@rimelight/ui 0.0.46 → 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 (222) hide show
  1. package/dist/icons-DPnFQCts.d.mts +72 -0
  2. package/dist/icons.d.mts +1 -1
  3. package/dist/index.d.mts +5 -6
  4. package/dist/preset.d.mts +1 -1
  5. package/dist/preset.mjs +73 -1
  6. package/dist/resolver.d.mts +4 -5
  7. package/dist/resolver.mjs +2 -4
  8. package/dist/shortcuts.d.mts +10 -11
  9. package/dist/stores.d.mts +3 -4
  10. package/dist/{types-DqAgCNcm.d.mts → types-DWmKMcYC.d.mts} +1 -1
  11. package/dist/types.d.mts +1 -1
  12. package/package.json +8 -6
  13. package/src/components/3d-hover/RLS3dHover.tsx +21 -0
  14. package/src/components/accordion/RLSAccordion.tsx +112 -0
  15. package/src/components/app/RLSApp.tsx +21 -0
  16. package/src/components/aspect-ratio/RLSAspectRatio.tsx +30 -0
  17. package/src/components/audio/RLSAudio.tsx +27 -0
  18. package/src/components/avatar/RLSAvatar.tsx +142 -0
  19. package/src/components/avatar/avatar.ts +22 -21
  20. package/src/components/avatar-group/RLSAvatarGroup.tsx +163 -0
  21. package/src/components/badge/RLSBadge.tsx +1 -1
  22. package/src/components/badge/RLVBadge.vue +5 -3
  23. package/src/components/banner/RLABanner.astro +1 -1
  24. package/src/components/banner/RLSBanner.tsx +151 -0
  25. package/src/components/breadcrumb/RLSBreadcrumb.tsx +194 -0
  26. package/src/components/browser-mockup/RLSBrowserMockup.tsx +21 -0
  27. package/src/components/button/RLSButton.tsx +53 -38
  28. package/src/components/button/RLVButton.vue +44 -32
  29. package/src/components/calendar/RLSCalendar.tsx +26 -0
  30. package/src/components/callout/RLSCallout.tsx +151 -0
  31. package/src/components/card/RLSCard.tsx +4 -0
  32. package/src/components/card/RLVCard.vue +4 -0
  33. package/src/components/card/card.ts +10 -0
  34. package/src/components/carousel/RLACarousel.astro +14 -1
  35. package/src/components/carousel/RLSCarousel.tsx +260 -0
  36. package/src/components/chart/RLSChart.tsx +299 -0
  37. package/src/components/chat/RLSChat.tsx +27 -0
  38. package/src/components/chat-message/RLSChatMessage.tsx +27 -0
  39. package/src/components/chat-messages/RLSChatMessages.tsx +27 -0
  40. package/src/components/chat-palette/RLSChatPalette.tsx +27 -0
  41. package/src/components/chat-prompt/RLSChatPrompt.tsx +27 -0
  42. package/src/components/chat-prompt-submit/RLSChatPromptSubmit.tsx +27 -0
  43. package/src/components/chat-reasoning/RLSChatReasoning.tsx +27 -0
  44. package/src/components/chat-shimmer/RLSChatShimmer.tsx +27 -0
  45. package/src/components/chat-tool/RLSChatTool.tsx +27 -0
  46. package/src/components/checkbox/RLACheckbox.astro +1 -0
  47. package/src/components/checkbox/RLSCheckbox.tsx +1 -1
  48. package/src/components/checkbox/checkbox.theme.ts +2 -2
  49. package/src/components/chip/RLSChip.tsx +65 -0
  50. package/src/components/collapsible/RLSCollapsible.tsx +89 -0
  51. package/src/components/color-area/RLSColorArea.tsx +554 -0
  52. package/src/components/color-field/RLSColorField.tsx +236 -0
  53. package/src/components/color-picker/RLSColorPicker.tsx +26 -0
  54. package/src/components/color-slider/RLSColorSlider.tsx +373 -0
  55. package/src/components/command-palette/RLSCommandPalette.tsx +26 -0
  56. package/src/components/compare/RLSCompare.tsx +26 -0
  57. package/src/components/confirm/RLSConfirm.tsx +173 -0
  58. package/src/components/container/RLSContainer.tsx +24 -0
  59. package/src/components/context-menu/RLSContextMenu.tsx +26 -0
  60. package/src/components/copy-markdown/RLSCopyMarkdown.tsx +57 -0
  61. package/src/components/dashboard-group/RLSDashboardGroup.tsx +29 -0
  62. package/src/components/dashboard-navbar/RLSDashboardNavbar.tsx +116 -0
  63. package/src/components/dashboard-panel/RLSDashboardPanel.tsx +84 -0
  64. package/src/components/dashboard-resize-handle/RLSDashboardResizeHandle.tsx +35 -0
  65. package/src/components/dashboard-search/RLADashboardSearch.astro +1 -1
  66. package/src/components/dashboard-search/RLSDashboardSearch.tsx +125 -0
  67. package/src/components/dashboard-search-button/RLSDashboardSearchButton.tsx +82 -0
  68. package/src/components/dashboard-sidebar/RLADashboardSidebar.astro +4 -4
  69. package/src/components/dashboard-sidebar/RLSDashboardSidebar.tsx +184 -0
  70. package/src/components/dashboard-sidebar-collapse/RLSDashboardSidebarCollapse.tsx +46 -0
  71. package/src/components/dashboard-sidebar-toggle/RLSDashboardSidebarToggle.tsx +35 -0
  72. package/src/components/dashboard-toolbar/RLSDashboardToolbar.tsx +49 -0
  73. package/src/components/date/RLSDate.tsx +34 -0
  74. package/src/components/dock/RLSDock.tsx +26 -0
  75. package/src/components/drawer/RLSDrawer.tsx +177 -0
  76. package/src/components/dropdown-menu/RLADropdownMenu.astro +250 -241
  77. package/src/components/dropdown-menu/RLSDropdownMenu.tsx +183 -86
  78. package/src/components/editor/RLSEditor.tsx +26 -0
  79. package/src/components/empty/RLSEmpty.tsx +132 -0
  80. package/src/components/error/RLSError.tsx +26 -0
  81. package/src/components/field-group/RLSFieldGroup.tsx +46 -0
  82. package/src/components/fieldset/RLSFieldset.tsx +26 -0
  83. package/src/components/file-upload/RLAFileUpload.astro +1 -1
  84. package/src/components/file-upload/RLSFileUpload.tsx +163 -0
  85. package/src/components/floating-action/RLSFloatingAction.tsx +26 -0
  86. package/src/components/footer/RLSFooter.tsx +56 -0
  87. package/src/components/form/RLSForm.tsx +34 -0
  88. package/src/components/gallery/RLSGallery.tsx +21 -0
  89. package/src/components/gamepad/RLSGamepad.tsx +269 -0
  90. package/src/components/grid/RLSGrid.tsx +29 -0
  91. package/src/components/head/RLAHead.astro +9 -0
  92. package/src/components/head/RLSHead.tsx +42 -0
  93. package/src/components/head/UIHead.astro +3 -0
  94. package/src/components/header/HeaderLayer.astro +1 -1
  95. package/src/components/header/RLSHeader.tsx +87 -0
  96. package/src/components/hover-card/RLSHoverCard.tsx +72 -0
  97. package/src/components/icon/RLSIcon.tsx +3 -1
  98. package/src/components/image/RLAImage.astro +447 -138
  99. package/src/components/image/RLSImage.tsx +545 -0
  100. package/src/components/image/image.theme.ts +19 -3
  101. package/src/components/image/image.ts +31 -1
  102. package/src/components/input/RLAInput.astro +62 -51
  103. package/src/components/input/RLSInput.tsx +1 -1
  104. package/src/components/input-date/RLSInputDate.tsx +92 -0
  105. package/src/components/input-menu/RLAInputMenu.astro +3 -3
  106. package/src/components/input-menu/RLSInputMenu.tsx +199 -0
  107. package/src/components/input-number/RLSInputNumber.tsx +184 -0
  108. package/src/components/input-pin/RLSInputPin.tsx +185 -0
  109. package/src/components/input-rating/RLAInputRating.astro +8 -8
  110. package/src/components/input-rating/RLSInputRating.tsx +198 -0
  111. package/src/components/input-rating/input-rating.ts +4 -0
  112. package/src/components/input-tags/RLSInputTags.tsx +94 -0
  113. package/src/components/input-time/RLSInputTime.tsx +92 -0
  114. package/src/components/kbd/RLSKbd.tsx +37 -0
  115. package/src/components/keyboard/RLSKeyboard.tsx +476 -0
  116. package/src/components/knob/RLSKnob.tsx +27 -0
  117. package/src/components/label/RLSLabel.tsx +27 -0
  118. package/src/components/layout-grid/RLALayoutGrid.astro +29 -29
  119. package/src/components/layout-grid/RLSLayoutGrid.tsx +402 -0
  120. package/src/components/layout-grid/layout-grid.ts +25 -1
  121. package/src/components/link/RLALink.astro +5 -5
  122. package/src/components/link/RLSLink.tsx +6 -5
  123. package/src/components/link/link.ts +21 -12
  124. package/src/components/link-group/RLSLinkGroup.tsx +76 -0
  125. package/src/components/listbox/RLSListbox.tsx +27 -0
  126. package/src/components/locale-selector/RLALocaleSelector.astro +110 -102
  127. package/src/components/locale-selector/RLSLocaleSelector.tsx +178 -0
  128. package/src/components/locale-selector/locale-selector.ts +2 -7
  129. package/src/components/logo/RLALogo.astro +153 -102
  130. package/src/components/logo/RLSLogo.tsx +129 -0
  131. package/src/components/main/RLSMain.tsx +40 -0
  132. package/src/components/marquee/RLSMarquee.tsx +80 -0
  133. package/src/components/meter/RLSMeter.tsx +27 -0
  134. package/src/components/modal/RLAModal.astro +1 -1
  135. package/src/components/modal/RLSModal.tsx +109 -72
  136. package/src/components/navigation-menu/RLANavigationMenu.astro +6 -6
  137. package/src/components/navigation-menu/RLSNavigationMenu.tsx +228 -0
  138. package/src/components/navigation-menu/navigation-menu.ts +2 -2
  139. package/src/components/package-managers/RLSPackageManagers.tsx +204 -0
  140. package/src/components/page/RLSPage.tsx +21 -0
  141. package/src/components/page-aside/RLSPageAside.tsx +21 -0
  142. package/src/components/page-body/RLSPageBody.tsx +21 -0
  143. package/src/components/page-header/RLSPageHeader.tsx +21 -0
  144. package/src/components/page-section/RLSPageSection.tsx +201 -0
  145. package/src/components/pagination/RLSPagination.tsx +114 -0
  146. package/src/components/password/RLSPassword.tsx +27 -0
  147. package/src/components/phone-mockup/RLSPhoneMockup.tsx +27 -0
  148. package/src/components/placeholder/RLSPlaceholder.tsx +47 -0
  149. package/src/components/popover/RLAPopover.astro +2 -2
  150. package/src/components/popover/RLSPopover.tsx +124 -0
  151. package/src/components/post/RLSPost.tsx +134 -0
  152. package/src/components/pricing-plan/RLSPricingPlan.tsx +26 -0
  153. package/src/components/pricing-table/RLSPricingTable.tsx +26 -0
  154. package/src/components/progress/RLSProgress.tsx +53 -0
  155. package/src/components/prose/RLSProse.tsx +26 -0
  156. package/src/components/qr-code/RLSQrCode.tsx +26 -0
  157. package/src/components/quote/RLAQuote.astro +10 -6
  158. package/src/components/quote/RLSQuote.tsx +37 -0
  159. package/src/components/quote/quote.theme.ts +5 -2
  160. package/src/components/radio-group/RLSRadioGroup.tsx +37 -0
  161. package/src/components/rating/RLSRating.tsx +27 -0
  162. package/src/components/scroll-area/RLAScrollArea.astro +1 -1
  163. package/src/components/scroll-area/RLSScrollArea.tsx +210 -0
  164. package/src/components/scroll-to-top/RLAScrollToTop.astro +5 -4
  165. package/src/components/scroll-to-top/RLSScrollToTop.tsx +145 -0
  166. package/src/components/search/RLASearch.astro +6 -6
  167. package/src/components/search/RLSSearch.tsx +237 -0
  168. package/src/components/select/RLASelect.astro +67 -4
  169. package/src/components/select/RLSSelect.tsx +107 -39
  170. package/src/components/select/RLVSelect.vue +50 -1
  171. package/src/components/select/select.theme.ts +30 -10
  172. package/src/components/select/select.ts +20 -1
  173. package/src/components/separator/RLSSeparator.tsx +92 -0
  174. package/src/components/share/RLSShare.tsx +66 -0
  175. package/src/components/shortcuts/RLAShortcuts.astro +2 -2
  176. package/src/components/shortcuts/RLSShortcuts.tsx +393 -0
  177. package/src/components/sidebar/RLASidebar.astro +1 -1
  178. package/src/components/sidebar/RLSSidebar.tsx +271 -0
  179. package/src/components/skeleton/RLSSkeleton.tsx +21 -0
  180. package/src/components/slideover/RLASlideover.astro +1 -1
  181. package/src/components/slideover/RLSSlideover.tsx +159 -0
  182. package/src/components/slider/RLSSlider.tsx +112 -0
  183. package/src/components/speed-dial/RLSSpeedDial.tsx +27 -0
  184. package/src/components/spinner/RLSSpinner.tsx +22 -0
  185. package/src/components/splitter/RLASplitter.astro +1 -1
  186. package/src/components/splitter/RLSSplitter.tsx +178 -0
  187. package/src/components/spoiler/RLSSpoiler.tsx +26 -0
  188. package/src/components/stepper/RLAStepper.astro +9 -9
  189. package/src/components/stepper/RLSStepper.tsx +205 -0
  190. package/src/components/steps/RLSSteps.tsx +108 -0
  191. package/src/components/sticky-surface/RLSStickySurface.tsx +63 -0
  192. package/src/components/surround/RLSSurround.tsx +57 -0
  193. package/src/components/switch/RLSSwitch.tsx +56 -0
  194. package/src/components/table/RLATable.astro +1044 -579
  195. package/src/components/table/RLSTable.tsx +893 -0
  196. package/src/components/table/table.theme.ts +47 -16
  197. package/src/components/table/table.ts +104 -66
  198. package/src/components/table-of-contents/RLSTableOfContents.tsx +196 -0
  199. package/src/components/tabs/RLATabs.astro +8 -8
  200. package/src/components/tabs/RLSTabs.tsx +298 -0
  201. package/src/components/textarea/RLATextarea.astro +1 -0
  202. package/src/components/textarea/RLSTextarea.tsx +3 -1
  203. package/src/components/theme-selector/RLAThemeSelector.astro +85 -56
  204. package/src/components/theme-selector/RLSThemeSelector.tsx +131 -0
  205. package/src/components/theme-selector/theme-selector.theme.ts +5 -7
  206. package/src/components/theme-selector/theme-selector.ts +11 -1
  207. package/src/components/timeline/RLSTimeline.tsx +171 -0
  208. package/src/components/toast/RLAToast.astro +2 -2
  209. package/src/components/toast/RLSToast.tsx +179 -0
  210. package/src/components/toaster/RLSToaster.tsx +82 -0
  211. package/src/components/tooltip/RLSTooltip.tsx +48 -0
  212. package/src/components/tour/RLSTour.tsx +26 -0
  213. package/src/components/tree/RLSTree.tsx +26 -0
  214. package/src/components/user/RLSUser.tsx +26 -0
  215. package/src/components/video/RLAVideo.astro +4 -1
  216. package/src/components/video/RLSVideo.tsx +158 -0
  217. package/src/components/watermark/RLSWatermark.tsx +27 -0
  218. package/src/components/window-mockup/RLSWindowMockup.tsx +27 -0
  219. package/src/preset.ts +73 -1
  220. package/src/resolver.ts +6 -1
  221. package/src/virtual.d.ts +6 -0
  222. package/dist/icons--RzV1RTU.d.mts +0 -72
@@ -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
@@ -136,7 +136,7 @@ const classes = layoutGridTheme(Astro.props)
136
136
  this.updateGrid()
137
137
 
138
138
  // Set up shortcuts using the library system
139
- const shortcutKey = this.dataset.shortcut || 'meta_shift_g'
139
+ const shortcutKey = this.dataset["shortcut"] || 'meta_shift_g'
140
140
  this.shortcutsCleanup = defineShortcuts({
141
141
  [shortcutKey]: {
142
142
  handler: (e) => {
@@ -160,10 +160,10 @@ const classes = layoutGridTheme(Astro.props)
160
160
 
161
161
  private handleResize() {
162
162
  const width = document.documentElement.clientWidth
163
- const smBreakpoint = parseInt(this.dataset.smBreakpoint || '640')
164
- const mdBreakpoint = parseInt(this.dataset.mdBreakpoint || '768')
165
- const lgBreakpoint = parseInt(this.dataset.lgBreakpoint || '1024')
166
- const xlBreakpoint = parseInt(this.dataset.xlBreakpoint || '1280')
163
+ const smBreakpoint = parseInt(this.dataset["smBreakpoint"] || '640')
164
+ const mdBreakpoint = parseInt(this.dataset["mdBreakpoint"] || '768')
165
+ const lgBreakpoint = parseInt(this.dataset["lgBreakpoint"] || '1024')
166
+ const xlBreakpoint = parseInt(this.dataset["xlBreakpoint"] || '1280')
167
167
 
168
168
  let newBreakpoint: 'base' | 'sm' | 'md' | 'lg' | 'xl' = 'base'
169
169
 
@@ -185,57 +185,57 @@ const classes = layoutGridTheme(Astro.props)
185
185
  if (!this.columnsContainer) return
186
186
 
187
187
  const width = document.documentElement.clientWidth
188
- const smBreakpoint = parseInt(this.dataset.smBreakpoint || '640')
189
- const mdBreakpoint = parseInt(this.dataset.mdBreakpoint || '768')
190
- const lgBreakpoint = parseInt(this.dataset.lgBreakpoint || '1024')
191
- const xlBreakpoint = parseInt(this.dataset.xlBreakpoint || '1280')
188
+ const smBreakpoint = parseInt(this.dataset["smBreakpoint"] || '640')
189
+ const mdBreakpoint = parseInt(this.dataset["mdBreakpoint"] || '768')
190
+ const lgBreakpoint = parseInt(this.dataset["lgBreakpoint"] || '1024')
191
+ const xlBreakpoint = parseInt(this.dataset["xlBreakpoint"] || '1280')
192
192
 
193
193
  let breakpointIndex = 0
194
- let colCount = parseInt(this.dataset.cols || '4')
194
+ let colCount = parseInt(this.dataset["cols"] || '4')
195
195
  let breakpointThreshold = 0
196
196
 
197
197
  switch (this.currentBreakpoint) {
198
198
  case 'xl':
199
199
  breakpointIndex = 4
200
- colCount = parseInt(this.dataset.xlCols || '12')
200
+ colCount = parseInt(this.dataset["xlCols"] || '12')
201
201
  breakpointThreshold = xlBreakpoint
202
202
  break
203
203
  case 'lg':
204
204
  breakpointIndex = 3
205
- colCount = parseInt(this.dataset.lgCols || '12')
205
+ colCount = parseInt(this.dataset["lgCols"] || '12')
206
206
  breakpointThreshold = lgBreakpoint
207
207
  break
208
208
  case 'md':
209
209
  breakpointIndex = 2
210
- colCount = parseInt(this.dataset.mdCols || '8')
210
+ colCount = parseInt(this.dataset["mdCols"] || '8')
211
211
  breakpointThreshold = mdBreakpoint
212
212
  break
213
213
  case 'sm':
214
214
  breakpointIndex = 1
215
- colCount = parseInt(this.dataset.smCols || '4')
215
+ colCount = parseInt(this.dataset["smCols"] || '4')
216
216
  breakpointThreshold = smBreakpoint
217
217
  break
218
218
  default:
219
219
  breakpointIndex = 0
220
- colCount = parseInt(this.dataset.cols || '4')
220
+ colCount = parseInt(this.dataset["cols"] || '4')
221
221
  breakpointThreshold = 0
222
222
  break
223
223
  }
224
224
 
225
- const gutterArray = JSON.parse(this.dataset.gutter || '[1,1,1,1,1]')
226
- const marginArray = JSON.parse(this.dataset.margin || '[1,1,1,1,1]')
225
+ const gutterArray = JSON.parse(this.dataset["gutter"] || '[1,1,1,1,1]')
226
+ const marginArray = JSON.parse(this.dataset["margin"] || '[1,1,1,1,1]')
227
227
 
228
228
  const gutterValue = gutterArray[breakpointIndex] ?? gutterArray[gutterArray.length - 1]
229
229
  const marginValue = marginArray[breakpointIndex] ?? marginArray[marginArray.length - 1]
230
230
 
231
- const gridColor = this.dataset.gridColor || '#ff0000'
232
- const gridOpacity = parseFloat(this.dataset.gridOpacity || '0.1')
233
- const showBackground = this.dataset.showBackground === 'true'
231
+ const gridColor = this.dataset["gridColor"] || '#ff0000'
232
+ const gridOpacity = parseFloat(this.dataset["gridOpacity"] || '0.1')
233
+ const showBackground = this.dataset["showBackground"] === 'true'
234
234
 
235
- const showFullWidth = this.dataset.showFullWidth !== 'false'
236
- const fullWidthColor = this.dataset.fullWidthColor || '#3b82f6'
237
- const fullWidthOpacity = parseFloat(this.dataset.fullWidthOpacity || '0.05')
238
- const showFullWidthBackground = this.dataset.showFullWidthBackground === 'true'
235
+ const showFullWidth = this.dataset["showFullWidth"] !== 'false'
236
+ const fullWidthColor = this.dataset["fullWidthColor"] || '#3b82f6'
237
+ const fullWidthOpacity = parseFloat(this.dataset["fullWidthOpacity"] || '0.05')
238
+ const showFullWidthBackground = this.dataset["showFullWidthBackground"] === 'true'
239
239
 
240
240
  // Convert rem spacings to pixels dynamically based on root font size
241
241
  const rootFontSize = parseFloat(getComputedStyle(document.documentElement).fontSize) || 16
@@ -243,20 +243,20 @@ const classes = layoutGridTheme(Astro.props)
243
243
  const gutterPx = gutterValue * rootFontSize
244
244
 
245
245
  // Calculate max width boundaries
246
- const maxWidthVal = this.dataset.maxWidth || '1440px'
246
+ const maxWidthVal = this.dataset["maxWidth"] || '1440px'
247
247
  let maxWidthPx = width
248
248
  if (!maxWidthVal.includes('vw')) {
249
249
  maxWidthPx = parseInt(maxWidthVal)
250
250
  }
251
251
 
252
- const innerMaxWidthVal = this.dataset.innerMaxWidth || '768px'
252
+ const innerMaxWidthVal = this.dataset["innerMaxWidth"] || '768px'
253
253
  let innerMaxWidthPx = width
254
254
  if (!innerMaxWidthVal.includes('vw')) {
255
255
  innerMaxWidthPx = parseInt(innerMaxWidthVal)
256
256
  }
257
- const innerGridColor = this.dataset.innerColor || '#10b981'
258
- const innerGridOpacity = parseFloat(this.dataset.innerOpacity || '0.1')
259
- const showInnerBackground = this.dataset.showInnerBackground === 'true'
257
+ const innerGridColor = this.dataset["innerColor"] || '#10b981'
258
+ const innerGridOpacity = parseFloat(this.dataset["innerOpacity"] || '0.1')
259
+ const showInnerBackground = this.dataset["showInnerBackground"] === 'true'
260
260
 
261
261
  // Calculate grid properties based on container width or screen width
262
262
  const activeWidth = width > maxWidthPx ? maxWidthPx : width