@hyperframes/studio 0.7.57 → 0.7.58
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-CtTDO63S.js} +1 -1
- package/dist/assets/{index-DfmYkU44.js → index-B_UvTX3E.js} +204 -204
- package/dist/assets/{index-KsfE1bUu.js → index-C47jAC3Q.js} +1 -1
- package/dist/assets/{index-Bf1x1y8H.js → index-DeQPzqwH.js} +1 -1
- package/dist/assets/index-uahwWkgw.css +1 -0
- 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 +15 -4
- package/dist/index.html +2 -2
- package/dist/index.js +5954 -4474
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/App.tsx +3 -3
- package/src/components/StudioFeedbackBar.tsx +2 -2
- 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/LayersPanel.tsx +110 -99
- 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/layersPanelSort.ts +80 -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/hooks/domEditCommitTypes.ts +17 -1
- package/src/hooks/elementLifecycleOpsTestUtils.ts +25 -0
- package/src/hooks/fetchStubTestUtils.ts +16 -0
- 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 +3 -1
- package/src/hooks/timelineTrackVisibility.ts +4 -3
- package/src/hooks/useClipboard.ts +19 -17
- package/src/hooks/useDomEditCommits.test.tsx +316 -38
- package/src/hooks/useDomEditCommits.ts +143 -78
- package/src/hooks/useDomEditSession.test.tsx +3 -1
- package/src/hooks/useDomEditSession.ts +1 -1
- package/src/hooks/useElementLifecycleOps.test.tsx +426 -60
- package/src/hooks/useElementLifecycleOps.ts +174 -81
- package/src/hooks/usePreviewPersistence.ts +2 -2
- package/src/hooks/useTimelineEditing.test.tsx +302 -154
- package/src/hooks/useTimelineEditing.ts +97 -93
- package/src/hooks/useTimelineEditingTypes.ts +1 -1
- package/src/hooks/useTimelineGroupEditing.ts +35 -3
- 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/telemetry/events.test.ts +10 -0
- package/src/telemetry/events.ts +1 -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/sourceScopedSelectorIndex.ts +29 -0
- 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
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* No imports from other domEditing* modules — safe to import from anywhere.
|
|
5
5
|
*/
|
|
6
6
|
import { COLOR_GRADING_SOURCE_HIDDEN_ATTR } from "@hyperframes/core/color-grading";
|
|
7
|
+
import { getSourceScopedSelectorIndex } from "../../utils/sourceScopedSelectorIndex";
|
|
7
8
|
import { CURATED_STYLE_PROPERTIES } from "./domEditingTypes";
|
|
8
9
|
|
|
9
10
|
// ─── Type guard ───────────────────────────────────────────────────────────────
|
|
@@ -296,11 +297,9 @@ export function getSelectorIndex(
|
|
|
296
297
|
): number | undefined {
|
|
297
298
|
if (!selector?.startsWith(".")) return undefined;
|
|
298
299
|
|
|
299
|
-
|
|
300
|
-
(candidate)
|
|
301
|
-
|
|
302
|
-
|
|
300
|
+
return getSourceScopedSelectorIndex(doc, el, selector, sourceFile, (candidate) =>
|
|
301
|
+
isHtmlElement(candidate)
|
|
302
|
+
? getSourceFileForElement(candidate, activeCompositionPath).sourceFile
|
|
303
|
+
: undefined,
|
|
303
304
|
);
|
|
304
|
-
const index = candidates.indexOf(el);
|
|
305
|
-
return index >= 0 ? index : undefined;
|
|
306
305
|
}
|
|
@@ -246,45 +246,28 @@ export function findElementForSelection(
|
|
|
246
246
|
selection: FindElementSelection,
|
|
247
247
|
activeCompositionPath: string | null = null,
|
|
248
248
|
): HTMLElement | null {
|
|
249
|
+
const sourceMatches = (candidate: Element): candidate is HTMLElement =>
|
|
250
|
+
isHtmlElement(candidate) &&
|
|
251
|
+
(!selection.sourceFile ||
|
|
252
|
+
getSourceFileForElement(candidate, activeCompositionPath).sourceFile ===
|
|
253
|
+
selection.sourceFile);
|
|
254
|
+
const findAll = (selector: string): HTMLElement[] =>
|
|
255
|
+
querySelectorAllSafely(doc, selector).filter(sourceMatches);
|
|
256
|
+
|
|
249
257
|
if (selection.hfId) {
|
|
250
|
-
const byHfId =
|
|
251
|
-
if (
|
|
258
|
+
const byHfId = findAll(`[data-hf-id="${escapeCssString(selection.hfId)}"]`)[0];
|
|
259
|
+
if (byHfId) return byHfId;
|
|
252
260
|
}
|
|
253
261
|
|
|
254
262
|
if (selection.id) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
getSourceFileForElement(byId, activeCompositionPath).sourceFile === selection.sourceFile)
|
|
260
|
-
) {
|
|
261
|
-
return byId;
|
|
262
|
-
}
|
|
263
|
+
// Flattened sub-compositions can repeat authored ids. getElementById returns
|
|
264
|
+
// only the first document match, so filter every id match by source first.
|
|
265
|
+
const byId = findAll(`[id="${escapeCssString(selection.id)}"]`)[0];
|
|
266
|
+
if (byId) return byId;
|
|
263
267
|
}
|
|
264
268
|
|
|
265
269
|
if (!selection.selector) return null;
|
|
266
|
-
|
|
267
|
-
// fallow-ignore-next-line code-duplication
|
|
268
|
-
if (selection.selector.startsWith(".") && selection.selectorIndex != null) {
|
|
269
|
-
const matches = querySelectorAllSafely(doc, selection.selector).filter(
|
|
270
|
-
(candidate): candidate is HTMLElement =>
|
|
271
|
-
isHtmlElement(candidate) &&
|
|
272
|
-
(!selection.sourceFile ||
|
|
273
|
-
getSourceFileForElement(candidate, activeCompositionPath).sourceFile ===
|
|
274
|
-
selection.sourceFile),
|
|
275
|
-
);
|
|
276
|
-
return matches[selection.selectorIndex] ?? null;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// fallow-ignore-next-line code-duplication
|
|
280
|
-
const matches = querySelectorAllSafely(doc, selection.selector).filter(
|
|
281
|
-
(candidate): candidate is HTMLElement =>
|
|
282
|
-
isHtmlElement(candidate) &&
|
|
283
|
-
(!selection.sourceFile ||
|
|
284
|
-
getSourceFileForElement(candidate, activeCompositionPath).sourceFile ===
|
|
285
|
-
selection.sourceFile),
|
|
286
|
-
);
|
|
287
|
-
return matches[0] ?? null;
|
|
270
|
+
return findAll(selection.selector)[selection.selectorIndex ?? 0] ?? null;
|
|
288
271
|
}
|
|
289
272
|
|
|
290
273
|
// fallow-ignore-next-line complexity
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { DomEditLayerItem } from "./domEditingTypes";
|
|
2
|
+
import { getElementZIndex } from "../../player/lib/layerOrdering";
|
|
3
|
+
|
|
4
|
+
interface CollapsedState {
|
|
5
|
+
[key: string]: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// ── Pure helpers ──────────────────────────────────────────────────────
|
|
9
|
+
|
|
10
|
+
// fallow-ignore-next-line complexity
|
|
11
|
+
export function sortLayersByZIndex(layers: DomEditLayerItem[]): DomEditLayerItem[] {
|
|
12
|
+
if (layers.length <= 1) return layers;
|
|
13
|
+
|
|
14
|
+
const minDepth = layers[0].depth;
|
|
15
|
+
for (let i = 1; i < layers.length; i++) {
|
|
16
|
+
if (layers[i].depth < minDepth) return layers;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const chunks: Array<{ root: DomEditLayerItem; children: DomEditLayerItem[]; domIndex: number }> =
|
|
20
|
+
[];
|
|
21
|
+
|
|
22
|
+
for (let i = 0; i < layers.length; i++) {
|
|
23
|
+
if (layers[i].depth === minDepth) {
|
|
24
|
+
const children: DomEditLayerItem[] = [];
|
|
25
|
+
let j = i + 1;
|
|
26
|
+
while (j < layers.length && layers[j].depth > minDepth) {
|
|
27
|
+
children.push(layers[j]);
|
|
28
|
+
j++;
|
|
29
|
+
}
|
|
30
|
+
chunks.push({ root: layers[i], children, domIndex: chunks.length });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (chunks.length <= 1) {
|
|
35
|
+
if (chunks.length === 1 && chunks[0].children.length > 0) {
|
|
36
|
+
const sorted = sortLayersByZIndex(chunks[0].children);
|
|
37
|
+
return [chunks[0].root, ...sorted];
|
|
38
|
+
}
|
|
39
|
+
return layers;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
chunks.sort((a, b) => {
|
|
43
|
+
const zA = getElementZIndex(a.root.element);
|
|
44
|
+
const zB = getElementZIndex(b.root.element);
|
|
45
|
+
if (zA !== zB) return zB - zA;
|
|
46
|
+
return b.domIndex - a.domIndex;
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const result: DomEditLayerItem[] = [];
|
|
50
|
+
for (const chunk of chunks) {
|
|
51
|
+
result.push(chunk.root);
|
|
52
|
+
if (chunk.children.length > 0) {
|
|
53
|
+
result.push(...sortLayersByZIndex(chunk.children));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function getVisibleLayers(
|
|
60
|
+
layers: DomEditLayerItem[],
|
|
61
|
+
collapsed: CollapsedState,
|
|
62
|
+
): DomEditLayerItem[] {
|
|
63
|
+
if (Object.keys(collapsed).length === 0) return layers;
|
|
64
|
+
|
|
65
|
+
const result: DomEditLayerItem[] = [];
|
|
66
|
+
let skipDepth = -1;
|
|
67
|
+
|
|
68
|
+
for (const layer of layers) {
|
|
69
|
+
if (skipDepth >= 0 && layer.depth > skipDepth) continue;
|
|
70
|
+
skipDepth = -1;
|
|
71
|
+
|
|
72
|
+
result.push(layer);
|
|
73
|
+
|
|
74
|
+
if (collapsed[layer.key] && layer.childCount > 0) {
|
|
75
|
+
skipDepth = layer.depth;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
import React, { act } from "react";
|
|
3
|
+
import { createRoot } from "react-dom/client";
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import {
|
|
6
|
+
LAYER_REVEAL_LIFT_Z,
|
|
7
|
+
LAYER_REVEAL_PENDING_COMMIT_ATTR,
|
|
8
|
+
beginLayerRevealCommit,
|
|
9
|
+
completeLayerRevealCommit,
|
|
10
|
+
liftElementToTop,
|
|
11
|
+
restoreLiftedElement,
|
|
12
|
+
useLayerRevealOverride,
|
|
13
|
+
} from "./useLayerRevealOverride";
|
|
14
|
+
import { readEffectiveZIndex } from "./canvasContextMenuZOrder";
|
|
15
|
+
import { getElementZIndex } from "../../player/lib/layerOrdering";
|
|
16
|
+
import {
|
|
17
|
+
LAYER_REVEAL_PRIOR_Z_ATTR,
|
|
18
|
+
readTimelineElementZIndex,
|
|
19
|
+
} from "../../player/lib/timelineElementHelpers";
|
|
20
|
+
import { installReactActEnvironment } from "../../hooks/domSelectionTestHarness";
|
|
21
|
+
|
|
22
|
+
installReactActEnvironment();
|
|
23
|
+
|
|
24
|
+
function makeEl(zIndex?: string, position?: string): HTMLElement {
|
|
25
|
+
const el = document.createElement("div");
|
|
26
|
+
if (zIndex != null) el.style.zIndex = zIndex;
|
|
27
|
+
if (position != null) el.style.position = position;
|
|
28
|
+
document.body.appendChild(el);
|
|
29
|
+
return el;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe("liftElementToTop / restoreLiftedElement", () => {
|
|
33
|
+
it("paints on top but every z reader keeps reporting the TRUE z", () => {
|
|
34
|
+
const el = makeEl("6", "absolute");
|
|
35
|
+
const lift = liftElementToTop(el);
|
|
36
|
+
expect(lift).not.toBeNull();
|
|
37
|
+
// The renderer sees the lifted value…
|
|
38
|
+
expect(el.style.zIndex).toBe(LAYER_REVEAL_LIFT_Z);
|
|
39
|
+
// …every studio reader sees the true z.
|
|
40
|
+
expect(readEffectiveZIndex(el)).toBe(6);
|
|
41
|
+
expect(getElementZIndex(el)).toBe(6);
|
|
42
|
+
expect(readTimelineElementZIndex(el)).toBe(6);
|
|
43
|
+
|
|
44
|
+
restoreLiftedElement(el, lift!);
|
|
45
|
+
expect(el.style.zIndex).toBe("6");
|
|
46
|
+
expect(el.hasAttribute(LAYER_REVEAL_PRIOR_Z_ATTR)).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("gives a static element a temporary position:relative and restores it", () => {
|
|
50
|
+
const el = makeEl();
|
|
51
|
+
const lift = liftElementToTop(el)!;
|
|
52
|
+
expect(el.style.position).toBe("relative");
|
|
53
|
+
expect(lift.positionLifted).toBe(true);
|
|
54
|
+
restoreLiftedElement(el, lift);
|
|
55
|
+
expect(el.style.position).toBe("");
|
|
56
|
+
expect(el.style.zIndex).toBe("");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("a z-reorder commit consumes the lift: restore becomes a no-op", () => {
|
|
60
|
+
const el = makeEl("3", "absolute");
|
|
61
|
+
const lift = liftElementToTop(el)!;
|
|
62
|
+
// Simulate handleDomZIndexReorderCommit: real z written, attrs removed.
|
|
63
|
+
el.removeAttribute(LAYER_REVEAL_PRIOR_Z_ATTR);
|
|
64
|
+
el.style.zIndex = "8";
|
|
65
|
+
restoreLiftedElement(el, lift);
|
|
66
|
+
expect(el.style.zIndex).toBe("8"); // the commit's value survives
|
|
67
|
+
expect(readEffectiveZIndex(el)).toBe(8);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("durable z persistence consumes its pending reveal ownership", () => {
|
|
71
|
+
const el = makeEl("3", "absolute");
|
|
72
|
+
const lift = liftElementToTop(el)!;
|
|
73
|
+
const ownership = beginLayerRevealCommit(el)!;
|
|
74
|
+
el.style.zIndex = "8";
|
|
75
|
+
|
|
76
|
+
expect(el.hasAttribute(LAYER_REVEAL_PENDING_COMMIT_ATTR)).toBe(true);
|
|
77
|
+
completeLayerRevealCommit(el, ownership);
|
|
78
|
+
restoreLiftedElement(el, lift);
|
|
79
|
+
|
|
80
|
+
expect(el.style.zIndex).toBe("8");
|
|
81
|
+
expect(el.hasAttribute(LAYER_REVEAL_PENDING_COMMIT_ATTR)).toBe(false);
|
|
82
|
+
expect(el.hasAttribute(LAYER_REVEAL_PRIOR_Z_ATTR)).toBe(false);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("does not clobber a z someone else wrote while lifted", () => {
|
|
86
|
+
const el = makeEl("3", "absolute");
|
|
87
|
+
const lift = liftElementToTop(el)!;
|
|
88
|
+
el.style.zIndex = "42"; // e.g. a GSAP seek or manual edit
|
|
89
|
+
restoreLiftedElement(el, lift);
|
|
90
|
+
expect(el.style.zIndex).toBe("42");
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe("useLayerRevealOverride — delayed reveal ownership", () => {
|
|
95
|
+
beforeEach(() => {
|
|
96
|
+
vi.useFakeTimers();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
afterEach(() => {
|
|
100
|
+
vi.useRealTimers();
|
|
101
|
+
document.body.innerHTML = "";
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("cancels a pending reveal when selection changes or playback begins", () => {
|
|
105
|
+
const host = document.createElement("div");
|
|
106
|
+
const selected = makeEl("2", "absolute");
|
|
107
|
+
const other = makeEl("3", "absolute");
|
|
108
|
+
document.body.appendChild(host);
|
|
109
|
+
const root = createRoot(host);
|
|
110
|
+
let scheduleReveal: ((element: HTMLElement, delayMs: number) => void) | undefined;
|
|
111
|
+
|
|
112
|
+
function Harness({ element, isPlaying }: { element: HTMLElement; isPlaying: boolean }) {
|
|
113
|
+
({ scheduleReveal } = useLayerRevealOverride({
|
|
114
|
+
isPlaying,
|
|
115
|
+
selectedElement: element,
|
|
116
|
+
}));
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
act(() => {
|
|
121
|
+
root.render(React.createElement(Harness, { element: selected, isPlaying: false }));
|
|
122
|
+
});
|
|
123
|
+
act(() => scheduleReveal!(selected, 150));
|
|
124
|
+
expect(vi.getTimerCount()).toBe(1);
|
|
125
|
+
|
|
126
|
+
act(() => {
|
|
127
|
+
root.render(React.createElement(Harness, { element: other, isPlaying: false }));
|
|
128
|
+
});
|
|
129
|
+
expect(vi.getTimerCount()).toBe(0);
|
|
130
|
+
|
|
131
|
+
act(() => scheduleReveal!(other, 150));
|
|
132
|
+
expect(vi.getTimerCount()).toBe(1);
|
|
133
|
+
act(() => {
|
|
134
|
+
root.render(React.createElement(Harness, { element: other, isPlaying: true }));
|
|
135
|
+
});
|
|
136
|
+
expect(vi.getTimerCount()).toBe(0);
|
|
137
|
+
|
|
138
|
+
act(() => vi.advanceTimersByTime(150));
|
|
139
|
+
expect(selected.style.zIndex).toBe("2");
|
|
140
|
+
expect(other.style.zIndex).toBe("3");
|
|
141
|
+
act(() => root.unmount());
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("revalidates the current selection before a delayed reveal runs", () => {
|
|
145
|
+
const host = document.createElement("div");
|
|
146
|
+
const selected = makeEl("2", "absolute");
|
|
147
|
+
const stale = makeEl("3", "absolute");
|
|
148
|
+
document.body.appendChild(host);
|
|
149
|
+
const root = createRoot(host);
|
|
150
|
+
let scheduleReveal: ((element: HTMLElement, delayMs: number) => void) | undefined;
|
|
151
|
+
|
|
152
|
+
function Harness() {
|
|
153
|
+
({ scheduleReveal } = useLayerRevealOverride({
|
|
154
|
+
isPlaying: false,
|
|
155
|
+
selectedElement: selected,
|
|
156
|
+
}));
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
act(() => root.render(React.createElement(Harness)));
|
|
161
|
+
act(() => scheduleReveal!(stale, 150));
|
|
162
|
+
expect(vi.getTimerCount()).toBe(1);
|
|
163
|
+
act(() => vi.advanceTimersByTime(150));
|
|
164
|
+
|
|
165
|
+
expect(stale.style.zIndex).toBe("3");
|
|
166
|
+
expect(stale.hasAttribute(LAYER_REVEAL_PRIOR_Z_ATTR)).toBe(false);
|
|
167
|
+
act(() => root.unmount());
|
|
168
|
+
});
|
|
169
|
+
});
|