import { EditorState, Plugin, PluginKey, Transaction } from "@tiptap/pm/state";
import { Editor, Range } from "@tiptap/core";
import { EditorView } from "@tiptap/pm/view";
import { AutoUpdateOptions, Middleware } from "@floating-ui/dom";
import { ResolvedPos } from "@tiptap/pm/model";
//#region src/findSuggestionMatch.d.ts
interface Trigger {
  char: string;
  allowSpaces: boolean;
  allowToIncludeChar: boolean;
  allowedPrefixes: string[] | null;
  startOfLine: boolean;
  $position: ResolvedPos;
}
type SuggestionMatch = {
  range: Range;
  query: string;
  text: string;
} | null;
declare function findSuggestionMatch$1(config: Trigger): SuggestionMatch;
//#endregion
//#region src/types.d.ts
type SuggestionPlacement = 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end';
type SuggestionFloatingUiOptions = {
  strategy?: 'absolute' | 'fixed';
  middleware?: Middleware[];
};
type SuggestionFloatingUiConfig = {
  placement: SuggestionPlacement;
  strategy: 'absolute' | 'fixed';
  middleware: Middleware[];
};
/**
 * The computed position handed to a custom `onPosition` callback when using
 * managed positioning via {@link SuggestionProps.mount}.
 */
type SuggestionPositionData = {
  x: number;
  y: number;
  placement: SuggestionPlacement;
  strategy: 'absolute' | 'fixed';
};
/**
 * Options for managed mounting + positioning via {@link SuggestionProps.mount}.
 */
type SuggestionMountOptions = {
  /**
   * Override how the computed position is applied to the element.
   * When provided, the plugin stops writing `style.left`/`style.top` itself and
   * hands you the computed coordinates so you can apply them however you want
   * (custom transforms, animation, writing to a framework ref, etc.).
   */
  onPosition?: (data: SuggestionPositionData) => void;
  /**
   * Options forwarded to Floating UI's `autoUpdate`. Use this to opt into
   * `animationFrame` polling for anchors that move inside transformed or
   * animated containers, or to disable specific observers.
   * @see https://floating-ui.com/docs/autoUpdate
   */
  autoUpdate?: AutoUpdateOptions;
};
/**
 * Mounts a floating element and takes over its positioning. The plugin appends
 * the element into the configured `container` (default `document.body`), keeps
 * it anchored to the suggestion's cursor rect, and automatically repositions it
 * on scroll, resize, and layout shifts via Floating UI's `autoUpdate` — no
 * manual listeners required.
 *
 * Returns an `unmount` function that tears down the listeners and removes the
 * element (when the plugin mounted it). Call it from `onExit`.
 */
type SuggestionMount = (element: HTMLElement, options?: SuggestionMountOptions) => () => void;
interface SuggestionOptions<I = any, TSelected = any> {
  /**
   * The plugin key for the suggestion plugin.
   * @default 'suggestion'
   * @example 'mention'
   */
  pluginKey?: PluginKey;
  /**
   * A function that returns a boolean to indicate if the suggestion should be active.
   * This is useful to prevent suggestions from opening for remote users in collaborative environments.
   * @param props The props object.
   * @param props.editor The editor instance.
   * @param props.range The range of the suggestion.
   * @param props.query The current suggestion query.
   * @param props.text The current suggestion text.
   * @param props.transaction The current transaction.
   * @returns {boolean}
   * @example ({ transaction }) => isChangeOrigin(transaction)
   */
  shouldShow?: (props: {
    editor: Editor;
    range: Range;
    query: string;
    text: string;
    transaction: Transaction;
  }) => boolean;
  /**
   * Controls when a dismissed suggestion becomes active again.
   * Return `true` to clear the dismissed context for the current transaction.
   */
  shouldResetDismissed?: (props: {
    editor: Editor;
    state: EditorState;
    range: Range;
    match: Exclude<SuggestionMatch, null>;
    transaction: Transaction;
    allowSpaces: boolean;
  }) => boolean;
  /**
   * The editor instance.
   * @default null
   */
  editor: Editor;
  /**
   * The character that triggers the suggestion.
   * @default '@'
   * @example '#'
   */
  char?: string;
  /**
   * Allow spaces in the suggestion query. Not compatible with `allowToIncludeChar`. Will be disabled if `allowToIncludeChar` is set to `true`.
   * @default false
   * @example true
   */
  allowSpaces?: boolean;
  /**
   * Allow the character to be included in the suggestion query. Not compatible with `allowSpaces`.
   * @default false
   */
  allowToIncludeChar?: boolean;
  /**
   * Allow prefixes in the suggestion query.
   * @default [' ']
   * @example [' ', '@']
   */
  allowedPrefixes?: string[] | null;
  /**
   * Only match suggestions at the start of the line.
   * @default false
   * @example true
   */
  startOfLine?: boolean;
  /**
   * The tag name of the decoration node.
   * @default 'span'
   * @example 'div'
   */
  decorationTag?: string;
  /**
   * The class name of the decoration node.
   * @default 'suggestion'
   * @example 'mention'
   */
  decorationClass?: string;
  /**
   * Creates a decoration with the provided content.
   * @param decorationContent - The content to display in the decoration
   * @default "" - Creates an empty decoration if no content provided
   */
  decorationContent?: string;
  /**
   * The class name of the decoration node when it is empty.
   * @default 'is-empty'
   * @example 'is-empty'
   */
  decorationEmptyClass?: string;
  /**
   * A function that is called when a suggestion is selected.
   * @param props The props object.
   * @param props.editor The editor instance.
   * @param props.range The range of the suggestion.
   * @param props.props The props of the selected suggestion.
   * @returns void
   * @example ({ editor, range, props }) => { props.command(props.props) }
   */
  command?: (props: {
    editor: Editor;
    range: Range;
    props: TSelected;
  }) => void;
  /**
   * Minimum query length before `items()` is called.
   * When the query is shorter, empty items are passed to the renderer.
   * @default 0 (no filter, same as before)
   * @example 2
   */
  minQueryLength?: number;
  /**
   * Debounce in milliseconds. When set, `items()` will only be called
   * after the user stops typing for this duration.
   * @default 0 (no debounce, same as before)
   * @example 300
   */
  debounce?: number;
  /**
   * Items shown immediately when the suggestion popup opens,
   * before the async `items()` call resolves.
   * Useful for showing recent or popular items while loading.
   * @default undefined (no pre-populated items)
   */
  initialItems?: I[];
  /**
   * Placement of the popup relative to the cursor.
   * Consumers can read this from `SuggestionProps` to configure their positioning library.
   * @default 'bottom-start'
   */
  placement?: SuggestionPlacement;
  /**
   * Offset of the popup in pixels.
   * Consumers can read this from `SuggestionProps` to configure their positioning library.
   * @default { mainAxis: 4, crossAxis: 0 }
   */
  offset?: {
    mainAxis?: number;
    crossAxis?: number;
  };
  /**
   * CSS selector or element that defines the containment context for the popup.
   * Consumers can read this from `SuggestionProps` when rendering inside modals or dialogs.
   * @default undefined (no containment)
   */
  container?: string | HTMLElement;
  /**
   * Whether the popup should automatically flip when there isn't enough space.
   * Consumers can read this from `SuggestionProps` to configure their positioning library.
   * @default true
   */
  flip?: boolean;
  /**
   * Additional Floating UI options and middleware passed through to the renderer.
   * The plugin keeps ownership of the anchor and placement, but consumers can
   * append custom middleware here.
   */
  floatingUi?: SuggestionFloatingUiOptions;
  /**
   * Dismiss the suggestion when the user interacts outside both the popup and
   * the editor. Only applies when using managed mounting via
   * {@link SuggestionProps.mount} (the plugin needs to know the popup element).
   * @default true
   */
  dismissOnOutsideClick?: boolean;
  /**
   * A function that returns the suggestion items in form of an array.
   * @param props The props object.
   * @param props.editor The editor instance.
   * @param props.query The current suggestion query.
   * @returns An array of suggestion items.
   * @example ({ editor, query }) => [{ id: 1, label: 'John Doe' }]
   */
  items?: (props: {
    query: string;
    editor: Editor;
    signal: AbortSignal;
  }) => I[] | Promise<I[]>;
  /**
   * The render function for the suggestion.
   * @returns An object with render functions.
   */
  render?: () => {
    onBeforeStart?: (props: SuggestionProps<I, TSelected>) => void;
    onStart?: (props: SuggestionProps<I, TSelected>) => void;
    onBeforeUpdate?: (props: SuggestionProps<I, TSelected>) => void;
    onUpdate?: (props: SuggestionProps<I, TSelected>) => void;
    onExit?: (props: SuggestionProps<I, TSelected>) => void;
    onKeyDown?: (props: SuggestionKeyDownProps) => boolean;
  };
  /**
   * A function that returns a boolean to indicate if the suggestion should be active.
   * @param props The props object.
   * @returns {boolean}
   */
  allow?: (props: {
    editor: Editor;
    state: EditorState;
    range: Range;
    isActive?: boolean;
  }) => boolean;
  findSuggestionMatch?: typeof findSuggestionMatch$1;
}
/**
 * The props passed to the suggestion's render functions (onStart, onUpdate, onExit).
 */
interface SuggestionProps<I = any, TSelected = any> {
  /**
   * The editor instance.
   */
  editor: Editor;
  /**
   * The range of the suggestion.
   */
  range: Range;
  /**
   * The current suggestion query.
   */
  query: string;
  /**
   * The current suggestion text.
   */
  text: string;
  /**
   * The suggestion items array.
   */
  items: I[];
  /**
   * A function that is called when a suggestion is selected.
   * @param props The props object.
   * @returns void
   */
  command: (props: TSelected) => void;
  /**
   * The decoration node HTML element
   * @default null
   */
  decorationNode: Element | null;
  /**
   * The function that returns the client rect
   * @default null
   * @example () => new DOMRect(0, 0, 0, 0)
   */
  clientRect?: (() => DOMRect | null) | null;
  /**
   * Placement of the popup relative to the cursor.
   * @default 'bottom-start'
   */
  placement: SuggestionPlacement;
  /**
   * Offset of the popup in pixels.
   * @default { mainAxis: 4, crossAxis: 0 }
   */
  offset: {
    mainAxis: number;
    crossAxis: number;
  };
  /**
   * CSS selector or element that defines the containment context for the popup.
   * @default undefined
   */
  container?: string | HTMLElement;
  /**
   * Whether the popup should automatically flip when there isn't enough space.
   * @default true
   */
  flip: boolean;
  /**
   * Resolved Floating UI config for direct use with `computePosition()`.
   * This is the escape hatch: reach for it only when you mount the element
   * yourself and want to run the positioning loop manually instead of using
   * {@link SuggestionProps.mount}.
   */
  floatingUi: SuggestionFloatingUiConfig;
  /**
   * Mounts your floating element and takes over positioning — the recommended,
   * default way to render a suggestion popup.
   *
   * Pass the element you rendered (e.g. from `ReactRenderer`/`VueRenderer`). The
   * plugin appends it into the configured `container` (default `document.body`),
   * keeps it anchored to the cursor, and repositions it on scroll, resize, and
   * layout shifts — no manual listeners required. Returns an `unmount` function
   * that tears everything down; call it in `onExit`.
   *
   * Escape hatch: mount the element yourself and skip this, then run your own
   * positioning loop with {@link SuggestionProps.floatingUi} +
   * {@link SuggestionProps.clientRect}.
   *
   * @example
   * ```ts
   * onStart: props => {
   *   component = new ReactRenderer(DropdownList, { props, editor: props.editor })
   *   unmount = props.mount(component.element)
   * },
   * onExit: () => unmount?.(),
   * ```
   */
  mount: SuggestionMount;
  /**
   * Whether the items are currently being loaded.
   * `true` before the async `items()` call resolves.
   * Useful for showing a loading spinner or skeleton.
   * @default false
   */
  loading: boolean;
}
/**
 * The props passed to the suggestion's onKeyDown render function
 */
interface SuggestionKeyDownProps {
  view: EditorView;
  event: KeyboardEvent;
  range: Range;
}
/** @internal Internal state shape for the suggestion plugin. */
interface SuggestionPluginState {
  active: boolean;
  range: Range;
  query: null | string;
  text: null | string;
  composing: boolean;
  decorationId?: string | null;
  dismissedRange: Range | null;
}
//#endregion
//#region src/suggestion.d.ts
declare const SuggestionPluginKey: PluginKey<any>;
/**
 * This utility allows you to create suggestions.
 * @see https://tiptap.dev/api/utilities/suggestion
 */
declare function Suggestion<I = any, TSelected = any>({ pluginKey, editor, char, allowSpaces, allowToIncludeChar, allowedPrefixes, startOfLine, decorationTag, decorationClass, decorationContent, decorationEmptyClass, command, items, minQueryLength, debounce, initialItems, placement, offset: offsetOption, container, flip, floatingUi, dismissOnOutsideClick, render, allow, findSuggestionMatch, shouldShow, shouldResetDismissed }: SuggestionOptions<I, TSelected>): Plugin<SuggestionPluginState>;
/**
 * Programmatically exit a suggestion plugin by dispatching a metadata-only
 * transaction. This is the safe, recommended API to remove suggestion
 * decorations without touching the document or causing mapping errors.
 */
declare function exitSuggestion(view: EditorView, pluginKeyRef?: PluginKey): void;
//#endregion
export { Suggestion, Suggestion as default, type SuggestionFloatingUiConfig, type SuggestionFloatingUiOptions, type SuggestionKeyDownProps, SuggestionMatch, type SuggestionMount, type SuggestionMountOptions, type SuggestionOptions, type SuggestionPlacement, SuggestionPluginKey, type SuggestionPositionData, type SuggestionProps, Trigger, exitSuggestion, findSuggestionMatch$1 as findSuggestionMatch };
//# sourceMappingURL=index.d.ts.map