@hyperframes/studio 0.6.0-alpha.9 → 0.6.1

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.
Files changed (111) hide show
  1. package/dist/assets/hyperframes-player-CzwFysqv.js +418 -0
  2. package/dist/assets/index-D1JDq7Gg.css +1 -0
  3. package/dist/assets/index-hYc4aP7M.js +117 -0
  4. package/dist/favicon.svg +14 -0
  5. package/dist/index.html +3 -2
  6. package/package.json +9 -9
  7. package/src/App.tsx +421 -4303
  8. package/src/captions/components/CaptionOverlay.tsx +13 -246
  9. package/src/captions/components/CaptionOverlayUtils.ts +221 -0
  10. package/src/components/AskAgentModal.tsx +120 -0
  11. package/src/components/StudioHeader.tsx +133 -0
  12. package/src/components/StudioLeftSidebar.tsx +125 -0
  13. package/src/components/StudioPreviewArea.tsx +167 -0
  14. package/src/components/StudioRightPanel.tsx +198 -0
  15. package/src/components/TimelineToolbar.tsx +89 -0
  16. package/src/components/editor/DomEditOverlay.tsx +88 -993
  17. package/src/components/editor/EaseCurveEditor.tsx +221 -0
  18. package/src/components/editor/FileTree.tsx +13 -621
  19. package/src/components/editor/FileTreeIcons.tsx +128 -0
  20. package/src/components/editor/FileTreeNodes.tsx +496 -0
  21. package/src/components/editor/MotionPanel.tsx +16 -390
  22. package/src/components/editor/MotionPanelFields.tsx +185 -0
  23. package/src/components/editor/PropertyPanel.test.ts +0 -49
  24. package/src/components/editor/PropertyPanel.tsx +132 -2763
  25. package/src/components/editor/domEditOverlayGeometry.ts +211 -0
  26. package/src/components/editor/domEditOverlayGestures.ts +138 -0
  27. package/src/components/editor/domEditOverlayStartGesture.ts +155 -0
  28. package/src/components/editor/domEditing.ts +44 -1117
  29. package/src/components/editor/domEditingAgentPrompt.ts +97 -0
  30. package/src/components/editor/domEditingDom.ts +266 -0
  31. package/src/components/editor/domEditingElement.ts +329 -0
  32. package/src/components/editor/domEditingLayers.ts +460 -0
  33. package/src/components/editor/domEditingTypes.ts +125 -0
  34. package/src/components/editor/manualEditingAvailability.test.ts +2 -2
  35. package/src/components/editor/manualEditingAvailability.ts +1 -1
  36. package/src/components/editor/manualEdits.ts +84 -1049
  37. package/src/components/editor/manualEditsDom.ts +436 -0
  38. package/src/components/editor/manualEditsParsing.ts +280 -0
  39. package/src/components/editor/manualEditsSnapshot.ts +333 -0
  40. package/src/components/editor/manualEditsTypes.ts +141 -0
  41. package/src/components/editor/propertyPanelColor.tsx +371 -0
  42. package/src/components/editor/propertyPanelFill.tsx +421 -0
  43. package/src/components/editor/propertyPanelFont.tsx +455 -0
  44. package/src/components/editor/propertyPanelHelpers.ts +401 -0
  45. package/src/components/editor/propertyPanelPrimitives.tsx +357 -0
  46. package/src/components/editor/propertyPanelSections.tsx +453 -0
  47. package/src/components/editor/propertyPanelStyleSections.tsx +411 -0
  48. package/src/components/editor/studioMotion.ts +47 -434
  49. package/src/components/editor/studioMotionOps.ts +299 -0
  50. package/src/components/editor/studioMotionTypes.ts +168 -0
  51. package/src/components/editor/useDomEditOverlayGestures.ts +393 -0
  52. package/src/components/editor/useDomEditOverlayRects.ts +207 -0
  53. package/src/components/nle/NLELayout.tsx +68 -155
  54. package/src/components/nle/NLEPreview.tsx +3 -0
  55. package/src/components/nle/useCompositionStack.ts +126 -0
  56. package/src/components/renders/RenderQueue.tsx +102 -31
  57. package/src/components/renders/useRenderQueue.ts +8 -2
  58. package/src/components/sidebar/LeftSidebar.tsx +186 -186
  59. package/src/contexts/DomEditContext.tsx +137 -0
  60. package/src/contexts/FileManagerContext.tsx +110 -0
  61. package/src/contexts/PanelLayoutContext.tsx +68 -0
  62. package/src/contexts/StudioContext.tsx +135 -0
  63. package/src/hooks/useAppHotkeys.ts +326 -0
  64. package/src/hooks/useAskAgentModal.ts +162 -0
  65. package/src/hooks/useCaptionDetection.ts +132 -0
  66. package/src/hooks/useCompositionDimensions.ts +25 -0
  67. package/src/hooks/useConsoleErrorCapture.ts +60 -0
  68. package/src/hooks/useDomEditCommits.ts +437 -0
  69. package/src/hooks/useDomEditSession.ts +342 -0
  70. package/src/hooks/useDomEditTextCommits.ts +330 -0
  71. package/src/hooks/useDomSelection.ts +398 -0
  72. package/src/hooks/useFileManager.ts +431 -0
  73. package/src/hooks/useFrameCapture.ts +77 -0
  74. package/src/hooks/useLintModal.ts +35 -0
  75. package/src/hooks/useManifestPersistence.ts +492 -0
  76. package/src/hooks/usePanelLayout.ts +68 -0
  77. package/src/hooks/usePreviewInteraction.ts +153 -0
  78. package/src/hooks/useRenderClipContent.ts +124 -0
  79. package/src/hooks/useTimelineEditing.ts +472 -0
  80. package/src/hooks/useToast.ts +20 -0
  81. package/src/player/components/Player.tsx +33 -2
  82. package/src/player/components/Timeline.test.ts +0 -8
  83. package/src/player/components/Timeline.tsx +196 -1518
  84. package/src/player/components/TimelineCanvas.tsx +434 -0
  85. package/src/player/components/TimelineClip.tsx +9 -244
  86. package/src/player/components/TimelineEmptyState.tsx +102 -0
  87. package/src/player/components/TimelineRuler.tsx +90 -0
  88. package/src/player/components/timelineIcons.tsx +49 -0
  89. package/src/player/components/timelineLayout.ts +215 -0
  90. package/src/player/components/timelineUtils.ts +211 -0
  91. package/src/player/components/useTimelineClipDrag.ts +388 -0
  92. package/src/player/components/useTimelinePlayhead.ts +200 -0
  93. package/src/player/components/useTimelineRangeSelection.ts +135 -0
  94. package/src/player/hooks/usePlaybackKeyboard.ts +171 -0
  95. package/src/player/hooks/useTimelinePlayer.ts +105 -1371
  96. package/src/player/hooks/useTimelineSyncCallbacks.ts +288 -0
  97. package/src/player/lib/playbackAdapter.ts +145 -0
  98. package/src/player/lib/playbackShortcuts.ts +68 -0
  99. package/src/player/lib/playbackTypes.ts +60 -0
  100. package/src/player/lib/timelineDOM.ts +373 -0
  101. package/src/player/lib/timelineElementHelpers.ts +303 -0
  102. package/src/player/lib/timelineIframeHelpers.ts +269 -0
  103. package/src/utils/domEditHelpers.ts +50 -0
  104. package/src/utils/studioFontHelpers.ts +83 -0
  105. package/src/utils/studioHelpers.ts +214 -0
  106. package/src/utils/studioPreviewHelpers.ts +185 -0
  107. package/src/utils/timelineDiscovery.ts +1 -1
  108. package/dist/assets/hyperframes-player-DjsVzYFP.js +0 -418
  109. package/dist/assets/index-14zH9lqh.css +0 -1
  110. package/dist/assets/index-DYCiFGWQ.js +0 -108
  111. package/src/player/components/TimelineClip.test.ts +0 -92
@@ -0,0 +1,398 @@
1
+ import { useState, useCallback, useRef, useEffect } from "react";
2
+ import type { TimelineElement } from "../player";
3
+ import { getPreviewTargetFromPointer } from "../utils/studioPreviewHelpers";
4
+ import { findMatchingTimelineElementId, type RightPanelTab } from "../utils/studioHelpers";
5
+ import {
6
+ domEditSelectionsTargetSame,
7
+ domEditSelectionInGroup,
8
+ toggleDomEditGroupSelection,
9
+ replaceDomEditGroupSelection,
10
+ seedDomEditGroupWithSelection,
11
+ } from "../utils/domEditHelpers";
12
+ import { STUDIO_INSPECTOR_PANELS_ENABLED } from "../components/editor/manualEditingAvailability";
13
+ import {
14
+ findElementForSelection,
15
+ findElementForTimelineElement,
16
+ resolveDomEditSelection,
17
+ type DomEditSelection,
18
+ } from "../components/editor/domEditing";
19
+
20
+ // ── Types ──
21
+
22
+ export interface UseDomSelectionParams {
23
+ projectId: string | null;
24
+ activeCompPath: string | null;
25
+ isMasterView: boolean;
26
+ compIdToSrc: Map<string, string>;
27
+ captionEditMode: boolean;
28
+ previewIframeRef: React.MutableRefObject<HTMLIFrameElement | null>;
29
+ timelineElements: TimelineElement[];
30
+ setSelectedTimelineElementId: (id: string | null) => void;
31
+ setRightCollapsed: (collapsed: boolean) => void;
32
+ setRightPanelTab: (tab: RightPanelTab) => void;
33
+ previewIframe: HTMLIFrameElement | null;
34
+ refreshKey: number;
35
+ rightPanelTab: RightPanelTab;
36
+ }
37
+
38
+ export interface UseDomSelectionReturn {
39
+ // State
40
+ domEditSelection: DomEditSelection | null;
41
+ domEditGroupSelections: DomEditSelection[];
42
+ domEditHoverSelection: DomEditSelection | null;
43
+ // Refs
44
+ domEditSelectionRef: React.MutableRefObject<DomEditSelection | null>;
45
+ domEditGroupSelectionsRef: React.MutableRefObject<DomEditSelection[]>;
46
+ domEditHoverSelectionRef: React.MutableRefObject<DomEditSelection | null>;
47
+ // State setters (needed by useDomEditSession for agent-prompt reset flows)
48
+ setDomEditSelection: React.Dispatch<React.SetStateAction<DomEditSelection | null>>;
49
+ setDomEditGroupSelections: React.Dispatch<React.SetStateAction<DomEditSelection[]>>;
50
+ // Callbacks
51
+ applyDomSelection: (
52
+ selection: DomEditSelection | null,
53
+ options?: { revealPanel?: boolean; additive?: boolean; preserveGroup?: boolean },
54
+ ) => void;
55
+ clearDomSelection: () => void;
56
+ buildDomSelectionFromTarget: (
57
+ target: HTMLElement,
58
+ options?: { preferClipAncestor?: boolean },
59
+ ) => DomEditSelection | null;
60
+ resolveDomSelectionFromPreviewPoint: (
61
+ clientX: number,
62
+ clientY: number,
63
+ options?: { preferClipAncestor?: boolean },
64
+ ) => DomEditSelection | null;
65
+ updateDomEditHoverSelection: (selection: DomEditSelection | null) => void;
66
+ buildDomSelectionForTimelineElement: (element: TimelineElement) => DomEditSelection | null;
67
+ handleTimelineElementSelect: (element: TimelineElement | null) => void;
68
+ refreshDomEditSelectionFromPreview: (selection: DomEditSelection) => void;
69
+ refreshDomEditGroupSelectionsFromPreview: (selections: DomEditSelection[]) => void;
70
+ }
71
+
72
+ // ── Hook ──
73
+
74
+ export function useDomSelection({
75
+ projectId,
76
+ activeCompPath,
77
+ isMasterView,
78
+ compIdToSrc,
79
+ captionEditMode,
80
+ previewIframeRef,
81
+ timelineElements,
82
+ setSelectedTimelineElementId,
83
+ setRightCollapsed,
84
+ setRightPanelTab,
85
+ previewIframe,
86
+ refreshKey,
87
+ rightPanelTab,
88
+ }: UseDomSelectionParams): UseDomSelectionReturn {
89
+ // ── State ──
90
+
91
+ const [domEditSelection, setDomEditSelection] = useState<DomEditSelection | null>(null);
92
+ const [domEditGroupSelections, setDomEditGroupSelections] = useState<DomEditSelection[]>([]);
93
+ const [domEditHoverSelection, setDomEditHoverSelection] = useState<DomEditSelection | null>(null);
94
+
95
+ // ── Refs ──
96
+
97
+ const domEditSelectionRef = useRef<DomEditSelection | null>(domEditSelection);
98
+ const domEditGroupSelectionsRef = useRef<DomEditSelection[]>(domEditGroupSelections);
99
+ const domEditHoverSelectionRef = useRef<DomEditSelection | null>(domEditHoverSelection);
100
+
101
+ // Keep refs in sync with state
102
+ domEditSelectionRef.current = domEditSelection;
103
+ domEditGroupSelectionsRef.current = domEditGroupSelections;
104
+ domEditHoverSelectionRef.current = domEditHoverSelection;
105
+
106
+ // ── Callbacks ──
107
+
108
+ const applyDomSelection = useCallback(
109
+ (
110
+ selection: DomEditSelection | null,
111
+ options?: { revealPanel?: boolean; additive?: boolean; preserveGroup?: boolean },
112
+ ) => {
113
+ if (!selection) {
114
+ domEditSelectionRef.current = null;
115
+ domEditGroupSelectionsRef.current = [];
116
+ setDomEditSelection(null);
117
+ setDomEditGroupSelections([]);
118
+ setSelectedTimelineElementId(null);
119
+ return;
120
+ }
121
+ if (!STUDIO_INSPECTOR_PANELS_ENABLED) {
122
+ domEditSelectionRef.current = null;
123
+ domEditGroupSelectionsRef.current = [];
124
+ setDomEditSelection(null);
125
+ setDomEditGroupSelections([]);
126
+ setSelectedTimelineElementId(null);
127
+ return;
128
+ }
129
+
130
+ const isAdditiveSelection = Boolean(options?.additive);
131
+ const currentSelection = domEditSelectionRef.current;
132
+ const previousGroup = domEditGroupSelectionsRef.current;
133
+ const currentGroup = isAdditiveSelection
134
+ ? seedDomEditGroupWithSelection(previousGroup, currentSelection)
135
+ : previousGroup;
136
+ const wasInGroup = domEditSelectionInGroup(currentGroup, selection);
137
+ const nextGroup = options?.preserveGroup
138
+ ? replaceDomEditGroupSelection(currentGroup, selection)
139
+ : isAdditiveSelection
140
+ ? toggleDomEditGroupSelection(currentGroup, selection)
141
+ : [selection];
142
+ const nextSelection = options?.preserveGroup
143
+ ? selection
144
+ : isAdditiveSelection && wasInGroup
145
+ ? domEditSelectionsTargetSame(currentSelection, selection)
146
+ ? (nextGroup[0] ?? null)
147
+ : domEditSelectionInGroup(nextGroup, currentSelection)
148
+ ? currentSelection
149
+ : (nextGroup[0] ?? null)
150
+ : selection;
151
+
152
+ domEditSelectionRef.current = nextSelection;
153
+ domEditGroupSelectionsRef.current = nextGroup;
154
+ setDomEditSelection(nextSelection);
155
+ setDomEditGroupSelections(nextGroup);
156
+
157
+ if (nextSelection) {
158
+ if (options?.revealPanel !== false) {
159
+ setRightCollapsed(false);
160
+ setRightPanelTab("design");
161
+ }
162
+ const nextSelectedTimelineId = findMatchingTimelineElementId(
163
+ nextSelection,
164
+ timelineElements,
165
+ );
166
+ setSelectedTimelineElementId(nextSelectedTimelineId);
167
+ return;
168
+ }
169
+
170
+ setSelectedTimelineElementId(null);
171
+ },
172
+ [setSelectedTimelineElementId, timelineElements, setRightCollapsed, setRightPanelTab],
173
+ );
174
+
175
+ const clearDomSelection = useCallback(() => {
176
+ applyDomSelection(null, { revealPanel: false });
177
+ }, [applyDomSelection]);
178
+
179
+ const buildDomSelectionFromTarget = useCallback(
180
+ (target: HTMLElement, options?: { preferClipAncestor?: boolean }) => {
181
+ return resolveDomEditSelection(target, {
182
+ activeCompositionPath: activeCompPath,
183
+ isMasterView,
184
+ preferClipAncestor: options?.preferClipAncestor,
185
+ });
186
+ },
187
+ [activeCompPath, isMasterView],
188
+ );
189
+
190
+ const resolveDomSelectionFromPreviewPoint = useCallback(
191
+ (clientX: number, clientY: number, options?: { preferClipAncestor?: boolean }) => {
192
+ const iframe = previewIframeRef.current;
193
+ if (!iframe || captionEditMode) return null;
194
+ const target = getPreviewTargetFromPointer(iframe, clientX, clientY, activeCompPath);
195
+ if (!target) return null;
196
+ return buildDomSelectionFromTarget(target, {
197
+ preferClipAncestor: options?.preferClipAncestor,
198
+ });
199
+ },
200
+ [activeCompPath, buildDomSelectionFromTarget, captionEditMode, previewIframeRef],
201
+ );
202
+
203
+ const updateDomEditHoverSelection = useCallback((selection: DomEditSelection | null) => {
204
+ if (domEditSelectionsTargetSame(domEditHoverSelectionRef.current, selection)) return;
205
+ domEditHoverSelectionRef.current = selection;
206
+ setDomEditHoverSelection(selection);
207
+ }, []);
208
+
209
+ const buildDomSelectionForTimelineElement = useCallback(
210
+ (element: TimelineElement): DomEditSelection | null => {
211
+ const iframe = previewIframeRef.current;
212
+ let doc: Document | null = null;
213
+ try {
214
+ doc = iframe?.contentDocument ?? null;
215
+ } catch {
216
+ return null;
217
+ }
218
+ if (!doc) return null;
219
+
220
+ const targetElement = findElementForTimelineElement(doc, element, {
221
+ activeCompositionPath: activeCompPath,
222
+ compIdToSrc,
223
+ isMasterView,
224
+ });
225
+ return targetElement
226
+ ? buildDomSelectionFromTarget(targetElement, { preferClipAncestor: false })
227
+ : null;
228
+ },
229
+ [activeCompPath, buildDomSelectionFromTarget, compIdToSrc, isMasterView, previewIframeRef],
230
+ );
231
+
232
+ const handleTimelineElementSelect = useCallback(
233
+ (element: TimelineElement | null) => {
234
+ if (!STUDIO_INSPECTOR_PANELS_ENABLED) return;
235
+ if (!element) {
236
+ applyDomSelection(null, { revealPanel: false });
237
+ return;
238
+ }
239
+
240
+ const selection = buildDomSelectionForTimelineElement(element);
241
+ if (selection) applyDomSelection(selection);
242
+ },
243
+ [applyDomSelection, buildDomSelectionForTimelineElement],
244
+ );
245
+
246
+ const refreshDomEditSelectionFromPreview = useCallback(
247
+ (selection: DomEditSelection) => {
248
+ const iframe = previewIframeRef.current;
249
+ let doc: Document | null = null;
250
+ try {
251
+ doc = iframe?.contentDocument ?? null;
252
+ } catch {
253
+ return;
254
+ }
255
+ if (!doc) return;
256
+
257
+ const element = findElementForSelection(doc, selection, activeCompPath);
258
+ if (!element) return;
259
+
260
+ const nextSelection = buildDomSelectionFromTarget(element);
261
+ if (nextSelection) {
262
+ applyDomSelection(nextSelection, { revealPanel: false, preserveGroup: true });
263
+ }
264
+ },
265
+ [activeCompPath, applyDomSelection, buildDomSelectionFromTarget, previewIframeRef],
266
+ );
267
+
268
+ const refreshDomEditGroupSelectionsFromPreview = useCallback(
269
+ (selections: DomEditSelection[]) => {
270
+ const iframe = previewIframeRef.current;
271
+ let doc: Document | null = null;
272
+ try {
273
+ doc = iframe?.contentDocument ?? null;
274
+ } catch {
275
+ return;
276
+ }
277
+ if (!doc) return;
278
+
279
+ const nextGroup: DomEditSelection[] = [];
280
+ for (const selection of selections) {
281
+ const element = findElementForSelection(doc, selection, activeCompPath);
282
+ if (!element) continue;
283
+ const nextSelection = buildDomSelectionFromTarget(element);
284
+ if (nextSelection) nextGroup.push(nextSelection);
285
+ }
286
+ if (nextGroup.length === 0) return;
287
+
288
+ const currentSelection = domEditSelectionRef.current;
289
+ const nextSelection =
290
+ nextGroup.find((selection) => domEditSelectionsTargetSame(selection, currentSelection)) ??
291
+ nextGroup[0] ??
292
+ null;
293
+
294
+ domEditSelectionRef.current = nextSelection;
295
+ domEditGroupSelectionsRef.current = nextGroup;
296
+ setDomEditSelection(nextSelection);
297
+ setDomEditGroupSelections(nextGroup);
298
+
299
+ if (nextSelection) {
300
+ setSelectedTimelineElementId(
301
+ findMatchingTimelineElementId(nextSelection, timelineElements),
302
+ );
303
+ } else {
304
+ setSelectedTimelineElementId(null);
305
+ }
306
+ },
307
+ [
308
+ activeCompPath,
309
+ buildDomSelectionFromTarget,
310
+ setSelectedTimelineElementId,
311
+ timelineElements,
312
+ previewIframeRef,
313
+ ],
314
+ );
315
+
316
+ // ── Effects ──
317
+
318
+ // Clear hover on caption mode change
319
+ // eslint-disable-next-line no-restricted-syntax
320
+ useEffect(() => {
321
+ if (captionEditMode) updateDomEditHoverSelection(null);
322
+ }, [captionEditMode, updateDomEditHoverSelection]);
323
+
324
+ // Clear hover on composition/project/preview change
325
+ // eslint-disable-next-line no-restricted-syntax
326
+ useEffect(() => {
327
+ updateDomEditHoverSelection(null);
328
+ }, [activeCompPath, projectId, previewIframe, refreshKey, updateDomEditHoverSelection]);
329
+
330
+ // Clear hover when matching selection
331
+ // eslint-disable-next-line no-restricted-syntax
332
+ useEffect(() => {
333
+ if (!domEditHoverSelection) return;
334
+ const hoverMatchesSelection = domEditSelectionsTargetSame(
335
+ domEditHoverSelection,
336
+ domEditSelection,
337
+ );
338
+ const hoverMatchesGroup = domEditSelectionInGroup(
339
+ domEditGroupSelections,
340
+ domEditHoverSelection,
341
+ );
342
+ if (!hoverMatchesSelection && !hoverMatchesGroup) return;
343
+ updateDomEditHoverSelection(null);
344
+ }, [
345
+ domEditGroupSelections,
346
+ domEditHoverSelection,
347
+ domEditSelection,
348
+ updateDomEditHoverSelection,
349
+ ]);
350
+
351
+ // Clear hover when element disconnected
352
+ // eslint-disable-next-line no-restricted-syntax
353
+ useEffect(() => {
354
+ if (!domEditHoverSelection) return;
355
+ if (domEditHoverSelection.element.isConnected) return;
356
+ updateDomEditHoverSelection(null);
357
+ }, [domEditHoverSelection, updateDomEditHoverSelection]);
358
+
359
+ // Clear selection on caption mode change
360
+ // eslint-disable-next-line no-restricted-syntax
361
+ useEffect(() => {
362
+ if (!captionEditMode) return;
363
+ applyDomSelection(null, { revealPanel: false });
364
+ }, [applyDomSelection, captionEditMode]);
365
+
366
+ // Disabled inspector effect
367
+ // eslint-disable-next-line no-restricted-syntax
368
+ useEffect(() => {
369
+ if (STUDIO_INSPECTOR_PANELS_ENABLED) return;
370
+ updateDomEditHoverSelection(null);
371
+ applyDomSelection(null, { revealPanel: false });
372
+ if (rightPanelTab !== "renders") setRightPanelTab("renders");
373
+ }, [applyDomSelection, rightPanelTab, updateDomEditHoverSelection, setRightPanelTab]);
374
+
375
+ return {
376
+ // State
377
+ domEditSelection,
378
+ domEditGroupSelections,
379
+ domEditHoverSelection,
380
+ // Refs
381
+ domEditSelectionRef,
382
+ domEditGroupSelectionsRef,
383
+ domEditHoverSelectionRef,
384
+ // State setters
385
+ setDomEditSelection,
386
+ setDomEditGroupSelections,
387
+ // Callbacks
388
+ applyDomSelection,
389
+ clearDomSelection,
390
+ buildDomSelectionFromTarget,
391
+ resolveDomSelectionFromPreviewPoint,
392
+ updateDomEditHoverSelection,
393
+ buildDomSelectionForTimelineElement,
394
+ handleTimelineElementSelect,
395
+ refreshDomEditSelectionFromPreview,
396
+ refreshDomEditGroupSelectionsFromPreview,
397
+ };
398
+ }