@astryxdesign/cli 0.0.15 → 0.1.0-canary.0b5b49f
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 +88 -0
- package/README.md +1 -1
- package/docs/getting-started.doc.mjs +15 -15
- package/docs/migration.doc.mjs +4 -4
- package/docs/styling-libraries.doc.mjs +3 -3
- package/docs/styling.doc.mjs +2 -3
- package/docs/theme.doc.dense.mjs +1 -1
- package/docs/theme.doc.mjs +39 -19
- package/docs/theme.doc.zh.mjs +1 -1
- package/package.json +9 -13
- package/src/api/doctor.mjs +4 -4
- package/src/commands/agent-docs.mjs +27 -10
- package/src/commands/agent-docs.test.mjs +21 -21
- package/src/commands/doctor.test.mjs +3 -3
- package/src/commands/init.mjs +3 -3
- package/src/utils/package-manager.mjs +1 -1
- package/templates/pages/documentation/page.tsx +39 -52
- package/templates/pages/documentation-design/page.tsx +80 -55
- package/templates/pages/documentation-technical/page.tsx +96 -54
- package/templates/pages/form-two-column/page.tsx +13 -30
- package/templates/pages/ide/page.tsx +167 -236
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,93 @@
|
|
|
1
1
|
# @xds/cli
|
|
2
2
|
|
|
3
|
+
# 0.1.0
|
|
4
|
+
|
|
5
|
+
#### Breaking Changes
|
|
6
|
+
|
|
7
|
+
- Read project config from `astryx.config.mjs` (was `xds.config.mjs`)
|
|
8
|
+
The CLI now resolves its optional project config from `astryx.config.mjs`
|
|
9
|
+
instead of `xds.config.mjs` — a hard cut, no fallback. Consumers with an
|
|
10
|
+
`xds.config.mjs` must rename it to `astryx.config.mjs` (the config shape and
|
|
11
|
+
all fields are unchanged). Part of removing `xds` naming from the public API.
|
|
12
|
+
- Rename the CLI command/bin from `xds` to `astryx`
|
|
13
|
+
The CLI binary is now `astryx` (was `xds`); `bin/xds.mjs` is renamed to
|
|
14
|
+
`bin/astryx.mjs`, the dual `xds`+`astryx` bin entries collapse to a single
|
|
15
|
+
`astryx`, and the program/manifest name is `astryx`. Invoke the CLI as
|
|
16
|
+
`npx astryx <command>` (e.g. `npx astryx component Button`). The swizzle
|
|
17
|
+
default output dir moves from `./components/xds` to `./components/astryx`.
|
|
18
|
+
Consumers using `npx xds`, an `xds` npm-script alias, or the `xds` MCP server
|
|
19
|
+
name should switch to `astryx`. Part of removing `xds` naming from the public API.
|
|
20
|
+
- Rename the exported `XDSError` class to `AstryxError`
|
|
21
|
+
The CLI's programmatic API error class is renamed `XDSError` -> `AstryxError`
|
|
22
|
+
(exported from `@xds/cli` + declared in its types). Consumers that catch or
|
|
23
|
+
reference `XDSError` from the CLI's API should switch to `AstryxError`. Part of
|
|
24
|
+
removing `xds` naming from the public API.
|
|
25
|
+
- Remove the XDS-prefix compatibility layer — astryx is now the only public surface
|
|
26
|
+
This release erases all `xds` naming from the public API; there is no compatibility
|
|
27
|
+
window. Consumers must migrate (we own all consumers pre-OSS):
|
|
28
|
+
- Remove the daily, brutalist, and default themes; neutral is the new baseline
|
|
29
|
+
Three theme packages are removed from the repo and will no longer be published:
|
|
30
|
+
|
|
31
|
+
#### Fixes
|
|
32
|
+
|
|
33
|
+
- `theme build` generates valid bare type imports (IconRegistry/DefinedTheme)
|
|
34
|
+
`astryx theme build` emitted `.d.ts` files importing `XDSIconRegistry` /
|
|
35
|
+
`XDSDefinedTheme` from `@xds/core`, but those aliases were removed — the
|
|
36
|
+
generated types failed to resolve. Generate `IconRegistry` / `DefinedTheme`
|
|
37
|
+
(the bare names `@xds/core` now exports) instead.
|
|
38
|
+
|
|
39
|
+
#### Documentation
|
|
40
|
+
|
|
41
|
+
- Update CLI theme docs to the current theme set
|
|
42
|
+
Refreshes the `astryx docs theme`, `getting-started`, `styling`,
|
|
43
|
+
`styling-libraries`, and `migration` reference docs to reflect the published
|
|
44
|
+
themes: `neutral`, `butter`, `chocolate`, `gothic`, `matcha`, `stone`, and
|
|
45
|
+
`y2k`. The removed `theme-default`, `theme-brutalist`, and `theme-daily`
|
|
46
|
+
packages are dropped from the docs, and install/import examples now use
|
|
47
|
+
`@astryxdesign/theme-neutral` as the recommended starting theme.
|
|
48
|
+
|
|
49
|
+
#### Other Changes
|
|
50
|
+
|
|
51
|
+
- **Component names:** the `XDS*` aliases are gone — use bare names (`Button` not
|
|
52
|
+
`XDSButton`, `useTheme` not `useXDSTheme`, `ButtonProps` not `XDSButtonProps`). The
|
|
53
|
+
`drop-xds-prefix-imports` codemod automates this.
|
|
54
|
+
- **CSS classes:** components emit only `.astryx-*` (the dual `.xds-*` class is gone).
|
|
55
|
+
Update custom CSS selectors `.xds-button` -> `.astryx-button` (prop/state value classes
|
|
56
|
+
like `.primary`/`.sm` are unchanged).
|
|
57
|
+
- **data attributes:** only `data-astryx-theme` / `data-astryx-media` are written; update
|
|
58
|
+
custom selectors and SSR root attributes off `data-xds-*`.
|
|
59
|
+
- **CSS layers:** `@layer xds-base` / `xds-theme` are renamed to `astryx-base` /
|
|
60
|
+
`astryx-theme`; update your `@layer` order line and any PostCSS `layersBefore` config.
|
|
61
|
+
`@astryxdesign/build`'s default library layer is now `astryx-base`.
|
|
62
|
+
- **Pre-compiled stylesheet:** the `@astryxdesign/core/xds.css` export is removed — import
|
|
63
|
+
`@astryxdesign/core/astryx.css`.
|
|
64
|
+
- **CSS custom properties:** the `--xds-*` padding fallback is gone; set `--astryx-*`.
|
|
65
|
+
- **CLI config key:** `@astryxdesign/cli` reads the package.json `"astryx"` field (was `"xds"`).
|
|
66
|
+
Rename the block; a stale `"xds"` key silently drops the package from discovery.
|
|
67
|
+
- `@astryxdesign/theme-daily`
|
|
68
|
+
- `@astryxdesign/theme-brutalist`
|
|
69
|
+
- `@astryxdesign/theme-default`
|
|
70
|
+
- import {defaultTheme} from '@astryxdesign/theme-default/built';
|
|
71
|
+
- import {neutralTheme} from '@astryxdesign/theme-neutral/built';
|
|
72
|
+
- <Theme theme={defaultTheme}>...</Theme>
|
|
73
|
+
- <Theme theme={neutralTheme}>...</Theme>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
- Remove the internal `drop-xds-meta-prefix` codemod from the OSS repo (#2970)
|
|
78
|
+
This codemod has been moved to its own package's tooling, where it belongs. It was registered as an optional, version-independent transform and is not part of any standard upgrade path, so removing it does not affect the public `0.0.13 → 0.0.15` migration.
|
|
79
|
+
- Rename the npm package scope from `@xds/*` to `@astryxdesign/*`
|
|
80
|
+
All published packages move to the new `@astryxdesign` scope (e.g. `@xds/core` → `@astryxdesign/core`), along with the workspace lockfile, build/runtime scope-directory scans, and docsite slug derivation. Consumers must update their imports and dependency names. The internal ESLint plugin namespace (`@xds/*` rules) is intentionally untouched and tracked separately. Existing `@xds/*` codemods continue to target the old scope so projects still on `@xds/*` can migrate.
|
|
81
|
+
|
|
82
|
+
#### Contributors
|
|
83
|
+
|
|
84
|
+
Thanks to everyone who contributed to this release:
|
|
85
|
+
|
|
86
|
+
- @cixzhang
|
|
87
|
+
- @ejhammond
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
3
91
|
# 0.0.15
|
|
4
92
|
|
|
5
93
|
#### Breaking Changes
|
package/README.md
CHANGED
|
@@ -341,7 +341,7 @@ astryx doctor — diagnosing your setup
|
|
|
341
341
|
@astryxdesign/core v0.0.14 is in step with @astryxdesign/cli v0.0.14.
|
|
342
342
|
⚠ Theme packages
|
|
343
343
|
No @astryxdesign/theme-* packages are installed.
|
|
344
|
-
→ fix: Install a theme, e.g. `npm install @astryxdesign/theme-
|
|
344
|
+
→ fix: Install a theme, e.g. `npm install @astryxdesign/theme-neutral`, then import its CSS or set xds.theme.
|
|
345
345
|
ℹ astryx.config.mjs
|
|
346
346
|
No astryx.config.mjs found — using defaults.
|
|
347
347
|
ℹ AI agent docs
|
|
@@ -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-
|
|
24
|
+
code: 'Install @astryxdesign/core, @astryxdesign/theme-neutral, and @astryxdesign/cli in this project. Run `npx astryx init` to set up agent docs. Read the generated files to learn the conventions.',
|
|
25
25
|
},
|
|
26
26
|
],
|
|
27
27
|
},
|
|
@@ -36,7 +36,7 @@ export const docs = {
|
|
|
36
36
|
type: 'code',
|
|
37
37
|
lang: 'bash',
|
|
38
38
|
label: 'Terminal',
|
|
39
|
-
code: `npm install @astryxdesign/core @astryxdesign/theme-
|
|
39
|
+
code: `npm install @astryxdesign/core @astryxdesign/theme-neutral @astryxdesign/cli`,
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
type: 'prose',
|
|
@@ -63,11 +63,11 @@ export const docs = {
|
|
|
63
63
|
label: 'globals.css',
|
|
64
64
|
code: `@import '@astryxdesign/core/reset.css';
|
|
65
65
|
@import '@astryxdesign/core/astryx.css';
|
|
66
|
-
@import '@astryxdesign/theme-
|
|
66
|
+
@import '@astryxdesign/theme-neutral/theme.css';`,
|
|
67
67
|
},
|
|
68
68
|
{
|
|
69
69
|
type: 'prose',
|
|
70
|
-
text: 'Available themes: @astryxdesign/theme-
|
|
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 `npx astryx docs theme` for the full theming guide.',
|
|
71
71
|
},
|
|
72
72
|
],
|
|
73
73
|
},
|
|
@@ -88,7 +88,7 @@ import {VStack} from '@astryxdesign/core/Layout';
|
|
|
88
88
|
export default function Page() {
|
|
89
89
|
return (
|
|
90
90
|
<VStack gap={2}>
|
|
91
|
-
<Button label="Hello
|
|
91
|
+
<Button label="Hello Astryx" onClick={() => alert('Hi!')} />
|
|
92
92
|
</VStack>
|
|
93
93
|
);
|
|
94
94
|
}`,
|
|
@@ -96,11 +96,11 @@ export default function Page() {
|
|
|
96
96
|
],
|
|
97
97
|
},
|
|
98
98
|
{
|
|
99
|
-
title: 'Customize with
|
|
99
|
+
title: 'Customize with StyleX',
|
|
100
100
|
content: [
|
|
101
101
|
{
|
|
102
102
|
type: 'prose',
|
|
103
|
-
text: '
|
|
103
|
+
text: 'Astryx components support various styling solutions, from plain CSS and `className` to Tailwind and CSS-in-JS. See the [styling docs](/docs/styling) for the full guide. Astryx also has a deep integration with [StyleX](https://stylexjs.com/), an atomic CSS-in-JS library: create styles with `stylex.create()` and pass them to components with the `xstyle` prop.',
|
|
104
104
|
},
|
|
105
105
|
{
|
|
106
106
|
type: 'code',
|
|
@@ -127,19 +127,19 @@ const overrides = stylex.create({
|
|
|
127
127
|
type: 'table',
|
|
128
128
|
headers: ['Example', 'Stack', 'Path'],
|
|
129
129
|
rows: [
|
|
130
|
-
['Next.js', 'Next.js + theme CSS', 'apps/example-nextjs'],
|
|
131
|
-
['Next.js + StyleX', 'Next.js + StyleX for custom styles', 'apps/example-nextjs-stylex'],
|
|
132
|
-
['Next.js + Tailwind', 'Next.js + Tailwind bridge', 'apps/example-nextjs-tailwind'],
|
|
133
|
-
['Next.js Source', 'Next.js importing from source', 'apps/example-nextjs-source'],
|
|
134
|
-
['Vite', 'Vite', 'apps/example-vite'],
|
|
130
|
+
['Next.js', 'Next.js + theme CSS', '[apps/example-nextjs](https://github.com/facebook/astryx/tree/main/apps/example-nextjs)'],
|
|
131
|
+
['Next.js + StyleX', 'Next.js + StyleX for custom styles', '[apps/example-nextjs-stylex](https://github.com/facebook/astryx/tree/main/apps/example-nextjs-stylex)'],
|
|
132
|
+
['Next.js + Tailwind', 'Next.js + Tailwind bridge', '[apps/example-nextjs-tailwind](https://github.com/facebook/astryx/tree/main/apps/example-nextjs-tailwind)'],
|
|
133
|
+
['Next.js Source', 'Next.js importing from source', '[apps/example-nextjs-source](https://github.com/facebook/astryx/tree/main/apps/example-nextjs-source)'],
|
|
134
|
+
['Vite', 'Vite', '[apps/example-vite](https://github.com/facebook/astryx/tree/main/apps/example-vite)'],
|
|
135
135
|
],
|
|
136
136
|
},
|
|
137
137
|
{
|
|
138
138
|
type: 'code',
|
|
139
139
|
lang: 'bash',
|
|
140
140
|
label: 'Clone and run an example',
|
|
141
|
-
code: `git clone https://github.com/
|
|
142
|
-
cd
|
|
141
|
+
code: `git clone https://github.com/facebook/astryx.git
|
|
142
|
+
cd astryx/apps/example-nextjs
|
|
143
143
|
pnpm install
|
|
144
144
|
pnpm dev`,
|
|
145
145
|
},
|
|
@@ -157,7 +157,7 @@ pnpm dev`,
|
|
|
157
157
|
lang: 'json',
|
|
158
158
|
label: 'package.json',
|
|
159
159
|
code: `"scripts": {
|
|
160
|
-
"
|
|
160
|
+
"astryx": "node node_modules/@astryxdesign/cli/bin/astryx.mjs"
|
|
161
161
|
}`,
|
|
162
162
|
},
|
|
163
163
|
{
|
package/docs/migration.doc.mjs
CHANGED
|
@@ -91,15 +91,15 @@ npx astryx component Button --json`,
|
|
|
91
91
|
lang: 'tsx',
|
|
92
92
|
label: 'Root provider with explicit mode',
|
|
93
93
|
code: `import {Theme} from '@astryxdesign/core/theme';
|
|
94
|
-
import {
|
|
94
|
+
import {neutralTheme} from '@astryxdesign/theme-neutral/built';
|
|
95
95
|
import {useState} from 'react';
|
|
96
|
-
import '@astryxdesign/theme-
|
|
96
|
+
import '@astryxdesign/theme-neutral/theme.css';
|
|
97
97
|
|
|
98
98
|
export function AppRoot({children}: {children: React.ReactNode}) {
|
|
99
99
|
const [mode, setMode] = useState<'system' | 'light' | 'dark'>('system');
|
|
100
100
|
|
|
101
101
|
return (
|
|
102
|
-
<Theme theme={
|
|
102
|
+
<Theme theme={neutralTheme} mode={mode}>
|
|
103
103
|
<SettingsContext.Provider value={{mode, setMode}}>
|
|
104
104
|
{children}
|
|
105
105
|
</SettingsContext.Provider>
|
|
@@ -121,7 +121,7 @@ export function AppRoot({children}: {children: React.ReactNode}) {
|
|
|
121
121
|
@import "tailwindcss/preflight.css" layer(base);
|
|
122
122
|
@import "@astryxdesign/core/reset.css";
|
|
123
123
|
@import "@astryxdesign/core/astryx.css";
|
|
124
|
-
@import "@astryxdesign/theme-
|
|
124
|
+
@import "@astryxdesign/theme-neutral/theme.css";
|
|
125
125
|
@import "@astryxdesign/core/tailwind-theme.css";
|
|
126
126
|
@import "tailwindcss/utilities.css" layer(utilities);`,
|
|
127
127
|
},
|
|
@@ -162,7 +162,7 @@ const styles = stylex.create({
|
|
|
162
162
|
@import "tailwindcss/preflight.css" layer(base);
|
|
163
163
|
@import "@astryxdesign/core/reset.css";
|
|
164
164
|
@import "@astryxdesign/core/astryx.css";
|
|
165
|
-
@import "@astryxdesign/theme-
|
|
165
|
+
@import "@astryxdesign/theme-neutral/theme.css";
|
|
166
166
|
@import "@astryxdesign/core/tailwind-theme.css";
|
|
167
167
|
@import "tailwindcss/utilities.css" layer(utilities);`,
|
|
168
168
|
},
|
|
@@ -374,9 +374,9 @@ tokens: {
|
|
|
374
374
|
lang: 'ts',
|
|
375
375
|
label: 'Resolve tokens without React context',
|
|
376
376
|
code: `import {resolveThemeTokens} from '@astryxdesign/core/theme/tokens';
|
|
377
|
-
import {
|
|
377
|
+
import {neutralTheme} from '@astryxdesign/theme-neutral';
|
|
378
378
|
|
|
379
|
-
const tokens = resolveThemeTokens(
|
|
379
|
+
const tokens = resolveThemeTokens(neutralTheme, {mode: 'light'});
|
|
380
380
|
|
|
381
381
|
const chartOptions = {
|
|
382
382
|
textColor: tokens['--color-text-primary'],
|
package/docs/styling.doc.mjs
CHANGED
|
@@ -22,9 +22,8 @@ export const docs = {
|
|
|
22
22
|
type: 'table',
|
|
23
23
|
headers: ['Approach', 'Use for', 'Example'],
|
|
24
24
|
rows: [
|
|
25
|
-
['
|
|
25
|
+
['StyleX', 'Component-specific overrides, reusable styles, pseudo-classes, and typed tokens', 'const styles = stylex.create(...); <Button xstyle={styles.save} />'],
|
|
26
26
|
['Tailwind utilities', 'Layout, wrappers, and utility styling', 'className="flex gap-3 p-4"'],
|
|
27
|
-
['stylex.create', 'Reusable styles, pseudo-classes, typed tokens', 'stylex.create({ card: { ... } })'],
|
|
28
27
|
['className', 'Integrating with external CSS or Tailwind on components', 'className="my-card shadow-lg"'],
|
|
29
28
|
['Styling-library token aliases', 'Keeping Panda, Chakra, MUI, Emotion, styled-components, UnoCSS, CSS Modules, or Sass in sync with the system', "colors.surface = 'var(--color-background-surface)'"],
|
|
30
29
|
],
|
|
@@ -104,7 +103,7 @@ const overrides = stylex.create({
|
|
|
104
103
|
@import "tailwindcss/preflight.css" layer(base);
|
|
105
104
|
@import "@astryxdesign/core/reset.css";
|
|
106
105
|
@import "@astryxdesign/core/astryx.css";
|
|
107
|
-
@import "@astryxdesign/theme-
|
|
106
|
+
@import "@astryxdesign/theme-neutral/theme.css";
|
|
108
107
|
@import "@astryxdesign/core/tailwind-theme.css";
|
|
109
108
|
@import "tailwindcss/utilities.css" layer(utilities);`,
|
|
110
109
|
},
|
package/docs/theme.doc.dense.mjs
CHANGED
|
@@ -6,7 +6,7 @@ export const docsDense = {
|
|
|
6
6
|
description: 'Theme provider, custom themes, light/dark, component overrides',
|
|
7
7
|
sections: [
|
|
8
8
|
{ title: 'Quick Start', content: [null, null, { type: 'prose', text: 'default import = runtime injection. /built import = pre-compiled CSS (pair with theme.css).' }] },
|
|
9
|
-
{ title: 'Themes', content: [null, { type: 'prose', text: '@astryxdesign/theme-{name} = source (runtime). @astryxdesign/theme-{name}/built = optimized (+ theme.css).' }] },
|
|
9
|
+
{ title: 'Themes', content: [null, { type: 'prose', text: 'published: neutral (start here), butter, chocolate, gothic (dark-only), matcha, stone, y2k. @astryxdesign/theme-{name} = source (runtime). @astryxdesign/theme-{name}/built = optimized (+ theme.css).' }] },
|
|
10
10
|
{ title: 'Props', content: [null] },
|
|
11
11
|
{ title: 'Custom Theme', content: [{ type: 'prose', text: 'CLI wizard or manual defineTheme. only override tokens that differ.' }, null] },
|
|
12
12
|
{ 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] },
|
package/docs/theme.doc.mjs
CHANGED
|
@@ -19,11 +19,11 @@ export const docs = {
|
|
|
19
19
|
lang: 'tsx',
|
|
20
20
|
label: 'Basic theme setup (runtime injection)',
|
|
21
21
|
code: `import {Theme} from '@astryxdesign/core';
|
|
22
|
-
import {
|
|
22
|
+
import {neutralTheme} from '@astryxdesign/theme-neutral';
|
|
23
23
|
|
|
24
24
|
function App() {
|
|
25
25
|
return (
|
|
26
|
-
<Theme theme={
|
|
26
|
+
<Theme theme={neutralTheme}>
|
|
27
27
|
<YourApp />
|
|
28
28
|
</Theme>
|
|
29
29
|
);
|
|
@@ -34,12 +34,12 @@ function App() {
|
|
|
34
34
|
lang: 'tsx',
|
|
35
35
|
label: 'Optimized setup (pre-built CSS)',
|
|
36
36
|
code: `import {Theme} from '@astryxdesign/core';
|
|
37
|
-
import {
|
|
38
|
-
import '@astryxdesign/theme-
|
|
37
|
+
import {neutralTheme} from '@astryxdesign/theme-neutral/built';
|
|
38
|
+
import '@astryxdesign/theme-neutral/theme.css';
|
|
39
39
|
|
|
40
40
|
function App() {
|
|
41
41
|
return (
|
|
42
|
-
<Theme theme={
|
|
42
|
+
<Theme theme={neutralTheme}>
|
|
43
43
|
<YourApp />
|
|
44
44
|
</Theme>
|
|
45
45
|
);
|
|
@@ -59,20 +59,40 @@ function App() {
|
|
|
59
59
|
type: 'table',
|
|
60
60
|
headers: ['Theme', 'Import', 'Description'],
|
|
61
61
|
rows: [
|
|
62
|
-
[
|
|
63
|
-
'Default',
|
|
64
|
-
"import {defaultTheme} from '@astryxdesign/theme-default'",
|
|
65
|
-
'Blue accent, system fonts, light/dark',
|
|
66
|
-
],
|
|
67
62
|
[
|
|
68
63
|
'Neutral',
|
|
69
64
|
"import {neutralTheme} from '@astryxdesign/theme-neutral'",
|
|
70
|
-
'
|
|
65
|
+
'Muted, minimal aesthetic with system fonts. A good starting point.',
|
|
66
|
+
],
|
|
67
|
+
[
|
|
68
|
+
'Butter',
|
|
69
|
+
"import {butterTheme} from '@astryxdesign/theme-butter'",
|
|
70
|
+
'Golden, buttery surfaces with blue accents; Sarina + Outfit type.',
|
|
71
|
+
],
|
|
72
|
+
[
|
|
73
|
+
'Chocolate',
|
|
74
|
+
"import {chocolateTheme} from '@astryxdesign/theme-chocolate'",
|
|
75
|
+
'Warm brown tones and cozy beige; Fraunces + Albert Sans type.',
|
|
76
|
+
],
|
|
77
|
+
[
|
|
78
|
+
'Gothic',
|
|
79
|
+
"import {gothicTheme} from '@astryxdesign/theme-gothic'",
|
|
80
|
+
'Dark-only atmospheric theme; deep blue-gray surfaces, distressed display type.',
|
|
81
|
+
],
|
|
82
|
+
[
|
|
83
|
+
'Matcha',
|
|
84
|
+
"import {matchaTheme} from '@astryxdesign/theme-matcha'",
|
|
85
|
+
'Earthy green theme with Figtree typography.',
|
|
86
|
+
],
|
|
87
|
+
[
|
|
88
|
+
'Stone',
|
|
89
|
+
"import {stoneTheme} from '@astryxdesign/theme-stone'",
|
|
90
|
+
'Warm stone and slate tones; Montserrat + Figtree type.',
|
|
71
91
|
],
|
|
72
92
|
[
|
|
73
|
-
'
|
|
74
|
-
"import {
|
|
75
|
-
'
|
|
93
|
+
'Y2K',
|
|
94
|
+
"import {y2kTheme} from '@astryxdesign/theme-y2k'",
|
|
95
|
+
'Playful Y2K pop; periwinkle body, holographic accents, Poppins + Crimson Text.',
|
|
76
96
|
],
|
|
77
97
|
],
|
|
78
98
|
},
|
|
@@ -194,14 +214,14 @@ const myTheme = defineTheme({
|
|
|
194
214
|
{
|
|
195
215
|
type: 'code',
|
|
196
216
|
lang: 'tsx',
|
|
197
|
-
label: 'Extending the
|
|
217
|
+
label: 'Extending the neutral theme',
|
|
198
218
|
code: `import {defineTheme} from '@astryxdesign/core/theme';
|
|
199
|
-
import {
|
|
219
|
+
import {neutralTheme} from '@astryxdesign/theme-neutral';
|
|
200
220
|
import {myIcons} from './icons';
|
|
201
221
|
|
|
202
222
|
const brandTheme = defineTheme({
|
|
203
223
|
name: 'brand',
|
|
204
|
-
extends:
|
|
224
|
+
extends: neutralTheme,
|
|
205
225
|
icons: myIcons,
|
|
206
226
|
tokens: {
|
|
207
227
|
'--color-accent': ['#7B61FF', '#9B85FF'],
|
|
@@ -525,9 +545,9 @@ const pandaOrEmotionTheme = {
|
|
|
525
545
|
lang: 'ts',
|
|
526
546
|
label: 'Resolve token values without a hook',
|
|
527
547
|
code: `import {resolveThemeTokens} from '@astryxdesign/core/theme/tokens';
|
|
528
|
-
import {
|
|
548
|
+
import {neutralTheme} from '@astryxdesign/theme-neutral';
|
|
529
549
|
|
|
530
|
-
const lightTokens = resolveThemeTokens(
|
|
550
|
+
const lightTokens = resolveThemeTokens(neutralTheme, {mode: 'light'});
|
|
531
551
|
const chartTheme = {
|
|
532
552
|
textColor: lightTokens['--color-text-primary'],
|
|
533
553
|
seriesColor: lightTokens['--color-data-categorical-blue'],
|
package/docs/theme.doc.zh.mjs
CHANGED
|
@@ -6,7 +6,7 @@ export const docsZh = {
|
|
|
6
6
|
description: 'Theme 提供者、自定义主题、亮/暗模式和组件样式覆盖。',
|
|
7
7
|
sections: [
|
|
8
8
|
{ title: '快速开始', content: [null, null, { type: 'prose', text: '默认导入使用运行时样式注入。/built 导入使用预编译 CSS(需配合 theme.css)。' }] },
|
|
9
|
-
{ title: '可用主题', content: [null, { type: 'prose', text: '
|
|
9
|
+
{ title: '可用主题', content: [null, { type: 'prose', text: '已发布主题:neutral(推荐起点)、butter、chocolate、gothic(仅暗色)、matcha、stone、y2k。@astryxdesign/theme-{name} = 源码版(运行时注入)。@astryxdesign/theme-{name}/built = 优化版(配合 theme.css)。' }] },
|
|
10
10
|
{ title: 'Theme 属性', content: [null] },
|
|
11
11
|
{ title: '创建自定义主题', content: [{ type: 'prose', text: '使用 CLI 向导(推荐)或手动 defineTheme。只覆盖与默认值不同的令牌。' }, null] },
|
|
12
12
|
{ title: 'defineTheme', content: [{ type: 'prose', text: '支持比例配置(typography、radius、motion)+ 显式令牌覆盖 + 组件覆盖。' }, null, null] },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.1.0-canary.0b5b49f",
|
|
4
4
|
"displayName": "CLI",
|
|
5
5
|
"description": "Scaffold projects, browse templates, generate themes, and get agent-ready docs from the command line.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -50,13 +50,13 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@clack/prompts": "^1.5.1",
|
|
52
52
|
"commander": "^12.1.0",
|
|
53
|
-
"jiti": "^2.7.0"
|
|
53
|
+
"jiti": "^2.7.0",
|
|
54
|
+
"jscodeshift": "^17.3.0"
|
|
54
55
|
},
|
|
55
56
|
"peerDependencies": {
|
|
56
|
-
"@astryxdesign/core": "
|
|
57
|
-
"@astryxdesign/lab": "
|
|
58
|
-
"@astryxdesign/theme-
|
|
59
|
-
"@astryxdesign/theme-neutral": "*"
|
|
57
|
+
"@astryxdesign/core": "0.1.0-canary.0b5b49f",
|
|
58
|
+
"@astryxdesign/lab": "0.1.0-canary.0b5b49f",
|
|
59
|
+
"@astryxdesign/theme-neutral": "0.1.0-canary.0b5b49f"
|
|
60
60
|
},
|
|
61
61
|
"peerDependenciesMeta": {
|
|
62
62
|
"@astryxdesign/core": {
|
|
@@ -65,18 +65,14 @@
|
|
|
65
65
|
"@astryxdesign/lab": {
|
|
66
66
|
"optional": true
|
|
67
67
|
},
|
|
68
|
-
"@astryxdesign/theme-default": {
|
|
69
|
-
"optional": true
|
|
70
|
-
},
|
|
71
68
|
"@astryxdesign/theme-neutral": {
|
|
72
69
|
"optional": true
|
|
73
70
|
}
|
|
74
71
|
},
|
|
75
72
|
"devDependencies": {
|
|
76
|
-
"@astryxdesign/core": "
|
|
77
|
-
"@astryxdesign/lab": "
|
|
78
|
-
"@astryxdesign/theme-
|
|
79
|
-
"@astryxdesign/theme-neutral": "*"
|
|
73
|
+
"@astryxdesign/core": "0.1.0-canary.0b5b49f",
|
|
74
|
+
"@astryxdesign/lab": "0.1.0-canary.0b5b49f",
|
|
75
|
+
"@astryxdesign/theme-neutral": "0.1.0-canary.0b5b49f"
|
|
80
76
|
},
|
|
81
77
|
"scripts": {
|
|
82
78
|
"astryx": "node bin/astryx.mjs",
|
package/src/api/doctor.mjs
CHANGED
|
@@ -240,7 +240,7 @@ export function checkThemes(ctx) {
|
|
|
240
240
|
label: 'Theme packages',
|
|
241
241
|
status: 'warn',
|
|
242
242
|
message: 'No @astryxdesign/theme-* packages are installed.',
|
|
243
|
-
fix: 'Install a theme, e.g. `npm install @astryxdesign/theme-
|
|
243
|
+
fix: 'Install a theme, e.g. `npm install @astryxdesign/theme-neutral`, then import its CSS or set xds.theme.',
|
|
244
244
|
};
|
|
245
245
|
}
|
|
246
246
|
|
|
@@ -355,8 +355,8 @@ export function checkAgentDocs(ctx) {
|
|
|
355
355
|
try {
|
|
356
356
|
const content = fs.readFileSync(path.join(ctx.cwd, rel), 'utf-8');
|
|
357
357
|
return (
|
|
358
|
-
content.includes('<!-- XDS:START -->') &&
|
|
359
|
-
content.includes('<!-- XDS:END -->')
|
|
358
|
+
(content.includes('<!-- ASTRYX:START -->') || content.includes('<!-- XDS:START -->')) &&
|
|
359
|
+
(content.includes('<!-- ASTRYX:END -->') || content.includes('<!-- XDS:END -->'))
|
|
360
360
|
);
|
|
361
361
|
} catch {
|
|
362
362
|
return false;
|
|
@@ -368,7 +368,7 @@ export function checkAgentDocs(ctx) {
|
|
|
368
368
|
id: 'agent-docs',
|
|
369
369
|
label: 'AI agent docs',
|
|
370
370
|
status: 'warn',
|
|
371
|
-
message: `Agent docs present (${present.join(', ')}) but no
|
|
371
|
+
message: `Agent docs present (${present.join(', ')}) but no Astryx section markers found.`,
|
|
372
372
|
fix: 'Add the XDS section to your agent docs with `astryx init --features agents`.',
|
|
373
373
|
};
|
|
374
374
|
}
|
|
@@ -31,8 +31,11 @@ const AGENTS_MD = 'AGENTS.md';
|
|
|
31
31
|
const CLAUDE_MD = 'CLAUDE.md';
|
|
32
32
|
const CLAUDE_DIR_MD = path.join('.claude', 'CLAUDE.md');
|
|
33
33
|
|
|
34
|
-
const
|
|
35
|
-
const
|
|
34
|
+
const MARKER_START = '<!-- ASTRYX:START -->';
|
|
35
|
+
const MARKER_END = '<!-- ASTRYX:END -->';
|
|
36
|
+
// Legacy markers — read during migration so the script finds existing XDS blocks
|
|
37
|
+
const LEGACY_MARKER_START = '<!-- XDS:START -->';
|
|
38
|
+
const LEGACY_MARKER_END = '<!-- XDS:END -->';
|
|
36
39
|
|
|
37
40
|
/**
|
|
38
41
|
* Agent tool presets — maps tool names to their file search paths.
|
|
@@ -99,7 +102,7 @@ export function resolveAgentPaths(targetDir, agent) {
|
|
|
99
102
|
*/
|
|
100
103
|
export function generateCompressedIndex(version, {coreDir, runPrefix = getRunPrefix()} = {}) {
|
|
101
104
|
const run = `${runPrefix} astryx`;
|
|
102
|
-
const lines = [
|
|
105
|
+
const lines = [MARKER_START];
|
|
103
106
|
|
|
104
107
|
// Component count from live discovery
|
|
105
108
|
let componentCount = '90+';
|
|
@@ -177,7 +180,7 @@ export function generateCompressedIndex(version, {coreDir, runPrefix = getRunPre
|
|
|
177
180
|
lines.push(`${run} swizzle <Name> eject source (--gap to report why)`);
|
|
178
181
|
lines.push(`${run} upgrade --apply codemods after version bump`);
|
|
179
182
|
lines.push(`after @astryxdesign/core bump, always run ${run} upgrade --apply`);
|
|
180
|
-
lines.push(
|
|
183
|
+
lines.push(MARKER_END);
|
|
181
184
|
|
|
182
185
|
return lines.join('\n');
|
|
183
186
|
}
|
|
@@ -218,14 +221,21 @@ export function injectXdsBlock(filePath, compressedIndex, {createIfMissing = fal
|
|
|
218
221
|
if (fs.existsSync(filePath)) {
|
|
219
222
|
content = fs.readFileSync(filePath, 'utf-8');
|
|
220
223
|
|
|
221
|
-
|
|
222
|
-
|
|
224
|
+
// Find existing section — try new markers first, fall back to legacy XDS markers
|
|
225
|
+
let startIdx = content.indexOf(MARKER_START);
|
|
226
|
+
let endIdx = content.indexOf(MARKER_END);
|
|
227
|
+
let markerEndLength = MARKER_END.length;
|
|
228
|
+
if (startIdx === -1) {
|
|
229
|
+
startIdx = content.indexOf(LEGACY_MARKER_START);
|
|
230
|
+
endIdx = content.indexOf(LEGACY_MARKER_END);
|
|
231
|
+
markerEndLength = LEGACY_MARKER_END.length;
|
|
232
|
+
}
|
|
223
233
|
|
|
224
234
|
if (startIdx !== -1 && endIdx !== -1) {
|
|
225
235
|
content =
|
|
226
236
|
content.slice(0, startIdx) +
|
|
227
237
|
compressedIndex +
|
|
228
|
-
content.slice(endIdx +
|
|
238
|
+
content.slice(endIdx + markerEndLength);
|
|
229
239
|
} else if (onlyReplace) {
|
|
230
240
|
// File exists but has no Astryx markers — skip it
|
|
231
241
|
return false;
|
|
@@ -277,13 +287,20 @@ export function removeXdsBlock(filePath, {deleteIfEmpty = false} = {}) {
|
|
|
277
287
|
if (!fs.existsSync(filePath)) return false;
|
|
278
288
|
|
|
279
289
|
let content = fs.readFileSync(filePath, 'utf-8');
|
|
280
|
-
|
|
281
|
-
|
|
290
|
+
// Find existing section — try new markers first, fall back to legacy
|
|
291
|
+
let startIdx = content.indexOf(MARKER_START);
|
|
292
|
+
let endIdx = content.indexOf(MARKER_END);
|
|
293
|
+
let markerEndLen = MARKER_END.length;
|
|
294
|
+
if (startIdx === -1) {
|
|
295
|
+
startIdx = content.indexOf(LEGACY_MARKER_START);
|
|
296
|
+
endIdx = content.indexOf(LEGACY_MARKER_END);
|
|
297
|
+
markerEndLen = LEGACY_MARKER_END.length;
|
|
298
|
+
}
|
|
282
299
|
|
|
283
300
|
if (startIdx === -1 || endIdx === -1) return false;
|
|
284
301
|
|
|
285
302
|
const before = content.slice(0, startIdx).trimEnd();
|
|
286
|
-
const after = content.slice(endIdx +
|
|
303
|
+
const after = content.slice(endIdx + markerEndLen).trimStart();
|
|
287
304
|
content = before + (after ? '\n\n' + after : '') + '\n';
|
|
288
305
|
|
|
289
306
|
if (deleteIfEmpty) {
|