@hyperframes/studio 0.8.103 → 0.8.105
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/assets/{hyperframes-player-DG795Hwu.js → hyperframes-player-tnfCiVdR.js} +1 -1
- package/dist/assets/{index-BiEtDkae.js → index-Ca6LZlVb.js} +1 -1
- package/dist/assets/index-Cre9X4RS.css +1 -0
- package/dist/assets/{index-BPJRf2X9.js → index-DEDhPmPD.js} +215 -215
- package/dist/assets/{index-DuCZ3pQw.js → index-zpe332hb.js} +1 -1
- package/dist/{chunk-62DDWOSH.js → chunk-EEXSYY5F.js} +19 -18
- package/dist/chunk-EEXSYY5F.js.map +1 -0
- package/dist/{chunk-6GAO75IU.js → chunk-NCUBAVGK.js} +10 -8
- package/dist/chunk-NCUBAVGK.js.map +1 -0
- package/dist/{chunk-HIGHVWYD.js → chunk-QADHJFDF.js} +2 -2
- package/dist/index.css +6 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +181 -168
- package/dist/index.html +2 -2
- package/dist/index.js +1018 -919
- package/dist/index.js.map +1 -1
- package/dist/player.js +2 -2
- package/dist/styles/tailwind-preset.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/ui.js +2 -2
- package/package.json +8 -8
- package/src/captions/components/CaptionAnimationPanel.tsx +2 -2
- package/src/captions/components/CaptionPropertyPanel.tsx +2 -2
- package/src/captions/components/CaptionTimeline.tsx +3 -3
- package/src/components/AskAgentModal.tsx +1 -1
- package/src/components/LintModal.tsx +35 -35
- package/src/components/StudioErrorBoundary.tsx +1 -1
- package/src/components/StudioHeader.dom.test.tsx +4 -4
- package/src/components/StudioHeader.tsx +2 -1
- package/src/components/StudioToast.tsx +7 -16
- package/src/components/TimelineToolPicker.tsx +1 -1
- package/src/components/TimelineToolbar.tsx +11 -11
- package/src/components/dock/Dock.tsx +1 -1
- package/src/components/dock/dock.css +9 -1
- package/src/components/editor/AnimationCard.tsx +5 -5
- package/src/components/editor/AnimationCardParts.tsx +1 -1
- package/src/components/editor/BlockParamsPanel.tsx +3 -3
- package/src/components/editor/BorderRadiusEditor.tsx +8 -15
- package/src/components/editor/CanvasContextMenu.tsx +1 -1
- package/src/components/editor/ComputedTweenNotice.tsx +1 -1
- package/src/components/editor/DomEditOverlay.tsx +5 -6
- package/src/components/editor/DomEditRotateHandle.tsx +1 -1
- package/src/components/editor/EaseCurveSection.tsx +14 -19
- package/src/components/editor/EaseModeControls.tsx +2 -2
- package/src/components/editor/EaseParamFields.tsx +8 -8
- package/src/components/editor/FileTree.tsx +1 -1
- package/src/components/editor/FileTreeIcons.tsx +47 -26
- package/src/components/editor/FileTreeNodes.tsx +11 -8
- package/src/components/editor/GestureRecordControl.tsx +3 -3
- package/src/components/editor/GsapAddAnimationControl.tsx +1 -1
- package/src/components/editor/GsapAnimationSection.tsx +2 -2
- package/src/components/editor/InlineTextToolbar.tsx +4 -4
- package/src/components/editor/InspectorHeaderActions.tsx +1 -1
- package/src/components/editor/KeyframeDiamond.tsx +6 -4
- package/src/components/editor/KeyframeNavigation.tsx +4 -4
- package/src/components/editor/LayersPanel.tsx +3 -3
- package/src/components/editor/PromotableControl.tsx +2 -2
- package/src/components/editor/PropertyPanel.tsx +3 -3
- package/src/components/editor/PropertyPanelEmptyState.tsx +4 -4
- package/src/components/editor/PropertyPanelFlatFooter.tsx +2 -2
- package/src/components/editor/PropertyPanelFlatHeader.test.tsx +1 -1
- package/src/components/editor/PropertyPanelFlatHeader.tsx +2 -2
- package/src/components/editor/SnapToolbar.tsx +5 -5
- package/src/components/editor/TimelineFxPopover.tsx +4 -4
- package/src/components/editor/Transform3DCube.tsx +1 -1
- package/src/components/editor/anchoredResizeCommitFeedsOffset.test.ts +46 -6
- package/src/components/editor/anchoredResizeReleaseShift.test.ts +0 -84
- package/src/components/editor/domEditOverlayGestures.ts +13 -19
- package/src/components/editor/domEditOverlayStartGesture.test.ts +170 -13
- package/src/components/editor/domEditOverlayStartGesture.ts +15 -25
- package/src/components/editor/easeCurveSvg.tsx +1 -1
- package/src/components/editor/manualEdits.test.ts +3 -9
- package/src/components/editor/manualEdits.ts +0 -1
- package/src/components/editor/manualEditsDom.ts +3 -13
- package/src/components/editor/manualEditsDomPatches.test.ts +3 -131
- package/src/components/editor/manualEditsDomPatches.ts +1 -53
- package/src/components/editor/manualEditsSnapshot.ts +3 -0
- package/src/components/editor/manualEditsTypes.ts +2 -0
- package/src/components/editor/manualOffsetDrag.test.ts +41 -0
- package/src/components/editor/manualOffsetDrag.ts +6 -27
- package/src/components/editor/persistSeam.integration.test.ts +0 -18
- package/src/components/editor/plainTranslate.ts +42 -6
- package/src/components/editor/propertyPanelColorCurveGraph.tsx +2 -2
- package/src/components/editor/propertyPanelColorGradingControls.tsx +1 -1
- package/src/components/editor/propertyPanelColorGradingSection.tsx +8 -8
- package/src/components/editor/propertyPanelColorGradingSlider.tsx +1 -1
- package/src/components/editor/propertyPanelColorSecondary.tsx +4 -4
- package/src/components/editor/propertyPanelFill.tsx +6 -6
- package/src/components/editor/propertyPanelFlatColorGradingAccessory.tsx +3 -3
- package/src/components/editor/propertyPanelFlatColorGradingSection.test.tsx +1 -1
- package/src/components/editor/propertyPanelFlatColorGradingSection.tsx +6 -9
- package/src/components/editor/propertyPanelFlatEffectsSection.tsx +4 -4
- package/src/components/editor/propertyPanelFlatMediaSection.tsx +2 -2
- package/src/components/editor/propertyPanelFlatMotionSection.tsx +2 -2
- package/src/components/editor/propertyPanelFlatOverlaysSection.tsx +2 -2
- package/src/components/editor/propertyPanelFlatPrimitives.test.tsx +4 -3
- package/src/components/editor/propertyPanelFlatPrimitives.tsx +1 -1
- package/src/components/editor/propertyPanelFlatSliderReadout.tsx +1 -1
- package/src/components/editor/propertyPanelFont.tsx +2 -2
- package/src/components/editor/propertyPanelFxCarveModule.tsx +1 -1
- package/src/components/editor/propertyPanelFxControls.tsx +2 -2
- package/src/components/editor/propertyPanelFxEqModule.tsx +2 -2
- package/src/components/editor/propertyPanelFxNodeRow.tsx +1 -1
- package/src/components/editor/propertyPanelFxPresetRun.tsx +1 -1
- package/src/components/editor/propertyPanelMediaSection.tsx +1 -1
- package/src/components/editor/propertyPanelPrimitives.tsx +1 -1
- package/src/components/editor/propertyPanelSections.tsx +2 -2
- package/src/components/editor/propertyPanelTransformCommit.test.ts +29 -0
- package/src/components/editor/propertyPanelTransformCommit.ts +8 -5
- package/src/components/editor/propertyPanelTypes.ts +1 -0
- package/src/components/editor/propertyPanelValueTier.test.ts +1 -1
- package/src/components/editor/propertyPanelValueTier.ts +1 -1
- package/src/components/editor/rotateInlineSave.test.ts +111 -0
- package/src/components/editor/rotationDraft.test.ts +111 -0
- package/src/components/editor/rotationDraft.ts +145 -0
- package/src/components/editor/useDomEditNudge.test.tsx +33 -0
- package/src/components/editor/useDomEditNudge.ts +6 -2
- package/src/components/editor/useDomEditOverlayGestures.ts +22 -24
- package/src/components/feedback/StudioFeedbackCard.tsx +11 -23
- package/src/components/nle/AssetPreviewOverlay.tsx +1 -1
- package/src/components/nle/AudioMeterStrip.tsx +2 -2
- package/src/components/nle/NLEPreview.test.ts +8 -4
- package/src/components/nle/PreviewOverlays.tsx +1 -1
- package/src/components/nle/PreviewPane.tsx +3 -3
- package/src/components/nle/PreviewPoster.tsx +29 -1
- package/src/components/nle/PreviewZoomOverlay.tsx +1 -1
- package/src/components/panels/SlideshowPanel.tsx +4 -4
- package/src/components/panels/SlideshowSubPanels.tsx +19 -21
- package/src/components/panels/VariablesBindElement.tsx +1 -1
- package/src/components/panels/VariablesDeclarationForm.tsx +1 -1
- package/src/components/panels/VariablesPanel.tsx +4 -6
- package/src/components/panels/VariablesRowAction.tsx +1 -1
- package/src/components/renders/FfmpegRequiredNotice.tsx +4 -4
- package/src/components/renders/RenderQueue.tsx +2 -2
- package/src/components/renders/RenderQueueItem.tsx +3 -3
- package/src/components/sidebar/AssetCard.tsx +3 -3
- package/src/components/sidebar/AssetContextMenu.tsx +7 -7
- package/src/components/sidebar/AssetsTab.tsx +6 -6
- package/src/components/sidebar/AudioRow.tsx +5 -3
- package/src/components/sidebar/BlocksTab.tsx +6 -6
- package/src/components/sidebar/CompositionsTab.drag.test.tsx +3 -69
- package/src/components/sidebar/CompositionsTab.rootBadge.test.tsx +4 -50
- package/src/components/sidebar/CompositionsTab.thumbnails.test.tsx +256 -0
- package/src/components/sidebar/CompositionsTab.tsx +65 -12
- package/src/components/sidebar/PromptPreviewModal.tsx +3 -3
- package/src/components/sidebar/SidebarLintButton.tsx +3 -3
- package/src/components/sidebar/compositionsTabTestUtils.tsx +39 -0
- package/src/components/timelineToolbarStyles.ts +3 -3
- package/src/components/ui/Button.tsx +4 -4
- package/src/components/ui/HyperframesLogo.tsx +19 -18
- package/src/components/ui/Input.tsx +1 -1
- package/src/components/ui/Menu.tsx +4 -2
- package/src/hooks/draggedGsapPosition.ts +28 -0
- package/src/hooks/elementOffsetStager.ts +34 -13
- package/src/hooks/gsapRuntimeBridge.ts +5 -3
- package/src/hooks/gsapRuntimeKeyframes.ts +36 -2
- package/src/hooks/plainRotation.test.ts +122 -0
- package/src/hooks/plainRotation.ts +42 -0
- package/src/hooks/useClipboard.source.test.ts +42 -4
- package/src/hooks/useClipboard.ts +13 -3
- package/src/hooks/useDomEditCommits.ts +0 -3
- package/src/hooks/useDomEditSession.ts +5 -5
- package/src/hooks/useDomGeometryCommit.test.tsx +79 -1
- package/src/hooks/useDomGeometryCommit.ts +16 -17
- package/src/hooks/useDomGeometryCommits.test.tsx +233 -33
- package/src/hooks/useDomGeometryCommits.ts +27 -80
- package/src/hooks/useGsapAwareEditing.test.tsx +194 -11
- package/src/hooks/useGsapAwareEditing.ts +43 -42
- package/src/hooks/useInlineTextEdit.test.tsx +33 -3
- package/src/hooks/useInlineTextEdit.ts +2 -2
- package/src/player/components/ClipContextMenu.tsx +1 -1
- package/src/player/components/CompositionThumbnail.tsx +23 -11
- package/src/player/components/EditModal.tsx +6 -6
- package/src/player/components/KeyframeDiamondContextMenu.tsx +2 -2
- package/src/player/components/PlayerControls.tsx +3 -3
- package/src/player/components/ShortcutsPanel.tsx +8 -20
- package/src/player/components/TimelineCanvas.tsx +1 -1
- package/src/player/components/TimelineClip.tsx +2 -2
- package/src/player/components/TimelineEmptyState.tsx +2 -2
- package/src/player/components/TimelineLanes.tsx +0 -1
- package/src/player/components/TrackClipCount.tsx +1 -1
- package/src/player/components/VolumeControl.tsx +1 -1
- package/src/player/components/timelineClipChildren.tsx +1 -1
- package/src/player/components/timelineMotionStyles.test.ts +6 -22
- package/src/player/components/trackHeaderLabelRows.tsx +16 -16
- package/src/player/lib/thumbnailScheduler.ts +4 -5
- package/src/player/lib/timelineViewportBudgets.test.ts +1 -1
- package/src/player/lib/timelineViewportBudgets.ts +1 -1
- package/src/styles/hex-baseline.json +7 -19
- package/src/styles/studio.css +0 -9
- package/src/styles/tailwind-preset.shared.js +2 -1
- package/src/styles/theme.css +204 -147
- package/src/styles/theme.test.ts +13 -9
- package/src/utils/blockCategories.ts +41 -9
- package/src/utils/clipboardPayload.ts +2 -0
- package/dist/assets/index-CQN3M56N.css +0 -1
- package/dist/chunk-62DDWOSH.js.map +0 -1
- package/dist/chunk-6GAO75IU.js.map +0 -1
- package/src/hooks/gsapTargetCache.ts +0 -62
- /package/dist/{chunk-HIGHVWYD.js.map → chunk-QADHJFDF.js.map} +0 -0
|
@@ -42,7 +42,6 @@ const VMIN = -HR / S; // bottom of visible view (undershoot headroom)
|
|
|
42
42
|
// of snapping to the view edge; the handle DOT is still clampView'd into view.
|
|
43
43
|
const DRAG_VMAX = 2;
|
|
44
44
|
const DRAG_VMIN = -1;
|
|
45
|
-
const ACCENT = "#3CE6AC";
|
|
46
45
|
|
|
47
46
|
// Figma-style ease-type dropdown: the current ease (glyph + name) as a button
|
|
48
47
|
// that opens the preset grid in a popover. This is where a preset is selected —
|
|
@@ -130,7 +129,7 @@ function EaseTypeDropdown({
|
|
|
130
129
|
aria-expanded={open}
|
|
131
130
|
aria-controls={open ? menuId : undefined}
|
|
132
131
|
onClick={() => setOpen((prev) => !prev)}
|
|
133
|
-
className="flex w-full items-center gap-2 rounded-md border border-
|
|
132
|
+
className="flex w-full items-center gap-2 rounded-md border border-border bg-input px-2 py-1.5 text-left transition-colors hover:border-border-strong"
|
|
134
133
|
>
|
|
135
134
|
<MiniCurveSvg ease={ease} active size={16} />
|
|
136
135
|
<span className="text-[11px] text-neutral-200">{label}</span>
|
|
@@ -151,7 +150,7 @@ function EaseTypeDropdown({
|
|
|
151
150
|
role="menu"
|
|
152
151
|
aria-label={`${MODE_LABELS[kind]} ease presets`}
|
|
153
152
|
onKeyDown={handleMenuKeyDown}
|
|
154
|
-
className="absolute inset-x-0 top-full z-20 mt-1 rounded-md border border-
|
|
153
|
+
className="absolute inset-x-0 top-full z-20 mt-1 rounded-md border border-border bg-raised p-2 shadow-xl"
|
|
155
154
|
>
|
|
156
155
|
<EasePresetGrid
|
|
157
156
|
kind={kind}
|
|
@@ -407,7 +406,7 @@ export function EaseCurveSection({
|
|
|
407
406
|
{showGraph ? (
|
|
408
407
|
<>
|
|
409
408
|
<div
|
|
410
|
-
className="mx-auto overflow-hidden rounded-md border border-
|
|
409
|
+
className="mx-auto overflow-hidden rounded-md border border-border bg-input"
|
|
411
410
|
style={{ aspectRatio: `${SVGW} / ${SVGH}`, width: "100%", maxWidth: 230 }}
|
|
412
411
|
>
|
|
413
412
|
<svg
|
|
@@ -429,7 +428,7 @@ export function EaseCurveSection({
|
|
|
429
428
|
y1={top}
|
|
430
429
|
x2={xToSvg(q)}
|
|
431
430
|
y2={bottom}
|
|
432
|
-
|
|
431
|
+
className="stroke-text-0"
|
|
433
432
|
strokeOpacity="0.05"
|
|
434
433
|
strokeWidth="1"
|
|
435
434
|
/>
|
|
@@ -441,7 +440,7 @@ export function EaseCurveSection({
|
|
|
441
440
|
y1={yToSvg(q)}
|
|
442
441
|
x2={right}
|
|
443
442
|
y2={yToSvg(q)}
|
|
444
|
-
|
|
443
|
+
className="stroke-text-0"
|
|
445
444
|
strokeOpacity="0.05"
|
|
446
445
|
strokeWidth="1"
|
|
447
446
|
/>
|
|
@@ -453,7 +452,7 @@ export function EaseCurveSection({
|
|
|
453
452
|
width={S}
|
|
454
453
|
height={bottom - top}
|
|
455
454
|
fill="none"
|
|
456
|
-
|
|
455
|
+
className="stroke-text-0"
|
|
457
456
|
strokeOpacity="0.1"
|
|
458
457
|
strokeWidth="1"
|
|
459
458
|
/>
|
|
@@ -463,7 +462,7 @@ export function EaseCurveSection({
|
|
|
463
462
|
y1={a0.y}
|
|
464
463
|
x2={a1.x}
|
|
465
464
|
y2={a1.y}
|
|
466
|
-
|
|
465
|
+
className="stroke-text-0"
|
|
467
466
|
strokeOpacity="0.08"
|
|
468
467
|
strokeWidth="1"
|
|
469
468
|
strokeDasharray="3 4"
|
|
@@ -476,8 +475,7 @@ export function EaseCurveSection({
|
|
|
476
475
|
y1={a0.y}
|
|
477
476
|
x2={p1.x}
|
|
478
477
|
y2={p1.y}
|
|
479
|
-
stroke
|
|
480
|
-
strokeOpacity="0.5"
|
|
478
|
+
className="stroke-accent-ink"
|
|
481
479
|
strokeWidth="1.5"
|
|
482
480
|
/>
|
|
483
481
|
<line
|
|
@@ -485,8 +483,7 @@ export function EaseCurveSection({
|
|
|
485
483
|
y1={a1.y}
|
|
486
484
|
x2={p2.x}
|
|
487
485
|
y2={p2.y}
|
|
488
|
-
stroke
|
|
489
|
-
strokeOpacity="0.5"
|
|
486
|
+
className="stroke-accent-ink"
|
|
490
487
|
strokeWidth="1.5"
|
|
491
488
|
/>
|
|
492
489
|
</>
|
|
@@ -495,13 +492,13 @@ export function EaseCurveSection({
|
|
|
495
492
|
<path
|
|
496
493
|
d={curvePath}
|
|
497
494
|
fill="none"
|
|
498
|
-
stroke
|
|
495
|
+
className="stroke-accent-ink"
|
|
499
496
|
strokeWidth="2.5"
|
|
500
497
|
strokeLinecap="round"
|
|
501
498
|
/>
|
|
502
499
|
{/* Anchors at (0,0) and (1,1) */}
|
|
503
|
-
<circle cx={a0.x} cy={a0.y} r="3" fill
|
|
504
|
-
<circle cx={a1.x} cy={a1.y} r="3" fill
|
|
500
|
+
<circle cx={a0.x} cy={a0.y} r="3" className="fill-accent-ink" />
|
|
501
|
+
<circle cx={a1.x} cy={a1.y} r="3" className="fill-accent-ink" />
|
|
505
502
|
{/* Draggable control handles (large transparent hit area + visible dot) */}
|
|
506
503
|
{showHandles &&
|
|
507
504
|
[["p1", p1] as const, ["p2", p2] as const].map(([key, pt]) => (
|
|
@@ -518,7 +515,7 @@ export function EaseCurveSection({
|
|
|
518
515
|
aria-valuemax={1}
|
|
519
516
|
aria-valuenow={key === "p1" ? x1 : x2}
|
|
520
517
|
aria-valuetext={`x ${key === "p1" ? x1 : x2}, y ${key === "p1" ? y1 : y2}`}
|
|
521
|
-
className="cursor-grab stroke-transparent outline-hidden active:cursor-grabbing focus-visible:stroke-
|
|
518
|
+
className="cursor-grab stroke-transparent outline-hidden active:cursor-grabbing focus-visible:stroke-text-0 focus-visible:stroke-[2px]"
|
|
522
519
|
onPointerDown={(e) => handlePointerDown(key, e)}
|
|
523
520
|
onKeyDown={(event) => handleKeyDown(key, event)}
|
|
524
521
|
onPointerEnter={() => setHover(key)}
|
|
@@ -528,10 +525,8 @@ export function EaseCurveSection({
|
|
|
528
525
|
cx={pt.x}
|
|
529
526
|
cy={pt.y}
|
|
530
527
|
r={hover === key || draggingRef.current === key ? 7 : 5.5}
|
|
531
|
-
fill="#0a0a1a"
|
|
532
|
-
stroke={ACCENT}
|
|
533
528
|
strokeWidth="2.5"
|
|
534
|
-
className="pointer-events-none transition-[r]"
|
|
529
|
+
className="pointer-events-none fill-input stroke-accent-ink transition-[r]"
|
|
535
530
|
/>
|
|
536
531
|
</g>
|
|
537
532
|
))}
|
|
@@ -59,7 +59,7 @@ export const EasePresetGrid = function EasePresetGrid({
|
|
|
59
59
|
<MiniCurveSvg ease={preset.ease} active={isActive} />
|
|
60
60
|
<span
|
|
61
61
|
className={`text-center text-[8px] leading-none ${
|
|
62
|
-
isActive ? "text-
|
|
62
|
+
isActive ? "text-accent-ink" : "text-neutral-500"
|
|
63
63
|
}`}
|
|
64
64
|
>
|
|
65
65
|
{preset.label}
|
|
@@ -80,7 +80,7 @@ export function EaseModeToggle({
|
|
|
80
80
|
}) {
|
|
81
81
|
return (
|
|
82
82
|
<div
|
|
83
|
-
className="mb-2 grid grid-cols-3 rounded-md bg-
|
|
83
|
+
className="mb-2 grid grid-cols-3 rounded-md bg-press p-0.5"
|
|
84
84
|
role="radiogroup"
|
|
85
85
|
aria-label="Ease editor mode"
|
|
86
86
|
>
|
|
@@ -93,17 +93,17 @@ export function EaseBezierField({
|
|
|
93
93
|
}
|
|
94
94
|
}}
|
|
95
95
|
onBlur={(event) => commit(event.currentTarget.value)}
|
|
96
|
-
className={`w-full rounded border bg-
|
|
96
|
+
className={`w-full rounded border bg-input px-1.5 py-1 font-mono text-[10px] text-neutral-300 outline-hidden ${
|
|
97
97
|
error
|
|
98
|
-
? "border-
|
|
99
|
-
: "border-
|
|
98
|
+
? "border-danger-ink/70 focus:border-danger-ink"
|
|
99
|
+
: "border-border focus:border-panel-accent/50"
|
|
100
100
|
}`}
|
|
101
101
|
/>
|
|
102
102
|
</div>
|
|
103
103
|
<p
|
|
104
104
|
id={errorId}
|
|
105
105
|
aria-live="polite"
|
|
106
|
-
className={`mt-1 text-[9px] text-
|
|
106
|
+
className={`mt-1 text-[9px] text-danger-ink ${error ? "" : "sr-only"}`}
|
|
107
107
|
>
|
|
108
108
|
{error ?? "Valid bezier values"}
|
|
109
109
|
</p>
|
|
@@ -183,7 +183,7 @@ export function SpringBounceField({
|
|
|
183
183
|
const bounce = parseSpringBounce(`spring(${value})`);
|
|
184
184
|
if (bounce !== null) onCommit(`spring(${round2(bounce)})`);
|
|
185
185
|
}}
|
|
186
|
-
className="w-16 rounded-sm border border-
|
|
186
|
+
className="w-16 rounded-sm border border-border bg-input px-1.5 py-1 font-mono text-[10px] text-neutral-300 outline-hidden focus:border-panel-accent/50"
|
|
187
187
|
/>
|
|
188
188
|
</div>
|
|
189
189
|
);
|
|
@@ -207,7 +207,7 @@ export function WiggleField({
|
|
|
207
207
|
min={1}
|
|
208
208
|
step={1}
|
|
209
209
|
onCommit={(value) => commitWiggle(onCommit, value, config.type, amplitude)}
|
|
210
|
-
className="w-14 rounded-sm border border-
|
|
210
|
+
className="w-14 rounded-sm border border-border bg-input px-1.5 py-1 font-mono text-[10px] text-neutral-300 outline-hidden focus:border-panel-accent/50"
|
|
211
211
|
/>
|
|
212
212
|
</div>
|
|
213
213
|
<div className="flex items-center gap-1">
|
|
@@ -220,7 +220,7 @@ export function WiggleField({
|
|
|
220
220
|
commitWiggle(onCommit, config.wiggles, event.currentTarget.value, amplitude);
|
|
221
221
|
}
|
|
222
222
|
}}
|
|
223
|
-
className="rounded-sm border border-
|
|
223
|
+
className="rounded-sm border border-border bg-input px-1.5 py-1 text-[10px] text-neutral-300 outline-hidden focus:border-panel-accent/50"
|
|
224
224
|
>
|
|
225
225
|
{WIGGLE_TYPES.map((type) => (
|
|
226
226
|
<option key={type} value={type}>
|
|
@@ -238,7 +238,7 @@ export function WiggleField({
|
|
|
238
238
|
max={1}
|
|
239
239
|
step={0.01}
|
|
240
240
|
onCommit={(value) => commitWiggle(onCommit, config.wiggles, config.type, value)}
|
|
241
|
-
className="w-16 rounded-sm border border-
|
|
241
|
+
className="w-16 rounded-sm border border-border bg-input px-1.5 py-1 font-mono text-[10px] text-neutral-300 outline-hidden focus:border-panel-accent/50"
|
|
242
242
|
/>
|
|
243
243
|
</div>
|
|
244
244
|
</div>
|
|
@@ -263,7 +263,7 @@ export const FileTree = memo(function FileTree({
|
|
|
263
263
|
<div
|
|
264
264
|
className={`flex-1 overflow-y-auto py-1 transition-colors ${
|
|
265
265
|
dragOverFolder === ""
|
|
266
|
-
? "bg-
|
|
266
|
+
? "bg-accent/5 outline-solid outline-1 outline-accent-ink -outline-offset-1"
|
|
267
267
|
: ""
|
|
268
268
|
}`}
|
|
269
269
|
onContextMenu={handleRootContextMenu}
|
|
@@ -21,34 +21,55 @@ import {
|
|
|
21
21
|
const SZ = 14;
|
|
22
22
|
const W = "duotone" as const;
|
|
23
23
|
|
|
24
|
+
type Icon = typeof File;
|
|
25
|
+
// Brand hues; each light half is darkened to hold 3:1 on a hovered or selected row.
|
|
26
|
+
const RED = "text-[light-dark(oklch(0.59_0.194_35),oklch(0.71_0.194_35))]";
|
|
27
|
+
const BLUE = "text-[light-dark(oklch(0.56_0.14_253),oklch(0.69_0.14_253))]";
|
|
28
|
+
const GREEN = "text-[light-dark(oklch(0.53_0.192_150),#22C55E)]";
|
|
29
|
+
const GRAY = "text-[light-dark(oklch(0.56_0.019_261),#9CA3AF)]";
|
|
30
|
+
export const DIM = "text-[light-dark(oklch(0.55_0.023_264),oklch(0.69_0.023_264))]";
|
|
31
|
+
const ICONS = new Map<string, [Icon, string]>([
|
|
32
|
+
["html", [FileHtml, RED]],
|
|
33
|
+
["css", [FileCss, "text-[light-dark(oklch(0.5_0.2_266),oklch(0.71_0.2_266))]"]],
|
|
34
|
+
["js", [FileJs, "text-[light-dark(oklch(0.56_0.156_101),#F0DB4F)]"]],
|
|
35
|
+
["jsx", [FileJsx, "text-[light-dark(oklch(0.55_0.117_219),#61DAFB)]"]],
|
|
36
|
+
["ts", [FileTs, BLUE]],
|
|
37
|
+
["tsx", [FileTsx, BLUE]],
|
|
38
|
+
["json", [FileCode, "text-[light-dark(oklch(0.54_0.182_152),#4ADE80)]"]],
|
|
39
|
+
["svg", [FileSvg, "text-[light-dark(oklch(0.58_0.187_48),#F97316)]"]],
|
|
40
|
+
["md", [FileMd, GRAY]],
|
|
41
|
+
["txt", [FileTxt, GRAY]],
|
|
42
|
+
["png", [FilePng, GREEN]],
|
|
43
|
+
["jpg", [FileJpg, GREEN]],
|
|
44
|
+
["webp", [PhImage, GREEN]],
|
|
45
|
+
["mp4", [FileVideo, "text-[light-dark(oklch(0.59_0.2_304),oklch(0.71_0.2_304))]"]],
|
|
46
|
+
["mp3", [Waveform, "text-[light-dark(oklch(0.53_0.159_165),#3CE6AC)]"]],
|
|
47
|
+
["woff", [TextAa, DIM]],
|
|
48
|
+
]);
|
|
49
|
+
const ALIAS = new Map(
|
|
50
|
+
Object.entries({
|
|
51
|
+
mjs: "js",
|
|
52
|
+
cjs: "js",
|
|
53
|
+
mts: "ts",
|
|
54
|
+
mdx: "md",
|
|
55
|
+
jpeg: "jpg",
|
|
56
|
+
gif: "webp",
|
|
57
|
+
ico: "webp",
|
|
58
|
+
webm: "mp4",
|
|
59
|
+
mov: "mp4",
|
|
60
|
+
wav: "mp3",
|
|
61
|
+
ogg: "mp3",
|
|
62
|
+
m4a: "mp3",
|
|
63
|
+
woff2: "woff",
|
|
64
|
+
ttf: "woff",
|
|
65
|
+
otf: "woff",
|
|
66
|
+
}),
|
|
67
|
+
);
|
|
68
|
+
|
|
24
69
|
export function FileIcon({ path }: { path: string }) {
|
|
25
70
|
const ext = path.split(".").pop()?.toLowerCase() ?? "";
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
if (ext === "css") return <FileCss size={SZ} weight={W} color="#264DE4" className={c} />;
|
|
29
|
-
if (ext === "js" || ext === "mjs" || ext === "cjs")
|
|
30
|
-
return <FileJs size={SZ} weight={W} color="#F0DB4F" className={c} />;
|
|
31
|
-
if (ext === "jsx") return <FileJsx size={SZ} weight={W} color="#61DAFB" className={c} />;
|
|
32
|
-
if (ext === "ts" || ext === "mts")
|
|
33
|
-
return <FileTs size={SZ} weight={W} color="#3178C6" className={c} />;
|
|
34
|
-
if (ext === "tsx") return <FileTsx size={SZ} weight={W} color="#3178C6" className={c} />;
|
|
35
|
-
if (ext === "json") return <FileCode size={SZ} weight={W} color="#4ADE80" className={c} />;
|
|
36
|
-
if (ext === "svg") return <FileSvg size={SZ} weight={W} color="#F97316" className={c} />;
|
|
37
|
-
if (ext === "md" || ext === "mdx")
|
|
38
|
-
return <FileMd size={SZ} weight={W} color="#9CA3AF" className={c} />;
|
|
39
|
-
if (ext === "txt") return <FileTxt size={SZ} weight={W} color="#9CA3AF" className={c} />;
|
|
40
|
-
if (ext === "png") return <FilePng size={SZ} weight={W} color="#22C55E" className={c} />;
|
|
41
|
-
if (ext === "jpg" || ext === "jpeg")
|
|
42
|
-
return <FileJpg size={SZ} weight={W} color="#22C55E" className={c} />;
|
|
43
|
-
if (ext === "webp" || ext === "gif" || ext === "ico")
|
|
44
|
-
return <PhImage size={SZ} weight={W} color="#22C55E" className={c} />;
|
|
45
|
-
if (ext === "mp4" || ext === "webm" || ext === "mov")
|
|
46
|
-
return <FileVideo size={SZ} weight={W} color="#A855F7" className={c} />;
|
|
47
|
-
if (ext === "mp3" || ext === "wav" || ext === "ogg" || ext === "m4a")
|
|
48
|
-
return <Waveform size={SZ} weight={W} color="#3CE6AC" className={c} />;
|
|
49
|
-
if (ext === "woff" || ext === "woff2" || ext === "ttf" || ext === "otf")
|
|
50
|
-
return <TextAa size={SZ} weight={W} color="#6B7280" className={c} />;
|
|
51
|
-
return <File size={SZ} weight={W} color="#6B7280" className={c} />;
|
|
71
|
+
const [Glyph, color] = ICONS.get(ALIAS.get(ext) ?? ext) ?? [File, DIM];
|
|
72
|
+
return <Glyph size={SZ} weight={W} className={`shrink-0 ${color}`} />;
|
|
52
73
|
}
|
|
53
74
|
|
|
54
75
|
// ── Tree Types ──
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
type TreeNode,
|
|
17
17
|
type ContextMenuState,
|
|
18
18
|
type InlineInputState,
|
|
19
|
+
DIM,
|
|
19
20
|
} from "./FileTreeIcons";
|
|
20
21
|
|
|
21
22
|
export type { ContextMenuState, InlineInputState };
|
|
@@ -173,7 +174,7 @@ export function ContextMenu({
|
|
|
173
174
|
<div className="border-t border-neutral-700 my-1" />
|
|
174
175
|
<button
|
|
175
176
|
role="menuitem"
|
|
176
|
-
className="w-full flex items-center gap-2 px-3 py-1.5 text-xs text-
|
|
177
|
+
className="w-full flex items-center gap-2 px-3 py-1.5 text-xs text-danger-ink hover:bg-danger/25 focus-visible:bg-danger/25 active:bg-danger/25 outline-hidden cursor-pointer text-left"
|
|
177
178
|
onClick={() => {
|
|
178
179
|
onDelete(state.targetPath);
|
|
179
180
|
onClose();
|
|
@@ -263,7 +264,7 @@ export function InlineInput({
|
|
|
263
264
|
style={{ paddingLeft: `${8 + depth * 12 + (isFolder ? 0 : 14)}px` }}
|
|
264
265
|
>
|
|
265
266
|
{isFolder ? (
|
|
266
|
-
<FolderSimple size={SZ_ICON} weight="duotone"
|
|
267
|
+
<FolderSimple size={SZ_ICON} weight="duotone" className={`shrink-0 ${DIM}`} />
|
|
267
268
|
) : (
|
|
268
269
|
<FileIcon path={value} />
|
|
269
270
|
)}
|
|
@@ -279,12 +280,12 @@ export function InlineInput({
|
|
|
279
280
|
onBlur={handleBlur}
|
|
280
281
|
aria-invalid={error ? true : undefined}
|
|
281
282
|
className={`w-full min-w-0 bg-neutral-800 text-neutral-200 text-xs px-1.5 py-0.5 rounded border outline-hidden ${
|
|
282
|
-
error ? "border-
|
|
283
|
+
error ? "border-danger-ink" : "border-neutral-600 focus:border-accent-ink"
|
|
283
284
|
}`}
|
|
284
285
|
spellCheck={false}
|
|
285
286
|
/>
|
|
286
287
|
{error && (
|
|
287
|
-
<div className="mt-0.5 text-[10px] text-
|
|
288
|
+
<div className="mt-0.5 text-[10px] text-danger-ink" role="alert">
|
|
288
289
|
{error}
|
|
289
290
|
</div>
|
|
290
291
|
)}
|
|
@@ -344,13 +345,13 @@ export function DeleteConfirm({
|
|
|
344
345
|
<div className="flex gap-1.5">
|
|
345
346
|
<button
|
|
346
347
|
onClick={onCancel}
|
|
347
|
-
className="flex-1 px-2 py-1 rounded-sm bg-
|
|
348
|
+
className="flex-1 px-2 py-1 rounded-sm bg-hover text-neutral-300 hover:bg-press transition-colors"
|
|
348
349
|
>
|
|
349
350
|
Cancel
|
|
350
351
|
</button>
|
|
351
352
|
<button
|
|
352
353
|
onClick={onConfirm}
|
|
353
|
-
className="flex-1 px-2 py-1 rounded-sm bg-
|
|
354
|
+
className="flex-1 px-2 py-1 rounded-sm bg-danger/15 text-danger-ink hover:bg-danger/25 transition-colors"
|
|
354
355
|
>
|
|
355
356
|
Delete
|
|
356
357
|
</button>
|
|
@@ -419,7 +420,7 @@ export const TreeFile = memo(function TreeFile({
|
|
|
419
420
|
<span className="truncate flex-1">{node.name}</span>
|
|
420
421
|
{lintInfo && lintInfo.count > 0 && (
|
|
421
422
|
<span
|
|
422
|
-
className="shrink-0 min-w-[16px] rounded-full bg-amber-500/20 px-1 text-[8px] font-bold text-
|
|
423
|
+
className="shrink-0 min-w-[16px] rounded-full bg-amber-500/20 px-1 text-[8px] font-bold text-warning-ink text-center mr-1"
|
|
423
424
|
title={lintInfo.messages.join("\n")}
|
|
424
425
|
>
|
|
425
426
|
{lintInfo.count}
|
|
@@ -505,7 +506,9 @@ export const TreeFolder = memo(function TreeFolder({
|
|
|
505
506
|
}}
|
|
506
507
|
onDragLeave={onDragLeave}
|
|
507
508
|
className={`w-full flex items-center gap-1.5 px-2.5 py-1 min-h-7 text-left text-xs text-neutral-400 hover:bg-neutral-800/30 hover:text-neutral-300 transition-colors ${
|
|
508
|
-
isDragOver
|
|
509
|
+
isDragOver
|
|
510
|
+
? "bg-accent/10 outline-solid outline-1 outline-accent-ink -outline-offset-1"
|
|
511
|
+
: ""
|
|
509
512
|
}`}
|
|
510
513
|
style={{ paddingLeft: `${8 + depth * 12}px` }}
|
|
511
514
|
>
|
|
@@ -43,7 +43,7 @@ export function GestureRecordPanelButton({
|
|
|
43
43
|
}}
|
|
44
44
|
className={`w-full flex items-center justify-center gap-2 rounded-lg py-2 text-[11px] font-medium transition-colors ${
|
|
45
45
|
recording
|
|
46
|
-
? "bg-red-500/15 text-
|
|
46
|
+
? "bg-red-500/15 text-danger-ink border border-red-500/30 animate-pulse"
|
|
47
47
|
: "bg-panel-input text-panel-text-2 hover:bg-panel-hover border border-panel-border"
|
|
48
48
|
}`}
|
|
49
49
|
>
|
|
@@ -77,8 +77,8 @@ export function GestureRecordBadge({
|
|
|
77
77
|
title={label}
|
|
78
78
|
className={`pointer-events-auto absolute z-20 flex h-7 w-7 items-center justify-center rounded-full border shadow-lg transition-colors ${
|
|
79
79
|
recording
|
|
80
|
-
? "border-
|
|
81
|
-
: "border-studio-accent/60 bg-neutral-950 text-
|
|
80
|
+
? "border-danger/60 bg-danger text-on-danger animate-pulse"
|
|
81
|
+
: "border-studio-accent/60 bg-neutral-950 text-accent-ink hover:bg-neutral-900"
|
|
82
82
|
}`}
|
|
83
83
|
style={{
|
|
84
84
|
left: Math.max(0, rect.left + rect.width + 8),
|
|
@@ -3,7 +3,7 @@ import { ADD_METHODS, ADD_METHOD_LABELS, METHOD_TOOLTIPS } from "./gsapAnimation
|
|
|
3
3
|
const STYLES = {
|
|
4
4
|
classic: {
|
|
5
5
|
method:
|
|
6
|
-
"rounded-lg border border-neutral-700 bg-neutral-900 px-2.5 py-1.5 text-[11px] font-medium text-neutral-300 transition-colors hover:border-neutral-600 hover:text-
|
|
6
|
+
"rounded-lg border border-neutral-700 bg-neutral-900 px-2.5 py-1.5 text-[11px] font-medium text-neutral-300 transition-colors hover:border-neutral-600 hover:text-text-0",
|
|
7
7
|
cancel: "px-1.5 text-[11px] text-neutral-500 hover:text-neutral-300",
|
|
8
8
|
trigger: "text-[11px] font-medium text-neutral-400 transition-colors hover:text-neutral-200",
|
|
9
9
|
},
|
|
@@ -24,13 +24,13 @@ export const GsapAnimationSection = memo(function GsapAnimationSection({
|
|
|
24
24
|
return (
|
|
25
25
|
<Section title="Animation" icon={<Film size={15} />}>
|
|
26
26
|
{multipleTimelines && (
|
|
27
|
-
<p className="mb-2 rounded-lg bg-amber-500/10 px-3 py-2 text-[11px] leading-relaxed text-
|
|
27
|
+
<p className="mb-2 rounded-lg bg-amber-500/10 px-3 py-2 text-[11px] leading-relaxed text-warning-ink">
|
|
28
28
|
This file has multiple GSAP timelines. Animation editing is disabled to prevent data loss
|
|
29
29
|
— consolidate into a single timeline to enable editing.
|
|
30
30
|
</p>
|
|
31
31
|
)}
|
|
32
32
|
{unsupportedTimelinePattern && (
|
|
33
|
-
<p className="mb-2 rounded-lg bg-amber-500/10 px-3 py-2 text-[11px] leading-relaxed text-
|
|
33
|
+
<p className="mb-2 rounded-lg bg-amber-500/10 px-3 py-2 text-[11px] leading-relaxed text-warning-ink">
|
|
34
34
|
This timeline uses a computed key (window.__timelines[variable]) the editor can't
|
|
35
35
|
resolve statically. Use a string-literal key (window.__timelines["id"]) or a
|
|
36
36
|
variable declaration (const tl = gsap.timeline()) to enable editing.
|
|
@@ -77,7 +77,7 @@ export function InlineTextToolbar({
|
|
|
77
77
|
data-inline-text-toolbar="true"
|
|
78
78
|
role="toolbar"
|
|
79
79
|
aria-label="Text formatting"
|
|
80
|
-
className="pointer-events-auto fixed z-200 flex items-center gap-1 rounded-lg border border-
|
|
80
|
+
className="pointer-events-auto fixed z-200 flex items-center gap-1 rounded-lg border border-border bg-raised p-1 shadow-[0_8px_24px_rgba(0,0,0,0.55)]"
|
|
81
81
|
style={{
|
|
82
82
|
left: placement.left,
|
|
83
83
|
top: placement.top,
|
|
@@ -98,12 +98,12 @@ export function InlineTextToolbar({
|
|
|
98
98
|
onClick={(event) => event.stopPropagation()}
|
|
99
99
|
>
|
|
100
100
|
<label
|
|
101
|
-
className="group relative flex h-6 w-6 cursor-pointer items-center justify-center rounded-md hover:bg-
|
|
101
|
+
className="group relative flex h-6 w-6 cursor-pointer items-center justify-center rounded-md hover:bg-hover"
|
|
102
102
|
title="Text colour"
|
|
103
103
|
>
|
|
104
104
|
<span
|
|
105
105
|
aria-hidden="true"
|
|
106
|
-
className="h-4 w-4 rounded-full border-2 border-
|
|
106
|
+
className="h-4 w-4 rounded-full border-2 border-border-strong transition-transform duration-150 group-hover:scale-110 group-active:scale-95"
|
|
107
107
|
// `background` maps a gradient to the PADDING box and then repeats it
|
|
108
108
|
// to fill the border box, so the 1px border shows the strip either
|
|
109
109
|
// side of the tile: the end colour on the left, the start colour on
|
|
@@ -202,7 +202,7 @@ function ToolbarToggle({
|
|
|
202
202
|
aria-label={label}
|
|
203
203
|
aria-pressed={on}
|
|
204
204
|
className={`flex h-6 w-6 items-center justify-center rounded-md text-xs ${
|
|
205
|
-
on ? "bg-studio-accent/20 text-
|
|
205
|
+
on ? "bg-studio-accent/20 text-accent-ink" : "text-text-2 hover:bg-hover"
|
|
206
206
|
}`}
|
|
207
207
|
style={{
|
|
208
208
|
fontWeight: bold ? 700 : 400,
|
|
@@ -67,7 +67,7 @@ export function InspectorHeaderActions({
|
|
|
67
67
|
}}
|
|
68
68
|
className={`flex h-6 w-6 items-center justify-center rounded transition-colors ${
|
|
69
69
|
copied
|
|
70
|
-
? "text-
|
|
70
|
+
? "text-accent-ink"
|
|
71
71
|
: "text-neutral-500 hover:bg-neutral-800 hover:text-neutral-300"
|
|
72
72
|
}`}
|
|
73
73
|
title={copied ? "Copied!" : "Copy element info to clipboard"}
|
|
@@ -19,8 +19,11 @@ export const KeyframeDiamond = memo(function KeyframeDiamond({
|
|
|
19
19
|
isHold = false,
|
|
20
20
|
}: KeyframeDiamondProps) {
|
|
21
21
|
const isFilled = state === "active";
|
|
22
|
-
const
|
|
23
|
-
|
|
22
|
+
const color = {
|
|
23
|
+
active: "text-accent",
|
|
24
|
+
inactive: "text-text-2 hover:text-text-0",
|
|
25
|
+
ghost: "text-text-off hover:text-text-0",
|
|
26
|
+
}[state];
|
|
24
27
|
|
|
25
28
|
return (
|
|
26
29
|
<button
|
|
@@ -29,8 +32,7 @@ export const KeyframeDiamond = memo(function KeyframeDiamond({
|
|
|
29
32
|
e.stopPropagation();
|
|
30
33
|
onClick();
|
|
31
34
|
}}
|
|
32
|
-
className=
|
|
33
|
-
style={{ color, opacity }}
|
|
35
|
+
className={`relative shrink-0 p-0.5 transition-colors before:absolute before:-inset-1.5 before:content-[''] ${color}`}
|
|
34
36
|
title={title}
|
|
35
37
|
aria-label={title}
|
|
36
38
|
aria-pressed={state === "active"}
|
|
@@ -82,11 +82,11 @@ function ArrowLeft({ disabled }: { disabled: boolean }) {
|
|
|
82
82
|
height="10"
|
|
83
83
|
viewBox="0 0 6 10"
|
|
84
84
|
fill="none"
|
|
85
|
-
|
|
85
|
+
className={disabled ? "text-text-off" : "text-text-2"}
|
|
86
86
|
>
|
|
87
87
|
<path
|
|
88
88
|
d="M5 1L1 5L5 9"
|
|
89
|
-
stroke="
|
|
89
|
+
stroke="currentColor"
|
|
90
90
|
strokeWidth="1.4"
|
|
91
91
|
strokeLinecap="round"
|
|
92
92
|
strokeLinejoin="round"
|
|
@@ -102,11 +102,11 @@ function ArrowRight({ disabled }: { disabled: boolean }) {
|
|
|
102
102
|
height="10"
|
|
103
103
|
viewBox="0 0 6 10"
|
|
104
104
|
fill="none"
|
|
105
|
-
|
|
105
|
+
className={disabled ? "text-text-off" : "text-text-2"}
|
|
106
106
|
>
|
|
107
107
|
<path
|
|
108
108
|
d="M1 1L5 5L1 9"
|
|
109
|
-
stroke="
|
|
109
|
+
stroke="currentColor"
|
|
110
110
|
strokeWidth="1.4"
|
|
111
111
|
strokeLinecap="round"
|
|
112
112
|
strokeLinejoin="round"
|
|
@@ -458,7 +458,7 @@ export const LayersPanel = memo(function LayersPanel() {
|
|
|
458
458
|
isDragged
|
|
459
459
|
? "opacity-40"
|
|
460
460
|
: selected
|
|
461
|
-
? "bg-panel-accent/14 text-
|
|
461
|
+
? "bg-panel-accent/14 text-accent-ink"
|
|
462
462
|
: "text-panel-text-2 hover:bg-panel-hover/40 hover:text-panel-text-1"
|
|
463
463
|
} ${dragKey ? "cursor-grabbing" : "cursor-pointer"}`}
|
|
464
464
|
style={{ paddingLeft: 8 + layer.depth * 16 }}
|
|
@@ -494,9 +494,9 @@ export const LayersPanel = memo(function LayersPanel() {
|
|
|
494
494
|
<span
|
|
495
495
|
className={`flex h-5 w-5 shrink-0 items-center justify-center rounded text-[8px] font-bold uppercase ${
|
|
496
496
|
selected
|
|
497
|
-
? "bg-panel-accent/18 text-
|
|
497
|
+
? "bg-panel-accent/18 text-accent-ink"
|
|
498
498
|
: isCompHost
|
|
499
|
-
? "bg-
|
|
499
|
+
? "bg-on text-accent-ink"
|
|
500
500
|
: "bg-panel-hover text-panel-text-4"
|
|
501
501
|
}`}
|
|
502
502
|
>
|
|
@@ -83,7 +83,7 @@ export function PromotableControl({
|
|
|
83
83
|
<span
|
|
84
84
|
// Sits above the row (not on top of top-0) so it clears a value that
|
|
85
85
|
// renders flush to the row's right edge, e.g. flat Font/Color rows.
|
|
86
|
-
className="pointer-events-none absolute -top-2 right-1.5 z-10 inline-flex max-w-[60%] items-center gap-1 truncate rounded-sm bg-studio-accent/20 px-1 py-px font-mono text-[8px] font-medium text-
|
|
86
|
+
className="pointer-events-none absolute -top-2 right-1.5 z-10 inline-flex max-w-[60%] items-center gap-1 truncate rounded-sm bg-studio-accent/20 px-1 py-px font-mono text-[8px] font-medium text-accent-ink"
|
|
87
87
|
title={`Bound to variable "${promote.boundId}"`}
|
|
88
88
|
>
|
|
89
89
|
◆ {promote.boundId}
|
|
@@ -97,7 +97,7 @@ export function PromotableControl({
|
|
|
97
97
|
e.stopPropagation();
|
|
98
98
|
promote.promote();
|
|
99
99
|
}}
|
|
100
|
-
className="absolute -top-2 right-1.5 z-10 inline-flex items-center gap-1 rounded-sm bg-
|
|
100
|
+
className="absolute -top-2 right-1.5 z-10 inline-flex items-center gap-1 rounded-sm bg-raised/80 px-1 py-px font-mono text-[8px] font-medium text-neutral-400 opacity-70 transition-colors hover:bg-studio-accent/20 hover:text-accent-ink hover:opacity-100"
|
|
101
101
|
>
|
|
102
102
|
◇ var
|
|
103
103
|
</button>
|
|
@@ -3,8 +3,8 @@ import { memo, useMemo, useRef, useState } from "react";
|
|
|
3
3
|
import { Move } from "../../icons/SystemIcons";
|
|
4
4
|
import { InspectorHeaderActions } from "./InspectorHeaderActions";
|
|
5
5
|
import { useStudioShellContext } from "../../contexts/StudioContext";
|
|
6
|
-
import { readStudioBoxSize
|
|
7
|
-
import { readMoveOffset } from "./plainTranslate";
|
|
6
|
+
import { readStudioBoxSize } from "./manualEdits";
|
|
7
|
+
import { readMoveOffset, readShownRotation } from "./plainTranslate";
|
|
8
8
|
import {
|
|
9
9
|
buildElementInfoText,
|
|
10
10
|
EMPTY_STYLES,
|
|
@@ -210,7 +210,7 @@ export const PropertyPanel = memo(function PropertyPanel(props: PropertyPanelPro
|
|
|
210
210
|
manualSize.height > 0
|
|
211
211
|
? manualSize.height
|
|
212
212
|
: (parsePxMetricValue(styles.height ?? "") ?? element.boundingBox.height);
|
|
213
|
-
const manualRotation =
|
|
213
|
+
const manualRotation = readShownRotation(element.element);
|
|
214
214
|
|
|
215
215
|
const elStart = Number.parseFloat(element?.dataAttributes?.start ?? "0") || 0;
|
|
216
216
|
const elDuration = Number.parseFloat(element?.dataAttributes?.duration ?? "1") || 0;
|
|
@@ -24,7 +24,7 @@ function FlatEmptyState() {
|
|
|
24
24
|
<div className="mt-2 flex w-full flex-col gap-1.5">
|
|
25
25
|
<span className="flex items-center justify-between rounded-lg border border-panel-border bg-panel-bg px-3 py-2">
|
|
26
26
|
<span className="flex items-center gap-2 text-[11px] text-panel-text-2">
|
|
27
|
-
<span className="text-
|
|
27
|
+
<span className="text-danger-ink">●</span>
|
|
28
28
|
Record a gesture
|
|
29
29
|
</span>
|
|
30
30
|
<span className="rounded-sm border border-panel-border-input px-[5px] py-px font-mono text-[9px] text-panel-text-5">
|
|
@@ -33,7 +33,7 @@ function FlatEmptyState() {
|
|
|
33
33
|
</span>
|
|
34
34
|
<span className="flex items-center justify-between rounded-lg border border-panel-border bg-panel-bg px-3 py-2">
|
|
35
35
|
<span className="flex items-center gap-2 text-[11px] text-panel-text-2">
|
|
36
|
-
<span className="text-
|
|
36
|
+
<span className="text-accent-ink">✦</span>
|
|
37
37
|
Describe a change to the agent
|
|
38
38
|
</span>
|
|
39
39
|
<span className="rounded-sm border border-panel-border-input px-[5px] py-px font-mono text-[9px] text-panel-text-5">
|
|
@@ -50,7 +50,7 @@ function elementKindGlyph(element: DomEditSelection): { glyph: string; className
|
|
|
50
50
|
return { glyph: "◆", className: "bg-panel-media/10 text-panel-media" };
|
|
51
51
|
}
|
|
52
52
|
if (element.textFields?.length > 0) {
|
|
53
|
-
return { glyph: "T", className: "bg-panel-accent/10 text-
|
|
53
|
+
return { glyph: "T", className: "bg-panel-accent/10 text-accent-ink" };
|
|
54
54
|
}
|
|
55
55
|
return { glyph: "▦", className: "bg-panel-container/10 text-panel-container" };
|
|
56
56
|
}
|
|
@@ -74,7 +74,7 @@ function FlatMultiSelectState({
|
|
|
74
74
|
return (
|
|
75
75
|
<div className="flex flex-col gap-3 px-4 py-3">
|
|
76
76
|
<div className="flex items-center gap-3 rounded-xl border border-panel-border bg-panel-surface p-3">
|
|
77
|
-
<span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-panel-accent/10 text-
|
|
77
|
+
<span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-panel-accent/10 text-accent-ink">
|
|
78
78
|
<Layers size={16} />
|
|
79
79
|
</span>
|
|
80
80
|
<div className="min-w-0 flex-1">
|
|
@@ -40,7 +40,7 @@ export function PropertyPanelFlatFooter({
|
|
|
40
40
|
height="13"
|
|
41
41
|
viewBox="0 0 16 16"
|
|
42
42
|
fill="currentColor"
|
|
43
|
-
className="text-
|
|
43
|
+
className="text-accent-ink"
|
|
44
44
|
>
|
|
45
45
|
<path d="M8 1l1.4 4.6L14 7l-4.6 1.4L8 13l-1.4-4.6L2 7l4.6-1.4z" />
|
|
46
46
|
</svg>
|
|
@@ -57,7 +57,7 @@ export function PropertyPanelFlatFooter({
|
|
|
57
57
|
track("button", "Gesture recording");
|
|
58
58
|
onToggleRecording();
|
|
59
59
|
}}
|
|
60
|
-
className={recording ? "text-
|
|
60
|
+
className={recording ? "text-danger-ink animate-pulse" : "text-danger-ink"}
|
|
61
61
|
>
|
|
62
62
|
<svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor">
|
|
63
63
|
{recording ? (
|