@replohq/sandbox-runtime 0.1.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.
- package/ClientErrorBoundary.d.ts +10 -0
- package/ClientErrorBoundary.js +61 -0
- package/ClientErrorBoundary.js.map +7 -0
- package/DocumentReadyBeacon.d.ts +1 -0
- package/DocumentReadyBeacon.js +9 -0
- package/DocumentReadyBeacon.js.map +7 -0
- package/LICENSE +11 -0
- package/LinkInterceptor.d.ts +1 -0
- package/LinkInterceptor.js +128 -0
- package/LinkInterceptor.js.map +7 -0
- package/NextErrorReporter.d.ts +1 -0
- package/NextErrorReporter.js +92 -0
- package/NextErrorReporter.js.map +7 -0
- package/_vendor/replo-utils/lib/crypto.d.ts +30 -0
- package/_vendor/replo-utils/lib/errors.d.ts +83 -0
- package/_vendor/replo-utils/lib/fonts.d.ts +49 -0
- package/_vendor/replo-utils/lib/fonts.mjs +221 -0
- package/_vendor/replo-utils/lib/geometry.d.ts +18 -0
- package/_vendor/replo-utils/lib/geometry.mjs +9 -0
- package/_vendor/replo-utils/lib/json.d.ts +6 -0
- package/_vendor/replo-utils/lib/log.d.ts +11 -0
- package/_vendor/replo-utils/lib/misc.d.ts +145 -0
- package/_vendor/replo-utils/lib/misc.mjs +2 -0
- package/_vendor/replo-utils/lib/object.d.ts +31 -0
- package/_vendor/replo-utils/lib/parse.d.ts +15 -0
- package/_vendor/replo-utils/lib/posthogReplay.d.ts +43 -0
- package/_vendor/replo-utils/lib/posthogReplay.mjs +121 -0
- package/_vendor/replo-utils/react/use-iframe-rpc-channel.d.ts +14 -0
- package/_vendor/replo-utils/react/use-iframe-rpc-channel.mjs +14 -0
- package/_vendor/schemas/designLibrary.d.ts +361 -0
- package/_vendor/schemas/designLibrary.mjs +126 -0
- package/_vendor/schemas/errors.d.ts +459 -0
- package/_vendor/schemas/generated/errors.d.ts +61 -0
- package/_vendor/schemas/generated/pageAnnotations.d.ts +48 -0
- package/_vendor/schemas/generated/pageAnnotations.mjs +1 -0
- package/_vendor/schemas/generated/selectMode.d.ts +119 -0
- package/_vendor/schemas/generated/selectMode.mjs +1 -0
- package/_vendor/schemas/generated/selectModeIframeRpc.d.ts +100 -0
- package/_vendor/schemas/generated/selectModeIframeRpc.mjs +1 -0
- package/_vendor/schemas/iframeRpcChannel.d.ts +82 -0
- package/_vendor/schemas/iframeRpcChannel.mjs +520 -0
- package/_vendor/schemas/pageAnnotations.d.ts +134 -0
- package/_vendor/schemas/pageAnnotations.mjs +61 -0
- package/_vendor/schemas/savedStyles.d.ts +140 -0
- package/_vendor/schemas/selectMode.d.ts +522 -0
- package/_vendor/schemas/selectMode.mjs +3 -0
- package/_vendor/schemas/selectModeIframeRpc.d.ts +900 -0
- package/_vendor/schemas/selectModeIframeRpc.mjs +223 -0
- package/annotations/AnnotationLayerMount.d.ts +1 -0
- package/annotations/AnnotationLayerMount.js +13 -0
- package/annotations/AnnotationLayerMount.js.map +7 -0
- package/annotations/annotationController.d.ts +1 -0
- package/annotations/annotationController.js +384 -0
- package/annotations/annotationController.js.map +7 -0
- package/annotations/bridgeGate.d.ts +7 -0
- package/annotations/bridgeGate.js +22 -0
- package/annotations/bridgeGate.js.map +7 -0
- package/chunk-3UFG7XTQ.mjs +205 -0
- package/chunk-FNTGY7I5.mjs +68 -0
- package/chunk-N5EI2MOZ.mjs +1535 -0
- package/design-library-preview/DesignLibraryPreview.d.ts +1 -0
- package/design-library-preview/DesignLibraryPreview.js +93 -0
- package/design-library-preview/DesignLibraryPreview.js.map +7 -0
- package/package.json +41 -0
- package/posthog-relay.d.ts +11 -0
- package/posthog-relay.js +72 -0
- package/posthog-relay.js.map +7 -0
- package/sandbox-runtime.d.ts +1 -0
- package/sandbox-runtime.js +29 -0
- package/sandbox-runtime.js.map +7 -0
- package/select-mode/EditorSelection.d.ts +24 -0
- package/select-mode/EditorSelection.js +95 -0
- package/select-mode/EditorSelection.js.map +7 -0
- package/select-mode/annotationFrames.d.ts +33 -0
- package/select-mode/annotationFrames.js +119 -0
- package/select-mode/annotationFrames.js.map +7 -0
- package/select-mode/descriptor/elementDescriptor.d.ts +26 -0
- package/select-mode/descriptor/elementDescriptor.js +201 -0
- package/select-mode/descriptor/elementDescriptor.js.map +7 -0
- package/select-mode/descriptor/styleExtraction.d.ts +3 -0
- package/select-mode/descriptor/styleExtraction.js +271 -0
- package/select-mode/descriptor/styleExtraction.js.map +7 -0
- package/select-mode/displayModeStore.d.ts +10 -0
- package/select-mode/displayModeStore.js +47 -0
- package/select-mode/displayModeStore.js.map +7 -0
- package/select-mode/fast-refresh-relay.d.ts +3 -0
- package/select-mode/fast-refresh-relay.js +33 -0
- package/select-mode/fast-refresh-relay.js.map +7 -0
- package/select-mode/fiber.d.ts +49 -0
- package/select-mode/fiber.js +306 -0
- package/select-mode/fiber.js.map +7 -0
- package/select-mode/hooks/useCrosshairCursor.d.ts +12 -0
- package/select-mode/hooks/useCrosshairCursor.js +20 -0
- package/select-mode/hooks/useCrosshairCursor.js.map +7 -0
- package/select-mode/hooks/useEditModeStateMachine.d.ts +16 -0
- package/select-mode/hooks/useEditModeStateMachine.js +235 -0
- package/select-mode/hooks/useEditModeStateMachine.js.map +7 -0
- package/select-mode/hooks/useOptimisticOverrides.d.ts +17 -0
- package/select-mode/hooks/useOptimisticOverrides.js +283 -0
- package/select-mode/hooks/useOptimisticOverrides.js.map +7 -0
- package/select-mode/hooks/useParentMessaging.d.ts +36 -0
- package/select-mode/hooks/useParentMessaging.js +74 -0
- package/select-mode/hooks/useParentMessaging.js.map +7 -0
- package/select-mode/hooks/useSelectModeController.d.ts +8 -0
- package/select-mode/hooks/useSelectModeController.js +46 -0
- package/select-mode/hooks/useSelectModeController.js.map +7 -0
- package/select-mode/hooks/useSelectionHover.d.ts +22 -0
- package/select-mode/hooks/useSelectionHover.js +110 -0
- package/select-mode/hooks/useSelectionHover.js.map +7 -0
- package/select-mode/hooks/useSelectionInteractions.d.ts +37 -0
- package/select-mode/hooks/useSelectionInteractions.js +353 -0
- package/select-mode/hooks/useSelectionInteractions.js.map +7 -0
- package/select-mode/hooks/useSelectionScrollSync.d.ts +28 -0
- package/select-mode/hooks/useSelectionScrollSync.js +70 -0
- package/select-mode/hooks/useSelectionScrollSync.js.map +7 -0
- package/select-mode/hooks/useSiblingResolution.d.ts +6 -0
- package/select-mode/hooks/useSiblingResolution.js +59 -0
- package/select-mode/hooks/useSiblingResolution.js.map +7 -0
- package/select-mode/iframeRpcChannel.d.ts +356 -0
- package/select-mode/iframeRpcChannel.js +92 -0
- package/select-mode/iframeRpcChannel.js.map +7 -0
- package/select-mode/inlineTextMarks.d.ts +6 -0
- package/select-mode/inlineTextMarks.js +25 -0
- package/select-mode/inlineTextMarks.js.map +7 -0
- package/select-mode/interactions/selectionGeometry.d.ts +105 -0
- package/select-mode/interactions/selectionGeometry.js +192 -0
- package/select-mode/interactions/selectionGeometry.js.map +7 -0
- package/select-mode/selectModeSession.d.ts +21 -0
- package/select-mode/selectModeSession.js +7 -0
- package/select-mode/selectModeSession.js.map +7 -0
- package/select-mode/selectionFrame.d.ts +81 -0
- package/select-mode/selectionFrame.js +132 -0
- package/select-mode/selectionFrame.js.map +7 -0
- package/select-mode/symbolicate.d.ts +2 -0
- package/select-mode/symbolicate.js +200 -0
- package/select-mode/symbolicate.js.map +7 -0
- package/select-mode/tiptapInlineEditor.d.ts +23 -0
- package/select-mode/tiptapInlineEditor.js +120 -0
- package/select-mode/tiptapInlineEditor.js.map +7 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { useEffect, useMemo } from "react";
|
|
2
|
+
import { useIframeRpcChannel } from "../../_vendor/replo-utils/react/use-iframe-rpc-channel.mjs";
|
|
3
|
+
import {
|
|
4
|
+
getSelectModeIframeRpcChannel,
|
|
5
|
+
getWebsiteBuilderRpc,
|
|
6
|
+
setSelectModeParentHandlers
|
|
7
|
+
} from "../iframeRpcChannel";
|
|
8
|
+
function useParentMessaging({
|
|
9
|
+
applyOptimisticUpdate,
|
|
10
|
+
markCommitted,
|
|
11
|
+
resolveSessionOverrides,
|
|
12
|
+
onEnterEditMode,
|
|
13
|
+
onExitEditMode,
|
|
14
|
+
onFormatCommand,
|
|
15
|
+
revertOverride,
|
|
16
|
+
setDisplayMode,
|
|
17
|
+
setSelectionType
|
|
18
|
+
}) {
|
|
19
|
+
useIframeRpcChannel(useMemo(() => getSelectModeIframeRpcChannel(), []));
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
setSelectModeParentHandlers({
|
|
22
|
+
setDisplayMode: ({ displayMode }) => {
|
|
23
|
+
setDisplayMode(displayMode);
|
|
24
|
+
},
|
|
25
|
+
setSelectionType: ({ selectionType }) => {
|
|
26
|
+
setSelectionType(selectionType);
|
|
27
|
+
},
|
|
28
|
+
applyOptimisticUpdate: (message) => {
|
|
29
|
+
applyOptimisticUpdate?.({
|
|
30
|
+
editId: message.editId,
|
|
31
|
+
payload: message.payload,
|
|
32
|
+
targetSelector: message.targetSelector,
|
|
33
|
+
targetMode: message.targetMode
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
markCommitted: ({ editId, sessionId }) => {
|
|
37
|
+
markCommitted?.(editId, sessionId);
|
|
38
|
+
},
|
|
39
|
+
resolveSessionOverrides: ({ sessionId, outcome }) => {
|
|
40
|
+
resolveSessionOverrides?.(sessionId, outcome);
|
|
41
|
+
},
|
|
42
|
+
revertOverride: ({ editId }) => {
|
|
43
|
+
revertOverride?.(editId);
|
|
44
|
+
},
|
|
45
|
+
enterEditMode: () => {
|
|
46
|
+
onEnterEditMode?.();
|
|
47
|
+
},
|
|
48
|
+
exitEditMode: () => {
|
|
49
|
+
onExitEditMode?.();
|
|
50
|
+
},
|
|
51
|
+
formatCommand: ({ command }) => {
|
|
52
|
+
onFormatCommand?.(command);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
getWebsiteBuilderRpc()?.iframeReady(void 0);
|
|
56
|
+
return () => {
|
|
57
|
+
setSelectModeParentHandlers(null);
|
|
58
|
+
};
|
|
59
|
+
}, [
|
|
60
|
+
applyOptimisticUpdate,
|
|
61
|
+
markCommitted,
|
|
62
|
+
resolveSessionOverrides,
|
|
63
|
+
onEnterEditMode,
|
|
64
|
+
onExitEditMode,
|
|
65
|
+
onFormatCommand,
|
|
66
|
+
revertOverride,
|
|
67
|
+
setDisplayMode,
|
|
68
|
+
setSelectionType
|
|
69
|
+
]);
|
|
70
|
+
}
|
|
71
|
+
export {
|
|
72
|
+
useParentMessaging
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=useParentMessaging.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../select-mode/hooks/useParentMessaging.ts"],
|
|
4
|
+
"sourcesContent": ["import type {\n DisplayMode,\n SelectModeFormatCommand,\n SelectModeOptimisticUpdatePayload,\n SelectModeSelectionType,\n} from \"schemas/generated/selectMode\";\n\nimport { useEffect, useMemo } from \"react\";\n\nimport { useIframeRpcChannel } from \"replo-utils/react/use-iframe-rpc-channel\";\n\nimport {\n getSelectModeIframeRpcChannel,\n getWebsiteBuilderRpc,\n setSelectModeParentHandlers,\n} from \"../iframeRpcChannel\";\n\n/**\n * Inbound side of the iframe<->parent selectMode bridge.\n *\n * Listens for Website Builder \u2192 canopy methods and applies them locally:\n * - `setDisplayMode`: switch the iframe between `browse` and `selection`.\n * - `setSelectionType`: declarative push of the parent's current\n * selection type. The interesting transition is `* \u2192 \"none\"`, which\n * tears down any in-iframe selection frame / in-progress drag \u2014 agent-ui\n * drives it from `agentUiState.selectionType` so panel dismiss / submit\n * flow through the same path as exiting selection mode entirely. The\n * regression test in `EditorSelection.spec.tsx` covers the case where\n * losing this used to lock the iframe out of further selections.\n *\n * Also fires `iframeReady` on mount so the parent knows it's safe to push\n * the initial `setDisplayMode` \u2014 without this handshake the parent would\n * race the iframe's mount and the first message could be lost.\n *\n * @author Kevin O'Connell 2026-04-17\n */\nexport function useParentMessaging({\n applyOptimisticUpdate,\n markCommitted,\n resolveSessionOverrides,\n onEnterEditMode,\n onExitEditMode,\n onFormatCommand,\n revertOverride,\n setDisplayMode,\n setSelectionType,\n}: {\n applyOptimisticUpdate?: (input: {\n editId: string;\n payload: SelectModeOptimisticUpdatePayload;\n targetSelector: string;\n targetMode: \"primary\" | \"group\";\n }) => void;\n markCommitted?: (editId: string, sessionId: string) => void;\n resolveSessionOverrides?: (\n sessionId: string,\n outcome: \"persisted\" | \"failed\",\n ) => void;\n onEnterEditMode?: () => void;\n onExitEditMode?: () => void;\n onFormatCommand?: (command: SelectModeFormatCommand) => void;\n revertOverride?: (editId: string) => void;\n setDisplayMode: (displayMode: DisplayMode) => void;\n setSelectionType: (selectionType: SelectModeSelectionType) => void;\n}) {\n useIframeRpcChannel(useMemo(() => getSelectModeIframeRpcChannel(), []));\n\n // eslint-disable-next-line replo/no-use-effect -- Legacy effect - may or may not be necessary\n useEffect(() => {\n setSelectModeParentHandlers({\n setDisplayMode: ({ displayMode }) => {\n setDisplayMode(displayMode);\n },\n setSelectionType: ({ selectionType }) => {\n setSelectionType(selectionType);\n },\n applyOptimisticUpdate: (message) => {\n applyOptimisticUpdate?.({\n editId: message.editId,\n payload: message.payload,\n targetSelector: message.targetSelector,\n targetMode: message.targetMode,\n });\n },\n markCommitted: ({ editId, sessionId }) => {\n markCommitted?.(editId, sessionId);\n },\n resolveSessionOverrides: ({ sessionId, outcome }) => {\n resolveSessionOverrides?.(sessionId, outcome);\n },\n revertOverride: ({ editId }) => {\n revertOverride?.(editId);\n },\n enterEditMode: () => {\n onEnterEditMode?.();\n },\n exitEditMode: () => {\n onExitEditMode?.();\n },\n formatCommand: ({ command }) => {\n onFormatCommand?.(command);\n },\n });\n getWebsiteBuilderRpc()?.iframeReady(undefined);\n\n return () => {\n setSelectModeParentHandlers(null);\n };\n }, [\n applyOptimisticUpdate,\n markCommitted,\n resolveSessionOverrides,\n onEnterEditMode,\n onExitEditMode,\n onFormatCommand,\n revertOverride,\n setDisplayMode,\n setSelectionType,\n ]);\n}\n"],
|
|
5
|
+
"mappings": "AAOA,SAAS,WAAW,eAAe;AAEnC,SAAS,2BAA2B;AAEpC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAqBA,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAkBG;AACD,sBAAoB,QAAQ,MAAM,8BAA8B,GAAG,CAAC,CAAC,CAAC;AAGtE,YAAU,MAAM;AACd,gCAA4B;AAAA,MAC1B,gBAAgB,CAAC,EAAE,YAAY,MAAM;AACnC,uBAAe,WAAW;AAAA,MAC5B;AAAA,MACA,kBAAkB,CAAC,EAAE,cAAc,MAAM;AACvC,yBAAiB,aAAa;AAAA,MAChC;AAAA,MACA,uBAAuB,CAAC,YAAY;AAClC,gCAAwB;AAAA,UACtB,QAAQ,QAAQ;AAAA,UAChB,SAAS,QAAQ;AAAA,UACjB,gBAAgB,QAAQ;AAAA,UACxB,YAAY,QAAQ;AAAA,QACtB,CAAC;AAAA,MACH;AAAA,MACA,eAAe,CAAC,EAAE,QAAQ,UAAU,MAAM;AACxC,wBAAgB,QAAQ,SAAS;AAAA,MACnC;AAAA,MACA,yBAAyB,CAAC,EAAE,WAAW,QAAQ,MAAM;AACnD,kCAA0B,WAAW,OAAO;AAAA,MAC9C;AAAA,MACA,gBAAgB,CAAC,EAAE,OAAO,MAAM;AAC9B,yBAAiB,MAAM;AAAA,MACzB;AAAA,MACA,eAAe,MAAM;AACnB,0BAAkB;AAAA,MACpB;AAAA,MACA,cAAc,MAAM;AAClB,yBAAiB;AAAA,MACnB;AAAA,MACA,eAAe,CAAC,EAAE,QAAQ,MAAM;AAC9B,0BAAkB,OAAO;AAAA,MAC3B;AAAA,IACF,CAAC;AACD,yBAAqB,GAAG,YAAY,MAAS;AAE7C,WAAO,MAAM;AACX,kCAA4B,IAAI;AAAA,IAClC;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DisplayMode, SelectModeSelectionType } from "../../_vendor/schemas/generated/selectMode";
|
|
2
|
+
import type { SelectModeInteractionSession } from "../selectModeSession";
|
|
3
|
+
export declare function useSelectModeController(): {
|
|
4
|
+
displayMode: DisplayMode;
|
|
5
|
+
interactionSessionRef: import("react").RefObject<SelectModeInteractionSession>;
|
|
6
|
+
setDisplayMode: (nextDisplayMode: DisplayMode) => void;
|
|
7
|
+
setSelectionType: (selectionType: SelectModeSelectionType) => void;
|
|
8
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useCallback, useRef } from "react";
|
|
2
|
+
import { displayModeStore, useDisplayMode } from "../displayModeStore";
|
|
3
|
+
import { getWebsiteBuilderRpc } from "../iframeRpcChannel";
|
|
4
|
+
import { hideSelectionFrame } from "../selectionFrame";
|
|
5
|
+
import { IDLE_SESSION } from "../selectModeSession";
|
|
6
|
+
function resetInteractionSession({
|
|
7
|
+
interactionSessionRef
|
|
8
|
+
}) {
|
|
9
|
+
const currentSession = interactionSessionRef.current;
|
|
10
|
+
if (currentSession.type === "drag" && currentSession.hasExceededThreshold) {
|
|
11
|
+
getWebsiteBuilderRpc()?.dragRectUpdated({
|
|
12
|
+
dragRect: null,
|
|
13
|
+
selectionRects: []
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
hideSelectionFrame();
|
|
17
|
+
interactionSessionRef.current = IDLE_SESSION;
|
|
18
|
+
}
|
|
19
|
+
function useSelectModeController() {
|
|
20
|
+
const displayMode = useDisplayMode();
|
|
21
|
+
const interactionSessionRef = useRef(IDLE_SESSION);
|
|
22
|
+
const setSelectionType = useCallback(
|
|
23
|
+
(selectionType) => {
|
|
24
|
+
if (selectionType === "none") {
|
|
25
|
+
resetInteractionSession({ interactionSessionRef });
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
[]
|
|
29
|
+
);
|
|
30
|
+
const setDisplayMode = useCallback((nextDisplayMode) => {
|
|
31
|
+
if (displayModeStore.getSnapshot() === "selection" && nextDisplayMode !== "selection") {
|
|
32
|
+
resetInteractionSession({ interactionSessionRef });
|
|
33
|
+
}
|
|
34
|
+
displayModeStore.setDisplayMode(nextDisplayMode);
|
|
35
|
+
}, []);
|
|
36
|
+
return {
|
|
37
|
+
displayMode,
|
|
38
|
+
interactionSessionRef,
|
|
39
|
+
setDisplayMode,
|
|
40
|
+
setSelectionType
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
useSelectModeController
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=useSelectModeController.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../select-mode/hooks/useSelectModeController.ts"],
|
|
4
|
+
"sourcesContent": ["import type {\n DisplayMode,\n SelectModeSelectionType,\n} from \"schemas/generated/selectMode\";\nimport type { SelectModeInteractionSession } from \"../selectModeSession\";\n\nimport { useCallback, useRef } from \"react\";\n\nimport { displayModeStore, useDisplayMode } from \"../displayModeStore\";\nimport { getWebsiteBuilderRpc } from \"../iframeRpcChannel\";\nimport { hideSelectionFrame } from \"../selectionFrame\";\nimport { IDLE_SESSION } from \"../selectModeSession\";\n\n/**\n * Tear down any in-progress drag/selection. Re-used by both the\n * display-mode flip-out path (defensive: belt-and-braces with the\n * parent's `setSelectionType(\"none\")` push) and by the explicit\n * `setSelectionType(\"none\")` path below.\n */\nfunction resetInteractionSession({\n interactionSessionRef,\n}: {\n interactionSessionRef: React.MutableRefObject<SelectModeInteractionSession>;\n}) {\n const currentSession = interactionSessionRef.current;\n if (currentSession.type === \"drag\" && currentSession.hasExceededThreshold) {\n getWebsiteBuilderRpc()?.dragRectUpdated({\n dragRect: null,\n selectionRects: [],\n });\n }\n hideSelectionFrame();\n interactionSessionRef.current = IDLE_SESSION;\n}\n\nexport function useSelectModeController() {\n // Display mode lives in a module singleton so the sibling `LinkInterceptor`\n // can read it (and stand down during selection) without a shared provider.\n const displayMode = useDisplayMode();\n const interactionSessionRef =\n useRef<SelectModeInteractionSession>(IDLE_SESSION);\n\n // The parent is authoritative for \"is there a current selection?\". Canopy\n // originates selections via pointer events, posts them up, agent-ui\n // mirrors `selection.type` into `agentUiState`, and the result is pushed\n // back down here. When the parent says `none` (panel dismissed / submit /\n // exit selection mode) we tear down the in-iframe frame; the matching\n // commit-side paths are in `useSelectionInteractions`.\n const setSelectionType = useCallback(\n (selectionType: SelectModeSelectionType) => {\n if (selectionType === \"none\") {\n resetInteractionSession({ interactionSessionRef });\n }\n },\n [],\n );\n\n const setDisplayMode = useCallback((nextDisplayMode: DisplayMode) => {\n if (\n displayModeStore.getSnapshot() === \"selection\" &&\n nextDisplayMode !== \"selection\"\n ) {\n resetInteractionSession({ interactionSessionRef });\n }\n\n displayModeStore.setDisplayMode(nextDisplayMode);\n }, []);\n\n return {\n displayMode,\n interactionSessionRef,\n setDisplayMode,\n setSelectionType,\n };\n}\n"],
|
|
5
|
+
"mappings": "AAMA,SAAS,aAAa,cAAc;AAEpC,SAAS,kBAAkB,sBAAsB;AACjD,SAAS,4BAA4B;AACrC,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;AAQ7B,SAAS,wBAAwB;AAAA,EAC/B;AACF,GAEG;AACD,QAAM,iBAAiB,sBAAsB;AAC7C,MAAI,eAAe,SAAS,UAAU,eAAe,sBAAsB;AACzE,yBAAqB,GAAG,gBAAgB;AAAA,MACtC,UAAU;AAAA,MACV,gBAAgB,CAAC;AAAA,IACnB,CAAC;AAAA,EACH;AACA,qBAAmB;AACnB,wBAAsB,UAAU;AAClC;AAEO,SAAS,0BAA0B;AAGxC,QAAM,cAAc,eAAe;AACnC,QAAM,wBACJ,OAAqC,YAAY;AAQnD,QAAM,mBAAmB;AAAA,IACvB,CAAC,kBAA2C;AAC1C,UAAI,kBAAkB,QAAQ;AAC5B,gCAAwB,EAAE,sBAAsB,CAAC;AAAA,MACnD;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,iBAAiB,YAAY,CAAC,oBAAiC;AACnE,QACE,iBAAiB,YAAY,MAAM,eACnC,oBAAoB,aACpB;AACA,8BAAwB,EAAE,sBAAsB,CAAC;AAAA,IACnD;AAEA,qBAAiB,eAAe,eAAe;AAAA,EACjD,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { MutableRefObject } from "react";
|
|
2
|
+
import type { DisplayMode } from "../../_vendor/schemas/generated/selectMode";
|
|
3
|
+
import type { SelectModeInteractionSession } from "../selectModeSession";
|
|
4
|
+
/**
|
|
5
|
+
* Tracks whichever element is under the user's pointer while in `selection`
|
|
6
|
+
* mode and reports its bounding rect to the parent so the parent can render
|
|
7
|
+
* the hover overlay.
|
|
8
|
+
*
|
|
9
|
+
* Two behaviors worth knowing about:
|
|
10
|
+
* - During an active drag we suppress hover updates; the drag overlay is
|
|
11
|
+
* the only highlight we want visible.
|
|
12
|
+
* - On scroll/wheel/resize we re-run the hover lookup from the last known
|
|
13
|
+
* pointer position (we use rAF to coalesce). Without this, scrolling
|
|
14
|
+
* over an already-hovered element wouldn't update the highlight to the
|
|
15
|
+
* new element actually under the cursor.
|
|
16
|
+
*
|
|
17
|
+
* @author Kevin O'Connell 2026-04-17
|
|
18
|
+
*/
|
|
19
|
+
export declare function useSelectionHover({ displayMode, interactionSessionRef, }: {
|
|
20
|
+
displayMode: DisplayMode;
|
|
21
|
+
interactionSessionRef: MutableRefObject<SelectModeInteractionSession>;
|
|
22
|
+
}): void;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
import { getNearestSelectableElement } from "../descriptor/elementDescriptor";
|
|
3
|
+
import { getWebsiteBuilderRpc } from "../iframeRpcChannel";
|
|
4
|
+
import { getElementBoundingRect } from "../interactions/selectionGeometry";
|
|
5
|
+
function useSelectionHover({
|
|
6
|
+
displayMode,
|
|
7
|
+
interactionSessionRef
|
|
8
|
+
}) {
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
if (displayMode !== "selection") {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
let hoverSyncAnimationFrameId = null;
|
|
14
|
+
let lastPointerClientPosition = null;
|
|
15
|
+
const postHoveredElement = (element) => {
|
|
16
|
+
getWebsiteBuilderRpc()?.hoverElement({
|
|
17
|
+
rect: element ? getElementBoundingRect(element) : null
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
const syncCurrentHover = (pointerClientPosition = lastPointerClientPosition) => {
|
|
21
|
+
let hoveredElement = null;
|
|
22
|
+
if (pointerClientPosition) {
|
|
23
|
+
const isPointerWithinViewport = pointerClientPosition.x >= 0 && pointerClientPosition.y >= 0 && pointerClientPosition.x <= window.innerWidth && pointerClientPosition.y <= window.innerHeight;
|
|
24
|
+
if (isPointerWithinViewport) {
|
|
25
|
+
hoveredElement = document.elementFromPoint(
|
|
26
|
+
pointerClientPosition.x,
|
|
27
|
+
pointerClientPosition.y
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (!hoveredElement) {
|
|
32
|
+
const hoveredElementStack = document.querySelectorAll(":hover");
|
|
33
|
+
hoveredElement = hoveredElementStack[hoveredElementStack.length - 1] ?? null;
|
|
34
|
+
}
|
|
35
|
+
postHoveredElement(
|
|
36
|
+
hoveredElement ? getNearestSelectableElement(hoveredElement) : null
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
const scheduleHoverSync = () => {
|
|
40
|
+
if (interactionSessionRef.current.type === "drag" || hoverSyncAnimationFrameId !== null) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
hoverSyncAnimationFrameId = requestAnimationFrame(() => {
|
|
44
|
+
hoverSyncAnimationFrameId = null;
|
|
45
|
+
syncCurrentHover();
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
const handlePointerMove = (event) => {
|
|
49
|
+
lastPointerClientPosition = {
|
|
50
|
+
x: event.clientX,
|
|
51
|
+
y: event.clientY
|
|
52
|
+
};
|
|
53
|
+
if (interactionSessionRef.current.type === "drag") {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
syncCurrentHover(lastPointerClientPosition);
|
|
57
|
+
};
|
|
58
|
+
const handlePointerOver = (event) => {
|
|
59
|
+
lastPointerClientPosition = {
|
|
60
|
+
x: event.clientX,
|
|
61
|
+
y: event.clientY
|
|
62
|
+
};
|
|
63
|
+
if (interactionSessionRef.current.type === "drag") {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
syncCurrentHover(lastPointerClientPosition);
|
|
67
|
+
};
|
|
68
|
+
const handlePointerOut = (event) => {
|
|
69
|
+
if (interactionSessionRef.current.type === "drag") {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const nextRelatedTarget = event.relatedTarget;
|
|
73
|
+
if (nextRelatedTarget instanceof Node && document.contains(nextRelatedTarget)) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
lastPointerClientPosition = null;
|
|
77
|
+
postHoveredElement(null);
|
|
78
|
+
};
|
|
79
|
+
const handleViewportChange = () => {
|
|
80
|
+
scheduleHoverSync();
|
|
81
|
+
};
|
|
82
|
+
syncCurrentHover();
|
|
83
|
+
document.addEventListener("pointermove", handlePointerMove, true);
|
|
84
|
+
document.addEventListener("pointerover", handlePointerOver, true);
|
|
85
|
+
document.addEventListener("pointerout", handlePointerOut, true);
|
|
86
|
+
document.addEventListener("scroll", handleViewportChange, true);
|
|
87
|
+
document.addEventListener("wheel", handleViewportChange, {
|
|
88
|
+
capture: true,
|
|
89
|
+
passive: true
|
|
90
|
+
});
|
|
91
|
+
window.addEventListener("resize", handleViewportChange);
|
|
92
|
+
return () => {
|
|
93
|
+
if (hoverSyncAnimationFrameId !== null) {
|
|
94
|
+
cancelAnimationFrame(hoverSyncAnimationFrameId);
|
|
95
|
+
}
|
|
96
|
+
document.removeEventListener("pointermove", handlePointerMove, true);
|
|
97
|
+
document.removeEventListener("pointerover", handlePointerOver, true);
|
|
98
|
+
document.removeEventListener("pointerout", handlePointerOut, true);
|
|
99
|
+
document.removeEventListener("scroll", handleViewportChange, true);
|
|
100
|
+
document.removeEventListener("wheel", handleViewportChange, {
|
|
101
|
+
capture: true
|
|
102
|
+
});
|
|
103
|
+
window.removeEventListener("resize", handleViewportChange);
|
|
104
|
+
};
|
|
105
|
+
}, [displayMode, interactionSessionRef]);
|
|
106
|
+
}
|
|
107
|
+
export {
|
|
108
|
+
useSelectionHover
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=useSelectionHover.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../select-mode/hooks/useSelectionHover.ts"],
|
|
4
|
+
"sourcesContent": ["import type { MutableRefObject } from \"react\";\nimport type { DisplayMode } from \"schemas/generated/selectMode\";\nimport type { SelectModeInteractionSession } from \"../selectModeSession\";\n\nimport { useEffect } from \"react\";\n\nimport { getNearestSelectableElement } from \"../descriptor/elementDescriptor\";\nimport { getWebsiteBuilderRpc } from \"../iframeRpcChannel\";\nimport { getElementBoundingRect } from \"../interactions/selectionGeometry\";\n\n/**\n * Tracks whichever element is under the user's pointer while in `selection`\n * mode and reports its bounding rect to the parent so the parent can render\n * the hover overlay.\n *\n * Two behaviors worth knowing about:\n * - During an active drag we suppress hover updates; the drag overlay is\n * the only highlight we want visible.\n * - On scroll/wheel/resize we re-run the hover lookup from the last known\n * pointer position (we use rAF to coalesce). Without this, scrolling\n * over an already-hovered element wouldn't update the highlight to the\n * new element actually under the cursor.\n *\n * @author Kevin O'Connell 2026-04-17\n */\nexport function useSelectionHover({\n displayMode,\n interactionSessionRef,\n}: {\n displayMode: DisplayMode;\n interactionSessionRef: MutableRefObject<SelectModeInteractionSession>;\n}) {\n // eslint-disable-next-line replo/no-use-effect -- Legacy effect - may or may not be necessary\n useEffect(() => {\n if (displayMode !== \"selection\") {\n return;\n }\n\n let hoverSyncAnimationFrameId: number | null = null;\n let lastPointerClientPosition: { x: number; y: number } | null = null;\n\n // NOTE (Kevin O'Connell, 2026-04-20): `null` is the deliberate \"no element\n // under pointer / pointer left viewport\" signal \u2014 it produces a\n // clear-hover notification to the parent, not an error.\n const postHoveredElement = (element: Element | null) => {\n // The hover overlay only needs the element rect \u2014 serializing the full\n // styled outerHTML on every pointer move would be wasteful and never\n // consumed by the parent.\n getWebsiteBuilderRpc()?.hoverElement({\n rect: element ? getElementBoundingRect(element) : null,\n });\n };\n\n const syncCurrentHover = (\n pointerClientPosition = lastPointerClientPosition,\n ) => {\n let hoveredElement: Element | null = null;\n\n if (pointerClientPosition) {\n const isPointerWithinViewport =\n pointerClientPosition.x >= 0 &&\n pointerClientPosition.y >= 0 &&\n pointerClientPosition.x <= window.innerWidth &&\n pointerClientPosition.y <= window.innerHeight;\n\n if (isPointerWithinViewport) {\n hoveredElement = document.elementFromPoint(\n pointerClientPosition.x,\n pointerClientPosition.y,\n );\n }\n }\n\n if (!hoveredElement) {\n const hoveredElementStack = document.querySelectorAll(\":hover\");\n hoveredElement =\n hoveredElementStack[hoveredElementStack.length - 1] ?? null;\n }\n\n postHoveredElement(\n hoveredElement ? getNearestSelectableElement(hoveredElement) : null,\n );\n };\n\n const scheduleHoverSync = () => {\n if (\n interactionSessionRef.current.type === \"drag\" ||\n hoverSyncAnimationFrameId !== null\n ) {\n return;\n }\n\n hoverSyncAnimationFrameId = requestAnimationFrame(() => {\n hoverSyncAnimationFrameId = null;\n syncCurrentHover();\n });\n };\n\n const handlePointerMove = (event: PointerEvent) => {\n lastPointerClientPosition = {\n x: event.clientX,\n y: event.clientY,\n };\n\n if (interactionSessionRef.current.type === \"drag\") {\n return;\n }\n\n syncCurrentHover(lastPointerClientPosition);\n };\n\n // Catches the \"cursor is already inside the iframe when select mode\n // toggles on\" case \u2014 pointermove only fires on motion, so a stationary\n // cursor would otherwise wait forever for the first hover sync.\n const handlePointerOver = (event: PointerEvent) => {\n lastPointerClientPosition = {\n x: event.clientX,\n y: event.clientY,\n };\n\n if (interactionSessionRef.current.type === \"drag\") {\n return;\n }\n\n syncCurrentHover(lastPointerClientPosition);\n };\n\n const handlePointerOut = (event: PointerEvent) => {\n if (interactionSessionRef.current.type === \"drag\") {\n return;\n }\n\n const nextRelatedTarget = event.relatedTarget;\n if (\n nextRelatedTarget instanceof Node &&\n document.contains(nextRelatedTarget)\n ) {\n return;\n }\n\n lastPointerClientPosition = null;\n postHoveredElement(null);\n };\n\n const handleViewportChange = () => {\n scheduleHoverSync();\n };\n\n syncCurrentHover();\n document.addEventListener(\"pointermove\", handlePointerMove, true);\n document.addEventListener(\"pointerover\", handlePointerOver, true);\n document.addEventListener(\"pointerout\", handlePointerOut, true);\n document.addEventListener(\"scroll\", handleViewportChange, true);\n document.addEventListener(\"wheel\", handleViewportChange, {\n capture: true,\n passive: true,\n });\n window.addEventListener(\"resize\", handleViewportChange);\n\n return () => {\n if (hoverSyncAnimationFrameId !== null) {\n cancelAnimationFrame(hoverSyncAnimationFrameId);\n }\n document.removeEventListener(\"pointermove\", handlePointerMove, true);\n document.removeEventListener(\"pointerover\", handlePointerOver, true);\n document.removeEventListener(\"pointerout\", handlePointerOut, true);\n document.removeEventListener(\"scroll\", handleViewportChange, true);\n document.removeEventListener(\"wheel\", handleViewportChange, {\n capture: true,\n });\n window.removeEventListener(\"resize\", handleViewportChange);\n };\n }, [displayMode, interactionSessionRef]);\n}\n"],
|
|
5
|
+
"mappings": "AAIA,SAAS,iBAAiB;AAE1B,SAAS,mCAAmC;AAC5C,SAAS,4BAA4B;AACrC,SAAS,8BAA8B;AAiBhC,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AACF,GAGG;AAED,YAAU,MAAM;AACd,QAAI,gBAAgB,aAAa;AAC/B;AAAA,IACF;AAEA,QAAI,4BAA2C;AAC/C,QAAI,4BAA6D;AAKjE,UAAM,qBAAqB,CAAC,YAA4B;AAItD,2BAAqB,GAAG,aAAa;AAAA,QACnC,MAAM,UAAU,uBAAuB,OAAO,IAAI;AAAA,MACpD,CAAC;AAAA,IACH;AAEA,UAAM,mBAAmB,CACvB,wBAAwB,8BACrB;AACH,UAAI,iBAAiC;AAErC,UAAI,uBAAuB;AACzB,cAAM,0BACJ,sBAAsB,KAAK,KAC3B,sBAAsB,KAAK,KAC3B,sBAAsB,KAAK,OAAO,cAClC,sBAAsB,KAAK,OAAO;AAEpC,YAAI,yBAAyB;AAC3B,2BAAiB,SAAS;AAAA,YACxB,sBAAsB;AAAA,YACtB,sBAAsB;AAAA,UACxB;AAAA,QACF;AAAA,MACF;AAEA,UAAI,CAAC,gBAAgB;AACnB,cAAM,sBAAsB,SAAS,iBAAiB,QAAQ;AAC9D,yBACE,oBAAoB,oBAAoB,SAAS,CAAC,KAAK;AAAA,MAC3D;AAEA;AAAA,QACE,iBAAiB,4BAA4B,cAAc,IAAI;AAAA,MACjE;AAAA,IACF;AAEA,UAAM,oBAAoB,MAAM;AAC9B,UACE,sBAAsB,QAAQ,SAAS,UACvC,8BAA8B,MAC9B;AACA;AAAA,MACF;AAEA,kCAA4B,sBAAsB,MAAM;AACtD,oCAA4B;AAC5B,yBAAiB;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,UAAM,oBAAoB,CAAC,UAAwB;AACjD,kCAA4B;AAAA,QAC1B,GAAG,MAAM;AAAA,QACT,GAAG,MAAM;AAAA,MACX;AAEA,UAAI,sBAAsB,QAAQ,SAAS,QAAQ;AACjD;AAAA,MACF;AAEA,uBAAiB,yBAAyB;AAAA,IAC5C;AAKA,UAAM,oBAAoB,CAAC,UAAwB;AACjD,kCAA4B;AAAA,QAC1B,GAAG,MAAM;AAAA,QACT,GAAG,MAAM;AAAA,MACX;AAEA,UAAI,sBAAsB,QAAQ,SAAS,QAAQ;AACjD;AAAA,MACF;AAEA,uBAAiB,yBAAyB;AAAA,IAC5C;AAEA,UAAM,mBAAmB,CAAC,UAAwB;AAChD,UAAI,sBAAsB,QAAQ,SAAS,QAAQ;AACjD;AAAA,MACF;AAEA,YAAM,oBAAoB,MAAM;AAChC,UACE,6BAA6B,QAC7B,SAAS,SAAS,iBAAiB,GACnC;AACA;AAAA,MACF;AAEA,kCAA4B;AAC5B,yBAAmB,IAAI;AAAA,IACzB;AAEA,UAAM,uBAAuB,MAAM;AACjC,wBAAkB;AAAA,IACpB;AAEA,qBAAiB;AACjB,aAAS,iBAAiB,eAAe,mBAAmB,IAAI;AAChE,aAAS,iBAAiB,eAAe,mBAAmB,IAAI;AAChE,aAAS,iBAAiB,cAAc,kBAAkB,IAAI;AAC9D,aAAS,iBAAiB,UAAU,sBAAsB,IAAI;AAC9D,aAAS,iBAAiB,SAAS,sBAAsB;AAAA,MACvD,SAAS;AAAA,MACT,SAAS;AAAA,IACX,CAAC;AACD,WAAO,iBAAiB,UAAU,oBAAoB;AAEtD,WAAO,MAAM;AACX,UAAI,8BAA8B,MAAM;AACtC,6BAAqB,yBAAyB;AAAA,MAChD;AACA,eAAS,oBAAoB,eAAe,mBAAmB,IAAI;AACnE,eAAS,oBAAoB,eAAe,mBAAmB,IAAI;AACnE,eAAS,oBAAoB,cAAc,kBAAkB,IAAI;AACjE,eAAS,oBAAoB,UAAU,sBAAsB,IAAI;AACjE,eAAS,oBAAoB,SAAS,sBAAsB;AAAA,QAC1D,SAAS;AAAA,MACX,CAAC;AACD,aAAO,oBAAoB,UAAU,oBAAoB;AAAA,IAC3D;AAAA,EACF,GAAG,CAAC,aAAa,qBAAqB,CAAC;AACzC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { MutableRefObject } from "react";
|
|
2
|
+
import type { DisplayMode, SelectableData } from "../../_vendor/schemas/generated/selectMode";
|
|
3
|
+
import type { SelectModeInteractionSession } from "../selectModeSession";
|
|
4
|
+
/**
|
|
5
|
+
* Owns the iframe-side pointer interactions that drive selection:
|
|
6
|
+
*
|
|
7
|
+
* - On `pointerdown` we open a `drag` session (storing both client + page
|
|
8
|
+
* coords plus the current scroll offset). We don't yet know if this will
|
|
9
|
+
* become a click or an actual drag.
|
|
10
|
+
* - On `pointermove` we update the drag rect and post `DRAG_RECT_UPDATED`
|
|
11
|
+
* to the parent so the live drag rectangle can render. We only flip
|
|
12
|
+
* `hasExceededThreshold` once the rect grows past 6×6 px so that a tiny
|
|
13
|
+
* accidental drag still resolves as a click.
|
|
14
|
+
* - On `pointerup` we either:
|
|
15
|
+
* - resolve as an `ELEMENT_SELECTED` (single click / sub-threshold drag)
|
|
16
|
+
* - resolve as an `AREA_SELECTED` (drag past threshold), filtering the
|
|
17
|
+
* candidates snapshotted at drag start against the final rectangle to
|
|
18
|
+
* enumerate which descendants the user enclosed.
|
|
19
|
+
* - During an active drag a `requestAnimationFrame` loop keeps the rect in
|
|
20
|
+
* sync with the page scroll so the rectangle visually "sticks" to the
|
|
21
|
+
* page rather than the viewport.
|
|
22
|
+
*
|
|
23
|
+
* We capture-listen and `preventDefault`/`stopPropagation` clicks so the
|
|
24
|
+
* underlying page can't navigate or trigger handlers while the user is
|
|
25
|
+
* working in selection mode.
|
|
26
|
+
*
|
|
27
|
+
* @author Kevin O'Connell 2026-04-17
|
|
28
|
+
*/
|
|
29
|
+
export declare function useSelectionInteractions({ displayMode, editingElementRef, interactionSessionRef, onBeginEditing, }: {
|
|
30
|
+
displayMode: DisplayMode;
|
|
31
|
+
editingElementRef?: MutableRefObject<HTMLElement | null>;
|
|
32
|
+
interactionSessionRef: MutableRefObject<SelectModeInteractionSession>;
|
|
33
|
+
onBeginEditing: (args: {
|
|
34
|
+
element: Element;
|
|
35
|
+
descriptorPromise: Promise<SelectableData>;
|
|
36
|
+
}) => void;
|
|
37
|
+
}): void;
|