@rimelight/ui 0.0.51 → 0.0.53
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.
- package/package.json +8 -8
- package/src/components/dropdown-menu/RLADropdownMenu.astro +258 -250
- package/src/components/dropdown-menu/RLSDropdownMenu.tsx +161 -140
- package/src/components/head/RLSHead.tsx +2 -7
- package/src/components/head/UIHead.astro +2 -2
- package/src/components/popover/RLAPopover.astro +1 -2
- package/src/components/select/RLASelect.astro +1 -1
- package/src/components/table/RLATable.astro +1692 -1044
- package/src/components/table/RLSTable.tsx +1239 -162
- package/src/components/table/table.theme.ts +20 -14
- package/src/components/table/table.ts +211 -43
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
type Component,
|
|
10
10
|
type JSX
|
|
11
11
|
} from "solid-js"
|
|
12
|
-
import { Portal } from "solid-js/web"
|
|
13
12
|
import type { DropdownMenuProps, DropdownMenuItem } from "./dropdown-menu"
|
|
14
13
|
import { dropdownMenuTheme } from "./dropdown-menu.theme"
|
|
15
14
|
import RLSIcon from "../icon/RLSIcon"
|
|
@@ -60,6 +59,7 @@ const RLSDropdownMenu: Component<RLSDropdownMenuProps> = (allProps) => {
|
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
onMount(() => {
|
|
62
|
+
if (typeof window === "undefined" || typeof document === "undefined") return
|
|
63
63
|
const handleOutsideClick = (e: MouseEvent) => {
|
|
64
64
|
const target = e.target as Node
|
|
65
65
|
if (
|
|
@@ -102,13 +102,17 @@ const RLSDropdownMenu: Component<RLSDropdownMenuProps> = (allProps) => {
|
|
|
102
102
|
|
|
103
103
|
return (
|
|
104
104
|
<div
|
|
105
|
-
ref={(el) =>
|
|
105
|
+
ref={(el) => {
|
|
106
|
+
menuContainer = el
|
|
107
|
+
}}
|
|
106
108
|
class={resolvedClasses().root}
|
|
107
109
|
data-slot="root"
|
|
108
110
|
{...rest}
|
|
109
111
|
>
|
|
110
112
|
<button
|
|
111
|
-
ref={(el) =>
|
|
113
|
+
ref={(el) => {
|
|
114
|
+
triggerBtn = el
|
|
115
|
+
}}
|
|
112
116
|
type="button"
|
|
113
117
|
disabled={props.disabled}
|
|
114
118
|
onClick={(e) => {
|
|
@@ -117,174 +121,191 @@ const RLSDropdownMenu: Component<RLSDropdownMenuProps> = (allProps) => {
|
|
|
117
121
|
if (next) updatePosition()
|
|
118
122
|
setIsOpen(next)
|
|
119
123
|
}}
|
|
120
|
-
class={resolvedClasses().trigger}
|
|
124
|
+
class={`${resolvedClasses().trigger} ${!props.label && !props.children && !props.trigger ? "aspect-square !px-1.5 !py-1.5 inline-flex items-center justify-center shrink-0" : ""}`}
|
|
121
125
|
data-slot="trigger"
|
|
122
126
|
>
|
|
123
|
-
|
|
124
|
-
props.trigger
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
127
|
+
<Show
|
|
128
|
+
when={props.trigger}
|
|
129
|
+
fallback={
|
|
130
|
+
<Show
|
|
131
|
+
when={props.children}
|
|
132
|
+
fallback={
|
|
133
|
+
<Show
|
|
134
|
+
when={props.icon}
|
|
135
|
+
fallback={
|
|
136
|
+
<Show
|
|
137
|
+
when={props.label}
|
|
138
|
+
fallback={<span class="i-lucide-ellipsis-vertical size-4" />}
|
|
139
|
+
>
|
|
140
|
+
<span>{props.label}</span>
|
|
141
|
+
</Show>
|
|
142
|
+
}
|
|
143
|
+
>
|
|
144
|
+
<RLSIcon name={props.icon!} size="sm" class="shrink-0" />
|
|
145
|
+
<Show when={props.label}>
|
|
146
|
+
<span>{props.label}</span>
|
|
147
|
+
</Show>
|
|
148
|
+
</Show>
|
|
149
|
+
}
|
|
150
|
+
>
|
|
151
|
+
{props.children}
|
|
152
|
+
</Show>
|
|
153
|
+
}
|
|
154
|
+
>
|
|
155
|
+
{props.trigger}
|
|
156
|
+
</Show>
|
|
134
157
|
</button>
|
|
135
158
|
|
|
136
159
|
<Show when={isOpen()}>
|
|
137
|
-
<
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
<
|
|
155
|
-
|
|
156
|
-
{(group
|
|
157
|
-
<div class={resolvedClasses().
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
-
: ""
|
|
160
|
+
<div
|
|
161
|
+
ref={(el) => {
|
|
162
|
+
menuContentRef = el
|
|
163
|
+
}}
|
|
164
|
+
class={resolvedClasses().content}
|
|
165
|
+
style={{
|
|
166
|
+
"position": "fixed",
|
|
167
|
+
"z-index": "99999",
|
|
168
|
+
"top": `${coords().top}px`,
|
|
169
|
+
...(coords().right !== undefined ? { right: `${coords().right}px`, left: "auto" } : {}),
|
|
170
|
+
...(coords().left !== undefined ? { left: `${coords().left}px` } : {})
|
|
171
|
+
}}
|
|
172
|
+
data-slot="content"
|
|
173
|
+
role="menu"
|
|
174
|
+
>
|
|
175
|
+
{props.arrow && <div class={resolvedClasses().arrow} />}
|
|
176
|
+
<div class={resolvedClasses().viewport}>
|
|
177
|
+
<For each={itemGroups()}>
|
|
178
|
+
{(group, groupIdx) => (
|
|
179
|
+
<div class={resolvedClasses().group}>
|
|
180
|
+
{groupIdx() > 0 && <div class={resolvedClasses().separator} />}
|
|
181
|
+
<For each={group}>
|
|
182
|
+
{(item) => {
|
|
183
|
+
if (item.type === "separator") {
|
|
184
|
+
return <div class={resolvedClasses().separator} />
|
|
185
|
+
}
|
|
186
|
+
if (item.type === "label") {
|
|
187
|
+
return <div class={resolvedClasses().label}>{item.label}</div>
|
|
188
|
+
}
|
|
174
189
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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
|
-
}
|
|
190
|
+
const itemColor = () =>
|
|
191
|
+
item.color === "error"
|
|
192
|
+
? "text-destructive hover:bg-destructive/10"
|
|
193
|
+
: item.color === "primary"
|
|
194
|
+
? "text-primary hover:bg-primary/10"
|
|
195
|
+
: ""
|
|
196
196
|
|
|
197
|
-
|
|
198
|
-
|
|
197
|
+
const renderLeadingContent = () => {
|
|
198
|
+
if (item.avatar) {
|
|
199
199
|
return (
|
|
200
|
-
<
|
|
201
|
-
{item.
|
|
202
|
-
|
|
203
|
-
)}
|
|
204
|
-
|
|
205
|
-
<For each={item.kbds}>
|
|
206
|
-
{(kbd) => (
|
|
207
|
-
<kbd class={resolvedClasses().itemTrailingKbds}>{kbd}</kbd>
|
|
208
|
-
)}
|
|
209
|
-
</For>
|
|
210
|
-
)}
|
|
211
|
-
</span>
|
|
200
|
+
<img
|
|
201
|
+
src={item.avatar.src}
|
|
202
|
+
alt={item.avatar.alt || item.label || ""}
|
|
203
|
+
class={resolvedClasses().itemLeadingAvatar}
|
|
204
|
+
/>
|
|
212
205
|
)
|
|
213
206
|
}
|
|
214
|
-
|
|
215
|
-
if (item.to) {
|
|
207
|
+
if (item.icon) {
|
|
216
208
|
return (
|
|
217
|
-
<
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
class={
|
|
221
|
-
|
|
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>
|
|
209
|
+
<RLSIcon
|
|
210
|
+
name={item.icon}
|
|
211
|
+
size="sm"
|
|
212
|
+
class={resolvedClasses().itemLeadingIcon}
|
|
213
|
+
/>
|
|
232
214
|
)
|
|
233
215
|
}
|
|
216
|
+
return null
|
|
217
|
+
}
|
|
234
218
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
219
|
+
const renderTrailingContent = () => {
|
|
220
|
+
if (!item.shortcut && (!item.kbds || item.kbds.length === 0)) return null
|
|
221
|
+
return (
|
|
222
|
+
<span class={resolvedClasses().itemTrailing}>
|
|
223
|
+
{item.shortcut && (
|
|
224
|
+
<span class={resolvedClasses().shortcut}>{item.shortcut}</span>
|
|
225
|
+
)}
|
|
226
|
+
{item.kbds && (
|
|
227
|
+
<For each={item.kbds}>
|
|
228
|
+
{(kbd) => (
|
|
229
|
+
<kbd class={resolvedClasses().itemTrailingKbds}>{kbd}</kbd>
|
|
230
|
+
)}
|
|
231
|
+
</For>
|
|
232
|
+
)}
|
|
233
|
+
</span>
|
|
234
|
+
)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (item.to) {
|
|
238
|
+
return (
|
|
239
|
+
<a
|
|
240
|
+
href={item.to}
|
|
241
|
+
target={item.target}
|
|
242
|
+
class={`${resolvedClasses().item} ${itemColor()} ${item.class || ""}`}
|
|
243
|
+
data-slot="item"
|
|
244
|
+
role="menuitem"
|
|
245
|
+
onClick={(e) => {
|
|
246
|
+
setIsOpen(false)
|
|
247
|
+
item.onSelect?.(e)
|
|
248
|
+
}}
|
|
249
|
+
>
|
|
250
|
+
{renderLeadingContent()}
|
|
251
|
+
<span class={resolvedClasses().itemLabel}>{item.label}</span>
|
|
252
|
+
{renderTrailingContent()}
|
|
253
|
+
</a>
|
|
254
|
+
)
|
|
255
|
+
}
|
|
262
256
|
|
|
257
|
+
if (item.type === "checkbox") {
|
|
258
|
+
const isChecked = () => !!item.checked
|
|
263
259
|
return (
|
|
264
260
|
<button
|
|
265
261
|
type="button"
|
|
266
262
|
disabled={item.disabled}
|
|
267
263
|
class={`${resolvedClasses().item} ${itemColor()} ${item.class || ""}`}
|
|
268
264
|
data-slot="item"
|
|
269
|
-
role="
|
|
265
|
+
role="menuitemcheckbox"
|
|
266
|
+
aria-checked={isChecked()}
|
|
270
267
|
onClick={(e) => {
|
|
271
|
-
|
|
268
|
+
const next = !isChecked()
|
|
269
|
+
item.onUpdateChecked?.(next)
|
|
272
270
|
item.onSelect?.(e)
|
|
273
271
|
}}
|
|
274
272
|
>
|
|
273
|
+
<span class="shrink-0 size-4 flex items-center justify-center border border-default rounded bg-default">
|
|
274
|
+
<Show when={isChecked()}>
|
|
275
|
+
<RLSIcon name="check" size="xs" class="text-primary" />
|
|
276
|
+
</Show>
|
|
277
|
+
</span>
|
|
275
278
|
{renderLeadingContent()}
|
|
276
279
|
<span class={resolvedClasses().itemLabel}>{item.label}</span>
|
|
277
280
|
{renderTrailingContent()}
|
|
278
281
|
</button>
|
|
279
282
|
)
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return (
|
|
286
|
+
<button
|
|
287
|
+
type="button"
|
|
288
|
+
disabled={item.disabled}
|
|
289
|
+
class={`${resolvedClasses().item} ${itemColor()} ${item.class || ""}`}
|
|
290
|
+
data-slot="item"
|
|
291
|
+
role="menuitem"
|
|
292
|
+
onClick={(e) => {
|
|
293
|
+
setIsOpen(false)
|
|
294
|
+
item.onSelect?.(e)
|
|
295
|
+
}}
|
|
296
|
+
>
|
|
297
|
+
{renderLeadingContent()}
|
|
298
|
+
<span class={resolvedClasses().itemLabel}>{item.label}</span>
|
|
299
|
+
{renderTrailingContent()}
|
|
300
|
+
</button>
|
|
301
|
+
)
|
|
302
|
+
}}
|
|
303
|
+
</For>
|
|
304
|
+
</div>
|
|
305
|
+
)}
|
|
306
|
+
</For>
|
|
286
307
|
</div>
|
|
287
|
-
</
|
|
308
|
+
</div>
|
|
288
309
|
</Show>
|
|
289
310
|
</div>
|
|
290
311
|
)
|
|
@@ -27,13 +27,8 @@ const RLSHead: Component<RLSHeadProps> = (_allProps) => {
|
|
|
27
27
|
if (localStorage.getItem("theme") === "system") applyTheme()
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
onCleanup(() => mql.removeEventListener("change", onChange))
|
|
33
|
-
} else {
|
|
34
|
-
mql.addListener(onChange)
|
|
35
|
-
onCleanup(() => mql.removeListener(onChange))
|
|
36
|
-
}
|
|
30
|
+
mql.addEventListener("change", onChange)
|
|
31
|
+
onCleanup(() => mql.removeEventListener("change", onChange))
|
|
37
32
|
})
|
|
38
33
|
|
|
39
34
|
return null
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import { ClientRouter } from 'astro:transitions';
|
|
3
3
|
|
|
4
4
|
export interface UIHeadProps {
|
|
5
|
-
/** Whether to enable View Transitions (ClientRouter) */
|
|
5
|
+
/** Whether to enable View Transitions (ClientRouter). Defaults to false in dev, true in prod. */
|
|
6
6
|
transitions?: boolean;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
const {
|
|
10
|
-
transitions =
|
|
10
|
+
transitions = !import.meta.env.DEV
|
|
11
11
|
} = Astro.props as UIHeadProps;
|
|
12
12
|
---
|
|
13
13
|
|
|
@@ -202,14 +202,13 @@ const popoverId = `rla-popover-${Math.random().toString(36).substring(2, 9)}`
|
|
|
202
202
|
const popoverId = container.querySelector<HTMLElement>('[data-slot="content"]')?.id;
|
|
203
203
|
if (!popoverId) return;
|
|
204
204
|
|
|
205
|
-
const panel = document.getElementById(popoverId) as HTMLElement & { hidePopover?: () => void; showPopover?: () => void } | null;
|
|
205
|
+
const panel = document.getElementById(popoverId) as HTMLElement & { hidePopover?: () => void; showPopover?: () => void; togglePopover?: () => void } | null;
|
|
206
206
|
if (!panel || typeof panel.showPopover !== 'function') return;
|
|
207
207
|
|
|
208
208
|
// For slot-based triggers (not a <button popovertarget>), wire click manually
|
|
209
209
|
const trigger = container.querySelector<HTMLElement>('[data-slot="trigger"]');
|
|
210
210
|
if (trigger && !trigger.querySelector('[popovertarget]')) {
|
|
211
211
|
trigger.addEventListener('click', () => {
|
|
212
|
-
// @ts-ignore
|
|
213
212
|
panel.togglePopover?.();
|
|
214
213
|
});
|
|
215
214
|
}
|
|
@@ -172,7 +172,7 @@ const currentLabel =
|
|
|
172
172
|
<script>
|
|
173
173
|
document.addEventListener("change", (event) => {
|
|
174
174
|
const target = event.target as HTMLSelectElement | null
|
|
175
|
-
if (!target || target.dataset
|
|
175
|
+
if (!target || target.dataset["slot"] !== "select") return
|
|
176
176
|
const root = target.closest('[data-slot="root"]')
|
|
177
177
|
const label = root?.querySelector('[data-slot="label"]')
|
|
178
178
|
if (label) {
|