@fragments-sdk/cli 0.5.2 → 0.7.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.js +996 -79
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-ICAIQ57V.js → chunk-6JBGU74P.js} +5 -3
- package/dist/chunk-6JBGU74P.js.map +1 -0
- package/dist/chunk-7OPWMLOE.js +1625 -0
- package/dist/chunk-7OPWMLOE.js.map +1 -0
- package/dist/{chunk-2H2JAA3U.js → chunk-CVXKXVOY.js} +3 -3
- package/dist/{chunk-2H2JAA3U.js.map → chunk-CVXKXVOY.js.map} +1 -1
- package/dist/{chunk-IOJE35DZ.js → chunk-NWQ4CJOQ.js} +3 -3
- package/dist/{chunk-2DJH4F4P.js → chunk-RVRTRESS.js} +3 -3
- package/dist/{chunk-V7YLRR4C.js → chunk-TJ34N7C7.js} +41 -4
- package/dist/{chunk-V7YLRR4C.js.map → chunk-TJ34N7C7.js.map} +1 -1
- package/dist/{chunk-XNWDI6UT.js → chunk-XHUDJNN3.js} +5 -5
- package/dist/{core-DKHB7FYV.js → core-W2HYIQW6.js} +4 -4
- package/dist/{generate-KL24VZVD.js → generate-LMTISDIJ.js} +5 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -7
- package/dist/index.js.map +1 -1
- package/dist/{init-NION5S3M.js → init-7CHRKQ7P.js} +5 -5
- package/dist/mcp-bin.js +8 -220
- package/dist/mcp-bin.js.map +1 -1
- package/dist/scan-WY23TJCP.js +12 -0
- package/dist/{service-RWUMZ3EW.js → service-T2L7VLTE.js} +5 -5
- package/dist/static-viewer-GBR7YNF3.js +12 -0
- package/dist/{test-ECPEXFDN.js → test-OJRXNDO2.js} +4 -4
- package/dist/{tokens-ITADYVPF.js → tokens-3BWDESVM.js} +6 -6
- package/dist/viewer-SUFOISZM.js +1822 -0
- package/dist/viewer-SUFOISZM.js.map +1 -0
- package/package.json +6 -5
- package/src/bin.ts +31 -0
- package/src/build.ts +147 -13
- package/src/cli-commands.ts +18 -0
- package/src/commands/__tests__/a11y-scoring.test.ts +278 -0
- package/src/commands/a11y-report.ts +625 -0
- package/src/commands/a11y.ts +168 -14
- package/src/commands/build.ts +16 -0
- package/src/commands/graph.ts +274 -0
- package/src/core/auto-props.ts +464 -0
- package/src/core/composition.ts +64 -1
- package/src/core/graph-extractor.test.ts +542 -0
- package/src/core/graph-extractor.ts +601 -0
- package/src/core/importAnalyzer.ts +5 -0
- package/src/core/schema.ts +2 -0
- package/src/core/types.ts +3 -1
- package/src/index.ts +4 -0
- package/src/mcp/server.ts +13 -220
- package/src/theme/__tests__/component-contrast.test.ts +338 -0
- package/src/theme/__tests__/contrast-validation.test.ts +326 -0
- package/src/theme/contrast.test.ts +331 -0
- package/src/theme/contrast.ts +246 -0
- package/src/theme/generator.ts +213 -1
- package/src/theme/index.ts +16 -0
- package/src/theme/types.ts +51 -0
- package/src/viewer/__tests__/a11y-fixes.test.ts +358 -0
- package/src/viewer/__tests__/viewer-integration.test.ts +2 -7
- package/src/viewer/components/AccessibilityPanel.tsx +493 -433
- package/src/viewer/components/ActionCapture.tsx +1 -1
- package/src/viewer/components/ActionsPanel.tsx +142 -183
- package/src/viewer/components/App.tsx +276 -183
- package/src/viewer/components/BottomPanel.tsx +40 -80
- package/src/viewer/components/CodePanel.tsx +9 -87
- package/src/viewer/components/CommandPalette.tsx +117 -74
- package/src/viewer/components/ComponentGraph.tsx +143 -126
- package/src/viewer/components/ComponentHeader.tsx +46 -43
- package/src/viewer/components/ContractPanel.tsx +124 -117
- package/src/viewer/components/ErrorBoundary.tsx +47 -35
- package/src/viewer/components/FigmaEmbed.tsx +18 -13
- package/src/viewer/components/FragmentEditor.tsx +126 -63
- package/src/viewer/components/HealthDashboard.tsx +146 -171
- package/src/viewer/components/HmrStatusIndicator.tsx +31 -41
- package/src/viewer/components/Icons.tsx +151 -98
- package/src/viewer/components/InteractionsPanel.tsx +317 -264
- package/src/viewer/components/IsolatedPreviewFrame.tsx +52 -27
- package/src/viewer/components/IsolatedRender.tsx +12 -6
- package/src/viewer/components/KeyboardShortcutsHelp.tsx +34 -70
- package/src/viewer/components/LandingPage.tsx +285 -305
- package/src/viewer/components/Layout.tsx +12 -10
- package/src/viewer/components/LeftSidebar.tsx +103 -155
- package/src/viewer/components/MultiViewportPreview.tsx +254 -63
- package/src/viewer/components/PreviewArea.tsx +113 -44
- package/src/viewer/components/PreviewFrameHost.tsx +36 -6
- package/src/viewer/components/PreviewPane.tsx +2 -3
- package/src/viewer/components/PreviewToolbar.tsx +109 -105
- package/src/viewer/components/PropsEditor.tsx +154 -74
- package/src/viewer/components/PropsTable.tsx +95 -82
- package/src/viewer/components/RelationsSection.tsx +71 -40
- package/src/viewer/components/ResizablePanel.tsx +158 -55
- package/src/viewer/components/RightSidebar.tsx +46 -56
- package/src/viewer/components/ScreenshotButton.tsx +12 -12
- package/src/viewer/components/SkeletonLoader.tsx +99 -83
- package/src/viewer/components/StoryRenderer.tsx +4 -11
- package/src/viewer/components/Toast.tsx +3 -67
- package/src/viewer/components/TokenStylePanel.tsx +136 -118
- package/src/viewer/components/UsageSection.tsx +26 -26
- package/src/viewer/components/VariantMatrix.tsx +140 -47
- package/src/viewer/components/VariantTabs.tsx +24 -68
- package/src/viewer/components/ViewportSelector.tsx +121 -114
- package/src/viewer/constants/ui.ts +23 -22
- package/src/viewer/entry.tsx +8 -3
- package/src/viewer/index.ts +3 -6
- package/src/viewer/preview-frame.html +43 -18
- package/src/viewer/server.ts +7 -16
- package/src/viewer/styles/globals.css +46 -85
- package/src/viewer/utils/a11y-fixes.ts +53 -30
- package/dist/chunk-ICAIQ57V.js.map +0 -1
- package/dist/chunk-U4GQ2JTD.js +0 -832
- package/dist/chunk-U4GQ2JTD.js.map +0 -1
- package/dist/scan-ESEXV7LF.js +0 -12
- package/dist/static-viewer-O37MJ5B6.js +0 -12
- package/dist/viewer-YDGFDTK5.js +0 -11104
- package/dist/viewer-YDGFDTK5.js.map +0 -1
- package/src/viewer/postcss.config.js +0 -6
- package/src/viewer/tailwind.config.js +0 -37
- /package/dist/{chunk-IOJE35DZ.js.map → chunk-NWQ4CJOQ.js.map} +0 -0
- /package/dist/{chunk-2DJH4F4P.js.map → chunk-RVRTRESS.js.map} +0 -0
- /package/dist/{chunk-XNWDI6UT.js.map → chunk-XHUDJNN3.js.map} +0 -0
- /package/dist/{core-DKHB7FYV.js.map → core-W2HYIQW6.js.map} +0 -0
- /package/dist/{generate-KL24VZVD.js.map → generate-LMTISDIJ.js.map} +0 -0
- /package/dist/{init-NION5S3M.js.map → init-7CHRKQ7P.js.map} +0 -0
- /package/dist/{scan-ESEXV7LF.js.map → scan-WY23TJCP.js.map} +0 -0
- /package/dist/{service-RWUMZ3EW.js.map → service-T2L7VLTE.js.map} +0 -0
- /package/dist/{static-viewer-O37MJ5B6.js.map → static-viewer-GBR7YNF3.js.map} +0 -0
- /package/dist/{test-ECPEXFDN.js.map → test-OJRXNDO2.js.map} +0 -0
- /package/dist/{tokens-ITADYVPF.js.map → tokens-3BWDESVM.js.map} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { useEffect, useCallback } from 'react';
|
|
2
|
+
import { Button, Menu, Stack, Separator } from '@fragments/ui';
|
|
3
3
|
import {
|
|
4
4
|
ZOOM_LEVELS,
|
|
5
5
|
type ZoomLevel,
|
|
@@ -12,13 +12,62 @@ export type { ZoomLevel, BackgroundOption };
|
|
|
12
12
|
export { getBackgroundStyle } from '../constants/ui.js';
|
|
13
13
|
|
|
14
14
|
// Background options with display metadata
|
|
15
|
-
const BACKGROUND_OPTIONS_UI: { value: BackgroundOption; label: string
|
|
16
|
-
{ value: 'white', label: 'White'
|
|
17
|
-
{ value: 'black', label: 'Black'
|
|
18
|
-
{ value: 'checkerboard', label: 'Checkerboard'
|
|
19
|
-
{ value: 'transparent', label: 'Transparent'
|
|
15
|
+
const BACKGROUND_OPTIONS_UI: { value: BackgroundOption; label: string }[] = [
|
|
16
|
+
{ value: 'white', label: 'White' },
|
|
17
|
+
{ value: 'black', label: 'Black' },
|
|
18
|
+
{ value: 'checkerboard', label: 'Checkerboard' },
|
|
19
|
+
{ value: 'transparent', label: 'Transparent' },
|
|
20
20
|
];
|
|
21
21
|
|
|
22
|
+
function BackgroundSwatch({ background }: { background: BackgroundOption }) {
|
|
23
|
+
const baseStyle = {
|
|
24
|
+
width: '14px',
|
|
25
|
+
height: '14px',
|
|
26
|
+
borderRadius: '4px',
|
|
27
|
+
border: '1px solid var(--border)',
|
|
28
|
+
flexShrink: 0,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
if (background === 'white') {
|
|
32
|
+
return <span aria-hidden="true" style={{ ...baseStyle, backgroundColor: '#ffffff' }} />;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (background === 'black') {
|
|
36
|
+
return <span aria-hidden="true" style={{ ...baseStyle, backgroundColor: '#171717', borderColor: '#2a2a2a' }} />;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (background === 'checkerboard') {
|
|
40
|
+
return (
|
|
41
|
+
<span
|
|
42
|
+
aria-hidden="true"
|
|
43
|
+
style={{
|
|
44
|
+
...baseStyle,
|
|
45
|
+
backgroundColor: '#ffffff',
|
|
46
|
+
backgroundImage: `
|
|
47
|
+
linear-gradient(45deg, #d4d4d8 25%, transparent 25%),
|
|
48
|
+
linear-gradient(-45deg, #d4d4d8 25%, transparent 25%),
|
|
49
|
+
linear-gradient(45deg, transparent 75%, #d4d4d8 75%),
|
|
50
|
+
linear-gradient(-45deg, transparent 75%, #d4d4d8 75%)
|
|
51
|
+
`,
|
|
52
|
+
backgroundSize: '8px 8px',
|
|
53
|
+
backgroundPosition: '0 0, 0 4px, 4px -4px, -4px 0',
|
|
54
|
+
}}
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<span
|
|
61
|
+
aria-hidden="true"
|
|
62
|
+
style={{
|
|
63
|
+
...baseStyle,
|
|
64
|
+
backgroundColor: 'transparent',
|
|
65
|
+
backgroundImage: 'linear-gradient(135deg, transparent 42%, var(--text-tertiary) 43%, var(--text-tertiary) 57%, transparent 58%)',
|
|
66
|
+
}}
|
|
67
|
+
/>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
22
71
|
interface PreviewToolbarProps {
|
|
23
72
|
zoom: ZoomLevel;
|
|
24
73
|
background: BackgroundOption;
|
|
@@ -32,9 +81,6 @@ export function PreviewToolbar({
|
|
|
32
81
|
onZoomChange,
|
|
33
82
|
onBackgroundChange,
|
|
34
83
|
}: PreviewToolbarProps) {
|
|
35
|
-
const [zoomOpen, setZoomOpen] = useState(false);
|
|
36
|
-
const [bgOpen, setBgOpen] = useState(false);
|
|
37
|
-
|
|
38
84
|
// Keyboard shortcuts for zoom
|
|
39
85
|
const handleKeyDown = useCallback((e: KeyboardEvent) => {
|
|
40
86
|
// Don't handle if in input/textarea
|
|
@@ -66,111 +112,69 @@ export function PreviewToolbar({
|
|
|
66
112
|
return () => document.removeEventListener('keydown', handleKeyDown);
|
|
67
113
|
}, [handleKeyDown]);
|
|
68
114
|
|
|
69
|
-
// Close dropdowns when clicking outside
|
|
70
|
-
useEffect(() => {
|
|
71
|
-
const handleClick = () => {
|
|
72
|
-
setZoomOpen(false);
|
|
73
|
-
setBgOpen(false);
|
|
74
|
-
};
|
|
75
|
-
if (zoomOpen || bgOpen) {
|
|
76
|
-
document.addEventListener('click', handleClick);
|
|
77
|
-
return () => document.removeEventListener('click', handleClick);
|
|
78
|
-
}
|
|
79
|
-
}, [zoomOpen, bgOpen]);
|
|
80
|
-
|
|
81
115
|
return (
|
|
82
|
-
<
|
|
116
|
+
<Stack direction="row" gap="sm" align="center">
|
|
83
117
|
{/* Zoom dropdown */}
|
|
84
|
-
<
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
>
|
|
99
|
-
<
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
{zoomOpen && (
|
|
104
|
-
<div className="absolute top-full left-0 mt-1 py-1 min-w-[80px] bg-[--bg-elevated] border border-[--border] rounded-lg shadow-lg z-50">
|
|
118
|
+
<Menu>
|
|
119
|
+
<Menu.Trigger asChild>
|
|
120
|
+
<Button variant="ghost" size="sm" title="Zoom level (+/-/0)">
|
|
121
|
+
<Stack direction="row" gap="xs" align="center">
|
|
122
|
+
<span style={{ display: 'inline-flex', width: '14px', height: '14px' }}>
|
|
123
|
+
<ZoomIcon />
|
|
124
|
+
</span>
|
|
125
|
+
<span>{zoom}%</span>
|
|
126
|
+
<span style={{ display: 'inline-flex', width: '12px', height: '12px' }}>
|
|
127
|
+
<ChevronDownIcon />
|
|
128
|
+
</span>
|
|
129
|
+
</Stack>
|
|
130
|
+
</Button>
|
|
131
|
+
</Menu.Trigger>
|
|
132
|
+
<Menu.Content side="bottom" align="start">
|
|
133
|
+
<Menu.RadioGroup
|
|
134
|
+
value={String(zoom)}
|
|
135
|
+
onValueChange={(value: string) => onZoomChange(Number(value) as ZoomLevel)}
|
|
136
|
+
>
|
|
105
137
|
{ZOOM_LEVELS.map((level) => (
|
|
106
|
-
<
|
|
107
|
-
key={level}
|
|
108
|
-
onClick={(e) => {
|
|
109
|
-
e.stopPropagation();
|
|
110
|
-
onZoomChange(level);
|
|
111
|
-
setZoomOpen(false);
|
|
112
|
-
}}
|
|
113
|
-
className={clsx(
|
|
114
|
-
'w-full px-3 py-1.5 text-xs text-left',
|
|
115
|
-
'hover:bg-[--bg-hover] transition-colors',
|
|
116
|
-
level === zoom ? 'text-[--color-accent] font-medium' : 'text-secondary'
|
|
117
|
-
)}
|
|
118
|
-
>
|
|
138
|
+
<Menu.RadioItem key={level} value={String(level)}>
|
|
119
139
|
{level}%
|
|
120
|
-
</
|
|
140
|
+
</Menu.RadioItem>
|
|
121
141
|
))}
|
|
122
|
-
</
|
|
123
|
-
|
|
124
|
-
</
|
|
142
|
+
</Menu.RadioGroup>
|
|
143
|
+
</Menu.Content>
|
|
144
|
+
</Menu>
|
|
125
145
|
|
|
126
146
|
{/* Divider */}
|
|
127
|
-
<
|
|
147
|
+
<Separator orientation="vertical" />
|
|
128
148
|
|
|
129
149
|
{/* Background selector */}
|
|
130
|
-
<
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
</span>
|
|
148
|
-
<span className="capitalize">{background}</span>
|
|
149
|
-
<ChevronDownIcon className="w-3 h-3" />
|
|
150
|
-
</button>
|
|
151
|
-
{bgOpen && (
|
|
152
|
-
<div className="absolute top-full left-0 mt-1 py-1 min-w-[120px] bg-[--bg-elevated] border border-[--border] rounded-lg shadow-lg z-50">
|
|
150
|
+
<Menu>
|
|
151
|
+
<Menu.Trigger asChild>
|
|
152
|
+
<Button variant="ghost" size="sm" title="Background color">
|
|
153
|
+
<Stack direction="row" gap="xs" align="center">
|
|
154
|
+
<BackgroundSwatch background={background} />
|
|
155
|
+
<span>{BACKGROUND_OPTIONS_UI.find(o => o.value === background)?.label}</span>
|
|
156
|
+
<span style={{ display: 'inline-flex', width: '12px', height: '12px' }}>
|
|
157
|
+
<ChevronDownIcon />
|
|
158
|
+
</span>
|
|
159
|
+
</Stack>
|
|
160
|
+
</Button>
|
|
161
|
+
</Menu.Trigger>
|
|
162
|
+
<Menu.Content side="bottom" align="start">
|
|
163
|
+
<Menu.RadioGroup
|
|
164
|
+
value={background}
|
|
165
|
+
onValueChange={(value: string) => onBackgroundChange(value as BackgroundOption)}
|
|
166
|
+
>
|
|
153
167
|
{BACKGROUND_OPTIONS_UI.map((option) => (
|
|
154
|
-
<
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}}
|
|
161
|
-
className={clsx(
|
|
162
|
-
'w-full px-3 py-1.5 text-xs text-left flex items-center gap-2',
|
|
163
|
-
'hover:bg-[--bg-hover] transition-colors',
|
|
164
|
-
option.value === background ? 'text-[--color-accent] font-medium' : 'text-secondary'
|
|
165
|
-
)}
|
|
166
|
-
>
|
|
167
|
-
<span className="text-sm">{option.icon}</span>
|
|
168
|
-
{option.label}
|
|
169
|
-
</button>
|
|
168
|
+
<Menu.RadioItem key={option.value} value={option.value}>
|
|
169
|
+
<Stack direction="row" gap="sm" align="center">
|
|
170
|
+
<BackgroundSwatch background={option.value} />
|
|
171
|
+
{option.label}
|
|
172
|
+
</Stack>
|
|
173
|
+
</Menu.RadioItem>
|
|
170
174
|
))}
|
|
171
|
-
</
|
|
172
|
-
|
|
173
|
-
</
|
|
174
|
-
</
|
|
175
|
+
</Menu.RadioGroup>
|
|
176
|
+
</Menu.Content>
|
|
177
|
+
</Menu>
|
|
178
|
+
</Stack>
|
|
175
179
|
);
|
|
176
180
|
}
|