{"version":3,"file":"prompt-input-mention-registry.cjs","sources":["../../../components/prompt-input/prompt-input-mention-registry.ts"],"sourcesContent":["'use client';\n\nimport type { ReactNode } from 'react';\nimport { mentionKey } from '../editor/mention';\n\nexport interface PromptInputMentionItem {\n  id: string;\n  label: string;\n  /**\n   * Entity kind, serialized into the markup. A single `@` menu legitimately\n   * returns several kinds, which is why this is per item and not per trigger.\n   * @defaultValue \"mention\"\n   */\n  type?: string;\n  icon?: ReactNode;\n  /** Trailing metadata — a badge, a shortcut, a timestamp. */\n  trailing?: ReactNode;\n  /** Section heading. Groups render in first-appearance order. */\n  group?: string;\n  disabled?: boolean;\n  /** Opaque; handed back on submit. Never serialized. */\n  data?: unknown;\n}\n\n/** A reference parsed out of markup, before it has been resolved. */\nexport interface PromptInputMentionRef {\n  type: string;\n  id: string;\n  label: string;\n}\n\n/** Everything `PromptInput.Mentions` contributes for one trigger. */\nexport interface PromptInputMentionsData {\n  items?: PromptInputMentionItem[];\n  onSearch?: (\n    query: string,\n    context: { trigger: string; signal: AbortSignal }\n  ) => Promise<PromptInputMentionItem[]>;\n  resolveMentions?: (\n    refs: PromptInputMentionRef[]\n  ) => Promise<PromptInputMentionItem[]>;\n  onOpenChange?: (open: boolean) => void;\n  emptyMessage?: ReactNode;\n  loadingRowCount?: number;\n}\n\nexport interface PromptInputMentionsConfig extends PromptInputMentionsData {\n  trigger: string;\n}\n\nfunction sameData(\n  a: PromptInputMentionsData,\n  b: PromptInputMentionsData\n): boolean {\n  return (\n    a.items === b.items &&\n    a.onSearch === b.onSearch &&\n    a.resolveMentions === b.resolveMentions &&\n    a.onOpenChange === b.onOpenChange &&\n    a.emptyMessage === b.emptyMessage &&\n    a.loadingRowCount === b.loadingRowCount\n  );\n}\n\n/**\n * Shared between `Mentions` (which writes the config), `Editor` (which reads\n * triggers, drives the menu and decorates chips) and Root (which reads `data`\n * back when assembling a message).\n *\n * `icon`, `trailing` and `data` cannot survive serialization, so they live here\n * rather than on the document — keyed by `trigger|type|id`, filled in when an\n * item is picked from the menu or returned by `resolveMentions`.\n *\n * Registration is split from data on purpose. The trigger is established once,\n * while the data is pushed after every `Mentions` render and compared field by\n * field — so an inline `items` array stays live without a config object whose\n * identity churns and restarts an in-flight search.\n */\nexport class PromptInputMentionRegistry {\n  private configs = new Map<string, PromptInputMentionsConfig>();\n  private items = new Map<string, PromptInputMentionItem>();\n  private listeners = new Set<() => void>();\n  private revision = 0;\n\n  register(trigger: string): () => void {\n    if (!this.configs.has(trigger)) {\n      this.configs.set(trigger, { trigger });\n      this.emit();\n    }\n    return () => {\n      if (this.configs.delete(trigger)) this.emit();\n    };\n  }\n\n  setData(trigger: string, data: PromptInputMentionsData): void {\n    const current = this.configs.get(trigger);\n    if (!current || sameData(current, data)) return;\n    this.configs.set(trigger, { trigger, ...data });\n    this.emit();\n  }\n\n  get(trigger: string): PromptInputMentionsConfig | undefined {\n    return this.configs.get(trigger);\n  }\n\n  triggers(): string[] {\n    return [...this.configs.keys()];\n  }\n\n  remember(trigger: string, item: PromptInputMentionItem): void {\n    this.rememberAll(trigger, [item]);\n  }\n\n  rememberAll(trigger: string, items: PromptInputMentionItem[]): void {\n    if (items.length === 0) return;\n    for (const item of items) {\n      const type = item.type ?? 'mention';\n      this.items.set(mentionKey(trigger, type, item.id), { ...item, type });\n    }\n    this.emit();\n  }\n\n  lookup(\n    trigger: string,\n    type: string,\n    id: string\n  ): PromptInputMentionItem | undefined {\n    return this.items.get(mentionKey(trigger, type, id));\n  }\n\n  has(trigger: string, type: string, id: string): boolean {\n    return this.items.has(mentionKey(trigger, type, id));\n  }\n\n  subscribe = (listener: () => void): (() => void) => {\n    this.listeners.add(listener);\n    return () => {\n      this.listeners.delete(listener);\n    };\n  };\n\n  /**\n   * Bumped by every mutation. Read as a `useSyncExternalStore` snapshot, so a\n   * reader that mounts after a writer has already emitted still sees the\n   * change — `Mentions` registers its trigger in an effect that runs before a\n   * later sibling `Editor` has subscribed.\n   */\n  getRevision = (): number => this.revision;\n\n  private emit() {\n    this.revision += 1;\n    for (const listener of this.listeners) listener();\n  }\n}\n"],"names":[],"mappings":";;;;;AAkDA;AAIE;AAEE;AACA;AACA;AACA;AACA;AAEJ;AAEA;;;;;;;;;;;;;AAaG;;AAEO;AACA;AACA;;AAGR;;;;;AAKE;AACE;;AACF;;;;;;AAMA;;;AAIF;;;;;;;;;;AAaE;;AACA;AACE;;;;;AAMJ;AAKE;;AAGF;AACE;;AAGF;AACE;AACA;AACE;AACF;AACF;AAEA;;;;;AAKG;AACH;;AAGE;AACA;AAAuC;;AAE1C;;"}