@hyperframes/studio 0.7.58 → 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-CtTDO63S.js → hyperframes-player-Bm07FLkl.js} +1 -1
- package/dist/assets/{index-C47jAC3Q.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-DeQPzqwH.js → index-FvzmPhfG.js} +1 -1
- package/dist/index.d.ts +12 -3
- package/dist/index.html +2 -2
- package/dist/index.js +13514 -8528
- 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 +3 -3
- package/src/components/DesignPanelPromoteProvider.tsx +15 -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/GestureRecordControl.tsx +7 -1
- package/src/components/editor/GsapAnimationSection.tsx +109 -14
- package/src/components/editor/InspectorHeaderActions.tsx +42 -4
- 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/gsapAnimationCallbacks.ts +27 -0
- package/src/components/editor/gsapLivePreview.ts +34 -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/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/gsapScriptCommitTypes.ts +6 -4
- package/src/hooks/timelineTrackVisibility.test.ts +52 -0
- package/src/hooks/timelineTrackVisibility.ts +27 -10
- package/src/hooks/useAppHotkeys.ts +9 -0
- package/src/hooks/useDomEditAttributeCommits.ts +123 -1
- package/src/hooks/useDomEditCommits.ts +29 -175
- package/src/hooks/useDomEditCommitsHelpers.ts +158 -0
- package/src/hooks/useDomEditSession.ts +17 -5
- package/src/hooks/useDomEditTextCommits.ts +14 -9
- package/src/hooks/useDomEditWiring.ts +10 -9
- package/src/hooks/useElementLifecycleOps.ts +8 -3
- 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/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 +4 -1
- package/src/hooks/useTimelineEditing.ts +16 -10
- package/src/hooks/useTimelineEditingTypes.ts +3 -0
- package/src/hooks/useTimelineGroupEditing.ts +16 -2
- package/src/hooks/useVariablesPersist.ts +9 -7
- package/src/icons/SystemIcons.tsx +2 -0
- package/src/styles/studio.css +22 -0
- package/src/styles/tailwind-preset.shared.js +7 -0
- package/src/utils/designInputTracking.test.ts +97 -0
- package/src/utils/designInputTracking.ts +80 -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/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-B_UvTX3E.js +0 -423
- package/dist/assets/index-uahwWkgw.css +0 -1
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import type { GsapAnimation } from "@hyperframes/core/gsap-parser";
|
|
3
|
+
import { useTrackDesignInput } from "../../contexts/DesignPanelInputContext";
|
|
4
|
+
import type { DomEditSelection } from "./domEditing";
|
|
5
|
+
import { formatTimingValue, RESPONSIVE_GRID } from "./propertyPanelHelpers";
|
|
6
|
+
import { parseTimingValue } from "./propertyPanelTimingSection";
|
|
7
|
+
import { CommitField } from "./propertyPanelPrimitives";
|
|
8
|
+
import { AnimationCard } from "./AnimationCard";
|
|
9
|
+
import { ADD_METHODS, ADD_METHOD_LABELS, METHOD_TOOLTIPS } from "./gsapAnimationConstants";
|
|
10
|
+
import {
|
|
11
|
+
trackAnimationMetaUpdate,
|
|
12
|
+
type GsapAnimationEditCallbacks,
|
|
13
|
+
} from "./gsapAnimationCallbacks";
|
|
14
|
+
import { deriveElementTiming } from "./propertyPanelFlatTimingDerivation";
|
|
15
|
+
|
|
16
|
+
export function FlatTimingRow({
|
|
17
|
+
element,
|
|
18
|
+
animations = [],
|
|
19
|
+
onSetAttribute,
|
|
20
|
+
onSetAttributes,
|
|
21
|
+
}: {
|
|
22
|
+
element: DomEditSelection;
|
|
23
|
+
animations?: GsapAnimation[];
|
|
24
|
+
onSetAttribute: (attr: string, value: string) => void | Promise<void>;
|
|
25
|
+
/** Commits start+duration together in ONE atomic persist call, bound to
|
|
26
|
+
* THIS render's `element` explicitly — not whatever is "currently"
|
|
27
|
+
* selected by the time the call resolves. Falls back to two sequential
|
|
28
|
+
* `onSetAttribute` calls (with the same non-atomicity/misdirection risk
|
|
29
|
+
* documented below) when the caller doesn't wire it up. */
|
|
30
|
+
onSetAttributes?: (selection: DomEditSelection, attrs: Record<string, string>) => Promise<void>;
|
|
31
|
+
}) {
|
|
32
|
+
const track = useTrackDesignInput();
|
|
33
|
+
const { start, duration, inferred: derived } = deriveElementTiming(element, animations);
|
|
34
|
+
const end = start + duration;
|
|
35
|
+
|
|
36
|
+
// While the range is inferred from animations, editing ONE field must pin the
|
|
37
|
+
// WHOLE displayed range: writing only data-duration flips inference off and
|
|
38
|
+
// drops start to data-start-or-0 (the clip silently shifts), and writing only
|
|
39
|
+
// data-start is ignored while duration is still inferred (the edit looks
|
|
40
|
+
// dead). Pin both attributes in ONE atomic commit bound to THIS element —
|
|
41
|
+
// two sequential `onSetAttribute` calls would each resolve `domEditSelection`
|
|
42
|
+
// fresh from current hook state, so a selection change between the two
|
|
43
|
+
// awaits could misdirect the second write at the newly-selected element, and
|
|
44
|
+
// a failure of just the second call would leave the pair half-applied.
|
|
45
|
+
const pinRange = async (nextStart: number, nextDuration: number) => {
|
|
46
|
+
const attrs = { start: nextStart.toFixed(2), duration: nextDuration.toFixed(2) };
|
|
47
|
+
if (onSetAttributes) {
|
|
48
|
+
await onSetAttributes(element, attrs);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
await onSetAttribute("start", attrs.start);
|
|
52
|
+
await onSetAttribute("duration", attrs.duration);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const commitStart = (nextValue: string) => {
|
|
56
|
+
const parsed = parseTimingValue(nextValue);
|
|
57
|
+
if (parsed == null) return;
|
|
58
|
+
if (derived) {
|
|
59
|
+
void pinRange(parsed, duration);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
void onSetAttribute("start", parsed.toFixed(2));
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const commitDuration = (nextValue: string) => {
|
|
66
|
+
const parsed = parseTimingValue(nextValue);
|
|
67
|
+
if (parsed == null || parsed <= 0) return;
|
|
68
|
+
if (derived) {
|
|
69
|
+
void pinRange(start, parsed);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
void onSetAttribute("duration", parsed.toFixed(2));
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const commitEnd = (nextValue: string) => {
|
|
76
|
+
const parsed = parseTimingValue(nextValue);
|
|
77
|
+
if (parsed == null || parsed <= start) return;
|
|
78
|
+
if (derived) {
|
|
79
|
+
void pinRange(start, parsed - start);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
void onSetAttribute("duration", (parsed - start).toFixed(2));
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const cell = (label: string, value: string, onCommit: (next: string) => void) => (
|
|
86
|
+
<div className="grid gap-px">
|
|
87
|
+
<span className="text-[9px] text-panel-text-4">{label}</span>
|
|
88
|
+
<span className="border-b border-transparent font-mono text-[11px] text-panel-text-0 hover:border-panel-border-input">
|
|
89
|
+
<CommitField
|
|
90
|
+
value={value}
|
|
91
|
+
onCommit={(next) => {
|
|
92
|
+
track("metric", label);
|
|
93
|
+
onCommit(next);
|
|
94
|
+
}}
|
|
95
|
+
/>
|
|
96
|
+
</span>
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<div className={RESPONSIVE_GRID}>
|
|
102
|
+
{cell("Start", formatTimingValue(start), commitStart)}
|
|
103
|
+
{cell("End", formatTimingValue(end), commitEnd)}
|
|
104
|
+
{cell("Duration", formatTimingValue(duration), commitDuration)}
|
|
105
|
+
{derived && (
|
|
106
|
+
<p className="col-span-3 mt-1 text-[10px] leading-snug text-panel-text-3">
|
|
107
|
+
Inferred from this element's animation — edit to pin an explicit clip range.
|
|
108
|
+
</p>
|
|
109
|
+
)}
|
|
110
|
+
</div>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function FlatMotionSection({
|
|
115
|
+
element,
|
|
116
|
+
animations,
|
|
117
|
+
showTiming,
|
|
118
|
+
showEffects,
|
|
119
|
+
multipleTimelines,
|
|
120
|
+
unsupportedTimelinePattern,
|
|
121
|
+
onSetAttribute,
|
|
122
|
+
onSetAttributes,
|
|
123
|
+
onAddAnimation,
|
|
124
|
+
...callbacks
|
|
125
|
+
}: {
|
|
126
|
+
element: DomEditSelection;
|
|
127
|
+
animations: GsapAnimation[];
|
|
128
|
+
showTiming: boolean;
|
|
129
|
+
showEffects: boolean;
|
|
130
|
+
multipleTimelines?: boolean;
|
|
131
|
+
unsupportedTimelinePattern?: boolean;
|
|
132
|
+
onSetAttribute: (attr: string, value: string) => void | Promise<void>;
|
|
133
|
+
onSetAttributes?: (selection: DomEditSelection, attrs: Record<string, string>) => Promise<void>;
|
|
134
|
+
onAddAnimation: (method: "to" | "from" | "set" | "fromTo") => void;
|
|
135
|
+
} & GsapAnimationEditCallbacks) {
|
|
136
|
+
const track = useTrackDesignInput();
|
|
137
|
+
const [addMenuOpen, setAddMenuOpen] = useState(false);
|
|
138
|
+
const trackProperty = (property: string) => {
|
|
139
|
+
const control =
|
|
140
|
+
property === "visibility"
|
|
141
|
+
? "toggle"
|
|
142
|
+
: property === "filter" || property === "clipPath"
|
|
143
|
+
? "text"
|
|
144
|
+
: "metric";
|
|
145
|
+
track(control, property);
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<div className="space-y-3">
|
|
150
|
+
{showTiming && (
|
|
151
|
+
<FlatTimingRow
|
|
152
|
+
element={element}
|
|
153
|
+
animations={animations}
|
|
154
|
+
onSetAttribute={onSetAttribute}
|
|
155
|
+
onSetAttributes={onSetAttributes}
|
|
156
|
+
/>
|
|
157
|
+
)}
|
|
158
|
+
{showEffects && (
|
|
159
|
+
<>
|
|
160
|
+
{multipleTimelines && (
|
|
161
|
+
<p className="rounded-lg bg-amber-500/10 px-3 py-2 text-[11px] leading-relaxed text-amber-400">
|
|
162
|
+
This file has multiple GSAP timelines. Animation editing is disabled to prevent data
|
|
163
|
+
loss — consolidate into a single timeline to enable editing.
|
|
164
|
+
</p>
|
|
165
|
+
)}
|
|
166
|
+
{unsupportedTimelinePattern && (
|
|
167
|
+
<p className="rounded-lg bg-amber-500/10 px-3 py-2 text-[11px] leading-relaxed text-amber-400">
|
|
168
|
+
This timeline uses a computed key the editor can't resolve statically.
|
|
169
|
+
</p>
|
|
170
|
+
)}
|
|
171
|
+
{!multipleTimelines && !unsupportedTimelinePattern && (
|
|
172
|
+
<div className="space-y-2">
|
|
173
|
+
{animations.map((anim, index) => (
|
|
174
|
+
<AnimationCard
|
|
175
|
+
key={anim.id}
|
|
176
|
+
animation={anim}
|
|
177
|
+
defaultExpanded={index === 0}
|
|
178
|
+
flat
|
|
179
|
+
onUpdateProperty={(animationId, property, value) => {
|
|
180
|
+
trackProperty(property);
|
|
181
|
+
callbacks.onUpdateProperty(animationId, property, value);
|
|
182
|
+
}}
|
|
183
|
+
onUpdateMeta={(animationId, updates) => {
|
|
184
|
+
trackAnimationMetaUpdate(track, updates);
|
|
185
|
+
callbacks.onUpdateMeta(animationId, updates);
|
|
186
|
+
}}
|
|
187
|
+
onDeleteAnimation={(animationId) => {
|
|
188
|
+
track("button", "Remove animation");
|
|
189
|
+
callbacks.onDeleteAnimation(animationId);
|
|
190
|
+
}}
|
|
191
|
+
onAddProperty={(animationId, property) => {
|
|
192
|
+
track("select", "Add effect property");
|
|
193
|
+
callbacks.onAddProperty(animationId, property);
|
|
194
|
+
}}
|
|
195
|
+
onRemoveProperty={(animationId, property) => {
|
|
196
|
+
track("button", `Remove ${property}`);
|
|
197
|
+
callbacks.onRemoveProperty(animationId, property);
|
|
198
|
+
}}
|
|
199
|
+
onUpdateFromProperty={
|
|
200
|
+
callbacks.onUpdateFromProperty
|
|
201
|
+
? (animationId, property, value) => {
|
|
202
|
+
trackProperty(property);
|
|
203
|
+
callbacks.onUpdateFromProperty?.(animationId, property, value);
|
|
204
|
+
}
|
|
205
|
+
: undefined
|
|
206
|
+
}
|
|
207
|
+
onAddFromProperty={
|
|
208
|
+
callbacks.onAddFromProperty
|
|
209
|
+
? (animationId, property) => {
|
|
210
|
+
track("select", "Add from property");
|
|
211
|
+
callbacks.onAddFromProperty?.(animationId, property);
|
|
212
|
+
}
|
|
213
|
+
: undefined
|
|
214
|
+
}
|
|
215
|
+
onRemoveFromProperty={
|
|
216
|
+
callbacks.onRemoveFromProperty
|
|
217
|
+
? (animationId, property) => {
|
|
218
|
+
track("button", `Remove from ${property}`);
|
|
219
|
+
callbacks.onRemoveFromProperty?.(animationId, property);
|
|
220
|
+
}
|
|
221
|
+
: undefined
|
|
222
|
+
}
|
|
223
|
+
onLivePreview={callbacks.onLivePreview}
|
|
224
|
+
onLivePreviewEnd={callbacks.onLivePreviewEnd}
|
|
225
|
+
onSetArcPath={
|
|
226
|
+
callbacks.onSetArcPath
|
|
227
|
+
? (animationId, config) => {
|
|
228
|
+
track(
|
|
229
|
+
"toggle",
|
|
230
|
+
config.autoRotate !== undefined ? "Auto rotate" : "Arc motion",
|
|
231
|
+
);
|
|
232
|
+
callbacks.onSetArcPath?.(animationId, config);
|
|
233
|
+
}
|
|
234
|
+
: undefined
|
|
235
|
+
}
|
|
236
|
+
onUpdateArcSegment={
|
|
237
|
+
callbacks.onUpdateArcSegment
|
|
238
|
+
? (animationId, segmentIndex, update) => {
|
|
239
|
+
if (update.curviness === undefined) {
|
|
240
|
+
track("button", `Reset arc segment ${segmentIndex + 1}`);
|
|
241
|
+
}
|
|
242
|
+
callbacks.onUpdateArcSegment?.(animationId, segmentIndex, update);
|
|
243
|
+
}
|
|
244
|
+
: undefined
|
|
245
|
+
}
|
|
246
|
+
onUpdateKeyframeEase={
|
|
247
|
+
callbacks.onUpdateKeyframeEase
|
|
248
|
+
? (animationId, percentage, ease) => {
|
|
249
|
+
track("select", "Keyframe ease");
|
|
250
|
+
callbacks.onUpdateKeyframeEase?.(animationId, percentage, ease);
|
|
251
|
+
}
|
|
252
|
+
: undefined
|
|
253
|
+
}
|
|
254
|
+
onSetAllKeyframeEases={
|
|
255
|
+
callbacks.onSetAllKeyframeEases
|
|
256
|
+
? (animationId, ease) => {
|
|
257
|
+
track("select", "All keyframe eases");
|
|
258
|
+
callbacks.onSetAllKeyframeEases?.(animationId, ease);
|
|
259
|
+
}
|
|
260
|
+
: undefined
|
|
261
|
+
}
|
|
262
|
+
onUnroll={
|
|
263
|
+
callbacks.onUnroll
|
|
264
|
+
? (animationId) => {
|
|
265
|
+
track("button", "Unroll animation");
|
|
266
|
+
callbacks.onUnroll?.(animationId);
|
|
267
|
+
}
|
|
268
|
+
: undefined
|
|
269
|
+
}
|
|
270
|
+
/>
|
|
271
|
+
))}
|
|
272
|
+
<div className="relative pt-1">
|
|
273
|
+
{addMenuOpen ? (
|
|
274
|
+
<div className="flex gap-1.5">
|
|
275
|
+
{ADD_METHODS.map((method) => (
|
|
276
|
+
<button
|
|
277
|
+
key={method}
|
|
278
|
+
type="button"
|
|
279
|
+
title={METHOD_TOOLTIPS[method]}
|
|
280
|
+
onClick={() => {
|
|
281
|
+
track("button", `Add ${method} animation`);
|
|
282
|
+
onAddAnimation(method);
|
|
283
|
+
setAddMenuOpen(false);
|
|
284
|
+
}}
|
|
285
|
+
className="rounded-lg border border-panel-border-input bg-panel-input px-2.5 py-1.5 text-[11px] font-medium text-panel-text-2 transition-colors hover:border-panel-text-4 hover:text-panel-text-0"
|
|
286
|
+
>
|
|
287
|
+
{ADD_METHOD_LABELS[method] ?? method}
|
|
288
|
+
</button>
|
|
289
|
+
))}
|
|
290
|
+
<button
|
|
291
|
+
type="button"
|
|
292
|
+
onClick={() => setAddMenuOpen(false)}
|
|
293
|
+
className="px-1.5 text-[11px] text-panel-text-3 hover:text-panel-text-1"
|
|
294
|
+
>
|
|
295
|
+
Cancel
|
|
296
|
+
</button>
|
|
297
|
+
</div>
|
|
298
|
+
) : (
|
|
299
|
+
<button
|
|
300
|
+
type="button"
|
|
301
|
+
onClick={() => setAddMenuOpen(true)}
|
|
302
|
+
className="text-[11px] font-medium text-panel-text-3 transition-colors hover:text-panel-text-1"
|
|
303
|
+
title="Add a new animation effect to this element"
|
|
304
|
+
>
|
|
305
|
+
+ Add effect
|
|
306
|
+
</button>
|
|
307
|
+
)}
|
|
308
|
+
</div>
|
|
309
|
+
</div>
|
|
310
|
+
)}
|
|
311
|
+
</>
|
|
312
|
+
)}
|
|
313
|
+
</div>
|
|
314
|
+
);
|
|
315
|
+
}
|