@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,159 @@
1
+ import {
2
+ createEffect,
3
+ createMemo,
4
+ createSignal,
5
+ onCleanup,
6
+ onMount,
7
+ Show,
8
+ splitProps,
9
+ type Component,
10
+ type JSX
11
+ } from "solid-js"
12
+ import type { SlideoverProps } from "./slideover"
13
+ import { slideoverTheme } from "./slideover.theme"
14
+ import RLSIcon from "../icon/RLSIcon"
15
+
16
+ export interface RLSSlideoverProps extends SlideoverProps {
17
+ children?: JSX.Element
18
+ trigger?: JSX.Element
19
+ triggerSlot?: JSX.Element
20
+ titleSlot?: JSX.Element
21
+ descriptionSlot?: JSX.Element
22
+ footer?: JSX.Element
23
+ footerSlot?: JSX.Element
24
+ defaultOpen?: boolean
25
+ onOpenChange?: (open: boolean) => void
26
+ }
27
+
28
+ const RLSSlideover: Component<RLSSlideoverProps> = (allProps) => {
29
+ const [props, rest] = splitProps(allProps, [
30
+ "side",
31
+ "open",
32
+ "defaultOpen",
33
+ "title",
34
+ "description",
35
+ "triggerLabel",
36
+ "unmountOnHide",
37
+ "ui",
38
+ "class",
39
+ "children",
40
+ "trigger",
41
+ "triggerSlot",
42
+ "titleSlot",
43
+ "descriptionSlot",
44
+ "footer",
45
+ "footerSlot",
46
+ "onOpenChange"
47
+ ])
48
+
49
+ const side = () => props.side ?? "left"
50
+ const unmountOnHide = () => props.unmountOnHide ?? true
51
+
52
+ const [isOpen, setIsOpen] = createSignal(props.open ?? props.defaultOpen ?? false)
53
+
54
+ createEffect(() => {
55
+ if (props.open !== undefined) {
56
+ setIsOpen(props.open)
57
+ }
58
+ })
59
+
60
+ const setOpenState = (open: boolean) => {
61
+ if (props.open === undefined) {
62
+ setIsOpen(open)
63
+ }
64
+ props.onOpenChange?.(open)
65
+ }
66
+
67
+ onMount(() => {
68
+ const onKeyDown = (e: KeyboardEvent) => {
69
+ if (e.key === "Escape" && isOpen()) {
70
+ setOpenState(false)
71
+ }
72
+ }
73
+ window.addEventListener("keydown", onKeyDown)
74
+ onCleanup(() => window.removeEventListener("keydown", onKeyDown))
75
+ })
76
+
77
+ const resolvedClasses = createMemo(() =>
78
+ slideoverTheme({
79
+ side: side(),
80
+ ui: props.ui,
81
+ class: props.class
82
+ })
83
+ )
84
+
85
+ const triggerContent = () => props.trigger ?? props.triggerSlot
86
+ const footerContent = () => props.footer ?? props.footerSlot
87
+
88
+ return (
89
+ <div class={resolvedClasses().root} data-slot="root" {...rest}>
90
+ {props.triggerLabel ? (
91
+ <button
92
+ type="button"
93
+ class={resolvedClasses().trigger}
94
+ data-slot="trigger"
95
+ onClick={() => setOpenState(true)}
96
+ >
97
+ {props.triggerLabel}
98
+ </button>
99
+ ) : triggerContent() ? (
100
+ <span onClick={() => setOpenState(true)}>{triggerContent()}</span>
101
+ ) : null}
102
+
103
+ <Show when={!unmountOnHide() || isOpen()}>
104
+ <Show when={isOpen()}>
105
+ <div
106
+ class={resolvedClasses().backdrop}
107
+ data-slot="backdrop"
108
+ onClick={() => setOpenState(false)}
109
+ />
110
+ </Show>
111
+
112
+ <div
113
+ class={resolvedClasses().content}
114
+ data-slot="content"
115
+ data-state={isOpen() ? "open" : "closed"}
116
+ style={{ display: isOpen() ? undefined : "none" }}
117
+ >
118
+ <button
119
+ class={resolvedClasses().closeButton}
120
+ data-slot="close-button"
121
+ type="button"
122
+ aria-label="Close slideover"
123
+ onClick={() => setOpenState(false)}
124
+ >
125
+ <RLSIcon name="i-rl-close" class="size-4" aria-hidden="true" />
126
+ </button>
127
+
128
+ <div class={resolvedClasses().header} data-slot="header">
129
+ {props.titleSlot !== undefined ? (
130
+ props.titleSlot
131
+ ) : props.title ? (
132
+ <h3 class={resolvedClasses().title} data-slot="title">
133
+ {props.title}
134
+ </h3>
135
+ ) : null}
136
+
137
+ {props.descriptionSlot !== undefined ? (
138
+ props.descriptionSlot
139
+ ) : props.description ? (
140
+ <p class={resolvedClasses().description} data-slot="description">
141
+ {props.description}
142
+ </p>
143
+ ) : null}
144
+ </div>
145
+
146
+ {props.children}
147
+
148
+ {footerContent() !== undefined && (
149
+ <div class={resolvedClasses().footer} data-slot="footer">
150
+ {footerContent()}
151
+ </div>
152
+ )}
153
+ </div>
154
+ </Show>
155
+ </div>
156
+ )
157
+ }
158
+
159
+ export default RLSSlideover
@@ -0,0 +1,112 @@
1
+ import {
2
+ createEffect,
3
+ createMemo,
4
+ createSignal,
5
+ splitProps,
6
+ type Component,
7
+ type JSX
8
+ } from "solid-js"
9
+ import type { SliderProps } from "./slider"
10
+ import { sliderTheme } from "./slider.theme"
11
+
12
+ export interface RLSSliderProps extends SliderProps {
13
+ children?: JSX.Element
14
+ defaultValue?: number
15
+ onChange?: (val: number) => void
16
+ }
17
+
18
+ const RLSSlider: Component<RLSSliderProps> = (allProps) => {
19
+ const [props, rest] = splitProps(allProps, [
20
+ "value",
21
+ "defaultValue",
22
+ "min",
23
+ "max",
24
+ "step",
25
+ "name",
26
+ "color",
27
+ "theme",
28
+ "ui",
29
+ "class",
30
+ "children",
31
+ "onChange"
32
+ ])
33
+
34
+ const min = () => props.min ?? 0
35
+ const max = () => props.max ?? 100
36
+ const step = () => props.step ?? 1
37
+
38
+ const [internalVal, setInternalVal] = createSignal(props.value ?? props.defaultValue ?? min())
39
+
40
+ createEffect(() => {
41
+ if (props.value !== undefined) {
42
+ setInternalVal(props.value)
43
+ }
44
+ })
45
+
46
+ const currentVal = () => (props.value !== undefined ? props.value : internalVal())
47
+
48
+ const percentage = createMemo(() => {
49
+ const v = currentVal()
50
+ const mn = min()
51
+ const mx = max()
52
+ return Math.min(100, Math.max(0, ((v - mn) / (mx - mn)) * 100))
53
+ })
54
+
55
+ const handleInput: JSX.EventHandler<HTMLInputElement, InputEvent> = (e) => {
56
+ const num = parseFloat(e.currentTarget.value)
57
+ if (!isNaN(num)) {
58
+ if (props.value === undefined) {
59
+ setInternalVal(num)
60
+ }
61
+ props.onChange?.(num)
62
+ }
63
+ }
64
+
65
+ const resolvedClasses = createMemo(() =>
66
+ sliderTheme({
67
+ color: props.color,
68
+ ui: props.ui,
69
+ class: props.class
70
+ })
71
+ )
72
+
73
+ return (
74
+ <div class={resolvedClasses().root} data-slot="slider-root" data-theme={props.theme} {...rest}>
75
+ <div class={resolvedClasses().track} data-slot="track">
76
+ <svg class="h-full w-full overflow-visible pointer-events-none">
77
+ <rect
78
+ class={`${resolvedClasses().range} h-full`}
79
+ width={`${percentage()}%`}
80
+ fill="currentColor"
81
+ rx="2"
82
+ />
83
+ </svg>
84
+ </div>
85
+
86
+ <input
87
+ type="range"
88
+ min={min()}
89
+ max={max()}
90
+ step={step()}
91
+ value={currentVal()}
92
+ name={props.name}
93
+ class="absolute inset-0 w-full h-full opacity-0 cursor-pointer z-10"
94
+ data-slot="input"
95
+ onInput={handleInput}
96
+ />
97
+
98
+ <svg class="absolute inset-0 h-full w-full overflow-visible pointer-events-none">
99
+ <circle
100
+ cx={`${percentage()}%`}
101
+ cy="50%"
102
+ r="8"
103
+ class={`${resolvedClasses().thumb} pointer-events-auto border-none`}
104
+ data-slot="thumb"
105
+ fill="currentColor"
106
+ />
107
+ </svg>
108
+ </div>
109
+ )
110
+ }
111
+
112
+ export default RLSSlider
@@ -0,0 +1,27 @@
1
+ import { createMemo, splitProps, type Component, type JSX } from "solid-js"
2
+ import type { SpeedDialProps } from "./speed-dial"
3
+ import { speedDialTheme } from "./speed-dial.theme"
4
+
5
+ export interface RLSSpeedDialProps extends SpeedDialProps {
6
+ children?: JSX.Element
7
+ }
8
+
9
+ const RLSSpeedDial: Component<RLSSpeedDialProps> = (allProps) => {
10
+ const [props, rest] = splitProps(allProps, ["ui", "class", "children"])
11
+
12
+ const resolvedClasses = createMemo(() =>
13
+ speedDialTheme({
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 RLSSpeedDial
@@ -0,0 +1,22 @@
1
+ import { createMemo, splitProps, type Component } from "solid-js"
2
+ import type { SpinnerProps } from "./spinner"
3
+ import { spinnerTheme } from "./spinner.theme"
4
+
5
+ export interface RLSSpinnerProps extends SpinnerProps {}
6
+
7
+ const RLSSpinner: Component<RLSSpinnerProps> = (allProps) => {
8
+ const [props, rest] = splitProps(allProps, ["size", "color", "theme", "ui", "class"])
9
+
10
+ const classes = createMemo(() =>
11
+ spinnerTheme({
12
+ size: props.size ?? "md",
13
+ color: props.color ?? "current",
14
+ ui: props.ui,
15
+ class: props.class
16
+ })
17
+ )
18
+
19
+ return <div class={classes()["root"]} data-slot="root" data-theme={props.theme} {...rest} />
20
+ }
21
+
22
+ export default RLSSpinner
@@ -0,0 +1,178 @@
1
+ import {
2
+ children,
3
+ createMemo,
4
+ createSignal,
5
+ For,
6
+ splitProps,
7
+ type Component,
8
+ type JSX
9
+ } from "solid-js"
10
+ import type { SplitterProps } from "./splitter"
11
+ import { splitterTheme } from "./splitter.theme"
12
+ import RLSIcon from "../icon/RLSIcon"
13
+
14
+ export interface RLSSplitterProps extends SplitterProps {
15
+ children?: JSX.Element
16
+ panels?: JSX.Element[]
17
+ }
18
+
19
+ interface DragState {
20
+ i: number
21
+ startPos: number
22
+ startA: number
23
+ startB: number
24
+ }
25
+
26
+ const RLSSplitter: Component<RLSSplitterProps> = (allProps) => {
27
+ const [props, rest] = splitProps(allProps, [
28
+ "direction",
29
+ "defaultSizes",
30
+ "ui",
31
+ "class",
32
+ "children",
33
+ "panels"
34
+ ])
35
+
36
+ const childContent = children(() => props.children)
37
+
38
+ const isHorizontal = () => (props.direction ?? "horizontal") === "horizontal"
39
+
40
+ const [sizes, setSizes] = createSignal<number[]>(
41
+ (() => {
42
+ const ds = props.defaultSizes ?? [50, 50]
43
+ const totalSize = ds.reduce((s, v) => s + v, 0)
44
+ return ds.map((s) => (s / (totalSize || 100)) * 100)
45
+ })()
46
+ )
47
+
48
+ const [drag, setDrag] = createSignal<DragState | null>(null)
49
+ let rootRef: HTMLDivElement | undefined
50
+
51
+ const panelContents = createMemo<JSX.Element[]>(() => {
52
+ if (props.panels && props.panels.length > 0) return props.panels
53
+ return childContent.toArray()
54
+ })
55
+
56
+ const resolvedClasses = createMemo(() =>
57
+ splitterTheme({
58
+ direction: props.direction ?? "horizontal",
59
+ ui: props.ui,
60
+ class: props.class
61
+ })
62
+ )
63
+
64
+ const containerSize = () =>
65
+ isHorizontal() ? (rootRef?.clientWidth ?? 0) : (rootRef?.clientHeight ?? 0)
66
+
67
+ const handlePointerDown = (i: number, e: PointerEvent) => {
68
+ const current = sizes()
69
+ if (current[i + 1] === undefined) return
70
+ e.preventDefault()
71
+ ;(e.currentTarget as HTMLElement).setPointerCapture(e.pointerId)
72
+ setDrag({
73
+ i,
74
+ startPos: isHorizontal() ? e.clientX : e.clientY,
75
+ startA: current[i] ?? 0,
76
+ startB: current[i + 1] ?? 0
77
+ })
78
+ }
79
+
80
+ const handlePointerMove = (i: number, e: PointerEvent) => {
81
+ const state = drag()
82
+ if (!state || state.i !== i) return
83
+ const delta = isHorizontal() ? e.clientX - state.startPos : e.clientY - state.startPos
84
+ const size = containerSize()
85
+ if (!size) return
86
+ const deltaPct = (delta / size) * 100
87
+ const minPct = (48 / size) * 100
88
+ const newA = Math.max(minPct, state.startA + deltaPct)
89
+ const newB = Math.max(minPct, state.startB - deltaPct)
90
+ setSizes((prev) => {
91
+ const next = [...prev]
92
+ next[state.i] = newA
93
+ if (next[state.i + 1] !== undefined) next[state.i + 1] = newB
94
+ return next
95
+ })
96
+ }
97
+
98
+ const handlePointerUp = (_i: number, e: PointerEvent) => {
99
+ if (!drag()) return
100
+ if ((e.currentTarget as HTMLElement).hasPointerCapture(e.pointerId)) {
101
+ ;(e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId)
102
+ }
103
+ setDrag(null)
104
+ }
105
+
106
+ const handleKeyDown = (i: number, e: KeyboardEvent) => {
107
+ const current = sizes()
108
+ if (current[i + 1] === undefined) return
109
+ const forward = isHorizontal() ? e.key === "ArrowRight" : e.key === "ArrowDown"
110
+ const backward = isHorizontal() ? e.key === "ArrowLeft" : e.key === "ArrowUp"
111
+ if (!forward && !backward) return
112
+ e.preventDefault()
113
+ const stepPct = 2
114
+ const delta = forward ? stepPct : -stepPct
115
+ const next = [...current]
116
+ const a = (next[i] ?? 0) + delta
117
+ const b = (next[i + 1] ?? 0) - delta
118
+ if (a < 0 || b < 0) return
119
+ next[i] = a
120
+ if (next[i + 1] !== undefined) next[i + 1] = b
121
+ setSizes(next)
122
+ }
123
+
124
+ const panelStyle = (size: number) =>
125
+ isHorizontal()
126
+ ? { "flex": `0 0 ${size}%` as const, "min-width": "0" }
127
+ : { "flex": `0 0 ${size}%` as const, "min-height": "0" }
128
+
129
+ return (
130
+ <div
131
+ ref={(el) => (rootRef = el)}
132
+ class={resolvedClasses().root}
133
+ data-slot="root"
134
+ data-resizable
135
+ data-direction={props.direction ?? "horizontal"}
136
+ {...rest}
137
+ >
138
+ <For each={sizes()}>
139
+ {(size, i) => (
140
+ <>
141
+ <div
142
+ class={resolvedClasses().panel}
143
+ data-slot="panel"
144
+ data-resizable-panel={i()}
145
+ style={panelStyle(size)}
146
+ >
147
+ {panelContents()[i()]}
148
+ </div>
149
+
150
+ {i() < sizes().length - 1 ? (
151
+ <div
152
+ class={resolvedClasses().handle}
153
+ data-slot="handle"
154
+ data-resizable-handle={i()}
155
+ role="separator"
156
+ aria-orientation={isHorizontal() ? "vertical" : "horizontal"}
157
+ tabindex={0}
158
+ aria-label="Resize panels"
159
+ onPointerDown={(e) => handlePointerDown(i(), e)}
160
+ onPointerMove={(e) => handlePointerMove(i(), e)}
161
+ onPointerUp={(e) => handlePointerUp(i(), e)}
162
+ onKeyDown={(e) => handleKeyDown(i(), e)}
163
+ >
164
+ <RLSIcon
165
+ name={isHorizontal() ? "gripVertical" : "gripHorizontal"}
166
+ class="size-3.5 text-muted/50"
167
+ aria-hidden="true"
168
+ />
169
+ </div>
170
+ ) : null}
171
+ </>
172
+ )}
173
+ </For>
174
+ </div>
175
+ )
176
+ }
177
+
178
+ export default RLSSplitter
@@ -0,0 +1,26 @@
1
+ import { createMemo, splitProps, type Component, type JSX } from "solid-js"
2
+ import type { SpoilerProps } from "./spoiler"
3
+ import { spoilerTheme } from "./spoiler.theme"
4
+
5
+ export interface RLSSpoilerProps extends SpoilerProps {
6
+ children?: JSX.Element
7
+ }
8
+
9
+ const RLSSpoiler: Component<RLSSpoilerProps> = (allProps) => {
10
+ const [props, rest] = splitProps(allProps, ["ui", "class", "children"])
11
+
12
+ const classes = createMemo(() =>
13
+ spoilerTheme({
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 RLSSpoiler