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

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 (230) hide show
  1. package/dist/accordion/accordion-root.mjs +2 -1
  2. package/dist/accordion/accordion-root.mjs.map +1 -1
  3. package/dist/combobox/combobox-clear.mjs +2 -1
  4. package/dist/combobox/combobox-clear.mjs.map +1 -1
  5. package/dist/combobox/combobox-list.mjs +2 -1
  6. package/dist/combobox/combobox-list.mjs.map +1 -1
  7. package/dist/combobox/combobox-popup.d.mts.map +1 -1
  8. package/dist/combobox/combobox-popup.mjs +7 -2
  9. package/dist/combobox/combobox-popup.mjs.map +1 -1
  10. package/dist/combobox/combobox-root.mjs +1 -1
  11. package/dist/combobox/combobox-trigger.mjs +2 -1
  12. package/dist/combobox/combobox-trigger.mjs.map +1 -1
  13. package/dist/dialog/dialog-close.mjs +2 -1
  14. package/dist/dialog/dialog-close.mjs.map +1 -1
  15. package/dist/dialog/dialog-form.d.mts +14 -8
  16. package/dist/dialog/dialog-form.d.mts.map +1 -1
  17. package/dist/dialog/dialog-form.mjs +36 -5
  18. package/dist/dialog/dialog-form.mjs.map +1 -1
  19. package/dist/dialog/dialog-popup.d.mts.map +1 -1
  20. package/dist/dialog/dialog-popup.mjs +13 -5
  21. package/dist/dialog/dialog-popup.mjs.map +1 -1
  22. package/dist/dialog/dialog-root.mjs +1 -1
  23. package/dist/dialog/dialog-trigger.mjs +2 -1
  24. package/dist/dialog/dialog-trigger.mjs.map +1 -1
  25. package/dist/field/field-root.mjs +5 -3
  26. package/dist/field/field-root.mjs.map +1 -1
  27. package/dist/form/form-root.mjs +2 -1
  28. package/dist/form/form-root.mjs.map +1 -1
  29. package/dist/form/form-submit.mjs +2 -1
  30. package/dist/form/form-submit.mjs.map +1 -1
  31. package/dist/index.d.mts +27 -1
  32. package/dist/index.mjs +6 -1
  33. package/dist/internal/announce.mjs +53 -0
  34. package/dist/internal/announce.mjs.map +1 -0
  35. package/dist/internal/decimal.mjs +27 -0
  36. package/dist/internal/decimal.mjs.map +1 -0
  37. package/dist/internal/dev-warn.mjs +17 -0
  38. package/dist/internal/dev-warn.mjs.map +1 -0
  39. package/dist/internal/field-context.mjs.map +1 -1
  40. package/dist/internal/range-value.mjs +51 -0
  41. package/dist/internal/range-value.mjs.map +1 -0
  42. package/dist/internal/render-element.mjs +54 -0
  43. package/dist/internal/render-element.mjs.map +1 -0
  44. package/dist/internal/toolbar-context.mjs +17 -0
  45. package/dist/internal/toolbar-context.mjs.map +1 -0
  46. package/dist/internal/use-exit-animation.mjs +26 -6
  47. package/dist/internal/use-exit-animation.mjs.map +1 -1
  48. package/dist/internal/use-field-control.mjs +5 -3
  49. package/dist/internal/use-field-control.mjs.map +1 -1
  50. package/dist/internal/use-popover-popup.mjs +3 -2
  51. package/dist/internal/use-popover-popup.mjs.map +1 -1
  52. package/dist/internal/use-popover-trigger.mjs +1 -1
  53. package/dist/internal/use-render.mjs +11 -34
  54. package/dist/internal/use-render.mjs.map +1 -1
  55. package/dist/internal/use-roving-focus.mjs +301 -0
  56. package/dist/internal/use-roving-focus.mjs.map +1 -0
  57. package/dist/menu/menu-checkbox-item.mjs +2 -1
  58. package/dist/menu/menu-checkbox-item.mjs.map +1 -1
  59. package/dist/menu/menu-item.mjs +2 -1
  60. package/dist/menu/menu-item.mjs.map +1 -1
  61. package/dist/menu/menu-popup.d.mts.map +1 -1
  62. package/dist/menu/menu-popup.mjs +7 -2
  63. package/dist/menu/menu-popup.mjs.map +1 -1
  64. package/dist/menu/menu-radio-item.mjs +2 -1
  65. package/dist/menu/menu-radio-item.mjs.map +1 -1
  66. package/dist/menu/menu-root.mjs +1 -1
  67. package/dist/menu/menu-trigger.d.mts +2 -1
  68. package/dist/menu/menu-trigger.d.mts.map +1 -1
  69. package/dist/menu/menu-trigger.mjs +15 -4
  70. package/dist/menu/menu-trigger.mjs.map +1 -1
  71. package/dist/meter/index.d.mts +24 -0
  72. package/dist/meter/index.d.mts.map +1 -0
  73. package/dist/meter/index.mjs +23 -0
  74. package/dist/meter/index.mjs.map +1 -0
  75. package/dist/meter/meter-context.mjs +13 -0
  76. package/dist/meter/meter-context.mjs.map +1 -0
  77. package/dist/meter/meter-indicator.d.mts +19 -0
  78. package/dist/meter/meter-indicator.d.mts.map +1 -0
  79. package/dist/meter/meter-indicator.mjs +25 -0
  80. package/dist/meter/meter-indicator.mjs.map +1 -0
  81. package/dist/meter/meter-label.d.mts +19 -0
  82. package/dist/meter/meter-label.d.mts.map +1 -0
  83. package/dist/meter/meter-label.mjs +28 -0
  84. package/dist/meter/meter-label.mjs.map +1 -0
  85. package/dist/meter/meter-region.d.mts +4 -0
  86. package/dist/meter/meter-region.d.mts.map +1 -0
  87. package/dist/meter/meter-region.mjs +39 -0
  88. package/dist/meter/meter-region.mjs.map +1 -0
  89. package/dist/meter/meter-root.d.mts +71 -0
  90. package/dist/meter/meter-root.d.mts.map +1 -0
  91. package/dist/meter/meter-root.mjs +83 -0
  92. package/dist/meter/meter-root.mjs.map +1 -0
  93. package/dist/meter/meter-track.d.mts +19 -0
  94. package/dist/meter/meter-track.d.mts.map +1 -0
  95. package/dist/meter/meter-track.mjs +25 -0
  96. package/dist/meter/meter-track.mjs.map +1 -0
  97. package/dist/meter/meter-value.d.mts +20 -0
  98. package/dist/meter/meter-value.d.mts.map +1 -0
  99. package/dist/meter/meter-value.mjs +29 -0
  100. package/dist/meter/meter-value.mjs.map +1 -0
  101. package/dist/number-field/index.d.mts +26 -0
  102. package/dist/number-field/index.d.mts.map +1 -0
  103. package/dist/number-field/index.mjs +26 -0
  104. package/dist/number-field/index.mjs.map +1 -0
  105. package/dist/number-field/number-field-arithmetic.mjs +78 -0
  106. package/dist/number-field/number-field-arithmetic.mjs.map +1 -0
  107. package/dist/number-field/number-field-context.d.mts +2 -0
  108. package/dist/number-field/number-field-context.mjs +13 -0
  109. package/dist/number-field/number-field-context.mjs.map +1 -0
  110. package/dist/number-field/number-field-decrement.d.mts +16 -0
  111. package/dist/number-field/number-field-decrement.d.mts.map +1 -0
  112. package/dist/number-field/number-field-decrement.mjs +19 -0
  113. package/dist/number-field/number-field-decrement.mjs.map +1 -0
  114. package/dist/number-field/number-field-format.mjs +279 -0
  115. package/dist/number-field/number-field-format.mjs.map +1 -0
  116. package/dist/number-field/number-field-increment.d.mts +32 -0
  117. package/dist/number-field/number-field-increment.d.mts.map +1 -0
  118. package/dist/number-field/number-field-increment.mjs +68 -0
  119. package/dist/number-field/number-field-increment.mjs.map +1 -0
  120. package/dist/number-field/number-field-input.d.mts +29 -0
  121. package/dist/number-field/number-field-input.d.mts.map +1 -0
  122. package/dist/number-field/number-field-input.mjs +163 -0
  123. package/dist/number-field/number-field-input.mjs.map +1 -0
  124. package/dist/number-field/number-field-label.d.mts +23 -0
  125. package/dist/number-field/number-field-label.d.mts.map +1 -0
  126. package/dist/number-field/number-field-label.mjs +47 -0
  127. package/dist/number-field/number-field-label.mjs.map +1 -0
  128. package/dist/number-field/number-field-root.d.mts +108 -0
  129. package/dist/number-field/number-field-root.d.mts.map +1 -0
  130. package/dist/number-field/number-field-root.mjs +523 -0
  131. package/dist/number-field/number-field-root.mjs.map +1 -0
  132. package/dist/number-field/use-step-button.mjs +107 -0
  133. package/dist/number-field/use-step-button.mjs.map +1 -0
  134. package/dist/popover/popover-close.mjs +2 -1
  135. package/dist/popover/popover-close.mjs.map +1 -1
  136. package/dist/popover/popover-popup.d.mts.map +1 -1
  137. package/dist/popover/popover-popup.mjs +7 -2
  138. package/dist/popover/popover-popup.mjs.map +1 -1
  139. package/dist/popover/popover-root.mjs +1 -1
  140. package/dist/progress/index.d.mts +24 -0
  141. package/dist/progress/index.d.mts.map +1 -0
  142. package/dist/progress/index.mjs +24 -0
  143. package/dist/progress/index.mjs.map +1 -0
  144. package/dist/progress/progress-context.mjs +13 -0
  145. package/dist/progress/progress-context.mjs.map +1 -0
  146. package/dist/progress/progress-indicator.d.mts +19 -0
  147. package/dist/progress/progress-indicator.d.mts.map +1 -0
  148. package/dist/progress/progress-indicator.mjs +29 -0
  149. package/dist/progress/progress-indicator.mjs.map +1 -0
  150. package/dist/progress/progress-label.d.mts +19 -0
  151. package/dist/progress/progress-label.d.mts.map +1 -0
  152. package/dist/progress/progress-label.mjs +30 -0
  153. package/dist/progress/progress-label.mjs.map +1 -0
  154. package/dist/progress/progress-root.d.mts +68 -0
  155. package/dist/progress/progress-root.d.mts.map +1 -0
  156. package/dist/progress/progress-root.mjs +80 -0
  157. package/dist/progress/progress-root.mjs.map +1 -0
  158. package/dist/progress/progress-track.d.mts +19 -0
  159. package/dist/progress/progress-track.d.mts.map +1 -0
  160. package/dist/progress/progress-track.mjs +29 -0
  161. package/dist/progress/progress-track.mjs.map +1 -0
  162. package/dist/progress/progress-value.d.mts +20 -0
  163. package/dist/progress/progress-value.d.mts.map +1 -0
  164. package/dist/progress/progress-value.mjs +33 -0
  165. package/dist/progress/progress-value.mjs.map +1 -0
  166. package/dist/slider/slider-arithmetic.mjs +1 -17
  167. package/dist/slider/slider-arithmetic.mjs.map +1 -1
  168. package/dist/slider/slider-root.mjs +3 -2
  169. package/dist/slider/slider-root.mjs.map +1 -1
  170. package/dist/slider/slider-thumb.mjs +2 -1
  171. package/dist/slider/slider-thumb.mjs.map +1 -1
  172. package/dist/slider/slider-track.mjs +2 -1
  173. package/dist/slider/slider-track.mjs.map +1 -1
  174. package/dist/tabs/tabs-indicator.mjs +2 -1
  175. package/dist/tabs/tabs-indicator.mjs.map +1 -1
  176. package/dist/tabs/tabs-tab.mjs +2 -1
  177. package/dist/tabs/tabs-tab.mjs.map +1 -1
  178. package/dist/toast/toast-action.mjs +2 -1
  179. package/dist/toast/toast-action.mjs.map +1 -1
  180. package/dist/toast/toast-close.mjs +2 -1
  181. package/dist/toast/toast-close.mjs.map +1 -1
  182. package/dist/toast/toast-root.mjs +3 -2
  183. package/dist/toast/toast-root.mjs.map +1 -1
  184. package/dist/toast/toast-viewport.d.mts.map +1 -1
  185. package/dist/toast/toast-viewport.mjs +30 -7
  186. package/dist/toast/toast-viewport.mjs.map +1 -1
  187. package/dist/toast/toast.d.mts.map +1 -1
  188. package/dist/toast/toast.mjs +5 -1
  189. package/dist/toast/toast.mjs.map +1 -1
  190. package/dist/toggle/toggle.mjs +2 -1
  191. package/dist/toggle/toggle.mjs.map +1 -1
  192. package/dist/toggle-group/index.d.mts +16 -0
  193. package/dist/toggle-group/index.d.mts.map +1 -0
  194. package/dist/toggle-group/index.mjs +15 -0
  195. package/dist/toggle-group/index.mjs.map +1 -0
  196. package/dist/toggle-group/toggle-group-context.d.mts +4 -0
  197. package/dist/toggle-group/toggle-group-context.d.mts.map +1 -0
  198. package/dist/toggle-group/toggle-group-context.mjs +13 -0
  199. package/dist/toggle-group/toggle-group-context.mjs.map +1 -0
  200. package/dist/toggle-group/toggle-group-item.d.mts +47 -0
  201. package/dist/toggle-group/toggle-group-item.d.mts.map +1 -0
  202. package/dist/toggle-group/toggle-group-item.mjs +63 -0
  203. package/dist/toggle-group/toggle-group-item.mjs.map +1 -0
  204. package/dist/toggle-group/toggle-group-root.d.mts +95 -0
  205. package/dist/toggle-group/toggle-group-root.d.mts.map +1 -0
  206. package/dist/toggle-group/toggle-group-root.mjs +211 -0
  207. package/dist/toggle-group/toggle-group-root.mjs.map +1 -0
  208. package/dist/toolbar/index.d.mts +18 -0
  209. package/dist/toolbar/index.d.mts.map +1 -0
  210. package/dist/toolbar/index.mjs +18 -0
  211. package/dist/toolbar/index.mjs.map +1 -0
  212. package/dist/toolbar/toolbar-button.d.mts +42 -0
  213. package/dist/toolbar/toolbar-button.d.mts.map +1 -0
  214. package/dist/toolbar/toolbar-button.mjs +50 -0
  215. package/dist/toolbar/toolbar-button.mjs.map +1 -0
  216. package/dist/toolbar/toolbar-root.d.mts +38 -0
  217. package/dist/toolbar/toolbar-root.d.mts.map +1 -0
  218. package/dist/toolbar/toolbar-root.mjs +66 -0
  219. package/dist/toolbar/toolbar-root.mjs.map +1 -0
  220. package/dist/toolbar/toolbar-separator.d.mts +25 -0
  221. package/dist/toolbar/toolbar-separator.d.mts.map +1 -0
  222. package/dist/toolbar/toolbar-separator.mjs +31 -0
  223. package/dist/toolbar/toolbar-separator.mjs.map +1 -0
  224. package/dist/tooltip/tooltip-popup.mjs +2 -1
  225. package/dist/tooltip/tooltip-popup.mjs.map +1 -1
  226. package/dist/tooltip/tooltip-root.mjs +18 -2
  227. package/dist/tooltip/tooltip-root.mjs.map +1 -1
  228. package/dist/tooltip/tooltip-trigger.mjs +2 -1
  229. package/dist/tooltip/tooltip-trigger.mjs.map +1 -1
  230. package/package.json +6 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-root.mjs","names":[],"sources":["../../src/progress/progress-root.tsx"],"sourcesContent":["// No \"use client\": `Progress.Root` uses only `useId`, arithmetic and `Intl`, and renders the\n// client context's provider (conventions 7.1's second exception). Rendered by a Server Component\n// it runs once, on the server (design/components/progress.md 8.1). It must not import from any\n// \"use client\" module except its context (checked by src/__tests__/directives.test.ts).\nimport { useId } from \"react\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { warnOnce } from \"../internal/dev-warn.js\";\nimport { clamp, formatRangeValue, isDegenerate, percentage } from \"../internal/range-value.js\";\nimport { mergeRenderRef, renderElement, resolveStateValue } from \"../internal/render-element.js\";\nimport type { DataAttributes } from \"../internal/render-element.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { ProgressContext } from \"./progress-context.js\";\n\n/** The state every Progress part receives. */\nexport interface ProgressState {\n /** The value clamped to `[min, max]`, or `null` while indeterminate. */\n readonly value: number | null;\n readonly min: number;\n readonly max: number;\n /** `(value - min) / (max - min) * 100`, a number 0–100; `null` while indeterminate. */\n readonly percentage: number | null;\n /**\n * The `Intl.NumberFormat` text of the value (or of the fraction, for the percent style): what\n * `Progress.Value` shows. `null` while indeterminate.\n */\n readonly formattedValue: string | null;\n /** What `aria-valuetext` carries: `getAriaValueText`'s result, else `formattedValue`. */\n readonly valueText: string | null;\n /** `value` is `null`. */\n readonly indeterminate: boolean;\n /** The clamped value has reached `max`. */\n readonly complete: boolean;\n}\n\nexport interface ProgressRootProps extends Omit<\n ComponentPropsWithRef<\"div\">,\n | \"role\"\n | \"aria-valuemin\"\n | \"aria-valuemax\"\n | \"aria-valuenow\"\n | \"aria-valuetext\"\n | \"defaultValue\"\n | \"defaultChecked\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /** The current value. Absent or `null`: indeterminate. Clamped to `[min, max]`. */\n value?: number | null;\n /** @default 0 */\n min?: number;\n /** @default 100 */\n max?: number;\n /**\n * `Intl.NumberFormat` options for `aria-valuetext` and `Progress.Value`. Default\n * `{ style: \"percent\" }`. A `percent` style formats the fraction of the range; any other style\n * formats the value. Serialisable: a Server Component may pass it.\n */\n format?: Intl.NumberFormatOptions;\n /**\n * BCP 47 tag for `Intl.NumberFormat`; default: the runtime's locale. Pass it when a client\n * tree is server-rendered.\n */\n locale?: string;\n /**\n * The `aria-valuetext` to render instead of `formattedValue`. Called with the clamped value\n * (`null` while indeterminate) and the state as it would be without this prop. Return `null`\n * to render no `aria-valuetext`. A function: from a Server Component it works when this Root\n * is rendered by that Server Component (the Root runs on the server), not when the Root is\n * rendered by a client component.\n */\n getAriaValueText?: (value: number | null, state: ProgressState) => string | null | undefined;\n className?: StateValue<string | undefined, ProgressState>;\n style?: StateValue<CSSProperties | undefined, ProgressState>;\n children?: StateValue<ReactNode, ProgressState>;\n render?: RenderProp<ComponentPropsWithRef<\"div\">, ProgressState>;\n}\n\n/**\n * `Progress.Root`: a `div[role=progressbar]` with the ARIA values, `aria-valuetext` from\n * `Intl.NumberFormat`, `data-indeterminate` / `data-complete`, and `--progress-value` (the\n * percentage, absent while indeterminate) in `style`, where the consumer's entries win. Owned\n * keys: `role`, `aria-valuemin`, `aria-valuemax`, `aria-valuenow`, `aria-valuetext`,\n * `aria-labelledby` (token-merged: the consumer's tokens, then `Progress.Label`'s id, always),\n * `data-indeterminate`, `data-complete`.\n */\nexport function ProgressRoot({\n value = null,\n min = 0,\n max = 100,\n format,\n locale,\n getAriaValueText,\n className,\n style,\n children,\n render,\n ref,\n ...rest\n}: ProgressRootProps) {\n const id = useId();\n\n let given = value;\n if (given !== null && !Number.isFinite(given)) {\n warnOnce(\n `Progress.Root:non-finite:${given}`,\n `Progress.Root: \\`value\\` is ${given}, which is not a finite number; the bar is rendered ` +\n \"as indeterminate. Pass `null` for an unknown value.\",\n );\n given = null;\n }\n const degenerate = isDegenerate(min, max);\n if (degenerate) {\n warnOnce(\n `Progress.Root:degenerate:${min}:${max}`,\n `Progress.Root: \\`max\\` (${max}) must be greater than \\`min\\` (${min}); the percentage is ` +\n \"rendered as 0. Pass `value={null}` while the total is unknown or empty.\",\n );\n }\n\n const clamped = given === null ? null : clamp(given, min, max);\n const formattedValue =\n clamped === null ? null : formatRangeValue(clamped, min, max, format, locale);\n const base: ProgressState = {\n value: clamped,\n min,\n max,\n percentage: clamped === null ? null : percentage(clamped, min, max),\n formattedValue,\n valueText: formattedValue,\n indeterminate: clamped === null,\n complete: clamped !== null && !degenerate && clamped >= max,\n };\n const valueText =\n getAriaValueText === undefined ? formattedValue : (getAriaValueText(clamped, base) ?? null);\n const state: ProgressState = valueText === base.valueText ? base : { ...base, valueText };\n\n const variables = state.percentage === null ? {} : { \"--progress-value\": `${state.percentage}%` };\n\n const libraryProps: Partial<ComponentPropsWithRef<\"div\">> & DataAttributes = {\n role: \"progressbar\",\n \"aria-valuemin\": min,\n \"aria-valuemax\": max,\n \"aria-valuenow\": clamped ?? undefined,\n \"aria-valuetext\": valueText ?? undefined,\n \"aria-labelledby\": `${id}-label`,\n \"data-indeterminate\": dataAttr(state.indeterminate),\n \"data-complete\": dataAttr(state.complete),\n };\n\n const element = renderElement<ComponentPropsWithRef<\"div\">, ProgressState>({\n defaultElement: \"div\",\n render,\n state,\n className,\n // The custom property loses to the consumer's own entry (design 3.1).\n style: (s) => ({ ...(variables as CSSProperties), ...resolveStateValue(style, s) }),\n children,\n props: rest,\n libraryProps,\n // Passed through to the element, never read during render.\n // oxlint-disable-next-line react/refs\n ref: mergeRenderRef(ref, render),\n });\n\n return <ProgressContext value={{ id, state }}>{element}</ProgressContext>;\n}\n\nProgressRoot.displayName = \"ProgressRoot\";\n"],"mappings":";;;;;;;;;;;;;;;;AAuFA,SAAgB,aAAa,EAC3B,QAAQ,MACR,MAAM,GACN,MAAM,KACN,QACA,QACA,kBACA,WACA,OACA,UACA,QACA,KACA,GAAG,QACiB;CACpB,MAAM,KAAK,MAAM;CAEjB,IAAI,QAAQ;CACZ,IAAI,UAAU,QAAQ,CAAC,OAAO,SAAS,KAAK,GAAG;EAC7C,SACE,4BAA4B,SAC5B,+BAA+B,MAAM,0GAEvC;EACA,QAAQ;CACV;CACA,MAAM,aAAa,aAAa,KAAK,GAAG;CACxC,IAAI,YACF,SACE,4BAA4B,IAAI,GAAG,OACnC,2BAA2B,IAAI,kCAAkC,IAAI,+FAEvE;CAGF,MAAM,UAAU,UAAU,OAAO,OAAO,MAAM,OAAO,KAAK,GAAG;CAC7D,MAAM,iBACJ,YAAY,OAAO,OAAO,iBAAiB,SAAS,KAAK,KAAK,QAAQ,MAAM;CAC9E,MAAM,OAAsB;EAC1B,OAAO;EACP;EACA;EACA,YAAY,YAAY,OAAO,OAAO,WAAW,SAAS,KAAK,GAAG;EAClE;EACA,WAAW;EACX,eAAe,YAAY;EAC3B,UAAU,YAAY,QAAQ,CAAC,cAAc,WAAW;CAC1D;CACA,MAAM,YACJ,qBAAqB,KAAA,IAAY,iBAAkB,iBAAiB,SAAS,IAAI,KAAK;CACxF,MAAM,QAAuB,cAAc,KAAK,YAAY,OAAO;EAAE,GAAG;EAAM;CAAU;CAExF,MAAM,YAAY,MAAM,eAAe,OAAO,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,WAAW,GAAG;CAEhG,MAAM,eAAuE;EAC3E,MAAM;EACN,iBAAiB;EACjB,iBAAiB;EACjB,iBAAiB,WAAW,KAAA;EAC5B,kBAAkB,aAAa,KAAA;EAC/B,mBAAmB,GAAG,GAAG;EACzB,sBAAsB,SAAS,MAAM,aAAa;EAClD,iBAAiB,SAAS,MAAM,QAAQ;CAC1C;CAEA,MAAM,UAAU,cAA2D;EACzE,gBAAgB;EAChB;EACA;EACA;EAEA,QAAQ,OAAO;GAAE,GAAI;GAA6B,GAAG,kBAAkB,OAAO,CAAC;EAAE;EACjF;EACA,OAAO;EACP;EAGA,KAAK,eAAe,KAAK,MAAM;CACjC,CAAC;CAED,OAAO,oBAAC,iBAAD;EAAiB,OAAO;GAAE;GAAI;EAAM;EAAI,UAAA;CAAyB,CAAA;AAC1E;AAEA,aAAa,cAAc"}
@@ -0,0 +1,19 @@
1
+ import { RenderProp, StateValue } from "../internal/types.mjs";
2
+ import { ProgressState } from "./progress-root.mjs";
3
+ import { CSSProperties, ComponentPropsWithRef, ReactNode } from "react";
4
+ //#region src/progress/progress-track.d.ts
5
+ export interface ProgressTrackProps extends Omit<ComponentPropsWithRef<"div">, "className" | "style" | "children"> {
6
+ className?: StateValue<string | undefined, ProgressState>;
7
+ style?: StateValue<CSSProperties | undefined, ProgressState>;
8
+ children?: StateValue<ReactNode, ProgressState>;
9
+ render?: RenderProp<ComponentPropsWithRef<"div">, ProgressState>;
10
+ }
11
+ /**
12
+ * `Progress.Track`: the rail. It renders nothing but the state's data attributes. Owned keys: `data-indeterminate`, `data-complete`.
13
+ */
14
+ export declare function ProgressTrack({ className, style, children, render, ...rest }: ProgressTrackProps): ReactNode;
15
+ export declare namespace ProgressTrack {
16
+ var displayName: string;
17
+ }
18
+ //#endregion
19
+ //# sourceMappingURL=progress-track.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-track.d.mts","names":[],"sources":["../../src/progress/progress-track.tsx"],"mappings":";;;;iBAQiB,2BAA2B,KAC1C;EAGA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;EACjC,SAAS,WAAW,8BAA8B;;;;;wBAMpC,gBAAgB,WAAW,OAAO,UAAU,WAAW,QAAQ,qBAAkB;yBAAjF"}
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { dataAttr } from "../internal/data-attr.mjs";
3
+ import { useRender } from "../internal/use-render.mjs";
4
+ import { useProgressContext } from "./progress-context.mjs";
5
+ //#region src/progress/progress-track.tsx
6
+ /**
7
+ * `Progress.Track`: the rail. It renders nothing but the state's data attributes. Owned keys: `data-indeterminate`, `data-complete`.
8
+ */
9
+ function ProgressTrack({ className, style, children, render, ...rest }) {
10
+ const { state } = useProgressContext("Progress.Track");
11
+ return useRender({
12
+ defaultElement: "div",
13
+ render,
14
+ state,
15
+ className,
16
+ style,
17
+ children,
18
+ props: rest,
19
+ libraryProps: {
20
+ "data-indeterminate": dataAttr(state.indeterminate),
21
+ "data-complete": dataAttr(state.complete)
22
+ }
23
+ });
24
+ }
25
+ ProgressTrack.displayName = "ProgressTrack";
26
+ //#endregion
27
+ export { ProgressTrack };
28
+
29
+ //# sourceMappingURL=progress-track.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-track.mjs","names":[],"sources":["../../src/progress/progress-track.tsx"],"sourcesContent":["\"use client\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { useProgressContext } from \"./progress-context.js\";\nimport type { ProgressState } from \"./progress-root.js\";\n\nexport interface ProgressTrackProps extends Omit<\n ComponentPropsWithRef<\"div\">,\n \"className\" | \"style\" | \"children\"\n> {\n className?: StateValue<string | undefined, ProgressState>;\n style?: StateValue<CSSProperties | undefined, ProgressState>;\n children?: StateValue<ReactNode, ProgressState>;\n render?: RenderProp<ComponentPropsWithRef<\"div\">, ProgressState>;\n}\n\n/**\n * `Progress.Track`: the rail. It renders nothing but the state's data attributes. Owned keys: `data-indeterminate`, `data-complete`.\n */\nexport function ProgressTrack({ className, style, children, render, ...rest }: ProgressTrackProps) {\n const { state } = useProgressContext(\"Progress.Track\");\n return useRender<ComponentPropsWithRef<\"div\">, ProgressState>({\n defaultElement: \"div\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps: {\n \"data-indeterminate\": dataAttr(state.indeterminate),\n \"data-complete\": dataAttr(state.complete),\n },\n });\n}\n\nProgressTrack.displayName = \"ProgressTrack\";\n"],"mappings":";;;;;;;;AAqBA,SAAgB,cAAc,EAAE,WAAW,OAAO,UAAU,QAAQ,GAAG,QAA4B;CACjG,MAAM,EAAE,UAAU,mBAAmB,gBAAgB;CACrD,OAAO,UAAuD;EAC5D,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;EACP,cAAc;GACZ,sBAAsB,SAAS,MAAM,aAAa;GAClD,iBAAiB,SAAS,MAAM,QAAQ;EAC1C;CACF,CAAC;AACH;AAEA,cAAc,cAAc"}
@@ -0,0 +1,20 @@
1
+ import { RenderProp, StateValue } from "../internal/types.mjs";
2
+ import { ProgressState } from "./progress-root.mjs";
3
+ import { CSSProperties, ComponentPropsWithRef, ReactNode } from "react";
4
+ //#region src/progress/progress-value.d.ts
5
+ export interface ProgressValueProps extends Omit<ComponentPropsWithRef<"span">, "className" | "style" | "children"> {
6
+ className?: StateValue<string | undefined, ProgressState>;
7
+ style?: StateValue<CSSProperties | undefined, ProgressState>;
8
+ /** Default: `state.formattedValue` (nothing while indeterminate). */
9
+ children?: StateValue<ReactNode, ProgressState>;
10
+ render?: RenderProp<ComponentPropsWithRef<"span">, ProgressState>;
11
+ }
12
+ /**
13
+ * `Progress.Value`: shows `state.formattedValue` or `children(state)`. `aria-hidden="true"` is a default the consumer may override, not an owned key: the same text is in the Root's `aria-valuetext`. Owned keys: `data-indeterminate`, `data-complete`.
14
+ */
15
+ export declare function ProgressValue({ className, style, children, render, ...rest }: ProgressValueProps): ReactNode;
16
+ export declare namespace ProgressValue {
17
+ var displayName: string;
18
+ }
19
+ //#endregion
20
+ //# sourceMappingURL=progress-value.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-value.d.mts","names":[],"sources":["../../src/progress/progress-value.tsx"],"mappings":";;;;iBAQiB,2BAA2B,KAC1C;EAGA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;;EAE9C,WAAW,WAAW,WAAW;EACjC,SAAS,WAAW,+BAA+B;;;;;wBAMrC,gBAAgB,WAAW,OAAO,UAAU,WAAW,QAAQ,qBAAkB;yBAAjF"}
@@ -0,0 +1,33 @@
1
+ "use client";
2
+ import { dataAttr } from "../internal/data-attr.mjs";
3
+ import { useRender } from "../internal/use-render.mjs";
4
+ import { useProgressContext } from "./progress-context.mjs";
5
+ //#region src/progress/progress-value.tsx
6
+ /**
7
+ * `Progress.Value`: shows `state.formattedValue` or `children(state)`. `aria-hidden="true"` is a default the consumer may override, not an owned key: the same text is in the Root's `aria-valuetext`. Owned keys: `data-indeterminate`, `data-complete`.
8
+ */
9
+ function ProgressValue({ className, style, children, render, ...rest }) {
10
+ const { state } = useProgressContext("Progress.Value");
11
+ const props = {
12
+ ...rest,
13
+ "aria-hidden": rest["aria-hidden"] ?? true
14
+ };
15
+ return useRender({
16
+ defaultElement: "span",
17
+ render,
18
+ state,
19
+ className,
20
+ style,
21
+ children: children ?? state.formattedValue,
22
+ props,
23
+ libraryProps: {
24
+ "data-indeterminate": dataAttr(state.indeterminate),
25
+ "data-complete": dataAttr(state.complete)
26
+ }
27
+ });
28
+ }
29
+ ProgressValue.displayName = "ProgressValue";
30
+ //#endregion
31
+ export { ProgressValue };
32
+
33
+ //# sourceMappingURL=progress-value.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-value.mjs","names":[],"sources":["../../src/progress/progress-value.tsx"],"sourcesContent":["\"use client\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { useProgressContext } from \"./progress-context.js\";\nimport type { ProgressState } from \"./progress-root.js\";\n\nexport interface ProgressValueProps extends Omit<\n ComponentPropsWithRef<\"span\">,\n \"className\" | \"style\" | \"children\"\n> {\n className?: StateValue<string | undefined, ProgressState>;\n style?: StateValue<CSSProperties | undefined, ProgressState>;\n /** Default: `state.formattedValue` (nothing while indeterminate). */\n children?: StateValue<ReactNode, ProgressState>;\n render?: RenderProp<ComponentPropsWithRef<\"span\">, ProgressState>;\n}\n\n/**\n * `Progress.Value`: shows `state.formattedValue` or `children(state)`. `aria-hidden=\"true\"` is a default the consumer may override, not an owned key: the same text is in the Root's `aria-valuetext`. Owned keys: `data-indeterminate`, `data-complete`.\n */\nexport function ProgressValue({ className, style, children, render, ...rest }: ProgressValueProps) {\n const { state } = useProgressContext(\"Progress.Value\");\n const props = { ...rest, \"aria-hidden\": rest[\"aria-hidden\"] ?? true };\n return useRender<ComponentPropsWithRef<\"span\">, ProgressState>({\n defaultElement: \"span\",\n render,\n state,\n className,\n style,\n children: children ?? state.formattedValue,\n props,\n libraryProps: {\n \"data-indeterminate\": dataAttr(state.indeterminate),\n \"data-complete\": dataAttr(state.complete),\n },\n });\n}\n\nProgressValue.displayName = \"ProgressValue\";\n"],"mappings":";;;;;;;;AAsBA,SAAgB,cAAc,EAAE,WAAW,OAAO,UAAU,QAAQ,GAAG,QAA4B;CACjG,MAAM,EAAE,UAAU,mBAAmB,gBAAgB;CACrD,MAAM,QAAQ;EAAE,GAAG;EAAM,eAAe,KAAK,kBAAkB;CAAK;CACpE,OAAO,UAAwD;EAC7D,gBAAgB;EAChB;EACA;EACA;EACA;EACA,UAAU,YAAY,MAAM;EAC5B;EACA,cAAc;GACZ,sBAAsB,SAAS,MAAM,aAAa;GAClD,iBAAiB,SAAS,MAAM,QAAQ;EAC1C;CACF,CAAC;AACH;AAEA,cAAc,cAAc"}
@@ -1,21 +1,5 @@
1
+ import { decimalsOf, roundTo } from "../internal/decimal.mjs";
1
2
  //#region src/slider/slider-arithmetic.ts
2
- /** Number of decimal places of `n` as written (`0.1` → 1, `1e-7` → 7, `5` → 0). */
3
- function decimalsOf(n) {
4
- if (!Number.isFinite(n)) return 0;
5
- const text = String(n);
6
- const exponent = /e-(\d+)$/i.exec(text);
7
- if (exponent !== null) {
8
- const mantissa = text.slice(0, exponent.index);
9
- const dot = mantissa.indexOf(".");
10
- return Number(exponent[1]) + (dot === -1 ? 0 : mantissa.length - dot - 1);
11
- }
12
- const dot = text.indexOf(".");
13
- return dot === -1 ? 0 : text.length - dot - 1;
14
- }
15
- function roundTo(value, decimals) {
16
- if (decimals <= 0) return Math.round(value);
17
- return Number(value.toFixed(Math.min(decimals, 100)));
18
- }
19
3
  /** Tolerance for grid computations on binary floating point (`0.3 / 0.1` is `2.9999999999999996`). */
20
4
  const EPSILON = 1e-9;
21
5
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"slider-arithmetic.mjs","names":[],"sources":["../../src/slider/slider-arithmetic.ts"],"sourcesContent":["// Pure value arithmetic of the Slider (design/components/slider.md 5). No directive: no React,\n// no client-only API. The library computes exactly what the platform's range sanitisation would,\n// so the number it renders is the number the DOM holds and `FormData` posts.\n\n/** Number of decimal places of `n` as written (`0.1` → 1, `1e-7` → 7, `5` → 0). */\nexport function decimalsOf(n: number): number {\n if (!Number.isFinite(n)) return 0;\n const text = String(n);\n const exponent = /e-(\\d+)$/i.exec(text);\n if (exponent !== null) {\n const mantissa = text.slice(0, exponent.index);\n const dot = mantissa.indexOf(\".\");\n return Number(exponent[1]) + (dot === -1 ? 0 : mantissa.length - dot - 1);\n }\n const dot = text.indexOf(\".\");\n return dot === -1 ? 0 : text.length - dot - 1;\n}\n\nfunction roundTo(value: number, decimals: number): number {\n if (decimals <= 0) return Math.round(value);\n // `toFixed` takes at most 100 digits; anything near that is already exact.\n return Number(value.toFixed(Math.min(decimals, 100)));\n}\n\n/** Tolerance for grid computations on binary floating point (`0.3 / 0.1` is `2.9999999999999996`). */\nconst EPSILON = 1e-9;\n\n/**\n * The value a native range with these bounds would hold for `value`: snapped to\n * `min + n × step` (ties toward +∞, the HTML step-mismatch rule), clamped to `[min, max]`, and,\n * when the snapped value exceeds `max`, the last grid point below `max` (so `min 0, max 5,\n * step 2` caps at `4`). Rounded to the decimal places of `step` and `min`. With `max < min` the\n * platform's maximum is `min`.\n */\nexport function snap(value: number, min: number, max: number, step: number): number {\n const decimals = Math.max(decimalsOf(step), decimalsOf(min));\n if (!Number.isFinite(value)) return min;\n if (!(max > min)) return roundTo(min, decimals);\n const lastIndex = Math.floor((max - min) / step + EPSILON);\n let index = Math.floor((value - min) / step + 0.5 + EPSILON);\n if (index > lastIndex) index = lastIndex;\n if (index < 0) index = 0;\n return roundTo(min + index * step, decimals);\n}\n\n/** Whether `max` is reachable: `max - min` is a whole number of steps. */\nexport function isMaxReachable(min: number, max: number, step: number): boolean {\n if (!(max > min)) return true;\n const steps = (max - min) / step;\n return Math.abs(steps - Math.round(steps)) < EPSILON * Math.max(1, steps);\n}\n\n/** Whether `value` is a value a native range with these bounds can hold unchanged. */\nexport function isOnGrid(value: number, min: number, max: number, step: number): boolean {\n return Math.abs(snap(value, min, max, step) - value) < EPSILON * Math.max(1, Math.abs(value));\n}\n\n/** The native `min` / `max` of thumb `index`: the slider's bounds, narrowed by its neighbours. */\nexport function thumbBounds(\n values: readonly number[],\n index: number,\n min: number,\n max: number,\n gap: number,\n): { readonly lower: number; readonly upper: number } {\n const decimals = Math.max(decimalsOf(gap), decimalsOf(min));\n const before = values[index - 1];\n const after = values[index + 1];\n const lower = before === undefined ? min : roundTo(before + gap, decimals);\n const upper = after === undefined ? max : roundTo(after - gap, decimals);\n return { lower, upper };\n}\n\n/**\n * `next` for thumb `index`, snapped to the slider's grid and clamped between its neighbours\n * (`values[i - 1] + gap`, `values[i + 1] - gap`; on the grid, because every thumb shares `step`\n * and `min`). With no room between the neighbours the thumb keeps its value.\n */\nexport function clampToNeighbours(\n values: readonly number[],\n index: number,\n next: number,\n min: number,\n max: number,\n step: number,\n gap: number,\n): number {\n const { lower, upper } = thumbBounds(values, index, min, max, gap);\n const current = values[index] ?? next;\n if (lower > upper + EPSILON) return current;\n return Math.min(Math.max(snap(next, min, max, step), lower), upper);\n}\n\n/**\n * The value a native input with these attributes would hold for `value` (each thumb's bounds come\n * from `reference`, the values it is rendered against). Used to compare a DOM read with the shown\n * value: jsdom does not sanitise a range's value, browsers do, and a consumer's off-grid value is\n * rendered as given and sanitised by the DOM.\n */\nexport function sanitize(\n values: readonly number[],\n reference: readonly number[],\n min: number,\n max: number,\n step: number,\n gap: number,\n): readonly number[] {\n return values.map((value, index) => {\n const { lower, upper } = thumbBounds(reference, index, min, max, gap);\n // The native step base is the input's own `min` attribute (the neighbour-adjusted bound).\n return snap(value, lower, Math.max(lower, upper), step);\n });\n}\n\n/** Position of `value` in `[min, max]`, in percent, clamped to `0`–`100`. */\nexport function percent(value: number, min: number, max: number): number {\n if (!(max > min)) return 0;\n const fraction = (value - min) / (max - min);\n return Math.min(100, Math.max(0, fraction * 100));\n}\n\n/**\n * The thumb a track press at `target` moves: the nearest by value. On a tie (two thumbs at one\n * value, or equidistant thumbs) the thumb that can move toward the pointer: the later one when\n * the pointer is above it, else the earlier one.\n */\nexport function nearestThumb(values: readonly number[], target: number): number {\n let best = 0;\n let bestDistance = Number.POSITIVE_INFINITY;\n values.forEach((value, index) => {\n const distance = Math.abs(value - target);\n if (distance < bestDistance - EPSILON) {\n best = index;\n bestDistance = distance;\n } else if (Math.abs(distance - bestDistance) <= EPSILON && target > value) {\n best = index;\n }\n });\n return best;\n}\n\n/** The platform's default value: the midpoint, snapped to the grid; `min` when `max < min`. */\nexport function platformDefault(min: number, max: number, step: number): number {\n if (!(max > min)) return min;\n return snap(min + (max - min) / 2, min, max, step);\n}\n\n/** Element-wise equality of two value arrays (within floating-point tolerance). */\nexport function equalValues(a: readonly number[], b: readonly number[]): boolean {\n if (a.length !== b.length) return false;\n return a.every((value, index) => {\n const other = b[index] as number;\n return value === other || Math.abs(value - other) < EPSILON * Math.max(1, Math.abs(value));\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"slider-arithmetic.mjs","names":[],"sources":["../../src/slider/slider-arithmetic.ts"],"sourcesContent":["// Pure value arithmetic of the Slider (design/components/slider.md 5). No directive: no React,\n// no client-only API. The library computes exactly what the platform's range sanitisation would,\n// so the number it renders is the number the DOM holds and `FormData` posts.\n\nimport { decimalsOf, roundTo } from \"../internal/decimal.js\";\n\nexport { decimalsOf };\n\n/** Tolerance for grid computations on binary floating point (`0.3 / 0.1` is `2.9999999999999996`). */\nconst EPSILON = 1e-9;\n\n/**\n * The value a native range with these bounds would hold for `value`: snapped to\n * `min + n × step` (ties toward +∞, the HTML step-mismatch rule), clamped to `[min, max]`, and,\n * when the snapped value exceeds `max`, the last grid point below `max` (so `min 0, max 5,\n * step 2` caps at `4`). Rounded to the decimal places of `step` and `min`. With `max < min` the\n * platform's maximum is `min`.\n */\nexport function snap(value: number, min: number, max: number, step: number): number {\n const decimals = Math.max(decimalsOf(step), decimalsOf(min));\n if (!Number.isFinite(value)) return min;\n if (!(max > min)) return roundTo(min, decimals);\n const lastIndex = Math.floor((max - min) / step + EPSILON);\n let index = Math.floor((value - min) / step + 0.5 + EPSILON);\n if (index > lastIndex) index = lastIndex;\n if (index < 0) index = 0;\n return roundTo(min + index * step, decimals);\n}\n\n/** Whether `max` is reachable: `max - min` is a whole number of steps. */\nexport function isMaxReachable(min: number, max: number, step: number): boolean {\n if (!(max > min)) return true;\n const steps = (max - min) / step;\n return Math.abs(steps - Math.round(steps)) < EPSILON * Math.max(1, steps);\n}\n\n/** Whether `value` is a value a native range with these bounds can hold unchanged. */\nexport function isOnGrid(value: number, min: number, max: number, step: number): boolean {\n return Math.abs(snap(value, min, max, step) - value) < EPSILON * Math.max(1, Math.abs(value));\n}\n\n/** The native `min` / `max` of thumb `index`: the slider's bounds, narrowed by its neighbours. */\nexport function thumbBounds(\n values: readonly number[],\n index: number,\n min: number,\n max: number,\n gap: number,\n): { readonly lower: number; readonly upper: number } {\n const decimals = Math.max(decimalsOf(gap), decimalsOf(min));\n const before = values[index - 1];\n const after = values[index + 1];\n const lower = before === undefined ? min : roundTo(before + gap, decimals);\n const upper = after === undefined ? max : roundTo(after - gap, decimals);\n return { lower, upper };\n}\n\n/**\n * `next` for thumb `index`, snapped to the slider's grid and clamped between its neighbours\n * (`values[i - 1] + gap`, `values[i + 1] - gap`; on the grid, because every thumb shares `step`\n * and `min`). With no room between the neighbours the thumb keeps its value.\n */\nexport function clampToNeighbours(\n values: readonly number[],\n index: number,\n next: number,\n min: number,\n max: number,\n step: number,\n gap: number,\n): number {\n const { lower, upper } = thumbBounds(values, index, min, max, gap);\n const current = values[index] ?? next;\n if (lower > upper + EPSILON) return current;\n return Math.min(Math.max(snap(next, min, max, step), lower), upper);\n}\n\n/**\n * The value a native input with these attributes would hold for `value` (each thumb's bounds come\n * from `reference`, the values it is rendered against). Used to compare a DOM read with the shown\n * value: jsdom does not sanitise a range's value, browsers do, and a consumer's off-grid value is\n * rendered as given and sanitised by the DOM.\n */\nexport function sanitize(\n values: readonly number[],\n reference: readonly number[],\n min: number,\n max: number,\n step: number,\n gap: number,\n): readonly number[] {\n return values.map((value, index) => {\n const { lower, upper } = thumbBounds(reference, index, min, max, gap);\n // The native step base is the input's own `min` attribute (the neighbour-adjusted bound).\n return snap(value, lower, Math.max(lower, upper), step);\n });\n}\n\n/** Position of `value` in `[min, max]`, in percent, clamped to `0`–`100`. */\nexport function percent(value: number, min: number, max: number): number {\n if (!(max > min)) return 0;\n const fraction = (value - min) / (max - min);\n return Math.min(100, Math.max(0, fraction * 100));\n}\n\n/**\n * The thumb a track press at `target` moves: the nearest by value. On a tie (two thumbs at one\n * value, or equidistant thumbs) the thumb that can move toward the pointer: the later one when\n * the pointer is above it, else the earlier one.\n */\nexport function nearestThumb(values: readonly number[], target: number): number {\n let best = 0;\n let bestDistance = Number.POSITIVE_INFINITY;\n values.forEach((value, index) => {\n const distance = Math.abs(value - target);\n if (distance < bestDistance - EPSILON) {\n best = index;\n bestDistance = distance;\n } else if (Math.abs(distance - bestDistance) <= EPSILON && target > value) {\n best = index;\n }\n });\n return best;\n}\n\n/** The platform's default value: the midpoint, snapped to the grid; `min` when `max < min`. */\nexport function platformDefault(min: number, max: number, step: number): number {\n if (!(max > min)) return min;\n return snap(min + (max - min) / 2, min, max, step);\n}\n\n/** Element-wise equality of two value arrays (within floating-point tolerance). */\nexport function equalValues(a: readonly number[], b: readonly number[]): boolean {\n if (a.length !== b.length) return false;\n return a.every((value, index) => {\n const other = b[index] as number;\n return value === other || Math.abs(value - other) < EPSILON * Math.max(1, Math.abs(value));\n });\n}\n"],"mappings":"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"}
@@ -5,11 +5,12 @@ import { transitionTypes } from "../internal/transition-types.mjs";
5
5
  import { useLatest } from "../internal/use-latest.mjs";
6
6
  import { useControllableAction } from "../internal/use-controllable-action.mjs";
7
7
  import { mergeTokenLists } from "../internal/merge-props.mjs";
8
- import { resolveStateValue, useRender } from "../internal/use-render.mjs";
8
+ import { resolveStateValue } from "../internal/render-element.mjs";
9
+ import { useRender } from "../internal/use-render.mjs";
9
10
  import { useDevWarning } from "../internal/use-dev-warning.mjs";
11
+ import { useActionTrigger } from "../internal/use-action-trigger.mjs";
10
12
  import { FieldContext } from "../internal/field-context.mjs";
11
13
  import { useFieldControl, useFieldValueChange, useMergedRef } from "../internal/use-field-control.mjs";
12
- import { useActionTrigger } from "../internal/use-action-trigger.mjs";
13
14
  import { useNativeGroupReconciliation } from "../internal/use-native-group-reconciliation.mjs";
14
15
  import { SliderContext } from "./slider-context.mjs";
15
16
  import { clampToNeighbours, equalValues, isMaxReachable, isOnGrid, nearestThumb, percent, platformDefault, sanitize } from "./slider-arithmetic.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"slider-root.mjs","names":[],"sources":["../../src/slider/slider-root.tsx"],"sourcesContent":["\"use client\";\nimport {\n addTransitionType,\n use,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode, RefObject } from \"react\";\nimport { createActionDetails } from \"../internal/action-details.js\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { FieldContext } from \"../internal/field-context.js\";\nimport { mergeTokenLists } from \"../internal/merge-props.js\";\nimport { transitionTypes } from \"../internal/transition-types.js\";\nimport type {\n ActionDetails,\n ChangeAction,\n ChangeReason,\n RenderProp,\n StateValue,\n} from \"../internal/types.js\";\nimport { useActionTrigger } from \"../internal/use-action-trigger.js\";\nimport { useControllableAction } from \"../internal/use-controllable-action.js\";\nimport { useDevWarning } from \"../internal/use-dev-warning.js\";\nimport {\n useFieldControl,\n useFieldValueChange,\n useMergedRef,\n} from \"../internal/use-field-control.js\";\nimport type { FormAssociatedElement } from \"../internal/use-form-reset.js\";\nimport { useLatest } from \"../internal/use-latest.js\";\nimport { useNativeGroupReconciliation } from \"../internal/use-native-group-reconciliation.js\";\nimport { resolveStateValue, useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport {\n clampToNeighbours,\n equalValues,\n isMaxReachable,\n isOnGrid,\n nearestThumb,\n percent,\n platformDefault,\n sanitize,\n} from \"./slider-arithmetic.js\";\nimport { SliderContext } from \"./slider-context.js\";\nimport type { SliderContextValue, SliderFieldWiring } from \"./slider-context.js\";\n\n/** One number (one thumb) or one number per thumb, in ascending order. */\nexport type SliderValue = number | readonly number[];\n\nexport type SliderOrientation = \"horizontal\" | \"vertical\";\n\n/** Details passed as the second argument of `Slider.Root`'s `valueChangeAction` (each step). */\nexport interface SliderValueChangeDetails extends ActionDetails {\n /**\n * `\"activate\"`: the user moved a thumb (`details.event` is the native `input` event for a key\n * press, the `pointerdown` / `pointermove` / `pointerup` for a drag, the `keydown` for a\n * JS-normalised key).\n * `\"platform\"`: a form reset (the `reset` event) or a value found in the inputs at mount\n * (`undefined`).\n * `\"dismiss\"`: the commit action rejected and the slider reverted to the committed value\n * (uncontrolled mode; `undefined`).\n */\n readonly reason: ChangeReason;\n /** Index of the thumb that moved; `null` on a platform path or a revert, where several may change. */\n readonly thumb: number | null;\n}\n\n/** Details passed as the second argument of `Slider.Root`'s `valueCommitAction` (each gesture). */\nexport interface SliderValueCommitDetails extends ActionDetails {\n /**\n * `\"activate\"`: a gesture ended (`details.event` is the native `change` event for a key press,\n * the `pointerup` / `pointercancel` / `lostpointercapture` for a drag, the `keydown` for a\n * JS-normalised key). `\"platform\"`: a form reset (the `reset` event) or mount reconciliation\n * (`undefined`). Never `\"dismiss\"`.\n */\n readonly reason: ChangeReason;\n /** Index of the thumb the gesture moved; `null` on a platform path. */\n readonly thumb: number | null;\n}\n\nexport interface SliderRootState<T extends SliderValue = number> {\n /**\n * The value the thumbs show: the value a gesture has reached while a pointer is captured or a\n * step or commit is in flight, else the optimistic value. Content rendered from it must not\n * suspend.\n */\n readonly value: T;\n /** `value` as an array, one entry per thumb, in thumb order. */\n readonly values: readonly number[];\n /** A step or commit dispatched through this Slider is in flight. */\n readonly pending: boolean;\n /** A pointer is captured on a thumb. */\n readonly dragging: boolean;\n readonly orientation: SliderOrientation;\n readonly disabled: boolean;\n readonly min: number;\n readonly max: number;\n readonly step: number;\n}\n\nexport interface SliderRootProps<T extends SliderValue = number> extends Omit<\n ComponentPropsWithRef<\"div\">,\n | \"defaultValue\"\n | \"role\"\n | \"className\"\n | \"style\"\n | \"children\"\n // The value attributes are the native inputs' (design 8): never authored.\n | \"aria-valuemin\"\n | \"aria-valuemax\"\n | \"aria-valuenow\"\n | \"aria-valuetext\"\n | \"aria-orientation\"\n> {\n /** Controlled value: one number, or one per thumb in ascending order. `undefined`: uncontrolled. */\n value?: T;\n /**\n * Initial value in uncontrolled mode; also the form-reset target (latest value). Default: the\n * platform's midpoint, `min + (max - min) / 2`, snapped to `step`.\n */\n defaultValue?: T;\n /**\n * Runs inside the Root's step transition on every step: each pointer move, each key press,\n * each platform change, and the revert after a rejected commit (`reason: \"dismiss\"`,\n * uncontrolled). Awaited; `data-pending` meanwhile (without this action a step starts no\n * transition and is never pending). Adopt the value here in a controlled\n * parent (`setValue(next)` in the sync prefix is a transition update). Not the place for a\n * save: a pending async action entangles every transition in the app, and a drag is many\n * steps. A `setState` after your own `await` needs `startTransition`.\n */\n valueChangeAction?: ChangeAction<T, SliderValueChangeDetails>;\n /**\n * Runs inside the Root's commit transition once per gesture: pointer release, each key press,\n * a form reset, a value found at mount. Awaited; the thumb keeps the gesture's value and shows\n * `data-pending` until it settles; in uncontrolled mode the value is committed when it\n * resolves and reverts to the previous value if it rejects. May be a Server Function.\n */\n valueCommitAction?: ChangeAction<T, SliderValueCommitDetails>;\n /** Default `0`. */\n min?: number;\n /**\n * Default `100`. A `max` that is not on the step grid from `min` is unreachable, as on a\n * native range (dev warning).\n */\n max?: number;\n /** Default `1`. Must be positive. Values snap to `min + n × step`. */\n step?: number;\n /** Minimum number of steps between two adjacent thumbs. Default `0` (thumbs may share a value). */\n minStepsBetweenThumbs?: number;\n /** Default `\"horizontal\"`. Vertical sliders have `min` at the bottom. */\n orientation?: SliderOrientation;\n /**\n * `aria-valuetext` for a thumb, from the value it shows. Set it when the number alone is not\n * meaningful (\"3 of 5 stars\", \"Tuesday\"). Default: none (the number is announced).\n */\n getAriaValueText?: (value: number, index: number) => string;\n /**\n * Form field name for every thumb's input (a Thumb's own `name` wins). With several thumbs,\n * read with `FormData.getAll()`.\n */\n name?: string;\n /** The `form` attribute for every thumb's input (a Thumb's own `form` wins). */\n form?: string;\n /** Disables every input (native `disabled`; not submitted) and the pointer. Never set while pending. */\n disabled?: boolean;\n className?: StateValue<string | undefined, SliderRootState<T>>;\n style?: StateValue<CSSProperties | undefined, SliderRootState<T>>;\n children?: StateValue<ReactNode, SliderRootState<T>>;\n render?: RenderProp<ComponentPropsWithRef<\"div\">, SliderRootState<T>>;\n}\n\nconst isDev = process.env.NODE_ENV !== \"production\";\n\nconst STEP_TYPES = transitionTypes(\"slider\", \"change\");\nconst COMMIT_TYPES = transitionTypes(\"slider\", \"commit\");\n\nfunction toArray(value: SliderValue): readonly number[] {\n return typeof value === \"number\" ? [value] : value;\n}\n\nfunction shapeOf(value: SliderValue | undefined): \"number\" | \"array\" | undefined {\n if (value === undefined) return undefined;\n return typeof value === \"number\" ? \"number\" : \"array\";\n}\n\nfunction replaceAt(values: readonly number[], index: number, value: number): readonly number[] {\n return values.map((v, i) => (i === index ? value : v));\n}\n\n/** Writes each registered input's `defaultValue` (the attribute a form reset restores). */\nfunction writeDefaults(\n registry: ReadonlyMap<number, HTMLInputElement>,\n target: readonly number[],\n): void {\n for (const [index, input] of registry) {\n const entry = target[index];\n if (entry !== undefined) input.defaultValue = String(entry);\n }\n}\n\n/** A pointer captured on a Thumb or the Track (design 4.1). */\ninterface ActiveGesture {\n readonly pointerId: number;\n /** Detaches the gesture's listeners. */\n readonly detach: () => void;\n}\n\n/**\n * Owns the slider's state (design/components/slider.md 2): the committed value through\n * `useControllableAction` with `valueCommitAction` (once per gesture), each step through its own\n * transition (`valueChangeAction`), and the value a gesture has reached in the urgent lane\n * (`live`), which the thumbs show while a pointer is captured or anything is in flight. Also the\n * pointer gesture, the Thumb registry, mount reconciliation and form reset, and the geometry\n * custom properties `--slider-start`, `--slider-end` and `--slider-value-<i>`.\n *\n * Owned keys (conventions 1.2): `role` (`\"group\"` with several thumbs), `aria-labelledby` (the\n * Label's id while a Label is mounted and there are several thumbs; token-merged with the\n * consumer's), `data-pending`, `data-dragging`, `data-orientation`, `data-disabled`. The custom\n * properties are merged into `style`, where the consumer's entries win.\n *\n * Inside a `Field.Root` (design 9.4) the Root calls `useFieldControl`: with one thumb, Thumb 0's\n * input is the Field's labelable control; with several, the Root registers itself as the group\n * and also owns the Field label in `aria-labelledby`, the Field's `aria-describedby` and\n * `data-invalid`. `name` / `disabled` default from the Field.\n */\nfunction SliderRootImpl<T extends SliderValue = number>(props: SliderRootProps<T>) {\n const {\n value,\n defaultValue,\n valueChangeAction,\n valueCommitAction,\n min = 0,\n max = 100,\n step: stepProp = 1,\n minStepsBetweenThumbs = 0,\n orientation = \"horizontal\",\n getAriaValueText,\n name: nameProp,\n form,\n disabled: disabledProp = false,\n className,\n style,\n children,\n render,\n ...rest\n } = props;\n\n const stepValid = Number.isFinite(stepProp) && stepProp > 0;\n const step = stepValid ? stepProp : 1;\n const gap = Math.max(0, minStepsBetweenThumbs) * step;\n\n const id = useId();\n const labelId = `${id}-label`;\n\n // The shape (one number or an array) is fixed at mount (design 3.1).\n const [shape] = useState<\"number\" | \"array\">(() => shapeOf(value ?? defaultValue) ?? \"number\");\n const fromArray = useCallback(\n (values: readonly number[]): T => (shape === \"number\" ? values[0] : values) as T,\n [shape],\n );\n\n // --- State (design 2) ----------------------------------------------------------------------\n\n const [live, setLive] = useState<readonly number[] | null>(null);\n const [gestureThumb, setGestureThumb] = useState<number | null>(null);\n /**\n * A step was taken and its gesture's commit has not been dispatched yet. Holds `live` on\n * screen between a key's native `input` and `change` when no step transition runs (no\n * `valueChangeAction`): otherwise react-dom restores the controlled input to the old value\n * after `input`, and Firefox then fires no `change`.\n */\n const [stepHeld, setStepHeld] = useState(false);\n const [pendingThumb, setPendingThumb] = useState<number | null>(null);\n\n /** The value of the latest step, read by the commit in the same or a later event. */\n const liveRef = useRef<readonly number[] | null>(null);\n /** The shown value when the open gesture began; `null` when no gesture is open. */\n const gestureStart = useRef<readonly number[] | null>(null);\n const activeGesture = useRef<ActiveGesture | null>(null);\n const commitSeq = useRef(0);\n const trackRef = useRef<HTMLElement | null>(null);\n\n const runCommit = async (next: T, details: SliderValueCommitDetails): Promise<void> => {\n const seq = ++commitSeq.current;\n try {\n await valueCommitAction?.(next, details);\n } catch (error) {\n // Design 2.4: in uncontrolled mode, tell the preview channel about the rollback, for the\n // latest commit only. Yield once to leave the commit's transition (conventions 2.6).\n if (value === undefined && seq === commitSeq.current) {\n await undefined;\n // `stepTo` and `committedRef` are declared below; this runs long after the render.\n stepTo(toArray(committedRef.current), null, \"dismiss\", undefined);\n }\n throw error;\n }\n };\n\n const commitState = useControllableAction<T, SliderValueCommitDetails>({\n controlled: value,\n defaultValue,\n initialValue: platformDefault(min, max, step) as T,\n action: runCommit,\n transitionTypes: () => COMMIT_TYPES,\n warn: { component: \"Slider.Root\", prop: \"value\" },\n });\n const { optimistic, committed, dispatch } = commitState;\n const committedRef = useLatest(committed);\n\n const { pending: stepPending, run: runStep } = useActionTrigger();\n\n const optimisticValues = useMemo(() => toArray(optimistic), [optimistic]);\n const held = gestureThumb !== null || stepHeld || stepPending || commitState.pending;\n const shown = held && live !== null ? live : optimisticValues;\n const pending = stepPending || commitState.pending;\n\n // --- Inside a Field.Root (design 9.4) ------------------------------------------------------\n\n // One thumb: its input is the Field's labelable control. Several: the Root (`role=\"group\"`)\n // registers, `Field.Label` drops `for` and names the group through `aria-labelledby`.\n const thumbCount = shown.length;\n const field = useFieldControl({\n labelable: thumbCount === 1,\n name: nameProp,\n disabled: disabledProp,\n component: \"Slider.Root\",\n });\n const fieldName = use(FieldContext)?.name;\n const name = field.name;\n const disabled = field.disabled;\n const fieldId = field.id;\n const thumbId = useCallback(\n (index: number) => (index === 0 && fieldId !== undefined ? fieldId : `${id}-thumb-${index}`),\n [id, fieldId],\n );\n const rootRef = useMergedRef<HTMLElement>(undefined, thumbCount > 1 ? field.ref : undefined);\n useDevWarning(\n field.inField && field.required,\n \"Slider.Root: a range is never empty, so `required` on the enclosing Field.Root has no \" +\n \"effect on the slider.\",\n );\n /**\n * The reason of the latest change the user or the platform made, consumed by the Field\n * notification below: `\"activate\"` dismisses a shown server error, a rollback does not.\n */\n const lastReason = useRef<ChangeReason | null>(null);\n // A pointer gesture and the JS-normalised keys fire no `input` / `change` the Field hears:\n // tell it at the commit, when the optimistic value changes (design 9.4.4).\n useFieldValueChange(optimisticValues.join(\"\\u0000\"), () => {\n const edit = lastReason.current === \"activate\";\n lastReason.current = null;\n return edit;\n });\n const {\n \"aria-labelledby\": fieldLabelledBy,\n \"aria-describedby\": fieldDescribedBy,\n \"aria-invalid\": fieldInvalid,\n \"data-invalid\": fieldDataInvalid,\n } = field.attributes;\n const inField = field.inField;\n const fieldRef = field.ref;\n const fieldWiring = useMemo<SliderFieldWiring | null>(() => {\n if (!inField) return null;\n const single = thumbCount === 1;\n return {\n inputRef: single ? fieldRef : undefined,\n describedBy: single ? fieldDescribedBy : undefined,\n invalid: fieldInvalid,\n dataInvalid: fieldDataInvalid,\n name: fieldName,\n };\n }, [inField, fieldRef, thumbCount, fieldDescribedBy, fieldInvalid, fieldDataInvalid, fieldName]);\n\n /** What the thumbs show, for handlers; also written by `stepTo` ahead of the render. */\n const shownRef = useLatest(shown);\n\n const latest = useLatest({\n valueChangeAction,\n fromArray,\n runStep,\n min,\n max,\n step,\n gap,\n orientation,\n disabled,\n });\n\n // --- Step and commit (design 2.4) ---------------------------------------------------------\n\n const stepTo = useCallback(\n (\n next: readonly number[],\n thumb: number | null,\n reason: ChangeReason,\n event: Event | undefined,\n ): boolean => {\n // No-op against what the user sees (conventions 2.3 item 8).\n if (equalValues(next, shownRef.current)) return false;\n liveRef.current = next;\n shownRef.current = next;\n // A controlled parent that adopts steps changes the optimistic value per step.\n lastReason.current = reason;\n setLive(next);\n setPendingThumb(thumb);\n // A revert has no commit after it: the optimistic value already shows the committed one.\n if (reason !== \"dismiss\") setStepHeld(true);\n const { valueChangeAction: action, fromArray: toValue, runStep: run } = latest.current;\n // Without a step action there is nothing to run and no consumer update to keep\n // interruptible: no transition, so `data-pending` does not blink on every pointer move.\n if (action === undefined) return true;\n run(() => {\n for (const type of STEP_TYPES) addTransitionType(type);\n return action?.(toValue(next), createActionDetails(event, { reason, thumb }));\n });\n return true;\n },\n [latest, shownRef],\n );\n\n const commitGesture = useCallback(\n (thumb: number | null, reason: ChangeReason, event: Event | undefined): void => {\n const start = gestureStart.current;\n gestureStart.current = null;\n // The commit's own pending state holds `live` from here (set in this same batch).\n setStepHeld(false);\n const next = liveRef.current;\n // Nothing changed since the gesture began (a drag out and back, a trailing `change`).\n if (start === null || next === null || equalValues(next, start)) return;\n lastReason.current = reason;\n setPendingThumb(thumb);\n dispatch(latest.current.fromArray(next), createActionDetails(event, { reason, thumb }));\n },\n [dispatch, latest],\n );\n\n // --- Thumb registry ------------------------------------------------------------------------\n\n const [registry] = useState(() => new Map<number, HTMLInputElement>());\n const warnedDuplicate = useRef(false);\n const warnedForm = useRef(false);\n const registerThumb = useCallback(\n (index: number, input: HTMLInputElement) => {\n const existing = registry.get(index);\n if (isDev && existing !== undefined && existing !== input && !warnedDuplicate.current) {\n warnedDuplicate.current = true;\n console.error(\n `Slider.Thumb: two Thumbs have \\`index={${index}}\\`. Each value needs exactly one ` +\n `Thumb; give every Thumb a distinct index.`,\n );\n }\n if (isDev && !warnedForm.current) {\n for (const other of registry.values()) {\n if (other !== input && other.form !== input.form) {\n warnedForm.current = true;\n console.error(\n \"Slider.Thumb: the thumbs of one Slider belong to different forms (a Thumb's \" +\n \"`form` prop). A form reset is followed through the first thumb's form only; \" +\n \"keep every thumb in one form.\",\n );\n break;\n }\n }\n }\n registry.set(index, input);\n return () => {\n if (registry.get(index) === input) registry.delete(index);\n };\n },\n [registry],\n );\n\n /** The first registered input: the form-associated element the reset subscription follows. */\n const formElement = useMemo<RefObject<FormAssociatedElement | null>>(\n () => ({\n get current() {\n let first: HTMLInputElement | null = null;\n let firstIndex = Number.POSITIVE_INFINITY;\n for (const [index, input] of registry) {\n if (index < firstIndex) {\n firstIndex = index;\n first = input;\n }\n }\n return first;\n },\n set current(_ignored) {},\n }),\n [registry],\n );\n\n // --- Labels --------------------------------------------------------------------------------\n\n const [labelCount, setLabelCount] = useState(0);\n // The same count for the dev warning, which can run before the re-render the registration\n // scheduled.\n const labelCountRef = useRef(0);\n const registerLabel = useCallback(() => {\n labelCountRef.current += 1;\n setLabelCount((count) => count + 1);\n return () => {\n labelCountRef.current -= 1;\n setLabelCount((count) => count - 1);\n };\n }, []);\n\n // --- Residual browser paths: mount reconciliation and form reset (design 9.2, 9.3) --------\n\n const [mountValue] = useState(value);\n const resetTarget = (): readonly number[] =>\n value !== undefined\n ? toArray(mountValue ?? value)\n : toArray(defaultValue ?? platformDefault(min, max, step));\n\n const readCurrent = (): readonly number[] =>\n shownRef.current.map((v, index) => {\n const input = registry.get(index);\n if (input === undefined) return v;\n const read = Number(input.value);\n return Number.isFinite(read) ? read : v;\n });\n\n const { onItemMounted } = useNativeGroupReconciliation<readonly number[]>({\n element: formElement,\n readCurrent,\n readDefault: resetTarget,\n base: () => shownRef.current,\n // Compare as the DOM would hold the values: a consumer's off-grid value is sanitised by the\n // browser (not by jsdom), and that is not a platform change.\n equals: (a, b) => {\n const reference = shownRef.current;\n return equalValues(\n sanitize(a, reference, min, max, step, gap),\n sanitize(b, reference, min, max, step, gap),\n );\n },\n onPlatformChange: (next, event) => {\n if (next.length !== shownRef.current.length) return;\n const before = shownRef.current;\n gestureStart.current = before;\n liveRef.current = before;\n stepTo(next, null, \"platform\", event);\n commitGesture(null, \"platform\", event);\n },\n onResetEvent: () => {\n // react-dom writes `defaultValue = value` after every update of a controlled input, so the\n // reset target is written here, right before the browser's reset algorithm reads it.\n writeDefaults(registry, resetTarget());\n },\n });\n\n // --- Keyboard (design 4.2) -----------------------------------------------------------------\n\n const inputStep = useCallback(\n (index: number, raw: number, event: Event) => {\n if (!Number.isFinite(raw)) return;\n const before = shownRef.current;\n if (index >= before.length) return;\n // A key press is a one-step gesture: it starts at the value shown before it.\n if (stepTo(replaceAt(before, index, raw), index, \"activate\", event)) {\n if (gestureStart.current === null) gestureStart.current = before;\n }\n },\n [shownRef, stepTo],\n );\n\n const inputCommit = useCallback(\n (index: number, event: Event) => {\n // A pointer gesture commits at its release.\n if (activeGesture.current !== null) return;\n commitGesture(index, \"activate\", event);\n },\n [commitGesture],\n );\n\n const inputKeyDown = useCallback(\n (index: number, event: KeyboardEvent) => {\n const {\n orientation: axis,\n disabled: off,\n min: lo,\n max: hi,\n step: inc,\n gap: g,\n } = latest.current;\n if (off) return;\n if (event.key !== \"ArrowLeft\" && event.key !== \"ArrowRight\") return;\n if (event.altKey || event.ctrlKey || event.metaKey) return;\n // Vertical: Firefox decreases a vertical range on ArrowRight; the APG says increase.\n // Horizontal RTL: the track is mirrored (min on the right), so ArrowLeft increases;\n // Chromium and Firefox mirror a native range, WebKit does not (design 7). LTR stays native.\n let increaseKey: \"ArrowLeft\" | \"ArrowRight\";\n if (axis === \"vertical\") {\n increaseKey = \"ArrowRight\";\n } else {\n // Read at the keydown: the direction may come from any ancestor and change at any time.\n const input = event.currentTarget as Element | null;\n if (input === null || getComputedStyle(input).direction !== \"rtl\") return;\n increaseKey = \"ArrowLeft\";\n }\n event.preventDefault();\n const before = shownRef.current;\n const current = before[index];\n if (current === undefined) return;\n const delta = event.key === increaseKey ? inc : -inc;\n const next = replaceAt(\n before,\n index,\n clampToNeighbours(before, index, current + delta, lo, hi, inc, g),\n );\n if (activeGesture.current !== null) {\n stepTo(next, index, \"activate\", event);\n return;\n }\n gestureStart.current = before;\n liveRef.current = before;\n stepTo(next, index, \"activate\", event);\n commitGesture(index, \"activate\", event);\n },\n [commitGesture, latest, shownRef, stepTo],\n );\n\n // --- Pointer (design 4.1) ------------------------------------------------------------------\n\n const warnedNoTrack = useRef(false);\n const beginGesture = useCallback(\n (index: number | null, event: PointerEvent, element: HTMLElement) => {\n const { disabled: off } = latest.current;\n if (off || event.button !== 0 || activeGesture.current !== null) return;\n const track = trackRef.current;\n if (track === null) {\n if (isDev && !warnedNoTrack.current) {\n warnedNoTrack.current = true;\n console.error(\n \"Slider.Thumb: a pointer press needs a Slider.Track to map the pointer to a value. \" +\n \"Without a Track the slider is keyboard-only.\",\n );\n }\n return;\n }\n // No text selection, no focus change through the compatibility `mousedown`.\n event.preventDefault();\n const rtl = getComputedStyle(track).direction === \"rtl\";\n\n const valueAt = (clientX: number, clientY: number): number => {\n const { min: lo, max: hi, orientation: axis } = latest.current;\n const rect = (trackRef.current ?? track).getBoundingClientRect();\n let fraction: number;\n if (axis === \"vertical\") {\n fraction = rect.height > 0 ? (rect.bottom - clientY) / rect.height : 0;\n } else {\n fraction = rect.width > 0 ? (clientX - rect.left) / rect.width : 0;\n if (rtl) fraction = 1 - fraction;\n }\n fraction = Math.min(1, Math.max(0, fraction));\n return lo + fraction * (hi - lo);\n };\n const moveTo = (thumb: number, raw: number, cause: Event): void => {\n const { min: lo, max: hi, step: inc, gap: g } = latest.current;\n const before = shownRef.current;\n if (thumb >= before.length) return;\n stepTo(\n replaceAt(before, thumb, clampToNeighbours(before, thumb, raw, lo, hi, inc, g)),\n thumb,\n \"activate\",\n cause,\n );\n };\n\n const start = valueAt(event.clientX, event.clientY);\n const startValues = shownRef.current;\n // A press on a Thumb that shares its value with a neighbour (stacked thumbs) moves the one\n // that can go toward the pointer, the Track's tie rule; when the press is exactly on the\n // value, the first move decides. Otherwise a Thumb press moves that Thumb.\n let tied: { readonly first: number; readonly last: number; readonly at: number } | null =\n null;\n if (index !== null) {\n const at = startValues[index];\n if (at !== undefined) {\n let first = index;\n let last = index;\n while (first > 0 && equalValues([startValues[first - 1] as number], [at])) first -= 1;\n while (\n last < startValues.length - 1 &&\n equalValues([startValues[last + 1] as number], [at])\n ) {\n last += 1;\n }\n if (first !== last) tied = { first, last, at };\n }\n }\n const resolveTie = (raw: number): number | null => {\n if (tied === null) return null;\n if (raw > tied.at) return tied.last;\n if (raw < tied.at) return tied.first;\n return null;\n };\n /** The thumb the gesture moves; `null` while a press on stacked thumbs is undecided. */\n let decided: number | null =\n index === null ? nearestThumb(startValues, start) : tied ? resolveTie(start) : index;\n /** The thumb shown as dragging and focused meanwhile. */\n let thumb = decided ?? index ?? 0;\n const pointerId = event.pointerId;\n try {\n element.setPointerCapture(pointerId);\n } catch {\n // An inactive pointer id (a synthetic event): the gesture still follows the element.\n }\n\n const decide = (raw: number): boolean => {\n if (decided !== null) return true;\n decided = resolveTie(raw);\n if (decided === null) return false;\n if (decided !== thumb) {\n thumb = decided;\n setGestureThumb(thumb);\n registry.get(thumb)?.focus({ focusVisible: false } as FocusOptions);\n }\n return true;\n };\n const follow = (pointerEvent: PointerEvent): void => {\n const raw = valueAt(pointerEvent.clientX, pointerEvent.clientY);\n if (decide(raw)) moveTo(thumb, raw, pointerEvent);\n };\n\n const onMove = (moveEvent: PointerEvent): void => {\n if (moveEvent.pointerId !== pointerId) return;\n follow(moveEvent);\n };\n const onEnd = (endEvent: PointerEvent): void => {\n if (endEvent.pointerId !== pointerId) return;\n detach();\n // The release position is the gesture's last (an engine may coalesce the final move\n // into the `pointerup`); a cancel or a lost capture keeps the last move's value.\n if (endEvent.type === \"pointerup\") follow(endEvent);\n activeGesture.current = null;\n setGestureThumb(null);\n commitGesture(thumb, \"activate\", endEvent);\n };\n const detach = (): void => {\n element.removeEventListener(\"pointermove\", onMove);\n element.removeEventListener(\"pointerup\", onEnd);\n element.removeEventListener(\"pointercancel\", onEnd);\n element.removeEventListener(\"lostpointercapture\", onEnd);\n };\n element.addEventListener(\"pointermove\", onMove);\n element.addEventListener(\"pointerup\", onEnd);\n element.addEventListener(\"pointercancel\", onEnd);\n element.addEventListener(\"lostpointercapture\", onEnd);\n\n activeGesture.current = { pointerId, detach };\n setGestureThumb(thumb);\n gestureStart.current = shownRef.current;\n liveRef.current = shownRef.current;\n // A capture alone holds `live` on screen: start it from what is shown, not from the value\n // an earlier gesture left behind (a press exactly on the current value steps nothing).\n setLive(shownRef.current);\n // `:focus-visible` does not match after a pointer press, as on a native range.\n registry.get(thumb)?.focus({ focusVisible: false } as FocusOptions);\n if (decided !== null) moveTo(thumb, start, event);\n },\n [commitGesture, latest, registry, shownRef, stepTo],\n );\n\n // An unmount mid-gesture leaves no listener behind.\n useEffect(\n () => () => {\n activeGesture.current?.detach();\n activeGesture.current = null;\n },\n [],\n );\n\n // --- Development warnings ------------------------------------------------------------------\n\n useDevWarning(\n !stepValid,\n `Slider.Root: \\`step\\` must be a positive number (got ${String(stepProp)}); using 1.`,\n );\n useDevWarning(\n stepValid && !isMaxReachable(min, max, step),\n `Slider.Root: \\`max\\` (${max}) is not on the step grid from \\`min\\` (${min}) with \\`step\\` ` +\n `${step}: it is unreachable, as on a native range. The last reachable value is the last ` +\n `step below \\`max\\`.`,\n );\n const given = value ?? defaultValue;\n const givenValues = given === undefined ? [] : toArray(given);\n useDevWarning(\n givenValues.some((v) => !isOnGrid(v, min, max, step)),\n `Slider.Root: the ${value !== undefined ? \"`value`\" : \"`defaultValue`\"} ` +\n `(${givenValues.join(\", \")}) is off the step grid or outside \\`min\\` / \\`max\\`. It is ` +\n `rendered as given and the browser sanitises it; the first user step snaps it.`,\n );\n useDevWarning(\n givenValues.some((v, i) => i > 0 && v < (givenValues[i - 1] as number)),\n `Slider.Root: the values (${givenValues.join(\", \")}) must be in ascending order; the thumbs ` +\n `would be rendered crossed.`,\n );\n const currentShape = shapeOf(given);\n useDevWarning(\n currentShape !== undefined && currentShape !== shape,\n `Slider.Root: the value changed shape between a number and an array after mount. The shape ` +\n `is fixed at mount; remount the Slider (a \\`key\\`) to change the number of thumbs.`,\n );\n // Inside a Field, `Field.Label` names the group (design 9.4.2).\n const unnamedGroup =\n shown.length > 1 &&\n !inField &&\n rest[\"aria-label\"] === undefined &&\n rest[\"aria-labelledby\"] === undefined;\n const warnedGroupName = useRef(false);\n useEffect(() => {\n if (!isDev || warnedGroupName.current || !unnamedGroup || labelCountRef.current > 0) return;\n warnedGroupName.current = true;\n console.error(\n \"Slider.Root: a slider with several thumbs is a `group` and needs a name: render a \" +\n \"Slider.Label, or pass `aria-label` / `aria-labelledby` to the Root.\",\n );\n }, [unnamedGroup]);\n\n // --- Render --------------------------------------------------------------------------------\n\n const count = shown.length;\n const percents = shown.map((v) => percent(v, min, max));\n const geometry: Record<string, string> = {\n \"--slider-start\": count > 1 ? `${percents[0] ?? 0}%` : \"0%\",\n \"--slider-end\": `${percents[count - 1] ?? 0}%`,\n };\n percents.forEach((p, index) => {\n geometry[`--slider-value-${index}`] = `${p}%`;\n });\n\n const shownValue = fromArray(shown);\n const dragging = gestureThumb !== null;\n const state = useMemo<SliderRootState<T>>(\n () => ({\n value: shownValue,\n values: shown,\n pending,\n dragging,\n orientation,\n disabled,\n min,\n max,\n step,\n }),\n [shownValue, shown, pending, dragging, orientation, disabled, min, max, step],\n );\n\n // Memoised (#48): the functions are stable, so this changes only with the state below.\n const context = useMemo<SliderContextValue>(\n () => ({\n state: state as SliderRootState<SliderValue>,\n shown,\n shownValue: shownValue as SliderValue,\n min,\n max,\n step,\n gap,\n orientation,\n disabled,\n pending,\n draggingThumb: gestureThumb,\n pendingThumb,\n name,\n form,\n getAriaValueText,\n labelId,\n thumbId,\n trackRef,\n inputStep,\n inputCommit,\n inputKeyDown,\n beginGesture,\n registerThumb,\n registerLabel,\n onItemMounted,\n field: fieldWiring,\n }),\n [\n state,\n shown,\n shownValue,\n min,\n max,\n step,\n gap,\n orientation,\n disabled,\n pending,\n gestureThumb,\n pendingThumb,\n name,\n form,\n getAriaValueText,\n labelId,\n thumbId,\n inputStep,\n inputCommit,\n inputKeyDown,\n beginGesture,\n registerThumb,\n registerLabel,\n onItemMounted,\n fieldWiring,\n ],\n );\n\n // Several thumbs: the Field's label, then `Slider.Label` while one is mounted (the consumer's\n // tokens come first through the merge). Only when there is one: an owned `undefined` would\n // remove the consumer's own tokens.\n const labelledBy =\n count > 1 ? mergeTokenLists(fieldLabelledBy, labelCount > 0 ? labelId : undefined) : \"\";\n const libraryProps: Partial<ComponentPropsWithRef<\"div\">> & DataAttributes = {\n role: count > 1 ? \"group\" : undefined,\n ...(labelledBy !== \"\" ? { \"aria-labelledby\": labelledBy } : {}),\n // The group element is described (read when focus enters it); one thumb: its input is.\n ...(count > 1 && fieldDescribedBy !== undefined\n ? { \"aria-describedby\": fieldDescribedBy }\n : {}),\n // Inside a Field only (`aria-invalid` goes on the inputs, never on the group).\n ...(inField ? { \"data-invalid\": fieldDataInvalid } : {}),\n \"data-pending\": dataAttr(pending),\n \"data-dragging\": dataAttr(dragging),\n \"data-orientation\": orientation,\n \"data-disabled\": dataAttr(disabled),\n };\n\n const element = useRender<ComponentPropsWithRef<\"div\">, SliderRootState<T>>({\n defaultElement: \"div\",\n render,\n state,\n className,\n // The geometry properties lose to the consumer's own entries (design 3.1).\n style: (s) => ({ ...(geometry as CSSProperties), ...resolveStateValue(style, s) }),\n children,\n props: rest,\n libraryProps,\n ref: rootRef,\n });\n\n return <SliderContext value={context}>{element}</SliderContext>;\n}\n\nSliderRootImpl.displayName = \"SliderRoot\";\n\n/**\n * `Slider.Root`. Overloaded so that the value's shape is inferred from `value` / `defaultValue`\n * as `number` or `readonly number[]` (an array literal would otherwise infer a mutable\n * `number[]`), and every action and state function receives that shape (design 3.1).\n */\nexport const SliderRoot = SliderRootImpl as {\n (props: SliderRootProps<number>): ReactNode;\n (props: SliderRootProps<readonly number[]>): ReactNode;\n (props: SliderRootProps<SliderValue>): ReactNode;\n displayName?: string;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"slider-root.mjs","names":[],"sources":["../../src/slider/slider-root.tsx"],"sourcesContent":["\"use client\";\nimport {\n addTransitionType,\n use,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode, RefObject } from \"react\";\nimport { createActionDetails } from \"../internal/action-details.js\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { FieldContext } from \"../internal/field-context.js\";\nimport { mergeTokenLists } from \"../internal/merge-props.js\";\nimport { transitionTypes } from \"../internal/transition-types.js\";\nimport type {\n ActionDetails,\n ChangeAction,\n ChangeReason,\n RenderProp,\n StateValue,\n} from \"../internal/types.js\";\nimport { useActionTrigger } from \"../internal/use-action-trigger.js\";\nimport { useControllableAction } from \"../internal/use-controllable-action.js\";\nimport { useDevWarning } from \"../internal/use-dev-warning.js\";\nimport {\n useFieldControl,\n useFieldValueChange,\n useMergedRef,\n} from \"../internal/use-field-control.js\";\nimport type { FormAssociatedElement } from \"../internal/use-form-reset.js\";\nimport { useLatest } from \"../internal/use-latest.js\";\nimport { useNativeGroupReconciliation } from \"../internal/use-native-group-reconciliation.js\";\nimport { resolveStateValue, useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport {\n clampToNeighbours,\n equalValues,\n isMaxReachable,\n isOnGrid,\n nearestThumb,\n percent,\n platformDefault,\n sanitize,\n} from \"./slider-arithmetic.js\";\nimport { SliderContext } from \"./slider-context.js\";\nimport type { SliderContextValue, SliderFieldWiring } from \"./slider-context.js\";\n\n/** One number (one thumb) or one number per thumb, in ascending order. */\nexport type SliderValue = number | readonly number[];\n\nexport type SliderOrientation = \"horizontal\" | \"vertical\";\n\n/** Details passed as the second argument of `Slider.Root`'s `valueChangeAction` (each step). */\nexport interface SliderValueChangeDetails extends ActionDetails {\n /**\n * `\"activate\"`: the user moved a thumb (`details.event` is the native `input` event for a key\n * press, the `pointerdown` / `pointermove` / `pointerup` for a drag, the `keydown` for a\n * JS-normalised key).\n * `\"platform\"`: a form reset (the `reset` event) or a value found in the inputs at mount\n * (`undefined`).\n * `\"dismiss\"`: the commit action rejected and the slider reverted to the committed value\n * (uncontrolled mode; `undefined`).\n */\n readonly reason: ChangeReason;\n /** Index of the thumb that moved; `null` on a platform path or a revert, where several may change. */\n readonly thumb: number | null;\n}\n\n/** Details passed as the second argument of `Slider.Root`'s `valueCommitAction` (each gesture). */\nexport interface SliderValueCommitDetails extends ActionDetails {\n /**\n * `\"activate\"`: a gesture ended (`details.event` is the native `change` event for a key press,\n * the `pointerup` / `pointercancel` / `lostpointercapture` for a drag, the `keydown` for a\n * JS-normalised key). `\"platform\"`: a form reset (the `reset` event) or mount reconciliation\n * (`undefined`). Never `\"dismiss\"`.\n */\n readonly reason: ChangeReason;\n /** Index of the thumb the gesture moved; `null` on a platform path. */\n readonly thumb: number | null;\n}\n\nexport interface SliderRootState<T extends SliderValue = number> {\n /**\n * The value the thumbs show: the value a gesture has reached while a pointer is captured or a\n * step or commit is in flight, else the optimistic value. Content rendered from it must not\n * suspend.\n */\n readonly value: T;\n /** `value` as an array, one entry per thumb, in thumb order. */\n readonly values: readonly number[];\n /** A step or commit dispatched through this Slider is in flight. */\n readonly pending: boolean;\n /** A pointer is captured on a thumb. */\n readonly dragging: boolean;\n readonly orientation: SliderOrientation;\n readonly disabled: boolean;\n readonly min: number;\n readonly max: number;\n readonly step: number;\n}\n\nexport interface SliderRootProps<T extends SliderValue = number> extends Omit<\n ComponentPropsWithRef<\"div\">,\n | \"defaultValue\"\n | \"role\"\n | \"className\"\n | \"style\"\n | \"children\"\n // The value attributes are the native inputs' (design 8): never authored.\n | \"aria-valuemin\"\n | \"aria-valuemax\"\n | \"aria-valuenow\"\n | \"aria-valuetext\"\n | \"aria-orientation\"\n> {\n /** Controlled value: one number, or one per thumb in ascending order. `undefined`: uncontrolled. */\n value?: T;\n /**\n * Initial value in uncontrolled mode; also the form-reset target (latest value). Default: the\n * platform's midpoint, `min + (max - min) / 2`, snapped to `step`.\n */\n defaultValue?: T;\n /**\n * Runs inside the Root's step transition on every step: each pointer move, each key press,\n * each platform change, and the revert after a rejected commit (`reason: \"dismiss\"`,\n * uncontrolled). Awaited; `data-pending` meanwhile (without this action a step starts no\n * transition and is never pending). Adopt the value here in a controlled\n * parent (`setValue(next)` in the sync prefix is a transition update). Not the place for a\n * save: a pending async action entangles every transition in the app, and a drag is many\n * steps. A `setState` after your own `await` needs `startTransition`.\n */\n valueChangeAction?: ChangeAction<T, SliderValueChangeDetails>;\n /**\n * Runs inside the Root's commit transition once per gesture: pointer release, each key press,\n * a form reset, a value found at mount. Awaited; the thumb keeps the gesture's value and shows\n * `data-pending` until it settles; in uncontrolled mode the value is committed when it\n * resolves and reverts to the previous value if it rejects. May be a Server Function.\n */\n valueCommitAction?: ChangeAction<T, SliderValueCommitDetails>;\n /** Default `0`. */\n min?: number;\n /**\n * Default `100`. A `max` that is not on the step grid from `min` is unreachable, as on a\n * native range (dev warning).\n */\n max?: number;\n /** Default `1`. Must be positive. Values snap to `min + n × step`. */\n step?: number;\n /** Minimum number of steps between two adjacent thumbs. Default `0` (thumbs may share a value). */\n minStepsBetweenThumbs?: number;\n /** Default `\"horizontal\"`. Vertical sliders have `min` at the bottom. */\n orientation?: SliderOrientation;\n /**\n * `aria-valuetext` for a thumb, from the value it shows. Set it when the number alone is not\n * meaningful (\"3 of 5 stars\", \"Tuesday\"). Default: none (the number is announced).\n */\n getAriaValueText?: (value: number, index: number) => string;\n /**\n * Form field name for every thumb's input (a Thumb's own `name` wins). With several thumbs,\n * read with `FormData.getAll()`.\n */\n name?: string;\n /** The `form` attribute for every thumb's input (a Thumb's own `form` wins). */\n form?: string;\n /** Disables every input (native `disabled`; not submitted) and the pointer. Never set while pending. */\n disabled?: boolean;\n className?: StateValue<string | undefined, SliderRootState<T>>;\n style?: StateValue<CSSProperties | undefined, SliderRootState<T>>;\n children?: StateValue<ReactNode, SliderRootState<T>>;\n render?: RenderProp<ComponentPropsWithRef<\"div\">, SliderRootState<T>>;\n}\n\nconst isDev = process.env.NODE_ENV !== \"production\";\n\nconst STEP_TYPES = transitionTypes(\"slider\", \"change\");\nconst COMMIT_TYPES = transitionTypes(\"slider\", \"commit\");\n\nfunction toArray(value: SliderValue): readonly number[] {\n return typeof value === \"number\" ? [value] : value;\n}\n\nfunction shapeOf(value: SliderValue | undefined): \"number\" | \"array\" | undefined {\n if (value === undefined) return undefined;\n return typeof value === \"number\" ? \"number\" : \"array\";\n}\n\nfunction replaceAt(values: readonly number[], index: number, value: number): readonly number[] {\n return values.map((v, i) => (i === index ? value : v));\n}\n\n/** Writes each registered input's `defaultValue` (the attribute a form reset restores). */\nfunction writeDefaults(\n registry: ReadonlyMap<number, HTMLInputElement>,\n target: readonly number[],\n): void {\n for (const [index, input] of registry) {\n const entry = target[index];\n if (entry !== undefined) input.defaultValue = String(entry);\n }\n}\n\n/** A pointer captured on a Thumb or the Track (design 4.1). */\ninterface ActiveGesture {\n readonly pointerId: number;\n /** Detaches the gesture's listeners. */\n readonly detach: () => void;\n}\n\n/**\n * Owns the slider's state (design/components/slider.md 2): the committed value through\n * `useControllableAction` with `valueCommitAction` (once per gesture), each step through its own\n * transition (`valueChangeAction`), and the value a gesture has reached in the urgent lane\n * (`live`), which the thumbs show while a pointer is captured or anything is in flight. Also the\n * pointer gesture, the Thumb registry, mount reconciliation and form reset, and the geometry\n * custom properties `--slider-start`, `--slider-end` and `--slider-value-<i>`.\n *\n * Owned keys (conventions 1.2): `role` (`\"group\"` with several thumbs), `aria-labelledby` (the\n * Label's id while a Label is mounted and there are several thumbs; token-merged with the\n * consumer's), `data-pending`, `data-dragging`, `data-orientation`, `data-disabled`. The custom\n * properties are merged into `style`, where the consumer's entries win.\n *\n * Inside a `Field.Root` (design 9.4) the Root calls `useFieldControl`: with one thumb, Thumb 0's\n * input is the Field's labelable control; with several, the Root registers itself as the group\n * and also owns the Field label in `aria-labelledby`, the Field's `aria-describedby` and\n * `data-invalid`. `name` / `disabled` default from the Field.\n */\nfunction SliderRootImpl<T extends SliderValue = number>(props: SliderRootProps<T>) {\n const {\n value,\n defaultValue,\n valueChangeAction,\n valueCommitAction,\n min = 0,\n max = 100,\n step: stepProp = 1,\n minStepsBetweenThumbs = 0,\n orientation = \"horizontal\",\n getAriaValueText,\n name: nameProp,\n form,\n disabled: disabledProp = false,\n className,\n style,\n children,\n render,\n ...rest\n } = props;\n\n const stepValid = Number.isFinite(stepProp) && stepProp > 0;\n const step = stepValid ? stepProp : 1;\n const gap = Math.max(0, minStepsBetweenThumbs) * step;\n\n const id = useId();\n const labelId = `${id}-label`;\n\n // The shape (one number or an array) is fixed at mount (design 3.1).\n const [shape] = useState<\"number\" | \"array\">(() => shapeOf(value ?? defaultValue) ?? \"number\");\n const fromArray = useCallback(\n (values: readonly number[]): T => (shape === \"number\" ? values[0] : values) as T,\n [shape],\n );\n\n // --- State (design 2) ----------------------------------------------------------------------\n\n const [live, setLive] = useState<readonly number[] | null>(null);\n const [gestureThumb, setGestureThumb] = useState<number | null>(null);\n /**\n * A step was taken and its gesture's commit has not been dispatched yet. Holds `live` on\n * screen between a key's native `input` and `change` when no step transition runs (no\n * `valueChangeAction`): otherwise react-dom restores the controlled input to the old value\n * after `input`, and Firefox then fires no `change`.\n */\n const [stepHeld, setStepHeld] = useState(false);\n const [pendingThumb, setPendingThumb] = useState<number | null>(null);\n\n /** The value of the latest step, read by the commit in the same or a later event. */\n const liveRef = useRef<readonly number[] | null>(null);\n /** The shown value when the open gesture began; `null` when no gesture is open. */\n const gestureStart = useRef<readonly number[] | null>(null);\n const activeGesture = useRef<ActiveGesture | null>(null);\n const commitSeq = useRef(0);\n const trackRef = useRef<HTMLElement | null>(null);\n\n const runCommit = async (next: T, details: SliderValueCommitDetails): Promise<void> => {\n const seq = ++commitSeq.current;\n try {\n await valueCommitAction?.(next, details);\n } catch (error) {\n // Design 2.4: in uncontrolled mode, tell the preview channel about the rollback, for the\n // latest commit only. Yield once to leave the commit's transition (conventions 2.6).\n if (value === undefined && seq === commitSeq.current) {\n await undefined;\n // `stepTo` and `committedRef` are declared below; this runs long after the render.\n stepTo(toArray(committedRef.current), null, \"dismiss\", undefined);\n }\n throw error;\n }\n };\n\n const commitState = useControllableAction<T, SliderValueCommitDetails>({\n controlled: value,\n defaultValue,\n initialValue: platformDefault(min, max, step) as T,\n action: runCommit,\n transitionTypes: () => COMMIT_TYPES,\n warn: { component: \"Slider.Root\", prop: \"value\" },\n });\n const { optimistic, committed, dispatch } = commitState;\n const committedRef = useLatest(committed);\n\n const { pending: stepPending, run: runStep } = useActionTrigger();\n\n const optimisticValues = useMemo(() => toArray(optimistic), [optimistic]);\n const held = gestureThumb !== null || stepHeld || stepPending || commitState.pending;\n const shown = held && live !== null ? live : optimisticValues;\n const pending = stepPending || commitState.pending;\n\n // --- Inside a Field.Root (design 9.4) ------------------------------------------------------\n\n // One thumb: its input is the Field's labelable control. Several: the Root (`role=\"group\"`)\n // registers, `Field.Label` drops `for` and names the group through `aria-labelledby`.\n const thumbCount = shown.length;\n const field = useFieldControl({\n labelable: thumbCount === 1,\n name: nameProp,\n disabled: disabledProp,\n component: \"Slider.Root\",\n });\n const fieldName = use(FieldContext)?.name;\n const name = field.name;\n const disabled = field.disabled;\n const fieldId = field.id;\n const thumbId = useCallback(\n (index: number) => (index === 0 && fieldId !== undefined ? fieldId : `${id}-thumb-${index}`),\n [id, fieldId],\n );\n const rootRef = useMergedRef<HTMLElement>(undefined, thumbCount > 1 ? field.ref : undefined);\n useDevWarning(\n field.inField && field.required,\n \"Slider.Root: a range is never empty, so `required` on the enclosing Field.Root has no \" +\n \"effect on the slider.\",\n );\n /**\n * The reason of the latest change the user or the platform made, consumed by the Field\n * notification below: `\"activate\"` dismisses a shown server error, a rollback does not.\n */\n const lastReason = useRef<ChangeReason | null>(null);\n // A pointer gesture and the JS-normalised keys fire no `input` / `change` the Field hears:\n // tell it at the commit, when the optimistic value changes (design 9.4.4).\n useFieldValueChange(optimisticValues.join(\"\\u0000\"), () => {\n const edit = lastReason.current === \"activate\";\n lastReason.current = null;\n return edit;\n });\n const {\n \"aria-labelledby\": fieldLabelledBy,\n \"aria-describedby\": fieldDescribedBy,\n \"aria-invalid\": fieldInvalid,\n \"data-invalid\": fieldDataInvalid,\n } = field.attributes;\n const inField = field.inField;\n const fieldRef = field.ref;\n const fieldWiring = useMemo<SliderFieldWiring | null>(() => {\n if (!inField) return null;\n const single = thumbCount === 1;\n return {\n inputRef: single ? fieldRef : undefined,\n describedBy: single ? fieldDescribedBy : undefined,\n invalid: fieldInvalid,\n dataInvalid: fieldDataInvalid,\n name: fieldName,\n };\n }, [inField, fieldRef, thumbCount, fieldDescribedBy, fieldInvalid, fieldDataInvalid, fieldName]);\n\n /** What the thumbs show, for handlers; also written by `stepTo` ahead of the render. */\n const shownRef = useLatest(shown);\n\n const latest = useLatest({\n valueChangeAction,\n fromArray,\n runStep,\n min,\n max,\n step,\n gap,\n orientation,\n disabled,\n });\n\n // --- Step and commit (design 2.4) ---------------------------------------------------------\n\n const stepTo = useCallback(\n (\n next: readonly number[],\n thumb: number | null,\n reason: ChangeReason,\n event: Event | undefined,\n ): boolean => {\n // No-op against what the user sees (conventions 2.3 item 8).\n if (equalValues(next, shownRef.current)) return false;\n liveRef.current = next;\n shownRef.current = next;\n // A controlled parent that adopts steps changes the optimistic value per step.\n lastReason.current = reason;\n setLive(next);\n setPendingThumb(thumb);\n // A revert has no commit after it: the optimistic value already shows the committed one.\n if (reason !== \"dismiss\") setStepHeld(true);\n const { valueChangeAction: action, fromArray: toValue, runStep: run } = latest.current;\n // Without a step action there is nothing to run and no consumer update to keep\n // interruptible: no transition, so `data-pending` does not blink on every pointer move.\n if (action === undefined) return true;\n run(() => {\n for (const type of STEP_TYPES) addTransitionType(type);\n return action?.(toValue(next), createActionDetails(event, { reason, thumb }));\n });\n return true;\n },\n [latest, shownRef],\n );\n\n const commitGesture = useCallback(\n (thumb: number | null, reason: ChangeReason, event: Event | undefined): void => {\n const start = gestureStart.current;\n gestureStart.current = null;\n // The commit's own pending state holds `live` from here (set in this same batch).\n setStepHeld(false);\n const next = liveRef.current;\n // Nothing changed since the gesture began (a drag out and back, a trailing `change`).\n if (start === null || next === null || equalValues(next, start)) return;\n lastReason.current = reason;\n setPendingThumb(thumb);\n dispatch(latest.current.fromArray(next), createActionDetails(event, { reason, thumb }));\n },\n [dispatch, latest],\n );\n\n // --- Thumb registry ------------------------------------------------------------------------\n\n const [registry] = useState(() => new Map<number, HTMLInputElement>());\n const warnedDuplicate = useRef(false);\n const warnedForm = useRef(false);\n const registerThumb = useCallback(\n (index: number, input: HTMLInputElement) => {\n const existing = registry.get(index);\n if (isDev && existing !== undefined && existing !== input && !warnedDuplicate.current) {\n warnedDuplicate.current = true;\n console.error(\n `Slider.Thumb: two Thumbs have \\`index={${index}}\\`. Each value needs exactly one ` +\n `Thumb; give every Thumb a distinct index.`,\n );\n }\n if (isDev && !warnedForm.current) {\n for (const other of registry.values()) {\n if (other !== input && other.form !== input.form) {\n warnedForm.current = true;\n console.error(\n \"Slider.Thumb: the thumbs of one Slider belong to different forms (a Thumb's \" +\n \"`form` prop). A form reset is followed through the first thumb's form only; \" +\n \"keep every thumb in one form.\",\n );\n break;\n }\n }\n }\n registry.set(index, input);\n return () => {\n if (registry.get(index) === input) registry.delete(index);\n };\n },\n [registry],\n );\n\n /** The first registered input: the form-associated element the reset subscription follows. */\n const formElement = useMemo<RefObject<FormAssociatedElement | null>>(\n () => ({\n get current() {\n let first: HTMLInputElement | null = null;\n let firstIndex = Number.POSITIVE_INFINITY;\n for (const [index, input] of registry) {\n if (index < firstIndex) {\n firstIndex = index;\n first = input;\n }\n }\n return first;\n },\n set current(_ignored) {},\n }),\n [registry],\n );\n\n // --- Labels --------------------------------------------------------------------------------\n\n const [labelCount, setLabelCount] = useState(0);\n // The same count for the dev warning, which can run before the re-render the registration\n // scheduled.\n const labelCountRef = useRef(0);\n const registerLabel = useCallback(() => {\n labelCountRef.current += 1;\n setLabelCount((count) => count + 1);\n return () => {\n labelCountRef.current -= 1;\n setLabelCount((count) => count - 1);\n };\n }, []);\n\n // --- Residual browser paths: mount reconciliation and form reset (design 9.2, 9.3) --------\n\n const [mountValue] = useState(value);\n const resetTarget = (): readonly number[] =>\n value !== undefined\n ? toArray(mountValue ?? value)\n : toArray(defaultValue ?? platformDefault(min, max, step));\n\n const readCurrent = (): readonly number[] =>\n shownRef.current.map((v, index) => {\n const input = registry.get(index);\n if (input === undefined) return v;\n const read = Number(input.value);\n return Number.isFinite(read) ? read : v;\n });\n\n const { onItemMounted } = useNativeGroupReconciliation<readonly number[]>({\n element: formElement,\n readCurrent,\n readDefault: resetTarget,\n base: () => shownRef.current,\n // Compare as the DOM would hold the values: a consumer's off-grid value is sanitised by the\n // browser (not by jsdom), and that is not a platform change.\n equals: (a, b) => {\n const reference = shownRef.current;\n return equalValues(\n sanitize(a, reference, min, max, step, gap),\n sanitize(b, reference, min, max, step, gap),\n );\n },\n onPlatformChange: (next, event) => {\n if (next.length !== shownRef.current.length) return;\n const before = shownRef.current;\n gestureStart.current = before;\n liveRef.current = before;\n stepTo(next, null, \"platform\", event);\n commitGesture(null, \"platform\", event);\n },\n onResetEvent: () => {\n // react-dom writes `defaultValue = value` after every update of a controlled input, so the\n // reset target is written here, right before the browser's reset algorithm reads it.\n writeDefaults(registry, resetTarget());\n },\n });\n\n // --- Keyboard (design 4.2) -----------------------------------------------------------------\n\n const inputStep = useCallback(\n (index: number, raw: number, event: Event) => {\n if (!Number.isFinite(raw)) return;\n const before = shownRef.current;\n if (index >= before.length) return;\n // A key press is a one-step gesture: it starts at the value shown before it.\n if (stepTo(replaceAt(before, index, raw), index, \"activate\", event)) {\n if (gestureStart.current === null) gestureStart.current = before;\n }\n },\n [shownRef, stepTo],\n );\n\n const inputCommit = useCallback(\n (index: number, event: Event) => {\n // A pointer gesture commits at its release.\n if (activeGesture.current !== null) return;\n commitGesture(index, \"activate\", event);\n },\n [commitGesture],\n );\n\n const inputKeyDown = useCallback(\n (index: number, event: KeyboardEvent) => {\n const {\n orientation: axis,\n disabled: off,\n min: lo,\n max: hi,\n step: inc,\n gap: g,\n } = latest.current;\n if (off) return;\n if (event.key !== \"ArrowLeft\" && event.key !== \"ArrowRight\") return;\n if (event.altKey || event.ctrlKey || event.metaKey) return;\n // Vertical: Firefox decreases a vertical range on ArrowRight; the APG says increase.\n // Horizontal RTL: the track is mirrored (min on the right), so ArrowLeft increases;\n // Chromium and Firefox mirror a native range, WebKit does not (design 7). LTR stays native.\n let increaseKey: \"ArrowLeft\" | \"ArrowRight\";\n if (axis === \"vertical\") {\n increaseKey = \"ArrowRight\";\n } else {\n // Read at the keydown: the direction may come from any ancestor and change at any time.\n const input = event.currentTarget as Element | null;\n if (input === null || getComputedStyle(input).direction !== \"rtl\") return;\n increaseKey = \"ArrowLeft\";\n }\n event.preventDefault();\n const before = shownRef.current;\n const current = before[index];\n if (current === undefined) return;\n const delta = event.key === increaseKey ? inc : -inc;\n const next = replaceAt(\n before,\n index,\n clampToNeighbours(before, index, current + delta, lo, hi, inc, g),\n );\n if (activeGesture.current !== null) {\n stepTo(next, index, \"activate\", event);\n return;\n }\n gestureStart.current = before;\n liveRef.current = before;\n stepTo(next, index, \"activate\", event);\n commitGesture(index, \"activate\", event);\n },\n [commitGesture, latest, shownRef, stepTo],\n );\n\n // --- Pointer (design 4.1) ------------------------------------------------------------------\n\n const warnedNoTrack = useRef(false);\n const beginGesture = useCallback(\n (index: number | null, event: PointerEvent, element: HTMLElement) => {\n const { disabled: off } = latest.current;\n if (off || event.button !== 0 || activeGesture.current !== null) return;\n const track = trackRef.current;\n if (track === null) {\n if (isDev && !warnedNoTrack.current) {\n warnedNoTrack.current = true;\n console.error(\n \"Slider.Thumb: a pointer press needs a Slider.Track to map the pointer to a value. \" +\n \"Without a Track the slider is keyboard-only.\",\n );\n }\n return;\n }\n // No text selection, no focus change through the compatibility `mousedown`.\n event.preventDefault();\n const rtl = getComputedStyle(track).direction === \"rtl\";\n\n const valueAt = (clientX: number, clientY: number): number => {\n const { min: lo, max: hi, orientation: axis } = latest.current;\n const rect = (trackRef.current ?? track).getBoundingClientRect();\n let fraction: number;\n if (axis === \"vertical\") {\n fraction = rect.height > 0 ? (rect.bottom - clientY) / rect.height : 0;\n } else {\n fraction = rect.width > 0 ? (clientX - rect.left) / rect.width : 0;\n if (rtl) fraction = 1 - fraction;\n }\n fraction = Math.min(1, Math.max(0, fraction));\n return lo + fraction * (hi - lo);\n };\n const moveTo = (thumb: number, raw: number, cause: Event): void => {\n const { min: lo, max: hi, step: inc, gap: g } = latest.current;\n const before = shownRef.current;\n if (thumb >= before.length) return;\n stepTo(\n replaceAt(before, thumb, clampToNeighbours(before, thumb, raw, lo, hi, inc, g)),\n thumb,\n \"activate\",\n cause,\n );\n };\n\n const start = valueAt(event.clientX, event.clientY);\n const startValues = shownRef.current;\n // A press on a Thumb that shares its value with a neighbour (stacked thumbs) moves the one\n // that can go toward the pointer, the Track's tie rule; when the press is exactly on the\n // value, the first move decides. Otherwise a Thumb press moves that Thumb.\n let tied: { readonly first: number; readonly last: number; readonly at: number } | null =\n null;\n if (index !== null) {\n const at = startValues[index];\n if (at !== undefined) {\n let first = index;\n let last = index;\n while (first > 0 && equalValues([startValues[first - 1] as number], [at])) first -= 1;\n while (\n last < startValues.length - 1 &&\n equalValues([startValues[last + 1] as number], [at])\n ) {\n last += 1;\n }\n if (first !== last) tied = { first, last, at };\n }\n }\n const resolveTie = (raw: number): number | null => {\n if (tied === null) return null;\n if (raw > tied.at) return tied.last;\n if (raw < tied.at) return tied.first;\n return null;\n };\n /** The thumb the gesture moves; `null` while a press on stacked thumbs is undecided. */\n let decided: number | null =\n index === null ? nearestThumb(startValues, start) : tied ? resolveTie(start) : index;\n /** The thumb shown as dragging and focused meanwhile. */\n let thumb = decided ?? index ?? 0;\n const pointerId = event.pointerId;\n try {\n element.setPointerCapture(pointerId);\n } catch {\n // An inactive pointer id (a synthetic event): the gesture still follows the element.\n }\n\n const decide = (raw: number): boolean => {\n if (decided !== null) return true;\n decided = resolveTie(raw);\n if (decided === null) return false;\n if (decided !== thumb) {\n thumb = decided;\n setGestureThumb(thumb);\n registry.get(thumb)?.focus({ focusVisible: false } as FocusOptions);\n }\n return true;\n };\n const follow = (pointerEvent: PointerEvent): void => {\n const raw = valueAt(pointerEvent.clientX, pointerEvent.clientY);\n if (decide(raw)) moveTo(thumb, raw, pointerEvent);\n };\n\n const onMove = (moveEvent: PointerEvent): void => {\n if (moveEvent.pointerId !== pointerId) return;\n follow(moveEvent);\n };\n const onEnd = (endEvent: PointerEvent): void => {\n if (endEvent.pointerId !== pointerId) return;\n detach();\n // The release position is the gesture's last (an engine may coalesce the final move\n // into the `pointerup`); a cancel or a lost capture keeps the last move's value.\n if (endEvent.type === \"pointerup\") follow(endEvent);\n activeGesture.current = null;\n setGestureThumb(null);\n commitGesture(thumb, \"activate\", endEvent);\n };\n const detach = (): void => {\n element.removeEventListener(\"pointermove\", onMove);\n element.removeEventListener(\"pointerup\", onEnd);\n element.removeEventListener(\"pointercancel\", onEnd);\n element.removeEventListener(\"lostpointercapture\", onEnd);\n };\n element.addEventListener(\"pointermove\", onMove);\n element.addEventListener(\"pointerup\", onEnd);\n element.addEventListener(\"pointercancel\", onEnd);\n element.addEventListener(\"lostpointercapture\", onEnd);\n\n activeGesture.current = { pointerId, detach };\n setGestureThumb(thumb);\n gestureStart.current = shownRef.current;\n liveRef.current = shownRef.current;\n // A capture alone holds `live` on screen: start it from what is shown, not from the value\n // an earlier gesture left behind (a press exactly on the current value steps nothing).\n setLive(shownRef.current);\n // `:focus-visible` does not match after a pointer press, as on a native range.\n registry.get(thumb)?.focus({ focusVisible: false } as FocusOptions);\n if (decided !== null) moveTo(thumb, start, event);\n },\n [commitGesture, latest, registry, shownRef, stepTo],\n );\n\n // An unmount mid-gesture leaves no listener behind.\n useEffect(\n () => () => {\n activeGesture.current?.detach();\n activeGesture.current = null;\n },\n [],\n );\n\n // --- Development warnings ------------------------------------------------------------------\n\n useDevWarning(\n !stepValid,\n `Slider.Root: \\`step\\` must be a positive number (got ${String(stepProp)}); using 1.`,\n );\n useDevWarning(\n stepValid && !isMaxReachable(min, max, step),\n `Slider.Root: \\`max\\` (${max}) is not on the step grid from \\`min\\` (${min}) with \\`step\\` ` +\n `${step}: it is unreachable, as on a native range. The last reachable value is the last ` +\n `step below \\`max\\`.`,\n );\n const given = value ?? defaultValue;\n const givenValues = given === undefined ? [] : toArray(given);\n useDevWarning(\n givenValues.some((v) => !isOnGrid(v, min, max, step)),\n `Slider.Root: the ${value !== undefined ? \"`value`\" : \"`defaultValue`\"} ` +\n `(${givenValues.join(\", \")}) is off the step grid or outside \\`min\\` / \\`max\\`. It is ` +\n `rendered as given and the browser sanitises it; the first user step snaps it.`,\n );\n useDevWarning(\n givenValues.some((v, i) => i > 0 && v < (givenValues[i - 1] as number)),\n `Slider.Root: the values (${givenValues.join(\", \")}) must be in ascending order; the thumbs ` +\n `would be rendered crossed.`,\n );\n const currentShape = shapeOf(given);\n useDevWarning(\n currentShape !== undefined && currentShape !== shape,\n `Slider.Root: the value changed shape between a number and an array after mount. The shape ` +\n `is fixed at mount; remount the Slider (a \\`key\\`) to change the number of thumbs.`,\n );\n // Inside a Field, `Field.Label` names the group (design 9.4.2).\n const unnamedGroup =\n shown.length > 1 &&\n !inField &&\n rest[\"aria-label\"] === undefined &&\n rest[\"aria-labelledby\"] === undefined;\n const warnedGroupName = useRef(false);\n useEffect(() => {\n if (!isDev || warnedGroupName.current || !unnamedGroup || labelCountRef.current > 0) return;\n warnedGroupName.current = true;\n console.error(\n \"Slider.Root: a slider with several thumbs is a `group` and needs a name: render a \" +\n \"Slider.Label, or pass `aria-label` / `aria-labelledby` to the Root.\",\n );\n }, [unnamedGroup]);\n\n // --- Render --------------------------------------------------------------------------------\n\n const count = shown.length;\n const percents = shown.map((v) => percent(v, min, max));\n const geometry: Record<string, string> = {\n \"--slider-start\": count > 1 ? `${percents[0] ?? 0}%` : \"0%\",\n \"--slider-end\": `${percents[count - 1] ?? 0}%`,\n };\n percents.forEach((p, index) => {\n geometry[`--slider-value-${index}`] = `${p}%`;\n });\n\n const shownValue = fromArray(shown);\n const dragging = gestureThumb !== null;\n const state = useMemo<SliderRootState<T>>(\n () => ({\n value: shownValue,\n values: shown,\n pending,\n dragging,\n orientation,\n disabled,\n min,\n max,\n step,\n }),\n [shownValue, shown, pending, dragging, orientation, disabled, min, max, step],\n );\n\n // Memoised (#48): the functions are stable, so this changes only with the state below.\n const context = useMemo<SliderContextValue>(\n () => ({\n state: state as SliderRootState<SliderValue>,\n shown,\n shownValue: shownValue as SliderValue,\n min,\n max,\n step,\n gap,\n orientation,\n disabled,\n pending,\n draggingThumb: gestureThumb,\n pendingThumb,\n name,\n form,\n getAriaValueText,\n labelId,\n thumbId,\n trackRef,\n inputStep,\n inputCommit,\n inputKeyDown,\n beginGesture,\n registerThumb,\n registerLabel,\n onItemMounted,\n field: fieldWiring,\n }),\n [\n state,\n shown,\n shownValue,\n min,\n max,\n step,\n gap,\n orientation,\n disabled,\n pending,\n gestureThumb,\n pendingThumb,\n name,\n form,\n getAriaValueText,\n labelId,\n thumbId,\n inputStep,\n inputCommit,\n inputKeyDown,\n beginGesture,\n registerThumb,\n registerLabel,\n onItemMounted,\n fieldWiring,\n ],\n );\n\n // Several thumbs: the Field's label, then `Slider.Label` while one is mounted (the consumer's\n // tokens come first through the merge). Only when there is one: an owned `undefined` would\n // remove the consumer's own tokens.\n const labelledBy =\n count > 1 ? mergeTokenLists(fieldLabelledBy, labelCount > 0 ? labelId : undefined) : \"\";\n const libraryProps: Partial<ComponentPropsWithRef<\"div\">> & DataAttributes = {\n role: count > 1 ? \"group\" : undefined,\n ...(labelledBy !== \"\" ? { \"aria-labelledby\": labelledBy } : {}),\n // The group element is described (read when focus enters it); one thumb: its input is.\n ...(count > 1 && fieldDescribedBy !== undefined\n ? { \"aria-describedby\": fieldDescribedBy }\n : {}),\n // Inside a Field only (`aria-invalid` goes on the inputs, never on the group).\n ...(inField ? { \"data-invalid\": fieldDataInvalid } : {}),\n \"data-pending\": dataAttr(pending),\n \"data-dragging\": dataAttr(dragging),\n \"data-orientation\": orientation,\n \"data-disabled\": dataAttr(disabled),\n };\n\n const element = useRender<ComponentPropsWithRef<\"div\">, SliderRootState<T>>({\n defaultElement: \"div\",\n render,\n state,\n className,\n // The geometry properties lose to the consumer's own entries (design 3.1).\n style: (s) => ({ ...(geometry as CSSProperties), ...resolveStateValue(style, s) }),\n children,\n props: rest,\n libraryProps,\n ref: rootRef,\n });\n\n return <SliderContext value={context}>{element}</SliderContext>;\n}\n\nSliderRootImpl.displayName = \"SliderRoot\";\n\n/**\n * `Slider.Root`. Overloaded so that the value's shape is inferred from `value` / `defaultValue`\n * as `number` or `readonly number[]` (an array literal would otherwise infer a mutable\n * `number[]`), and every action and state function receives that shape (design 3.1).\n */\nexport const SliderRoot = SliderRootImpl as {\n (props: SliderRootProps<number>): ReactNode;\n (props: SliderRootProps<readonly number[]>): ReactNode;\n (props: SliderRootProps<SliderValue>): ReactNode;\n displayName?: string;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA+KA,MAAM,QAAQ,QAAQ,IAAI,aAAa;AAEvC,MAAM,aAAa,gBAAgB,UAAU,QAAQ;AACrD,MAAM,eAAe,gBAAgB,UAAU,QAAQ;AAEvD,SAAS,QAAQ,OAAuC;CACtD,OAAO,OAAO,UAAU,WAAW,CAAC,KAAK,IAAI;AAC/C;AAEA,SAAS,QAAQ,OAAgE;CAC/E,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAChC,OAAO,OAAO,UAAU,WAAW,WAAW;AAChD;AAEA,SAAS,UAAU,QAA2B,OAAe,OAAkC;CAC7F,OAAO,OAAO,KAAK,GAAG,MAAO,MAAM,QAAQ,QAAQ,CAAE;AACvD;;AAGA,SAAS,cACP,UACA,QACM;CACN,KAAK,MAAM,CAAC,OAAO,UAAU,UAAU;EACrC,MAAM,QAAQ,OAAO;EACrB,IAAI,UAAU,KAAA,GAAW,MAAM,eAAe,OAAO,KAAK;CAC5D;AACF;;;;;;;;;;;;;;;;;;;AA2BA,SAAS,eAA+C,OAA2B;CACjF,MAAM,EACJ,OACA,cACA,mBACA,mBACA,MAAM,GACN,MAAM,KACN,MAAM,WAAW,GACjB,wBAAwB,GACxB,cAAc,cACd,kBACA,MAAM,UACN,MACA,UAAU,eAAe,OACzB,WACA,OACA,UACA,QACA,GAAG,SACD;CAEJ,MAAM,YAAY,OAAO,SAAS,QAAQ,KAAK,WAAW;CAC1D,MAAM,OAAO,YAAY,WAAW;CACpC,MAAM,MAAM,KAAK,IAAI,GAAG,qBAAqB,IAAI;CAEjD,MAAM,KAAK,MAAM;CACjB,MAAM,UAAU,GAAG,GAAG;CAGtB,MAAM,CAAC,SAAS,eAAmC,QAAQ,SAAS,YAAY,KAAK,QAAQ;CAC7F,MAAM,YAAY,aACf,WAAkC,UAAU,WAAW,OAAO,KAAK,QACpE,CAAC,KAAK,CACR;CAIA,MAAM,CAAC,MAAM,WAAW,SAAmC,IAAI;CAC/D,MAAM,CAAC,cAAc,mBAAmB,SAAwB,IAAI;;;;;;;CAOpE,MAAM,CAAC,UAAU,eAAe,SAAS,KAAK;CAC9C,MAAM,CAAC,cAAc,mBAAmB,SAAwB,IAAI;;CAGpE,MAAM,UAAU,OAAiC,IAAI;;CAErD,MAAM,eAAe,OAAiC,IAAI;CAC1D,MAAM,gBAAgB,OAA6B,IAAI;CACvD,MAAM,YAAY,OAAO,CAAC;CAC1B,MAAM,WAAW,OAA2B,IAAI;CAEhD,MAAM,YAAY,OAAO,MAAS,YAAqD;EACrF,MAAM,MAAM,EAAE,UAAU;EACxB,IAAI;GACF,MAAM,oBAAoB,MAAM,OAAO;EACzC,SAAS,OAAO;GAGd,IAAI,UAAU,KAAA,KAAa,QAAQ,UAAU,SAAS;IACpD,MAAM,KAAA;IAEN,OAAO,QAAQ,aAAa,OAAO,GAAG,MAAM,WAAW,KAAA,CAAS;GAClE;GACA,MAAM;EACR;CACF;CAEA,MAAM,cAAc,sBAAmD;EACrE,YAAY;EACZ;EACA,cAAc,gBAAgB,KAAK,KAAK,IAAI;EAC5C,QAAQ;EACR,uBAAuB;EACvB,MAAM;GAAE,WAAW;GAAe,MAAM;EAAQ;CAClD,CAAC;CACD,MAAM,EAAE,YAAY,WAAW,aAAa;CAC5C,MAAM,eAAe,UAAU,SAAS;CAExC,MAAM,EAAE,SAAS,aAAa,KAAK,YAAY,iBAAiB;CAEhE,MAAM,mBAAmB,cAAc,QAAQ,UAAU,GAAG,CAAC,UAAU,CAAC;CAExE,MAAM,SADO,iBAAiB,QAAQ,YAAY,eAAe,YAAY,YACvD,SAAS,OAAO,OAAO;CAC7C,MAAM,UAAU,eAAe,YAAY;CAM3C,MAAM,aAAa,MAAM;CACzB,MAAM,QAAQ,gBAAgB;EAC5B,WAAW,eAAe;EAC1B,MAAM;EACN,UAAU;EACV,WAAW;CACb,CAAC;CACD,MAAM,YAAY,IAAI,YAAY,CAAC,EAAE;CACrC,MAAM,OAAO,MAAM;CACnB,MAAM,WAAW,MAAM;CACvB,MAAM,UAAU,MAAM;CACtB,MAAM,UAAU,aACb,UAAmB,UAAU,KAAK,YAAY,KAAA,IAAY,UAAU,GAAG,GAAG,SAAS,SACpF,CAAC,IAAI,OAAO,CACd;CACA,MAAM,UAAU,aAA0B,KAAA,GAAW,aAAa,IAAI,MAAM,MAAM,KAAA,CAAS;CAC3F,cACE,MAAM,WAAW,MAAM,UACvB,6GAEF;;;;;CAKA,MAAM,aAAa,OAA4B,IAAI;CAGnD,oBAAoB,iBAAiB,KAAK,IAAQ,SAAS;EACzD,MAAM,OAAO,WAAW,YAAY;EACpC,WAAW,UAAU;EACrB,OAAO;CACT,CAAC;CACD,MAAM,EACJ,mBAAmB,iBACnB,oBAAoB,kBACpB,gBAAgB,cAChB,gBAAgB,qBACd,MAAM;CACV,MAAM,UAAU,MAAM;CACtB,MAAM,WAAW,MAAM;CACvB,MAAM,cAAc,cAAwC;EAC1D,IAAI,CAAC,SAAS,OAAO;EACrB,MAAM,SAAS,eAAe;EAC9B,OAAO;GACL,UAAU,SAAS,WAAW,KAAA;GAC9B,aAAa,SAAS,mBAAmB,KAAA;GACzC,SAAS;GACT,aAAa;GACb,MAAM;EACR;CACF,GAAG;EAAC;EAAS;EAAU;EAAY;EAAkB;EAAc;EAAkB;CAAS,CAAC;;CAG/F,MAAM,WAAW,UAAU,KAAK;CAEhC,MAAM,SAAS,UAAU;EACvB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAID,MAAM,SAAS,aAEX,MACA,OACA,QACA,UACY;EAEZ,IAAI,YAAY,MAAM,SAAS,OAAO,GAAG,OAAO;EAChD,QAAQ,UAAU;EAClB,SAAS,UAAU;EAEnB,WAAW,UAAU;EACrB,QAAQ,IAAI;EACZ,gBAAgB,KAAK;EAErB,IAAI,WAAW,WAAW,YAAY,IAAI;EAC1C,MAAM,EAAE,mBAAmB,QAAQ,WAAW,SAAS,SAAS,QAAQ,OAAO;EAG/E,IAAI,WAAW,KAAA,GAAW,OAAO;EACjC,UAAU;GACR,KAAK,MAAM,QAAQ,YAAY,kBAAkB,IAAI;GACrD,OAAO,SAAS,QAAQ,IAAI,GAAG,oBAAoB,OAAO;IAAE;IAAQ;GAAM,CAAC,CAAC;EAC9E,CAAC;EACD,OAAO;CACT,GACA,CAAC,QAAQ,QAAQ,CACnB;CAEA,MAAM,gBAAgB,aACnB,OAAsB,QAAsB,UAAmC;EAC9E,MAAM,QAAQ,aAAa;EAC3B,aAAa,UAAU;EAEvB,YAAY,KAAK;EACjB,MAAM,OAAO,QAAQ;EAErB,IAAI,UAAU,QAAQ,SAAS,QAAQ,YAAY,MAAM,KAAK,GAAG;EACjE,WAAW,UAAU;EACrB,gBAAgB,KAAK;EACrB,SAAS,OAAO,QAAQ,UAAU,IAAI,GAAG,oBAAoB,OAAO;GAAE;GAAQ;EAAM,CAAC,CAAC;CACxF,GACA,CAAC,UAAU,MAAM,CACnB;CAIA,MAAM,CAAC,YAAY,+BAAe,IAAI,IAA8B,CAAC;CACrE,MAAM,kBAAkB,OAAO,KAAK;CACpC,MAAM,aAAa,OAAO,KAAK;CAC/B,MAAM,gBAAgB,aACnB,OAAe,UAA4B;EAC1C,MAAM,WAAW,SAAS,IAAI,KAAK;EACnC,IAAI,SAAS,aAAa,KAAA,KAAa,aAAa,SAAS,CAAC,gBAAgB,SAAS;GACrF,gBAAgB,UAAU;GAC1B,QAAQ,MACN,0CAA0C,MAAM,4EAElD;EACF;EACA,IAAI,SAAS,CAAC,WAAW,SAClB;QAAA,MAAM,SAAS,SAAS,OAAO,GAClC,IAAI,UAAU,SAAS,MAAM,SAAS,MAAM,MAAM;IAChD,WAAW,UAAU;IACrB,QAAQ,MACN,uLAGF;IACA;GACF;;EAGJ,SAAS,IAAI,OAAO,KAAK;EACzB,aAAa;GACX,IAAI,SAAS,IAAI,KAAK,MAAM,OAAO,SAAS,OAAO,KAAK;EAC1D;CACF,GACA,CAAC,QAAQ,CACX;;CAGA,MAAM,cAAc,eACX;EACL,IAAI,UAAU;GACZ,IAAI,QAAiC;GACrC,IAAI,aAAa,OAAO;GACxB,KAAK,MAAM,CAAC,OAAO,UAAU,UAC3B,IAAI,QAAQ,YAAY;IACtB,aAAa;IACb,QAAQ;GACV;GAEF,OAAO;EACT;EACA,IAAI,QAAQ,UAAU,CAAC;CACzB,IACA,CAAC,QAAQ,CACX;CAIA,MAAM,CAAC,YAAY,iBAAiB,SAAS,CAAC;CAG9C,MAAM,gBAAgB,OAAO,CAAC;CAC9B,MAAM,gBAAgB,kBAAkB;EACtC,cAAc,WAAW;EACzB,eAAe,UAAU,QAAQ,CAAC;EAClC,aAAa;GACX,cAAc,WAAW;GACzB,eAAe,UAAU,QAAQ,CAAC;EACpC;CACF,GAAG,CAAC,CAAC;CAIL,MAAM,CAAC,cAAc,SAAS,KAAK;CACnC,MAAM,oBACJ,UAAU,KAAA,IACN,QAAQ,cAAc,KAAK,IAC3B,QAAQ,gBAAgB,gBAAgB,KAAK,KAAK,IAAI,CAAC;CAE7D,MAAM,oBACJ,SAAS,QAAQ,KAAK,GAAG,UAAU;EACjC,MAAM,QAAQ,SAAS,IAAI,KAAK;EAChC,IAAI,UAAU,KAAA,GAAW,OAAO;EAChC,MAAM,OAAO,OAAO,MAAM,KAAK;EAC/B,OAAO,OAAO,SAAS,IAAI,IAAI,OAAO;CACxC,CAAC;CAEH,MAAM,EAAE,kBAAkB,6BAAgD;EACxE,SAAS;EACT;EACA,aAAa;EACb,YAAY,SAAS;EAGrB,SAAS,GAAG,MAAM;GAChB,MAAM,YAAY,SAAS;GAC3B,OAAO,YACL,SAAS,GAAG,WAAW,KAAK,KAAK,MAAM,GAAG,GAC1C,SAAS,GAAG,WAAW,KAAK,KAAK,MAAM,GAAG,CAC5C;EACF;EACA,mBAAmB,MAAM,UAAU;GACjC,IAAI,KAAK,WAAW,SAAS,QAAQ,QAAQ;GAC7C,MAAM,SAAS,SAAS;GACxB,aAAa,UAAU;GACvB,QAAQ,UAAU;GAClB,OAAO,MAAM,MAAM,YAAY,KAAK;GACpC,cAAc,MAAM,YAAY,KAAK;EACvC;EACA,oBAAoB;GAGlB,cAAc,UAAU,YAAY,CAAC;EACvC;CACF,CAAC;CAID,MAAM,YAAY,aACf,OAAe,KAAa,UAAiB;EAC5C,IAAI,CAAC,OAAO,SAAS,GAAG,GAAG;EAC3B,MAAM,SAAS,SAAS;EACxB,IAAI,SAAS,OAAO,QAAQ;EAE5B,IAAI,OAAO,UAAU,QAAQ,OAAO,GAAG,GAAG,OAAO,YAAY,KAAK,GAC5D;OAAA,aAAa,YAAY,MAAM,aAAa,UAAU;EAAA;CAE9D,GACA,CAAC,UAAU,MAAM,CACnB;CAEA,MAAM,cAAc,aACjB,OAAe,UAAiB;EAE/B,IAAI,cAAc,YAAY,MAAM;EACpC,cAAc,OAAO,YAAY,KAAK;CACxC,GACA,CAAC,aAAa,CAChB;CAEA,MAAM,eAAe,aAClB,OAAe,UAAyB;EACvC,MAAM,EACJ,aAAa,MACb,UAAU,KACV,KAAK,IACL,KAAK,IACL,MAAM,KACN,KAAK,MACH,OAAO;EACX,IAAI,KAAK;EACT,IAAI,MAAM,QAAQ,eAAe,MAAM,QAAQ,cAAc;EAC7D,IAAI,MAAM,UAAU,MAAM,WAAW,MAAM,SAAS;EAIpD,IAAI;EACJ,IAAI,SAAS,YACX,cAAc;OACT;GAEL,MAAM,QAAQ,MAAM;GACpB,IAAI,UAAU,QAAQ,iBAAiB,KAAK,CAAC,CAAC,cAAc,OAAO;GACnE,cAAc;EAChB;EACA,MAAM,eAAe;EACrB,MAAM,SAAS,SAAS;EACxB,MAAM,UAAU,OAAO;EACvB,IAAI,YAAY,KAAA,GAAW;EAC3B,MAAM,QAAQ,MAAM,QAAQ,cAAc,MAAM,CAAC;EACjD,MAAM,OAAO,UACX,QACA,OACA,kBAAkB,QAAQ,OAAO,UAAU,OAAO,IAAI,IAAI,KAAK,CAAC,CAClE;EACA,IAAI,cAAc,YAAY,MAAM;GAClC,OAAO,MAAM,OAAO,YAAY,KAAK;GACrC;EACF;EACA,aAAa,UAAU;EACvB,QAAQ,UAAU;EAClB,OAAO,MAAM,OAAO,YAAY,KAAK;EACrC,cAAc,OAAO,YAAY,KAAK;CACxC,GACA;EAAC;EAAe;EAAQ;EAAU;CAAM,CAC1C;CAIA,MAAM,gBAAgB,OAAO,KAAK;CAClC,MAAM,eAAe,aAClB,OAAsB,OAAqB,YAAyB;EACnE,MAAM,EAAE,UAAU,QAAQ,OAAO;EACjC,IAAI,OAAO,MAAM,WAAW,KAAK,cAAc,YAAY,MAAM;EACjE,MAAM,QAAQ,SAAS;EACvB,IAAI,UAAU,MAAM;GAClB,IAAI,SAAS,CAAC,cAAc,SAAS;IACnC,cAAc,UAAU;IACxB,QAAQ,MACN,gIAEF;GACF;GACA;EACF;EAEA,MAAM,eAAe;EACrB,MAAM,MAAM,iBAAiB,KAAK,CAAC,CAAC,cAAc;EAElD,MAAM,WAAW,SAAiB,YAA4B;GAC5D,MAAM,EAAE,KAAK,IAAI,KAAK,IAAI,aAAa,SAAS,OAAO;GACvD,MAAM,QAAQ,SAAS,WAAW,MAAA,CAAO,sBAAsB;GAC/D,IAAI;GACJ,IAAI,SAAS,YACX,WAAW,KAAK,SAAS,KAAK,KAAK,SAAS,WAAW,KAAK,SAAS;QAChE;IACL,WAAW,KAAK,QAAQ,KAAK,UAAU,KAAK,QAAQ,KAAK,QAAQ;IACjE,IAAI,KAAK,WAAW,IAAI;GAC1B;GACA,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,QAAQ,CAAC;GAC5C,OAAO,KAAK,YAAY,KAAK;EAC/B;EACA,MAAM,UAAU,OAAe,KAAa,UAAuB;GACjE,MAAM,EAAE,KAAK,IAAI,KAAK,IAAI,MAAM,KAAK,KAAK,MAAM,OAAO;GACvD,MAAM,SAAS,SAAS;GACxB,IAAI,SAAS,OAAO,QAAQ;GAC5B,OACE,UAAU,QAAQ,OAAO,kBAAkB,QAAQ,OAAO,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,GAC9E,OACA,YACA,KACF;EACF;EAEA,MAAM,QAAQ,QAAQ,MAAM,SAAS,MAAM,OAAO;EAClD,MAAM,cAAc,SAAS;EAI7B,IAAI,OACF;EACF,IAAI,UAAU,MAAM;GAClB,MAAM,KAAK,YAAY;GACvB,IAAI,OAAO,KAAA,GAAW;IACpB,IAAI,QAAQ;IACZ,IAAI,OAAO;IACX,OAAO,QAAQ,KAAK,YAAY,CAAC,YAAY,QAAQ,EAAY,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS;IACpF,OACE,OAAO,YAAY,SAAS,KAC5B,YAAY,CAAC,YAAY,OAAO,EAAY,GAAG,CAAC,EAAE,CAAC,GAEnD,QAAQ;IAEV,IAAI,UAAU,MAAM,OAAO;KAAE;KAAO;KAAM;IAAG;GAC/C;EACF;EACA,MAAM,cAAc,QAA+B;GACjD,IAAI,SAAS,MAAM,OAAO;GAC1B,IAAI,MAAM,KAAK,IAAI,OAAO,KAAK;GAC/B,IAAI,MAAM,KAAK,IAAI,OAAO,KAAK;GAC/B,OAAO;EACT;;EAEA,IAAI,UACF,UAAU,OAAO,aAAa,aAAa,KAAK,IAAI,OAAO,WAAW,KAAK,IAAI;;EAEjF,IAAI,QAAQ,WAAW,SAAS;EAChC,MAAM,YAAY,MAAM;EACxB,IAAI;GACF,QAAQ,kBAAkB,SAAS;EACrC,QAAQ,CAER;EAEA,MAAM,UAAU,QAAyB;GACvC,IAAI,YAAY,MAAM,OAAO;GAC7B,UAAU,WAAW,GAAG;GACxB,IAAI,YAAY,MAAM,OAAO;GAC7B,IAAI,YAAY,OAAO;IACrB,QAAQ;IACR,gBAAgB,KAAK;IACrB,SAAS,IAAI,KAAK,CAAC,EAAE,MAAM,EAAE,cAAc,MAAM,CAAiB;GACpE;GACA,OAAO;EACT;EACA,MAAM,UAAU,iBAAqC;GACnD,MAAM,MAAM,QAAQ,aAAa,SAAS,aAAa,OAAO;GAC9D,IAAI,OAAO,GAAG,GAAG,OAAO,OAAO,KAAK,YAAY;EAClD;EAEA,MAAM,UAAU,cAAkC;GAChD,IAAI,UAAU,cAAc,WAAW;GACvC,OAAO,SAAS;EAClB;EACA,MAAM,SAAS,aAAiC;GAC9C,IAAI,SAAS,cAAc,WAAW;GACtC,OAAO;GAGP,IAAI,SAAS,SAAS,aAAa,OAAO,QAAQ;GAClD,cAAc,UAAU;GACxB,gBAAgB,IAAI;GACpB,cAAc,OAAO,YAAY,QAAQ;EAC3C;EACA,MAAM,eAAqB;GACzB,QAAQ,oBAAoB,eAAe,MAAM;GACjD,QAAQ,oBAAoB,aAAa,KAAK;GAC9C,QAAQ,oBAAoB,iBAAiB,KAAK;GAClD,QAAQ,oBAAoB,sBAAsB,KAAK;EACzD;EACA,QAAQ,iBAAiB,eAAe,MAAM;EAC9C,QAAQ,iBAAiB,aAAa,KAAK;EAC3C,QAAQ,iBAAiB,iBAAiB,KAAK;EAC/C,QAAQ,iBAAiB,sBAAsB,KAAK;EAEpD,cAAc,UAAU;GAAE;GAAW;EAAO;EAC5C,gBAAgB,KAAK;EACrB,aAAa,UAAU,SAAS;EAChC,QAAQ,UAAU,SAAS;EAG3B,QAAQ,SAAS,OAAO;EAExB,SAAS,IAAI,KAAK,CAAC,EAAE,MAAM,EAAE,cAAc,MAAM,CAAiB;EAClE,IAAI,YAAY,MAAM,OAAO,OAAO,OAAO,KAAK;CAClD,GACA;EAAC;EAAe;EAAQ;EAAU;EAAU;CAAM,CACpD;CAGA,sBACc;EACV,cAAc,SAAS,OAAO;EAC9B,cAAc,UAAU;CAC1B,GACA,CAAC,CACH;CAIA,cACE,CAAC,WACD,wDAAwD,OAAO,QAAQ,EAAE,YAC3E;CACA,cACE,aAAa,CAAC,eAAe,KAAK,KAAK,IAAI,GAC3C,yBAAyB,IAAI,0CAA0C,IAAI,kBACtE,KAAK,oGAEZ;CACA,MAAM,QAAQ,SAAS;CACvB,MAAM,cAAc,UAAU,KAAA,IAAY,CAAC,IAAI,QAAQ,KAAK;CAC5D,cACE,YAAY,MAAM,MAAM,CAAC,SAAS,GAAG,KAAK,KAAK,IAAI,CAAC,GACpD,oBAAoB,UAAU,KAAA,IAAY,YAAY,iBAAiB,IACjE,YAAY,KAAK,IAAI,EAAE,yIAE/B;CACA,cACE,YAAY,MAAM,GAAG,MAAM,IAAI,KAAK,IAAK,YAAY,IAAI,EAAa,GACtE,4BAA4B,YAAY,KAAK,IAAI,EAAE,oEAErD;CACA,MAAM,eAAe,QAAQ,KAAK;CAClC,cACE,iBAAiB,KAAA,KAAa,iBAAiB,OAC/C,2KAEF;CAEA,MAAM,eACJ,MAAM,SAAS,KACf,CAAC,WACD,KAAK,kBAAkB,KAAA,KACvB,KAAK,uBAAuB,KAAA;CAC9B,MAAM,kBAAkB,OAAO,KAAK;CACpC,gBAAgB;EACd,IAAI,CAAC,SAAS,gBAAgB,WAAW,CAAC,gBAAgB,cAAc,UAAU,GAAG;EACrF,gBAAgB,UAAU;EAC1B,QAAQ,MACN,uJAEF;CACF,GAAG,CAAC,YAAY,CAAC;CAIjB,MAAM,QAAQ,MAAM;CACpB,MAAM,WAAW,MAAM,KAAK,MAAM,QAAQ,GAAG,KAAK,GAAG,CAAC;CACtD,MAAM,WAAmC;EACvC,kBAAkB,QAAQ,IAAI,GAAG,SAAS,MAAM,EAAE,KAAK;EACvD,gBAAgB,GAAG,SAAS,QAAQ,MAAM,EAAE;CAC9C;CACA,SAAS,SAAS,GAAG,UAAU;EAC7B,SAAS,kBAAkB,WAAW,GAAG,EAAE;CAC7C,CAAC;CAED,MAAM,aAAa,UAAU,KAAK;CAClC,MAAM,WAAW,iBAAiB;CAClC,MAAM,QAAQ,eACL;EACL,OAAO;EACP,QAAQ;EACR;EACA;EACA;EACA;EACA;EACA;EACA;CACF,IACA;EAAC;EAAY;EAAO;EAAS;EAAU;EAAa;EAAU;EAAK;EAAK;CAAI,CAC9E;CAGA,MAAM,UAAU,eACP;EACE;EACP;EACY;EACZ;EACA;EACA;EACA;EACA;EACA;EACA;EACA,eAAe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,OAAO;CACT,IACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CACF;CAKA,MAAM,aACJ,QAAQ,IAAI,gBAAgB,iBAAiB,aAAa,IAAI,UAAU,KAAA,CAAS,IAAI;CACvF,MAAM,eAAuE;EAC3E,MAAM,QAAQ,IAAI,UAAU,KAAA;EAC5B,GAAI,eAAe,KAAK,EAAE,mBAAmB,WAAW,IAAI,CAAC;EAE7D,GAAI,QAAQ,KAAK,qBAAqB,KAAA,IAClC,EAAE,oBAAoB,iBAAiB,IACvC,CAAC;EAEL,GAAI,UAAU,EAAE,gBAAgB,iBAAiB,IAAI,CAAC;EACtD,gBAAgB,SAAS,OAAO;EAChC,iBAAiB,SAAS,QAAQ;EAClC,oBAAoB;EACpB,iBAAiB,SAAS,QAAQ;CACpC;CAEA,MAAM,UAAU,UAA4D;EAC1E,gBAAgB;EAChB;EACA;EACA;EAEA,QAAQ,OAAO;GAAE,GAAI;GAA4B,GAAG,kBAAkB,OAAO,CAAC;EAAE;EAChF;EACA,OAAO;EACP;EACA,KAAK;CACP,CAAC;CAED,OAAO,oBAAC,eAAD;EAAe,OAAO;EAAU,UAAA;CAAuB,CAAA;AAChE;AAEA,eAAe,cAAc;;;;;;AAO7B,MAAa,aAAa"}
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
  import { dataAttr } from "../internal/data-attr.mjs";
3
3
  import { mergeRefs, mergeTokenLists } from "../internal/merge-props.mjs";
4
- import { resolveStateValue, useRender } from "../internal/use-render.mjs";
4
+ import { resolveStateValue } from "../internal/render-element.mjs";
5
+ import { useRender } from "../internal/use-render.mjs";
5
6
  import { useDevWarning } from "../internal/use-dev-warning.mjs";
6
7
  import { useSliderContext } from "./slider-context.mjs";
7
8
  import { percent, thumbBounds } from "./slider-arithmetic.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"slider-thumb.mjs","names":[],"sources":["../../src/slider/slider-thumb.tsx"],"sourcesContent":["\"use client\";\nimport { useEffectEvent, useLayoutEffect, useMemo, useRef } from \"react\";\nimport type {\n ChangeEvent,\n ComponentPropsWithRef,\n CSSProperties,\n PointerEvent as ReactPointerEvent,\n ReactNode,\n Ref,\n} from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { mergeRefs, mergeTokenLists } from \"../internal/merge-props.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useDevWarning } from \"../internal/use-dev-warning.js\";\nimport { resolveStateValue, useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport { percent, thumbBounds } from \"./slider-arithmetic.js\";\nimport { useSliderContext } from \"./slider-context.js\";\nimport type { SliderOrientation } from \"./slider-root.js\";\n\nexport interface SliderThumbState {\n readonly index: number;\n /** The value this thumb shows. */\n readonly value: number;\n /** The Root is pending and this thumb is the one the latest step or commit moved. */\n readonly pending: boolean;\n /** A pointer is captured on this thumb. */\n readonly dragging: boolean;\n readonly orientation: SliderOrientation;\n readonly disabled: boolean;\n}\n\nexport interface SliderThumbProps extends Omit<\n ComponentPropsWithRef<\"span\">,\n | \"onPointerDown\"\n | \"aria-label\"\n | \"aria-labelledby\"\n | \"aria-describedby\"\n // The value attributes are the native input's (design 8): never authored.\n | \"aria-valuemin\"\n | \"aria-valuemax\"\n | \"aria-valuenow\"\n | \"aria-valuetext\"\n | \"aria-orientation\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /** Which value this thumb edits. Default `0`. */\n index?: number;\n /** Form field name of this thumb's input; overrides the Root's `name`. */\n name?: string;\n /** The `form` attribute of this thumb's input; overrides the Root's. */\n form?: string;\n /**\n * Forwarded to the input (the element with role `slider`), not the styled element. Required\n * for every thumb of a multi-thumb slider unless `aria-labelledby` is given (dev warning).\n */\n \"aria-label\"?: string;\n /** Forwarded to the input. */\n \"aria-labelledby\"?: string;\n /** Forwarded to the input. */\n \"aria-describedby\"?: string;\n /** The native `<input type=\"range\">` inside the thumb. */\n inputRef?: Ref<HTMLInputElement>;\n /** Forwarded to the input. */\n autoFocus?: boolean;\n className?: StateValue<string | undefined, SliderThumbState>;\n style?: StateValue<CSSProperties | undefined, SliderThumbState>;\n /** Rendered inside the styled element, next to the input (an icon, a value bubble). */\n children?: StateValue<ReactNode, SliderThumbState>;\n render?: RenderProp<ComponentPropsWithRef<\"span\">, SliderThumbState>;\n}\n\n/** Visually hidden, sized to the thumb so an assistive-technology focus ring lands on it. */\nconst HIDDEN_INPUT_STYLE: CSSProperties = {\n position: \"absolute\",\n inset: 0,\n width: \"100%\",\n height: \"100%\",\n margin: 0,\n opacity: 0,\n pointerEvents: \"none\",\n};\n\n/** Chromium derives the accessibility orientation from `writing-mode`; `rtl` puts `min` at the bottom. */\nconst VERTICAL_INPUT_STYLE: CSSProperties = {\n ...HIDDEN_INPUT_STYLE,\n writingMode: \"vertical-lr\",\n direction: \"rtl\",\n};\n\n/**\n * One value handle: a styled element (`span`) **containing** a visually hidden native\n * `<input type=\"range\">`, which is the focusable, labelled, form-participating `slider` with the\n * native keyboard (conventions 1.1 exception). `ref` goes to the styled element, `inputRef` to the\n * input. The input's native `min` / `max` are the neighbours' values, so thumbs cannot cross.\n *\n * Owned keys on the styled element: `onPointerDown`, `data-index`, `data-orientation`,\n * `data-dragging`, `data-pending`, `data-disabled`, and `--slider-value` / `touch-action` in\n * `style` (the consumer's entries win). `aria-label`, `aria-labelledby`, `aria-describedby`,\n * `name`, `form` and `autoFocus` go to the input; every other input attribute is the library's.\n */\nexport function SliderThumb({\n index = 0,\n name,\n form,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n inputRef: consumerInputRef,\n autoFocus,\n className,\n style,\n children,\n render,\n ...rest\n}: SliderThumbProps) {\n const ctx = useSliderContext(\"Slider.Thumb\");\n const value = ctx.shown[index];\n const inRange = value !== undefined;\n const shownValue = value ?? ctx.min;\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n // Inside a Field with one thumb, Thumb 0's input is the Field's control (design 9.4.1).\n const fieldInputRef = index === 0 ? ctx.field?.inputRef : undefined;\n const mergedInputRef = useMemo(\n () =>\n mergeRefs<HTMLInputElement | null>(\n inputRef,\n consumerInputRef,\n fieldInputRef as Ref<HTMLInputElement | null> | undefined,\n ),\n [consumerInputRef, fieldInputRef],\n );\n\n // Registration with the Root (pointer focus, reconciliation, reset), from a layout effect so\n // the Root's mount reconciliation, which runs after its children's, sees every input.\n const { registerThumb, onItemMounted } = ctx;\n useLayoutEffect(() => {\n const input = inputRef.current;\n if (input === null) return;\n const unregister = registerThumb(index, input);\n onItemMounted();\n return unregister;\n }, [index, registerThumb, onItemMounted]);\n\n // React surfaces no `onChange` for the native `change` (design 4.2), and the vertical\n // ArrowLeft / ArrowRight normalisation needs the `keydown` before the browser acts on it.\n const onNativeChange = useEffectEvent((event: Event) => {\n ctx.inputCommit(index, event);\n });\n const onNativeKeyDown = useEffectEvent((event: KeyboardEvent) => {\n ctx.inputKeyDown(index, event);\n });\n useLayoutEffect(() => {\n const input = inputRef.current;\n if (input === null) return;\n input.addEventListener(\"change\", onNativeChange);\n input.addEventListener(\"keydown\", onNativeKeyDown);\n return () => {\n input.removeEventListener(\"change\", onNativeChange);\n input.removeEventListener(\"keydown\", onNativeKeyDown);\n };\n }, [inRange]);\n\n useDevWarning(\n !inRange,\n `Slider.Thumb: \\`index={${index}}\\` is outside the value (${ctx.shown.length} ` +\n `${ctx.shown.length === 1 ? \"value\" : \"values\"}). The Thumb renders nothing.`,\n );\n useDevWarning(\n inRange && ctx.shown.length > 1 && ariaLabel === undefined && ariaLabelledBy === undefined,\n `Slider.Thumb: each thumb of a multi-thumb slider needs its own name (\\`aria-label\\` or ` +\n `\\`aria-labelledby\\`), e.g. \"Minimum price\"; the thumb at index ${index} has none.`,\n );\n\n const fieldName = ctx.field?.name;\n useDevWarning(\n inRange && name !== undefined && fieldName !== undefined && name !== fieldName,\n `Slider.Thumb: its \\`name\\` (\"${name}\") differs from the Field.Root's (\"${fieldName}\"). ` +\n \"The Field reads server errors and `validate`'s value by the Field's name.\",\n );\n\n const pending = ctx.pending && ctx.pendingThumb === index;\n const dragging = ctx.draggingThumb === index;\n const state: SliderThumbState = {\n index,\n value: shownValue,\n pending,\n dragging,\n orientation: ctx.orientation,\n disabled: ctx.disabled,\n };\n\n const { lower, upper } = thumbBounds(ctx.shown, index, ctx.min, ctx.max, ctx.gap);\n const input = inRange ? (\n <input\n ref={mergedInputRef}\n type=\"range\"\n id={ctx.thumbId(index)}\n name={name ?? ctx.name}\n form={form ?? ctx.form}\n min={lower}\n max={upper}\n step={ctx.step}\n value={shownValue}\n disabled={ctx.disabled}\n autoFocus={autoFocus}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={\n mergeTokenLists(ariaDescribedBy, index === 0 ? ctx.field?.describedBy : undefined) ||\n undefined\n }\n aria-invalid={ctx.field?.invalid}\n aria-valuetext={ctx.getAriaValueText?.(shownValue, index)}\n style={ctx.orientation === \"vertical\" ? VERTICAL_INPUT_STYLE : HIDDEN_INPUT_STYLE}\n onChange={(event: ChangeEvent<HTMLInputElement>) => {\n ctx.inputStep(index, Number(event.target.value), event.nativeEvent);\n }}\n />\n ) : null;\n\n const geometry = {\n \"--slider-value\": `${percent(shownValue, ctx.min, ctx.max)}%`,\n touchAction: ctx.orientation === \"vertical\" ? \"pan-x\" : \"pan-y\",\n } as CSSProperties;\n\n const element = useRender<ComponentPropsWithRef<\"span\">, SliderThumbState>({\n defaultElement: \"span\",\n render,\n state,\n className,\n // The library's entries lose to the consumer's own (design 3.2).\n style: (s) => ({ ...geometry, ...resolveStateValue(style, s) }),\n children: undefined,\n props: rest,\n libraryProps: {\n \"data-index\": String(index),\n \"data-orientation\": ctx.orientation,\n \"data-dragging\": dataAttr(dragging),\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(ctx.disabled),\n ...(ctx.field !== null ? { \"data-invalid\": ctx.field.dataInvalid } : {}),\n onPointerDown: (event: ReactPointerEvent<HTMLSpanElement>) => {\n ctx.beginGesture(index, event.nativeEvent, event.currentTarget);\n },\n // Owned, so a `render` element's own children can never drop the input.\n children: (\n <>\n {input}\n {resolveStateValue(children, state)}\n </>\n ),\n // `children` is not in the library layer's type (useRender resolves it), but an owned\n // key wins over a `render` element's own children, which is what keeps the input.\n } as Partial<ComponentPropsWithRef<\"span\">> & DataAttributes,\n });\n\n return inRange ? element : null;\n}\n\nSliderThumb.displayName = \"SliderThumb\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"slider-thumb.mjs","names":[],"sources":["../../src/slider/slider-thumb.tsx"],"sourcesContent":["\"use client\";\nimport { useEffectEvent, useLayoutEffect, useMemo, useRef } from \"react\";\nimport type {\n ChangeEvent,\n ComponentPropsWithRef,\n CSSProperties,\n PointerEvent as ReactPointerEvent,\n ReactNode,\n Ref,\n} from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { mergeRefs, mergeTokenLists } from \"../internal/merge-props.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useDevWarning } from \"../internal/use-dev-warning.js\";\nimport { resolveStateValue, useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport { percent, thumbBounds } from \"./slider-arithmetic.js\";\nimport { useSliderContext } from \"./slider-context.js\";\nimport type { SliderOrientation } from \"./slider-root.js\";\n\nexport interface SliderThumbState {\n readonly index: number;\n /** The value this thumb shows. */\n readonly value: number;\n /** The Root is pending and this thumb is the one the latest step or commit moved. */\n readonly pending: boolean;\n /** A pointer is captured on this thumb. */\n readonly dragging: boolean;\n readonly orientation: SliderOrientation;\n readonly disabled: boolean;\n}\n\nexport interface SliderThumbProps extends Omit<\n ComponentPropsWithRef<\"span\">,\n | \"onPointerDown\"\n | \"aria-label\"\n | \"aria-labelledby\"\n | \"aria-describedby\"\n // The value attributes are the native input's (design 8): never authored.\n | \"aria-valuemin\"\n | \"aria-valuemax\"\n | \"aria-valuenow\"\n | \"aria-valuetext\"\n | \"aria-orientation\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /** Which value this thumb edits. Default `0`. */\n index?: number;\n /** Form field name of this thumb's input; overrides the Root's `name`. */\n name?: string;\n /** The `form` attribute of this thumb's input; overrides the Root's. */\n form?: string;\n /**\n * Forwarded to the input (the element with role `slider`), not the styled element. Required\n * for every thumb of a multi-thumb slider unless `aria-labelledby` is given (dev warning).\n */\n \"aria-label\"?: string;\n /** Forwarded to the input. */\n \"aria-labelledby\"?: string;\n /** Forwarded to the input. */\n \"aria-describedby\"?: string;\n /** The native `<input type=\"range\">` inside the thumb. */\n inputRef?: Ref<HTMLInputElement>;\n /** Forwarded to the input. */\n autoFocus?: boolean;\n className?: StateValue<string | undefined, SliderThumbState>;\n style?: StateValue<CSSProperties | undefined, SliderThumbState>;\n /** Rendered inside the styled element, next to the input (an icon, a value bubble). */\n children?: StateValue<ReactNode, SliderThumbState>;\n render?: RenderProp<ComponentPropsWithRef<\"span\">, SliderThumbState>;\n}\n\n/** Visually hidden, sized to the thumb so an assistive-technology focus ring lands on it. */\nconst HIDDEN_INPUT_STYLE: CSSProperties = {\n position: \"absolute\",\n inset: 0,\n width: \"100%\",\n height: \"100%\",\n margin: 0,\n opacity: 0,\n pointerEvents: \"none\",\n};\n\n/** Chromium derives the accessibility orientation from `writing-mode`; `rtl` puts `min` at the bottom. */\nconst VERTICAL_INPUT_STYLE: CSSProperties = {\n ...HIDDEN_INPUT_STYLE,\n writingMode: \"vertical-lr\",\n direction: \"rtl\",\n};\n\n/**\n * One value handle: a styled element (`span`) **containing** a visually hidden native\n * `<input type=\"range\">`, which is the focusable, labelled, form-participating `slider` with the\n * native keyboard (conventions 1.1 exception). `ref` goes to the styled element, `inputRef` to the\n * input. The input's native `min` / `max` are the neighbours' values, so thumbs cannot cross.\n *\n * Owned keys on the styled element: `onPointerDown`, `data-index`, `data-orientation`,\n * `data-dragging`, `data-pending`, `data-disabled`, and `--slider-value` / `touch-action` in\n * `style` (the consumer's entries win). `aria-label`, `aria-labelledby`, `aria-describedby`,\n * `name`, `form` and `autoFocus` go to the input; every other input attribute is the library's.\n */\nexport function SliderThumb({\n index = 0,\n name,\n form,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n inputRef: consumerInputRef,\n autoFocus,\n className,\n style,\n children,\n render,\n ...rest\n}: SliderThumbProps) {\n const ctx = useSliderContext(\"Slider.Thumb\");\n const value = ctx.shown[index];\n const inRange = value !== undefined;\n const shownValue = value ?? ctx.min;\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n // Inside a Field with one thumb, Thumb 0's input is the Field's control (design 9.4.1).\n const fieldInputRef = index === 0 ? ctx.field?.inputRef : undefined;\n const mergedInputRef = useMemo(\n () =>\n mergeRefs<HTMLInputElement | null>(\n inputRef,\n consumerInputRef,\n fieldInputRef as Ref<HTMLInputElement | null> | undefined,\n ),\n [consumerInputRef, fieldInputRef],\n );\n\n // Registration with the Root (pointer focus, reconciliation, reset), from a layout effect so\n // the Root's mount reconciliation, which runs after its children's, sees every input.\n const { registerThumb, onItemMounted } = ctx;\n useLayoutEffect(() => {\n const input = inputRef.current;\n if (input === null) return;\n const unregister = registerThumb(index, input);\n onItemMounted();\n return unregister;\n }, [index, registerThumb, onItemMounted]);\n\n // React surfaces no `onChange` for the native `change` (design 4.2), and the vertical\n // ArrowLeft / ArrowRight normalisation needs the `keydown` before the browser acts on it.\n const onNativeChange = useEffectEvent((event: Event) => {\n ctx.inputCommit(index, event);\n });\n const onNativeKeyDown = useEffectEvent((event: KeyboardEvent) => {\n ctx.inputKeyDown(index, event);\n });\n useLayoutEffect(() => {\n const input = inputRef.current;\n if (input === null) return;\n input.addEventListener(\"change\", onNativeChange);\n input.addEventListener(\"keydown\", onNativeKeyDown);\n return () => {\n input.removeEventListener(\"change\", onNativeChange);\n input.removeEventListener(\"keydown\", onNativeKeyDown);\n };\n }, [inRange]);\n\n useDevWarning(\n !inRange,\n `Slider.Thumb: \\`index={${index}}\\` is outside the value (${ctx.shown.length} ` +\n `${ctx.shown.length === 1 ? \"value\" : \"values\"}). The Thumb renders nothing.`,\n );\n useDevWarning(\n inRange && ctx.shown.length > 1 && ariaLabel === undefined && ariaLabelledBy === undefined,\n `Slider.Thumb: each thumb of a multi-thumb slider needs its own name (\\`aria-label\\` or ` +\n `\\`aria-labelledby\\`), e.g. \"Minimum price\"; the thumb at index ${index} has none.`,\n );\n\n const fieldName = ctx.field?.name;\n useDevWarning(\n inRange && name !== undefined && fieldName !== undefined && name !== fieldName,\n `Slider.Thumb: its \\`name\\` (\"${name}\") differs from the Field.Root's (\"${fieldName}\"). ` +\n \"The Field reads server errors and `validate`'s value by the Field's name.\",\n );\n\n const pending = ctx.pending && ctx.pendingThumb === index;\n const dragging = ctx.draggingThumb === index;\n const state: SliderThumbState = {\n index,\n value: shownValue,\n pending,\n dragging,\n orientation: ctx.orientation,\n disabled: ctx.disabled,\n };\n\n const { lower, upper } = thumbBounds(ctx.shown, index, ctx.min, ctx.max, ctx.gap);\n const input = inRange ? (\n <input\n ref={mergedInputRef}\n type=\"range\"\n id={ctx.thumbId(index)}\n name={name ?? ctx.name}\n form={form ?? ctx.form}\n min={lower}\n max={upper}\n step={ctx.step}\n value={shownValue}\n disabled={ctx.disabled}\n autoFocus={autoFocus}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={\n mergeTokenLists(ariaDescribedBy, index === 0 ? ctx.field?.describedBy : undefined) ||\n undefined\n }\n aria-invalid={ctx.field?.invalid}\n aria-valuetext={ctx.getAriaValueText?.(shownValue, index)}\n style={ctx.orientation === \"vertical\" ? VERTICAL_INPUT_STYLE : HIDDEN_INPUT_STYLE}\n onChange={(event: ChangeEvent<HTMLInputElement>) => {\n ctx.inputStep(index, Number(event.target.value), event.nativeEvent);\n }}\n />\n ) : null;\n\n const geometry = {\n \"--slider-value\": `${percent(shownValue, ctx.min, ctx.max)}%`,\n touchAction: ctx.orientation === \"vertical\" ? \"pan-x\" : \"pan-y\",\n } as CSSProperties;\n\n const element = useRender<ComponentPropsWithRef<\"span\">, SliderThumbState>({\n defaultElement: \"span\",\n render,\n state,\n className,\n // The library's entries lose to the consumer's own (design 3.2).\n style: (s) => ({ ...geometry, ...resolveStateValue(style, s) }),\n children: undefined,\n props: rest,\n libraryProps: {\n \"data-index\": String(index),\n \"data-orientation\": ctx.orientation,\n \"data-dragging\": dataAttr(dragging),\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(ctx.disabled),\n ...(ctx.field !== null ? { \"data-invalid\": ctx.field.dataInvalid } : {}),\n onPointerDown: (event: ReactPointerEvent<HTMLSpanElement>) => {\n ctx.beginGesture(index, event.nativeEvent, event.currentTarget);\n },\n // Owned, so a `render` element's own children can never drop the input.\n children: (\n <>\n {input}\n {resolveStateValue(children, state)}\n </>\n ),\n // `children` is not in the library layer's type (useRender resolves it), but an owned\n // key wins over a `render` element's own children, which is what keeps the input.\n } as Partial<ComponentPropsWithRef<\"span\">> & DataAttributes,\n });\n\n return inRange ? element : null;\n}\n\nSliderThumb.displayName = \"SliderThumb\";\n"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { dataAttr } from "../internal/data-attr.mjs";
3
- import { resolveStateValue, useRender } from "../internal/use-render.mjs";
3
+ import { resolveStateValue } from "../internal/render-element.mjs";
4
+ import { useRender } from "../internal/use-render.mjs";
4
5
  import { useSliderContext } from "./slider-context.mjs";
5
6
  import { useCallback } from "react";
6
7
  //#region src/slider/slider-track.tsx
@@ -1 +1 @@
1
- {"version":3,"file":"slider-track.mjs","names":[],"sources":["../../src/slider/slider-track.tsx"],"sourcesContent":["\"use client\";\nimport { useCallback } from \"react\";\nimport type {\n ComponentPropsWithRef,\n CSSProperties,\n PointerEvent as ReactPointerEvent,\n ReactNode,\n} from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { resolveStateValue, useRender } from \"../internal/use-render.js\";\nimport { useSliderContext } from \"./slider-context.js\";\nimport type { SliderOrientation } from \"./slider-root.js\";\n\nexport interface SliderTrackState {\n readonly orientation: SliderOrientation;\n /** A pointer is captured on a thumb. */\n readonly dragging: boolean;\n readonly disabled: boolean;\n}\n\nexport interface SliderTrackProps extends Omit<\n ComponentPropsWithRef<\"div\">,\n \"onPointerDown\" | \"className\" | \"style\" | \"children\"\n> {\n className?: StateValue<string | undefined, SliderTrackState>;\n style?: StateValue<CSSProperties | undefined, SliderTrackState>;\n children?: StateValue<ReactNode, SliderTrackState>;\n render?: RenderProp<ComponentPropsWithRef<\"div\">, SliderTrackState>;\n}\n\n/**\n * The rail the thumbs move along. A press moves the nearest thumb, focuses its input and starts\n * its drag; its box is the geometry reference for the pointer math (its computed `direction`\n * mirrors a horizontal slider). Owned keys: `onPointerDown`, `data-orientation`,\n * `data-disabled`, and `touch-action` in `style` (`pan-y` horizontal, `pan-x` vertical; the\n * consumer's entry wins).\n */\nexport function SliderTrack({ className, style, children, render, ...rest }: SliderTrackProps) {\n const ctx = useSliderContext(\"Slider.Track\");\n const { trackRef } = ctx;\n const libraryRef = useCallback(\n (element: HTMLDivElement) => {\n trackRef.current = element;\n return () => {\n if (trackRef.current === element) trackRef.current = null;\n };\n },\n [trackRef],\n );\n\n const state: SliderTrackState = {\n orientation: ctx.orientation,\n dragging: ctx.draggingThumb !== null,\n disabled: ctx.disabled,\n };\n const touchAction: CSSProperties = {\n touchAction: ctx.orientation === \"vertical\" ? \"pan-x\" : \"pan-y\",\n };\n\n return useRender<ComponentPropsWithRef<\"div\">, SliderTrackState>({\n defaultElement: \"div\",\n render,\n state,\n className,\n style: (s) => ({ ...touchAction, ...resolveStateValue(style, s) }),\n children,\n props: rest,\n ref: libraryRef,\n libraryProps: {\n \"data-orientation\": ctx.orientation,\n \"data-disabled\": dataAttr(ctx.disabled),\n onPointerDown: (event: ReactPointerEvent<HTMLDivElement>) => {\n // A press on a Thumb bubbles here after the Thumb began its gesture; the Root ignores it.\n ctx.beginGesture(null, event.nativeEvent, event.currentTarget);\n },\n },\n });\n}\n\nSliderTrack.displayName = \"SliderTrack\";\n"],"mappings":";;;;;;;;;;;;;AAsCA,SAAgB,YAAY,EAAE,WAAW,OAAO,UAAU,QAAQ,GAAG,QAA0B;CAC7F,MAAM,MAAM,iBAAiB,cAAc;CAC3C,MAAM,EAAE,aAAa;CACrB,MAAM,aAAa,aAChB,YAA4B;EAC3B,SAAS,UAAU;EACnB,aAAa;GACX,IAAI,SAAS,YAAY,SAAS,SAAS,UAAU;EACvD;CACF,GACA,CAAC,QAAQ,CACX;CAEA,MAAM,QAA0B;EAC9B,aAAa,IAAI;EACjB,UAAU,IAAI,kBAAkB;EAChC,UAAU,IAAI;CAChB;CACA,MAAM,cAA6B,EACjC,aAAa,IAAI,gBAAgB,aAAa,UAAU,QAC1D;CAEA,OAAO,UAA0D;EAC/D,gBAAgB;EAChB;EACA;EACA;EACA,QAAQ,OAAO;GAAE,GAAG;GAAa,GAAG,kBAAkB,OAAO,CAAC;EAAE;EAChE;EACA,OAAO;EACP,KAAK;EACL,cAAc;GACZ,oBAAoB,IAAI;GACxB,iBAAiB,SAAS,IAAI,QAAQ;GACtC,gBAAgB,UAA6C;IAE3D,IAAI,aAAa,MAAM,MAAM,aAAa,MAAM,aAAa;GAC/D;EACF;CACF,CAAC;AACH;AAEA,YAAY,cAAc"}
1
+ {"version":3,"file":"slider-track.mjs","names":[],"sources":["../../src/slider/slider-track.tsx"],"sourcesContent":["\"use client\";\nimport { useCallback } from \"react\";\nimport type {\n ComponentPropsWithRef,\n CSSProperties,\n PointerEvent as ReactPointerEvent,\n ReactNode,\n} from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { resolveStateValue, useRender } from \"../internal/use-render.js\";\nimport { useSliderContext } from \"./slider-context.js\";\nimport type { SliderOrientation } from \"./slider-root.js\";\n\nexport interface SliderTrackState {\n readonly orientation: SliderOrientation;\n /** A pointer is captured on a thumb. */\n readonly dragging: boolean;\n readonly disabled: boolean;\n}\n\nexport interface SliderTrackProps extends Omit<\n ComponentPropsWithRef<\"div\">,\n \"onPointerDown\" | \"className\" | \"style\" | \"children\"\n> {\n className?: StateValue<string | undefined, SliderTrackState>;\n style?: StateValue<CSSProperties | undefined, SliderTrackState>;\n children?: StateValue<ReactNode, SliderTrackState>;\n render?: RenderProp<ComponentPropsWithRef<\"div\">, SliderTrackState>;\n}\n\n/**\n * The rail the thumbs move along. A press moves the nearest thumb, focuses its input and starts\n * its drag; its box is the geometry reference for the pointer math (its computed `direction`\n * mirrors a horizontal slider). Owned keys: `onPointerDown`, `data-orientation`,\n * `data-disabled`, and `touch-action` in `style` (`pan-y` horizontal, `pan-x` vertical; the\n * consumer's entry wins).\n */\nexport function SliderTrack({ className, style, children, render, ...rest }: SliderTrackProps) {\n const ctx = useSliderContext(\"Slider.Track\");\n const { trackRef } = ctx;\n const libraryRef = useCallback(\n (element: HTMLDivElement) => {\n trackRef.current = element;\n return () => {\n if (trackRef.current === element) trackRef.current = null;\n };\n },\n [trackRef],\n );\n\n const state: SliderTrackState = {\n orientation: ctx.orientation,\n dragging: ctx.draggingThumb !== null,\n disabled: ctx.disabled,\n };\n const touchAction: CSSProperties = {\n touchAction: ctx.orientation === \"vertical\" ? \"pan-x\" : \"pan-y\",\n };\n\n return useRender<ComponentPropsWithRef<\"div\">, SliderTrackState>({\n defaultElement: \"div\",\n render,\n state,\n className,\n style: (s) => ({ ...touchAction, ...resolveStateValue(style, s) }),\n children,\n props: rest,\n ref: libraryRef,\n libraryProps: {\n \"data-orientation\": ctx.orientation,\n \"data-disabled\": dataAttr(ctx.disabled),\n onPointerDown: (event: ReactPointerEvent<HTMLDivElement>) => {\n // A press on a Thumb bubbles here after the Thumb began its gesture; the Root ignores it.\n ctx.beginGesture(null, event.nativeEvent, event.currentTarget);\n },\n },\n });\n}\n\nSliderTrack.displayName = \"SliderTrack\";\n"],"mappings":";;;;;;;;;;;;;;AAsCA,SAAgB,YAAY,EAAE,WAAW,OAAO,UAAU,QAAQ,GAAG,QAA0B;CAC7F,MAAM,MAAM,iBAAiB,cAAc;CAC3C,MAAM,EAAE,aAAa;CACrB,MAAM,aAAa,aAChB,YAA4B;EAC3B,SAAS,UAAU;EACnB,aAAa;GACX,IAAI,SAAS,YAAY,SAAS,SAAS,UAAU;EACvD;CACF,GACA,CAAC,QAAQ,CACX;CAEA,MAAM,QAA0B;EAC9B,aAAa,IAAI;EACjB,UAAU,IAAI,kBAAkB;EAChC,UAAU,IAAI;CAChB;CACA,MAAM,cAA6B,EACjC,aAAa,IAAI,gBAAgB,aAAa,UAAU,QAC1D;CAEA,OAAO,UAA0D;EAC/D,gBAAgB;EAChB;EACA;EACA;EACA,QAAQ,OAAO;GAAE,GAAG;GAAa,GAAG,kBAAkB,OAAO,CAAC;EAAE;EAChE;EACA,OAAO;EACP,KAAK;EACL,cAAc;GACZ,oBAAoB,IAAI;GACxB,iBAAiB,SAAS,IAAI,QAAQ;GACtC,gBAAgB,UAA6C;IAE3D,IAAI,aAAa,MAAM,MAAM,aAAa,MAAM,aAAa;GAC/D;EACF;CACF,CAAC;AACH;AAEA,YAAY,cAAc"}