{"version":3,"file":"templateEditable.mjs","names":[],"sources":["../../../../package/common/templateEditor/templateEditable.tsx"],"sourcesContent":["import { useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport { flushSync } from 'react-dom';\nimport cx from 'classnames';\nimport { faEye } from '@fortawesome/free-solid-svg-icons';\nimport ActionIcon from 'components/common/actionIcon';\nimport BodyEnd from 'components/common/bodyEnd';\n\nimport styles from './templateEditor.module.pcss';\nimport { useOverlay } from '../hooks/useOverlay';\nimport { usePopoverPosition } from '../popover/usePopoverPosition';\nimport { PopoverAlign, PopoverPlacement } from '../popover/popover.types';\nimport { ButtonStyleType } from '../button/button.types';\nimport { ThemeColor } from '../themeProvider/color.types';\nimport TemplateEditorSuggestions from './templateEditorSuggestions';\nimport {\n  chipsWithin,\n  closestChip,\n  domToValue,\n  getCaretOffset,\n  getSelectionOffsets,\n  hasFocusWithin,\n  isAfterChip,\n  markSelectedChips,\n  morphChips,\n  normalizeEditable,\n  offsetFromPoint,\n  offsetOfPoint,\n  rectOfOffsets,\n  scrollOffsetIntoView,\n  refreshChips,\n  renderValue,\n  setSelectionOffsets,\n} from './templateEditor.dom';\nimport {\n  cutChip,\n  filterGroups,\n  flattenTokens,\n  isLineStartBeforeToken,\n  normalizeLineBreaks,\n  openTokenRun,\n  parseTemplate,\n  spacesAround,\n  tokenLength,\n  tokenSpanEndingAt,\n  tokenSpanStartingAt,\n} from './templateEditor.utils';\nimport type { TemplateEditableProps } from './templateEditor.types';\n\n/** Consecutive plain-text edits closer together than this collapse into one undo step. */\nconst HISTORY_COALESCE_MS = 500;\nconst HISTORY_LIMIT = 100;\n\n/**\n * Editing is intercepted on `beforeinput` rather than `keydown` throughout:\n * Android soft keyboards report `keyCode 229` for every key, so Enter and\n * Backspace are simply not identifiable from a key event there. `keydown` is\n * used only for navigation, Escape, and the undo shortcuts.\n */\nconst EVENT_TYPES = [\n  'beforeinput',\n  'input',\n  'keydown',\n  'mousedown',\n  'click',\n  'compositionstart',\n  'compositionend',\n  'paste',\n  'copy',\n  'cut',\n  'dragstart',\n  'dragenter',\n  'dragover',\n  'dragleave',\n  'drop',\n  'dragend',\n] as const;\n\ntype EventType = (typeof EVENT_TYPES)[number];\ntype Handlers = Partial<Record<EventType, (event: never) => void>>;\n\ninterface HistoryEntry {\n  value: string;\n  caret: number;\n}\n\ninterface HistoryState {\n  entries: HistoryEntry[];\n  index: number;\n  lastPushAt: number;\n}\n\nfunction freshHistory(value: string, caret: number): HistoryState {\n  return { entries: [{ value, caret }], index: 0, lastPushAt: 0 };\n}\n\ninterface SuggestState {\n  /** What a pick replaces: the typed run from its opening delimiter, or the selection the menu was opened on. */\n  start: number;\n  end: number;\n  query: string;\n  fromMenu?: boolean;\n}\n\ninterface Offsets {\n  start: number;\n  end: number;\n}\n\nfunction isOneToken(text: string, prefix: string, suffix: string): boolean {\n  const segments = parseTemplate(text, prefix, suffix);\n  return segments.length === 1 && segments[0].type === 'token';\n}\n\nfunction TemplateEditable({\n  value = '',\n  onChange,\n  onFocus,\n  onBlur,\n  className,\n  style,\n  id,\n  tabIndex = 0,\n  readOnly = false,\n  disabled = false,\n  apiRef,\n  dragRef,\n  chipContext,\n  tokenGroups,\n  ariaLabel,\n  multiline = true,\n  rows = 4,\n  autoFocus = false,\n  smartSpacing = true,\n  menuLabel,\n  previewLabel,\n  onTogglePreview,\n  classNames,\n  styles: slotStyles,\n}: TemplateEditableProps) {\n  const wrapperRef = useRef<HTMLDivElement>(null);\n  const editableRef = useRef<HTMLDivElement>(null);\n  const caretAnchorRef = useRef<HTMLSpanElement>(null);\n  const dropCaretRef = useRef<HTMLSpanElement>(null);\n  const popupAnchorRef = useRef<HTMLDivElement>(null);\n  const popupPanelRef = useRef<HTMLDivElement>(null);\n  const noArrowRef = useRef<HTMLElement>(null);\n  const menuButtonRef = useRef<HTMLButtonElement>(null);\n\n  // `null` rather than the initial value, so the first layout effect always\n  // renders the incoming value into the (still empty) editable.\n  const lastEmittedRef = useRef<string | null>(null);\n  const lastSelectionRef = useRef<Offsets | null>(null);\n  const isComposingRef = useRef(false);\n  const pendingResyncRef = useRef<string | null>(null);\n  const dismissedRunRef = useRef<number | null>(null);\n  const historyRef = useRef<HistoryState>({ entries: [], index: -1, lastPushAt: 0 });\n  const chipContextRef = useRef(chipContext);\n  const handlersRef = useRef<Handlers>({});\n\n  const [suggest, setSuggest] = useState<SuggestState | null>(null);\n  const [highlightRequest, setHighlightRequest] = useState<string | null>(null);\n\n  const generatedId = useId();\n  const listId = `${id ?? generatedId}-suggestions`;\n  const optionId = useCallback((tokenId: string) => `${listId}-${tokenId.replace(/\\W/g, '-')}`, [listId]);\n\n  const { prefix, suffix } = chipContext;\n  const editingBlocked = readOnly || disabled;\n\n  const suggestionGroups = useMemo(() => {\n    if (!suggest) return [];\n    return filterGroups(tokenGroups, suggest.query)\n      .map((group) => ({ ...group, tokens: group.tokens.filter((token) => !token.disabled) }))\n      .filter((group) => group.tokens.length > 0);\n  }, [tokenGroups, suggest]);\n  const suggestionTokens = useMemo(() => flattenTokens(suggestionGroups), [suggestionGroups]);\n  const isSuggestOpen = !!suggest && suggestionTokens.length > 0;\n  const isMenuOpen = isSuggestOpen && !!suggest?.fromMenu;\n  const canPick = useMemo(() => flattenTokens(tokenGroups).some((token) => !token.disabled), [tokenGroups]);\n  // Derived rather than stored: a request that no longer matches the filtered\n  // list simply falls back to the first entry, so no effect has to reset it.\n  const highlightedId =\n    highlightRequest && suggestionTokens.some((token) => token.id === highlightRequest)\n      ? highlightRequest\n      : (suggestionTokens[0]?.id ?? null);\n\n  const currentValue = useCallback(\n    () => (editableRef.current ? domToValue(editableRef.current, prefix, suffix) : ''),\n    [prefix, suffix],\n  );\n\n  /**\n   * Where an insertion should land. The live selection wins whenever it is\n   * still inside this field. `lastSelectionRef` covers the rest, which is the\n   * normal case for a palette click: the palette cannot suppress its own\n   * mousedown without also killing drag initiation, so the field really does\n   * blur, and the caret has to be recovered from the last recorded selection.\n   */\n  const resolveOffsets = useCallback((): Offsets => {\n    const el = editableRef.current;\n    const end = el ? domToValue(el, prefix, suffix).length : 0;\n    const live = el ? getSelectionOffsets(el, prefix, suffix) : null;\n    return live ?? lastSelectionRef.current ?? { start: end, end };\n  }, [prefix, suffix]);\n\n  const pushHistory = useCallback((next: string, caret: number, discrete: boolean) => {\n    const history = historyRef.current;\n    history.entries = history.entries.slice(0, history.index + 1);\n    const now = Date.now();\n    const canCoalesce = !discrete && history.index >= 0 && now - history.lastPushAt < HISTORY_COALESCE_MS;\n    if (canCoalesce) {\n      history.entries[history.index] = { value: next, caret };\n    } else {\n      history.entries.push({ value: next, caret });\n      if (history.entries.length > HISTORY_LIMIT) history.entries.shift();\n      history.index = history.entries.length - 1;\n    }\n    history.lastPushAt = now;\n  }, []);\n\n  const commit = useCallback(\n    (next: string, caret: number, options: { history?: 'push' | 'skip'; discrete?: boolean } = {}) => {\n      if (next === lastEmittedRef.current) return;\n      lastEmittedRef.current = next;\n      if (options.history !== 'skip') pushHistory(next, caret, options.discrete ?? false);\n      onChange?.(next);\n    },\n    [onChange, pushHistory],\n  );\n\n  /** Re-renders the editable from a template string and puts the caret at an exact offset. */\n  const applyValue = useCallback(\n    (next: string, caret: number, options: { history?: 'push' | 'skip'; discrete?: boolean } = {}) => {\n      const el = editableRef.current;\n      if (!el) return;\n      // Rebuilding every child can clamp scrollTop, so it is restored before the\n      // caret is revealed; otherwise the field lurches to the top mid-edit.\n      const { scrollTop } = el;\n      renderValue(el, next, chipContextRef.current);\n      el.scrollTop = scrollTop;\n      setSelectionOffsets(el, caret, caret, prefix, suffix);\n      lastSelectionRef.current = { start: caret, end: caret };\n      if (hasFocusWithin(el)) scrollOffsetIntoView(el, caret, prefix, suffix);\n      commit(next, caret, options);\n    },\n    [commit, prefix, suffix],\n  );\n\n  const spliceValue = useCallback(\n    (start: number, end: number, insert: string, discrete = true) => {\n      const value = currentValue();\n      applyValue(value.slice(0, start) + insert + value.slice(end), start + insert.length, { discrete });\n    },\n    [applyValue, currentValue],\n  );\n\n  /** Reads the DOM back after a native edit, repairing it first. */\n  const emit = useCallback(() => {\n    const el = editableRef.current;\n    if (!el) return;\n    const before = getSelectionOffsets(el, prefix, suffix);\n    const changed = normalizeEditable(el, chipContextRef.current);\n    if (changed && before && hasFocusWithin(el)) {\n      setSelectionOffsets(el, before.start, before.end, prefix, suffix);\n    }\n    const next = domToValue(el, prefix, suffix);\n    const selection = getSelectionOffsets(el, prefix, suffix);\n    if (selection) lastSelectionRef.current = selection;\n    commit(next, selection?.start ?? next.length);\n  }, [commit, prefix, suffix]);\n\n  /**\n   * Pops in the chips an insertion or a drop placed between two offsets. Only those: the splice\n   * rebuilt every chip, and a class on all of them would animate the whole template each time.\n   */\n  const markPlaced = useCallback(\n    (start: number, end: number) => {\n      const el = editableRef.current;\n      if (!el) return;\n      chipsWithin(el, start, end, prefix, suffix).forEach((chip) => {\n        chip.classList.add(styles.templateEditorChipInserted);\n        chip.addEventListener('animationend', () => chip.classList.remove(styles.templateEditorChipInserted), {\n          once: true,\n        });\n      });\n    },\n    [prefix, suffix],\n  );\n\n  /**\n   * Puts `text` over `start…end` of `value`, with smart spacing's spaces around it when `spaced`.\n   * The caret goes right after the text, before a space added after it, so punctuation typed next\n   * lands against the chip: `{{name}}, one`, not `{{name}} ,one`.\n   */\n  const place = useCallback(\n    (text: string, start: number, end: number, value: string, spaced: boolean) => {\n      const [before, after] = spaced && smartSpacing ? spacesAround(value, start, end, prefix, suffix) : ['', ''];\n      const from = start + before.length;\n      applyValue(value.slice(0, start) + before + text + after + value.slice(end), from + text.length, {\n        discrete: true,\n      });\n      markPlaced(from, from + text.length);\n    },\n    [applyValue, markPlaced, prefix, smartSpacing, suffix],\n  );\n\n  const insertTokenAt = useCallback(\n    (tokenId: string, start: number, end: number, spaced = true) => {\n      const el = editableRef.current;\n      if (!el || editingBlocked) return;\n      el.focus({ preventScroll: true });\n      place(prefix + tokenId + suffix, start, end, currentValue(), spaced);\n      setSuggest(null);\n      dismissedRunRef.current = null;\n    },\n    [currentValue, editingBlocked, place, prefix, suffix],\n  );\n\n  /**\n   * Opens the popup on the unterminated run the caret sits in, and closes it once\n   * the caret leaves. The menu stays open for exactly as long as the selection it\n   * was opened on, so typing or moving the caret closes it.\n   */\n  const detectSuggest = useCallback(() => {\n    const el = editableRef.current;\n    const selection = el && !editingBlocked && !isComposingRef.current ? getSelectionOffsets(el, prefix, suffix) : null;\n    const caret = selection && selection.start === selection.end ? selection.start : null;\n    const run = el && caret !== null ? openTokenRun(domToValue(el, prefix, suffix), caret, prefix, suffix) : null;\n    if (caret !== null && !run) dismissedRunRef.current = null;\n    const typed =\n      run && caret !== null && dismissedRunRef.current !== run.start\n        ? { start: run.start, end: caret, query: run.query }\n        : null;\n    setSuggest((current) => {\n      if (current?.fromMenu && current.start === selection?.start && current.end === selection?.end) return current;\n      if (!typed) return null;\n      return current && !current.fromMenu && current.start === typed.start && current.query === typed.query\n        ? current\n        : typed;\n    });\n  }, [editingBlocked, prefix, suffix]);\n\n  const applyHistory = useCallback(\n    (direction: -1 | 1) => {\n      const history = historyRef.current;\n      const nextIndex = history.index + direction;\n      if (nextIndex < 0 || nextIndex >= history.entries.length) return;\n      const el = editableRef.current;\n      if (!el) return;\n      history.index = nextIndex;\n      history.lastPushAt = 0;\n      const entry = history.entries[nextIndex];\n      const { scrollTop } = el;\n      renderValue(el, entry.value, chipContextRef.current);\n      el.scrollTop = scrollTop;\n      setSelectionOffsets(el, entry.caret, entry.caret, prefix, suffix);\n      lastSelectionRef.current = { start: entry.caret, end: entry.caret };\n      if (hasFocusWithin(el)) scrollOffsetIntoView(el, entry.caret, prefix, suffix);\n      commit(entry.value, entry.caret, { history: 'skip' });\n      setSuggest(null);\n    },\n    [commit, prefix, suffix],\n  );\n\n  /** The offsets a placed chip occupies, used as the source span of a chip drag. */\n  const spanOfChip = useCallback(\n    (chip: HTMLElement): Offsets | null => {\n      const el = editableRef.current;\n      if (!el || !chip.parentNode) return null;\n      const index = Array.prototype.indexOf.call(chip.parentNode.childNodes, chip);\n      const start = offsetOfPoint(el, chip.parentNode, index, prefix, suffix);\n      return { start, end: start + tokenLength(chip.dataset.token ?? '', prefix, suffix) };\n    },\n    [prefix, suffix],\n  );\n\n  const showDropCaret = useCallback(\n    (offset: number | null) => {\n      const el = editableRef.current;\n      const caret = dropCaretRef.current;\n      const wrapper = wrapperRef.current;\n      if (!el || !caret || !wrapper) return;\n      const rect = offset == null ? null : rectOfOffsets(el, offset, offset, prefix, suffix);\n      if (!rect) {\n        caret.classList.remove(styles.templateEditorDropCaretVisible);\n        return;\n      }\n      const host = wrapper.getBoundingClientRect();\n      caret.style.left = `${rect.left - host.left}px`;\n      caret.style.top = `${rect.top - host.top}px`;\n      caret.style.height = `${rect.height || 16}px`;\n      caret.classList.add(styles.templateEditorDropCaretVisible);\n    },\n    [prefix, suffix],\n  );\n\n  const commitSuggestion = useCallback(\n    (tokenId: string) => {\n      // A run typed out is literal, as all typing is: only a pick from the menu is spaced.\n      if (suggest) insertTokenAt(tokenId, suggest.start, suggest.end, !!suggest.fromMenu);\n    },\n    [insertTokenAt, suggest],\n  );\n\n  const toggleMenu = useCallback(() => {\n    const el = editableRef.current;\n    if (!el || editingBlocked) return;\n    if (suggest?.fromMenu) {\n      setSuggest(null);\n      return;\n    }\n    const { start, end } = resolveOffsets();\n    el.focus({ preventScroll: true });\n    setSelectionOffsets(el, start, end, prefix, suffix);\n    lastSelectionRef.current = { start, end };\n    setHighlightRequest(null);\n    setSuggest({ start, end, query: '', fromMenu: true });\n  }, [editingBlocked, prefix, resolveOffsets, suffix, suggest?.fromMenu]);\n\n  // ---------------------------------------------------------------- handlers\n\n  const handlers: Handlers = {\n    beforeinput: (event: InputEvent) => {\n      const el = editableRef.current;\n      if (!el) return;\n      if (editingBlocked) {\n        event.preventDefault();\n        return;\n      }\n      const { inputType } = event;\n\n      if (inputType === 'historyUndo' || inputType === 'historyRedo') {\n        event.preventDefault();\n        applyHistory(inputType === 'historyUndo' ? -1 : 1);\n        return;\n      }\n      // Paste and drop are handled by their own events, which carry the data. `deleteByDrag` too:\n      // `dragend` removes what was moved out, and the browser's own removal on top of it took\n      // the same span out a second time.\n      if (inputType === 'insertFromPaste' || inputType === 'insertFromDrop' || inputType === 'deleteByDrag') {\n        event.preventDefault();\n        return;\n      }\n      if (inputType === 'insertParagraph' || inputType === 'insertLineBreak') {\n        event.preventDefault();\n        if (!multiline) return;\n        const selection = getSelectionOffsets(el, prefix, suffix);\n        const start = selection?.start ?? domToValue(el, prefix, suffix).length;\n        spliceValue(start, selection?.end ?? start, '\\n');\n        return;\n      }\n      if (inputType === 'deleteContentBackward' || inputType === 'deleteContentForward') {\n        const selection = getSelectionOffsets(el, prefix, suffix);\n        if (!selection) return;\n        if (selection.start !== selection.end) {\n          event.preventDefault();\n          spliceValue(selection.start, selection.end, '');\n          return;\n        }\n        // A chip is one unit: never let the browser nibble at its label.\n        const current = domToValue(el, prefix, suffix);\n        const backward = inputType === 'deleteContentBackward';\n        const span = backward\n          ? tokenSpanEndingAt(current, selection.start, prefix, suffix)\n          : tokenSpanStartingAt(current, selection.start, prefix, suffix);\n        if (span) {\n          event.preventDefault();\n          spliceValue(span.start, span.end, '');\n        } else if (backward && isLineStartBeforeToken(current, selection.start, prefix, suffix)) {\n          // Left to the browser, this deletes the spacer's invisible character and nothing else.\n          event.preventDefault();\n          spliceValue(selection.start - 1, selection.start, '');\n        } else {\n          // A character whose removal leaves a chip starting its line, where it gets a spacer: left to\n          // the browser, the caret ended up after the chip in Chromium and on the line above in WebKit.\n          // Half a surrogate pair is left to it, since it removes the whole character.\n          const at = backward ? selection.start - 1 : selection.start;\n          const unit = current.charCodeAt(at);\n          const without = current.slice(0, at) + current.slice(at + 1);\n          if (unit && (unit < 0xd800 || unit > 0xdfff) && isLineStartBeforeToken(without, at, prefix, suffix)) {\n            event.preventDefault();\n            spliceValue(at, at + 1, '');\n          }\n        }\n      }\n    },\n\n    input: () => {\n      if (isComposingRef.current) return;\n      emit();\n      detectSuggest();\n    },\n\n    keydown: (event: KeyboardEvent) => {\n      const el = editableRef.current;\n      if (!el) return;\n\n      if (isSuggestOpen) {\n        if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n          event.preventDefault();\n          const index = suggestionTokens.findIndex((token) => token.id === highlightedId);\n          const delta = event.key === 'ArrowDown' ? 1 : -1;\n          const next = (index + delta + suggestionTokens.length) % suggestionTokens.length;\n          setHighlightRequest(suggestionTokens[next]?.id ?? null);\n          return;\n        }\n        if (event.key === 'Enter' || event.key === 'Tab') {\n          const tokenId = highlightedId ?? suggestionTokens[0]?.id;\n          if (tokenId) {\n            event.preventDefault();\n            commitSuggestion(tokenId);\n          }\n          return;\n        }\n      }\n\n      // Undo and redo: Safari does not reliably emit the beforeinput history types.\n      const mod = event.metaKey || event.ctrlKey;\n      if (mod && (event.key === 'z' || event.key === 'Z')) {\n        event.preventDefault();\n        if (!editingBlocked) applyHistory(event.shiftKey ? 1 : -1);\n        return;\n      }\n      if (mod && (event.key === 'y' || event.key === 'Y')) {\n        event.preventDefault();\n        if (!editingBlocked) applyHistory(1);\n        return;\n      }\n\n      if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') return;\n      if (event.shiftKey || event.altKey || mod) return;\n      const selection = getSelectionOffsets(el, prefix, suffix);\n      if (!selection || selection.start !== selection.end) return;\n      const view = el.ownerDocument.defaultView;\n      const rtl = !!view && view.getComputedStyle(el).direction === 'rtl';\n      const backwards = rtl ? event.key === 'ArrowRight' : event.key === 'ArrowLeft';\n      const current = domToValue(el, prefix, suffix);\n      const span = backwards\n        ? tokenSpanEndingAt(current, selection.start, prefix, suffix)\n        : tokenSpanStartingAt(current, selection.start, prefix, suffix);\n      const step = backwards ? selection.start - 1 : selection.start + 1;\n      // Onto or off a line's spacer: natively its zero-width character is a stop\n      // of its own, a press that moves nothing on screen.\n      const viaSpacer =\n        isLineStartBeforeToken(current, selection.start, prefix, suffix) ||\n        isLineStartBeforeToken(current, step, prefix, suffix);\n      if (!span && !viaSpacer) return;\n      // Step over the chip in a single press, landing on its far edge. Left to\n      // the browser, an atomic `contenteditable=false` element yields an extra,\n      // invisible stop that reads as the caret disappearing into the chip.\n      // Deleting a whole chip does not depend on this: `beforeinput` removes the\n      // entire placeholder from either edge on one Backspace or Delete. Shift is\n      // excluded above, so extending a selection over a chip stays native.\n      event.preventDefault();\n      const target = span ? (backwards ? span.start : span.end) : step;\n      setSelectionOffsets(el, target, target, prefix, suffix);\n      lastSelectionRef.current = { start: target, end: target };\n    },\n\n    // Chips are imperative DOM, so presses on them and on their remove buttons\n    // are delegated from the editable rather than bound per chip.\n    mousedown: (event: MouseEvent) => {\n      // Stops the press from moving the caret into the chip or starting a drag.\n      if ((event.target as HTMLElement | null)?.closest?.('[data-chip-remove]')) event.preventDefault();\n    },\n\n    click: (event: MouseEvent) => {\n      const el = editableRef.current;\n      if (!el || editingBlocked) return;\n      const target = event.target as HTMLElement | null;\n      const chip = closestChip(el, target);\n      const span = chip ? spanOfChip(chip) : null;\n      if (!chip || !span) return;\n      el.focus({ preventScroll: true });\n      if (target?.closest?.('[data-chip-remove]')) {\n        event.preventDefault();\n        event.stopPropagation();\n        const { value: next, at } = cutChip(currentValue(), span.start, span.end, smartSpacing);\n        applyValue(next, at, { discrete: true });\n        return;\n      }\n      // A chip has no caret positions of its own, and with no margin beside it the\n      // text between two chips is zero wide. So the chip is the click target for\n      // both of its sides, and the half nearer the pointer decides which.\n      const offset = isAfterChip(el, chip, event.clientX, event.clientY) ? span.end : span.start;\n      setSelectionOffsets(el, offset, offset, prefix, suffix);\n      lastSelectionRef.current = { start: offset, end: offset };\n    },\n\n    compositionstart: () => {\n      isComposingRef.current = true;\n      setSuggest(null);\n    },\n\n    compositionend: () => {\n      isComposingRef.current = false;\n      const pending = pendingResyncRef.current;\n      pendingResyncRef.current = null;\n      const el = editableRef.current;\n      if (pending !== null && el) {\n        renderValue(el, pending, chipContextRef.current);\n        lastEmittedRef.current = pending;\n        historyRef.current = freshHistory(pending, pending.length);\n        return;\n      }\n      emit();\n      detectSuggest();\n    },\n\n    paste: (event: ClipboardEvent) => {\n      event.preventDefault();\n      const el = editableRef.current;\n      if (!el || editingBlocked) return;\n      const text = event.clipboardData?.getData('text/plain') ?? '';\n      const selection = getSelectionOffsets(el, prefix, suffix);\n      const start = selection?.start ?? domToValue(el, prefix, suffix).length;\n      spliceValue(start, selection?.end ?? start, normalizeLineBreaks(text, multiline));\n    },\n\n    copy: (event: ClipboardEvent) => {\n      const el = editableRef.current;\n      if (!el) return;\n      const selection = getSelectionOffsets(el, prefix, suffix);\n      if (!selection || selection.start === selection.end) return;\n      // Without this the clipboard gets a chip's *label*, so a copy and paste\n      // would silently turn a placeholder into ordinary prose.\n      event.preventDefault();\n      event.clipboardData?.setData('text/plain', domToValue(el, prefix, suffix).slice(selection.start, selection.end));\n    },\n\n    cut: (event: ClipboardEvent) => {\n      const el = editableRef.current;\n      if (!el) return;\n      const selection = getSelectionOffsets(el, prefix, suffix);\n      if (!selection || selection.start === selection.end) return;\n      event.preventDefault();\n      event.clipboardData?.setData('text/plain', domToValue(el, prefix, suffix).slice(selection.start, selection.end));\n      if (editingBlocked) return;\n      spliceValue(selection.start, selection.end, '');\n    },\n\n    dragstart: (event: DragEvent) => {\n      const el = editableRef.current;\n      if (!el || editingBlocked) {\n        event.preventDefault();\n        return;\n      }\n      const chip = closestChip(el, event.target as Node);\n      const span = chip ? spanOfChip(chip) : getSelectionOffsets(el, prefix, suffix);\n      if (!span || span.start === span.end) {\n        event.preventDefault();\n        return;\n      }\n      const text = domToValue(el, prefix, suffix).slice(span.start, span.end);\n      dragRef.current = { kind: 'move', text, start: span.start, end: span.end, source: el };\n      event.dataTransfer?.setData('text/plain', text);\n      if (event.dataTransfer) event.dataTransfer.effectAllowed = 'move';\n      chip?.setAttribute('data-dragging', 'true');\n    },\n\n    // Chrome only needs `dragover` prevented to accept a drop, but Firefox wants\n    // `dragenter` prevented as well before it treats this as a drop target.\n    dragenter: (event: DragEvent) => {\n      const el = editableRef.current;\n      if (!el || editingBlocked) return;\n      if (!dragRef.current && event.dataTransfer && Array.from(event.dataTransfer.types).includes('Files')) return;\n      event.preventDefault();\n      el.setAttribute('data-dragover', 'true');\n    },\n\n    dragover: (event: DragEvent) => {\n      const el = editableRef.current;\n      if (!el || editingBlocked) return;\n      const payload = dragRef.current;\n      // Files belong to DropZone, not here.\n      if (!payload && event.dataTransfer && Array.from(event.dataTransfer.types).includes('Files')) return;\n      event.preventDefault();\n      // A chip dragged out of another editor allows only `move`, and the browser refuses a drop\n      // whose effect the source does not allow: answered with `copy`, it never dropped.\n      if (event.dataTransfer) {\n        const move = payload?.kind === 'move' || event.dataTransfer.effectAllowed === 'move';\n        event.dataTransfer.dropEffect = move ? 'move' : 'copy';\n      }\n      el.setAttribute('data-dragover', 'true');\n      showDropCaret(offsetFromPoint(el, event.clientX, event.clientY, prefix, suffix));\n    },\n\n    dragleave: (event: DragEvent) => {\n      const el = editableRef.current;\n      if (!el) return;\n      if (event.relatedTarget && el.contains(event.relatedTarget as Node)) return;\n      el.removeAttribute('data-dragover');\n      showDropCaret(null);\n    },\n\n    drop: (event: DragEvent) => {\n      const el = editableRef.current;\n      if (!el) return;\n      const payload = dragRef.current;\n      if (!payload && event.dataTransfer && Array.from(event.dataTransfer.types).includes('Files')) return;\n      // Mandatory: without it the browser inserts its own markup into the editable.\n      event.preventDefault();\n      el.removeAttribute('data-dragover');\n      showDropCaret(null);\n      el.querySelector('[data-dragging]')?.removeAttribute('data-dragging');\n      dragRef.current = null;\n      if (editingBlocked) return;\n\n      const current = domToValue(el, prefix, suffix);\n      // Neither caret-from-point API exists in every engine; where it is\n      // missing the drop lands wherever the caret already was.\n      const dropped = offsetFromPoint(el, event.clientX, event.clientY, prefix, suffix) ?? resolveOffsets().start;\n\n      if (payload?.kind === 'insert') {\n        insertTokenAt(payload.id, dropped, dropped);\n        return;\n      }\n      if (payload?.kind === 'move' && payload.source === el) {\n        // Dropped back inside itself: nothing to do.\n        if (dropped >= payload.start && dropped <= payload.end) return;\n        // Spaced as a chip only when it is one: a dragged selection of text moves as it was.\n        const one = isOneToken(payload.text, prefix, suffix);\n        const { value: without } = cutChip(current, payload.start, payload.end, one && smartSpacing);\n        const target = dropped > payload.end ? dropped - (current.length - without.length) : dropped;\n        el.focus({ preventScroll: true });\n        place(payload.text, target, target, without, one);\n        return;\n      }\n      // Anything else: a drag out of another editor, or out of another app.\n      const text = normalizeLineBreaks(event.dataTransfer?.getData('text/plain') ?? '', multiline);\n      if (!text) return;\n      el.focus({ preventScroll: true });\n      place(text, dropped, dropped, current, isOneToken(text, prefix, suffix));\n    },\n\n    dragend: (event: DragEvent) => {\n      const el = editableRef.current;\n      const payload = dragRef.current;\n      dragRef.current = null;\n      el?.removeAttribute('data-dragover');\n      el?.querySelector('[data-dragging]')?.removeAttribute('data-dragging');\n      showDropCaret(null);\n      // Moved somewhere else, such as another editor, so it leaves this one, as dragged text does. A\n      // drop back into this field has already moved it and cleared the payload. Not through\n      // `applyValue`, which would pull the caret back out of the field it was dropped into.\n      if (!el || editingBlocked || payload?.kind !== 'move' || event.dataTransfer?.dropEffect !== 'move') return;\n      const tidy = smartSpacing && isOneToken(payload.text, prefix, suffix);\n      const { value: next, at } = cutChip(domToValue(el, prefix, suffix), payload.start, payload.end, tidy);\n      const { scrollTop } = el;\n      renderValue(el, next, chipContextRef.current);\n      el.scrollTop = scrollTop;\n      lastSelectionRef.current = { start: at, end: at };\n      commit(next, at, { discrete: true });\n    },\n  };\n\n  // Handlers are attached once and dispatched through this ref, so a re-render\n  // never detaches and re-attaches thirteen listeners. Declared before the\n  // attaching effect so the first commit already has them.\n  useEffect(() => {\n    handlersRef.current = handlers;\n    chipContextRef.current = chipContext;\n  });\n\n  useEffect(() => {\n    const el = editableRef.current;\n    if (!el) return;\n    const listeners = EVENT_TYPES.map((type) => {\n      const listener = (event: Event) => handlersRef.current[type]?.(event as never);\n      el.addEventListener(type, listener);\n      return [type, listener] as const;\n    });\n    return () => listeners.forEach(([type, listener]) => el.removeEventListener(type, listener));\n  }, []);\n\n  // The caret only matters while this field has focus, and a document-scoped\n  // listener fires on every selection change anywhere on the page, so it is\n  // registered for exactly as long as it is useful. It writes to a ref, never\n  // to state: the palette must not re-render on every caret move.\n  useEffect(() => {\n    const el = editableRef.current;\n    if (!el) return;\n    const doc = el.ownerDocument;\n    let attached = false;\n\n    const onSelectionChange = () => {\n      const selection = getSelectionOffsets(el, prefix, suffix);\n      if (selection) lastSelectionRef.current = selection;\n      markSelectedChips(el, selection, prefix, suffix);\n      detectSuggest();\n    };\n    const attach = () => {\n      if (attached) return;\n      attached = true;\n      doc.addEventListener('selectionchange', onSelectionChange);\n    };\n    // Cleared here because the listener is gone: the selectionchange of a click elsewhere comes\n    // after the blur, and would otherwise leave the chips drawn selected.\n    const detach = () => {\n      if (!attached) return;\n      attached = false;\n      doc.removeEventListener('selectionchange', onSelectionChange);\n      markSelectedChips(el, null, prefix, suffix);\n    };\n\n    el.addEventListener('focus', attach);\n    el.addEventListener('blur', detach);\n    if (hasFocusWithin(el)) attach();\n    return () => {\n      el.removeEventListener('focus', attach);\n      el.removeEventListener('blur', detach);\n      detach();\n    };\n  }, [detectSuggest, prefix, suffix]);\n\n  // Controlled resync: only when the incoming value is not the one we just emitted.\n  useLayoutEffect(() => {\n    const el = editableRef.current;\n    if (!el) return;\n    const incoming = String(value ?? '');\n    if (incoming === lastEmittedRef.current) return;\n    if (isComposingRef.current) {\n      pendingResyncRef.current = incoming;\n      return;\n    }\n    const caret = hasFocusWithin(el) ? getCaretOffset(el, prefix, suffix) : null;\n    const { scrollTop } = el;\n    renderValue(el, incoming, chipContextRef.current);\n    el.scrollTop = scrollTop;\n    lastEmittedRef.current = incoming;\n    const clamped = caret === null ? incoming.length : Math.min(caret, incoming.length);\n    // A caret from the old value means nothing in the new one, and an insertion there could land\n    // inside one of its tokens and split it: unfocused, the next one appends instead. Focused, it\n    // is read back from the selection, which has been snapped out of any chip.\n    lastSelectionRef.current = null;\n    if (caret !== null) {\n      setSelectionOffsets(el, clamped, clamped, prefix, suffix);\n      lastSelectionRef.current = getSelectionOffsets(el, prefix, suffix);\n      scrollOffsetIntoView(el, clamped, prefix, suffix);\n    }\n    // A value set from outside starts a new history, as it does in a native\n    // textarea. Keeping the old entries would let undo restore text from before\n    // a form reset, a state the field never held right before this one.\n    historyRef.current = freshHistory(incoming, clamped);\n  }, [prefix, suffix, value]);\n\n  // A layout effect, so a preview toggled under `flushSync` has its chips refreshed by the time\n  // `morphChips` lets the browser capture them.\n  useLayoutEffect(() => {\n    const el = editableRef.current;\n    if (el) refreshChips(el, chipContext);\n  }, [chipContext]);\n\n  // `focus()` alone lands the caret at the start in some engines and at the end\n  // in others, so the position is set explicitly afterwards. Mount only:\n  // refocusing on a later prop change would fight the user.\n  useEffect(() => {\n    const el = editableRef.current;\n    if (!autoFocus || !el || editingBlocked) return;\n    el.focus({ preventScroll: true });\n    const end = domToValue(el, prefix, suffix).length;\n    setSelectionOffsets(el, end, end, prefix, suffix);\n    lastSelectionRef.current = { start: end, end };\n    scrollOffsetIntoView(el, end, prefix, suffix);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n\n  useEffect(() => {\n    if (!apiRef) return;\n    apiRef.current = {\n      insertToken: (tokenId) => {\n        const { start, end } = resolveOffsets();\n        insertTokenAt(tokenId, start, end);\n      },\n      highlightToken: (tokenId) => {\n        editableRef.current\n          ?.querySelectorAll<HTMLElement>('[data-chip]')\n          .forEach((chip) => chip.toggleAttribute('data-highlighted', chip.dataset.token === tokenId));\n      },\n    };\n    return () => {\n      apiRef.current = null;\n    };\n  }, [apiRef, insertTokenAt, resolveOffsets]);\n\n  // Anchor the popup to the run being typed rather than to the collapsed caret:\n  // a collapsed range reports no client rects in most engines, a run always has one.\n  // The menu anchors to its whole button: a zero-width point on the button's right\n  // edge sits on the field's clipping edge, where the popup counts it as scrolled\n  // out of view and never shows.\n  useLayoutEffect(() => {\n    const el = editableRef.current;\n    const anchor = caretAnchorRef.current;\n    const wrapper = wrapperRef.current;\n    if (!isSuggestOpen || !el || !anchor || !wrapper || !suggest) return;\n    const rect = suggest.fromMenu\n      ? (menuButtonRef.current?.getBoundingClientRect() ?? null)\n      : rectOfOffsets(el, suggest.start, suggest.end, prefix, suffix);\n    if (!rect) return;\n    const host = wrapper.getBoundingClientRect();\n    anchor.style.left = `${rect.left - host.left}px`;\n    anchor.style.width = suggest.fromMenu ? `${rect.width}px` : '';\n    anchor.style.top = `${rect.top - host.top}px`;\n    anchor.style.height = `${rect.height || 16}px`;\n  }, [isSuggestOpen, prefix, suffix, suggest]);\n\n  // A layer of its own, so Escape closes the list rather than a Modal or Drawer the field sits in,\n  // whose own Escape handler stands down only for a layer opened above it.\n  useOverlay({\n    isActive: isSuggestOpen,\n    containerRef: popupPanelRef,\n    onEscape: () => {\n      if (!suggest?.fromMenu) dismissedRunRef.current = suggest?.start ?? null;\n      setSuggest(null);\n    },\n    trapFocus: false,\n    lockScroll: false,\n  });\n\n  usePopoverPosition({\n    isOpen: isSuggestOpen,\n    placement: PopoverPlacement.Bottom,\n    align: suggest?.fromMenu ? PopoverAlign.End : PopoverAlign.Start,\n    offset: 0,\n    triggerRef: caretAnchorRef,\n    floatingRef: popupAnchorRef,\n    panelRef: popupPanelRef,\n    arrowRef: noArrowRef,\n  });\n\n  return (\n    <div\n      ref={wrapperRef}\n      className={cx(styles.templateEditorSurface, !multiline && styles.templateEditorSurfaceSingleLine)}\n    >\n      <div\n        {...(editingBlocked ? {} : { contentEditable: true, suppressContentEditableWarning: true })}\n        ref={editableRef}\n        id={id}\n        role='textbox'\n        aria-multiline={multiline}\n        aria-label={ariaLabel}\n        aria-readonly={readOnly || undefined}\n        aria-disabled={disabled || undefined}\n        aria-autocomplete={isSuggestOpen ? 'list' : undefined}\n        aria-controls={isSuggestOpen ? listId : undefined}\n        aria-activedescendant={isSuggestOpen && highlightedId ? optionId(highlightedId) : undefined}\n        tabIndex={disabled ? -1 : tabIndex}\n        spellCheck\n        data-template-editable\n        className={cx(\n          styles.templateEditorEditable,\n          disabled && styles.templateEditorEditableDisabled,\n          className,\n          classNames?.editable,\n        )}\n        // `minHeight` is set inline rather than in the stylesheet because Input's own multiline\n        // rule sets it, and which of two single-class rules wins is a bundling detail.\n        style={{\n          minHeight: multiline ? `calc(${rows} * 1.5em)` : undefined,\n          ...style,\n          ...slotStyles?.editable,\n        }}\n        onFocus={onFocus}\n        onBlur={(event) => {\n          setSuggest(null);\n          onBlur?.(event);\n        }}\n      />\n      {((menuLabel && !editingBlocked) || previewLabel) && (\n        <span className={styles.templateEditorActions}>\n          {previewLabel && (\n            <ActionIcon\n              icon={faEye}\n              styleType={chipContext.preview ? ButtonStyleType.Light : ButtonStyleType.Plain}\n              color={chipContext.preview ? ThemeColor.Primary : 'var(--text-dark)'}\n              aria-label={previewLabel}\n              title={previewLabel}\n              aria-pressed={!!chipContext.preview}\n              className={classNames?.previewButton}\n              style={slotStyles?.previewButton}\n              // Keeps the field's focus and caret, so editing carries on in the preview.\n              onMouseDown={(event) => event.preventDefault()}\n              onClick={() => {\n                const el = editableRef.current;\n                if (el && onTogglePreview) {\n                  morphChips(el, styles.templateEditorChipMorph, () => flushSync(onTogglePreview));\n                }\n              }}\n            />\n          )}\n          {menuLabel && !editingBlocked && (\n            <ActionIcon\n              ref={menuButtonRef}\n              icon={<span aria-hidden='true'>{'{ }'}</span>}\n              color='var(--text-dark)'\n              disabled={!canPick}\n              aria-label={menuLabel}\n              title={menuLabel}\n              aria-haspopup='listbox'\n              aria-expanded={isMenuOpen}\n              aria-controls={isMenuOpen ? listId : undefined}\n              className={classNames?.menuButton}\n              style={slotStyles?.menuButton}\n              // Keeps the field's focus and selection, which is where the pick lands.\n              onMouseDown={(event) => event.preventDefault()}\n              onClick={toggleMenu}\n            />\n          )}\n        </span>\n      )}\n      <span ref={caretAnchorRef} aria-hidden='true' className={styles.templateEditorCaretAnchor} />\n      <span ref={dropCaretRef} aria-hidden='true' className={styles.templateEditorDropCaret} />\n      {isSuggestOpen && (\n        <BodyEnd>\n          <div ref={popupAnchorRef} className={styles.templateEditorSuggestionsAnchor}>\n            <div\n              ref={popupPanelRef}\n              className={cx(styles.templateEditorSuggestions, classNames?.suggestions)}\n              style={slotStyles?.suggestions}\n            >\n              <TemplateEditorSuggestions\n                groups={suggestionGroups}\n                query={suggest?.query ?? ''}\n                highlightedId={highlightedId}\n                listId={listId}\n                optionId={optionId}\n                onSelect={commitSuggestion}\n                classNames={classNames}\n                styles={slotStyles}\n              />\n            </div>\n          </div>\n        </BodyEnd>\n      )}\n    </div>\n  );\n}\n\nexport default TemplateEditable;\n"],"mappings":"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"}