@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 +50 -0
- package/dist/index.d.mts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +16 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +14 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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 ←\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 ›\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 ←\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 ›\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
|
package/dist/index.mjs.map
CHANGED
|
@@ -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 ←\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 ›\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 ←\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 ›\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"]}
|