@astryxdesign/cli 0.1.6-canary.ff5dfca → 0.1.7-canary.04cd8f7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/README.md +115 -19
- package/docs/cli-integrations.doc.mjs +150 -0
- package/docs/getting-started.doc.mjs +9 -9
- package/docs/migration.doc.mjs +18 -18
- package/docs/principles.doc.dense.mjs +1 -1
- package/docs/principles.doc.mjs +6 -6
- package/docs/principles.doc.zh.mjs +1 -1
- package/docs/styling-libraries.doc.mjs +3 -3
- package/docs/styling.doc.mjs +4 -4
- package/docs/theme.doc.dense.mjs +2 -2
- package/docs/theme.doc.mjs +7 -7
- package/docs/theme.doc.zh.mjs +1 -1
- package/docs/tokens.doc.mjs +1 -1
- package/docs/working-with-ai.doc.mjs +18 -18
- package/package.json +9 -10
- package/src/api/doctor.mjs +3 -3
- package/src/codemods/ensure-jscodeshift.mjs +11 -27
- package/src/codemods/run-codemod.mjs +1 -1
- package/src/codemods/runner.mjs +2 -2
- package/src/commands/agent-docs.mjs +7 -8
- package/src/commands/agent-docs.test.mjs +11 -4
- package/src/commands/build-theme.mjs +10 -71
- package/src/commands/build.mjs +15 -15
- package/src/commands/component/index.mjs +4 -4
- package/src/commands/discover.mjs +7 -5
- package/src/commands/docs.mjs +4 -4
- package/src/commands/hook/index.mjs +4 -4
- package/src/commands/init.mjs +48 -152
- package/src/commands/init.next-steps.test.mjs +1 -1
- package/src/commands/interactive-guard.test.mjs +19 -22
- package/src/commands/json-contract.test.mjs +1 -1
- package/src/commands/layout.mjs +1 -1
- package/src/commands/search.mjs +4 -4
- package/src/commands/swizzle.mjs +11 -34
- package/src/commands/template.mjs +11 -31
- package/src/commands/upgrade.mjs +9 -6
- package/src/commands/upgrade.test.mjs +1 -1
- package/src/index.mjs +5 -6
- package/src/lib/component-format.mjs +2 -1
- package/src/lib/term-log.mjs +48 -0
- package/src/utils/package-manager.mjs +78 -0
- package/src/utils/package-manager.test.mjs +108 -1
- package/src/utils/path-safety.mjs +0 -18
- package/src/utils/update-check.mjs +2 -1
- package/templates/blocks/components/TabList/TabListTabsWithActions.doc.mjs +1 -1
- package/templates/blocks/components/TabList/TabListTabsWithActions.tsx +2 -7
- package/docs/integration-authoring.md +0 -105
- package/src/utils/interactive.mjs +0 -76
- package/src/utils/interactive.test.mjs +0 -70
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @xds/cli
|
|
2
2
|
|
|
3
|
+
# 0.1.7
|
|
4
|
+
|
|
5
|
+
#### New Features
|
|
6
|
+
|
|
7
|
+
- Export the authoring factories from `@astryxdesign/core`: `createConfig` at `@astryxdesign/core/config` and `createIntegration`/`createPageTemplate`/`createBlockTemplate`/`createComponentDoc`/`createFunctionDoc`/`createDoc` at `@astryxdesign/core/authoring`. Authoring a config or integration no longer requires depending on the CLI. Existing `@astryxdesign/cli/*` imports keep working via re-export.
|
|
8
|
+
- Add the finalized doc-authoring API to `@astryxdesign/cli/doc`: `createComponentDoc`, `createFunctionDoc` (any function, including hooks), and `createDoc` (generic reference/topic docs). Each factory stamps a `type` discriminant and is validated at the load boundary against a matching per-kind schema. The legacy loose `export const docs = {...}` format keeps loading unchanged, and `.ts`-authored hook/function sources now derive their import path to a tree-shakeable subpath instead of the bare package root.
|
|
9
|
+
- New codemod for the Table `tableProps` deprecation: lifts object-literal `tableProps` keys into direct props on `<Table>`, keeps colliding or dynamic values in place with a TODO note. **Codemod:** `npx astryx upgrade --codemod migrate-table-tableprops-to-direct-props` (#3679)
|
|
10
|
+
- New docs topic `internationalization` covering how to localize astryx components, provide translation catalogs, override default strings, coexist with existing i18n libraries (react-intl, i18next, next-intl), swap languages at runtime, and validate coverage with the shipped pseudo locale. Run `npx astryx docs internationalization` or read it at https://astryx.atmeta.com/docs/internationalization.
|
|
11
|
+
- template: accept `.template.{ts,mjs,js}` as the canonical suffix for template-spec files, alongside the legacy `.doc.*` suffix. Template specs export `createBlockTemplate`/`createPageTemplate` — a scaffoldable template, not documentation — so they now get a descriptive name. Core, external-package, and integration discovery (`findShowcase`, `--blocks`, `astryx template <id>` scaffolding) all treat `Foo.template.ts` identically to a legacy `Foo.doc.mjs`; same-stem `.tsx` source resolves for either suffix, and `.template.ts` authoring is loaded via jiti. Additive only — no existing files are renamed.
|
|
12
|
+
|
|
13
|
+
#### Fixes
|
|
14
|
+
|
|
15
|
+
- Translated component docs no longer drop props
|
|
16
|
+
A `docsZh` / `docsDense` block that carried its own `props` array replaced the English component doc **wholesale** rather than overlaying it, so any prop the translation had not caught up with simply ceased to exist. `astryx component Button --zh` silently omitted `isInterruptible` and `isIconOnly`; ten components were affected, including `MobileNav`, `Popover` and `Stack` through the multi-component `components[]` shape.
|
|
17
|
+
- Anchor --dense / --zh doc overlays to their base sections (#2182)
|
|
18
|
+
The compressed and translated reference docs were merged into the base doc **by array position**, so an overlay whose sections were ordered differently — or which omitted one — grafted every title onto the wrong body.
|
|
19
|
+
- template: inline full demo-image URLs in the Avatar blocks and theme-showcase page so scaffolding strips them to a clean placeholder. Templates that stored only the CDN base in a `const` and appended the filename via interpolation (`` `${CDN}/File.png` ``) previously scaffolded a malformed `src` — the placeholder data URI with the filename glued onto the end — plus a dead `const CDN = 'data:…'`. (#4027)
|
|
20
|
+
|
|
21
|
+
#### Documentation
|
|
22
|
+
|
|
23
|
+
- Document the minimal `package.json#exports` recipe an integration needs so its block templates are importable by a bundler-resolution consumer and type-check under `moduleResolution: bundler`: `"./templates/*.tsx": "./templates/*.tsx"` plus an extensionful `import('@acme/widgets/templates/…/…Showcase.tsx')`. Adds `packages/cli/docs/integration-authoring.md` and a fixture test proving the recipe against the repo's own `tsc` and `esbuild`.
|
|
24
|
+
|
|
25
|
+
#### Contributors
|
|
26
|
+
|
|
27
|
+
Thanks to everyone who contributed to this release:
|
|
28
|
+
|
|
29
|
+
- @AKnassa
|
|
30
|
+
- @ejhammond
|
|
31
|
+
- @imdreamrunner
|
|
32
|
+
- @nynexman4464
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
3
36
|
# 0.1.6
|
|
4
37
|
|
|
5
38
|
---
|
package/README.md
CHANGED
|
@@ -2,15 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
The CLI is the primary interface for working with the design system, for humans and machines alike. It provides component documentation, design tokens, page templates, theming tools, and upgrade codemods, all accessible via terminal commands, a typed JSON API, or programmatic imports. AI agents and build tools use the same API that powers the CLI, enabling end-to-end frontend development loops.
|
|
4
4
|
|
|
5
|
+
Run it one-off with the scoped package (works whether or not it's installed):
|
|
6
|
+
|
|
5
7
|
```bash
|
|
6
|
-
npx
|
|
7
|
-
npx
|
|
8
|
-
npx
|
|
9
|
-
npx
|
|
10
|
-
npx
|
|
11
|
-
npx
|
|
8
|
+
npx @astryxdesign/cli --help
|
|
9
|
+
npx @astryxdesign/cli search button
|
|
10
|
+
npx @astryxdesign/cli component Button
|
|
11
|
+
npx @astryxdesign/cli docs tokens
|
|
12
|
+
npx @astryxdesign/cli docs migration
|
|
13
|
+
npx @astryxdesign/cli template --list
|
|
12
14
|
```
|
|
13
15
|
|
|
16
|
+
Once it's a project dependency (`npm install -D @astryxdesign/cli`), drop the scope and use the shorter `astryx` — e.g. `npx astryx component Button` or `pnpm exec astryx component Button`. Bare `astryx` resolves to an unrelated npm package until the CLI is installed, so prefer the scoped form above for first-run/one-off use.
|
|
17
|
+
|
|
14
18
|
## Finding things: `astryx search`
|
|
15
19
|
|
|
16
20
|
When you don't know whether what you need is a component, a hook, a docs topic,
|
|
@@ -20,27 +24,29 @@ fuzzy matching for typos) and tagged with their domain plus the follow-up
|
|
|
20
24
|
command to run:
|
|
21
25
|
|
|
22
26
|
```bash
|
|
23
|
-
$
|
|
27
|
+
$ astryx search button
|
|
24
28
|
|
|
25
29
|
Results for "button" (20):
|
|
26
30
|
|
|
27
31
|
[component] Button
|
|
28
32
|
Button triggers an action when clicked. Use it for form submissions…
|
|
29
|
-
→
|
|
33
|
+
→ astryx component Button
|
|
30
34
|
|
|
31
35
|
[component] IconButton
|
|
32
36
|
A button that shows only an icon with no visible text…
|
|
33
|
-
→
|
|
37
|
+
→ astryx component IconButton
|
|
34
38
|
|
|
35
39
|
[hook] useClickableContainer
|
|
36
40
|
Makes a container element clickable while preserving nested…
|
|
37
|
-
→
|
|
41
|
+
→ astryx hook useClickableContainer
|
|
38
42
|
|
|
39
43
|
[template] Banner — Collapsible
|
|
40
44
|
Combine an action button, dismiss control, and expandable detail area…
|
|
41
|
-
→
|
|
45
|
+
→ astryx template BannerCollapsibleContent
|
|
42
46
|
```
|
|
43
47
|
|
|
48
|
+
(The CLI prints the follow-up commands with your actual runner — `npx astryx …` when installed, or `npx @astryxdesign/cli …` when run one-off.)
|
|
49
|
+
|
|
44
50
|
Options:
|
|
45
51
|
|
|
46
52
|
- `--type <component|hook|doc|template>`: restrict to a single domain
|
|
@@ -415,7 +421,7 @@ failures (warnings are fine) and `1` when any check fails. That makes it
|
|
|
415
421
|
usable directly as a CI step:
|
|
416
422
|
|
|
417
423
|
```yaml
|
|
418
|
-
- run: npx
|
|
424
|
+
- run: npx @astryxdesign/cli doctor
|
|
419
425
|
```
|
|
420
426
|
|
|
421
427
|
Use `--json` for a structured envelope (`{ apiVersion, type: "doctor",
|
|
@@ -423,13 +429,103 @@ data: { checks, summary } }`) that AI agents and scripts can parse.
|
|
|
423
429
|
|
|
424
430
|
## Configuration
|
|
425
431
|
|
|
426
|
-
The CLI reads
|
|
432
|
+
The CLI reads an optional `astryx.config.{ts,mjs,js}` from your project root
|
|
433
|
+
(a sibling of `package.json`). Every field is optional; with no config file the
|
|
434
|
+
CLI runs on defaults.
|
|
427
435
|
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
436
|
+
```typescript
|
|
437
|
+
import {createConfig} from '@astryxdesign/core/config';
|
|
438
|
+
|
|
439
|
+
export default createConfig({
|
|
440
|
+
integrations: ['@acme/astryx-widgets'],
|
|
433
441
|
issuesUrl: 'https://github.com/your-org/your-repo/issues',
|
|
434
|
-
};
|
|
442
|
+
});
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
`createConfig` is a type-preserving helper: it returns its argument unchanged
|
|
446
|
+
and exists only to give the config file editor autocomplete and type-checking. A
|
|
447
|
+
plain `export default {}` object works identically. It's exported from
|
|
448
|
+
`@astryxdesign/core` (not the CLI) so your config file gets type feedback
|
|
449
|
+
without depending on the CLI; the same helper is re-exported from
|
|
450
|
+
`@astryxdesign/cli/config` for back-compat.
|
|
451
|
+
|
|
452
|
+
| Field | Type | Purpose |
|
|
453
|
+
| ----------------------------- | ------------------------------ | ----------------------------------------------------------------------------------------------- |
|
|
454
|
+
| `integrations` | `string[]` | Integration package names to load (see [Integrations](#integrations)). |
|
|
455
|
+
| `issuesUrl` | `string` | Where "report an issue" links point for your project. Defaults to the core issue tracker. |
|
|
456
|
+
| `hooks.postCodemod` | `PostCodemodHook[]` | Commands to run after `astryx upgrade` applies codemods (e.g. reinstall, rebuild, reformat). |
|
|
457
|
+
| `experimental.xle.components` | `Record<string, XleComponent>` | Register app-local components so layout (XLE) expressions can reference them by name. Unstable. |
|
|
458
|
+
|
|
459
|
+
The config is validated against a strict schema when the CLI loads it, so an
|
|
460
|
+
unknown field is a hard error rather than a silent no-op. `astryx doctor`
|
|
461
|
+
reports whether the config loads cleanly.
|
|
462
|
+
|
|
463
|
+
## Integrations
|
|
464
|
+
|
|
465
|
+
An **integration** is any npm package that contributes its own components,
|
|
466
|
+
templates, and upgrade codemods to Astryx. The CLI surfaces them next to core's,
|
|
467
|
+
through the same commands, so a consumer can `astryx component`,
|
|
468
|
+
`astryx template`, and `astryx upgrade` across core and every integration
|
|
469
|
+
uniformly. Use it to ship a first-party add-on, publish a third-party component
|
|
470
|
+
library, or share an internal design-system package across apps.
|
|
471
|
+
|
|
472
|
+
The system runs on two files, each with a small typed API:
|
|
473
|
+
|
|
474
|
+
| File | Written by | Role |
|
|
475
|
+
| -------------------------------- | ---------- | ----------------------------------------- |
|
|
476
|
+
| `astryx.config.{ts,mjs,js}` | Consumer | Lists which integration packages to load. |
|
|
477
|
+
| `astryx.integration.{ts,mjs,js}` | Author | Declares what a package contributes. |
|
|
478
|
+
|
|
479
|
+
The consumer side is the `integrations` field of [`astryx.config`](#configuration).
|
|
480
|
+
The author side is the integration manifest below.
|
|
481
|
+
|
|
482
|
+
### The integration manifest
|
|
483
|
+
|
|
484
|
+
A package becomes an integration by exporting a manifest from
|
|
485
|
+
`astryx.integration.{ts,mjs,js}` at its root (a sibling of `package.json`). The
|
|
486
|
+
manifest points at where each kind of contribution lives; identity (name,
|
|
487
|
+
version) comes from `package.json`, not the manifest.
|
|
488
|
+
|
|
489
|
+
```typescript
|
|
490
|
+
import {createIntegration} from '@astryxdesign/core/authoring';
|
|
491
|
+
|
|
492
|
+
export default createIntegration({
|
|
493
|
+
components: './components',
|
|
494
|
+
templates: './templates',
|
|
495
|
+
codemods: './codemods',
|
|
496
|
+
issuesUrl: 'https://github.com/acme/widgets/issues',
|
|
497
|
+
});
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
| Field | Type | Purpose |
|
|
501
|
+
| ------------ | -------- | --------------------------------------------------------------------- |
|
|
502
|
+
| `components` | `string` | Directory holding the package's components and their `.doc.*` files. |
|
|
503
|
+
| `templates` | `string` | Directory holding the package's page/block templates. |
|
|
504
|
+
| `codemods` | `string` | Directory holding upgrade codemods run by `astryx upgrade`. |
|
|
505
|
+
| `issuesUrl` | `string` | Where "report an issue" links for this package's contributions point. |
|
|
506
|
+
|
|
507
|
+
Every field is optional; declare only the roots the package ships.
|
|
508
|
+
`createIntegration` is a type-preserving helper (editor autocomplete and
|
|
509
|
+
type-checking); it lives in `@astryxdesign/core/authoring` and is re-exported
|
|
510
|
+
from `@astryxdesign/cli/integration` for back-compat.
|
|
511
|
+
|
|
512
|
+
### How it works
|
|
513
|
+
|
|
514
|
+
Every command loads the consumer's `astryx.config`, resolves each listed
|
|
515
|
+
integration's manifest from `node_modules`, and discovers its contributions.
|
|
516
|
+
Everything is validated against one strict schema at the load boundary, so the
|
|
517
|
+
CLI presents core and integration contributions through a single, uniform
|
|
518
|
+
surface.
|
|
519
|
+
|
|
520
|
+
Discovery is resilient: a broken or misconfigured integration is skipped with a
|
|
521
|
+
one-line warning on stderr instead of crashing the CLI, and it never corrupts a
|
|
522
|
+
`--json` envelope. To inspect problems, run
|
|
523
|
+
`astryx validate-integration <package>` for a detailed report on one package, or
|
|
524
|
+
`astryx doctor` for an overall health check.
|
|
525
|
+
|
|
526
|
+
For the full authoring walkthrough (component doc format, template packaging
|
|
527
|
+
and `exports` requirements, and codemod authoring), see the guide:
|
|
528
|
+
|
|
529
|
+
```bash
|
|
530
|
+
astryx docs cli-integrations
|
|
435
531
|
```
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('../../core/src/docs-types').ReferenceDoc} */
|
|
4
|
+
|
|
5
|
+
export const docs = {
|
|
6
|
+
name: 'cli-integrations',
|
|
7
|
+
title: 'CLI Integrations',
|
|
8
|
+
category: 'guide',
|
|
9
|
+
description:
|
|
10
|
+
'Author an npm package that contributes components, templates, and upgrade codemods to Astryx.',
|
|
11
|
+
|
|
12
|
+
sections: [
|
|
13
|
+
{
|
|
14
|
+
title: 'Overview',
|
|
15
|
+
category: 'guide',
|
|
16
|
+
content: [
|
|
17
|
+
{
|
|
18
|
+
type: 'prose',
|
|
19
|
+
text: 'An integration is an npm package that contributes components, templates, and/or upgrade codemods to a consumer\u2019s design-system workflow. Consumers install the package and add it to their `astryx.config`; from then on the integration\u2019s contributions show up alongside core\u2019s in the same CLI commands.',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
type: 'prose',
|
|
23
|
+
text: 'The system runs on two files. The consumer writes `astryx.config.{ts,mjs,js}` at their project root to list which packages to load. The author writes `astryx.integration.{ts,mjs,js}` at the package root to declare what the package contributes. This page is the author\u2019s guide. For the consumer side, run `npx astryx docs getting-started`.',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: 'prose',
|
|
27
|
+
text: 'On the consumer side, adding your package is one line:',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
type: 'code',
|
|
31
|
+
lang: 'typescript',
|
|
32
|
+
code: "import {createConfig} from '@astryxdesign/core/config';\n\nexport default createConfig({\n integrations: ['@acme/astryx-widgets'],\n});",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
type: 'prose',
|
|
36
|
+
text: 'Your components and templates then appear next to core\u2019s:',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
type: 'code',
|
|
40
|
+
lang: 'bash',
|
|
41
|
+
code: 'astryx component --list --package @acme/astryx-widgets\nastryx component AcmeCarousel --props',
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
title: 'The Integration File',
|
|
47
|
+
category: 'guide',
|
|
48
|
+
content: [
|
|
49
|
+
{
|
|
50
|
+
type: 'prose',
|
|
51
|
+
text: 'To register your package as an integration, add an `astryx.integration.{ts,mjs,js}` file as a sibling of your `package.json`. It tells the CLI where to find your components, templates, and codemods. Identity (name, version) comes from your `package.json`, not this file.',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
type: 'code',
|
|
55
|
+
lang: 'typescript',
|
|
56
|
+
code: "// astryx.integration.ts\nimport {createIntegration} from '@astryxdesign/core/authoring';\n\nexport default createIntegration({\n components: './components',\n templates: './templates',\n codemods: './codemods',\n issuesUrl: 'https://github.com/acme/widgets/issues',\n});",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
type: 'prose',
|
|
60
|
+
text: 'Every field is optional. Declare only the contribution roots your package ships. `createIntegration` is a type-preserving helper for editor autocomplete and type-checking. It lives in `@astryxdesign/core/authoring` and is also re-exported from `@astryxdesign/cli/integration` for back-compat.',
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
title: 'Components',
|
|
66
|
+
category: 'guide',
|
|
67
|
+
content: [
|
|
68
|
+
{
|
|
69
|
+
type: 'prose',
|
|
70
|
+
text: 'Export your components from your library however you like, and consumers still import them from your package. For each component the CLI should document, ship a `.doc.{ts,mjs,js}` file with the same stem, for example `AcmeCarousel.tsx` alongside `AcmeCarousel.doc.ts`.',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
type: 'code',
|
|
74
|
+
lang: 'typescript',
|
|
75
|
+
code: "// AcmeCarousel.doc.ts\nimport {createComponentDoc} from '@astryxdesign/core/authoring';\n\nexport default createComponentDoc({\n name: 'AcmeCarousel',\n description: 'A carousel that cycles through slides.',\n // props, usage, examples, ...\n});",
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
title: 'Templates',
|
|
81
|
+
category: 'guide',
|
|
82
|
+
content: [
|
|
83
|
+
{
|
|
84
|
+
type: 'prose',
|
|
85
|
+
text: 'Templates are usually not exported from the package directly. Instead, consumers browse them through the CLI and materialize them into their app. Define a template with `createPageTemplate` (full pages) or `createBlockTemplate` (smaller chunks) in a `.template.{ts,mjs,js}` file next to the source, for example `AcmeLandingPage.tsx` and `AcmeLandingPage.template.ts`.',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
type: 'code',
|
|
89
|
+
lang: 'typescript',
|
|
90
|
+
code: "// AcmeLandingPage.template.ts\nimport {createPageTemplate} from '@astryxdesign/core/authoring';\n\nexport default createPageTemplate({\n // name, description, preview, ...\n});",
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
type: 'prose',
|
|
94
|
+
text: 'The CLI needs the template source at consume time, so make sure it is included in your published package. This is typically done via the `exports` key in `package.json`. It also lets the docsite render template previews in the future.',
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
type: 'code',
|
|
98
|
+
lang: 'jsonc',
|
|
99
|
+
code: '{\n "exports": {\n // ...\n "./templates/*.tsx": "./templates/*.tsx"\n }\n}',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
type: 'prose',
|
|
103
|
+
text: 'To verify it resolves, try importing the template component with its `.tsx` extension. An extensionless specifier will not resolve under `moduleResolution: bundler`, and the extensionful export above is what lets this type-check without consumers enabling `allowImportingTsExtensions`.',
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
type: 'code',
|
|
107
|
+
lang: 'typescript',
|
|
108
|
+
code: "import('@acme/astryx-widgets/templates/AcmeLandingPage.tsx');",
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
title: 'Codemods',
|
|
114
|
+
category: 'guide',
|
|
115
|
+
content: [
|
|
116
|
+
{
|
|
117
|
+
type: 'prose',
|
|
118
|
+
text: 'Ship codemods so `astryx upgrade` can migrate consumers across breaking changes in your package. Point the integration file\u2019s `codemods` field at your codemods root, and author each one with `createCodemod` (transforms source files) or `createConfigCodemod` (rewrites the consumer\u2019s `astryx.config`).',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
type: 'code',
|
|
122
|
+
lang: 'typescript',
|
|
123
|
+
code: "// codemods/v2-rename-prop.ts\nimport {createCodemod} from '@astryxdesign/cli/codemod';\n\nexport default createCodemod({\n // version, description, transform, ...\n});",
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
type: 'prose',
|
|
127
|
+
text: 'The codemod helpers live in `@astryxdesign/cli/codemod`, not `@astryxdesign/core/authoring` like the doc, integration, and template helpers. Consumers can also run their own post-codemod hooks, such as a reinstall or rebuild, via `hooks.postCodemod` in their `astryx.config`.',
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
title: 'How It Works',
|
|
133
|
+
category: 'guide',
|
|
134
|
+
content: [
|
|
135
|
+
{
|
|
136
|
+
type: 'prose',
|
|
137
|
+
text: 'Every CLI command loads the consumer\u2019s `astryx.config`, resolves each listed integration\u2019s manifest from `node_modules`, and discovers its contributions. Everything is validated against one strict schema at the load boundary. The `create*` helpers do not validate. They are identity functions whose value is their TypeScript surface, so validation happens when the CLI loads the file, not when you author it.',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
type: 'prose',
|
|
141
|
+
text: 'Discovery is resilient. A broken or misconfigured integration is skipped with a single non-blocking warning on stderr instead of crashing the CLI, and it never corrupts a `--json` stdout envelope. Everyday commands keep working with the remaining valid contributions.',
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
type: 'prose',
|
|
145
|
+
text: 'To inspect problems, run `astryx validate-integration <package>` for a detailed report on one package, or `astryx doctor` for an overall health check of the setup.',
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
};
|
|
@@ -21,7 +21,7 @@ export const docs = {
|
|
|
21
21
|
type: 'code',
|
|
22
22
|
lang: 'text',
|
|
23
23
|
label: 'Paste this into your AI',
|
|
24
|
-
code: 'Install @astryxdesign/core, @astryxdesign/theme-neutral, and @astryxdesign/cli in this project
|
|
24
|
+
code: 'Install @astryxdesign/core, @astryxdesign/theme-neutral, and @astryxdesign/cli in this project, then run `npx @astryxdesign/cli init` to set up agent docs. Read the generated files to learn the conventions.',
|
|
25
25
|
},
|
|
26
26
|
],
|
|
27
27
|
},
|
|
@@ -40,7 +40,7 @@ export const docs = {
|
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
type: 'prose',
|
|
43
|
-
text:
|
|
43
|
+
text: "Then run `astryx init` to install the AI agent cheat sheet (AGENTS.md/CLAUDE.md). It's non-interactive — no prompts — so it's safe for AI agents, CI, and scripts. Add `--all` for pointers to the theme and page-building workflows.",
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
type: 'code',
|
|
@@ -67,11 +67,11 @@ export const docs = {
|
|
|
67
67
|
},
|
|
68
68
|
{
|
|
69
69
|
type: 'prose',
|
|
70
|
-
text: 'Available themes: @astryxdesign/theme-neutral (muted minimal, a good starting point), @astryxdesign/theme-butter, @astryxdesign/theme-chocolate, @astryxdesign/theme-gothic (dark-only), @astryxdesign/theme-matcha, @astryxdesign/theme-stone, and @astryxdesign/theme-y2k. See `
|
|
70
|
+
text: 'Available themes: @astryxdesign/theme-neutral (muted minimal, a good starting point), @astryxdesign/theme-butter, @astryxdesign/theme-chocolate, @astryxdesign/theme-gothic (dark-only), @astryxdesign/theme-matcha, @astryxdesign/theme-stone, and @astryxdesign/theme-y2k. See `astryx docs theme` for the full theming guide.',
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
type: 'prose',
|
|
74
|
-
text: 'These stylesheets are cascade-layered: the reset loads in @layer reset and component styles in @layer astryx-base. If your project has existing global CSS, a legacy reset, or Tailwind, declare the layer order explicitly and assign every stylesheet to a layer deliberately: unlayered styles and later layers both override astryx-base regardless of specificity. See the Cascade Layer Safety section in `
|
|
74
|
+
text: 'These stylesheets are cascade-layered: the reset loads in @layer reset and component styles in @layer astryx-base. If your project has existing global CSS, a legacy reset, or Tailwind, declare the layer order explicitly and assign every stylesheet to a layer deliberately: unlayered styles and later layers both override astryx-base regardless of specificity. See the Cascade Layer Safety section in `astryx docs migration` before building screens.',
|
|
75
75
|
},
|
|
76
76
|
],
|
|
77
77
|
},
|
|
@@ -172,11 +172,11 @@ pnpm dev`,
|
|
|
172
172
|
type: 'code',
|
|
173
173
|
lang: 'bash',
|
|
174
174
|
label: 'Terminal',
|
|
175
|
-
code: `
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
175
|
+
code: `astryx component # list all components
|
|
176
|
+
astryx component Button # props, usage, theming for Button
|
|
177
|
+
astryx docs # list all doc topics
|
|
178
|
+
astryx template --list # available page templates
|
|
179
|
+
astryx docs tokens # spacing, color, radius reference`,
|
|
180
180
|
},
|
|
181
181
|
],
|
|
182
182
|
},
|
package/docs/migration.doc.mjs
CHANGED
|
@@ -54,18 +54,18 @@ export const docs = {
|
|
|
54
54
|
type: 'code',
|
|
55
55
|
lang: 'bash',
|
|
56
56
|
label: 'Migration-oriented CLI pass',
|
|
57
|
-
code: `
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
57
|
+
code: `astryx docs migration
|
|
58
|
+
astryx docs theme
|
|
59
|
+
astryx docs styling
|
|
60
|
+
astryx template --list --type block
|
|
61
|
+
astryx template AppShellTopNavWithSideNav --skeleton
|
|
62
|
+
astryx template PopoverSettingsPanel --skeleton
|
|
63
|
+
astryx component AppShell
|
|
64
|
+
astryx component SideNav
|
|
65
|
+
astryx component TopNav
|
|
66
|
+
astryx component CommandPalette
|
|
67
|
+
astryx component Button
|
|
68
|
+
astryx component TextInput`,
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
type: 'prose',
|
|
@@ -75,8 +75,8 @@ npx astryx component TextInput`,
|
|
|
75
75
|
type: 'code',
|
|
76
76
|
lang: 'bash',
|
|
77
77
|
label: 'Dense and JSON modes',
|
|
78
|
-
code: `
|
|
79
|
-
|
|
78
|
+
code: `astryx docs migration --dense
|
|
79
|
+
astryx component Button --json`,
|
|
80
80
|
},
|
|
81
81
|
],
|
|
82
82
|
},
|
|
@@ -371,10 +371,10 @@ if (getComputedStyle(button).paddingInline === '0px') {
|
|
|
371
371
|
code: `We are migrating this existing Tailwind/shadcn app to Astryx incrementally.
|
|
372
372
|
|
|
373
373
|
First run:
|
|
374
|
-
-
|
|
375
|
-
-
|
|
376
|
-
-
|
|
377
|
-
-
|
|
374
|
+
- astryx docs migration --dense
|
|
375
|
+
- astryx docs theme --dense
|
|
376
|
+
- astryx docs styling --dense
|
|
377
|
+
- astryx template AppShellTopNavWithSideNav --skeleton
|
|
378
378
|
|
|
379
379
|
Then migrate one route or shell surface at a time. Keep business logic and routing intact. Replace shadcn/Radix/Tailwind primitives with Astryx components, remove hardcoded colors, verify light and dark mode, and take screenshots before moving to the next surface.`,
|
|
380
380
|
},
|
|
@@ -9,6 +9,6 @@ export const docsDense = {
|
|
|
9
9
|
{ section: 'Rules', title: 'Rules', content: [{ type: 'list', items: ['use components', 'frame-first layout: shell + region budgets before content (astryx docs layout)', 'dense data = rows (Table, List/Item) not Cards; Card = widgets/galleries/settings groups', 'StyleX or Tailwind for styling', 'semantic tokens only', 'CSS vars for colors', 'controlled form inputs', 'useLinkComponent() for navigation'] }] },
|
|
10
10
|
{ section: 'Styling Approach', title: 'Styling', content: [{ type: 'prose', text: 'xstyle prop for component overrides. StyleX or Tailwind for layout. See astryx docs styling.' }] },
|
|
11
11
|
{ section: 'Anti-Patterns', title: 'Anti-Patterns', content: [{ type: 'list', items: ['no inline styles on raw elements', 'no hardcoded colors — use tokens or Tailwind semantic classes', 'no hardcoded spacing', 'no hardcoded <a> — use useLinkComponent()', 'no Card-wrapped list items — frame first, rows for dense data (astryx docs layout)', 'no decorative Badge — StatusDot/Token for status', 'read docs before inventing props'] }] },
|
|
12
|
-
{ section: 'Design Tokens', title: 'Tokens', content: [{ type: 'prose', text: 'run
|
|
12
|
+
{ section: 'Design Tokens', title: 'Tokens', content: [{ type: 'prose', text: 'run astryx docs tokens for full reference' }] },
|
|
13
13
|
],
|
|
14
14
|
};
|
package/docs/principles.doc.mjs
CHANGED
|
@@ -39,10 +39,10 @@ export const docs = {
|
|
|
39
39
|
style: 'ordered',
|
|
40
40
|
items: [
|
|
41
41
|
'Use components for everything they cover',
|
|
42
|
-
'Layout is frame-first: pick the shell and budget regions before writing content (see \`
|
|
42
|
+
'Layout is frame-first: pick the shell and budget regions before writing content (see \`astryx docs layout\`)',
|
|
43
43
|
'Dense data renders as rows (Table, List/Item), edge-to-edge with dividers; Card is for widgets, galleries, and settings groups',
|
|
44
|
-
'StyleX or Tailwind for custom styling; both are first-class (see \`
|
|
45
|
-
'Semantic tokens, not hardcoded values (see \`
|
|
44
|
+
'StyleX or Tailwind for custom styling; both are first-class (see \`astryx docs styling\`)',
|
|
45
|
+
'Semantic tokens, not hardcoded values (see \`astryx docs tokens\`)',
|
|
46
46
|
'CSS custom properties for colors, not hex values',
|
|
47
47
|
'Form inputs are controlled (value + onChange)',
|
|
48
48
|
'Use useLinkComponent() for navigation so consumers can plug in their framework router via LinkProvider',
|
|
@@ -60,7 +60,7 @@ export const docs = {
|
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
62
|
type: 'prose',
|
|
63
|
-
text: 'See \`
|
|
63
|
+
text: 'See \`astryx docs styling\` for the complete guide with examples.',
|
|
64
64
|
},
|
|
65
65
|
],
|
|
66
66
|
},
|
|
@@ -76,7 +76,7 @@ export const docs = {
|
|
|
76
76
|
'Hardcoded colors (#fff). Use var(--color-*) or Tailwind semantic classes (text-primary, bg-surface)',
|
|
77
77
|
'Hardcoded spacing (16px). Use spacing tokens or Tailwind spacing utilities',
|
|
78
78
|
'Hardcoded <a> elements. Use useLinkComponent() so consumers can swap in their framework router via LinkProvider',
|
|
79
|
-
'Wrapping every list item or page section in a Card. Decide the frame first; dense data renders as rows (see \`
|
|
79
|
+
'Wrapping every list item or page section in a Card. Decide the frame first; dense data renders as rows (see \`astryx docs layout\`)',
|
|
80
80
|
'Badge as decoration. Reserve Badge for counts and enumerated states; use StatusDot or Token for status',
|
|
81
81
|
'Inventing props. Read component docs first',
|
|
82
82
|
],
|
|
@@ -89,7 +89,7 @@ export const docs = {
|
|
|
89
89
|
content: [
|
|
90
90
|
{
|
|
91
91
|
type: 'prose',
|
|
92
|
-
text: 'The design system provides semantic design tokens for spacing, color, radius, shadow, typography, and size. Tokens adapt to the active theme and color mode. Run \`
|
|
92
|
+
text: 'The design system provides semantic design tokens for spacing, color, radius, shadow, typography, and size. Tokens adapt to the active theme and color mode. Run \`astryx docs tokens\` for the full reference with all values.',
|
|
93
93
|
},
|
|
94
94
|
],
|
|
95
95
|
},
|
|
@@ -9,6 +9,6 @@ export const docsZh = {
|
|
|
9
9
|
{ section: 'Rules', title: '规则', content: [{ type: 'list', items: ['所有支持的场景都使用 XDS 组件', '布局采用框架优先:先选定外壳并规划区域尺寸,再编写内容(见 astryx docs layout)', '密集数据使用行(Table、List/Item)通栏渲染;Card 用于小部件、画廊和设置分组', '使用 StyleX 或 Tailwind 进行样式设置', '使用语义化令牌,不使用硬编码值', '使用 CSS 变量设置颜色,不使用十六进制值', '表单输入为受控组件(value + onChange)', '使用 useLinkComponent() 进行导航'] }] },
|
|
10
10
|
{ section: 'Styling Approach', title: '样式方法', content: [{ type: 'prose', text: '组件覆盖使用 xstyle 属性。布局使用 StyleX 或 Tailwind。详见 astryx docs styling。' }] },
|
|
11
11
|
{ section: 'Anti-Patterns', title: '反模式', content: [{ type: 'list', items: ['不要在原始元素上使用内联样式', '不要硬编码颜色 — 使用令牌或 Tailwind 语义类', '不要硬编码间距', '不要硬编码 <a> 元素 — 使用 useLinkComponent()', '不要把每个列表项都包在 Card 里 — 先定框架,密集数据用行渲染(见 astryx docs layout)', '不要把 Badge 当装饰 — 状态请使用 StatusDot 或 Token', '不要自创属性。先阅读组件文档'] }] },
|
|
12
|
-
{ section: 'Design Tokens', title: '设计令牌', content: [{ type: 'prose', text: '运行
|
|
12
|
+
{ section: 'Design Tokens', title: '设计令牌', content: [{ type: 'prose', text: '运行 astryx docs tokens 查看完整参考' }] },
|
|
13
13
|
],
|
|
14
14
|
};
|
|
@@ -24,7 +24,7 @@ export const docs = {
|
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
type: 'prose',
|
|
27
|
-
text: 'For available token names and values, run `
|
|
27
|
+
text: 'For available token names and values, run `astryx docs tokens`. Focused references are also available with `astryx docs color`, `astryx docs spacing`, `astryx docs shape`, `astryx docs typography`, `astryx docs elevation`, and `astryx docs motion`.',
|
|
28
28
|
},
|
|
29
29
|
],
|
|
30
30
|
},
|
|
@@ -452,10 +452,10 @@ function RevenueChart({data}: {data: Array<{x: string; y: number}>}) {
|
|
|
452
452
|
type: 'list',
|
|
453
453
|
style: 'ordered',
|
|
454
454
|
items: [
|
|
455
|
-
'Import the reset/base CSS and a theme CSS file early enough for first paint. For production SSR, prefer built themes from `
|
|
455
|
+
'Import the reset/base CSS and a theme CSS file early enough for first paint. For production SSR, prefer built themes from `astryx theme build` or published `/built` theme imports plus `theme.css`.',
|
|
456
456
|
'Choose one owner for color mode. Theme uses `data-theme="light|dark"` and `color-scheme` to resolve `light-dark()` tokens.',
|
|
457
457
|
'Map the external library\'s semantic layer to system variables by intent, not by exact naming. For example, MUI `background.paper` maps to `--color-background-surface`.',
|
|
458
|
-
'Use `
|
|
458
|
+
'Use `astryx docs tokens` and focused token docs when building mappings. Keep mappings small at first: text, surface/body/card/popover, border, accent, status, spacing, radius, typography, shadow.',
|
|
459
459
|
'Use token resolver APIs only for non-CSS APIs that need resolved values.',
|
|
460
460
|
],
|
|
461
461
|
},
|
package/docs/styling.doc.mjs
CHANGED
|
@@ -30,7 +30,7 @@ export const docs = {
|
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
type: 'prose',
|
|
33
|
-
text: 'All approaches resolve to the same design tokens, so theming and dark mode work regardless of which you choose. For external styling libraries, run `
|
|
33
|
+
text: 'All approaches resolve to the same design tokens, so theming and dark mode work regardless of which you choose. For external styling libraries, run `astryx docs styling-libraries`; it covers Tailwind, StyleX, Panda, Chakra, MUI, CSS-in-JS, CSS Modules, Sass, and `useTheme()` for non-CSS processing.',
|
|
34
34
|
},
|
|
35
35
|
],
|
|
36
36
|
},
|
|
@@ -118,7 +118,7 @@ const overrides = stylex.create({
|
|
|
118
118
|
},
|
|
119
119
|
{
|
|
120
120
|
type: 'prose',
|
|
121
|
-
text: 'The bridge is pure CSS with zero JS. Theme changes (dark mode, custom themes) apply automatically because the utilities reference the same CSS custom properties that components use. This is the paved Tailwind path; for other styling libraries that follow the same aliasing pattern, run `
|
|
121
|
+
text: 'The bridge is pure CSS with zero JS. Theme changes (dark mode, custom themes) apply automatically because the utilities reference the same CSS custom properties that components use. This is the paved Tailwind path; for other styling libraries that follow the same aliasing pattern, run `astryx docs styling-libraries`.',
|
|
122
122
|
},
|
|
123
123
|
],
|
|
124
124
|
},
|
|
@@ -263,7 +263,7 @@ const overrides = stylex.create({
|
|
|
263
263
|
},
|
|
264
264
|
{
|
|
265
265
|
type: 'prose',
|
|
266
|
-
text: 'For systematic theming, use defineTheme component overrides instead of raw CSS selectors. defineTheme keeps the higher-level `prop:value` API (`variant:primary`, `size:sm`) and handles selector generation for you. Run `
|
|
266
|
+
text: 'For systematic theming, use defineTheme component overrides instead of raw CSS selectors. defineTheme keeps the higher-level `prop:value` API (`variant:primary`, `size:sm`) and handles selector generation for you. Run `astryx docs theme` for the full theming guide.',
|
|
267
267
|
},
|
|
268
268
|
],
|
|
269
269
|
},
|
|
@@ -334,7 +334,7 @@ const styles = stylex.create({
|
|
|
334
334
|
},
|
|
335
335
|
{
|
|
336
336
|
type: 'prose',
|
|
337
|
-
text: 'See `
|
|
337
|
+
text: 'See `astryx docs tokens` for the full token reference (all spacing, color, radius, shadow, and typography tokens with values). See `astryx docs theme` for how to override tokens via defineTheme.',
|
|
338
338
|
},
|
|
339
339
|
],
|
|
340
340
|
},
|
package/docs/theme.doc.dense.mjs
CHANGED
|
@@ -10,9 +10,9 @@ export const docsDense = {
|
|
|
10
10
|
{ section: 'Theme Props', title: 'Props', content: [null] },
|
|
11
11
|
{ section: 'Creating a Custom Theme', title: 'Custom Theme', content: [{ type: 'prose', text: 'CLI wizard or manual defineTheme. only override tokens that differ.' }, null] },
|
|
12
12
|
{ section: 'defineTheme', title: 'defineTheme', content: [{ type: 'prose', text: 'scale configs (color, typography, radius, motion) + explicit token overrides + component overrides. color derives full palette from accent hex via HCT.' }, null, null] },
|
|
13
|
-
{ section: 'Component Style Overrides', title: 'Component Overrides', content: [{ type: 'prose', text: 'components field uses semantic component keys + style keys (base, variant:value, stateName), not raw selectors. for external CSS, prefer data-* selectors from `astryx docs styling`. write standard CSS (borderRadius, padding) — pipeline expands to internal vars. public vars (--button-press-scale etc) set directly. private vars (--_*) cannot be set — use CSS properties. run `
|
|
13
|
+
{ section: 'Component Style Overrides', title: 'Component Overrides', content: [{ type: 'prose', text: 'components field uses semantic component keys + style keys (base, variant:value, stateName), not raw selectors. for external CSS, prefer data-* selectors from `astryx docs styling`. write standard CSS (borderRadius, padding) — pipeline expands to internal vars. public vars (--button-press-scale etc) set directly. private vars (--_*) cannot be set — use CSS properties. run `astryx component <Name>` for details.' }, null, null, null, null] },
|
|
14
14
|
{ section: 'Custom Variants', title: 'Custom Variants', content: [{ type: 'prose', text: 'any unknown prop:value in components becomes a new variant. astryx theme build generates TS augmentations. works on any extensible prop axis (variant, status, etc).' }, null, null, null, null] },
|
|
15
|
-
{ section: 'Building Themes for Production', title: 'Build for Production', content: [{ type: 'prose', text: '
|
|
15
|
+
{ section: 'Building Themes for Production', title: 'Build for Production', content: [{ type: 'prose', text: 'astryx theme build compiles defineTheme to static CSS. outputs .css + .js (__built:true) + .d.ts.' }, null, null, null, null] },
|
|
16
16
|
{ section: 'Runtime vs Built Themes', title: 'Runtime vs Built', content: [{ type: 'prose', text: 'runtime: useInsertionEffect injects styles client-side. built: static CSS on first paint. USE /built + theme.css FOR SSR.' }, null, null, null] },
|
|
17
17
|
{ section: 'Light/Dark Mode', title: 'Light/Dark', content: [{ type: 'prose', text: 'light-dark() in token values via [light, dark] tuples. mode=system follows OS.' }, null, null] },
|
|
18
18
|
{ section: 'Nesting Themes', title: 'Nesting', content: [{ type: 'prose', text: 'wrap sections in separate <Theme> providers' }, null] },
|