@remotion/studio 4.0.517 → 4.0.518

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 (52) hide show
  1. package/dist/components/AssetSelector.js +62 -21
  2. package/dist/components/AssetSelectorItem.d.ts +2 -1
  3. package/dist/components/AssetSelectorItem.js +41 -10
  4. package/dist/components/CaptionTextEditor.js +32 -8
  5. package/dist/components/CompositionContextButton.js +2 -1
  6. package/dist/components/CompositionSelector.js +1 -1
  7. package/dist/components/EditorContent.js +6 -3
  8. package/dist/components/ElementInstallConfirmation.d.ts +5 -0
  9. package/dist/components/ElementInstallConfirmation.js +25 -1
  10. package/dist/components/ElementLibraryModal.js +3 -1
  11. package/dist/components/InlineCaptionInspector.js +13 -2
  12. package/dist/components/Modals.js +49 -0
  13. package/dist/components/PlaybackRateSelector.js +2 -5
  14. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.d.ts +2 -0
  15. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.js +28 -8
  16. package/dist/components/SelectedOutlineKeyboardControls.d.ts +2 -2
  17. package/dist/components/SelectedOutlineOverlay.d.ts +1 -3
  18. package/dist/components/SelectedOutlineOverlay.js +21 -17
  19. package/dist/components/SelectedOutlineRenderer.d.ts +1 -1
  20. package/dist/components/SelectedOutlineRenderer.js +9 -78
  21. package/dist/components/SidebarRenderButton.js +2 -1
  22. package/dist/components/WebMcp.d.ts +2 -0
  23. package/dist/components/WebMcp.js +945 -0
  24. package/dist/components/composition-menu-items.js +26 -0
  25. package/dist/components/selected-outline-geometry.d.ts +2 -21
  26. package/dist/components/selected-outline-geometry.js +5 -16
  27. package/dist/components/selected-outline-measurement.d.ts +1 -29
  28. package/dist/components/selected-outline-measurement.js +1 -231
  29. package/dist/components/selected-outline-types.d.ts +2 -15
  30. package/dist/components/selected-outline-uv.js +3 -106
  31. package/dist/esm/{chunk-gzqm3g2m.js → chunk-7prjt5n5.js} +4782 -5611
  32. package/dist/esm/internals.mjs +4782 -5611
  33. package/dist/esm/previewEntry.mjs +4790 -5619
  34. package/dist/esm/renderEntry.mjs +1 -1
  35. package/dist/helpers/create-folder-tree.js +16 -1
  36. package/dist/helpers/format-file-location.d.ts +8 -0
  37. package/dist/helpers/format-file-location.js +14 -3
  38. package/dist/helpers/get-timeline-max-zoom.d.ts +8 -0
  39. package/dist/helpers/get-timeline-max-zoom.js +17 -6
  40. package/dist/helpers/hoverable.d.ts +1 -0
  41. package/dist/helpers/hoverable.js +4 -1
  42. package/dist/icons/enter.d.ts +4 -0
  43. package/dist/icons/enter.js +10 -0
  44. package/dist/state/playbackrate.d.ts +1 -0
  45. package/dist/state/playbackrate.js +4 -1
  46. package/package.json +14 -14
  47. package/dist/components/selected-outline-order.d.ts +0 -12
  48. package/dist/components/selected-outline-order.js +0 -251
  49. package/dist/helpers/get-box-quads-polyfill-internals.d.ts +0 -82
  50. package/dist/helpers/get-box-quads-polyfill-internals.js +0 -2403
  51. package/dist/helpers/get-box-quads-ponyfill.d.ts +0 -10
  52. package/dist/helpers/get-box-quads-ponyfill.js +0 -23
@@ -213,7 +213,7 @@ var renderContent = (Root) => {
213
213
  renderToDOM(/* @__PURE__ */ jsx("div", {
214
214
  children: /* @__PURE__ */ jsx(DelayedSpinner, {})
215
215
  }));
216
- import("./chunk-gzqm3g2m.js").then(({ StudioInternals }) => {
216
+ import("./chunk-7prjt5n5.js").then(({ StudioInternals }) => {
217
217
  window.remotion_isStudio = true;
218
218
  window.remotion_isReadOnlyStudio = true;
219
219
  window.remotion_inputProps = "{}";
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createFolderTree = exports.getKeysToExpand = exports.splitParentIntoNameAndParent = exports.buildAssetFolderStructure = void 0;
4
4
  const persist_open_folders_1 = require("./persist-open-folders");
5
+ const sort_by_nonce_history_1 = require("./sort-by-nonce-history");
5
6
  const buildAssetFolderStructure = (files, parentFolderName, foldersExpanded) => {
6
7
  const notInFolder = files.filter((f) => !f.name.includes('/'));
7
8
  const inFolder = files.filter((f) => f.name.includes('/'));
@@ -152,6 +153,20 @@ const createFolderTree = (comps, folders, foldersExpanded) => {
152
153
  const list = findItemListToPush(items, item.folderName, item.parentFolderName);
153
154
  list.push(toPush);
154
155
  }
155
- return items;
156
+ const sortTreeItems = (treeItems) => {
157
+ return (0, sort_by_nonce_history_1.sortItemsByNonceHistory)(treeItems.map((item) => ({
158
+ item,
159
+ nonce: item.type === 'folder' ? item.folder.nonce : item.composition.nonce,
160
+ }))).map(({ item }) => {
161
+ if (item.type === 'composition') {
162
+ return item;
163
+ }
164
+ return {
165
+ ...item,
166
+ items: sortTreeItems(item.items),
167
+ };
168
+ });
169
+ };
170
+ return sortTreeItems(items);
156
171
  };
157
172
  exports.createFolderTree = createFolderTree;
@@ -2,6 +2,14 @@ type FileLocation = {
2
2
  readonly source: string | null;
3
3
  readonly line: number | null;
4
4
  };
5
+ export type RelativeFileLocation = {
6
+ readonly filename: string;
7
+ readonly line: number;
8
+ };
9
+ export declare const getRelativeFileLocation: ({ location, root, }: {
10
+ readonly location: FileLocation | null;
11
+ readonly root: string;
12
+ }) => RelativeFileLocation | null;
5
13
  export declare const formatFileLocation: ({ location, root, }: {
6
14
  readonly location: FileLocation | null;
7
15
  readonly root: string;
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.formatContextForAgents = exports.formatFileLocation = void 0;
3
+ exports.formatContextForAgents = exports.formatFileLocation = exports.getRelativeFileLocation = void 0;
4
4
  const normalizeSlashes = (path) => path.replace(/\\/g, '/');
5
5
  const stripTrailingSlashes = (path) => path.replace(/\/+$/, '');
6
6
  const stripLeadingDotSlash = (path) => path.replace(/^\.\/+/, '');
7
- const formatFileLocation = ({ location, root, }) => {
7
+ const getRelativeFileLocation = ({ location, root, }) => {
8
8
  if (!(location === null || location === void 0 ? void 0 : location.source) || location.line === null) {
9
9
  return null;
10
10
  }
@@ -22,7 +22,18 @@ const formatFileLocation = ({ location, root, }) => {
22
22
  const relativeSource = sourceIsInsideRoot
23
23
  ? source.slice(normalizedRoot.length + 1)
24
24
  : source;
25
- return `${stripLeadingDotSlash(relativeSource)}:${location.line}`;
25
+ return {
26
+ filename: stripLeadingDotSlash(relativeSource),
27
+ line: location.line,
28
+ };
29
+ };
30
+ exports.getRelativeFileLocation = getRelativeFileLocation;
31
+ const formatFileLocation = ({ location, root, }) => {
32
+ const relativeLocation = (0, exports.getRelativeFileLocation)({ location, root });
33
+ if (relativeLocation === null) {
34
+ return null;
35
+ }
36
+ return `${relativeLocation.filename}:${relativeLocation.line}`;
26
37
  };
27
38
  exports.formatFileLocation = formatFileLocation;
28
39
  const formatContextForAgents = ({ name, location, root, }) => {
@@ -11,10 +11,18 @@ export declare const clampTimelineZoom: ({ zoom, durationInFrames, }: {
11
11
  zoom: number;
12
12
  durationInFrames: number;
13
13
  }) => number;
14
+ export declare const timelineZoomToNormalized: ({ zoom, maxZoom, }: {
15
+ zoom: number;
16
+ maxZoom: number;
17
+ }) => number;
14
18
  export declare const timelineZoomToSliderValue: ({ zoom, maxZoom, }: {
15
19
  zoom: number;
16
20
  maxZoom: number;
17
21
  }) => number;
22
+ export declare const normalizedToTimelineZoom: ({ normalized, maxZoom, }: {
23
+ normalized: number;
24
+ maxZoom: number;
25
+ }) => number;
18
26
  export declare const sliderValueToTimelineZoom: ({ sliderValue, maxZoom, }: {
19
27
  sliderValue: number;
20
28
  maxZoom: number;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TIMELINE_ZOOM_SLIDER_PROPS = exports.sliderValueToTimelineZoom = exports.timelineZoomToSliderValue = exports.clampTimelineZoom = exports.getTimelineMaxZoom = exports.TIMELINE_FRAMES_VISIBLE_AT_MAX_ZOOM = exports.TIMELINE_MAX_ZOOM_FLOOR = exports.TIMELINE_MIN_ZOOM = void 0;
3
+ exports.TIMELINE_ZOOM_SLIDER_PROPS = exports.sliderValueToTimelineZoom = exports.normalizedToTimelineZoom = exports.timelineZoomToSliderValue = exports.timelineZoomToNormalized = exports.clampTimelineZoom = exports.getTimelineMaxZoom = exports.TIMELINE_FRAMES_VISIBLE_AT_MAX_ZOOM = exports.TIMELINE_MAX_ZOOM_FLOOR = exports.TIMELINE_MIN_ZOOM = void 0;
4
4
  exports.TIMELINE_MIN_ZOOM = 1;
5
5
  exports.TIMELINE_MAX_ZOOM_FLOOR = 5;
6
6
  /**
@@ -20,23 +20,34 @@ const clampTimelineZoom = ({ zoom, durationInFrames, }) => {
20
20
  return Math.round(clamped * 10) / 10;
21
21
  };
22
22
  exports.clampTimelineZoom = clampTimelineZoom;
23
- const timelineZoomToSliderValue = ({ zoom, maxZoom, }) => {
23
+ const timelineZoomToNormalized = ({ zoom, maxZoom, }) => {
24
24
  if (maxZoom <= exports.TIMELINE_MIN_ZOOM) {
25
25
  return 0;
26
26
  }
27
27
  const clampedZoom = Math.min(maxZoom, Math.max(exports.TIMELINE_MIN_ZOOM, zoom));
28
- const t = Math.log(clampedZoom / exports.TIMELINE_MIN_ZOOM) /
28
+ const normalized = Math.log(clampedZoom / exports.TIMELINE_MIN_ZOOM) /
29
29
  Math.log(maxZoom / exports.TIMELINE_MIN_ZOOM);
30
- return Math.round(t * TIMELINE_ZOOM_SLIDER_MAX);
30
+ return (Math.round(normalized * TIMELINE_ZOOM_SLIDER_MAX) / TIMELINE_ZOOM_SLIDER_MAX);
31
+ };
32
+ exports.timelineZoomToNormalized = timelineZoomToNormalized;
33
+ const timelineZoomToSliderValue = ({ zoom, maxZoom, }) => {
34
+ return Math.round((0, exports.timelineZoomToNormalized)({ zoom, maxZoom }) * TIMELINE_ZOOM_SLIDER_MAX);
31
35
  };
32
36
  exports.timelineZoomToSliderValue = timelineZoomToSliderValue;
33
- const sliderValueToTimelineZoom = ({ sliderValue, maxZoom, }) => {
37
+ const normalizedToTimelineZoom = ({ normalized, maxZoom, }) => {
34
38
  if (maxZoom <= exports.TIMELINE_MIN_ZOOM) {
35
39
  return exports.TIMELINE_MIN_ZOOM;
36
40
  }
37
- const t = sliderValue / TIMELINE_ZOOM_SLIDER_MAX;
41
+ const t = Math.min(1, Math.max(0, normalized));
38
42
  return exports.TIMELINE_MIN_ZOOM * (maxZoom / exports.TIMELINE_MIN_ZOOM) ** t;
39
43
  };
44
+ exports.normalizedToTimelineZoom = normalizedToTimelineZoom;
45
+ const sliderValueToTimelineZoom = ({ sliderValue, maxZoom, }) => {
46
+ return (0, exports.normalizedToTimelineZoom)({
47
+ normalized: sliderValue / TIMELINE_ZOOM_SLIDER_MAX,
48
+ maxZoom,
49
+ });
50
+ };
40
51
  exports.sliderValueToTimelineZoom = sliderValueToTimelineZoom;
41
52
  exports.TIMELINE_ZOOM_SLIDER_PROPS = {
42
53
  min: 0,
@@ -3,6 +3,7 @@ export declare const HOVERABLE_CLASS_NAME = "__remotion-hoverable";
3
3
  export declare const HOVER_GROUP_CLASS_NAME = "__remotion-hover-group";
4
4
  export declare const HOVER_GROUP_REVEAL_CLASS_NAME = "__remotion-hover-group-reveal";
5
5
  export declare const FOCUS_VISIBLE_ONLY_CLASS_NAME = "__remotion-focus-visible-only";
6
+ export declare const NO_HOVER_BACKGROUND_STYLE: React.CSSProperties;
6
7
  export declare const hoverableStyle: ({ idleBackground, hoverBackground, idleColor, hoverColor, }: {
7
8
  idleBackground: string;
8
9
  hoverBackground: string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.makeHoverableCSS = exports.hoverableStyle = exports.FOCUS_VISIBLE_ONLY_CLASS_NAME = exports.HOVER_GROUP_REVEAL_CLASS_NAME = exports.HOVER_GROUP_CLASS_NAME = exports.HOVERABLE_CLASS_NAME = void 0;
3
+ exports.makeHoverableCSS = exports.hoverableStyle = exports.NO_HOVER_BACKGROUND_STYLE = exports.FOCUS_VISIBLE_ONLY_CLASS_NAME = exports.HOVER_GROUP_REVEAL_CLASS_NAME = exports.HOVER_GROUP_CLASS_NAME = exports.HOVERABLE_CLASS_NAME = void 0;
4
4
  const colors_1 = require("./colors");
5
5
  // Purely visual hover styling must be driven by CSS `:hover` rather than
6
6
  // React state: When the Studio runs in an <iframe> (like in Browser Studio),
@@ -16,6 +16,9 @@ const BG_VARIABLE = '--remotion-hoverable-bg';
16
16
  const HOVER_BG_VARIABLE = '--remotion-hoverable-hover-bg';
17
17
  const COLOR_VARIABLE = '--remotion-hoverable-color';
18
18
  const HOVER_COLOR_VARIABLE = '--remotion-hoverable-hover-color';
19
+ exports.NO_HOVER_BACKGROUND_STYLE = {
20
+ [HOVER_BG_VARIABLE]: colors_1.TRANSPARENT,
21
+ };
19
22
  // To disable the hover effect (e.g. for a disabled control), pass the idle
20
23
  // values as the hover values.
21
24
  const hoverableStyle = ({ idleBackground, hoverBackground, idleColor, hoverColor, }) => {
@@ -0,0 +1,4 @@
1
+ import type { SVGProps } from 'react';
2
+ export declare const EnterIcon: React.FC<SVGProps<SVGSVGElement> & {
3
+ readonly color: string;
4
+ }>;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EnterIcon = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ // Font Awesome Pro v7.3.1, Copyright 2026 Fonticons, Inc.
6
+ // https://fontawesome.com/license (Commercial License)
7
+ const EnterIcon = ({ color, ...props }) => {
8
+ return (jsx_runtime_1.jsx("svg", { ...props, xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 640 640", children: jsx_runtime_1.jsx("path", { fill: color, d: "M544 144C544 135.2 551.2 128 560 128C568.8 128 576 135.2 576 144L576 240C576 293 533 336 480 336L118.6 336L235.3 452.7C241.5 458.9 241.5 469.1 235.3 475.3C229.1 481.5 218.9 481.5 212.7 475.3L68.7 331.3C65.7 328.3 64 324.2 64 320C64 315.8 65.7 311.7 68.7 308.7L212.7 164.7C218.9 158.5 229.1 158.5 235.3 164.7C241.5 170.9 241.5 181.1 235.3 187.3L118.6 304L480 304C515.3 304 544 275.3 544 240L544 144z" }) }));
9
+ };
10
+ exports.EnterIcon = EnterIcon;
@@ -1,2 +1,3 @@
1
+ export declare const commonPlaybackRates: number[];
1
2
  export declare const persistPlaybackRate: (option: number) => void;
2
3
  export declare const loadPlaybackRate: () => number;
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.loadPlaybackRate = exports.persistPlaybackRate = void 0;
3
+ exports.loadPlaybackRate = exports.persistPlaybackRate = exports.commonPlaybackRates = void 0;
4
4
  const key = 'remotion.playbackrate';
5
+ exports.commonPlaybackRates = [
6
+ -4, -2, -1, -0.5, -0.25, 0.25, 0.5, 1, 1.5, 2, 4,
7
+ ];
5
8
  const persistPlaybackRate = (option) => {
6
9
  localStorage.setItem(key, String(option));
7
10
  };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/studio"
4
4
  },
5
5
  "name": "@remotion/studio",
6
- "version": "4.0.517",
6
+ "version": "4.0.518",
7
7
  "description": "APIs for interacting with the Remotion Studio",
8
8
  "main": "dist",
9
9
  "scripts": {
@@ -25,19 +25,19 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@tanstack/react-virtual": "3.14.9",
28
- "@remotion/canvas": "4.0.517",
29
- "@remotion/studio-protocol": "4.0.517",
28
+ "@remotion/canvas": "4.0.518",
29
+ "@remotion/studio-protocol": "4.0.518",
30
30
  "semver": "7.5.3",
31
- "remotion": "4.0.517",
32
- "@remotion/captions": "4.0.517",
33
- "@remotion/media": "4.0.517",
34
- "@remotion/player": "4.0.517",
35
- "@remotion/media-utils": "4.0.517",
36
- "@remotion/renderer": "4.0.517",
37
- "@remotion/web-renderer": "4.0.517",
38
- "@remotion/studio-shared": "4.0.517",
39
- "@remotion/timeline-utils": "4.0.517",
40
- "@remotion/zod-types": "4.0.517",
31
+ "remotion": "4.0.518",
32
+ "@remotion/captions": "4.0.518",
33
+ "@remotion/media": "4.0.518",
34
+ "@remotion/player": "4.0.518",
35
+ "@remotion/media-utils": "4.0.518",
36
+ "@remotion/renderer": "4.0.518",
37
+ "@remotion/web-renderer": "4.0.518",
38
+ "@remotion/studio-shared": "4.0.518",
39
+ "@remotion/timeline-utils": "4.0.518",
40
+ "@remotion/zod-types": "4.0.518",
41
41
  "@jridgewell/trace-mapping": "0.3.31",
42
42
  "mediabunny": "1.55.1",
43
43
  "memfs": "3.4.3",
@@ -48,7 +48,7 @@
48
48
  "react": "19.2.3",
49
49
  "react-dom": "19.2.3",
50
50
  "@types/semver": "7.5.3",
51
- "@remotion/eslint-config-internal": "4.0.517",
51
+ "@remotion/eslint-config-internal": "4.0.518",
52
52
  "eslint": "9.19.0",
53
53
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
54
54
  },
@@ -1,12 +0,0 @@
1
- import type { SelectedOutline } from './selected-outline-geometry';
2
- import type { SelectedOutlineLayoutTarget } from './selected-outline-types';
3
- type OutlineSequenceParent = {
4
- readonly id: string;
5
- readonly parent: string | null;
6
- };
7
- export declare const orderOutlinesForRendering: ({ outlines, sequences, targetsByKey, }: {
8
- readonly outlines: readonly SelectedOutline[];
9
- readonly sequences: readonly OutlineSequenceParent[];
10
- readonly targetsByKey: ReadonlyMap<string, SelectedOutlineLayoutTarget>;
11
- }) => readonly SelectedOutline[];
12
- export {};
@@ -1,251 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.orderOutlinesForRendering = void 0;
4
- const outlinePointEqualityTolerance = 0.5;
5
- const outlineAreaEqualityTolerance = 0.5;
6
- const outlineBoundsOverlapTolerance = 0.5;
7
- const outlinePointsAreEquivalent = (a, b) => {
8
- return (Math.abs(a.x - b.x) <= outlinePointEqualityTolerance &&
9
- Math.abs(a.y - b.y) <= outlinePointEqualityTolerance);
10
- };
11
- const outlinesHaveEquivalentHitArea = (a, b) => {
12
- if (a.points.length !== b.points.length) {
13
- return false;
14
- }
15
- for (let startIndex = 0; startIndex < b.points.length; startIndex++) {
16
- for (const direction of [1, -1]) {
17
- const pointsMatch = a.points.every((point, index) => {
18
- const bIndex = (startIndex + direction * index + b.points.length) % b.points.length;
19
- return outlinePointsAreEquivalent(point, b.points[bIndex]);
20
- });
21
- if (pointsMatch) {
22
- return true;
23
- }
24
- }
25
- }
26
- return false;
27
- };
28
- const getOutlineHitArea = (outline) => {
29
- let area = 0;
30
- for (let i = 0; i < outline.points.length; i++) {
31
- const current = outline.points[i];
32
- const next = outline.points[(i + 1) % outline.points.length];
33
- area += current.x * next.y - next.x * current.y;
34
- }
35
- return Math.abs(area) / 2;
36
- };
37
- const getOutlineBounds = (outline) => {
38
- const xs = outline.points.map((point) => point.x);
39
- const ys = outline.points.map((point) => point.y);
40
- return {
41
- maxX: Math.max(...xs),
42
- maxY: Math.max(...ys),
43
- minX: Math.min(...xs),
44
- minY: Math.min(...ys),
45
- };
46
- };
47
- const outlineBoundsOverlap = (a, b) => {
48
- const aBounds = getOutlineBounds(a);
49
- const bBounds = getOutlineBounds(b);
50
- return (aBounds.minX <= bBounds.maxX + outlineBoundsOverlapTolerance &&
51
- aBounds.maxX + outlineBoundsOverlapTolerance >= bBounds.minX &&
52
- aBounds.minY <= bBounds.maxY + outlineBoundsOverlapTolerance &&
53
- aBounds.maxY + outlineBoundsOverlapTolerance >= bBounds.minY);
54
- };
55
- const getSequenceId = (target) => {
56
- var _a;
57
- var _b;
58
- return (_b = (_a = target === null || target === void 0 ? void 0 : target.sequence) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : null;
59
- };
60
- const getParentBySequenceId = ({ sequences, targetsByKey, }) => {
61
- const parentBySequenceId = new Map();
62
- for (const sequence of sequences) {
63
- parentBySequenceId.set(sequence.id, sequence.parent);
64
- }
65
- for (const target of targetsByKey.values()) {
66
- const sequenceId = getSequenceId(target);
67
- if (sequenceId !== null && !parentBySequenceId.has(sequenceId)) {
68
- parentBySequenceId.set(sequenceId, target.sequence.parent);
69
- }
70
- }
71
- return parentBySequenceId;
72
- };
73
- const isAncestorTarget = ({ ancestor, descendant, parentBySequenceId, }) => {
74
- var _a;
75
- var _b, _c;
76
- const ancestorId = getSequenceId(ancestor);
77
- if (ancestorId === null) {
78
- return false;
79
- }
80
- let parentId = (_b = (_a = descendant.sequence) === null || _a === void 0 ? void 0 : _a.parent) !== null && _b !== void 0 ? _b : null;
81
- while (parentId !== null) {
82
- if (parentId === ancestorId) {
83
- return true;
84
- }
85
- parentId = (_c = parentBySequenceId.get(parentId)) !== null && _c !== void 0 ? _c : null;
86
- }
87
- return false;
88
- };
89
- const orderOutlineGroup = ({ outlines, parentBySequenceId, targetsByKey, }) => {
90
- var _a;
91
- var _b, _c, _d, _e;
92
- const incomingEdges = new Map();
93
- const outgoingEdges = new Map();
94
- const outlinesByKey = new Map(outlines.map((outline) => [outline.key, outline]));
95
- for (const outline of outlines) {
96
- incomingEdges.set(outline.key, new Set());
97
- outgoingEdges.set(outline.key, new Set());
98
- }
99
- const hasPath = ({ fromKey, seen, toKey, }) => {
100
- var _a;
101
- if (fromKey === toKey) {
102
- return true;
103
- }
104
- if (seen.has(fromKey)) {
105
- return false;
106
- }
107
- seen.add(fromKey);
108
- for (const nextKey of (_a = outgoingEdges.get(fromKey)) !== null && _a !== void 0 ? _a : []) {
109
- if (hasPath({ fromKey: nextKey, seen, toKey })) {
110
- return true;
111
- }
112
- }
113
- return false;
114
- };
115
- const addEdge = (before, after, options) => {
116
- if (before.key === after.key) {
117
- return;
118
- }
119
- const incoming = incomingEdges.get(after.key);
120
- const outgoing = outgoingEdges.get(before.key);
121
- if (incoming === undefined || outgoing === undefined) {
122
- throw new Error('Expected outline to be registered before adding edge');
123
- }
124
- if (outgoing.has(after.key)) {
125
- return;
126
- }
127
- if (hasPath({ fromKey: after.key, seen: new Set(), toKey: before.key })) {
128
- if (options === null || options === void 0 ? void 0 : options.skipIfCycle) {
129
- return;
130
- }
131
- throw new Error('Could not determine a stable outline rendering order');
132
- }
133
- incoming.add(before.key);
134
- outgoing.add(after.key);
135
- };
136
- const addAncestorConstraint = ({ ancestor, descendant, descendantContainsSelection, equivalentHitArea, }) => {
137
- // Usually, children should be above parents so nested elements are directly
138
- // selectable. If an unselected child has the same hit area as its parent, put
139
- // it below the parent so the wrapper can be selected. Once the child or
140
- // one of its properties is selected, keep it above the parent so it remains
141
- // directly draggable.
142
- if (equivalentHitArea && !descendantContainsSelection) {
143
- addEdge(descendant, ancestor);
144
- }
145
- else {
146
- addEdge(ancestor, descendant);
147
- }
148
- };
149
- const outlineBySequenceId = new Map();
150
- for (const outline of outlines) {
151
- const sequenceId = getSequenceId(targetsByKey.get(outline.key));
152
- if (sequenceId !== null) {
153
- outlineBySequenceId.set(sequenceId, outline);
154
- }
155
- }
156
- // Only constrain each outline against its nearest rendered ancestor. The
157
- // resulting graph follows the sequence tree, so pairwise subpixel equivalence
158
- // cannot introduce contradictory edges across three nested outlines.
159
- for (const descendant of outlines) {
160
- const descendantTarget = targetsByKey.get(descendant.key);
161
- let parentId = (_b = (_a = descendantTarget === null || descendantTarget === void 0 ? void 0 : descendantTarget.sequence) === null || _a === void 0 ? void 0 : _a.parent) !== null && _b !== void 0 ? _b : null;
162
- while (parentId !== null) {
163
- const ancestor = outlineBySequenceId.get(parentId);
164
- if (ancestor !== undefined) {
165
- addAncestorConstraint({
166
- ancestor,
167
- descendant,
168
- descendantContainsSelection: ((_c = descendantTarget === null || descendantTarget === void 0 ? void 0 : descendantTarget.selected) !== null && _c !== void 0 ? _c : false) ||
169
- ((_d = descendantTarget === null || descendantTarget === void 0 ? void 0 : descendantTarget.containsSelection) !== null && _d !== void 0 ? _d : false),
170
- equivalentHitArea: outlinesHaveEquivalentHitArea(ancestor, descendant),
171
- });
172
- break;
173
- }
174
- parentId = (_e = parentBySequenceId.get(parentId)) !== null && _e !== void 0 ? _e : null;
175
- }
176
- }
177
- // For unrelated overlapping outlines, put broader hit targets below
178
- // smaller ones so a large selected sequence cannot swallow clicks on
179
- // a more specific element in the same canvas area.
180
- for (let i = 0; i < outlines.length; i++) {
181
- for (let j = i + 1; j < outlines.length; j++) {
182
- const a = outlines[i];
183
- const b = outlines[j];
184
- const aTarget = targetsByKey.get(a.key);
185
- const bTarget = targetsByKey.get(b.key);
186
- if (aTarget === undefined || bTarget === undefined) {
187
- continue;
188
- }
189
- const aAncestorOfB = isAncestorTarget({
190
- ancestor: aTarget,
191
- descendant: bTarget,
192
- parentBySequenceId,
193
- });
194
- const bAncestorOfA = isAncestorTarget({
195
- ancestor: bTarget,
196
- descendant: aTarget,
197
- parentBySequenceId,
198
- });
199
- if (aAncestorOfB || bAncestorOfA || !outlineBoundsOverlap(a, b)) {
200
- continue;
201
- }
202
- const aArea = getOutlineHitArea(a);
203
- const bArea = getOutlineHitArea(b);
204
- if (Math.abs(aArea - bArea) <= outlineAreaEqualityTolerance) {
205
- continue;
206
- }
207
- if (aArea > bArea) {
208
- addEdge(a, b, { skipIfCycle: true });
209
- }
210
- else {
211
- addEdge(b, a, { skipIfCycle: true });
212
- }
213
- }
214
- }
215
- const emitted = new Set();
216
- const visiting = new Set();
217
- const ordered = [];
218
- const visit = (outline) => {
219
- var _a;
220
- if (emitted.has(outline.key)) {
221
- return;
222
- }
223
- if (visiting.has(outline.key)) {
224
- throw new Error('Could not determine a stable outline rendering order');
225
- }
226
- visiting.add(outline.key);
227
- for (const dependencyKey of (_a = incomingEdges.get(outline.key)) !== null && _a !== void 0 ? _a : []) {
228
- const dependency = outlinesByKey.get(dependencyKey);
229
- if (dependency === undefined) {
230
- throw new Error('Expected outline dependency to exist');
231
- }
232
- visit(dependency);
233
- }
234
- visiting.delete(outline.key);
235
- emitted.add(outline.key);
236
- ordered.push(outline);
237
- };
238
- for (const outline of outlines) {
239
- visit(outline);
240
- }
241
- return ordered;
242
- };
243
- const orderOutlinesForRendering = ({ outlines, sequences, targetsByKey, }) => {
244
- const parentBySequenceId = getParentBySequenceId({ sequences, targetsByKey });
245
- return orderOutlineGroup({
246
- outlines,
247
- parentBySequenceId,
248
- targetsByKey,
249
- });
250
- };
251
- exports.orderOutlinesForRendering = orderOutlinesForRendering;
@@ -1,82 +0,0 @@
1
- /**
2
- * @param {globalThis} windowObj?
3
- * @param {boolean=} force
4
- */
5
- export declare function addPolyfill(windowObj?: globalThis, force?: boolean | undefined): void;
6
- /**
7
- * @param {globalThis} windowObj?
8
- */
9
- export declare function patchAdoptNode(windowObj?: globalThis): void;
10
- /**
11
- * @param {Node} node
12
- * @param {DOMQuadInit} quad
13
- * @param {Element} from
14
- * @param {{fromBox?: 'margin'|'border'|'padding'|'content', toBox?: 'margin'|'border'|'padding'|'content', iframes?: HTMLIFrameElement[]}=} options
15
- * @returns {DOMQuad}
16
- */
17
- export declare function convertQuadFromNode(node: Node, quad: DOMQuadInit, from: Element, options?: {
18
- fromBox?: 'margin' | 'border' | 'padding' | 'content';
19
- toBox?: 'margin' | 'border' | 'padding' | 'content';
20
- iframes?: HTMLIFrameElement[];
21
- } | undefined): DOMQuad;
22
- /**
23
- * @param {Node} node
24
- * @param {{x: number, y: number, width: number, height: number}} rect
25
- * @param {Element} from
26
- * @param {{fromBox?: 'margin'|'border'|'padding'|'content', toBox?: 'margin'|'border'|'padding'|'content', iframes?: HTMLIFrameElement[]}=} options
27
- * @returns {DOMQuad}
28
- */
29
- export declare function convertRectFromNode(node: Node, rect: {
30
- x: number;
31
- y: number;
32
- width: number;
33
- height: number;
34
- }, from: Element, options?: {
35
- fromBox?: 'margin' | 'border' | 'padding' | 'content';
36
- toBox?: 'margin' | 'border' | 'padding' | 'content';
37
- iframes?: HTMLIFrameElement[];
38
- } | undefined): DOMQuad;
39
- /**
40
- * @param {Node} node
41
- * @param {DOMPointInit} point
42
- * @param {Element} from
43
- * @param {{fromBox?: 'margin'|'border'|'padding'|'content', toBox?: 'margin'|'border'|'padding'|'content', iframes?: HTMLIFrameElement[]}=} options
44
- * @returns {DOMPoint}
45
- */
46
- export declare function convertPointFromNode(node: Node, point: DOMPointInit, from: Element, options?: {
47
- fromBox?: 'margin' | 'border' | 'padding' | 'content';
48
- toBox?: 'margin' | 'border' | 'padding' | 'content';
49
- iframes?: HTMLIFrameElement[];
50
- } | undefined): DOMPoint;
51
- export declare function clearCache(): void;
52
- export declare function useCache(): void;
53
- /**
54
- * @param {Node} node
55
- * @param {{box?: 'margin'|'border'|'padding'|'content', relativeTo?: Element, iframes?: HTMLIFrameElement[]}=} options
56
- * @returns {DOMQuad[]}
57
- */
58
- export declare function getBoxQuads(node: Node, options?: {
59
- box?: 'margin' | 'border' | 'padding' | 'content';
60
- relativeTo?: Element;
61
- iframes?: HTMLIFrameElement[];
62
- } | undefined): DOMQuad[];
63
- /**
64
- * @param {Node} node
65
- * @param {DOMMatrix=} matrix
66
- */
67
- export declare function getElementSize(node: Node, matrix?: DOMMatrix | undefined): {
68
- width: number;
69
- height: number;
70
- };
71
- /**
72
- * @param {Node} node
73
- * @param {Element} ancestor
74
- * @param {HTMLIFrameElement[]} iframes
75
- * @param {boolean=} excludeSelfZoom
76
- */
77
- export declare function getResultingTransformationBetweenElementAndAllAncestors(node: Node, ancestor: Element, iframes: HTMLIFrameElement[], excludeSelfZoom?: boolean | undefined): DOMMatrix;
78
- /**
79
- * @param {Node} element
80
- * @param {HTMLIFrameElement[]=} iframes
81
- */
82
- export declare function getElementCombinedTransform(element: Node, iframes?: HTMLIFrameElement[] | undefined): DOMMatrix;