@relevaince/mentions 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,6 +13,7 @@ This is **not** a simple `@mention` dropdown. It is a resource-addressing langua
13
13
  - **Async providers** — fetch suggestions from any API
14
14
  - **Debounced fetching** — per-provider `debounceMs` prevents API floods
15
15
  - **Structured output** — returns `{ markdown, tokens, plainText }` on every change
16
+ - **`useMentionsContent`** — hook that pairs `onChange` with reactive `output` and `hasContent` (e.g. disable submit until there is text)
16
17
  - **Markdown serialization** — `@[label](id)` token syntax for storage and LLM context
17
18
  - **Markdown parsing** — `extractFromMarkdown()` returns tokens + plain text from a markdown string
18
19
  - **Headless styling** — zero bundled CSS, style via `data-*` attributes with Tailwind or plain CSS
@@ -235,6 +236,55 @@ function Chat() {
235
236
  | `focus` | `() => void` | Focuses the editor and places the cursor at the end |
236
237
  | `getOutput` | `() => MentionsOutput \| null` | Reads the current structured output without waiting for onChange |
237
238
 
239
+ ## Hooks
240
+
241
+ ### `useMentionsContent`
242
+
243
+ Keeps the latest `MentionsOutput` in React state so UI can react to editor content. `ref.current.getOutput()` does not trigger re-renders; this hook wires `onChange` for you and exposes `hasContent` from trimmed `plainText`.
244
+
245
+ ```ts
246
+ function useMentionsContent(): {
247
+ output: MentionsOutput | null;
248
+ onChange: (output: MentionsOutput) => void;
249
+ hasContent: boolean;
250
+ };
251
+ ```
252
+
253
+ **Submit button disabled when empty:**
254
+
255
+ ```tsx
256
+ import { useRef } from "react";
257
+ import {
258
+ MentionsInput,
259
+ useMentionsContent,
260
+ type MentionsInputHandle,
261
+ } from "@relevaince/mentions";
262
+
263
+ function Composer() {
264
+ const textareaRef = useRef<MentionsInputHandle>(null);
265
+ const { output, onChange, hasContent } = useMentionsContent();
266
+
267
+ function onSubmit() {
268
+ if (!output) return;
269
+ sendMessage(output);
270
+ }
271
+
272
+ return (
273
+ <>
274
+ <MentionsInput
275
+ ref={textareaRef}
276
+ providers={providers}
277
+ onChange={onChange}
278
+ onSubmit={onSubmit}
279
+ />
280
+ <button type="button" disabled={!hasContent} onClick={onSubmit}>
281
+ Send
282
+ </button>
283
+ </>
284
+ );
285
+ }
286
+ ```
287
+
238
288
  ## Streaming
239
289
 
240
290
  Stream AI-generated text into the editor while maintaining mention state. Set `streaming={true}` to enter streaming mode: the suggestion dropdown is suppressed, user keyboard/paste input is blocked, and `onChange` is throttled (~150 ms). Call `ref.current.setContent(accumulated)` on each chunk — completed mention tokens are parsed into chips automatically.
package/dist/index.d.mts CHANGED
@@ -197,6 +197,12 @@ type MentionsInputHandle = {
197
197
  */
198
198
  declare const MentionsInput: React.ForwardRefExoticComponent<MentionsInputProps & React.RefAttributes<MentionsInputHandle>>;
199
199
 
200
+ declare function useMentionsContent(): {
201
+ output: MentionsOutput | null;
202
+ onChange: (o: MentionsOutput) => void;
203
+ hasContent: boolean;
204
+ };
205
+
200
206
  /**
201
207
  * Serialize a Tiptap JSON document to a markdown string.
202
208
  *
@@ -230,4 +236,4 @@ declare function extractFromMarkdown(markdown: string): {
230
236
  plainText: string;
231
237
  };
232
238
 
233
- export { type MentionItem, type MentionProvider, type MentionToken, MentionsInput, type MentionsInputHandle, type MentionsInputProps, type MentionsOutput, extractFromMarkdown, parseFromMarkdown, serializeToMarkdown };
239
+ export { type MentionItem, type MentionProvider, type MentionToken, MentionsInput, type MentionsInputHandle, type MentionsInputProps, type MentionsOutput, extractFromMarkdown, parseFromMarkdown, serializeToMarkdown, useMentionsContent };
package/dist/index.d.ts CHANGED
@@ -197,6 +197,12 @@ type MentionsInputHandle = {
197
197
  */
198
198
  declare const MentionsInput: React.ForwardRefExoticComponent<MentionsInputProps & React.RefAttributes<MentionsInputHandle>>;
199
199
 
200
+ declare function useMentionsContent(): {
201
+ output: MentionsOutput | null;
202
+ onChange: (o: MentionsOutput) => void;
203
+ hasContent: boolean;
204
+ };
205
+
200
206
  /**
201
207
  * Serialize a Tiptap JSON document to a markdown string.
202
208
  *
@@ -230,4 +236,4 @@ declare function extractFromMarkdown(markdown: string): {
230
236
  plainText: string;
231
237
  };
232
238
 
233
- export { type MentionItem, type MentionProvider, type MentionToken, MentionsInput, type MentionsInputHandle, type MentionsInputProps, type MentionsOutput, extractFromMarkdown, parseFromMarkdown, serializeToMarkdown };
239
+ export { type MentionItem, type MentionProvider, type MentionToken, MentionsInput, type MentionsInputHandle, type MentionsInputProps, type MentionsOutput, extractFromMarkdown, parseFromMarkdown, serializeToMarkdown, useMentionsContent };
package/dist/index.js CHANGED
@@ -33,7 +33,8 @@ __export(index_exports, {
33
33
  MentionsInput: () => MentionsInput,
34
34
  extractFromMarkdown: () => extractFromMarkdown,
35
35
  parseFromMarkdown: () => parseFromMarkdown,
36
- serializeToMarkdown: () => serializeToMarkdown
36
+ serializeToMarkdown: () => serializeToMarkdown,
37
+ useMentionsContent: () => useMentionsContent
37
38
  });
38
39
  module.exports = __toCommonJS(index_exports);
39
40
 
@@ -1621,11 +1622,24 @@ var MentionsInput = (0, import_react5.forwardRef)(
1621
1622
  );
1622
1623
  }
1623
1624
  );
1625
+
1626
+ // src/hooks/useMentionsContent.ts
1627
+ var import_react7 = require("react");
1628
+ function useMentionsContent() {
1629
+ const [output, setOutput] = (0, import_react7.useState)(null);
1630
+ const onChange = (0, import_react7.useCallback)((o) => setOutput(o), []);
1631
+ return {
1632
+ output,
1633
+ onChange,
1634
+ hasContent: (output?.plainText ?? "").trim().length > 0
1635
+ };
1636
+ }
1624
1637
  // Annotate the CommonJS export names for ESM import in node:
1625
1638
  0 && (module.exports = {
1626
1639
  MentionsInput,
1627
1640
  extractFromMarkdown,
1628
1641
  parseFromMarkdown,
1629
- serializeToMarkdown
1642
+ serializeToMarkdown,
1643
+ useMentionsContent
1630
1644
  });
1631
1645
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/MentionsInput.tsx","../src/hooks/useMentionsEditor.ts","../src/core/mentionExtension.ts","../src/core/suggestionPlugin.ts","../src/core/markdownSerializer.ts","../src/core/markdownParser.ts","../src/hooks/useSuggestion.ts","../src/utils/debounce.ts","../src/components/SuggestionList.tsx","../src/utils/ariaHelpers.ts"],"sourcesContent":["/* ------------------------------------------------------------------ */\n/* Components */\n/* ------------------------------------------------------------------ */\nexport { MentionsInput } from \"./components/MentionsInput\";\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\nexport type { MentionToken } from \"./types/MentionToken\";\nexport type {\n MentionProvider,\n MentionItem,\n} from \"./types/MentionProvider\";\nexport type { MentionsOutput } from \"./types/MentionsOutput\";\nexport type {\n MentionsInputProps,\n MentionsInputHandle,\n} from \"./types/MentionsInputProps\";\n\n/* ------------------------------------------------------------------ */\n/* Utilities */\n/* ------------------------------------------------------------------ */\nexport { serializeToMarkdown } from \"./core/markdownSerializer\";\nexport { parseFromMarkdown, extractFromMarkdown } from \"./core/markdownParser\";\n","import React, { forwardRef, useCallback, useId, useImperativeHandle } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { EditorContent } from \"@tiptap/react\";\nimport { useMentionsEditor } from \"../hooks/useMentionsEditor\";\nimport { useSuggestion } from \"../hooks/useSuggestion\";\nimport { SuggestionList } from \"./SuggestionList\";\nimport { comboboxAttrs } from \"../utils/ariaHelpers\";\nimport type {\n MentionsInputProps,\n MentionsInputHandle,\n} from \"../types/MentionsInputProps\";\n\n/**\n * `<MentionsInput>` — the single public component.\n *\n * A structured text editor with typed entity tokens.\n * Consumers register `providers` for each trigger character,\n * and receive structured output via `onChange` and `onSubmit`.\n */\nexport const MentionsInput = forwardRef<MentionsInputHandle, MentionsInputProps>(\n function MentionsInput(\n {\n value,\n providers,\n onChange,\n placeholder = \"Type a message...\",\n autoFocus = false,\n disabled = false,\n className,\n onSubmit,\n clearOnSubmit = true,\n maxLength,\n renderItem,\n renderChip,\n renderEmpty,\n renderLoading,\n renderGroupHeader,\n onFocus,\n onBlur,\n onMentionAdd,\n onMentionRemove,\n onMentionClick,\n onMentionHover,\n minHeight,\n maxHeight,\n submitKey = \"enter\",\n allowTrigger,\n validateMention,\n portalContainer,\n streaming,\n onStreamingComplete,\n },\n ref,\n ) {\n const instanceId = useId();\n const listboxId = `mentions-listbox-${instanceId}`;\n\n const { uiState, actions, callbacksRef } = useSuggestion(providers, {\n onMentionAdd,\n });\n\n const { editor, getOutput, clear, setContent, appendText, focus } = useMentionsEditor({\n providers,\n value,\n onChange,\n onSubmit,\n clearOnSubmit,\n placeholder,\n autoFocus,\n editable: !disabled,\n callbacksRef,\n onFocus,\n onBlur,\n submitKey,\n onMentionRemove,\n onMentionClick,\n onMentionHover,\n allowTrigger,\n validateMention,\n streaming,\n onStreamingComplete,\n });\n\n useImperativeHandle(\n ref,\n () => ({ clear, setContent, appendText, focus, getOutput }),\n [clear, setContent, appendText, focus, getOutput],\n );\n\n const isExpanded = uiState.state !== \"idle\";\n\n const handleHover = useCallback((index: number) => {\n void index;\n }, []);\n\n const handleFocusEditor = useCallback(() => {\n editor?.commands.focus();\n }, [editor]);\n\n const editorStyle: React.CSSProperties = {};\n if (minHeight != null) editorStyle.minHeight = `${minHeight}px`;\n if (maxHeight != null) {\n editorStyle.maxHeight = `${maxHeight}px`;\n editorStyle.overflowY = \"auto\";\n }\n\n const suggestionList = isExpanded ? (\n <SuggestionList\n items={uiState.items}\n activeIndex={uiState.activeIndex}\n breadcrumbs={uiState.breadcrumbs}\n loading={uiState.loading}\n trigger={uiState.trigger}\n query={uiState.query}\n clientRect={uiState.clientRect}\n onSelect={(item) => actions.select(item)}\n onHover={handleHover}\n onGoBack={actions.goBack}\n onSearchNested={actions.searchNested}\n onNavigateUp={actions.navigateUp}\n onNavigateDown={actions.navigateDown}\n onClose={actions.close}\n onFocusEditor={handleFocusEditor}\n renderItem={renderItem}\n renderEmpty={renderEmpty}\n renderLoading={renderLoading}\n renderGroupHeader={renderGroupHeader}\n listboxId={listboxId}\n />\n ) : null;\n\n return (\n <div\n className={className}\n data-mentions-input=\"\"\n data-disabled={disabled ? \"\" : undefined}\n {...comboboxAttrs(isExpanded, listboxId)}\n aria-activedescendant={\n isExpanded && uiState.items[uiState.activeIndex]\n ? `mention-option-${uiState.items[uiState.activeIndex].id}`\n : undefined\n }\n >\n <div style={editorStyle}>\n <EditorContent editor={editor} />\n </div>\n\n {portalContainer\n ? suggestionList && createPortal(suggestionList, portalContainer)\n : suggestionList}\n </div>\n );\n },\n);\n","import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { useEditor } from \"@tiptap/react\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\nimport { Extension } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport { MentionNode } from \"../core/mentionExtension\";\nimport { createSuggestionExtension } from \"../core/suggestionPlugin\";\nimport type { StreamingRef } from \"../core/suggestionPlugin\";\nimport {\n serializeToMarkdown,\n extractTokens,\n extractPlainText,\n} from \"../core/markdownSerializer\";\nimport { parseFromMarkdown } from \"../core/markdownParser\";\nimport type { MentionProvider } from \"../types/MentionProvider\";\nimport type { MentionToken } from \"../types/MentionToken\";\nimport type { MentionsOutput } from \"../types/MentionsOutput\";\nimport type { SuggestionCallbacksRef } from \"../core/suggestionPlugin\";\n\n/* ------------------------------------------------------------------ */\n/* Helper: build MentionsOutput from the current editor */\n/* ------------------------------------------------------------------ */\n\nfunction buildOutput(editor: { getJSON: () => any }): MentionsOutput {\n const json = editor.getJSON();\n return {\n markdown: serializeToMarkdown(json),\n tokens: extractTokens(json),\n plainText: extractPlainText(json),\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Collect all mention tokens from a doc JSON */\n/* ------------------------------------------------------------------ */\n\nfunction collectMentionTokens(doc: any): MentionToken[] {\n const tokens: MentionToken[] = [];\n function walk(node: any) {\n if (node.type === \"mention\" && node.attrs) {\n tokens.push({\n id: node.attrs.id,\n type: node.attrs.entityType ?? node.attrs.type,\n label: node.attrs.label,\n });\n }\n if (node.content) {\n for (const child of node.content) walk(child);\n }\n }\n walk(doc);\n return tokens;\n}\n\n/* ------------------------------------------------------------------ */\n/* Submit keyboard shortcut extension (Cmd/Ctrl+Enter) */\n/* ------------------------------------------------------------------ */\n\nfunction createSubmitExtension(\n onSubmitRef: React.RefObject<((output: MentionsOutput) => void) | undefined>,\n clearOnSubmitRef: React.RefObject<boolean>,\n submitKeyRef: React.RefObject<string>,\n) {\n return Extension.create({\n name: \"submitShortcut\",\n priority: 150,\n\n addKeyboardShortcuts() {\n return {\n \"Mod-Enter\": () => {\n const key = submitKeyRef.current;\n if (key === \"mod+enter\" || key === \"enter\") {\n if (onSubmitRef.current) {\n onSubmitRef.current(buildOutput(this.editor));\n if (clearOnSubmitRef.current) {\n this.editor.commands.clearContent(true);\n }\n }\n return true;\n }\n return false;\n },\n };\n },\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Enter key handling */\n/* ------------------------------------------------------------------ */\n\nconst enterSubmitPluginKey = new PluginKey(\"enterSubmit\");\n\nfunction createEnterExtension(\n onSubmitRef: React.RefObject<((output: MentionsOutput) => void) | undefined>,\n clearOnSubmitRef: React.RefObject<boolean>,\n submitKeyRef: React.RefObject<string>,\n) {\n return Extension.create({\n name: \"enterSubmit\",\n priority: 150,\n\n addProseMirrorPlugins() {\n const editor = this.editor;\n\n return [\n new Plugin({\n key: enterSubmitPluginKey,\n props: {\n handleKeyDown(_view, event) {\n if (event.key !== \"Enter\") return false;\n\n const key = submitKeyRef.current;\n\n if (key === \"none\") return false;\n\n if (key === \"mod+enter\") {\n // Enter = new line (default PM behavior handles it)\n // Shift+Enter also new line\n return false;\n }\n\n // key === \"enter\" (default)\n if (event.shiftKey) {\n editor.commands.splitBlock();\n return true;\n }\n\n if (event.metaKey || event.ctrlKey) return false;\n\n if (onSubmitRef.current) {\n onSubmitRef.current(buildOutput(editor));\n if (clearOnSubmitRef.current) {\n editor.commands.clearContent(true);\n }\n }\n return true;\n },\n },\n }),\n ];\n },\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Mention removal detection plugin */\n/* ------------------------------------------------------------------ */\n\nconst mentionRemovePluginKey = new PluginKey(\"mentionRemove\");\n\nfunction createMentionRemoveExtension(\n onMentionRemoveRef: React.RefObject<((token: MentionToken) => void) | undefined>,\n) {\n return Extension.create({\n name: \"mentionRemoveDetector\",\n priority: 100,\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: mentionRemovePluginKey,\n appendTransaction(transactions, oldState, newState) {\n if (!onMentionRemoveRef.current) return null;\n\n const oldMentions = collectMentionTokens(oldState.doc.toJSON());\n const newMentions = collectMentionTokens(newState.doc.toJSON());\n\n if (oldMentions.length <= newMentions.length) return null;\n\n const newIds = new Set(newMentions.map((m) => m.id));\n for (const m of oldMentions) {\n if (!newIds.has(m.id)) {\n onMentionRemoveRef.current(m);\n }\n }\n\n return null;\n },\n }),\n ];\n },\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Streaming input blocker plugin */\n/* ------------------------------------------------------------------ */\n\nconst streamingBlockPluginKey = new PluginKey(\"streamingBlock\");\n\nfunction createStreamingBlockExtension(streamingRef: StreamingRef) {\n return Extension.create({\n name: \"streamingBlock\",\n priority: 200,\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: streamingBlockPluginKey,\n props: {\n handleKeyDown() {\n return streamingRef.current;\n },\n handleKeyPress() {\n return streamingRef.current;\n },\n handlePaste() {\n return streamingRef.current;\n },\n handleDrop() {\n return streamingRef.current;\n },\n },\n }),\n ];\n },\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Hook */\n/* ------------------------------------------------------------------ */\n\ntype UseMentionsEditorOptions = {\n providers: MentionProvider[];\n value?: string;\n onChange?: (output: MentionsOutput) => void;\n onSubmit?: (output: MentionsOutput) => void;\n clearOnSubmit?: boolean;\n placeholder?: string;\n autoFocus?: boolean;\n editable?: boolean;\n callbacksRef: SuggestionCallbacksRef;\n onFocus?: () => void;\n onBlur?: () => void;\n submitKey?: string;\n onMentionRemove?: (token: MentionToken) => void;\n onMentionClick?: (token: MentionToken, event: MouseEvent) => void;\n onMentionHover?: (token: MentionToken) => ReactNode;\n allowTrigger?: (trigger: string, context: { textBefore: string }) => boolean;\n validateMention?: (token: MentionToken) => boolean | Promise<boolean>;\n streaming?: boolean;\n onStreamingComplete?: (output: MentionsOutput) => void;\n};\n\nexport function useMentionsEditor({\n providers,\n value,\n onChange,\n onSubmit,\n clearOnSubmit = true,\n placeholder,\n autoFocus = false,\n editable = true,\n callbacksRef,\n onFocus,\n onBlur,\n submitKey = \"enter\",\n onMentionRemove,\n onMentionClick,\n onMentionHover,\n allowTrigger,\n validateMention,\n streaming = false,\n onStreamingComplete,\n}: UseMentionsEditorOptions) {\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n const onSubmitRef = useRef(onSubmit);\n onSubmitRef.current = onSubmit;\n\n const clearOnSubmitRef = useRef(clearOnSubmit);\n clearOnSubmitRef.current = clearOnSubmit;\n\n const onFocusRef = useRef(onFocus);\n onFocusRef.current = onFocus;\n\n const onBlurRef = useRef(onBlur);\n onBlurRef.current = onBlur;\n\n const submitKeyRef = useRef(submitKey);\n submitKeyRef.current = submitKey;\n\n const onMentionRemoveRef = useRef(onMentionRemove);\n onMentionRemoveRef.current = onMentionRemove;\n\n const onMentionClickRef = useRef(onMentionClick);\n onMentionClickRef.current = onMentionClick;\n\n const onMentionHoverRef = useRef(onMentionHover);\n onMentionHoverRef.current = onMentionHover;\n\n const allowTriggerRef = useRef(allowTrigger);\n allowTriggerRef.current = allowTrigger;\n\n const validateMentionRef = useRef(validateMention);\n validateMentionRef.current = validateMention;\n\n const onStreamingCompleteRef = useRef(onStreamingComplete);\n onStreamingCompleteRef.current = onStreamingComplete;\n\n // Streaming state — mutable ref so ProseMirror plugins can read it\n // without re-creating the extension chain.\n const streamingRef = useRef<boolean>(streaming);\n streamingRef.current = streaming;\n const prevStreamingRef = useRef(streaming);\n\n // Throttle state for onChange during streaming\n const throttleTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingOutputRef = useRef<MentionsOutput | null>(null);\n\n // Track internal value to avoid controlled-value infinite loops\n const internalMarkdownRef = useRef<string | null>(null);\n\n const initialContent = useMemo(() => {\n if (!value) return undefined;\n return parseFromMarkdown(value);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const triggersKey = providers.map((p) => p.trigger).join(\",\");\n const triggers = useMemo(\n () => providers.map((p) => p.trigger),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [triggersKey],\n );\n\n const suggestionExtension = useMemo(\n () =>\n createSuggestionExtension(\n triggers,\n callbacksRef,\n allowTriggerRef,\n streamingRef,\n ),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [triggersKey],\n );\n\n const submitExt = useMemo(\n () => createSubmitExtension(onSubmitRef, clearOnSubmitRef, submitKeyRef),\n [],\n );\n const enterExt = useMemo(\n () => createEnterExtension(onSubmitRef, clearOnSubmitRef, submitKeyRef),\n [],\n );\n const mentionRemoveExt = useMemo(\n () => createMentionRemoveExtension(onMentionRemoveRef),\n [],\n );\n\n const streamingBlockExt = useMemo(\n () => createStreamingBlockExtension(streamingRef),\n [],\n );\n\n const mentionNodeExt = useMemo(\n () =>\n MentionNode.configure({\n onClickRef: onMentionClickRef,\n onHoverRef: onMentionHoverRef,\n }),\n [],\n );\n\n const editor = useEditor({\n extensions: [\n StarterKit.configure({\n heading: false,\n blockquote: false,\n codeBlock: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n horizontalRule: false,\n hardBreak: false,\n }),\n Placeholder.configure({\n placeholder: ({ editor }) =>\n editor.isEmpty ? (placeholder ?? \"Type a message...\") : \"\",\n showOnlyCurrent: true,\n }),\n mentionNodeExt,\n suggestionExtension,\n submitExt,\n enterExt,\n mentionRemoveExt,\n streamingBlockExt,\n ],\n content: initialContent,\n autofocus: autoFocus ? \"end\" : false,\n editable,\n editorProps: {\n attributes: {\n class: \"mentions-editor\",\n },\n },\n onUpdate: ({ editor }) => {\n const output = buildOutput(editor);\n internalMarkdownRef.current = output.markdown;\n\n if (streamingRef.current) {\n pendingOutputRef.current = output;\n if (!throttleTimerRef.current) {\n throttleTimerRef.current = setTimeout(() => {\n throttleTimerRef.current = null;\n if (pendingOutputRef.current) {\n onChangeRef.current?.(pendingOutputRef.current);\n pendingOutputRef.current = null;\n }\n }, 150);\n }\n } else {\n onChangeRef.current?.(output);\n }\n },\n onFocus: () => {\n onFocusRef.current?.();\n },\n onBlur: () => {\n onBlurRef.current?.();\n },\n });\n\n // Flush throttled onChange and fire onStreamingComplete when streaming ends\n useEffect(() => {\n if (prevStreamingRef.current && !streaming && editor) {\n if (throttleTimerRef.current) {\n clearTimeout(throttleTimerRef.current);\n throttleTimerRef.current = null;\n }\n const output = buildOutput(editor);\n onChangeRef.current?.(output);\n onStreamingCompleteRef.current?.(output);\n pendingOutputRef.current = null;\n }\n prevStreamingRef.current = streaming;\n }, [streaming, editor]);\n\n // Clean up throttle timer on unmount\n useEffect(() => {\n return () => {\n if (throttleTimerRef.current) {\n clearTimeout(throttleTimerRef.current);\n }\n };\n }, []);\n\n // Sync editable state\n useEffect(() => {\n if (editor && editor.isEditable !== editable) {\n editor.setEditable(editable);\n }\n }, [editor, editable]);\n\n // Controlled value: update editor when external value changes\n useEffect(() => {\n if (!editor || value === undefined) return;\n if (value === internalMarkdownRef.current) return;\n const doc = parseFromMarkdown(value);\n editor.commands.setContent(doc);\n internalMarkdownRef.current = value;\n }, [editor, value]);\n\n // Mention validation\n useEffect(() => {\n if (!editor || !validateMention) return;\n\n const runValidation = async () => {\n const doc = editor.getJSON();\n const tokens = collectMentionTokens(doc);\n const invalidIds = new Set<string>();\n\n await Promise.all(\n tokens.map(async (token) => {\n const valid = await validateMention(token);\n if (!valid) invalidIds.add(token.id);\n }),\n );\n\n editor.view.dom.querySelectorAll(\"[data-mention]\").forEach((el) => {\n const id = el.getAttribute(\"data-id\");\n if (id && invalidIds.has(id)) {\n el.setAttribute(\"data-mention-invalid\", \"\");\n } else {\n el.removeAttribute(\"data-mention-invalid\");\n }\n });\n };\n\n runValidation();\n }, [editor, validateMention]);\n\n /* ---------------------------------------------------------------- */\n /* Imperative methods */\n /* ---------------------------------------------------------------- */\n\n const clear = useCallback(() => {\n editor?.commands.clearContent(true);\n }, [editor]);\n\n const setContent = useCallback(\n (markdown: string) => {\n if (!editor) return;\n const doc = parseFromMarkdown(markdown);\n editor.commands.setContent(doc);\n internalMarkdownRef.current = markdown;\n if (streamingRef.current) {\n editor.commands.focus(\"end\");\n }\n },\n [editor],\n );\n\n const appendText = useCallback(\n (text: string) => {\n if (!editor) return;\n const endPos = editor.state.doc.content.size - 1;\n editor.commands.insertContentAt(endPos, text);\n if (streamingRef.current) {\n editor.commands.focus(\"end\");\n }\n },\n [editor],\n );\n\n const focus = useCallback(() => {\n editor?.commands.focus(\"end\");\n }, [editor]);\n\n const getOutput = useCallback((): MentionsOutput | null => {\n if (!editor) return null;\n return buildOutput(editor);\n }, [editor]);\n\n return { editor, getOutput, clear, setContent, appendText, focus };\n}\n","import { mergeAttributes, Node } from \"@tiptap/core\";\nimport type { ReactNode } from \"react\";\nimport type { MentionToken } from \"../types/MentionToken\";\n\nexport interface MentionNodeAttrs {\n id: string;\n label: string;\n entityType: string;\n rootLabel?: string | null;\n}\n\nconst DEFAULT_PREFIXES: Record<string, string> = {\n workspace: \"@\",\n contract: \"@\",\n file: \"#\",\n web: \":\",\n};\n\nexport type MentionNodeOptions = {\n onClickRef?: React.RefObject<((token: MentionToken, event: MouseEvent) => void) | undefined>;\n onHoverRef?: React.RefObject<((token: MentionToken) => ReactNode) | undefined>;\n};\n\nexport const MentionNode = Node.create<MentionNodeOptions>({\n name: \"mention\",\n group: \"inline\",\n inline: true,\n atom: true,\n selectable: true,\n draggable: false,\n\n addOptions() {\n return {\n onClickRef: undefined,\n onHoverRef: undefined,\n };\n },\n\n addAttributes() {\n return {\n id: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-id\"),\n renderHTML: (attributes) => ({ \"data-id\": attributes.id }),\n },\n label: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-label\"),\n renderHTML: (attributes) => ({ \"data-label\": attributes.label }),\n },\n entityType: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-type\"),\n renderHTML: (attributes) => ({ \"data-type\": attributes.entityType }),\n },\n rootLabel: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-root-label\"),\n renderHTML: (attributes) =>\n attributes.rootLabel\n ? { \"data-root-label\": attributes.rootLabel }\n : {},\n },\n };\n },\n\n parseHTML() {\n return [{ tag: 'span[data-mention]' }];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const entityType = node.attrs.entityType as string;\n const label = node.attrs.label as string;\n const prefix = DEFAULT_PREFIXES[entityType] ?? \"@\";\n const display = `${prefix}${label}`;\n\n const hasClick = !!this.options.onClickRef?.current;\n const extraAttrs: Record<string, string> = {};\n if (hasClick) {\n extraAttrs[\"data-mention-clickable\"] = \"\";\n }\n\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n \"data-mention\": \"\",\n class: \"mention-chip\",\n ...extraAttrs,\n }),\n display,\n ];\n },\n\n renderText({ node }) {\n const entityType = node.attrs.entityType as string;\n const label = node.attrs.label as string;\n const prefix = DEFAULT_PREFIXES[entityType] ?? \"@\";\n return `${prefix}${label}`;\n },\n\n addNodeView() {\n const options = this.options;\n\n return ({ node, HTMLAttributes }) => {\n const entityType = node.attrs.entityType as string;\n const label = node.attrs.label as string;\n const id = node.attrs.id as string;\n const prefix = DEFAULT_PREFIXES[entityType] ?? \"@\";\n\n const dom = document.createElement(\"span\");\n Object.entries(\n mergeAttributes(HTMLAttributes, {\n \"data-mention\": \"\",\n \"data-type\": entityType,\n \"data-id\": id,\n class: \"mention-chip\",\n }),\n ).forEach(([key, val]) => {\n if (val != null && val !== false) dom.setAttribute(key, String(val));\n });\n\n dom.textContent = `${prefix}${label}`;\n\n if (options.onClickRef?.current) {\n dom.setAttribute(\"data-mention-clickable\", \"\");\n dom.style.cursor = \"pointer\";\n }\n\n dom.addEventListener(\"click\", (event) => {\n const handler = options.onClickRef?.current;\n if (handler) {\n event.preventDefault();\n event.stopPropagation();\n handler({ id, type: entityType, label }, event);\n }\n });\n\n // Hover tooltip\n let tooltip: HTMLElement | null = null;\n\n dom.addEventListener(\"mouseenter\", () => {\n const hoverFn = options.onHoverRef?.current;\n if (!hoverFn) return;\n\n const content = hoverFn({ id, type: entityType, label });\n if (!content) return;\n\n tooltip = document.createElement(\"div\");\n tooltip.setAttribute(\"data-mention-tooltip\", \"\");\n tooltip.textContent = typeof content === \"string\" ? content : \"\";\n dom.style.position = \"relative\";\n dom.appendChild(tooltip);\n });\n\n dom.addEventListener(\"mouseleave\", () => {\n if (tooltip && tooltip.parentNode) {\n tooltip.parentNode.removeChild(tooltip);\n tooltip = null;\n }\n });\n\n return { dom };\n };\n },\n\n addKeyboardShortcuts() {\n return {\n Backspace: () =>\n this.editor.commands.command(({ tr, state }) => {\n let isMention = false;\n const { selection } = state;\n const { empty, anchor } = selection;\n\n if (!empty) return false;\n\n state.doc.nodesBetween(anchor - 1, anchor, (node, pos) => {\n if (node.type.name === this.name) {\n isMention = true;\n tr.insertText(\"\", pos, pos + node.nodeSize);\n }\n });\n\n return isMention;\n }),\n };\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport type { EditorView } from \"@tiptap/pm/view\";\n\n/* ------------------------------------------------------------------ */\n/* Suggestion state types */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionState =\n | \"idle\"\n | \"loading\"\n | \"showing\"\n | \"drilling\"\n | \"inserting\";\n\n/* ------------------------------------------------------------------ */\n/* Callbacks the React layer implements */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionCallbacks = {\n onStart: (props: SuggestionCallbackProps) => void;\n onUpdate: (props: SuggestionCallbackProps) => void;\n onExit: () => void;\n onKeyDown: (props: { event: KeyboardEvent }) => boolean;\n};\n\nexport type SuggestionCallbackProps = {\n query: string;\n trigger: string;\n clientRect: (() => DOMRect | null) | null;\n range: { from: number; to: number };\n command: (attrs: Record<string, unknown>) => void;\n};\n\n/* ------------------------------------------------------------------ */\n/* Trigger detection */\n/* ------------------------------------------------------------------ */\n\ntype TriggerMatch = {\n trigger: string;\n query: string;\n from: number;\n to: number;\n textBefore: string;\n};\n\nfunction detectTrigger(\n text: string,\n cursorPos: number,\n docStartPos: number,\n triggers: string[],\n): TriggerMatch | null {\n const relCursor = cursorPos - docStartPos;\n const before = text.slice(0, relCursor);\n\n for (let i = before.length - 1; i >= 0; i--) {\n const ch = before[i];\n if (ch === \"\\n\") return null;\n\n for (const trigger of triggers) {\n if (before.substring(i, i + trigger.length) === trigger) {\n if (i === 0 || /\\s/.test(before[i - 1])) {\n const query = before.slice(i + trigger.length);\n return {\n trigger,\n query,\n from: docStartPos + i,\n to: cursorPos,\n textBefore: before.slice(0, i),\n };\n }\n }\n }\n }\n\n return null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Plugin key */\n/* ------------------------------------------------------------------ */\n\nconst suggestionPluginKey = new PluginKey(\"mentionSuggestion\");\n\n/* ------------------------------------------------------------------ */\n/* Ref-based callback container (avoids stale closure issues) */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionCallbacksRef = { current: SuggestionCallbacks };\n\nexport type AllowTriggerRef = {\n current?: (trigger: string, context: { textBefore: string }) => boolean;\n};\n\nexport type StreamingRef = { current: boolean };\n\n/* ------------------------------------------------------------------ */\n/* Build the single multi-trigger suggestion extension */\n/* ------------------------------------------------------------------ */\n\nexport function createSuggestionExtension(\n triggers: string[],\n callbacksRef: SuggestionCallbacksRef,\n allowTriggerRef?: AllowTriggerRef,\n streamingRef?: StreamingRef,\n) {\n return Extension.create({\n name: \"mentionSuggestion\",\n priority: 200,\n\n addProseMirrorPlugins() {\n const editor = this.editor;\n let active = false;\n let lastQuery: string | null = null;\n let lastTrigger: string | null = null;\n\n const getClientRect = (\n view: EditorView,\n from: number,\n ): (() => DOMRect | null) => {\n return () => {\n try {\n const coords = view.coordsAtPos(from);\n return new DOMRect(\n coords.left,\n coords.top,\n 0,\n coords.bottom - coords.top,\n );\n } catch {\n return null;\n }\n };\n };\n\n const makeCommand = (range: { from: number; to: number }) => {\n return (attrs: Record<string, unknown>) => {\n editor\n .chain()\n .focus()\n .insertContentAt(range, [\n {\n type: \"mention\",\n attrs: {\n id: attrs.id,\n label: attrs.label,\n entityType: attrs.entityType,\n rootLabel: attrs.rootLabel ?? null,\n },\n },\n { type: \"text\", text: \" \" },\n ])\n .run();\n };\n };\n\n const plugin = new Plugin({\n key: suggestionPluginKey,\n\n props: {\n handleKeyDown(_view, event) {\n if (!active) return false;\n return callbacksRef.current.onKeyDown({ event });\n },\n },\n\n view() {\n return {\n update(view, _prevState) {\n if (streamingRef?.current) {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n return;\n }\n\n const { state } = view;\n const { selection } = state;\n\n if (!selection.empty) {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n return;\n }\n\n const $pos = selection.$from;\n const textBlock = $pos.parent;\n\n if (!textBlock.isTextblock) {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n return;\n }\n\n const blockStart = $pos.start();\n const blockText = textBlock.textContent;\n const cursorPos = $pos.pos;\n\n const match = detectTrigger(blockText, cursorPos, blockStart, triggers);\n\n if (match) {\n // Check allowTrigger gate\n if (allowTriggerRef?.current) {\n const allowed = allowTriggerRef.current(match.trigger, {\n textBefore: match.textBefore,\n });\n if (!allowed) {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n return;\n }\n }\n\n const range = { from: match.from, to: match.to };\n const props: SuggestionCallbackProps = {\n query: match.query,\n trigger: match.trigger,\n clientRect: getClientRect(view, match.from),\n range,\n command: makeCommand(range),\n };\n\n if (!active) {\n active = true;\n lastQuery = match.query;\n lastTrigger = match.trigger;\n callbacksRef.current.onStart(props);\n } else if (\n match.query !== lastQuery ||\n match.trigger !== lastTrigger\n ) {\n lastQuery = match.query;\n lastTrigger = match.trigger;\n callbacksRef.current.onUpdate(props);\n }\n } else {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n }\n },\n\n destroy() {\n if (active) {\n callbacksRef.current.onExit();\n }\n },\n };\n },\n });\n\n return [plugin];\n },\n });\n}\n","import type { JSONContent } from \"@tiptap/core\";\nimport type { MentionToken } from \"../types/MentionToken\";\n\n/**\n * Serialize a Tiptap JSON document to a markdown string.\n *\n * Mention nodes are encoded as `@[label](id)` or `@rootLabel[label](id)` when the mention has a root (e.g. file under workspace).\n * All other text passes through verbatim.\n */\nexport function serializeToMarkdown(doc: JSONContent): string {\n if (!doc.content) return \"\";\n\n const parts: string[] = [];\n\n for (const block of doc.content) {\n if (block.type === \"paragraph\") {\n parts.push(serializeParagraph(block));\n } else if (block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n\n return parts.join(\"\\n\");\n}\n\nfunction serializeParagraph(node: JSONContent): string {\n if (!node.content) return \"\";\n\n return node.content\n .map((child) => {\n if (child.type === \"mention\") {\n const { id, label, entityType, rootLabel } = child.attrs ?? {};\n const idPart =\n entityType && entityType !== \"unknown\"\n ? `${entityType}:${id}`\n : id;\n if (rootLabel != null && rootLabel !== \"\") {\n return `@${rootLabel}[${label}](${idPart})`;\n }\n return `@[${label}](${idPart})`;\n }\n return child.text ?? \"\";\n })\n .join(\"\");\n}\n\n/**\n * Extract all `MentionToken`s from a Tiptap JSON document, in document order.\n */\nexport function extractTokens(doc: JSONContent): MentionToken[] {\n const tokens: MentionToken[] = [];\n\n function walk(node: JSONContent) {\n if (node.type === \"mention\" && node.attrs) {\n tokens.push({\n id: node.attrs.id as string,\n type: node.attrs.entityType as string,\n label: node.attrs.label as string,\n });\n }\n if (node.content) {\n for (const child of node.content) {\n walk(child);\n }\n }\n }\n\n walk(doc);\n return tokens;\n}\n\n/**\n * Extract plain text from a Tiptap JSON document.\n * Mention nodes are replaced with their label (no trigger prefix in plain text).\n */\nexport function extractPlainText(doc: JSONContent): string {\n if (!doc.content) return \"\";\n\n const parts: string[] = [];\n\n for (const block of doc.content) {\n if (block.type === \"paragraph\") {\n parts.push(extractParagraphText(block));\n }\n }\n\n return parts.join(\"\\n\");\n}\n\nfunction extractParagraphText(node: JSONContent): string {\n if (!node.content) return \"\";\n\n return node.content\n .map((child) => {\n if (child.type === \"mention\") {\n return child.attrs?.label ?? \"\";\n }\n return child.text ?? \"\";\n })\n .join(\"\");\n}\n","import type { JSONContent } from \"@tiptap/core\";\nimport { extractTokens, extractPlainText } from \"./markdownSerializer\";\nimport type { MentionToken } from \"../types/MentionToken\";\n\n/**\n * Regex matching mention tokens:\n * - `@[label](id)` or `@[label](type:id)`\n * - `@rootLabel[label](type:id)` when the mention has a root (e.g. file under workspace).\n * Groups: (1) rootLabel (may be empty string), (2) label, (3) optional entityType, (4) id.\n *\n * `[^\\[@]` prevents the rootLabel from crossing `@` boundaries so that plain\n * `@word` in running text is never swallowed into a false rootLabel match.\n */\nconst MENTION_RE = /@([^\\[@]*)\\[([^\\]]+)\\]\\((?:([^:)]+):)?([^)]+)\\)/g;\n\n/**\n * Parse a markdown string (with `@[label](id)`, `@[label](type:id)`, or `@rootLabel[label](id)` tokens)\n * into a Tiptap-compatible JSON document.\n */\nexport function parseFromMarkdown(markdown: string): JSONContent {\n const lines = markdown.split(\"\\n\");\n\n const content: JSONContent[] = lines.map((line) => {\n const children = parseLine(line);\n return children.length > 0\n ? { type: \"paragraph\", content: children }\n : { type: \"paragraph\" };\n });\n\n return { type: \"doc\", content };\n}\n\nfunction parseLine(line: string): JSONContent[] {\n const nodes: JSONContent[] = [];\n let lastIndex = 0;\n\n // Reset regex state\n MENTION_RE.lastIndex = 0;\n\n let match: RegExpExecArray | null;\n while ((match = MENTION_RE.exec(line)) !== null) {\n const fullMatch = match[0];\n const rootLabel = match[1] || null;\n const label = match[2];\n const entityType = match[3] ?? \"unknown\";\n const id = match[4];\n\n // Text before this mention\n if (match.index > lastIndex) {\n nodes.push({\n type: \"text\",\n text: line.slice(lastIndex, match.index),\n });\n }\n\n // Mention node\n nodes.push({\n type: \"mention\",\n attrs: {\n id,\n label,\n entityType,\n rootLabel,\n },\n });\n\n lastIndex = match.index + fullMatch.length;\n }\n\n // Trailing text\n if (lastIndex < line.length) {\n nodes.push({\n type: \"text\",\n text: line.slice(lastIndex),\n });\n }\n\n return nodes;\n}\n\n/* ------------------------------------------------------------------ */\n/* Convenience helper: markdown → tokens + plain text */\n/* ------------------------------------------------------------------ */\n\n/**\n * Parse a markdown string and extract structured data from it.\n *\n * This is a convenience wrapper that combines `parseFromMarkdown`,\n * `extractTokens`, and `extractPlainText` into a single call.\n *\n * @example\n * ```ts\n * const { tokens, plainText } = extractFromMarkdown(\n * \"Check @Marketing[Q4 Strategy.pdf](file_1) for details\"\n * );\n * // tokens → [{ id: \"file_1\", type: \"unknown\", label: \"Q4 Strategy.pdf\" }]\n * // plainText → \"Check Q4 Strategy.pdf for details\"\n * ```\n */\nexport function extractFromMarkdown(markdown: string): {\n tokens: MentionToken[];\n plainText: string;\n} {\n const doc = parseFromMarkdown(markdown);\n return {\n tokens: extractTokens(doc),\n plainText: extractPlainText(doc),\n };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { MentionItem, MentionProvider } from \"../types/MentionProvider\";\nimport type { MentionToken } from \"../types/MentionToken\";\nimport type {\n SuggestionCallbackProps,\n SuggestionCallbacks,\n SuggestionCallbacksRef,\n SuggestionState,\n} from \"../core/suggestionPlugin\";\nimport { debounce } from \"../utils/debounce\";\n\n/* ------------------------------------------------------------------ */\n/* Public state exposed to the UI layer */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionUIState = {\n state: SuggestionState;\n items: MentionItem[];\n breadcrumbs: MentionItem[];\n activeIndex: number;\n loading: boolean;\n clientRect: (() => DOMRect | null) | null;\n trigger: string | null;\n query: string;\n};\n\nexport type SuggestionActions = {\n navigateUp: () => void;\n navigateDown: () => void;\n select: (item?: MentionItem) => void;\n goBack: () => void;\n close: () => void;\n searchNested: (query: string) => void;\n};\n\nexport type SuggestionHookOptions = {\n onMentionAdd?: (token: MentionToken) => void;\n};\n\nconst IDLE_STATE: SuggestionUIState = {\n state: \"idle\",\n items: [],\n breadcrumbs: [],\n activeIndex: 0,\n loading: false,\n clientRect: null,\n trigger: null,\n query: \"\",\n};\n\n/* ------------------------------------------------------------------ */\n/* Hook */\n/* ------------------------------------------------------------------ */\n\nexport function useSuggestion(\n providers: MentionProvider[],\n options: SuggestionHookOptions = {},\n) {\n const [uiState, setUIState] = useState<SuggestionUIState>(IDLE_STATE);\n\n const stateRef = useRef(uiState);\n stateRef.current = uiState;\n\n const providersRef = useRef(providers);\n providersRef.current = providers;\n\n const onMentionAddRef = useRef(options.onMentionAdd);\n onMentionAddRef.current = options.onMentionAdd;\n\n const commandRef = useRef<((attrs: Record<string, unknown>) => void) | null>(\n null,\n );\n const providerRef = useRef<MentionProvider | null>(null);\n\n const debouncedFetchRef = useRef<ReturnType<typeof debounce> | null>(null);\n\n useEffect(() => {\n return () => {\n debouncedFetchRef.current?.cancel();\n };\n }, []);\n\n /* ---------------------------------------------------------------- */\n /* Fetch items from the provider */\n /* ---------------------------------------------------------------- */\n\n const fetchItems = useCallback(\n async (\n provider: MentionProvider,\n query: string,\n parent?: MentionItem,\n useSearchAll?: boolean,\n ) => {\n setUIState((prev) => ({ ...prev, loading: true, state: \"loading\" }));\n\n try {\n let items: MentionItem[];\n\n if (useSearchAll && provider.searchAll) {\n items = await provider.searchAll(query);\n } else if (parent && provider.getChildren) {\n items = await provider.getChildren(parent, query);\n } else {\n items = await provider.getRootItems(query);\n }\n\n setUIState((prev) => ({\n ...prev,\n items,\n loading: false,\n state: \"showing\",\n activeIndex: 0,\n }));\n } catch {\n setUIState((prev) => ({\n ...prev,\n items: [],\n loading: false,\n state: \"showing\",\n }));\n }\n },\n [],\n );\n\n const scheduleFetch = useCallback(\n (\n provider: MentionProvider,\n query: string,\n parent?: MentionItem,\n useSearchAll?: boolean,\n ) => {\n debouncedFetchRef.current?.cancel();\n\n const ms = provider.debounceMs;\n if (ms && ms > 0) {\n setUIState((prev) => ({ ...prev, loading: true }));\n const debouncedFn = debounce(() => {\n fetchItems(provider, query, parent, useSearchAll);\n }, ms);\n debouncedFetchRef.current = debouncedFn;\n debouncedFn();\n } else {\n fetchItems(provider, query, parent, useSearchAll);\n }\n },\n [fetchItems],\n );\n\n /* ---------------------------------------------------------------- */\n /* Suggestion plugin callbacks */\n /* ---------------------------------------------------------------- */\n\n const onStart = useCallback(\n (props: SuggestionCallbackProps) => {\n const provider = providersRef.current.find(\n (p) => p.trigger === props.trigger,\n );\n if (!provider) return;\n\n providerRef.current = provider;\n commandRef.current = props.command;\n\n setUIState({\n state: \"loading\",\n items: [],\n breadcrumbs: [],\n activeIndex: 0,\n loading: true,\n clientRect: props.clientRect,\n trigger: props.trigger,\n query: props.query,\n });\n\n if (!props.query.trim() && provider.getRecentItems) {\n provider.getRecentItems().then((recentItems) => {\n const tagged = recentItems.map((item) => ({\n ...item,\n group: item.group ?? \"Recent\",\n }));\n setUIState((prev) => ({\n ...prev,\n items: tagged,\n loading: false,\n state: \"showing\",\n activeIndex: 0,\n }));\n }).catch(() => {\n scheduleFetch(provider, props.query);\n });\n return;\n }\n\n if (props.query.trim() && provider.searchAll) {\n scheduleFetch(provider, props.query, undefined, true);\n } else {\n scheduleFetch(provider, props.query);\n }\n },\n [scheduleFetch],\n );\n\n const onUpdate = useCallback(\n (props: SuggestionCallbackProps) => {\n const provider = providerRef.current;\n if (!provider) return;\n\n commandRef.current = props.command;\n const current = stateRef.current;\n\n if (current.breadcrumbs.length > 0) {\n setUIState((prev) => ({\n ...prev,\n breadcrumbs: [],\n clientRect: props.clientRect,\n query: props.query,\n activeIndex: 0,\n }));\n } else {\n setUIState((prev) => ({\n ...prev,\n clientRect: props.clientRect,\n query: props.query,\n }));\n }\n\n if (props.query.trim() && provider.searchAll) {\n scheduleFetch(provider, props.query, undefined, true);\n } else if (!props.query.trim() && provider.getRecentItems) {\n provider.getRecentItems().then((recentItems) => {\n const tagged = recentItems.map((item) => ({\n ...item,\n group: item.group ?? \"Recent\",\n }));\n setUIState((prev) => ({\n ...prev,\n items: tagged,\n loading: false,\n state: \"showing\",\n activeIndex: 0,\n }));\n }).catch(() => {\n scheduleFetch(provider, props.query);\n });\n } else {\n scheduleFetch(provider, props.query);\n }\n },\n [scheduleFetch],\n );\n\n const onExit = useCallback(() => {\n debouncedFetchRef.current?.cancel();\n providerRef.current = null;\n commandRef.current = null;\n setUIState(IDLE_STATE);\n }, []);\n\n /* ---------------------------------------------------------------- */\n /* Navigation actions */\n /* ---------------------------------------------------------------- */\n\n const navigateUp = useCallback(() => {\n setUIState((prev) => ({\n ...prev,\n activeIndex: Math.max(0, prev.activeIndex - 1),\n }));\n }, []);\n\n const navigateDown = useCallback(() => {\n setUIState((prev) => ({\n ...prev,\n activeIndex: Math.min(prev.items.length - 1, prev.activeIndex + 1),\n }));\n }, []);\n\n const select = useCallback(\n (item?: MentionItem) => {\n const current = stateRef.current;\n const selected = item ?? current.items[current.activeIndex];\n if (!selected) return;\n\n const provider = providerRef.current;\n\n if (selected.hasChildren && provider?.getChildren) {\n setUIState((prev) => ({\n ...prev,\n state: \"drilling\",\n breadcrumbs: [...prev.breadcrumbs, selected],\n items: [],\n activeIndex: 0,\n query: \"\",\n }));\n\n fetchItems(provider, \"\", selected);\n return;\n }\n\n const rootLabel =\n current.breadcrumbs.length > 0\n ? current.breadcrumbs[0].label\n : selected.rootLabel ?? null;\n\n if (commandRef.current) {\n commandRef.current({\n id: selected.id,\n label: selected.label,\n entityType: selected.type,\n rootLabel,\n });\n }\n\n onMentionAddRef.current?.({\n id: selected.id,\n type: selected.type,\n label: selected.label,\n });\n },\n [fetchItems],\n );\n\n const goBack = useCallback(() => {\n const provider = providerRef.current;\n if (!provider) return;\n\n setUIState((prev) => {\n const newBreadcrumbs = prev.breadcrumbs.slice(0, -1);\n const parent = newBreadcrumbs[newBreadcrumbs.length - 1];\n\n if (parent) {\n fetchItems(provider, \"\", parent);\n } else {\n fetchItems(provider, prev.query);\n }\n\n return {\n ...prev,\n breadcrumbs: newBreadcrumbs,\n items: [],\n activeIndex: 0,\n state: \"loading\" as const,\n };\n });\n }, [fetchItems]);\n\n const close = useCallback(() => {\n debouncedFetchRef.current?.cancel();\n setUIState(IDLE_STATE);\n }, []);\n\n /* ---------------------------------------------------------------- */\n /* Nested search */\n /* ---------------------------------------------------------------- */\n\n const searchNested = useCallback(\n (query: string) => {\n const provider = providerRef.current;\n if (!provider) return;\n\n const current = stateRef.current;\n const parent = current.breadcrumbs[current.breadcrumbs.length - 1];\n if (parent) {\n scheduleFetch(provider, query, parent);\n }\n },\n [scheduleFetch],\n );\n\n /* ---------------------------------------------------------------- */\n /* Keyboard handler */\n /* ---------------------------------------------------------------- */\n\n const onKeyDown = useCallback(\n ({ event }: { event: KeyboardEvent }): boolean => {\n const current = stateRef.current;\n if (current.state === \"idle\") return false;\n\n switch (event.key) {\n case \"ArrowUp\":\n event.preventDefault();\n navigateUp();\n return true;\n case \"ArrowDown\":\n event.preventDefault();\n navigateDown();\n return true;\n case \"Enter\": {\n event.preventDefault();\n const selectedItem = current.items[current.activeIndex];\n if (selectedItem) {\n select(selectedItem);\n }\n return true;\n }\n case \"Tab\": {\n event.preventDefault();\n const selectedItem = current.items[current.activeIndex];\n if (selectedItem) {\n select(selectedItem);\n }\n return true;\n }\n case \"ArrowRight\": {\n const activeItem = current.items[current.activeIndex];\n if (activeItem?.hasChildren) {\n event.preventDefault();\n select(activeItem);\n return true;\n }\n return false;\n }\n case \"ArrowLeft\":\n if (current.breadcrumbs.length > 0) {\n event.preventDefault();\n goBack();\n return true;\n }\n return false;\n case \"Escape\":\n event.preventDefault();\n close();\n return true;\n default:\n return false;\n }\n },\n [navigateUp, navigateDown, select, goBack, close],\n );\n\n /* ---------------------------------------------------------------- */\n /* Build a ref that always points to the latest callbacks. */\n /* ---------------------------------------------------------------- */\n\n const callbacksRef: SuggestionCallbacksRef = useRef<SuggestionCallbacks>({\n onStart,\n onUpdate,\n onExit,\n onKeyDown,\n });\n\n callbacksRef.current = { onStart, onUpdate, onExit, onKeyDown };\n\n const actions: SuggestionActions = {\n navigateUp,\n navigateDown,\n select,\n goBack,\n close,\n searchNested,\n };\n\n return { uiState, actions, callbacksRef };\n}\n","/**\n * Returns a debounced version of `fn` that delays invocation until\n * `ms` milliseconds have elapsed since the last call.\n * Call `.cancel()` on the returned function to clear any pending timer.\n */\nexport function debounce<T extends (...args: any[]) => void>(\n fn: T,\n ms: number,\n): T & { cancel: () => void } {\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const debounced = ((...args: any[]) => {\n if (timer != null) clearTimeout(timer);\n timer = setTimeout(() => {\n timer = null;\n fn(...args);\n }, ms);\n }) as T & { cancel: () => void };\n\n debounced.cancel = () => {\n if (timer != null) {\n clearTimeout(timer);\n timer = null;\n }\n };\n\n return debounced;\n}\n","import React, { useEffect, useRef, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { MentionItem } from \"../types/MentionProvider\";\nimport { listboxAttrs, optionAttrs } from \"../utils/ariaHelpers\";\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionListProps = {\n items: MentionItem[];\n activeIndex: number;\n breadcrumbs: MentionItem[];\n loading: boolean;\n trigger: string | null;\n query: string;\n clientRect: (() => DOMRect | null) | null;\n onSelect: (item: MentionItem) => void;\n onHover: (index: number) => void;\n onGoBack: () => void;\n onSearchNested?: (query: string) => void;\n onNavigateUp?: () => void;\n onNavigateDown?: () => void;\n onClose?: () => void;\n onFocusEditor?: () => void;\n renderItem?: (item: MentionItem, depth: number) => ReactNode;\n renderEmpty?: (query: string) => ReactNode;\n renderLoading?: () => ReactNode;\n renderGroupHeader?: (group: string) => ReactNode;\n listboxId: string;\n};\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport function SuggestionList({\n items,\n activeIndex,\n breadcrumbs,\n loading,\n trigger,\n query,\n clientRect,\n onSelect,\n onHover,\n onGoBack,\n onSearchNested,\n onNavigateUp,\n onNavigateDown,\n onClose,\n onFocusEditor,\n renderItem,\n renderEmpty,\n renderLoading,\n renderGroupHeader,\n listboxId,\n}: SuggestionListProps) {\n const listRef = useRef<HTMLDivElement>(null);\n const searchInputRef = useRef<HTMLInputElement>(null);\n const depth = breadcrumbs.length;\n const [nestedQuery, setNestedQuery] = useState(\"\");\n\n const breadcrumbKey = breadcrumbs.map((b) => b.id).join(\"/\");\n const prevBreadcrumbKey = useRef(breadcrumbKey);\n useEffect(() => {\n if (prevBreadcrumbKey.current !== breadcrumbKey) {\n setNestedQuery(\"\");\n prevBreadcrumbKey.current = breadcrumbKey;\n }\n }, [breadcrumbKey]);\n\n const prevBreadcrumbsLen = useRef(breadcrumbs.length);\n useEffect(() => {\n if (prevBreadcrumbsLen.current > 0 && breadcrumbs.length === 0) {\n onFocusEditor?.();\n } else if (breadcrumbs.length > 0 && searchInputRef.current) {\n requestAnimationFrame(() => searchInputRef.current?.focus());\n }\n prevBreadcrumbsLen.current = breadcrumbs.length;\n }, [breadcrumbKey, breadcrumbs.length, onFocusEditor]);\n\n useEffect(() => {\n if (!listRef.current) return;\n const active = listRef.current.querySelector('[aria-selected=\"true\"]');\n active?.scrollIntoView({ block: \"nearest\" });\n }, [activeIndex]);\n\n const { style, position } = usePopoverPosition(clientRect);\n\n const activeQuery = breadcrumbs.length > 0 ? nestedQuery : query;\n const showEmpty = !loading && items.length === 0 && activeQuery.trim().length > 0;\n\n if (items.length === 0 && !loading && !showEmpty) return null;\n\n const handleSearchKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n switch (e.key) {\n case \"ArrowDown\":\n e.preventDefault();\n onNavigateDown?.();\n break;\n case \"ArrowUp\":\n e.preventDefault();\n onNavigateUp?.();\n break;\n case \"Enter\": {\n e.preventDefault();\n e.stopPropagation();\n const selectedItem = items[activeIndex];\n if (selectedItem) onSelect(selectedItem);\n break;\n }\n case \"Escape\":\n e.preventDefault();\n onFocusEditor?.();\n onClose?.();\n break;\n case \"ArrowLeft\":\n if (nestedQuery === \"\" || e.currentTarget.selectionStart === 0) {\n e.preventDefault();\n onGoBack();\n }\n break;\n case \"ArrowRight\": {\n const item = items[activeIndex];\n if (item?.hasChildren) {\n e.preventDefault();\n onSelect(item);\n }\n break;\n }\n case \"Backspace\":\n if (nestedQuery === \"\") {\n e.preventDefault();\n onGoBack();\n }\n break;\n }\n };\n\n const hasGroups = items.some((item) => item.group);\n\n return (\n <div\n data-suggestions=\"\"\n data-trigger={trigger}\n data-suggestions-position={position}\n style={style}\n ref={listRef}\n >\n {breadcrumbs.length > 0 && (\n <div data-suggestion-breadcrumb=\"\">\n <button\n type=\"button\"\n data-suggestion-back=\"\"\n onClick={onGoBack}\n aria-label=\"Go back\"\n >\n &larr;\n </button>\n {breadcrumbs.map((crumb, i) => (\n <span key={crumb.id} data-suggestion-breadcrumb-item=\"\">\n {i > 0 && <span data-suggestion-breadcrumb-sep=\"\">/</span>}\n {crumb.label}\n </span>\n ))}\n </div>\n )}\n\n {breadcrumbs.length > 0 && (\n <div data-suggestion-search=\"\">\n <input\n ref={searchInputRef}\n type=\"text\"\n data-suggestion-search-input=\"\"\n placeholder=\"Search...\"\n value={nestedQuery}\n onChange={(e) => {\n const q = e.target.value;\n setNestedQuery(q);\n onSearchNested?.(q);\n }}\n onKeyDown={handleSearchKeyDown}\n autoComplete=\"off\"\n spellCheck={false}\n />\n </div>\n )}\n\n {loading && (\n <div data-suggestion-loading=\"\">\n {renderLoading ? renderLoading() : \"Loading...\"}\n </div>\n )}\n\n {showEmpty && (\n <div data-suggestion-empty=\"\">\n {renderEmpty ? renderEmpty(activeQuery) : \"No results\"}\n </div>\n )}\n\n {!loading && items.length > 0 && (\n <div {...listboxAttrs(listboxId, `${trigger ?? \"\"} suggestions`)}>\n {hasGroups\n ? renderGroupedItems(items, activeIndex, depth, onSelect, onHover, renderItem, renderGroupHeader)\n : items.map((item, index) => (\n <SuggestionItem\n key={item.id}\n item={item}\n index={index}\n isActive={index === activeIndex}\n depth={depth}\n onSelect={onSelect}\n onHover={onHover}\n renderItem={renderItem}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Grouped rendering */\n/* ------------------------------------------------------------------ */\n\nfunction renderGroupedItems(\n items: MentionItem[],\n activeIndex: number,\n depth: number,\n onSelect: (item: MentionItem) => void,\n onHover: (index: number) => void,\n renderItem?: (item: MentionItem, depth: number) => ReactNode,\n renderGroupHeader?: (group: string) => ReactNode,\n) {\n const elements: ReactNode[] = [];\n let lastGroup: string | undefined;\n\n items.forEach((item, index) => {\n if (item.group && item.group !== lastGroup) {\n lastGroup = item.group;\n elements.push(\n <div key={`group-${item.group}`} data-suggestion-group-header=\"\">\n {renderGroupHeader ? renderGroupHeader(item.group) : item.group}\n </div>,\n );\n }\n\n elements.push(\n <SuggestionItem\n key={item.id}\n item={item}\n index={index}\n isActive={index === activeIndex}\n depth={depth}\n onSelect={onSelect}\n onHover={onHover}\n renderItem={renderItem}\n />,\n );\n });\n\n return elements;\n}\n\n/* ------------------------------------------------------------------ */\n/* Single item */\n/* ------------------------------------------------------------------ */\n\nfunction SuggestionItem({\n item,\n index,\n isActive,\n depth,\n onSelect,\n onHover,\n renderItem,\n}: {\n item: MentionItem;\n index: number;\n isActive: boolean;\n depth: number;\n onSelect: (item: MentionItem) => void;\n onHover: (index: number) => void;\n renderItem?: (item: MentionItem, depth: number) => ReactNode;\n}) {\n const itemId = `mention-option-${item.id}`;\n\n return (\n <div\n {...optionAttrs(itemId, isActive, index)}\n data-suggestion-item=\"\"\n data-suggestion-item-active={isActive ? \"\" : undefined}\n data-has-children={item.hasChildren ? \"\" : undefined}\n onMouseEnter={() => onHover(index)}\n onClick={() => onSelect(item)}\n >\n {renderItem ? (\n renderItem(item, depth)\n ) : (\n <DefaultSuggestionItem item={item} />\n )}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Default item render */\n/* ------------------------------------------------------------------ */\n\nfunction DefaultSuggestionItem({ item }: { item: MentionItem }) {\n return (\n <>\n {item.icon && (\n <span data-suggestion-item-icon=\"\">{item.icon}</span>\n )}\n <span data-suggestion-item-label=\"\">{item.label}</span>\n {item.description && (\n <span data-suggestion-item-description=\"\">{item.description}</span>\n )}\n {item.hasChildren && (\n <span data-suggestion-item-chevron=\"\" aria-hidden=\"true\">\n &rsaquo;\n </span>\n )}\n </>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Popover positioning with edge-aware flipping */\n/* ------------------------------------------------------------------ */\n\nconst POPOVER_HEIGHT_ESTIMATE = 280;\nconst POPOVER_WIDTH_ESTIMATE = 360;\n\nfunction usePopoverPosition(\n clientRect: (() => DOMRect | null) | null,\n): { style: React.CSSProperties; position: \"above\" | \"below\" } {\n if (!clientRect) {\n return { style: { display: \"none\" }, position: \"below\" };\n }\n\n const rect = clientRect();\n if (!rect) {\n return { style: { display: \"none\" }, position: \"below\" };\n }\n\n const viewportH = typeof window !== \"undefined\" ? window.innerHeight : 800;\n const viewportW = typeof window !== \"undefined\" ? window.innerWidth : 1200;\n\n const spaceBelow = viewportH - rect.bottom;\n const shouldFlip = spaceBelow < POPOVER_HEIGHT_ESTIMATE && rect.top > spaceBelow;\n\n let left = rect.left;\n if (left + POPOVER_WIDTH_ESTIMATE > viewportW) {\n left = Math.max(0, viewportW - POPOVER_WIDTH_ESTIMATE);\n }\n\n if (shouldFlip) {\n return {\n style: {\n position: \"fixed\",\n left: `${left}px`,\n bottom: `${viewportH - rect.top + 4}px`,\n zIndex: 50,\n },\n position: \"above\",\n };\n }\n\n return {\n style: {\n position: \"fixed\",\n left: `${left}px`,\n top: `${rect.bottom + 4}px`,\n zIndex: 50,\n },\n position: \"below\",\n };\n}\n","/**\n * Generates ARIA attributes for the suggestion combobox pattern.\n */\n\nexport function comboboxAttrs(expanded: boolean, listboxId: string) {\n return {\n role: \"combobox\" as const,\n \"aria-haspopup\": \"listbox\" as const,\n \"aria-expanded\": expanded,\n \"aria-owns\": expanded ? listboxId : undefined,\n };\n}\n\nexport function listboxAttrs(id: string, label: string) {\n return {\n id,\n role: \"listbox\" as const,\n \"aria-label\": label,\n };\n}\n\nexport function optionAttrs(\n id: string,\n selected: boolean,\n index: number,\n) {\n return {\n id,\n role: \"option\" as const,\n \"aria-selected\": selected,\n \"aria-posinset\": index + 1,\n };\n}\n"],"mappings":"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","names":["import_react","import_react","import_core","import_state","import_core","StarterKit","Placeholder","editor","import_react","import_react","import_jsx_runtime","MentionsInput"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/MentionsInput.tsx","../src/hooks/useMentionsEditor.ts","../src/core/mentionExtension.ts","../src/core/suggestionPlugin.ts","../src/core/markdownSerializer.ts","../src/core/markdownParser.ts","../src/hooks/useSuggestion.ts","../src/utils/debounce.ts","../src/components/SuggestionList.tsx","../src/utils/ariaHelpers.ts","../src/hooks/useMentionsContent.ts"],"sourcesContent":["/* ------------------------------------------------------------------ */\n/* Components */\n/* ------------------------------------------------------------------ */\nexport { MentionsInput } from \"./components/MentionsInput\";\n\n/* ------------------------------------------------------------------ */\n/* Hooks */\n/* ------------------------------------------------------------------ */\nexport { useMentionsContent } from \"./hooks/useMentionsContent\";\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\nexport type { MentionToken } from \"./types/MentionToken\";\nexport type {\n MentionProvider,\n MentionItem,\n} from \"./types/MentionProvider\";\nexport type { MentionsOutput } from \"./types/MentionsOutput\";\nexport type {\n MentionsInputProps,\n MentionsInputHandle,\n} from \"./types/MentionsInputProps\";\n\n/* ------------------------------------------------------------------ */\n/* Utilities */\n/* ------------------------------------------------------------------ */\nexport { serializeToMarkdown } from \"./core/markdownSerializer\";\nexport { parseFromMarkdown, extractFromMarkdown } from \"./core/markdownParser\";\n","import React, { forwardRef, useCallback, useId, useImperativeHandle } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { EditorContent } from \"@tiptap/react\";\nimport { useMentionsEditor } from \"../hooks/useMentionsEditor\";\nimport { useSuggestion } from \"../hooks/useSuggestion\";\nimport { SuggestionList } from \"./SuggestionList\";\nimport { comboboxAttrs } from \"../utils/ariaHelpers\";\nimport type {\n MentionsInputProps,\n MentionsInputHandle,\n} from \"../types/MentionsInputProps\";\n\n/**\n * `<MentionsInput>` — the single public component.\n *\n * A structured text editor with typed entity tokens.\n * Consumers register `providers` for each trigger character,\n * and receive structured output via `onChange` and `onSubmit`.\n */\nexport const MentionsInput = forwardRef<MentionsInputHandle, MentionsInputProps>(\n function MentionsInput(\n {\n value,\n providers,\n onChange,\n placeholder = \"Type a message...\",\n autoFocus = false,\n disabled = false,\n className,\n onSubmit,\n clearOnSubmit = true,\n maxLength,\n renderItem,\n renderChip,\n renderEmpty,\n renderLoading,\n renderGroupHeader,\n onFocus,\n onBlur,\n onMentionAdd,\n onMentionRemove,\n onMentionClick,\n onMentionHover,\n minHeight,\n maxHeight,\n submitKey = \"enter\",\n allowTrigger,\n validateMention,\n portalContainer,\n streaming,\n onStreamingComplete,\n },\n ref,\n ) {\n const instanceId = useId();\n const listboxId = `mentions-listbox-${instanceId}`;\n\n const { uiState, actions, callbacksRef } = useSuggestion(providers, {\n onMentionAdd,\n });\n\n const { editor, getOutput, clear, setContent, appendText, focus } = useMentionsEditor({\n providers,\n value,\n onChange,\n onSubmit,\n clearOnSubmit,\n placeholder,\n autoFocus,\n editable: !disabled,\n callbacksRef,\n onFocus,\n onBlur,\n submitKey,\n onMentionRemove,\n onMentionClick,\n onMentionHover,\n allowTrigger,\n validateMention,\n streaming,\n onStreamingComplete,\n });\n\n useImperativeHandle(\n ref,\n () => ({ clear, setContent, appendText, focus, getOutput }),\n [clear, setContent, appendText, focus, getOutput],\n );\n\n const isExpanded = uiState.state !== \"idle\";\n\n const handleHover = useCallback((index: number) => {\n void index;\n }, []);\n\n const handleFocusEditor = useCallback(() => {\n editor?.commands.focus();\n }, [editor]);\n\n const editorStyle: React.CSSProperties = {};\n if (minHeight != null) editorStyle.minHeight = `${minHeight}px`;\n if (maxHeight != null) {\n editorStyle.maxHeight = `${maxHeight}px`;\n editorStyle.overflowY = \"auto\";\n }\n\n const suggestionList = isExpanded ? (\n <SuggestionList\n items={uiState.items}\n activeIndex={uiState.activeIndex}\n breadcrumbs={uiState.breadcrumbs}\n loading={uiState.loading}\n trigger={uiState.trigger}\n query={uiState.query}\n clientRect={uiState.clientRect}\n onSelect={(item) => actions.select(item)}\n onHover={handleHover}\n onGoBack={actions.goBack}\n onSearchNested={actions.searchNested}\n onNavigateUp={actions.navigateUp}\n onNavigateDown={actions.navigateDown}\n onClose={actions.close}\n onFocusEditor={handleFocusEditor}\n renderItem={renderItem}\n renderEmpty={renderEmpty}\n renderLoading={renderLoading}\n renderGroupHeader={renderGroupHeader}\n listboxId={listboxId}\n />\n ) : null;\n\n return (\n <div\n className={className}\n data-mentions-input=\"\"\n data-disabled={disabled ? \"\" : undefined}\n {...comboboxAttrs(isExpanded, listboxId)}\n aria-activedescendant={\n isExpanded && uiState.items[uiState.activeIndex]\n ? `mention-option-${uiState.items[uiState.activeIndex].id}`\n : undefined\n }\n >\n <div style={editorStyle}>\n <EditorContent editor={editor} />\n </div>\n\n {portalContainer\n ? suggestionList && createPortal(suggestionList, portalContainer)\n : suggestionList}\n </div>\n );\n },\n);\n","import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { useEditor } from \"@tiptap/react\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\nimport { Extension } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport { MentionNode } from \"../core/mentionExtension\";\nimport { createSuggestionExtension } from \"../core/suggestionPlugin\";\nimport type { StreamingRef } from \"../core/suggestionPlugin\";\nimport {\n serializeToMarkdown,\n extractTokens,\n extractPlainText,\n} from \"../core/markdownSerializer\";\nimport { parseFromMarkdown } from \"../core/markdownParser\";\nimport type { MentionProvider } from \"../types/MentionProvider\";\nimport type { MentionToken } from \"../types/MentionToken\";\nimport type { MentionsOutput } from \"../types/MentionsOutput\";\nimport type { SuggestionCallbacksRef } from \"../core/suggestionPlugin\";\n\n/* ------------------------------------------------------------------ */\n/* Helper: build MentionsOutput from the current editor */\n/* ------------------------------------------------------------------ */\n\nfunction buildOutput(editor: { getJSON: () => any }): MentionsOutput {\n const json = editor.getJSON();\n return {\n markdown: serializeToMarkdown(json),\n tokens: extractTokens(json),\n plainText: extractPlainText(json),\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Collect all mention tokens from a doc JSON */\n/* ------------------------------------------------------------------ */\n\nfunction collectMentionTokens(doc: any): MentionToken[] {\n const tokens: MentionToken[] = [];\n function walk(node: any) {\n if (node.type === \"mention\" && node.attrs) {\n tokens.push({\n id: node.attrs.id,\n type: node.attrs.entityType ?? node.attrs.type,\n label: node.attrs.label,\n });\n }\n if (node.content) {\n for (const child of node.content) walk(child);\n }\n }\n walk(doc);\n return tokens;\n}\n\n/* ------------------------------------------------------------------ */\n/* Submit keyboard shortcut extension (Cmd/Ctrl+Enter) */\n/* ------------------------------------------------------------------ */\n\nfunction createSubmitExtension(\n onSubmitRef: React.RefObject<((output: MentionsOutput) => void) | undefined>,\n clearOnSubmitRef: React.RefObject<boolean>,\n submitKeyRef: React.RefObject<string>,\n) {\n return Extension.create({\n name: \"submitShortcut\",\n priority: 150,\n\n addKeyboardShortcuts() {\n return {\n \"Mod-Enter\": () => {\n const key = submitKeyRef.current;\n if (key === \"mod+enter\" || key === \"enter\") {\n if (onSubmitRef.current) {\n onSubmitRef.current(buildOutput(this.editor));\n if (clearOnSubmitRef.current) {\n this.editor.commands.clearContent(true);\n }\n }\n return true;\n }\n return false;\n },\n };\n },\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Enter key handling */\n/* ------------------------------------------------------------------ */\n\nconst enterSubmitPluginKey = new PluginKey(\"enterSubmit\");\n\nfunction createEnterExtension(\n onSubmitRef: React.RefObject<((output: MentionsOutput) => void) | undefined>,\n clearOnSubmitRef: React.RefObject<boolean>,\n submitKeyRef: React.RefObject<string>,\n) {\n return Extension.create({\n name: \"enterSubmit\",\n priority: 150,\n\n addProseMirrorPlugins() {\n const editor = this.editor;\n\n return [\n new Plugin({\n key: enterSubmitPluginKey,\n props: {\n handleKeyDown(_view, event) {\n if (event.key !== \"Enter\") return false;\n\n const key = submitKeyRef.current;\n\n if (key === \"none\") return false;\n\n if (key === \"mod+enter\") {\n // Enter = new line (default PM behavior handles it)\n // Shift+Enter also new line\n return false;\n }\n\n // key === \"enter\" (default)\n if (event.shiftKey) {\n editor.commands.splitBlock();\n return true;\n }\n\n if (event.metaKey || event.ctrlKey) return false;\n\n if (onSubmitRef.current) {\n onSubmitRef.current(buildOutput(editor));\n if (clearOnSubmitRef.current) {\n editor.commands.clearContent(true);\n }\n }\n return true;\n },\n },\n }),\n ];\n },\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Mention removal detection plugin */\n/* ------------------------------------------------------------------ */\n\nconst mentionRemovePluginKey = new PluginKey(\"mentionRemove\");\n\nfunction createMentionRemoveExtension(\n onMentionRemoveRef: React.RefObject<((token: MentionToken) => void) | undefined>,\n) {\n return Extension.create({\n name: \"mentionRemoveDetector\",\n priority: 100,\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: mentionRemovePluginKey,\n appendTransaction(transactions, oldState, newState) {\n if (!onMentionRemoveRef.current) return null;\n\n const oldMentions = collectMentionTokens(oldState.doc.toJSON());\n const newMentions = collectMentionTokens(newState.doc.toJSON());\n\n if (oldMentions.length <= newMentions.length) return null;\n\n const newIds = new Set(newMentions.map((m) => m.id));\n for (const m of oldMentions) {\n if (!newIds.has(m.id)) {\n onMentionRemoveRef.current(m);\n }\n }\n\n return null;\n },\n }),\n ];\n },\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Streaming input blocker plugin */\n/* ------------------------------------------------------------------ */\n\nconst streamingBlockPluginKey = new PluginKey(\"streamingBlock\");\n\nfunction createStreamingBlockExtension(streamingRef: StreamingRef) {\n return Extension.create({\n name: \"streamingBlock\",\n priority: 200,\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: streamingBlockPluginKey,\n props: {\n handleKeyDown() {\n return streamingRef.current;\n },\n handleKeyPress() {\n return streamingRef.current;\n },\n handlePaste() {\n return streamingRef.current;\n },\n handleDrop() {\n return streamingRef.current;\n },\n },\n }),\n ];\n },\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Hook */\n/* ------------------------------------------------------------------ */\n\ntype UseMentionsEditorOptions = {\n providers: MentionProvider[];\n value?: string;\n onChange?: (output: MentionsOutput) => void;\n onSubmit?: (output: MentionsOutput) => void;\n clearOnSubmit?: boolean;\n placeholder?: string;\n autoFocus?: boolean;\n editable?: boolean;\n callbacksRef: SuggestionCallbacksRef;\n onFocus?: () => void;\n onBlur?: () => void;\n submitKey?: string;\n onMentionRemove?: (token: MentionToken) => void;\n onMentionClick?: (token: MentionToken, event: MouseEvent) => void;\n onMentionHover?: (token: MentionToken) => ReactNode;\n allowTrigger?: (trigger: string, context: { textBefore: string }) => boolean;\n validateMention?: (token: MentionToken) => boolean | Promise<boolean>;\n streaming?: boolean;\n onStreamingComplete?: (output: MentionsOutput) => void;\n};\n\nexport function useMentionsEditor({\n providers,\n value,\n onChange,\n onSubmit,\n clearOnSubmit = true,\n placeholder,\n autoFocus = false,\n editable = true,\n callbacksRef,\n onFocus,\n onBlur,\n submitKey = \"enter\",\n onMentionRemove,\n onMentionClick,\n onMentionHover,\n allowTrigger,\n validateMention,\n streaming = false,\n onStreamingComplete,\n}: UseMentionsEditorOptions) {\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n const onSubmitRef = useRef(onSubmit);\n onSubmitRef.current = onSubmit;\n\n const clearOnSubmitRef = useRef(clearOnSubmit);\n clearOnSubmitRef.current = clearOnSubmit;\n\n const onFocusRef = useRef(onFocus);\n onFocusRef.current = onFocus;\n\n const onBlurRef = useRef(onBlur);\n onBlurRef.current = onBlur;\n\n const submitKeyRef = useRef(submitKey);\n submitKeyRef.current = submitKey;\n\n const onMentionRemoveRef = useRef(onMentionRemove);\n onMentionRemoveRef.current = onMentionRemove;\n\n const onMentionClickRef = useRef(onMentionClick);\n onMentionClickRef.current = onMentionClick;\n\n const onMentionHoverRef = useRef(onMentionHover);\n onMentionHoverRef.current = onMentionHover;\n\n const allowTriggerRef = useRef(allowTrigger);\n allowTriggerRef.current = allowTrigger;\n\n const validateMentionRef = useRef(validateMention);\n validateMentionRef.current = validateMention;\n\n const onStreamingCompleteRef = useRef(onStreamingComplete);\n onStreamingCompleteRef.current = onStreamingComplete;\n\n // Streaming state — mutable ref so ProseMirror plugins can read it\n // without re-creating the extension chain.\n const streamingRef = useRef<boolean>(streaming);\n streamingRef.current = streaming;\n const prevStreamingRef = useRef(streaming);\n\n // Throttle state for onChange during streaming\n const throttleTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingOutputRef = useRef<MentionsOutput | null>(null);\n\n // Track internal value to avoid controlled-value infinite loops\n const internalMarkdownRef = useRef<string | null>(null);\n\n const initialContent = useMemo(() => {\n if (!value) return undefined;\n return parseFromMarkdown(value);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const triggersKey = providers.map((p) => p.trigger).join(\",\");\n const triggers = useMemo(\n () => providers.map((p) => p.trigger),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [triggersKey],\n );\n\n const suggestionExtension = useMemo(\n () =>\n createSuggestionExtension(\n triggers,\n callbacksRef,\n allowTriggerRef,\n streamingRef,\n ),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [triggersKey],\n );\n\n const submitExt = useMemo(\n () => createSubmitExtension(onSubmitRef, clearOnSubmitRef, submitKeyRef),\n [],\n );\n const enterExt = useMemo(\n () => createEnterExtension(onSubmitRef, clearOnSubmitRef, submitKeyRef),\n [],\n );\n const mentionRemoveExt = useMemo(\n () => createMentionRemoveExtension(onMentionRemoveRef),\n [],\n );\n\n const streamingBlockExt = useMemo(\n () => createStreamingBlockExtension(streamingRef),\n [],\n );\n\n const mentionNodeExt = useMemo(\n () =>\n MentionNode.configure({\n onClickRef: onMentionClickRef,\n onHoverRef: onMentionHoverRef,\n }),\n [],\n );\n\n const editor = useEditor({\n extensions: [\n StarterKit.configure({\n heading: false,\n blockquote: false,\n codeBlock: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n horizontalRule: false,\n hardBreak: false,\n }),\n Placeholder.configure({\n placeholder: ({ editor }) =>\n editor.isEmpty ? (placeholder ?? \"Type a message...\") : \"\",\n showOnlyCurrent: true,\n }),\n mentionNodeExt,\n suggestionExtension,\n submitExt,\n enterExt,\n mentionRemoveExt,\n streamingBlockExt,\n ],\n content: initialContent,\n autofocus: autoFocus ? \"end\" : false,\n editable,\n editorProps: {\n attributes: {\n class: \"mentions-editor\",\n },\n },\n onUpdate: ({ editor }) => {\n const output = buildOutput(editor);\n internalMarkdownRef.current = output.markdown;\n\n if (streamingRef.current) {\n pendingOutputRef.current = output;\n if (!throttleTimerRef.current) {\n throttleTimerRef.current = setTimeout(() => {\n throttleTimerRef.current = null;\n if (pendingOutputRef.current) {\n onChangeRef.current?.(pendingOutputRef.current);\n pendingOutputRef.current = null;\n }\n }, 150);\n }\n } else {\n onChangeRef.current?.(output);\n }\n },\n onFocus: () => {\n onFocusRef.current?.();\n },\n onBlur: () => {\n onBlurRef.current?.();\n },\n });\n\n // Flush throttled onChange and fire onStreamingComplete when streaming ends\n useEffect(() => {\n if (prevStreamingRef.current && !streaming && editor) {\n if (throttleTimerRef.current) {\n clearTimeout(throttleTimerRef.current);\n throttleTimerRef.current = null;\n }\n const output = buildOutput(editor);\n onChangeRef.current?.(output);\n onStreamingCompleteRef.current?.(output);\n pendingOutputRef.current = null;\n }\n prevStreamingRef.current = streaming;\n }, [streaming, editor]);\n\n // Clean up throttle timer on unmount\n useEffect(() => {\n return () => {\n if (throttleTimerRef.current) {\n clearTimeout(throttleTimerRef.current);\n }\n };\n }, []);\n\n // Sync editable state\n useEffect(() => {\n if (editor && editor.isEditable !== editable) {\n editor.setEditable(editable);\n }\n }, [editor, editable]);\n\n // Controlled value: update editor when external value changes\n useEffect(() => {\n if (!editor || value === undefined) return;\n if (value === internalMarkdownRef.current) return;\n const doc = parseFromMarkdown(value);\n editor.commands.setContent(doc);\n internalMarkdownRef.current = value;\n }, [editor, value]);\n\n // Mention validation\n useEffect(() => {\n if (!editor || !validateMention) return;\n\n const runValidation = async () => {\n const doc = editor.getJSON();\n const tokens = collectMentionTokens(doc);\n const invalidIds = new Set<string>();\n\n await Promise.all(\n tokens.map(async (token) => {\n const valid = await validateMention(token);\n if (!valid) invalidIds.add(token.id);\n }),\n );\n\n editor.view.dom.querySelectorAll(\"[data-mention]\").forEach((el) => {\n const id = el.getAttribute(\"data-id\");\n if (id && invalidIds.has(id)) {\n el.setAttribute(\"data-mention-invalid\", \"\");\n } else {\n el.removeAttribute(\"data-mention-invalid\");\n }\n });\n };\n\n runValidation();\n }, [editor, validateMention]);\n\n /* ---------------------------------------------------------------- */\n /* Imperative methods */\n /* ---------------------------------------------------------------- */\n\n const clear = useCallback(() => {\n editor?.commands.clearContent(true);\n }, [editor]);\n\n const setContent = useCallback(\n (markdown: string) => {\n if (!editor) return;\n const doc = parseFromMarkdown(markdown);\n editor.commands.setContent(doc);\n internalMarkdownRef.current = markdown;\n if (streamingRef.current) {\n editor.commands.focus(\"end\");\n }\n },\n [editor],\n );\n\n const appendText = useCallback(\n (text: string) => {\n if (!editor) return;\n const endPos = editor.state.doc.content.size - 1;\n editor.commands.insertContentAt(endPos, text);\n if (streamingRef.current) {\n editor.commands.focus(\"end\");\n }\n },\n [editor],\n );\n\n const focus = useCallback(() => {\n editor?.commands.focus(\"end\");\n }, [editor]);\n\n const getOutput = useCallback((): MentionsOutput | null => {\n if (!editor) return null;\n return buildOutput(editor);\n }, [editor]);\n\n return { editor, getOutput, clear, setContent, appendText, focus };\n}\n","import { mergeAttributes, Node } from \"@tiptap/core\";\nimport type { ReactNode } from \"react\";\nimport type { MentionToken } from \"../types/MentionToken\";\n\nexport interface MentionNodeAttrs {\n id: string;\n label: string;\n entityType: string;\n rootLabel?: string | null;\n}\n\nconst DEFAULT_PREFIXES: Record<string, string> = {\n workspace: \"@\",\n contract: \"@\",\n file: \"#\",\n web: \":\",\n};\n\nexport type MentionNodeOptions = {\n onClickRef?: React.RefObject<((token: MentionToken, event: MouseEvent) => void) | undefined>;\n onHoverRef?: React.RefObject<((token: MentionToken) => ReactNode) | undefined>;\n};\n\nexport const MentionNode = Node.create<MentionNodeOptions>({\n name: \"mention\",\n group: \"inline\",\n inline: true,\n atom: true,\n selectable: true,\n draggable: false,\n\n addOptions() {\n return {\n onClickRef: undefined,\n onHoverRef: undefined,\n };\n },\n\n addAttributes() {\n return {\n id: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-id\"),\n renderHTML: (attributes) => ({ \"data-id\": attributes.id }),\n },\n label: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-label\"),\n renderHTML: (attributes) => ({ \"data-label\": attributes.label }),\n },\n entityType: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-type\"),\n renderHTML: (attributes) => ({ \"data-type\": attributes.entityType }),\n },\n rootLabel: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-root-label\"),\n renderHTML: (attributes) =>\n attributes.rootLabel\n ? { \"data-root-label\": attributes.rootLabel }\n : {},\n },\n };\n },\n\n parseHTML() {\n return [{ tag: 'span[data-mention]' }];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const entityType = node.attrs.entityType as string;\n const label = node.attrs.label as string;\n const prefix = DEFAULT_PREFIXES[entityType] ?? \"@\";\n const display = `${prefix}${label}`;\n\n const hasClick = !!this.options.onClickRef?.current;\n const extraAttrs: Record<string, string> = {};\n if (hasClick) {\n extraAttrs[\"data-mention-clickable\"] = \"\";\n }\n\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n \"data-mention\": \"\",\n class: \"mention-chip\",\n ...extraAttrs,\n }),\n display,\n ];\n },\n\n renderText({ node }) {\n const entityType = node.attrs.entityType as string;\n const label = node.attrs.label as string;\n const prefix = DEFAULT_PREFIXES[entityType] ?? \"@\";\n return `${prefix}${label}`;\n },\n\n addNodeView() {\n const options = this.options;\n\n return ({ node, HTMLAttributes }) => {\n const entityType = node.attrs.entityType as string;\n const label = node.attrs.label as string;\n const id = node.attrs.id as string;\n const prefix = DEFAULT_PREFIXES[entityType] ?? \"@\";\n\n const dom = document.createElement(\"span\");\n Object.entries(\n mergeAttributes(HTMLAttributes, {\n \"data-mention\": \"\",\n \"data-type\": entityType,\n \"data-id\": id,\n class: \"mention-chip\",\n }),\n ).forEach(([key, val]) => {\n if (val != null && val !== false) dom.setAttribute(key, String(val));\n });\n\n dom.textContent = `${prefix}${label}`;\n\n if (options.onClickRef?.current) {\n dom.setAttribute(\"data-mention-clickable\", \"\");\n dom.style.cursor = \"pointer\";\n }\n\n dom.addEventListener(\"click\", (event) => {\n const handler = options.onClickRef?.current;\n if (handler) {\n event.preventDefault();\n event.stopPropagation();\n handler({ id, type: entityType, label }, event);\n }\n });\n\n // Hover tooltip\n let tooltip: HTMLElement | null = null;\n\n dom.addEventListener(\"mouseenter\", () => {\n const hoverFn = options.onHoverRef?.current;\n if (!hoverFn) return;\n\n const content = hoverFn({ id, type: entityType, label });\n if (!content) return;\n\n tooltip = document.createElement(\"div\");\n tooltip.setAttribute(\"data-mention-tooltip\", \"\");\n tooltip.textContent = typeof content === \"string\" ? content : \"\";\n dom.style.position = \"relative\";\n dom.appendChild(tooltip);\n });\n\n dom.addEventListener(\"mouseleave\", () => {\n if (tooltip && tooltip.parentNode) {\n tooltip.parentNode.removeChild(tooltip);\n tooltip = null;\n }\n });\n\n return { dom };\n };\n },\n\n addKeyboardShortcuts() {\n return {\n Backspace: () =>\n this.editor.commands.command(({ tr, state }) => {\n let isMention = false;\n const { selection } = state;\n const { empty, anchor } = selection;\n\n if (!empty) return false;\n\n state.doc.nodesBetween(anchor - 1, anchor, (node, pos) => {\n if (node.type.name === this.name) {\n isMention = true;\n tr.insertText(\"\", pos, pos + node.nodeSize);\n }\n });\n\n return isMention;\n }),\n };\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport type { EditorView } from \"@tiptap/pm/view\";\n\n/* ------------------------------------------------------------------ */\n/* Suggestion state types */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionState =\n | \"idle\"\n | \"loading\"\n | \"showing\"\n | \"drilling\"\n | \"inserting\";\n\n/* ------------------------------------------------------------------ */\n/* Callbacks the React layer implements */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionCallbacks = {\n onStart: (props: SuggestionCallbackProps) => void;\n onUpdate: (props: SuggestionCallbackProps) => void;\n onExit: () => void;\n onKeyDown: (props: { event: KeyboardEvent }) => boolean;\n};\n\nexport type SuggestionCallbackProps = {\n query: string;\n trigger: string;\n clientRect: (() => DOMRect | null) | null;\n range: { from: number; to: number };\n command: (attrs: Record<string, unknown>) => void;\n};\n\n/* ------------------------------------------------------------------ */\n/* Trigger detection */\n/* ------------------------------------------------------------------ */\n\ntype TriggerMatch = {\n trigger: string;\n query: string;\n from: number;\n to: number;\n textBefore: string;\n};\n\nfunction detectTrigger(\n text: string,\n cursorPos: number,\n docStartPos: number,\n triggers: string[],\n): TriggerMatch | null {\n const relCursor = cursorPos - docStartPos;\n const before = text.slice(0, relCursor);\n\n for (let i = before.length - 1; i >= 0; i--) {\n const ch = before[i];\n if (ch === \"\\n\") return null;\n\n for (const trigger of triggers) {\n if (before.substring(i, i + trigger.length) === trigger) {\n if (i === 0 || /\\s/.test(before[i - 1])) {\n const query = before.slice(i + trigger.length);\n return {\n trigger,\n query,\n from: docStartPos + i,\n to: cursorPos,\n textBefore: before.slice(0, i),\n };\n }\n }\n }\n }\n\n return null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Plugin key */\n/* ------------------------------------------------------------------ */\n\nconst suggestionPluginKey = new PluginKey(\"mentionSuggestion\");\n\n/* ------------------------------------------------------------------ */\n/* Ref-based callback container (avoids stale closure issues) */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionCallbacksRef = { current: SuggestionCallbacks };\n\nexport type AllowTriggerRef = {\n current?: (trigger: string, context: { textBefore: string }) => boolean;\n};\n\nexport type StreamingRef = { current: boolean };\n\n/* ------------------------------------------------------------------ */\n/* Build the single multi-trigger suggestion extension */\n/* ------------------------------------------------------------------ */\n\nexport function createSuggestionExtension(\n triggers: string[],\n callbacksRef: SuggestionCallbacksRef,\n allowTriggerRef?: AllowTriggerRef,\n streamingRef?: StreamingRef,\n) {\n return Extension.create({\n name: \"mentionSuggestion\",\n priority: 200,\n\n addProseMirrorPlugins() {\n const editor = this.editor;\n let active = false;\n let lastQuery: string | null = null;\n let lastTrigger: string | null = null;\n\n const getClientRect = (\n view: EditorView,\n from: number,\n ): (() => DOMRect | null) => {\n return () => {\n try {\n const coords = view.coordsAtPos(from);\n return new DOMRect(\n coords.left,\n coords.top,\n 0,\n coords.bottom - coords.top,\n );\n } catch {\n return null;\n }\n };\n };\n\n const makeCommand = (range: { from: number; to: number }) => {\n return (attrs: Record<string, unknown>) => {\n editor\n .chain()\n .focus()\n .insertContentAt(range, [\n {\n type: \"mention\",\n attrs: {\n id: attrs.id,\n label: attrs.label,\n entityType: attrs.entityType,\n rootLabel: attrs.rootLabel ?? null,\n },\n },\n { type: \"text\", text: \" \" },\n ])\n .run();\n };\n };\n\n const plugin = new Plugin({\n key: suggestionPluginKey,\n\n props: {\n handleKeyDown(_view, event) {\n if (!active) return false;\n return callbacksRef.current.onKeyDown({ event });\n },\n },\n\n view() {\n return {\n update(view, _prevState) {\n if (streamingRef?.current) {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n return;\n }\n\n const { state } = view;\n const { selection } = state;\n\n if (!selection.empty) {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n return;\n }\n\n const $pos = selection.$from;\n const textBlock = $pos.parent;\n\n if (!textBlock.isTextblock) {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n return;\n }\n\n const blockStart = $pos.start();\n const blockText = textBlock.textContent;\n const cursorPos = $pos.pos;\n\n const match = detectTrigger(blockText, cursorPos, blockStart, triggers);\n\n if (match) {\n // Check allowTrigger gate\n if (allowTriggerRef?.current) {\n const allowed = allowTriggerRef.current(match.trigger, {\n textBefore: match.textBefore,\n });\n if (!allowed) {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n return;\n }\n }\n\n const range = { from: match.from, to: match.to };\n const props: SuggestionCallbackProps = {\n query: match.query,\n trigger: match.trigger,\n clientRect: getClientRect(view, match.from),\n range,\n command: makeCommand(range),\n };\n\n if (!active) {\n active = true;\n lastQuery = match.query;\n lastTrigger = match.trigger;\n callbacksRef.current.onStart(props);\n } else if (\n match.query !== lastQuery ||\n match.trigger !== lastTrigger\n ) {\n lastQuery = match.query;\n lastTrigger = match.trigger;\n callbacksRef.current.onUpdate(props);\n }\n } else {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n }\n },\n\n destroy() {\n if (active) {\n callbacksRef.current.onExit();\n }\n },\n };\n },\n });\n\n return [plugin];\n },\n });\n}\n","import type { JSONContent } from \"@tiptap/core\";\nimport type { MentionToken } from \"../types/MentionToken\";\n\n/**\n * Serialize a Tiptap JSON document to a markdown string.\n *\n * Mention nodes are encoded as `@[label](id)` or `@rootLabel[label](id)` when the mention has a root (e.g. file under workspace).\n * All other text passes through verbatim.\n */\nexport function serializeToMarkdown(doc: JSONContent): string {\n if (!doc.content) return \"\";\n\n const parts: string[] = [];\n\n for (const block of doc.content) {\n if (block.type === \"paragraph\") {\n parts.push(serializeParagraph(block));\n } else if (block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n\n return parts.join(\"\\n\");\n}\n\nfunction serializeParagraph(node: JSONContent): string {\n if (!node.content) return \"\";\n\n return node.content\n .map((child) => {\n if (child.type === \"mention\") {\n const { id, label, entityType, rootLabel } = child.attrs ?? {};\n const idPart =\n entityType && entityType !== \"unknown\"\n ? `${entityType}:${id}`\n : id;\n if (rootLabel != null && rootLabel !== \"\") {\n return `@${rootLabel}[${label}](${idPart})`;\n }\n return `@[${label}](${idPart})`;\n }\n return child.text ?? \"\";\n })\n .join(\"\");\n}\n\n/**\n * Extract all `MentionToken`s from a Tiptap JSON document, in document order.\n */\nexport function extractTokens(doc: JSONContent): MentionToken[] {\n const tokens: MentionToken[] = [];\n\n function walk(node: JSONContent) {\n if (node.type === \"mention\" && node.attrs) {\n tokens.push({\n id: node.attrs.id as string,\n type: node.attrs.entityType as string,\n label: node.attrs.label as string,\n });\n }\n if (node.content) {\n for (const child of node.content) {\n walk(child);\n }\n }\n }\n\n walk(doc);\n return tokens;\n}\n\n/**\n * Extract plain text from a Tiptap JSON document.\n * Mention nodes are replaced with their label (no trigger prefix in plain text).\n */\nexport function extractPlainText(doc: JSONContent): string {\n if (!doc.content) return \"\";\n\n const parts: string[] = [];\n\n for (const block of doc.content) {\n if (block.type === \"paragraph\") {\n parts.push(extractParagraphText(block));\n }\n }\n\n return parts.join(\"\\n\");\n}\n\nfunction extractParagraphText(node: JSONContent): string {\n if (!node.content) return \"\";\n\n return node.content\n .map((child) => {\n if (child.type === \"mention\") {\n return child.attrs?.label ?? \"\";\n }\n return child.text ?? \"\";\n })\n .join(\"\");\n}\n","import type { JSONContent } from \"@tiptap/core\";\nimport { extractTokens, extractPlainText } from \"./markdownSerializer\";\nimport type { MentionToken } from \"../types/MentionToken\";\n\n/**\n * Regex matching mention tokens:\n * - `@[label](id)` or `@[label](type:id)`\n * - `@rootLabel[label](type:id)` when the mention has a root (e.g. file under workspace).\n * Groups: (1) rootLabel (may be empty string), (2) label, (3) optional entityType, (4) id.\n *\n * `[^\\[@]` prevents the rootLabel from crossing `@` boundaries so that plain\n * `@word` in running text is never swallowed into a false rootLabel match.\n */\nconst MENTION_RE = /@([^\\[@]*)\\[([^\\]]+)\\]\\((?:([^:)]+):)?([^)]+)\\)/g;\n\n/**\n * Parse a markdown string (with `@[label](id)`, `@[label](type:id)`, or `@rootLabel[label](id)` tokens)\n * into a Tiptap-compatible JSON document.\n */\nexport function parseFromMarkdown(markdown: string): JSONContent {\n const lines = markdown.split(\"\\n\");\n\n const content: JSONContent[] = lines.map((line) => {\n const children = parseLine(line);\n return children.length > 0\n ? { type: \"paragraph\", content: children }\n : { type: \"paragraph\" };\n });\n\n return { type: \"doc\", content };\n}\n\nfunction parseLine(line: string): JSONContent[] {\n const nodes: JSONContent[] = [];\n let lastIndex = 0;\n\n // Reset regex state\n MENTION_RE.lastIndex = 0;\n\n let match: RegExpExecArray | null;\n while ((match = MENTION_RE.exec(line)) !== null) {\n const fullMatch = match[0];\n const rootLabel = match[1] || null;\n const label = match[2];\n const entityType = match[3] ?? \"unknown\";\n const id = match[4];\n\n // Text before this mention\n if (match.index > lastIndex) {\n nodes.push({\n type: \"text\",\n text: line.slice(lastIndex, match.index),\n });\n }\n\n // Mention node\n nodes.push({\n type: \"mention\",\n attrs: {\n id,\n label,\n entityType,\n rootLabel,\n },\n });\n\n lastIndex = match.index + fullMatch.length;\n }\n\n // Trailing text\n if (lastIndex < line.length) {\n nodes.push({\n type: \"text\",\n text: line.slice(lastIndex),\n });\n }\n\n return nodes;\n}\n\n/* ------------------------------------------------------------------ */\n/* Convenience helper: markdown → tokens + plain text */\n/* ------------------------------------------------------------------ */\n\n/**\n * Parse a markdown string and extract structured data from it.\n *\n * This is a convenience wrapper that combines `parseFromMarkdown`,\n * `extractTokens`, and `extractPlainText` into a single call.\n *\n * @example\n * ```ts\n * const { tokens, plainText } = extractFromMarkdown(\n * \"Check @Marketing[Q4 Strategy.pdf](file_1) for details\"\n * );\n * // tokens → [{ id: \"file_1\", type: \"unknown\", label: \"Q4 Strategy.pdf\" }]\n * // plainText → \"Check Q4 Strategy.pdf for details\"\n * ```\n */\nexport function extractFromMarkdown(markdown: string): {\n tokens: MentionToken[];\n plainText: string;\n} {\n const doc = parseFromMarkdown(markdown);\n return {\n tokens: extractTokens(doc),\n plainText: extractPlainText(doc),\n };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { MentionItem, MentionProvider } from \"../types/MentionProvider\";\nimport type { MentionToken } from \"../types/MentionToken\";\nimport type {\n SuggestionCallbackProps,\n SuggestionCallbacks,\n SuggestionCallbacksRef,\n SuggestionState,\n} from \"../core/suggestionPlugin\";\nimport { debounce } from \"../utils/debounce\";\n\n/* ------------------------------------------------------------------ */\n/* Public state exposed to the UI layer */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionUIState = {\n state: SuggestionState;\n items: MentionItem[];\n breadcrumbs: MentionItem[];\n activeIndex: number;\n loading: boolean;\n clientRect: (() => DOMRect | null) | null;\n trigger: string | null;\n query: string;\n};\n\nexport type SuggestionActions = {\n navigateUp: () => void;\n navigateDown: () => void;\n select: (item?: MentionItem) => void;\n goBack: () => void;\n close: () => void;\n searchNested: (query: string) => void;\n};\n\nexport type SuggestionHookOptions = {\n onMentionAdd?: (token: MentionToken) => void;\n};\n\nconst IDLE_STATE: SuggestionUIState = {\n state: \"idle\",\n items: [],\n breadcrumbs: [],\n activeIndex: 0,\n loading: false,\n clientRect: null,\n trigger: null,\n query: \"\",\n};\n\n/* ------------------------------------------------------------------ */\n/* Hook */\n/* ------------------------------------------------------------------ */\n\nexport function useSuggestion(\n providers: MentionProvider[],\n options: SuggestionHookOptions = {},\n) {\n const [uiState, setUIState] = useState<SuggestionUIState>(IDLE_STATE);\n\n const stateRef = useRef(uiState);\n stateRef.current = uiState;\n\n const providersRef = useRef(providers);\n providersRef.current = providers;\n\n const onMentionAddRef = useRef(options.onMentionAdd);\n onMentionAddRef.current = options.onMentionAdd;\n\n const commandRef = useRef<((attrs: Record<string, unknown>) => void) | null>(\n null,\n );\n const providerRef = useRef<MentionProvider | null>(null);\n\n const debouncedFetchRef = useRef<ReturnType<typeof debounce> | null>(null);\n\n useEffect(() => {\n return () => {\n debouncedFetchRef.current?.cancel();\n };\n }, []);\n\n /* ---------------------------------------------------------------- */\n /* Fetch items from the provider */\n /* ---------------------------------------------------------------- */\n\n const fetchItems = useCallback(\n async (\n provider: MentionProvider,\n query: string,\n parent?: MentionItem,\n useSearchAll?: boolean,\n ) => {\n setUIState((prev) => ({ ...prev, loading: true, state: \"loading\" }));\n\n try {\n let items: MentionItem[];\n\n if (useSearchAll && provider.searchAll) {\n items = await provider.searchAll(query);\n } else if (parent && provider.getChildren) {\n items = await provider.getChildren(parent, query);\n } else {\n items = await provider.getRootItems(query);\n }\n\n setUIState((prev) => ({\n ...prev,\n items,\n loading: false,\n state: \"showing\",\n activeIndex: 0,\n }));\n } catch {\n setUIState((prev) => ({\n ...prev,\n items: [],\n loading: false,\n state: \"showing\",\n }));\n }\n },\n [],\n );\n\n const scheduleFetch = useCallback(\n (\n provider: MentionProvider,\n query: string,\n parent?: MentionItem,\n useSearchAll?: boolean,\n ) => {\n debouncedFetchRef.current?.cancel();\n\n const ms = provider.debounceMs;\n if (ms && ms > 0) {\n setUIState((prev) => ({ ...prev, loading: true }));\n const debouncedFn = debounce(() => {\n fetchItems(provider, query, parent, useSearchAll);\n }, ms);\n debouncedFetchRef.current = debouncedFn;\n debouncedFn();\n } else {\n fetchItems(provider, query, parent, useSearchAll);\n }\n },\n [fetchItems],\n );\n\n /* ---------------------------------------------------------------- */\n /* Suggestion plugin callbacks */\n /* ---------------------------------------------------------------- */\n\n const onStart = useCallback(\n (props: SuggestionCallbackProps) => {\n const provider = providersRef.current.find(\n (p) => p.trigger === props.trigger,\n );\n if (!provider) return;\n\n providerRef.current = provider;\n commandRef.current = props.command;\n\n setUIState({\n state: \"loading\",\n items: [],\n breadcrumbs: [],\n activeIndex: 0,\n loading: true,\n clientRect: props.clientRect,\n trigger: props.trigger,\n query: props.query,\n });\n\n if (!props.query.trim() && provider.getRecentItems) {\n provider.getRecentItems().then((recentItems) => {\n const tagged = recentItems.map((item) => ({\n ...item,\n group: item.group ?? \"Recent\",\n }));\n setUIState((prev) => ({\n ...prev,\n items: tagged,\n loading: false,\n state: \"showing\",\n activeIndex: 0,\n }));\n }).catch(() => {\n scheduleFetch(provider, props.query);\n });\n return;\n }\n\n if (props.query.trim() && provider.searchAll) {\n scheduleFetch(provider, props.query, undefined, true);\n } else {\n scheduleFetch(provider, props.query);\n }\n },\n [scheduleFetch],\n );\n\n const onUpdate = useCallback(\n (props: SuggestionCallbackProps) => {\n const provider = providerRef.current;\n if (!provider) return;\n\n commandRef.current = props.command;\n const current = stateRef.current;\n\n if (current.breadcrumbs.length > 0) {\n setUIState((prev) => ({\n ...prev,\n breadcrumbs: [],\n clientRect: props.clientRect,\n query: props.query,\n activeIndex: 0,\n }));\n } else {\n setUIState((prev) => ({\n ...prev,\n clientRect: props.clientRect,\n query: props.query,\n }));\n }\n\n if (props.query.trim() && provider.searchAll) {\n scheduleFetch(provider, props.query, undefined, true);\n } else if (!props.query.trim() && provider.getRecentItems) {\n provider.getRecentItems().then((recentItems) => {\n const tagged = recentItems.map((item) => ({\n ...item,\n group: item.group ?? \"Recent\",\n }));\n setUIState((prev) => ({\n ...prev,\n items: tagged,\n loading: false,\n state: \"showing\",\n activeIndex: 0,\n }));\n }).catch(() => {\n scheduleFetch(provider, props.query);\n });\n } else {\n scheduleFetch(provider, props.query);\n }\n },\n [scheduleFetch],\n );\n\n const onExit = useCallback(() => {\n debouncedFetchRef.current?.cancel();\n providerRef.current = null;\n commandRef.current = null;\n setUIState(IDLE_STATE);\n }, []);\n\n /* ---------------------------------------------------------------- */\n /* Navigation actions */\n /* ---------------------------------------------------------------- */\n\n const navigateUp = useCallback(() => {\n setUIState((prev) => ({\n ...prev,\n activeIndex: Math.max(0, prev.activeIndex - 1),\n }));\n }, []);\n\n const navigateDown = useCallback(() => {\n setUIState((prev) => ({\n ...prev,\n activeIndex: Math.min(prev.items.length - 1, prev.activeIndex + 1),\n }));\n }, []);\n\n const select = useCallback(\n (item?: MentionItem) => {\n const current = stateRef.current;\n const selected = item ?? current.items[current.activeIndex];\n if (!selected) return;\n\n const provider = providerRef.current;\n\n if (selected.hasChildren && provider?.getChildren) {\n setUIState((prev) => ({\n ...prev,\n state: \"drilling\",\n breadcrumbs: [...prev.breadcrumbs, selected],\n items: [],\n activeIndex: 0,\n query: \"\",\n }));\n\n fetchItems(provider, \"\", selected);\n return;\n }\n\n const rootLabel =\n current.breadcrumbs.length > 0\n ? current.breadcrumbs[0].label\n : selected.rootLabel ?? null;\n\n if (commandRef.current) {\n commandRef.current({\n id: selected.id,\n label: selected.label,\n entityType: selected.type,\n rootLabel,\n });\n }\n\n onMentionAddRef.current?.({\n id: selected.id,\n type: selected.type,\n label: selected.label,\n });\n },\n [fetchItems],\n );\n\n const goBack = useCallback(() => {\n const provider = providerRef.current;\n if (!provider) return;\n\n setUIState((prev) => {\n const newBreadcrumbs = prev.breadcrumbs.slice(0, -1);\n const parent = newBreadcrumbs[newBreadcrumbs.length - 1];\n\n if (parent) {\n fetchItems(provider, \"\", parent);\n } else {\n fetchItems(provider, prev.query);\n }\n\n return {\n ...prev,\n breadcrumbs: newBreadcrumbs,\n items: [],\n activeIndex: 0,\n state: \"loading\" as const,\n };\n });\n }, [fetchItems]);\n\n const close = useCallback(() => {\n debouncedFetchRef.current?.cancel();\n setUIState(IDLE_STATE);\n }, []);\n\n /* ---------------------------------------------------------------- */\n /* Nested search */\n /* ---------------------------------------------------------------- */\n\n const searchNested = useCallback(\n (query: string) => {\n const provider = providerRef.current;\n if (!provider) return;\n\n const current = stateRef.current;\n const parent = current.breadcrumbs[current.breadcrumbs.length - 1];\n if (parent) {\n scheduleFetch(provider, query, parent);\n }\n },\n [scheduleFetch],\n );\n\n /* ---------------------------------------------------------------- */\n /* Keyboard handler */\n /* ---------------------------------------------------------------- */\n\n const onKeyDown = useCallback(\n ({ event }: { event: KeyboardEvent }): boolean => {\n const current = stateRef.current;\n if (current.state === \"idle\") return false;\n\n switch (event.key) {\n case \"ArrowUp\":\n event.preventDefault();\n navigateUp();\n return true;\n case \"ArrowDown\":\n event.preventDefault();\n navigateDown();\n return true;\n case \"Enter\": {\n event.preventDefault();\n const selectedItem = current.items[current.activeIndex];\n if (selectedItem) {\n select(selectedItem);\n }\n return true;\n }\n case \"Tab\": {\n event.preventDefault();\n const selectedItem = current.items[current.activeIndex];\n if (selectedItem) {\n select(selectedItem);\n }\n return true;\n }\n case \"ArrowRight\": {\n const activeItem = current.items[current.activeIndex];\n if (activeItem?.hasChildren) {\n event.preventDefault();\n select(activeItem);\n return true;\n }\n return false;\n }\n case \"ArrowLeft\":\n if (current.breadcrumbs.length > 0) {\n event.preventDefault();\n goBack();\n return true;\n }\n return false;\n case \"Escape\":\n event.preventDefault();\n close();\n return true;\n default:\n return false;\n }\n },\n [navigateUp, navigateDown, select, goBack, close],\n );\n\n /* ---------------------------------------------------------------- */\n /* Build a ref that always points to the latest callbacks. */\n /* ---------------------------------------------------------------- */\n\n const callbacksRef: SuggestionCallbacksRef = useRef<SuggestionCallbacks>({\n onStart,\n onUpdate,\n onExit,\n onKeyDown,\n });\n\n callbacksRef.current = { onStart, onUpdate, onExit, onKeyDown };\n\n const actions: SuggestionActions = {\n navigateUp,\n navigateDown,\n select,\n goBack,\n close,\n searchNested,\n };\n\n return { uiState, actions, callbacksRef };\n}\n","/**\n * Returns a debounced version of `fn` that delays invocation until\n * `ms` milliseconds have elapsed since the last call.\n * Call `.cancel()` on the returned function to clear any pending timer.\n */\nexport function debounce<T extends (...args: any[]) => void>(\n fn: T,\n ms: number,\n): T & { cancel: () => void } {\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const debounced = ((...args: any[]) => {\n if (timer != null) clearTimeout(timer);\n timer = setTimeout(() => {\n timer = null;\n fn(...args);\n }, ms);\n }) as T & { cancel: () => void };\n\n debounced.cancel = () => {\n if (timer != null) {\n clearTimeout(timer);\n timer = null;\n }\n };\n\n return debounced;\n}\n","import React, { useEffect, useRef, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { MentionItem } from \"../types/MentionProvider\";\nimport { listboxAttrs, optionAttrs } from \"../utils/ariaHelpers\";\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionListProps = {\n items: MentionItem[];\n activeIndex: number;\n breadcrumbs: MentionItem[];\n loading: boolean;\n trigger: string | null;\n query: string;\n clientRect: (() => DOMRect | null) | null;\n onSelect: (item: MentionItem) => void;\n onHover: (index: number) => void;\n onGoBack: () => void;\n onSearchNested?: (query: string) => void;\n onNavigateUp?: () => void;\n onNavigateDown?: () => void;\n onClose?: () => void;\n onFocusEditor?: () => void;\n renderItem?: (item: MentionItem, depth: number) => ReactNode;\n renderEmpty?: (query: string) => ReactNode;\n renderLoading?: () => ReactNode;\n renderGroupHeader?: (group: string) => ReactNode;\n listboxId: string;\n};\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport function SuggestionList({\n items,\n activeIndex,\n breadcrumbs,\n loading,\n trigger,\n query,\n clientRect,\n onSelect,\n onHover,\n onGoBack,\n onSearchNested,\n onNavigateUp,\n onNavigateDown,\n onClose,\n onFocusEditor,\n renderItem,\n renderEmpty,\n renderLoading,\n renderGroupHeader,\n listboxId,\n}: SuggestionListProps) {\n const listRef = useRef<HTMLDivElement>(null);\n const searchInputRef = useRef<HTMLInputElement>(null);\n const depth = breadcrumbs.length;\n const [nestedQuery, setNestedQuery] = useState(\"\");\n\n const breadcrumbKey = breadcrumbs.map((b) => b.id).join(\"/\");\n const prevBreadcrumbKey = useRef(breadcrumbKey);\n useEffect(() => {\n if (prevBreadcrumbKey.current !== breadcrumbKey) {\n setNestedQuery(\"\");\n prevBreadcrumbKey.current = breadcrumbKey;\n }\n }, [breadcrumbKey]);\n\n const prevBreadcrumbsLen = useRef(breadcrumbs.length);\n useEffect(() => {\n if (prevBreadcrumbsLen.current > 0 && breadcrumbs.length === 0) {\n onFocusEditor?.();\n } else if (breadcrumbs.length > 0 && searchInputRef.current) {\n requestAnimationFrame(() => searchInputRef.current?.focus());\n }\n prevBreadcrumbsLen.current = breadcrumbs.length;\n }, [breadcrumbKey, breadcrumbs.length, onFocusEditor]);\n\n useEffect(() => {\n if (!listRef.current) return;\n const active = listRef.current.querySelector('[aria-selected=\"true\"]');\n active?.scrollIntoView({ block: \"nearest\" });\n }, [activeIndex]);\n\n const { style, position } = usePopoverPosition(clientRect);\n\n const activeQuery = breadcrumbs.length > 0 ? nestedQuery : query;\n const showEmpty = !loading && items.length === 0 && activeQuery.trim().length > 0;\n\n if (items.length === 0 && !loading && !showEmpty) return null;\n\n const handleSearchKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n switch (e.key) {\n case \"ArrowDown\":\n e.preventDefault();\n onNavigateDown?.();\n break;\n case \"ArrowUp\":\n e.preventDefault();\n onNavigateUp?.();\n break;\n case \"Enter\": {\n e.preventDefault();\n e.stopPropagation();\n const selectedItem = items[activeIndex];\n if (selectedItem) onSelect(selectedItem);\n break;\n }\n case \"Escape\":\n e.preventDefault();\n onFocusEditor?.();\n onClose?.();\n break;\n case \"ArrowLeft\":\n if (nestedQuery === \"\" || e.currentTarget.selectionStart === 0) {\n e.preventDefault();\n onGoBack();\n }\n break;\n case \"ArrowRight\": {\n const item = items[activeIndex];\n if (item?.hasChildren) {\n e.preventDefault();\n onSelect(item);\n }\n break;\n }\n case \"Backspace\":\n if (nestedQuery === \"\") {\n e.preventDefault();\n onGoBack();\n }\n break;\n }\n };\n\n const hasGroups = items.some((item) => item.group);\n\n return (\n <div\n data-suggestions=\"\"\n data-trigger={trigger}\n data-suggestions-position={position}\n style={style}\n ref={listRef}\n >\n {breadcrumbs.length > 0 && (\n <div data-suggestion-breadcrumb=\"\">\n <button\n type=\"button\"\n data-suggestion-back=\"\"\n onClick={onGoBack}\n aria-label=\"Go back\"\n >\n &larr;\n </button>\n {breadcrumbs.map((crumb, i) => (\n <span key={crumb.id} data-suggestion-breadcrumb-item=\"\">\n {i > 0 && <span data-suggestion-breadcrumb-sep=\"\">/</span>}\n {crumb.label}\n </span>\n ))}\n </div>\n )}\n\n {breadcrumbs.length > 0 && (\n <div data-suggestion-search=\"\">\n <input\n ref={searchInputRef}\n type=\"text\"\n data-suggestion-search-input=\"\"\n placeholder=\"Search...\"\n value={nestedQuery}\n onChange={(e) => {\n const q = e.target.value;\n setNestedQuery(q);\n onSearchNested?.(q);\n }}\n onKeyDown={handleSearchKeyDown}\n autoComplete=\"off\"\n spellCheck={false}\n />\n </div>\n )}\n\n {loading && (\n <div data-suggestion-loading=\"\">\n {renderLoading ? renderLoading() : \"Loading...\"}\n </div>\n )}\n\n {showEmpty && (\n <div data-suggestion-empty=\"\">\n {renderEmpty ? renderEmpty(activeQuery) : \"No results\"}\n </div>\n )}\n\n {!loading && items.length > 0 && (\n <div {...listboxAttrs(listboxId, `${trigger ?? \"\"} suggestions`)}>\n {hasGroups\n ? renderGroupedItems(items, activeIndex, depth, onSelect, onHover, renderItem, renderGroupHeader)\n : items.map((item, index) => (\n <SuggestionItem\n key={item.id}\n item={item}\n index={index}\n isActive={index === activeIndex}\n depth={depth}\n onSelect={onSelect}\n onHover={onHover}\n renderItem={renderItem}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Grouped rendering */\n/* ------------------------------------------------------------------ */\n\nfunction renderGroupedItems(\n items: MentionItem[],\n activeIndex: number,\n depth: number,\n onSelect: (item: MentionItem) => void,\n onHover: (index: number) => void,\n renderItem?: (item: MentionItem, depth: number) => ReactNode,\n renderGroupHeader?: (group: string) => ReactNode,\n) {\n const elements: ReactNode[] = [];\n let lastGroup: string | undefined;\n\n items.forEach((item, index) => {\n if (item.group && item.group !== lastGroup) {\n lastGroup = item.group;\n elements.push(\n <div key={`group-${item.group}`} data-suggestion-group-header=\"\">\n {renderGroupHeader ? renderGroupHeader(item.group) : item.group}\n </div>,\n );\n }\n\n elements.push(\n <SuggestionItem\n key={item.id}\n item={item}\n index={index}\n isActive={index === activeIndex}\n depth={depth}\n onSelect={onSelect}\n onHover={onHover}\n renderItem={renderItem}\n />,\n );\n });\n\n return elements;\n}\n\n/* ------------------------------------------------------------------ */\n/* Single item */\n/* ------------------------------------------------------------------ */\n\nfunction SuggestionItem({\n item,\n index,\n isActive,\n depth,\n onSelect,\n onHover,\n renderItem,\n}: {\n item: MentionItem;\n index: number;\n isActive: boolean;\n depth: number;\n onSelect: (item: MentionItem) => void;\n onHover: (index: number) => void;\n renderItem?: (item: MentionItem, depth: number) => ReactNode;\n}) {\n const itemId = `mention-option-${item.id}`;\n\n return (\n <div\n {...optionAttrs(itemId, isActive, index)}\n data-suggestion-item=\"\"\n data-suggestion-item-active={isActive ? \"\" : undefined}\n data-has-children={item.hasChildren ? \"\" : undefined}\n onMouseEnter={() => onHover(index)}\n onClick={() => onSelect(item)}\n >\n {renderItem ? (\n renderItem(item, depth)\n ) : (\n <DefaultSuggestionItem item={item} />\n )}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Default item render */\n/* ------------------------------------------------------------------ */\n\nfunction DefaultSuggestionItem({ item }: { item: MentionItem }) {\n return (\n <>\n {item.icon && (\n <span data-suggestion-item-icon=\"\">{item.icon}</span>\n )}\n <span data-suggestion-item-label=\"\">{item.label}</span>\n {item.description && (\n <span data-suggestion-item-description=\"\">{item.description}</span>\n )}\n {item.hasChildren && (\n <span data-suggestion-item-chevron=\"\" aria-hidden=\"true\">\n &rsaquo;\n </span>\n )}\n </>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Popover positioning with edge-aware flipping */\n/* ------------------------------------------------------------------ */\n\nconst POPOVER_HEIGHT_ESTIMATE = 280;\nconst POPOVER_WIDTH_ESTIMATE = 360;\n\nfunction usePopoverPosition(\n clientRect: (() => DOMRect | null) | null,\n): { style: React.CSSProperties; position: \"above\" | \"below\" } {\n if (!clientRect) {\n return { style: { display: \"none\" }, position: \"below\" };\n }\n\n const rect = clientRect();\n if (!rect) {\n return { style: { display: \"none\" }, position: \"below\" };\n }\n\n const viewportH = typeof window !== \"undefined\" ? window.innerHeight : 800;\n const viewportW = typeof window !== \"undefined\" ? window.innerWidth : 1200;\n\n const spaceBelow = viewportH - rect.bottom;\n const shouldFlip = spaceBelow < POPOVER_HEIGHT_ESTIMATE && rect.top > spaceBelow;\n\n let left = rect.left;\n if (left + POPOVER_WIDTH_ESTIMATE > viewportW) {\n left = Math.max(0, viewportW - POPOVER_WIDTH_ESTIMATE);\n }\n\n if (shouldFlip) {\n return {\n style: {\n position: \"fixed\",\n left: `${left}px`,\n bottom: `${viewportH - rect.top + 4}px`,\n zIndex: 50,\n },\n position: \"above\",\n };\n }\n\n return {\n style: {\n position: \"fixed\",\n left: `${left}px`,\n top: `${rect.bottom + 4}px`,\n zIndex: 50,\n },\n position: \"below\",\n };\n}\n","/**\n * Generates ARIA attributes for the suggestion combobox pattern.\n */\n\nexport function comboboxAttrs(expanded: boolean, listboxId: string) {\n return {\n role: \"combobox\" as const,\n \"aria-haspopup\": \"listbox\" as const,\n \"aria-expanded\": expanded,\n \"aria-owns\": expanded ? listboxId : undefined,\n };\n}\n\nexport function listboxAttrs(id: string, label: string) {\n return {\n id,\n role: \"listbox\" as const,\n \"aria-label\": label,\n };\n}\n\nexport function optionAttrs(\n id: string,\n selected: boolean,\n index: number,\n) {\n return {\n id,\n role: \"option\" as const,\n \"aria-selected\": selected,\n \"aria-posinset\": index + 1,\n };\n}\n","import { useCallback, useState } from \"react\";\nimport type { MentionsOutput } from \"../types/MentionsOutput\";\n\nexport function useMentionsContent() {\n const [output, setOutput] = useState<MentionsOutput | null>(null);\n const onChange = useCallback((o: MentionsOutput) => setOutput(o), []);\n\n return {\n output,\n onChange,\n hasContent: (output?.plainText ?? \"\").trim().length > 0,\n };\n}\n"],"mappings":"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","names":["import_react","import_react","import_core","import_state","import_core","StarterKit","Placeholder","editor","import_react","import_react","import_jsx_runtime","MentionsInput","import_react"]}
package/dist/index.mjs CHANGED
@@ -1582,10 +1582,23 @@ var MentionsInput = forwardRef(
1582
1582
  );
1583
1583
  }
1584
1584
  );
1585
+
1586
+ // src/hooks/useMentionsContent.ts
1587
+ import { useCallback as useCallback4, useState as useState3 } from "react";
1588
+ function useMentionsContent() {
1589
+ const [output, setOutput] = useState3(null);
1590
+ const onChange = useCallback4((o) => setOutput(o), []);
1591
+ return {
1592
+ output,
1593
+ onChange,
1594
+ hasContent: (output?.plainText ?? "").trim().length > 0
1595
+ };
1596
+ }
1585
1597
  export {
1586
1598
  MentionsInput,
1587
1599
  extractFromMarkdown,
1588
1600
  parseFromMarkdown,
1589
- serializeToMarkdown
1601
+ serializeToMarkdown,
1602
+ useMentionsContent
1590
1603
  };
1591
1604
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/MentionsInput.tsx","../src/hooks/useMentionsEditor.ts","../src/core/mentionExtension.ts","../src/core/suggestionPlugin.ts","../src/core/markdownSerializer.ts","../src/core/markdownParser.ts","../src/hooks/useSuggestion.ts","../src/utils/debounce.ts","../src/components/SuggestionList.tsx","../src/utils/ariaHelpers.ts"],"sourcesContent":["import React, { forwardRef, useCallback, useId, useImperativeHandle } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { EditorContent } from \"@tiptap/react\";\nimport { useMentionsEditor } from \"../hooks/useMentionsEditor\";\nimport { useSuggestion } from \"../hooks/useSuggestion\";\nimport { SuggestionList } from \"./SuggestionList\";\nimport { comboboxAttrs } from \"../utils/ariaHelpers\";\nimport type {\n MentionsInputProps,\n MentionsInputHandle,\n} from \"../types/MentionsInputProps\";\n\n/**\n * `<MentionsInput>` — the single public component.\n *\n * A structured text editor with typed entity tokens.\n * Consumers register `providers` for each trigger character,\n * and receive structured output via `onChange` and `onSubmit`.\n */\nexport const MentionsInput = forwardRef<MentionsInputHandle, MentionsInputProps>(\n function MentionsInput(\n {\n value,\n providers,\n onChange,\n placeholder = \"Type a message...\",\n autoFocus = false,\n disabled = false,\n className,\n onSubmit,\n clearOnSubmit = true,\n maxLength,\n renderItem,\n renderChip,\n renderEmpty,\n renderLoading,\n renderGroupHeader,\n onFocus,\n onBlur,\n onMentionAdd,\n onMentionRemove,\n onMentionClick,\n onMentionHover,\n minHeight,\n maxHeight,\n submitKey = \"enter\",\n allowTrigger,\n validateMention,\n portalContainer,\n streaming,\n onStreamingComplete,\n },\n ref,\n ) {\n const instanceId = useId();\n const listboxId = `mentions-listbox-${instanceId}`;\n\n const { uiState, actions, callbacksRef } = useSuggestion(providers, {\n onMentionAdd,\n });\n\n const { editor, getOutput, clear, setContent, appendText, focus } = useMentionsEditor({\n providers,\n value,\n onChange,\n onSubmit,\n clearOnSubmit,\n placeholder,\n autoFocus,\n editable: !disabled,\n callbacksRef,\n onFocus,\n onBlur,\n submitKey,\n onMentionRemove,\n onMentionClick,\n onMentionHover,\n allowTrigger,\n validateMention,\n streaming,\n onStreamingComplete,\n });\n\n useImperativeHandle(\n ref,\n () => ({ clear, setContent, appendText, focus, getOutput }),\n [clear, setContent, appendText, focus, getOutput],\n );\n\n const isExpanded = uiState.state !== \"idle\";\n\n const handleHover = useCallback((index: number) => {\n void index;\n }, []);\n\n const handleFocusEditor = useCallback(() => {\n editor?.commands.focus();\n }, [editor]);\n\n const editorStyle: React.CSSProperties = {};\n if (minHeight != null) editorStyle.minHeight = `${minHeight}px`;\n if (maxHeight != null) {\n editorStyle.maxHeight = `${maxHeight}px`;\n editorStyle.overflowY = \"auto\";\n }\n\n const suggestionList = isExpanded ? (\n <SuggestionList\n items={uiState.items}\n activeIndex={uiState.activeIndex}\n breadcrumbs={uiState.breadcrumbs}\n loading={uiState.loading}\n trigger={uiState.trigger}\n query={uiState.query}\n clientRect={uiState.clientRect}\n onSelect={(item) => actions.select(item)}\n onHover={handleHover}\n onGoBack={actions.goBack}\n onSearchNested={actions.searchNested}\n onNavigateUp={actions.navigateUp}\n onNavigateDown={actions.navigateDown}\n onClose={actions.close}\n onFocusEditor={handleFocusEditor}\n renderItem={renderItem}\n renderEmpty={renderEmpty}\n renderLoading={renderLoading}\n renderGroupHeader={renderGroupHeader}\n listboxId={listboxId}\n />\n ) : null;\n\n return (\n <div\n className={className}\n data-mentions-input=\"\"\n data-disabled={disabled ? \"\" : undefined}\n {...comboboxAttrs(isExpanded, listboxId)}\n aria-activedescendant={\n isExpanded && uiState.items[uiState.activeIndex]\n ? `mention-option-${uiState.items[uiState.activeIndex].id}`\n : undefined\n }\n >\n <div style={editorStyle}>\n <EditorContent editor={editor} />\n </div>\n\n {portalContainer\n ? suggestionList && createPortal(suggestionList, portalContainer)\n : suggestionList}\n </div>\n );\n },\n);\n","import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { useEditor } from \"@tiptap/react\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\nimport { Extension } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport { MentionNode } from \"../core/mentionExtension\";\nimport { createSuggestionExtension } from \"../core/suggestionPlugin\";\nimport type { StreamingRef } from \"../core/suggestionPlugin\";\nimport {\n serializeToMarkdown,\n extractTokens,\n extractPlainText,\n} from \"../core/markdownSerializer\";\nimport { parseFromMarkdown } from \"../core/markdownParser\";\nimport type { MentionProvider } from \"../types/MentionProvider\";\nimport type { MentionToken } from \"../types/MentionToken\";\nimport type { MentionsOutput } from \"../types/MentionsOutput\";\nimport type { SuggestionCallbacksRef } from \"../core/suggestionPlugin\";\n\n/* ------------------------------------------------------------------ */\n/* Helper: build MentionsOutput from the current editor */\n/* ------------------------------------------------------------------ */\n\nfunction buildOutput(editor: { getJSON: () => any }): MentionsOutput {\n const json = editor.getJSON();\n return {\n markdown: serializeToMarkdown(json),\n tokens: extractTokens(json),\n plainText: extractPlainText(json),\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Collect all mention tokens from a doc JSON */\n/* ------------------------------------------------------------------ */\n\nfunction collectMentionTokens(doc: any): MentionToken[] {\n const tokens: MentionToken[] = [];\n function walk(node: any) {\n if (node.type === \"mention\" && node.attrs) {\n tokens.push({\n id: node.attrs.id,\n type: node.attrs.entityType ?? node.attrs.type,\n label: node.attrs.label,\n });\n }\n if (node.content) {\n for (const child of node.content) walk(child);\n }\n }\n walk(doc);\n return tokens;\n}\n\n/* ------------------------------------------------------------------ */\n/* Submit keyboard shortcut extension (Cmd/Ctrl+Enter) */\n/* ------------------------------------------------------------------ */\n\nfunction createSubmitExtension(\n onSubmitRef: React.RefObject<((output: MentionsOutput) => void) | undefined>,\n clearOnSubmitRef: React.RefObject<boolean>,\n submitKeyRef: React.RefObject<string>,\n) {\n return Extension.create({\n name: \"submitShortcut\",\n priority: 150,\n\n addKeyboardShortcuts() {\n return {\n \"Mod-Enter\": () => {\n const key = submitKeyRef.current;\n if (key === \"mod+enter\" || key === \"enter\") {\n if (onSubmitRef.current) {\n onSubmitRef.current(buildOutput(this.editor));\n if (clearOnSubmitRef.current) {\n this.editor.commands.clearContent(true);\n }\n }\n return true;\n }\n return false;\n },\n };\n },\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Enter key handling */\n/* ------------------------------------------------------------------ */\n\nconst enterSubmitPluginKey = new PluginKey(\"enterSubmit\");\n\nfunction createEnterExtension(\n onSubmitRef: React.RefObject<((output: MentionsOutput) => void) | undefined>,\n clearOnSubmitRef: React.RefObject<boolean>,\n submitKeyRef: React.RefObject<string>,\n) {\n return Extension.create({\n name: \"enterSubmit\",\n priority: 150,\n\n addProseMirrorPlugins() {\n const editor = this.editor;\n\n return [\n new Plugin({\n key: enterSubmitPluginKey,\n props: {\n handleKeyDown(_view, event) {\n if (event.key !== \"Enter\") return false;\n\n const key = submitKeyRef.current;\n\n if (key === \"none\") return false;\n\n if (key === \"mod+enter\") {\n // Enter = new line (default PM behavior handles it)\n // Shift+Enter also new line\n return false;\n }\n\n // key === \"enter\" (default)\n if (event.shiftKey) {\n editor.commands.splitBlock();\n return true;\n }\n\n if (event.metaKey || event.ctrlKey) return false;\n\n if (onSubmitRef.current) {\n onSubmitRef.current(buildOutput(editor));\n if (clearOnSubmitRef.current) {\n editor.commands.clearContent(true);\n }\n }\n return true;\n },\n },\n }),\n ];\n },\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Mention removal detection plugin */\n/* ------------------------------------------------------------------ */\n\nconst mentionRemovePluginKey = new PluginKey(\"mentionRemove\");\n\nfunction createMentionRemoveExtension(\n onMentionRemoveRef: React.RefObject<((token: MentionToken) => void) | undefined>,\n) {\n return Extension.create({\n name: \"mentionRemoveDetector\",\n priority: 100,\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: mentionRemovePluginKey,\n appendTransaction(transactions, oldState, newState) {\n if (!onMentionRemoveRef.current) return null;\n\n const oldMentions = collectMentionTokens(oldState.doc.toJSON());\n const newMentions = collectMentionTokens(newState.doc.toJSON());\n\n if (oldMentions.length <= newMentions.length) return null;\n\n const newIds = new Set(newMentions.map((m) => m.id));\n for (const m of oldMentions) {\n if (!newIds.has(m.id)) {\n onMentionRemoveRef.current(m);\n }\n }\n\n return null;\n },\n }),\n ];\n },\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Streaming input blocker plugin */\n/* ------------------------------------------------------------------ */\n\nconst streamingBlockPluginKey = new PluginKey(\"streamingBlock\");\n\nfunction createStreamingBlockExtension(streamingRef: StreamingRef) {\n return Extension.create({\n name: \"streamingBlock\",\n priority: 200,\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: streamingBlockPluginKey,\n props: {\n handleKeyDown() {\n return streamingRef.current;\n },\n handleKeyPress() {\n return streamingRef.current;\n },\n handlePaste() {\n return streamingRef.current;\n },\n handleDrop() {\n return streamingRef.current;\n },\n },\n }),\n ];\n },\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Hook */\n/* ------------------------------------------------------------------ */\n\ntype UseMentionsEditorOptions = {\n providers: MentionProvider[];\n value?: string;\n onChange?: (output: MentionsOutput) => void;\n onSubmit?: (output: MentionsOutput) => void;\n clearOnSubmit?: boolean;\n placeholder?: string;\n autoFocus?: boolean;\n editable?: boolean;\n callbacksRef: SuggestionCallbacksRef;\n onFocus?: () => void;\n onBlur?: () => void;\n submitKey?: string;\n onMentionRemove?: (token: MentionToken) => void;\n onMentionClick?: (token: MentionToken, event: MouseEvent) => void;\n onMentionHover?: (token: MentionToken) => ReactNode;\n allowTrigger?: (trigger: string, context: { textBefore: string }) => boolean;\n validateMention?: (token: MentionToken) => boolean | Promise<boolean>;\n streaming?: boolean;\n onStreamingComplete?: (output: MentionsOutput) => void;\n};\n\nexport function useMentionsEditor({\n providers,\n value,\n onChange,\n onSubmit,\n clearOnSubmit = true,\n placeholder,\n autoFocus = false,\n editable = true,\n callbacksRef,\n onFocus,\n onBlur,\n submitKey = \"enter\",\n onMentionRemove,\n onMentionClick,\n onMentionHover,\n allowTrigger,\n validateMention,\n streaming = false,\n onStreamingComplete,\n}: UseMentionsEditorOptions) {\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n const onSubmitRef = useRef(onSubmit);\n onSubmitRef.current = onSubmit;\n\n const clearOnSubmitRef = useRef(clearOnSubmit);\n clearOnSubmitRef.current = clearOnSubmit;\n\n const onFocusRef = useRef(onFocus);\n onFocusRef.current = onFocus;\n\n const onBlurRef = useRef(onBlur);\n onBlurRef.current = onBlur;\n\n const submitKeyRef = useRef(submitKey);\n submitKeyRef.current = submitKey;\n\n const onMentionRemoveRef = useRef(onMentionRemove);\n onMentionRemoveRef.current = onMentionRemove;\n\n const onMentionClickRef = useRef(onMentionClick);\n onMentionClickRef.current = onMentionClick;\n\n const onMentionHoverRef = useRef(onMentionHover);\n onMentionHoverRef.current = onMentionHover;\n\n const allowTriggerRef = useRef(allowTrigger);\n allowTriggerRef.current = allowTrigger;\n\n const validateMentionRef = useRef(validateMention);\n validateMentionRef.current = validateMention;\n\n const onStreamingCompleteRef = useRef(onStreamingComplete);\n onStreamingCompleteRef.current = onStreamingComplete;\n\n // Streaming state — mutable ref so ProseMirror plugins can read it\n // without re-creating the extension chain.\n const streamingRef = useRef<boolean>(streaming);\n streamingRef.current = streaming;\n const prevStreamingRef = useRef(streaming);\n\n // Throttle state for onChange during streaming\n const throttleTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingOutputRef = useRef<MentionsOutput | null>(null);\n\n // Track internal value to avoid controlled-value infinite loops\n const internalMarkdownRef = useRef<string | null>(null);\n\n const initialContent = useMemo(() => {\n if (!value) return undefined;\n return parseFromMarkdown(value);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const triggersKey = providers.map((p) => p.trigger).join(\",\");\n const triggers = useMemo(\n () => providers.map((p) => p.trigger),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [triggersKey],\n );\n\n const suggestionExtension = useMemo(\n () =>\n createSuggestionExtension(\n triggers,\n callbacksRef,\n allowTriggerRef,\n streamingRef,\n ),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [triggersKey],\n );\n\n const submitExt = useMemo(\n () => createSubmitExtension(onSubmitRef, clearOnSubmitRef, submitKeyRef),\n [],\n );\n const enterExt = useMemo(\n () => createEnterExtension(onSubmitRef, clearOnSubmitRef, submitKeyRef),\n [],\n );\n const mentionRemoveExt = useMemo(\n () => createMentionRemoveExtension(onMentionRemoveRef),\n [],\n );\n\n const streamingBlockExt = useMemo(\n () => createStreamingBlockExtension(streamingRef),\n [],\n );\n\n const mentionNodeExt = useMemo(\n () =>\n MentionNode.configure({\n onClickRef: onMentionClickRef,\n onHoverRef: onMentionHoverRef,\n }),\n [],\n );\n\n const editor = useEditor({\n extensions: [\n StarterKit.configure({\n heading: false,\n blockquote: false,\n codeBlock: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n horizontalRule: false,\n hardBreak: false,\n }),\n Placeholder.configure({\n placeholder: ({ editor }) =>\n editor.isEmpty ? (placeholder ?? \"Type a message...\") : \"\",\n showOnlyCurrent: true,\n }),\n mentionNodeExt,\n suggestionExtension,\n submitExt,\n enterExt,\n mentionRemoveExt,\n streamingBlockExt,\n ],\n content: initialContent,\n autofocus: autoFocus ? \"end\" : false,\n editable,\n editorProps: {\n attributes: {\n class: \"mentions-editor\",\n },\n },\n onUpdate: ({ editor }) => {\n const output = buildOutput(editor);\n internalMarkdownRef.current = output.markdown;\n\n if (streamingRef.current) {\n pendingOutputRef.current = output;\n if (!throttleTimerRef.current) {\n throttleTimerRef.current = setTimeout(() => {\n throttleTimerRef.current = null;\n if (pendingOutputRef.current) {\n onChangeRef.current?.(pendingOutputRef.current);\n pendingOutputRef.current = null;\n }\n }, 150);\n }\n } else {\n onChangeRef.current?.(output);\n }\n },\n onFocus: () => {\n onFocusRef.current?.();\n },\n onBlur: () => {\n onBlurRef.current?.();\n },\n });\n\n // Flush throttled onChange and fire onStreamingComplete when streaming ends\n useEffect(() => {\n if (prevStreamingRef.current && !streaming && editor) {\n if (throttleTimerRef.current) {\n clearTimeout(throttleTimerRef.current);\n throttleTimerRef.current = null;\n }\n const output = buildOutput(editor);\n onChangeRef.current?.(output);\n onStreamingCompleteRef.current?.(output);\n pendingOutputRef.current = null;\n }\n prevStreamingRef.current = streaming;\n }, [streaming, editor]);\n\n // Clean up throttle timer on unmount\n useEffect(() => {\n return () => {\n if (throttleTimerRef.current) {\n clearTimeout(throttleTimerRef.current);\n }\n };\n }, []);\n\n // Sync editable state\n useEffect(() => {\n if (editor && editor.isEditable !== editable) {\n editor.setEditable(editable);\n }\n }, [editor, editable]);\n\n // Controlled value: update editor when external value changes\n useEffect(() => {\n if (!editor || value === undefined) return;\n if (value === internalMarkdownRef.current) return;\n const doc = parseFromMarkdown(value);\n editor.commands.setContent(doc);\n internalMarkdownRef.current = value;\n }, [editor, value]);\n\n // Mention validation\n useEffect(() => {\n if (!editor || !validateMention) return;\n\n const runValidation = async () => {\n const doc = editor.getJSON();\n const tokens = collectMentionTokens(doc);\n const invalidIds = new Set<string>();\n\n await Promise.all(\n tokens.map(async (token) => {\n const valid = await validateMention(token);\n if (!valid) invalidIds.add(token.id);\n }),\n );\n\n editor.view.dom.querySelectorAll(\"[data-mention]\").forEach((el) => {\n const id = el.getAttribute(\"data-id\");\n if (id && invalidIds.has(id)) {\n el.setAttribute(\"data-mention-invalid\", \"\");\n } else {\n el.removeAttribute(\"data-mention-invalid\");\n }\n });\n };\n\n runValidation();\n }, [editor, validateMention]);\n\n /* ---------------------------------------------------------------- */\n /* Imperative methods */\n /* ---------------------------------------------------------------- */\n\n const clear = useCallback(() => {\n editor?.commands.clearContent(true);\n }, [editor]);\n\n const setContent = useCallback(\n (markdown: string) => {\n if (!editor) return;\n const doc = parseFromMarkdown(markdown);\n editor.commands.setContent(doc);\n internalMarkdownRef.current = markdown;\n if (streamingRef.current) {\n editor.commands.focus(\"end\");\n }\n },\n [editor],\n );\n\n const appendText = useCallback(\n (text: string) => {\n if (!editor) return;\n const endPos = editor.state.doc.content.size - 1;\n editor.commands.insertContentAt(endPos, text);\n if (streamingRef.current) {\n editor.commands.focus(\"end\");\n }\n },\n [editor],\n );\n\n const focus = useCallback(() => {\n editor?.commands.focus(\"end\");\n }, [editor]);\n\n const getOutput = useCallback((): MentionsOutput | null => {\n if (!editor) return null;\n return buildOutput(editor);\n }, [editor]);\n\n return { editor, getOutput, clear, setContent, appendText, focus };\n}\n","import { mergeAttributes, Node } from \"@tiptap/core\";\nimport type { ReactNode } from \"react\";\nimport type { MentionToken } from \"../types/MentionToken\";\n\nexport interface MentionNodeAttrs {\n id: string;\n label: string;\n entityType: string;\n rootLabel?: string | null;\n}\n\nconst DEFAULT_PREFIXES: Record<string, string> = {\n workspace: \"@\",\n contract: \"@\",\n file: \"#\",\n web: \":\",\n};\n\nexport type MentionNodeOptions = {\n onClickRef?: React.RefObject<((token: MentionToken, event: MouseEvent) => void) | undefined>;\n onHoverRef?: React.RefObject<((token: MentionToken) => ReactNode) | undefined>;\n};\n\nexport const MentionNode = Node.create<MentionNodeOptions>({\n name: \"mention\",\n group: \"inline\",\n inline: true,\n atom: true,\n selectable: true,\n draggable: false,\n\n addOptions() {\n return {\n onClickRef: undefined,\n onHoverRef: undefined,\n };\n },\n\n addAttributes() {\n return {\n id: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-id\"),\n renderHTML: (attributes) => ({ \"data-id\": attributes.id }),\n },\n label: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-label\"),\n renderHTML: (attributes) => ({ \"data-label\": attributes.label }),\n },\n entityType: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-type\"),\n renderHTML: (attributes) => ({ \"data-type\": attributes.entityType }),\n },\n rootLabel: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-root-label\"),\n renderHTML: (attributes) =>\n attributes.rootLabel\n ? { \"data-root-label\": attributes.rootLabel }\n : {},\n },\n };\n },\n\n parseHTML() {\n return [{ tag: 'span[data-mention]' }];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const entityType = node.attrs.entityType as string;\n const label = node.attrs.label as string;\n const prefix = DEFAULT_PREFIXES[entityType] ?? \"@\";\n const display = `${prefix}${label}`;\n\n const hasClick = !!this.options.onClickRef?.current;\n const extraAttrs: Record<string, string> = {};\n if (hasClick) {\n extraAttrs[\"data-mention-clickable\"] = \"\";\n }\n\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n \"data-mention\": \"\",\n class: \"mention-chip\",\n ...extraAttrs,\n }),\n display,\n ];\n },\n\n renderText({ node }) {\n const entityType = node.attrs.entityType as string;\n const label = node.attrs.label as string;\n const prefix = DEFAULT_PREFIXES[entityType] ?? \"@\";\n return `${prefix}${label}`;\n },\n\n addNodeView() {\n const options = this.options;\n\n return ({ node, HTMLAttributes }) => {\n const entityType = node.attrs.entityType as string;\n const label = node.attrs.label as string;\n const id = node.attrs.id as string;\n const prefix = DEFAULT_PREFIXES[entityType] ?? \"@\";\n\n const dom = document.createElement(\"span\");\n Object.entries(\n mergeAttributes(HTMLAttributes, {\n \"data-mention\": \"\",\n \"data-type\": entityType,\n \"data-id\": id,\n class: \"mention-chip\",\n }),\n ).forEach(([key, val]) => {\n if (val != null && val !== false) dom.setAttribute(key, String(val));\n });\n\n dom.textContent = `${prefix}${label}`;\n\n if (options.onClickRef?.current) {\n dom.setAttribute(\"data-mention-clickable\", \"\");\n dom.style.cursor = \"pointer\";\n }\n\n dom.addEventListener(\"click\", (event) => {\n const handler = options.onClickRef?.current;\n if (handler) {\n event.preventDefault();\n event.stopPropagation();\n handler({ id, type: entityType, label }, event);\n }\n });\n\n // Hover tooltip\n let tooltip: HTMLElement | null = null;\n\n dom.addEventListener(\"mouseenter\", () => {\n const hoverFn = options.onHoverRef?.current;\n if (!hoverFn) return;\n\n const content = hoverFn({ id, type: entityType, label });\n if (!content) return;\n\n tooltip = document.createElement(\"div\");\n tooltip.setAttribute(\"data-mention-tooltip\", \"\");\n tooltip.textContent = typeof content === \"string\" ? content : \"\";\n dom.style.position = \"relative\";\n dom.appendChild(tooltip);\n });\n\n dom.addEventListener(\"mouseleave\", () => {\n if (tooltip && tooltip.parentNode) {\n tooltip.parentNode.removeChild(tooltip);\n tooltip = null;\n }\n });\n\n return { dom };\n };\n },\n\n addKeyboardShortcuts() {\n return {\n Backspace: () =>\n this.editor.commands.command(({ tr, state }) => {\n let isMention = false;\n const { selection } = state;\n const { empty, anchor } = selection;\n\n if (!empty) return false;\n\n state.doc.nodesBetween(anchor - 1, anchor, (node, pos) => {\n if (node.type.name === this.name) {\n isMention = true;\n tr.insertText(\"\", pos, pos + node.nodeSize);\n }\n });\n\n return isMention;\n }),\n };\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport type { EditorView } from \"@tiptap/pm/view\";\n\n/* ------------------------------------------------------------------ */\n/* Suggestion state types */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionState =\n | \"idle\"\n | \"loading\"\n | \"showing\"\n | \"drilling\"\n | \"inserting\";\n\n/* ------------------------------------------------------------------ */\n/* Callbacks the React layer implements */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionCallbacks = {\n onStart: (props: SuggestionCallbackProps) => void;\n onUpdate: (props: SuggestionCallbackProps) => void;\n onExit: () => void;\n onKeyDown: (props: { event: KeyboardEvent }) => boolean;\n};\n\nexport type SuggestionCallbackProps = {\n query: string;\n trigger: string;\n clientRect: (() => DOMRect | null) | null;\n range: { from: number; to: number };\n command: (attrs: Record<string, unknown>) => void;\n};\n\n/* ------------------------------------------------------------------ */\n/* Trigger detection */\n/* ------------------------------------------------------------------ */\n\ntype TriggerMatch = {\n trigger: string;\n query: string;\n from: number;\n to: number;\n textBefore: string;\n};\n\nfunction detectTrigger(\n text: string,\n cursorPos: number,\n docStartPos: number,\n triggers: string[],\n): TriggerMatch | null {\n const relCursor = cursorPos - docStartPos;\n const before = text.slice(0, relCursor);\n\n for (let i = before.length - 1; i >= 0; i--) {\n const ch = before[i];\n if (ch === \"\\n\") return null;\n\n for (const trigger of triggers) {\n if (before.substring(i, i + trigger.length) === trigger) {\n if (i === 0 || /\\s/.test(before[i - 1])) {\n const query = before.slice(i + trigger.length);\n return {\n trigger,\n query,\n from: docStartPos + i,\n to: cursorPos,\n textBefore: before.slice(0, i),\n };\n }\n }\n }\n }\n\n return null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Plugin key */\n/* ------------------------------------------------------------------ */\n\nconst suggestionPluginKey = new PluginKey(\"mentionSuggestion\");\n\n/* ------------------------------------------------------------------ */\n/* Ref-based callback container (avoids stale closure issues) */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionCallbacksRef = { current: SuggestionCallbacks };\n\nexport type AllowTriggerRef = {\n current?: (trigger: string, context: { textBefore: string }) => boolean;\n};\n\nexport type StreamingRef = { current: boolean };\n\n/* ------------------------------------------------------------------ */\n/* Build the single multi-trigger suggestion extension */\n/* ------------------------------------------------------------------ */\n\nexport function createSuggestionExtension(\n triggers: string[],\n callbacksRef: SuggestionCallbacksRef,\n allowTriggerRef?: AllowTriggerRef,\n streamingRef?: StreamingRef,\n) {\n return Extension.create({\n name: \"mentionSuggestion\",\n priority: 200,\n\n addProseMirrorPlugins() {\n const editor = this.editor;\n let active = false;\n let lastQuery: string | null = null;\n let lastTrigger: string | null = null;\n\n const getClientRect = (\n view: EditorView,\n from: number,\n ): (() => DOMRect | null) => {\n return () => {\n try {\n const coords = view.coordsAtPos(from);\n return new DOMRect(\n coords.left,\n coords.top,\n 0,\n coords.bottom - coords.top,\n );\n } catch {\n return null;\n }\n };\n };\n\n const makeCommand = (range: { from: number; to: number }) => {\n return (attrs: Record<string, unknown>) => {\n editor\n .chain()\n .focus()\n .insertContentAt(range, [\n {\n type: \"mention\",\n attrs: {\n id: attrs.id,\n label: attrs.label,\n entityType: attrs.entityType,\n rootLabel: attrs.rootLabel ?? null,\n },\n },\n { type: \"text\", text: \" \" },\n ])\n .run();\n };\n };\n\n const plugin = new Plugin({\n key: suggestionPluginKey,\n\n props: {\n handleKeyDown(_view, event) {\n if (!active) return false;\n return callbacksRef.current.onKeyDown({ event });\n },\n },\n\n view() {\n return {\n update(view, _prevState) {\n if (streamingRef?.current) {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n return;\n }\n\n const { state } = view;\n const { selection } = state;\n\n if (!selection.empty) {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n return;\n }\n\n const $pos = selection.$from;\n const textBlock = $pos.parent;\n\n if (!textBlock.isTextblock) {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n return;\n }\n\n const blockStart = $pos.start();\n const blockText = textBlock.textContent;\n const cursorPos = $pos.pos;\n\n const match = detectTrigger(blockText, cursorPos, blockStart, triggers);\n\n if (match) {\n // Check allowTrigger gate\n if (allowTriggerRef?.current) {\n const allowed = allowTriggerRef.current(match.trigger, {\n textBefore: match.textBefore,\n });\n if (!allowed) {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n return;\n }\n }\n\n const range = { from: match.from, to: match.to };\n const props: SuggestionCallbackProps = {\n query: match.query,\n trigger: match.trigger,\n clientRect: getClientRect(view, match.from),\n range,\n command: makeCommand(range),\n };\n\n if (!active) {\n active = true;\n lastQuery = match.query;\n lastTrigger = match.trigger;\n callbacksRef.current.onStart(props);\n } else if (\n match.query !== lastQuery ||\n match.trigger !== lastTrigger\n ) {\n lastQuery = match.query;\n lastTrigger = match.trigger;\n callbacksRef.current.onUpdate(props);\n }\n } else {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n }\n },\n\n destroy() {\n if (active) {\n callbacksRef.current.onExit();\n }\n },\n };\n },\n });\n\n return [plugin];\n },\n });\n}\n","import type { JSONContent } from \"@tiptap/core\";\nimport type { MentionToken } from \"../types/MentionToken\";\n\n/**\n * Serialize a Tiptap JSON document to a markdown string.\n *\n * Mention nodes are encoded as `@[label](id)` or `@rootLabel[label](id)` when the mention has a root (e.g. file under workspace).\n * All other text passes through verbatim.\n */\nexport function serializeToMarkdown(doc: JSONContent): string {\n if (!doc.content) return \"\";\n\n const parts: string[] = [];\n\n for (const block of doc.content) {\n if (block.type === \"paragraph\") {\n parts.push(serializeParagraph(block));\n } else if (block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n\n return parts.join(\"\\n\");\n}\n\nfunction serializeParagraph(node: JSONContent): string {\n if (!node.content) return \"\";\n\n return node.content\n .map((child) => {\n if (child.type === \"mention\") {\n const { id, label, entityType, rootLabel } = child.attrs ?? {};\n const idPart =\n entityType && entityType !== \"unknown\"\n ? `${entityType}:${id}`\n : id;\n if (rootLabel != null && rootLabel !== \"\") {\n return `@${rootLabel}[${label}](${idPart})`;\n }\n return `@[${label}](${idPart})`;\n }\n return child.text ?? \"\";\n })\n .join(\"\");\n}\n\n/**\n * Extract all `MentionToken`s from a Tiptap JSON document, in document order.\n */\nexport function extractTokens(doc: JSONContent): MentionToken[] {\n const tokens: MentionToken[] = [];\n\n function walk(node: JSONContent) {\n if (node.type === \"mention\" && node.attrs) {\n tokens.push({\n id: node.attrs.id as string,\n type: node.attrs.entityType as string,\n label: node.attrs.label as string,\n });\n }\n if (node.content) {\n for (const child of node.content) {\n walk(child);\n }\n }\n }\n\n walk(doc);\n return tokens;\n}\n\n/**\n * Extract plain text from a Tiptap JSON document.\n * Mention nodes are replaced with their label (no trigger prefix in plain text).\n */\nexport function extractPlainText(doc: JSONContent): string {\n if (!doc.content) return \"\";\n\n const parts: string[] = [];\n\n for (const block of doc.content) {\n if (block.type === \"paragraph\") {\n parts.push(extractParagraphText(block));\n }\n }\n\n return parts.join(\"\\n\");\n}\n\nfunction extractParagraphText(node: JSONContent): string {\n if (!node.content) return \"\";\n\n return node.content\n .map((child) => {\n if (child.type === \"mention\") {\n return child.attrs?.label ?? \"\";\n }\n return child.text ?? \"\";\n })\n .join(\"\");\n}\n","import type { JSONContent } from \"@tiptap/core\";\nimport { extractTokens, extractPlainText } from \"./markdownSerializer\";\nimport type { MentionToken } from \"../types/MentionToken\";\n\n/**\n * Regex matching mention tokens:\n * - `@[label](id)` or `@[label](type:id)`\n * - `@rootLabel[label](type:id)` when the mention has a root (e.g. file under workspace).\n * Groups: (1) rootLabel (may be empty string), (2) label, (3) optional entityType, (4) id.\n *\n * `[^\\[@]` prevents the rootLabel from crossing `@` boundaries so that plain\n * `@word` in running text is never swallowed into a false rootLabel match.\n */\nconst MENTION_RE = /@([^\\[@]*)\\[([^\\]]+)\\]\\((?:([^:)]+):)?([^)]+)\\)/g;\n\n/**\n * Parse a markdown string (with `@[label](id)`, `@[label](type:id)`, or `@rootLabel[label](id)` tokens)\n * into a Tiptap-compatible JSON document.\n */\nexport function parseFromMarkdown(markdown: string): JSONContent {\n const lines = markdown.split(\"\\n\");\n\n const content: JSONContent[] = lines.map((line) => {\n const children = parseLine(line);\n return children.length > 0\n ? { type: \"paragraph\", content: children }\n : { type: \"paragraph\" };\n });\n\n return { type: \"doc\", content };\n}\n\nfunction parseLine(line: string): JSONContent[] {\n const nodes: JSONContent[] = [];\n let lastIndex = 0;\n\n // Reset regex state\n MENTION_RE.lastIndex = 0;\n\n let match: RegExpExecArray | null;\n while ((match = MENTION_RE.exec(line)) !== null) {\n const fullMatch = match[0];\n const rootLabel = match[1] || null;\n const label = match[2];\n const entityType = match[3] ?? \"unknown\";\n const id = match[4];\n\n // Text before this mention\n if (match.index > lastIndex) {\n nodes.push({\n type: \"text\",\n text: line.slice(lastIndex, match.index),\n });\n }\n\n // Mention node\n nodes.push({\n type: \"mention\",\n attrs: {\n id,\n label,\n entityType,\n rootLabel,\n },\n });\n\n lastIndex = match.index + fullMatch.length;\n }\n\n // Trailing text\n if (lastIndex < line.length) {\n nodes.push({\n type: \"text\",\n text: line.slice(lastIndex),\n });\n }\n\n return nodes;\n}\n\n/* ------------------------------------------------------------------ */\n/* Convenience helper: markdown → tokens + plain text */\n/* ------------------------------------------------------------------ */\n\n/**\n * Parse a markdown string and extract structured data from it.\n *\n * This is a convenience wrapper that combines `parseFromMarkdown`,\n * `extractTokens`, and `extractPlainText` into a single call.\n *\n * @example\n * ```ts\n * const { tokens, plainText } = extractFromMarkdown(\n * \"Check @Marketing[Q4 Strategy.pdf](file_1) for details\"\n * );\n * // tokens → [{ id: \"file_1\", type: \"unknown\", label: \"Q4 Strategy.pdf\" }]\n * // plainText → \"Check Q4 Strategy.pdf for details\"\n * ```\n */\nexport function extractFromMarkdown(markdown: string): {\n tokens: MentionToken[];\n plainText: string;\n} {\n const doc = parseFromMarkdown(markdown);\n return {\n tokens: extractTokens(doc),\n plainText: extractPlainText(doc),\n };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { MentionItem, MentionProvider } from \"../types/MentionProvider\";\nimport type { MentionToken } from \"../types/MentionToken\";\nimport type {\n SuggestionCallbackProps,\n SuggestionCallbacks,\n SuggestionCallbacksRef,\n SuggestionState,\n} from \"../core/suggestionPlugin\";\nimport { debounce } from \"../utils/debounce\";\n\n/* ------------------------------------------------------------------ */\n/* Public state exposed to the UI layer */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionUIState = {\n state: SuggestionState;\n items: MentionItem[];\n breadcrumbs: MentionItem[];\n activeIndex: number;\n loading: boolean;\n clientRect: (() => DOMRect | null) | null;\n trigger: string | null;\n query: string;\n};\n\nexport type SuggestionActions = {\n navigateUp: () => void;\n navigateDown: () => void;\n select: (item?: MentionItem) => void;\n goBack: () => void;\n close: () => void;\n searchNested: (query: string) => void;\n};\n\nexport type SuggestionHookOptions = {\n onMentionAdd?: (token: MentionToken) => void;\n};\n\nconst IDLE_STATE: SuggestionUIState = {\n state: \"idle\",\n items: [],\n breadcrumbs: [],\n activeIndex: 0,\n loading: false,\n clientRect: null,\n trigger: null,\n query: \"\",\n};\n\n/* ------------------------------------------------------------------ */\n/* Hook */\n/* ------------------------------------------------------------------ */\n\nexport function useSuggestion(\n providers: MentionProvider[],\n options: SuggestionHookOptions = {},\n) {\n const [uiState, setUIState] = useState<SuggestionUIState>(IDLE_STATE);\n\n const stateRef = useRef(uiState);\n stateRef.current = uiState;\n\n const providersRef = useRef(providers);\n providersRef.current = providers;\n\n const onMentionAddRef = useRef(options.onMentionAdd);\n onMentionAddRef.current = options.onMentionAdd;\n\n const commandRef = useRef<((attrs: Record<string, unknown>) => void) | null>(\n null,\n );\n const providerRef = useRef<MentionProvider | null>(null);\n\n const debouncedFetchRef = useRef<ReturnType<typeof debounce> | null>(null);\n\n useEffect(() => {\n return () => {\n debouncedFetchRef.current?.cancel();\n };\n }, []);\n\n /* ---------------------------------------------------------------- */\n /* Fetch items from the provider */\n /* ---------------------------------------------------------------- */\n\n const fetchItems = useCallback(\n async (\n provider: MentionProvider,\n query: string,\n parent?: MentionItem,\n useSearchAll?: boolean,\n ) => {\n setUIState((prev) => ({ ...prev, loading: true, state: \"loading\" }));\n\n try {\n let items: MentionItem[];\n\n if (useSearchAll && provider.searchAll) {\n items = await provider.searchAll(query);\n } else if (parent && provider.getChildren) {\n items = await provider.getChildren(parent, query);\n } else {\n items = await provider.getRootItems(query);\n }\n\n setUIState((prev) => ({\n ...prev,\n items,\n loading: false,\n state: \"showing\",\n activeIndex: 0,\n }));\n } catch {\n setUIState((prev) => ({\n ...prev,\n items: [],\n loading: false,\n state: \"showing\",\n }));\n }\n },\n [],\n );\n\n const scheduleFetch = useCallback(\n (\n provider: MentionProvider,\n query: string,\n parent?: MentionItem,\n useSearchAll?: boolean,\n ) => {\n debouncedFetchRef.current?.cancel();\n\n const ms = provider.debounceMs;\n if (ms && ms > 0) {\n setUIState((prev) => ({ ...prev, loading: true }));\n const debouncedFn = debounce(() => {\n fetchItems(provider, query, parent, useSearchAll);\n }, ms);\n debouncedFetchRef.current = debouncedFn;\n debouncedFn();\n } else {\n fetchItems(provider, query, parent, useSearchAll);\n }\n },\n [fetchItems],\n );\n\n /* ---------------------------------------------------------------- */\n /* Suggestion plugin callbacks */\n /* ---------------------------------------------------------------- */\n\n const onStart = useCallback(\n (props: SuggestionCallbackProps) => {\n const provider = providersRef.current.find(\n (p) => p.trigger === props.trigger,\n );\n if (!provider) return;\n\n providerRef.current = provider;\n commandRef.current = props.command;\n\n setUIState({\n state: \"loading\",\n items: [],\n breadcrumbs: [],\n activeIndex: 0,\n loading: true,\n clientRect: props.clientRect,\n trigger: props.trigger,\n query: props.query,\n });\n\n if (!props.query.trim() && provider.getRecentItems) {\n provider.getRecentItems().then((recentItems) => {\n const tagged = recentItems.map((item) => ({\n ...item,\n group: item.group ?? \"Recent\",\n }));\n setUIState((prev) => ({\n ...prev,\n items: tagged,\n loading: false,\n state: \"showing\",\n activeIndex: 0,\n }));\n }).catch(() => {\n scheduleFetch(provider, props.query);\n });\n return;\n }\n\n if (props.query.trim() && provider.searchAll) {\n scheduleFetch(provider, props.query, undefined, true);\n } else {\n scheduleFetch(provider, props.query);\n }\n },\n [scheduleFetch],\n );\n\n const onUpdate = useCallback(\n (props: SuggestionCallbackProps) => {\n const provider = providerRef.current;\n if (!provider) return;\n\n commandRef.current = props.command;\n const current = stateRef.current;\n\n if (current.breadcrumbs.length > 0) {\n setUIState((prev) => ({\n ...prev,\n breadcrumbs: [],\n clientRect: props.clientRect,\n query: props.query,\n activeIndex: 0,\n }));\n } else {\n setUIState((prev) => ({\n ...prev,\n clientRect: props.clientRect,\n query: props.query,\n }));\n }\n\n if (props.query.trim() && provider.searchAll) {\n scheduleFetch(provider, props.query, undefined, true);\n } else if (!props.query.trim() && provider.getRecentItems) {\n provider.getRecentItems().then((recentItems) => {\n const tagged = recentItems.map((item) => ({\n ...item,\n group: item.group ?? \"Recent\",\n }));\n setUIState((prev) => ({\n ...prev,\n items: tagged,\n loading: false,\n state: \"showing\",\n activeIndex: 0,\n }));\n }).catch(() => {\n scheduleFetch(provider, props.query);\n });\n } else {\n scheduleFetch(provider, props.query);\n }\n },\n [scheduleFetch],\n );\n\n const onExit = useCallback(() => {\n debouncedFetchRef.current?.cancel();\n providerRef.current = null;\n commandRef.current = null;\n setUIState(IDLE_STATE);\n }, []);\n\n /* ---------------------------------------------------------------- */\n /* Navigation actions */\n /* ---------------------------------------------------------------- */\n\n const navigateUp = useCallback(() => {\n setUIState((prev) => ({\n ...prev,\n activeIndex: Math.max(0, prev.activeIndex - 1),\n }));\n }, []);\n\n const navigateDown = useCallback(() => {\n setUIState((prev) => ({\n ...prev,\n activeIndex: Math.min(prev.items.length - 1, prev.activeIndex + 1),\n }));\n }, []);\n\n const select = useCallback(\n (item?: MentionItem) => {\n const current = stateRef.current;\n const selected = item ?? current.items[current.activeIndex];\n if (!selected) return;\n\n const provider = providerRef.current;\n\n if (selected.hasChildren && provider?.getChildren) {\n setUIState((prev) => ({\n ...prev,\n state: \"drilling\",\n breadcrumbs: [...prev.breadcrumbs, selected],\n items: [],\n activeIndex: 0,\n query: \"\",\n }));\n\n fetchItems(provider, \"\", selected);\n return;\n }\n\n const rootLabel =\n current.breadcrumbs.length > 0\n ? current.breadcrumbs[0].label\n : selected.rootLabel ?? null;\n\n if (commandRef.current) {\n commandRef.current({\n id: selected.id,\n label: selected.label,\n entityType: selected.type,\n rootLabel,\n });\n }\n\n onMentionAddRef.current?.({\n id: selected.id,\n type: selected.type,\n label: selected.label,\n });\n },\n [fetchItems],\n );\n\n const goBack = useCallback(() => {\n const provider = providerRef.current;\n if (!provider) return;\n\n setUIState((prev) => {\n const newBreadcrumbs = prev.breadcrumbs.slice(0, -1);\n const parent = newBreadcrumbs[newBreadcrumbs.length - 1];\n\n if (parent) {\n fetchItems(provider, \"\", parent);\n } else {\n fetchItems(provider, prev.query);\n }\n\n return {\n ...prev,\n breadcrumbs: newBreadcrumbs,\n items: [],\n activeIndex: 0,\n state: \"loading\" as const,\n };\n });\n }, [fetchItems]);\n\n const close = useCallback(() => {\n debouncedFetchRef.current?.cancel();\n setUIState(IDLE_STATE);\n }, []);\n\n /* ---------------------------------------------------------------- */\n /* Nested search */\n /* ---------------------------------------------------------------- */\n\n const searchNested = useCallback(\n (query: string) => {\n const provider = providerRef.current;\n if (!provider) return;\n\n const current = stateRef.current;\n const parent = current.breadcrumbs[current.breadcrumbs.length - 1];\n if (parent) {\n scheduleFetch(provider, query, parent);\n }\n },\n [scheduleFetch],\n );\n\n /* ---------------------------------------------------------------- */\n /* Keyboard handler */\n /* ---------------------------------------------------------------- */\n\n const onKeyDown = useCallback(\n ({ event }: { event: KeyboardEvent }): boolean => {\n const current = stateRef.current;\n if (current.state === \"idle\") return false;\n\n switch (event.key) {\n case \"ArrowUp\":\n event.preventDefault();\n navigateUp();\n return true;\n case \"ArrowDown\":\n event.preventDefault();\n navigateDown();\n return true;\n case \"Enter\": {\n event.preventDefault();\n const selectedItem = current.items[current.activeIndex];\n if (selectedItem) {\n select(selectedItem);\n }\n return true;\n }\n case \"Tab\": {\n event.preventDefault();\n const selectedItem = current.items[current.activeIndex];\n if (selectedItem) {\n select(selectedItem);\n }\n return true;\n }\n case \"ArrowRight\": {\n const activeItem = current.items[current.activeIndex];\n if (activeItem?.hasChildren) {\n event.preventDefault();\n select(activeItem);\n return true;\n }\n return false;\n }\n case \"ArrowLeft\":\n if (current.breadcrumbs.length > 0) {\n event.preventDefault();\n goBack();\n return true;\n }\n return false;\n case \"Escape\":\n event.preventDefault();\n close();\n return true;\n default:\n return false;\n }\n },\n [navigateUp, navigateDown, select, goBack, close],\n );\n\n /* ---------------------------------------------------------------- */\n /* Build a ref that always points to the latest callbacks. */\n /* ---------------------------------------------------------------- */\n\n const callbacksRef: SuggestionCallbacksRef = useRef<SuggestionCallbacks>({\n onStart,\n onUpdate,\n onExit,\n onKeyDown,\n });\n\n callbacksRef.current = { onStart, onUpdate, onExit, onKeyDown };\n\n const actions: SuggestionActions = {\n navigateUp,\n navigateDown,\n select,\n goBack,\n close,\n searchNested,\n };\n\n return { uiState, actions, callbacksRef };\n}\n","/**\n * Returns a debounced version of `fn` that delays invocation until\n * `ms` milliseconds have elapsed since the last call.\n * Call `.cancel()` on the returned function to clear any pending timer.\n */\nexport function debounce<T extends (...args: any[]) => void>(\n fn: T,\n ms: number,\n): T & { cancel: () => void } {\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const debounced = ((...args: any[]) => {\n if (timer != null) clearTimeout(timer);\n timer = setTimeout(() => {\n timer = null;\n fn(...args);\n }, ms);\n }) as T & { cancel: () => void };\n\n debounced.cancel = () => {\n if (timer != null) {\n clearTimeout(timer);\n timer = null;\n }\n };\n\n return debounced;\n}\n","import React, { useEffect, useRef, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { MentionItem } from \"../types/MentionProvider\";\nimport { listboxAttrs, optionAttrs } from \"../utils/ariaHelpers\";\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionListProps = {\n items: MentionItem[];\n activeIndex: number;\n breadcrumbs: MentionItem[];\n loading: boolean;\n trigger: string | null;\n query: string;\n clientRect: (() => DOMRect | null) | null;\n onSelect: (item: MentionItem) => void;\n onHover: (index: number) => void;\n onGoBack: () => void;\n onSearchNested?: (query: string) => void;\n onNavigateUp?: () => void;\n onNavigateDown?: () => void;\n onClose?: () => void;\n onFocusEditor?: () => void;\n renderItem?: (item: MentionItem, depth: number) => ReactNode;\n renderEmpty?: (query: string) => ReactNode;\n renderLoading?: () => ReactNode;\n renderGroupHeader?: (group: string) => ReactNode;\n listboxId: string;\n};\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport function SuggestionList({\n items,\n activeIndex,\n breadcrumbs,\n loading,\n trigger,\n query,\n clientRect,\n onSelect,\n onHover,\n onGoBack,\n onSearchNested,\n onNavigateUp,\n onNavigateDown,\n onClose,\n onFocusEditor,\n renderItem,\n renderEmpty,\n renderLoading,\n renderGroupHeader,\n listboxId,\n}: SuggestionListProps) {\n const listRef = useRef<HTMLDivElement>(null);\n const searchInputRef = useRef<HTMLInputElement>(null);\n const depth = breadcrumbs.length;\n const [nestedQuery, setNestedQuery] = useState(\"\");\n\n const breadcrumbKey = breadcrumbs.map((b) => b.id).join(\"/\");\n const prevBreadcrumbKey = useRef(breadcrumbKey);\n useEffect(() => {\n if (prevBreadcrumbKey.current !== breadcrumbKey) {\n setNestedQuery(\"\");\n prevBreadcrumbKey.current = breadcrumbKey;\n }\n }, [breadcrumbKey]);\n\n const prevBreadcrumbsLen = useRef(breadcrumbs.length);\n useEffect(() => {\n if (prevBreadcrumbsLen.current > 0 && breadcrumbs.length === 0) {\n onFocusEditor?.();\n } else if (breadcrumbs.length > 0 && searchInputRef.current) {\n requestAnimationFrame(() => searchInputRef.current?.focus());\n }\n prevBreadcrumbsLen.current = breadcrumbs.length;\n }, [breadcrumbKey, breadcrumbs.length, onFocusEditor]);\n\n useEffect(() => {\n if (!listRef.current) return;\n const active = listRef.current.querySelector('[aria-selected=\"true\"]');\n active?.scrollIntoView({ block: \"nearest\" });\n }, [activeIndex]);\n\n const { style, position } = usePopoverPosition(clientRect);\n\n const activeQuery = breadcrumbs.length > 0 ? nestedQuery : query;\n const showEmpty = !loading && items.length === 0 && activeQuery.trim().length > 0;\n\n if (items.length === 0 && !loading && !showEmpty) return null;\n\n const handleSearchKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n switch (e.key) {\n case \"ArrowDown\":\n e.preventDefault();\n onNavigateDown?.();\n break;\n case \"ArrowUp\":\n e.preventDefault();\n onNavigateUp?.();\n break;\n case \"Enter\": {\n e.preventDefault();\n e.stopPropagation();\n const selectedItem = items[activeIndex];\n if (selectedItem) onSelect(selectedItem);\n break;\n }\n case \"Escape\":\n e.preventDefault();\n onFocusEditor?.();\n onClose?.();\n break;\n case \"ArrowLeft\":\n if (nestedQuery === \"\" || e.currentTarget.selectionStart === 0) {\n e.preventDefault();\n onGoBack();\n }\n break;\n case \"ArrowRight\": {\n const item = items[activeIndex];\n if (item?.hasChildren) {\n e.preventDefault();\n onSelect(item);\n }\n break;\n }\n case \"Backspace\":\n if (nestedQuery === \"\") {\n e.preventDefault();\n onGoBack();\n }\n break;\n }\n };\n\n const hasGroups = items.some((item) => item.group);\n\n return (\n <div\n data-suggestions=\"\"\n data-trigger={trigger}\n data-suggestions-position={position}\n style={style}\n ref={listRef}\n >\n {breadcrumbs.length > 0 && (\n <div data-suggestion-breadcrumb=\"\">\n <button\n type=\"button\"\n data-suggestion-back=\"\"\n onClick={onGoBack}\n aria-label=\"Go back\"\n >\n &larr;\n </button>\n {breadcrumbs.map((crumb, i) => (\n <span key={crumb.id} data-suggestion-breadcrumb-item=\"\">\n {i > 0 && <span data-suggestion-breadcrumb-sep=\"\">/</span>}\n {crumb.label}\n </span>\n ))}\n </div>\n )}\n\n {breadcrumbs.length > 0 && (\n <div data-suggestion-search=\"\">\n <input\n ref={searchInputRef}\n type=\"text\"\n data-suggestion-search-input=\"\"\n placeholder=\"Search...\"\n value={nestedQuery}\n onChange={(e) => {\n const q = e.target.value;\n setNestedQuery(q);\n onSearchNested?.(q);\n }}\n onKeyDown={handleSearchKeyDown}\n autoComplete=\"off\"\n spellCheck={false}\n />\n </div>\n )}\n\n {loading && (\n <div data-suggestion-loading=\"\">\n {renderLoading ? renderLoading() : \"Loading...\"}\n </div>\n )}\n\n {showEmpty && (\n <div data-suggestion-empty=\"\">\n {renderEmpty ? renderEmpty(activeQuery) : \"No results\"}\n </div>\n )}\n\n {!loading && items.length > 0 && (\n <div {...listboxAttrs(listboxId, `${trigger ?? \"\"} suggestions`)}>\n {hasGroups\n ? renderGroupedItems(items, activeIndex, depth, onSelect, onHover, renderItem, renderGroupHeader)\n : items.map((item, index) => (\n <SuggestionItem\n key={item.id}\n item={item}\n index={index}\n isActive={index === activeIndex}\n depth={depth}\n onSelect={onSelect}\n onHover={onHover}\n renderItem={renderItem}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Grouped rendering */\n/* ------------------------------------------------------------------ */\n\nfunction renderGroupedItems(\n items: MentionItem[],\n activeIndex: number,\n depth: number,\n onSelect: (item: MentionItem) => void,\n onHover: (index: number) => void,\n renderItem?: (item: MentionItem, depth: number) => ReactNode,\n renderGroupHeader?: (group: string) => ReactNode,\n) {\n const elements: ReactNode[] = [];\n let lastGroup: string | undefined;\n\n items.forEach((item, index) => {\n if (item.group && item.group !== lastGroup) {\n lastGroup = item.group;\n elements.push(\n <div key={`group-${item.group}`} data-suggestion-group-header=\"\">\n {renderGroupHeader ? renderGroupHeader(item.group) : item.group}\n </div>,\n );\n }\n\n elements.push(\n <SuggestionItem\n key={item.id}\n item={item}\n index={index}\n isActive={index === activeIndex}\n depth={depth}\n onSelect={onSelect}\n onHover={onHover}\n renderItem={renderItem}\n />,\n );\n });\n\n return elements;\n}\n\n/* ------------------------------------------------------------------ */\n/* Single item */\n/* ------------------------------------------------------------------ */\n\nfunction SuggestionItem({\n item,\n index,\n isActive,\n depth,\n onSelect,\n onHover,\n renderItem,\n}: {\n item: MentionItem;\n index: number;\n isActive: boolean;\n depth: number;\n onSelect: (item: MentionItem) => void;\n onHover: (index: number) => void;\n renderItem?: (item: MentionItem, depth: number) => ReactNode;\n}) {\n const itemId = `mention-option-${item.id}`;\n\n return (\n <div\n {...optionAttrs(itemId, isActive, index)}\n data-suggestion-item=\"\"\n data-suggestion-item-active={isActive ? \"\" : undefined}\n data-has-children={item.hasChildren ? \"\" : undefined}\n onMouseEnter={() => onHover(index)}\n onClick={() => onSelect(item)}\n >\n {renderItem ? (\n renderItem(item, depth)\n ) : (\n <DefaultSuggestionItem item={item} />\n )}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Default item render */\n/* ------------------------------------------------------------------ */\n\nfunction DefaultSuggestionItem({ item }: { item: MentionItem }) {\n return (\n <>\n {item.icon && (\n <span data-suggestion-item-icon=\"\">{item.icon}</span>\n )}\n <span data-suggestion-item-label=\"\">{item.label}</span>\n {item.description && (\n <span data-suggestion-item-description=\"\">{item.description}</span>\n )}\n {item.hasChildren && (\n <span data-suggestion-item-chevron=\"\" aria-hidden=\"true\">\n &rsaquo;\n </span>\n )}\n </>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Popover positioning with edge-aware flipping */\n/* ------------------------------------------------------------------ */\n\nconst POPOVER_HEIGHT_ESTIMATE = 280;\nconst POPOVER_WIDTH_ESTIMATE = 360;\n\nfunction usePopoverPosition(\n clientRect: (() => DOMRect | null) | null,\n): { style: React.CSSProperties; position: \"above\" | \"below\" } {\n if (!clientRect) {\n return { style: { display: \"none\" }, position: \"below\" };\n }\n\n const rect = clientRect();\n if (!rect) {\n return { style: { display: \"none\" }, position: \"below\" };\n }\n\n const viewportH = typeof window !== \"undefined\" ? window.innerHeight : 800;\n const viewportW = typeof window !== \"undefined\" ? window.innerWidth : 1200;\n\n const spaceBelow = viewportH - rect.bottom;\n const shouldFlip = spaceBelow < POPOVER_HEIGHT_ESTIMATE && rect.top > spaceBelow;\n\n let left = rect.left;\n if (left + POPOVER_WIDTH_ESTIMATE > viewportW) {\n left = Math.max(0, viewportW - POPOVER_WIDTH_ESTIMATE);\n }\n\n if (shouldFlip) {\n return {\n style: {\n position: \"fixed\",\n left: `${left}px`,\n bottom: `${viewportH - rect.top + 4}px`,\n zIndex: 50,\n },\n position: \"above\",\n };\n }\n\n return {\n style: {\n position: \"fixed\",\n left: `${left}px`,\n top: `${rect.bottom + 4}px`,\n zIndex: 50,\n },\n position: \"below\",\n };\n}\n","/**\n * Generates ARIA attributes for the suggestion combobox pattern.\n */\n\nexport function comboboxAttrs(expanded: boolean, listboxId: string) {\n return {\n role: \"combobox\" as const,\n \"aria-haspopup\": \"listbox\" as const,\n \"aria-expanded\": expanded,\n \"aria-owns\": expanded ? listboxId : undefined,\n };\n}\n\nexport function listboxAttrs(id: string, label: string) {\n return {\n id,\n role: \"listbox\" as const,\n \"aria-label\": label,\n };\n}\n\nexport function optionAttrs(\n id: string,\n selected: boolean,\n index: number,\n) {\n return {\n id,\n role: \"option\" as const,\n \"aria-selected\": selected,\n \"aria-posinset\": index + 1,\n };\n}\n"],"mappings":"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","names":["useCallback","Extension","Plugin","PluginKey","Extension","PluginKey","Plugin","editor","useCallback","useEffect","useRef","useRef","useEffect","useCallback","useEffect","useRef","useState","useRef","useState","useEffect","jsx","jsxs","MentionsInput","useCallback"]}
1
+ {"version":3,"sources":["../src/components/MentionsInput.tsx","../src/hooks/useMentionsEditor.ts","../src/core/mentionExtension.ts","../src/core/suggestionPlugin.ts","../src/core/markdownSerializer.ts","../src/core/markdownParser.ts","../src/hooks/useSuggestion.ts","../src/utils/debounce.ts","../src/components/SuggestionList.tsx","../src/utils/ariaHelpers.ts","../src/hooks/useMentionsContent.ts"],"sourcesContent":["import React, { forwardRef, useCallback, useId, useImperativeHandle } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { EditorContent } from \"@tiptap/react\";\nimport { useMentionsEditor } from \"../hooks/useMentionsEditor\";\nimport { useSuggestion } from \"../hooks/useSuggestion\";\nimport { SuggestionList } from \"./SuggestionList\";\nimport { comboboxAttrs } from \"../utils/ariaHelpers\";\nimport type {\n MentionsInputProps,\n MentionsInputHandle,\n} from \"../types/MentionsInputProps\";\n\n/**\n * `<MentionsInput>` — the single public component.\n *\n * A structured text editor with typed entity tokens.\n * Consumers register `providers` for each trigger character,\n * and receive structured output via `onChange` and `onSubmit`.\n */\nexport const MentionsInput = forwardRef<MentionsInputHandle, MentionsInputProps>(\n function MentionsInput(\n {\n value,\n providers,\n onChange,\n placeholder = \"Type a message...\",\n autoFocus = false,\n disabled = false,\n className,\n onSubmit,\n clearOnSubmit = true,\n maxLength,\n renderItem,\n renderChip,\n renderEmpty,\n renderLoading,\n renderGroupHeader,\n onFocus,\n onBlur,\n onMentionAdd,\n onMentionRemove,\n onMentionClick,\n onMentionHover,\n minHeight,\n maxHeight,\n submitKey = \"enter\",\n allowTrigger,\n validateMention,\n portalContainer,\n streaming,\n onStreamingComplete,\n },\n ref,\n ) {\n const instanceId = useId();\n const listboxId = `mentions-listbox-${instanceId}`;\n\n const { uiState, actions, callbacksRef } = useSuggestion(providers, {\n onMentionAdd,\n });\n\n const { editor, getOutput, clear, setContent, appendText, focus } = useMentionsEditor({\n providers,\n value,\n onChange,\n onSubmit,\n clearOnSubmit,\n placeholder,\n autoFocus,\n editable: !disabled,\n callbacksRef,\n onFocus,\n onBlur,\n submitKey,\n onMentionRemove,\n onMentionClick,\n onMentionHover,\n allowTrigger,\n validateMention,\n streaming,\n onStreamingComplete,\n });\n\n useImperativeHandle(\n ref,\n () => ({ clear, setContent, appendText, focus, getOutput }),\n [clear, setContent, appendText, focus, getOutput],\n );\n\n const isExpanded = uiState.state !== \"idle\";\n\n const handleHover = useCallback((index: number) => {\n void index;\n }, []);\n\n const handleFocusEditor = useCallback(() => {\n editor?.commands.focus();\n }, [editor]);\n\n const editorStyle: React.CSSProperties = {};\n if (minHeight != null) editorStyle.minHeight = `${minHeight}px`;\n if (maxHeight != null) {\n editorStyle.maxHeight = `${maxHeight}px`;\n editorStyle.overflowY = \"auto\";\n }\n\n const suggestionList = isExpanded ? (\n <SuggestionList\n items={uiState.items}\n activeIndex={uiState.activeIndex}\n breadcrumbs={uiState.breadcrumbs}\n loading={uiState.loading}\n trigger={uiState.trigger}\n query={uiState.query}\n clientRect={uiState.clientRect}\n onSelect={(item) => actions.select(item)}\n onHover={handleHover}\n onGoBack={actions.goBack}\n onSearchNested={actions.searchNested}\n onNavigateUp={actions.navigateUp}\n onNavigateDown={actions.navigateDown}\n onClose={actions.close}\n onFocusEditor={handleFocusEditor}\n renderItem={renderItem}\n renderEmpty={renderEmpty}\n renderLoading={renderLoading}\n renderGroupHeader={renderGroupHeader}\n listboxId={listboxId}\n />\n ) : null;\n\n return (\n <div\n className={className}\n data-mentions-input=\"\"\n data-disabled={disabled ? \"\" : undefined}\n {...comboboxAttrs(isExpanded, listboxId)}\n aria-activedescendant={\n isExpanded && uiState.items[uiState.activeIndex]\n ? `mention-option-${uiState.items[uiState.activeIndex].id}`\n : undefined\n }\n >\n <div style={editorStyle}>\n <EditorContent editor={editor} />\n </div>\n\n {portalContainer\n ? suggestionList && createPortal(suggestionList, portalContainer)\n : suggestionList}\n </div>\n );\n },\n);\n","import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { useEditor } from \"@tiptap/react\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\nimport { Extension } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport { MentionNode } from \"../core/mentionExtension\";\nimport { createSuggestionExtension } from \"../core/suggestionPlugin\";\nimport type { StreamingRef } from \"../core/suggestionPlugin\";\nimport {\n serializeToMarkdown,\n extractTokens,\n extractPlainText,\n} from \"../core/markdownSerializer\";\nimport { parseFromMarkdown } from \"../core/markdownParser\";\nimport type { MentionProvider } from \"../types/MentionProvider\";\nimport type { MentionToken } from \"../types/MentionToken\";\nimport type { MentionsOutput } from \"../types/MentionsOutput\";\nimport type { SuggestionCallbacksRef } from \"../core/suggestionPlugin\";\n\n/* ------------------------------------------------------------------ */\n/* Helper: build MentionsOutput from the current editor */\n/* ------------------------------------------------------------------ */\n\nfunction buildOutput(editor: { getJSON: () => any }): MentionsOutput {\n const json = editor.getJSON();\n return {\n markdown: serializeToMarkdown(json),\n tokens: extractTokens(json),\n plainText: extractPlainText(json),\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Collect all mention tokens from a doc JSON */\n/* ------------------------------------------------------------------ */\n\nfunction collectMentionTokens(doc: any): MentionToken[] {\n const tokens: MentionToken[] = [];\n function walk(node: any) {\n if (node.type === \"mention\" && node.attrs) {\n tokens.push({\n id: node.attrs.id,\n type: node.attrs.entityType ?? node.attrs.type,\n label: node.attrs.label,\n });\n }\n if (node.content) {\n for (const child of node.content) walk(child);\n }\n }\n walk(doc);\n return tokens;\n}\n\n/* ------------------------------------------------------------------ */\n/* Submit keyboard shortcut extension (Cmd/Ctrl+Enter) */\n/* ------------------------------------------------------------------ */\n\nfunction createSubmitExtension(\n onSubmitRef: React.RefObject<((output: MentionsOutput) => void) | undefined>,\n clearOnSubmitRef: React.RefObject<boolean>,\n submitKeyRef: React.RefObject<string>,\n) {\n return Extension.create({\n name: \"submitShortcut\",\n priority: 150,\n\n addKeyboardShortcuts() {\n return {\n \"Mod-Enter\": () => {\n const key = submitKeyRef.current;\n if (key === \"mod+enter\" || key === \"enter\") {\n if (onSubmitRef.current) {\n onSubmitRef.current(buildOutput(this.editor));\n if (clearOnSubmitRef.current) {\n this.editor.commands.clearContent(true);\n }\n }\n return true;\n }\n return false;\n },\n };\n },\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Enter key handling */\n/* ------------------------------------------------------------------ */\n\nconst enterSubmitPluginKey = new PluginKey(\"enterSubmit\");\n\nfunction createEnterExtension(\n onSubmitRef: React.RefObject<((output: MentionsOutput) => void) | undefined>,\n clearOnSubmitRef: React.RefObject<boolean>,\n submitKeyRef: React.RefObject<string>,\n) {\n return Extension.create({\n name: \"enterSubmit\",\n priority: 150,\n\n addProseMirrorPlugins() {\n const editor = this.editor;\n\n return [\n new Plugin({\n key: enterSubmitPluginKey,\n props: {\n handleKeyDown(_view, event) {\n if (event.key !== \"Enter\") return false;\n\n const key = submitKeyRef.current;\n\n if (key === \"none\") return false;\n\n if (key === \"mod+enter\") {\n // Enter = new line (default PM behavior handles it)\n // Shift+Enter also new line\n return false;\n }\n\n // key === \"enter\" (default)\n if (event.shiftKey) {\n editor.commands.splitBlock();\n return true;\n }\n\n if (event.metaKey || event.ctrlKey) return false;\n\n if (onSubmitRef.current) {\n onSubmitRef.current(buildOutput(editor));\n if (clearOnSubmitRef.current) {\n editor.commands.clearContent(true);\n }\n }\n return true;\n },\n },\n }),\n ];\n },\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Mention removal detection plugin */\n/* ------------------------------------------------------------------ */\n\nconst mentionRemovePluginKey = new PluginKey(\"mentionRemove\");\n\nfunction createMentionRemoveExtension(\n onMentionRemoveRef: React.RefObject<((token: MentionToken) => void) | undefined>,\n) {\n return Extension.create({\n name: \"mentionRemoveDetector\",\n priority: 100,\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: mentionRemovePluginKey,\n appendTransaction(transactions, oldState, newState) {\n if (!onMentionRemoveRef.current) return null;\n\n const oldMentions = collectMentionTokens(oldState.doc.toJSON());\n const newMentions = collectMentionTokens(newState.doc.toJSON());\n\n if (oldMentions.length <= newMentions.length) return null;\n\n const newIds = new Set(newMentions.map((m) => m.id));\n for (const m of oldMentions) {\n if (!newIds.has(m.id)) {\n onMentionRemoveRef.current(m);\n }\n }\n\n return null;\n },\n }),\n ];\n },\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Streaming input blocker plugin */\n/* ------------------------------------------------------------------ */\n\nconst streamingBlockPluginKey = new PluginKey(\"streamingBlock\");\n\nfunction createStreamingBlockExtension(streamingRef: StreamingRef) {\n return Extension.create({\n name: \"streamingBlock\",\n priority: 200,\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: streamingBlockPluginKey,\n props: {\n handleKeyDown() {\n return streamingRef.current;\n },\n handleKeyPress() {\n return streamingRef.current;\n },\n handlePaste() {\n return streamingRef.current;\n },\n handleDrop() {\n return streamingRef.current;\n },\n },\n }),\n ];\n },\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Hook */\n/* ------------------------------------------------------------------ */\n\ntype UseMentionsEditorOptions = {\n providers: MentionProvider[];\n value?: string;\n onChange?: (output: MentionsOutput) => void;\n onSubmit?: (output: MentionsOutput) => void;\n clearOnSubmit?: boolean;\n placeholder?: string;\n autoFocus?: boolean;\n editable?: boolean;\n callbacksRef: SuggestionCallbacksRef;\n onFocus?: () => void;\n onBlur?: () => void;\n submitKey?: string;\n onMentionRemove?: (token: MentionToken) => void;\n onMentionClick?: (token: MentionToken, event: MouseEvent) => void;\n onMentionHover?: (token: MentionToken) => ReactNode;\n allowTrigger?: (trigger: string, context: { textBefore: string }) => boolean;\n validateMention?: (token: MentionToken) => boolean | Promise<boolean>;\n streaming?: boolean;\n onStreamingComplete?: (output: MentionsOutput) => void;\n};\n\nexport function useMentionsEditor({\n providers,\n value,\n onChange,\n onSubmit,\n clearOnSubmit = true,\n placeholder,\n autoFocus = false,\n editable = true,\n callbacksRef,\n onFocus,\n onBlur,\n submitKey = \"enter\",\n onMentionRemove,\n onMentionClick,\n onMentionHover,\n allowTrigger,\n validateMention,\n streaming = false,\n onStreamingComplete,\n}: UseMentionsEditorOptions) {\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n const onSubmitRef = useRef(onSubmit);\n onSubmitRef.current = onSubmit;\n\n const clearOnSubmitRef = useRef(clearOnSubmit);\n clearOnSubmitRef.current = clearOnSubmit;\n\n const onFocusRef = useRef(onFocus);\n onFocusRef.current = onFocus;\n\n const onBlurRef = useRef(onBlur);\n onBlurRef.current = onBlur;\n\n const submitKeyRef = useRef(submitKey);\n submitKeyRef.current = submitKey;\n\n const onMentionRemoveRef = useRef(onMentionRemove);\n onMentionRemoveRef.current = onMentionRemove;\n\n const onMentionClickRef = useRef(onMentionClick);\n onMentionClickRef.current = onMentionClick;\n\n const onMentionHoverRef = useRef(onMentionHover);\n onMentionHoverRef.current = onMentionHover;\n\n const allowTriggerRef = useRef(allowTrigger);\n allowTriggerRef.current = allowTrigger;\n\n const validateMentionRef = useRef(validateMention);\n validateMentionRef.current = validateMention;\n\n const onStreamingCompleteRef = useRef(onStreamingComplete);\n onStreamingCompleteRef.current = onStreamingComplete;\n\n // Streaming state — mutable ref so ProseMirror plugins can read it\n // without re-creating the extension chain.\n const streamingRef = useRef<boolean>(streaming);\n streamingRef.current = streaming;\n const prevStreamingRef = useRef(streaming);\n\n // Throttle state for onChange during streaming\n const throttleTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingOutputRef = useRef<MentionsOutput | null>(null);\n\n // Track internal value to avoid controlled-value infinite loops\n const internalMarkdownRef = useRef<string | null>(null);\n\n const initialContent = useMemo(() => {\n if (!value) return undefined;\n return parseFromMarkdown(value);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const triggersKey = providers.map((p) => p.trigger).join(\",\");\n const triggers = useMemo(\n () => providers.map((p) => p.trigger),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [triggersKey],\n );\n\n const suggestionExtension = useMemo(\n () =>\n createSuggestionExtension(\n triggers,\n callbacksRef,\n allowTriggerRef,\n streamingRef,\n ),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [triggersKey],\n );\n\n const submitExt = useMemo(\n () => createSubmitExtension(onSubmitRef, clearOnSubmitRef, submitKeyRef),\n [],\n );\n const enterExt = useMemo(\n () => createEnterExtension(onSubmitRef, clearOnSubmitRef, submitKeyRef),\n [],\n );\n const mentionRemoveExt = useMemo(\n () => createMentionRemoveExtension(onMentionRemoveRef),\n [],\n );\n\n const streamingBlockExt = useMemo(\n () => createStreamingBlockExtension(streamingRef),\n [],\n );\n\n const mentionNodeExt = useMemo(\n () =>\n MentionNode.configure({\n onClickRef: onMentionClickRef,\n onHoverRef: onMentionHoverRef,\n }),\n [],\n );\n\n const editor = useEditor({\n extensions: [\n StarterKit.configure({\n heading: false,\n blockquote: false,\n codeBlock: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n horizontalRule: false,\n hardBreak: false,\n }),\n Placeholder.configure({\n placeholder: ({ editor }) =>\n editor.isEmpty ? (placeholder ?? \"Type a message...\") : \"\",\n showOnlyCurrent: true,\n }),\n mentionNodeExt,\n suggestionExtension,\n submitExt,\n enterExt,\n mentionRemoveExt,\n streamingBlockExt,\n ],\n content: initialContent,\n autofocus: autoFocus ? \"end\" : false,\n editable,\n editorProps: {\n attributes: {\n class: \"mentions-editor\",\n },\n },\n onUpdate: ({ editor }) => {\n const output = buildOutput(editor);\n internalMarkdownRef.current = output.markdown;\n\n if (streamingRef.current) {\n pendingOutputRef.current = output;\n if (!throttleTimerRef.current) {\n throttleTimerRef.current = setTimeout(() => {\n throttleTimerRef.current = null;\n if (pendingOutputRef.current) {\n onChangeRef.current?.(pendingOutputRef.current);\n pendingOutputRef.current = null;\n }\n }, 150);\n }\n } else {\n onChangeRef.current?.(output);\n }\n },\n onFocus: () => {\n onFocusRef.current?.();\n },\n onBlur: () => {\n onBlurRef.current?.();\n },\n });\n\n // Flush throttled onChange and fire onStreamingComplete when streaming ends\n useEffect(() => {\n if (prevStreamingRef.current && !streaming && editor) {\n if (throttleTimerRef.current) {\n clearTimeout(throttleTimerRef.current);\n throttleTimerRef.current = null;\n }\n const output = buildOutput(editor);\n onChangeRef.current?.(output);\n onStreamingCompleteRef.current?.(output);\n pendingOutputRef.current = null;\n }\n prevStreamingRef.current = streaming;\n }, [streaming, editor]);\n\n // Clean up throttle timer on unmount\n useEffect(() => {\n return () => {\n if (throttleTimerRef.current) {\n clearTimeout(throttleTimerRef.current);\n }\n };\n }, []);\n\n // Sync editable state\n useEffect(() => {\n if (editor && editor.isEditable !== editable) {\n editor.setEditable(editable);\n }\n }, [editor, editable]);\n\n // Controlled value: update editor when external value changes\n useEffect(() => {\n if (!editor || value === undefined) return;\n if (value === internalMarkdownRef.current) return;\n const doc = parseFromMarkdown(value);\n editor.commands.setContent(doc);\n internalMarkdownRef.current = value;\n }, [editor, value]);\n\n // Mention validation\n useEffect(() => {\n if (!editor || !validateMention) return;\n\n const runValidation = async () => {\n const doc = editor.getJSON();\n const tokens = collectMentionTokens(doc);\n const invalidIds = new Set<string>();\n\n await Promise.all(\n tokens.map(async (token) => {\n const valid = await validateMention(token);\n if (!valid) invalidIds.add(token.id);\n }),\n );\n\n editor.view.dom.querySelectorAll(\"[data-mention]\").forEach((el) => {\n const id = el.getAttribute(\"data-id\");\n if (id && invalidIds.has(id)) {\n el.setAttribute(\"data-mention-invalid\", \"\");\n } else {\n el.removeAttribute(\"data-mention-invalid\");\n }\n });\n };\n\n runValidation();\n }, [editor, validateMention]);\n\n /* ---------------------------------------------------------------- */\n /* Imperative methods */\n /* ---------------------------------------------------------------- */\n\n const clear = useCallback(() => {\n editor?.commands.clearContent(true);\n }, [editor]);\n\n const setContent = useCallback(\n (markdown: string) => {\n if (!editor) return;\n const doc = parseFromMarkdown(markdown);\n editor.commands.setContent(doc);\n internalMarkdownRef.current = markdown;\n if (streamingRef.current) {\n editor.commands.focus(\"end\");\n }\n },\n [editor],\n );\n\n const appendText = useCallback(\n (text: string) => {\n if (!editor) return;\n const endPos = editor.state.doc.content.size - 1;\n editor.commands.insertContentAt(endPos, text);\n if (streamingRef.current) {\n editor.commands.focus(\"end\");\n }\n },\n [editor],\n );\n\n const focus = useCallback(() => {\n editor?.commands.focus(\"end\");\n }, [editor]);\n\n const getOutput = useCallback((): MentionsOutput | null => {\n if (!editor) return null;\n return buildOutput(editor);\n }, [editor]);\n\n return { editor, getOutput, clear, setContent, appendText, focus };\n}\n","import { mergeAttributes, Node } from \"@tiptap/core\";\nimport type { ReactNode } from \"react\";\nimport type { MentionToken } from \"../types/MentionToken\";\n\nexport interface MentionNodeAttrs {\n id: string;\n label: string;\n entityType: string;\n rootLabel?: string | null;\n}\n\nconst DEFAULT_PREFIXES: Record<string, string> = {\n workspace: \"@\",\n contract: \"@\",\n file: \"#\",\n web: \":\",\n};\n\nexport type MentionNodeOptions = {\n onClickRef?: React.RefObject<((token: MentionToken, event: MouseEvent) => void) | undefined>;\n onHoverRef?: React.RefObject<((token: MentionToken) => ReactNode) | undefined>;\n};\n\nexport const MentionNode = Node.create<MentionNodeOptions>({\n name: \"mention\",\n group: \"inline\",\n inline: true,\n atom: true,\n selectable: true,\n draggable: false,\n\n addOptions() {\n return {\n onClickRef: undefined,\n onHoverRef: undefined,\n };\n },\n\n addAttributes() {\n return {\n id: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-id\"),\n renderHTML: (attributes) => ({ \"data-id\": attributes.id }),\n },\n label: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-label\"),\n renderHTML: (attributes) => ({ \"data-label\": attributes.label }),\n },\n entityType: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-type\"),\n renderHTML: (attributes) => ({ \"data-type\": attributes.entityType }),\n },\n rootLabel: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-root-label\"),\n renderHTML: (attributes) =>\n attributes.rootLabel\n ? { \"data-root-label\": attributes.rootLabel }\n : {},\n },\n };\n },\n\n parseHTML() {\n return [{ tag: 'span[data-mention]' }];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const entityType = node.attrs.entityType as string;\n const label = node.attrs.label as string;\n const prefix = DEFAULT_PREFIXES[entityType] ?? \"@\";\n const display = `${prefix}${label}`;\n\n const hasClick = !!this.options.onClickRef?.current;\n const extraAttrs: Record<string, string> = {};\n if (hasClick) {\n extraAttrs[\"data-mention-clickable\"] = \"\";\n }\n\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n \"data-mention\": \"\",\n class: \"mention-chip\",\n ...extraAttrs,\n }),\n display,\n ];\n },\n\n renderText({ node }) {\n const entityType = node.attrs.entityType as string;\n const label = node.attrs.label as string;\n const prefix = DEFAULT_PREFIXES[entityType] ?? \"@\";\n return `${prefix}${label}`;\n },\n\n addNodeView() {\n const options = this.options;\n\n return ({ node, HTMLAttributes }) => {\n const entityType = node.attrs.entityType as string;\n const label = node.attrs.label as string;\n const id = node.attrs.id as string;\n const prefix = DEFAULT_PREFIXES[entityType] ?? \"@\";\n\n const dom = document.createElement(\"span\");\n Object.entries(\n mergeAttributes(HTMLAttributes, {\n \"data-mention\": \"\",\n \"data-type\": entityType,\n \"data-id\": id,\n class: \"mention-chip\",\n }),\n ).forEach(([key, val]) => {\n if (val != null && val !== false) dom.setAttribute(key, String(val));\n });\n\n dom.textContent = `${prefix}${label}`;\n\n if (options.onClickRef?.current) {\n dom.setAttribute(\"data-mention-clickable\", \"\");\n dom.style.cursor = \"pointer\";\n }\n\n dom.addEventListener(\"click\", (event) => {\n const handler = options.onClickRef?.current;\n if (handler) {\n event.preventDefault();\n event.stopPropagation();\n handler({ id, type: entityType, label }, event);\n }\n });\n\n // Hover tooltip\n let tooltip: HTMLElement | null = null;\n\n dom.addEventListener(\"mouseenter\", () => {\n const hoverFn = options.onHoverRef?.current;\n if (!hoverFn) return;\n\n const content = hoverFn({ id, type: entityType, label });\n if (!content) return;\n\n tooltip = document.createElement(\"div\");\n tooltip.setAttribute(\"data-mention-tooltip\", \"\");\n tooltip.textContent = typeof content === \"string\" ? content : \"\";\n dom.style.position = \"relative\";\n dom.appendChild(tooltip);\n });\n\n dom.addEventListener(\"mouseleave\", () => {\n if (tooltip && tooltip.parentNode) {\n tooltip.parentNode.removeChild(tooltip);\n tooltip = null;\n }\n });\n\n return { dom };\n };\n },\n\n addKeyboardShortcuts() {\n return {\n Backspace: () =>\n this.editor.commands.command(({ tr, state }) => {\n let isMention = false;\n const { selection } = state;\n const { empty, anchor } = selection;\n\n if (!empty) return false;\n\n state.doc.nodesBetween(anchor - 1, anchor, (node, pos) => {\n if (node.type.name === this.name) {\n isMention = true;\n tr.insertText(\"\", pos, pos + node.nodeSize);\n }\n });\n\n return isMention;\n }),\n };\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport type { EditorView } from \"@tiptap/pm/view\";\n\n/* ------------------------------------------------------------------ */\n/* Suggestion state types */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionState =\n | \"idle\"\n | \"loading\"\n | \"showing\"\n | \"drilling\"\n | \"inserting\";\n\n/* ------------------------------------------------------------------ */\n/* Callbacks the React layer implements */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionCallbacks = {\n onStart: (props: SuggestionCallbackProps) => void;\n onUpdate: (props: SuggestionCallbackProps) => void;\n onExit: () => void;\n onKeyDown: (props: { event: KeyboardEvent }) => boolean;\n};\n\nexport type SuggestionCallbackProps = {\n query: string;\n trigger: string;\n clientRect: (() => DOMRect | null) | null;\n range: { from: number; to: number };\n command: (attrs: Record<string, unknown>) => void;\n};\n\n/* ------------------------------------------------------------------ */\n/* Trigger detection */\n/* ------------------------------------------------------------------ */\n\ntype TriggerMatch = {\n trigger: string;\n query: string;\n from: number;\n to: number;\n textBefore: string;\n};\n\nfunction detectTrigger(\n text: string,\n cursorPos: number,\n docStartPos: number,\n triggers: string[],\n): TriggerMatch | null {\n const relCursor = cursorPos - docStartPos;\n const before = text.slice(0, relCursor);\n\n for (let i = before.length - 1; i >= 0; i--) {\n const ch = before[i];\n if (ch === \"\\n\") return null;\n\n for (const trigger of triggers) {\n if (before.substring(i, i + trigger.length) === trigger) {\n if (i === 0 || /\\s/.test(before[i - 1])) {\n const query = before.slice(i + trigger.length);\n return {\n trigger,\n query,\n from: docStartPos + i,\n to: cursorPos,\n textBefore: before.slice(0, i),\n };\n }\n }\n }\n }\n\n return null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Plugin key */\n/* ------------------------------------------------------------------ */\n\nconst suggestionPluginKey = new PluginKey(\"mentionSuggestion\");\n\n/* ------------------------------------------------------------------ */\n/* Ref-based callback container (avoids stale closure issues) */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionCallbacksRef = { current: SuggestionCallbacks };\n\nexport type AllowTriggerRef = {\n current?: (trigger: string, context: { textBefore: string }) => boolean;\n};\n\nexport type StreamingRef = { current: boolean };\n\n/* ------------------------------------------------------------------ */\n/* Build the single multi-trigger suggestion extension */\n/* ------------------------------------------------------------------ */\n\nexport function createSuggestionExtension(\n triggers: string[],\n callbacksRef: SuggestionCallbacksRef,\n allowTriggerRef?: AllowTriggerRef,\n streamingRef?: StreamingRef,\n) {\n return Extension.create({\n name: \"mentionSuggestion\",\n priority: 200,\n\n addProseMirrorPlugins() {\n const editor = this.editor;\n let active = false;\n let lastQuery: string | null = null;\n let lastTrigger: string | null = null;\n\n const getClientRect = (\n view: EditorView,\n from: number,\n ): (() => DOMRect | null) => {\n return () => {\n try {\n const coords = view.coordsAtPos(from);\n return new DOMRect(\n coords.left,\n coords.top,\n 0,\n coords.bottom - coords.top,\n );\n } catch {\n return null;\n }\n };\n };\n\n const makeCommand = (range: { from: number; to: number }) => {\n return (attrs: Record<string, unknown>) => {\n editor\n .chain()\n .focus()\n .insertContentAt(range, [\n {\n type: \"mention\",\n attrs: {\n id: attrs.id,\n label: attrs.label,\n entityType: attrs.entityType,\n rootLabel: attrs.rootLabel ?? null,\n },\n },\n { type: \"text\", text: \" \" },\n ])\n .run();\n };\n };\n\n const plugin = new Plugin({\n key: suggestionPluginKey,\n\n props: {\n handleKeyDown(_view, event) {\n if (!active) return false;\n return callbacksRef.current.onKeyDown({ event });\n },\n },\n\n view() {\n return {\n update(view, _prevState) {\n if (streamingRef?.current) {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n return;\n }\n\n const { state } = view;\n const { selection } = state;\n\n if (!selection.empty) {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n return;\n }\n\n const $pos = selection.$from;\n const textBlock = $pos.parent;\n\n if (!textBlock.isTextblock) {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n return;\n }\n\n const blockStart = $pos.start();\n const blockText = textBlock.textContent;\n const cursorPos = $pos.pos;\n\n const match = detectTrigger(blockText, cursorPos, blockStart, triggers);\n\n if (match) {\n // Check allowTrigger gate\n if (allowTriggerRef?.current) {\n const allowed = allowTriggerRef.current(match.trigger, {\n textBefore: match.textBefore,\n });\n if (!allowed) {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n return;\n }\n }\n\n const range = { from: match.from, to: match.to };\n const props: SuggestionCallbackProps = {\n query: match.query,\n trigger: match.trigger,\n clientRect: getClientRect(view, match.from),\n range,\n command: makeCommand(range),\n };\n\n if (!active) {\n active = true;\n lastQuery = match.query;\n lastTrigger = match.trigger;\n callbacksRef.current.onStart(props);\n } else if (\n match.query !== lastQuery ||\n match.trigger !== lastTrigger\n ) {\n lastQuery = match.query;\n lastTrigger = match.trigger;\n callbacksRef.current.onUpdate(props);\n }\n } else {\n if (active) {\n active = false;\n lastQuery = null;\n lastTrigger = null;\n callbacksRef.current.onExit();\n }\n }\n },\n\n destroy() {\n if (active) {\n callbacksRef.current.onExit();\n }\n },\n };\n },\n });\n\n return [plugin];\n },\n });\n}\n","import type { JSONContent } from \"@tiptap/core\";\nimport type { MentionToken } from \"../types/MentionToken\";\n\n/**\n * Serialize a Tiptap JSON document to a markdown string.\n *\n * Mention nodes are encoded as `@[label](id)` or `@rootLabel[label](id)` when the mention has a root (e.g. file under workspace).\n * All other text passes through verbatim.\n */\nexport function serializeToMarkdown(doc: JSONContent): string {\n if (!doc.content) return \"\";\n\n const parts: string[] = [];\n\n for (const block of doc.content) {\n if (block.type === \"paragraph\") {\n parts.push(serializeParagraph(block));\n } else if (block.type === \"text\") {\n parts.push(block.text ?? \"\");\n }\n }\n\n return parts.join(\"\\n\");\n}\n\nfunction serializeParagraph(node: JSONContent): string {\n if (!node.content) return \"\";\n\n return node.content\n .map((child) => {\n if (child.type === \"mention\") {\n const { id, label, entityType, rootLabel } = child.attrs ?? {};\n const idPart =\n entityType && entityType !== \"unknown\"\n ? `${entityType}:${id}`\n : id;\n if (rootLabel != null && rootLabel !== \"\") {\n return `@${rootLabel}[${label}](${idPart})`;\n }\n return `@[${label}](${idPart})`;\n }\n return child.text ?? \"\";\n })\n .join(\"\");\n}\n\n/**\n * Extract all `MentionToken`s from a Tiptap JSON document, in document order.\n */\nexport function extractTokens(doc: JSONContent): MentionToken[] {\n const tokens: MentionToken[] = [];\n\n function walk(node: JSONContent) {\n if (node.type === \"mention\" && node.attrs) {\n tokens.push({\n id: node.attrs.id as string,\n type: node.attrs.entityType as string,\n label: node.attrs.label as string,\n });\n }\n if (node.content) {\n for (const child of node.content) {\n walk(child);\n }\n }\n }\n\n walk(doc);\n return tokens;\n}\n\n/**\n * Extract plain text from a Tiptap JSON document.\n * Mention nodes are replaced with their label (no trigger prefix in plain text).\n */\nexport function extractPlainText(doc: JSONContent): string {\n if (!doc.content) return \"\";\n\n const parts: string[] = [];\n\n for (const block of doc.content) {\n if (block.type === \"paragraph\") {\n parts.push(extractParagraphText(block));\n }\n }\n\n return parts.join(\"\\n\");\n}\n\nfunction extractParagraphText(node: JSONContent): string {\n if (!node.content) return \"\";\n\n return node.content\n .map((child) => {\n if (child.type === \"mention\") {\n return child.attrs?.label ?? \"\";\n }\n return child.text ?? \"\";\n })\n .join(\"\");\n}\n","import type { JSONContent } from \"@tiptap/core\";\nimport { extractTokens, extractPlainText } from \"./markdownSerializer\";\nimport type { MentionToken } from \"../types/MentionToken\";\n\n/**\n * Regex matching mention tokens:\n * - `@[label](id)` or `@[label](type:id)`\n * - `@rootLabel[label](type:id)` when the mention has a root (e.g. file under workspace).\n * Groups: (1) rootLabel (may be empty string), (2) label, (3) optional entityType, (4) id.\n *\n * `[^\\[@]` prevents the rootLabel from crossing `@` boundaries so that plain\n * `@word` in running text is never swallowed into a false rootLabel match.\n */\nconst MENTION_RE = /@([^\\[@]*)\\[([^\\]]+)\\]\\((?:([^:)]+):)?([^)]+)\\)/g;\n\n/**\n * Parse a markdown string (with `@[label](id)`, `@[label](type:id)`, or `@rootLabel[label](id)` tokens)\n * into a Tiptap-compatible JSON document.\n */\nexport function parseFromMarkdown(markdown: string): JSONContent {\n const lines = markdown.split(\"\\n\");\n\n const content: JSONContent[] = lines.map((line) => {\n const children = parseLine(line);\n return children.length > 0\n ? { type: \"paragraph\", content: children }\n : { type: \"paragraph\" };\n });\n\n return { type: \"doc\", content };\n}\n\nfunction parseLine(line: string): JSONContent[] {\n const nodes: JSONContent[] = [];\n let lastIndex = 0;\n\n // Reset regex state\n MENTION_RE.lastIndex = 0;\n\n let match: RegExpExecArray | null;\n while ((match = MENTION_RE.exec(line)) !== null) {\n const fullMatch = match[0];\n const rootLabel = match[1] || null;\n const label = match[2];\n const entityType = match[3] ?? \"unknown\";\n const id = match[4];\n\n // Text before this mention\n if (match.index > lastIndex) {\n nodes.push({\n type: \"text\",\n text: line.slice(lastIndex, match.index),\n });\n }\n\n // Mention node\n nodes.push({\n type: \"mention\",\n attrs: {\n id,\n label,\n entityType,\n rootLabel,\n },\n });\n\n lastIndex = match.index + fullMatch.length;\n }\n\n // Trailing text\n if (lastIndex < line.length) {\n nodes.push({\n type: \"text\",\n text: line.slice(lastIndex),\n });\n }\n\n return nodes;\n}\n\n/* ------------------------------------------------------------------ */\n/* Convenience helper: markdown → tokens + plain text */\n/* ------------------------------------------------------------------ */\n\n/**\n * Parse a markdown string and extract structured data from it.\n *\n * This is a convenience wrapper that combines `parseFromMarkdown`,\n * `extractTokens`, and `extractPlainText` into a single call.\n *\n * @example\n * ```ts\n * const { tokens, plainText } = extractFromMarkdown(\n * \"Check @Marketing[Q4 Strategy.pdf](file_1) for details\"\n * );\n * // tokens → [{ id: \"file_1\", type: \"unknown\", label: \"Q4 Strategy.pdf\" }]\n * // plainText → \"Check Q4 Strategy.pdf for details\"\n * ```\n */\nexport function extractFromMarkdown(markdown: string): {\n tokens: MentionToken[];\n plainText: string;\n} {\n const doc = parseFromMarkdown(markdown);\n return {\n tokens: extractTokens(doc),\n plainText: extractPlainText(doc),\n };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { MentionItem, MentionProvider } from \"../types/MentionProvider\";\nimport type { MentionToken } from \"../types/MentionToken\";\nimport type {\n SuggestionCallbackProps,\n SuggestionCallbacks,\n SuggestionCallbacksRef,\n SuggestionState,\n} from \"../core/suggestionPlugin\";\nimport { debounce } from \"../utils/debounce\";\n\n/* ------------------------------------------------------------------ */\n/* Public state exposed to the UI layer */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionUIState = {\n state: SuggestionState;\n items: MentionItem[];\n breadcrumbs: MentionItem[];\n activeIndex: number;\n loading: boolean;\n clientRect: (() => DOMRect | null) | null;\n trigger: string | null;\n query: string;\n};\n\nexport type SuggestionActions = {\n navigateUp: () => void;\n navigateDown: () => void;\n select: (item?: MentionItem) => void;\n goBack: () => void;\n close: () => void;\n searchNested: (query: string) => void;\n};\n\nexport type SuggestionHookOptions = {\n onMentionAdd?: (token: MentionToken) => void;\n};\n\nconst IDLE_STATE: SuggestionUIState = {\n state: \"idle\",\n items: [],\n breadcrumbs: [],\n activeIndex: 0,\n loading: false,\n clientRect: null,\n trigger: null,\n query: \"\",\n};\n\n/* ------------------------------------------------------------------ */\n/* Hook */\n/* ------------------------------------------------------------------ */\n\nexport function useSuggestion(\n providers: MentionProvider[],\n options: SuggestionHookOptions = {},\n) {\n const [uiState, setUIState] = useState<SuggestionUIState>(IDLE_STATE);\n\n const stateRef = useRef(uiState);\n stateRef.current = uiState;\n\n const providersRef = useRef(providers);\n providersRef.current = providers;\n\n const onMentionAddRef = useRef(options.onMentionAdd);\n onMentionAddRef.current = options.onMentionAdd;\n\n const commandRef = useRef<((attrs: Record<string, unknown>) => void) | null>(\n null,\n );\n const providerRef = useRef<MentionProvider | null>(null);\n\n const debouncedFetchRef = useRef<ReturnType<typeof debounce> | null>(null);\n\n useEffect(() => {\n return () => {\n debouncedFetchRef.current?.cancel();\n };\n }, []);\n\n /* ---------------------------------------------------------------- */\n /* Fetch items from the provider */\n /* ---------------------------------------------------------------- */\n\n const fetchItems = useCallback(\n async (\n provider: MentionProvider,\n query: string,\n parent?: MentionItem,\n useSearchAll?: boolean,\n ) => {\n setUIState((prev) => ({ ...prev, loading: true, state: \"loading\" }));\n\n try {\n let items: MentionItem[];\n\n if (useSearchAll && provider.searchAll) {\n items = await provider.searchAll(query);\n } else if (parent && provider.getChildren) {\n items = await provider.getChildren(parent, query);\n } else {\n items = await provider.getRootItems(query);\n }\n\n setUIState((prev) => ({\n ...prev,\n items,\n loading: false,\n state: \"showing\",\n activeIndex: 0,\n }));\n } catch {\n setUIState((prev) => ({\n ...prev,\n items: [],\n loading: false,\n state: \"showing\",\n }));\n }\n },\n [],\n );\n\n const scheduleFetch = useCallback(\n (\n provider: MentionProvider,\n query: string,\n parent?: MentionItem,\n useSearchAll?: boolean,\n ) => {\n debouncedFetchRef.current?.cancel();\n\n const ms = provider.debounceMs;\n if (ms && ms > 0) {\n setUIState((prev) => ({ ...prev, loading: true }));\n const debouncedFn = debounce(() => {\n fetchItems(provider, query, parent, useSearchAll);\n }, ms);\n debouncedFetchRef.current = debouncedFn;\n debouncedFn();\n } else {\n fetchItems(provider, query, parent, useSearchAll);\n }\n },\n [fetchItems],\n );\n\n /* ---------------------------------------------------------------- */\n /* Suggestion plugin callbacks */\n /* ---------------------------------------------------------------- */\n\n const onStart = useCallback(\n (props: SuggestionCallbackProps) => {\n const provider = providersRef.current.find(\n (p) => p.trigger === props.trigger,\n );\n if (!provider) return;\n\n providerRef.current = provider;\n commandRef.current = props.command;\n\n setUIState({\n state: \"loading\",\n items: [],\n breadcrumbs: [],\n activeIndex: 0,\n loading: true,\n clientRect: props.clientRect,\n trigger: props.trigger,\n query: props.query,\n });\n\n if (!props.query.trim() && provider.getRecentItems) {\n provider.getRecentItems().then((recentItems) => {\n const tagged = recentItems.map((item) => ({\n ...item,\n group: item.group ?? \"Recent\",\n }));\n setUIState((prev) => ({\n ...prev,\n items: tagged,\n loading: false,\n state: \"showing\",\n activeIndex: 0,\n }));\n }).catch(() => {\n scheduleFetch(provider, props.query);\n });\n return;\n }\n\n if (props.query.trim() && provider.searchAll) {\n scheduleFetch(provider, props.query, undefined, true);\n } else {\n scheduleFetch(provider, props.query);\n }\n },\n [scheduleFetch],\n );\n\n const onUpdate = useCallback(\n (props: SuggestionCallbackProps) => {\n const provider = providerRef.current;\n if (!provider) return;\n\n commandRef.current = props.command;\n const current = stateRef.current;\n\n if (current.breadcrumbs.length > 0) {\n setUIState((prev) => ({\n ...prev,\n breadcrumbs: [],\n clientRect: props.clientRect,\n query: props.query,\n activeIndex: 0,\n }));\n } else {\n setUIState((prev) => ({\n ...prev,\n clientRect: props.clientRect,\n query: props.query,\n }));\n }\n\n if (props.query.trim() && provider.searchAll) {\n scheduleFetch(provider, props.query, undefined, true);\n } else if (!props.query.trim() && provider.getRecentItems) {\n provider.getRecentItems().then((recentItems) => {\n const tagged = recentItems.map((item) => ({\n ...item,\n group: item.group ?? \"Recent\",\n }));\n setUIState((prev) => ({\n ...prev,\n items: tagged,\n loading: false,\n state: \"showing\",\n activeIndex: 0,\n }));\n }).catch(() => {\n scheduleFetch(provider, props.query);\n });\n } else {\n scheduleFetch(provider, props.query);\n }\n },\n [scheduleFetch],\n );\n\n const onExit = useCallback(() => {\n debouncedFetchRef.current?.cancel();\n providerRef.current = null;\n commandRef.current = null;\n setUIState(IDLE_STATE);\n }, []);\n\n /* ---------------------------------------------------------------- */\n /* Navigation actions */\n /* ---------------------------------------------------------------- */\n\n const navigateUp = useCallback(() => {\n setUIState((prev) => ({\n ...prev,\n activeIndex: Math.max(0, prev.activeIndex - 1),\n }));\n }, []);\n\n const navigateDown = useCallback(() => {\n setUIState((prev) => ({\n ...prev,\n activeIndex: Math.min(prev.items.length - 1, prev.activeIndex + 1),\n }));\n }, []);\n\n const select = useCallback(\n (item?: MentionItem) => {\n const current = stateRef.current;\n const selected = item ?? current.items[current.activeIndex];\n if (!selected) return;\n\n const provider = providerRef.current;\n\n if (selected.hasChildren && provider?.getChildren) {\n setUIState((prev) => ({\n ...prev,\n state: \"drilling\",\n breadcrumbs: [...prev.breadcrumbs, selected],\n items: [],\n activeIndex: 0,\n query: \"\",\n }));\n\n fetchItems(provider, \"\", selected);\n return;\n }\n\n const rootLabel =\n current.breadcrumbs.length > 0\n ? current.breadcrumbs[0].label\n : selected.rootLabel ?? null;\n\n if (commandRef.current) {\n commandRef.current({\n id: selected.id,\n label: selected.label,\n entityType: selected.type,\n rootLabel,\n });\n }\n\n onMentionAddRef.current?.({\n id: selected.id,\n type: selected.type,\n label: selected.label,\n });\n },\n [fetchItems],\n );\n\n const goBack = useCallback(() => {\n const provider = providerRef.current;\n if (!provider) return;\n\n setUIState((prev) => {\n const newBreadcrumbs = prev.breadcrumbs.slice(0, -1);\n const parent = newBreadcrumbs[newBreadcrumbs.length - 1];\n\n if (parent) {\n fetchItems(provider, \"\", parent);\n } else {\n fetchItems(provider, prev.query);\n }\n\n return {\n ...prev,\n breadcrumbs: newBreadcrumbs,\n items: [],\n activeIndex: 0,\n state: \"loading\" as const,\n };\n });\n }, [fetchItems]);\n\n const close = useCallback(() => {\n debouncedFetchRef.current?.cancel();\n setUIState(IDLE_STATE);\n }, []);\n\n /* ---------------------------------------------------------------- */\n /* Nested search */\n /* ---------------------------------------------------------------- */\n\n const searchNested = useCallback(\n (query: string) => {\n const provider = providerRef.current;\n if (!provider) return;\n\n const current = stateRef.current;\n const parent = current.breadcrumbs[current.breadcrumbs.length - 1];\n if (parent) {\n scheduleFetch(provider, query, parent);\n }\n },\n [scheduleFetch],\n );\n\n /* ---------------------------------------------------------------- */\n /* Keyboard handler */\n /* ---------------------------------------------------------------- */\n\n const onKeyDown = useCallback(\n ({ event }: { event: KeyboardEvent }): boolean => {\n const current = stateRef.current;\n if (current.state === \"idle\") return false;\n\n switch (event.key) {\n case \"ArrowUp\":\n event.preventDefault();\n navigateUp();\n return true;\n case \"ArrowDown\":\n event.preventDefault();\n navigateDown();\n return true;\n case \"Enter\": {\n event.preventDefault();\n const selectedItem = current.items[current.activeIndex];\n if (selectedItem) {\n select(selectedItem);\n }\n return true;\n }\n case \"Tab\": {\n event.preventDefault();\n const selectedItem = current.items[current.activeIndex];\n if (selectedItem) {\n select(selectedItem);\n }\n return true;\n }\n case \"ArrowRight\": {\n const activeItem = current.items[current.activeIndex];\n if (activeItem?.hasChildren) {\n event.preventDefault();\n select(activeItem);\n return true;\n }\n return false;\n }\n case \"ArrowLeft\":\n if (current.breadcrumbs.length > 0) {\n event.preventDefault();\n goBack();\n return true;\n }\n return false;\n case \"Escape\":\n event.preventDefault();\n close();\n return true;\n default:\n return false;\n }\n },\n [navigateUp, navigateDown, select, goBack, close],\n );\n\n /* ---------------------------------------------------------------- */\n /* Build a ref that always points to the latest callbacks. */\n /* ---------------------------------------------------------------- */\n\n const callbacksRef: SuggestionCallbacksRef = useRef<SuggestionCallbacks>({\n onStart,\n onUpdate,\n onExit,\n onKeyDown,\n });\n\n callbacksRef.current = { onStart, onUpdate, onExit, onKeyDown };\n\n const actions: SuggestionActions = {\n navigateUp,\n navigateDown,\n select,\n goBack,\n close,\n searchNested,\n };\n\n return { uiState, actions, callbacksRef };\n}\n","/**\n * Returns a debounced version of `fn` that delays invocation until\n * `ms` milliseconds have elapsed since the last call.\n * Call `.cancel()` on the returned function to clear any pending timer.\n */\nexport function debounce<T extends (...args: any[]) => void>(\n fn: T,\n ms: number,\n): T & { cancel: () => void } {\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const debounced = ((...args: any[]) => {\n if (timer != null) clearTimeout(timer);\n timer = setTimeout(() => {\n timer = null;\n fn(...args);\n }, ms);\n }) as T & { cancel: () => void };\n\n debounced.cancel = () => {\n if (timer != null) {\n clearTimeout(timer);\n timer = null;\n }\n };\n\n return debounced;\n}\n","import React, { useEffect, useRef, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { MentionItem } from \"../types/MentionProvider\";\nimport { listboxAttrs, optionAttrs } from \"../utils/ariaHelpers\";\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport type SuggestionListProps = {\n items: MentionItem[];\n activeIndex: number;\n breadcrumbs: MentionItem[];\n loading: boolean;\n trigger: string | null;\n query: string;\n clientRect: (() => DOMRect | null) | null;\n onSelect: (item: MentionItem) => void;\n onHover: (index: number) => void;\n onGoBack: () => void;\n onSearchNested?: (query: string) => void;\n onNavigateUp?: () => void;\n onNavigateDown?: () => void;\n onClose?: () => void;\n onFocusEditor?: () => void;\n renderItem?: (item: MentionItem, depth: number) => ReactNode;\n renderEmpty?: (query: string) => ReactNode;\n renderLoading?: () => ReactNode;\n renderGroupHeader?: (group: string) => ReactNode;\n listboxId: string;\n};\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport function SuggestionList({\n items,\n activeIndex,\n breadcrumbs,\n loading,\n trigger,\n query,\n clientRect,\n onSelect,\n onHover,\n onGoBack,\n onSearchNested,\n onNavigateUp,\n onNavigateDown,\n onClose,\n onFocusEditor,\n renderItem,\n renderEmpty,\n renderLoading,\n renderGroupHeader,\n listboxId,\n}: SuggestionListProps) {\n const listRef = useRef<HTMLDivElement>(null);\n const searchInputRef = useRef<HTMLInputElement>(null);\n const depth = breadcrumbs.length;\n const [nestedQuery, setNestedQuery] = useState(\"\");\n\n const breadcrumbKey = breadcrumbs.map((b) => b.id).join(\"/\");\n const prevBreadcrumbKey = useRef(breadcrumbKey);\n useEffect(() => {\n if (prevBreadcrumbKey.current !== breadcrumbKey) {\n setNestedQuery(\"\");\n prevBreadcrumbKey.current = breadcrumbKey;\n }\n }, [breadcrumbKey]);\n\n const prevBreadcrumbsLen = useRef(breadcrumbs.length);\n useEffect(() => {\n if (prevBreadcrumbsLen.current > 0 && breadcrumbs.length === 0) {\n onFocusEditor?.();\n } else if (breadcrumbs.length > 0 && searchInputRef.current) {\n requestAnimationFrame(() => searchInputRef.current?.focus());\n }\n prevBreadcrumbsLen.current = breadcrumbs.length;\n }, [breadcrumbKey, breadcrumbs.length, onFocusEditor]);\n\n useEffect(() => {\n if (!listRef.current) return;\n const active = listRef.current.querySelector('[aria-selected=\"true\"]');\n active?.scrollIntoView({ block: \"nearest\" });\n }, [activeIndex]);\n\n const { style, position } = usePopoverPosition(clientRect);\n\n const activeQuery = breadcrumbs.length > 0 ? nestedQuery : query;\n const showEmpty = !loading && items.length === 0 && activeQuery.trim().length > 0;\n\n if (items.length === 0 && !loading && !showEmpty) return null;\n\n const handleSearchKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n switch (e.key) {\n case \"ArrowDown\":\n e.preventDefault();\n onNavigateDown?.();\n break;\n case \"ArrowUp\":\n e.preventDefault();\n onNavigateUp?.();\n break;\n case \"Enter\": {\n e.preventDefault();\n e.stopPropagation();\n const selectedItem = items[activeIndex];\n if (selectedItem) onSelect(selectedItem);\n break;\n }\n case \"Escape\":\n e.preventDefault();\n onFocusEditor?.();\n onClose?.();\n break;\n case \"ArrowLeft\":\n if (nestedQuery === \"\" || e.currentTarget.selectionStart === 0) {\n e.preventDefault();\n onGoBack();\n }\n break;\n case \"ArrowRight\": {\n const item = items[activeIndex];\n if (item?.hasChildren) {\n e.preventDefault();\n onSelect(item);\n }\n break;\n }\n case \"Backspace\":\n if (nestedQuery === \"\") {\n e.preventDefault();\n onGoBack();\n }\n break;\n }\n };\n\n const hasGroups = items.some((item) => item.group);\n\n return (\n <div\n data-suggestions=\"\"\n data-trigger={trigger}\n data-suggestions-position={position}\n style={style}\n ref={listRef}\n >\n {breadcrumbs.length > 0 && (\n <div data-suggestion-breadcrumb=\"\">\n <button\n type=\"button\"\n data-suggestion-back=\"\"\n onClick={onGoBack}\n aria-label=\"Go back\"\n >\n &larr;\n </button>\n {breadcrumbs.map((crumb, i) => (\n <span key={crumb.id} data-suggestion-breadcrumb-item=\"\">\n {i > 0 && <span data-suggestion-breadcrumb-sep=\"\">/</span>}\n {crumb.label}\n </span>\n ))}\n </div>\n )}\n\n {breadcrumbs.length > 0 && (\n <div data-suggestion-search=\"\">\n <input\n ref={searchInputRef}\n type=\"text\"\n data-suggestion-search-input=\"\"\n placeholder=\"Search...\"\n value={nestedQuery}\n onChange={(e) => {\n const q = e.target.value;\n setNestedQuery(q);\n onSearchNested?.(q);\n }}\n onKeyDown={handleSearchKeyDown}\n autoComplete=\"off\"\n spellCheck={false}\n />\n </div>\n )}\n\n {loading && (\n <div data-suggestion-loading=\"\">\n {renderLoading ? renderLoading() : \"Loading...\"}\n </div>\n )}\n\n {showEmpty && (\n <div data-suggestion-empty=\"\">\n {renderEmpty ? renderEmpty(activeQuery) : \"No results\"}\n </div>\n )}\n\n {!loading && items.length > 0 && (\n <div {...listboxAttrs(listboxId, `${trigger ?? \"\"} suggestions`)}>\n {hasGroups\n ? renderGroupedItems(items, activeIndex, depth, onSelect, onHover, renderItem, renderGroupHeader)\n : items.map((item, index) => (\n <SuggestionItem\n key={item.id}\n item={item}\n index={index}\n isActive={index === activeIndex}\n depth={depth}\n onSelect={onSelect}\n onHover={onHover}\n renderItem={renderItem}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Grouped rendering */\n/* ------------------------------------------------------------------ */\n\nfunction renderGroupedItems(\n items: MentionItem[],\n activeIndex: number,\n depth: number,\n onSelect: (item: MentionItem) => void,\n onHover: (index: number) => void,\n renderItem?: (item: MentionItem, depth: number) => ReactNode,\n renderGroupHeader?: (group: string) => ReactNode,\n) {\n const elements: ReactNode[] = [];\n let lastGroup: string | undefined;\n\n items.forEach((item, index) => {\n if (item.group && item.group !== lastGroup) {\n lastGroup = item.group;\n elements.push(\n <div key={`group-${item.group}`} data-suggestion-group-header=\"\">\n {renderGroupHeader ? renderGroupHeader(item.group) : item.group}\n </div>,\n );\n }\n\n elements.push(\n <SuggestionItem\n key={item.id}\n item={item}\n index={index}\n isActive={index === activeIndex}\n depth={depth}\n onSelect={onSelect}\n onHover={onHover}\n renderItem={renderItem}\n />,\n );\n });\n\n return elements;\n}\n\n/* ------------------------------------------------------------------ */\n/* Single item */\n/* ------------------------------------------------------------------ */\n\nfunction SuggestionItem({\n item,\n index,\n isActive,\n depth,\n onSelect,\n onHover,\n renderItem,\n}: {\n item: MentionItem;\n index: number;\n isActive: boolean;\n depth: number;\n onSelect: (item: MentionItem) => void;\n onHover: (index: number) => void;\n renderItem?: (item: MentionItem, depth: number) => ReactNode;\n}) {\n const itemId = `mention-option-${item.id}`;\n\n return (\n <div\n {...optionAttrs(itemId, isActive, index)}\n data-suggestion-item=\"\"\n data-suggestion-item-active={isActive ? \"\" : undefined}\n data-has-children={item.hasChildren ? \"\" : undefined}\n onMouseEnter={() => onHover(index)}\n onClick={() => onSelect(item)}\n >\n {renderItem ? (\n renderItem(item, depth)\n ) : (\n <DefaultSuggestionItem item={item} />\n )}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Default item render */\n/* ------------------------------------------------------------------ */\n\nfunction DefaultSuggestionItem({ item }: { item: MentionItem }) {\n return (\n <>\n {item.icon && (\n <span data-suggestion-item-icon=\"\">{item.icon}</span>\n )}\n <span data-suggestion-item-label=\"\">{item.label}</span>\n {item.description && (\n <span data-suggestion-item-description=\"\">{item.description}</span>\n )}\n {item.hasChildren && (\n <span data-suggestion-item-chevron=\"\" aria-hidden=\"true\">\n &rsaquo;\n </span>\n )}\n </>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Popover positioning with edge-aware flipping */\n/* ------------------------------------------------------------------ */\n\nconst POPOVER_HEIGHT_ESTIMATE = 280;\nconst POPOVER_WIDTH_ESTIMATE = 360;\n\nfunction usePopoverPosition(\n clientRect: (() => DOMRect | null) | null,\n): { style: React.CSSProperties; position: \"above\" | \"below\" } {\n if (!clientRect) {\n return { style: { display: \"none\" }, position: \"below\" };\n }\n\n const rect = clientRect();\n if (!rect) {\n return { style: { display: \"none\" }, position: \"below\" };\n }\n\n const viewportH = typeof window !== \"undefined\" ? window.innerHeight : 800;\n const viewportW = typeof window !== \"undefined\" ? window.innerWidth : 1200;\n\n const spaceBelow = viewportH - rect.bottom;\n const shouldFlip = spaceBelow < POPOVER_HEIGHT_ESTIMATE && rect.top > spaceBelow;\n\n let left = rect.left;\n if (left + POPOVER_WIDTH_ESTIMATE > viewportW) {\n left = Math.max(0, viewportW - POPOVER_WIDTH_ESTIMATE);\n }\n\n if (shouldFlip) {\n return {\n style: {\n position: \"fixed\",\n left: `${left}px`,\n bottom: `${viewportH - rect.top + 4}px`,\n zIndex: 50,\n },\n position: \"above\",\n };\n }\n\n return {\n style: {\n position: \"fixed\",\n left: `${left}px`,\n top: `${rect.bottom + 4}px`,\n zIndex: 50,\n },\n position: \"below\",\n };\n}\n","/**\n * Generates ARIA attributes for the suggestion combobox pattern.\n */\n\nexport function comboboxAttrs(expanded: boolean, listboxId: string) {\n return {\n role: \"combobox\" as const,\n \"aria-haspopup\": \"listbox\" as const,\n \"aria-expanded\": expanded,\n \"aria-owns\": expanded ? listboxId : undefined,\n };\n}\n\nexport function listboxAttrs(id: string, label: string) {\n return {\n id,\n role: \"listbox\" as const,\n \"aria-label\": label,\n };\n}\n\nexport function optionAttrs(\n id: string,\n selected: boolean,\n index: number,\n) {\n return {\n id,\n role: \"option\" as const,\n \"aria-selected\": selected,\n \"aria-posinset\": index + 1,\n };\n}\n","import { useCallback, useState } from \"react\";\nimport type { MentionsOutput } from \"../types/MentionsOutput\";\n\nexport function useMentionsContent() {\n const [output, setOutput] = useState<MentionsOutput | null>(null);\n const onChange = useCallback((o: MentionsOutput) => setOutput(o), []);\n\n return {\n output,\n onChange,\n hasContent: (output?.plainText ?? \"\").trim().length > 0,\n };\n}\n"],"mappings":";AAAA,SAAgB,YAAY,eAAAA,cAAa,OAAO,2BAA2B;AAC3E,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;;;ACF9B,SAAS,aAAa,WAAW,SAAS,cAAc;AAExD,SAAS,iBAAiB;AAC1B,OAAO,gBAAgB;AACvB,OAAO,iBAAiB;AACxB,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,UAAAC,SAAQ,aAAAC,kBAAiB;;;ACNlC,SAAS,iBAAiB,YAAY;AAWtC,IAAM,mBAA2C;AAAA,EAC/C,WAAW;AAAA,EACX,UAAU;AAAA,EACV,MAAM;AAAA,EACN,KAAK;AACP;AAOO,IAAM,cAAc,KAAK,OAA2B;AAAA,EACzD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,WAAW;AAAA,EAEX,aAAa;AACX,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,YAAY;AAAA,IACd;AAAA,EACF;AAAA,EAEA,gBAAgB;AACd,WAAO;AAAA,MACL,IAAI;AAAA,QACF,SAAS;AAAA,QACT,WAAW,CAAC,YAAY,QAAQ,aAAa,SAAS;AAAA,QACtD,YAAY,CAAC,gBAAgB,EAAE,WAAW,WAAW,GAAG;AAAA,MAC1D;AAAA,MACA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW,CAAC,YAAY,QAAQ,aAAa,YAAY;AAAA,QACzD,YAAY,CAAC,gBAAgB,EAAE,cAAc,WAAW,MAAM;AAAA,MAChE;AAAA,MACA,YAAY;AAAA,QACV,SAAS;AAAA,QACT,WAAW,CAAC,YAAY,QAAQ,aAAa,WAAW;AAAA,QACxD,YAAY,CAAC,gBAAgB,EAAE,aAAa,WAAW,WAAW;AAAA,MACpE;AAAA,MACA,WAAW;AAAA,QACT,SAAS;AAAA,QACT,WAAW,CAAC,YAAY,QAAQ,aAAa,iBAAiB;AAAA,QAC9D,YAAY,CAAC,eACX,WAAW,YACP,EAAE,mBAAmB,WAAW,UAAU,IAC1C,CAAC;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YAAY;AACV,WAAO,CAAC,EAAE,KAAK,qBAAqB,CAAC;AAAA,EACvC;AAAA,EAEA,WAAW,EAAE,MAAM,eAAe,GAAG;AACnC,UAAM,aAAa,KAAK,MAAM;AAC9B,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,SAAS,iBAAiB,UAAU,KAAK;AAC/C,UAAM,UAAU,GAAG,MAAM,GAAG,KAAK;AAEjC,UAAM,WAAW,CAAC,CAAC,KAAK,QAAQ,YAAY;AAC5C,UAAM,aAAqC,CAAC;AAC5C,QAAI,UAAU;AACZ,iBAAW,wBAAwB,IAAI;AAAA,IACzC;AAEA,WAAO;AAAA,MACL;AAAA,MACA,gBAAgB,gBAAgB;AAAA,QAC9B,gBAAgB;AAAA,QAChB,OAAO;AAAA,QACP,GAAG;AAAA,MACL,CAAC;AAAA,MACD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,KAAK,GAAG;AACnB,UAAM,aAAa,KAAK,MAAM;AAC9B,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,SAAS,iBAAiB,UAAU,KAAK;AAC/C,WAAO,GAAG,MAAM,GAAG,KAAK;AAAA,EAC1B;AAAA,EAEA,cAAc;AACZ,UAAM,UAAU,KAAK;AAErB,WAAO,CAAC,EAAE,MAAM,eAAe,MAAM;AACnC,YAAM,aAAa,KAAK,MAAM;AAC9B,YAAM,QAAQ,KAAK,MAAM;AACzB,YAAM,KAAK,KAAK,MAAM;AACtB,YAAM,SAAS,iBAAiB,UAAU,KAAK;AAE/C,YAAM,MAAM,SAAS,cAAc,MAAM;AACzC,aAAO;AAAA,QACL,gBAAgB,gBAAgB;AAAA,UAC9B,gBAAgB;AAAA,UAChB,aAAa;AAAA,UACb,WAAW;AAAA,UACX,OAAO;AAAA,QACT,CAAC;AAAA,MACH,EAAE,QAAQ,CAAC,CAAC,KAAK,GAAG,MAAM;AACxB,YAAI,OAAO,QAAQ,QAAQ,MAAO,KAAI,aAAa,KAAK,OAAO,GAAG,CAAC;AAAA,MACrE,CAAC;AAED,UAAI,cAAc,GAAG,MAAM,GAAG,KAAK;AAEnC,UAAI,QAAQ,YAAY,SAAS;AAC/B,YAAI,aAAa,0BAA0B,EAAE;AAC7C,YAAI,MAAM,SAAS;AAAA,MACrB;AAEA,UAAI,iBAAiB,SAAS,CAAC,UAAU;AACvC,cAAM,UAAU,QAAQ,YAAY;AACpC,YAAI,SAAS;AACX,gBAAM,eAAe;AACrB,gBAAM,gBAAgB;AACtB,kBAAQ,EAAE,IAAI,MAAM,YAAY,MAAM,GAAG,KAAK;AAAA,QAChD;AAAA,MACF,CAAC;AAGD,UAAI,UAA8B;AAElC,UAAI,iBAAiB,cAAc,MAAM;AACvC,cAAM,UAAU,QAAQ,YAAY;AACpC,YAAI,CAAC,QAAS;AAEd,cAAM,UAAU,QAAQ,EAAE,IAAI,MAAM,YAAY,MAAM,CAAC;AACvD,YAAI,CAAC,QAAS;AAEd,kBAAU,SAAS,cAAc,KAAK;AACtC,gBAAQ,aAAa,wBAAwB,EAAE;AAC/C,gBAAQ,cAAc,OAAO,YAAY,WAAW,UAAU;AAC9D,YAAI,MAAM,WAAW;AACrB,YAAI,YAAY,OAAO;AAAA,MACzB,CAAC;AAED,UAAI,iBAAiB,cAAc,MAAM;AACvC,YAAI,WAAW,QAAQ,YAAY;AACjC,kBAAQ,WAAW,YAAY,OAAO;AACtC,oBAAU;AAAA,QACZ;AAAA,MACF,CAAC;AAED,aAAO,EAAE,IAAI;AAAA,IACf;AAAA,EACF;AAAA,EAEA,uBAAuB;AACrB,WAAO;AAAA,MACL,WAAW,MACT,KAAK,OAAO,SAAS,QAAQ,CAAC,EAAE,IAAI,MAAM,MAAM;AAC9C,YAAI,YAAY;AAChB,cAAM,EAAE,UAAU,IAAI;AACtB,cAAM,EAAE,OAAO,OAAO,IAAI;AAE1B,YAAI,CAAC,MAAO,QAAO;AAEnB,cAAM,IAAI,aAAa,SAAS,GAAG,QAAQ,CAAC,MAAM,QAAQ;AACxD,cAAI,KAAK,KAAK,SAAS,KAAK,MAAM;AAChC,wBAAY;AACZ,eAAG,WAAW,IAAI,KAAK,MAAM,KAAK,QAAQ;AAAA,UAC5C;AAAA,QACF,CAAC;AAED,eAAO;AAAA,MACT,CAAC;AAAA,IACL;AAAA,EACF;AACF,CAAC;;;AC1LD,SAAS,iBAAiB;AAC1B,SAAS,QAAQ,iBAAiB;AA6ClC,SAAS,cACP,MACA,WACA,aACA,UACqB;AACrB,QAAM,YAAY,YAAY;AAC9B,QAAM,SAAS,KAAK,MAAM,GAAG,SAAS;AAEtC,WAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,UAAM,KAAK,OAAO,CAAC;AACnB,QAAI,OAAO,KAAM,QAAO;AAExB,eAAW,WAAW,UAAU;AAC9B,UAAI,OAAO,UAAU,GAAG,IAAI,QAAQ,MAAM,MAAM,SAAS;AACvD,YAAI,MAAM,KAAK,KAAK,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG;AACvC,gBAAM,QAAQ,OAAO,MAAM,IAAI,QAAQ,MAAM;AAC7C,iBAAO;AAAA,YACL;AAAA,YACA;AAAA,YACA,MAAM,cAAc;AAAA,YACpB,IAAI;AAAA,YACJ,YAAY,OAAO,MAAM,GAAG,CAAC;AAAA,UAC/B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,IAAM,sBAAsB,IAAI,UAAU,mBAAmB;AAkBtD,SAAS,0BACd,UACA,cACA,iBACA,cACA;AACA,SAAO,UAAU,OAAO;AAAA,IACtB,MAAM;AAAA,IACN,UAAU;AAAA,IAEV,wBAAwB;AACtB,YAAM,SAAS,KAAK;AACpB,UAAI,SAAS;AACb,UAAI,YAA2B;AAC/B,UAAI,cAA6B;AAEjC,YAAM,gBAAgB,CACpB,MACA,SAC2B;AAC3B,eAAO,MAAM;AACX,cAAI;AACF,kBAAM,SAAS,KAAK,YAAY,IAAI;AACpC,mBAAO,IAAI;AAAA,cACT,OAAO;AAAA,cACP,OAAO;AAAA,cACP;AAAA,cACA,OAAO,SAAS,OAAO;AAAA,YACzB;AAAA,UACF,QAAQ;AACN,mBAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,YAAM,cAAc,CAAC,UAAwC;AAC3D,eAAO,CAAC,UAAmC;AACzC,iBACG,MAAM,EACN,MAAM,EACN,gBAAgB,OAAO;AAAA,YACtB;AAAA,cACE,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,IAAI,MAAM;AAAA,gBACV,OAAO,MAAM;AAAA,gBACb,YAAY,MAAM;AAAA,gBAClB,WAAW,MAAM,aAAa;AAAA,cAChC;AAAA,YACF;AAAA,YACA,EAAE,MAAM,QAAQ,MAAM,IAAI;AAAA,UAC5B,CAAC,EACA,IAAI;AAAA,QACT;AAAA,MACF;AAEA,YAAM,SAAS,IAAI,OAAO;AAAA,QACxB,KAAK;AAAA,QAEL,OAAO;AAAA,UACL,cAAc,OAAO,OAAO;AAC1B,gBAAI,CAAC,OAAQ,QAAO;AACpB,mBAAO,aAAa,QAAQ,UAAU,EAAE,MAAM,CAAC;AAAA,UACjD;AAAA,QACF;AAAA,QAEA,OAAO;AACL,iBAAO;AAAA,YACL,OAAO,MAAM,YAAY;AACvB,kBAAI,cAAc,SAAS;AACzB,oBAAI,QAAQ;AACV,2BAAS;AACT,8BAAY;AACZ,gCAAc;AACd,+BAAa,QAAQ,OAAO;AAAA,gBAC9B;AACA;AAAA,cACF;AAEA,oBAAM,EAAE,MAAM,IAAI;AAClB,oBAAM,EAAE,UAAU,IAAI;AAEtB,kBAAI,CAAC,UAAU,OAAO;AACpB,oBAAI,QAAQ;AACV,2BAAS;AACT,8BAAY;AACZ,gCAAc;AACd,+BAAa,QAAQ,OAAO;AAAA,gBAC9B;AACA;AAAA,cACF;AAEA,oBAAM,OAAO,UAAU;AACvB,oBAAM,YAAY,KAAK;AAEvB,kBAAI,CAAC,UAAU,aAAa;AAC1B,oBAAI,QAAQ;AACV,2BAAS;AACT,8BAAY;AACZ,gCAAc;AACd,+BAAa,QAAQ,OAAO;AAAA,gBAC9B;AACA;AAAA,cACF;AAEA,oBAAM,aAAa,KAAK,MAAM;AAC9B,oBAAM,YAAY,UAAU;AAC5B,oBAAM,YAAY,KAAK;AAEvB,oBAAM,QAAQ,cAAc,WAAW,WAAW,YAAY,QAAQ;AAEtE,kBAAI,OAAO;AAET,oBAAI,iBAAiB,SAAS;AAC5B,wBAAM,UAAU,gBAAgB,QAAQ,MAAM,SAAS;AAAA,oBACrD,YAAY,MAAM;AAAA,kBACpB,CAAC;AACD,sBAAI,CAAC,SAAS;AACZ,wBAAI,QAAQ;AACV,+BAAS;AACT,kCAAY;AACZ,oCAAc;AACd,mCAAa,QAAQ,OAAO;AAAA,oBAC9B;AACA;AAAA,kBACF;AAAA,gBACF;AAEA,sBAAM,QAAQ,EAAE,MAAM,MAAM,MAAM,IAAI,MAAM,GAAG;AAC/C,sBAAM,QAAiC;AAAA,kBACrC,OAAO,MAAM;AAAA,kBACb,SAAS,MAAM;AAAA,kBACf,YAAY,cAAc,MAAM,MAAM,IAAI;AAAA,kBAC1C;AAAA,kBACA,SAAS,YAAY,KAAK;AAAA,gBAC5B;AAEA,oBAAI,CAAC,QAAQ;AACX,2BAAS;AACT,8BAAY,MAAM;AAClB,gCAAc,MAAM;AACpB,+BAAa,QAAQ,QAAQ,KAAK;AAAA,gBACpC,WACE,MAAM,UAAU,aAChB,MAAM,YAAY,aAClB;AACA,8BAAY,MAAM;AAClB,gCAAc,MAAM;AACpB,+BAAa,QAAQ,SAAS,KAAK;AAAA,gBACrC;AAAA,cACF,OAAO;AACL,oBAAI,QAAQ;AACV,2BAAS;AACT,8BAAY;AACZ,gCAAc;AACd,+BAAa,QAAQ,OAAO;AAAA,gBAC9B;AAAA,cACF;AAAA,YACF;AAAA,YAEA,UAAU;AACR,kBAAI,QAAQ;AACV,6BAAa,QAAQ,OAAO;AAAA,cAC9B;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAED,aAAO,CAAC,MAAM;AAAA,IAChB;AAAA,EACF,CAAC;AACH;;;ACvQO,SAAS,oBAAoB,KAA0B;AAC5D,MAAI,CAAC,IAAI,QAAS,QAAO;AAEzB,QAAM,QAAkB,CAAC;AAEzB,aAAW,SAAS,IAAI,SAAS;AAC/B,QAAI,MAAM,SAAS,aAAa;AAC9B,YAAM,KAAK,mBAAmB,KAAK,CAAC;AAAA,IACtC,WAAW,MAAM,SAAS,QAAQ;AAChC,YAAM,KAAK,MAAM,QAAQ,EAAE;AAAA,IAC7B;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,mBAAmB,MAA2B;AACrD,MAAI,CAAC,KAAK,QAAS,QAAO;AAE1B,SAAO,KAAK,QACT,IAAI,CAAC,UAAU;AACd,QAAI,MAAM,SAAS,WAAW;AAC5B,YAAM,EAAE,IAAI,OAAO,YAAY,UAAU,IAAI,MAAM,SAAS,CAAC;AAC7D,YAAM,SACJ,cAAc,eAAe,YACzB,GAAG,UAAU,IAAI,EAAE,KACnB;AACN,UAAI,aAAa,QAAQ,cAAc,IAAI;AACzC,eAAO,IAAI,SAAS,IAAI,KAAK,KAAK,MAAM;AAAA,MAC1C;AACA,aAAO,KAAK,KAAK,KAAK,MAAM;AAAA,IAC9B;AACA,WAAO,MAAM,QAAQ;AAAA,EACvB,CAAC,EACA,KAAK,EAAE;AACZ;AAKO,SAAS,cAAc,KAAkC;AAC9D,QAAM,SAAyB,CAAC;AAEhC,WAAS,KAAK,MAAmB;AAC/B,QAAI,KAAK,SAAS,aAAa,KAAK,OAAO;AACzC,aAAO,KAAK;AAAA,QACV,IAAI,KAAK,MAAM;AAAA,QACf,MAAM,KAAK,MAAM;AAAA,QACjB,OAAO,KAAK,MAAM;AAAA,MACpB,CAAC;AAAA,IACH;AACA,QAAI,KAAK,SAAS;AAChB,iBAAW,SAAS,KAAK,SAAS;AAChC,aAAK,KAAK;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAEA,OAAK,GAAG;AACR,SAAO;AACT;AAMO,SAAS,iBAAiB,KAA0B;AACzD,MAAI,CAAC,IAAI,QAAS,QAAO;AAEzB,QAAM,QAAkB,CAAC;AAEzB,aAAW,SAAS,IAAI,SAAS;AAC/B,QAAI,MAAM,SAAS,aAAa;AAC9B,YAAM,KAAK,qBAAqB,KAAK,CAAC;AAAA,IACxC;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,qBAAqB,MAA2B;AACvD,MAAI,CAAC,KAAK,QAAS,QAAO;AAE1B,SAAO,KAAK,QACT,IAAI,CAAC,UAAU;AACd,QAAI,MAAM,SAAS,WAAW;AAC5B,aAAO,MAAM,OAAO,SAAS;AAAA,IAC/B;AACA,WAAO,MAAM,QAAQ;AAAA,EACvB,CAAC,EACA,KAAK,EAAE;AACZ;;;ACvFA,IAAM,aAAa;AAMZ,SAAS,kBAAkB,UAA+B;AAC/D,QAAM,QAAQ,SAAS,MAAM,IAAI;AAEjC,QAAM,UAAyB,MAAM,IAAI,CAAC,SAAS;AACjD,UAAM,WAAW,UAAU,IAAI;AAC/B,WAAO,SAAS,SAAS,IACrB,EAAE,MAAM,aAAa,SAAS,SAAS,IACvC,EAAE,MAAM,YAAY;AAAA,EAC1B,CAAC;AAED,SAAO,EAAE,MAAM,OAAO,QAAQ;AAChC;AAEA,SAAS,UAAU,MAA6B;AAC9C,QAAM,QAAuB,CAAC;AAC9B,MAAI,YAAY;AAGhB,aAAW,YAAY;AAEvB,MAAI;AACJ,UAAQ,QAAQ,WAAW,KAAK,IAAI,OAAO,MAAM;AAC/C,UAAM,YAAY,MAAM,CAAC;AACzB,UAAM,YAAY,MAAM,CAAC,KAAK;AAC9B,UAAM,QAAQ,MAAM,CAAC;AACrB,UAAM,aAAa,MAAM,CAAC,KAAK;AAC/B,UAAM,KAAK,MAAM,CAAC;AAGlB,QAAI,MAAM,QAAQ,WAAW;AAC3B,YAAM,KAAK;AAAA,QACT,MAAM;AAAA,QACN,MAAM,KAAK,MAAM,WAAW,MAAM,KAAK;AAAA,MACzC,CAAC;AAAA,IACH;AAGA,UAAM,KAAK;AAAA,MACT,MAAM;AAAA,MACN,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAED,gBAAY,MAAM,QAAQ,UAAU;AAAA,EACtC;AAGA,MAAI,YAAY,KAAK,QAAQ;AAC3B,UAAM,KAAK;AAAA,MACT,MAAM;AAAA,MACN,MAAM,KAAK,MAAM,SAAS;AAAA,IAC5B,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAqBO,SAAS,oBAAoB,UAGlC;AACA,QAAM,MAAM,kBAAkB,QAAQ;AACtC,SAAO;AAAA,IACL,QAAQ,cAAc,GAAG;AAAA,IACzB,WAAW,iBAAiB,GAAG;AAAA,EACjC;AACF;;;AJnFA,SAAS,YAAY,QAAgD;AACnE,QAAM,OAAO,OAAO,QAAQ;AAC5B,SAAO;AAAA,IACL,UAAU,oBAAoB,IAAI;AAAA,IAClC,QAAQ,cAAc,IAAI;AAAA,IAC1B,WAAW,iBAAiB,IAAI;AAAA,EAClC;AACF;AAMA,SAAS,qBAAqB,KAA0B;AACtD,QAAM,SAAyB,CAAC;AAChC,WAAS,KAAK,MAAW;AACvB,QAAI,KAAK,SAAS,aAAa,KAAK,OAAO;AACzC,aAAO,KAAK;AAAA,QACV,IAAI,KAAK,MAAM;AAAA,QACf,MAAM,KAAK,MAAM,cAAc,KAAK,MAAM;AAAA,QAC1C,OAAO,KAAK,MAAM;AAAA,MACpB,CAAC;AAAA,IACH;AACA,QAAI,KAAK,SAAS;AAChB,iBAAW,SAAS,KAAK,QAAS,MAAK,KAAK;AAAA,IAC9C;AAAA,EACF;AACA,OAAK,GAAG;AACR,SAAO;AACT;AAMA,SAAS,sBACP,aACA,kBACA,cACA;AACA,SAAOC,WAAU,OAAO;AAAA,IACtB,MAAM;AAAA,IACN,UAAU;AAAA,IAEV,uBAAuB;AACrB,aAAO;AAAA,QACL,aAAa,MAAM;AACjB,gBAAM,MAAM,aAAa;AACzB,cAAI,QAAQ,eAAe,QAAQ,SAAS;AAC1C,gBAAI,YAAY,SAAS;AACvB,0BAAY,QAAQ,YAAY,KAAK,MAAM,CAAC;AAC5C,kBAAI,iBAAiB,SAAS;AAC5B,qBAAK,OAAO,SAAS,aAAa,IAAI;AAAA,cACxC;AAAA,YACF;AACA,mBAAO;AAAA,UACT;AACA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAMA,IAAM,uBAAuB,IAAIC,WAAU,aAAa;AAExD,SAAS,qBACP,aACA,kBACA,cACA;AACA,SAAOD,WAAU,OAAO;AAAA,IACtB,MAAM;AAAA,IACN,UAAU;AAAA,IAEV,wBAAwB;AACtB,YAAM,SAAS,KAAK;AAEpB,aAAO;AAAA,QACL,IAAIE,QAAO;AAAA,UACT,KAAK;AAAA,UACL,OAAO;AAAA,YACL,cAAc,OAAO,OAAO;AAC1B,kBAAI,MAAM,QAAQ,QAAS,QAAO;AAElC,oBAAM,MAAM,aAAa;AAEzB,kBAAI,QAAQ,OAAQ,QAAO;AAE3B,kBAAI,QAAQ,aAAa;AAGvB,uBAAO;AAAA,cACT;AAGA,kBAAI,MAAM,UAAU;AAClB,uBAAO,SAAS,WAAW;AAC3B,uBAAO;AAAA,cACT;AAEA,kBAAI,MAAM,WAAW,MAAM,QAAS,QAAO;AAE3C,kBAAI,YAAY,SAAS;AACvB,4BAAY,QAAQ,YAAY,MAAM,CAAC;AACvC,oBAAI,iBAAiB,SAAS;AAC5B,yBAAO,SAAS,aAAa,IAAI;AAAA,gBACnC;AAAA,cACF;AACA,qBAAO;AAAA,YACT;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAMA,IAAM,yBAAyB,IAAID,WAAU,eAAe;AAE5D,SAAS,6BACP,oBACA;AACA,SAAOD,WAAU,OAAO;AAAA,IACtB,MAAM;AAAA,IACN,UAAU;AAAA,IAEV,wBAAwB;AACtB,aAAO;AAAA,QACL,IAAIE,QAAO;AAAA,UACT,KAAK;AAAA,UACL,kBAAkB,cAAc,UAAU,UAAU;AAClD,gBAAI,CAAC,mBAAmB,QAAS,QAAO;AAExC,kBAAM,cAAc,qBAAqB,SAAS,IAAI,OAAO,CAAC;AAC9D,kBAAM,cAAc,qBAAqB,SAAS,IAAI,OAAO,CAAC;AAE9D,gBAAI,YAAY,UAAU,YAAY,OAAQ,QAAO;AAErD,kBAAM,SAAS,IAAI,IAAI,YAAY,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AACnD,uBAAW,KAAK,aAAa;AAC3B,kBAAI,CAAC,OAAO,IAAI,EAAE,EAAE,GAAG;AACrB,mCAAmB,QAAQ,CAAC;AAAA,cAC9B;AAAA,YACF;AAEA,mBAAO;AAAA,UACT;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAMA,IAAM,0BAA0B,IAAID,WAAU,gBAAgB;AAE9D,SAAS,8BAA8B,cAA4B;AACjE,SAAOD,WAAU,OAAO;AAAA,IACtB,MAAM;AAAA,IACN,UAAU;AAAA,IAEV,wBAAwB;AACtB,aAAO;AAAA,QACL,IAAIE,QAAO;AAAA,UACT,KAAK;AAAA,UACL,OAAO;AAAA,YACL,gBAAgB;AACd,qBAAO,aAAa;AAAA,YACtB;AAAA,YACA,iBAAiB;AACf,qBAAO,aAAa;AAAA,YACtB;AAAA,YACA,cAAc;AACZ,qBAAO,aAAa;AAAA,YACtB;AAAA,YACA,aAAa;AACX,qBAAO,aAAa;AAAA,YACtB;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAC;AACH;AA4BO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA,YAAY;AAAA,EACZ,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AACF,GAA6B;AAC3B,QAAM,cAAc,OAAO,QAAQ;AACnC,cAAY,UAAU;AAEtB,QAAM,cAAc,OAAO,QAAQ;AACnC,cAAY,UAAU;AAEtB,QAAM,mBAAmB,OAAO,aAAa;AAC7C,mBAAiB,UAAU;AAE3B,QAAM,aAAa,OAAO,OAAO;AACjC,aAAW,UAAU;AAErB,QAAM,YAAY,OAAO,MAAM;AAC/B,YAAU,UAAU;AAEpB,QAAM,eAAe,OAAO,SAAS;AACrC,eAAa,UAAU;AAEvB,QAAM,qBAAqB,OAAO,eAAe;AACjD,qBAAmB,UAAU;AAE7B,QAAM,oBAAoB,OAAO,cAAc;AAC/C,oBAAkB,UAAU;AAE5B,QAAM,oBAAoB,OAAO,cAAc;AAC/C,oBAAkB,UAAU;AAE5B,QAAM,kBAAkB,OAAO,YAAY;AAC3C,kBAAgB,UAAU;AAE1B,QAAM,qBAAqB,OAAO,eAAe;AACjD,qBAAmB,UAAU;AAE7B,QAAM,yBAAyB,OAAO,mBAAmB;AACzD,yBAAuB,UAAU;AAIjC,QAAM,eAAe,OAAgB,SAAS;AAC9C,eAAa,UAAU;AACvB,QAAM,mBAAmB,OAAO,SAAS;AAGzC,QAAM,mBAAmB,OAA6C,IAAI;AAC1E,QAAM,mBAAmB,OAA8B,IAAI;AAG3D,QAAM,sBAAsB,OAAsB,IAAI;AAEtD,QAAM,iBAAiB,QAAQ,MAAM;AACnC,QAAI,CAAC,MAAO,QAAO;AACnB,WAAO,kBAAkB,KAAK;AAAA,EAEhC,GAAG,CAAC,CAAC;AAEL,QAAM,cAAc,UAAU,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,GAAG;AAC5D,QAAM,WAAW;AAAA,IACf,MAAM,UAAU,IAAI,CAAC,MAAM,EAAE,OAAO;AAAA;AAAA,IAEpC,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,sBAAsB;AAAA,IAC1B,MACE;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA,IAEF,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,YAAY;AAAA,IAChB,MAAM,sBAAsB,aAAa,kBAAkB,YAAY;AAAA,IACvE,CAAC;AAAA,EACH;AACA,QAAM,WAAW;AAAA,IACf,MAAM,qBAAqB,aAAa,kBAAkB,YAAY;AAAA,IACtE,CAAC;AAAA,EACH;AACA,QAAM,mBAAmB;AAAA,IACvB,MAAM,6BAA6B,kBAAkB;AAAA,IACrD,CAAC;AAAA,EACH;AAEA,QAAM,oBAAoB;AAAA,IACxB,MAAM,8BAA8B,YAAY;AAAA,IAChD,CAAC;AAAA,EACH;AAEA,QAAM,iBAAiB;AAAA,IACrB,MACE,YAAY,UAAU;AAAA,MACpB,YAAY;AAAA,MACZ,YAAY;AAAA,IACd,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,UAAU;AAAA,IACvB,YAAY;AAAA,MACV,WAAW,UAAU;AAAA,QACnB,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,YAAY;AAAA,QACZ,aAAa;AAAA,QACb,UAAU;AAAA,QACV,gBAAgB;AAAA,QAChB,WAAW;AAAA,MACb,CAAC;AAAA,MACD,YAAY,UAAU;AAAA,QACpB,aAAa,CAAC,EAAE,QAAAC,QAAO,MACrBA,QAAO,UAAW,eAAe,sBAAuB;AAAA,QAC1D,iBAAiB;AAAA,MACnB,CAAC;AAAA,MACD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,SAAS;AAAA,IACT,WAAW,YAAY,QAAQ;AAAA,IAC/B;AAAA,IACA,aAAa;AAAA,MACX,YAAY;AAAA,QACV,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU,CAAC,EAAE,QAAAA,QAAO,MAAM;AACxB,YAAM,SAAS,YAAYA,OAAM;AACjC,0BAAoB,UAAU,OAAO;AAErC,UAAI,aAAa,SAAS;AACxB,yBAAiB,UAAU;AAC3B,YAAI,CAAC,iBAAiB,SAAS;AAC7B,2BAAiB,UAAU,WAAW,MAAM;AAC1C,6BAAiB,UAAU;AAC3B,gBAAI,iBAAiB,SAAS;AAC5B,0BAAY,UAAU,iBAAiB,OAAO;AAC9C,+BAAiB,UAAU;AAAA,YAC7B;AAAA,UACF,GAAG,GAAG;AAAA,QACR;AAAA,MACF,OAAO;AACL,oBAAY,UAAU,MAAM;AAAA,MAC9B;AAAA,IACF;AAAA,IACA,SAAS,MAAM;AACb,iBAAW,UAAU;AAAA,IACvB;AAAA,IACA,QAAQ,MAAM;AACZ,gBAAU,UAAU;AAAA,IACtB;AAAA,EACF,CAAC;AAGD,YAAU,MAAM;AACd,QAAI,iBAAiB,WAAW,CAAC,aAAa,QAAQ;AACpD,UAAI,iBAAiB,SAAS;AAC5B,qBAAa,iBAAiB,OAAO;AACrC,yBAAiB,UAAU;AAAA,MAC7B;AACA,YAAM,SAAS,YAAY,MAAM;AACjC,kBAAY,UAAU,MAAM;AAC5B,6BAAuB,UAAU,MAAM;AACvC,uBAAiB,UAAU;AAAA,IAC7B;AACA,qBAAiB,UAAU;AAAA,EAC7B,GAAG,CAAC,WAAW,MAAM,CAAC;AAGtB,YAAU,MAAM;AACd,WAAO,MAAM;AACX,UAAI,iBAAiB,SAAS;AAC5B,qBAAa,iBAAiB,OAAO;AAAA,MACvC;AAAA,IACF;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,YAAU,MAAM;AACd,QAAI,UAAU,OAAO,eAAe,UAAU;AAC5C,aAAO,YAAY,QAAQ;AAAA,IAC7B;AAAA,EACF,GAAG,CAAC,QAAQ,QAAQ,CAAC;AAGrB,YAAU,MAAM;AACd,QAAI,CAAC,UAAU,UAAU,OAAW;AACpC,QAAI,UAAU,oBAAoB,QAAS;AAC3C,UAAM,MAAM,kBAAkB,KAAK;AACnC,WAAO,SAAS,WAAW,GAAG;AAC9B,wBAAoB,UAAU;AAAA,EAChC,GAAG,CAAC,QAAQ,KAAK,CAAC;AAGlB,YAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,gBAAiB;AAEjC,UAAM,gBAAgB,YAAY;AAChC,YAAM,MAAM,OAAO,QAAQ;AAC3B,YAAM,SAAS,qBAAqB,GAAG;AACvC,YAAM,aAAa,oBAAI,IAAY;AAEnC,YAAM,QAAQ;AAAA,QACZ,OAAO,IAAI,OAAO,UAAU;AAC1B,gBAAM,QAAQ,MAAM,gBAAgB,KAAK;AACzC,cAAI,CAAC,MAAO,YAAW,IAAI,MAAM,EAAE;AAAA,QACrC,CAAC;AAAA,MACH;AAEA,aAAO,KAAK,IAAI,iBAAiB,gBAAgB,EAAE,QAAQ,CAAC,OAAO;AACjE,cAAM,KAAK,GAAG,aAAa,SAAS;AACpC,YAAI,MAAM,WAAW,IAAI,EAAE,GAAG;AAC5B,aAAG,aAAa,wBAAwB,EAAE;AAAA,QAC5C,OAAO;AACL,aAAG,gBAAgB,sBAAsB;AAAA,QAC3C;AAAA,MACF,CAAC;AAAA,IACH;AAEA,kBAAc;AAAA,EAChB,GAAG,CAAC,QAAQ,eAAe,CAAC;AAM5B,QAAM,QAAQ,YAAY,MAAM;AAC9B,YAAQ,SAAS,aAAa,IAAI;AAAA,EACpC,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,aAAa;AAAA,IACjB,CAAC,aAAqB;AACpB,UAAI,CAAC,OAAQ;AACb,YAAM,MAAM,kBAAkB,QAAQ;AACtC,aAAO,SAAS,WAAW,GAAG;AAC9B,0BAAoB,UAAU;AAC9B,UAAI,aAAa,SAAS;AACxB,eAAO,SAAS,MAAM,KAAK;AAAA,MAC7B;AAAA,IACF;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,aAAa;AAAA,IACjB,CAAC,SAAiB;AAChB,UAAI,CAAC,OAAQ;AACb,YAAM,SAAS,OAAO,MAAM,IAAI,QAAQ,OAAO;AAC/C,aAAO,SAAS,gBAAgB,QAAQ,IAAI;AAC5C,UAAI,aAAa,SAAS;AACxB,eAAO,SAAS,MAAM,KAAK;AAAA,MAC7B;AAAA,IACF;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,QAAQ,YAAY,MAAM;AAC9B,YAAQ,SAAS,MAAM,KAAK;AAAA,EAC9B,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,YAAY,YAAY,MAA6B;AACzD,QAAI,CAAC,OAAQ,QAAO;AACpB,WAAO,YAAY,MAAM;AAAA,EAC3B,GAAG,CAAC,MAAM,CAAC;AAEX,SAAO,EAAE,QAAQ,WAAW,OAAO,YAAY,YAAY,MAAM;AACnE;;;AK7hBA,SAAS,eAAAC,cAAa,aAAAC,YAAW,UAAAC,SAAQ,gBAAgB;;;ACKlD,SAAS,SACd,IACA,IAC4B;AAC5B,MAAI,QAA8C;AAElD,QAAM,aAAa,IAAI,SAAgB;AACrC,QAAI,SAAS,KAAM,cAAa,KAAK;AACrC,YAAQ,WAAW,MAAM;AACvB,cAAQ;AACR,SAAG,GAAG,IAAI;AAAA,IACZ,GAAG,EAAE;AAAA,EACP;AAEA,YAAU,SAAS,MAAM;AACvB,QAAI,SAAS,MAAM;AACjB,mBAAa,KAAK;AAClB,cAAQ;AAAA,IACV;AAAA,EACF;AAEA,SAAO;AACT;;;ADYA,IAAM,aAAgC;AAAA,EACpC,OAAO;AAAA,EACP,OAAO,CAAC;AAAA,EACR,aAAa,CAAC;AAAA,EACd,aAAa;AAAA,EACb,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,OAAO;AACT;AAMO,SAAS,cACd,WACA,UAAiC,CAAC,GAClC;AACA,QAAM,CAAC,SAAS,UAAU,IAAI,SAA4B,UAAU;AAEpE,QAAM,WAAWC,QAAO,OAAO;AAC/B,WAAS,UAAU;AAEnB,QAAM,eAAeA,QAAO,SAAS;AACrC,eAAa,UAAU;AAEvB,QAAM,kBAAkBA,QAAO,QAAQ,YAAY;AACnD,kBAAgB,UAAU,QAAQ;AAElC,QAAM,aAAaA;AAAA,IACjB;AAAA,EACF;AACA,QAAM,cAAcA,QAA+B,IAAI;AAEvD,QAAM,oBAAoBA,QAA2C,IAAI;AAEzE,EAAAC,WAAU,MAAM;AACd,WAAO,MAAM;AACX,wBAAkB,SAAS,OAAO;AAAA,IACpC;AAAA,EACF,GAAG,CAAC,CAAC;AAML,QAAM,aAAaC;AAAA,IACjB,OACE,UACA,OACA,QACA,iBACG;AACH,iBAAW,CAAC,UAAU,EAAE,GAAG,MAAM,SAAS,MAAM,OAAO,UAAU,EAAE;AAEnE,UAAI;AACF,YAAI;AAEJ,YAAI,gBAAgB,SAAS,WAAW;AACtC,kBAAQ,MAAM,SAAS,UAAU,KAAK;AAAA,QACxC,WAAW,UAAU,SAAS,aAAa;AACzC,kBAAQ,MAAM,SAAS,YAAY,QAAQ,KAAK;AAAA,QAClD,OAAO;AACL,kBAAQ,MAAM,SAAS,aAAa,KAAK;AAAA,QAC3C;AAEA,mBAAW,CAAC,UAAU;AAAA,UACpB,GAAG;AAAA,UACH;AAAA,UACA,SAAS;AAAA,UACT,OAAO;AAAA,UACP,aAAa;AAAA,QACf,EAAE;AAAA,MACJ,QAAQ;AACN,mBAAW,CAAC,UAAU;AAAA,UACpB,GAAG;AAAA,UACH,OAAO,CAAC;AAAA,UACR,SAAS;AAAA,UACT,OAAO;AAAA,QACT,EAAE;AAAA,MACJ;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,gBAAgBA;AAAA,IACpB,CACE,UACA,OACA,QACA,iBACG;AACH,wBAAkB,SAAS,OAAO;AAElC,YAAM,KAAK,SAAS;AACpB,UAAI,MAAM,KAAK,GAAG;AAChB,mBAAW,CAAC,UAAU,EAAE,GAAG,MAAM,SAAS,KAAK,EAAE;AACjD,cAAM,cAAc,SAAS,MAAM;AACjC,qBAAW,UAAU,OAAO,QAAQ,YAAY;AAAA,QAClD,GAAG,EAAE;AACL,0BAAkB,UAAU;AAC5B,oBAAY;AAAA,MACd,OAAO;AACL,mBAAW,UAAU,OAAO,QAAQ,YAAY;AAAA,MAClD;AAAA,IACF;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAMA,QAAM,UAAUA;AAAA,IACd,CAAC,UAAmC;AAClC,YAAM,WAAW,aAAa,QAAQ;AAAA,QACpC,CAAC,MAAM,EAAE,YAAY,MAAM;AAAA,MAC7B;AACA,UAAI,CAAC,SAAU;AAEf,kBAAY,UAAU;AACtB,iBAAW,UAAU,MAAM;AAE3B,iBAAW;AAAA,QACT,OAAO;AAAA,QACP,OAAO,CAAC;AAAA,QACR,aAAa,CAAC;AAAA,QACd,aAAa;AAAA,QACb,SAAS;AAAA,QACT,YAAY,MAAM;AAAA,QAClB,SAAS,MAAM;AAAA,QACf,OAAO,MAAM;AAAA,MACf,CAAC;AAED,UAAI,CAAC,MAAM,MAAM,KAAK,KAAK,SAAS,gBAAgB;AAClD,iBAAS,eAAe,EAAE,KAAK,CAAC,gBAAgB;AAC9C,gBAAM,SAAS,YAAY,IAAI,CAAC,UAAU;AAAA,YACxC,GAAG;AAAA,YACH,OAAO,KAAK,SAAS;AAAA,UACvB,EAAE;AACF,qBAAW,CAAC,UAAU;AAAA,YACpB,GAAG;AAAA,YACH,OAAO;AAAA,YACP,SAAS;AAAA,YACT,OAAO;AAAA,YACP,aAAa;AAAA,UACf,EAAE;AAAA,QACJ,CAAC,EAAE,MAAM,MAAM;AACb,wBAAc,UAAU,MAAM,KAAK;AAAA,QACrC,CAAC;AACD;AAAA,MACF;AAEA,UAAI,MAAM,MAAM,KAAK,KAAK,SAAS,WAAW;AAC5C,sBAAc,UAAU,MAAM,OAAO,QAAW,IAAI;AAAA,MACtD,OAAO;AACL,sBAAc,UAAU,MAAM,KAAK;AAAA,MACrC;AAAA,IACF;AAAA,IACA,CAAC,aAAa;AAAA,EAChB;AAEA,QAAM,WAAWA;AAAA,IACf,CAAC,UAAmC;AAClC,YAAM,WAAW,YAAY;AAC7B,UAAI,CAAC,SAAU;AAEf,iBAAW,UAAU,MAAM;AAC3B,YAAM,UAAU,SAAS;AAEzB,UAAI,QAAQ,YAAY,SAAS,GAAG;AAClC,mBAAW,CAAC,UAAU;AAAA,UACpB,GAAG;AAAA,UACH,aAAa,CAAC;AAAA,UACd,YAAY,MAAM;AAAA,UAClB,OAAO,MAAM;AAAA,UACb,aAAa;AAAA,QACf,EAAE;AAAA,MACJ,OAAO;AACL,mBAAW,CAAC,UAAU;AAAA,UACpB,GAAG;AAAA,UACH,YAAY,MAAM;AAAA,UAClB,OAAO,MAAM;AAAA,QACf,EAAE;AAAA,MACJ;AAEA,UAAI,MAAM,MAAM,KAAK,KAAK,SAAS,WAAW;AAC5C,sBAAc,UAAU,MAAM,OAAO,QAAW,IAAI;AAAA,MACtD,WAAW,CAAC,MAAM,MAAM,KAAK,KAAK,SAAS,gBAAgB;AACzD,iBAAS,eAAe,EAAE,KAAK,CAAC,gBAAgB;AAC9C,gBAAM,SAAS,YAAY,IAAI,CAAC,UAAU;AAAA,YACxC,GAAG;AAAA,YACH,OAAO,KAAK,SAAS;AAAA,UACvB,EAAE;AACF,qBAAW,CAAC,UAAU;AAAA,YACpB,GAAG;AAAA,YACH,OAAO;AAAA,YACP,SAAS;AAAA,YACT,OAAO;AAAA,YACP,aAAa;AAAA,UACf,EAAE;AAAA,QACJ,CAAC,EAAE,MAAM,MAAM;AACb,wBAAc,UAAU,MAAM,KAAK;AAAA,QACrC,CAAC;AAAA,MACH,OAAO;AACL,sBAAc,UAAU,MAAM,KAAK;AAAA,MACrC;AAAA,IACF;AAAA,IACA,CAAC,aAAa;AAAA,EAChB;AAEA,QAAM,SAASA,aAAY,MAAM;AAC/B,sBAAkB,SAAS,OAAO;AAClC,gBAAY,UAAU;AACtB,eAAW,UAAU;AACrB,eAAW,UAAU;AAAA,EACvB,GAAG,CAAC,CAAC;AAML,QAAM,aAAaA,aAAY,MAAM;AACnC,eAAW,CAAC,UAAU;AAAA,MACpB,GAAG;AAAA,MACH,aAAa,KAAK,IAAI,GAAG,KAAK,cAAc,CAAC;AAAA,IAC/C,EAAE;AAAA,EACJ,GAAG,CAAC,CAAC;AAEL,QAAM,eAAeA,aAAY,MAAM;AACrC,eAAW,CAAC,UAAU;AAAA,MACpB,GAAG;AAAA,MACH,aAAa,KAAK,IAAI,KAAK,MAAM,SAAS,GAAG,KAAK,cAAc,CAAC;AAAA,IACnE,EAAE;AAAA,EACJ,GAAG,CAAC,CAAC;AAEL,QAAM,SAASA;AAAA,IACb,CAAC,SAAuB;AACtB,YAAM,UAAU,SAAS;AACzB,YAAM,WAAW,QAAQ,QAAQ,MAAM,QAAQ,WAAW;AAC1D,UAAI,CAAC,SAAU;AAEf,YAAM,WAAW,YAAY;AAE7B,UAAI,SAAS,eAAe,UAAU,aAAa;AACjD,mBAAW,CAAC,UAAU;AAAA,UACpB,GAAG;AAAA,UACH,OAAO;AAAA,UACP,aAAa,CAAC,GAAG,KAAK,aAAa,QAAQ;AAAA,UAC3C,OAAO,CAAC;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACT,EAAE;AAEF,mBAAW,UAAU,IAAI,QAAQ;AACjC;AAAA,MACF;AAEA,YAAM,YACJ,QAAQ,YAAY,SAAS,IACzB,QAAQ,YAAY,CAAC,EAAE,QACvB,SAAS,aAAa;AAE5B,UAAI,WAAW,SAAS;AACtB,mBAAW,QAAQ;AAAA,UACjB,IAAI,SAAS;AAAA,UACb,OAAO,SAAS;AAAA,UAChB,YAAY,SAAS;AAAA,UACrB;AAAA,QACF,CAAC;AAAA,MACH;AAEA,sBAAgB,UAAU;AAAA,QACxB,IAAI,SAAS;AAAA,QACb,MAAM,SAAS;AAAA,QACf,OAAO,SAAS;AAAA,MAClB,CAAC;AAAA,IACH;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,QAAM,SAASA,aAAY,MAAM;AAC/B,UAAM,WAAW,YAAY;AAC7B,QAAI,CAAC,SAAU;AAEf,eAAW,CAAC,SAAS;AACnB,YAAM,iBAAiB,KAAK,YAAY,MAAM,GAAG,EAAE;AACnD,YAAM,SAAS,eAAe,eAAe,SAAS,CAAC;AAEvD,UAAI,QAAQ;AACV,mBAAW,UAAU,IAAI,MAAM;AAAA,MACjC,OAAO;AACL,mBAAW,UAAU,KAAK,KAAK;AAAA,MACjC;AAEA,aAAO;AAAA,QACL,GAAG;AAAA,QACH,aAAa;AAAA,QACb,OAAO,CAAC;AAAA,QACR,aAAa;AAAA,QACb,OAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,QAAQA,aAAY,MAAM;AAC9B,sBAAkB,SAAS,OAAO;AAClC,eAAW,UAAU;AAAA,EACvB,GAAG,CAAC,CAAC;AAML,QAAM,eAAeA;AAAA,IACnB,CAAC,UAAkB;AACjB,YAAM,WAAW,YAAY;AAC7B,UAAI,CAAC,SAAU;AAEf,YAAM,UAAU,SAAS;AACzB,YAAM,SAAS,QAAQ,YAAY,QAAQ,YAAY,SAAS,CAAC;AACjE,UAAI,QAAQ;AACV,sBAAc,UAAU,OAAO,MAAM;AAAA,MACvC;AAAA,IACF;AAAA,IACA,CAAC,aAAa;AAAA,EAChB;AAMA,QAAM,YAAYA;AAAA,IAChB,CAAC,EAAE,MAAM,MAAyC;AAChD,YAAM,UAAU,SAAS;AACzB,UAAI,QAAQ,UAAU,OAAQ,QAAO;AAErC,cAAQ,MAAM,KAAK;AAAA,QACjB,KAAK;AACH,gBAAM,eAAe;AACrB,qBAAW;AACX,iBAAO;AAAA,QACT,KAAK;AACH,gBAAM,eAAe;AACrB,uBAAa;AACb,iBAAO;AAAA,QACT,KAAK,SAAS;AACZ,gBAAM,eAAe;AACrB,gBAAM,eAAe,QAAQ,MAAM,QAAQ,WAAW;AACtD,cAAI,cAAc;AAChB,mBAAO,YAAY;AAAA,UACrB;AACA,iBAAO;AAAA,QACT;AAAA,QACA,KAAK,OAAO;AACV,gBAAM,eAAe;AACrB,gBAAM,eAAe,QAAQ,MAAM,QAAQ,WAAW;AACtD,cAAI,cAAc;AAChB,mBAAO,YAAY;AAAA,UACrB;AACA,iBAAO;AAAA,QACT;AAAA,QACA,KAAK,cAAc;AACjB,gBAAM,aAAa,QAAQ,MAAM,QAAQ,WAAW;AACpD,cAAI,YAAY,aAAa;AAC3B,kBAAM,eAAe;AACrB,mBAAO,UAAU;AACjB,mBAAO;AAAA,UACT;AACA,iBAAO;AAAA,QACT;AAAA,QACA,KAAK;AACH,cAAI,QAAQ,YAAY,SAAS,GAAG;AAClC,kBAAM,eAAe;AACrB,mBAAO;AACP,mBAAO;AAAA,UACT;AACA,iBAAO;AAAA,QACT,KAAK;AACH,gBAAM,eAAe;AACrB,gBAAM;AACN,iBAAO;AAAA,QACT;AACE,iBAAO;AAAA,MACX;AAAA,IACF;AAAA,IACA,CAAC,YAAY,cAAc,QAAQ,QAAQ,KAAK;AAAA,EAClD;AAMA,QAAM,eAAuCF,QAA4B;AAAA,IACvE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,eAAa,UAAU,EAAE,SAAS,UAAU,QAAQ,UAAU;AAE9D,QAAM,UAA6B;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,SAAS,aAAa;AAC1C;;;AEpcA,SAAgB,aAAAG,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;;;ACI5C,SAAS,cAAc,UAAmB,WAAmB;AAClE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,IACjB,aAAa,WAAW,YAAY;AAAA,EACtC;AACF;AAEO,SAAS,aAAa,IAAY,OAAe;AACtD,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AACF;AAEO,SAAS,YACd,IACA,UACA,OACA;AACA,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,iBAAiB;AAAA,IACjB,iBAAiB,QAAQ;AAAA,EAC3B;AACF;;;ADwHU,SAiKN,UAjKM,KASE,YATF;AApHH,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AACtB,QAAM,UAAUC,QAAuB,IAAI;AAC3C,QAAM,iBAAiBA,QAAyB,IAAI;AACpD,QAAM,QAAQ,YAAY;AAC1B,QAAM,CAAC,aAAa,cAAc,IAAIC,UAAS,EAAE;AAEjD,QAAM,gBAAgB,YAAY,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,KAAK,GAAG;AAC3D,QAAM,oBAAoBD,QAAO,aAAa;AAC9C,EAAAE,WAAU,MAAM;AACd,QAAI,kBAAkB,YAAY,eAAe;AAC/C,qBAAe,EAAE;AACjB,wBAAkB,UAAU;AAAA,IAC9B;AAAA,EACF,GAAG,CAAC,aAAa,CAAC;AAElB,QAAM,qBAAqBF,QAAO,YAAY,MAAM;AACpD,EAAAE,WAAU,MAAM;AACd,QAAI,mBAAmB,UAAU,KAAK,YAAY,WAAW,GAAG;AAC9D,sBAAgB;AAAA,IAClB,WAAW,YAAY,SAAS,KAAK,eAAe,SAAS;AAC3D,4BAAsB,MAAM,eAAe,SAAS,MAAM,CAAC;AAAA,IAC7D;AACA,uBAAmB,UAAU,YAAY;AAAA,EAC3C,GAAG,CAAC,eAAe,YAAY,QAAQ,aAAa,CAAC;AAErD,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,QAAQ,QAAS;AACtB,UAAM,SAAS,QAAQ,QAAQ,cAAc,wBAAwB;AACrE,YAAQ,eAAe,EAAE,OAAO,UAAU,CAAC;AAAA,EAC7C,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,EAAE,OAAO,SAAS,IAAI,mBAAmB,UAAU;AAEzD,QAAM,cAAc,YAAY,SAAS,IAAI,cAAc;AAC3D,QAAM,YAAY,CAAC,WAAW,MAAM,WAAW,KAAK,YAAY,KAAK,EAAE,SAAS;AAEhF,MAAI,MAAM,WAAW,KAAK,CAAC,WAAW,CAAC,UAAW,QAAO;AAEzD,QAAM,sBAAsB,CAAC,MAA6C;AACxE,YAAQ,EAAE,KAAK;AAAA,MACb,KAAK;AACH,UAAE,eAAe;AACjB,yBAAiB;AACjB;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,uBAAe;AACf;AAAA,MACF,KAAK,SAAS;AACZ,UAAE,eAAe;AACjB,UAAE,gBAAgB;AAClB,cAAM,eAAe,MAAM,WAAW;AACtC,YAAI,aAAc,UAAS,YAAY;AACvC;AAAA,MACF;AAAA,MACA,KAAK;AACH,UAAE,eAAe;AACjB,wBAAgB;AAChB,kBAAU;AACV;AAAA,MACF,KAAK;AACH,YAAI,gBAAgB,MAAM,EAAE,cAAc,mBAAmB,GAAG;AAC9D,YAAE,eAAe;AACjB,mBAAS;AAAA,QACX;AACA;AAAA,MACF,KAAK,cAAc;AACjB,cAAM,OAAO,MAAM,WAAW;AAC9B,YAAI,MAAM,aAAa;AACrB,YAAE,eAAe;AACjB,mBAAS,IAAI;AAAA,QACf;AACA;AAAA,MACF;AAAA,MACA,KAAK;AACH,YAAI,gBAAgB,IAAI;AACtB,YAAE,eAAe;AACjB,mBAAS;AAAA,QACX;AACA;AAAA,IACJ;AAAA,EACF;AAEA,QAAM,YAAY,MAAM,KAAK,CAAC,SAAS,KAAK,KAAK;AAEjD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,oBAAiB;AAAA,MACjB,gBAAc;AAAA,MACd,6BAA2B;AAAA,MAC3B;AAAA,MACA,KAAK;AAAA,MAEJ;AAAA,oBAAY,SAAS,KACpB,qBAAC,SAAI,8BAA2B,IAC9B;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,wBAAqB;AAAA,cACrB,SAAS;AAAA,cACT,cAAW;AAAA,cACZ;AAAA;AAAA,UAED;AAAA,UACC,YAAY,IAAI,CAAC,OAAO,MACvB,qBAAC,UAAoB,mCAAgC,IAClD;AAAA,gBAAI,KAAK,oBAAC,UAAK,kCAA+B,IAAG,eAAC;AAAA,YAClD,MAAM;AAAA,eAFE,MAAM,EAGjB,CACD;AAAA,WACH;AAAA,QAGD,YAAY,SAAS,KACpB,oBAAC,SAAI,0BAAuB,IAC1B;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,MAAK;AAAA,YACL,gCAA6B;AAAA,YAC7B,aAAY;AAAA,YACZ,OAAO;AAAA,YACP,UAAU,CAAC,MAAM;AACf,oBAAM,IAAI,EAAE,OAAO;AACnB,6BAAe,CAAC;AAChB,+BAAiB,CAAC;AAAA,YACpB;AAAA,YACA,WAAW;AAAA,YACX,cAAa;AAAA,YACb,YAAY;AAAA;AAAA,QACd,GACF;AAAA,QAGD,WACC,oBAAC,SAAI,2BAAwB,IAC1B,0BAAgB,cAAc,IAAI,cACrC;AAAA,QAGD,aACC,oBAAC,SAAI,yBAAsB,IACxB,wBAAc,YAAY,WAAW,IAAI,cAC5C;AAAA,QAGD,CAAC,WAAW,MAAM,SAAS,KAC1B,oBAAC,SAAK,GAAG,aAAa,WAAW,GAAG,WAAW,EAAE,cAAc,GAC5D,sBACG,mBAAmB,OAAO,aAAa,OAAO,UAAU,SAAS,YAAY,iBAAiB,IAC9F,MAAM,IAAI,CAAC,MAAM,UACf;AAAA,UAAC;AAAA;AAAA,YAEC;AAAA,YACA;AAAA,YACA,UAAU,UAAU;AAAA,YACpB;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA;AAAA,UAPK,KAAK;AAAA,QAQZ,CACD,GACP;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAMA,SAAS,mBACP,OACA,aACA,OACA,UACA,SACA,YACA,mBACA;AACA,QAAM,WAAwB,CAAC;AAC/B,MAAI;AAEJ,QAAM,QAAQ,CAAC,MAAM,UAAU;AAC7B,QAAI,KAAK,SAAS,KAAK,UAAU,WAAW;AAC1C,kBAAY,KAAK;AACjB,eAAS;AAAA,QACP,oBAAC,SAAgC,gCAA6B,IAC3D,8BAAoB,kBAAkB,KAAK,KAAK,IAAI,KAAK,SADlD,SAAS,KAAK,KAAK,EAE7B;AAAA,MACF;AAAA,IACF;AAEA,aAAS;AAAA,MACP;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA;AAAA,UACA,UAAU,UAAU;AAAA,UACpB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA;AAAA,QAPK,KAAK;AAAA,MAQZ;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAMA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAQG;AACD,QAAM,SAAS,kBAAkB,KAAK,EAAE;AAExC,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG,YAAY,QAAQ,UAAU,KAAK;AAAA,MACvC,wBAAqB;AAAA,MACrB,+BAA6B,WAAW,KAAK;AAAA,MAC7C,qBAAmB,KAAK,cAAc,KAAK;AAAA,MAC3C,cAAc,MAAM,QAAQ,KAAK;AAAA,MACjC,SAAS,MAAM,SAAS,IAAI;AAAA,MAE3B,uBACC,WAAW,MAAM,KAAK,IAEtB,oBAAC,yBAAsB,MAAY;AAAA;AAAA,EAEvC;AAEJ;AAMA,SAAS,sBAAsB,EAAE,KAAK,GAA0B;AAC9D,SACE,iCACG;AAAA,SAAK,QACJ,oBAAC,UAAK,6BAA0B,IAAI,eAAK,MAAK;AAAA,IAEhD,oBAAC,UAAK,8BAA2B,IAAI,eAAK,OAAM;AAAA,IAC/C,KAAK,eACJ,oBAAC,UAAK,oCAAiC,IAAI,eAAK,aAAY;AAAA,IAE7D,KAAK,eACJ,oBAAC,UAAK,gCAA6B,IAAG,eAAY,QAAO,oBAEzD;AAAA,KAEJ;AAEJ;AAMA,IAAM,0BAA0B;AAChC,IAAM,yBAAyB;AAE/B,SAAS,mBACP,YAC6D;AAC7D,MAAI,CAAC,YAAY;AACf,WAAO,EAAE,OAAO,EAAE,SAAS,OAAO,GAAG,UAAU,QAAQ;AAAA,EACzD;AAEA,QAAM,OAAO,WAAW;AACxB,MAAI,CAAC,MAAM;AACT,WAAO,EAAE,OAAO,EAAE,SAAS,OAAO,GAAG,UAAU,QAAQ;AAAA,EACzD;AAEA,QAAM,YAAY,OAAO,WAAW,cAAc,OAAO,cAAc;AACvE,QAAM,YAAY,OAAO,WAAW,cAAc,OAAO,aAAa;AAEtE,QAAM,aAAa,YAAY,KAAK;AACpC,QAAM,aAAa,aAAa,2BAA2B,KAAK,MAAM;AAEtE,MAAI,OAAO,KAAK;AAChB,MAAI,OAAO,yBAAyB,WAAW;AAC7C,WAAO,KAAK,IAAI,GAAG,YAAY,sBAAsB;AAAA,EACvD;AAEA,MAAI,YAAY;AACd,WAAO;AAAA,MACL,OAAO;AAAA,QACL,UAAU;AAAA,QACV,MAAM,GAAG,IAAI;AAAA,QACb,QAAQ,GAAG,YAAY,KAAK,MAAM,CAAC;AAAA,QACnC,QAAQ;AAAA,MACV;AAAA,MACA,UAAU;AAAA,IACZ;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,MACL,UAAU;AAAA,MACV,MAAM,GAAG,IAAI;AAAA,MACb,KAAK,GAAG,KAAK,SAAS,CAAC;AAAA,MACvB,QAAQ;AAAA,IACV;AAAA,IACA,UAAU;AAAA,EACZ;AACF;;;ARlRM,gBAAAC,MAyBA,QAAAC,aAzBA;AAxFC,IAAM,gBAAgB;AAAA,EAC3B,SAASC,eACP;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GACA,KACA;AACA,UAAM,aAAa,MAAM;AACzB,UAAM,YAAY,oBAAoB,UAAU;AAEhD,UAAM,EAAE,SAAS,SAAS,aAAa,IAAI,cAAc,WAAW;AAAA,MAClE;AAAA,IACF,CAAC;AAED,UAAM,EAAE,QAAQ,WAAW,OAAO,YAAY,YAAY,MAAM,IAAI,kBAAkB;AAAA,MACpF;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU,CAAC;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED;AAAA,MACE;AAAA,MACA,OAAO,EAAE,OAAO,YAAY,YAAY,OAAO,UAAU;AAAA,MACzD,CAAC,OAAO,YAAY,YAAY,OAAO,SAAS;AAAA,IAClD;AAEA,UAAM,aAAa,QAAQ,UAAU;AAErC,UAAM,cAAcC,aAAY,CAAC,UAAkB;AACjD,WAAK;AAAA,IACP,GAAG,CAAC,CAAC;AAEL,UAAM,oBAAoBA,aAAY,MAAM;AAC1C,cAAQ,SAAS,MAAM;AAAA,IACzB,GAAG,CAAC,MAAM,CAAC;AAEX,UAAM,cAAmC,CAAC;AAC1C,QAAI,aAAa,KAAM,aAAY,YAAY,GAAG,SAAS;AAC3D,QAAI,aAAa,MAAM;AACrB,kBAAY,YAAY,GAAG,SAAS;AACpC,kBAAY,YAAY;AAAA,IAC1B;AAEA,UAAM,iBAAiB,aACrB,gBAAAH;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,QAAQ;AAAA,QACf,aAAa,QAAQ;AAAA,QACrB,aAAa,QAAQ;AAAA,QACrB,SAAS,QAAQ;AAAA,QACjB,SAAS,QAAQ;AAAA,QACjB,OAAO,QAAQ;AAAA,QACf,YAAY,QAAQ;AAAA,QACpB,UAAU,CAAC,SAAS,QAAQ,OAAO,IAAI;AAAA,QACvC,SAAS;AAAA,QACT,UAAU,QAAQ;AAAA,QAClB,gBAAgB,QAAQ;AAAA,QACxB,cAAc,QAAQ;AAAA,QACtB,gBAAgB,QAAQ;AAAA,QACxB,SAAS,QAAQ;AAAA,QACjB,eAAe;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF,IACE;AAEJ,WACE,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,uBAAoB;AAAA,QACpB,iBAAe,WAAW,KAAK;AAAA,QAC9B,GAAG,cAAc,YAAY,SAAS;AAAA,QACvC,yBACE,cAAc,QAAQ,MAAM,QAAQ,WAAW,IAC3C,kBAAkB,QAAQ,MAAM,QAAQ,WAAW,EAAE,EAAE,KACvD;AAAA,QAGN;AAAA,0BAAAD,KAAC,SAAI,OAAO,aACV,0BAAAA,KAAC,iBAAc,QAAgB,GACjC;AAAA,UAEC,kBACG,kBAAkB,aAAa,gBAAgB,eAAe,IAC9D;AAAA;AAAA;AAAA,IACN;AAAA,EAEJ;AACF;;;AUzJA,SAAS,eAAAI,cAAa,YAAAC,iBAAgB;AAG/B,SAAS,qBAAqB;AACnC,QAAM,CAAC,QAAQ,SAAS,IAAIA,UAAgC,IAAI;AAChE,QAAM,WAAWD,aAAY,CAAC,MAAsB,UAAU,CAAC,GAAG,CAAC,CAAC;AAEpE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa,QAAQ,aAAa,IAAI,KAAK,EAAE,SAAS;AAAA,EACxD;AACF;","names":["useCallback","Extension","Plugin","PluginKey","Extension","PluginKey","Plugin","editor","useCallback","useEffect","useRef","useRef","useEffect","useCallback","useEffect","useRef","useState","useRef","useState","useEffect","jsx","jsxs","MentionsInput","useCallback","useCallback","useState"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relevaince/mentions",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Structured mention engine for Relevaince OMNI chat input",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",