@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
|
@@ -70,6 +70,8 @@ export function MultiViewportPreview({
|
|
|
70
70
|
}: MultiViewportPreviewProps) {
|
|
71
71
|
const [selectedMobile, setSelectedMobile] = useState<MobilePreset>(MOBILE_PRESETS[0]);
|
|
72
72
|
const [showMobileDropdown, setShowMobileDropdown] = useState(false);
|
|
73
|
+
const [hoveredPreset, setHoveredPreset] = useState<string | null>(null);
|
|
74
|
+
const [mobileButtonHovered, setMobileButtonHovered] = useState(false);
|
|
73
75
|
|
|
74
76
|
// Build viewports with selected mobile preset
|
|
75
77
|
const viewports: ViewportConfig[] = [
|
|
@@ -79,28 +81,72 @@ export function MultiViewportPreview({
|
|
|
79
81
|
];
|
|
80
82
|
|
|
81
83
|
return (
|
|
82
|
-
<div
|
|
84
|
+
<div style={{
|
|
85
|
+
height: '100%',
|
|
86
|
+
display: 'flex',
|
|
87
|
+
flexDirection: 'column',
|
|
88
|
+
background: 'var(--bg-primary)',
|
|
89
|
+
}}>
|
|
83
90
|
{/* Header */}
|
|
84
|
-
<div
|
|
91
|
+
<div style={{
|
|
92
|
+
flexShrink: 0,
|
|
93
|
+
padding: '12px 16px',
|
|
94
|
+
borderBottom: '1px solid var(--border)',
|
|
95
|
+
background: 'var(--bg-secondary)',
|
|
96
|
+
display: 'flex',
|
|
97
|
+
alignItems: 'center',
|
|
98
|
+
justifyContent: 'center',
|
|
99
|
+
gap: 32,
|
|
100
|
+
}}>
|
|
85
101
|
{/* Mobile with dropdown */}
|
|
86
|
-
<div
|
|
102
|
+
<div style={{ position: 'relative' }}>
|
|
87
103
|
<button
|
|
88
104
|
onClick={() => setShowMobileDropdown(!showMobileDropdown)}
|
|
89
|
-
|
|
105
|
+
onMouseEnter={() => setMobileButtonHovered(true)}
|
|
106
|
+
onMouseLeave={() => setMobileButtonHovered(false)}
|
|
107
|
+
style={{
|
|
108
|
+
display: 'flex',
|
|
109
|
+
alignItems: 'center',
|
|
110
|
+
gap: 8,
|
|
111
|
+
fontSize: 14,
|
|
112
|
+
padding: '4px 8px',
|
|
113
|
+
borderRadius: 4,
|
|
114
|
+
transition: 'background-color 0.15s',
|
|
115
|
+
background: mobileButtonHovered ? 'var(--bg-hover)' : 'transparent',
|
|
116
|
+
border: 'none',
|
|
117
|
+
cursor: 'pointer',
|
|
118
|
+
color: 'inherit',
|
|
119
|
+
}}
|
|
90
120
|
>
|
|
91
|
-
<span
|
|
92
|
-
<span
|
|
93
|
-
<span
|
|
94
|
-
<ChevronDownIcon
|
|
121
|
+
<span style={{ fontSize: 18 }}>📱</span>
|
|
122
|
+
<span style={{ fontWeight: 500, color: 'var(--text-secondary)' }}>Mobile</span>
|
|
123
|
+
<span style={{ fontSize: 12, color: 'var(--text-tertiary)' }}>({selectedMobile.width}px)</span>
|
|
124
|
+
<ChevronDownIcon style={{ width: 12, height: 12, color: 'var(--text-tertiary)' }} />
|
|
95
125
|
</button>
|
|
96
126
|
|
|
97
127
|
{showMobileDropdown && (
|
|
98
128
|
<>
|
|
99
129
|
<div
|
|
100
|
-
|
|
130
|
+
style={{
|
|
131
|
+
position: 'fixed',
|
|
132
|
+
inset: 0,
|
|
133
|
+
zIndex: 10,
|
|
134
|
+
}}
|
|
101
135
|
onClick={() => setShowMobileDropdown(false)}
|
|
102
136
|
/>
|
|
103
|
-
<div
|
|
137
|
+
<div style={{
|
|
138
|
+
position: 'absolute',
|
|
139
|
+
top: '100%',
|
|
140
|
+
left: 0,
|
|
141
|
+
marginTop: 4,
|
|
142
|
+
zIndex: 20,
|
|
143
|
+
background: 'var(--bg-elevated)',
|
|
144
|
+
border: '1px solid var(--border)',
|
|
145
|
+
borderRadius: 8,
|
|
146
|
+
boxShadow: '0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)',
|
|
147
|
+
padding: '4px 0',
|
|
148
|
+
minWidth: 180,
|
|
149
|
+
}}>
|
|
104
150
|
{MOBILE_PRESETS.map((preset) => (
|
|
105
151
|
<button
|
|
106
152
|
key={preset.name}
|
|
@@ -108,12 +154,25 @@ export function MultiViewportPreview({
|
|
|
108
154
|
setSelectedMobile(preset);
|
|
109
155
|
setShowMobileDropdown(false);
|
|
110
156
|
}}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
157
|
+
onMouseEnter={() => setHoveredPreset(preset.name)}
|
|
158
|
+
onMouseLeave={() => setHoveredPreset(null)}
|
|
159
|
+
style={{
|
|
160
|
+
width: '100%',
|
|
161
|
+
padding: '6px 12px',
|
|
162
|
+
textAlign: 'left',
|
|
163
|
+
fontSize: 12,
|
|
164
|
+
transition: 'background-color 0.15s',
|
|
165
|
+
display: 'flex',
|
|
166
|
+
alignItems: 'center',
|
|
167
|
+
justifyContent: 'space-between',
|
|
168
|
+
color: selectedMobile.name === preset.name ? '#3b82f6' : 'var(--text-secondary)',
|
|
169
|
+
background: hoveredPreset === preset.name ? 'var(--bg-hover)' : 'transparent',
|
|
170
|
+
border: 'none',
|
|
171
|
+
cursor: 'pointer',
|
|
172
|
+
}}
|
|
114
173
|
>
|
|
115
174
|
<span>{preset.name}</span>
|
|
116
|
-
<span
|
|
175
|
+
<span style={{ color: 'var(--text-tertiary)' }}>{preset.width}×{preset.height}</span>
|
|
117
176
|
</button>
|
|
118
177
|
))}
|
|
119
178
|
</div>
|
|
@@ -122,23 +181,23 @@ export function MultiViewportPreview({
|
|
|
122
181
|
</div>
|
|
123
182
|
|
|
124
183
|
{/* Tablet */}
|
|
125
|
-
<div
|
|
126
|
-
<span
|
|
127
|
-
<span
|
|
128
|
-
<span
|
|
184
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 14 }}>
|
|
185
|
+
<span style={{ fontSize: 18 }}>📱</span>
|
|
186
|
+
<span style={{ fontWeight: 500, color: 'var(--text-secondary)' }}>Tablet</span>
|
|
187
|
+
<span style={{ fontSize: 12, color: 'var(--text-tertiary)' }}>(768px)</span>
|
|
129
188
|
</div>
|
|
130
189
|
|
|
131
190
|
{/* Desktop */}
|
|
132
|
-
<div
|
|
133
|
-
<span
|
|
134
|
-
<span
|
|
135
|
-
<span
|
|
191
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 14 }}>
|
|
192
|
+
<span style={{ fontSize: 18 }}>🖥️</span>
|
|
193
|
+
<span style={{ fontWeight: 500, color: 'var(--text-secondary)' }}>Desktop</span>
|
|
194
|
+
<span style={{ fontSize: 12, color: 'var(--text-tertiary)' }}>(1280px)</span>
|
|
136
195
|
</div>
|
|
137
196
|
</div>
|
|
138
197
|
|
|
139
198
|
{/* Viewport panels with horizontal scroll */}
|
|
140
|
-
<div
|
|
141
|
-
<div
|
|
199
|
+
<div style={{ flex: 1, overflowX: 'auto', overflowY: 'auto' }}>
|
|
200
|
+
<div style={{ display: 'flex', gap: 32, padding: 32, minWidth: 'max-content' }}>
|
|
142
201
|
{viewports.map((vp) => (
|
|
143
202
|
<ViewportPanel
|
|
144
203
|
key={`${vp.name}-${vp.width}`}
|
|
@@ -246,51 +305,124 @@ function DeviceMockup({
|
|
|
246
305
|
const backgroundStyle = getBackgroundStyle(background);
|
|
247
306
|
|
|
248
307
|
return (
|
|
249
|
-
<div
|
|
308
|
+
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
|
|
250
309
|
{/* Label */}
|
|
251
|
-
<div
|
|
310
|
+
<div style={{
|
|
311
|
+
marginBottom: 12,
|
|
312
|
+
fontSize: 14,
|
|
313
|
+
fontWeight: 500,
|
|
314
|
+
color: 'var(--text-tertiary)',
|
|
315
|
+
}}>
|
|
252
316
|
{label}
|
|
253
317
|
</div>
|
|
254
318
|
|
|
255
319
|
{/* Device frame */}
|
|
256
320
|
<div
|
|
257
|
-
|
|
258
|
-
|
|
321
|
+
style={{
|
|
322
|
+
position: 'relative',
|
|
323
|
+
flexShrink: 0,
|
|
324
|
+
width: `${frameWidth}px`,
|
|
325
|
+
}}
|
|
259
326
|
>
|
|
260
327
|
<div
|
|
261
|
-
className="relative rounded-[40px] bg-[#1a1a1a] p-3 shadow-2xl"
|
|
262
328
|
style={{
|
|
263
|
-
|
|
329
|
+
position: 'relative',
|
|
330
|
+
borderRadius: 40,
|
|
331
|
+
background: '#1a1a1a',
|
|
332
|
+
padding: 12,
|
|
333
|
+
boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255,255,255,0.1)',
|
|
264
334
|
}}
|
|
265
335
|
>
|
|
266
336
|
{/* Side buttons (mobile only) */}
|
|
267
337
|
{isMobile && (
|
|
268
338
|
<>
|
|
269
|
-
<div
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
339
|
+
<div style={{
|
|
340
|
+
position: 'absolute',
|
|
341
|
+
left: -3,
|
|
342
|
+
top: 96,
|
|
343
|
+
width: 3,
|
|
344
|
+
height: 32,
|
|
345
|
+
background: '#2a2a2a',
|
|
346
|
+
borderRadius: '4px 0 0 4px',
|
|
347
|
+
}} />
|
|
348
|
+
<div style={{
|
|
349
|
+
position: 'absolute',
|
|
350
|
+
left: -3,
|
|
351
|
+
top: 144,
|
|
352
|
+
width: 3,
|
|
353
|
+
height: 48,
|
|
354
|
+
background: '#2a2a2a',
|
|
355
|
+
borderRadius: '4px 0 0 4px',
|
|
356
|
+
}} />
|
|
357
|
+
<div style={{
|
|
358
|
+
position: 'absolute',
|
|
359
|
+
left: -3,
|
|
360
|
+
top: 208,
|
|
361
|
+
width: 3,
|
|
362
|
+
height: 48,
|
|
363
|
+
background: '#2a2a2a',
|
|
364
|
+
borderRadius: '4px 0 0 4px',
|
|
365
|
+
}} />
|
|
366
|
+
<div style={{
|
|
367
|
+
position: 'absolute',
|
|
368
|
+
right: -3,
|
|
369
|
+
top: 128,
|
|
370
|
+
width: 3,
|
|
371
|
+
height: 64,
|
|
372
|
+
background: '#2a2a2a',
|
|
373
|
+
borderRadius: '0 4px 4px 0',
|
|
374
|
+
}} />
|
|
273
375
|
</>
|
|
274
376
|
)}
|
|
275
377
|
|
|
276
378
|
{/* Screen container */}
|
|
277
379
|
<div
|
|
278
|
-
|
|
279
|
-
|
|
380
|
+
style={{
|
|
381
|
+
position: 'relative',
|
|
382
|
+
borderRadius: 32,
|
|
383
|
+
overflow: 'hidden',
|
|
384
|
+
background: '#ffffff',
|
|
385
|
+
height: `${screenHeight}px`,
|
|
386
|
+
width: `${width}px`,
|
|
387
|
+
}}
|
|
280
388
|
>
|
|
281
389
|
{/* Notch (mobile) or Camera (tablet) */}
|
|
282
390
|
{isMobile ? (
|
|
283
|
-
<div
|
|
284
|
-
|
|
285
|
-
|
|
391
|
+
<div style={{
|
|
392
|
+
position: 'absolute',
|
|
393
|
+
top: 0,
|
|
394
|
+
left: '50%',
|
|
395
|
+
transform: 'translateX(-50%)',
|
|
396
|
+
width: 120,
|
|
397
|
+
height: 30,
|
|
398
|
+
background: '#1a1a1a',
|
|
399
|
+
borderRadius: '0 0 16px 16px',
|
|
400
|
+
zIndex: 10,
|
|
401
|
+
display: 'flex',
|
|
402
|
+
alignItems: 'center',
|
|
403
|
+
justifyContent: 'center',
|
|
404
|
+
gap: 8,
|
|
405
|
+
}}>
|
|
406
|
+
<div style={{ width: 8, height: 8, borderRadius: '50%', background: '#2a2a2a' }} />
|
|
407
|
+
<div style={{ width: 48, height: 6, borderRadius: 9999, background: '#2a2a2a' }} />
|
|
286
408
|
</div>
|
|
287
409
|
) : (
|
|
288
|
-
<div
|
|
410
|
+
<div style={{
|
|
411
|
+
position: 'absolute',
|
|
412
|
+
top: 8,
|
|
413
|
+
left: '50%',
|
|
414
|
+
transform: 'translateX(-50%)',
|
|
415
|
+
width: 12,
|
|
416
|
+
height: 12,
|
|
417
|
+
borderRadius: '50%',
|
|
418
|
+
background: '#2a2a2a',
|
|
419
|
+
zIndex: 10,
|
|
420
|
+
}} />
|
|
289
421
|
)}
|
|
290
422
|
|
|
291
423
|
{/* Screen content */}
|
|
292
424
|
<div
|
|
293
|
-
|
|
425
|
+
style={{ width: '100%', height: '100%', overflow: 'hidden' }}
|
|
294
426
|
data-theme={previewTheme}
|
|
295
427
|
>
|
|
296
428
|
{useIframeIsolation ? (
|
|
@@ -303,11 +435,16 @@ function DeviceMockup({
|
|
|
303
435
|
minHeight={screenHeight}
|
|
304
436
|
/>
|
|
305
437
|
) : (
|
|
306
|
-
<div
|
|
438
|
+
<div style={{
|
|
439
|
+
paddingTop: isMobile ? 40 : 24,
|
|
440
|
+
paddingLeft: 16,
|
|
441
|
+
paddingRight: 16,
|
|
442
|
+
paddingBottom: 16,
|
|
443
|
+
}}>
|
|
307
444
|
<ErrorBoundary
|
|
308
445
|
componentName={componentName}
|
|
309
446
|
fallback={
|
|
310
|
-
<div
|
|
447
|
+
<div style={{ fontSize: 12, color: '#ef4444', padding: 8 }}>
|
|
311
448
|
Error rendering at {width}px
|
|
312
449
|
</div>
|
|
313
450
|
}
|
|
@@ -319,7 +456,17 @@ function DeviceMockup({
|
|
|
319
456
|
</div>
|
|
320
457
|
|
|
321
458
|
{/* Home indicator */}
|
|
322
|
-
<div
|
|
459
|
+
<div style={{
|
|
460
|
+
position: 'absolute',
|
|
461
|
+
bottom: 8,
|
|
462
|
+
left: '50%',
|
|
463
|
+
transform: 'translateX(-50%)',
|
|
464
|
+
width: 100,
|
|
465
|
+
height: 4,
|
|
466
|
+
background: 'rgba(0,0,0,0.2)',
|
|
467
|
+
borderRadius: 9999,
|
|
468
|
+
zIndex: 10,
|
|
469
|
+
}} />
|
|
323
470
|
</div>
|
|
324
471
|
</div>
|
|
325
472
|
</div>
|
|
@@ -355,31 +502,60 @@ function DesktopMockup({
|
|
|
355
502
|
const backgroundStyle = getBackgroundStyle(background);
|
|
356
503
|
|
|
357
504
|
return (
|
|
358
|
-
<div
|
|
505
|
+
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
|
|
359
506
|
{/* Label */}
|
|
360
|
-
<div
|
|
507
|
+
<div style={{
|
|
508
|
+
marginBottom: 12,
|
|
509
|
+
fontSize: 14,
|
|
510
|
+
fontWeight: 500,
|
|
511
|
+
color: 'var(--text-tertiary)',
|
|
512
|
+
}}>
|
|
361
513
|
{label}
|
|
362
514
|
</div>
|
|
363
515
|
|
|
364
516
|
{/* Monitor frame */}
|
|
365
|
-
<div
|
|
517
|
+
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
|
|
366
518
|
{/* Screen */}
|
|
367
519
|
<div
|
|
368
|
-
className="relative bg-[#1a1a1a] rounded-lg p-2 shadow-2xl"
|
|
369
520
|
style={{
|
|
370
|
-
|
|
521
|
+
position: 'relative',
|
|
522
|
+
background: '#1a1a1a',
|
|
523
|
+
borderRadius: 8,
|
|
524
|
+
padding: 8,
|
|
525
|
+
boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255,255,255,0.1)',
|
|
371
526
|
}}
|
|
372
527
|
>
|
|
373
528
|
{/* Browser chrome */}
|
|
374
|
-
<div
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
529
|
+
<div style={{
|
|
530
|
+
display: 'flex',
|
|
531
|
+
alignItems: 'center',
|
|
532
|
+
gap: 8,
|
|
533
|
+
padding: '8px 12px',
|
|
534
|
+
background: '#2a2a2a',
|
|
535
|
+
borderRadius: '6px 6px 0 0',
|
|
536
|
+
}}>
|
|
537
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
|
538
|
+
<div style={{ width: 12, height: 12, borderRadius: '50%', background: '#ff5f57' }} />
|
|
539
|
+
<div style={{ width: 12, height: 12, borderRadius: '50%', background: '#ffbd2e' }} />
|
|
540
|
+
<div style={{ width: 12, height: 12, borderRadius: '50%', background: '#28ca41' }} />
|
|
379
541
|
</div>
|
|
380
|
-
<div
|
|
381
|
-
<div
|
|
382
|
-
|
|
542
|
+
<div style={{ flex: 1, margin: '0 16px' }}>
|
|
543
|
+
<div style={{
|
|
544
|
+
height: 24,
|
|
545
|
+
background: '#3a3a3a',
|
|
546
|
+
borderRadius: 6,
|
|
547
|
+
display: 'flex',
|
|
548
|
+
alignItems: 'center',
|
|
549
|
+
justifyContent: 'center',
|
|
550
|
+
padding: '0 12px',
|
|
551
|
+
}}>
|
|
552
|
+
<span style={{
|
|
553
|
+
fontSize: 12,
|
|
554
|
+
color: '#9ca3af',
|
|
555
|
+
overflow: 'hidden',
|
|
556
|
+
textOverflow: 'ellipsis',
|
|
557
|
+
whiteSpace: 'nowrap',
|
|
558
|
+
}}>
|
|
383
559
|
localhost:6006 — {width}px
|
|
384
560
|
</span>
|
|
385
561
|
</div>
|
|
@@ -388,8 +564,12 @@ function DesktopMockup({
|
|
|
388
564
|
|
|
389
565
|
{/* Screen content */}
|
|
390
566
|
<div
|
|
391
|
-
|
|
392
|
-
|
|
567
|
+
style={{
|
|
568
|
+
overflow: 'hidden',
|
|
569
|
+
width: `${width}px`,
|
|
570
|
+
height: `${height}px`,
|
|
571
|
+
...backgroundStyle,
|
|
572
|
+
}}
|
|
393
573
|
data-theme={previewTheme}
|
|
394
574
|
>
|
|
395
575
|
{useIframeIsolation ? (
|
|
@@ -402,11 +582,11 @@ function DesktopMockup({
|
|
|
402
582
|
minHeight={height}
|
|
403
583
|
/>
|
|
404
584
|
) : (
|
|
405
|
-
<div
|
|
585
|
+
<div style={{ padding: 24 }}>
|
|
406
586
|
<ErrorBoundary
|
|
407
587
|
componentName={componentName}
|
|
408
588
|
fallback={
|
|
409
|
-
<div
|
|
589
|
+
<div style={{ fontSize: 12, color: '#ef4444', padding: 8 }}>
|
|
410
590
|
Error rendering at {width}px
|
|
411
591
|
</div>
|
|
412
592
|
}
|
|
@@ -419,8 +599,19 @@ function DesktopMockup({
|
|
|
419
599
|
</div>
|
|
420
600
|
|
|
421
601
|
{/* Monitor stand */}
|
|
422
|
-
<div
|
|
423
|
-
|
|
602
|
+
<div style={{
|
|
603
|
+
width: 80,
|
|
604
|
+
height: 16,
|
|
605
|
+
background: 'linear-gradient(to bottom, #2a2a2a, #1a1a1a)',
|
|
606
|
+
borderRadius: '0 0 2px 2px',
|
|
607
|
+
}} />
|
|
608
|
+
<div style={{
|
|
609
|
+
width: 128,
|
|
610
|
+
height: 8,
|
|
611
|
+
background: '#1a1a1a',
|
|
612
|
+
borderRadius: 9999,
|
|
613
|
+
boxShadow: '0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)',
|
|
614
|
+
}} />
|
|
424
615
|
</div>
|
|
425
616
|
</div>
|
|
426
617
|
);
|