noteloom 0.6.0 → 0.7.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.
Files changed (62) hide show
  1. package/dist/canvas.cjs +1 -1
  2. package/dist/canvas.js +1 -1
  3. package/dist/comments.cjs +1 -1
  4. package/dist/comments.js +3 -3
  5. package/dist/index.cjs +2 -1
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.ts +6 -0
  8. package/dist/index.js +1529 -1488
  9. package/dist/index.js.map +1 -1
  10. package/dist/shared/{CommentThreadCard-DcCHq2Dy.cjs → CommentThreadCard-CIB6nZEA.cjs} +2 -2
  11. package/dist/shared/{CommentThreadCard-DcCHq2Dy.cjs.map → CommentThreadCard-CIB6nZEA.cjs.map} +1 -1
  12. package/dist/shared/{CommentThreadCard-DwtE85Xx.js → CommentThreadCard-lW_lbI74.js} +2 -2
  13. package/dist/shared/{CommentThreadCard-DwtE85Xx.js.map → CommentThreadCard-lW_lbI74.js.map} +1 -1
  14. package/dist/shared/{CommentsPanel-BRgACUu_.cjs → CommentsPanel-CRxb3RWi.cjs} +2 -2
  15. package/dist/shared/{CommentsPanel-BRgACUu_.cjs.map → CommentsPanel-CRxb3RWi.cjs.map} +1 -1
  16. package/dist/shared/{CommentsPanel-D4eP-K_f.js → CommentsPanel-Dg0k_XNU.js} +3 -3
  17. package/dist/shared/{CommentsPanel-D4eP-K_f.js.map → CommentsPanel-Dg0k_XNU.js.map} +1 -1
  18. package/dist/shared/{VersionHistory-BRBYQgj5.cjs → VersionHistory-BsSwOq_k.cjs} +2 -2
  19. package/dist/shared/{VersionHistory-BRBYQgj5.cjs.map → VersionHistory-BsSwOq_k.cjs.map} +1 -1
  20. package/dist/shared/{VersionHistory-D9sIIAYN.js → VersionHistory-BzMnJpbc.js} +3 -3
  21. package/dist/shared/{VersionHistory-D9sIIAYN.js.map → VersionHistory-BzMnJpbc.js.map} +1 -1
  22. package/dist/shared/{VoiceListeningIndicator-Dw0fggpE.cjs → VoiceListeningIndicator-B_7-6Mq4.cjs} +2 -2
  23. package/dist/shared/{VoiceListeningIndicator-Dw0fggpE.cjs.map → VoiceListeningIndicator-B_7-6Mq4.cjs.map} +1 -1
  24. package/dist/shared/{VoiceListeningIndicator-DgLMmGSP.js → VoiceListeningIndicator-DeA3hb33.js} +4 -4
  25. package/dist/shared/{VoiceListeningIndicator-DgLMmGSP.js.map → VoiceListeningIndicator-DeA3hb33.js.map} +1 -1
  26. package/dist/shared/{icons-Bdptdx1e.js → icons-CmfXmn13.js} +307 -259
  27. package/dist/shared/icons-CmfXmn13.js.map +1 -0
  28. package/dist/shared/{icons-DabR_JDW.cjs → icons-DQ7j_-ZK.cjs} +44 -3
  29. package/dist/shared/icons-DQ7j_-ZK.cjs.map +1 -0
  30. package/dist/shared/{index-DOIEccLM.js → index-DUigqWQn.js} +3 -3
  31. package/dist/shared/{index-DOIEccLM.js.map → index-DUigqWQn.js.map} +1 -1
  32. package/dist/shared/{index-B7_F6NA9.cjs → index-vWtS1iyt.cjs} +2 -2
  33. package/dist/shared/{index-B7_F6NA9.cjs.map → index-vWtS1iyt.cjs.map} +1 -1
  34. package/dist/shared/{leafBlockFactory-D3SCDvzc.cjs → leafBlockFactory-6GFBveaC.cjs} +2 -2
  35. package/dist/shared/{leafBlockFactory-D3SCDvzc.cjs.map → leafBlockFactory-6GFBveaC.cjs.map} +1 -1
  36. package/dist/shared/{leafBlockFactory-ChlzpKIn.js → leafBlockFactory-Dm6cd2NY.js} +5 -5
  37. package/dist/shared/{leafBlockFactory-ChlzpKIn.js.map → leafBlockFactory-Dm6cd2NY.js.map} +1 -1
  38. package/dist/shared/{serialize-C1rjLsIz.js → serialize-R4V4gmHs.js} +2 -2
  39. package/dist/shared/{serialize-C1rjLsIz.js.map → serialize-R4V4gmHs.js.map} +1 -1
  40. package/dist/shared/{serialize-k0zXqwEM.cjs → serialize-vLXz0cze.cjs} +2 -2
  41. package/dist/shared/{serialize-k0zXqwEM.cjs.map → serialize-vLXz0cze.cjs.map} +1 -1
  42. package/dist/shared/starter-kit-BQUaaql0.cjs +29 -0
  43. package/dist/shared/starter-kit-BQUaaql0.cjs.map +1 -0
  44. package/dist/shared/{starter-kit-CJzWMyF8.js → starter-kit-Bp30PiE4.js} +1246 -1188
  45. package/dist/shared/starter-kit-Bp30PiE4.js.map +1 -0
  46. package/dist/shared/{usePopoverEdgeClamp-gRlLQeVG.cjs → usePopoverEdgeClamp-BJLbbANB.cjs} +2 -2
  47. package/dist/shared/{usePopoverEdgeClamp-gRlLQeVG.cjs.map → usePopoverEdgeClamp-BJLbbANB.cjs.map} +1 -1
  48. package/dist/shared/{usePopoverEdgeClamp-B9KNv9SE.js → usePopoverEdgeClamp-DSpz-6xR.js} +2 -2
  49. package/dist/shared/{usePopoverEdgeClamp-B9KNv9SE.js.map → usePopoverEdgeClamp-DSpz-6xR.js.map} +1 -1
  50. package/dist/starter-kit.cjs +1 -1
  51. package/dist/starter-kit.js +2 -2
  52. package/dist/style.css +41 -0
  53. package/dist/versions.cjs +1 -1
  54. package/dist/versions.js +1 -1
  55. package/dist/voice.cjs +1 -1
  56. package/dist/voice.js +1 -1
  57. package/package.json +1 -1
  58. package/dist/shared/icons-Bdptdx1e.js.map +0 -1
  59. package/dist/shared/icons-DabR_JDW.cjs.map +0 -1
  60. package/dist/shared/starter-kit-CJzWMyF8.js.map +0 -1
  61. package/dist/shared/starter-kit-Ch2LEpzF.cjs +0 -27
  62. package/dist/shared/starter-kit-Ch2LEpzF.cjs.map +0 -1
@@ -1,2 +1,2 @@
1
- "use strict";const x=require("react/jsx-runtime"),r=require("react"),L=require("./icons-DabR_JDW.cjs"),v='button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';function y({isOpen:t,onClose:e,title:o,size:n="default",variant:s="dialog",children:u}){const c=r.useRef(null),a=r.useRef(null);if(r.useEffect(()=>{if(!t)return;const l=d=>{d.key==="Escape"&&e()};return document.addEventListener("keydown",l),()=>document.removeEventListener("keydown",l)},[t,e]),r.useEffect(()=>{var l,d,m;if(t){a.current=document.activeElement;const f=c.current;(l=(f==null?void 0:f.querySelector(v))??f)==null||l.focus();return}(m=(d=a.current)==null?void 0:d.focus)==null||m.call(d),a.current=null},[t]),!t)return null;const i=s==="sheet";return x.jsx("div",{className:`be-modal-overlay${i?" be-modal-overlay-sheet":""}`,onMouseDown:l=>{l.target===l.currentTarget&&e()},children:x.jsxs("div",{ref:c,className:`be-modal${n==="large"?" be-modal-large":""}${i?" be-modal-sheet":""}`,role:"dialog","aria-modal":"true","aria-label":o,tabIndex:-1,children:[o&&x.jsx("div",{className:"be-modal-title",children:o}),u]})})}const p=8;function g(t,e){const o=Math.max(p,window.innerWidth-e-p);return Math.min(Math.max(t,p),o)}function A(t,e){const o=Math.max(p,window.innerHeight-e-p);return Math.min(Math.max(t,p),o)}function B(t,e,o,n,s,u){const c=t.getBlock(e),i=t.getBlock(c.parentId).contentIds.indexOf(e),l="titleRunIds"in n,d="titleRunIds"in(c.props??{}),m=u?!u.isLeaf(c.type)&&c.contentIds.length>0:!1,f=u?!u.isLeaf(o):!1,h=[];if(m&&!f&&c.contentIds.forEach((E,w)=>h.push(L.moveBlock(E,c.parentId,i+1+w))),h.push(L.changeBlockType(e,o,n)),l)h.push(L.updateBlockProps(e,{titleRunIds:s})),!d&&!m&&h.push(L.setBlockContentIds(e,[]));else{const E=m&&f?c.contentIds:[];h.push(L.setBlockContentIds(e,[...E,...s]))}return{newBlockId:e,ops:h}}function T(t,e,o){const[n,s]=r.useState(null);return r.useLayoutEffect(()=>{s(o??null)},[o]),r.useLayoutEffect(()=>{if(!e||!t.current||n==null)return;const u=t.current.getBoundingClientRect(),c=g(n,u.width);c!==n&&s(c)},[e,t,n]),n}function C(t,e,o){const[n,s]=r.useState(null);return r.useLayoutEffect(()=>{s(o??null)},[o]),r.useLayoutEffect(()=>{if(!e||!t.current||n==null)return;const u=t.current.getBoundingClientRect(),c=u.width/2,i=g(n-c,u.width)+c;i!==n&&s(i)},[e,t,n]),n}function R(t,e,o){const[n,s]=r.useState(null);return r.useLayoutEffect(()=>{s(o??null)},[o]),r.useLayoutEffect(()=>{if(!e||!t.current||n==null)return;const u=t.current.getBoundingClientRect(),a=g(n-u.width,u.width)+u.width;a!==n&&s(a)},[e,t,n]),n}exports.Modal=y;exports.clampLeftToViewport=g;exports.clampTopToViewport=A;exports.convertBlockType=B;exports.useAutoAdjustedCenteredLeft=C;exports.useAutoAdjustedRightLeft=R;exports.useHorizontalAutoAdjustedLeft=T;
2
- //# sourceMappingURL=usePopoverEdgeClamp-gRlLQeVG.cjs.map
1
+ "use strict";const x=require("react/jsx-runtime"),r=require("react"),L=require("./icons-DQ7j_-ZK.cjs"),v='button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';function y({isOpen:t,onClose:e,title:o,size:n="default",variant:s="dialog",children:u}){const c=r.useRef(null),a=r.useRef(null);if(r.useEffect(()=>{if(!t)return;const l=d=>{d.key==="Escape"&&e()};return document.addEventListener("keydown",l),()=>document.removeEventListener("keydown",l)},[t,e]),r.useEffect(()=>{var l,d,m;if(t){a.current=document.activeElement;const f=c.current;(l=(f==null?void 0:f.querySelector(v))??f)==null||l.focus();return}(m=(d=a.current)==null?void 0:d.focus)==null||m.call(d),a.current=null},[t]),!t)return null;const i=s==="sheet";return x.jsx("div",{className:`be-modal-overlay${i?" be-modal-overlay-sheet":""}`,onMouseDown:l=>{l.target===l.currentTarget&&e()},children:x.jsxs("div",{ref:c,className:`be-modal${n==="large"?" be-modal-large":""}${i?" be-modal-sheet":""}`,role:"dialog","aria-modal":"true","aria-label":o,tabIndex:-1,children:[o&&x.jsx("div",{className:"be-modal-title",children:o}),u]})})}const p=8;function g(t,e){const o=Math.max(p,window.innerWidth-e-p);return Math.min(Math.max(t,p),o)}function A(t,e){const o=Math.max(p,window.innerHeight-e-p);return Math.min(Math.max(t,p),o)}function B(t,e,o,n,s,u){const c=t.getBlock(e),i=t.getBlock(c.parentId).contentIds.indexOf(e),l="titleRunIds"in n,d="titleRunIds"in(c.props??{}),m=u?!u.isLeaf(c.type)&&c.contentIds.length>0:!1,f=u?!u.isLeaf(o):!1,h=[];if(m&&!f&&c.contentIds.forEach((E,w)=>h.push(L.moveBlock(E,c.parentId,i+1+w))),h.push(L.changeBlockType(e,o,n)),l)h.push(L.updateBlockProps(e,{titleRunIds:s})),!d&&!m&&h.push(L.setBlockContentIds(e,[]));else{const E=m&&f?c.contentIds:[];h.push(L.setBlockContentIds(e,[...E,...s]))}return{newBlockId:e,ops:h}}function T(t,e,o){const[n,s]=r.useState(null);return r.useLayoutEffect(()=>{s(o??null)},[o]),r.useLayoutEffect(()=>{if(!e||!t.current||n==null)return;const u=t.current.getBoundingClientRect(),c=g(n,u.width);c!==n&&s(c)},[e,t,n]),n}function C(t,e,o){const[n,s]=r.useState(null);return r.useLayoutEffect(()=>{s(o??null)},[o]),r.useLayoutEffect(()=>{if(!e||!t.current||n==null)return;const u=t.current.getBoundingClientRect(),c=u.width/2,i=g(n-c,u.width)+c;i!==n&&s(i)},[e,t,n]),n}function R(t,e,o){const[n,s]=r.useState(null);return r.useLayoutEffect(()=>{s(o??null)},[o]),r.useLayoutEffect(()=>{if(!e||!t.current||n==null)return;const u=t.current.getBoundingClientRect(),a=g(n-u.width,u.width)+u.width;a!==n&&s(a)},[e,t,n]),n}exports.Modal=y;exports.clampLeftToViewport=g;exports.clampTopToViewport=A;exports.convertBlockType=B;exports.useAutoAdjustedCenteredLeft=C;exports.useAutoAdjustedRightLeft=R;exports.useHorizontalAutoAdjustedLeft=T;
2
+ //# sourceMappingURL=usePopoverEdgeClamp-BJLbbANB.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"usePopoverEdgeClamp-gRlLQeVG.cjs","sources":["../../src/react/Modal.jsx","../../src/react/popoverPosition.js","../../src/blocks/shared/convertBlockType.js","../../src/react/usePopoverEdgeClamp.js"],"sourcesContent":["import { useEffect, useRef } from 'react';\n\nconst FOCUSABLE_SELECTOR =\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\n/**\n * Minimal, dependency-free modal dialog: a fixed backdrop + centered panel.\n * Closes on Escape or a click directly on the backdrop (not bubbled up from\n * inside the panel, which is why the backdrop's onMouseDown checks\n * `event.target === event.currentTarget`). No focus trap — the whole\n * editor package is deliberately zero-dependency, and dialogs here are\n * short, single-purpose forms, not deep navigable UI.\n *\n * Does move focus IN (to the first focusable element inside the panel, or\n * the panel itself as a fallback) on open, and OUT (back to whatever had\n * focus right before the modal opened — typically the button that opened\n * it) on close — distinct from a focus trap: it's a one-time move each\n * way, not a loop that prevents Tab from ever leaving the panel.\n */\nexport function Modal({ isOpen, onClose, title, size = 'default', variant = 'dialog', children }) {\n const panelRef = useRef(null);\n const previouslyFocusedRef = useRef(null);\n\n useEffect(() => {\n if (!isOpen) return undefined;\n const handleKeyDown = (event) => {\n if (event.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [isOpen, onClose]);\n\n useEffect(() => {\n if (isOpen) {\n previouslyFocusedRef.current = document.activeElement;\n const panel = panelRef.current;\n const focusable = panel?.querySelector(FOCUSABLE_SELECTOR);\n (focusable ?? panel)?.focus();\n return undefined;\n }\n previouslyFocusedRef.current?.focus?.();\n previouslyFocusedRef.current = null;\n return undefined;\n }, [isOpen]);\n\n if (!isOpen) return null;\n const isSheet = variant === 'sheet';\n\n return (\n <div\n className={`be-modal-overlay${isSheet ? ' be-modal-overlay-sheet' : ''}`}\n onMouseDown={(event) => {\n if (event.target === event.currentTarget) onClose();\n }}\n >\n <div\n ref={panelRef}\n className={`be-modal${size === 'large' ? ' be-modal-large' : ''}${isSheet ? ' be-modal-sheet' : ''}`}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n tabIndex={-1}\n >\n {title && <div className=\"be-modal-title\">{title}</div>}\n {children}\n </div>\n </div>\n );\n}\n","const MARGIN = 8;\n\n/**\n * Shifts `left`/`top` back inside the viewport (never past the opposite\n * edge either) for a box of the given size — the \"shift\" strategy antd's\n * `autoAdjustOverflow` uses, not a side-flip. Shared by every popover-\n * positioning hook in this file so the margin/clamp math lives in exactly\n * one place.\n */\nexport function clampLeftToViewport(left, width) {\n const maxLeft = Math.max(MARGIN, window.innerWidth - width - MARGIN);\n return Math.min(Math.max(left, MARGIN), maxLeft);\n}\n\nexport function clampTopToViewport(top, height) {\n const maxTop = Math.max(MARGIN, window.innerHeight - height - MARGIN);\n return Math.min(Math.max(top, MARGIN), maxTop);\n}\n","import {\n changeBlockType,\n moveBlock,\n setBlockContentIds,\n updateBlockProps,\n} from '../../store/operations.js';\n\n/**\n * Builds the ops that convert `blockId` to a different type IN PLACE — same\n * id, same parentId, same position among siblings — carrying over `runIds`\n * (reusing the existing Run objects — never recreated) rather than creating\n * new ones, so any marks/text already typed survive the conversion. `props`\n * may include `titleRunIds` (for a listItem-shaped target) — `runIds` is\n * threaded into whichever of contentIds/props.titleRunIds the target type\n * actually uses (and whichever the *source* type used, when detaching).\n *\n * Keeping the same id (rather than deleting the old block and inserting a\n * new one) matters beyond just simplicity: it's what lets a future\n * multi-peer merge treat two concurrent conversions of the same block as\n * one field-level conflict on that id (last-write-wins) instead of two\n * unrelated structural edits that would otherwise leave both resulting\n * blocks sitting side by side after merging.\n *\n * `registry` is optional and additive — this function's two original\n * callers (markdownShortcuts.js, applyVoiceAction.js) never pass one, and\n * only ever call this on a fresh, childless, single-run paragraph, so their\n * behavior is completely unaffected by anything below. When `registry` IS\n * supplied (the \"Turn into\" feature), the *source* block's own nested\n * children — real child blocks in `contentIds`, distinct from a leaf's own\n * runs, true for `listItem`/`toggleHeading`/`callout` (`!registry.isLeaf`)\n * — are handled instead of being silently orphaned:\n * - If the *target* type can also hold children (`!registry.isLeaf(type)`,\n * e.g. listItem -> toggleHeading), the children simply stay parented to\n * this same block id — nothing needs to move.\n * - If the target is a pure leaf (e.g. toggleHeading -> heading) and can't\n * hold them, they're promoted to sibling blocks inserted immediately\n * after this block instead — content is never silently dropped.\n *\n * Returns `{ ops, newBlockId }` rather than applying anything itself —\n * `newBlockId` is always `blockId` (kept for backward compatibility with\n * callers written when this returned a freshly generated id). The caller\n * folds `ops` into its own batch (e.g. alongside an `updateRun` that strips\n * a matched markdown-shortcut prefix from the first run), so the whole\n * thing is one atomic undo step.\n */\nexport function convertBlockType(store, blockId, type, props, runIds, registry) {\n const block = store.getBlock(blockId);\n const parent = store.getBlock(block.parentId);\n const index = parent.contentIds.indexOf(blockId);\n const targetUsesTitleRunIds = 'titleRunIds' in props;\n const sourceUsesTitleRunIds = 'titleRunIds' in (block.props ?? {});\n const sourceHasChildren = registry\n ? !registry.isLeaf(block.type) && block.contentIds.length > 0\n : false;\n const targetCanHoldChildren = registry ? !registry.isLeaf(type) : false;\n\n const ops = [];\n\n // Children only need to move when the target can't hold them (promoted\n // to siblings). When the target can also hold children, they're already\n // correctly parented to this same block id — nothing to do.\n if (sourceHasChildren && !targetCanHoldChildren) {\n block.contentIds.forEach((childId, i) =>\n ops.push(moveBlock(childId, block.parentId, index + 1 + i)),\n );\n }\n\n ops.push(changeBlockType(blockId, type, props));\n\n if (targetUsesTitleRunIds) {\n ops.push(updateBlockProps(blockId, { titleRunIds: runIds }));\n // A leaf source's old contentIds held its own runs, now superseded by\n // titleRunIds — clear it so those ids aren't misread as child blocks.\n // A container source that already used titleRunIds (or had its\n // children promoted to siblings above) already has the right\n // contentIds and needs no clearing.\n if (!sourceUsesTitleRunIds && !sourceHasChildren) {\n ops.push(setBlockContentIds(blockId, []));\n }\n } else {\n // Target keeps its own runs directly in contentIds. Any children still\n // sitting in contentIds at this point are ones the target can also\n // hold (handled above) and must be kept alongside the transferred\n // runIds, not replaced by them.\n const keepChildren = sourceHasChildren && targetCanHoldChildren ? block.contentIds : [];\n ops.push(setBlockContentIds(blockId, [...keepChildren, ...runIds]));\n }\n\n return { newBlockId: blockId, ops };\n}\n","import { useLayoutEffect, useState } from 'react';\nimport { clampLeftToViewport } from './popoverPosition.js';\n\n// All three hooks below share the exact two-phase shape\n// useAutoAdjustedPosition.js documents in full (snap to the raw anchor\n// first so nothing jumps, then measure + clamp once real layout exists,\n// both as useLayoutEffects so the whole chain settles before the browser\n// ever paints) — only the *anchor math* differs per popover's own CSS\n// convention, so each is kept as its own tiny hook rather than forcing one\n// generic shape to cover every transform variant.\n\n/**\n * For a popover that's LEFT-anchored (plain `left: <value>`, no transform)\n * but already owns its own vertical placement (Select/SlashMenu both flip\n * between `top`/`bottom` to dodge the on-screen keyboard) — this only ever\n * touches the horizontal axis, leaving the caller's vertical decision alone.\n */\nexport function useHorizontalAutoAdjustedLeft(menuRef, isOpen, rawLeft) {\n const [left, setLeft] = useState(null);\n\n useLayoutEffect(() => {\n setLeft(rawLeft ?? null);\n }, [rawLeft]);\n\n useLayoutEffect(() => {\n if (!isOpen || !menuRef.current || left == null) return;\n const rect = menuRef.current.getBoundingClientRect();\n const clamped = clampLeftToViewport(left, rect.width);\n if (clamped !== left) setLeft(clamped);\n }, [isOpen, menuRef, left]);\n\n return left;\n}\n\n/**\n * For a popover CENTERED on an x-coordinate via `left: <centerX>;\n * transform: translateX(-50%)` (FloatingToolbar's own bubble, centered over\n * the text selection it's formatting) — clamps the box's actual left/right\n * edges (accounting for the -50% shift) and returns an adjusted `centerX`\n * for that same `left` + `transform: translateX(-50%)` pairing, so the\n * caller's JSX doesn't need to change anything but the number.\n */\nexport function useAutoAdjustedCenteredLeft(menuRef, isOpen, rawCenterLeft) {\n const [centerLeft, setCenterLeft] = useState(null);\n\n useLayoutEffect(() => {\n setCenterLeft(rawCenterLeft ?? null);\n }, [rawCenterLeft]);\n\n useLayoutEffect(() => {\n if (!isOpen || !menuRef.current || centerLeft == null) return;\n const rect = menuRef.current.getBoundingClientRect();\n const half = rect.width / 2;\n const clampedEdge = clampLeftToViewport(centerLeft - half, rect.width);\n const nextCenter = clampedEdge + half;\n if (nextCenter !== centerLeft) setCenterLeft(nextCenter);\n }, [isOpen, menuRef, centerLeft]);\n\n return centerLeft;\n}\n\n/**\n * For a popover RIGHT-anchored on an x-coordinate via `left: <rightEdgeX>;\n * transform: translateX(-100%)` (TableHeaderRow's column menu, whose right\n * edge lines up with the header cell's own right edge and grows leftward)\n * — clamps the box's actual left edge and returns an adjusted `rightEdgeX`\n * for that same `left` + `transform: translateX(-100%)` pairing.\n */\nexport function useAutoAdjustedRightLeft(menuRef, isOpen, rawRightEdgeLeft) {\n const [rightLeft, setRightLeft] = useState(null);\n\n useLayoutEffect(() => {\n setRightLeft(rawRightEdgeLeft ?? null);\n }, [rawRightEdgeLeft]);\n\n useLayoutEffect(() => {\n if (!isOpen || !menuRef.current || rightLeft == null) return;\n const rect = menuRef.current.getBoundingClientRect();\n const clampedEdge = clampLeftToViewport(rightLeft - rect.width, rect.width);\n const nextRightLeft = clampedEdge + rect.width;\n if (nextRightLeft !== rightLeft) setRightLeft(nextRightLeft);\n }, [isOpen, menuRef, rightLeft]);\n\n return rightLeft;\n}\n"],"names":["FOCUSABLE_SELECTOR","Modal","isOpen","onClose","title","size","variant","children","panelRef","useRef","previouslyFocusedRef","useEffect","handleKeyDown","event","panel","_a","_c","_b","isSheet","jsx","jsxs","MARGIN","clampLeftToViewport","left","width","maxLeft","clampTopToViewport","top","height","maxTop","convertBlockType","store","blockId","type","props","runIds","registry","block","index","targetUsesTitleRunIds","sourceUsesTitleRunIds","sourceHasChildren","targetCanHoldChildren","ops","childId","i","moveBlock","changeBlockType","updateBlockProps","setBlockContentIds","keepChildren","useHorizontalAutoAdjustedLeft","menuRef","rawLeft","setLeft","useState","useLayoutEffect","rect","clamped","useAutoAdjustedCenteredLeft","rawCenterLeft","centerLeft","setCenterLeft","half","nextCenter","useAutoAdjustedRightLeft","rawRightEdgeLeft","rightLeft","setRightLeft","nextRightLeft"],"mappings":"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"}
1
+ {"version":3,"file":"usePopoverEdgeClamp-BJLbbANB.cjs","sources":["../../src/react/Modal.jsx","../../src/react/popoverPosition.js","../../src/blocks/shared/convertBlockType.js","../../src/react/usePopoverEdgeClamp.js"],"sourcesContent":["import { useEffect, useRef } from 'react';\n\nconst FOCUSABLE_SELECTOR =\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\n/**\n * Minimal, dependency-free modal dialog: a fixed backdrop + centered panel.\n * Closes on Escape or a click directly on the backdrop (not bubbled up from\n * inside the panel, which is why the backdrop's onMouseDown checks\n * `event.target === event.currentTarget`). No focus trap — the whole\n * editor package is deliberately zero-dependency, and dialogs here are\n * short, single-purpose forms, not deep navigable UI.\n *\n * Does move focus IN (to the first focusable element inside the panel, or\n * the panel itself as a fallback) on open, and OUT (back to whatever had\n * focus right before the modal opened — typically the button that opened\n * it) on close — distinct from a focus trap: it's a one-time move each\n * way, not a loop that prevents Tab from ever leaving the panel.\n */\nexport function Modal({ isOpen, onClose, title, size = 'default', variant = 'dialog', children }) {\n const panelRef = useRef(null);\n const previouslyFocusedRef = useRef(null);\n\n useEffect(() => {\n if (!isOpen) return undefined;\n const handleKeyDown = (event) => {\n if (event.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [isOpen, onClose]);\n\n useEffect(() => {\n if (isOpen) {\n previouslyFocusedRef.current = document.activeElement;\n const panel = panelRef.current;\n const focusable = panel?.querySelector(FOCUSABLE_SELECTOR);\n (focusable ?? panel)?.focus();\n return undefined;\n }\n previouslyFocusedRef.current?.focus?.();\n previouslyFocusedRef.current = null;\n return undefined;\n }, [isOpen]);\n\n if (!isOpen) return null;\n const isSheet = variant === 'sheet';\n\n return (\n <div\n className={`be-modal-overlay${isSheet ? ' be-modal-overlay-sheet' : ''}`}\n onMouseDown={(event) => {\n if (event.target === event.currentTarget) onClose();\n }}\n >\n <div\n ref={panelRef}\n className={`be-modal${size === 'large' ? ' be-modal-large' : ''}${isSheet ? ' be-modal-sheet' : ''}`}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n tabIndex={-1}\n >\n {title && <div className=\"be-modal-title\">{title}</div>}\n {children}\n </div>\n </div>\n );\n}\n","const MARGIN = 8;\n\n/**\n * Shifts `left`/`top` back inside the viewport (never past the opposite\n * edge either) for a box of the given size — the \"shift\" strategy antd's\n * `autoAdjustOverflow` uses, not a side-flip. Shared by every popover-\n * positioning hook in this file so the margin/clamp math lives in exactly\n * one place.\n */\nexport function clampLeftToViewport(left, width) {\n const maxLeft = Math.max(MARGIN, window.innerWidth - width - MARGIN);\n return Math.min(Math.max(left, MARGIN), maxLeft);\n}\n\nexport function clampTopToViewport(top, height) {\n const maxTop = Math.max(MARGIN, window.innerHeight - height - MARGIN);\n return Math.min(Math.max(top, MARGIN), maxTop);\n}\n","import {\n changeBlockType,\n moveBlock,\n setBlockContentIds,\n updateBlockProps,\n} from '../../store/operations.js';\n\n/**\n * Builds the ops that convert `blockId` to a different type IN PLACE — same\n * id, same parentId, same position among siblings — carrying over `runIds`\n * (reusing the existing Run objects — never recreated) rather than creating\n * new ones, so any marks/text already typed survive the conversion. `props`\n * may include `titleRunIds` (for a listItem-shaped target) — `runIds` is\n * threaded into whichever of contentIds/props.titleRunIds the target type\n * actually uses (and whichever the *source* type used, when detaching).\n *\n * Keeping the same id (rather than deleting the old block and inserting a\n * new one) matters beyond just simplicity: it's what lets a future\n * multi-peer merge treat two concurrent conversions of the same block as\n * one field-level conflict on that id (last-write-wins) instead of two\n * unrelated structural edits that would otherwise leave both resulting\n * blocks sitting side by side after merging.\n *\n * `registry` is optional and additive — this function's two original\n * callers (markdownShortcuts.js, applyVoiceAction.js) never pass one, and\n * only ever call this on a fresh, childless, single-run paragraph, so their\n * behavior is completely unaffected by anything below. When `registry` IS\n * supplied (the \"Turn into\" feature), the *source* block's own nested\n * children — real child blocks in `contentIds`, distinct from a leaf's own\n * runs, true for `listItem`/`toggleHeading`/`callout` (`!registry.isLeaf`)\n * — are handled instead of being silently orphaned:\n * - If the *target* type can also hold children (`!registry.isLeaf(type)`,\n * e.g. listItem -> toggleHeading), the children simply stay parented to\n * this same block id — nothing needs to move.\n * - If the target is a pure leaf (e.g. toggleHeading -> heading) and can't\n * hold them, they're promoted to sibling blocks inserted immediately\n * after this block instead — content is never silently dropped.\n *\n * Returns `{ ops, newBlockId }` rather than applying anything itself —\n * `newBlockId` is always `blockId` (kept for backward compatibility with\n * callers written when this returned a freshly generated id). The caller\n * folds `ops` into its own batch (e.g. alongside an `updateRun` that strips\n * a matched markdown-shortcut prefix from the first run), so the whole\n * thing is one atomic undo step.\n */\nexport function convertBlockType(store, blockId, type, props, runIds, registry) {\n const block = store.getBlock(blockId);\n const parent = store.getBlock(block.parentId);\n const index = parent.contentIds.indexOf(blockId);\n const targetUsesTitleRunIds = 'titleRunIds' in props;\n const sourceUsesTitleRunIds = 'titleRunIds' in (block.props ?? {});\n const sourceHasChildren = registry\n ? !registry.isLeaf(block.type) && block.contentIds.length > 0\n : false;\n const targetCanHoldChildren = registry ? !registry.isLeaf(type) : false;\n\n const ops = [];\n\n // Children only need to move when the target can't hold them (promoted\n // to siblings). When the target can also hold children, they're already\n // correctly parented to this same block id — nothing to do.\n if (sourceHasChildren && !targetCanHoldChildren) {\n block.contentIds.forEach((childId, i) =>\n ops.push(moveBlock(childId, block.parentId, index + 1 + i)),\n );\n }\n\n ops.push(changeBlockType(blockId, type, props));\n\n if (targetUsesTitleRunIds) {\n ops.push(updateBlockProps(blockId, { titleRunIds: runIds }));\n // A leaf source's old contentIds held its own runs, now superseded by\n // titleRunIds — clear it so those ids aren't misread as child blocks.\n // A container source that already used titleRunIds (or had its\n // children promoted to siblings above) already has the right\n // contentIds and needs no clearing.\n if (!sourceUsesTitleRunIds && !sourceHasChildren) {\n ops.push(setBlockContentIds(blockId, []));\n }\n } else {\n // Target keeps its own runs directly in contentIds. Any children still\n // sitting in contentIds at this point are ones the target can also\n // hold (handled above) and must be kept alongside the transferred\n // runIds, not replaced by them.\n const keepChildren = sourceHasChildren && targetCanHoldChildren ? block.contentIds : [];\n ops.push(setBlockContentIds(blockId, [...keepChildren, ...runIds]));\n }\n\n return { newBlockId: blockId, ops };\n}\n","import { useLayoutEffect, useState } from 'react';\nimport { clampLeftToViewport } from './popoverPosition.js';\n\n// All three hooks below share the exact two-phase shape\n// useAutoAdjustedPosition.js documents in full (snap to the raw anchor\n// first so nothing jumps, then measure + clamp once real layout exists,\n// both as useLayoutEffects so the whole chain settles before the browser\n// ever paints) — only the *anchor math* differs per popover's own CSS\n// convention, so each is kept as its own tiny hook rather than forcing one\n// generic shape to cover every transform variant.\n\n/**\n * For a popover that's LEFT-anchored (plain `left: <value>`, no transform)\n * but already owns its own vertical placement (Select/SlashMenu both flip\n * between `top`/`bottom` to dodge the on-screen keyboard) — this only ever\n * touches the horizontal axis, leaving the caller's vertical decision alone.\n */\nexport function useHorizontalAutoAdjustedLeft(menuRef, isOpen, rawLeft) {\n const [left, setLeft] = useState(null);\n\n useLayoutEffect(() => {\n setLeft(rawLeft ?? null);\n }, [rawLeft]);\n\n useLayoutEffect(() => {\n if (!isOpen || !menuRef.current || left == null) return;\n const rect = menuRef.current.getBoundingClientRect();\n const clamped = clampLeftToViewport(left, rect.width);\n if (clamped !== left) setLeft(clamped);\n }, [isOpen, menuRef, left]);\n\n return left;\n}\n\n/**\n * For a popover CENTERED on an x-coordinate via `left: <centerX>;\n * transform: translateX(-50%)` (FloatingToolbar's own bubble, centered over\n * the text selection it's formatting) — clamps the box's actual left/right\n * edges (accounting for the -50% shift) and returns an adjusted `centerX`\n * for that same `left` + `transform: translateX(-50%)` pairing, so the\n * caller's JSX doesn't need to change anything but the number.\n */\nexport function useAutoAdjustedCenteredLeft(menuRef, isOpen, rawCenterLeft) {\n const [centerLeft, setCenterLeft] = useState(null);\n\n useLayoutEffect(() => {\n setCenterLeft(rawCenterLeft ?? null);\n }, [rawCenterLeft]);\n\n useLayoutEffect(() => {\n if (!isOpen || !menuRef.current || centerLeft == null) return;\n const rect = menuRef.current.getBoundingClientRect();\n const half = rect.width / 2;\n const clampedEdge = clampLeftToViewport(centerLeft - half, rect.width);\n const nextCenter = clampedEdge + half;\n if (nextCenter !== centerLeft) setCenterLeft(nextCenter);\n }, [isOpen, menuRef, centerLeft]);\n\n return centerLeft;\n}\n\n/**\n * For a popover RIGHT-anchored on an x-coordinate via `left: <rightEdgeX>;\n * transform: translateX(-100%)` (TableHeaderRow's column menu, whose right\n * edge lines up with the header cell's own right edge and grows leftward)\n * — clamps the box's actual left edge and returns an adjusted `rightEdgeX`\n * for that same `left` + `transform: translateX(-100%)` pairing.\n */\nexport function useAutoAdjustedRightLeft(menuRef, isOpen, rawRightEdgeLeft) {\n const [rightLeft, setRightLeft] = useState(null);\n\n useLayoutEffect(() => {\n setRightLeft(rawRightEdgeLeft ?? null);\n }, [rawRightEdgeLeft]);\n\n useLayoutEffect(() => {\n if (!isOpen || !menuRef.current || rightLeft == null) return;\n const rect = menuRef.current.getBoundingClientRect();\n const clampedEdge = clampLeftToViewport(rightLeft - rect.width, rect.width);\n const nextRightLeft = clampedEdge + rect.width;\n if (nextRightLeft !== rightLeft) setRightLeft(nextRightLeft);\n }, [isOpen, menuRef, rightLeft]);\n\n return rightLeft;\n}\n"],"names":["FOCUSABLE_SELECTOR","Modal","isOpen","onClose","title","size","variant","children","panelRef","useRef","previouslyFocusedRef","useEffect","handleKeyDown","event","panel","_a","_c","_b","isSheet","jsx","jsxs","MARGIN","clampLeftToViewport","left","width","maxLeft","clampTopToViewport","top","height","maxTop","convertBlockType","store","blockId","type","props","runIds","registry","block","index","targetUsesTitleRunIds","sourceUsesTitleRunIds","sourceHasChildren","targetCanHoldChildren","ops","childId","i","moveBlock","changeBlockType","updateBlockProps","setBlockContentIds","keepChildren","useHorizontalAutoAdjustedLeft","menuRef","rawLeft","setLeft","useState","useLayoutEffect","rect","clamped","useAutoAdjustedCenteredLeft","rawCenterLeft","centerLeft","setCenterLeft","half","nextCenter","useAutoAdjustedRightLeft","rawRightEdgeLeft","rightLeft","setRightLeft","nextRightLeft"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as v, jsxs as M } from "react/jsx-runtime";
2
2
  import { useRef as w, useEffect as E, useState as x, useLayoutEffect as p } from "react";
3
- import { m as T, i as b, j as R, s as B } from "./icons-Bdptdx1e.js";
3
+ import { m as T, i as b, j as R, s as B } from "./icons-CmfXmn13.js";
4
4
  const y = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
5
5
  function j({ isOpen: t, onClose: e, title: o, size: n = "default", variant: s = "dialog", children: r }) {
6
6
  const c = w(null), u = w(null);
@@ -106,4 +106,4 @@ export {
106
106
  $ as e,
107
107
  U as u
108
108
  };
109
- //# sourceMappingURL=usePopoverEdgeClamp-B9KNv9SE.js.map
109
+ //# sourceMappingURL=usePopoverEdgeClamp-DSpz-6xR.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"usePopoverEdgeClamp-B9KNv9SE.js","sources":["../../src/react/Modal.jsx","../../src/react/popoverPosition.js","../../src/blocks/shared/convertBlockType.js","../../src/react/usePopoverEdgeClamp.js"],"sourcesContent":["import { useEffect, useRef } from 'react';\n\nconst FOCUSABLE_SELECTOR =\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\n/**\n * Minimal, dependency-free modal dialog: a fixed backdrop + centered panel.\n * Closes on Escape or a click directly on the backdrop (not bubbled up from\n * inside the panel, which is why the backdrop's onMouseDown checks\n * `event.target === event.currentTarget`). No focus trap — the whole\n * editor package is deliberately zero-dependency, and dialogs here are\n * short, single-purpose forms, not deep navigable UI.\n *\n * Does move focus IN (to the first focusable element inside the panel, or\n * the panel itself as a fallback) on open, and OUT (back to whatever had\n * focus right before the modal opened — typically the button that opened\n * it) on close — distinct from a focus trap: it's a one-time move each\n * way, not a loop that prevents Tab from ever leaving the panel.\n */\nexport function Modal({ isOpen, onClose, title, size = 'default', variant = 'dialog', children }) {\n const panelRef = useRef(null);\n const previouslyFocusedRef = useRef(null);\n\n useEffect(() => {\n if (!isOpen) return undefined;\n const handleKeyDown = (event) => {\n if (event.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [isOpen, onClose]);\n\n useEffect(() => {\n if (isOpen) {\n previouslyFocusedRef.current = document.activeElement;\n const panel = panelRef.current;\n const focusable = panel?.querySelector(FOCUSABLE_SELECTOR);\n (focusable ?? panel)?.focus();\n return undefined;\n }\n previouslyFocusedRef.current?.focus?.();\n previouslyFocusedRef.current = null;\n return undefined;\n }, [isOpen]);\n\n if (!isOpen) return null;\n const isSheet = variant === 'sheet';\n\n return (\n <div\n className={`be-modal-overlay${isSheet ? ' be-modal-overlay-sheet' : ''}`}\n onMouseDown={(event) => {\n if (event.target === event.currentTarget) onClose();\n }}\n >\n <div\n ref={panelRef}\n className={`be-modal${size === 'large' ? ' be-modal-large' : ''}${isSheet ? ' be-modal-sheet' : ''}`}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n tabIndex={-1}\n >\n {title && <div className=\"be-modal-title\">{title}</div>}\n {children}\n </div>\n </div>\n );\n}\n","const MARGIN = 8;\n\n/**\n * Shifts `left`/`top` back inside the viewport (never past the opposite\n * edge either) for a box of the given size — the \"shift\" strategy antd's\n * `autoAdjustOverflow` uses, not a side-flip. Shared by every popover-\n * positioning hook in this file so the margin/clamp math lives in exactly\n * one place.\n */\nexport function clampLeftToViewport(left, width) {\n const maxLeft = Math.max(MARGIN, window.innerWidth - width - MARGIN);\n return Math.min(Math.max(left, MARGIN), maxLeft);\n}\n\nexport function clampTopToViewport(top, height) {\n const maxTop = Math.max(MARGIN, window.innerHeight - height - MARGIN);\n return Math.min(Math.max(top, MARGIN), maxTop);\n}\n","import {\n changeBlockType,\n moveBlock,\n setBlockContentIds,\n updateBlockProps,\n} from '../../store/operations.js';\n\n/**\n * Builds the ops that convert `blockId` to a different type IN PLACE — same\n * id, same parentId, same position among siblings — carrying over `runIds`\n * (reusing the existing Run objects — never recreated) rather than creating\n * new ones, so any marks/text already typed survive the conversion. `props`\n * may include `titleRunIds` (for a listItem-shaped target) — `runIds` is\n * threaded into whichever of contentIds/props.titleRunIds the target type\n * actually uses (and whichever the *source* type used, when detaching).\n *\n * Keeping the same id (rather than deleting the old block and inserting a\n * new one) matters beyond just simplicity: it's what lets a future\n * multi-peer merge treat two concurrent conversions of the same block as\n * one field-level conflict on that id (last-write-wins) instead of two\n * unrelated structural edits that would otherwise leave both resulting\n * blocks sitting side by side after merging.\n *\n * `registry` is optional and additive — this function's two original\n * callers (markdownShortcuts.js, applyVoiceAction.js) never pass one, and\n * only ever call this on a fresh, childless, single-run paragraph, so their\n * behavior is completely unaffected by anything below. When `registry` IS\n * supplied (the \"Turn into\" feature), the *source* block's own nested\n * children — real child blocks in `contentIds`, distinct from a leaf's own\n * runs, true for `listItem`/`toggleHeading`/`callout` (`!registry.isLeaf`)\n * — are handled instead of being silently orphaned:\n * - If the *target* type can also hold children (`!registry.isLeaf(type)`,\n * e.g. listItem -> toggleHeading), the children simply stay parented to\n * this same block id — nothing needs to move.\n * - If the target is a pure leaf (e.g. toggleHeading -> heading) and can't\n * hold them, they're promoted to sibling blocks inserted immediately\n * after this block instead — content is never silently dropped.\n *\n * Returns `{ ops, newBlockId }` rather than applying anything itself —\n * `newBlockId` is always `blockId` (kept for backward compatibility with\n * callers written when this returned a freshly generated id). The caller\n * folds `ops` into its own batch (e.g. alongside an `updateRun` that strips\n * a matched markdown-shortcut prefix from the first run), so the whole\n * thing is one atomic undo step.\n */\nexport function convertBlockType(store, blockId, type, props, runIds, registry) {\n const block = store.getBlock(blockId);\n const parent = store.getBlock(block.parentId);\n const index = parent.contentIds.indexOf(blockId);\n const targetUsesTitleRunIds = 'titleRunIds' in props;\n const sourceUsesTitleRunIds = 'titleRunIds' in (block.props ?? {});\n const sourceHasChildren = registry\n ? !registry.isLeaf(block.type) && block.contentIds.length > 0\n : false;\n const targetCanHoldChildren = registry ? !registry.isLeaf(type) : false;\n\n const ops = [];\n\n // Children only need to move when the target can't hold them (promoted\n // to siblings). When the target can also hold children, they're already\n // correctly parented to this same block id — nothing to do.\n if (sourceHasChildren && !targetCanHoldChildren) {\n block.contentIds.forEach((childId, i) =>\n ops.push(moveBlock(childId, block.parentId, index + 1 + i)),\n );\n }\n\n ops.push(changeBlockType(blockId, type, props));\n\n if (targetUsesTitleRunIds) {\n ops.push(updateBlockProps(blockId, { titleRunIds: runIds }));\n // A leaf source's old contentIds held its own runs, now superseded by\n // titleRunIds — clear it so those ids aren't misread as child blocks.\n // A container source that already used titleRunIds (or had its\n // children promoted to siblings above) already has the right\n // contentIds and needs no clearing.\n if (!sourceUsesTitleRunIds && !sourceHasChildren) {\n ops.push(setBlockContentIds(blockId, []));\n }\n } else {\n // Target keeps its own runs directly in contentIds. Any children still\n // sitting in contentIds at this point are ones the target can also\n // hold (handled above) and must be kept alongside the transferred\n // runIds, not replaced by them.\n const keepChildren = sourceHasChildren && targetCanHoldChildren ? block.contentIds : [];\n ops.push(setBlockContentIds(blockId, [...keepChildren, ...runIds]));\n }\n\n return { newBlockId: blockId, ops };\n}\n","import { useLayoutEffect, useState } from 'react';\nimport { clampLeftToViewport } from './popoverPosition.js';\n\n// All three hooks below share the exact two-phase shape\n// useAutoAdjustedPosition.js documents in full (snap to the raw anchor\n// first so nothing jumps, then measure + clamp once real layout exists,\n// both as useLayoutEffects so the whole chain settles before the browser\n// ever paints) — only the *anchor math* differs per popover's own CSS\n// convention, so each is kept as its own tiny hook rather than forcing one\n// generic shape to cover every transform variant.\n\n/**\n * For a popover that's LEFT-anchored (plain `left: <value>`, no transform)\n * but already owns its own vertical placement (Select/SlashMenu both flip\n * between `top`/`bottom` to dodge the on-screen keyboard) — this only ever\n * touches the horizontal axis, leaving the caller's vertical decision alone.\n */\nexport function useHorizontalAutoAdjustedLeft(menuRef, isOpen, rawLeft) {\n const [left, setLeft] = useState(null);\n\n useLayoutEffect(() => {\n setLeft(rawLeft ?? null);\n }, [rawLeft]);\n\n useLayoutEffect(() => {\n if (!isOpen || !menuRef.current || left == null) return;\n const rect = menuRef.current.getBoundingClientRect();\n const clamped = clampLeftToViewport(left, rect.width);\n if (clamped !== left) setLeft(clamped);\n }, [isOpen, menuRef, left]);\n\n return left;\n}\n\n/**\n * For a popover CENTERED on an x-coordinate via `left: <centerX>;\n * transform: translateX(-50%)` (FloatingToolbar's own bubble, centered over\n * the text selection it's formatting) — clamps the box's actual left/right\n * edges (accounting for the -50% shift) and returns an adjusted `centerX`\n * for that same `left` + `transform: translateX(-50%)` pairing, so the\n * caller's JSX doesn't need to change anything but the number.\n */\nexport function useAutoAdjustedCenteredLeft(menuRef, isOpen, rawCenterLeft) {\n const [centerLeft, setCenterLeft] = useState(null);\n\n useLayoutEffect(() => {\n setCenterLeft(rawCenterLeft ?? null);\n }, [rawCenterLeft]);\n\n useLayoutEffect(() => {\n if (!isOpen || !menuRef.current || centerLeft == null) return;\n const rect = menuRef.current.getBoundingClientRect();\n const half = rect.width / 2;\n const clampedEdge = clampLeftToViewport(centerLeft - half, rect.width);\n const nextCenter = clampedEdge + half;\n if (nextCenter !== centerLeft) setCenterLeft(nextCenter);\n }, [isOpen, menuRef, centerLeft]);\n\n return centerLeft;\n}\n\n/**\n * For a popover RIGHT-anchored on an x-coordinate via `left: <rightEdgeX>;\n * transform: translateX(-100%)` (TableHeaderRow's column menu, whose right\n * edge lines up with the header cell's own right edge and grows leftward)\n * — clamps the box's actual left edge and returns an adjusted `rightEdgeX`\n * for that same `left` + `transform: translateX(-100%)` pairing.\n */\nexport function useAutoAdjustedRightLeft(menuRef, isOpen, rawRightEdgeLeft) {\n const [rightLeft, setRightLeft] = useState(null);\n\n useLayoutEffect(() => {\n setRightLeft(rawRightEdgeLeft ?? null);\n }, [rawRightEdgeLeft]);\n\n useLayoutEffect(() => {\n if (!isOpen || !menuRef.current || rightLeft == null) return;\n const rect = menuRef.current.getBoundingClientRect();\n const clampedEdge = clampLeftToViewport(rightLeft - rect.width, rect.width);\n const nextRightLeft = clampedEdge + rect.width;\n if (nextRightLeft !== rightLeft) setRightLeft(nextRightLeft);\n }, [isOpen, menuRef, rightLeft]);\n\n return rightLeft;\n}\n"],"names":["FOCUSABLE_SELECTOR","Modal","isOpen","onClose","title","size","variant","children","panelRef","useRef","previouslyFocusedRef","useEffect","handleKeyDown","event","panel","_a","_c","_b","isSheet","jsx","jsxs","MARGIN","clampLeftToViewport","left","width","maxLeft","clampTopToViewport","top","height","maxTop","convertBlockType","store","blockId","type","props","runIds","registry","block","index","targetUsesTitleRunIds","sourceUsesTitleRunIds","sourceHasChildren","targetCanHoldChildren","ops","childId","i","moveBlock","changeBlockType","updateBlockProps","setBlockContentIds","keepChildren","useHorizontalAutoAdjustedLeft","menuRef","rawLeft","setLeft","useState","useLayoutEffect","rect","clamped","useAutoAdjustedCenteredLeft","rawCenterLeft","centerLeft","setCenterLeft","half","nextCenter","useAutoAdjustedRightLeft","rawRightEdgeLeft","rightLeft","setRightLeft","nextRightLeft"],"mappings":"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"}
1
+ {"version":3,"file":"usePopoverEdgeClamp-DSpz-6xR.js","sources":["../../src/react/Modal.jsx","../../src/react/popoverPosition.js","../../src/blocks/shared/convertBlockType.js","../../src/react/usePopoverEdgeClamp.js"],"sourcesContent":["import { useEffect, useRef } from 'react';\n\nconst FOCUSABLE_SELECTOR =\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\n/**\n * Minimal, dependency-free modal dialog: a fixed backdrop + centered panel.\n * Closes on Escape or a click directly on the backdrop (not bubbled up from\n * inside the panel, which is why the backdrop's onMouseDown checks\n * `event.target === event.currentTarget`). No focus trap — the whole\n * editor package is deliberately zero-dependency, and dialogs here are\n * short, single-purpose forms, not deep navigable UI.\n *\n * Does move focus IN (to the first focusable element inside the panel, or\n * the panel itself as a fallback) on open, and OUT (back to whatever had\n * focus right before the modal opened — typically the button that opened\n * it) on close — distinct from a focus trap: it's a one-time move each\n * way, not a loop that prevents Tab from ever leaving the panel.\n */\nexport function Modal({ isOpen, onClose, title, size = 'default', variant = 'dialog', children }) {\n const panelRef = useRef(null);\n const previouslyFocusedRef = useRef(null);\n\n useEffect(() => {\n if (!isOpen) return undefined;\n const handleKeyDown = (event) => {\n if (event.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [isOpen, onClose]);\n\n useEffect(() => {\n if (isOpen) {\n previouslyFocusedRef.current = document.activeElement;\n const panel = panelRef.current;\n const focusable = panel?.querySelector(FOCUSABLE_SELECTOR);\n (focusable ?? panel)?.focus();\n return undefined;\n }\n previouslyFocusedRef.current?.focus?.();\n previouslyFocusedRef.current = null;\n return undefined;\n }, [isOpen]);\n\n if (!isOpen) return null;\n const isSheet = variant === 'sheet';\n\n return (\n <div\n className={`be-modal-overlay${isSheet ? ' be-modal-overlay-sheet' : ''}`}\n onMouseDown={(event) => {\n if (event.target === event.currentTarget) onClose();\n }}\n >\n <div\n ref={panelRef}\n className={`be-modal${size === 'large' ? ' be-modal-large' : ''}${isSheet ? ' be-modal-sheet' : ''}`}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n tabIndex={-1}\n >\n {title && <div className=\"be-modal-title\">{title}</div>}\n {children}\n </div>\n </div>\n );\n}\n","const MARGIN = 8;\n\n/**\n * Shifts `left`/`top` back inside the viewport (never past the opposite\n * edge either) for a box of the given size — the \"shift\" strategy antd's\n * `autoAdjustOverflow` uses, not a side-flip. Shared by every popover-\n * positioning hook in this file so the margin/clamp math lives in exactly\n * one place.\n */\nexport function clampLeftToViewport(left, width) {\n const maxLeft = Math.max(MARGIN, window.innerWidth - width - MARGIN);\n return Math.min(Math.max(left, MARGIN), maxLeft);\n}\n\nexport function clampTopToViewport(top, height) {\n const maxTop = Math.max(MARGIN, window.innerHeight - height - MARGIN);\n return Math.min(Math.max(top, MARGIN), maxTop);\n}\n","import {\n changeBlockType,\n moveBlock,\n setBlockContentIds,\n updateBlockProps,\n} from '../../store/operations.js';\n\n/**\n * Builds the ops that convert `blockId` to a different type IN PLACE — same\n * id, same parentId, same position among siblings — carrying over `runIds`\n * (reusing the existing Run objects — never recreated) rather than creating\n * new ones, so any marks/text already typed survive the conversion. `props`\n * may include `titleRunIds` (for a listItem-shaped target) — `runIds` is\n * threaded into whichever of contentIds/props.titleRunIds the target type\n * actually uses (and whichever the *source* type used, when detaching).\n *\n * Keeping the same id (rather than deleting the old block and inserting a\n * new one) matters beyond just simplicity: it's what lets a future\n * multi-peer merge treat two concurrent conversions of the same block as\n * one field-level conflict on that id (last-write-wins) instead of two\n * unrelated structural edits that would otherwise leave both resulting\n * blocks sitting side by side after merging.\n *\n * `registry` is optional and additive — this function's two original\n * callers (markdownShortcuts.js, applyVoiceAction.js) never pass one, and\n * only ever call this on a fresh, childless, single-run paragraph, so their\n * behavior is completely unaffected by anything below. When `registry` IS\n * supplied (the \"Turn into\" feature), the *source* block's own nested\n * children — real child blocks in `contentIds`, distinct from a leaf's own\n * runs, true for `listItem`/`toggleHeading`/`callout` (`!registry.isLeaf`)\n * — are handled instead of being silently orphaned:\n * - If the *target* type can also hold children (`!registry.isLeaf(type)`,\n * e.g. listItem -> toggleHeading), the children simply stay parented to\n * this same block id — nothing needs to move.\n * - If the target is a pure leaf (e.g. toggleHeading -> heading) and can't\n * hold them, they're promoted to sibling blocks inserted immediately\n * after this block instead — content is never silently dropped.\n *\n * Returns `{ ops, newBlockId }` rather than applying anything itself —\n * `newBlockId` is always `blockId` (kept for backward compatibility with\n * callers written when this returned a freshly generated id). The caller\n * folds `ops` into its own batch (e.g. alongside an `updateRun` that strips\n * a matched markdown-shortcut prefix from the first run), so the whole\n * thing is one atomic undo step.\n */\nexport function convertBlockType(store, blockId, type, props, runIds, registry) {\n const block = store.getBlock(blockId);\n const parent = store.getBlock(block.parentId);\n const index = parent.contentIds.indexOf(blockId);\n const targetUsesTitleRunIds = 'titleRunIds' in props;\n const sourceUsesTitleRunIds = 'titleRunIds' in (block.props ?? {});\n const sourceHasChildren = registry\n ? !registry.isLeaf(block.type) && block.contentIds.length > 0\n : false;\n const targetCanHoldChildren = registry ? !registry.isLeaf(type) : false;\n\n const ops = [];\n\n // Children only need to move when the target can't hold them (promoted\n // to siblings). When the target can also hold children, they're already\n // correctly parented to this same block id — nothing to do.\n if (sourceHasChildren && !targetCanHoldChildren) {\n block.contentIds.forEach((childId, i) =>\n ops.push(moveBlock(childId, block.parentId, index + 1 + i)),\n );\n }\n\n ops.push(changeBlockType(blockId, type, props));\n\n if (targetUsesTitleRunIds) {\n ops.push(updateBlockProps(blockId, { titleRunIds: runIds }));\n // A leaf source's old contentIds held its own runs, now superseded by\n // titleRunIds — clear it so those ids aren't misread as child blocks.\n // A container source that already used titleRunIds (or had its\n // children promoted to siblings above) already has the right\n // contentIds and needs no clearing.\n if (!sourceUsesTitleRunIds && !sourceHasChildren) {\n ops.push(setBlockContentIds(blockId, []));\n }\n } else {\n // Target keeps its own runs directly in contentIds. Any children still\n // sitting in contentIds at this point are ones the target can also\n // hold (handled above) and must be kept alongside the transferred\n // runIds, not replaced by them.\n const keepChildren = sourceHasChildren && targetCanHoldChildren ? block.contentIds : [];\n ops.push(setBlockContentIds(blockId, [...keepChildren, ...runIds]));\n }\n\n return { newBlockId: blockId, ops };\n}\n","import { useLayoutEffect, useState } from 'react';\nimport { clampLeftToViewport } from './popoverPosition.js';\n\n// All three hooks below share the exact two-phase shape\n// useAutoAdjustedPosition.js documents in full (snap to the raw anchor\n// first so nothing jumps, then measure + clamp once real layout exists,\n// both as useLayoutEffects so the whole chain settles before the browser\n// ever paints) — only the *anchor math* differs per popover's own CSS\n// convention, so each is kept as its own tiny hook rather than forcing one\n// generic shape to cover every transform variant.\n\n/**\n * For a popover that's LEFT-anchored (plain `left: <value>`, no transform)\n * but already owns its own vertical placement (Select/SlashMenu both flip\n * between `top`/`bottom` to dodge the on-screen keyboard) — this only ever\n * touches the horizontal axis, leaving the caller's vertical decision alone.\n */\nexport function useHorizontalAutoAdjustedLeft(menuRef, isOpen, rawLeft) {\n const [left, setLeft] = useState(null);\n\n useLayoutEffect(() => {\n setLeft(rawLeft ?? null);\n }, [rawLeft]);\n\n useLayoutEffect(() => {\n if (!isOpen || !menuRef.current || left == null) return;\n const rect = menuRef.current.getBoundingClientRect();\n const clamped = clampLeftToViewport(left, rect.width);\n if (clamped !== left) setLeft(clamped);\n }, [isOpen, menuRef, left]);\n\n return left;\n}\n\n/**\n * For a popover CENTERED on an x-coordinate via `left: <centerX>;\n * transform: translateX(-50%)` (FloatingToolbar's own bubble, centered over\n * the text selection it's formatting) — clamps the box's actual left/right\n * edges (accounting for the -50% shift) and returns an adjusted `centerX`\n * for that same `left` + `transform: translateX(-50%)` pairing, so the\n * caller's JSX doesn't need to change anything but the number.\n */\nexport function useAutoAdjustedCenteredLeft(menuRef, isOpen, rawCenterLeft) {\n const [centerLeft, setCenterLeft] = useState(null);\n\n useLayoutEffect(() => {\n setCenterLeft(rawCenterLeft ?? null);\n }, [rawCenterLeft]);\n\n useLayoutEffect(() => {\n if (!isOpen || !menuRef.current || centerLeft == null) return;\n const rect = menuRef.current.getBoundingClientRect();\n const half = rect.width / 2;\n const clampedEdge = clampLeftToViewport(centerLeft - half, rect.width);\n const nextCenter = clampedEdge + half;\n if (nextCenter !== centerLeft) setCenterLeft(nextCenter);\n }, [isOpen, menuRef, centerLeft]);\n\n return centerLeft;\n}\n\n/**\n * For a popover RIGHT-anchored on an x-coordinate via `left: <rightEdgeX>;\n * transform: translateX(-100%)` (TableHeaderRow's column menu, whose right\n * edge lines up with the header cell's own right edge and grows leftward)\n * — clamps the box's actual left edge and returns an adjusted `rightEdgeX`\n * for that same `left` + `transform: translateX(-100%)` pairing.\n */\nexport function useAutoAdjustedRightLeft(menuRef, isOpen, rawRightEdgeLeft) {\n const [rightLeft, setRightLeft] = useState(null);\n\n useLayoutEffect(() => {\n setRightLeft(rawRightEdgeLeft ?? null);\n }, [rawRightEdgeLeft]);\n\n useLayoutEffect(() => {\n if (!isOpen || !menuRef.current || rightLeft == null) return;\n const rect = menuRef.current.getBoundingClientRect();\n const clampedEdge = clampLeftToViewport(rightLeft - rect.width, rect.width);\n const nextRightLeft = clampedEdge + rect.width;\n if (nextRightLeft !== rightLeft) setRightLeft(nextRightLeft);\n }, [isOpen, menuRef, rightLeft]);\n\n return rightLeft;\n}\n"],"names":["FOCUSABLE_SELECTOR","Modal","isOpen","onClose","title","size","variant","children","panelRef","useRef","previouslyFocusedRef","useEffect","handleKeyDown","event","panel","_a","_c","_b","isSheet","jsx","jsxs","MARGIN","clampLeftToViewport","left","width","maxLeft","clampTopToViewport","top","height","maxTop","convertBlockType","store","blockId","type","props","runIds","registry","block","index","targetUsesTitleRunIds","sourceUsesTitleRunIds","sourceHasChildren","targetCanHoldChildren","ops","childId","i","moveBlock","changeBlockType","updateBlockProps","setBlockContentIds","keepChildren","useHorizontalAutoAdjustedLeft","menuRef","rawLeft","setLeft","useState","useLayoutEffect","rect","clamped","useAutoAdjustedCenteredLeft","rawCenterLeft","centerLeft","setCenterLeft","half","nextCenter","useAutoAdjustedRightLeft","rawRightEdgeLeft","rightLeft","setRightLeft","nextRightLeft"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./shared/index-B7_F6NA9.cjs"),i=require("./shared/starter-kit-Ch2LEpzF.cjs");exports.defineBlock=e.defineBlock;exports.defineExtension=e.defineExtension;exports.defineInline=e.defineInline;exports.registerExtensions=e.registerExtensions;exports.starterKit=i.starterKit;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./shared/index-vWtS1iyt.cjs"),i=require("./shared/starter-kit-BQUaaql0.cjs");exports.defineBlock=e.defineBlock;exports.defineExtension=e.defineExtension;exports.defineInline=e.defineInline;exports.registerExtensions=e.registerExtensions;exports.starterKit=i.starterKit;
2
2
  //# sourceMappingURL=starter-kit.cjs.map
@@ -1,5 +1,5 @@
1
- import { b as n, d as a, e as i, a as r } from "./shared/index-DOIEccLM.js";
2
- import { am as o } from "./shared/starter-kit-CJzWMyF8.js";
1
+ import { b as n, d as a, e as i, a as r } from "./shared/index-DUigqWQn.js";
2
+ import { am as o } from "./shared/starter-kit-Bp30PiE4.js";
3
3
  export {
4
4
  n as defineBlock,
5
5
  a as defineExtension,
package/dist/style.css CHANGED
@@ -427,6 +427,7 @@
427
427
  }
428
428
 
429
429
  .be-code-block-pre {
430
+ position: relative;
430
431
  margin: 0;
431
432
  padding: 0.9em 1em;
432
433
  overflow-x: auto;
@@ -440,6 +441,46 @@
440
441
  display: block;
441
442
  }
442
443
 
444
+ /* Syntax-highlight overlay (EditorProvider's `highlightCode` prop, see
445
+ useHighlightCode's doc comment) -- a read-only, aria-hidden <code> painted
446
+ directly behind the real editable one, which be-code-block-highlighted
447
+ below makes text-transparent (caret still visible) so only this overlay's
448
+ colors actually show. Matches the editable layer's own box exactly:
449
+ absolutely positioned to be-code-block-pre's padding edges (not inset: 0,
450
+ which would land on the *border* edge and double the padding), same font
451
+ inherited from be-code-block-pre.
452
+
453
+ white-space: pre (NOT pre-wrap) is deliberate and load-bearing, matching
454
+ be-code-block-pre's own overflow-x: auto -- long lines scroll instead of
455
+ wrapping, same as the real editable text underneath, which inherits
456
+ plain `white-space: pre` from the <pre> element's UA-default styling
457
+ (nothing here ever set pre-wrap on it). Wrapping the overlay while the
458
+ real text doesn't wrap desyncs the two layers' line breaks the moment a
459
+ line is long enough to wrap -- the overlay's *visible* colored text
460
+ reflows onto a new line while the real (invisible) text, and therefore
461
+ the browser's actual caret, stays on the original unwrapped line,
462
+ landing the caret nowhere near where it visually appears to be. Left
463
+ unset (no clip/overflow:hidden) so the overflowing text is still
464
+ painted -- .be-code-block-pre's own overflow-x: auto is what makes both
465
+ layers scroll together (see the containing-block note below); pre-wrap
466
+ must never be reintroduced here without also adding it to the real
467
+ editable layer's own CSS. */
468
+ .be-code-block-highlight {
469
+ position: absolute;
470
+ top: 0.9em;
471
+ left: 1em;
472
+ bottom: 0.9em;
473
+ display: block;
474
+ margin: 0;
475
+ pointer-events: none;
476
+ white-space: pre;
477
+ }
478
+
479
+ .be-code-block-highlighted code[data-placeholder] .be-editable {
480
+ color: transparent;
481
+ caret-color: var(--noteloom-code-text);
482
+ }
483
+
443
484
  .be-code-block-body {
444
485
  display: flex;
445
486
  align-items: stretch;
package/dist/versions.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./shared/VersionHistory-BRBYQgj5.cjs"),o=require("./shared/indexedDbPersistence-BWJ1h5Vp.cjs");exports.VersionHistory=e.VersionHistory;exports.createAutoVersionHistory=e.createAutoVersionHistory;exports.diffDocumentsHTML=e.diffDocumentsHTML;exports.useDocumentVersions=e.useDocumentVersions;exports.deleteDocumentVersion=o.deleteDocumentVersion;exports.listDocumentVersions=o.listDocumentVersions;exports.loadDocumentVersion=o.loadDocumentVersion;exports.saveDocumentVersion=o.saveDocumentVersion;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./shared/VersionHistory-BsSwOq_k.cjs"),o=require("./shared/indexedDbPersistence-BWJ1h5Vp.cjs");exports.VersionHistory=e.VersionHistory;exports.createAutoVersionHistory=e.createAutoVersionHistory;exports.diffDocumentsHTML=e.diffDocumentsHTML;exports.useDocumentVersions=e.useDocumentVersions;exports.deleteDocumentVersion=o.deleteDocumentVersion;exports.listDocumentVersions=o.listDocumentVersions;exports.loadDocumentVersion=o.loadDocumentVersion;exports.saveDocumentVersion=o.saveDocumentVersion;
2
2
  //# sourceMappingURL=versions.cjs.map
package/dist/versions.js CHANGED
@@ -1,4 +1,4 @@
1
- import { V as o, c as r, d as t, u as n } from "./shared/VersionHistory-D9sIIAYN.js";
1
+ import { V as o, c as r, d as t, u as n } from "./shared/VersionHistory-BzMnJpbc.js";
2
2
  import { b as i, c, e as u, f as m } from "./shared/indexedDbPersistence-BKlGPFTP.js";
3
3
  export {
4
4
  o as VersionHistory,
package/dist/voice.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./shared/VoiceListeningIndicator-Dw0fggpE.cjs");exports.VoiceListeningIndicator=i.VoiceListeningIndicator;exports.VoicePermissionModal=i.VoicePermissionModal;exports.listVoiceCommands=i.listVoiceCommands;exports.useVoiceTyping=i.useVoiceTyping;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./shared/VoiceListeningIndicator-B_7-6Mq4.cjs");exports.VoiceListeningIndicator=i.VoiceListeningIndicator;exports.VoicePermissionModal=i.VoicePermissionModal;exports.listVoiceCommands=i.listVoiceCommands;exports.useVoiceTyping=i.useVoiceTyping;
2
2
  //# sourceMappingURL=voice.cjs.map
package/dist/voice.js CHANGED
@@ -1,4 +1,4 @@
1
- import { V as s, a, l as e, u as n } from "./shared/VoiceListeningIndicator-DgLMmGSP.js";
1
+ import { V as s, a, l as e, u as n } from "./shared/VoiceListeningIndicator-DeA3hb33.js";
2
2
  export {
3
3
  s as VoiceListeningIndicator,
4
4
  a as VoicePermissionModal,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "noteloom",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Zero-runtime-dependency, React-first block/rich-text editor — nestable content blocks, inline widgets, slash commands, undo/redo, clipboard, real-time collaborative editing (a custom CRDT over WebRTC), offline-first persistence (IndexedDB + PWA-ready), and live presence, with an optional default theme (noteloom/style.css).",
5
5
  "keywords": [
6
6
  "react",