diff --git a/packages/cli/README.md b/packages/cli/README.md index 58f6c5717e49a..6450e7dcfca9f 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -383,52 +383,52 @@ Every response has a `type` discriminant. The full set is below (generated from -| Type | What `data` carries | -| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `component.list` | The component catalog grouped by category: `detail` (the level: names \| compact \| full) and `components`, the grouped map of names+package, brief entries, or a full ComponentDoc per entry. | -| `component.detail` | One component's authored ComponentDoc plus ownership metadata (owner package, import specifier, and whether source is available). | -| `component.detail.props` | Just one component's props table (ComponentPropDoc[]). | -| `component.detail.source` | One component's source file, as {component, source}. | -| `component.detail.showcase` | One component's showcase example, as {component, aspectRatio, source}. | -| `component.detail.blocks` | One component's example blocks, as {component, showcase, examples, related} of BlockEntry. | -| `docs.list` | All reference-doc topics as DocsListEntry[] ({topic, description}), in discovery order. | -| `docs.detail` | One topic's full ReferenceDoc, with token-ref blocks inlined. | -| `docs.detail.section` | A single ReferenceSection of a topic: the first whose title contains the section query. | -| `blog.list` | The feed URL plus every post parsed from the RSS feed, each with slug, title, description, date, type, authors, link, and plaintext URL. | -| `blog.detail` | One post's metadata plus the feed URL and the post's full plaintext body. | -| `discover.list` | The configured external packages (name, category, components, version, description); when empty it carries meta.configured to tell "nothing configured" from "nothing discovered". | -| `discover.detail` | A single external package entry, for an @scope/name query. | -| `discover.detail.doc` | The validated ComponentDoc for one external component: an @scope/name/Component query, or a free-text term resolving to exactly one component. | -| `discover.search` | The echoed query plus the matching {package, component} pairs, when a free-text term matches several components. | -| `search` | The echoed query plus a ranked SearchResultEntry[] (domain, name, score, reason, description, follow-up command, and import path where relevant). | -| `build.help` | A marker (`playbook: true`) that the renderer expands into the how-to-build-a-page workflow; emitted when no query is given. | -| `build.kit` | The grouped composition kit: echoed query, hasResults/directMatch flags, the closest page templates, drop-in block patterns, idea-specific components/hooks, and the always-on frame + foundation component-name arrays. | -| `swizzle.list` | The names of swizzlable components discoverable from cwd's @astryxdesign/core. | -| `swizzle.copy` | An eject receipt: component name, owning package, output directory, files-copied count, the written file names, whether any file uses StyleX, and an optional maintainer note. | -| `template.list` | Every discovered template (page + block); each entry carries id, name, description, kind, owning package, optional category and componentsUsed, and readiness flags. | -| `template.show` | The resolved template's raw source plus its description, kind, and the component names it composes. | -| `template.skeleton` | A layout skeleton (structural tags with spatial annotations) plus the template's description and the components it composes. | -| `template.copy` | A scaffold receipt: template id, output directory, written file name, and file count. | -| `template.cdn` | A write receipt for the no-build-step CDN starter page: the path (relative to cwd), the Astryx version every CDN URL was pinned to, whether it was written, and the reason it was not — `exists` when a file was already there, which is a success. | -| `hook.list` | The hook catalog grouped by category: `detail` (the level: names \| compact \| full) and `components`, the grouped map of hook names, brief entries, or a full HookDoc per entry. | -| `hook.detail` | One hook's full authored HookDoc. | -| `hook.detail.params` | Just one hook's parameters table (HookParamDoc[]). | -| `theme.build` | A theme build receipt: name, token- and component-override counts, output size, the written outputs {css, js, dts, and variantsDts when applicable}, and any validation warnings. | -| `theme.build.check` | The --check receipt: theme name, an upToDate flag, the stale outputs (each {path, reason: missing \| outdated}), and the full list of checked paths. Writes nothing. | -| `theme.build.batch` | Several themes built in one invocation: `count` plus one {file, receipt} per theme in argument order, where receipt is that theme's theme.build (or theme.build.check) envelope, or null when it produced no CSS. | -| `theme.list` | Every bundled theme as a ThemeListEntry[]: each with slug, displayName, description, and a maintained flag. | -| `theme.add` | A scaffold receipt: resolved slug, displayName, maintained flag, outputDir (relative to cwd), the theme entry file, its exportName, and the files written. | -| `theme.template` | A write receipt for the annotated theme template: the path (relative to cwd), whether it was written, and the reason it was not — `exists` when a file was already there, which is a success. | -| `theme.targets` | The whole themeable surface: the echoed filter, the component count, and one entry per theming target — {key, className, component, props, states}, where props and states are its legal override keys. | -| `upgrade.list` | Every available codemod, oldest→newest, as {name, title, version, optional}; returned for --list without running anything. | -| `upgrade.status` | A short-circuit outcome with no codemods run (up_to_date, no_codemods, or config_fixable), each carrying the agent-docs summary. | -| `upgrade.run` | The run receipt: from/to versions, codemod count, integrations processed, the agent-docs summary, and (apply mode) filesChanged, transformsApplied, and per-codemod errors. | -| `manifest` | The self-describing CLI capability manifest: name, version, apiVersion, global options, the command tree (args, options, json flag, response types, examples), the jsonSupported allowlist, and the flat responseTypes index. | -| `doctor` | The health-check report: `checks` (each with id, label, status: pass \| warn \| fail \| info, a message, and a fix when not passing) plus a `summary` of counts per status. | -| `integration.validate` | The validation result: the package name and version (both null when no local manifest is found) plus issues, an AstryxIntegrationIssue[] of {code, severity: warning \| error, message}. | -| `layout.expand` | The expansion: parsed form, generated TSX code, componentsUsed, states (count of useState hooks scaffolded), todos, blocksReferenced (each {name, mode}), warnings, and written (the output path, or null when nothing was written). | -| `layout.check` | The validation result: a valid flag, the detected form, errors (each with line/col, message, formatted text, and suggestions), warnings, and the expression re-printed in both canonical surfaces (compact and outline). | -| `layout.grammar` | The XLE/XLO grammar cheatsheet: a text field with the full reference plus an aliases map (short name → canonical component) generated from this install's registry. | +| Type | What `data` carries | +| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `component.list` | The component catalog grouped by category: `detail` (the level: names \| compact \| full) and `components`, the grouped map of names+package, brief entries, or a full ComponentDoc per entry. | +| `component.detail` | One component's authored ComponentDoc plus ownership metadata (owner package, import specifier, and whether source is available). | +| `component.detail.props` | Just one component's props table (ComponentPropDoc[]). | +| `component.detail.source` | One component's source file, as {component, source}. | +| `component.detail.showcase` | One component's showcase example, as {component, aspectRatio, source}. | +| `component.detail.blocks` | One component's example blocks, as {component, showcase, examples, related} of BlockEntry. | +| `docs.list` | All reference-doc topics as DocsListEntry[] ({topic, description}), in discovery order. | +| `docs.detail` | One topic's full ReferenceDoc, with token-ref blocks inlined. | +| `docs.detail.section` | A single ReferenceSection of a topic: the first whose title contains the section query. | +| `blog.list` | The feed URL plus every post parsed from the RSS feed, each with slug, title, description, date, type, authors, link, and plaintext URL. | +| `blog.detail` | One post's metadata plus the feed URL and the post's full plaintext body. | +| `discover.list` | The configured external packages (name, category, components, version, description); when empty it carries meta.configured to tell "nothing configured" from "nothing discovered". | +| `discover.detail` | A single external package entry, for an @scope/name query. | +| `discover.detail.doc` | The validated ComponentDoc for one external component: an @scope/name/Component query, or a free-text term resolving to exactly one component. | +| `discover.search` | The echoed query plus the matching {package, component} pairs, when a free-text term matches several components. | +| `search` | The echoed query plus a ranked SearchResultEntry[] (domain, name, score, reason, description, follow-up command, and import path where relevant). | +| `build.help` | A marker (`playbook: true`) that the renderer expands into the how-to-build-a-page workflow; emitted when no query is given. | +| `build.kit` | The grouped composition kit: echoed query, hasResults/directMatch flags, the closest page templates, drop-in block patterns, idea-specific components/hooks, and the always-on frame + foundation component-name arrays. | +| `swizzle.list` | The names of swizzlable components discoverable from cwd's @astryxdesign/core. | +| `swizzle.copy` | An eject receipt: component name, owning package, output directory, files-copied count, the written file names, whether any file uses StyleX, and an optional maintainer note. | +| `template.list` | Every discovered template (page + block); each entry carries id, name, description, kind, owning package, optional category and componentsUsed, and readiness flags. | +| `template.show` | The resolved template's raw source plus its description, kind, and the component names it composes. | +| `template.skeleton` | A layout skeleton (structural tags with spatial annotations) plus the template's description and the components it composes. | +| `template.copy` | A scaffold receipt: template id, output directory, written file name, and file count. | +| `template.cdn` | A write receipt for the no-build-step CDN starter page: the path (relative to cwd), the Astryx version every CDN URL was pinned to, whether it was written, and the reason it was not. `exists` when a file was already there, which is a success. | +| `hook.list` | The hook catalog grouped by category: `detail` (the level: names \| compact \| full) and `components`, the grouped map of hook names, brief entries, or a full HookDoc per entry. | +| `hook.detail` | One hook's full authored HookDoc. | +| `hook.detail.params` | Just one hook's parameters table (HookParamDoc[]). | +| `theme.build` | A theme build receipt: name, token- and component-override counts, output size, the written outputs {css, js, dts, and variantsDts when applicable}, and any validation warnings. | +| `theme.build.check` | The --check receipt: theme name, an upToDate flag, the stale outputs (each {path, reason: missing \| outdated}), and the full list of checked paths. Writes nothing. | +| `theme.build.batch` | Several themes built in one invocation: `count` plus one {file, receipt} per theme in argument order, where receipt is that theme's theme.build (or theme.build.check) envelope, or null when it produced no CSS. | +| `theme.list` | Every bundled theme as a ThemeListEntry[]: each with slug, displayName, description, and a maintained flag. | +| `theme.add` | A scaffold receipt: resolved slug, displayName, maintained flag, outputDir (relative to cwd), the theme entry file, its exportName, and the files written. | +| `theme.template` | A write receipt for the annotated theme template: the path (relative to cwd), whether it was written, and the reason it was not. `exists` when a file was already there, which is a success. | +| `theme.targets` | The whole themeable surface: the echoed filter, the component count, and one entry per theming target — {key, className, component, props, states}, where props and states are its legal override keys. | +| `upgrade.list` | Every available codemod, oldest→newest, as {name, title, version, optional}; returned for --list without running anything. | +| `upgrade.status` | A short-circuit outcome with no codemods run (up_to_date, no_codemods, or config_fixable), each carrying the agent-docs summary. | +| `upgrade.run` | The run receipt: from/to versions, codemod count, integrations processed, the agent-docs summary, and (apply mode) filesChanged, transformsApplied, and per-codemod errors. | +| `manifest` | The self-describing CLI capability manifest: name, version, apiVersion, global options, the command tree (args, options, json flag, response types, examples), the jsonSupported allowlist, and the flat responseTypes index. | +| `doctor` | The health-check report: `checks` (each with id, label, status: pass \| warn \| fail \| info, a message, and a fix when not passing) plus a `summary` of counts per status. | +| `integration.validate` | The validation result: the package name and version (both null when no local manifest is found) plus issues, an AstryxIntegrationIssue[] of {code, severity: warning \| error, message}. | +| `layout.expand` | The expansion: parsed form, generated TSX code, componentsUsed, states (count of useState hooks scaffolded), todos, blocksReferenced (each {name, mode}), warnings, and written (the output path, or null when nothing was written). | +| `layout.check` | The validation result: a valid flag, the detected form, errors (each with line/col, message, formatted text, and suggestions), warnings, and the expression re-printed in both canonical surfaces (compact and outline). | +| `layout.grammar` | The XLE/XLO grammar cheatsheet: a text field with the full reference plus an aliases map (short name → canonical component) generated from this install's registry. | diff --git a/packages/cli/api/docs/docs.doc.mjs b/packages/cli/api/docs/docs.doc.mjs index efe95815f594a..3962d2cae6d0f 100644 --- a/packages/cli/api/docs/docs.doc.mjs +++ b/packages/cli/api/docs/docs.doc.mjs @@ -19,8 +19,8 @@ export const doc = { 'returns that full ReferenceDoc (with token-ref blocks inlined); a topic ' + 'plus a section returns the first section whose title contains the ' + '(case-insensitive) query. The topic set is the CLI\'s own docs plus the ' + - 'ones the project\'s configured integrations contribute — including any ' + - 'topic an integration replaces or extends — so it depends on the cwd. ' + + 'ones the project\'s configured integrations contribute, including any ' + + 'topic an integration replaces or extends, so it depends on the cwd. ' + 'Overlay options select localized or dense variants.', importPath: '@astryxdesign/cli/api', signature: diff --git a/packages/cli/api/template/template.doc.mjs b/packages/cli/api/template/template.doc.mjs index 549afadbea7da..e2ba07ebfcff2 100644 --- a/packages/cli/api/template/template.doc.mjs +++ b/packages/cli/api/template/template.doc.mjs @@ -104,7 +104,7 @@ export const doc = { { type: 'template.skeleton', description: - "A layout skeleton — structural tags with spatial annotations — plus the template's description and the components it composes.", + "A layout skeleton (structural tags with spatial annotations) plus the template's description and the components it composes.", }, { type: 'template.copy', @@ -114,7 +114,7 @@ export const doc = { { type: 'template.cdn', description: - 'A write receipt for the CDN starter page: the path (relative to cwd), the Astryx version every CDN URL was pinned to, whether it was written, and the reason it was not — `exists` when a file was already there, which is a success.', + 'A write receipt for the CDN starter page: the path (relative to cwd), the Astryx version every CDN URL was pinned to, whether it was written, and the reason it was not. `exists` when a file was already there, which is a success.', }, ], throws: [ diff --git a/packages/cli/api/theme/themeTemplate.doc.mjs b/packages/cli/api/theme/themeTemplate.doc.mjs index a33f33a296c11..71964b8d22c7b 100644 --- a/packages/cli/api/theme/themeTemplate.doc.mjs +++ b/packages/cli/api/theme/themeTemplate.doc.mjs @@ -15,9 +15,9 @@ export const doc = { displayName: 'themeTemplate()', summary: 'Write the annotated theme template into a project.', description: - 'Writes theme.template.ts: the annotated reference for the whole theme surface — every ' + + 'Writes theme.template.ts: the annotated reference for the whole theme surface, covering every ' + 'defineTheme field, the token families, the component override syntax, and how a theme is ' + - 'consumed — with the CLI command that prints the authoritative reference for each section. ' + + 'consumed, with the CLI command that prints the authoritative reference for each section. ' + 'Read it, copy what you need into your own theme file, delete it. Where `theme add` starts ' + 'you from a theme we ship, this starts you from a blank one. Refuses to overwrite without ' + '`overwrite`, so it is safe to re-run.', @@ -48,7 +48,7 @@ export const doc = { { type: 'theme.template', description: - 'Receipt: the path (relative to cwd), whether it was written, and the reason it was not — `exists` when a file was already there, which is a success, not a failure.', + 'Receipt: the path (relative to cwd), whether it was written, and the reason it was not. `exists` when a file was already there, which is a success, not a failure.', }, ], throws: [{code: 'ERR_PATH_TRAVERSAL', when: 'the target path escapes cwd'}], diff --git a/packages/cli/assets/docs/typography.doc.mjs b/packages/cli/assets/docs/typography.doc.mjs index 9e0de880e731c..2fa62fe63e11e 100644 --- a/packages/cli/assets/docs/typography.doc.mjs +++ b/packages/cli/assets/docs/typography.doc.mjs @@ -51,7 +51,7 @@ export const docs = { content: [ { type: 'prose', - text: 'Astryx never loads font files. defineTheme and the built CSS only set font-family — naming a webfont (Fraunces, JetBrains Mono, …) makes every browser look for it, and quietly fall back when the app has not loaded it. `astryx theme build` warns when a theme names families that are neither CSS generics nor common system fonts and prints the snippet to add; loading the font is always the app\'s job.', + text: 'Astryx never loads font files. defineTheme and the built CSS only set font-family: naming a webfont (Fraunces, JetBrains Mono, and so on) makes every browser look for it, and quietly fall back when the app has not loaded it. `astryx theme build` warns when a theme names families that are neither CSS generics nor common system fonts and prints the snippet to add; loading the font is always the app\'s job.', }, { type: 'code', @@ -77,7 +77,7 @@ export const docs = { }, { type: 'prose', - text: "Always pair a webfont with a real fallback stack — metric-similar system fonts plus a generic — so text stays readable before the font loads and wherever it never does: defineTheme({typography: {heading: {family: 'Fraunces', fallbacks: 'Georgia, serif'}}}).", + text: "Always pair a webfont with a real fallback stack (metric-similar system fonts plus a generic) so text stays readable before the font loads and wherever it never does: defineTheme({typography: {heading: {family: 'Fraunces', fallbacks: 'Georgia, serif'}}}).", }, ], }, diff --git a/packages/cli/clients/cli/commands/theme-template.doc.mjs b/packages/cli/clients/cli/commands/theme-template.doc.mjs index af4087d0784e0..b7117b20c00b9 100644 --- a/packages/cli/clients/cli/commands/theme-template.doc.mjs +++ b/packages/cli/clients/cli/commands/theme-template.doc.mjs @@ -16,9 +16,9 @@ export const doc = { namespace: 'cli', summary: 'Write the annotated theme template into your project', description: - 'Writes theme.template.ts: the annotated reference for the whole theme surface — every ' + + 'Writes theme.template.ts: the annotated reference for the whole theme surface, covering every ' + 'defineTheme field, the token families, the component override syntax, and how a theme is ' + - 'consumed — naming the CLI command that prints the authoritative reference for each. Read ' + + 'consumed, naming the CLI command that prints the authoritative reference for each. Read ' + 'it, copy what you need into your own theme file, delete it. Use `theme add ` instead ' + 'to start from a theme we ship. Leaves an existing file untouched unless --overwrite.', fn: 'themeTemplate', diff --git a/packages/cli/foundation/response/response-types.doc.mjs b/packages/cli/foundation/response/response-types.doc.mjs index 9d9825e9b2e45..921a77bd6c3b6 100644 --- a/packages/cli/foundation/response/response-types.doc.mjs +++ b/packages/cli/foundation/response/response-types.doc.mjs @@ -153,7 +153,7 @@ export const doc = { { value: 'template.cdn', description: - 'A write receipt for the no-build-step CDN starter page: the path (relative to cwd), the Astryx version every CDN URL was pinned to, whether it was written, and the reason it was not — `exists` when a file was already there, which is a success.', + 'A write receipt for the no-build-step CDN starter page: the path (relative to cwd), the Astryx version every CDN URL was pinned to, whether it was written, and the reason it was not. `exists` when a file was already there, which is a success.', }, // hook @@ -197,7 +197,7 @@ export const doc = { { value: 'theme.template', description: - 'A write receipt for the annotated theme template: the path (relative to cwd), whether it was written, and the reason it was not — `exists` when a file was already there, which is a success.', + 'A write receipt for the annotated theme template: the path (relative to cwd), whether it was written, and the reason it was not. `exists` when a file was already there, which is a success.', }, { value: 'theme.targets', diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index bb0314c088472..b59b46bbac14f 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -13,6 +13,7 @@ **The exit ran on the entrance's curve.** `--ease-standard` is `cubic-bezier(0.24, 1, 0.4, 1)`, a decelerate curve: it spends its speed immediately and coasts. Right for an entrance, wrong for an exit. Measured on device (iPhone, real Safari), a scrim tap put the sheet half off-screen in 59ms of the 410ms transition and 90% off in 163ms, with the dim gone before it — so the close was over before the eye could follow it. The closing state now carries an accelerating curve of its own, `cubic-bezier(0.3, 0, 0.6, 0.6)`: away from rest, gathering speed, quickest as it leaves the screen, and moving within ~50ms so it reads as one departure rather than a hesitation and a snap. Only the curve changes — the exit keeps `--duration-medium`, the entrance's band, which is what keeps it legible under a theme that scales the motion scale down (neutral's medium is 300ms against the base 410ms). The scrim leaves with the sheet: while closing, the dim runs `linear` rather than the decelerate token. A fade covers no distance, so front-loading its progress just ends it early — the reasoning the touch date picker's surface swap already carries. `BottomSheetSwitcher` gets the same treatment when its flow closes; a handoff between two sheets is not a close and is unchanged. + - `useListFocus` no longer swallows Escape when no `onEscape` was supplied. The hook called `preventDefault()` on every Escape — a habit inherited from the arrow keys, which share the handler and need it to suppress page scroll — so a list with nothing to dismiss still marked the key handled, and a surrounding layer that defers to `defaultPrevented` (a focus trap, a native popover) never got its turn. Escape is now consumed only when an `onEscape` is passed. Arrow, Home and End handling is unchanged (#5346). Behaviour change: `AvatarGroup`, `ButtonGroup`, `Outline`, `Pagination`, `SegmentedControl`, `TabList` and `Toolbar` pass no `onEscape`, so an Escape pressed inside one of them now reaches the surrounding layer and can dismiss it — the point of the fix, but a host that counted on the key stopping there will notice. `NavHeadingMenu` does the same when it renders without a menu close handler. Menus and flyouts that do pass `onEscape` are unaffected. `patch`, not `[breaking]`: the swallowing was never a contract — the hook documented Escape only as "custom callback", and no component advertised consuming the key. - TabList: the selected tab now carries `aria-current="true"` — ARIA's generic "current item within a set" — instead of `aria-current="page"`. The strip is a `