@evinvest/uikit 0.32.0 → 0.33.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 (288) hide show
  1. package/README.md +21 -10
  2. package/dist/components/atomic/accordion.js +2 -1
  3. package/dist/components/atomic/accordion.js.map +1 -1
  4. package/dist/components/atomic/alert.js +4 -4
  5. package/dist/components/atomic/alert.js.map +1 -1
  6. package/dist/components/atomic/badge.js +4 -3
  7. package/dist/components/atomic/badge.js.map +1 -1
  8. package/dist/components/atomic/breadcrumb.js +7 -9
  9. package/dist/components/atomic/breadcrumb.js.map +1 -1
  10. package/dist/components/atomic/button.js +4 -3
  11. package/dist/components/atomic/button.js.map +1 -1
  12. package/dist/components/atomic/calendar.js +10 -25
  13. package/dist/components/atomic/calendar.js.map +1 -1
  14. package/dist/components/atomic/checkbox.js +2 -1
  15. package/dist/components/atomic/checkbox.js.map +1 -1
  16. package/dist/components/atomic/command.js +5 -20
  17. package/dist/components/atomic/command.js.map +1 -1
  18. package/dist/components/atomic/context-menu.js +6 -13
  19. package/dist/components/atomic/context-menu.js.map +1 -1
  20. package/dist/components/atomic/dialog.js +4 -2
  21. package/dist/components/atomic/dialog.js.map +1 -1
  22. package/dist/components/atomic/dropdown-menu.js +6 -14
  23. package/dist/components/atomic/dropdown-menu.js.map +1 -1
  24. package/dist/components/atomic/hover-card.js.map +1 -1
  25. package/dist/components/atomic/info-tip.js +8 -9
  26. package/dist/components/atomic/info-tip.js.map +1 -1
  27. package/dist/components/atomic/input-otp.js +2 -1
  28. package/dist/components/atomic/input-otp.js.map +1 -1
  29. package/dist/components/atomic/key-value.js +5 -4
  30. package/dist/components/atomic/key-value.js.map +1 -1
  31. package/dist/components/atomic/menubar.js +7 -18
  32. package/dist/components/atomic/menubar.js.map +1 -1
  33. package/dist/components/atomic/native-select.js +1 -1
  34. package/dist/components/atomic/native-select.js.map +1 -1
  35. package/dist/components/atomic/navigation-menu.js +6 -14
  36. package/dist/components/atomic/navigation-menu.js.map +1 -1
  37. package/dist/components/atomic/pagination.js +18 -19
  38. package/dist/components/atomic/pagination.js.map +1 -1
  39. package/dist/components/atomic/popover.js.map +1 -1
  40. package/dist/components/atomic/radio-group.js +5 -4
  41. package/dist/components/atomic/radio-group.js.map +1 -1
  42. package/dist/components/atomic/section-descriptor.js +5 -8
  43. package/dist/components/atomic/section-descriptor.js.map +1 -1
  44. package/dist/components/atomic/select-listbox.js +2 -2
  45. package/dist/components/atomic/select-listbox.js.map +1 -1
  46. package/dist/components/atomic/select.js +5 -13
  47. package/dist/components/atomic/select.js.map +1 -1
  48. package/dist/components/atomic/sheet.js +4 -2
  49. package/dist/components/atomic/sheet.js.map +1 -1
  50. package/dist/components/atomic/sidebar.js +7 -26
  51. package/dist/components/atomic/sidebar.js.map +1 -1
  52. package/dist/components/atomic/slider.js.map +1 -1
  53. package/dist/components/atomic/sonner.js +20 -18
  54. package/dist/components/atomic/sonner.js.map +1 -1
  55. package/dist/components/atomic/spinner.js +6 -3
  56. package/dist/components/atomic/spinner.js.map +1 -1
  57. package/dist/components/atomic/tabs.js.map +1 -1
  58. package/dist/components/atomic/toggle-group.js +2 -2
  59. package/dist/components/atomic/toggle-group.js.map +1 -1
  60. package/dist/components/atomic/toggle.js +3 -6
  61. package/dist/components/atomic/toggle.js.map +1 -1
  62. package/dist/components/atomic/tooltip.js.map +1 -1
  63. package/dist/components/derived/carousel.js +6 -6
  64. package/dist/components/derived/carousel.js.map +1 -1
  65. package/dist/components/derived/command-palette.js +8 -7
  66. package/dist/components/derived/command-palette.js.map +1 -1
  67. package/dist/components/derived/confirm-dialog.js +8 -13
  68. package/dist/components/derived/confirm-dialog.js.map +1 -1
  69. package/dist/components/derived/date-time-picker.js +10 -14
  70. package/dist/components/derived/date-time-picker.js.map +1 -1
  71. package/dist/components/derived/field.js.map +1 -1
  72. package/dist/components/derived/form.js +0 -1
  73. package/dist/components/derived/form.js.map +1 -1
  74. package/dist/components/derived/icon-button.js.map +1 -1
  75. package/dist/components/derived/item.js +0 -1
  76. package/dist/components/derived/item.js.map +1 -1
  77. package/dist/components/derived/popover-form.js +4 -3
  78. package/dist/components/derived/popover-form.js.map +1 -1
  79. package/dist/components/derived/settings.js +4 -4
  80. package/dist/components/derived/settings.js.map +1 -1
  81. package/dist/components/shell/account-menu-profile.js +1 -1
  82. package/dist/components/shell/account-menu-profile.js.map +1 -1
  83. package/dist/components/shell/account-settings-dialog.js +3 -2
  84. package/dist/components/shell/account-settings-dialog.js.map +1 -1
  85. package/dist/components/shell/aside.js +6 -4
  86. package/dist/components/shell/aside.js.map +1 -1
  87. package/dist/components/shell/auth-wall.js +3 -5
  88. package/dist/components/shell/auth-wall.js.map +1 -1
  89. package/dist/components/shell/bottom-tab-bar.js +3 -3
  90. package/dist/components/shell/bottom-tab-bar.js.map +1 -1
  91. package/dist/components/shell/chat-composer.js +9 -7
  92. package/dist/components/shell/chat-composer.js.map +1 -1
  93. package/dist/components/shell/chat-message.js.map +1 -1
  94. package/dist/components/shell/chat-typing.js +2 -1
  95. package/dist/components/shell/chat-typing.js.map +1 -1
  96. package/dist/components/shell/footer.js +26 -24
  97. package/dist/components/shell/footer.js.map +1 -1
  98. package/dist/components/shell/header-controls.js +17 -15
  99. package/dist/components/shell/header-controls.js.map +1 -1
  100. package/dist/components/shell/hotbar.js +158 -0
  101. package/dist/components/shell/hotbar.js.map +1 -0
  102. package/dist/components/shell/logo.js +3 -2
  103. package/dist/components/shell/logo.js.map +1 -1
  104. package/dist/components/shell/mobile-app-bar.js +4 -4
  105. package/dist/components/shell/mobile-app-bar.js.map +1 -1
  106. package/dist/components/shell/nav-collapse.js +6 -5
  107. package/dist/components/shell/nav-collapse.js.map +1 -1
  108. package/dist/components/shell/resource-error.js +2 -2
  109. package/dist/components/shell/resource-error.js.map +1 -1
  110. package/dist/components/shell/section-nav.js +3 -3
  111. package/dist/components/shell/section-nav.js.map +1 -1
  112. package/dist/components/shell/shell-icons.js +7 -22
  113. package/dist/components/shell/shell-icons.js.map +1 -1
  114. package/dist/components/shell/shell-nav.js +4 -4
  115. package/dist/components/shell/shell-nav.js.map +1 -1
  116. package/dist/components/shell/smart-header.js.map +1 -1
  117. package/dist/components/shell/status-screen.js +35 -35
  118. package/dist/components/shell/status-screen.js.map +1 -1
  119. package/dist/components/shell/system-banner.js +6 -6
  120. package/dist/components/shell/system-banner.js.map +1 -1
  121. package/dist/components/shell/workspace-tab.js +2 -1
  122. package/dist/components/shell/workspace-tab.js.map +1 -1
  123. package/dist/generated/accent.js +10 -10
  124. package/dist/generated/accent.js.map +1 -1
  125. package/dist/generated/accordion.js +6 -2
  126. package/dist/generated/accordion.js.map +1 -1
  127. package/dist/generated/account-list.js +4 -4
  128. package/dist/generated/account-list.js.map +1 -1
  129. package/dist/generated/account-settings-dialog.js +6 -2
  130. package/dist/generated/account-settings-dialog.js.map +1 -1
  131. package/dist/generated/alert-dialog.js +1 -1
  132. package/dist/generated/alert-dialog.js.map +1 -1
  133. package/dist/generated/alert.js +3 -10
  134. package/dist/generated/alert.js.map +1 -1
  135. package/dist/generated/aside.js +7 -0
  136. package/dist/generated/aside.js.map +1 -1
  137. package/dist/generated/badge.js +2 -11
  138. package/dist/generated/badge.js.map +1 -1
  139. package/dist/generated/band.js +10 -10
  140. package/dist/generated/band.js.map +1 -1
  141. package/dist/generated/breadcrumb.js +1 -1
  142. package/dist/generated/breadcrumb.js.map +1 -1
  143. package/dist/generated/button-group.js +3 -3
  144. package/dist/generated/button-group.js.map +1 -1
  145. package/dist/generated/button.js +4 -20
  146. package/dist/generated/button.js.map +1 -1
  147. package/dist/generated/calendar.js +5 -5
  148. package/dist/generated/calendar.js.map +1 -1
  149. package/dist/generated/card.js +1 -1
  150. package/dist/generated/card.js.map +1 -1
  151. package/dist/generated/carousel.js +1 -1
  152. package/dist/generated/carousel.js.map +1 -1
  153. package/dist/generated/chat-composer.js +9 -2
  154. package/dist/generated/chat-composer.js.map +1 -1
  155. package/dist/generated/chat-message.js +25 -19
  156. package/dist/generated/chat-message.js.map +1 -1
  157. package/dist/generated/checkbox.js +1 -1
  158. package/dist/generated/checkbox.js.map +1 -1
  159. package/dist/generated/command-palette.js +10 -1
  160. package/dist/generated/command-palette.js.map +1 -1
  161. package/dist/generated/command.js +8 -6
  162. package/dist/generated/command.js.map +1 -1
  163. package/dist/generated/confirm-dialog.js +8 -8
  164. package/dist/generated/confirm-dialog.js.map +1 -1
  165. package/dist/generated/context-menu.js +7 -5
  166. package/dist/generated/context-menu.js.map +1 -1
  167. package/dist/generated/copy.js +97 -0
  168. package/dist/generated/copy.js.map +1 -0
  169. package/dist/generated/date-time-picker.js +10 -0
  170. package/dist/generated/date-time-picker.js.map +1 -1
  171. package/dist/generated/dialog.js +2 -2
  172. package/dist/generated/dialog.js.map +1 -1
  173. package/dist/generated/drawer.js +6 -6
  174. package/dist/generated/drawer.js.map +1 -1
  175. package/dist/generated/dropdown-menu.js +7 -5
  176. package/dist/generated/dropdown-menu.js.map +1 -1
  177. package/dist/generated/empty.js +5 -5
  178. package/dist/generated/empty.js.map +1 -1
  179. package/dist/generated/field.js +9 -7
  180. package/dist/generated/field.js.map +1 -1
  181. package/dist/generated/footer.js +45 -0
  182. package/dist/generated/footer.js.map +1 -0
  183. package/dist/generated/header-controls.js +5 -10
  184. package/dist/generated/header-controls.js.map +1 -1
  185. package/dist/generated/hover-card.js +1 -1
  186. package/dist/generated/hover-card.js.map +1 -1
  187. package/dist/generated/icon-button.js +4 -2
  188. package/dist/generated/icon-button.js.map +1 -1
  189. package/dist/generated/icons.js +36 -0
  190. package/dist/generated/icons.js.map +1 -0
  191. package/dist/generated/info-tip.js +5 -0
  192. package/dist/generated/info-tip.js.map +1 -0
  193. package/dist/generated/input-group.js +10 -10
  194. package/dist/generated/input-group.js.map +1 -1
  195. package/dist/generated/input-otp.js +2 -2
  196. package/dist/generated/input-otp.js.map +1 -1
  197. package/dist/generated/input.js +4 -4
  198. package/dist/generated/input.js.map +1 -1
  199. package/dist/generated/item.js +11 -11
  200. package/dist/generated/item.js.map +1 -1
  201. package/dist/generated/kbd.js +1 -1
  202. package/dist/generated/kbd.js.map +1 -1
  203. package/dist/generated/key-value.js +7 -1
  204. package/dist/generated/key-value.js.map +1 -1
  205. package/dist/generated/label.js +1 -1
  206. package/dist/generated/label.js.map +1 -1
  207. package/dist/generated/logo.js +9 -0
  208. package/dist/generated/logo.js.map +1 -0
  209. package/dist/generated/menu.js +7 -0
  210. package/dist/generated/menu.js.map +1 -0
  211. package/dist/generated/menubar.js +10 -8
  212. package/dist/generated/menubar.js.map +1 -1
  213. package/dist/generated/navigation-menu.js +11 -5
  214. package/dist/generated/navigation-menu.js.map +1 -1
  215. package/dist/generated/orientation.js +5 -0
  216. package/dist/generated/orientation.js.map +1 -0
  217. package/dist/generated/pagination.js +15 -0
  218. package/dist/generated/pagination.js.map +1 -0
  219. package/dist/generated/popover-form.js +5 -0
  220. package/dist/generated/popover-form.js.map +1 -1
  221. package/dist/generated/popover.js +1 -1
  222. package/dist/generated/popover.js.map +1 -1
  223. package/dist/generated/primitives.js +7 -0
  224. package/dist/generated/primitives.js.map +1 -0
  225. package/dist/generated/radio-group.js +5 -1
  226. package/dist/generated/radio-group.js.map +1 -1
  227. package/dist/generated/section-descriptor.js +7 -0
  228. package/dist/generated/section-descriptor.js.map +1 -0
  229. package/dist/generated/select.js +16 -10
  230. package/dist/generated/select.js.map +1 -1
  231. package/dist/generated/settings.js +2 -7
  232. package/dist/generated/settings.js.map +1 -1
  233. package/dist/generated/sheet.js +1 -1
  234. package/dist/generated/sheet.js.map +1 -1
  235. package/dist/generated/sidebar.js +24 -12
  236. package/dist/generated/sidebar.js.map +1 -1
  237. package/dist/generated/size.js +12 -0
  238. package/dist/generated/size.js.map +1 -0
  239. package/dist/generated/skeleton.js +1 -1
  240. package/dist/generated/skeleton.js.map +1 -1
  241. package/dist/generated/slider.js +2 -2
  242. package/dist/generated/slider.js.map +1 -1
  243. package/dist/generated/slot.js +5 -0
  244. package/dist/generated/slot.js.map +1 -0
  245. package/dist/generated/smart-header.js +2 -0
  246. package/dist/generated/smart-header.js.map +1 -1
  247. package/dist/generated/sonner.js +11 -13
  248. package/dist/generated/sonner.js.map +1 -1
  249. package/dist/generated/spinner.js +5 -0
  250. package/dist/generated/spinner.js.map +1 -0
  251. package/dist/generated/status-screen.js +27 -0
  252. package/dist/generated/status-screen.js.map +1 -0
  253. package/dist/generated/switch.js +2 -2
  254. package/dist/generated/switch.js.map +1 -1
  255. package/dist/generated/system-banner.js +6 -16
  256. package/dist/generated/system-banner.js.map +1 -1
  257. package/dist/generated/table.js +9 -9
  258. package/dist/generated/table.js.map +1 -1
  259. package/dist/generated/tabs.js +2 -2
  260. package/dist/generated/tabs.js.map +1 -1
  261. package/dist/generated/textarea.js +1 -1
  262. package/dist/generated/textarea.js.map +1 -1
  263. package/dist/generated/toggle-group.js +9 -0
  264. package/dist/generated/toggle-group.js.map +1 -0
  265. package/dist/generated/toggle.js +1 -9
  266. package/dist/generated/toggle.js.map +1 -1
  267. package/dist/generated/tone.js +12 -0
  268. package/dist/generated/tone.js.map +1 -0
  269. package/dist/generated/tooltip.js +1 -1
  270. package/dist/generated/tooltip.js.map +1 -1
  271. package/dist/generated/workspace-tab.js +3 -3
  272. package/dist/generated/workspace-tab.js.map +1 -1
  273. package/dist/icons/icon-shapes.js +10 -0
  274. package/dist/icons/icon-shapes.js.map +1 -0
  275. package/dist/icons/select-chevron.js +2 -1
  276. package/dist/icons/select-chevron.js.map +1 -1
  277. package/dist/icons/ui-icons.js +3 -57
  278. package/dist/icons/ui-icons.js.map +1 -1
  279. package/dist/index.d.ts +203 -155
  280. package/dist/index.js +1 -0
  281. package/dist/lib/cn.js +1 -0
  282. package/dist/lib/cn.js.map +1 -1
  283. package/dist/primitives/use-floating.js.map +1 -1
  284. package/dist/primitives/use-roving-focus.js.map +1 -1
  285. package/package.json +1 -1
  286. package/styles/ev.css +13 -76
  287. package/styles/theme.css +133 -66
  288. package/styles/tokens.css +157 -149
@@ -20,6 +20,8 @@ import {
20
20
  CAROUSEL_PREVIOUS_HORIZONTAL,
21
21
  CAROUSEL_PREVIOUS_VERTICAL
22
22
  } from "../../generated/carousel.js";
23
+ import * as copy from "../../generated/copy.js";
24
+ import { iconShapes } from "../../icons/icon-shapes.js";
23
25
  const CarouselContext = React.createContext(null);
24
26
  function useCarousel() {
25
27
  const context = React.useContext(CarouselContext);
@@ -176,7 +178,6 @@ function CarouselPrevious({
176
178
  return /* @__PURE__ */ jsxs(
177
179
  Button,
178
180
  {
179
- "data-slot": "carousel-previous",
180
181
  variant,
181
182
  size,
182
183
  icon,
@@ -200,10 +201,10 @@ function CarouselPrevious({
200
201
  strokeLinecap: "round",
201
202
  strokeLinejoin: "round",
202
203
  "aria-hidden": "true",
203
- children: /* @__PURE__ */ jsx("path", { d: "m15 18-6-6 6-6" })
204
+ children: iconShapes("chevron-left")
204
205
  }
205
206
  ),
206
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Previous slide" })
207
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: copy.CAROUSEL_PREVIOUS })
207
208
  ]
208
209
  }
209
210
  );
@@ -219,7 +220,6 @@ function CarouselNext({
219
220
  return /* @__PURE__ */ jsxs(
220
221
  Button,
221
222
  {
222
- "data-slot": "carousel-next",
223
223
  variant,
224
224
  size,
225
225
  icon,
@@ -243,10 +243,10 @@ function CarouselNext({
243
243
  strokeLinecap: "round",
244
244
  strokeLinejoin: "round",
245
245
  "aria-hidden": "true",
246
- children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" })
246
+ children: iconShapes("chevron-right")
247
247
  }
248
248
  ),
249
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Next slide" })
249
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: copy.CAROUSEL_NEXT })
250
250
  ]
251
251
  }
252
252
  );
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/derived/carousel.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { Button, type ButtonProps } from \"../atomic/button\";\nimport { useControllableState } from \"../../primitives/use-controllable-state\";\nimport {\n CAROUSEL_CONTENT_TRACK,\n CAROUSEL_CONTENT_TRACK_HORIZONTAL,\n CAROUSEL_CONTENT_TRACK_VERTICAL,\n CAROUSEL_CONTENT_VIEWPORT,\n CAROUSEL_EDGE_FADE_NEXT,\n CAROUSEL_EDGE_FADE_PREV,\n CAROUSEL_ITEM,\n CAROUSEL_ITEM_HORIZONTAL,\n CAROUSEL_ITEM_VERTICAL,\n CAROUSEL_NAV,\n CAROUSEL_NEXT_HORIZONTAL,\n CAROUSEL_NEXT_VERTICAL,\n CAROUSEL_PREVIOUS_HORIZONTAL,\n CAROUSEL_PREVIOUS_VERTICAL,\n} from \"../../generated/carousel\";\n\ntype CarouselOrientation = \"horizontal\" | \"vertical\";\n\ntype CarouselContextProps = {\n orientation: CarouselOrientation;\n index: number;\n count: number;\n setCount: (count: number) => void;\n scrollPrev: () => void;\n scrollNext: () => void;\n canScrollPrev: boolean;\n canScrollNext: boolean;\n};\n\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null);\n\nfunction useCarousel() {\n const context = React.useContext(CarouselContext);\n if (!context) {\n throw new Error(\"useCarousel must be used within a <Carousel />\");\n }\n return context;\n}\n\nexport interface CarouselProps extends React.ComponentProps<\"div\"> {\n orientation?: CarouselOrientation;\n index?: number;\n defaultIndex?: number;\n onIndexChange?: (index: number) => void;\n}\n\nexport function Carousel({\n orientation = \"horizontal\",\n index: indexProp,\n defaultIndex = 0,\n onIndexChange,\n className,\n children,\n onKeyDown,\n ...props\n}: CarouselProps) {\n const [index, setIndex] = useControllableState<number>({\n value: indexProp,\n defaultValue: defaultIndex,\n onChange: onIndexChange,\n });\n const [count, setCount] = React.useState(0);\n\n const canScrollPrev = index > 0;\n const canScrollNext = index < count - 1;\n\n const scrollPrev = React.useCallback(() => {\n if (index > 0) setIndex(index - 1);\n }, [index, setIndex]);\n\n const scrollNext = React.useCallback(() => {\n if (index < count - 1) setIndex(index + 1);\n }, [index, count, setIndex]);\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n scrollPrev();\n } else if (event.key === \"ArrowRight\") {\n event.preventDefault();\n scrollNext();\n }\n onKeyDown?.(event);\n };\n\n return (\n <CarouselContext.Provider\n value={{\n orientation,\n index,\n count,\n setCount,\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext,\n }}\n >\n <div\n onKeyDownCapture={handleKeyDown}\n className={cn(\"relative\", className)}\n role=\"region\"\n aria-roledescription=\"carousel\"\n tabIndex={0}\n data-slot=\"carousel\"\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n );\n}\n\nexport function CarouselContent({\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\">) {\n const { orientation, index, setCount } = useCarousel();\n const childCount = React.Children.count(children);\n\n React.useEffect(() => {\n setCount(childCount);\n }, [childCount, setCount]);\n\n // drag/momentum: omitted vs embla — see README Limitations\n const transform =\n orientation === \"horizontal\"\n ? `translate3d(-${index * 100}%, 0, 0)`\n : `translate3d(0, -${index * 100}%, 0)`;\n\n return (\n <div className={CAROUSEL_CONTENT_VIEWPORT} data-slot=\"carousel-content\">\n <div\n className={cn(\n CAROUSEL_CONTENT_TRACK,\n orientation === \"horizontal\"\n ? CAROUSEL_CONTENT_TRACK_HORIZONTAL\n : CAROUSEL_CONTENT_TRACK_VERTICAL,\n className,\n )}\n style={{ transform }}\n {...props}\n >\n {children}\n </div>\n </div>\n );\n}\n\nexport function CarouselItem({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n const { orientation } = useCarousel();\n\n return (\n <div\n role=\"group\"\n aria-roledescription=\"slide\"\n data-slot=\"carousel-item\"\n className={cn(\n CAROUSEL_ITEM,\n orientation === \"horizontal\" ? CAROUSEL_ITEM_HORIZONTAL : CAROUSEL_ITEM_VERTICAL,\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Netflix-style edge scrims that dissolve the current slide into the surface\n * colour, signalling adjacent slides without revealing them. Each side shows\n * only when there is somewhere to scroll. Drop inside a <Carousel>.\n */\nexport function CarouselEdgeFade({\n className,\n}: {\n className?: string;\n}) {\n const { canScrollPrev, canScrollNext } = useCarousel();\n\n return (\n <>\n <div\n aria-hidden\n className={cn(\n CAROUSEL_EDGE_FADE_PREV,\n canScrollPrev ? \"opacity-100\" : \"opacity-0\",\n className,\n )}\n />\n <div\n aria-hidden\n className={cn(\n CAROUSEL_EDGE_FADE_NEXT,\n canScrollNext ? \"opacity-100\" : \"opacity-0\",\n className,\n )}\n />\n </>\n );\n}\n\nexport function CarouselPrevious({\n className,\n variant = \"outline\",\n size = \"md\",\n icon = true,\n ...props\n}: ButtonProps) {\n const { orientation, scrollPrev, canScrollPrev } = useCarousel();\n\n return (\n <Button\n data-slot=\"carousel-previous\"\n variant={variant}\n size={size}\n icon={icon}\n className={cn(\n CAROUSEL_NAV,\n orientation === \"horizontal\"\n ? CAROUSEL_PREVIOUS_HORIZONTAL\n : CAROUSEL_PREVIOUS_VERTICAL,\n className,\n )}\n disabled={!canScrollPrev}\n onClick={scrollPrev}\n {...props}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n <span className=\"sr-only\">Previous slide</span>\n </Button>\n );\n}\n\nexport function CarouselNext({\n className,\n variant = \"outline\",\n size = \"md\",\n icon = true,\n ...props\n}: ButtonProps) {\n const { orientation, scrollNext, canScrollNext } = useCarousel();\n\n return (\n <Button\n data-slot=\"carousel-next\"\n variant={variant}\n size={size}\n icon={icon}\n className={cn(\n CAROUSEL_NAV,\n orientation === \"horizontal\"\n ? CAROUSEL_NEXT_HORIZONTAL\n : CAROUSEL_NEXT_VERTICAL,\n className,\n )}\n disabled={!canScrollNext}\n onClick={scrollNext}\n {...props}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n <span className=\"sr-only\">Next slide</span>\n </Button>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/derived/carousel.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { Button, type ButtonProps } from \"../atomic/button\";\nimport { useControllableState } from \"../../primitives/use-controllable-state\";\nimport {\n CAROUSEL_CONTENT_TRACK,\n CAROUSEL_CONTENT_TRACK_HORIZONTAL,\n CAROUSEL_CONTENT_TRACK_VERTICAL,\n CAROUSEL_CONTENT_VIEWPORT,\n CAROUSEL_EDGE_FADE_NEXT,\n CAROUSEL_EDGE_FADE_PREV,\n CAROUSEL_ITEM,\n CAROUSEL_ITEM_HORIZONTAL,\n CAROUSEL_ITEM_VERTICAL,\n CAROUSEL_NAV,\n CAROUSEL_NEXT_HORIZONTAL,\n CAROUSEL_NEXT_VERTICAL,\n CAROUSEL_PREVIOUS_HORIZONTAL,\n CAROUSEL_PREVIOUS_VERTICAL,\n} from \"../../generated/carousel\";\nimport type { Orientation } from \"../../generated/orientation\";\nimport * as copy from \"../../generated/copy\";\nimport { iconShapes } from \"../../icons/icon-shapes\";\n\n\ntype CarouselContextProps = {\n orientation: Orientation;\n index: number;\n count: number;\n setCount: (count: number) => void;\n scrollPrev: () => void;\n scrollNext: () => void;\n canScrollPrev: boolean;\n canScrollNext: boolean;\n};\n\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null);\n\nfunction useCarousel() {\n const context = React.useContext(CarouselContext);\n if (!context) {\n throw new Error(\"useCarousel must be used within a <Carousel />\");\n }\n return context;\n}\n\nexport interface CarouselProps extends React.ComponentProps<\"div\"> {\n orientation?: Orientation;\n index?: number;\n defaultIndex?: number;\n onIndexChange?: (index: number) => void;\n}\n\nexport function Carousel({\n orientation = \"horizontal\",\n index: indexProp,\n defaultIndex = 0,\n onIndexChange,\n className,\n children,\n onKeyDown,\n ...props\n}: CarouselProps) {\n const [index, setIndex] = useControllableState<number>({\n value: indexProp,\n defaultValue: defaultIndex,\n onChange: onIndexChange,\n });\n const [count, setCount] = React.useState(0);\n\n const canScrollPrev = index > 0;\n const canScrollNext = index < count - 1;\n\n const scrollPrev = React.useCallback(() => {\n if (index > 0) setIndex(index - 1);\n }, [index, setIndex]);\n\n const scrollNext = React.useCallback(() => {\n if (index < count - 1) setIndex(index + 1);\n }, [index, count, setIndex]);\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n scrollPrev();\n } else if (event.key === \"ArrowRight\") {\n event.preventDefault();\n scrollNext();\n }\n onKeyDown?.(event);\n };\n\n return (\n <CarouselContext.Provider\n value={{\n orientation,\n index,\n count,\n setCount,\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext,\n }}\n >\n <div\n onKeyDownCapture={handleKeyDown}\n className={cn(\"relative\", className)}\n role=\"region\"\n aria-roledescription=\"carousel\"\n tabIndex={0}\n data-slot=\"carousel\"\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n );\n}\n\nexport function CarouselContent({\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\">) {\n const { orientation, index, setCount } = useCarousel();\n const childCount = React.Children.count(children);\n\n React.useEffect(() => {\n setCount(childCount);\n }, [childCount, setCount]);\n\n // drag/momentum: omitted vs embla — see README Limitations\n const transform =\n orientation === \"horizontal\"\n ? `translate3d(-${index * 100}%, 0, 0)`\n : `translate3d(0, -${index * 100}%, 0)`;\n\n return (\n <div className={CAROUSEL_CONTENT_VIEWPORT} data-slot=\"carousel-content\">\n <div\n className={cn(\n CAROUSEL_CONTENT_TRACK,\n orientation === \"horizontal\"\n ? CAROUSEL_CONTENT_TRACK_HORIZONTAL\n : CAROUSEL_CONTENT_TRACK_VERTICAL,\n className,\n )}\n style={{ transform }}\n {...props}\n >\n {children}\n </div>\n </div>\n );\n}\n\nexport function CarouselItem({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n const { orientation } = useCarousel();\n\n return (\n <div\n role=\"group\"\n aria-roledescription=\"slide\"\n data-slot=\"carousel-item\"\n className={cn(\n CAROUSEL_ITEM,\n orientation === \"horizontal\" ? CAROUSEL_ITEM_HORIZONTAL : CAROUSEL_ITEM_VERTICAL,\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Netflix-style edge scrims that dissolve the current slide into the surface\n * colour, signalling adjacent slides without revealing them. Each side shows\n * only when there is somewhere to scroll. Drop inside a <Carousel>.\n */\nexport function CarouselEdgeFade({\n className,\n}: {\n className?: string;\n}) {\n const { canScrollPrev, canScrollNext } = useCarousel();\n\n return (\n <>\n <div\n aria-hidden\n className={cn(\n CAROUSEL_EDGE_FADE_PREV,\n canScrollPrev ? \"opacity-100\" : \"opacity-0\",\n className,\n )}\n />\n <div\n aria-hidden\n className={cn(\n CAROUSEL_EDGE_FADE_NEXT,\n canScrollNext ? \"opacity-100\" : \"opacity-0\",\n className,\n )}\n />\n </>\n );\n}\n\nexport function CarouselPrevious({\n className,\n variant = \"outline\",\n size = \"md\",\n icon = true,\n ...props\n}: ButtonProps) {\n const { orientation, scrollPrev, canScrollPrev } = useCarousel();\n\n return (\n <Button\n variant={variant}\n size={size}\n icon={icon}\n className={cn(\n CAROUSEL_NAV,\n orientation === \"horizontal\"\n ? CAROUSEL_PREVIOUS_HORIZONTAL\n : CAROUSEL_PREVIOUS_VERTICAL,\n className,\n )}\n disabled={!canScrollPrev}\n onClick={scrollPrev}\n {...props}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n {iconShapes(\"chevron-left\")}\n </svg>\n <span className=\"sr-only\">{copy.CAROUSEL_PREVIOUS}</span>\n </Button>\n );\n}\n\nexport function CarouselNext({\n className,\n variant = \"outline\",\n size = \"md\",\n icon = true,\n ...props\n}: ButtonProps) {\n const { orientation, scrollNext, canScrollNext } = useCarousel();\n\n return (\n <Button\n variant={variant}\n size={size}\n icon={icon}\n className={cn(\n CAROUSEL_NAV,\n orientation === \"horizontal\"\n ? CAROUSEL_NEXT_HORIZONTAL\n : CAROUSEL_NEXT_VERTICAL,\n className,\n )}\n disabled={!canScrollNext}\n onClick={scrollNext}\n {...props}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n {iconShapes(\"chevron-right\")}\n </svg>\n <span className=\"sr-only\">{copy.CAROUSEL_NEXT}</span>\n </Button>\n );\n}\n"],"mappings":"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","names":[]}
@@ -8,7 +8,8 @@ import {
8
8
  COMMAND_PALETTE_HINTS,
9
9
  COMMAND_PALETTE_LABEL,
10
10
  COMMAND_PALETTE_LIST,
11
- COMMAND_PALETTE_TITLE
11
+ COMMAND_PALETTE_TITLE,
12
+ COMMAND_PALETTE_LABELS
12
13
  } from "../../generated/command-palette.js";
13
14
  import { cn } from "../../lib/cn.js";
14
15
  import { useControllableState } from "../../primitives/use-controllable-state.js";
@@ -43,11 +44,11 @@ function CommandPalette({
43
44
  showCloseButton: false,
44
45
  className: cn(COMMAND_PALETTE_CONTENT, className),
45
46
  children: [
46
- /* @__PURE__ */ jsx(DialogTitle, { className: COMMAND_PALETTE_TITLE, children: labels.title ?? "Command palette" }),
47
+ /* @__PURE__ */ jsx(DialogTitle, { className: COMMAND_PALETTE_TITLE, children: labels.title ?? COMMAND_PALETTE_LABELS.title }),
47
48
  /* @__PURE__ */ jsxs(Command, { className: COMMAND_PALETTE_COMMAND, children: [
48
- /* @__PURE__ */ jsx(CommandInput, { placeholder: labels.placeholder ?? "Type a command or search\u2026" }),
49
+ /* @__PURE__ */ jsx(CommandInput, { placeholder: labels.placeholder ?? COMMAND_PALETTE_LABELS.placeholder }),
49
50
  /* @__PURE__ */ jsxs(CommandList, { className: COMMAND_PALETTE_LIST, children: [
50
- /* @__PURE__ */ jsx(CommandEmpty, { children: labels.empty ?? "No results." }),
51
+ /* @__PURE__ */ jsx(CommandEmpty, { children: labels.empty ?? COMMAND_PALETTE_LABELS.empty }),
51
52
  groups.map((group, i) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
52
53
  i > 0 && /* @__PURE__ */ jsx(CommandSeparator, {}),
53
54
  /* @__PURE__ */ jsx(CommandGroup, { ...group.heading !== void 0 ? { heading: group.heading } : {}, children: group.items.map((item) => /* @__PURE__ */ jsxs(
@@ -78,15 +79,15 @@ function CommandPalette({
78
79
  children: [
79
80
  /* @__PURE__ */ jsxs("span", { className: COMMAND_PALETTE_HINT, children: [
80
81
  /* @__PURE__ */ jsx(Kbd, { children: "\u2191\u2193" }),
81
- labels.navigate ?? "navigate"
82
+ labels.navigate ?? COMMAND_PALETTE_LABELS.navigate
82
83
  ] }),
83
84
  /* @__PURE__ */ jsxs("span", { className: COMMAND_PALETTE_HINT, children: [
84
85
  /* @__PURE__ */ jsx(Kbd, { children: "\u21B5" }),
85
- labels.select ?? "select"
86
+ labels.select ?? COMMAND_PALETTE_LABELS.select
86
87
  ] }),
87
88
  /* @__PURE__ */ jsxs("span", { className: COMMAND_PALETTE_HINT, children: [
88
89
  /* @__PURE__ */ jsx(Kbd, { children: "esc" }),
89
- labels.close ?? "close"
90
+ labels.close ?? COMMAND_PALETTE_LABELS.close
90
91
  ] })
91
92
  ]
92
93
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/derived/command-palette.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n COMMAND_PALETTE_COMMAND,\n COMMAND_PALETTE_CONTENT,\n COMMAND_PALETTE_HINT,\n COMMAND_PALETTE_HINTS,\n COMMAND_PALETTE_LABEL,\n COMMAND_PALETTE_LIST,\n COMMAND_PALETTE_TITLE,\n} from \"../../generated/command-palette\";\nimport { cn } from \"../../lib/cn\";\nimport { useControllableState } from \"../../primitives/use-controllable-state\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n CommandShortcut,\n} from \"../atomic/command\";\nimport { Dialog, DialogContent, DialogTitle } from \"../atomic/dialog\";\nimport { Kbd } from \"../atomic/kbd\";\n\nexport interface CommandPaletteItem {\n id: string;\n label: string;\n icon?: React.ReactNode;\n /** Shown at the row end, e.g. \"⌘N\". */\n shortcut?: string;\n /** Extra words the search matches besides the label. */\n keywords?: readonly string[];\n disabled?: boolean;\n onSelect: () => void;\n}\n\nexport interface CommandPaletteGroup {\n id: string;\n heading?: string;\n items: readonly CommandPaletteItem[];\n}\n\nexport interface CommandPaletteLabels {\n /** Names the dialog for assistive tech. Default `\"Command palette\"`. */\n title?: string;\n placeholder?: string;\n empty?: string;\n navigate?: string;\n select?: string;\n close?: string;\n}\n\nexport interface CommandPaletteProps {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n groups: readonly CommandPaletteGroup[];\n labels?: CommandPaletteLabels;\n className?: string;\n}\n\n// Built on Dialog + Command rather than the kit's CommandDialog: that one has no accessible\n// name and no footer, and both need Dialog's title and focus wiring.\n/**\n * Search-and-run over a list of actions. Choosing a row runs it and closes the\n * palette. Pair it with `useCommandPaletteShortcut` for ⌘K / Ctrl+K.\n */\nexport function CommandPalette({\n open,\n defaultOpen = false,\n onOpenChange,\n groups,\n labels = {},\n className,\n}: CommandPaletteProps) {\n const [isOpen, setOpen] = useControllableState<boolean>({\n ...(open !== undefined ? { value: open } : {}),\n defaultValue: defaultOpen,\n ...(onOpenChange ? { onChange: onOpenChange } : {}),\n });\n return (\n <Dialog open={isOpen} onOpenChange={setOpen}>\n <DialogContent\n showCloseButton={false}\n className={cn(COMMAND_PALETTE_CONTENT, className)}\n >\n <DialogTitle className={COMMAND_PALETTE_TITLE}>{labels.title ?? \"Command palette\"}</DialogTitle>\n <Command className={COMMAND_PALETTE_COMMAND}>\n <CommandInput placeholder={labels.placeholder ?? \"Type a command or search…\"} />\n <CommandList className={COMMAND_PALETTE_LIST}>\n <CommandEmpty>{labels.empty ?? \"No results.\"}</CommandEmpty>\n {groups.map((group, i) => (\n <React.Fragment key={group.id}>\n {i > 0 && <CommandSeparator />}\n <CommandGroup {...(group.heading !== undefined ? { heading: group.heading } : {})}>\n {group.items.map((item) => (\n <CommandItem\n key={item.id}\n value={[item.label, ...(item.keywords ?? [])].join(\" \")}\n disabled={item.disabled ?? false}\n onSelect={() => {\n setOpen(false);\n item.onSelect();\n }}\n >\n {item.icon}\n <span className={COMMAND_PALETTE_LABEL}>{item.label}</span>\n {item.shortcut !== undefined && <CommandShortcut>{item.shortcut}</CommandShortcut>}\n </CommandItem>\n ))}\n </CommandGroup>\n </React.Fragment>\n ))}\n </CommandList>\n </Command>\n <div\n data-slot=\"command-palette-hints\"\n className={COMMAND_PALETTE_HINTS}\n >\n <span className={COMMAND_PALETTE_HINT}>\n <Kbd>↑↓</Kbd>\n {labels.navigate ?? \"navigate\"}\n </span>\n <span className={COMMAND_PALETTE_HINT}>\n <Kbd>↵</Kbd>\n {labels.select ?? \"select\"}\n </span>\n <span className={COMMAND_PALETTE_HINT}>\n <Kbd>esc</Kbd>\n {labels.close ?? \"close\"}\n </span>\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n\n/**\n * Calls `onTrigger` on ⌘K (Mac) or Ctrl+K, and keeps the browser from taking\n * the key (Chrome focuses the address bar on Ctrl+K in some layouts). Matches the\n * physical key (`code`), so it also works on a Russian or other non-Latin layout.\n */\nexport function useCommandPaletteShortcut(onTrigger: () => void, enabled = true): void {\n // Latest callback without re-binding the listener on every render.\n const ref = React.useRef(onTrigger);\n React.useEffect(() => {\n ref.current = onTrigger;\n });\n React.useEffect(() => {\n if (!enabled) return;\n const onKeyDown = (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && !e.altKey && !e.shiftKey && e.code === \"KeyK\") {\n e.preventDefault();\n // A held key would toggle the palette open and shut.\n if (!e.repeat) ref.current();\n }\n };\n document.addEventListener(\"keydown\", onKeyDown);\n return () => document.removeEventListener(\"keydown\", onKeyDown);\n }, [enabled]);\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/derived/command-palette.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n COMMAND_PALETTE_COMMAND,\n COMMAND_PALETTE_CONTENT,\n COMMAND_PALETTE_HINT,\n COMMAND_PALETTE_HINTS,\n COMMAND_PALETTE_LABEL,\n COMMAND_PALETTE_LIST,\n COMMAND_PALETTE_TITLE,\n COMMAND_PALETTE_LABELS,\n} from \"../../generated/command-palette\";\nimport { cn } from \"../../lib/cn\";\nimport { useControllableState } from \"../../primitives/use-controllable-state\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n CommandShortcut,\n} from \"../atomic/command\";\nimport { Dialog, DialogContent, DialogTitle } from \"../atomic/dialog\";\nimport { Kbd } from \"../atomic/kbd\";\n\nexport interface CommandPaletteItem {\n id: string;\n label: string;\n icon?: React.ReactNode;\n /** Shown at the row end, e.g. \"⌘N\". */\n shortcut?: string;\n /** Extra words the search matches besides the label. */\n keywords?: readonly string[];\n disabled?: boolean;\n onSelect: () => void;\n}\n\nexport interface CommandPaletteGroup {\n id: string;\n heading?: string;\n items: readonly CommandPaletteItem[];\n}\n\nexport interface CommandPaletteLabels {\n /** Names the dialog for assistive tech. Default `\"Command palette\"`. */\n title?: string;\n placeholder?: string;\n empty?: string;\n navigate?: string;\n select?: string;\n close?: string;\n}\n\nexport interface CommandPaletteProps {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n groups: readonly CommandPaletteGroup[];\n labels?: CommandPaletteLabels;\n className?: string;\n}\n\n// Built on Dialog + Command rather than the kit's CommandDialog: that one has no accessible\n// name and no footer, and both need Dialog's title and focus wiring.\n/**\n * Search-and-run over a list of actions. Choosing a row runs it and closes the\n * palette. Pair it with `useCommandPaletteShortcut` for ⌘K / Ctrl+K.\n */\nexport function CommandPalette({\n open,\n defaultOpen = false,\n onOpenChange,\n groups,\n labels = {},\n className,\n}: CommandPaletteProps) {\n const [isOpen, setOpen] = useControllableState<boolean>({\n ...(open !== undefined ? { value: open } : {}),\n defaultValue: defaultOpen,\n ...(onOpenChange ? { onChange: onOpenChange } : {}),\n });\n return (\n <Dialog open={isOpen} onOpenChange={setOpen}>\n <DialogContent\n showCloseButton={false}\n className={cn(COMMAND_PALETTE_CONTENT, className)}\n >\n <DialogTitle className={COMMAND_PALETTE_TITLE}>{labels.title ?? COMMAND_PALETTE_LABELS.title}</DialogTitle>\n <Command className={COMMAND_PALETTE_COMMAND}>\n <CommandInput placeholder={labels.placeholder ?? COMMAND_PALETTE_LABELS.placeholder} />\n <CommandList className={COMMAND_PALETTE_LIST}>\n <CommandEmpty>{labels.empty ?? COMMAND_PALETTE_LABELS.empty}</CommandEmpty>\n {groups.map((group, i) => (\n <React.Fragment key={group.id}>\n {i > 0 && <CommandSeparator />}\n <CommandGroup {...(group.heading !== undefined ? { heading: group.heading } : {})}>\n {group.items.map((item) => (\n <CommandItem\n key={item.id}\n value={[item.label, ...(item.keywords ?? [])].join(\" \")}\n disabled={item.disabled ?? false}\n onSelect={() => {\n setOpen(false);\n item.onSelect();\n }}\n >\n {item.icon}\n <span className={COMMAND_PALETTE_LABEL}>{item.label}</span>\n {item.shortcut !== undefined && <CommandShortcut>{item.shortcut}</CommandShortcut>}\n </CommandItem>\n ))}\n </CommandGroup>\n </React.Fragment>\n ))}\n </CommandList>\n </Command>\n <div\n data-slot=\"command-palette-hints\"\n className={COMMAND_PALETTE_HINTS}\n >\n <span className={COMMAND_PALETTE_HINT}>\n <Kbd>↑↓</Kbd>\n {labels.navigate ?? COMMAND_PALETTE_LABELS.navigate}\n </span>\n <span className={COMMAND_PALETTE_HINT}>\n <Kbd>↵</Kbd>\n {labels.select ?? COMMAND_PALETTE_LABELS.select}\n </span>\n <span className={COMMAND_PALETTE_HINT}>\n <Kbd>esc</Kbd>\n {labels.close ?? COMMAND_PALETTE_LABELS.close}\n </span>\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n\n/**\n * Calls `onTrigger` on ⌘K (Mac) or Ctrl+K, and keeps the browser from taking\n * the key (Chrome focuses the address bar on Ctrl+K in some layouts). Matches the\n * physical key (`code`), so it also works on a Russian or other non-Latin layout.\n */\nexport function useCommandPaletteShortcut(onTrigger: () => void, enabled = true): void {\n // Latest callback without re-binding the listener on every render.\n const ref = React.useRef(onTrigger);\n React.useEffect(() => {\n ref.current = onTrigger;\n });\n React.useEffect(() => {\n if (!enabled) return;\n const onKeyDown = (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && !e.altKey && !e.shiftKey && e.code === \"KeyK\") {\n e.preventDefault();\n // A held key would toggle the palette open and shut.\n if (!e.repeat) ref.current();\n }\n };\n document.addEventListener(\"keydown\", onKeyDown);\n return () => document.removeEventListener(\"keydown\", onKeyDown);\n }, [enabled]);\n}\n"],"mappings":"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","names":[]}
@@ -13,8 +13,9 @@ import {
13
13
  CONFIRM_DIALOG_SPINNER,
14
14
  CONFIRM_DIALOG_TEXT,
15
15
  CONFIRM_DIALOG_TITLE,
16
- confirmDialogIconToneClasses
16
+ CONFIRM_DIALOG_LABELS
17
17
  } from "../../generated/confirm-dialog.js";
18
+ import { toneClasses } from "../../generated/tone.js";
18
19
  import { useControllableState } from "../../primitives/use-controllable-state.js";
19
20
  import {
20
21
  AlertDialog,
@@ -35,7 +36,7 @@ function ConfirmDialog({
35
36
  trigger,
36
37
  title,
37
38
  description,
38
- tone = "default",
39
+ tone = "neutral",
39
40
  confirmLabel,
40
41
  onConfirm,
41
42
  icon,
@@ -49,7 +50,7 @@ function ConfirmDialog({
49
50
  });
50
51
  const [pending, setPending] = React.useState(false);
51
52
  const [error, setError] = React.useState(null);
52
- const danger = tone === "danger";
53
+ const danger = tone === "error";
53
54
  React.useEffect(() => {
54
55
  if (isOpen) setError(null);
55
56
  }, [isOpen]);
@@ -68,20 +69,14 @@ function ConfirmDialog({
68
69
  setOpen(false);
69
70
  } catch (e) {
70
71
  setPending(false);
71
- setError(e instanceof Error && e.message ? e.message : labels.error ?? "Something went wrong");
72
+ setError(e instanceof Error && e.message ? e.message : labels.error ?? CONFIRM_DIALOG_LABELS.error);
72
73
  }
73
74
  };
74
75
  return /* @__PURE__ */ jsxs(AlertDialog, { open: isOpen, onOpenChange: change, children: [
75
76
  trigger != null && /* @__PURE__ */ jsx(AlertDialogTrigger, { asChild: true, children: trigger }),
76
- /* @__PURE__ */ jsxs(AlertDialogContent, { className: cn(CONFIRM_DIALOG_CONTENT, className), children: [
77
+ /* @__PURE__ */ jsxs(AlertDialogContent, { className: cn(CONFIRM_DIALOG_CONTENT, toneClasses[tone], className), children: [
77
78
  /* @__PURE__ */ jsxs(AlertDialogHeader, { className: CONFIRM_DIALOG_HEADER, children: [
78
- /* @__PURE__ */ jsx(
79
- "span",
80
- {
81
- className: cn(CONFIRM_DIALOG_ICON, confirmDialogIconToneClasses[tone]),
82
- children: icon ?? /* @__PURE__ */ jsx(UiIcon, { name: "alert" })
83
- }
84
- ),
79
+ /* @__PURE__ */ jsx("span", { className: CONFIRM_DIALOG_ICON, children: icon ?? /* @__PURE__ */ jsx(UiIcon, { name: "alert" }) }),
85
80
  /* @__PURE__ */ jsxs("div", { className: CONFIRM_DIALOG_TEXT, children: [
86
81
  /* @__PURE__ */ jsx(AlertDialogTitle, { className: CONFIRM_DIALOG_TITLE, children: title }),
87
82
  description != null && /* @__PURE__ */ jsx(AlertDialogDescription, { className: CONFIRM_DIALOG_DESCRIPTION, children: description }),
@@ -96,7 +91,7 @@ function ConfirmDialog({
96
91
  "aria-disabled": pending,
97
92
  onClick: () => change(false),
98
93
  className: cn(buttonVariants({ variant: "ghost", size: "xs" }), CONFIRM_DIALOG_PENDING),
99
- children: labels.cancel ?? "Cancel"
94
+ children: labels.cancel ?? CONFIRM_DIALOG_LABELS.cancel
100
95
  }
101
96
  ),
102
97
  /* @__PURE__ */ jsxs(
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/derived/confirm-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport {\n CONFIRM_DIALOG_CONTENT,\n CONFIRM_DIALOG_DESCRIPTION,\n CONFIRM_DIALOG_ERROR,\n CONFIRM_DIALOG_FOOTER,\n CONFIRM_DIALOG_HEADER,\n CONFIRM_DIALOG_ICON,\n CONFIRM_DIALOG_PENDING,\n CONFIRM_DIALOG_SPINNER,\n CONFIRM_DIALOG_TEXT,\n CONFIRM_DIALOG_TITLE,\n confirmDialogIconToneClasses,\n type ConfirmDialogTone,\n} from \"../../generated/confirm-dialog\";\nimport { useControllableState } from \"../../primitives/use-controllable-state\";\nimport {\n AlertDialog,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"../atomic/alert-dialog\";\nimport { buttonVariants } from \"../atomic/button\";\nimport { Spinner } from \"../atomic/spinner\";\nimport { UiIcon } from \"../../icons/ui-icons\";\n\nexport type { ConfirmDialogTone };\n\nexport interface ConfirmDialogLabels {\n cancel?: string;\n /** Shown when `onConfirm` rejects with something that has no message. */\n error?: string;\n}\n\nexport interface ConfirmDialogProps {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Opens the dialog; wrapped with `asChild`, so pass one button. */\n trigger?: React.ReactNode;\n title: React.ReactNode;\n description?: React.ReactNode;\n tone?: ConfirmDialogTone;\n confirmLabel: React.ReactNode;\n /**\n * Resolve to close the dialog. While a returned promise is pending both\n * buttons are disabled and Escape and outside clicks do nothing; a rejection\n * keeps the dialog open and shows its message under the text.\n */\n onConfirm: () => void | Promise<void>;\n /** Replaces the tone's glyph. */\n icon?: React.ReactNode;\n labels?: ConfirmDialogLabels;\n className?: string;\n}\n\nexport function ConfirmDialog({\n open,\n defaultOpen = false,\n onOpenChange,\n trigger,\n title,\n description,\n tone = \"default\",\n confirmLabel,\n onConfirm,\n icon,\n labels = {},\n className,\n}: ConfirmDialogProps) {\n const [isOpen, setOpen] = useControllableState<boolean>({\n ...(open !== undefined ? { value: open } : {}),\n defaultValue: defaultOpen,\n ...(onOpenChange ? { onChange: onOpenChange } : {}),\n });\n const [pending, setPending] = React.useState(false);\n const [error, setError] = React.useState<string | null>(null);\n const danger = tone === \"danger\";\n // A controlled parent can reopen the dialog without going through `change`.\n React.useEffect(() => {\n if (isOpen) setError(null);\n }, [isOpen]);\n\n const change = (next: boolean) => {\n if (pending) return;\n if (next) setError(null);\n setOpen(next);\n };\n\n const confirm = async () => {\n if (pending) return;\n setError(null);\n setPending(true);\n try {\n await onConfirm();\n setPending(false);\n setOpen(false);\n } catch (e) {\n setPending(false);\n setError(e instanceof Error && e.message ? e.message : (labels.error ?? \"Something went wrong\"));\n }\n };\n\n return (\n <AlertDialog open={isOpen} onOpenChange={change}>\n {trigger != null && <AlertDialogTrigger asChild>{trigger}</AlertDialogTrigger>}\n <AlertDialogContent className={cn(CONFIRM_DIALOG_CONTENT, className)}>\n <AlertDialogHeader className={CONFIRM_DIALOG_HEADER}>\n <span\n className={cn(CONFIRM_DIALOG_ICON, confirmDialogIconToneClasses[tone])}\n >\n {icon ?? <UiIcon name=\"alert\" />}\n </span>\n <div className={CONFIRM_DIALOG_TEXT}>\n <AlertDialogTitle className={CONFIRM_DIALOG_TITLE}>{title}</AlertDialogTitle>\n {description != null && (\n <AlertDialogDescription className={CONFIRM_DIALOG_DESCRIPTION}>{description}</AlertDialogDescription>\n )}\n {error !== null && (\n <p role=\"alert\" className={CONFIRM_DIALOG_ERROR}>\n {error}\n </p>\n )}\n </div>\n </AlertDialogHeader>\n <AlertDialogFooter className={CONFIRM_DIALOG_FOOTER}>\n {/* aria-disabled, not disabled: a disabled button that holds focus drops it to <body> and Tab leaves the dialog. */}\n <button\n type=\"button\"\n aria-disabled={pending}\n onClick={() => change(false)}\n className={cn(buttonVariants({ variant: \"ghost\", size: \"xs\" }), CONFIRM_DIALOG_PENDING)}\n >\n {labels.cancel ?? \"Cancel\"}\n </button>\n <button\n type=\"button\"\n aria-disabled={pending}\n aria-busy={pending}\n onClick={confirm}\n className={cn(buttonVariants({ variant: danger ? \"destructive\" : \"primary\", size: \"xs\" }), CONFIRM_DIALOG_PENDING)}\n >\n {pending && <Spinner className={CONFIRM_DIALOG_SPINNER} />}\n {confirmLabel}\n </button>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/derived/confirm-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport {\n CONFIRM_DIALOG_CONTENT,\n CONFIRM_DIALOG_DESCRIPTION,\n CONFIRM_DIALOG_ERROR,\n CONFIRM_DIALOG_FOOTER,\n CONFIRM_DIALOG_HEADER,\n CONFIRM_DIALOG_ICON,\n CONFIRM_DIALOG_PENDING,\n CONFIRM_DIALOG_SPINNER,\n CONFIRM_DIALOG_TEXT,\n CONFIRM_DIALOG_TITLE,\n CONFIRM_DIALOG_LABELS,\n} from \"../../generated/confirm-dialog\";\nimport { toneClasses, type Tone } from \"../../generated/tone\";\nimport { useControllableState } from \"../../primitives/use-controllable-state\";\nimport {\n AlertDialog,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"../atomic/alert-dialog\";\nimport { buttonVariants } from \"../atomic/button\";\nimport { Spinner } from \"../atomic/spinner\";\nimport { UiIcon } from \"../../icons/ui-icons\";\n\nexport interface ConfirmDialogLabels {\n cancel?: string;\n /** Shown when `onConfirm` rejects with something that has no message. */\n error?: string;\n}\n\nexport interface ConfirmDialogProps {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Opens the dialog; wrapped with `asChild`, so pass one button. */\n trigger?: React.ReactNode;\n title: React.ReactNode;\n description?: React.ReactNode;\n tone?: Tone;\n confirmLabel: React.ReactNode;\n /**\n * Resolve to close the dialog. While a returned promise is pending both\n * buttons are disabled and Escape and outside clicks do nothing; a rejection\n * keeps the dialog open and shows its message under the text.\n */\n onConfirm: () => void | Promise<void>;\n /** Replaces the tone's glyph. */\n icon?: React.ReactNode;\n labels?: ConfirmDialogLabels;\n className?: string;\n}\n\nexport function ConfirmDialog({\n open,\n defaultOpen = false,\n onOpenChange,\n trigger,\n title,\n description,\n tone = \"neutral\",\n confirmLabel,\n onConfirm,\n icon,\n labels = {},\n className,\n}: ConfirmDialogProps) {\n const [isOpen, setOpen] = useControllableState<boolean>({\n ...(open !== undefined ? { value: open } : {}),\n defaultValue: defaultOpen,\n ...(onOpenChange ? { onChange: onOpenChange } : {}),\n });\n const [pending, setPending] = React.useState(false);\n const [error, setError] = React.useState<string | null>(null);\n const danger = tone === \"error\";\n // A controlled parent can reopen the dialog without going through `change`.\n React.useEffect(() => {\n if (isOpen) setError(null);\n }, [isOpen]);\n\n const change = (next: boolean) => {\n if (pending) return;\n if (next) setError(null);\n setOpen(next);\n };\n\n const confirm = async () => {\n if (pending) return;\n setError(null);\n setPending(true);\n try {\n await onConfirm();\n setPending(false);\n setOpen(false);\n } catch (e) {\n setPending(false);\n setError(e instanceof Error && e.message ? e.message : (labels.error ?? CONFIRM_DIALOG_LABELS.error));\n }\n };\n\n return (\n <AlertDialog open={isOpen} onOpenChange={change}>\n {trigger != null && <AlertDialogTrigger asChild>{trigger}</AlertDialogTrigger>}\n <AlertDialogContent className={cn(CONFIRM_DIALOG_CONTENT, toneClasses[tone], className)}>\n <AlertDialogHeader className={CONFIRM_DIALOG_HEADER}>\n <span className={CONFIRM_DIALOG_ICON}>\n {icon ?? <UiIcon name=\"alert\" />}\n </span>\n <div className={CONFIRM_DIALOG_TEXT}>\n <AlertDialogTitle className={CONFIRM_DIALOG_TITLE}>{title}</AlertDialogTitle>\n {description != null && (\n <AlertDialogDescription className={CONFIRM_DIALOG_DESCRIPTION}>{description}</AlertDialogDescription>\n )}\n {error !== null && (\n <p role=\"alert\" className={CONFIRM_DIALOG_ERROR}>\n {error}\n </p>\n )}\n </div>\n </AlertDialogHeader>\n <AlertDialogFooter className={CONFIRM_DIALOG_FOOTER}>\n {/* aria-disabled, not disabled: a disabled button that holds focus drops it to <body> and Tab leaves the dialog. */}\n <button\n type=\"button\"\n aria-disabled={pending}\n onClick={() => change(false)}\n className={cn(buttonVariants({ variant: \"ghost\", size: \"xs\" }), CONFIRM_DIALOG_PENDING)}\n >\n {labels.cancel ?? CONFIRM_DIALOG_LABELS.cancel}\n </button>\n <button\n type=\"button\"\n aria-disabled={pending}\n aria-busy={pending}\n onClick={confirm}\n className={cn(buttonVariants({ variant: danger ? \"destructive\" : \"primary\", size: \"xs\" }), CONFIRM_DIALOG_PENDING)}\n >\n {pending && <Spinner className={CONFIRM_DIALOG_SPINNER} />}\n {confirmLabel}\n </button>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n );\n}\n"],"mappings":"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","names":[]}
@@ -14,14 +14,10 @@ import {
14
14
  DATE_TIME_PICKER_TIME,
15
15
  DATE_TIME_PICKER_TIME_INPUT,
16
16
  DATE_TIME_PICKER_TIME_SEPARATOR,
17
- DATE_TIME_PICKER_TRIGGER
17
+ DATE_TIME_PICKER_TRIGGER,
18
+ DATE_TIME_PICKER_LABELS
18
19
  } from "../../generated/date-time-picker.js";
19
- const CALENDAR_ICON = [
20
- "M8 2v4",
21
- "M16 2v4",
22
- "M3 10h18",
23
- "M5 4h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z"
24
- ];
20
+ import { iconShapes } from "../../icons/icon-shapes.js";
25
21
  function CalendarIcon() {
26
22
  return /* @__PURE__ */ jsx(
27
23
  "svg",
@@ -37,7 +33,7 @@ function CalendarIcon() {
37
33
  strokeLinecap: "round",
38
34
  strokeLinejoin: "round",
39
35
  "aria-hidden": true,
40
- children: CALENDAR_ICON.map((d) => /* @__PURE__ */ jsx("path", { d }, d))
36
+ children: iconShapes("calendar")
41
37
  }
42
38
  );
43
39
  }
@@ -56,7 +52,7 @@ function XIcon() {
56
52
  strokeLinecap: "round",
57
53
  strokeLinejoin: "round",
58
54
  "aria-hidden": true,
59
- children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" })
55
+ children: iconShapes("x")
60
56
  }
61
57
  );
62
58
  }
@@ -214,7 +210,7 @@ function DateTimePicker({
214
210
  {
215
211
  "data-slot": "date-time-picker-content",
216
212
  role: "dialog",
217
- "aria-label": labels.dialog ?? "Choose date and time",
213
+ "aria-label": labels.dialog ?? DATE_TIME_PICKER_LABELS.dialog,
218
214
  align,
219
215
  onBlur: onContentBlur,
220
216
  onKeyDown: onContentKeyDown,
@@ -245,7 +241,7 @@ function DateTimePicker({
245
241
  className: DATE_TIME_PICKER_TIME_INPUT,
246
242
  ref: hoursRef,
247
243
  "data-slot": "date-time-picker-hours",
248
- "aria-label": labels.hours ?? "Hours",
244
+ "aria-label": labels.hours ?? DATE_TIME_PICKER_LABELS.hours,
249
245
  value: pad(value?.getHours() ?? 0),
250
246
  disabled,
251
247
  onChange: onHours
@@ -260,7 +256,7 @@ function DateTimePicker({
260
256
  onFocus: selectAll,
261
257
  className: DATE_TIME_PICKER_TIME_INPUT,
262
258
  "data-slot": "date-time-picker-minutes",
263
- "aria-label": labels.minutes ?? "Minutes",
259
+ "aria-label": labels.minutes ?? DATE_TIME_PICKER_LABELS.minutes,
264
260
  value: pad(value?.getMinutes() ?? 0),
265
261
  disabled,
266
262
  onChange: onMinutes
@@ -274,7 +270,7 @@ function DateTimePicker({
274
270
  "data-slot": "date-time-picker-clear",
275
271
  disabled,
276
272
  onClick: onClear,
277
- children: labels.clear ?? "Clear"
273
+ children: labels.clear ?? DATE_TIME_PICKER_LABELS.clear
278
274
  }
279
275
  ),
280
276
  /* @__PURE__ */ jsx(
@@ -283,7 +279,7 @@ function DateTimePicker({
283
279
  type: "button",
284
280
  className: buttonVariants({ variant: "ghost", size: "sm", icon: true }),
285
281
  "data-slot": "date-time-picker-close",
286
- "aria-label": labels.close ?? "Close",
282
+ "aria-label": labels.close ?? DATE_TIME_PICKER_LABELS.close,
287
283
  disabled,
288
284
  onClick: () => setOpen(false),
289
285
  children: /* @__PURE__ */ jsx(XIcon, {})
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/derived/date-time-picker.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { focusCandidates } from \"../../primitives/focus-scope\";\nimport { useControllableState } from \"../../primitives/use-controllable-state\";\nimport { buttonVariants } from \"../atomic/button\";\nimport { Calendar } from \"../atomic/calendar\";\nimport { Input } from \"../atomic/input\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../atomic/popover\";\nimport {\n DATE_TIME_PICKER_CLEAR,\n DATE_TIME_PICKER_CONTENT,\n DATE_TIME_PICKER_TIME,\n DATE_TIME_PICKER_TIME_INPUT,\n DATE_TIME_PICKER_TIME_SEPARATOR,\n DATE_TIME_PICKER_TRIGGER,\n} from \"../../generated/date-time-picker\";\n\n// lucide `calendar`, inlined per the kit's no-icon-dep convention.\nconst CALENDAR_ICON = [\n \"M8 2v4\",\n \"M16 2v4\",\n \"M3 10h18\",\n \"M5 4h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z\",\n] as const;\n\nfunction CalendarIcon() {\n return (\n <svg\n className=\"size-4\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n >\n {CALENDAR_ICON.map(d => (\n <path key={d} d={d} />\n ))}\n </svg>\n );\n}\n\n// lucide `x`, inlined like every other icon in the kit.\nfunction XIcon() {\n return (\n <svg\n className=\"size-4\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n >\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n );\n}\n\nconst pad = (n: number): string => String(n).padStart(2, \"0\");\n\n// The value always carries whole minutes: seconds/ms are dropped on every write.\nfunction atMinute(d: Date): Date {\n return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes());\n}\n\n/** Inclusive clamp at minute precision. */\nfunction clampMoment(d: Date, min: Date | undefined, max: Date | undefined): Date {\n const lo = min && atMinute(min);\n const hi = max && atMinute(max);\n if (lo && d.getTime() < lo.getTime()) return lo;\n if (hi && d.getTime() > hi.getTime()) return hi;\n return d;\n}\n\n/**\n * Parses the digits an operator typed into an hours/minutes field. `null`\n * (nothing typed, or no digit at all) keeps the last value.\n *\n * The LAST two digits win: the field is controlled, so what the browser hands\n * over is the old value plus the keystroke (\"01\" + \"5\" = \"015\"), and the\n * freshest digits are the ones the operator meant.\n */\nfunction parseField(raw: string, max: number): number | null {\n const digits = raw.replace(/\\D/g, \"\").slice(-2);\n if (digits === \"\") return null;\n return Math.min(Number(digits), max);\n}\n\n// A focused field is replaced, not appended to: with the whole value selected,\n// \"1\" then \"5\" reads as 15.\nconst selectAll = (e: React.FocusEvent<HTMLInputElement>) => e.currentTarget.select();\n\nfunction isoLabel(d: Date): string {\n return `${d.getFullYear().toString().padStart(4, \"0\")}-${pad(d.getMonth() + 1)}-${pad(\n d.getDate(),\n )} ${pad(d.getHours())}:${pad(d.getMinutes())}`;\n}\n\n/** The picker's own strings; every one defaults to English. */\nexport interface DateTimePickerLabels {\n /** `aria-label` of the calendar's previous-month button; \"Previous month\". */\n previousMonth?: string;\n /** `aria-label` of the calendar's next-month button; \"Next month\". */\n nextMonth?: string;\n /** `aria-label` of the hours input; \"Hours\". */\n hours?: string;\n /** `aria-label` of the minutes input; \"Minutes\". */\n minutes?: string;\n /** Text of the clear button; \"Clear\". */\n clear?: string;\n /** `aria-label` of the popover dialog; \"Choose date and time\". */\n dialog?: string;\n /** `aria-label` of the close button; \"Close\". */\n close?: string;\n}\n\nexport interface DateTimePickerProps\n extends React.AriaAttributes,\n Pick<React.ComponentProps<\"button\">, \"onFocus\" | \"onBlur\"> {\n /** Controlled value; `null` = empty. Local-zone `Date` (seconds/ms are zeroed on every change). */\n value?: Date | null;\n /** Uncontrolled seed; default `null`. */\n defaultValue?: Date | null;\n onChange?: (value: Date | null) => void;\n /** Earliest allowed moment (inclusive, minute precision). */\n min?: Date;\n /** Latest allowed moment (inclusive, minute precision). */\n max?: Date;\n /**\n * BCP-47 tag for the trigger label and calendar captions (`Intl`). Absent →\n * `YYYY-MM-DD HH:MM` and English captions, like the Rust port.\n */\n locale?: string;\n /** Overrides the trigger label entirely (e.g. the cabinet's `formatMoment`). */\n format?: (value: Date) => string;\n /** Shown on the trigger while empty; default \"\". */\n placeholder?: string;\n labels?: DateTimePickerLabels;\n disabled?: boolean;\n /** Renders a hidden `<input name>` carrying unix seconds (\"\" when empty) for plain forms. */\n name?: string;\n /**\n * \"Today\" for the calendar highlight and as the day a typed time lands on\n * while empty; default `new Date()`.\n */\n today?: Date;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** `PopoverContent` alignment; default \"start\". */\n align?: \"start\" | \"center\" | \"end\";\n /** Fused onto the trigger. */\n className?: string;\n /** Put on the trigger, so a `FieldLabel`'s `htmlFor` reaches it. */\n id?: string;\n}\n\n/**\n * A date + time field over the kit's own bricks: an outline trigger opening a\n * popover with the `Calendar` and two numeric hours/minutes inputs — no native\n * `datetime-local`, so the browser's locale popup never appears.\n *\n * Every edit reports through `onChange`; the popover stays open after a day\n * click (the operator still sets the time) and closes on clear or on the close\n * button (which keeps the value). Opening moves focus into the hours field;\n * closing hands it back to the trigger unless the operator already focused\n * something else. Any other `aria-*` prop, `onFocus` and `onBlur` land on the\n * trigger.\n */\nexport function DateTimePicker({\n value: valueProp,\n defaultValue = null,\n onChange,\n min,\n max,\n locale,\n format,\n placeholder = \"\",\n labels = {},\n disabled = false,\n name,\n today = new Date(),\n open,\n defaultOpen = false,\n onOpenChange,\n align = \"start\",\n className,\n id,\n ...rest\n}: DateTimePickerProps) {\n const [value, setValue] = useControllableState<Date | null>({\n ...(valueProp !== undefined ? { value: valueProp } : {}),\n defaultValue,\n ...(onChange ? { onChange } : {}),\n });\n const [isOpen, setOpen] = useControllableState<boolean>({\n ...(open !== undefined ? { value: open } : {}),\n defaultValue: defaultOpen,\n ...(onOpenChange ? { onChange: onOpenChange } : {}),\n });\n\n const rootRef = React.useRef<HTMLDivElement | null>(null);\n const hoursRef = React.useRef<HTMLInputElement | null>(null);\n const focusTrigger = () =>\n rootRef.current?.querySelector<HTMLElement>(\"[data-slot=date-time-picker-trigger]\")?.focus();\n // The content lives in a Portal, so the native tab order would skip it.\n React.useEffect(() => {\n if (!isOpen) return;\n hoursRef.current?.focus();\n return () => {\n const active = document.activeElement;\n const content = hoursRef.current?.closest(\"[data-slot=date-time-picker-content]\");\n const lost = !active || active === document.body || !!content?.contains(active);\n if (lost) focusTrigger();\n };\n }, [isOpen]);\n\n const emit = (next: Date) => setValue(clampMoment(atMinute(next), min, max));\n // A fresh copy of the moment a typed time edits: the value, or midnight of\n // `today` while empty — never the consumer's own `Date` instance.\n const base = () =>\n value\n ? new Date(value.getTime())\n : new Date(today.getFullYear(), today.getMonth(), today.getDate());\n\n const onSelect = (day: Date) =>\n emit(\n new Date(\n day.getFullYear(),\n day.getMonth(),\n day.getDate(),\n value?.getHours() ?? 0,\n value?.getMinutes() ?? 0,\n ),\n );\n const onHours = (e: React.ChangeEvent<HTMLInputElement>) => {\n const hour = parseField(e.target.value, 23);\n if (hour === null) return;\n const next = base();\n next.setHours(hour);\n emit(next);\n };\n const onMinutes = (e: React.ChangeEvent<HTMLInputElement>) => {\n const minute = parseField(e.target.value, 59);\n if (minute === null) return;\n const next = base();\n next.setMinutes(minute);\n emit(next);\n };\n const onClear = () => {\n setValue(null);\n setOpen(false);\n };\n // The content is portalled to the end of <body>, so Tab from its last\n // control (and Shift+Tab from its first) has nowhere to go: focus falls out\n // of the document and the dialog stays open over the page. Those two edges\n // close the popover and hand focus back to the trigger — the document's tab\n // order then continues from where the operator started. Middle controls keep\n // the browser's default. Not a trap: the popover is non-modal.\n const onContentKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key !== \"Tab\") return;\n const items = focusCandidates(e.currentTarget);\n const edge = e.shiftKey ? items[0] : items[items.length - 1];\n if (!edge || e.target !== edge) return;\n e.preventDefault();\n setOpen(false);\n focusTrigger();\n };\n // Focus moving elsewhere by pointer or script (the dismissable layer only\n // watches Escape and outside pointerdown). A null `relatedTarget` is the\n // window losing focus (alt-tab), not the operator leaving: keep the popover\n // for their return. Tab-out never reaches here — `onContentKeyDown` closes\n // first.\n const onContentBlur = (e: React.FocusEvent<HTMLDivElement>) => {\n const next = e.relatedTarget;\n if (!(next instanceof Node)) return;\n if (e.currentTarget.contains(next) || rootRef.current?.contains(next)) return;\n setOpen(false);\n };\n\n const label = value\n ? format\n ? format(value)\n : locale\n ? // The fields are 24-hour, so the label is too — even where the locale\n // would default to 12-hour (\"2:05 PM\" over a \"14\" hours field).\n new Intl.DateTimeFormat(locale, {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n hourCycle: \"h23\",\n }).format(value)\n : isoLabel(value)\n : placeholder;\n\n return (\n <div data-slot=\"date-time-picker\" ref={rootRef}>\n <Popover open={isOpen} onOpenChange={setOpen}>\n <PopoverTrigger\n type=\"button\"\n data-slot=\"date-time-picker-trigger\"\n data-placeholder={value ? undefined : \"true\"}\n aria-haspopup=\"dialog\"\n className={cn(\n buttonVariants({ variant: \"outline\", size: \"md\" }),\n DATE_TIME_PICKER_TRIGGER,\n className,\n )}\n disabled={disabled}\n {...(id !== undefined ? { id } : {})}\n {...rest}\n >\n <CalendarIcon />\n <span>{label}</span>\n </PopoverTrigger>\n {name !== undefined && (\n <input\n type=\"hidden\"\n name={name}\n value={value ? String(Math.floor(value.getTime() / 1000)) : \"\"}\n />\n )}\n <PopoverContent\n data-slot=\"date-time-picker-content\"\n role=\"dialog\"\n aria-label={labels.dialog ?? \"Choose date and time\"}\n align={align}\n onBlur={onContentBlur}\n onKeyDown={onContentKeyDown}\n className={DATE_TIME_PICKER_CONTENT}\n >\n <Calendar\n {...(value ? { selected: value } : {})}\n onSelect={onSelect}\n // The content remounts on every open, so this lands on the value's month.\n defaultMonth={value ?? min ?? today}\n today={today}\n disabled={disabled}\n {...(min ? { min } : {})}\n {...(max ? { max } : {})}\n {...(locale !== undefined ? { locale } : {})}\n {...(labels.previousMonth !== undefined\n ? { previousMonthLabel: labels.previousMonth }\n : {})}\n {...(labels.nextMonth !== undefined ? { nextMonthLabel: labels.nextMonth } : {})}\n />\n <div className={DATE_TIME_PICKER_TIME} data-slot=\"date-time-picker-time\">\n <Input\n type=\"text\"\n inputMode=\"numeric\"\n onFocus={selectAll}\n className={DATE_TIME_PICKER_TIME_INPUT}\n ref={hoursRef}\n data-slot=\"date-time-picker-hours\"\n aria-label={labels.hours ?? \"Hours\"}\n value={pad(value?.getHours() ?? 0)}\n disabled={disabled}\n onChange={onHours}\n />\n <span className={DATE_TIME_PICKER_TIME_SEPARATOR} aria-hidden>\n :\n </span>\n <Input\n type=\"text\"\n inputMode=\"numeric\"\n onFocus={selectAll}\n className={DATE_TIME_PICKER_TIME_INPUT}\n data-slot=\"date-time-picker-minutes\"\n aria-label={labels.minutes ?? \"Minutes\"}\n value={pad(value?.getMinutes() ?? 0)}\n disabled={disabled}\n onChange={onMinutes}\n />\n <button\n type=\"button\"\n className={buttonVariants({ variant: \"ghost\", size: \"sm\", className: DATE_TIME_PICKER_CLEAR })}\n data-slot=\"date-time-picker-clear\"\n disabled={disabled}\n onClick={onClear}\n >\n {labels.clear ?? \"Clear\"}\n </button>\n <button\n type=\"button\"\n className={buttonVariants({ variant: \"ghost\", size: \"sm\", icon: true })}\n data-slot=\"date-time-picker-close\"\n aria-label={labels.close ?? \"Close\"}\n disabled={disabled}\n onClick={() => setOpen(false)}\n >\n <XIcon />\n </button>\n </div>\n </PopoverContent>\n </Popover>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/derived/date-time-picker.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { focusCandidates } from \"../../primitives/focus-scope\";\nimport { useControllableState } from \"../../primitives/use-controllable-state\";\nimport { buttonVariants } from \"../atomic/button\";\nimport { Calendar } from \"../atomic/calendar\";\nimport { Input } from \"../atomic/input\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../atomic/popover\";\nimport {\n DATE_TIME_PICKER_CLEAR,\n DATE_TIME_PICKER_CONTENT,\n DATE_TIME_PICKER_TIME,\n DATE_TIME_PICKER_TIME_INPUT,\n DATE_TIME_PICKER_TIME_SEPARATOR,\n DATE_TIME_PICKER_TRIGGER,\n DATE_TIME_PICKER_LABELS,\n} from \"../../generated/date-time-picker\";\nimport { iconShapes } from \"../../icons/icon-shapes\";\n\nfunction CalendarIcon() {\n return (\n <svg\n className=\"size-4\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n >\n {iconShapes(\"calendar\")}\n </svg>\n );\n}\n\nfunction XIcon() {\n return (\n <svg\n className=\"size-4\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n >\n {iconShapes(\"x\")}\n </svg>\n );\n}\n\nconst pad = (n: number): string => String(n).padStart(2, \"0\");\n\n// The value always carries whole minutes: seconds/ms are dropped on every write.\nfunction atMinute(d: Date): Date {\n return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes());\n}\n\n/** Inclusive clamp at minute precision. */\nfunction clampMoment(d: Date, min: Date | undefined, max: Date | undefined): Date {\n const lo = min && atMinute(min);\n const hi = max && atMinute(max);\n if (lo && d.getTime() < lo.getTime()) return lo;\n if (hi && d.getTime() > hi.getTime()) return hi;\n return d;\n}\n\n/**\n * Parses the digits an operator typed into an hours/minutes field. `null`\n * (nothing typed, or no digit at all) keeps the last value.\n *\n * The LAST two digits win: the field is controlled, so what the browser hands\n * over is the old value plus the keystroke (\"01\" + \"5\" = \"015\"), and the\n * freshest digits are the ones the operator meant.\n */\nfunction parseField(raw: string, max: number): number | null {\n const digits = raw.replace(/\\D/g, \"\").slice(-2);\n if (digits === \"\") return null;\n return Math.min(Number(digits), max);\n}\n\n// A focused field is replaced, not appended to: with the whole value selected,\n// \"1\" then \"5\" reads as 15.\nconst selectAll = (e: React.FocusEvent<HTMLInputElement>) => e.currentTarget.select();\n\nfunction isoLabel(d: Date): string {\n return `${d.getFullYear().toString().padStart(4, \"0\")}-${pad(d.getMonth() + 1)}-${pad(\n d.getDate(),\n )} ${pad(d.getHours())}:${pad(d.getMinutes())}`;\n}\n\n/** The picker's own strings; every one defaults to English. */\nexport interface DateTimePickerLabels {\n /** `aria-label` of the calendar's previous-month button; \"Previous month\". */\n previousMonth?: string;\n /** `aria-label` of the calendar's next-month button; \"Next month\". */\n nextMonth?: string;\n /** `aria-label` of the hours input; \"Hours\". */\n hours?: string;\n /** `aria-label` of the minutes input; \"Minutes\". */\n minutes?: string;\n /** Text of the clear button; \"Clear\". */\n clear?: string;\n /** `aria-label` of the popover dialog; \"Choose date and time\". */\n dialog?: string;\n /** `aria-label` of the close button; \"Close\". */\n close?: string;\n}\n\nexport interface DateTimePickerProps\n extends React.AriaAttributes,\n Pick<React.ComponentProps<\"button\">, \"onFocus\" | \"onBlur\"> {\n /** Controlled value; `null` = empty. Local-zone `Date` (seconds/ms are zeroed on every change). */\n value?: Date | null;\n /** Uncontrolled seed; default `null`. */\n defaultValue?: Date | null;\n onChange?: (value: Date | null) => void;\n /** Earliest allowed moment (inclusive, minute precision). */\n min?: Date;\n /** Latest allowed moment (inclusive, minute precision). */\n max?: Date;\n /**\n * BCP-47 tag for the trigger label and calendar captions (`Intl`). Absent →\n * `YYYY-MM-DD HH:MM` and English captions, like the Rust port.\n */\n locale?: string;\n /** Overrides the trigger label entirely (e.g. the cabinet's `formatMoment`). */\n format?: (value: Date) => string;\n /** Shown on the trigger while empty; default \"\". */\n placeholder?: string;\n labels?: DateTimePickerLabels;\n disabled?: boolean;\n /** Renders a hidden `<input name>` carrying unix seconds (\"\" when empty) for plain forms. */\n name?: string;\n /**\n * \"Today\" for the calendar highlight and as the day a typed time lands on\n * while empty; default `new Date()`.\n */\n today?: Date;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** `PopoverContent` alignment; default \"start\". */\n align?: \"start\" | \"center\" | \"end\";\n /** Fused onto the trigger. */\n className?: string;\n /** Put on the trigger, so a `FieldLabel`'s `htmlFor` reaches it. */\n id?: string;\n}\n\n/**\n * A date + time field over the kit's own bricks: an outline trigger opening a\n * popover with the `Calendar` and two numeric hours/minutes inputs — no native\n * `datetime-local`, so the browser's locale popup never appears.\n *\n * Every edit reports through `onChange`; the popover stays open after a day\n * click (the operator still sets the time) and closes on clear or on the close\n * button (which keeps the value). Opening moves focus into the hours field;\n * closing hands it back to the trigger unless the operator already focused\n * something else. Any other `aria-*` prop, `onFocus` and `onBlur` land on the\n * trigger.\n */\nexport function DateTimePicker({\n value: valueProp,\n defaultValue = null,\n onChange,\n min,\n max,\n locale,\n format,\n placeholder = \"\",\n labels = {},\n disabled = false,\n name,\n today = new Date(),\n open,\n defaultOpen = false,\n onOpenChange,\n align = \"start\",\n className,\n id,\n ...rest\n}: DateTimePickerProps) {\n const [value, setValue] = useControllableState<Date | null>({\n ...(valueProp !== undefined ? { value: valueProp } : {}),\n defaultValue,\n ...(onChange ? { onChange } : {}),\n });\n const [isOpen, setOpen] = useControllableState<boolean>({\n ...(open !== undefined ? { value: open } : {}),\n defaultValue: defaultOpen,\n ...(onOpenChange ? { onChange: onOpenChange } : {}),\n });\n\n const rootRef = React.useRef<HTMLDivElement | null>(null);\n const hoursRef = React.useRef<HTMLInputElement | null>(null);\n const focusTrigger = () =>\n rootRef.current?.querySelector<HTMLElement>(\"[data-slot=date-time-picker-trigger]\")?.focus();\n // The content lives in a Portal, so the native tab order would skip it.\n React.useEffect(() => {\n if (!isOpen) return;\n hoursRef.current?.focus();\n return () => {\n const active = document.activeElement;\n const content = hoursRef.current?.closest(\"[data-slot=date-time-picker-content]\");\n const lost = !active || active === document.body || !!content?.contains(active);\n if (lost) focusTrigger();\n };\n }, [isOpen]);\n\n const emit = (next: Date) => setValue(clampMoment(atMinute(next), min, max));\n // A fresh copy of the moment a typed time edits: the value, or midnight of\n // `today` while empty — never the consumer's own `Date` instance.\n const base = () =>\n value\n ? new Date(value.getTime())\n : new Date(today.getFullYear(), today.getMonth(), today.getDate());\n\n const onSelect = (day: Date) =>\n emit(\n new Date(\n day.getFullYear(),\n day.getMonth(),\n day.getDate(),\n value?.getHours() ?? 0,\n value?.getMinutes() ?? 0,\n ),\n );\n const onHours = (e: React.ChangeEvent<HTMLInputElement>) => {\n const hour = parseField(e.target.value, 23);\n if (hour === null) return;\n const next = base();\n next.setHours(hour);\n emit(next);\n };\n const onMinutes = (e: React.ChangeEvent<HTMLInputElement>) => {\n const minute = parseField(e.target.value, 59);\n if (minute === null) return;\n const next = base();\n next.setMinutes(minute);\n emit(next);\n };\n const onClear = () => {\n setValue(null);\n setOpen(false);\n };\n // The content is portalled to the end of <body>, so Tab from its last\n // control (and Shift+Tab from its first) has nowhere to go: focus falls out\n // of the document and the dialog stays open over the page. Those two edges\n // close the popover and hand focus back to the trigger — the document's tab\n // order then continues from where the operator started. Middle controls keep\n // the browser's default. Not a trap: the popover is non-modal.\n const onContentKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key !== \"Tab\") return;\n const items = focusCandidates(e.currentTarget);\n const edge = e.shiftKey ? items[0] : items[items.length - 1];\n if (!edge || e.target !== edge) return;\n e.preventDefault();\n setOpen(false);\n focusTrigger();\n };\n // Focus moving elsewhere by pointer or script (the dismissable layer only\n // watches Escape and outside pointerdown). A null `relatedTarget` is the\n // window losing focus (alt-tab), not the operator leaving: keep the popover\n // for their return. Tab-out never reaches here — `onContentKeyDown` closes\n // first.\n const onContentBlur = (e: React.FocusEvent<HTMLDivElement>) => {\n const next = e.relatedTarget;\n if (!(next instanceof Node)) return;\n if (e.currentTarget.contains(next) || rootRef.current?.contains(next)) return;\n setOpen(false);\n };\n\n const label = value\n ? format\n ? format(value)\n : locale\n ? // The fields are 24-hour, so the label is too — even where the locale\n // would default to 12-hour (\"2:05 PM\" over a \"14\" hours field).\n new Intl.DateTimeFormat(locale, {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n hourCycle: \"h23\",\n }).format(value)\n : isoLabel(value)\n : placeholder;\n\n return (\n <div data-slot=\"date-time-picker\" ref={rootRef}>\n <Popover open={isOpen} onOpenChange={setOpen}>\n <PopoverTrigger\n type=\"button\"\n data-slot=\"date-time-picker-trigger\"\n data-placeholder={value ? undefined : \"true\"}\n aria-haspopup=\"dialog\"\n className={cn(\n buttonVariants({ variant: \"outline\", size: \"md\" }),\n DATE_TIME_PICKER_TRIGGER,\n className,\n )}\n disabled={disabled}\n {...(id !== undefined ? { id } : {})}\n {...rest}\n >\n <CalendarIcon />\n <span>{label}</span>\n </PopoverTrigger>\n {name !== undefined && (\n <input\n type=\"hidden\"\n name={name}\n value={value ? String(Math.floor(value.getTime() / 1000)) : \"\"}\n />\n )}\n <PopoverContent\n data-slot=\"date-time-picker-content\"\n role=\"dialog\"\n aria-label={labels.dialog ?? DATE_TIME_PICKER_LABELS.dialog}\n align={align}\n onBlur={onContentBlur}\n onKeyDown={onContentKeyDown}\n className={DATE_TIME_PICKER_CONTENT}\n >\n <Calendar\n {...(value ? { selected: value } : {})}\n onSelect={onSelect}\n // The content remounts on every open, so this lands on the value's month.\n defaultMonth={value ?? min ?? today}\n today={today}\n disabled={disabled}\n {...(min ? { min } : {})}\n {...(max ? { max } : {})}\n {...(locale !== undefined ? { locale } : {})}\n {...(labels.previousMonth !== undefined\n ? { previousMonthLabel: labels.previousMonth }\n : {})}\n {...(labels.nextMonth !== undefined ? { nextMonthLabel: labels.nextMonth } : {})}\n />\n <div className={DATE_TIME_PICKER_TIME} data-slot=\"date-time-picker-time\">\n <Input\n type=\"text\"\n inputMode=\"numeric\"\n onFocus={selectAll}\n className={DATE_TIME_PICKER_TIME_INPUT}\n ref={hoursRef}\n data-slot=\"date-time-picker-hours\"\n aria-label={labels.hours ?? DATE_TIME_PICKER_LABELS.hours}\n value={pad(value?.getHours() ?? 0)}\n disabled={disabled}\n onChange={onHours}\n />\n <span className={DATE_TIME_PICKER_TIME_SEPARATOR} aria-hidden>\n :\n </span>\n <Input\n type=\"text\"\n inputMode=\"numeric\"\n onFocus={selectAll}\n className={DATE_TIME_PICKER_TIME_INPUT}\n data-slot=\"date-time-picker-minutes\"\n aria-label={labels.minutes ?? DATE_TIME_PICKER_LABELS.minutes}\n value={pad(value?.getMinutes() ?? 0)}\n disabled={disabled}\n onChange={onMinutes}\n />\n <button\n type=\"button\"\n className={buttonVariants({ variant: \"ghost\", size: \"sm\", className: DATE_TIME_PICKER_CLEAR })}\n data-slot=\"date-time-picker-clear\"\n disabled={disabled}\n onClick={onClear}\n >\n {labels.clear ?? DATE_TIME_PICKER_LABELS.clear}\n </button>\n <button\n type=\"button\"\n className={buttonVariants({ variant: \"ghost\", size: \"sm\", icon: true })}\n data-slot=\"date-time-picker-close\"\n aria-label={labels.close ?? DATE_TIME_PICKER_LABELS.close}\n disabled={disabled}\n onClick={() => setOpen(false)}\n >\n <XIcon />\n </button>\n </div>\n </PopoverContent>\n </Popover>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/derived/field.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { Label } from \"../atomic/label\";\nimport { walkElements } from \"../../primitives/walk-elements\";\nimport { isLabelable, markLabelable } from \"../../primitives/labelable\";\nimport { FieldControlContext, useFieldClaims } from \"../atomic/field-context\";\nimport {\n FIELD_BASE,\n FIELD_SET,\n FIELD_LEGEND,\n FIELD_GROUP,\n FIELD_CONTENT,\n FIELD_LABEL,\n FIELD_TITLE,\n FIELD_DESCRIPTION,\n FIELD_SEPARATOR,\n FIELD_SEPARATOR_LINE,\n FIELD_SEPARATOR_CONTENT,\n FIELD_ERROR,\n fieldOrientation,\n type FieldOrientation,\n} from \"../../generated/field\";\n\nexport type { FieldOrientation };\n\nexport function FieldSet({ className, ...props }: React.ComponentProps<\"fieldset\">) {\n return (\n <fieldset\n data-slot=\"field-set\"\n className={cn(FIELD_SET, className)}\n {...props}\n />\n );\n}\n\nexport function FieldLegend({\n className,\n variant = \"legend\",\n ...props\n}: React.ComponentProps<\"legend\"> & { variant?: \"legend\" | \"label\" }) {\n return (\n <legend\n data-slot=\"field-legend\"\n data-variant={variant}\n className={cn(FIELD_LEGEND, className)}\n {...props}\n />\n );\n}\n\nexport function FieldGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-group\"\n className={cn(FIELD_GROUP, className)}\n {...props}\n />\n );\n}\n\n/**\n * A labelled control. `Field` mints one id and hands it to both ends: its\n * `FieldLabel` takes it as `for`, and the kit's `Input`, `Textarea`,\n * `NativeSelect`, `SelectTrigger`, `Checkbox` and `Switch` take it as `id` —\n * each only when the caller passed none. `controlId` names the id instead of\n * minting one. One control per `Field`: a field that holds two has to name\n * their ids by hand, or both would claim the one id (a development warning\n * says so).\n */\nexport function Field({\n className,\n orientation = \"vertical\",\n controlId,\n ...props\n}: React.ComponentProps<\"div\"> & { orientation?: FieldOrientation; controlId?: string }) {\n const minted = React.useId();\n const claim = useFieldClaims();\n const id = controlId ?? minted;\n const control = React.useMemo(() => ({ id, claim }), [id, claim]);\n return (\n <FieldControlContext.Provider value={control}>\n <div\n role=\"group\"\n data-slot=\"field\"\n data-orientation={orientation}\n className={cn(FIELD_BASE, fieldOrientation[orientation], className)}\n {...props}\n />\n </FieldControlContext.Provider>\n );\n}\n\nmarkLabelable(Field);\n\nexport function FieldContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-content\"\n className={cn(FIELD_CONTENT, className)}\n {...props}\n />\n );\n}\n\nexport interface FieldLabelProps extends Omit<React.ComponentProps<typeof Label>, \"htmlFor\"> {\n /** `null` opts out of the `Field`'s id: the label then has no `for` at all. */\n htmlFor?: string | null;\n}\n\n/**\n * Takes its `Field`'s id as `for` unless it wraps a control itself — a label\n * around an `<input>` already labels it, and a `for` pointing elsewhere would\n * steal the click. A control inside a component of yours is invisible to that\n * check; pass `htmlFor={null}` there.\n */\nexport function FieldLabel({ className, htmlFor, children, ...props }: FieldLabelProps) {\n const field = React.useContext(FieldControlContext);\n const target = htmlFor === null ? undefined : (htmlFor ?? (wrapsControl(children) ? undefined : field?.id));\n return (\n <Label\n data-slot=\"field-label\"\n htmlFor={target}\n className={cn(FIELD_LABEL, className)}\n {...props}\n >\n {children}\n </Label>\n );\n}\n\n// The labelable elements (HTML's list, less `output`/`meter`/`progress`, which a\n// field label never wraps) and the kit's controls that render one — plus a\n// nested `Field`, the choice-card shape, whose control is labelled by its own.\n// The kit's controls carry a mark (`primitives/labelable`) rather than sitting\n// in a set here: a set would import every control into every page with a Field.\nconst LABELABLE_TAGS = new Set([\"input\", \"select\", \"textarea\", \"button\"]);\n\nfunction wrapsControl(children: React.ReactNode): boolean {\n let found = false;\n walkElements(children, (element) => {\n if (found) return false;\n const { type } = element;\n const props = element.props as { type?: unknown };\n if (typeof type === \"string\" ? LABELABLE_TAGS.has(type) && props.type !== \"hidden\" : isLabelable(type)) {\n found = true;\n }\n return !found;\n });\n return found;\n}\n\nexport function FieldTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-label\"\n className={cn(FIELD_TITLE, className)}\n {...props}\n />\n );\n}\n\nexport function FieldDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n return (\n <p\n data-slot=\"field-description\"\n className={cn(FIELD_DESCRIPTION, className)}\n {...props}\n />\n );\n}\n\nexport function FieldSeparator({\n children,\n className,\n ...props\n}: React.ComponentProps<\"div\"> & { children?: React.ReactNode }) {\n return (\n <div\n data-slot=\"field-separator\"\n data-content={!!children}\n className={cn(FIELD_SEPARATOR, className)}\n {...props}\n >\n <div role=\"separator\" className={FIELD_SEPARATOR_LINE} />\n {children && (\n <span\n className={FIELD_SEPARATOR_CONTENT}\n data-slot=\"field-separator-content\"\n >\n {children}\n </span>\n )}\n </div>\n );\n}\n\nexport function FieldError({\n className,\n children,\n errors,\n ...props\n}: React.ComponentProps<\"div\"> & {\n errors?: Array<{ message?: string } | undefined>;\n}) {\n const content = React.useMemo(() => {\n if (children) {\n return children;\n }\n\n if (!errors) {\n return null;\n }\n\n if (errors?.length === 1 && errors[0]?.message) {\n return errors[0].message;\n }\n\n return (\n <ul className=\"ml-4 flex list-disc flex-col gap-1\">\n {errors.map(\n (error, index) => error?.message && <li key={index}>{error.message}</li>,\n )}\n </ul>\n );\n }, [children, errors]);\n\n if (!content) {\n return null;\n }\n\n return (\n <div\n role=\"alert\"\n data-slot=\"field-error\"\n className={cn(FIELD_ERROR, className)}\n {...props}\n >\n {content}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/derived/field.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { Label } from \"../atomic/label\";\nimport { walkElements } from \"../../primitives/walk-elements\";\nimport { isLabelable, markLabelable } from \"../../primitives/labelable\";\nimport { FieldControlContext, useFieldClaims } from \"../atomic/field-context\";\nimport {\n FIELD_BASE,\n FIELD_SET,\n FIELD_LEGEND,\n FIELD_GROUP,\n FIELD_CONTENT,\n FIELD_LABEL,\n FIELD_TITLE,\n FIELD_DESCRIPTION,\n FIELD_SEPARATOR,\n FIELD_SEPARATOR_LINE,\n FIELD_SEPARATOR_CONTENT,\n FIELD_ERROR,\n fieldOrientation,\n type FieldOrientation,\n} from \"../../generated/field\";\nimport type { FieldLegendVariant } from \"../../generated/field\";\n\nexport type { FieldOrientation };\n\nexport function FieldSet({ className, ...props }: React.ComponentProps<\"fieldset\">) {\n return (\n <fieldset\n data-slot=\"field-set\"\n className={cn(FIELD_SET, className)}\n {...props}\n />\n );\n}\n\nexport function FieldLegend({\n className,\n variant = \"legend\",\n ...props\n}: React.ComponentProps<\"legend\"> & { variant?: FieldLegendVariant }) {\n return (\n <legend\n data-slot=\"field-legend\"\n data-variant={variant}\n className={cn(FIELD_LEGEND, className)}\n {...props}\n />\n );\n}\n\nexport function FieldGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-group\"\n className={cn(FIELD_GROUP, className)}\n {...props}\n />\n );\n}\n\n/**\n * A labelled control. `Field` mints one id and hands it to both ends: its\n * `FieldLabel` takes it as `for`, and the kit's `Input`, `Textarea`,\n * `NativeSelect`, `SelectTrigger`, `Checkbox` and `Switch` take it as `id` —\n * each only when the caller passed none. `controlId` names the id instead of\n * minting one. One control per `Field`: a field that holds two has to name\n * their ids by hand, or both would claim the one id (a development warning\n * says so).\n */\nexport function Field({\n className,\n orientation = \"vertical\",\n controlId,\n ...props\n}: React.ComponentProps<\"div\"> & { orientation?: FieldOrientation; controlId?: string }) {\n const minted = React.useId();\n const claim = useFieldClaims();\n const id = controlId ?? minted;\n const control = React.useMemo(() => ({ id, claim }), [id, claim]);\n return (\n <FieldControlContext.Provider value={control}>\n <div\n role=\"group\"\n data-slot=\"field\"\n data-orientation={orientation}\n className={cn(FIELD_BASE, fieldOrientation[orientation], className)}\n {...props}\n />\n </FieldControlContext.Provider>\n );\n}\n\nmarkLabelable(Field);\n\nexport function FieldContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-content\"\n className={cn(FIELD_CONTENT, className)}\n {...props}\n />\n );\n}\n\nexport interface FieldLabelProps extends Omit<React.ComponentProps<typeof Label>, \"htmlFor\"> {\n /** `null` opts out of the `Field`'s id: the label then has no `for` at all. */\n htmlFor?: string | null;\n}\n\n/**\n * Takes its `Field`'s id as `for` unless it wraps a control itself — a label\n * around an `<input>` already labels it, and a `for` pointing elsewhere would\n * steal the click. A control inside a component of yours is invisible to that\n * check; pass `htmlFor={null}` there.\n */\nexport function FieldLabel({ className, htmlFor, children, ...props }: FieldLabelProps) {\n const field = React.useContext(FieldControlContext);\n const target = htmlFor === null ? undefined : (htmlFor ?? (wrapsControl(children) ? undefined : field?.id));\n return (\n <Label\n data-slot=\"field-label\"\n htmlFor={target}\n className={cn(FIELD_LABEL, className)}\n {...props}\n >\n {children}\n </Label>\n );\n}\n\n// The labelable elements (HTML's list, less `output`/`meter`/`progress`, which a\n// field label never wraps) and the kit's controls that render one — plus a\n// nested `Field`, the choice-card shape, whose control is labelled by its own.\n// The kit's controls carry a mark (`primitives/labelable`) rather than sitting\n// in a set here: a set would import every control into every page with a Field.\nconst LABELABLE_TAGS = new Set([\"input\", \"select\", \"textarea\", \"button\"]);\n\nfunction wrapsControl(children: React.ReactNode): boolean {\n let found = false;\n walkElements(children, (element) => {\n if (found) return false;\n const { type } = element;\n const props = element.props as { type?: unknown };\n if (typeof type === \"string\" ? LABELABLE_TAGS.has(type) && props.type !== \"hidden\" : isLabelable(type)) {\n found = true;\n }\n return !found;\n });\n return found;\n}\n\nexport function FieldTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-label\"\n className={cn(FIELD_TITLE, className)}\n {...props}\n />\n );\n}\n\nexport function FieldDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n return (\n <p\n data-slot=\"field-description\"\n className={cn(FIELD_DESCRIPTION, className)}\n {...props}\n />\n );\n}\n\nexport function FieldSeparator({\n children,\n className,\n ...props\n}: React.ComponentProps<\"div\"> & { children?: React.ReactNode }) {\n return (\n <div\n data-slot=\"field-separator\"\n data-content={!!children}\n className={cn(FIELD_SEPARATOR, className)}\n {...props}\n >\n <div role=\"separator\" className={FIELD_SEPARATOR_LINE} />\n {children && (\n <span\n className={FIELD_SEPARATOR_CONTENT}\n data-slot=\"field-separator-content\"\n >\n {children}\n </span>\n )}\n </div>\n );\n}\n\nexport function FieldError({\n className,\n children,\n errors,\n ...props\n}: React.ComponentProps<\"div\"> & {\n errors?: Array<{ message?: string } | undefined>;\n}) {\n const content = React.useMemo(() => {\n if (children) {\n return children;\n }\n\n if (!errors) {\n return null;\n }\n\n if (errors?.length === 1 && errors[0]?.message) {\n return errors[0].message;\n }\n\n return (\n <ul className=\"ml-4 flex list-disc flex-col gap-1\">\n {errors.map(\n (error, index) => error?.message && <li key={index}>{error.message}</li>,\n )}\n </ul>\n );\n }, [children, errors]);\n\n if (!content) {\n return null;\n }\n\n return (\n <div\n role=\"alert\"\n data-slot=\"field-error\"\n className={cn(FIELD_ERROR, className)}\n {...props}\n >\n {content}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -38,7 +38,6 @@ function FormLabel({
38
38
  return /* @__PURE__ */ jsx(
39
39
  Label,
40
40
  {
41
- "data-slot": "form-label",
42
41
  "data-error": !!error,
43
42
  className: cn("data-[error=true]:text-accent-error", className),
44
43
  htmlFor: formItemId,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/derived/form.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { Label } from \"../atomic/label\";\nimport { Slot } from \"../../primitives/slot\";\nimport { FORM_DESCRIPTION, FORM_ITEM, FORM_MESSAGE } from \"../../generated/form\";\n\n/**\n * Dep-light, presentational form primitives. We keep the ARIA id-wiring of\n * shadcn's form (label/control/description/message share an id so\n * `aria-describedby`/`id` line up) but drop `react-hook-form`'s state engine:\n * validation and field state are the consumer's job. `FormItem` mints an id via\n * `React.useId` and exposes it through `FormItemContext`.\n */\ntype FormItemContextValue = {\n id: string;\n formItemId: string;\n formDescriptionId: string;\n formMessageId: string;\n};\n\nconst FormItemContext = React.createContext<FormItemContextValue | null>(null);\n\nfunction useFormItem(): FormItemContextValue {\n const ctx = React.useContext(FormItemContext);\n if (!ctx) {\n throw new Error(\"Form parts must be used within <FormItem>\");\n }\n return ctx;\n}\n\nexport function Form({ ...props }: React.ComponentProps<\"form\">) {\n return <form data-slot=\"form\" {...props} />;\n}\n\nexport function FormItem({ className, ...props }: React.ComponentProps<\"div\">) {\n const id = React.useId();\n const value = React.useMemo<FormItemContextValue>(\n () => ({\n id,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n }),\n [id],\n );\n\n return (\n <FormItemContext.Provider value={value}>\n <div data-slot=\"form-item\" className={cn(FORM_ITEM, className)} {...props} />\n </FormItemContext.Provider>\n );\n}\n\nexport function FormLabel({\n className,\n error,\n ...props\n}: React.ComponentProps<typeof Label> & { error?: boolean }) {\n const { formItemId } = useFormItem();\n\n return (\n <Label\n data-slot=\"form-label\"\n data-error={!!error}\n className={cn(\"data-[error=true]:text-accent-error\", className)}\n htmlFor={formItemId}\n {...props}\n />\n );\n}\n\nexport function FormControl({\n error,\n ...props\n}: React.ComponentProps<typeof Slot> & { error?: boolean }) {\n const { formItemId, formDescriptionId, formMessageId } = useFormItem();\n\n return (\n <Slot\n data-slot=\"form-control\"\n id={formItemId}\n aria-describedby={\n !error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`\n }\n aria-invalid={!!error}\n {...props}\n />\n );\n}\n\nexport function FormDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n const { formDescriptionId } = useFormItem();\n\n return (\n <p\n data-slot=\"form-description\"\n id={formDescriptionId}\n className={cn(FORM_DESCRIPTION, className)}\n {...props}\n />\n );\n}\n\nexport function FormMessage({ className, children, ...props }: React.ComponentProps<\"p\">) {\n const { formMessageId } = useFormItem();\n\n if (!children) {\n return null;\n }\n\n return (\n <p\n data-slot=\"form-message\"\n id={formMessageId}\n className={cn(FORM_MESSAGE, className)}\n {...props}\n >\n {children}\n </p>\n );\n}\n"],"mappings":";AAiCS;AA/BT,YAAY,WAAW;AACvB,SAAS,UAAU;AACnB,SAAS,aAAa;AACtB,SAAS,YAAY;AACrB,SAAS,kBAAkB,WAAW,oBAAoB;AAgB1D,MAAM,kBAAkB,MAAM,cAA2C,IAAI;AAE7E,SAAS,cAAoC;AAC3C,QAAM,MAAM,MAAM,WAAW,eAAe;AAC5C,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AACA,SAAO;AACT;AAEO,SAAS,KAAK,EAAE,GAAG,MAAM,GAAiC;AAC/D,SAAO,oBAAC,UAAK,aAAU,QAAQ,GAAG,OAAO;AAC3C;AAEO,SAAS,SAAS,EAAE,WAAW,GAAG,MAAM,GAAgC;AAC7E,QAAM,KAAK,MAAM,MAAM;AACvB,QAAM,QAAQ,MAAM;AAAA,IAClB,OAAO;AAAA,MACL;AAAA,MACA,YAAY,GAAG,EAAE;AAAA,MACjB,mBAAmB,GAAG,EAAE;AAAA,MACxB,eAAe,GAAG,EAAE;AAAA,IACtB;AAAA,IACA,CAAC,EAAE;AAAA,EACL;AAEA,SACE,oBAAC,gBAAgB,UAAhB,EAAyB,OACxB,8BAAC,SAAI,aAAU,aAAY,WAAW,GAAG,WAAW,SAAS,GAAI,GAAG,OAAO,GAC7E;AAEJ;AAEO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAA6D;AAC3D,QAAM,EAAE,WAAW,IAAI,YAAY;AAEnC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,cAAY,CAAC,CAAC;AAAA,MACd,WAAW,GAAG,uCAAuC,SAAS;AAAA,MAC9D,SAAS;AAAA,MACR,GAAG;AAAA;AAAA,EACN;AAEJ;AAEO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA,GAAG;AACL,GAA4D;AAC1D,QAAM,EAAE,YAAY,mBAAmB,cAAc,IAAI,YAAY;AAErE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,IAAI;AAAA,MACJ,oBACE,CAAC,QAAQ,GAAG,iBAAiB,KAAK,GAAG,iBAAiB,IAAI,aAAa;AAAA,MAEzE,gBAAc,CAAC,CAAC;AAAA,MACf,GAAG;AAAA;AAAA,EACN;AAEJ;AAEO,SAAS,gBAAgB,EAAE,WAAW,GAAG,MAAM,GAA8B;AAClF,QAAM,EAAE,kBAAkB,IAAI,YAAY;AAE1C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,IAAI;AAAA,MACJ,WAAW,GAAG,kBAAkB,SAAS;AAAA,MACxC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEO,SAAS,YAAY,EAAE,WAAW,UAAU,GAAG,MAAM,GAA8B;AACxF,QAAM,EAAE,cAAc,IAAI,YAAY;AAEtC,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,IAAI;AAAA,MACJ,WAAW,GAAG,cAAc,SAAS;AAAA,MACpC,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/derived/form.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { Label } from \"../atomic/label\";\nimport { Slot } from \"../../primitives/slot\";\nimport { FORM_DESCRIPTION, FORM_ITEM, FORM_MESSAGE } from \"../../generated/form\";\n\n/**\n * Dep-light, presentational form primitives. We keep the ARIA id-wiring of\n * shadcn's form (label/control/description/message share an id so\n * `aria-describedby`/`id` line up) but drop `react-hook-form`'s state engine:\n * validation and field state are the consumer's job. `FormItem` mints an id via\n * `React.useId` and exposes it through `FormItemContext`.\n */\ntype FormItemContextValue = {\n id: string;\n formItemId: string;\n formDescriptionId: string;\n formMessageId: string;\n};\n\nconst FormItemContext = React.createContext<FormItemContextValue | null>(null);\n\nfunction useFormItem(): FormItemContextValue {\n const ctx = React.useContext(FormItemContext);\n if (!ctx) {\n throw new Error(\"Form parts must be used within <FormItem>\");\n }\n return ctx;\n}\n\nexport function Form({ ...props }: React.ComponentProps<\"form\">) {\n return <form data-slot=\"form\" {...props} />;\n}\n\nexport function FormItem({ className, ...props }: React.ComponentProps<\"div\">) {\n const id = React.useId();\n const value = React.useMemo<FormItemContextValue>(\n () => ({\n id,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n }),\n [id],\n );\n\n return (\n <FormItemContext.Provider value={value}>\n <div data-slot=\"form-item\" className={cn(FORM_ITEM, className)} {...props} />\n </FormItemContext.Provider>\n );\n}\n\nexport function FormLabel({\n className,\n error,\n ...props\n}: React.ComponentProps<typeof Label> & { error?: boolean }) {\n const { formItemId } = useFormItem();\n\n return (\n <Label\n data-error={!!error}\n className={cn(\"data-[error=true]:text-accent-error\", className)}\n htmlFor={formItemId}\n {...props}\n />\n );\n}\n\nexport function FormControl({\n error,\n ...props\n}: React.ComponentProps<typeof Slot> & { error?: boolean }) {\n const { formItemId, formDescriptionId, formMessageId } = useFormItem();\n\n return (\n <Slot\n data-slot=\"form-control\"\n id={formItemId}\n aria-describedby={\n !error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`\n }\n aria-invalid={!!error}\n {...props}\n />\n );\n}\n\nexport function FormDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n const { formDescriptionId } = useFormItem();\n\n return (\n <p\n data-slot=\"form-description\"\n id={formDescriptionId}\n className={cn(FORM_DESCRIPTION, className)}\n {...props}\n />\n );\n}\n\nexport function FormMessage({ className, children, ...props }: React.ComponentProps<\"p\">) {\n const { formMessageId } = useFormItem();\n\n if (!children) {\n return null;\n }\n\n return (\n <p\n data-slot=\"form-message\"\n id={formMessageId}\n className={cn(FORM_MESSAGE, className)}\n {...props}\n >\n {children}\n </p>\n );\n}\n"],"mappings":";AAiCS;AA/BT,YAAY,WAAW;AACvB,SAAS,UAAU;AACnB,SAAS,aAAa;AACtB,SAAS,YAAY;AACrB,SAAS,kBAAkB,WAAW,oBAAoB;AAgB1D,MAAM,kBAAkB,MAAM,cAA2C,IAAI;AAE7E,SAAS,cAAoC;AAC3C,QAAM,MAAM,MAAM,WAAW,eAAe;AAC5C,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AACA,SAAO;AACT;AAEO,SAAS,KAAK,EAAE,GAAG,MAAM,GAAiC;AAC/D,SAAO,oBAAC,UAAK,aAAU,QAAQ,GAAG,OAAO;AAC3C;AAEO,SAAS,SAAS,EAAE,WAAW,GAAG,MAAM,GAAgC;AAC7E,QAAM,KAAK,MAAM,MAAM;AACvB,QAAM,QAAQ,MAAM;AAAA,IAClB,OAAO;AAAA,MACL;AAAA,MACA,YAAY,GAAG,EAAE;AAAA,MACjB,mBAAmB,GAAG,EAAE;AAAA,MACxB,eAAe,GAAG,EAAE;AAAA,IACtB;AAAA,IACA,CAAC,EAAE;AAAA,EACL;AAEA,SACE,oBAAC,gBAAgB,UAAhB,EAAyB,OACxB,8BAAC,SAAI,aAAU,aAAY,WAAW,GAAG,WAAW,SAAS,GAAI,GAAG,OAAO,GAC7E;AAEJ;AAEO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAA6D;AAC3D,QAAM,EAAE,WAAW,IAAI,YAAY;AAEnC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,cAAY,CAAC,CAAC;AAAA,MACd,WAAW,GAAG,uCAAuC,SAAS;AAAA,MAC9D,SAAS;AAAA,MACR,GAAG;AAAA;AAAA,EACN;AAEJ;AAEO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA,GAAG;AACL,GAA4D;AAC1D,QAAM,EAAE,YAAY,mBAAmB,cAAc,IAAI,YAAY;AAErE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,IAAI;AAAA,MACJ,oBACE,CAAC,QAAQ,GAAG,iBAAiB,KAAK,GAAG,iBAAiB,IAAI,aAAa;AAAA,MAEzE,gBAAc,CAAC,CAAC;AAAA,MACf,GAAG;AAAA;AAAA,EACN;AAEJ;AAEO,SAAS,gBAAgB,EAAE,WAAW,GAAG,MAAM,GAA8B;AAClF,QAAM,EAAE,kBAAkB,IAAI,YAAY;AAE1C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,IAAI;AAAA,MACJ,WAAW,GAAG,kBAAkB,SAAS;AAAA,MACxC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEO,SAAS,YAAY,EAAE,WAAW,UAAU,GAAG,MAAM,GAA8B;AACxF,QAAM,EAAE,cAAc,IAAI,YAAY;AAEtC,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,IAAI;AAAA,MACJ,WAAW,GAAG,cAAc,SAAS;AAAA,MACpC,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/derived/icon-button.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { ICON_BUTTON_BASE, ICON_BUTTON_PRESSED, iconButtonSizeClasses, type IconButtonSize } from \"../../generated/icon-button\";\nimport { buttonVariants } from \"../atomic/button\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../atomic/tooltip\";\n\nexport type { IconButtonSize };\nexport type IconButtonVariant = \"outline\" | \"ghost\";\n\nexport interface IconButtonProps extends Omit<React.ComponentPropsWithoutRef<\"button\">, \"aria-label\" | \"children\"> {\n /** Required: a glyph alone names nothing. */\n \"aria-label\": string;\n /** The glyph, 16 px. */\n children: React.ReactNode;\n variant?: IconButtonVariant;\n size?: IconButtonSize;\n /** Toggled on: the active fill, and `aria-pressed` for assistive tech. */\n pressed?: boolean;\n /** Shown in a Tooltip on hover and focus. */\n tooltip?: React.ReactNode;\n}\n\n/**\n * A square button holding one glyph. It forwards its ref (also on React 18,\n * where function components drop `ref`) so it can be the child of any\n * `asChild` trigger; with a `tooltip` the same element anchors the tooltip.\n */\nexport const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(function IconButton(\n { variant = \"ghost\", size = \"md\", pressed, tooltip, className, type = \"button\", ...props },\n ref,\n) {\n const button = (\n <button\n ref={ref}\n type={type}\n data-slot=\"icon-button\"\n data-variant={variant}\n aria-pressed={pressed}\n className={cn(\n buttonVariants({ variant, size, icon: true }),\n iconButtonSizeClasses[size],\n ICON_BUTTON_BASE,\n pressed && ICON_BUTTON_PRESSED,\n className,\n )}\n {...props}\n />\n );\n if (tooltip === undefined) return button;\n return (\n <Tooltip>\n <TooltipTrigger asChild>{button}</TooltipTrigger>\n <TooltipContent>{tooltip}</TooltipContent>\n </Tooltip>\n );\n});\n"],"mappings":"AAgCI,cAkBA,YAlBA;AAhCJ,YAAY,WAAW;AACvB,SAAS,UAAU;AACnB,SAAS,kBAAkB,qBAAqB,6BAAkD;AAClG,SAAS,sBAAsB;AAC/B,SAAS,SAAS,gBAAgB,sBAAsB;AAuBjD,MAAM,aAAa,MAAM,WAA+C,SAASA,YACtF,EAAE,UAAU,SAAS,OAAO,MAAM,SAAS,SAAS,WAAW,OAAO,UAAU,GAAG,MAAM,GACzF,KACA;AACA,QAAM,SACJ;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,aAAU;AAAA,MACV,gBAAc;AAAA,MACd,gBAAc;AAAA,MACd,WAAW;AAAA,QACT,eAAe,EAAE,SAAS,MAAM,MAAM,KAAK,CAAC;AAAA,QAC5C,sBAAsB,IAAI;AAAA,QAC1B;AAAA,QACA,WAAW;AAAA,QACX;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEF,MAAI,YAAY,OAAW,QAAO;AAClC,SACE,qBAAC,WACC;AAAA,wBAAC,kBAAe,SAAO,MAAE,kBAAO;AAAA,IAChC,oBAAC,kBAAgB,mBAAQ;AAAA,KAC3B;AAEJ,CAAC;","names":["IconButton"]}
1
+ {"version":3,"sources":["../../../src/components/derived/icon-button.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { ICON_BUTTON_BASE, ICON_BUTTON_PRESSED, iconButtonSizeClasses, type IconButtonSize } from \"../../generated/icon-button\";\nimport { buttonVariants } from \"../atomic/button\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../atomic/tooltip\";\nimport type { IconButtonVariant } from \"../../generated/icon-button\";\n\nexport type { IconButtonSize };\nexport type { IconButtonVariant };\n\nexport interface IconButtonProps extends Omit<React.ComponentPropsWithoutRef<\"button\">, \"aria-label\" | \"children\"> {\n /** Required: a glyph alone names nothing. */\n \"aria-label\": string;\n /** The glyph, 16 px. */\n children: React.ReactNode;\n variant?: IconButtonVariant;\n size?: IconButtonSize;\n /** Toggled on: the active fill, and `aria-pressed` for assistive tech. */\n pressed?: boolean;\n /** Shown in a Tooltip on hover and focus. */\n tooltip?: React.ReactNode;\n}\n\n/**\n * A square button holding one glyph. It forwards its ref (also on React 18,\n * where function components drop `ref`) so it can be the child of any\n * `asChild` trigger; with a `tooltip` the same element anchors the tooltip.\n */\nexport const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(function IconButton(\n { variant = \"ghost\", size = \"md\", pressed, tooltip, className, type = \"button\", ...props },\n ref,\n) {\n const button = (\n <button\n ref={ref}\n type={type}\n data-slot=\"icon-button\"\n data-variant={variant}\n aria-pressed={pressed}\n className={cn(\n buttonVariants({ variant, size, icon: true }),\n iconButtonSizeClasses[size],\n ICON_BUTTON_BASE,\n pressed && ICON_BUTTON_PRESSED,\n className,\n )}\n {...props}\n />\n );\n if (tooltip === undefined) return button;\n return (\n <Tooltip>\n <TooltipTrigger asChild>{button}</TooltipTrigger>\n <TooltipContent>{tooltip}</TooltipContent>\n </Tooltip>\n );\n});\n"],"mappings":"AAiCI,cAkBA,YAlBA;AAjCJ,YAAY,WAAW;AACvB,SAAS,UAAU;AACnB,SAAS,kBAAkB,qBAAqB,6BAAkD;AAClG,SAAS,sBAAsB;AAC/B,SAAS,SAAS,gBAAgB,sBAAsB;AAwBjD,MAAM,aAAa,MAAM,WAA+C,SAASA,YACtF,EAAE,UAAU,SAAS,OAAO,MAAM,SAAS,SAAS,WAAW,OAAO,UAAU,GAAG,MAAM,GACzF,KACA;AACA,QAAM,SACJ;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,aAAU;AAAA,MACV,gBAAc;AAAA,MACd,gBAAc;AAAA,MACd,WAAW;AAAA,QACT,eAAe,EAAE,SAAS,MAAM,MAAM,KAAK,CAAC;AAAA,QAC5C,sBAAsB,IAAI;AAAA,QAC1B;AAAA,QACA,WAAW;AAAA,QACX;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEF,MAAI,YAAY,OAAW,QAAO;AAClC,SACE,qBAAC,WACC;AAAA,wBAAC,kBAAe,SAAO,MAAE,kBAAO;AAAA,IAChC,oBAAC,kBAAgB,mBAAQ;AAAA,KAC3B;AAEJ,CAAC;","names":["IconButton"]}
@@ -36,7 +36,6 @@ function ItemSeparator({
36
36
  return /* @__PURE__ */ jsx(
37
37
  Separator,
38
38
  {
39
- "data-slot": "item-separator",
40
39
  orientation: "horizontal",
41
40
  className: cn(ITEM_SEPARATOR, className),
42
41
  ...props