@replohq/sandbox-runtime 1.7.12 → 1.8.0

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.
@@ -1,6 +1,7 @@
1
1
  import { useCallback } from "react";
2
2
  import { buildGoogleFontsCssUrl, quoteFontFamily } from "../../_vendor/replo-utils/lib/fonts.mjs";
3
3
  import { buildSelector } from "../descriptor/elementDescriptor";
4
+ import { createImagePreview } from "../imageOverridePreview";
4
5
  import {
5
6
  SELECT_MODE_OVERRIDE_ATTRIBUTE,
6
7
  SELECT_MODE_OVERRIDE_STYLE_ATTRIBUTE
@@ -10,6 +11,7 @@ const OVERRIDE_REGISTRATION_TIMEOUT_MS = 15e3;
10
11
  const SESSION_OUTCOME_RETENTION_MS = 6e4;
11
12
  const OVERRIDE_REGISTRY_KEY = "reploSelectOverrideRegistryV2";
12
13
  const SESSION_OUTCOME_REGISTRY_KEY = "reploSelectOverrideSessionOutcomesV2";
14
+ const imagePreviews = /* @__PURE__ */ new Map();
13
15
  function getOverrideList() {
14
16
  const existing = Reflect.get(window, OVERRIDE_REGISTRY_KEY);
15
17
  if (Array.isArray(existing)) {
@@ -45,18 +47,12 @@ function getElementsForTargetMode({
45
47
  })
46
48
  ];
47
49
  }
48
- function isImageSourcePayload({
49
- element,
50
- payload
51
- }) {
52
- return payload.kind === "attribute" && payload.name.toLowerCase() === "src" && element instanceof HTMLImageElement;
53
- }
54
50
  function getOriginalState({
55
51
  element,
56
52
  payload
57
53
  }) {
58
54
  if (payload.kind === "attribute") {
59
- const names = isImageSourcePayload({ element, payload }) ? [payload.name, "srcset"] : [payload.name];
55
+ const names = [payload.name];
60
56
  return {
61
57
  kind: "attributes",
62
58
  values: names.map((name) => ({
@@ -95,14 +91,12 @@ function applyPayload({
95
91
  payload,
96
92
  token
97
93
  }) {
94
+ if (payload.kind === "image") return;
98
95
  if (payload.kind === "css") {
99
96
  addToken(element, token);
100
97
  return;
101
98
  }
102
99
  if (payload.kind === "attribute") {
103
- if (isImageSourcePayload({ element, payload })) {
104
- element.removeAttribute("srcset");
105
- }
106
100
  element.setAttribute(payload.name, payload.value);
107
101
  return;
108
102
  }
@@ -207,6 +201,7 @@ function reapplyOverride({
207
201
  override,
208
202
  skipElement
209
203
  }) {
204
+ if (override.payload.kind === "image") return;
210
205
  for (const target of override.targets) {
211
206
  const element = resolveTarget(target);
212
207
  if (!element || skipElement && element.contains(skipElement)) {
@@ -222,6 +217,51 @@ function reapplyOverride({
222
217
  applyPayload({ element, payload: override.payload, token: override.token });
223
218
  }
224
219
  }
220
+ function syncImagePreviews() {
221
+ const configurations = /* @__PURE__ */ new Map();
222
+ for (const override of getOverrideList()) {
223
+ if (override.payload.kind !== "image") continue;
224
+ for (const target of override.targets) {
225
+ const element = resolveTarget(target);
226
+ if (!(element instanceof HTMLImageElement)) continue;
227
+ const previous = configurations.get(element);
228
+ configurations.set(element, {
229
+ image: override.payload.image,
230
+ pending: !override.settled || Boolean(previous?.pending)
231
+ });
232
+ }
233
+ }
234
+ for (const [element, preview] of imagePreviews) {
235
+ if (configurations.has(element)) continue;
236
+ preview.dispose();
237
+ imagePreviews.delete(element);
238
+ }
239
+ const acknowledged = /* @__PURE__ */ new Set();
240
+ for (const [element, configuration] of configurations) {
241
+ let preview = imagePreviews.get(element);
242
+ if (!preview) {
243
+ preview = createImagePreview(element);
244
+ imagePreviews.set(element, preview);
245
+ }
246
+ if (!configuration.pending && preview.isPersisted(configuration.image)) {
247
+ preview.dispose();
248
+ imagePreviews.delete(element);
249
+ acknowledged.add(element);
250
+ } else {
251
+ preview.render(configuration.image);
252
+ }
253
+ }
254
+ setOverrideList(
255
+ getOverrideList().filter((entry) => {
256
+ if (entry.payload.kind !== "image") return true;
257
+ entry.targets = entry.targets.filter((target) => {
258
+ const element = resolveTarget(target);
259
+ return !element || !acknowledged.has(element);
260
+ });
261
+ return entry.targets.length > 0;
262
+ })
263
+ );
264
+ }
225
265
  function removeOverride({
226
266
  editId,
227
267
  outcome
@@ -233,6 +273,16 @@ function removeOverride({
233
273
  return;
234
274
  }
235
275
  clearTimeout(override.registrationTimeout);
276
+ if (override.payload.kind === "image") {
277
+ override.settled = true;
278
+ setOverrideList(
279
+ getOverrideList().filter(
280
+ (entry) => entry !== override || outcome === "persisted"
281
+ )
282
+ );
283
+ syncImagePreviews();
284
+ return;
285
+ }
236
286
  getStyleElement(override.token)?.remove();
237
287
  for (const target of override.targets) {
238
288
  const element = resolveTarget(target);
@@ -279,6 +329,7 @@ function useOptimisticOverrides() {
279
329
  });
280
330
  const token = `override-${editId}`;
281
331
  const override = {
332
+ settled: false,
282
333
  editId,
283
334
  injectedFontFamily: null,
284
335
  payload,
@@ -286,7 +337,6 @@ function useOptimisticOverrides() {
286
337
  removeOverride({ editId, outcome: "failed" });
287
338
  }, OVERRIDE_REGISTRATION_TIMEOUT_MS),
288
339
  sessionId: null,
289
- state: "live",
290
340
  targets: elements.map((element) => ({
291
341
  element,
292
342
  originalState: getOriginalState({ element, payload }),
@@ -297,6 +347,7 @@ function useOptimisticOverrides() {
297
347
  getOverrideList().push(override);
298
348
  installCssRule(override);
299
349
  reapplyOverride({ override, skipElement: null });
350
+ syncImagePreviews();
300
351
  },
301
352
  []
302
353
  );
@@ -305,6 +356,7 @@ function useOptimisticOverrides() {
305
356
  for (const override of getOverrideList()) {
306
357
  reapplyOverride({ override, skipElement });
307
358
  }
359
+ syncImagePreviews();
308
360
  },
309
361
  []
310
362
  );
@@ -317,7 +369,6 @@ function useOptimisticOverrides() {
317
369
  }
318
370
  clearTimeout(override.registrationTimeout);
319
371
  override.sessionId = sessionId;
320
- override.state = "fired";
321
372
  const outcome = getSessionOutcomes().get(sessionId);
322
373
  if (outcome) {
323
374
  removeOverride({ editId, outcome });
@@ -402,16 +402,7 @@ function useSelectionInteractions() {
402
402
  const scrollOffset = snapshot.type === "drag" ? snapshot.scrollOffset : getDocumentScrollOffset();
403
403
  const candidates = store().dragCandidates;
404
404
  resetDragState({ notifyParentDragCleared: false });
405
- if (!dragStart || snapshot.type !== "drag") {
406
- const targetElement = event.target;
407
- if (!(targetElement instanceof Element)) {
408
- return;
409
- }
410
- commitClickSelection({
411
- targetElement,
412
- pointerEvent: event,
413
- candidates
414
- });
405
+ if (snapshot.type !== "drag" || !dragStart) {
415
406
  return;
416
407
  }
417
408
  const resolvedDragCurrent = dragCurrent ?? dragStart;
@@ -1,8 +1,8 @@
1
1
  import type { SelectedElement } from "../_vendor/schemas/generated/selectMode";
2
2
  import type { IframeRpcChannelInputHandlers, IframeRpcChannelRemote } from "../_vendor/schemas/iframeRpcChannel";
3
- import { canopyToWebsiteBuilderMethodConfig, websiteBuilderToCanopyMethodConfig } from "../_vendor/schemas/selectModeIframeRpc";
4
- export type WebsiteBuilderRpcRemote = IframeRpcChannelRemote<typeof canopyToWebsiteBuilderMethodConfig>;
5
- type SelectModeParentMessagingHandlers = Omit<IframeRpcChannelInputHandlers<typeof websiteBuilderToCanopyMethodConfig>, "symbolicateSelectedElement" | "navigateToRoute">;
3
+ import { previewIframeToWebsiteBuilderMethodConfig, websiteBuilderToPreviewIframeMethodConfig } from "../_vendor/schemas/selectModeIframeRpc";
4
+ export type WebsiteBuilderRpcRemote = IframeRpcChannelRemote<typeof previewIframeToWebsiteBuilderMethodConfig>;
5
+ type SelectModeParentMessagingHandlers = Omit<IframeRpcChannelInputHandlers<typeof websiteBuilderToPreviewIframeMethodConfig>, "symbolicateSelectedElement" | "navigateToRoute">;
6
6
  export declare function setNavigateToRouteHandler(handler: ((input: {
7
7
  pathname: string;
8
8
  }) => void) | null): void;
@@ -32,6 +32,20 @@ export declare function getSelectModeIframeRpcChannel(): import("../_vendor/sche
32
32
  lineHeight: import("zod").ZodNumber;
33
33
  }, import("zod/v4/core").$strip>>;
34
34
  outerHTML: import("zod").ZodString;
35
+ image: import("zod").ZodOptional<import("zod").ZodObject<{
36
+ src: import("zod").ZodString;
37
+ currentSrc: import("zod").ZodString;
38
+ srcSet: import("zod").ZodString;
39
+ sizes: import("zod").ZodString;
40
+ previewUrl: import("zod").ZodNullable<import("zod").ZodString>;
41
+ sources: import("zod").ZodArray<import("zod").ZodObject<{
42
+ srcSet: import("zod").ZodString;
43
+ sizes: import("zod").ZodString;
44
+ media: import("zod").ZodString;
45
+ type: import("zod").ZodString;
46
+ previewUrl: import("zod").ZodNullable<import("zod").ZodString>;
47
+ }, import("zod/v4/core").$strip>>;
48
+ }, import("zod/v4/core").$strip>>;
35
49
  definedStyles: import("zod").ZodDefault<import("zod").ZodArray<import("zod").ZodObject<{
36
50
  property: import("zod").ZodString;
37
51
  variant: import("zod").ZodNullable<import("zod").ZodObject<{
@@ -109,6 +123,20 @@ export declare function getSelectModeIframeRpcChannel(): import("../_vendor/sche
109
123
  lineHeight: import("zod").ZodNumber;
110
124
  }, import("zod/v4/core").$strip>>;
111
125
  outerHTML: import("zod").ZodString;
126
+ image: import("zod").ZodOptional<import("zod").ZodObject<{
127
+ src: import("zod").ZodString;
128
+ currentSrc: import("zod").ZodString;
129
+ srcSet: import("zod").ZodString;
130
+ sizes: import("zod").ZodString;
131
+ previewUrl: import("zod").ZodNullable<import("zod").ZodString>;
132
+ sources: import("zod").ZodArray<import("zod").ZodObject<{
133
+ srcSet: import("zod").ZodString;
134
+ sizes: import("zod").ZodString;
135
+ media: import("zod").ZodString;
136
+ type: import("zod").ZodString;
137
+ previewUrl: import("zod").ZodNullable<import("zod").ZodString>;
138
+ }, import("zod/v4/core").$strip>>;
139
+ }, import("zod/v4/core").$strip>>;
112
140
  definedStyles: import("zod").ZodDefault<import("zod").ZodArray<import("zod").ZodObject<{
113
141
  property: import("zod").ZodString;
114
142
  variant: import("zod").ZodNullable<import("zod").ZodObject<{
@@ -274,6 +302,20 @@ export declare function getSelectModeIframeRpcChannel(): import("../_vendor/sche
274
302
  lineHeight: import("zod").ZodNumber;
275
303
  }, import("zod/v4/core").$strip>>;
276
304
  outerHTML: import("zod").ZodString;
305
+ image: import("zod").ZodOptional<import("zod").ZodObject<{
306
+ src: import("zod").ZodString;
307
+ currentSrc: import("zod").ZodString;
308
+ srcSet: import("zod").ZodString;
309
+ sizes: import("zod").ZodString;
310
+ previewUrl: import("zod").ZodNullable<import("zod").ZodString>;
311
+ sources: import("zod").ZodArray<import("zod").ZodObject<{
312
+ srcSet: import("zod").ZodString;
313
+ sizes: import("zod").ZodString;
314
+ media: import("zod").ZodString;
315
+ type: import("zod").ZodString;
316
+ previewUrl: import("zod").ZodNullable<import("zod").ZodString>;
317
+ }, import("zod/v4/core").$strip>>;
318
+ }, import("zod/v4/core").$strip>>;
277
319
  definedStyles: import("zod").ZodDefault<import("zod").ZodArray<import("zod").ZodObject<{
278
320
  property: import("zod").ZodString;
279
321
  variant: import("zod").ZodNullable<import("zod").ZodObject<{
@@ -3,10 +3,10 @@ import {
3
3
  createIframeRpcRemote
4
4
  } from "../_vendor/schemas/iframeRpcChannel.mjs";
5
5
  import {
6
- canopyToWebsiteBuilderMethodConfig,
6
+ previewIframeToWebsiteBuilderMethodConfig,
7
7
  SELECT_MODE_IFRAME_RPC_CHANNEL_ID,
8
8
  SELECT_MODE_IFRAME_RPC_CHANNEL_VERSION,
9
- websiteBuilderToCanopyMethodConfig
9
+ websiteBuilderToPreviewIframeMethodConfig
10
10
  } from "../_vendor/schemas/selectModeIframeRpc.mjs";
11
11
  import { symbolicateSelectedElement } from "./symbolicate";
12
12
  let messagingHandlers = null;
@@ -22,8 +22,8 @@ function createSelectModeIframeRpcChannel() {
22
22
  getTargetWindow: () => window.parent === window ? null : window.parent,
23
23
  targetOrigin: "*",
24
24
  isExpectedMessage: (event) => event.source === window.parent,
25
- outgoingMethods: canopyToWebsiteBuilderMethodConfig,
26
- incomingMethods: websiteBuilderToCanopyMethodConfig,
25
+ outgoingMethods: previewIframeToWebsiteBuilderMethodConfig,
26
+ incomingMethods: websiteBuilderToPreviewIframeMethodConfig,
27
27
  handlers: {
28
28
  setDisplayMode: (input) => {
29
29
  messagingHandlers?.setDisplayMode(input);
@@ -0,0 +1,6 @@
1
+ import type { SelectModeImage } from "../_vendor/schemas/generated/selectMode";
2
+ export declare function createImagePreview(image: HTMLImageElement): {
3
+ render(config: SelectModeImage): void;
4
+ isPersisted(config: SelectModeImage): boolean;
5
+ dispose(): void;
6
+ };
@@ -0,0 +1,77 @@
1
+ import { getImageEditSnapshot } from "../_vendor/schemas/selectModeImage.mjs";
2
+ import { getImageDescriptor, getPictureSources } from "./imageSources";
3
+ function createImagePreview(image) {
4
+ const picture = document.createElement("picture");
5
+ picture.hidden = true;
6
+ picture.dataset.reploImageResolver = "true";
7
+ const resolver = document.createElement("img");
8
+ resolver.alt = "";
9
+ const style = document.createElement("style");
10
+ const token = crypto.randomUUID();
11
+ image.dataset.reploImagePreview = token;
12
+ document.head.append(style);
13
+ let configuration = "";
14
+ let disposed = false;
15
+ function paint() {
16
+ if (disposed) return;
17
+ const url = resolver.currentSrc || resolver.src;
18
+ if (!url) return;
19
+ const rule = `[data-replo-image-preview="${token}"] { content: url(${JSON.stringify(url)}) !important; }`;
20
+ if (style.textContent !== rule) style.textContent = rule;
21
+ }
22
+ resolver.addEventListener("load", paint);
23
+ return {
24
+ render(config) {
25
+ const next = JSON.stringify(config);
26
+ if (configuration !== next) {
27
+ configuration = next;
28
+ const originals = getPictureSources(image);
29
+ const sources = config.sources.map((source, index) => {
30
+ const original = originals.find((candidate) => {
31
+ return candidate.media.trim() === source.media && candidate.type === source.type;
32
+ }) ?? originals[index];
33
+ const node = document.createElement("source");
34
+ node.media = source.media;
35
+ node.type = resolveMetadata(source.type, original?.type);
36
+ node.srcset = resolveMetadata(source.srcSet, original?.srcset);
37
+ node.sizes = resolveMetadata(source.sizes, original?.sizes);
38
+ return node;
39
+ });
40
+ resolver.setAttribute(
41
+ "src",
42
+ resolveMetadata(config.src, image.getAttribute("src"))
43
+ );
44
+ resolver.setAttribute(
45
+ "srcset",
46
+ resolveMetadata(config.srcSet, image.getAttribute("srcset"))
47
+ );
48
+ resolver.setAttribute(
49
+ "sizes",
50
+ resolveMetadata(config.sizes, image.sizes)
51
+ );
52
+ picture.replaceChildren(...sources, resolver);
53
+ if (!picture.isConnected) document.body.append(picture);
54
+ }
55
+ paint();
56
+ },
57
+ isPersisted(config) {
58
+ return JSON.stringify(
59
+ getImageEditSnapshot(getImageDescriptor(image), image.baseURI)
60
+ ) === JSON.stringify(getImageEditSnapshot(config, image.baseURI));
61
+ },
62
+ dispose() {
63
+ disposed = true;
64
+ resolver.removeEventListener("load", paint);
65
+ picture.remove();
66
+ style.remove();
67
+ if (image.dataset.reploImagePreview === token)
68
+ delete image.dataset.reploImagePreview;
69
+ }
70
+ };
71
+ }
72
+ function resolveMetadata(value, original) {
73
+ return value === "[image metadata omitted]" ? original ?? "" : value;
74
+ }
75
+ export {
76
+ createImagePreview
77
+ };
@@ -0,0 +1,3 @@
1
+ import type { SelectModeImage } from "../_vendor/schemas/generated/selectMode";
2
+ export declare function getPictureSources(image: HTMLImageElement): HTMLSourceElement[];
3
+ export declare function getImageDescriptor(element: Element): SelectModeImage | undefined;
@@ -0,0 +1,68 @@
1
+ function getPictureSources(image) {
2
+ const parent = image.parentElement;
3
+ if (parent?.tagName !== "PICTURE") {
4
+ return [];
5
+ }
6
+ return Array.from(parent.children).filter(
7
+ (child) => {
8
+ return child instanceof HTMLSourceElement && Boolean(
9
+ child.compareDocumentPosition(image) & Node.DOCUMENT_POSITION_FOLLOWING
10
+ );
11
+ }
12
+ );
13
+ }
14
+ const MAX_IMAGE_METADATA_LENGTH = 2048;
15
+ const MAX_PICTURE_SOURCES = 16;
16
+ function boundedImageMetadata(value) {
17
+ if (value.length > MAX_IMAGE_METADATA_LENGTH || /data:/i.test(value)) {
18
+ return "[image metadata omitted]";
19
+ }
20
+ return value;
21
+ }
22
+ function getPreviewUrl({
23
+ src,
24
+ srcSet,
25
+ baseURI
26
+ }) {
27
+ if (src.length > MAX_IMAGE_METADATA_LENGTH || srcSet.length > MAX_IMAGE_METADATA_LENGTH)
28
+ return null;
29
+ const candidate = src || srcSet.trim().split(/\s+/)[0]?.replace(/,+$/, "");
30
+ if (!candidate) {
31
+ return null;
32
+ }
33
+ try {
34
+ const url = new URL(candidate, baseURI);
35
+ return ["http:", "https:"].includes(url.protocol) ? url.href : null;
36
+ } catch {
37
+ return null;
38
+ }
39
+ }
40
+ function getImageDescriptor(element) {
41
+ if (!(element instanceof HTMLImageElement)) {
42
+ return void 0;
43
+ }
44
+ const src = element.getAttribute("src") ?? "";
45
+ const srcSet = element.getAttribute("srcset") ?? "";
46
+ return {
47
+ src: boundedImageMetadata(src),
48
+ srcSet: boundedImageMetadata(srcSet),
49
+ sizes: boundedImageMetadata(element.sizes),
50
+ currentSrc: boundedImageMetadata(element.currentSrc),
51
+ previewUrl: getPreviewUrl({ src, srcSet, baseURI: element.baseURI }),
52
+ sources: getPictureSources(element).filter((source) => source.media.length <= MAX_IMAGE_METADATA_LENGTH).slice(0, MAX_PICTURE_SOURCES).map((source) => ({
53
+ srcSet: boundedImageMetadata(source.srcset),
54
+ sizes: boundedImageMetadata(source.sizes),
55
+ media: source.media.trim(),
56
+ type: boundedImageMetadata(source.type),
57
+ previewUrl: getPreviewUrl({
58
+ src: "",
59
+ srcSet: source.srcset,
60
+ baseURI: source.baseURI
61
+ })
62
+ }))
63
+ };
64
+ }
65
+ export {
66
+ getImageDescriptor,
67
+ getPictureSources
68
+ };
@@ -1,25 +1,20 @@
1
- import type { DisplayMode, SelectableData, SelectModeBoundingRect, SelectModeFormatCommand, SelectModeSelectionType } from "../_vendor/schemas/generated/selectMode";
1
+ import type { DisplayMode, SelectableData, SelectModeBoundingRect, SelectModeFormatCommand, SelectModeSelectionType, SelectModeTiptapActiveMarks } from "../_vendor/schemas/generated/selectMode";
2
2
  import type { InlineEditFeedback } from "../_vendor/schemas/generated/selectModeIframeRpc";
3
3
  import type { DragCandidate } from "./interactions/selectionGeometry";
4
4
  import type { SelectionFrameSpec } from "./selectionFrame";
5
5
  import type { SelectModeInteractionSession } from "./selectModeSession";
6
6
  import type { InlineTiptapEditor } from "./tiptapInlineEditor";
7
- export type ActiveMarks = {
8
- bold: boolean;
9
- italic: boolean;
10
- underline: boolean;
11
- strike: boolean;
12
- };
13
- export declare const EMPTY_ACTIVE_MARKS: ActiveMarks;
14
- type InlineEditRequest = {
7
+ export declare const EMPTY_ACTIVE_MARKS: SelectModeTiptapActiveMarks;
8
+ type InlineEditDraft = {
15
9
  status: "pending";
16
10
  editId: string;
17
11
  element: HTMLElement;
18
12
  timeout: number;
19
- stopFeedback: () => void;
20
13
  } | {
21
14
  status: Exclude<InlineEditFeedback["status"], "pending">;
22
15
  element: HTMLElement;
16
+ };
17
+ type InlineEditRequest = InlineEditDraft & {
23
18
  stopFeedback: () => void;
24
19
  };
25
20
  type LastClick = {
@@ -52,7 +47,7 @@ interface SelectModeStoreState {
52
47
  initialHTML: string | null;
53
48
  isCommitting: boolean;
54
49
  beginEditingAt: number;
55
- activeMarks: ActiveMarks;
50
+ activeMarks: SelectModeTiptapActiveMarks;
56
51
  actions: {
57
52
  reset: () => void;
58
53
  setDisplayMode: (displayMode: DisplayMode) => void;
@@ -12,10 +12,7 @@ import {
12
12
  import { reportInlineEditFeedback } from "./inlineEditFeedback";
13
13
  import { getDocumentScrollOffset } from "./interactions/selectionGeometry";
14
14
  import { isTextEditableElement } from "./isTextEditableElement";
15
- import {
16
- getAreaSelectionFrameSpecs,
17
- getElementSelectionFrameSpecs
18
- } from "./selectionFrame";
15
+ import { getSelectionFrameSpecs } from "./selectionFrame";
19
16
  import { getConnectedSelectedElement, IDLE_SESSION } from "./selectModeSession";
20
17
  import {
21
18
  isUserSourceLocation,
@@ -405,17 +402,19 @@ const selectModeStore = createShallowStore(
405
402
  },
406
403
  showElementSelectionFrames: ({ elements, scrollOffset }) => {
407
404
  set({
408
- selectionFrames: getElementSelectionFrameSpecs({
405
+ selectionFrames: getSelectionFrameSpecs({
409
406
  elements,
410
- scrollOffset
407
+ scrollOffset,
408
+ variant: "element"
411
409
  })
412
410
  });
413
411
  },
414
412
  showAreaSelectionFrames: ({ elements, scrollOffset }) => {
415
413
  set({
416
- selectionFrames: getAreaSelectionFrameSpecs({
414
+ selectionFrames: getSelectionFrameSpecs({
417
415
  elements,
418
- scrollOffset
416
+ scrollOffset,
417
+ variant: "area"
419
418
  })
420
419
  });
421
420
  },
@@ -12,17 +12,11 @@ export type SelectionFrameSpec = {
12
12
  pageRect: SelectionFramePageRect;
13
13
  variant: SelectionFrameVariant;
14
14
  };
15
- export declare function getElementSelectionFrameSpecs({ elements, scrollOffset, }: {
16
- elements: Element[];
17
- scrollOffset: {
18
- left: number;
19
- top: number;
20
- };
21
- }): SelectionFrameSpec[];
22
- export declare function getAreaSelectionFrameSpecs({ elements, scrollOffset, }: {
15
+ export declare function getSelectionFrameSpecs({ elements, scrollOffset, variant, }: {
23
16
  elements: Element[];
24
17
  scrollOffset: {
25
18
  left: number;
26
19
  top: number;
27
20
  };
21
+ variant: SelectionFrameVariant;
28
22
  }): SelectionFrameSpec[];
@@ -1,7 +1,7 @@
1
1
  const SELECTION_FRAMES_CONTAINER_ID = "replo-select-mode-selection-frames";
2
2
  const SELECTION_FRAME_BORDER_HEX = "#c026d3";
3
3
  const SELECTION_FRAME_EDITING_BORDER_HEX = "#e879f9";
4
- function getFrameSpecs({
4
+ function getSelectionFrameSpecs({
5
5
  elements,
6
6
  scrollOffset,
7
7
  variant
@@ -19,22 +19,9 @@ function getFrameSpecs({
19
19
  };
20
20
  });
21
21
  }
22
- function getElementSelectionFrameSpecs({
23
- elements,
24
- scrollOffset
25
- }) {
26
- return getFrameSpecs({ elements, scrollOffset, variant: "element" });
27
- }
28
- function getAreaSelectionFrameSpecs({
29
- elements,
30
- scrollOffset
31
- }) {
32
- return getFrameSpecs({ elements, scrollOffset, variant: "area" });
33
- }
34
22
  export {
35
23
  SELECTION_FRAMES_CONTAINER_ID,
36
24
  SELECTION_FRAME_BORDER_HEX,
37
25
  SELECTION_FRAME_EDITING_BORDER_HEX,
38
- getAreaSelectionFrameSpecs,
39
- getElementSelectionFrameSpecs
26
+ getSelectionFrameSpecs
40
27
  };