@fragments-sdk/cli 0.9.0 → 0.10.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/dist/bin.d.ts +1 -0
- package/dist/bin.js +502 -84
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-CJEGT3WD.js → chunk-566BNPQZ.js} +21 -6
- package/dist/chunk-566BNPQZ.js.map +1 -0
- package/dist/{chunk-WI6SLMSO.js → chunk-CAMXG5HJ.js} +5 -5
- package/dist/chunk-D2CDBRNU.js +2 -0
- package/dist/{chunk-YMPGYEWK.js → chunk-D5PYOXEI.js} +2 -2
- package/dist/{chunk-NGIMCIK2.js → chunk-OQO55NKV.js} +405 -34
- package/dist/chunk-OQO55NKV.js.map +1 -0
- package/dist/{chunk-TOIE7VXF.js → chunk-PW7QTQA6.js} +2 -2
- package/dist/{chunk-AWYCDRPG.js → chunk-WXSR2II7.js} +2 -2
- package/dist/chunk-WXSR2II7.js.map +1 -0
- package/dist/{chunk-2JIKCJX3.js → chunk-ZDA3PLQ6.js} +17 -14
- package/dist/chunk-ZDA3PLQ6.js.map +1 -0
- package/dist/core/index.d.ts +1 -2092
- package/dist/core/index.js +26 -21
- package/dist/{discovery-Z4RDDFVR.js → discovery-NEOY4MPN.js} +3 -3
- package/dist/generate-BGKTKO6E.js +459 -0
- package/dist/generate-BGKTKO6E.js.map +1 -0
- package/dist/index.d.ts +3 -5
- package/dist/index.js +7 -8
- package/dist/index.js.map +1 -1
- package/dist/{init-KSAAS7X3.js → init-Q53R5Q2T.js} +66 -76
- package/dist/init-Q53R5Q2T.js.map +1 -0
- package/dist/mcp-bin.js +5 -7
- package/dist/mcp-bin.js.map +1 -1
- package/dist/scan-OQU7M4GH.js +14 -0
- package/dist/scan-generate-T5QNUG7N.js +691 -0
- package/dist/scan-generate-T5QNUG7N.js.map +1 -0
- package/dist/{service-A5GIGGGK.js → service-TQYWY65E.js} +4 -5
- package/dist/{static-viewer-NSODM5VX.js → static-viewer-NUBFPKWH.js} +4 -5
- package/dist/static-viewer-NUBFPKWH.js.map +1 -0
- package/dist/{test-RPWZAYSJ.js → test-2CSOSS3B.js} +4 -5
- package/dist/{test-RPWZAYSJ.js.map → test-2CSOSS3B.js.map} +1 -1
- package/dist/{tokens-NIXSZRX7.js → tokens-DXEGYTOJ.js} +6 -7
- package/dist/{tokens-NIXSZRX7.js.map → tokens-DXEGYTOJ.js.map} +1 -1
- package/dist/{viewer-SBTJDMP7.js → viewer-DBEPYM3G.js} +245 -23
- package/dist/viewer-DBEPYM3G.js.map +1 -0
- package/package.json +2 -1
- package/src/bin.ts +33 -1
- package/src/build.ts +13 -3
- package/src/commands/__tests__/scan-generate.test.ts +308 -0
- package/src/commands/build.ts +16 -2
- package/src/commands/generate.ts +383 -68
- package/src/commands/init.ts +81 -56
- package/src/commands/perf.ts +1 -1
- package/src/commands/scan-generate.ts +1013 -0
- package/src/commands/setup.ts +499 -0
- package/src/core/auto-props.ts +1 -1
- package/src/core/bundle-measurer.ts +2 -2
- package/src/core/config.ts +16 -4
- package/src/core/discovery.ts +2 -2
- package/src/core/generators/context.ts +1 -1
- package/src/core/generators/registry.ts +3 -3
- package/src/core/generators/typescript-extractor.ts +11 -1
- package/src/core/graph-extractor.ts +1 -1
- package/src/core/index.ts +3 -190
- package/src/core/loader.ts +2 -2
- package/src/core/parser.ts +1 -1
- package/src/core/previewLoader.ts +1 -1
- package/src/index.ts +2 -2
- package/src/migrate/converter.ts +9 -1
- package/src/migrate/parser.ts +2 -0
- package/src/migrate/types.ts +2 -0
- package/src/service/snippet-validation.test.ts +1 -1
- package/src/service/snippet-validation.ts +2 -2
- package/src/setup.ts +69 -24
- package/src/viewer/__tests__/viewer-integration.test.ts +4 -10
- package/src/viewer/components/AccessibilityPanel.tsx +305 -312
- package/src/viewer/components/ActionsPanel.tsx +31 -29
- package/src/viewer/components/AllVariantsPreview.tsx +78 -0
- package/src/viewer/components/App.tsx +187 -740
- package/src/viewer/components/BottomPanel.tsx +228 -132
- package/src/viewer/components/CodePanel.tsx +1 -1
- package/src/viewer/components/CommandPalette.tsx +7 -10
- package/src/viewer/components/ComponentDocView.tsx +164 -0
- package/src/viewer/components/ComponentGraph.tsx +111 -142
- package/src/viewer/components/ContractPanel.tsx +6 -6
- package/src/viewer/components/EmptyVariantMessage.tsx +54 -0
- package/src/viewer/components/FigmaEmbed.tsx +20 -18
- package/src/viewer/components/FragmentEditor.tsx +92 -115
- package/src/viewer/components/HeaderSearch.tsx +24 -0
- package/src/viewer/components/HealthDashboard.tsx +16 -2
- package/src/viewer/components/Icons.tsx +9 -0
- package/src/viewer/components/InteractionsPanel.tsx +101 -117
- package/src/viewer/components/IsolatedPreviewFrame.tsx +1 -0
- package/src/viewer/components/LandingPage.tsx +3 -3
- package/src/viewer/components/LeftSidebar.tsx +141 -63
- package/src/viewer/components/LoadErrorMessage.tsx +102 -0
- package/src/viewer/components/MultiViewportPreview.tsx +61 -142
- package/src/viewer/components/NoVariantsMessage.tsx +59 -0
- package/src/viewer/components/PanelShell.tsx +161 -0
- package/src/viewer/components/PerformancePanel.tsx +31 -28
- package/src/viewer/components/PreviewArea.tsx +1 -1
- package/src/viewer/components/PreviewAside.tsx +168 -0
- package/src/viewer/components/PreviewFrameHost.tsx +3 -3
- package/src/viewer/components/PropsEditor.tsx +70 -156
- package/src/viewer/components/ResizablePanel.tsx +103 -263
- package/src/viewer/components/RightSidebar.tsx +3 -9
- package/src/viewer/components/SkeletonLoader.tsx +13 -13
- package/src/viewer/components/TokenStylePanel.tsx +182 -209
- package/src/viewer/components/TopToolbar.tsx +159 -0
- package/src/viewer/components/VariantMatrix.tsx +42 -86
- package/src/viewer/components/VariantTabs.tsx +3 -3
- package/src/viewer/components/ViewerHeader.tsx +69 -0
- package/src/viewer/components/WebMCPDevTools.tsx +17 -23
- package/src/viewer/components/viewer-utils.ts +16 -0
- package/src/viewer/entry.tsx +5 -0
- package/src/viewer/hooks/useAppState.ts +27 -4
- package/src/viewer/hooks/usePreviewBridge.ts +2 -2
- package/src/viewer/preview-frame.html +6 -12
- package/src/viewer/server.ts +169 -2
- package/src/viewer/vendor/shared/src/ComponentDocContent.module.scss +10 -0
- package/src/viewer/vendor/shared/src/ComponentDocContent.module.scss.d.ts +2 -0
- package/src/viewer/vendor/shared/src/ComponentDocContent.tsx +274 -0
- package/src/viewer/vendor/shared/src/DocsHeaderBar.tsx +6 -18
- package/src/viewer/vendor/shared/src/DocsPageShell.tsx +5 -0
- package/src/viewer/vendor/shared/src/DocsSidebarNav.tsx +5 -16
- package/src/viewer/vendor/shared/src/PropsTable.module.scss +68 -0
- package/src/viewer/vendor/shared/src/PropsTable.module.scss.d.ts +2 -0
- package/src/viewer/vendor/shared/src/PropsTable.tsx +76 -0
- package/src/viewer/vendor/shared/src/VariantPreviewCard.module.scss +114 -0
- package/src/viewer/vendor/shared/src/VariantPreviewCard.module.scss.d.ts +2 -0
- package/src/viewer/vendor/shared/src/VariantPreviewCard.tsx +134 -0
- package/src/viewer/vendor/shared/src/index.ts +8 -0
- package/src/viewer/vendor/shared/src/types.ts +12 -0
- package/src/viewer/vite-plugin.ts +109 -4
- package/dist/chunk-2JIKCJX3.js.map +0 -1
- package/dist/chunk-AWYCDRPG.js.map +0 -1
- package/dist/chunk-CJEGT3WD.js.map +0 -1
- package/dist/chunk-EKLMXTWU.js +0 -80
- package/dist/chunk-EKLMXTWU.js.map +0 -1
- package/dist/chunk-GOVI6COW.js +0 -195
- package/dist/chunk-GOVI6COW.js.map +0 -1
- package/dist/chunk-NGIMCIK2.js.map +0 -1
- package/dist/defineFragment-D0UTve-I.d.ts +0 -665
- package/dist/generate-35OIMW4Y.js +0 -252
- package/dist/generate-35OIMW4Y.js.map +0 -1
- package/dist/init-KSAAS7X3.js.map +0 -1
- package/dist/scan-65RH3QMM.js +0 -15
- package/dist/viewer-SBTJDMP7.js.map +0 -1
- package/src/core/__tests__/preview-runtime.test.tsx +0 -111
- package/src/core/composition.test.ts +0 -262
- package/src/core/composition.ts +0 -318
- package/src/core/constants.ts +0 -114
- package/src/core/context.ts +0 -2
- package/src/core/defineFragment.ts +0 -141
- package/src/core/figma.ts +0 -263
- package/src/core/fragment-types.ts +0 -214
- package/src/core/performance-presets.ts +0 -142
- package/src/core/preview-runtime.tsx +0 -144
- package/src/core/schema.ts +0 -221
- package/src/core/storyAdapter.test.ts +0 -571
- package/src/core/storyAdapter.ts +0 -761
- package/src/core/storybook-csf.ts +0 -11
- package/src/core/token-parser.ts +0 -321
- package/src/core/token-types.ts +0 -287
- package/src/core/types.ts +0 -762
- /package/dist/{chunk-WI6SLMSO.js.map → chunk-CAMXG5HJ.js.map} +0 -0
- /package/dist/{discovery-Z4RDDFVR.js.map → chunk-D2CDBRNU.js.map} +0 -0
- /package/dist/{chunk-YMPGYEWK.js.map → chunk-D5PYOXEI.js.map} +0 -0
- /package/dist/{chunk-TOIE7VXF.js.map → chunk-PW7QTQA6.js.map} +0 -0
- /package/dist/{scan-65RH3QMM.js.map → discovery-NEOY4MPN.js.map} +0 -0
- /package/dist/{service-A5GIGGGK.js.map → scan-OQU7M4GH.js.map} +0 -0
- /package/dist/{static-viewer-NSODM5VX.js.map → service-TQYWY65E.js.map} +0 -0
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Performance budget presets and classification utilities.
|
|
3
|
-
*
|
|
4
|
-
* ESLint model: global defaults, zero-config, auto-measurement.
|
|
5
|
-
* Users configure 0-3 numbers. Per-component overrides are the `eslint-disable` equivalent.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
// ---------------------------------------------------------------------------
|
|
9
|
-
// Types
|
|
10
|
-
// ---------------------------------------------------------------------------
|
|
11
|
-
|
|
12
|
-
export interface PerformanceBudgets {
|
|
13
|
-
/** Maximum gzipped bundle size in bytes */
|
|
14
|
-
bundleSize: number;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface PerformanceConfig {
|
|
18
|
-
preset: string;
|
|
19
|
-
budgets: PerformanceBudgets;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export type ComplexityTier = 'lightweight' | 'moderate' | 'heavy';
|
|
23
|
-
|
|
24
|
-
export interface PerformanceData {
|
|
25
|
-
/** Gzipped bundle size in bytes */
|
|
26
|
-
bundleSize: number;
|
|
27
|
-
/** Raw (minified, not gzipped) bundle size in bytes */
|
|
28
|
-
rawSize: number;
|
|
29
|
-
/** Complexity classification */
|
|
30
|
-
complexity: ComplexityTier;
|
|
31
|
-
/** Percentage of budget used (0-100+) */
|
|
32
|
-
budgetPercent: number;
|
|
33
|
-
/** Whether the component exceeds its budget */
|
|
34
|
-
overBudget: boolean;
|
|
35
|
-
/** ISO timestamp when measured */
|
|
36
|
-
measuredAt: string;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface PerformanceSummary {
|
|
40
|
-
/** Preset name used */
|
|
41
|
-
preset: string;
|
|
42
|
-
/** Budget applied in bytes */
|
|
43
|
-
budget: number;
|
|
44
|
-
/** Total components measured */
|
|
45
|
-
total: number;
|
|
46
|
-
/** Number of components over budget */
|
|
47
|
-
overBudget: number;
|
|
48
|
-
/** Distribution by tier */
|
|
49
|
-
tiers: Record<ComplexityTier, number>;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// ---------------------------------------------------------------------------
|
|
53
|
-
// Presets
|
|
54
|
-
// ---------------------------------------------------------------------------
|
|
55
|
-
|
|
56
|
-
const PRESETS: Record<string, PerformanceBudgets> = {
|
|
57
|
-
strict: { bundleSize: 8 * 1024 }, // 8KB gzipped
|
|
58
|
-
standard: { bundleSize: 15 * 1024 }, // 15KB gzipped
|
|
59
|
-
relaxed: { bundleSize: 30 * 1024 }, // 30KB gzipped
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
export const PRESET_NAMES = Object.keys(PRESETS) as readonly string[];
|
|
63
|
-
|
|
64
|
-
// ---------------------------------------------------------------------------
|
|
65
|
-
// Resolution
|
|
66
|
-
// ---------------------------------------------------------------------------
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Resolve a performance config from user input.
|
|
70
|
-
* Accepts a preset name string or a custom config object.
|
|
71
|
-
*/
|
|
72
|
-
export function resolvePerformanceConfig(
|
|
73
|
-
input: string | { preset?: string; budgets?: Partial<PerformanceBudgets> } | undefined
|
|
74
|
-
): PerformanceConfig {
|
|
75
|
-
if (!input) {
|
|
76
|
-
return { preset: 'standard', budgets: PRESETS.standard };
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (typeof input === 'string') {
|
|
80
|
-
const budgets = PRESETS[input];
|
|
81
|
-
if (!budgets) {
|
|
82
|
-
throw new Error(
|
|
83
|
-
`Unknown performance preset "${input}". Available: ${PRESET_NAMES.join(', ')}`
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
return { preset: input, budgets };
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const presetName = input.preset ?? 'standard';
|
|
90
|
-
const baseBudgets = PRESETS[presetName];
|
|
91
|
-
if (!baseBudgets) {
|
|
92
|
-
throw new Error(
|
|
93
|
-
`Unknown performance preset "${presetName}". Available: ${PRESET_NAMES.join(', ')}`
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return {
|
|
98
|
-
preset: presetName,
|
|
99
|
-
budgets: {
|
|
100
|
-
bundleSize: input.budgets?.bundleSize ?? baseBudgets.bundleSize,
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// ---------------------------------------------------------------------------
|
|
106
|
-
// Classification
|
|
107
|
-
// ---------------------------------------------------------------------------
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Classify a component's complexity based on gzipped bundle size.
|
|
111
|
-
*
|
|
112
|
-
* - lightweight: < 5KB — simple, leaf components
|
|
113
|
-
* - moderate: < 15KB — typical composed components
|
|
114
|
-
* - heavy: >= 15KB — complex widgets with dependencies
|
|
115
|
-
*/
|
|
116
|
-
export function classifyComplexity(gzipBytes: number): ComplexityTier {
|
|
117
|
-
if (gzipBytes < 5 * 1024) return 'lightweight';
|
|
118
|
-
if (gzipBytes < 15 * 1024) return 'moderate';
|
|
119
|
-
return 'heavy';
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// ---------------------------------------------------------------------------
|
|
123
|
-
// Formatting helpers
|
|
124
|
-
// ---------------------------------------------------------------------------
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Format bytes to a human-readable string (e.g. "2.1KB", "15.3KB").
|
|
128
|
-
*/
|
|
129
|
-
export function formatBytes(bytes: number): string {
|
|
130
|
-
if (bytes < 1024) return `${bytes}B`;
|
|
131
|
-
const kb = bytes / 1024;
|
|
132
|
-
return kb < 10 ? `${kb.toFixed(1)}KB` : `${Math.round(kb)}KB`;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Create a visual budget bar for terminal output.
|
|
137
|
-
*/
|
|
138
|
-
export function budgetBar(percent: number, width = 20): string {
|
|
139
|
-
const filled = Math.min(Math.round((percent / 100) * width), width);
|
|
140
|
-
const bar = '█'.repeat(filled) + '░'.repeat(width - filled);
|
|
141
|
-
return percent > 100 ? `\x1b[31m${bar}\x1b[0m` : `\x1b[32m${bar}\x1b[0m`;
|
|
142
|
-
}
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState, type ReactNode } from "react";
|
|
2
|
-
import type { VariantLoader, VariantRenderOptions } from "./types.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Minimal contract for rendering a preview variant.
|
|
6
|
-
* Compatible with fragment variants and Storybook-adapted variants.
|
|
7
|
-
*/
|
|
8
|
-
export interface PreviewVariantLike {
|
|
9
|
-
render: (options?: VariantRenderOptions) => ReactNode;
|
|
10
|
-
loaders?: VariantLoader[];
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface PreviewRuntimeState {
|
|
14
|
-
content: ReactNode | null;
|
|
15
|
-
isLoading: boolean;
|
|
16
|
-
error: Error | null;
|
|
17
|
-
loadedData?: Record<string, unknown>;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface PreviewRuntimeOptions {
|
|
21
|
-
variant?: PreviewVariantLike | null;
|
|
22
|
-
loadedData?: Record<string, unknown>;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const EMPTY_STATE: PreviewRuntimeState = {
|
|
26
|
-
content: null,
|
|
27
|
-
isLoading: false,
|
|
28
|
-
error: null,
|
|
29
|
-
loadedData: undefined,
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
function toError(error: unknown): Error {
|
|
33
|
-
return error instanceof Error ? error : new Error(String(error));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Execute all variant loaders and merge their payloads.
|
|
38
|
-
* `loadedData` is applied last so host-level overrides win.
|
|
39
|
-
*/
|
|
40
|
-
export async function executeVariantLoaders(
|
|
41
|
-
loaders: VariantLoader[] | undefined,
|
|
42
|
-
loadedData?: Record<string, unknown>,
|
|
43
|
-
): Promise<Record<string, unknown> | undefined> {
|
|
44
|
-
const hasLoaders = !!loaders && loaders.length > 0;
|
|
45
|
-
if (!hasLoaders) {
|
|
46
|
-
return loadedData;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const results = await Promise.all(loaders.map((loader) => loader()));
|
|
50
|
-
const mergedFromLoaders = results.reduce<Record<string, unknown>>(
|
|
51
|
-
(acc, result) => ({ ...acc, ...result }),
|
|
52
|
-
{},
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
return loadedData ? { ...mergedFromLoaders, ...loadedData } : mergedFromLoaders;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Resolve a full runtime state (loader execution + render) in one async call.
|
|
60
|
-
* This is useful for testing and for hook/component orchestration.
|
|
61
|
-
*/
|
|
62
|
-
export async function resolvePreviewRuntimeState(
|
|
63
|
-
options: PreviewRuntimeOptions,
|
|
64
|
-
): Promise<PreviewRuntimeState> {
|
|
65
|
-
const { variant, loadedData } = options;
|
|
66
|
-
if (!variant) {
|
|
67
|
-
return EMPTY_STATE;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
const mergedLoadedData = await executeVariantLoaders(variant.loaders, loadedData);
|
|
72
|
-
const content = variant.render({ loadedData: mergedLoadedData });
|
|
73
|
-
return {
|
|
74
|
-
content,
|
|
75
|
-
isLoading: false,
|
|
76
|
-
error: null,
|
|
77
|
-
loadedData: mergedLoadedData,
|
|
78
|
-
};
|
|
79
|
-
} catch (error) {
|
|
80
|
-
return {
|
|
81
|
-
content: null,
|
|
82
|
-
isLoading: false,
|
|
83
|
-
error: toError(error),
|
|
84
|
-
loadedData: undefined,
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Hook for rendering a preview variant with loader support.
|
|
91
|
-
*/
|
|
92
|
-
export function usePreviewVariantRuntime(
|
|
93
|
-
options: PreviewRuntimeOptions,
|
|
94
|
-
): PreviewRuntimeState {
|
|
95
|
-
const { variant, loadedData } = options;
|
|
96
|
-
const [state, setState] = useState<PreviewRuntimeState>(EMPTY_STATE);
|
|
97
|
-
|
|
98
|
-
useEffect(() => {
|
|
99
|
-
let cancelled = false;
|
|
100
|
-
|
|
101
|
-
if (!variant) {
|
|
102
|
-
setState(EMPTY_STATE);
|
|
103
|
-
return () => {
|
|
104
|
-
cancelled = true;
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const hasLoaders = !!variant.loaders && variant.loaders.length > 0;
|
|
109
|
-
setState({
|
|
110
|
-
content: null,
|
|
111
|
-
isLoading: hasLoaders,
|
|
112
|
-
error: null,
|
|
113
|
-
loadedData: undefined,
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
resolvePreviewRuntimeState({ variant, loadedData }).then((nextState) => {
|
|
117
|
-
if (!cancelled) {
|
|
118
|
-
setState(nextState);
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
return () => {
|
|
123
|
-
cancelled = true;
|
|
124
|
-
};
|
|
125
|
-
}, [variant, loadedData]);
|
|
126
|
-
|
|
127
|
-
return state;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
interface PreviewVariantRuntimeProps extends PreviewRuntimeOptions {
|
|
131
|
-
children: (state: PreviewRuntimeState) => ReactNode;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Render-prop component wrapper around `usePreviewVariantRuntime`.
|
|
136
|
-
*/
|
|
137
|
-
export function PreviewVariantRuntime({
|
|
138
|
-
variant,
|
|
139
|
-
loadedData,
|
|
140
|
-
children,
|
|
141
|
-
}: PreviewVariantRuntimeProps) {
|
|
142
|
-
const state = usePreviewVariantRuntime({ variant, loadedData });
|
|
143
|
-
return <>{children(state)}</>;
|
|
144
|
-
}
|
package/src/core/schema.ts
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Zod schemas for runtime validation of fragment definitions
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
// Figma property mapping schemas
|
|
8
|
-
const figmaStringMappingSchema = z.object({
|
|
9
|
-
__type: z.literal('figma-string'),
|
|
10
|
-
figmaProperty: z.string().min(1),
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
const figmaBooleanMappingSchema = z.object({
|
|
14
|
-
__type: z.literal('figma-boolean'),
|
|
15
|
-
figmaProperty: z.string().min(1),
|
|
16
|
-
valueMapping: z.object({ true: z.unknown(), false: z.unknown() }).optional(),
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
const figmaEnumMappingSchema = z.object({
|
|
20
|
-
__type: z.literal('figma-enum'),
|
|
21
|
-
figmaProperty: z.string().min(1),
|
|
22
|
-
valueMapping: z.record(z.unknown()),
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
const figmaInstanceMappingSchema = z.object({
|
|
26
|
-
__type: z.literal('figma-instance'),
|
|
27
|
-
figmaProperty: z.string().min(1),
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
const figmaChildrenMappingSchema = z.object({
|
|
31
|
-
__type: z.literal('figma-children'),
|
|
32
|
-
layers: z.array(z.string().min(1)),
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
const figmaTextContentMappingSchema = z.object({
|
|
36
|
-
__type: z.literal('figma-text-content'),
|
|
37
|
-
layer: z.string().min(1),
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
export const figmaPropMappingSchema = z.discriminatedUnion('__type', [
|
|
41
|
-
figmaStringMappingSchema,
|
|
42
|
-
figmaBooleanMappingSchema,
|
|
43
|
-
figmaEnumMappingSchema,
|
|
44
|
-
figmaInstanceMappingSchema,
|
|
45
|
-
figmaChildrenMappingSchema,
|
|
46
|
-
figmaTextContentMappingSchema,
|
|
47
|
-
]);
|
|
48
|
-
|
|
49
|
-
export const fragmentMetaSchema = z.object({
|
|
50
|
-
name: z.string().min(1),
|
|
51
|
-
description: z.string().min(1),
|
|
52
|
-
category: z.string().min(1),
|
|
53
|
-
tags: z.array(z.string()).optional(),
|
|
54
|
-
status: z.enum(['stable', 'beta', 'deprecated', 'experimental']).optional(),
|
|
55
|
-
since: z.string().optional(),
|
|
56
|
-
dependencies: z.array(z.object({
|
|
57
|
-
name: z.string().min(1),
|
|
58
|
-
version: z.string().min(1),
|
|
59
|
-
reason: z.string().optional(),
|
|
60
|
-
})).optional(),
|
|
61
|
-
figma: z.string().url().optional(),
|
|
62
|
-
figmaProps: z.record(figmaPropMappingSchema).optional(),
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
export const fragmentUsageSchema = z.object({
|
|
66
|
-
when: z.array(z.string()).min(1),
|
|
67
|
-
whenNot: z.array(z.string()).min(1),
|
|
68
|
-
guidelines: z.array(z.string()).optional(),
|
|
69
|
-
accessibility: z.array(z.string()).optional(),
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
export const propTypeSchema: z.ZodType<string> = z.enum([
|
|
73
|
-
'string',
|
|
74
|
-
'number',
|
|
75
|
-
'boolean',
|
|
76
|
-
'enum',
|
|
77
|
-
'function',
|
|
78
|
-
'node',
|
|
79
|
-
'element',
|
|
80
|
-
'object',
|
|
81
|
-
'array',
|
|
82
|
-
'union',
|
|
83
|
-
'custom',
|
|
84
|
-
]);
|
|
85
|
-
|
|
86
|
-
export const propDefinitionSchema = z.object({
|
|
87
|
-
type: propTypeSchema,
|
|
88
|
-
values: z.array(z.string()).readonly().optional(),
|
|
89
|
-
default: z.unknown().optional(),
|
|
90
|
-
description: z.string().optional(),
|
|
91
|
-
required: z.boolean().optional(),
|
|
92
|
-
constraints: z.array(z.string()).optional(),
|
|
93
|
-
typeDetails: z.record(z.unknown()).optional(),
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
export const relationshipTypeSchema = z.enum([
|
|
97
|
-
'alternative',
|
|
98
|
-
'sibling',
|
|
99
|
-
'parent',
|
|
100
|
-
'child',
|
|
101
|
-
'composition',
|
|
102
|
-
'complementary',
|
|
103
|
-
'used-by',
|
|
104
|
-
]);
|
|
105
|
-
|
|
106
|
-
export const componentRelationSchema = z.object({
|
|
107
|
-
component: z.string().min(1),
|
|
108
|
-
relationship: relationshipTypeSchema,
|
|
109
|
-
note: z.string().min(1),
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
export const fragmentVariantSchema = z.object({
|
|
113
|
-
name: z.string().min(1),
|
|
114
|
-
description: z.string().min(1),
|
|
115
|
-
render: z.function().returns(z.unknown()),
|
|
116
|
-
code: z.string().optional(),
|
|
117
|
-
figma: z.string().url().optional(),
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Schema for banned patterns in codebase
|
|
122
|
-
*/
|
|
123
|
-
export const fragmentBanSchema = z.object({
|
|
124
|
-
pattern: z.string().min(1),
|
|
125
|
-
message: z.string().min(1),
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Schema for agent-optimized contract metadata
|
|
130
|
-
*/
|
|
131
|
-
export const fragmentContractSchema = z.object({
|
|
132
|
-
propsSummary: z.array(z.string()).optional(),
|
|
133
|
-
a11yRules: z.array(z.string()).optional(),
|
|
134
|
-
bans: z.array(fragmentBanSchema).optional(),
|
|
135
|
-
scenarioTags: z.array(z.string()).optional(),
|
|
136
|
-
performanceBudget: z.number().positive().optional(),
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Schema for provenance tracking of generated fragments
|
|
141
|
-
*/
|
|
142
|
-
export const fragmentGeneratedSchema = z.object({
|
|
143
|
-
source: z.enum(['storybook', 'manual', 'ai']),
|
|
144
|
-
sourceFile: z.string().optional(),
|
|
145
|
-
confidence: z.number().min(0).max(1).optional(),
|
|
146
|
-
timestamp: z.string().datetime().optional(),
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Schema for AI-specific metadata for playground context generation
|
|
151
|
-
*/
|
|
152
|
-
export const aiMetadataSchema = z.object({
|
|
153
|
-
compositionPattern: z.enum(['compound', 'simple', 'controlled', 'wrapper']).optional(),
|
|
154
|
-
subComponents: z.array(z.string()).optional(),
|
|
155
|
-
requiredChildren: z.array(z.string()).optional(),
|
|
156
|
-
commonPatterns: z.array(z.string()).optional(),
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Schema for block definitions
|
|
161
|
-
*/
|
|
162
|
-
export const blockDefinitionSchema = z.object({
|
|
163
|
-
name: z.string().min(1),
|
|
164
|
-
description: z.string().min(1),
|
|
165
|
-
category: z.string().min(1),
|
|
166
|
-
components: z.array(z.string().min(1)).min(1),
|
|
167
|
-
code: z.string().min(1),
|
|
168
|
-
tags: z.array(z.string()).optional(),
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
export const fragmentDefinitionSchema = z.object({
|
|
172
|
-
component: z.any(), // Allow any component type (function, class, forwardRef, etc.)
|
|
173
|
-
meta: fragmentMetaSchema,
|
|
174
|
-
usage: fragmentUsageSchema,
|
|
175
|
-
props: z.record(propDefinitionSchema),
|
|
176
|
-
relations: z.array(componentRelationSchema).optional(),
|
|
177
|
-
variants: z.array(fragmentVariantSchema), // Allow empty variants array
|
|
178
|
-
contract: fragmentContractSchema.optional(),
|
|
179
|
-
ai: aiMetadataSchema.optional(),
|
|
180
|
-
_generated: fragmentGeneratedSchema.optional(),
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Config schema - validates required fields, passes through optional config objects.
|
|
185
|
-
* Type definitions are in types.ts - schema just ensures basic structure.
|
|
186
|
-
*/
|
|
187
|
-
export const fragmentsConfigSchema = z.object({
|
|
188
|
-
include: z.array(z.string()).min(1),
|
|
189
|
-
exclude: z.array(z.string()).optional(),
|
|
190
|
-
components: z.array(z.string()).optional(),
|
|
191
|
-
outFile: z.string().optional(),
|
|
192
|
-
framework: z.enum(['react', 'vue', 'svelte']).optional(),
|
|
193
|
-
figmaFile: z.string().url().optional(),
|
|
194
|
-
figmaToken: z.string().optional(),
|
|
195
|
-
screenshots: z.object({}).passthrough().optional(),
|
|
196
|
-
service: z.object({}).passthrough().optional(),
|
|
197
|
-
registry: z.object({}).passthrough().optional(),
|
|
198
|
-
tokens: z.object({
|
|
199
|
-
include: z.array(z.string()).min(1),
|
|
200
|
-
}).passthrough().optional(),
|
|
201
|
-
snippets: z.object({
|
|
202
|
-
mode: z.enum(['warn', 'error']).optional(),
|
|
203
|
-
scope: z.enum(['snippet', 'snippet+render']).optional(),
|
|
204
|
-
requireFullSnippet: z.boolean().optional(),
|
|
205
|
-
allowedExternalModules: z.array(z.string().min(1)).optional(),
|
|
206
|
-
}).optional(),
|
|
207
|
-
performance: z.union([
|
|
208
|
-
z.enum(['strict', 'standard', 'relaxed']),
|
|
209
|
-
z.object({
|
|
210
|
-
preset: z.enum(['strict', 'standard', 'relaxed']).optional(),
|
|
211
|
-
budgets: z.object({
|
|
212
|
-
bundleSize: z.number().positive().optional(),
|
|
213
|
-
}).optional(),
|
|
214
|
-
}),
|
|
215
|
-
]).optional(),
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* @deprecated Use blockDefinitionSchema instead
|
|
220
|
-
*/
|
|
221
|
-
export const recipeDefinitionSchema = blockDefinitionSchema;
|