{"version":3,"file":"composer.cjs","names":[],"sources":["../../src/core/composer.ts"],"sourcesContent":["import type { Readable } from '@vielzeug/ripple';\n\nimport { computed } from '@vielzeug/ripple';\n\n/**\n * Keyboard shortcut that triggers a send:\n * - `'enter'` (default) — Enter sends, Shift+Enter inserts a newline.\n * - `'mod+enter'` — Enter always inserts a newline; Ctrl/Cmd+Enter sends.\n */\nexport type SendShortcut = 'enter' | 'mod+enter';\n\nexport type ComposerControlOptions = {\n  disabled?: Readable<boolean | undefined>;\n  /** Blocks further sends (e.g. a send is already in flight) without disabling editing. */\n  loading?: Readable<boolean | undefined>;\n  /** Called for a send attempt that passed the `canSend` guard. */\n  onSend: (event: KeyboardEvent | MouseEvent) => void;\n  sendShortcut?: Readable<SendShortcut | undefined>;\n  value: Readable<string | undefined>;\n};\n\nexport type ComposerControl = {\n  /** Whether the current value is non-blank and the control isn't disabled/loading. */\n  canSend: Readable<boolean>;\n  /** Wire onto the raw `<textarea>`'s `keydown` — intercepts the resolved send shortcut. */\n  handleKeydown: (event: KeyboardEvent) => void;\n  /** `aria-keyshortcuts` value describing the resolved shortcut. */\n  keyShortcutsHint: Readable<string>;\n  /** Attempts a send; no-ops when `canSend` is false. Wire onto the send button's `click`. */\n  send: (event: KeyboardEvent | MouseEvent) => void;\n};\n\nconst isBlank = (value: string | undefined): boolean => !value || value.trim() === '';\n\n/**\n * Send-gesture logic for a message/comment composer — decides *when* a send is allowed\n * and *whether* a given keydown counts as one. Owns no DOM, value state, or event dispatch;\n * the component wires `handleKeydown`/`send` and decides what a send actually does.\n *\n * @example\n * ```ts\n * const composer = createComposerControl({\n *   onSend: (event) => attemptSend(event),\n *   sendShortcut: props['send-shortcut'],\n *   value,\n * });\n * // <textarea @keydown=\"${composer.handleKeydown}\" aria-keyshortcuts=\"${composer.keyShortcutsHint}\">\n * // <button ?disabled=\"${() => !composer.canSend.value}\" @click=\"${composer.send}\">\n * ```\n */\nexport const createComposerControl = (options: ComposerControlOptions): ComposerControl => {\n  const canSend = computed(() => !isBlank(options.value.value) && !options.disabled?.value && !options.loading?.value);\n\n  const send = (event: KeyboardEvent | MouseEvent): void => {\n    if (!canSend.value) return;\n\n    options.onSend(event);\n  };\n\n  const handleKeydown = (event: KeyboardEvent): void => {\n    // A composing IME candidate selection also fires `Enter` — never treat that as a send.\n    if (event.key !== 'Enter' || event.isComposing) return;\n\n    const mode = options.sendShortcut?.value ?? 'enter';\n    const hasModifier = event.metaKey || event.ctrlKey;\n\n    if (mode === 'mod+enter' ? !hasModifier : event.shiftKey) return;\n\n    event.preventDefault();\n    send(event);\n  };\n\n  const keyShortcutsHint = computed(() =>\n    (options.sendShortcut?.value ?? 'enter') === 'mod+enter' ? 'Control+Enter Meta+Enter' : 'Enter',\n  );\n\n  return { canSend, handleKeydown, keyShortcutsHint, send };\n};\n"],"mappings":"kCAgCA,IAAM,EAAW,GAAuC,CAAC,GAAS,EAAM,KAAK,IAAM,GAkBtE,EAAyB,GAAqD,CACzF,IAAM,GAAA,EAAU,EAAA,SAAA,KAAe,CAAC,EAAQ,EAAQ,MAAM,KAAK,GAAK,CAAC,EAAQ,UAAU,OAAS,CAAC,EAAQ,SAAS,KAAK,EAE7G,EAAQ,GAA4C,CACnD,EAAQ,OAEb,EAAQ,OAAO,CAAK,CACtB,EAmBA,MAAO,CAAE,UAAS,cAjBK,GAA+B,CAEpD,GAAI,EAAM,MAAQ,SAAW,EAAM,YAAa,OAEhD,IAAM,EAAO,EAAQ,cAAc,OAAS,QACtC,EAAc,EAAM,SAAW,EAAM,SAEvC,IAAS,YAAc,CAAC,EAAc,EAAM,YAEhD,EAAM,eAAe,EACrB,EAAK,CAAK,EACZ,EAMiC,kBAAA,EAJR,EAAA,SAAA,MACtB,EAAQ,cAAc,OAAS,WAAa,YAAc,2BAA6B,OAGzD,EAAkB,MAAK,CAC1D"}