@rimelight/ui 0.0.47 → 0.0.49

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,476 @@
1
+ import { createMemo, For, Show, splitProps, type Component } from "solid-js"
2
+
3
+ interface HighlightGroup {
4
+ keys: string[]
5
+ color?: string
6
+ label?: string
7
+ }
8
+
9
+ export interface RLSKeyboardProps {
10
+ highlightedKeys?: string[]
11
+ groups?: HighlightGroup[]
12
+ keyGap?: number
13
+ sectionGap?: number
14
+ keySize?: number
15
+ variant?: "full" | "60"
16
+ os?: "windows" | "mac"
17
+ highlightColor?: string
18
+ backgroundColor?: string
19
+ }
20
+
21
+ interface Key {
22
+ label?: string
23
+ width: number
24
+ height?: number
25
+ code?: string
26
+ type?: "spacer" | "key"
27
+ }
28
+
29
+ interface RenderKey extends Key {
30
+ x: number
31
+ y: number
32
+ w: number
33
+ h: number
34
+ }
35
+
36
+ const mainRows: Key[][] = [
37
+ [
38
+ { label: "Esc", width: 1, code: "Escape" },
39
+ { type: "spacer", width: 1 },
40
+ { label: "F1", width: 1 },
41
+ { label: "F2", width: 1 },
42
+ { label: "F3", width: 1 },
43
+ { label: "F4", width: 1 },
44
+ { type: "spacer", width: 0.5 },
45
+ { label: "F5", width: 1 },
46
+ { label: "F6", width: 1 },
47
+ { label: "F7", width: 1 },
48
+ { label: "F8", width: 1 },
49
+ { type: "spacer", width: 0.5 },
50
+ { label: "F9", width: 1 },
51
+ { label: "F10", width: 1 },
52
+ { label: "F11", width: 1 },
53
+ { label: "F12", width: 1 }
54
+ ],
55
+ [
56
+ { label: "`", width: 1 },
57
+ { label: "1", width: 1, code: "Digit1" },
58
+ { label: "2", width: 1, code: "Digit2" },
59
+ { label: "3", width: 1, code: "Digit3" },
60
+ { label: "4", width: 1, code: "Digit4" },
61
+ { label: "5", width: 1, code: "Digit5" },
62
+ { label: "6", width: 1, code: "Digit6" },
63
+ { label: "7", width: 1, code: "Digit7" },
64
+ { label: "8", width: 1, code: "Digit8" },
65
+ { label: "9", width: 1, code: "Digit9" },
66
+ { label: "0", width: 1, code: "Digit0" },
67
+ { label: "-", width: 1, code: "Minus" },
68
+ { label: "=", width: 1, code: "Equal" },
69
+ { label: "Bkspc", width: 2, code: "Backspace" }
70
+ ],
71
+ [
72
+ { label: "Tab", width: 1.5 },
73
+ { label: "Q", width: 1 },
74
+ { label: "W", width: 1 },
75
+ { label: "E", width: 1 },
76
+ { label: "R", width: 1 },
77
+ { label: "T", width: 1 },
78
+ { label: "Y", width: 1 },
79
+ { label: "U", width: 1 },
80
+ { label: "I", width: 1 },
81
+ { label: "O", width: 1 },
82
+ { label: "P", width: 1 },
83
+ { label: "[", width: 1 },
84
+ { label: "]", width: 1 },
85
+ { label: "\\", width: 1.5 }
86
+ ],
87
+ [
88
+ { label: "Caps", width: 1.75, code: "CapsLock" },
89
+ { label: "A", width: 1 },
90
+ { label: "S", width: 1 },
91
+ { label: "D", width: 1 },
92
+ { label: "F", width: 1 },
93
+ { label: "G", width: 1 },
94
+ { label: "H", width: 1 },
95
+ { label: "J", width: 1 },
96
+ { label: "K", width: 1 },
97
+ { label: "L", width: 1 },
98
+ { label: ";", width: 1 },
99
+ { label: "'", width: 1 },
100
+ { label: "Enter", width: 2.25, code: "Enter" }
101
+ ],
102
+ [
103
+ { label: "Shift", width: 2.5, code: "ShiftLeft" },
104
+ { label: "Z", width: 1 },
105
+ { label: "X", width: 1 },
106
+ { label: "C", width: 1 },
107
+ { label: "V", width: 1 },
108
+ { label: "B", width: 1 },
109
+ { label: "N", width: 1 },
110
+ { label: "M", width: 1 },
111
+ { label: ",", width: 1 },
112
+ { label: ".", width: 1, code: "Period" },
113
+ { label: "/", width: 1, code: "Slash" },
114
+ { label: "Shift", width: 2.5, code: "ShiftRight" }
115
+ ],
116
+ [
117
+ { label: "Ctrl", width: 1.25, code: "ControlLeft" },
118
+ { label: "Win", width: 1.25, code: "MetaLeft" },
119
+ { label: "Alt", width: 1.25, code: "AltLeft" },
120
+ { label: "Space", width: 6.25, code: "Space" },
121
+ { label: "Alt", width: 1.25, code: "AltRight" },
122
+ { label: "Fn", width: 1.25 },
123
+ { label: "Menu", width: 1.25, code: "ContextMenu" },
124
+ { label: "Ctrl", width: 1.25, code: "ControlRight" }
125
+ ]
126
+ ]
127
+
128
+ const functionRows: Key[][] = [
129
+ [
130
+ { label: "PrtSc", width: 1, code: "PrintScreen" },
131
+ { label: "ScrLk", width: 1, code: "ScrollLock" },
132
+ { label: "Pause", width: 1, code: "Pause" }
133
+ ],
134
+ [
135
+ { label: "Ins", width: 1 },
136
+ { label: "Home", width: 1 },
137
+ { label: "PgUp", width: 1 }
138
+ ],
139
+ [
140
+ { label: "Del", width: 1 },
141
+ { label: "End", width: 1 },
142
+ { label: "PgDn", width: 1 }
143
+ ],
144
+ [{ type: "spacer", width: 3 }],
145
+ [
146
+ { type: "spacer", width: 1 },
147
+ { label: "↑", width: 1, code: "ArrowUp" },
148
+ { type: "spacer", width: 1 }
149
+ ],
150
+ [
151
+ { label: "←", width: 1, code: "ArrowLeft" },
152
+ { label: "↓", width: 1, code: "ArrowDown" },
153
+ { label: "→", width: 1, code: "ArrowRight" }
154
+ ]
155
+ ]
156
+
157
+ const numpadKeys: Key[] = [
158
+ { label: "Num", width: 1, code: "NumLock" },
159
+ { label: "/", width: 1, code: "NumpadDivide" },
160
+ { label: "*", width: 1, code: "NumpadMultiply" },
161
+ { label: "-", width: 1, code: "NumpadSubtract" },
162
+ { label: "7", width: 1, code: "Numpad7" },
163
+ { label: "8", width: 1, code: "Numpad8" },
164
+ { label: "9", width: 1, code: "Numpad9" },
165
+ { label: "+", width: 1, height: 2, code: "NumpadAdd" },
166
+ { label: "4", width: 1, code: "Numpad4" },
167
+ { label: "5", width: 1, code: "Numpad5" },
168
+ { label: "6", width: 1, code: "Numpad6" },
169
+ { label: "1", width: 1, code: "Numpad1" },
170
+ { label: "2", width: 1, code: "Numpad2" },
171
+ { label: "3", width: 1, code: "Numpad3" },
172
+ { label: "Enter", width: 1, height: 2, code: "NumpadEnter" },
173
+ { label: "0", width: 2, code: "Numpad0" },
174
+ { label: ".", width: 1, code: "NumpadDecimal" }
175
+ ]
176
+
177
+ const numpadPositions: [number, number][] = [
178
+ [0, 0],
179
+ [1, 0],
180
+ [2, 0],
181
+ [3, 0],
182
+ [0, 1],
183
+ [1, 1],
184
+ [2, 1],
185
+ [3, 1],
186
+ [0, 2],
187
+ [1, 2],
188
+ [2, 2],
189
+ [0, 3],
190
+ [1, 3],
191
+ [2, 3],
192
+ [3, 3],
193
+ [0, 4],
194
+ [2, 4]
195
+ ]
196
+
197
+ const RLSKeyboard: Component<RLSKeyboardProps> = (allProps) => {
198
+ const [props] = splitProps(allProps, [
199
+ "highlightedKeys",
200
+ "groups",
201
+ "keyGap",
202
+ "sectionGap",
203
+ "keySize",
204
+ "variant",
205
+ "os",
206
+ "highlightColor",
207
+ "backgroundColor"
208
+ ])
209
+
210
+ const keyGap = (): number => props.keyGap ?? 8
211
+ const sectionGap = (): number => props.sectionGap ?? 40
212
+ const keySize = (): number => props.keySize ?? 40
213
+ const variant = (): "full" | "60" => props.variant ?? "full"
214
+ const os = (): "windows" | "mac" => props.os ?? "windows"
215
+ const highlightColor = (): string => props.highlightColor || "var(--rl-primary-500)"
216
+ const backgroundColor = (): string => props.backgroundColor || "transparent"
217
+ const highlightedKeys = (): string[] => props.highlightedKeys ?? []
218
+ const groups = (): HighlightGroup[] => props.groups ?? []
219
+
220
+ const getKeyLabel = (key: Key): string | undefined => {
221
+ if (os() !== "mac") return key.label
222
+
223
+ const macMap: Record<string, string> = {
224
+ Ctrl: "control",
225
+ Win: "option",
226
+ Alt: "command",
227
+ Bkspc: "delete",
228
+ Enter: "return",
229
+ Caps: "caps lock",
230
+ Shift: "shift",
231
+ Menu: "option",
232
+ Tab: "tab",
233
+ Esc: "esc"
234
+ }
235
+
236
+ const label = (key.label && macMap[key.label]) || key.label
237
+
238
+ if (label === "command") return "cmd ⌘"
239
+ if (label === "option") return "opt ⌥"
240
+ if (label === "control") return "ctrl ⌃"
241
+ if (label === "shift") return "shift ⇧"
242
+ if (label === "return") return "return ↩"
243
+ if (label === "delete") return "delete ⌫"
244
+
245
+ return label
246
+ }
247
+
248
+ const getKeyHighlight = (key: Key): { active: boolean; color: string | undefined } => {
249
+ const code = key.code || key.label || ""
250
+ const label = key.label || ""
251
+ const macLabel = getKeyLabel(key) || ""
252
+
253
+ const isMatch = (list: string[]) => {
254
+ if (!list || !Array.isArray(list)) return false
255
+ if (list.includes(code)) return true
256
+ if (list.includes(label)) {
257
+ if (code.startsWith("Numpad") && /^\d$/.test(label)) return false
258
+ return true
259
+ }
260
+ return os() === "mac" && list.includes(macLabel)
261
+ }
262
+
263
+ if (isMatch(highlightedKeys())) {
264
+ return { active: true, color: highlightColor() }
265
+ }
266
+
267
+ for (const group of groups()) {
268
+ if (isMatch(group.keys)) {
269
+ return { active: true, color: group.color || highlightColor() }
270
+ }
271
+ }
272
+
273
+ return { active: false, color: undefined }
274
+ }
275
+
276
+ const displayMainRows = createMemo<Key[][]>(() =>
277
+ variant() === "60"
278
+ ? [
279
+ [{ label: "Esc", width: 1, code: "Escape" }, ...(mainRows[1] || []).slice(1)],
280
+ ...mainRows.slice(2)
281
+ ]
282
+ : mainRows
283
+ )
284
+
285
+ const processRows = (rows: Key[][], startX: number, startY: number): RenderKey[] => {
286
+ const result: RenderKey[] = []
287
+ let currentY = startY
288
+
289
+ for (const row of rows) {
290
+ let currentX = startX
291
+ for (const key of row) {
292
+ const w = key.width || 1
293
+ const h = key.height || 1
294
+ const widthPx = w * keySize() + (w - 1) * keyGap()
295
+ const heightPx = h * keySize() + (h - 1) * keyGap()
296
+
297
+ if (key.type !== "spacer") {
298
+ result.push({ ...key, x: currentX, y: currentY, w: widthPx, h: heightPx })
299
+ }
300
+ currentX += widthPx + keyGap()
301
+ }
302
+ currentY += keySize() + keyGap()
303
+ }
304
+ return result
305
+ }
306
+
307
+ const mainRenderKeys = createMemo<RenderKey[]>(() => processRows(displayMainRows(), 0, 0))
308
+ const mainHeight = (): number => displayMainRows().length * (keySize() + keyGap())
309
+
310
+ const secondaryRenderKeys = createMemo<RenderKey[]>(() =>
311
+ variant() === "full" ? processRows(functionRows, 0, mainHeight() + sectionGap()) : []
312
+ )
313
+
314
+ const numpadRenderKeys = createMemo<RenderKey[]>(() => {
315
+ if (variant() !== "full") return []
316
+ const result: RenderKey[] = []
317
+ const secondaryY = mainHeight() + sectionGap()
318
+ const numpadX = 3 * keySize() + 3 * keyGap() + sectionGap()
319
+
320
+ numpadKeys.forEach((key, i) => {
321
+ const w = key.width || 1
322
+ const h = key.height || 1
323
+ const pxOffset = numpadPositions[i]?.[0] ?? 0
324
+ const pyOffset = numpadPositions[i]?.[1] ?? 0
325
+ const px = numpadX + pxOffset * (keySize() + keyGap())
326
+ const py = secondaryY + (pyOffset + 1) * (keySize() + keyGap())
327
+
328
+ result.push({
329
+ ...key,
330
+ x: px,
331
+ y: py,
332
+ w: w * keySize() + (w - 1) * keyGap(),
333
+ h: h * keySize() + (h - 1) * keyGap()
334
+ })
335
+ })
336
+
337
+ return result
338
+ })
339
+
340
+ const totalWidth = createMemo(() => {
341
+ let width = 15 * keySize() + 14 * keyGap()
342
+ if (variant() === "full") {
343
+ const numpadX = 3 * keySize() + 3 * keyGap() + sectionGap()
344
+ width = Math.max(width, numpadX + 4 * keySize() + 3 * keyGap())
345
+ }
346
+ return width
347
+ })
348
+
349
+ const finalHeight = createMemo(() => {
350
+ if (variant() === "full") {
351
+ const secondaryY = mainHeight() + sectionGap()
352
+ return secondaryY + 6 * keySize() + 5 * keyGap()
353
+ }
354
+ return mainHeight()
355
+ })
356
+
357
+ const allKeys = createMemo<RenderKey[]>(() => [
358
+ ...mainRenderKeys(),
359
+ ...secondaryRenderKeys(),
360
+ ...numpadRenderKeys()
361
+ ])
362
+
363
+ return (
364
+ <div class="keyboard-wrapper">
365
+ <div class="keyboard-container">
366
+ <svg
367
+ viewBox={`-16 -16 ${totalWidth() + 32} ${finalHeight() + 64}`}
368
+ class="keyboard-svg"
369
+ preserveAspectRatio="xMidYMid meet"
370
+ >
371
+ <Show when={backgroundColor() !== "transparent"}>
372
+ <rect
373
+ x="-16"
374
+ y="-16"
375
+ width={totalWidth() + 32}
376
+ height={finalHeight() + 64}
377
+ fill={backgroundColor()}
378
+ rx="12"
379
+ />
380
+ </Show>
381
+
382
+ <For each={allKeys()}>
383
+ {(key) => {
384
+ const highlight = getKeyHighlight(key)
385
+ const color = highlight.active ? highlight.color || highlightColor() : "#2a2a3e"
386
+ const label = getKeyLabel(key)
387
+
388
+ return (
389
+ <g class={`kb-key-group ${highlight.active ? "highlighted" : ""}`}>
390
+ <rect
391
+ x={key.x}
392
+ y={key.y + 1}
393
+ width={key.w}
394
+ height={key.h}
395
+ rx="4"
396
+ fill="#1a1a2e"
397
+ />
398
+ <rect
399
+ x={key.x}
400
+ y={key.y}
401
+ width={key.w}
402
+ height={key.h}
403
+ rx="4"
404
+ fill={color}
405
+ stroke={highlight.active ? "#ffffff66" : "#3a3a4e"}
406
+ stroke-width="1"
407
+ />
408
+ {label ? (
409
+ <text
410
+ x={key.x + key.w / 2}
411
+ y={key.y + key.h / 2}
412
+ text-anchor="middle"
413
+ dominant-baseline="central"
414
+ class="kb-key-label"
415
+ fill={highlight.active ? "#fff" : "#e0e0e0"}
416
+ >
417
+ {label}
418
+ </text>
419
+ ) : null}
420
+ </g>
421
+ )
422
+ }}
423
+ </For>
424
+ </svg>
425
+ </div>
426
+
427
+ <Show when={groups().some((group) => group.label)}>
428
+ <div class="flex flex-wrap justify-center gap-x-6 gap-y-3 mt-6 w-full">
429
+ <For each={groups().filter((group) => group.label)}>
430
+ {(group) => (
431
+ <div class="flex items-center gap-2 m-0 p-0 text-[10px] text-[#a0a0b0] uppercase tracking-[0.05em] font-medium whitespace-nowrap leading-none">
432
+ <svg width="8" height="8" class="flex-shrink-0 block">
433
+ <rect width="8" height="8" rx="2" fill={group.color || "#6366f1"} />
434
+ </svg>
435
+ <span class="m-0 p-0 leading-none inline-block">{group.label}</span>
436
+ </div>
437
+ )}
438
+ </For>
439
+ </div>
440
+ </Show>
441
+
442
+ <style>{`
443
+ .keyboard-wrapper {
444
+ display: flex;
445
+ flex-direction: column;
446
+ align-items: center;
447
+ padding: 1rem;
448
+ border-radius: 0.75rem;
449
+ width: 100%;
450
+ max-width: 100%;
451
+ margin: 1rem 0;
452
+ box-sizing: border-box;
453
+ }
454
+ .keyboard-container {
455
+ width: 100%;
456
+ display: flex;
457
+ justify-content: center;
458
+ }
459
+ .keyboard-svg {
460
+ width: 100%;
461
+ height: auto;
462
+ max-width: 56.25rem;
463
+ }
464
+ .kb-key-label {
465
+ font-family: var(--font-mono, monospace);
466
+ font-size: 0.625rem;
467
+ font-weight: 600;
468
+ pointer-events: none;
469
+ user-select: none;
470
+ }
471
+ `}</style>
472
+ </div>
473
+ )
474
+ }
475
+
476
+ export default RLSKeyboard
@@ -0,0 +1,27 @@
1
+ import { createMemo, splitProps, type Component, type JSX } from "solid-js"
2
+ import type { KnobProps } from "./knob"
3
+ import { knobTheme } from "./knob.theme"
4
+
5
+ export interface RLSKnobProps extends KnobProps {
6
+ children?: JSX.Element
7
+ }
8
+
9
+ const RLSKnob: Component<RLSKnobProps> = (allProps) => {
10
+ const [props, rest] = splitProps(allProps, ["ui", "class", "children"])
11
+
12
+ const resolvedClasses = createMemo(() =>
13
+ knobTheme({
14
+ ui: props.ui,
15
+ class: props.class,
16
+ ...allProps
17
+ })
18
+ )
19
+
20
+ return (
21
+ <div class={resolvedClasses().root} data-slot="root" {...rest}>
22
+ {props.children}
23
+ </div>
24
+ )
25
+ }
26
+
27
+ export default RLSKnob
@@ -0,0 +1,27 @@
1
+ import { createMemo, splitProps, type Component, type JSX } from "solid-js"
2
+ import type { LabelProps } from "./label"
3
+ import { labelTheme } from "./label.theme"
4
+
5
+ export interface RLSLabelProps extends LabelProps {
6
+ children?: JSX.Element
7
+ }
8
+
9
+ const RLSLabel: Component<RLSLabelProps> = (allProps) => {
10
+ const [props, rest] = splitProps(allProps, ["for", "size", "ui", "class", "children"])
11
+
12
+ const classes = createMemo(() =>
13
+ labelTheme({
14
+ size: props.size ?? "md",
15
+ ui: props.ui,
16
+ class: props.class
17
+ })
18
+ )
19
+
20
+ return (
21
+ <label class={classes()["root"]} data-slot="root" for={props.for} {...rest}>
22
+ {props.children}
23
+ </label>
24
+ )
25
+ }
26
+
27
+ export default RLSLabel