@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,315 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/lib/color-utils.ts
21
+ var color_utils_exports = {};
22
+ __export(color_utils_exports, {
23
+ clamp: () => clamp,
24
+ formatColor: () => formatColor,
25
+ gamutMapChroma: () => gamutMapChroma,
26
+ hexToRgb: () => hexToRgb,
27
+ isInGamut: () => isInGamut,
28
+ maxChromaForLH: () => maxChromaForLH,
29
+ oklchToRgb: () => oklchToRgb,
30
+ parseColor: () => parseColor,
31
+ renderAreaGradient: () => renderAreaGradient,
32
+ rgbToHex: () => rgbToHex,
33
+ rgbToOklch: () => rgbToOklch
34
+ });
35
+ module.exports = __toCommonJS(color_utils_exports);
36
+ var DEG = Math.PI / 180;
37
+ var MAX_CHROMA = 0.4;
38
+ function clamp(v, min, max) {
39
+ return Math.min(max, Math.max(min, v));
40
+ }
41
+ function round(v, d) {
42
+ const f = 10 ** d;
43
+ return Math.round(v * f) / f;
44
+ }
45
+ function oklchToOklab(l, c, h) {
46
+ const hRad = h * DEG;
47
+ return { L: l, a: c * Math.cos(hRad), b: c * Math.sin(hRad) };
48
+ }
49
+ function oklabToOklch(L, a, b) {
50
+ const c = Math.sqrt(a * a + b * b);
51
+ let h = Math.atan2(b, a) / DEG;
52
+ if (h < 0) h += 360;
53
+ return { l: L, c, h };
54
+ }
55
+ function oklabToLinearRgb(L, a, b) {
56
+ const l_ = L + 0.3963377774 * a + 0.2158037573 * b;
57
+ const m_ = L - 0.1055613458 * a - 0.0638541728 * b;
58
+ const s_ = L - 0.0894841775 * a - 1.291485548 * b;
59
+ const l = l_ * l_ * l_;
60
+ const m = m_ * m_ * m_;
61
+ const s = s_ * s_ * s_;
62
+ return {
63
+ r: 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
64
+ g: -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
65
+ b: -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s
66
+ };
67
+ }
68
+ function linearRgbToOklab(r, g, b) {
69
+ const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
70
+ const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
71
+ const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
72
+ return {
73
+ L: 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,
74
+ a: 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,
75
+ b: 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s
76
+ };
77
+ }
78
+ function linearToSrgb(c) {
79
+ return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
80
+ }
81
+ function srgbToLinear(c) {
82
+ return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
83
+ }
84
+ function oklchToRgb(l, c, h) {
85
+ const lab = oklchToOklab(l, c, h);
86
+ const lin = oklabToLinearRgb(lab.L, lab.a, lab.b);
87
+ return [
88
+ clamp(Math.round(linearToSrgb(lin.r) * 255), 0, 255),
89
+ clamp(Math.round(linearToSrgb(lin.g) * 255), 0, 255),
90
+ clamp(Math.round(linearToSrgb(lin.b) * 255), 0, 255)
91
+ ];
92
+ }
93
+ function rgbToOklch(r, g, b) {
94
+ const lr = srgbToLinear(r / 255);
95
+ const lg = srgbToLinear(g / 255);
96
+ const lb = srgbToLinear(b / 255);
97
+ const lab = linearRgbToOklab(lr, lg, lb);
98
+ return oklabToOklch(lab.L, lab.a, lab.b);
99
+ }
100
+ function isInGamut(l, c, h) {
101
+ const lab = oklchToOklab(l, c, h);
102
+ const lin = oklabToLinearRgb(lab.L, lab.a, lab.b);
103
+ const eps = 1e-3;
104
+ return lin.r >= -eps && lin.r <= 1 + eps && lin.g >= -eps && lin.g <= 1 + eps && lin.b >= -eps && lin.b <= 1 + eps;
105
+ }
106
+ function gamutMapChroma(l, c, h) {
107
+ if (isInGamut(l, c, h)) return c;
108
+ let lo = 0;
109
+ let hi = c;
110
+ while (hi - lo > 1e-3) {
111
+ const mid = (lo + hi) / 2;
112
+ if (isInGamut(l, mid, h)) lo = mid;
113
+ else hi = mid;
114
+ }
115
+ return lo;
116
+ }
117
+ function maxChromaForLH(l, h) {
118
+ let lo = 0;
119
+ let hi = MAX_CHROMA;
120
+ while (hi - lo > 1e-3) {
121
+ const mid = (lo + hi) / 2;
122
+ if (isInGamut(l, mid, h)) lo = mid;
123
+ else hi = mid;
124
+ }
125
+ return lo;
126
+ }
127
+ function hexToRgb(hex) {
128
+ hex = hex.replace(/^#/, "");
129
+ if (hex.length === 3 || hex.length === 4) {
130
+ hex = hex.split("").map((c) => c + c).join("");
131
+ }
132
+ const r = parseInt(hex.slice(0, 2), 16);
133
+ const g = parseInt(hex.slice(2, 4), 16);
134
+ const b = parseInt(hex.slice(4, 6), 16);
135
+ const a = hex.length === 8 ? parseInt(hex.slice(6, 8), 16) / 255 : 1;
136
+ return [r, g, b, a];
137
+ }
138
+ function rgbToHex(r, g, b, a) {
139
+ const hex = [r, g, b].map((v) => clamp(Math.round(v), 0, 255).toString(16).padStart(2, "0")).join("");
140
+ if (a !== void 0 && a < 1) {
141
+ return `#${hex}${clamp(Math.round(a * 255), 0, 255).toString(16).padStart(2, "0")}`;
142
+ }
143
+ return `#${hex}`;
144
+ }
145
+ function parseColor(input) {
146
+ const s = input.trim().toLowerCase();
147
+ if (s.startsWith("#")) {
148
+ const [r, g, b, a] = hexToRgb(s);
149
+ if (isNaN(r) || isNaN(g) || isNaN(b)) return null;
150
+ const oklch = rgbToOklch(r, g, b);
151
+ return { l: oklch.l, c: oklch.c, h: oklch.h, a };
152
+ }
153
+ const oklchMatch = s.match(
154
+ /oklch\(\s*([\d.]+)%?\s+([\d.]+)\s+([\d.]+)(?:\s*\/\s*([\d.]+%?))?\s*\)/
155
+ );
156
+ if (oklchMatch) {
157
+ let l = parseFloat(oklchMatch[1]);
158
+ if (l > 1) l /= 100;
159
+ const c = parseFloat(oklchMatch[2]);
160
+ const h = parseFloat(oklchMatch[3]);
161
+ let a = 1;
162
+ if (oklchMatch[4]) {
163
+ a = oklchMatch[4].endsWith("%") ? parseFloat(oklchMatch[4]) / 100 : parseFloat(oklchMatch[4]);
164
+ }
165
+ return { l, c, h, a };
166
+ }
167
+ const rgbMatch = s.match(
168
+ /rgba?\(\s*([\d.]+)[,\s]+([\d.]+)[,\s]+([\d.]+)(?:[,\s/]+([\d.]+%?))?\s*\)/
169
+ );
170
+ if (rgbMatch) {
171
+ const r = parseFloat(rgbMatch[1]);
172
+ const g = parseFloat(rgbMatch[2]);
173
+ const b = parseFloat(rgbMatch[3]);
174
+ let a = 1;
175
+ if (rgbMatch[4]) {
176
+ a = rgbMatch[4].endsWith("%") ? parseFloat(rgbMatch[4]) / 100 : parseFloat(rgbMatch[4]);
177
+ }
178
+ const oklch = rgbToOklch(r, g, b);
179
+ return { l: oklch.l, c: oklch.c, h: oklch.h, a };
180
+ }
181
+ const hslMatch = s.match(
182
+ /hsla?\(\s*([\d.]+)[,\s]+([\d.]+)%[,\s]+([\d.]+)%(?:[,\s/]+([\d.]+%?))?\s*\)/
183
+ );
184
+ if (hslMatch) {
185
+ const [r, g, b] = hslToRgb(
186
+ parseFloat(hslMatch[1]),
187
+ parseFloat(hslMatch[2]),
188
+ parseFloat(hslMatch[3])
189
+ );
190
+ let a = 1;
191
+ if (hslMatch[4]) {
192
+ a = hslMatch[4].endsWith("%") ? parseFloat(hslMatch[4]) / 100 : parseFloat(hslMatch[4]);
193
+ }
194
+ const oklch = rgbToOklch(r, g, b);
195
+ return { l: oklch.l, c: oklch.c, h: oklch.h, a };
196
+ }
197
+ const named = {
198
+ white: "#ffffff",
199
+ black: "#000000",
200
+ red: "#ff0000",
201
+ green: "#008000",
202
+ blue: "#0000ff",
203
+ yellow: "#ffff00",
204
+ cyan: "#00ffff",
205
+ magenta: "#ff00ff",
206
+ orange: "#ffa500",
207
+ transparent: "#00000000"
208
+ };
209
+ if (named[s]) return parseColor(named[s]);
210
+ return null;
211
+ }
212
+ function hslToRgb(h, s, l) {
213
+ s /= 100;
214
+ l /= 100;
215
+ const c = (1 - Math.abs(2 * l - 1)) * s;
216
+ const x = c * (1 - Math.abs(h / 60 % 2 - 1));
217
+ const m = l - c / 2;
218
+ let r = 0, g = 0, b = 0;
219
+ if (h < 60) {
220
+ r = c;
221
+ g = x;
222
+ } else if (h < 120) {
223
+ r = x;
224
+ g = c;
225
+ } else if (h < 180) {
226
+ g = c;
227
+ b = x;
228
+ } else if (h < 240) {
229
+ g = x;
230
+ b = c;
231
+ } else if (h < 300) {
232
+ r = x;
233
+ b = c;
234
+ } else {
235
+ r = c;
236
+ b = x;
237
+ }
238
+ return [
239
+ Math.round((r + m) * 255),
240
+ Math.round((g + m) * 255),
241
+ Math.round((b + m) * 255)
242
+ ];
243
+ }
244
+ function rgbToHsl(r, g, b) {
245
+ r /= 255;
246
+ g /= 255;
247
+ b /= 255;
248
+ const max = Math.max(r, g, b);
249
+ const min = Math.min(r, g, b);
250
+ const l = (max + min) / 2;
251
+ if (max === min) return [0, 0, l * 100];
252
+ const d = max - min;
253
+ const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
254
+ let h = 0;
255
+ if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
256
+ else if (max === g) h = ((b - r) / d + 2) / 6;
257
+ else h = ((r - g) / d + 4) / 6;
258
+ return [h * 360, s * 100, l * 100];
259
+ }
260
+ function formatColor(color, format) {
261
+ const hasAlpha = color.a < 1;
262
+ switch (format) {
263
+ case "hex": {
264
+ const [r, g, b] = oklchToRgb(color.l, color.c, color.h);
265
+ return rgbToHex(r, g, b, hasAlpha ? color.a : void 0);
266
+ }
267
+ case "oklch": {
268
+ const l = round(color.l * 100, 1);
269
+ const c = round(color.c, 3);
270
+ const h = round(color.h, 1);
271
+ return hasAlpha ? `oklch(${l}% ${c} ${h} / ${round(color.a, 2)})` : `oklch(${l}% ${c} ${h})`;
272
+ }
273
+ case "rgb": {
274
+ const [r, g, b] = oklchToRgb(color.l, color.c, color.h);
275
+ return hasAlpha ? `rgba(${r}, ${g}, ${b}, ${round(color.a, 2)})` : `rgb(${r}, ${g}, ${b})`;
276
+ }
277
+ case "hsl": {
278
+ const [r, g, b] = oklchToRgb(color.l, color.c, color.h);
279
+ const [h, s, l] = rgbToHsl(r, g, b);
280
+ 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)}%)`;
281
+ }
282
+ }
283
+ }
284
+ function renderAreaGradient(width, height, hue) {
285
+ const data = new ImageData(width, height);
286
+ const buf = data.data;
287
+ for (let y = 0; y < height; y++) {
288
+ const l = 1 - y / (height - 1);
289
+ for (let x = 0; x < width; x++) {
290
+ const c = x / (width - 1) * MAX_CHROMA;
291
+ const [r, g, b] = oklchToRgb(l, c, hue);
292
+ const idx = (y * width + x) * 4;
293
+ buf[idx] = r;
294
+ buf[idx + 1] = g;
295
+ buf[idx + 2] = b;
296
+ buf[idx + 3] = 255;
297
+ }
298
+ }
299
+ return data;
300
+ }
301
+ // Annotate the CommonJS export names for ESM import in node:
302
+ 0 && (module.exports = {
303
+ clamp,
304
+ formatColor,
305
+ gamutMapChroma,
306
+ hexToRgb,
307
+ isInGamut,
308
+ maxChromaForLH,
309
+ oklchToRgb,
310
+ parseColor,
311
+ renderAreaGradient,
312
+ rgbToHex,
313
+ rgbToOklch
314
+ });
315
+ //# sourceMappingURL=color-utils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/color-utils.ts"],"sourcesContent":["/* ============================================================\n * color-utils — OKLCH-native color conversion & gamut mapping\n * ============================================================\n * Pure math, no React.\n * All internal state uses OKLCH { l, c, h, a }.\n * Provides parsing from CSS strings and formatting to hex/oklch/rgb/hsl.\n * ============================================================ */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface OklchColor {\n l: number; // 0 – 1 (lightness)\n c: number; // 0 – 0.4 (chroma)\n h: number; // 0 – 360 (hue, degrees)\n a: number; // 0 – 1 (alpha)\n}\n\nexport type ColorFormat = \"hex\" | \"oklch\" | \"rgb\" | \"hsl\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEG = Math.PI / 180;\nconst MAX_CHROMA = 0.4;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nexport function clamp(v: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, v));\n}\n\nfunction round(v: number, d: number): number {\n const f = 10 ** d;\n return Math.round(v * f) / f;\n}\n\n// ---------------------------------------------------------------------------\n// OKLCH ↔ OKLab\n// ---------------------------------------------------------------------------\n\nfunction oklchToOklab(l: number, c: number, h: number) {\n const hRad = h * DEG;\n return { L: l, a: c * Math.cos(hRad), b: c * Math.sin(hRad) };\n}\n\nfunction oklabToOklch(L: number, a: number, b: number) {\n const c = Math.sqrt(a * a + b * b);\n let h = Math.atan2(b, a) / DEG;\n if (h < 0) h += 360;\n return { l: L, c, h };\n}\n\n// ---------------------------------------------------------------------------\n// OKLab ↔ Linear sRGB\n// ---------------------------------------------------------------------------\n\nfunction oklabToLinearRgb(L: number, a: number, b: number) {\n const l_ = L + 0.3963377774 * a + 0.2158037573 * b;\n const m_ = L - 0.1055613458 * a - 0.0638541728 * b;\n const s_ = L - 0.0894841775 * a - 1.291485548 * b;\n\n const l = l_ * l_ * l_;\n const m = m_ * m_ * m_;\n const s = s_ * s_ * s_;\n\n return {\n r: +4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,\n g: -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,\n b: -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s,\n };\n}\n\nfunction linearRgbToOklab(r: number, g: number, b: number) {\n const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);\n const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);\n const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);\n\n return {\n L: 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n a: 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,\n b: 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Linear sRGB ↔ sRGB (gamma)\n// ---------------------------------------------------------------------------\n\nfunction linearToSrgb(c: number): number {\n return c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;\n}\n\nfunction srgbToLinear(c: number): number {\n return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n}\n\n// ---------------------------------------------------------------------------\n// OKLCH → sRGB (clamped 0-255)\n// ---------------------------------------------------------------------------\n\nexport function oklchToRgb(\n l: number,\n c: number,\n h: number,\n): [number, number, number] {\n const lab = oklchToOklab(l, c, h);\n const lin = oklabToLinearRgb(lab.L, lab.a, lab.b);\n return [\n clamp(Math.round(linearToSrgb(lin.r) * 255), 0, 255),\n clamp(Math.round(linearToSrgb(lin.g) * 255), 0, 255),\n clamp(Math.round(linearToSrgb(lin.b) * 255), 0, 255),\n ];\n}\n\n// ---------------------------------------------------------------------------\n// sRGB → OKLCH\n// ---------------------------------------------------------------------------\n\nexport function rgbToOklch(\n r: number,\n g: number,\n b: number,\n): { l: number; c: number; h: number } {\n const lr = srgbToLinear(r / 255);\n const lg = srgbToLinear(g / 255);\n const lb = srgbToLinear(b / 255);\n const lab = linearRgbToOklab(lr, lg, lb);\n return oklabToOklch(lab.L, lab.a, lab.b);\n}\n\n// ---------------------------------------------------------------------------\n// Gamut check — is (l, c, h) within sRGB?\n// ---------------------------------------------------------------------------\n\nexport function isInGamut(l: number, c: number, h: number): boolean {\n const lab = oklchToOklab(l, c, h);\n const lin = oklabToLinearRgb(lab.L, lab.a, lab.b);\n const eps = 0.001;\n return (\n lin.r >= -eps &&\n lin.r <= 1 + eps &&\n lin.g >= -eps &&\n lin.g <= 1 + eps &&\n lin.b >= -eps &&\n lin.b <= 1 + eps\n );\n}\n\n// ---------------------------------------------------------------------------\n// Gamut mapping — reduce chroma until in gamut (binary search)\n// ---------------------------------------------------------------------------\n\nexport function gamutMapChroma(l: number, c: number, h: number): number {\n if (isInGamut(l, c, h)) return c;\n let lo = 0;\n let hi = c;\n while (hi - lo > 0.001) {\n const mid = (lo + hi) / 2;\n if (isInGamut(l, mid, h)) lo = mid;\n else hi = mid;\n }\n return lo;\n}\n\n// ---------------------------------------------------------------------------\n// Max chroma for a given (l, h) — for area rendering\n// ---------------------------------------------------------------------------\n\nexport function maxChromaForLH(l: number, h: number): number {\n let lo = 0;\n let hi = MAX_CHROMA;\n while (hi - lo > 0.001) {\n const mid = (lo + hi) / 2;\n if (isInGamut(l, mid, h)) lo = mid;\n else hi = mid;\n }\n return lo;\n}\n\n// ---------------------------------------------------------------------------\n// Hex parsing & formatting\n// ---------------------------------------------------------------------------\n\nexport function hexToRgb(hex: string): [number, number, number, number] {\n hex = hex.replace(/^#/, \"\");\n if (hex.length === 3 || hex.length === 4) {\n hex = hex\n .split(\"\")\n .map((c) => c + c)\n .join(\"\");\n }\n const r = parseInt(hex.slice(0, 2), 16);\n const g = parseInt(hex.slice(2, 4), 16);\n const b = parseInt(hex.slice(4, 6), 16);\n const a = hex.length === 8 ? parseInt(hex.slice(6, 8), 16) / 255 : 1;\n return [r, g, b, a];\n}\n\nexport function rgbToHex(r: number, g: number, b: number, a?: number): string {\n const hex = [r, g, b]\n .map((v) => clamp(Math.round(v), 0, 255).toString(16).padStart(2, \"0\"))\n .join(\"\");\n if (a !== undefined && a < 1) {\n return `#${hex}${clamp(Math.round(a * 255), 0, 255)\n .toString(16)\n .padStart(2, \"0\")}`;\n }\n return `#${hex}`;\n}\n\n// ---------------------------------------------------------------------------\n// Parse any CSS color string → OklchColor\n// ---------------------------------------------------------------------------\n\nexport function parseColor(input: string): OklchColor | null {\n const s = input.trim().toLowerCase();\n\n // hex: #rgb, #rgba, #rrggbb, #rrggbbaa\n if (s.startsWith(\"#\")) {\n const [r, g, b, a] = hexToRgb(s);\n if (isNaN(r) || isNaN(g) || isNaN(b)) return null;\n const oklch = rgbToOklch(r, g, b);\n return { l: oklch.l, c: oklch.c, h: oklch.h, a };\n }\n\n // oklch(l% c h) or oklch(l% c h / a)\n const oklchMatch = s.match(\n /oklch\\(\\s*([\\d.]+)%?\\s+([\\d.]+)\\s+([\\d.]+)(?:\\s*\\/\\s*([\\d.]+%?))?\\s*\\)/,\n );\n if (oklchMatch) {\n let l = parseFloat(oklchMatch[1]);\n if (l > 1) l /= 100; // handle percentage\n const c = parseFloat(oklchMatch[2]);\n const h = parseFloat(oklchMatch[3]);\n let a = 1;\n if (oklchMatch[4]) {\n a = oklchMatch[4].endsWith(\"%\")\n ? parseFloat(oklchMatch[4]) / 100\n : parseFloat(oklchMatch[4]);\n }\n return { l, c, h, a };\n }\n\n // rgb(r, g, b) or rgb(r g b) or rgba(r, g, b, a)\n const rgbMatch = s.match(\n /rgba?\\(\\s*([\\d.]+)[,\\s]+([\\d.]+)[,\\s]+([\\d.]+)(?:[,\\s/]+([\\d.]+%?))?\\s*\\)/,\n );\n if (rgbMatch) {\n const r = parseFloat(rgbMatch[1]);\n const g = parseFloat(rgbMatch[2]);\n const b = parseFloat(rgbMatch[3]);\n let a = 1;\n if (rgbMatch[4]) {\n a = rgbMatch[4].endsWith(\"%\")\n ? parseFloat(rgbMatch[4]) / 100\n : parseFloat(rgbMatch[4]);\n }\n const oklch = rgbToOklch(r, g, b);\n return { l: oklch.l, c: oklch.c, h: oklch.h, a };\n }\n\n // hsl(h, s%, l%) or hsla(h, s%, l%, a)\n const hslMatch = s.match(\n /hsla?\\(\\s*([\\d.]+)[,\\s]+([\\d.]+)%[,\\s]+([\\d.]+)%(?:[,\\s/]+([\\d.]+%?))?\\s*\\)/,\n );\n if (hslMatch) {\n const [r, g, b] = hslToRgb(\n parseFloat(hslMatch[1]),\n parseFloat(hslMatch[2]),\n parseFloat(hslMatch[3]),\n );\n let a = 1;\n if (hslMatch[4]) {\n a = hslMatch[4].endsWith(\"%\")\n ? parseFloat(hslMatch[4]) / 100\n : parseFloat(hslMatch[4]);\n }\n const oklch = rgbToOklch(r, g, b);\n return { l: oklch.l, c: oklch.c, h: oklch.h, a };\n }\n\n // Named colors — small subset for common use\n const named: Record<string, string> = {\n white: \"#ffffff\",\n black: \"#000000\",\n red: \"#ff0000\",\n green: \"#008000\",\n blue: \"#0000ff\",\n yellow: \"#ffff00\",\n cyan: \"#00ffff\",\n magenta: \"#ff00ff\",\n orange: \"#ffa500\",\n transparent: \"#00000000\",\n };\n if (named[s]) return parseColor(named[s]);\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// HSL ↔ RGB helpers\n// ---------------------------------------------------------------------------\n\nfunction hslToRgb(h: number, s: number, l: number): [number, number, number] {\n s /= 100;\n l /= 100;\n const c = (1 - Math.abs(2 * l - 1)) * s;\n const x = c * (1 - Math.abs(((h / 60) % 2) - 1));\n const m = l - c / 2;\n let r = 0,\n g = 0,\n b = 0;\n if (h < 60) {\n r = c;\n g = x;\n } else if (h < 120) {\n r = x;\n g = c;\n } else if (h < 180) {\n g = c;\n b = x;\n } else if (h < 240) {\n g = x;\n b = c;\n } else if (h < 300) {\n r = x;\n b = c;\n } else {\n r = c;\n b = x;\n }\n return [\n Math.round((r + m) * 255),\n Math.round((g + m) * 255),\n Math.round((b + m) * 255),\n ];\n}\n\nfunction rgbToHsl(r: number, g: number, b: number): [number, number, number] {\n r /= 255;\n g /= 255;\n b /= 255;\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const l = (max + min) / 2;\n if (max === min) return [0, 0, l * 100];\n const d = max - min;\n const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n let h = 0;\n if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6;\n else if (max === g) h = ((b - r) / d + 2) / 6;\n else h = ((r - g) / d + 4) / 6;\n return [h * 360, s * 100, l * 100];\n}\n\n// ---------------------------------------------------------------------------\n// Format OklchColor → CSS string\n// ---------------------------------------------------------------------------\n\nexport function formatColor(color: OklchColor, format: ColorFormat): string {\n const hasAlpha = color.a < 1;\n\n switch (format) {\n case \"hex\": {\n const [r, g, b] = oklchToRgb(color.l, color.c, color.h);\n return rgbToHex(r, g, b, hasAlpha ? color.a : undefined);\n }\n case \"oklch\": {\n const l = round(color.l * 100, 1);\n const c = round(color.c, 3);\n const h = round(color.h, 1);\n return hasAlpha\n ? `oklch(${l}% ${c} ${h} / ${round(color.a, 2)})`\n : `oklch(${l}% ${c} ${h})`;\n }\n case \"rgb\": {\n const [r, g, b] = oklchToRgb(color.l, color.c, color.h);\n return hasAlpha\n ? `rgba(${r}, ${g}, ${b}, ${round(color.a, 2)})`\n : `rgb(${r}, ${g}, ${b})`;\n }\n case \"hsl\": {\n const [r, g, b] = oklchToRgb(color.l, color.c, color.h);\n const [h, s, l] = rgbToHsl(r, g, b);\n return hasAlpha\n ? `hsla(${round(h, 0)}, ${round(s, 1)}%, ${round(l, 1)}%, ${round(color.a, 2)})`\n : `hsl(${round(h, 0)}, ${round(s, 1)}%, ${round(l, 1)}%)`;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Render a 2D area gradient (lightness × chroma) for a given hue\n// Returns ImageData to draw onto a canvas\n// ---------------------------------------------------------------------------\n\nexport function renderAreaGradient(\n width: number,\n height: number,\n hue: number,\n): ImageData {\n const data = new ImageData(width, height);\n const buf = data.data;\n\n for (let y = 0; y < height; y++) {\n const l = 1 - y / (height - 1); // top = 1 (light), bottom = 0 (dark)\n for (let x = 0; x < width; x++) {\n const c = (x / (width - 1)) * MAX_CHROMA;\n const [r, g, b] = oklchToRgb(l, c, hue);\n const idx = (y * width + x) * 4;\n buf[idx] = r;\n buf[idx + 1] = g;\n buf[idx + 2] = b;\n buf[idx + 3] = 255;\n }\n }\n\n return data;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,24 @@
1
+ interface OklchColor {
2
+ l: number;
3
+ c: number;
4
+ h: number;
5
+ a: number;
6
+ }
7
+ type ColorFormat = "hex" | "oklch" | "rgb" | "hsl";
8
+ declare function clamp(v: number, min: number, max: number): number;
9
+ declare function oklchToRgb(l: number, c: number, h: number): [number, number, number];
10
+ declare function rgbToOklch(r: number, g: number, b: number): {
11
+ l: number;
12
+ c: number;
13
+ h: number;
14
+ };
15
+ declare function isInGamut(l: number, c: number, h: number): boolean;
16
+ declare function gamutMapChroma(l: number, c: number, h: number): number;
17
+ declare function maxChromaForLH(l: number, h: number): number;
18
+ declare function hexToRgb(hex: string): [number, number, number, number];
19
+ declare function rgbToHex(r: number, g: number, b: number, a?: number): string;
20
+ declare function parseColor(input: string): OklchColor | null;
21
+ declare function formatColor(color: OklchColor, format: ColorFormat): string;
22
+ declare function renderAreaGradient(width: number, height: number, hue: number): ImageData;
23
+
24
+ export { type ColorFormat, type OklchColor, clamp, formatColor, gamutMapChroma, hexToRgb, isInGamut, maxChromaForLH, oklchToRgb, parseColor, renderAreaGradient, rgbToHex, rgbToOklch };
@@ -0,0 +1,24 @@
1
+ interface OklchColor {
2
+ l: number;
3
+ c: number;
4
+ h: number;
5
+ a: number;
6
+ }
7
+ type ColorFormat = "hex" | "oklch" | "rgb" | "hsl";
8
+ declare function clamp(v: number, min: number, max: number): number;
9
+ declare function oklchToRgb(l: number, c: number, h: number): [number, number, number];
10
+ declare function rgbToOklch(r: number, g: number, b: number): {
11
+ l: number;
12
+ c: number;
13
+ h: number;
14
+ };
15
+ declare function isInGamut(l: number, c: number, h: number): boolean;
16
+ declare function gamutMapChroma(l: number, c: number, h: number): number;
17
+ declare function maxChromaForLH(l: number, h: number): number;
18
+ declare function hexToRgb(hex: string): [number, number, number, number];
19
+ declare function rgbToHex(r: number, g: number, b: number, a?: number): string;
20
+ declare function parseColor(input: string): OklchColor | null;
21
+ declare function formatColor(color: OklchColor, format: ColorFormat): string;
22
+ declare function renderAreaGradient(width: number, height: number, hue: number): ImageData;
23
+
24
+ export { type ColorFormat, type OklchColor, clamp, formatColor, gamutMapChroma, hexToRgb, isInGamut, maxChromaForLH, oklchToRgb, parseColor, renderAreaGradient, rgbToHex, rgbToOklch };
@@ -0,0 +1,280 @@
1
+ // src/lib/color-utils.ts
2
+ var DEG = Math.PI / 180;
3
+ var MAX_CHROMA = 0.4;
4
+ function clamp(v, min, max) {
5
+ return Math.min(max, Math.max(min, v));
6
+ }
7
+ function round(v, d) {
8
+ const f = 10 ** d;
9
+ return Math.round(v * f) / f;
10
+ }
11
+ function oklchToOklab(l, c, h) {
12
+ const hRad = h * DEG;
13
+ return { L: l, a: c * Math.cos(hRad), b: c * Math.sin(hRad) };
14
+ }
15
+ function oklabToOklch(L, a, b) {
16
+ const c = Math.sqrt(a * a + b * b);
17
+ let h = Math.atan2(b, a) / DEG;
18
+ if (h < 0) h += 360;
19
+ return { l: L, c, h };
20
+ }
21
+ function oklabToLinearRgb(L, a, b) {
22
+ const l_ = L + 0.3963377774 * a + 0.2158037573 * b;
23
+ const m_ = L - 0.1055613458 * a - 0.0638541728 * b;
24
+ const s_ = L - 0.0894841775 * a - 1.291485548 * b;
25
+ const l = l_ * l_ * l_;
26
+ const m = m_ * m_ * m_;
27
+ const s = s_ * s_ * s_;
28
+ return {
29
+ r: 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
30
+ g: -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
31
+ b: -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s
32
+ };
33
+ }
34
+ function linearRgbToOklab(r, g, b) {
35
+ const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
36
+ const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
37
+ const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
38
+ return {
39
+ L: 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,
40
+ a: 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,
41
+ b: 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s
42
+ };
43
+ }
44
+ function linearToSrgb(c) {
45
+ return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
46
+ }
47
+ function srgbToLinear(c) {
48
+ return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
49
+ }
50
+ function oklchToRgb(l, c, h) {
51
+ const lab = oklchToOklab(l, c, h);
52
+ const lin = oklabToLinearRgb(lab.L, lab.a, lab.b);
53
+ return [
54
+ clamp(Math.round(linearToSrgb(lin.r) * 255), 0, 255),
55
+ clamp(Math.round(linearToSrgb(lin.g) * 255), 0, 255),
56
+ clamp(Math.round(linearToSrgb(lin.b) * 255), 0, 255)
57
+ ];
58
+ }
59
+ function rgbToOklch(r, g, b) {
60
+ const lr = srgbToLinear(r / 255);
61
+ const lg = srgbToLinear(g / 255);
62
+ const lb = srgbToLinear(b / 255);
63
+ const lab = linearRgbToOklab(lr, lg, lb);
64
+ return oklabToOklch(lab.L, lab.a, lab.b);
65
+ }
66
+ function isInGamut(l, c, h) {
67
+ const lab = oklchToOklab(l, c, h);
68
+ const lin = oklabToLinearRgb(lab.L, lab.a, lab.b);
69
+ const eps = 1e-3;
70
+ return lin.r >= -eps && lin.r <= 1 + eps && lin.g >= -eps && lin.g <= 1 + eps && lin.b >= -eps && lin.b <= 1 + eps;
71
+ }
72
+ function gamutMapChroma(l, c, h) {
73
+ if (isInGamut(l, c, h)) return c;
74
+ let lo = 0;
75
+ let hi = c;
76
+ while (hi - lo > 1e-3) {
77
+ const mid = (lo + hi) / 2;
78
+ if (isInGamut(l, mid, h)) lo = mid;
79
+ else hi = mid;
80
+ }
81
+ return lo;
82
+ }
83
+ function maxChromaForLH(l, h) {
84
+ let lo = 0;
85
+ let hi = MAX_CHROMA;
86
+ while (hi - lo > 1e-3) {
87
+ const mid = (lo + hi) / 2;
88
+ if (isInGamut(l, mid, h)) lo = mid;
89
+ else hi = mid;
90
+ }
91
+ return lo;
92
+ }
93
+ function hexToRgb(hex) {
94
+ hex = hex.replace(/^#/, "");
95
+ if (hex.length === 3 || hex.length === 4) {
96
+ hex = hex.split("").map((c) => c + c).join("");
97
+ }
98
+ const r = parseInt(hex.slice(0, 2), 16);
99
+ const g = parseInt(hex.slice(2, 4), 16);
100
+ const b = parseInt(hex.slice(4, 6), 16);
101
+ const a = hex.length === 8 ? parseInt(hex.slice(6, 8), 16) / 255 : 1;
102
+ return [r, g, b, a];
103
+ }
104
+ function rgbToHex(r, g, b, a) {
105
+ const hex = [r, g, b].map((v) => clamp(Math.round(v), 0, 255).toString(16).padStart(2, "0")).join("");
106
+ if (a !== void 0 && a < 1) {
107
+ return `#${hex}${clamp(Math.round(a * 255), 0, 255).toString(16).padStart(2, "0")}`;
108
+ }
109
+ return `#${hex}`;
110
+ }
111
+ function parseColor(input) {
112
+ const s = input.trim().toLowerCase();
113
+ if (s.startsWith("#")) {
114
+ const [r, g, b, a] = hexToRgb(s);
115
+ if (isNaN(r) || isNaN(g) || isNaN(b)) return null;
116
+ const oklch = rgbToOklch(r, g, b);
117
+ return { l: oklch.l, c: oklch.c, h: oklch.h, a };
118
+ }
119
+ const oklchMatch = s.match(
120
+ /oklch\(\s*([\d.]+)%?\s+([\d.]+)\s+([\d.]+)(?:\s*\/\s*([\d.]+%?))?\s*\)/
121
+ );
122
+ if (oklchMatch) {
123
+ let l = parseFloat(oklchMatch[1]);
124
+ if (l > 1) l /= 100;
125
+ const c = parseFloat(oklchMatch[2]);
126
+ const h = parseFloat(oklchMatch[3]);
127
+ let a = 1;
128
+ if (oklchMatch[4]) {
129
+ a = oklchMatch[4].endsWith("%") ? parseFloat(oklchMatch[4]) / 100 : parseFloat(oklchMatch[4]);
130
+ }
131
+ return { l, c, h, a };
132
+ }
133
+ const rgbMatch = s.match(
134
+ /rgba?\(\s*([\d.]+)[,\s]+([\d.]+)[,\s]+([\d.]+)(?:[,\s/]+([\d.]+%?))?\s*\)/
135
+ );
136
+ if (rgbMatch) {
137
+ const r = parseFloat(rgbMatch[1]);
138
+ const g = parseFloat(rgbMatch[2]);
139
+ const b = parseFloat(rgbMatch[3]);
140
+ let a = 1;
141
+ if (rgbMatch[4]) {
142
+ a = rgbMatch[4].endsWith("%") ? parseFloat(rgbMatch[4]) / 100 : parseFloat(rgbMatch[4]);
143
+ }
144
+ const oklch = rgbToOklch(r, g, b);
145
+ return { l: oklch.l, c: oklch.c, h: oklch.h, a };
146
+ }
147
+ const hslMatch = s.match(
148
+ /hsla?\(\s*([\d.]+)[,\s]+([\d.]+)%[,\s]+([\d.]+)%(?:[,\s/]+([\d.]+%?))?\s*\)/
149
+ );
150
+ if (hslMatch) {
151
+ const [r, g, b] = hslToRgb(
152
+ parseFloat(hslMatch[1]),
153
+ parseFloat(hslMatch[2]),
154
+ parseFloat(hslMatch[3])
155
+ );
156
+ let a = 1;
157
+ if (hslMatch[4]) {
158
+ a = hslMatch[4].endsWith("%") ? parseFloat(hslMatch[4]) / 100 : parseFloat(hslMatch[4]);
159
+ }
160
+ const oklch = rgbToOklch(r, g, b);
161
+ return { l: oklch.l, c: oklch.c, h: oklch.h, a };
162
+ }
163
+ const named = {
164
+ white: "#ffffff",
165
+ black: "#000000",
166
+ red: "#ff0000",
167
+ green: "#008000",
168
+ blue: "#0000ff",
169
+ yellow: "#ffff00",
170
+ cyan: "#00ffff",
171
+ magenta: "#ff00ff",
172
+ orange: "#ffa500",
173
+ transparent: "#00000000"
174
+ };
175
+ if (named[s]) return parseColor(named[s]);
176
+ return null;
177
+ }
178
+ function hslToRgb(h, s, l) {
179
+ s /= 100;
180
+ l /= 100;
181
+ const c = (1 - Math.abs(2 * l - 1)) * s;
182
+ const x = c * (1 - Math.abs(h / 60 % 2 - 1));
183
+ const m = l - c / 2;
184
+ let r = 0, g = 0, b = 0;
185
+ if (h < 60) {
186
+ r = c;
187
+ g = x;
188
+ } else if (h < 120) {
189
+ r = x;
190
+ g = c;
191
+ } else if (h < 180) {
192
+ g = c;
193
+ b = x;
194
+ } else if (h < 240) {
195
+ g = x;
196
+ b = c;
197
+ } else if (h < 300) {
198
+ r = x;
199
+ b = c;
200
+ } else {
201
+ r = c;
202
+ b = x;
203
+ }
204
+ return [
205
+ Math.round((r + m) * 255),
206
+ Math.round((g + m) * 255),
207
+ Math.round((b + m) * 255)
208
+ ];
209
+ }
210
+ function rgbToHsl(r, g, b) {
211
+ r /= 255;
212
+ g /= 255;
213
+ b /= 255;
214
+ const max = Math.max(r, g, b);
215
+ const min = Math.min(r, g, b);
216
+ const l = (max + min) / 2;
217
+ if (max === min) return [0, 0, l * 100];
218
+ const d = max - min;
219
+ const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
220
+ let h = 0;
221
+ if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
222
+ else if (max === g) h = ((b - r) / d + 2) / 6;
223
+ else h = ((r - g) / d + 4) / 6;
224
+ return [h * 360, s * 100, l * 100];
225
+ }
226
+ function formatColor(color, format) {
227
+ const hasAlpha = color.a < 1;
228
+ switch (format) {
229
+ case "hex": {
230
+ const [r, g, b] = oklchToRgb(color.l, color.c, color.h);
231
+ return rgbToHex(r, g, b, hasAlpha ? color.a : void 0);
232
+ }
233
+ case "oklch": {
234
+ const l = round(color.l * 100, 1);
235
+ const c = round(color.c, 3);
236
+ const h = round(color.h, 1);
237
+ return hasAlpha ? `oklch(${l}% ${c} ${h} / ${round(color.a, 2)})` : `oklch(${l}% ${c} ${h})`;
238
+ }
239
+ case "rgb": {
240
+ const [r, g, b] = oklchToRgb(color.l, color.c, color.h);
241
+ return hasAlpha ? `rgba(${r}, ${g}, ${b}, ${round(color.a, 2)})` : `rgb(${r}, ${g}, ${b})`;
242
+ }
243
+ case "hsl": {
244
+ const [r, g, b] = oklchToRgb(color.l, color.c, color.h);
245
+ const [h, s, l] = rgbToHsl(r, g, b);
246
+ 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)}%)`;
247
+ }
248
+ }
249
+ }
250
+ function renderAreaGradient(width, height, hue) {
251
+ const data = new ImageData(width, height);
252
+ const buf = data.data;
253
+ for (let y = 0; y < height; y++) {
254
+ const l = 1 - y / (height - 1);
255
+ for (let x = 0; x < width; x++) {
256
+ const c = x / (width - 1) * MAX_CHROMA;
257
+ const [r, g, b] = oklchToRgb(l, c, hue);
258
+ const idx = (y * width + x) * 4;
259
+ buf[idx] = r;
260
+ buf[idx + 1] = g;
261
+ buf[idx + 2] = b;
262
+ buf[idx + 3] = 255;
263
+ }
264
+ }
265
+ return data;
266
+ }
267
+ export {
268
+ clamp,
269
+ formatColor,
270
+ gamutMapChroma,
271
+ hexToRgb,
272
+ isInGamut,
273
+ maxChromaForLH,
274
+ oklchToRgb,
275
+ parseColor,
276
+ renderAreaGradient,
277
+ rgbToHex,
278
+ rgbToOklch
279
+ };
280
+ //# sourceMappingURL=color-utils.js.map