@comitor/ui 1.11.0 → 2.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 (176) hide show
  1. package/LICENSE +35 -0
  2. package/README.md +23 -7
  3. package/dist/components/ui/action-bar-constants.d.ts +31 -0
  4. package/dist/components/ui/action-bar-constants.js +9 -0
  5. package/dist/components/ui/action-bar-constants.js.map +1 -0
  6. package/dist/components/ui/action-bar.d.ts +67 -0
  7. package/dist/components/ui/action-bar.js +522 -0
  8. package/dist/components/ui/action-bar.js.map +1 -0
  9. package/dist/components/ui/badge-overflow.d.ts +30 -0
  10. package/dist/components/ui/badge-overflow.js +179 -0
  11. package/dist/components/ui/badge-overflow.js.map +1 -0
  12. package/dist/components/ui/banner.d.ts +79 -0
  13. package/dist/components/ui/banner.js +518 -0
  14. package/dist/components/ui/banner.js.map +1 -0
  15. package/dist/components/ui/circular-progress.d.ts +50 -0
  16. package/dist/components/ui/circular-progress.js +266 -0
  17. package/dist/components/ui/circular-progress.js.map +1 -0
  18. package/dist/components/ui/cropper-constants.d.ts +34 -0
  19. package/dist/components/ui/cropper-constants.js +10 -0
  20. package/dist/components/ui/cropper-constants.js.map +1 -0
  21. package/dist/components/ui/cropper.d.ts +106 -0
  22. package/dist/components/ui/cropper.js +1269 -0
  23. package/dist/components/ui/cropper.js.map +1 -0
  24. package/dist/components/ui/drawer.d.ts +1 -1
  25. package/dist/components/ui/drawer.js +2 -2
  26. package/dist/components/ui/drawer.js.map +1 -1
  27. package/dist/components/ui/kanban-constants.d.ts +61 -0
  28. package/dist/components/ui/kanban-constants.js +21 -0
  29. package/dist/components/ui/kanban-constants.js.map +1 -0
  30. package/dist/components/ui/kanban.d.ts +72 -0
  31. package/dist/components/ui/kanban.js +787 -0
  32. package/dist/components/ui/kanban.js.map +1 -0
  33. package/dist/components/ui/key-value-constants.d.ts +33 -0
  34. package/dist/components/ui/key-value-constants.js +11 -0
  35. package/dist/components/ui/key-value-constants.js.map +1 -0
  36. package/dist/components/ui/key-value.d.ts +96 -0
  37. package/dist/components/ui/key-value.js +641 -0
  38. package/dist/components/ui/key-value.js.map +1 -0
  39. package/dist/components/ui/mask-input-constants.d.ts +99 -0
  40. package/dist/components/ui/mask-input-constants.js +601 -0
  41. package/dist/components/ui/mask-input-constants.js.map +1 -0
  42. package/dist/components/ui/mask-input.d.ts +36 -0
  43. package/dist/components/ui/mask-input.js +558 -0
  44. package/dist/components/ui/mask-input.js.map +1 -0
  45. package/dist/components/ui/mention.d.ts +31 -0
  46. package/dist/components/ui/mention.js +128 -0
  47. package/dist/components/ui/mention.js.map +1 -0
  48. package/dist/components/ui/phone-input-constants.d.ts +54 -0
  49. package/dist/components/ui/phone-input-constants.js +9 -0
  50. package/dist/components/ui/phone-input-constants.js.map +1 -0
  51. package/dist/components/ui/phone-input.d.ts +85 -0
  52. package/dist/components/ui/phone-input.js +743 -0
  53. package/dist/components/ui/phone-input.js.map +1 -0
  54. package/dist/components/ui/rating.d.ts +56 -0
  55. package/dist/components/ui/rating.js +646 -0
  56. package/dist/components/ui/rating.js.map +1 -0
  57. package/dist/components/ui/responsive-dialog.d.ts +35 -0
  58. package/dist/components/ui/responsive-dialog.js +193 -0
  59. package/dist/components/ui/responsive-dialog.js.map +1 -0
  60. package/dist/components/ui/scroll-spy.d.ts +42 -0
  61. package/dist/components/ui/scroll-spy.js +334 -0
  62. package/dist/components/ui/scroll-spy.js.map +1 -0
  63. package/dist/components/ui/stepper-constants.d.ts +29 -0
  64. package/dist/components/ui/stepper-constants.js +9 -0
  65. package/dist/components/ui/stepper-constants.js.map +1 -0
  66. package/dist/components/ui/stepper.d.ts +80 -0
  67. package/dist/components/ui/stepper.js +902 -0
  68. package/dist/components/ui/stepper.js.map +1 -0
  69. package/dist/components/ui/tags-input.d.ts +41 -0
  70. package/dist/components/ui/tags-input.js +127 -0
  71. package/dist/components/ui/tags-input.js.map +1 -0
  72. package/dist/components/ui/time-picker-constants.d.ts +48 -0
  73. package/dist/components/ui/time-picker-constants.js +14 -0
  74. package/dist/components/ui/time-picker-constants.js.map +1 -0
  75. package/dist/components/ui/time-picker.d.ts +115 -0
  76. package/dist/components/ui/time-picker.js +1620 -0
  77. package/dist/components/ui/time-picker.js.map +1 -0
  78. package/dist/components/ui/timeline.d.ts +32 -0
  79. package/dist/components/ui/timeline.js +559 -0
  80. package/dist/components/ui/timeline.js.map +1 -0
  81. package/dist/components/ui/tour-constants.d.ts +39 -0
  82. package/dist/components/ui/tour-constants.js +12 -0
  83. package/dist/components/ui/tour-constants.js.map +1 -0
  84. package/dist/components/ui/tour.d.ts +124 -0
  85. package/dist/components/ui/tour.js +1207 -0
  86. package/dist/components/ui/tour.js.map +1 -0
  87. package/dist/data-grid/data-grid-cell-variants.js +10 -6
  88. package/dist/data-grid/data-grid-cell-variants.js.map +1 -1
  89. package/dist/data-grid/data-grid-cell-wrapper.js +1 -1
  90. package/dist/data-grid/data-grid-cell-wrapper.js.map +1 -1
  91. package/dist/data-grid/data-grid-column-header.js +4 -2
  92. package/dist/data-grid/data-grid-column-header.js.map +1 -1
  93. package/dist/data-grid/data-grid-context-menu.js +5 -4
  94. package/dist/data-grid/data-grid-context-menu.js.map +1 -1
  95. package/dist/data-grid/data-grid-filter-menu.d.ts +12 -1
  96. package/dist/data-grid/data-grid-filter-menu.js +28 -17
  97. package/dist/data-grid/data-grid-filter-menu.js.map +1 -1
  98. package/dist/data-grid/data-grid-keyboard-shortcuts.d.ts +12 -1
  99. package/dist/data-grid/data-grid-keyboard-shortcuts.js +7 -5
  100. package/dist/data-grid/data-grid-keyboard-shortcuts.js.map +1 -1
  101. package/dist/data-grid/data-grid-locale.d.ts +24 -0
  102. package/dist/data-grid/data-grid-locale.js +25 -0
  103. package/dist/data-grid/data-grid-locale.js.map +1 -0
  104. package/dist/data-grid/data-grid-paste-dialog.js +3 -2
  105. package/dist/data-grid/data-grid-paste-dialog.js.map +1 -1
  106. package/dist/data-grid/data-grid-row-height-menu.d.ts +11 -1
  107. package/dist/data-grid/data-grid-row-height-menu.js +25 -28
  108. package/dist/data-grid/data-grid-row-height-menu.js.map +1 -1
  109. package/dist/data-grid/data-grid-row.js +1 -1
  110. package/dist/data-grid/data-grid-row.js.map +1 -1
  111. package/dist/data-grid/data-grid-search.js +6 -5
  112. package/dist/data-grid/data-grid-search.js.map +1 -1
  113. package/dist/data-grid/data-grid-select-column.js +3 -1
  114. package/dist/data-grid/data-grid-select-column.js.map +1 -1
  115. package/dist/data-grid/data-grid-sort-menu.d.ts +12 -1
  116. package/dist/data-grid/data-grid-sort-menu.js +25 -13
  117. package/dist/data-grid/data-grid-sort-menu.js.map +1 -1
  118. package/dist/data-grid/data-grid-view-menu.d.ts +12 -1
  119. package/dist/data-grid/data-grid-view-menu.js +12 -4
  120. package/dist/data-grid/data-grid-view-menu.js.map +1 -1
  121. package/dist/data-grid/data-grid.d.ts +14 -2
  122. package/dist/data-grid/data-grid.js +7 -4
  123. package/dist/data-grid/data-grid.js.map +1 -1
  124. package/dist/data-grid/filters.d.ts +17 -21
  125. package/dist/data-grid/filters.js +73 -52
  126. package/dist/data-grid/filters.js.map +1 -1
  127. package/dist/data-grid/index.d.ts +4 -1
  128. package/dist/data-grid/index.js +20 -2
  129. package/dist/data-grid/index.js.map +1 -1
  130. package/dist/data-grid/messages-en.d.ts +294 -0
  131. package/dist/data-grid/messages-en.js +279 -0
  132. package/dist/data-grid/messages-en.js.map +1 -0
  133. package/dist/data-grid/messages-vi.d.ts +12 -0
  134. package/dist/data-grid/messages-vi.js +279 -0
  135. package/dist/data-grid/messages-vi.js.map +1 -0
  136. package/dist/data-grid/messages.d.ts +549 -262
  137. package/dist/data-grid/messages.js +16 -275
  138. package/dist/data-grid/messages.js.map +1 -1
  139. package/dist/data-grid/sortable.js +1 -1
  140. package/dist/data-grid/sortable.js.map +1 -1
  141. package/dist/data-grid/use-data-grid-undo-redo.d.ts +13 -1
  142. package/dist/data-grid/use-data-grid-undo-redo.js +13 -10
  143. package/dist/data-grid/use-data-grid-undo-redo.js.map +1 -1
  144. package/dist/data-grid/use-data-grid.d.ts +281 -1
  145. package/dist/data-grid/use-data-grid.js +24 -19
  146. package/dist/data-grid/use-data-grid.js.map +1 -1
  147. package/dist/data-grid/utils.d.ts +9 -1
  148. package/dist/data-grid/utils.js +3 -2
  149. package/dist/data-grid/utils.js.map +1 -1
  150. package/dist/index.d.ts +31 -0
  151. package/dist/index.js +42 -0
  152. package/dist/index.js.map +1 -1
  153. package/dist/lib/compose-refs.js.map +1 -0
  154. package/dist/lib/use-as-ref.js.map +1 -0
  155. package/dist/lib/use-is-mobile.d.ts +10 -0
  156. package/dist/lib/use-is-mobile.js +21 -0
  157. package/dist/lib/use-is-mobile.js.map +1 -0
  158. package/dist/lib/use-isomorphic-layout-effect.js.map +1 -0
  159. package/dist/lib/use-lazy-ref.js.map +1 -0
  160. package/dist/lib/visually-hidden-input.d.ts +12 -0
  161. package/dist/lib/visually-hidden-input.js +105 -0
  162. package/dist/lib/visually-hidden-input.js.map +1 -0
  163. package/package.json +5 -1
  164. package/styles.css +19 -0
  165. package/dist/data-grid/compose-refs.js.map +0 -1
  166. package/dist/data-grid/use-as-ref.js.map +0 -1
  167. package/dist/data-grid/use-isomorphic-layout-effect.js.map +0 -1
  168. package/dist/data-grid/use-lazy-ref.js.map +0 -1
  169. /package/dist/{data-grid → lib}/compose-refs.d.ts +0 -0
  170. /package/dist/{data-grid → lib}/compose-refs.js +0 -0
  171. /package/dist/{data-grid → lib}/use-as-ref.d.ts +0 -0
  172. /package/dist/{data-grid → lib}/use-as-ref.js +0 -0
  173. /package/dist/{data-grid → lib}/use-isomorphic-layout-effect.d.ts +0 -0
  174. /package/dist/{data-grid → lib}/use-isomorphic-layout-effect.js +0 -0
  175. /package/dist/{data-grid → lib}/use-lazy-ref.d.ts +0 -0
  176. /package/dist/{data-grid → lib}/use-lazy-ref.js +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/ui/rating.tsx"],"sourcesContent":["\"use client\";\n\n/*\n * Port từ Dice UI (https://diceui.com/docs/components/rating) — 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 { Star } from \"lucide-react\";\nimport * as React from \"react\";\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 { VisuallyHiddenInput } from \"../../lib/visually-hidden-input.js\";\n\ntype Direction = \"ltr\" | \"rtl\";\ntype Orientation = \"horizontal\" | \"vertical\";\ntype ActivationMode = \"automatic\" | \"manual\";\ntype Size = \"default\" | \"sm\" | \"lg\";\ntype Step = 0.5 | 1;\ntype DataState = \"full\" | \"partial\" | \"empty\";\ntype FocusIntent = \"first\" | \"last\" | \"prev\" | \"next\";\n\ntype RootElement = React.ComponentRef<typeof Rating>;\ntype ItemElement = React.ComponentRef<typeof RatingItem>;\n\nconst ROOT_NAME = \"Rating\";\nconst ITEM_NAME = \"RatingItem\";\n\nconst ENTRY_FOCUS = \"ratingFocusGroup.onEntryFocus\";\nconst EVENT_OPTIONS = { bubbles: false, cancelable: true };\n\nfunction getItemId(id: string, value: number) {\n return `${id}-item-${value}`;\n}\n\nfunction getPartialFillGradientId(id: string, step: Step) {\n return `partial-fill-gradient-${id}-${step}`;\n}\n\nconst MAP_KEY_TO_FOCUS_INTENT: Record<string, FocusIntent> = {\n ArrowLeft: \"prev\",\n ArrowUp: \"prev\",\n ArrowRight: \"next\",\n ArrowDown: \"next\",\n Home: \"first\",\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<ItemElement>, 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<ItemElement | 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\ninterface StoreState {\n value: number;\n hoveredValue: number | null;\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 notify: () => 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, ogStore?: Store | null): T {\n const contextStore = React.useContext(StoreContext);\n\n const store = ogStore ?? contextStore;\n\n if (!store) {\n throw new Error(`\\`useRating\\` phải được gọi bên trong \\`${ROOT_NAME}\\``);\n }\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<ItemElement | null>;\n value: number;\n disabled: boolean;\n}\n\ninterface RatingContextValue {\n rootId: string;\n dir: Direction;\n orientation: Orientation;\n activationMode: ActivationMode;\n size: Size;\n max: number;\n step: Step;\n clearable: boolean;\n disabled: boolean;\n readOnly: boolean;\n itemLabel: (value: number, max: number) => string;\n getAutoIndex: (instanceId: string) => number;\n}\n\nconst RatingContext = React.createContext<RatingContextValue | null>(null);\n\nfunction useRatingContext(consumerName: string) {\n const context = React.useContext(RatingContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ROOT_NAME}\\``);\n }\n return context;\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 \\`FocusProvider\\``);\n }\n return context;\n}\n\ninterface RatingProps extends React.ComponentProps<\"div\"> {\n value?: number;\n defaultValue?: number;\n onValueChange?: (value: number) => void;\n onHover?: (value: number | null) => void;\n max?: number;\n activationMode?: ActivationMode;\n dir?: Direction;\n orientation?: Orientation;\n size?: Size;\n asChild?: boolean;\n step?: Step;\n clearable?: boolean;\n disabled?: boolean;\n readOnly?: boolean;\n required?: boolean;\n name?: string;\n /**\n * Tên của TỪNG ngôi sao cho trình đọc màn hình — mặc định `(value) => value + \" sao\"`.\n *\n * ⚠ Thêm so với thượng nguồn. Ở bản gốc mỗi `RatingItem` là một `role=\"radio\"` chỉ chứa một\n * `<svg>`, tức một nút KHÔNG TÊN: trình đọc màn hình đọc \"nút radio, 3 trên 5\" mà không nói 3\n * CÁI GÌ. Là HÀM chứ không phải chuỗi mẫu vì có số chèn vào giữa câu (README §5).\n *\n * Nhóm vẫn cần tên riêng: truyền `aria-label` (vd \"Mức hài lòng\") cho chính `Rating`.\n */\n itemLabel?: (value: number, max: number) => string;\n}\n\nconst defaultItemLabel = (value: number) => `${value} sao`;\n\nfunction Rating(props: RatingProps) {\n const {\n value: valueProp,\n defaultValue = 0,\n onValueChange,\n onHover,\n onFocus: onFocusProp,\n onMouseDown: onMouseDownProp,\n dir: dirProp,\n orientation = \"horizontal\",\n activationMode = \"automatic\",\n size = \"default\",\n max = 5,\n step = 1,\n clearable = false,\n asChild,\n disabled = false,\n readOnly = false,\n required = false,\n itemLabel = defaultItemLabel,\n className,\n children,\n id,\n name,\n ref,\n ...rootProps\n } = props;\n\n const dir = useDirection(dirProp);\n const instanceId = React.useId();\n const rootId = id ?? instanceId;\n\n const listenersRef = useLazyRef(() => new Set<() => void>());\n const stateRef = useLazyRef<StoreState>(() => ({\n value: valueProp ?? defaultValue,\n hoveredValue: null\n }));\n\n const propsRef = useAsRef({\n onValueChange,\n onHover,\n onFocus: onFocusProp,\n onMouseDown: onMouseDownProp,\n step\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 === \"number\") {\n stateRef.current.value = value;\n propsRef.current.onValueChange?.(value);\n } else if (key === \"hoveredValue\") {\n stateRef.current.hoveredValue = value as number | null;\n propsRef.current.onHover?.(value as number | null);\n } else {\n stateRef.current[key] = value;\n }\n\n store.notify();\n },\n notify: () => {\n for (const cb of listenersRef.current) {\n cb();\n }\n }\n };\n }, [listenersRef, stateRef, propsRef]);\n\n useIsomorphicLayoutEffect(() => {\n if (valueProp !== undefined) {\n store.setState(\"value\", valueProp);\n }\n }, [valueProp]);\n\n const value = useStore((state) => state.value, store);\n\n const [formTrigger, setFormTrigger] = React.useState<RootElement | null>(null);\n const composedRef = useComposedRefs(ref, (node) => setFormTrigger(node));\n const isFormControl = formTrigger ? !!formTrigger.closest(\"form\") : true;\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\n const autoIndexMapRef = React.useRef(new Map<string, number>());\n const nextAutoIndexRef = React.useRef(0);\n\n const getAutoIndex = React.useCallback((instanceId: string) => {\n const existingIndex = autoIndexMapRef.current.get(instanceId);\n if (existingIndex !== undefined) {\n return existingIndex;\n }\n\n const newIndex = nextAutoIndexRef.current++;\n autoIndexMapRef.current.set(instanceId, newIndex);\n return newIndex;\n }, []);\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<HTMLDivElement>) => {\n rootProps.onBlur?.(event);\n if (event.defaultPrevented) return;\n\n setIsTabbingBackOut(false);\n },\n [rootProps.onBlur]\n );\n\n const onFocus = React.useCallback(\n (event: React.FocusEvent<HTMLDivElement>) => {\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 // Nửa sao: tìm mục đại diện cho giá trị đang chọn bằng giá trị TRẦN (3,5 → mục 4).\n const selectedItem =\n propsRef.current.step < 1\n ? items.find((item) => item.value === Math.ceil(value))\n : items.find((item) => item.value === value);\n const currentItem = items.find((item) => item.id === tabStopId);\n\n const candidateItems = [selectedItem, 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, value, tabStopId]\n );\n\n const onMouseDown = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n propsRef.current.onMouseDown?.(event);\n\n if (event.defaultPrevented) return;\n\n isClickFocusRef.current = true;\n },\n [propsRef]\n );\n\n const contextValue = React.useMemo<RatingContextValue>(\n () => ({\n rootId,\n dir,\n orientation,\n activationMode,\n disabled,\n readOnly,\n size,\n max,\n step,\n clearable,\n itemLabel,\n getAutoIndex\n }),\n [rootId, dir, orientation, activationMode, disabled, readOnly, size, max, step, clearable, itemLabel, getAutoIndex]\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 RootPrimitive = asChild ? Slot : \"div\";\n\n /*\n * ⚠ Khác thượng nguồn: gradient của NỬA SAO phải nằm BÊN TRONG phần tử gốc. Trong SVG,\n * `stopColor=\"currentColor\"` lấy `color` tính ở chỗ gradient được KHAI, không phải ở chỗ nó được\n * dùng — bản gốc đặt `<svg>` này làm anh em của phần tử gốc, nên nửa sao ăn màu chữ của trang\n * (đo trên trình duyệt: #0E1116 ở light, #F7F7F8 ở dark) thay vì màu sao `text-primary-ink`.\n * Với `asChild` thì Slot không nhận thêm con được, nên gradient đành đứng ngoài như bản gốc —\n * khi đó app phải tự đặt màu chữ cho phần tử BAO NGOÀI.\n */\n const partialFillGradient = (\n <svg width=\"0\" height=\"0\" aria-hidden=\"true\" focusable=\"false\" style={{ position: \"absolute\" }}>\n <defs>\n <linearGradient id={getPartialFillGradientId(rootId, step)}>\n {dir === \"rtl\" ? (\n <>\n <stop offset=\"50%\" stopColor=\"transparent\" />\n <stop offset=\"50%\" stopColor=\"currentColor\" />\n </>\n ) : (\n <>\n <stop offset=\"50%\" stopColor=\"currentColor\" />\n <stop offset=\"50%\" stopColor=\"transparent\" />\n </>\n )}\n </linearGradient>\n </defs>\n </svg>\n );\n\n return (\n <StoreContext.Provider value={store}>\n <RatingContext.Provider value={contextValue}>\n <FocusContext.Provider value={focusContextValue}>\n <RootPrimitive\n id={rootId}\n role=\"radiogroup\"\n aria-orientation={orientation}\n aria-disabled={disabled || undefined}\n aria-readonly={readOnly || undefined}\n aria-required={required || undefined}\n data-disabled={disabled ? \"\" : undefined}\n data-readonly={readOnly ? \"\" : undefined}\n data-orientation={orientation}\n data-slot=\"rating\"\n dir={dir}\n tabIndex={isTabbingBackOut || focusableItemCount === 0 ? -1 : 0}\n {...rootProps}\n ref={composedRef}\n className={cn(\n /*\n * Ngôi sao là thành phần PHI VĂN BẢN mang nghĩa (nó LÀ giá trị) → màu đi qua bậc\n * `-ink` của tone, không phải token tô nền. Bản gốc `text-primary` đọc thẳng màu\n * TÔ NỀN; ở bảng mặc định hai token trùng nhau (`--primary-ink: var(--primary)`),\n * nhưng bảng tương phản cao kéo `--primary-ink` xuống bậc tối — và chỉ `-ink` mới\n * được đổi theo. Hợp đồng §1 của docs/hop-dong-mau.md.\n */\n \"flex gap-1 text-primary-ink 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 {asChild ? (\n children\n ) : (\n <>\n {children}\n {partialFillGradient}\n </>\n )}\n </RootPrimitive>\n {asChild ? partialFillGradient : null}\n {isFormControl && (\n <VisuallyHiddenInput\n type=\"hidden\"\n control={formTrigger}\n name={name}\n value={value}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n />\n )}\n </FocusContext.Provider>\n </RatingContext.Provider>\n </StoreContext.Provider>\n );\n}\n\ninterface RatingItemProps extends Omit<React.ComponentProps<\"button\">, \"children\"> {\n index?: number;\n asChild?: boolean;\n children?: React.ReactNode | ((dataState: DataState) => React.ReactNode);\n}\n\nfunction RatingItem(props: RatingItemProps) {\n const {\n index,\n asChild,\n onClick: onClickProp,\n onFocus: onFocusProp,\n onKeyDown: onKeyDownProp,\n onMouseDown: onMouseDownProp,\n onMouseEnter: onMouseEnterProp,\n onMouseMove: onMouseMoveProp,\n onMouseLeave: onMouseLeaveProp,\n disabled,\n className,\n children,\n ref,\n ...itemProps\n } = props;\n\n const itemRef = React.useRef<ItemElement>(null);\n const composedRef = useComposedRefs(ref, itemRef);\n\n const context = useRatingContext(ITEM_NAME);\n\n const instanceId = React.useId();\n\n const actualIndex = React.useMemo(() => {\n if (index !== undefined) {\n return index;\n }\n\n return context.getAutoIndex(instanceId);\n }, [index, context, instanceId]);\n\n const itemValue = actualIndex + 1;\n const store = useStoreContext(ITEM_NAME);\n const focusContext = useFocusContext(ITEM_NAME);\n const value = useStore((state) => state.value);\n const hoveredValue = useStore((state) => state.hoveredValue);\n const clearable = context.clearable;\n const step = context.step;\n const activationMode = context.activationMode;\n\n const itemId = getItemId(context.rootId, itemValue);\n const isDisabled = context.disabled || disabled;\n const isReadOnly = context.readOnly;\n const isTabStop = focusContext.tabStopId === itemId;\n\n const displayValue = hoveredValue ?? value;\n const isFilled = displayValue >= itemValue;\n const isPartiallyFilled = step < 1 && displayValue >= itemValue - step && displayValue < itemValue;\n const isHovered = hoveredValue !== null && hoveredValue < itemValue;\n /*\n * ⚠ Khác thượng nguồn: bản gốc đặt `aria-checked={isFilled}`, tức chọn 4 sao thì BỐN nút radio\n * cùng báo \"đã chọn\" — một radiogroup có nhiều radio được chọn là trạng thái không tồn tại với\n * trình đọc màn hình. Ở đây chỉ đúng MỘT mục được chọn: mục chứa giá trị (3,5 → mục 4), và đọc\n * theo `value` thật chứ không theo sao đang được rê chuột (`displayValue`).\n */\n const isChecked = value > 0 && Math.ceil(value) === itemValue;\n\n const isMouseClickRef = React.useRef(false);\n\n const propsRef = useAsRef({\n onClick: onClickProp,\n onFocus: onFocusProp,\n onKeyDown: onKeyDownProp,\n onMouseDown: onMouseDownProp,\n onMouseEnter: onMouseEnterProp,\n onMouseMove: onMouseMoveProp,\n onMouseLeave: onMouseLeaveProp\n });\n\n useIsomorphicLayoutEffect(() => {\n focusContext.onItemRegister({\n id: itemId,\n ref: itemRef,\n value: itemValue,\n disabled: !!isDisabled\n });\n\n if (!isDisabled) {\n focusContext.onFocusableItemAdd();\n }\n\n return () => {\n focusContext.onItemUnregister(itemId);\n if (!isDisabled) {\n focusContext.onFocusableItemRemove();\n }\n };\n }, [focusContext, itemId, itemValue, isDisabled]);\n\n const onClick = React.useCallback(\n (event: React.MouseEvent<ItemElement>) => {\n propsRef.current.onClick?.(event);\n if (event.defaultPrevented) return;\n\n if (!isDisabled && !isReadOnly) {\n let newValue = itemValue;\n\n if (step < 1) {\n const rect = event.currentTarget.getBoundingClientRect();\n const clickX = event.clientX - rect.left;\n const isLeftHalf = clickX < rect.width / 2;\n\n if (context.dir === \"rtl\") {\n if (!isLeftHalf) {\n newValue = itemValue - step;\n }\n } else {\n if (isLeftHalf) {\n newValue = itemValue - step;\n }\n }\n }\n\n if (clearable && value === newValue) {\n newValue = 0;\n }\n\n store.setState(\"value\", newValue);\n }\n },\n [isDisabled, isReadOnly, clearable, step, value, itemValue, store, context.dir, propsRef]\n );\n\n const onFocus = React.useCallback(\n (event: React.FocusEvent<ItemElement>) => {\n propsRef.current.onFocus?.(event);\n if (event.defaultPrevented) return;\n\n focusContext.onItemFocus(itemId);\n\n const isKeyboardFocus = !isMouseClickRef.current;\n\n if (!isDisabled && !isReadOnly && activationMode !== \"manual\" && isKeyboardFocus) {\n // Nửa sao: nếu giá trị đang là nửa-bậc THUỘC mục này (3,5 khi mục là 4) thì đừng đổi nó.\n const isHalfStepValue = step < 1 && value === itemValue - step;\n\n if (!isHalfStepValue) {\n const newValue = clearable && value === itemValue ? 0 : itemValue;\n store.setState(\"value\", newValue);\n }\n }\n\n isMouseClickRef.current = false;\n },\n [focusContext, itemId, activationMode, isDisabled, isReadOnly, clearable, value, itemValue, step, store, propsRef]\n );\n\n const onKeyDown = React.useCallback(\n (event: React.KeyboardEvent<ItemElement>) => {\n propsRef.current.onKeyDown?.(event);\n if (event.defaultPrevented) return;\n\n if ((event.key === \"Enter\" || event.key === \" \") && activationMode === \"manual\") {\n event.preventDefault();\n if (!isDisabled && !isReadOnly && itemRef.current) {\n itemRef.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, context.orientation);\n\n if (focusIntent !== undefined) {\n if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) return;\n event.preventDefault();\n\n // Nửa sao: mũi tên tăng/giảm đúng một `step` thay vì nhảy sang mục kế.\n if (step < 1 && (focusIntent === \"prev\" || focusIntent === \"next\")) {\n if (!isDisabled && !isReadOnly) {\n let newValue = value;\n\n if (focusIntent === \"next\") {\n newValue = Math.min(value + step, context.max);\n } else {\n newValue = Math.max(value - step, 0);\n }\n\n store.setState(\"value\", newValue);\n\n // Đưa focus tới mục đại diện cho giá trị mới.\n const items = focusContext.getItems().filter((item) => !item.disabled);\n const targetItem = items.find((item) => item.value === Math.ceil(newValue));\n if (targetItem?.ref.current) {\n queueMicrotask(() => targetItem.ref.current?.focus());\n }\n }\n return;\n }\n\n // Bậc nguyên, hoặc Home/End: điều hướng như thường.\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 = candidateRefs.slice(currentIndex + 1);\n }\n\n queueMicrotask(() => focusFirst(candidateRefs));\n }\n },\n [\n focusContext,\n context.dir,\n context.orientation,\n activationMode,\n isDisabled,\n isReadOnly,\n step,\n value,\n context.max,\n store,\n propsRef\n ]\n );\n\n const onMouseDown = React.useCallback(\n (event: React.MouseEvent<ItemElement>) => {\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(itemId);\n }\n },\n [focusContext, itemId, isDisabled, propsRef]\n );\n\n const onMouseEnter = React.useCallback(\n (event: React.MouseEvent<ItemElement>) => {\n propsRef.current.onMouseEnter?.(event);\n if (event.defaultPrevented) return;\n\n if (!isDisabled && !isReadOnly) {\n let hoverValue = itemValue;\n\n if (step < 1) {\n const rect = event.currentTarget.getBoundingClientRect();\n const mouseX = event.clientX - rect.left;\n const isLeftHalf = mouseX < rect.width / 2;\n\n if (context.dir === \"rtl\") {\n if (!isLeftHalf) {\n hoverValue = itemValue - step;\n }\n } else {\n if (isLeftHalf) {\n hoverValue = itemValue - step;\n }\n }\n }\n\n store.setState(\"hoveredValue\", hoverValue);\n }\n },\n [isDisabled, isReadOnly, step, itemValue, store, context.dir, propsRef]\n );\n\n const onMouseLeave = React.useCallback(\n (event: React.MouseEvent<ItemElement>) => {\n propsRef.current.onMouseLeave?.(event);\n if (event.defaultPrevented) return;\n\n if (!isDisabled && !isReadOnly) {\n store.setState(\"hoveredValue\", null);\n }\n },\n [isDisabled, isReadOnly, store, propsRef]\n );\n\n const onMouseMove = React.useCallback(\n (event: React.MouseEvent<ItemElement>) => {\n propsRef.current.onMouseMove?.(event);\n if (event.defaultPrevented) return;\n\n if (!isDisabled && !isReadOnly && step < 1) {\n const rect = event.currentTarget.getBoundingClientRect();\n const mouseX = event.clientX - rect.left;\n const isLeftHalf = mouseX < rect.width / 2;\n\n let hoverValue = itemValue;\n if (context.dir === \"rtl\") {\n hoverValue = !isLeftHalf ? itemValue - step : itemValue;\n } else {\n hoverValue = isLeftHalf ? itemValue - step : itemValue;\n }\n\n store.setState(\"hoveredValue\", hoverValue);\n }\n },\n [isDisabled, isReadOnly, step, itemValue, store, context.dir, propsRef]\n );\n\n const dataState: DataState = isFilled ? \"full\" : isPartiallyFilled ? \"partial\" : \"empty\";\n\n const ItemPrimitive = asChild ? Slot : \"button\";\n\n return (\n <ItemPrimitive\n role=\"radio\"\n type=\"button\"\n id={itemId}\n aria-label={context.itemLabel(itemValue, context.max)}\n aria-checked={isChecked}\n aria-posinset={itemValue}\n aria-setsize={context.max}\n data-disabled={isDisabled ? \"\" : undefined}\n data-readonly={isReadOnly ? \"\" : undefined}\n data-state={dataState}\n data-hovered={isHovered ? \"\" : undefined}\n data-slot=\"rating-item\"\n disabled={isDisabled}\n tabIndex={isTabStop ? 0 : -1}\n {...itemProps}\n ref={composedRef}\n style={{\n ...itemProps.style,\n ...(isPartiallyFilled && {\n \"--partial-fill\": `url(#${getPartialFillGradientId(context.rootId, step)})`\n })\n }}\n className={cn(\n // Viền focus cùng khuôn với `Checkbox`/`RadioGroup` của gói.\n \"inline-flex items-center justify-center rounded transition-colors 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\",\n \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:transition-colors [&_svg]:duration-200 data-[state=empty]:[&_svg]:fill-transparent data-[state=full]:[&_svg]:fill-current data-[state=partial]:[&_svg]:fill-(--partial-fill) [&_svg:not([class*='size-'])]:size-full\",\n context.size === \"sm\" ? \"size-4\" : context.size === \"lg\" ? \"size-6\" : \"size-5\",\n className\n )}\n onClick={onClick}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onMouseDown={onMouseDown}\n onMouseEnter={onMouseEnter}\n onMouseMove={onMouseMove}\n onMouseLeave={onMouseLeave}\n >\n {typeof children === \"function\" ? children(dataState) : (children ?? <Star aria-hidden=\"true\" />)}\n </ItemPrimitive>\n );\n}\n\nexport { Rating, RatingItem, type RatingItemProps, type RatingProps, useStore as useRating };\n"],"mappings":"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","names":["value","instanceId","tabStopId","id","items","ref"]}
@@ -0,0 +1,35 @@
1
+ import * as React from 'react';
2
+ import { DialogProps, DialogCloseProps, DialogContentProps, DialogDescriptionProps, DialogFooterProps, DialogHeaderProps, DialogOverlayProps, DialogPortalProps, DialogTitleProps, DialogTriggerProps } from './dialog.js';
3
+ import '@radix-ui/react-dialog';
4
+
5
+ interface ResponsiveDialogProps extends DialogProps {
6
+ /**
7
+ * Bề ngang (px) mà DƯỚI mức đó hiện `Drawer` thay cho `Dialog`. Mặc định 768 — mốc `md`.
8
+ */
9
+ breakpoint?: number;
10
+ }
11
+ declare function ResponsiveDialog({ breakpoint, open: openProp, defaultOpen, onOpenChange: onOpenChangeProp, ...props }: ResponsiveDialogProps): React.JSX.Element;
12
+ type ResponsiveDialogTriggerProps = DialogTriggerProps;
13
+ declare function ResponsiveDialogTrigger({ ...props }: ResponsiveDialogTriggerProps): React.JSX.Element;
14
+ type ResponsiveDialogCloseProps = DialogCloseProps;
15
+ declare function ResponsiveDialogClose({ ...props }: ResponsiveDialogCloseProps): React.JSX.Element;
16
+ type ResponsiveDialogPortalProps = DialogPortalProps;
17
+ declare function ResponsiveDialogPortal({ ...props }: ResponsiveDialogPortalProps): React.JSX.Element;
18
+ type ResponsiveDialogOverlayProps = DialogOverlayProps;
19
+ declare function ResponsiveDialogOverlay({ ...props }: ResponsiveDialogOverlayProps): React.JSX.Element;
20
+ /**
21
+ * `showCloseButton`, `size` và `closeLabel` là prop của `DialogContent` — chỉ có tác dụng ở nhánh
22
+ * hộp thoại. Nhánh ngăn kéo không có nút đóng góc (vuốt xuống, chạm nền, hoặc Escape để đóng).
23
+ */
24
+ type ResponsiveDialogContentProps = DialogContentProps;
25
+ declare function ResponsiveDialogContent({ className, showCloseButton, size, closeLabel, ...props }: ResponsiveDialogContentProps): React.JSX.Element;
26
+ type ResponsiveDialogHeaderProps = DialogHeaderProps;
27
+ declare function ResponsiveDialogHeader({ ...props }: ResponsiveDialogHeaderProps): React.JSX.Element;
28
+ type ResponsiveDialogFooterProps = DialogFooterProps;
29
+ declare function ResponsiveDialogFooter({ ...props }: ResponsiveDialogFooterProps): React.JSX.Element;
30
+ type ResponsiveDialogTitleProps = DialogTitleProps;
31
+ declare function ResponsiveDialogTitle({ ...props }: ResponsiveDialogTitleProps): React.JSX.Element;
32
+ type ResponsiveDialogDescriptionProps = DialogDescriptionProps;
33
+ declare function ResponsiveDialogDescription({ ...props }: ResponsiveDialogDescriptionProps): React.JSX.Element;
34
+
35
+ export { ResponsiveDialog, ResponsiveDialogClose, type ResponsiveDialogCloseProps, ResponsiveDialogContent, type ResponsiveDialogContentProps, ResponsiveDialogDescription, type ResponsiveDialogDescriptionProps, ResponsiveDialogFooter, type ResponsiveDialogFooterProps, ResponsiveDialogHeader, type ResponsiveDialogHeaderProps, ResponsiveDialogOverlay, type ResponsiveDialogOverlayProps, ResponsiveDialogPortal, type ResponsiveDialogPortalProps, type ResponsiveDialogProps, ResponsiveDialogTitle, type ResponsiveDialogTitleProps, ResponsiveDialogTrigger, type ResponsiveDialogTriggerProps };
@@ -0,0 +1,193 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "../../lib/cn.js";
5
+ import { useAsRef } from "../../lib/use-as-ref.js";
6
+ import { useIsMobile } from "../../lib/use-is-mobile.js";
7
+ import { useIsomorphicLayoutEffect } from "../../lib/use-isomorphic-layout-effect.js";
8
+ import { useLazyRef } from "../../lib/use-lazy-ref.js";
9
+ import {
10
+ Dialog,
11
+ DialogClose,
12
+ DialogContent,
13
+ DialogDescription,
14
+ DialogFooter,
15
+ DialogHeader,
16
+ DialogOverlay,
17
+ DialogPortal,
18
+ DialogTitle,
19
+ DialogTrigger
20
+ } from "./dialog.js";
21
+ import {
22
+ Drawer,
23
+ DrawerClose,
24
+ DrawerContent,
25
+ DrawerDescription,
26
+ DrawerFooter,
27
+ DrawerHeader,
28
+ DrawerOverlay,
29
+ DrawerPortal,
30
+ DrawerTitle,
31
+ DrawerTrigger
32
+ } from "./drawer.js";
33
+ const ROOT_NAME = "ResponsiveDialog";
34
+ const StoreContext = React.createContext(null);
35
+ function useStore(selector, ogStore) {
36
+ const contextStore = React.useContext(StoreContext);
37
+ const store = ogStore ?? contextStore;
38
+ if (!store) {
39
+ throw new Error(`C\xE1c ph\u1EA7n c\u1EE7a \`${ROOT_NAME}\` ph\u1EA3i n\u1EB1m b\xEAn trong \`${ROOT_NAME}\``);
40
+ }
41
+ const getSnapshot = React.useCallback(() => selector(store.getState()), [store, selector]);
42
+ return React.useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);
43
+ }
44
+ function ResponsiveDialog({
45
+ breakpoint = 768,
46
+ open: openProp,
47
+ defaultOpen = false,
48
+ onOpenChange: onOpenChangeProp,
49
+ ...props
50
+ }) {
51
+ const isMobile = useIsMobile(breakpoint);
52
+ const listenersRef = useLazyRef(() => /* @__PURE__ */ new Set());
53
+ const stateRef = useLazyRef(() => ({
54
+ open: openProp ?? defaultOpen,
55
+ isMobile
56
+ }));
57
+ const onOpenChangeRef = useAsRef(onOpenChangeProp);
58
+ const store = React.useMemo(() => {
59
+ return {
60
+ subscribe: (cb) => {
61
+ listenersRef.current.add(cb);
62
+ return () => listenersRef.current.delete(cb);
63
+ },
64
+ getState: () => stateRef.current,
65
+ setState: (key, value) => {
66
+ if (Object.is(stateRef.current[key], value)) return;
67
+ if (key === "open" && typeof value === "boolean") {
68
+ stateRef.current.open = value;
69
+ onOpenChangeRef.current?.(value);
70
+ } else {
71
+ stateRef.current[key] = value;
72
+ }
73
+ store.notify();
74
+ },
75
+ notify: () => {
76
+ for (const cb of listenersRef.current) {
77
+ cb();
78
+ }
79
+ }
80
+ };
81
+ }, [listenersRef, stateRef, onOpenChangeRef]);
82
+ if (stateRef.current.isMobile !== isMobile) {
83
+ stateRef.current.isMobile = isMobile;
84
+ }
85
+ const open = useStore((state) => state.open, store);
86
+ useIsomorphicLayoutEffect(() => {
87
+ if (openProp !== void 0) {
88
+ store.setState("open", openProp);
89
+ }
90
+ }, [openProp]);
91
+ const onOpenChange = React.useCallback(
92
+ (value) => {
93
+ store.setState("open", value);
94
+ },
95
+ [store]
96
+ );
97
+ if (isMobile) {
98
+ return /* @__PURE__ */ jsx(StoreContext.Provider, { value: store, children: /* @__PURE__ */ jsx(Drawer, { open, onOpenChange, ...props }) });
99
+ }
100
+ return /* @__PURE__ */ jsx(StoreContext.Provider, { value: store, children: /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, ...props }) });
101
+ }
102
+ function ResponsiveDialogTrigger({ ...props }) {
103
+ const isMobile = useStore((state) => state.isMobile);
104
+ if (isMobile) {
105
+ return /* @__PURE__ */ jsx(DrawerTrigger, { "data-variant": "drawer", ...props });
106
+ }
107
+ return /* @__PURE__ */ jsx(DialogTrigger, { "data-variant": "dialog", ...props });
108
+ }
109
+ function ResponsiveDialogClose({ ...props }) {
110
+ const isMobile = useStore((state) => state.isMobile);
111
+ if (isMobile) {
112
+ return /* @__PURE__ */ jsx(DrawerClose, { "data-variant": "drawer", ...props });
113
+ }
114
+ return /* @__PURE__ */ jsx(DialogClose, { "data-variant": "dialog", ...props });
115
+ }
116
+ function ResponsiveDialogPortal({ ...props }) {
117
+ const isMobile = useStore((state) => state.isMobile);
118
+ if (isMobile) {
119
+ return /* @__PURE__ */ jsx(DrawerPortal, { "data-variant": "drawer", ...props });
120
+ }
121
+ return /* @__PURE__ */ jsx(DialogPortal, { "data-variant": "dialog", ...props });
122
+ }
123
+ function ResponsiveDialogOverlay({ ...props }) {
124
+ const isMobile = useStore((state) => state.isMobile);
125
+ if (isMobile) {
126
+ return /* @__PURE__ */ jsx(DrawerOverlay, { "data-variant": "drawer", ...props });
127
+ }
128
+ return /* @__PURE__ */ jsx(DialogOverlay, { "data-variant": "dialog", ...props });
129
+ }
130
+ function ResponsiveDialogContent({
131
+ className,
132
+ showCloseButton,
133
+ size,
134
+ closeLabel,
135
+ ...props
136
+ }) {
137
+ const isMobile = useStore((state) => state.isMobile);
138
+ if (isMobile) {
139
+ return /* @__PURE__ */ jsx(DrawerContent, { "data-variant": "drawer", className: cn("px-4 pb-4", className), ...props });
140
+ }
141
+ return /* @__PURE__ */ jsx(
142
+ DialogContent,
143
+ {
144
+ "data-variant": "dialog",
145
+ className,
146
+ showCloseButton,
147
+ size,
148
+ closeLabel,
149
+ ...props
150
+ }
151
+ );
152
+ }
153
+ function ResponsiveDialogHeader({ ...props }) {
154
+ const isMobile = useStore((state) => state.isMobile);
155
+ if (isMobile) {
156
+ return /* @__PURE__ */ jsx(DrawerHeader, { "data-variant": "drawer", ...props });
157
+ }
158
+ return /* @__PURE__ */ jsx(DialogHeader, { "data-variant": "dialog", ...props });
159
+ }
160
+ function ResponsiveDialogFooter({ ...props }) {
161
+ const isMobile = useStore((state) => state.isMobile);
162
+ if (isMobile) {
163
+ return /* @__PURE__ */ jsx(DrawerFooter, { "data-variant": "drawer", ...props });
164
+ }
165
+ return /* @__PURE__ */ jsx(DialogFooter, { "data-variant": "dialog", ...props });
166
+ }
167
+ function ResponsiveDialogTitle({ ...props }) {
168
+ const isMobile = useStore((state) => state.isMobile);
169
+ if (isMobile) {
170
+ return /* @__PURE__ */ jsx(DrawerTitle, { "data-variant": "drawer", ...props });
171
+ }
172
+ return /* @__PURE__ */ jsx(DialogTitle, { "data-variant": "dialog", ...props });
173
+ }
174
+ function ResponsiveDialogDescription({ ...props }) {
175
+ const isMobile = useStore((state) => state.isMobile);
176
+ if (isMobile) {
177
+ return /* @__PURE__ */ jsx(DrawerDescription, { "data-variant": "drawer", ...props });
178
+ }
179
+ return /* @__PURE__ */ jsx(DialogDescription, { "data-variant": "dialog", ...props });
180
+ }
181
+ export {
182
+ ResponsiveDialog,
183
+ ResponsiveDialogClose,
184
+ ResponsiveDialogContent,
185
+ ResponsiveDialogDescription,
186
+ ResponsiveDialogFooter,
187
+ ResponsiveDialogHeader,
188
+ ResponsiveDialogOverlay,
189
+ ResponsiveDialogPortal,
190
+ ResponsiveDialogTitle,
191
+ ResponsiveDialogTrigger
192
+ };
193
+ //# sourceMappingURL=responsive-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/ui/responsive-dialog.tsx"],"sourcesContent":["\"use client\";\n\n/*\n * Port từ Dice UI (https://diceui.com/docs/components/responsive-dialog) — 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 * Hộp thoại (`Dialog`) trên màn rộng, ngăn kéo (`Drawer`, vaul) dưới `breakpoint` — cả hai đều là\n * primitive CỦA GÓI, nên mọi quy ước của chúng (cỡ `size`, `closeLabel`, trần chiều cao, tay cầm\n * kéo) áp y nguyên. Mỗi phần gắn `data-variant=\"dialog\" | \"drawer\"` để app style theo nhánh.\n */\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\nimport { useAsRef } from \"../../lib/use-as-ref.js\";\nimport { useIsMobile } from \"../../lib/use-is-mobile.js\";\nimport { useIsomorphicLayoutEffect } from \"../../lib/use-isomorphic-layout-effect.js\";\nimport { useLazyRef } from \"../../lib/use-lazy-ref.js\";\nimport {\n Dialog,\n DialogClose,\n type DialogCloseProps,\n DialogContent,\n type DialogContentProps,\n DialogDescription,\n type DialogDescriptionProps,\n DialogFooter,\n type DialogFooterProps,\n DialogHeader,\n type DialogHeaderProps,\n DialogOverlay,\n type DialogOverlayProps,\n DialogPortal,\n type DialogPortalProps,\n type DialogProps,\n DialogTitle,\n type DialogTitleProps,\n DialogTrigger,\n type DialogTriggerProps\n} from \"./dialog.js\";\nimport {\n Drawer,\n DrawerClose,\n DrawerContent,\n DrawerDescription,\n DrawerFooter,\n DrawerHeader,\n DrawerOverlay,\n DrawerPortal,\n DrawerTitle,\n DrawerTrigger\n} from \"./drawer.js\";\n\nconst ROOT_NAME = \"ResponsiveDialog\";\n\ninterface StoreState {\n open: boolean;\n isMobile: boolean;\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 notify: () => void;\n}\n\nconst StoreContext = React.createContext<Store | null>(null);\n\nfunction useStore<T>(selector: (state: StoreState) => T, ogStore?: Store | null): T {\n const contextStore = React.useContext(StoreContext);\n const store = ogStore ?? contextStore;\n\n if (!store) {\n throw new Error(`Các phần của \\`${ROOT_NAME}\\` phải nằm bên trong \\`${ROOT_NAME}\\``);\n }\n\n const getSnapshot = React.useCallback(() => selector(store.getState()), [store, selector]);\n\n return React.useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);\n}\n\ninterface ResponsiveDialogProps extends DialogProps {\n /**\n * Bề ngang (px) mà DƯỚI mức đó hiện `Drawer` thay cho `Dialog`. Mặc định 768 — mốc `md`.\n */\n breakpoint?: number;\n}\n\n/*\n * ⚠ Khác thượng nguồn — FOCUS Ở NHÁNH NGĂN KÉO: vaul 1.1.2 mặc định `autoFocus = false`, nên với\n * bản gốc focus ở lại trên nút mở NẰM SAU lớp phủ và Tab đi khắp trang phía sau (đo ở 375px với\n * cú bấm thật). Chỗ sửa nằm ở `Drawer` của gói — nó mặc định `autoFocus = true` cho MỌI nơi dùng\n * (xem drawer.tsx) — nên ở đây không phải làm gì: hai nhánh cùng đưa focus vào phần tử đầu tiên.\n * Muốn focus chỗ khác thì gọi `event.preventDefault()` trong `onOpenAutoFocus` của\n * `ResponsiveDialogContent` rồi tự `focus()` — cách này dùng được ở CẢ HAI nhánh.\n */\nfunction ResponsiveDialog({\n breakpoint = 768,\n open: openProp,\n defaultOpen = false,\n onOpenChange: onOpenChangeProp,\n ...props\n}: ResponsiveDialogProps) {\n const isMobile = useIsMobile(breakpoint);\n\n const listenersRef = useLazyRef(() => new Set<() => void>());\n const stateRef = useLazyRef<StoreState>(() => ({\n open: openProp ?? defaultOpen,\n isMobile\n }));\n\n const onOpenChangeRef = useAsRef(onOpenChangeProp);\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 === \"open\" && typeof value === \"boolean\") {\n stateRef.current.open = value;\n onOpenChangeRef.current?.(value);\n } else {\n stateRef.current[key] = value;\n }\n\n store.notify();\n },\n notify: () => {\n for (const cb of listenersRef.current) {\n cb();\n }\n }\n };\n }, [listenersRef, stateRef, onOpenChangeRef]);\n\n /*\n * Ghi thẳng vào state (không `notify`) là cố ý, như thượng nguồn: đổi nhánh Dialog ⇄ Drawer\n * đổi KIỂU phần tử gốc ngay bên dưới, nên cả cây con gắn lại và tự đọc giá trị mới.\n */\n if (stateRef.current.isMobile !== isMobile) {\n stateRef.current.isMobile = isMobile;\n }\n\n const open = useStore((state) => state.open, store);\n\n useIsomorphicLayoutEffect(() => {\n if (openProp !== undefined) {\n store.setState(\"open\", openProp);\n }\n }, [openProp]);\n\n const onOpenChange = React.useCallback(\n (value: boolean) => {\n store.setState(\"open\", value);\n },\n [store]\n );\n\n if (isMobile) {\n return (\n <StoreContext.Provider value={store}>\n <Drawer open={open} onOpenChange={onOpenChange} {...props} />\n </StoreContext.Provider>\n );\n }\n\n return (\n <StoreContext.Provider value={store}>\n <Dialog open={open} onOpenChange={onOpenChange} {...props} />\n </StoreContext.Provider>\n );\n}\n\ntype ResponsiveDialogTriggerProps = DialogTriggerProps;\n\nfunction ResponsiveDialogTrigger({ ...props }: ResponsiveDialogTriggerProps) {\n const isMobile = useStore((state) => state.isMobile);\n\n if (isMobile) {\n return <DrawerTrigger data-variant=\"drawer\" {...props} />;\n }\n\n return <DialogTrigger data-variant=\"dialog\" {...props} />;\n}\n\ntype ResponsiveDialogCloseProps = DialogCloseProps;\n\nfunction ResponsiveDialogClose({ ...props }: ResponsiveDialogCloseProps) {\n const isMobile = useStore((state) => state.isMobile);\n\n if (isMobile) {\n return <DrawerClose data-variant=\"drawer\" {...props} />;\n }\n\n return <DialogClose data-variant=\"dialog\" {...props} />;\n}\n\ntype ResponsiveDialogPortalProps = DialogPortalProps;\n\nfunction ResponsiveDialogPortal({ ...props }: ResponsiveDialogPortalProps) {\n const isMobile = useStore((state) => state.isMobile);\n\n if (isMobile) {\n return <DrawerPortal data-variant=\"drawer\" {...props} />;\n }\n\n return <DialogPortal data-variant=\"dialog\" {...props} />;\n}\n\ntype ResponsiveDialogOverlayProps = DialogOverlayProps;\n\nfunction ResponsiveDialogOverlay({ ...props }: ResponsiveDialogOverlayProps) {\n const isMobile = useStore((state) => state.isMobile);\n\n if (isMobile) {\n return <DrawerOverlay data-variant=\"drawer\" {...props} />;\n }\n\n return <DialogOverlay data-variant=\"dialog\" {...props} />;\n}\n\n/**\n * `showCloseButton`, `size` và `closeLabel` là prop của `DialogContent` — chỉ có tác dụng ở nhánh\n * hộp thoại. Nhánh ngăn kéo không có nút đóng góc (vuốt xuống, chạm nền, hoặc Escape để đóng).\n */\ntype ResponsiveDialogContentProps = DialogContentProps;\n\nfunction ResponsiveDialogContent({\n className,\n showCloseButton,\n size,\n closeLabel,\n ...props\n}: ResponsiveDialogContentProps) {\n const isMobile = useStore((state) => state.isMobile);\n\n if (isMobile) {\n /*\n * ⚠ Khác thượng nguồn: bản gốc rải NGUYÊN props của `DialogContent` xuống `DrawerContent`,\n * nên app nào truyền `showCloseButton` (và ở gói này thêm `size`, `closeLabel`) là prop đó\n * rơi xuống thẻ DOM — React cảnh báo prop lạ, còn `size=\"lg\"` thành thuộc tính HTML thật.\n * Ba prop này bị tách ra ở chữ ký hàm và chỉ đi vào nhánh hộp thoại.\n */\n return <DrawerContent data-variant=\"drawer\" className={cn(\"px-4 pb-4\", className)} {...props} />;\n }\n\n return (\n <DialogContent\n data-variant=\"dialog\"\n className={className}\n showCloseButton={showCloseButton}\n size={size}\n closeLabel={closeLabel}\n {...props}\n />\n );\n}\n\ntype ResponsiveDialogHeaderProps = DialogHeaderProps;\n\nfunction ResponsiveDialogHeader({ ...props }: ResponsiveDialogHeaderProps) {\n const isMobile = useStore((state) => state.isMobile);\n\n if (isMobile) {\n return <DrawerHeader data-variant=\"drawer\" {...props} />;\n }\n\n return <DialogHeader data-variant=\"dialog\" {...props} />;\n}\n\ntype ResponsiveDialogFooterProps = DialogFooterProps;\n\n/*\n * ⚠ Khác thượng nguồn: bản gốc nhận `showCloseButton` và chuyển cho `DialogFooter` (shadcn mới vẽ\n * sẵn nút \"Close\" ở chân hộp thoại). `DialogFooter` của gói KHÔNG có prop đó — nút đóng nằm ở\n * `DialogContent` (`showCloseButton`), còn nút huỷ ở chân thì app tự đặt bằng\n * `ResponsiveDialogClose`.\n */\nfunction ResponsiveDialogFooter({ ...props }: ResponsiveDialogFooterProps) {\n const isMobile = useStore((state) => state.isMobile);\n\n if (isMobile) {\n return <DrawerFooter data-variant=\"drawer\" {...props} />;\n }\n\n return <DialogFooter data-variant=\"dialog\" {...props} />;\n}\n\ntype ResponsiveDialogTitleProps = DialogTitleProps;\n\nfunction ResponsiveDialogTitle({ ...props }: ResponsiveDialogTitleProps) {\n const isMobile = useStore((state) => state.isMobile);\n\n if (isMobile) {\n return <DrawerTitle data-variant=\"drawer\" {...props} />;\n }\n\n return <DialogTitle data-variant=\"dialog\" {...props} />;\n}\n\ntype ResponsiveDialogDescriptionProps = DialogDescriptionProps;\n\nfunction ResponsiveDialogDescription({ ...props }: ResponsiveDialogDescriptionProps) {\n const isMobile = useStore((state) => state.isMobile);\n\n if (isMobile) {\n return <DrawerDescription data-variant=\"drawer\" {...props} />;\n }\n\n return <DialogDescription data-variant=\"dialog\" {...props} />;\n}\n\nexport {\n ResponsiveDialog,\n ResponsiveDialogClose,\n type ResponsiveDialogCloseProps,\n ResponsiveDialogContent,\n type ResponsiveDialogContentProps,\n ResponsiveDialogDescription,\n type ResponsiveDialogDescriptionProps,\n ResponsiveDialogFooter,\n type ResponsiveDialogFooterProps,\n ResponsiveDialogHeader,\n type ResponsiveDialogHeaderProps,\n ResponsiveDialogOverlay,\n type ResponsiveDialogOverlayProps,\n ResponsiveDialogPortal,\n type ResponsiveDialogPortalProps,\n type ResponsiveDialogProps,\n ResponsiveDialogTitle,\n type ResponsiveDialogTitleProps,\n ResponsiveDialogTrigger,\n type ResponsiveDialogTriggerProps\n};\n"],"mappings":"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","names":[]}
@@ -0,0 +1,42 @@
1
+ import * as React from 'react';
2
+
3
+ type Direction = "ltr" | "rtl";
4
+ type Orientation = "horizontal" | "vertical";
5
+ interface ScrollSpyProps extends React.ComponentProps<"div"> {
6
+ value?: string;
7
+ defaultValue?: string;
8
+ onValueChange?: (value: string) => void;
9
+ rootMargin?: string;
10
+ threshold?: number | number[];
11
+ offset?: number;
12
+ /**
13
+ * Kiểu cuộn khi bấm link. Không truyền thì `"smooth"`, hoặc `"auto"` nếu người dùng bật giảm
14
+ * chuyển động (`prefers-reduced-motion`).
15
+ */
16
+ scrollBehavior?: ScrollBehavior;
17
+ scrollContainer?: HTMLElement | null;
18
+ dir?: Direction;
19
+ orientation?: Orientation;
20
+ asChild?: boolean;
21
+ }
22
+ declare function ScrollSpy(props: ScrollSpyProps): React.JSX.Element;
23
+ interface ScrollSpyNavProps extends React.ComponentProps<"nav"> {
24
+ asChild?: boolean;
25
+ }
26
+ declare function ScrollSpyNav(props: ScrollSpyNavProps): React.JSX.Element;
27
+ interface ScrollSpyLinkProps extends React.ComponentProps<"a"> {
28
+ value: string;
29
+ asChild?: boolean;
30
+ }
31
+ declare function ScrollSpyLink(props: ScrollSpyLinkProps): React.JSX.Element;
32
+ interface ScrollSpyViewportProps extends React.ComponentProps<"div"> {
33
+ asChild?: boolean;
34
+ }
35
+ declare function ScrollSpyViewport(props: ScrollSpyViewportProps): React.JSX.Element;
36
+ interface ScrollSpySectionProps extends React.ComponentProps<"div"> {
37
+ value: string;
38
+ asChild?: boolean;
39
+ }
40
+ declare function ScrollSpySection(props: ScrollSpySectionProps): React.JSX.Element;
41
+
42
+ export { ScrollSpy, ScrollSpyLink, type ScrollSpyLinkProps, ScrollSpyNav, type ScrollSpyNavProps, type ScrollSpyProps, ScrollSpySection, type ScrollSpySectionProps, ScrollSpyViewport, type ScrollSpyViewportProps };