@astryxdesign/cli 0.1.1-canary.a514b99 → 0.1.1-canary.a7d67d0
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/docs/working-with-ai.doc.mjs +6 -6
- package/package.json +19 -8
- package/src/api/discover.mjs +78 -26
- package/src/api/layout.mjs +301 -0
- package/src/api/layout.test.mjs +238 -0
- package/src/api/template.mjs +191 -50
- package/src/api/template.test.mjs +2 -0
- package/src/codemods/__tests__/registry.test.mjs +1 -0
- package/src/codemods/registry.mjs +1 -0
- package/src/codemods/transforms/v0.1.2/__tests__/rename-text-color-active-to-accent.test.mjs +120 -0
- package/src/codemods/transforms/v0.1.2/index.mjs +19 -0
- package/src/codemods/transforms/v0.1.2/rename-text-color-active-to-accent.mjs +136 -0
- package/src/commands/gap-report.mjs +17 -9
- package/src/commands/gap-report.test.mjs +21 -16
- package/src/commands/init.mjs +34 -8
- package/src/commands/init.next-steps.test.mjs +46 -0
- package/src/commands/layout.mjs +139 -0
- package/src/commands/swizzle.mjs +51 -23
- package/src/commands/upgrade.mjs +2 -71
- package/src/config.mjs +31 -0
- package/src/config.test.mjs +24 -0
- package/src/index.mjs +4 -0
- package/src/lib/config-schema.mjs +119 -0
- package/src/lib/config.mjs +34 -7
- package/src/lib/config.test.mjs +51 -2
- package/src/lib/error-codes.mjs +8 -0
- package/src/lib/integrations.mjs +155 -0
- package/src/lib/integrations.test.mjs +154 -0
- package/src/lib/levenshtein.mjs +29 -0
- package/src/lib/manifest.mjs +6 -0
- package/src/lib/package-scanner.mjs +31 -7
- package/src/lib/string-utils.mjs +5 -14
- package/src/lib/xle/browser.d.ts +100 -0
- package/src/lib/xle/browser.mjs +120 -0
- package/src/lib/xle/expand.mjs +622 -0
- package/src/lib/xle/parse.mjs +581 -0
- package/src/lib/xle/print.mjs +174 -0
- package/src/lib/xle/registry-core.mjs +170 -0
- package/src/lib/xle/registry.mjs +237 -0
- package/src/lib/xle/splice.mjs +137 -0
- package/src/lib/xle/validate.mjs +356 -0
- package/src/lib/xle/xle.test.mjs +333 -0
- package/src/types/config.d.ts +99 -0
- package/src/utils/github.mjs +12 -27
- package/templates/blocks/components/Card/ClickableCardWithNestedButton.doc.mjs +1 -1
- package/templates/blocks/components/Card/SelectableCardMulti.doc.mjs +1 -1
- package/templates/blocks/components/ChatDictationButton/ChatDictationButtonShowcase.tsx +3 -3
- package/templates/blocks/components/CommandPaletteEmpty/CommandPaletteEmptyShowcase.doc.mjs +15 -0
- package/templates/blocks/components/CommandPaletteEmpty/CommandPaletteEmptyShowcase.tsx +26 -0
- package/templates/blocks/components/DateInput/DateInputDateRange.doc.mjs +2 -2
- package/templates/blocks/components/FileInput/FileInputShowcase.tsx +4 -2
- package/templates/blocks/components/LinkProvider/LinkProviderCustomLink.doc.mjs +14 -0
- package/templates/blocks/components/LinkProvider/LinkProviderCustomLink.tsx +43 -0
- package/templates/blocks/components/MultiSelector/MultiSelectorShowcase.tsx +6 -2
- package/templates/blocks/components/NumberInput/NumberInputShowcase.tsx +6 -2
- package/templates/blocks/components/RadioList/RadioListShowcase.tsx +8 -1
- package/templates/blocks/components/SegmentedControl/SegmentedControlShowcase.tsx +3 -1
- package/templates/blocks/components/Selector/SelectorShowcase.tsx +4 -1
- package/templates/blocks/components/Slider/SliderShowcase.tsx +10 -1
- package/templates/blocks/components/Tab/TabShowcase.tsx +3 -1
- package/templates/blocks/components/TabList/TabListShowcase.tsx +3 -1
- package/templates/blocks/components/TabMenu/TabMenuShowcase.tsx +3 -1
- package/templates/blocks/components/Table/ColumnResizeHookUsage.doc.mjs +14 -0
- package/templates/blocks/components/Table/ColumnResizeHookUsage.tsx +59 -0
- package/templates/blocks/components/Table/StickyColumnsHookUsage.doc.mjs +14 -0
- package/templates/blocks/components/Table/StickyColumnsHookUsage.tsx +104 -0
- package/templates/blocks/components/Text/TextColors.tsx +20 -5
- package/templates/blocks/components/TextArea/TextAreaShowcase.tsx +4 -2
- package/templates/blocks/components/TextInput/TextInputShowcase.tsx +4 -2
- package/templates/blocks/components/Thumbnail/ThumbnailGallery.tsx +25 -5
- package/templates/blocks/components/Timestamp/TimestampColors.tsx +2 -2
- package/templates/blocks/components/ToggleButton/ToggleButtonGroup.doc.mjs +1 -1
- package/templates/blocks/components/Tokenizer/TokenizerShowcase.tsx +8 -6
- package/templates/blocks/components/Typeahead/TypeaheadShowcase.tsx +6 -2
- package/templates/pages/theme-showcase/page.tsx +8 -19
- package/templates/blocks/components/MoreMenu/MoreMenuInToolbar.doc.mjs +0 -14
- package/templates/blocks/components/MoreMenu/MoreMenuInToolbar.tsx +0 -57
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file XLE/XLO browser barrel — the layout language without Node deps.
|
|
5
|
+
*
|
|
6
|
+
* The CLI builds its registry by reading .doc.mjs from disk (registry.mjs,
|
|
7
|
+
* Node-only). The browser playground instead receives a *serialized*
|
|
8
|
+
* registry (built at deploy time) and hydrates it here, then runs the same
|
|
9
|
+
* pure parse → validate → expand → print pipeline. Importing this module
|
|
10
|
+
* never pulls in node:fs, so it bundles cleanly for the web.
|
|
11
|
+
*
|
|
12
|
+
* @input expression string + a serialized-or-hydrated registry (+ blocks)
|
|
13
|
+
* @output checkExpression / expandExpression + the raw pipeline pieces
|
|
14
|
+
* @position lib/xle — exported as `@astryxdesign/cli/xle`
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import {parse, detectForm, XLEParseError} from './parse.mjs';
|
|
18
|
+
import {validate} from './validate.mjs';
|
|
19
|
+
import {expand} from './expand.mjs';
|
|
20
|
+
import {toCompact, toOutline} from './print.mjs';
|
|
21
|
+
import {hydrateRegistry} from './registry-core.mjs';
|
|
22
|
+
|
|
23
|
+
export {parse, detectForm, XLEParseError, validate, expand, toCompact, toOutline};
|
|
24
|
+
export {hydrateRegistry, serializeRegistry, ALIAS_TABLE, resolveComponent, SPACING_STEPS} from './registry-core.mjs';
|
|
25
|
+
|
|
26
|
+
/** Accept either a hydrated registry (Map fields) or serialized JSON. */
|
|
27
|
+
function asRegistry(registry) {
|
|
28
|
+
return registry && registry.components instanceof Map ? registry : hydrateRegistry(registry);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function formatIssue(issue) {
|
|
32
|
+
const where = issue.line != null ? `line ${issue.line}: ` : '';
|
|
33
|
+
return `${where}${issue.message}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Validate an expression and return both canonical surfaces — the browser
|
|
38
|
+
* twin of `layout check`. Never throws on invalid input; returns the errors.
|
|
39
|
+
*
|
|
40
|
+
* @param {string} expression
|
|
41
|
+
* @param {object} registry - serialized or hydrated
|
|
42
|
+
* @param {object} [opts]
|
|
43
|
+
* @param {Array} [opts.blocks] - block list for {hint} resolution (default [])
|
|
44
|
+
* @param {'compact'|'outline'|'auto'} [opts.form]
|
|
45
|
+
* @param {boolean} [opts.loose]
|
|
46
|
+
* @returns {{ok: boolean, valid?: boolean, form?: string, errors: Array, warnings: string[], compact?: string, outline?: string, parseError?: object}}
|
|
47
|
+
*/
|
|
48
|
+
export function checkExpression(expression, registry, opts = {}) {
|
|
49
|
+
const {blocks = [], form = 'auto', loose = false} = opts;
|
|
50
|
+
let doc;
|
|
51
|
+
try {
|
|
52
|
+
doc = parse(expression, {form});
|
|
53
|
+
} catch (e) {
|
|
54
|
+
if (e instanceof XLEParseError) {
|
|
55
|
+
return {
|
|
56
|
+
ok: false,
|
|
57
|
+
valid: false,
|
|
58
|
+
errors: [{message: e.message, line: e.line, col: e.col, formatted: formatIssue(e), kind: 'parse'}],
|
|
59
|
+
warnings: [],
|
|
60
|
+
parseError: {message: e.message, line: e.line, col: e.col},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
throw e;
|
|
64
|
+
}
|
|
65
|
+
const {errors, warnings} = validate(doc, asRegistry(registry), blocks, {loose});
|
|
66
|
+
return {
|
|
67
|
+
ok: true,
|
|
68
|
+
valid: errors.length === 0,
|
|
69
|
+
form: doc.form,
|
|
70
|
+
errors: errors.map(e => ({...e, formatted: formatIssue(e)})),
|
|
71
|
+
warnings: warnings.map(formatIssue),
|
|
72
|
+
compact: toCompact(doc),
|
|
73
|
+
outline: toOutline(doc),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Validate + expand to TSX — the browser twin of `layout expand`.
|
|
79
|
+
* Returns either {code, ...} or {errors} (never writes files).
|
|
80
|
+
*
|
|
81
|
+
* @param {string} expression
|
|
82
|
+
* @param {object} registry
|
|
83
|
+
* @param {object} [opts]
|
|
84
|
+
* @param {Array} [opts.blocks]
|
|
85
|
+
* @param {'compact'|'outline'|'auto'} [opts.form]
|
|
86
|
+
* @param {boolean} [opts.loose]
|
|
87
|
+
* @param {string} [opts.name] - generated component name (PascalCase)
|
|
88
|
+
* @param {Map} [opts.blockModules] - prepared block sources/imports for splicing;
|
|
89
|
+
* omit in the browser (hints stay as TODO markers without sources)
|
|
90
|
+
*/
|
|
91
|
+
export function expandExpression(expression, registry, opts = {}) {
|
|
92
|
+
const {blocks = [], form = 'auto', loose = false, name = 'GeneratedLayout', blockModules} = opts;
|
|
93
|
+
const reg = asRegistry(registry);
|
|
94
|
+
let doc;
|
|
95
|
+
try {
|
|
96
|
+
doc = parse(expression, {form});
|
|
97
|
+
} catch (e) {
|
|
98
|
+
if (e instanceof XLEParseError) {
|
|
99
|
+
return {ok: false, errors: [{message: e.message, line: e.line, col: e.col, formatted: formatIssue(e), kind: 'parse'}]};
|
|
100
|
+
}
|
|
101
|
+
throw e;
|
|
102
|
+
}
|
|
103
|
+
const {errors, warnings} = validate(doc, reg, blocks, {loose});
|
|
104
|
+
if (errors.length > 0) {
|
|
105
|
+
return {ok: false, errors: errors.map(e => ({...e, formatted: formatIssue(e)}))};
|
|
106
|
+
}
|
|
107
|
+
if (!/^[A-Z][A-Za-z0-9]*$/.test(name)) {
|
|
108
|
+
return {ok: false, errors: [{message: `Component name must be PascalCase, got '${name}'`, formatted: `Component name must be PascalCase, got '${name}'`}]};
|
|
109
|
+
}
|
|
110
|
+
const result = expand(doc, reg, {componentName: name, blockModules});
|
|
111
|
+
return {
|
|
112
|
+
ok: true,
|
|
113
|
+
form: form === 'auto' ? detectForm(expression) : form,
|
|
114
|
+
code: result.code,
|
|
115
|
+
componentsUsed: result.componentsUsed,
|
|
116
|
+
states: result.states,
|
|
117
|
+
todos: result.todos,
|
|
118
|
+
warnings: warnings.map(formatIssue),
|
|
119
|
+
};
|
|
120
|
+
}
|