import { importShared } from "./__federation_fn_import-hlt2XzeI.js"; import { aa as a, ab as f$1, ac as ySyncPluginKey, ad as getRelativeSelection, ae as b, af as f$2, ag as isShadowRoot, ah as isHTMLElement$1, ai as useFloating$1, aj as isElement, ak as getOverflowAncestors, al as isWebKit, am as isLastTraversableNode, an as getParentNode, ao as getComputedStyle$1, ap as getNodeName, aq as $e$1, ar as offset, as as shift, at as flip, au as To$1, av as m, aw as Ao$1, ax as D, ay as b$1, az as Yo, aA as L$1, aB as S$1, aC as Bo$1, aD as autoUpdate, aE as No$1, aF as Vn, aG as _o$1, aH as H$1, aI as fo$1, aJ as Ro$1, aK as Vo$1, aL as No$2, aM as autoPlacement, aN as size, aO as Bt$2, aP as Ao$2, aQ as zo$1, aR as A$1, aS as D$1, aT as Oe$1, aU as Lo$1, aV as R$1, aW as h, aX as $n, aY as Cn, $ as __vitePreload, e as useCallbackRef, f as useLayoutEffect2, P as Primitive, d as createContextScope, aZ as Anchor, u as useComposedRefs, c as composeEventHandlers, b as Presence, a_ as Root2$2, n as useId$1, a as useDirection, a$ as createPopperScope, b0 as createRovingFocusGroupScope, b1 as Item, b2 as createCollection, R as ReactRemoveScroll, l as useFocusGuards, F as FocusScope, D as DismissableLayer, b3 as Root$1, b4 as Content, b5 as dispatchDiscreteCustomEvent, j as hideOthers, k as createSlot, b6 as Arrow, m as useControllableState, b7 as Root$2, b8 as createSlottable, T as Trigger$3, L as List, H as Content$1, a6 as Root2$3, a5 as SelectValue, J as SelectTrigger, K as SelectIcon, X as SelectItem, Y as SelectItemIndicator, Z as SelectItemText, Q as SelectContent, U as SelectViewport, a3 as Select, I as Root$3, S as Slot$2, b9 as At$2, a0 as twMerge, a1 as clsx, a2 as cva, M as SelectScrollUpButton, N as SelectScrollDownButton, a9 as defaultSchema, } from "./index-BSkdT-DR.js"; import { j as jsxRuntimeExports } from "./jsx-runtime-CvJTHeKY.js"; import { a as PluginKey, P as Plugin, D as DecorationSet, A as Decoration, R as Mark, m as mergeAttributes, Y as posToDOMRect } from "./index-Bs--Ol2m.js"; import { w as withSelectorExports } from "./with-selector-B2V6shWK.js"; import { r as requireReactDom } from "./index-eoEhLOdg.js"; var x = Object.defineProperty; var Y = (r, d, e) => (d in r ? x(r, d, { enumerable: true, configurable: true, writable: true, value: e }) : (r[d] = e)); var c = (r, d, e) => Y(r, typeof d != "symbol" ? d + "" : d, e); const M$2 = Mark.create({ name: "comment", excludes: "", inclusive: false, keepOnSplit: true, addAttributes() { return { // orphans are marks that currently don't have an active thread. It could be // that users have resolved the thread. Resolved threads by default are not shown in the document, // but we need to keep the mark (positioning) data so we can still "revive" it when the thread is unresolved // or we enter a "comments" view that includes resolved threads. orphan: { parseHTML: (r) => !!r.getAttribute("data-orphan"), renderHTML: (r) => r.orphan ? { "data-orphan": "true", } : {}, default: false, }, threadId: { parseHTML: (r) => r.getAttribute("data-bn-thread-id"), renderHTML: (r) => ({ "data-bn-thread-id": r.threadId, }), default: "", }, }; }, renderHTML({ HTMLAttributes: r }) { return [ "span", mergeAttributes(r, { class: "bn-thread-mark", }), ]; }, parseHTML() { return [{ tag: "span.bn-thread-mark" }]; }, extendMarkSchema(r) { return r.name === "comment" ? { blocknoteIgnore: true, } : {}; }, }); let F$2 = class F extends f$2 { constructor(e) { super(); c(this, "userCache", /* @__PURE__ */ new Map()); // avoid duplicate loads c(this, "loadingUsers", /* @__PURE__ */ new Set()); this.resolveUsers = e; } /** * Load information about users based on an array of user ids. */ async loadUsers(e) { const t = e.filter((a) => !this.userCache.has(a) && !this.loadingUsers.has(a)); if (t.length !== 0) { for (const a of t) this.loadingUsers.add(a); try { const a = await this.resolveUsers(t); for (const s of a) this.userCache.set(s.id, s); this.emit("update", this.userCache); } finally { for (const a of t) this.loadingUsers.delete(a); } } } /** * Retrieve information about a user based on their id, if cached. * * The user will have to be loaded via `loadUsers` first */ getUser(e) { return this.userCache.get(e); } /** * Subscribe to changes in the user store. * * @param cb - The callback to call when the user store changes. * @returns A function to unsubscribe from the user store. */ subscribe(e) { return this.on("update", e); } }; const w$1 = new PluginKey("blocknote-comments"); function K(r, d) { const e = /* @__PURE__ */ new Map(); return ( r.descendants((t, a) => { t.marks.forEach((s) => { if (s.type.name === d) { const o = s.attrs.threadId; if (!o) return; const m = a, n = m + t.nodeSize, i = e.get(o) ?? { from: 1 / 0, to: 0, }; e.set(o, { from: Math.min(m, i.from), to: Math.max(n, i.to), }); } }); }), e ); } const ne$1 = a(({ editor: r, options: { schema: d, threadStore: e, resolveUsers: t } }) => { if (!t) throw new Error("resolveUsers is required to be defined when using comments"); if (!e) throw new Error("threadStore is required to be defined when using comments"); const a = M$2.name, s = new F$2(t), o = f$1( { pendingComment: false, selectedThreadId: void 0, threadPositions: /* @__PURE__ */ new Map(), }, { onUpdate() { o.state.selectedThreadId !== o.prevState.selectedThreadId && r.transact((n) => n.setMeta(w$1, true)); }, }, ), m = (n) => { r.transact((i) => { i.doc.descendants((u, l) => { u.marks.forEach((h) => { if (h.type.name === a) { const T = h.type, f = h.attrs.threadId, A = n.get(f), v = !!(!A || A.resolved || A.deletedAt); if (v !== h.attrs.orphan) { const E = Math.max(l, 0), b = Math.min(l + u.nodeSize, i.doc.content.size - 1, i.doc.content.size - 1); (i.removeMark(E, b, h), i.addMark( E, b, T.create({ ...h.attrs, orphan: v, }), ), v && o.state.selectedThreadId === f && o.setState((P) => ({ ...P, selectedThreadId: void 0, }))); } } }); }); }); }; return { key: "comments", store: o, prosemirrorPlugins: [ new Plugin({ key: w$1, state: { init() { return { decorations: DecorationSet.empty, }; }, apply(n, i) { const u = n.getMeta(w$1); if (!n.docChanged && !u) return i; const l = n.docChanged ? K(n.doc, a) : o.state.threadPositions; (l.size > 0 || o.state.threadPositions.size > 0) && o.setState((T) => ({ ...T, threadPositions: l, })); const h = []; if (o.state.selectedThreadId) { const T = l.get(o.state.selectedThreadId); T && h.push( Decoration.inline(T.from, T.to, { class: "bn-thread-mark-selected", }), ); } return { decorations: DecorationSet.create(n.doc, h), }; }, }, props: { decorations(n) { var i; return ((i = w$1.getState(n)) == null ? void 0 : i.decorations) ?? DecorationSet.empty; }, handleClick: (n, i, u) => { if (u.button !== 0) return; const l = n.state.doc.nodeAt(i); if (!l) { o.setState((f) => ({ ...f, selectedThreadId: void 0, })); return; } const h = l.marks.find((f) => f.type.name === a && f.attrs.orphan !== true), T = h == null ? void 0 : h.attrs.threadId; T !== o.state.selectedThreadId && o.setState((f) => ({ ...f, selectedThreadId: T, })); }, }, }), ], threadStore: e, mount() { const n = e.subscribe(m); m(e.getThreads()); const i = r.onSelectionChange(() => { o.state.pendingComment && o.setState((u) => ({ ...u, pendingComment: false, })); }); return () => { (n(), i()); }; }, selectThread(n, i = true) { var u, l; if ( o.state.selectedThreadId !== n && (o.setState((h) => ({ ...h, pendingComment: false, selectedThreadId: n, })), n && i) ) { const h = o.state.threadPositions.get(n); if (!h) return; (l = (u = r.prosemirrorView) == null ? void 0 : u.domAtPos(h.from).node) == null || l.scrollIntoView({ behavior: "smooth", block: "center", }); } }, startPendingComment() { var n; (o.setState((i) => ({ ...i, selectedThreadId: void 0, pendingComment: true, })), (n = r.getExtension(b)) == null || n.showSelection(true, "comments")); }, stopPendingComment() { var n; (o.setState((i) => ({ ...i, selectedThreadId: void 0, pendingComment: false, })), (n = r.getExtension(b)) == null || n.showSelection(false, "comments")); }, async createThread(n) { const i = await e.createThread(n); if (e.addThreadToDocument) { const u = r.prosemirrorView, l = u.state.selection, h = ySyncPluginKey.getState(u.state), T = { prosemirror: { head: l.head, anchor: l.anchor, }, yjs: h ? getRelativeSelection(h.binding, u.state) : void 0, }; await e.addThreadToDocument({ threadId: i.id, selection: T, }); } else r._tiptapEditor.commands.setMark(a, { orphan: false, threadId: i.id, }); }, userStore: s, commentEditorSchema: d, tiptapExtensions: [M$2], }; }); /*! * tabbable 6.5.0 * @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE */ // NOTE: separate `:not()` selectors has broader browser support than the newer // `:not([inert], [inert] *)` (Feb 2023) var candidateSelectors = [ "input:not([inert]):not([inert] *)", "select:not([inert]):not([inert] *)", "textarea:not([inert]):not([inert] *)", "a[href]:not([inert]):not([inert] *)", "area[href]:not([inert]):not([inert] *)", "button:not([inert]):not([inert] *)", "[tabindex]:not(slot):not([inert]):not([inert] *)", "audio[controls]:not([inert]):not([inert] *)", "video[controls]:not([inert]):not([inert] *)", '[contenteditable]:not([contenteditable="false"]):not([inert]):not([inert] *)', "details>summary:first-of-type:not([inert]):not([inert] *)", "details:not([inert]):not([inert] *)", ]; var candidateSelector = /* #__PURE__ */ candidateSelectors.join(","); var NoElement = typeof Element === "undefined"; var matches = NoElement ? function () {} : Element.prototype.matches || Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; var getRootNode = !NoElement && Element.prototype.getRootNode ? function (element) { var _element$getRootNode; return ( element === null || element === void 0 ? void 0 : (_element$getRootNode = element.getRootNode) === null || _element$getRootNode === void 0 ? void 0 : _element$getRootNode.call(element) ); } : function (element) { return element === null || element === void 0 ? void 0 : element.ownerDocument; }; /** * Determines if a node is inert or in an inert ancestor. * @param {Node} [node] * @param {boolean} [lookUp] If true and `node` is not inert, looks up at ancestors to * see if any of them are inert. If false, only `node` itself is considered. * @returns {boolean} True if inert itself or by way of being in an inert ancestor. * False if `node` is falsy. */ var _isInert = function isInert(node, lookUp) { var _node$getAttribute; if (lookUp === void 0) { lookUp = true; } // CAREFUL: JSDom does not support inert at all, so we can't use the `HTMLElement.inert` // JS API property; we have to check the attribute, which can either be empty or 'true'; // if it's `null` (not specified) or 'false', it's an active element var inertAtt = node === null || node === void 0 ? void 0 : (_node$getAttribute = node.getAttribute) === null || _node$getAttribute === void 0 ? void 0 : _node$getAttribute.call(node, "inert"); var inert = inertAtt === "" || inertAtt === "true"; // NOTE: this could also be handled with `node.matches('[inert], :is([inert] *)')` // if it weren't for `matches()` not being a function on shadow roots; the following // code works for any kind of node var result = inert || (lookUp && node && // closest does not exist on shadow roots, so we fall back to a manual // lookup upward, in case it is not defined. (typeof node.closest === "function" ? node.closest("[inert]") : _isInert(node.parentNode))); return result; }; /** * Determines if a node's content is editable. * @param {Element} [node] * @returns True if it's content-editable; false if it's not or `node` is falsy. */ var isContentEditable = function isContentEditable(node) { var _node$getAttribute2; // CAREFUL: JSDom does not support the `HTMLElement.isContentEditable` API so we have // to use the attribute directly to check for this, which can either be empty or 'true'; // if it's `null` (not specified) or 'false', it's a non-editable element var attValue = node === null || node === void 0 ? void 0 : (_node$getAttribute2 = node.getAttribute) === null || _node$getAttribute2 === void 0 ? void 0 : _node$getAttribute2.call(node, "contenteditable"); return attValue === "" || attValue === "true"; }; /** * @param {Element} el container to check in * @param {boolean} includeContainer add container to check * @param {(node: Element) => boolean} filter filter candidates * @returns {Element[]} */ var getCandidates = function getCandidates(el, includeContainer, filter) { // even if `includeContainer=false`, we still have to check it for inertness because // if it's inert (either by itself or via its parent), then all its children are inert if (_isInert(el)) { return []; } var candidates = Array.prototype.slice.apply(el.querySelectorAll(candidateSelector)); if (includeContainer && matches.call(el, candidateSelector)) { candidates.unshift(el); } candidates = candidates.filter(filter); return candidates; }; /** * @callback GetShadowRoot * @param {Element} element to check for shadow root * @returns {ShadowRoot|boolean} ShadowRoot if available or boolean indicating if a shadowRoot is attached but not available. */ /** * @callback ShadowRootFilter * @param {Element} shadowHostNode the element which contains shadow content * @returns {boolean} true if a shadow root could potentially contain valid candidates. */ /** * @typedef {Object} CandidateScope * @property {Element} scopeParent contains inner candidates * @property {Element[]} candidates list of candidates found in the scope parent */ /** * @typedef {Object} IterativeOptions * @property {GetShadowRoot|boolean} getShadowRoot true if shadow support is enabled; falsy if not; * if a function, implies shadow support is enabled and either returns the shadow root of an element * or a boolean stating if it has an undisclosed shadow root * @property {(node: Element) => boolean} filter filter candidates * @property {boolean} flatten if true then result will flatten any CandidateScope into the returned list * @property {ShadowRootFilter} shadowRootFilter filter shadow roots; */ /** * @param {Element[]} elements list of element containers to match candidates from * @param {boolean} includeContainer add container list to check * @param {IterativeOptions} options * @returns {Array.} */ var _getCandidatesIteratively = function getCandidatesIteratively(elements, includeContainer, options) { var candidates = []; var elementsToCheck = Array.from(elements); while (elementsToCheck.length) { var element = elementsToCheck.shift(); if (_isInert(element, false)) { // no need to look up since we're drilling down // anything inside this container will also be inert continue; } if (element.tagName === "SLOT") { // add shadow dom slot scope (slot itself cannot be focusable) var assigned = element.assignedElements(); var content = assigned.length ? assigned : element.children; var nestedCandidates = _getCandidatesIteratively(content, true, options); if (options.flatten) { candidates.push.apply(candidates, nestedCandidates); } else { candidates.push({ scopeParent: element, candidates: nestedCandidates, }); } } else { // check candidate element var validCandidate = matches.call(element, candidateSelector); if (validCandidate && options.filter(element) && (includeContainer || !elements.includes(element))) { candidates.push(element); } // iterate over shadow content if possible var shadowRoot = element.shadowRoot || // check for an undisclosed shadow (typeof options.getShadowRoot === "function" && options.getShadowRoot(element)); // no inert look up because we're already drilling down and checking for inertness // on the way down, so all containers to this root node should have already been // vetted as non-inert var validShadowRoot = !_isInert(shadowRoot, false) && (!options.shadowRootFilter || options.shadowRootFilter(element)); if (shadowRoot && validShadowRoot) { // add shadow dom scope IIF a shadow root node was given; otherwise, an undisclosed // shadow exists, so look at light dom children as fallback BUT create a scope for any // child candidates found because they're likely slotted elements (elements that are // children of the web component element (which has the shadow), in the light dom, but // slotted somewhere _inside_ the undisclosed shadow) -- the scope is created below, // _after_ we return from this recursive call var _nestedCandidates = _getCandidatesIteratively(shadowRoot === true ? element.children : shadowRoot.children, true, options); if (options.flatten) { candidates.push.apply(candidates, _nestedCandidates); } else { candidates.push({ scopeParent: element, candidates: _nestedCandidates, }); } } else { // there's not shadow so just dig into the element's (light dom) children // __without__ giving the element special scope treatment elementsToCheck.unshift.apply(elementsToCheck, element.children); } } } return candidates; }; /** * @private * Determines if the node has an explicitly specified `tabindex` attribute. * @param {HTMLElement} node * @returns {boolean} True if so; false if not. */ var hasTabIndex = function hasTabIndex(node) { return !isNaN(parseInt(node.getAttribute("tabindex"), 10)); }; /** * Determine the tab index of a given node. * @param {HTMLElement} node * @returns {number} Tab order (negative, 0, or positive number). * @throws {Error} If `node` is falsy. */ var getTabIndex = function getTabIndex(node) { if (!node) { throw new Error("No node provided"); } if (node.tabIndex < 0) { // in Chrome,
,