@alfadocs/ui-kit-debug 1.93.1 → 1.95.0
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.
- package/dist/_chunks/{ai-prompt-input-DH_rnV-F.js → ai-prompt-input-CG9BEggs.js} +2 -2
- package/dist/_chunks/{ai-prompt-input-DH_rnV-F.js.map → ai-prompt-input-CG9BEggs.js.map} +1 -1
- package/dist/_chunks/{anamnesis-summary-rows-EKPfVCmh.js → anamnesis-summary-rows-DTZ3per6.js} +4 -4
- package/dist/_chunks/{anamnesis-summary-rows-EKPfVCmh.js.map → anamnesis-summary-rows-DTZ3per6.js.map} +1 -1
- package/dist/_chunks/{audio-recorder-m7Jqvvcl.js → audio-recorder-BOm2FgEu.js} +2 -2
- package/dist/_chunks/{audio-recorder-m7Jqvvcl.js.map → audio-recorder-BOm2FgEu.js.map} +1 -1
- package/dist/_chunks/{balance-badge-cell-BtJvre1-.js → balance-badge-cell-vZxbOFgP.js} +4 -4
- package/dist/_chunks/{balance-badge-cell-BtJvre1-.js.map → balance-badge-cell-vZxbOFgP.js.map} +1 -1
- package/dist/_chunks/{bishop-score-C5di6oAV.js → bishop-score-BBYuyk2k.js} +2 -2
- package/dist/_chunks/{bishop-score-C5di6oAV.js.map → bishop-score-BBYuyk2k.js.map} +1 -1
- package/dist/_chunks/{calendar-appointment-editor-dialog-sJKLoVJ2.js → calendar-appointment-editor-dialog-WDKc3jMA.js} +6 -6
- package/dist/_chunks/{calendar-appointment-editor-dialog-sJKLoVJ2.js.map → calendar-appointment-editor-dialog-WDKc3jMA.js.map} +1 -1
- package/dist/_chunks/chart-pMkQN-qy.js +1550 -0
- package/dist/_chunks/chart-pMkQN-qy.js.map +1 -0
- package/dist/_chunks/{data-table-CqQgoNsU.js → data-table-C_nnpJ-Q.js} +2 -2
- package/dist/_chunks/{data-table-CqQgoNsU.js.map → data-table-C_nnpJ-Q.js.map} +1 -1
- package/dist/_chunks/{date-time-picker-n-yrlMJq.js → date-time-picker-cwsWiB4q.js} +2 -2
- package/dist/_chunks/{date-time-picker-n-yrlMJq.js.map → date-time-picker-cwsWiB4q.js.map} +1 -1
- package/dist/_chunks/{document-preview-QEbr7jp1.js → document-preview-ytR1FcWA.js} +2 -2
- package/dist/_chunks/{document-preview-QEbr7jp1.js.map → document-preview-ytR1FcWA.js.map} +1 -1
- package/dist/_chunks/{file-manager-BnI1ZWZu.js → file-manager-CAIbuaSs.js} +2 -2
- package/dist/_chunks/{file-manager-BnI1ZWZu.js.map → file-manager-CAIbuaSs.js.map} +1 -1
- package/dist/_chunks/{gestational-age-calculator-Dr9hdDta.js → gestational-age-calculator-Dn8IOXHB.js} +2 -2
- package/dist/_chunks/{gestational-age-calculator-Dr9hdDta.js.map → gestational-age-calculator-Dn8IOXHB.js.map} +1 -1
- package/dist/_chunks/group-options-BvKhQ3xb.js.map +1 -1
- package/dist/_chunks/{hcg-doubling-K41Wy7LB.js → hcg-doubling-DQe1ptNB.js} +2 -2
- package/dist/_chunks/{hcg-doubling-K41Wy7LB.js.map → hcg-doubling-DQe1ptNB.js.map} +1 -1
- package/dist/_chunks/{heatmap-fCxwNz2o.js → heatmap-DdF8qTTV.js} +2 -2
- package/dist/_chunks/{heatmap-fCxwNz2o.js.map → heatmap-DdF8qTTV.js.map} +1 -1
- package/dist/_chunks/{kit-extensions-a0G4COFH.js → kit-extensions-44gudqqq.js} +3 -3
- package/dist/_chunks/{kit-extensions-a0G4COFH.js.map → kit-extensions-44gudqqq.js.map} +1 -1
- package/dist/_chunks/{link-cell-renderer-BS3V4LA6.js → link-cell-renderer-OmvrkUeN.js} +2 -2
- package/dist/_chunks/{link-cell-renderer-BS3V4LA6.js.map → link-cell-renderer-OmvrkUeN.js.map} +1 -1
- package/dist/_chunks/{muscle-scheme-C66WlCxG.js → muscle-scheme-B7qMW0ho.js} +2 -2
- package/dist/_chunks/{muscle-scheme-C66WlCxG.js.map → muscle-scheme-B7qMW0ho.js.map} +1 -1
- package/dist/_chunks/{operator-hero-C_5B-8Qp.js → operator-hero-D_0KoEuJ.js} +31 -31
- package/dist/_chunks/operator-hero-D_0KoEuJ.js.map +1 -0
- package/dist/_chunks/{optical-prescription-CMM1Y6Xg.js → optical-prescription-BGVeDVSP.js} +2 -2
- package/dist/_chunks/{optical-prescription-CMM1Y6Xg.js.map → optical-prescription-BGVeDVSP.js.map} +1 -1
- package/dist/_chunks/{patient-details-BjcUpD9S.js → patient-details-DTlpBYHJ.js} +2 -2
- package/dist/_chunks/{patient-details-BjcUpD9S.js.map → patient-details-DTlpBYHJ.js.map} +1 -1
- package/dist/_chunks/{patient-field-row-B0tdiaWi.js → patient-field-row-DWTKV1hF.js} +2 -2
- package/dist/_chunks/{patient-field-row-B0tdiaWi.js.map → patient-field-row-DWTKV1hF.js.map} +1 -1
- package/dist/_chunks/{patient-summary-card-Cvv6_Ugk.js → patient-summary-card-C61AR4Tn.js} +2 -2
- package/dist/_chunks/{patient-summary-card-Cvv6_Ugk.js.map → patient-summary-card-C61AR4Tn.js.map} +1 -1
- package/dist/_chunks/{pregnancy-dating-BHvfDxz4.js → pregnancy-dating-CuVj9KGR.js} +2 -2
- package/dist/_chunks/{pregnancy-dating-BHvfDxz4.js.map → pregnancy-dating-CuVj9KGR.js.map} +1 -1
- package/dist/_chunks/{registration-form-CRm6DaB9.js → registration-form-BygI73vG.js} +2 -2
- package/dist/_chunks/{registration-form-CRm6DaB9.js.map → registration-form-BygI73vG.js.map} +1 -1
- package/dist/_chunks/{reserved.agent-DnPwaa4u.js → reserved.agent-BvwjDyne.js} +3 -3
- package/dist/_chunks/{reserved.agent-DnPwaa4u.js.map → reserved.agent-BvwjDyne.js.map} +1 -1
- package/dist/_chunks/{select-4S-eYZUf.js → select-BBDRYxJl.js} +247 -241
- package/dist/_chunks/select-BBDRYxJl.js.map +1 -0
- package/dist/_chunks/signature-request-BVGeF0qB.js +2774 -0
- package/dist/_chunks/signature-request-BVGeF0qB.js.map +1 -0
- package/dist/_chunks/{slot-grid-B-IAFX3C.js → slot-grid-BhjaLJ0o.js} +229 -214
- package/dist/_chunks/{slot-grid-B-IAFX3C.js.map → slot-grid-BhjaLJ0o.js.map} +1 -1
- package/dist/_chunks/{tabs-BTj-2qMZ.js → tabs-BmxQu-TJ.js} +2 -2
- package/dist/_chunks/{tabs-BTj-2qMZ.js.map → tabs-BmxQu-TJ.js.map} +1 -1
- package/dist/_chunks/{task-editor-CI1SKUNc.js → task-editor-Cv7xSakv.js} +3 -3
- package/dist/_chunks/{task-editor-CI1SKUNc.js.map → task-editor-Cv7xSakv.js.map} +1 -1
- package/dist/_chunks/{tasks-panel-BkjtgjQ8.js → tasks-panel-BTCYGLGA.js} +2 -2
- package/dist/_chunks/{tasks-panel-BkjtgjQ8.js.map → tasks-panel-BTCYGLGA.js.map} +1 -1
- package/dist/_chunks/time-picker-DSt-ns5F.js +914 -0
- package/dist/_chunks/time-picker-DSt-ns5F.js.map +1 -0
- package/dist/_chunks/{unit-converter-BH5ueIhT.js → unit-converter-C95sa5y8.js} +2 -2
- package/dist/_chunks/{unit-converter-BH5ueIhT.js.map → unit-converter-C95sa5y8.js.map} +1 -1
- package/dist/_chunks/{use-appointment-details-read-D8vDg0sg.js → use-appointment-details-read-B6uhmNdV.js} +2 -2
- package/dist/_chunks/{use-appointment-details-read-D8vDg0sg.js.map → use-appointment-details-read-B6uhmNdV.js.map} +1 -1
- package/dist/_chunks/{voice-control-panel-BP0otrID.js → voice-control-panel-BGJjUwnY.js} +2 -2
- package/dist/_chunks/{voice-control-panel-BP0otrID.js.map → voice-control-panel-BGJjUwnY.js.map} +1 -1
- package/dist/agent-catalog.json +20 -8
- package/dist/agent-i18n/en.json +6 -6
- package/dist/apexcharts.css +4 -1
- package/dist/components/_shared/group-options.d.ts +2 -2
- package/dist/components/_shared/group-options.d.ts.map +1 -1
- package/dist/components/ai-prompt-input/index.js +1 -1
- package/dist/components/appointment-details-panel/index.js +1 -1
- package/dist/components/audio-recorder/index.js +1 -1
- package/dist/components/bishop-score/index.js +1 -1
- package/dist/components/booking/index.js +1 -1
- package/dist/components/chart/chart-axis-scale.d.ts +21 -0
- package/dist/components/chart/chart-axis-scale.d.ts.map +1 -0
- package/dist/components/chart/chart.agent.d.ts.map +1 -1
- package/dist/components/chart/chart.d.ts +55 -0
- package/dist/components/chart/chart.d.ts.map +1 -1
- package/dist/components/chart/index.d.ts +1 -1
- package/dist/components/chart/index.d.ts.map +1 -1
- package/dist/components/chart/index.js +1 -1
- package/dist/components/data-table/index.js +2 -2
- package/dist/components/date-time-picker/index.js +1 -1
- package/dist/components/document-preview/index.js +1 -1
- package/dist/components/file-manager/index.js +1 -1
- package/dist/components/gestational-age-calculator/index.js +1 -1
- package/dist/components/hcg-doubling/index.js +1 -1
- package/dist/components/heatmap/index.js +1 -1
- package/dist/components/muscle-scheme/index.js +1 -1
- package/dist/components/operator-hero/index.js +1 -1
- package/dist/components/operator-hero/operator-hero.d.ts +3 -2
- package/dist/components/operator-hero/operator-hero.d.ts.map +1 -1
- package/dist/components/optical-prescription/index.js +1 -1
- package/dist/components/patient-details/index.js +1 -1
- package/dist/components/patient-summary-card/index.js +1 -1
- package/dist/components/patient-table/index.js +1 -1
- package/dist/components/pregnancy-dating/index.js +1 -1
- package/dist/components/rich-text-editor/index.js +1 -1
- package/dist/components/select/index.js +1 -1
- package/dist/components/select/select.d.ts +13 -1
- package/dist/components/select/select.d.ts.map +1 -1
- package/dist/components/skeleton-scheme/index.js +1 -1
- package/dist/components/slot-grid/index.js +1 -1
- package/dist/components/slot-grid/slot-grid.d.ts.map +1 -1
- package/dist/components/tabs/index.js +1 -1
- package/dist/components/task-editor/index.js +1 -1
- package/dist/components/tasks-panel/index.js +1 -1
- package/dist/components/time-picker/index.js +1 -1
- package/dist/components/time-picker/time-picker.d.ts +15 -8
- package/dist/components/time-picker/time-picker.d.ts.map +1 -1
- package/dist/components/unit-converter/index.js +1 -1
- package/dist/components/voice-control-panel/index.js +1 -1
- package/dist/core.css +1 -1
- package/dist/i18n/locales/ar.d.ts +8 -1
- package/dist/i18n/locales/ar.d.ts.map +1 -1
- package/dist/i18n/locales/ar.js +10 -3
- package/dist/i18n/locales/ar.js.map +1 -1
- package/dist/i18n/locales/de.d.ts +9 -2
- package/dist/i18n/locales/de.d.ts.map +1 -1
- package/dist/i18n/locales/de.js +11 -4
- package/dist/i18n/locales/de.js.map +1 -1
- package/dist/i18n/locales/el.d.ts +9 -2
- package/dist/i18n/locales/el.d.ts.map +1 -1
- package/dist/i18n/locales/el.js +11 -4
- package/dist/i18n/locales/el.js.map +1 -1
- package/dist/i18n/locales/en.d.ts +9 -2
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +10 -3
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +9 -2
- package/dist/i18n/locales/es.d.ts.map +1 -1
- package/dist/i18n/locales/es.js +11 -4
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +8 -1
- package/dist/i18n/locales/fr.d.ts.map +1 -1
- package/dist/i18n/locales/fr.js +10 -3
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hi.d.ts +9 -2
- package/dist/i18n/locales/hi.d.ts.map +1 -1
- package/dist/i18n/locales/hi.js +11 -4
- package/dist/i18n/locales/hi.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +9 -2
- package/dist/i18n/locales/it.d.ts.map +1 -1
- package/dist/i18n/locales/it.js +11 -4
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/ja.d.ts +9 -2
- package/dist/i18n/locales/ja.d.ts.map +1 -1
- package/dist/i18n/locales/ja.js +11 -4
- package/dist/i18n/locales/ja.js.map +1 -1
- package/dist/i18n/locales/nl.d.ts +9 -2
- package/dist/i18n/locales/nl.d.ts.map +1 -1
- package/dist/i18n/locales/nl.js +11 -4
- package/dist/i18n/locales/nl.js.map +1 -1
- package/dist/i18n/locales/pl.d.ts +9 -2
- package/dist/i18n/locales/pl.d.ts.map +1 -1
- package/dist/i18n/locales/pl.js +11 -4
- package/dist/i18n/locales/pl.js.map +1 -1
- package/dist/i18n/locales/pt.d.ts +8 -1
- package/dist/i18n/locales/pt.d.ts.map +1 -1
- package/dist/i18n/locales/pt.js +10 -3
- package/dist/i18n/locales/pt.js.map +1 -1
- package/dist/i18n/locales/ro.d.ts +9 -2
- package/dist/i18n/locales/ro.d.ts.map +1 -1
- package/dist/i18n/locales/ro.js +11 -4
- package/dist/i18n/locales/ro.js.map +1 -1
- package/dist/i18n/locales/ru.d.ts +9 -2
- package/dist/i18n/locales/ru.d.ts.map +1 -1
- package/dist/i18n/locales/ru.js +11 -4
- package/dist/i18n/locales/ru.js.map +1 -1
- package/dist/i18n/locales/sq.d.ts +9 -2
- package/dist/i18n/locales/sq.d.ts.map +1 -1
- package/dist/i18n/locales/sq.js +11 -4
- package/dist/i18n/locales/sq.js.map +1 -1
- package/dist/i18n/locales/sv.d.ts +9 -2
- package/dist/i18n/locales/sv.d.ts.map +1 -1
- package/dist/i18n/locales/sv.js +11 -4
- package/dist/i18n/locales/sv.js.map +1 -1
- package/dist/i18n/locales/tr.d.ts +9 -2
- package/dist/i18n/locales/tr.d.ts.map +1 -1
- package/dist/i18n/locales/tr.js +11 -4
- package/dist/i18n/locales/tr.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +9 -2
- package/dist/i18n/locales/zh.d.ts.map +1 -1
- package/dist/i18n/locales/zh.js +11 -4
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/index.js +34 -34
- package/dist/locales/ar.json +10 -3
- package/dist/locales/de.json +11 -4
- package/dist/locales/el.json +11 -4
- package/dist/locales/en.json +10 -3
- package/dist/locales/es.json +11 -4
- package/dist/locales/fr.json +10 -3
- package/dist/locales/hi.json +11 -4
- package/dist/locales/it.json +11 -4
- package/dist/locales/ja.json +11 -4
- package/dist/locales/nl.json +11 -4
- package/dist/locales/pl.json +11 -4
- package/dist/locales/pt.json +10 -3
- package/dist/locales/ro.json +11 -4
- package/dist/locales/ru.json +11 -4
- package/dist/locales/sq.json +11 -4
- package/dist/locales/sv.json +11 -4
- package/dist/locales/tr.json +11 -4
- package/dist/locales/zh.json +11 -4
- package/dist/patterns/anamnesis/index.js +1 -1
- package/dist/patterns/calendar/index.js +1 -1
- package/dist/patterns/registration-form/index.js +1 -1
- package/dist/patterns/signature-request/index.js +1 -1
- package/dist/patterns/signature-request/required-documents.d.ts +2 -1
- package/dist/patterns/signature-request/required-documents.d.ts.map +1 -1
- package/dist/patterns/signature-request/signature-request.d.ts +61 -0
- package/dist/patterns/signature-request/signature-request.d.ts.map +1 -1
- package/dist/tokens.css +4 -1
- package/package.json +1 -1
- package/dist/_chunks/chart-D4huJSru.js +0 -1340
- package/dist/_chunks/chart-D4huJSru.js.map +0 -1
- package/dist/_chunks/operator-hero-C_5B-8Qp.js.map +0 -1
- package/dist/_chunks/select-4S-eYZUf.js.map +0 -1
- package/dist/_chunks/signature-request-DvhyrRpn.js +0 -2448
- package/dist/_chunks/signature-request-DvhyrRpn.js.map +0 -1
- package/dist/_chunks/time-picker-DVfyAR81.js +0 -871
- package/dist/_chunks/time-picker-DVfyAR81.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time-picker-DSt-ns5F.js","sources":["../../src/components/time-picker/time-picker.agent.ts","../../src/components/time-picker/time-picker.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — TimePicker. */\n/* */\n/* TimePicker is a segmented time input. With the `dropdown` prop it also */\n/* has a list to pick from (hour, minute and AM/PM columns), which */\n/* `open` / `close` drive. Without `dropdown` there is no list and they */\n/* resolve to no-ops on the curated handle (kept for shape parity with */\n/* the other pickers, see PRS §26 §15 on curated handles). */\n/* */\n/* See `src/docs/26-agent-readiness.mdx` §15. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { TimePickerHandle } from './time-picker';\n\nexport const timePickerAgent: AgentAdapter<TimePickerHandle> = {\n id: 'time-picker',\n capabilities: ['select_single', 'set_value', 'open', 'close'],\n state: {\n value: {\n type: 'HH:MM | null',\n descriptionKey: 'ui.agent.timePicker.state.value',\n description:\n 'Currently selected time as 24h HH:MM. Null when unset with allowEmpty; otherwise defaults to 00:00.',\n read: (handle) => {\n const value = handle.getValue();\n if (!value) return null;\n const hh = String(value.hours).padStart(2, '0');\n const mm = String(value.minutes).padStart(2, '0');\n return `${hh}:${mm}`;\n },\n },\n isOpen: {\n type: 'boolean',\n descriptionKey: 'ui.agent.timePicker.state.isOpen',\n description:\n 'Whether the time dropdown is open. Always false unless the picker has the dropdown prop.',\n read: (handle) => handle.isOpen(),\n },\n },\n actions: {\n set_time: {\n safety: 'write',\n argsType: '{ time: string }',\n argsSchema: {\n type: 'object',\n properties: {\n time: { type: 'string', pattern: '^([01][0-9]|2[0-3]):[0-5][0-9]$' },\n },\n required: ['time'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.timePicker.actions.setTime',\n description: 'Set the time using a 24h HH:MM string.',\n examples: [{ args: { time: '14:30' }, note: '2:30 PM in 24h form.' }],\n invoke: (handle, args: { time: string }) => {\n const [hStr, mStr] = args.time.split(':');\n handle.setValue({\n hours: Number.parseInt(hStr ?? '0', 10),\n minutes: Number.parseInt(mStr ?? '0', 10),\n });\n },\n },\n clear: {\n safety: 'destructive',\n idempotent: true,\n descriptionKey: 'ui.agent.timePicker.actions.clear',\n description: 'Clear to null with allowEmpty; otherwise reset to 00:00.',\n invoke: (handle) => {\n handle.clear();\n },\n },\n open: {\n safety: 'read',\n descriptionKey: 'ui.agent.timePicker.actions.open',\n description:\n 'Open the time dropdown without moving focus. A no-op unless the picker has the dropdown prop and is enabled.',\n invoke: (handle) => {\n handle.open();\n },\n },\n close: {\n safety: 'read',\n descriptionKey: 'ui.agent.timePicker.actions.close',\n description:\n 'Close the time dropdown. A no-op unless the picker has the dropdown prop.',\n invoke: (handle) => {\n handle.close();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'time-picker',\n description: 'Marks the TimePicker wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","import {\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type KeyboardEvent,\n type MouseEvent,\n type MutableRefObject,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport * as Popover from '@radix-ui/react-popover';\nimport { Clock, X } from 'lucide-react';\nimport {\n FormFieldContext,\n useFormField,\n useFormFieldControlId,\n} from '../form-field/form-field-context';\nimport type { TimeValue } from '../_shared/time';\nimport { useIsomorphicLayoutEffect } from '../../hooks/use-isomorphic-layout-effect';\nimport { useAgentRegistration } from '../../agent';\nimport { timePickerAgent } from './time-picker.agent';\n\n/* -------------------------------------------------------------------------- */\n/* Imperative handle */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Curated imperative handle, registered with the agent registry and consumed\n * by the agent adapter. (The forwarded `ref` is the root element.)\n */\nexport interface TimePickerHandle {\n /** Get the current time value, or null when unset. */\n getValue: () => TimeValue | null;\n /** Set the time value. Hours are kept within 0–23 and minutes within 0–59. */\n setValue: (value: TimeValue) => void;\n /** Clear to null with allowEmpty; otherwise reset to 00:00. */\n clear: () => void;\n /** Whether the time dropdown is open. Always false unless `dropdown` is on. */\n isOpen: () => boolean;\n /** Open the time dropdown without moving focus. A no-op unless `dropdown` is on and the picker is enabled. */\n open: () => void;\n /** Close the time dropdown. A no-op unless `dropdown` is on. */\n close: () => void;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------------- */\n\n/** Detect 12h vs 24h from the browser locale. */\nfunction detectHour12(locale: string): boolean {\n try {\n const resolved = new Intl.DateTimeFormat(locale, {\n hour: 'numeric',\n }).resolvedOptions();\n return resolved.hourCycle === 'h12' || resolved.hourCycle === 'h11';\n } catch {\n return false;\n }\n}\n\n/** Get localised AM/PM labels via Intl. */\nfunction getLocalePeriodLabels(locale: string): { am: string; pm: string } {\n try {\n const am =\n new Intl.DateTimeFormat(locale, {\n hour: 'numeric',\n hour12: true,\n })\n .formatToParts(new Date(2000, 0, 1, 9))\n .find((p) => p.type === 'dayPeriod')?.value ?? 'AM';\n\n const pm =\n new Intl.DateTimeFormat(locale, {\n hour: 'numeric',\n hour12: true,\n })\n .formatToParts(new Date(2000, 0, 1, 15))\n .find((p) => p.type === 'dayPeriod')?.value ?? 'PM';\n\n return { am, pm };\n } catch {\n return { am: 'AM', pm: 'PM' };\n }\n}\n\n/** Clamp a number between min and max. */\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\n/** The last minute of the hour on the step grid: 55 for step 5, 30 for step 30. */\nfunction lastMinuteOnGrid(step: number): number {\n return Math.floor(59 / step) * step;\n}\n\n/**\n * Snap a typed minute to the nearest step. Never past the last grid value of\n * the hour: 58 with step 5 is 55, not 60, which a consumer setting minutes on\n * a Date would roll into the next hour (or day, from 23:58).\n */\nfunction snapMinuteToStep(value: number, step: number): number {\n const rounded = Math.round(clamp(value, 0, 59) / step) * step;\n return clamp(rounded, 0, lastMinuteOnGrid(step));\n}\n\n/** The next or previous minute on the step grid, wrapping within the hour. An off-grid value moves to its neighbouring grid value. */\nfunction stepMinute(value: number, step: number, direction: 1 | -1): number {\n const last = lastMinuteOnGrid(step);\n if (direction === 1) {\n const next = Math.floor(value / step) * step + step;\n return next > last ? 0 : next;\n }\n const previous = Math.ceil(value / step) * step - step;\n return previous < 0 ? last : previous;\n}\n\n/** Keep a value from outside (handle, agent) within 00:00–23:59. */\nfunction normaliseTime(value: TimeValue): TimeValue {\n const whole = (n: number) => (Number.isFinite(n) ? Math.trunc(n) : 0);\n return {\n hours: clamp(whole(value.hours), 0, 23),\n minutes: clamp(whole(value.minutes), 0, 59),\n };\n}\n\n/** Convert 24h hour to 12h display hour. */\nfunction to12Hour(h24: number): number {\n if (h24 === 0) return 12;\n if (h24 > 12) return h24 - 12;\n return h24;\n}\n\n/** Convert 12h display hour + period to 24h hour. */\nfunction to24Hour(h12: number, isPM: boolean): number {\n if (isPM) return h12 === 12 ? 12 : h12 + 12;\n return h12 === 12 ? 0 : h12;\n}\n\nconst pad2 = (n: number): string => String(n).padStart(2, '0');\n\n/** See `contentCallbackRef`: keeps a host scroll lock from cancelling the event. */\nfunction stopScrollLockPropagation(event: Event): void {\n event.stopPropagation();\n}\n\n/* -------------------------------------------------------------------------- */\n/* CVA variants */\n/* -------------------------------------------------------------------------- */\n\nconst wrapperVariants = cva(\n [\n 'ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]',\n 'ds:rounded-[var(--radius-sm)] ds:border ds:border-[color:var(--control-border)] ds:bg-background',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:focus-within:outline-[length:var(--focus-ring-width)] ds:focus-within:outline-solid',\n 'ds:focus-within:outline-ring ds:focus-within:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-within:outline-[CanvasText]',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:h-8 ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:text-[length:var(--font-size-sm)]',\n md: 'ds:h-[var(--min-target-size)] ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:text-[length:var(--font-size-base)]',\n lg: 'ds:h-12 ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)] ds:text-[length:var(--font-size-lg)]',\n },\n tone: {\n default: 'ds:border-[color:var(--control-border)]',\n error: 'ds:border-destructive',\n },\n isDisabled: {\n true: 'ds:cursor-not-allowed ds:opacity-50',\n false: '',\n },\n /** `dropdown` on and enabled: a click anywhere on the field opens the list. */\n opensOnClick: {\n true: 'ds:cursor-pointer',\n false: '',\n },\n },\n defaultVariants: {\n size: 'md',\n tone: 'default',\n isDisabled: false,\n opensOnClick: false,\n },\n },\n);\n\nconst segmentVariants = cva(\n [\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:rounded-[var(--radius-sm)] ds:text-center ds:tabular-nums',\n 'ds:bg-transparent ds:text-foreground',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:select-none',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:min-w-6 ds:h-6 ds:text-[length:var(--font-size-sm)]',\n md: 'ds:min-w-8 ds:h-8 ds:text-[length:var(--font-size-base)]',\n lg: 'ds:min-w-10 ds:h-10 ds:text-[length:var(--font-size-lg)]',\n },\n },\n defaultVariants: { size: 'md' },\n },\n);\n\nconst periodButtonVariants = cva(\n [\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:rounded-[var(--radius-sm)] ds:text-center',\n 'ds:bg-transparent ds:text-foreground ds:cursor-pointer',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:select-none',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:hover:bg-muted',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:min-w-8 ds:h-6 ds:text-[length:var(--font-size-sm)] ds:ps-1 ds:pe-1',\n md: 'ds:min-w-10 ds:h-8 ds:text-[length:var(--font-size-base)] ds:ps-1.5 ds:pe-1.5',\n lg: 'ds:min-w-12 ds:h-10 ds:text-[length:var(--font-size-lg)] ds:ps-2 ds:pe-2',\n },\n },\n defaultVariants: { size: 'md' },\n },\n);\n\nconst separatorVariants = cva('ds:text-muted-foreground ds:select-none', {\n variants: {\n size: {\n sm: 'ds:text-[length:var(--font-size-sm)]',\n md: 'ds:text-[length:var(--font-size-base)]',\n lg: 'ds:text-[length:var(--font-size-lg)]',\n },\n },\n defaultVariants: { size: 'md' },\n});\n\n/**\n * The clock button: flush with the field's inline-end edge (the negative\n * margin cancels the wrapper's end padding) and stretched to its inner\n * height. The `before:` hit area reaches over the field's 1px border, so\n * the target is the field's full height: 44px in `md`, 48px accessible.\n */\nconst clockButtonVariants = cva(\n [\n 'ds:relative ds:inline-flex ds:shrink-0 ds:self-stretch ds:items-center ds:justify-center',\n 'ds:before:absolute ds:before:inset-x-0 ds:before:-inset-y-px',\n 'ds:bg-transparent ds:text-muted-foreground ds:cursor-pointer',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n 'ds:hover:bg-muted ds:hover:text-foreground',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-ring',\n 'ds:focus-visible:[outline-offset:calc(var(--focus-ring-width)*-1)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n 'ds:disabled:cursor-not-allowed ds:disabled:hover:bg-transparent',\n ].join(' '),\n {\n variants: {\n // Only the button that ends the field rounds its inline-end corner.\n trailing: { true: 'ds:rounded-e-[var(--radius-sm)]', false: '' },\n size: {\n sm: 'ds:min-w-8 ds:[&_svg]:size-4',\n md: 'ds:min-w-[var(--min-target-size)] ds:[&_svg]:size-4',\n lg: 'ds:min-w-12 ds:[&_svg]:size-5',\n },\n },\n defaultVariants: { size: 'md', trailing: true },\n compoundVariants: [\n { size: 'sm', trailing: true, className: 'ds:-me-[var(--spacing-sm)]' },\n {\n size: ['md', 'lg'],\n trailing: true,\n className: 'ds:-me-[var(--spacing-md)]',\n },\n ],\n },\n);\n\n/**\n * The dropdown panel. `--time-picker-option-size` is one option's block size:\n * 2rem for `sm` and 3rem for `lg` (the field heights), `--min-target-size`\n * for `md`, so it grows to 48px under `.theme-accessible`.\n */\nconst dropdownContentVariants = cva(\n [\n 'ds:z-[var(--z-popover)] ds:flex ds:rounded-[var(--radius-md)]',\n 'ds:border ds:border-border ds:bg-background ds:text-foreground ds:shadow-[var(--shadow-lg)]',\n 'ds:p-[var(--spacing-xs)]',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:[--time-picker-option-size:var(--spacing-xl)] ds:text-[length:var(--font-size-sm)]',\n md: 'ds:[--time-picker-option-size:var(--min-target-size)] ds:text-[length:var(--font-size-base)]',\n lg: 'ds:[--time-picker-option-size:var(--spacing-2xl)] ds:text-[length:var(--font-size-lg)]',\n },\n },\n defaultVariants: { size: 'md' },\n },\n);\n\n/** One column: six and a half options tall, so a part-visible option at the edge shows it scrolls. */\nconst columnVariants = cva(\n [\n 'ds:relative ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)]',\n 'ds:max-h-[calc(var(--time-picker-option-size)*6.5)] ds:overflow-y-auto ds:overscroll-contain',\n 'ds:p-[var(--spacing-2xs)]',\n ].join(' '),\n {\n variants: {\n separated: {\n true: 'ds:border-s ds:border-border',\n false: '',\n },\n },\n defaultVariants: { separated: false },\n },\n);\n\nconst optionVariants = cva(\n [\n 'ds:flex ds:shrink-0 ds:items-center ds:justify-center',\n 'ds:h-[var(--time-picker-option-size)] ds:min-w-[var(--time-picker-option-size)]',\n 'ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)]',\n 'ds:rounded-[var(--radius-sm)] ds:tabular-nums ds:whitespace-nowrap',\n 'ds:cursor-pointer ds:select-none',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n // Inset ring: the column scrolls, so an outset ring would be clipped.\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:[outline-offset:calc(var(--focus-ring-width)*-1)]',\n ].join(' '),\n {\n variants: {\n // The kit's selected treatment (the calendar's selected day): solid\n // primary. Paired with aria-selected, so not colour alone.\n selected: {\n true: [\n 'ds:bg-primary ds:text-primary-foreground ds:font-semibold ds:hover:bg-primary-hover',\n 'ds:focus-visible:outline-primary-foreground',\n 'ds:forced-colors:bg-[Highlight] ds:forced-colors:text-[HighlightText]',\n // CanvasText can sit close to Highlight in some contrast themes.\n 'ds:forced-colors:focus-visible:outline-[HighlightText]',\n ].join(' '),\n false: [\n 'ds:text-foreground ds:hover:bg-muted ds:focus-visible:outline-ring',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n ].join(' '),\n },\n },\n defaultVariants: { selected: false },\n },\n);\n\n/* -------------------------------------------------------------------------- */\n/* Props */\n/* -------------------------------------------------------------------------- */\n\ntype MinuteStep = 1 | 5 | 10 | 15 | 30;\n\ninterface TimePickerBaseProps extends Pick<\n VariantProps<typeof wrapperVariants>,\n 'size'\n> {\n /** Force 12h/24h mode. Defaults to locale detection. */\n hour12?: boolean;\n /** Minute increment step. */\n minuteStep?: MinuteStep;\n /** Use full-width colon separator for CJK apps. */\n fullWidthSeparator?: boolean;\n /** Custom AM/PM labels. */\n periodLabels?: { am: string; pm: string };\n /** Component size. */\n size?: 'sm' | 'md' | 'lg';\n /**\n * Adds a list to pick the time from: a clock button at the field's end,\n * and a click anywhere on the field opens a panel with an hour column, a\n * minute column (in `minuteStep` steps) and, in 12h mode, an AM/PM column.\n * Typing still works while it is open. For pointer and touch-first forms\n * such as business hours. Off by default: the typed field is unchanged.\n */\n dropdown?: boolean;\n /** Whether the input is disabled. */\n disabled?: boolean;\n /** Additional class names. */\n className?: string;\n /** id override. */\n id?: string;\n /**\n * Accessible name for the time group when it is NOT in a `FormField`, or\n * to override the field's label (two pickers in one field, say). Without\n * a name of its own the group is called \"Time\". Inside a `FormField` the\n * group takes the field's label.\n */\n 'aria-label'?: string;\n /** Accessible name by reference. Wins over `aria-label` and the FormField label. */\n 'aria-labelledby'?: string;\n}\n\n/** Empty values are opt-in, keeping existing onChange callbacks non-nullable. */\nexport type TimePickerProps = TimePickerBaseProps &\n (\n | {\n allowEmpty?: false;\n value?: TimeValue;\n defaultValue?: TimeValue;\n onChange?: (value: TimeValue) => void;\n }\n | {\n /** Start unset and allow clearing to null, distinct from midnight. */\n allowEmpty: true;\n value?: TimeValue | null;\n defaultValue?: TimeValue | null;\n onChange?: (value: TimeValue | null) => void;\n }\n );\n\n/* -------------------------------------------------------------------------- */\n/* Dropdown columns */\n/* -------------------------------------------------------------------------- */\n\ntype Segment = 'hour' | 'minute' | 'period';\n\ninterface ColumnOption {\n value: number;\n label: string;\n}\n\ninterface DropdownColumn {\n key: Segment;\n label: string;\n options: ColumnOption[];\n /** Index of the selected option, or -1 (a minute off the step grid). */\n selectedIndex: number;\n /** Index of the option that takes focus when the column is entered. */\n anchorIndex: number;\n}\n\ninterface TimePickerDropdownColumnsProps {\n columns: DropdownColumn[];\n columnRefs: MutableRefObject<Partial<Record<Segment, HTMLDivElement | null>>>;\n onPick: (column: Segment, value: number) => void;\n onOptionKeyDown: (\n event: KeyboardEvent<HTMLDivElement>,\n columnIndex: number,\n optionIndex: number,\n ) => void;\n}\n\n/** The listbox columns. Mounted with the panel, so its layout effect runs once the panel is in the DOM. */\nfunction TimePickerDropdownColumns({\n columns,\n columnRefs,\n onPick,\n onOptionKeyDown,\n}: TimePickerDropdownColumnsProps) {\n const selectionKey = columns.map((c) => c.selectedIndex).join(':');\n const hasCentredRef = useRef(false);\n\n // Centre each column's selected option when the panel opens; afterwards\n // (typed values update the columns live) only scroll one that is out of\n // view, so a pointer pick never jumps the list under the pointer.\n useIsomorphicLayoutEffect(() => {\n const centreAll = !hasCentredRef.current;\n hasCentredRef.current = true;\n for (const list of Object.values(columnRefs.current)) {\n if (!list) continue;\n const option =\n list.querySelector<HTMLElement>('[aria-selected=\"true\"]') ??\n list.querySelector<HTMLElement>('[role=\"option\"][tabindex=\"0\"]');\n if (!option) continue;\n const top = option.offsetTop;\n const bottom = top + option.offsetHeight;\n const inView =\n top >= list.scrollTop && bottom <= list.scrollTop + list.clientHeight;\n if (centreAll || !inView) {\n list.scrollTop = top - (list.clientHeight - option.offsetHeight) / 2;\n }\n }\n }, [selectionKey, columnRefs]);\n\n return (\n <>\n {columns.map((column, columnIndex) => (\n <div\n key={column.key}\n ref={(node) => {\n columnRefs.current[column.key] = node;\n }}\n role=\"listbox\"\n aria-label={column.label}\n data-column={column.key}\n className={columnVariants({ separated: columnIndex > 0 })}\n >\n {column.options.map((option, optionIndex) => {\n const selected = optionIndex === column.selectedIndex;\n return (\n <div\n key={option.value}\n role=\"option\"\n aria-selected={selected}\n tabIndex={optionIndex === column.anchorIndex ? 0 : -1}\n data-value={option.value}\n className={optionVariants({ selected })}\n onClick={() => onPick(column.key, option.value)}\n onKeyDown={(event) =>\n onOptionKeyDown(event, columnIndex, optionIndex)\n }\n >\n {option.label}\n </div>\n );\n })}\n </div>\n ))}\n </>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------------- */\n\nexport const TimePicker = forwardRef<HTMLDivElement, TimePickerProps>(\n (props, ref) => {\n const {\n value,\n allowEmpty = false,\n defaultValue,\n onChange,\n hour12: hour12Prop,\n minuteStep = 1,\n fullWidthSeparator = false,\n periodLabels: periodLabelsProp,\n size = 'md',\n dropdown = false,\n disabled,\n className,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n } = props;\n const onEmptyChange = props.allowEmpty ? props.onChange : undefined;\n const { t, i18n } = useTranslation('ui');\n const ctx = useFormField();\n // Inside a FormField the group is named by the field's label.\n const inFormField = useContext(FormFieldContext) !== null;\n const effectiveId = useFormFieldControlId(ctx, id);\n const effectiveDisabled = Boolean(ctx.disabled || disabled);\n const effectiveTone = ctx.invalid ? 'error' : 'default';\n\n const isHour12 =\n hour12Prop !== undefined ? hour12Prop : detectHour12(i18n.language);\n const localePeriods = getLocalePeriodLabels(i18n.language);\n const periods = periodLabelsProp ?? localePeriods;\n\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState<TimeValue | null>(\n value !== undefined\n ? value\n : defaultValue !== undefined\n ? defaultValue\n : allowEmpty\n ? null\n : { hours: 0, minutes: 0 },\n );\n const rawValue = isControlled ? value : internalValue;\n const currentValue = useMemo(\n () => (allowEmpty ? rawValue : (rawValue ?? { hours: 0, minutes: 0 })),\n [allowEmpty, rawValue],\n );\n // An explicit edit starts from midnight; focus and opening never commit it.\n const editBase = () => latestValueRef.current ?? { hours: 0, minutes: 0 };\n\n // The latest value, for timers and blur commits that outlive the render\n // which scheduled them. `emit` moves it ahead of the next render.\n const latestValueRef = useRef(currentValue);\n latestValueRef.current = currentValue;\n\n const emit = useCallback(\n (next: TimeValue | null) => {\n latestValueRef.current = next;\n if (!isControlled) setInternalValue(next);\n if (next === null) onEmptyChange?.(null);\n else onChange?.(next);\n },\n [isControlled, onChange, onEmptyChange],\n );\n\n // Segment refs\n const rootRef = useRef<HTMLDivElement>(null);\n const hourRef = useRef<HTMLSpanElement>(null);\n const minuteRef = useRef<HTMLSpanElement>(null);\n const periodRef = useRef<HTMLSpanElement>(null);\n\n /* ---------------------------------------------------------------- */\n /* Typing: a first digit that could start a two-digit value waits */\n /* for the second. It commits after a second or when the user */\n /* leaves the segment; stepping with the arrows replaces it. */\n /* ---------------------------------------------------------------- */\n\n const hourPendingRef = useRef('');\n const minutePendingRef = useRef('');\n const hourTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const minuteTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const cancelHourPending = () => {\n hourPendingRef.current = '';\n if (hourTimerRef.current) {\n clearTimeout(hourTimerRef.current);\n hourTimerRef.current = null;\n }\n };\n\n const cancelMinutePending = () => {\n minutePendingRef.current = '';\n if (minuteTimerRef.current) {\n clearTimeout(minuteTimerRef.current);\n minuteTimerRef.current = null;\n }\n };\n\n // A parent reset or a disabled field must not be undone by a pending digit.\n useIsomorphicLayoutEffect(() => {\n if (value === null || effectiveDisabled) {\n cancelHourPending();\n cancelMinutePending();\n }\n }, [value, effectiveDisabled]);\n\n const clearValue = useCallback(() => {\n hourPendingRef.current = '';\n minutePendingRef.current = '';\n if (hourTimerRef.current) clearTimeout(hourTimerRef.current);\n if (minuteTimerRef.current) clearTimeout(minuteTimerRef.current);\n hourTimerRef.current = null;\n minuteTimerRef.current = null;\n emit(allowEmpty ? null : { hours: 0, minutes: 0 });\n }, [allowEmpty, emit]);\n\n const clearFromKeyboard = (e: KeyboardEvent<HTMLSpanElement>): boolean => {\n if (!allowEmpty || (e.key !== 'Backspace' && e.key !== 'Delete'))\n return false;\n e.preventDefault();\n clearValue();\n return true;\n };\n\n const commitHourDigits = (digits: string) => {\n const base = editBase();\n const clamped = clamp(\n parseInt(digits, 10),\n isHour12 ? 1 : 0,\n isHour12 ? 12 : 23,\n );\n emit({\n ...base,\n hours: isHour12 ? to24Hour(clamped, base.hours >= 12) : clamped,\n });\n };\n\n const commitMinuteDigits = (digits: string) => {\n emit({\n ...editBase(),\n minutes: snapMinuteToStep(parseInt(digits, 10), minuteStep),\n });\n };\n\n const flushHourPending = () => {\n const pending = hourPendingRef.current;\n cancelHourPending();\n if (pending) commitHourDigits(pending);\n };\n\n const flushMinutePending = () => {\n const pending = minutePendingRef.current;\n cancelMinutePending();\n if (pending) commitMinuteDigits(pending);\n };\n\n // Timers call the latest render's flush, so a commit uses the current\n // `onChange` and 12h/step settings.\n const flushRef = useRef({\n hour: flushHourPending,\n minute: flushMinutePending,\n });\n flushRef.current = { hour: flushHourPending, minute: flushMinutePending };\n\n // Cleanup timers\n useEffect(() => {\n return () => {\n if (hourTimerRef.current) clearTimeout(hourTimerRef.current);\n if (minuteTimerRef.current) clearTimeout(minuteTimerRef.current);\n };\n }, []);\n\n const separator = fullWidthSeparator ? ':' : ':';\n\n // Display values\n const unsetLabel = t('inputs.timePicker.unset', 'No time set');\n const displayHour =\n currentValue === null\n ? '--'\n : isHour12\n ? pad2(to12Hour(currentValue.hours))\n : pad2(currentValue.hours);\n const displayMinute =\n currentValue === null ? '--' : pad2(currentValue.minutes);\n const isPM = (currentValue?.hours ?? 0) >= 12;\n\n /* ---------------------------------------------------------------- */\n /* Dropdown state */\n /* ---------------------------------------------------------------- */\n\n const [open, setOpenState] = useState(false);\n const isOpen = dropdown && open;\n // Read by the handle, so `open()` then `isOpen()` agree before a render.\n const openRef = useRef(open);\n openRef.current = open;\n const setOpen = useCallback((next: boolean) => {\n openRef.current = next;\n setOpenState(next);\n }, []);\n const [dropdownDir, setDropdownDir] = useState<'ltr' | 'rtl'>('ltr');\n /** `keyboard` moves focus into the list on open; `pointer` leaves it where it is. */\n const openModeRef = useRef<'pointer' | 'keyboard'>('pointer');\n const initialColumnRef = useRef<Segment>('hour');\n /** Where Escape (and a close with focus inside the list) sends focus. */\n const returnFocusRef = useRef<HTMLElement | null>(null);\n /** Set when focus moved on by itself (outside click, Tab): leave it there on close. */\n const skipFocusReturnRef = useRef(false);\n const contentRef = useRef<HTMLDivElement | null>(null);\n const clockButtonRef = useRef<HTMLButtonElement>(null);\n const columnRefs = useRef<Partial<Record<Segment, HTMLDivElement | null>>>(\n {},\n );\n\n const focusColumn = useCallback((column: Segment) => {\n columnRefs.current[column]\n ?.querySelector<HTMLElement>('[role=\"option\"][tabindex=\"0\"]')\n ?.focus({ preventScroll: true });\n }, []);\n\n const handleOpenChange = useCallback(\n (next: boolean) => {\n if (next) {\n if (effectiveDisabled) return;\n // Portalled to <body>, so the panel inherits no direction: copy\n // the field's.\n const root = rootRef.current;\n setDropdownDir(\n root && window.getComputedStyle(root).direction === 'rtl'\n ? 'rtl'\n : 'ltr',\n );\n skipFocusReturnRef.current = false;\n }\n setOpen(next);\n },\n [effectiveDisabled, setOpen],\n );\n\n const openDropdown = (\n mode: 'pointer' | 'keyboard',\n column: Segment,\n returnTo: HTMLElement | null,\n ) => {\n if (!dropdown || effectiveDisabled) return;\n openModeRef.current = mode;\n initialColumnRef.current = column;\n returnFocusRef.current = returnTo;\n if (open) {\n if (mode === 'keyboard') focusColumn(column);\n return;\n }\n handleOpenChange(true);\n };\n\n // Turning `dropdown` off, or disabling the picker, closes the list.\n useEffect(() => {\n if (open && (!dropdown || effectiveDisabled)) setOpen(false);\n }, [open, dropdown, effectiveDisabled, setOpen]);\n\n // Alt+ArrowDown on a segment opens the list on that segment's column;\n // with the list open, Alt+ArrowUp closes it, as it does in the list.\n const openFromSegment = (\n e: KeyboardEvent<HTMLSpanElement>,\n column: Segment,\n ): boolean => {\n if (!dropdown || !e.altKey) return false;\n if (e.key === 'ArrowUp' && open) {\n e.preventDefault();\n setOpen(false);\n return true;\n }\n if (e.key !== 'ArrowDown') return false;\n e.preventDefault();\n flushHourPending();\n flushMinutePending();\n openDropdown('keyboard', column, e.currentTarget);\n return true;\n };\n\n // Hour segment keyboard handler\n const handleHourKeyDown = (e: KeyboardEvent<HTMLSpanElement>) => {\n if (effectiveDisabled) return;\n if (clearFromKeyboard(e)) return;\n if (openFromSegment(e, 'hour')) return;\n\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault();\n cancelHourPending();\n const base = editBase();\n const delta = e.key === 'ArrowUp' ? 1 : -1;\n const maxH = 23;\n let newH = base.hours + delta;\n if (newH < 0) newH = maxH;\n if (newH > maxH) newH = 0;\n emit({ ...base, hours: newH });\n return;\n }\n\n if (e.key === 'Tab' && !e.shiftKey) {\n e.preventDefault();\n // Leaving the segment commits a pending digit (see the blur handler).\n minuteRef.current?.focus();\n return;\n }\n\n if (e.key.length === 1 && e.key >= '0' && e.key <= '9') {\n e.preventDefault();\n if (hourTimerRef.current) clearTimeout(hourTimerRef.current);\n const next = hourPendingRef.current + e.key;\n // A first digit that cannot start a two-digit hour commits now.\n const complete =\n next.length >= 2 || parseInt(next, 10) > (isHour12 ? 1 : 2);\n if (complete) {\n cancelHourPending();\n commitHourDigits(next);\n minuteRef.current?.focus();\n } else {\n hourPendingRef.current = next;\n hourTimerRef.current = setTimeout(\n () => flushRef.current.hour(),\n 1000,\n );\n }\n }\n };\n\n // Minute segment keyboard handler\n const handleMinuteKeyDown = (e: KeyboardEvent<HTMLSpanElement>) => {\n if (effectiveDisabled) return;\n if (clearFromKeyboard(e)) return;\n if (openFromSegment(e, 'minute')) return;\n\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault();\n cancelMinutePending();\n const base = editBase();\n emit({\n ...base,\n minutes: stepMinute(\n base.minutes,\n minuteStep,\n e.key === 'ArrowUp' ? 1 : -1,\n ),\n });\n return;\n }\n\n if (e.key === 'Tab' && !e.shiftKey && isHour12) {\n e.preventDefault();\n periodRef.current?.focus();\n return;\n }\n\n if (e.key === 'Tab' && e.shiftKey) {\n e.preventDefault();\n hourRef.current?.focus();\n return;\n }\n\n if (e.key.length === 1 && e.key >= '0' && e.key <= '9') {\n e.preventDefault();\n if (minuteTimerRef.current) clearTimeout(minuteTimerRef.current);\n const next = minutePendingRef.current + e.key;\n // 6–9 cannot start a two-digit minute, so it commits now.\n const complete = next.length >= 2 || parseInt(next, 10) > 5;\n if (complete) {\n cancelMinutePending();\n commitMinuteDigits(next);\n if (isHour12) {\n periodRef.current?.focus();\n }\n } else {\n minutePendingRef.current = next;\n minuteTimerRef.current = setTimeout(\n () => flushRef.current.minute(),\n 1000,\n );\n }\n }\n };\n\n // Period toggle handler\n const handlePeriodKeyDown = (e: KeyboardEvent<HTMLSpanElement>) => {\n if (effectiveDisabled) return;\n if (clearFromKeyboard(e)) return;\n if (openFromSegment(e, 'period')) return;\n const base = editBase();\n const basePM = base.hours >= 12;\n\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault();\n const newH = basePM ? base.hours - 12 : base.hours + 12;\n emit({ ...base, hours: clamp(newH, 0, 23) });\n return;\n }\n\n if (e.key === 'Tab' && e.shiftKey) {\n e.preventDefault();\n minuteRef.current?.focus();\n return;\n }\n\n // a/p keys toggle AM/PM\n if (e.key === 'a' || e.key === 'A') {\n e.preventDefault();\n if (latestValueRef.current === null || basePM) {\n emit({ ...base, hours: basePM ? base.hours - 12 : base.hours });\n }\n }\n if (e.key === 'p' || e.key === 'P') {\n e.preventDefault();\n if (!basePM) {\n emit({ ...base, hours: base.hours + 12 });\n }\n }\n };\n\n // Leaving a segment commits a lone typed digit (\"5\" then a click on Save\n // is 05) and rounds nothing else: an untouched 12:58 stays 12:58.\n const handleHourBlur = () => {\n flushHourPending();\n };\n\n const handleMinuteBlur = () => {\n flushMinutePending();\n };\n\n const hourLabel = t('inputs.timePicker.hour', 'Hour');\n const minuteLabel = t('inputs.timePicker.minute', 'Minute');\n const periodLabel = t('inputs.timePicker.period', 'Period');\n const groupLabel = t('inputs.timePicker.groupLabel', 'Time');\n const openDropdownLabel = t(\n 'inputs.timePicker.openDropdown',\n 'Choose time',\n );\n\n // The FormField's label names this picker only while its `for` points\n // here. Several controls can share one field (DateTimePicker's trigger\n // and its own TimePicker): the others keep their own name.\n const formFieldLabelId = `${ctx.id}-label`;\n const hasFormFieldLabel = inFormField && Boolean(ctx.label);\n const [isLabelTarget, setIsLabelTarget] = useState(true);\n\n // Accessible name: an explicit aria-labelledby, then an explicit\n // aria-label, then the FormField's label, then \"Time\".\n const groupLabelledBy =\n ariaLabelledBy ??\n (!ariaLabel && hasFormFieldLabel && isLabelTarget\n ? formFieldLabelId\n : undefined);\n const groupAriaLabel = groupLabelledBy\n ? undefined\n : (ariaLabel ?? groupLabel);\n\n // The clear button names its field when a text label is known.\n const clearFieldLabel =\n ariaLabel ?? (hasFormFieldLabel ? ctx.label : undefined);\n const clearLabel = clearFieldLabel\n ? t('inputs.timePicker.clearNamed', { label: clearFieldLabel })\n : t('inputs.text.clear');\n\n // FormField's `<label for>` points at this group, which is not labelable,\n // so the browser does nothing with a click on it. Focus the hours instead.\n useEffect(() => {\n if (!hasFormFieldLabel) return undefined;\n const scope = rootRef.current?.getRootNode();\n const label =\n scope instanceof Document || scope instanceof ShadowRoot\n ? scope.getElementById(formFieldLabelId)\n : null;\n if (!(label instanceof HTMLLabelElement)) {\n setIsLabelTarget(false);\n return undefined;\n }\n const sync = () => setIsLabelTarget(label.htmlFor === effectiveId);\n sync();\n // The field moves `for` to a control that registers after mount.\n const observer = new MutationObserver(sync);\n observer.observe(label, { attributes: true, attributeFilter: ['for'] });\n const onLabelClick = () => {\n if (label.htmlFor !== effectiveId || effectiveDisabled) return;\n hourRef.current?.focus();\n };\n label.addEventListener('click', onLabelClick);\n return () => {\n observer.disconnect();\n label.removeEventListener('click', onLabelClick);\n };\n }, [hasFormFieldLabel, formFieldLabelId, effectiveId, effectiveDisabled]);\n\n /* ---------------------------------------------------------------- */\n /* Dropdown columns and handlers */\n /* ---------------------------------------------------------------- */\n\n const hourOptions = useMemo<ColumnOption[]>(\n () =>\n Array.from({ length: isHour12 ? 12 : 24 }, (_, i) =>\n isHour12 ? i + 1 : i,\n ).map((hour) => ({ value: hour, label: pad2(hour) })),\n [isHour12],\n );\n const minuteOptions = useMemo<ColumnOption[]>(() => {\n const options: ColumnOption[] = [];\n for (let minute = 0; minute <= 59; minute += minuteStep) {\n options.push({ value: minute, label: pad2(minute) });\n }\n return options;\n }, [minuteStep]);\n\n const columns: DropdownColumn[] = [];\n if (dropdown) {\n const hourSelected = hourOptions.findIndex(\n (o) =>\n o.value ===\n (currentValue === null\n ? undefined\n : isHour12\n ? to12Hour(currentValue.hours)\n : currentValue.hours),\n );\n columns.push({\n key: 'hour',\n label: hourLabel,\n options: hourOptions,\n selectedIndex: hourSelected,\n anchorIndex: Math.max(hourSelected, 0),\n });\n // A minute off the step grid (07 with step 5) selects nothing; focus\n // enters the column at the grid value just before it.\n const minuteSelected = minuteOptions.findIndex(\n (o) => o.value === currentValue?.minutes,\n );\n columns.push({\n key: 'minute',\n label: minuteLabel,\n options: minuteOptions,\n selectedIndex: minuteSelected,\n anchorIndex:\n minuteSelected >= 0\n ? minuteSelected\n : clamp(\n Math.floor((currentValue?.minutes ?? 0) / minuteStep),\n 0,\n minuteOptions.length - 1,\n ),\n });\n if (isHour12) {\n columns.push({\n key: 'period',\n label: periodLabel,\n options: [\n { value: 0, label: periods.am },\n { value: 1, label: periods.pm },\n ],\n selectedIndex: currentValue === null ? -1 : isPM ? 1 : 0,\n anchorIndex: isPM ? 1 : 0,\n });\n }\n }\n\n // An hour or AM/PM pick keeps the list open; a minute pick closes it and\n // returns focus to the minute segment.\n const pickOption = (column: Segment, optionValue: number) => {\n cancelHourPending();\n cancelMinutePending();\n const base = editBase();\n if (column === 'hour') {\n const hours = isHour12\n ? to24Hour(optionValue, base.hours >= 12)\n : optionValue;\n if (latestValueRef.current === null || hours !== base.hours)\n emit({ ...base, hours });\n return;\n }\n if (column === 'period') {\n const wantPM = optionValue === 1;\n if (latestValueRef.current === null || wantPM !== base.hours >= 12) {\n emit({ ...base, hours: (base.hours % 12) + (wantPM ? 12 : 0) });\n }\n return;\n }\n if (latestValueRef.current === null || optionValue !== base.minutes) {\n emit({ ...base, minutes: optionValue });\n }\n minuteRef.current?.focus();\n setOpen(false);\n };\n\n const handleOptionKeyDown = (\n e: KeyboardEvent<HTMLDivElement>,\n columnIndex: number,\n optionIndex: number,\n ) => {\n const column = columns[columnIndex];\n if (!column) return;\n const last = column.options.length - 1;\n const focusOption = (index: number) => {\n columnRefs.current[column.key]\n ?.querySelectorAll<HTMLElement>('[role=\"option\"]')\n [index]?.focus();\n };\n\n if (e.altKey && e.key === 'ArrowUp') {\n e.preventDefault();\n returnFocusRef.current?.focus();\n setOpen(false);\n return;\n }\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n focusOption(Math.min(optionIndex + 1, last));\n break;\n case 'ArrowUp':\n e.preventDefault();\n focusOption(Math.max(optionIndex - 1, 0));\n break;\n case 'Home':\n e.preventDefault();\n focusOption(0);\n break;\n case 'End':\n e.preventDefault();\n focusOption(last);\n break;\n case 'ArrowLeft':\n case 'ArrowRight': {\n e.preventDefault();\n // Columns follow the reading direction: in RTL the hours are on\n // the right, so ArrowLeft moves on to the minutes.\n const forward = (e.key === 'ArrowRight') === (dropdownDir === 'ltr');\n const target = columns[columnIndex + (forward ? 1 : -1)];\n if (target) focusColumn(target.key);\n break;\n }\n case 'Enter':\n case ' ': {\n e.preventDefault();\n const option = column.options[optionIndex];\n if (option) pickOption(column.key, option.value);\n break;\n }\n case 'Tab':\n // Leave the picker in the direction of travel and close. No\n // preventDefault: the browser moves on from the new focus, even\n // out of the page, so the close must not bring it back.\n skipFocusReturnRef.current = true;\n if (e.shiftKey) {\n hourRef.current?.focus();\n } else {\n clockButtonRef.current?.focus();\n }\n setOpen(false);\n break;\n default:\n break;\n }\n };\n\n // A click anywhere on the field opens the list. Focus stays on the\n // segment that was clicked, so typing still works.\n const handleFieldClick = (e: MouseEvent<HTMLDivElement>) => {\n if (!dropdown || effectiveDisabled) return;\n const target = e.target;\n if (!(target instanceof Node)) return;\n // The clock button opens and closes the list itself.\n if (clockButtonRef.current?.contains(target)) return;\n const segments = [hourRef.current, minuteRef.current, periodRef.current];\n let segment = segments.find((s) => s?.contains(target)) ?? null;\n if (!segment) {\n // The padding or the separator: keep a focused segment, else hours.\n const active = target.ownerDocument?.activeElement;\n segment = segments.find((s) => s && s === active) ?? hourRef.current;\n if (segment && segment !== active) segment.focus();\n }\n openDropdown('pointer', 'hour', segment);\n };\n\n // Child handlers run before Radix's toggle, so the mode is set first.\n const handleClockClick = (e: MouseEvent<HTMLButtonElement>) => {\n // Enter and Space reach a button as a click with no pointer detail.\n openModeRef.current = e.detail === 0 ? 'keyboard' : 'pointer';\n initialColumnRef.current = 'hour';\n returnFocusRef.current = e.currentTarget;\n };\n\n const handleContentOpenAutoFocus = (e: Event) => {\n // Never steal focus on a pointer open.\n e.preventDefault();\n if (openModeRef.current === 'keyboard') {\n focusColumn(initialColumnRef.current);\n }\n };\n\n const handleContentCloseAutoFocus = (e: Event) => {\n e.preventDefault();\n const skip = skipFocusReturnRef.current;\n skipFocusReturnRef.current = false;\n if (skip) return;\n // Focus went down with the panel: send it back where it came from.\n const active = document.activeElement;\n if (!active || active === document.body) {\n returnFocusRef.current?.focus();\n }\n };\n\n const handleContentInteractOutside = (e: Event) => {\n const target = e.target;\n // The field is the panel's anchor: clicking or focusing a segment\n // keeps the list open.\n if (target instanceof Node && rootRef.current?.contains(target)) {\n e.preventDefault();\n return;\n }\n skipFocusReturnRef.current = true;\n };\n\n const handleContentEscapeKeyDown = () => {\n if (contentRef.current?.contains(document.activeElement)) {\n returnFocusRef.current?.focus();\n }\n };\n\n // Inside a modal Dialog, its scroll lock cancels every wheel and\n // touchmove that starts outside the dialog's own DOM, and the panel is\n // portalled outside it, so the columns would not scroll by mouse or\n // touch. Stopping the two events at the panel keeps them from the\n // lock's document listener; the column scrolls natively and\n // `overscroll-contain` keeps the page still.\n const contentCallbackRef = useCallback((node: HTMLDivElement | null) => {\n const stop = stopScrollLockPropagation;\n contentRef.current?.removeEventListener('wheel', stop);\n contentRef.current?.removeEventListener('touchmove', stop);\n contentRef.current = node;\n node?.addEventListener('wheel', stop, { passive: true });\n node?.addEventListener('touchmove', stop, { passive: true });\n }, []);\n\n const handleContentMouseDown = (e: MouseEvent<HTMLDivElement>) => {\n // After a pointer open focus stays on the segment, so typing works:\n // a click in the list must not take it.\n if (!contentRef.current?.contains(document.activeElement)) {\n e.preventDefault();\n }\n };\n\n const handle = useMemo<TimePickerHandle>(\n () => ({\n getValue: () => currentValue,\n setValue: (next) => emit(normaliseTime(next)),\n clear: clearValue,\n isOpen: () => dropdown && openRef.current,\n open: () => {\n if (!dropdown || effectiveDisabled) return;\n openModeRef.current = 'pointer';\n handleOpenChange(true);\n },\n close: () => {\n if (dropdown) setOpen(false);\n },\n }),\n [\n currentValue,\n emit,\n clearValue,\n dropdown,\n effectiveDisabled,\n handleOpenChange,\n setOpen,\n ],\n );\n\n useImperativeHandle(ref, () => rootRef.current as HTMLDivElement, []);\n useAgentRegistration(timePickerAgent, handle, effectiveId);\n\n const field = (\n // eslint-disable-next-line jsx-a11y/role-supports-aria-props, jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions -- aria-invalid is a global ARIA state conveying group-level validation; the click is a pointer shortcut to the list, which the keyboard opens with Alt+ArrowDown or the clock button\n <div\n ref={rootRef}\n id={effectiveId}\n role=\"group\"\n aria-label={groupAriaLabel}\n aria-labelledby={groupLabelledBy}\n aria-describedby={ctx.describedBy || undefined}\n aria-invalid={ctx.invalid || undefined}\n // `aria-required` is not valid on `role=\"group\"` per ARIA 1.2 — the\n // FormField label's visible asterisk + `aria-describedby` link\n // communicate the required state instead.\n aria-disabled={effectiveDisabled || undefined}\n data-component=\"time-picker\"\n data-component-id={effectiveId}\n className={wrapperVariants({\n size,\n tone: effectiveTone,\n isDisabled: effectiveDisabled,\n opensOnClick: dropdown && !effectiveDisabled,\n className,\n })}\n onClick={dropdown ? handleFieldClick : undefined}\n >\n {/* Hour segment */}\n <span\n ref={hourRef}\n role=\"spinbutton\"\n aria-disabled={effectiveDisabled || undefined}\n aria-label={hourLabel}\n aria-valuemin={isHour12 ? 1 : 0}\n aria-valuemax={isHour12 ? 12 : 23}\n aria-valuenow={\n currentValue === null\n ? undefined\n : isHour12\n ? to12Hour(currentValue.hours)\n : currentValue.hours\n }\n aria-valuetext={currentValue === null ? unsetLabel : displayHour}\n aria-keyshortcuts={dropdown ? 'Alt+ArrowDown' : undefined}\n tabIndex={effectiveDisabled ? -1 : 0}\n inputMode=\"numeric\"\n onKeyDown={handleHourKeyDown}\n onBlur={handleHourBlur}\n className={segmentVariants({ size })}\n >\n {displayHour}\n </span>\n\n {/* Separator */}\n <span aria-hidden=\"true\" className={separatorVariants({ size })}>\n {separator}\n </span>\n\n {/* Minute segment */}\n <span\n ref={minuteRef}\n role=\"spinbutton\"\n aria-disabled={effectiveDisabled || undefined}\n aria-label={minuteLabel}\n aria-valuemin={0}\n aria-valuemax={59}\n aria-valuenow={currentValue?.minutes}\n aria-valuetext={currentValue === null ? unsetLabel : displayMinute}\n aria-keyshortcuts={dropdown ? 'Alt+ArrowDown' : undefined}\n tabIndex={effectiveDisabled ? -1 : 0}\n inputMode=\"numeric\"\n onKeyDown={handleMinuteKeyDown}\n onBlur={handleMinuteBlur}\n className={segmentVariants({ size })}\n >\n {displayMinute}\n </span>\n\n {/* AM/PM toggle (12h mode only) */}\n {isHour12 ? (\n <span\n ref={periodRef}\n role=\"spinbutton\"\n aria-disabled={effectiveDisabled || undefined}\n aria-label={periodLabel}\n aria-valuemin={0}\n aria-valuemax={1}\n aria-valuenow={currentValue === null ? undefined : isPM ? 1 : 0}\n aria-valuetext={\n currentValue === null\n ? unsetLabel\n : isPM\n ? periods.pm\n : periods.am\n }\n aria-keyshortcuts={dropdown ? 'Alt+ArrowDown' : undefined}\n tabIndex={effectiveDisabled ? -1 : 0}\n onKeyDown={handlePeriodKeyDown}\n className={periodButtonVariants({ size })}\n >\n {currentValue === null ? '--' : isPM ? periods.pm : periods.am}\n </span>\n ) : null}\n\n {allowEmpty ? (\n <button\n type=\"button\"\n aria-label={clearLabel}\n disabled={effectiveDisabled || currentValue === null}\n // Prevent blur from committing pending digits before the clear.\n onPointerDown={(event) => {\n event.preventDefault();\n cancelHourPending();\n cancelMinutePending();\n }}\n onClick={(event) => {\n event.stopPropagation();\n clearValue();\n hourRef.current?.focus();\n }}\n // An empty field has nothing to clear: keep the slot, hide the control.\n className={clockButtonVariants({\n size,\n trailing: !dropdown,\n className: currentValue === null ? 'ds:invisible' : undefined,\n })}\n >\n <X aria-hidden=\"true\" />\n </button>\n ) : null}\n\n {/* Clock button: opens the list (dropdown only). Radix adds\n aria-haspopup=\"dialog\", aria-expanded and aria-controls. */}\n {dropdown ? (\n <Popover.Trigger asChild>\n <button\n ref={clockButtonRef}\n type=\"button\"\n aria-label={openDropdownLabel}\n disabled={effectiveDisabled}\n onClick={handleClockClick}\n className={clockButtonVariants({ size })}\n >\n <Clock aria-hidden=\"true\" />\n </button>\n </Popover.Trigger>\n ) : null}\n </div>\n );\n\n if (!dropdown) return field;\n\n return (\n <Popover.Root open={isOpen} onOpenChange={handleOpenChange}>\n {/* The whole field anchors the panel, so it lines up with the\n field's start rather than the clock button. */}\n <Popover.Anchor asChild>{field}</Popover.Anchor>\n <Popover.Portal>\n <Popover.Content\n ref={contentCallbackRef}\n side=\"bottom\"\n align=\"start\"\n sideOffset={4}\n dir={dropdownDir}\n /* Portalled to <body>, outside the field's [data-component]\n scope: it needs its own marker for the kit's baselines. */\n data-component=\"time-picker-dropdown\"\n aria-label={groupAriaLabel}\n aria-labelledby={groupLabelledBy}\n className={dropdownContentVariants({ size })}\n onOpenAutoFocus={handleContentOpenAutoFocus}\n onCloseAutoFocus={handleContentCloseAutoFocus}\n onInteractOutside={handleContentInteractOutside}\n onEscapeKeyDown={handleContentEscapeKeyDown}\n onMouseDown={handleContentMouseDown}\n >\n <TimePickerDropdownColumns\n columns={columns}\n columnRefs={columnRefs}\n onPick={pickOption}\n onOptionKeyDown={handleOptionKeyDown}\n />\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n );\n },\n);\n\nTimePicker.displayName = 'TimePicker';\n"],"names":["timePickerAgent","handle","value","hh","mm","args","hStr","mStr","detectHour12","locale","resolved","getLocalePeriodLabels","am","_a","p","pm","_b","clamp","min","max","lastMinuteOnGrid","step","snapMinuteToStep","rounded","stepMinute","direction","last","next","previous","normaliseTime","whole","n","to12Hour","h24","to24Hour","h12","isPM","pad2","stopScrollLockPropagation","event","wrapperVariants","cva","segmentVariants","periodButtonVariants","separatorVariants","clockButtonVariants","dropdownContentVariants","columnVariants","optionVariants","TimePickerDropdownColumns","columns","columnRefs","onPick","onOptionKeyDown","selectionKey","c","hasCentredRef","useRef","useIsomorphicLayoutEffect","centreAll","list","option","top","bottom","inView","jsx","Fragment","column","columnIndex","node","optionIndex","selected","TimePicker","forwardRef","props","ref","allowEmpty","defaultValue","onChange","hour12Prop","minuteStep","fullWidthSeparator","periodLabelsProp","size","dropdown","disabled","className","id","ariaLabel","ariaLabelledBy","onEmptyChange","t","i18n","useTranslation","ctx","useFormField","inFormField","useContext","FormFieldContext","effectiveId","useFormFieldControlId","effectiveDisabled","effectiveTone","isHour12","localePeriods","periods","isControlled","internalValue","setInternalValue","useState","rawValue","currentValue","useMemo","editBase","latestValueRef","emit","useCallback","rootRef","hourRef","minuteRef","periodRef","hourPendingRef","minutePendingRef","hourTimerRef","minuteTimerRef","cancelHourPending","cancelMinutePending","clearValue","clearFromKeyboard","commitHourDigits","digits","base","clamped","commitMinuteDigits","flushHourPending","pending","flushMinutePending","flushRef","useEffect","separator","unsetLabel","displayHour","displayMinute","open","setOpenState","isOpen","openRef","setOpen","dropdownDir","setDropdownDir","openModeRef","initialColumnRef","returnFocusRef","skipFocusReturnRef","contentRef","clockButtonRef","focusColumn","handleOpenChange","root","openDropdown","mode","returnTo","openFromSegment","handleHourKeyDown","delta","maxH","newH","handleMinuteKeyDown","_c","handlePeriodKeyDown","basePM","handleHourBlur","handleMinuteBlur","hourLabel","minuteLabel","periodLabel","groupLabel","openDropdownLabel","formFieldLabelId","hasFormFieldLabel","isLabelTarget","setIsLabelTarget","groupLabelledBy","groupAriaLabel","clearFieldLabel","clearLabel","scope","label","sync","observer","onLabelClick","hourOptions","_","i","hour","minuteOptions","options","minute","hourSelected","o","minuteSelected","pickOption","optionValue","hours","wantPM","handleOptionKeyDown","focusOption","index","forward","target","handleFieldClick","segments","segment","s","active","handleClockClick","handleContentOpenAutoFocus","handleContentCloseAutoFocus","skip","handleContentInteractOutside","handleContentEscapeKeyDown","contentCallbackRef","stop","handleContentMouseDown","useImperativeHandle","useAgentRegistration","field","jsxs","X","Popover","Clock"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import { useTranslation as M } from "react-i18next";
|
|
|
5
5
|
import { u as Y } from "./registry-DvAUVLHh.js";
|
|
6
6
|
import { F as C } from "./form-field-CyHfOVKF.js";
|
|
7
7
|
import { N as B } from "./number-input-CVwI1ltI.js";
|
|
8
|
-
import { S } from "./select-
|
|
8
|
+
import { S } from "./select-BBDRYxJl.js";
|
|
9
9
|
import { I as D } from "./insert-result-CDMMt7q8.js";
|
|
10
10
|
const L = [
|
|
11
11
|
"weight",
|
|
@@ -334,4 +334,4 @@ export {
|
|
|
334
334
|
ee as b,
|
|
335
335
|
Q as c
|
|
336
336
|
};
|
|
337
|
-
//# sourceMappingURL=unit-converter-
|
|
337
|
+
//# sourceMappingURL=unit-converter-C95sa5y8.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unit-converter-BH5ueIhT.js","sources":["../../src/components/unit-converter/unit-converter.agent.ts","../../src/components/unit-converter/units.ts","../../src/components/unit-converter/unit-converter.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — UnitConverter. */\n/* */\n/* Generic clinical/everyday unit conversion. The agent-relevant surface */\n/* is the read-only converted result plus the structural inputs (category, */\n/* source value, from-unit, to-unit) and `set_value` actions to drive */\n/* them. Values are plain measurements — no patient identity. The handle */\n/* is the curated `UnitConverterHandle`. See `src/docs/26-agent-readiness`.*/\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { UnitConverterHandle } from './unit-converter';\nimport type { UnitCategory } from './units';\n\n/**\n * Measurement families, mirrored from `./units`'s `CATEGORIES`. Inlined as a\n * literal (rather than runtime-imported) so the ESM catalog build can load this\n * pure module without TS path resolution; `satisfies` keeps it in lockstep with\n * the `UnitCategory` union at compile time.\n */\nconst CATEGORIES = [\n 'weight',\n 'length',\n 'temperature',\n 'glucose',\n] as const satisfies readonly UnitCategory[];\n\nexport const unitConverterAgent: AgentAdapter<UnitConverterHandle> = {\n id: 'unit-converter',\n capabilities: ['set_value', 'view_change'],\n state: {\n category: {\n type: \"'weight' | 'length' | 'temperature' | 'glucose'\",\n descriptionKey: 'ui.agent.unitConverter.state.category',\n description:\n 'Active measurement family. Determines which from/to units are selectable.',\n read: (handle) => handle.getCategory(),\n },\n inputs: {\n type: '{ value: number | null, fromId: string, toId: string }',\n descriptionKey: 'ui.agent.unitConverter.state.inputs',\n description:\n 'Source value plus the from-unit and to-unit ids within the active category.',\n read: (handle) => handle.getInputs(),\n },\n result: {\n type: 'number | null',\n descriptionKey: 'ui.agent.unitConverter.state.result',\n description:\n 'Converted value in the to-unit, or null when the source value is empty.',\n read: (handle) => handle.getResult(),\n },\n },\n actions: {\n set_value: {\n safety: 'write',\n argsType: '{ value: number | null }',\n argsSchema: {\n type: 'object',\n properties: {\n value: {\n type: ['number', 'null'],\n description: 'Source value to convert, or null to clear.',\n },\n },\n required: ['value'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.unitConverter.actions.setValue',\n description: 'Set the source value to convert.',\n examples: [{ args: { value: 70 }, note: 'Convert 70 of the from-unit.' }],\n invoke: (handle, args: { value: number | null }) => {\n handle.setValue(args.value);\n },\n },\n set_units: {\n safety: 'read',\n argsType: '{ fromId?: string, toId?: string }',\n argsSchema: {\n type: 'object',\n properties: {\n fromId: {\n type: 'string',\n description: 'Source unit id within the active category.',\n },\n toId: {\n type: 'string',\n description: 'Target unit id within the active category.',\n },\n },\n additionalProperties: false,\n },\n idempotent: true,\n descriptionKey: 'ui.agent.unitConverter.actions.setUnits',\n description:\n 'Set the from-unit and/or to-unit. Ids outside the active category are ignored.',\n examples: [\n { args: { fromId: 'kg', toId: 'lb' }, note: 'Convert kg → lb.' },\n ],\n invoke: (handle, args: { fromId?: string; toId?: string }) => {\n handle.setUnits(args);\n },\n },\n set_category: {\n safety: 'read',\n argsType: \"{ category: 'weight' | 'length' | 'temperature' | 'glucose' }\",\n argsSchema: {\n type: 'object',\n properties: {\n category: {\n enum: [...CATEGORIES],\n description: 'Measurement family to switch to.',\n },\n },\n required: ['category'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.unitConverter.actions.setCategory',\n description:\n 'Switch the measurement family. Resets the from/to units to that category defaults.',\n invoke: (\n handle,\n args: {\n category: 'weight' | 'length' | 'temperature' | 'glucose';\n },\n ) => {\n handle.setCategory(args.category);\n },\n },\n get_result: {\n safety: 'read',\n returns: 'number | null',\n returnsSchema: { type: ['number', 'null'] },\n idempotent: true,\n descriptionKey: 'ui.agent.unitConverter.actions.getResult',\n description:\n 'Return the converted value in the to-unit, or null when no source value is set.',\n invoke: (handle) => handle.getResult(),\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'unit-converter',\n description: 'Marks the UnitConverter wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific converter instance.',\n },\n },\n};\n","/* ------------------------------------------------------------------ */\n/* Generic unit conversion — pure, framework-free, unit-testable. */\n/* */\n/* Every unit is described by an affine map to its category's base */\n/* unit: base = value * factor + offset. Conversion is base-in then */\n/* base-out, so the same code handles linear scales (weight, length, */\n/* glucose) and offset scales (temperature) uniformly. */\n/* ------------------------------------------------------------------ */\n\nexport type UnitCategory = 'weight' | 'length' | 'temperature' | 'glucose';\n\nexport interface UnitDef {\n id: string;\n category: UnitCategory;\n /** Multiplier to the category base unit. */\n factor: number;\n /** Additive offset to the base unit (non-zero only for temperature). */\n offset: number;\n}\n\n/* Base units: kg, cm, °C, mmol/L. */\nexport const UNITS: Record<string, UnitDef> = {\n // weight → base kg\n kg: { id: 'kg', category: 'weight', factor: 1, offset: 0 },\n g: { id: 'g', category: 'weight', factor: 0.001, offset: 0 },\n lb: { id: 'lb', category: 'weight', factor: 0.45359237, offset: 0 },\n oz: { id: 'oz', category: 'weight', factor: 0.028349523125, offset: 0 },\n // length → base cm\n cm: { id: 'cm', category: 'length', factor: 1, offset: 0 },\n m: { id: 'm', category: 'length', factor: 100, offset: 0 },\n in: { id: 'in', category: 'length', factor: 2.54, offset: 0 },\n ft: { id: 'ft', category: 'length', factor: 30.48, offset: 0 },\n // temperature → base °C (affine: °C = °F·5/9 − 32·5/9)\n c: { id: 'c', category: 'temperature', factor: 1, offset: 0 },\n f: { id: 'f', category: 'temperature', factor: 5 / 9, offset: (-32 * 5) / 9 },\n // glucose → base mmol/L (1 mg/dL = 1/18.0156 mmol/L)\n mmol_l: { id: 'mmol_l', category: 'glucose', factor: 1, offset: 0 },\n mg_dl: { id: 'mg_dl', category: 'glucose', factor: 1 / 18.0156, offset: 0 },\n};\n\nexport const UNITS_BY_CATEGORY: Record<UnitCategory, string[]> = {\n weight: ['kg', 'g', 'lb', 'oz'],\n length: ['cm', 'm', 'in', 'ft'],\n temperature: ['c', 'f'],\n glucose: ['mmol_l', 'mg_dl'],\n};\n\nexport const CATEGORIES: UnitCategory[] = [\n 'weight',\n 'length',\n 'temperature',\n 'glucose',\n];\n\n/**\n * Convert `value` from one unit to another. Both ids must belong to the same\n * category; mismatched categories throw (a programming error, not user input).\n */\nexport function convertUnits(\n value: number,\n fromId: string,\n toId: string,\n): number {\n const from = UNITS[fromId];\n const to = UNITS[toId];\n if (!from || !to) throw new Error(`Unknown unit: ${fromId} → ${toId}`);\n if (from.category !== to.category) {\n throw new Error(\n `Cannot convert across categories: ${from.category} → ${to.category}`,\n );\n }\n const base = value * from.factor + from.offset;\n return (base - to.offset) / to.factor;\n}\n","/* ------------------------------------------------------------------ */\n/* UnitConverter — generic clinical/everyday unit conversion across */\n/* weight, length, temperature and glucose. */\n/* */\n/* Maths lives in `./units` (pure, separately tested). */\n/* ------------------------------------------------------------------ */\n\nimport { forwardRef, useEffect, useMemo, useRef, useState } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { unitConverterAgent } from './unit-converter.agent';\nimport { FormField } from '../form-field';\nimport { NumberInput } from '../number-input';\nimport { Select } from '../select';\nimport {\n InsertButton,\n type InsertPayload,\n type InsertVariant,\n type InsertMode,\n} from '../_shared/insert-result';\nimport {\n type UnitCategory,\n CATEGORIES,\n UNITS_BY_CATEGORY,\n convertUnits,\n} from './units';\n\nconst rootVariants = cva('ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]', {\n variants: {\n width: { full: 'ds:w-full', auto: 'ds:inline-flex' },\n },\n defaultVariants: { width: 'full' },\n});\n\n/**\n * DS token NAME backing the result-card category chip, one per measurement\n * family. The converter shows no on-screen badge, but the inserted card carries\n * a category chip so the reader can tell at a glance which family the figure\n * belongs to; each token is a closed-palette semantic alias resolved to a\n * concrete colour at raster time by `InsertButton`.\n */\nconst CATEGORY_HIGHLIGHT_TOKEN: Record<UnitCategory, string> = {\n weight: '--info',\n length: '--success',\n temperature: '--warning-readable',\n glucose: '--accent',\n};\n\n/**\n * Category chip token. The `temperature` family resolves to `--warning-readable`,\n * which the result card's colour probe resolves in the live themed DOM: orange-600\n * in light, non-accessible mode (where bare `--warning` yellow only reaches\n * ~3.2:1 on the white card) and `--warning` elsewhere, whose deepened ramp already\n * clears contrast. Resolving the token NAME at the card means the choice tracks\n * the live theme regardless of where the theme class lives. Other families are\n * unchanged.\n */\nfunction categoryHighlightToken(category: UnitCategory): string {\n return CATEGORY_HIGHLIGHT_TOKEN[category];\n}\n\nexport interface UnitConverterProps extends VariantProps<typeof rootVariants> {\n /** Initial category. Defaults to `'weight'`. */\n defaultCategory?: UnitCategory;\n /** Fires with the converted value (and `null` when input is empty). */\n onResultChange?: (value: number | null) => void;\n /** When provided, shows an \"Insert\" button that emits the result for an editor. */\n onInsert?: (payload: InsertPayload) => void;\n /**\n * Which verb the result button performs. Defaults to `'insert'`.\n * Use `'copy'` in an app-shell surface (no editor to insert into) — the\n * button writes the result to the clipboard as a multi-format `ClipboardItem`.\n */\n insertVariant?: InsertVariant;\n /** `copy` variant only — fired after a successful clipboard write. */\n onCopy?: (mode: InsertMode) => void;\n /** `copy` variant only — fired if the clipboard write can't proceed. */\n onError?: (error: unknown) => void;\n /**\n * Brand wordmark printed in the inserted/copied result-card footer.\n * Omitted → no brand line (and no footer hairline); a string → that custom\n * brand; `false` → no brand line. Brand is opt-in.\n */\n insertBrand?: string | false;\n /** Opaque instance id, emitted as `data-component-id`. */\n id?: string;\n /** Extra class names on the wrapper. */\n className?: string;\n}\n\n/**\n * Curated imperative handle for agent / external automation. Reads/writes the\n * structural inputs (category, value, from/to units) and the converted result.\n * No patient identity. Consumed by the `unit-converter.agent.ts` adapter; the\n * public `ref` stays the DOM element.\n */\nexport interface UnitConverterHandle {\n /** Active measurement family. */\n getCategory: () => UnitCategory;\n /** Switch the measurement family (resets from/to units to that category). */\n setCategory: (next: UnitCategory) => void;\n /** Source value + from/to unit ids. */\n getInputs: () => { value: number | null; fromId: string; toId: string };\n /** Set the source value to convert. */\n setValue: (value: number | null) => void;\n /** Set from-unit and/or to-unit (ids outside the active category are ignored). */\n setUnits: (next: { fromId?: string; toId?: string }) => void;\n /** Converted value in the to-unit, or null when no source value is set. */\n getResult: () => number | null;\n}\n\nexport const UnitConverter = forwardRef<HTMLDivElement, UnitConverterProps>(\n (\n {\n defaultCategory = 'weight',\n onResultChange,\n onInsert,\n insertVariant = 'insert',\n onCopy,\n onError,\n insertBrand,\n id,\n width,\n className,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation('ui');\n\n const [category, setCategory] = useState<UnitCategory>(defaultCategory);\n const [value, setValue] = useState<number | null>(null);\n const [fromId, setFromId] = useState<string>(\n UNITS_BY_CATEGORY[defaultCategory][0],\n );\n const [toId, setToId] = useState<string>(\n UNITS_BY_CATEGORY[defaultCategory][1],\n );\n\n const handleCategoryChange = (next: string): void => {\n const cat = next as UnitCategory;\n const units = UNITS_BY_CATEGORY[cat];\n setCategory(cat);\n setFromId(units[0]);\n setToId(units[1] ?? units[0]);\n };\n\n const converted = useMemo(\n () => (value === null ? null : convertUnits(value, fromId, toId)),\n [value, fromId, toId],\n );\n\n const numberFmt = useMemo(\n () => new Intl.NumberFormat(i18n.language, { maximumFractionDigits: 3 }),\n [i18n.language],\n );\n\n useEffect(() => {\n onResultChange?.(converted);\n }, [converted, onResultChange]);\n\n // Live refs so the once-built agent handle reads/writes current state\n // without re-creating on every keystroke. Public `ref` stays the DOM node.\n const liveRef = useRef({ category, value, fromId, toId, converted });\n liveRef.current = { category, value, fromId, toId, converted };\n const agentHandle = useMemo<UnitConverterHandle>(\n () => ({\n getCategory: () => liveRef.current.category,\n setCategory: (next) => handleCategoryChange(next),\n getInputs: () => ({\n value: liveRef.current.value,\n fromId: liveRef.current.fromId,\n toId: liveRef.current.toId,\n }),\n setValue: (next) => setValue(next),\n setUnits: (next) => {\n const units = UNITS_BY_CATEGORY[liveRef.current.category];\n if (next.fromId !== undefined && units.includes(next.fromId)) {\n setFromId(next.fromId);\n }\n if (next.toId !== undefined && units.includes(next.toId)) {\n setToId(next.toId);\n }\n },\n getResult: () => liveRef.current.converted,\n }),\n [],\n );\n useAgentRegistration(unitConverterAgent, agentHandle, id);\n\n const categoryOptions = CATEGORIES.map((c) => ({\n value: c,\n label: t(`unitConverter.category.${c}`),\n }));\n const unitOptions = UNITS_BY_CATEGORY[category].map((u) => ({\n value: u,\n label: t(`unitConverter.units.${u}`),\n }));\n\n return (\n <div\n ref={ref}\n data-component=\"unit-converter\"\n data-component-id={id}\n className={rootVariants({ width, className })}\n >\n <FormField label={t('unitConverter.categoryLabel')}>\n <Select\n options={categoryOptions}\n value={category}\n onValueChange={handleCategoryChange}\n />\n </FormField>\n\n <div className=\"ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)] ds:sm:grid-cols-3\">\n <FormField label={t('unitConverter.value')}>\n <NumberInput mode=\"decimal\" value={value} onChange={setValue} />\n </FormField>\n <FormField label={t('unitConverter.from')}>\n <Select\n options={unitOptions}\n value={fromId}\n onValueChange={setFromId}\n />\n </FormField>\n <FormField label={t('unitConverter.to')}>\n <Select\n options={unitOptions}\n value={toId}\n onValueChange={setToId}\n />\n </FormField>\n </div>\n\n <p className=\"ds:sr-only\" role=\"status\" aria-live=\"polite\">\n {converted !== null\n ? `${numberFmt.format(value ?? 0)} ${t(\n `unitConverter.units.${fromId}`,\n )} = ${numberFmt.format(converted)} ${t(\n `unitConverter.units.${toId}`,\n )}`\n : ''}\n </p>\n\n {converted !== null ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <span className=\"type-label ds:text-muted-foreground\">\n {t('unitConverter.result')}\n </span>\n <span className=\"type-metric ds:text-foreground\">\n {numberFmt.format(converted)} {t(`unitConverter.units.${toId}`)}\n </span>\n {insertVariant === 'copy' || onInsert ? (\n <InsertButton\n variant={insertVariant}\n onInsert={onInsert}\n onCopy={onCopy}\n onError={onError}\n card={{\n title: t('insert.title.unitConverter'),\n icon: 'ruler',\n highlight: t(`unitConverter.category.${category}`),\n // Chip tints by measurement family so the inserted card\n // signals the category at a glance — with the contrast-safe\n // orange override for the `--warning` temperature family.\n highlightToken: categoryHighlightToken(category),\n brand: insertBrand,\n fields: [\n {\n // Source measurement → ruler glyph (matches the header).\n icon: 'ruler',\n label: t('unitConverter.from'),\n value: `${numberFmt.format(value ?? 0)} ${t(\n `unitConverter.units.${fromId}`,\n )}`,\n },\n {\n // Converted result → trending-up (arrow) glyph signals the\n // conversion direction to the output value.\n icon: 'trending-up',\n label: t('unitConverter.to'),\n value: `${numberFmt.format(converted)} ${t(\n `unitConverter.units.${toId}`,\n )}`,\n },\n ],\n }}\n />\n ) : null}\n </div>\n ) : (\n <p className=\"type-body ds:text-muted-foreground\">\n {t('unitConverter.empty')}\n </p>\n )}\n </div>\n );\n },\n);\n\nUnitConverter.displayName = 'UnitConverter';\n"],"names":["CATEGORIES","unitConverterAgent","handle","args","UNITS","UNITS_BY_CATEGORY","convertUnits","value","fromId","toId","from","to","rootVariants","cva","CATEGORY_HIGHLIGHT_TOKEN","categoryHighlightToken","category","UnitConverter","forwardRef","defaultCategory","onResultChange","onInsert","insertVariant","onCopy","onError","insertBrand","id","width","className","ref","t","i18n","useTranslation","setCategory","useState","setValue","setFromId","setToId","handleCategoryChange","next","cat","units","converted","useMemo","numberFmt","useEffect","liveRef","useRef","agentHandle","useAgentRegistration","categoryOptions","c","unitOptions","u","jsxs","jsx","FormField","Select","NumberInput","InsertButton"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"unit-converter-C95sa5y8.js","sources":["../../src/components/unit-converter/unit-converter.agent.ts","../../src/components/unit-converter/units.ts","../../src/components/unit-converter/unit-converter.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — UnitConverter. */\n/* */\n/* Generic clinical/everyday unit conversion. The agent-relevant surface */\n/* is the read-only converted result plus the structural inputs (category, */\n/* source value, from-unit, to-unit) and `set_value` actions to drive */\n/* them. Values are plain measurements — no patient identity. The handle */\n/* is the curated `UnitConverterHandle`. See `src/docs/26-agent-readiness`.*/\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { UnitConverterHandle } from './unit-converter';\nimport type { UnitCategory } from './units';\n\n/**\n * Measurement families, mirrored from `./units`'s `CATEGORIES`. Inlined as a\n * literal (rather than runtime-imported) so the ESM catalog build can load this\n * pure module without TS path resolution; `satisfies` keeps it in lockstep with\n * the `UnitCategory` union at compile time.\n */\nconst CATEGORIES = [\n 'weight',\n 'length',\n 'temperature',\n 'glucose',\n] as const satisfies readonly UnitCategory[];\n\nexport const unitConverterAgent: AgentAdapter<UnitConverterHandle> = {\n id: 'unit-converter',\n capabilities: ['set_value', 'view_change'],\n state: {\n category: {\n type: \"'weight' | 'length' | 'temperature' | 'glucose'\",\n descriptionKey: 'ui.agent.unitConverter.state.category',\n description:\n 'Active measurement family. Determines which from/to units are selectable.',\n read: (handle) => handle.getCategory(),\n },\n inputs: {\n type: '{ value: number | null, fromId: string, toId: string }',\n descriptionKey: 'ui.agent.unitConverter.state.inputs',\n description:\n 'Source value plus the from-unit and to-unit ids within the active category.',\n read: (handle) => handle.getInputs(),\n },\n result: {\n type: 'number | null',\n descriptionKey: 'ui.agent.unitConverter.state.result',\n description:\n 'Converted value in the to-unit, or null when the source value is empty.',\n read: (handle) => handle.getResult(),\n },\n },\n actions: {\n set_value: {\n safety: 'write',\n argsType: '{ value: number | null }',\n argsSchema: {\n type: 'object',\n properties: {\n value: {\n type: ['number', 'null'],\n description: 'Source value to convert, or null to clear.',\n },\n },\n required: ['value'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.unitConverter.actions.setValue',\n description: 'Set the source value to convert.',\n examples: [{ args: { value: 70 }, note: 'Convert 70 of the from-unit.' }],\n invoke: (handle, args: { value: number | null }) => {\n handle.setValue(args.value);\n },\n },\n set_units: {\n safety: 'read',\n argsType: '{ fromId?: string, toId?: string }',\n argsSchema: {\n type: 'object',\n properties: {\n fromId: {\n type: 'string',\n description: 'Source unit id within the active category.',\n },\n toId: {\n type: 'string',\n description: 'Target unit id within the active category.',\n },\n },\n additionalProperties: false,\n },\n idempotent: true,\n descriptionKey: 'ui.agent.unitConverter.actions.setUnits',\n description:\n 'Set the from-unit and/or to-unit. Ids outside the active category are ignored.',\n examples: [\n { args: { fromId: 'kg', toId: 'lb' }, note: 'Convert kg → lb.' },\n ],\n invoke: (handle, args: { fromId?: string; toId?: string }) => {\n handle.setUnits(args);\n },\n },\n set_category: {\n safety: 'read',\n argsType: \"{ category: 'weight' | 'length' | 'temperature' | 'glucose' }\",\n argsSchema: {\n type: 'object',\n properties: {\n category: {\n enum: [...CATEGORIES],\n description: 'Measurement family to switch to.',\n },\n },\n required: ['category'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.unitConverter.actions.setCategory',\n description:\n 'Switch the measurement family. Resets the from/to units to that category defaults.',\n invoke: (\n handle,\n args: {\n category: 'weight' | 'length' | 'temperature' | 'glucose';\n },\n ) => {\n handle.setCategory(args.category);\n },\n },\n get_result: {\n safety: 'read',\n returns: 'number | null',\n returnsSchema: { type: ['number', 'null'] },\n idempotent: true,\n descriptionKey: 'ui.agent.unitConverter.actions.getResult',\n description:\n 'Return the converted value in the to-unit, or null when no source value is set.',\n invoke: (handle) => handle.getResult(),\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'unit-converter',\n description: 'Marks the UnitConverter wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific converter instance.',\n },\n },\n};\n","/* ------------------------------------------------------------------ */\n/* Generic unit conversion — pure, framework-free, unit-testable. */\n/* */\n/* Every unit is described by an affine map to its category's base */\n/* unit: base = value * factor + offset. Conversion is base-in then */\n/* base-out, so the same code handles linear scales (weight, length, */\n/* glucose) and offset scales (temperature) uniformly. */\n/* ------------------------------------------------------------------ */\n\nexport type UnitCategory = 'weight' | 'length' | 'temperature' | 'glucose';\n\nexport interface UnitDef {\n id: string;\n category: UnitCategory;\n /** Multiplier to the category base unit. */\n factor: number;\n /** Additive offset to the base unit (non-zero only for temperature). */\n offset: number;\n}\n\n/* Base units: kg, cm, °C, mmol/L. */\nexport const UNITS: Record<string, UnitDef> = {\n // weight → base kg\n kg: { id: 'kg', category: 'weight', factor: 1, offset: 0 },\n g: { id: 'g', category: 'weight', factor: 0.001, offset: 0 },\n lb: { id: 'lb', category: 'weight', factor: 0.45359237, offset: 0 },\n oz: { id: 'oz', category: 'weight', factor: 0.028349523125, offset: 0 },\n // length → base cm\n cm: { id: 'cm', category: 'length', factor: 1, offset: 0 },\n m: { id: 'm', category: 'length', factor: 100, offset: 0 },\n in: { id: 'in', category: 'length', factor: 2.54, offset: 0 },\n ft: { id: 'ft', category: 'length', factor: 30.48, offset: 0 },\n // temperature → base °C (affine: °C = °F·5/9 − 32·5/9)\n c: { id: 'c', category: 'temperature', factor: 1, offset: 0 },\n f: { id: 'f', category: 'temperature', factor: 5 / 9, offset: (-32 * 5) / 9 },\n // glucose → base mmol/L (1 mg/dL = 1/18.0156 mmol/L)\n mmol_l: { id: 'mmol_l', category: 'glucose', factor: 1, offset: 0 },\n mg_dl: { id: 'mg_dl', category: 'glucose', factor: 1 / 18.0156, offset: 0 },\n};\n\nexport const UNITS_BY_CATEGORY: Record<UnitCategory, string[]> = {\n weight: ['kg', 'g', 'lb', 'oz'],\n length: ['cm', 'm', 'in', 'ft'],\n temperature: ['c', 'f'],\n glucose: ['mmol_l', 'mg_dl'],\n};\n\nexport const CATEGORIES: UnitCategory[] = [\n 'weight',\n 'length',\n 'temperature',\n 'glucose',\n];\n\n/**\n * Convert `value` from one unit to another. Both ids must belong to the same\n * category; mismatched categories throw (a programming error, not user input).\n */\nexport function convertUnits(\n value: number,\n fromId: string,\n toId: string,\n): number {\n const from = UNITS[fromId];\n const to = UNITS[toId];\n if (!from || !to) throw new Error(`Unknown unit: ${fromId} → ${toId}`);\n if (from.category !== to.category) {\n throw new Error(\n `Cannot convert across categories: ${from.category} → ${to.category}`,\n );\n }\n const base = value * from.factor + from.offset;\n return (base - to.offset) / to.factor;\n}\n","/* ------------------------------------------------------------------ */\n/* UnitConverter — generic clinical/everyday unit conversion across */\n/* weight, length, temperature and glucose. */\n/* */\n/* Maths lives in `./units` (pure, separately tested). */\n/* ------------------------------------------------------------------ */\n\nimport { forwardRef, useEffect, useMemo, useRef, useState } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { unitConverterAgent } from './unit-converter.agent';\nimport { FormField } from '../form-field';\nimport { NumberInput } from '../number-input';\nimport { Select } from '../select';\nimport {\n InsertButton,\n type InsertPayload,\n type InsertVariant,\n type InsertMode,\n} from '../_shared/insert-result';\nimport {\n type UnitCategory,\n CATEGORIES,\n UNITS_BY_CATEGORY,\n convertUnits,\n} from './units';\n\nconst rootVariants = cva('ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]', {\n variants: {\n width: { full: 'ds:w-full', auto: 'ds:inline-flex' },\n },\n defaultVariants: { width: 'full' },\n});\n\n/**\n * DS token NAME backing the result-card category chip, one per measurement\n * family. The converter shows no on-screen badge, but the inserted card carries\n * a category chip so the reader can tell at a glance which family the figure\n * belongs to; each token is a closed-palette semantic alias resolved to a\n * concrete colour at raster time by `InsertButton`.\n */\nconst CATEGORY_HIGHLIGHT_TOKEN: Record<UnitCategory, string> = {\n weight: '--info',\n length: '--success',\n temperature: '--warning-readable',\n glucose: '--accent',\n};\n\n/**\n * Category chip token. The `temperature` family resolves to `--warning-readable`,\n * which the result card's colour probe resolves in the live themed DOM: orange-600\n * in light, non-accessible mode (where bare `--warning` yellow only reaches\n * ~3.2:1 on the white card) and `--warning` elsewhere, whose deepened ramp already\n * clears contrast. Resolving the token NAME at the card means the choice tracks\n * the live theme regardless of where the theme class lives. Other families are\n * unchanged.\n */\nfunction categoryHighlightToken(category: UnitCategory): string {\n return CATEGORY_HIGHLIGHT_TOKEN[category];\n}\n\nexport interface UnitConverterProps extends VariantProps<typeof rootVariants> {\n /** Initial category. Defaults to `'weight'`. */\n defaultCategory?: UnitCategory;\n /** Fires with the converted value (and `null` when input is empty). */\n onResultChange?: (value: number | null) => void;\n /** When provided, shows an \"Insert\" button that emits the result for an editor. */\n onInsert?: (payload: InsertPayload) => void;\n /**\n * Which verb the result button performs. Defaults to `'insert'`.\n * Use `'copy'` in an app-shell surface (no editor to insert into) — the\n * button writes the result to the clipboard as a multi-format `ClipboardItem`.\n */\n insertVariant?: InsertVariant;\n /** `copy` variant only — fired after a successful clipboard write. */\n onCopy?: (mode: InsertMode) => void;\n /** `copy` variant only — fired if the clipboard write can't proceed. */\n onError?: (error: unknown) => void;\n /**\n * Brand wordmark printed in the inserted/copied result-card footer.\n * Omitted → no brand line (and no footer hairline); a string → that custom\n * brand; `false` → no brand line. Brand is opt-in.\n */\n insertBrand?: string | false;\n /** Opaque instance id, emitted as `data-component-id`. */\n id?: string;\n /** Extra class names on the wrapper. */\n className?: string;\n}\n\n/**\n * Curated imperative handle for agent / external automation. Reads/writes the\n * structural inputs (category, value, from/to units) and the converted result.\n * No patient identity. Consumed by the `unit-converter.agent.ts` adapter; the\n * public `ref` stays the DOM element.\n */\nexport interface UnitConverterHandle {\n /** Active measurement family. */\n getCategory: () => UnitCategory;\n /** Switch the measurement family (resets from/to units to that category). */\n setCategory: (next: UnitCategory) => void;\n /** Source value + from/to unit ids. */\n getInputs: () => { value: number | null; fromId: string; toId: string };\n /** Set the source value to convert. */\n setValue: (value: number | null) => void;\n /** Set from-unit and/or to-unit (ids outside the active category are ignored). */\n setUnits: (next: { fromId?: string; toId?: string }) => void;\n /** Converted value in the to-unit, or null when no source value is set. */\n getResult: () => number | null;\n}\n\nexport const UnitConverter = forwardRef<HTMLDivElement, UnitConverterProps>(\n (\n {\n defaultCategory = 'weight',\n onResultChange,\n onInsert,\n insertVariant = 'insert',\n onCopy,\n onError,\n insertBrand,\n id,\n width,\n className,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation('ui');\n\n const [category, setCategory] = useState<UnitCategory>(defaultCategory);\n const [value, setValue] = useState<number | null>(null);\n const [fromId, setFromId] = useState<string>(\n UNITS_BY_CATEGORY[defaultCategory][0],\n );\n const [toId, setToId] = useState<string>(\n UNITS_BY_CATEGORY[defaultCategory][1],\n );\n\n const handleCategoryChange = (next: string): void => {\n const cat = next as UnitCategory;\n const units = UNITS_BY_CATEGORY[cat];\n setCategory(cat);\n setFromId(units[0]);\n setToId(units[1] ?? units[0]);\n };\n\n const converted = useMemo(\n () => (value === null ? null : convertUnits(value, fromId, toId)),\n [value, fromId, toId],\n );\n\n const numberFmt = useMemo(\n () => new Intl.NumberFormat(i18n.language, { maximumFractionDigits: 3 }),\n [i18n.language],\n );\n\n useEffect(() => {\n onResultChange?.(converted);\n }, [converted, onResultChange]);\n\n // Live refs so the once-built agent handle reads/writes current state\n // without re-creating on every keystroke. Public `ref` stays the DOM node.\n const liveRef = useRef({ category, value, fromId, toId, converted });\n liveRef.current = { category, value, fromId, toId, converted };\n const agentHandle = useMemo<UnitConverterHandle>(\n () => ({\n getCategory: () => liveRef.current.category,\n setCategory: (next) => handleCategoryChange(next),\n getInputs: () => ({\n value: liveRef.current.value,\n fromId: liveRef.current.fromId,\n toId: liveRef.current.toId,\n }),\n setValue: (next) => setValue(next),\n setUnits: (next) => {\n const units = UNITS_BY_CATEGORY[liveRef.current.category];\n if (next.fromId !== undefined && units.includes(next.fromId)) {\n setFromId(next.fromId);\n }\n if (next.toId !== undefined && units.includes(next.toId)) {\n setToId(next.toId);\n }\n },\n getResult: () => liveRef.current.converted,\n }),\n [],\n );\n useAgentRegistration(unitConverterAgent, agentHandle, id);\n\n const categoryOptions = CATEGORIES.map((c) => ({\n value: c,\n label: t(`unitConverter.category.${c}`),\n }));\n const unitOptions = UNITS_BY_CATEGORY[category].map((u) => ({\n value: u,\n label: t(`unitConverter.units.${u}`),\n }));\n\n return (\n <div\n ref={ref}\n data-component=\"unit-converter\"\n data-component-id={id}\n className={rootVariants({ width, className })}\n >\n <FormField label={t('unitConverter.categoryLabel')}>\n <Select\n options={categoryOptions}\n value={category}\n onValueChange={handleCategoryChange}\n />\n </FormField>\n\n <div className=\"ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)] ds:sm:grid-cols-3\">\n <FormField label={t('unitConverter.value')}>\n <NumberInput mode=\"decimal\" value={value} onChange={setValue} />\n </FormField>\n <FormField label={t('unitConverter.from')}>\n <Select\n options={unitOptions}\n value={fromId}\n onValueChange={setFromId}\n />\n </FormField>\n <FormField label={t('unitConverter.to')}>\n <Select\n options={unitOptions}\n value={toId}\n onValueChange={setToId}\n />\n </FormField>\n </div>\n\n <p className=\"ds:sr-only\" role=\"status\" aria-live=\"polite\">\n {converted !== null\n ? `${numberFmt.format(value ?? 0)} ${t(\n `unitConverter.units.${fromId}`,\n )} = ${numberFmt.format(converted)} ${t(\n `unitConverter.units.${toId}`,\n )}`\n : ''}\n </p>\n\n {converted !== null ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <span className=\"type-label ds:text-muted-foreground\">\n {t('unitConverter.result')}\n </span>\n <span className=\"type-metric ds:text-foreground\">\n {numberFmt.format(converted)} {t(`unitConverter.units.${toId}`)}\n </span>\n {insertVariant === 'copy' || onInsert ? (\n <InsertButton\n variant={insertVariant}\n onInsert={onInsert}\n onCopy={onCopy}\n onError={onError}\n card={{\n title: t('insert.title.unitConverter'),\n icon: 'ruler',\n highlight: t(`unitConverter.category.${category}`),\n // Chip tints by measurement family so the inserted card\n // signals the category at a glance — with the contrast-safe\n // orange override for the `--warning` temperature family.\n highlightToken: categoryHighlightToken(category),\n brand: insertBrand,\n fields: [\n {\n // Source measurement → ruler glyph (matches the header).\n icon: 'ruler',\n label: t('unitConverter.from'),\n value: `${numberFmt.format(value ?? 0)} ${t(\n `unitConverter.units.${fromId}`,\n )}`,\n },\n {\n // Converted result → trending-up (arrow) glyph signals the\n // conversion direction to the output value.\n icon: 'trending-up',\n label: t('unitConverter.to'),\n value: `${numberFmt.format(converted)} ${t(\n `unitConverter.units.${toId}`,\n )}`,\n },\n ],\n }}\n />\n ) : null}\n </div>\n ) : (\n <p className=\"type-body ds:text-muted-foreground\">\n {t('unitConverter.empty')}\n </p>\n )}\n </div>\n );\n },\n);\n\nUnitConverter.displayName = 'UnitConverter';\n"],"names":["CATEGORIES","unitConverterAgent","handle","args","UNITS","UNITS_BY_CATEGORY","convertUnits","value","fromId","toId","from","to","rootVariants","cva","CATEGORY_HIGHLIGHT_TOKEN","categoryHighlightToken","category","UnitConverter","forwardRef","defaultCategory","onResultChange","onInsert","insertVariant","onCopy","onError","insertBrand","id","width","className","ref","t","i18n","useTranslation","setCategory","useState","setValue","setFromId","setToId","handleCategoryChange","next","cat","units","converted","useMemo","numberFmt","useEffect","liveRef","useRef","agentHandle","useAgentRegistration","categoryOptions","c","unitOptions","u","jsxs","jsx","FormField","Select","NumberInput","InsertButton"],"mappings":"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"}
|
|
@@ -16,7 +16,7 @@ import { E as zt } from "./editable-description-KU56SP4P.js";
|
|
|
16
16
|
import { N as Xe } from "./note-timeline-BrjHBQfx.js";
|
|
17
17
|
import { P as Ot } from "./panel-header-CbtlTe85.js";
|
|
18
18
|
import { P as Ge } from "./panel-subview-DCyvn-49.js";
|
|
19
|
-
import { P as _t } from "./patient-summary-card-
|
|
19
|
+
import { P as _t } from "./patient-summary-card-C61AR4Tn.js";
|
|
20
20
|
import { S as ne } from "./section-card-D5nWiTcK.js";
|
|
21
21
|
import { C as nn, S as ue } from "./skeleton-tTWJpvAq.js";
|
|
22
22
|
import { T as an } from "./text-area-COMVJ1yE.js";
|
|
@@ -2195,4 +2195,4 @@ export {
|
|
|
2195
2195
|
Kn as s,
|
|
2196
2196
|
_s as u
|
|
2197
2197
|
};
|
|
2198
|
-
//# sourceMappingURL=use-appointment-details-read-
|
|
2198
|
+
//# sourceMappingURL=use-appointment-details-read-B6uhmNdV.js.map
|