@ai-matrx/design-system 0.86.358 → 0.86.360

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.md +23 -1
  2. package/dist/carousel.cjs +2 -1
  3. package/dist/carousel.cjs.map +1 -1
  4. package/dist/carousel.js +4 -4
  5. package/dist/{chunk-OUQT72UL.js → chunk-C5HYUXR2.js} +2 -2
  6. package/dist/{chunk-K3XWUACX.js → chunk-FF524V6P.js} +2 -2
  7. package/dist/{chunk-TEMAM5ET.js → chunk-HISATFYI.js} +2 -2
  8. package/dist/{chunk-WVEDW5VO.js → chunk-LU75R6YX.js} +3 -2
  9. package/dist/chunk-LU75R6YX.js.map +1 -0
  10. package/dist/{chunk-K5ZQROWN.js → chunk-QK7GPIEA.js} +3 -3
  11. package/dist/{chunk-KSCSH7AO.js → chunk-TSETPQWU.js} +2 -2
  12. package/dist/{chunk-NFJ63LIH.js → chunk-UCEKAKHP.js} +2 -2
  13. package/dist/{chunk-T3FKFPCW.js → chunk-WHERV3VC.js} +2 -2
  14. package/dist/{chunk-QTPW44IJ.js → chunk-WOA6WHV2.js} +2 -2
  15. package/dist/{chunk-P56Y43RL.js → chunk-ZU2ZODDD.js} +4 -4
  16. package/dist/clipboard-fallback-dialog.cjs +2 -1
  17. package/dist/clipboard-fallback-dialog.cjs.map +1 -1
  18. package/dist/clipboard-fallback-dialog.js +1 -1
  19. package/dist/controls.cjs +2 -1
  20. package/dist/controls.cjs.map +1 -1
  21. package/dist/controls.css +18 -1
  22. package/dist/controls.d.cts +5 -0
  23. package/dist/controls.d.ts +5 -0
  24. package/dist/controls.js +4 -4
  25. package/dist/data-table/data-row-inspector.cjs +2 -1
  26. package/dist/data-table/data-row-inspector.cjs.map +1 -1
  27. package/dist/data-table/data-row-inspector.js +4 -4
  28. package/dist/data-table/data-row-window.cjs +2 -1
  29. package/dist/data-table/data-row-window.cjs.map +1 -1
  30. package/dist/data-table/data-row-window.js +5 -5
  31. package/dist/data-table/index.cjs +2 -1
  32. package/dist/data-table/index.cjs.map +1 -1
  33. package/dist/data-table/index.js +7 -7
  34. package/dist/data-table/pagination.cjs +2 -1
  35. package/dist/data-table/pagination.cjs.map +1 -1
  36. package/dist/data-table/pagination.js +2 -2
  37. package/dist/data-table/uuid-cell.cjs +2 -1
  38. package/dist/data-table/uuid-cell.cjs.map +1 -1
  39. package/dist/data-table/uuid-cell.js +2 -2
  40. package/dist/desktop.cjs +3 -2
  41. package/dist/desktop.cjs.map +1 -1
  42. package/dist/desktop.d.cts +1 -1
  43. package/dist/desktop.d.ts +1 -1
  44. package/dist/desktop.js +4 -4
  45. package/dist/desktop.js.map +1 -1
  46. package/dist/index.cjs +2 -1
  47. package/dist/index.cjs.map +1 -1
  48. package/dist/index.d.cts +9 -9
  49. package/dist/index.d.ts +9 -9
  50. package/dist/index.js +6 -6
  51. package/dist/item.cjs +2 -1
  52. package/dist/item.cjs.map +1 -1
  53. package/dist/item.js +2 -2
  54. package/dist/lite-table.cjs +2 -1
  55. package/dist/lite-table.cjs.map +1 -1
  56. package/dist/lite-table.js +1 -1
  57. package/dist/look-desktop.css +7 -0
  58. package/dist/record-list.cjs +2 -1
  59. package/dist/record-list.cjs.map +1 -1
  60. package/dist/record-list.js +2 -2
  61. package/dist/settings.cjs +2 -1
  62. package/dist/settings.cjs.map +1 -1
  63. package/dist/settings.js +2 -2
  64. package/dist/swipe-deck.cjs +11 -2
  65. package/dist/swipe-deck.cjs.map +1 -1
  66. package/dist/swipe-deck.js +11 -2
  67. package/dist/swipe-deck.js.map +1 -1
  68. package/dist/writing-field.cjs +7 -1
  69. package/dist/writing-field.cjs.map +1 -1
  70. package/dist/writing-field.d.cts +4 -0
  71. package/dist/writing-field.d.ts +4 -0
  72. package/dist/writing-field.js +7 -2
  73. package/dist/writing-field.js.map +1 -1
  74. package/package.json +2 -2
  75. package/dist/chunk-WVEDW5VO.js.map +0 -1
  76. /package/dist/{chunk-OUQT72UL.js.map → chunk-C5HYUXR2.js.map} +0 -0
  77. /package/dist/{chunk-K3XWUACX.js.map → chunk-FF524V6P.js.map} +0 -0
  78. /package/dist/{chunk-TEMAM5ET.js.map → chunk-HISATFYI.js.map} +0 -0
  79. /package/dist/{chunk-K5ZQROWN.js.map → chunk-QK7GPIEA.js.map} +0 -0
  80. /package/dist/{chunk-KSCSH7AO.js.map → chunk-TSETPQWU.js.map} +0 -0
  81. /package/dist/{chunk-NFJ63LIH.js.map → chunk-UCEKAKHP.js.map} +0 -0
  82. /package/dist/{chunk-T3FKFPCW.js.map → chunk-WHERV3VC.js.map} +0 -0
  83. /package/dist/{chunk-QTPW44IJ.js.map → chunk-WOA6WHV2.js.map} +0 -0
  84. /package/dist/{chunk-P56Y43RL.js.map → chunk-ZU2ZODDD.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/writing-field/pro-textarea.tsx","../src/writing-field/control-fit.ts","../src/writing-field/control-placement.ts","../src/writing-field/add-ons.tsx","../src/writing-field/voice-chrome.tsx","../src/writing-field/pro-input.tsx","../src/writing-field/reserved-padding.ts"],"sourcesContent":["\"use client\";\n\n/**\n * ProTextarea — THE box a person writes words in (one-ui-system rule 6). Moved from\n * matrx-frontend `components/official/ProTextarea.tsx` (2026-10-22): the field core lives here; the\n * recorder, the \"…\" actions, the page's agents, the right-click menu, markdown formatting and text\n * stats arrive through the add-on ports (`./add-ons.tsx`), registered once at the host root.\n *\n * Built in: auto-grow (`autoGrow` + `minHeight`/`maxHeight`), floating label, `hero` appearance,\n * the reserved control row or the `inline` composer shape (`controls`), the ONE fitting rule\n * (`./control-fit.ts`: whatever does not fit beside the text folds into \"…\", never deleted), submit\n * (`onSubmit`, ⌘/Ctrl+Enter, `submitOnEnter`, the one composer rule from `@ai-matrx/kit/composer-keys`),\n * field navigation (`onEnterKey`), a `leading` slot, Expand (`expandable`), a hosted editor\n * (`editor`, `./editor-slot.ts`), the pre-hydration keep, and the dictation handle: the forwarded\n * node is a real `HTMLTextAreaElement` carrying `startDictation()` / `stopDictation()` /\n * `isDictating()` / `requestClose()` / `isTranscribing()`; a refusal always returns a named reason\n * with a sentence AND says it on screen (notify + `onTranscriptionError`).\n */\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { composerKeyIntent, intentTakesTheKey } from \"@ai-matrx/kit/composer-keys\";\nimport { useMediaQuery } from \"@ai-matrx/kit/media-query\";\nimport { copyText } from \"@ai-matrx/kit/clipboard\";\nimport { cn } from \"../cn\";\nimport { Label } from \"../label\";\nimport { Dialog, DialogContent, DialogTitle } from \"../dialog\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../popover\";\nimport { TapTargetButtonSolid } from \"../tap-target/tap-target-button\";\nimport { MaximizeTapButton, MoreHorizontalTapButton } from \"../tap-target/tap-buttons\";\nimport { CopyIcon, Loader2Icon, Maximize2Icon, MicIcon, SendIcon, SlidersHorizontalIcon } from \"../icons\";\nimport { UNCONFIGURED } from \"../stand-in-notice\";\nimport { DENSE_SIZES, controlSizes, fitFieldControls } from \"./control-fit\";\nimport {\n INLINE_CONTROLS_MIN_HEIGHT_PX,\n TAP_HALF_GAP_PX,\n inlineControlsFieldPadding,\n proTextareaClusterPlacement,\n type ProTextareaControls,\n} from \"./control-placement\";\nimport type { ProTextareaEditorSlot } from \"./editor-slot\";\nimport {\n announceMissingPort,\n resolveHookPorts,\n splitAddOnProps,\n useWritingFieldAddOns,\n type WritingFieldApi,\n} from \"./add-ons\";\nimport { FieldMenuRow, FinalizingStrip, ListeningStrip, VoiceProtectionDialog, micAriaLabel } from \"./voice-chrome\";\nimport type { ProTextareaAddOnProps } from \"./index\";\nimport { Textarea } from \"../controls/controls\";\n\nconst FILL_HEIGHT_REGEX = /(?:^|\\s)(h-full|h-dvh|flex-1|grow|inset-0|min-h-0)(?:\\s|$)/;\n\n/** Detect when the caller wants the field to stretch to its container. */\nfunction wantsFillHeight(className?: string, wrapperClassName?: string): boolean {\n return FILL_HEIGHT_REGEX.test(className ?? \"\") || FILL_HEIGHT_REGEX.test(wrapperClassName ?? \"\");\n}\n\n/** Why `startDictation()` refused. Every value is a real, nameable condition. */\nexport type DictationRefusalReason =\n | \"voice-disabled\"\n | \"field-disabled\"\n | \"no-microphone\"\n | \"recorder-unavailable\"\n | \"finalizing\";\n\nexport type DictationStartResult =\n | { started: true }\n | { started: false; reason: DictationRefusalReason; message: string };\n\n/**\n * Real HTMLTextAreaElement with the expandos ProTextarea sets one commit after mount (always call\n * them with `?.()`). Expandos, not `useImperativeHandle`: hundreds of hosts forward this ref\n * expecting a genuine element (`focus()`, `select()`, `selectionStart`, form association).\n */\nexport interface ProTextareaElement extends HTMLTextAreaElement {\n requestClose?: () => void;\n isTranscribing?: () => boolean;\n startDictation?: () => Promise<DictationStartResult>;\n stopDictation?: () => void;\n isDictating?: () => boolean;\n}\n\nexport interface ProTextareaProps\n extends React.TextareaHTMLAttributes<HTMLTextAreaElement>,\n ProTextareaAddOnProps {\n onTranscriptionComplete?: (text: string) => void;\n onTranscriptionError?: (error: string) => void;\n /** If true, appends to existing text; if false, replaces. Default: true. */\n appendTranscript?: boolean;\n /** Voice input. ON by default; `false` when the host owns recording itself. */\n enableVoice?: boolean;\n autoGrow?: boolean;\n minHeight?: number;\n maxHeight?: number;\n wrapperClassName?: string;\n /** Called when it's safe to close/unmount (after confirm or once recording/transcription completes). */\n onRequestClose?: () => void;\n /** Warn before unmount during recording/transcription. Default: true. */\n protectTranscription?: boolean;\n /** Copy rows in \"…\". Default: true. */\n showCopyButton?: boolean;\n /** Text stats in \"…\" + the pinned stats bar. OFF by default. */\n enableTextStats?: boolean;\n /** Initial pinned stats bar display when text stats are enabled. Default: true. */\n defaultShowTextStatsBar?: boolean;\n onSubmit?: () => void;\n submitDisabled?: boolean;\n allowEmptySubmit?: boolean;\n isSubmitting?: boolean;\n /** Accessible/tooltip label for the submit button. Default: \"Send\". */\n submitLabel?: string;\n /** The submit button's VISIBLE word (\"Build agent\"): a labeled solid pill instead of the send glyph. */\n submitText?: string;\n submitIcon?: React.ReactNode;\n submitOnCmdEnter?: boolean;\n submitOnEnter?: boolean;\n /** Field-navigation mode: plain Enter calls this; Shift+Enter / ⌘+Enter insert a newline. */\n onEnterKey?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;\n auxiliaryControlsTabIndex?: number;\n auxiliaryControlsLabel?: string;\n /** Dense-form label inside the border (use only on a `bg-card` surface). */\n floatingLabel?: string;\n /** Markdown chords + selection toolbar. Default: on for a long-form box. */\n markdownFormatting?: boolean;\n /** Draw the mic + \"…\" cluster inside this element; `\"none\"`: the host already carries them. */\n controlsHost?: HTMLElement | null | \"none\";\n /** Host a different editor in place of the <textarea> (`./editor-slot.ts`). */\n editor?: ProTextareaEditorSlot;\n /** Expand button (in the control row) that opens the same field large. Off by default. */\n expandable?: boolean;\n /** `\"row\"` (default): a reserved row under the text. `\"inline\"`: the chat-composer shape. */\n controls?: ProTextareaControls;\n /** `field` (default) or `hero` (a front door's one big composer). */\n appearance?: \"field\" | \"hero\";\n /** Content at the START of the reserved control row. */\n leading?: React.ReactNode;\n /** `all` (default): \"…\" carries the shared action registry. `none`: only the field's own controls. */\n menuActions?: \"all\" | \"none\";\n}\n\nexport const ProTextarea = React.forwardRef<HTMLTextAreaElement, ProTextareaProps>(\n (\n {\n className,\n wrapperClassName,\n onTranscriptionComplete,\n onTranscriptionError,\n appendTranscript = true,\n menuActions = \"all\",\n enableVoice = true,\n autoGrow = false,\n minHeight,\n maxHeight,\n value,\n onChange,\n onKeyDown,\n disabled,\n onRequestClose,\n protectTranscription = true,\n showCopyButton = true,\n enableTextStats = false,\n defaultShowTextStatsBar = true,\n onSubmit,\n submitDisabled,\n allowEmptySubmit = false,\n isSubmitting = false,\n submitLabel = \"Send\",\n submitText,\n submitIcon,\n submitOnCmdEnter,\n submitOnEnter = false,\n onEnterKey,\n auxiliaryControlsTabIndex,\n auxiliaryControlsLabel,\n floatingLabel,\n id: idProp,\n placeholder,\n style,\n editor,\n markdownFormatting,\n expandable = false,\n controls,\n controlsHost,\n appearance = \"field\",\n leading,\n ...rest\n },\n ref,\n ) => {\n const addOns = useWritingFieldAddOns();\n const ports = resolveHookPorts(addOns);\n const { dom: props, addOnProps } = splitAddOnProps(\n rest as Record<string, unknown>,\n addOns.propNames,\n ) as { dom: React.TextareaHTMLAttributes<HTMLTextAreaElement>; addOnProps: Record<string, unknown> };\n const notify = ports.notify;\n\n // A one-row box takes the inline controls on its own; an explicit `controls` still wins.\n const resolvedControls: ProTextareaControls =\n controls ?? (props.rows !== undefined && Number(props.rows) <= 1 ? \"inline\" : \"row\");\n const inlineControls = resolvedControls === \"inline\" && !editor;\n const [smallType, setSmallType] = React.useState(false);\n const denseInline = inlineControls && smallType;\n const inlineMinHeight = denseInline ? DENSE_SIZES.box + 2 * TAP_HALF_GAP_PX : INLINE_CONTROLS_MIN_HEIGHT_PX;\n const effectiveMinHeight = inlineControls ? Math.max(minHeight ?? 0, inlineMinHeight) : minHeight;\n // Both measured boxes are watched through CALLBACK refs: the field subtree can mount again (the\n // right-click wrapper wraps it once it loads).\n const clusterRef = React.useRef<HTMLDivElement | null>(null);\n const [clusterWidth, setClusterWidth] = React.useState(0);\n const clusterObserver = React.useRef<ResizeObserver | null>(null);\n // Stable, so React re-runs it only when the node changes (a new function each render re-measured in\n // every commit, which loops when the measured size moves with the field's own controls).\n const setClusterNode = React.useCallback((node: HTMLDivElement | null) => {\n if (clusterRef.current === node) return;\n clusterRef.current = node;\n clusterObserver.current?.disconnect();\n clusterObserver.current = null;\n if (!node || typeof ResizeObserver === \"undefined\") return;\n const measure = () => setClusterWidth(node.offsetWidth);\n measure();\n clusterObserver.current = new ResizeObserver(measure);\n clusterObserver.current.observe(node);\n }, []);\n const fieldBoxRef = React.useRef<HTMLDivElement | null>(null);\n const [fieldBoxWidth, setFieldBoxWidth] = React.useState(0);\n const fieldBoxObserver = React.useRef<ResizeObserver | null>(null);\n // Stable, so React re-runs it only when the node changes (a new function each render re-measured in\n // every commit, which loops when the measured size moves with the field's own controls).\n const setFieldBoxNode = React.useCallback((node: HTMLDivElement | null) => {\n if (fieldBoxRef.current === node) return;\n fieldBoxRef.current = node;\n fieldBoxObserver.current?.disconnect();\n fieldBoxObserver.current = null;\n if (!node || typeof ResizeObserver === \"undefined\") return;\n const measure = () => {\n setFieldBoxWidth(node.offsetWidth);\n const field = node.querySelector(\"textarea\");\n if (field) setSmallType(Number.parseFloat(getComputedStyle(field).fontSize) < 14);\n };\n measure();\n fieldBoxObserver.current = new ResizeObserver(measure);\n fieldBoxObserver.current.observe(node);\n }, []);\n React.useEffect(\n () => () => {\n clusterObserver.current?.disconnect();\n fieldBoxObserver.current?.disconnect();\n },\n [],\n );\n const coarsePointer = useMediaQuery(\"(pointer: coarse)\");\n const openAudioSettings = ports.useOpenAudioSettings();\n const generatedId = React.useId();\n const inputId = idProp ?? (floatingLabel ? generatedId : undefined);\n const [isFocused, setIsFocused] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n const [expandOpen, setExpandOpen] = React.useState(false);\n const [overflowing, setOverflowing] = React.useState(false);\n const [menuOpen, setMenuOpen] = React.useState(false);\n const [statsOpen, setStatsOpen] = React.useState(false);\n const [showTextStatsBar, setShowTextStatsBar] = React.useState(defaultShowTextStatsBar);\n // The element ref is ALWAYS our own, merged into the host's forwarded ref (a CALLBACK ref left\n // `.current` undefined and every internal feature returned silently — RC-B6).\n const internalRef = React.useRef<HTMLTextAreaElement | null>(null);\n const textareaRef = internalRef;\n const setTextareaRef = (node: HTMLTextAreaElement | null) => {\n internalRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) (ref as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;\n };\n\n // Markdown formatting for a long-form box (the element mirrored into state once per mount).\n const formattingOn =\n markdownFormatting ??\n (!editor && !submitOnEnter && (props.rows === undefined || Number(props.rows) >= 2));\n const [formatElement, setFormatElement] = React.useState<HTMLTextAreaElement | null>(null);\n React.useLayoutEffect(() => {\n if (internalRef.current !== formatElement) setFormatElement(internalRef.current);\n });\n ports.useFormatting(formatElement, formattingOn, addOnProps);\n\n // Auto-grow: scrollHeight excludes the border; add it so the last line never hides.\n React.useEffect(() => {\n if (!autoGrow || !textareaRef.current) return;\n const textarea = textareaRef.current;\n textarea.style.height = \"auto\";\n let newHeight = textarea.scrollHeight + (textarea.offsetHeight - textarea.clientHeight);\n if (effectiveMinHeight) newHeight = Math.max(newHeight, effectiveMinHeight);\n if (maxHeight) newHeight = Math.min(newHeight, maxHeight);\n textarea.style.height = `${newHeight}px`;\n }, [value, autoGrow, effectiveMinHeight, maxHeight, clusterWidth]);\n\n /** Write through React's own change path; true when the field now holds `newValue`. */\n const pushToTextarea = React.useCallback(\n (newValue: string): boolean => {\n if (editor) return editor.handle.current?.write(newValue) ?? false;\n const el = textareaRef.current;\n if (!el) return false;\n const setter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, \"value\")?.set;\n if (!setter) return false;\n setter.call(el, newValue);\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n return el.value === newValue;\n },\n [editor],\n );\n\n // THE PRE-HYDRATION KEEP: text typed into a server-rendered box before hydration is handed to\n // the host through its own onChange (lane P, 2026-10-07).\n const keepPreHydrationText = React.useEffectEvent(() => {\n const el = internalRef.current;\n if (editor || !el || !onChange) return;\n const typed = el.value;\n if (!typed || typed === String(value ?? \"\")) return;\n el.value = \"\";\n pushToTextarea(typed);\n });\n React.useLayoutEffect(() => {\n keepPreHydrationText();\n }, []);\n\n const getLiveText = React.useCallback(\n () =>\n editor\n ? (editor.handle.current?.getValue() ?? String(value ?? \"\"))\n : (textareaRef.current?.value ?? String(value ?? \"\")),\n [editor, value],\n );\n\n // Voice rides the host's ONE recorder through the voice port.\n const voice = ports.useVoice({\n enabled: enableVoice,\n instanceId: inputId,\n label: typeof floatingLabel === \"string\" ? floatingLabel : undefined,\n getValue: getLiveText,\n writeValue: pushToTextarea,\n appendTranscript,\n protect: protectTranscription,\n onRequestClose,\n onTranscriptionComplete,\n onTranscriptionError,\n });\n const { isRecording, isTranscribing } = voice;\n const isAudioAvailable = voice.microphone;\n\n const refuseDictation = React.useCallback(\n (reason: DictationRefusalReason, message: string): DictationStartResult => {\n notify.error(message);\n onTranscriptionError?.(message);\n return { started: false, reason, message };\n },\n [notify, onTranscriptionError],\n );\n\n /** The imperative half of the mic button: the same checks, then the same start. */\n const startDictation = React.useCallback(async (): Promise<DictationStartResult> => {\n if (!enableVoice)\n return refuseDictation(\"voice-disabled\", \"Voice input is turned off for this field, so it cannot start dictating.\");\n if (disabled) return refuseDictation(\"field-disabled\", \"This field is disabled, so it cannot start dictating.\");\n if (!isAudioAvailable)\n return refuseDictation(\"no-microphone\", \"No microphone is available in this browser, so dictation cannot start.\");\n if (!voice.available)\n return refuseDictation(\n \"recorder-unavailable\",\n \"Voice recording is unavailable on this screen, so dictation cannot start.\",\n );\n if (isTranscribing && !isRecording)\n return refuseDictation(\n \"finalizing\",\n \"The last recording is still being transcribed. Wait for it to finish, then start again.\",\n );\n await voice.startDictation();\n return { started: true };\n }, [enableVoice, disabled, isAudioAvailable, voice, isTranscribing, isRecording, refuseDictation]);\n\n React.useEffect(() => {\n const el = textareaRef.current as ProTextareaElement | null;\n if (!el) return;\n el.requestClose = voice.requestClose;\n el.isTranscribing = () => isTranscribing;\n el.startDictation = startDictation;\n el.stopDictation = voice.stopDictation;\n el.isDictating = () => isRecording;\n }, [voice.requestClose, isTranscribing, startDictation, voice.stopDictation, isRecording]);\n\n const valueAsString = String(value ?? \"\");\n const hasContent = valueAsString.trim().length > 0;\n const canSubmit = !!onSubmit && (hasContent || allowEmptySubmit) && !submitDisabled && !isSubmitting && !disabled;\n const cmdEnterEnabled = submitOnCmdEnter ?? !!onSubmit;\n const triggerSubmit = React.useCallback(() => {\n if (canSubmit && onSubmit) onSubmit();\n }, [canSubmit, onSubmit]);\n\n const insertNewlineAtCursor = React.useCallback(() => {\n const el = textareaRef.current;\n if (!el) return;\n const start = el.selectionStart ?? el.value.length;\n const end = el.selectionEnd ?? el.value.length;\n pushToTextarea(el.value.slice(0, start) + \"\\n\" + el.value.slice(end));\n const caret = start + 1;\n requestAnimationFrame(() => {\n const node = textareaRef.current;\n if (!node) return;\n node.selectionStart = caret;\n node.selectionEnd = caret;\n });\n }, [pushToTextarea]);\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n // Typing hides the hover controls until the mouse moves again (like the OS cursor).\n if (isHovered) setIsHovered(false);\n onKeyDown?.(e);\n if (e.defaultPrevented || e.key !== \"Enter\") return;\n const withCmd = e.metaKey || e.ctrlKey;\n if (onEnterKey) {\n if (e.shiftKey) return;\n e.preventDefault();\n if (withCmd) insertNewlineAtCursor();\n else onEnterKey(e);\n return;\n }\n if (!onSubmit) return;\n if (cmdEnterEnabled && withCmd) {\n e.preventDefault();\n triggerSubmit();\n return;\n }\n const intent = composerKeyIntent(\n {\n key: e.key,\n shiftKey: e.shiftKey,\n metaKey: e.metaKey,\n ctrlKey: e.ctrlKey,\n isComposing: e.nativeEvent.isComposing,\n },\n { submitOnEnter },\n );\n if (!intentTakesTheKey(intent)) return;\n e.preventDefault();\n triggerSubmit();\n },\n [isHovered, onKeyDown, onEnterKey, insertNewlineAtCursor, onSubmit, cmdEnterEnabled, submitOnEnter, triggerSubmit],\n );\n\n const fieldApi: WritingFieldApi = {\n kind: \"textarea\",\n text: valueAsString,\n getText: getLiveText,\n write: pushToTextarea,\n getSelection: () => {\n const handle = editor?.handle.current ?? null;\n if (handle) return handle.getSelection();\n const el = textareaRef.current;\n return { start: el?.selectionStart ?? 0, end: el?.selectionEnd ?? 0 };\n },\n getElement: () => textareaRef.current,\n addOnProps,\n showCopyButton,\n flashCopied: () => undefined,\n };\n\n const showControls =\n (appearance === \"hero\" ||\n (typeof HTMLElement !== \"undefined\" && controlsHost instanceof HTMLElement) ||\n isHovered ||\n isFocused ||\n isRecording ||\n isTranscribing) &&\n !disabled;\n const isVoiceDisabled = !isAudioAvailable || disabled || (isTranscribing && !isRecording);\n\n const addOnMenuItems = addOns.Menu\n ? (addOns.menuHasItems?.({ kind: \"textarea\", addOnProps, showCopyButton }) ?? true)\n : false;\n // The menu's OWN actions; \"…\" also shows to hold whatever did not fit.\n const showMenu = !disabled && menuActions !== \"none\" && (showCopyButton || addOnMenuItems);\n // THE ONE FITTING RULE (./control-fit.ts), shared with ProInput.\n const micOffered = enableVoice && isAudioAvailable;\n const fit = fitFieldControls({\n fieldWidth: fieldBoxWidth,\n sizes: controlSizes({ coarse: coarsePointer, dense: denseInline }),\n fixedPx: inlineControls ? 12 + 2 * TAP_HALF_GAP_PX : 8,\n minText: inlineControls ? undefined : 0,\n hasSubmit: !!onSubmit,\n menuHasOwnItems: showMenu,\n mic: micOffered,\n clear: false,\n expand: expandable && !editor && overflowing,\n });\n const voiceBusyNow = isRecording || isTranscribing;\n const micInline = micOffered && (fit.mic === \"inline\" || voiceBusyNow);\n const voiceInMenu = micOffered && !micInline;\n const expandInMenu = fit.folded.includes(\"expand\");\n const menuShown =\n !disabled && (showMenu || voiceInMenu || expandInMenu || (menuActions === \"none\" && enableVoice));\n const audioSettingsInMenu = menuShown && enableVoice;\n const hasCoarseControls = (enableVoice && isAudioAvailable && !disabled) || showMenu;\n const Stats = addOns.TextStats;\n const showTextStats = enableTextStats && showMenu && !!Stats;\n React.useEffect(() => {\n if (enableTextStats && !addOns.TextStats) announceMissingPort(\"TextStats\");\n }, [enableTextStats, addOns.TextStats]);\n const showPinnedTextStatsBar = showTextStats && showTextStatsBar;\n // An auto-growing box sizes itself to its text, so it never fills its host's height.\n const fillHeight = !autoGrow && wantsFillHeight(className, wrapperClassName);\n\n React.useEffect(() => {\n if (!expandable || editor) return;\n const el = internalRef.current;\n if (!el) return;\n const measure = () => setOverflowing(el.scrollHeight > el.clientHeight + 2);\n measure();\n const observer = new ResizeObserver(measure);\n observer.observe(el);\n return () => observer.disconnect();\n }, [expandable, editor, value]);\n\n const isInvalid = props[\"aria-invalid\"] === true || props[\"aria-invalid\"] === \"true\";\n const labelFloated = isFocused || valueAsString.length > 0;\n\n const hero = appearance === \"hero\";\n const fieldClassName = cn(\n hero\n ? \"flex w-full border border-border bg-card px-5 pt-4 pb-3 text-base leading-7 text-foreground placeholder:text-muted-foreground shadow-[0_1px_2px_rgb(0_0_0/0.05),0_12px_32px_-12px_rgb(0_0_0/0.22)] transition-[border-color,box-shadow] duration-200\"\n : \"flex w-full border border-border bg-card px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground\",\n showPinnedTextStatsBar\n ? hero\n ? \"rounded-2xl sm:rounded-b-none sm:border-b-0\"\n : \"rounded-md sm:rounded-b-none sm:border-b-0\"\n : hero\n ? \"rounded-2xl\"\n : \"rounded-md\",\n // THE FIELD FOCUS (Arman 2026-10-21): border takes the ring + the one halo token.\n \"focus-visible:outline-none focus-visible:border-primary focus-visible:ring-[3px] focus-visible:ring-primary/15\",\n \"disabled:cursor-not-allowed disabled:text-disabled-foreground\",\n fillHeight ? \"min-h-0 flex-1 resize-none overflow-y-auto\" : \"resize-y\",\n autoGrow && \"resize-none overflow-y-auto\",\n hero ? \"pr-5\" : \"pr-3\",\n className,\n // AFTER the caller's className: the reserved control row always wins (a floor, never a ceiling).\n !inlineControls &&\n !controlsHost &&\n (hasCoarseControls || onSubmit) &&\n (editor?.singleLine && !onSubmit\n ? \"pr-24 pointer-coarse:pr-32\"\n : hero\n ? \"pb-[max(3.5rem,var(--matrx-textarea-end,0px))]\"\n : \"pb-[max(2.75rem,var(--matrx-textarea-end,0px))]\"),\n );\n const reservesRow = !inlineControls && !controlsHost && (hasCoarseControls || !!onSubmit) && !editor?.singleLine;\n const fieldStyle: React.CSSProperties = {\n ...style,\n minHeight: effectiveMinHeight !== undefined ? `${effectiveMinHeight}px` : style?.minHeight,\n maxHeight: maxHeight !== undefined ? `${maxHeight}px` : style?.maxHeight,\n ...(inlineControls ? inlineControlsFieldPadding(clusterWidth, inlineMinHeight) : {}),\n };\n\n const closeMenu = () => setMenuOpen(false);\n const ownRows =\n expandInMenu || voiceInMenu || audioSettingsInMenu ? (\n <>\n {expandInMenu ? (\n <FieldMenuRow\n icon={<Maximize2Icon />}\n onClick={() => {\n closeMenu();\n setExpandOpen(true);\n }}\n >\n Expand\n </FieldMenuRow>\n ) : null}\n {voiceInMenu ? (\n <FieldMenuRow\n icon={<MicIcon />}\n disabled={isVoiceDisabled}\n onClick={() => {\n closeMenu();\n void voice.handleVoiceClick();\n }}\n >\n Voice input\n </FieldMenuRow>\n ) : null}\n {audioSettingsInMenu ? (\n <FieldMenuRow\n icon={<SlidersHorizontalIcon />}\n onClick={() => {\n closeMenu();\n openAudioSettings();\n }}\n >\n Audio settings\n </FieldMenuRow>\n ) : null}\n {showMenu ? <div className=\"my-1 h-px bg-border\" role=\"separator\" /> : null}\n </>\n ) : null;\n const trailingRows =\n showTextStats && Stats ? (\n <>\n <div className=\"my-1 h-px bg-border\" role=\"separator\" />\n <Stats.MenuItems\n showStatsBar={showTextStatsBar}\n onToggleStatsBar={() => setShowTextStatsBar((prev) => !prev)}\n onOpenStatsPanel={() => setStatsOpen(true)}\n />\n </>\n ) : null;\n const Menu = addOns.Menu;\n const menuBody =\n statsOpen && Stats ? (\n <div className=\"w-56\">\n <Stats.Panel text={valueAsString} onBack={() => setStatsOpen(false)} onClose={closeMenu} />\n </div>\n ) : Menu && menuActions !== \"none\" ? (\n <Menu field={fieldApi} ownRows={ownRows} trailingRows={trailingRows} close={closeMenu} />\n ) : (\n <StandInMenu field={fieldApi} ownRows={ownRows} trailingRows={trailingRows} close={closeMenu} registry={menuActions !== \"none\"} />\n );\n\n const cluster = (\n <div\n ref={setClusterNode}\n onMouseDown={(e) => e.preventDefault()}\n data-matrx-tap-dense={denseInline ? \"\" : undefined}\n className={\n controlsHost\n ? \"flex items-center\"\n : cn(\n \"absolute z-10 flex items-center\",\n hero && !inlineControls\n ? \"bottom-2 right-2\"\n : proTextareaClusterPlacement(!!onSubmit, inlineControls ? \"inline\" : \"row\").className,\n editor?.singleLine && \"top-1/2 bottom-auto -translate-y-1/2\",\n )\n }\n >\n {fit.expandInline ? (\n <MaximizeTapButton\n tabIndex={auxiliaryControlsTabIndex}\n variant=\"transparent\"\n ariaLabel={auxiliaryControlsLabel ? `Expand ${auxiliaryControlsLabel}` : \"Expand\"}\n tooltip=\"Expand\"\n onClick={() => setExpandOpen(true)}\n className=\"text-muted-foreground\"\n />\n ) : null}\n {/* A GLASS PLANE (tap-target placement rule 1): it rides over the field's own text. */}\n <div\n data-matrx-glass-plane\n className={cn(\n \"flex items-center transition-opacity duration-200 focus-within:opacity-100 focus-within:pointer-events-auto\",\n \"pointer-coarse:opacity-100 pointer-coarse:pointer-events-auto\",\n showControls || menuOpen ? \"opacity-100\" : \"opacity-0 pointer-events-none\",\n )}\n >\n {micInline && addOns.MicButton ? (\n <addOns.MicButton\n tabIndex={auxiliaryControlsTabIndex}\n onMicClick={() => void voice.handleVoiceClick()}\n dense={denseInline}\n disabled={isVoiceDisabled}\n isRecording={isRecording}\n isTranscribing={isTranscribing}\n audioLevel={voice.audioLevel}\n micAriaLabel={micAriaLabel(isRecording, auxiliaryControlsLabel)}\n />\n ) : null}\n {menuShown && (\n <Popover\n open={menuOpen}\n onOpenChange={(open) => {\n setMenuOpen(open);\n if (!open) setStatsOpen(false);\n }}\n >\n <PopoverTrigger asChild>\n <MoreHorizontalTapButton\n tabIndex={auxiliaryControlsTabIndex}\n variant=\"transparent\"\n ariaLabel={auxiliaryControlsLabel ? `More options for ${auxiliaryControlsLabel}` : \"More options\"}\n tooltip=\"More\"\n className=\"text-muted-foreground\"\n />\n </PopoverTrigger>\n <PopoverContent\n /* sizing: fixed — the add-on body sizes itself (list, stats, agent panels) */\n align=\"end\"\n side=\"bottom\"\n sideOffset={6}\n className=\"w-auto max-w-none p-0\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n {menuBody}\n </PopoverContent>\n </Popover>\n )}\n </div>\n {onSubmit && (\n <TapTargetButtonSolid\n onClick={triggerSubmit}\n disabled={!canSubmit}\n ariaLabel={submitLabel}\n tooltip={submitLabel}\n label={submitText}\n icon={\n isSubmitting ? (\n <Loader2Icon className=\"h-4 w-4 animate-spin\" />\n ) : (\n (submitIcon ?? <SendIcon className=\"h-4 w-4\" />)\n )\n }\n />\n )}\n </div>\n );\n\n const field = (\n <div\n ref={setFieldBoxNode}\n className={cn(\"relative group\", wrapperClassName)}\n data-writing-field-host={addOns.Menu && addOns.useVoice ? undefined : UNCONFIGURED}\n onMouseEnter={() => setIsHovered(true)}\n onMouseMove={() => {\n if (!isHovered) setIsHovered(true);\n }}\n onMouseLeave={() => setIsHovered(false)}\n >\n <div className={cn(\"flex min-h-0 min-w-0 w-full flex-col\", fillHeight ? \"h-full flex-1\" : \"flex-1\")}>\n <div className={cn(\"relative min-w-0 w-full\", fillHeight && \"flex min-h-0 flex-1 flex-col\")}>\n {editor ? (\n editor.render({\n id: inputId,\n className: fieldClassName,\n style: fieldStyle,\n placeholder: floatingLabel ? undefined : placeholder,\n disabled,\n onFocus: () => setIsFocused(true),\n onBlur: () => setIsFocused(false),\n onKeyDown: () => {\n if (isHovered) setIsHovered(false);\n },\n })\n ) : (\n <Textarea\n hero={hero}\n joinedBottom={showPinnedTextStatsBar}\n ref={setTextareaRef}\n id={inputId}\n placeholder={floatingLabel ? undefined : placeholder}\n className={cn(\"w-full\", fillHeight ? \"min-h-0 flex-1 resize-none overflow-y-auto\" : \"resize-y\", autoGrow && \"resize-none overflow-y-auto\", className)}\n reservedInlineEnd={inlineControls ? clusterWidth + 6 : 0}\n reservedBlockEnd={reservesRow ? hero ? 56 : 44 : 0}\n style={fieldStyle}\n value={value}\n onChange={onChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n {...props}\n />\n )}\n\n {expandable && !editor ? (\n <Dialog open={expandOpen} onOpenChange={setExpandOpen}>\n <DialogContent className=\"flex max-h-[90dvh] w-[min(56rem,calc(100vw-2rem))] max-w-none flex-col gap-3 sm:max-w-none\">\n <DialogTitle className=\"truncate\">{auxiliaryControlsLabel ?? floatingLabel ?? \"Text\"}</DialogTitle>\n {/* The SAME field, large: one value, one onChange. */}\n <ProTextarea\n {...(addOnProps as ProTextareaAddOnProps)}\n value={value}\n onChange={onChange}\n placeholder={placeholder}\n disabled={disabled}\n wrapperClassName=\"h-[min(70dvh,40rem)]\"\n className=\"h-full text-sm\"\n autoFocus\n />\n </DialogContent>\n </Dialog>\n ) : null}\n\n {floatingLabel && inputId && (\n <Label\n htmlFor={inputId}\n className={cn(\n \"absolute left-3 px-1 pointer-events-none transition-all duration-200 ease-in-out z-10 bg-transparent\",\n labelFloated ? \"-top-2 text-xs\" : \"top-3 text-sm\",\n isInvalid ? \"text-destructive\" : isFocused ? \"text-primary\" : \"text-muted-foreground\",\n disabled && \"text-disabled-foreground\",\n )}\n >\n {floatingLabel}\n </Label>\n )}\n\n {leading && reservesRow ? (\n <div\n data-pro-textarea-leading=\"\"\n onMouseDown={(e) => e.preventDefault()}\n className={cn(\"absolute z-10 flex items-center gap-1\", hero ? \"bottom-2 left-3\" : \"bottom-1 left-1\")}\n >\n {leading}\n </div>\n ) : null}\n {controlsHost === \"none\" ? null : controlsHost ? createPortal(cluster, controlsHost) : cluster}\n\n {enableVoice && isRecording && (\n <ListeningStrip\n liveTranscript={voice.liveTranscript}\n className={\n inlineControls\n ? \"inset-x-0 bottom-full mb-1.5 border border-border bg-card shadow-sm\"\n : cn(\"left-2 bottom-2 bg-primary/10 dark:bg-primary/15\", onSubmit ? \"right-32\" : \"right-24\")\n }\n />\n )}\n {enableVoice && isTranscribing && !isRecording && (\n <FinalizingStrip className={inlineControls ? \"left-0 bottom-full mb-1.5\" : \"left-2 bottom-2\"} />\n )}\n </div>\n\n {voice.dialogs}\n <VoiceProtectionDialog voice={voice} />\n\n {/* Desktop-only: on a phone the counts row is clutter under every field. */}\n {showPinnedTextStatsBar && Stats ? (\n <div className=\"hidden sm:block\">\n <Stats.Bar text={valueAsString} />\n </div>\n ) : null}\n </div>\n </div>\n );\n\n const ContextMenu = addOns.ContextMenu;\n if (!ContextMenu) return field;\n return (\n <ContextMenu field={fieldApi} disabled={disabled}>\n {field}\n </ContextMenu>\n );\n },\n);\n\nProTextarea.displayName = \"ProTextarea\";\n\n/** \"…\" with no Menu port: the field's own rows plus a working Copy — announced as a stand-in. */\nexport function StandInMenu({\n field,\n ownRows,\n trailingRows,\n close,\n registry,\n}: {\n field: WritingFieldApi;\n ownRows: React.ReactNode;\n trailingRows: React.ReactNode;\n close: () => void;\n registry: boolean;\n}) {\n React.useEffect(() => {\n if (registry) announceMissingPort(\"Menu\");\n }, [registry]);\n return (\n <div className=\"flex w-48 flex-col p-1\" data-writing-field-host={registry ? UNCONFIGURED : undefined}>\n {ownRows}\n {registry && field.showCopyButton ? (\n <FieldMenuRow\n icon={<CopyIcon />}\n onClick={() => {\n const text = field.getText();\n close();\n if (text) void copyText(text).then((ok) => ok && field.flashCopied());\n }}\n >\n Copy\n </FieldMenuRow>\n ) : null}\n {trailingRows}\n </div>\n );\n}\n","/**\n * THE ONE FITTING RULE for ProInput and ProTextarea's controls (2026-10-15).\n *\n * A writing field's controls never take the room the text needs, and a control\n * that does not fit is never deleted — it moves inside \"…\". Until this module\n * each field had its own step-down rule: ProInput dropped its mic AND its \"…\"\n * outright below ~220px when it also had Clear + Send (voice, copy, clean-up and\n * read-aloud became unreachable), and on a phone a 110px field kept two letters\n * of text beside Clear and Send.\n *\n * The rule:\n * - REQUIRED controls always show: Send (the field's action) and \"…\" whenever\n * it holds anything.\n * - OPTIONAL controls show in priority order while the text keeps its floor;\n * the rest go inside \"…\". Folding runs from the lowest priority up: Expand,\n * then Clear, then the mic.\n * - There is no device chevron (Arman, 2026-10-16): the microphone choice is\n * a right-click / press-and-hold on the mic, and an \"Audio settings\" row in\n * \"…\" whenever \"…\" shows — so it never takes room here.\n * - A live recording always keeps its stop button inline (the caller forces it).\n *\n * Widths are the real rendered footprints per pointer and density (measured\n * 2026-10-15 on a fine pointer and a 375px phone), so a phone folds earlier\n * instead of being crushed.\n */\n\nexport type FoldableControl = \"mic\" | \"clear\" | \"expand\";\n\n/** How the mic shows: inline, inside \"…\", or not offered. */\nexport type MicFit = \"inline\" | \"folded\" | \"none\";\n\nexport interface ControlSizes {\n /** One tap box (Send, \"…\", Clear, Expand). */\n box: number;\n /** The mic button, its own 3px margins included. */\n mic: number;\n}\n\n/** 38px tap box; the mic is a 28px button plus its 3px margins. */\nexport const FINE_SIZES: ControlSizes = { box: 38, mic: 34 };\n/** Touch: the tap box keeps 38px of layout (the 44px hit area is invisible); the mic pads out. */\nexport const COARSE_SIZES: ControlSizes = { box: 38, mic: 46 };\n/** The dense field scope (`data-matrx-tap-dense`): a 24px pill in a 28px box. */\nexport const DENSE_SIZES: ControlSizes = { box: 28, mic: 28 };\n\nexport function controlSizes(opts: { coarse: boolean; dense: boolean }): ControlSizes {\n if (opts.dense) return DENSE_SIZES;\n return opts.coarse ? COARSE_SIZES : FINE_SIZES;\n}\n\n/** Below this field height the controls take the dense 28px size. */\nexport const DENSE_FIELD_MAX_HEIGHT_PX = 34;\n\nexport function isDenseField(fieldHeight: number): boolean {\n return fieldHeight > 0 && fieldHeight < DENSE_FIELD_MAX_HEIGHT_PX;\n}\n\n/**\n * The text's floor: half the field, never more than 140px and never less than\n * 48px (about five characters).\n */\nexport function minTextPx(fieldWidth: number): number {\n return Math.max(48, Math.min(140, Math.round(fieldWidth * 0.5)));\n}\n\nexport interface FitRequest {\n /** The field's measured width; 0 = not measured yet (first paint, jsdom) → everything that may be inline is. */\n fieldWidth: number;\n sizes: ControlSizes;\n /** Space the field always spends outside the controls: its left padding, a start icon, the text gap. */\n fixedPx?: number | undefined;\n /** The text floor; defaults to `minTextPx(fieldWidth)`. A reserved control row passes 0. */\n minText?: number | undefined;\n hasSubmit: boolean;\n /** The \"…\" menu has items of its own (copy, clean-up, read-aloud, agents…). */\n menuHasOwnItems: boolean;\n /** The field offers voice input. */\n mic: boolean;\n /** Clear is offered right now (the field has text). */\n clear: boolean;\n /** Expand is offered right now (the text overflows the box). */\n expand: boolean;\n}\n\nexport interface FitResult {\n mic: MicFit;\n clearInline: boolean;\n expandInline: boolean;\n /** Controls that live inside \"…\" because they did not fit. */\n folded: FoldableControl[];\n /** \"…\" shows: it has its own items or holds a folded control. */\n showMenu: boolean;\n /** Width every inline control takes together, px. */\n inlineWidth: number;\n}\n\nexport function fitFieldControls(req: FitRequest): FitResult {\n const { sizes } = req;\n const folded: FoldableControl[] = [];\n let mic: MicFit = req.mic ? \"inline\" : \"none\";\n let clearInline = req.clear;\n let expandInline = req.expand;\n\n const menuWillShow = () => req.menuHasOwnItems || folded.length > 0;\n const width = () =>\n (req.hasSubmit ? sizes.box : 0) +\n (menuWillShow() ? sizes.box : 0) +\n (mic === \"inline\" ? sizes.mic : 0) +\n (clearInline ? sizes.box : 0) +\n (expandInline ? sizes.box : 0);\n\n if (req.fieldWidth > 0) {\n const floor = req.minText ?? minTextPx(req.fieldWidth);\n const room = req.fieldWidth - (req.fixedPx ?? 0) - floor;\n const steps: Array<() => void> = [\n () => {\n if (expandInline) {\n expandInline = false;\n folded.push(\"expand\");\n }\n },\n () => {\n if (clearInline) {\n clearInline = false;\n folded.push(\"clear\");\n }\n },\n () => {\n if (mic === \"inline\") {\n mic = \"folded\";\n folded.push(\"mic\");\n }\n },\n ];\n for (const step of steps) {\n if (width() <= room) break;\n step();\n }\n }\n\n return {\n mic,\n clearInline,\n expandInline,\n folded,\n showMenu: menuWillShow(),\n inlineWidth: width(),\n };\n}\n","/**\n * WHERE PROTEXTAREA'S MIC + \"…\" CLUSTER SITS, and the rule that it never covers\n * text (the ProTextarea twin of `proInputReservedPadding.ts`, page-pass 2026-09-27).\n *\n * A textarea's lines run the full width, so the cluster cannot take a right\n * gutter; it sits in a bottom ROW the field reserves (`pb-11`) on every\n * pointer. Mic, \"…\" and the submit button share ONE flex row inset 4px from\n * the corner, so they sit as adjacent tap boxes — no hand-typed offset between\n * them (a 48px offset beside a 38px box left a 10px hole, 2026-10-05).\n */\nexport type ClusterRow = \"top\" | \"bottom\";\n\nexport interface ClusterPlacement {\n row: ClusterRow;\n /** Distance from the right edge, px (clears the submit button when they share a row). */\n rightPx: number;\n /** The rows the field reserves, per pointer kind. */\n reserved: { fine: ClusterRow[]; coarse: ClusterRow[] };\n /** The submit button's row and width, when there is one. */\n submit: { row: ClusterRow; widthPx: number } | null;\n /** The classes the cluster container adds. */\n className: string;\n}\n\n/** The tap box (`--matrx-tap-box`, 38px since 2026-10-01). */\nexport const SUBMIT_BUTTON_WIDTH_PX = 38;\n\n/** Where the cluster sits: a reserved row under the text, or inline at the end of the last line. */\nexport type ProTextareaControls = \"row\" | \"inline\";\n\n/** The tap pill's half-gap (`--matrx-tap-gap` / 2): a container edge is a neighbour (tap-target rule 4). */\nexport const TAP_HALF_GAP_PX = 3;\n\n/** One tap row plus the half-gap above and below it: the shortest an inline-controls box may be. */\nexport const INLINE_CONTROLS_MIN_HEIGHT_PX = SUBMIT_BUTTON_WIDTH_PX + 2 * TAP_HALF_GAP_PX;\n\n/**\n * The inline-controls text padding: centered on one tap row vertically (whatever\n * the host's line height — `1lh`), and a right gutter the measured cluster\n * width plus the half-gap, so text never runs under a control.\n */\nexport function inlineControlsFieldPadding(\n clusterWidthPx: number,\n /** The one-line height: 44px, or 34px for a dense (small-type) box. */\n minHeightPx: number = INLINE_CONTROLS_MIN_HEIGHT_PX,\n): {\n paddingTop: string;\n paddingBottom: string;\n paddingRight: string;\n} {\n const block = `calc((${minHeightPx}px - 1lh) / 2 - 1px)`;\n return {\n paddingTop: block,\n paddingBottom: block,\n paddingRight: `${clusterWidthPx + 2 * TAP_HALF_GAP_PX}px`,\n };\n}\n\nexport function proTextareaClusterPlacement(\n hasSubmit: boolean,\n controls: ProTextareaControls = \"row\",\n): ClusterPlacement {\n if (controls === \"inline\") {\n // Inset by the half-gap: a 38px box in a 44px-min box is dead-centre on\n // one line, and stays on the last line as the text grows.\n return {\n row: \"bottom\",\n rightPx: hasSubmit ? SUBMIT_BUTTON_WIDTH_PX + TAP_HALF_GAP_PX : TAP_HALF_GAP_PX,\n reserved: { fine: [\"bottom\"], coarse: [\"bottom\"] },\n submit: hasSubmit ? { row: \"bottom\", widthPx: SUBMIT_BUTTON_WIDTH_PX } : null,\n className: \"bottom-[3px] right-[3px]\",\n };\n }\n // One flex row inset 4px from the bottom-right corner: the hover part, then\n // the submit button. They are adjacent tap boxes in the SAME row, so the\n // cluster sits exactly one submit box (plus the inset) from the edge.\n return {\n row: \"bottom\",\n rightPx: hasSubmit ? SUBMIT_BUTTON_WIDTH_PX + 4 : 4,\n reserved: { fine: [\"bottom\"], coarse: [\"bottom\"] },\n submit: hasSubmit ? { row: \"bottom\", widthPx: SUBMIT_BUTTON_WIDTH_PX } : null,\n className: \"bottom-1 right-1\",\n };\n}\n\n/** Every way a placement lets the cluster cover text or the submit button. `[]` = sound. */\nexport function clusterPlacementProblems(p: ClusterPlacement): string[] {\n const problems: string[] = [];\n if (!p.reserved.fine.includes(p.row)) {\n problems.push(`on a fine pointer the ${p.row} row is not reserved, so the cluster covers text on hover`);\n }\n if (!p.reserved.coarse.includes(p.row)) {\n problems.push(`on a touch screen the ${p.row} row is not reserved, so the cluster covers text`);\n }\n if (p.submit && p.submit.row === p.row && p.rightPx < p.submit.widthPx) {\n problems.push(\"the cluster overlaps the submit button\");\n }\n return problems;\n}\n\n// What fits beside the text — and what moves inside \"…\" — is decided by THE\n// ONE FITTING RULE shared with ProInput: `proFieldControlFit.ts`.\n","\"use client\";\n\n/**\n * THE WRITING FIELD'S ADD-ON PORTS. `ProTextarea` / `ProInput` (this subpath) own the box: the\n * textarea/input, auto-grow, the control row, submit and Enter rules, the dictation handle, the\n * close-protection dialog. Everything that needs a recorder, a server, an agent or a menu engine\n * reaches the field through these ports, registered ONCE at the host root:\n *\n * <WritingFieldAddOnsProvider addOns={matrxWritingFieldAddOns}>…</WritingFieldAddOnsProvider>\n *\n * so design-system (layer 2) never imports chat, agents, rich-content, context-menu or a recorder.\n * A port the host did not register falls back to a stand-in that ANNOUNCES itself (law 4): one\n * console notice naming the port, and `data-writing-field-host=\"unconfigured\"` on the field.\n *\n * Hook ports (`useVoice`, `useFormatting`, `useOpenAudioSettings`) are called on every render, so\n * the registered object must be module-constant: the provider keeps the FIRST object it receives\n * and announces a swap instead of breaking hook order.\n *\n * One context for every bundle copy of this module (tsup inlines it into each entry), keyed like\n * `writing-box.tsx`.\n */\nimport * as React from \"react\";\nimport { announceStandIn } from \"../stand-in-notice\";\n\n/** Options the field hands its voice port — the same contract the app's `useMicField` takes. */\nexport interface WritingFieldVoiceOptions {\n /** Voice is on for this field (`enableVoice`). When false the port must stay inert. */\n enabled: boolean;\n instanceId?: string | undefined;\n label?: string | undefined;\n getValue: () => string;\n /** Write the next value through the field's own change path. */\n writeValue: (next: string) => boolean | void;\n appendTranscript?: boolean | undefined;\n join?: ((base: string, text: string) => string) | undefined;\n protect?: boolean | undefined;\n onRequestClose?: (() => void) | undefined;\n onTranscriptionComplete?: ((text: string) => void) | undefined;\n onTranscriptionError?: ((error: string) => void) | undefined;\n}\n\n/** What a voice port returns: recorder state plus the controls the field draws. */\nexport interface WritingFieldVoice {\n /** The browser exposes a microphone (device enumeration works). */\n microphone: boolean;\n /** A recorder is mounted on this route. */\n available: boolean;\n isRecording: boolean;\n isTranscribing: boolean;\n audioLevel: number;\n liveTranscript: string;\n handleVoiceClick: () => void | Promise<void>;\n startDictation: () => Promise<void>;\n stopDictation: () => void;\n requestClose: () => void;\n showProtectionDialog: boolean;\n setShowProtectionDialog: (open: boolean) => void;\n confirmClose: () => void;\n cancelClose: () => void;\n /** The port's own dialogs (troubleshooting), drawn beside the field. */\n dialogs?: React.ReactNode | undefined;\n}\n\nexport interface WritingFieldMicButtonProps {\n onMicClick: () => void;\n disabled?: boolean | undefined;\n isRecording?: boolean | undefined;\n isTranscribing?: boolean | undefined;\n audioLevel?: number | undefined;\n micAriaLabel?: string | undefined;\n tabIndex?: number | undefined;\n dense?: boolean | undefined;\n}\n\n/** The field as an add-on sees it. */\nexport interface WritingFieldApi {\n kind: \"textarea\" | \"input\";\n /** The value the host last rendered. */\n text: string;\n /** The live text (the DOM or the hosted editor), falling back to `text`. */\n getText: () => string;\n /** Write through the field's own change path; true when the field now holds `next`. */\n write: (next: string) => boolean;\n getSelection: () => { start: number; end: number };\n getElement: () => HTMLTextAreaElement | HTMLInputElement | null;\n /** The add-on props the caller passed (surfaceName, getApplicationScope, cleanup…), untouched. */\n addOnProps: Readonly<Record<string, unknown>>;\n showCopyButton: boolean;\n /** Show the brief \"Copied\" check on the \"…\" trigger (ProInput). */\n flashCopied: () => void;\n}\n\nexport interface WritingFieldMenuProps {\n field: WritingFieldApi;\n /** The field's own rows (Expand, Voice input, Audio settings, Clear) — place them in the list view. */\n ownRows: React.ReactNode;\n /** Rows the field adds after the add-on's list (text stats). */\n trailingRows: React.ReactNode;\n close: () => void;\n}\n\nexport interface WritingFieldContextMenuProps {\n field: WritingFieldApi;\n disabled?: boolean | undefined;\n children: React.ReactNode;\n}\n\nexport interface WritingFieldTextStats {\n Bar: React.ComponentType<{ text: string }>;\n MenuItems: React.ComponentType<{\n showStatsBar: boolean;\n onToggleStatsBar: () => void;\n onOpenStatsPanel: () => void;\n }>;\n Panel: React.ComponentType<{ text: string; onBack?: () => void; onClose?: () => void }>;\n}\n\nexport interface WritingFieldNotify {\n error: (message: string, options?: { description?: string }) => void;\n info: (message: string) => void;\n success: (message: string) => void;\n}\n\nexport interface WritingFieldAddOns {\n useVoice?: ((options: WritingFieldVoiceOptions) => WritingFieldVoice) | undefined;\n MicButton?: React.ComponentType<WritingFieldMicButtonProps> | undefined;\n useOpenAudioSettings?: (() => () => void) | undefined;\n /** Markdown chords + selection toolbar on a long-form box. */\n useFormatting?:\n | ((\n element: HTMLTextAreaElement | null,\n on: boolean,\n addOnProps: Readonly<Record<string, unknown>>,\n ) => void)\n | undefined;\n /** The \"…\" body (actions, agents, read-aloud). */\n Menu?: React.ComponentType<WritingFieldMenuProps> | undefined;\n /** Whether `Menu` has rows of its own for this field (so \"…\" shows). */\n menuHasItems?: ((field: Pick<WritingFieldApi, \"kind\" | \"addOnProps\" | \"showCopyButton\">) => boolean) | undefined;\n /** The right-click floor around the field. */\n ContextMenu?: React.ComponentType<WritingFieldContextMenuProps> | undefined;\n TextStats?: WritingFieldTextStats | undefined;\n notify?: WritingFieldNotify | undefined;\n /** Extra prop names the add-ons read (kept off the DOM element). */\n propNames?: readonly string[] | undefined;\n}\n\n/** Add-on prop names the field never spreads onto the DOM (the Matrx add-ons' props). */\nexport const ADD_ON_PROP_NAMES: readonly string[] = [\n \"surfaceName\",\n \"getApplicationScope\",\n \"sourceFeature\",\n \"surfaceContextItems\",\n \"enableBoundAgents\",\n \"enableContextMenu\",\n \"enableCleanup\",\n \"cleanupAgentId\",\n \"cleanupContextItems\",\n \"enableHelpWithThis\",\n \"helpMandateKey\",\n \"helpContextItems\",\n \"enableCustomAgent\",\n \"customAgentMandateKey\",\n \"customAgentContextItems\",\n \"uploadImage\",\n];\n\n/** Split a field's rest props into DOM props and add-on props. */\nexport function splitAddOnProps<T extends Record<string, unknown>>(\n props: T,\n extra: readonly string[] = [],\n): { dom: T; addOnProps: Record<string, unknown> } {\n const dom: Record<string, unknown> = {};\n const addOnProps: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(props)) {\n if (ADD_ON_PROP_NAMES.includes(key) || extra.includes(key)) addOnProps[key] = value;\n else dom[key] = value;\n }\n return { dom: dom as T, addOnProps };\n}\n\nconst KEY = Symbol.for(\"@ai-matrx/design-system/writing-field-add-ons\");\ntype Registry = Record<symbol, React.Context<WritingFieldAddOns | null> | undefined>;\nconst registry = globalThis as unknown as Registry;\nconst AddOnsContext: React.Context<WritingFieldAddOns | null> =\n registry[KEY] ?? (registry[KEY] = React.createContext<WritingFieldAddOns | null>(null));\n\n/** Mount once at the host's app root. The first `addOns` object is kept for the provider's life. */\nexport function WritingFieldAddOnsProvider({\n addOns,\n children,\n}: {\n addOns: WritingFieldAddOns;\n children: React.ReactNode;\n}) {\n const first = React.useRef(addOns);\n if (first.current !== addOns) {\n announceStandIn(\n \"writing-field-add-ons-swap\",\n \"WritingFieldAddOnsProvider received a different addOns object; the first one is kept (hook ports must be module-constant).\",\n );\n }\n return <AddOnsContext.Provider value={first.current}>{children}</AddOnsContext.Provider>;\n}\n\nconst EMPTY: WritingFieldAddOns = {};\n\n/** The registered add-ons (or none). */\nexport function useWritingFieldAddOns(): WritingFieldAddOns {\n return React.useContext(AddOnsContext) ?? EMPTY;\n}\n\n/** Announce a missing port once, in words naming what to register. */\nexport function announceMissingPort(port: string): void {\n announceStandIn(\n `writing-field:${port}`,\n `A writing field drew without its \"${port}\" add-on: the host did not register it in <WritingFieldAddOnsProvider addOns={{ ${port} }}>.`,\n );\n}\n\nconst INERT = () => undefined;\n\n/** The voice stand-in: no recorder, every control inert, announced when a field asks for voice. */\nexport function useStandInVoice(options: WritingFieldVoiceOptions): WritingFieldVoice {\n React.useEffect(() => {\n if (options.enabled) announceMissingPort(\"useVoice\");\n }, [options.enabled]);\n return {\n microphone: false,\n available: false,\n isRecording: false,\n isTranscribing: false,\n audioLevel: 0,\n liveTranscript: \"\",\n handleVoiceClick: INERT,\n startDictation: async () => undefined,\n stopDictation: INERT,\n requestClose: () => options.onRequestClose?.(),\n showProtectionDialog: false,\n setShowProtectionDialog: INERT,\n confirmClose: () => options.onRequestClose?.(),\n cancelClose: INERT,\n };\n}\n\n/** Notices with no host toast go to the console, announced once. */\nexport const STAND_IN_NOTIFY: WritingFieldNotify = {\n error: (message) => {\n announceMissingPort(\"notify\");\n console.error(`[writing-field] ${message}`);\n },\n info: (message) => {\n announceMissingPort(\"notify\");\n console.info(`[writing-field] ${message}`);\n },\n success: (message) => {\n announceMissingPort(\"notify\");\n console.info(`[writing-field] ${message}`);\n },\n};\n\nfunction useNoFormatting(): void {}\nfunction useNoAudioSettings(): () => void {\n return () => announceMissingPort(\"useOpenAudioSettings\");\n}\n\n/** The add-ons with every missing hook port filled by its stand-in (stable for a stable registry). */\nexport function resolveHookPorts(addOns: WritingFieldAddOns) {\n return {\n useVoice: addOns.useVoice ?? useStandInVoice,\n useFormatting: addOns.useFormatting ?? useNoFormatting,\n useOpenAudioSettings: addOns.useOpenAudioSettings ?? useNoAudioSettings,\n notify: addOns.notify ?? STAND_IN_NOTIFY,\n };\n}\n","\"use client\";\n\n/**\n * The field-owned voice chrome every writing field shares: the live \"Listening…\" strip, the\n * \"Finalizing…\" strip and the close-protection dialog. The recorder itself is the host's\n * (`useVoice` port); these only draw its state.\n */\nimport * as React from \"react\";\nimport { cn } from \"../cn\";\nimport { Tile } from \"../controls/surfaces\";\nimport { CheckIcon, Loader2Icon } from \"../icons\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n} from \"../alert-dialog\";\nimport type { WritingFieldVoice } from \"./add-ons\";\n\nexport function ListeningStrip({ liveTranscript, className }: { liveTranscript: string; className?: string }) {\n return (\n <div className={cn(\"absolute flex items-center gap-1.5 px-2 py-1 rounded-md\", className)}>\n <span aria-hidden className=\"w-2 h-2 bg-primary rounded-full flex-shrink-0 animate-pulse\" />\n <span className=\"type-secondary text-primary font-medium truncate\">\n {liveTranscript ? liveTranscript.slice(-60) : \"Listening...\"}\n </span>\n </div>\n );\n}\n\nexport function FinalizingStrip({ className }: { className?: string }) {\n return (\n <div\n className={cn(\n \"absolute flex items-center gap-1.5 px-2 py-1 rounded-md bg-blue-100 dark:bg-blue-900/30\",\n className,\n )}\n >\n <Loader2Icon className=\"w-3 h-3 animate-spin text-blue-600 dark:text-blue-400\" />\n <span className=\"type-secondary text-blue-600 dark:text-blue-400 font-medium\">Finalizing...</span>\n </div>\n );\n}\n\n/** Warns before a field closes while a recording or transcription is in flight. */\nexport function VoiceProtectionDialog({ voice }: { voice: WritingFieldVoice }) {\n const { isRecording, isTranscribing } = voice;\n const busy = isRecording || isTranscribing;\n return (\n <AlertDialog open={voice.showProtectionDialog} onOpenChange={voice.setShowProtectionDialog}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <div className=\"flex items-center gap-3 mb-2\">\n {busy ? (\n <>\n <Loader2Icon className=\"h-5 w-5 animate-spin text-blue-500\" />\n <AlertDialogTitle>\n {isRecording ? \"Recording in Progress\" : \"Transcription in Progress\"}\n </AlertDialogTitle>\n </>\n ) : (\n <>\n <CheckIcon className=\"h-5 w-5 text-green-500\" />\n <AlertDialogTitle>Voice Input Complete</AlertDialogTitle>\n </>\n )}\n </div>\n <AlertDialogDescription>\n {isRecording\n ? \"Your voice is currently being recorded. If you close now, the recording will be stopped and lost.\"\n : isTranscribing\n ? \"Your voice recording is currently being transcribed. If you close now, the transcription will be lost.\"\n : \"Your voice input has been processed successfully! You can now safely close this panel.\"}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n {busy ? (\n <>\n <AlertDialogCancel onClick={voice.cancelClose}>Cancel & Wait</AlertDialogCancel>\n <AlertDialogAction\n onClick={voice.confirmClose}\n className=\"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n >\n {isRecording ? \"Stop Recording\" : \"End Transcription\"}\n </AlertDialogAction>\n </>\n ) : (\n <AlertDialogAction onClick={voice.confirmClose}>Close</AlertDialogAction>\n )}\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n );\n}\n\n/** A menu row in the field's own part of \"…\" (Expand, Voice input, Audio settings, Clear). */\nexport function FieldMenuRow({\n icon,\n children,\n onClick,\n disabled,\n}: {\n icon: React.ReactNode;\n children: React.ReactNode;\n onClick: () => void;\n disabled?: boolean;\n}) {\n return (\n <Tile\n type=\"button\"\n disabled={disabled}\n onClick={onClick}\n variant=\"quiet\"\n className=\"w-full\"\n icon={icon}\n title={children}\n />\n );\n}\n\n/** The mic button a host without a voice port would get — never drawn: no port, no microphone. */\nexport function micAriaLabel(isRecording: boolean, label?: string): string {\n if (isRecording) return label ? `Stop recording for ${label}` : \"Stop recording\";\n return label ? `Start voice input for ${label}` : \"Start voice input\";\n}\n","\"use client\";\n\n/**\n * ProInput — THE one-line box a person writes words in (titles, names, short replies). Moved from\n * matrx-frontend `components/official/ProInput.tsx` (2026-10-22); its recorder, read-aloud, Copy\n * and Clean up arrive through the add-on ports (`./add-ons.tsx`).\n *\n * Built in: submit (`onSubmit`, ⌘/Ctrl+Enter, `submitOnEnter`), field navigation (`onEnterKey`),\n * Clear (`clearable` + `onClear`), `startIcon`, the iOS zoom guard (value text 16px), floating\n * label, the ONE fitting rule (`./control-fit.ts`), and the measured right padding that keeps the\n * hover cluster off the text (`./reserved-padding.ts`; a narrow field reveals it on focus).\n */\nimport * as React from \"react\";\nimport { useMediaQuery } from \"@ai-matrx/kit/media-query\";\nimport { cn } from \"../cn\";\nimport { Label } from \"../label\";\nimport { Field } from \"../controls/controls\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../popover\";\nimport {\n CheckTapButton,\n LoadingTapButton,\n MoreHorizontalTapButton,\n SendTapButton,\n XTapButton,\n} from \"../tap-target/tap-buttons\";\nimport { MicIcon, SlidersHorizontalIcon, XIcon } from \"../icons\";\nimport { UNCONFIGURED } from \"../stand-in-notice\";\nimport { PRO_INPUT_TEXT_GAP_PX, hoverRevealsCluster, reservedRightPaddingPx } from \"./reserved-padding\";\nimport { controlSizes, fitFieldControls, isDenseField } from \"./control-fit\";\nimport { resolveHookPorts, splitAddOnProps, useWritingFieldAddOns, type WritingFieldApi } from \"./add-ons\";\nimport { FieldMenuRow, FinalizingStrip, VoiceProtectionDialog, micAriaLabel } from \"./voice-chrome\";\nimport { StandInMenu } from \"./pro-textarea\";\nimport type { ProInputAddOnProps } from \"./index\";\n\n/** Real HTMLInputElement with optional expando methods set by ProInput. */\nexport interface ProInputElement extends HTMLInputElement {\n requestClose?: () => void;\n isTranscribing?: () => boolean;\n}\n\nexport interface ProInputProps extends React.InputHTMLAttributes<HTMLInputElement>, ProInputAddOnProps {\n onTranscriptionComplete?: (text: string) => void;\n onTranscriptionError?: (error: string) => void;\n /** If true, appends to existing text; if false, replaces. Default: true. */\n appendTranscript?: boolean;\n wrapperClassName?: string;\n onRequestClose?: () => void;\n /** Warn before unmount during recording/transcription. Default: true. */\n protectTranscription?: boolean;\n /** Show the Copy action inside the \"…\" menu. Default: true. */\n showCopyButton?: boolean;\n /** Voice input. Default true; false for search bars and filters. */\n enableVoice?: boolean;\n onSubmit?: () => void;\n submitDisabled?: boolean;\n isSubmitting?: boolean;\n /** Accessible/tooltip label for the submit button. Default: \"Send\". */\n submitLabel?: string;\n submitOnCmdEnter?: boolean;\n submitOnEnter?: boolean;\n /** Field-navigation mode: plain Enter calls this instead of submitting. */\n onEnterKey?: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n auxiliaryControlsTabIndex?: number;\n auxiliaryControlsLabel?: string;\n /** Optional leading icon/node — auto-applies left padding. */\n startIcon?: React.ReactNode;\n /** Shows a clear (×) control while the field has content. */\n clearable?: boolean;\n /** Called when the clear control is pressed. Defaults to clearing via `onChange`. */\n onClear?: () => void;\n /** Dense-form label inside the border (use only on a `bg-card` surface). */\n floatingLabel?: string;\n}\n\nconst joinWithSpace = (base: string, text: string) => `${base}${base.endsWith(\" \") ? \"\" : \" \"}${text}`;\n\nexport const ProInput = React.forwardRef<HTMLInputElement, ProInputProps>(\n (\n {\n className,\n wrapperClassName,\n onTranscriptionComplete,\n onTranscriptionError,\n appendTranscript = true,\n value,\n onChange,\n onKeyDown,\n disabled,\n onRequestClose,\n protectTranscription = true,\n showCopyButton = true,\n enableVoice = true,\n onSubmit,\n submitDisabled,\n isSubmitting = false,\n submitLabel = \"Send\",\n submitOnCmdEnter,\n submitOnEnter = false,\n onEnterKey,\n auxiliaryControlsTabIndex,\n auxiliaryControlsLabel,\n startIcon,\n clearable = false,\n onClear,\n floatingLabel,\n id: idProp,\n placeholder,\n type = \"text\",\n ...rest\n },\n ref,\n ) => {\n const addOns = useWritingFieldAddOns();\n const ports = resolveHookPorts(addOns);\n const { dom: props, addOnProps } = splitAddOnProps(rest as Record<string, unknown>, addOns.propNames) as {\n dom: React.InputHTMLAttributes<HTMLInputElement>;\n addOnProps: Record<string, unknown>;\n };\n const generatedId = React.useId();\n // Field owns its geometry; the legacy native size attribute must not become a skin.\n const { size: _nativeSize, width: nativeWidth, style: nativeStyle, ...fieldProps } = props;\n const inputId = idProp ?? (floatingLabel ? generatedId : undefined);\n const [hasCopied, setHasCopied] = React.useState(false);\n const [menuOpen, setMenuOpen] = React.useState(false);\n const [isFocused, setIsFocused] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n const internalRef = React.useRef<HTMLInputElement | null>(null);\n const clusterRef = React.useRef<HTMLDivElement | null>(null);\n const auxRef = React.useRef<HTMLDivElement>(null);\n const [clusterWidths, setClusterWidths] = React.useState({ cluster: 0, aux: 0 });\n const [inputWidth, setInputWidth] = React.useState(0);\n const [inputHeight, setInputHeight] = React.useState(0);\n const coarsePointer = useMediaQuery(\"(pointer: coarse)\");\n const clusterObserver = React.useRef<ResizeObserver | null>(null);\n // Stable, so React re-runs it only when the node changes (a new function each render re-measured in\n // every commit, which loops when the measured size moves with the field's own controls).\n const setClusterNode = React.useCallback((cluster: HTMLDivElement | null) => {\n if (clusterRef.current === cluster) return;\n clusterRef.current = cluster;\n clusterObserver.current?.disconnect();\n clusterObserver.current = null;\n if (!cluster || typeof ResizeObserver === \"undefined\") return;\n const measure = () => {\n const next = {\n cluster: cluster.getBoundingClientRect().width,\n aux: auxRef.current?.getBoundingClientRect().width ?? 0,\n };\n setClusterWidths((prev) => (prev.cluster === next.cluster && prev.aux === next.aux ? prev : next));\n };\n measure();\n clusterObserver.current = new ResizeObserver(measure);\n clusterObserver.current.observe(cluster);\n if (auxRef.current) clusterObserver.current.observe(auxRef.current);\n }, []);\n const inputRef = internalRef;\n const inputObserver = React.useRef<ResizeObserver | null>(null);\n // A merged CALLBACK ref: the host gets the element AND the field still measures that element.\n // Stable, so React re-runs it only when the node changes (a new function each render re-measured in\n // every commit, which loops when the measured size moves with the field's own controls).\n const setInputRef = React.useCallback((node: HTMLInputElement | null) => {\n if (internalRef.current !== node) {\n inputObserver.current?.disconnect();\n inputObserver.current = null;\n if (node && typeof ResizeObserver !== \"undefined\") {\n const measure = () => {\n const rect = node.getBoundingClientRect();\n setInputWidth(rect.width);\n setInputHeight(rect.height);\n };\n measure();\n inputObserver.current = new ResizeObserver(measure);\n inputObserver.current.observe(node);\n }\n }\n internalRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) (ref as React.MutableRefObject<HTMLInputElement | null>).current = node;\n }, [ref]);\n // THE PRE-HYDRATION KEEP (see ProTextarea).\n const keepPreHydrationText = React.useEffectEvent(() => {\n const el = inputRef.current;\n if (!el || !onChange) return;\n const typed = el.value;\n if (!typed || typed === String(value ?? \"\")) return;\n el.value = \"\";\n Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, \"value\")?.set?.call(el, typed);\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n });\n React.useLayoutEffect(() => {\n keepPreHydrationText();\n }, []);\n React.useEffect(\n () => () => {\n clusterObserver.current?.disconnect();\n inputObserver.current?.disconnect();\n },\n [],\n );\n const openAudioSettings = ports.useOpenAudioSettings();\n\n const pushToInput = React.useCallback((newValue: string): boolean => {\n const el = inputRef.current;\n if (!el) return false;\n const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, \"value\")?.set;\n if (!setter) return false;\n setter.call(el, newValue);\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n return el.value === newValue;\n }, []);\n\n const getLiveText = React.useCallback(() => inputRef.current?.value ?? String(value ?? \"\"), [value]);\n const voice = ports.useVoice({\n enabled: enableVoice,\n instanceId: inputId,\n getValue: getLiveText,\n writeValue: pushToInput,\n appendTranscript,\n join: joinWithSpace,\n protect: protectTranscription,\n onRequestClose,\n onTranscriptionComplete,\n onTranscriptionError,\n });\n const { isRecording, isTranscribing } = voice;\n const isAudioAvailable = voice.microphone;\n\n React.useEffect(() => {\n const el = inputRef.current as ProInputElement | null;\n if (!el) return;\n el.requestClose = voice.requestClose;\n el.isTranscribing = () => isTranscribing;\n }, [voice.requestClose, isTranscribing]);\n\n const flashCopied = React.useCallback(() => {\n setHasCopied(true);\n setTimeout(() => setHasCopied(false), 450);\n }, []);\n\n const handleClear = React.useCallback(() => {\n if (onClear) {\n onClear();\n return;\n }\n pushToInput(\"\");\n onChange?.({ target: { value: \"\" } } as React.ChangeEvent<HTMLInputElement>);\n }, [onClear, pushToInput, onChange]);\n\n const valueAsString = String(value ?? \"\");\n const hasContent = valueAsString.trim().length > 0;\n const canSubmit = !!onSubmit && hasContent && !submitDisabled && !isSubmitting && !disabled;\n const cmdEnterEnabled = submitOnCmdEnter ?? !!onSubmit;\n const triggerSubmit = React.useCallback(() => {\n if (canSubmit && onSubmit) onSubmit();\n }, [canSubmit, onSubmit]);\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (isHovered) setIsHovered(false);\n onKeyDown?.(e);\n if (e.defaultPrevented || e.key !== \"Enter\") return;\n const withCmd = e.metaKey || e.ctrlKey;\n if (onEnterKey) {\n if (e.shiftKey || withCmd) return;\n e.preventDefault();\n onEnterKey(e);\n return;\n }\n if (!onSubmit) return;\n if (cmdEnterEnabled && withCmd) {\n e.preventDefault();\n triggerSubmit();\n return;\n }\n if (submitOnEnter && !e.shiftKey && !withCmd) {\n e.preventDefault();\n triggerSubmit();\n }\n },\n [isHovered, onKeyDown, onEnterKey, onSubmit, cmdEnterEnabled, submitOnEnter, triggerSubmit],\n );\n\n const fieldApi: WritingFieldApi = {\n kind: \"input\",\n text: valueAsString,\n getText: getLiveText,\n write: pushToInput,\n getSelection: () => ({\n start: inputRef.current?.selectionStart ?? 0,\n end: inputRef.current?.selectionEnd ?? 0,\n }),\n getElement: () => inputRef.current,\n addOnProps: { ...addOnProps, type },\n showCopyButton,\n flashCopied,\n };\n\n const pointerReveals = hoverRevealsCluster(inputWidth) ? isHovered : isFocused;\n const showHoverControls = (pointerReveals || isRecording || isTranscribing) && !disabled;\n const isVoiceDisabled = !isAudioAvailable || disabled || (isTranscribing && !isRecording);\n const showMic = enableVoice && isAudioAvailable;\n const showClear = clearable && hasContent;\n const addOnMenuItems = addOns.Menu\n ? (addOns.menuHasItems?.({ kind: \"input\", addOnProps: fieldApi.addOnProps, showCopyButton }) ?? true)\n : false;\n const denseField = isDenseField(inputHeight);\n const fit = fitFieldControls({\n fieldWidth: inputWidth,\n sizes: controlSizes({ coarse: coarsePointer, dense: denseField }),\n fixedPx: (startIcon ? 36 : 12) + PRO_INPUT_TEXT_GAP_PX,\n hasSubmit: !!onSubmit,\n menuHasOwnItems: !disabled && (showCopyButton || addOnMenuItems || hasContent),\n mic: showMic,\n clear: showClear,\n expand: false,\n });\n const voiceBusy = isRecording || isTranscribing;\n const showMicInline = showMic && (fit.mic === \"inline\" || voiceBusy);\n const voiceInMenu = showMic && !showMicInline;\n const clearInline = showClear && fit.clearInline;\n const clearInMenu = showClear && !fit.clearInline;\n const showMenu = !disabled && (showCopyButton || addOnMenuItems || voiceInMenu || clearInMenu || hasContent);\n const audioSettingsInMenu = showMenu && enableVoice;\n const auxVisible = (showHoverControls || menuOpen) && (showMicInline || showMenu);\n const measuredRightPadding = reservedRightPaddingPx({\n clusterWidth: clusterWidths.cluster,\n auxWidth: clusterWidths.aux,\n auxVisible,\n });\n const isInvalid = props[\"aria-invalid\"] === true || props[\"aria-invalid\"] === \"true\";\n const labelFloated = isFocused || valueAsString.length > 0;\n const showVoiceStatus = isRecording || (isTranscribing && !isRecording);\n const closeMenu = () => setMenuOpen(false);\n\n const ownRows = (\n <>\n {clearInMenu ? (\n <FieldMenuRow\n icon={<XIcon />}\n onClick={() => {\n closeMenu();\n handleClear();\n }}\n >\n Clear\n </FieldMenuRow>\n ) : null}\n {voiceInMenu ? (\n <FieldMenuRow\n icon={<MicIcon />}\n disabled={isVoiceDisabled}\n onClick={() => {\n closeMenu();\n void voice.handleVoiceClick();\n }}\n >\n Voice input\n </FieldMenuRow>\n ) : null}\n {audioSettingsInMenu ? (\n <FieldMenuRow\n icon={<SlidersHorizontalIcon />}\n onClick={() => {\n closeMenu();\n openAudioSettings();\n }}\n >\n Audio settings\n </FieldMenuRow>\n ) : null}\n {clearInMenu || voiceInMenu || audioSettingsInMenu ? (\n <div className=\"my-1 h-px bg-border\" role=\"separator\" />\n ) : null}\n </>\n );\n const Menu = addOns.Menu;\n\n return (\n <div\n className={cn(\"relative group\", wrapperClassName)}\n data-writing-field-host={addOns.Menu && addOns.useVoice ? undefined : UNCONFIGURED}\n onMouseEnter={() => setIsHovered(true)}\n onMouseMove={() => {\n if (!isHovered) setIsHovered(true);\n }}\n onMouseLeave={() => setIsHovered(false)}\n >\n <Field\n ref={setInputRef}\n id={inputId}\n type={type}\n placeholder={floatingLabel ? undefined : placeholder}\n className={cn(\"w-full\", className)}\n style={{ ...(nativeWidth === undefined ? {} : { width: nativeWidth }), ...nativeStyle }}\n icon={startIcon}\n end={<span aria-hidden=\"true\" style={{ width: measuredRightPadding === null ? `calc(${Number(!!onSubmit) + Number(clearInline)} * (var(--matrx-tap-pill-size) + var(--matrx-tap-gap)))` : Math.max(0, measuredRightPadding - 12), flexShrink: 0 }} />}\n value={value}\n onChange={onChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n {...fieldProps}\n />\n {floatingLabel && inputId && (\n <Label\n htmlFor={inputId}\n className={cn(\n \"absolute left-3 px-1 pointer-events-none transition-all duration-200 ease-in-out z-10 bg-card\",\n labelFloated ? \"-top-2 text-xs\" : \"top-2 text-sm\",\n isInvalid ? \"text-destructive\" : isFocused ? \"text-primary\" : \"text-muted-foreground\",\n disabled && \"text-disabled-foreground\",\n )}\n >\n {floatingLabel}\n </Label>\n )}\n {/* A GLASS PLANE (tap-target placement rule 1); a press here never takes focus from the field. */}\n <div\n ref={setClusterNode}\n onMouseDown={(e) => e.preventDefault()}\n data-matrx-glass-plane\n data-matrx-tap-dense={denseField ? \"\" : undefined}\n className=\"absolute right-0 top-1/2 -translate-y-1/2 flex items-center z-10\"\n >\n <div\n ref={auxRef}\n className={cn(\n \"flex items-center transition-opacity duration-200\",\n showHoverControls || menuOpen ? \"opacity-100\" : \"opacity-0 pointer-events-none\",\n )}\n >\n {showMicInline && addOns.MicButton ? (\n <addOns.MicButton\n dense={denseField}\n tabIndex={auxiliaryControlsTabIndex}\n onMicClick={() => void voice.handleVoiceClick()}\n disabled={isVoiceDisabled}\n isRecording={isRecording}\n isTranscribing={isTranscribing}\n audioLevel={voice.audioLevel}\n micAriaLabel={micAriaLabel(isRecording, auxiliaryControlsLabel)}\n />\n ) : null}\n {showMenu && (\n <Popover open={menuOpen} onOpenChange={setMenuOpen}>\n <PopoverTrigger asChild>\n {hasCopied ? (\n <CheckTapButton\n tabIndex={auxiliaryControlsTabIndex}\n variant=\"transparent\"\n ariaLabel={auxiliaryControlsLabel ? `Copied ${auxiliaryControlsLabel}` : \"Copied\"}\n tooltip=\"Copied\"\n className=\"text-green-500\"\n />\n ) : (\n <MoreHorizontalTapButton\n tabIndex={auxiliaryControlsTabIndex}\n variant=\"transparent\"\n ariaLabel={auxiliaryControlsLabel ? `More options for ${auxiliaryControlsLabel}` : \"More options\"}\n tooltip=\"More\"\n className=\"text-muted-foreground\"\n />\n )}\n </PopoverTrigger>\n <PopoverContent\n /* sizing: fixed — the add-on body sizes itself (short list vs. cleanup panel) */\n align=\"end\"\n side=\"bottom\"\n sideOffset={6}\n className=\"w-auto max-w-none p-0\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n {Menu ? (\n <Menu field={fieldApi} ownRows={ownRows} trailingRows={null} close={closeMenu} />\n ) : (\n <StandInMenu field={fieldApi} ownRows={ownRows} trailingRows={null} close={closeMenu} registry />\n )}\n </PopoverContent>\n </Popover>\n )}\n </div>\n {clearInline && (\n <XTapButton\n variant=\"transparent\"\n onClick={handleClear}\n ariaLabel=\"Clear\"\n tooltip=\"Clear\"\n className=\"text-muted-foreground\"\n />\n )}\n {onSubmit &&\n (isSubmitting ? (\n <LoadingTapButton variant=\"transparent\" ariaLabel={submitLabel} tooltip={submitLabel} className=\"text-primary\" />\n ) : (\n <SendTapButton\n variant=\"transparent\"\n onClick={triggerSubmit}\n disabled={!canSubmit}\n ariaLabel={submitLabel}\n tooltip={submitLabel}\n className={canSubmit ? \"text-primary\" : \"text-muted-foreground\"}\n />\n ))}\n </div>\n {showVoiceStatus && (\n <div className=\"absolute left-0 top-full mt-1 flex items-center gap-1.5 px-2 py-1 rounded-md max-w-full\">\n {isRecording ? (\n <div className=\"relative flex items-center gap-1.5 px-2 py-1 bg-primary/10 dark:bg-primary/15 rounded-md max-w-full\">\n <span aria-hidden className=\"w-2 h-2 bg-primary rounded-full flex-shrink-0 animate-pulse\" />\n <span className=\"type-secondary text-primary font-medium truncate\">\n {voice.liveTranscript ? voice.liveTranscript.slice(-60) : \"Listening...\"}\n </span>\n </div>\n ) : (\n <FinalizingStrip className=\"relative\" />\n )}\n </div>\n )}\n {voice.dialogs}\n <VoiceProtectionDialog voice={voice} />\n </div>\n );\n },\n);\n\nProInput.displayName = \"ProInput\";\n","/**\n * THE TOOLBAR NEVER COVERS TEXT (page-pass 2026-09-27, /chat/message-templates/<id> at 375px).\n *\n * ProInput's mic + \"…\" cluster fades in over the right end of the field. On a\n * phone a tap counts as a hover and stays one, so the cluster sat on top of the\n * text being typed and clipped it. The fix is to reserve exactly the width the\n * visible right-hand controls take — measured, never guessed — as the input's\n * right padding:\n *\n * - the whole cluster while the mic / \"…\" part is showing;\n * - only the always-visible part (clear, submit) while it is faded out — the\n * faded part still takes layout width, so it is subtracted, not ignored.\n *\n * `null` means \"nothing measured yet\" (first paint, jsdom): the caller keeps its\n * class-based fallback padding.\n */\nexport const PRO_INPUT_TEXT_GAP_PX = 4;\nexport const PRO_INPUT_MIN_RIGHT_PADDING_PX = 12;\n\nexport function reservedRightPaddingPx({\n clusterWidth,\n auxWidth,\n auxVisible,\n}: {\n clusterWidth: number;\n auxWidth: number;\n auxVisible: boolean;\n}): number | null {\n if (!(clusterWidth > 0)) return null;\n const visible = auxVisible\n ? clusterWidth\n : Math.max(0, clusterWidth - Math.max(0, auxWidth));\n if (visible <= 0) return PRO_INPUT_MIN_RIGHT_PADDING_PX;\n return Math.max(\n PRO_INPUT_MIN_RIGHT_PADDING_PX,\n Math.ceil(visible) + PRO_INPUT_TEXT_GAP_PX,\n );\n}\n\n/**\n * A NARROW FIELD NEVER LETS A HOVER STEAL ITS CLICK.\n *\n * The mic + \"…\" cluster fades in on pointer hover over the right end of the\n * field. In a field only a couple of hundred px wide (a board tile's task-add\n * row, a sidebar) the cluster and its reserved padding leave a sliver of text,\n * and a press aimed at the middle of the field lands ON the mic: no focus, no\n * typing. Below this width the cluster appears on FOCUS instead of hover, so\n * the first press always focuses the field.\n */\nexport const PRO_INPUT_NARROW_FIELD_PX = 260;\n\nexport function hoverRevealsCluster(inputWidth: number): boolean {\n return !(inputWidth > 0 && inputWidth < PRO_INPUT_NARROW_FIELD_PX);\n}\n\n// What fits beside the text — and what moves inside \"…\" — is decided by THE\n// ONE FITTING RULE shared with ProTextarea: `proFieldControlFit.ts`.\n"],"mappings":"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","names":["React","jsx","Fragment","jsx","jsxs","field","registry","React","useMediaQuery","Fragment","jsx","jsxs","useMediaQuery"]}
1
+ {"version":3,"sources":["../src/writing-field/pro-textarea.tsx","../src/writing-field/control-fit.ts","../src/writing-field/control-placement.ts","../src/writing-field/add-ons.tsx","../src/writing-field/voice-chrome.tsx","../src/writing-field/pro-input.tsx","../src/writing-field/reserved-padding.ts"],"sourcesContent":["\"use client\";\n\n/**\n * ProTextarea — THE box a person writes words in (one-ui-system rule 6). Moved from\n * matrx-frontend `components/official/ProTextarea.tsx` (2026-10-22): the field core lives here; the\n * recorder, the \"…\" actions, the page's agents, the right-click menu, markdown formatting and text\n * stats arrive through the add-on ports (`./add-ons.tsx`), registered once at the host root.\n *\n * Built in: auto-grow (`autoGrow` + `minHeight`/`maxHeight`), floating label, `hero` appearance,\n * the reserved control row or the `inline` composer shape (`controls`), the ONE fitting rule\n * (`./control-fit.ts`: whatever does not fit beside the text folds into \"…\", never deleted), submit\n * (`onSubmit`, ⌘/Ctrl+Enter, `submitOnEnter`, the one composer rule from `@ai-matrx/kit/composer-keys`),\n * field navigation (`onEnterKey`), a `leading` slot, Expand (`expandable`), a hosted editor\n * (`editor`, `./editor-slot.ts`), the pre-hydration keep, and the dictation handle: the forwarded\n * node is a real `HTMLTextAreaElement` carrying `startDictation()` / `stopDictation()` /\n * `isDictating()` / `requestClose()` / `isTranscribing()`; a refusal always returns a named reason\n * with a sentence AND says it on screen (notify + `onTranscriptionError`).\n */\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { composerKeyIntent, intentTakesTheKey } from \"@ai-matrx/kit/composer-keys\";\nimport { useMediaQuery } from \"@ai-matrx/kit/media-query\";\nimport { copyText } from \"@ai-matrx/kit/clipboard\";\nimport { cn } from \"../cn\";\nimport { Label } from \"../label\";\nimport { Dialog, DialogContent, DialogTitle } from \"../dialog\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../popover\";\nimport { TapTargetButtonSolid } from \"../tap-target/tap-target-button\";\nimport { MaximizeTapButton, MoreHorizontalTapButton } from \"../tap-target/tap-buttons\";\nimport { CopyIcon, Loader2Icon, Maximize2Icon, MicIcon, SendIcon, SlidersHorizontalIcon } from \"../icons\";\nimport { UNCONFIGURED } from \"../stand-in-notice\";\nimport { DENSE_SIZES, controlSizes, fitFieldControls } from \"./control-fit\";\nimport {\n INLINE_CONTROLS_MIN_HEIGHT_PX,\n TAP_HALF_GAP_PX,\n inlineControlsFieldPadding,\n proTextareaClusterPlacement,\n type ProTextareaControls,\n} from \"./control-placement\";\nimport type { ProTextareaEditorSlot } from \"./editor-slot\";\nimport {\n announceMissingPort,\n resolveHookPorts,\n splitAddOnProps,\n useWritingFieldAddOns,\n type WritingFieldApi,\n} from \"./add-ons\";\nimport { FieldMenuRow, FinalizingStrip, ListeningStrip, VoiceProtectionDialog, micAriaLabel } from \"./voice-chrome\";\nimport type { ProTextareaAddOnProps } from \"./index\";\nimport { Textarea } from \"../controls/controls\";\n\nconst FILL_HEIGHT_REGEX = /(?:^|\\s)(h-full|h-dvh|flex-1|grow|inset-0|min-h-0)(?:\\s|$)/;\n\n/** Detect when the caller wants the field to stretch to its container. */\nfunction wantsFillHeight(className?: string, wrapperClassName?: string): boolean {\n return FILL_HEIGHT_REGEX.test(className ?? \"\") || FILL_HEIGHT_REGEX.test(wrapperClassName ?? \"\");\n}\n\n/** Why `startDictation()` refused. Every value is a real, nameable condition. */\nexport type DictationRefusalReason =\n | \"voice-disabled\"\n | \"field-disabled\"\n | \"no-microphone\"\n | \"recorder-unavailable\"\n | \"finalizing\";\n\nexport type DictationStartResult =\n | { started: true }\n | { started: false; reason: DictationRefusalReason; message: string };\n\n/**\n * Real HTMLTextAreaElement with the expandos ProTextarea sets one commit after mount (always call\n * them with `?.()`). Expandos, not `useImperativeHandle`: hundreds of hosts forward this ref\n * expecting a genuine element (`focus()`, `select()`, `selectionStart`, form association).\n */\nexport interface ProTextareaElement extends HTMLTextAreaElement {\n requestClose?: () => void;\n isTranscribing?: () => boolean;\n startDictation?: () => Promise<DictationStartResult>;\n stopDictation?: () => void;\n isDictating?: () => boolean;\n}\n\nexport interface ProTextareaProps\n extends React.TextareaHTMLAttributes<HTMLTextAreaElement>,\n ProTextareaAddOnProps {\n onTranscriptionComplete?: (text: string) => void;\n onTranscriptionError?: (error: string) => void;\n /** If true, appends to existing text; if false, replaces. Default: true. */\n appendTranscript?: boolean;\n /** Voice input. ON by default; `false` when the host owns recording itself. */\n enableVoice?: boolean;\n autoGrow?: boolean;\n minHeight?: number;\n maxHeight?: number;\n wrapperClassName?: string;\n /** Called when it's safe to close/unmount (after confirm or once recording/transcription completes). */\n onRequestClose?: () => void;\n /** Warn before unmount during recording/transcription. Default: true. */\n protectTranscription?: boolean;\n /** Copy rows in \"…\". Default: true. */\n showCopyButton?: boolean;\n /** Text stats in \"…\" + the pinned stats bar. OFF by default. */\n enableTextStats?: boolean;\n /** Initial pinned stats bar display when text stats are enabled. Default: true. */\n defaultShowTextStatsBar?: boolean;\n onSubmit?: () => void;\n submitDisabled?: boolean;\n allowEmptySubmit?: boolean;\n isSubmitting?: boolean;\n /** Accessible/tooltip label for the submit button. Default: \"Send\". */\n submitLabel?: string;\n /** The submit button's VISIBLE word (\"Build agent\"): a labeled solid pill instead of the send glyph. */\n submitText?: string;\n submitIcon?: React.ReactNode;\n submitOnCmdEnter?: boolean;\n submitOnEnter?: boolean;\n /** Field-navigation mode: plain Enter calls this; Shift+Enter / ⌘+Enter insert a newline. */\n onEnterKey?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;\n auxiliaryControlsTabIndex?: number;\n auxiliaryControlsLabel?: string;\n /** Dense-form label inside the border (use only on a `bg-card` surface). */\n floatingLabel?: string;\n /** The host surface draws frame, fill and focus (a document pane, a card body) — no border, no ring. */\n bare?: boolean | undefined;\n /** Markdown chords + selection toolbar. Default: on for a long-form box. */\n markdownFormatting?: boolean;\n /** Draw the mic + \"…\" cluster inside this element; `\"none\"`: the host already carries them. */\n controlsHost?: HTMLElement | null | \"none\";\n /** Host a different editor in place of the <textarea> (`./editor-slot.ts`). */\n editor?: ProTextareaEditorSlot;\n /** Expand button (in the control row) that opens the same field large. Off by default. */\n expandable?: boolean;\n /** `\"row\"` (default): a reserved row under the text. `\"inline\"`: the chat-composer shape. */\n controls?: ProTextareaControls;\n /** `field` (default) or `hero` (a front door's one big composer). */\n appearance?: \"field\" | \"hero\";\n /** Content at the START of the reserved control row. */\n leading?: React.ReactNode;\n /** `all` (default): \"…\" carries the shared action registry. `none`: only the field's own controls. */\n menuActions?: \"all\" | \"none\";\n}\n\nexport const ProTextarea = React.forwardRef<HTMLTextAreaElement, ProTextareaProps>(\n (\n {\n className,\n wrapperClassName,\n onTranscriptionComplete,\n onTranscriptionError,\n appendTranscript = true,\n menuActions = \"all\",\n enableVoice = true,\n autoGrow = false,\n minHeight,\n maxHeight,\n value,\n onChange,\n onKeyDown,\n disabled,\n onRequestClose,\n protectTranscription = true,\n showCopyButton = true,\n enableTextStats = false,\n defaultShowTextStatsBar = true,\n onSubmit,\n submitDisabled,\n allowEmptySubmit = false,\n isSubmitting = false,\n submitLabel = \"Send\",\n submitText,\n submitIcon,\n submitOnCmdEnter,\n submitOnEnter = false,\n onEnterKey,\n auxiliaryControlsTabIndex,\n auxiliaryControlsLabel,\n floatingLabel,\n bare,\n id: idProp,\n placeholder,\n style,\n editor,\n markdownFormatting,\n expandable = false,\n controls,\n controlsHost,\n appearance = \"field\",\n leading,\n ...rest\n },\n ref,\n ) => {\n const addOns = useWritingFieldAddOns();\n const ports = resolveHookPorts(addOns);\n const { dom: props, addOnProps } = splitAddOnProps(\n rest as Record<string, unknown>,\n addOns.propNames,\n ) as { dom: React.TextareaHTMLAttributes<HTMLTextAreaElement>; addOnProps: Record<string, unknown> };\n const notify = ports.notify;\n\n // A one-row box takes the inline controls on its own; an explicit `controls` still wins.\n const resolvedControls: ProTextareaControls =\n controls ?? (props.rows !== undefined && Number(props.rows) <= 1 ? \"inline\" : \"row\");\n const inlineControls = resolvedControls === \"inline\" && !editor;\n const [smallType, setSmallType] = React.useState(false);\n const denseInline = inlineControls && smallType;\n const inlineMinHeight = denseInline ? DENSE_SIZES.box + 2 * TAP_HALF_GAP_PX : INLINE_CONTROLS_MIN_HEIGHT_PX;\n const effectiveMinHeight = inlineControls ? Math.max(minHeight ?? 0, inlineMinHeight) : minHeight;\n // Both measured boxes are watched through CALLBACK refs: the field subtree can mount again (the\n // right-click wrapper wraps it once it loads).\n const clusterRef = React.useRef<HTMLDivElement | null>(null);\n const [clusterWidth, setClusterWidth] = React.useState(0);\n const clusterObserver = React.useRef<ResizeObserver | null>(null);\n // Stable, so React re-runs it only when the node changes (a new function each render re-measured in\n // every commit, which loops when the measured size moves with the field's own controls).\n const setClusterNode = React.useCallback((node: HTMLDivElement | null) => {\n if (clusterRef.current === node) return;\n clusterRef.current = node;\n clusterObserver.current?.disconnect();\n clusterObserver.current = null;\n if (!node || typeof ResizeObserver === \"undefined\") return;\n const measure = () => setClusterWidth(node.offsetWidth);\n measure();\n clusterObserver.current = new ResizeObserver(measure);\n clusterObserver.current.observe(node);\n }, []);\n const fieldBoxRef = React.useRef<HTMLDivElement | null>(null);\n const [fieldBoxWidth, setFieldBoxWidth] = React.useState(0);\n const fieldBoxObserver = React.useRef<ResizeObserver | null>(null);\n // Stable, so React re-runs it only when the node changes (a new function each render re-measured in\n // every commit, which loops when the measured size moves with the field's own controls).\n const setFieldBoxNode = React.useCallback((node: HTMLDivElement | null) => {\n if (fieldBoxRef.current === node) return;\n fieldBoxRef.current = node;\n fieldBoxObserver.current?.disconnect();\n fieldBoxObserver.current = null;\n if (!node || typeof ResizeObserver === \"undefined\") return;\n const measure = () => {\n setFieldBoxWidth(node.offsetWidth);\n const field = node.querySelector(\"textarea\");\n if (field) setSmallType(Number.parseFloat(getComputedStyle(field).fontSize) < 14);\n };\n measure();\n fieldBoxObserver.current = new ResizeObserver(measure);\n fieldBoxObserver.current.observe(node);\n }, []);\n React.useEffect(\n () => () => {\n clusterObserver.current?.disconnect();\n fieldBoxObserver.current?.disconnect();\n },\n [],\n );\n const coarsePointer = useMediaQuery(\"(pointer: coarse)\");\n const openAudioSettings = ports.useOpenAudioSettings();\n const generatedId = React.useId();\n const inputId = idProp ?? (floatingLabel ? generatedId : undefined);\n const [isFocused, setIsFocused] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n const [expandOpen, setExpandOpen] = React.useState(false);\n const [overflowing, setOverflowing] = React.useState(false);\n const [menuOpen, setMenuOpen] = React.useState(false);\n const [statsOpen, setStatsOpen] = React.useState(false);\n const [showTextStatsBar, setShowTextStatsBar] = React.useState(defaultShowTextStatsBar);\n // The element ref is ALWAYS our own, merged into the host's forwarded ref (a CALLBACK ref left\n // `.current` undefined and every internal feature returned silently — RC-B6).\n const internalRef = React.useRef<HTMLTextAreaElement | null>(null);\n const textareaRef = internalRef;\n const setTextareaRef = (node: HTMLTextAreaElement | null) => {\n internalRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) (ref as React.MutableRefObject<HTMLTextAreaElement | null>).current = node;\n };\n\n // Markdown formatting for a long-form box (the element mirrored into state once per mount).\n const formattingOn =\n markdownFormatting ??\n (!editor && !submitOnEnter && (props.rows === undefined || Number(props.rows) >= 2));\n const [formatElement, setFormatElement] = React.useState<HTMLTextAreaElement | null>(null);\n React.useLayoutEffect(() => {\n if (internalRef.current !== formatElement) setFormatElement(internalRef.current);\n });\n ports.useFormatting(formatElement, formattingOn, addOnProps);\n\n // Auto-grow: scrollHeight excludes the border; add it so the last line never hides.\n React.useEffect(() => {\n if (!autoGrow || !textareaRef.current) return;\n const textarea = textareaRef.current;\n textarea.style.height = \"auto\";\n let newHeight = textarea.scrollHeight + (textarea.offsetHeight - textarea.clientHeight);\n if (effectiveMinHeight) newHeight = Math.max(newHeight, effectiveMinHeight);\n if (maxHeight) newHeight = Math.min(newHeight, maxHeight);\n textarea.style.height = `${newHeight}px`;\n }, [value, autoGrow, effectiveMinHeight, maxHeight, clusterWidth]);\n\n /** Write through React's own change path; true when the field now holds `newValue`. */\n const pushToTextarea = React.useCallback(\n (newValue: string): boolean => {\n if (editor) return editor.handle.current?.write(newValue) ?? false;\n const el = textareaRef.current;\n if (!el) return false;\n const setter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, \"value\")?.set;\n if (!setter) return false;\n setter.call(el, newValue);\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n return el.value === newValue;\n },\n [editor],\n );\n\n // THE PRE-HYDRATION KEEP: text typed into a server-rendered box before hydration is handed to\n // the host through its own onChange (lane P, 2026-10-07).\n const keepPreHydrationText = React.useEffectEvent(() => {\n const el = internalRef.current;\n if (editor || !el || !onChange) return;\n const typed = el.value;\n if (!typed || typed === String(value ?? \"\")) return;\n el.value = \"\";\n pushToTextarea(typed);\n });\n React.useLayoutEffect(() => {\n keepPreHydrationText();\n }, []);\n\n const getLiveText = React.useCallback(\n () =>\n editor\n ? (editor.handle.current?.getValue() ?? String(value ?? \"\"))\n : (textareaRef.current?.value ?? String(value ?? \"\")),\n [editor, value],\n );\n\n // Voice rides the host's ONE recorder through the voice port.\n const voice = ports.useVoice({\n enabled: enableVoice,\n instanceId: inputId,\n label: typeof floatingLabel === \"string\" ? floatingLabel : undefined,\n getValue: getLiveText,\n writeValue: pushToTextarea,\n appendTranscript,\n protect: protectTranscription,\n onRequestClose,\n onTranscriptionComplete,\n onTranscriptionError,\n });\n const { isRecording, isTranscribing } = voice;\n const isAudioAvailable = voice.microphone;\n\n const refuseDictation = React.useCallback(\n (reason: DictationRefusalReason, message: string): DictationStartResult => {\n notify.error(message);\n onTranscriptionError?.(message);\n return { started: false, reason, message };\n },\n [notify, onTranscriptionError],\n );\n\n /** The imperative half of the mic button: the same checks, then the same start. */\n const startDictation = React.useCallback(async (): Promise<DictationStartResult> => {\n if (!enableVoice)\n return refuseDictation(\"voice-disabled\", \"Voice input is turned off for this field, so it cannot start dictating.\");\n if (disabled) return refuseDictation(\"field-disabled\", \"This field is disabled, so it cannot start dictating.\");\n if (!isAudioAvailable)\n return refuseDictation(\"no-microphone\", \"No microphone is available in this browser, so dictation cannot start.\");\n if (!voice.available)\n return refuseDictation(\n \"recorder-unavailable\",\n \"Voice recording is unavailable on this screen, so dictation cannot start.\",\n );\n if (isTranscribing && !isRecording)\n return refuseDictation(\n \"finalizing\",\n \"The last recording is still being transcribed. Wait for it to finish, then start again.\",\n );\n await voice.startDictation();\n return { started: true };\n }, [enableVoice, disabled, isAudioAvailable, voice, isTranscribing, isRecording, refuseDictation]);\n\n React.useEffect(() => {\n const el = textareaRef.current as ProTextareaElement | null;\n if (!el) return;\n el.requestClose = voice.requestClose;\n el.isTranscribing = () => isTranscribing;\n el.startDictation = startDictation;\n el.stopDictation = voice.stopDictation;\n el.isDictating = () => isRecording;\n }, [voice.requestClose, isTranscribing, startDictation, voice.stopDictation, isRecording]);\n\n const valueAsString = String(value ?? \"\");\n const hasContent = valueAsString.trim().length > 0;\n const canSubmit = !!onSubmit && (hasContent || allowEmptySubmit) && !submitDisabled && !isSubmitting && !disabled;\n const cmdEnterEnabled = submitOnCmdEnter ?? !!onSubmit;\n const triggerSubmit = React.useCallback(() => {\n if (canSubmit && onSubmit) onSubmit();\n }, [canSubmit, onSubmit]);\n\n const insertNewlineAtCursor = React.useCallback(() => {\n const el = textareaRef.current;\n if (!el) return;\n const start = el.selectionStart ?? el.value.length;\n const end = el.selectionEnd ?? el.value.length;\n pushToTextarea(el.value.slice(0, start) + \"\\n\" + el.value.slice(end));\n const caret = start + 1;\n requestAnimationFrame(() => {\n const node = textareaRef.current;\n if (!node) return;\n node.selectionStart = caret;\n node.selectionEnd = caret;\n });\n }, [pushToTextarea]);\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n // Typing hides the hover controls until the mouse moves again (like the OS cursor).\n if (isHovered) setIsHovered(false);\n onKeyDown?.(e);\n if (e.defaultPrevented || e.key !== \"Enter\") return;\n const withCmd = e.metaKey || e.ctrlKey;\n if (onEnterKey) {\n if (e.shiftKey) return;\n e.preventDefault();\n if (withCmd) insertNewlineAtCursor();\n else onEnterKey(e);\n return;\n }\n if (!onSubmit) return;\n if (cmdEnterEnabled && withCmd) {\n e.preventDefault();\n triggerSubmit();\n return;\n }\n const intent = composerKeyIntent(\n {\n key: e.key,\n shiftKey: e.shiftKey,\n metaKey: e.metaKey,\n ctrlKey: e.ctrlKey,\n isComposing: e.nativeEvent.isComposing,\n },\n { submitOnEnter },\n );\n if (!intentTakesTheKey(intent)) return;\n e.preventDefault();\n triggerSubmit();\n },\n [isHovered, onKeyDown, onEnterKey, insertNewlineAtCursor, onSubmit, cmdEnterEnabled, submitOnEnter, triggerSubmit],\n );\n\n const fieldApi: WritingFieldApi = {\n kind: \"textarea\",\n text: valueAsString,\n getText: getLiveText,\n write: pushToTextarea,\n getSelection: () => {\n const handle = editor?.handle.current ?? null;\n if (handle) return handle.getSelection();\n const el = textareaRef.current;\n return { start: el?.selectionStart ?? 0, end: el?.selectionEnd ?? 0 };\n },\n getElement: () => textareaRef.current,\n addOnProps,\n showCopyButton,\n flashCopied: () => undefined,\n };\n\n const showControls =\n (appearance === \"hero\" ||\n (typeof HTMLElement !== \"undefined\" && controlsHost instanceof HTMLElement) ||\n isHovered ||\n isFocused ||\n isRecording ||\n isTranscribing) &&\n !disabled;\n const isVoiceDisabled = !isAudioAvailable || disabled || (isTranscribing && !isRecording);\n\n const addOnMenuItems = addOns.Menu\n ? (addOns.menuHasItems?.({ kind: \"textarea\", addOnProps, showCopyButton }) ?? true)\n : false;\n // The menu's OWN actions; \"…\" also shows to hold whatever did not fit.\n const showMenu = !disabled && menuActions !== \"none\" && (showCopyButton || addOnMenuItems);\n // THE ONE FITTING RULE (./control-fit.ts), shared with ProInput.\n const micOffered = enableVoice && isAudioAvailable;\n const fit = fitFieldControls({\n fieldWidth: fieldBoxWidth,\n sizes: controlSizes({ coarse: coarsePointer, dense: denseInline }),\n fixedPx: inlineControls ? 12 + 2 * TAP_HALF_GAP_PX : 8,\n minText: inlineControls ? undefined : 0,\n hasSubmit: !!onSubmit,\n menuHasOwnItems: showMenu,\n mic: micOffered,\n clear: false,\n expand: expandable && !editor && overflowing,\n });\n const voiceBusyNow = isRecording || isTranscribing;\n const micInline = micOffered && (fit.mic === \"inline\" || voiceBusyNow);\n const voiceInMenu = micOffered && !micInline;\n const expandInMenu = fit.folded.includes(\"expand\");\n const menuShown =\n !disabled && (showMenu || voiceInMenu || expandInMenu || (menuActions === \"none\" && enableVoice));\n const audioSettingsInMenu = menuShown && enableVoice;\n const hasCoarseControls = (enableVoice && isAudioAvailable && !disabled) || showMenu;\n const Stats = addOns.TextStats;\n const showTextStats = enableTextStats && showMenu && !!Stats;\n React.useEffect(() => {\n if (enableTextStats && !addOns.TextStats) announceMissingPort(\"TextStats\");\n }, [enableTextStats, addOns.TextStats]);\n const showPinnedTextStatsBar = showTextStats && showTextStatsBar;\n // An auto-growing box sizes itself to its text, so it never fills its host's height.\n const fillHeight = !autoGrow && wantsFillHeight(className, wrapperClassName);\n\n React.useEffect(() => {\n if (!expandable || editor) return;\n const el = internalRef.current;\n if (!el) return;\n const measure = () => setOverflowing(el.scrollHeight > el.clientHeight + 2);\n measure();\n const observer = new ResizeObserver(measure);\n observer.observe(el);\n return () => observer.disconnect();\n }, [expandable, editor, value]);\n\n const isInvalid = props[\"aria-invalid\"] === true || props[\"aria-invalid\"] === \"true\";\n const labelFloated = isFocused || valueAsString.length > 0;\n\n const hero = appearance === \"hero\";\n const fieldClassName = cn(\n hero\n ? \"flex w-full border border-border bg-card px-5 pt-4 pb-3 text-base leading-7 text-foreground placeholder:text-muted-foreground shadow-[0_1px_2px_rgb(0_0_0/0.05),0_12px_32px_-12px_rgb(0_0_0/0.22)] transition-[border-color,box-shadow] duration-200\"\n : \"flex w-full border border-border bg-card px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground\",\n showPinnedTextStatsBar\n ? hero\n ? \"rounded-2xl sm:rounded-b-none sm:border-b-0\"\n : \"rounded-md sm:rounded-b-none sm:border-b-0\"\n : hero\n ? \"rounded-2xl\"\n : \"rounded-md\",\n // THE FIELD FOCUS (Arman 2026-10-21): border takes the ring + the one halo token.\n \"focus-visible:outline-none focus-visible:border-primary focus-visible:ring-[3px] focus-visible:ring-primary/15\",\n \"disabled:cursor-not-allowed disabled:text-disabled-foreground\",\n fillHeight ? \"min-h-0 flex-1 resize-none overflow-y-auto\" : \"resize-y\",\n autoGrow && \"resize-none overflow-y-auto\",\n hero ? \"pr-5\" : \"pr-3\",\n className,\n // AFTER the caller's className: the reserved control row always wins (a floor, never a ceiling).\n !inlineControls &&\n !controlsHost &&\n (hasCoarseControls || onSubmit) &&\n (editor?.singleLine && !onSubmit\n ? \"pr-24 pointer-coarse:pr-32\"\n : hero\n ? \"pb-[max(3.5rem,var(--matrx-textarea-end,0px))]\"\n : \"pb-[max(2.75rem,var(--matrx-textarea-end,0px))]\"),\n );\n const reservesRow = !inlineControls && !controlsHost && (hasCoarseControls || !!onSubmit) && !editor?.singleLine;\n const fieldStyle: React.CSSProperties = {\n ...style,\n minHeight: effectiveMinHeight !== undefined ? `${effectiveMinHeight}px` : style?.minHeight,\n maxHeight: maxHeight !== undefined ? `${maxHeight}px` : style?.maxHeight,\n ...(inlineControls ? inlineControlsFieldPadding(clusterWidth, inlineMinHeight) : {}),\n };\n\n const closeMenu = () => setMenuOpen(false);\n const ownRows =\n expandInMenu || voiceInMenu || audioSettingsInMenu ? (\n <>\n {expandInMenu ? (\n <FieldMenuRow\n icon={<Maximize2Icon />}\n onClick={() => {\n closeMenu();\n setExpandOpen(true);\n }}\n >\n Expand\n </FieldMenuRow>\n ) : null}\n {voiceInMenu ? (\n <FieldMenuRow\n icon={<MicIcon />}\n disabled={isVoiceDisabled}\n onClick={() => {\n closeMenu();\n void voice.handleVoiceClick();\n }}\n >\n Voice input\n </FieldMenuRow>\n ) : null}\n {audioSettingsInMenu ? (\n <FieldMenuRow\n icon={<SlidersHorizontalIcon />}\n onClick={() => {\n closeMenu();\n openAudioSettings();\n }}\n >\n Audio settings\n </FieldMenuRow>\n ) : null}\n {showMenu ? <div className=\"my-1 h-px bg-border\" role=\"separator\" /> : null}\n </>\n ) : null;\n const trailingRows =\n showTextStats && Stats ? (\n <>\n <div className=\"my-1 h-px bg-border\" role=\"separator\" />\n <Stats.MenuItems\n showStatsBar={showTextStatsBar}\n onToggleStatsBar={() => setShowTextStatsBar((prev) => !prev)}\n onOpenStatsPanel={() => setStatsOpen(true)}\n />\n </>\n ) : null;\n const Menu = addOns.Menu;\n const menuBody =\n statsOpen && Stats ? (\n <div className=\"w-56\">\n <Stats.Panel text={valueAsString} onBack={() => setStatsOpen(false)} onClose={closeMenu} />\n </div>\n ) : Menu && menuActions !== \"none\" ? (\n <Menu field={fieldApi} ownRows={ownRows} trailingRows={trailingRows} close={closeMenu} />\n ) : (\n <StandInMenu field={fieldApi} ownRows={ownRows} trailingRows={trailingRows} close={closeMenu} registry={menuActions !== \"none\"} />\n );\n\n const cluster = (\n <div\n ref={setClusterNode}\n onMouseDown={(e) => e.preventDefault()}\n data-matrx-tap-dense={denseInline ? \"\" : undefined}\n className={\n controlsHost\n ? \"flex items-center\"\n : cn(\n \"absolute z-10 flex items-center\",\n hero && !inlineControls\n ? \"bottom-2 right-2\"\n : proTextareaClusterPlacement(!!onSubmit, inlineControls ? \"inline\" : \"row\").className,\n editor?.singleLine && \"top-1/2 bottom-auto -translate-y-1/2\",\n )\n }\n >\n {fit.expandInline ? (\n <MaximizeTapButton\n tabIndex={auxiliaryControlsTabIndex}\n variant=\"transparent\"\n ariaLabel={auxiliaryControlsLabel ? `Expand ${auxiliaryControlsLabel}` : \"Expand\"}\n tooltip=\"Expand\"\n onClick={() => setExpandOpen(true)}\n className=\"text-muted-foreground\"\n />\n ) : null}\n {/* A GLASS PLANE (tap-target placement rule 1): it rides over the field's own text. */}\n <div\n data-matrx-glass-plane\n className={cn(\n \"flex items-center transition-opacity duration-200 focus-within:opacity-100 focus-within:pointer-events-auto\",\n \"pointer-coarse:opacity-100 pointer-coarse:pointer-events-auto\",\n showControls || menuOpen ? \"opacity-100\" : \"opacity-0 pointer-events-none\",\n )}\n >\n {micInline && addOns.MicButton ? (\n <addOns.MicButton\n tabIndex={auxiliaryControlsTabIndex}\n onMicClick={() => void voice.handleVoiceClick()}\n dense={denseInline}\n disabled={isVoiceDisabled}\n isRecording={isRecording}\n isTranscribing={isTranscribing}\n audioLevel={voice.audioLevel}\n micAriaLabel={micAriaLabel(isRecording, auxiliaryControlsLabel)}\n />\n ) : null}\n {menuShown && (\n <Popover\n open={menuOpen}\n onOpenChange={(open) => {\n setMenuOpen(open);\n if (!open) setStatsOpen(false);\n }}\n >\n <PopoverTrigger asChild>\n <MoreHorizontalTapButton\n tabIndex={auxiliaryControlsTabIndex}\n variant=\"transparent\"\n ariaLabel={auxiliaryControlsLabel ? `More options for ${auxiliaryControlsLabel}` : \"More options\"}\n tooltip=\"More\"\n className=\"text-muted-foreground\"\n />\n </PopoverTrigger>\n <PopoverContent\n /* sizing: fixed — the add-on body sizes itself (list, stats, agent panels) */\n align=\"end\"\n side=\"bottom\"\n sideOffset={6}\n className=\"w-auto max-w-none p-0\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n {menuBody}\n </PopoverContent>\n </Popover>\n )}\n </div>\n {onSubmit && (\n <TapTargetButtonSolid\n onClick={triggerSubmit}\n disabled={!canSubmit}\n ariaLabel={submitLabel}\n tooltip={submitLabel}\n label={submitText}\n icon={\n isSubmitting ? (\n <Loader2Icon className=\"h-4 w-4 animate-spin\" />\n ) : (\n (submitIcon ?? <SendIcon className=\"h-4 w-4\" />)\n )\n }\n />\n )}\n </div>\n );\n\n const field = (\n <div\n ref={setFieldBoxNode}\n className={cn(\"relative group\", wrapperClassName)}\n data-writing-field-host={addOns.Menu && addOns.useVoice ? undefined : UNCONFIGURED}\n onMouseEnter={() => setIsHovered(true)}\n onMouseMove={() => {\n if (!isHovered) setIsHovered(true);\n }}\n onMouseLeave={() => setIsHovered(false)}\n >\n <div className={cn(\"flex min-h-0 min-w-0 w-full flex-col\", fillHeight ? \"h-full flex-1\" : \"flex-1\")}>\n <div className={cn(\"relative min-w-0 w-full\", fillHeight && \"flex min-h-0 flex-1 flex-col\")}>\n {editor ? (\n editor.render({\n id: inputId,\n className: fieldClassName,\n style: fieldStyle,\n placeholder: floatingLabel ? undefined : placeholder,\n disabled,\n onFocus: () => setIsFocused(true),\n onBlur: () => setIsFocused(false),\n onKeyDown: () => {\n if (isHovered) setIsHovered(false);\n },\n })\n ) : (\n <Textarea\n variant={bare ? \"bare\" : \"field\"}\n data-keep-inset={bare ? \"\" : undefined}\n hero={hero}\n joinedBottom={showPinnedTextStatsBar}\n ref={setTextareaRef}\n id={inputId}\n placeholder={floatingLabel ? undefined : placeholder}\n className={cn(\"w-full\", fillHeight ? \"min-h-0 flex-1 resize-none overflow-y-auto\" : \"resize-y\", autoGrow && \"resize-none overflow-y-auto\", className)}\n reservedInlineEnd={inlineControls ? clusterWidth + 6 : 0}\n reservedBlockEnd={reservesRow ? hero ? 56 : 44 : 0}\n style={fieldStyle}\n value={value}\n onChange={onChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n {...props}\n />\n )}\n\n {expandable && !editor ? (\n <Dialog open={expandOpen} onOpenChange={setExpandOpen}>\n <DialogContent className=\"flex max-h-[90dvh] w-[min(56rem,calc(100vw-2rem))] max-w-none flex-col gap-3 sm:max-w-none\">\n <DialogTitle className=\"truncate\">{auxiliaryControlsLabel ?? floatingLabel ?? \"Text\"}</DialogTitle>\n {/* The SAME field, large: one value, one onChange. */}\n <ProTextarea\n {...(addOnProps as ProTextareaAddOnProps)}\n value={value}\n onChange={onChange}\n placeholder={placeholder}\n disabled={disabled}\n wrapperClassName=\"h-[min(70dvh,40rem)]\"\n className=\"h-full text-sm\"\n autoFocus\n />\n </DialogContent>\n </Dialog>\n ) : null}\n\n {floatingLabel && inputId && (\n <Label\n htmlFor={inputId}\n className={cn(\n \"absolute left-3 px-1 pointer-events-none transition-all duration-200 ease-in-out z-10 bg-transparent\",\n labelFloated ? \"-top-2 text-xs\" : \"top-3 text-sm\",\n isInvalid ? \"text-destructive\" : isFocused ? \"text-primary\" : \"text-muted-foreground\",\n disabled && \"text-disabled-foreground\",\n )}\n >\n {floatingLabel}\n </Label>\n )}\n\n {leading && reservesRow ? (\n <div\n data-pro-textarea-leading=\"\"\n onMouseDown={(e) => e.preventDefault()}\n className={cn(\"absolute z-10 flex items-center gap-1\", hero ? \"bottom-2 left-3\" : \"bottom-1 left-1\")}\n >\n {leading}\n </div>\n ) : null}\n {controlsHost === \"none\" ? null : controlsHost ? createPortal(cluster, controlsHost) : cluster}\n\n {enableVoice && isRecording && (\n <ListeningStrip\n liveTranscript={voice.liveTranscript}\n className={\n inlineControls\n ? \"inset-x-0 bottom-full mb-1.5 border border-border bg-card shadow-sm\"\n : cn(\"left-2 bottom-2 bg-primary/10 dark:bg-primary/15\", onSubmit ? \"right-32\" : \"right-24\")\n }\n />\n )}\n {enableVoice && isTranscribing && !isRecording && (\n <FinalizingStrip className={inlineControls ? \"left-0 bottom-full mb-1.5\" : \"left-2 bottom-2\"} />\n )}\n </div>\n\n {voice.dialogs}\n <VoiceProtectionDialog voice={voice} />\n\n {/* Desktop-only: on a phone the counts row is clutter under every field. */}\n {showPinnedTextStatsBar && Stats ? (\n <div className=\"hidden sm:block\">\n <Stats.Bar text={valueAsString} />\n </div>\n ) : null}\n </div>\n </div>\n );\n\n const ContextMenu = addOns.ContextMenu;\n if (!ContextMenu) return field;\n return (\n <ContextMenu field={fieldApi} disabled={disabled}>\n {field}\n </ContextMenu>\n );\n },\n);\n\nProTextarea.displayName = \"ProTextarea\";\n\n/** \"…\" with no Menu port: the field's own rows plus a working Copy — announced as a stand-in. */\nexport function StandInMenu({\n field,\n ownRows,\n trailingRows,\n close,\n registry,\n}: {\n field: WritingFieldApi;\n ownRows: React.ReactNode;\n trailingRows: React.ReactNode;\n close: () => void;\n registry: boolean;\n}) {\n React.useEffect(() => {\n if (registry) announceMissingPort(\"Menu\");\n }, [registry]);\n return (\n <div className=\"flex w-48 flex-col p-1\" data-writing-field-host={registry ? UNCONFIGURED : undefined}>\n {ownRows}\n {registry && field.showCopyButton ? (\n <FieldMenuRow\n icon={<CopyIcon />}\n onClick={() => {\n const text = field.getText();\n close();\n if (text) void copyText(text).then((ok) => ok && field.flashCopied());\n }}\n >\n Copy\n </FieldMenuRow>\n ) : null}\n {trailingRows}\n </div>\n );\n}\n","/**\n * THE ONE FITTING RULE for ProInput and ProTextarea's controls (2026-10-15).\n *\n * A writing field's controls never take the room the text needs, and a control\n * that does not fit is never deleted — it moves inside \"…\". Until this module\n * each field had its own step-down rule: ProInput dropped its mic AND its \"…\"\n * outright below ~220px when it also had Clear + Send (voice, copy, clean-up and\n * read-aloud became unreachable), and on a phone a 110px field kept two letters\n * of text beside Clear and Send.\n *\n * The rule:\n * - REQUIRED controls always show: Send (the field's action) and \"…\" whenever\n * it holds anything.\n * - OPTIONAL controls show in priority order while the text keeps its floor;\n * the rest go inside \"…\". Folding runs from the lowest priority up: Expand,\n * then Clear, then the mic.\n * - There is no device chevron (Arman, 2026-10-16): the microphone choice is\n * a right-click / press-and-hold on the mic, and an \"Audio settings\" row in\n * \"…\" whenever \"…\" shows — so it never takes room here.\n * - A live recording always keeps its stop button inline (the caller forces it).\n *\n * Widths are the real rendered footprints per pointer and density (measured\n * 2026-10-15 on a fine pointer and a 375px phone), so a phone folds earlier\n * instead of being crushed.\n */\n\nexport type FoldableControl = \"mic\" | \"clear\" | \"expand\";\n\n/** How the mic shows: inline, inside \"…\", or not offered. */\nexport type MicFit = \"inline\" | \"folded\" | \"none\";\n\nexport interface ControlSizes {\n /** One tap box (Send, \"…\", Clear, Expand). */\n box: number;\n /** The mic button, its own 3px margins included. */\n mic: number;\n}\n\n/** 38px tap box; the mic is a 28px button plus its 3px margins. */\nexport const FINE_SIZES: ControlSizes = { box: 38, mic: 34 };\n/** Touch: the tap box keeps 38px of layout (the 44px hit area is invisible); the mic pads out. */\nexport const COARSE_SIZES: ControlSizes = { box: 38, mic: 46 };\n/** The dense field scope (`data-matrx-tap-dense`): a 24px pill in a 28px box. */\nexport const DENSE_SIZES: ControlSizes = { box: 28, mic: 28 };\n\nexport function controlSizes(opts: { coarse: boolean; dense: boolean }): ControlSizes {\n if (opts.dense) return DENSE_SIZES;\n return opts.coarse ? COARSE_SIZES : FINE_SIZES;\n}\n\n/** Below this field height the controls take the dense 28px size. */\nexport const DENSE_FIELD_MAX_HEIGHT_PX = 34;\n\nexport function isDenseField(fieldHeight: number): boolean {\n return fieldHeight > 0 && fieldHeight < DENSE_FIELD_MAX_HEIGHT_PX;\n}\n\n/**\n * The text's floor: half the field, never more than 140px and never less than\n * 48px (about five characters).\n */\nexport function minTextPx(fieldWidth: number): number {\n return Math.max(48, Math.min(140, Math.round(fieldWidth * 0.5)));\n}\n\nexport interface FitRequest {\n /** The field's measured width; 0 = not measured yet (first paint, jsdom) → everything that may be inline is. */\n fieldWidth: number;\n sizes: ControlSizes;\n /** Space the field always spends outside the controls: its left padding, a start icon, the text gap. */\n fixedPx?: number | undefined;\n /** The text floor; defaults to `minTextPx(fieldWidth)`. A reserved control row passes 0. */\n minText?: number | undefined;\n hasSubmit: boolean;\n /** The \"…\" menu has items of its own (copy, clean-up, read-aloud, agents…). */\n menuHasOwnItems: boolean;\n /** The field offers voice input. */\n mic: boolean;\n /** Clear is offered right now (the field has text). */\n clear: boolean;\n /** Expand is offered right now (the text overflows the box). */\n expand: boolean;\n}\n\nexport interface FitResult {\n mic: MicFit;\n clearInline: boolean;\n expandInline: boolean;\n /** Controls that live inside \"…\" because they did not fit. */\n folded: FoldableControl[];\n /** \"…\" shows: it has its own items or holds a folded control. */\n showMenu: boolean;\n /** Width every inline control takes together, px. */\n inlineWidth: number;\n}\n\nexport function fitFieldControls(req: FitRequest): FitResult {\n const { sizes } = req;\n const folded: FoldableControl[] = [];\n let mic: MicFit = req.mic ? \"inline\" : \"none\";\n let clearInline = req.clear;\n let expandInline = req.expand;\n\n const menuWillShow = () => req.menuHasOwnItems || folded.length > 0;\n const width = () =>\n (req.hasSubmit ? sizes.box : 0) +\n (menuWillShow() ? sizes.box : 0) +\n (mic === \"inline\" ? sizes.mic : 0) +\n (clearInline ? sizes.box : 0) +\n (expandInline ? sizes.box : 0);\n\n if (req.fieldWidth > 0) {\n const floor = req.minText ?? minTextPx(req.fieldWidth);\n const room = req.fieldWidth - (req.fixedPx ?? 0) - floor;\n const steps: Array<() => void> = [\n () => {\n if (expandInline) {\n expandInline = false;\n folded.push(\"expand\");\n }\n },\n () => {\n if (clearInline) {\n clearInline = false;\n folded.push(\"clear\");\n }\n },\n () => {\n if (mic === \"inline\") {\n mic = \"folded\";\n folded.push(\"mic\");\n }\n },\n ];\n for (const step of steps) {\n if (width() <= room) break;\n step();\n }\n }\n\n return {\n mic,\n clearInline,\n expandInline,\n folded,\n showMenu: menuWillShow(),\n inlineWidth: width(),\n };\n}\n","/**\n * WHERE PROTEXTAREA'S MIC + \"…\" CLUSTER SITS, and the rule that it never covers\n * text (the ProTextarea twin of `proInputReservedPadding.ts`, page-pass 2026-09-27).\n *\n * A textarea's lines run the full width, so the cluster cannot take a right\n * gutter; it sits in a bottom ROW the field reserves (`pb-11`) on every\n * pointer. Mic, \"…\" and the submit button share ONE flex row inset 4px from\n * the corner, so they sit as adjacent tap boxes — no hand-typed offset between\n * them (a 48px offset beside a 38px box left a 10px hole, 2026-10-05).\n */\nexport type ClusterRow = \"top\" | \"bottom\";\n\nexport interface ClusterPlacement {\n row: ClusterRow;\n /** Distance from the right edge, px (clears the submit button when they share a row). */\n rightPx: number;\n /** The rows the field reserves, per pointer kind. */\n reserved: { fine: ClusterRow[]; coarse: ClusterRow[] };\n /** The submit button's row and width, when there is one. */\n submit: { row: ClusterRow; widthPx: number } | null;\n /** The classes the cluster container adds. */\n className: string;\n}\n\n/** The tap box (`--matrx-tap-box`, 38px since 2026-10-01). */\nexport const SUBMIT_BUTTON_WIDTH_PX = 38;\n\n/** Where the cluster sits: a reserved row under the text, or inline at the end of the last line. */\nexport type ProTextareaControls = \"row\" | \"inline\";\n\n/** The tap pill's half-gap (`--matrx-tap-gap` / 2): a container edge is a neighbour (tap-target rule 4). */\nexport const TAP_HALF_GAP_PX = 3;\n\n/** One tap row plus the half-gap above and below it: the shortest an inline-controls box may be. */\nexport const INLINE_CONTROLS_MIN_HEIGHT_PX = SUBMIT_BUTTON_WIDTH_PX + 2 * TAP_HALF_GAP_PX;\n\n/**\n * The inline-controls text padding: centered on one tap row vertically (whatever\n * the host's line height — `1lh`), and a right gutter the measured cluster\n * width plus the half-gap, so text never runs under a control.\n */\nexport function inlineControlsFieldPadding(\n clusterWidthPx: number,\n /** The one-line height: 44px, or 34px for a dense (small-type) box. */\n minHeightPx: number = INLINE_CONTROLS_MIN_HEIGHT_PX,\n): {\n paddingTop: string;\n paddingBottom: string;\n paddingRight: string;\n} {\n const block = `calc((${minHeightPx}px - 1lh) / 2 - 1px)`;\n return {\n paddingTop: block,\n paddingBottom: block,\n paddingRight: `${clusterWidthPx + 2 * TAP_HALF_GAP_PX}px`,\n };\n}\n\nexport function proTextareaClusterPlacement(\n hasSubmit: boolean,\n controls: ProTextareaControls = \"row\",\n): ClusterPlacement {\n if (controls === \"inline\") {\n // Inset by the half-gap: a 38px box in a 44px-min box is dead-centre on\n // one line, and stays on the last line as the text grows.\n return {\n row: \"bottom\",\n rightPx: hasSubmit ? SUBMIT_BUTTON_WIDTH_PX + TAP_HALF_GAP_PX : TAP_HALF_GAP_PX,\n reserved: { fine: [\"bottom\"], coarse: [\"bottom\"] },\n submit: hasSubmit ? { row: \"bottom\", widthPx: SUBMIT_BUTTON_WIDTH_PX } : null,\n className: \"bottom-[3px] right-[3px]\",\n };\n }\n // One flex row inset 4px from the bottom-right corner: the hover part, then\n // the submit button. They are adjacent tap boxes in the SAME row, so the\n // cluster sits exactly one submit box (plus the inset) from the edge.\n return {\n row: \"bottom\",\n rightPx: hasSubmit ? SUBMIT_BUTTON_WIDTH_PX + 4 : 4,\n reserved: { fine: [\"bottom\"], coarse: [\"bottom\"] },\n submit: hasSubmit ? { row: \"bottom\", widthPx: SUBMIT_BUTTON_WIDTH_PX } : null,\n className: \"bottom-1 right-1\",\n };\n}\n\n/** Every way a placement lets the cluster cover text or the submit button. `[]` = sound. */\nexport function clusterPlacementProblems(p: ClusterPlacement): string[] {\n const problems: string[] = [];\n if (!p.reserved.fine.includes(p.row)) {\n problems.push(`on a fine pointer the ${p.row} row is not reserved, so the cluster covers text on hover`);\n }\n if (!p.reserved.coarse.includes(p.row)) {\n problems.push(`on a touch screen the ${p.row} row is not reserved, so the cluster covers text`);\n }\n if (p.submit && p.submit.row === p.row && p.rightPx < p.submit.widthPx) {\n problems.push(\"the cluster overlaps the submit button\");\n }\n return problems;\n}\n\n// What fits beside the text — and what moves inside \"…\" — is decided by THE\n// ONE FITTING RULE shared with ProInput: `proFieldControlFit.ts`.\n","\"use client\";\n\n/**\n * THE WRITING FIELD'S ADD-ON PORTS. `ProTextarea` / `ProInput` (this subpath) own the box: the\n * textarea/input, auto-grow, the control row, submit and Enter rules, the dictation handle, the\n * close-protection dialog. Everything that needs a recorder, a server, an agent or a menu engine\n * reaches the field through these ports, registered ONCE at the host root:\n *\n * <WritingFieldAddOnsProvider addOns={matrxWritingFieldAddOns}>…</WritingFieldAddOnsProvider>\n *\n * so design-system (layer 2) never imports chat, agents, rich-content, context-menu or a recorder.\n * A port the host did not register falls back to a stand-in that ANNOUNCES itself (law 4): one\n * console notice naming the port, and `data-writing-field-host=\"unconfigured\"` on the field.\n *\n * Hook ports (`useVoice`, `useFormatting`, `useOpenAudioSettings`) are called on every render, so\n * the registered object must be module-constant: the provider keeps the FIRST object it receives\n * and announces a swap instead of breaking hook order.\n *\n * One context for every bundle copy of this module (tsup inlines it into each entry), keyed like\n * `writing-box.tsx`.\n */\nimport * as React from \"react\";\nimport { announceStandIn } from \"../stand-in-notice\";\n\n/** Options the field hands its voice port — the same contract the app's `useMicField` takes. */\nexport interface WritingFieldVoiceOptions {\n /** Voice is on for this field (`enableVoice`). When false the port must stay inert. */\n enabled: boolean;\n instanceId?: string | undefined;\n label?: string | undefined;\n getValue: () => string;\n /** Write the next value through the field's own change path. */\n writeValue: (next: string) => boolean | void;\n appendTranscript?: boolean | undefined;\n join?: ((base: string, text: string) => string) | undefined;\n protect?: boolean | undefined;\n onRequestClose?: (() => void) | undefined;\n onTranscriptionComplete?: ((text: string) => void) | undefined;\n onTranscriptionError?: ((error: string) => void) | undefined;\n}\n\n/** What a voice port returns: recorder state plus the controls the field draws. */\nexport interface WritingFieldVoice {\n /** The browser exposes a microphone (device enumeration works). */\n microphone: boolean;\n /** A recorder is mounted on this route. */\n available: boolean;\n isRecording: boolean;\n isTranscribing: boolean;\n audioLevel: number;\n liveTranscript: string;\n handleVoiceClick: () => void | Promise<void>;\n startDictation: () => Promise<void>;\n stopDictation: () => void;\n requestClose: () => void;\n showProtectionDialog: boolean;\n setShowProtectionDialog: (open: boolean) => void;\n confirmClose: () => void;\n cancelClose: () => void;\n /** The port's own dialogs (troubleshooting), drawn beside the field. */\n dialogs?: React.ReactNode | undefined;\n}\n\nexport interface WritingFieldMicButtonProps {\n onMicClick: () => void;\n disabled?: boolean | undefined;\n isRecording?: boolean | undefined;\n isTranscribing?: boolean | undefined;\n audioLevel?: number | undefined;\n micAriaLabel?: string | undefined;\n tabIndex?: number | undefined;\n dense?: boolean | undefined;\n}\n\n/** The field as an add-on sees it. */\nexport interface WritingFieldApi {\n kind: \"textarea\" | \"input\";\n /** The value the host last rendered. */\n text: string;\n /** The live text (the DOM or the hosted editor), falling back to `text`. */\n getText: () => string;\n /** Write through the field's own change path; true when the field now holds `next`. */\n write: (next: string) => boolean;\n getSelection: () => { start: number; end: number };\n getElement: () => HTMLTextAreaElement | HTMLInputElement | null;\n /** The add-on props the caller passed (surfaceName, getApplicationScope, cleanup…), untouched. */\n addOnProps: Readonly<Record<string, unknown>>;\n showCopyButton: boolean;\n /** Show the brief \"Copied\" check on the \"…\" trigger (ProInput). */\n flashCopied: () => void;\n}\n\nexport interface WritingFieldMenuProps {\n field: WritingFieldApi;\n /** The field's own rows (Expand, Voice input, Audio settings, Clear) — place them in the list view. */\n ownRows: React.ReactNode;\n /** Rows the field adds after the add-on's list (text stats). */\n trailingRows: React.ReactNode;\n close: () => void;\n}\n\nexport interface WritingFieldContextMenuProps {\n field: WritingFieldApi;\n disabled?: boolean | undefined;\n children: React.ReactNode;\n}\n\nexport interface WritingFieldTextStats {\n Bar: React.ComponentType<{ text: string }>;\n MenuItems: React.ComponentType<{\n showStatsBar: boolean;\n onToggleStatsBar: () => void;\n onOpenStatsPanel: () => void;\n }>;\n Panel: React.ComponentType<{ text: string; onBack?: () => void; onClose?: () => void }>;\n}\n\nexport interface WritingFieldNotify {\n error: (message: string, options?: { description?: string }) => void;\n info: (message: string) => void;\n success: (message: string) => void;\n}\n\nexport interface WritingFieldAddOns {\n useVoice?: ((options: WritingFieldVoiceOptions) => WritingFieldVoice) | undefined;\n MicButton?: React.ComponentType<WritingFieldMicButtonProps> | undefined;\n useOpenAudioSettings?: (() => () => void) | undefined;\n /** Markdown chords + selection toolbar on a long-form box. */\n useFormatting?:\n | ((\n element: HTMLTextAreaElement | null,\n on: boolean,\n addOnProps: Readonly<Record<string, unknown>>,\n ) => void)\n | undefined;\n /** The \"…\" body (actions, agents, read-aloud). */\n Menu?: React.ComponentType<WritingFieldMenuProps> | undefined;\n /** Whether `Menu` has rows of its own for this field (so \"…\" shows). */\n menuHasItems?: ((field: Pick<WritingFieldApi, \"kind\" | \"addOnProps\" | \"showCopyButton\">) => boolean) | undefined;\n /** The right-click floor around the field. */\n ContextMenu?: React.ComponentType<WritingFieldContextMenuProps> | undefined;\n TextStats?: WritingFieldTextStats | undefined;\n notify?: WritingFieldNotify | undefined;\n /** Extra prop names the add-ons read (kept off the DOM element). */\n propNames?: readonly string[] | undefined;\n}\n\n/** Add-on prop names the field never spreads onto the DOM (the Matrx add-ons' props). */\nexport const ADD_ON_PROP_NAMES: readonly string[] = [\n \"surfaceName\",\n \"getApplicationScope\",\n \"sourceFeature\",\n \"surfaceContextItems\",\n \"enableBoundAgents\",\n \"enableContextMenu\",\n \"enableCleanup\",\n \"cleanupAgentId\",\n \"cleanupContextItems\",\n \"enableHelpWithThis\",\n \"helpMandateKey\",\n \"helpContextItems\",\n \"enableCustomAgent\",\n \"customAgentMandateKey\",\n \"customAgentContextItems\",\n \"uploadImage\",\n];\n\n/** Split a field's rest props into DOM props and add-on props. */\nexport function splitAddOnProps<T extends Record<string, unknown>>(\n props: T,\n extra: readonly string[] = [],\n): { dom: T; addOnProps: Record<string, unknown> } {\n const dom: Record<string, unknown> = {};\n const addOnProps: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(props)) {\n if (ADD_ON_PROP_NAMES.includes(key) || extra.includes(key)) addOnProps[key] = value;\n else dom[key] = value;\n }\n return { dom: dom as T, addOnProps };\n}\n\nconst KEY = Symbol.for(\"@ai-matrx/design-system/writing-field-add-ons\");\ntype Registry = Record<symbol, React.Context<WritingFieldAddOns | null> | undefined>;\nconst registry = globalThis as unknown as Registry;\nconst AddOnsContext: React.Context<WritingFieldAddOns | null> =\n registry[KEY] ?? (registry[KEY] = React.createContext<WritingFieldAddOns | null>(null));\n\n/** Mount once at the host's app root. The first `addOns` object is kept for the provider's life. */\nexport function WritingFieldAddOnsProvider({\n addOns,\n children,\n}: {\n addOns: WritingFieldAddOns;\n children: React.ReactNode;\n}) {\n const first = React.useRef(addOns);\n if (first.current !== addOns) {\n announceStandIn(\n \"writing-field-add-ons-swap\",\n \"WritingFieldAddOnsProvider received a different addOns object; the first one is kept (hook ports must be module-constant).\",\n );\n }\n return <AddOnsContext.Provider value={first.current}>{children}</AddOnsContext.Provider>;\n}\n\nconst EMPTY: WritingFieldAddOns = {};\n\n/** The registered add-ons (or none). */\nexport function useWritingFieldAddOns(): WritingFieldAddOns {\n return React.useContext(AddOnsContext) ?? EMPTY;\n}\n\n/** Announce a missing port once, in words naming what to register. */\nexport function announceMissingPort(port: string): void {\n announceStandIn(\n `writing-field:${port}`,\n `A writing field drew without its \"${port}\" add-on: the host did not register it in <WritingFieldAddOnsProvider addOns={{ ${port} }}>.`,\n );\n}\n\nconst INERT = () => undefined;\n\n/** The voice stand-in: no recorder, every control inert, announced when a field asks for voice. */\nexport function useStandInVoice(options: WritingFieldVoiceOptions): WritingFieldVoice {\n React.useEffect(() => {\n if (options.enabled) announceMissingPort(\"useVoice\");\n }, [options.enabled]);\n return {\n microphone: false,\n available: false,\n isRecording: false,\n isTranscribing: false,\n audioLevel: 0,\n liveTranscript: \"\",\n handleVoiceClick: INERT,\n startDictation: async () => undefined,\n stopDictation: INERT,\n requestClose: () => options.onRequestClose?.(),\n showProtectionDialog: false,\n setShowProtectionDialog: INERT,\n confirmClose: () => options.onRequestClose?.(),\n cancelClose: INERT,\n };\n}\n\n/** Notices with no host toast go to the console, announced once. */\nexport const STAND_IN_NOTIFY: WritingFieldNotify = {\n error: (message) => {\n announceMissingPort(\"notify\");\n console.error(`[writing-field] ${message}`);\n },\n info: (message) => {\n announceMissingPort(\"notify\");\n console.info(`[writing-field] ${message}`);\n },\n success: (message) => {\n announceMissingPort(\"notify\");\n console.info(`[writing-field] ${message}`);\n },\n};\n\nfunction useNoFormatting(): void {}\nfunction useNoAudioSettings(): () => void {\n return () => announceMissingPort(\"useOpenAudioSettings\");\n}\n\n/** The add-ons with every missing hook port filled by its stand-in (stable for a stable registry). */\nexport function resolveHookPorts(addOns: WritingFieldAddOns) {\n return {\n useVoice: addOns.useVoice ?? useStandInVoice,\n useFormatting: addOns.useFormatting ?? useNoFormatting,\n useOpenAudioSettings: addOns.useOpenAudioSettings ?? useNoAudioSettings,\n notify: addOns.notify ?? STAND_IN_NOTIFY,\n };\n}\n","\"use client\";\n\n/**\n * The field-owned voice chrome every writing field shares: the live \"Listening…\" strip, the\n * \"Finalizing…\" strip and the close-protection dialog. The recorder itself is the host's\n * (`useVoice` port); these only draw its state.\n */\nimport * as React from \"react\";\nimport { cn } from \"../cn\";\nimport { Tile } from \"../controls/surfaces\";\nimport { CheckIcon, Loader2Icon } from \"../icons\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n} from \"../alert-dialog\";\nimport type { WritingFieldVoice } from \"./add-ons\";\n\nexport function ListeningStrip({ liveTranscript, className }: { liveTranscript: string; className?: string }) {\n return (\n <div className={cn(\"absolute flex items-center gap-1.5 px-2 py-1 rounded-md\", className)}>\n <span aria-hidden className=\"w-2 h-2 bg-primary rounded-full flex-shrink-0 animate-pulse\" />\n <span className=\"type-secondary text-primary font-medium truncate\">\n {liveTranscript ? liveTranscript.slice(-60) : \"Listening...\"}\n </span>\n </div>\n );\n}\n\nexport function FinalizingStrip({ className }: { className?: string }) {\n return (\n <div\n className={cn(\n \"absolute flex items-center gap-1.5 px-2 py-1 rounded-md bg-blue-100 dark:bg-blue-900/30\",\n className,\n )}\n >\n <Loader2Icon className=\"w-3 h-3 animate-spin text-blue-600 dark:text-blue-400\" />\n <span className=\"type-secondary text-blue-600 dark:text-blue-400 font-medium\">Finalizing...</span>\n </div>\n );\n}\n\n/** Warns before a field closes while a recording or transcription is in flight. */\nexport function VoiceProtectionDialog({ voice }: { voice: WritingFieldVoice }) {\n const { isRecording, isTranscribing } = voice;\n const busy = isRecording || isTranscribing;\n return (\n <AlertDialog open={voice.showProtectionDialog} onOpenChange={voice.setShowProtectionDialog}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <div className=\"flex items-center gap-3 mb-2\">\n {busy ? (\n <>\n <Loader2Icon className=\"h-5 w-5 animate-spin text-blue-500\" />\n <AlertDialogTitle>\n {isRecording ? \"Recording in Progress\" : \"Transcription in Progress\"}\n </AlertDialogTitle>\n </>\n ) : (\n <>\n <CheckIcon className=\"h-5 w-5 text-green-500\" />\n <AlertDialogTitle>Voice Input Complete</AlertDialogTitle>\n </>\n )}\n </div>\n <AlertDialogDescription>\n {isRecording\n ? \"Your voice is currently being recorded. If you close now, the recording will be stopped and lost.\"\n : isTranscribing\n ? \"Your voice recording is currently being transcribed. If you close now, the transcription will be lost.\"\n : \"Your voice input has been processed successfully! You can now safely close this panel.\"}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n {busy ? (\n <>\n <AlertDialogCancel onClick={voice.cancelClose}>Cancel & Wait</AlertDialogCancel>\n <AlertDialogAction\n onClick={voice.confirmClose}\n className=\"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n >\n {isRecording ? \"Stop Recording\" : \"End Transcription\"}\n </AlertDialogAction>\n </>\n ) : (\n <AlertDialogAction onClick={voice.confirmClose}>Close</AlertDialogAction>\n )}\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n );\n}\n\n/** A menu row in the field's own part of \"…\" (Expand, Voice input, Audio settings, Clear). */\nexport function FieldMenuRow({\n icon,\n children,\n onClick,\n disabled,\n}: {\n icon: React.ReactNode;\n children: React.ReactNode;\n onClick: () => void;\n disabled?: boolean;\n}) {\n return (\n <Tile\n type=\"button\"\n disabled={disabled}\n onClick={onClick}\n variant=\"quiet\"\n className=\"w-full\"\n icon={icon}\n title={children}\n />\n );\n}\n\n/** The mic button a host without a voice port would get — never drawn: no port, no microphone. */\nexport function micAriaLabel(isRecording: boolean, label?: string): string {\n if (isRecording) return label ? `Stop recording for ${label}` : \"Stop recording\";\n return label ? `Start voice input for ${label}` : \"Start voice input\";\n}\n","\"use client\";\n\n/**\n * ProInput — THE one-line box a person writes words in (titles, names, short replies). Moved from\n * matrx-frontend `components/official/ProInput.tsx` (2026-10-22); its recorder, read-aloud, Copy\n * and Clean up arrive through the add-on ports (`./add-ons.tsx`).\n *\n * Built in: submit (`onSubmit`, ⌘/Ctrl+Enter, `submitOnEnter`), field navigation (`onEnterKey`),\n * Clear (`clearable` + `onClear`), `startIcon`, the iOS zoom guard (value text 16px), floating\n * label, the ONE fitting rule (`./control-fit.ts`), and the measured right padding that keeps the\n * hover cluster off the text (`./reserved-padding.ts`; a narrow field reveals it on focus).\n */\nimport * as React from \"react\";\nimport { useMediaQuery } from \"@ai-matrx/kit/media-query\";\nimport { cn } from \"../cn\";\nimport { Label } from \"../label\";\nimport { Field } from \"../controls/controls\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../popover\";\nimport {\n CheckTapButton,\n LoadingTapButton,\n MoreHorizontalTapButton,\n SendTapButton,\n XTapButton,\n} from \"../tap-target/tap-buttons\";\nimport { MicIcon, SlidersHorizontalIcon, XIcon } from \"../icons\";\nimport { UNCONFIGURED } from \"../stand-in-notice\";\nimport { PRO_INPUT_TEXT_GAP_PX, hoverRevealsCluster, reservedRightPaddingPx } from \"./reserved-padding\";\nimport { controlSizes, fitFieldControls, isDenseField } from \"./control-fit\";\nimport { resolveHookPorts, splitAddOnProps, useWritingFieldAddOns, type WritingFieldApi } from \"./add-ons\";\nimport { FieldMenuRow, FinalizingStrip, VoiceProtectionDialog, micAriaLabel } from \"./voice-chrome\";\nimport { StandInMenu } from \"./pro-textarea\";\nimport type { ProInputAddOnProps } from \"./index\";\n\n/** Real HTMLInputElement with optional expando methods set by ProInput. */\nexport interface ProInputElement extends HTMLInputElement {\n requestClose?: () => void;\n isTranscribing?: () => boolean;\n}\n\nexport interface ProInputProps extends React.InputHTMLAttributes<HTMLInputElement>, ProInputAddOnProps {\n onTranscriptionComplete?: (text: string) => void;\n onTranscriptionError?: (error: string) => void;\n /** If true, appends to existing text; if false, replaces. Default: true. */\n appendTranscript?: boolean;\n wrapperClassName?: string;\n onRequestClose?: () => void;\n /** Warn before unmount during recording/transcription. Default: true. */\n protectTranscription?: boolean;\n /** Show the Copy action inside the \"…\" menu. Default: true. */\n showCopyButton?: boolean;\n /** Voice input. Default true; false for search bars and filters. */\n enableVoice?: boolean;\n onSubmit?: () => void;\n submitDisabled?: boolean;\n isSubmitting?: boolean;\n /** Accessible/tooltip label for the submit button. Default: \"Send\". */\n submitLabel?: string;\n submitOnCmdEnter?: boolean;\n submitOnEnter?: boolean;\n /** Field-navigation mode: plain Enter calls this instead of submitting. */\n onEnterKey?: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n auxiliaryControlsTabIndex?: number;\n auxiliaryControlsLabel?: string;\n /** Optional leading icon/node — auto-applies left padding. */\n startIcon?: React.ReactNode;\n /** Shows a clear (×) control while the field has content. */\n clearable?: boolean;\n /** Called when the clear control is pressed. Defaults to clearing via `onChange`. */\n onClear?: () => void;\n /** Dense-form label inside the border (use only on a `bg-card` surface). */\n floatingLabel?: string;\n /** The host capsule draws frame, fill and focus (a search pill) — see Field `bare`. */\n bare?: boolean;\n}\n\nconst joinWithSpace = (base: string, text: string) => `${base}${base.endsWith(\" \") ? \"\" : \" \"}${text}`;\n\nexport const ProInput = React.forwardRef<HTMLInputElement, ProInputProps>(\n (\n {\n className,\n wrapperClassName,\n onTranscriptionComplete,\n onTranscriptionError,\n appendTranscript = true,\n value,\n onChange,\n onKeyDown,\n disabled,\n onRequestClose,\n protectTranscription = true,\n showCopyButton = true,\n enableVoice = true,\n onSubmit,\n submitDisabled,\n isSubmitting = false,\n submitLabel = \"Send\",\n submitOnCmdEnter,\n submitOnEnter = false,\n onEnterKey,\n auxiliaryControlsTabIndex,\n auxiliaryControlsLabel,\n startIcon,\n clearable = false,\n onClear,\n floatingLabel,\n bare,\n id: idProp,\n placeholder,\n type = \"text\",\n ...rest\n },\n ref,\n ) => {\n const addOns = useWritingFieldAddOns();\n const ports = resolveHookPorts(addOns);\n const { dom: props, addOnProps } = splitAddOnProps(rest as Record<string, unknown>, addOns.propNames) as {\n dom: React.InputHTMLAttributes<HTMLInputElement>;\n addOnProps: Record<string, unknown>;\n };\n const generatedId = React.useId();\n // Field owns its geometry; the legacy native size attribute must not become a skin.\n const { size: _nativeSize, width: nativeWidth, style: nativeStyle, ...fieldProps } = props;\n const inputId = idProp ?? (floatingLabel ? generatedId : undefined);\n const [hasCopied, setHasCopied] = React.useState(false);\n const [menuOpen, setMenuOpen] = React.useState(false);\n const [isFocused, setIsFocused] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n const internalRef = React.useRef<HTMLInputElement | null>(null);\n const clusterRef = React.useRef<HTMLDivElement | null>(null);\n const auxRef = React.useRef<HTMLDivElement>(null);\n const [clusterWidths, setClusterWidths] = React.useState({ cluster: 0, aux: 0 });\n const [inputWidth, setInputWidth] = React.useState(0);\n const [inputHeight, setInputHeight] = React.useState(0);\n const coarsePointer = useMediaQuery(\"(pointer: coarse)\");\n const clusterObserver = React.useRef<ResizeObserver | null>(null);\n // Stable, so React re-runs it only when the node changes (a new function each render re-measured in\n // every commit, which loops when the measured size moves with the field's own controls).\n const setClusterNode = React.useCallback((cluster: HTMLDivElement | null) => {\n if (clusterRef.current === cluster) return;\n clusterRef.current = cluster;\n clusterObserver.current?.disconnect();\n clusterObserver.current = null;\n if (!cluster || typeof ResizeObserver === \"undefined\") return;\n const measure = () => {\n const next = {\n cluster: cluster.getBoundingClientRect().width,\n aux: auxRef.current?.getBoundingClientRect().width ?? 0,\n };\n setClusterWidths((prev) => (prev.cluster === next.cluster && prev.aux === next.aux ? prev : next));\n };\n measure();\n clusterObserver.current = new ResizeObserver(measure);\n clusterObserver.current.observe(cluster);\n if (auxRef.current) clusterObserver.current.observe(auxRef.current);\n }, []);\n const inputRef = internalRef;\n const inputObserver = React.useRef<ResizeObserver | null>(null);\n // A merged CALLBACK ref: the host gets the element AND the field still measures that element.\n // Stable, so React re-runs it only when the node changes (a new function each render re-measured in\n // every commit, which loops when the measured size moves with the field's own controls).\n const setInputRef = React.useCallback((node: HTMLInputElement | null) => {\n if (internalRef.current !== node) {\n inputObserver.current?.disconnect();\n inputObserver.current = null;\n if (node && typeof ResizeObserver !== \"undefined\") {\n const measure = () => {\n const rect = node.getBoundingClientRect();\n setInputWidth(rect.width);\n setInputHeight(rect.height);\n };\n measure();\n inputObserver.current = new ResizeObserver(measure);\n inputObserver.current.observe(node);\n }\n }\n internalRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) (ref as React.MutableRefObject<HTMLInputElement | null>).current = node;\n }, [ref]);\n // THE PRE-HYDRATION KEEP (see ProTextarea).\n const keepPreHydrationText = React.useEffectEvent(() => {\n const el = inputRef.current;\n if (!el || !onChange) return;\n const typed = el.value;\n if (!typed || typed === String(value ?? \"\")) return;\n el.value = \"\";\n Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, \"value\")?.set?.call(el, typed);\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n });\n React.useLayoutEffect(() => {\n keepPreHydrationText();\n }, []);\n React.useEffect(\n () => () => {\n clusterObserver.current?.disconnect();\n inputObserver.current?.disconnect();\n },\n [],\n );\n const openAudioSettings = ports.useOpenAudioSettings();\n\n const pushToInput = React.useCallback((newValue: string): boolean => {\n const el = inputRef.current;\n if (!el) return false;\n const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, \"value\")?.set;\n if (!setter) return false;\n setter.call(el, newValue);\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n return el.value === newValue;\n }, []);\n\n const getLiveText = React.useCallback(() => inputRef.current?.value ?? String(value ?? \"\"), [value]);\n const voice = ports.useVoice({\n enabled: enableVoice,\n instanceId: inputId,\n getValue: getLiveText,\n writeValue: pushToInput,\n appendTranscript,\n join: joinWithSpace,\n protect: protectTranscription,\n onRequestClose,\n onTranscriptionComplete,\n onTranscriptionError,\n });\n const { isRecording, isTranscribing } = voice;\n const isAudioAvailable = voice.microphone;\n\n React.useEffect(() => {\n const el = inputRef.current as ProInputElement | null;\n if (!el) return;\n el.requestClose = voice.requestClose;\n el.isTranscribing = () => isTranscribing;\n }, [voice.requestClose, isTranscribing]);\n\n const flashCopied = React.useCallback(() => {\n setHasCopied(true);\n setTimeout(() => setHasCopied(false), 450);\n }, []);\n\n const handleClear = React.useCallback(() => {\n if (onClear) {\n onClear();\n return;\n }\n pushToInput(\"\");\n onChange?.({ target: { value: \"\" } } as React.ChangeEvent<HTMLInputElement>);\n }, [onClear, pushToInput, onChange]);\n\n const valueAsString = String(value ?? \"\");\n const hasContent = valueAsString.trim().length > 0;\n const canSubmit = !!onSubmit && hasContent && !submitDisabled && !isSubmitting && !disabled;\n const cmdEnterEnabled = submitOnCmdEnter ?? !!onSubmit;\n const triggerSubmit = React.useCallback(() => {\n if (canSubmit && onSubmit) onSubmit();\n }, [canSubmit, onSubmit]);\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (isHovered) setIsHovered(false);\n onKeyDown?.(e);\n if (e.defaultPrevented || e.key !== \"Enter\") return;\n const withCmd = e.metaKey || e.ctrlKey;\n if (onEnterKey) {\n if (e.shiftKey || withCmd) return;\n e.preventDefault();\n onEnterKey(e);\n return;\n }\n if (!onSubmit) return;\n if (cmdEnterEnabled && withCmd) {\n e.preventDefault();\n triggerSubmit();\n return;\n }\n if (submitOnEnter && !e.shiftKey && !withCmd) {\n e.preventDefault();\n triggerSubmit();\n }\n },\n [isHovered, onKeyDown, onEnterKey, onSubmit, cmdEnterEnabled, submitOnEnter, triggerSubmit],\n );\n\n const fieldApi: WritingFieldApi = {\n kind: \"input\",\n text: valueAsString,\n getText: getLiveText,\n write: pushToInput,\n getSelection: () => ({\n start: inputRef.current?.selectionStart ?? 0,\n end: inputRef.current?.selectionEnd ?? 0,\n }),\n getElement: () => inputRef.current,\n addOnProps: { ...addOnProps, type },\n showCopyButton,\n flashCopied,\n };\n\n const pointerReveals = hoverRevealsCluster(inputWidth) ? isHovered : isFocused;\n const showHoverControls = (pointerReveals || isRecording || isTranscribing) && !disabled;\n const isVoiceDisabled = !isAudioAvailable || disabled || (isTranscribing && !isRecording);\n const showMic = enableVoice && isAudioAvailable;\n const showClear = clearable && hasContent;\n const addOnMenuItems = addOns.Menu\n ? (addOns.menuHasItems?.({ kind: \"input\", addOnProps: fieldApi.addOnProps, showCopyButton }) ?? true)\n : false;\n const denseField = isDenseField(inputHeight);\n const fit = fitFieldControls({\n fieldWidth: inputWidth,\n sizes: controlSizes({ coarse: coarsePointer, dense: denseField }),\n fixedPx: (startIcon ? 36 : 12) + PRO_INPUT_TEXT_GAP_PX,\n hasSubmit: !!onSubmit,\n menuHasOwnItems: !disabled && (showCopyButton || addOnMenuItems || hasContent),\n mic: showMic,\n clear: showClear,\n expand: false,\n });\n const voiceBusy = isRecording || isTranscribing;\n const showMicInline = showMic && (fit.mic === \"inline\" || voiceBusy);\n const voiceInMenu = showMic && !showMicInline;\n const clearInline = showClear && fit.clearInline;\n const clearInMenu = showClear && !fit.clearInline;\n const showMenu = !disabled && (showCopyButton || addOnMenuItems || voiceInMenu || clearInMenu || hasContent);\n const audioSettingsInMenu = showMenu && enableVoice;\n const auxVisible = (showHoverControls || menuOpen) && (showMicInline || showMenu);\n const measuredRightPadding = reservedRightPaddingPx({\n clusterWidth: clusterWidths.cluster,\n auxWidth: clusterWidths.aux,\n auxVisible,\n });\n const isInvalid = props[\"aria-invalid\"] === true || props[\"aria-invalid\"] === \"true\";\n const labelFloated = isFocused || valueAsString.length > 0;\n const showVoiceStatus = isRecording || (isTranscribing && !isRecording);\n const closeMenu = () => setMenuOpen(false);\n\n const ownRows = (\n <>\n {clearInMenu ? (\n <FieldMenuRow\n icon={<XIcon />}\n onClick={() => {\n closeMenu();\n handleClear();\n }}\n >\n Clear\n </FieldMenuRow>\n ) : null}\n {voiceInMenu ? (\n <FieldMenuRow\n icon={<MicIcon />}\n disabled={isVoiceDisabled}\n onClick={() => {\n closeMenu();\n void voice.handleVoiceClick();\n }}\n >\n Voice input\n </FieldMenuRow>\n ) : null}\n {audioSettingsInMenu ? (\n <FieldMenuRow\n icon={<SlidersHorizontalIcon />}\n onClick={() => {\n closeMenu();\n openAudioSettings();\n }}\n >\n Audio settings\n </FieldMenuRow>\n ) : null}\n {clearInMenu || voiceInMenu || audioSettingsInMenu ? (\n <div className=\"my-1 h-px bg-border\" role=\"separator\" />\n ) : null}\n </>\n );\n const Menu = addOns.Menu;\n\n return (\n <div\n className={cn(\"relative group\", wrapperClassName)}\n data-writing-field-host={addOns.Menu && addOns.useVoice ? undefined : UNCONFIGURED}\n onMouseEnter={() => setIsHovered(true)}\n onMouseMove={() => {\n if (!isHovered) setIsHovered(true);\n }}\n onMouseLeave={() => setIsHovered(false)}\n >\n <Field\n ref={setInputRef}\n id={inputId}\n type={type}\n placeholder={floatingLabel ? undefined : placeholder}\n className={cn(\"w-full\", className)}\n style={{ ...(nativeWidth === undefined ? {} : { width: nativeWidth }), ...nativeStyle }}\n icon={startIcon}\n bare={bare}\n end={<span aria-hidden=\"true\" style={{ width: measuredRightPadding === null ? `calc(${Number(!!onSubmit) + Number(clearInline)} * (var(--matrx-tap-pill-size) + var(--matrx-tap-gap)))` : Math.max(0, measuredRightPadding - 12), flexShrink: 0 }} />}\n value={value}\n onChange={onChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n {...fieldProps}\n />\n {floatingLabel && inputId && (\n <Label\n htmlFor={inputId}\n className={cn(\n \"absolute left-3 px-1 pointer-events-none transition-all duration-200 ease-in-out z-10 bg-card\",\n labelFloated ? \"-top-2 text-xs\" : \"top-2 text-sm\",\n isInvalid ? \"text-destructive\" : isFocused ? \"text-primary\" : \"text-muted-foreground\",\n disabled && \"text-disabled-foreground\",\n )}\n >\n {floatingLabel}\n </Label>\n )}\n {/* A GLASS PLANE (tap-target placement rule 1); a press here never takes focus from the field. */}\n <div\n ref={setClusterNode}\n onMouseDown={(e) => e.preventDefault()}\n data-matrx-glass-plane\n data-matrx-tap-dense={denseField ? \"\" : undefined}\n className=\"absolute right-0 top-1/2 -translate-y-1/2 flex items-center z-10\"\n >\n <div\n ref={auxRef}\n className={cn(\n \"flex items-center transition-opacity duration-200\",\n showHoverControls || menuOpen ? \"opacity-100\" : \"opacity-0 pointer-events-none\",\n )}\n >\n {showMicInline && addOns.MicButton ? (\n <addOns.MicButton\n dense={denseField}\n tabIndex={auxiliaryControlsTabIndex}\n onMicClick={() => void voice.handleVoiceClick()}\n disabled={isVoiceDisabled}\n isRecording={isRecording}\n isTranscribing={isTranscribing}\n audioLevel={voice.audioLevel}\n micAriaLabel={micAriaLabel(isRecording, auxiliaryControlsLabel)}\n />\n ) : null}\n {showMenu && (\n <Popover open={menuOpen} onOpenChange={setMenuOpen}>\n <PopoverTrigger asChild>\n {hasCopied ? (\n <CheckTapButton\n tabIndex={auxiliaryControlsTabIndex}\n variant=\"transparent\"\n ariaLabel={auxiliaryControlsLabel ? `Copied ${auxiliaryControlsLabel}` : \"Copied\"}\n tooltip=\"Copied\"\n className=\"text-green-500\"\n />\n ) : (\n <MoreHorizontalTapButton\n tabIndex={auxiliaryControlsTabIndex}\n variant=\"transparent\"\n ariaLabel={auxiliaryControlsLabel ? `More options for ${auxiliaryControlsLabel}` : \"More options\"}\n tooltip=\"More\"\n className=\"text-muted-foreground\"\n />\n )}\n </PopoverTrigger>\n <PopoverContent\n /* sizing: fixed — the add-on body sizes itself (short list vs. cleanup panel) */\n align=\"end\"\n side=\"bottom\"\n sideOffset={6}\n className=\"w-auto max-w-none p-0\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n {Menu ? (\n <Menu field={fieldApi} ownRows={ownRows} trailingRows={null} close={closeMenu} />\n ) : (\n <StandInMenu field={fieldApi} ownRows={ownRows} trailingRows={null} close={closeMenu} registry />\n )}\n </PopoverContent>\n </Popover>\n )}\n </div>\n {clearInline && (\n <XTapButton\n variant=\"transparent\"\n onClick={handleClear}\n ariaLabel=\"Clear\"\n tooltip=\"Clear\"\n className=\"text-muted-foreground\"\n />\n )}\n {onSubmit &&\n (isSubmitting ? (\n <LoadingTapButton variant=\"transparent\" ariaLabel={submitLabel} tooltip={submitLabel} className=\"text-primary\" />\n ) : (\n <SendTapButton\n variant=\"transparent\"\n onClick={triggerSubmit}\n disabled={!canSubmit}\n ariaLabel={submitLabel}\n tooltip={submitLabel}\n className={canSubmit ? \"text-primary\" : \"text-muted-foreground\"}\n />\n ))}\n </div>\n {showVoiceStatus && (\n <div className=\"absolute left-0 top-full mt-1 flex items-center gap-1.5 px-2 py-1 rounded-md max-w-full\">\n {isRecording ? (\n <div className=\"relative flex items-center gap-1.5 px-2 py-1 bg-primary/10 dark:bg-primary/15 rounded-md max-w-full\">\n <span aria-hidden className=\"w-2 h-2 bg-primary rounded-full flex-shrink-0 animate-pulse\" />\n <span className=\"type-secondary text-primary font-medium truncate\">\n {voice.liveTranscript ? voice.liveTranscript.slice(-60) : \"Listening...\"}\n </span>\n </div>\n ) : (\n <FinalizingStrip className=\"relative\" />\n )}\n </div>\n )}\n {voice.dialogs}\n <VoiceProtectionDialog voice={voice} />\n </div>\n );\n },\n);\n\nProInput.displayName = \"ProInput\";\n","/**\n * THE TOOLBAR NEVER COVERS TEXT (page-pass 2026-09-27, /chat/message-templates/<id> at 375px).\n *\n * ProInput's mic + \"…\" cluster fades in over the right end of the field. On a\n * phone a tap counts as a hover and stays one, so the cluster sat on top of the\n * text being typed and clipped it. The fix is to reserve exactly the width the\n * visible right-hand controls take — measured, never guessed — as the input's\n * right padding:\n *\n * - the whole cluster while the mic / \"…\" part is showing;\n * - only the always-visible part (clear, submit) while it is faded out — the\n * faded part still takes layout width, so it is subtracted, not ignored.\n *\n * `null` means \"nothing measured yet\" (first paint, jsdom): the caller keeps its\n * class-based fallback padding.\n */\nexport const PRO_INPUT_TEXT_GAP_PX = 4;\nexport const PRO_INPUT_MIN_RIGHT_PADDING_PX = 12;\n\nexport function reservedRightPaddingPx({\n clusterWidth,\n auxWidth,\n auxVisible,\n}: {\n clusterWidth: number;\n auxWidth: number;\n auxVisible: boolean;\n}): number | null {\n if (!(clusterWidth > 0)) return null;\n const visible = auxVisible\n ? clusterWidth\n : Math.max(0, clusterWidth - Math.max(0, auxWidth));\n if (visible <= 0) return PRO_INPUT_MIN_RIGHT_PADDING_PX;\n return Math.max(\n PRO_INPUT_MIN_RIGHT_PADDING_PX,\n Math.ceil(visible) + PRO_INPUT_TEXT_GAP_PX,\n );\n}\n\n/**\n * A NARROW FIELD NEVER LETS A HOVER STEAL ITS CLICK.\n *\n * The mic + \"…\" cluster fades in on pointer hover over the right end of the\n * field. In a field only a couple of hundred px wide (a board tile's task-add\n * row, a sidebar) the cluster and its reserved padding leave a sliver of text,\n * and a press aimed at the middle of the field lands ON the mic: no focus, no\n * typing. Below this width the cluster appears on FOCUS instead of hover, so\n * the first press always focuses the field.\n */\nexport const PRO_INPUT_NARROW_FIELD_PX = 260;\n\nexport function hoverRevealsCluster(inputWidth: number): boolean {\n return !(inputWidth > 0 && inputWidth < PRO_INPUT_NARROW_FIELD_PX);\n}\n\n// What fits beside the text — and what moves inside \"…\" — is decided by THE\n// ONE FITTING RULE shared with ProTextarea: `proFieldControlFit.ts`.\n"],"mappings":"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","names":["React","jsx","Fragment","jsx","jsxs","field","registry","React","useMediaQuery","Fragment","jsx","jsxs","useMediaQuery"]}