@rimelight/ui 0.0.30 → 0.0.31
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 +1 -1
- package/src/components/astro/RLAAlert.astro +60 -0
- package/src/components/astro/RLAAlertDialog.astro +86 -0
- package/src/components/astro/RLAAspectRatio.astro +23 -0
- package/src/components/astro/RLAAvatar.astro +56 -0
- package/src/components/astro/RLAAvatarGroup.astro +19 -0
- package/src/components/astro/RLABadge.astro +31 -0
- package/src/components/astro/RLABreadcrumb.astro +44 -0
- package/src/components/astro/RLACard.astro +74 -0
- package/src/components/astro/RLACarousel.astro +71 -0
- package/src/components/astro/RLAChart.astro +215 -0
- package/src/components/astro/RLACheckbox.astro +51 -0
- package/src/components/astro/RLACollapsible.astro +38 -0
- package/src/components/astro/RLACombobox.astro +131 -0
- package/src/components/astro/RLADialog.astro +95 -0
- package/src/components/astro/RLADrawer.astro +74 -0
- package/src/components/astro/RLADropdownMenu.astro +82 -0
- package/src/components/astro/RLADropzone.astro +134 -0
- package/src/components/astro/RLAField.astro +43 -0
- package/src/components/{Head.astro → astro/RLAHead.astro} +181 -199
- package/src/components/astro/RLAHoverCard.astro +31 -0
- package/src/components/astro/RLAInput.astro +60 -0
- package/src/components/astro/RLAInputGroup.astro +35 -0
- package/src/components/astro/RLAKbd.astro +22 -0
- package/src/components/astro/RLALabel.astro +23 -0
- package/src/components/astro/RLALocaleSelector.astro +110 -0
- package/src/components/astro/RLAMarquee.astro +32 -0
- package/src/components/astro/RLANativeSelect.astro +51 -0
- package/src/components/astro/RLANavigationMenu.astro +136 -0
- package/src/components/astro/RLAPagination.astro +94 -0
- package/src/components/astro/RLAPopover.astro +31 -0
- package/src/components/astro/RLAProgress.astro +43 -0
- package/src/components/astro/RLAResizable.astro +177 -0
- package/src/components/astro/RLAScrollArea.astro +157 -0
- package/src/components/astro/RLASelect.astro +109 -0
- package/src/components/astro/RLASeparator.astro +27 -0
- package/src/components/astro/RLASheet.astro +72 -0
- package/src/components/astro/RLASidebar.astro +135 -0
- package/src/components/astro/RLASkeleton.astro +20 -0
- package/src/components/astro/RLASlider.astro +53 -0
- package/src/components/astro/RLASpinner.astro +25 -0
- package/src/components/astro/RLAStickySurface.astro +27 -0
- package/src/components/astro/RLASwitch.astro +49 -0
- package/src/components/astro/RLATable.astro +60 -0
- package/src/components/astro/RLATabs.astro +92 -0
- package/src/components/astro/RLATextarea.astro +42 -0
- package/src/components/astro/RLAThemeSelector.astro +73 -0
- package/src/components/astro/RLAToast.astro +107 -0
- package/src/components/astro/RLAToggle.astro +38 -0
- package/src/components/astro/RLAToggleGroup.astro +30 -0
- package/src/components/astro/RLATooltip.astro +31 -0
- package/src/integrations/ui.ts +1 -0
- package/src/themes/alert.theme.ts +51 -0
- package/src/themes/alertDialog.theme.ts +33 -0
- package/src/themes/aspectRatio.theme.ts +11 -0
- package/src/themes/avatar.theme.ts +28 -0
- package/src/themes/avatarGroup.theme.ts +10 -0
- package/src/themes/badge.theme.ts +61 -0
- package/src/themes/breadcrumb.theme.ts +15 -0
- package/src/themes/card.theme.ts +34 -0
- package/src/themes/carousel.theme.ts +32 -0
- package/src/themes/chart.theme.ts +21 -0
- package/src/themes/checkbox.theme.ts +42 -0
- package/src/themes/collapsible.theme.ts +22 -0
- package/src/themes/combobox.theme.ts +28 -0
- package/src/themes/dialog.theme.ts +37 -0
- package/src/themes/drawer.theme.ts +44 -0
- package/src/themes/dropdownMenu.theme.ts +27 -0
- package/src/themes/dropzone.theme.ts +24 -0
- package/src/themes/field.theme.ts +24 -0
- package/src/themes/hoverCard.theme.ts +27 -0
- package/src/themes/input.theme.ts +36 -0
- package/src/themes/inputGroup.theme.ts +23 -0
- package/src/themes/kbd.theme.ts +24 -0
- package/src/themes/label.theme.ts +20 -0
- package/src/themes/localeSelector.theme.ts +50 -0
- package/src/themes/marquee.theme.ts +27 -0
- package/src/themes/nativeSelect.theme.ts +24 -0
- package/src/themes/navigationMenu.theme.ts +19 -0
- package/src/themes/pagination.theme.ts +26 -0
- package/src/themes/popover.theme.ts +28 -0
- package/src/themes/progress.theme.ts +26 -0
- package/src/themes/resizable.theme.ts +22 -0
- package/src/themes/scrollArea.theme.ts +24 -0
- package/src/themes/section.theme.ts +1 -2
- package/src/themes/select.theme.ts +27 -0
- package/src/themes/separator.theme.ts +19 -0
- package/src/themes/sheet.theme.ts +43 -0
- package/src/themes/sidebar.theme.ts +33 -0
- package/src/themes/skeleton.theme.ts +20 -0
- package/src/themes/slider.theme.ts +28 -0
- package/src/themes/spinner.theme.ts +30 -0
- package/src/themes/stickySurface.theme.ts +10 -0
- package/src/themes/switch.theme.ts +59 -0
- package/src/themes/table.theme.ts +36 -0
- package/src/themes/tabs.theme.ts +44 -0
- package/src/themes/textarea.theme.ts +26 -0
- package/src/themes/themeSelector.theme.ts +16 -0
- package/src/themes/toast.theme.ts +25 -0
- package/src/themes/toggle.theme.ts +42 -0
- package/src/themes/toggleGroup.theme.ts +21 -0
- package/src/themes/tooltip.theme.ts +27 -0
- package/src/types/components/alert-dialog.ts +35 -0
- package/src/types/components/alert.ts +31 -0
- package/src/types/components/aspect-ratio.ts +15 -0
- package/src/types/components/avatar.ts +47 -0
- package/src/types/components/badge.ts +27 -0
- package/src/types/components/breadcrumb.ts +24 -0
- package/src/types/components/card.ts +31 -0
- package/src/types/components/carousel.ts +25 -0
- package/src/types/components/chart.ts +38 -0
- package/src/types/components/checkbox.ts +35 -0
- package/src/types/components/collapsible.ts +31 -0
- package/src/types/components/combobox.ts +43 -0
- package/src/types/components/dialog.ts +39 -0
- package/src/types/components/drawer.ts +31 -0
- package/src/types/components/dropdown-menu.ts +42 -0
- package/src/types/components/dropzone.ts +39 -0
- package/src/types/components/field.ts +31 -0
- package/src/types/components/hover-card.ts +19 -0
- package/src/types/components/index.ts +47 -0
- package/src/types/components/input-group.ts +23 -0
- package/src/types/components/input.ts +59 -0
- package/src/types/components/kbd.ts +15 -0
- package/src/types/components/label.ts +19 -0
- package/src/types/components/localeSelector.ts +33 -0
- package/src/types/components/marquee.ts +23 -0
- package/src/types/components/native-select.ts +39 -0
- package/src/types/components/navigation-menu.ts +27 -0
- package/src/types/components/pagination.ts +23 -0
- package/src/types/components/popover.ts +23 -0
- package/src/types/components/progress.ts +27 -0
- package/src/types/components/resizable.ts +19 -0
- package/src/types/components/scroll-area.ts +23 -0
- package/src/types/components/select.ts +43 -0
- package/src/types/components/separator.ts +19 -0
- package/src/types/components/sheet.ts +31 -0
- package/src/types/components/sidebar.ts +36 -0
- package/src/types/components/skeleton.ts +15 -0
- package/src/types/components/slider.ts +35 -0
- package/src/types/components/spinner.ts +19 -0
- package/src/types/components/sticky-surface.ts +19 -0
- package/src/types/components/switch.ts +35 -0
- package/src/types/components/table.ts +31 -0
- package/src/types/components/tabs.ts +43 -0
- package/src/types/components/textarea.ts +51 -0
- package/src/types/components/themeSelector.ts +15 -0
- package/src/types/components/toast.ts +35 -0
- package/src/types/components/toggle-group.ts +23 -0
- package/src/types/components/toggle.ts +27 -0
- package/src/types/components/tooltip.ts +23 -0
- package/src/components/ThemeToggle.astro +0 -57
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { scv } from "css-variants"
|
|
3
|
+
import { useUi, resolveClasses } from "../../utils"
|
|
4
|
+
import type { TableProps } from "../../types"
|
|
5
|
+
import tableThemeDefault, { createTableTheme } from "../../themes/table.theme"
|
|
6
|
+
|
|
7
|
+
const tableTheme = tableThemeDefault
|
|
8
|
+
const table = scv(tableTheme)
|
|
9
|
+
|
|
10
|
+
const {
|
|
11
|
+
headers = [],
|
|
12
|
+
rows = [],
|
|
13
|
+
striped = false,
|
|
14
|
+
bordered = false,
|
|
15
|
+
hoverable = true,
|
|
16
|
+
ui: uiProp,
|
|
17
|
+
class: className,
|
|
18
|
+
...rest
|
|
19
|
+
} = Astro.props as TableProps
|
|
20
|
+
|
|
21
|
+
const classes = resolveClasses(table, {
|
|
22
|
+
striped,
|
|
23
|
+
bordered
|
|
24
|
+
}, useUi("table", uiProp), className);
|
|
25
|
+
---
|
|
26
|
+
<div class={classes.root} data-slot="root">
|
|
27
|
+
<table class={classes.table} data-slot="table" {...rest}>
|
|
28
|
+
{headers.length > 0 && (
|
|
29
|
+
<thead class={classes.thead} data-slot="thead">
|
|
30
|
+
<tr class={classes.tr} data-slot="tr">
|
|
31
|
+
{headers.map(header => {
|
|
32
|
+
const label = typeof header === "string" ? header : header.label
|
|
33
|
+
const cellClass = typeof header === "string" ? "" : (header.class || "")
|
|
34
|
+
return (
|
|
35
|
+
<th class={classes.th + " " + cellClass} data-slot="th">
|
|
36
|
+
{label}
|
|
37
|
+
</th>
|
|
38
|
+
)
|
|
39
|
+
})}
|
|
40
|
+
</tr>
|
|
41
|
+
</thead>
|
|
42
|
+
)}
|
|
43
|
+
<tbody class={classes.tbody} data-slot="tbody">
|
|
44
|
+
<slot>
|
|
45
|
+
{rows.map(row => {
|
|
46
|
+
const cells = Array.isArray(row) ? row : Object.values(row)
|
|
47
|
+
return (
|
|
48
|
+
<tr class={classes.tr} data-slot="tr">
|
|
49
|
+
{cells.map(cell => (
|
|
50
|
+
<td class={classes.td} data-slot="td">
|
|
51
|
+
{cell}
|
|
52
|
+
</td>
|
|
53
|
+
))}
|
|
54
|
+
</tr>
|
|
55
|
+
)
|
|
56
|
+
})}
|
|
57
|
+
</slot>
|
|
58
|
+
</tbody>
|
|
59
|
+
</table>
|
|
60
|
+
</div>
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { scv } from "css-variants"
|
|
3
|
+
import { useUi, resolveClasses } from "../../utils"
|
|
4
|
+
import type { TabsProps } from "../../types"
|
|
5
|
+
import tabsThemeDefault, { createTabsTheme } from "../../themes/tabs.theme"
|
|
6
|
+
|
|
7
|
+
const tabsTheme = tabsThemeDefault
|
|
8
|
+
const tabs = scv(tabsTheme)
|
|
9
|
+
|
|
10
|
+
const {
|
|
11
|
+
items = [],
|
|
12
|
+
value = "",
|
|
13
|
+
variant = "solid",
|
|
14
|
+
orientation = "horizontal",
|
|
15
|
+
size = "md",
|
|
16
|
+
color = "primary",
|
|
17
|
+
ui: uiProp,
|
|
18
|
+
class: className,
|
|
19
|
+
...rest
|
|
20
|
+
} = Astro.props as TabsProps
|
|
21
|
+
|
|
22
|
+
const classes = resolveClasses(tabs, {
|
|
23
|
+
variant,
|
|
24
|
+
orientation,
|
|
25
|
+
size
|
|
26
|
+
}, useUi("tabs", uiProp), className);
|
|
27
|
+
|
|
28
|
+
const initialValue = value || (items.length > 0 ? items[0].value : "")
|
|
29
|
+
---
|
|
30
|
+
<div class={classes.root} data-slot="root" data-tabs-container data-value={initialValue} {...rest}>
|
|
31
|
+
<div class={classes.list} data-slot="list" role="tablist">
|
|
32
|
+
{items.map((item) => {
|
|
33
|
+
const active = item.value === initialValue
|
|
34
|
+
return (
|
|
35
|
+
<button
|
|
36
|
+
type="button"
|
|
37
|
+
class={classes.trigger}
|
|
38
|
+
data-slot="trigger"
|
|
39
|
+
role="tab"
|
|
40
|
+
data-value={item.value}
|
|
41
|
+
data-state={active ? "active" : "inactive"}
|
|
42
|
+
disabled={item.disabled}
|
|
43
|
+
>
|
|
44
|
+
{item.icon && <span class={item.icon + " mr-2"} />}
|
|
45
|
+
{item.label}
|
|
46
|
+
</button>
|
|
47
|
+
)
|
|
48
|
+
})}
|
|
49
|
+
</div>
|
|
50
|
+
<div class="flex-1">
|
|
51
|
+
<slot>
|
|
52
|
+
{items.map(item => {
|
|
53
|
+
const active = item.value === initialValue
|
|
54
|
+
return (
|
|
55
|
+
<div
|
|
56
|
+
class={classes.content + (active ? "" : " hidden")}
|
|
57
|
+
data-slot="content"
|
|
58
|
+
role="tabpanel"
|
|
59
|
+
data-value={item.value}
|
|
60
|
+
>
|
|
61
|
+
{item.content}
|
|
62
|
+
</div>
|
|
63
|
+
)
|
|
64
|
+
})}
|
|
65
|
+
</slot>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<script>
|
|
70
|
+
document.querySelectorAll("[data-tabs-container]").forEach(container => {
|
|
71
|
+
const triggers = container.querySelectorAll("[role=tab]");
|
|
72
|
+
const panels = container.querySelectorAll("[role=tabpanel]");
|
|
73
|
+
|
|
74
|
+
triggers.forEach(trigger => {
|
|
75
|
+
trigger.addEventListener("click", () => {
|
|
76
|
+
const targetValue = (trigger as HTMLButtonElement).dataset.value;
|
|
77
|
+
|
|
78
|
+
triggers.forEach(t => {
|
|
79
|
+
t.setAttribute("data-state", t.dataset.value === targetValue ? "active" : "inactive");
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
panels.forEach(panel => {
|
|
83
|
+
if ((panel as HTMLElement).dataset.value === targetValue) {
|
|
84
|
+
panel.classList.remove("hidden");
|
|
85
|
+
} else {
|
|
86
|
+
panel.classList.add("hidden");
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
</script>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { scv } from "css-variants"
|
|
3
|
+
import { useUi, resolveClasses } from "../../utils"
|
|
4
|
+
import type { TextareaProps } from "../../types"
|
|
5
|
+
import textareaThemeDefault, { createTextareaTheme } from "../../themes/textarea.theme"
|
|
6
|
+
|
|
7
|
+
const textareaTheme = textareaThemeDefault
|
|
8
|
+
const textarea = scv(textareaTheme)
|
|
9
|
+
|
|
10
|
+
const {
|
|
11
|
+
value = "",
|
|
12
|
+
placeholder,
|
|
13
|
+
disabled = false,
|
|
14
|
+
readonly = false,
|
|
15
|
+
name,
|
|
16
|
+
required = false,
|
|
17
|
+
rows = 4,
|
|
18
|
+
error = false,
|
|
19
|
+
size = "md",
|
|
20
|
+
color = "primary",
|
|
21
|
+
ui: uiProp,
|
|
22
|
+
class: className,
|
|
23
|
+
...rest
|
|
24
|
+
} = Astro.props as TextareaProps
|
|
25
|
+
|
|
26
|
+
const classes = resolveClasses(textarea, {
|
|
27
|
+
size,
|
|
28
|
+
error: !!error
|
|
29
|
+
}, useUi("textarea", uiProp), className);
|
|
30
|
+
---
|
|
31
|
+
<div class={classes.root} data-slot="root">
|
|
32
|
+
<textarea
|
|
33
|
+
class={classes.textarea}
|
|
34
|
+
placeholder={placeholder}
|
|
35
|
+
disabled={disabled}
|
|
36
|
+
readonly={readonly}
|
|
37
|
+
name={name}
|
|
38
|
+
required={required}
|
|
39
|
+
rows={rows}
|
|
40
|
+
{...rest}
|
|
41
|
+
>{value}</textarea>
|
|
42
|
+
</div>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { scv } from "css-variants"
|
|
3
|
+
import { useUi, resolveClasses } from "../../utils"
|
|
4
|
+
import type { ThemeSelectorProps } from "../../types"
|
|
5
|
+
import themeSelectorTheme from "../../themes/themeSelector.theme"
|
|
6
|
+
import RLAButton from "./RLAButton.astro"
|
|
7
|
+
|
|
8
|
+
const themeSelector = scv(themeSelectorTheme)
|
|
9
|
+
|
|
10
|
+
const {
|
|
11
|
+
size = "md",
|
|
12
|
+
ui: uiProp,
|
|
13
|
+
class: className,
|
|
14
|
+
...rest
|
|
15
|
+
} = Astro.props as ThemeSelectorProps
|
|
16
|
+
|
|
17
|
+
const classes = resolveClasses(themeSelector, {
|
|
18
|
+
size
|
|
19
|
+
}, useUi("themeSelector", uiProp), className);
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
<RLAButton
|
|
23
|
+
size={size}
|
|
24
|
+
class:list={["theme-toggle-button", classes.root]}
|
|
25
|
+
variant="ghost"
|
|
26
|
+
aria-label="Toggle theme"
|
|
27
|
+
{...rest}
|
|
28
|
+
>
|
|
29
|
+
<span class:list={[classes.sun]} />
|
|
30
|
+
<span class:list={[classes.moon]} />
|
|
31
|
+
</RLAButton>
|
|
32
|
+
|
|
33
|
+
<script>
|
|
34
|
+
function applyStoredTheme() {
|
|
35
|
+
const stored = localStorage.getItem('theme');
|
|
36
|
+
if (stored === 'dark') {
|
|
37
|
+
document.documentElement.classList.add('dark');
|
|
38
|
+
} else if (stored === 'light') {
|
|
39
|
+
document.documentElement.classList.remove('dark');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function setupThemeToggle() {
|
|
44
|
+
const buttons = document.querySelectorAll('.theme-toggle-button');
|
|
45
|
+
|
|
46
|
+
const updateButtons = (isDark: boolean) => {
|
|
47
|
+
buttons.forEach(btn => {
|
|
48
|
+
btn.setAttribute('data-state', isDark ? 'on' : 'off');
|
|
49
|
+
btn.setAttribute('aria-pressed', isDark.toString());
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const currentIsDark = document.documentElement.classList.contains('dark');
|
|
54
|
+
updateButtons(currentIsDark);
|
|
55
|
+
|
|
56
|
+
buttons.forEach(button => {
|
|
57
|
+
if (button.hasAttribute('data-initialized')) return;
|
|
58
|
+
button.setAttribute('data-initialized', '');
|
|
59
|
+
button.addEventListener('click', () => {
|
|
60
|
+
const isDark = document.documentElement.classList.toggle('dark');
|
|
61
|
+
localStorage.setItem('theme', isDark ? 'dark' : 'light');
|
|
62
|
+
updateButtons(isDark);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
applyStoredTheme();
|
|
68
|
+
setupThemeToggle();
|
|
69
|
+
document.addEventListener('astro:page-load', () => {
|
|
70
|
+
applyStoredTheme();
|
|
71
|
+
setupThemeToggle();
|
|
72
|
+
});
|
|
73
|
+
</script>
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { scv } from "css-variants"
|
|
3
|
+
import { useUi, resolveClasses } from "../../utils"
|
|
4
|
+
import type { ToastProps } from "../../types"
|
|
5
|
+
import toastThemeDefault, { createToastTheme } from "../../themes/toast.theme"
|
|
6
|
+
|
|
7
|
+
const toastTheme = toastThemeDefault
|
|
8
|
+
const toast = scv(toastTheme)
|
|
9
|
+
|
|
10
|
+
const {
|
|
11
|
+
title,
|
|
12
|
+
description,
|
|
13
|
+
variant = "default",
|
|
14
|
+
actionLabel,
|
|
15
|
+
duration = 5000,
|
|
16
|
+
color = "primary",
|
|
17
|
+
ui: uiProp,
|
|
18
|
+
class: className,
|
|
19
|
+
...rest
|
|
20
|
+
} = Astro.props as ToastProps
|
|
21
|
+
|
|
22
|
+
const classes = resolveClasses(toast, {
|
|
23
|
+
variant
|
|
24
|
+
}, useUi("toast", uiProp), className)
|
|
25
|
+
|
|
26
|
+
const variantIcons: Record<string, string> = {
|
|
27
|
+
default: "i-lucide-bell",
|
|
28
|
+
destructive: "i-lucide-alert-circle",
|
|
29
|
+
success: "i-lucide-check-circle-2",
|
|
30
|
+
warning: "i-lucide-alert-triangle",
|
|
31
|
+
info: "i-lucide-info",
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const icon = variantIcons[variant] ?? variantIcons.default!
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
<div
|
|
38
|
+
class={classes.root}
|
|
39
|
+
data-slot="root"
|
|
40
|
+
data-toast
|
|
41
|
+
data-duration={duration}
|
|
42
|
+
role="alert"
|
|
43
|
+
aria-live="assertive"
|
|
44
|
+
aria-atomic="true"
|
|
45
|
+
{...rest}
|
|
46
|
+
>
|
|
47
|
+
{/* Icon */}
|
|
48
|
+
<span class={icon + " size-4 shrink-0 mt-0.5"} aria-hidden="true" />
|
|
49
|
+
|
|
50
|
+
{/* Text body */}
|
|
51
|
+
<div class="flex flex-col gap-0.5 flex-1 min-w-0">
|
|
52
|
+
{title && (
|
|
53
|
+
<div class={classes.title} data-slot="title">
|
|
54
|
+
<slot name="title">{title}</slot>
|
|
55
|
+
</div>
|
|
56
|
+
)}
|
|
57
|
+
{description && (
|
|
58
|
+
<div class={classes.description} data-slot="description">
|
|
59
|
+
<slot name="description">{description}</slot>
|
|
60
|
+
</div>
|
|
61
|
+
)}
|
|
62
|
+
<slot />
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
{/* Action */}
|
|
66
|
+
{actionLabel && (
|
|
67
|
+
<button
|
|
68
|
+
type="button"
|
|
69
|
+
class={classes.action}
|
|
70
|
+
data-slot="action"
|
|
71
|
+
data-toast-action
|
|
72
|
+
>
|
|
73
|
+
{actionLabel}
|
|
74
|
+
</button>
|
|
75
|
+
)}
|
|
76
|
+
|
|
77
|
+
{/* Close button */}
|
|
78
|
+
<button
|
|
79
|
+
type="button"
|
|
80
|
+
class={classes.close}
|
|
81
|
+
data-slot="close"
|
|
82
|
+
data-toast-close
|
|
83
|
+
aria-label="Dismiss notification"
|
|
84
|
+
>
|
|
85
|
+
<span class="i-lucide-x size-3.5" aria-hidden="true" />
|
|
86
|
+
</button>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<script>
|
|
90
|
+
document.querySelectorAll("[data-toast]").forEach(toast => {
|
|
91
|
+
const close = toast.querySelector("[data-toast-close]");
|
|
92
|
+
const duration = parseInt((toast as HTMLElement).dataset.duration ?? "5000", 10);
|
|
93
|
+
|
|
94
|
+
const dismiss = () => {
|
|
95
|
+
toast.classList.add("opacity-0", "translate-y-2", "pointer-events-none");
|
|
96
|
+
toast.addEventListener("transitionend", () => toast.remove(), { once: true });
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Auto-dismiss
|
|
100
|
+
if (duration > 0) {
|
|
101
|
+
setTimeout(dismiss, duration);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Manual close
|
|
105
|
+
close?.addEventListener("click", dismiss);
|
|
106
|
+
});
|
|
107
|
+
</script>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { scv } from "css-variants"
|
|
3
|
+
import { useUi, resolveClasses } from "../../utils"
|
|
4
|
+
import type { ToggleProps } from "../../types"
|
|
5
|
+
import toggleThemeDefault, { createToggleTheme } from "../../themes/toggle.theme"
|
|
6
|
+
import { getUIConfig } from "virtual:rimelight-ui"
|
|
7
|
+
|
|
8
|
+
const uiConfig = getUIConfig()
|
|
9
|
+
const toggleTheme = uiConfig.colors ? createToggleTheme(uiConfig.colors) : toggleThemeDefault
|
|
10
|
+
|
|
11
|
+
const toggle = scv(toggleTheme)
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
active = false,
|
|
15
|
+
disabled = false,
|
|
16
|
+
color = "primary",
|
|
17
|
+
size = "md",
|
|
18
|
+
ui: uiProp,
|
|
19
|
+
class: className,
|
|
20
|
+
...rest
|
|
21
|
+
} = Astro.props as ToggleProps
|
|
22
|
+
|
|
23
|
+
const classes = resolveClasses(toggle, {
|
|
24
|
+
color,
|
|
25
|
+
size,
|
|
26
|
+
active
|
|
27
|
+
}, useUi("toggle", uiProp), className);
|
|
28
|
+
---
|
|
29
|
+
<button
|
|
30
|
+
type="button"
|
|
31
|
+
class={classes.root}
|
|
32
|
+
data-slot="root"
|
|
33
|
+
data-state={active ? "on" : "off"}
|
|
34
|
+
disabled={disabled}
|
|
35
|
+
{...rest}
|
|
36
|
+
>
|
|
37
|
+
<slot />
|
|
38
|
+
</button>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { scv } from "css-variants"
|
|
3
|
+
import { useUi, resolveClasses } from "../../utils"
|
|
4
|
+
import type { ToggleGroupProps } from "../../types"
|
|
5
|
+
import toggleGroupThemeDefault, { createToggleGroupTheme } from "../../themes/toggleGroup.theme"
|
|
6
|
+
|
|
7
|
+
const toggleGroupTheme = toggleGroupThemeDefault
|
|
8
|
+
const toggleGroup = scv(toggleGroupTheme)
|
|
9
|
+
|
|
10
|
+
const {
|
|
11
|
+
value = [],
|
|
12
|
+
type = "single",
|
|
13
|
+
size = "md",
|
|
14
|
+
ui: uiProp,
|
|
15
|
+
class: className,
|
|
16
|
+
...rest
|
|
17
|
+
} = Astro.props as ToggleGroupProps
|
|
18
|
+
|
|
19
|
+
const classes = resolveClasses(toggleGroup, {
|
|
20
|
+
size
|
|
21
|
+
}, useUi("toggleGroup", uiProp), className);
|
|
22
|
+
---
|
|
23
|
+
<div
|
|
24
|
+
class={classes.root}
|
|
25
|
+
data-slot="root"
|
|
26
|
+
data-type={type}
|
|
27
|
+
{...rest}
|
|
28
|
+
>
|
|
29
|
+
<slot />
|
|
30
|
+
</div>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { scv } from "css-variants"
|
|
3
|
+
import { useUi, resolveClasses } from "../../utils"
|
|
4
|
+
import type { TooltipProps } from "../../types"
|
|
5
|
+
import tooltipTheme from "../../themes/tooltip.theme"
|
|
6
|
+
|
|
7
|
+
const tooltip = scv(tooltipTheme)
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
content,
|
|
11
|
+
placement = "top",
|
|
12
|
+
ui: uiProp,
|
|
13
|
+
class: className,
|
|
14
|
+
...rest
|
|
15
|
+
} = Astro.props as TooltipProps
|
|
16
|
+
|
|
17
|
+
const classes = resolveClasses(tooltip, {
|
|
18
|
+
placement
|
|
19
|
+
}, useUi("tooltip", uiProp), className)
|
|
20
|
+
---
|
|
21
|
+
<div class={classes.root} data-slot="tooltip-container" {...rest}>
|
|
22
|
+
<div class={classes.trigger} data-slot="trigger" tabindex="0">
|
|
23
|
+
<slot />
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div class={classes.content} data-slot="content" role="tooltip">
|
|
27
|
+
<slot name="content">
|
|
28
|
+
{content}
|
|
29
|
+
</slot>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
package/src/integrations/ui.ts
CHANGED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { defineTheme } from "../utils/defineTheme"
|
|
2
|
+
|
|
3
|
+
const defaultColors = ["primary", "secondary", "info", "success", "warning", "error"]
|
|
4
|
+
|
|
5
|
+
export const createAlertTheme = (colors: string[] = defaultColors) =>
|
|
6
|
+
defineTheme({
|
|
7
|
+
slots: ["root", "icon", "content", "title", "description"],
|
|
8
|
+
base: {
|
|
9
|
+
root: "relative w-full rounded-lg border p-4 flex gap-3 text-sm transition-all shadow-sm",
|
|
10
|
+
icon: "shrink-0 size-5 text-current",
|
|
11
|
+
content: "flex flex-col gap-1 w-full",
|
|
12
|
+
title: "font-semibold leading-none tracking-tight text-foreground",
|
|
13
|
+
description: "text-xs opacity-90 leading-relaxed"
|
|
14
|
+
},
|
|
15
|
+
variants: {
|
|
16
|
+
variant: {
|
|
17
|
+
default: { root: "bg-background text-foreground border-border" },
|
|
18
|
+
destructive: { root: "bg-error-500/10 text-error-700 border-error-500/20 dark:text-error-400" },
|
|
19
|
+
outline: { root: "border bg-transparent" },
|
|
20
|
+
solid: { root: "border-transparent text-white" }
|
|
21
|
+
},
|
|
22
|
+
color: Object.fromEntries(colors.map((color) => [color, { root: "" }])),
|
|
23
|
+
hasIcon: {
|
|
24
|
+
true: { icon: "block" },
|
|
25
|
+
false: { icon: "hidden" }
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
compoundVariants: [
|
|
29
|
+
...colors.map((color) => ({
|
|
30
|
+
variant: "solid" as const,
|
|
31
|
+
color,
|
|
32
|
+
classNames: {
|
|
33
|
+
root: `bg-${color}-500 text-white border-transparent`
|
|
34
|
+
}
|
|
35
|
+
})),
|
|
36
|
+
...colors.map((color) => ({
|
|
37
|
+
variant: "outline" as const,
|
|
38
|
+
color,
|
|
39
|
+
classNames: {
|
|
40
|
+
root: `border-${color}-500/20 text-${color}-600 bg-${color}-500/5`
|
|
41
|
+
}
|
|
42
|
+
}))
|
|
43
|
+
],
|
|
44
|
+
defaultVariants: {
|
|
45
|
+
variant: "default",
|
|
46
|
+
color: "primary",
|
|
47
|
+
hasIcon: false
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
export default createAlertTheme()
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { defineTheme } from "../utils/defineTheme"
|
|
2
|
+
|
|
3
|
+
export const alertDialogTheme = defineTheme({
|
|
4
|
+
slots: ["root", "trigger", "backdrop", "content", "header", "title", "description", "footer", "cancelButton", "actionButton"],
|
|
5
|
+
base: {
|
|
6
|
+
root: "relative inline-block",
|
|
7
|
+
trigger: "",
|
|
8
|
+
backdrop: "fixed inset-0 z-50 bg-black/60 backdrop-blur-sm transition-all duration-300",
|
|
9
|
+
content: [
|
|
10
|
+
"fixed left-1/2 top-1/2 z-50 w-full max-w-md -translate-x-1/2 -translate-y-1/2 rounded-xl border border-border",
|
|
11
|
+
"bg-background p-6 shadow-xl transition-all duration-300 outline-none",
|
|
12
|
+
"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",
|
|
13
|
+
"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"
|
|
14
|
+
],
|
|
15
|
+
header: "flex flex-col gap-1.5 text-center sm:text-left mb-4",
|
|
16
|
+
title: "text-lg font-semibold leading-none tracking-tight text-foreground",
|
|
17
|
+
description: "text-sm text-muted-foreground leading-relaxed",
|
|
18
|
+
footer: "flex flex-col-reverse sm:flex-row sm:justify-end gap-2 mt-6",
|
|
19
|
+
cancelButton: "w-full sm:w-auto",
|
|
20
|
+
actionButton: "w-full sm:w-auto"
|
|
21
|
+
},
|
|
22
|
+
variants: {
|
|
23
|
+
variant: {
|
|
24
|
+
default: { actionButton: "" },
|
|
25
|
+
destructive: { actionButton: "bg-error-500 hover:bg-error-600 focus-visible:ring-error-500/50" }
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
defaultVariants: {
|
|
29
|
+
variant: "default"
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
export default alertDialogTheme
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { defineTheme } from "../utils/defineTheme"
|
|
2
|
+
|
|
3
|
+
export const aspectRatioTheme = defineTheme({
|
|
4
|
+
slots: ["root", "content"],
|
|
5
|
+
base: {
|
|
6
|
+
root: "relative w-full overflow-hidden",
|
|
7
|
+
content: "absolute inset-0 h-full w-full object-cover"
|
|
8
|
+
}
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
export default aspectRatioTheme
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { defineTheme } from "../utils/defineTheme"
|
|
2
|
+
|
|
3
|
+
export const avatarTheme = defineTheme({
|
|
4
|
+
slots: ["root", "image", "fallback", "badge"],
|
|
5
|
+
base: {
|
|
6
|
+
root: "relative flex shrink-0 overflow-hidden rounded-full select-none",
|
|
7
|
+
image: "aspect-square h-full w-full object-cover",
|
|
8
|
+
fallback: "flex h-full w-full items-center justify-center rounded-full bg-muted font-semibold text-muted-foreground uppercase",
|
|
9
|
+
badge: "absolute bottom-0 right-0 block size-2.5 rounded-full ring-2 ring-background"
|
|
10
|
+
},
|
|
11
|
+
variants: {
|
|
12
|
+
size: {
|
|
13
|
+
sm: { root: "size-8", fallback: "text-xs" },
|
|
14
|
+
md: { root: "size-10", fallback: "text-sm" },
|
|
15
|
+
lg: { root: "size-12", fallback: "text-base" }
|
|
16
|
+
},
|
|
17
|
+
hasBadge: {
|
|
18
|
+
true: { badge: "block" },
|
|
19
|
+
false: { badge: "hidden" }
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
defaultVariants: {
|
|
23
|
+
size: "md",
|
|
24
|
+
hasBadge: false
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
export default avatarTheme
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defineTheme } from "../utils/defineTheme"
|
|
2
|
+
|
|
3
|
+
export const avatarGroupTheme = defineTheme({
|
|
4
|
+
slots: ["root"],
|
|
5
|
+
base: {
|
|
6
|
+
root: "flex -space-x-3 hover:space-x-0 transition-all duration-300 [&_[data-slot=root]]:ring-2 [&_[data-slot=root]]:ring-background [&_[data-slot=root]]:transition-all"
|
|
7
|
+
}
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
export default avatarGroupTheme
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { defineTheme } from "../utils/defineTheme"
|
|
2
|
+
|
|
3
|
+
const defaultColors = ["primary", "secondary", "info", "success", "warning", "error"]
|
|
4
|
+
|
|
5
|
+
export const createBadgeTheme = (colors: string[] = defaultColors) =>
|
|
6
|
+
defineTheme({
|
|
7
|
+
slots: ["root"],
|
|
8
|
+
base: {
|
|
9
|
+
root: "inline-flex items-center gap-1.5 font-medium select-none overflow-hidden transition-all duration-150"
|
|
10
|
+
},
|
|
11
|
+
variants: {
|
|
12
|
+
variant: {
|
|
13
|
+
solid: { root: "border border-transparent text-white" },
|
|
14
|
+
outline: { root: "border" },
|
|
15
|
+
soft: { root: "border border-transparent" },
|
|
16
|
+
ghost: { root: "bg-transparent hover:bg-muted" }
|
|
17
|
+
},
|
|
18
|
+
color: Object.fromEntries(colors.map((color) => [color, { root: "" }])),
|
|
19
|
+
size: {
|
|
20
|
+
sm: { root: "px-2 py-0.5 text-2xs rounded-full h-5" },
|
|
21
|
+
md: { root: "px-2.5 py-0.5 text-xs rounded-full h-6" },
|
|
22
|
+
lg: { root: "px-3 py-1 text-sm rounded-full h-7" }
|
|
23
|
+
},
|
|
24
|
+
shape: {
|
|
25
|
+
square: { root: "rounded-sm" },
|
|
26
|
+
rounded: { root: "rounded-md" },
|
|
27
|
+
pill: { root: "rounded-full" }
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
compoundVariants: [
|
|
31
|
+
...colors.map((color) => ({
|
|
32
|
+
variant: "solid" as const,
|
|
33
|
+
color,
|
|
34
|
+
classNames: {
|
|
35
|
+
root: `bg-${color}-500 text-white hover:bg-${color}-600`
|
|
36
|
+
}
|
|
37
|
+
})),
|
|
38
|
+
...colors.map((color) => ({
|
|
39
|
+
variant: "outline" as const,
|
|
40
|
+
color,
|
|
41
|
+
classNames: {
|
|
42
|
+
root: `border-${color}-500/20 text-${color}-600 bg-transparent hover:bg-${color}-500/5`
|
|
43
|
+
}
|
|
44
|
+
})),
|
|
45
|
+
...colors.map((color) => ({
|
|
46
|
+
variant: "soft" as const,
|
|
47
|
+
color,
|
|
48
|
+
classNames: {
|
|
49
|
+
root: `text-${color}-600 bg-${color}-500/10 hover:bg-${color}-500/20`
|
|
50
|
+
}
|
|
51
|
+
}))
|
|
52
|
+
],
|
|
53
|
+
defaultVariants: {
|
|
54
|
+
variant: "solid",
|
|
55
|
+
color: "primary",
|
|
56
|
+
size: "md",
|
|
57
|
+
shape: "pill"
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
export default createBadgeTheme()
|