hyperframes 0.8.48 → 0.8.49
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/cli.js +81 -14
- package/dist/fontLocalizeCli.js +76 -13
- package/dist/hyperframe-runtime.js +34 -27
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +34 -27
- package/dist/hyperframes-player.global.js +3 -3
- package/dist/studio/assets/hyperframes-player-CqON2Rzo.js +464 -0
- package/dist/studio/assets/{index-B3-orIjW.js → index-BGovDksE.js} +1 -1
- package/dist/studio/assets/{index-C9gJKpqQ.js → index-Bgmx2h7W.js} +135 -135
- package/dist/studio/assets/{index-D_j-0PD3.js → index-mIgSsKqs.js} +1 -1
- package/dist/studio/index.d.ts +4 -3
- package/dist/studio/index.html +1 -1
- package/dist/studio/index.js +443 -303
- package/dist/studio/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/studio/assets/hyperframes-player-CtVX6jL_.js +0 -464
package/dist/studio/index.js
CHANGED
|
@@ -1195,6 +1195,9 @@ function deriveTimelineStoreKey(params) {
|
|
|
1195
1195
|
if (!params.domId && !params.selector) return void 0;
|
|
1196
1196
|
return buildTimelineElementKey({ id: "", fallbackIndex: 0, ...params });
|
|
1197
1197
|
}
|
|
1198
|
+
function deriveTimelineStoreKeyForDomId(domId, sourceFile) {
|
|
1199
|
+
return deriveTimelineStoreKey({ domId, sourceFile });
|
|
1200
|
+
}
|
|
1198
1201
|
function getTimelineDomNodes(doc) {
|
|
1199
1202
|
const rootComp = doc.querySelector("[data-composition-id]");
|
|
1200
1203
|
return Array.from(doc.querySelectorAll("[data-start]")).filter(
|
|
@@ -18623,6 +18626,71 @@ function snapMoveToTargets(start, duration, targets, pixelsPerSecond, timelineDu
|
|
|
18623
18626
|
return { start: clamped, snapTime: target?.time ?? null, snapType: target?.type ?? null };
|
|
18624
18627
|
}
|
|
18625
18628
|
|
|
18629
|
+
// src/player/components/timelineZones.ts
|
|
18630
|
+
function classifyZone(el) {
|
|
18631
|
+
return isAudioTimelineElement(el) ? "audio" : "visual";
|
|
18632
|
+
}
|
|
18633
|
+
function isMainTrackElement(el) {
|
|
18634
|
+
return el.track === 0 && classifyZone(el) === "visual" && el.expandedParentStart == null;
|
|
18635
|
+
}
|
|
18636
|
+
var keyOf = (el) => el.key ?? el.id;
|
|
18637
|
+
var EPS = 1e-6;
|
|
18638
|
+
function overlaps2(a, b) {
|
|
18639
|
+
return a.start < b.start + b.duration - EPS && b.start < a.start + a.duration - EPS;
|
|
18640
|
+
}
|
|
18641
|
+
function byStableId(a, b) {
|
|
18642
|
+
const ka = keyOf(a);
|
|
18643
|
+
const kb = keyOf(b);
|
|
18644
|
+
return ka < kb ? -1 : ka > kb ? 1 : 0;
|
|
18645
|
+
}
|
|
18646
|
+
function packTrackLanes(clips, base2, laneOf) {
|
|
18647
|
+
const ordered = [...clips].sort(byStableId);
|
|
18648
|
+
const lanes = [];
|
|
18649
|
+
for (const el of ordered) {
|
|
18650
|
+
let sub = lanes.findIndex((occ) => occ.every((o) => !overlaps2(o, el)));
|
|
18651
|
+
if (sub === -1) {
|
|
18652
|
+
sub = lanes.length;
|
|
18653
|
+
lanes.push([]);
|
|
18654
|
+
}
|
|
18655
|
+
lanes[sub].push(el);
|
|
18656
|
+
laneOf.set(keyOf(el), base2 + sub);
|
|
18657
|
+
}
|
|
18658
|
+
return Math.max(1, lanes.length);
|
|
18659
|
+
}
|
|
18660
|
+
function packZoneLanes(clips, base2, laneOf) {
|
|
18661
|
+
const byTrack = /* @__PURE__ */ new Map();
|
|
18662
|
+
for (const el of clips) {
|
|
18663
|
+
const list = byTrack.get(el.track);
|
|
18664
|
+
if (list) list.push(el);
|
|
18665
|
+
else byTrack.set(el.track, [el]);
|
|
18666
|
+
}
|
|
18667
|
+
let used = 0;
|
|
18668
|
+
for (const track2 of [...byTrack.keys()].sort((a, b) => a - b)) {
|
|
18669
|
+
used += packTrackLanes(byTrack.get(track2), base2 + used, laneOf);
|
|
18670
|
+
}
|
|
18671
|
+
return used;
|
|
18672
|
+
}
|
|
18673
|
+
function normalizeToZones(elements) {
|
|
18674
|
+
if (elements.length === 0) return elements;
|
|
18675
|
+
const laneOf = /* @__PURE__ */ new Map();
|
|
18676
|
+
const visual = [];
|
|
18677
|
+
const audio = [];
|
|
18678
|
+
for (const el of elements) {
|
|
18679
|
+
(classifyZone(el) === "audio" ? audio : visual).push(el);
|
|
18680
|
+
}
|
|
18681
|
+
let nextLane = 0;
|
|
18682
|
+
nextLane += packZoneLanes(visual, nextLane, laneOf);
|
|
18683
|
+
packZoneLanes(audio, nextLane, laneOf);
|
|
18684
|
+
let changed = false;
|
|
18685
|
+
const remapped = elements.map((el) => {
|
|
18686
|
+
const lane = laneOf.get(keyOf(el));
|
|
18687
|
+
if (lane == null || lane === el.track) return el;
|
|
18688
|
+
changed = true;
|
|
18689
|
+
return { ...el, track: lane, authoredTrack: el.authoredTrack ?? el.track };
|
|
18690
|
+
});
|
|
18691
|
+
return changed ? remapped : elements;
|
|
18692
|
+
}
|
|
18693
|
+
|
|
18626
18694
|
// src/player/components/timelineCollision.ts
|
|
18627
18695
|
function clampTrackToZone(targetTrack, trackOrder, audioRow, isAudio) {
|
|
18628
18696
|
if (audioRow < 0) return targetTrack;
|
|
@@ -18675,6 +18743,21 @@ function resolveZoneDropPlacement(input) {
|
|
|
18675
18743
|
}
|
|
18676
18744
|
return { track: placement.track, insertRow: null };
|
|
18677
18745
|
}
|
|
18746
|
+
function landsOnMainTrack(landingTrack, isAudio) {
|
|
18747
|
+
return isMainTrackElement({
|
|
18748
|
+
id: "",
|
|
18749
|
+
tag: isAudio ? "audio" : "video",
|
|
18750
|
+
start: 0,
|
|
18751
|
+
duration: 0,
|
|
18752
|
+
track: landingTrack
|
|
18753
|
+
});
|
|
18754
|
+
}
|
|
18755
|
+
function resolveMainTrackDropStart(others, originTrack, landingTrack, isAudio, desiredStart) {
|
|
18756
|
+
if (originTrack === landingTrack || !landsOnMainTrack(landingTrack, isAudio)) {
|
|
18757
|
+
return desiredStart;
|
|
18758
|
+
}
|
|
18759
|
+
return others.some(isMainTrackElement) ? desiredStart : 0;
|
|
18760
|
+
}
|
|
18678
18761
|
function resolveInsertRow(rowFloat, trackCount, band = INSERT_BOUNDARY_BAND) {
|
|
18679
18762
|
if (trackCount === 0) return 0;
|
|
18680
18763
|
if (rowFloat <= 0) return 0;
|
|
@@ -18720,6 +18803,197 @@ function resolvePlacement({
|
|
|
18720
18803
|
return { track: desiredTrack, needsInsert: true };
|
|
18721
18804
|
}
|
|
18722
18805
|
|
|
18806
|
+
// src/player/components/timelineAuthoredMoveTarget.ts
|
|
18807
|
+
function canMoveTimelineElement(element) {
|
|
18808
|
+
return getTimelineEditCapabilities({
|
|
18809
|
+
tag: element.tag,
|
|
18810
|
+
kind: element.kind,
|
|
18811
|
+
duration: element.duration,
|
|
18812
|
+
domId: element.domId,
|
|
18813
|
+
hfId: element.hfId,
|
|
18814
|
+
selector: element.selector,
|
|
18815
|
+
compositionSrc: element.compositionSrc,
|
|
18816
|
+
playbackStart: element.playbackStart,
|
|
18817
|
+
playbackStartAttr: element.playbackStartAttr,
|
|
18818
|
+
sourceDuration: element.sourceDuration,
|
|
18819
|
+
timingSource: element.timingSource,
|
|
18820
|
+
timelineLocked: element.timelineLocked
|
|
18821
|
+
}).canMove;
|
|
18822
|
+
}
|
|
18823
|
+
function resolveExpandedHostAlias(drag, deps) {
|
|
18824
|
+
const selectedKeys = deps.selectedKeys;
|
|
18825
|
+
if (!selectedKeys) return null;
|
|
18826
|
+
const collapsedKeys = new Set(selectedKeys);
|
|
18827
|
+
const candidates = deps.elements.includes(drag.element) ? deps.elements : [...deps.elements, drag.element];
|
|
18828
|
+
for (const element of candidates) {
|
|
18829
|
+
const hostKey2 = element.expandedHostKey;
|
|
18830
|
+
const childKey2 = getTimelineElementIdentity(element);
|
|
18831
|
+
if (hostKey2 && collapsedKeys.has(hostKey2) && collapsedKeys.has(childKey2)) {
|
|
18832
|
+
collapsedKeys.delete(childKey2);
|
|
18833
|
+
}
|
|
18834
|
+
}
|
|
18835
|
+
const hostKey = drag.element.expandedHostKey;
|
|
18836
|
+
const childKey = getTimelineElementIdentity(drag.element);
|
|
18837
|
+
if (!hostKey || collapsedKeys.has(childKey)) {
|
|
18838
|
+
if (collapsedKeys.size === selectedKeys.size) return null;
|
|
18839
|
+
return { drag, selectedKeys: collapsedKeys };
|
|
18840
|
+
}
|
|
18841
|
+
const host = deps.elements.find((element) => getTimelineElementIdentity(element) === hostKey);
|
|
18842
|
+
if (!host || !canMoveTimelineElement(host)) return null;
|
|
18843
|
+
const delta = drag.previewStart - drag.element.start;
|
|
18844
|
+
const mapTrack = (track2) => track2 === drag.element.track ? host.track : track2;
|
|
18845
|
+
return {
|
|
18846
|
+
drag: {
|
|
18847
|
+
...drag,
|
|
18848
|
+
element: host,
|
|
18849
|
+
previewStart: Math.max(0, Math.round((host.start + delta) * 1e3) / 1e3),
|
|
18850
|
+
previewTrack: mapTrack(drag.previewTrack) ?? host.track,
|
|
18851
|
+
desiredTrack: mapTrack(drag.desiredTrack)
|
|
18852
|
+
},
|
|
18853
|
+
selectedKeys: collapsedKeys
|
|
18854
|
+
};
|
|
18855
|
+
}
|
|
18856
|
+
|
|
18857
|
+
// src/player/components/timelineAuthoredTrack.ts
|
|
18858
|
+
var keyOf2 = (element) => element.key ?? element.id;
|
|
18859
|
+
var sameSourceFile = (a, b) => (a.sourceFile ?? null) === (b.sourceFile ?? null);
|
|
18860
|
+
function authoredTrackForLane(lane, elements, dragged) {
|
|
18861
|
+
const dragKey = keyOf2(dragged);
|
|
18862
|
+
const peers = elements.filter((element) => {
|
|
18863
|
+
return keyOf2(element) !== dragKey && sameSourceFile(element, dragged);
|
|
18864
|
+
});
|
|
18865
|
+
const occupant = peers.find((element) => element.track === lane);
|
|
18866
|
+
if (occupant) return occupant.authoredTrack ?? occupant.track;
|
|
18867
|
+
let nearest = null;
|
|
18868
|
+
for (const peer of peers) {
|
|
18869
|
+
if (!nearest || Math.abs(peer.track - lane) < Math.abs(nearest.track - lane)) nearest = peer;
|
|
18870
|
+
}
|
|
18871
|
+
if (!nearest) return lane;
|
|
18872
|
+
return Math.round((nearest.authoredTrack ?? nearest.track) + (lane - nearest.track));
|
|
18873
|
+
}
|
|
18874
|
+
|
|
18875
|
+
// src/player/components/timelineGaps.ts
|
|
18876
|
+
var TRACK_GAP_EPSILON_S = 1e-3;
|
|
18877
|
+
var keyOf3 = (e) => e.key ?? e.id;
|
|
18878
|
+
function laneGapFloor(elements) {
|
|
18879
|
+
return Math.max(0, ...elements.map((e) => e.expandedParentStart ?? 0));
|
|
18880
|
+
}
|
|
18881
|
+
var round3 = (v) => Math.round(v * 1e3) / 1e3;
|
|
18882
|
+
var endOf = (e) => e.start + e.duration;
|
|
18883
|
+
function sortedLaneClips(elements) {
|
|
18884
|
+
return [...elements].sort((a, b) => a.start - b.start || keyOf3(a).localeCompare(keyOf3(b)));
|
|
18885
|
+
}
|
|
18886
|
+
function resolveTrackGapAt(elements, time, epsilon = TRACK_GAP_EPSILON_S, floor = 0) {
|
|
18887
|
+
const clips = sortedLaneClips(elements);
|
|
18888
|
+
const occupied = clips.some((c) => time >= c.start - epsilon && time < endOf(c) - epsilon);
|
|
18889
|
+
if (occupied) return null;
|
|
18890
|
+
const following = clips.filter((c) => c.start > time - epsilon);
|
|
18891
|
+
if (following.length === 0) return null;
|
|
18892
|
+
const gapEnd = following[0].start;
|
|
18893
|
+
const gapStart = Math.max(
|
|
18894
|
+
floor,
|
|
18895
|
+
...clips.filter((c) => c.start <= time - epsilon).map((c) => endOf(c))
|
|
18896
|
+
);
|
|
18897
|
+
if (gapEnd - gapStart <= epsilon) return null;
|
|
18898
|
+
return { gapStart, gapEnd, followingKeys: following.map(keyOf3) };
|
|
18899
|
+
}
|
|
18900
|
+
function resolveAllGapIntervals(elements, epsilon = TRACK_GAP_EPSILON_S, floor = 0) {
|
|
18901
|
+
const gaps = [];
|
|
18902
|
+
let cursor = floor;
|
|
18903
|
+
for (const clip of sortedLaneClips(elements)) {
|
|
18904
|
+
if (clip.start - cursor > epsilon) gaps.push({ start: cursor, end: clip.start });
|
|
18905
|
+
cursor = Math.max(cursor, endOf(clip));
|
|
18906
|
+
}
|
|
18907
|
+
return gaps;
|
|
18908
|
+
}
|
|
18909
|
+
function resolveAllTrackGaps(elements, epsilon = TRACK_GAP_EPSILON_S, floor = 0) {
|
|
18910
|
+
const shifts = [];
|
|
18911
|
+
let cursor = floor;
|
|
18912
|
+
for (const clip of sortedLaneClips(elements)) {
|
|
18913
|
+
const newStart = round3(cursor);
|
|
18914
|
+
if (Math.abs(newStart - clip.start) > epsilon) {
|
|
18915
|
+
shifts.push({ key: keyOf3(clip), newStart });
|
|
18916
|
+
}
|
|
18917
|
+
cursor += clip.duration;
|
|
18918
|
+
}
|
|
18919
|
+
return shifts;
|
|
18920
|
+
}
|
|
18921
|
+
function resolveLaneEmptyIntervals(elements, end, epsilon = TRACK_GAP_EPSILON_S, floor = 0) {
|
|
18922
|
+
const gaps = resolveAllGapIntervals(elements, epsilon, floor);
|
|
18923
|
+
const maxEnd = Math.max(floor, ...elements.map(endOf));
|
|
18924
|
+
if (end - maxEnd > epsilon) gaps.push({ start: maxEnd, end });
|
|
18925
|
+
return gaps;
|
|
18926
|
+
}
|
|
18927
|
+
function resolveCloseGapShifts(elements, gap) {
|
|
18928
|
+
const width = gap.gapEnd - gap.gapStart;
|
|
18929
|
+
const followSet = new Set(gap.followingKeys);
|
|
18930
|
+
return sortedLaneClips(elements).filter((c) => followSet.has(keyOf3(c))).map((c) => ({ key: keyOf3(c), newStart: Math.max(gap.gapStart, round3(c.start - width)) }));
|
|
18931
|
+
}
|
|
18932
|
+
|
|
18933
|
+
// src/player/components/timelineDragLanding.ts
|
|
18934
|
+
var keyOf4 = (e) => e.key ?? e.id;
|
|
18935
|
+
function insertTrackValue(trackOrder, insertRow) {
|
|
18936
|
+
if (trackOrder.length === 0) return 0;
|
|
18937
|
+
if (insertRow <= 0) return trackOrder[0] - 0.5;
|
|
18938
|
+
if (insertRow >= trackOrder.length) return trackOrder[trackOrder.length - 1] + 0.5;
|
|
18939
|
+
return (trackOrder[insertRow - 1] + trackOrder[insertRow]) / 2;
|
|
18940
|
+
}
|
|
18941
|
+
function layoutAfterTrackInsert(element, previewStart, insertRow, multi, deps) {
|
|
18942
|
+
const { elements, trackOrder } = deps;
|
|
18943
|
+
const editKey = keyOf4(element);
|
|
18944
|
+
if (element.expandedParentStart != null) return null;
|
|
18945
|
+
const targetTrack = insertTrackValue(trackOrder, insertRow);
|
|
18946
|
+
const writableZone = classifyZone(element);
|
|
18947
|
+
const writable = (src) => sameSourceFile(src, element) && classifyZone(src) === writableZone && src.expandedParentStart == null;
|
|
18948
|
+
const topologyOrder = [...new Set(elements.filter(writable).map((e) => e.track))].sort(
|
|
18949
|
+
(a, b) => a - b
|
|
18950
|
+
);
|
|
18951
|
+
const topologyInsertRow = topologyOrder.filter((track2) => track2 < targetTrack).length;
|
|
18952
|
+
const topologyTargetTrack = insertTrackValue(topologyOrder, topologyInsertRow);
|
|
18953
|
+
const normalized = normalizeToZones(
|
|
18954
|
+
elements.filter(writable).map((e) => {
|
|
18955
|
+
if (keyOf4(e) === editKey) {
|
|
18956
|
+
return { ...e, start: previewStart, track: topologyTargetTrack };
|
|
18957
|
+
}
|
|
18958
|
+
if (multi?.keys.has(keyOf4(e))) return { ...e, start: multi.movedStart(e) };
|
|
18959
|
+
return e;
|
|
18960
|
+
})
|
|
18961
|
+
);
|
|
18962
|
+
return { normalized, targetTrack, writable };
|
|
18963
|
+
}
|
|
18964
|
+
function resolveDragLandingStart(drag, deps) {
|
|
18965
|
+
const alias = resolveExpandedHostAlias(drag, deps);
|
|
18966
|
+
const target = alias?.drag ?? drag;
|
|
18967
|
+
const keys = alias?.selectedKeys ?? deps.selectedKeys;
|
|
18968
|
+
const element = target.element;
|
|
18969
|
+
const key2 = keyOf4(element);
|
|
18970
|
+
if (keys && keys.size > 1 && keys.has(key2)) return drag.previewStart;
|
|
18971
|
+
let landingTrack = target.previewTrack;
|
|
18972
|
+
let renumbered = /* @__PURE__ */ new Map();
|
|
18973
|
+
if (target.insertRow != null) {
|
|
18974
|
+
const layout = layoutAfterTrackInsert(
|
|
18975
|
+
element,
|
|
18976
|
+
target.previewStart,
|
|
18977
|
+
target.insertRow,
|
|
18978
|
+
null,
|
|
18979
|
+
deps
|
|
18980
|
+
);
|
|
18981
|
+
if (layout) {
|
|
18982
|
+
renumbered = new Map(layout.normalized.map((n) => [keyOf4(n), n.track]));
|
|
18983
|
+
landingTrack = renumbered.get(key2) ?? layout.targetTrack;
|
|
18984
|
+
}
|
|
18985
|
+
}
|
|
18986
|
+
const others = deps.elements.filter((e) => keyOf4(e) !== key2).map((e) => renumbered.has(keyOf4(e)) ? { ...e, track: renumbered.get(keyOf4(e)) } : e);
|
|
18987
|
+
const snapped = resolveMainTrackDropStart(
|
|
18988
|
+
others,
|
|
18989
|
+
element.track,
|
|
18990
|
+
landingTrack,
|
|
18991
|
+
isAudioTimelineElement(element),
|
|
18992
|
+
target.previewStart
|
|
18993
|
+
);
|
|
18994
|
+
return snapped === target.previewStart ? drag.previewStart : round3(drag.previewStart + snapped - target.previewStart);
|
|
18995
|
+
}
|
|
18996
|
+
|
|
18723
18997
|
// src/player/components/timelineClipDragPreview.ts
|
|
18724
18998
|
function getTimelineDragOverlayPosition(drag, scroll) {
|
|
18725
18999
|
if (!drag.started || !scroll) return null;
|
|
@@ -18818,12 +19092,18 @@ function computeDragPreview(drag, clientX, clientY, ctx3) {
|
|
|
18818
19092
|
nextMove.track,
|
|
18819
19093
|
ctx3
|
|
18820
19094
|
);
|
|
19095
|
+
const placed = { ...drag, previewStart, previewTrack, insertRow };
|
|
19096
|
+
const snappedStart = resolveDragLandingStart(placed, {
|
|
19097
|
+
elements,
|
|
19098
|
+
trackOrder,
|
|
19099
|
+
selectedKeys
|
|
19100
|
+
});
|
|
18821
19101
|
return {
|
|
18822
19102
|
...drag,
|
|
18823
19103
|
started: true,
|
|
18824
19104
|
pointerClientX: clientX,
|
|
18825
19105
|
pointerClientY: clientY,
|
|
18826
|
-
previewStart,
|
|
19106
|
+
previewStart: snappedStart,
|
|
18827
19107
|
previewTrack,
|
|
18828
19108
|
// The lane the POINTER aims at (pre-collision): the commit reads it to tell a
|
|
18829
19109
|
// deliberate vertical lane change from a horizontal drag merely bumped sideways.
|
|
@@ -19179,71 +19459,6 @@ var TimelineCanvas = memo13(function TimelineCanvas2(props) {
|
|
|
19179
19459
|
// src/player/components/useTimelineClipDrag.ts
|
|
19180
19460
|
import { useRef as useRef29, useState as useState17, useCallback as useCallback19, useMemo as useMemo16, useEffect as useEffect21 } from "react";
|
|
19181
19461
|
|
|
19182
|
-
// src/player/components/timelineZones.ts
|
|
19183
|
-
function classifyZone(el) {
|
|
19184
|
-
return isAudioTimelineElement(el) ? "audio" : "visual";
|
|
19185
|
-
}
|
|
19186
|
-
function isMainTrackElement(el) {
|
|
19187
|
-
return el.track === 0 && classifyZone(el) === "visual" && el.expandedParentStart == null;
|
|
19188
|
-
}
|
|
19189
|
-
var keyOf = (el) => el.key ?? el.id;
|
|
19190
|
-
var EPS = 1e-6;
|
|
19191
|
-
function overlaps2(a, b) {
|
|
19192
|
-
return a.start < b.start + b.duration - EPS && b.start < a.start + a.duration - EPS;
|
|
19193
|
-
}
|
|
19194
|
-
function byStableId(a, b) {
|
|
19195
|
-
const ka = keyOf(a);
|
|
19196
|
-
const kb = keyOf(b);
|
|
19197
|
-
return ka < kb ? -1 : ka > kb ? 1 : 0;
|
|
19198
|
-
}
|
|
19199
|
-
function packTrackLanes(clips, base2, laneOf) {
|
|
19200
|
-
const ordered = [...clips].sort(byStableId);
|
|
19201
|
-
const lanes = [];
|
|
19202
|
-
for (const el of ordered) {
|
|
19203
|
-
let sub = lanes.findIndex((occ) => occ.every((o) => !overlaps2(o, el)));
|
|
19204
|
-
if (sub === -1) {
|
|
19205
|
-
sub = lanes.length;
|
|
19206
|
-
lanes.push([]);
|
|
19207
|
-
}
|
|
19208
|
-
lanes[sub].push(el);
|
|
19209
|
-
laneOf.set(keyOf(el), base2 + sub);
|
|
19210
|
-
}
|
|
19211
|
-
return Math.max(1, lanes.length);
|
|
19212
|
-
}
|
|
19213
|
-
function packZoneLanes(clips, base2, laneOf) {
|
|
19214
|
-
const byTrack = /* @__PURE__ */ new Map();
|
|
19215
|
-
for (const el of clips) {
|
|
19216
|
-
const list = byTrack.get(el.track);
|
|
19217
|
-
if (list) list.push(el);
|
|
19218
|
-
else byTrack.set(el.track, [el]);
|
|
19219
|
-
}
|
|
19220
|
-
let used = 0;
|
|
19221
|
-
for (const track2 of [...byTrack.keys()].sort((a, b) => a - b)) {
|
|
19222
|
-
used += packTrackLanes(byTrack.get(track2), base2 + used, laneOf);
|
|
19223
|
-
}
|
|
19224
|
-
return used;
|
|
19225
|
-
}
|
|
19226
|
-
function normalizeToZones(elements) {
|
|
19227
|
-
if (elements.length === 0) return elements;
|
|
19228
|
-
const laneOf = /* @__PURE__ */ new Map();
|
|
19229
|
-
const visual = [];
|
|
19230
|
-
const audio = [];
|
|
19231
|
-
for (const el of elements) {
|
|
19232
|
-
(classifyZone(el) === "audio" ? audio : visual).push(el);
|
|
19233
|
-
}
|
|
19234
|
-
let nextLane = 0;
|
|
19235
|
-
nextLane += packZoneLanes(visual, nextLane, laneOf);
|
|
19236
|
-
packZoneLanes(audio, nextLane, laneOf);
|
|
19237
|
-
let changed = false;
|
|
19238
|
-
const remapped = elements.map((el) => {
|
|
19239
|
-
const lane = laneOf.get(keyOf(el));
|
|
19240
|
-
if (lane == null || lane === el.track) return el;
|
|
19241
|
-
changed = true;
|
|
19242
|
-
return { ...el, track: lane, authoredTrack: el.authoredTrack ?? el.track };
|
|
19243
|
-
});
|
|
19244
|
-
return changed ? remapped : elements;
|
|
19245
|
-
}
|
|
19246
|
-
|
|
19247
19462
|
// src/player/components/timelineStackingSync.ts
|
|
19248
19463
|
var EPS2 = 1e-6;
|
|
19249
19464
|
var paintScopeKey = (el) => JSON.stringify([el.sourceFile ?? null, el.stackingContextId ?? null]);
|
|
@@ -19359,57 +19574,6 @@ function computeStackingPatches(elements, editedKeys) {
|
|
|
19359
19574
|
return patches;
|
|
19360
19575
|
}
|
|
19361
19576
|
|
|
19362
|
-
// src/player/components/timelineAuthoredMoveTarget.ts
|
|
19363
|
-
function canMoveTimelineElement(element) {
|
|
19364
|
-
return getTimelineEditCapabilities({
|
|
19365
|
-
tag: element.tag,
|
|
19366
|
-
kind: element.kind,
|
|
19367
|
-
duration: element.duration,
|
|
19368
|
-
domId: element.domId,
|
|
19369
|
-
hfId: element.hfId,
|
|
19370
|
-
selector: element.selector,
|
|
19371
|
-
compositionSrc: element.compositionSrc,
|
|
19372
|
-
playbackStart: element.playbackStart,
|
|
19373
|
-
playbackStartAttr: element.playbackStartAttr,
|
|
19374
|
-
sourceDuration: element.sourceDuration,
|
|
19375
|
-
timingSource: element.timingSource,
|
|
19376
|
-
timelineLocked: element.timelineLocked
|
|
19377
|
-
}).canMove;
|
|
19378
|
-
}
|
|
19379
|
-
function resolveExpandedHostAlias(drag, deps) {
|
|
19380
|
-
const selectedKeys = deps.selectedKeys;
|
|
19381
|
-
if (!selectedKeys) return null;
|
|
19382
|
-
const collapsedKeys = new Set(selectedKeys);
|
|
19383
|
-
const candidates = deps.elements.includes(drag.element) ? deps.elements : [...deps.elements, drag.element];
|
|
19384
|
-
for (const element of candidates) {
|
|
19385
|
-
const hostKey2 = element.expandedHostKey;
|
|
19386
|
-
const childKey2 = getTimelineElementIdentity(element);
|
|
19387
|
-
if (hostKey2 && collapsedKeys.has(hostKey2) && collapsedKeys.has(childKey2)) {
|
|
19388
|
-
collapsedKeys.delete(childKey2);
|
|
19389
|
-
}
|
|
19390
|
-
}
|
|
19391
|
-
const hostKey = drag.element.expandedHostKey;
|
|
19392
|
-
const childKey = getTimelineElementIdentity(drag.element);
|
|
19393
|
-
if (!hostKey || collapsedKeys.has(childKey)) {
|
|
19394
|
-
if (collapsedKeys.size === selectedKeys.size) return null;
|
|
19395
|
-
return { drag, selectedKeys: collapsedKeys };
|
|
19396
|
-
}
|
|
19397
|
-
const host = deps.elements.find((element) => getTimelineElementIdentity(element) === hostKey);
|
|
19398
|
-
if (!host || !canMoveTimelineElement(host)) return null;
|
|
19399
|
-
const delta = drag.previewStart - drag.element.start;
|
|
19400
|
-
const mapTrack = (track2) => track2 === drag.element.track ? host.track : track2;
|
|
19401
|
-
return {
|
|
19402
|
-
drag: {
|
|
19403
|
-
...drag,
|
|
19404
|
-
element: host,
|
|
19405
|
-
previewStart: Math.max(0, Math.round((host.start + delta) * 1e3) / 1e3),
|
|
19406
|
-
previewTrack: mapTrack(drag.previewTrack) ?? host.track,
|
|
19407
|
-
desiredTrack: mapTrack(drag.desiredTrack)
|
|
19408
|
-
},
|
|
19409
|
-
selectedKeys: collapsedKeys
|
|
19410
|
-
};
|
|
19411
|
-
}
|
|
19412
|
-
|
|
19413
19577
|
// src/player/components/timelineOptimisticRevision.ts
|
|
19414
19578
|
var revisionsByUpdater = /* @__PURE__ */ new WeakMap();
|
|
19415
19579
|
function beginTimelineOptimisticGesture(updateElement, keys) {
|
|
@@ -19485,27 +19649,9 @@ function refreshAfterDurableLaneMove(pending2, deps) {
|
|
|
19485
19649
|
});
|
|
19486
19650
|
}
|
|
19487
19651
|
|
|
19488
|
-
// src/player/components/timelineAuthoredTrack.ts
|
|
19489
|
-
var keyOf2 = (element) => element.key ?? element.id;
|
|
19490
|
-
var sameSourceFile = (a, b) => (a.sourceFile ?? null) === (b.sourceFile ?? null);
|
|
19491
|
-
function authoredTrackForLane(lane, elements, dragged) {
|
|
19492
|
-
const dragKey = keyOf2(dragged);
|
|
19493
|
-
const peers = elements.filter((element) => {
|
|
19494
|
-
return keyOf2(element) !== dragKey && sameSourceFile(element, dragged);
|
|
19495
|
-
});
|
|
19496
|
-
const occupant = peers.find((element) => element.track === lane);
|
|
19497
|
-
if (occupant) return occupant.authoredTrack ?? occupant.track;
|
|
19498
|
-
let nearest = null;
|
|
19499
|
-
for (const peer of peers) {
|
|
19500
|
-
if (!nearest || Math.abs(peer.track - lane) < Math.abs(nearest.track - lane)) nearest = peer;
|
|
19501
|
-
}
|
|
19502
|
-
if (!nearest) return lane;
|
|
19503
|
-
return Math.round((nearest.authoredTrack ?? nearest.track) + (lane - nearest.track));
|
|
19504
|
-
}
|
|
19505
|
-
|
|
19506
19652
|
// src/player/components/timelineClipDragCommit.ts
|
|
19507
|
-
var
|
|
19508
|
-
var
|
|
19653
|
+
var keyOf5 = (e) => e.key ?? e.id;
|
|
19654
|
+
var round32 = (v) => Math.round(v * 1e3) / 1e3;
|
|
19509
19655
|
var laneChangeGestureSeq = 0;
|
|
19510
19656
|
function persistMoveEdits(edits, deps, coalesceKey, operation = "timing", coalesceMs) {
|
|
19511
19657
|
if (edits.length === 0) return Promise.resolve(true);
|
|
@@ -19516,19 +19662,19 @@ function persistMoveEdits(edits, deps, coalesceKey, operation = "timing", coales
|
|
|
19516
19662
|
);
|
|
19517
19663
|
}
|
|
19518
19664
|
const prev = edits.map((e) => ({
|
|
19519
|
-
key:
|
|
19665
|
+
key: keyOf5(e.element),
|
|
19520
19666
|
start: e.element.start,
|
|
19521
19667
|
track: e.element.track,
|
|
19522
19668
|
authoredTrack: e.element.authoredTrack
|
|
19523
19669
|
}));
|
|
19524
19670
|
const revision = beginTimelineOptimisticGesture(
|
|
19525
19671
|
updateElement,
|
|
19526
|
-
edits.map((edit) =>
|
|
19672
|
+
edits.map((edit) => keyOf5(edit.element))
|
|
19527
19673
|
);
|
|
19528
19674
|
const applyEdit = (e) => {
|
|
19529
19675
|
const writtenTrack = e.persistTrack ?? (e.updates.track !== e.element.track ? e.updates.track : void 0);
|
|
19530
19676
|
updateElement(
|
|
19531
|
-
|
|
19677
|
+
keyOf5(e.element),
|
|
19532
19678
|
writtenTrack == null ? e.updates : { ...e.updates, authoredTrack: writtenTrack }
|
|
19533
19679
|
);
|
|
19534
19680
|
};
|
|
@@ -19540,7 +19686,7 @@ function persistMoveEdits(edits, deps, coalesceKey, operation = "timing", coales
|
|
|
19540
19686
|
return Promise.resolve(persisted).then(
|
|
19541
19687
|
() => {
|
|
19542
19688
|
for (const e of edits) {
|
|
19543
|
-
const key2 =
|
|
19689
|
+
const key2 = keyOf5(e.element);
|
|
19544
19690
|
if (isLatestTimelineOptimisticGesture(updateElement, revision, key2)) applyEdit(e);
|
|
19545
19691
|
}
|
|
19546
19692
|
return true;
|
|
@@ -19556,34 +19702,29 @@ function persistMoveEdits(edits, deps, coalesceKey, operation = "timing", coales
|
|
|
19556
19702
|
}
|
|
19557
19703
|
);
|
|
19558
19704
|
}
|
|
19559
|
-
function insertTrackValue(trackOrder, insertRow) {
|
|
19560
|
-
if (trackOrder.length === 0) return 0;
|
|
19561
|
-
if (insertRow <= 0) return trackOrder[0] - 0.5;
|
|
19562
|
-
if (insertRow >= trackOrder.length) return trackOrder[trackOrder.length - 1] + 0.5;
|
|
19563
|
-
return (trackOrder[insertRow - 1] + trackOrder[insertRow]) / 2;
|
|
19564
|
-
}
|
|
19565
19705
|
function resolveMultiSelection(drag, deps) {
|
|
19566
19706
|
const { elements, selectedKeys } = deps;
|
|
19567
|
-
const dragKey =
|
|
19707
|
+
const dragKey = keyOf5(drag.element);
|
|
19568
19708
|
if (!selectedKeys || selectedKeys.size <= 1 || !selectedKeys.has(dragKey)) return null;
|
|
19569
19709
|
const keys = new Set(
|
|
19570
19710
|
[...selectedKeys].filter((k) => {
|
|
19571
|
-
const el = elements.find((e) =>
|
|
19711
|
+
const el = elements.find((e) => keyOf5(e) === k);
|
|
19572
19712
|
return el ? canMoveTimelineElement(el) : false;
|
|
19573
19713
|
})
|
|
19574
19714
|
);
|
|
19575
19715
|
const delta = drag.previewStart - drag.element.start;
|
|
19576
|
-
const movedStart = (e) =>
|
|
19716
|
+
const movedStart = (e) => keyOf5(e) === dragKey ? drag.previewStart : Math.max(0, round32(e.start + delta));
|
|
19577
19717
|
return { keys, movedStart };
|
|
19578
19718
|
}
|
|
19579
|
-
function commitDraggedClipMove(
|
|
19719
|
+
function commitDraggedClipMove(rawDrag, deps) {
|
|
19720
|
+
const drag = { ...rawDrag, previewStart: resolveDragLandingStart(rawDrag, deps) };
|
|
19580
19721
|
const hostAlias = resolveExpandedHostAlias(drag, deps);
|
|
19581
19722
|
if (hostAlias) {
|
|
19582
19723
|
commitDraggedClipMove(hostAlias.drag, { ...deps, selectedKeys: hostAlias.selectedKeys });
|
|
19583
19724
|
return;
|
|
19584
19725
|
}
|
|
19585
19726
|
const { elements, updateElement, onMoveElement } = deps;
|
|
19586
|
-
const dragKey =
|
|
19727
|
+
const dragKey = keyOf5(drag.element);
|
|
19587
19728
|
const isInsert = drag.insertRow != null;
|
|
19588
19729
|
const laneChanged = drag.previewTrack !== drag.element.track;
|
|
19589
19730
|
const aimTrack = drag.desiredTrack ?? drag.previewTrack;
|
|
@@ -19593,7 +19734,7 @@ function commitDraggedClipMove(drag, deps) {
|
|
|
19593
19734
|
const delta = drag.previewStart - drag.element.start;
|
|
19594
19735
|
if (delta === 0) return;
|
|
19595
19736
|
if (multi) {
|
|
19596
|
-
const edits2 = elements.filter((e) => multi.keys.has(
|
|
19737
|
+
const edits2 = elements.filter((e) => multi.keys.has(keyOf5(e))).map((e) => ({
|
|
19597
19738
|
element: e,
|
|
19598
19739
|
updates: { start: multi.movedStart(e), track: e.track }
|
|
19599
19740
|
})).filter((e) => e.updates.start !== e.element.start);
|
|
@@ -19625,14 +19766,14 @@ function commitDraggedClipMove(drag, deps) {
|
|
|
19625
19766
|
const edits = [dragEdit];
|
|
19626
19767
|
if (multi) {
|
|
19627
19768
|
for (const e of elements) {
|
|
19628
|
-
if (
|
|
19769
|
+
if (keyOf5(e) === dragKey || !multi.keys.has(keyOf5(e))) continue;
|
|
19629
19770
|
const start = multi.movedStart(e);
|
|
19630
19771
|
if (start !== e.start) edits.push({ element: e, updates: { start, track: e.track } });
|
|
19631
19772
|
}
|
|
19632
19773
|
}
|
|
19633
19774
|
const candidate = elements.map((e) => {
|
|
19634
|
-
if (
|
|
19635
|
-
if (multi?.keys.has(
|
|
19775
|
+
if (keyOf5(e) === dragKey) return { ...e, start: drag.previewStart, track: drag.previewTrack };
|
|
19776
|
+
if (multi?.keys.has(keyOf5(e))) return { ...e, start: multi.movedStart(e) };
|
|
19636
19777
|
return e;
|
|
19637
19778
|
});
|
|
19638
19779
|
const multiKeys = multi ? multi.keys : null;
|
|
@@ -19660,45 +19801,30 @@ function commitDraggedClipMove(drag, deps) {
|
|
|
19660
19801
|
).catch(() => void 0);
|
|
19661
19802
|
}
|
|
19662
19803
|
function buildTrackInsertEdits(element, previewStart, insertRow, multi, deps) {
|
|
19663
|
-
const { elements
|
|
19664
|
-
const editKey =
|
|
19665
|
-
|
|
19666
|
-
|
|
19667
|
-
const
|
|
19668
|
-
|
|
19669
|
-
if (multi?.keys.has(keyOf3(e))) return { ...e, start: multi.movedStart(e) };
|
|
19670
|
-
return e;
|
|
19671
|
-
});
|
|
19672
|
-
const writableZone = classifyZone(element);
|
|
19673
|
-
const writable = (src) => sameSourceFile(src, element) && classifyZone(src) === writableZone && src.expandedParentStart == null;
|
|
19674
|
-
const topologyOrder = [...new Set(elements.filter(writable).map((e) => e.track))].sort(
|
|
19675
|
-
(a, b) => a - b
|
|
19676
|
-
);
|
|
19677
|
-
const topologyInsertRow = topologyOrder.filter((track2) => track2 < targetTrack).length;
|
|
19678
|
-
const topologyTargetTrack = insertTrackValue(topologyOrder, topologyInsertRow);
|
|
19679
|
-
const normalized = normalizeToZones(
|
|
19680
|
-
elements.filter(writable).map((e) => {
|
|
19681
|
-
if (keyOf3(e) === editKey) {
|
|
19682
|
-
return { ...e, start: previewStart, track: topologyTargetTrack };
|
|
19683
|
-
}
|
|
19684
|
-
if (multi?.keys.has(keyOf3(e))) return { ...e, start: multi.movedStart(e) };
|
|
19685
|
-
return e;
|
|
19686
|
-
})
|
|
19687
|
-
);
|
|
19688
|
-
const bySrc = new Map(elements.map((e) => [keyOf3(e), e]));
|
|
19804
|
+
const { elements } = deps;
|
|
19805
|
+
const editKey = keyOf5(element);
|
|
19806
|
+
const layout = layoutAfterTrackInsert(element, previewStart, insertRow, multi, deps);
|
|
19807
|
+
if (!layout) return null;
|
|
19808
|
+
const { normalized, targetTrack, writable } = layout;
|
|
19809
|
+
const bySrc = new Map(elements.map((e) => [keyOf5(e), e]));
|
|
19689
19810
|
for (const norm of normalized) {
|
|
19690
|
-
const src = bySrc.get(
|
|
19811
|
+
const src = bySrc.get(keyOf5(norm));
|
|
19691
19812
|
if (src && writable(src) && !canMoveTimelineElement(src) && norm.track !== (src.authoredTrack ?? src.track)) {
|
|
19692
19813
|
console.warn(
|
|
19693
|
-
`[Timeline] Track insert refused: locked clip ${
|
|
19814
|
+
`[Timeline] Track insert refused: locked clip ${keyOf5(src)} would need renumbering`
|
|
19694
19815
|
);
|
|
19695
19816
|
return null;
|
|
19696
19817
|
}
|
|
19697
19818
|
}
|
|
19819
|
+
const candidate = elements.map((e) => {
|
|
19820
|
+
if (keyOf5(e) === editKey) return { ...e, start: previewStart, track: targetTrack };
|
|
19821
|
+
if (multi?.keys.has(keyOf5(e))) return { ...e, start: multi.movedStart(e) };
|
|
19822
|
+
return e;
|
|
19823
|
+
});
|
|
19698
19824
|
const edits = [];
|
|
19699
19825
|
if (multi) {
|
|
19700
19826
|
for (const src of elements) {
|
|
19701
|
-
const srcKey =
|
|
19827
|
+
const srcKey = keyOf5(src);
|
|
19702
19828
|
if (srcKey !== editKey && multi.keys.has(srcKey) && !writable(src) && canMoveTimelineElement(src)) {
|
|
19703
19829
|
edits.push({
|
|
19704
19830
|
element: src,
|
|
@@ -19709,15 +19835,18 @@ function buildTrackInsertEdits(element, previewStart, insertRow, multi, deps) {
|
|
|
19709
19835
|
}
|
|
19710
19836
|
}
|
|
19711
19837
|
for (const norm of normalized) {
|
|
19712
|
-
const src = bySrc.get(
|
|
19838
|
+
const src = bySrc.get(keyOf5(norm));
|
|
19713
19839
|
if (!src || !canMoveTimelineElement(src)) continue;
|
|
19714
|
-
const
|
|
19840
|
+
const normKey = keyOf5(norm);
|
|
19841
|
+
let start = src.start;
|
|
19842
|
+
if (normKey === editKey) start = previewStart;
|
|
19843
|
+
else if (multi?.keys.has(normKey)) start = multi.movedStart(src);
|
|
19715
19844
|
edits.push({ element: src, updates: { start, track: norm.track } });
|
|
19716
19845
|
}
|
|
19717
19846
|
return { candidate, edits };
|
|
19718
19847
|
}
|
|
19719
19848
|
function commitTrackInsert(drag, deps, multi) {
|
|
19720
|
-
const dragKey =
|
|
19849
|
+
const dragKey = keyOf5(drag.element);
|
|
19721
19850
|
const built = buildTrackInsertEdits(
|
|
19722
19851
|
drag.element,
|
|
19723
19852
|
drag.previewStart,
|
|
@@ -19779,7 +19908,7 @@ function syncStackingForEdit(candidate, dragKey, currentLane, aimedLane, multiKe
|
|
|
19779
19908
|
if (!readZIndex || !onStackingPatches) return Promise.resolve();
|
|
19780
19909
|
if (aimedLane === currentLane) return Promise.resolve();
|
|
19781
19910
|
const stackingEls = candidate.map((el, domIndex) => ({
|
|
19782
|
-
key:
|
|
19911
|
+
key: keyOf5(el),
|
|
19783
19912
|
start: el.start,
|
|
19784
19913
|
duration: el.duration,
|
|
19785
19914
|
track: el.track,
|
|
@@ -21721,9 +21850,10 @@ function useTimelineGeometry({
|
|
|
21721
21850
|
useEffect24(() => {
|
|
21722
21851
|
if (zoomMode !== "manual" || isDragging.current) return;
|
|
21723
21852
|
const el = scrollRef.current;
|
|
21724
|
-
|
|
21725
|
-
if (!el || target <= 0) return;
|
|
21853
|
+
if (!el) return;
|
|
21726
21854
|
const raf = requestAnimationFrame(() => {
|
|
21855
|
+
const target = lastScrollLeftRef.current;
|
|
21856
|
+
if (target <= 0) return;
|
|
21727
21857
|
const max = Math.max(0, el.scrollWidth - el.clientWidth);
|
|
21728
21858
|
const next = Math.min(target, max);
|
|
21729
21859
|
if (Math.abs(el.scrollLeft - next) > 0.5) el.scrollLeft = next;
|
|
@@ -21918,69 +22048,11 @@ function useResolvedTimelineEditCallbacks(overrides) {
|
|
|
21918
22048
|
// src/player/components/useTrackGapMenu.ts
|
|
21919
22049
|
import { useCallback as useCallback24, useEffect as useEffect27, useMemo as useMemo21, useState as useState21 } from "react";
|
|
21920
22050
|
|
|
21921
|
-
// src/player/components/timelineGaps.ts
|
|
21922
|
-
var TRACK_GAP_EPSILON_S = 1e-3;
|
|
21923
|
-
var keyOf4 = (e) => e.key ?? e.id;
|
|
21924
|
-
function laneGapFloor(elements) {
|
|
21925
|
-
return Math.max(0, ...elements.map((e) => e.expandedParentStart ?? 0));
|
|
21926
|
-
}
|
|
21927
|
-
var round32 = (v) => Math.round(v * 1e3) / 1e3;
|
|
21928
|
-
var endOf = (e) => e.start + e.duration;
|
|
21929
|
-
function sortedLaneClips(elements) {
|
|
21930
|
-
return [...elements].sort((a, b) => a.start - b.start || keyOf4(a).localeCompare(keyOf4(b)));
|
|
21931
|
-
}
|
|
21932
|
-
function resolveTrackGapAt(elements, time, epsilon = TRACK_GAP_EPSILON_S, floor = 0) {
|
|
21933
|
-
const clips = sortedLaneClips(elements);
|
|
21934
|
-
const occupied = clips.some((c) => time >= c.start - epsilon && time < endOf(c) - epsilon);
|
|
21935
|
-
if (occupied) return null;
|
|
21936
|
-
const following = clips.filter((c) => c.start > time - epsilon);
|
|
21937
|
-
if (following.length === 0) return null;
|
|
21938
|
-
const gapEnd = following[0].start;
|
|
21939
|
-
const gapStart = Math.max(
|
|
21940
|
-
floor,
|
|
21941
|
-
...clips.filter((c) => c.start <= time - epsilon).map((c) => endOf(c))
|
|
21942
|
-
);
|
|
21943
|
-
if (gapEnd - gapStart <= epsilon) return null;
|
|
21944
|
-
return { gapStart, gapEnd, followingKeys: following.map(keyOf4) };
|
|
21945
|
-
}
|
|
21946
|
-
function resolveAllGapIntervals(elements, epsilon = TRACK_GAP_EPSILON_S, floor = 0) {
|
|
21947
|
-
const gaps = [];
|
|
21948
|
-
let cursor = floor;
|
|
21949
|
-
for (const clip of sortedLaneClips(elements)) {
|
|
21950
|
-
if (clip.start - cursor > epsilon) gaps.push({ start: cursor, end: clip.start });
|
|
21951
|
-
cursor = Math.max(cursor, endOf(clip));
|
|
21952
|
-
}
|
|
21953
|
-
return gaps;
|
|
21954
|
-
}
|
|
21955
|
-
function resolveAllTrackGaps(elements, epsilon = TRACK_GAP_EPSILON_S, floor = 0) {
|
|
21956
|
-
const shifts = [];
|
|
21957
|
-
let cursor = floor;
|
|
21958
|
-
for (const clip of sortedLaneClips(elements)) {
|
|
21959
|
-
const newStart = round32(cursor);
|
|
21960
|
-
if (Math.abs(newStart - clip.start) > epsilon) {
|
|
21961
|
-
shifts.push({ key: keyOf4(clip), newStart });
|
|
21962
|
-
}
|
|
21963
|
-
cursor += clip.duration;
|
|
21964
|
-
}
|
|
21965
|
-
return shifts;
|
|
21966
|
-
}
|
|
21967
|
-
function resolveLaneEmptyIntervals(elements, end, epsilon = TRACK_GAP_EPSILON_S, floor = 0) {
|
|
21968
|
-
const gaps = resolveAllGapIntervals(elements, epsilon, floor);
|
|
21969
|
-
const maxEnd = Math.max(floor, ...elements.map(endOf));
|
|
21970
|
-
if (end - maxEnd > epsilon) gaps.push({ start: maxEnd, end });
|
|
21971
|
-
return gaps;
|
|
21972
|
-
}
|
|
21973
|
-
function resolveCloseGapShifts(elements, gap) {
|
|
21974
|
-
const width = gap.gapEnd - gap.gapStart;
|
|
21975
|
-
const followSet = new Set(gap.followingKeys);
|
|
21976
|
-
return sortedLaneClips(elements).filter((c) => followSet.has(keyOf4(c))).map((c) => ({ key: keyOf4(c), newStart: Math.max(gap.gapStart, round32(c.start - width)) }));
|
|
21977
|
-
}
|
|
21978
|
-
|
|
21979
22051
|
// src/player/components/timelineGapCommit.ts
|
|
21980
|
-
var
|
|
22052
|
+
var keyOf6 = (e) => e.key ?? e.id;
|
|
21981
22053
|
var gapCloseGestureSeq = 0;
|
|
21982
22054
|
function resolveShiftedElements(elements, shifts) {
|
|
21983
|
-
const byKey = new Map(elements.map((e) => [
|
|
22055
|
+
const byKey = new Map(elements.map((e) => [keyOf6(e), e]));
|
|
21984
22056
|
return shifts.flatMap((s) => {
|
|
21985
22057
|
const element = byKey.get(s.key);
|
|
21986
22058
|
return element ? [{ element, start: s.newStart }] : [];
|
|
@@ -22023,9 +22095,9 @@ function resolveMainTrackDeleteRippleShifts(survivingElements, deletedElements,
|
|
|
22023
22095
|
for (const survivor of survivors) {
|
|
22024
22096
|
const width = deletedMainTrack.filter((d) => d.start < survivor.start).reduce((sum, d) => sum + d.duration, 0);
|
|
22025
22097
|
if (width <= 0) continue;
|
|
22026
|
-
const newStart =
|
|
22098
|
+
const newStart = round3(Math.max(laneGapFloor(survivors), survivor.start - width));
|
|
22027
22099
|
if (Math.abs(newStart - survivor.start) > TRACK_GAP_EPSILON_S) {
|
|
22028
|
-
shifts.push({ key:
|
|
22100
|
+
shifts.push({ key: keyOf6(survivor), newStart });
|
|
22029
22101
|
}
|
|
22030
22102
|
}
|
|
22031
22103
|
if (shifts.length === 0 || !canShiftTrackGapClips(survivors, shifts)) return null;
|
|
@@ -22608,6 +22680,14 @@ function computeRevealScroll(input) {
|
|
|
22608
22680
|
};
|
|
22609
22681
|
}
|
|
22610
22682
|
|
|
22683
|
+
// src/utils/retryBudget.ts
|
|
22684
|
+
function recordRetryAttempt(ref, id, maxRetries) {
|
|
22685
|
+
const previous = ref.current;
|
|
22686
|
+
const count = previous.id === id ? previous.count + 1 : 1;
|
|
22687
|
+
ref.current = { id, count };
|
|
22688
|
+
return count <= maxRetries;
|
|
22689
|
+
}
|
|
22690
|
+
|
|
22611
22691
|
// src/player/components/useTimelineFocusCoordinator.ts
|
|
22612
22692
|
function isCurrentRequest(request, projectId, sessionEpoch) {
|
|
22613
22693
|
return request !== null && request.projectId === projectId && request.sessionEpoch === sessionEpoch;
|
|
@@ -22629,7 +22709,7 @@ function focusElement(container, targetId) {
|
|
|
22629
22709
|
});
|
|
22630
22710
|
return true;
|
|
22631
22711
|
}
|
|
22632
|
-
function scrollToTarget(container, resolution, elements, rowGeometry, pixelsPerSecond, contentOrigin, allowHorizontal) {
|
|
22712
|
+
function scrollToTarget(container, resolution, elements, rowGeometry, pixelsPerSecond, contentOrigin, allowHorizontal, lastScrollLeftRef) {
|
|
22633
22713
|
const rowIndex = rowGeometry.getRowIndex(resolution.row.physicalTrackKey);
|
|
22634
22714
|
if (rowIndex < 0) return false;
|
|
22635
22715
|
const elementId2 = resolution.target.kind === "row" ? resolution.row.elementId : resolution.target.elementId;
|
|
@@ -22651,10 +22731,15 @@ function scrollToTarget(container, resolution, elements, rowGeometry, pixelsPerS
|
|
|
22651
22731
|
stickyTop: RULER_H,
|
|
22652
22732
|
allowHorizontal: allowHorizontal && left !== null
|
|
22653
22733
|
});
|
|
22654
|
-
if (target.left !== null)
|
|
22734
|
+
if (target.left !== null) {
|
|
22735
|
+
container.scrollLeft = target.left;
|
|
22736
|
+
lastScrollLeftRef.current = target.left;
|
|
22737
|
+
}
|
|
22655
22738
|
if (target.top !== null) container.scrollTop = target.top;
|
|
22656
22739
|
return target.left !== null || target.top !== null;
|
|
22657
22740
|
}
|
|
22741
|
+
var MAX_UNRESOLVED_FOCUS_RETRIES = 5;
|
|
22742
|
+
var UNRESOLVED_FOCUS_TIMEOUT_MS = 4e3;
|
|
22658
22743
|
function useTimelineFocusCoordinator({
|
|
22659
22744
|
scrollRef,
|
|
22660
22745
|
logicalRows,
|
|
@@ -22666,12 +22751,14 @@ function useTimelineFocusCoordinator({
|
|
|
22666
22751
|
viewportVersion,
|
|
22667
22752
|
projectId,
|
|
22668
22753
|
sessionEpoch,
|
|
22669
|
-
syncScrollViewport
|
|
22754
|
+
syncScrollViewport,
|
|
22755
|
+
lastScrollLeftRef
|
|
22670
22756
|
}) {
|
|
22671
22757
|
const request = usePlayerStore((state) => state.timelineFocus);
|
|
22672
22758
|
const previousRowsRef = useRef37(logicalRows);
|
|
22673
22759
|
const resolvedRef = useRef37(null);
|
|
22674
22760
|
const appliedRef = useRef37(null);
|
|
22761
|
+
const unresolvedFocusAttemptsRef = useRef37({ id: -1, count: 0 });
|
|
22675
22762
|
const resolution = useMemo26(() => {
|
|
22676
22763
|
if (isCurrentRequest(request, projectId, sessionEpoch)) {
|
|
22677
22764
|
if (resolvedRef.current?.nonce !== request.nonce) {
|
|
@@ -22701,8 +22788,23 @@ function useTimelineFocusCoordinator({
|
|
|
22701
22788
|
useEffect29(() => {
|
|
22702
22789
|
if (!isCurrentRequest(request, projectId, sessionEpoch)) return;
|
|
22703
22790
|
if (!resolution) {
|
|
22704
|
-
|
|
22705
|
-
|
|
22791
|
+
const withinBudget = recordRetryAttempt(
|
|
22792
|
+
unresolvedFocusAttemptsRef,
|
|
22793
|
+
request.nonce,
|
|
22794
|
+
MAX_UNRESOLVED_FOCUS_RETRIES
|
|
22795
|
+
);
|
|
22796
|
+
if (!withinBudget) {
|
|
22797
|
+
usePlayerStore.getState().clearTimelineFocus(request.nonce);
|
|
22798
|
+
return;
|
|
22799
|
+
}
|
|
22800
|
+
const nonce = request.nonce;
|
|
22801
|
+
const timeout = setTimeout(() => {
|
|
22802
|
+
usePlayerStore.getState().clearTimelineFocus(nonce);
|
|
22803
|
+
}, UNRESOLVED_FOCUS_TIMEOUT_MS);
|
|
22804
|
+
return () => clearTimeout(timeout);
|
|
22805
|
+
}
|
|
22806
|
+
if (unresolvedFocusAttemptsRef.current.count !== 0) {
|
|
22807
|
+
unresolvedFocusAttemptsRef.current = { id: -1, count: 0 };
|
|
22706
22808
|
}
|
|
22707
22809
|
if (resolution.target.id !== request.id) {
|
|
22708
22810
|
usePlayerStore.getState().requestTimelineFocus(resolution.target.id);
|
|
@@ -22720,7 +22822,8 @@ function useTimelineFocusCoordinator({
|
|
|
22720
22822
|
rowGeometry,
|
|
22721
22823
|
pixelsPerSecond,
|
|
22722
22824
|
contentOrigin,
|
|
22723
|
-
allowHorizontal
|
|
22825
|
+
allowHorizontal,
|
|
22826
|
+
lastScrollLeftRef
|
|
22724
22827
|
)) {
|
|
22725
22828
|
syncScrollViewport(container);
|
|
22726
22829
|
}
|
|
@@ -22730,6 +22833,7 @@ function useTimelineFocusCoordinator({
|
|
|
22730
22833
|
allowHorizontal,
|
|
22731
22834
|
contentOrigin,
|
|
22732
22835
|
elements,
|
|
22836
|
+
lastScrollLeftRef,
|
|
22733
22837
|
pixelsPerSecond,
|
|
22734
22838
|
projectId,
|
|
22735
22839
|
request,
|
|
@@ -23037,7 +23141,8 @@ function useTimelineLogicalFocus(input) {
|
|
|
23037
23141
|
viewportVersion: input.viewport,
|
|
23038
23142
|
projectId,
|
|
23039
23143
|
sessionEpoch: input.sessionEpoch,
|
|
23040
|
-
syncScrollViewport: input.syncScrollViewport
|
|
23144
|
+
syncScrollViewport: input.syncScrollViewport,
|
|
23145
|
+
lastScrollLeftRef: input.lastScrollLeftRef
|
|
23041
23146
|
});
|
|
23042
23147
|
const rows = useTimelineRowVirtualization({
|
|
23043
23148
|
scrollRef: input.scrollRef,
|
|
@@ -38885,9 +38990,14 @@ function isResolverDisagreement(session, hfId) {
|
|
|
38885
38990
|
return false;
|
|
38886
38991
|
}
|
|
38887
38992
|
}
|
|
38888
|
-
function
|
|
38889
|
-
|
|
38890
|
-
|
|
38993
|
+
function sdkCutoverIneligibleReason(hfId, ops) {
|
|
38994
|
+
if (!hfId) return "target_unaddressable";
|
|
38995
|
+
if (ops.length === 0) return "no_ops";
|
|
38996
|
+
if (!ops.every((o) => CUTOVER_OP_TYPES.has(o.type))) return "unsupported_op_type";
|
|
38997
|
+
if (hasChildScopedOp(ops)) return "child_scoped_op";
|
|
38998
|
+
if (ops.some(mapsToReservedAttr)) return "reserved_attribute";
|
|
38999
|
+
if (hasUnsafeHtmlAttributeOp(ops)) return "unsafe_html_attribute";
|
|
39000
|
+
return null;
|
|
38891
39001
|
}
|
|
38892
39002
|
|
|
38893
39003
|
// src/utils/sdkEditTransaction.ts
|
|
@@ -39097,11 +39207,11 @@ function gsapReadSource(deps, targetPath) {
|
|
|
39097
39207
|
return read ? () => read(targetPath) : void 0;
|
|
39098
39208
|
}
|
|
39099
39209
|
async function sdkCutoverPersist(selection, ops, originalContent, targetPath, sdkSession, deps, options) {
|
|
39100
|
-
if (!
|
|
39101
|
-
return declinedCutover("ineligible_operation", "dom");
|
|
39210
|
+
if (!sdkFamilyEnabled("dom")) return declinedCutover("feature_disabled", "dom");
|
|
39102
39211
|
if (!sdkSession) return declinedCutover("session_unavailable", "dom");
|
|
39103
39212
|
const hfId = selection.hfId;
|
|
39104
|
-
|
|
39213
|
+
const ineligible = sdkCutoverIneligibleReason(hfId, ops);
|
|
39214
|
+
if (ineligible || !hfId) return declinedCutover(ineligible ?? "target_unaddressable", "dom");
|
|
39105
39215
|
const target = sdkSession.getElement(hfId);
|
|
39106
39216
|
if (!target)
|
|
39107
39217
|
return declinedCutover("target_not_found", "dom", isResolverDisagreement(sdkSession, hfId));
|
|
@@ -39676,12 +39786,12 @@ function useElementLifecycleOps({
|
|
|
39676
39786
|
import { useCallback as useCallback55, useRef as useRef66 } from "react";
|
|
39677
39787
|
|
|
39678
39788
|
// src/player/components/timelineZMirror.ts
|
|
39679
|
-
var
|
|
39789
|
+
var keyOf7 = (el) => el.key ?? el.id;
|
|
39680
39790
|
function expandedChildAllowedLanes(element, elements) {
|
|
39681
39791
|
if (element.expandedParentStart == null) return null;
|
|
39682
|
-
const selfKey =
|
|
39792
|
+
const selfKey = keyOf7(element);
|
|
39683
39793
|
return new Set(
|
|
39684
|
-
elements.filter((el) =>
|
|
39794
|
+
elements.filter((el) => keyOf7(el) !== selfKey && sameSourceFile(el, element)).map((el) => el.track)
|
|
39685
39795
|
);
|
|
39686
39796
|
}
|
|
39687
39797
|
function displayTrackOrder(elements) {
|
|
@@ -39691,12 +39801,12 @@ function resolveZMirrorLaneMove(input) {
|
|
|
39691
39801
|
const { action, element, elements } = input;
|
|
39692
39802
|
if (classifyZone(element) === "audio") return null;
|
|
39693
39803
|
if (!(element.duration > 0)) return null;
|
|
39694
|
-
const selfKey =
|
|
39804
|
+
const selfKey = keyOf7(element);
|
|
39695
39805
|
const start = element.start;
|
|
39696
39806
|
const end = element.start + element.duration;
|
|
39697
39807
|
const up = action === "bring-forward" || action === "bring-to-front";
|
|
39698
39808
|
const overlapSet = elements.filter(
|
|
39699
|
-
(el) =>
|
|
39809
|
+
(el) => keyOf7(el) !== selfKey && classifyZone(el) === "visual" && samePaintScope(el, element) && timeRangesOverlap(start, end, el.start, el.start + el.duration)
|
|
39700
39810
|
);
|
|
39701
39811
|
const referenceLane = resolveReferenceLane(input, overlapSet, up);
|
|
39702
39812
|
if (referenceLane == null) return null;
|
|
@@ -39732,13 +39842,13 @@ function resolveRepositionLaneMove(input) {
|
|
|
39732
39842
|
const { element, elements, desiredOrderKeys } = input;
|
|
39733
39843
|
if (classifyZone(element) === "audio") return null;
|
|
39734
39844
|
if (!(element.duration > 0)) return null;
|
|
39735
|
-
const selfKey =
|
|
39845
|
+
const selfKey = keyOf7(element);
|
|
39736
39846
|
const selfIdx = desiredOrderKeys.indexOf(selfKey);
|
|
39737
39847
|
if (selfIdx === -1) return null;
|
|
39738
39848
|
const clipLaneForKey = (key2) => {
|
|
39739
39849
|
if (key2 == null) return null;
|
|
39740
|
-
const el = elements.find((candidate) =>
|
|
39741
|
-
return el && classifyZone(el) === "visual" && el.duration > 0 && samePaintScope(el, element) &&
|
|
39850
|
+
const el = elements.find((candidate) => keyOf7(candidate) === key2);
|
|
39851
|
+
return el && classifyZone(el) === "visual" && el.duration > 0 && samePaintScope(el, element) && keyOf7(el) !== selfKey ? el.track : null;
|
|
39742
39852
|
};
|
|
39743
39853
|
let aboveLane = null;
|
|
39744
39854
|
for (let i = selfIdx + 1; i < desiredOrderKeys.length && aboveLane == null; i++) {
|
|
@@ -39817,7 +39927,7 @@ function resolveReferenceLane(input, overlapSet, up) {
|
|
|
39817
39927
|
}
|
|
39818
39928
|
function crossedNeighborLane({ elements, crossedKey }) {
|
|
39819
39929
|
if (crossedKey == null) return null;
|
|
39820
|
-
const crossed = elements.find((el) =>
|
|
39930
|
+
const crossed = elements.find((el) => keyOf7(el) === crossedKey);
|
|
39821
39931
|
return crossed && classifyZone(crossed) === "visual" ? crossed.track : null;
|
|
39822
39932
|
}
|
|
39823
39933
|
|
|
@@ -41789,6 +41899,7 @@ var CaptionTimeline = memo27(function CaptionTimeline2({
|
|
|
41789
41899
|
|
|
41790
41900
|
// src/hooks/useTimelineSelectionPreviewSync.ts
|
|
41791
41901
|
import { useEffect as useEffect49, useMemo as useMemo36, useRef as useRef68 } from "react";
|
|
41902
|
+
var MAX_UNRESOLVED_SYNC_RETRIES = 3;
|
|
41792
41903
|
function orderSelectedIds(ids, anchor2) {
|
|
41793
41904
|
const ordered = [...ids];
|
|
41794
41905
|
if (!anchor2 || !ids.has(anchor2)) return ordered;
|
|
@@ -41806,6 +41917,22 @@ function selectionIdsMatch(currentIds, selectedIds, currentAnchor, wantedAnchor)
|
|
|
41806
41917
|
function anchorIsOutsideSelection(anchor2, selectedIds) {
|
|
41807
41918
|
return anchor2 !== null && !selectedIds.includes(anchor2);
|
|
41808
41919
|
}
|
|
41920
|
+
async function resolveSelectionsForIds(ids, timelineElements, buildDomSelectionForTimelineElement) {
|
|
41921
|
+
const elements = ids.map((id) => timelineElements.find((item) => (item.key ?? item.id) === id)).filter((element) => Boolean(element));
|
|
41922
|
+
const resolved2 = await Promise.all(
|
|
41923
|
+
elements.map((element) => buildDomSelectionForTimelineElement(element))
|
|
41924
|
+
);
|
|
41925
|
+
return resolved2.filter((selection) => Boolean(selection));
|
|
41926
|
+
}
|
|
41927
|
+
function applyResolvedSelections(selections, applyDomSelection, applyMarqueeSelection) {
|
|
41928
|
+
if (selections.length === 0) {
|
|
41929
|
+
applyDomSelection(null, { revealPanel: false });
|
|
41930
|
+
} else if (selections.length === 1) {
|
|
41931
|
+
applyDomSelection(selections[0]);
|
|
41932
|
+
} else {
|
|
41933
|
+
applyMarqueeSelection(selections, false);
|
|
41934
|
+
}
|
|
41935
|
+
}
|
|
41809
41936
|
function useTimelineSelectionPreviewSync({
|
|
41810
41937
|
selectedElementId,
|
|
41811
41938
|
selectedElementIds,
|
|
@@ -41827,6 +41954,7 @@ function useTimelineSelectionPreviewSync({
|
|
|
41827
41954
|
const domEditGroupSelectionsRef = useRef68(domEditGroupSelections);
|
|
41828
41955
|
const lastSyncedSelectedKeyRef = useRef68("");
|
|
41829
41956
|
const missingSelectionKeyRef = useRef68("");
|
|
41957
|
+
const unresolvedAttemptsRef = useRef68({ id: "", count: 0 });
|
|
41830
41958
|
domEditSelectionRef.current = domEditSelection;
|
|
41831
41959
|
domEditGroupSelectionsRef.current = domEditGroupSelections;
|
|
41832
41960
|
useEffect49(() => {
|
|
@@ -41841,6 +41969,7 @@ function useTimelineSelectionPreviewSync({
|
|
|
41841
41969
|
const currentAnchor = currentDomEditSelection ? resolveTimelineIdForSelection(currentDomEditSelection, timelineElements, activeCompPath) : null;
|
|
41842
41970
|
if (selectedIds.length === 0) {
|
|
41843
41971
|
missingSelectionKeyRef.current = "";
|
|
41972
|
+
unresolvedAttemptsRef.current = { id: "", count: 0 };
|
|
41844
41973
|
logSelect("timeline-empty", {
|
|
41845
41974
|
had: currentIds.length,
|
|
41846
41975
|
previousKey: previousSelectedKey.length > 0,
|
|
@@ -41862,36 +41991,30 @@ function useTimelineSelectionPreviewSync({
|
|
|
41862
41991
|
onSelectionNotFound();
|
|
41863
41992
|
};
|
|
41864
41993
|
const syncSelection = async () => {
|
|
41865
|
-
const selections =
|
|
41866
|
-
|
|
41867
|
-
|
|
41868
|
-
|
|
41869
|
-
|
|
41870
|
-
resolvableCount += 1;
|
|
41871
|
-
const selection = await buildDomSelectionForTimelineElement(element);
|
|
41872
|
-
if (selection) selections.push(selection);
|
|
41873
|
-
}
|
|
41994
|
+
const selections = await resolveSelectionsForIds(
|
|
41995
|
+
selectedIds,
|
|
41996
|
+
timelineElements,
|
|
41997
|
+
buildDomSelectionForTimelineElement
|
|
41998
|
+
);
|
|
41874
41999
|
if (cancelled) return;
|
|
41875
|
-
if (selections.length <
|
|
41876
|
-
|
|
41877
|
-
|
|
41878
|
-
|
|
42000
|
+
if (selections.length < selectedIds.length) {
|
|
42001
|
+
if (recordRetryAttempt(unresolvedAttemptsRef, selectedKey, MAX_UNRESOLVED_SYNC_RETRIES)) {
|
|
42002
|
+
if (anchorIsOutsideSelection(currentAnchor, selectedIds)) {
|
|
42003
|
+
applyDomSelection(null, { revealPanel: false, announce: false });
|
|
42004
|
+
}
|
|
42005
|
+
return;
|
|
41879
42006
|
}
|
|
41880
|
-
|
|
42007
|
+
warnSelectionMissingOnce();
|
|
42008
|
+
} else {
|
|
42009
|
+
unresolvedAttemptsRef.current = { id: "", count: 0 };
|
|
42010
|
+
missingSelectionKeyRef.current = "";
|
|
41881
42011
|
}
|
|
41882
|
-
missingSelectionKeyRef.current = "";
|
|
41883
42012
|
logSelect("timeline-sync", {
|
|
41884
42013
|
wanted: selectedIds.length,
|
|
41885
42014
|
had: currentIds.length,
|
|
41886
42015
|
resolved: selections.length
|
|
41887
42016
|
});
|
|
41888
|
-
|
|
41889
|
-
applyDomSelection(null, { revealPanel: false });
|
|
41890
|
-
} else if (selections.length === 1) {
|
|
41891
|
-
applyDomSelection(selections[0]);
|
|
41892
|
-
} else {
|
|
41893
|
-
applyMarqueeSelection(selections, false);
|
|
41894
|
-
}
|
|
42017
|
+
applyResolvedSelections(selections, applyDomSelection, applyMarqueeSelection);
|
|
41895
42018
|
};
|
|
41896
42019
|
void syncSelection();
|
|
41897
42020
|
return () => {
|
|
@@ -66615,7 +66738,7 @@ async function commitTimelineCompositionInsertion(input) {
|
|
|
66615
66738
|
await input.writeFile(input.targetPath, result.before, result.after);
|
|
66616
66739
|
throw error;
|
|
66617
66740
|
}
|
|
66618
|
-
input.selectHost(
|
|
66741
|
+
input.selectHost(deriveTimelineStoreKeyForDomId(result.hostId, input.targetPath));
|
|
66619
66742
|
try {
|
|
66620
66743
|
input.resync?.();
|
|
66621
66744
|
} catch (error) {
|
|
@@ -66629,6 +66752,13 @@ async function commitTimelineCompositionInsertion(input) {
|
|
|
66629
66752
|
});
|
|
66630
66753
|
}
|
|
66631
66754
|
|
|
66755
|
+
// src/player/components/timelineDropReveal.ts
|
|
66756
|
+
function selectAndRevealTimelineElement(key2) {
|
|
66757
|
+
const store = usePlayerStore.getState();
|
|
66758
|
+
store.setSelectedElementId(key2);
|
|
66759
|
+
store.requestTimelineFocus(timelineClipFocusId(key2));
|
|
66760
|
+
}
|
|
66761
|
+
|
|
66632
66762
|
// src/hooks/useTimelineAssetDropOps.ts
|
|
66633
66763
|
function useTimelineAssetDropOps({
|
|
66634
66764
|
projectIdRef,
|
|
@@ -66699,6 +66829,7 @@ function useTimelineAssetDropOps({
|
|
|
66699
66829
|
writeFile: writeProjectFile,
|
|
66700
66830
|
recordEdit
|
|
66701
66831
|
});
|
|
66832
|
+
selectAndRevealTimelineElement(deriveTimelineStoreKeyForDomId(newId, targetPath));
|
|
66702
66833
|
forceReloadSdkSession?.();
|
|
66703
66834
|
reloadPreview();
|
|
66704
66835
|
} catch (error) {
|
|
@@ -66768,7 +66899,7 @@ function useTimelineAssetDropOps({
|
|
|
66768
66899
|
writeFile: writeProjectFile,
|
|
66769
66900
|
recordEdit,
|
|
66770
66901
|
observeVersion: observeProjectFileVersion,
|
|
66771
|
-
selectHost:
|
|
66902
|
+
selectHost: selectAndRevealTimelineElement,
|
|
66772
66903
|
resync: forceReloadSdkSession,
|
|
66773
66904
|
refresh: reloadPreview
|
|
66774
66905
|
});
|
|
@@ -75724,8 +75855,9 @@ async function addBlockToProject(opts) {
|
|
|
75724
75855
|
currentTime: opts.currentTime ?? 0
|
|
75725
75856
|
});
|
|
75726
75857
|
const { width, height } = resolveTimelineAssetCompositionSize(originalContent);
|
|
75858
|
+
const hostId = buildUniqueCompositionId(block.name, collectHtmlIds(originalContent));
|
|
75727
75859
|
const subComposition = buildSubCompositionHtml({
|
|
75728
|
-
id:
|
|
75860
|
+
id: hostId,
|
|
75729
75861
|
compositionFile,
|
|
75730
75862
|
start,
|
|
75731
75863
|
duration,
|
|
@@ -75751,7 +75883,11 @@ async function addBlockToProject(opts) {
|
|
|
75751
75883
|
});
|
|
75752
75884
|
await refreshFileTree();
|
|
75753
75885
|
reloadPreview();
|
|
75754
|
-
return {
|
|
75886
|
+
return {
|
|
75887
|
+
block,
|
|
75888
|
+
compositionPath: compositionFile,
|
|
75889
|
+
hostKey: deriveTimelineStoreKeyForDomId(hostId, targetPath)
|
|
75890
|
+
};
|
|
75755
75891
|
} catch (error) {
|
|
75756
75892
|
const message = error instanceof Error ? error.message : "Failed to add block";
|
|
75757
75893
|
showToast(message);
|
|
@@ -75851,7 +75987,9 @@ function useBlockHandlers({
|
|
|
75851
75987
|
previewIframe: previewIframeRef.current,
|
|
75852
75988
|
currentTime: usePlayerStore.getState().currentTime
|
|
75853
75989
|
})
|
|
75854
|
-
)
|
|
75990
|
+
).then((result) => {
|
|
75991
|
+
if (result) selectAndRevealTimelineElement(result.hostKey);
|
|
75992
|
+
});
|
|
75855
75993
|
},
|
|
75856
75994
|
[projectId, blockCtx, previewIframeRef, runBlockInstall]
|
|
75857
75995
|
);
|
|
@@ -75887,7 +76025,9 @@ function useBlockHandlers({
|
|
|
75887
76025
|
previewIframe: previewIframeRef.current,
|
|
75888
76026
|
currentTime: usePlayerStore.getState().currentTime
|
|
75889
76027
|
})
|
|
75890
|
-
)
|
|
76028
|
+
).then((result) => {
|
|
76029
|
+
if (result) selectAndRevealTimelineElement(result.hostKey);
|
|
76030
|
+
});
|
|
75891
76031
|
},
|
|
75892
76032
|
[projectId, blockCtx, previewIframeRef, runBlockInstall]
|
|
75893
76033
|
);
|