@rimelight/ui 0.0.47 → 0.0.48

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 (197) hide show
  1. package/dist/index.d.mts +4 -5
  2. package/dist/preset.mjs +73 -1
  3. package/dist/resolver.d.mts +3 -4
  4. package/dist/resolver.mjs +2 -4
  5. package/dist/shortcuts.d.mts +10 -11
  6. package/dist/stores.d.mts +3 -4
  7. package/package.json +8 -6
  8. package/src/components/3d-hover/RLS3dHover.tsx +21 -0
  9. package/src/components/accordion/RLSAccordion.tsx +112 -0
  10. package/src/components/app/RLSApp.tsx +21 -0
  11. package/src/components/aspect-ratio/RLSAspectRatio.tsx +30 -0
  12. package/src/components/audio/RLSAudio.tsx +27 -0
  13. package/src/components/avatar/RLSAvatar.tsx +142 -0
  14. package/src/components/avatar/avatar.ts +22 -21
  15. package/src/components/avatar-group/RLSAvatarGroup.tsx +163 -0
  16. package/src/components/badge/RLSBadge.tsx +1 -1
  17. package/src/components/badge/RLVBadge.vue +5 -3
  18. package/src/components/banner/RLSBanner.tsx +151 -0
  19. package/src/components/breadcrumb/RLSBreadcrumb.tsx +194 -0
  20. package/src/components/browser-mockup/RLSBrowserMockup.tsx +21 -0
  21. package/src/components/button/RLSButton.tsx +49 -40
  22. package/src/components/button/RLVButton.vue +44 -32
  23. package/src/components/calendar/RLSCalendar.tsx +26 -0
  24. package/src/components/callout/RLSCallout.tsx +151 -0
  25. package/src/components/card/RLSCard.tsx +4 -0
  26. package/src/components/card/RLVCard.vue +4 -0
  27. package/src/components/card/card.ts +10 -0
  28. package/src/components/carousel/RLACarousel.astro +14 -1
  29. package/src/components/carousel/RLSCarousel.tsx +260 -0
  30. package/src/components/chart/RLSChart.tsx +299 -0
  31. package/src/components/chat/RLSChat.tsx +27 -0
  32. package/src/components/chat-message/RLSChatMessage.tsx +27 -0
  33. package/src/components/chat-messages/RLSChatMessages.tsx +27 -0
  34. package/src/components/chat-palette/RLSChatPalette.tsx +27 -0
  35. package/src/components/chat-prompt/RLSChatPrompt.tsx +27 -0
  36. package/src/components/chat-prompt-submit/RLSChatPromptSubmit.tsx +27 -0
  37. package/src/components/chat-reasoning/RLSChatReasoning.tsx +27 -0
  38. package/src/components/chat-shimmer/RLSChatShimmer.tsx +27 -0
  39. package/src/components/chat-tool/RLSChatTool.tsx +27 -0
  40. package/src/components/checkbox/RLACheckbox.astro +1 -0
  41. package/src/components/checkbox/RLSCheckbox.tsx +1 -1
  42. package/src/components/checkbox/checkbox.theme.ts +2 -2
  43. package/src/components/chip/RLSChip.tsx +65 -0
  44. package/src/components/collapsible/RLSCollapsible.tsx +89 -0
  45. package/src/components/color-area/RLSColorArea.tsx +554 -0
  46. package/src/components/color-field/RLSColorField.tsx +236 -0
  47. package/src/components/color-picker/RLSColorPicker.tsx +26 -0
  48. package/src/components/color-slider/RLSColorSlider.tsx +373 -0
  49. package/src/components/command-palette/RLSCommandPalette.tsx +26 -0
  50. package/src/components/compare/RLSCompare.tsx +26 -0
  51. package/src/components/confirm/RLSConfirm.tsx +173 -0
  52. package/src/components/container/RLSContainer.tsx +24 -0
  53. package/src/components/context-menu/RLSContextMenu.tsx +26 -0
  54. package/src/components/copy-markdown/RLSCopyMarkdown.tsx +57 -0
  55. package/src/components/dashboard-group/RLSDashboardGroup.tsx +29 -0
  56. package/src/components/dashboard-navbar/RLSDashboardNavbar.tsx +116 -0
  57. package/src/components/dashboard-panel/RLSDashboardPanel.tsx +84 -0
  58. package/src/components/dashboard-resize-handle/RLSDashboardResizeHandle.tsx +35 -0
  59. package/src/components/dashboard-search/RLADashboardSearch.astro +1 -1
  60. package/src/components/dashboard-search/RLSDashboardSearch.tsx +125 -0
  61. package/src/components/dashboard-search-button/RLSDashboardSearchButton.tsx +82 -0
  62. package/src/components/dashboard-sidebar/RLSDashboardSidebar.tsx +184 -0
  63. package/src/components/dashboard-sidebar-collapse/RLSDashboardSidebarCollapse.tsx +46 -0
  64. package/src/components/dashboard-sidebar-toggle/RLSDashboardSidebarToggle.tsx +35 -0
  65. package/src/components/dashboard-toolbar/RLSDashboardToolbar.tsx +49 -0
  66. package/src/components/date/RLSDate.tsx +34 -0
  67. package/src/components/dock/RLSDock.tsx +26 -0
  68. package/src/components/drawer/RLSDrawer.tsx +177 -0
  69. package/src/components/dropdown-menu/RLADropdownMenu.astro +250 -241
  70. package/src/components/dropdown-menu/RLSDropdownMenu.tsx +183 -86
  71. package/src/components/editor/RLSEditor.tsx +26 -0
  72. package/src/components/empty/RLSEmpty.tsx +132 -0
  73. package/src/components/error/RLSError.tsx +26 -0
  74. package/src/components/field-group/RLSFieldGroup.tsx +46 -0
  75. package/src/components/fieldset/RLSFieldset.tsx +26 -0
  76. package/src/components/file-upload/RLSFileUpload.tsx +163 -0
  77. package/src/components/floating-action/RLSFloatingAction.tsx +26 -0
  78. package/src/components/footer/RLSFooter.tsx +56 -0
  79. package/src/components/form/RLSForm.tsx +34 -0
  80. package/src/components/gallery/RLSGallery.tsx +21 -0
  81. package/src/components/gamepad/RLSGamepad.tsx +269 -0
  82. package/src/components/grid/RLSGrid.tsx +29 -0
  83. package/src/components/head/RLAHead.astro +9 -0
  84. package/src/components/head/RLSHead.tsx +42 -0
  85. package/src/components/head/UIHead.astro +3 -0
  86. package/src/components/header/RLSHeader.tsx +87 -0
  87. package/src/components/hover-card/RLSHoverCard.tsx +72 -0
  88. package/src/components/icon/RLSIcon.tsx +3 -1
  89. package/src/components/image/RLAImage.astro +447 -138
  90. package/src/components/image/RLSImage.tsx +545 -0
  91. package/src/components/image/image.theme.ts +19 -3
  92. package/src/components/image/image.ts +31 -1
  93. package/src/components/input/RLAInput.astro +62 -51
  94. package/src/components/input/RLSInput.tsx +1 -1
  95. package/src/components/input-date/RLSInputDate.tsx +92 -0
  96. package/src/components/input-menu/RLSInputMenu.tsx +199 -0
  97. package/src/components/input-number/RLSInputNumber.tsx +184 -0
  98. package/src/components/input-pin/RLSInputPin.tsx +185 -0
  99. package/src/components/input-rating/RLSInputRating.tsx +198 -0
  100. package/src/components/input-rating/input-rating.ts +4 -0
  101. package/src/components/input-tags/RLSInputTags.tsx +94 -0
  102. package/src/components/input-time/RLSInputTime.tsx +92 -0
  103. package/src/components/kbd/RLSKbd.tsx +37 -0
  104. package/src/components/keyboard/RLSKeyboard.tsx +476 -0
  105. package/src/components/knob/RLSKnob.tsx +27 -0
  106. package/src/components/label/RLSLabel.tsx +27 -0
  107. package/src/components/layout-grid/RLSLayoutGrid.tsx +402 -0
  108. package/src/components/layout-grid/layout-grid.ts +25 -1
  109. package/src/components/link/RLSLink.tsx +2 -1
  110. package/src/components/link/link.ts +21 -12
  111. package/src/components/link-group/RLSLinkGroup.tsx +76 -0
  112. package/src/components/listbox/RLSListbox.tsx +27 -0
  113. package/src/components/locale-selector/RLALocaleSelector.astro +2 -1
  114. package/src/components/locale-selector/RLSLocaleSelector.tsx +178 -0
  115. package/src/components/logo/RLALogo.astro +69 -4
  116. package/src/components/logo/RLSLogo.tsx +129 -0
  117. package/src/components/main/RLSMain.tsx +40 -0
  118. package/src/components/marquee/RLSMarquee.tsx +80 -0
  119. package/src/components/meter/RLSMeter.tsx +27 -0
  120. package/src/components/modal/RLAModal.astro +1 -1
  121. package/src/components/modal/RLSModal.tsx +109 -72
  122. package/src/components/navigation-menu/RLSNavigationMenu.tsx +228 -0
  123. package/src/components/navigation-menu/navigation-menu.ts +2 -2
  124. package/src/components/package-managers/RLSPackageManagers.tsx +204 -0
  125. package/src/components/page/RLSPage.tsx +21 -0
  126. package/src/components/page-aside/RLSPageAside.tsx +21 -0
  127. package/src/components/page-body/RLSPageBody.tsx +21 -0
  128. package/src/components/page-header/RLSPageHeader.tsx +21 -0
  129. package/src/components/page-section/RLSPageSection.tsx +201 -0
  130. package/src/components/pagination/RLSPagination.tsx +114 -0
  131. package/src/components/password/RLSPassword.tsx +27 -0
  132. package/src/components/phone-mockup/RLSPhoneMockup.tsx +27 -0
  133. package/src/components/placeholder/RLSPlaceholder.tsx +47 -0
  134. package/src/components/popover/RLSPopover.tsx +124 -0
  135. package/src/components/post/RLSPost.tsx +134 -0
  136. package/src/components/pricing-plan/RLSPricingPlan.tsx +26 -0
  137. package/src/components/pricing-table/RLSPricingTable.tsx +26 -0
  138. package/src/components/progress/RLSProgress.tsx +53 -0
  139. package/src/components/prose/RLSProse.tsx +26 -0
  140. package/src/components/qr-code/RLSQrCode.tsx +26 -0
  141. package/src/components/quote/RLAQuote.astro +10 -6
  142. package/src/components/quote/RLSQuote.tsx +37 -0
  143. package/src/components/quote/quote.theme.ts +5 -2
  144. package/src/components/radio-group/RLSRadioGroup.tsx +37 -0
  145. package/src/components/rating/RLSRating.tsx +27 -0
  146. package/src/components/scroll-area/RLSScrollArea.tsx +210 -0
  147. package/src/components/scroll-to-top/RLAScrollToTop.astro +1 -0
  148. package/src/components/scroll-to-top/RLSScrollToTop.tsx +145 -0
  149. package/src/components/search/RLSSearch.tsx +237 -0
  150. package/src/components/select/RLASelect.astro +67 -4
  151. package/src/components/select/RLSSelect.tsx +107 -39
  152. package/src/components/select/RLVSelect.vue +50 -1
  153. package/src/components/select/select.theme.ts +30 -10
  154. package/src/components/select/select.ts +20 -1
  155. package/src/components/separator/RLSSeparator.tsx +92 -0
  156. package/src/components/share/RLSShare.tsx +66 -0
  157. package/src/components/shortcuts/RLSShortcuts.tsx +393 -0
  158. package/src/components/sidebar/RLSSidebar.tsx +271 -0
  159. package/src/components/skeleton/RLSSkeleton.tsx +21 -0
  160. package/src/components/slideover/RLASlideover.astro +1 -1
  161. package/src/components/slideover/RLSSlideover.tsx +159 -0
  162. package/src/components/slider/RLSSlider.tsx +112 -0
  163. package/src/components/speed-dial/RLSSpeedDial.tsx +27 -0
  164. package/src/components/spinner/RLSSpinner.tsx +22 -0
  165. package/src/components/splitter/RLSSplitter.tsx +178 -0
  166. package/src/components/spoiler/RLSSpoiler.tsx +26 -0
  167. package/src/components/stepper/RLSStepper.tsx +205 -0
  168. package/src/components/steps/RLSSteps.tsx +108 -0
  169. package/src/components/sticky-surface/RLSStickySurface.tsx +63 -0
  170. package/src/components/surround/RLSSurround.tsx +57 -0
  171. package/src/components/switch/RLSSwitch.tsx +56 -0
  172. package/src/components/table/RLATable.astro +1044 -579
  173. package/src/components/table/RLSTable.tsx +893 -0
  174. package/src/components/table/table.theme.ts +47 -16
  175. package/src/components/table/table.ts +104 -66
  176. package/src/components/table-of-contents/RLSTableOfContents.tsx +196 -0
  177. package/src/components/tabs/RLSTabs.tsx +298 -0
  178. package/src/components/textarea/RLATextarea.astro +1 -0
  179. package/src/components/textarea/RLSTextarea.tsx +3 -1
  180. package/src/components/theme-selector/RLAThemeSelector.astro +85 -56
  181. package/src/components/theme-selector/RLSThemeSelector.tsx +131 -0
  182. package/src/components/theme-selector/theme-selector.theme.ts +5 -7
  183. package/src/components/theme-selector/theme-selector.ts +11 -1
  184. package/src/components/timeline/RLSTimeline.tsx +171 -0
  185. package/src/components/toast/RLSToast.tsx +179 -0
  186. package/src/components/toaster/RLSToaster.tsx +82 -0
  187. package/src/components/tooltip/RLSTooltip.tsx +48 -0
  188. package/src/components/tour/RLSTour.tsx +26 -0
  189. package/src/components/tree/RLSTree.tsx +26 -0
  190. package/src/components/user/RLSUser.tsx +26 -0
  191. package/src/components/video/RLAVideo.astro +4 -1
  192. package/src/components/video/RLSVideo.tsx +158 -0
  193. package/src/components/watermark/RLSWatermark.tsx +27 -0
  194. package/src/components/window-mockup/RLSWindowMockup.tsx +27 -0
  195. package/src/preset.ts +73 -1
  196. package/src/resolver.ts +6 -1
  197. package/src/virtual.d.ts +6 -0
@@ -0,0 +1,554 @@
1
+ import {
2
+ createEffect,
3
+ createMemo,
4
+ createSignal,
5
+ splitProps,
6
+ type Component,
7
+ type JSX
8
+ } from "solid-js"
9
+ import type { ColorAreaProps } from "./color-area"
10
+ import { colorAreaTheme } from "./color-area.theme"
11
+
12
+ export interface RLSColorAreaProps extends ColorAreaProps {
13
+ onChange?: (value: string) => void
14
+ onValueChange?: (value: string) => void
15
+ onChangeEnd?: (value: string) => void
16
+ children?: JSX.Element
17
+ }
18
+
19
+ type Channel =
20
+ | "hue"
21
+ | "saturation"
22
+ | "red"
23
+ | "green"
24
+ | "blue"
25
+ | "alpha"
26
+ | "lightness"
27
+ | "brightness"
28
+
29
+ interface ChannelState {
30
+ hue: number
31
+ sat: number
32
+ light: number
33
+ bright: number
34
+ red: number
35
+ green: number
36
+ blue: number
37
+ }
38
+
39
+ const clamp = (val: number, min: number, max: number) => Math.max(min, Math.min(max, val))
40
+
41
+ const hexToRgb = (hex: string): [number, number, number] => {
42
+ const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i
43
+ const fullHex = hex.replace(shorthandRegex, (_, r, g, b) => r + r + g + g + b + b)
44
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(fullHex)
45
+ return result
46
+ ? [parseInt(result[1]!, 16), parseInt(result[2]!, 16), parseInt(result[3]!, 16)]
47
+ : [0, 0, 0]
48
+ }
49
+
50
+ const toHex = (c: number): string => {
51
+ const hex = Math.max(0, Math.min(255, c)).toString(16)
52
+ return hex.length === 1 ? "0" + hex : hex
53
+ }
54
+
55
+ const rgbToHex = (r: number, g: number, b: number): string => "#" + toHex(r) + toHex(g) + toHex(b)
56
+
57
+ const rgbToHsl = (r: number, g: number, b: number): [number, number, number] => {
58
+ r /= 255
59
+ g /= 255
60
+ b /= 255
61
+ const max = Math.max(r, g, b)
62
+ const min = Math.min(r, g, b)
63
+ let h = 0
64
+ let s = 0
65
+ const l = (max + min) / 2
66
+ if (max !== min) {
67
+ const d = max - min
68
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
69
+ switch (max) {
70
+ case r:
71
+ h = (g - b) / d + (g < b ? 6 : 0)
72
+ break
73
+ case g:
74
+ h = (b - r) / d + 2
75
+ break
76
+ case b:
77
+ h = (r - g) / d + 4
78
+ break
79
+ }
80
+ h /= 6
81
+ }
82
+ return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)]
83
+ }
84
+
85
+ const hue2rgb = (p: number, q: number, t: number): number => {
86
+ if (t < 0) t += 1
87
+ if (t > 1) t -= 1
88
+ if (t < 1 / 6) return p + (q - p) * 6 * t
89
+ if (t < 1 / 2) return q
90
+ if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6
91
+ return p
92
+ }
93
+
94
+ const hslToRgb = (h: number, s: number, l: number): [number, number, number] => {
95
+ h /= 360
96
+ s /= 100
97
+ l /= 100
98
+ let r = l
99
+ let g = l
100
+ let b = l
101
+ if (s !== 0) {
102
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s
103
+ const p = 2 * l - q
104
+ r = hue2rgb(p, q, h + 1 / 3)
105
+ g = hue2rgb(p, q, h)
106
+ b = hue2rgb(p, q, h - 1 / 3)
107
+ }
108
+ return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]
109
+ }
110
+
111
+ const rgbToHsb = (r: number, g: number, b: number): [number, number, number] => {
112
+ r /= 255
113
+ g /= 255
114
+ b /= 255
115
+ const max = Math.max(r, g, b)
116
+ const min = Math.min(r, g, b)
117
+ let h = 0
118
+ let s = 0
119
+ const v = max
120
+ const d = max - min
121
+ s = max === 0 ? 0 : d / max
122
+ if (max !== min) {
123
+ switch (max) {
124
+ case r:
125
+ h = (g - b) / d + (g < b ? 6 : 0)
126
+ break
127
+ case g:
128
+ h = (b - r) / d + 2
129
+ break
130
+ case b:
131
+ h = (r - g) / d + 4
132
+ break
133
+ }
134
+ h /= 6
135
+ }
136
+ return [Math.round(h * 360), Math.round(s * 100), Math.round(v * 100)]
137
+ }
138
+
139
+ const hsbToRgb = (h: number, s: number, b: number): [number, number, number] => {
140
+ h /= 360
141
+ s /= 100
142
+ b /= 100
143
+ let r = 0
144
+ let g = 0
145
+ let bl = 0
146
+ const i = Math.floor(h * 6)
147
+ const f = h * 6 - i
148
+ const p = b * (1 - s)
149
+ const q = b * (1 - f * s)
150
+ const t = b * (1 - (1 - f) * s)
151
+ switch (i % 6) {
152
+ case 0:
153
+ r = b
154
+ g = t
155
+ bl = p
156
+ break
157
+ case 1:
158
+ r = q
159
+ g = b
160
+ bl = p
161
+ break
162
+ case 2:
163
+ r = p
164
+ g = b
165
+ bl = t
166
+ break
167
+ case 3:
168
+ r = p
169
+ g = q
170
+ bl = b
171
+ break
172
+ case 4:
173
+ r = t
174
+ g = p
175
+ bl = b
176
+ break
177
+ case 5:
178
+ r = b
179
+ g = p
180
+ bl = q
181
+ break
182
+ }
183
+ return [Math.round(r * 255), Math.round(g * 255), Math.round(bl * 255)]
184
+ }
185
+
186
+ const getChannelRange = (channel: string): { min: number; max: number } => {
187
+ switch (channel) {
188
+ case "hue":
189
+ return { min: 0, max: 360 }
190
+ case "alpha":
191
+ return { min: 0, max: 100 }
192
+ case "red":
193
+ case "green":
194
+ case "blue":
195
+ return { min: 0, max: 255 }
196
+ default:
197
+ return { min: 0, max: 100 }
198
+ }
199
+ }
200
+
201
+ const RLSColorArea: Component<RLSColorAreaProps> = (allProps) => {
202
+ const [props, rest] = splitProps(allProps, [
203
+ "colorSpace",
204
+ "defaultValue",
205
+ "disabled",
206
+ "modelValue",
207
+ "name",
208
+ "required",
209
+ "xChannel",
210
+ "xName",
211
+ "yChannel",
212
+ "yName",
213
+ "color",
214
+ "theme",
215
+ "ui",
216
+ "class",
217
+ "onChange",
218
+ "onValueChange",
219
+ "onChangeEnd",
220
+ "children"
221
+ ])
222
+
223
+ const colorSpace = props.colorSpace ?? "hsl"
224
+ const xChannel: Channel = props.xChannel ?? "saturation"
225
+ const yChannel: Channel = props.yChannel ?? "lightness"
226
+
227
+ const initialValue = props.modelValue || props.defaultValue || "#ff0000"
228
+
229
+ const [value, setValue] = createSignal<string>(initialValue)
230
+ const [isDragging, setIsDragging] = createSignal(false)
231
+ const [state, setState] = createSignal<ChannelState>({
232
+ hue: 0,
233
+ sat: 0,
234
+ light: 50,
235
+ bright: 100,
236
+ red: 255,
237
+ green: 0,
238
+ blue: 0
239
+ })
240
+ let areaRef: HTMLDivElement | undefined
241
+
242
+ const syncChannelsFromValue = (hex: string, current: ChannelState): ChannelState => {
243
+ const rgb = hexToRgb(hex)
244
+ const hsl = rgbToHsl(rgb[0], rgb[1], rgb[2])
245
+ const hsb = rgbToHsb(rgb[0], rgb[1], rgb[2])
246
+ const max = Math.max(rgb[0], rgb[1], rgb[2])
247
+ const min = Math.min(rgb[0], rgb[1], rgb[2])
248
+ return {
249
+ hue: max !== min ? hsl[0] : current.hue,
250
+ sat: hsl[1],
251
+ light: hsl[2],
252
+ bright: hsb[2],
253
+ red: rgb[0],
254
+ green: rgb[1],
255
+ blue: rgb[2]
256
+ }
257
+ }
258
+
259
+ createEffect(() => {
260
+ const hex = value()
261
+ setState((prev) => syncChannelsFromValue(hex, prev))
262
+ })
263
+
264
+ const resolvedClasses = createMemo(() =>
265
+ colorAreaTheme({
266
+ color: props.color ?? "primary",
267
+ theme: props.theme,
268
+ ui: props.ui,
269
+ class: props.class
270
+ })
271
+ )
272
+
273
+ const channelValue = (ch: Channel, s: ChannelState): number => {
274
+ switch (ch) {
275
+ case "hue":
276
+ return s.hue
277
+ case "saturation":
278
+ return s.sat
279
+ case "lightness":
280
+ return s.light
281
+ case "brightness":
282
+ return s.bright
283
+ case "red":
284
+ return s.red
285
+ case "green":
286
+ return s.green
287
+ case "blue":
288
+ return s.blue
289
+ default:
290
+ return 0
291
+ }
292
+ }
293
+
294
+ const pctX = createMemo(() => {
295
+ const range = getChannelRange(xChannel)
296
+ const s = state()
297
+ return ((channelValue(xChannel, s) - range.min) / (range.max - range.min)) * 100
298
+ })
299
+
300
+ const pctY = createMemo(() => {
301
+ const range = getChannelRange(yChannel)
302
+ const s = state()
303
+ return 100 - ((channelValue(yChannel, s) - range.min) / (range.max - range.min)) * 100
304
+ })
305
+
306
+ const xVal = createMemo(() => channelValue(xChannel, state()))
307
+ const yVal = createMemo(() => channelValue(yChannel, state()))
308
+
309
+ const areaStyle = createMemo(() => {
310
+ const hueVal = state().hue
311
+ let background: string
312
+ if (colorSpace === "hsl" && xChannel === "saturation" && yChannel === "lightness") {
313
+ background =
314
+ "linear-gradient(to top, #000 0%, transparent 50%, #fff 100%), linear-gradient(to right, #808080 0%, transparent 100%), hsl(" +
315
+ hueVal +
316
+ ", 100%, 50%)"
317
+ } else if (colorSpace === "hsb" && xChannel === "saturation" && yChannel === "brightness") {
318
+ background =
319
+ "linear-gradient(to top, #000 0%, transparent 100%), linear-gradient(to right, #fff 0%, transparent 100%), hsl(" +
320
+ hueVal +
321
+ ", 100%, 50%)"
322
+ } else {
323
+ background = `hsl(${hueVal}, 100%, 50%)`
324
+ }
325
+ return {
326
+ background,
327
+ backgroundRepeat: "no-repeat",
328
+ backgroundSize: "100% 100%"
329
+ }
330
+ })
331
+
332
+ const applyPointer = (clientX: number, clientY: number) => {
333
+ const area = areaRef
334
+ if (!area) return
335
+ if (props.disabled) return
336
+ const rect = area.getBoundingClientRect()
337
+ const x = clamp((clientX - rect.left) / rect.width, 0, 1)
338
+ const y = 1 - clamp((clientY - rect.top) / rect.height, 0, 1)
339
+
340
+ const xRange = getChannelRange(xChannel)
341
+ const yRange = getChannelRange(yChannel)
342
+ const newX = Math.round(xRange.min + x * (xRange.max - xRange.min))
343
+ const newY = Math.round(yRange.min + y * (yRange.max - yRange.min))
344
+
345
+ const cur = state()
346
+ let hue = cur.hue
347
+ let saturation = cur.sat
348
+ let lightness = cur.light
349
+ let brightness = cur.bright
350
+ let r = cur.red
351
+ let g = cur.green
352
+ let b = cur.blue
353
+
354
+ let newRgb: [number, number, number] = [r, g, b]
355
+
356
+ if (colorSpace === "hsl") {
357
+ if (xChannel === "saturation") saturation = newX
358
+ if (yChannel === "lightness") lightness = newY
359
+ if (xChannel === "lightness") lightness = newX
360
+ if (yChannel === "saturation") saturation = newY
361
+ if (xChannel === "hue") hue = newX
362
+ if (yChannel === "hue") hue = newY
363
+ newRgb = hslToRgb(hue, saturation, lightness)
364
+ } else if (colorSpace === "hsb") {
365
+ if (xChannel === "saturation") saturation = newX
366
+ if (yChannel === "brightness") brightness = newY
367
+ if (xChannel === "brightness") brightness = newX
368
+ if (yChannel === "saturation") saturation = newY
369
+ if (xChannel === "hue") hue = newX
370
+ if (yChannel === "hue") hue = newY
371
+ newRgb = hsbToRgb(hue, saturation, brightness)
372
+ } else if (colorSpace === "rgb") {
373
+ if (xChannel === "red") r = newX
374
+ if (yChannel === "green") g = newY
375
+ if (xChannel === "green") g = newX
376
+ if (yChannel === "red") r = newY
377
+ if (xChannel === "blue") b = newX
378
+ if (yChannel === "blue") b = newY
379
+ newRgb = [r, g, b]
380
+ }
381
+
382
+ const newValue = rgbToHex(newRgb[0], newRgb[1], newRgb[2])
383
+ if (newValue !== value()) {
384
+ setState({
385
+ hue,
386
+ sat: saturation,
387
+ light: lightness,
388
+ bright: brightness,
389
+ red: newRgb[0],
390
+ green: newRgb[1],
391
+ blue: newRgb[2]
392
+ })
393
+ setValue(newValue)
394
+ props.onChange?.(newValue)
395
+ props.onValueChange?.(newValue)
396
+ }
397
+ }
398
+
399
+ const handlePointerDown = (e: PointerEvent) => {
400
+ if (props.disabled) return
401
+ setIsDragging(true)
402
+ try {
403
+ ;(e.currentTarget as HTMLElement).setPointerCapture(e.pointerId)
404
+ } catch {}
405
+ applyPointer(e.clientX, e.clientY)
406
+ }
407
+
408
+ const handlePointerMove = (e: PointerEvent) => {
409
+ if (!isDragging()) return
410
+ applyPointer(e.clientX, e.clientY)
411
+ }
412
+
413
+ const handlePointerUp = (e: PointerEvent) => {
414
+ if (!isDragging()) return
415
+ setIsDragging(false)
416
+ try {
417
+ ;(e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId)
418
+ } catch {}
419
+ props.onChangeEnd?.(value())
420
+ }
421
+
422
+ const handleKeyDown = (e: KeyboardEvent) => {
423
+ if (props.disabled) return
424
+ const isShift = e.shiftKey
425
+ const stepSize = isShift ? 10 : 1
426
+ const xRange = getChannelRange(xChannel)
427
+ const yRange = getChannelRange(yChannel)
428
+ let posX = xVal()
429
+ let posY = yVal()
430
+ let handled = false
431
+
432
+ if (e.key === "ArrowLeft") {
433
+ posX = clamp(posX - stepSize, xRange.min, xRange.max)
434
+ handled = true
435
+ } else if (e.key === "ArrowRight") {
436
+ posX = clamp(posX + stepSize, xRange.min, xRange.max)
437
+ handled = true
438
+ } else if (e.key === "ArrowUp") {
439
+ posY = clamp(posY + stepSize, yRange.min, yRange.max)
440
+ handled = true
441
+ } else if (e.key === "ArrowDown") {
442
+ posY = clamp(posY - stepSize, yRange.min, yRange.max)
443
+ handled = true
444
+ } else if (e.key === "Home") {
445
+ posX = xRange.min
446
+ handled = true
447
+ } else if (e.key === "End") {
448
+ posX = xRange.max
449
+ handled = true
450
+ }
451
+
452
+ if (handled) {
453
+ e.preventDefault()
454
+ const cur = state()
455
+ let hue = cur.hue
456
+ let saturation = cur.sat
457
+ let lightness = cur.light
458
+ let brightness = cur.bright
459
+ let r = cur.red
460
+ let g = cur.green
461
+ let b = cur.blue
462
+
463
+ let newRgb: [number, number, number] = [r, g, b]
464
+
465
+ if (colorSpace === "hsl") {
466
+ if (xChannel === "saturation") saturation = posX
467
+ if (yChannel === "lightness") lightness = posY
468
+ if (xChannel === "lightness") lightness = posX
469
+ if (yChannel === "saturation") saturation = posY
470
+ if (xChannel === "hue") hue = posX
471
+ if (yChannel === "hue") hue = posY
472
+ newRgb = hslToRgb(hue, saturation, lightness)
473
+ } else if (colorSpace === "hsb") {
474
+ if (xChannel === "saturation") saturation = posX
475
+ if (yChannel === "brightness") brightness = posY
476
+ if (xChannel === "brightness") brightness = posX
477
+ if (yChannel === "saturation") saturation = posY
478
+ if (xChannel === "hue") hue = posX
479
+ if (yChannel === "hue") hue = posY
480
+ newRgb = hsbToRgb(hue, saturation, brightness)
481
+ } else if (colorSpace === "rgb") {
482
+ if (xChannel === "red") r = posX
483
+ if (yChannel === "green") g = posY
484
+ if (xChannel === "green") g = posX
485
+ if (yChannel === "red") r = posY
486
+ if (xChannel === "blue") b = posX
487
+ if (yChannel === "blue") b = posY
488
+ newRgb = [r, g, b]
489
+ }
490
+
491
+ const newValue = rgbToHex(newRgb[0], newRgb[1], newRgb[2])
492
+ if (newValue !== value()) {
493
+ setState({
494
+ hue,
495
+ sat: saturation,
496
+ light: lightness,
497
+ bright: brightness,
498
+ red: newRgb[0],
499
+ green: newRgb[1],
500
+ blue: newRgb[2]
501
+ })
502
+ setValue(newValue)
503
+ props.onChange?.(newValue)
504
+ props.onValueChange?.(newValue)
505
+ }
506
+ }
507
+ }
508
+
509
+ return (
510
+ <div
511
+ class={`${resolvedClasses().root} ${props.disabled ? "opacity-50 pointer-events-none" : ""}`}
512
+ data-slot="root"
513
+ data-color-space={colorSpace}
514
+ data-value={value()}
515
+ data-x-channel={xChannel}
516
+ data-y-channel={yChannel}
517
+ data-disabled={props.disabled ? "true" : "false"}
518
+ data-theme={props.theme}
519
+ {...rest}
520
+ >
521
+ <div
522
+ ref={(el) => (areaRef = el)}
523
+ class={resolvedClasses().area}
524
+ data-slot="area"
525
+ style={areaStyle()}
526
+ onPointerDown={handlePointerDown}
527
+ onPointerMove={handlePointerMove}
528
+ onPointerUp={handlePointerUp}
529
+ onPointerCancel={handlePointerUp}
530
+ >
531
+ <div
532
+ class={resolvedClasses().thumb}
533
+ data-slot="thumb"
534
+ role="slider"
535
+ aria-label="Color Area Thumb"
536
+ tabindex={0}
537
+ style={{
538
+ "left": `${pctX()}%`,
539
+ "top": `${pctY()}%`,
540
+ "background-color": value()
541
+ }}
542
+ onKeyDown={handleKeyDown}
543
+ />
544
+ </div>
545
+ {props.name ? (
546
+ <input type="hidden" name={props.name} value={value()} data-main-input />
547
+ ) : null}
548
+ {props.xName ? <input type="hidden" name={props.xName} value={xVal()} data-x-input /> : null}
549
+ {props.yName ? <input type="hidden" name={props.yName} value={yVal()} data-y-input /> : null}
550
+ </div>
551
+ )
552
+ }
553
+
554
+ export default RLSColorArea