@hyperframes/studio 0.8.104 → 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-DAoaajuM.js → hyperframes-player-tnfCiVdR.js} +1 -1
- package/dist/assets/{index-BDK4rTMb.js → index-Ca6LZlVb.js} +1 -1
- package/dist/assets/index-Cre9X4RS.css +1 -0
- package/dist/assets/{index-De2aO4XM.js → index-DEDhPmPD.js} +205 -205
- package/dist/assets/{index-WV9LroAD.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.html +2 -2
- package/dist/index.js +614 -638
- 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/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/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/anchoredResizeReleaseShift.test.ts +0 -84
- package/src/components/editor/easeCurveSvg.tsx +1 -1
- package/src/components/editor/manualEditsDom.ts +3 -3
- package/src/components/editor/manualEditsDomPatches.test.ts +2 -86
- package/src/components/editor/manualEditsDomPatches.ts +0 -30
- package/src/components/editor/manualEditsSnapshot.ts +1 -0
- package/src/components/editor/persistSeam.integration.test.ts +0 -18
- package/src/components/editor/plainTranslate.ts +34 -3
- 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/propertyPanelValueTier.test.ts +1 -1
- package/src/components/editor/propertyPanelValueTier.ts +1 -1
- 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/elementOffsetStager.ts +8 -7
- 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/useDomGeometryCommit.test.tsx +4 -1
- package/src/hooks/useDomGeometryCommit.ts +0 -1
- package/src/hooks/useDomGeometryCommits.test.tsx +177 -32
- package/src/hooks/useDomGeometryCommits.ts +4 -49
- 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
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { useCallback, useRef, useState } from "react";
|
|
2
2
|
import { buildProjectApiPath } from "../../utils/projectRouting";
|
|
3
|
+
import {
|
|
4
|
+
createThumbnailKey,
|
|
5
|
+
thumbnailScheduler,
|
|
6
|
+
type ThumbnailRequest,
|
|
7
|
+
} from "../../player/lib/thumbnailScheduler";
|
|
3
8
|
import type { PreviewCompositionSize } from "../../utils/previewCompositionSize";
|
|
4
9
|
|
|
5
10
|
/** Frame 0 as the thumbnail route last rendered it; `cachedOnly` never starts a render. */
|
|
@@ -65,7 +70,7 @@ export function usePreviewPoster(
|
|
|
65
70
|
const renderMissingPoster = useCallback(() => {
|
|
66
71
|
if (missingForRef.current !== visit || liveReadyForRef.current !== visit) return;
|
|
67
72
|
missingForRef.current = null;
|
|
68
|
-
|
|
73
|
+
renderPosterForNextOpen(projectId);
|
|
69
74
|
}, [visit, projectId]);
|
|
70
75
|
const onLiveReadyToShowChange = useCallback(
|
|
71
76
|
(ready: boolean) => {
|
|
@@ -91,6 +96,29 @@ export function usePreviewPoster(
|
|
|
91
96
|
};
|
|
92
97
|
}
|
|
93
98
|
|
|
99
|
+
/** Renders frame 0 under the thumbnail cap; the lease ends once the render settles. */
|
|
100
|
+
export function renderPosterForNextOpen(projectId: string): void {
|
|
101
|
+
const url = previewPosterUrl(projectId, false);
|
|
102
|
+
const request: ThumbnailRequest = {
|
|
103
|
+
key: createThumbnailKey({ kind: "poster-render", url }),
|
|
104
|
+
projectId,
|
|
105
|
+
sessionEpoch: 0,
|
|
106
|
+
kind: "composition",
|
|
107
|
+
priority: "overscan",
|
|
108
|
+
discardWhenReleased: true,
|
|
109
|
+
load: async (signal) => {
|
|
110
|
+
await (await fetch(url, { signal })).arrayBuffer();
|
|
111
|
+
return { value: { kind: "image", url, aspect: 16 / 9 }, weight: 0 };
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
const settled = () => ["ready", "error"].includes(thumbnailScheduler.getSnapshot(request).status);
|
|
115
|
+
let lease: { release(): void } | null = null;
|
|
116
|
+
lease = thumbnailScheduler.acquire(request, () => {
|
|
117
|
+
if (settled()) lease?.release();
|
|
118
|
+
});
|
|
119
|
+
if (settled()) lease.release();
|
|
120
|
+
}
|
|
121
|
+
|
|
94
122
|
function useVisitNumber(key: string): number {
|
|
95
123
|
const [seen, setSeen] = useState({ key, visit: 0 });
|
|
96
124
|
if (seen.key === key) return seen.visit;
|
|
@@ -85,7 +85,7 @@ export function PreviewZoomOverlay({
|
|
|
85
85
|
</span>
|
|
86
86
|
<button
|
|
87
87
|
type="button"
|
|
88
|
-
className="rounded px-1.5 py-0.5 font-medium text-
|
|
88
|
+
className="rounded px-1.5 py-0.5 font-medium text-accent-ink hover:bg-white/10 transition-colors"
|
|
89
89
|
onClick={onFit}
|
|
90
90
|
aria-label="Fit the whole frame in view"
|
|
91
91
|
data-testid="preview-zoom-fit"
|
|
@@ -413,7 +413,7 @@ export function SlideshowPanel({ scenes, onPersist, onPersistNotes }: SlideshowP
|
|
|
413
413
|
|
|
414
414
|
return (
|
|
415
415
|
<div
|
|
416
|
-
className="flex flex-col h-full overflow-y-auto text-
|
|
416
|
+
className="flex flex-col h-full overflow-y-auto text-text-0"
|
|
417
417
|
onKeyDown={(e) => {
|
|
418
418
|
// In-panel undo — scoped so it never fights the app-level file undo.
|
|
419
419
|
if ((e.metaKey || e.ctrlKey) && !e.shiftKey && e.key.toLowerCase() === "z") {
|
|
@@ -428,14 +428,14 @@ export function SlideshowPanel({ scenes, onPersist, onPersistNotes }: SlideshowP
|
|
|
428
428
|
{persistError && (
|
|
429
429
|
<div
|
|
430
430
|
role="alert"
|
|
431
|
-
className="flex items-center justify-between gap-2 px-3 py-2 bg-
|
|
431
|
+
className="flex items-center justify-between gap-2 px-3 py-2 bg-danger/15 border-b border-red-500/40"
|
|
432
432
|
>
|
|
433
|
-
<span className="text-[11px] text-
|
|
433
|
+
<span className="text-[11px] text-danger-ink">Changes not saved</span>
|
|
434
434
|
<button
|
|
435
435
|
type="button"
|
|
436
436
|
disabled={retrying}
|
|
437
437
|
onClick={handleRetryPersist}
|
|
438
|
-
className="px-2 py-0.5 text-[10px] rounded-sm bg-
|
|
438
|
+
className="px-2 py-0.5 text-[10px] rounded-sm bg-danger text-on-danger enabled:hover:brightness-95 enabled:active:scale-[0.97] disabled:opacity-50 transition-colors"
|
|
439
439
|
>
|
|
440
440
|
{retrying ? "Retrying…" : "Retry"}
|
|
441
441
|
</button>
|
|
@@ -72,9 +72,7 @@ export function SlideList({
|
|
|
72
72
|
tabIndex={0}
|
|
73
73
|
aria-pressed={isSelected}
|
|
74
74
|
className={`flex items-center gap-2 px-3 py-1.5 rounded cursor-pointer text-[11px] transition-colors ${
|
|
75
|
-
isSelected
|
|
76
|
-
? "bg-studio-accent/20 text-white"
|
|
77
|
-
: "hover:bg-neutral-800/60 text-neutral-300"
|
|
75
|
+
isSelected ? "bg-on text-text-0" : "hover:bg-neutral-800/60 text-neutral-300"
|
|
78
76
|
}`}
|
|
79
77
|
onClick={() => onSelect(scene.id)}
|
|
80
78
|
onKeyDown={(e) => {
|
|
@@ -100,7 +98,7 @@ export function SlideList({
|
|
|
100
98
|
aria-label="Move slide up"
|
|
101
99
|
title="Move up"
|
|
102
100
|
disabled={slideIndex <= 0}
|
|
103
|
-
className="px-1 py-0.5 text-[10px] text-neutral-400 enabled:hover:text-
|
|
101
|
+
className="px-1 py-0.5 text-[10px] text-neutral-400 enabled:hover:text-text-0 enabled:active:scale-[0.95] disabled:opacity-30 disabled:cursor-not-allowed"
|
|
104
102
|
onClick={(e) => {
|
|
105
103
|
e.stopPropagation();
|
|
106
104
|
onReorder(scene.id, "up");
|
|
@@ -113,7 +111,7 @@ export function SlideList({
|
|
|
113
111
|
aria-label="Move slide down"
|
|
114
112
|
title="Move down"
|
|
115
113
|
disabled={slideIndex === slides.length - 1}
|
|
116
|
-
className="px-1 py-0.5 text-[10px] text-neutral-400 enabled:hover:text-
|
|
114
|
+
className="px-1 py-0.5 text-[10px] text-neutral-400 enabled:hover:text-text-0 enabled:active:scale-[0.95] disabled:opacity-30 disabled:cursor-not-allowed"
|
|
117
115
|
onClick={(e) => {
|
|
118
116
|
e.stopPropagation();
|
|
119
117
|
onReorder(scene.id, "down");
|
|
@@ -162,7 +160,7 @@ export function SlideInspector({
|
|
|
162
160
|
<div className="flex flex-col gap-1">
|
|
163
161
|
<label className="text-[11px] text-neutral-400">Notes</label>
|
|
164
162
|
<textarea
|
|
165
|
-
className="bg-neutral-800 border border-neutral-700 rounded-sm px-2 py-1.5 text-[11px] text-
|
|
163
|
+
className="bg-neutral-800 border border-neutral-700 rounded-sm px-2 py-1.5 text-[11px] text-text-0 resize-none placeholder-neutral-600 focus:border-studio-accent/60 focus:outline-hidden"
|
|
166
164
|
rows={3}
|
|
167
165
|
placeholder="Speaker notes or script..."
|
|
168
166
|
value={slide?.notes ?? ""}
|
|
@@ -174,7 +172,7 @@ export function SlideInspector({
|
|
|
174
172
|
<span className="text-[11px] text-neutral-400">Fragment hold-points</span>
|
|
175
173
|
<button
|
|
176
174
|
type="button"
|
|
177
|
-
className="text-[10px] px-2 py-0.5 rounded-sm bg-
|
|
175
|
+
className="text-[10px] px-2 py-0.5 rounded-sm bg-hover hover:bg-press text-neutral-200 transition-colors"
|
|
178
176
|
onClick={onMarkFragment}
|
|
179
177
|
title={`Mark ${currentTime.toFixed(2)}s as hold-point`}
|
|
180
178
|
>
|
|
@@ -192,7 +190,7 @@ export function SlideInspector({
|
|
|
192
190
|
<button
|
|
193
191
|
type="button"
|
|
194
192
|
aria-label={`Remove fragment at ${t.toFixed(2)}s`}
|
|
195
|
-
className="text-neutral-400 hover:text-
|
|
193
|
+
className="text-neutral-400 hover:text-danger-ink transition-colors"
|
|
196
194
|
onClick={() => onRemoveFragment(t)}
|
|
197
195
|
>
|
|
198
196
|
×
|
|
@@ -249,7 +247,7 @@ export function BranchTree({
|
|
|
249
247
|
<input
|
|
250
248
|
id={inputId}
|
|
251
249
|
type="text"
|
|
252
|
-
className="flex-1 bg-neutral-800 border border-neutral-700 rounded-sm px-2 py-1 text-[11px] text-
|
|
250
|
+
className="flex-1 bg-neutral-800 border border-neutral-700 rounded-sm px-2 py-1 text-[11px] text-text-0 placeholder-neutral-600 focus:border-studio-accent/60 focus:outline-hidden"
|
|
253
251
|
placeholder="New branch name..."
|
|
254
252
|
value={newLabel}
|
|
255
253
|
onChange={(e) => setNewLabel(e.target.value)}
|
|
@@ -260,7 +258,7 @@ export function BranchTree({
|
|
|
260
258
|
/>
|
|
261
259
|
<button
|
|
262
260
|
type="button"
|
|
263
|
-
className="px-2 py-1 rounded-sm bg-
|
|
261
|
+
className="px-2 py-1 rounded-sm bg-hover hover:bg-press text-[11px] text-neutral-200 transition-colors shrink-0"
|
|
264
262
|
onClick={handleCreate}
|
|
265
263
|
>
|
|
266
264
|
Add
|
|
@@ -326,7 +324,7 @@ function BranchItem({
|
|
|
326
324
|
<div className="flex items-center gap-1">
|
|
327
325
|
{editing ? (
|
|
328
326
|
<input
|
|
329
|
-
className="flex-1 bg-neutral-800 border border-neutral-600 rounded-sm px-1.5 py-0.5 text-[11px] text-
|
|
327
|
+
className="flex-1 bg-neutral-800 border border-neutral-600 rounded-sm px-1.5 py-0.5 text-[11px] text-text-0 focus:border-studio-accent/60 focus:outline-hidden"
|
|
330
328
|
value={draft}
|
|
331
329
|
autoFocus
|
|
332
330
|
onChange={(e) => setDraft(e.target.value)}
|
|
@@ -341,7 +339,7 @@ function BranchItem({
|
|
|
341
339
|
<span
|
|
342
340
|
role="button"
|
|
343
341
|
tabIndex={0}
|
|
344
|
-
className="flex-1 text-[11px] text-
|
|
342
|
+
className="flex-1 text-[11px] text-text-0 font-medium truncate cursor-pointer hover:text-neutral-300"
|
|
345
343
|
title="Click to rename"
|
|
346
344
|
onClick={() => setEditing(true)}
|
|
347
345
|
onKeyDown={(e) => {
|
|
@@ -357,15 +355,15 @@ function BranchItem({
|
|
|
357
355
|
<button
|
|
358
356
|
type="button"
|
|
359
357
|
aria-label={`Delete branch ${seq.label}`}
|
|
360
|
-
className="text-[10px] text-neutral-500 hover:text-
|
|
358
|
+
className="text-[10px] text-neutral-500 hover:text-danger-ink active:scale-[0.95] transition-colors px-1"
|
|
361
359
|
onClick={() => setConfirmingDelete(true)}
|
|
362
360
|
>
|
|
363
361
|
✕
|
|
364
362
|
</button>
|
|
365
363
|
</div>
|
|
366
364
|
{confirmingDelete && (
|
|
367
|
-
<div className="px-2 py-1.5 bg-
|
|
368
|
-
<span className="text-[10px] text-
|
|
365
|
+
<div className="px-2 py-1.5 bg-danger/15 border-l-2 border-red-500 flex flex-col gap-1 rounded-xs">
|
|
366
|
+
<span className="text-[10px] text-danger-ink">
|
|
369
367
|
Delete branch “{seq.label}”
|
|
370
368
|
{seq.slides.length > 0
|
|
371
369
|
? ` and its ${seq.slides.length} slide${seq.slides.length === 1 ? "" : "s"}`
|
|
@@ -379,7 +377,7 @@ function BranchItem({
|
|
|
379
377
|
setConfirmingDelete(false);
|
|
380
378
|
onDelete(seq.id);
|
|
381
379
|
}}
|
|
382
|
-
className="px-2 py-0.5 text-[10px] rounded-sm bg-
|
|
380
|
+
className="px-2 py-0.5 text-[10px] rounded-sm bg-danger text-on-danger hover:brightness-95 active:brightness-90 transition-colors"
|
|
383
381
|
>
|
|
384
382
|
Delete
|
|
385
383
|
</button>
|
|
@@ -414,7 +412,7 @@ function BranchItem({
|
|
|
414
412
|
type="button"
|
|
415
413
|
aria-pressed={isSelected}
|
|
416
414
|
className={`flex-1 text-left truncate transition-colors hover:text-neutral-200 ${
|
|
417
|
-
isSelected ? "text-
|
|
415
|
+
isSelected ? "text-text-0" : "text-neutral-400"
|
|
418
416
|
}`}
|
|
419
417
|
onClick={() => onSelectBranchSlide(seq.id, scene.id)}
|
|
420
418
|
>
|
|
@@ -497,7 +495,7 @@ export function HotspotTool({
|
|
|
497
495
|
<label className="text-[11px] text-neutral-400">Hotspot label</label>
|
|
498
496
|
<input
|
|
499
497
|
type="text"
|
|
500
|
-
className="bg-neutral-800 border border-neutral-700 rounded-sm px-2 py-1 text-[11px] text-
|
|
498
|
+
className="bg-neutral-800 border border-neutral-700 rounded-sm px-2 py-1 text-[11px] text-text-0 placeholder-neutral-600 focus:border-studio-accent/60 focus:outline-hidden"
|
|
501
499
|
placeholder="Button label..."
|
|
502
500
|
value={hotspotLabel}
|
|
503
501
|
onChange={(e) => setHotspotLabel(e.target.value)}
|
|
@@ -505,7 +503,7 @@ export function HotspotTool({
|
|
|
505
503
|
/>
|
|
506
504
|
<label className="text-[11px] text-neutral-400">Target branch</label>
|
|
507
505
|
<select
|
|
508
|
-
className="bg-neutral-800 border border-neutral-700 rounded-sm px-2 py-1 text-[11px] text-
|
|
506
|
+
className="bg-neutral-800 border border-neutral-700 rounded-sm px-2 py-1 text-[11px] text-text-0 focus:border-studio-accent/60 focus:outline-hidden"
|
|
509
507
|
value={targetSequenceId}
|
|
510
508
|
onChange={(e) => setTargetSequenceId(e.target.value)}
|
|
511
509
|
aria-label="Target branch sequence"
|
|
@@ -527,7 +525,7 @@ export function HotspotTool({
|
|
|
527
525
|
? "Choose a target branch first"
|
|
528
526
|
: undefined
|
|
529
527
|
}
|
|
530
|
-
className="px-3 py-1.5 rounded-sm bg-
|
|
528
|
+
className="px-3 py-1.5 rounded-sm bg-accent enabled:hover:bg-accent-hover enabled:active:scale-[0.98] text-on-accent text-[11px] font-medium transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
|
|
531
529
|
onClick={handleMakeHotspot}
|
|
532
530
|
>
|
|
533
531
|
Make hotspot
|
|
@@ -550,7 +548,7 @@ export function HotspotTool({
|
|
|
550
548
|
<button
|
|
551
549
|
type="button"
|
|
552
550
|
aria-label={`Remove hotspot ${h.label}`}
|
|
553
|
-
className="text-[10px] text-neutral-500 hover:text-
|
|
551
|
+
className="text-[10px] text-neutral-500 hover:text-danger-ink transition-colors"
|
|
554
552
|
onClick={() => onRemoveHotspot(selectedSceneId, h.id)}
|
|
555
553
|
>
|
|
556
554
|
✕
|
|
@@ -215,7 +215,7 @@ export function VariablesBindElement({
|
|
|
215
215
|
className={`${VARIABLES_INPUT_CLASS} font-mono`}
|
|
216
216
|
/>
|
|
217
217
|
{existingDecl && (
|
|
218
|
-
<p className="text-[9px] leading-snug text-
|
|
218
|
+
<p className="text-[9px] leading-snug text-warning-ink">
|
|
219
219
|
"{trimmedId}" already exists. This element will use its current value
|
|
220
220
|
{existingDecl.default !== undefined && (
|
|
221
221
|
<span className="font-mono"> ({String(existingDecl.default)})</span>
|
|
@@ -299,7 +299,7 @@ export function DeclarationForm({
|
|
|
299
299
|
className={VARIABLES_INPUT_CLASS}
|
|
300
300
|
/>
|
|
301
301
|
</Field>
|
|
302
|
-
{error && <p className="text-[10px] text-
|
|
302
|
+
{error && <p className="text-[10px] text-danger-ink">{error}</p>}
|
|
303
303
|
<div className="flex items-center justify-end gap-2 pt-1">
|
|
304
304
|
<button
|
|
305
305
|
type="button"
|
|
@@ -56,9 +56,9 @@ function formatIssue(issue: VariableValidationIssue): string {
|
|
|
56
56
|
function ValidationStrip({ issues }: { issues: VariableValidationIssue[] }) {
|
|
57
57
|
if (issues.length === 0) return null;
|
|
58
58
|
return (
|
|
59
|
-
<div className="space-y-1 rounded-lg border border-
|
|
59
|
+
<div className="space-y-1 rounded-lg border border-danger/40 bg-danger/15 p-2">
|
|
60
60
|
{issues.map((issue) => (
|
|
61
|
-
<p key={`${issue.kind}:${issue.variableId}`} className="text-[10px] text-
|
|
61
|
+
<p key={`${issue.kind}:${issue.variableId}`} className="text-[10px] text-danger-ink">
|
|
62
62
|
{formatIssue(issue)}
|
|
63
63
|
</p>
|
|
64
64
|
))}
|
|
@@ -99,7 +99,7 @@ function VariableRow({
|
|
|
99
99
|
</span>
|
|
100
100
|
{unused && (
|
|
101
101
|
<span
|
|
102
|
-
className="rounded-sm bg-amber-
|
|
102
|
+
className="rounded-sm bg-amber-500/15 px-1 py-px text-[8px] text-warning-ink"
|
|
103
103
|
title="No script reads this variable"
|
|
104
104
|
>
|
|
105
105
|
unused
|
|
@@ -175,9 +175,7 @@ function PreviewModeHeader({
|
|
|
175
175
|
<span className="text-[11px] font-semibold text-neutral-200">Variables</span>
|
|
176
176
|
<span
|
|
177
177
|
className={`rounded-full px-2 py-0.5 text-[9px] font-medium ${
|
|
178
|
-
hasOverrides
|
|
179
|
-
? "bg-studio-accent/20 text-studio-accent"
|
|
180
|
-
: "bg-neutral-800 text-neutral-500"
|
|
178
|
+
hasOverrides ? "bg-studio-accent/20 text-accent-ink" : "bg-neutral-800 text-neutral-500"
|
|
181
179
|
}`}
|
|
182
180
|
>
|
|
183
181
|
{hasOverrides ? `Previewing ${overrideCount} custom` : "Previewing defaults"}
|
|
@@ -16,7 +16,7 @@ export function RowAction({
|
|
|
16
16
|
onClick={onClick}
|
|
17
17
|
title={title}
|
|
18
18
|
className={`h-5 rounded px-1.5 text-[9px] text-neutral-500 hover:bg-neutral-800 ${
|
|
19
|
-
danger ? "hover:text-
|
|
19
|
+
danger ? "hover:text-danger-ink" : "hover:text-neutral-200"
|
|
20
20
|
}`}
|
|
21
21
|
>
|
|
22
22
|
{label}
|
|
@@ -67,7 +67,7 @@ export const FfmpegRequiredNotice = memo(function FfmpegRequiredNotice({
|
|
|
67
67
|
className="flex flex-col gap-2 rounded-xl border border-amber-500/30 bg-amber-500/10 p-2.5"
|
|
68
68
|
>
|
|
69
69
|
<div className="flex flex-col gap-0.5">
|
|
70
|
-
<span className="text-[11px] font-semibold text-
|
|
70
|
+
<span className="text-[11px] font-semibold text-warning-ink">
|
|
71
71
|
{status.title ?? "FFmpeg not found"}
|
|
72
72
|
</span>
|
|
73
73
|
{/* text-2, not the panel's usual text-4 for secondary copy: the amber
|
|
@@ -81,7 +81,7 @@ export const FfmpegRequiredNotice = memo(function FfmpegRequiredNotice({
|
|
|
81
81
|
|
|
82
82
|
{status.command ? (
|
|
83
83
|
<div className="flex items-center gap-1.5">
|
|
84
|
-
<code className="flex-1 overflow-x-auto whitespace-nowrap rounded-xs bg-
|
|
84
|
+
<code className="flex-1 overflow-x-auto whitespace-nowrap rounded-xs bg-input px-2 py-1 text-[10px] text-panel-text-2">
|
|
85
85
|
{status.command}
|
|
86
86
|
</code>
|
|
87
87
|
{/* Fixed width so swapping the label to "Copied" cannot shift the
|
|
@@ -89,7 +89,7 @@ export const FfmpegRequiredNotice = memo(function FfmpegRequiredNotice({
|
|
|
89
89
|
<button
|
|
90
90
|
type="button"
|
|
91
91
|
onClick={() => void copy(status.command ?? "")}
|
|
92
|
-
className={`h-6 w-14 shrink-0 rounded-xs border border-amber-500/30 text-[10px] font-medium text-
|
|
92
|
+
className={`h-6 w-14 shrink-0 rounded-xs border border-amber-500/30 text-[10px] font-medium text-warning-ink transition-colors hover:bg-amber-500/20 active:scale-[0.98] ${FOCUS_RING}`}
|
|
93
93
|
>
|
|
94
94
|
{copied ? "Copied" : "Copy"}
|
|
95
95
|
</button>
|
|
@@ -107,7 +107,7 @@ export const FfmpegRequiredNotice = memo(function FfmpegRequiredNotice({
|
|
|
107
107
|
type="button"
|
|
108
108
|
onClick={onRecheck}
|
|
109
109
|
disabled={checking}
|
|
110
|
-
className={`rounded-xs py-0.5 text-[10px] font-medium text-
|
|
110
|
+
className={`rounded-xs py-0.5 text-[10px] font-medium text-warning-ink underline-offset-2 transition-colors hover:underline disabled:opacity-50 ${FOCUS_RING}`}
|
|
111
111
|
>
|
|
112
112
|
{checking ? "Checking…" : "Recheck"}
|
|
113
113
|
</button>
|
|
@@ -467,7 +467,7 @@ export const RenderQueue = memo(function RenderQueue({
|
|
|
467
467
|
role="alert"
|
|
468
468
|
className="flex items-start justify-between gap-2 px-3 py-2 border-b border-border bg-danger/10"
|
|
469
469
|
>
|
|
470
|
-
<span className="text-step-10 text-danger">{actionError}</span>
|
|
470
|
+
<span className="text-step-10 text-danger-ink">{actionError}</span>
|
|
471
471
|
{onDismissActionError && (
|
|
472
472
|
<IconButton
|
|
473
473
|
size="sm"
|
|
@@ -497,7 +497,7 @@ export const RenderQueue = memo(function RenderQueue({
|
|
|
497
497
|
<div ref={listRef} className="flex-1 overflow-y-auto">
|
|
498
498
|
{loadError && jobs.length === 0 ? (
|
|
499
499
|
<div className="flex flex-col items-center justify-center h-full px-4 gap-2" role="alert">
|
|
500
|
-
<p className="text-step-10 text-danger text-center">{loadError}</p>
|
|
500
|
+
<p className="text-step-10 text-danger-ink text-center">{loadError}</p>
|
|
501
501
|
{onRetryLoad && (
|
|
502
502
|
<Button size="sm" variant="secondary" onClick={onRetryLoad}>
|
|
503
503
|
Retry
|
|
@@ -115,7 +115,7 @@ export const RenderQueueItem = memo(function RenderQueueItem({
|
|
|
115
115
|
)}
|
|
116
116
|
{job.status === "failed" && (
|
|
117
117
|
<div className="w-full h-full flex items-center justify-center">
|
|
118
|
-
<div className="w-2 h-2 rounded-full bg-danger" />
|
|
118
|
+
<div className="w-2 h-2 rounded-full bg-danger-ink" />
|
|
119
119
|
</div>
|
|
120
120
|
)}
|
|
121
121
|
{job.status === "cancelled" && (
|
|
@@ -140,7 +140,7 @@ export const RenderQueueItem = memo(function RenderQueueItem({
|
|
|
140
140
|
<div className="mt-1">
|
|
141
141
|
<div className="flex items-center justify-between mb-0.5">
|
|
142
142
|
<span className="text-step-9 text-text-4">{job.stage || "Rendering"}</span>
|
|
143
|
-
<span className="text-step-9 font-mono text-accent">{job.progress}%</span>
|
|
143
|
+
<span className="text-step-9 font-mono text-accent-ink">{job.progress}%</span>
|
|
144
144
|
</div>
|
|
145
145
|
<div
|
|
146
146
|
className="w-full h-1 bg-border rounded-full overflow-hidden"
|
|
@@ -159,7 +159,7 @@ export const RenderQueueItem = memo(function RenderQueueItem({
|
|
|
159
159
|
)}
|
|
160
160
|
|
|
161
161
|
{job.status === "failed" && job.error && (
|
|
162
|
-
<span className="text-step-9 text-danger mt-0.5 block">{job.error}</span>
|
|
162
|
+
<span className="text-step-9 text-danger-ink mt-0.5 block">{job.error}</span>
|
|
163
163
|
)}
|
|
164
164
|
{job.status === "cancelled" && (
|
|
165
165
|
<span className="text-step-9 text-text-4 mt-0.5 block">Cancelled</span>
|
|
@@ -31,7 +31,7 @@ function CopyChip({ feedback, asset }: { feedback: CopyFeedback; asset: string }
|
|
|
31
31
|
<span
|
|
32
32
|
role="status"
|
|
33
33
|
className={`shrink-0 text-[9px] font-medium px-1.5 py-px rounded ${
|
|
34
|
-
feedback.ok ? "text-
|
|
34
|
+
feedback.ok ? "text-accent-ink bg-panel-accent/10" : "text-danger-ink bg-red-500/10"
|
|
35
35
|
}`}
|
|
36
36
|
>
|
|
37
37
|
{feedback.ok ? "Copied" : "Copy failed"}
|
|
@@ -355,7 +355,7 @@ export function FontRow({
|
|
|
355
355
|
}`}
|
|
356
356
|
>
|
|
357
357
|
<div className="w-[50px] h-[32px] rounded-sm overflow-hidden bg-neutral-900 shrink-0 flex items-center justify-center">
|
|
358
|
-
<span className="text-[9px] font-medium text-
|
|
358
|
+
<span className="text-[9px] font-medium text-text-muted">{extension}</span>
|
|
359
359
|
</div>
|
|
360
360
|
<div className="min-w-0 flex-1">
|
|
361
361
|
<span
|
|
@@ -366,7 +366,7 @@ export function FontRow({
|
|
|
366
366
|
<div className="flex items-center gap-1.5">
|
|
367
367
|
<span className="text-[10px] text-neutral-600 truncate">{extension}</span>
|
|
368
368
|
{used && (
|
|
369
|
-
<span className="text-[9px] font-medium text-
|
|
369
|
+
<span className="text-[9px] font-medium text-accent-ink bg-panel-accent/10 px-1.5 py-px rounded-sm">
|
|
370
370
|
in use
|
|
371
371
|
</span>
|
|
372
372
|
)}
|
|
@@ -147,7 +147,7 @@ export function ContextMenu({
|
|
|
147
147
|
<button
|
|
148
148
|
role="menuitem"
|
|
149
149
|
onClick={() => setMode("confirm-delete")}
|
|
150
|
-
className={`${itemCls} text-
|
|
150
|
+
className={`${itemCls} text-danger-ink`}
|
|
151
151
|
>
|
|
152
152
|
Delete
|
|
153
153
|
</button>
|
|
@@ -181,9 +181,9 @@ export function ContextMenu({
|
|
|
181
181
|
}
|
|
182
182
|
}}
|
|
183
183
|
aria-label={`Rename ${filename(asset)}`}
|
|
184
|
-
className="w-full bg-neutral-800 border border-neutral-600 rounded-sm px-1.5 py-1 text-[11px] text-
|
|
184
|
+
className="w-full bg-neutral-800 border border-neutral-600 rounded-sm px-1.5 py-1 text-[11px] text-text-0 focus:border-studio-accent/60 focus:outline-hidden"
|
|
185
185
|
/>
|
|
186
|
-
{renameError && <span className="text-[10px] text-
|
|
186
|
+
{renameError && <span className="text-[10px] text-danger-ink">{renameError}</span>}
|
|
187
187
|
<div className="flex items-center justify-end gap-1">
|
|
188
188
|
<button
|
|
189
189
|
onClick={() => setMode("menu")}
|
|
@@ -193,7 +193,7 @@ export function ContextMenu({
|
|
|
193
193
|
</button>
|
|
194
194
|
<button
|
|
195
195
|
onClick={commitRename}
|
|
196
|
-
className="px-2 py-0.5 text-[10px] rounded-sm bg-
|
|
196
|
+
className="px-2 py-0.5 text-[10px] rounded-sm bg-accent hover:bg-accent-hover text-on-accent transition-colors"
|
|
197
197
|
>
|
|
198
198
|
Rename
|
|
199
199
|
</button>
|
|
@@ -215,12 +215,12 @@ function DeleteConfirm({
|
|
|
215
215
|
onCancel: () => void;
|
|
216
216
|
}) {
|
|
217
217
|
return (
|
|
218
|
-
<div className="px-2 py-1.5 bg-
|
|
219
|
-
<span className="text-[10px] text-
|
|
218
|
+
<div className="px-2 py-1.5 bg-danger/15 border-l-2 border-red-500 flex items-center justify-between gap-2">
|
|
219
|
+
<span className="text-[10px] text-danger-ink truncate">Delete {name}?</span>
|
|
220
220
|
<div className="flex items-center gap-1 shrink-0">
|
|
221
221
|
<button
|
|
222
222
|
onClick={onConfirm}
|
|
223
|
-
className="px-2 py-0.5 text-[10px] rounded-sm bg-
|
|
223
|
+
className="px-2 py-0.5 text-[10px] rounded-sm bg-danger text-on-danger hover:brightness-95 active:brightness-90 transition-colors"
|
|
224
224
|
>
|
|
225
225
|
Delete
|
|
226
226
|
</button>
|
|
@@ -177,7 +177,7 @@ function EmptyState({
|
|
|
177
177
|
fill="none"
|
|
178
178
|
stroke="currentColor"
|
|
179
179
|
strokeWidth="1.5"
|
|
180
|
-
className="text-
|
|
180
|
+
className="text-text-off"
|
|
181
181
|
>
|
|
182
182
|
<path
|
|
183
183
|
d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"
|
|
@@ -349,7 +349,7 @@ export const AssetsTab = memo(function AssetsTab({
|
|
|
349
349
|
onClick={() => setViewMode(m)}
|
|
350
350
|
className={`flex-1 px-2 py-1 text-[11px] font-medium rounded transition-colors ${
|
|
351
351
|
viewMode === m
|
|
352
|
-
? "bg-panel-accent/15 text-
|
|
352
|
+
? "bg-panel-accent/15 text-accent-ink"
|
|
353
353
|
: "text-panel-text-3 hover:text-panel-text-1"
|
|
354
354
|
}`}
|
|
355
355
|
>
|
|
@@ -396,7 +396,7 @@ export const AssetsTab = memo(function AssetsTab({
|
|
|
396
396
|
aria-pressed={activeFilter === "all"}
|
|
397
397
|
className={`px-2.5 py-1 text-[11px] font-medium rounded-md transition-colors active:scale-[0.98] ${
|
|
398
398
|
activeFilter === "all"
|
|
399
|
-
? "bg-panel-accent/15 text-
|
|
399
|
+
? "bg-panel-accent/15 text-accent-ink"
|
|
400
400
|
: "bg-panel-input text-panel-text-3 hover:text-panel-text-1"
|
|
401
401
|
}`}
|
|
402
402
|
>
|
|
@@ -410,7 +410,7 @@ export const AssetsTab = memo(function AssetsTab({
|
|
|
410
410
|
aria-pressed={activeFilter === cat}
|
|
411
411
|
className={`px-2.5 py-1 text-[11px] font-medium rounded-md transition-colors active:scale-[0.98] ${
|
|
412
412
|
activeFilter === cat
|
|
413
|
-
? "bg-panel-accent/15 text-
|
|
413
|
+
? "bg-panel-accent/15 text-accent-ink"
|
|
414
414
|
: "bg-panel-input text-panel-text-3 hover:text-panel-text-1"
|
|
415
415
|
}`}
|
|
416
416
|
>
|
|
@@ -425,7 +425,7 @@ export const AssetsTab = memo(function AssetsTab({
|
|
|
425
425
|
onClick={() => setUsageFilter(usageFilter === "used" ? "all" : "used")}
|
|
426
426
|
className={`px-2.5 py-1 text-[11px] font-medium rounded-md transition-colors ${
|
|
427
427
|
usageFilter === "used"
|
|
428
|
-
? "bg-panel-accent/15 text-
|
|
428
|
+
? "bg-panel-accent/15 text-accent-ink"
|
|
429
429
|
: "bg-panel-input text-panel-text-3 hover:text-panel-text-1"
|
|
430
430
|
}`}
|
|
431
431
|
>
|
|
@@ -435,7 +435,7 @@ export const AssetsTab = memo(function AssetsTab({
|
|
|
435
435
|
onClick={() => setUsageFilter(usageFilter === "unused" ? "all" : "unused")}
|
|
436
436
|
className={`px-2.5 py-1 text-[11px] font-medium rounded-md transition-colors ${
|
|
437
437
|
usageFilter === "unused"
|
|
438
|
-
? "bg-panel-accent/15 text-
|
|
438
|
+
? "bg-panel-accent/15 text-accent-ink"
|
|
439
439
|
: "bg-panel-input text-panel-text-3 hover:text-panel-text-1"
|
|
440
440
|
}`}
|
|
441
441
|
>
|
|
@@ -240,7 +240,7 @@ export function AudioRow({
|
|
|
240
240
|
aria-pressed={playing}
|
|
241
241
|
className={`w-7 h-7 rounded-md shrink-0 flex items-center justify-center transition-colors active:scale-[0.95] ${
|
|
242
242
|
playing
|
|
243
|
-
? "bg-panel-accent/15 text-
|
|
243
|
+
? "bg-panel-accent/15 text-accent-ink"
|
|
244
244
|
: "text-panel-text-5 group-hover:text-panel-text-3"
|
|
245
245
|
}`}
|
|
246
246
|
onClick={(e) => {
|
|
@@ -273,7 +273,7 @@ export function AudioRow({
|
|
|
273
273
|
</span>
|
|
274
274
|
)}
|
|
275
275
|
{used && (
|
|
276
|
-
<span className="text-[9px] font-medium text-
|
|
276
|
+
<span className="text-[9px] font-medium text-accent-ink bg-panel-accent/10 px-1.5 py-px rounded-sm shrink-0">
|
|
277
277
|
in use
|
|
278
278
|
</span>
|
|
279
279
|
)}
|
|
@@ -281,7 +281,9 @@ export function AudioRow({
|
|
|
281
281
|
<span
|
|
282
282
|
role="status"
|
|
283
283
|
className={`shrink-0 text-[9px] font-medium px-1.5 py-px rounded ${
|
|
284
|
-
copyFailed
|
|
284
|
+
copyFailed
|
|
285
|
+
? "text-danger-ink bg-red-500/10"
|
|
286
|
+
: "text-accent-ink bg-panel-accent/10"
|
|
285
287
|
}`}
|
|
286
288
|
>
|
|
287
289
|
{copyFailed ? "Copy failed" : "Copied"}
|
|
@@ -40,7 +40,7 @@ export const BlocksTab = memo(function BlocksTab({ onAddBlock, onPreviewBlock }:
|
|
|
40
40
|
|
|
41
41
|
if (error) {
|
|
42
42
|
return (
|
|
43
|
-
<div className="flex flex-1 items-center justify-center text-
|
|
43
|
+
<div className="flex flex-1 items-center justify-center text-danger-ink text-xs px-4 text-center">
|
|
44
44
|
{error}
|
|
45
45
|
</div>
|
|
46
46
|
);
|
|
@@ -77,9 +77,9 @@ export const BlocksTab = memo(function BlocksTab({ onAddBlock, onPreviewBlock }:
|
|
|
77
77
|
{/* Block grid */}
|
|
78
78
|
<div className="flex-1 overflow-y-auto min-h-0 px-2 pb-2">
|
|
79
79
|
{category === "vfx" && (
|
|
80
|
-
<div className="mb-2 px-2 py-1.5 rounded-md bg-purple-500/10 border border-purple-500/20 text-[9px] text-
|
|
80
|
+
<div className="mb-2 px-2 py-1.5 rounded-md bg-purple-500/10 border border-purple-500/20 text-[9px] text-text-2 leading-relaxed">
|
|
81
81
|
VFX blocks use WebGL via HTML-in-Canvas. Enable{" "}
|
|
82
|
-
<span className="font-mono text-
|
|
82
|
+
<span className="font-mono text-text-0">chrome://flags/#html-in-canvas</span> for
|
|
83
83
|
preview.
|
|
84
84
|
</div>
|
|
85
85
|
)}
|
|
@@ -423,8 +423,8 @@ function BlockCard({
|
|
|
423
423
|
title="Add to composition at current time"
|
|
424
424
|
className={`flex items-center gap-1 px-3 py-1.5 rounded-md text-[10px] font-semibold transition-colors active:scale-[0.97] ${
|
|
425
425
|
addState === "failed"
|
|
426
|
-
? "bg-
|
|
427
|
-
: "bg-white text-black hover:bg-
|
|
426
|
+
? "bg-danger text-on-danger"
|
|
427
|
+
: "bg-white text-black hover:bg-white/85"
|
|
428
428
|
}`}
|
|
429
429
|
>
|
|
430
430
|
<svg
|
|
@@ -453,7 +453,7 @@ function BlockCard({
|
|
|
453
453
|
className={`flex items-center gap-1.5 px-3 ${onAdd ? "py-1" : "py-1.5"} rounded-md transition-colors active:scale-[0.97] ${
|
|
454
454
|
onAdd
|
|
455
455
|
? "bg-white/15 text-white/90 hover:bg-white/25 text-[9px]"
|
|
456
|
-
: "bg-
|
|
456
|
+
: "bg-text-0 text-bg-0 hover:bg-text-2 text-[10px] font-semibold"
|
|
457
457
|
}`}
|
|
458
458
|
>
|
|
459
459
|
<svg
|