@godxjp/ui 19.6.0 → 20.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (326) hide show
  1. package/README.md +8 -2
  2. package/dist/app/theme-axes.d.ts +2 -0
  3. package/dist/app/theme-axes.js +45 -0
  4. package/dist/components/charts/chart-cartesian.d.ts +2 -1
  5. package/dist/components/charts/chart-cartesian.js +52 -3
  6. package/dist/components/charts/chart-category-axis.d.ts +55 -0
  7. package/dist/components/charts/chart-category-axis.js +93 -0
  8. package/dist/components/charts/chart-frame.d.ts +10 -1
  9. package/dist/components/charts/chart-frame.js +19 -3
  10. package/dist/components/charts/compact-bar-trend.d.ts +1 -1
  11. package/dist/components/charts/compact-bar-trend.js +2 -0
  12. package/dist/components/charts/pie-chart.d.ts +1 -1
  13. package/dist/components/charts/pie-chart.js +12 -1
  14. package/dist/components/charts/recharts-peer.d.ts +49 -0
  15. package/dist/components/charts/recharts-peer.js +45 -0
  16. package/dist/components/data-display/card.d.ts +14 -3
  17. package/dist/components/data-display/card.js +22 -4
  18. package/dist/components/data-display/code-block.js +6 -2
  19. package/dist/components/data-display/collapsible.d.ts +23 -4
  20. package/dist/components/data-display/collapsible.js +119 -4
  21. package/dist/components/data-display/data-table.d.ts +39 -4
  22. package/dist/components/data-display/data-table.js +802 -270
  23. package/dist/components/data-display/descriptions.d.ts +27 -6
  24. package/dist/components/data-display/descriptions.js +58 -17
  25. package/dist/components/data-display/index.d.ts +5 -1
  26. package/dist/components/data-display/index.js +4 -0
  27. package/dist/components/data-display/legend.d.ts +15 -0
  28. package/dist/components/data-display/legend.js +11 -0
  29. package/dist/components/data-display/list-row.d.ts +10 -1
  30. package/dist/components/data-display/list-row.js +8 -2
  31. package/dist/components/data-display/popover.d.ts +60 -7
  32. package/dist/components/data-display/popover.js +268 -39
  33. package/dist/components/data-display/progress.d.ts +50 -2
  34. package/dist/components/data-display/progress.js +57 -9
  35. package/dist/components/data-display/range-timeline.d.ts +38 -0
  36. package/dist/components/data-display/range-timeline.js +161 -0
  37. package/dist/components/data-display/scroll-area.js +13 -2
  38. package/dist/components/data-display/service-launcher-card.js +10 -10
  39. package/dist/components/data-display/table.d.ts +11 -3
  40. package/dist/components/data-display/table.js +48 -18
  41. package/dist/components/data-display/tree-list.js +4 -9
  42. package/dist/components/data-entry/calendar.d.ts +2 -2
  43. package/dist/components/data-entry/calendar.js +79 -33
  44. package/dist/components/data-entry/cascader.d.ts +1 -1
  45. package/dist/components/data-entry/cascader.js +188 -24
  46. package/dist/components/data-entry/checkbox.d.ts +19 -6
  47. package/dist/components/data-entry/checkbox.js +55 -16
  48. package/dist/components/data-entry/choice-option.d.ts +1 -1
  49. package/dist/components/data-entry/color-picker.d.ts +1 -1
  50. package/dist/components/data-entry/color-picker.js +17 -5
  51. package/dist/components/data-entry/control-appearance.d.ts +64 -0
  52. package/dist/components/data-entry/control-appearance.js +39 -0
  53. package/dist/components/data-entry/control-surface.d.ts +61 -0
  54. package/dist/components/data-entry/control-surface.js +39 -0
  55. package/dist/components/data-entry/date-picker.d.ts +1 -1
  56. package/dist/components/data-entry/date-picker.js +344 -113
  57. package/dist/components/data-entry/date-range-picker.d.ts +2 -2
  58. package/dist/components/data-entry/date-range-picker.js +278 -140
  59. package/dist/components/data-entry/field.js +0 -1
  60. package/dist/components/data-entry/form-field.d.ts +1 -1
  61. package/dist/components/data-entry/form-field.js +39 -4
  62. package/dist/components/data-entry/form.d.ts +4 -0
  63. package/dist/components/data-entry/form.js +5 -3
  64. package/dist/components/data-entry/index.d.ts +7 -3
  65. package/dist/components/data-entry/index.js +10 -1
  66. package/dist/components/data-entry/input-otp.d.ts +1 -1
  67. package/dist/components/data-entry/input.d.ts +12 -34
  68. package/dist/components/data-entry/input.js +92 -24
  69. package/dist/components/data-entry/label.d.ts +3 -2
  70. package/dist/components/data-entry/label.js +23 -10
  71. package/dist/components/data-entry/month-picker.d.ts +2 -2
  72. package/dist/components/data-entry/month-picker.js +47 -10
  73. package/dist/components/data-entry/month-range-picker.d.ts +2 -2
  74. package/dist/components/data-entry/month-range-picker.js +51 -11
  75. package/dist/components/data-entry/number-input.d.ts +7 -0
  76. package/dist/components/data-entry/number-input.js +147 -98
  77. package/dist/components/data-entry/password-input.d.ts +1 -1
  78. package/dist/components/data-entry/radio.d.ts +1 -1
  79. package/dist/components/data-entry/radio.js +61 -13
  80. package/dist/components/data-entry/search-input.d.ts +1 -1
  81. package/dist/components/data-entry/search-input.js +16 -2
  82. package/dist/components/data-entry/search-select.d.ts +2 -2
  83. package/dist/components/data-entry/search-select.js +209 -78
  84. package/dist/components/data-entry/select.d.ts +22 -4
  85. package/dist/components/data-entry/select.js +215 -163
  86. package/dist/components/data-entry/slider.d.ts +9 -1
  87. package/dist/components/data-entry/slider.js +87 -9
  88. package/dist/components/data-entry/switch.d.ts +3 -0
  89. package/dist/components/data-entry/switch.js +29 -3
  90. package/dist/components/data-entry/textarea.d.ts +14 -56
  91. package/dist/components/data-entry/textarea.js +80 -33
  92. package/dist/components/data-entry/time-picker.d.ts +2 -2
  93. package/dist/components/data-entry/time-picker.js +333 -109
  94. package/dist/components/data-entry/time-range-picker.d.ts +5 -0
  95. package/dist/components/data-entry/time-range-picker.js +89 -0
  96. package/dist/components/data-entry/transfer.d.ts +1 -1
  97. package/dist/components/data-entry/transfer.js +99 -31
  98. package/dist/components/data-entry/tree-select-strategy.d.ts +1 -1
  99. package/dist/components/data-entry/tree-select.d.ts +1 -1
  100. package/dist/components/data-entry/tree-select.js +197 -92
  101. package/dist/components/data-entry/tree-utils.d.ts +1 -1
  102. package/dist/components/data-entry/tree-utils.js +7 -14
  103. package/dist/components/data-entry/upload-files.d.ts +2 -0
  104. package/dist/components/data-entry/upload-files.js +31 -0
  105. package/dist/components/data-entry/upload-request.d.ts +4 -0
  106. package/dist/components/data-entry/upload-request.js +53 -0
  107. package/dist/components/data-entry/upload-types.d.ts +28 -0
  108. package/dist/components/data-entry/upload-types.js +2 -0
  109. package/dist/components/data-entry/upload.d.ts +2 -2
  110. package/dist/components/data-entry/upload.js +482 -117
  111. package/dist/components/feedback/dialog.d.ts +105 -38
  112. package/dist/components/feedback/dialog.js +268 -193
  113. package/dist/components/feedback/overlay-close-focus.d.ts +31 -0
  114. package/dist/components/feedback/overlay-close-focus.js +31 -0
  115. package/dist/components/feedback/overlay-header-tone.d.ts +1 -1
  116. package/dist/components/feedback/sheet.d.ts +53 -11
  117. package/dist/components/feedback/sheet.js +150 -81
  118. package/dist/components/feedback/tooltip.d.ts +51 -7
  119. package/dist/components/feedback/tooltip.js +107 -25
  120. package/dist/components/general/button.d.ts +1 -1
  121. package/dist/components/general/button.js +7 -3
  122. package/dist/components/general/index.d.ts +1 -0
  123. package/dist/components/general/index.js +2 -0
  124. package/dist/components/general/logo.d.ts +17 -0
  125. package/dist/components/general/logo.js +22 -16
  126. package/dist/components/general/typography.d.ts +3 -0
  127. package/dist/components/general/typography.js +15 -1
  128. package/dist/components/general/visually-hidden.d.ts +3 -0
  129. package/dist/components/general/visually-hidden.js +9 -0
  130. package/dist/components/layout/app-launcher.d.ts +34 -0
  131. package/dist/components/layout/app-launcher.js +228 -0
  132. package/dist/components/layout/app-shell.d.ts +3 -1
  133. package/dist/components/layout/app-shell.js +69 -12
  134. package/dist/components/layout/aspect-ratio.js +0 -1
  135. package/dist/components/layout/auth-divider.js +0 -1
  136. package/dist/components/layout/breadcrumb.d.ts +14 -2
  137. package/dist/components/layout/breadcrumb.js +46 -4
  138. package/dist/components/layout/flex.d.ts +1 -1
  139. package/dist/components/layout/flex.js +41 -3
  140. package/dist/components/layout/index.d.ts +3 -0
  141. package/dist/components/layout/index.js +5 -1
  142. package/dist/components/layout/nav-surface.d.ts +26 -0
  143. package/dist/components/layout/nav-surface.js +17 -0
  144. package/dist/components/layout/org-switcher.d.ts +5 -1
  145. package/dist/components/layout/org-switcher.js +25 -4
  146. package/dist/components/layout/page-container.d.ts +1 -1
  147. package/dist/components/layout/page-container.js +5 -3
  148. package/dist/components/layout/responsive-grid.d.ts +16 -2
  149. package/dist/components/layout/responsive-grid.js +29 -2
  150. package/dist/components/layout/separator.js +0 -1
  151. package/dist/components/layout/sidebar.js +4 -1
  152. package/dist/components/layout/split-pane.d.ts +14 -1
  153. package/dist/components/layout/split-pane.js +26 -13
  154. package/dist/components/layout/topbar-item.d.ts +3 -0
  155. package/dist/components/layout/topbar-item.js +19 -5
  156. package/dist/components/layout/topbar.d.ts +1 -1
  157. package/dist/components/layout/topbar.js +27 -6
  158. package/dist/components/navigation/app-setting-picker.js +21 -2
  159. package/dist/components/navigation/app-setting-toggle.d.ts +16 -0
  160. package/dist/components/navigation/app-setting-toggle.js +96 -0
  161. package/dist/components/navigation/dropdown-menu.d.ts +227 -18
  162. package/dist/components/navigation/dropdown-menu.js +402 -118
  163. package/dist/components/navigation/index.d.ts +2 -0
  164. package/dist/components/navigation/index.js +2 -0
  165. package/dist/components/navigation/pagination-utils.d.ts +2 -1
  166. package/dist/components/navigation/pagination.d.ts +2 -2
  167. package/dist/components/navigation/pagination.js +155 -83
  168. package/dist/components/navigation/steps.d.ts +2 -2
  169. package/dist/components/navigation/steps.js +29 -4
  170. package/dist/components/navigation/tabs.d.ts +29 -16
  171. package/dist/components/navigation/tabs.js +374 -144
  172. package/dist/components/ui/accordion.d.ts +50 -5
  173. package/dist/components/ui/accordion.js +239 -33
  174. package/dist/components/ui/aspect-ratio.d.ts +23 -2
  175. package/dist/components/ui/aspect-ratio.js +15 -13
  176. package/dist/components/ui/avatar.d.ts +29 -4
  177. package/dist/components/ui/avatar.js +111 -25
  178. package/dist/components/ui/hover-card.d.ts +42 -4
  179. package/dist/components/ui/hover-card.js +183 -27
  180. package/dist/components/ui/input-otp.d.ts +26 -28
  181. package/dist/components/ui/input-otp.js +50 -7
  182. package/dist/components/ui/label.js +0 -1
  183. package/dist/components/ui/password-input.d.ts +36 -2
  184. package/dist/components/ui/password-input.js +27 -7
  185. package/dist/components/ui/rating.d.ts +25 -0
  186. package/dist/components/ui/rating.js +67 -27
  187. package/dist/components/ui/segmented.d.ts +12 -3
  188. package/dist/components/ui/segmented.js +17 -2
  189. package/dist/components/ui/separator.d.ts +12 -2
  190. package/dist/components/ui/separator.js +30 -9
  191. package/dist/components/ui/tag-input.d.ts +45 -0
  192. package/dist/components/ui/tag-input.js +109 -27
  193. package/dist/components/ui/toggle-group.d.ts +50 -5
  194. package/dist/components/ui/toggle-group.js +79 -20
  195. package/dist/components/ui/toggle.d.ts +31 -5
  196. package/dist/components/ui/toggle.js +42 -3
  197. package/dist/form/form-context.d.ts +29 -0
  198. package/dist/form/form-context.js +44 -4
  199. package/dist/form/form-field-array.d.ts +22 -0
  200. package/dist/form/form-field-array.js +50 -0
  201. package/dist/form/form-field-control.d.ts +2 -1
  202. package/dist/form/form-field-control.js +116 -40
  203. package/dist/form/form-root.d.ts +2 -1
  204. package/dist/form/form-root.js +142 -23
  205. package/dist/form/index.d.ts +3 -1
  206. package/dist/form/index.js +12 -1
  207. package/dist/i18n/messages/en.json +64 -5
  208. package/dist/i18n/messages/ja.json +64 -5
  209. package/dist/i18n/messages/vi.json +64 -5
  210. package/dist/inertia/index.d.ts +20 -0
  211. package/dist/inertia/index.js +60 -1
  212. package/dist/lib/control-styles.d.ts +25 -3
  213. package/dist/lib/control-styles.js +9 -3
  214. package/dist/lib/datetime/picker-format.d.ts +8 -0
  215. package/dist/lib/datetime/picker-format.js +54 -0
  216. package/dist/lib/slot.d.ts +32 -0
  217. package/dist/lib/slot.js +22 -0
  218. package/dist/lib/variants.d.ts +22 -3
  219. package/dist/lib/variants.js +56 -1
  220. package/dist/props/components/app.prop.d.ts +25 -1
  221. package/dist/props/components/charts.prop.d.ts +21 -0
  222. package/dist/props/components/data-display.prop.d.ts +72 -4
  223. package/dist/props/components/data-entry.prop.d.ts +718 -46
  224. package/dist/props/components/form.prop.d.ts +142 -4
  225. package/dist/props/components/general.prop.d.ts +17 -1
  226. package/dist/props/components/index.d.ts +3 -3
  227. package/dist/props/components/layout.prop.d.ts +281 -11
  228. package/dist/props/components/navigation.prop.d.ts +114 -4
  229. package/dist/props/registry.d.ts +397 -11
  230. package/dist/props/registry.js +526 -11
  231. package/dist/props/vocabulary/content.prop.d.ts +1 -1
  232. package/dist/props/vocabulary/data.prop.d.ts +179 -1
  233. package/dist/props/vocabulary/index.d.ts +5 -5
  234. package/dist/props/vocabulary/interaction.prop.d.ts +68 -3
  235. package/dist/props/vocabulary/layout.prop.d.ts +57 -1
  236. package/dist/props/vocabulary/navigation.prop.d.ts +40 -0
  237. package/dist/props/vocabulary/shared.prop.d.ts +33 -0
  238. package/dist/styles/badge-layout.css +2 -1
  239. package/dist/styles/card-layout.css +26 -4
  240. package/dist/styles/chart-layout.css +15 -0
  241. package/dist/styles/control.css +657 -15
  242. package/dist/styles/core.css +5 -2
  243. package/dist/styles/data-display-layout.css +313 -6
  244. package/dist/styles/data-entry-layout.css +13 -0
  245. package/dist/styles/focus-ring.css +4 -0
  246. package/dist/styles/index.css +5 -2
  247. package/dist/styles/layout.css +327 -4
  248. package/dist/styles/navigation-layout.css +227 -0
  249. package/dist/styles/shell-layout.css +369 -13
  250. package/dist/styles/table-layout.css +95 -6
  251. package/dist/styles/text-layout.css +10 -4
  252. package/dist/tokens/base.css +2 -1
  253. package/dist/tokens/components/badge.css +1 -0
  254. package/dist/tokens/components/chart.css +6 -0
  255. package/dist/tokens/components/control.css +79 -2
  256. package/dist/tokens/components/data-display.css +20 -0
  257. package/dist/tokens/components/descriptions.css +11 -0
  258. package/dist/tokens/components/flex.css +8 -0
  259. package/dist/tokens/components/navigation.css +55 -0
  260. package/dist/tokens/components/shell.css +53 -3
  261. package/dist/tokens/components/table.css +14 -0
  262. package/dist/tokens/foundation.css +2 -0
  263. package/dist/tokens/semantic/layout.css +9 -0
  264. package/docs/COMPONENTS.md +9 -3
  265. package/docs/CONSUMER-RULES.md +13 -0
  266. package/docs/DESIGN-AUTHORITY.md +145 -83
  267. package/docs/DEVELOPMENT.md +4 -3
  268. package/docs/FORMS.md +151 -6
  269. package/docs/FRAME-COVERAGE-REPORT.md +32 -17
  270. package/docs/README.md +15 -15
  271. package/docs/STANDARDS-vocabulary-tokens.md +1 -1
  272. package/docs/TESTING.md +15 -6
  273. package/docs/WHAT-BELONGS-HERE.md +179 -0
  274. package/docs/charts/cjk-category-axis.tsx +81 -0
  275. package/docs/data-display/card/index.tsx +22 -0
  276. package/docs/data-display/data-table/examples/antd-parity.tsx +257 -0
  277. package/docs/data-display/data-table/index.tsx +23 -0
  278. package/docs/data-display/descriptions.tsx +41 -0
  279. package/docs/data-display/legend.tsx +145 -0
  280. package/docs/data-display/progress.tsx +32 -0
  281. package/docs/data-display/scroll-area.tsx +31 -25
  282. package/docs/data-display/table.tsx +104 -45
  283. package/docs/data-display/timeline.tsx +41 -0
  284. package/docs/data-entry/date-picker.tsx +85 -0
  285. package/docs/data-entry/date-range-picker.tsx +26 -0
  286. package/docs/data-entry/form-dynamic-fields.tsx +199 -0
  287. package/docs/data-entry/form.tsx +74 -4
  288. package/docs/data-entry/input-otp.tsx +24 -0
  289. package/docs/data-entry/input.tsx +46 -1
  290. package/docs/data-entry/month-range-picker.tsx +1 -1
  291. package/docs/data-entry/segmented.tsx +1 -1
  292. package/docs/data-entry/select.tsx +29 -2
  293. package/docs/data-entry/switch.tsx +41 -0
  294. package/docs/data-entry/textarea.tsx +38 -0
  295. package/docs/data-entry/time-picker.tsx +85 -1
  296. package/docs/data-entry/time-range-picker.tsx +55 -0
  297. package/docs/data-entry/transfer.tsx +17 -0
  298. package/docs/data-entry/upload.tsx +56 -12
  299. package/docs/feedback/sheet.tsx +1 -1
  300. package/docs/feedback/tooltip.tsx +1 -1
  301. package/docs/general/activity.tsx +2 -2
  302. package/docs/general/button/index.tsx +14 -1
  303. package/docs/general/typography.tsx +14 -1
  304. package/docs/layout/app-launcher.tsx +151 -0
  305. package/docs/layout/app-shell-arrangements.tsx +225 -0
  306. package/docs/layout/app-shell.tsx +11 -0
  307. package/docs/layout/aspect-ratio.tsx +1 -1
  308. package/docs/layout/flex.tsx +50 -0
  309. package/docs/layout/responsive-grid.tsx +21 -1
  310. package/docs/layout/topbar.tsx +5 -9
  311. package/docs/navigation/app-setting-picker.tsx +37 -1
  312. package/docs/navigation/app-setting-toggle.tsx +111 -0
  313. package/docs/navigation/breadcrumb.tsx +48 -0
  314. package/docs/navigation/dropdown-menu.tsx +21 -0
  315. package/docs/navigation/pagination.tsx +52 -0
  316. package/docs/navigation/steps.tsx +37 -0
  317. package/docs/navigation/tabs.tsx +97 -1
  318. package/docs/query/button-refetch.tsx +1 -0
  319. package/package.json +28 -8
  320. package/scripts/_agent-setup.mjs +182 -3
  321. package/scripts/consumer-rule.md +98 -0
  322. package/scripts/guinea-pig-skill.md +322 -0
  323. package/scripts/init-guinea-pig.mjs +84 -0
  324. package/scripts/postinstall.mjs +13 -2
  325. package/scripts/ui-audit.mjs +351 -37
  326. /package/dist/tokens/{antd.generated.css → derived.css} +0 -0
@@ -1,51 +1,280 @@
1
1
  "use client";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
- import * as PopoverPrimitive from "@radix-ui/react-popover";
4
+ import { chain, mergeRefs } from "@react-aria/utils";
5
+ import { Popover as AriaPopover } from "react-aria-components";
5
6
  import { cn } from "../../lib/utils.js";
6
- function Popover(props) {
7
- return /* @__PURE__ */ jsx(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
8
- }
9
- function PopoverTrigger(props) {
10
- return /* @__PURE__ */ jsx(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
11
- }
12
- function PopoverAnchor(props) {
13
- return /* @__PURE__ */ jsx(PopoverPrimitive.Anchor, { "data-slot": "popover-anchor", ...props });
14
- }
15
- const PopoverContent = React.forwardRef(({ className, align = "center", sideOffset = 4, flush, style, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
16
- PopoverPrimitive.Content,
17
- {
18
- ref,
19
- "data-slot": "popover-content",
20
- "data-flush": flush ? "" : void 0,
21
- align,
22
- sideOffset,
23
- style: flush ? { ...style, "--popover-space-inset": "0" } : style,
24
- className: cn(
25
- "ui-popover-content origin-[var(--radix-popover-content-transform-origin)]",
26
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
27
- "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
28
- "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
29
- "data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
30
- className
31
- ),
32
- ...props
7
+ import { Slot } from "../../lib/slot.js";
8
+ import { useOverlayCloseFocus } from "../feedback/overlay-close-focus.js";
9
+ function toPlacement(side, align) {
10
+ if (align === "center") return side;
11
+ if (side === "top" || side === "bottom") return `${side} ${align}`;
12
+ return `${side} ${align === "start" ? "top" : "bottom"}`;
13
+ }
14
+ function toContainerPadding(padding) {
15
+ if (padding == null) return void 0;
16
+ if (typeof padding === "number") return padding;
17
+ const sides = Object.values(padding).filter(
18
+ (value) => typeof value === "number"
19
+ );
20
+ return sides.length ? Math.max(...sides) : void 0;
21
+ }
22
+ function firstTabbable(container) {
23
+ for (const node of container.querySelectorAll("*")) {
24
+ if (node.tagName === "A") continue;
25
+ if (node.hidden || node.disabled) continue;
26
+ if (node.tagName === "INPUT" && node.type === "hidden") continue;
27
+ if (node.tabIndex >= 0) return node;
28
+ }
29
+ return null;
30
+ }
31
+ const PopoverRootContext = React.createContext(null);
32
+ function usePopoverRoot(component) {
33
+ const context = React.useContext(PopoverRootContext);
34
+ if (!context) {
35
+ throw new Error(`\`${component}\` ph\u1EA3i n\u1EB1m trong \`Popover\`.`);
33
36
  }
34
- ) }));
35
- PopoverContent.displayName = PopoverPrimitive.Content.displayName;
37
+ return context;
38
+ }
39
+ function Popover({
40
+ open,
41
+ defaultOpen,
42
+ onOpenChange,
43
+ modal = false,
44
+ children
45
+ }) {
46
+ const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen ?? false);
47
+ const [anchored, setAnchored] = React.useState(false);
48
+ const triggerRef = React.useRef(null);
49
+ const anchorRef = React.useRef(null);
50
+ const contentId = React.useId();
51
+ const titleId = React.useId();
52
+ const descriptionId = React.useId();
53
+ const triggerId = React.useId();
54
+ const [hasTitle, registerTitle] = React.useState(false);
55
+ const [hasDescription, registerDescription] = React.useState(false);
56
+ const isOpen = open ?? uncontrolledOpen;
57
+ const setOpen = React.useCallback(
58
+ (next) => {
59
+ if (open === void 0) {
60
+ setUncontrolledOpen(next);
61
+ }
62
+ onOpenChange?.(next);
63
+ },
64
+ [open, onOpenChange]
65
+ );
66
+ const value = React.useMemo(
67
+ () => ({
68
+ open: isOpen,
69
+ setOpen,
70
+ contentId,
71
+ isNonModal: !modal,
72
+ triggerRef,
73
+ anchorRef,
74
+ anchored,
75
+ setAnchored,
76
+ titleId,
77
+ descriptionId,
78
+ hasTitle,
79
+ hasDescription,
80
+ registerTitle,
81
+ registerDescription,
82
+ triggerId
83
+ }),
84
+ [
85
+ isOpen,
86
+ setOpen,
87
+ contentId,
88
+ modal,
89
+ anchored,
90
+ titleId,
91
+ descriptionId,
92
+ hasTitle,
93
+ hasDescription,
94
+ triggerId
95
+ ]
96
+ );
97
+ return /* @__PURE__ */ jsx(PopoverRootContext.Provider, { value, children });
98
+ }
99
+ function PopoverTrigger({ asChild, onClick, ref, ...props }) {
100
+ const root = usePopoverRoot("PopoverTrigger");
101
+ const Comp = asChild ? Slot : "button";
102
+ return /* @__PURE__ */ jsx(
103
+ Comp,
104
+ {
105
+ type: "button",
106
+ "data-slot": "popover-trigger",
107
+ "aria-haspopup": "dialog",
108
+ "aria-expanded": root.open,
109
+ id: props.id ?? root.triggerId,
110
+ "aria-controls": root.open ? root.contentId : void 0,
111
+ "data-state": root.open ? "open" : "closed",
112
+ ...props,
113
+ ref: mergeRefs(ref, root.triggerRef),
114
+ onClick: chain(onClick, () => root.setOpen(!root.open))
115
+ }
116
+ );
117
+ }
118
+ function PopoverAnchor({ asChild, ref, ...props }) {
119
+ const root = usePopoverRoot("PopoverAnchor");
120
+ const Comp = asChild ? Slot : "span";
121
+ const { setAnchored } = root;
122
+ React.useEffect(() => {
123
+ setAnchored(true);
124
+ return () => setAnchored(false);
125
+ }, [setAnchored]);
126
+ return /* @__PURE__ */ jsx(Comp, { "data-slot": "popover-anchor", ...props, ref: mergeRefs(ref, root.anchorRef) });
127
+ }
128
+ function PopoverContent({
129
+ className,
130
+ style,
131
+ children,
132
+ ref,
133
+ flush,
134
+ side = "bottom",
135
+ align = "center",
136
+ sideOffset = 4,
137
+ alignOffset,
138
+ avoidCollisions = true,
139
+ collisionPadding,
140
+ sticky: _sticky,
141
+ hideWhenDetached: _hideWhenDetached,
142
+ forceMount: _forceMount,
143
+ onOpenAutoFocus,
144
+ onCloseAutoFocus,
145
+ ...props
146
+ }) {
147
+ const root = usePopoverRoot("PopoverContent");
148
+ const contentRef = React.useRef(null);
149
+ const openAutoFocusRef = React.useRef(onOpenAutoFocus);
150
+ openAutoFocusRef.current = onOpenAutoFocus;
151
+ useOverlayCloseFocus(root.open, onCloseAutoFocus, contentRef);
152
+ React.useEffect(() => {
153
+ if (!root.open) return;
154
+ const node = contentRef.current;
155
+ if (!node) return;
156
+ const event = new Event("popover.openAutoFocus", { bubbles: false, cancelable: true });
157
+ openAutoFocusRef.current?.(event);
158
+ if (!event.defaultPrevented) {
159
+ const target = firstTabbable(node);
160
+ target?.focus({ preventScroll: true });
161
+ if (!node.contains(document.activeElement)) {
162
+ node.focus({ preventScroll: true });
163
+ }
164
+ }
165
+ }, [root.open]);
166
+ const { open, setOpen, triggerRef } = root;
167
+ React.useEffect(() => {
168
+ if (!open) return;
169
+ const onPointerDown = (event) => {
170
+ const target = event.target;
171
+ if (!target) return;
172
+ if (contentRef.current?.contains(target)) return;
173
+ if (triggerRef.current?.contains(target)) return;
174
+ setOpen(false);
175
+ };
176
+ document.addEventListener("pointerdown", onPointerDown);
177
+ return () => document.removeEventListener("pointerdown", onPointerDown);
178
+ }, [open, setOpen, triggerRef]);
179
+ return /* @__PURE__ */ jsx(
180
+ AriaPopover,
181
+ {
182
+ isOpen: root.open,
183
+ onOpenChange: root.setOpen,
184
+ isNonModal: root.isNonModal,
185
+ triggerRef: root.anchored ? root.anchorRef : root.triggerRef,
186
+ placement: toPlacement(side, align),
187
+ offset: sideOffset,
188
+ crossOffset: alignOffset,
189
+ shouldFlip: avoidCollisions,
190
+ containerPadding: toContainerPadding(collisionPadding),
191
+ render: (racProps, { isExiting }) => {
192
+ const {
193
+ className: _racClassName,
194
+ "data-rac": _rac,
195
+ ref: racRef,
196
+ style: racStyle,
197
+ ...rest
198
+ } = racProps;
199
+ const availableHeight = racStyle?.maxHeight;
200
+ return /* @__PURE__ */ jsx(
201
+ "div",
202
+ {
203
+ ...rest,
204
+ id: root.contentId,
205
+ role: "dialog",
206
+ tabIndex: -1,
207
+ "data-slot": "popover-content",
208
+ "data-side": side,
209
+ "data-align": align,
210
+ "data-state": isExiting ? "closed" : "open",
211
+ "data-flush": flush ? "" : void 0,
212
+ ...props,
213
+ "aria-labelledby": props["aria-labelledby"] ?? (props["aria-label"] ? void 0 : root.hasTitle ? root.titleId : root.triggerId),
214
+ "aria-describedby": props["aria-describedby"] ?? (root.hasDescription ? root.descriptionId : void 0),
215
+ ref: mergeRefs(ref, racRef, contentRef),
216
+ className: cn(
217
+ "ui-popover-content origin-[var(--radix-popover-content-transform-origin)]",
218
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
219
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
220
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
221
+ "data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
222
+ className
223
+ ),
224
+ style: {
225
+ ...racStyle,
226
+ "--radix-popover-trigger-width": "var(--trigger-width)",
227
+ "--radix-popover-content-transform-origin": "var(--trigger-anchor-point)",
228
+ ...availableHeight == null ? null : {
229
+ "--radix-popover-content-available-height": typeof availableHeight === "number" ? `${availableHeight}px` : availableHeight
230
+ },
231
+ ...style,
232
+ ...flush ? { "--popover-space-inset": "0" } : null
233
+ },
234
+ children
235
+ }
236
+ );
237
+ }
238
+ }
239
+ );
240
+ }
36
241
  const PopoverHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { "data-slot": "popover-header", className: cn("ui-popover-header", className), ...props });
37
- const PopoverTitle = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { "data-slot": "popover-title", className: cn("font-medium", className), ...props });
242
+ const PopoverTitle = ({ className, id, ...props }) => {
243
+ const root = usePopoverRoot("PopoverTitle");
244
+ React.useEffect(() => {
245
+ root.registerTitle(true);
246
+ return () => root.registerTitle(false);
247
+ }, [root]);
248
+ return /* @__PURE__ */ jsx(
249
+ "div",
250
+ {
251
+ "data-slot": "popover-title",
252
+ id: id ?? root.titleId,
253
+ className: cn("font-medium", className),
254
+ ...props
255
+ }
256
+ );
257
+ };
38
258
  const PopoverDescription = ({
39
259
  className,
260
+ id,
40
261
  ...props
41
- }) => /* @__PURE__ */ jsx(
42
- "p",
43
- {
44
- "data-slot": "popover-description",
45
- className: cn("text-muted-foreground", className),
46
- ...props
47
- }
48
- );
262
+ }) => {
263
+ const root = usePopoverRoot("PopoverDescription");
264
+ React.useEffect(() => {
265
+ root.registerDescription(true);
266
+ return () => root.registerDescription(false);
267
+ }, [root]);
268
+ return /* @__PURE__ */ jsx(
269
+ "p",
270
+ {
271
+ "data-slot": "popover-description",
272
+ id: id ?? root.descriptionId,
273
+ className: cn("text-muted-foreground", className),
274
+ ...props
275
+ }
276
+ );
277
+ };
49
278
  export {
50
279
  Popover,
51
280
  PopoverAnchor,
@@ -1,8 +1,29 @@
1
1
  import * as React from "react";
2
2
  export type ProgressTone = "success" | "warning" | "destructive";
3
- export type ProgressProps = {
3
+ /**
4
+ * One slice of a BREAKDOWN bar — how much of the total this state holds, in the SAME unit as every
5
+ * other slice (counts, bytes, yen). Never a percentage: the bar owns the ratio arithmetic, so the
6
+ * caller never has to round three numbers that must still add up to 100.
7
+ *
8
+ * `label` is not decoration. Colour alone cannot carry the meaning of a slice (WCAG 1.4.1), and it
9
+ * is the only thing a screen reader has to say about it, so it is required.
10
+ */
11
+ export type ProgressSegment = {
4
12
  value: number;
13
+ tone: ProgressTone;
14
+ label: string;
15
+ };
16
+ type ProgressBase = Omit<React.HTMLAttributes<HTMLDivElement>, "role" | "children" | "aria-valuenow" | "aria-valuemin" | "aria-valuemax" | "aria-valuetext"> & {
17
+ /**
18
+ * Visible caption under the bar; it also becomes the bar's accessible name. Omit it and the bar
19
+ * falls back to the catalogue name — or to whatever `aria-label`/`aria-labelledby` the caller
20
+ * passes, which is how a bar gets its name from a heading that is already on screen.
21
+ */
5
22
  label?: string;
23
+ };
24
+ /** A METER: one ratio of one whole. */
25
+ type ProgressMeterProps = ProgressBase & {
26
+ value: number;
6
27
  tone?: ProgressTone;
7
28
  /**
8
29
  * Allow `value` to exceed 100 and render an OVER-CAPACITY fill: the bar caps at 100% width but
@@ -11,5 +32,32 @@ export type ProgressProps = {
11
32
  * real ratio.
12
33
  */
13
34
  over?: boolean;
35
+ segments?: never;
36
+ };
37
+ /**
38
+ * A BREAKDOWN: one whole split into its states.
39
+ *
40
+ * ## Why this is not a meter with three calls
41
+ *
42
+ * A meter answers "how far along?" and has ONE value, so `role="progressbar"` fits it exactly.
43
+ * A breakdown answers "what is this total made of?" — 2 overdue · 3 due soon · 12 done. Stacking
44
+ * three progressbars says the wrong thing three times over (three separate 0–100 measurements),
45
+ * and no ARIA value pattern models a partition. It is a picture of data, so it names itself once
46
+ * as `role="img"` and reads out every slice with its own label and amount.
47
+ *
48
+ * ## Why it is a taller bar than the meter
49
+ *
50
+ * A 0.5rem pill is legible when it carries one fill against one track. Three abutting fills at
51
+ * that height read as a coloured hairline — the ratios, which are the entire point, stop being
52
+ * comparable. So the breakdown takes its own block size and corner, both retunable
53
+ * (`--progress-breakdown-*`).
54
+ */
55
+ type ProgressBreakdownProps = ProgressBase & {
56
+ segments: ProgressSegment[];
57
+ value?: never;
58
+ tone?: never;
59
+ over?: never;
14
60
  };
15
- export declare function Progress({ value, label, tone, over }: ProgressProps): React.JSX.Element;
61
+ export type ProgressProps = ProgressMeterProps | ProgressBreakdownProps;
62
+ export declare function Progress(props: ProgressProps): React.JSX.Element;
63
+ export {};
@@ -1,27 +1,75 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
- function Progress({ value, label, tone, over = false }) {
5
- const isOver = over && value > 100;
6
- const boundedValue = Math.max(0, Math.min(100, value));
7
- const effectiveTone = tone ?? (isOver ? "destructive" : "success");
4
+ import { useTranslation } from "../../i18n/use-translation.js";
5
+ import { cn } from "../../lib/utils.js";
6
+ function Progress(props) {
7
+ const { t } = useTranslation();
8
8
  const labelId = React.useId();
9
+ const {
10
+ label,
11
+ className,
12
+ segments,
13
+ value,
14
+ tone,
15
+ over = false,
16
+ "aria-label": ariaLabel,
17
+ "aria-labelledby": ariaLabelledBy,
18
+ ...domProps
19
+ } = props;
20
+ const named = ariaLabel !== void 0 || ariaLabelledBy !== void 0;
21
+ const labelledBy = ariaLabelledBy ?? (label !== void 0 ? labelId : void 0);
22
+ const caption = label !== void 0 ? /* @__PURE__ */ jsx("div", { className: "ui-progress-label", id: labelId, children: label }) : null;
23
+ if (segments !== void 0) {
24
+ const amounts = segments.map((segment) => Math.max(0, segment.value));
25
+ const total = amounts.reduce((sum, amount) => sum + amount, 0);
26
+ const separator = t("dataDisplay.progress.breakdownSeparator");
27
+ const spoken = segments.map((segment, index) => `${segment.label} ${amounts[index]}`).join(separator);
28
+ return /* @__PURE__ */ jsxs(
29
+ "div",
30
+ {
31
+ className: cn("ui-progress", className),
32
+ "data-breakdown": "",
33
+ role: "img",
34
+ "aria-labelledby": ariaLabelledBy,
35
+ "aria-label": ariaLabelledBy !== void 0 ? void 0 : ariaLabel !== void 0 ? `${ariaLabel}${separator}${spoken}` : label !== void 0 ? `${label}${separator}${spoken}` : spoken,
36
+ ...domProps,
37
+ children: [
38
+ /* @__PURE__ */ jsx("div", { className: "ui-progress-track", children: segments.map((segment, index) => /* @__PURE__ */ jsx(
39
+ "div",
40
+ {
41
+ className: "ui-progress-segment",
42
+ "data-tone": segment.tone,
43
+ style: { inlineSize: total === 0 ? "0%" : `${amounts[index] / total * 100}%` }
44
+ },
45
+ `${segment.label}-${index}`
46
+ )) }),
47
+ caption
48
+ ]
49
+ }
50
+ );
51
+ }
52
+ const meterValue = value ?? 0;
53
+ const isOver = over && meterValue > 100;
54
+ const boundedValue = Math.max(0, Math.min(100, meterValue));
55
+ const effectiveTone = tone ?? (isOver ? "destructive" : "success");
9
56
  return /* @__PURE__ */ jsxs(
10
57
  "div",
11
58
  {
12
- className: "ui-progress",
59
+ className: cn("ui-progress", className),
13
60
  "data-tone": effectiveTone,
14
61
  "data-over": isOver ? "" : void 0,
15
62
  role: "progressbar",
16
63
  "aria-valuenow": boundedValue,
17
64
  "aria-valuemin": 0,
18
65
  "aria-valuemax": 100,
19
- "aria-valuetext": `${isOver ? Math.round(value) : boundedValue}%`,
20
- "aria-labelledby": label ? labelId : void 0,
21
- "aria-label": label ? void 0 : "Progress",
66
+ "aria-valuetext": `${isOver ? Math.round(meterValue) : boundedValue}%`,
67
+ "aria-labelledby": labelledBy,
68
+ "aria-label": labelledBy !== void 0 ? void 0 : named ? ariaLabel : t("dataDisplay.progress.ariaLabel"),
69
+ ...domProps,
22
70
  children: [
23
71
  /* @__PURE__ */ jsx("div", { className: "ui-progress-track", children: /* @__PURE__ */ jsx("div", { className: "ui-progress-bar", style: { width: `${boundedValue}%` } }) }),
24
- label ? /* @__PURE__ */ jsx("div", { className: "ui-progress-label", id: labelId, children: label }) : null
72
+ caption
25
73
  ]
26
74
  }
27
75
  );
@@ -0,0 +1,38 @@
1
+ import * as React from "react";
2
+ export type RangeTimelineRow = {
3
+ id: string;
4
+ label: React.ReactNode;
5
+ start: number;
6
+ end: number;
7
+ startLabel: string;
8
+ endLabel: string;
9
+ };
10
+ export type RangeTimelineProps = React.HTMLAttributes<HTMLElement> & {
11
+ label: string;
12
+ columns: {
13
+ label: string;
14
+ units: number;
15
+ }[];
16
+ bands?: {
17
+ label: string;
18
+ units: number;
19
+ }[];
20
+ rows: RangeTimelineRow[];
21
+ today?: number | null;
22
+ onRangeChange?: (id: string, edge: "start" | "end", delta: number) => void;
23
+ };
24
+ /** A horizontal range axis. Units and labels are data; the design system owns all geometry. */
25
+ export declare const RangeTimeline: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
26
+ label: string;
27
+ columns: {
28
+ label: string;
29
+ units: number;
30
+ }[];
31
+ bands?: {
32
+ label: string;
33
+ units: number;
34
+ }[];
35
+ rows: RangeTimelineRow[];
36
+ today?: number | null;
37
+ onRangeChange?: (id: string, edge: "start" | "end", delta: number) => void;
38
+ } & React.RefAttributes<HTMLElement>>;
@@ -0,0 +1,161 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { useTranslation } from "../../i18n/use-translation.js";
5
+ import { GripVertical } from "lucide-react";
6
+ import { Button } from "../general/button.js";
7
+ import { Text } from "../general/typography.js";
8
+ import { cn } from "../../lib/utils.js";
9
+ const RangeTimeline = React.forwardRef(
10
+ function RangeTimeline2({ label, columns, bands, rows, today, onRangeChange, className, ...props }, ref) {
11
+ const { t } = useTranslation();
12
+ const units = Math.max(
13
+ 1,
14
+ columns.reduce((sum, column) => sum + column.units, 0)
15
+ );
16
+ const track = React.useRef(null);
17
+ const drag = React.useRef(null);
18
+ const [preview, setPreview] = React.useState(null);
19
+ const deltaAt = (x) => drag.current ? Math.round((x - drag.current.x) * units * drag.current.direction / drag.current.width) : 0;
20
+ const cancel = () => {
21
+ drag.current = null;
22
+ setPreview(null);
23
+ };
24
+ const complete = (event) => {
25
+ const current = drag.current;
26
+ if (!current) return;
27
+ const row = rows.find((row2) => row2.id === current.id);
28
+ const delta = deltaAt(event.clientX);
29
+ cancel();
30
+ if (!row) return;
31
+ const bounded = current.edge === "start" ? Math.min(delta, row.end - row.start) : Math.max(delta, row.start - row.end);
32
+ if (bounded) onRangeChange?.(row.id, current.edge, bounded);
33
+ };
34
+ return /* @__PURE__ */ jsx(
35
+ "section",
36
+ {
37
+ ...props,
38
+ ref,
39
+ className: cn("ui-range-timeline", className),
40
+ "aria-label": label,
41
+ tabIndex: 0,
42
+ children: /* @__PURE__ */ jsxs(
43
+ "div",
44
+ {
45
+ className: "ui-range-timeline-canvas",
46
+ style: { "--range-timeline-columns": Math.max(1, columns.length) },
47
+ children: [
48
+ bands && bands.length > 0 && /* @__PURE__ */ jsxs("div", { className: "ui-range-timeline-header", children: [
49
+ /* @__PURE__ */ jsx("div", { className: "ui-range-timeline-label", "aria-hidden": "true" }),
50
+ /* @__PURE__ */ jsx("div", { className: "ui-range-timeline-columns", children: bands.map((band, index) => /* @__PURE__ */ jsx(
51
+ "div",
52
+ {
53
+ className: "ui-range-timeline-column",
54
+ style: { flex: band.units },
55
+ children: /* @__PURE__ */ jsx(Text, { size: "xs", weight: "medium", children: band.label })
56
+ },
57
+ index
58
+ )) })
59
+ ] }),
60
+ /* @__PURE__ */ jsxs("div", { className: "ui-range-timeline-header", children: [
61
+ /* @__PURE__ */ jsx("div", { className: "ui-range-timeline-label", children: /* @__PURE__ */ jsx(Text, { weight: "bold", children: label }) }),
62
+ /* @__PURE__ */ jsx("div", { className: "ui-range-timeline-columns", ref: track, children: columns.map((column, index) => /* @__PURE__ */ jsx(
63
+ "div",
64
+ {
65
+ className: "ui-range-timeline-column",
66
+ style: { flex: column.units },
67
+ children: /* @__PURE__ */ jsx(Text, { size: "xs", children: column.label })
68
+ },
69
+ index
70
+ )) })
71
+ ] }),
72
+ rows.map((row) => {
73
+ const delta = preview?.id === row.id ? preview.delta : 0;
74
+ const start = Math.min(row.end, row.start + (preview?.edge === "start" ? delta : 0));
75
+ const end = Math.max(row.start, row.end + (preview?.edge === "end" ? delta : 0));
76
+ const left = Math.max(0, start), right = Math.min(units, end + 1);
77
+ return /* @__PURE__ */ jsxs("div", { className: "ui-range-timeline-row", children: [
78
+ /* @__PURE__ */ jsx("div", { className: "ui-range-timeline-label", children: row.label }),
79
+ /* @__PURE__ */ jsxs("div", { className: "ui-range-timeline-track", children: [
80
+ today != null && today >= 0 && today < units && /* @__PURE__ */ jsx(
81
+ "span",
82
+ {
83
+ "aria-hidden": "true",
84
+ className: "ui-range-timeline-today",
85
+ style: { insetInlineStart: `${(today + 0.5) / units * 100}%` }
86
+ }
87
+ ),
88
+ right <= left && /* @__PURE__ */ jsx(Text, { tone: "muted", children: t("rangeTimeline.outsideRange") }),
89
+ right > left && /* @__PURE__ */ jsx(
90
+ "div",
91
+ {
92
+ className: "ui-range-timeline-bar",
93
+ style: {
94
+ insetInlineStart: `${left / units * 100}%`,
95
+ inlineSize: `${(right - left) / units * 100}%`
96
+ },
97
+ children: onRangeChange && (right - left) * Math.max(1, columns.length) >= units && ["start", "end"].filter(
98
+ (edge) => edge === "start" ? start >= 0 && start < units : end >= 0 && end < units
99
+ ).map((edge) => /* @__PURE__ */ jsx(
100
+ Button,
101
+ {
102
+ variant: "ghost",
103
+ size: "icon-xs",
104
+ className: "ui-range-timeline-handle",
105
+ "data-edge": edge,
106
+ "aria-label": edge === "start" ? row.startLabel : row.endLabel,
107
+ onPointerDown: (event) => {
108
+ const width = track.current?.getBoundingClientRect().width ?? 0;
109
+ if (!width || event.button !== 0) return;
110
+ event.currentTarget.setPointerCapture(event.pointerId);
111
+ drag.current = {
112
+ id: row.id,
113
+ edge,
114
+ x: event.clientX,
115
+ width,
116
+ direction: getComputedStyle(event.currentTarget).direction === "rtl" ? -1 : 1
117
+ };
118
+ },
119
+ onPointerMove: (event) => {
120
+ if (drag.current)
121
+ setPreview({
122
+ id: drag.current.id,
123
+ edge: drag.current.edge,
124
+ delta: deltaAt(event.clientX)
125
+ });
126
+ },
127
+ onPointerUp: complete,
128
+ onPointerCancel: cancel,
129
+ onLostPointerCapture: cancel,
130
+ onKeyDown: (event) => {
131
+ if (event.key === "Escape") {
132
+ cancel();
133
+ return;
134
+ }
135
+ const step = event.key === "ArrowRight" ? 1 : event.key === "ArrowLeft" ? -1 : 0;
136
+ if (!step) return;
137
+ event.preventDefault();
138
+ const direction = getComputedStyle(event.currentTarget).direction === "rtl" ? -1 : 1;
139
+ const delta2 = step * direction;
140
+ if (edge === "start" ? row.start + delta2 <= row.end : row.end + delta2 >= row.start)
141
+ onRangeChange(row.id, edge, delta2);
142
+ },
143
+ children: /* @__PURE__ */ jsx(GripVertical, { "aria-hidden": "true" })
144
+ },
145
+ edge
146
+ ))
147
+ }
148
+ )
149
+ ] })
150
+ ] }, row.id);
151
+ })
152
+ ]
153
+ }
154
+ )
155
+ }
156
+ );
157
+ }
158
+ );
159
+ export {
160
+ RangeTimeline
161
+ };