@remotion/studio 4.0.523 → 4.0.525

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 (182) hide show
  1. package/dist/components/ActionTooltip.d.ts +11 -0
  2. package/dist/components/ActionTooltip.js +153 -0
  3. package/dist/components/AppLaunchButton.js +2 -0
  4. package/dist/components/AssetSelectorModal.d.ts +6 -0
  5. package/dist/components/AssetSelectorModal.js +174 -0
  6. package/dist/components/Canvas.js +18 -3
  7. package/dist/components/CheckboardToggle.js +8 -10
  8. package/dist/components/ColorPicker/AlphaSlider.js +1 -1
  9. package/dist/components/ColorPicker/HueSlider.js +1 -1
  10. package/dist/components/ColorPicker/SaturationValueArea.js +1 -1
  11. package/dist/components/CompositionSelector.js +1 -0
  12. package/dist/components/CompositionSelectorItem.js +1 -0
  13. package/dist/components/EditorGuides/Guide.js +1 -1
  14. package/dist/components/ElementInstallConfirmation.js +35 -62
  15. package/dist/components/FullscreenToggle.js +5 -8
  16. package/dist/components/GlobalKeybindings.js +71 -0
  17. package/dist/components/InspectorLocationCopy.js +1 -1
  18. package/dist/components/InspectorOpenInEditor.d.ts +1 -0
  19. package/dist/components/InspectorOpenInEditor.js +18 -15
  20. package/dist/components/InspectorPanel/CompositionInspectorHeader.js +6 -7
  21. package/dist/components/InspectorPanel/CompositionMetadata.js +1 -0
  22. package/dist/components/InspectorPanel/ElementLibraryButton.js +1 -0
  23. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +4 -12
  24. package/dist/components/InspectorSequenceSection.js +23 -14
  25. package/dist/components/LazySyntaxHighlightedSource.d.ts +4 -0
  26. package/dist/components/LazySyntaxHighlightedSource.js +43 -0
  27. package/dist/components/LoopToggle.js +9 -2
  28. package/dist/components/Menu/MenuItem.js +1 -2
  29. package/dist/components/MenuBuildIndicator.js +1 -1
  30. package/dist/components/MenuToolbar.js +6 -4
  31. package/dist/components/Modals.js +2 -1
  32. package/dist/components/MuteToggle.d.ts +1 -0
  33. package/dist/components/MuteToggle.js +17 -6
  34. package/dist/components/NewComposition/CodemodFooter.js +1 -0
  35. package/dist/components/NewComposition/DeleteComposition.js +42 -6
  36. package/dist/components/NewComposition/DeleteFolder.js +1 -0
  37. package/dist/components/NewComposition/DuplicateComposition.js +5 -0
  38. package/dist/components/NewComposition/InputDragger.js +2 -2
  39. package/dist/components/NewComposition/NewComposition.d.ts +1 -0
  40. package/dist/components/NewComposition/NewComposition.js +5 -4
  41. package/dist/components/NewComposition/NewFolder.js +31 -6
  42. package/dist/components/NewComposition/RenameComposition.js +3 -2
  43. package/dist/components/NewComposition/RenameFolder.js +3 -4
  44. package/dist/components/NewComposition/SlugPreview.d.ts +7 -0
  45. package/dist/components/NewComposition/SlugPreview.js +18 -0
  46. package/dist/components/NewComposition/duplicate-composition-api.d.ts +3 -2
  47. package/dist/components/NewComposition/duplicate-composition-api.js +9 -2
  48. package/dist/components/Notifications/NotificationCenter.d.ts +1 -0
  49. package/dist/components/Notifications/NotificationCenter.js +22 -1
  50. package/dist/components/OutlineToggle.js +17 -10
  51. package/dist/components/PlayPause.js +7 -1
  52. package/dist/components/PlaybackKeyboardShortcutsManager.d.ts +2 -0
  53. package/dist/components/PlaybackKeyboardShortcutsManager.js +36 -1
  54. package/dist/components/PlaybackRateSelector.js +2 -2
  55. package/dist/components/Preview.js +0 -3
  56. package/dist/components/PreviewToolbar.js +4 -7
  57. package/dist/components/PreviewToolbarOverflowButton.js +10 -3
  58. package/dist/components/QuickSwitcher/QuickSwitcherContent.js +1 -1
  59. package/dist/components/RenderButton.js +40 -4
  60. package/dist/components/RenderModal/WebRenderModalBasic.js +1 -1
  61. package/dist/components/RenderModal/render-modals.js +3 -0
  62. package/dist/components/RenderQueue/CaptionQueueItem.js +2 -1
  63. package/dist/components/RenderQueue/RenderQueueCopyToClipboard.js +2 -1
  64. package/dist/components/RenderQueue/RenderQueueDownloadItem.js +2 -1
  65. package/dist/components/RenderQueue/RenderQueueItemCancelButton.js +2 -1
  66. package/dist/components/RenderQueue/RenderQueueOpenInFolder.js +2 -1
  67. package/dist/components/RenderQueue/RenderQueueRemoveItem.js +2 -1
  68. package/dist/components/RenderQueue/RenderQueueRepeat.js +2 -1
  69. package/dist/components/RenderQueue/VideoMattingQueueItem.js +2 -1
  70. package/dist/components/RenderQueue/actions.d.ts +2 -1
  71. package/dist/components/RenderQueue/actions.js +2 -1
  72. package/dist/components/RulersAndGuidesToggle.js +8 -1
  73. package/dist/components/SegmentedButton.d.ts +1 -0
  74. package/dist/components/SegmentedButton.js +9 -3
  75. package/dist/components/SelectedOutlineElement.js +16 -6
  76. package/dist/components/SelectedOutlinePolygon.js +4 -2
  77. package/dist/components/SettingsButton.js +8 -6
  78. package/dist/components/SettingsContext.d.ts +8 -0
  79. package/dist/components/SettingsContext.js +57 -2
  80. package/dist/components/SettingsModal.js +4 -1
  81. package/dist/components/SettingsModalFooter.js +1 -1
  82. package/dist/components/SidebarCollapserControls.js +13 -16
  83. package/dist/components/SizeSelector.js +2 -2
  84. package/dist/components/SkillsSettings.js +35 -4
  85. package/dist/components/SnappingToggle.js +7 -8
  86. package/dist/components/Splitter/SplitterHandle.js +1 -2
  87. package/dist/components/StudioSettings.js +32 -18
  88. package/dist/components/SyntaxHighlightedSource.d.ts +5 -0
  89. package/dist/components/{HighlightedElementSource.js → SyntaxHighlightedSource.js} +2 -2
  90. package/dist/components/Tabs/vertical.d.ts +1 -1
  91. package/dist/components/Tabs/vertical.js +16 -2
  92. package/dist/components/Timeline/EasingEditorModal.js +2 -2
  93. package/dist/components/Timeline/Timeline.js +47 -39
  94. package/dist/components/Timeline/TimelineAssetField.js +148 -9
  95. package/dist/components/Timeline/TimelineDragHandler.js +1 -2
  96. package/dist/components/Timeline/TimelineEffectItem.d.ts +1 -0
  97. package/dist/components/Timeline/TimelineEffectItem.js +2 -2
  98. package/dist/components/Timeline/TimelineEffectPropItem.d.ts +1 -0
  99. package/dist/components/Timeline/TimelineEffectPropItem.js +2 -2
  100. package/dist/components/Timeline/TimelineExpandedRow.js +2 -2
  101. package/dist/components/Timeline/TimelineInOutDragHandler.js +1 -2
  102. package/dist/components/Timeline/TimelineLayerChildren.js +12 -9
  103. package/dist/components/Timeline/TimelineSchemaField.js +8 -1
  104. package/dist/components/Timeline/TimelineSelection.d.ts +3 -1
  105. package/dist/components/Timeline/TimelineSelection.js +32 -5
  106. package/dist/components/Timeline/TimelineSequence.js +6 -6
  107. package/dist/components/Timeline/TimelineSequenceItem.js +12 -10
  108. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +3 -12
  109. package/dist/components/Timeline/TimelineTranslateField.js +25 -12
  110. package/dist/components/Timeline/TimelineZoomControls.js +2 -1
  111. package/dist/components/Timeline/get-sequence-context-menu-items.js +22 -6
  112. package/dist/components/Timeline/timeline-field-display-utils.js +12 -7
  113. package/dist/components/Timeline/timeline-translate-utils.d.ts +17 -0
  114. package/dist/components/Timeline/timeline-translate-utils.js +53 -12
  115. package/dist/components/Timeline/use-open-sequence-in-apps.d.ts +2 -0
  116. package/dist/components/Timeline/use-open-sequence-in-apps.js +17 -0
  117. package/dist/components/Timeline/use-timeline-asset-drop.js +17 -3
  118. package/dist/components/Timeline/use-timeline-keyframe-drag.js +4 -4
  119. package/dist/components/TimelineCombobox.d.ts +1 -0
  120. package/dist/components/TimelineCombobox.js +9 -4
  121. package/dist/components/TimelineInOutToggle.js +8 -15
  122. package/dist/components/UndoRedoButtons.js +11 -0
  123. package/dist/components/composition-menu-items.js +56 -2
  124. package/dist/components/folder-menu-items.js +44 -0
  125. package/dist/components/get-open-in-menu-items.js +1 -1
  126. package/dist/components/handle-drop.js +3 -2
  127. package/dist/components/import-assets.d.ts +24 -1
  128. package/dist/components/import-assets.js +3 -1
  129. package/dist/components/keyboard-shortcuts.d.ts +4 -4
  130. package/dist/components/keyboard-shortcuts.js +28 -9
  131. package/dist/error-overlay/remotion-overlay/CodeFrame.js +29 -18
  132. package/dist/esm/LazyModels-gfmpcy4h.mjs +11 -0
  133. package/dist/esm/LazyModels-m1rf06wh.mjs +11 -0
  134. package/dist/esm/{HighlightedElementSource-jfc66k4p.mjs → SyntaxHighlightedSource-3xks91rz.mjs} +4 -4
  135. package/dist/esm/{TranscriptionModal-916jqhry.mjs → TranscriptionModal-8pvrehg4.mjs} +7 -7
  136. package/dist/esm/{VideoMattingModal-2tm79s9b.mjs → VideoMattingModal-fefbzgka.mjs} +7 -7
  137. package/dist/esm/{index-xhe2m2qr.mjs → index-0x13f28h.mjs} +35 -13
  138. package/dist/esm/{index-sgtmgc4h.mjs → index-1089795y.mjs} +3 -3
  139. package/dist/esm/{index-hy4xcgty.mjs → index-41kqns5c.mjs} +5 -3
  140. package/dist/esm/{index-6cvm9a65.mjs → index-ggqpre9v.mjs} +2868 -2099
  141. package/dist/esm/{index-czwvnn9g.mjs → index-hbezgbbq.mjs} +1 -1
  142. package/dist/esm/{index-1x7bsdh6.mjs → index-jrw61pkj.mjs} +2 -2
  143. package/dist/esm/{index-jg13hf2g.mjs → index-k426ye99.mjs} +2 -1
  144. package/dist/esm/{index-te66vvrp.mjs → index-mww32xc8.mjs} +4 -4
  145. package/dist/esm/{index-x7t2y7ws.mjs → index-s848rffx.mjs} +6985 -5956
  146. package/dist/esm/{index-3hgr6gjx.mjs → index-tzxb8808.mjs} +1 -1
  147. package/dist/esm/{index-5qddp5h7.mjs → index-vsxrxfpj.mjs} +1 -1
  148. package/dist/esm/index.mjs +3 -3
  149. package/dist/esm/internals.mjs +8 -8
  150. package/dist/esm/previewEntry.mjs +8 -8
  151. package/dist/esm/renderEntry.mjs +3 -3
  152. package/dist/helpers/colors.d.ts +1 -0
  153. package/dist/helpers/colors.js +4 -3
  154. package/dist/helpers/get-git-menu-item.d.ts +4 -0
  155. package/dist/helpers/get-git-menu-item.js +8 -1
  156. package/dist/helpers/get-sequence-double-click-action.d.ts +3 -3
  157. package/dist/helpers/get-sequence-double-click-action.js +2 -2
  158. package/dist/helpers/inject-css.js +2 -2
  159. package/dist/helpers/pointer-session.d.ts +1 -0
  160. package/dist/helpers/pointer-session.js +10 -1
  161. package/dist/helpers/prism-vsc-dark-plus.d.ts +1 -0
  162. package/dist/helpers/prism-vsc-dark-plus.js +305 -0
  163. package/dist/helpers/studio-runtime-config.d.ts +1 -1
  164. package/dist/helpers/use-create-composition.d.ts +1 -0
  165. package/dist/helpers/use-create-composition.js +17 -7
  166. package/dist/helpers/use-keybinding.d.ts +1 -1
  167. package/dist/helpers/use-keyboard-shortcut-label.d.ts +2 -2
  168. package/dist/helpers/use-media-metadata.js +5 -1
  169. package/dist/helpers/use-menu-structure.js +6 -2
  170. package/dist/helpers/use-rename-composition.d.ts +1 -0
  171. package/dist/helpers/use-rename-composition.js +16 -5
  172. package/dist/icons/skills.js +1 -1
  173. package/dist/renderEntry.js +2 -2
  174. package/dist/state/modals.d.ts +13 -1
  175. package/dist/state/z-index.js +1 -3
  176. package/package.json +20 -20
  177. package/dist/components/HighlightedElementSource.d.ts +0 -5
  178. package/dist/esm/LazyModels-2trdm224.mjs +0 -11
  179. package/dist/esm/LazyModels-fjb5ckaq.mjs +0 -11
  180. package/dist/helpers/prism-tomorrow.d.ts +0 -1
  181. package/dist/helpers/prism-tomorrow.js +0 -151
  182. /package/dist/esm/{resolve-composition-component-location-14148845.mjs → resolve-composition-component-location-bt2d6qxq.mjs} +0 -0
@@ -899,10 +899,7 @@ const TimelineSequenceLeftEdgeDragHandleInner = ({ nodePathInfo, windowWidth, ti
899
899
  onMove,
900
900
  onEnd: (reason, endEvent) => {
901
901
  stopPointerSessionRef.current = null;
902
- if ((reason === 'pointerup' ||
903
- reason === 'buttons-released' ||
904
- (reason === 'lostpointercapture' && (endEvent === null || endEvent === void 0 ? void 0 : endEvent.buttons) === 0)) &&
905
- endEvent) {
902
+ if ((0, pointer_session_1.isPointerSessionRelease)(reason, endEvent)) {
906
903
  onUp(endEvent);
907
904
  }
908
905
  else if (endEvent) {
@@ -1122,10 +1119,7 @@ const useTimelineSequenceFromDrag = ({ nodePathInfo, windowWidth, timelineDurati
1122
1119
  },
1123
1120
  onEnd: (reason, endEvent) => {
1124
1121
  stopPointerSessionRef.current = null;
1125
- finishDrag((reason === 'pointerup' ||
1126
- reason === 'buttons-released' ||
1127
- (reason === 'lostpointercapture' && (endEvent === null || endEvent === void 0 ? void 0 : endEvent.buttons) === 0)) &&
1128
- endEvent !== null);
1122
+ finishDrag((0, pointer_session_1.isPointerSessionRelease)(reason, endEvent));
1129
1123
  },
1130
1124
  });
1131
1125
  }, [
@@ -1325,10 +1319,7 @@ const TimelineSequenceRightEdgeDragHandleInner = ({ nodePathInfo, mediaDurationD
1325
1319
  onMove,
1326
1320
  onEnd: (reason, endEvent) => {
1327
1321
  stopPointerSessionRef.current = null;
1328
- if ((reason === 'pointerup' ||
1329
- reason === 'buttons-released' ||
1330
- (reason === 'lostpointercapture' && (endEvent === null || endEvent === void 0 ? void 0 : endEvent.buttons) === 0)) &&
1331
- endEvent) {
1322
+ if ((0, pointer_session_1.isPointerSessionRelease)(reason, endEvent)) {
1332
1323
  onUp(endEvent);
1333
1324
  }
1334
1325
  else if (endEvent) {
@@ -4,9 +4,9 @@ exports.TimelineTranslateField = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const InputDragger_1 = require("../NewComposition/InputDragger");
7
- const timeline_field_display_utils_1 = require("./timeline-field-display-utils");
8
7
  const timeline_field_utils_1 = require("./timeline-field-utils");
9
8
  const timeline_translate_utils_1 = require("./timeline-translate-utils");
9
+ const TimelineSchemaField_1 = require("./TimelineSchemaField");
10
10
  const Transform3DModeContext_1 = require("./Transform3DModeContext");
11
11
  const leftDraggerStyle = {
12
12
  paddingLeft: 0,
@@ -21,11 +21,15 @@ const containerStyle = {
21
21
  const translateDragSensitivity = 3;
22
22
  const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onDragValueChange, onDragEnd, }) => {
23
23
  var _a;
24
+ var _b, _c, _d, _e;
24
25
  const [dragX, setDragX] = (0, react_1.useState)(null);
25
26
  const [dragY, setDragY] = (0, react_1.useState)(null);
26
27
  const [dragZ, setDragZ] = (0, react_1.useState)(null);
27
28
  const transform3DMode = (0, react_1.useContext)(Transform3DModeContext_1.Transform3DModeContext);
28
- const [codeX, codeY, codeZ] = (0, react_1.useMemo)(() => (0, timeline_translate_utils_1.parseTranslate)(String(effectiveValue !== null && effectiveValue !== void 0 ? effectiveValue : '0px 0px')), [effectiveValue]);
29
+ const parsedTranslate = (0, react_1.useMemo)(() => (0, timeline_translate_utils_1.parseTranslateWithUnits)(String(effectiveValue !== null && effectiveValue !== void 0 ? effectiveValue : '0px 0px')), [effectiveValue]);
30
+ const codeX = (_b = parsedTranslate === null || parsedTranslate === void 0 ? void 0 : parsedTranslate[0].value) !== null && _b !== void 0 ? _b : 0;
31
+ const codeY = (_c = parsedTranslate === null || parsedTranslate === void 0 ? void 0 : parsedTranslate[1].value) !== null && _c !== void 0 ? _c : 0;
32
+ const codeZ = (_d = (_a = parsedTranslate === null || parsedTranslate === void 0 ? void 0 : parsedTranslate[2]) === null || _a === void 0 ? void 0 : _a.value) !== null && _d !== void 0 ? _d : null;
29
33
  const show3D = transform3DMode || (codeZ !== null && codeZ !== 0);
30
34
  const configuredStep = field.fieldSchema.type === 'translate' ? field.fieldSchema.step : undefined;
31
35
  const step = configuredStep !== null && configuredStep !== void 0 ? configuredStep : 1;
@@ -33,15 +37,21 @@ const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onD
33
37
  defaultDecimalPlaces: 1,
34
38
  step: configuredStep,
35
39
  }), [configuredStep]);
36
- const formatter = (0, react_1.useCallback)((v) => {
37
- return (0, timeline_field_display_utils_1.formatTimelineFieldValueForDisplay)({
38
- fieldSchema: field.fieldSchema,
39
- value: v,
40
- });
41
- }, [field.fieldSchema]);
40
+ const formatCoordinate = (0, react_1.useCallback)((v, unit) => {
41
+ return `${(0, timeline_field_utils_1.formatTimelineNumber)({
42
+ decimalPlaces,
43
+ fixed: false,
44
+ value: (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(v)),
45
+ })}${unit}`;
46
+ }, [decimalPlaces]);
42
47
  const serialize = (0, react_1.useCallback)((x, y, z = dragZ !== null && dragZ !== void 0 ? dragZ : codeZ) => {
43
- return (0, timeline_translate_utils_1.serializeTranslate)([x, y, z], decimalPlaces);
44
- }, [codeZ, decimalPlaces, dragZ]);
48
+ var _a, _b;
49
+ return (0, timeline_translate_utils_1.serializeTranslateWithUnits)([
50
+ { value: x, unit: (_a = parsedTranslate === null || parsedTranslate === void 0 ? void 0 : parsedTranslate[0].unit) !== null && _a !== void 0 ? _a : 'px' },
51
+ { value: y, unit: (_b = parsedTranslate === null || parsedTranslate === void 0 ? void 0 : parsedTranslate[1].unit) !== null && _b !== void 0 ? _b : 'px' },
52
+ z === null ? null : { value: z, unit: 'px' },
53
+ ], decimalPlaces);
54
+ }, [codeZ, decimalPlaces, dragZ, parsedTranslate]);
45
55
  // --- X callbacks ---
46
56
  const onXChange = (0, react_1.useCallback)((newVal) => {
47
57
  setDragX(newVal);
@@ -135,9 +145,12 @@ const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onD
135
145
  }
136
146
  }
137
147
  }, [codeX, codeY, dragX, dragY, onSave, propStatus, serialize]);
148
+ if (parsedTranslate === null) {
149
+ return (jsx_runtime_1.jsx(TimelineSchemaField_1.UnsupportedStatus, { label: "unsupported offset", formattedValue: false }));
150
+ }
138
151
  return (jsx_runtime_1.jsxs("span", { style: containerStyle, children: [
139
- jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragX !== null && dragX !== void 0 ? dragX : codeX, buttonStyle: leftDraggerStyle, style: leftDraggerStyle, status: "ok", small: true, onValueChange: onXChange, onValueChangeEnd: onXChangeEnd, onTextChange: onXTextChange, min: -Infinity, max: Infinity, step: step, formatter: formatter, rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces, dragSensitivity: translateDragSensitivity, "aria-label": "Offset X" }), jsx_runtime_1.jsx("div", { style: { marginLeft: -6, marginRight: -6 } }), jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragY !== null && dragY !== void 0 ? dragY : codeY, buttonStyle: rightDraggerStyle, style: rightDraggerStyle, status: "ok", small: true, onValueChange: onYChange, onValueChangeEnd: onYChangeEnd, onTextChange: onYTextChange, min: -Infinity, max: Infinity, step: step, formatter: formatter, rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces, dragSensitivity: translateDragSensitivity, "aria-label": "Offset Y" }), show3D ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
140
- jsx_runtime_1.jsx("div", { style: { marginLeft: -6, marginRight: -6 } }), jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: (_a = dragZ !== null && dragZ !== void 0 ? dragZ : codeZ) !== null && _a !== void 0 ? _a : 0, buttonStyle: rightDraggerStyle, style: rightDraggerStyle, status: "ok", small: true, onValueChange: onZChange, onValueChangeEnd: onZChangeEnd, onTextChange: onZTextChange, min: -Infinity, max: Infinity, step: step, formatter: formatter, rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces, dragSensitivity: translateDragSensitivity, "aria-label": "Offset Z" })
152
+ jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragX !== null && dragX !== void 0 ? dragX : codeX, buttonStyle: leftDraggerStyle, style: leftDraggerStyle, status: "ok", small: true, onValueChange: onXChange, onValueChangeEnd: onXChangeEnd, onTextChange: onXTextChange, min: -Infinity, max: Infinity, step: step, formatter: (value) => formatCoordinate(value, parsedTranslate[0].unit), rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces, dragSensitivity: translateDragSensitivity, "aria-label": "Offset X" }), jsx_runtime_1.jsx("div", { style: { marginLeft: -6, marginRight: -6 } }), jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragY !== null && dragY !== void 0 ? dragY : codeY, buttonStyle: rightDraggerStyle, style: rightDraggerStyle, status: "ok", small: true, onValueChange: onYChange, onValueChangeEnd: onYChangeEnd, onTextChange: onYTextChange, min: -Infinity, max: Infinity, step: step, formatter: (value) => formatCoordinate(value, parsedTranslate[1].unit), rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces, dragSensitivity: translateDragSensitivity, "aria-label": "Offset Y" }), show3D ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
153
+ jsx_runtime_1.jsx("div", { style: { marginLeft: -6, marginRight: -6 } }), jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: (_e = dragZ !== null && dragZ !== void 0 ? dragZ : codeZ) !== null && _e !== void 0 ? _e : 0, buttonStyle: rightDraggerStyle, style: rightDraggerStyle, status: "ok", small: true, onValueChange: onZChange, onValueChangeEnd: onZChangeEnd, onTextChange: onZTextChange, min: -Infinity, max: Infinity, step: step, formatter: (value) => formatCoordinate(value, 'px'), rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces, dragSensitivity: translateDragSensitivity, "aria-label": "Offset Z" })
141
154
  ] })) : null] }));
142
155
  };
143
156
  exports.TimelineTranslateField = TimelineTranslateField;
@@ -44,6 +44,7 @@ const is_current_selected_still_1 = require("../../helpers/is-current-selected-s
44
44
  const canvas_zoom_1 = require("../../icons/canvas-zoom");
45
45
  const timeline_zoom_1 = require("../../state/timeline-zoom");
46
46
  const z_index_1 = require("../../state/z-index");
47
+ const ActionTooltip_1 = require("../ActionTooltip");
47
48
  const ControlButton_1 = require("../ControlButton");
48
49
  const layout_1 = require("../layout");
49
50
  const timeline_refs_1 = require("./timeline-refs");
@@ -123,7 +124,7 @@ const TimelineZoomControlsInner = ({ sliderMaxWidth }) => {
123
124
  return null;
124
125
  }
125
126
  return (jsx_runtime_1.jsxs("div", { style: container, children: [
126
- jsx_runtime_1.jsx(ControlButton_1.ControlButton, { onClick: onMinusClicked, style: buttonStyle, title: "Zoom out timeline", role: 'ControlButton', type: "button", children: (color) => jsx_runtime_1.jsx(canvas_zoom_1.CanvasZoomOutIcon, { color: color }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(TimelineZoomSlider, { maxWidth: sliderMaxWidth, minZoom: minZoom, timelineViewportWidth: timelineViewportWidth }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(ControlButton_1.ControlButton, { onClick: onPlusClicked, style: buttonStyle, title: "Zoom in timeline", role: 'button', type: "button", children: (color) => jsx_runtime_1.jsx(canvas_zoom_1.CanvasZoomIcon, { color: color }) })
127
+ jsx_runtime_1.jsx(ActionTooltip_1.ActionTooltip, { label: "Zoom out", shortcut: null, delay: 800, dismissOnClick: true, children: jsx_runtime_1.jsx(ControlButton_1.ControlButton, { onClick: onMinusClicked, style: buttonStyle, title: "", "aria-label": "Zoom out timeline", type: "button", children: (color) => jsx_runtime_1.jsx(canvas_zoom_1.CanvasZoomOutIcon, { color: color }) }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(TimelineZoomSlider, { maxWidth: sliderMaxWidth, minZoom: minZoom, timelineViewportWidth: timelineViewportWidth }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(ActionTooltip_1.ActionTooltip, { label: "Zoom in", shortcut: null, delay: 800, dismissOnClick: true, children: jsx_runtime_1.jsx(ControlButton_1.ControlButton, { onClick: onPlusClicked, style: buttonStyle, title: "", "aria-label": "Zoom in timeline", type: "button", children: (color) => jsx_runtime_1.jsx(canvas_zoom_1.CanvasZoomIcon, { color: color }) }) })
127
128
  ] }));
128
129
  };
129
130
  exports.TimelineZoomControls = react_1.default.memo(TimelineZoomControlsInner);
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getSequenceContextMenuItems = exports.getMultiSequenceContextMenuItems = void 0;
4
4
  const no_react_1 = require("remotion/no-react");
5
5
  const format_file_location_1 = require("../../helpers/format-file-location");
6
+ const get_git_menu_item_1 = require("../../helpers/get-git-menu-item");
6
7
  const get_open_in_menu_items_1 = require("../get-open-in-menu-items");
7
8
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
8
9
  const actions_1 = require("../RenderQueue/actions");
@@ -68,6 +69,11 @@ const getSequenceContextMenuItems = ({ assetLinkInfo, canOpenInEditor, deleteDis
68
69
  const defaultEditorId = (0, use_default_editor_info_1.getPreferredEditorId)(editorInfo);
69
70
  const defaultEditor = installedEditors.find((editor) => editor.id === defaultEditorId);
70
71
  const editorName = (_e = defaultEditor === null || defaultEditor === void 0 ? void 0 : defaultEditor.nameWithType) !== null && _e !== void 0 ? _e : null;
72
+ const defaultOpenInTarget = (0, get_git_menu_item_1.getDefaultOpenInTarget)({ canOpenInEditor });
73
+ const gitSourceName = window.remotion_gitSource
74
+ ? (0, get_git_menu_item_1.getGitSourceName)(window.remotion_gitSource)
75
+ : null;
76
+ const defaultOpenInName = defaultOpenInTarget === 'editor' ? editorName : gitSourceName;
71
77
  const defaultCodingAgent = codingAgentInfo === null || codingAgentInfo === void 0 ? void 0 : codingAgentInfo.installedCodingAgents.find((codingAgent) => codingAgent.id === codingAgentInfo.defaultCodingAgent);
72
78
  const contextForAgents = (0, format_file_location_1.formatContextForAgents)({
73
79
  location: originalLocation,
@@ -103,18 +109,28 @@ const getSequenceContextMenuItems = ({ assetLinkInfo, canOpenInEditor, deleteDis
103
109
  })
104
110
  : [];
105
111
  const items = [
106
- editorName
112
+ defaultOpenInTarget && defaultOpenInName
107
113
  ? {
108
114
  type: 'item',
109
- id: 'open-in-editor',
115
+ id: defaultOpenInTarget === 'editor'
116
+ ? 'open-in-editor'
117
+ : 'open-in-git-source',
110
118
  keyHint: null,
111
- label: `Open in ${editorName}`,
119
+ label: `Open in ${defaultOpenInName}`,
112
120
  leftItem: null,
113
- disabled: !canOpenInEditor || !originalLocation,
114
- onClick: () => openInEditor(null),
121
+ disabled: !originalLocation,
122
+ onClick: () => {
123
+ if (defaultOpenInTarget === 'editor') {
124
+ openInEditor(null);
125
+ return;
126
+ }
127
+ (0, get_git_menu_item_1.openGitSource)({ folder: false, location: originalLocation });
128
+ },
115
129
  quickSwitcherLabel: null,
116
130
  subMenu: null,
117
- value: 'open-in-editor',
131
+ value: defaultOpenInTarget === 'editor'
132
+ ? 'open-in-editor'
133
+ : 'open-in-git-source',
118
134
  }
119
135
  : null,
120
136
  defaultCodingAgent
@@ -95,11 +95,14 @@ const formatNumberTimelineFieldValueForDisplay = ({ fieldSchema, value, }) => {
95
95
  const digits = (0, timeline_field_utils_1.getDecimalPlaces)(numericValue);
96
96
  return digits === 0 ? String(numericValue) : numericValue.toFixed(digits);
97
97
  }
98
- return (0, timeline_field_utils_1.formatTimelineNumber)({
99
- decimalPlaces: stepDecimals,
100
- fixed: true,
101
- value: numericValue,
102
- });
98
+ // The step controls increments, not the precision of source or typed values.
99
+ // Keep finer values while trimming floating point noise.
100
+ const normalizedValue = (0, timeline_field_utils_1.getDecimalPlaces)(numericValue) > stepDecimals
101
+ ? Number(numericValue.toPrecision(15))
102
+ : numericValue;
103
+ return (0, timeline_field_utils_1.getDecimalPlaces)(normalizedValue) > stepDecimals
104
+ ? String(normalizedValue)
105
+ : normalizedValue.toFixed(stepDecimals);
103
106
  };
104
107
  const formatRotationTimelineFieldValueForDisplay = ({ fieldSchema, value, }) => {
105
108
  const configuredStep = fieldSchema.type === 'rotation-css' ||
@@ -150,8 +153,10 @@ const formatTranslateTimelineFieldValueForDisplay = ({ fieldSchema, value, }) =>
150
153
  if (numericValue !== null) {
151
154
  return formatTranslateCoordinateForDisplay(numericValue, decimalPlaces);
152
155
  }
153
- const translate = (0, timeline_translate_utils_1.parseTranslate)(String(value !== null && value !== void 0 ? value : '0px 0px'));
154
- return (0, timeline_translate_utils_1.serializeTranslate)(translate, decimalPlaces);
156
+ const translate = (0, timeline_translate_utils_1.parseTranslateWithUnits)(String(value !== null && value !== void 0 ? value : '0px 0px'));
157
+ return translate === null
158
+ ? null
159
+ : (0, timeline_translate_utils_1.serializeTranslateWithUnits)(translate, decimalPlaces);
155
160
  };
156
161
  const formatTransformOriginAxisValueForDisplay = ({ decimalPlaces, unit, value, }) => {
157
162
  return `${(0, timeline_field_utils_1.formatTimelineNumber)({
@@ -1,3 +1,20 @@
1
1
  export type ParsedTranslate = readonly [number, number, number | null];
2
+ export type TranslateUnit = 'px' | '%';
3
+ export type ParsedTranslateWithUnits = readonly [
4
+ {
5
+ readonly value: number;
6
+ readonly unit: TranslateUnit;
7
+ },
8
+ {
9
+ readonly value: number;
10
+ readonly unit: TranslateUnit;
11
+ },
12
+ {
13
+ readonly value: number;
14
+ readonly unit: 'px';
15
+ } | null
16
+ ];
17
+ export declare const parseTranslateWithUnits: (value: string) => ParsedTranslateWithUnits | null;
2
18
  export declare const parseTranslate: (value: string) => ParsedTranslate;
3
19
  export declare const serializeTranslate: ([x, y, z]: ParsedTranslate, decimalPlaces?: number) => string;
20
+ export declare const serializeTranslateWithUnits: ([x, y, z]: ParsedTranslateWithUnits, decimalPlaces?: number) => string;
@@ -1,20 +1,53 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.serializeTranslate = exports.parseTranslate = void 0;
3
+ exports.serializeTranslateWithUnits = exports.serializeTranslate = exports.parseTranslate = exports.parseTranslateWithUnits = void 0;
4
4
  const timeline_field_utils_1 = require("./timeline-field-utils");
5
- const PIXEL_PATTERN = /^(-?\d+(?:\.\d+)?)px(?:\s+(-?\d+(?:\.\d+)?)px)?(?:\s+(-?\d+(?:\.\d+)?)px)?$/;
5
+ const TRANSLATE_PATTERN = /^(-?\d+(?:\.\d+)?)(px|%)?(?:\s+(-?\d+(?:\.\d+)?)(px|%)?)?(?:\s+(-?\d+(?:\.\d+)?)(px)?)?$/i;
6
6
  const translateDecimalPlaces = 1;
7
- const parseTranslate = (value) => {
8
- const m = value.match(PIXEL_PATTERN);
9
- if (!m) {
10
- return [0, 0, null];
7
+ const parseTranslateWithUnits = (value) => {
8
+ const match = value.match(TRANSLATE_PATTERN);
9
+ if (!match) {
10
+ return null;
11
+ }
12
+ const x = (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(match[1]));
13
+ const y = match[3] === undefined ? 0 : (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(match[3]));
14
+ const z = match[5] === undefined ? null : (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(match[5]));
15
+ if ((match[2] === undefined && x !== 0) ||
16
+ (match[3] !== undefined && match[4] === undefined && y !== 0) ||
17
+ (match[5] !== undefined && match[6] === undefined && z !== 0)) {
18
+ return null;
11
19
  }
12
20
  return [
13
- (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(m[1])),
14
- m[2] !== undefined ? (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(m[2])) : 0,
15
- m[3] !== undefined ? (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(m[3])) : null,
21
+ {
22
+ value: x,
23
+ unit: match[2] === undefined
24
+ ? 'px'
25
+ : match[2].toLowerCase(),
26
+ },
27
+ {
28
+ value: y,
29
+ unit: match[4] === undefined
30
+ ? 'px'
31
+ : match[4].toLowerCase(),
32
+ },
33
+ z === null
34
+ ? z
35
+ : {
36
+ value: z,
37
+ unit: 'px',
38
+ },
16
39
  ];
17
40
  };
41
+ exports.parseTranslateWithUnits = parseTranslateWithUnits;
42
+ const parseTranslate = (value) => {
43
+ var _a;
44
+ var _b;
45
+ const parsed = (0, exports.parseTranslateWithUnits)(value);
46
+ if (parsed === null || parsed[0].unit !== 'px' || parsed[1].unit !== 'px') {
47
+ return [0, 0, null];
48
+ }
49
+ return [parsed[0].value, parsed[1].value, (_b = (_a = parsed[2]) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : null];
50
+ };
18
51
  exports.parseTranslate = parseTranslate;
19
52
  const formatTranslateCoordinate = (value, decimalPlaces) => {
20
53
  const normalized = (0, timeline_field_utils_1.normalizeTimelineNumber)(value);
@@ -22,9 +55,17 @@ const formatTranslateCoordinate = (value, decimalPlaces) => {
22
55
  return String(Object.is(rounded, -0) ? 0 : rounded);
23
56
  };
24
57
  const serializeTranslate = ([x, y, z], decimalPlaces = translateDecimalPlaces) => {
25
- const xy = `${formatTranslateCoordinate(x, decimalPlaces)}px ${formatTranslateCoordinate(y, decimalPlaces)}px`;
58
+ return (0, exports.serializeTranslateWithUnits)([
59
+ { value: x, unit: 'px' },
60
+ { value: y, unit: 'px' },
61
+ z === null ? null : { value: z, unit: 'px' },
62
+ ], decimalPlaces);
63
+ };
64
+ exports.serializeTranslate = serializeTranslate;
65
+ const serializeTranslateWithUnits = ([x, y, z], decimalPlaces = translateDecimalPlaces) => {
66
+ const xy = `${formatTranslateCoordinate(x.value, decimalPlaces)}${x.unit} ${formatTranslateCoordinate(y.value, decimalPlaces)}${y.unit}`;
26
67
  return z === null
27
68
  ? xy
28
- : `${xy} ${formatTranslateCoordinate(z, decimalPlaces)}px`;
69
+ : `${xy} ${formatTranslateCoordinate(z.value, decimalPlaces)}${z.unit}`;
29
70
  };
30
- exports.serializeTranslate = serializeTranslate;
71
+ exports.serializeTranslateWithUnits = serializeTranslateWithUnits;
@@ -1,11 +1,13 @@
1
1
  import type { EditorPickerId } from '@remotion/studio-shared';
2
2
  import type { TSequence } from 'remotion';
3
3
  export declare const useOpenSequenceInApps: (sequence: TSequence) => {
4
+ canOpenSource: boolean;
4
5
  canOpenInEditor: boolean;
5
6
  canConfigureApps: boolean;
6
7
  codingAgentInfo: import("@remotion/studio-shared").GetDefaultCodingAgentInfoResponse | null;
7
8
  editorInfo: import("@remotion/studio-shared").GetDefaultEditorInfoResponse | null;
8
9
  openInCodingAgent: (codingAgentId: "claude-code" | "codex" | "copilot" | "cursor", codingAgentName: string, contextForAgents: string | null) => Promise<void>;
9
10
  openInEditor: (editorId: EditorPickerId | null) => Promise<void>;
11
+ openSource: () => void;
10
12
  originalLocation: import("remotion").ResolvedStackLocation | null;
11
13
  };
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useOpenSequenceInApps = void 0;
4
4
  const react_1 = require("react");
5
5
  const client_id_1 = require("../../helpers/client-id");
6
+ const get_git_menu_item_1 = require("../../helpers/get-git-menu-item");
6
7
  const open_in_editor_1 = require("../../helpers/open-in-editor");
7
8
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
8
9
  const use_default_editor_info_1 = require("../use-default-editor-info");
@@ -16,6 +17,8 @@ const useOpenSequenceInApps = (sequence) => {
16
17
  const { canConfigureApps, canOpenInEditor: editorAvailable, defaultEditorId, editorInfo, } = (0, use_default_editor_info_1.useEditorOpening)(previewConnected);
17
18
  const codingAgentInfo = (0, use_default_editor_info_1.useDefaultCodingAgentInfo)(canConfigureApps);
18
19
  const canOpenInEditor = (0, react_1.useMemo)(() => Boolean(editorAvailable && originalLocation), [editorAvailable, originalLocation]);
20
+ const defaultOpenInTarget = (0, get_git_menu_item_1.getDefaultOpenInTarget)({ canOpenInEditor });
21
+ const canOpenSource = defaultOpenInTarget !== null && originalLocation !== null;
19
22
  const openInEditor = (0, react_1.useCallback)(async (editorId) => {
20
23
  const resolvedEditorId = editorId !== null && editorId !== void 0 ? editorId : defaultEditorId;
21
24
  if (!canOpenInEditor || !originalLocation || !resolvedEditorId) {
@@ -28,6 +31,18 @@ const useOpenSequenceInApps = (sequence) => {
28
31
  (0, NotificationCenter_1.showNotification)(err.message, 2000);
29
32
  }
30
33
  }, [canOpenInEditor, defaultEditorId, originalLocation]);
34
+ const openSource = (0, react_1.useCallback)(() => {
35
+ if (!originalLocation) {
36
+ return;
37
+ }
38
+ if (defaultOpenInTarget === 'editor') {
39
+ openInEditor(null);
40
+ return;
41
+ }
42
+ if (defaultOpenInTarget === 'git-source') {
43
+ (0, get_git_menu_item_1.openGitSource)({ folder: false, location: originalLocation });
44
+ }
45
+ }, [defaultOpenInTarget, openInEditor, originalLocation]);
31
46
  const openInCodingAgent = (0, react_1.useCallback)(async (codingAgentId, codingAgentName, contextForAgents) => {
32
47
  try {
33
48
  const response = await (0, open_in_editor_1.openInCodingAgent)(codingAgentId, contextForAgents);
@@ -40,12 +55,14 @@ const useOpenSequenceInApps = (sequence) => {
40
55
  }
41
56
  }, []);
42
57
  return {
58
+ canOpenSource,
43
59
  canOpenInEditor,
44
60
  canConfigureApps,
45
61
  codingAgentInfo,
46
62
  editorInfo,
47
63
  openInCodingAgent,
48
64
  openInEditor,
65
+ openSource,
49
66
  originalLocation,
50
67
  };
51
68
  };
@@ -29,6 +29,7 @@ const useTimelineAssetDrop = () => {
29
29
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
30
30
  const [isAddingAsset, setIsAddingAsset] = (0, react_1.useState)(false);
31
31
  const [assetDropFrame, setAssetDropFrame] = (0, react_1.useState)(null);
32
+ const unsupportedDropNotifiedRef = (0, react_1.useRef)(false);
32
33
  const currentCompositionId = (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition' ? canvasContent.compositionId : null;
33
34
  const currentComposition = (0, react_1.useMemo)(() => {
34
35
  var _a;
@@ -71,9 +72,18 @@ const useTimelineAssetDrop = () => {
71
72
  dataTransfer === null ||
72
73
  !(0, drop_handler_data_1.isSupportedDropEvent)(event) ||
73
74
  !isEventTargetInsideElement(event, timeline)) {
75
+ unsupportedDropNotifiedRef.current = false;
74
76
  setAssetDropFrame(null);
75
77
  return;
76
78
  }
79
+ const mayBeCanvasCapture = (0, drop_handler_data_1.isFileDragEvent)(event) && !window.remotion_isReadOnlyStudio;
80
+ const shouldNotifyAboutUnsupportedDrop = (compositionComponentInfo === null || compositionComponentInfo === void 0 ? void 0 : compositionComponentInfo.canAddSequence) === false &&
81
+ !mayBeCanvasCapture;
82
+ if (shouldNotifyAboutUnsupportedDrop &&
83
+ !unsupportedDropNotifiedRef.current) {
84
+ (0, NotificationCenter_1.showCannotAddSequenceDropNotification)();
85
+ }
86
+ unsupportedDropNotifiedRef.current = shouldNotifyAboutUnsupportedDrop;
77
87
  event.preventDefault();
78
88
  event.stopPropagation();
79
89
  dataTransfer.dropEffect = canInsertAsset ? 'copy' : 'none';
@@ -82,8 +92,10 @@ const useTimelineAssetDrop = () => {
82
92
  scrollable !== null &&
83
93
  isEventTargetInsideElement(event, scrollable);
84
94
  setAssetDropFrame(shouldShowDropFrame ? getDropFrame(event) : null);
85
- }, [canInsertAsset, getDropFrame]);
95
+ }, [canInsertAsset, compositionComponentInfo === null || compositionComponentInfo === void 0 ? void 0 : compositionComponentInfo.canAddSequence, getDropFrame]);
86
96
  const onAssetDrop = (0, react_1.useCallback)(async (event) => {
97
+ const unsupportedDropWasNotified = unsupportedDropNotifiedRef.current;
98
+ unsupportedDropNotifiedRef.current = false;
87
99
  setAssetDropFrame(null);
88
100
  const timeline = timeline_refs_1.timelineVerticalScroll.current;
89
101
  const { dataTransfer } = event;
@@ -122,8 +134,9 @@ const useTimelineAssetDrop = () => {
122
134
  currentCompositionId === null ||
123
135
  compositionFile === null ||
124
136
  videoConfig === null) {
125
- if ((compositionComponentInfo === null || compositionComponentInfo === void 0 ? void 0 : compositionComponentInfo.canAddSequence) === false) {
126
- (0, NotificationCenter_1.showNotification)('Cannot insert items into this composition component', 3000);
137
+ if ((compositionComponentInfo === null || compositionComponentInfo === void 0 ? void 0 : compositionComponentInfo.canAddSequence) === false &&
138
+ !unsupportedDropWasNotified) {
139
+ (0, NotificationCenter_1.showCannotAddSequenceDropNotification)();
127
140
  }
128
141
  return;
129
142
  }
@@ -166,6 +179,7 @@ const useTimelineAssetDrop = () => {
166
179
  videoConfig,
167
180
  ]);
168
181
  const clearAssetDropFrame = (0, react_1.useCallback)(() => {
182
+ unsupportedDropNotifiedRef.current = false;
169
183
  setAssetDropFrame(null);
170
184
  }, []);
171
185
  (0, react_1.useEffect)(() => {
@@ -450,8 +450,8 @@ const useTimelineKeyframeDrag = ({ frame, nodePathInfo, onSelect, selectable, se
450
450
  event: e,
451
451
  captureTarget: e.currentTarget,
452
452
  onMove: onPointerMove,
453
- onEnd: (reason) => {
454
- if (reason === 'pointerup' || reason === 'buttons-released') {
453
+ onEnd: (reason, endEvent) => {
454
+ if ((0, pointer_session_1.isPointerSessionRelease)(reason, endEvent)) {
455
455
  onPointerUp();
456
456
  }
457
457
  else {
@@ -657,8 +657,8 @@ const useTimelineEasingKeyframeDrag = ({ onSelect, selectable, selected, selecti
657
657
  event: e,
658
658
  captureTarget: e.currentTarget,
659
659
  onMove: onPointerMove,
660
- onEnd: (reason) => {
661
- if (reason === 'pointerup' || reason === 'buttons-released') {
660
+ onEnd: (reason, endEvent) => {
661
+ if ((0, pointer_session_1.isPointerSessionRelease)(reason, endEvent)) {
662
662
  onPointerUp();
663
663
  }
664
664
  else {
@@ -5,6 +5,7 @@ export declare const TimelineCombobox: React.FC<{
5
5
  readonly values: ComboboxValue[];
6
6
  readonly selectedId: string | number;
7
7
  readonly title: string;
8
+ readonly tooltipDelay: number | null;
8
9
  readonly labelWidth?: number;
9
10
  readonly renderLeftItem?: RenderInlineAction;
10
11
  readonly unhoveredIconColor?: string;
@@ -4,6 +4,7 @@ exports.TimelineCombobox = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const colors_1 = require("../helpers/colors");
6
6
  const caret_1 = require("../icons/caret");
7
+ const ActionTooltip_1 = require("./ActionTooltip");
7
8
  const layout_1 = require("./layout");
8
9
  const SegmentedButton_1 = require("./SegmentedButton");
9
10
  const segmentedButtonStyle = {
@@ -21,7 +22,7 @@ const label = {
21
22
  userSelect: 'none',
22
23
  whiteSpace: 'nowrap',
23
24
  };
24
- const TimelineCombobox = ({ values, selectedId, title, labelWidth = 32, renderLeftItem, unhoveredIconColor = colors_1.LIGHT_TEXT, }) => {
25
+ const TimelineCombobox = ({ values, selectedId, title, tooltipDelay, labelWidth = 32, renderLeftItem, unhoveredIconColor = colors_1.LIGHT_TEXT, }) => {
25
26
  const selected = values.find((value) => value.id === selectedId);
26
27
  const segments = [
27
28
  {
@@ -32,16 +33,20 @@ const TimelineCombobox = ({ values, selectedId, title, labelWidth = 32, renderLe
32
33
  leaveLeftSpace: true,
33
34
  onOpenChange: null,
34
35
  renderContent: (color) => (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [renderLeftItem ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [renderLeftItem(color), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 })
35
- ] })) : null, selected ? (jsx_runtime_1.jsx("div", { title: typeof selected.label === 'string' ? selected.label : undefined, style: { ...label, width: labelWidth }, children: selected.label })) : null, jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(caret_1.CaretDown, { color: color })
36
+ ] })) : null, selected ? (jsx_runtime_1.jsx("div", { title: tooltipDelay === null && typeof selected.label === 'string'
37
+ ? selected.label
38
+ : undefined, style: { ...label, width: labelWidth }, children: selected.label })) : null, jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(caret_1.CaretDown, { color: color })
36
39
  ] })),
37
40
  segmentId: 'selector',
38
41
  selectedId,
39
42
  style: { fontFamily: 'inherit', padding: '0 4px' },
40
- title,
43
+ title: tooltipDelay === null ? title : null,
44
+ tooltipLabel: null,
41
45
  type: 'menu',
42
46
  values,
43
47
  },
44
48
  ];
45
- return (jsx_runtime_1.jsx(SegmentedButton_1.SegmentedButton, { segments: segments, style: segmentedButtonStyle, title: null }));
49
+ const button = (jsx_runtime_1.jsx(SegmentedButton_1.SegmentedButton, { segments: segments, style: segmentedButtonStyle, title: null }));
50
+ return tooltipDelay === null ? (button) : (jsx_runtime_1.jsx(ActionTooltip_1.ActionTooltip, { label: title, shortcut: null, delay: tooltipDelay, dismissOnClick: true, children: button }));
46
51
  };
47
52
  exports.TimelineCombobox = TimelineCombobox;
@@ -5,24 +5,13 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const player_1 = require("@remotion/player");
6
6
  const react_1 = require("react");
7
7
  const remotion_1 = require("remotion");
8
- const no_react_1 = require("remotion/no-react");
9
- const client_id_1 = require("../helpers/client-id");
10
8
  const colors_1 = require("../helpers/colors");
11
9
  const use_keybinding_1 = require("../helpers/use-keybinding");
10
+ const use_keyboard_shortcut_label_1 = require("../helpers/use-keyboard-shortcut-label");
12
11
  const timelineInOutPointer_1 = require("../icons/timelineInOutPointer");
13
12
  const in_out_1 = require("../state/in-out");
13
+ const ActionTooltip_1 = require("./ActionTooltip");
14
14
  const ControlButton_1 = require("./ControlButton");
15
- const keyboard_shortcuts_1 = require("./keyboard-shortcuts");
16
- const getTooltipText = (pointType, action) => {
17
- const shortcut = (0, keyboard_shortcuts_1.getKeyboardShortcutLabel)(action);
18
- return [
19
- `Mark ${pointType}`,
20
- (0, use_keybinding_1.areKeyboardShortcutsDisabled)() || shortcut === '' ? null : `(${shortcut})`,
21
- '- right click to clear',
22
- ]
23
- .filter(no_react_1.NoReactInternals.truthy)
24
- .join(' ');
25
- };
26
15
  const style = {
27
16
  width: 17,
28
17
  height: 17,
@@ -34,7 +23,11 @@ exports.inOutHandles = (0, react_1.createRef)();
34
23
  exports.defaultInOutValue = { inFrame: null, outFrame: null };
35
24
  const TimelineInOutPointToggle = () => {
36
25
  var _a;
37
- (0, client_id_1.useStudioConfigRevision)();
26
+ const inShortcut = (0, use_keyboard_shortcut_label_1.useKeyboardShortcutLabel)('setInPoint');
27
+ const outShortcut = (0, use_keyboard_shortcut_label_1.useKeyboardShortcutLabel)('setOutPoint');
28
+ const inAriaShortcut = (0, use_keyboard_shortcut_label_1.useKeyboardShortcutAriaKeyShortcuts)('setInPoint');
29
+ const outAriaShortcut = (0, use_keyboard_shortcut_label_1.useKeyboardShortcutAriaKeyShortcuts)('setOutPoint');
30
+ const shortcutsDisabled = (0, use_keybinding_1.areKeyboardShortcutsDisabled)();
38
31
  const { inFrame, outFrame } = (0, in_out_1.useTimelineInOutFramePosition)();
39
32
  const { setInAndOutFrames } = (0, in_out_1.useTimelineSetInOutFramePosition)();
40
33
  const videoConfig = remotion_1.Internals.useUnsafeVideoConfig();
@@ -249,7 +242,7 @@ const TimelineInOutPointToggle = () => {
249
242
  };
250
243
  }, [confId, onInMark, onInOutClear, onOutMark]);
251
244
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
252
- jsx_runtime_1.jsx(ControlButton_1.ControlButton, { title: getTooltipText('In', 'setInPoint'), "aria-label": getTooltipText('In', 'setInPoint'), style: buttonStyle, onClick: onInMark, onContextMenu: clearInMark, disabled: !videoConfig || isFirstFrame, children: (color) => (jsx_runtime_1.jsx(timelineInOutPointer_1.TimelineInPointer, { color: inFrame === null ? color : colors_1.BLUE, style: style })) }), jsx_runtime_1.jsx(ControlButton_1.ControlButton, { title: getTooltipText('Out', 'setOutPoint'), "aria-label": getTooltipText('Out', 'setOutPoint'), style: buttonStyle, onClick: onOutMark, onContextMenu: clearOutMark, disabled: !videoConfig || isLastFrame, children: (color) => (jsx_runtime_1.jsx(timelineInOutPointer_1.TimelineOutPointer, { color: outFrame === null ? color : colors_1.BLUE, style: style })) })
245
+ jsx_runtime_1.jsx(ActionTooltip_1.ActionTooltip, { label: "In point", shortcut: shortcutsDisabled ? null : inShortcut, delay: 800, dismissOnClick: true, children: jsx_runtime_1.jsx(ControlButton_1.ControlButton, { title: "", "aria-label": "In point", "aria-description": "Right click to clear", "aria-keyshortcuts": shortcutsDisabled ? undefined : inAriaShortcut || undefined, style: buttonStyle, onClick: onInMark, onContextMenu: clearInMark, disabled: !videoConfig || isFirstFrame, children: (color) => (jsx_runtime_1.jsx(timelineInOutPointer_1.TimelineInPointer, { color: inFrame === null ? color : colors_1.BLUE, style: style })) }) }), jsx_runtime_1.jsx(ActionTooltip_1.ActionTooltip, { label: "Out point", shortcut: shortcutsDisabled ? null : outShortcut, delay: 800, dismissOnClick: true, children: jsx_runtime_1.jsx(ControlButton_1.ControlButton, { title: "", "aria-label": "Out point", "aria-description": "Right click to clear", "aria-keyshortcuts": shortcutsDisabled ? undefined : outAriaShortcut || undefined, style: buttonStyle, onClick: onOutMark, onContextMenu: clearOutMark, disabled: !videoConfig || isLastFrame, children: (color) => (jsx_runtime_1.jsx(timelineInOutPointer_1.TimelineOutPointer, { color: outFrame === null ? color : colors_1.BLUE, style: style })) }) })
253
246
  ] }));
254
247
  };
255
248
  exports.TimelineInOutPointToggle = TimelineInOutPointToggle;
@@ -6,6 +6,7 @@ const react_1 = require("react");
6
6
  const browser_studio_operations_1 = require("../helpers/browser-studio-operations");
7
7
  const client_id_1 = require("../helpers/client-id");
8
8
  const colors_1 = require("../helpers/colors");
9
+ const url_state_1 = require("../helpers/url-state");
9
10
  const use_keybinding_1 = require("../helpers/use-keybinding");
10
11
  const use_keyboard_shortcut_label_1 = require("../helpers/use-keyboard-shortcut-label");
11
12
  const redo_1 = require("../icons/redo");
@@ -43,6 +44,11 @@ const UndoRedoButtons = () => {
43
44
  ? browserStudioOperations.undo()
44
45
  : (0, call_api_1.callApi)('/api/undo', {});
45
46
  promise
47
+ .then((response) => {
48
+ if (response.success && response.route !== null) {
49
+ (0, url_state_1.pushUrl)(response.route);
50
+ }
51
+ })
46
52
  .catch(() => {
47
53
  // Ignore errors
48
54
  })
@@ -60,6 +66,11 @@ const UndoRedoButtons = () => {
60
66
  ? browserStudioOperations.redo()
61
67
  : (0, call_api_1.callApi)('/api/redo', {});
62
68
  promise
69
+ .then((response) => {
70
+ if (response.success && response.route !== null) {
71
+ (0, url_state_1.pushUrl)(response.route);
72
+ }
73
+ })
63
74
  .catch(() => {
64
75
  // Ignore errors
65
76
  })