@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
@@ -9,6 +9,7 @@ import {
9
9
  type Component,
10
10
  type JSX
11
11
  } from "solid-js"
12
+ import { Portal } from "solid-js/web"
12
13
  import type { DropdownMenuProps, DropdownMenuItem } from "./dropdown-menu"
13
14
  import { dropdownMenuTheme } from "./dropdown-menu.theme"
14
15
  import RLSIcon from "../icon/RLSIcon"
@@ -35,16 +36,52 @@ const RLSDropdownMenu: Component<RLSDropdownMenuProps> = (allProps) => {
35
36
  ])
36
37
 
37
38
  const [isOpen, setIsOpen] = createSignal(false)
39
+ const [coords, setCoords] = createSignal<{ top: number; left?: number; right?: number }>({
40
+ top: 0
41
+ })
38
42
  let menuContainer: HTMLDivElement | undefined
43
+ let menuContentRef: HTMLDivElement | undefined
44
+ let triggerBtn: HTMLButtonElement | undefined
45
+
46
+ const updatePosition = () => {
47
+ if (!triggerBtn) return
48
+ const rect = triggerBtn.getBoundingClientRect()
49
+ const align = props.content?.align || "start"
50
+ const top = rect.bottom + 4
51
+ if (align === "end") {
52
+ const right = window.innerWidth - rect.right
53
+ setCoords({ top, right })
54
+ } else if (align === "center") {
55
+ const left = rect.left + rect.width / 2
56
+ setCoords({ top, left })
57
+ } else {
58
+ setCoords({ top, left: rect.left })
59
+ }
60
+ }
39
61
 
40
62
  onMount(() => {
41
63
  const handleOutsideClick = (e: MouseEvent) => {
42
- if (isOpen() && menuContainer && !menuContainer.contains(e.target as Node)) {
64
+ const target = e.target as Node
65
+ if (
66
+ isOpen() &&
67
+ menuContainer &&
68
+ !menuContainer.contains(target) &&
69
+ (!menuContentRef || !menuContentRef.contains(target))
70
+ ) {
43
71
  setIsOpen(false)
44
72
  }
45
73
  }
74
+ const handleScroll = () => {
75
+ if (isOpen()) updatePosition()
76
+ }
46
77
  document.addEventListener("click", handleOutsideClick)
47
- onCleanup(() => document.removeEventListener("click", handleOutsideClick))
78
+ window.addEventListener("scroll", handleScroll, true)
79
+ window.addEventListener("resize", handleScroll)
80
+ onCleanup(() => {
81
+ document.removeEventListener("click", handleOutsideClick)
82
+ window.removeEventListener("scroll", handleScroll, true)
83
+ window.removeEventListener("resize", handleScroll)
84
+ })
48
85
  })
49
86
 
50
87
  const resolvedClasses = createMemo(() =>
@@ -63,13 +100,6 @@ const RLSDropdownMenu: Component<RLSDropdownMenuProps> = (allProps) => {
63
100
  return [props.items as DropdownMenuItem[]]
64
101
  })
65
102
 
66
- const alignClass = () => {
67
- const align = props.content?.align || "start"
68
- if (align === "end") return "right-0"
69
- if (align === "center") return "left-1/2 -translate-x-1/2"
70
- return "left-0"
71
- }
72
-
73
103
  return (
74
104
  <div
75
105
  ref={(el) => (menuContainer = el)}
@@ -78,11 +108,14 @@ const RLSDropdownMenu: Component<RLSDropdownMenuProps> = (allProps) => {
78
108
  {...rest}
79
109
  >
80
110
  <button
111
+ ref={(el) => (triggerBtn = el)}
81
112
  type="button"
82
113
  disabled={props.disabled}
83
114
  onClick={(e) => {
84
115
  e.stopPropagation()
85
- setIsOpen(!isOpen())
116
+ const next = !isOpen()
117
+ if (next) updatePosition()
118
+ setIsOpen(next)
86
119
  }}
87
120
  class={resolvedClasses().trigger}
88
121
  data-slot="trigger"
@@ -101,39 +134,137 @@ const RLSDropdownMenu: Component<RLSDropdownMenuProps> = (allProps) => {
101
134
  </button>
102
135
 
103
136
  <Show when={isOpen()}>
104
- <div
105
- class={`${resolvedClasses().content} ${alignClass()}`}
106
- data-slot="content"
107
- role="menu"
108
- >
109
- {props.arrow && <div class={resolvedClasses().arrow} />}
110
- <div class={resolvedClasses().viewport}>
111
- <For each={itemGroups()}>
112
- {(group, groupIdx) => (
113
- <div class={resolvedClasses().group}>
114
- {groupIdx() > 0 && <div class={resolvedClasses().separator} />}
115
- <For each={group}>
116
- {(item) => {
117
- if (item.type === "separator") {
118
- return <div class={resolvedClasses().separator} />
119
- }
120
- if (item.type === "label") {
121
- return <div class={resolvedClasses().label}>{item.label}</div>
122
- }
123
-
124
- const itemColor = () =>
125
- item.color === "error"
126
- ? "text-destructive hover:bg-destructive/10"
127
- : item.color === "primary"
128
- ? "text-primary hover:bg-primary/10"
129
- : ""
130
-
131
- if (item.to) {
137
+ <Portal>
138
+ <div
139
+ ref={(el) => (menuContentRef = el)}
140
+ class={resolvedClasses().content}
141
+ style={{
142
+ "position": "fixed",
143
+ "z-index": "99999",
144
+ "top": `${coords().top}px`,
145
+ ...(coords().right !== undefined
146
+ ? { right: `${coords().right}px`, left: "auto" }
147
+ : {}),
148
+ ...(coords().left !== undefined ? { left: `${coords().left}px` } : {})
149
+ }}
150
+ data-slot="content"
151
+ role="menu"
152
+ >
153
+ {props.arrow && <div class={resolvedClasses().arrow} />}
154
+ <div class={resolvedClasses().viewport}>
155
+ <For each={itemGroups()}>
156
+ {(group, groupIdx) => (
157
+ <div class={resolvedClasses().group}>
158
+ {groupIdx() > 0 && <div class={resolvedClasses().separator} />}
159
+ <For each={group}>
160
+ {(item) => {
161
+ if (item.type === "separator") {
162
+ return <div class={resolvedClasses().separator} />
163
+ }
164
+ if (item.type === "label") {
165
+ return <div class={resolvedClasses().label}>{item.label}</div>
166
+ }
167
+
168
+ const itemColor = () =>
169
+ item.color === "error"
170
+ ? "text-destructive hover:bg-destructive/10"
171
+ : item.color === "primary"
172
+ ? "text-primary hover:bg-primary/10"
173
+ : ""
174
+
175
+ const renderLeadingContent = () => {
176
+ if (item.avatar) {
177
+ return (
178
+ <img
179
+ src={item.avatar.src}
180
+ alt={item.avatar.alt || item.label || ""}
181
+ class={resolvedClasses().itemLeadingAvatar}
182
+ />
183
+ )
184
+ }
185
+ if (item.icon) {
186
+ return (
187
+ <RLSIcon
188
+ name={item.icon}
189
+ size="sm"
190
+ class={resolvedClasses().itemLeadingIcon}
191
+ />
192
+ )
193
+ }
194
+ return null
195
+ }
196
+
197
+ const renderTrailingContent = () => {
198
+ if (!item.shortcut && (!item.kbds || item.kbds.length === 0)) return null
199
+ return (
200
+ <span class={resolvedClasses().itemTrailing}>
201
+ {item.shortcut && (
202
+ <span class={resolvedClasses().shortcut}>{item.shortcut}</span>
203
+ )}
204
+ {item.kbds && (
205
+ <For each={item.kbds}>
206
+ {(kbd) => (
207
+ <kbd class={resolvedClasses().itemTrailingKbds}>{kbd}</kbd>
208
+ )}
209
+ </For>
210
+ )}
211
+ </span>
212
+ )
213
+ }
214
+
215
+ if (item.to) {
216
+ return (
217
+ <a
218
+ href={item.to}
219
+ target={item.target}
220
+ class={`${resolvedClasses().item} ${itemColor()} ${item.class || ""}`}
221
+ data-slot="item"
222
+ role="menuitem"
223
+ onClick={(e) => {
224
+ setIsOpen(false)
225
+ item.onSelect?.(e)
226
+ }}
227
+ >
228
+ {renderLeadingContent()}
229
+ <span class={resolvedClasses().itemLabel}>{item.label}</span>
230
+ {renderTrailingContent()}
231
+ </a>
232
+ )
233
+ }
234
+
235
+ if (item.type === "checkbox") {
236
+ const isChecked = () => !!item.checked
237
+ return (
238
+ <button
239
+ type="button"
240
+ disabled={item.disabled}
241
+ class={`${resolvedClasses().item} ${itemColor()} ${item.class || ""}`}
242
+ data-slot="item"
243
+ role="menuitemcheckbox"
244
+ aria-checked={isChecked()}
245
+ onClick={(e) => {
246
+ const next = !isChecked()
247
+ item.onUpdateChecked?.(next)
248
+ item.onSelect?.(e)
249
+ }}
250
+ >
251
+ <span class="shrink-0 size-4 flex items-center justify-center border border-default rounded bg-default">
252
+ <Show when={isChecked()}>
253
+ <RLSIcon name="check" size="xs" class="text-primary" />
254
+ </Show>
255
+ </span>
256
+ {renderLeadingContent()}
257
+ <span class={resolvedClasses().itemLabel}>{item.label}</span>
258
+ {renderTrailingContent()}
259
+ </button>
260
+ )
261
+ }
262
+
132
263
  return (
133
- <a
134
- href={item.to}
135
- target={item.target}
136
- class={`${resolvedClasses().item} ${itemColor()} ${item.class || ""}`}
264
+ <button
265
+ type="button"
266
+ disabled={item.disabled}
267
+ class={`${resolvedClasses().item} ${itemColor()} ${item.class || ""}`}
137
268
  data-slot="item"
138
269
  role="menuitem"
139
270
  onClick={(e) => {
@@ -141,53 +272,19 @@ const RLSDropdownMenu: Component<RLSDropdownMenuProps> = (allProps) => {
141
272
  item.onSelect?.(e)
142
273
  }}
143
274
  >
144
- {item.icon && (
145
- <RLSIcon
146
- name={item.icon}
147
- size="sm"
148
- class={resolvedClasses().itemLeadingIcon}
149
- />
150
- )}
275
+ {renderLeadingContent()}
151
276
  <span class={resolvedClasses().itemLabel}>{item.label}</span>
152
- {item.shortcut && (
153
- <span class={resolvedClasses().shortcut}>{item.shortcut}</span>
154
- )}
155
- </a>
277
+ {renderTrailingContent()}
278
+ </button>
156
279
  )
157
- }
158
-
159
- return (
160
- <button
161
- type="button"
162
- disabled={item.disabled}
163
- class={`${resolvedClasses().item} ${itemColor()} ${item.class || ""}`}
164
- data-slot="item"
165
- role="menuitem"
166
- onClick={(e) => {
167
- setIsOpen(false)
168
- item.onSelect?.(e)
169
- }}
170
- >
171
- {item.icon && (
172
- <RLSIcon
173
- name={item.icon}
174
- size="sm"
175
- class={resolvedClasses().itemLeadingIcon}
176
- />
177
- )}
178
- <span class={resolvedClasses().itemLabel}>{item.label}</span>
179
- {item.shortcut && (
180
- <span class={resolvedClasses().shortcut}>{item.shortcut}</span>
181
- )}
182
- </button>
183
- )
184
- }}
185
- </For>
186
- </div>
187
- )}
188
- </For>
280
+ }}
281
+ </For>
282
+ </div>
283
+ )}
284
+ </For>
285
+ </div>
189
286
  </div>
190
- </div>
287
+ </Portal>
191
288
  </Show>
192
289
  </div>
193
290
  )
@@ -0,0 +1,26 @@
1
+ import { createMemo, splitProps, type Component, type JSX } from "solid-js"
2
+ import type { EditorProps } from "./editor"
3
+ import { editorTheme } from "./editor.theme"
4
+
5
+ export interface RLSEditorProps extends EditorProps {
6
+ children?: JSX.Element
7
+ }
8
+
9
+ const RLSEditor: Component<RLSEditorProps> = (allProps) => {
10
+ const [props, rest] = splitProps(allProps, ["ui", "class", "children"])
11
+
12
+ const resolvedClasses = createMemo(() =>
13
+ editorTheme({
14
+ ui: props.ui,
15
+ class: props.class
16
+ })
17
+ )
18
+
19
+ return (
20
+ <div class={resolvedClasses().root} data-slot="root" {...rest}>
21
+ {props.children}
22
+ </div>
23
+ )
24
+ }
25
+
26
+ export default RLSEditor
@@ -0,0 +1,132 @@
1
+ import { createMemo, splitProps, For, type Component, type JSX } from "solid-js"
2
+ import type { EmptyProps } from "./empty"
3
+ import { emptyTheme } from "./empty.theme"
4
+ import RLSButton from "../button/RLSButton"
5
+ import RLSAvatar from "../avatar/RLSAvatar"
6
+ import RLSIcon from "../icon/RLSIcon"
7
+
8
+ export interface RLSEmptyProps extends EmptyProps {
9
+ children?: JSX.Element
10
+ headerSlot?: JSX.Element
11
+ leadingSlot?: JSX.Element
12
+ titleSlot?: JSX.Element
13
+ descriptionSlot?: JSX.Element
14
+ bodySlot?: JSX.Element
15
+ actionsSlot?: JSX.Element
16
+ footerSlot?: JSX.Element
17
+ }
18
+
19
+ const RLSEmpty: Component<RLSEmptyProps> = (allProps) => {
20
+ const [props, rest] = splitProps(allProps, [
21
+ "icon",
22
+ "avatar",
23
+ "loading",
24
+ "loadingIcon",
25
+ "title",
26
+ "description",
27
+ "actions",
28
+ "variant",
29
+ "size",
30
+ "as",
31
+ "ui",
32
+ "class",
33
+ "children",
34
+ "headerSlot",
35
+ "leadingSlot",
36
+ "titleSlot",
37
+ "descriptionSlot",
38
+ "bodySlot",
39
+ "actionsSlot",
40
+ "footerSlot"
41
+ ])
42
+
43
+ const activeIcon = props.loading ? (props.loadingIcon ?? "i-lucide-loader-circle") : props.icon
44
+ const actionList = props.actions ?? []
45
+
46
+ const classes = createMemo(() =>
47
+ emptyTheme({
48
+ variant: props.variant ?? "outline",
49
+ size: props.size ?? "md",
50
+ loading: props.loading ?? false,
51
+ ui: props.ui,
52
+ class: props.class
53
+ })
54
+ )
55
+
56
+ return (
57
+ <div class={classes()["root"]} data-slot="root" {...rest}>
58
+ {props.headerSlot !== undefined ? (
59
+ props.headerSlot
60
+ ) : (
61
+ <div class={classes()["header"]} data-slot="header">
62
+ {props.leadingSlot !== undefined ? (
63
+ props.leadingSlot
64
+ ) : activeIcon ? (
65
+ <div class={classes()["avatar"]} data-slot="avatar">
66
+ <RLSIcon
67
+ name={activeIcon}
68
+ class={`size-full ${props.loading ? "animate-spin" : ""}`}
69
+ aria-hidden="true"
70
+ />
71
+ </div>
72
+ ) : props.avatar ? (
73
+ <div class={classes()["avatar"]} data-slot="avatar">
74
+ <RLSAvatar {...props.avatar} />
75
+ </div>
76
+ ) : null}
77
+
78
+ {(props.title || props.titleSlot !== undefined) && (
79
+ <div class={classes()["title"]} data-slot="title">
80
+ {props.titleSlot !== undefined ? props.titleSlot : props.title}
81
+ </div>
82
+ )}
83
+
84
+ {(props.description || props.descriptionSlot !== undefined) && (
85
+ <div class={classes()["description"]} data-slot="description">
86
+ {props.descriptionSlot !== undefined ? props.descriptionSlot : props.description}
87
+ </div>
88
+ )}
89
+ </div>
90
+ )}
91
+
92
+ {(props.bodySlot !== undefined || props.children !== undefined) && (
93
+ <div class={classes()["body"]} data-slot="body">
94
+ {props.bodySlot !== undefined ? props.bodySlot : props.children}
95
+ </div>
96
+ )}
97
+
98
+ {((props.actions?.length ?? 0) > 0 || props.actionsSlot !== undefined) && (
99
+ <div class={classes()["actions"]} data-slot="actions">
100
+ {props.actionsSlot !== undefined ? (
101
+ props.actionsSlot
102
+ ) : (
103
+ <For each={actionList}>
104
+ {(action) => {
105
+ const { icon, label, color, variant, ...actionRest } = action
106
+ return (
107
+ <RLSButton
108
+ size={props.size === "xs" || props.size === "sm" ? "xs" : "sm"}
109
+ color={(color || "primary") as any}
110
+ variant={(variant || "solid") as any}
111
+ {...(icon ? { leadingIcon: icon } : {})}
112
+ {...actionRest}
113
+ >
114
+ {label}
115
+ </RLSButton>
116
+ )
117
+ }}
118
+ </For>
119
+ )}
120
+ </div>
121
+ )}
122
+
123
+ {props.footerSlot !== undefined && (
124
+ <div class={classes()["footer"]} data-slot="footer">
125
+ {props.footerSlot}
126
+ </div>
127
+ )}
128
+ </div>
129
+ )
130
+ }
131
+
132
+ export default RLSEmpty
@@ -0,0 +1,26 @@
1
+ import { createMemo, splitProps, type Component, type JSX } from "solid-js"
2
+ import type { ErrorProps } from "./error"
3
+ import { errorTheme } from "./error.theme"
4
+
5
+ export interface RLSErrorProps extends ErrorProps {
6
+ children?: JSX.Element
7
+ }
8
+
9
+ const RLSError: Component<RLSErrorProps> = (allProps) => {
10
+ const [props, rest] = splitProps(allProps, ["ui", "class", "children"])
11
+
12
+ const classes = createMemo(() =>
13
+ errorTheme({
14
+ ui: props.ui,
15
+ class: props.class
16
+ })
17
+ )
18
+
19
+ return (
20
+ <div class={classes()["root"]} data-slot="root" {...rest}>
21
+ {props.children}
22
+ </div>
23
+ )
24
+ }
25
+
26
+ export default RLSError
@@ -0,0 +1,46 @@
1
+ import { createMemo, splitProps, type Component, type JSX } from "solid-js"
2
+ import type { FieldGroupProps } from "./field-group"
3
+ import { fieldGroupTheme } from "./field-group.theme"
4
+
5
+ export interface RLSFieldGroupProps extends Omit<FieldGroupProps, "prepend" | "append"> {
6
+ prepend?: JSX.Element
7
+ append?: JSX.Element
8
+ children?: JSX.Element
9
+ }
10
+
11
+ const RLSFieldGroup: Component<RLSFieldGroupProps> = (allProps) => {
12
+ const [props, rest] = splitProps(allProps, [
13
+ "prepend",
14
+ "append",
15
+ "size",
16
+ "ui",
17
+ "class",
18
+ "children"
19
+ ])
20
+
21
+ const resolvedClasses = createMemo(() =>
22
+ fieldGroupTheme({
23
+ size: props.size ?? "md",
24
+ ui: props.ui,
25
+ class: props.class
26
+ })
27
+ )
28
+
29
+ return (
30
+ <div class={resolvedClasses().root} data-slot="root" {...rest}>
31
+ {props.prepend ? (
32
+ <div class={resolvedClasses().prepend} data-slot="prepend">
33
+ {props.prepend}
34
+ </div>
35
+ ) : null}
36
+ {props.children}
37
+ {props.append ? (
38
+ <div class={resolvedClasses().append} data-slot="append">
39
+ {props.append}
40
+ </div>
41
+ ) : null}
42
+ </div>
43
+ )
44
+ }
45
+
46
+ export default RLSFieldGroup
@@ -0,0 +1,26 @@
1
+ import { createMemo, splitProps, type Component, type JSX } from "solid-js"
2
+ import type { FieldsetProps } from "./fieldset"
3
+ import { fieldsetTheme } from "./fieldset.theme"
4
+
5
+ export interface RLSFieldsetProps extends FieldsetProps {
6
+ children?: JSX.Element
7
+ }
8
+
9
+ const RLSFieldset: Component<RLSFieldsetProps> = (allProps) => {
10
+ const [props, rest] = splitProps(allProps, ["ui", "class", "children"])
11
+
12
+ const resolvedClasses = createMemo(() =>
13
+ fieldsetTheme({
14
+ ui: props.ui,
15
+ class: props.class
16
+ })
17
+ )
18
+
19
+ return (
20
+ <div class={resolvedClasses().root} data-slot="root" {...rest}>
21
+ {props.children}
22
+ </div>
23
+ )
24
+ }
25
+
26
+ export default RLSFieldset