prev-cli 0.12.2 → 0.12.4
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/package.json +1 -1
- package/src/theme/Preview.tsx +137 -52
- package/src/theme/index.ts +2 -0
- package/src/theme/styles.css +6 -0
package/package.json
CHANGED
package/src/theme/Preview.tsx
CHANGED
|
@@ -217,7 +217,7 @@ export function Preview({ src, height = 400, title, mode = 'wasm' }: PreviewProp
|
|
|
217
217
|
setDeviceMode('desktop') // Clear device mode when using custom
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
-
// Icon button component
|
|
220
|
+
// Icon button component - using inline styles since Tailwind isn't enabled for docs
|
|
221
221
|
const IconButton = ({
|
|
222
222
|
onClick,
|
|
223
223
|
active,
|
|
@@ -231,11 +231,18 @@ export function Preview({ src, height = 400, title, mode = 'wasm' }: PreviewProp
|
|
|
231
231
|
}) => (
|
|
232
232
|
<button
|
|
233
233
|
onClick={onClick}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
234
|
+
style={{
|
|
235
|
+
padding: '6px',
|
|
236
|
+
borderRadius: '4px',
|
|
237
|
+
border: 'none',
|
|
238
|
+
cursor: 'pointer',
|
|
239
|
+
display: 'flex',
|
|
240
|
+
alignItems: 'center',
|
|
241
|
+
justifyContent: 'center',
|
|
242
|
+
transition: 'background-color 0.15s, color 0.15s',
|
|
243
|
+
backgroundColor: active ? '#3b82f6' : 'transparent',
|
|
244
|
+
color: active ? '#fff' : '#71717a',
|
|
245
|
+
}}
|
|
239
246
|
title={btnTitle}
|
|
240
247
|
aria-label={btnTitle}
|
|
241
248
|
>
|
|
@@ -243,30 +250,47 @@ export function Preview({ src, height = 400, title, mode = 'wasm' }: PreviewProp
|
|
|
243
250
|
</button>
|
|
244
251
|
)
|
|
245
252
|
|
|
246
|
-
// Floating DevTools Pill
|
|
253
|
+
// Floating DevTools Pill - using inline styles since Tailwind isn't enabled for docs
|
|
247
254
|
const DevToolsPill = () => {
|
|
248
|
-
const
|
|
255
|
+
const baseStyle: React.CSSProperties = {
|
|
256
|
+
position: 'absolute',
|
|
257
|
+
zIndex: 50,
|
|
258
|
+
display: 'flex',
|
|
259
|
+
alignItems: 'center',
|
|
260
|
+
gap: '2px',
|
|
261
|
+
padding: '4px 6px',
|
|
262
|
+
backgroundColor: '#fff',
|
|
263
|
+
borderRadius: '8px',
|
|
264
|
+
boxShadow: '0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -1px rgba(0,0,0,0.06)',
|
|
265
|
+
border: '1px solid #e4e4e7',
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const positionStyle: React.CSSProperties = pillPosition.x === 0 && pillPosition.y === 0
|
|
249
269
|
? { bottom: 12, right: 12 }
|
|
250
270
|
: { left: pillPosition.x, top: pillPosition.y }
|
|
251
271
|
|
|
272
|
+
const dividerStyle: React.CSSProperties = {
|
|
273
|
+
width: '1px',
|
|
274
|
+
height: '16px',
|
|
275
|
+
backgroundColor: '#e4e4e7',
|
|
276
|
+
margin: '0 2px',
|
|
277
|
+
}
|
|
278
|
+
|
|
252
279
|
return (
|
|
253
280
|
<div
|
|
254
281
|
ref={pillRef}
|
|
255
|
-
|
|
256
|
-
isDragging ? 'cursor-grabbing' : ''
|
|
257
|
-
}`}
|
|
258
|
-
style={pillStyle}
|
|
282
|
+
style={{ ...baseStyle, ...positionStyle, cursor: isDragging ? 'grabbing' : undefined }}
|
|
259
283
|
>
|
|
260
284
|
{/* Drag handle */}
|
|
261
285
|
<div
|
|
262
286
|
onMouseDown={handleMouseDown}
|
|
263
|
-
|
|
287
|
+
style={{ padding: '4px', cursor: 'grab', color: '#a1a1aa' }}
|
|
264
288
|
title="Drag to move"
|
|
265
289
|
>
|
|
266
|
-
<GripVertical
|
|
290
|
+
<GripVertical style={{ width: 12, height: 12 }} />
|
|
267
291
|
</div>
|
|
268
292
|
|
|
269
|
-
<div
|
|
293
|
+
<div style={dividerStyle} />
|
|
270
294
|
|
|
271
295
|
{/* Device modes */}
|
|
272
296
|
<IconButton
|
|
@@ -274,7 +298,7 @@ export function Preview({ src, height = 400, title, mode = 'wasm' }: PreviewProp
|
|
|
274
298
|
active={deviceMode === 'mobile' && customWidth === null}
|
|
275
299
|
title="Mobile (375px)"
|
|
276
300
|
>
|
|
277
|
-
<Smartphone
|
|
301
|
+
<Smartphone style={{ width: 14, height: 14 }} />
|
|
278
302
|
</IconButton>
|
|
279
303
|
|
|
280
304
|
<IconButton
|
|
@@ -282,7 +306,7 @@ export function Preview({ src, height = 400, title, mode = 'wasm' }: PreviewProp
|
|
|
282
306
|
active={deviceMode === 'tablet' && customWidth === null}
|
|
283
307
|
title="Tablet (768px)"
|
|
284
308
|
>
|
|
285
|
-
<Tablet
|
|
309
|
+
<Tablet style={{ width: 14, height: 14 }} />
|
|
286
310
|
</IconButton>
|
|
287
311
|
|
|
288
312
|
<IconButton
|
|
@@ -290,31 +314,43 @@ export function Preview({ src, height = 400, title, mode = 'wasm' }: PreviewProp
|
|
|
290
314
|
active={deviceMode === 'desktop' && customWidth === null}
|
|
291
315
|
title="Desktop (100%)"
|
|
292
316
|
>
|
|
293
|
-
<Monitor
|
|
317
|
+
<Monitor style={{ width: 14, height: 14 }} />
|
|
294
318
|
</IconButton>
|
|
295
319
|
|
|
296
|
-
<div
|
|
320
|
+
<div style={dividerStyle} />
|
|
297
321
|
|
|
298
322
|
{/* Width slider toggle */}
|
|
299
|
-
<div
|
|
323
|
+
<div style={{ position: 'relative' }}>
|
|
300
324
|
<IconButton
|
|
301
325
|
onClick={() => setShowSlider(!showSlider)}
|
|
302
326
|
active={showSlider || customWidth !== null}
|
|
303
327
|
title="Custom width"
|
|
304
328
|
>
|
|
305
|
-
<SlidersHorizontal
|
|
329
|
+
<SlidersHorizontal style={{ width: 14, height: 14 }} />
|
|
306
330
|
</IconButton>
|
|
307
331
|
|
|
308
332
|
{/* Slider popup */}
|
|
309
333
|
{showSlider && (
|
|
310
|
-
<div
|
|
311
|
-
|
|
312
|
-
|
|
334
|
+
<div style={{
|
|
335
|
+
position: 'absolute',
|
|
336
|
+
bottom: '100%',
|
|
337
|
+
left: '50%',
|
|
338
|
+
transform: 'translateX(-50%)',
|
|
339
|
+
marginBottom: '8px',
|
|
340
|
+
padding: '12px',
|
|
341
|
+
backgroundColor: '#fff',
|
|
342
|
+
borderRadius: '8px',
|
|
343
|
+
boxShadow: '0 4px 6px -1px rgba(0,0,0,0.1)',
|
|
344
|
+
border: '1px solid #e4e4e7',
|
|
345
|
+
minWidth: '192px',
|
|
346
|
+
}}>
|
|
347
|
+
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '8px' }}>
|
|
348
|
+
<span style={{ fontSize: '12px', color: '#71717a' }}>Width: {customWidth ?? currentWidth ?? '100%'}px</span>
|
|
313
349
|
<button
|
|
314
350
|
onClick={() => setShowSlider(false)}
|
|
315
|
-
|
|
351
|
+
style={{ padding: '2px', background: 'none', border: 'none', cursor: 'pointer', color: '#a1a1aa' }}
|
|
316
352
|
>
|
|
317
|
-
<X
|
|
353
|
+
<X style={{ width: 12, height: 12 }} />
|
|
318
354
|
</button>
|
|
319
355
|
</div>
|
|
320
356
|
<input
|
|
@@ -323,9 +359,9 @@ export function Preview({ src, height = 400, title, mode = 'wasm' }: PreviewProp
|
|
|
323
359
|
max={1920}
|
|
324
360
|
value={customWidth ?? (typeof currentWidth === 'number' ? currentWidth : 1920)}
|
|
325
361
|
onChange={(e) => handleSliderChange(parseInt(e.target.value))}
|
|
326
|
-
|
|
362
|
+
style={{ width: '100%', accentColor: '#3b82f6' }}
|
|
327
363
|
/>
|
|
328
|
-
<div
|
|
364
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', fontSize: '12px', color: '#a1a1aa', marginTop: '4px' }}>
|
|
329
365
|
<span>320px</span>
|
|
330
366
|
<span>1920px</span>
|
|
331
367
|
</div>
|
|
@@ -333,7 +369,7 @@ export function Preview({ src, height = 400, title, mode = 'wasm' }: PreviewProp
|
|
|
333
369
|
)}
|
|
334
370
|
</div>
|
|
335
371
|
|
|
336
|
-
<div
|
|
372
|
+
<div style={dividerStyle} />
|
|
337
373
|
|
|
338
374
|
{/* Dark mode toggle */}
|
|
339
375
|
<IconButton
|
|
@@ -341,7 +377,7 @@ export function Preview({ src, height = 400, title, mode = 'wasm' }: PreviewProp
|
|
|
341
377
|
active={isDarkMode}
|
|
342
378
|
title={isDarkMode ? 'Light mode' : 'Dark mode'}
|
|
343
379
|
>
|
|
344
|
-
{isDarkMode ? <Moon
|
|
380
|
+
{isDarkMode ? <Moon style={{ width: 14, height: 14 }} /> : <SunMedium style={{ width: 14, height: 14 }} />}
|
|
345
381
|
</IconButton>
|
|
346
382
|
|
|
347
383
|
{/* Fullscreen toggle */}
|
|
@@ -350,7 +386,7 @@ export function Preview({ src, height = 400, title, mode = 'wasm' }: PreviewProp
|
|
|
350
386
|
active={isFullscreen}
|
|
351
387
|
title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}
|
|
352
388
|
>
|
|
353
|
-
{isFullscreen ? <Minimize2
|
|
389
|
+
{isFullscreen ? <Minimize2 style={{ width: 14, height: 14 }} /> : <Maximize2 style={{ width: 14, height: 14 }} />}
|
|
354
390
|
</IconButton>
|
|
355
391
|
</div>
|
|
356
392
|
)
|
|
@@ -370,11 +406,22 @@ export function Preview({ src, height = 400, title, mode = 'wasm' }: PreviewProp
|
|
|
370
406
|
|
|
371
407
|
if (isFullscreen) {
|
|
372
408
|
return (
|
|
373
|
-
<div
|
|
409
|
+
<div style={{
|
|
410
|
+
position: 'fixed',
|
|
411
|
+
inset: 0,
|
|
412
|
+
zIndex: 40,
|
|
413
|
+
backgroundColor: '#f4f4f5',
|
|
414
|
+
display: 'flex',
|
|
415
|
+
alignItems: 'flex-start',
|
|
416
|
+
justifyContent: 'center',
|
|
417
|
+
overflow: 'auto',
|
|
418
|
+
}}>
|
|
374
419
|
{/* Checkered background pattern */}
|
|
375
420
|
<div
|
|
376
|
-
className="absolute inset-0 opacity-50"
|
|
377
421
|
style={{
|
|
422
|
+
position: 'absolute',
|
|
423
|
+
inset: 0,
|
|
424
|
+
opacity: 0.5,
|
|
378
425
|
backgroundImage: 'linear-gradient(45deg, #e5e5e5 25%, transparent 25%), linear-gradient(-45deg, #e5e5e5 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #e5e5e5 75%), linear-gradient(-45deg, transparent 75%, #e5e5e5 75%)',
|
|
379
426
|
backgroundSize: '20px 20px',
|
|
380
427
|
backgroundPosition: '0 0, 0 10px, 10px -10px, -10px 0px',
|
|
@@ -383,13 +430,19 @@ export function Preview({ src, height = 400, title, mode = 'wasm' }: PreviewProp
|
|
|
383
430
|
|
|
384
431
|
{/* Iframe container */}
|
|
385
432
|
<div
|
|
386
|
-
|
|
387
|
-
|
|
433
|
+
style={{
|
|
434
|
+
position: 'relative',
|
|
435
|
+
backgroundColor: '#fff',
|
|
436
|
+
boxShadow: '0 25px 50px -12px rgba(0,0,0,0.25)',
|
|
437
|
+
transition: 'all 0.3s',
|
|
438
|
+
height: '100%',
|
|
439
|
+
...getIframeContainerStyle(),
|
|
440
|
+
}}
|
|
388
441
|
>
|
|
389
442
|
<iframe
|
|
390
443
|
ref={iframeRef}
|
|
391
444
|
src={previewUrl}
|
|
392
|
-
|
|
445
|
+
style={{ width: '100%', height: '100%', border: 'none' }}
|
|
393
446
|
title={displayTitle}
|
|
394
447
|
/>
|
|
395
448
|
</div>
|
|
@@ -402,26 +455,39 @@ export function Preview({ src, height = 400, title, mode = 'wasm' }: PreviewProp
|
|
|
402
455
|
return (
|
|
403
456
|
<div
|
|
404
457
|
ref={containerRef}
|
|
405
|
-
|
|
458
|
+
style={{
|
|
459
|
+
margin: '16px 0',
|
|
460
|
+
border: '1px solid #e4e4e7',
|
|
461
|
+
borderRadius: '8px',
|
|
462
|
+
overflow: 'hidden',
|
|
463
|
+
position: 'relative',
|
|
464
|
+
}}
|
|
406
465
|
>
|
|
407
466
|
{/* Header */}
|
|
408
|
-
<div
|
|
409
|
-
|
|
410
|
-
|
|
467
|
+
<div style={{
|
|
468
|
+
display: 'flex',
|
|
469
|
+
alignItems: 'center',
|
|
470
|
+
justifyContent: 'space-between',
|
|
471
|
+
padding: '8px 12px',
|
|
472
|
+
backgroundColor: '#fafafa',
|
|
473
|
+
borderBottom: '1px solid #e4e4e7',
|
|
474
|
+
}}>
|
|
475
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
476
|
+
<span style={{ fontSize: '14px', fontWeight: 500, color: '#52525b' }}>
|
|
411
477
|
{displayTitle}
|
|
412
478
|
</span>
|
|
413
479
|
{mode === 'wasm' && buildStatus === 'building' && (
|
|
414
|
-
<Loader2
|
|
480
|
+
<Loader2 style={{ width: 14, height: 14, color: '#3b82f6', animation: 'spin 1s linear infinite' }} />
|
|
415
481
|
)}
|
|
416
482
|
{mode === 'wasm' && buildStatus === 'error' && (
|
|
417
|
-
<span
|
|
483
|
+
<span style={{ fontSize: '12px', color: '#ef4444' }}>Error</span>
|
|
418
484
|
)}
|
|
419
485
|
</div>
|
|
420
|
-
<div
|
|
486
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
421
487
|
{mode === 'wasm' && buildTime && (
|
|
422
|
-
<span
|
|
488
|
+
<span style={{ fontSize: '12px', color: '#a1a1aa' }}>{buildTime}ms</span>
|
|
423
489
|
)}
|
|
424
|
-
<span
|
|
490
|
+
<span style={{ fontSize: '12px', color: '#a1a1aa' }}>
|
|
425
491
|
{currentWidth ? `${currentWidth}px` : '100%'}
|
|
426
492
|
</span>
|
|
427
493
|
</div>
|
|
@@ -429,8 +495,20 @@ export function Preview({ src, height = 400, title, mode = 'wasm' }: PreviewProp
|
|
|
429
495
|
|
|
430
496
|
{/* Build error display */}
|
|
431
497
|
{mode === 'wasm' && buildError && (
|
|
432
|
-
<div
|
|
433
|
-
|
|
498
|
+
<div style={{
|
|
499
|
+
padding: '8px 12px',
|
|
500
|
+
backgroundColor: '#fef2f2',
|
|
501
|
+
borderBottom: '1px solid #fecaca',
|
|
502
|
+
}}>
|
|
503
|
+
<pre style={{
|
|
504
|
+
fontSize: '12px',
|
|
505
|
+
color: '#dc2626',
|
|
506
|
+
whiteSpace: 'pre-wrap',
|
|
507
|
+
fontFamily: 'monospace',
|
|
508
|
+
overflow: 'auto',
|
|
509
|
+
maxHeight: '128px',
|
|
510
|
+
margin: 0,
|
|
511
|
+
}}>
|
|
434
512
|
{buildError}
|
|
435
513
|
</pre>
|
|
436
514
|
</div>
|
|
@@ -438,8 +516,9 @@ export function Preview({ src, height = 400, title, mode = 'wasm' }: PreviewProp
|
|
|
438
516
|
|
|
439
517
|
{/* Preview area with checkered background */}
|
|
440
518
|
<div
|
|
441
|
-
className="relative bg-zinc-100 dark:bg-zinc-900"
|
|
442
519
|
style={{
|
|
520
|
+
position: 'relative',
|
|
521
|
+
backgroundColor: '#f4f4f5',
|
|
443
522
|
backgroundImage: 'linear-gradient(45deg, #e5e5e5 25%, transparent 25%), linear-gradient(-45deg, #e5e5e5 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #e5e5e5 75%), linear-gradient(-45deg, transparent 75%, #e5e5e5 75%)',
|
|
444
523
|
backgroundSize: '16px 16px',
|
|
445
524
|
backgroundPosition: '0 0, 0 8px, 8px -8px, -8px 0px',
|
|
@@ -447,14 +526,20 @@ export function Preview({ src, height = 400, title, mode = 'wasm' }: PreviewProp
|
|
|
447
526
|
>
|
|
448
527
|
{/* Iframe container */}
|
|
449
528
|
<div
|
|
450
|
-
|
|
451
|
-
|
|
529
|
+
style={{
|
|
530
|
+
backgroundColor: '#fff',
|
|
531
|
+
transition: 'all 0.3s',
|
|
532
|
+
...getIframeContainerStyle(),
|
|
533
|
+
}}
|
|
452
534
|
>
|
|
453
535
|
<iframe
|
|
454
536
|
ref={iframeRef}
|
|
455
537
|
src={previewUrl}
|
|
456
|
-
style={{
|
|
457
|
-
|
|
538
|
+
style={{
|
|
539
|
+
height: typeof height === 'number' ? `${height}px` : height,
|
|
540
|
+
width: '100%',
|
|
541
|
+
border: 'none',
|
|
542
|
+
}}
|
|
458
543
|
title={displayTitle}
|
|
459
544
|
/>
|
|
460
545
|
</div>
|
package/src/theme/styles.css
CHANGED