"use strict"; Object.defineProperty(exports, "__esModule", { value: !0 }); var plugin_eventListener = require("./_chunks-cjs/plugin.event-listener.cjs"), jsxRuntime = require("react/jsx-runtime"), react = require("@xstate/react"), isEqual = require("lodash/isEqual.js"), noop = require("lodash/noop.js"), React = require("react"), slate = require("slate"), slateReact = require("slate-react"), reactCompilerRuntime = require("react-compiler-runtime"), uniq = require("lodash/uniq.js"), behavior_core = require("./_chunks-cjs/behavior.core.cjs"); function _interopDefaultCompat(e) { return e && typeof e == "object" && "default" in e ? e : { default: e }; } var isEqual__default = /* @__PURE__ */ _interopDefaultCompat(isEqual), noop__default = /* @__PURE__ */ _interopDefaultCompat(noop), uniq__default = /* @__PURE__ */ _interopDefaultCompat(uniq); function normalizePoint(point, value) { if (!point || !value) return null; const newPath = []; let newOffset = point.offset || 0; const blockKey = typeof point.path[0] == "object" && "_key" in point.path[0] && point.path[0]._key, childKey = typeof point.path[2] == "object" && "_key" in point.path[2] && point.path[2]._key, block = value.find((blk) => blk._key === blockKey); if (block) newPath.push({ _key: block._key }); else return null; if (block && point.path[1] === "children") { if (!block.children || Array.isArray(block.children) && block.children.length === 0) return null; const child = Array.isArray(block.children) && block.children.find((cld) => cld._key === childKey); if (child) newPath.push("children"), newPath.push({ _key: child._key }), newOffset = child.text && child.text.length >= point.offset ? point.offset : child.text && child.text.length || 0; else return null; } return { path: newPath, offset: newOffset }; } function normalizeSelection(selection, value) { if (!selection || !value || value.length === 0) return null; let newAnchor = null, newFocus = null; const { anchor, focus } = selection; return anchor && value.find((blk) => isEqual__default.default({ _key: blk._key }, anchor.path[0])) && (newAnchor = normalizePoint(anchor, value)), focus && value.find((blk) => isEqual__default.default({ _key: blk._key }, focus.path[0])) && (newFocus = normalizePoint(focus, value)), newAnchor && newFocus ? { anchor: newAnchor, focus: newFocus, backward: selection.backward } : null; } function DefaultBlockObject(props) { const $ = reactCompilerRuntime.c(4); let t0; $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = { userSelect: "none" }, $[0] = t0) : t0 = $[0]; let t1; return $[1] !== props.value._key || $[2] !== props.value._type ? (t1 = /* @__PURE__ */ jsxRuntime.jsxs("div", { style: t0, children: [ "[", props.value._type, ": ", props.value._key, "]" ] }), $[1] = props.value._key, $[2] = props.value._type, $[3] = t1) : t1 = $[3], t1; } function DefaultInlineObject(props) { const $ = reactCompilerRuntime.c(4); let t0; $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = { userSelect: "none" }, $[0] = t0) : t0 = $[0]; let t1; return $[1] !== props.value._key || $[2] !== props.value._type ? (t1 = /* @__PURE__ */ jsxRuntime.jsxs("span", { style: t0, children: [ "[", props.value._type, ": ", props.value._key, "]" ] }), $[1] = props.value._key, $[2] = props.value._type, $[3] = t1) : t1 = $[3], t1; } const debug$3 = plugin_eventListener.debugWithName("components:DraggableBlock"), DraggableBlock = (t0) => { const $ = reactCompilerRuntime.c(51), { children, element, readOnly, blockRef } = t0, editor = slateReact.useSlateStatic(), dragGhostRef = React.useRef(void 0), [isDragOver, setIsDragOver] = React.useState(!1); let t1, t2; $[0] !== editor || $[1] !== element ? (t2 = slate.Editor.isVoid(editor, element), $[0] = editor, $[1] = element, $[2] = t2) : t2 = $[2], t1 = t2; const isVoid = t1; let t3, t4; $[3] !== editor || $[4] !== element ? (t4 = slate.Editor.isInline(editor, element), $[3] = editor, $[4] = element, $[5] = t4) : t4 = $[5], t3 = t4; const isInline = t3, [blockElement, setBlockElement] = React.useState(null); let t5, t6; $[6] !== blockRef || $[7] !== editor || $[8] !== element ? (t5 = () => setBlockElement(blockRef ? blockRef.current : slateReact.ReactEditor.toDOMNode(editor, element)), t6 = [editor, element, blockRef], $[6] = blockRef, $[7] = editor, $[8] = element, $[9] = t5, $[10] = t6) : (t5 = $[9], t6 = $[10]), React.useEffect(t5, t6); let t7; $[11] !== blockElement || $[12] !== editor || $[13] !== element ? (t7 = (event) => { const isMyDragOver = plugin_eventListener.IS_DRAGGING_BLOCK_ELEMENT.get(editor); if (!isMyDragOver || !blockElement) return; event.preventDefault(), event.dataTransfer.dropEffect = "move", plugin_eventListener.IS_DRAGGING_ELEMENT_TARGET.set(editor, element); const elementRect = blockElement.getBoundingClientRect(), offset = elementRect.top, height = elementRect.height, Y = event.pageY, loc = Math.abs(offset - Y); if (element === editor.children[0] || (loc < height / 2 ? plugin_eventListener.IS_DRAGGING_BLOCK_TARGET_POSITION.set(editor, "top") : plugin_eventListener.IS_DRAGGING_BLOCK_TARGET_POSITION.set(editor, "bottom")), isMyDragOver === element) { event.dataTransfer.dropEffect = "none"; return; } setIsDragOver(!0); }, $[11] = blockElement, $[12] = editor, $[13] = element, $[14] = t7) : t7 = $[14]; const handleDragOver = t7; let t8; $[15] === Symbol.for("react.memo_cache_sentinel") ? (t8 = () => { setIsDragOver(!1); }, $[15] = t8) : t8 = $[15]; const handleDragLeave = t8; let t9; $[16] !== editor || $[17] !== element ? (t9 = (event_0) => { const targetBlock = plugin_eventListener.IS_DRAGGING_ELEMENT_TARGET.get(editor); if (targetBlock) { plugin_eventListener.IS_DRAGGING.set(editor, !1), event_0.preventDefault(), event_0.stopPropagation(), plugin_eventListener.IS_DRAGGING_ELEMENT_TARGET.delete(editor), dragGhostRef.current && (debug$3("Removing drag ghost"), document.body.removeChild(dragGhostRef.current)); const dragPosition = plugin_eventListener.IS_DRAGGING_BLOCK_TARGET_POSITION.get(editor); plugin_eventListener.IS_DRAGGING_BLOCK_TARGET_POSITION.delete(editor); let targetPath = slateReact.ReactEditor.findPath(editor, targetBlock); const myPath = slateReact.ReactEditor.findPath(editor, element), isBefore = slate.Path.isBefore(myPath, targetPath); if (dragPosition === "bottom" && !isBefore) { if (targetPath[0] >= editor.children.length - 1) { debug$3("target is already at the bottom, not moving"); return; } const originalPath = targetPath; targetPath = slate.Path.next(targetPath), debug$3(`Adjusting targetPath from ${JSON.stringify(originalPath)} to ${JSON.stringify(targetPath)}`); } if (dragPosition === "top" && isBefore && targetPath[0] !== editor.children.length - 1) { const originalPath_0 = targetPath; targetPath = slate.Path.previous(targetPath), debug$3(`Adjusting targetPath from ${JSON.stringify(originalPath_0)} to ${JSON.stringify(targetPath)}`); } if (slate.Path.equals(targetPath, myPath)) { event_0.preventDefault(), debug$3("targetPath and myPath is the same, not moving"); return; } debug$3(`Moving element ${element._key} from path ${JSON.stringify(myPath)} to ${JSON.stringify(targetPath)} (${dragPosition})`), slate.Transforms.moveNodes(editor, { at: myPath, to: targetPath }), editor.onChange(); return; } debug$3("No target element, not doing anything"); }, $[16] = editor, $[17] = element, $[18] = t9) : t9 = $[18]; const handleDragEnd = t9; let t10; $[19] !== editor || $[20] !== element ? (t10 = (event_1) => { plugin_eventListener.IS_DRAGGING_BLOCK_ELEMENT.get(editor) && (debug$3("On drop (prevented)", element), event_1.preventDefault(), event_1.stopPropagation(), setIsDragOver(!1)); }, $[19] = editor, $[20] = element, $[21] = t10) : t10 = $[21]; const handleDrop = t10; let t11; $[22] !== editor || $[23] !== element || $[24] !== isVoid ? (t11 = (event_2) => { if (!isVoid) { plugin_eventListener.IS_DRAGGING_BLOCK_ELEMENT.delete(editor); return; } plugin_eventListener.IS_DRAGGING.set(editor, !0), plugin_eventListener.IS_DRAGGING_BLOCK_ELEMENT.set(editor, element), event_2.stopPropagation(); const target = event_2.target; target instanceof HTMLElement && (target.style.opacity = "1"); }, $[22] = editor, $[23] = element, $[24] = isVoid, $[25] = t11) : t11 = $[25]; const handleDrag = t11; let t12; $[26] !== blockElement || $[27] !== editor || $[28] !== handleDrag || $[29] !== isInline || $[30] !== isVoid ? (t12 = (event_3) => { if (!isVoid || isInline) { debug$3("Not dragging block"), plugin_eventListener.IS_DRAGGING_BLOCK_ELEMENT.delete(editor), plugin_eventListener.IS_DRAGGING.set(editor, !1); return; } if (debug$3("Drag start"), plugin_eventListener.IS_DRAGGING.set(editor, !0), event_3.dataTransfer && (event_3.dataTransfer.setData("application/portable-text", "something"), event_3.dataTransfer.effectAllowed = "move"), blockElement && blockElement instanceof HTMLElement) { let dragGhost = blockElement.cloneNode(!0); const customGhost = dragGhost.querySelector("[data-pt-drag-ghost-element]"); if (customGhost && (dragGhost = customGhost), dragGhost.setAttribute("data-dragged", ""), document.body) { dragGhostRef.current = dragGhost, dragGhost.style.position = "absolute", dragGhost.style.left = "-99999px", dragGhost.style.boxSizing = "border-box", document.body.appendChild(dragGhost); const rect = blockElement.getBoundingClientRect(), x = event_3.clientX - rect.left, y = event_3.clientY - rect.top; dragGhost.style.width = `${rect.width}px`, dragGhost.style.height = `${rect.height}px`, event_3.dataTransfer.setDragImage(dragGhost, x, y); } } handleDrag(event_3); }, $[26] = blockElement, $[27] = editor, $[28] = handleDrag, $[29] = isInline, $[30] = isVoid, $[31] = t12) : t12 = $[31]; const handleDragStart = t12; let t13; $[32] !== editor || $[33] !== isDragOver ? (t13 = isDragOver && editor.children[0] === plugin_eventListener.IS_DRAGGING_ELEMENT_TARGET.get(editor), $[32] = editor, $[33] = isDragOver, $[34] = t13) : t13 = $[34]; const isDraggingOverFirstBlock = t13; let t14; $[35] !== editor || $[36] !== isDragOver ? (t14 = isDragOver && editor.children[editor.children.length - 1] === plugin_eventListener.IS_DRAGGING_ELEMENT_TARGET.get(editor), $[35] = editor, $[36] = isDragOver, $[37] = t14) : t14 = $[37]; const isDraggingOverLastBlock = t14, dragPosition_0 = plugin_eventListener.IS_DRAGGING_BLOCK_TARGET_POSITION.get(editor), isDraggingOverTop = isDraggingOverFirstBlock || isDragOver && !isDraggingOverFirstBlock && !isDraggingOverLastBlock && dragPosition_0 === "top", isDraggingOverBottom = isDraggingOverLastBlock || isDragOver && !isDraggingOverFirstBlock && !isDraggingOverLastBlock && dragPosition_0 === "bottom"; let t15, t16; $[38] === Symbol.for("react.memo_cache_sentinel") ? (t16 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-drop-indicator", style: { position: "absolute", width: "100%", height: 1, borderBottom: "1px solid currentColor", zIndex: 5 } }), $[38] = t16) : t16 = $[38], t15 = t16; const dropIndicator = t15; if (readOnly) { let t172; return $[39] !== children ? (t172 = /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children }), $[39] = children, $[40] = t172) : t172 = $[40], t172; } const t17 = isDraggingOverTop && dropIndicator, t18 = isDraggingOverBottom && dropIndicator; let t19; return $[41] !== children || $[42] !== handleDrag || $[43] !== handleDragEnd || $[44] !== handleDragOver || $[45] !== handleDragStart || $[46] !== handleDrop || $[47] !== isVoid || $[48] !== t17 || $[49] !== t18 ? (t19 = /* @__PURE__ */ jsxRuntime.jsxs("div", { draggable: isVoid, onDragStart: handleDragStart, onDrag: handleDrag, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDragEnd: handleDragEnd, onDrop: handleDrop, children: [ t17, children, t18 ] }), $[41] = children, $[42] = handleDrag, $[43] = handleDragEnd, $[44] = handleDragOver, $[45] = handleDragStart, $[46] = handleDrop, $[47] = isVoid, $[48] = t17, $[49] = t18, $[50] = t19) : t19 = $[50], t19; }; DraggableBlock.displayName = "DraggableBlock"; plugin_eventListener.debugWithName("components:Element"); const EMPTY_ANNOTATIONS = [], inlineBlockStyle = { display: "inline-block" }, Element = ({ attributes, children, element, schemaTypes, readOnly, renderBlock, renderChild, renderListItem, renderStyle, spellCheck }) => { const editor = slateReact.useSlateStatic(), selected = slateReact.useSelected(), blockRef = React.useRef(null), inlineBlockObjectRef = React.useRef(null), focused = selected && editor.selection && slate.Range.isCollapsed(editor.selection) || !1, value = React.useMemo(() => plugin_eventListener.fromSlateValue([element], schemaTypes.block.name, plugin_eventListener.KEY_TO_VALUE_ELEMENT.get(editor))[0], [editor, element, schemaTypes.block.name]); let renderedBlock = children, className; const blockPath = React.useMemo(() => [{ _key: element._key }], [element]); if (typeof element._type != "string") throw new Error("Expected element to have a _type property"); if (typeof element._key != "string") throw new Error("Expected element to have a _key property"); if (editor.isInline(element)) { const path = slateReact.ReactEditor.findPath(editor, element), [block] = slate.Editor.node(editor, path, { depth: 1 }), schemaType = schemaTypes.inlineObjects.find((_type) => _type.name === element._type); if (!schemaType) throw new Error("Could not find type for inline block element"); if (slate.Element.isElement(block)) { const elmPath = [{ _key: block._key }, "children", { _key: element._key }]; return /* @__PURE__ */ jsxRuntime.jsxs("span", { ...attributes, children: [ children, /* @__PURE__ */ jsxRuntime.jsxs("span", { draggable: !readOnly, className: "pt-inline-object", "data-testid": "pt-inline-object", ref: inlineBlockObjectRef, style: inlineBlockStyle, contentEditable: !1, children: [ renderChild && renderChild({ annotations: EMPTY_ANNOTATIONS, // These inline objects currently doesn't support annotations. This is a limitation of the current PT spec/model. children: /* @__PURE__ */ jsxRuntime.jsx(DefaultInlineObject, { value }), editorElementRef: inlineBlockObjectRef, focused, path: elmPath, schemaType, selected, type: schemaType, value }), !renderChild && /* @__PURE__ */ jsxRuntime.jsx(DefaultInlineObject, { value }) ] }, element._key) ] }); } throw new Error("Block not found!"); } if (element._type === schemaTypes.block.name) { className = "pt-block pt-text-block"; const isListItem = "listItem" in element, style = "style" in element && element.style || "normal"; className = `pt-block pt-text-block pt-text-block-style-${style}`; const blockStyleType = schemaTypes.styles.find((item) => item.value === style); renderStyle && blockStyleType && (renderedBlock = renderStyle({ block: element, children, focused, selected, value: style, path: blockPath, schemaType: blockStyleType, editorElementRef: blockRef })); let level; if (isListItem && (typeof element.level == "number" && (level = element.level), className += ` pt-list-item pt-list-item-${element.listItem} pt-list-item-level-${level || 1}`), editor.isListBlock(value) && isListItem && element.listItem) { const listType = schemaTypes.lists.find((item_0) => item_0.value === element.listItem); renderListItem && listType && (renderedBlock = renderListItem({ block: value, children: renderedBlock, focused, selected, value: element.listItem, path: blockPath, schemaType: listType, level: value.level || 1, editorElementRef: blockRef })); } const renderProps = Object.defineProperty({ children: renderedBlock, editorElementRef: blockRef, focused, level, listItem: isListItem ? element.listItem : void 0, path: blockPath, selected, style, schemaType: schemaTypes.block, value }, "type", { enumerable: !1, get() { return console.warn("Property 'type' is deprecated, use 'schemaType' instead."), schemaTypes.block; } }), propsOrDefaultRendered = renderBlock ? renderBlock(renderProps) : children; return /* @__PURE__ */ jsxRuntime.jsx("div", { ...attributes, className, spellCheck, children: /* @__PURE__ */ jsxRuntime.jsx(DraggableBlock, { element, readOnly, blockRef, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: blockRef, children: propsOrDefaultRendered }) }) }, element._key); } const schemaType_0 = schemaTypes.blockObjects.find((_type_0) => _type_0.name === element._type); if (!schemaType_0) throw new Error(`Could not find schema type for block element of _type ${element._type}`); className = "pt-block pt-object-block"; const block_0 = plugin_eventListener.fromSlateValue([element], schemaTypes.block.name, plugin_eventListener.KEY_TO_VALUE_ELEMENT.get(editor))[0]; let renderedBlockFromProps; if (renderBlock) { const _props = Object.defineProperty({ children: /* @__PURE__ */ jsxRuntime.jsx(DefaultBlockObject, { value }), editorElementRef: blockRef, focused, path: blockPath, schemaType: schemaType_0, selected, value: block_0 }, "type", { enumerable: !1, get() { return console.warn("Property 'type' is deprecated, use 'schemaType' instead."), schemaType_0; } }); renderedBlockFromProps = renderBlock(_props); } return /* @__PURE__ */ jsxRuntime.jsxs("div", { ...attributes, className, children: [ children, /* @__PURE__ */ jsxRuntime.jsx(DraggableBlock, { element, readOnly, blockRef, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: blockRef, contentEditable: !1, children: renderedBlockFromProps || /* @__PURE__ */ jsxRuntime.jsx(DefaultBlockObject, { value }) }) }) ] }, element._key); }; Element.displayName = "Element"; const debug$2 = plugin_eventListener.debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (props) => { const { editorActor, attributes, children, leaf, schemaTypes, renderChild, renderDecorator, renderAnnotation } = props, spanRef = React.useRef(null), portableTextEditor = plugin_eventListener.usePortableTextEditor(), blockSelected = slateReact.useSelected(), [focused, setFocused] = React.useState(!1), [selected, setSelected] = React.useState(!1), block = children.props.parent, path = React.useMemo(() => block ? [{ _key: block?._key }, "children", { _key: leaf._key }] : [], [block, leaf._key]), decoratorValues = React.useMemo(() => schemaTypes.decorators.map((dec) => dec.value), [schemaTypes.decorators]), marks = React.useMemo(() => uniq__default.default((leaf.marks || EMPTY_MARKS).filter((mark) => decoratorValues.includes(mark))), [decoratorValues, leaf.marks]), annotationMarks = Array.isArray(leaf.marks) ? leaf.marks : EMPTY_MARKS, annotations = React.useMemo(() => annotationMarks.map((mark_0) => !decoratorValues.includes(mark_0) && block?.markDefs?.find((def) => def._key === mark_0)).filter(Boolean), [annotationMarks, block, decoratorValues]), shouldTrackSelectionAndFocus = annotations.length > 0 && blockSelected; React.useEffect(() => { if (!shouldTrackSelectionAndFocus) { setFocused(!1); return; } const sel = plugin_eventListener.PortableTextEditor.getSelection(portableTextEditor); sel && isEqual__default.default(sel.focus.path, path) && plugin_eventListener.PortableTextEditor.isCollapsedSelection(portableTextEditor) && React.startTransition(() => { setFocused(!0); }); }, [shouldTrackSelectionAndFocus, path, portableTextEditor]); const setSelectedFromRange = React.useCallback(() => { if (!shouldTrackSelectionAndFocus) return; debug$2("Setting selection and focus from range"); const winSelection = window.getSelection(); if (!winSelection) { setSelected(!1); return; } if (winSelection && winSelection.rangeCount > 0) { const range = winSelection.getRangeAt(0); spanRef.current && range.intersectsNode(spanRef.current) ? setSelected(!0) : setSelected(!1); } else setSelected(!1); }, [shouldTrackSelectionAndFocus]); React.useEffect(() => { if (!shouldTrackSelectionAndFocus) return; const onBlur = editorActor.on("blur", () => { setFocused(!1), setSelected(!1); }), onFocus = editorActor.on("focus", () => { const sel_0 = plugin_eventListener.PortableTextEditor.getSelection(portableTextEditor); sel_0 && isEqual__default.default(sel_0.focus.path, path) && plugin_eventListener.PortableTextEditor.isCollapsedSelection(portableTextEditor) && setFocused(!0), setSelectedFromRange(); }), onSelection = editorActor.on("selection", (event) => { event.selection && isEqual__default.default(event.selection.focus.path, path) && plugin_eventListener.PortableTextEditor.isCollapsedSelection(portableTextEditor) ? setFocused(!0) : setFocused(!1), setSelectedFromRange(); }); return () => { onBlur.unsubscribe(), onFocus.unsubscribe(), onSelection.unsubscribe(); }; }, [editorActor, path, portableTextEditor, setSelectedFromRange, shouldTrackSelectionAndFocus]), React.useEffect(() => setSelectedFromRange(), [setSelectedFromRange]); const content = React.useMemo(() => { let returnedChildren = children; if (slate.Text.isText(leaf) && leaf._type === schemaTypes.span.name && (marks.forEach((mark_1) => { const schemaType = schemaTypes.decorators.find((dec_0) => dec_0.value === mark_1); if (schemaType && renderDecorator) { const _props = Object.defineProperty({ children: returnedChildren, editorElementRef: spanRef, focused, path, selected, schemaType, value: mark_1 }, "type", { enumerable: !1, get() { return console.warn("Property 'type' is deprecated, use 'schemaType' instead."), schemaType; } }); returnedChildren = renderDecorator(_props); } }), block && annotations.length > 0 && annotations.forEach((annotation) => { const schemaType_0 = schemaTypes.annotations.find((t) => t.name === annotation._type); if (schemaType_0) if (renderAnnotation) { const _props_0 = Object.defineProperty({ block, children: returnedChildren, editorElementRef: spanRef, focused, path, selected, schemaType: schemaType_0, value: annotation }, "type", { enumerable: !1, get() { return console.warn("Property 'type' is deprecated, use 'schemaType' instead."), schemaType_0; } }); returnedChildren = /* @__PURE__ */ jsxRuntime.jsx("span", { ref: spanRef, children: renderAnnotation(_props_0) }); } else returnedChildren = /* @__PURE__ */ jsxRuntime.jsx("span", { ref: spanRef, children: returnedChildren }); }), block && renderChild)) { const child = block.children.find((_child) => _child._key === leaf._key); if (child) { const _props_1 = Object.defineProperty({ annotations, children: /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: returnedChildren }), editorElementRef: spanRef, focused, path, schemaType: schemaTypes.span, selected, value: child }, "type", { enumerable: !1, get() { return console.warn("Property 'type' is deprecated, use 'schemaType' instead."), schemaTypes.span; } }); returnedChildren = renderChild(_props_1); } } return returnedChildren; }, [annotations, block, children, focused, leaf, marks, path, renderAnnotation, renderChild, renderDecorator, schemaTypes.annotations, schemaTypes.decorators, schemaTypes.span, selected]); return React.useMemo(() => /* @__PURE__ */ jsxRuntime.jsx("span", { ...attributes, ref: spanRef, children: content }, leaf._key), [leaf, attributes, content]); }; Leaf.displayName = "Leaf"; const debug$1 = plugin_eventListener.debugWithName("plugin:withHotKeys"); function createWithHotkeys(editorActor, portableTextEditor, hotkeysFromOptions) { const reservedHotkeys = ["enter", "tab", "shift", "delete", "end"], activeHotkeys = hotkeysFromOptions ?? {}; return function(editor) { return editor.pteWithHotKeys = (event) => { Object.keys(activeHotkeys).forEach((cat) => { if (cat === "marks") for (const hotkey in activeHotkeys[cat]) { if (reservedHotkeys.includes(hotkey)) throw new Error(`The hotkey ${hotkey} is reserved!`); if (behavior_core.isHotkey(hotkey, event.nativeEvent)) { event.preventDefault(); const possibleMark = activeHotkeys[cat]; if (possibleMark) { const mark = possibleMark[hotkey]; debug$1(`HotKey ${hotkey} to toggle ${mark}`), editorActor.send({ type: "behavior event", behaviorEvent: { type: "decorator.toggle", decorator: mark }, editor }); } } } if (cat === "custom") for (const hotkey in activeHotkeys[cat]) { if (reservedHotkeys.includes(hotkey)) throw new Error(`The hotkey ${hotkey} is reserved!`); if (behavior_core.isHotkey(hotkey, event.nativeEvent)) { const possibleCommand = activeHotkeys[cat]; if (possibleCommand) { const command = possibleCommand[hotkey]; command(event, portableTextEditor); } } } }); }, editor; }; } function withSyncRangeDecorations({ editorActor, slateEditor, syncRangeDecorations }) { const originalApply = slateEditor.apply; return slateEditor.apply = (op) => { originalApply(op), !editorActor.getSnapshot().matches({ "edit mode": "read only" }) && op.type !== "set_selection" && syncRangeDecorations(op); }, () => { slateEditor.apply = originalApply; }; } const debug = plugin_eventListener.debugWithName("component:Editable"), PLACEHOLDER_STYLE = { position: "absolute", userSelect: "none", pointerEvents: "none", left: 0, right: 0 }, PortableTextEditable = React.forwardRef(function(props, forwardedRef) { const { hotkeys, onBlur, onFocus, onBeforeInput, onPaste, onCopy, onClick, rangeDecorations, renderAnnotation, renderBlock, renderChild, renderDecorator, renderListItem, renderPlaceholder, renderStyle, selection: propsSelection, scrollSelectionIntoView, spellCheck, ...restProps } = props, portableTextEditor = plugin_eventListener.usePortableTextEditor(), ref = React.useRef(null), [editableElement, setEditableElement] = React.useState(null), [hasInvalidValue, setHasInvalidValue] = React.useState(!1), [rangeDecorationState, setRangeDecorationsState] = React.useState([]); React.useImperativeHandle(forwardedRef, () => ref.current); const rangeDecorationsRef = React.useRef(rangeDecorations), editorActor = React.useContext(plugin_eventListener.EditorActorContext), readOnly = react.useSelector(editorActor, (s) => s.matches({ "edit mode": "read only" })), schemaTypes = react.useSelector(editorActor, (s_0) => s_0.context.schema), slateEditor = slateReact.useSlate(), blockTypeName = schemaTypes.block.name; React.useMemo(() => { if (readOnly) return debug("Editable is in read only mode"), slateEditor; const withHotKeys = createWithHotkeys(editorActor, portableTextEditor, hotkeys); return debug("Editable is in edit mode"), withHotKeys(slateEditor); }, [editorActor, hotkeys, portableTextEditor, readOnly, slateEditor]); const renderElement = React.useCallback((eProps) => /* @__PURE__ */ jsxRuntime.jsx(Element, { ...eProps, readOnly, renderBlock, renderChild, renderListItem, renderStyle, schemaTypes, spellCheck }), [schemaTypes, spellCheck, readOnly, renderBlock, renderChild, renderListItem, renderStyle]), renderLeaf = React.useCallback((lProps) => { if (lProps.leaf._type === "span") { let rendered = /* @__PURE__ */ jsxRuntime.jsx(Leaf, { ...lProps, editorActor, schemaTypes, renderAnnotation, renderChild, renderDecorator, readOnly }); if (renderPlaceholder && lProps.leaf.placeholder && lProps.text.text === "") return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [ /* @__PURE__ */ jsxRuntime.jsx("span", { style: PLACEHOLDER_STYLE, contentEditable: !1, children: renderPlaceholder() }), rendered ] }); const decoration = lProps.leaf.rangeDecoration; return decoration && (rendered = decoration.component({ children: rendered })), rendered; } return lProps.children; }, [editorActor, readOnly, renderAnnotation, renderChild, renderDecorator, renderPlaceholder, schemaTypes]), restoreSelectionFromProps = React.useCallback(() => { if (propsSelection) { debug(`Selection from props ${JSON.stringify(propsSelection)}`); const normalizedSelection = normalizeSelection(propsSelection, plugin_eventListener.fromSlateValue(slateEditor.children, blockTypeName)); if (normalizedSelection !== null) { debug(`Normalized selection from props ${JSON.stringify(normalizedSelection)}`); const slateRange = plugin_eventListener.toSlateRange(normalizedSelection, slateEditor); slateRange && (slate.Transforms.select(slateEditor, slateRange), slateEditor.operations.some((o) => o.type === "set_selection") || editorActor.send({ type: "notify.selection", selection: normalizedSelection }), slateEditor.onChange()); } } }, [blockTypeName, editorActor, propsSelection, slateEditor]), syncRangeDecorations = React.useCallback((operation) => { if (rangeDecorations && rangeDecorations.length > 0) { const newSlateRanges = []; if (rangeDecorations.forEach((rangeDecorationItem) => { const slateRange_0 = plugin_eventListener.toSlateRange(rangeDecorationItem.selection, slateEditor); if (!slate.Range.isRange(slateRange_0)) { rangeDecorationItem.onMoved && rangeDecorationItem.onMoved({ newSelection: null, rangeDecoration: rangeDecorationItem, origin: "local" }); return; } let newRange; if (operation && (newRange = plugin_eventListener.moveRangeByOperation(slateRange_0, operation), newRange && newRange !== slateRange_0 || newRange === null && slateRange_0)) { const value = plugin_eventListener.PortableTextEditor.getValue(portableTextEditor), newRangeSelection = plugin_eventListener.toPortableTextRange(value, newRange, schemaTypes); rangeDecorationItem.onMoved && rangeDecorationItem.onMoved({ newSelection: newRangeSelection, rangeDecoration: rangeDecorationItem, origin: "local" }); } newRange !== null && newSlateRanges.push({ ...newRange || slateRange_0, rangeDecoration: rangeDecorationItem }); }), newSlateRanges.length > 0) { setRangeDecorationsState(newSlateRanges); return; } } setRangeDecorationsState((rangeDecorationState_0) => rangeDecorationState_0.length > 0 ? [] : rangeDecorationState_0); }, [portableTextEditor, rangeDecorations, schemaTypes, slateEditor]); React.useEffect(() => { const onReady = editorActor.on("ready", () => { syncRangeDecorations(), restoreSelectionFromProps(); }), onInvalidValue = editorActor.on("invalid value", () => { setHasInvalidValue(!0); }), onValueChanged = editorActor.on("value changed", () => { setHasInvalidValue(!1); }); return () => { onReady.unsubscribe(), onInvalidValue.unsubscribe(), onValueChanged.unsubscribe(); }; }, [editorActor, restoreSelectionFromProps, syncRangeDecorations]), React.useEffect(() => { propsSelection && !hasInvalidValue && restoreSelectionFromProps(); }, [hasInvalidValue, propsSelection, restoreSelectionFromProps]); const [syncedRangeDecorations, setSyncedRangeDecorations] = React.useState(!1); React.useEffect(() => { syncedRangeDecorations || (setSyncedRangeDecorations(!0), syncRangeDecorations()); }, [syncRangeDecorations, syncedRangeDecorations]), React.useEffect(() => { isEqual__default.default(rangeDecorations, rangeDecorationsRef.current) || syncRangeDecorations(), rangeDecorationsRef.current = rangeDecorations; }, [rangeDecorations, syncRangeDecorations]), React.useEffect(() => { const teardown = withSyncRangeDecorations({ editorActor, slateEditor, syncRangeDecorations }); return () => teardown(); }, [editorActor, slateEditor, syncRangeDecorations]); const handleCopy = React.useCallback((event) => { onCopy ? onCopy(event) !== void 0 && event.preventDefault() : event.nativeEvent.clipboardData && editorActor.send({ type: "behavior event", behaviorEvent: { type: "copy", data: event.nativeEvent.clipboardData }, editor: slateEditor, nativeEvent: event }); }, [onCopy, editorActor, slateEditor]), handlePaste = React.useCallback((event_0) => { const value_0 = plugin_eventListener.PortableTextEditor.getValue(portableTextEditor), path = plugin_eventListener.toPortableTextRange(value_0, slateEditor.selection, schemaTypes)?.focus.path || [], onPasteResult = onPaste?.({ event: event_0, value: value_0, path, schemaTypes }); onPasteResult || !slateEditor.selection ? (event_0.preventDefault(), editorActor.send({ type: "notify.loading" }), Promise.resolve(onPasteResult).then((result_0) => { debug("Custom paste function from client resolved", result_0), !result_0 || !result_0.insert ? (debug("No result from custom paste handler, pasting normally"), slateEditor.insertData(event_0.clipboardData)) : result_0.insert ? slateEditor.insertFragment(plugin_eventListener.toSlateValue(result_0.insert, { schemaTypes })) : console.warn("Your onPaste function returned something unexpected:", result_0); }).catch((error) => (console.error(error), error)).finally(() => { editorActor.send({ type: "notify.done loading" }); })) : event_0.nativeEvent.clipboardData && editorActor.send({ type: "behavior event", behaviorEvent: { type: "paste", data: event_0.nativeEvent.clipboardData }, editor: slateEditor, nativeEvent: event_0 }), debug("No result from custom paste handler, pasting normally"); }, [editorActor, onPaste, portableTextEditor, schemaTypes, slateEditor]), handleOnFocus = React.useCallback((event_1) => { if (onFocus && onFocus(event_1), !event_1.isDefaultPrevented()) { const selection = plugin_eventListener.PortableTextEditor.getSelection(portableTextEditor); selection === null && (slate.Transforms.select(slateEditor, slate.Editor.start(slateEditor, [])), slateEditor.onChange()), editorActor.send({ type: "notify.focused", event: event_1 }); const newSelection = plugin_eventListener.PortableTextEditor.getSelection(portableTextEditor); selection === newSelection && editorActor.send({ type: "notify.selection", selection }); } }, [editorActor, onFocus, portableTextEditor, slateEditor]), handleClick = React.useCallback((event_2) => { onClick && onClick(event_2); const focusBlockPath = slateEditor.selection ? slateEditor.selection.focus.path.slice(0, 1) : void 0, focusBlock = focusBlockPath ? slate.Node.descendant(slateEditor, focusBlockPath) : void 0, [_, lastNodePath] = slate.Node.last(slateEditor, []), lastBlockPath = lastNodePath.slice(0, 1), lastNodeFocused = focusBlockPath ? slate.Path.equals(lastBlockPath, focusBlockPath) : !1, lastBlockIsVoid = focusBlock ? !slateEditor.isTextBlock(focusBlock) : !1; slateEditor.selection && slate.Range.isCollapsed(slateEditor.selection) && lastNodeFocused && lastBlockIsVoid && (slate.Transforms.insertNodes(slateEditor, slateEditor.pteCreateTextBlock({ decorators: [] })), slateEditor.onChange()); }, [onClick, slateEditor]), handleOnBlur = React.useCallback((event_3) => { onBlur && onBlur(event_3), event_3.isPropagationStopped() || editorActor.send({ type: "notify.blurred", event: event_3 }); }, [editorActor, onBlur]), handleOnBeforeInput = React.useCallback((event_4) => { onBeforeInput && onBeforeInput(event_4); }, [onBeforeInput]), validateSelection = React.useCallback(() => { if (!slateEditor.selection) return; const root = slateReact.ReactEditor.findDocumentOrShadowRoot(slateEditor), { activeElement } = root; if (ref.current !== activeElement) return; const domSelection = slateReact.ReactEditor.getWindow(slateEditor).getSelection(); if (!domSelection || domSelection.rangeCount === 0) return; const existingDOMRange = domSelection.getRangeAt(0); try { const newDOMRange = slateReact.ReactEditor.toDOMRange(slateEditor, slateEditor.selection); (newDOMRange.startOffset !== existingDOMRange.startOffset || newDOMRange.endOffset !== existingDOMRange.endOffset) && (debug("DOM range out of sync, validating selection"), domSelection?.removeAllRanges(), domSelection.addRange(newDOMRange)); } catch { debug("Could not resolve selection, selecting top document"), slate.Transforms.deselect(slateEditor), slateEditor.children.length > 0 && slate.Transforms.select(slateEditor, [0, 0]), slateEditor.onChange(); } }, [ref, slateEditor]); React.useEffect(() => { if (editableElement) { const mutationObserver = new MutationObserver(validateSelection); return mutationObserver.observe(editableElement, { attributeOldValue: !1, attributes: !1, characterData: !1, childList: !0, subtree: !0 }), () => { mutationObserver.disconnect(); }; } }, [validateSelection, editableElement]); const handleKeyDown = React.useCallback((event_5) => { props.onKeyDown && props.onKeyDown(event_5), event_5.isDefaultPrevented() || slateEditor.pteWithHotKeys(event_5), event_5.isDefaultPrevented() || editorActor.send({ type: "behavior event", behaviorEvent: { type: "key.down", keyboardEvent: { key: event_5.key, code: event_5.code, altKey: event_5.altKey, ctrlKey: event_5.ctrlKey, metaKey: event_5.metaKey, shiftKey: event_5.shiftKey } }, editor: slateEditor, nativeEvent: event_5 }); }, [props, editorActor, slateEditor]), handleKeyUp = React.useCallback((event_6) => { props.onKeyUp && props.onKeyUp(event_6), event_6.isDefaultPrevented() || editorActor.send({ type: "behavior event", behaviorEvent: { type: "key.up", keyboardEvent: { key: event_6.key, code: event_6.code, altKey: event_6.altKey, ctrlKey: event_6.ctrlKey, metaKey: event_6.metaKey, shiftKey: event_6.shiftKey } }, editor: slateEditor, nativeEvent: event_6 }); }, [props, editorActor, slateEditor]), scrollSelectionIntoViewToSlate = React.useMemo(() => { if (scrollSelectionIntoView !== void 0) return scrollSelectionIntoView === null ? noop__default.default : (_editor, domRange) => { scrollSelectionIntoView(portableTextEditor, domRange); }; }, [portableTextEditor, scrollSelectionIntoView]), decorate = React.useCallback(([, path_0]) => { if (plugin_eventListener.isEqualToEmptyEditor(slateEditor.children, schemaTypes)) return [{ anchor: { path: [0, 0], offset: 0 }, focus: { path: [0, 0], offset: 0 }, placeholder: !0 }]; if (path_0.length === 0) return []; const result_1 = rangeDecorationState.filter((item) => slate.Range.isCollapsed(item) ? path_0.length !== 2 ? !1 : slate.Path.equals(item.focus.path, path_0) && slate.Path.equals(item.anchor.path, path_0) : slate.Range.intersection(item, { anchor: { path: path_0, offset: 0 }, focus: { path: path_0, offset: 0 } }) || slate.Range.includes(item, path_0)); return result_1.length > 0 ? result_1 : []; }, [slateEditor, schemaTypes, rangeDecorationState]); return React.useEffect(() => { ref.current = slateReact.ReactEditor.toDOMNode(slateEditor, slateEditor), setEditableElement(ref.current); }, [slateEditor, ref]), portableTextEditor ? hasInvalidValue ? null : /* @__PURE__ */ jsxRuntime.jsx( slateReact.Editable, { ...restProps, autoFocus: !1, className: restProps.className || "pt-editable", decorate, onBlur: handleOnBlur, onCopy: handleCopy, onClick: handleClick, onDOMBeforeInput: handleOnBeforeInput, onFocus: handleOnFocus, onKeyDown: handleKeyDown, onKeyUp: handleKeyUp, onPaste: handlePaste, readOnly, renderPlaceholder: void 0, renderElement, renderLeaf, scrollSelectionIntoView: scrollSelectionIntoViewToSlate } ) : null; }); PortableTextEditable.displayName = "ForwardRef(PortableTextEditable)"; exports.EditorEventListener = plugin_eventListener.EventListenerPlugin; exports.EditorProvider = plugin_eventListener.EditorProvider; exports.PortableTextEditor = plugin_eventListener.PortableTextEditor; exports.defineSchema = plugin_eventListener.defineSchema; exports.keyGenerator = plugin_eventListener.defaultKeyGenerator; exports.useEditor = plugin_eventListener.useEditor; exports.useEditorSelector = plugin_eventListener.useEditorSelector; exports.usePortableTextEditor = plugin_eventListener.usePortableTextEditor; exports.usePortableTextEditorSelection = plugin_eventListener.usePortableTextEditorSelection; exports.PortableTextEditable = PortableTextEditable; //# sourceMappingURL=index.cjs.map