@hyperframes/studio 0.7.57 → 0.7.59
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--Z69cEkE.js → hyperframes-player-Bm07FLkl.js} +1 -1
- package/dist/assets/{index-KsfE1bUu.js → index-B995FG46.js} +1 -1
- package/dist/assets/index-CrkAdJkb.js +426 -0
- package/dist/assets/index-Dj5p8U_A.css +1 -0
- package/dist/assets/{index-Bf1x1y8H.js → index-FvzmPhfG.js} +1 -1
- package/dist/{chunk-5QSIMBEJ.js → chunk-OBAG3GWK.js} +33 -21
- package/dist/chunk-OBAG3GWK.js.map +1 -0
- package/dist/{domEditingLayers-6LQGKPOI.js → domEditingLayers-2CKWGEHS.js} +2 -2
- package/dist/index.d.ts +27 -7
- package/dist/index.html +2 -2
- package/dist/index.js +18029 -11563
- package/dist/index.js.map +1 -1
- package/dist/styles/tailwind-preset.d.ts +5 -0
- package/dist/styles/tailwind-preset.js +8 -1
- package/dist/styles/tailwind-preset.js.map +1 -1
- package/package.json +7 -7
- package/src/App.tsx +6 -6
- package/src/components/DesignPanelPromoteProvider.tsx +15 -2
- package/src/components/StudioFeedbackBar.tsx +2 -2
- package/src/components/StudioRightPanel.tsx +29 -51
- package/src/components/editor/AnimationCard.test.tsx +134 -0
- package/src/components/editor/AnimationCard.tsx +19 -4
- package/src/components/editor/ArcPathControls.tsx +1 -0
- package/src/components/editor/CanvasContextMenu.test.tsx +27 -14
- package/src/components/editor/CanvasContextMenu.tsx +71 -6
- package/src/components/editor/DomEditOverlay.tsx +5 -2
- package/src/components/editor/GestureRecordControl.tsx +7 -1
- package/src/components/editor/GsapAnimationSection.tsx +109 -14
- package/src/components/editor/InspectorHeaderActions.tsx +42 -4
- package/src/components/editor/LayersPanel.tsx +110 -99
- package/src/components/editor/PropertyPanel.test.tsx +948 -0
- package/src/components/editor/PropertyPanel.tsx +144 -148
- package/src/components/editor/PropertyPanelEmptyState.test.tsx +74 -0
- package/src/components/editor/PropertyPanelEmptyState.tsx +179 -1
- package/src/components/editor/PropertyPanelFlat.tsx +580 -0
- package/src/components/editor/PropertyPanelFlatFooter.test.tsx +83 -0
- package/src/components/editor/PropertyPanelFlatFooter.tsx +73 -0
- package/src/components/editor/PropertyPanelFlatHeader.test.tsx +79 -0
- package/src/components/editor/PropertyPanelFlatHeader.tsx +112 -0
- package/src/components/editor/canvasContextMenuZOrder.test.ts +57 -0
- package/src/components/editor/canvasContextMenuZOrder.ts +40 -1
- package/src/components/editor/domEditingDom.ts +5 -6
- package/src/components/editor/domEditingElement.ts +15 -32
- package/src/components/editor/gsapAnimationCallbacks.ts +27 -0
- package/src/components/editor/gsapLivePreview.ts +34 -0
- package/src/components/editor/layersPanelSort.ts +80 -0
- package/src/components/editor/manualEditingAvailability.test.ts +10 -0
- package/src/components/editor/manualEditingAvailability.ts +9 -0
- package/src/components/editor/propertyPanel3dTransform.tsx +5 -0
- package/src/components/editor/propertyPanelColor.test.tsx +28 -0
- package/src/components/editor/propertyPanelColor.tsx +31 -1
- package/src/components/editor/propertyPanelColorGradingControls.tsx +11 -2
- package/src/components/editor/propertyPanelColorGradingSection.tsx +45 -365
- package/src/components/editor/propertyPanelColorGradingSlider.tsx +19 -5
- package/src/components/editor/propertyPanelFill.tsx +22 -5
- package/src/components/editor/propertyPanelFlatColorGradingSection.test.tsx +622 -0
- package/src/components/editor/propertyPanelFlatColorGradingSection.tsx +570 -0
- package/src/components/editor/propertyPanelFlatLayoutSection.test.tsx +293 -0
- package/src/components/editor/propertyPanelFlatLayoutSection.tsx +383 -0
- package/src/components/editor/propertyPanelFlatMaskInsetRows.tsx +102 -0
- package/src/components/editor/propertyPanelFlatMediaSection.test.tsx +436 -0
- package/src/components/editor/propertyPanelFlatMediaSection.tsx +286 -0
- package/src/components/editor/propertyPanelFlatMotionSection.test.tsx +272 -0
- package/src/components/editor/propertyPanelFlatMotionSection.tsx +315 -0
- package/src/components/editor/propertyPanelFlatPrimitives.test.tsx +1174 -0
- package/src/components/editor/propertyPanelFlatPrimitives.tsx +563 -0
- package/src/components/editor/propertyPanelFlatSelectRow.tsx +101 -0
- package/src/components/editor/propertyPanelFlatStyleHelpers.test.ts +23 -0
- package/src/components/editor/propertyPanelFlatStyleHelpers.ts +27 -0
- package/src/components/editor/propertyPanelFlatStyleSections.test.tsx +598 -0
- package/src/components/editor/propertyPanelFlatStyleSections.tsx +516 -0
- package/src/components/editor/propertyPanelFlatTextSection.test.tsx +465 -0
- package/src/components/editor/propertyPanelFlatTextSection.tsx +407 -0
- package/src/components/editor/propertyPanelFlatTimingDerivation.test.ts +71 -0
- package/src/components/editor/propertyPanelFlatTimingDerivation.ts +59 -0
- package/src/components/editor/propertyPanelFlatToggle.test.tsx +63 -0
- package/src/components/editor/propertyPanelFlatToggle.tsx +53 -0
- package/src/components/editor/propertyPanelFont.test.tsx +30 -0
- package/src/components/editor/propertyPanelFont.tsx +136 -95
- package/src/components/editor/propertyPanelHelpers.ts +73 -0
- package/src/components/editor/propertyPanelInputCoverage.test.tsx +587 -0
- package/src/components/editor/propertyPanelMediaSection.tsx +10 -0
- package/src/components/editor/propertyPanelPrimitives.tsx +60 -29
- package/src/components/editor/propertyPanelSections.test.tsx +161 -0
- package/src/components/editor/propertyPanelSections.tsx +154 -90
- package/src/components/editor/propertyPanelStyleSections.tsx +12 -1
- package/src/components/editor/propertyPanelTimingSection.tsx +1 -1
- package/src/components/editor/propertyPanelTypes.ts +14 -1
- package/src/components/editor/propertyPanelValueTier.test.ts +32 -0
- package/src/components/editor/propertyPanelValueTier.ts +28 -0
- package/src/components/editor/useColorGradingController.test.ts +418 -0
- package/src/components/editor/useColorGradingController.ts +596 -0
- package/src/components/editor/useLayerRevealOverride.test.ts +169 -0
- package/src/components/editor/useLayerRevealOverride.ts +389 -0
- package/src/components/nle/PreviewOverlays.tsx +27 -2
- package/src/components/nle/TimelinePane.test.ts +3 -0
- package/src/components/nle/TimelinePane.tsx +11 -1
- package/src/components/nle/useCanvasZOrderTimelineMirror.test.tsx +440 -0
- package/src/components/nle/useCanvasZOrderTimelineMirror.ts +191 -0
- package/src/components/nle/useTimelineEditCallbacks.ts +1 -0
- package/src/components/nle/zLaneGesture.test.ts +176 -0
- package/src/components/nle/zLaneGesture.ts +77 -0
- package/src/components/panels/VariablesPanel.tsx +4 -0
- package/src/components/sidebar/CompositionsTab.test.ts +28 -2
- package/src/components/sidebar/CompositionsTab.tsx +3 -1
- package/src/components/storyboard/FramePoster.tsx +24 -4
- package/src/components/storyboard/StoryboardFrameFocus.tsx +4 -0
- package/src/components/storyboard/StoryboardFrameTile.tsx +30 -1
- package/src/components/storyboard/StoryboardGrid.tsx +23 -1
- package/src/components/storyboard/StoryboardLoaded.tsx +58 -2
- package/src/components/storyboard/StoryboardView.tsx +9 -2
- package/src/components/storyboard/frameComments.test.ts +95 -0
- package/src/components/storyboard/frameComments.ts +115 -0
- package/src/components/storyboard/useFrameComments.ts +82 -0
- package/src/contexts/DesignPanelInputContext.test.tsx +81 -0
- package/src/contexts/DesignPanelInputContext.tsx +48 -0
- package/src/contexts/DomEditContext.tsx +4 -0
- package/src/contexts/VariablePromoteContext.test.tsx +67 -0
- package/src/contexts/VariablePromoteContext.tsx +10 -5
- package/src/hooks/domEditCommitRunner.ts +11 -0
- package/src/hooks/domEditCommitTypes.ts +17 -1
- package/src/hooks/elementLifecycleOpsTestUtils.ts +25 -0
- package/src/hooks/fetchStubTestUtils.ts +16 -0
- package/src/hooks/gsapScriptCommitTypes.ts +6 -4
- package/src/hooks/timelineEditingHelpers.test.ts +92 -1
- package/src/hooks/timelineEditingHelpers.ts +32 -15
- package/src/hooks/timelineMoveAdapter.ts +2 -1
- package/src/hooks/timelineTimingSync.test.ts +703 -33
- package/src/hooks/timelineTimingSync.ts +282 -97
- package/src/hooks/timelineTrackVisibility.test.ts +55 -1
- package/src/hooks/timelineTrackVisibility.ts +31 -13
- package/src/hooks/useAppHotkeys.ts +9 -0
- package/src/hooks/useClipboard.ts +19 -17
- package/src/hooks/useDomEditAttributeCommits.ts +123 -1
- package/src/hooks/useDomEditCommits.test.tsx +316 -38
- package/src/hooks/useDomEditCommits.ts +81 -162
- package/src/hooks/useDomEditCommitsHelpers.ts +158 -0
- package/src/hooks/useDomEditSession.test.tsx +3 -1
- package/src/hooks/useDomEditSession.ts +18 -6
- package/src/hooks/useDomEditTextCommits.ts +14 -9
- package/src/hooks/useDomEditWiring.ts +10 -9
- package/src/hooks/useElementLifecycleOps.test.tsx +426 -60
- package/src/hooks/useElementLifecycleOps.ts +182 -84
- package/src/hooks/useFileManager.projectOwnership.test.tsx +98 -0
- package/src/hooks/useFileManager.ts +82 -60
- package/src/hooks/useGsapAnimationOps.ts +7 -6
- package/src/hooks/useGsapKeyframeOps.ts +6 -5
- package/src/hooks/useGsapPropertyDebounce.ts +43 -28
- package/src/hooks/useGsapPropertyDebounceFlush.test.ts +35 -0
- package/src/hooks/useGsapScriptCommits.test.tsx +48 -2
- package/src/hooks/useGsapScriptCommits.ts +150 -50
- package/src/hooks/useGsapSelectionHandlers.test.tsx +116 -0
- package/src/hooks/useGsapSelectionHandlers.ts +94 -31
- package/src/hooks/useInspectorSplitResize.ts +51 -0
- package/src/hooks/usePersistentEditHistory.projectOwnership.test.tsx +60 -0
- package/src/hooks/usePersistentEditHistory.test.ts +49 -1
- package/src/hooks/usePersistentEditHistory.ts +71 -31
- package/src/hooks/usePreviewPersistence.ts +2 -2
- package/src/hooks/useProjectCompositionVariables.ts +10 -10
- package/src/hooks/useProjectSignaturePoll.test.tsx +135 -0
- package/src/hooks/useProjectSignaturePoll.ts +68 -0
- package/src/hooks/useSdkSession.lifecycle.test.tsx +137 -0
- package/src/hooks/useSdkSession.ts +155 -14
- package/src/hooks/useSlideshowPersist.ts +7 -1
- package/src/hooks/useStoryboard.ts +23 -4
- package/src/hooks/useTimelineEditing.test.tsx +306 -155
- package/src/hooks/useTimelineEditing.ts +111 -101
- package/src/hooks/useTimelineEditingTypes.ts +4 -1
- package/src/hooks/useTimelineGroupEditing.ts +51 -5
- package/src/hooks/useVariablesPersist.ts +9 -7
- package/src/icons/SystemIcons.tsx +2 -0
- package/src/player/components/Timeline.test.ts +31 -21
- package/src/player/components/Timeline.tsx +62 -91
- package/src/player/components/TimelineCanvas.tsx +36 -5
- package/src/player/components/TimelineLanes.tsx +32 -10
- package/src/player/components/TimelineOverlays.tsx +36 -0
- package/src/player/components/TimelineRuler.tsx +18 -5
- package/src/player/components/TrackGapContextMenu.tsx +116 -0
- package/src/player/components/timelineCallbacks.ts +4 -1
- package/src/player/components/timelineClipDragCommit.test.ts +279 -3
- package/src/player/components/timelineClipDragCommit.ts +173 -71
- package/src/player/components/timelineGapCommit.test.ts +163 -0
- package/src/player/components/timelineGapCommit.ts +103 -0
- package/src/player/components/timelineGaps.test.ts +221 -0
- package/src/player/components/timelineGaps.ts +182 -0
- package/src/player/components/timelineLayout.test.ts +2 -1
- package/src/player/components/timelineLayout.ts +22 -6
- package/src/player/components/timelineMarquee.test.ts +20 -10
- package/src/player/components/timelineMarquee.ts +9 -2
- package/src/player/components/timelineStackingSync.test.ts +42 -1
- package/src/player/components/timelineStackingSync.ts +31 -16
- package/src/player/components/timelineZMirror.test.ts +667 -0
- package/src/player/components/timelineZMirror.ts +393 -0
- package/src/player/components/timelineZoom.test.ts +2 -2
- package/src/player/components/timelineZoom.ts +7 -3
- package/src/player/components/useTimelineClipDrag.ts +1 -1
- package/src/player/components/useTimelineGapHighlights.test.ts +119 -0
- package/src/player/components/useTimelineGapHighlights.ts +110 -0
- package/src/player/components/useTimelinePlayhead.ts +4 -3
- package/src/player/components/useTimelineRangeSelection.ts +6 -4
- package/src/player/components/useTimelineScrollViewport.ts +73 -0
- package/src/player/components/useTimelineStackingSync.test.tsx +0 -1
- package/src/player/components/useTimelineStackingSync.ts +5 -3
- package/src/player/components/useTimelineTrackDerivations.ts +38 -0
- package/src/player/components/useTrackGapMenu.ts +155 -0
- package/src/player/hooks/useExpandedTimelineElements.test.ts +67 -4
- package/src/player/hooks/useExpandedTimelineElements.ts +12 -1
- package/src/player/hooks/useTimelineSyncCallbacks.ts +2 -0
- package/src/player/lib/layerOrdering.test.ts +1 -15
- package/src/player/lib/layerOrdering.ts +5 -28
- package/src/player/lib/timelineDOM.test.ts +72 -0
- package/src/player/lib/timelineDOM.ts +3 -0
- package/src/player/lib/timelineElementHelpers.ts +35 -11
- package/src/player/store/playerStore.ts +12 -1
- package/src/styles/studio.css +22 -0
- package/src/styles/tailwind-preset.shared.js +7 -0
- package/src/telemetry/events.test.ts +10 -0
- package/src/telemetry/events.ts +1 -0
- package/src/utils/designInputTracking.test.ts +97 -0
- package/src/utils/designInputTracking.ts +80 -0
- package/src/utils/domEditSaveQueue.ts +4 -3
- package/src/utils/editHistory.test.ts +82 -0
- package/src/utils/editHistory.ts +14 -2
- package/src/utils/gsapSoftReload.test.ts +54 -115
- package/src/utils/gsapSoftReload.ts +42 -152
- package/src/utils/gsapUndoRestore.test.ts +269 -0
- package/src/utils/gsapUndoRestore.ts +269 -0
- package/src/utils/sdkCutover.gate.test.ts +7 -7
- package/src/utils/sdkCutover.test.ts +490 -57
- package/src/utils/sdkCutover.ts +181 -219
- package/src/utils/sdkEditTransaction.ts +292 -0
- package/src/utils/sdkResolverAttempts.ts +94 -0
- package/src/utils/sdkResolverShadow.test.ts +148 -0
- package/src/utils/sdkResolverShadow.ts +139 -106
- package/src/utils/setSlideshowManifest.test.ts +0 -9
- package/src/utils/setSlideshowManifest.ts +20 -27
- package/src/utils/sourceScopedSelectorIndex.ts +29 -0
- package/src/utils/studioFileHistory.test.ts +41 -0
- package/src/utils/studioFileHistory.ts +30 -27
- package/src/utils/studioFileMutationCoordinator.ts +45 -0
- package/src/utils/studioHelpers.test.ts +45 -0
- package/src/utils/studioHelpers.ts +45 -14
- package/src/utils/studioSaveDiagnostics.ts +17 -0
- package/dist/assets/index-DfmYkU44.js +0 -423
- package/dist/assets/index-_pqzyxB1.css +0 -1
- package/dist/chunk-5QSIMBEJ.js.map +0 -1
- /package/dist/{domEditingLayers-6LQGKPOI.js.map → domEditingLayers-2CKWGEHS.js.map} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
2
|
import { Minus, Plus, RotateCcw, Settings } from "../../icons/SystemIcons";
|
|
3
3
|
import { LABEL } from "./propertyPanelHelpers";
|
|
4
|
+
import { useTrackDesignInput } from "../../contexts/DesignPanelInputContext";
|
|
4
5
|
|
|
5
6
|
const SLIDER_THUMB_SIZE = 10;
|
|
6
7
|
const SLIDER_THUMB_RADIUS = SLIDER_THUMB_SIZE / 2;
|
|
@@ -59,9 +60,11 @@ export function ColorGradingSliderControl({
|
|
|
59
60
|
onClick: () => void;
|
|
60
61
|
};
|
|
61
62
|
}) {
|
|
63
|
+
const track = useTrackDesignInput();
|
|
62
64
|
const [draftState, setDraftState] = useState<{ value: number; source: number } | null>(null);
|
|
63
65
|
const [inputDraft, setInputDraft] = useState<{ value: string; source: number } | null>(null);
|
|
64
66
|
const commitTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
67
|
+
const interactionChangedRef = useRef(false);
|
|
65
68
|
const valueRef = useRef(value);
|
|
66
69
|
valueRef.current = value;
|
|
67
70
|
|
|
@@ -92,9 +95,13 @@ export function ColorGradingSliderControl({
|
|
|
92
95
|
(nextValue: number) => {
|
|
93
96
|
const clamped = setLocalDraft(nextValue);
|
|
94
97
|
if (commitTimerRef.current) clearTimeout(commitTimerRef.current);
|
|
98
|
+
if (interactionChangedRef.current) {
|
|
99
|
+
interactionChangedRef.current = false;
|
|
100
|
+
track("slider", label);
|
|
101
|
+
}
|
|
95
102
|
if (clamped !== valueRef.current) onCommit(clamped);
|
|
96
103
|
},
|
|
97
|
-
[onCommit, setLocalDraft],
|
|
104
|
+
[label, onCommit, setLocalDraft, track],
|
|
98
105
|
);
|
|
99
106
|
|
|
100
107
|
const scheduleCommit = useCallback(
|
|
@@ -115,6 +122,7 @@ export function ColorGradingSliderControl({
|
|
|
115
122
|
const commitInputDraft = useCallback(() => {
|
|
116
123
|
const parsed = parseNumericInput(inputValue, scale);
|
|
117
124
|
if (parsed === null) {
|
|
125
|
+
interactionChangedRef.current = false;
|
|
118
126
|
setInputDraft(null);
|
|
119
127
|
return;
|
|
120
128
|
}
|
|
@@ -123,6 +131,7 @@ export function ColorGradingSliderControl({
|
|
|
123
131
|
|
|
124
132
|
const nudge = useCallback(
|
|
125
133
|
(direction: -1 | 1) => {
|
|
134
|
+
interactionChangedRef.current = true;
|
|
126
135
|
commitDraft(draft + step * direction);
|
|
127
136
|
},
|
|
128
137
|
[commitDraft, draft, step],
|
|
@@ -166,6 +175,7 @@ export function ColorGradingSliderControl({
|
|
|
166
175
|
aria-label={`Reset ${label}`}
|
|
167
176
|
onClick={(event) => {
|
|
168
177
|
event.stopPropagation();
|
|
178
|
+
track("button", `Reset ${label}`);
|
|
169
179
|
onReset();
|
|
170
180
|
}}
|
|
171
181
|
className="flex h-5 w-5 flex-shrink-0 items-center justify-center rounded text-panel-text-5 transition-colors hover:bg-panel-hover hover:text-panel-text-1 disabled:cursor-not-allowed disabled:opacity-40"
|
|
@@ -205,7 +215,10 @@ export function ColorGradingSliderControl({
|
|
|
205
215
|
value={draft}
|
|
206
216
|
disabled={disabled}
|
|
207
217
|
aria-label={label}
|
|
208
|
-
onChange={(event) =>
|
|
218
|
+
onChange={(event) => {
|
|
219
|
+
interactionChangedRef.current = true;
|
|
220
|
+
scheduleCommit(Number(event.currentTarget.value));
|
|
221
|
+
}}
|
|
209
222
|
onMouseUp={() => commitDraft(draft)}
|
|
210
223
|
onTouchEnd={() => commitDraft(draft)}
|
|
211
224
|
onBlur={() => commitDraft(draft)}
|
|
@@ -223,9 +236,10 @@ export function ColorGradingSliderControl({
|
|
|
223
236
|
max={max / scale}
|
|
224
237
|
step={step / scale}
|
|
225
238
|
disabled={disabled}
|
|
226
|
-
onChange={(event) =>
|
|
227
|
-
|
|
228
|
-
|
|
239
|
+
onChange={(event) => {
|
|
240
|
+
interactionChangedRef.current = true;
|
|
241
|
+
setInputDraft({ value: event.currentTarget.value, source: valueRef.current });
|
|
242
|
+
}}
|
|
229
243
|
onBlur={commitInputDraft}
|
|
230
244
|
onKeyDown={(event) => {
|
|
231
245
|
if (event.key === "Enter") {
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
SliderControl,
|
|
17
17
|
} from "./propertyPanelPrimitives";
|
|
18
18
|
import { ColorField } from "./propertyPanelColor";
|
|
19
|
+
import { useTrackDesignInput } from "../../contexts/DesignPanelInputContext";
|
|
19
20
|
|
|
20
21
|
/* ------------------------------------------------------------------ */
|
|
21
22
|
/* Asset path helpers */
|
|
@@ -87,6 +88,7 @@ export function ImageFillField({
|
|
|
87
88
|
onCommit: (nextValue: string) => void;
|
|
88
89
|
onImportAssets?: (files: FileList) => Promise<string[]>;
|
|
89
90
|
}) {
|
|
91
|
+
const track = useTrackDesignInput();
|
|
90
92
|
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
|
91
93
|
const [uploading, setUploading] = useState(false);
|
|
92
94
|
const imageAssets = useMemo(() => assets.filter((a) => IMAGE_EXT.test(a)), [assets]);
|
|
@@ -102,7 +104,10 @@ export function ImageFillField({
|
|
|
102
104
|
try {
|
|
103
105
|
const uploaded = await onImportAssets(files);
|
|
104
106
|
const nextImage = uploaded.find((a) => IMAGE_EXT.test(a));
|
|
105
|
-
if (nextImage)
|
|
107
|
+
if (nextImage) {
|
|
108
|
+
track("button", "Upload image");
|
|
109
|
+
onCommit(`url("${toProjectRootAssetPath(nextImage)}")`);
|
|
110
|
+
}
|
|
106
111
|
} finally {
|
|
107
112
|
setUploading(false);
|
|
108
113
|
}
|
|
@@ -156,6 +161,7 @@ export function ImageFillField({
|
|
|
156
161
|
disabled={disabled}
|
|
157
162
|
onChange={(e) => {
|
|
158
163
|
const next = e.target.value;
|
|
164
|
+
track("select", "Project asset");
|
|
159
165
|
if (!next) {
|
|
160
166
|
onCommit("none");
|
|
161
167
|
return;
|
|
@@ -205,6 +211,7 @@ export function GradientField({
|
|
|
205
211
|
disabled?: boolean;
|
|
206
212
|
onCommit: (nextValue: string) => void;
|
|
207
213
|
}) {
|
|
214
|
+
const track = useTrackDesignInput();
|
|
208
215
|
const previewRef = useRef<HTMLDivElement | null>(null);
|
|
209
216
|
const parsed = parseGradient(value) ?? buildDefaultGradientModel(fallbackColor);
|
|
210
217
|
|
|
@@ -226,11 +233,13 @@ export function GradientField({
|
|
|
226
233
|
? Math.min(100, (parsed.stops.at(-1)?.position ?? 90) + 10)
|
|
227
234
|
: 100,
|
|
228
235
|
);
|
|
236
|
+
track("button", "Add gradient stop");
|
|
229
237
|
commit(nextGradient);
|
|
230
238
|
};
|
|
231
239
|
|
|
232
240
|
const removeStop = (index: number) => {
|
|
233
241
|
if (parsed.stops.length <= 2) return;
|
|
242
|
+
track("button", `Remove gradient stop ${index + 1}`);
|
|
234
243
|
commit({ ...parsed, stops: parsed.stops.filter((_, i) => i !== index) });
|
|
235
244
|
};
|
|
236
245
|
|
|
@@ -263,6 +272,7 @@ export function GradientField({
|
|
|
263
272
|
</div>
|
|
264
273
|
<div className="flex min-w-0 flex-wrap items-center gap-2">
|
|
265
274
|
<SegmentedControl
|
|
275
|
+
trackName="Gradient type"
|
|
266
276
|
disabled={disabled}
|
|
267
277
|
value={parsed.kind}
|
|
268
278
|
onChange={(next) => patch({ kind: next as GradientModel["kind"] })}
|
|
@@ -277,7 +287,10 @@ export function GradientField({
|
|
|
277
287
|
type="checkbox"
|
|
278
288
|
checked={parsed.repeating}
|
|
279
289
|
disabled={disabled}
|
|
280
|
-
onChange={(e) =>
|
|
290
|
+
onChange={(e) => {
|
|
291
|
+
track("toggle", "Repeat gradient");
|
|
292
|
+
patch({ repeating: e.target.checked });
|
|
293
|
+
}}
|
|
281
294
|
className="h-4 w-4 rounded border-neutral-700 bg-neutral-950 text-panel-accent focus:ring-panel-accent"
|
|
282
295
|
/>
|
|
283
296
|
Repeat
|
|
@@ -285,15 +298,16 @@ export function GradientField({
|
|
|
285
298
|
<button
|
|
286
299
|
type="button"
|
|
287
300
|
disabled={disabled}
|
|
288
|
-
onClick={() =>
|
|
301
|
+
onClick={() => {
|
|
302
|
+
track("button", "Reverse gradient");
|
|
289
303
|
commit({
|
|
290
304
|
...parsed,
|
|
291
305
|
stops: [...parsed.stops].reverse().map((stop) => ({
|
|
292
306
|
...stop,
|
|
293
307
|
position: 100 - stop.position,
|
|
294
308
|
})),
|
|
295
|
-
})
|
|
296
|
-
}
|
|
309
|
+
});
|
|
310
|
+
}}
|
|
297
311
|
className="inline-flex h-7 items-center gap-1.5 rounded-lg border border-neutral-700 bg-neutral-950 px-2.5 text-[11px] font-medium text-neutral-300 transition-colors hover:border-neutral-600 hover:text-white disabled:cursor-not-allowed disabled:text-neutral-600"
|
|
298
312
|
>
|
|
299
313
|
<RotateCcw size={12} />
|
|
@@ -306,6 +320,7 @@ export function GradientField({
|
|
|
306
320
|
<div className="grid gap-1.5">
|
|
307
321
|
<span className={LABEL}>{parsed.kind === "linear" ? "Angle" : "Start angle"}</span>
|
|
308
322
|
<SliderControl
|
|
323
|
+
trackName={parsed.kind === "linear" ? "Angle" : "Start angle"}
|
|
309
324
|
value={parsed.angle}
|
|
310
325
|
min={0}
|
|
311
326
|
max={360}
|
|
@@ -342,6 +357,7 @@ export function GradientField({
|
|
|
342
357
|
<div className="grid min-w-0 gap-1.5">
|
|
343
358
|
<span className={LABEL}>Center X</span>
|
|
344
359
|
<SliderControl
|
|
360
|
+
trackName="Center X"
|
|
345
361
|
value={parsed.centerX}
|
|
346
362
|
min={0}
|
|
347
363
|
max={100}
|
|
@@ -355,6 +371,7 @@ export function GradientField({
|
|
|
355
371
|
<div className="grid min-w-0 gap-1.5">
|
|
356
372
|
<span className={LABEL}>Center Y</span>
|
|
357
373
|
<SliderControl
|
|
374
|
+
trackName="Center Y"
|
|
358
375
|
value={parsed.centerY}
|
|
359
376
|
min={0}
|
|
360
377
|
max={100}
|