@funstack/ui 0.1.0-alpha.1 → 0.1.0-alpha.3

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/dist/accordion/accordion-context.mjs.map +1 -1
  2. package/dist/accordion/accordion-item.mjs +18 -4
  3. package/dist/accordion/accordion-item.mjs.map +1 -1
  4. package/dist/accordion/accordion-panel.mjs +2 -3
  5. package/dist/accordion/accordion-panel.mjs.map +1 -1
  6. package/dist/accordion/accordion-root.d.mts.map +1 -1
  7. package/dist/accordion/accordion-root.mjs +32 -14
  8. package/dist/accordion/accordion-root.mjs.map +1 -1
  9. package/dist/accordion/accordion-trigger.mjs +4 -5
  10. package/dist/accordion/accordion-trigger.mjs.map +1 -1
  11. package/dist/checkbox/checkbox.d.mts +5 -3
  12. package/dist/checkbox/checkbox.d.mts.map +1 -1
  13. package/dist/checkbox/checkbox.mjs +25 -9
  14. package/dist/checkbox/checkbox.mjs.map +1 -1
  15. package/dist/checkbox-group/checkbox-group-context.mjs.map +1 -1
  16. package/dist/checkbox-group/checkbox-group-item.d.mts +2 -1
  17. package/dist/checkbox-group/checkbox-group-item.d.mts.map +1 -1
  18. package/dist/checkbox-group/checkbox-group-item.mjs +3 -1
  19. package/dist/checkbox-group/checkbox-group-item.mjs.map +1 -1
  20. package/dist/checkbox-group/checkbox-group-root.d.mts +5 -2
  21. package/dist/checkbox-group/checkbox-group-root.d.mts.map +1 -1
  22. package/dist/checkbox-group/checkbox-group-root.mjs +24 -5
  23. package/dist/checkbox-group/checkbox-group-root.mjs.map +1 -1
  24. package/dist/combobox/combobox-clear.d.mts +34 -0
  25. package/dist/combobox/combobox-clear.d.mts.map +1 -0
  26. package/dist/combobox/combobox-clear.mjs +58 -0
  27. package/dist/combobox/combobox-clear.mjs.map +1 -0
  28. package/dist/combobox/combobox-context.mjs +23 -0
  29. package/dist/combobox/combobox-context.mjs.map +1 -0
  30. package/dist/combobox/combobox-group.d.mts +72 -0
  31. package/dist/combobox/combobox-group.d.mts.map +1 -0
  32. package/dist/combobox/combobox-group.mjs +104 -0
  33. package/dist/combobox/combobox-group.mjs.map +1 -0
  34. package/dist/combobox/combobox-input.d.mts +42 -0
  35. package/dist/combobox/combobox-input.d.mts.map +1 -0
  36. package/dist/combobox/combobox-input.mjs +102 -0
  37. package/dist/combobox/combobox-input.mjs.map +1 -0
  38. package/dist/combobox/combobox-label.d.mts +22 -0
  39. package/dist/combobox/combobox-label.d.mts.map +1 -0
  40. package/dist/combobox/combobox-label.mjs +32 -0
  41. package/dist/combobox/combobox-label.mjs.map +1 -0
  42. package/dist/combobox/combobox-list.d.mts +37 -0
  43. package/dist/combobox/combobox-list.d.mts.map +1 -0
  44. package/dist/combobox/combobox-list.mjs +70 -0
  45. package/dist/combobox/combobox-list.mjs.map +1 -0
  46. package/dist/combobox/combobox-option.d.mts +45 -0
  47. package/dist/combobox/combobox-option.d.mts.map +1 -0
  48. package/dist/combobox/combobox-option.mjs +88 -0
  49. package/dist/combobox/combobox-option.mjs.map +1 -0
  50. package/dist/combobox/combobox-popup.d.mts +49 -0
  51. package/dist/combobox/combobox-popup.d.mts.map +1 -0
  52. package/dist/combobox/combobox-popup.mjs +86 -0
  53. package/dist/combobox/combobox-popup.mjs.map +1 -0
  54. package/dist/combobox/combobox-root.d.mts +135 -0
  55. package/dist/combobox/combobox-root.d.mts.map +1 -0
  56. package/dist/combobox/combobox-root.mjs +523 -0
  57. package/dist/combobox/combobox-root.mjs.map +1 -0
  58. package/dist/combobox/combobox-trigger.d.mts +36 -0
  59. package/dist/combobox/combobox-trigger.d.mts.map +1 -0
  60. package/dist/combobox/combobox-trigger.mjs +92 -0
  61. package/dist/combobox/combobox-trigger.mjs.map +1 -0
  62. package/dist/combobox/index.d.mts +36 -0
  63. package/dist/combobox/index.d.mts.map +1 -0
  64. package/dist/combobox/index.mjs +36 -0
  65. package/dist/combobox/index.mjs.map +1 -0
  66. package/dist/dialog/dialog-close.d.mts +17 -10
  67. package/dist/dialog/dialog-close.d.mts.map +1 -1
  68. package/dist/dialog/dialog-close.mjs +31 -20
  69. package/dist/dialog/dialog-close.mjs.map +1 -1
  70. package/dist/dialog/dialog-context.mjs.map +1 -1
  71. package/dist/dialog/dialog-form.d.mts +12 -5
  72. package/dist/dialog/dialog-form.d.mts.map +1 -1
  73. package/dist/dialog/dialog-form.mjs +16 -28
  74. package/dist/dialog/dialog-form.mjs.map +1 -1
  75. package/dist/dialog/dialog-popup.d.mts +10 -4
  76. package/dist/dialog/dialog-popup.d.mts.map +1 -1
  77. package/dist/dialog/dialog-popup.mjs +106 -41
  78. package/dist/dialog/dialog-popup.mjs.map +1 -1
  79. package/dist/dialog/dialog-root.d.mts +14 -8
  80. package/dist/dialog/dialog-root.d.mts.map +1 -1
  81. package/dist/dialog/dialog-root.mjs +66 -11
  82. package/dist/dialog/dialog-root.mjs.map +1 -1
  83. package/dist/dialog/dialog-trigger.d.mts +3 -2
  84. package/dist/dialog/dialog-trigger.d.mts.map +1 -1
  85. package/dist/dialog/dialog-trigger.mjs.map +1 -1
  86. package/dist/dialog/index.d.mts +4 -2
  87. package/dist/dialog/index.d.mts.map +1 -1
  88. package/dist/dialog/index.mjs +4 -2
  89. package/dist/dialog/index.mjs.map +1 -1
  90. package/dist/field/field-control.d.mts +33 -0
  91. package/dist/field/field-control.d.mts.map +1 -0
  92. package/dist/field/field-control.mjs +68 -0
  93. package/dist/field/field-control.mjs.map +1 -0
  94. package/dist/field/field-description.d.mts +24 -0
  95. package/dist/field/field-description.d.mts.map +1 -0
  96. package/dist/field/field-description.mjs +34 -0
  97. package/dist/field/field-description.mjs.map +1 -0
  98. package/dist/field/field-error.d.mts +30 -0
  99. package/dist/field/field-error.d.mts.map +1 -0
  100. package/dist/field/field-error.mjs +42 -0
  101. package/dist/field/field-error.mjs.map +1 -0
  102. package/dist/field/field-label.d.mts +25 -0
  103. package/dist/field/field-label.d.mts.map +1 -0
  104. package/dist/field/field-label.mjs +46 -0
  105. package/dist/field/field-label.mjs.map +1 -0
  106. package/dist/field/field-root.d.mts +53 -0
  107. package/dist/field/field-root.d.mts.map +1 -0
  108. package/dist/field/field-root.mjs +317 -0
  109. package/dist/field/field-root.mjs.map +1 -0
  110. package/dist/field/index.d.mts +18 -0
  111. package/dist/field/index.d.mts.map +1 -0
  112. package/dist/field/index.mjs +17 -0
  113. package/dist/field/index.mjs.map +1 -0
  114. package/dist/form/form-root.d.mts +58 -0
  115. package/dist/form/form-root.d.mts.map +1 -0
  116. package/dist/form/form-root.mjs +146 -0
  117. package/dist/form/form-root.mjs.map +1 -0
  118. package/dist/form/form-submit.d.mts +31 -0
  119. package/dist/form/form-submit.d.mts.map +1 -0
  120. package/dist/form/form-submit.mjs +52 -0
  121. package/dist/form/form-submit.mjs.map +1 -0
  122. package/dist/form/index.d.mts +11 -0
  123. package/dist/form/index.d.mts.map +1 -0
  124. package/dist/form/index.mjs +11 -0
  125. package/dist/form/index.mjs.map +1 -0
  126. package/dist/index.d.mts +46 -2
  127. package/dist/index.mjs +8 -1
  128. package/dist/internal/content-focus-probe.mjs +42 -0
  129. package/dist/internal/content-focus-probe.mjs.map +1 -0
  130. package/dist/internal/field-context.d.mts +19 -0
  131. package/dist/internal/field-context.d.mts.map +1 -0
  132. package/dist/internal/field-context.mjs +14 -0
  133. package/dist/internal/field-context.mjs.map +1 -0
  134. package/dist/internal/focus-first-invalid.mjs +67 -0
  135. package/dist/internal/focus-first-invalid.mjs.map +1 -0
  136. package/dist/internal/form-status-watcher.mjs +31 -0
  137. package/dist/internal/form-status-watcher.mjs.map +1 -0
  138. package/dist/internal/modal-registry.mjs +39 -0
  139. package/dist/internal/modal-registry.mjs.map +1 -0
  140. package/dist/internal/platform-attributes.d.mts +12 -1
  141. package/dist/internal/platform-attributes.d.mts.map +1 -1
  142. package/dist/internal/types.d.mts +11 -1
  143. package/dist/internal/types.d.mts.map +1 -1
  144. package/dist/internal/use-controllable-action.mjs +35 -13
  145. package/dist/internal/use-controllable-action.mjs.map +1 -1
  146. package/dist/internal/use-field-control.mjs +107 -0
  147. package/dist/internal/use-field-control.mjs.map +1 -0
  148. package/dist/internal/use-form-owner-event.mjs +44 -0
  149. package/dist/internal/use-form-owner-event.mjs.map +1 -0
  150. package/dist/internal/use-form-reset.mjs +12 -31
  151. package/dist/internal/use-form-reset.mjs.map +1 -1
  152. package/dist/internal/use-hydrated-mount.mjs +21 -0
  153. package/dist/internal/use-hydrated-mount.mjs.map +1 -0
  154. package/dist/internal/use-latest.mjs +32 -0
  155. package/dist/internal/use-latest.mjs.map +1 -0
  156. package/dist/internal/use-modal-registration.mjs +47 -0
  157. package/dist/internal/use-modal-registration.mjs.map +1 -0
  158. package/dist/internal/use-native-group-reconciliation.mjs +6 -5
  159. package/dist/internal/use-native-group-reconciliation.mjs.map +1 -1
  160. package/dist/internal/use-native-select-value.mjs +184 -0
  161. package/dist/internal/use-native-select-value.mjs.map +1 -0
  162. package/dist/internal/use-popover-popup.mjs +8 -22
  163. package/dist/internal/use-popover-popup.mjs.map +1 -1
  164. package/dist/internal/use-popover-root.mjs +58 -23
  165. package/dist/internal/use-popover-root.mjs.map +1 -1
  166. package/dist/internal/validity.d.mts +24 -0
  167. package/dist/internal/validity.d.mts.map +1 -0
  168. package/dist/internal/validity.mjs +108 -0
  169. package/dist/internal/validity.mjs.map +1 -0
  170. package/dist/menu/menu-group.d.mts.map +1 -1
  171. package/dist/menu/menu-group.mjs +3 -2
  172. package/dist/menu/menu-group.mjs.map +1 -1
  173. package/dist/menu/menu-radio-group.mjs +9 -4
  174. package/dist/menu/menu-radio-group.mjs.map +1 -1
  175. package/dist/menu/menu-root.mjs.map +1 -1
  176. package/dist/radio-group/radio-group-root.d.mts +4 -2
  177. package/dist/radio-group/radio-group-root.d.mts.map +1 -1
  178. package/dist/radio-group/radio-group-root.mjs +34 -8
  179. package/dist/radio-group/radio-group-root.mjs.map +1 -1
  180. package/dist/select/index.d.mts +30 -0
  181. package/dist/select/index.d.mts.map +1 -0
  182. package/dist/select/index.mjs +30 -0
  183. package/dist/select/index.mjs.map +1 -0
  184. package/dist/select/select-context.mjs +13 -0
  185. package/dist/select/select-context.mjs.map +1 -0
  186. package/dist/select/select-dom.mjs +44 -0
  187. package/dist/select/select-dom.mjs.map +1 -0
  188. package/dist/select/select-group-label.d.mts +22 -0
  189. package/dist/select/select-group-label.d.mts.map +1 -0
  190. package/dist/select/select-group-label.mjs +39 -0
  191. package/dist/select/select-group-label.mjs.map +1 -0
  192. package/dist/select/select-group.d.mts +28 -0
  193. package/dist/select/select-group.d.mts.map +1 -0
  194. package/dist/select/select-group.mjs +47 -0
  195. package/dist/select/select-group.mjs.map +1 -0
  196. package/dist/select/select-option.d.mts +42 -0
  197. package/dist/select/select-option.d.mts.map +1 -0
  198. package/dist/select/select-option.mjs +65 -0
  199. package/dist/select/select-option.mjs.map +1 -0
  200. package/dist/select/select-root.d.mts +68 -0
  201. package/dist/select/select-root.d.mts.map +1 -0
  202. package/dist/select/select-root.mjs +114 -0
  203. package/dist/select/select-root.mjs.map +1 -0
  204. package/dist/select/select-separator.d.mts +20 -0
  205. package/dist/select/select-separator.d.mts.map +1 -0
  206. package/dist/select/select-separator.mjs +30 -0
  207. package/dist/select/select-separator.mjs.map +1 -0
  208. package/dist/select/select-trigger.d.mts +29 -0
  209. package/dist/select/select-trigger.d.mts.map +1 -0
  210. package/dist/select/select-trigger.mjs +48 -0
  211. package/dist/select/select-trigger.mjs.map +1 -0
  212. package/dist/select/select-value.d.mts +31 -0
  213. package/dist/select/select-value.d.mts.map +1 -0
  214. package/dist/select/select-value.mjs +101 -0
  215. package/dist/select/select-value.mjs.map +1 -0
  216. package/dist/slider/index.d.mts +32 -0
  217. package/dist/slider/index.d.mts.map +1 -0
  218. package/dist/slider/index.mjs +27 -0
  219. package/dist/slider/index.mjs.map +1 -0
  220. package/dist/slider/slider-arithmetic.mjs +120 -0
  221. package/dist/slider/slider-arithmetic.mjs.map +1 -0
  222. package/dist/slider/slider-context.mjs +13 -0
  223. package/dist/slider/slider-context.mjs.map +1 -0
  224. package/dist/slider/slider-indicator.d.mts +22 -0
  225. package/dist/slider/slider-indicator.d.mts.map +1 -0
  226. package/dist/slider/slider-indicator.mjs +36 -0
  227. package/dist/slider/slider-indicator.mjs.map +1 -0
  228. package/dist/slider/slider-label.d.mts +23 -0
  229. package/dist/slider/slider-label.d.mts.map +1 -0
  230. package/dist/slider/slider-label.mjs +44 -0
  231. package/dist/slider/slider-label.mjs.map +1 -0
  232. package/dist/slider/slider-root.d.mts +111 -0
  233. package/dist/slider/slider-root.d.mts.map +1 -0
  234. package/dist/slider/slider-root.mjs +582 -0
  235. package/dist/slider/slider-root.mjs.map +1 -0
  236. package/dist/slider/slider-thumb.d.mts +58 -0
  237. package/dist/slider/slider-thumb.d.mts.map +1 -0
  238. package/dist/slider/slider-thumb.mjs +145 -0
  239. package/dist/slider/slider-thumb.mjs.map +1 -0
  240. package/dist/slider/slider-track.d.mts +29 -0
  241. package/dist/slider/slider-track.d.mts.map +1 -0
  242. package/dist/slider/slider-track.mjs +54 -0
  243. package/dist/slider/slider-track.mjs.map +1 -0
  244. package/dist/slider/slider-value.d.mts +34 -0
  245. package/dist/slider/slider-value.d.mts.map +1 -0
  246. package/dist/slider/slider-value.mjs +38 -0
  247. package/dist/slider/slider-value.mjs.map +1 -0
  248. package/dist/switch/switch.d.mts +5 -3
  249. package/dist/switch/switch.d.mts.map +1 -1
  250. package/dist/switch/switch.mjs +24 -8
  251. package/dist/switch/switch.mjs.map +1 -1
  252. package/dist/tabs/tabs-root.mjs +13 -3
  253. package/dist/tabs/tabs-root.mjs.map +1 -1
  254. package/dist/toast/index.d.mts +25 -0
  255. package/dist/toast/index.d.mts.map +1 -0
  256. package/dist/toast/index.mjs +26 -0
  257. package/dist/toast/index.mjs.map +1 -0
  258. package/dist/toast/toast-action.d.mts +39 -0
  259. package/dist/toast/toast-action.d.mts.map +1 -0
  260. package/dist/toast/toast-action.mjs +64 -0
  261. package/dist/toast/toast-action.mjs.map +1 -0
  262. package/dist/toast/toast-close.d.mts +25 -0
  263. package/dist/toast/toast-close.d.mts.map +1 -0
  264. package/dist/toast/toast-close.mjs +46 -0
  265. package/dist/toast/toast-close.mjs.map +1 -0
  266. package/dist/toast/toast-context.mjs +19 -0
  267. package/dist/toast/toast-context.mjs.map +1 -0
  268. package/dist/toast/toast-description.d.mts +24 -0
  269. package/dist/toast/toast-description.d.mts.map +1 -0
  270. package/dist/toast/toast-description.mjs +35 -0
  271. package/dist/toast/toast-description.mjs.map +1 -0
  272. package/dist/toast/toast-root.d.mts +43 -0
  273. package/dist/toast/toast-root.d.mts.map +1 -0
  274. package/dist/toast/toast-root.mjs +204 -0
  275. package/dist/toast/toast-root.mjs.map +1 -0
  276. package/dist/toast/toast-title.d.mts +24 -0
  277. package/dist/toast/toast-title.d.mts.map +1 -0
  278. package/dist/toast/toast-title.mjs +33 -0
  279. package/dist/toast/toast-title.mjs.map +1 -0
  280. package/dist/toast/toast-viewport.d.mts +52 -0
  281. package/dist/toast/toast-viewport.d.mts.map +1 -0
  282. package/dist/toast/toast-viewport.mjs +621 -0
  283. package/dist/toast/toast-viewport.mjs.map +1 -0
  284. package/dist/toast/toast.d.mts +119 -0
  285. package/dist/toast/toast.d.mts.map +1 -0
  286. package/dist/toast/toast.mjs +153 -0
  287. package/dist/toast/toast.mjs.map +1 -0
  288. package/package.json +7 -1
@@ -0,0 +1,582 @@
1
+ "use client";
2
+ import { createActionDetails } from "../internal/action-details.mjs";
3
+ import { dataAttr } from "../internal/data-attr.mjs";
4
+ import { transitionTypes } from "../internal/transition-types.mjs";
5
+ import { useLatest } from "../internal/use-latest.mjs";
6
+ import { useControllableAction } from "../internal/use-controllable-action.mjs";
7
+ import { mergeTokenLists } from "../internal/merge-props.mjs";
8
+ import { resolveStateValue, useRender } from "../internal/use-render.mjs";
9
+ import { useDevWarning } from "../internal/use-dev-warning.mjs";
10
+ import { FieldContext } from "../internal/field-context.mjs";
11
+ import { useFieldControl, useFieldValueChange, useMergedRef } from "../internal/use-field-control.mjs";
12
+ import { useActionTrigger } from "../internal/use-action-trigger.mjs";
13
+ import { useNativeGroupReconciliation } from "../internal/use-native-group-reconciliation.mjs";
14
+ import { SliderContext } from "./slider-context.mjs";
15
+ import { clampToNeighbours, equalValues, isMaxReachable, isOnGrid, nearestThumb, percent, platformDefault, sanitize } from "./slider-arithmetic.mjs";
16
+ import { addTransitionType, use, useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
17
+ import { jsx } from "react/jsx-runtime";
18
+ //#region src/slider/slider-root.tsx
19
+ const isDev = process.env.NODE_ENV !== "production";
20
+ const STEP_TYPES = transitionTypes("slider", "change");
21
+ const COMMIT_TYPES = transitionTypes("slider", "commit");
22
+ function toArray(value) {
23
+ return typeof value === "number" ? [value] : value;
24
+ }
25
+ function shapeOf(value) {
26
+ if (value === void 0) return void 0;
27
+ return typeof value === "number" ? "number" : "array";
28
+ }
29
+ function replaceAt(values, index, value) {
30
+ return values.map((v, i) => i === index ? value : v);
31
+ }
32
+ /** Writes each registered input's `defaultValue` (the attribute a form reset restores). */
33
+ function writeDefaults(registry, target) {
34
+ for (const [index, input] of registry) {
35
+ const entry = target[index];
36
+ if (entry !== void 0) input.defaultValue = String(entry);
37
+ }
38
+ }
39
+ /**
40
+ * Owns the slider's state (design/components/slider.md 2): the committed value through
41
+ * `useControllableAction` with `valueCommitAction` (once per gesture), each step through its own
42
+ * transition (`valueChangeAction`), and the value a gesture has reached in the urgent lane
43
+ * (`live`), which the thumbs show while a pointer is captured or anything is in flight. Also the
44
+ * pointer gesture, the Thumb registry, mount reconciliation and form reset, and the geometry
45
+ * custom properties `--slider-start`, `--slider-end` and `--slider-value-<i>`.
46
+ *
47
+ * Owned keys (conventions 1.2): `role` (`"group"` with several thumbs), `aria-labelledby` (the
48
+ * Label's id while a Label is mounted and there are several thumbs; token-merged with the
49
+ * consumer's), `data-pending`, `data-dragging`, `data-orientation`, `data-disabled`. The custom
50
+ * properties are merged into `style`, where the consumer's entries win.
51
+ *
52
+ * Inside a `Field.Root` (design 9.4) the Root calls `useFieldControl`: with one thumb, Thumb 0's
53
+ * input is the Field's labelable control; with several, the Root registers itself as the group
54
+ * and also owns the Field label in `aria-labelledby`, the Field's `aria-describedby` and
55
+ * `data-invalid`. `name` / `disabled` default from the Field.
56
+ */
57
+ function SliderRootImpl(props) {
58
+ const { value, defaultValue, valueChangeAction, valueCommitAction, min = 0, max = 100, step: stepProp = 1, minStepsBetweenThumbs = 0, orientation = "horizontal", getAriaValueText, name: nameProp, form, disabled: disabledProp = false, className, style, children, render, ...rest } = props;
59
+ const stepValid = Number.isFinite(stepProp) && stepProp > 0;
60
+ const step = stepValid ? stepProp : 1;
61
+ const gap = Math.max(0, minStepsBetweenThumbs) * step;
62
+ const id = useId();
63
+ const labelId = `${id}-label`;
64
+ const [shape] = useState(() => shapeOf(value ?? defaultValue) ?? "number");
65
+ const fromArray = useCallback((values) => shape === "number" ? values[0] : values, [shape]);
66
+ const [live, setLive] = useState(null);
67
+ const [gestureThumb, setGestureThumb] = useState(null);
68
+ /**
69
+ * A step was taken and its gesture's commit has not been dispatched yet. Holds `live` on
70
+ * screen between a key's native `input` and `change` when no step transition runs (no
71
+ * `valueChangeAction`): otherwise react-dom restores the controlled input to the old value
72
+ * after `input`, and Firefox then fires no `change`.
73
+ */
74
+ const [stepHeld, setStepHeld] = useState(false);
75
+ const [pendingThumb, setPendingThumb] = useState(null);
76
+ /** The value of the latest step, read by the commit in the same or a later event. */
77
+ const liveRef = useRef(null);
78
+ /** The shown value when the open gesture began; `null` when no gesture is open. */
79
+ const gestureStart = useRef(null);
80
+ const activeGesture = useRef(null);
81
+ const commitSeq = useRef(0);
82
+ const trackRef = useRef(null);
83
+ const runCommit = async (next, details) => {
84
+ const seq = ++commitSeq.current;
85
+ try {
86
+ await valueCommitAction?.(next, details);
87
+ } catch (error) {
88
+ if (value === void 0 && seq === commitSeq.current) {
89
+ await void 0;
90
+ stepTo(toArray(committedRef.current), null, "dismiss", void 0);
91
+ }
92
+ throw error;
93
+ }
94
+ };
95
+ const commitState = useControllableAction({
96
+ controlled: value,
97
+ defaultValue,
98
+ initialValue: platformDefault(min, max, step),
99
+ action: runCommit,
100
+ transitionTypes: () => COMMIT_TYPES,
101
+ warn: {
102
+ component: "Slider.Root",
103
+ prop: "value"
104
+ }
105
+ });
106
+ const { optimistic, committed, dispatch } = commitState;
107
+ const committedRef = useLatest(committed);
108
+ const { pending: stepPending, run: runStep } = useActionTrigger();
109
+ const optimisticValues = useMemo(() => toArray(optimistic), [optimistic]);
110
+ const shown = (gestureThumb !== null || stepHeld || stepPending || commitState.pending) && live !== null ? live : optimisticValues;
111
+ const pending = stepPending || commitState.pending;
112
+ const thumbCount = shown.length;
113
+ const field = useFieldControl({
114
+ labelable: thumbCount === 1,
115
+ name: nameProp,
116
+ disabled: disabledProp,
117
+ component: "Slider.Root"
118
+ });
119
+ const fieldName = use(FieldContext)?.name;
120
+ const name = field.name;
121
+ const disabled = field.disabled;
122
+ const fieldId = field.id;
123
+ const thumbId = useCallback((index) => index === 0 && fieldId !== void 0 ? fieldId : `${id}-thumb-${index}`, [id, fieldId]);
124
+ const rootRef = useMergedRef(void 0, thumbCount > 1 ? field.ref : void 0);
125
+ useDevWarning(field.inField && field.required, "Slider.Root: a range is never empty, so `required` on the enclosing Field.Root has no effect on the slider.");
126
+ /**
127
+ * The reason of the latest change the user or the platform made, consumed by the Field
128
+ * notification below: `"activate"` dismisses a shown server error, a rollback does not.
129
+ */
130
+ const lastReason = useRef(null);
131
+ useFieldValueChange(optimisticValues.join("\0"), () => {
132
+ const edit = lastReason.current === "activate";
133
+ lastReason.current = null;
134
+ return edit;
135
+ });
136
+ const { "aria-labelledby": fieldLabelledBy, "aria-describedby": fieldDescribedBy, "aria-invalid": fieldInvalid, "data-invalid": fieldDataInvalid } = field.attributes;
137
+ const inField = field.inField;
138
+ const fieldRef = field.ref;
139
+ const fieldWiring = useMemo(() => {
140
+ if (!inField) return null;
141
+ const single = thumbCount === 1;
142
+ return {
143
+ inputRef: single ? fieldRef : void 0,
144
+ describedBy: single ? fieldDescribedBy : void 0,
145
+ invalid: fieldInvalid,
146
+ dataInvalid: fieldDataInvalid,
147
+ name: fieldName
148
+ };
149
+ }, [
150
+ inField,
151
+ fieldRef,
152
+ thumbCount,
153
+ fieldDescribedBy,
154
+ fieldInvalid,
155
+ fieldDataInvalid,
156
+ fieldName
157
+ ]);
158
+ /** What the thumbs show, for handlers; also written by `stepTo` ahead of the render. */
159
+ const shownRef = useLatest(shown);
160
+ const latest = useLatest({
161
+ valueChangeAction,
162
+ fromArray,
163
+ runStep,
164
+ min,
165
+ max,
166
+ step,
167
+ gap,
168
+ orientation,
169
+ disabled
170
+ });
171
+ const stepTo = useCallback((next, thumb, reason, event) => {
172
+ if (equalValues(next, shownRef.current)) return false;
173
+ liveRef.current = next;
174
+ shownRef.current = next;
175
+ lastReason.current = reason;
176
+ setLive(next);
177
+ setPendingThumb(thumb);
178
+ if (reason !== "dismiss") setStepHeld(true);
179
+ const { valueChangeAction: action, fromArray: toValue, runStep: run } = latest.current;
180
+ if (action === void 0) return true;
181
+ run(() => {
182
+ for (const type of STEP_TYPES) addTransitionType(type);
183
+ return action?.(toValue(next), createActionDetails(event, {
184
+ reason,
185
+ thumb
186
+ }));
187
+ });
188
+ return true;
189
+ }, [latest, shownRef]);
190
+ const commitGesture = useCallback((thumb, reason, event) => {
191
+ const start = gestureStart.current;
192
+ gestureStart.current = null;
193
+ setStepHeld(false);
194
+ const next = liveRef.current;
195
+ if (start === null || next === null || equalValues(next, start)) return;
196
+ lastReason.current = reason;
197
+ setPendingThumb(thumb);
198
+ dispatch(latest.current.fromArray(next), createActionDetails(event, {
199
+ reason,
200
+ thumb
201
+ }));
202
+ }, [dispatch, latest]);
203
+ const [registry] = useState(() => /* @__PURE__ */ new Map());
204
+ const warnedDuplicate = useRef(false);
205
+ const warnedForm = useRef(false);
206
+ const registerThumb = useCallback((index, input) => {
207
+ const existing = registry.get(index);
208
+ if (isDev && existing !== void 0 && existing !== input && !warnedDuplicate.current) {
209
+ warnedDuplicate.current = true;
210
+ console.error(`Slider.Thumb: two Thumbs have \`index={${index}}\`. Each value needs exactly one Thumb; give every Thumb a distinct index.`);
211
+ }
212
+ if (isDev && !warnedForm.current) {
213
+ for (const other of registry.values()) if (other !== input && other.form !== input.form) {
214
+ warnedForm.current = true;
215
+ console.error("Slider.Thumb: the thumbs of one Slider belong to different forms (a Thumb's `form` prop). A form reset is followed through the first thumb's form only; keep every thumb in one form.");
216
+ break;
217
+ }
218
+ }
219
+ registry.set(index, input);
220
+ return () => {
221
+ if (registry.get(index) === input) registry.delete(index);
222
+ };
223
+ }, [registry]);
224
+ /** The first registered input: the form-associated element the reset subscription follows. */
225
+ const formElement = useMemo(() => ({
226
+ get current() {
227
+ let first = null;
228
+ let firstIndex = Number.POSITIVE_INFINITY;
229
+ for (const [index, input] of registry) if (index < firstIndex) {
230
+ firstIndex = index;
231
+ first = input;
232
+ }
233
+ return first;
234
+ },
235
+ set current(_ignored) {}
236
+ }), [registry]);
237
+ const [labelCount, setLabelCount] = useState(0);
238
+ const labelCountRef = useRef(0);
239
+ const registerLabel = useCallback(() => {
240
+ labelCountRef.current += 1;
241
+ setLabelCount((count) => count + 1);
242
+ return () => {
243
+ labelCountRef.current -= 1;
244
+ setLabelCount((count) => count - 1);
245
+ };
246
+ }, []);
247
+ const [mountValue] = useState(value);
248
+ const resetTarget = () => value !== void 0 ? toArray(mountValue ?? value) : toArray(defaultValue ?? platformDefault(min, max, step));
249
+ const readCurrent = () => shownRef.current.map((v, index) => {
250
+ const input = registry.get(index);
251
+ if (input === void 0) return v;
252
+ const read = Number(input.value);
253
+ return Number.isFinite(read) ? read : v;
254
+ });
255
+ const { onItemMounted } = useNativeGroupReconciliation({
256
+ element: formElement,
257
+ readCurrent,
258
+ readDefault: resetTarget,
259
+ base: () => shownRef.current,
260
+ equals: (a, b) => {
261
+ const reference = shownRef.current;
262
+ return equalValues(sanitize(a, reference, min, max, step, gap), sanitize(b, reference, min, max, step, gap));
263
+ },
264
+ onPlatformChange: (next, event) => {
265
+ if (next.length !== shownRef.current.length) return;
266
+ const before = shownRef.current;
267
+ gestureStart.current = before;
268
+ liveRef.current = before;
269
+ stepTo(next, null, "platform", event);
270
+ commitGesture(null, "platform", event);
271
+ },
272
+ onResetEvent: () => {
273
+ writeDefaults(registry, resetTarget());
274
+ }
275
+ });
276
+ const inputStep = useCallback((index, raw, event) => {
277
+ if (!Number.isFinite(raw)) return;
278
+ const before = shownRef.current;
279
+ if (index >= before.length) return;
280
+ if (stepTo(replaceAt(before, index, raw), index, "activate", event)) {
281
+ if (gestureStart.current === null) gestureStart.current = before;
282
+ }
283
+ }, [shownRef, stepTo]);
284
+ const inputCommit = useCallback((index, event) => {
285
+ if (activeGesture.current !== null) return;
286
+ commitGesture(index, "activate", event);
287
+ }, [commitGesture]);
288
+ const inputKeyDown = useCallback((index, event) => {
289
+ const { orientation: axis, disabled: off, min: lo, max: hi, step: inc, gap: g } = latest.current;
290
+ if (off) return;
291
+ if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
292
+ if (event.altKey || event.ctrlKey || event.metaKey) return;
293
+ let increaseKey;
294
+ if (axis === "vertical") increaseKey = "ArrowRight";
295
+ else {
296
+ const input = event.currentTarget;
297
+ if (input === null || getComputedStyle(input).direction !== "rtl") return;
298
+ increaseKey = "ArrowLeft";
299
+ }
300
+ event.preventDefault();
301
+ const before = shownRef.current;
302
+ const current = before[index];
303
+ if (current === void 0) return;
304
+ const delta = event.key === increaseKey ? inc : -inc;
305
+ const next = replaceAt(before, index, clampToNeighbours(before, index, current + delta, lo, hi, inc, g));
306
+ if (activeGesture.current !== null) {
307
+ stepTo(next, index, "activate", event);
308
+ return;
309
+ }
310
+ gestureStart.current = before;
311
+ liveRef.current = before;
312
+ stepTo(next, index, "activate", event);
313
+ commitGesture(index, "activate", event);
314
+ }, [
315
+ commitGesture,
316
+ latest,
317
+ shownRef,
318
+ stepTo
319
+ ]);
320
+ const warnedNoTrack = useRef(false);
321
+ const beginGesture = useCallback((index, event, element) => {
322
+ const { disabled: off } = latest.current;
323
+ if (off || event.button !== 0 || activeGesture.current !== null) return;
324
+ const track = trackRef.current;
325
+ if (track === null) {
326
+ if (isDev && !warnedNoTrack.current) {
327
+ warnedNoTrack.current = true;
328
+ console.error("Slider.Thumb: a pointer press needs a Slider.Track to map the pointer to a value. Without a Track the slider is keyboard-only.");
329
+ }
330
+ return;
331
+ }
332
+ event.preventDefault();
333
+ const rtl = getComputedStyle(track).direction === "rtl";
334
+ const valueAt = (clientX, clientY) => {
335
+ const { min: lo, max: hi, orientation: axis } = latest.current;
336
+ const rect = (trackRef.current ?? track).getBoundingClientRect();
337
+ let fraction;
338
+ if (axis === "vertical") fraction = rect.height > 0 ? (rect.bottom - clientY) / rect.height : 0;
339
+ else {
340
+ fraction = rect.width > 0 ? (clientX - rect.left) / rect.width : 0;
341
+ if (rtl) fraction = 1 - fraction;
342
+ }
343
+ fraction = Math.min(1, Math.max(0, fraction));
344
+ return lo + fraction * (hi - lo);
345
+ };
346
+ const moveTo = (thumb, raw, cause) => {
347
+ const { min: lo, max: hi, step: inc, gap: g } = latest.current;
348
+ const before = shownRef.current;
349
+ if (thumb >= before.length) return;
350
+ stepTo(replaceAt(before, thumb, clampToNeighbours(before, thumb, raw, lo, hi, inc, g)), thumb, "activate", cause);
351
+ };
352
+ const start = valueAt(event.clientX, event.clientY);
353
+ const startValues = shownRef.current;
354
+ let tied = null;
355
+ if (index !== null) {
356
+ const at = startValues[index];
357
+ if (at !== void 0) {
358
+ let first = index;
359
+ let last = index;
360
+ while (first > 0 && equalValues([startValues[first - 1]], [at])) first -= 1;
361
+ while (last < startValues.length - 1 && equalValues([startValues[last + 1]], [at])) last += 1;
362
+ if (first !== last) tied = {
363
+ first,
364
+ last,
365
+ at
366
+ };
367
+ }
368
+ }
369
+ const resolveTie = (raw) => {
370
+ if (tied === null) return null;
371
+ if (raw > tied.at) return tied.last;
372
+ if (raw < tied.at) return tied.first;
373
+ return null;
374
+ };
375
+ /** The thumb the gesture moves; `null` while a press on stacked thumbs is undecided. */
376
+ let decided = index === null ? nearestThumb(startValues, start) : tied ? resolveTie(start) : index;
377
+ /** The thumb shown as dragging and focused meanwhile. */
378
+ let thumb = decided ?? index ?? 0;
379
+ const pointerId = event.pointerId;
380
+ try {
381
+ element.setPointerCapture(pointerId);
382
+ } catch {}
383
+ const decide = (raw) => {
384
+ if (decided !== null) return true;
385
+ decided = resolveTie(raw);
386
+ if (decided === null) return false;
387
+ if (decided !== thumb) {
388
+ thumb = decided;
389
+ setGestureThumb(thumb);
390
+ registry.get(thumb)?.focus({ focusVisible: false });
391
+ }
392
+ return true;
393
+ };
394
+ const follow = (pointerEvent) => {
395
+ const raw = valueAt(pointerEvent.clientX, pointerEvent.clientY);
396
+ if (decide(raw)) moveTo(thumb, raw, pointerEvent);
397
+ };
398
+ const onMove = (moveEvent) => {
399
+ if (moveEvent.pointerId !== pointerId) return;
400
+ follow(moveEvent);
401
+ };
402
+ const onEnd = (endEvent) => {
403
+ if (endEvent.pointerId !== pointerId) return;
404
+ detach();
405
+ if (endEvent.type === "pointerup") follow(endEvent);
406
+ activeGesture.current = null;
407
+ setGestureThumb(null);
408
+ commitGesture(thumb, "activate", endEvent);
409
+ };
410
+ const detach = () => {
411
+ element.removeEventListener("pointermove", onMove);
412
+ element.removeEventListener("pointerup", onEnd);
413
+ element.removeEventListener("pointercancel", onEnd);
414
+ element.removeEventListener("lostpointercapture", onEnd);
415
+ };
416
+ element.addEventListener("pointermove", onMove);
417
+ element.addEventListener("pointerup", onEnd);
418
+ element.addEventListener("pointercancel", onEnd);
419
+ element.addEventListener("lostpointercapture", onEnd);
420
+ activeGesture.current = {
421
+ pointerId,
422
+ detach
423
+ };
424
+ setGestureThumb(thumb);
425
+ gestureStart.current = shownRef.current;
426
+ liveRef.current = shownRef.current;
427
+ setLive(shownRef.current);
428
+ registry.get(thumb)?.focus({ focusVisible: false });
429
+ if (decided !== null) moveTo(thumb, start, event);
430
+ }, [
431
+ commitGesture,
432
+ latest,
433
+ registry,
434
+ shownRef,
435
+ stepTo
436
+ ]);
437
+ useEffect(() => () => {
438
+ activeGesture.current?.detach();
439
+ activeGesture.current = null;
440
+ }, []);
441
+ useDevWarning(!stepValid, `Slider.Root: \`step\` must be a positive number (got ${String(stepProp)}); using 1.`);
442
+ useDevWarning(stepValid && !isMaxReachable(min, max, step), `Slider.Root: \`max\` (${max}) is not on the step grid from \`min\` (${min}) with \`step\` ${step}: it is unreachable, as on a native range. The last reachable value is the last step below \`max\`.`);
443
+ const given = value ?? defaultValue;
444
+ const givenValues = given === void 0 ? [] : toArray(given);
445
+ useDevWarning(givenValues.some((v) => !isOnGrid(v, min, max, step)), `Slider.Root: the ${value !== void 0 ? "`value`" : "`defaultValue`"} (${givenValues.join(", ")}) is off the step grid or outside \`min\` / \`max\`. It is rendered as given and the browser sanitises it; the first user step snaps it.`);
446
+ useDevWarning(givenValues.some((v, i) => i > 0 && v < givenValues[i - 1]), `Slider.Root: the values (${givenValues.join(", ")}) must be in ascending order; the thumbs would be rendered crossed.`);
447
+ const currentShape = shapeOf(given);
448
+ useDevWarning(currentShape !== void 0 && currentShape !== shape, "Slider.Root: the value changed shape between a number and an array after mount. The shape is fixed at mount; remount the Slider (a `key`) to change the number of thumbs.");
449
+ const unnamedGroup = shown.length > 1 && !inField && rest["aria-label"] === void 0 && rest["aria-labelledby"] === void 0;
450
+ const warnedGroupName = useRef(false);
451
+ useEffect(() => {
452
+ if (!isDev || warnedGroupName.current || !unnamedGroup || labelCountRef.current > 0) return;
453
+ warnedGroupName.current = true;
454
+ console.error("Slider.Root: a slider with several thumbs is a `group` and needs a name: render a Slider.Label, or pass `aria-label` / `aria-labelledby` to the Root.");
455
+ }, [unnamedGroup]);
456
+ const count = shown.length;
457
+ const percents = shown.map((v) => percent(v, min, max));
458
+ const geometry = {
459
+ "--slider-start": count > 1 ? `${percents[0] ?? 0}%` : "0%",
460
+ "--slider-end": `${percents[count - 1] ?? 0}%`
461
+ };
462
+ percents.forEach((p, index) => {
463
+ geometry[`--slider-value-${index}`] = `${p}%`;
464
+ });
465
+ const shownValue = fromArray(shown);
466
+ const dragging = gestureThumb !== null;
467
+ const state = useMemo(() => ({
468
+ value: shownValue,
469
+ values: shown,
470
+ pending,
471
+ dragging,
472
+ orientation,
473
+ disabled,
474
+ min,
475
+ max,
476
+ step
477
+ }), [
478
+ shownValue,
479
+ shown,
480
+ pending,
481
+ dragging,
482
+ orientation,
483
+ disabled,
484
+ min,
485
+ max,
486
+ step
487
+ ]);
488
+ const context = useMemo(() => ({
489
+ state,
490
+ shown,
491
+ shownValue,
492
+ min,
493
+ max,
494
+ step,
495
+ gap,
496
+ orientation,
497
+ disabled,
498
+ pending,
499
+ draggingThumb: gestureThumb,
500
+ pendingThumb,
501
+ name,
502
+ form,
503
+ getAriaValueText,
504
+ labelId,
505
+ thumbId,
506
+ trackRef,
507
+ inputStep,
508
+ inputCommit,
509
+ inputKeyDown,
510
+ beginGesture,
511
+ registerThumb,
512
+ registerLabel,
513
+ onItemMounted,
514
+ field: fieldWiring
515
+ }), [
516
+ state,
517
+ shown,
518
+ shownValue,
519
+ min,
520
+ max,
521
+ step,
522
+ gap,
523
+ orientation,
524
+ disabled,
525
+ pending,
526
+ gestureThumb,
527
+ pendingThumb,
528
+ name,
529
+ form,
530
+ getAriaValueText,
531
+ labelId,
532
+ thumbId,
533
+ inputStep,
534
+ inputCommit,
535
+ inputKeyDown,
536
+ beginGesture,
537
+ registerThumb,
538
+ registerLabel,
539
+ onItemMounted,
540
+ fieldWiring
541
+ ]);
542
+ const labelledBy = count > 1 ? mergeTokenLists(fieldLabelledBy, labelCount > 0 ? labelId : void 0) : "";
543
+ const libraryProps = {
544
+ role: count > 1 ? "group" : void 0,
545
+ ...labelledBy !== "" ? { "aria-labelledby": labelledBy } : {},
546
+ ...count > 1 && fieldDescribedBy !== void 0 ? { "aria-describedby": fieldDescribedBy } : {},
547
+ ...inField ? { "data-invalid": fieldDataInvalid } : {},
548
+ "data-pending": dataAttr(pending),
549
+ "data-dragging": dataAttr(dragging),
550
+ "data-orientation": orientation,
551
+ "data-disabled": dataAttr(disabled)
552
+ };
553
+ const element = useRender({
554
+ defaultElement: "div",
555
+ render,
556
+ state,
557
+ className,
558
+ style: (s) => ({
559
+ ...geometry,
560
+ ...resolveStateValue(style, s)
561
+ }),
562
+ children,
563
+ props: rest,
564
+ libraryProps,
565
+ ref: rootRef
566
+ });
567
+ return /* @__PURE__ */ jsx(SliderContext, {
568
+ value: context,
569
+ children: element
570
+ });
571
+ }
572
+ SliderRootImpl.displayName = "SliderRoot";
573
+ /**
574
+ * `Slider.Root`. Overloaded so that the value's shape is inferred from `value` / `defaultValue`
575
+ * as `number` or `readonly number[]` (an array literal would otherwise infer a mutable
576
+ * `number[]`), and every action and state function receives that shape (design 3.1).
577
+ */
578
+ const SliderRoot = SliderRootImpl;
579
+ //#endregion
580
+ export { SliderRoot };
581
+
582
+ //# sourceMappingURL=slider-root.mjs.map