@remotion/studio 4.0.479 → 4.0.482

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 (75) hide show
  1. package/dist/components/AudioWaveform.js +19 -11
  2. package/dist/components/Button.d.ts +1 -0
  3. package/dist/components/Button.js +2 -2
  4. package/dist/components/CurrentCompositionSideEffects.d.ts +0 -3
  5. package/dist/components/CurrentCompositionSideEffects.js +1 -37
  6. package/dist/components/Editor.js +2 -5
  7. package/dist/components/EditorContent.js +2 -1
  8. package/dist/components/ExpandedTracksProvider.d.ts +1 -0
  9. package/dist/components/ExpandedTracksProvider.js +81 -7
  10. package/dist/components/GlobalKeybindings.d.ts +3 -1
  11. package/dist/components/GlobalKeybindings.js +104 -10
  12. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +7 -5
  13. package/dist/components/InspectorPanel/inspector-selection.d.ts +3 -3
  14. package/dist/components/InspectorPanel/inspector-selection.js +7 -6
  15. package/dist/components/InspectorPanel/styles.d.ts +1 -0
  16. package/dist/components/InspectorPanel/styles.js +19 -1
  17. package/dist/components/InspectorPanel.js +3 -3
  18. package/dist/components/InspectorSequenceSection.d.ts +3 -0
  19. package/dist/components/InspectorSequenceSection.js +12 -2
  20. package/dist/components/KeyboardShortcutsExplainer.js +10 -2
  21. package/dist/components/MediaVolumeProvider.js +4 -4
  22. package/dist/components/Modals.js +2 -1
  23. package/dist/components/NewComposition/CodemodFooter.d.ts +1 -0
  24. package/dist/components/NewComposition/CodemodFooter.js +25 -3
  25. package/dist/components/NewComposition/InputDragger.d.ts +4 -0
  26. package/dist/components/NewComposition/InputDragger.js +18 -2
  27. package/dist/components/NewComposition/NewComposition.d.ts +2 -0
  28. package/dist/components/NewComposition/NewComposition.js +178 -0
  29. package/dist/components/PreviewToolbar.js +3 -3
  30. package/dist/components/ResetZoomButton.d.ts +2 -1
  31. package/dist/components/ResetZoomButton.js +5 -1
  32. package/dist/components/SelectedOutlineElement.js +39 -0
  33. package/dist/components/SelectedOutlineOverlay.d.ts +6 -0
  34. package/dist/components/SelectedOutlineOverlay.js +21 -3
  35. package/dist/components/Timeline/Timeline.js +9 -9
  36. package/dist/components/Timeline/TimelineEffectItem.js +1 -1
  37. package/dist/components/Timeline/TimelineEffectPropItem.js +1 -1
  38. package/dist/components/Timeline/TimelineExpandArrowButton.js +42 -2
  39. package/dist/components/Timeline/TimelineExpandedRow.js +2 -2
  40. package/dist/components/Timeline/TimelineExpandedSection.js +8 -9
  41. package/dist/components/Timeline/TimelineRowChrome.d.ts +2 -0
  42. package/dist/components/Timeline/TimelineRowChrome.js +5 -3
  43. package/dist/components/Timeline/TimelineSelection.d.ts +26 -3
  44. package/dist/components/Timeline/TimelineSelection.js +322 -91
  45. package/dist/components/Timeline/TimelineSequenceItem.js +62 -5
  46. package/dist/components/Timeline/TimelineSequencePropItem.js +1 -1
  47. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +6 -4
  48. package/dist/components/Timeline/find-track-for-node-path-info.js +2 -2
  49. package/dist/components/Timeline/get-node-keyframes.d.ts +7 -0
  50. package/dist/components/Timeline/get-node-keyframes.js +26 -1
  51. package/dist/components/Timeline/reset-selected-timeline-props.js +15 -2
  52. package/dist/components/Timeline/timeline-expanded-filter.d.ts +12 -0
  53. package/dist/components/Timeline/timeline-expanded-filter.js +38 -0
  54. package/dist/components/Timeline/timeline-field-display-utils.js +3 -0
  55. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +50 -18
  56. package/dist/components/Timeline/use-timeline-expanded-tree.d.ts +1 -0
  57. package/dist/components/Timeline/use-timeline-expanded-tree.js +27 -0
  58. package/dist/components/Timeline/use-timeline-height.js +51 -7
  59. package/dist/components/Timeline/use-timeline-keyframe-drag.js +12 -6
  60. package/dist/components/TopPanel.js +1 -1
  61. package/dist/components/composition-menu-items.js +17 -0
  62. package/dist/components/selected-outline-measurement.js +48 -14
  63. package/dist/error-overlay/remotion-overlay/ErrorLoader.js +8 -1
  64. package/dist/esm/{chunk-fge2mq5p.js → chunk-nkqfa5bw.js} +17611 -16502
  65. package/dist/esm/internals.mjs +17611 -16502
  66. package/dist/esm/previewEntry.mjs +5179 -4068
  67. package/dist/esm/renderEntry.mjs +1 -1
  68. package/dist/helpers/calculate-timeline.js +6 -2
  69. package/dist/helpers/get-sequence-visible-range.d.ts +1 -0
  70. package/dist/helpers/get-sequence-visible-range.js +15 -1
  71. package/dist/helpers/migrate-expanded-tracks-for-subscription-key.js +3 -3
  72. package/dist/state/modals.d.ts +2 -0
  73. package/package.json +11 -11
  74. package/dist/components/Timeline/TimelineItemStack.d.ts +0 -5
  75. package/dist/components/Timeline/TimelineItemStack.js +0 -29
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useTimelineRowContainsSelection = exports.useTimelineGuideSelection = exports.useTimelineEasingSelection = exports.useTimelineKeyframeSelection = exports.useTimelineRowSelection = exports.useTimelineMarqueeSelectableItem = exports.useTimelineMarqueeSelection = exports.useCurrentTimelineSelectionStateAsRef = exports.TIMELINE_SCRUBBER_ATTR = exports.TIMELINE_MARQUEE_ITEM_ATTR = exports.useTimelineSelection = exports.TimelineSelectionProvider = exports.TimelineSelectAllKeybindings = exports.getTimelineSequenceSelectionKey = exports.getSelectableTimelineSequenceSelections = exports.getTimelineSelectionKey = exports.getTimelineSelectionFromNodePathInfo = exports.getTimelineMarqueeSelection = exports.timelineMarqueeRectsIntersect = exports.getClampedTimelineMarqueePoint = exports.getNormalizedTimelineMarqueeRect = exports.getAvailableTimelineSelectionState = exports.getTimelineSelectionAfterInteraction = exports.EMPTY_TIMELINE_SELECTION_STATE = exports.shouldSelectTimelineRowOnPointerDown = exports.isTimelineSelectionModifierEvent = exports.TIMELINE_TICKS_BACKGROUND = exports.TIMELINE_BACKGROUND = exports.getTimelineSelectedTrackHighlightStyle = exports.getTimelineColor = exports.getTimelineSelectedLabelStyle = exports.TIMELINE_SELECTED_LABEL_HORIZONTAL_PADDING = exports.TIMELINE_SELECTED_LABEL_TEXT = exports.TIMELINE_SELECTED_LABEL_BACKGROUND = exports.TIMELINE_SELECTED_BACKGROUND = void 0;
3
+ exports.useTimelineRowContainsSelection = exports.useTimelineGuideSelection = exports.useTimelineEasingSelection = exports.useTimelineKeyframeSelection = exports.useTimelineRowSelection = exports.useTimelineFocusableItem = exports.useTimelineMarqueeSelectableItem = exports.useTimelineMarqueeSelection = exports.useCurrentTimelineSelectionStateAsRef = exports.TIMELINE_SCRUBBER_ATTR = exports.TIMELINE_MARQUEE_ITEM_ATTR = exports.useTimelineSelection = exports.TimelineSelectionProvider = exports.TimelineSelectableItemsProvider = exports.TimelineSelectAllKeybindings = exports.getTimelineSequenceSelectionKey = exports.getSelectableTimelineItems = exports.getSelectableTimelineSequenceSelections = exports.getTimelineSelectionKey = exports.getTimelineSelectionFromNodePathInfo = exports.TimelineSelectionOrderProvider = exports.getTimelineMarqueeSelection = exports.timelineMarqueeRectsIntersect = exports.getClampedTimelineMarqueePoint = exports.getNormalizedTimelineMarqueeRect = exports.getAvailableTimelineSelectionState = exports.getTimelineSelectionAfterInteraction = exports.EMPTY_TIMELINE_SELECTION_STATE = exports.shouldSelectTimelineRowOnPointerDown = exports.isTimelineSelectionModifierEvent = exports.TIMELINE_TICKS_BACKGROUND = exports.TIMELINE_BACKGROUND = exports.getTimelineSelectedTrackHighlightStyle = exports.getTimelineColor = exports.getTimelineSelectedLabelStyle = exports.TIMELINE_SELECTED_LABEL_HORIZONTAL_PADDING = exports.TIMELINE_SELECTED_LABEL_TEXT = exports.TIMELINE_SELECTED_LABEL_BACKGROUND = exports.TIMELINE_SELECTED_BACKGROUND = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const studio_shared_1 = require("@remotion/studio-shared");
6
6
  const react_1 = require("react");
@@ -11,6 +11,11 @@ const timeline_layout_1 = require("../../helpers/timeline-layout");
11
11
  const timeline_node_path_key_1 = require("../../helpers/timeline-node-path-key");
12
12
  const use_keybinding_1 = require("../../helpers/use-keybinding");
13
13
  const z_index_1 = require("../../state/z-index");
14
+ const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
15
+ const get_node_keyframes_1 = require("./get-node-keyframes");
16
+ const get_timeline_easing_segments_1 = require("./get-timeline-easing-segments");
17
+ const timeline_expanded_filter_1 = require("./timeline-expanded-filter");
18
+ const timeline_refs_1 = require("./timeline-refs");
14
19
  const TimelineClipboardKeybindings_1 = require("./TimelineClipboardKeybindings");
15
20
  const TimelineDeleteKeybindings_1 = require("./TimelineDeleteKeybindings");
16
21
  exports.TIMELINE_SELECTED_BACKGROUND = '#3B3F42';
@@ -242,8 +247,8 @@ const defaultTimelineSelectionContextValue = {
242
247
  isSelected: () => false,
243
248
  selectItem: () => undefined,
244
249
  selectItems: () => undefined,
245
- registerSelectableItem: () => () => undefined,
246
250
  registerMarqueeSelectableItem: () => () => undefined,
251
+ registerFocusableItem: () => () => undefined,
247
252
  getMarqueeSelection: () => ({
248
253
  lockedSelectionKind: null,
249
254
  selectedItems: [],
@@ -252,7 +257,16 @@ const defaultTimelineSelectionContextValue = {
252
257
  clearSelection: () => undefined,
253
258
  };
254
259
  const TimelineSelectionContext = (0, react_1.createContext)(defaultTimelineSelectionContextValue);
260
+ const EMPTY_SELECTABLE_TIMELINE_ITEMS = [];
261
+ const SelectableTimelineItemsContext = (0, react_1.createContext)({ current: EMPTY_SELECTABLE_TIMELINE_ITEMS });
262
+ const TimelineSelectionOrderProvider = ({ children, items }) => {
263
+ const itemsRef = (0, react_1.useRef)(items);
264
+ itemsRef.current = items;
265
+ return (jsx_runtime_1.jsx(SelectableTimelineItemsContext.Provider, { value: itemsRef, children: children }));
266
+ };
267
+ exports.TimelineSelectionOrderProvider = TimelineSelectionOrderProvider;
255
268
  const CurrentTimelineSelectionContext = (0, react_1.createContext)(null);
269
+ const TIMELINE_SELECTION_REVEAL_RETRY_COUNT = 2;
256
270
  const parseEffectIndex = (effectIndex) => {
257
271
  const parsed = Number(effectIndex);
258
272
  if (!Number.isInteger(parsed) || parsed < 0) {
@@ -341,6 +355,108 @@ const getSelectableTimelineSequenceSelections = (tracks) => {
341
355
  });
342
356
  };
343
357
  exports.getSelectableTimelineSequenceSelections = getSelectableTimelineSequenceSelections;
358
+ const canEditEasingForInterpolationFunction = (interpolationFunction) => interpolationFunction === 'interpolate' ||
359
+ interpolationFunction === 'interpolateColors';
360
+ const getTimelineTreeNodeCanEditEasing = ({ node, nodePathInfo, propStatuses, }) => {
361
+ var _a;
362
+ if (node.kind !== 'field' || node.field === null) {
363
+ return false;
364
+ }
365
+ if (node.field.kind === 'sequence-field') {
366
+ const sequencePropStatus = (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePathInfo.sequenceSubscriptionKey)) === null || _a === void 0 ? void 0 : _a[node.field.key];
367
+ return ((sequencePropStatus === null || sequencePropStatus === void 0 ? void 0 : sequencePropStatus.status) === 'keyframed' &&
368
+ canEditEasingForInterpolationFunction(sequencePropStatus.interpolationFunction));
369
+ }
370
+ const effectStatus = remotion_1.Internals.getEffectPropStatusesCtx({
371
+ propStatuses,
372
+ nodePath: nodePathInfo.sequenceSubscriptionKey,
373
+ effectIndex: node.field.effectIndex,
374
+ });
375
+ const effectPropStatus = effectStatus.type === 'can-update-effect'
376
+ ? effectStatus.props[node.field.key]
377
+ : null;
378
+ return ((effectPropStatus === null || effectPropStatus === void 0 ? void 0 : effectPropStatus.status) === 'keyframed' &&
379
+ canEditEasingForInterpolationFunction(effectPropStatus.interpolationFunction));
380
+ };
381
+ const getSelectableTimelineItems = ({ getDragOverrides, getEffectDragOverrides, getIsExpanded, propStatuses, selectedItems, timeline, timelinePosition, }) => {
382
+ const selectedRowKeys = (0, timeline_expanded_filter_1.getSelectedTimelineExpandedRowKeys)(selectedItems);
383
+ return timeline.flatMap((track) => {
384
+ const { nodePathInfo } = track;
385
+ if (nodePathInfo === null) {
386
+ return [];
387
+ }
388
+ const sequenceSelection = (0, exports.getTimelineSelectionFromNodePathInfo)(nodePathInfo);
389
+ if (sequenceSelection === null) {
390
+ return [];
391
+ }
392
+ if (!getIsExpanded(nodePathInfo)) {
393
+ return [sequenceSelection];
394
+ }
395
+ const tree = (0, timeline_layout_1.buildTimelineTree)({
396
+ sequence: track.sequence,
397
+ nodePathInfo,
398
+ getDragOverrides,
399
+ getEffectDragOverrides,
400
+ propStatuses,
401
+ });
402
+ const filteredTree = (0, timeline_expanded_filter_1.filterTimelineExpandedTree)({
403
+ nodes: tree,
404
+ shouldShowNode: (node) => (0, timeline_expanded_filter_1.isTimelineExpandedNodeSelected)({
405
+ nodePathInfo: node.nodePathInfo,
406
+ selectedRowKeys,
407
+ }) ||
408
+ (0, get_node_keyframes_1.getNodeHasKeyframes)({
409
+ node,
410
+ nodePath: nodePathInfo.sequenceSubscriptionKey,
411
+ propStatuses,
412
+ getDragOverrides,
413
+ getEffectDragOverrides,
414
+ }),
415
+ });
416
+ const visibleTreeRows = (0, timeline_layout_1.flattenVisibleTreeNodes)({
417
+ nodes: filteredTree,
418
+ getIsExpanded,
419
+ });
420
+ return [
421
+ sequenceSelection,
422
+ ...visibleTreeRows.flatMap(({ node }) => {
423
+ const rowSelection = (0, exports.getTimelineSelectionFromNodePathInfo)(node.nodePathInfo);
424
+ if (rowSelection === null) {
425
+ return [];
426
+ }
427
+ const keyframes = (0, get_node_keyframes_1.getNodeKeyframes)({
428
+ node,
429
+ nodePath: nodePathInfo.sequenceSubscriptionKey,
430
+ propStatuses,
431
+ keyframeDisplayOffset: track.keyframeDisplayOffset,
432
+ getDragOverrides,
433
+ getEffectDragOverrides,
434
+ timelinePosition,
435
+ });
436
+ const keyframeSelections = keyframes.map((keyframe) => ({
437
+ type: 'keyframe',
438
+ nodePathInfo: node.nodePathInfo,
439
+ frame: keyframe.frame,
440
+ }));
441
+ const easingSelections = getTimelineTreeNodeCanEditEasing({
442
+ node,
443
+ nodePathInfo,
444
+ propStatuses,
445
+ })
446
+ ? (0, get_timeline_easing_segments_1.getTimelineEasingSegments)(keyframes).map((segment) => ({
447
+ type: 'easing',
448
+ nodePathInfo: node.nodePathInfo,
449
+ fromFrame: segment.fromFrame,
450
+ toFrame: segment.toFrame,
451
+ segmentIndex: segment.segmentIndex,
452
+ }))
453
+ : [];
454
+ return [rowSelection, ...easingSelections, ...keyframeSelections];
455
+ }),
456
+ ];
457
+ });
458
+ };
459
+ exports.getSelectableTimelineItems = getSelectableTimelineItems;
344
460
  const getTimelineSequenceSelectionKey = (nodePathInfo) => (0, timeline_node_path_key_1.timelineNodePathInfoToKey)({ ...nodePathInfo, auxiliaryKeys: [] });
345
461
  exports.getTimelineSequenceSelectionKey = getTimelineSequenceSelectionKey;
346
462
  const TimelineSelectAllKeybindings = ({ timeline }) => {
@@ -376,29 +492,78 @@ const TimelineSelectAllKeybindings = ({ timeline }) => {
376
492
  return null;
377
493
  };
378
494
  exports.TimelineSelectAllKeybindings = TimelineSelectAllKeybindings;
495
+ const TimelineEscapeKeybindings = () => {
496
+ const keybindings = (0, use_keybinding_1.useKeybinding)();
497
+ const currentSelection = (0, exports.useCurrentTimelineSelectionStateAsRef)();
498
+ (0, react_1.useEffect)(() => {
499
+ const escape = keybindings.registerKeybinding({
500
+ event: 'keydown',
501
+ key: 'Escape',
502
+ callback: (event) => {
503
+ const { selectedItems, clearSelection } = currentSelection.current;
504
+ if (selectedItems.length === 0) {
505
+ return;
506
+ }
507
+ clearSelection();
508
+ event.preventDefault();
509
+ },
510
+ commandCtrlKey: false,
511
+ preventDefault: false,
512
+ triggerIfInputFieldFocused: false,
513
+ keepRegisteredWhenNotHighestContext: false,
514
+ });
515
+ return () => {
516
+ escape.unregister();
517
+ };
518
+ }, [currentSelection, keybindings]);
519
+ return null;
520
+ };
521
+ const TimelineSelectableItemsProvider = ({ children, timeline }) => {
522
+ const { getIsExpanded } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksGetterContext);
523
+ const { propStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
524
+ const { getDragOverrides, getEffectDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
525
+ const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
526
+ const { selectedItems } = (0, exports.useTimelineSelection)();
527
+ const selectableItems = (0, react_1.useMemo)(() => (0, exports.getSelectableTimelineItems)({
528
+ getDragOverrides,
529
+ getEffectDragOverrides,
530
+ getIsExpanded,
531
+ propStatuses,
532
+ selectedItems,
533
+ timeline,
534
+ timelinePosition,
535
+ }), [
536
+ getDragOverrides,
537
+ getEffectDragOverrides,
538
+ getIsExpanded,
539
+ propStatuses,
540
+ selectedItems,
541
+ timeline,
542
+ timelinePosition,
543
+ ]);
544
+ return (jsx_runtime_1.jsx(exports.TimelineSelectionOrderProvider, { items: selectableItems, children: children }));
545
+ };
546
+ exports.TimelineSelectableItemsProvider = TimelineSelectableItemsProvider;
379
547
  const TimelineSelectionProvider = ({ children }) => {
380
548
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
381
549
  const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
382
550
  const timelineSelectionScope = (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition' ? canvasContent.compositionId : null;
551
+ const { expandParentTracks } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksSetterContext);
383
552
  const canSelect = previewServerState.type === 'connected' &&
384
553
  !window.remotion_isReadOnlyStudio;
385
554
  const [selectedItems, setSelectedItems] = (0, react_1.useState)([]);
386
555
  const selectionAnchor = (0, react_1.useRef)(null);
387
556
  const selectionScope = (0, react_1.useRef)(null);
388
- const selectableItemsOrder = (0, react_1.useRef)(new Map());
389
- const selectableItems = (0, react_1.useRef)(new Map());
390
- const selectableItemRegistrationCounts = (0, react_1.useRef)(new Map());
391
557
  const marqueeSelectableItems = (0, react_1.useRef)(new Map());
392
- const registrationCounter = (0, react_1.useRef)(0);
393
558
  const marqueeRegistrationCounter = (0, react_1.useRef)(0);
394
- const [selectableItemsVersion, setSelectableItemsVersion] = (0, react_1.useState)(0);
395
- const bumpSelectableItemsVersion = (0, react_1.useCallback)(() => {
396
- setSelectableItemsVersion((version) => version + 1);
397
- }, []);
559
+ const focusableItems = (0, react_1.useRef)(new Map());
560
+ const focusableRegistrationCounter = (0, react_1.useRef)(0);
561
+ const [revealRequest, setRevealRequest] = (0, react_1.useState)(null);
398
562
  (0, react_1.useEffect)(() => {
399
563
  if (!canSelect) {
400
564
  selectionScope.current = null;
401
565
  selectionAnchor.current = null;
566
+ setRevealRequest(null);
402
567
  setSelectedItems([]);
403
568
  }
404
569
  }, [canSelect]);
@@ -407,28 +572,90 @@ const TimelineSelectionProvider = ({ children }) => {
407
572
  if (selectionScope.current !== timelineSelectionScope) {
408
573
  return exports.EMPTY_TIMELINE_SELECTION_STATE;
409
574
  }
410
- return (0, exports.getAvailableTimelineSelectionState)({
411
- availableKeys: new Set(selectableItems.current.keys()),
412
- availableItemsByKey: selectableItems.current,
413
- state: {
414
- selectedItems: currentSelectedItems,
415
- anchor: selectionAnchor.current,
416
- },
417
- });
575
+ return {
576
+ selectedItems: currentSelectedItems,
577
+ anchor: selectionAnchor.current,
578
+ };
418
579
  }, [timelineSelectionScope]);
419
580
  const availableSelectionState = getCurrentAvailableSelectionState(selectedItems);
420
581
  const availableSelectedItems = availableSelectionState.selectedItems;
582
+ const revealSelectionKey = (0, react_1.useCallback)((selectedKey) => {
583
+ let cancelled = false;
584
+ let animationFrame = null;
585
+ const reveal = (attempt) => {
586
+ var _a;
587
+ var _b;
588
+ if (cancelled) {
589
+ return;
590
+ }
591
+ const scrollParent = timeline_refs_1.timelineVerticalScroll.current;
592
+ const focusableRegistrations = focusableItems.current.get(selectedKey);
593
+ const focusableElement = scrollParent && focusableRegistrations
594
+ ? [...focusableRegistrations.values()]
595
+ .sort((a, b) => a.order - b.order)
596
+ .map((registered) => registered.getElement())
597
+ .find((element) => element !== null && scrollParent.contains(element))
598
+ : null;
599
+ const rect = (_b = focusableElement === null || focusableElement === void 0 ? void 0 : focusableElement.getBoundingClientRect()) !== null && _b !== void 0 ? _b : (_a = marqueeSelectableItems.current.get(selectedKey)) === null || _a === void 0 ? void 0 : _a.getRect();
600
+ if (!scrollParent || !rect) {
601
+ if (attempt < TIMELINE_SELECTION_REVEAL_RETRY_COUNT) {
602
+ animationFrame = requestAnimationFrame(() => reveal(attempt + 1));
603
+ }
604
+ return;
605
+ }
606
+ const parentRect = scrollParent.getBoundingClientRect();
607
+ if (rect.top >= parentRect.top && rect.bottom <= parentRect.bottom) {
608
+ return;
609
+ }
610
+ const elementCenter = rect.top + rect.height / 2;
611
+ const parentCenter = parentRect.top + parentRect.height / 2;
612
+ scrollParent.scrollTop += elementCenter - parentCenter;
613
+ };
614
+ animationFrame = requestAnimationFrame(() => reveal(0));
615
+ return () => {
616
+ cancelled = true;
617
+ if (animationFrame !== null) {
618
+ cancelAnimationFrame(animationFrame);
619
+ }
620
+ };
621
+ }, []);
622
+ (0, react_1.useEffect)(() => {
623
+ if (revealRequest === null) {
624
+ return;
625
+ }
626
+ return revealSelectionKey(revealRequest.key);
627
+ }, [revealRequest, revealSelectionKey]);
628
+ const requestRevealSelectionItem = (0, react_1.useCallback)((item) => {
629
+ const key = (0, exports.getTimelineSelectionKey)(item);
630
+ setRevealRequest((previousRequest) => {
631
+ var _a;
632
+ return ({
633
+ key,
634
+ token: ((_a = previousRequest === null || previousRequest === void 0 ? void 0 : previousRequest.token) !== null && _a !== void 0 ? _a : 0) + 1,
635
+ });
636
+ });
637
+ }, []);
638
+ const expandParentsForSelectionItems = (0, react_1.useCallback)((items) => {
639
+ for (const item of items) {
640
+ if (item.type === 'guide') {
641
+ continue;
642
+ }
643
+ expandParentTracks(item.nodePathInfo);
644
+ }
645
+ }, [expandParentTracks]);
646
+ const expandParentsForSelectionItem = (0, react_1.useCallback)((item) => {
647
+ if (item.type === 'guide') {
648
+ return;
649
+ }
650
+ expandParentTracks(item.nodePathInfo);
651
+ }, [expandParentTracks]);
421
652
  (0, react_1.useEffect)(() => {
422
653
  setSelectedItems((currentSelectedItems) => {
423
654
  const nextState = selectionScope.current === timelineSelectionScope
424
- ? (0, exports.getAvailableTimelineSelectionState)({
425
- availableKeys: new Set(selectableItems.current.keys()),
426
- availableItemsByKey: selectableItems.current,
427
- state: {
428
- selectedItems: currentSelectedItems,
429
- anchor: selectionAnchor.current,
430
- },
431
- })
655
+ ? {
656
+ selectedItems: currentSelectedItems,
657
+ anchor: selectionAnchor.current,
658
+ }
432
659
  : exports.EMPTY_TIMELINE_SELECTION_STATE;
433
660
  selectionScope.current = timelineSelectionScope;
434
661
  selectionAnchor.current = nextState.anchor;
@@ -438,7 +665,7 @@ const TimelineSelectionProvider = ({ children }) => {
438
665
  }
439
666
  return nextState.selectedItems;
440
667
  });
441
- }, [selectableItemsVersion, timelineSelectionScope]);
668
+ }, [timelineSelectionScope]);
442
669
  const selectedKeys = (0, react_1.useMemo)(() => new Set(availableSelectedItems.map(exports.getTimelineSelectionKey)), [availableSelectedItems]);
443
670
  const isSelected = (0, react_1.useCallback)((item) => {
444
671
  return selectedKeys.has((0, exports.getTimelineSelectionKey)(item));
@@ -446,19 +673,16 @@ const TimelineSelectionProvider = ({ children }) => {
446
673
  const selectItem = (0, react_1.useCallback)((item, interaction = {
447
674
  shiftKey: false,
448
675
  toggleKey: false,
449
- }) => {
676
+ }, allSelectableItems = [], options = {}) => {
450
677
  if (!canSelectItem(item)) {
451
678
  return;
452
679
  }
680
+ expandParentsForSelectionItem(item);
681
+ if (options.reveal) {
682
+ requestRevealSelectionItem(item);
683
+ }
453
684
  setSelectedItems((currentSelectedItems) => {
454
685
  const currentSelectionState = getCurrentAvailableSelectionState(currentSelectedItems);
455
- const orderedSelectableItems = [
456
- ...selectableItems.current.values(),
457
- ].sort((a, b) => {
458
- var _a, _b;
459
- return (((_a = selectableItemsOrder.current.get((0, exports.getTimelineSelectionKey)(a))) !== null && _a !== void 0 ? _a : 0) -
460
- ((_b = selectableItemsOrder.current.get((0, exports.getTimelineSelectionKey)(b))) !== null && _b !== void 0 ? _b : 0));
461
- });
462
686
  const nextState = (0, exports.getTimelineSelectionAfterInteraction)({
463
687
  currentState: {
464
688
  selectedItems: currentSelectionState.selectedItems,
@@ -466,47 +690,37 @@ const TimelineSelectionProvider = ({ children }) => {
466
690
  },
467
691
  clickedItem: item,
468
692
  interaction,
469
- allSelectableItems: orderedSelectableItems,
693
+ allSelectableItems,
470
694
  });
471
695
  selectionScope.current = timelineSelectionScope;
472
696
  selectionAnchor.current = nextState.anchor;
473
697
  return nextState.selectedItems;
474
698
  });
475
- }, [canSelectItem, getCurrentAvailableSelectionState, timelineSelectionScope]);
476
- const selectItems = (0, react_1.useCallback)((items) => {
699
+ }, [
700
+ canSelectItem,
701
+ expandParentsForSelectionItem,
702
+ getCurrentAvailableSelectionState,
703
+ requestRevealSelectionItem,
704
+ timelineSelectionScope,
705
+ ]);
706
+ const selectItems = (0, react_1.useCallback)((items, options = {}) => {
477
707
  if (!items.every(canSelectItem)) {
478
708
  return;
479
709
  }
480
710
  selectionScope.current = timelineSelectionScope;
481
711
  selectionAnchor.current =
482
712
  items.length === 0 ? null : items[items.length - 1];
483
- setSelectedItems(items);
484
- }, [canSelectItem, timelineSelectionScope]);
485
- const registerSelectableItem = (0, react_1.useCallback)((item) => {
486
- var _a;
487
- const key = (0, exports.getTimelineSelectionKey)(item);
488
- const currentRegistrationCount = (_a = selectableItemRegistrationCounts.current.get(key)) !== null && _a !== void 0 ? _a : 0;
489
- if (currentRegistrationCount === 0) {
490
- const registrationOrder = registrationCounter.current;
491
- registrationCounter.current += 1;
492
- selectableItemsOrder.current.set(key, registrationOrder);
713
+ expandParentsForSelectionItems(items);
714
+ if (options.reveal && items.length === 1) {
715
+ requestRevealSelectionItem(items[0]);
493
716
  }
494
- selectableItemRegistrationCounts.current.set(key, currentRegistrationCount + 1);
495
- selectableItems.current.set(key, item);
496
- bumpSelectableItemsVersion();
497
- return () => {
498
- var _a;
499
- const nextRegistrationCount = ((_a = selectableItemRegistrationCounts.current.get(key)) !== null && _a !== void 0 ? _a : 1) - 1;
500
- if (nextRegistrationCount > 0) {
501
- selectableItemRegistrationCounts.current.set(key, nextRegistrationCount);
502
- return;
503
- }
504
- selectableItemRegistrationCounts.current.delete(key);
505
- selectableItems.current.delete(key);
506
- selectableItemsOrder.current.delete(key);
507
- bumpSelectableItemsVersion();
508
- };
509
- }, [bumpSelectableItemsVersion]);
717
+ setSelectedItems(items);
718
+ }, [
719
+ canSelectItem,
720
+ expandParentsForSelectionItems,
721
+ requestRevealSelectionItem,
722
+ timelineSelectionScope,
723
+ ]);
510
724
  const registerMarqueeSelectableItem = (0, react_1.useCallback)((item, getRect) => {
511
725
  const key = (0, exports.getTimelineSelectionKey)(item);
512
726
  const registrationOrder = marqueeRegistrationCounter.current;
@@ -520,6 +734,25 @@ const TimelineSelectionProvider = ({ children }) => {
520
734
  marqueeSelectableItems.current.delete(key);
521
735
  };
522
736
  }, []);
737
+ const registerFocusableItem = (0, react_1.useCallback)((item, getElement) => {
738
+ var _a;
739
+ const key = (0, exports.getTimelineSelectionKey)(item);
740
+ const registrationOrder = focusableRegistrationCounter.current;
741
+ focusableRegistrationCounter.current += 1;
742
+ const registrations = (_a = focusableItems.current.get(key)) !== null && _a !== void 0 ? _a : new Map();
743
+ registrations.set(registrationOrder, {
744
+ getElement,
745
+ order: registrationOrder,
746
+ });
747
+ focusableItems.current.set(key, registrations);
748
+ return () => {
749
+ const latestRegistrations = focusableItems.current.get(key);
750
+ latestRegistrations === null || latestRegistrations === void 0 ? void 0 : latestRegistrations.delete(registrationOrder);
751
+ if ((latestRegistrations === null || latestRegistrations === void 0 ? void 0 : latestRegistrations.size) === 0) {
752
+ focusableItems.current.delete(key);
753
+ }
754
+ };
755
+ }, []);
523
756
  const getMarqueeSelectionForRect = (0, react_1.useCallback)((marqueeRect, lockedSelectionKind) => {
524
757
  const candidates = [...marqueeSelectableItems.current.values()]
525
758
  .sort((a, b) => a.order - b.order)
@@ -564,8 +797,8 @@ const TimelineSelectionProvider = ({ children }) => {
564
797
  isSelected,
565
798
  selectItem,
566
799
  selectItems,
567
- registerSelectableItem,
568
800
  registerMarqueeSelectableItem,
801
+ registerFocusableItem,
569
802
  getMarqueeSelection: getMarqueeSelectionForRect,
570
803
  containsSelection,
571
804
  clearSelection,
@@ -575,15 +808,15 @@ const TimelineSelectionProvider = ({ children }) => {
575
808
  isSelected,
576
809
  selectItem,
577
810
  selectItems,
578
- registerSelectableItem,
579
811
  registerMarqueeSelectableItem,
812
+ registerFocusableItem,
580
813
  getMarqueeSelectionForRect,
581
814
  containsSelection,
582
815
  clearSelection,
583
816
  ]);
584
817
  const currentSelection = (0, react_1.useRef)(value);
585
818
  currentSelection.current = value;
586
- return (jsx_runtime_1.jsx(CurrentTimelineSelectionContext.Provider, { value: currentSelection, children: jsx_runtime_1.jsxs(TimelineSelectionContext.Provider, { value: value, children: [children, jsx_runtime_1.jsx(TimelineClipboardKeybindings_1.TimelineClipboardKeybindings, {}), jsx_runtime_1.jsx(TimelineDeleteKeybindings_1.TimelineDeleteKeybindings, {})
819
+ return (jsx_runtime_1.jsx(CurrentTimelineSelectionContext.Provider, { value: currentSelection, children: jsx_runtime_1.jsxs(TimelineSelectionContext.Provider, { value: value, children: [children, jsx_runtime_1.jsx(TimelineEscapeKeybindings, {}), jsx_runtime_1.jsx(TimelineClipboardKeybindings_1.TimelineClipboardKeybindings, {}), jsx_runtime_1.jsx(TimelineDeleteKeybindings_1.TimelineDeleteKeybindings, {})
587
820
  ] }) }));
588
821
  };
589
822
  exports.TimelineSelectionProvider = TimelineSelectionProvider;
@@ -712,22 +945,27 @@ const useTimelineMarqueeSelectableItem = (item, ref) => {
712
945
  }, [item, ref, registerMarqueeSelectableItem]);
713
946
  };
714
947
  exports.useTimelineMarqueeSelectableItem = useTimelineMarqueeSelectableItem;
715
- const useTimelineRowSelection = (nodePathInfo) => {
716
- const { canSelect, isSelected, selectItem, registerSelectableItem } = (0, exports.useTimelineSelection)();
717
- const selectionItem = (0, react_1.useMemo)(() => (0, exports.getTimelineSelectionFromNodePathInfo)(nodePathInfo), [nodePathInfo]);
948
+ const useTimelineFocusableItem = (item, ref) => {
949
+ const { registerFocusableItem } = (0, exports.useTimelineSelection)();
718
950
  (0, react_1.useEffect)(() => {
719
- if (selectionItem === null) {
951
+ if (item === null) {
720
952
  return;
721
953
  }
722
- return registerSelectableItem(selectionItem);
723
- }, [registerSelectableItem, selectionItem]);
954
+ return registerFocusableItem(item, () => ref.current);
955
+ }, [item, ref, registerFocusableItem]);
956
+ };
957
+ exports.useTimelineFocusableItem = useTimelineFocusableItem;
958
+ const useTimelineRowSelection = (nodePathInfo) => {
959
+ const { canSelect, isSelected, selectItem } = (0, exports.useTimelineSelection)();
960
+ const selectableTimelineItemsRef = (0, react_1.useContext)(SelectableTimelineItemsContext);
961
+ const selectionItem = (0, react_1.useMemo)(() => (0, exports.getTimelineSelectionFromNodePathInfo)(nodePathInfo), [nodePathInfo]);
724
962
  const selected = selectionItem === null ? false : isSelected(selectionItem);
725
963
  const onSelect = (0, react_1.useCallback)((interaction) => {
726
964
  if (selectionItem === null) {
727
965
  return;
728
966
  }
729
- selectItem(selectionItem, interaction);
730
- }, [selectItem, selectionItem]);
967
+ selectItem(selectionItem, interaction, selectableTimelineItemsRef.current, { reveal: true });
968
+ }, [selectItem, selectableTimelineItemsRef, selectionItem]);
731
969
  return {
732
970
  onSelect,
733
971
  selectable: canSelect && selectionItem !== null,
@@ -737,19 +975,17 @@ const useTimelineRowSelection = (nodePathInfo) => {
737
975
  };
738
976
  exports.useTimelineRowSelection = useTimelineRowSelection;
739
977
  const useTimelineKeyframeSelection = (nodePathInfo, frame) => {
740
- const { canSelect, isSelected, selectItem, registerSelectableItem } = (0, exports.useTimelineSelection)();
978
+ const { canSelect, isSelected, selectItem } = (0, exports.useTimelineSelection)();
979
+ const selectableTimelineItemsRef = (0, react_1.useContext)(SelectableTimelineItemsContext);
741
980
  const selectionItem = (0, react_1.useMemo)(() => ({
742
981
  type: 'keyframe',
743
982
  nodePathInfo,
744
983
  frame,
745
984
  }), [nodePathInfo, frame]);
746
- (0, react_1.useEffect)(() => {
747
- return registerSelectableItem(selectionItem);
748
- }, [registerSelectableItem, selectionItem]);
749
985
  const selected = isSelected(selectionItem);
750
986
  const onSelect = (0, react_1.useCallback)((interaction) => {
751
- selectItem(selectionItem, interaction);
752
- }, [selectItem, selectionItem]);
987
+ selectItem(selectionItem, interaction, selectableTimelineItemsRef.current);
988
+ }, [selectItem, selectableTimelineItemsRef, selectionItem]);
753
989
  return {
754
990
  onSelect,
755
991
  selectable: canSelect,
@@ -759,7 +995,8 @@ const useTimelineKeyframeSelection = (nodePathInfo, frame) => {
759
995
  };
760
996
  exports.useTimelineKeyframeSelection = useTimelineKeyframeSelection;
761
997
  const useTimelineEasingSelection = ({ nodePathInfo, fromFrame, toFrame, segmentIndex, }) => {
762
- const { canSelect, isSelected, selectItem, registerSelectableItem } = (0, exports.useTimelineSelection)();
998
+ const { canSelect, isSelected, selectItem } = (0, exports.useTimelineSelection)();
999
+ const selectableTimelineItemsRef = (0, react_1.useContext)(SelectableTimelineItemsContext);
763
1000
  const selectionItem = (0, react_1.useMemo)(() => ({
764
1001
  type: 'easing',
765
1002
  nodePathInfo,
@@ -767,13 +1004,10 @@ const useTimelineEasingSelection = ({ nodePathInfo, fromFrame, toFrame, segmentI
767
1004
  toFrame,
768
1005
  segmentIndex,
769
1006
  }), [nodePathInfo, fromFrame, segmentIndex, toFrame]);
770
- (0, react_1.useEffect)(() => {
771
- return registerSelectableItem(selectionItem);
772
- }, [registerSelectableItem, selectionItem]);
773
1007
  const selected = isSelected(selectionItem);
774
1008
  const onSelect = (0, react_1.useCallback)((interaction) => {
775
- selectItem(selectionItem, interaction);
776
- }, [selectItem, selectionItem]);
1009
+ selectItem(selectionItem, interaction, selectableTimelineItemsRef.current);
1010
+ }, [selectItem, selectableTimelineItemsRef, selectionItem]);
777
1011
  return {
778
1012
  onSelect,
779
1013
  selectable: canSelect,
@@ -783,14 +1017,11 @@ const useTimelineEasingSelection = ({ nodePathInfo, fromFrame, toFrame, segmentI
783
1017
  };
784
1018
  exports.useTimelineEasingSelection = useTimelineEasingSelection;
785
1019
  const useTimelineGuideSelection = (guideId) => {
786
- const { canSelect, clearSelection, isSelected, selectItem, registerSelectableItem, } = (0, exports.useTimelineSelection)();
1020
+ const { canSelect, clearSelection, isSelected, selectItem } = (0, exports.useTimelineSelection)();
787
1021
  const selectionItem = (0, react_1.useMemo)(() => ({
788
1022
  type: 'guide',
789
1023
  guideId,
790
1024
  }), [guideId]);
791
- (0, react_1.useEffect)(() => {
792
- return registerSelectableItem(selectionItem);
793
- }, [registerSelectableItem, selectionItem]);
794
1025
  const selected = isSelected(selectionItem);
795
1026
  const onSelect = (0, react_1.useCallback)(() => {
796
1027
  selectItem(selectionItem);