@rimelight/ui 0.0.44 → 0.0.45
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 +10 -9
- package/src/components/button/RLSButton.tsx +1 -1
- package/src/components/dashboard-sidebar/RLADashboardSidebar.astro +53 -24
- package/src/components/dashboard-sidebar/dashboard-sidebar.theme.ts +5 -5
- package/src/components/icon/RLSIcon.tsx +1 -1
- package/src/components/modal/RLAModal.astro +8 -5
- package/src/components/modal/RLSModal.tsx +17 -12
- package/src/components/modal/modal.theme.ts +5 -4
- package/LICENSE +0 -21
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rimelight/ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.45",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Rimelight Entertainment's UI Package",
|
|
6
6
|
"homepage": "https://rimelight.com/docs",
|
|
@@ -26,6 +26,10 @@
|
|
|
26
26
|
"publishConfig": {
|
|
27
27
|
"access": "public"
|
|
28
28
|
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"astro": "astro",
|
|
31
|
+
"check": "vp check --fix && astro check"
|
|
32
|
+
},
|
|
29
33
|
"dependencies": {
|
|
30
34
|
"@unocss/vite": "66.8.1",
|
|
31
35
|
"unocss": "66.8.1"
|
|
@@ -35,11 +39,11 @@
|
|
|
35
39
|
"@astrojs/solid-js": "7.0.2",
|
|
36
40
|
"@astrojs/ts-plugin": "1.10.11",
|
|
37
41
|
"@astrojs/vue": "7.0.2",
|
|
38
|
-
"@rimelight/config": "
|
|
39
|
-
"astro": "7.2.
|
|
42
|
+
"@rimelight/config": "workspace:*",
|
|
43
|
+
"astro": "7.2.9",
|
|
40
44
|
"solid-js": "1.9.15",
|
|
41
45
|
"typescript": "6.0.3",
|
|
42
|
-
"vue": "3.5.
|
|
46
|
+
"vue": "3.5.42"
|
|
43
47
|
},
|
|
44
48
|
"peerDependencies": {
|
|
45
49
|
"@astrojs/solid-js": ">=7.0.1",
|
|
@@ -65,8 +69,5 @@
|
|
|
65
69
|
"engines": {
|
|
66
70
|
"node": ">=26.7.0"
|
|
67
71
|
},
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
"check": "vp check --fix && astro check"
|
|
71
|
-
}
|
|
72
|
-
}
|
|
72
|
+
"packageManager": "pnpm@12.0.0"
|
|
73
|
+
}
|
|
@@ -75,7 +75,7 @@ const RLSButton: Component<RLSButtonProps> = (allProps) => {
|
|
|
75
75
|
justify: props.justify,
|
|
76
76
|
block: props.block,
|
|
77
77
|
square: props.square !== undefined ? props.square : !props.label && !props.children,
|
|
78
|
-
rounded: props.rounded,
|
|
78
|
+
rounded: props.rounded ?? false,
|
|
79
79
|
leading: isLeading(),
|
|
80
80
|
trailing: isTrailing(),
|
|
81
81
|
loading: props.loading,
|
|
@@ -15,9 +15,6 @@ const classes = dashboardSidebarTheme({
|
|
|
15
15
|
...Astro.props,
|
|
16
16
|
collapsed: collapsible && collapsed
|
|
17
17
|
});
|
|
18
|
-
|
|
19
|
-
const collapsedWidth = "4rem";
|
|
20
|
-
const defaultWidth = "16rem";
|
|
21
18
|
---
|
|
22
19
|
|
|
23
20
|
<div
|
|
@@ -26,11 +23,10 @@ const defaultWidth = "16rem";
|
|
|
26
23
|
data-collapsible={collapsible ? "true" : "false"}
|
|
27
24
|
data-collapsed={collapsible && collapsed ? "true" : "false"}
|
|
28
25
|
data-slot="root"
|
|
29
|
-
class={classes.root}
|
|
26
|
+
class:list={[classes.root, className]}
|
|
30
27
|
{...rest}
|
|
31
|
-
style={`width: ${collapsible && collapsed ? collapsedWidth : defaultWidth}; min-width: ${collapsible && collapsed ? collapsedWidth : defaultWidth}; flex-shrink: 0; --width: ${defaultWidth}; --collapsed-width: ${collapsedWidth}`}
|
|
32
28
|
>
|
|
33
|
-
<div data-slot="header" class={classes.header}
|
|
29
|
+
<div data-slot="header" class={classes.header}>
|
|
34
30
|
<slot name="header" />
|
|
35
31
|
</div>
|
|
36
32
|
|
|
@@ -48,15 +44,15 @@ const defaultWidth = "16rem";
|
|
|
48
44
|
<div
|
|
49
45
|
data-dashboard-sidebar-mobile
|
|
50
46
|
data-slot="content"
|
|
51
|
-
class={classes.content
|
|
47
|
+
class:list={[classes.content, "fixed inset-y-0 left-0 z-50 w-72 max-w-[85vw] bg-default shadow-2xl border-e border-default transform -translate-x-full transition-transform duration-300 flex flex-col h-full"]}
|
|
52
48
|
>
|
|
53
|
-
<div data-slot="header" class={classes.header
|
|
49
|
+
<div data-slot="header" class:list={[classes.header, "sm:px-6 shrink-0"]} data-menu>
|
|
54
50
|
<slot name="header" />
|
|
55
51
|
</div>
|
|
56
|
-
<div data-slot="body" class={classes.body
|
|
52
|
+
<div data-slot="body" class:list={[classes.body, "sm:px-6 overflow-y-auto flex-1"]} data-menu>
|
|
57
53
|
<slot />
|
|
58
54
|
</div>
|
|
59
|
-
<div data-slot="footer" class={classes.footer
|
|
55
|
+
<div data-slot="footer" class:list={[classes.footer, "sm:px-6 shrink-0"]} data-menu>
|
|
60
56
|
<slot name="footer" />
|
|
61
57
|
</div>
|
|
62
58
|
</div>
|
|
@@ -70,20 +66,34 @@ const defaultWidth = "16rem";
|
|
|
70
66
|
const mobilePanel = document.querySelector<HTMLElement>('[data-dashboard-sidebar-mobile]');
|
|
71
67
|
const overlay = document.querySelector<HTMLElement>('[data-dashboard-sidebar-overlay]');
|
|
72
68
|
|
|
73
|
-
const
|
|
69
|
+
const openMobile = () => {
|
|
70
|
+
if (!mobilePanel || !overlay) return;
|
|
71
|
+
mobilePanel.classList.remove('-translate-x-full');
|
|
72
|
+
mobilePanel.classList.add('translate-x-0');
|
|
73
|
+
overlay.classList.remove('hidden');
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const closeMobile = () => {
|
|
74
77
|
if (!mobilePanel || !overlay) return;
|
|
75
|
-
|
|
76
|
-
mobilePanel.classList.
|
|
77
|
-
overlay.classList.
|
|
78
|
+
mobilePanel.classList.add('-translate-x-full');
|
|
79
|
+
mobilePanel.classList.remove('translate-x-0');
|
|
80
|
+
overlay.classList.add('hidden');
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const toggleMobile = () => {
|
|
84
|
+
if (!mobilePanel) return;
|
|
85
|
+
if (mobilePanel.classList.contains('translate-x-0')) {
|
|
86
|
+
closeMobile();
|
|
87
|
+
} else {
|
|
88
|
+
openMobile();
|
|
89
|
+
}
|
|
78
90
|
};
|
|
79
91
|
|
|
80
92
|
const collapseSidebar = (val?: boolean) => {
|
|
81
93
|
if (!collapsible) return;
|
|
82
94
|
const isCollapsed = val !== undefined ? val : sidebar.dataset.collapsed !== 'true';
|
|
83
|
-
|
|
84
|
-
sidebar.
|
|
85
|
-
sidebar.style.minWidth = w;
|
|
86
|
-
sidebar.style.setProperty('--width', w);
|
|
95
|
+
sidebar.dataset.collapsed = isCollapsed ? 'true' : 'false';
|
|
96
|
+
sidebar.setAttribute('data-collapsed', isCollapsed ? 'true' : 'false');
|
|
87
97
|
|
|
88
98
|
document.querySelectorAll('[data-dashboard-toggle="collapse"]').forEach(btn => {
|
|
89
99
|
btn.querySelectorAll('[data-dashboard-collapse-icon]').forEach(el => {
|
|
@@ -92,16 +102,32 @@ const defaultWidth = "16rem";
|
|
|
92
102
|
});
|
|
93
103
|
};
|
|
94
104
|
|
|
95
|
-
|
|
105
|
+
const handleClick = (e: MouseEvent) => {
|
|
96
106
|
const target = e.target as Element | null;
|
|
97
|
-
|
|
107
|
+
if (!target) return;
|
|
108
|
+
|
|
109
|
+
// Toggle buttons (mobile drawer + collapse)
|
|
110
|
+
const toggle = target.closest<HTMLElement>('[data-dashboard-toggle]');
|
|
98
111
|
if (toggle) {
|
|
99
112
|
const side = toggle.dataset.dashboardToggle;
|
|
100
113
|
if (side === 'mobile') toggleMobile();
|
|
101
114
|
if (side === 'collapse') collapseSidebar();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Backdrop overlay click
|
|
119
|
+
if (target.closest('[data-dashboard-sidebar-overlay]')) {
|
|
120
|
+
closeMobile();
|
|
121
|
+
return;
|
|
102
122
|
}
|
|
103
123
|
|
|
104
|
-
|
|
124
|
+
// Close the mobile drawer when clicking a navigation link inside it
|
|
125
|
+
if (target.closest('[data-dashboard-sidebar-mobile] a')) {
|
|
126
|
+
closeMobile();
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const navItem = target.closest<HTMLElement>('[data-dashboard-nav]');
|
|
105
131
|
if (navItem) {
|
|
106
132
|
const container = navItem.closest('[data-dashboard-nav-container]');
|
|
107
133
|
if (container) {
|
|
@@ -113,10 +139,13 @@ const defaultWidth = "16rem";
|
|
|
113
139
|
navItem.classList.add('bg-muted', 'text-highlighted');
|
|
114
140
|
}
|
|
115
141
|
}
|
|
116
|
-
}
|
|
142
|
+
};
|
|
117
143
|
|
|
118
|
-
|
|
144
|
+
const handleKey = (e: KeyboardEvent) => {
|
|
145
|
+
if (e.key === 'Escape') closeMobile();
|
|
146
|
+
};
|
|
119
147
|
|
|
120
|
-
(
|
|
148
|
+
document.addEventListener('click', handleClick);
|
|
149
|
+
document.addEventListener('keydown', handleKey);
|
|
121
150
|
})();
|
|
122
151
|
</script>
|
|
@@ -3,12 +3,12 @@ import { defineTheme } from "../../resolver"
|
|
|
3
3
|
export const dashboardSidebarTheme = defineTheme("dashboard-sidebar", {
|
|
4
4
|
slots: ["root", "header", "body", "footer", "toggle", "handle", "content", "overlay"],
|
|
5
5
|
base: {
|
|
6
|
-
root: "group relative flex flex-col h-full min-h-0 min-w-
|
|
6
|
+
root: "group relative hidden lg:flex flex-col h-full min-h-0 shrink-0 transition-[width] duration-300 w-64 min-w-64 max-w-64 data-[collapsed=true]:w-16 data-[collapsed=true]:min-w-16 data-[collapsed=true]:max-w-16 data-[collapsed=true]:overflow-hidden data-[collapsed=false]:w-64 data-[collapsed=false]:min-w-64 data-[collapsed=false]:max-w-64",
|
|
7
7
|
header:
|
|
8
|
-
"h-16 min-h-16 shrink-0 flex items-center gap-3 px-6 py-4 border-b border-default group-data-[collapsed=true]:justify-center group-data-[collapsed=true]:gap-0 group-data-[collapsed=true]:px-0",
|
|
9
|
-
body: "flex flex-col gap-1 flex-1 overflow-y-auto px-3 py-3",
|
|
8
|
+
"h-16 min-h-16 shrink-0 flex items-center gap-3 px-6 py-4 border-b border-default group-data-[collapsed=true]:justify-center group-data-[collapsed=true]:items-center group-data-[collapsed=true]:gap-0 group-data-[collapsed=true]:px-0",
|
|
9
|
+
body: "flex flex-col gap-1 flex-1 overflow-y-auto px-3 py-3 group-data-[collapsed=true]:items-center group-data-[collapsed=true]:px-0 group-data-[collapsed=true]:overflow-hidden",
|
|
10
10
|
footer:
|
|
11
|
-
"shrink-0 flex items-center gap-1.5 px-3 py-3 group-data-[collapsed=true]:
|
|
11
|
+
"shrink-0 flex items-center gap-1.5 px-3 py-3 border-t border-default/40 group-data-[collapsed=true]:justify-center group-data-[collapsed=true]:items-center group-data-[collapsed=true]:px-0",
|
|
12
12
|
toggle: "",
|
|
13
13
|
handle: "",
|
|
14
14
|
content: "lg:hidden",
|
|
@@ -32,7 +32,7 @@ export const dashboardSidebarTheme = defineTheme("dashboard-sidebar", {
|
|
|
32
32
|
},
|
|
33
33
|
collapsed: {
|
|
34
34
|
true: {
|
|
35
|
-
root: "w-16 w-
|
|
35
|
+
root: "w-16 min-w-16 max-w-16 overflow-hidden",
|
|
36
36
|
body: "overflow-hidden"
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -16,7 +16,7 @@ const RLSIcon: Component<IconProps> = (allProps) => {
|
|
|
16
16
|
return (
|
|
17
17
|
<span class={classes().root} data-slot="icon" aria-hidden="true" {...rest}>
|
|
18
18
|
{resolved().isClass ? (
|
|
19
|
-
<span class={`${resolved().content} size-full`} />
|
|
19
|
+
<span class={`${resolved().content} block size-full`} />
|
|
20
20
|
) : (
|
|
21
21
|
<span innerHTML={resolved().content} />
|
|
22
22
|
)}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
import type { ModalProps } from "./modal"
|
|
3
3
|
import { modalTheme } from "./modal.theme"
|
|
4
|
-
import
|
|
4
|
+
import RLAButton from "../button/RLAButton.astro"
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
@@ -49,15 +49,18 @@ const modalId = `rla-modal-${Math.random().toString(36).substring(2, 9)}`
|
|
|
49
49
|
data-unmount-on-hide={unmountOnHide ? "true" : "false"}
|
|
50
50
|
{...rest}
|
|
51
51
|
>
|
|
52
|
-
<
|
|
52
|
+
<RLAButton
|
|
53
53
|
class={classes.closeButton}
|
|
54
54
|
data-slot="close-button"
|
|
55
55
|
type="button"
|
|
56
|
+
variant="ghost"
|
|
57
|
+
color="neutral"
|
|
58
|
+
size="sm"
|
|
59
|
+
square
|
|
60
|
+
leadingIcon="i-rl-close"
|
|
56
61
|
data-dialog-close={modalId}
|
|
57
62
|
aria-label="Close modal"
|
|
58
|
-
|
|
59
|
-
<RLAIcon name="i-rl-close" class="size-4" aria-hidden="true" />
|
|
60
|
-
</button>
|
|
63
|
+
/>
|
|
61
64
|
|
|
62
65
|
<div class={classes.header} data-slot="header">
|
|
63
66
|
{title && <h3 class={classes.title} data-slot="title">{title}</h3>}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "solid-js"
|
|
11
11
|
import type { ModalProps } from "./modal"
|
|
12
12
|
import { modalTheme } from "./modal.theme"
|
|
13
|
-
import
|
|
13
|
+
import RLSButton from "../button/RLSButton"
|
|
14
14
|
|
|
15
15
|
export interface RLSModalProps extends ModalProps {
|
|
16
16
|
onClose?: () => void
|
|
@@ -41,6 +41,7 @@ const RLSModal: Component<RLSModalProps> = (allProps) => {
|
|
|
41
41
|
|
|
42
42
|
const closeOnClickOutside = () => props.closeOnClickOutside !== false
|
|
43
43
|
const closeOnEscape = () => props.closeOnEscape !== false
|
|
44
|
+
const unmountOnHide = () => props.unmountOnHide !== false
|
|
44
45
|
|
|
45
46
|
const handleClose = () => {
|
|
46
47
|
props.onClose?.()
|
|
@@ -54,8 +55,8 @@ const RLSModal: Component<RLSModalProps> = (allProps) => {
|
|
|
54
55
|
e.preventDefault()
|
|
55
56
|
} else {
|
|
56
57
|
e.preventDefault()
|
|
57
|
-
handleClose()
|
|
58
58
|
}
|
|
59
|
+
handleClose()
|
|
59
60
|
}
|
|
60
61
|
const handleClick = (e: MouseEvent) => {
|
|
61
62
|
// Clicking the ::backdrop means e.target IS the dialog element
|
|
@@ -91,24 +92,28 @@ const RLSModal: Component<RLSModalProps> = (allProps) => {
|
|
|
91
92
|
})
|
|
92
93
|
|
|
93
94
|
return (
|
|
94
|
-
<Show when={props.open || !
|
|
95
|
+
<Show when={props.open || !unmountOnHide()}>
|
|
95
96
|
<dialog
|
|
96
97
|
ref={(el) => (dialogRef = el)}
|
|
97
|
-
class={`w-full rounded-xl border border-default bg-default p-6 shadow-xl outline-none flex flex-col max-h-[90vh] overflow-y-auto text-highlighted backdrop:bg-black/60 backdrop:backdrop-blur-sm ${
|
|
98
|
-
|
|
99
|
-
} ${props.class || ""}`}
|
|
98
|
+
class={`w-[calc(100%-1.5rem)] sm:w-full rounded-xl border border-default bg-default p-5 sm:p-6 shadow-xl outline-none flex flex-col max-h-[calc(100dvh-1.5rem)] sm:max-h-[90vh] overflow-y-auto text-highlighted backdrop:bg-black/60 backdrop:backdrop-blur-sm ${
|
|
99
|
+
props.open ? "" : "hidden"
|
|
100
|
+
} ${resolvedClasses().content || ""} ${props.class || ""}`}
|
|
101
|
+
data-state={props.open ? "open" : "closed"}
|
|
100
102
|
data-slot="content"
|
|
101
103
|
{...rest}
|
|
102
104
|
>
|
|
103
|
-
<
|
|
105
|
+
<RLSButton
|
|
104
106
|
type="button"
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
variant="ghost"
|
|
108
|
+
color="neutral"
|
|
109
|
+
size="sm"
|
|
110
|
+
square
|
|
111
|
+
leadingIcon="close"
|
|
107
112
|
aria-label="Close modal"
|
|
113
|
+
data-slot="close-button"
|
|
114
|
+
class="absolute right-4 top-4 text-muted hover:text-highlighted"
|
|
108
115
|
onClick={handleClose}
|
|
109
|
-
|
|
110
|
-
<RLSIcon name="close" size="sm" aria-hidden="true" />
|
|
111
|
-
</button>
|
|
116
|
+
/>
|
|
112
117
|
|
|
113
118
|
{props.title || props.description || props.titleSlot || props.descriptionSlot ? (
|
|
114
119
|
<div class={resolvedClasses().header || "mb-4"} data-slot="header">
|
|
@@ -17,8 +17,9 @@ export const modalTheme = defineTheme("modal", {
|
|
|
17
17
|
trigger: "",
|
|
18
18
|
backdrop: "fixed inset-0 z-50 bg-black/60 backdrop-blur-sm transition-all duration-300",
|
|
19
19
|
content: [
|
|
20
|
-
"fixed left-1/2 top-1/2 z-50 w-full max-w-lg -translate-x-1/2 -translate-y-1/2 rounded-xl border border-default",
|
|
21
|
-
"bg-default p-6 shadow-xl transition-all duration-300 outline-none",
|
|
20
|
+
"fixed left-1/2 top-1/2 z-50 w-[calc(100%-1.5rem)] sm:w-full max-w-lg -translate-x-1/2 -translate-y-1/2 rounded-xl border border-default",
|
|
21
|
+
"bg-default p-5 sm:p-6 shadow-xl transition-all duration-300 outline-none",
|
|
22
|
+
"max-h-[calc(100dvh-1.5rem)] sm:max-h-[90vh] overflow-y-auto",
|
|
22
23
|
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-1/2",
|
|
23
24
|
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-1/2"
|
|
24
25
|
],
|
|
@@ -27,8 +28,8 @@ export const modalTheme = defineTheme("modal", {
|
|
|
27
28
|
description: "text-sm text-muted leading-relaxed",
|
|
28
29
|
footer: "flex flex-col-reverse sm:flex-row sm:justify-end gap-2 mt-6",
|
|
29
30
|
closeButton: [
|
|
30
|
-
"absolute right-4 top-4
|
|
31
|
-
"focus:outline-none
|
|
31
|
+
"absolute right-4 top-4 opacity-70 transition-opacity hover:opacity-100",
|
|
32
|
+
"focus:outline-none"
|
|
32
33
|
]
|
|
33
34
|
},
|
|
34
35
|
variants: {
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Rimelight Entertainment
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|