@puzzle-ui/ui 0.3.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 (240) hide show
  1. package/README.md +70 -70
  2. package/dist/components/actions/button/button.css +5 -2
  3. package/dist/components/actions/button-group/button-group.css +16 -17
  4. package/dist/components/data-display/badge/badge.css +15 -2
  5. package/dist/components/data-display/badge/index.cjs +13 -2
  6. package/dist/components/data-display/badge/index.cjs.map +1 -1
  7. package/dist/components/data-display/badge/index.d.cts +7 -2
  8. package/dist/components/data-display/badge/index.d.ts +7 -2
  9. package/dist/components/data-display/badge/index.js +13 -2
  10. package/dist/components/data-display/badge/index.js.map +1 -1
  11. package/dist/components/data-display/empty-state/empty-state.css +128 -0
  12. package/dist/components/data-display/empty-state/empty-state.utils.cjs +6 -0
  13. package/dist/components/data-display/empty-state/empty-state.utils.cjs.map +1 -0
  14. package/dist/components/data-display/empty-state/empty-state.utils.js +6 -0
  15. package/dist/components/data-display/empty-state/empty-state.utils.js.map +1 -0
  16. package/dist/components/data-display/empty-state/index.cjs +49 -0
  17. package/dist/components/data-display/empty-state/index.cjs.map +1 -0
  18. package/dist/components/data-display/empty-state/index.d.cts +19 -0
  19. package/dist/components/data-display/empty-state/index.d.ts +19 -0
  20. package/dist/components/data-display/empty-state/index.js +44 -0
  21. package/dist/components/data-display/empty-state/index.js.map +1 -0
  22. package/dist/components/data-display/rating/index.cjs +84 -0
  23. package/dist/components/data-display/rating/index.cjs.map +1 -0
  24. package/dist/components/data-display/rating/index.d.cts +3 -0
  25. package/dist/components/data-display/rating/index.d.ts +3 -0
  26. package/dist/components/data-display/rating/index.js +84 -0
  27. package/dist/components/data-display/rating/index.js.map +1 -0
  28. package/dist/components/data-display/rating/rating.css +72 -0
  29. package/dist/components/data-display/rating/rating.types.d.cts +15 -0
  30. package/dist/components/data-display/rating/rating.types.d.ts +15 -0
  31. package/dist/components/data-display/rating/rating.utils.cjs +27 -0
  32. package/dist/components/data-display/rating/rating.utils.cjs.map +1 -0
  33. package/dist/components/data-display/rating/rating.utils.js +25 -0
  34. package/dist/components/data-display/rating/rating.utils.js.map +1 -0
  35. package/dist/components/editors/text-editor/editor.cjs.map +1 -1
  36. package/dist/components/editors/text-editor/editor.js.map +1 -1
  37. package/dist/components/editors/text-editor/text-document.cjs.map +1 -1
  38. package/dist/components/editors/text-editor/text-document.js.map +1 -1
  39. package/dist/components/editors/text-editor/text-parser.cjs.map +1 -1
  40. package/dist/components/editors/text-editor/text-parser.js.map +1 -1
  41. package/dist/components/editors/text-editor/text-renderer.cjs.map +1 -1
  42. package/dist/components/editors/text-editor/text-renderer.js.map +1 -1
  43. package/dist/components/forms/autocomplete/index.cjs.map +1 -1
  44. package/dist/components/forms/autocomplete/index.js.map +1 -1
  45. package/dist/components/forms/checkbox/checkbox.css +2 -10
  46. package/dist/components/forms/color-picker/color-picker.css +351 -0
  47. package/dist/components/forms/color-picker/color-picker.types.d.cts +25 -0
  48. package/dist/components/forms/color-picker/color-picker.types.d.ts +25 -0
  49. package/dist/components/forms/color-picker/color-picker.utils.cjs +116 -0
  50. package/dist/components/forms/color-picker/color-picker.utils.cjs.map +1 -0
  51. package/dist/components/forms/color-picker/color-picker.utils.js +109 -0
  52. package/dist/components/forms/color-picker/color-picker.utils.js.map +1 -0
  53. package/dist/components/forms/color-picker/index.cjs +340 -0
  54. package/dist/components/forms/color-picker/index.cjs.map +1 -0
  55. package/dist/components/forms/color-picker/index.d.cts +3 -0
  56. package/dist/components/forms/color-picker/index.d.ts +3 -0
  57. package/dist/components/forms/color-picker/index.js +340 -0
  58. package/dist/components/forms/color-picker/index.js.map +1 -0
  59. package/dist/components/forms/file-upload/file-upload.utils.cjs.map +1 -1
  60. package/dist/components/forms/file-upload/file-upload.utils.js.map +1 -1
  61. package/dist/components/forms/input/number-input.js +5 -5
  62. package/dist/components/forms/input/number-input.js.map +1 -1
  63. package/dist/components/forms/input-group/index.d.cts +3 -0
  64. package/dist/components/forms/input-group/index.d.ts +3 -0
  65. package/dist/components/forms/input-group/input-group.cjs +18 -0
  66. package/dist/components/forms/input-group/input-group.cjs.map +1 -0
  67. package/dist/components/forms/input-group/input-group.css +62 -0
  68. package/dist/components/forms/input-group/input-group.d.cts +7 -0
  69. package/dist/components/forms/input-group/input-group.d.ts +7 -0
  70. package/dist/components/forms/input-group/input-group.js +18 -0
  71. package/dist/components/forms/input-group/input-group.js.map +1 -0
  72. package/dist/components/forms/input-group/input-group.types.d.cts +7 -0
  73. package/dist/components/forms/input-group/input-group.types.d.ts +7 -0
  74. package/dist/components/forms/input-group/input-group.utils.cjs +5 -0
  75. package/dist/components/forms/input-group/input-group.utils.cjs.map +1 -0
  76. package/dist/components/forms/input-group/input-group.utils.js +5 -0
  77. package/dist/components/forms/input-group/input-group.utils.js.map +1 -0
  78. package/dist/components/forms/radio-group/index.d.cts +2 -1
  79. package/dist/components/forms/radio-group/index.d.ts +2 -1
  80. package/dist/components/forms/select/index.cjs.map +1 -1
  81. package/dist/components/forms/select/index.js.map +1 -1
  82. package/dist/components/forms/slider/index.cjs +1 -1
  83. package/dist/components/forms/slider/index.cjs.map +1 -1
  84. package/dist/components/forms/slider/index.js +1 -1
  85. package/dist/components/forms/slider/index.js.map +1 -1
  86. package/dist/components/forms/stepper/index.d.cts +4 -2
  87. package/dist/components/forms/stepper/index.d.ts +4 -2
  88. package/dist/components/forms/time-picker/index.cjs +108 -0
  89. package/dist/components/forms/time-picker/index.cjs.map +1 -0
  90. package/dist/components/forms/time-picker/index.d.cts +3 -0
  91. package/dist/components/forms/time-picker/index.d.ts +3 -0
  92. package/dist/components/forms/time-picker/index.js +108 -0
  93. package/dist/components/forms/time-picker/index.js.map +1 -0
  94. package/dist/components/forms/time-picker/time-picker.css +166 -0
  95. package/dist/components/forms/time-picker/time-picker.types.d.cts +34 -0
  96. package/dist/components/forms/time-picker/time-picker.types.d.ts +34 -0
  97. package/dist/components/forms/time-picker/time-picker.utils.cjs +25 -0
  98. package/dist/components/forms/time-picker/time-picker.utils.cjs.map +1 -0
  99. package/dist/components/forms/time-picker/time-picker.utils.js +24 -0
  100. package/dist/components/forms/time-picker/time-picker.utils.js.map +1 -0
  101. package/dist/components/forms/token-input/index.cjs +189 -0
  102. package/dist/components/forms/token-input/index.cjs.map +1 -0
  103. package/dist/components/forms/token-input/index.d.cts +3 -0
  104. package/dist/components/forms/token-input/index.d.ts +3 -0
  105. package/dist/components/forms/token-input/index.js +189 -0
  106. package/dist/components/forms/token-input/index.js.map +1 -0
  107. package/dist/components/forms/token-input/token-input.css +145 -0
  108. package/dist/components/forms/token-input/token-input.types.d.cts +48 -0
  109. package/dist/components/forms/token-input/token-input.types.d.ts +48 -0
  110. package/dist/components/forms/token-input/token-input.utils.cjs +30 -0
  111. package/dist/components/forms/token-input/token-input.utils.cjs.map +1 -0
  112. package/dist/components/forms/token-input/token-input.utils.js +24 -0
  113. package/dist/components/forms/token-input/token-input.utils.js.map +1 -0
  114. package/dist/components/layout/aspect-ratio/aspect-ratio.css +14 -0
  115. package/dist/components/layout/aspect-ratio/aspect-ratio.utils.cjs +11 -0
  116. package/dist/components/layout/aspect-ratio/aspect-ratio.utils.cjs.map +1 -0
  117. package/dist/components/layout/aspect-ratio/aspect-ratio.utils.js +11 -0
  118. package/dist/components/layout/aspect-ratio/aspect-ratio.utils.js.map +1 -0
  119. package/dist/components/layout/aspect-ratio/index.cjs +16 -0
  120. package/dist/components/layout/aspect-ratio/index.cjs.map +1 -0
  121. package/dist/components/layout/aspect-ratio/index.d.cts +11 -0
  122. package/dist/components/layout/aspect-ratio/index.d.ts +11 -0
  123. package/dist/components/layout/aspect-ratio/index.js +16 -0
  124. package/dist/components/layout/aspect-ratio/index.js.map +1 -0
  125. package/dist/components/layout/container/container.css +1 -0
  126. package/dist/components/layout/page-layout/page-layout.css +1 -0
  127. package/dist/components/layout/resizable-panels/index.cjs +1 -1
  128. package/dist/components/layout/resizable-panels/index.cjs.map +1 -1
  129. package/dist/components/layout/resizable-panels/index.js +1 -1
  130. package/dist/components/layout/resizable-panels/index.js.map +1 -1
  131. package/dist/components/layout/resizable-panels/resizable-panels.utils.cjs.map +1 -1
  132. package/dist/components/layout/resizable-panels/resizable-panels.utils.js.map +1 -1
  133. package/dist/components/layout/scroll-area/index.cjs +27 -0
  134. package/dist/components/layout/scroll-area/index.cjs.map +1 -0
  135. package/dist/components/layout/scroll-area/index.d.cts +15 -0
  136. package/dist/components/layout/scroll-area/index.d.ts +15 -0
  137. package/dist/components/layout/scroll-area/index.js +27 -0
  138. package/dist/components/layout/scroll-area/index.js.map +1 -0
  139. package/dist/components/layout/scroll-area/scroll-area.css +25 -0
  140. package/dist/components/layout/scroll-area/scroll-area.utils.cjs +8 -0
  141. package/dist/components/layout/scroll-area/scroll-area.utils.cjs.map +1 -0
  142. package/dist/components/layout/scroll-area/scroll-area.utils.d.cts +2 -0
  143. package/dist/components/layout/scroll-area/scroll-area.utils.d.ts +2 -0
  144. package/dist/components/layout/scroll-area/scroll-area.utils.js +8 -0
  145. package/dist/components/layout/scroll-area/scroll-area.utils.js.map +1 -0
  146. package/dist/components/layout/section/index.cjs +10 -4
  147. package/dist/components/layout/section/index.cjs.map +1 -1
  148. package/dist/components/layout/section/index.d.cts +1 -1
  149. package/dist/components/layout/section/index.d.ts +1 -1
  150. package/dist/components/layout/section/index.js +11 -5
  151. package/dist/components/layout/section/index.js.map +1 -1
  152. package/dist/components/layout/section/section.css +9 -3
  153. package/dist/components/layout/section/types.d.cts +5 -5
  154. package/dist/components/layout/section/types.d.ts +5 -5
  155. package/dist/components/layout/separator/index.cjs +18 -0
  156. package/dist/components/layout/separator/index.cjs.map +1 -0
  157. package/dist/components/layout/separator/index.d.cts +17 -0
  158. package/dist/components/layout/separator/index.d.ts +17 -0
  159. package/dist/components/layout/separator/index.js +18 -0
  160. package/dist/components/layout/separator/index.js.map +1 -0
  161. package/dist/components/layout/separator/separator.css +15 -0
  162. package/dist/components/layout/separator/separator.utils.cjs +11 -0
  163. package/dist/components/layout/separator/separator.utils.cjs.map +1 -0
  164. package/dist/components/layout/separator/separator.utils.d.cts +2 -0
  165. package/dist/components/layout/separator/separator.utils.d.ts +2 -0
  166. package/dist/components/layout/separator/separator.utils.js +11 -0
  167. package/dist/components/layout/separator/separator.utils.js.map +1 -0
  168. package/dist/components/layout/stack/index.cjs +18 -2
  169. package/dist/components/layout/stack/index.cjs.map +1 -1
  170. package/dist/components/layout/stack/index.d.cts +8 -6
  171. package/dist/components/layout/stack/index.d.ts +8 -6
  172. package/dist/components/layout/stack/index.js +18 -2
  173. package/dist/components/layout/stack/index.js.map +1 -1
  174. package/dist/components/layout/stack/stack.css +118 -138
  175. package/dist/components/navigation/accordion/index.cjs.map +1 -1
  176. package/dist/components/navigation/accordion/index.js.map +1 -1
  177. package/dist/components/navigation/carousel/index.cjs +5 -2
  178. package/dist/components/navigation/carousel/index.cjs.map +1 -1
  179. package/dist/components/navigation/carousel/index.js +5 -2
  180. package/dist/components/navigation/carousel/index.js.map +1 -1
  181. package/dist/components/navigation/pagination/index.cjs +146 -0
  182. package/dist/components/navigation/pagination/index.cjs.map +1 -0
  183. package/dist/components/navigation/pagination/index.d.cts +3 -0
  184. package/dist/components/navigation/pagination/index.d.ts +3 -0
  185. package/dist/components/navigation/pagination/index.js +146 -0
  186. package/dist/components/navigation/pagination/index.js.map +1 -0
  187. package/dist/components/navigation/pagination/pagination.css +134 -0
  188. package/dist/components/navigation/pagination/pagination.types.d.cts +38 -0
  189. package/dist/components/navigation/pagination/pagination.types.d.ts +38 -0
  190. package/dist/components/navigation/pagination/pagination.utils.cjs +54 -0
  191. package/dist/components/navigation/pagination/pagination.utils.cjs.map +1 -0
  192. package/dist/components/navigation/pagination/pagination.utils.js +53 -0
  193. package/dist/components/navigation/pagination/pagination.utils.js.map +1 -0
  194. package/dist/components/navigation/tabs/index.d.cts +3 -2
  195. package/dist/components/navigation/tabs/index.d.ts +3 -2
  196. package/dist/components/navigation/tree-view/index.cjs.map +1 -1
  197. package/dist/components/navigation/tree-view/index.js.map +1 -1
  198. package/dist/components/overlays/context-menu/context-menu.css +151 -0
  199. package/dist/components/overlays/context-menu/context-menu.types.d.cts +69 -0
  200. package/dist/components/overlays/context-menu/context-menu.types.d.ts +69 -0
  201. package/dist/components/overlays/context-menu/context-menu.utils.cjs +46 -0
  202. package/dist/components/overlays/context-menu/context-menu.utils.cjs.map +1 -0
  203. package/dist/components/overlays/context-menu/context-menu.utils.js +40 -0
  204. package/dist/components/overlays/context-menu/context-menu.utils.js.map +1 -0
  205. package/dist/components/overlays/context-menu/index.cjs +830 -0
  206. package/dist/components/overlays/context-menu/index.cjs.map +1 -0
  207. package/dist/components/overlays/context-menu/index.d.cts +42 -0
  208. package/dist/components/overlays/context-menu/index.d.ts +42 -0
  209. package/dist/components/overlays/context-menu/index.js +818 -0
  210. package/dist/components/overlays/context-menu/index.js.map +1 -0
  211. package/dist/components/overlays/dropdown-menu/dropdown-menu-content.cjs.map +1 -1
  212. package/dist/components/overlays/dropdown-menu/dropdown-menu-content.js.map +1 -1
  213. package/dist/components/overlays/dropdown-menu/dropdown-menu.utils.cjs.map +1 -1
  214. package/dist/components/overlays/dropdown-menu/dropdown-menu.utils.js.map +1 -1
  215. package/dist/components/typography/heading.cjs +6 -2
  216. package/dist/components/typography/heading.cjs.map +1 -1
  217. package/dist/components/typography/heading.d.cts +3 -2
  218. package/dist/components/typography/heading.d.ts +3 -2
  219. package/dist/components/typography/heading.js +6 -2
  220. package/dist/components/typography/heading.js.map +1 -1
  221. package/dist/components/typography/text.cjs +6 -2
  222. package/dist/components/typography/text.cjs.map +1 -1
  223. package/dist/components/typography/text.d.cts +3 -2
  224. package/dist/components/typography/text.d.ts +3 -2
  225. package/dist/components/typography/text.js +6 -2
  226. package/dist/components/typography/text.js.map +1 -1
  227. package/dist/components/utilities/preview/index.cjs +89 -21
  228. package/dist/components/utilities/preview/index.cjs.map +1 -1
  229. package/dist/components/utilities/preview/index.d.cts +6 -2
  230. package/dist/components/utilities/preview/index.d.ts +6 -2
  231. package/dist/components/utilities/preview/index.js +89 -21
  232. package/dist/components/utilities/preview/index.js.map +1 -1
  233. package/dist/components/utilities/preview/preview.css +26 -11
  234. package/dist/components/utilities/transition/index.d.cts +1 -1
  235. package/dist/components/utilities/transition/index.d.ts +1 -1
  236. package/dist/index.cjs +136 -97
  237. package/dist/index.d.cts +23 -2
  238. package/dist/index.d.ts +23 -2
  239. package/dist/index.js +12 -1
  240. package/package.json +7 -6
@@ -0,0 +1,351 @@
1
+ .puzzle-color-picker {
2
+ gap: var(--puzzle-space-1, .25rem);
3
+ min-width: 0;
4
+ color: var(--puzzle-color-text);
5
+ flex-direction: column;
6
+ font-family: inherit;
7
+ display: inline-flex;
8
+ }
9
+
10
+ .puzzle-color-picker__label {
11
+ color: var(--puzzle-color-text);
12
+ font-size: var(--puzzle-font-size-sm, .875rem);
13
+ font-weight: var(--puzzle-font-weight-medium, 500);
14
+ }
15
+
16
+ .puzzle-color-picker__description {
17
+ color: var(--puzzle-color-text-muted);
18
+ font-size: var(--puzzle-font-size-xs, .75rem);
19
+ }
20
+
21
+ .puzzle-color-picker__trigger {
22
+ box-sizing: border-box;
23
+ align-items: center;
24
+ gap: var(--puzzle-space-2, .5rem);
25
+ width: 100%;
26
+ min-height: 2.5rem;
27
+ padding: var(--puzzle-space-2, .5rem) var(--puzzle-space-3, .75rem);
28
+ border: 1px solid var(--puzzle-color-border);
29
+ border-radius: var(--puzzle-radius-md, .5rem);
30
+ color: var(--puzzle-color-text);
31
+ background: var(--puzzle-color-surface);
32
+ font: inherit;
33
+ font-size: var(--puzzle-font-size-sm, .875rem);
34
+ text-align: start;
35
+ cursor: pointer;
36
+ transition: border-color var(--puzzle-duration-fast, .15s) ease,
37
+ background-color var(--puzzle-duration-fast, .15s) ease;
38
+ display: inline-flex;
39
+ }
40
+
41
+ .puzzle-color-picker__trigger:hover:not(:disabled) {
42
+ border-color: var(--puzzle-color-primary);
43
+ }
44
+
45
+ .puzzle-color-picker__trigger:focus-visible {
46
+ outline: 2px solid var(--puzzle-color-ring);
47
+ outline-offset: 2px;
48
+ }
49
+
50
+ .puzzle-color-picker__trigger:disabled {
51
+ opacity: .5;
52
+ cursor: not-allowed;
53
+ }
54
+
55
+ .puzzle-color-picker__trigger-swatch {
56
+ border: 1px solid var(--puzzle-color-border);
57
+ border-radius: var(--puzzle-radius-sm, .25rem);
58
+ flex: 0 0 1.25rem;
59
+ width: 1.25rem;
60
+ height: 1.25rem;
61
+ }
62
+
63
+ .puzzle-color-picker__trigger-value {
64
+ text-overflow: ellipsis;
65
+ white-space: nowrap;
66
+ flex: 1;
67
+ min-width: 0;
68
+ overflow: hidden;
69
+ }
70
+
71
+ .puzzle-color-picker__trigger-chevron {
72
+ color: var(--puzzle-color-text-muted);
73
+ }
74
+
75
+ .puzzle-color-picker__popover {
76
+ width: 17rem;
77
+ max-width: calc(100vw - 1rem);
78
+ padding: var(--puzzle-space-3, .75rem);
79
+ }
80
+
81
+ .puzzle-color-picker__panel {
82
+ gap: var(--puzzle-space-3, .75rem);
83
+ min-width: 0;
84
+ color: var(--puzzle-color-text);
85
+ font-size: var(--puzzle-font-size-sm, .875rem);
86
+ flex-direction: column;
87
+ display: flex;
88
+ }
89
+
90
+ .puzzle-color-picker__area {
91
+ border-radius: var(--puzzle-radius-md, .5rem);
92
+ background: var(--puzzle-color-picker-hue);
93
+ cursor: crosshair;
94
+ touch-action: none;
95
+ user-select: none;
96
+ width: 100%;
97
+ height: 10rem;
98
+ position: relative;
99
+ overflow: hidden;
100
+ }
101
+
102
+ .puzzle-color-picker__area-saturation {
103
+ background: linear-gradient(to right, #fff, #0000);
104
+ position: absolute;
105
+ inset: 0;
106
+ }
107
+
108
+ .puzzle-color-picker__area-brightness {
109
+ background: linear-gradient(to top, #000, #0000);
110
+ position: absolute;
111
+ inset: 0;
112
+ }
113
+
114
+ .puzzle-color-picker__area-indicator {
115
+ z-index: 1;
116
+ pointer-events: none;
117
+ border: 2px solid #fff;
118
+ border-radius: 50%;
119
+ width: .875rem;
120
+ height: .875rem;
121
+ position: absolute;
122
+ transform: translate(-50%, -50%);
123
+ box-shadow: 0 0 0 1px #00000073;
124
+ }
125
+
126
+ .puzzle-color-picker__area:focus-visible {
127
+ outline: 2px solid var(--puzzle-color-ring);
128
+ outline-offset: 3px;
129
+ }
130
+
131
+ .puzzle-color-picker__sliders {
132
+ gap: var(--puzzle-space-2, .5rem);
133
+ flex-direction: column;
134
+ display: flex;
135
+ }
136
+
137
+ .puzzle-color-picker__slider-row {
138
+ align-items: center;
139
+ gap: var(--puzzle-space-3, .75rem);
140
+ color: var(--puzzle-color-text-muted);
141
+ font-size: var(--puzzle-font-size-xs, .75rem);
142
+ display: flex;
143
+ }
144
+
145
+ .puzzle-color-picker__slider-row span {
146
+ flex: 0 0 3.5rem;
147
+ }
148
+
149
+ .puzzle-color-picker__slider-row input {
150
+ -webkit-appearance: none;
151
+ appearance: none;
152
+ cursor: pointer;
153
+ border: 0;
154
+ border-radius: 999px;
155
+ flex: 1;
156
+ min-width: 0;
157
+ height: 1rem;
158
+ margin: 0;
159
+ }
160
+
161
+ .puzzle-color-picker__slider-row input::-webkit-slider-thumb {
162
+ -webkit-appearance: none;
163
+ appearance: none;
164
+ background: var(--puzzle-color-text);
165
+ border: 2px solid #fff;
166
+ border-radius: 50%;
167
+ width: .875rem;
168
+ height: .875rem;
169
+ box-shadow: 0 0 0 1px #00000059;
170
+ }
171
+
172
+ .puzzle-color-picker__slider-row input::-moz-range-thumb {
173
+ background: var(--puzzle-color-text);
174
+ border: 2px solid #fff;
175
+ border-radius: 50%;
176
+ width: .75rem;
177
+ height: .75rem;
178
+ box-shadow: 0 0 0 1px #00000059;
179
+ }
180
+
181
+ .puzzle-color-picker__slider-row input:focus-visible {
182
+ outline: 2px solid var(--puzzle-color-ring);
183
+ outline-offset: 3px;
184
+ }
185
+
186
+ .puzzle-color-picker__hue-slider {
187
+ background: linear-gradient(to right, red, #ff0, #0f0, #0ff, #00f, #f0f, red);
188
+ }
189
+
190
+ .puzzle-color-picker__opacity-slider {
191
+ background-color: #fff;
192
+ background-image: linear-gradient(to right, transparent, var(--puzzle-color-picker-hue)),
193
+ conic-gradient(#ccc 25%, #fff 0 50%, #ccc 0 75%, #fff 0);
194
+ background-size: 100% 100%, .5rem .5rem;
195
+ }
196
+
197
+ .puzzle-color-picker__input-section {
198
+ gap: var(--puzzle-space-2, .5rem);
199
+ padding-top: var(--puzzle-space-3, .75rem);
200
+ border-top: 1px solid var(--puzzle-color-border);
201
+ flex-direction: column;
202
+ display: flex;
203
+ }
204
+
205
+ .puzzle-color-picker__input-label, .puzzle-color-picker__section-label {
206
+ color: var(--puzzle-color-text-muted);
207
+ font-size: var(--puzzle-font-size-xs, .75rem);
208
+ font-weight: var(--puzzle-font-weight-medium, 500);
209
+ }
210
+
211
+ .puzzle-color-picker__input-row {
212
+ gap: var(--puzzle-space-2, .5rem);
213
+ display: flex;
214
+ }
215
+
216
+ .puzzle-color-picker__input-row input {
217
+ box-sizing: border-box;
218
+ min-width: 0;
219
+ height: 2.25rem;
220
+ padding-inline: var(--puzzle-space-2, .5rem);
221
+ border: 1px solid var(--puzzle-color-border);
222
+ border-radius: var(--puzzle-radius-sm, .25rem);
223
+ color: var(--puzzle-color-text);
224
+ background: var(--puzzle-color-surface);
225
+ font-family: monospace;
226
+ font-size: var(--puzzle-font-size-sm, .875rem);
227
+ flex: 1;
228
+ }
229
+
230
+ .puzzle-color-picker__input-row input:focus-visible {
231
+ outline: 2px solid var(--puzzle-color-ring);
232
+ outline-offset: 2px;
233
+ }
234
+
235
+ .puzzle-color-picker__input-row input[aria-invalid="true"] {
236
+ border-color: var(--puzzle-color-danger);
237
+ }
238
+
239
+ .puzzle-color-picker__apply {
240
+ padding-inline: var(--puzzle-space-3, .75rem);
241
+ border: 1px solid var(--puzzle-color-border);
242
+ border-radius: var(--puzzle-radius-sm, .25rem);
243
+ color: var(--puzzle-color-text);
244
+ background: var(--puzzle-color-surface);
245
+ font: inherit;
246
+ font-size: var(--puzzle-font-size-xs, .75rem);
247
+ cursor: pointer;
248
+ }
249
+
250
+ .puzzle-color-picker__apply:hover {
251
+ background: var(--puzzle-color-surface-secondary, var(--puzzle-color-border));
252
+ }
253
+
254
+ .puzzle-color-picker__apply:focus-visible {
255
+ outline: 2px solid var(--puzzle-color-ring);
256
+ outline-offset: 2px;
257
+ }
258
+
259
+ .puzzle-color-picker__error {
260
+ color: var(--puzzle-color-danger);
261
+ font-size: var(--puzzle-font-size-xs, .75rem);
262
+ margin: 0;
263
+ }
264
+
265
+ .puzzle-color-picker__swatches-section {
266
+ gap: var(--puzzle-space-2, .5rem);
267
+ padding-top: var(--puzzle-space-3, .75rem);
268
+ border-top: 1px solid var(--puzzle-color-border);
269
+ flex-direction: column;
270
+ display: flex;
271
+ }
272
+
273
+ .puzzle-color-picker__swatches {
274
+ gap: var(--puzzle-space-2, .5rem);
275
+ grid-template-columns: repeat(8, minmax(0, 1fr));
276
+ display: grid;
277
+ }
278
+
279
+ .puzzle-color-picker__swatch {
280
+ box-sizing: border-box;
281
+ aspect-ratio: 1;
282
+ border-radius: var(--puzzle-radius-sm, .25rem);
283
+ cursor: pointer;
284
+ width: 100%;
285
+ transition: outline-color var(--puzzle-duration-fast, .15s) ease,
286
+ transform var(--puzzle-duration-fast, .15s) ease;
287
+ border: 1px solid #0000001f;
288
+ padding: 0;
289
+ position: relative;
290
+ }
291
+
292
+ .puzzle-color-picker__swatch:hover {
293
+ transform: scale(1.08);
294
+ }
295
+
296
+ .puzzle-color-picker__swatch:focus-visible {
297
+ outline: 2px solid var(--puzzle-color-ring);
298
+ outline-offset: 2px;
299
+ }
300
+
301
+ .puzzle-color-picker__swatch[data-selected="true"]:after {
302
+ border: 2px solid var(--puzzle-color-primary);
303
+ border-radius: calc(var(--puzzle-radius-sm, .25rem) + .2rem);
304
+ content: "";
305
+ pointer-events: none;
306
+ position: absolute;
307
+ inset: -.2rem;
308
+ }
309
+
310
+ .puzzle-color-picker__clear {
311
+ background-color: #fff;
312
+ background-image: linear-gradient(45deg, #ccc 25%, #0000 25%), linear-gradient(-45deg, #ccc 25%, #0000 25%), linear-gradient(45deg, #0000 75%, #ccc 75%), linear-gradient(-45deg, #0000 75%, #ccc 75%);
313
+ background-position: 0 0, 0 .25rem, .25rem -.25rem, -.25rem 0;
314
+ background-size: .5rem .5rem;
315
+ overflow: hidden;
316
+ }
317
+
318
+ .puzzle-color-picker__clear span {
319
+ pointer-events: none;
320
+ background: #dc2626;
321
+ width: 130%;
322
+ height: 2px;
323
+ position: absolute;
324
+ top: 50%;
325
+ left: -15%;
326
+ transform: rotate(-45deg);
327
+ }
328
+
329
+ .puzzle-color-picker[data-disabled="true"] {
330
+ opacity: .55;
331
+ }
332
+
333
+ @media (prefers-reduced-motion: reduce) {
334
+ .puzzle-color-picker__trigger, .puzzle-color-picker__swatch {
335
+ transition: none;
336
+ }
337
+
338
+ .puzzle-color-picker__swatch:hover {
339
+ transform: none;
340
+ }
341
+ }
342
+
343
+ @media (forced-colors: active) {
344
+ .puzzle-color-picker__trigger:focus-visible, .puzzle-color-picker__area:focus-visible, .puzzle-color-picker__swatch:focus-visible {
345
+ outline: 2px solid highlight;
346
+ }
347
+
348
+ .puzzle-color-picker__swatch[data-selected="true"]:after {
349
+ border-color: highlight;
350
+ }
351
+ }
@@ -0,0 +1,25 @@
1
+ import { ComponentPropsWithRef, ReactNode } from "react";
2
+ export type ColorPickerFormat = "hex" | "hexa" | "rgb" | "hsl";
3
+ export type ColorPickerSwatch = string | {
4
+ value: string;
5
+ label?: string;
6
+ };
7
+ export type ColorPickerProps = Omit<ComponentPropsWithRef<"button">, "children" | "value" | "defaultValue" | "onChange" | "type"> & {
8
+ value?: string;
9
+ defaultValue?: string;
10
+ onChange?: (value: string | undefined) => void;
11
+ label?: ReactNode;
12
+ description?: ReactNode;
13
+ placeholder?: string;
14
+ colors?: readonly ColorPickerSwatch[];
15
+ format?: ColorPickerFormat;
16
+ clearable?: boolean;
17
+ clearLabel?: string;
18
+ open?: boolean;
19
+ defaultOpen?: boolean;
20
+ onOpenChange?: (open: boolean) => void;
21
+ position?: "top" | "right" | "bottom" | "left";
22
+ align?: "start" | "center" | "end";
23
+ rootClassName?: string;
24
+ popoverClassName?: string;
25
+ };
@@ -0,0 +1,25 @@
1
+ import { ComponentPropsWithRef, ReactNode } from "react";
2
+ export type ColorPickerFormat = "hex" | "hexa" | "rgb" | "hsl";
3
+ export type ColorPickerSwatch = string | {
4
+ value: string;
5
+ label?: string;
6
+ };
7
+ export type ColorPickerProps = Omit<ComponentPropsWithRef<"button">, "children" | "value" | "defaultValue" | "onChange" | "type"> & {
8
+ value?: string;
9
+ defaultValue?: string;
10
+ onChange?: (value: string | undefined) => void;
11
+ label?: ReactNode;
12
+ description?: ReactNode;
13
+ placeholder?: string;
14
+ colors?: readonly ColorPickerSwatch[];
15
+ format?: ColorPickerFormat;
16
+ clearable?: boolean;
17
+ clearLabel?: string;
18
+ open?: boolean;
19
+ defaultOpen?: boolean;
20
+ onOpenChange?: (open: boolean) => void;
21
+ position?: "top" | "right" | "bottom" | "left";
22
+ align?: "start" | "center" | "end";
23
+ rootClassName?: string;
24
+ popoverClassName?: string;
25
+ };
@@ -0,0 +1,116 @@
1
+ let _puzzle_ui_core = require("@puzzle-ui/core");
2
+ // src/components/forms/color-picker/color-picker.utils.ts
3
+ const DEFAULT_HSV = {
4
+ h: 0,
5
+ s: 100,
6
+ v: 100,
7
+ a: 1
8
+ };
9
+ const rgbToHsv = ({ r, g, b, a = 1 }) => {
10
+ const red = r / 255;
11
+ const green = g / 255;
12
+ const blue = b / 255;
13
+ const max = Math.max(red, green, blue);
14
+ const delta = max - Math.min(red, green, blue);
15
+ let h = 0;
16
+ if (delta !== 0) {
17
+ if (max === red) h = 60 * ((green - blue) / delta % 6);
18
+ else if (max === green) h = 60 * ((blue - red) / delta + 2);
19
+ else h = 60 * ((red - green) / delta + 4);
20
+ }
21
+ return {
22
+ h: (h + 360) % 360,
23
+ s: max === 0 ? 0 : delta / max * 100,
24
+ v: max * 100,
25
+ a
26
+ };
27
+ };
28
+ const hsvToRgb = ({ h, s, v, a }) => {
29
+ const hue = (h % 360 + 360) % 360;
30
+ const saturation = (0, _puzzle_ui_core.clamp)(s / 100, 0, 1);
31
+ const value = (0, _puzzle_ui_core.clamp)(v / 100, 0, 1);
32
+ const chroma = value * saturation;
33
+ const x = chroma * (1 - Math.abs(hue / 60 % 2 - 1));
34
+ const m = value - chroma;
35
+ let channels;
36
+ if (hue < 60) channels = [
37
+ chroma,
38
+ x,
39
+ 0
40
+ ];
41
+ else if (hue < 120) channels = [
42
+ x,
43
+ chroma,
44
+ 0
45
+ ];
46
+ else if (hue < 180) channels = [
47
+ 0,
48
+ chroma,
49
+ x
50
+ ];
51
+ else if (hue < 240) channels = [
52
+ 0,
53
+ x,
54
+ chroma
55
+ ];
56
+ else if (hue < 300) channels = [
57
+ x,
58
+ 0,
59
+ chroma
60
+ ];
61
+ else channels = [
62
+ chroma,
63
+ 0,
64
+ x
65
+ ];
66
+ return {
67
+ r: Math.round((channels[0] + m) * 255),
68
+ g: Math.round((channels[1] + m) * 255),
69
+ b: Math.round((channels[2] + m) * 255),
70
+ a: (0, _puzzle_ui_core.clamp)(a, 0, 1)
71
+ };
72
+ };
73
+ const rgbToFormat = (rgb, format) => {
74
+ switch (format) {
75
+ case "rgb": return (0, _puzzle_ui_core.rgbToCss)(rgb);
76
+ case "hsl": return (0, _puzzle_ui_core.hslToCss)((0, _puzzle_ui_core.rgbToHsl)(rgb));
77
+ default: return (0, _puzzle_ui_core.rgbToHex)(rgb.r, rgb.g, rgb.b, rgb.a);
78
+ }
79
+ };
80
+ const hsvToFormat = (hsv, format) => rgbToFormat(hsvToRgb(hsv), format);
81
+ const parseColorToHsv = (color) => {
82
+ const rgb = (0, _puzzle_ui_core.parseColor)(color);
83
+ return rgb ? rgbToHsv(rgb) : null;
84
+ };
85
+ /**
86
+ * Resolves a CSS color in browser context.
87
+ * Core stays framework/browser independent.
88
+ */
89
+ const resolveCssColor = (color) => {
90
+ if (typeof document === "undefined") return null;
91
+ const element = document.createElement("span");
92
+ element.style.color = color;
93
+ if (!element.style.color) return null;
94
+ element.style.position = "absolute";
95
+ element.style.visibility = "hidden";
96
+ document.body.appendChild(element);
97
+ const resolved = getComputedStyle(element).color;
98
+ element.remove();
99
+ return resolved || null;
100
+ };
101
+ const parseColorToHsvInBrowser = (color) => {
102
+ const direct = parseColorToHsv(color);
103
+ if (direct) return direct;
104
+ const resolved = resolveCssColor(color);
105
+ return resolved ? parseColorToHsv(resolved) : null;
106
+ };
107
+ exports.DEFAULT_HSV = DEFAULT_HSV;
108
+ exports.hsvToFormat = hsvToFormat;
109
+ exports.hsvToRgb = hsvToRgb;
110
+ exports.parseColorToHsv = parseColorToHsv;
111
+ exports.parseColorToHsvInBrowser = parseColorToHsvInBrowser;
112
+ exports.resolveCssColor = resolveCssColor;
113
+ exports.rgbToFormat = rgbToFormat;
114
+ exports.rgbToHsv = rgbToHsv;
115
+
116
+ //# sourceMappingURL=color-picker.utils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-picker.utils.cjs","names":["clamp","rgbToCss","hslToCss","rgbToHsl","rgbToHex","parseColor"],"sources":["../../../../src/components/forms/color-picker/color-picker.utils.ts"],"sourcesContent":["import {\n clamp,\n hslToRgb,\n rgbToHsl,\n parseColor,\n rgbToHex,\n rgbToCss,\n hslToCss,\n type RGBColor,\n type HSLColor,\n} from \"@puzzle-ui/core\";\n\nimport type { ColorPickerFormat } from \"./color-picker.types\";\n\nexport type HSVColor = {\n h: number;\n s: number;\n v: number;\n a: number;\n};\n\nexport const DEFAULT_HSV: HSVColor = {\n h: 0,\n s: 100,\n v: 100,\n a: 1,\n};\n\nexport const rgbToHsv = ({ r, g, b, a = 1 }: RGBColor): HSVColor => {\n const red = r / 255;\n const green = g / 255;\n const blue = b / 255;\n\n const max = Math.max(red, green, blue);\n const min = Math.min(red, green, blue);\n const delta = max - min;\n\n let h = 0;\n\n if (delta !== 0) {\n if (max === red) {\n h = 60 * (((green - blue) / delta) % 6);\n } else if (max === green) {\n h = 60 * ((blue - red) / delta + 2);\n } else {\n h = 60 * ((red - green) / delta + 4);\n }\n }\n\n return {\n h: (h + 360) % 360,\n s: max === 0 ? 0 : (delta / max) * 100,\n v: max * 100,\n a,\n };\n};\n\nexport const hsvToRgb = ({ h, s, v, a }: HSVColor): RGBColor => {\n const hue = ((h % 360) + 360) % 360;\n\n const saturation = clamp(s / 100, 0, 1);\n const value = clamp(v / 100, 0, 1);\n\n const chroma = value * saturation;\n const x = chroma * (1 - Math.abs(((hue / 60) % 2) - 1));\n const m = value - chroma;\n\n let channels: [number, number, number];\n\n if (hue < 60) channels = [chroma, x, 0];\n else if (hue < 120) channels = [x, chroma, 0];\n else if (hue < 180) channels = [0, chroma, x];\n else if (hue < 240) channels = [0, x, chroma];\n else if (hue < 300) channels = [x, 0, chroma];\n else channels = [chroma, 0, x];\n\n return {\n r: Math.round((channels[0] + m) * 255),\n g: Math.round((channels[1] + m) * 255),\n b: Math.round((channels[2] + m) * 255),\n a: clamp(a, 0, 1),\n };\n};\n\nexport const rgbToFormat = (\n rgb: RGBColor,\n format: ColorPickerFormat,\n): string => {\n switch (format) {\n case \"rgb\":\n return rgbToCss(rgb);\n case \"hsl\":\n return hslToCss(rgbToHsl(rgb));\n case \"hexa\":\n case \"hex\":\n default:\n return rgbToHex(rgb.r, rgb.g, rgb.b, rgb.a);\n }\n};\n\nexport const hsvToFormat = (hsv: HSVColor, format: ColorPickerFormat): string =>\n rgbToFormat(hsvToRgb(hsv), format);\n\nexport const parseColorToHsv = (color: string): HSVColor | null => {\n const rgb = parseColor(color);\n\n return rgb ? rgbToHsv(rgb) : null;\n};\n\nexport const hslToFormat = (hsl: HSLColor, format: ColorPickerFormat): string =>\n rgbToFormat(hslToRgb(hsl), format);\n\n/**\n * Resolves a CSS color in browser context.\n * Core stays framework/browser independent.\n */\nexport const resolveCssColor = (color: string): string | null => {\n if (typeof document === \"undefined\") return null;\n\n const element = document.createElement(\"span\");\n\n element.style.color = color;\n\n if (!element.style.color) return null;\n\n element.style.position = \"absolute\";\n element.style.visibility = \"hidden\";\n\n document.body.appendChild(element);\n\n const resolved = getComputedStyle(element).color;\n\n element.remove();\n\n return resolved || null;\n};\n\nexport const parseColorToHsvInBrowser = (color: string): HSVColor | null => {\n const direct = parseColorToHsv(color);\n\n if (direct) return direct;\n\n const resolved = resolveCssColor(color);\n\n return resolved ? parseColorToHsv(resolved) : null;\n};\n"],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ import { clamp, hslToCss, parseColor, rgbToCss, rgbToHex, rgbToHsl } from "@puzzle-ui/core";
2
+ // src/components/forms/color-picker/color-picker.utils.ts
3
+ const DEFAULT_HSV = {
4
+ h: 0,
5
+ s: 100,
6
+ v: 100,
7
+ a: 1
8
+ };
9
+ const rgbToHsv = ({ r, g, b, a = 1 }) => {
10
+ const red = r / 255;
11
+ const green = g / 255;
12
+ const blue = b / 255;
13
+ const max = Math.max(red, green, blue);
14
+ const delta = max - Math.min(red, green, blue);
15
+ let h = 0;
16
+ if (delta !== 0) {
17
+ if (max === red) h = 60 * ((green - blue) / delta % 6);
18
+ else if (max === green) h = 60 * ((blue - red) / delta + 2);
19
+ else h = 60 * ((red - green) / delta + 4);
20
+ }
21
+ return {
22
+ h: (h + 360) % 360,
23
+ s: max === 0 ? 0 : delta / max * 100,
24
+ v: max * 100,
25
+ a
26
+ };
27
+ };
28
+ const hsvToRgb = ({ h, s, v, a }) => {
29
+ const hue = (h % 360 + 360) % 360;
30
+ const saturation = clamp(s / 100, 0, 1);
31
+ const value = clamp(v / 100, 0, 1);
32
+ const chroma = value * saturation;
33
+ const x = chroma * (1 - Math.abs(hue / 60 % 2 - 1));
34
+ const m = value - chroma;
35
+ let channels;
36
+ if (hue < 60) channels = [
37
+ chroma,
38
+ x,
39
+ 0
40
+ ];
41
+ else if (hue < 120) channels = [
42
+ x,
43
+ chroma,
44
+ 0
45
+ ];
46
+ else if (hue < 180) channels = [
47
+ 0,
48
+ chroma,
49
+ x
50
+ ];
51
+ else if (hue < 240) channels = [
52
+ 0,
53
+ x,
54
+ chroma
55
+ ];
56
+ else if (hue < 300) channels = [
57
+ x,
58
+ 0,
59
+ chroma
60
+ ];
61
+ else channels = [
62
+ chroma,
63
+ 0,
64
+ x
65
+ ];
66
+ return {
67
+ r: Math.round((channels[0] + m) * 255),
68
+ g: Math.round((channels[1] + m) * 255),
69
+ b: Math.round((channels[2] + m) * 255),
70
+ a: clamp(a, 0, 1)
71
+ };
72
+ };
73
+ const rgbToFormat = (rgb, format) => {
74
+ switch (format) {
75
+ case "rgb": return rgbToCss(rgb);
76
+ case "hsl": return hslToCss(rgbToHsl(rgb));
77
+ default: return rgbToHex(rgb.r, rgb.g, rgb.b, rgb.a);
78
+ }
79
+ };
80
+ const hsvToFormat = (hsv, format) => rgbToFormat(hsvToRgb(hsv), format);
81
+ const parseColorToHsv = (color) => {
82
+ const rgb = parseColor(color);
83
+ return rgb ? rgbToHsv(rgb) : null;
84
+ };
85
+ /**
86
+ * Resolves a CSS color in browser context.
87
+ * Core stays framework/browser independent.
88
+ */
89
+ const resolveCssColor = (color) => {
90
+ if (typeof document === "undefined") return null;
91
+ const element = document.createElement("span");
92
+ element.style.color = color;
93
+ if (!element.style.color) return null;
94
+ element.style.position = "absolute";
95
+ element.style.visibility = "hidden";
96
+ document.body.appendChild(element);
97
+ const resolved = getComputedStyle(element).color;
98
+ element.remove();
99
+ return resolved || null;
100
+ };
101
+ const parseColorToHsvInBrowser = (color) => {
102
+ const direct = parseColorToHsv(color);
103
+ if (direct) return direct;
104
+ const resolved = resolveCssColor(color);
105
+ return resolved ? parseColorToHsv(resolved) : null;
106
+ };
107
+ export { DEFAULT_HSV, hsvToFormat, hsvToRgb, parseColorToHsv, parseColorToHsvInBrowser, resolveCssColor, rgbToFormat, rgbToHsv };
108
+
109
+ //# sourceMappingURL=color-picker.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-picker.utils.js","names":[],"sources":["../../../../src/components/forms/color-picker/color-picker.utils.ts"],"sourcesContent":["import {\n clamp,\n hslToRgb,\n rgbToHsl,\n parseColor,\n rgbToHex,\n rgbToCss,\n hslToCss,\n type RGBColor,\n type HSLColor,\n} from \"@puzzle-ui/core\";\n\nimport type { ColorPickerFormat } from \"./color-picker.types\";\n\nexport type HSVColor = {\n h: number;\n s: number;\n v: number;\n a: number;\n};\n\nexport const DEFAULT_HSV: HSVColor = {\n h: 0,\n s: 100,\n v: 100,\n a: 1,\n};\n\nexport const rgbToHsv = ({ r, g, b, a = 1 }: RGBColor): HSVColor => {\n const red = r / 255;\n const green = g / 255;\n const blue = b / 255;\n\n const max = Math.max(red, green, blue);\n const min = Math.min(red, green, blue);\n const delta = max - min;\n\n let h = 0;\n\n if (delta !== 0) {\n if (max === red) {\n h = 60 * (((green - blue) / delta) % 6);\n } else if (max === green) {\n h = 60 * ((blue - red) / delta + 2);\n } else {\n h = 60 * ((red - green) / delta + 4);\n }\n }\n\n return {\n h: (h + 360) % 360,\n s: max === 0 ? 0 : (delta / max) * 100,\n v: max * 100,\n a,\n };\n};\n\nexport const hsvToRgb = ({ h, s, v, a }: HSVColor): RGBColor => {\n const hue = ((h % 360) + 360) % 360;\n\n const saturation = clamp(s / 100, 0, 1);\n const value = clamp(v / 100, 0, 1);\n\n const chroma = value * saturation;\n const x = chroma * (1 - Math.abs(((hue / 60) % 2) - 1));\n const m = value - chroma;\n\n let channels: [number, number, number];\n\n if (hue < 60) channels = [chroma, x, 0];\n else if (hue < 120) channels = [x, chroma, 0];\n else if (hue < 180) channels = [0, chroma, x];\n else if (hue < 240) channels = [0, x, chroma];\n else if (hue < 300) channels = [x, 0, chroma];\n else channels = [chroma, 0, x];\n\n return {\n r: Math.round((channels[0] + m) * 255),\n g: Math.round((channels[1] + m) * 255),\n b: Math.round((channels[2] + m) * 255),\n a: clamp(a, 0, 1),\n };\n};\n\nexport const rgbToFormat = (\n rgb: RGBColor,\n format: ColorPickerFormat,\n): string => {\n switch (format) {\n case \"rgb\":\n return rgbToCss(rgb);\n case \"hsl\":\n return hslToCss(rgbToHsl(rgb));\n case \"hexa\":\n case \"hex\":\n default:\n return rgbToHex(rgb.r, rgb.g, rgb.b, rgb.a);\n }\n};\n\nexport const hsvToFormat = (hsv: HSVColor, format: ColorPickerFormat): string =>\n rgbToFormat(hsvToRgb(hsv), format);\n\nexport const parseColorToHsv = (color: string): HSVColor | null => {\n const rgb = parseColor(color);\n\n return rgb ? rgbToHsv(rgb) : null;\n};\n\nexport const hslToFormat = (hsl: HSLColor, format: ColorPickerFormat): string =>\n rgbToFormat(hslToRgb(hsl), format);\n\n/**\n * Resolves a CSS color in browser context.\n * Core stays framework/browser independent.\n */\nexport const resolveCssColor = (color: string): string | null => {\n if (typeof document === \"undefined\") return null;\n\n const element = document.createElement(\"span\");\n\n element.style.color = color;\n\n if (!element.style.color) return null;\n\n element.style.position = \"absolute\";\n element.style.visibility = \"hidden\";\n\n document.body.appendChild(element);\n\n const resolved = getComputedStyle(element).color;\n\n element.remove();\n\n return resolved || null;\n};\n\nexport const parseColorToHsvInBrowser = (color: string): HSVColor | null => {\n const direct = parseColorToHsv(color);\n\n if (direct) return direct;\n\n const resolved = resolveCssColor(color);\n\n return resolved ? parseColorToHsv(resolved) : null;\n};\n"],"mappings":";;AAqBA,MAAa,cAAwB;CACnC,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;AACL;AAEA,MAAa,YAAY,EAAE,GAAG,GAAG,GAAG,IAAI,QAA4B;CAClE,MAAM,MAAM,IAAI;CAChB,MAAM,QAAQ,IAAI;CAClB,MAAM,OAAO,IAAI;CAEjB,MAAM,MAAM,KAAK,IAAI,KAAK,OAAO,IAAI;CAErC,MAAM,QAAQ,MADF,KAAK,IAAI,KAAK,OAAO,IACX;CAEtB,IAAI,IAAI;CAER,IAAI,UAAU,GAAG;EACf,IAAI,QAAQ,KACV,IAAI,OAAQ,QAAQ,QAAQ,QAAS;OAChC,IAAI,QAAQ,OACjB,IAAI,OAAO,OAAO,OAAO,QAAQ;OAEjC,IAAI,OAAO,MAAM,SAAS,QAAQ;CAEtC;CAEA,OAAO;EACL,IAAI,IAAI,OAAO;EACf,GAAG,QAAQ,IAAI,IAAK,QAAQ,MAAO;EACnC,GAAG,MAAM;EACT;CACF;AACF;AAEA,MAAa,YAAY,EAAE,GAAG,GAAG,GAAG,QAA4B;CAC9D,MAAM,OAAQ,IAAI,MAAO,OAAO;CAEhC,MAAM,aAAa,MAAM,IAAI,KAAK,GAAG,CAAC;CACtC,MAAM,QAAQ,MAAM,IAAI,KAAK,GAAG,CAAC;CAEjC,MAAM,SAAS,QAAQ;CACvB,MAAM,IAAI,UAAU,IAAI,KAAK,IAAM,MAAM,KAAM,IAAK,CAAC;CACrD,MAAM,IAAI,QAAQ;CAElB,IAAI;CAEJ,IAAI,MAAM,IAAI,WAAW;EAAC;EAAQ;EAAG;CAAC;MACjC,IAAI,MAAM,KAAK,WAAW;EAAC;EAAG;EAAQ;CAAC;MACvC,IAAI,MAAM,KAAK,WAAW;EAAC;EAAG;EAAQ;CAAC;MACvC,IAAI,MAAM,KAAK,WAAW;EAAC;EAAG;EAAG;CAAM;MACvC,IAAI,MAAM,KAAK,WAAW;EAAC;EAAG;EAAG;CAAM;MACvC,WAAW;EAAC;EAAQ;EAAG;CAAC;CAE7B,OAAO;EACL,GAAG,KAAK,OAAO,SAAS,KAAK,KAAK,GAAG;EACrC,GAAG,KAAK,OAAO,SAAS,KAAK,KAAK,GAAG;EACrC,GAAG,KAAK,OAAO,SAAS,KAAK,KAAK,GAAG;EACrC,GAAG,MAAM,GAAG,GAAG,CAAC;CAClB;AACF;AAEA,MAAa,eACX,KACA,WACW;CACX,QAAQ,QAAR;EACE,KAAK,OACH,OAAO,SAAS,GAAG;EACrB,KAAK,OACH,OAAO,SAAS,SAAS,GAAG,CAAC;EAG/B,SACE,OAAO,SAAS,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;CAC9C;AACF;AAEA,MAAa,eAAe,KAAe,WACzC,YAAY,SAAS,GAAG,GAAG,MAAM;AAEnC,MAAa,mBAAmB,UAAmC;CACjE,MAAM,MAAM,WAAW,KAAK;CAE5B,OAAO,MAAM,SAAS,GAAG,IAAI;AAC/B;;;;;AASA,MAAa,mBAAmB,UAAiC;CAC/D,IAAI,OAAO,aAAa,aAAa,OAAO;CAE5C,MAAM,UAAU,SAAS,cAAc,MAAM;CAE7C,QAAQ,MAAM,QAAQ;CAEtB,IAAI,CAAC,QAAQ,MAAM,OAAO,OAAO;CAEjC,QAAQ,MAAM,WAAW;CACzB,QAAQ,MAAM,aAAa;CAE3B,SAAS,KAAK,YAAY,OAAO;CAEjC,MAAM,WAAW,iBAAiB,OAAO,CAAC,CAAC;CAE3C,QAAQ,OAAO;CAEf,OAAO,YAAY;AACrB;AAEA,MAAa,4BAA4B,UAAmC;CAC1E,MAAM,SAAS,gBAAgB,KAAK;CAEpC,IAAI,QAAQ,OAAO;CAEnB,MAAM,WAAW,gBAAgB,KAAK;CAEtC,OAAO,WAAW,gBAAgB,QAAQ,IAAI;AAChD"}