@prototyperco/ui 0.5.0-alpha.0 → 0.5.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 (349) hide show
  1. package/dist/components/accordion.cjs +154 -0
  2. package/dist/components/accordion.cjs.map +1 -0
  3. package/dist/components/accordion.d.cts +14 -0
  4. package/dist/components/accordion.d.ts +14 -0
  5. package/dist/components/accordion.js +127 -0
  6. package/dist/components/accordion.js.map +1 -0
  7. package/dist/components/alert-dialog.cjs +324 -0
  8. package/dist/components/alert-dialog.cjs.map +1 -0
  9. package/dist/components/alert-dialog.d.cts +30 -0
  10. package/dist/components/alert-dialog.d.ts +30 -0
  11. package/dist/components/alert-dialog.js +289 -0
  12. package/dist/components/alert-dialog.js.map +1 -0
  13. package/dist/components/alert.cjs +105 -0
  14. package/dist/components/alert.cjs.map +1 -0
  15. package/dist/components/alert.d.cts +17 -0
  16. package/dist/components/alert.d.ts +17 -0
  17. package/dist/components/alert.js +78 -0
  18. package/dist/components/alert.js.map +1 -0
  19. package/dist/components/autocomplete.cjs +512 -0
  20. package/dist/components/autocomplete.cjs.map +1 -0
  21. package/dist/components/autocomplete.d.cts +31 -0
  22. package/dist/components/autocomplete.d.ts +31 -0
  23. package/dist/components/autocomplete.js +472 -0
  24. package/dist/components/autocomplete.js.map +1 -0
  25. package/dist/components/avatar.cjs +144 -0
  26. package/dist/components/avatar.cjs.map +1 -0
  27. package/dist/components/avatar.d.cts +18 -0
  28. package/dist/components/avatar.d.ts +18 -0
  29. package/dist/components/avatar.js +115 -0
  30. package/dist/components/avatar.js.map +1 -0
  31. package/dist/components/badge.cjs +81 -0
  32. package/dist/components/badge.cjs.map +1 -0
  33. package/dist/components/badge.d.cts +13 -0
  34. package/dist/components/badge.d.ts +13 -0
  35. package/dist/components/badge.js +56 -0
  36. package/dist/components/badge.js.map +1 -0
  37. package/dist/components/breadcrumb.cjs +142 -0
  38. package/dist/components/breadcrumb.cjs.map +1 -0
  39. package/dist/components/breadcrumb.d.cts +20 -0
  40. package/dist/components/breadcrumb.d.ts +20 -0
  41. package/dist/components/breadcrumb.js +112 -0
  42. package/dist/components/breadcrumb.js.map +1 -0
  43. package/dist/components/button.cjs +145 -0
  44. package/dist/components/button.cjs.map +1 -0
  45. package/dist/components/button.d.cts +16 -0
  46. package/dist/components/button.d.ts +16 -0
  47. package/dist/components/button.js +120 -0
  48. package/dist/components/button.js.map +1 -0
  49. package/dist/components/card.cjs +141 -0
  50. package/dist/components/card.cjs.map +1 -0
  51. package/dist/components/card.d.cts +23 -0
  52. package/dist/components/card.d.ts +23 -0
  53. package/dist/components/card.js +111 -0
  54. package/dist/components/card.js.map +1 -0
  55. package/dist/components/checkbox-group.cjs +56 -0
  56. package/dist/components/checkbox-group.cjs.map +1 -0
  57. package/dist/components/checkbox-group.d.cts +8 -0
  58. package/dist/components/checkbox-group.d.ts +8 -0
  59. package/dist/components/checkbox-group.js +32 -0
  60. package/dist/components/checkbox-group.js.map +1 -0
  61. package/dist/components/checkbox.cjs +152 -0
  62. package/dist/components/checkbox.cjs.map +1 -0
  63. package/dist/components/checkbox.d.cts +12 -0
  64. package/dist/components/checkbox.d.ts +12 -0
  65. package/dist/components/checkbox.js +126 -0
  66. package/dist/components/checkbox.js.map +1 -0
  67. package/dist/components/collapsible.cjs +89 -0
  68. package/dist/components/collapsible.cjs.map +1 -0
  69. package/dist/components/collapsible.d.cts +12 -0
  70. package/dist/components/collapsible.d.ts +12 -0
  71. package/dist/components/collapsible.js +63 -0
  72. package/dist/components/collapsible.js.map +1 -0
  73. package/dist/components/color-picker.cjs +983 -0
  74. package/dist/components/color-picker.cjs.map +1 -0
  75. package/dist/components/color-picker.d.cts +41 -0
  76. package/dist/components/color-picker.d.ts +41 -0
  77. package/dist/components/color-picker.js +939 -0
  78. package/dist/components/color-picker.js.map +1 -0
  79. package/dist/components/columns.cjs +163 -0
  80. package/dist/components/columns.cjs.map +1 -0
  81. package/dist/components/columns.d.cts +16 -0
  82. package/dist/components/columns.d.ts +16 -0
  83. package/dist/components/columns.js +136 -0
  84. package/dist/components/columns.js.map +1 -0
  85. package/dist/components/combobox.cjs +633 -0
  86. package/dist/components/combobox.cjs.map +1 -0
  87. package/dist/components/combobox.d.cts +40 -0
  88. package/dist/components/combobox.d.ts +40 -0
  89. package/dist/components/combobox.js +576 -0
  90. package/dist/components/combobox.js.map +1 -0
  91. package/dist/components/command-palette.cjs +370 -0
  92. package/dist/components/command-palette.cjs.map +1 -0
  93. package/dist/components/command-palette.d.cts +42 -0
  94. package/dist/components/command-palette.d.ts +42 -0
  95. package/dist/components/command-palette.js +329 -0
  96. package/dist/components/command-palette.js.map +1 -0
  97. package/dist/components/container.cjs +80 -0
  98. package/dist/components/container.cjs.map +1 -0
  99. package/dist/components/container.d.cts +27 -0
  100. package/dist/components/container.d.ts +27 -0
  101. package/dist/components/container.js +54 -0
  102. package/dist/components/container.js.map +1 -0
  103. package/dist/components/context-menu.cjs +309 -0
  104. package/dist/components/context-menu.cjs.map +1 -0
  105. package/dist/components/context-menu.d.cts +37 -0
  106. package/dist/components/context-menu.d.ts +37 -0
  107. package/dist/components/context-menu.js +271 -0
  108. package/dist/components/context-menu.js.map +1 -0
  109. package/dist/components/dialog.cjs +319 -0
  110. package/dist/components/dialog.cjs.map +1 -0
  111. package/dist/components/dialog.d.cts +32 -0
  112. package/dist/components/dialog.d.ts +32 -0
  113. package/dist/components/dialog.js +285 -0
  114. package/dist/components/dialog.js.map +1 -0
  115. package/dist/components/drawer.cjs +185 -0
  116. package/dist/components/drawer.cjs.map +1 -0
  117. package/dist/components/drawer.d.cts +32 -0
  118. package/dist/components/drawer.d.ts +32 -0
  119. package/dist/components/drawer.js +151 -0
  120. package/dist/components/drawer.js.map +1 -0
  121. package/dist/components/field.cjs +334 -0
  122. package/dist/components/field.cjs.map +1 -0
  123. package/dist/components/field.d.cts +39 -0
  124. package/dist/components/field.d.ts +39 -0
  125. package/dist/components/field.js +299 -0
  126. package/dist/components/field.js.map +1 -0
  127. package/dist/components/fieldset.cjs +75 -0
  128. package/dist/components/fieldset.cjs.map +1 -0
  129. package/dist/components/fieldset.d.cts +12 -0
  130. package/dist/components/fieldset.d.ts +12 -0
  131. package/dist/components/fieldset.js +50 -0
  132. package/dist/components/fieldset.js.map +1 -0
  133. package/dist/components/form.cjs +52 -0
  134. package/dist/components/form.cjs.map +1 -0
  135. package/dist/components/form.d.cts +8 -0
  136. package/dist/components/form.d.ts +8 -0
  137. package/dist/components/form.js +28 -0
  138. package/dist/components/form.js.map +1 -0
  139. package/dist/components/input-group.cjs +338 -0
  140. package/dist/components/input-group.cjs.map +1 -0
  141. package/dist/components/input-group.d.cts +27 -0
  142. package/dist/components/input-group.d.ts +27 -0
  143. package/dist/components/input-group.js +307 -0
  144. package/dist/components/input-group.js.map +1 -0
  145. package/dist/components/input.cjs +63 -0
  146. package/dist/components/input.cjs.map +1 -0
  147. package/dist/components/input.d.cts +8 -0
  148. package/dist/components/input.d.ts +8 -0
  149. package/dist/components/input.js +39 -0
  150. package/dist/components/input.js.map +1 -0
  151. package/dist/components/label.cjs +54 -0
  152. package/dist/components/label.cjs.map +1 -0
  153. package/dist/components/label.d.cts +8 -0
  154. package/dist/components/label.d.ts +8 -0
  155. package/dist/components/label.js +28 -0
  156. package/dist/components/label.js.map +1 -0
  157. package/dist/components/menu.cjs +305 -0
  158. package/dist/components/menu.cjs.map +1 -0
  159. package/dist/components/menu.d.cts +37 -0
  160. package/dist/components/menu.d.ts +37 -0
  161. package/dist/components/menu.js +267 -0
  162. package/dist/components/menu.js.map +1 -0
  163. package/dist/components/menubar.cjs +503 -0
  164. package/dist/components/menubar.cjs.map +1 -0
  165. package/dist/components/menubar.d.cts +37 -0
  166. package/dist/components/menubar.d.ts +37 -0
  167. package/dist/components/menubar.js +464 -0
  168. package/dist/components/menubar.js.map +1 -0
  169. package/dist/components/meter.cjs +152 -0
  170. package/dist/components/meter.cjs.map +1 -0
  171. package/dist/components/meter.d.cts +23 -0
  172. package/dist/components/meter.d.ts +23 -0
  173. package/dist/components/meter.js +122 -0
  174. package/dist/components/meter.js.map +1 -0
  175. package/dist/components/navigation-menu.cjs +315 -0
  176. package/dist/components/navigation-menu.cjs.map +1 -0
  177. package/dist/components/navigation-menu.d.cts +22 -0
  178. package/dist/components/navigation-menu.d.ts +22 -0
  179. package/dist/components/navigation-menu.js +283 -0
  180. package/dist/components/navigation-menu.js.map +1 -0
  181. package/dist/components/number-field.cjs +217 -0
  182. package/dist/components/number-field.cjs.map +1 -0
  183. package/dist/components/number-field.d.cts +23 -0
  184. package/dist/components/number-field.d.ts +23 -0
  185. package/dist/components/number-field.js +185 -0
  186. package/dist/components/number-field.js.map +1 -0
  187. package/dist/components/popover.cjs +125 -0
  188. package/dist/components/popover.cjs.map +1 -0
  189. package/dist/components/popover.d.cts +16 -0
  190. package/dist/components/popover.d.ts +16 -0
  191. package/dist/components/popover.js +96 -0
  192. package/dist/components/popover.js.map +1 -0
  193. package/dist/components/preview-card.cjs +86 -0
  194. package/dist/components/preview-card.cjs.map +1 -0
  195. package/dist/components/preview-card.d.cts +12 -0
  196. package/dist/components/preview-card.d.ts +12 -0
  197. package/dist/components/preview-card.js +60 -0
  198. package/dist/components/preview-card.js.map +1 -0
  199. package/dist/components/progress.cjs +167 -0
  200. package/dist/components/progress.cjs.map +1 -0
  201. package/dist/components/progress.d.cts +23 -0
  202. package/dist/components/progress.d.ts +23 -0
  203. package/dist/components/progress.js +137 -0
  204. package/dist/components/progress.js.map +1 -0
  205. package/dist/components/radio-group.cjs +98 -0
  206. package/dist/components/radio-group.cjs.map +1 -0
  207. package/dist/components/radio-group.d.cts +11 -0
  208. package/dist/components/radio-group.d.ts +11 -0
  209. package/dist/components/radio-group.js +73 -0
  210. package/dist/components/radio-group.js.map +1 -0
  211. package/dist/components/resizable-panel.cjs +91 -0
  212. package/dist/components/resizable-panel.cjs.map +1 -0
  213. package/dist/components/resizable-panel.d.cts +14 -0
  214. package/dist/components/resizable-panel.d.ts +14 -0
  215. package/dist/components/resizable-panel.js +69 -0
  216. package/dist/components/resizable-panel.js.map +1 -0
  217. package/dist/components/row.cjs +94 -0
  218. package/dist/components/row.cjs.map +1 -0
  219. package/dist/components/row.d.cts +27 -0
  220. package/dist/components/row.d.ts +27 -0
  221. package/dist/components/row.js +68 -0
  222. package/dist/components/row.js.map +1 -0
  223. package/dist/components/scroll-area.cjs +96 -0
  224. package/dist/components/scroll-area.cjs.map +1 -0
  225. package/dist/components/scroll-area.d.cts +10 -0
  226. package/dist/components/scroll-area.d.ts +10 -0
  227. package/dist/components/scroll-area.js +71 -0
  228. package/dist/components/scroll-area.js.map +1 -0
  229. package/dist/components/section.cjs +104 -0
  230. package/dist/components/section.cjs.map +1 -0
  231. package/dist/components/section.d.cts +26 -0
  232. package/dist/components/section.d.ts +26 -0
  233. package/dist/components/section.js +79 -0
  234. package/dist/components/section.js.map +1 -0
  235. package/dist/components/segmented-control.cjs +117 -0
  236. package/dist/components/segmented-control.cjs.map +1 -0
  237. package/dist/components/segmented-control.d.cts +16 -0
  238. package/dist/components/segmented-control.d.ts +16 -0
  239. package/dist/components/segmented-control.js +91 -0
  240. package/dist/components/segmented-control.js.map +1 -0
  241. package/dist/components/select.cjs +273 -0
  242. package/dist/components/select.cjs.map +1 -0
  243. package/dist/components/select.d.cts +26 -0
  244. package/dist/components/select.d.ts +26 -0
  245. package/dist/components/select.js +239 -0
  246. package/dist/components/select.js.map +1 -0
  247. package/dist/components/separator.cjs +60 -0
  248. package/dist/components/separator.cjs.map +1 -0
  249. package/dist/components/separator.d.cts +8 -0
  250. package/dist/components/separator.d.ts +8 -0
  251. package/dist/components/separator.js +36 -0
  252. package/dist/components/separator.js.map +1 -0
  253. package/dist/components/skeleton.cjs +54 -0
  254. package/dist/components/skeleton.cjs.map +1 -0
  255. package/dist/components/skeleton.d.cts +8 -0
  256. package/dist/components/skeleton.d.ts +8 -0
  257. package/dist/components/skeleton.js +28 -0
  258. package/dist/components/skeleton.js.map +1 -0
  259. package/dist/components/slider.cjs +221 -0
  260. package/dist/components/slider.cjs.map +1 -0
  261. package/dist/components/slider.d.cts +16 -0
  262. package/dist/components/slider.d.ts +16 -0
  263. package/dist/components/slider.js +182 -0
  264. package/dist/components/slider.js.map +1 -0
  265. package/dist/components/spinner.cjs +97 -0
  266. package/dist/components/spinner.cjs.map +1 -0
  267. package/dist/components/spinner.d.cts +13 -0
  268. package/dist/components/spinner.d.ts +13 -0
  269. package/dist/components/spinner.js +72 -0
  270. package/dist/components/spinner.js.map +1 -0
  271. package/dist/components/switch.cjs +177 -0
  272. package/dist/components/switch.cjs.map +1 -0
  273. package/dist/components/switch.d.cts +22 -0
  274. package/dist/components/switch.d.ts +22 -0
  275. package/dist/components/switch.js +139 -0
  276. package/dist/components/switch.js.map +1 -0
  277. package/dist/components/tabs.cjs +123 -0
  278. package/dist/components/tabs.cjs.map +1 -0
  279. package/dist/components/tabs.d.cts +19 -0
  280. package/dist/components/tabs.d.ts +19 -0
  281. package/dist/components/tabs.js +95 -0
  282. package/dist/components/tabs.js.map +1 -0
  283. package/dist/components/text-field.cjs +290 -0
  284. package/dist/components/text-field.cjs.map +1 -0
  285. package/dist/components/text-field.d.cts +27 -0
  286. package/dist/components/text-field.d.ts +27 -0
  287. package/dist/components/text-field.js +262 -0
  288. package/dist/components/text-field.js.map +1 -0
  289. package/dist/components/textarea.cjs +60 -0
  290. package/dist/components/textarea.cjs.map +1 -0
  291. package/dist/components/textarea.d.cts +8 -0
  292. package/dist/components/textarea.d.ts +8 -0
  293. package/dist/components/textarea.js +34 -0
  294. package/dist/components/textarea.js.map +1 -0
  295. package/dist/components/toast.cjs +167 -0
  296. package/dist/components/toast.cjs.map +1 -0
  297. package/dist/components/toast.d.cts +28 -0
  298. package/dist/components/toast.d.ts +28 -0
  299. package/dist/components/toast.js +147 -0
  300. package/dist/components/toast.js.map +1 -0
  301. package/dist/components/toggle-group.cjs +171 -0
  302. package/dist/components/toggle-group.cjs.map +1 -0
  303. package/dist/components/toggle-group.d.cts +18 -0
  304. package/dist/components/toggle-group.d.ts +18 -0
  305. package/dist/components/toggle-group.js +136 -0
  306. package/dist/components/toggle-group.js.map +1 -0
  307. package/dist/components/toggle.cjs +92 -0
  308. package/dist/components/toggle.cjs.map +1 -0
  309. package/dist/components/toggle.d.cts +14 -0
  310. package/dist/components/toggle.d.ts +14 -0
  311. package/dist/components/toggle.js +67 -0
  312. package/dist/components/toggle.js.map +1 -0
  313. package/dist/components/toolbar.cjs +160 -0
  314. package/dist/components/toolbar.cjs.map +1 -0
  315. package/dist/components/toolbar.d.cts +14 -0
  316. package/dist/components/toolbar.d.ts +14 -0
  317. package/dist/components/toolbar.js +131 -0
  318. package/dist/components/toolbar.js.map +1 -0
  319. package/dist/components/tooltip.cjs +116 -0
  320. package/dist/components/tooltip.cjs.map +1 -0
  321. package/dist/components/tooltip.d.cts +13 -0
  322. package/dist/components/tooltip.d.ts +13 -0
  323. package/dist/components/tooltip.js +89 -0
  324. package/dist/components/tooltip.js.map +1 -0
  325. package/dist/components/tree-view.cjs +472 -0
  326. package/dist/components/tree-view.cjs.map +1 -0
  327. package/dist/components/tree-view.d.cts +33 -0
  328. package/dist/components/tree-view.d.ts +33 -0
  329. package/dist/components/tree-view.js +435 -0
  330. package/dist/components/tree-view.js.map +1 -0
  331. package/dist/index.cjs +11 -14
  332. package/dist/index.cjs.map +1 -1
  333. package/dist/index.d.cts +101 -903
  334. package/dist/index.d.ts +101 -903
  335. package/dist/index.js +4 -6
  336. package/dist/index.js.map +1 -1
  337. package/dist/lib/color-utils.cjs +315 -0
  338. package/dist/lib/color-utils.cjs.map +1 -0
  339. package/dist/lib/color-utils.d.cts +24 -0
  340. package/dist/lib/color-utils.d.ts +24 -0
  341. package/dist/lib/color-utils.js +280 -0
  342. package/dist/lib/color-utils.js.map +1 -0
  343. package/dist/lib/utils.cjs +35 -0
  344. package/dist/lib/utils.cjs.map +1 -0
  345. package/dist/lib/utils.d.cts +5 -0
  346. package/dist/lib/utils.d.ts +5 -0
  347. package/dist/lib/utils.js +10 -0
  348. package/dist/lib/utils.js.map +1 -0
  349. package/package.json +24 -5
@@ -0,0 +1,939 @@
1
+ "use client";
2
+
3
+ // src/components/color-picker.tsx
4
+ import * as React from "react";
5
+ import { Popover as PopoverPrimitive } from "@base-ui/react/popover";
6
+ import { Pipette } from "lucide-react";
7
+
8
+ // src/lib/utils.ts
9
+ import { clsx } from "clsx";
10
+ import { twMerge } from "tailwind-merge";
11
+ function cn(...inputs) {
12
+ return twMerge(clsx(inputs));
13
+ }
14
+
15
+ // src/lib/color-utils.ts
16
+ var DEG = Math.PI / 180;
17
+ var MAX_CHROMA = 0.4;
18
+ function clamp(v, min, max) {
19
+ return Math.min(max, Math.max(min, v));
20
+ }
21
+ function round(v, d) {
22
+ const f = 10 ** d;
23
+ return Math.round(v * f) / f;
24
+ }
25
+ function oklchToOklab(l, c, h) {
26
+ const hRad = h * DEG;
27
+ return { L: l, a: c * Math.cos(hRad), b: c * Math.sin(hRad) };
28
+ }
29
+ function oklabToOklch(L, a, b) {
30
+ const c = Math.sqrt(a * a + b * b);
31
+ let h = Math.atan2(b, a) / DEG;
32
+ if (h < 0) h += 360;
33
+ return { l: L, c, h };
34
+ }
35
+ function oklabToLinearRgb(L, a, b) {
36
+ const l_ = L + 0.3963377774 * a + 0.2158037573 * b;
37
+ const m_ = L - 0.1055613458 * a - 0.0638541728 * b;
38
+ const s_ = L - 0.0894841775 * a - 1.291485548 * b;
39
+ const l = l_ * l_ * l_;
40
+ const m = m_ * m_ * m_;
41
+ const s = s_ * s_ * s_;
42
+ return {
43
+ r: 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
44
+ g: -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
45
+ b: -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s
46
+ };
47
+ }
48
+ function linearRgbToOklab(r, g, b) {
49
+ const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
50
+ const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
51
+ const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
52
+ return {
53
+ L: 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,
54
+ a: 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,
55
+ b: 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s
56
+ };
57
+ }
58
+ function linearToSrgb(c) {
59
+ return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
60
+ }
61
+ function srgbToLinear(c) {
62
+ return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
63
+ }
64
+ function oklchToRgb(l, c, h) {
65
+ const lab = oklchToOklab(l, c, h);
66
+ const lin = oklabToLinearRgb(lab.L, lab.a, lab.b);
67
+ return [
68
+ clamp(Math.round(linearToSrgb(lin.r) * 255), 0, 255),
69
+ clamp(Math.round(linearToSrgb(lin.g) * 255), 0, 255),
70
+ clamp(Math.round(linearToSrgb(lin.b) * 255), 0, 255)
71
+ ];
72
+ }
73
+ function rgbToOklch(r, g, b) {
74
+ const lr = srgbToLinear(r / 255);
75
+ const lg = srgbToLinear(g / 255);
76
+ const lb = srgbToLinear(b / 255);
77
+ const lab = linearRgbToOklab(lr, lg, lb);
78
+ return oklabToOklch(lab.L, lab.a, lab.b);
79
+ }
80
+ function isInGamut(l, c, h) {
81
+ const lab = oklchToOklab(l, c, h);
82
+ const lin = oklabToLinearRgb(lab.L, lab.a, lab.b);
83
+ const eps = 1e-3;
84
+ return lin.r >= -eps && lin.r <= 1 + eps && lin.g >= -eps && lin.g <= 1 + eps && lin.b >= -eps && lin.b <= 1 + eps;
85
+ }
86
+ function gamutMapChroma(l, c, h) {
87
+ if (isInGamut(l, c, h)) return c;
88
+ let lo = 0;
89
+ let hi = c;
90
+ while (hi - lo > 1e-3) {
91
+ const mid = (lo + hi) / 2;
92
+ if (isInGamut(l, mid, h)) lo = mid;
93
+ else hi = mid;
94
+ }
95
+ return lo;
96
+ }
97
+ function hexToRgb(hex) {
98
+ hex = hex.replace(/^#/, "");
99
+ if (hex.length === 3 || hex.length === 4) {
100
+ hex = hex.split("").map((c) => c + c).join("");
101
+ }
102
+ const r = parseInt(hex.slice(0, 2), 16);
103
+ const g = parseInt(hex.slice(2, 4), 16);
104
+ const b = parseInt(hex.slice(4, 6), 16);
105
+ const a = hex.length === 8 ? parseInt(hex.slice(6, 8), 16) / 255 : 1;
106
+ return [r, g, b, a];
107
+ }
108
+ function rgbToHex(r, g, b, a) {
109
+ const hex = [r, g, b].map((v) => clamp(Math.round(v), 0, 255).toString(16).padStart(2, "0")).join("");
110
+ if (a !== void 0 && a < 1) {
111
+ return `#${hex}${clamp(Math.round(a * 255), 0, 255).toString(16).padStart(2, "0")}`;
112
+ }
113
+ return `#${hex}`;
114
+ }
115
+ function parseColor(input) {
116
+ const s = input.trim().toLowerCase();
117
+ if (s.startsWith("#")) {
118
+ const [r, g, b, a] = hexToRgb(s);
119
+ if (isNaN(r) || isNaN(g) || isNaN(b)) return null;
120
+ const oklch = rgbToOklch(r, g, b);
121
+ return { l: oklch.l, c: oklch.c, h: oklch.h, a };
122
+ }
123
+ const oklchMatch = s.match(
124
+ /oklch\(\s*([\d.]+)%?\s+([\d.]+)\s+([\d.]+)(?:\s*\/\s*([\d.]+%?))?\s*\)/
125
+ );
126
+ if (oklchMatch) {
127
+ let l = parseFloat(oklchMatch[1]);
128
+ if (l > 1) l /= 100;
129
+ const c = parseFloat(oklchMatch[2]);
130
+ const h = parseFloat(oklchMatch[3]);
131
+ let a = 1;
132
+ if (oklchMatch[4]) {
133
+ a = oklchMatch[4].endsWith("%") ? parseFloat(oklchMatch[4]) / 100 : parseFloat(oklchMatch[4]);
134
+ }
135
+ return { l, c, h, a };
136
+ }
137
+ const rgbMatch = s.match(
138
+ /rgba?\(\s*([\d.]+)[,\s]+([\d.]+)[,\s]+([\d.]+)(?:[,\s/]+([\d.]+%?))?\s*\)/
139
+ );
140
+ if (rgbMatch) {
141
+ const r = parseFloat(rgbMatch[1]);
142
+ const g = parseFloat(rgbMatch[2]);
143
+ const b = parseFloat(rgbMatch[3]);
144
+ let a = 1;
145
+ if (rgbMatch[4]) {
146
+ a = rgbMatch[4].endsWith("%") ? parseFloat(rgbMatch[4]) / 100 : parseFloat(rgbMatch[4]);
147
+ }
148
+ const oklch = rgbToOklch(r, g, b);
149
+ return { l: oklch.l, c: oklch.c, h: oklch.h, a };
150
+ }
151
+ const hslMatch = s.match(
152
+ /hsla?\(\s*([\d.]+)[,\s]+([\d.]+)%[,\s]+([\d.]+)%(?:[,\s/]+([\d.]+%?))?\s*\)/
153
+ );
154
+ if (hslMatch) {
155
+ const [r, g, b] = hslToRgb(
156
+ parseFloat(hslMatch[1]),
157
+ parseFloat(hslMatch[2]),
158
+ parseFloat(hslMatch[3])
159
+ );
160
+ let a = 1;
161
+ if (hslMatch[4]) {
162
+ a = hslMatch[4].endsWith("%") ? parseFloat(hslMatch[4]) / 100 : parseFloat(hslMatch[4]);
163
+ }
164
+ const oklch = rgbToOklch(r, g, b);
165
+ return { l: oklch.l, c: oklch.c, h: oklch.h, a };
166
+ }
167
+ const named = {
168
+ white: "#ffffff",
169
+ black: "#000000",
170
+ red: "#ff0000",
171
+ green: "#008000",
172
+ blue: "#0000ff",
173
+ yellow: "#ffff00",
174
+ cyan: "#00ffff",
175
+ magenta: "#ff00ff",
176
+ orange: "#ffa500",
177
+ transparent: "#00000000"
178
+ };
179
+ if (named[s]) return parseColor(named[s]);
180
+ return null;
181
+ }
182
+ function hslToRgb(h, s, l) {
183
+ s /= 100;
184
+ l /= 100;
185
+ const c = (1 - Math.abs(2 * l - 1)) * s;
186
+ const x = c * (1 - Math.abs(h / 60 % 2 - 1));
187
+ const m = l - c / 2;
188
+ let r = 0, g = 0, b = 0;
189
+ if (h < 60) {
190
+ r = c;
191
+ g = x;
192
+ } else if (h < 120) {
193
+ r = x;
194
+ g = c;
195
+ } else if (h < 180) {
196
+ g = c;
197
+ b = x;
198
+ } else if (h < 240) {
199
+ g = x;
200
+ b = c;
201
+ } else if (h < 300) {
202
+ r = x;
203
+ b = c;
204
+ } else {
205
+ r = c;
206
+ b = x;
207
+ }
208
+ return [
209
+ Math.round((r + m) * 255),
210
+ Math.round((g + m) * 255),
211
+ Math.round((b + m) * 255)
212
+ ];
213
+ }
214
+ function rgbToHsl(r, g, b) {
215
+ r /= 255;
216
+ g /= 255;
217
+ b /= 255;
218
+ const max = Math.max(r, g, b);
219
+ const min = Math.min(r, g, b);
220
+ const l = (max + min) / 2;
221
+ if (max === min) return [0, 0, l * 100];
222
+ const d = max - min;
223
+ const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
224
+ let h = 0;
225
+ if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
226
+ else if (max === g) h = ((b - r) / d + 2) / 6;
227
+ else h = ((r - g) / d + 4) / 6;
228
+ return [h * 360, s * 100, l * 100];
229
+ }
230
+ function formatColor(color, format) {
231
+ const hasAlpha = color.a < 1;
232
+ switch (format) {
233
+ case "hex": {
234
+ const [r, g, b] = oklchToRgb(color.l, color.c, color.h);
235
+ return rgbToHex(r, g, b, hasAlpha ? color.a : void 0);
236
+ }
237
+ case "oklch": {
238
+ const l = round(color.l * 100, 1);
239
+ const c = round(color.c, 3);
240
+ const h = round(color.h, 1);
241
+ return hasAlpha ? `oklch(${l}% ${c} ${h} / ${round(color.a, 2)})` : `oklch(${l}% ${c} ${h})`;
242
+ }
243
+ case "rgb": {
244
+ const [r, g, b] = oklchToRgb(color.l, color.c, color.h);
245
+ return hasAlpha ? `rgba(${r}, ${g}, ${b}, ${round(color.a, 2)})` : `rgb(${r}, ${g}, ${b})`;
246
+ }
247
+ case "hsl": {
248
+ const [r, g, b] = oklchToRgb(color.l, color.c, color.h);
249
+ const [h, s, l] = rgbToHsl(r, g, b);
250
+ return hasAlpha ? `hsla(${round(h, 0)}, ${round(s, 1)}%, ${round(l, 1)}%, ${round(color.a, 2)})` : `hsl(${round(h, 0)}, ${round(s, 1)}%, ${round(l, 1)}%)`;
251
+ }
252
+ }
253
+ }
254
+ function renderAreaGradient(width, height, hue) {
255
+ const data = new ImageData(width, height);
256
+ const buf = data.data;
257
+ for (let y = 0; y < height; y++) {
258
+ const l = 1 - y / (height - 1);
259
+ for (let x = 0; x < width; x++) {
260
+ const c = x / (width - 1) * MAX_CHROMA;
261
+ const [r, g, b] = oklchToRgb(l, c, hue);
262
+ const idx = (y * width + x) * 4;
263
+ buf[idx] = r;
264
+ buf[idx + 1] = g;
265
+ buf[idx + 2] = b;
266
+ buf[idx + 3] = 255;
267
+ }
268
+ }
269
+ return data;
270
+ }
271
+
272
+ // src/components/color-picker.tsx
273
+ import { jsx, jsxs } from "react/jsx-runtime";
274
+ var ColorPickerCtx = React.createContext(
275
+ null
276
+ );
277
+ function useColorPicker() {
278
+ const ctx = React.useContext(ColorPickerCtx);
279
+ if (!ctx)
280
+ throw new Error(
281
+ "ColorPicker sub-components must be used within <ColorPicker>"
282
+ );
283
+ return ctx;
284
+ }
285
+ function ColorPicker({
286
+ value: controlledValue,
287
+ defaultValue = "#6366f1",
288
+ onValueChange,
289
+ onValueCommit,
290
+ outputFormat = "hex",
291
+ name,
292
+ disabled = false,
293
+ enableAlpha = false,
294
+ open,
295
+ onOpenChange,
296
+ children,
297
+ className
298
+ }) {
299
+ const [internal, setInternal] = React.useState(
300
+ () => parseColor(controlledValue ?? defaultValue) ?? {
301
+ l: 0.55,
302
+ c: 0.25,
303
+ h: 264,
304
+ a: 1
305
+ }
306
+ );
307
+ const [isDragging, setIsDragging] = React.useState(false);
308
+ const prevControlled = React.useRef(controlledValue);
309
+ React.useEffect(() => {
310
+ if (controlledValue !== void 0 && controlledValue !== prevControlled.current) {
311
+ prevControlled.current = controlledValue;
312
+ const parsed = parseColor(controlledValue);
313
+ if (parsed) setInternal(parsed);
314
+ }
315
+ }, [controlledValue]);
316
+ const color = React.useMemo(() => {
317
+ if (controlledValue !== void 0) {
318
+ return parseColor(controlledValue) ?? internal;
319
+ }
320
+ return internal;
321
+ }, [controlledValue, internal]);
322
+ const cssValue = React.useMemo(
323
+ () => formatColor(color, outputFormat),
324
+ [color, outputFormat]
325
+ );
326
+ const updateColor = React.useCallback(
327
+ (next) => {
328
+ setInternal(next);
329
+ const formatted = formatColor(next, outputFormat);
330
+ onValueChange?.(formatted);
331
+ },
332
+ [outputFormat, onValueChange]
333
+ );
334
+ const setChannel = React.useCallback(
335
+ (channel, value) => {
336
+ updateColor({ ...color, [channel]: value });
337
+ },
338
+ [color, updateColor]
339
+ );
340
+ const setColor = React.useCallback(
341
+ (next) => {
342
+ updateColor(next);
343
+ },
344
+ [updateColor]
345
+ );
346
+ const setColorFromString = React.useCallback(
347
+ (css) => {
348
+ const parsed = parseColor(css);
349
+ if (parsed) updateColor(parsed);
350
+ },
351
+ [updateColor]
352
+ );
353
+ const onInteractionEnd = React.useCallback(() => {
354
+ const formatted = formatColor(color, outputFormat);
355
+ onValueCommit?.(formatted);
356
+ }, [color, outputFormat, onValueCommit]);
357
+ const ctx = React.useMemo(
358
+ () => ({
359
+ color,
360
+ setChannel,
361
+ setColor,
362
+ setColorFromString,
363
+ cssValue,
364
+ outputFormat,
365
+ disabled,
366
+ enableAlpha,
367
+ isDragging,
368
+ setIsDragging,
369
+ onInteractionEnd
370
+ }),
371
+ [
372
+ color,
373
+ setChannel,
374
+ setColor,
375
+ setColorFromString,
376
+ cssValue,
377
+ outputFormat,
378
+ disabled,
379
+ enableAlpha,
380
+ isDragging,
381
+ setIsDragging,
382
+ onInteractionEnd
383
+ ]
384
+ );
385
+ return /* @__PURE__ */ jsx(ColorPickerCtx, { value: ctx, children: /* @__PURE__ */ jsx(PopoverPrimitive.Root, { open, onOpenChange, children: /* @__PURE__ */ jsxs("div", { "data-slot": "color-picker", className: cn("inline-flex", className), children: [
386
+ children,
387
+ name && /* @__PURE__ */ jsx("input", { type: "hidden", name, value: cssValue })
388
+ ] }) }) });
389
+ }
390
+ function ColorPickerTrigger({
391
+ className,
392
+ children,
393
+ ...props
394
+ }) {
395
+ const { cssValue, disabled } = useColorPicker();
396
+ return /* @__PURE__ */ jsxs(
397
+ PopoverPrimitive.Trigger,
398
+ {
399
+ "data-slot": "color-picker-trigger",
400
+ disabled,
401
+ className: cn(
402
+ "inline-flex items-center gap-2 rounded-md border border-border bg-surface px-3 py-2 text-sm",
403
+ "focus-visible:focus-ring",
404
+ "disabled:status-disabled",
405
+ "transition-colors duration-150 motion-reduce:transition-none",
406
+ className
407
+ ),
408
+ ...props,
409
+ children: [
410
+ /* @__PURE__ */ jsx(
411
+ "span",
412
+ {
413
+ className: "size-5 shrink-0 rounded-sm border border-border/50 shadow-sm",
414
+ style: { backgroundColor: cssValue }
415
+ }
416
+ ),
417
+ children ?? /* @__PURE__ */ jsx("span", { className: "font-mono text-xs uppercase", children: cssValue })
418
+ ]
419
+ }
420
+ );
421
+ }
422
+ function ColorPickerContent({
423
+ className,
424
+ sideOffset = 8,
425
+ align = "start",
426
+ ...props
427
+ }) {
428
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
429
+ PopoverPrimitive.Positioner,
430
+ {
431
+ sideOffset,
432
+ align,
433
+ className: "isolate z-50",
434
+ children: /* @__PURE__ */ jsx(
435
+ PopoverPrimitive.Popup,
436
+ {
437
+ "data-slot": "color-picker-content",
438
+ className: cn(
439
+ "flex w-64 flex-col gap-3 rounded-lg bg-overlay p-3 shadow-overlay outline-none",
440
+ "origin-(--transform-origin)",
441
+ "data-open:animate-in data-open:duration-150 data-open:[animation-timing-function:var(--ease-out-fluid)]",
442
+ "data-closed:animate-out data-closed:duration-100 data-closed:[animation-timing-function:var(--ease-in-quart)]",
443
+ "data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95",
444
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
445
+ "data-entering:will-change-[opacity,transform] data-exiting:will-change-[opacity,transform]",
446
+ "motion-reduce:animate-none motion-reduce:transition-none",
447
+ className
448
+ ),
449
+ ...props
450
+ }
451
+ )
452
+ }
453
+ ) });
454
+ }
455
+ function ColorPickerArea({
456
+ className,
457
+ children,
458
+ ...props
459
+ }) {
460
+ const { color, setColor, disabled, setIsDragging, onInteractionEnd } = useColorPicker();
461
+ const canvasRef = React.useRef(null);
462
+ const containerRef = React.useRef(null);
463
+ const prevHue = React.useRef(color.h);
464
+ React.useEffect(() => {
465
+ const canvas = canvasRef.current;
466
+ if (!canvas) return;
467
+ const ctx = canvas.getContext("2d", { willReadFrequently: true });
468
+ if (!ctx) return;
469
+ const w = 128;
470
+ const h = 128;
471
+ canvas.width = w;
472
+ canvas.height = h;
473
+ const imageData = renderAreaGradient(w, h, color.h);
474
+ ctx.putImageData(imageData, 0, 0);
475
+ prevHue.current = color.h;
476
+ }, [color.h]);
477
+ const computeFromPointer = React.useCallback(
478
+ (clientX, clientY) => {
479
+ const el = containerRef.current;
480
+ if (!el) return;
481
+ const rect = el.getBoundingClientRect();
482
+ const x = clamp((clientX - rect.left) / rect.width, 0, 1);
483
+ const y = clamp((clientY - rect.top) / rect.height, 0, 1);
484
+ const c = x * 0.4;
485
+ const l = 1 - y;
486
+ const clamped = gamutMapChroma(l, c, color.h);
487
+ setColor({ ...color, l, c: Math.min(c, clamped) });
488
+ },
489
+ [color, setColor]
490
+ );
491
+ const handlePointerDown = React.useCallback(
492
+ (e) => {
493
+ if (disabled) return;
494
+ e.preventDefault();
495
+ e.currentTarget.setPointerCapture(e.pointerId);
496
+ setIsDragging(true);
497
+ computeFromPointer(e.clientX, e.clientY);
498
+ },
499
+ [disabled, setIsDragging, computeFromPointer]
500
+ );
501
+ const handlePointerMove = React.useCallback(
502
+ (e) => {
503
+ if (!e.currentTarget.hasPointerCapture(e.pointerId))
504
+ return;
505
+ computeFromPointer(e.clientX, e.clientY);
506
+ },
507
+ [computeFromPointer]
508
+ );
509
+ const handlePointerUp = React.useCallback(() => {
510
+ setIsDragging(false);
511
+ onInteractionEnd();
512
+ }, [setIsDragging, onInteractionEnd]);
513
+ const handleKeyDown = React.useCallback(
514
+ (e) => {
515
+ if (disabled) return;
516
+ const step = e.shiftKey ? 5e-3 : 0.02;
517
+ let { l, c } = color;
518
+ let handled = true;
519
+ switch (e.key) {
520
+ case "ArrowRight":
521
+ c = Math.min(c + step, 0.4);
522
+ break;
523
+ case "ArrowLeft":
524
+ c = Math.max(c - step, 0);
525
+ break;
526
+ case "ArrowUp":
527
+ l = Math.min(l + step, 1);
528
+ break;
529
+ case "ArrowDown":
530
+ l = Math.max(l - step, 0);
531
+ break;
532
+ case "Home":
533
+ c = 0;
534
+ break;
535
+ case "End":
536
+ c = 0.4;
537
+ break;
538
+ case "PageUp":
539
+ l = 1;
540
+ break;
541
+ case "PageDown":
542
+ l = 0;
543
+ break;
544
+ default:
545
+ handled = false;
546
+ }
547
+ if (handled) {
548
+ e.preventDefault();
549
+ const clamped = gamutMapChroma(l, c, color.h);
550
+ setColor({ ...color, l, c: Math.min(c, clamped) });
551
+ onInteractionEnd();
552
+ }
553
+ },
554
+ [color, setColor, disabled, onInteractionEnd]
555
+ );
556
+ const thumbX = clamp(color.c / 0.4, 0, 1) * 100;
557
+ const thumbY = (1 - color.l) * 100;
558
+ return /* @__PURE__ */ jsxs(
559
+ "div",
560
+ {
561
+ ref: containerRef,
562
+ "data-slot": "color-picker-area",
563
+ role: "slider",
564
+ "aria-label": "Color area",
565
+ "aria-valuetext": `Lightness ${Math.round(color.l * 100)}%, Chroma ${Math.round(color.c / 0.4 * 100)}%`,
566
+ tabIndex: disabled ? -1 : 0,
567
+ className: cn(
568
+ "relative aspect-square w-full cursor-crosshair overflow-hidden rounded-md touch-none select-none",
569
+ "focus-visible:focus-ring",
570
+ disabled && "pointer-events-none opacity-50",
571
+ className
572
+ ),
573
+ onPointerDown: handlePointerDown,
574
+ onPointerMove: handlePointerMove,
575
+ onPointerUp: handlePointerUp,
576
+ onKeyDown: handleKeyDown,
577
+ ...props,
578
+ children: [
579
+ /* @__PURE__ */ jsx(
580
+ "canvas",
581
+ {
582
+ ref: canvasRef,
583
+ className: "pointer-events-none absolute inset-0 size-full",
584
+ style: { imageRendering: "auto" }
585
+ }
586
+ ),
587
+ children ?? /* @__PURE__ */ jsx(
588
+ ColorPickerAreaThumb,
589
+ {
590
+ style: { left: `${thumbX}%`, top: `${thumbY}%` }
591
+ }
592
+ )
593
+ ]
594
+ }
595
+ );
596
+ }
597
+ function ColorPickerAreaThumb({
598
+ className,
599
+ style,
600
+ ...props
601
+ }) {
602
+ const { color, isDragging } = useColorPicker();
603
+ const [r, g, b] = oklchToRgb(color.l, color.c, color.h);
604
+ return /* @__PURE__ */ jsx(
605
+ "div",
606
+ {
607
+ "data-slot": "color-picker-area-thumb",
608
+ className: cn(
609
+ "pointer-events-none absolute size-4 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white shadow-md",
610
+ "transition-transform duration-150 ease-smooth motion-reduce:transition-none",
611
+ isDragging && "scale-110 shadow-lg",
612
+ className
613
+ ),
614
+ style: {
615
+ backgroundColor: `rgb(${r}, ${g}, ${b})`,
616
+ ...style
617
+ },
618
+ ...props
619
+ }
620
+ );
621
+ }
622
+ function ColorPickerSlider({
623
+ channel,
624
+ className,
625
+ children,
626
+ ...props
627
+ }) {
628
+ const {
629
+ color,
630
+ setChannel,
631
+ disabled,
632
+ setIsDragging,
633
+ onInteractionEnd,
634
+ enableAlpha
635
+ } = useColorPicker();
636
+ const trackRef = React.useRef(null);
637
+ if (channel === "alpha" && !enableAlpha) return null;
638
+ const isHue = channel === "hue";
639
+ const value = isHue ? color.h : color.a;
640
+ const min = 0;
641
+ const max = isHue ? 360 : 1;
642
+ const pct = (value - min) / (max - min) * 100;
643
+ const computeValue = React.useCallback(
644
+ (clientX) => {
645
+ const el = trackRef.current;
646
+ if (!el) return value;
647
+ const rect = el.getBoundingClientRect();
648
+ const ratio = clamp((clientX - rect.left) / rect.width, 0, 1);
649
+ return min + ratio * (max - min);
650
+ },
651
+ [min, max, value]
652
+ );
653
+ const handlePointerDown = React.useCallback(
654
+ (e) => {
655
+ if (disabled) return;
656
+ e.preventDefault();
657
+ e.currentTarget.setPointerCapture(e.pointerId);
658
+ setIsDragging(true);
659
+ const v = computeValue(e.clientX);
660
+ setChannel(isHue ? "h" : "a", v);
661
+ },
662
+ [disabled, setIsDragging, computeValue, setChannel, isHue]
663
+ );
664
+ const handlePointerMove = React.useCallback(
665
+ (e) => {
666
+ if (!e.currentTarget.hasPointerCapture(e.pointerId))
667
+ return;
668
+ const v = computeValue(e.clientX);
669
+ setChannel(isHue ? "h" : "a", v);
670
+ },
671
+ [computeValue, setChannel, isHue]
672
+ );
673
+ const handlePointerUp = React.useCallback(() => {
674
+ setIsDragging(false);
675
+ onInteractionEnd();
676
+ }, [setIsDragging, onInteractionEnd]);
677
+ const handleKeyDown = React.useCallback(
678
+ (e) => {
679
+ if (disabled) return;
680
+ const coarseStep = isHue ? 10 : 0.05;
681
+ const fineStep = isHue ? 1 : 0.01;
682
+ const step = e.shiftKey ? fineStep : coarseStep;
683
+ let v = value;
684
+ let handled = true;
685
+ switch (e.key) {
686
+ case "ArrowRight":
687
+ case "ArrowUp":
688
+ v = Math.min(v + step, max);
689
+ break;
690
+ case "ArrowLeft":
691
+ case "ArrowDown":
692
+ v = Math.max(v - step, min);
693
+ break;
694
+ case "Home":
695
+ v = min;
696
+ break;
697
+ case "End":
698
+ v = max;
699
+ break;
700
+ default:
701
+ handled = false;
702
+ }
703
+ if (handled) {
704
+ e.preventDefault();
705
+ setChannel(isHue ? "h" : "a", v);
706
+ onInteractionEnd();
707
+ }
708
+ },
709
+ [disabled, isHue, value, min, max, setChannel, onInteractionEnd]
710
+ );
711
+ const gradient = isHue ? `linear-gradient(to right, ${Array.from({ length: 13 }, (_, i) => {
712
+ const h = i / 12 * 360;
713
+ const [r, g, b] = oklchToRgb(0.7, 0.15, h);
714
+ return `rgb(${r},${g},${b})`;
715
+ }).join(",")})` : (() => {
716
+ const [r, g, b] = oklchToRgb(color.l, color.c, color.h);
717
+ return `linear-gradient(to right, transparent, rgb(${r},${g},${b}))`;
718
+ })();
719
+ return /* @__PURE__ */ jsxs(
720
+ "div",
721
+ {
722
+ ref: trackRef,
723
+ "data-slot": "color-picker-slider",
724
+ "data-channel": channel,
725
+ role: "slider",
726
+ tabIndex: disabled ? -1 : 0,
727
+ "aria-label": isHue ? "Hue" : "Alpha",
728
+ "aria-valuemin": min,
729
+ "aria-valuemax": max,
730
+ "aria-valuenow": Math.round(isHue ? value : value * 100),
731
+ className: cn(
732
+ "group relative h-3 w-full cursor-pointer rounded-full touch-none select-none",
733
+ "focus-visible:focus-ring",
734
+ disabled && "pointer-events-none opacity-50",
735
+ !isHue && "checkerboard",
736
+ className
737
+ ),
738
+ style: isHue ? { background: gradient } : void 0,
739
+ onPointerDown: handlePointerDown,
740
+ onPointerMove: handlePointerMove,
741
+ onPointerUp: handlePointerUp,
742
+ onKeyDown: handleKeyDown,
743
+ ...props,
744
+ children: [
745
+ !isHue && /* @__PURE__ */ jsx(
746
+ "div",
747
+ {
748
+ className: "absolute inset-0 rounded-full",
749
+ style: { background: gradient }
750
+ }
751
+ ),
752
+ children ?? /* @__PURE__ */ jsx(ColorPickerSliderThumb, { style: { left: `${pct}%` } })
753
+ ]
754
+ }
755
+ );
756
+ }
757
+ function ColorPickerSliderThumb({
758
+ className,
759
+ style,
760
+ ...props
761
+ }) {
762
+ const { isDragging } = useColorPicker();
763
+ return /* @__PURE__ */ jsx(
764
+ "div",
765
+ {
766
+ "data-slot": "color-picker-slider-thumb",
767
+ className: cn(
768
+ "pointer-events-none absolute top-1/2 size-4 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white bg-white shadow-md",
769
+ "transition-transform duration-150 ease-smooth motion-reduce:transition-none",
770
+ isDragging && "scale-110 shadow-lg",
771
+ className
772
+ ),
773
+ style,
774
+ ...props
775
+ }
776
+ );
777
+ }
778
+ function ColorPickerInput({
779
+ className,
780
+ ...props
781
+ }) {
782
+ const { cssValue, setColorFromString, disabled, onInteractionEnd } = useColorPicker();
783
+ const [local, setLocal] = React.useState(cssValue);
784
+ const [focused, setFocused] = React.useState(false);
785
+ React.useEffect(() => {
786
+ if (!focused) setLocal(cssValue);
787
+ }, [cssValue, focused]);
788
+ const handleChange = React.useCallback(
789
+ (e) => {
790
+ const v = e.target.value;
791
+ setLocal(v);
792
+ setColorFromString(v);
793
+ },
794
+ [setColorFromString]
795
+ );
796
+ const handleBlur = React.useCallback(() => {
797
+ setFocused(false);
798
+ setLocal(cssValue);
799
+ onInteractionEnd();
800
+ }, [cssValue, onInteractionEnd]);
801
+ const handleKeyDown = React.useCallback(
802
+ (e) => {
803
+ if (e.key === "Enter") {
804
+ setColorFromString(local);
805
+ onInteractionEnd();
806
+ e.target.blur();
807
+ }
808
+ },
809
+ [local, setColorFromString, onInteractionEnd]
810
+ );
811
+ return /* @__PURE__ */ jsx(
812
+ "input",
813
+ {
814
+ "data-slot": "color-picker-input",
815
+ type: "text",
816
+ value: local,
817
+ disabled,
818
+ className: cn(
819
+ "h-8 w-full min-w-0 flex-1 rounded-md border border-field-border bg-field-background shadow-field px-2 font-mono text-xs",
820
+ "hover-only:hover:border-field-border-hover",
821
+ "focus-visible:focus-field-ring",
822
+ "disabled:status-disabled",
823
+ className
824
+ ),
825
+ onChange: handleChange,
826
+ onFocus: () => setFocused(true),
827
+ onBlur: handleBlur,
828
+ onKeyDown: handleKeyDown,
829
+ ...props
830
+ }
831
+ );
832
+ }
833
+ function ColorPickerEyeDropper({
834
+ className,
835
+ ...props
836
+ }) {
837
+ const { setColorFromString, disabled, onInteractionEnd } = useColorPicker();
838
+ const [supported, setSupported] = React.useState(false);
839
+ React.useEffect(() => {
840
+ setSupported("EyeDropper" in window);
841
+ }, []);
842
+ const handleClick = React.useCallback(async () => {
843
+ try {
844
+ const dropper = new window.EyeDropper();
845
+ const result = await dropper.open();
846
+ if (result?.sRGBHex) {
847
+ setColorFromString(result.sRGBHex);
848
+ onInteractionEnd();
849
+ }
850
+ } catch {
851
+ }
852
+ }, [setColorFromString, onInteractionEnd]);
853
+ if (!supported) return null;
854
+ return /* @__PURE__ */ jsx(
855
+ "button",
856
+ {
857
+ type: "button",
858
+ "data-slot": "color-picker-eye-dropper",
859
+ "aria-label": "Pick color from screen",
860
+ disabled,
861
+ className: cn(
862
+ "inline-flex size-8 shrink-0 items-center justify-center rounded-md border border-border bg-surface text-muted-foreground",
863
+ "hover-only:hover:bg-surface-secondary hover-only:hover:text-foreground",
864
+ "focus-visible:focus-ring",
865
+ "disabled:status-disabled",
866
+ "transition-colors duration-150 motion-reduce:transition-none",
867
+ className
868
+ ),
869
+ onClick: handleClick,
870
+ ...props,
871
+ children: /* @__PURE__ */ jsx(Pipette, { className: "size-3.5" })
872
+ }
873
+ );
874
+ }
875
+ function ColorPickerSwatches({
876
+ className,
877
+ ...props
878
+ }) {
879
+ return /* @__PURE__ */ jsx(
880
+ "div",
881
+ {
882
+ "data-slot": "color-picker-swatches",
883
+ className: cn("flex flex-wrap gap-1", className),
884
+ ...props
885
+ }
886
+ );
887
+ }
888
+ function ColorPickerSwatch({
889
+ value,
890
+ className,
891
+ ...props
892
+ }) {
893
+ const { setColorFromString, disabled, onInteractionEnd, cssValue } = useColorPicker();
894
+ const parsed = React.useMemo(() => parseColor(value), [value]);
895
+ const swatchCss = React.useMemo(
896
+ () => parsed ? formatColor(parsed, "hex") : value,
897
+ [parsed, value]
898
+ );
899
+ const handleClick = React.useCallback(() => {
900
+ setColorFromString(value);
901
+ onInteractionEnd();
902
+ }, [value, setColorFromString, onInteractionEnd]);
903
+ const isActive = cssValue.toLowerCase() === swatchCss.toLowerCase();
904
+ return /* @__PURE__ */ jsx(
905
+ "button",
906
+ {
907
+ type: "button",
908
+ "data-slot": "color-picker-swatch",
909
+ "data-active": isActive || void 0,
910
+ disabled,
911
+ className: cn(
912
+ "size-6 rounded-sm border border-border/50 shadow-sm",
913
+ "motion-safe:hover-only:hover:scale-110 focus-visible:focus-ring",
914
+ "disabled:status-disabled",
915
+ "transition-transform duration-150 ease-smooth motion-reduce:transition-none",
916
+ "data-active:ring-2 data-active:ring-ring data-active:ring-offset-1 data-active:ring-offset-overlay",
917
+ className
918
+ ),
919
+ style: { backgroundColor: value },
920
+ onClick: handleClick,
921
+ title: value,
922
+ ...props
923
+ }
924
+ );
925
+ }
926
+ export {
927
+ ColorPicker,
928
+ ColorPickerArea,
929
+ ColorPickerAreaThumb,
930
+ ColorPickerContent,
931
+ ColorPickerEyeDropper,
932
+ ColorPickerInput,
933
+ ColorPickerSlider,
934
+ ColorPickerSliderThumb,
935
+ ColorPickerSwatch,
936
+ ColorPickerSwatches,
937
+ ColorPickerTrigger
938
+ };
939
+ //# sourceMappingURL=color-picker.js.map