diff --git a/CHANGELOG.md b/CHANGELOG.md index e1a02bb..e3fcf2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ ## 0.3.0 (unreleased) +- **Typefaces** — Google Sans replaces Figtree and Google Sans Code replaces + Geist Mono. Neither is bundled: the package depends on `google_fonts`, + which fetches each cut on first use and caches it (ship the files under a + `google_fonts/` asset folder for offline-first apps). The fetch needs + `android.permission.INTERNET` in the main Android manifest and the + `com.apple.security.network.client` entitlement in a sandboxed macOS app. + `FlowTypography.standard` is now built at runtime, and the new + `FlowTypography.recut` re-cuts a token at another weight or style, which + `copyWith(fontWeight:)` no longer can on the standard scale. Hosts that + named `Figtree` or `GeistMono` directly should update. + - **Fix** — `FlowChatView`'s bottom inset no longer stacks on the safe area. The design's 24 (compact) and 40 (wide) are now measured from the bottom of the safe area, so a phone's home indicator is absorbed rather diff --git a/CLAUDE.md b/CLAUDE.md index a54478b..e2bf1b4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,14 +8,14 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co Two hard constraints shape everything here: -- **No third-party dependencies.** `dependencies:` in `pubspec.yaml` contains only the Flutter SDK and Flutter's own first-party packages — `material_ui` (Material's home since Flutter 3.47) and its transitive set, all published by flutter.dev. Nothing outside that. Dev dependencies (`flutter_test`, `flutter_lints`) are fine. Bundled *assets* are not dependencies: the package ships Figtree and Geist Mono (`fonts/`, SIL OFL) because the design system is set in them, declared under `flutter: fonts:` and referenced as `package: 'flow_ui'`. +- **One third-party dependency: `google_fonts`.** `dependencies:` in `pubspec.yaml` holds the Flutter SDK, Flutter's own first-party packages — `material_ui` (Material's home since Flutter 3.47) and its transitive set, all published by flutter.dev — and `google_fonts` (material.io), which fetches Google Sans and Google Sans Code from Google Fonts at runtime. Nothing else, and no font files ship with the package. Dev dependencies (`flutter_test`, `flutter_lints`) are fine. - **Nothing model-facing.** Components render state passed in and report intent out through callbacks. No prompts, schemas, provider/network calls, or any LLM awareness — that belongs to the layers built on top. The theme, the conversation components (message, thread, streaming text, actions, loading), the composer and its menus, attachments with their preview, suggestions, and the chat surface are implemented; the roadmap below tracks the rest. Message content is modeled as typed parts (`lib/src/models/`) — sealed `FlowMessagePart` subtypes rendered by `FlowMessage`, with `FlowCustomPart` + `FlowCustomPartBuilder` as the extension seam for host-injected content. ## Layout -- Package at the repo root: `lib/`, `test/`, `fonts/`, `pubspec.yaml`. +- Package at the repo root: `lib/`, `test/`, `pubspec.yaml`. - `playground/` — the Flow UI Playground: a full Flutter app depending on the package via `path: ../`. Use it to demo and manually exercise components (every component has a stage demo, with variant pills and code snippets). ## Commands diff --git a/README.md b/README.md index 3dd6473..eb4314d 100644 --- a/README.md +++ b/README.md @@ -73,8 +73,14 @@ MaterialApp( ) ``` -The default typography ships with the package — Figtree, bundled under the -SIL Open Font License — so the theme renders as designed with no font setup. +The default typography — Google Sans and Google Sans Code — arrives through +[google_fonts](https://pub.dev/packages/google_fonts): each cut is fetched +on first use and cached on the device, so there is no font to bundle. The +fetch needs network access: `android.permission.INTERNET` in an Android +app's main manifest (Flutter's template grants it only to debug and profile) +and the `com.apple.security.network.client` entitlement in a sandboxed macOS +app; without it text falls back to the platform face. To render offline on +first launch, ship the files under a `google_fonts/` asset folder. ## Build a chat screen @@ -292,5 +298,6 @@ cd playground && flutter run -d chrome ## License -Code is released under the [MIT License](LICENSE). The bundled Figtree font -is licensed separately under the [SIL Open Font License](fonts/OFL.txt). +Code is released under the [MIT License](LICENSE). Google Sans and Google +Sans Code are fetched from Google Fonts under the +[SIL Open Font License](https://openfontlicense.org), not bundled. diff --git a/docs/.gitignore b/docs/.gitignore index fe9b4fd..ac497a3 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -8,8 +8,7 @@ dist/ # generated types .astro/ -# synced/built at build time from the repo (see scripts/) -public/fonts/ +# built at build time from the repo (see scripts/) public/playground/ public/api/ diff --git a/docs/README.md b/docs/README.md index fedcbe5..ed869b1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,10 +9,10 @@ npm run dev # http://localhost:4321 npm run build # static site in dist/ ``` -`predev`/`prebuild` copy the package's bundled Figtree faces from the repo's -`fonts/` into `public/fonts/` (gitignored) — repo fonts stay the single -source. Brand colors in `src/styles/theme.css` mirror the package's design -tokens in `lib/src/theme/flow_colors.dart`. +Google Sans loads from Google Fonts via the `` in `astro.config.mjs` — +the same source the package fetches from at runtime. Brand colors in +`src/styles/theme.css` mirror the package's design tokens in +`lib/src/theme/flow_colors.dart`. `npm run playground` builds the repo's `playground/` Flutter app for the web into `public/playground/` — served at `/playground/` (path diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 0189697..80d0196 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -43,6 +43,19 @@ export default defineConfig({ customCss: ['./src/styles/theme.css'], logo: { src: './src/assets/flow-ui-logo.svg', alt: '' }, head: [ + // Google Sans from Google Fonts — the same source the package fetches at runtime. + { tag: 'link', attrs: { rel: 'preconnect', href: 'https://fonts.googleapis.com' } }, + { + tag: 'link', + attrs: { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true }, + }, + { + tag: 'link', + attrs: { + rel: 'stylesheet', + href: 'https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500;600;700&display=swap', + }, + }, // Social-preview image on every page — Starlight emits the rest // of the OG/Twitter tags; the image is ours to provide. { diff --git a/docs/package.json b/docs/package.json index a5b59b5..0856279 100644 --- a/docs/package.json +++ b/docs/package.json @@ -4,10 +4,8 @@ "version": "0.0.1", "private": true, "scripts": { - "predev": "bash scripts/sync-fonts.sh", "dev": "astro dev", "start": "astro dev", - "prebuild": "bash scripts/sync-fonts.sh", "build": "astro build", "playground": "bash scripts/build-playground.sh", "build:site": "npm run playground && npm run build", diff --git a/docs/scripts/sync-fonts.sh b/docs/scripts/sync-fonts.sh deleted file mode 100755 index 7919bfa..0000000 --- a/docs/scripts/sync-fonts.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -# Copies the package's bundled Figtree faces (the four weights the design -# uses) into the docs site, keeping repo fonts/ the single source. Runs -# automatically via the predev/prebuild npm hooks. -set -euo pipefail -cd "$(dirname "$0")/.." -mkdir -p public/fonts -cp ../fonts/Figtree-Regular.ttf \ - ../fonts/Figtree-Medium.ttf \ - ../fonts/Figtree-SemiBold.ttf \ - ../fonts/Figtree-Bold.ttf \ - ../fonts/OFL.txt \ - public/fonts/ diff --git a/docs/src/content/docs/components/code-block.mdx b/docs/src/content/docs/components/code-block.mdx index f436289..5acdea9 100644 --- a/docs/src/content/docs/components/code-block.mdx +++ b/docs/src/content/docs/components/code-block.mdx @@ -137,7 +137,7 @@ FlowCodeLanguage.register( ## Theming Token inks are theme tokens. Install a `FlowSyntaxColors` on the theme to -recolor them; the code face is Geist Mono, bundled with the package, and +recolor them; the code face is Google Sans Code, fetched through `google_fonts`, and swaps via the typography: ```dart title="Custom syntax palette and mono face" diff --git a/docs/src/content/docs/getting-started.mdx b/docs/src/content/docs/getting-started.mdx index 1187863..30bd45d 100644 --- a/docs/src/content/docs/getting-started.mdx +++ b/docs/src/content/docs/getting-started.mdx @@ -42,8 +42,12 @@ MaterialApp( back to a preset matched to the ambient `ThemeData.brightness`. -Figtree — the face the design system is set in — ships inside the package, -so there is nothing to add to your own `pubspec.yaml` fonts section. +Google Sans — the face the design system is set in — is fetched through +`google_fonts` on first use, so there is nothing to add to your `pubspec.yaml` +fonts section. The fetch needs network access: `android.permission.INTERNET` +in the main Android manifest (Flutter grants it only to debug and profile) +and the `com.apple.security.network.client` entitlement in a sandboxed macOS +app. To render offline on first launch, ship the files under `google_fonts/`. ## Render a conversation diff --git a/docs/src/content/docs/theming.mdx b/docs/src/content/docs/theming.mdx index 65b629d..90aae55 100644 --- a/docs/src/content/docs/theming.mdx +++ b/docs/src/content/docs/theming.mdx @@ -93,7 +93,7 @@ Text( ## The type scale `FlowTypography.standard` follows the Material 3 scale — display, headline, -title, body and label, each in large / medium / small — set in Figtree. +title, body and label, each in large / medium / small — set in Google Sans. Letter-spacing stays at zero. Line heights step with the role: 1.5 for body, 1.3 for title and label, 1.2 for headline, 1.15 for display. diff --git a/docs/src/styles/theme.css b/docs/src/styles/theme.css index 0d27db2..ee203bb 100644 --- a/docs/src/styles/theme.css +++ b/docs/src/styles/theme.css @@ -1,7 +1,7 @@ /* flow_ui docs theme. * * Design language: the Flow palette (lib/src/theme/flow_colors.dart) — - * warm paper & near-black ink, one rose accent — set in Figtree and laid + * warm paper & near-black ink, one rose accent — set in Google Sans and laid * out in the modern docs idiom: display-scale headlines, ink-neutral pill * buttons, lifted borderless panels, whisper hairlines, minimal chrome. * Rose is the accent voice (links, active states, the mark), never a slab. @@ -9,39 +9,12 @@ /* ---------------------------------------------------------------- fonts */ -@font-face { - font-family: 'Figtree'; - src: url('/fonts/Figtree-Regular.ttf') format('truetype'); - font-weight: 400; - font-style: normal; - font-display: swap; -} -@font-face { - font-family: 'Figtree'; - src: url('/fonts/Figtree-Medium.ttf') format('truetype'); - font-weight: 500; - font-style: normal; - font-display: swap; -} -@font-face { - font-family: 'Figtree'; - src: url('/fonts/Figtree-SemiBold.ttf') format('truetype'); - font-weight: 600; - font-style: normal; - font-display: swap; -} -@font-face { - font-family: 'Figtree'; - src: url('/fonts/Figtree-Bold.ttf') format('truetype'); - font-weight: 700; - font-style: normal; - font-display: swap; -} +/* Google Sans loads from Google Fonts via the in astro.config.mjs. */ /* -------------------------------------------------------------- palette */ :root { - --sl-font: 'Figtree', ui-sans-serif, system-ui, sans-serif; + --sl-font: 'Google Sans', ui-sans-serif, system-ui, sans-serif; --sl-nav-height: 4rem; --sl-nav-pad-x: 1.5rem; } diff --git a/example/linux/flutter/generated_plugins.cmake b/example/linux/flutter/generated_plugins.cmake index 2e1de87..be1ee3e 100644 --- a/example/linux/flutter/generated_plugins.cmake +++ b/example/linux/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/example/pubspec.lock b/example/pubspec.lock index 445ce6d..475383f 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" async: dependency: transitive description: @@ -33,6 +41,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.2" + code_assets: + dependency: transitive + description: + name: code_assets + sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8 + url: "https://pub.dev" + source: hosted + version: "1.2.1" collection: dependency: transitive description: @@ -41,6 +57,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.19.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" + source: hosted + version: "3.0.7" cupertino_ui: dependency: transitive description: @@ -57,6 +81,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.3" + ffi: + dependency: transitive + description: + name: ffi + sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" + url: "https://pub.dev" + source: hosted + version: "2.2.0" flow_ui: dependency: "direct main" description: @@ -87,6 +119,22 @@ packages: description: flutter source: sdk version: "0.0.0" + google_fonts: + dependency: transitive + description: + name: google_fonts + sha256: e3cb3ee6b47fd2472c23de6da5744796a4da195137759ddb3fbcc9467b7b3c7d + url: "https://pub.dev" + source: hosted + version: "8.2.1" + hooks: + dependency: transitive + description: + name: hooks + sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba" + url: "https://pub.dev" + source: hosted + version: "2.0.2" http: dependency: "direct main" description: @@ -107,10 +155,34 @@ packages: dependency: transitive description: name: intl - sha256: "1ca20c894b1717686a2319b8548763d812bc0aabdac580420a44c5178c57a867" + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" url: "https://pub.dev" source: hosted - version: "0.20.3" + version: "0.20.2" + jni: + dependency: transitive + description: + name: jni + sha256: f038e58b4dc2c9037f50e233175086337e0b305e356d28211bf55f21c504cbd3 + url: "https://pub.dev" + source: hosted + version: "1.0.3" + jni_flutter: + dependency: transitive + description: + name: jni_flutter + sha256: "7b717011ea40d04fd47c2731d3d1d36eb99eba3435c2753d62489e8c3c9991d5" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + jni_util: + dependency: transitive + description: + name: jni_util + sha256: "1ba86da04a5f2bf18fde2edb235587e70c5b0fc5bd4ba955f46b00942c3fc35f" + url: "https://pub.dev" + source: hosted + version: "1.0.0" leak_tracker: dependency: transitive description: @@ -143,14 +215,22 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.0" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" matcher: dependency: transitive description: name: matcher - sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd" + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 url: "https://pub.dev" source: hosted - version: "0.12.20" + version: "0.12.19" material_color_utilities: dependency: transitive description: @@ -171,10 +251,26 @@ packages: dependency: transitive description: name: meta - sha256: c82594181e3312f3d0695fc95aaaf7758d75b8d4ae2bbecf223b9fd5109a059d + sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349" + url: "https://pub.dev" + source: hosted + version: "1.18.0" + objective_c: + dependency: transitive + description: + name: objective_c + sha256: b7fb95a6d9a4f009edd63dc5ac69f07420b23a16161c6dd8660290b59c602e8e + url: "https://pub.dev" + source: hosted + version: "9.5.0" + package_config: + dependency: transitive + description: + name: package_config + sha256: ffcf4cf3d6c0b74ac43708d9f56625506e8a68aa935abe9d267a7330f320eb5d url: "https://pub.dev" source: hosted - version: "1.18.3" + version: "3.0.0" path: dependency: transitive description: @@ -183,6 +279,86 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: a7f4874f987173da295a61c181b8ee71dab59b332a486b391babf26a1b884825 + url: "https://pub.dev" + source: hosted + version: "2.1.6" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd" + url: "https://pub.dev" + source: hosted + version: "2.3.1" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" + url: "https://pub.dev" + source: hosted + version: "2.6.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: "58c2005f147315b11e9b4a7bc889cd5203e250cba8e3f012dae259b4972b5c16" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "484838772624c3a4b94f1e44a3e19897fee738f2d5c4ce448443b0417f7c9dda" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + record_use: + dependency: transitive + description: + name: record_use + sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed" + url: "https://pub.dev" + source: hosted + version: "0.6.0" sky_engine: dependency: transitive description: flutter @@ -232,10 +408,10 @@ packages: dependency: transitive description: name: test_api - sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11" + sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e" url: "https://pub.dev" source: hosted - version: "0.7.12" + version: "0.7.11" typed_data: dependency: transitive description: @@ -248,10 +424,10 @@ packages: dependency: transitive description: name: vector_math - sha256: f36f9f3be64c6198714492bb455c11056e33e2f85d9a0b676a48301e44fdcf47 + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.2.0" vm_service: dependency: transitive description: @@ -268,6 +444,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" sdks: dart: ">=3.12.2 <4.0.0" flutter: ">=3.44.0" diff --git a/example/windows/flutter/generated_plugins.cmake b/example/windows/flutter/generated_plugins.cmake index b93c4c3..3ad69c6 100644 --- a/example/windows/flutter/generated_plugins.cmake +++ b/example/windows/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/fonts/Figtree-Black.ttf b/fonts/Figtree-Black.ttf deleted file mode 100644 index 526fe1d..0000000 Binary files a/fonts/Figtree-Black.ttf and /dev/null differ diff --git a/fonts/Figtree-Bold.ttf b/fonts/Figtree-Bold.ttf deleted file mode 100644 index 6f8ad64..0000000 Binary files a/fonts/Figtree-Bold.ttf and /dev/null differ diff --git a/fonts/Figtree-ExtraBold.ttf b/fonts/Figtree-ExtraBold.ttf deleted file mode 100644 index 8589c04..0000000 Binary files a/fonts/Figtree-ExtraBold.ttf and /dev/null differ diff --git a/fonts/Figtree-Light.ttf b/fonts/Figtree-Light.ttf deleted file mode 100644 index e238878..0000000 Binary files a/fonts/Figtree-Light.ttf and /dev/null differ diff --git a/fonts/Figtree-Medium.ttf b/fonts/Figtree-Medium.ttf deleted file mode 100644 index 5b89c89..0000000 Binary files a/fonts/Figtree-Medium.ttf and /dev/null differ diff --git a/fonts/Figtree-Regular.ttf b/fonts/Figtree-Regular.ttf deleted file mode 100644 index 4b42cdb..0000000 Binary files a/fonts/Figtree-Regular.ttf and /dev/null differ diff --git a/fonts/Figtree-SemiBold.ttf b/fonts/Figtree-SemiBold.ttf deleted file mode 100644 index aa2b78c..0000000 Binary files a/fonts/Figtree-SemiBold.ttf and /dev/null differ diff --git a/fonts/GeistMono-Medium.ttf b/fonts/GeistMono-Medium.ttf deleted file mode 100644 index ff49ece..0000000 Binary files a/fonts/GeistMono-Medium.ttf and /dev/null differ diff --git a/fonts/GeistMono-Regular.ttf b/fonts/GeistMono-Regular.ttf deleted file mode 100644 index 50c9d5a..0000000 Binary files a/fonts/GeistMono-Regular.ttf and /dev/null differ diff --git a/fonts/GeistMono-SemiBold.ttf b/fonts/GeistMono-SemiBold.ttf deleted file mode 100644 index 1b21724..0000000 Binary files a/fonts/GeistMono-SemiBold.ttf and /dev/null differ diff --git a/fonts/OFL-GeistMono.txt b/fonts/OFL-GeistMono.txt deleted file mode 100644 index 04e95fc..0000000 --- a/fonts/OFL-GeistMono.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -https://openfontlicense.org - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. \ No newline at end of file diff --git a/fonts/OFL.txt b/fonts/OFL.txt deleted file mode 100644 index 80b12bb..0000000 --- a/fonts/OFL.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2022 The Figtree Project Authors (https://github.com/erikdkennedy/figtree) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/lib/src/theme/flow_theme.dart b/lib/src/theme/flow_theme.dart index cfdaabb..8f9baf0 100644 --- a/lib/src/theme/flow_theme.dart +++ b/lib/src/theme/flow_theme.dart @@ -42,7 +42,7 @@ import 'flow_typography.dart'; class FlowTheme extends ThemeExtension { const FlowTheme({ required this.colors, - this.typography = FlowTypography.standard, + this._typography, this.syntax, this.composerStyle, this.messageStyle, @@ -64,7 +64,11 @@ class FlowTheme extends ThemeExtension { const FlowTheme(colors: FlowColors.dark, syntax: FlowSyntaxColors.dark); final FlowColors colors; - final FlowTypography typography; + final FlowTypography? _typography; + + /// The type scale — [FlowTypography.standard] unless the host set one. + /// Resolved on read, since the standard scale isn't `const`. + FlowTypography get typography => _typography ?? FlowTypography.standard; /// Syntax token colors for code blocks. Null resolves to the preset /// matching the ambient brightness — unlike [typography], the right @@ -117,7 +121,7 @@ class FlowTheme extends ThemeExtension { }) { return FlowTheme( colors: colors ?? this.colors, - typography: typography ?? this.typography, + typography: typography ?? _typography, syntax: syntax ?? this.syntax, composerStyle: composerStyle ?? this.composerStyle, messageStyle: messageStyle ?? this.messageStyle, diff --git a/lib/src/theme/flow_typography.dart b/lib/src/theme/flow_typography.dart index 7f586ea..292aa46 100644 --- a/lib/src/theme/flow_typography.dart +++ b/lib/src/theme/flow_typography.dart @@ -1,33 +1,30 @@ +import 'package:google_fonts/google_fonts.dart'; import 'package:material_ui/material_ui.dart'; -/// The typefaces the presets are drawn in, bundled with this package under -/// `fonts/` (SIL Open Font License — see `fonts/OFL.txt` and -/// `fonts/OFL-GeistMono.txt`): Figtree for prose, Geist Mono for code. +/// Google Sans for prose and Google Sans Code for code, served by +/// `google_fonts`: each cut is fetched on first use and cached, or read from +/// a `google_fonts/` asset folder when the host ships one. /// -/// Declared with `package:` so the families resolve to `packages/flow_ui/…` -/// and a host gets the design's typefaces without adding a font of their -/// own. -const String _fontFamily = 'Figtree'; -const String _monoFontFamily = 'GeistMono'; -const String _fontPackage = 'flow_ui'; +/// google_fonts registers each cut as its own font family (`GoogleSans_600`, +/// …), so roles are built through the package and re-weighted with +/// [FlowTypography.recut] rather than `copyWith(fontWeight:)`. +const String _fontFamily = 'GoogleSans'; +const String _monoFontFamily = 'GoogleSansCode'; -/// The mono roles' standard cuts — file-level so they can double as the -/// constructor defaults, which keeps [FlowTypography]'s pre-code -/// constructor calls compiling unchanged. -const TextStyle _standardCode = TextStyle( - fontFamily: _monoFontFamily, - package: _fontPackage, - fontSize: 13, - fontWeight: FontWeight.w400, - height: 1.6, -); -const TextStyle _standardCodeInline = TextStyle( - fontFamily: _monoFontFamily, - package: _fontPackage, - fontSize: 14, - fontWeight: FontWeight.w400, - height: 1.5, -); +TextStyle _sans(double size, FontWeight weight, double height) => + GoogleFonts.googleSans(fontSize: size, fontWeight: weight, height: height); + +TextStyle _mono(double size, FontWeight weight, double height) => + GoogleFonts.googleSansCode( + fontSize: size, + fontWeight: weight, + height: height, + ); + +/// Defaults for the mono roles, resolved by the [FlowTypography.code] and +/// [FlowTypography.codeInline] getters. +final TextStyle _standardCode = _mono(13, FontWeight.w400, 1.6); +final TextStyle _standardCodeInline = _mono(14, FontWeight.w400, 1.5); /// Text style tokens for flow_ui components. /// @@ -71,8 +68,8 @@ class FlowTypography { required this.labelMediumEmphasised, required this.labelSmall, required this.labelSmallEmphasised, - this.code = _standardCode, - this.codeInline = _standardCodeInline, + this._code, + this._codeInline, }); final TextStyle displayLarge; @@ -114,209 +111,51 @@ class FlowTypography { final TextStyle labelSmall; final TextStyle labelSmallEmphasised; - /// Code, set in the bundled Geist Mono — the code block's body. A step - /// under prose (13) on a taller line (1.6), so a block reads as inset - /// material rather than continuing the paragraph. - final TextStyle code; + final TextStyle? _code; + final TextStyle? _codeInline; + + /// Code, set in Google Sans Code — the code block's body. A step under + /// prose (13) on a taller line (1.6), so a block reads as inset material + /// rather than continuing the paragraph. + TextStyle get code => _code ?? _standardCode; /// The mono face at prose size, for future inline code spans. - final TextStyle codeInline; + TextStyle get codeInline => _codeInline ?? _standardCodeInline; - /// The Flow type scale: Figtree, with the code roles in Geist Mono. - static const FlowTypography standard = FlowTypography( - displayLarge: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 52, - fontWeight: FontWeight.w400, - height: 1.15, - ), - displayMedium: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 46, - fontWeight: FontWeight.w400, - height: 1.15, - ), - displaySmall: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 40, - fontWeight: FontWeight.w400, - height: 1.15, - ), + /// The Flow type scale: Google Sans, with the code roles in Google Sans + /// Code. + static final FlowTypography standard = FlowTypography( + displayLarge: _sans(52, FontWeight.w400, 1.15), + displayMedium: _sans(46, FontWeight.w400, 1.15), + displaySmall: _sans(40, FontWeight.w400, 1.15), // The greeting: 32 regular at 1.3. - headlineLarge: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 36, - fontWeight: FontWeight.w400, - height: 1.2, - ), - headlineMedium: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 32, - fontWeight: FontWeight.w400, - height: 1.2, - ), - headlineSmall: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 28, - fontWeight: FontWeight.w400, - height: 1.2, - ), - titleLarge: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 24, - fontWeight: FontWeight.w400, - height: 1.3, - ), - titleLargeEmphasised: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 24, - fontWeight: FontWeight.w600, - height: 1.3, - ), - titleMedium: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 21, - fontWeight: FontWeight.w400, - height: 1.3, - ), - titleMediumEmphasised: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 21, - fontWeight: FontWeight.w600, - height: 1.3, - ), - titleSmall: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 18, - fontWeight: FontWeight.w400, - height: 1.3, - ), - titleSmallEmphasised: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 18, - fontWeight: FontWeight.w600, - height: 1.3, - ), - bodyLarge: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 16, - fontWeight: FontWeight.w400, - height: 1.5, - ), - bodyLargeEmphasised: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 16, - fontWeight: FontWeight.w500, - height: 1.5, - ), - bodyLargeDark: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 16, - fontWeight: FontWeight.w600, - height: 1.5, - ), - bodyMedium: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 14, - fontWeight: FontWeight.w400, - height: 1.5, - ), - bodyMediumEmphasised: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 14, - fontWeight: FontWeight.w500, - height: 1.5, - ), - bodyMediumDark: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 14, - fontWeight: FontWeight.w600, - height: 1.5, - ), - bodySmall: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 12, - fontWeight: FontWeight.w400, - height: 1.5, - ), - bodySmallEmphasised: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 12, - fontWeight: FontWeight.w500, - height: 1.5, - ), - bodySmallDark: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 12, - fontWeight: FontWeight.w600, - height: 1.5, - ), - labelLarge: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 16, - fontWeight: FontWeight.w400, - height: 1.3, - ), - labelLargeEmphasised: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 16, - fontWeight: FontWeight.w500, - height: 1.3, - ), - labelMedium: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 14, - fontWeight: FontWeight.w400, - height: 1.3, - ), - labelMediumEmphasised: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 14, - fontWeight: FontWeight.w500, - height: 1.3, - ), - labelSmall: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 12, - fontWeight: FontWeight.w400, - height: 1.3, - ), - labelSmallEmphasised: TextStyle( - fontFamily: _fontFamily, - package: _fontPackage, - fontSize: 12, - fontWeight: FontWeight.w500, - height: 1.3, - ), + headlineLarge: _sans(36, FontWeight.w400, 1.2), + headlineMedium: _sans(32, FontWeight.w400, 1.2), + headlineSmall: _sans(28, FontWeight.w400, 1.2), + titleLarge: _sans(24, FontWeight.w400, 1.3), + titleLargeEmphasised: _sans(24, FontWeight.w600, 1.3), + titleMedium: _sans(21, FontWeight.w400, 1.3), + titleMediumEmphasised: _sans(21, FontWeight.w600, 1.3), + titleSmall: _sans(18, FontWeight.w400, 1.3), + titleSmallEmphasised: _sans(18, FontWeight.w600, 1.3), + bodyLarge: _sans(16, FontWeight.w400, 1.5), + bodyLargeEmphasised: _sans(16, FontWeight.w500, 1.5), + bodyLargeDark: _sans(16, FontWeight.w600, 1.5), + bodyMedium: _sans(14, FontWeight.w400, 1.5), + bodyMediumEmphasised: _sans(14, FontWeight.w500, 1.5), + bodyMediumDark: _sans(14, FontWeight.w600, 1.5), + bodySmall: _sans(12, FontWeight.w400, 1.5), + bodySmallEmphasised: _sans(12, FontWeight.w500, 1.5), + bodySmallDark: _sans(12, FontWeight.w600, 1.5), + labelLarge: _sans(16, FontWeight.w400, 1.3), + labelLargeEmphasised: _sans(16, FontWeight.w500, 1.3), + labelMedium: _sans(14, FontWeight.w400, 1.3), + labelMediumEmphasised: _sans(14, FontWeight.w500, 1.3), + labelSmall: _sans(12, FontWeight.w400, 1.3), + labelSmallEmphasised: _sans(12, FontWeight.w500, 1.3), ); - /// The same scale set in [fontFamily] instead of the bundled Figtree. + /// The same scale set in [fontFamily] instead of Google Sans. /// The mono roles keep their own face — swap those with /// [withCodeFontFamily]. /// @@ -384,6 +223,35 @@ class FlowTypography { return copyWith(code: reface(code), codeInline: reface(codeInline)); } + /// [style] at [fontWeight] and/or [fontStyle], in the matching cut. + /// + /// google_fonts registers each cut as its own font family, so `copyWith` + /// on a token would leave the engine faking the weight; this loads the + /// real cut. Styles in any other face pass through `copyWith`. + static TextStyle recut( + TextStyle style, { + FontWeight? fontWeight, + FontStyle? fontStyle, + }) { + // google_fonts names each cut `_`. + final family = style.fontFamily ?? ''; + if (family.startsWith('${_fontFamily}_')) { + return GoogleFonts.googleSans( + textStyle: style, + fontWeight: fontWeight, + fontStyle: fontStyle, + ); + } + if (family.startsWith('${_monoFontFamily}_')) { + return GoogleFonts.googleSansCode( + textStyle: style, + fontWeight: fontWeight, + fontStyle: fontStyle, + ); + } + return style.copyWith(fontWeight: fontWeight, fontStyle: fontStyle); + } + FlowTypography copyWith({ TextStyle? displayLarge, TextStyle? displayMedium, diff --git a/lib/src/utils/flow_chip_text.dart b/lib/src/utils/flow_chip_text.dart index a9566d7..10e549d 100644 --- a/lib/src/utils/flow_chip_text.dart +++ b/lib/src/utils/flow_chip_text.dart @@ -1,6 +1,8 @@ import 'package:flutter/rendering.dart'; import 'package:material_ui/material_ui.dart'; +import '../theme/flow_typography.dart'; + /// Internal — not exported from the package barrel. /// /// The inline-code chip, painted rather than composed: Flutter gives a @@ -65,7 +67,7 @@ class FlowChipText extends StatelessWidget { final defaults = DefaultTextStyle.of(context); var style = defaults.style; if (MediaQuery.boldTextOf(context)) { - style = style.merge(const TextStyle(fontWeight: FontWeight.bold)); + style = FlowTypography.recut(style, fontWeight: FontWeight.bold); } final registrar = SelectionContainer.maybeOf(context); final selectionStyle = DefaultSelectionStyle.of(context); diff --git a/lib/src/widgets/flow_attachment_group.dart b/lib/src/widgets/flow_attachment_group.dart index 821bd9d..dd22c08 100644 --- a/lib/src/widgets/flow_attachment_group.dart +++ b/lib/src/widgets/flow_attachment_group.dart @@ -5,6 +5,7 @@ import 'package:material_ui/material_ui.dart'; import '../models/flow_attachment.dart'; import '../theme/flow_theme.dart'; +import '../theme/flow_typography.dart'; import '../utils/flow_attachment_error.dart'; import '../utils/flow_circle_button.dart'; import 'flow_attachment_preview.dart'; @@ -481,10 +482,10 @@ class _TypePill extends StatelessWidget { padding: _pillPadding, child: Text( kind, - style: context.flowTypography.labelSmall.copyWith( - color: colors.surfaceBright, + style: FlowTypography.recut( + context.flowTypography.labelSmall, fontWeight: FontWeight.w600, - ), + ).copyWith(color: colors.surfaceBright), ), ), ), diff --git a/lib/src/widgets/flow_error_state.dart b/lib/src/widgets/flow_error_state.dart index 92dba9f..003e06f 100644 --- a/lib/src/widgets/flow_error_state.dart +++ b/lib/src/widgets/flow_error_state.dart @@ -2,6 +2,7 @@ import 'package:material_ui/material_ui.dart'; import '../styles/flow_error_state_style.dart'; import '../theme/flow_theme.dart'; +import '../theme/flow_typography.dart'; /// A failure surface: an error glyph and a host-written explanation on a /// hairline card, with an optional retry pill. @@ -107,9 +108,10 @@ class FlowErrorState extends StatelessWidget { final effective = context.flowTheme.errorStateStyle?.merge(style) ?? style; final rowStyle = title != null - ? typography.labelMedium - .copyWith(fontWeight: FontWeight.w600, color: colors.onSurface) - .merge(effective?.titleStyle) + ? FlowTypography.recut( + typography.labelMedium, + fontWeight: FontWeight.w600, + ).copyWith(color: colors.onSurface).merge(effective?.titleStyle) : typography.bodyMedium .copyWith(color: colors.onSurfaceVariant) .merge(effective?.messageStyle); @@ -252,10 +254,10 @@ class _RetryButtonState extends State<_RetryButton> { const SizedBox(width: _glyphGap), Text( label, - style: typography.labelMedium.copyWith( + style: FlowTypography.recut( + typography.labelMedium, fontWeight: FontWeight.w600, - color: foreground, - ), + ).copyWith(color: foreground), ), ], ], diff --git a/lib/src/widgets/flow_markdown.dart b/lib/src/widgets/flow_markdown.dart index 00b525d..bb54af1 100644 --- a/lib/src/widgets/flow_markdown.dart +++ b/lib/src/widgets/flow_markdown.dart @@ -811,8 +811,12 @@ class _FlowMarkdownState extends State { .copyWith(color: base.color) .merge(_mdStyle?.inlineCodeStyle); } - if (run.bold) style = style.copyWith(fontWeight: FontWeight.w600); - if (run.italic) style = style.copyWith(fontStyle: FontStyle.italic); + if (run.bold) { + style = FlowTypography.recut(style, fontWeight: FontWeight.w600); + } + if (run.italic) { + style = FlowTypography.recut(style, fontStyle: FontStyle.italic); + } final linked = run.linkHref != null && widget.onLinkTap != null; final decorations = [ diff --git a/playground/android/app/src/main/AndroidManifest.xml b/playground/android/app/src/main/AndroidManifest.xml index 6fa5570..c1b2d6b 100644 --- a/playground/android/app/src/main/AndroidManifest.xml +++ b/playground/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,6 @@ + + com.apple.security.network.server + com.apple.security.network.client + diff --git a/playground/macos/Runner/Release.entitlements b/playground/macos/Runner/Release.entitlements index 852fa1a..ee95ab7 100644 --- a/playground/macos/Runner/Release.entitlements +++ b/playground/macos/Runner/Release.entitlements @@ -4,5 +4,7 @@ com.apple.security.app-sandbox + com.apple.security.network.client + diff --git a/playground/pubspec.lock b/playground/pubspec.lock index 2632490..ceb3341 100644 --- a/playground/pubspec.lock +++ b/playground/pubspec.lock @@ -41,6 +41,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.2" + code_assets: + dependency: transitive + description: + name: code_assets + sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8 + url: "https://pub.dev" + source: hosted + version: "1.2.1" collection: dependency: transitive description: @@ -49,6 +57,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.19.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" + source: hosted + version: "3.0.7" cupertino_icons: dependency: "direct main" description: @@ -73,6 +89,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.3" + ffi: + dependency: transitive + description: + name: ffi + sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" + url: "https://pub.dev" + source: hosted + version: "2.2.0" flow_ui: dependency: "direct main" description: @@ -124,6 +148,22 @@ packages: url: "https://pub.dev" source: hosted version: "18.0.0" + google_fonts: + dependency: "direct main" + description: + name: google_fonts + sha256: e3cb3ee6b47fd2472c23de6da5744796a4da195137759ddb3fbcc9467b7b3c7d + url: "https://pub.dev" + source: hosted + version: "8.2.1" + hooks: + dependency: transitive + description: + name: hooks + sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba" + url: "https://pub.dev" + source: hosted + version: "2.0.2" http: dependency: transitive description: @@ -144,10 +184,34 @@ packages: dependency: transitive description: name: intl - sha256: "1ca20c894b1717686a2319b8548763d812bc0aabdac580420a44c5178c57a867" + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" + url: "https://pub.dev" + source: hosted + version: "0.20.2" + jni: + dependency: transitive + description: + name: jni + sha256: f038e58b4dc2c9037f50e233175086337e0b305e356d28211bf55f21c504cbd3 + url: "https://pub.dev" + source: hosted + version: "1.0.3" + jni_flutter: + dependency: transitive + description: + name: jni_flutter + sha256: "7b717011ea40d04fd47c2731d3d1d36eb99eba3435c2753d62489e8c3c9991d5" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + jni_util: + dependency: transitive + description: + name: jni_util + sha256: "1ba86da04a5f2bf18fde2edb235587e70c5b0fc5bd4ba955f46b00942c3fc35f" url: "https://pub.dev" source: hosted - version: "0.20.3" + version: "1.0.0" leak_tracker: dependency: transitive description: @@ -192,10 +256,10 @@ packages: dependency: transitive description: name: matcher - sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd" + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 url: "https://pub.dev" source: hosted - version: "0.12.20" + version: "0.12.19" material_color_utilities: dependency: transitive description: @@ -216,10 +280,26 @@ packages: dependency: transitive description: name: meta - sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9" + sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349" url: "https://pub.dev" source: hosted - version: "1.19.0" + version: "1.18.0" + objective_c: + dependency: transitive + description: + name: objective_c + sha256: b7fb95a6d9a4f009edd63dc5ac69f07420b23a16161c6dd8660290b59c602e8e + url: "https://pub.dev" + source: hosted + version: "9.5.0" + package_config: + dependency: transitive + description: + name: package_config + sha256: ffcf4cf3d6c0b74ac43708d9f56625506e8a68aa935abe9d267a7330f320eb5d + url: "https://pub.dev" + source: hosted + version: "3.0.0" path: dependency: transitive description: @@ -236,6 +316,54 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: a7f4874f987173da295a61c181b8ee71dab59b332a486b391babf26a1b884825 + url: "https://pub.dev" + source: hosted + version: "2.1.6" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd" + url: "https://pub.dev" + source: hosted + version: "2.3.1" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" + url: "https://pub.dev" + source: hosted + version: "2.6.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: "58c2005f147315b11e9b4a7bc889cd5203e250cba8e3f012dae259b4972b5c16" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "484838772624c3a4b94f1e44a3e19897fee738f2d5c4ce448443b0417f7c9dda" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" petitparser: dependency: transitive description: @@ -252,6 +380,38 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + record_use: + dependency: transitive + description: + name: record_use + sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed" + url: "https://pub.dev" + source: hosted + version: "0.6.0" sky_engine: dependency: transitive description: flutter @@ -301,10 +461,10 @@ packages: dependency: transitive description: name: test_api - sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11" + sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e" url: "https://pub.dev" source: hosted - version: "0.7.12" + version: "0.7.11" typed_data: dependency: transitive description: @@ -341,10 +501,10 @@ packages: dependency: transitive description: name: vector_math - sha256: f36f9f3be64c6198714492bb455c11056e33e2f85d9a0b676a48301e44fdcf47 + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.2.0" vm_service: dependency: transitive description: @@ -361,6 +521,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" xml: dependency: transitive description: @@ -369,6 +537,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" sdks: dart: ">=3.12.2 <4.0.0" flutter: ">=3.44.0" diff --git a/playground/pubspec.yaml b/playground/pubspec.yaml index 504973e..8538b08 100644 --- a/playground/pubspec.yaml +++ b/playground/pubspec.yaml @@ -32,8 +32,7 @@ dependencies: flutter: sdk: flutter material_ui: ^1.0.0 - # The component library under demo — also supplies Figtree, the face the - # playground chrome is set in. + # The component library under demo. flow_ui: path: ../ # Renders the logo's SVG asset — app-only. @@ -52,6 +51,8 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8 + # Google Sans for the chrome. + google_fonts: ^8.2.1 dev_dependencies: flutter_test: diff --git a/playground/windows/flutter/generated_plugins.cmake b/playground/windows/flutter/generated_plugins.cmake index b93c4c3..3ad69c6 100644 --- a/playground/windows/flutter/generated_plugins.cmake +++ b/playground/windows/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/pubspec.yaml b/pubspec.yaml index fd47331..0c71362 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,6 +19,9 @@ environment: dependencies: flutter: sdk: flutter + # Google Sans and Google Sans Code, fetched from Google Fonts at runtime — + # the one dependency outside flutter.dev's packages; no font files ship. + google_fonts: ^8.2.1 material_ui: ^1.0.0 dev_dependencies: @@ -26,39 +29,3 @@ dev_dependencies: sdk: flutter flutter_lints: ^6.0.0 -flutter: - # Figtree is the typeface of the Flow UI design file, and Geist Mono its - # code face. Both ship with the package (SIL Open Font License, see - # fonts/OFL.txt and fonts/OFL-GeistMono.txt) so the default theme renders - # as designed without the host bundling a font — and without a font - # dependency. - # - # Static instances rather than the variable TTFs: Flutter maps FontWeight - # to the nearest declared weight, so a weight axis would not be - # interpolated. Geist Mono carries only the three weights the mono roles - # reach for, to keep what every host app inherits small. - fonts: - - family: Figtree - fonts: - - asset: fonts/Figtree-Light.ttf - weight: 300 - - asset: fonts/Figtree-Regular.ttf - weight: 400 - - asset: fonts/Figtree-Medium.ttf - weight: 500 - - asset: fonts/Figtree-SemiBold.ttf - weight: 600 - - asset: fonts/Figtree-Bold.ttf - weight: 700 - - asset: fonts/Figtree-ExtraBold.ttf - weight: 800 - - asset: fonts/Figtree-Black.ttf - weight: 900 - - family: GeistMono - fonts: - - asset: fonts/GeistMono-Regular.ttf - weight: 400 - - asset: fonts/GeistMono-Medium.ttf - weight: 500 - - asset: fonts/GeistMono-SemiBold.ttf - weight: 600