{"version":3,"file":"TimecodeInput.mjs","names":["BaseInput"],"sources":["../../src/timecodeInput/TimecodeInput.tsx"],"sourcesContent":["import { Input as BaseInput } from '@base-ui/react/input';\nimport React from 'react';\n\n/**\n * Props for the timecode text input primitive.\n *\n * Extends Base UI `Input` props, so controlled and uncontrolled React input\n * patterns both work. Use `onValueChange` for the current text value as the\n * user types, or `onChange` when composing with native form handlers.\n *\n * By default it renders as a plain text input, disables browser autocomplete,\n * and disables spellcheck so punctuation-heavy values such as `1:02:03.04`\n * stay visually stable. Pass explicit native input props when a form needs\n * different behavior.\n */\nexport interface TimecodeInputProps extends React.ComponentPropsWithoutRef<typeof BaseInput> {\n  /**\n   * Marks the current input text as invalid when `aria-invalid` is not provided.\n   *\n   * Prefer this boolean for parser-driven validation state. Pass\n   * `aria-invalid` directly only when you need a custom ARIA value such as\n   * `'grammar'` or `'spelling'`.\n   */\n  invalid?: boolean;\n}\n\n/**\n * Text input for entering timeline positions as timecode.\n *\n * Use `TimecodeInput` when a toolbar, inspector, or properties panel needs a\n * native text input for clip starts, clip ends, playhead positions, or range\n * boundaries. It keeps flexible entry open to the user (`90`, `1:30.25`,\n * `1:02:03.4567`, and `00:01:30:12` can all represent timeline positions)\n * while the companion helpers parse precise input and format display text\n * consistently.\n *\n * This component renders only the input. Pair it with `parseTimecode` to\n * validate the current text, pass `invalid` when parsing returns `null`, and\n * convert valid seconds back to `RationalTime` with `fromSeconds(parsed, rate)`\n * at your timeline boundary.\n *\n * The rendered input receives `data-slot=\"timecode-input\"` and a\n * `timecode-input` class before consumer classes, which keeps it compatible\n * with shadcn-style slot selectors and Canvas Timeline's semantic stylesheet\n * approach. It forwards refs to the underlying native input element.\n *\n * @param props - Base UI input props plus default text-entry attributes and invalid styling.\n * @returns A text input element configured for timecode entry.\n *\n * @example\n * ```tsx\n * import { useState } from 'react';\n * import { TimecodeInput } from '@techsquidtv/canvas-timeline-react/timecode-input';\n * import { fromSeconds, type RationalTime } from '@techsquidtv/canvas-timeline-utils';\n * import {\n *   type TimecodeFormatOptions,\n *   type TimecodeParseOptions,\n *   formatTimecode,\n *   parseTimecode,\n * } from '@techsquidtv/canvas-timeline-utils/timecode';\n *\n * const formatOptions = [\n *   { value: 'seconds', label: 'Seconds', formatOptions: { format: 'seconds' } },\n *   {\n *     value: 'frames-24',\n *     label: '24 fps',\n *     formatOptions: { format: 'frames', frameRate: 24 },\n *     parseOptions: { frameRate: 24 },\n *   },\n * ] satisfies Array<{\n *   value: string;\n *   label: string;\n *   formatOptions: TimecodeFormatOptions;\n *   parseOptions?: TimecodeParseOptions;\n * }>;\n * const sequenceRate = 24000;\n * const initialSeconds = 3723.04;\n *\n * function ClipStartInput({\n *   onApply,\n * }: {\n *   onApply: (time: RationalTime) => void;\n * }) {\n *   const [formatValue, setFormatValue] = useState('seconds');\n *   const [text, setText] = useState(() =>\n *     formatTimecode(initialSeconds, { format: 'seconds' })\n *   );\n *   const selectedFormat =\n *     formatOptions.find((option) => option.value === formatValue) ?? formatOptions[0];\n *   const parsedSeconds = parseTimecode(text, selectedFormat.parseOptions);\n *\n *   function handleFormatChange(nextFormatValue: string) {\n *     const nextFormat = formatOptions.find((option) => option.value === nextFormatValue);\n *     const nextSeconds = parseTimecode(text, selectedFormat.parseOptions);\n *\n *     if (!nextFormat) {\n *       return;\n *     }\n *\n *     setFormatValue(nextFormat.value);\n *\n *     if (nextSeconds !== null) {\n *       setText(formatTimecode(nextSeconds, nextFormat.formatOptions));\n *     }\n *   }\n *\n *   return (\n *     <form\n *       onSubmit={(event) => {\n *         event.preventDefault();\n *         if (parsedSeconds !== null) {\n *           onApply(fromSeconds(parsedSeconds, sequenceRate));\n *           setText(formatTimecode(parsedSeconds, selectedFormat.formatOptions));\n *         }\n *       }}\n *     >\n *       <TimecodeInput\n *         aria-label=\"Clip start\"\n *         value={text}\n *         invalid={parsedSeconds === null}\n *         onValueChange={setText}\n *       />\n *       <select\n *         aria-label=\"Timecode format\"\n *         value={formatValue}\n *         onChange={(event) => handleFormatChange(event.currentTarget.value)}\n *       >\n *         {formatOptions.map((option) => (\n *           <option key={option.value} value={option.value}>\n *             {parsedSeconds === null\n *               ? option.label\n *               : `${option.label} (${formatTimecode(parsedSeconds, {\n *                   ...option.formatOptions,\n *                 })})`}\n *           </option>\n *         ))}\n *       </select>\n *       <button disabled={parsedSeconds === null} type=\"submit\">\n *         Apply\n *       </button>\n *     </form>\n *   );\n * }\n * ```\n */\nexport const TimecodeInput = React.forwardRef<HTMLInputElement, TimecodeInputProps>(\n  (\n    {\n      'aria-invalid': ariaInvalid,\n      autoComplete = 'off',\n      className = '',\n      inputMode = 'text',\n      invalid = false,\n      spellCheck = false,\n      type = 'text',\n      ...props\n    },\n    ref\n  ) => (\n    <BaseInput\n      ref={ref as React.ForwardedRef<HTMLElement>}\n      {...props}\n      aria-invalid={ariaInvalid ?? (invalid ? true : undefined)}\n      autoComplete={autoComplete}\n      className={['timecode-input', className].filter(Boolean).join(' ')}\n      data-slot=\"timecode-input\"\n      inputMode={inputMode}\n      spellCheck={spellCheck}\n      type={type}\n    />\n  )\n);\n\nTimecodeInput.displayName = 'TimecodeInput';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiJA,MAAa,gBAAgB,MAAM,YAE/B,EACE,gBAAgB,aAChB,eAAe,OACf,YAAY,IACZ,YAAY,QACZ,UAAU,OACV,aAAa,OACb,OAAO,QACP,GAAG,SAEL,QAEA,oBAACA,OAAD;CACO;CACL,GAAI;CACJ,gBAAc,gBAAgB,UAAU,OAAO,KAAA;CACjC;CACd,WAAW,CAAC,kBAAkB,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;CACjE,aAAU;CACC;CACC;CACN;AACP,CAAA,CAEL;AAEA,cAAc,cAAc"}