{"version":3,"file":"auto-resize.cjs","names":[],"sources":["../../src/core/auto-resize.ts"],"sourcesContent":["import type { Readable } from '@vielzeug/ripple';\n\nexport type AutoResizeOptions = {\n  /** Gates growth; omit for an always-on composer field, or pass a signal for a toggleable `auto-resize` attribute. */\n  enabled?: Readable<boolean | undefined>;\n};\n\nexport type AutoResizeControl = {\n  /** Recomputes height from the wired element's current content. No-ops when `enabled` is false or nothing is wired. */\n  recompute: () => void;\n  /** Wire onto the raw `<textarea>` when it mounts. Returns a detach function to call on unmount. */\n  wire: (el: HTMLTextAreaElement) => () => void;\n};\n\n/**\n * Grows a `<textarea>`'s height to fit its content, shared by every component that offers\n * auto-resize (`ore-textarea`, `ore-message-composer`) instead of each reimplementing it.\n *\n * Owns only height — manual-resize cursor/direction is a per-component styling concern, not\n * shared behavior, so it stays local to whichever component renders a resize handle.\n *\n * @example\n * ```ts\n * const autoResize = createAutoResize({ enabled: props['auto-resize'] });\n *\n * onElement(textareaRef, (el) => autoResize.wire(el));\n * // after a programmatic value change that doesn't fire a native `input` event:\n * autoResize.recompute();\n * ```\n */\nexport const createAutoResize = (options: AutoResizeOptions = {}): AutoResizeControl => {\n  let wiredEl: HTMLTextAreaElement | null = null;\n\n  const recompute = (): void => {\n    if (!wiredEl || options.enabled?.value === false) return;\n\n    wiredEl.style.height = 'auto';\n    wiredEl.style.height = `${wiredEl.scrollHeight}px`;\n  };\n\n  const wire = (el: HTMLTextAreaElement): (() => void) => {\n    wiredEl = el;\n    el.addEventListener('input', recompute);\n\n    // Deferred a frame: right after mount, the browser hasn't necessarily finished laying out\n    // the textarea yet, so a synchronous `scrollHeight` read here can be stale — often reading\n    // as 0 and collapsing the field until the next real `input` event happens to correct it.\n    // `ore-textarea` has always worked around this locally with its own extra `requestAnimationFrame`\n    // call; folding the deferral into `wire()` itself means every consumer gets it for free.\n    requestAnimationFrame(recompute);\n\n    return () => {\n      el.removeEventListener('input', recompute);\n\n      if (wiredEl === el) wiredEl = null;\n    };\n  };\n\n  return { recompute, wire };\n};\n"],"mappings":"AA8BA,IAAa,GAAoB,EAA6B,CAAC,IAAyB,CACtF,IAAI,EAAsC,KAEpC,MAAwB,CACxB,CAAC,GAAW,EAAQ,SAAS,QAAU,KAE3C,EAAQ,MAAM,OAAS,OACvB,EAAQ,MAAM,OAAS,GAAG,EAAQ,aAAa,IACjD,EAoBA,MAAO,CAAE,YAAW,KAlBN,IACZ,EAAU,EACV,EAAG,iBAAiB,QAAS,CAAS,EAOtC,sBAAsB,CAAS,MAElB,CACX,EAAG,oBAAoB,QAAS,CAAS,EAErC,IAAY,IAAI,EAAU,KAChC,EAGuB,CAC3B"}