{"version":3,"sources":["../src/index.ts","../src/suggestion.ts","../src/findSuggestionMatch.ts","../src/helpers.ts","../src/plugin/props.ts","../src/plugin/state.ts","../src/plugin/async.ts","../src/plugin/floating-ui.ts","../src/plugin/view.ts"],"sourcesContent":["import { exitSuggestion, Suggestion } from './suggestion.js'\n\nexport * from './findSuggestionMatch.js'\nexport * from './suggestion.js'\n\nexport { exitSuggestion }\n\nexport default Suggestion\n","import type { Range } from '@tiptap/core'\nimport type { EditorState, Transaction } from '@tiptap/pm/state'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport type { EditorView } from '@tiptap/pm/view'\n\nimport type { SuggestionMatch } from './findSuggestionMatch.js'\nimport { findSuggestionMatch as defaultFindSuggestionMatch } from './findSuggestionMatch.js'\nimport {\n  clientRectFor as clientRectForHelper,\n  dispatchExit as dispatchExitHelper,\n  shouldKeepDismissed as shouldKeepDismissedHelper,\n} from './helpers.js'\nimport { createSuggestionProps } from './plugin/props.js'\nimport { createSuggestionState } from './plugin/state.js'\nimport { createSuggestionView } from './plugin/view.js'\nimport type { SuggestionOptions } from './types.js'\n\nexport type {\n  SuggestionFloatingUiConfig,\n  SuggestionFloatingUiOptions,\n  SuggestionKeyDownProps,\n  SuggestionMount,\n  SuggestionMountOptions,\n  SuggestionOptions,\n  SuggestionPlacement,\n  SuggestionPositionData,\n  SuggestionProps,\n} from './types.js'\n\nexport const SuggestionPluginKey = new PluginKey('suggestion')\n\ntype ShouldKeepDismissedProps = {\n  match: Exclude<SuggestionMatch, null>\n  dismissedRange: Range\n  state: EditorState\n  transaction: Transaction\n}\n\n/**\n * This utility allows you to create suggestions.\n * @see https://tiptap.dev/api/utilities/suggestion\n */\nexport function Suggestion<I = any, TSelected = any>({\n  pluginKey = SuggestionPluginKey,\n  editor,\n  char = '@',\n  allowSpaces = false,\n  allowToIncludeChar = false,\n  allowedPrefixes = [' '],\n  startOfLine = false,\n  decorationTag = 'span',\n  decorationClass = 'suggestion',\n  decorationContent = '',\n  decorationEmptyClass = 'is-empty',\n  command = () => null,\n  items = () => [],\n  minQueryLength = 0,\n  debounce = 0,\n  initialItems,\n  placement = 'bottom-start',\n  offset: offsetOption = {},\n  container,\n  flip = true,\n  floatingUi,\n  dismissOnOutsideClick = true,\n  render = () => ({}),\n  allow = () => true,\n  findSuggestionMatch = defaultFindSuggestionMatch,\n  shouldShow,\n  shouldResetDismissed,\n}: SuggestionOptions<I, TSelected>) {\n  const renderer = render?.()\n  const effectiveAllowSpaces = allowSpaces && !allowToIncludeChar\n\n  const clientRectFor = (view: EditorView, decorationNode: Element | null) =>\n    clientRectForHelper(editor, view, decorationNode, pluginKey)\n\n  // helper to check if the dismissed suggestion should stay dismissed, with access to editor and options\n  function shouldKeepDismissed(props: ShouldKeepDismissedProps) {\n    return shouldKeepDismissedHelper({\n      ...props,\n      editor,\n      shouldResetDismissed,\n      effectiveAllowSpaces,\n    })\n  }\n\n  const dispatchExit = (view: EditorView) =>\n    dispatchExitHelper({\n      view,\n      pluginKeyRef: pluginKey,\n    })\n\n  return new Plugin({\n    key: pluginKey,\n\n    view: () =>\n      createSuggestionView({\n        editor,\n        pluginKey,\n        items,\n        renderer,\n        minQueryLength,\n        debounce,\n        initialItems,\n        placement,\n        offset: offsetOption,\n        container,\n        flip,\n        floatingUi,\n        dismissOnOutsideClick,\n        command,\n        clientRectFor,\n        dispatchExit,\n      }),\n\n    state: createSuggestionState({\n      editor,\n      char,\n      effectiveAllowSpaces,\n      allowToIncludeChar,\n      allowedPrefixes,\n      startOfLine,\n      findSuggestionMatch,\n      allow,\n      shouldShow,\n      shouldKeepDismissed,\n      pluginKey,\n    }),\n\n    props: createSuggestionProps({\n      pluginKey,\n      decorationTag,\n      decorationClass,\n      decorationContent,\n      decorationEmptyClass,\n      renderer,\n      dispatchExit,\n    }),\n  })\n}\n\n/**\n * Programmatically exit a suggestion plugin by dispatching a metadata-only\n * transaction. This is the safe, recommended API to remove suggestion\n * decorations without touching the document or causing mapping errors.\n */\nexport function exitSuggestion(view: EditorView, pluginKeyRef: PluginKey = SuggestionPluginKey) {\n  const tr = view.state.tr.setMeta(pluginKeyRef, { exit: true })\n  view.dispatch(tr)\n}\n","import type { Range } from '@tiptap/core'\nimport { escapeForRegEx } from '@tiptap/core'\nimport type { ResolvedPos } from '@tiptap/pm/model'\n\nexport interface Trigger {\n  char: string\n  allowSpaces: boolean\n  allowToIncludeChar: boolean\n  allowedPrefixes: string[] | null\n  startOfLine: boolean\n  $position: ResolvedPos\n}\n\nexport type SuggestionMatch = {\n  range: Range\n  query: string\n  text: string\n} | null\n\nexport function findSuggestionMatch(config: Trigger): SuggestionMatch {\n  const {\n    char,\n    allowSpaces: allowSpacesOption,\n    allowToIncludeChar,\n    allowedPrefixes,\n    startOfLine,\n    $position,\n  } = config\n\n  const allowSpaces = allowSpacesOption && !allowToIncludeChar\n\n  const escapedChar = escapeForRegEx(char)\n  const suffix = new RegExp(`\\\\s${escapedChar}$`)\n  const prefix = startOfLine ? '^' : ''\n  const finalEscapedChar = allowToIncludeChar ? '' : escapedChar\n  const regexp = allowSpaces\n    ? new RegExp(`${prefix}${escapedChar}.*?(?=\\\\s${finalEscapedChar}|$)`, 'gm')\n    : new RegExp(`${prefix}(?:^)?${escapedChar}[^\\\\s${finalEscapedChar}]*`, 'gm')\n\n  const text = $position.nodeBefore?.isText && $position.nodeBefore.text\n\n  if (!text) {\n    return null\n  }\n\n  const textFrom = $position.pos - text.length\n  const match = Array.from(text.matchAll(regexp)).pop()\n\n  if (!match || match.input === undefined || match.index === undefined) {\n    return null\n  }\n\n  // JavaScript doesn't have lookbehinds. This hacks a check that first character\n  // is a space or the start of the line\n  const matchPrefix = match.input.slice(Math.max(0, match.index - 1), match.index)\n  const matchPrefixIsAllowed = new RegExp(`^[${allowedPrefixes?.join('')}\\0]?$`).test(matchPrefix)\n\n  if (allowedPrefixes !== null && !matchPrefixIsAllowed) {\n    return null\n  }\n\n  // The absolute position of the match in the document\n  const from = textFrom + match.index\n  let to = from + match[0].length\n\n  // Edge case handling; if spaces are allowed and we're directly in between\n  // two triggers\n  if (allowSpaces && suffix.test(text.slice(to - 1, to + 1))) {\n    match[0] += ' '\n    to += 1\n  }\n\n  // If the $position is located within the matched substring, return that range\n  if (from < $position.pos && to >= $position.pos) {\n    return {\n      range: {\n        from,\n        to,\n      },\n      query: match[0].slice(char.length),\n      text: match[0],\n    }\n  }\n\n  return null\n}\n","import type { Editor, Range } from '@tiptap/core'\nimport type { EditorState, PluginKey, Transaction } from '@tiptap/pm/state'\nimport type { EditorView } from '@tiptap/pm/view'\n\nimport type { SuggestionMatch } from './findSuggestionMatch.js'\nimport type { SuggestionOptions, SuggestionPluginState } from './types.js'\n\n/**\n * Returns true if the transaction inserted any whitespace or newline character.\n * Used to determine when a dismissed suggestion should become active again.\n */\nexport function hasInsertedWhitespace(transaction: Transaction): boolean {\n  if (!transaction.docChanged) {\n    return false\n  }\n  return transaction.steps.some(step => {\n    const slice = (step as any).slice\n    if (!slice?.content) {\n      return false\n    }\n    // textBetween with '\\n' as block separator catches both inline spaces and newlines\n    const inserted = slice.content.textBetween(0, slice.content.size, '\\n')\n    return /\\s/.test(inserted)\n  })\n}\n\n/**\n * Gets the DOM rectangle corresponding to the current editor cursor anchor position.\n * Calculates screen coordinates based on Tiptap's cursor position and converts to a DOMRect object.\n */\nexport function getAnchorClientRect(editor: Editor): () => DOMRect | null {\n  return () => {\n    const pos = editor.state.selection.$anchor.pos\n    const coords = editor.view.coordsAtPos(pos)\n    const { top, right, bottom, left } = coords\n\n    try {\n      return new DOMRect(left, top, right - left, bottom - top)\n    } catch {\n      return null\n    }\n  }\n}\n\n/**\n * Creates a clientRect callback for a given decoration node.\n * Returns the anchor rect when no decoration node is present.\n * Uses the pluginKey's state to resolve the current decoration node on demand.\n */\nexport function clientRectFor(\n  editor: Editor,\n  view: EditorView,\n  decorationNode: Element | null,\n  pluginKey: PluginKey,\n): () => DOMRect | null {\n  if (!decorationNode) {\n    return getAnchorClientRect(editor)\n  }\n\n  return () => {\n    const state: SuggestionPluginState = pluginKey.getState(editor.state) as any\n    const decorationId = state?.decorationId\n    const currentDecorationNode = view.dom.querySelector(`[data-decoration-id=\"${decorationId}\"]`)\n\n    return currentDecorationNode?.getBoundingClientRect() || null\n  }\n}\n\n/**\n * Determines whether a dismissed suggestion should stay dismissed.\n * Returns `true` (keep dismissed) or `false` (allow reactivation).\n */\nexport function shouldKeepDismissed({\n  match,\n  dismissedRange,\n  state,\n  transaction,\n  editor,\n  shouldResetDismissed,\n  effectiveAllowSpaces,\n}: {\n  match: Exclude<SuggestionMatch, null>\n  dismissedRange: Range\n  state: EditorState\n  transaction: Transaction\n  editor: Editor\n  shouldResetDismissed?: SuggestionOptions['shouldResetDismissed']\n  effectiveAllowSpaces: boolean\n}): boolean {\n  if (\n    shouldResetDismissed?.({\n      editor,\n      state,\n      range: dismissedRange,\n      match,\n      transaction,\n      allowSpaces: effectiveAllowSpaces,\n    })\n  ) {\n    return false\n  }\n\n  if (effectiveAllowSpaces) {\n    return match.range.from === dismissedRange.from\n  }\n\n  return match.range.from === dismissedRange.from && !hasInsertedWhitespace(transaction)\n}\n\n/**\n * Dispatch an exit of the suggestion plugin by dispatching a metadata-only\n * transaction to clear the plugin state. The renderer's onExit hook is NOT\n * called here — it fires via the plugin view's stopped transition, which\n * builds SuggestionProps consistently with the normal lifecycle.\n *\n * This prevents a double onExit call (one from dispatchExit, one from the\n * view's update) and keeps exitSuggestion consistent with Escape-triggered\n * exits.\n */\nexport function dispatchExit({\n  view,\n  pluginKeyRef,\n}: {\n  view: EditorView\n  pluginKeyRef: PluginKey\n}): void {\n  const tr = view.state.tr.setMeta(pluginKeyRef, { exit: true })\n  view.dispatch(tr)\n}\n","import type { EditorState, PluginKey } from '@tiptap/pm/state'\nimport type { EditorView } from '@tiptap/pm/view'\nimport { Decoration, DecorationSet } from '@tiptap/pm/view'\n\nimport type { SuggestionKeyDownProps, SuggestionPluginState } from '../types.js'\n\n/**\n * Creates the `props` object for the suggestion ProseMirror plugin.\n * Contains `handleKeyDown` for keyboard handling and `decorations`\n * for rendering the suggestion highlight.\n */\nexport interface CreateSuggestionPropsOptions {\n  pluginKey: PluginKey\n  decorationTag: string\n  decorationClass: string\n  decorationContent: string\n  decorationEmptyClass: string\n  renderer: { onKeyDown?: (props: SuggestionKeyDownProps) => boolean } | undefined\n  dispatchExit: (view: EditorView) => void\n}\n\n/**\n * Creates the `props` object for the suggestion ProseMirror plugin.\n * Contains `handleKeyDown` for keyboard handling and `decorations`\n * for rendering the suggestion highlight.\n */\nexport function createSuggestionProps({\n  pluginKey,\n  decorationTag,\n  decorationClass,\n  decorationContent,\n  decorationEmptyClass,\n  renderer,\n  dispatchExit,\n}: CreateSuggestionPropsOptions) {\n  return {\n    /**\n     * Call the keydown hook if suggestion is active.\n     */\n    handleKeyDown(view: EditorView, event: KeyboardEvent) {\n      const state: SuggestionPluginState = pluginKey.getState(view.state) as any\n\n      if (!state.active) {\n        return false\n      }\n\n      // If Escape is pressed, call onKeyDown and dispatch a metadata-only\n      // transaction to unset the suggestion state. This provides a safe\n      // and deterministic way to exit the suggestion without altering the\n      // document (avoids transaction mapping/mismatch issues).\n      if (event.key === 'Escape' || event.key === 'Esc') {\n        // Allow the consumer to react to Escape, but always clear the\n        // suggestion state afterward so the decoration is removed too.\n        renderer?.onKeyDown?.({ view, event, range: state.range })\n\n        // dispatch metadata-only transaction to unset the plugin state\n        dispatchExit(view)\n\n        return true\n      }\n\n      const handled = renderer?.onKeyDown?.({ view, event, range: state.range }) || false\n      return handled\n    },\n\n    /**\n     * Setup decorator on the currently active suggestion.\n     */\n    decorations(state: EditorState) {\n      const pluginState: SuggestionPluginState = pluginKey.getState(state) as any\n      const { active, range, decorationId, query } = pluginState\n\n      if (!active) {\n        return null\n      }\n\n      const isEmpty = !query?.length\n      const classNames = [decorationClass]\n\n      if (isEmpty) {\n        classNames.push(decorationEmptyClass)\n      }\n\n      return DecorationSet.create(state.doc, [\n        Decoration.inline(range.from, range.to, {\n          nodeName: decorationTag,\n          class: classNames.join(' '),\n          'data-decoration-id': decorationId || undefined,\n          'data-decoration-content': decorationContent,\n        }),\n      ])\n    },\n  }\n}\n","import type { Editor, Range } from '@tiptap/core'\nimport type { EditorState, PluginKey, Transaction } from '@tiptap/pm/state'\n\nimport type {\n  findSuggestionMatch as defaultFindSuggestionMatch,\n  SuggestionMatch,\n} from '../findSuggestionMatch.js'\nimport type { SuggestionOptions, SuggestionPluginState } from '../types.js'\n\nexport interface CreateSuggestionStateOptions {\n  editor: Editor\n  char: string\n  effectiveAllowSpaces: boolean\n  allowToIncludeChar: boolean\n  allowedPrefixes: string[] | null\n  startOfLine: boolean\n  findSuggestionMatch: typeof defaultFindSuggestionMatch\n  allow: Exclude<SuggestionOptions['allow'], undefined>\n  shouldShow?: SuggestionOptions['shouldShow']\n  shouldKeepDismissed: (props: {\n    match: Exclude<SuggestionMatch, null>\n    dismissedRange: Range\n    state: EditorState\n    transaction: Transaction\n  }) => boolean\n  pluginKey: PluginKey\n}\n\n/**\n * Creates the `state` object for the suggestion ProseMirror plugin.\n * Contains `init()` and `apply()` for managing the plugin's internal state\n * across transactions.\n */\nexport function createSuggestionState({\n  editor,\n  char,\n  effectiveAllowSpaces,\n  allowToIncludeChar,\n  allowedPrefixes,\n  startOfLine,\n  findSuggestionMatch,\n  allow,\n  shouldShow,\n  shouldKeepDismissed,\n  pluginKey,\n}: CreateSuggestionStateOptions) {\n  return {\n    /**\n     * Initialize the plugin's internal state.\n     */\n    init(): SuggestionPluginState {\n      return {\n        active: false,\n        range: { from: 0, to: 0 },\n        query: null,\n        text: null,\n        composing: false,\n        dismissedRange: null,\n      }\n    },\n\n    /**\n     * Apply changes to the plugin state from a view transaction.\n     */\n    apply(\n      transaction: Transaction,\n      prev: SuggestionPluginState,\n      _oldState: EditorState,\n      state: EditorState,\n    ): SuggestionPluginState {\n      const { isEditable } = editor\n      const { composing } = editor.view\n      const { selection } = transaction\n      const { empty, from } = selection\n      const next = { ...prev }\n\n      // If a transaction carries the exit meta for this plugin, immediately\n      // deactivate the suggestion. This allows metadata-only transactions\n      // (dispatched by escape or programmatic exit) to deterministically\n      // clear decorations without changing the document.\n      const meta = transaction.getMeta(pluginKey)\n      if (meta && meta.exit) {\n        next.active = false\n        next.decorationId = null\n        next.range = { from: 0, to: 0 }\n        next.query = null\n        next.text = null\n        next.dismissedRange = prev.active ? { ...prev.range } : prev.dismissedRange\n\n        return next\n      }\n\n      next.composing = composing\n\n      if (transaction.docChanged && next.dismissedRange !== null) {\n        next.dismissedRange = {\n          from: transaction.mapping.map(next.dismissedRange.from),\n          to: transaction.mapping.map(next.dismissedRange.to),\n        }\n      }\n\n      // We can only be suggesting if the view is editable, and:\n      //   * there is no selection, or\n      //   * a composition is active (see: https://github.com/ueberdosis/tiptap/issues/1449)\n      if (isEditable && (empty || editor.view.composing)) {\n        // Reset active state if we just left the previous suggestion range\n        if ((from < prev.range.from || from > prev.range.to) && !composing && !prev.composing) {\n          next.active = false\n        }\n\n        // Try to match against where our cursor currently is\n        const match = findSuggestionMatch({\n          char,\n          allowSpaces: effectiveAllowSpaces,\n          allowToIncludeChar,\n          allowedPrefixes,\n          startOfLine,\n          $position: selection.$from,\n        })\n        const decorationId = `id_${Math.floor(Math.random() * 0xffffffff)}`\n\n        // If we found a match, update the current state to show it\n        if (\n          match &&\n          allow({\n            editor,\n            state,\n            range: match.range,\n            isActive: prev.active,\n          }) &&\n          (!shouldShow ||\n            shouldShow({\n              editor,\n              range: match.range,\n              query: match.query,\n              text: match.text,\n              transaction,\n            }))\n        ) {\n          if (\n            next.dismissedRange !== null &&\n            !shouldKeepDismissed({\n              match,\n              dismissedRange: next.dismissedRange,\n              state,\n              transaction,\n            })\n          ) {\n            next.dismissedRange = null\n          }\n\n          if (next.dismissedRange === null) {\n            next.active = true\n            next.decorationId = prev.decorationId || decorationId\n            next.range = match.range\n            next.query = match.query\n            next.text = match.text\n          } else {\n            next.active = false\n          }\n        } else {\n          if (!match) {\n            next.dismissedRange = null\n          }\n          next.active = false\n        }\n      } else {\n        next.active = false\n      }\n\n      // Make sure to empty the range if suggestion is inactive\n      if (!next.active) {\n        next.decorationId = null\n        next.range = { from: 0, to: 0 }\n        next.query = null\n        next.text = null\n      }\n\n      return next\n    },\n  }\n}\n","import type { Editor } from '@tiptap/core'\n\nimport type { SuggestionOptions } from '../types.js'\n\nexport interface CreateSuggestionAsyncRequestManagerOptions<I = any> {\n  editor: Editor\n  items: NonNullable<SuggestionOptions<I>['items']>\n}\n\ntype AsyncRequestResult<I> =\n  | { status: 'resolved'; items: I[] }\n  | { status: 'aborted' }\n  | { status: 'error' }\n\nexport function createSuggestionAsyncRequestManager<I = any>({\n  editor,\n  items,\n}: CreateSuggestionAsyncRequestManagerOptions<I>) {\n  let abortController: AbortController | null = null\n  let debounceTimer: ReturnType<typeof setTimeout> | null = null\n  let debounceResolve: (() => void) | null = null\n\n  const clearDebounceTimer = () => {\n    if (debounceTimer !== null) {\n      clearTimeout(debounceTimer)\n      debounceTimer = null\n    }\n\n    debounceResolve?.()\n    debounceResolve = null\n  }\n\n  const waitForDebounce = (delay: number) => {\n    return new Promise<void>(resolve => {\n      debounceResolve = resolve\n      debounceTimer = setTimeout(() => {\n        debounceTimer = null\n        const pendingResolve = debounceResolve\n        debounceResolve = null\n        pendingResolve?.()\n      }, delay)\n    })\n  }\n\n  const abort = () => {\n    abortController?.abort()\n    clearDebounceTimer()\n    abortController = null\n  }\n\n  const fetch = async (query: string, debounce: number): Promise<AsyncRequestResult<I>> => {\n    abort()\n    abortController = new AbortController()\n    const controller = abortController\n\n    if (debounce > 0) {\n      await waitForDebounce(debounce)\n    }\n\n    if (abortController !== controller || controller.signal.aborted) {\n      return { status: 'aborted' }\n    }\n\n    try {\n      const result = await items({\n        editor,\n        query,\n        signal: controller.signal,\n      })\n\n      if (abortController !== controller || controller.signal.aborted) {\n        return { status: 'aborted' }\n      }\n\n      return { status: 'resolved', items: result }\n    } catch {\n      if (abortController !== controller || controller.signal.aborted) {\n        return { status: 'aborted' }\n      }\n\n      return { status: 'error' }\n    }\n  }\n\n  return {\n    abort,\n    fetch,\n  }\n}\n","import type { Middleware, VirtualElement } from '@floating-ui/dom'\nimport {\n  autoUpdate,\n  computePosition,\n  flip as floatingUiFlip,\n  offset as floatingUiOffset,\n} from '@floating-ui/dom'\n\nimport type {\n  SuggestionFloatingUiConfig,\n  SuggestionFloatingUiOptions,\n  SuggestionMount,\n  SuggestionPlacement,\n} from '../types.js'\n\nexport interface CreateSuggestionFloatingUiConfigOptions {\n  placement: SuggestionPlacement\n  offset: { mainAxis?: number; crossAxis?: number }\n  flip: boolean\n  floatingUi?: SuggestionFloatingUiOptions\n}\n\nexport function createSuggestionFloatingUiConfig({\n  placement,\n  offset,\n  flip,\n  floatingUi,\n}: CreateSuggestionFloatingUiConfigOptions): SuggestionFloatingUiConfig {\n  const middleware: Middleware[] = [\n    floatingUiOffset({\n      mainAxis: offset.mainAxis ?? 4,\n      crossAxis: offset.crossAxis ?? 0,\n    }),\n  ]\n\n  if (flip) {\n    middleware.push(floatingUiFlip())\n  }\n\n  if (floatingUi?.middleware?.length) {\n    middleware.push(...floatingUi.middleware)\n  }\n\n  return {\n    placement,\n    strategy: floatingUi?.strategy ?? 'absolute',\n    middleware,\n  }\n}\n\nexport interface CreateMountOptions {\n  /** Returns the current cursor/anchor rect the popup should track. */\n  getReferenceRect: () => DOMRect | null\n  /**\n   * An element inside the editor's layout/scroll context. Floating UI walks up\n   * from here to discover the scroll ancestors (and the window) to observe, so\n   * the scroll container does not need to be configured manually.\n   */\n  contextElement: Element\n  /** Resolved Floating UI config (placement, strategy, middleware). */\n  config: SuggestionFloatingUiConfig\n  /**\n   * CSS selector or element the popup should be mounted into. Defaults to\n   * `document.body`. Used to portal the popup inside dialogs/modals so it\n   * renders on top of (and clips within) the right context.\n   */\n  container?: string | HTMLElement\n  /**\n   * When `true`, a pointerdown outside both the popup and the editor dismisses\n   * the suggestion. Wired up and torn down alongside the mounted element.\n   */\n  dismissOnOutsideClick: boolean\n  /** Dismisses the active suggestion (used by outside-click handling). */\n  dismiss: () => void\n}\n\n/**\n * Resolves a container option (selector or element) to a mount target,\n * falling back to `document.body` when it can't be resolved.\n */\nfunction resolveContainer(container?: string | HTMLElement): HTMLElement {\n  if (container instanceof HTMLElement) {\n    return container\n  }\n\n  if (typeof container === 'string') {\n    try {\n      // `container` is consumer-provided; an invalid selector throws a\n      // DOMException, so fall back to document.body instead of crashing.\n      const found = document.querySelector<HTMLElement>(container)\n\n      if (found) {\n        return found\n      }\n    } catch {\n      return document.body\n    }\n  }\n\n  return document.body\n}\n\n/**\n * Builds the `mount` function handed to the renderer on `SuggestionProps`.\n *\n * Mounts the popup into the container, then wires Floating UI's `autoUpdate`\n * against a virtual reference that re-reads the live cursor rect, so the popup\n * stays anchored across scroll, resize, and layout shifts without the consumer\n * attaching any listeners. The returned `unmount` tears all of that down.\n */\nexport function createMount({\n  getReferenceRect,\n  contextElement,\n  config,\n  container,\n  dismissOnOutsideClick,\n  dismiss,\n}: CreateMountOptions): SuggestionMount {\n  return (element, options = {}) => {\n    const reference: VirtualElement = {\n      getBoundingClientRect: () => getReferenceRect() ?? new DOMRect(),\n      contextElement,\n    }\n\n    let positioned = false\n\n    // Mount the popup into the container (default `document.body`) unless the\n    // consumer already placed it in the DOM themselves — in which case we leave\n    // mounting (and unmounting) to them.\n    const mountedByUs = !element.isConnected\n\n    if (mountedByUs) {\n      resolveContainer(container).appendChild(element)\n    }\n\n    // Hide the element until the first measurement resolves so it doesn't flash\n    // at its initial coordinates. Skipped when the consumer owns applying the\n    // position via `onPosition`.\n    if (!options.onPosition) {\n      element.style.visibility = 'hidden'\n      element.style.width = 'max-content'\n    }\n\n    const update = () => {\n      computePosition(reference, element, {\n        placement: config.placement,\n        strategy: config.strategy,\n        middleware: config.middleware,\n      }).then(({ x, y, placement, strategy }) => {\n        if (options.onPosition) {\n          options.onPosition({ x, y, placement: placement as SuggestionPlacement, strategy })\n          return\n        }\n\n        Object.assign(element.style, {\n          position: strategy,\n          left: `${x}px`,\n          top: `${y}px`,\n        })\n\n        if (!positioned) {\n          positioned = true\n          element.style.visibility = ''\n        }\n      })\n    }\n\n    const cleanupAutoUpdate = autoUpdate(reference, element, update, options.autoUpdate)\n\n    // Dismiss when the user interacts outside both the popup and the editor.\n    // Capture phase so a parent that stops propagation can't swallow it.\n    let onOutsidePointerDown: ((event: PointerEvent) => void) | undefined\n\n    if (dismissOnOutsideClick) {\n      onOutsidePointerDown = event => {\n        const target = event.target\n\n        if (\n          !(target instanceof Node) ||\n          element.contains(target) ||\n          contextElement.contains(target)\n        ) {\n          return\n        }\n\n        dismiss()\n      }\n\n      document.addEventListener('pointerdown', onOutsidePointerDown, true)\n    }\n\n    return () => {\n      cleanupAutoUpdate()\n\n      if (onOutsidePointerDown) {\n        document.removeEventListener('pointerdown', onOutsidePointerDown, true)\n      }\n\n      if (mountedByUs) {\n        element.remove()\n      }\n    }\n  }\n}\n","import type { Editor } from '@tiptap/core'\nimport type { EditorState, PluginKey } from '@tiptap/pm/state'\nimport type { EditorView } from '@tiptap/pm/view'\n\nimport type {\n  PluginState,\n  SuggestionFloatingUiOptions,\n  SuggestionOptions,\n  SuggestionPlacement,\n  SuggestionProps,\n} from '../types.js'\nimport { createSuggestionAsyncRequestManager } from './async.js'\nimport { createMount, createSuggestionFloatingUiConfig } from './floating-ui.js'\n\nexport interface CreateSuggestionViewOptions {\n  editor: Editor\n  pluginKey: PluginKey<PluginState>\n  items: NonNullable<SuggestionOptions['items']>\n  renderer: ReturnType<NonNullable<SuggestionOptions['render']>> | undefined\n  minQueryLength: number\n  debounce: number\n  initialItems?: any[]\n  placement: SuggestionPlacement\n  offset: { mainAxis?: number; crossAxis?: number }\n  container?: string | HTMLElement\n  flip: boolean\n  floatingUi?: SuggestionFloatingUiOptions\n  dismissOnOutsideClick: boolean\n  command: NonNullable<SuggestionOptions['command']>\n  clientRectFor: (view: EditorView, decorationNode: Element | null) => () => DOMRect | null\n  dispatchExit: (view: EditorView) => void\n}\n\n/**\n * Creates the `view` object for the suggestion ProseMirror plugin.\n *\n * Manages the async lifecycle: tracks state transitions, calls renderer hooks,\n * fetches items with debounce and AbortController support.\n *\n * 1. Tracks plugin state transitions (started, updated, stopped) to determine when to call renderer hooks.\n * 2. Calls `onBeforeStart`, `onBeforeUpdate`, `onStart` before fetching to allow the renderer to prepare for first render\n * 3. Manages async fetching of suggestion items with support for debouncing and aborting in-flight requests\n * 4. Calls `onUpdate` after fetching new items to update the renderer with the latest data\n * 5. At the end calls a final `onExit` or `onUpdate` to allow the renderer to clean up or finalize the state\n */\nexport function createSuggestionView({\n  editor,\n  pluginKey,\n  items,\n  renderer,\n  minQueryLength,\n  debounce,\n  initialItems,\n  placement,\n  offset: offsetOption,\n  container,\n  flip,\n  floatingUi,\n  dismissOnOutsideClick,\n  command,\n  clientRectFor,\n  dispatchExit,\n}: CreateSuggestionViewOptions) {\n  let props: SuggestionProps | undefined\n  const asyncRequest = createSuggestionAsyncRequestManager({\n    editor,\n    items,\n  })\n  const floatingUiConfig = createSuggestionFloatingUiConfig({\n    placement,\n    offset: offsetOption,\n    flip,\n    floatingUi,\n  })\n\n  function dispatchStateUpdate(\n    state: 'started' | 'updated' | 'stopped',\n    dispatchProps: SuggestionProps,\n  ) {\n    switch (state) {\n      case 'started':\n        renderer?.onStart?.(dispatchProps)\n        break\n      case 'updated':\n        renderer?.onUpdate?.(dispatchProps)\n        break\n      case 'stopped':\n        renderer?.onExit?.(dispatchProps)\n        break\n      default:\n        break\n    }\n  }\n\n  return {\n    update: async (view: EditorView, prevState: EditorState) => {\n      const prev = pluginKey.getState(prevState)\n      const next = pluginKey.getState(view.state)\n\n      if (!prev || !next) {\n        return\n      }\n\n      let currentState: 'started' | 'updated' | 'stopped' | null = null\n      const queryChanged = prev.query !== next.query\n      const textChanged = prev.text !== next.text\n      const rangeChanged = prev.range.from !== next.range.from || prev.range.to !== next.range.to\n      const effectiveQueryChanged = queryChanged || textChanged || rangeChanged\n\n      if (!prev.active && next.active) {\n        currentState = 'started'\n      } else if (prev.active && !next.active) {\n        currentState = 'stopped'\n      } else if (next.active && effectiveQueryChanged) {\n        currentState = 'updated'\n      } else {\n        return\n      }\n\n      const state = currentState === 'stopped' ? prev : next\n      const decorationNode = view.dom.querySelector(`[data-decoration-id=\"${state.decorationId}\"]`)\n      const clientRect = clientRectFor(view, decorationNode)\n\n      const exceedsMinQueryLength =\n        minQueryLength === 0 || (state.query ? state.query.length >= minQueryLength : false)\n      const willFetch =\n        (currentState === 'started' || currentState === 'updated') && exceedsMinQueryLength\n\n      props = {\n        editor,\n        range: state.range,\n        query: state.query || '',\n        text: state.text || '',\n        items: initialItems ?? [],\n        command: commandProps => {\n          return command({\n            editor,\n            range: state.range,\n            props: commandProps,\n          })\n        },\n        decorationNode,\n        clientRect,\n        loading: willFetch,\n        placement,\n        offset: { mainAxis: offsetOption.mainAxis ?? 4, crossAxis: offsetOption.crossAxis ?? 0 },\n        container,\n        flip,\n        floatingUi: floatingUiConfig,\n        mount: createMount({\n          getReferenceRect: clientRect,\n          contextElement: view.dom,\n          config: floatingUiConfig,\n          container,\n          dismissOnOutsideClick,\n          dismiss: () => dispatchExit(editor.view),\n        }),\n      }\n\n      if (currentState === 'started') {\n        renderer?.onBeforeStart?.(props)\n      }\n\n      if (currentState === 'updated') {\n        renderer?.onBeforeUpdate?.(props)\n      }\n\n      // we run the start before we fetch\n      // to allow for the component to render immediately\n      if (currentState === 'started') {\n        dispatchStateUpdate(currentState, props)\n      }\n\n      if (currentState === 'started' || currentState === 'updated') {\n        if (!willFetch) {\n          // Abort any in-flight request so stale results don't overwrite\n          asyncRequest.abort()\n          props = { ...props, items: initialItems ?? [], loading: false }\n        } else {\n          // update the renderer with loading state before we start the async fetch\n          props = { ...props, items: initialItems ?? [], loading: true }\n          currentState = 'updated'\n          dispatchStateUpdate(currentState, props)\n\n          const result = await asyncRequest.fetch(state.query || '', debounce)\n\n          if (result.status === 'aborted') {\n            return\n          }\n\n          // Re-check plugin state because the suggestion may have been dismissed\n          const currentPluginState = pluginKey.getState(view.state)\n          if (!currentPluginState?.active) {\n            asyncRequest.abort()\n\n            return\n          }\n\n          props =\n            result.status === 'resolved'\n              ? {\n                  ...props,\n                  items: result.items,\n                  loading: false,\n                }\n              : {\n                  ...props,\n                  loading: false,\n                }\n        }\n      }\n\n      if (currentState === 'stopped') {\n        // stop running updates immediately and call onExit to allow the renderer to clean up\n        asyncRequest.abort()\n        dispatchStateUpdate(currentState, props)\n        props = undefined\n        return\n      }\n\n      if (currentState === 'updated') {\n        dispatchStateUpdate(currentState, props)\n      }\n    },\n\n    destroy: () => {\n      asyncRequest.abort()\n\n      if (!props) {\n        return\n      }\n\n      renderer?.onExit?.(props)\n    },\n  }\n}\n"],"mappings":"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","names":["dispatchExit","findSuggestionMatch","shouldKeepDismissed","floatingUiOffset","floatingUiFlip","clientRectFor","dispatchExit","findSuggestionMatch","clientRectFor","shouldKeepDismissed","dispatchExit"]}