@rimelight/ui 0.0.29 → 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.
Files changed (156) hide show
  1. package/package.json +1 -1
  2. package/src/components/astro/RLAAlert.astro +60 -0
  3. package/src/components/astro/RLAAlertDialog.astro +86 -0
  4. package/src/components/astro/RLAAspectRatio.astro +23 -0
  5. package/src/components/astro/RLAAvatar.astro +56 -0
  6. package/src/components/astro/RLAAvatarGroup.astro +19 -0
  7. package/src/components/astro/RLABadge.astro +31 -0
  8. package/src/components/astro/RLABreadcrumb.astro +44 -0
  9. package/src/components/astro/RLACard.astro +74 -0
  10. package/src/components/astro/RLACarousel.astro +71 -0
  11. package/src/components/astro/RLAChart.astro +215 -0
  12. package/src/components/astro/RLACheckbox.astro +51 -0
  13. package/src/components/astro/RLACollapsible.astro +38 -0
  14. package/src/components/astro/RLACombobox.astro +131 -0
  15. package/src/components/astro/RLADialog.astro +95 -0
  16. package/src/components/astro/RLADrawer.astro +74 -0
  17. package/src/components/astro/RLADropdownMenu.astro +82 -0
  18. package/src/components/astro/RLADropzone.astro +134 -0
  19. package/src/components/astro/RLAField.astro +43 -0
  20. package/src/components/{Head.astro → astro/RLAHead.astro} +181 -199
  21. package/src/components/astro/RLAHoverCard.astro +31 -0
  22. package/src/components/astro/RLAInput.astro +60 -0
  23. package/src/components/astro/RLAInputGroup.astro +35 -0
  24. package/src/components/astro/RLAKbd.astro +22 -0
  25. package/src/components/astro/RLALabel.astro +23 -0
  26. package/src/components/astro/RLALocaleSelector.astro +110 -0
  27. package/src/components/astro/RLAMain.astro +28 -0
  28. package/src/components/astro/RLAMarquee.astro +32 -0
  29. package/src/components/astro/RLANativeSelect.astro +51 -0
  30. package/src/components/astro/RLANavigationMenu.astro +136 -0
  31. package/src/components/astro/RLAPagination.astro +94 -0
  32. package/src/components/astro/RLAPopover.astro +31 -0
  33. package/src/components/astro/RLAProgress.astro +43 -0
  34. package/src/components/astro/RLAResizable.astro +177 -0
  35. package/src/components/astro/RLAScrollArea.astro +157 -0
  36. package/src/components/astro/RLASection.astro +0 -1
  37. package/src/components/astro/RLASelect.astro +109 -0
  38. package/src/components/astro/RLASeparator.astro +27 -0
  39. package/src/components/astro/RLASheet.astro +72 -0
  40. package/src/components/astro/RLASidebar.astro +135 -0
  41. package/src/components/astro/RLASkeleton.astro +20 -0
  42. package/src/components/astro/RLASlider.astro +53 -0
  43. package/src/components/astro/RLASpinner.astro +25 -0
  44. package/src/components/astro/RLAStickySurface.astro +27 -0
  45. package/src/components/astro/RLASwitch.astro +49 -0
  46. package/src/components/astro/RLATable.astro +60 -0
  47. package/src/components/astro/RLATabs.astro +92 -0
  48. package/src/components/astro/RLATextarea.astro +42 -0
  49. package/src/components/astro/RLAThemeSelector.astro +73 -0
  50. package/src/components/astro/RLAToast.astro +107 -0
  51. package/src/components/astro/RLAToggle.astro +38 -0
  52. package/src/components/astro/RLAToggleGroup.astro +30 -0
  53. package/src/components/astro/RLATooltip.astro +31 -0
  54. package/src/integrations/ui.ts +1 -0
  55. package/src/themes/alert.theme.ts +51 -0
  56. package/src/themes/alertDialog.theme.ts +33 -0
  57. package/src/themes/aspectRatio.theme.ts +11 -0
  58. package/src/themes/avatar.theme.ts +28 -0
  59. package/src/themes/avatarGroup.theme.ts +10 -0
  60. package/src/themes/badge.theme.ts +61 -0
  61. package/src/themes/breadcrumb.theme.ts +15 -0
  62. package/src/themes/card.theme.ts +34 -0
  63. package/src/themes/carousel.theme.ts +32 -0
  64. package/src/themes/chart.theme.ts +21 -0
  65. package/src/themes/checkbox.theme.ts +42 -0
  66. package/src/themes/collapsible.theme.ts +22 -0
  67. package/src/themes/combobox.theme.ts +28 -0
  68. package/src/themes/dialog.theme.ts +37 -0
  69. package/src/themes/drawer.theme.ts +44 -0
  70. package/src/themes/dropdownMenu.theme.ts +27 -0
  71. package/src/themes/dropzone.theme.ts +24 -0
  72. package/src/themes/field.theme.ts +24 -0
  73. package/src/themes/hoverCard.theme.ts +27 -0
  74. package/src/themes/input.theme.ts +36 -0
  75. package/src/themes/inputGroup.theme.ts +23 -0
  76. package/src/themes/kbd.theme.ts +24 -0
  77. package/src/themes/label.theme.ts +20 -0
  78. package/src/themes/localeSelector.theme.ts +50 -0
  79. package/src/themes/main.theme.ts +12 -0
  80. package/src/themes/marquee.theme.ts +27 -0
  81. package/src/themes/nativeSelect.theme.ts +24 -0
  82. package/src/themes/navigationMenu.theme.ts +19 -0
  83. package/src/themes/pagination.theme.ts +26 -0
  84. package/src/themes/popover.theme.ts +28 -0
  85. package/src/themes/progress.theme.ts +26 -0
  86. package/src/themes/resizable.theme.ts +22 -0
  87. package/src/themes/scrollArea.theme.ts +24 -0
  88. package/src/themes/section.theme.ts +1 -2
  89. package/src/themes/select.theme.ts +27 -0
  90. package/src/themes/separator.theme.ts +19 -0
  91. package/src/themes/sheet.theme.ts +43 -0
  92. package/src/themes/sidebar.theme.ts +33 -0
  93. package/src/themes/skeleton.theme.ts +20 -0
  94. package/src/themes/slider.theme.ts +28 -0
  95. package/src/themes/spinner.theme.ts +30 -0
  96. package/src/themes/stickySurface.theme.ts +10 -0
  97. package/src/themes/switch.theme.ts +59 -0
  98. package/src/themes/table.theme.ts +36 -0
  99. package/src/themes/tabs.theme.ts +44 -0
  100. package/src/themes/textarea.theme.ts +26 -0
  101. package/src/themes/themeSelector.theme.ts +16 -0
  102. package/src/themes/toast.theme.ts +25 -0
  103. package/src/themes/toggle.theme.ts +42 -0
  104. package/src/themes/toggleGroup.theme.ts +21 -0
  105. package/src/themes/tooltip.theme.ts +27 -0
  106. package/src/types/components/alert-dialog.ts +35 -0
  107. package/src/types/components/alert.ts +31 -0
  108. package/src/types/components/aspect-ratio.ts +15 -0
  109. package/src/types/components/avatar.ts +47 -0
  110. package/src/types/components/badge.ts +27 -0
  111. package/src/types/components/breadcrumb.ts +24 -0
  112. package/src/types/components/card.ts +31 -0
  113. package/src/types/components/carousel.ts +25 -0
  114. package/src/types/components/chart.ts +38 -0
  115. package/src/types/components/checkbox.ts +35 -0
  116. package/src/types/components/collapsible.ts +31 -0
  117. package/src/types/components/combobox.ts +43 -0
  118. package/src/types/components/dialog.ts +39 -0
  119. package/src/types/components/drawer.ts +31 -0
  120. package/src/types/components/dropdown-menu.ts +42 -0
  121. package/src/types/components/dropzone.ts +39 -0
  122. package/src/types/components/field.ts +31 -0
  123. package/src/types/components/hover-card.ts +19 -0
  124. package/src/types/components/index.ts +51 -3
  125. package/src/types/components/input-group.ts +23 -0
  126. package/src/types/components/input.ts +59 -0
  127. package/src/types/components/kbd.ts +15 -0
  128. package/src/types/components/label.ts +19 -0
  129. package/src/types/components/localeSelector.ts +33 -0
  130. package/src/types/components/main.ts +17 -0
  131. package/src/types/components/marquee.ts +23 -0
  132. package/src/types/components/native-select.ts +39 -0
  133. package/src/types/components/navigation-menu.ts +27 -0
  134. package/src/types/components/pagination.ts +23 -0
  135. package/src/types/components/popover.ts +23 -0
  136. package/src/types/components/progress.ts +27 -0
  137. package/src/types/components/resizable.ts +19 -0
  138. package/src/types/components/scroll-area.ts +23 -0
  139. package/src/types/components/select.ts +43 -0
  140. package/src/types/components/separator.ts +19 -0
  141. package/src/types/components/sheet.ts +31 -0
  142. package/src/types/components/sidebar.ts +36 -0
  143. package/src/types/components/skeleton.ts +15 -0
  144. package/src/types/components/slider.ts +35 -0
  145. package/src/types/components/spinner.ts +19 -0
  146. package/src/types/components/sticky-surface.ts +19 -0
  147. package/src/types/components/switch.ts +35 -0
  148. package/src/types/components/table.ts +31 -0
  149. package/src/types/components/tabs.ts +43 -0
  150. package/src/types/components/textarea.ts +51 -0
  151. package/src/types/components/themeSelector.ts +15 -0
  152. package/src/types/components/toast.ts +35 -0
  153. package/src/types/components/toggle-group.ts +23 -0
  154. package/src/types/components/toggle.ts +27 -0
  155. package/src/types/components/tooltip.ts +23 -0
  156. package/src/components/ThemeToggle.astro +0 -57
@@ -0,0 +1,110 @@
1
+ ---
2
+ import { scv } from "css-variants"
3
+ import { useUi, resolveClasses } from "../../utils"
4
+ import type { LocaleSelectorProps } from "../../types"
5
+ import localeSelectorTheme from "../../themes/localeSelector.theme"
6
+ import { getRelativeLocaleUrlList, getRelativeLocaleUrl } from "astro:i18n";
7
+
8
+ const localeSelector = scv(localeSelectorTheme)
9
+
10
+ const {
11
+ locales,
12
+ variant = "default",
13
+ size = "md",
14
+ ui: uiProp,
15
+ class: className,
16
+ ...rest
17
+ } = Astro.props as LocaleSelectorProps;
18
+
19
+ const classes = resolveClasses(localeSelector, {
20
+ variant,
21
+ size
22
+ }, useUi("localeSelector", uiProp), className);
23
+
24
+ const currentLocale = Astro.currentLocale ?? 'en';
25
+ const localeUrls = [...new Map(getRelativeLocaleUrlList().map(url => {
26
+ const locale = url.split('/')[1] || 'en';
27
+ return [locale, url];
28
+ })).values()];
29
+
30
+ const processedLocales = locales && locales.length > 0
31
+ ? locales.map(item => typeof item === 'string' ? { code: item, label: item } : item)
32
+ : [...new Map(getRelativeLocaleUrlList().map(url => {
33
+ const locale = url.split('/')[1] || 'en';
34
+ return [locale, { code: locale, label: locale }];
35
+ })).values()];
36
+
37
+ function getLocaleDisplayName(localeCode: string): string {
38
+ try {
39
+ const formatter = new Intl.DisplayNames([localeCode], { type: 'language' });
40
+ const nativeName = formatter.of(localeCode);
41
+
42
+ return nativeName
43
+ ? nativeName.charAt(0).toUpperCase() + nativeName.slice(1)
44
+ : localeCode.toUpperCase();
45
+ } catch (e) {
46
+ return localeCode.toUpperCase();
47
+ }
48
+ }
49
+ ---
50
+
51
+ <div class:list={[classes.root]} {...rest}>
52
+ {Astro.slots.has("label") && (
53
+ <label for="language-picker" class:list={[classes.label]}>
54
+ <slot name="label" />
55
+ </label>
56
+ )}
57
+
58
+ <div class:list={[classes.wrapper]}>
59
+ <select
60
+ id="language-picker"
61
+ class:list={[classes.select]}
62
+ aria-label="Select language"
63
+ data-variant={variant}
64
+ data-size={size}
65
+ >
66
+ {processedLocales.map((item) => {
67
+ const targetUrl = getRelativeLocaleUrl(item.code, Astro.url.pathname.replace(/^\/[^/]+/, ''));
68
+ return (
69
+ <option
70
+ value={targetUrl}
71
+ selected={currentLocale === item.code}
72
+ class:list={[classes.option]}
73
+ >
74
+ {item.label !== item.code ? item.label : getLocaleDisplayName(item.code)}
75
+ </option>
76
+ );
77
+ })}
78
+ </select>
79
+
80
+ <div class:list={[classes.iconWrapper]}>
81
+ <slot name="icon">
82
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-4 h-4 opacity-70">
83
+ <path fill-rule="evenodd" d="M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" />
84
+ </svg>
85
+ </slot>
86
+ </div>
87
+ </div>
88
+ </div>
89
+
90
+ <script>
91
+ const initializeLanguagePicker = () => {
92
+ const languagePickers = document.querySelectorAll('#language-picker');
93
+
94
+ languagePickers.forEach(picker => {
95
+ if (picker.hasAttribute('data-initialized')) return;
96
+ picker.setAttribute('data-initialized', 'true');
97
+
98
+ picker.addEventListener('change', (event) => {
99
+ const target = event.target as HTMLSelectElement;
100
+ const targetUrl = target.value;
101
+ if (targetUrl) {
102
+ window.location.href = targetUrl;
103
+ }
104
+ });
105
+ });
106
+ };
107
+
108
+ document.addEventListener('DOMContentLoaded', initializeLanguagePicker);
109
+ document.addEventListener('astro:page-load', initializeLanguagePicker);
110
+ </script>
@@ -0,0 +1,28 @@
1
+ ---
2
+ import { scv } from "css-variants"
3
+ import { useUi, resolveClasses } from "../../utils"
4
+ import type { MainProps } from "../../types"
5
+ import mainTheme from "../../themes/main.theme"
6
+
7
+ const main = scv(mainTheme)
8
+
9
+ const {
10
+ as = "main",
11
+ ui: uiProp,
12
+ class: className,
13
+ ...rest
14
+ } = Astro.props as MainProps;
15
+
16
+ const classes = resolveClasses(main, {
17
+ hasContent: Astro.slots.has("default")
18
+ }, useUi("main", uiProp), className);
19
+
20
+ const Tag = as;
21
+ ---
22
+
23
+ <Tag
24
+ class:list={[classes.root]}
25
+ {...rest}
26
+ >
27
+ <slot />
28
+ </Tag>
@@ -0,0 +1,32 @@
1
+ ---
2
+ import { scv } from "css-variants"
3
+ import { useUi, resolveClasses } from "../../utils"
4
+ import type { MarqueeProps } from "../../types"
5
+ import marqueeTheme from "../../themes/marquee.theme"
6
+
7
+ const marquee = scv(marqueeTheme)
8
+
9
+ const {
10
+ direction = "left",
11
+ speed = 40,
12
+ pauseOnHover = true,
13
+ ui: uiProp,
14
+ class: className,
15
+ ...rest
16
+ } = Astro.props as MarqueeProps
17
+
18
+ const classes = resolveClasses(marquee, {
19
+ direction,
20
+ pauseOnHover
21
+ }, useUi("marquee", uiProp), className)
22
+
23
+ const duration = `${speed}s`
24
+ ---
25
+ <div class={classes.root} data-slot="marquee-root" {...rest}>
26
+ <div class={classes.track} data-slot="track" style={{ animationDuration: duration }}>
27
+ <slot />
28
+ </div>
29
+ <div class={classes.track} data-slot="track" aria-hidden="true" style={{ animationDuration: duration }}>
30
+ <slot />
31
+ </div>
32
+ </div>
@@ -0,0 +1,51 @@
1
+ ---
2
+ import { scv } from "css-variants"
3
+ import { useUi, resolveClasses } from "../../utils"
4
+ import type { NativeSelectProps } from "../../types"
5
+ import nativeSelectThemeDefault, { createNativeSelectTheme } from "../../themes/nativeSelect.theme"
6
+
7
+ const nativeSelectTheme = nativeSelectThemeDefault
8
+ const nativeSelect = scv(nativeSelectTheme)
9
+
10
+ const {
11
+ items = [],
12
+ value = "",
13
+ disabled = false,
14
+ name,
15
+ label,
16
+ size = "md",
17
+ color = "primary",
18
+ ui: uiProp,
19
+ class: className,
20
+ ...rest
21
+ } = Astro.props as NativeSelectProps
22
+
23
+ const classes = resolveClasses(nativeSelect, {
24
+ size
25
+ }, useUi("nativeSelect", uiProp), className);
26
+
27
+ const normalizedItems = items.map(item => {
28
+ if (typeof item === "string") {
29
+ return { label: item, value: item }
30
+ }
31
+ return item
32
+ })
33
+ ---
34
+ <div class={classes.root} data-slot="root">
35
+ {label && <label class={classes.label} data-slot="label">{label}</label>}
36
+ <div class="relative w-full">
37
+ <select
38
+ class={classes.select}
39
+ disabled={disabled}
40
+ name={name}
41
+ {...rest}
42
+ >
43
+ {normalizedItems.map(item => (
44
+ <option value={item.value} selected={item.value === value}>
45
+ {item.label}
46
+ </option>
47
+ ))}
48
+ </select>
49
+ <span class={classes.icon + " i-lucide-chevron-down"} />
50
+ </div>
51
+ </div>
@@ -0,0 +1,136 @@
1
+ ---
2
+ import { scv } from "css-variants"
3
+ import { useUi, resolveClasses } from "../../utils"
4
+ import type { NavigationMenuProps } from "../../types"
5
+ import navigationMenuThemeDefault, { createNavigationMenuTheme } from "../../themes/navigationMenu.theme"
6
+
7
+ const navigationMenuTheme = navigationMenuThemeDefault
8
+ const navigationMenu = scv(navigationMenuTheme)
9
+
10
+ const {
11
+ items = [],
12
+ color = "primary",
13
+ ui: uiProp,
14
+ class: className,
15
+ ...rest
16
+ } = Astro.props as NavigationMenuProps
17
+
18
+ const classes = resolveClasses(navigationMenu, {}, useUi("navigationMenu", uiProp), className)
19
+ ---
20
+
21
+ <nav class={classes.root} data-slot="root" data-nav-menu {...rest}>
22
+ <ul class={classes.list} data-slot="list" role="list">
23
+ {items.map((item, i) => {
24
+ const hasChildren = item.children && item.children.length > 0
25
+ return (
26
+ <li class={classes.item} data-slot="item" data-nav-item>
27
+ {hasChildren ? (
28
+ <button
29
+ type="button"
30
+ class={classes.trigger}
31
+ data-slot="trigger"
32
+ data-nav-trigger
33
+ aria-expanded="false"
34
+ aria-haspopup="true"
35
+ >
36
+ {item.icon && <span class={item.icon + " mr-1.5 size-4"} />}
37
+ {item.label}
38
+ <span class="i-lucide-chevron-down ml-1 size-3.5 transition-transform duration-200" aria-hidden="true" />
39
+ </button>
40
+ ) : (
41
+ <a
42
+ href={item.href ?? "#"}
43
+ class={classes.link}
44
+ data-slot="link"
45
+ >
46
+ {item.icon && <span class={item.icon + " mr-1.5 size-4"} />}
47
+ {item.label}
48
+ </a>
49
+ )}
50
+
51
+ {hasChildren && (
52
+ <div class={classes.content + " hidden"} data-slot="content" data-nav-content role="region">
53
+ <ul role="list" class="py-1">
54
+ {item.children!.map(child => (
55
+ <li>
56
+ <a
57
+ href={child.href ?? "#"}
58
+ class="flex items-start gap-3 rounded-sm px-3 py-2 text-sm hover:bg-accent hover:text-accent-foreground transition-colors"
59
+ >
60
+ {child.icon && <span class={child.icon + " mt-0.5 size-4 shrink-0 text-muted-foreground"} />}
61
+ <div>
62
+ <div class="font-medium leading-none">{child.label}</div>
63
+ {child.description && (
64
+ <p class="mt-1 text-xs text-muted-foreground line-clamp-2">{child.description}</p>
65
+ )}
66
+ </div>
67
+ </a>
68
+ </li>
69
+ ))}
70
+ </ul>
71
+ </div>
72
+ )}
73
+ </li>
74
+ )
75
+ })}
76
+ </ul>
77
+
78
+ <slot />
79
+
80
+ <div class={classes.viewport} data-slot="viewport" />
81
+ </nav>
82
+
83
+ <script>
84
+ document.querySelectorAll("[data-nav-menu]").forEach(menu => {
85
+ const items = menu.querySelectorAll("[data-nav-item]");
86
+
87
+ items.forEach(item => {
88
+ const trigger = item.querySelector("[data-nav-trigger]");
89
+ const content = item.querySelector("[data-nav-content]");
90
+
91
+ if (!trigger || !content) return;
92
+
93
+ const open = () => {
94
+ content.classList.remove("hidden");
95
+ trigger.setAttribute("aria-expanded", "true");
96
+ const icon = trigger.querySelector(".i-lucide-chevron-down");
97
+ if (icon) (icon as HTMLElement).style.transform = "rotate(180deg)";
98
+ };
99
+
100
+ const close = () => {
101
+ content.classList.add("hidden");
102
+ trigger.setAttribute("aria-expanded", "false");
103
+ const icon = trigger.querySelector(".i-lucide-chevron-down");
104
+ if (icon) (icon as HTMLElement).style.transform = "";
105
+ };
106
+
107
+ trigger.addEventListener("click", (e) => {
108
+ e.stopPropagation();
109
+ const isOpen = !content.classList.contains("hidden");
110
+ // Close all others
111
+ items.forEach(other => {
112
+ const otherContent = other.querySelector("[data-nav-content]");
113
+ const otherTrigger = other.querySelector("[data-nav-trigger]");
114
+ if (otherContent && !otherContent.classList.contains("hidden")) {
115
+ otherContent.classList.add("hidden");
116
+ otherTrigger?.setAttribute("aria-expanded", "false");
117
+ const icon = otherTrigger?.querySelector(".i-lucide-chevron-down");
118
+ if (icon) (icon as HTMLElement).style.transform = "";
119
+ }
120
+ });
121
+ if (!isOpen) open();
122
+ });
123
+ });
124
+
125
+ document.addEventListener("click", () => {
126
+ items.forEach(item => {
127
+ const content = item.querySelector("[data-nav-content]");
128
+ const trigger = item.querySelector("[data-nav-trigger]");
129
+ if (content) content.classList.add("hidden");
130
+ if (trigger) trigger.setAttribute("aria-expanded", "false");
131
+ const icon = trigger?.querySelector(".i-lucide-chevron-down");
132
+ if (icon) (icon as HTMLElement).style.transform = "";
133
+ });
134
+ });
135
+ });
136
+ </script>
@@ -0,0 +1,94 @@
1
+ ---
2
+ import { scv } from "css-variants"
3
+ import { useUi, resolveClasses } from "../../utils"
4
+ import type { PaginationProps } from "../../types"
5
+ import paginationTheme from "../../themes/pagination.theme"
6
+
7
+ const pagination = scv(paginationTheme)
8
+
9
+ const {
10
+ currentPage = 1,
11
+ totalPages = 1,
12
+ baseUrl = "?page=",
13
+ ui: uiProp,
14
+ class: className,
15
+ ...rest
16
+ } = Astro.props as PaginationProps
17
+
18
+ const classes = resolveClasses(pagination, {}, useUi("pagination", uiProp), className)
19
+
20
+ const getPageNumbers = () => {
21
+ const pages: (number | "ellipsis")[] = []
22
+ const maxVisible = 5
23
+ if (totalPages <= maxVisible) {
24
+ for (let i = 1; i <= totalPages; i++) pages.push(i)
25
+ } else {
26
+ pages.push(1)
27
+ if (currentPage > 3) pages.push("ellipsis")
28
+ const start = Math.max(2, currentPage - 1)
29
+ const end = Math.min(totalPages - 1, currentPage + 1)
30
+ for (let i = start; i <= end; i++) {
31
+ if (!pages.includes(i)) pages.push(i)
32
+ }
33
+ if (currentPage < totalPages - 2) pages.push("ellipsis")
34
+ if (!pages.includes(totalPages)) pages.push(totalPages)
35
+ }
36
+ return pages
37
+ }
38
+
39
+ const pages = getPageNumbers()
40
+ ---
41
+ <nav class={classes.root} data-slot="pagination-root" aria-label="pagination" {...rest}>
42
+ <ul class={classes.list} data-slot="list">
43
+ <li class={classes.item}>
44
+ <a
45
+ href={currentPage > 1 ? `${baseUrl}${currentPage - 1}` : undefined}
46
+ class={classes.link}
47
+ aria-label="Go to previous page"
48
+ aria-disabled={currentPage === 1}
49
+ style={currentPage === 1 ? "pointer-events: none; opacity: 0.5;" : ""}
50
+ >
51
+ <span class="i-lucide-chevron-left size-4" aria-hidden="true" />
52
+ </a>
53
+ </li>
54
+
55
+ {pages.map((p) => {
56
+ if (p === "ellipsis") {
57
+ return (
58
+ <li class={classes.item}>
59
+ <span class={classes.ellipsis} aria-hidden="true">
60
+ &hellip;
61
+ </span>
62
+ </li>
63
+ )
64
+ }
65
+
66
+ const isActive = p === currentPage
67
+ const itemClasses = resolveClasses(pagination, { active: isActive }, useUi("pagination", uiProp))
68
+
69
+ return (
70
+ <li class={classes.item}>
71
+ <a
72
+ href={`${baseUrl}${p}`}
73
+ class={itemClasses.link}
74
+ aria-current={isActive ? "page" : undefined}
75
+ >
76
+ {p}
77
+ </a>
78
+ </li>
79
+ )
80
+ })}
81
+
82
+ <li class={classes.item}>
83
+ <a
84
+ href={currentPage < totalPages ? `${baseUrl}${currentPage + 1}` : undefined}
85
+ class={classes.link}
86
+ aria-label="Go to next page"
87
+ aria-disabled={currentPage === totalPages}
88
+ style={currentPage === totalPages ? "pointer-events: none; opacity: 0.5;" : ""}
89
+ >
90
+ <span class="i-lucide-chevron-right size-4" aria-hidden="true" />
91
+ </a>
92
+ </li>
93
+ </ul>
94
+ </nav>
@@ -0,0 +1,31 @@
1
+ ---
2
+ import { scv } from "css-variants"
3
+ import { useUi, resolveClasses } from "../../utils"
4
+ import type { PopoverProps } from "../../types"
5
+ import popoverTheme from "../../themes/popover.theme"
6
+
7
+ const popover = scv(popoverTheme)
8
+
9
+ const {
10
+ triggerLabel,
11
+ placement = "bottom",
12
+ ui: uiProp,
13
+ class: className,
14
+ ...rest
15
+ } = Astro.props as PopoverProps
16
+
17
+ const classes = resolveClasses(popover, {
18
+ placement
19
+ }, useUi("popover", uiProp), className)
20
+ ---
21
+ <div class={classes.root} data-slot="popover-container" {...rest}>
22
+ <div class={classes.trigger} data-slot="trigger" tabindex="0">
23
+ <slot name="trigger">
24
+ {triggerLabel && <button type="button" class="cursor-pointer">{triggerLabel}</button>}
25
+ </slot>
26
+ </div>
27
+
28
+ <div class={classes.content} data-slot="content">
29
+ <slot />
30
+ </div>
31
+ </div>
@@ -0,0 +1,43 @@
1
+ ---
2
+ import { scv } from "css-variants"
3
+ import { useUi, resolveClasses } from "../../utils"
4
+ import type { ProgressProps } from "../../types"
5
+ import progressThemeDefault, { createProgressTheme } from "../../themes/progress.theme"
6
+ import { getUIConfig } from "virtual:rimelight-ui"
7
+
8
+ const uiConfig = getUIConfig()
9
+ const progressTheme = uiConfig.colors ? createProgressTheme(uiConfig.colors) : progressThemeDefault
10
+ const progress = scv(progressTheme)
11
+
12
+ const {
13
+ value = 0,
14
+ max = 100,
15
+ color = "primary",
16
+ size = "md",
17
+ ui: uiProp,
18
+ class: className,
19
+ ...rest
20
+ } = Astro.props as ProgressProps
21
+
22
+ const classes = resolveClasses(progress, {
23
+ color,
24
+ size
25
+ }, useUi("progress", uiProp), className)
26
+
27
+ const percentage = Math.min(100, Math.max(0, (value / max) * 100))
28
+ ---
29
+ <div
30
+ class={classes.root}
31
+ data-slot="progress-root"
32
+ role="progressbar"
33
+ aria-valuemin={0}
34
+ aria-valuemax={max}
35
+ aria-valuenow={value}
36
+ {...rest}
37
+ >
38
+ <div
39
+ class={classes.indicator}
40
+ data-slot="indicator"
41
+ style={{ transform: `translateX(-${100 - percentage}%)` }}
42
+ />
43
+ </div>