@utopia-studio-design/design-system-cli 0.3.4 → 0.4.0
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/README.md +1 -1
- package/bin/utopia-ds.mjs +25 -2
- package/data/docs/foundations.md +28 -0
- package/data/docs/guide.md +22 -0
- package/data/docs/quick-start-ai.md +2 -2
- package/data/manifests/catalog.json +9 -0
- package/data/manifests/components.json +72 -3
- package/lib/api.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ The same structured API powers terminal output, JSON automation, generated agent
|
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
6
|
npm install -D @utopia-studio-design/design-system-cli
|
|
7
|
-
npx utopia-ds init
|
|
7
|
+
npx utopia-ds init . --theme utopia-default --yes
|
|
8
8
|
npx utopia-ds search "Arabic data table" --json
|
|
9
9
|
npx utopia-ds component DataTable --json
|
|
10
10
|
npx utopia-ds template template-saas-solution-homepage --copy ./saas-website
|
package/bin/utopia-ds.mjs
CHANGED
|
@@ -11,10 +11,24 @@ import { createTemplateSubmissionUrl, validateTemplateSubmission } from '../lib/
|
|
|
11
11
|
const args = process.argv.slice(2)
|
|
12
12
|
const command = args.find((arg) => !arg.startsWith('--')) ?? 'help'
|
|
13
13
|
const commandIndex = args.indexOf(command)
|
|
14
|
-
const
|
|
14
|
+
const optionsWithValues = new Set(['--copy', '--theme'])
|
|
15
|
+
const values = commandIndex >= 0 ? positionalValues(args.slice(commandIndex + 1)) : []
|
|
15
16
|
const json = args.includes('--json')
|
|
16
17
|
const dense = args.includes('--dense')
|
|
17
18
|
|
|
19
|
+
function positionalValues(input) {
|
|
20
|
+
const positionals = []
|
|
21
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
22
|
+
const argument = input[index]
|
|
23
|
+
if (optionsWithValues.has(argument)) {
|
|
24
|
+
index += 1
|
|
25
|
+
continue
|
|
26
|
+
}
|
|
27
|
+
if (!argument.startsWith('--')) positionals.push(argument)
|
|
28
|
+
}
|
|
29
|
+
return positionals
|
|
30
|
+
}
|
|
31
|
+
|
|
18
32
|
function output(type, data, format = null) {
|
|
19
33
|
if (json) return console.log(JSON.stringify(envelope(type, data), null, 2))
|
|
20
34
|
if (format) return console.log(format(data, dense))
|
|
@@ -29,7 +43,13 @@ function fail(message, code = 'ERR_INPUT', suggestions = []) {
|
|
|
29
43
|
|
|
30
44
|
function argAfter(flag, fallback) {
|
|
31
45
|
const index = args.indexOf(flag)
|
|
32
|
-
|
|
46
|
+
if (index < 0) return fallback
|
|
47
|
+
const value = args[index + 1]
|
|
48
|
+
if (!value || value.startsWith('--')) {
|
|
49
|
+
fail(`${flag} requires a value.`, 'ERR_ARGUMENT')
|
|
50
|
+
return null
|
|
51
|
+
}
|
|
52
|
+
return value
|
|
33
53
|
}
|
|
34
54
|
|
|
35
55
|
function help() {
|
|
@@ -150,6 +170,7 @@ function scaffoldTheme() {
|
|
|
150
170
|
function init() {
|
|
151
171
|
const target = resolve(values[0] ?? process.cwd())
|
|
152
172
|
const theme = argAfter('--theme', 'utopia-default')
|
|
173
|
+
if (!theme) return
|
|
153
174
|
if (!getTheme(theme)) return fail(`Unknown theme "${theme}".`, 'ERR_THEME', listThemes().map((item) => item.id))
|
|
154
175
|
const pkgPath = join(target, 'package.json')
|
|
155
176
|
if (!existsSync(pkgPath)) return fail(`No package.json found in ${target}.`, 'ERR_PROJECT')
|
|
@@ -186,8 +207,10 @@ function runMcp() {
|
|
|
186
207
|
function copyTemplateProject(entry) {
|
|
187
208
|
if (!entry.bundlePath) return fail(`Template "${entry.id}" is a blueprint contract and has no runnable bundle.`, 'ERR_TEMPLATE_BUNDLE')
|
|
188
209
|
const requestedTarget = argAfter('--copy', entry.id.replace(/^template-/, ''))
|
|
210
|
+
if (!requestedTarget) return
|
|
189
211
|
const target = resolve(requestedTarget)
|
|
190
212
|
const theme = argAfter('--theme', 'utopia-default')
|
|
213
|
+
if (!theme) return
|
|
191
214
|
if (!getTheme(theme)) return fail(`Unknown theme "${theme}".`, 'ERR_THEME', listThemes().map((item) => item.id))
|
|
192
215
|
if (existsSync(target) && !args.includes('--force')) return fail(`Target already exists: ${target}. Pass --force to overwrite it.`, 'ERR_TARGET_EXISTS')
|
|
193
216
|
const source = resolve(dirname(new URL(import.meta.url).pathname), '..', 'data', entry.bundlePath)
|
package/data/docs/foundations.md
CHANGED
|
@@ -121,9 +121,37 @@ The engine-neutral registry is published as `manifests/motion-profiles.json`. It
|
|
|
121
121
|
- Core owns icon slots, icon-only controls, labels, and accessibility.
|
|
122
122
|
- Theme manifests own icon philosophy and icon style.
|
|
123
123
|
- Use `lucide-react` as the default shadcn/ui icon baseline for examples and previews.
|
|
124
|
+
- Use `PhosphorIcon` when a product selects the Phosphor family. Import individual
|
|
125
|
+
`*Icon` exports from `@phosphor-icons/react` so bundlers can tree-shake unused icons.
|
|
126
|
+
- `PhosphorIcon` uses `currentColor` and `--icon-size-xs|sm|md`; do not pass raw
|
|
127
|
+
color or pixel sizes.
|
|
128
|
+
- Mark visual-only icons with `decorative`. Give meaningful standalone icons a
|
|
129
|
+
localized `label`. Put interactive icons inside `IconButton` and label the button.
|
|
124
130
|
- Mirror arrows and chevrons when they mean previous/next, open/close, or inline movement.
|
|
125
131
|
- Do not mirror direction-neutral icons such as settings, add, download, home, camera, or panel icons unless a theme says otherwise.
|
|
126
132
|
|
|
133
|
+
```tsx
|
|
134
|
+
import { ArrowRightIcon, HouseIcon } from '@phosphor-icons/react'
|
|
135
|
+
import { PhosphorIcon } from '@utopia-studio-design/design-system/PhosphorIcon'
|
|
136
|
+
|
|
137
|
+
export function IconExamples() {
|
|
138
|
+
return (
|
|
139
|
+
<>
|
|
140
|
+
<PhosphorIcon decorative icon={HouseIcon} size="sm" />
|
|
141
|
+
<PhosphorIcon
|
|
142
|
+
direction="directional"
|
|
143
|
+
icon={ArrowRightIcon}
|
|
144
|
+
label="Continue"
|
|
145
|
+
/>
|
|
146
|
+
</>
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Phosphor is an additional supported family, not a silent replacement for
|
|
152
|
+
Lucide-based component internals. Breadcrumb separators and existing Ceramic
|
|
153
|
+
navigation defaults keep their documented icon contracts.
|
|
154
|
+
|
|
127
155
|
## Illustration Contract
|
|
128
156
|
|
|
129
157
|
- Illustrations are theme and product media, not core component requirements.
|
package/data/docs/guide.md
CHANGED
|
@@ -87,6 +87,28 @@ import {
|
|
|
87
87
|
- `BreadcrumbSeparator` provides an RTL-aware Lucide `ChevronRight` by default. Breadcrumb does not add a home icon.
|
|
88
88
|
- Breadcrumb links own their no-underline treatment and compact typography, so consumer-level anchor styles do not require an override.
|
|
89
89
|
|
|
90
|
+
## Phosphor Icon Composition
|
|
91
|
+
|
|
92
|
+
Phosphor is an optional supported icon family. It does not replace Lucide-based
|
|
93
|
+
defaults inside existing Ceramic components.
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
import { GearIcon } from '@phosphor-icons/react'
|
|
97
|
+
import { IconButton } from '@utopia-studio-design/design-system/IconButton'
|
|
98
|
+
import { PhosphorIcon } from '@utopia-studio-design/design-system/PhosphorIcon'
|
|
99
|
+
|
|
100
|
+
<IconButton label="Settings">
|
|
101
|
+
<PhosphorIcon decorative icon={GearIcon} size="sm" />
|
|
102
|
+
</IconButton>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
- Install `@phosphor-icons/react` in an application that imports Phosphor icons directly.
|
|
106
|
+
- Import named `*Icon` exports so unused icons can be removed from the bundle.
|
|
107
|
+
- Use `decorative` when the surrounding control or text already supplies the accessible name.
|
|
108
|
+
- Use `label` for a meaningful standalone icon.
|
|
109
|
+
- Set `direction="directional"` only for arrows, chevrons, and other meanings that follow reading direction.
|
|
110
|
+
- Keep color inherited and select `xs`, `sm`, or `md`; do not pass raw color or pixel size values.
|
|
111
|
+
|
|
90
112
|
## AI Rule
|
|
91
113
|
|
|
92
114
|
Before generating UI, read:
|
|
@@ -5,7 +5,7 @@ Ceramic follows the Astryx principle that humans, coding agents, build tools, an
|
|
|
5
5
|
## Paste This Into Your AI
|
|
6
6
|
|
|
7
7
|
```text
|
|
8
|
-
Install @utopia-studio-design/design-system and @utopia-studio-design/design-system-cli. Run `npx utopia-ds init --theme utopia-default`. Read the generated AGENTS.md and active theme config. Before editing UI, run `npx utopia-ds manifest --json`, search for the intended pattern, inspect its component or template contract, and read the Arabic-friendly guide when the product supports Arabic or RTL. Do not invent props, imports, tokens, or localized copy.
|
|
8
|
+
Install @utopia-studio-design/design-system and @utopia-studio-design/design-system-cli. Run `npx utopia-ds init . --theme utopia-default --yes`. Read the generated AGENTS.md and active theme config. Before editing UI, run `npx utopia-ds manifest --json`, search for the intended pattern, inspect its component or template contract, and read the Arabic-friendly guide when the product supports Arabic or RTL. Do not invent props, imports, tokens, or localized copy.
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Install
|
|
@@ -13,7 +13,7 @@ Install @utopia-studio-design/design-system and @utopia-studio-design/design-sys
|
|
|
13
13
|
```sh
|
|
14
14
|
npm install @utopia-studio-design/design-system
|
|
15
15
|
npm install -D @utopia-studio-design/design-system-cli
|
|
16
|
-
npx utopia-ds init --theme utopia-default
|
|
16
|
+
npx utopia-ds init . --theme utopia-default --yes
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
The init command creates:
|
|
@@ -177,6 +177,13 @@
|
|
|
177
177
|
"Separator"
|
|
178
178
|
]
|
|
179
179
|
},
|
|
180
|
+
{
|
|
181
|
+
"id": "utilities",
|
|
182
|
+
"label": "Utilities",
|
|
183
|
+
"items": [
|
|
184
|
+
"Phosphor Icon"
|
|
185
|
+
]
|
|
186
|
+
},
|
|
180
187
|
{
|
|
181
188
|
"id": "data",
|
|
182
189
|
"label": "Data Display",
|
|
@@ -293,6 +300,7 @@
|
|
|
293
300
|
"Native Select",
|
|
294
301
|
"Navigation Menu",
|
|
295
302
|
"Pagination",
|
|
303
|
+
"Phosphor Icon",
|
|
296
304
|
"Popover",
|
|
297
305
|
"Progress",
|
|
298
306
|
"Radio Group",
|
|
@@ -373,6 +381,7 @@
|
|
|
373
381
|
"Native Select",
|
|
374
382
|
"Navigation Menu",
|
|
375
383
|
"Pagination",
|
|
384
|
+
"Phosphor Icon",
|
|
376
385
|
"Popover",
|
|
377
386
|
"Progress",
|
|
378
387
|
"Radio Group",
|
|
@@ -2319,7 +2319,8 @@
|
|
|
2319
2319
|
"useWhen": [
|
|
2320
2320
|
"Structured tabular data with headers and comparable rows",
|
|
2321
2321
|
"AI-generated admin/product views that need accessible table semantics",
|
|
2322
|
-
"Arabic-friendly data displays that must preserve table meaning in dir='rtl'"
|
|
2322
|
+
"Arabic-friendly data displays that must preserve table meaning in dir='rtl'",
|
|
2323
|
+
"Responsive dashboards where wide tables must scroll inside the component instead of expanding the page"
|
|
2323
2324
|
],
|
|
2324
2325
|
"avoidWhen": [
|
|
2325
2326
|
"Card lists are easier to scan",
|
|
@@ -2330,7 +2331,14 @@
|
|
|
2330
2331
|
"Raw shadcn theme colors",
|
|
2331
2332
|
"Left/right-only layout rules",
|
|
2332
2333
|
"Utopia brand primitives inside reusable component logic"
|
|
2333
|
-
]
|
|
2334
|
+
],
|
|
2335
|
+
"ai": {
|
|
2336
|
+
"props": {
|
|
2337
|
+
"DataTableShell": "Full-width bounded shell with min-inline-size: 0 and component-owned horizontal scrolling. Place DataTableToolbar, DataTable, and DataTableFooter inside it.",
|
|
2338
|
+
"DataTable": "Semantic table content may exceed the available inline size; its nearest DataTableShell owns horizontal overflow."
|
|
2339
|
+
},
|
|
2340
|
+
"responsive": "Keep DataTableShell inside a min-inline-size: 0 grid or flex child. The shell prevents intrinsic table width from creating page-level horizontal scrolling."
|
|
2341
|
+
}
|
|
2334
2342
|
},
|
|
2335
2343
|
{
|
|
2336
2344
|
"name": "Date Picker",
|
|
@@ -2796,6 +2804,65 @@
|
|
|
2796
2804
|
]
|
|
2797
2805
|
}
|
|
2798
2806
|
},
|
|
2807
|
+
{
|
|
2808
|
+
"name": "Phosphor Icon",
|
|
2809
|
+
"category": "Utilities",
|
|
2810
|
+
"status": "available",
|
|
2811
|
+
"packageImport": "import { PhosphorIcon } from '@utopia-studio-design/design-system/PhosphorIcon';",
|
|
2812
|
+
"sourcePath": "packages/design-system/src/components/PhosphorIcon.tsx",
|
|
2813
|
+
"shadcnFoundation": [
|
|
2814
|
+
"@phosphor-icons/react",
|
|
2815
|
+
"named icon imports",
|
|
2816
|
+
"semantic icon size tokens",
|
|
2817
|
+
"currentColor"
|
|
2818
|
+
],
|
|
2819
|
+
"fallbackToShadcn": "lucide-react icon composed through the same semantic slot",
|
|
2820
|
+
"requiredTokens": [
|
|
2821
|
+
"--icon-size-xs",
|
|
2822
|
+
"--icon-size-sm",
|
|
2823
|
+
"--icon-size-md"
|
|
2824
|
+
],
|
|
2825
|
+
"useWhen": [
|
|
2826
|
+
"A product selects the Phosphor icon family",
|
|
2827
|
+
"Ceramic must own icon sizing, accessibility, and RTL behavior",
|
|
2828
|
+
"A named Phosphor icon is imported directly for tree-shaking"
|
|
2829
|
+
],
|
|
2830
|
+
"avoidWhen": [
|
|
2831
|
+
"The icon itself is interactive; compose it inside IconButton",
|
|
2832
|
+
"An existing Ceramic component already owns its Lucide-based icon contract",
|
|
2833
|
+
"Replacing Breadcrumb or Navigation defaults without a component-specific decision"
|
|
2834
|
+
],
|
|
2835
|
+
"neverInvent": [
|
|
2836
|
+
"Raw SVG paths copied into product code",
|
|
2837
|
+
"Raw color or pixel icon sizes",
|
|
2838
|
+
"Unlabeled meaningful standalone icons",
|
|
2839
|
+
"Mirroring direction-neutral icons",
|
|
2840
|
+
"Namespace imports that prevent per-icon tree-shaking",
|
|
2841
|
+
"Left/right-only layout rules",
|
|
2842
|
+
"Utopia brand primitives inside reusable component logic"
|
|
2843
|
+
],
|
|
2844
|
+
"ai": {
|
|
2845
|
+
"props": [
|
|
2846
|
+
"icon",
|
|
2847
|
+
"size",
|
|
2848
|
+
"weight",
|
|
2849
|
+
"decorative",
|
|
2850
|
+
"label",
|
|
2851
|
+
"direction"
|
|
2852
|
+
],
|
|
2853
|
+
"rules": [
|
|
2854
|
+
"Import individual *Icon exports from @phosphor-icons/react.",
|
|
2855
|
+
"Use decorative for visual-only icons and a localized label for meaningful standalone icons.",
|
|
2856
|
+
"Use direction=\"directional\" only when the icon meaning follows reading direction.",
|
|
2857
|
+
"Color is inherited through currentColor and size comes from Ceramic semantic tokens."
|
|
2858
|
+
],
|
|
2859
|
+
"arabicFriendly": [
|
|
2860
|
+
"Directional arrows and chevrons mirror when the wrapper is inside dir=\"rtl\".",
|
|
2861
|
+
"Home, settings, search, download, and other direction-neutral icons do not mirror.",
|
|
2862
|
+
"Use localized accessible labels supplied by the product."
|
|
2863
|
+
]
|
|
2864
|
+
}
|
|
2865
|
+
},
|
|
2799
2866
|
{
|
|
2800
2867
|
"name": "Input",
|
|
2801
2868
|
"category": "Forms",
|
|
@@ -4511,7 +4578,8 @@
|
|
|
4511
4578
|
"useWhen": [
|
|
4512
4579
|
"Peer views",
|
|
4513
4580
|
"Same-context panels",
|
|
4514
|
-
"Keyboard-switchable content sections"
|
|
4581
|
+
"Keyboard-switchable content sections",
|
|
4582
|
+
"Full-width application workspaces when layout='fluid'"
|
|
4515
4583
|
],
|
|
4516
4584
|
"avoidWhen": [
|
|
4517
4585
|
"Page navigation",
|
|
@@ -4525,6 +4593,7 @@
|
|
|
4525
4593
|
],
|
|
4526
4594
|
"ai": {
|
|
4527
4595
|
"props": {
|
|
4596
|
+
"layout": "Use 'contained' for compact content panels (the default 42rem measure) or 'fluid' for dashboards and application workspaces that should fill the available inline size.",
|
|
4528
4597
|
"motion": "Optional boolean. Defaults to the MotionProvider policy and disables this component pattern when false."
|
|
4529
4598
|
}
|
|
4530
4599
|
}
|
package/lib/api.mjs
CHANGED
|
@@ -8,7 +8,7 @@ const packagedDataRoot = join(packageRoot, 'data')
|
|
|
8
8
|
const hasWorkspaceSource = existsSync(join(workspaceRoot, 'packages/design-system/src/manifests/components.json'))
|
|
9
9
|
|
|
10
10
|
export const apiVersion = 1
|
|
11
|
-
export const cliVersion = '0.
|
|
11
|
+
export const cliVersion = '0.4.0'
|
|
12
12
|
export const mcpLaunch = {
|
|
13
13
|
command: 'npx',
|
|
14
14
|
args: ['-y', '--package', '@utopia-studio-design/design-system-cli', 'utopia-ds', 'mcp'],
|