@mortenbrudvik/waveui 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/README.md +634 -167
  2. package/dist/components/data-display/InfoButton.cjs +2 -0
  3. package/dist/components/data-display/InfoButton.cjs.map +1 -0
  4. package/dist/components/data-display/InfoButton.mjs +173 -0
  5. package/dist/components/data-display/InfoButton.mjs.map +1 -0
  6. package/dist/components/data-display/InfoLabel.cjs +1 -1
  7. package/dist/components/data-display/InfoLabel.cjs.map +1 -1
  8. package/dist/components/data-display/InfoLabel.mjs +39 -96
  9. package/dist/components/data-display/InfoLabel.mjs.map +1 -1
  10. package/dist/components/input/Calendar.cjs +2 -0
  11. package/dist/components/input/Calendar.cjs.map +1 -0
  12. package/dist/components/input/Calendar.mjs +352 -0
  13. package/dist/components/input/Calendar.mjs.map +1 -0
  14. package/dist/components/input/Calendar.views.cjs +2 -0
  15. package/dist/components/input/Calendar.views.cjs.map +1 -0
  16. package/dist/components/input/Calendar.views.mjs +194 -0
  17. package/dist/components/input/Calendar.views.mjs.map +1 -0
  18. package/dist/components/input/Checkbox.cjs +1 -1
  19. package/dist/components/input/Checkbox.cjs.map +1 -1
  20. package/dist/components/input/Checkbox.mjs +91 -75
  21. package/dist/components/input/Checkbox.mjs.map +1 -1
  22. package/dist/components/input/ColorArea.cjs +1 -1
  23. package/dist/components/input/ColorArea.cjs.map +1 -1
  24. package/dist/components/input/ColorArea.mjs +18 -18
  25. package/dist/components/input/ColorArea.mjs.map +1 -1
  26. package/dist/components/input/ColorPicker.parts.cjs +1 -1
  27. package/dist/components/input/ColorPicker.parts.cjs.map +1 -1
  28. package/dist/components/input/ColorPicker.parts.mjs +1 -1
  29. package/dist/components/input/ColorPicker.parts.mjs.map +1 -1
  30. package/dist/components/input/Combobox.cjs +1 -1
  31. package/dist/components/input/Combobox.cjs.map +1 -1
  32. package/dist/components/input/Combobox.expand.cjs +1 -1
  33. package/dist/components/input/Combobox.expand.cjs.map +1 -1
  34. package/dist/components/input/Combobox.expand.mjs +20 -20
  35. package/dist/components/input/Combobox.expand.mjs.map +1 -1
  36. package/dist/components/input/Combobox.mjs +219 -138
  37. package/dist/components/input/Combobox.mjs.map +1 -1
  38. package/dist/components/input/Combobox.text.cjs +2 -0
  39. package/dist/components/input/Combobox.text.cjs.map +1 -0
  40. package/dist/components/input/Combobox.text.mjs +24 -0
  41. package/dist/components/input/Combobox.text.mjs.map +1 -0
  42. package/dist/components/input/DatePicker.cjs +1 -1
  43. package/dist/components/input/DatePicker.cjs.map +1 -1
  44. package/dist/components/input/DatePicker.mjs +205 -286
  45. package/dist/components/input/DatePicker.mjs.map +1 -1
  46. package/dist/components/input/Dropdown.cjs +1 -1
  47. package/dist/components/input/Dropdown.cjs.map +1 -1
  48. package/dist/components/input/Dropdown.mjs +137 -105
  49. package/dist/components/input/Dropdown.mjs.map +1 -1
  50. package/dist/components/input/Field.cjs +1 -1
  51. package/dist/components/input/Field.cjs.map +1 -1
  52. package/dist/components/input/Field.mjs +99 -66
  53. package/dist/components/input/Field.mjs.map +1 -1
  54. package/dist/components/input/Input.cjs +1 -1
  55. package/dist/components/input/Input.cjs.map +1 -1
  56. package/dist/components/input/Input.mjs +79 -55
  57. package/dist/components/input/Input.mjs.map +1 -1
  58. package/dist/components/input/Label.cjs +1 -1
  59. package/dist/components/input/Label.cjs.map +1 -1
  60. package/dist/components/input/Label.mjs +19 -13
  61. package/dist/components/input/Label.mjs.map +1 -1
  62. package/dist/components/input/Listbox.cjs +2 -0
  63. package/dist/components/input/Listbox.cjs.map +1 -0
  64. package/dist/components/input/Listbox.mjs +134 -0
  65. package/dist/components/input/Listbox.mjs.map +1 -0
  66. package/dist/components/input/Option.cjs +1 -1
  67. package/dist/components/input/Option.cjs.map +1 -1
  68. package/dist/components/input/Option.mjs +158 -97
  69. package/dist/components/input/Option.mjs.map +1 -1
  70. package/dist/components/input/Rating.cjs +1 -1
  71. package/dist/components/input/Rating.cjs.map +1 -1
  72. package/dist/components/input/Rating.item.cjs +2 -0
  73. package/dist/components/input/Rating.item.cjs.map +1 -0
  74. package/dist/components/input/Rating.item.mjs +255 -0
  75. package/dist/components/input/Rating.item.mjs.map +1 -0
  76. package/dist/components/input/Rating.mjs +150 -151
  77. package/dist/components/input/Rating.mjs.map +1 -1
  78. package/dist/components/input/SearchBox.cjs +1 -1
  79. package/dist/components/input/SearchBox.cjs.map +1 -1
  80. package/dist/components/input/SearchBox.mjs +146 -115
  81. package/dist/components/input/SearchBox.mjs.map +1 -1
  82. package/dist/components/input/Select.cjs +1 -1
  83. package/dist/components/input/Select.cjs.map +1 -1
  84. package/dist/components/input/Select.mjs +34 -25
  85. package/dist/components/input/Select.mjs.map +1 -1
  86. package/dist/components/input/Slider.cjs +1 -1
  87. package/dist/components/input/Slider.cjs.map +1 -1
  88. package/dist/components/input/Slider.mjs +77 -54
  89. package/dist/components/input/Slider.mjs.map +1 -1
  90. package/dist/components/input/SpinButton.cjs +1 -1
  91. package/dist/components/input/SpinButton.cjs.map +1 -1
  92. package/dist/components/input/SpinButton.mjs +198 -96
  93. package/dist/components/input/SpinButton.mjs.map +1 -1
  94. package/dist/components/input/SwatchPicker.cjs +1 -1
  95. package/dist/components/input/SwatchPicker.cjs.map +1 -1
  96. package/dist/components/input/SwatchPicker.context.cjs +2 -0
  97. package/dist/components/input/SwatchPicker.context.cjs.map +1 -0
  98. package/dist/components/input/SwatchPicker.context.mjs +35 -0
  99. package/dist/components/input/SwatchPicker.context.mjs.map +1 -0
  100. package/dist/components/input/SwatchPicker.mjs +131 -103
  101. package/dist/components/input/SwatchPicker.mjs.map +1 -1
  102. package/dist/components/input/SwatchPicker.swatches.cjs +2 -0
  103. package/dist/components/input/SwatchPicker.swatches.cjs.map +1 -0
  104. package/dist/components/input/SwatchPicker.swatches.mjs +207 -0
  105. package/dist/components/input/SwatchPicker.swatches.mjs.map +1 -0
  106. package/dist/components/input/Switch.cjs +1 -1
  107. package/dist/components/input/Switch.cjs.map +1 -1
  108. package/dist/components/input/Switch.mjs +71 -55
  109. package/dist/components/input/Switch.mjs.map +1 -1
  110. package/dist/components/input/TagPicker.cjs +1 -1
  111. package/dist/components/input/TagPicker.cjs.map +1 -1
  112. package/dist/components/input/TagPicker.mjs +154 -123
  113. package/dist/components/input/TagPicker.mjs.map +1 -1
  114. package/dist/components/input/Textarea.cjs +1 -1
  115. package/dist/components/input/Textarea.cjs.map +1 -1
  116. package/dist/components/input/Textarea.mjs +28 -21
  117. package/dist/components/input/Textarea.mjs.map +1 -1
  118. package/dist/components/input/TimePicker.cjs +1 -1
  119. package/dist/components/input/TimePicker.cjs.map +1 -1
  120. package/dist/components/input/TimePicker.mjs +204 -199
  121. package/dist/components/input/TimePicker.mjs.map +1 -1
  122. package/dist/components/input/dateUtils.cjs +1 -1
  123. package/dist/components/input/dateUtils.cjs.map +1 -1
  124. package/dist/components/input/dateUtils.mjs +114 -96
  125. package/dist/components/input/dateUtils.mjs.map +1 -1
  126. package/dist/components/input/fieldLabel.cjs +2 -0
  127. package/dist/components/input/fieldLabel.cjs.map +1 -0
  128. package/dist/components/input/fieldLabel.mjs +17 -0
  129. package/dist/components/input/fieldLabel.mjs.map +1 -0
  130. package/dist/components/input/inputLook.cjs +2 -0
  131. package/dist/components/input/inputLook.cjs.map +1 -0
  132. package/dist/components/input/inputLook.mjs +28 -0
  133. package/dist/components/input/inputLook.mjs.map +1 -0
  134. package/dist/components/input/pickerLabels.cjs +2 -0
  135. package/dist/components/input/pickerLabels.cjs.map +1 -0
  136. package/dist/components/input/pickerLabels.mjs +16 -0
  137. package/dist/components/input/pickerLabels.mjs.map +1 -0
  138. package/dist/components/input/pickerStyles.cjs +1 -1
  139. package/dist/components/input/pickerStyles.cjs.map +1 -1
  140. package/dist/components/input/pickerStyles.mjs +42 -4
  141. package/dist/components/input/pickerStyles.mjs.map +1 -1
  142. package/dist/components/input/pickerValues.cjs +2 -0
  143. package/dist/components/input/pickerValues.cjs.map +1 -0
  144. package/dist/components/input/pickerValues.mjs +24 -0
  145. package/dist/components/input/pickerValues.mjs.map +1 -0
  146. package/dist/components/navigation/Menu.popover.cjs +1 -1
  147. package/dist/components/navigation/Menu.popover.cjs.map +1 -1
  148. package/dist/components/navigation/Menu.popover.mjs +10 -10
  149. package/dist/components/navigation/Menu.root.cjs +1 -1
  150. package/dist/components/navigation/Menu.root.cjs.map +1 -1
  151. package/dist/components/navigation/Menu.root.mjs +10 -10
  152. package/dist/components/overlays/Popover.cjs +1 -1
  153. package/dist/components/overlays/Popover.cjs.map +1 -1
  154. package/dist/components/overlays/Popover.mjs +203 -208
  155. package/dist/components/overlays/Popover.mjs.map +1 -1
  156. package/dist/components/overlays/Popover.shared.cjs +1 -1
  157. package/dist/components/overlays/Popover.shared.cjs.map +1 -1
  158. package/dist/components/overlays/Popover.shared.mjs +82 -77
  159. package/dist/components/overlays/Popover.shared.mjs.map +1 -1
  160. package/dist/components/provider/WaveProvider.cjs +1 -1
  161. package/dist/components/provider/WaveProvider.cjs.map +1 -1
  162. package/dist/components/provider/WaveProvider.mjs +25 -19
  163. package/dist/components/provider/WaveProvider.mjs.map +1 -1
  164. package/dist/components/table/useGridNavigation.cjs +1 -1
  165. package/dist/components/table/useGridNavigation.cjs.map +1 -1
  166. package/dist/components/table/useGridNavigation.mjs +67 -70
  167. package/dist/components/table/useGridNavigation.mjs.map +1 -1
  168. package/dist/hooks/useActiveDescendant.cjs +2 -0
  169. package/dist/hooks/useActiveDescendant.cjs.map +1 -0
  170. package/dist/hooks/useActiveDescendant.mjs +56 -0
  171. package/dist/hooks/useActiveDescendant.mjs.map +1 -0
  172. package/dist/hooks/useFieldControl.cjs.map +1 -1
  173. package/dist/hooks/useFieldControl.mjs.map +1 -1
  174. package/dist/hooks/useListbox.cjs +1 -1
  175. package/dist/hooks/useListbox.cjs.map +1 -1
  176. package/dist/hooks/useListbox.mjs +250 -210
  177. package/dist/hooks/useListbox.mjs.map +1 -1
  178. package/dist/hooks/useRovingGrid.cjs +2 -0
  179. package/dist/hooks/useRovingGrid.cjs.map +1 -0
  180. package/dist/hooks/useRovingGrid.mjs +69 -0
  181. package/dist/hooks/useRovingGrid.mjs.map +1 -0
  182. package/dist/index.cjs +1 -1
  183. package/dist/index.d.cts +2901 -203
  184. package/dist/index.d.ts +2901 -203
  185. package/dist/index.mjs +107 -99
  186. package/dist/lib/classNames.cjs +1 -1
  187. package/dist/lib/classNames.cjs.map +1 -1
  188. package/dist/lib/classNames.mjs +111 -67
  189. package/dist/lib/classNames.mjs.map +1 -1
  190. package/dist/lib/date.cjs +2 -0
  191. package/dist/lib/date.cjs.map +1 -0
  192. package/dist/lib/date.mjs +44 -0
  193. package/dist/lib/date.mjs.map +1 -0
  194. package/dist/lib/focus.cjs +1 -1
  195. package/dist/lib/focus.cjs.map +1 -1
  196. package/dist/lib/focus.mjs +5 -2
  197. package/dist/lib/focus.mjs.map +1 -1
  198. package/dist/lib/layers.cjs.map +1 -1
  199. package/dist/lib/layers.mjs.map +1 -1
  200. package/dist/lib/styles.cjs +1 -1
  201. package/dist/lib/styles.cjs.map +1 -1
  202. package/dist/lib/styles.mjs +21 -4
  203. package/dist/lib/styles.mjs.map +1 -1
  204. package/dist/styles.css +1 -1
  205. package/package.json +1 -1
  206. package/src/styles/tokens.css +13 -0
@@ -6,13 +6,13 @@ import { hsvToHex as r } from "../../lib/color.mjs";
6
6
  import { useEventCallback as i } from "../../hooks/useEventCallback.mjs";
7
7
  import { getArrowIntent as a, getDirection as o } from "../../lib/direction.mjs";
8
8
  import { useMergedRefs as s } from "../../hooks/useMergedRefs.mjs";
9
- import { useFieldContext as ee, useFieldControl as c } from "../../hooks/useFieldControl.mjs";
10
- import { useMediaQuery as l } from "../../hooks/useMediaQuery.mjs";
11
- import { useFormReset as u } from "../../hooks/useFormReset.mjs";
12
- import { HiddenInput as te } from "../internal/HiddenInput.mjs";
13
- import { COLOR_THUMB_CLASSES as ne, areaValueText as d, colorAreaGradient as re, displayColor as ie, toPercent as f, toPosition as p } from "./colorUtils.mjs";
14
- import { useColorPartState as m } from "./ColorPicker.parts.mjs";
15
- import { isOwnEvent as h } from "../../lib/events.mjs";
9
+ import { useFieldContext as ee, useFieldControl as te } from "../../hooks/useFieldControl.mjs";
10
+ import { useMediaQuery as c } from "../../hooks/useMediaQuery.mjs";
11
+ import { useFormReset as l } from "../../hooks/useFormReset.mjs";
12
+ import { HiddenInput as ne } from "../internal/HiddenInput.mjs";
13
+ import { isOwnEvent as u } from "../../lib/events.mjs";
14
+ import { COLOR_THUMB_CLASSES as re, areaValueText as d, colorAreaGradient as ie, displayColor as f, toPercent as p, toPosition as m } from "./colorUtils.mjs";
15
+ import { useColorPartState as h } from "./ColorPicker.parts.mjs";
16
16
  import * as g from "react";
17
17
  import { jsx as _, jsxs as ae } from "react/jsx-runtime";
18
18
  //#region src/components/input/ColorArea.tsx
@@ -25,7 +25,7 @@ function v(e) {
25
25
  return Math.min(100, Math.max(0, e));
26
26
  }
27
27
  var se = "(pointer: coarse)", y = ({ value: y, defaultValue: ce, onValueChange: le, shape: ue, labels: de, disabled: fe = !1, name: pe, form: b, required: me, controlRef: he, className: ge, style: _e, id: ve, "aria-label": ye, "aria-labelledby": x, "aria-describedby": S, "aria-invalid": C, "aria-required": w, "aria-errormessage": T, autoFocus: E, tabIndex: D, onKeyDown: O, onPointerDown: k, onPointerMove: A, ref: j, ...M }) => {
28
- let N = m({
28
+ let N = h({
29
29
  value: y,
30
30
  defaultValue: ce,
31
31
  onValueChange: le,
@@ -40,18 +40,18 @@ var se = "(pointer: coarse)", y = ({ value: y, defaultValue: ce, onValueChange:
40
40
  valueText: P.labels.valueText
41
41
  },
42
42
  ...de
43
- }, be = ue ?? P?.shape ?? "rounded", I = N.color, L = ie(I), R = f(L.s), z = f(L.v), [B, V] = g.useState("saturation"), xe = l(se), H = g.useRef(null), [U, Se] = g.useState(0), W = g.useRef(null), G = g.useRef(null), K = g.useRef(null), Ce = s(j, W), we = s(G, he), q = g.useRef(0);
43
+ }, be = ue ?? P?.shape ?? "rounded", I = N.color, L = f(I), R = p(L.s), z = p(L.v), [B, V] = g.useState("saturation"), xe = c(se), H = g.useRef(null), [U, Se] = g.useState(0), W = g.useRef(null), G = g.useRef(null), K = g.useRef(null), Ce = s(j, W), we = s(G, he), q = g.useRef(0);
44
44
  g.useLayoutEffect(() => {
45
45
  q.current !== U && (q.current = U, (B === "saturation" ? G : K).current?.focus({ preventScroll: !0 }));
46
46
  }, [B, U]);
47
- let Te = ee(), { "aria-invalid": J, "aria-required": Ee, required: De, ...Oe } = c({
47
+ let Te = ee(), { "aria-invalid": J, "aria-required": Ee, required: De, ...Oe } = te({
48
48
  id: ve,
49
49
  "aria-label": ye ?? (P && x === void 0 ? P.labels.area : void 0),
50
50
  "aria-labelledby": x,
51
51
  "aria-describedby": S,
52
52
  "aria-invalid": C
53
53
  }, { labelable: !1 }), ke = J !== void 0 && J !== !1 && J !== "false" && T || void 0, Ae = me ?? (w === !0 || w === "true" || (Te?.required ?? !1));
54
- u(W, N.reset, b);
54
+ l(W, N.reset, b);
55
55
  let Y = (e, t) => {
56
56
  t !== (e === "saturation" ? R : z) && N.setColor(e === "saturation" ? {
57
57
  ...I,
@@ -61,7 +61,7 @@ var se = "(pointer: coarse)", y = ({ value: y, defaultValue: ce, onValueChange:
61
61
  v: t / 100
62
62
  });
63
63
  }, X = t(O, (e) => {
64
- if (N.disabled || !h(e) || e.nativeEvent.isComposing || e.altKey || e.ctrlKey || e.metaKey) return;
64
+ if (N.disabled || !u(e) || e.nativeEvent.isComposing || e.altKey || e.ctrlKey || e.metaKey) return;
65
65
  let t = e.shiftKey ? 10 : 1, n, r;
66
66
  switch (e.key) {
67
67
  case "ArrowLeft":
@@ -115,7 +115,7 @@ var se = "(pointer: coarse)", y = ({ value: y, defaultValue: ce, onValueChange:
115
115
  focusVisible: !1
116
116
  });
117
117
  }), Pe = t(k, (e) => {
118
- !N.disabled && e.button === 0 && e.isPrimary && h(e) && (e.preventDefault(), e.currentTarget.setPointerCapture(e.pointerId), Z(e), Ne());
118
+ !N.disabled && e.button === 0 && e.isPrimary && u(e) && (e.preventDefault(), e.currentTarget.setPointerCapture(e.pointerId), Z(e), Ne());
119
119
  }), Fe = t(A, (e) => {
120
120
  !N.disabled && e.currentTarget.hasPointerCapture(e.pointerId) && Z(e);
121
121
  }), Q = {
@@ -125,9 +125,9 @@ var se = "(pointer: coarse)", y = ({ value: y, defaultValue: ce, onValueChange:
125
125
  valueText: F.valueText
126
126
  }, Ie = {
127
127
  ..._e,
128
- "--wave-color-area-gradient": re(L.h),
129
- "--wave-color-area-x": p(L.s),
130
- "--wave-color-area-y": p(L.v),
128
+ "--wave-color-area-gradient": ie(L.h),
129
+ "--wave-color-area-x": m(L.s),
130
+ "--wave-color-area-y": m(L.v),
131
131
  "--wave-color-thumb": r({
132
132
  h: L.h,
133
133
  s: L.s,
@@ -167,7 +167,7 @@ var se = "(pointer: coarse)", y = ({ value: y, defaultValue: ce, onValueChange:
167
167
  }),
168
168
  /* @__PURE__ */ _("span", {
169
169
  "aria-hidden": "true",
170
- className: e(n.thumb, ne, "start-(--wave-color-area-x) bottom-(--wave-color-area-y) -translate-x-1/2 wave-rtl:translate-x-1/2 translate-y-1/2", "group-has-[:focus-visible]/color-area:ring-2 group-has-[:focus-visible]/color-area:ring-background forced-colors:group-has-[:focus-visible]/color-area:ring-[Canvas] group-has-[:focus-visible]/color-area:outline-2 group-has-[:focus-visible]/color-area:outline-offset-2 group-has-[:focus-visible]/color-area:outline-ring forced-colors:group-has-[:focus-visible]/color-area:outline-[Highlight]")
170
+ className: e(n.thumb, re, "start-(--wave-color-area-x) bottom-(--wave-color-area-y) -translate-x-1/2 wave-rtl:translate-x-1/2 translate-y-1/2", "group-has-[:focus-visible]/color-area:ring-2 group-has-[:focus-visible]/color-area:ring-background forced-colors:group-has-[:focus-visible]/color-area:ring-[Canvas] group-has-[:focus-visible]/color-area:outline-2 group-has-[:focus-visible]/color-area:outline-offset-2 group-has-[:focus-visible]/color-area:outline-ring forced-colors:group-has-[:focus-visible]/color-area:outline-[Highlight]")
171
171
  }),
172
172
  /* @__PURE__ */ _("input", {
173
173
  ...$("saturation"),
@@ -185,7 +185,7 @@ var se = "(pointer: coarse)", y = ({ value: y, defaultValue: ce, onValueChange:
185
185
  "aria-orientation": "vertical",
186
186
  "aria-valuetext": d(L, "value", Q)
187
187
  }),
188
- !P && /* @__PURE__ */ _(te, {
188
+ !P && /* @__PURE__ */ _(ne, {
189
189
  type: "text",
190
190
  name: pe,
191
191
  form: b,
@@ -1 +1 @@
1
- {"version":3,"file":"ColorArea.mjs","names":["React","DEFAULT_LABELS","clampPercent","value","COARSE_POINTER","ColorArea","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaRequired","ariaErrorMessage","rest","part","useColorPartState","strings","picker","labels","resolvedShape","shape","color","shown","displayColor","saturation","toPercent","brightness","activeAxis","setActiveAxis","coarsePointer","useMediaQuery","fieldRef","focusToken","setFocusToken","rootRef","saturationRef","brightnessRef","mergedRootRef","useMergedRefs","ref","mergedSaturationRef","controlRef","handledFocusTokenRef","field","useFieldContext","invalid","_ariaRequired","_required","groupProps","useFieldControl","errorMessageId","isRequired","required","form","applyAxis","percent","axis","handleKeyDown","composeEventHandlers","onKeyDown","isOwnEvent","event","step","next","intent","getArrowIntent","getDirection","token","handleInputChange","handleInputFocus","moveToPointer","useEventCallback","fieldElement","rect","x","s","v","focusActiveAxis","handlePointerDown","onPointerDown","handlePointerMove","onPointerMove","textLabels","areaStyle","style","colorAreaGradient","toPosition","hsvToHex","inputProps","tabIndex","cn","colorAreaClassNames","className","COLOR_THUMB_CLASSES","areaValueText","HiddenInput"],"sources":["../../../src/components/input/ColorArea.tsx"],"sourcesContent":["import * as React from 'react';\nimport { colorAreaClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { hsvToHex } from '../../lib/color';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { getArrowIntent, getDirection } from '../../lib/direction';\nimport { isOwnEvent } from '../../lib/events';\nimport type { ColorPickerShape, HsvColor } from '../../lib/types';\nimport { useEventCallback } from '../../hooks/useEventCallback';\nimport { useFieldContext, useFieldControl } from '../../hooks/useFieldControl';\nimport { useFormReset } from '../../hooks/useFormReset';\nimport { useMediaQuery } from '../../hooks/useMediaQuery';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { HiddenInput } from '../internal/HiddenInput';\nimport { useColorPartState } from './ColorPicker.parts';\nimport {\n COLOR_THUMB_CLASSES,\n areaValueText,\n colorAreaGradient,\n displayColor,\n toPercent,\n toPosition,\n} from './colorUtils';\n\n/** Texts of a ColorArea, for localisation. Every key is optional. */\nexport interface ColorAreaLabels {\n /** Name of the horizontal slider.\n * @default 'Saturation'\n */\n saturation?: string;\n /** Name of the vertical slider (the `value` channel).\n * @default 'Brightness'\n */\n brightness?: string;\n /** Role description of both sliders.\n * @default '2D slider'\n */\n roleDescription?: string;\n /** Names the color at the end of each value text; return `''` to leave it out.\n * @default an English namer (\"dark blue\")\n */\n colorName?: (color: HsvColor) => string;\n /** Replaces a whole value text, for languages whose order differs. */\n valueText?: (color: HsvColor, channel: 'saturation' | 'value') => string;\n}\n\n/** Properties for the ColorArea component. */\nexport interface ColorAreaProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'defaultValue' | 'onChange'\n> {\n /**\n * The color (Fluent's `color`). Inside a ColorPicker, leave `value` and `defaultValue` out to\n * bind the area to the picker.\n */\n value?: HsvColor;\n /**\n * Initial color for uncontrolled usage (also what a form reset restores).\n * @default the brand blue, `{ h: 208, s: 0.92, v: 0.74 }` (`#0f6cbd`)\n */\n defaultValue?: HsvColor;\n /**\n * Called with the new color on every step (a key, a pointer move or assistive technology) that\n * changes it (Fluent's `onChange`). A bound area calls it too.\n */\n onValueChange?: (value: HsvColor) => void;\n /**\n * `'square'` removes the corner radius (the thumb stays round). Bound to a ColorPicker, the\n * picker's shape unless you pass one.\n * @default 'rounded'\n */\n shape?: ColorPickerShape;\n /** Texts of the area; bound to a ColorPicker, the picker's `labels` fill the keys you leave out. */\n labels?: ColorAreaLabels;\n /**\n * Unavailable: both inputs are natively disabled, pointer presses are ignored and the area is\n * dimmed. A bound area is also disabled while the picker's value is not a hex color.\n * @default false\n */\n disabled?: boolean;\n /** Form field name: the color is submitted as hex (`hsvToHex`). Ignored while bound to a ColorPicker. */\n name?: string;\n /** Id of the form the area belongs to, when it is rendered outside that form. */\n form?: string;\n /**\n * Marks the hidden form input required (a color is always set, so it never blocks). A consumer\n * `aria-required` does the same: a group supports neither, so neither is set on it.\n */\n required?: boolean;\n /** Ref to the saturation `<input type=\"range\">`. */\n controlRef?: React.Ref<HTMLInputElement>;\n /** Ref to the root `role=\"group\"` element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** The two axes: saturation (x) and brightness (y, the `value` channel). */\ntype AreaAxis = 'saturation' | 'value';\n\nconst DEFAULT_LABELS = {\n saturation: 'Saturation',\n brightness: 'Brightness',\n roleDescription: '2D slider',\n} as const;\n\n/** A whole percentage clamped to 0–100. */\nfunction clampPercent(value: number): number {\n return Math.min(100, Math.max(0, value));\n}\n\n/** Touch-primary devices expose both inputs, so a touch screen reader can swipe each (D19). */\nconst COARSE_POINTER = '(pointer: coarse)';\n\n/**\n * A 2-D color field: saturation from left to right (mirrored in right-to-left layouts) and\n * brightness from bottom to top, at the value's hue. ArrowLeft and ArrowRight move saturation by\n * 1 %, ArrowUp and ArrowDown brightness; Shift with an arrow moves by 10, Page Up and Page Down\n * move brightness by 10, and Home and End set saturation to 0 and 100. A press or drag (mouse,\n * touch or pen) moves the thumb to the pointer. It is one Tab stop holding two sliders for\n * assistive technology, \"Saturation\" and \"Brightness\", whose value texts start with their own\n * channel and name the color; focus follows the axis a key moves, and unless the primary pointer\n * is coarse (touch), only the slider with the Tab stop is exposed. Inside a ColorPicker, leave\n * `value` and `defaultValue` out and it binds to the picker. Fluent's\n * `ColorArea`, with `value`/`onValueChange` for its `color`/`onChange`.\n *\n * @example\n * <ColorArea aria-label=\"Accent color\" value={color} onValueChange={setColor} />\n */\nexport const ColorArea = ({\n value,\n defaultValue,\n onValueChange,\n shape,\n labels,\n disabled = false,\n name,\n form,\n required,\n controlRef,\n className,\n style,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n 'aria-errormessage': ariaErrorMessage,\n autoFocus,\n tabIndex,\n onKeyDown,\n onPointerDown,\n onPointerMove,\n ref,\n ...rest\n}: ColorAreaProps) => {\n const part = useColorPartState({ value, defaultValue, onValueChange, disabled });\n const { picker } = part;\n const strings = {\n ...DEFAULT_LABELS,\n ...(picker && {\n saturation: picker.labels.saturation,\n brightness: picker.labels.brightness,\n roleDescription: picker.labels.roleDescription,\n colorName: picker.labels.colorName,\n valueText: picker.labels.valueText,\n }),\n ...labels,\n };\n const resolvedShape = shape ?? picker?.shape ?? 'rounded';\n const color = part.color;\n const shown = displayColor(color);\n const saturation = toPercent(shown.s);\n const brightness = toPercent(shown.v);\n\n const [activeAxis, setActiveAxis] = React.useState<AreaAxis>('saturation');\n const coarsePointer = useMediaQuery(COARSE_POINTER);\n const fieldRef = React.useRef<HTMLDivElement>(null);\n // Bumped on every handled key (not only an axis change), so the layout effect below moves focus\n // to the axis's input even when the key's axis is the one an earlier assistive-technology change\n // already made the Tab stop, without moving focus; focusing an input that already has focus does\n // nothing. Never bumped for an AT-driven change (`handleInputChange`) or a real focus event. A\n // plain counter, not a ref: react-hooks/refs only allows a ref's `current` to be touched from an\n // effect, a ref callback or a function assigned directly to a JSX handler prop, not one passed\n // through `composeEventHandlers`.\n const [focusToken, setFocusToken] = React.useState(0);\n const rootRef = React.useRef<HTMLDivElement>(null);\n const saturationRef = React.useRef<HTMLInputElement>(null);\n const brightnessRef = React.useRef<HTMLInputElement>(null);\n const mergedRootRef = useMergedRefs(ref, rootRef);\n const mergedSaturationRef = useMergedRefs(saturationRef, controlRef);\n /** The last `focusToken` this component already moved focus for (read/written in the effect only). */\n const handledFocusTokenRef = React.useRef(0);\n\n React.useLayoutEffect(() => {\n if (handledFocusTokenRef.current === focusToken) return;\n handledFocusTokenRef.current = focusToken;\n (activeAxis === 'saturation' ? saturationRef : brightnessRef).current?.focus({\n preventScroll: true,\n });\n }, [activeAxis, focusToken]);\n\n const field = useFieldContext();\n const fieldProps = useFieldControl(\n {\n id,\n 'aria-label':\n ariaLabel ?? (picker && ariaLabelledBy === undefined ? picker.labels.area : undefined),\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n },\n { labelable: false },\n );\n // A group supports neither aria-invalid, aria-required nor `required` (ARIA 1.2): the invalid\n // state goes to both inputs and the required state to the hidden input.\n const {\n 'aria-invalid': invalid,\n 'aria-required': _ariaRequired,\n required: _required,\n ...groupProps\n } = fieldProps;\n const isInvalid = invalid !== undefined && invalid !== false && invalid !== 'false';\n const errorMessageId = (isInvalid && ariaErrorMessage) || undefined;\n const isRequired =\n required ?? (ariaRequired === true || ariaRequired === 'true' || (field?.required ?? false));\n\n useFormReset(rootRef, part.reset, form);\n\n /** Applies a whole percentage to one axis, keeping the other channels as given. */\n const applyAxis = (axis: AreaAxis, percent: number) => {\n if (percent === (axis === 'saturation' ? saturation : brightness)) return;\n part.setColor(\n axis === 'saturation' ? { ...color, s: percent / 100 } : { ...color, v: percent / 100 },\n );\n };\n\n const handleKeyDown = composeEventHandlers(\n onKeyDown,\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (part.disabled || !isOwnEvent(event) || event.nativeEvent.isComposing) return;\n // A key with Alt, Ctrl or Meta belongs to the browser (Alt+Left is \"back\").\n if (event.altKey || event.ctrlKey || event.metaKey) return;\n const step = event.shiftKey ? 10 : 1;\n let axis: AreaAxis;\n let next: number;\n switch (event.key) {\n case 'ArrowLeft':\n case 'ArrowRight': {\n const intent = getArrowIntent(event.key, {\n orientation: 'horizontal',\n dir: getDirection(event.currentTarget),\n });\n axis = 'saturation';\n next = saturation + (intent === 'next' ? step : -step);\n break;\n }\n case 'ArrowUp':\n axis = 'value';\n next = brightness + step;\n break;\n case 'ArrowDown':\n axis = 'value';\n next = brightness - step;\n break;\n case 'PageUp':\n axis = 'value';\n next = brightness + 10;\n break;\n case 'PageDown':\n axis = 'value';\n next = brightness - 10;\n break;\n case 'Home':\n axis = 'saturation';\n next = 0;\n break;\n case 'End':\n axis = 'saturation';\n next = 100;\n break;\n default:\n return;\n }\n // Prevented, so the native range input never moves on its own.\n event.preventDefault();\n if (axis !== activeAxis) setActiveAxis(axis);\n // Every handled key moves focus to its axis's input, even when an earlier\n // assistive-technology change already made that axis the Tab stop.\n setFocusToken((token) => token + 1);\n applyAxis(axis, clampPercent(next));\n },\n );\n\n /** A change event from assistive technology (a swipe): that input becomes the Tab stop. */\n const handleInputChange = (axis: AreaAxis) => (event: React.ChangeEvent<HTMLInputElement>) => {\n if (part.disabled) return;\n if (axis !== activeAxis) setActiveAxis(axis);\n applyAxis(axis, clampPercent(Math.round(Number(event.currentTarget.value))));\n };\n\n const handleInputFocus = (axis: AreaAxis) => () => {\n if (axis !== activeAxis) setActiveAxis(axis);\n };\n\n // Both read a ref (`fieldRef`, or `saturationRef`/`brightnessRef`): `useEventCallback` (a custom\n // hook, opaque to react-hooks/refs) keeps that safe to call from the handler below, unlike a\n // plain function or `React.useCallback` passed into the generic `composeEventHandlers`.\n /** Moves the thumb to the pointer: saturation along x (mirrored in RTL), brightness along y. */\n const moveToPointer = useEventCallback((event: React.PointerEvent<HTMLDivElement>) => {\n const fieldElement = fieldRef.current;\n if (!fieldElement) return;\n const rect = fieldElement.getBoundingClientRect();\n if (rect.width <= 0 || rect.height <= 0) return;\n const x = Math.min(1, Math.max(0, (event.clientX - rect.left) / rect.width));\n const s = getDirection(event.currentTarget) === 'rtl' ? 1 - x : x;\n const v = Math.min(1, Math.max(0, 1 - (event.clientY - rect.top) / rect.height));\n if (s === shown.s && v === shown.v) return;\n part.setColor({ ...color, s, v });\n });\n /**\n * Focuses the input of the active axis (the press moves focus there instead of the point),\n * without the focus ring: Chromium treats this script focus as keyboard focus, where the\n * browser's own focus of a pressed control shows none. Browsers without the `focusVisible`\n * option ignore it.\n */\n const focusActiveAxis = useEventCallback(() => {\n const options: FocusOptions = { preventScroll: true, focusVisible: false };\n (activeAxis === 'saturation' ? saturationRef : brightnessRef).current?.focus(options);\n });\n\n const handlePointerDown = composeEventHandlers(\n onPointerDown,\n (event: React.PointerEvent<HTMLDivElement>) => {\n if (part.disabled || event.button !== 0 || !event.isPrimary || !isOwnEvent(event)) return;\n // No text selection and no focus move of the press: focus goes to the Tab stop instead.\n event.preventDefault();\n event.currentTarget.setPointerCapture(event.pointerId);\n moveToPointer(event);\n focusActiveAxis();\n },\n );\n\n // The drag lasts while the root holds the pointer; losing the capture (pointerup,\n // lostpointercapture) ends it.\n const handlePointerMove = composeEventHandlers(\n onPointerMove,\n (event: React.PointerEvent<HTMLDivElement>) => {\n if (part.disabled || !event.currentTarget.hasPointerCapture(event.pointerId)) return;\n moveToPointer(event);\n },\n );\n\n const textLabels = {\n saturation: strings.saturation,\n brightness: strings.brightness,\n colorName: strings.colorName,\n valueText: strings.valueText,\n };\n\n const areaStyle = {\n ...style,\n '--wave-color-area-gradient': colorAreaGradient(shown.h),\n '--wave-color-area-x': toPosition(shown.s),\n '--wave-color-area-y': toPosition(shown.v),\n '--wave-color-thumb': hsvToHex({ h: shown.h, s: shown.s, v: shown.v }),\n } as React.CSSProperties;\n\n const inputProps = (axis: AreaAxis) => ({\n type: 'range' as const,\n min: 0,\n max: 100,\n step: 1,\n disabled: part.disabled,\n 'aria-roledescription': strings.roleDescription,\n 'aria-invalid': invalid,\n 'aria-errormessage': errorMessageId,\n // One Tab stop: the input used last (C-ROUTING: a consumer tabIndex applies to it).\n tabIndex: axis === activeAxis ? (tabIndex ?? 0) : -1,\n // Where the primary pointer is not coarse, desktop screen readers meet one 2-D slider: the\n // input without the Tab stop is hidden (it stays focusable by script, never by Tab).\n 'aria-hidden': axis !== activeAxis && !coarsePointer ? true : undefined,\n onChange: handleInputChange(axis),\n onFocus: handleInputFocus(axis),\n className: 'sr-only',\n });\n\n return (\n <div\n role=\"group\"\n data-disabled={part.disabled ? '' : undefined}\n {...groupProps}\n className={cn(\n colorAreaClassNames.root,\n 'group/color-area relative h-40 w-full min-w-40 touch-none select-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50',\n resolvedShape === 'square' ? 'rounded-none' : 'rounded',\n className,\n )}\n style={areaStyle}\n {...rest}\n ref={mergedRootRef}\n onKeyDown={handleKeyDown}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n >\n <div\n ref={fieldRef}\n aria-hidden=\"true\"\n className={cn(\n colorAreaClassNames.field,\n 'absolute inset-0 rounded-[inherit] bg-(image:--wave-color-area-gradient) wave-rtl:-scale-x-100 forced-colors:forced-color-adjust-none',\n )}\n />\n <span\n aria-hidden=\"true\"\n className={cn(\n colorAreaClassNames.thumb,\n COLOR_THUMB_CLASSES,\n 'start-(--wave-color-area-x) bottom-(--wave-color-area-y) -translate-x-1/2 wave-rtl:translate-x-1/2 translate-y-1/2',\n 'group-has-[:focus-visible]/color-area:ring-2 group-has-[:focus-visible]/color-area:ring-background forced-colors:group-has-[:focus-visible]/color-area:ring-[Canvas] group-has-[:focus-visible]/color-area:outline-2 group-has-[:focus-visible]/color-area:outline-offset-2 group-has-[:focus-visible]/color-area:outline-ring forced-colors:group-has-[:focus-visible]/color-area:outline-[Highlight]',\n )}\n />\n <input\n {...inputProps('saturation')}\n ref={mergedSaturationRef}\n value={saturation}\n aria-label={strings.saturation}\n aria-valuetext={areaValueText(shown, 'saturation', textLabels)}\n autoFocus={autoFocus}\n />\n <input\n {...inputProps('value')}\n ref={brightnessRef}\n value={brightness}\n aria-label={strings.brightness}\n aria-orientation=\"vertical\"\n aria-valuetext={areaValueText(shown, 'value', textLabels)}\n />\n {!picker && (\n <HiddenInput\n type=\"text\"\n name={name}\n form={form}\n disabled={part.disabled}\n value={hsvToHex(color)}\n required={isRequired}\n onInvalid={() =>\n (activeAxis === 'saturation' ? saturationRef : brightnessRef).current?.focus()\n }\n />\n )}\n </div>\n );\n};\n\nColorArea.displayName = 'ColorArea';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkGA,IAAMC,KAAiB;CACrB,YAAY;CACZ,YAAY;CACZ,iBAAiB;AACnB;AAGA,SAASC,EAAa,GAAuB;CAC3C,OAAO,KAAK,IAAI,KAAK,KAAK,IAAI,GAAGC,CAAK,CAAC;AACzC;AAGA,IAAMC,KAAiB,qBAiBVC,KAAa,EACxB,UACA,kBACA,mBACA,WACA,YACA,eAAW,IACX,UACA,SACA,cACA,gBACA,eACA,WACA,QACA,cAAcC,IACd,mBAAmBC,GACnB,oBAAoBC,GACpB,gBAAgBC,GAChB,iBAAiBC,GACjB,qBAAqBC,GACrB,cACA,aACA,cACA,kBACA,kBACA,QACA,GAAGC,QACiB;CACpB,IAAMC,IAAOC,EAAkB;EAAE;EAAO;EAAc;EAAe;CAAS,CAAC,GACzE,EAAE,cAAWD,GACbE,IAAU;EACd,GAAGd;EACH,GAAIe,KAAU;GACZ,YAAYA,EAAO,OAAO;GAC1B,YAAYA,EAAO,OAAO;GAC1B,iBAAiBA,EAAO,OAAO;GAC/B,WAAWA,EAAO,OAAO;GACzB,WAAWA,EAAO,OAAO;EAC3B;EACA,GAAGC;CACL,GACMC,KAAgBC,MAASH,GAAQ,SAAS,WAC1CI,IAAQP,EAAK,OACbQ,IAAQC,GAAaF,CAAK,GAC1BG,IAAaC,EAAUH,EAAM,CAAC,GAC9BI,IAAaD,EAAUH,EAAM,CAAC,GAE9B,CAACK,GAAYC,KAAiB3B,EAAM,SAAmB,YAAY,GACnE4B,KAAgBC,EAAczB,EAAc,GAC5C0B,IAAW9B,EAAM,OAAuB,IAAI,GAQ5C,CAAC+B,GAAYC,MAAiBhC,EAAM,SAAS,CAAC,GAC9CiC,IAAUjC,EAAM,OAAuB,IAAI,GAC3CkC,IAAgBlC,EAAM,OAAyB,IAAI,GACnDmC,IAAgBnC,EAAM,OAAyB,IAAI,GACnDoC,KAAgBC,EAAcC,GAAKL,CAAO,GAC1CM,KAAsBF,EAAcH,GAAeM,EAAU,GAE7DC,IAAuBzC,EAAM,OAAO,CAAC;CAE3C,EAAM,sBAAsB;EAC1B,AAAIyC,EAAqB,YAAYV,MACrC,EAAqB,UAAUA,IAC9BL,MAAe,eAAeQ,IAAgBC,EAAA,CAAe,SAAS,MAAM,EAC3E,eAAe,GACjB,CAAC;CACH,GAAG,CAACT,GAAYK,CAAU,CAAC;CAE3B,IAAMW,KAAQC,GAAgB,GAcxB,EACJ,gBAAgBC,GAChB,iBAAiBC,IACjB,UAAUC,IACV,GAAGC,OAjBcC,EACjB;EACE;EACA,cACE1C,OAAcU,KAAUT,MAAmB,KAAA,IAAYS,EAAO,OAAO,OAAO,KAAA;EAC9E,mBAAmBT;EACnB,oBAAoBC;EACpB,gBAAgBC;CAClB,GACA,EAAE,WAAW,GAAM,CASjB,GAEEwC,KADYL,MAAY,KAAA,KAAaA,MAAY,MAASA,MAAY,WACvCjC,KAAqB,KAAA,GACpDuC,KACJC,OAAazC,MAAiB,MAAQA,MAAiB,WAAWgC,IAAO,YAAY;CAEvF,EAAaT,GAASpB,EAAK,OAAOuC,CAAI;CAGtC,IAAMC,KAAa,GAAgB,MAAoB;EACrD,AAAIC,OAAaC,MAAS,eAAehC,IAAaE,MACtDZ,EAAK,SACH0C,MAAS,eAAe;GAAE,GAAGnC;GAAO,GAAGkC,IAAU;EAAI,IAAI;GAAE,GAAGlC;GAAO,GAAGkC,IAAU;EAAI,CACxF;CACF,GAEME,IAAgBC,EACpBC,IACC,MAA+C;EAG9C,IAFI7C,EAAK,YAAY,CAAC8C,EAAWC,CAAK,KAAKA,EAAM,YAAY,eAEzDA,EAAM,UAAUA,EAAM,WAAWA,EAAM,SAAS;EACpD,IAAMC,IAAOD,EAAM,WAAW,KAAK,GAC/BL,GACAO;EACJ,QAAQF,EAAM,KAAd;GACE,KAAK;GACL,KAAK,cAAc;IACjB,IAAMG,IAASC,EAAeJ,EAAM,KAAK;KACvC,aAAa;KACb,KAAKK,EAAaL,EAAM,aAAa;IACvC,CAAC;IAED,AADA,IAAO,cACP,IAAOrC,KAAcwC,MAAW,SAASF,IAAO,CAACA;IACjD;GACF;GACA,KAAK;IAEH,AADA,IAAO,SACP,IAAOpC,IAAaoC;IACpB;GACF,KAAK;IAEH,AADA,IAAO,SACP,IAAOpC,IAAaoC;IACpB;GACF,KAAK;IAEH,AADA,IAAO,SACP,IAAOpC,IAAa;IACpB;GACF,KAAK;IAEH,AADA,IAAO,SACP,IAAOA,IAAa;IACpB;GACF,KAAK;IAEH,AADA,IAAO,cACP,IAAO;IACP;GACF,KAAK;IAEH,AADA,IAAO,cACP,IAAO;IACP;GACF,SACE;EACJ;EAOA,AALAmC,EAAM,eAAe,GACjBL,MAAS7B,KAAYC,EAAc4B,CAAI,GAG3CvB,IAAe,MAAUkC,IAAQ,CAAC,GAClCb,EAAUE,GAAMrD,EAAa4D,CAAI,CAAC;CACpC,CACF,GAGMK,MAAqB,OAAoB,MAA+C;EAC5F,AAAItD,EAAK,aACL0C,MAAS7B,KAAYC,EAAc4B,CAAI,GAC3CF,EAAUE,GAAMrD,EAAa,KAAK,MAAM,OAAO0D,EAAM,cAAc,KAAK,CAAC,CAAC,CAAC;CAC7E,GAEMQ,MAAoB,YAAyB;EACjD,AAAIb,MAAS7B,KAAYC,EAAc4B,CAAI;CAC7C,GAMMc,IAAgBC,GAAkB,MAA8C;EACpF,IAAMC,IAAezC,EAAS;EAC9B,IAAI,CAACyC,GAAc;EACnB,IAAMC,IAAOD,EAAa,sBAAsB;EAChD,IAAIC,EAAK,SAAS,KAAKA,EAAK,UAAU,GAAG;EACzC,IAAMC,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,IAAIb,EAAM,UAAUY,EAAK,QAAQA,EAAK,KAAK,CAAC,GACrEE,IAAIT,EAAaL,EAAM,aAAa,MAAM,QAAQ,IAAIa,IAAIA,GAC1DE,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAKf,EAAM,UAAUY,EAAK,OAAOA,EAAK,MAAM,CAAC;EAC/E,CAAIE,MAAMrD,EAAM,KAAKsD,MAAMtD,EAAM,MACjCR,EAAK,SAAS;GAAE,GAAGO;GAAO;GAAG;EAAE,CAAC;CAClC,CAAC,GAOKwD,KAAkBN,QAAuB;EAE7C,CAAC5C,MAAe,eAAeQ,IAAgBC,EAAA,CAAe,SAAS,MAAM;GAD7C,eAAe;GAAM,cAAc;EACU,CAAO;CACtF,CAAC,GAEK0C,KAAoBpB,EACxBqB,IACC,MAA8C;EAC7C,AAAI,GAAK,YAAYlB,EAAM,WAAW,KAAMA,EAAM,aAAcD,EAAWC,CAAK,MAEhFA,EAAM,eAAe,GACrBA,EAAM,cAAc,kBAAkBA,EAAM,SAAS,GACrDS,EAAcT,CAAK,GACnBgB,GAAgB;CAClB,CACF,GAIMG,KAAoBtB,EACxBuB,IACC,MAA8C;EAC7C,AAAI,GAAK,YAAapB,EAAM,cAAc,kBAAkBA,EAAM,SAAS,KAC3ES,EAAcT,CAAK;CACrB,CACF,GAEMqB,IAAa;EACjB,YAAYlE,EAAQ;EACpB,YAAYA,EAAQ;EACpB,WAAWA,EAAQ;EACnB,WAAWA,EAAQ;CACrB,GAEMmE,KAAY;EAChB,GAAGC;EACH,8BAA8BC,GAAkB/D,EAAM,CAAC;EACvD,uBAAuBgE,EAAWhE,EAAM,CAAC;EACzC,uBAAuBgE,EAAWhE,EAAM,CAAC;EACzC,sBAAsBiE,EAAS;GAAE,GAAGjE,EAAM;GAAG,GAAGA,EAAM;GAAG,GAAGA,EAAM;EAAE,CAAC;CACvE,GAEMkE,KAAc,OAAoB;EACtC,MAAM;EACN,KAAK;EACL,KAAK;EACL,MAAM;EACN,UAAU1E,EAAK;EACf,wBAAwBE,EAAQ;EAChC,gBAAgB6B;EAChB,qBAAqBK;EAErB,UAAUM,MAAS7B,IAAc8D,KAAY,IAAK;EAGlD,eAAejC,MAAS7B,KAAc,CAACE,MAAuB,KAAA;EAC9D,UAAUuC,GAAkBZ,CAAI;EAChC,SAASa,GAAiBb,CAAI;EAC9B,WAAW;CACb;CAEA,OACE,mBAAC,OAAD;EACE,MAAK;EACL,iBAAe1C,EAAK,WAAW,KAAK,KAAA;EACpC,GAAIkC;EACJ,WAAW0C,EACTC,EAAoB,MACpB,uIACAxE,OAAkB,WAAW,iBAAiB,WAC9CyE,EACF;EACA,OAAOT;EACP,GAAItE;EACJ,KAAKwB;EACL,WAAWoB;EACX,eAAeqB;EACf,eAAeE;EAfjB,UAAA;GAiBE,kBAAC,OAAD;IACE,KAAKjD;IACL,eAAY;IACZ,WAAW2D,EACTC,EAAoB,OACpB,uIACF;GACD,CAAA;GACD,kBAAC,QAAD;IACE,eAAY;IACZ,WAAWD,EACTC,EAAoB,OACpBE,IACA,sHACA,wYACF;GACD,CAAA;GACD,kBAAC,SAAD;IACE,GAAIL,EAAW,YAAY;IAC3B,KAAKhD;IACL,OAAOhB;IACP,cAAYR,EAAQ;IACpB,kBAAgB8E,EAAcxE,GAAO,cAAc4D,CAAU;IAClD;GACZ,CAAA;GACD,kBAAC,SAAD;IACE,GAAIM,EAAW,OAAO;IACtB,KAAKpD;IACL,OAAOV;IACP,cAAYV,EAAQ;IACpB,oBAAiB;IACjB,kBAAgB8E,EAAcxE,GAAO,SAAS4D,CAAU;GACzD,CAAA;GACA,CAACjE,KACA,kBAAC8E,IAAD;IACE,MAAK;IACC;IACA;IACN,UAAUjF,EAAK;IACf,OAAOyE,EAASlE,CAAK;IACrB,UAAU8B;IACV,kBACGxB,MAAe,eAAeQ,IAAgBC,EAAA,CAAe,SAAS,MAAM;GAEhF,CAAA;EAEA;;AAET;AAEA,EAAU,cAAc"}
1
+ {"version":3,"file":"ColorArea.mjs","names":["React","DEFAULT_LABELS","clampPercent","value","COARSE_POINTER","ColorArea","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaRequired","ariaErrorMessage","rest","part","useColorPartState","strings","picker","labels","resolvedShape","shape","color","shown","displayColor","saturation","toPercent","brightness","activeAxis","setActiveAxis","coarsePointer","useMediaQuery","fieldRef","focusToken","setFocusToken","rootRef","saturationRef","brightnessRef","mergedRootRef","useMergedRefs","ref","mergedSaturationRef","controlRef","handledFocusTokenRef","field","useFieldContext","invalid","_ariaRequired","_required","groupProps","useFieldControl","errorMessageId","isRequired","required","form","applyAxis","percent","axis","handleKeyDown","composeEventHandlers","onKeyDown","isOwnEvent","event","step","next","intent","getArrowIntent","getDirection","token","handleInputChange","handleInputFocus","moveToPointer","useEventCallback","fieldElement","rect","x","s","v","focusActiveAxis","handlePointerDown","onPointerDown","handlePointerMove","onPointerMove","textLabels","areaStyle","style","colorAreaGradient","toPosition","hsvToHex","inputProps","tabIndex","cn","colorAreaClassNames","className","COLOR_THUMB_CLASSES","areaValueText","HiddenInput"],"sources":["../../../src/components/input/ColorArea.tsx"],"sourcesContent":["import * as React from 'react';\nimport { colorAreaClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { hsvToHex } from '../../lib/color';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { getArrowIntent, getDirection } from '../../lib/direction';\nimport { isOwnEvent } from '../../lib/events';\nimport type { ColorPickerShape, HsvColor } from '../../lib/types';\nimport { useEventCallback } from '../../hooks/useEventCallback';\nimport { useFieldContext, useFieldControl } from '../../hooks/useFieldControl';\nimport { useFormReset } from '../../hooks/useFormReset';\nimport { useMediaQuery } from '../../hooks/useMediaQuery';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { HiddenInput } from '../internal/HiddenInput';\nimport { useColorPartState } from './ColorPicker.parts';\nimport {\n COLOR_THUMB_CLASSES,\n areaValueText,\n colorAreaGradient,\n displayColor,\n toPercent,\n toPosition,\n} from './colorUtils';\n\n/** Texts of a ColorArea, for localisation. Every key is optional. */\nexport interface ColorAreaLabels {\n /** Name of the horizontal slider.\n * @default 'Saturation'\n */\n saturation?: string;\n /** Name of the vertical slider (the `value` channel).\n * @default 'Brightness'\n */\n brightness?: string;\n /** Role description of both sliders.\n * @default '2D slider'\n */\n roleDescription?: string;\n /** Names the color at the end of each value text; return `''` to leave it out.\n * @default an English namer (\"dark blue\")\n */\n colorName?: (color: HsvColor) => string;\n /** Replaces a whole value text, for languages whose order differs. */\n valueText?: (color: HsvColor, channel: 'saturation' | 'value') => string;\n}\n\n/** Properties for the ColorArea component. */\nexport interface ColorAreaProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'defaultValue' | 'onChange'\n> {\n /**\n * The color (Fluent's `color`). Inside a ColorPicker, leave `value` and `defaultValue` out to\n * bind the area to the picker.\n */\n value?: HsvColor;\n /**\n * Initial color for uncontrolled usage (also what a form reset restores).\n * @default the brand blue, `{ h: 208, s: 0.92, v: 0.74 }` (`#0f6cbd`)\n */\n defaultValue?: HsvColor;\n /**\n * Called with the new color on every step (a key, a pointer move or assistive technology) that\n * changes it (Fluent's `onChange`). A bound area calls it too.\n */\n onValueChange?: (value: HsvColor) => void;\n /**\n * `'square'` removes the corner radius (the thumb stays round). Bound to a ColorPicker, the\n * picker's shape unless you pass one.\n * @default 'rounded'\n */\n shape?: ColorPickerShape;\n /** Texts of the area; bound to a ColorPicker, the picker's `labels` fill the keys you leave out. */\n labels?: ColorAreaLabels;\n /**\n * Unavailable: both inputs are natively disabled, pointer presses are ignored and the area is\n * dimmed. A bound area is also disabled while the picker's value is not a hex color.\n * @default false\n */\n disabled?: boolean;\n /** Form field name: the color is submitted as hex (`hsvToHex`). Ignored while bound to a ColorPicker. */\n name?: string;\n /** Id of the form the area belongs to, when it is rendered outside that form. */\n form?: string;\n /**\n * Marks the hidden form input required (a color is always set, so it never blocks). A consumer\n * `aria-required` does the same: a group supports neither, so neither is set on it.\n */\n required?: boolean;\n /** Ref to the saturation `<input type=\"range\">`. */\n controlRef?: React.Ref<HTMLInputElement>;\n /** Ref to the root `role=\"group\"` element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** The two axes: saturation (x) and brightness (y, the `value` channel). */\ntype AreaAxis = 'saturation' | 'value';\n\nconst DEFAULT_LABELS = {\n saturation: 'Saturation',\n brightness: 'Brightness',\n roleDescription: '2D slider',\n} as const;\n\n/** A whole percentage clamped to 0–100. */\nfunction clampPercent(value: number): number {\n return Math.min(100, Math.max(0, value));\n}\n\n/** Touch-primary devices expose both inputs, so a touch screen reader can swipe each (D19). */\nconst COARSE_POINTER = '(pointer: coarse)';\n\n/**\n * A 2-D color field: saturation from left to right (mirrored in right-to-left layouts) and\n * brightness from bottom to top, at the value's hue. ArrowLeft and ArrowRight move saturation by\n * 1 %, ArrowUp and ArrowDown brightness; Shift with an arrow moves by 10, Page Up and Page Down\n * move brightness by 10, and Home and End set saturation to 0 and 100. A press or drag (mouse,\n * touch or pen) moves the thumb to the pointer. It is one Tab stop holding two sliders for\n * assistive technology, \"Saturation\" and \"Brightness\", whose value texts start with their own\n * channel and name the color; focus follows the axis a key moves, and unless the primary pointer\n * is coarse (touch), only the slider with the Tab stop is exposed. Inside a ColorPicker, leave\n * `value` and `defaultValue` out and it binds to the picker. Fluent's\n * `ColorArea`, with `value`/`onValueChange` for its `color`/`onChange`.\n *\n * @example\n * <ColorArea aria-label=\"Accent color\" value={color} onValueChange={setColor} />\n */\nexport const ColorArea = ({\n value,\n defaultValue,\n onValueChange,\n shape,\n labels,\n disabled = false,\n name,\n form,\n required,\n controlRef,\n className,\n style,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n 'aria-errormessage': ariaErrorMessage,\n autoFocus,\n tabIndex,\n onKeyDown,\n onPointerDown,\n onPointerMove,\n ref,\n ...rest\n}: ColorAreaProps) => {\n const part = useColorPartState({ value, defaultValue, onValueChange, disabled });\n const { picker } = part;\n const strings = {\n ...DEFAULT_LABELS,\n ...(picker && {\n saturation: picker.labels.saturation,\n brightness: picker.labels.brightness,\n roleDescription: picker.labels.roleDescription,\n colorName: picker.labels.colorName,\n valueText: picker.labels.valueText,\n }),\n ...labels,\n };\n const resolvedShape = shape ?? picker?.shape ?? 'rounded';\n const color = part.color;\n const shown = displayColor(color);\n const saturation = toPercent(shown.s);\n const brightness = toPercent(shown.v);\n\n const [activeAxis, setActiveAxis] = React.useState<AreaAxis>('saturation');\n const coarsePointer = useMediaQuery(COARSE_POINTER);\n const fieldRef = React.useRef<HTMLDivElement>(null);\n // Bumped on every handled key (not only an axis change), so the layout effect below moves focus\n // to the axis's input even when the key's axis is the one an earlier assistive-technology change\n // already made the Tab stop, without moving focus; focusing an input that already has focus does\n // nothing. Never bumped for an AT-driven change (`handleInputChange`) or a real focus event. A\n // plain counter, not a ref: react-hooks/refs only allows a ref's `current` to be touched from an\n // effect, a ref callback or a function assigned directly to a JSX handler prop, not one passed\n // through `composeEventHandlers`.\n const [focusToken, setFocusToken] = React.useState(0);\n const rootRef = React.useRef<HTMLDivElement>(null);\n const saturationRef = React.useRef<HTMLInputElement>(null);\n const brightnessRef = React.useRef<HTMLInputElement>(null);\n const mergedRootRef = useMergedRefs(ref, rootRef);\n const mergedSaturationRef = useMergedRefs(saturationRef, controlRef);\n /** The last `focusToken` this component already moved focus for (read/written in the effect only). */\n const handledFocusTokenRef = React.useRef(0);\n\n React.useLayoutEffect(() => {\n if (handledFocusTokenRef.current === focusToken) return;\n handledFocusTokenRef.current = focusToken;\n (activeAxis === 'saturation' ? saturationRef : brightnessRef).current?.focus({\n preventScroll: true,\n });\n }, [activeAxis, focusToken]);\n\n const field = useFieldContext();\n const fieldProps = useFieldControl(\n {\n id,\n 'aria-label':\n ariaLabel ?? (picker && ariaLabelledBy === undefined ? picker.labels.area : undefined),\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n },\n { labelable: false },\n );\n // A group supports neither aria-invalid, aria-required nor `required` (ARIA 1.2): the invalid\n // state goes to both inputs and the required state to the hidden input.\n const {\n 'aria-invalid': invalid,\n 'aria-required': _ariaRequired,\n required: _required,\n ...groupProps\n } = fieldProps;\n const isInvalid = invalid !== undefined && invalid !== false && invalid !== 'false';\n const errorMessageId = (isInvalid && ariaErrorMessage) || undefined;\n const isRequired =\n required ?? (ariaRequired === true || ariaRequired === 'true' || (field?.required ?? false));\n\n useFormReset(rootRef, part.reset, form);\n\n /** Applies a whole percentage to one axis, keeping the other channels as given. */\n const applyAxis = (axis: AreaAxis, percent: number) => {\n if (percent === (axis === 'saturation' ? saturation : brightness)) return;\n part.setColor(\n axis === 'saturation' ? { ...color, s: percent / 100 } : { ...color, v: percent / 100 },\n );\n };\n\n const handleKeyDown = composeEventHandlers(\n onKeyDown,\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (part.disabled || !isOwnEvent(event) || event.nativeEvent.isComposing) return;\n // A key with Alt, Ctrl or Meta belongs to the browser (Alt+Left is \"back\").\n if (event.altKey || event.ctrlKey || event.metaKey) return;\n const step = event.shiftKey ? 10 : 1;\n let axis: AreaAxis;\n let next: number;\n switch (event.key) {\n case 'ArrowLeft':\n case 'ArrowRight': {\n const intent = getArrowIntent(event.key, {\n orientation: 'horizontal',\n dir: getDirection(event.currentTarget),\n });\n axis = 'saturation';\n next = saturation + (intent === 'next' ? step : -step);\n break;\n }\n case 'ArrowUp':\n axis = 'value';\n next = brightness + step;\n break;\n case 'ArrowDown':\n axis = 'value';\n next = brightness - step;\n break;\n case 'PageUp':\n axis = 'value';\n next = brightness + 10;\n break;\n case 'PageDown':\n axis = 'value';\n next = brightness - 10;\n break;\n case 'Home':\n axis = 'saturation';\n next = 0;\n break;\n case 'End':\n axis = 'saturation';\n next = 100;\n break;\n default:\n return;\n }\n // Prevented, so the native range input never moves on its own.\n event.preventDefault();\n if (axis !== activeAxis) setActiveAxis(axis);\n // Every handled key moves focus to its axis's input, even when an earlier\n // assistive-technology change already made that axis the Tab stop.\n setFocusToken((token) => token + 1);\n applyAxis(axis, clampPercent(next));\n },\n );\n\n /** A change event from assistive technology (a swipe): that input becomes the Tab stop. */\n const handleInputChange = (axis: AreaAxis) => (event: React.ChangeEvent<HTMLInputElement>) => {\n if (part.disabled) return;\n if (axis !== activeAxis) setActiveAxis(axis);\n applyAxis(axis, clampPercent(Math.round(Number(event.currentTarget.value))));\n };\n\n const handleInputFocus = (axis: AreaAxis) => () => {\n if (axis !== activeAxis) setActiveAxis(axis);\n };\n\n // Both read a ref (`fieldRef`, or `saturationRef`/`brightnessRef`): `useEventCallback` (a custom\n // hook, opaque to react-hooks/refs) keeps that safe to call from the handler below, unlike a\n // plain function or `React.useCallback` passed into the generic `composeEventHandlers`.\n /** Moves the thumb to the pointer: saturation along x (mirrored in RTL), brightness along y. */\n const moveToPointer = useEventCallback((event: React.PointerEvent<HTMLDivElement>) => {\n const fieldElement = fieldRef.current;\n if (!fieldElement) return;\n const rect = fieldElement.getBoundingClientRect();\n if (rect.width <= 0 || rect.height <= 0) return;\n const x = Math.min(1, Math.max(0, (event.clientX - rect.left) / rect.width));\n const s = getDirection(event.currentTarget) === 'rtl' ? 1 - x : x;\n const v = Math.min(1, Math.max(0, 1 - (event.clientY - rect.top) / rect.height));\n if (s === shown.s && v === shown.v) return;\n part.setColor({ ...color, s, v });\n });\n /**\n * Focuses the input of the active axis (the press moves focus there instead of the point),\n * without the focus ring: Chromium treats this script focus as keyboard focus, where the\n * browser's own focus of a pressed control shows none. Browsers without the `focusVisible`\n * option ignore it.\n */\n const focusActiveAxis = useEventCallback(() => {\n const options: FocusOptions = { preventScroll: true, focusVisible: false };\n (activeAxis === 'saturation' ? saturationRef : brightnessRef).current?.focus(options);\n });\n\n const handlePointerDown = composeEventHandlers(\n onPointerDown,\n (event: React.PointerEvent<HTMLDivElement>) => {\n if (part.disabled || event.button !== 0 || !event.isPrimary || !isOwnEvent(event)) return;\n // No text selection and no focus move of the press: focus goes to the Tab stop instead.\n event.preventDefault();\n event.currentTarget.setPointerCapture(event.pointerId);\n moveToPointer(event);\n focusActiveAxis();\n },\n );\n\n // The drag lasts while the root holds the pointer; losing the capture (pointerup,\n // lostpointercapture) ends it.\n const handlePointerMove = composeEventHandlers(\n onPointerMove,\n (event: React.PointerEvent<HTMLDivElement>) => {\n if (part.disabled || !event.currentTarget.hasPointerCapture(event.pointerId)) return;\n moveToPointer(event);\n },\n );\n\n const textLabels = {\n saturation: strings.saturation,\n brightness: strings.brightness,\n colorName: strings.colorName,\n valueText: strings.valueText,\n };\n\n const areaStyle = {\n ...style,\n '--wave-color-area-gradient': colorAreaGradient(shown.h),\n '--wave-color-area-x': toPosition(shown.s),\n '--wave-color-area-y': toPosition(shown.v),\n '--wave-color-thumb': hsvToHex({ h: shown.h, s: shown.s, v: shown.v }),\n } as React.CSSProperties;\n\n const inputProps = (axis: AreaAxis) => ({\n type: 'range' as const,\n min: 0,\n max: 100,\n step: 1,\n disabled: part.disabled,\n 'aria-roledescription': strings.roleDescription,\n 'aria-invalid': invalid,\n 'aria-errormessage': errorMessageId,\n // One Tab stop: the input used last (C-ROUTING: a consumer tabIndex applies to it).\n tabIndex: axis === activeAxis ? (tabIndex ?? 0) : -1,\n // Where the primary pointer is not coarse, desktop screen readers meet one 2-D slider: the\n // input without the Tab stop is hidden (it stays focusable by script, never by Tab).\n 'aria-hidden': axis !== activeAxis && !coarsePointer ? true : undefined,\n onChange: handleInputChange(axis),\n onFocus: handleInputFocus(axis),\n className: 'sr-only',\n });\n\n return (\n <div\n role=\"group\"\n data-disabled={part.disabled ? '' : undefined}\n {...groupProps}\n className={cn(\n colorAreaClassNames.root,\n 'group/color-area relative h-40 w-full min-w-40 touch-none select-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50',\n resolvedShape === 'square' ? 'rounded-none' : 'rounded',\n className,\n )}\n style={areaStyle}\n {...rest}\n ref={mergedRootRef}\n onKeyDown={handleKeyDown}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n >\n <div\n ref={fieldRef}\n aria-hidden=\"true\"\n className={cn(\n colorAreaClassNames.field,\n 'absolute inset-0 rounded-[inherit] bg-(image:--wave-color-area-gradient) wave-rtl:-scale-x-100 forced-colors:forced-color-adjust-none',\n )}\n />\n <span\n aria-hidden=\"true\"\n className={cn(\n colorAreaClassNames.thumb,\n COLOR_THUMB_CLASSES,\n 'start-(--wave-color-area-x) bottom-(--wave-color-area-y) -translate-x-1/2 wave-rtl:translate-x-1/2 translate-y-1/2',\n 'group-has-[:focus-visible]/color-area:ring-2 group-has-[:focus-visible]/color-area:ring-background forced-colors:group-has-[:focus-visible]/color-area:ring-[Canvas] group-has-[:focus-visible]/color-area:outline-2 group-has-[:focus-visible]/color-area:outline-offset-2 group-has-[:focus-visible]/color-area:outline-ring forced-colors:group-has-[:focus-visible]/color-area:outline-[Highlight]',\n )}\n />\n <input\n {...inputProps('saturation')}\n ref={mergedSaturationRef}\n value={saturation}\n aria-label={strings.saturation}\n aria-valuetext={areaValueText(shown, 'saturation', textLabels)}\n autoFocus={autoFocus}\n />\n <input\n {...inputProps('value')}\n ref={brightnessRef}\n value={brightness}\n aria-label={strings.brightness}\n aria-orientation=\"vertical\"\n aria-valuetext={areaValueText(shown, 'value', textLabels)}\n />\n {!picker && (\n <HiddenInput\n type=\"text\"\n name={name}\n form={form}\n disabled={part.disabled}\n value={hsvToHex(color)}\n required={isRequired}\n onInvalid={() =>\n (activeAxis === 'saturation' ? saturationRef : brightnessRef).current?.focus()\n }\n />\n )}\n </div>\n );\n};\n\nColorArea.displayName = 'ColorArea';\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/composeEventHandlers.cjs"),i=require("../../lib/classNames.cjs"),a=require("../../hooks/useControllable.cjs"),o=require("../../hooks/useId.cjs"),s=require("../../hooks/useMergedRefs.cjs"),c=require("../../lib/aria.cjs"),l=require("../../lib/styles.cjs"),u=require("./Input.cjs"),d=require("./colorUtils.cjs"),f=require("./SwatchPicker.cjs");let p=require("react");p=e.__toESM(p,1);let m=require("react/jsx-runtime");var h=`#0f6cbd`,g={h:208,s:.92,v:.74},_={hex:`Hex`,hexInput:`Hex color value`,hexError:`Enter a hex color such as ${h}.`,presets:`Preset colors`,opacity:`Opacity`,area:`Saturation and brightness`,saturation:`Saturation`,brightness:`Brightness`,roleDescription:`2D slider`,hue:`Hue`,transparency:`Transparency`},v=p.createContext(null);v.displayName=`ColorPickerContext`;function y(){return p.useContext(v)}var b=()=>{};function x({value:e,defaultValue:t,onValueChange:n,disabled:r}){let i=y(),o=i!==null&&e===void 0&&t===void 0?i:null,s=t??g,[c,l]=a.useControllable(e,s,o?void 0:n);return o?{picker:o,color:o.hsv,setColor:e=>{o.setHsv(e),n?.(e)},reset:b,disabled:r||o.disabled}:{picker:null,color:c,setColor:l,reset:()=>{d.sameColor(c,s)||l(s)},disabled:r}}var S={hsv:g,setHsv:b,color:h,parsed:null,setColor:b,pickPreset:b,presetItems:[],shape:`rounded`,labels:_,disabled:!0,draftResetKey:0,field:null,groupInvalid:void 0,errorMessageId:void 0,registerHexInput:b};function C(e){return p.useContext(v)||(n.reportMissingContext(e,`<ColorPicker>`),S)}function w(e){let t=e.trim();return t===``||t===`#`}function T(e){let t=e.trim().replace(/^#/,``).length;return t===4||t===8}var E=({id:e,"aria-label":n,"aria-labelledby":a,"aria-describedby":f,"aria-invalid":h,"aria-errormessage":g,"aria-details":_,"aria-required":v,autoFocus:y,tabIndex:b,onFocus:x,onBlur:S,onKeyDown:E,onKeyUp:D,inputMode:O,enterKeyHint:k,autoCapitalize:ee,autoCorrect:te,spellCheck:ne,controlRef:re,className:A,ref:j,...M})=>{let N=C(`ColorPicker.HexField`),{color:P,parsed:ie,field:F,groupInvalid:I,errorMessageId:L,labels:R}=N,z=ie?.alpha??255,[B,V]=p.useState(null),[H,U]=p.useState(P);P!==H&&(U(P),B?.flagged&&V(null));let[W,G]=p.useState(N.draftResetKey);N.draftResetKey!==W&&(G(N.draftResetKey),V(null));let K=B?.text??P,q=B!==null&&!w(B.text)&&(B.flagged||!d.isHexDraft(B.text)),J=I!==void 0&&I!==!1&&I!==`false`,Y=o.useId(`wave-color-picker-error`),X=h??(q?!0:J?I:void 0),ae=u.isInvalidLook(!1,X),oe=p.useRef(null),se=s.useMergedRefs(oe,re,N.registerHexInput),Z=(e,t)=>N.setColor(d.formatHexColor(e,t)),Q=e=>{let t=e.target.value.trim();t!==``&&!t.startsWith(`#`)&&(t=`#${t}`),V({text:t,flagged:!1});let n=d.parseHexInput(t);n&&Z(n.rgb,T(t)?n.alpha:z)},$=()=>{if(B===null||B.flagged)return;let e=d.parseHexColor(B.text);if(e||w(B.text)){e&&!d.parseHexInput(B.text)&&Z(e.rgb,T(B.text)?e.alpha:z),V(null);return}V({text:B.text,flagged:!0})},ce=r.composeEventHandlers(S,$),le=r.composeEventHandlers(E,e=>{e.key===`Enter`&&!e.nativeEvent.isComposing&&$()});return(0,m.jsxs)(`label`,{ref:j,className:t.cn(i.colorPickerHexFieldClassNames.root,`flex min-w-0 flex-col gap-1`,A),...M,children:[(0,m.jsx)(`span`,{className:t.cn(i.colorPickerHexFieldClassNames.label,`text-caption-1 text-muted-foreground`),children:R.hex}),(0,m.jsx)(`input`,{ref:se,id:e,type:`text`,value:K,onChange:Q,onKeyDown:le,onKeyUp:D,onFocus:x,onBlur:ce,"aria-label":n??(a===void 0?R.hexInput:void 0),"aria-labelledby":a,"aria-invalid":X,"aria-errormessage":g??L,"aria-describedby":c.joinIds(q&&Y,F?.validationMessageId??(J?F?.errorId:void 0),L,f),"aria-details":_,"aria-required":v,autoFocus:y,tabIndex:b,inputMode:O,enterKeyHint:k,autoCapitalize:ee,autoCorrect:te,spellCheck:ne??!1,maxLength:9,autoComplete:`off`,className:t.cn(i.colorPickerHexFieldClassNames.input,`w-24 rounded border border-input border-b-stroke-accessible bg-background px-2 py-1 text-body-1 text-foreground`,l.inputFocus,ae&&`border-destructive focus:border-b-destructive`)}),q&&(0,m.jsx)(`span`,{id:Y,className:t.cn(i.colorPickerHexFieldClassNames.errorMessage,`text-caption-1 text-error`),children:R.hexError})]})};E.displayName=`ColorPickerHexField`;var D=({className:e,"aria-label":n,size:r=`small`,shape:a=`rounded`,...o})=>{let s=C(`ColorPicker.Swatches`);return s.presetItems.length===0?null:(0,m.jsx)(f.SwatchPicker,{"aria-label":n??(o[`aria-labelledby`]===void 0?s.labels.presets:void 0),size:r,shape:a,...o,className:t.cn(i.colorPickerSwatchesClassNames.root,e),items:s.presetItems,value:s.parsed?s.parsed.rgb:``,onValueChange:s.pickPreset})};D.displayName=`ColorPickerSwatches`;var O=({className:e,style:n,ref:r,...a})=>{let o=C(`ColorPicker.Preview`),s=o.parsed?d.formatHexColor(o.parsed.rgb,o.parsed.alpha):o.color;return(0,m.jsx)(`div`,{"data-color-preview":``,"aria-hidden":`true`,...a,ref:r,className:t.cn(i.colorPickerPreviewClassNames.root,`h-10 w-10 shrink-0 rounded border border-border forced-colors:forced-color-adjust-none`,o.shape===`square`&&`rounded-none`,e),style:{...n,backgroundColor:s}})};O.displayName=`ColorPickerPreview`,exports.ColorPickerContext=v,exports.ColorPickerHexField=E,exports.ColorPickerPreview=O,exports.ColorPickerSwatches=D,exports.DEFAULT_COLOR=h,exports.DEFAULT_COLOR_PICKER_LABELS=_,exports.DEFAULT_PART_COLOR=g,exports.useColorPartState=x,exports.useColorPickerContext=y,exports.usePickerPartContext=C;
1
+ "use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/composeEventHandlers.cjs"),i=require("../../lib/classNames.cjs"),a=require("../../hooks/useControllable.cjs"),o=require("../../hooks/useId.cjs"),s=require("../../hooks/useMergedRefs.cjs"),c=require("../../lib/aria.cjs"),l=require("../../lib/styles.cjs"),u=require("./Input.cjs"),d=require("./colorUtils.cjs"),f=require("./SwatchPicker.cjs");let p=require("react");p=e.__toESM(p,1);let m=require("react/jsx-runtime");var h=`#0f6cbd`,g={h:208,s:.92,v:.74},_={hex:`Hex`,hexInput:`Hex color value`,hexError:`Enter a hex color such as ${h}.`,presets:`Preset colors`,opacity:`Opacity`,area:`Saturation and brightness`,saturation:`Saturation`,brightness:`Brightness`,roleDescription:`2D slider`,hue:`Hue`,transparency:`Transparency`},v=p.createContext(null);v.displayName=`ColorPickerContext`;function y(){return p.useContext(v)}var b=()=>{};function x({value:e,defaultValue:t,onValueChange:n,disabled:r}){let i=y(),o=i!==null&&e===void 0&&t===void 0?i:null,s=t??g,[c,l]=a.useControllable(e,s,o?void 0:n);return o?{picker:o,color:o.hsv,setColor:e=>{o.setHsv(e),n?.(e)},reset:b,disabled:r||o.disabled}:{picker:null,color:c,setColor:l,reset:()=>{d.sameColor(c,s)||l(s)},disabled:r}}var S={hsv:g,setHsv:b,color:h,parsed:null,setColor:b,pickPreset:b,presetItems:[],shape:`rounded`,labels:_,disabled:!0,draftResetKey:0,field:null,groupInvalid:void 0,errorMessageId:void 0,registerHexInput:b};function C(e){return p.useContext(v)||(n.reportMissingContext(e,`<ColorPicker>`),S)}function w(e){let t=e.trim();return t===``||t===`#`}function T(e){let t=e.trim().replace(/^#/,``).length;return t===4||t===8}var E=({id:e,"aria-label":n,"aria-labelledby":a,"aria-describedby":f,"aria-invalid":h,"aria-errormessage":g,"aria-details":_,"aria-required":v,autoFocus:y,tabIndex:b,onFocus:x,onBlur:S,onKeyDown:E,onKeyUp:D,inputMode:O,enterKeyHint:k,autoCapitalize:ee,autoCorrect:te,spellCheck:ne,controlRef:re,className:A,ref:j,...M})=>{let N=C(`ColorPicker.HexField`),{color:P,parsed:ie,field:F,groupInvalid:I,errorMessageId:L,labels:R}=N,z=ie?.alpha??255,[B,V]=p.useState(null),[H,U]=p.useState(P);P!==H&&(U(P),B?.flagged&&V(null));let[W,G]=p.useState(N.draftResetKey);N.draftResetKey!==W&&(G(N.draftResetKey),V(null));let K=B?.text??P,q=B!==null&&!w(B.text)&&(B.flagged||!d.isHexDraft(B.text)),J=I!==void 0&&I!==!1&&I!==`false`,Y=o.useId(`wave-color-picker-error`),X=h??(q?!0:J?I:void 0),ae=u.isInvalidLook(!1,X),oe=p.useRef(null),se=s.useMergedRefs(oe,re,N.registerHexInput),Z=(e,t)=>N.setColor(d.formatHexColor(e,t)),Q=e=>{let t=e.target.value.trim();t!==``&&!t.startsWith(`#`)&&(t=`#${t}`),V({text:t,flagged:!1});let n=d.parseHexInput(t);n&&Z(n.rgb,T(t)?n.alpha:z)},$=()=>{if(B===null||B.flagged)return;let e=d.parseHexColor(B.text);if(e||w(B.text)){e&&!d.parseHexInput(B.text)&&Z(e.rgb,T(B.text)?e.alpha:z),V(null);return}V({text:B.text,flagged:!0})},ce=r.composeEventHandlers(S,$),le=r.composeEventHandlers(E,e=>{e.key===`Enter`&&!e.nativeEvent.isComposing&&$()});return(0,m.jsxs)(`label`,{ref:j,className:t.cn(i.colorPickerHexFieldClassNames.root,`flex min-w-0 flex-col gap-1`,A),...M,children:[(0,m.jsx)(`span`,{className:t.cn(i.colorPickerHexFieldClassNames.label,`text-caption-1 text-muted-foreground`),children:R.hex}),(0,m.jsx)(`input`,{ref:se,id:e,type:`text`,value:K,onChange:Q,onKeyDown:le,onKeyUp:D,onFocus:x,onBlur:ce,"aria-label":n??(a===void 0?R.hexInput:void 0),"aria-labelledby":a,"aria-invalid":X,"aria-errormessage":g??L,"aria-describedby":c.joinIds(q&&Y,F?.validationMessageId??(J?F?.errorId:void 0),L,f),"aria-details":_,"aria-required":v,autoFocus:y,tabIndex:b,inputMode:O,enterKeyHint:k,autoCapitalize:ee,autoCorrect:te,spellCheck:ne??!1,maxLength:9,autoComplete:`off`,className:t.cn(i.colorPickerHexFieldClassNames.input,`w-24 rounded border border-input border-b-stroke-accessible bg-background px-2 py-1 text-body-1 text-foreground`,l.inputFocus,ae&&`border-destructive`)}),q&&(0,m.jsx)(`span`,{id:Y,className:t.cn(i.colorPickerHexFieldClassNames.errorMessage,`text-caption-1 text-error`),children:R.hexError})]})};E.displayName=`ColorPickerHexField`;var D=({className:e,"aria-label":n,size:r=`small`,shape:a=`rounded`,...o})=>{let s=C(`ColorPicker.Swatches`);return s.presetItems.length===0?null:(0,m.jsx)(f.SwatchPicker,{"aria-label":n??(o[`aria-labelledby`]===void 0?s.labels.presets:void 0),size:r,shape:a,...o,className:t.cn(i.colorPickerSwatchesClassNames.root,e),items:s.presetItems,value:s.parsed?s.parsed.rgb:``,onValueChange:s.pickPreset})};D.displayName=`ColorPickerSwatches`;var O=({className:e,style:n,ref:r,...a})=>{let o=C(`ColorPicker.Preview`),s=o.parsed?d.formatHexColor(o.parsed.rgb,o.parsed.alpha):o.color;return(0,m.jsx)(`div`,{"data-color-preview":``,"aria-hidden":`true`,...a,ref:r,className:t.cn(i.colorPickerPreviewClassNames.root,`h-10 w-10 shrink-0 rounded border border-border forced-colors:forced-color-adjust-none`,o.shape===`square`&&`rounded-none`,e),style:{...n,backgroundColor:s}})};O.displayName=`ColorPickerPreview`,exports.ColorPickerContext=v,exports.ColorPickerHexField=E,exports.ColorPickerPreview=O,exports.ColorPickerSwatches=D,exports.DEFAULT_COLOR=h,exports.DEFAULT_COLOR_PICKER_LABELS=_,exports.DEFAULT_PART_COLOR=g,exports.useColorPartState=x,exports.useColorPickerContext=y,exports.usePickerPartContext=C;
2
2
  //# sourceMappingURL=ColorPicker.parts.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ColorPicker.parts.cjs","names":["React","useControllable","sameColor","isHexDraft","useId","isInvalidLook","useMergedRefs","formatHexColor","parseHexInput","parseHexColor","composeEventHandlers","cn","colorPickerHexFieldClassNames","joinIds","inputFocus","SwatchPicker","colorPickerSwatchesClassNames","colorPickerPreviewClassNames","require_runtime","require_cn","require_dev","require_composeEventHandlers","require_classNames","require_useControllable","require_useId","require_useMergedRefs","require_aria","require_styles","require_Input","require_colorUtils","require_SwatchPicker","react","react_jsx_runtime","DEFAULT_COLOR","DEFAULT_PART_COLOR","DEFAULT_COLOR_PICKER_LABELS","ColorPickerContext","useColorPickerContext","noop","useColorPartState","context","picker","value","defaultValue","initial","own","setOwn","onValueChange","next","disabled","INERT_PICKER_CONTEXT","usePickerPartContext","componentName","isBlankDraft","trimmed","text","hasAlphaDigits","digits","ColorPickerHexField","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaErrorMessage","ariaDetails","ariaRequired","rest","alpha","parsed","draft","setDraft","syncedColor","setSyncedColor","color","seenResetKey","setSeenResetKey","hexText","draftInvalid","fieldInvalid","groupInvalid","errorId","resolvedInvalid","invalidLook","inputRef","mergedInputRef","controlRef","commit","rgb","nextAlpha","handleChange","event","typed","finishDraft","handleBlur","onBlur","handleKeyDown","onKeyDown","className","labels","errorMessageId","field","spellCheck","ColorPickerSwatches","ColorPickerPreview","shown","style"],"sources":["../../../src/components/input/ColorPicker.parts.tsx"],"sourcesContent":["import * as React from 'react';\nimport { useControllable } from '../../hooks/useControllable';\nimport type { FieldContextValue } from '../../hooks/useFieldControl';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { joinIds } from '../../lib/aria';\nimport {\n colorPickerHexFieldClassNames,\n colorPickerPreviewClassNames,\n colorPickerSwatchesClassNames,\n} from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { reportMissingContext } from '../../lib/dev';\nimport { inputFocus, inputInvalid } from '../../lib/styles';\nimport type { ColorPickerShape, HsvColor } from '../../lib/types';\nimport { isInvalidLook } from './Input';\nimport { SwatchPicker, type SwatchItem, type SwatchPickerProps } from './SwatchPicker';\nimport {\n formatHexColor,\n isHexDraft,\n parseHexColor,\n parseHexInput,\n sameColor,\n type HexColor,\n} from './colorUtils';\n\n/*\n * The picker's labels and context, and how the standalone color parts bind to it (spec P3-05,\n * D21). `ColorArea`, `ColorSlider` and `AlphaSlider` read the context; `ColorPicker.tsx` provides\n * it and renders the picker-only parts. This module never imports `ColorPicker.tsx`.\n */\n\n// wave-allow-color: default color value (user color data, C-TOKENS exception)\nexport const DEFAULT_COLOR = '#0f6cbd';\n\n/** The default color of a standalone part: the default picker color in HSV. */\nexport const DEFAULT_PART_COLOR: HsvColor = { h: 208, s: 0.92, v: 0.74 };\n\n/**\n * Texts of the ColorPicker's own parts and of the color parts bound to it, for localisation.\n * Every key is optional; missing keys use the English default.\n */\nexport interface ColorPickerLabels {\n /** Visible caption above the hex field.\n * @default 'Hex'\n */\n hex?: string;\n /** Accessible name of the hex text field.\n * @default 'Hex color value'\n */\n hexInput?: string;\n /** Error text shown (and used as the hex field's description) while the typed text can never be\n * a hex color, or when the field is left with text that is not one (such as `#12345`).\n * @default 'Enter a hex color such as #0f6cbd.'\n */\n hexError?: string;\n /** Accessible name of the preset swatches radiogroup.\n * @default 'Preset colors'\n */\n presets?: string;\n /** Visible label of the opacity row and accessible name of the opacity slider (a bound\n * `AlphaSlider`).\n * @default 'Opacity'\n */\n opacity?: string;\n /** Accessible name of a bound `ColorArea`'s group.\n * @default 'Saturation and brightness'\n */\n area?: string;\n /** Name of a bound area's saturation slider and of a bound `channel=\"saturation\"` slider.\n * @default 'Saturation'\n */\n saturation?: string;\n /** Name of a bound area's brightness slider and of a bound `channel=\"value\"` slider.\n * @default 'Brightness'\n */\n brightness?: string;\n /** Role description of a bound area's two sliders.\n * @default '2D slider'\n */\n roleDescription?: string;\n /** Name of a bound hue slider.\n * @default 'Hue'\n */\n hue?: string;\n /** Name of a bound `AlphaSlider` with `transparency`.\n * @default 'Transparency'\n */\n transparency?: string;\n /** Names the color at the end of the bound parts' value texts; return `''` to leave it out.\n * @default an English namer (\"dark blue\")\n */\n colorName?: (color: HsvColor) => string;\n /** Replaces a whole value text of a bound part, for languages whose order differs. */\n valueText?: (color: HsvColor, channel: 'hue' | 'saturation' | 'value' | 'alpha') => string;\n}\n\n/** The labels with every string default filled in (the two functions stay optional). */\nexport type ResolvedColorPickerLabels = Required<\n Omit<ColorPickerLabels, 'colorName' | 'valueText'>\n> &\n Pick<ColorPickerLabels, 'colorName' | 'valueText'>;\n\nexport const DEFAULT_COLOR_PICKER_LABELS: ResolvedColorPickerLabels = {\n hex: 'Hex',\n hexInput: 'Hex color value',\n hexError: `Enter a hex color such as ${DEFAULT_COLOR}.`,\n presets: 'Preset colors',\n opacity: 'Opacity',\n area: 'Saturation and brightness',\n saturation: 'Saturation',\n brightness: 'Brightness',\n roleDescription: '2D slider',\n hue: 'Hue',\n transparency: 'Transparency',\n};\n\n/** What a ColorPicker shares with its parts and with the color parts bound to it. */\nexport interface ColorPickerContextValue {\n /** The working color: HSV, so hue and saturation survive gray, white and black. */\n hsv: HsvColor;\n /** Writes the working color from a bound part and reports its hex (only when the hex changes). */\n setHsv: (next: HsvColor) => void;\n /** The picker's value as given: a hex string, or a value that is not one (as given). */\n color: string;\n /** The value parsed (`#rrggbb` and the alpha byte), `null` while it is not a hex color. */\n parsed: HexColor | null;\n /** Writes the value as hex text (the hex field). */\n setColor: (next: string) => void;\n /** Applies a preset's `#rrggbb` at the current opacity and drops the hex field's draft. */\n pickPreset: (rgb: string) => void;\n /** The picker's presets as swatch items (values are `#rrggbb`). */\n presetItems: readonly SwatchItem[];\n /** The picker's `shape`, inherited by the bound parts and `ColorPicker.Preview`. */\n shape: ColorPickerShape;\n /** The picker's labels with every string default filled in. */\n labels: ResolvedColorPickerLabels;\n /** `true` while the value is not a hex color: the bound parts are disabled until one arrives. */\n disabled: boolean;\n /** Changes whenever the hex field must drop its draft: a form reset or a preset pick. */\n draftResetKey: number;\n /** The Field around the picker (its parts render in a `null` Field context). */\n field: FieldContextValue | null;\n /** The invalid state set on the picker from outside (its `aria-invalid` or the Field's), as given. */\n groupInvalid: React.AriaAttributes['aria-invalid'];\n /** The consumer's `aria-errormessage`, routed to the hex field while that state is set. */\n errorMessageId: string | undefined;\n /** The hex field registers its `<input>` here (the hidden input's `onInvalid` focuses it). */\n registerHexInput: (input: HTMLInputElement | null) => void;\n}\n\nexport const ColorPickerContext = React.createContext<ColorPickerContextValue | null>(null);\nColorPickerContext.displayName = 'ColorPickerContext';\n\n/** The enclosing ColorPicker's context, or `null` outside one (the standalone parts need none). */\nexport function useColorPickerContext(): ColorPickerContextValue | null {\n return React.useContext(ColorPickerContext);\n}\n\n/** What a color part passes to {@link useColorPartState}. */\nexport interface ColorPartOptions {\n value: HsvColor | undefined;\n defaultValue: HsvColor | undefined;\n onValueChange: ((value: HsvColor) => void) | undefined;\n disabled: boolean;\n}\n\n/** Where a color part's color lives: in the enclosing picker (bound) or in the part. */\nexport interface ColorPartState {\n /** The enclosing picker when the part binds to it, else `null`. */\n picker: ColorPickerContextValue | null;\n /** The color as given (bound: the picker's working color). */\n color: HsvColor;\n /**\n * Writes a new color. Bound: the picker's working color, then the part's own `onValueChange`\n * (a part given only the callback listens; C-NAMING). Otherwise the part's state, through\n * `useControllable`.\n */\n setColor: (next: HsvColor) => void;\n /** Restores `defaultValue` on a form reset, reporting only a real change; nothing while bound. */\n reset: () => void;\n /** The part's `disabled`, or the picker's disabled state while bound. */\n disabled: boolean;\n}\n\nconst noop = () => {};\n\n/**\n * The binding rule of `ColorArea`, `ColorSlider` and `AlphaSlider` (D21): inside a ColorPicker, a\n * part with neither `value` nor `defaultValue` reads and writes the picker's working color;\n * anywhere else, or with either prop, it keeps its own color.\n */\nexport function useColorPartState({\n value,\n defaultValue,\n onValueChange,\n disabled,\n}: ColorPartOptions): ColorPartState {\n const context = useColorPickerContext();\n const picker =\n context !== null && value === undefined && defaultValue === undefined ? context : null;\n const initial = defaultValue ?? DEFAULT_PART_COLOR;\n const [own, setOwn] = useControllable(value, initial, picker ? undefined : onValueChange);\n if (picker) {\n return {\n picker,\n color: picker.hsv,\n setColor: (next) => {\n picker.setHsv(next);\n onValueChange?.(next);\n },\n reset: noop,\n disabled: disabled || picker.disabled,\n };\n }\n return {\n picker: null,\n color: own,\n setColor: setOwn,\n reset: () => {\n if (!sameColor(own, initial)) setOwn(initial);\n },\n disabled,\n };\n}\n\n// ---------------------------------------------------------------------------------------------\n// The picker-only parts: ColorPicker.HexField, ColorPicker.Swatches, ColorPicker.Preview\n// ---------------------------------------------------------------------------------------------\n\n/** The context a misplaced part renders with in production (C-CONTEXT). */\nconst INERT_PICKER_CONTEXT: ColorPickerContextValue = {\n hsv: DEFAULT_PART_COLOR,\n setHsv: noop,\n color: DEFAULT_COLOR,\n parsed: null,\n setColor: noop,\n pickPreset: noop,\n presetItems: [],\n shape: 'rounded',\n labels: DEFAULT_COLOR_PICKER_LABELS,\n disabled: true,\n draftResetKey: 0,\n field: null,\n groupInvalid: undefined,\n errorMessageId: undefined,\n registerHexInput: noop,\n};\n\n/**\n * The context of a picker-only part: throws `[WaveUI] <name> must be used within <ColorPicker>`\n * in development; logs once and returns an inert value in production (C-CONTEXT).\n */\nexport function usePickerPartContext(componentName: string): ColorPickerContextValue {\n const context = React.useContext(ColorPickerContext);\n if (context) return context;\n reportMissingContext(componentName, '<ColorPicker>');\n return INERT_PICKER_CONTEXT;\n}\n\n/** The hex field's text while the user edits it (`null` state: the field shows the value). */\ninterface HexDraft {\n /** The typed text. */\n text: string;\n /** Kept after leaving the field because it is not a hex color, so it is flagged as invalid. */\n flagged: boolean;\n}\n\n/** A hex draft without digits (`''` or a lone `#`): leaving the field shows the value again. */\nfunction isBlankDraft(text: string): boolean {\n const trimmed = text.trim();\n return trimmed === '' || trimmed === '#';\n}\n\n/** Whether typed hex text carries its own alpha digits (`#rgba` or `#rrggbbaa`). */\nfunction hasAlphaDigits(text: string): boolean {\n const digits = text.trim().replace(/^#/, '').length;\n return digits === 4 || digits === 8;\n}\n\n/**\n * Properties for the ColorPickerHexField sub-component. `id`, the labelling and validation\n * `aria-*` (`aria-label`, `aria-labelledby`, `aria-describedby`, `aria-invalid`,\n * `aria-errormessage`, `aria-details`, `aria-required`), `autoFocus`, `tabIndex`, the focus and key\n * handlers and the text-entry attributes (`inputMode`, `enterKeyHint`, `autoCapitalize`,\n * `autoCorrect`, `spellCheck`) go to the `<input>`; everything else stays on the outer label.\n */\nexport interface ColorPickerHexFieldProps extends React.HTMLAttributes<HTMLElement> {\n /** Ref to the hex `<input>`. */\n controlRef?: React.Ref<HTMLInputElement>;\n /** Ref to the field's outer element: the label around the caption, the input and the error. */\n ref?: React.Ref<HTMLLabelElement>;\n}\n\n/**\n * The hex text field of a ColorPicker: a caption, the input and its error. The text is a draft:\n * complete 6- and 8-digit values apply while typing, text that can never be a hex color is\n * flagged at once, and leaving the field (or Enter) applies a short `#rgb`/`#rgba` and shows the\n * value again; other text stays flagged until it is corrected, cleared, or the value changes from\n * elsewhere (a preset, another part, the parent, a form reset). Inside a Field it carries the\n * Field's invalid state and error. Must be inside a ColorPicker. Also exported as\n * `ColorPickerHexField` (import the flat name in React Server Components).\n */\nexport const ColorPickerHexField = ({\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-errormessage': ariaErrorMessage,\n 'aria-details': ariaDetails,\n 'aria-required': ariaRequired,\n autoFocus,\n tabIndex,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n inputMode,\n enterKeyHint,\n autoCapitalize,\n autoCorrect,\n spellCheck,\n controlRef,\n className,\n ref,\n ...rest\n}: ColorPickerHexFieldProps) => {\n const picker = usePickerPartContext('ColorPicker.HexField');\n const { color, parsed, field, groupInvalid, errorMessageId, labels } = picker;\n const alpha = parsed?.alpha ?? 255;\n\n // The hex text is a draft over `color` while the user edits it (null: show `color`).\n const [draft, setDraft] = React.useState<HexDraft | null>(null);\n // A value change from elsewhere replaces a flagged draft (input-pickers#25); while the user\n // types, the draft is not flagged and stays.\n const [syncedColor, setSyncedColor] = React.useState(color);\n if (color !== syncedColor) {\n setSyncedColor(color);\n if (draft?.flagged) setDraft(null);\n }\n // A form reset or a preset pick drops any draft.\n const [seenResetKey, setSeenResetKey] = React.useState(picker.draftResetKey);\n if (picker.draftResetKey !== seenResetKey) {\n setSeenResetKey(picker.draftResetKey);\n setDraft(null);\n }\n const hexText = draft?.text ?? color;\n const draftInvalid =\n draft !== null && !isBlankDraft(draft.text) && (draft.flagged || !isHexDraft(draft.text));\n // Any invalid state from outside (the picker's prop or the Field) is set on the input as is;\n // only `true` shows the error look.\n const fieldInvalid =\n groupInvalid !== undefined && groupInvalid !== false && groupInvalid !== 'false';\n const errorId = useId('wave-color-picker-error');\n const resolvedInvalid =\n ariaInvalid ?? (draftInvalid ? true : fieldInvalid ? groupInvalid : undefined);\n const invalidLook = isInvalidLook(false, resolvedInvalid);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const mergedInputRef = useMergedRefs(inputRef, controlRef, picker.registerHexInput);\n\n /** The single commit path: every edit is `#rrggbb` + an alpha byte. */\n const commit = (rgb: string, nextAlpha: number) =>\n picker.setColor(formatHexColor(rgb, nextAlpha));\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n // Surrounding whitespace (a pasted `'#abcdef '`) is dropped, so the text that is checked,\n // committed and shown is the same.\n let text = event.target.value.trim();\n if (text !== '' && !text.startsWith('#')) text = `#${text}`;\n setDraft({ text, flagged: false });\n const typed = parseHexInput(text);\n // A 6-digit hex keeps the current opacity; an 8-digit one brings its own alpha.\n if (typed) commit(typed.rgb, hasAlphaDigits(text) ? typed.alpha : alpha);\n };\n\n /** Finishes the draft when the field is left or Enter is pressed. */\n const finishDraft = () => {\n if (draft === null || draft.flagged) return;\n const typed = parseHexColor(draft.text);\n if (typed || isBlankDraft(draft.text)) {\n // A short `#rgb` (current opacity) or `#rgba` is applied here; complete values were\n // applied while typing, so a rejecting parent is not asked twice. Then the field shows the\n // current value (also when a controlled parent rejected it).\n if (typed && !parseHexInput(draft.text)) {\n commit(typed.rgb, hasAlphaDigits(draft.text) ? typed.alpha : alpha);\n }\n setDraft(null);\n return;\n }\n // Text that is not a hex color is kept and flagged instead of thrown away (WCAG 3.3.1).\n setDraft({ text: draft.text, flagged: true });\n };\n\n const handleBlur = composeEventHandlers(onBlur, finishDraft);\n // Not prevented: Enter still submits the surrounding form, with the color just applied.\n const handleKeyDown = composeEventHandlers(\n onKeyDown,\n (event: React.KeyboardEvent<HTMLElement>) => {\n if (event.key === 'Enter' && !event.nativeEvent.isComposing) finishDraft();\n },\n );\n\n return (\n <label\n ref={ref}\n className={cn(colorPickerHexFieldClassNames.root, 'flex min-w-0 flex-col gap-1', className)}\n {...rest}\n >\n <span\n className={cn(colorPickerHexFieldClassNames.label, 'text-caption-1 text-muted-foreground')}\n >\n {labels.hex}\n </span>\n <input\n ref={mergedInputRef}\n id={id}\n type=\"text\"\n value={hexText}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onKeyUp={onKeyUp}\n onFocus={onFocus}\n onBlur={handleBlur}\n aria-label={ariaLabel ?? (ariaLabelledBy === undefined ? labels.hexInput : undefined)}\n aria-labelledby={ariaLabelledBy}\n aria-invalid={resolvedInvalid}\n aria-errormessage={ariaErrorMessage ?? errorMessageId}\n aria-describedby={joinIds(\n draftInvalid && errorId,\n field?.validationMessageId ?? (fieldInvalid ? field?.errorId : undefined),\n errorMessageId,\n ariaDescribedBy,\n )}\n aria-details={ariaDetails}\n aria-required={ariaRequired}\n autoFocus={autoFocus}\n tabIndex={tabIndex}\n inputMode={inputMode}\n enterKeyHint={enterKeyHint}\n autoCapitalize={autoCapitalize}\n autoCorrect={autoCorrect}\n spellCheck={spellCheck ?? false}\n maxLength={9}\n autoComplete=\"off\"\n className={cn(\n colorPickerHexFieldClassNames.input,\n 'w-24 rounded border border-input border-b-stroke-accessible bg-background px-2 py-1 text-body-1 text-foreground',\n inputFocus,\n invalidLook && inputInvalid,\n )}\n />\n {draftInvalid && (\n <span\n id={errorId}\n className={cn(colorPickerHexFieldClassNames.errorMessage, 'text-caption-1 text-error')}\n >\n {labels.hexError}\n </span>\n )}\n </label>\n );\n};\n\nColorPickerHexField.displayName = 'ColorPickerHexField';\n\n/** Properties for the ColorPickerSwatches sub-component: the picker's `presets` as a SwatchPicker. */\nexport type ColorPickerSwatchesProps = Omit<\n SwatchPickerProps,\n 'items' | 'value' | 'defaultValue' | 'onValueChange' | 'onChange' | 'name' | 'form' | 'required'\n>;\n\n/**\n * The picker's `presets` as swatches (a SwatchPicker named by `labels.presets`, small and rounded\n * unless you pass `size` or `shape`). Picking one keeps the opacity. Renders nothing without\n * presets. Must be inside a ColorPicker. Also exported as `ColorPickerSwatches`.\n */\nexport const ColorPickerSwatches = ({\n className,\n 'aria-label': ariaLabel,\n size = 'small',\n shape = 'rounded',\n ...rest\n}: ColorPickerSwatchesProps) => {\n const picker = usePickerPartContext('ColorPicker.Swatches');\n if (picker.presetItems.length === 0) return null;\n return (\n <SwatchPicker\n aria-label={\n ariaLabel ?? (rest['aria-labelledby'] === undefined ? picker.labels.presets : undefined)\n }\n size={size}\n shape={shape}\n {...rest}\n className={cn(colorPickerSwatchesClassNames.root, className)}\n items={picker.presetItems}\n value={picker.parsed ? picker.parsed.rgb : ''}\n onValueChange={picker.pickPreset}\n />\n );\n};\n\nColorPickerSwatches.displayName = 'ColorPickerSwatches';\n\n/** Properties for the ColorPickerPreview sub-component. */\nexport interface ColorPickerPreviewProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/**\n * A swatch of the picker's current color (decorative, `aria-hidden`); it keeps its color in forced\n * colors and follows the picker's `shape`. Must be inside a ColorPicker. Also exported as\n * `ColorPickerPreview`.\n */\nexport const ColorPickerPreview = ({ className, style, ref, ...rest }: ColorPickerPreviewProps) => {\n const picker = usePickerPartContext('ColorPicker.Preview');\n const shown = picker.parsed\n ? formatHexColor(picker.parsed.rgb, picker.parsed.alpha)\n : picker.color;\n return (\n <div\n data-color-preview=\"\"\n aria-hidden=\"true\"\n {...rest}\n ref={ref}\n className={cn(\n colorPickerPreviewClassNames.root,\n 'h-10 w-10 shrink-0 rounded border border-border forced-colors:forced-color-adjust-none',\n picker.shape === 'square' && 'rounded-none',\n className,\n )}\n style={{ ...style, backgroundColor: shown }}\n />\n );\n};\n\nColorPickerPreview.displayName = 'ColorPickerPreview';\n"],"mappings":"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"}
1
+ {"version":3,"file":"ColorPicker.parts.cjs","names":["React","useControllable","sameColor","isHexDraft","useId","isInvalidLook","useMergedRefs","formatHexColor","parseHexInput","parseHexColor","composeEventHandlers","cn","colorPickerHexFieldClassNames","joinIds","inputFocus","SwatchPicker","colorPickerSwatchesClassNames","colorPickerPreviewClassNames","require_runtime","require_cn","require_dev","require_composeEventHandlers","require_classNames","require_useControllable","require_useId","require_useMergedRefs","require_aria","require_styles","require_Input","require_colorUtils","require_SwatchPicker","react","react_jsx_runtime","DEFAULT_COLOR","DEFAULT_PART_COLOR","DEFAULT_COLOR_PICKER_LABELS","ColorPickerContext","useColorPickerContext","noop","useColorPartState","context","picker","value","defaultValue","initial","own","setOwn","onValueChange","next","disabled","INERT_PICKER_CONTEXT","usePickerPartContext","componentName","isBlankDraft","trimmed","text","hasAlphaDigits","digits","ColorPickerHexField","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaErrorMessage","ariaDetails","ariaRequired","rest","alpha","parsed","draft","setDraft","syncedColor","setSyncedColor","color","seenResetKey","setSeenResetKey","hexText","draftInvalid","fieldInvalid","groupInvalid","errorId","resolvedInvalid","invalidLook","inputRef","mergedInputRef","controlRef","commit","rgb","nextAlpha","handleChange","event","typed","finishDraft","handleBlur","onBlur","handleKeyDown","onKeyDown","className","labels","errorMessageId","field","spellCheck","ColorPickerSwatches","ColorPickerPreview","shown","style"],"sources":["../../../src/components/input/ColorPicker.parts.tsx"],"sourcesContent":["import * as React from 'react';\nimport { useControllable } from '../../hooks/useControllable';\nimport type { FieldContextValue } from '../../hooks/useFieldControl';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { joinIds } from '../../lib/aria';\nimport {\n colorPickerHexFieldClassNames,\n colorPickerPreviewClassNames,\n colorPickerSwatchesClassNames,\n} from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { reportMissingContext } from '../../lib/dev';\nimport { inputFocus, inputInvalid } from '../../lib/styles';\nimport type { ColorPickerShape, HsvColor } from '../../lib/types';\nimport { isInvalidLook } from './Input';\nimport { SwatchPicker, type SwatchItem, type SwatchPickerProps } from './SwatchPicker';\nimport {\n formatHexColor,\n isHexDraft,\n parseHexColor,\n parseHexInput,\n sameColor,\n type HexColor,\n} from './colorUtils';\n\n/*\n * The picker's labels and context, and how the standalone color parts bind to it (spec P3-05,\n * D21). `ColorArea`, `ColorSlider` and `AlphaSlider` read the context; `ColorPicker.tsx` provides\n * it and renders the picker-only parts. This module never imports `ColorPicker.tsx`.\n */\n\n// wave-allow-color: default color value (user color data, C-TOKENS exception)\nexport const DEFAULT_COLOR = '#0f6cbd';\n\n/** The default color of a standalone part: the default picker color in HSV. */\nexport const DEFAULT_PART_COLOR: HsvColor = { h: 208, s: 0.92, v: 0.74 };\n\n/**\n * Texts of the ColorPicker's own parts and of the color parts bound to it, for localisation.\n * Every key is optional; missing keys use the English default.\n */\nexport interface ColorPickerLabels {\n /** Visible caption above the hex field.\n * @default 'Hex'\n */\n hex?: string;\n /** Accessible name of the hex text field.\n * @default 'Hex color value'\n */\n hexInput?: string;\n /** Error text shown (and used as the hex field's description) while the typed text can never be\n * a hex color, or when the field is left with text that is not one (such as `#12345`).\n * @default 'Enter a hex color such as #0f6cbd.'\n */\n hexError?: string;\n /** Accessible name of the preset swatches radiogroup.\n * @default 'Preset colors'\n */\n presets?: string;\n /** Visible label of the opacity row and accessible name of the opacity slider (a bound\n * `AlphaSlider`).\n * @default 'Opacity'\n */\n opacity?: string;\n /** Accessible name of a bound `ColorArea`'s group.\n * @default 'Saturation and brightness'\n */\n area?: string;\n /** Name of a bound area's saturation slider and of a bound `channel=\"saturation\"` slider.\n * @default 'Saturation'\n */\n saturation?: string;\n /** Name of a bound area's brightness slider and of a bound `channel=\"value\"` slider.\n * @default 'Brightness'\n */\n brightness?: string;\n /** Role description of a bound area's two sliders.\n * @default '2D slider'\n */\n roleDescription?: string;\n /** Name of a bound hue slider.\n * @default 'Hue'\n */\n hue?: string;\n /** Name of a bound `AlphaSlider` with `transparency`.\n * @default 'Transparency'\n */\n transparency?: string;\n /** Names the color at the end of the bound parts' value texts; return `''` to leave it out.\n * @default an English namer (\"dark blue\")\n */\n colorName?: (color: HsvColor) => string;\n /** Replaces a whole value text of a bound part, for languages whose order differs. */\n valueText?: (color: HsvColor, channel: 'hue' | 'saturation' | 'value' | 'alpha') => string;\n}\n\n/** The labels with every string default filled in (the two functions stay optional). */\nexport type ResolvedColorPickerLabels = Required<\n Omit<ColorPickerLabels, 'colorName' | 'valueText'>\n> &\n Pick<ColorPickerLabels, 'colorName' | 'valueText'>;\n\nexport const DEFAULT_COLOR_PICKER_LABELS: ResolvedColorPickerLabels = {\n hex: 'Hex',\n hexInput: 'Hex color value',\n hexError: `Enter a hex color such as ${DEFAULT_COLOR}.`,\n presets: 'Preset colors',\n opacity: 'Opacity',\n area: 'Saturation and brightness',\n saturation: 'Saturation',\n brightness: 'Brightness',\n roleDescription: '2D slider',\n hue: 'Hue',\n transparency: 'Transparency',\n};\n\n/** What a ColorPicker shares with its parts and with the color parts bound to it. */\nexport interface ColorPickerContextValue {\n /** The working color: HSV, so hue and saturation survive gray, white and black. */\n hsv: HsvColor;\n /** Writes the working color from a bound part and reports its hex (only when the hex changes). */\n setHsv: (next: HsvColor) => void;\n /** The picker's value as given: a hex string, or a value that is not one (as given). */\n color: string;\n /** The value parsed (`#rrggbb` and the alpha byte), `null` while it is not a hex color. */\n parsed: HexColor | null;\n /** Writes the value as hex text (the hex field). */\n setColor: (next: string) => void;\n /** Applies a preset's `#rrggbb` at the current opacity and drops the hex field's draft. */\n pickPreset: (rgb: string) => void;\n /** The picker's presets as swatch items (values are `#rrggbb`). */\n presetItems: readonly SwatchItem[];\n /** The picker's `shape`, inherited by the bound parts and `ColorPicker.Preview`. */\n shape: ColorPickerShape;\n /** The picker's labels with every string default filled in. */\n labels: ResolvedColorPickerLabels;\n /** `true` while the value is not a hex color: the bound parts are disabled until one arrives. */\n disabled: boolean;\n /** Changes whenever the hex field must drop its draft: a form reset or a preset pick. */\n draftResetKey: number;\n /** The Field around the picker (its parts render in a `null` Field context). */\n field: FieldContextValue | null;\n /** The invalid state set on the picker from outside (its `aria-invalid` or the Field's), as given. */\n groupInvalid: React.AriaAttributes['aria-invalid'];\n /** The consumer's `aria-errormessage`, routed to the hex field while that state is set. */\n errorMessageId: string | undefined;\n /** The hex field registers its `<input>` here (the hidden input's `onInvalid` focuses it). */\n registerHexInput: (input: HTMLInputElement | null) => void;\n}\n\nexport const ColorPickerContext = React.createContext<ColorPickerContextValue | null>(null);\nColorPickerContext.displayName = 'ColorPickerContext';\n\n/** The enclosing ColorPicker's context, or `null` outside one (the standalone parts need none). */\nexport function useColorPickerContext(): ColorPickerContextValue | null {\n return React.useContext(ColorPickerContext);\n}\n\n/** What a color part passes to {@link useColorPartState}. */\nexport interface ColorPartOptions {\n value: HsvColor | undefined;\n defaultValue: HsvColor | undefined;\n onValueChange: ((value: HsvColor) => void) | undefined;\n disabled: boolean;\n}\n\n/** Where a color part's color lives: in the enclosing picker (bound) or in the part. */\nexport interface ColorPartState {\n /** The enclosing picker when the part binds to it, else `null`. */\n picker: ColorPickerContextValue | null;\n /** The color as given (bound: the picker's working color). */\n color: HsvColor;\n /**\n * Writes a new color. Bound: the picker's working color, then the part's own `onValueChange`\n * (a part given only the callback listens; C-NAMING). Otherwise the part's state, through\n * `useControllable`.\n */\n setColor: (next: HsvColor) => void;\n /** Restores `defaultValue` on a form reset, reporting only a real change; nothing while bound. */\n reset: () => void;\n /** The part's `disabled`, or the picker's disabled state while bound. */\n disabled: boolean;\n}\n\nconst noop = () => {};\n\n/**\n * The binding rule of `ColorArea`, `ColorSlider` and `AlphaSlider` (D21): inside a ColorPicker, a\n * part with neither `value` nor `defaultValue` reads and writes the picker's working color;\n * anywhere else, or with either prop, it keeps its own color.\n */\nexport function useColorPartState({\n value,\n defaultValue,\n onValueChange,\n disabled,\n}: ColorPartOptions): ColorPartState {\n const context = useColorPickerContext();\n const picker =\n context !== null && value === undefined && defaultValue === undefined ? context : null;\n const initial = defaultValue ?? DEFAULT_PART_COLOR;\n const [own, setOwn] = useControllable(value, initial, picker ? undefined : onValueChange);\n if (picker) {\n return {\n picker,\n color: picker.hsv,\n setColor: (next) => {\n picker.setHsv(next);\n onValueChange?.(next);\n },\n reset: noop,\n disabled: disabled || picker.disabled,\n };\n }\n return {\n picker: null,\n color: own,\n setColor: setOwn,\n reset: () => {\n if (!sameColor(own, initial)) setOwn(initial);\n },\n disabled,\n };\n}\n\n// ---------------------------------------------------------------------------------------------\n// The picker-only parts: ColorPicker.HexField, ColorPicker.Swatches, ColorPicker.Preview\n// ---------------------------------------------------------------------------------------------\n\n/** The context a misplaced part renders with in production (C-CONTEXT). */\nconst INERT_PICKER_CONTEXT: ColorPickerContextValue = {\n hsv: DEFAULT_PART_COLOR,\n setHsv: noop,\n color: DEFAULT_COLOR,\n parsed: null,\n setColor: noop,\n pickPreset: noop,\n presetItems: [],\n shape: 'rounded',\n labels: DEFAULT_COLOR_PICKER_LABELS,\n disabled: true,\n draftResetKey: 0,\n field: null,\n groupInvalid: undefined,\n errorMessageId: undefined,\n registerHexInput: noop,\n};\n\n/**\n * The context of a picker-only part: throws `[WaveUI] <name> must be used within <ColorPicker>`\n * in development; logs once and returns an inert value in production (C-CONTEXT).\n */\nexport function usePickerPartContext(componentName: string): ColorPickerContextValue {\n const context = React.useContext(ColorPickerContext);\n if (context) return context;\n reportMissingContext(componentName, '<ColorPicker>');\n return INERT_PICKER_CONTEXT;\n}\n\n/** The hex field's text while the user edits it (`null` state: the field shows the value). */\ninterface HexDraft {\n /** The typed text. */\n text: string;\n /** Kept after leaving the field because it is not a hex color, so it is flagged as invalid. */\n flagged: boolean;\n}\n\n/** A hex draft without digits (`''` or a lone `#`): leaving the field shows the value again. */\nfunction isBlankDraft(text: string): boolean {\n const trimmed = text.trim();\n return trimmed === '' || trimmed === '#';\n}\n\n/** Whether typed hex text carries its own alpha digits (`#rgba` or `#rrggbbaa`). */\nfunction hasAlphaDigits(text: string): boolean {\n const digits = text.trim().replace(/^#/, '').length;\n return digits === 4 || digits === 8;\n}\n\n/**\n * Properties for the ColorPickerHexField sub-component. `id`, the labelling and validation\n * `aria-*` (`aria-label`, `aria-labelledby`, `aria-describedby`, `aria-invalid`,\n * `aria-errormessage`, `aria-details`, `aria-required`), `autoFocus`, `tabIndex`, the focus and key\n * handlers and the text-entry attributes (`inputMode`, `enterKeyHint`, `autoCapitalize`,\n * `autoCorrect`, `spellCheck`) go to the `<input>`; everything else stays on the outer label.\n */\nexport interface ColorPickerHexFieldProps extends React.HTMLAttributes<HTMLElement> {\n /** Ref to the hex `<input>`. */\n controlRef?: React.Ref<HTMLInputElement>;\n /** Ref to the field's outer element: the label around the caption, the input and the error. */\n ref?: React.Ref<HTMLLabelElement>;\n}\n\n/**\n * The hex text field of a ColorPicker: a caption, the input and its error. The text is a draft:\n * complete 6- and 8-digit values apply while typing, text that can never be a hex color is\n * flagged at once, and leaving the field (or Enter) applies a short `#rgb`/`#rgba` and shows the\n * value again; other text stays flagged until it is corrected, cleared, or the value changes from\n * elsewhere (a preset, another part, the parent, a form reset). Inside a Field it carries the\n * Field's invalid state and error. Must be inside a ColorPicker. Also exported as\n * `ColorPickerHexField` (import the flat name in React Server Components).\n */\nexport const ColorPickerHexField = ({\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-errormessage': ariaErrorMessage,\n 'aria-details': ariaDetails,\n 'aria-required': ariaRequired,\n autoFocus,\n tabIndex,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n inputMode,\n enterKeyHint,\n autoCapitalize,\n autoCorrect,\n spellCheck,\n controlRef,\n className,\n ref,\n ...rest\n}: ColorPickerHexFieldProps) => {\n const picker = usePickerPartContext('ColorPicker.HexField');\n const { color, parsed, field, groupInvalid, errorMessageId, labels } = picker;\n const alpha = parsed?.alpha ?? 255;\n\n // The hex text is a draft over `color` while the user edits it (null: show `color`).\n const [draft, setDraft] = React.useState<HexDraft | null>(null);\n // A value change from elsewhere replaces a flagged draft (input-pickers#25); while the user\n // types, the draft is not flagged and stays.\n const [syncedColor, setSyncedColor] = React.useState(color);\n if (color !== syncedColor) {\n setSyncedColor(color);\n if (draft?.flagged) setDraft(null);\n }\n // A form reset or a preset pick drops any draft.\n const [seenResetKey, setSeenResetKey] = React.useState(picker.draftResetKey);\n if (picker.draftResetKey !== seenResetKey) {\n setSeenResetKey(picker.draftResetKey);\n setDraft(null);\n }\n const hexText = draft?.text ?? color;\n const draftInvalid =\n draft !== null && !isBlankDraft(draft.text) && (draft.flagged || !isHexDraft(draft.text));\n // Any invalid state from outside (the picker's prop or the Field) is set on the input as is;\n // only `true` shows the error look.\n const fieldInvalid =\n groupInvalid !== undefined && groupInvalid !== false && groupInvalid !== 'false';\n const errorId = useId('wave-color-picker-error');\n const resolvedInvalid =\n ariaInvalid ?? (draftInvalid ? true : fieldInvalid ? groupInvalid : undefined);\n const invalidLook = isInvalidLook(false, resolvedInvalid);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const mergedInputRef = useMergedRefs(inputRef, controlRef, picker.registerHexInput);\n\n /** The single commit path: every edit is `#rrggbb` + an alpha byte. */\n const commit = (rgb: string, nextAlpha: number) =>\n picker.setColor(formatHexColor(rgb, nextAlpha));\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n // Surrounding whitespace (a pasted `'#abcdef '`) is dropped, so the text that is checked,\n // committed and shown is the same.\n let text = event.target.value.trim();\n if (text !== '' && !text.startsWith('#')) text = `#${text}`;\n setDraft({ text, flagged: false });\n const typed = parseHexInput(text);\n // A 6-digit hex keeps the current opacity; an 8-digit one brings its own alpha.\n if (typed) commit(typed.rgb, hasAlphaDigits(text) ? typed.alpha : alpha);\n };\n\n /** Finishes the draft when the field is left or Enter is pressed. */\n const finishDraft = () => {\n if (draft === null || draft.flagged) return;\n const typed = parseHexColor(draft.text);\n if (typed || isBlankDraft(draft.text)) {\n // A short `#rgb` (current opacity) or `#rgba` is applied here; complete values were\n // applied while typing, so a rejecting parent is not asked twice. Then the field shows the\n // current value (also when a controlled parent rejected it).\n if (typed && !parseHexInput(draft.text)) {\n commit(typed.rgb, hasAlphaDigits(draft.text) ? typed.alpha : alpha);\n }\n setDraft(null);\n return;\n }\n // Text that is not a hex color is kept and flagged instead of thrown away (WCAG 3.3.1).\n setDraft({ text: draft.text, flagged: true });\n };\n\n const handleBlur = composeEventHandlers(onBlur, finishDraft);\n // Not prevented: Enter still submits the surrounding form, with the color just applied.\n const handleKeyDown = composeEventHandlers(\n onKeyDown,\n (event: React.KeyboardEvent<HTMLElement>) => {\n if (event.key === 'Enter' && !event.nativeEvent.isComposing) finishDraft();\n },\n );\n\n return (\n <label\n ref={ref}\n className={cn(colorPickerHexFieldClassNames.root, 'flex min-w-0 flex-col gap-1', className)}\n {...rest}\n >\n <span\n className={cn(colorPickerHexFieldClassNames.label, 'text-caption-1 text-muted-foreground')}\n >\n {labels.hex}\n </span>\n <input\n ref={mergedInputRef}\n id={id}\n type=\"text\"\n value={hexText}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onKeyUp={onKeyUp}\n onFocus={onFocus}\n onBlur={handleBlur}\n aria-label={ariaLabel ?? (ariaLabelledBy === undefined ? labels.hexInput : undefined)}\n aria-labelledby={ariaLabelledBy}\n aria-invalid={resolvedInvalid}\n aria-errormessage={ariaErrorMessage ?? errorMessageId}\n aria-describedby={joinIds(\n draftInvalid && errorId,\n field?.validationMessageId ?? (fieldInvalid ? field?.errorId : undefined),\n errorMessageId,\n ariaDescribedBy,\n )}\n aria-details={ariaDetails}\n aria-required={ariaRequired}\n autoFocus={autoFocus}\n tabIndex={tabIndex}\n inputMode={inputMode}\n enterKeyHint={enterKeyHint}\n autoCapitalize={autoCapitalize}\n autoCorrect={autoCorrect}\n spellCheck={spellCheck ?? false}\n maxLength={9}\n autoComplete=\"off\"\n className={cn(\n colorPickerHexFieldClassNames.input,\n 'w-24 rounded border border-input border-b-stroke-accessible bg-background px-2 py-1 text-body-1 text-foreground',\n inputFocus,\n invalidLook && inputInvalid,\n )}\n />\n {draftInvalid && (\n <span\n id={errorId}\n className={cn(colorPickerHexFieldClassNames.errorMessage, 'text-caption-1 text-error')}\n >\n {labels.hexError}\n </span>\n )}\n </label>\n );\n};\n\nColorPickerHexField.displayName = 'ColorPickerHexField';\n\n/** Properties for the ColorPickerSwatches sub-component: the picker's `presets` as a SwatchPicker. */\nexport type ColorPickerSwatchesProps = Omit<\n SwatchPickerProps,\n 'items' | 'value' | 'defaultValue' | 'onValueChange' | 'onChange' | 'name' | 'form' | 'required'\n>;\n\n/**\n * The picker's `presets` as swatches (a SwatchPicker named by `labels.presets`, small and rounded\n * unless you pass `size` or `shape`). Picking one keeps the opacity. Renders nothing without\n * presets. Must be inside a ColorPicker. Also exported as `ColorPickerSwatches`.\n */\nexport const ColorPickerSwatches = ({\n className,\n 'aria-label': ariaLabel,\n size = 'small',\n shape = 'rounded',\n ...rest\n}: ColorPickerSwatchesProps) => {\n const picker = usePickerPartContext('ColorPicker.Swatches');\n if (picker.presetItems.length === 0) return null;\n return (\n <SwatchPicker\n aria-label={\n ariaLabel ?? (rest['aria-labelledby'] === undefined ? picker.labels.presets : undefined)\n }\n size={size}\n shape={shape}\n {...rest}\n className={cn(colorPickerSwatchesClassNames.root, className)}\n items={picker.presetItems}\n value={picker.parsed ? picker.parsed.rgb : ''}\n onValueChange={picker.pickPreset}\n />\n );\n};\n\nColorPickerSwatches.displayName = 'ColorPickerSwatches';\n\n/** Properties for the ColorPickerPreview sub-component. */\nexport interface ColorPickerPreviewProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/**\n * A swatch of the picker's current color (decorative, `aria-hidden`); it keeps its color in forced\n * colors and follows the picker's `shape`. Must be inside a ColorPicker. Also exported as\n * `ColorPickerPreview`.\n */\nexport const ColorPickerPreview = ({ className, style, ref, ...rest }: ColorPickerPreviewProps) => {\n const picker = usePickerPartContext('ColorPicker.Preview');\n const shown = picker.parsed\n ? formatHexColor(picker.parsed.rgb, picker.parsed.alpha)\n : picker.color;\n return (\n <div\n data-color-preview=\"\"\n aria-hidden=\"true\"\n {...rest}\n ref={ref}\n className={cn(\n colorPickerPreviewClassNames.root,\n 'h-10 w-10 shrink-0 rounded border border-border forced-colors:forced-color-adjust-none',\n picker.shape === 'square' && 'rounded-none',\n className,\n )}\n style={{ ...style, backgroundColor: shown }}\n />\n );\n};\n\nColorPickerPreview.displayName = 'ColorPickerPreview';\n"],"mappings":"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"}
@@ -146,7 +146,7 @@ var O = ({ id: t, "aria-label": i, "aria-labelledby": a, "aria-describedby": o,
146
146
  spellCheck: M ?? !1,
147
147
  maxLength: 9,
148
148
  autoComplete: "off",
149
- className: e(r.input, "w-24 rounded border border-input border-b-stroke-accessible bg-background px-2 py-1 text-body-1 text-foreground", ee, ce && "border-destructive focus:border-b-destructive")
149
+ className: e(r.input, "w-24 rounded border border-input border-b-stroke-accessible bg-background px-2 py-1 text-body-1 text-foreground", ee, ce && "border-destructive")
150
150
  }),
151
151
  J && /* @__PURE__ */ g("span", {
152
152
  id: X,
@@ -1 +1 @@
1
- {"version":3,"file":"ColorPicker.parts.mjs","names":["useId","useId$1","React","DEFAULT_COLOR","DEFAULT_PART_COLOR","DEFAULT_COLOR_PICKER_LABELS","ColorPickerContext","useColorPickerContext","noop","useColorPartState","context","picker","value","defaultValue","initial","own","setOwn","useControllable","onValueChange","next","disabled","sameColor","INERT_PICKER_CONTEXT","usePickerPartContext","reportMissingContext","componentName","isBlankDraft","trimmed","text","hasAlphaDigits","digits","ColorPickerHexField","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaErrorMessage","ariaDetails","ariaRequired","rest","alpha","parsed","draft","setDraft","syncedColor","setSyncedColor","color","seenResetKey","setSeenResetKey","hexText","draftInvalid","isHexDraft","fieldInvalid","groupInvalid","errorId","resolvedInvalid","invalidLook","isInvalidLook","inputRef","mergedInputRef","useMergedRefs","controlRef","commit","formatHexColor","rgb","nextAlpha","handleChange","event","typed","parseHexInput","finishDraft","parseHexColor","handleBlur","composeEventHandlers","onBlur","handleKeyDown","onKeyDown","cn","colorPickerHexFieldClassNames","className","labels","errorMessageId","joinIds","field","spellCheck","inputFocus","ColorPickerSwatches","SwatchPicker","colorPickerSwatchesClassNames","ColorPickerPreview","shown","colorPickerPreviewClassNames","style"],"sources":["../../../src/components/input/ColorPicker.parts.tsx"],"sourcesContent":["import * as React from 'react';\nimport { useControllable } from '../../hooks/useControllable';\nimport type { FieldContextValue } from '../../hooks/useFieldControl';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { joinIds } from '../../lib/aria';\nimport {\n colorPickerHexFieldClassNames,\n colorPickerPreviewClassNames,\n colorPickerSwatchesClassNames,\n} from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { reportMissingContext } from '../../lib/dev';\nimport { inputFocus, inputInvalid } from '../../lib/styles';\nimport type { ColorPickerShape, HsvColor } from '../../lib/types';\nimport { isInvalidLook } from './Input';\nimport { SwatchPicker, type SwatchItem, type SwatchPickerProps } from './SwatchPicker';\nimport {\n formatHexColor,\n isHexDraft,\n parseHexColor,\n parseHexInput,\n sameColor,\n type HexColor,\n} from './colorUtils';\n\n/*\n * The picker's labels and context, and how the standalone color parts bind to it (spec P3-05,\n * D21). `ColorArea`, `ColorSlider` and `AlphaSlider` read the context; `ColorPicker.tsx` provides\n * it and renders the picker-only parts. This module never imports `ColorPicker.tsx`.\n */\n\n// wave-allow-color: default color value (user color data, C-TOKENS exception)\nexport const DEFAULT_COLOR = '#0f6cbd';\n\n/** The default color of a standalone part: the default picker color in HSV. */\nexport const DEFAULT_PART_COLOR: HsvColor = { h: 208, s: 0.92, v: 0.74 };\n\n/**\n * Texts of the ColorPicker's own parts and of the color parts bound to it, for localisation.\n * Every key is optional; missing keys use the English default.\n */\nexport interface ColorPickerLabels {\n /** Visible caption above the hex field.\n * @default 'Hex'\n */\n hex?: string;\n /** Accessible name of the hex text field.\n * @default 'Hex color value'\n */\n hexInput?: string;\n /** Error text shown (and used as the hex field's description) while the typed text can never be\n * a hex color, or when the field is left with text that is not one (such as `#12345`).\n * @default 'Enter a hex color such as #0f6cbd.'\n */\n hexError?: string;\n /** Accessible name of the preset swatches radiogroup.\n * @default 'Preset colors'\n */\n presets?: string;\n /** Visible label of the opacity row and accessible name of the opacity slider (a bound\n * `AlphaSlider`).\n * @default 'Opacity'\n */\n opacity?: string;\n /** Accessible name of a bound `ColorArea`'s group.\n * @default 'Saturation and brightness'\n */\n area?: string;\n /** Name of a bound area's saturation slider and of a bound `channel=\"saturation\"` slider.\n * @default 'Saturation'\n */\n saturation?: string;\n /** Name of a bound area's brightness slider and of a bound `channel=\"value\"` slider.\n * @default 'Brightness'\n */\n brightness?: string;\n /** Role description of a bound area's two sliders.\n * @default '2D slider'\n */\n roleDescription?: string;\n /** Name of a bound hue slider.\n * @default 'Hue'\n */\n hue?: string;\n /** Name of a bound `AlphaSlider` with `transparency`.\n * @default 'Transparency'\n */\n transparency?: string;\n /** Names the color at the end of the bound parts' value texts; return `''` to leave it out.\n * @default an English namer (\"dark blue\")\n */\n colorName?: (color: HsvColor) => string;\n /** Replaces a whole value text of a bound part, for languages whose order differs. */\n valueText?: (color: HsvColor, channel: 'hue' | 'saturation' | 'value' | 'alpha') => string;\n}\n\n/** The labels with every string default filled in (the two functions stay optional). */\nexport type ResolvedColorPickerLabels = Required<\n Omit<ColorPickerLabels, 'colorName' | 'valueText'>\n> &\n Pick<ColorPickerLabels, 'colorName' | 'valueText'>;\n\nexport const DEFAULT_COLOR_PICKER_LABELS: ResolvedColorPickerLabels = {\n hex: 'Hex',\n hexInput: 'Hex color value',\n hexError: `Enter a hex color such as ${DEFAULT_COLOR}.`,\n presets: 'Preset colors',\n opacity: 'Opacity',\n area: 'Saturation and brightness',\n saturation: 'Saturation',\n brightness: 'Brightness',\n roleDescription: '2D slider',\n hue: 'Hue',\n transparency: 'Transparency',\n};\n\n/** What a ColorPicker shares with its parts and with the color parts bound to it. */\nexport interface ColorPickerContextValue {\n /** The working color: HSV, so hue and saturation survive gray, white and black. */\n hsv: HsvColor;\n /** Writes the working color from a bound part and reports its hex (only when the hex changes). */\n setHsv: (next: HsvColor) => void;\n /** The picker's value as given: a hex string, or a value that is not one (as given). */\n color: string;\n /** The value parsed (`#rrggbb` and the alpha byte), `null` while it is not a hex color. */\n parsed: HexColor | null;\n /** Writes the value as hex text (the hex field). */\n setColor: (next: string) => void;\n /** Applies a preset's `#rrggbb` at the current opacity and drops the hex field's draft. */\n pickPreset: (rgb: string) => void;\n /** The picker's presets as swatch items (values are `#rrggbb`). */\n presetItems: readonly SwatchItem[];\n /** The picker's `shape`, inherited by the bound parts and `ColorPicker.Preview`. */\n shape: ColorPickerShape;\n /** The picker's labels with every string default filled in. */\n labels: ResolvedColorPickerLabels;\n /** `true` while the value is not a hex color: the bound parts are disabled until one arrives. */\n disabled: boolean;\n /** Changes whenever the hex field must drop its draft: a form reset or a preset pick. */\n draftResetKey: number;\n /** The Field around the picker (its parts render in a `null` Field context). */\n field: FieldContextValue | null;\n /** The invalid state set on the picker from outside (its `aria-invalid` or the Field's), as given. */\n groupInvalid: React.AriaAttributes['aria-invalid'];\n /** The consumer's `aria-errormessage`, routed to the hex field while that state is set. */\n errorMessageId: string | undefined;\n /** The hex field registers its `<input>` here (the hidden input's `onInvalid` focuses it). */\n registerHexInput: (input: HTMLInputElement | null) => void;\n}\n\nexport const ColorPickerContext = React.createContext<ColorPickerContextValue | null>(null);\nColorPickerContext.displayName = 'ColorPickerContext';\n\n/** The enclosing ColorPicker's context, or `null` outside one (the standalone parts need none). */\nexport function useColorPickerContext(): ColorPickerContextValue | null {\n return React.useContext(ColorPickerContext);\n}\n\n/** What a color part passes to {@link useColorPartState}. */\nexport interface ColorPartOptions {\n value: HsvColor | undefined;\n defaultValue: HsvColor | undefined;\n onValueChange: ((value: HsvColor) => void) | undefined;\n disabled: boolean;\n}\n\n/** Where a color part's color lives: in the enclosing picker (bound) or in the part. */\nexport interface ColorPartState {\n /** The enclosing picker when the part binds to it, else `null`. */\n picker: ColorPickerContextValue | null;\n /** The color as given (bound: the picker's working color). */\n color: HsvColor;\n /**\n * Writes a new color. Bound: the picker's working color, then the part's own `onValueChange`\n * (a part given only the callback listens; C-NAMING). Otherwise the part's state, through\n * `useControllable`.\n */\n setColor: (next: HsvColor) => void;\n /** Restores `defaultValue` on a form reset, reporting only a real change; nothing while bound. */\n reset: () => void;\n /** The part's `disabled`, or the picker's disabled state while bound. */\n disabled: boolean;\n}\n\nconst noop = () => {};\n\n/**\n * The binding rule of `ColorArea`, `ColorSlider` and `AlphaSlider` (D21): inside a ColorPicker, a\n * part with neither `value` nor `defaultValue` reads and writes the picker's working color;\n * anywhere else, or with either prop, it keeps its own color.\n */\nexport function useColorPartState({\n value,\n defaultValue,\n onValueChange,\n disabled,\n}: ColorPartOptions): ColorPartState {\n const context = useColorPickerContext();\n const picker =\n context !== null && value === undefined && defaultValue === undefined ? context : null;\n const initial = defaultValue ?? DEFAULT_PART_COLOR;\n const [own, setOwn] = useControllable(value, initial, picker ? undefined : onValueChange);\n if (picker) {\n return {\n picker,\n color: picker.hsv,\n setColor: (next) => {\n picker.setHsv(next);\n onValueChange?.(next);\n },\n reset: noop,\n disabled: disabled || picker.disabled,\n };\n }\n return {\n picker: null,\n color: own,\n setColor: setOwn,\n reset: () => {\n if (!sameColor(own, initial)) setOwn(initial);\n },\n disabled,\n };\n}\n\n// ---------------------------------------------------------------------------------------------\n// The picker-only parts: ColorPicker.HexField, ColorPicker.Swatches, ColorPicker.Preview\n// ---------------------------------------------------------------------------------------------\n\n/** The context a misplaced part renders with in production (C-CONTEXT). */\nconst INERT_PICKER_CONTEXT: ColorPickerContextValue = {\n hsv: DEFAULT_PART_COLOR,\n setHsv: noop,\n color: DEFAULT_COLOR,\n parsed: null,\n setColor: noop,\n pickPreset: noop,\n presetItems: [],\n shape: 'rounded',\n labels: DEFAULT_COLOR_PICKER_LABELS,\n disabled: true,\n draftResetKey: 0,\n field: null,\n groupInvalid: undefined,\n errorMessageId: undefined,\n registerHexInput: noop,\n};\n\n/**\n * The context of a picker-only part: throws `[WaveUI] <name> must be used within <ColorPicker>`\n * in development; logs once and returns an inert value in production (C-CONTEXT).\n */\nexport function usePickerPartContext(componentName: string): ColorPickerContextValue {\n const context = React.useContext(ColorPickerContext);\n if (context) return context;\n reportMissingContext(componentName, '<ColorPicker>');\n return INERT_PICKER_CONTEXT;\n}\n\n/** The hex field's text while the user edits it (`null` state: the field shows the value). */\ninterface HexDraft {\n /** The typed text. */\n text: string;\n /** Kept after leaving the field because it is not a hex color, so it is flagged as invalid. */\n flagged: boolean;\n}\n\n/** A hex draft without digits (`''` or a lone `#`): leaving the field shows the value again. */\nfunction isBlankDraft(text: string): boolean {\n const trimmed = text.trim();\n return trimmed === '' || trimmed === '#';\n}\n\n/** Whether typed hex text carries its own alpha digits (`#rgba` or `#rrggbbaa`). */\nfunction hasAlphaDigits(text: string): boolean {\n const digits = text.trim().replace(/^#/, '').length;\n return digits === 4 || digits === 8;\n}\n\n/**\n * Properties for the ColorPickerHexField sub-component. `id`, the labelling and validation\n * `aria-*` (`aria-label`, `aria-labelledby`, `aria-describedby`, `aria-invalid`,\n * `aria-errormessage`, `aria-details`, `aria-required`), `autoFocus`, `tabIndex`, the focus and key\n * handlers and the text-entry attributes (`inputMode`, `enterKeyHint`, `autoCapitalize`,\n * `autoCorrect`, `spellCheck`) go to the `<input>`; everything else stays on the outer label.\n */\nexport interface ColorPickerHexFieldProps extends React.HTMLAttributes<HTMLElement> {\n /** Ref to the hex `<input>`. */\n controlRef?: React.Ref<HTMLInputElement>;\n /** Ref to the field's outer element: the label around the caption, the input and the error. */\n ref?: React.Ref<HTMLLabelElement>;\n}\n\n/**\n * The hex text field of a ColorPicker: a caption, the input and its error. The text is a draft:\n * complete 6- and 8-digit values apply while typing, text that can never be a hex color is\n * flagged at once, and leaving the field (or Enter) applies a short `#rgb`/`#rgba` and shows the\n * value again; other text stays flagged until it is corrected, cleared, or the value changes from\n * elsewhere (a preset, another part, the parent, a form reset). Inside a Field it carries the\n * Field's invalid state and error. Must be inside a ColorPicker. Also exported as\n * `ColorPickerHexField` (import the flat name in React Server Components).\n */\nexport const ColorPickerHexField = ({\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-errormessage': ariaErrorMessage,\n 'aria-details': ariaDetails,\n 'aria-required': ariaRequired,\n autoFocus,\n tabIndex,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n inputMode,\n enterKeyHint,\n autoCapitalize,\n autoCorrect,\n spellCheck,\n controlRef,\n className,\n ref,\n ...rest\n}: ColorPickerHexFieldProps) => {\n const picker = usePickerPartContext('ColorPicker.HexField');\n const { color, parsed, field, groupInvalid, errorMessageId, labels } = picker;\n const alpha = parsed?.alpha ?? 255;\n\n // The hex text is a draft over `color` while the user edits it (null: show `color`).\n const [draft, setDraft] = React.useState<HexDraft | null>(null);\n // A value change from elsewhere replaces a flagged draft (input-pickers#25); while the user\n // types, the draft is not flagged and stays.\n const [syncedColor, setSyncedColor] = React.useState(color);\n if (color !== syncedColor) {\n setSyncedColor(color);\n if (draft?.flagged) setDraft(null);\n }\n // A form reset or a preset pick drops any draft.\n const [seenResetKey, setSeenResetKey] = React.useState(picker.draftResetKey);\n if (picker.draftResetKey !== seenResetKey) {\n setSeenResetKey(picker.draftResetKey);\n setDraft(null);\n }\n const hexText = draft?.text ?? color;\n const draftInvalid =\n draft !== null && !isBlankDraft(draft.text) && (draft.flagged || !isHexDraft(draft.text));\n // Any invalid state from outside (the picker's prop or the Field) is set on the input as is;\n // only `true` shows the error look.\n const fieldInvalid =\n groupInvalid !== undefined && groupInvalid !== false && groupInvalid !== 'false';\n const errorId = useId('wave-color-picker-error');\n const resolvedInvalid =\n ariaInvalid ?? (draftInvalid ? true : fieldInvalid ? groupInvalid : undefined);\n const invalidLook = isInvalidLook(false, resolvedInvalid);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const mergedInputRef = useMergedRefs(inputRef, controlRef, picker.registerHexInput);\n\n /** The single commit path: every edit is `#rrggbb` + an alpha byte. */\n const commit = (rgb: string, nextAlpha: number) =>\n picker.setColor(formatHexColor(rgb, nextAlpha));\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n // Surrounding whitespace (a pasted `'#abcdef '`) is dropped, so the text that is checked,\n // committed and shown is the same.\n let text = event.target.value.trim();\n if (text !== '' && !text.startsWith('#')) text = `#${text}`;\n setDraft({ text, flagged: false });\n const typed = parseHexInput(text);\n // A 6-digit hex keeps the current opacity; an 8-digit one brings its own alpha.\n if (typed) commit(typed.rgb, hasAlphaDigits(text) ? typed.alpha : alpha);\n };\n\n /** Finishes the draft when the field is left or Enter is pressed. */\n const finishDraft = () => {\n if (draft === null || draft.flagged) return;\n const typed = parseHexColor(draft.text);\n if (typed || isBlankDraft(draft.text)) {\n // A short `#rgb` (current opacity) or `#rgba` is applied here; complete values were\n // applied while typing, so a rejecting parent is not asked twice. Then the field shows the\n // current value (also when a controlled parent rejected it).\n if (typed && !parseHexInput(draft.text)) {\n commit(typed.rgb, hasAlphaDigits(draft.text) ? typed.alpha : alpha);\n }\n setDraft(null);\n return;\n }\n // Text that is not a hex color is kept and flagged instead of thrown away (WCAG 3.3.1).\n setDraft({ text: draft.text, flagged: true });\n };\n\n const handleBlur = composeEventHandlers(onBlur, finishDraft);\n // Not prevented: Enter still submits the surrounding form, with the color just applied.\n const handleKeyDown = composeEventHandlers(\n onKeyDown,\n (event: React.KeyboardEvent<HTMLElement>) => {\n if (event.key === 'Enter' && !event.nativeEvent.isComposing) finishDraft();\n },\n );\n\n return (\n <label\n ref={ref}\n className={cn(colorPickerHexFieldClassNames.root, 'flex min-w-0 flex-col gap-1', className)}\n {...rest}\n >\n <span\n className={cn(colorPickerHexFieldClassNames.label, 'text-caption-1 text-muted-foreground')}\n >\n {labels.hex}\n </span>\n <input\n ref={mergedInputRef}\n id={id}\n type=\"text\"\n value={hexText}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onKeyUp={onKeyUp}\n onFocus={onFocus}\n onBlur={handleBlur}\n aria-label={ariaLabel ?? (ariaLabelledBy === undefined ? labels.hexInput : undefined)}\n aria-labelledby={ariaLabelledBy}\n aria-invalid={resolvedInvalid}\n aria-errormessage={ariaErrorMessage ?? errorMessageId}\n aria-describedby={joinIds(\n draftInvalid && errorId,\n field?.validationMessageId ?? (fieldInvalid ? field?.errorId : undefined),\n errorMessageId,\n ariaDescribedBy,\n )}\n aria-details={ariaDetails}\n aria-required={ariaRequired}\n autoFocus={autoFocus}\n tabIndex={tabIndex}\n inputMode={inputMode}\n enterKeyHint={enterKeyHint}\n autoCapitalize={autoCapitalize}\n autoCorrect={autoCorrect}\n spellCheck={spellCheck ?? false}\n maxLength={9}\n autoComplete=\"off\"\n className={cn(\n colorPickerHexFieldClassNames.input,\n 'w-24 rounded border border-input border-b-stroke-accessible bg-background px-2 py-1 text-body-1 text-foreground',\n inputFocus,\n invalidLook && inputInvalid,\n )}\n />\n {draftInvalid && (\n <span\n id={errorId}\n className={cn(colorPickerHexFieldClassNames.errorMessage, 'text-caption-1 text-error')}\n >\n {labels.hexError}\n </span>\n )}\n </label>\n );\n};\n\nColorPickerHexField.displayName = 'ColorPickerHexField';\n\n/** Properties for the ColorPickerSwatches sub-component: the picker's `presets` as a SwatchPicker. */\nexport type ColorPickerSwatchesProps = Omit<\n SwatchPickerProps,\n 'items' | 'value' | 'defaultValue' | 'onValueChange' | 'onChange' | 'name' | 'form' | 'required'\n>;\n\n/**\n * The picker's `presets` as swatches (a SwatchPicker named by `labels.presets`, small and rounded\n * unless you pass `size` or `shape`). Picking one keeps the opacity. Renders nothing without\n * presets. Must be inside a ColorPicker. Also exported as `ColorPickerSwatches`.\n */\nexport const ColorPickerSwatches = ({\n className,\n 'aria-label': ariaLabel,\n size = 'small',\n shape = 'rounded',\n ...rest\n}: ColorPickerSwatchesProps) => {\n const picker = usePickerPartContext('ColorPicker.Swatches');\n if (picker.presetItems.length === 0) return null;\n return (\n <SwatchPicker\n aria-label={\n ariaLabel ?? (rest['aria-labelledby'] === undefined ? picker.labels.presets : undefined)\n }\n size={size}\n shape={shape}\n {...rest}\n className={cn(colorPickerSwatchesClassNames.root, className)}\n items={picker.presetItems}\n value={picker.parsed ? picker.parsed.rgb : ''}\n onValueChange={picker.pickPreset}\n />\n );\n};\n\nColorPickerSwatches.displayName = 'ColorPickerSwatches';\n\n/** Properties for the ColorPickerPreview sub-component. */\nexport interface ColorPickerPreviewProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/**\n * A swatch of the picker's current color (decorative, `aria-hidden`); it keeps its color in forced\n * colors and follows the picker's `shape`. Must be inside a ColorPicker. Also exported as\n * `ColorPickerPreview`.\n */\nexport const ColorPickerPreview = ({ className, style, ref, ...rest }: ColorPickerPreviewProps) => {\n const picker = usePickerPartContext('ColorPicker.Preview');\n const shown = picker.parsed\n ? formatHexColor(picker.parsed.rgb, picker.parsed.alpha)\n : picker.color;\n return (\n <div\n data-color-preview=\"\"\n aria-hidden=\"true\"\n {...rest}\n ref={ref}\n className={cn(\n colorPickerPreviewClassNames.root,\n 'h-10 w-10 shrink-0 rounded border border-border forced-colors:forced-color-adjust-none',\n picker.shape === 'square' && 'rounded-none',\n className,\n )}\n style={{ ...style, backgroundColor: shown }}\n />\n );\n};\n\nColorPickerPreview.displayName = 'ColorPickerPreview';\n"],"mappings":"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"}
1
+ {"version":3,"file":"ColorPicker.parts.mjs","names":["useId","useId$1","React","DEFAULT_COLOR","DEFAULT_PART_COLOR","DEFAULT_COLOR_PICKER_LABELS","ColorPickerContext","useColorPickerContext","noop","useColorPartState","context","picker","value","defaultValue","initial","own","setOwn","useControllable","onValueChange","next","disabled","sameColor","INERT_PICKER_CONTEXT","usePickerPartContext","reportMissingContext","componentName","isBlankDraft","trimmed","text","hasAlphaDigits","digits","ColorPickerHexField","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaErrorMessage","ariaDetails","ariaRequired","rest","alpha","parsed","draft","setDraft","syncedColor","setSyncedColor","color","seenResetKey","setSeenResetKey","hexText","draftInvalid","isHexDraft","fieldInvalid","groupInvalid","errorId","resolvedInvalid","invalidLook","isInvalidLook","inputRef","mergedInputRef","useMergedRefs","controlRef","commit","formatHexColor","rgb","nextAlpha","handleChange","event","typed","parseHexInput","finishDraft","parseHexColor","handleBlur","composeEventHandlers","onBlur","handleKeyDown","onKeyDown","cn","colorPickerHexFieldClassNames","className","labels","errorMessageId","joinIds","field","spellCheck","inputFocus","ColorPickerSwatches","SwatchPicker","colorPickerSwatchesClassNames","ColorPickerPreview","shown","colorPickerPreviewClassNames","style"],"sources":["../../../src/components/input/ColorPicker.parts.tsx"],"sourcesContent":["import * as React from 'react';\nimport { useControllable } from '../../hooks/useControllable';\nimport type { FieldContextValue } from '../../hooks/useFieldControl';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { joinIds } from '../../lib/aria';\nimport {\n colorPickerHexFieldClassNames,\n colorPickerPreviewClassNames,\n colorPickerSwatchesClassNames,\n} from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { reportMissingContext } from '../../lib/dev';\nimport { inputFocus, inputInvalid } from '../../lib/styles';\nimport type { ColorPickerShape, HsvColor } from '../../lib/types';\nimport { isInvalidLook } from './Input';\nimport { SwatchPicker, type SwatchItem, type SwatchPickerProps } from './SwatchPicker';\nimport {\n formatHexColor,\n isHexDraft,\n parseHexColor,\n parseHexInput,\n sameColor,\n type HexColor,\n} from './colorUtils';\n\n/*\n * The picker's labels and context, and how the standalone color parts bind to it (spec P3-05,\n * D21). `ColorArea`, `ColorSlider` and `AlphaSlider` read the context; `ColorPicker.tsx` provides\n * it and renders the picker-only parts. This module never imports `ColorPicker.tsx`.\n */\n\n// wave-allow-color: default color value (user color data, C-TOKENS exception)\nexport const DEFAULT_COLOR = '#0f6cbd';\n\n/** The default color of a standalone part: the default picker color in HSV. */\nexport const DEFAULT_PART_COLOR: HsvColor = { h: 208, s: 0.92, v: 0.74 };\n\n/**\n * Texts of the ColorPicker's own parts and of the color parts bound to it, for localisation.\n * Every key is optional; missing keys use the English default.\n */\nexport interface ColorPickerLabels {\n /** Visible caption above the hex field.\n * @default 'Hex'\n */\n hex?: string;\n /** Accessible name of the hex text field.\n * @default 'Hex color value'\n */\n hexInput?: string;\n /** Error text shown (and used as the hex field's description) while the typed text can never be\n * a hex color, or when the field is left with text that is not one (such as `#12345`).\n * @default 'Enter a hex color such as #0f6cbd.'\n */\n hexError?: string;\n /** Accessible name of the preset swatches radiogroup.\n * @default 'Preset colors'\n */\n presets?: string;\n /** Visible label of the opacity row and accessible name of the opacity slider (a bound\n * `AlphaSlider`).\n * @default 'Opacity'\n */\n opacity?: string;\n /** Accessible name of a bound `ColorArea`'s group.\n * @default 'Saturation and brightness'\n */\n area?: string;\n /** Name of a bound area's saturation slider and of a bound `channel=\"saturation\"` slider.\n * @default 'Saturation'\n */\n saturation?: string;\n /** Name of a bound area's brightness slider and of a bound `channel=\"value\"` slider.\n * @default 'Brightness'\n */\n brightness?: string;\n /** Role description of a bound area's two sliders.\n * @default '2D slider'\n */\n roleDescription?: string;\n /** Name of a bound hue slider.\n * @default 'Hue'\n */\n hue?: string;\n /** Name of a bound `AlphaSlider` with `transparency`.\n * @default 'Transparency'\n */\n transparency?: string;\n /** Names the color at the end of the bound parts' value texts; return `''` to leave it out.\n * @default an English namer (\"dark blue\")\n */\n colorName?: (color: HsvColor) => string;\n /** Replaces a whole value text of a bound part, for languages whose order differs. */\n valueText?: (color: HsvColor, channel: 'hue' | 'saturation' | 'value' | 'alpha') => string;\n}\n\n/** The labels with every string default filled in (the two functions stay optional). */\nexport type ResolvedColorPickerLabels = Required<\n Omit<ColorPickerLabels, 'colorName' | 'valueText'>\n> &\n Pick<ColorPickerLabels, 'colorName' | 'valueText'>;\n\nexport const DEFAULT_COLOR_PICKER_LABELS: ResolvedColorPickerLabels = {\n hex: 'Hex',\n hexInput: 'Hex color value',\n hexError: `Enter a hex color such as ${DEFAULT_COLOR}.`,\n presets: 'Preset colors',\n opacity: 'Opacity',\n area: 'Saturation and brightness',\n saturation: 'Saturation',\n brightness: 'Brightness',\n roleDescription: '2D slider',\n hue: 'Hue',\n transparency: 'Transparency',\n};\n\n/** What a ColorPicker shares with its parts and with the color parts bound to it. */\nexport interface ColorPickerContextValue {\n /** The working color: HSV, so hue and saturation survive gray, white and black. */\n hsv: HsvColor;\n /** Writes the working color from a bound part and reports its hex (only when the hex changes). */\n setHsv: (next: HsvColor) => void;\n /** The picker's value as given: a hex string, or a value that is not one (as given). */\n color: string;\n /** The value parsed (`#rrggbb` and the alpha byte), `null` while it is not a hex color. */\n parsed: HexColor | null;\n /** Writes the value as hex text (the hex field). */\n setColor: (next: string) => void;\n /** Applies a preset's `#rrggbb` at the current opacity and drops the hex field's draft. */\n pickPreset: (rgb: string) => void;\n /** The picker's presets as swatch items (values are `#rrggbb`). */\n presetItems: readonly SwatchItem[];\n /** The picker's `shape`, inherited by the bound parts and `ColorPicker.Preview`. */\n shape: ColorPickerShape;\n /** The picker's labels with every string default filled in. */\n labels: ResolvedColorPickerLabels;\n /** `true` while the value is not a hex color: the bound parts are disabled until one arrives. */\n disabled: boolean;\n /** Changes whenever the hex field must drop its draft: a form reset or a preset pick. */\n draftResetKey: number;\n /** The Field around the picker (its parts render in a `null` Field context). */\n field: FieldContextValue | null;\n /** The invalid state set on the picker from outside (its `aria-invalid` or the Field's), as given. */\n groupInvalid: React.AriaAttributes['aria-invalid'];\n /** The consumer's `aria-errormessage`, routed to the hex field while that state is set. */\n errorMessageId: string | undefined;\n /** The hex field registers its `<input>` here (the hidden input's `onInvalid` focuses it). */\n registerHexInput: (input: HTMLInputElement | null) => void;\n}\n\nexport const ColorPickerContext = React.createContext<ColorPickerContextValue | null>(null);\nColorPickerContext.displayName = 'ColorPickerContext';\n\n/** The enclosing ColorPicker's context, or `null` outside one (the standalone parts need none). */\nexport function useColorPickerContext(): ColorPickerContextValue | null {\n return React.useContext(ColorPickerContext);\n}\n\n/** What a color part passes to {@link useColorPartState}. */\nexport interface ColorPartOptions {\n value: HsvColor | undefined;\n defaultValue: HsvColor | undefined;\n onValueChange: ((value: HsvColor) => void) | undefined;\n disabled: boolean;\n}\n\n/** Where a color part's color lives: in the enclosing picker (bound) or in the part. */\nexport interface ColorPartState {\n /** The enclosing picker when the part binds to it, else `null`. */\n picker: ColorPickerContextValue | null;\n /** The color as given (bound: the picker's working color). */\n color: HsvColor;\n /**\n * Writes a new color. Bound: the picker's working color, then the part's own `onValueChange`\n * (a part given only the callback listens; C-NAMING). Otherwise the part's state, through\n * `useControllable`.\n */\n setColor: (next: HsvColor) => void;\n /** Restores `defaultValue` on a form reset, reporting only a real change; nothing while bound. */\n reset: () => void;\n /** The part's `disabled`, or the picker's disabled state while bound. */\n disabled: boolean;\n}\n\nconst noop = () => {};\n\n/**\n * The binding rule of `ColorArea`, `ColorSlider` and `AlphaSlider` (D21): inside a ColorPicker, a\n * part with neither `value` nor `defaultValue` reads and writes the picker's working color;\n * anywhere else, or with either prop, it keeps its own color.\n */\nexport function useColorPartState({\n value,\n defaultValue,\n onValueChange,\n disabled,\n}: ColorPartOptions): ColorPartState {\n const context = useColorPickerContext();\n const picker =\n context !== null && value === undefined && defaultValue === undefined ? context : null;\n const initial = defaultValue ?? DEFAULT_PART_COLOR;\n const [own, setOwn] = useControllable(value, initial, picker ? undefined : onValueChange);\n if (picker) {\n return {\n picker,\n color: picker.hsv,\n setColor: (next) => {\n picker.setHsv(next);\n onValueChange?.(next);\n },\n reset: noop,\n disabled: disabled || picker.disabled,\n };\n }\n return {\n picker: null,\n color: own,\n setColor: setOwn,\n reset: () => {\n if (!sameColor(own, initial)) setOwn(initial);\n },\n disabled,\n };\n}\n\n// ---------------------------------------------------------------------------------------------\n// The picker-only parts: ColorPicker.HexField, ColorPicker.Swatches, ColorPicker.Preview\n// ---------------------------------------------------------------------------------------------\n\n/** The context a misplaced part renders with in production (C-CONTEXT). */\nconst INERT_PICKER_CONTEXT: ColorPickerContextValue = {\n hsv: DEFAULT_PART_COLOR,\n setHsv: noop,\n color: DEFAULT_COLOR,\n parsed: null,\n setColor: noop,\n pickPreset: noop,\n presetItems: [],\n shape: 'rounded',\n labels: DEFAULT_COLOR_PICKER_LABELS,\n disabled: true,\n draftResetKey: 0,\n field: null,\n groupInvalid: undefined,\n errorMessageId: undefined,\n registerHexInput: noop,\n};\n\n/**\n * The context of a picker-only part: throws `[WaveUI] <name> must be used within <ColorPicker>`\n * in development; logs once and returns an inert value in production (C-CONTEXT).\n */\nexport function usePickerPartContext(componentName: string): ColorPickerContextValue {\n const context = React.useContext(ColorPickerContext);\n if (context) return context;\n reportMissingContext(componentName, '<ColorPicker>');\n return INERT_PICKER_CONTEXT;\n}\n\n/** The hex field's text while the user edits it (`null` state: the field shows the value). */\ninterface HexDraft {\n /** The typed text. */\n text: string;\n /** Kept after leaving the field because it is not a hex color, so it is flagged as invalid. */\n flagged: boolean;\n}\n\n/** A hex draft without digits (`''` or a lone `#`): leaving the field shows the value again. */\nfunction isBlankDraft(text: string): boolean {\n const trimmed = text.trim();\n return trimmed === '' || trimmed === '#';\n}\n\n/** Whether typed hex text carries its own alpha digits (`#rgba` or `#rrggbbaa`). */\nfunction hasAlphaDigits(text: string): boolean {\n const digits = text.trim().replace(/^#/, '').length;\n return digits === 4 || digits === 8;\n}\n\n/**\n * Properties for the ColorPickerHexField sub-component. `id`, the labelling and validation\n * `aria-*` (`aria-label`, `aria-labelledby`, `aria-describedby`, `aria-invalid`,\n * `aria-errormessage`, `aria-details`, `aria-required`), `autoFocus`, `tabIndex`, the focus and key\n * handlers and the text-entry attributes (`inputMode`, `enterKeyHint`, `autoCapitalize`,\n * `autoCorrect`, `spellCheck`) go to the `<input>`; everything else stays on the outer label.\n */\nexport interface ColorPickerHexFieldProps extends React.HTMLAttributes<HTMLElement> {\n /** Ref to the hex `<input>`. */\n controlRef?: React.Ref<HTMLInputElement>;\n /** Ref to the field's outer element: the label around the caption, the input and the error. */\n ref?: React.Ref<HTMLLabelElement>;\n}\n\n/**\n * The hex text field of a ColorPicker: a caption, the input and its error. The text is a draft:\n * complete 6- and 8-digit values apply while typing, text that can never be a hex color is\n * flagged at once, and leaving the field (or Enter) applies a short `#rgb`/`#rgba` and shows the\n * value again; other text stays flagged until it is corrected, cleared, or the value changes from\n * elsewhere (a preset, another part, the parent, a form reset). Inside a Field it carries the\n * Field's invalid state and error. Must be inside a ColorPicker. Also exported as\n * `ColorPickerHexField` (import the flat name in React Server Components).\n */\nexport const ColorPickerHexField = ({\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-errormessage': ariaErrorMessage,\n 'aria-details': ariaDetails,\n 'aria-required': ariaRequired,\n autoFocus,\n tabIndex,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n inputMode,\n enterKeyHint,\n autoCapitalize,\n autoCorrect,\n spellCheck,\n controlRef,\n className,\n ref,\n ...rest\n}: ColorPickerHexFieldProps) => {\n const picker = usePickerPartContext('ColorPicker.HexField');\n const { color, parsed, field, groupInvalid, errorMessageId, labels } = picker;\n const alpha = parsed?.alpha ?? 255;\n\n // The hex text is a draft over `color` while the user edits it (null: show `color`).\n const [draft, setDraft] = React.useState<HexDraft | null>(null);\n // A value change from elsewhere replaces a flagged draft (input-pickers#25); while the user\n // types, the draft is not flagged and stays.\n const [syncedColor, setSyncedColor] = React.useState(color);\n if (color !== syncedColor) {\n setSyncedColor(color);\n if (draft?.flagged) setDraft(null);\n }\n // A form reset or a preset pick drops any draft.\n const [seenResetKey, setSeenResetKey] = React.useState(picker.draftResetKey);\n if (picker.draftResetKey !== seenResetKey) {\n setSeenResetKey(picker.draftResetKey);\n setDraft(null);\n }\n const hexText = draft?.text ?? color;\n const draftInvalid =\n draft !== null && !isBlankDraft(draft.text) && (draft.flagged || !isHexDraft(draft.text));\n // Any invalid state from outside (the picker's prop or the Field) is set on the input as is;\n // only `true` shows the error look.\n const fieldInvalid =\n groupInvalid !== undefined && groupInvalid !== false && groupInvalid !== 'false';\n const errorId = useId('wave-color-picker-error');\n const resolvedInvalid =\n ariaInvalid ?? (draftInvalid ? true : fieldInvalid ? groupInvalid : undefined);\n const invalidLook = isInvalidLook(false, resolvedInvalid);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const mergedInputRef = useMergedRefs(inputRef, controlRef, picker.registerHexInput);\n\n /** The single commit path: every edit is `#rrggbb` + an alpha byte. */\n const commit = (rgb: string, nextAlpha: number) =>\n picker.setColor(formatHexColor(rgb, nextAlpha));\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n // Surrounding whitespace (a pasted `'#abcdef '`) is dropped, so the text that is checked,\n // committed and shown is the same.\n let text = event.target.value.trim();\n if (text !== '' && !text.startsWith('#')) text = `#${text}`;\n setDraft({ text, flagged: false });\n const typed = parseHexInput(text);\n // A 6-digit hex keeps the current opacity; an 8-digit one brings its own alpha.\n if (typed) commit(typed.rgb, hasAlphaDigits(text) ? typed.alpha : alpha);\n };\n\n /** Finishes the draft when the field is left or Enter is pressed. */\n const finishDraft = () => {\n if (draft === null || draft.flagged) return;\n const typed = parseHexColor(draft.text);\n if (typed || isBlankDraft(draft.text)) {\n // A short `#rgb` (current opacity) or `#rgba` is applied here; complete values were\n // applied while typing, so a rejecting parent is not asked twice. Then the field shows the\n // current value (also when a controlled parent rejected it).\n if (typed && !parseHexInput(draft.text)) {\n commit(typed.rgb, hasAlphaDigits(draft.text) ? typed.alpha : alpha);\n }\n setDraft(null);\n return;\n }\n // Text that is not a hex color is kept and flagged instead of thrown away (WCAG 3.3.1).\n setDraft({ text: draft.text, flagged: true });\n };\n\n const handleBlur = composeEventHandlers(onBlur, finishDraft);\n // Not prevented: Enter still submits the surrounding form, with the color just applied.\n const handleKeyDown = composeEventHandlers(\n onKeyDown,\n (event: React.KeyboardEvent<HTMLElement>) => {\n if (event.key === 'Enter' && !event.nativeEvent.isComposing) finishDraft();\n },\n );\n\n return (\n <label\n ref={ref}\n className={cn(colorPickerHexFieldClassNames.root, 'flex min-w-0 flex-col gap-1', className)}\n {...rest}\n >\n <span\n className={cn(colorPickerHexFieldClassNames.label, 'text-caption-1 text-muted-foreground')}\n >\n {labels.hex}\n </span>\n <input\n ref={mergedInputRef}\n id={id}\n type=\"text\"\n value={hexText}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onKeyUp={onKeyUp}\n onFocus={onFocus}\n onBlur={handleBlur}\n aria-label={ariaLabel ?? (ariaLabelledBy === undefined ? labels.hexInput : undefined)}\n aria-labelledby={ariaLabelledBy}\n aria-invalid={resolvedInvalid}\n aria-errormessage={ariaErrorMessage ?? errorMessageId}\n aria-describedby={joinIds(\n draftInvalid && errorId,\n field?.validationMessageId ?? (fieldInvalid ? field?.errorId : undefined),\n errorMessageId,\n ariaDescribedBy,\n )}\n aria-details={ariaDetails}\n aria-required={ariaRequired}\n autoFocus={autoFocus}\n tabIndex={tabIndex}\n inputMode={inputMode}\n enterKeyHint={enterKeyHint}\n autoCapitalize={autoCapitalize}\n autoCorrect={autoCorrect}\n spellCheck={spellCheck ?? false}\n maxLength={9}\n autoComplete=\"off\"\n className={cn(\n colorPickerHexFieldClassNames.input,\n 'w-24 rounded border border-input border-b-stroke-accessible bg-background px-2 py-1 text-body-1 text-foreground',\n inputFocus,\n invalidLook && inputInvalid,\n )}\n />\n {draftInvalid && (\n <span\n id={errorId}\n className={cn(colorPickerHexFieldClassNames.errorMessage, 'text-caption-1 text-error')}\n >\n {labels.hexError}\n </span>\n )}\n </label>\n );\n};\n\nColorPickerHexField.displayName = 'ColorPickerHexField';\n\n/** Properties for the ColorPickerSwatches sub-component: the picker's `presets` as a SwatchPicker. */\nexport type ColorPickerSwatchesProps = Omit<\n SwatchPickerProps,\n 'items' | 'value' | 'defaultValue' | 'onValueChange' | 'onChange' | 'name' | 'form' | 'required'\n>;\n\n/**\n * The picker's `presets` as swatches (a SwatchPicker named by `labels.presets`, small and rounded\n * unless you pass `size` or `shape`). Picking one keeps the opacity. Renders nothing without\n * presets. Must be inside a ColorPicker. Also exported as `ColorPickerSwatches`.\n */\nexport const ColorPickerSwatches = ({\n className,\n 'aria-label': ariaLabel,\n size = 'small',\n shape = 'rounded',\n ...rest\n}: ColorPickerSwatchesProps) => {\n const picker = usePickerPartContext('ColorPicker.Swatches');\n if (picker.presetItems.length === 0) return null;\n return (\n <SwatchPicker\n aria-label={\n ariaLabel ?? (rest['aria-labelledby'] === undefined ? picker.labels.presets : undefined)\n }\n size={size}\n shape={shape}\n {...rest}\n className={cn(colorPickerSwatchesClassNames.root, className)}\n items={picker.presetItems}\n value={picker.parsed ? picker.parsed.rgb : ''}\n onValueChange={picker.pickPreset}\n />\n );\n};\n\nColorPickerSwatches.displayName = 'ColorPickerSwatches';\n\n/** Properties for the ColorPickerPreview sub-component. */\nexport interface ColorPickerPreviewProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/**\n * A swatch of the picker's current color (decorative, `aria-hidden`); it keeps its color in forced\n * colors and follows the picker's `shape`. Must be inside a ColorPicker. Also exported as\n * `ColorPickerPreview`.\n */\nexport const ColorPickerPreview = ({ className, style, ref, ...rest }: ColorPickerPreviewProps) => {\n const picker = usePickerPartContext('ColorPicker.Preview');\n const shown = picker.parsed\n ? formatHexColor(picker.parsed.rgb, picker.parsed.alpha)\n : picker.color;\n return (\n <div\n data-color-preview=\"\"\n aria-hidden=\"true\"\n {...rest}\n ref={ref}\n className={cn(\n colorPickerPreviewClassNames.root,\n 'h-10 w-10 shrink-0 rounded border border-border forced-colors:forced-color-adjust-none',\n picker.shape === 'square' && 'rounded-none',\n className,\n )}\n style={{ ...style, backgroundColor: shown }}\n />\n );\n};\n\nColorPickerPreview.displayName = 'ColorPickerPreview';\n"],"mappings":"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"}