@replohq/sandbox-runtime 1.7.10 → 1.7.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/_vendor/replo-utils/react/zustand.d.ts +11 -0
- package/_vendor/replo-utils/react/zustand.mjs +13 -0
- package/_vendor/schemas/generated/selectModeIframeRpc.d.ts +11 -8
- package/_vendor/schemas/selectModeIframeRpc.d.ts +66 -130
- package/_vendor/schemas/selectModeIframeRpc.mjs +16 -11
- package/buildMetadata.js +3 -3
- package/package.json +6 -5
- package/select-mode/EditorSelection.d.ts +1 -22
- package/select-mode/EditorSelection.js +61 -100
- package/select-mode/SelectionFrames.d.ts +1 -0
- package/select-mode/SelectionFrames.js +58 -0
- package/select-mode/annotationFrames.d.ts +13 -0
- package/select-mode/annotationFrames.js +31 -1
- package/select-mode/displayModeStore.d.ts +0 -2
- package/select-mode/displayModeStore.js +11 -30
- package/select-mode/hooks/useParentMessaging.js +3 -0
- package/select-mode/hooks/useSelectionHover.d.ts +1 -19
- package/select-mode/hooks/useSelectionHover.js +37 -49
- package/select-mode/hooks/useSelectionInteractions.d.ts +1 -12
- package/select-mode/hooks/useSelectionInteractions.js +57 -39
- package/select-mode/hooks/useSelectionScrollSync.d.ts +1 -25
- package/select-mode/hooks/useSelectionScrollSync.js +48 -40
- package/select-mode/iframeRpcChannel.d.ts +24 -1
- package/select-mode/inlineEditFeedback.d.ts +6 -0
- package/select-mode/inlineEditFeedback.js +47 -0
- package/select-mode/isTextEditableElement.d.ts +1 -0
- package/select-mode/isTextEditableElement.js +15 -0
- package/select-mode/selectModeStore.d.ts +160 -0
- package/select-mode/selectModeStore.js +586 -0
- package/select-mode/selectionFrame.d.ts +10 -59
- package/select-mode/selectionFrame.js +26 -150
- package/select-mode/symbolicate.js +4 -0
- package/select-mode/tiptapInlineEditor.js +16 -1
- package/select-mode/useShallowStore.d.ts +2 -0
- package/select-mode/useShallowStore.js +9 -0
- package/select-mode/hooks/useCrosshairCursor.d.ts +0 -10
- package/select-mode/hooks/useCrosshairCursor.js +0 -23
- package/select-mode/hooks/useEditModeStateMachine.d.ts +0 -16
- package/select-mode/hooks/useEditModeStateMachine.js +0 -228
- package/select-mode/hooks/useSelectModeController.d.ts +0 -11
- package/select-mode/hooks/useSelectModeController.js +0 -72
|
@@ -19,18 +19,14 @@ import {
|
|
|
19
19
|
isAdditiveSelectionClick,
|
|
20
20
|
unionElementPageRects
|
|
21
21
|
} from "../interactions/selectionGeometry";
|
|
22
|
-
import {
|
|
23
|
-
hideSelectionFrame,
|
|
24
|
-
showAreaSelectionFrames,
|
|
25
|
-
showElementSelectionFrames
|
|
26
|
-
} from "../selectionFrame";
|
|
22
|
+
import { isTextEditableElement } from "../isTextEditableElement";
|
|
27
23
|
import { isSelectionStillCurrent } from "../selectionPublish";
|
|
28
24
|
import {
|
|
29
25
|
getConnectedSelectedElement,
|
|
30
26
|
IDLE_SESSION
|
|
31
27
|
} from "../selectModeSession";
|
|
28
|
+
import { useDisplayMode, useSelectModeStore } from "../selectModeStore";
|
|
32
29
|
import { symbolicateSelectedElement } from "../symbolicate";
|
|
33
|
-
import { isTextEditableElement } from "./useEditModeStateMachine";
|
|
34
30
|
import { getRepetitionSiblingElements } from "./useSiblingResolution";
|
|
35
31
|
const DOUBLE_CLICK_THRESHOLD_MS = 500;
|
|
36
32
|
function getSelectedElementsFromSession(session) {
|
|
@@ -49,21 +45,35 @@ function getSelectedElementsFromSession(session) {
|
|
|
49
45
|
async function maybeSymbolicate(data) {
|
|
50
46
|
return data.kind === "react-element" ? symbolicateSelectedElement(data) : data;
|
|
51
47
|
}
|
|
52
|
-
function useSelectionInteractions({
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
interactionSessionRef,
|
|
56
|
-
onBeginEditing
|
|
57
|
-
}) {
|
|
48
|
+
function useSelectionInteractions() {
|
|
49
|
+
const selectModeStore = useSelectModeStore();
|
|
50
|
+
const displayMode = useDisplayMode();
|
|
58
51
|
useEffect(() => {
|
|
59
52
|
if (displayMode !== "selection") {
|
|
60
53
|
return;
|
|
61
54
|
}
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
55
|
+
const store = () => selectModeStore.getState();
|
|
56
|
+
const interactionSessionRef = {
|
|
57
|
+
get current() {
|
|
58
|
+
return store().interactionSession;
|
|
59
|
+
},
|
|
60
|
+
set current(next) {
|
|
61
|
+
store().actions.setInteractionSession(next);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const editingElementRef = {
|
|
65
|
+
get current() {
|
|
66
|
+
return store().editingElement;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const actions = () => store().actions;
|
|
70
|
+
const onBeginEditing = actions().beginEditing;
|
|
71
|
+
const hideSelectionFrame = () => {
|
|
72
|
+
actions().hideSelectionFrames();
|
|
73
|
+
};
|
|
74
|
+
const showAreaSelectionFrames = actions().showAreaSelectionFrames;
|
|
75
|
+
const showElementSelectionFrames = actions().showElementSelectionFrames;
|
|
76
|
+
const editingPointerIds = store().editingPointerIds;
|
|
67
77
|
const clearCommittedSelection = ({
|
|
68
78
|
rect
|
|
69
79
|
}) => {
|
|
@@ -72,11 +82,12 @@ function useSelectionInteractions({
|
|
|
72
82
|
getWebsiteBuilderRpc()?.areaSelected({ rect, items: [] });
|
|
73
83
|
};
|
|
74
84
|
const stopDragAnimation = () => {
|
|
85
|
+
const dragAnimationFrameId = store().dragAnimationFrameId;
|
|
75
86
|
if (dragAnimationFrameId === null) {
|
|
76
87
|
return;
|
|
77
88
|
}
|
|
78
89
|
cancelAnimationFrame(dragAnimationFrameId);
|
|
79
|
-
|
|
90
|
+
actions().setDragAnimationFrameId(null);
|
|
80
91
|
};
|
|
81
92
|
const resetDragState = ({
|
|
82
93
|
notifyParentDragCleared = true
|
|
@@ -84,7 +95,7 @@ function useSelectionInteractions({
|
|
|
84
95
|
const currentSession = interactionSessionRef.current;
|
|
85
96
|
stopDragAnimation();
|
|
86
97
|
if (currentSession.type !== "drag") {
|
|
87
|
-
|
|
98
|
+
actions().setDragCandidates([]);
|
|
88
99
|
return;
|
|
89
100
|
}
|
|
90
101
|
if (notifyParentDragCleared && currentSession.hasExceededThreshold) {
|
|
@@ -93,7 +104,7 @@ function useSelectionInteractions({
|
|
|
93
104
|
selectionRects: []
|
|
94
105
|
});
|
|
95
106
|
}
|
|
96
|
-
|
|
107
|
+
actions().setDragCandidates([]);
|
|
97
108
|
interactionSessionRef.current = IDLE_SESSION;
|
|
98
109
|
};
|
|
99
110
|
const postCurrentDragRect = () => {
|
|
@@ -120,7 +131,7 @@ function useSelectionInteractions({
|
|
|
120
131
|
scrollOffset: session.scrollOffset
|
|
121
132
|
});
|
|
122
133
|
const selectionRects = getCandidatesInSelection({
|
|
123
|
-
candidates: dragCandidates,
|
|
134
|
+
candidates: store().dragCandidates,
|
|
124
135
|
selectionPageRect
|
|
125
136
|
}).map((candidate) => ({
|
|
126
137
|
id: candidate.id,
|
|
@@ -137,7 +148,7 @@ function useSelectionInteractions({
|
|
|
137
148
|
const syncDragRectToViewport = () => {
|
|
138
149
|
const session = interactionSessionRef.current;
|
|
139
150
|
if (session.type !== "drag") {
|
|
140
|
-
|
|
151
|
+
actions().setDragAnimationFrameId(null);
|
|
141
152
|
return;
|
|
142
153
|
}
|
|
143
154
|
const nextScrollOffset = getDocumentScrollOffset();
|
|
@@ -159,7 +170,9 @@ function useSelectionInteractions({
|
|
|
159
170
|
scrollOffset: nextScrollOffset
|
|
160
171
|
};
|
|
161
172
|
}
|
|
162
|
-
|
|
173
|
+
actions().setDragAnimationFrameId(
|
|
174
|
+
requestAnimationFrame(syncDragRectToViewport)
|
|
175
|
+
);
|
|
163
176
|
};
|
|
164
177
|
const handlePointerDown = (event) => {
|
|
165
178
|
if (event.button !== 0) {
|
|
@@ -173,8 +186,8 @@ function useSelectionInteractions({
|
|
|
173
186
|
event.preventDefault();
|
|
174
187
|
event.stopPropagation();
|
|
175
188
|
const scrollOffset = getDocumentScrollOffset();
|
|
176
|
-
|
|
177
|
-
interactionSessionRef.current
|
|
189
|
+
actions().setCommittedSelectionAtPointerDown(
|
|
190
|
+
getSelectedElementsFromSession(interactionSessionRef.current)
|
|
178
191
|
);
|
|
179
192
|
const dragStart = getDragPositionFromClient({
|
|
180
193
|
clientX: event.clientX,
|
|
@@ -188,9 +201,11 @@ function useSelectionInteractions({
|
|
|
188
201
|
scrollOffset,
|
|
189
202
|
hasExceededThreshold: false
|
|
190
203
|
};
|
|
191
|
-
|
|
192
|
-
if (dragAnimationFrameId === null) {
|
|
193
|
-
|
|
204
|
+
actions().setDragCandidates(collectDragCandidates(scrollOffset));
|
|
205
|
+
if (store().dragAnimationFrameId === null) {
|
|
206
|
+
actions().setDragAnimationFrameId(
|
|
207
|
+
requestAnimationFrame(syncDragRectToViewport)
|
|
208
|
+
);
|
|
194
209
|
}
|
|
195
210
|
};
|
|
196
211
|
const handlePointerMove = (event) => {
|
|
@@ -210,10 +225,12 @@ function useSelectionInteractions({
|
|
|
210
225
|
};
|
|
211
226
|
const handleViewportChangeDuringDrag = () => {
|
|
212
227
|
const session = interactionSessionRef.current;
|
|
213
|
-
if (session.type !== "drag" || dragAnimationFrameId !== null) {
|
|
228
|
+
if (session.type !== "drag" || store().dragAnimationFrameId !== null) {
|
|
214
229
|
return;
|
|
215
230
|
}
|
|
216
|
-
|
|
231
|
+
actions().setDragAnimationFrameId(
|
|
232
|
+
requestAnimationFrame(syncDragRectToViewport)
|
|
233
|
+
);
|
|
217
234
|
};
|
|
218
235
|
const commitAreaSelection = ({
|
|
219
236
|
selectedElements,
|
|
@@ -275,9 +292,9 @@ function useSelectionInteractions({
|
|
|
275
292
|
scrollOffset
|
|
276
293
|
});
|
|
277
294
|
const now = pointerEvent.timeStamp;
|
|
278
|
-
const previousClick = lastClick;
|
|
295
|
+
const previousClick = store().lastClick;
|
|
279
296
|
if (previousClick && previousClick.target === selectionElement && now - previousClick.time <= DOUBLE_CLICK_THRESHOLD_MS && isTextEditableElement(selectionElement)) {
|
|
280
|
-
|
|
297
|
+
actions().setLastClick(null);
|
|
281
298
|
onBeginEditing({
|
|
282
299
|
element: selectionElement,
|
|
283
300
|
descriptorPromise: previousClick.descriptorPromise
|
|
@@ -289,11 +306,11 @@ function useSelectionInteractions({
|
|
|
289
306
|
clickPosition,
|
|
290
307
|
siblingSelectors: siblingElements.map(buildSelector)
|
|
291
308
|
});
|
|
292
|
-
|
|
309
|
+
actions().setLastClick({
|
|
293
310
|
descriptorPromise: Promise.resolve(data),
|
|
294
311
|
target: selectionElement,
|
|
295
312
|
time: now
|
|
296
|
-
};
|
|
313
|
+
});
|
|
297
314
|
if (!selectionElement.isConnected) {
|
|
298
315
|
return;
|
|
299
316
|
}
|
|
@@ -309,6 +326,7 @@ function useSelectionInteractions({
|
|
|
309
326
|
};
|
|
310
327
|
void maybeSymbolicate(data).then((symbolicated) => {
|
|
311
328
|
const session = interactionSessionRef.current;
|
|
329
|
+
const committedSelectionAtPointerDown = store().committedSelectionAtPointerDown;
|
|
312
330
|
const isPendingClickOnSelection = session.type === "drag" && !session.hasExceededThreshold && committedSelectionAtPointerDown.length === 1 && committedSelectionAtPointerDown[0] === selectionElement;
|
|
313
331
|
if (!isPendingClickOnSelection && !isSelectionStillCurrent({
|
|
314
332
|
session: interactionSessionRef.current,
|
|
@@ -329,14 +347,14 @@ function useSelectionInteractions({
|
|
|
329
347
|
commitElementSelection({ selectionElement, pointerEvent });
|
|
330
348
|
return;
|
|
331
349
|
}
|
|
332
|
-
|
|
350
|
+
actions().setLastClick(null);
|
|
333
351
|
const pointerRect = getPointRect({
|
|
334
352
|
x: pointerEvent.clientX,
|
|
335
353
|
y: pointerEvent.clientY
|
|
336
354
|
});
|
|
337
355
|
const nextElements = getSelectionAfterAdditiveClick({
|
|
338
356
|
candidates,
|
|
339
|
-
currentSelectedElements: committedSelectionAtPointerDown,
|
|
357
|
+
currentSelectedElements: store().committedSelectionAtPointerDown,
|
|
340
358
|
targetElement: selectionElement
|
|
341
359
|
});
|
|
342
360
|
const [firstElement] = nextElements;
|
|
@@ -349,7 +367,7 @@ function useSelectionInteractions({
|
|
|
349
367
|
selectionElement: firstElement,
|
|
350
368
|
pointerEvent
|
|
351
369
|
});
|
|
352
|
-
|
|
370
|
+
actions().setLastClick(null);
|
|
353
371
|
return;
|
|
354
372
|
}
|
|
355
373
|
const scrollOffset = getDocumentScrollOffset();
|
|
@@ -382,7 +400,7 @@ function useSelectionInteractions({
|
|
|
382
400
|
const dragStart = snapshot.type === "drag" ? snapshot.dragStart : null;
|
|
383
401
|
const dragCurrent = snapshot.type === "drag" ? snapshot.dragCurrent : null;
|
|
384
402
|
const scrollOffset = snapshot.type === "drag" ? snapshot.scrollOffset : getDocumentScrollOffset();
|
|
385
|
-
const candidates = dragCandidates;
|
|
403
|
+
const candidates = store().dragCandidates;
|
|
386
404
|
resetDragState({ notifyParentDragCleared: false });
|
|
387
405
|
if (!dragStart || snapshot.type !== "drag") {
|
|
388
406
|
const targetElement = event.target;
|
|
@@ -469,7 +487,7 @@ function useSelectionInteractions({
|
|
|
469
487
|
window.removeEventListener("resize", handleViewportChangeDuringDrag);
|
|
470
488
|
resetDragState();
|
|
471
489
|
};
|
|
472
|
-
}, [displayMode,
|
|
490
|
+
}, [displayMode, selectModeStore]);
|
|
473
491
|
}
|
|
474
492
|
export {
|
|
475
493
|
useSelectionInteractions
|
|
@@ -1,25 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import type { DisplayMode } from "../../_vendor/schemas/generated/selectMode";
|
|
3
|
-
import type { SelectModeInteractionSession } from "../selectModeSession";
|
|
4
|
-
/**
|
|
5
|
-
* After a selection (element or area) has been resolved, the parent's
|
|
6
|
-
* highlight overlay is positioned in viewport coordinates. When the user
|
|
7
|
-
* scrolls the iframe document the highlight would otherwise lag behind the
|
|
8
|
-
* underlying element. This hook re-sends an updated rect on every scroll
|
|
9
|
-
* (rAF-coalesced) so the parent overlay tracks the element/area through
|
|
10
|
-
* scrolls without us having to mirror scroll state into the parent.
|
|
11
|
-
*
|
|
12
|
-
* - For an `element` session we send only `{ boundingRect, clickPosition }`
|
|
13
|
-
* — the rest of the descriptor (selector, outerHTML, computed styles,
|
|
14
|
-
* text metrics, source location) was captured at selection-commit time
|
|
15
|
-
* and doesn't change while the user is just scrolling. Rebuilding the
|
|
16
|
-
* full descriptor here would call `serializeStyledElement` recursively.
|
|
17
|
-
* The in-iframe frames only remeasure the selected repetition group.
|
|
18
|
-
* - For an `area` session we keep the original *page* rect (which doesn't
|
|
19
|
-
* move) and convert it to viewport coordinates using the latest scroll
|
|
20
|
-
* offset before sending.
|
|
21
|
-
*/
|
|
22
|
-
export declare function useSelectionScrollSync({ displayMode, interactionSessionRef, }: {
|
|
23
|
-
displayMode: DisplayMode;
|
|
24
|
-
interactionSessionRef: MutableRefObject<SelectModeInteractionSession>;
|
|
25
|
-
}): void;
|
|
1
|
+
export declare function useSelectionScrollSync(): void;
|
|
@@ -5,59 +5,67 @@ import {
|
|
|
5
5
|
getElementBoundingRect,
|
|
6
6
|
getViewportRectFromPageRect
|
|
7
7
|
} from "../interactions/selectionGeometry";
|
|
8
|
-
import {
|
|
9
|
-
function useSelectionScrollSync({
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}) {
|
|
8
|
+
import { useDisplayMode, useSelectModeStore } from "../selectModeStore";
|
|
9
|
+
function useSelectionScrollSync() {
|
|
10
|
+
const store = useSelectModeStore();
|
|
11
|
+
const displayMode = useDisplayMode();
|
|
13
12
|
useEffect(() => {
|
|
14
13
|
if (displayMode !== "selection") {
|
|
15
14
|
return;
|
|
16
15
|
}
|
|
17
|
-
let animationFrameId = null;
|
|
18
16
|
const handleScroll = () => {
|
|
19
|
-
|
|
17
|
+
const { scrollSyncAnimationFrameId, actions } = store.getState();
|
|
18
|
+
if (scrollSyncAnimationFrameId !== null) {
|
|
20
19
|
return;
|
|
21
20
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
scrollOffset
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
21
|
+
actions.setScrollSyncAnimationFrameId(
|
|
22
|
+
requestAnimationFrame(() => {
|
|
23
|
+
const { interactionSession, actions: storeActions } = store.getState();
|
|
24
|
+
storeActions.setScrollSyncAnimationFrameId(null);
|
|
25
|
+
if (interactionSession.type === "element") {
|
|
26
|
+
const boundingRect = getElementBoundingRect(
|
|
27
|
+
interactionSession.element
|
|
28
|
+
);
|
|
29
|
+
const sessionClickPosition = interactionSession.clickPosition;
|
|
30
|
+
const clickPosition = {
|
|
31
|
+
x: sessionClickPosition !== null ? boundingRect.left + sessionClickPosition.x : boundingRect.right,
|
|
32
|
+
y: sessionClickPosition !== null ? boundingRect.top + sessionClickPosition.y : boundingRect.bottom
|
|
33
|
+
};
|
|
34
|
+
const scrollOffset = getDocumentScrollOffset();
|
|
35
|
+
storeActions.showElementSelectionFrames({
|
|
36
|
+
elements: [
|
|
37
|
+
interactionSession.element,
|
|
38
|
+
...interactionSession.siblingElements
|
|
39
|
+
],
|
|
40
|
+
scrollOffset
|
|
41
|
+
});
|
|
42
|
+
getWebsiteBuilderRpc()?.selectedElementRectUpdate({
|
|
43
|
+
rect: boundingRect,
|
|
44
|
+
clickPosition
|
|
45
|
+
});
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (interactionSession.type === "area") {
|
|
49
|
+
getWebsiteBuilderRpc()?.selectedAreaRectUpdate({
|
|
50
|
+
rect: getViewportRectFromPageRect({
|
|
51
|
+
rect: interactionSession.pageRect,
|
|
52
|
+
scrollOffset: getDocumentScrollOffset()
|
|
53
|
+
})
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
);
|
|
52
58
|
};
|
|
53
59
|
document.addEventListener("scroll", handleScroll, true);
|
|
54
60
|
return () => {
|
|
55
61
|
document.removeEventListener("scroll", handleScroll, true);
|
|
56
|
-
|
|
57
|
-
|
|
62
|
+
const { scrollSyncAnimationFrameId, actions } = store.getState();
|
|
63
|
+
if (scrollSyncAnimationFrameId !== null) {
|
|
64
|
+
cancelAnimationFrame(scrollSyncAnimationFrameId);
|
|
65
|
+
actions.setScrollSyncAnimationFrameId(null);
|
|
58
66
|
}
|
|
59
67
|
};
|
|
60
|
-
}, [displayMode,
|
|
68
|
+
}, [displayMode, store]);
|
|
61
69
|
}
|
|
62
70
|
export {
|
|
63
71
|
useSelectionScrollSync
|
|
@@ -337,6 +337,28 @@ export declare function getSelectModeIframeRpcChannel(): import("../_vendor/sche
|
|
|
337
337
|
}, import("zod/v4/core").$strip>;
|
|
338
338
|
outputSchema: import("zod").ZodVoid;
|
|
339
339
|
};
|
|
340
|
+
inlineEditFeedbackChanged: {
|
|
341
|
+
inputSchema: import("zod").ZodObject<{
|
|
342
|
+
feedback: import("zod").ZodNullable<import("zod").ZodObject<{
|
|
343
|
+
status: import("zod").ZodEnum<{
|
|
344
|
+
unavailable: "unavailable";
|
|
345
|
+
pending: "pending";
|
|
346
|
+
failed: "failed";
|
|
347
|
+
}>;
|
|
348
|
+
rect: import("zod").ZodObject<{
|
|
349
|
+
x: import("zod").ZodNumber;
|
|
350
|
+
y: import("zod").ZodNumber;
|
|
351
|
+
left: import("zod").ZodNumber;
|
|
352
|
+
top: import("zod").ZodNumber;
|
|
353
|
+
right: import("zod").ZodNumber;
|
|
354
|
+
bottom: import("zod").ZodNumber;
|
|
355
|
+
width: import("zod").ZodNumber;
|
|
356
|
+
height: import("zod").ZodNumber;
|
|
357
|
+
}, import("zod/v4/core").$strip>;
|
|
358
|
+
}, import("zod/v4/core").$strip>>;
|
|
359
|
+
}, import("zod/v4/core").$strip>;
|
|
360
|
+
outputSchema: import("zod").ZodVoid;
|
|
361
|
+
};
|
|
340
362
|
editorStateUpdate: {
|
|
341
363
|
inputSchema: import("zod").ZodObject<{
|
|
342
364
|
activeMarks: import("zod").ZodObject<{
|
|
@@ -345,7 +367,8 @@ export declare function getSelectModeIframeRpcChannel(): import("../_vendor/sche
|
|
|
345
367
|
underline: import("zod").ZodBoolean;
|
|
346
368
|
strike: import("zod").ZodBoolean;
|
|
347
369
|
}, import("zod/v4/core").$strip>;
|
|
348
|
-
|
|
370
|
+
isInlineEditing: import("zod").ZodBoolean;
|
|
371
|
+
isInlineEditPending: import("zod").ZodBoolean;
|
|
349
372
|
}, import("zod/v4/core").$strip>;
|
|
350
373
|
outputSchema: import("zod").ZodVoid;
|
|
351
374
|
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { InlineEditFeedback } from "../_vendor/schemas/generated/selectModeIframeRpc";
|
|
2
|
+
export declare function reportInlineEditFeedback({ element, onDisconnected, status, }: {
|
|
3
|
+
element: HTMLElement;
|
|
4
|
+
onDisconnected: () => void;
|
|
5
|
+
status?: InlineEditFeedback["status"];
|
|
6
|
+
}): () => void;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getWebsiteBuilderRpc } from "./iframeRpcChannel";
|
|
2
|
+
function reportInlineEditFeedback({
|
|
3
|
+
element,
|
|
4
|
+
onDisconnected,
|
|
5
|
+
status = "pending"
|
|
6
|
+
}) {
|
|
7
|
+
let animationFrame = 0;
|
|
8
|
+
let stopped = false;
|
|
9
|
+
let previousRect = "";
|
|
10
|
+
const report = () => {
|
|
11
|
+
if (stopped) return;
|
|
12
|
+
if (!element.isConnected) {
|
|
13
|
+
onDisconnected();
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const bounds = element.getBoundingClientRect();
|
|
17
|
+
const rect = {
|
|
18
|
+
x: bounds.x,
|
|
19
|
+
y: bounds.y,
|
|
20
|
+
top: bounds.top,
|
|
21
|
+
right: bounds.right,
|
|
22
|
+
bottom: bounds.bottom,
|
|
23
|
+
left: bounds.left,
|
|
24
|
+
width: bounds.width,
|
|
25
|
+
height: bounds.height
|
|
26
|
+
};
|
|
27
|
+
const serializedRect = JSON.stringify(rect);
|
|
28
|
+
if (serializedRect !== previousRect) {
|
|
29
|
+
previousRect = serializedRect;
|
|
30
|
+
getWebsiteBuilderRpc()?.inlineEditFeedbackChanged({
|
|
31
|
+
feedback: { status, rect }
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
animationFrame = requestAnimationFrame(report);
|
|
35
|
+
};
|
|
36
|
+
const timer = status === "pending" ? window.setTimeout(report, 150) : null;
|
|
37
|
+
if (status !== "pending") report();
|
|
38
|
+
return () => {
|
|
39
|
+
stopped = true;
|
|
40
|
+
if (timer !== null) clearTimeout(timer);
|
|
41
|
+
cancelAnimationFrame(animationFrame);
|
|
42
|
+
getWebsiteBuilderRpc()?.inlineEditFeedbackChanged({ feedback: null });
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export {
|
|
46
|
+
reportInlineEditFeedback
|
|
47
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isTextEditableElement(element: Element): element is HTMLElement;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
function isTextEditableElement(element) {
|
|
2
|
+
const tagName = element.tagName.toLowerCase();
|
|
3
|
+
return element instanceof HTMLElement && Boolean(element.textContent?.trim()) && ![
|
|
4
|
+
"input",
|
|
5
|
+
"textarea",
|
|
6
|
+
"select",
|
|
7
|
+
"option",
|
|
8
|
+
"img",
|
|
9
|
+
"video",
|
|
10
|
+
"canvas"
|
|
11
|
+
].includes(tagName);
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
isTextEditableElement
|
|
15
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import type { DisplayMode, SelectableData, SelectModeBoundingRect, SelectModeFormatCommand, SelectModeSelectionType } from "../_vendor/schemas/generated/selectMode";
|
|
2
|
+
import type { InlineEditFeedback } from "../_vendor/schemas/generated/selectModeIframeRpc";
|
|
3
|
+
import type { DragCandidate } from "./interactions/selectionGeometry";
|
|
4
|
+
import type { SelectionFrameSpec } from "./selectionFrame";
|
|
5
|
+
import type { SelectModeInteractionSession } from "./selectModeSession";
|
|
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 = {
|
|
15
|
+
status: "pending";
|
|
16
|
+
editId: string;
|
|
17
|
+
element: HTMLElement;
|
|
18
|
+
timeout: number;
|
|
19
|
+
stopFeedback: () => void;
|
|
20
|
+
} | {
|
|
21
|
+
status: Exclude<InlineEditFeedback["status"], "pending">;
|
|
22
|
+
element: HTMLElement;
|
|
23
|
+
stopFeedback: () => void;
|
|
24
|
+
};
|
|
25
|
+
type LastClick = {
|
|
26
|
+
descriptorPromise: Promise<SelectableData>;
|
|
27
|
+
target: Element;
|
|
28
|
+
time: number;
|
|
29
|
+
};
|
|
30
|
+
interface SelectModeStoreState {
|
|
31
|
+
displayMode: DisplayMode;
|
|
32
|
+
interactionSession: SelectModeInteractionSession;
|
|
33
|
+
selectionFrames: SelectionFrameSpec[];
|
|
34
|
+
isSelectionFrameEditing: boolean;
|
|
35
|
+
lastPointerClientPosition: {
|
|
36
|
+
x: number;
|
|
37
|
+
y: number;
|
|
38
|
+
} | null;
|
|
39
|
+
lastPostedHoverRect: SelectModeBoundingRect | null | undefined;
|
|
40
|
+
hoverSyncAnimationFrameId: number | null;
|
|
41
|
+
lastClick: LastClick | null;
|
|
42
|
+
dragCandidates: DragCandidate[];
|
|
43
|
+
committedSelectionAtPointerDown: Element[];
|
|
44
|
+
dragAnimationFrameId: number | null;
|
|
45
|
+
editingPointerIds: Set<number>;
|
|
46
|
+
scrollSyncAnimationFrameId: number | null;
|
|
47
|
+
inlineEditRequest: InlineEditRequest | null;
|
|
48
|
+
editor: InlineTiptapEditor | null;
|
|
49
|
+
editingElement: HTMLElement | null;
|
|
50
|
+
editId: string | null;
|
|
51
|
+
originalInnerHTML: string | null;
|
|
52
|
+
initialHTML: string | null;
|
|
53
|
+
isCommitting: boolean;
|
|
54
|
+
beginEditingAt: number;
|
|
55
|
+
activeMarks: ActiveMarks;
|
|
56
|
+
actions: {
|
|
57
|
+
reset: () => void;
|
|
58
|
+
setDisplayMode: (displayMode: DisplayMode) => void;
|
|
59
|
+
setSelectionType: ({ selectionType, selectors, }: {
|
|
60
|
+
selectionType: SelectModeSelectionType;
|
|
61
|
+
selectors?: string[];
|
|
62
|
+
}) => void;
|
|
63
|
+
setInteractionSession: (interactionSession: SelectModeInteractionSession) => void;
|
|
64
|
+
resetInteractionSession: () => void;
|
|
65
|
+
postSelectedElementSnapshot: (options?: {
|
|
66
|
+
clearMissing?: boolean;
|
|
67
|
+
}) => boolean;
|
|
68
|
+
showElementSelectionFrames: ({ elements, scrollOffset, }: {
|
|
69
|
+
elements: Element[];
|
|
70
|
+
scrollOffset: {
|
|
71
|
+
left: number;
|
|
72
|
+
top: number;
|
|
73
|
+
};
|
|
74
|
+
}) => void;
|
|
75
|
+
showAreaSelectionFrames: ({ elements, scrollOffset, }: {
|
|
76
|
+
elements: Element[];
|
|
77
|
+
scrollOffset: {
|
|
78
|
+
left: number;
|
|
79
|
+
top: number;
|
|
80
|
+
};
|
|
81
|
+
}) => void;
|
|
82
|
+
hideSelectionFrames: () => void;
|
|
83
|
+
setLastPointerClientPosition: (position: {
|
|
84
|
+
x: number;
|
|
85
|
+
y: number;
|
|
86
|
+
} | null) => void;
|
|
87
|
+
setLastPostedHoverRect: (rect: SelectModeBoundingRect | null | undefined) => void;
|
|
88
|
+
resetHoverRectDedup: () => void;
|
|
89
|
+
setHoverSyncAnimationFrameId: (id: number | null) => void;
|
|
90
|
+
setLastClick: (lastClick: LastClick | null) => void;
|
|
91
|
+
setDragCandidates: (dragCandidates: DragCandidate[]) => void;
|
|
92
|
+
setCommittedSelectionAtPointerDown: (elements: Element[]) => void;
|
|
93
|
+
setDragAnimationFrameId: (id: number | null) => void;
|
|
94
|
+
setScrollSyncAnimationFrameId: (id: number | null) => void;
|
|
95
|
+
beginEditing: ({ element, descriptorPromise, }: {
|
|
96
|
+
element: Element;
|
|
97
|
+
descriptorPromise: Promise<SelectableData>;
|
|
98
|
+
}) => void;
|
|
99
|
+
commitInlineEdit: () => void;
|
|
100
|
+
revertInlineEdit: () => void;
|
|
101
|
+
formatCommand: (command: SelectModeFormatCommand) => void;
|
|
102
|
+
dismissInlineEditRequest: () => void;
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export declare const selectModeStore: import("zustand/traditional").UseBoundStoreWithEqualityFn<import("zustand").StoreApi<SelectModeStoreState>>;
|
|
106
|
+
export declare function useSelectModeStore(): import("zustand/traditional").UseBoundStoreWithEqualityFn<import("zustand").StoreApi<SelectModeStoreState>>;
|
|
107
|
+
export declare const useSelectModeStoreActions: () => {
|
|
108
|
+
reset: () => void;
|
|
109
|
+
setDisplayMode: (displayMode: DisplayMode) => void;
|
|
110
|
+
setSelectionType: ({ selectionType, selectors, }: {
|
|
111
|
+
selectionType: SelectModeSelectionType;
|
|
112
|
+
selectors?: string[];
|
|
113
|
+
}) => void;
|
|
114
|
+
setInteractionSession: (interactionSession: SelectModeInteractionSession) => void;
|
|
115
|
+
resetInteractionSession: () => void;
|
|
116
|
+
postSelectedElementSnapshot: (options?: {
|
|
117
|
+
clearMissing?: boolean;
|
|
118
|
+
}) => boolean;
|
|
119
|
+
showElementSelectionFrames: ({ elements, scrollOffset, }: {
|
|
120
|
+
elements: Element[];
|
|
121
|
+
scrollOffset: {
|
|
122
|
+
left: number;
|
|
123
|
+
top: number;
|
|
124
|
+
};
|
|
125
|
+
}) => void;
|
|
126
|
+
showAreaSelectionFrames: ({ elements, scrollOffset, }: {
|
|
127
|
+
elements: Element[];
|
|
128
|
+
scrollOffset: {
|
|
129
|
+
left: number;
|
|
130
|
+
top: number;
|
|
131
|
+
};
|
|
132
|
+
}) => void;
|
|
133
|
+
hideSelectionFrames: () => void;
|
|
134
|
+
setLastPointerClientPosition: (position: {
|
|
135
|
+
x: number;
|
|
136
|
+
y: number;
|
|
137
|
+
} | null) => void;
|
|
138
|
+
setLastPostedHoverRect: (rect: SelectModeBoundingRect | null | undefined) => void;
|
|
139
|
+
resetHoverRectDedup: () => void;
|
|
140
|
+
setHoverSyncAnimationFrameId: (id: number | null) => void;
|
|
141
|
+
setLastClick: (lastClick: LastClick | null) => void;
|
|
142
|
+
setDragCandidates: (dragCandidates: DragCandidate[]) => void;
|
|
143
|
+
setCommittedSelectionAtPointerDown: (elements: Element[]) => void;
|
|
144
|
+
setDragAnimationFrameId: (id: number | null) => void;
|
|
145
|
+
setScrollSyncAnimationFrameId: (id: number | null) => void;
|
|
146
|
+
beginEditing: ({ element, descriptorPromise, }: {
|
|
147
|
+
element: Element;
|
|
148
|
+
descriptorPromise: Promise<SelectableData>;
|
|
149
|
+
}) => void;
|
|
150
|
+
commitInlineEdit: () => void;
|
|
151
|
+
revertInlineEdit: () => void;
|
|
152
|
+
formatCommand: (command: SelectModeFormatCommand) => void;
|
|
153
|
+
dismissInlineEditRequest: () => void;
|
|
154
|
+
};
|
|
155
|
+
export declare const useDisplayMode: () => DisplayMode;
|
|
156
|
+
export declare const useSelectionFrames: () => SelectionFrameSpec[];
|
|
157
|
+
export declare const useIsSelectionFrameEditing: () => boolean;
|
|
158
|
+
export declare const useEditingElement: () => HTMLElement | null;
|
|
159
|
+
export declare const useInteractionSession: () => SelectModeInteractionSession;
|
|
160
|
+
export {};
|