@comitor/ui 3.0.0 → 3.1.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.
Files changed (110) hide show
  1. package/README.md +5 -1
  2. package/dist/components/composite/confirm-dialog.js +56 -35
  3. package/dist/components/composite/confirm-dialog.js.map +1 -1
  4. package/dist/components/composite/search-filter-bar-constants.d.ts +3 -0
  5. package/dist/components/composite/search-filter-bar-constants.js.map +1 -1
  6. package/dist/components/composite/table-pagination-constants.d.ts +3 -1
  7. package/dist/components/composite/table-pagination-constants.js.map +1 -1
  8. package/dist/components/composite/table-pagination.js +10 -2
  9. package/dist/components/composite/table-pagination.js.map +1 -1
  10. package/dist/components/composite/text-utils.d.ts +4 -23
  11. package/dist/components/composite/text-utils.js +1 -11
  12. package/dist/components/composite/text-utils.js.map +1 -1
  13. package/dist/components/composite/toast.d.ts +2 -1
  14. package/dist/components/composite/toast.js +3 -9
  15. package/dist/components/composite/toast.js.map +1 -1
  16. package/dist/components/ui/action-bar.js +45 -1
  17. package/dist/components/ui/action-bar.js.map +1 -1
  18. package/dist/components/ui/banner.d.ts +8 -0
  19. package/dist/components/ui/banner.js +149 -35
  20. package/dist/components/ui/banner.js.map +1 -1
  21. package/dist/components/ui/circular-progress.js +10 -2
  22. package/dist/components/ui/circular-progress.js.map +1 -1
  23. package/dist/components/ui/kanban.js +9 -3
  24. package/dist/components/ui/kanban.js.map +1 -1
  25. package/dist/components/ui/key-value.js +70 -76
  26. package/dist/components/ui/key-value.js.map +1 -1
  27. package/dist/components/ui/mask-input-constants.d.ts +34 -2
  28. package/dist/components/ui/mask-input-constants.js +87 -76
  29. package/dist/components/ui/mask-input-constants.js.map +1 -1
  30. package/dist/components/ui/mask-input.d.ts +6 -5
  31. package/dist/components/ui/mask-input.js +23 -21
  32. package/dist/components/ui/mask-input.js.map +1 -1
  33. package/dist/components/ui/mention.d.ts +14 -2
  34. package/dist/components/ui/mention.js +33 -6
  35. package/dist/components/ui/mention.js.map +1 -1
  36. package/dist/components/ui/phone-input.d.ts +18 -8
  37. package/dist/components/ui/phone-input.js +125 -35
  38. package/dist/components/ui/phone-input.js.map +1 -1
  39. package/dist/components/ui/rating.js +4 -2
  40. package/dist/components/ui/rating.js.map +1 -1
  41. package/dist/components/ui/scroll-spy.js +46 -31
  42. package/dist/components/ui/scroll-spy.js.map +1 -1
  43. package/dist/components/ui/slider.d.ts +1 -1
  44. package/dist/components/ui/slider.js +15 -1
  45. package/dist/components/ui/slider.js.map +1 -1
  46. package/dist/components/ui/sonner.js +2 -0
  47. package/dist/components/ui/sonner.js.map +1 -1
  48. package/dist/components/ui/stepper.js +26 -3
  49. package/dist/components/ui/stepper.js.map +1 -1
  50. package/dist/components/ui/time-picker.d.ts +24 -4
  51. package/dist/components/ui/time-picker.js +425 -162
  52. package/dist/components/ui/time-picker.js.map +1 -1
  53. package/dist/components/ui/timeline.js +45 -9
  54. package/dist/components/ui/timeline.js.map +1 -1
  55. package/dist/components/ui/toggle-group.js +12 -1
  56. package/dist/components/ui/toggle-group.js.map +1 -1
  57. package/dist/components/ui/tour.js +3 -2
  58. package/dist/components/ui/tour.js.map +1 -1
  59. package/dist/data-grid/data-grid-cell-variants.js +4 -4
  60. package/dist/data-grid/data-grid-cell-variants.js.map +1 -1
  61. package/dist/data-grid/data-grid-cell-wrapper.d.ts +1 -1
  62. package/dist/data-grid/data-grid-cell-wrapper.js +6 -0
  63. package/dist/data-grid/data-grid-cell-wrapper.js.map +1 -1
  64. package/dist/data-grid/data-grid-row.js +1 -1
  65. package/dist/data-grid/data-grid-row.js.map +1 -1
  66. package/dist/data-grid/data-grid-select-column.js +6 -2
  67. package/dist/data-grid/data-grid-select-column.js.map +1 -1
  68. package/dist/data-grid/data-grid-skeleton.d.ts +5 -0
  69. package/dist/data-grid/data-grid-skeleton.js +1 -4
  70. package/dist/data-grid/data-grid-skeleton.js.map +1 -1
  71. package/dist/data-grid/data-grid.d.ts +1 -1
  72. package/dist/data-grid/data-grid.js +3 -2
  73. package/dist/data-grid/data-grid.js.map +1 -1
  74. package/dist/data-grid/filters.js +3 -2
  75. package/dist/data-grid/filters.js.map +1 -1
  76. package/dist/data-grid/types.d.ts +7 -0
  77. package/dist/data-grid/use-data-grid.d.ts +1 -0
  78. package/dist/data-grid/use-data-grid.js +70 -24
  79. package/dist/data-grid/use-data-grid.js.map +1 -1
  80. package/dist/data-grid/utils.d.ts +7 -0
  81. package/dist/data-grid/utils.js +3 -1
  82. package/dist/data-grid/utils.js.map +1 -1
  83. package/dist/i18n/locale-provider.d.ts +18 -0
  84. package/dist/i18n/locale-provider.js.map +1 -1
  85. package/dist/i18n/namespaces/rating.js +2 -1
  86. package/dist/i18n/namespaces/rating.js.map +1 -1
  87. package/dist/i18n/namespaces/search-filter-bar.js +8 -6
  88. package/dist/i18n/namespaces/search-filter-bar.js.map +1 -1
  89. package/dist/i18n/namespaces/shell.d.ts +4 -0
  90. package/dist/i18n/namespaces/shell.js +1 -1
  91. package/dist/i18n/namespaces/shell.js.map +1 -1
  92. package/dist/i18n/namespaces/table-pagination.js +6 -4
  93. package/dist/i18n/namespaces/table-pagination.js.map +1 -1
  94. package/dist/i18n/namespaces/toast.d.ts +3 -2
  95. package/dist/i18n/namespaces/toast.js.map +1 -1
  96. package/dist/index.d.ts +2 -1
  97. package/dist/lib/collect-item-elements.d.ts +47 -0
  98. package/dist/lib/collect-item-elements.js +22 -0
  99. package/dist/lib/collect-item-elements.js.map +1 -0
  100. package/dist/lib/text-search.d.ts +32 -0
  101. package/dist/lib/text-search.js +17 -0
  102. package/dist/lib/text-search.js.map +1 -0
  103. package/dist/lib/toast-language.d.ts +8 -0
  104. package/dist/lib/toast-language.js +19 -0
  105. package/dist/lib/toast-language.js.map +1 -0
  106. package/dist/shell/app-shell.d.ts +1 -0
  107. package/dist/shell/index.d.ts +2 -1
  108. package/dist/shell/shell-context.d.ts +1 -0
  109. package/dist/shell/utils.d.ts +2 -1
  110. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/ui/stepper.tsx"],"sourcesContent":["\"use client\";\n\n/*\n * Port từ Dice UI (https://diceui.com/docs/components/stepper) — MIT, © 2024 Sadman Sakib.\n * Giữ nguyên cấu trúc thượng nguồn để còn đối chiếu ngược được; mọi chỗ đổi đều có chú thích.\n */\n\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { Check } from \"lucide-react\";\nimport * as React from \"react\";\nimport { useComitorLabels } from \"../../i18n/locale-provider.js\";\nimport { cn } from \"../../lib/cn.js\";\nimport { useComposedRefs } from \"../../lib/compose-refs.js\";\nimport { useAsRef } from \"../../lib/use-as-ref.js\";\nimport { useIsomorphicLayoutEffect } from \"../../lib/use-isomorphic-layout-effect.js\";\nimport { useLazyRef } from \"../../lib/use-lazy-ref.js\";\nimport type { StepperLabels } from \"./stepper-constants.js\";\n\nconst ROOT_NAME = \"Stepper\";\nconst LIST_NAME = \"StepperList\";\nconst ITEM_NAME = \"StepperItem\";\nconst TRIGGER_NAME = \"StepperTrigger\";\nconst INDICATOR_NAME = \"StepperIndicator\";\nconst SEPARATOR_NAME = \"StepperSeparator\";\nconst TITLE_NAME = \"StepperTitle\";\nconst DESCRIPTION_NAME = \"StepperDescription\";\nconst CONTENT_NAME = \"StepperContent\";\nconst PREV_NAME = \"StepperPrev\";\nconst NEXT_NAME = \"StepperNext\";\n\nconst ENTRY_FOCUS = \"stepperFocusGroup.onEntryFocus\";\nconst EVENT_OPTIONS = { bubbles: false, cancelable: true };\nconst ARROW_KEYS = [\"ArrowUp\", \"ArrowDown\", \"ArrowLeft\", \"ArrowRight\"];\n\ntype Direction = \"ltr\" | \"rtl\";\ntype Orientation = \"horizontal\" | \"vertical\";\ntype NavigationDirection = \"next\" | \"prev\";\ntype ActivationMode = \"automatic\" | \"manual\";\ntype DataState = \"inactive\" | \"active\" | \"completed\";\n\ninterface DivProps extends React.ComponentProps<\"div\"> {\n asChild?: boolean;\n}\ninterface ButtonProps extends React.ComponentProps<\"button\"> {\n asChild?: boolean;\n}\n\ntype ListElement = React.ComponentRef<typeof StepperList>;\ntype TriggerElement = React.ComponentRef<typeof StepperTrigger>;\n\nfunction getId(id: string, variant: \"trigger\" | \"content\" | \"title\" | \"description\", value: string) {\n return `${id}-${variant}-${value}`;\n}\n\ntype FocusIntent = \"first\" | \"last\" | \"prev\" | \"next\";\n\nconst MAP_KEY_TO_FOCUS_INTENT: Record<string, FocusIntent> = {\n ArrowLeft: \"prev\",\n ArrowUp: \"prev\",\n ArrowRight: \"next\",\n ArrowDown: \"next\",\n PageUp: \"first\",\n Home: \"first\",\n PageDown: \"last\",\n End: \"last\"\n};\n\nfunction getDirectionAwareKey(key: string, dir?: Direction) {\n if (dir !== \"rtl\") return key;\n return key === \"ArrowLeft\" ? \"ArrowRight\" : key === \"ArrowRight\" ? \"ArrowLeft\" : key;\n}\n\nfunction getFocusIntent(event: React.KeyboardEvent<TriggerElement>, dir?: Direction, orientation?: Orientation) {\n const key = getDirectionAwareKey(event.key, dir);\n if (orientation === \"horizontal\" && [\"ArrowUp\", \"ArrowDown\"].includes(key)) return undefined;\n if (orientation === \"vertical\" && [\"ArrowLeft\", \"ArrowRight\"].includes(key)) return undefined;\n return MAP_KEY_TO_FOCUS_INTENT[key];\n}\n\nfunction focusFirst(candidates: React.RefObject<TriggerElement | null>[], preventScroll = false) {\n const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;\n for (const candidateRef of candidates) {\n const candidate = candidateRef.current;\n if (!candidate) continue;\n if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;\n candidate.focus({ preventScroll });\n if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;\n }\n}\n\nfunction wrapArray<T>(array: T[], startIndex: number) {\n return array.map<T>((_, index) => array[(startIndex + index) % array.length] as T);\n}\n\nfunction getDataState(\n value: string | undefined,\n itemValue: string,\n stepState: StepState | undefined,\n steps: Map<string, StepState>,\n variant: \"item\" | \"separator\" = \"item\"\n): DataState {\n const stepKeys = Array.from(steps.keys());\n const currentIndex = stepKeys.indexOf(itemValue);\n\n if (stepState?.completed) return \"completed\";\n\n if (value === itemValue) {\n return variant === \"separator\" ? \"inactive\" : \"active\";\n }\n\n if (value) {\n const activeIndex = stepKeys.indexOf(value);\n\n if (activeIndex > currentIndex) return \"completed\";\n }\n\n return \"inactive\";\n}\n\ninterface StepState {\n value: string;\n completed: boolean;\n disabled: boolean;\n}\n\ninterface StoreState {\n steps: Map<string, StepState>;\n value: string;\n}\n\ninterface Store {\n subscribe: (callback: () => void) => () => void;\n getState: () => StoreState;\n setState: <K extends keyof StoreState>(key: K, value: StoreState[K]) => void;\n setStateWithValidation: (value: string, direction: NavigationDirection) => Promise<boolean>;\n hasValidation: () => boolean;\n notify: () => void;\n addStep: (value: string, completed: boolean, disabled: boolean) => void;\n removeStep: (value: string) => void;\n setStep: (value: string, completed: boolean, disabled: boolean) => void;\n}\n\nconst StoreContext = React.createContext<Store | null>(null);\n\nfunction useStoreContext(consumerName: string) {\n const context = React.useContext(StoreContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ROOT_NAME}\\``);\n }\n return context;\n}\n\nfunction useStore<T>(selector: (state: StoreState) => T): T {\n const store = useStoreContext(\"useStepper\");\n\n const getSnapshot = React.useCallback(() => selector(store.getState()), [store, selector]);\n\n return React.useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);\n}\n\ninterface ItemData {\n id: string;\n ref: React.RefObject<TriggerElement | null>;\n value: string;\n active: boolean;\n disabled: boolean;\n}\n\ninterface StepperContextValue {\n rootId: string;\n dir: Direction;\n orientation: Orientation;\n activationMode: ActivationMode;\n disabled: boolean;\n nonInteractive: boolean;\n loop: boolean;\n labels: StepperLabels;\n}\n\nconst StepperContext = React.createContext<StepperContextValue | null>(null);\n\nfunction useStepperContext(consumerName: string) {\n const context = React.useContext(StepperContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ROOT_NAME}\\``);\n }\n return context;\n}\n\ninterface StepperProps extends DivProps {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n onValueComplete?: (value: string, completed: boolean) => void;\n onValueAdd?: (value: string) => void;\n onValueRemove?: (value: string) => void;\n onValidate?: (value: string, direction: NavigationDirection) => boolean | Promise<boolean>;\n activationMode?: ActivationMode;\n dir?: Direction;\n orientation?: Orientation;\n disabled?: boolean;\n loop?: boolean;\n nonInteractive?: boolean;\n /**\n * Chuỗi hiển thị/a11y — ghi đè từng khoá. Không truyền thì theo namespace `stepper` của\n * `ComitorLocaleProvider` (mặc định tiếng Anh).\n *\n * ⚠ Thêm so với thượng nguồn: bản gốc không có chuỗi nào, và chính vì thế có hai chỗ ra nút\n * KHÔNG TÊN (ô chỉ báo bước đã xong, `StepperPrev`/`StepperNext` thiếu `children`).\n */\n labels?: Partial<StepperLabels>;\n}\n\nfunction Stepper(props: StepperProps) {\n const {\n value,\n defaultValue,\n onValueChange,\n onValueComplete,\n onValueAdd,\n onValueRemove,\n onValidate,\n dir: dirProp,\n orientation = \"horizontal\",\n activationMode = \"automatic\",\n asChild,\n disabled = false,\n nonInteractive = false,\n loop = false,\n labels: labelsProp,\n className,\n id,\n ...rootProps\n } = props;\n\n const listenersRef = useLazyRef(() => new Set<() => void>());\n const stateRef = useLazyRef<StoreState>(() => ({\n steps: new Map(),\n value: value ?? defaultValue ?? \"\"\n }));\n\n const propsRef = useAsRef({\n onValueChange,\n onValueComplete,\n onValueAdd,\n onValueRemove,\n onValidate\n });\n\n const store = React.useMemo<Store>(() => {\n return {\n subscribe: (cb) => {\n listenersRef.current.add(cb);\n return () => listenersRef.current.delete(cb);\n },\n getState: () => stateRef.current,\n setState: (key, value) => {\n if (Object.is(stateRef.current[key], value)) return;\n\n if (key === \"value\" && typeof value === \"string\") {\n stateRef.current.value = value;\n propsRef.current.onValueChange?.(value);\n } else {\n stateRef.current[key] = value;\n }\n\n store.notify();\n },\n setStateWithValidation: async (value, direction) => {\n if (!propsRef.current.onValidate) {\n store.setState(\"value\", value);\n return true;\n }\n\n try {\n const isValid = await propsRef.current.onValidate(value, direction);\n if (isValid) {\n store.setState(\"value\", value);\n }\n return isValid;\n } catch {\n return false;\n }\n },\n hasValidation: () => !!propsRef.current.onValidate,\n /*\n * ⚠ Khác thượng nguồn: mỗi lần thêm/bớt/sửa bước đều thay `steps` bằng một `Map` MỚI. Bản gốc\n * sửa tại chỗ nên `useStore((s) => s.steps)` không bao giờ thấy tham chiếu mới — phần tử chỉ\n * đọc `steps` (`StepperPrev`/`StepperNext`) không render lại sau khi các bước đăng ký, và\n * nằm `disabled` cho tới lần đổi bước đầu tiên.\n */\n addStep: (value, completed, disabled) => {\n const newStep: StepState = { value, completed, disabled };\n const steps = new Map(stateRef.current.steps);\n steps.set(value, newStep);\n stateRef.current.steps = steps;\n propsRef.current.onValueAdd?.(value);\n store.notify();\n },\n removeStep: (value) => {\n const steps = new Map(stateRef.current.steps);\n steps.delete(value);\n stateRef.current.steps = steps;\n propsRef.current.onValueRemove?.(value);\n store.notify();\n },\n setStep: (value, completed, disabled) => {\n const step = stateRef.current.steps.get(value);\n if (step) {\n const updatedStep: StepState = { ...step, completed, disabled };\n const steps = new Map(stateRef.current.steps);\n steps.set(value, updatedStep);\n stateRef.current.steps = steps;\n\n if (completed !== step.completed) {\n propsRef.current.onValueComplete?.(value, completed);\n }\n\n store.notify();\n }\n },\n notify: () => {\n for (const cb of listenersRef.current) {\n cb();\n }\n }\n };\n }, [listenersRef, stateRef, propsRef]);\n\n useIsomorphicLayoutEffect(() => {\n if (value !== undefined) {\n store.setState(\"value\", value);\n }\n }, [value]);\n\n const dir = useDirection(dirProp);\n\n const instanceId = React.useId();\n const rootId = id ?? instanceId;\n\n const labels = useComitorLabels(\"stepper\", labelsProp);\n\n const contextValue = React.useMemo<StepperContextValue>(\n () => ({\n rootId,\n dir,\n orientation,\n activationMode,\n disabled,\n nonInteractive,\n loop,\n labels\n }),\n [rootId, dir, orientation, activationMode, disabled, nonInteractive, loop, labels]\n );\n\n const RootPrimitive = asChild ? Slot : \"div\";\n\n return (\n <StoreContext.Provider value={store}>\n <StepperContext.Provider value={contextValue}>\n <RootPrimitive\n id={rootId}\n data-disabled={disabled ? \"\" : undefined}\n data-orientation={orientation}\n data-slot=\"stepper\"\n dir={dir}\n {...rootProps}\n className={cn(\"flex gap-6\", orientation === \"horizontal\" ? \"w-full flex-col\" : \"flex-row\", className)}\n />\n </StepperContext.Provider>\n </StoreContext.Provider>\n );\n}\n\ninterface FocusContextValue {\n tabStopId: string | null;\n onItemFocus: (tabStopId: string) => void;\n onItemShiftTab: () => void;\n onFocusableItemAdd: () => void;\n onFocusableItemRemove: () => void;\n onItemRegister: (item: ItemData) => void;\n onItemUnregister: (id: string) => void;\n getItems: () => ItemData[];\n}\n\nconst FocusContext = React.createContext<FocusContextValue | null>(null);\n\nfunction useFocusContext(consumerName: string) {\n const context = React.useContext(FocusContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${LIST_NAME}\\``);\n }\n return context;\n}\n\nfunction StepperList(props: DivProps) {\n const {\n asChild,\n onBlur: onBlurProp,\n onFocus: onFocusProp,\n onMouseDown: onMouseDownProp,\n className,\n children,\n ref,\n ...listProps\n } = props;\n\n const context = useStepperContext(LIST_NAME);\n const orientation = context.orientation;\n const currentValue = useStore((state) => state.value);\n\n const propsRef = useAsRef({\n onBlur: onBlurProp,\n onFocus: onFocusProp,\n onMouseDown: onMouseDownProp\n });\n\n const [tabStopId, setTabStopId] = React.useState<string | null>(null);\n const [isTabbingBackOut, setIsTabbingBackOut] = React.useState(false);\n const [focusableItemCount, setFocusableItemCount] = React.useState(0);\n const isClickFocusRef = React.useRef(false);\n const itemsRef = React.useRef<Map<string, ItemData>>(new Map());\n const listRef = React.useRef<ListElement>(null);\n const composedRef = useComposedRefs(ref, listRef);\n\n const onItemFocus = React.useCallback((tabStopId: string) => {\n setTabStopId(tabStopId);\n }, []);\n\n const onItemShiftTab = React.useCallback(() => {\n setIsTabbingBackOut(true);\n }, []);\n\n const onFocusableItemAdd = React.useCallback(() => {\n setFocusableItemCount((prevCount) => prevCount + 1);\n }, []);\n\n const onFocusableItemRemove = React.useCallback(() => {\n setFocusableItemCount((prevCount) => prevCount - 1);\n }, []);\n\n const onItemRegister = React.useCallback((item: ItemData) => {\n itemsRef.current.set(item.id, item);\n }, []);\n\n const onItemUnregister = React.useCallback((id: string) => {\n itemsRef.current.delete(id);\n }, []);\n\n const getItems = React.useCallback(() => {\n return Array.from(itemsRef.current.values())\n .filter((item) => item.ref.current)\n .sort((a, b) => {\n const elementA = a.ref.current;\n const elementB = b.ref.current;\n if (!elementA || !elementB) return 0;\n const position = elementA.compareDocumentPosition(elementB);\n if (position & Node.DOCUMENT_POSITION_FOLLOWING) {\n return -1;\n }\n if (position & Node.DOCUMENT_POSITION_PRECEDING) {\n return 1;\n }\n return 0;\n });\n }, []);\n\n const onBlur = React.useCallback(\n (event: React.FocusEvent<ListElement>) => {\n propsRef.current.onBlur?.(event);\n if (event.defaultPrevented) return;\n\n setIsTabbingBackOut(false);\n },\n [propsRef]\n );\n\n const onFocus = React.useCallback(\n (event: React.FocusEvent<ListElement>) => {\n propsRef.current.onFocus?.(event);\n if (event.defaultPrevented) return;\n\n const isKeyboardFocus = !isClickFocusRef.current;\n if (event.target === event.currentTarget && isKeyboardFocus && !isTabbingBackOut) {\n const entryFocusEvent = new CustomEvent(ENTRY_FOCUS, EVENT_OPTIONS);\n event.currentTarget.dispatchEvent(entryFocusEvent);\n\n if (!entryFocusEvent.defaultPrevented) {\n const items = Array.from(itemsRef.current.values()).filter((item) => !item.disabled);\n const selectedItem = currentValue ? items.find((item) => item.value === currentValue) : undefined;\n const activeItem = items.find((item) => item.active);\n const currentItem = items.find((item) => item.id === tabStopId);\n\n const candidateItems = [selectedItem, activeItem, currentItem, ...items].filter(Boolean) as ItemData[];\n const candidateRefs = candidateItems.map((item) => item.ref);\n focusFirst(candidateRefs, false);\n }\n }\n isClickFocusRef.current = false;\n },\n [propsRef, isTabbingBackOut, currentValue, tabStopId]\n );\n\n const onMouseDown = React.useCallback(\n (event: React.MouseEvent<ListElement>) => {\n propsRef.current.onMouseDown?.(event);\n\n if (event.defaultPrevented) return;\n\n isClickFocusRef.current = true;\n },\n [propsRef]\n );\n\n const focusContextValue = React.useMemo<FocusContextValue>(\n () => ({\n tabStopId,\n onItemFocus,\n onItemShiftTab,\n onFocusableItemAdd,\n onFocusableItemRemove,\n onItemRegister,\n onItemUnregister,\n getItems\n }),\n [\n tabStopId,\n onItemFocus,\n onItemShiftTab,\n onFocusableItemAdd,\n onFocusableItemRemove,\n onItemRegister,\n onItemUnregister,\n getItems\n ]\n );\n\n const ListPrimitive = asChild ? Slot : \"div\";\n\n return (\n <FocusContext.Provider value={focusContextValue}>\n <ListPrimitive\n role=\"tablist\"\n aria-orientation={orientation}\n data-orientation={orientation}\n data-slot=\"stepper-list\"\n dir={context.dir}\n tabIndex={isTabbingBackOut || focusableItemCount === 0 ? -1 : 0}\n {...listProps}\n ref={composedRef}\n className={cn(\n \"flex outline-none\",\n orientation === \"horizontal\" ? \"flex-row items-center\" : \"flex-col items-start\",\n className\n )}\n onBlur={onBlur}\n onFocus={onFocus}\n onMouseDown={onMouseDown}\n >\n {children}\n </ListPrimitive>\n </FocusContext.Provider>\n );\n}\n\ninterface StepperItemContextValue {\n value: string;\n stepState: StepState | undefined;\n}\n\nconst StepperItemContext = React.createContext<StepperItemContextValue | null>(null);\n\nfunction useStepperItemContext(consumerName: string) {\n const context = React.useContext(StepperItemContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ITEM_NAME}\\``);\n }\n return context;\n}\n\ninterface StepperItemProps extends DivProps {\n value: string;\n completed?: boolean;\n disabled?: boolean;\n}\n\nfunction StepperItem(props: StepperItemProps) {\n const {\n value: itemValue,\n completed = false,\n disabled = false,\n asChild,\n className,\n children,\n ref,\n ...itemProps\n } = props;\n\n const context = useStepperContext(ITEM_NAME);\n const store = useStoreContext(ITEM_NAME);\n const orientation = context.orientation;\n const value = useStore((state) => state.value);\n\n /*\n * ⚠ Khác thượng nguồn: đăng ký/huỷ đăng ký chỉ phụ thuộc `itemValue`. Bản gốc phụ thuộc cả\n * `completed`/`disabled`, nên đánh dấu một bước là xong thì bước đó bị XOÁ rồi THÊM LẠI vào cuối\n * `Map` — thứ tự bước đảo (bước 1 thành \"Bước 3\"), `StepperPrev`/`StepperNext` tính sai vị trí,\n * và `onValueRemove`/`onValueAdd` bắn oan. Hai cờ đó đã có effect `setStep` ngay dưới đồng bộ.\n */\n useIsomorphicLayoutEffect(() => {\n store.addStep(itemValue, completed, disabled);\n\n return () => {\n store.removeStep(itemValue);\n };\n }, [itemValue]);\n\n useIsomorphicLayoutEffect(() => {\n store.setStep(itemValue, completed, disabled);\n }, [itemValue, completed, disabled]);\n\n const stepState = useStore((state) => state.steps.get(itemValue));\n const steps = useStore((state) => state.steps);\n const dataState = getDataState(value, itemValue, stepState, steps);\n\n const itemContextValue = React.useMemo<StepperItemContextValue>(\n () => ({\n value: itemValue,\n stepState\n }),\n [itemValue, stepState]\n );\n\n const ItemPrimitive = asChild ? Slot : \"div\";\n\n return (\n <StepperItemContext.Provider value={itemContextValue}>\n <ItemPrimitive\n data-disabled={stepState?.disabled ? \"\" : undefined}\n data-orientation={orientation}\n data-state={dataState}\n data-slot=\"stepper-item\"\n dir={context.dir}\n {...itemProps}\n ref={ref}\n className={cn(\n \"relative flex items-center not-last:flex-1\",\n orientation === \"horizontal\" ? \"flex-row\" : \"flex-col\",\n className\n )}\n >\n {children}\n </ItemPrimitive>\n </StepperItemContext.Provider>\n );\n}\n\nfunction StepperTrigger(props: ButtonProps) {\n const {\n asChild,\n onClick: onClickProp,\n onFocus: onFocusProp,\n onKeyDown: onKeyDownProp,\n onMouseDown: onMouseDownProp,\n disabled,\n className,\n ref,\n ...triggerProps\n } = props;\n\n const context = useStepperContext(TRIGGER_NAME);\n const itemContext = useStepperItemContext(TRIGGER_NAME);\n const itemValue = itemContext.value;\n\n const store = useStoreContext(TRIGGER_NAME);\n const focusContext = useFocusContext(TRIGGER_NAME);\n const value = useStore((state) => state.value);\n const steps = useStore((state) => state.steps);\n const stepState = useStore((state) => state.steps.get(itemValue));\n\n const propsRef = useAsRef({\n onClick: onClickProp,\n onFocus: onFocusProp,\n onKeyDown: onKeyDownProp,\n onMouseDown: onMouseDownProp\n });\n\n const activationMode = context.activationMode;\n const orientation = context.orientation;\n const loop = context.loop;\n\n const stepIndex = Array.from(steps.keys()).indexOf(itemValue);\n\n const stepPosition = stepIndex + 1;\n const stepCount = steps.size;\n\n const triggerId = getId(context.rootId, \"trigger\", itemValue);\n const contentId = getId(context.rootId, \"content\", itemValue);\n const titleId = getId(context.rootId, \"title\", itemValue);\n const descriptionId = getId(context.rootId, \"description\", itemValue);\n\n const isDisabled = disabled || stepState?.disabled || context.disabled;\n const isActive = value === itemValue;\n const isTabStop = focusContext.tabStopId === triggerId;\n const dataState = getDataState(value, itemValue, stepState, steps);\n\n const triggerRef = React.useRef<TriggerElement>(null);\n const composedRef = useComposedRefs(ref, triggerRef);\n const isArrowKeyPressedRef = React.useRef(false);\n const isMouseClickRef = React.useRef(false);\n\n React.useEffect(() => {\n function onKeyDown(event: KeyboardEvent) {\n if (ARROW_KEYS.includes(event.key)) {\n isArrowKeyPressedRef.current = true;\n }\n }\n function onKeyUp() {\n isArrowKeyPressedRef.current = false;\n }\n document.addEventListener(\"keydown\", onKeyDown);\n document.addEventListener(\"keyup\", onKeyUp);\n return () => {\n document.removeEventListener(\"keydown\", onKeyDown);\n document.removeEventListener(\"keyup\", onKeyUp);\n };\n }, []);\n\n useIsomorphicLayoutEffect(() => {\n focusContext.onItemRegister({\n id: triggerId,\n ref: triggerRef,\n value: itemValue,\n active: isTabStop,\n disabled: !!isDisabled\n });\n\n if (!isDisabled) {\n focusContext.onFocusableItemAdd();\n }\n\n return () => {\n focusContext.onItemUnregister(triggerId);\n if (!isDisabled) {\n focusContext.onFocusableItemRemove();\n }\n };\n }, [focusContext, triggerId, itemValue, isTabStop, isDisabled]);\n\n const onClick = React.useCallback(\n async (event: React.MouseEvent<TriggerElement>) => {\n propsRef.current.onClick?.(event);\n if (event.defaultPrevented) return;\n\n if (!isDisabled && !context.nonInteractive) {\n const currentStepIndex = Array.from(steps.keys()).indexOf(value ?? \"\");\n const targetStepIndex = Array.from(steps.keys()).indexOf(itemValue);\n const direction = targetStepIndex > currentStepIndex ? \"next\" : \"prev\";\n\n await store.setStateWithValidation(itemValue, direction);\n }\n },\n [isDisabled, context.nonInteractive, store, itemValue, value, steps, propsRef]\n );\n\n const onFocus = React.useCallback(\n async (event: React.FocusEvent<TriggerElement>) => {\n propsRef.current.onFocus?.(event);\n if (event.defaultPrevented) return;\n\n focusContext.onItemFocus(triggerId);\n\n const isKeyboardFocus = !isMouseClickRef.current;\n\n if (!isActive && !isDisabled && activationMode !== \"manual\" && !context.nonInteractive && isKeyboardFocus) {\n const currentStepIndex = Array.from(steps.keys()).indexOf(value || \"\");\n const targetStepIndex = Array.from(steps.keys()).indexOf(itemValue);\n const direction = targetStepIndex > currentStepIndex ? \"next\" : \"prev\";\n\n await store.setStateWithValidation(itemValue, direction);\n }\n\n isMouseClickRef.current = false;\n },\n [\n focusContext,\n triggerId,\n activationMode,\n isActive,\n isDisabled,\n context.nonInteractive,\n store,\n itemValue,\n value,\n steps,\n propsRef\n ]\n );\n\n const onKeyDown = React.useCallback(\n async (event: React.KeyboardEvent<TriggerElement>) => {\n propsRef.current.onKeyDown?.(event);\n if (event.defaultPrevented) return;\n\n if (event.key === \"Enter\" && context.nonInteractive) {\n event.preventDefault();\n return;\n }\n\n if ((event.key === \"Enter\" || event.key === \" \") && activationMode === \"manual\" && !context.nonInteractive) {\n event.preventDefault();\n if (!isDisabled && triggerRef.current) {\n triggerRef.current.click();\n }\n return;\n }\n\n if (event.key === \"Tab\" && event.shiftKey) {\n focusContext.onItemShiftTab();\n return;\n }\n\n if (event.target !== event.currentTarget) return;\n\n const focusIntent = getFocusIntent(event, context.dir, orientation);\n\n if (focusIntent !== undefined) {\n if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) return;\n event.preventDefault();\n\n const items = focusContext.getItems().filter((item) => !item.disabled);\n let candidateRefs = items.map((item) => item.ref);\n\n if (focusIntent === \"last\") {\n candidateRefs.reverse();\n } else if (focusIntent === \"prev\" || focusIntent === \"next\") {\n if (focusIntent === \"prev\") candidateRefs.reverse();\n const currentIndex = candidateRefs.findIndex((ref) => ref.current === event.currentTarget);\n candidateRefs = loop ? wrapArray(candidateRefs, currentIndex + 1) : candidateRefs.slice(currentIndex + 1);\n }\n\n if (store.hasValidation() && candidateRefs.length > 0) {\n const nextRef = candidateRefs[0];\n const nextElement = nextRef?.current;\n const nextItem = items.find((item) => item.ref.current === nextElement);\n\n if (nextItem && nextItem.value !== itemValue) {\n const currentStepIndex = Array.from(steps.keys()).indexOf(value || \"\");\n const targetStepIndex = Array.from(steps.keys()).indexOf(nextItem.value);\n const direction: NavigationDirection = targetStepIndex > currentStepIndex ? \"next\" : \"prev\";\n\n if (direction === \"next\") {\n const isValid = await store.setStateWithValidation(nextItem.value, direction);\n if (!isValid) return;\n } else {\n store.setState(\"value\", nextItem.value);\n }\n\n queueMicrotask(() => nextElement?.focus());\n return;\n }\n }\n\n queueMicrotask(() => focusFirst(candidateRefs));\n }\n },\n [\n focusContext,\n context.nonInteractive,\n context.dir,\n activationMode,\n orientation,\n loop,\n isDisabled,\n store,\n propsRef,\n itemValue,\n value,\n steps\n ]\n );\n\n const onMouseDown = React.useCallback(\n (event: React.MouseEvent<TriggerElement>) => {\n propsRef.current.onMouseDown?.(event);\n if (event.defaultPrevented) return;\n\n isMouseClickRef.current = true;\n\n if (isDisabled) {\n event.preventDefault();\n } else {\n focusContext.onItemFocus(triggerId);\n }\n },\n [focusContext, triggerId, isDisabled, propsRef]\n );\n\n const TriggerPrimitive = asChild ? Slot : \"button\";\n\n return (\n <TriggerPrimitive\n id={triggerId}\n role=\"tab\"\n type=\"button\"\n aria-controls={contentId}\n aria-current={isActive ? \"step\" : undefined}\n aria-describedby={`${titleId} ${descriptionId}`}\n aria-posinset={stepPosition}\n aria-selected={isActive}\n aria-setsize={stepCount}\n data-disabled={isDisabled ? \"\" : undefined}\n data-state={dataState}\n data-slot=\"stepper-trigger\"\n disabled={isDisabled}\n tabIndex={isTabStop ? 0 : -1}\n {...triggerProps}\n ref={composedRef}\n className={cn(\n /*\n * ⚠ Khác thượng nguồn:\n * - Vòng focus theo khuôn `Checkbox`/`RadioGroup` của gói, thay cho `ring-[3px]` của bản gốc.\n * - Lỗi (`aria-invalid`) viền bằng `--destructive-ink` — VAI TRÒ viền trên nền trang (hợp\n * đồng §1 của docs/hop-dong-mau.md); bản gốc dùng `border-destructive` là token TÔ NỀN.\n */\n \"inline-flex items-center justify-center gap-3 rounded-md text-left transition-all outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive-ink aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n \"not-has-data-[slot=description]:rounded-full not-has-data-[slot=title]:rounded-full\",\n className\n )}\n onClick={onClick}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onMouseDown={onMouseDown}\n />\n );\n}\n\ninterface StepperIndicatorProps extends Omit<DivProps, \"children\"> {\n children?: React.ReactNode | ((dataState: DataState) => React.ReactNode);\n}\n\nfunction StepperIndicator(props: StepperIndicatorProps) {\n const { className, children, asChild, ref, ...indicatorProps } = props;\n\n const context = useStepperContext(INDICATOR_NAME);\n const itemContext = useStepperItemContext(INDICATOR_NAME);\n\n const value = useStore((state) => state.value);\n const itemValue = itemContext.value;\n const stepState = useStore((state) => state.steps.get(itemValue));\n const steps = useStore((state) => state.steps);\n\n const stepPosition = Array.from(steps.keys()).indexOf(itemValue) + 1;\n\n const dataState = getDataState(value, itemValue, stepState, steps);\n\n const IndicatorPrimitive = asChild ? Slot : \"div\";\n\n return (\n <IndicatorPrimitive\n data-state={dataState}\n data-slot=\"stepper-indicator\"\n dir={context.dir}\n {...indicatorProps}\n ref={ref}\n className={cn(\n /*\n * ⚠ Khác thượng nguồn — màu đi qua token VAI TRÒ (docs/hop-dong-mau.md §1, §3):\n * - Lúc nghỉ: viền `--control-edge` thay `border-muted`. Ô chỉ báo là HÌNH của chính nút\n * bước, nên viền của nó là viền control; `--muted` là token bề mặt, đem làm viền thì bảng\n * tương phản cao không kéo lên được. Ở bảng mặc định `--control-edge` nhạt đúng như bản gốc.\n * - Đang làm/đã xong: nền ĐẶC `bg-primary` + chữ/tick `text-primary-foreground` (giữ nguyên),\n * nhưng viền là `--primary-ink` chứ không `border-primary`: nền vàng đặc chỉ ~1,86:1 với\n * nền trang, nên chính VIỀN mới là dấu hiệu trạng thái đạt 3:1 (6,51:1 ở bảng tương phản cao).\n * - Chữ lúc nghỉ viết `data-[state=inactive]:text-muted-foreground` thay cho lớp trần: CSS y\n * hệt (ba trạng thái loại trừ nhau), nhưng cổng `lint:a11y` không ghép nhầm chữ xám với nền\n * vàng của trạng thái đang làm — cặp đó không bao giờ cùng xuất hiện.\n */\n \"flex size-7 shrink-0 items-center justify-center rounded-full border-2 border-control-edge bg-background text-sm font-medium data-[state=inactive]:text-muted-foreground transition-colors data-[state=active]:border-primary-ink data-[state=active]:bg-primary data-[state=active]:text-primary-foreground data-[state=completed]:border-primary-ink data-[state=completed]:bg-primary data-[state=completed]:text-primary-foreground\",\n className\n )}\n >\n {typeof children === \"function\" ? (\n children(dataState)\n ) : children ? (\n children\n ) : dataState === \"completed\" ? (\n /*\n * ⚠ Khác thượng nguồn: bản gốc chỉ vẽ dấu tick. Trigger chỉ chứa ô chỉ báo (demo mặc định\n * của Dice UI) thì bước đã xong thành một nút KHÔNG TÊN — con số vốn là tên nút đã bị dấu\n * tick thay mất. Thêm chữ `sr-only` giữ lại con số và nói luôn trạng thái.\n */\n <>\n <Check aria-hidden=\"true\" className=\"size-4\" />\n <span className=\"sr-only\">{context.labels.completedStep(stepPosition)}</span>\n </>\n ) : (\n stepPosition\n )}\n </IndicatorPrimitive>\n );\n}\n\ninterface StepperSeparatorProps extends DivProps {\n forceMount?: boolean;\n}\n\nfunction StepperSeparator(props: StepperSeparatorProps) {\n const { className, asChild, forceMount = false, ref, ...separatorProps } = props;\n\n const context = useStepperContext(SEPARATOR_NAME);\n const itemContext = useStepperItemContext(SEPARATOR_NAME);\n const value = useStore((state) => state.value);\n const steps = useStore((state) => state.steps);\n\n const orientation = context.orientation;\n\n const stepIndex = Array.from(steps.keys()).indexOf(itemContext.value);\n\n const isLastStep = stepIndex === steps.size - 1;\n\n if (isLastStep && !forceMount) return null;\n\n const dataState = getDataState(value, itemContext.value, itemContext.stepState, steps, \"separator\");\n\n const SeparatorPrimitive = asChild ? Slot : \"div\";\n\n /*\n * ⚠ Khác thượng nguồn: bỏ `role=\"separator\"` + `aria-orientation`. Thẻ đã `aria-hidden` nên hai\n * thuộc tính đó không bao giờ tới trình đọc màn hình — cùng khuôn `TimelineConnector` của chính\n * Dice UI. Để lại thì cổng `lint:a11y` đọc `role=` là dấu hiệu CONTROL (thanh chia `Resizable`\n * focus được) và bắt sợi tóc trang trí ở đoạn CHƯA tới phải đạt 3:1 như một control.\n */\n return (\n <SeparatorPrimitive\n aria-hidden=\"true\"\n data-orientation={orientation}\n data-state={dataState}\n data-slot=\"stepper-separator\"\n dir={context.dir}\n {...separatorProps}\n ref={ref}\n className={cn(\n /*\n * ⚠ Khác thượng nguồn: đoạn nối ĐÃ XONG mang nghĩa tiến độ (phi văn bản, 3:1) → `--primary-ink`\n * thay `bg-primary` (token tô nền, ~1,86:1 với nền trang). Đoạn CHƯA tới giữ `bg-border`:\n * sợi tóc 1px, thuần trang trí.\n */\n \"bg-border transition-colors data-[state=active]:bg-primary-ink data-[state=completed]:bg-primary-ink\",\n orientation === \"horizontal\" ? \"h-px flex-1\" : \"h-10 w-px\",\n className\n )}\n />\n );\n}\n\ninterface StepperTitleProps extends React.ComponentProps<\"span\"> {\n asChild?: boolean;\n}\n\nfunction StepperTitle(props: StepperTitleProps) {\n const { className, asChild, ref, ...titleProps } = props;\n\n const context = useStepperContext(TITLE_NAME);\n const itemContext = useStepperItemContext(TITLE_NAME);\n\n const titleId = getId(context.rootId, \"title\", itemContext.value);\n\n const TitlePrimitive = asChild ? Slot : \"span\";\n\n return (\n <TitlePrimitive\n id={titleId}\n data-slot=\"title\"\n dir={context.dir}\n {...titleProps}\n ref={ref}\n className={cn(\"text-sm font-medium\", className)}\n />\n );\n}\n\ninterface StepperDescriptionProps extends React.ComponentProps<\"span\"> {\n asChild?: boolean;\n}\n\nfunction StepperDescription(props: StepperDescriptionProps) {\n const { className, asChild, ref, ...descriptionProps } = props;\n\n const context = useStepperContext(DESCRIPTION_NAME);\n const itemContext = useStepperItemContext(DESCRIPTION_NAME);\n\n const descriptionId = getId(context.rootId, \"description\", itemContext.value);\n\n const DescriptionPrimitive = asChild ? Slot : \"span\";\n\n return (\n <DescriptionPrimitive\n id={descriptionId}\n data-slot=\"description\"\n dir={context.dir}\n {...descriptionProps}\n ref={ref}\n className={cn(\"text-xs text-muted-foreground\", className)}\n />\n );\n}\n\ninterface StepperContentProps extends DivProps {\n value: string;\n forceMount?: boolean;\n}\n\nfunction StepperContent(props: StepperContentProps) {\n const { value: valueProp, asChild, forceMount = false, ref, className, ...contentProps } = props;\n\n const context = useStepperContext(CONTENT_NAME);\n const value = useStore((state) => state.value);\n\n const contentId = getId(context.rootId, \"content\", valueProp);\n const triggerId = getId(context.rootId, \"trigger\", valueProp);\n\n if (valueProp !== value && !forceMount) return null;\n\n const ContentPrimitive = asChild ? Slot : \"div\";\n\n return (\n <ContentPrimitive\n id={contentId}\n role=\"tabpanel\"\n aria-labelledby={triggerId}\n data-slot=\"stepper-content\"\n dir={context.dir}\n {...contentProps}\n ref={ref}\n className={cn(\"flex-1 outline-none\", className)}\n />\n );\n}\n\nfunction StepperPrev(props: ButtonProps) {\n const { asChild, onClick: onClickProp, disabled, children, ...prevProps } = props;\n\n const context = useStepperContext(PREV_NAME);\n const store = useStoreContext(PREV_NAME);\n const value = useStore((state) => state.value);\n const steps = useStore((state) => state.steps);\n\n const propsRef = useAsRef({\n onClick: onClickProp\n });\n\n const stepKeys = Array.from(steps.keys());\n const currentIndex = value ? stepKeys.indexOf(value) : -1;\n const isDisabled = disabled || currentIndex <= 0;\n\n const onClick = React.useCallback(\n async (event: React.MouseEvent<HTMLButtonElement>) => {\n propsRef.current.onClick?.(event);\n if (event.defaultPrevented || isDisabled) return;\n\n const prevIndex = Math.max(currentIndex - 1, 0);\n const prevStepValue = stepKeys[prevIndex];\n\n if (prevStepValue) {\n store.setState(\"value\", prevStepValue);\n }\n },\n [propsRef, isDisabled, currentIndex, stepKeys, store]\n );\n\n const PrevPrimitive = asChild ? Slot : \"button\";\n\n return (\n <PrevPrimitive type=\"button\" data-slot=\"stepper-prev\" disabled={isDisabled} {...prevProps} onClick={onClick}>\n {/* ⚠ Khác thượng nguồn: thiếu `children` thì bản gốc ra nút rỗng, không tên. */}\n {asChild ? children : (children ?? context.labels.prev)}\n </PrevPrimitive>\n );\n}\n\nfunction StepperNext(props: ButtonProps) {\n const { asChild, onClick: onClickProp, disabled, children, ...nextProps } = props;\n\n const context = useStepperContext(NEXT_NAME);\n const store = useStoreContext(NEXT_NAME);\n const value = useStore((state) => state.value);\n const steps = useStore((state) => state.steps);\n\n const propsRef = useAsRef({\n onClick: onClickProp\n });\n\n const stepKeys = Array.from(steps.keys());\n const currentIndex = value ? stepKeys.indexOf(value) : -1;\n const isDisabled = disabled || currentIndex >= stepKeys.length - 1;\n\n const onClick = React.useCallback(\n async (event: React.MouseEvent<HTMLButtonElement>) => {\n propsRef.current.onClick?.(event);\n if (event.defaultPrevented || isDisabled) return;\n\n const nextIndex = Math.min(currentIndex + 1, stepKeys.length - 1);\n const nextStepValue = stepKeys[nextIndex];\n\n if (nextStepValue) {\n await store.setStateWithValidation(nextStepValue, \"next\");\n }\n },\n [propsRef, isDisabled, currentIndex, stepKeys, store]\n );\n\n const NextPrimitive = asChild ? Slot : \"button\";\n\n return (\n <NextPrimitive type=\"button\" data-slot=\"stepper-next\" disabled={isDisabled} {...nextProps} onClick={onClick}>\n {/* ⚠ Khác thượng nguồn: thiếu `children` thì bản gốc ra nút rỗng, không tên. */}\n {asChild ? children : (children ?? context.labels.next)}\n </NextPrimitive>\n );\n}\n\nexport {\n Stepper,\n StepperContent,\n type StepperContentProps,\n StepperDescription,\n type StepperDescriptionProps,\n StepperIndicator,\n type StepperIndicatorProps,\n StepperItem,\n type StepperItemProps,\n StepperList,\n StepperNext,\n StepperPrev,\n type StepperProps,\n StepperSeparator,\n type StepperSeparatorProps,\n StepperTitle,\n type StepperTitleProps,\n StepperTrigger,\n useStore as useStepper\n};\n"],"mappings":"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","names":["value","disabled","tabStopId","onKeyDown","ref"]}
1
+ {"version":3,"sources":["../../../src/components/ui/stepper.tsx"],"sourcesContent":["\"use client\";\n\n/*\n * Port từ Dice UI (https://diceui.com/docs/components/stepper) — MIT, © 2024 Sadman Sakib.\n * Giữ nguyên cấu trúc thượng nguồn để còn đối chiếu ngược được; mọi chỗ đổi đều có chú thích.\n */\n\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { Check } from \"lucide-react\";\nimport * as React from \"react\";\nimport { useComitorLabels } from \"../../i18n/locale-provider.js\";\nimport { cn } from \"../../lib/cn.js\";\nimport { collectItemElements } from \"../../lib/collect-item-elements.js\";\nimport { useComposedRefs } from \"../../lib/compose-refs.js\";\nimport { useAsRef } from \"../../lib/use-as-ref.js\";\nimport { useIsomorphicLayoutEffect } from \"../../lib/use-isomorphic-layout-effect.js\";\nimport { useLazyRef } from \"../../lib/use-lazy-ref.js\";\nimport type { StepperLabels } from \"./stepper-constants.js\";\n\nconst ROOT_NAME = \"Stepper\";\nconst LIST_NAME = \"StepperList\";\nconst ITEM_NAME = \"StepperItem\";\nconst TRIGGER_NAME = \"StepperTrigger\";\nconst INDICATOR_NAME = \"StepperIndicator\";\nconst SEPARATOR_NAME = \"StepperSeparator\";\nconst TITLE_NAME = \"StepperTitle\";\nconst DESCRIPTION_NAME = \"StepperDescription\";\nconst CONTENT_NAME = \"StepperContent\";\nconst PREV_NAME = \"StepperPrev\";\nconst NEXT_NAME = \"StepperNext\";\n\nconst ENTRY_FOCUS = \"stepperFocusGroup.onEntryFocus\";\nconst EVENT_OPTIONS = { bubbles: false, cancelable: true };\nconst ARROW_KEYS = [\"ArrowUp\", \"ArrowDown\", \"ArrowLeft\", \"ArrowRight\"];\n\ntype Direction = \"ltr\" | \"rtl\";\ntype Orientation = \"horizontal\" | \"vertical\";\ntype NavigationDirection = \"next\" | \"prev\";\ntype ActivationMode = \"automatic\" | \"manual\";\ntype DataState = \"inactive\" | \"active\" | \"completed\";\n\ninterface DivProps extends React.ComponentProps<\"div\"> {\n asChild?: boolean;\n}\ninterface ButtonProps extends React.ComponentProps<\"button\"> {\n asChild?: boolean;\n}\n\ntype ListElement = React.ComponentRef<typeof StepperList>;\ntype TriggerElement = React.ComponentRef<typeof StepperTrigger>;\n\nfunction getId(id: string, variant: \"trigger\" | \"content\" | \"title\" | \"description\", value: string) {\n return `${id}-${variant}-${value}`;\n}\n\ntype FocusIntent = \"first\" | \"last\" | \"prev\" | \"next\";\n\nconst MAP_KEY_TO_FOCUS_INTENT: Record<string, FocusIntent> = {\n ArrowLeft: \"prev\",\n ArrowUp: \"prev\",\n ArrowRight: \"next\",\n ArrowDown: \"next\",\n PageUp: \"first\",\n Home: \"first\",\n PageDown: \"last\",\n End: \"last\"\n};\n\nfunction getDirectionAwareKey(key: string, dir?: Direction) {\n if (dir !== \"rtl\") return key;\n return key === \"ArrowLeft\" ? \"ArrowRight\" : key === \"ArrowRight\" ? \"ArrowLeft\" : key;\n}\n\nfunction getFocusIntent(event: React.KeyboardEvent<TriggerElement>, dir?: Direction, orientation?: Orientation) {\n const key = getDirectionAwareKey(event.key, dir);\n if (orientation === \"horizontal\" && [\"ArrowUp\", \"ArrowDown\"].includes(key)) return undefined;\n if (orientation === \"vertical\" && [\"ArrowLeft\", \"ArrowRight\"].includes(key)) return undefined;\n return MAP_KEY_TO_FOCUS_INTENT[key];\n}\n\nfunction focusFirst(candidates: React.RefObject<TriggerElement | null>[], preventScroll = false) {\n const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;\n for (const candidateRef of candidates) {\n const candidate = candidateRef.current;\n if (!candidate) continue;\n if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;\n candidate.focus({ preventScroll });\n if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;\n }\n}\n\nfunction wrapArray<T>(array: T[], startIndex: number) {\n return array.map<T>((_, index) => array[(startIndex + index) % array.length] as T);\n}\n\nfunction getDataState(\n value: string | undefined,\n itemValue: string,\n stepState: StepState | undefined,\n steps: Map<string, StepState>,\n variant: \"item\" | \"separator\" = \"item\"\n): DataState {\n const stepKeys = Array.from(steps.keys());\n const currentIndex = stepKeys.indexOf(itemValue);\n\n if (stepState?.completed) return \"completed\";\n\n if (value === itemValue) {\n return variant === \"separator\" ? \"inactive\" : \"active\";\n }\n\n if (value) {\n const activeIndex = stepKeys.indexOf(value);\n\n if (activeIndex > currentIndex) return \"completed\";\n }\n\n return \"inactive\";\n}\n\ninterface StepState {\n value: string;\n completed: boolean;\n disabled: boolean;\n}\n\n/*\n * ⚠ Khác thượng nguồn (3.1.0): các bước ĐỌC TỪ CÂY PHẦN TỬ của `Stepper`, theo thứ tự tài liệu —\n * `StepperItem` viết trong `StepperList` (qua mảng, fragment, thẻ HTML), còn `StepperList` viết trong\n * `Stepper` cũng như vậy. Cờ `completed`/`disabled` lấy từ props với cùng mặc định như lúc đăng ký.\n * Không đọc được (luật ở `collectItemElements`) thì rỗng — đúng như trước bản này.\n */\nfunction getStepsFromChildren(children: React.ReactNode) {\n const steps = new Map<string, StepState>();\n const items = collectItemElements(children, { item: StepperItem, list: StepperList });\n for (const { props } of items ?? []) {\n const { value, completed = false, disabled = false } = props;\n steps.set(value, { value, completed, disabled });\n }\n return steps;\n}\n\ninterface StoreState {\n steps: Map<string, StepState>;\n value: string;\n}\n\ninterface Store {\n subscribe: (callback: () => void) => () => void;\n getState: () => StoreState;\n getInitialState: () => StoreState;\n setState: <K extends keyof StoreState>(key: K, value: StoreState[K]) => void;\n setStateWithValidation: (value: string, direction: NavigationDirection) => Promise<boolean>;\n hasValidation: () => boolean;\n notify: () => void;\n addStep: (value: string, completed: boolean, disabled: boolean) => void;\n removeStep: (value: string) => void;\n setStep: (value: string, completed: boolean, disabled: boolean) => void;\n}\n\nconst StoreContext = React.createContext<Store | null>(null);\n\nfunction useStoreContext(consumerName: string) {\n const context = React.useContext(StoreContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ROOT_NAME}\\``);\n }\n return context;\n}\n\nfunction useStore<T>(selector: (state: StoreState) => T): T {\n const store = useStoreContext(\"useStepper\");\n\n const getSnapshot = React.useCallback(() => selector(store.getState()), [store, selector]);\n /*\n * ⚠ Khác thượng nguồn (3.1.0): snapshot SERVER riêng — trạng thái đọc từ cây ở lượt render đầu của\n * gốc (xem `initialStateRef` trong `Stepper`). React dùng nó ở server và ở lượt hydrate của TỪNG\n * phần, nên hai bên ra cùng một HTML, kể cả phần hydrate muộn; hydrate xong React tự so với\n * `getSnapshot` và render lại nếu khác. Bản gốc dùng `getSnapshot` cho cả hai.\n */\n const getServerSnapshot = React.useCallback(() => selector(store.getInitialState()), [store, selector]);\n\n return React.useSyncExternalStore(store.subscribe, getSnapshot, getServerSnapshot);\n}\n\ninterface ItemData {\n id: string;\n ref: React.RefObject<TriggerElement | null>;\n value: string;\n active: boolean;\n disabled: boolean;\n}\n\ninterface StepperContextValue {\n rootId: string;\n dir: Direction;\n orientation: Orientation;\n activationMode: ActivationMode;\n disabled: boolean;\n nonInteractive: boolean;\n loop: boolean;\n labels: StepperLabels;\n}\n\nconst StepperContext = React.createContext<StepperContextValue | null>(null);\n\nfunction useStepperContext(consumerName: string) {\n const context = React.useContext(StepperContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ROOT_NAME}\\``);\n }\n return context;\n}\n\ninterface StepperProps extends DivProps {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n onValueComplete?: (value: string, completed: boolean) => void;\n onValueAdd?: (value: string) => void;\n onValueRemove?: (value: string) => void;\n onValidate?: (value: string, direction: NavigationDirection) => boolean | Promise<boolean>;\n activationMode?: ActivationMode;\n dir?: Direction;\n orientation?: Orientation;\n disabled?: boolean;\n loop?: boolean;\n nonInteractive?: boolean;\n /**\n * Chuỗi hiển thị/a11y — ghi đè từng khoá. Không truyền thì theo namespace `stepper` của\n * `ComitorLocaleProvider` (mặc định tiếng Anh).\n *\n * ⚠ Thêm so với thượng nguồn: bản gốc không có chuỗi nào, và chính vì thế có hai chỗ ra nút\n * KHÔNG TÊN (ô chỉ báo bước đã xong, `StepperPrev`/`StepperNext` thiếu `children`).\n */\n labels?: Partial<StepperLabels>;\n}\n\nfunction Stepper(props: StepperProps) {\n const {\n value,\n defaultValue,\n onValueChange,\n onValueComplete,\n onValueAdd,\n onValueRemove,\n onValidate,\n dir: dirProp,\n orientation = \"horizontal\",\n activationMode = \"automatic\",\n asChild,\n disabled = false,\n nonInteractive = false,\n loop = false,\n labels: labelsProp,\n className,\n id,\n ...rootProps\n } = props;\n\n const listenersRef = useLazyRef(() => new Set<() => void>());\n const stateRef = useLazyRef<StoreState>(() => ({\n steps: new Map(),\n value: value ?? defaultValue ?? \"\"\n }));\n /*\n * ⚠ Khác thượng nguồn (3.1.0): trạng thái cho mọi lượt render TRƯỚC khi các bước đăng ký. Bản gốc\n * chỉ biết bước qua đăng ký trong layout effect, nên HTML server — và khung hình đầu, cả lúc hydrate\n * lẫn lúc mount thuần client — có mọi chỉ số \"0\", không vạch nối, Quay lại/Tiếp theo đều khoá, bước\n * `completed`/`disabled` không mang cờ của nó; mount xong mới tự đúng, thành một khung nháy.\n * - Chụp MỘT lần, ở lượt render đầu, và không bao giờ sửa: nó là snapshot SERVER của `useStore`,\n * nên phải đúng là cái server đã render — kể cả cho phần hydrate muộn hơn gốc.\n * - Chỉ có hiệu lực tới layout effect đầu của gốc (`registeredRef`). Effect của con chạy trước của\n * cha, nên lúc đó mọi bước đọc được đã đăng ký, theo đúng thứ tự đọc được (bất biến ở\n * `collectItemElements`) — đổi nguồn không đổi gì trên màn hình. Từ đó thứ tự ĐĂNG KÝ thắng như\n * cũ: bước thêm/bớt/đổi chỗ sau mount vẫn theo đăng ký.\n */\n const initialStateRef = useLazyRef<StoreState>(() => ({\n steps: getStepsFromChildren(props.children),\n value: stateRef.current.value\n }));\n const registeredRef = React.useRef(false);\n\n const propsRef = useAsRef({\n onValueChange,\n onValueComplete,\n onValueAdd,\n onValueRemove,\n onValidate\n });\n\n const store = React.useMemo<Store>(() => {\n return {\n subscribe: (cb) => {\n listenersRef.current.add(cb);\n return () => listenersRef.current.delete(cb);\n },\n // ⚠ Khác thượng nguồn (3.1.0): trước khi các bước đăng ký, trạng thái có hiệu lực là trạng thái\n // đọc từ cây — xem `initialStateRef`. Các hàm ghi bên dưới luôn ghi vào `stateRef`.\n getState: () => (registeredRef.current ? stateRef.current : initialStateRef.current),\n getInitialState: () => initialStateRef.current,\n setState: (key, value) => {\n if (Object.is(stateRef.current[key], value)) return;\n\n if (key === \"value\" && typeof value === \"string\") {\n stateRef.current.value = value;\n propsRef.current.onValueChange?.(value);\n } else {\n stateRef.current[key] = value;\n }\n\n store.notify();\n },\n setStateWithValidation: async (value, direction) => {\n if (!propsRef.current.onValidate) {\n store.setState(\"value\", value);\n return true;\n }\n\n try {\n const isValid = await propsRef.current.onValidate(value, direction);\n if (isValid) {\n store.setState(\"value\", value);\n }\n return isValid;\n } catch {\n return false;\n }\n },\n hasValidation: () => !!propsRef.current.onValidate,\n /*\n * ⚠ Khác thượng nguồn: mỗi lần thêm/bớt/sửa bước đều thay `steps` bằng một `Map` MỚI. Bản gốc\n * sửa tại chỗ nên `useStore((s) => s.steps)` không bao giờ thấy tham chiếu mới — phần tử chỉ\n * đọc `steps` (`StepperPrev`/`StepperNext`) không render lại sau khi các bước đăng ký, và\n * nằm `disabled` cho tới lần đổi bước đầu tiên.\n */\n addStep: (value, completed, disabled) => {\n const newStep: StepState = { value, completed, disabled };\n const steps = new Map(stateRef.current.steps);\n steps.set(value, newStep);\n stateRef.current.steps = steps;\n propsRef.current.onValueAdd?.(value);\n store.notify();\n },\n removeStep: (value) => {\n const steps = new Map(stateRef.current.steps);\n steps.delete(value);\n stateRef.current.steps = steps;\n propsRef.current.onValueRemove?.(value);\n store.notify();\n },\n setStep: (value, completed, disabled) => {\n const step = stateRef.current.steps.get(value);\n if (step) {\n const updatedStep: StepState = { ...step, completed, disabled };\n const steps = new Map(stateRef.current.steps);\n steps.set(value, updatedStep);\n stateRef.current.steps = steps;\n\n if (completed !== step.completed) {\n propsRef.current.onValueComplete?.(value, completed);\n }\n\n store.notify();\n }\n },\n notify: () => {\n for (const cb of listenersRef.current) {\n cb();\n }\n }\n };\n }, [listenersRef, stateRef, initialStateRef, propsRef]);\n\n useIsomorphicLayoutEffect(() => {\n if (value !== undefined) {\n store.setState(\"value\", value);\n }\n }, [value]);\n\n // ⚠ Khác thượng nguồn (3.1.0): từ đây thứ tự ĐĂNG KÝ là nguồn sự thật — xem `initialStateRef`.\n useIsomorphicLayoutEffect(() => {\n registeredRef.current = true;\n store.notify();\n }, [store]);\n\n const dir = useDirection(dirProp);\n\n const instanceId = React.useId();\n const rootId = id ?? instanceId;\n\n const labels = useComitorLabels(\"stepper\", labelsProp);\n\n const contextValue = React.useMemo<StepperContextValue>(\n () => ({\n rootId,\n dir,\n orientation,\n activationMode,\n disabled,\n nonInteractive,\n loop,\n labels\n }),\n [rootId, dir, orientation, activationMode, disabled, nonInteractive, loop, labels]\n );\n\n const RootPrimitive = asChild ? Slot : \"div\";\n\n return (\n <StoreContext.Provider value={store}>\n <StepperContext.Provider value={contextValue}>\n <RootPrimitive\n id={rootId}\n data-disabled={disabled ? \"\" : undefined}\n data-orientation={orientation}\n data-slot=\"stepper\"\n dir={dir}\n {...rootProps}\n className={cn(\"flex gap-6\", orientation === \"horizontal\" ? \"w-full flex-col\" : \"flex-row\", className)}\n />\n </StepperContext.Provider>\n </StoreContext.Provider>\n );\n}\n\ninterface FocusContextValue {\n tabStopId: string | null;\n onItemFocus: (tabStopId: string) => void;\n onItemShiftTab: () => void;\n onFocusableItemAdd: () => void;\n onFocusableItemRemove: () => void;\n onItemRegister: (item: ItemData) => void;\n onItemUnregister: (id: string) => void;\n getItems: () => ItemData[];\n}\n\nconst FocusContext = React.createContext<FocusContextValue | null>(null);\n\nfunction useFocusContext(consumerName: string) {\n const context = React.useContext(FocusContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${LIST_NAME}\\``);\n }\n return context;\n}\n\nfunction StepperList(props: DivProps) {\n const {\n asChild,\n onBlur: onBlurProp,\n onFocus: onFocusProp,\n onMouseDown: onMouseDownProp,\n className,\n children,\n ref,\n ...listProps\n } = props;\n\n const context = useStepperContext(LIST_NAME);\n const orientation = context.orientation;\n const currentValue = useStore((state) => state.value);\n\n const propsRef = useAsRef({\n onBlur: onBlurProp,\n onFocus: onFocusProp,\n onMouseDown: onMouseDownProp\n });\n\n const [tabStopId, setTabStopId] = React.useState<string | null>(null);\n const [isTabbingBackOut, setIsTabbingBackOut] = React.useState(false);\n const [focusableItemCount, setFocusableItemCount] = React.useState(0);\n const isClickFocusRef = React.useRef(false);\n const itemsRef = React.useRef<Map<string, ItemData>>(new Map());\n const listRef = React.useRef<ListElement>(null);\n const composedRef = useComposedRefs(ref, listRef);\n\n const onItemFocus = React.useCallback((tabStopId: string) => {\n setTabStopId(tabStopId);\n }, []);\n\n const onItemShiftTab = React.useCallback(() => {\n setIsTabbingBackOut(true);\n }, []);\n\n const onFocusableItemAdd = React.useCallback(() => {\n setFocusableItemCount((prevCount) => prevCount + 1);\n }, []);\n\n const onFocusableItemRemove = React.useCallback(() => {\n setFocusableItemCount((prevCount) => prevCount - 1);\n }, []);\n\n const onItemRegister = React.useCallback((item: ItemData) => {\n itemsRef.current.set(item.id, item);\n }, []);\n\n const onItemUnregister = React.useCallback((id: string) => {\n itemsRef.current.delete(id);\n }, []);\n\n const getItems = React.useCallback(() => {\n return Array.from(itemsRef.current.values())\n .filter((item) => item.ref.current)\n .sort((a, b) => {\n const elementA = a.ref.current;\n const elementB = b.ref.current;\n if (!elementA || !elementB) return 0;\n const position = elementA.compareDocumentPosition(elementB);\n if (position & Node.DOCUMENT_POSITION_FOLLOWING) {\n return -1;\n }\n if (position & Node.DOCUMENT_POSITION_PRECEDING) {\n return 1;\n }\n return 0;\n });\n }, []);\n\n const onBlur = React.useCallback(\n (event: React.FocusEvent<ListElement>) => {\n propsRef.current.onBlur?.(event);\n if (event.defaultPrevented) return;\n\n setIsTabbingBackOut(false);\n },\n [propsRef]\n );\n\n const onFocus = React.useCallback(\n (event: React.FocusEvent<ListElement>) => {\n propsRef.current.onFocus?.(event);\n if (event.defaultPrevented) return;\n\n const isKeyboardFocus = !isClickFocusRef.current;\n if (event.target === event.currentTarget && isKeyboardFocus && !isTabbingBackOut) {\n const entryFocusEvent = new CustomEvent(ENTRY_FOCUS, EVENT_OPTIONS);\n event.currentTarget.dispatchEvent(entryFocusEvent);\n\n if (!entryFocusEvent.defaultPrevented) {\n const items = Array.from(itemsRef.current.values()).filter((item) => !item.disabled);\n const selectedItem = currentValue ? items.find((item) => item.value === currentValue) : undefined;\n const activeItem = items.find((item) => item.active);\n const currentItem = items.find((item) => item.id === tabStopId);\n\n const candidateItems = [selectedItem, activeItem, currentItem, ...items].filter(Boolean) as ItemData[];\n const candidateRefs = candidateItems.map((item) => item.ref);\n focusFirst(candidateRefs, false);\n }\n }\n isClickFocusRef.current = false;\n },\n [propsRef, isTabbingBackOut, currentValue, tabStopId]\n );\n\n const onMouseDown = React.useCallback(\n (event: React.MouseEvent<ListElement>) => {\n propsRef.current.onMouseDown?.(event);\n\n if (event.defaultPrevented) return;\n\n isClickFocusRef.current = true;\n },\n [propsRef]\n );\n\n const focusContextValue = React.useMemo<FocusContextValue>(\n () => ({\n tabStopId,\n onItemFocus,\n onItemShiftTab,\n onFocusableItemAdd,\n onFocusableItemRemove,\n onItemRegister,\n onItemUnregister,\n getItems\n }),\n [\n tabStopId,\n onItemFocus,\n onItemShiftTab,\n onFocusableItemAdd,\n onFocusableItemRemove,\n onItemRegister,\n onItemUnregister,\n getItems\n ]\n );\n\n const ListPrimitive = asChild ? Slot : \"div\";\n\n return (\n <FocusContext.Provider value={focusContextValue}>\n <ListPrimitive\n role=\"tablist\"\n aria-orientation={orientation}\n data-orientation={orientation}\n data-slot=\"stepper-list\"\n dir={context.dir}\n tabIndex={isTabbingBackOut || focusableItemCount === 0 ? -1 : 0}\n {...listProps}\n ref={composedRef}\n className={cn(\n \"flex outline-none\",\n orientation === \"horizontal\" ? \"flex-row items-center\" : \"flex-col items-start\",\n className\n )}\n onBlur={onBlur}\n onFocus={onFocus}\n onMouseDown={onMouseDown}\n >\n {children}\n </ListPrimitive>\n </FocusContext.Provider>\n );\n}\n\ninterface StepperItemContextValue {\n value: string;\n stepState: StepState | undefined;\n}\n\nconst StepperItemContext = React.createContext<StepperItemContextValue | null>(null);\n\nfunction useStepperItemContext(consumerName: string) {\n const context = React.useContext(StepperItemContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ITEM_NAME}\\``);\n }\n return context;\n}\n\ninterface StepperItemProps extends DivProps {\n value: string;\n completed?: boolean;\n disabled?: boolean;\n}\n\nfunction StepperItem(props: StepperItemProps) {\n const {\n value: itemValue,\n completed = false,\n disabled = false,\n asChild,\n className,\n children,\n ref,\n ...itemProps\n } = props;\n\n const context = useStepperContext(ITEM_NAME);\n const store = useStoreContext(ITEM_NAME);\n const orientation = context.orientation;\n const value = useStore((state) => state.value);\n\n /*\n * ⚠ Khác thượng nguồn: đăng ký/huỷ đăng ký chỉ phụ thuộc `itemValue`. Bản gốc phụ thuộc cả\n * `completed`/`disabled`, nên đánh dấu một bước là xong thì bước đó bị XOÁ rồi THÊM LẠI vào cuối\n * `Map` — thứ tự bước đảo (bước 1 thành \"Bước 3\"), `StepperPrev`/`StepperNext` tính sai vị trí,\n * và `onValueRemove`/`onValueAdd` bắn oan. Hai cờ đó đã có effect `setStep` ngay dưới đồng bộ.\n */\n useIsomorphicLayoutEffect(() => {\n store.addStep(itemValue, completed, disabled);\n\n return () => {\n store.removeStep(itemValue);\n };\n }, [itemValue]);\n\n useIsomorphicLayoutEffect(() => {\n store.setStep(itemValue, completed, disabled);\n }, [itemValue, completed, disabled]);\n\n const stepState = useStore((state) => state.steps.get(itemValue));\n const steps = useStore((state) => state.steps);\n const dataState = getDataState(value, itemValue, stepState, steps);\n\n const itemContextValue = React.useMemo<StepperItemContextValue>(\n () => ({\n value: itemValue,\n stepState\n }),\n [itemValue, stepState]\n );\n\n const ItemPrimitive = asChild ? Slot : \"div\";\n\n return (\n <StepperItemContext.Provider value={itemContextValue}>\n <ItemPrimitive\n data-disabled={stepState?.disabled ? \"\" : undefined}\n data-orientation={orientation}\n data-state={dataState}\n data-slot=\"stepper-item\"\n dir={context.dir}\n {...itemProps}\n ref={ref}\n className={cn(\n \"relative flex items-center not-last:flex-1\",\n orientation === \"horizontal\" ? \"flex-row\" : \"flex-col\",\n className\n )}\n >\n {children}\n </ItemPrimitive>\n </StepperItemContext.Provider>\n );\n}\n\nfunction StepperTrigger(props: ButtonProps) {\n const {\n asChild,\n onClick: onClickProp,\n onFocus: onFocusProp,\n onKeyDown: onKeyDownProp,\n onMouseDown: onMouseDownProp,\n disabled,\n className,\n ref,\n ...triggerProps\n } = props;\n\n const context = useStepperContext(TRIGGER_NAME);\n const itemContext = useStepperItemContext(TRIGGER_NAME);\n const itemValue = itemContext.value;\n\n const store = useStoreContext(TRIGGER_NAME);\n const focusContext = useFocusContext(TRIGGER_NAME);\n const value = useStore((state) => state.value);\n const steps = useStore((state) => state.steps);\n const stepState = useStore((state) => state.steps.get(itemValue));\n\n const propsRef = useAsRef({\n onClick: onClickProp,\n onFocus: onFocusProp,\n onKeyDown: onKeyDownProp,\n onMouseDown: onMouseDownProp\n });\n\n const activationMode = context.activationMode;\n const orientation = context.orientation;\n const loop = context.loop;\n\n const stepIndex = Array.from(steps.keys()).indexOf(itemValue);\n\n const stepPosition = stepIndex + 1;\n const stepCount = steps.size;\n\n const triggerId = getId(context.rootId, \"trigger\", itemValue);\n const contentId = getId(context.rootId, \"content\", itemValue);\n const titleId = getId(context.rootId, \"title\", itemValue);\n const descriptionId = getId(context.rootId, \"description\", itemValue);\n\n const isDisabled = disabled || stepState?.disabled || context.disabled;\n const isActive = value === itemValue;\n const isTabStop = focusContext.tabStopId === triggerId;\n const dataState = getDataState(value, itemValue, stepState, steps);\n\n const triggerRef = React.useRef<TriggerElement>(null);\n const composedRef = useComposedRefs(ref, triggerRef);\n const isArrowKeyPressedRef = React.useRef(false);\n const isMouseClickRef = React.useRef(false);\n\n React.useEffect(() => {\n function onKeyDown(event: KeyboardEvent) {\n if (ARROW_KEYS.includes(event.key)) {\n isArrowKeyPressedRef.current = true;\n }\n }\n function onKeyUp() {\n isArrowKeyPressedRef.current = false;\n }\n document.addEventListener(\"keydown\", onKeyDown);\n document.addEventListener(\"keyup\", onKeyUp);\n return () => {\n document.removeEventListener(\"keydown\", onKeyDown);\n document.removeEventListener(\"keyup\", onKeyUp);\n };\n }, []);\n\n useIsomorphicLayoutEffect(() => {\n focusContext.onItemRegister({\n id: triggerId,\n ref: triggerRef,\n value: itemValue,\n active: isTabStop,\n disabled: !!isDisabled\n });\n\n if (!isDisabled) {\n focusContext.onFocusableItemAdd();\n }\n\n return () => {\n focusContext.onItemUnregister(triggerId);\n if (!isDisabled) {\n focusContext.onFocusableItemRemove();\n }\n };\n }, [focusContext, triggerId, itemValue, isTabStop, isDisabled]);\n\n const onClick = React.useCallback(\n async (event: React.MouseEvent<TriggerElement>) => {\n propsRef.current.onClick?.(event);\n if (event.defaultPrevented) return;\n\n if (!isDisabled && !context.nonInteractive) {\n const currentStepIndex = Array.from(steps.keys()).indexOf(value ?? \"\");\n const targetStepIndex = Array.from(steps.keys()).indexOf(itemValue);\n const direction = targetStepIndex > currentStepIndex ? \"next\" : \"prev\";\n\n await store.setStateWithValidation(itemValue, direction);\n }\n },\n [isDisabled, context.nonInteractive, store, itemValue, value, steps, propsRef]\n );\n\n const onFocus = React.useCallback(\n async (event: React.FocusEvent<TriggerElement>) => {\n propsRef.current.onFocus?.(event);\n if (event.defaultPrevented) return;\n\n focusContext.onItemFocus(triggerId);\n\n const isKeyboardFocus = !isMouseClickRef.current;\n\n if (!isActive && !isDisabled && activationMode !== \"manual\" && !context.nonInteractive && isKeyboardFocus) {\n const currentStepIndex = Array.from(steps.keys()).indexOf(value || \"\");\n const targetStepIndex = Array.from(steps.keys()).indexOf(itemValue);\n const direction = targetStepIndex > currentStepIndex ? \"next\" : \"prev\";\n\n await store.setStateWithValidation(itemValue, direction);\n }\n\n isMouseClickRef.current = false;\n },\n [\n focusContext,\n triggerId,\n activationMode,\n isActive,\n isDisabled,\n context.nonInteractive,\n store,\n itemValue,\n value,\n steps,\n propsRef\n ]\n );\n\n const onKeyDown = React.useCallback(\n async (event: React.KeyboardEvent<TriggerElement>) => {\n propsRef.current.onKeyDown?.(event);\n if (event.defaultPrevented) return;\n\n if (event.key === \"Enter\" && context.nonInteractive) {\n event.preventDefault();\n return;\n }\n\n if ((event.key === \"Enter\" || event.key === \" \") && activationMode === \"manual\" && !context.nonInteractive) {\n event.preventDefault();\n if (!isDisabled && triggerRef.current) {\n triggerRef.current.click();\n }\n return;\n }\n\n if (event.key === \"Tab\" && event.shiftKey) {\n focusContext.onItemShiftTab();\n return;\n }\n\n if (event.target !== event.currentTarget) return;\n\n const focusIntent = getFocusIntent(event, context.dir, orientation);\n\n if (focusIntent !== undefined) {\n if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) return;\n event.preventDefault();\n\n const items = focusContext.getItems().filter((item) => !item.disabled);\n let candidateRefs = items.map((item) => item.ref);\n\n if (focusIntent === \"last\") {\n candidateRefs.reverse();\n } else if (focusIntent === \"prev\" || focusIntent === \"next\") {\n if (focusIntent === \"prev\") candidateRefs.reverse();\n const currentIndex = candidateRefs.findIndex((ref) => ref.current === event.currentTarget);\n candidateRefs = loop ? wrapArray(candidateRefs, currentIndex + 1) : candidateRefs.slice(currentIndex + 1);\n }\n\n if (store.hasValidation() && candidateRefs.length > 0) {\n const nextRef = candidateRefs[0];\n const nextElement = nextRef?.current;\n const nextItem = items.find((item) => item.ref.current === nextElement);\n\n if (nextItem && nextItem.value !== itemValue) {\n const currentStepIndex = Array.from(steps.keys()).indexOf(value || \"\");\n const targetStepIndex = Array.from(steps.keys()).indexOf(nextItem.value);\n const direction: NavigationDirection = targetStepIndex > currentStepIndex ? \"next\" : \"prev\";\n\n if (direction === \"next\") {\n const isValid = await store.setStateWithValidation(nextItem.value, direction);\n if (!isValid) return;\n } else {\n store.setState(\"value\", nextItem.value);\n }\n\n queueMicrotask(() => nextElement?.focus());\n return;\n }\n }\n\n queueMicrotask(() => focusFirst(candidateRefs));\n }\n },\n [\n focusContext,\n context.nonInteractive,\n context.dir,\n activationMode,\n orientation,\n loop,\n isDisabled,\n store,\n propsRef,\n itemValue,\n value,\n steps\n ]\n );\n\n const onMouseDown = React.useCallback(\n (event: React.MouseEvent<TriggerElement>) => {\n propsRef.current.onMouseDown?.(event);\n if (event.defaultPrevented) return;\n\n isMouseClickRef.current = true;\n\n if (isDisabled) {\n event.preventDefault();\n } else {\n focusContext.onItemFocus(triggerId);\n }\n },\n [focusContext, triggerId, isDisabled, propsRef]\n );\n\n const TriggerPrimitive = asChild ? Slot : \"button\";\n\n return (\n <TriggerPrimitive\n id={triggerId}\n role=\"tab\"\n type=\"button\"\n aria-controls={contentId}\n aria-current={isActive ? \"step\" : undefined}\n aria-describedby={`${titleId} ${descriptionId}`}\n aria-posinset={stepPosition}\n aria-selected={isActive}\n aria-setsize={stepCount}\n data-disabled={isDisabled ? \"\" : undefined}\n data-state={dataState}\n data-slot=\"stepper-trigger\"\n disabled={isDisabled}\n tabIndex={isTabStop ? 0 : -1}\n {...triggerProps}\n ref={composedRef}\n className={cn(\n /*\n * ⚠ Khác thượng nguồn:\n * - Vòng focus theo khuôn `Checkbox`/`RadioGroup` của gói, thay cho `ring-[3px]` của bản gốc.\n * - Lỗi (`aria-invalid`) viền bằng `--destructive-ink` — VAI TRÒ viền trên nền trang (hợp\n * đồng §1 của docs/hop-dong-mau.md); bản gốc dùng `border-destructive` là token TÔ NỀN.\n */\n \"inline-flex items-center justify-center gap-3 rounded-md text-left transition-all outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive-ink aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n \"not-has-data-[slot=description]:rounded-full not-has-data-[slot=title]:rounded-full\",\n className\n )}\n onClick={onClick}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onMouseDown={onMouseDown}\n />\n );\n}\n\ninterface StepperIndicatorProps extends Omit<DivProps, \"children\"> {\n children?: React.ReactNode | ((dataState: DataState) => React.ReactNode);\n}\n\nfunction StepperIndicator(props: StepperIndicatorProps) {\n const { className, children, asChild, ref, ...indicatorProps } = props;\n\n const context = useStepperContext(INDICATOR_NAME);\n const itemContext = useStepperItemContext(INDICATOR_NAME);\n\n const value = useStore((state) => state.value);\n const itemValue = itemContext.value;\n const stepState = useStore((state) => state.steps.get(itemValue));\n const steps = useStore((state) => state.steps);\n\n const stepPosition = Array.from(steps.keys()).indexOf(itemValue) + 1;\n\n const dataState = getDataState(value, itemValue, stepState, steps);\n\n const IndicatorPrimitive = asChild ? Slot : \"div\";\n\n return (\n <IndicatorPrimitive\n data-state={dataState}\n data-slot=\"stepper-indicator\"\n dir={context.dir}\n {...indicatorProps}\n ref={ref}\n className={cn(\n /*\n * ⚠ Khác thượng nguồn — màu đi qua token VAI TRÒ (docs/hop-dong-mau.md §1, §3):\n * - Lúc nghỉ: viền `--control-edge` thay `border-muted`. Ô chỉ báo là HÌNH của chính nút\n * bước, nên viền của nó là viền control; `--muted` là token bề mặt, đem làm viền thì bảng\n * tương phản cao không kéo lên được. Ở bảng mặc định `--control-edge` nhạt đúng như bản gốc.\n * - Đang làm/đã xong: nền ĐẶC `bg-primary` + chữ/tick `text-primary-foreground` (giữ nguyên),\n * nhưng viền là `--primary-ink` chứ không `border-primary`: nền vàng đặc chỉ ~1,86:1 với\n * nền trang, nên chính VIỀN mới là dấu hiệu trạng thái đạt 3:1 (6,51:1 ở bảng tương phản cao).\n * - Chữ lúc nghỉ viết `data-[state=inactive]:text-muted-foreground` thay cho lớp trần: CSS y\n * hệt (ba trạng thái loại trừ nhau), nhưng cổng `lint:a11y` không ghép nhầm chữ xám với nền\n * vàng của trạng thái đang làm — cặp đó không bao giờ cùng xuất hiện.\n */\n \"flex size-7 shrink-0 items-center justify-center rounded-full border-2 border-control-edge bg-background text-sm font-medium data-[state=inactive]:text-muted-foreground transition-colors data-[state=active]:border-primary-ink data-[state=active]:bg-primary data-[state=active]:text-primary-foreground data-[state=completed]:border-primary-ink data-[state=completed]:bg-primary data-[state=completed]:text-primary-foreground\",\n className\n )}\n >\n {typeof children === \"function\" ? (\n children(dataState)\n ) : children ? (\n children\n ) : dataState === \"completed\" ? (\n /*\n * ⚠ Khác thượng nguồn: bản gốc chỉ vẽ dấu tick. Trigger chỉ chứa ô chỉ báo (demo mặc định\n * của Dice UI) thì bước đã xong thành một nút KHÔNG TÊN — con số vốn là tên nút đã bị dấu\n * tick thay mất. Thêm chữ `sr-only` giữ lại con số và nói luôn trạng thái.\n */\n <>\n <Check aria-hidden=\"true\" className=\"size-4\" />\n <span className=\"sr-only\">{context.labels.completedStep(stepPosition)}</span>\n </>\n ) : (\n stepPosition\n )}\n </IndicatorPrimitive>\n );\n}\n\ninterface StepperSeparatorProps extends DivProps {\n forceMount?: boolean;\n}\n\nfunction StepperSeparator(props: StepperSeparatorProps) {\n const { className, asChild, forceMount = false, ref, ...separatorProps } = props;\n\n const context = useStepperContext(SEPARATOR_NAME);\n const itemContext = useStepperItemContext(SEPARATOR_NAME);\n const value = useStore((state) => state.value);\n const steps = useStore((state) => state.steps);\n\n const orientation = context.orientation;\n\n const stepIndex = Array.from(steps.keys()).indexOf(itemContext.value);\n\n const isLastStep = stepIndex === steps.size - 1;\n\n if (isLastStep && !forceMount) return null;\n\n const dataState = getDataState(value, itemContext.value, itemContext.stepState, steps, \"separator\");\n\n const SeparatorPrimitive = asChild ? Slot : \"div\";\n\n /*\n * ⚠ Khác thượng nguồn: bỏ `role=\"separator\"` + `aria-orientation`. Thẻ đã `aria-hidden` nên hai\n * thuộc tính đó không bao giờ tới trình đọc màn hình — cùng khuôn `TimelineConnector` của chính\n * Dice UI. Để lại thì cổng `lint:a11y` đọc `role=` là dấu hiệu CONTROL (thanh chia `Resizable`\n * focus được) và bắt sợi tóc trang trí ở đoạn CHƯA tới phải đạt 3:1 như một control.\n */\n return (\n <SeparatorPrimitive\n aria-hidden=\"true\"\n data-orientation={orientation}\n data-state={dataState}\n data-slot=\"stepper-separator\"\n dir={context.dir}\n {...separatorProps}\n ref={ref}\n className={cn(\n /*\n * ⚠ Khác thượng nguồn: đoạn nối ĐÃ XONG mang nghĩa tiến độ (phi văn bản, 3:1) → `--primary-ink`\n * thay `bg-primary` (token tô nền, ~1,86:1 với nền trang). Đoạn CHƯA tới giữ `bg-border`:\n * sợi tóc 1px, thuần trang trí.\n */\n \"bg-border transition-colors data-[state=active]:bg-primary-ink data-[state=completed]:bg-primary-ink\",\n orientation === \"horizontal\" ? \"h-px flex-1\" : \"h-10 w-px\",\n className\n )}\n />\n );\n}\n\ninterface StepperTitleProps extends React.ComponentProps<\"span\"> {\n asChild?: boolean;\n}\n\nfunction StepperTitle(props: StepperTitleProps) {\n const { className, asChild, ref, ...titleProps } = props;\n\n const context = useStepperContext(TITLE_NAME);\n const itemContext = useStepperItemContext(TITLE_NAME);\n\n const titleId = getId(context.rootId, \"title\", itemContext.value);\n\n const TitlePrimitive = asChild ? Slot : \"span\";\n\n return (\n <TitlePrimitive\n id={titleId}\n data-slot=\"title\"\n dir={context.dir}\n {...titleProps}\n ref={ref}\n className={cn(\"text-sm font-medium\", className)}\n />\n );\n}\n\ninterface StepperDescriptionProps extends React.ComponentProps<\"span\"> {\n asChild?: boolean;\n}\n\nfunction StepperDescription(props: StepperDescriptionProps) {\n const { className, asChild, ref, ...descriptionProps } = props;\n\n const context = useStepperContext(DESCRIPTION_NAME);\n const itemContext = useStepperItemContext(DESCRIPTION_NAME);\n\n const descriptionId = getId(context.rootId, \"description\", itemContext.value);\n\n const DescriptionPrimitive = asChild ? Slot : \"span\";\n\n return (\n <DescriptionPrimitive\n id={descriptionId}\n data-slot=\"description\"\n dir={context.dir}\n {...descriptionProps}\n ref={ref}\n className={cn(\"text-xs text-muted-foreground\", className)}\n />\n );\n}\n\ninterface StepperContentProps extends DivProps {\n value: string;\n forceMount?: boolean;\n}\n\nfunction StepperContent(props: StepperContentProps) {\n const { value: valueProp, asChild, forceMount = false, ref, className, ...contentProps } = props;\n\n const context = useStepperContext(CONTENT_NAME);\n const value = useStore((state) => state.value);\n\n const contentId = getId(context.rootId, \"content\", valueProp);\n const triggerId = getId(context.rootId, \"trigger\", valueProp);\n\n if (valueProp !== value && !forceMount) return null;\n\n const ContentPrimitive = asChild ? Slot : \"div\";\n\n return (\n <ContentPrimitive\n id={contentId}\n role=\"tabpanel\"\n aria-labelledby={triggerId}\n data-slot=\"stepper-content\"\n dir={context.dir}\n {...contentProps}\n ref={ref}\n className={cn(\"flex-1 outline-none\", className)}\n />\n );\n}\n\nfunction StepperPrev(props: ButtonProps) {\n const { asChild, onClick: onClickProp, disabled, children, ...prevProps } = props;\n\n const context = useStepperContext(PREV_NAME);\n const store = useStoreContext(PREV_NAME);\n const value = useStore((state) => state.value);\n const steps = useStore((state) => state.steps);\n\n const propsRef = useAsRef({\n onClick: onClickProp\n });\n\n const stepKeys = Array.from(steps.keys());\n const currentIndex = value ? stepKeys.indexOf(value) : -1;\n const isDisabled = disabled || currentIndex <= 0;\n\n const onClick = React.useCallback(\n async (event: React.MouseEvent<HTMLButtonElement>) => {\n propsRef.current.onClick?.(event);\n if (event.defaultPrevented || isDisabled) return;\n\n const prevIndex = Math.max(currentIndex - 1, 0);\n const prevStepValue = stepKeys[prevIndex];\n\n if (prevStepValue) {\n store.setState(\"value\", prevStepValue);\n }\n },\n [propsRef, isDisabled, currentIndex, stepKeys, store]\n );\n\n const PrevPrimitive = asChild ? Slot : \"button\";\n\n return (\n <PrevPrimitive type=\"button\" data-slot=\"stepper-prev\" disabled={isDisabled} {...prevProps} onClick={onClick}>\n {/* ⚠ Khác thượng nguồn: thiếu `children` thì bản gốc ra nút rỗng, không tên. */}\n {asChild ? children : (children ?? context.labels.prev)}\n </PrevPrimitive>\n );\n}\n\nfunction StepperNext(props: ButtonProps) {\n const { asChild, onClick: onClickProp, disabled, children, ...nextProps } = props;\n\n const context = useStepperContext(NEXT_NAME);\n const store = useStoreContext(NEXT_NAME);\n const value = useStore((state) => state.value);\n const steps = useStore((state) => state.steps);\n\n const propsRef = useAsRef({\n onClick: onClickProp\n });\n\n const stepKeys = Array.from(steps.keys());\n const currentIndex = value ? stepKeys.indexOf(value) : -1;\n const isDisabled = disabled || currentIndex >= stepKeys.length - 1;\n\n const onClick = React.useCallback(\n async (event: React.MouseEvent<HTMLButtonElement>) => {\n propsRef.current.onClick?.(event);\n if (event.defaultPrevented || isDisabled) return;\n\n const nextIndex = Math.min(currentIndex + 1, stepKeys.length - 1);\n const nextStepValue = stepKeys[nextIndex];\n\n if (nextStepValue) {\n await store.setStateWithValidation(nextStepValue, \"next\");\n }\n },\n [propsRef, isDisabled, currentIndex, stepKeys, store]\n );\n\n const NextPrimitive = asChild ? Slot : \"button\";\n\n return (\n <NextPrimitive type=\"button\" data-slot=\"stepper-next\" disabled={isDisabled} {...nextProps} onClick={onClick}>\n {/* ⚠ Khác thượng nguồn: thiếu `children` thì bản gốc ra nút rỗng, không tên. */}\n {asChild ? children : (children ?? context.labels.next)}\n </NextPrimitive>\n );\n}\n\nexport {\n Stepper,\n StepperContent,\n type StepperContentProps,\n StepperDescription,\n type StepperDescriptionProps,\n StepperIndicator,\n type StepperIndicatorProps,\n StepperItem,\n type StepperItemProps,\n StepperList,\n StepperNext,\n StepperPrev,\n type StepperProps,\n StepperSeparator,\n type StepperSeparatorProps,\n StepperTitle,\n type StepperTitleProps,\n StepperTrigger,\n useStore as useStepper\n};\n"],"mappings":"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","names":["value","disabled","tabStopId","onKeyDown","ref"]}
@@ -43,12 +43,32 @@ interface TimePickerProps extends DivProps {
43
43
  /** Bấm vào khoảng trống của nhóm ô: `"focus"` (mặc định) focus ô đầu, `"open"` mở bảng chọn. */
44
44
  inputGroupClickAction?: "focus" | "open";
45
45
  /**
46
- * ⚠ Thượng nguồn nhận `min`/`max` và đưa vào context nhưng CHƯA áp dụng ở đâu cả — không chặn
47
- * gõ, không làm mờ mục trong cột. Giữ để khớp API gốc; muốn ràng buộc khung giờ (ca làm, giờ
48
- * hành chính) thì app phải tự kiểm ở `onValueChange` / tầng validate của form.
46
+ * Khung giờ cho phép (từ `3.1.0`), cùng định dạng 24 giờ với `value`: `"HH:mm"` hoặc `"HH:mm:ss"`.
47
+ * Chỉ đặt một đầu thì đầu kia là 00:00 / 23:59:59. `min` > `max` là khung VẮT QUA NỬA ĐÊM (ca đêm
48
+ * `min="22:00" max="06:00"`), như `<input type="time">`. Không `showSeconds` thì so tới PHÚT: cận
49
+ * có giây được làm tròn vào trong (`min` lên, `max` xuống). Không đặt cả hai thì không có gì đổi.
50
+ *
51
+ * - **Mục bị khoá** trong bảng chọn (`aria-disabled`, mờ, không bấm được, phím mũi tên bỏ qua) khi
52
+ * KHÔNG thời điểm nào bắt đầu bằng nó nằm trong khung, xét các ô LỚN hơn đang chọn: giờ bị khoá
53
+ * khi cả 60 phút của nó đều ngoài khung, phút khi cả phút đó ngoài khung (ở giờ đang chọn), giây
54
+ * khi đúng thời điểm đó ngoài khung, AM/PM khi cả nửa ngày ngoài khung.
55
+ * - **Kẹp**: chọn một mục hay gõ xong một ô mà ra thời điểm ngoài khung thì giá trị ghi là thời điểm
56
+ * được phép GẦN NHẤT, giữ nguyên thứ vừa chọn/gõ nếu nó còn chỗ trong khung (`max="17:00"`, đang
57
+ * 09:45, chọn giờ 17 → `"17:00"`), không thì là cận gần nhất (gõ giờ 20 → `"17:00"`). Ô gõ được kẹp
58
+ * đúng lúc nó được GHI như trước nay: gõ đủ hai chữ số (hay một chữ số không thể mở đầu số hai
59
+ * chữ số) — lúc focus nhảy sang ô kế; Tab, Enter, rời ô; phím mũi tên; phím buổi. Chữ số đầu còn
60
+ * chờ chữ số thứ hai thì chưa kẹp.
61
+ * - Ô trống được lấp bằng giờ hiện tại ĐÃ KẸP vào khung, và cột mở ra ở giờ đó khi chưa có giá trị.
62
+ *
63
+ * Nhờ vậy `onValueChange` không bao giờ báo một thời điểm ngoài khung do NGƯỜI DÙNG tạo ra.
64
+ * KHÔNG kẹp: giá trị APP đặt (`value` / `defaultValue` — hiện nguyên, mục của nó trong cột hiện bị
65
+ * khoá; kiểm nó ở tầng validate của form), `min`/`max` đổi khi đã có giá trị, xoá một ô bằng
66
+ * Backspace/Delete, `TimePickerClear`.
67
+ *
68
+ * ⚠ Khác thượng nguồn (3.1.0): thượng nguồn chỉ lưu hai prop này vào context, không áp dụng ở đâu.
49
69
  */
50
70
  min?: string;
51
- /** Xem `min`. */
71
+ /** Cận trên của khung giờ — luật đầy đủ ở `min`. */
52
72
  max?: string;
53
73
  hourStep?: number;
54
74
  minuteStep?: number;