@rimelight/ui 0.0.34 → 0.0.36

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 (185) hide show
  1. package/README.md +1 -0
  2. package/package.json +19 -24
  3. package/src/components/astro/RLAAccordion.astro +94 -18
  4. package/src/components/astro/RLAAvatar.astro +135 -68
  5. package/src/components/astro/RLABadge.astro +4 -2
  6. package/src/components/astro/RLABanner.astro +138 -23
  7. package/src/components/astro/RLABreadcrumb.astro +13 -0
  8. package/src/components/astro/RLAButton.astro +8 -4
  9. package/src/components/astro/RLACallout.astro +112 -0
  10. package/src/components/astro/RLACard.astro +6 -5
  11. package/src/components/astro/RLACarousel.astro +104 -75
  12. package/src/components/astro/RLAChart.astro +4 -1
  13. package/src/components/astro/RLAChip.astro +11 -5
  14. package/src/components/astro/RLACollapsible.astro +4 -1
  15. package/src/components/astro/RLAColorArea.astro +432 -0
  16. package/src/components/astro/RLAColorField.astro +300 -0
  17. package/src/components/astro/RLAColorSlider.astro +413 -0
  18. package/src/components/astro/RLAConfirm.astro +13 -11
  19. package/src/components/astro/RLACopyMarkdown.astro +78 -0
  20. package/src/components/astro/RLADate.astro +30 -0
  21. package/src/components/astro/RLADrawer.astro +50 -3
  22. package/src/components/astro/RLADropdownMenu.astro +78 -51
  23. package/src/components/astro/RLAFieldGroup.astro +4 -1
  24. package/src/components/astro/RLAFileUpload.astro +114 -100
  25. package/src/components/astro/RLAFooter.astro +2 -1
  26. package/src/components/astro/RLAFormField.astro +10 -6
  27. package/src/components/astro/RLAGrid.astro +31 -39
  28. package/src/components/astro/RLAHead.astro +139 -39
  29. package/src/components/astro/RLAHeader.astro +2 -1
  30. package/src/components/astro/RLAImage.astro +274 -251
  31. package/src/components/astro/RLAInput.astro +14 -9
  32. package/src/components/astro/RLAInputMenu.astro +119 -83
  33. package/src/components/astro/RLAKbd.astro +5 -5
  34. package/src/components/astro/RLALayoutGrid.astro +395 -0
  35. package/src/components/astro/RLALink.astro +23 -1
  36. package/src/components/astro/RLALinkGroup.astro +99 -99
  37. package/src/components/astro/RLALocaleSelector.astro +34 -41
  38. package/src/components/astro/RLALogo.astro +117 -90
  39. package/src/components/astro/RLAModal.astro +48 -18
  40. package/src/components/astro/RLANavigationMenu.astro +381 -326
  41. package/src/components/astro/{RLADocsPackageManagers.astro → RLAPackageManagers.astro} +81 -87
  42. package/src/components/astro/RLAPageSection.astro +4 -2
  43. package/src/components/astro/RLAPopover.astro +4 -3
  44. package/src/components/astro/RLAPost.astro +11 -2
  45. package/src/components/astro/RLAScrollArea.astro +4 -1
  46. package/src/components/astro/RLAScrollToTop.astro +200 -172
  47. package/src/components/astro/RLASearch.astro +282 -0
  48. package/src/components/astro/RLASelect.astro +78 -55
  49. package/src/components/astro/RLASeparator.astro +11 -6
  50. package/src/components/astro/RLAShare.astro +60 -0
  51. package/src/components/astro/RLAShortcuts.astro +429 -0
  52. package/src/components/astro/RLASidebar.astro +158 -212
  53. package/src/components/astro/RLASlideover.astro +47 -17
  54. package/src/components/astro/RLASplitter.astro +194 -141
  55. package/src/components/astro/RLASteps.astro +118 -71
  56. package/src/components/astro/RLASurround.astro +39 -0
  57. package/src/components/astro/RLATable.astro +4 -1
  58. package/src/components/astro/RLATableOfContents.astro +109 -23
  59. package/src/components/astro/RLATabs.astro +147 -133
  60. package/src/components/astro/RLATextarea.astro +4 -1
  61. package/src/components/astro/RLAThemeSelector.astro +105 -76
  62. package/src/components/astro/RLAToast.astro +35 -21
  63. package/src/components/vue/RLVBanner.vue +230 -0
  64. package/src/components/vue/RLVButton.vue +3 -2
  65. package/src/components/vue/RLVCheckbox.vue +4 -2
  66. package/src/components/vue/RLVFooter.vue +3 -2
  67. package/src/components/vue/RLVHeader.vue +3 -2
  68. package/src/components/vue/RLVIcon.vue +4 -2
  69. package/src/components/vue/RLVInput.vue +5 -4
  70. package/src/components/vue/RLVLogo.vue +25 -3
  71. package/src/components/vue/RLVPlaceholder.vue +3 -2
  72. package/src/components/vue/RLVPost.vue +8 -2
  73. package/src/components/vue/RLVProgress.vue +60 -0
  74. package/src/components/vue/RLVScrollToTop.vue +65 -52
  75. package/src/components/vue/RLVSection.vue +14 -13
  76. package/src/components/vue/RLVToast.vue +17 -4
  77. package/src/composables/index.ts +1 -0
  78. package/src/composables/useHeaderStore.ts +1 -0
  79. package/src/composables/useShortcuts.ts +11 -0
  80. package/src/config/security.ts +43 -36
  81. package/src/config/site.config.ts +1 -0
  82. package/src/docs/components/ApiChangelog.astro +147 -0
  83. package/src/{plugins/starlightDocsApi → docs}/components/ApiEmits.astro +4 -4
  84. package/src/{plugins/starlightDocsApi → docs}/components/ApiProps.astro +4 -4
  85. package/src/{plugins/starlightDocsApi → docs}/components/ApiSlots.astro +4 -4
  86. package/src/docs/components/ApiTheme.astro +100 -0
  87. package/src/docs/extractAll.ts +94 -0
  88. package/src/docs/extractors/extractAstro.ts +69 -0
  89. package/src/docs/extractors/extractTheme.ts +56 -0
  90. package/src/{plugins/starlightDocsApi/extract-vue.ts → docs/extractors/extractVue.ts} +164 -15
  91. package/src/{plugins/starlightDocsApi → docs}/utils.ts +1 -2
  92. package/src/env.d.ts +0 -12
  93. package/src/integrations/ui.ts +35 -19
  94. package/src/middleware/security.ts +75 -19
  95. package/src/presets/index.ts +118 -293
  96. package/src/styles/index.css +0 -2
  97. package/src/themes/accordion.theme.ts +29 -3
  98. package/src/themes/aspect-ratio.theme.ts +1 -1
  99. package/src/themes/avatar-group.theme.ts +1 -1
  100. package/src/themes/avatar.theme.ts +2 -2
  101. package/src/themes/badge.theme.ts +2 -3
  102. package/src/themes/banner.theme.ts +40 -4
  103. package/src/themes/breadcrumb.theme.ts +1 -1
  104. package/src/themes/button.theme.ts +21 -22
  105. package/src/themes/{alert.theme.ts → callout.theme.ts} +12 -39
  106. package/src/themes/card.theme.ts +17 -9
  107. package/src/themes/carousel.theme.ts +1 -1
  108. package/src/themes/checkbox.theme.ts +1 -2
  109. package/src/themes/chip.theme.ts +2 -3
  110. package/src/themes/color-area.theme.ts +33 -0
  111. package/src/themes/color-field.theme.ts +32 -0
  112. package/src/themes/color-slider.theme.ts +34 -0
  113. package/src/themes/confirm.theme.ts +1 -1
  114. package/src/themes/container.theme.ts +1 -1
  115. package/src/themes/drawer.theme.ts +1 -1
  116. package/src/themes/footer.theme.ts +2 -2
  117. package/src/themes/grid.theme.ts +38 -0
  118. package/src/themes/header.theme.ts +4 -3
  119. package/src/themes/hover-card.theme.ts +1 -1
  120. package/src/themes/image.theme.ts +11 -1
  121. package/src/themes/input.theme.ts +7 -1
  122. package/src/themes/kbd.theme.ts +2 -3
  123. package/src/themes/label.theme.ts +1 -1
  124. package/src/themes/layout-grid.theme.ts +16 -0
  125. package/src/themes/link-group.theme.ts +0 -4
  126. package/src/themes/marquee.theme.ts +1 -1
  127. package/src/themes/modal.theme.ts +1 -1
  128. package/src/themes/navigation-menu.theme.ts +2 -2
  129. package/src/themes/page-section.theme.ts +4 -2
  130. package/src/themes/pagination.theme.ts +1 -1
  131. package/src/themes/pin-input.theme.ts +1 -1
  132. package/src/themes/popover.theme.ts +1 -1
  133. package/src/themes/post.theme.ts +23 -3
  134. package/src/themes/progress.theme.ts +1 -2
  135. package/src/themes/scroll-to-top.theme.ts +2 -3
  136. package/src/themes/search.theme.ts +64 -0
  137. package/src/themes/separator.theme.ts +1 -1
  138. package/src/themes/slideover.theme.ts +1 -1
  139. package/src/themes/slider.theme.ts +1 -2
  140. package/src/themes/spinner.theme.ts +1 -2
  141. package/src/themes/{megamenu.theme.ts → steps.theme.ts} +3 -3
  142. package/src/themes/sticky-surface.theme.ts +1 -1
  143. package/src/themes/switch.theme.ts +1 -2
  144. package/src/themes/table-of-contents.theme.ts +21 -2
  145. package/src/themes/timeline.theme.ts +7 -2
  146. package/src/themes/toast.theme.ts +1 -1
  147. package/src/types/components/accordion.ts +35 -2
  148. package/src/types/components/avatar.ts +16 -0
  149. package/src/types/components/banner.ts +42 -0
  150. package/src/types/components/button.ts +3 -4
  151. package/src/types/components/{alert.ts → callout.ts} +6 -6
  152. package/src/types/components/color-area.ts +19 -0
  153. package/src/types/components/color-field.ts +21 -0
  154. package/src/types/components/color-slider.ts +20 -0
  155. package/src/types/components/grid.ts +23 -0
  156. package/src/types/components/input.ts +4 -0
  157. package/src/types/components/layout-grid.ts +145 -0
  158. package/src/types/components/link-group.ts +4 -2
  159. package/src/types/components/link.ts +15 -0
  160. package/src/types/components/logo.ts +3 -3
  161. package/src/types/components/post.ts +12 -0
  162. package/src/types/components/search.ts +29 -0
  163. package/src/types/components/sidebar.ts +2 -6
  164. package/src/types/components/{megamenu.ts → steps.ts} +7 -1
  165. package/src/types/components/table-of-contents.ts +22 -0
  166. package/src/types/components/toast.ts +4 -0
  167. package/src/types/docs.ts +40 -0
  168. package/src/types/index.ts +151 -1
  169. package/src/types/theme.ts +6 -6
  170. package/src/utils/color.ts +165 -0
  171. package/src/utils/docs.ts +260 -110
  172. package/src/utils/headerStack.ts +24 -4
  173. package/src/utils/index.ts +2 -0
  174. package/src/utils/shortcuts.ts +322 -0
  175. package/src/components/TableOfContents.astro +0 -107
  176. package/src/components/astro/RLAAlert.astro +0 -93
  177. package/src/components/astro/RLAChangelog.astro +0 -23
  178. package/src/components/astro/RLAMegamenu.astro +0 -23
  179. package/src/plugins/index.ts +0 -2
  180. package/src/plugins/starlightDocsApi/components/ApiTheme.astro +0 -27
  181. package/src/plugins/starlightDocsApi/index.ts +0 -272
  182. package/src/styles/prism.css +0 -42
  183. package/src/themes/changelog.theme.ts +0 -13
  184. package/src/types/components/index.ts +0 -134
  185. /package/src/{plugins/starlightDocsApi → docs}/types.ts +0 -0
@@ -4,7 +4,10 @@ import { useUi, resolveClasses } from "../../utils"
4
4
  import type { ToastProps } from "../../types"
5
5
  import toastThemeDefault, { createToastTheme } from "../../themes/toast.theme"
6
6
 
7
- const toastTheme = toastThemeDefault
7
+ import { getUIConfig } from "virtual:rimelight-ui"
8
+
9
+ const uiConfig = getUIConfig()
10
+ const toastTheme = uiConfig.colors ? createToastTheme() : toastThemeDefault
8
11
  const toast = scv(toastTheme)
9
12
 
10
13
  const {
@@ -16,11 +19,12 @@ const {
16
19
  color = "primary",
17
20
  ui: uiProp,
18
21
  class: className,
22
+ dismissable = true,
19
23
  ...rest
20
24
  } = Astro.props as ToastProps
21
25
 
22
26
  const classes = resolveClasses(toast, {
23
- variant
27
+ variant: (variant === "success" || variant === "destructive") ? variant : "default"
24
28
  }, useUi("toast", uiProp), className)
25
29
 
26
30
  const variantIcons: Record<string, string> = {
@@ -39,6 +43,7 @@ const icon = variantIcons[variant] ?? variantIcons.default!
39
43
  data-slot="root"
40
44
  data-toast
41
45
  data-duration={duration}
46
+ data-dismissable={dismissable.toString()}
42
47
  role="alert"
43
48
  aria-live="assertive"
44
49
  aria-atomic="true"
@@ -49,45 +54,54 @@ const icon = variantIcons[variant] ?? variantIcons.default!
49
54
 
50
55
  {/* Text body */}
51
56
  <div class="flex flex-col gap-0.5 flex-1 min-w-0">
52
- {title && (
57
+ {(title || Astro.slots.has("title")) && (
53
58
  <div class={classes.title} data-slot="title">
54
59
  <slot name="title">{title}</slot>
55
60
  </div>
56
61
  )}
57
- {description && (
62
+ {(description || Astro.slots.has("description")) && (
58
63
  <div class={classes.description} data-slot="description">
59
64
  <slot name="description">{description}</slot>
60
65
  </div>
61
66
  )}
62
67
  <slot />
68
+ {(Astro.slots.has("actions") || actionLabel) && (
69
+ <div class="flex items-center justify-end gap-2 mt-3" data-slot="actions">
70
+ <slot name="actions">
71
+ {actionLabel && (
72
+ <button
73
+ type="button"
74
+ class={classes.action}
75
+ data-slot="action"
76
+ data-toast-action
77
+ >
78
+ {actionLabel}
79
+ </button>
80
+ )}
81
+ </slot>
82
+ </div>
83
+ )}
63
84
  </div>
64
85
 
65
- {/* Action */}
66
- {actionLabel && (
86
+ {/* Close button */}
87
+ {dismissable !== false && (
67
88
  <button
68
89
  type="button"
69
- class={classes.action}
70
- data-slot="action"
71
- data-toast-action
90
+ class={classes.close}
91
+ data-slot="close"
92
+ data-toast-close
93
+ aria-label="Dismiss notification"
72
94
  >
73
- {actionLabel}
95
+ <span class="i-lucide-x size-3.5" aria-hidden="true" />
74
96
  </button>
75
97
  )}
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
98
  </div>
88
99
 
89
100
  <script>
90
101
  document.querySelectorAll("[data-toast]").forEach(toast => {
102
+ const dismissable = toast.getAttribute("data-dismissable") !== "false";
103
+ if (!dismissable) return;
104
+
91
105
  const close = toast.querySelector("[data-toast-close]");
92
106
  const duration = parseInt((toast as HTMLElement).dataset.duration ?? "5000", 10);
93
107
 
@@ -0,0 +1,230 @@
1
+ <script setup lang="ts">
2
+ import { computed, onMounted, onUnmounted, ref, useAttrs } from "vue"
3
+ import { scv } from "css-variants"
4
+ import { useUi, resolveClasses } from "../../utils"
5
+ import type { BannerProps } from "../../types/components/banner"
6
+ import bannerTheme from "../../themes/banner.theme"
7
+ import { getHeaderStack } from "../../utils/headerStack"
8
+
9
+ const attrs = useAttrs()
10
+ const banner = scv(bannerTheme)
11
+
12
+ const {
13
+ contain = true,
14
+ sticky = false,
15
+ fixed = true,
16
+ stackIndex = 0,
17
+ hideOnScroll = true,
18
+ dismissable = false,
19
+ dismissId,
20
+ actions = [],
21
+ ui: uiProp,
22
+ class: className
23
+ } = defineProps<BannerProps>()
24
+
25
+ defineSlots<{
26
+ default(props: {}): any
27
+ left(props: {}): any
28
+ center(props: {}): any
29
+ right(props: {}): any
30
+ actions(props: {}): any
31
+ }>()
32
+
33
+ const resolvedClasses = computed(() =>
34
+ resolveClasses(banner, { contain, sticky, fixed }, useUi("banner", uiProp), className)
35
+ )
36
+
37
+ const id = `rlv-banner-${Math.random().toString(36).slice(2, 8)}`
38
+ const storageKey = dismissId || id
39
+ const rootRef = ref<HTMLElement | null>(null)
40
+ const contentRef = ref<HTMLElement | null>(null)
41
+ const naturalHeight = ref(0)
42
+ const isVisible = ref(true)
43
+ const closed = ref(false)
44
+ const showActions = ref(false)
45
+
46
+ const fixedStyle = computed(() => {
47
+ if (!fixed) return {}
48
+ return {
49
+ zIndex: 200 - stackIndex
50
+ }
51
+ })
52
+
53
+ let resizeObserver: ResizeObserver | null = null
54
+ let scrollHandler: (() => void) | null = null
55
+
56
+ onMounted(() => {
57
+ if (dismissable) {
58
+ const stored = localStorage.getItem(`rl-banner-dismiss-${storageKey}`)
59
+ if (stored === "true") {
60
+ closed.value = true
61
+ return
62
+ }
63
+ }
64
+
65
+ if (!fixed) return
66
+
67
+ const stack = getHeaderStack()
68
+
69
+ const updateStack = () => {
70
+ stack.register(id, stackIndex, naturalHeight.value, isVisible.value, rootRef.value, "banner")
71
+ }
72
+
73
+ if (contentRef.value) {
74
+ naturalHeight.value = contentRef.value.getBoundingClientRect().height
75
+ resizeObserver = new ResizeObserver((entries) => {
76
+ const h = entries[0]?.contentRect.height
77
+ if (h && h > 0) {
78
+ naturalHeight.value = h
79
+ updateStack()
80
+ }
81
+ })
82
+ resizeObserver.observe(contentRef.value)
83
+ }
84
+
85
+ if (hideOnScroll) {
86
+ let localLastScrollY = window.scrollY
87
+ scrollHandler = () => {
88
+ const current = window.scrollY
89
+ const diff = current - localLastScrollY
90
+
91
+ if (Math.abs(diff) < 10) return
92
+
93
+ const newVisible = current <= 50 ? true : diff <= 0
94
+ if (newVisible !== isVisible.value) {
95
+ isVisible.value = newVisible
96
+ updateStack()
97
+ }
98
+
99
+ localLastScrollY = current
100
+ }
101
+
102
+ window.addEventListener("scroll", scrollHandler, { passive: true })
103
+ }
104
+
105
+ updateStack()
106
+ })
107
+
108
+ onUnmounted(() => {
109
+ resizeObserver?.disconnect()
110
+ if (scrollHandler) window.removeEventListener("scroll", scrollHandler)
111
+ if (fixed) getHeaderStack().unregister(id)
112
+ })
113
+
114
+ function handleClose() {
115
+ localStorage.setItem(`rl-banner-dismiss-${storageKey}`, "true")
116
+ closed.value = true
117
+ if (fixed) getHeaderStack().unregister(id)
118
+ }
119
+
120
+ function handleActionClick(action: any) {
121
+ if (action.onClick) action.onClick()
122
+ }
123
+ </script>
124
+
125
+ <template>
126
+ <div
127
+ v-if="!closed"
128
+ ref="rootRef"
129
+ :id="id"
130
+ :class="[resolvedClasses.root]"
131
+ :style="fixedStyle"
132
+ data-slot="root"
133
+ v-bind="attrs"
134
+ >
135
+ <div ref="contentRef" :class="resolvedClasses.content">
136
+ <div :class="resolvedClasses.container">
137
+ <div v-show="!showActions" :class="resolvedClasses.left" data-slot="left">
138
+ <slot name="left" />
139
+ </div>
140
+ <div v-show="!showActions" :class="resolvedClasses.center" data-slot="center">
141
+ <slot name="center">
142
+ <slot />
143
+ </slot>
144
+ </div>
145
+
146
+ <div class="flex-1"></div>
147
+
148
+ <div :class="resolvedClasses.side">
149
+ <slot name="right" />
150
+ </div>
151
+
152
+ <template v-if="actions.length > 0 || !!$slots.actions">
153
+ <button
154
+ class="flex-none flex items-center justify-center size-7 rounded-md hover:bg-black/10 dark:hover:bg-white/10 cursor-pointer md:hidden text-sm leading-none"
155
+ :class="showActions ? 'order-first' : ''"
156
+ :aria-label="showActions ? 'Hide actions' : 'Show actions'"
157
+ @click="showActions = !showActions"
158
+ >
159
+ ···
160
+ </button>
161
+ <div
162
+ :class="[
163
+ resolvedClasses.actions,
164
+ 'flex-row items-center justify-center gap-2',
165
+ showActions ? 'flex order-first' : 'hidden',
166
+ 'md:flex'
167
+ ]"
168
+ >
169
+ <slot name="actions">
170
+ <template v-for="(action, i) in actions" :key="i">
171
+ <a
172
+ v-if="action.href"
173
+ :key="`a-${i}`"
174
+ :href="action.href"
175
+ :class="[
176
+ 'inline-flex items-center justify-center gap-1 px-3 py-1 rounded-md text-xs font-semibold transition-colors no-underline cursor-pointer shrink-0',
177
+ action.variant === 'solid' || !action.variant
178
+ ? 'bg-foreground text-background hover:opacity-90'
179
+ : 'bg-white/20 text-white hover:bg-white/30',
180
+ action.class
181
+ ]"
182
+ @click="handleActionClick(action)"
183
+ >
184
+ {{ action.label }}
185
+ </a>
186
+ <button
187
+ v-else
188
+ :key="`b-${i}`"
189
+ :class="[
190
+ 'inline-flex items-center justify-center gap-1 px-3 py-1 rounded-md text-xs font-semibold transition-colors cursor-pointer shrink-0',
191
+ action.variant === 'solid' || !action.variant
192
+ ? 'bg-foreground text-background hover:opacity-90'
193
+ : 'bg-white/20 text-white hover:bg-white/30',
194
+ action.class
195
+ ]"
196
+ @click="handleActionClick(action)"
197
+ >
198
+ {{ action.label }}
199
+ </button>
200
+ </template>
201
+ </slot>
202
+ </div>
203
+ </template>
204
+
205
+ <button
206
+ v-if="dismissable"
207
+ :class="[resolvedClasses.dismiss]"
208
+ aria-label="Close banner"
209
+ type="button"
210
+ @click="handleClose"
211
+ >
212
+ <svg
213
+ xmlns="http://www.w3.org/2000/svg"
214
+ width="14"
215
+ height="14"
216
+ viewBox="0 0 24 24"
217
+ fill="none"
218
+ stroke="currentColor"
219
+ stroke-width="2"
220
+ stroke-linecap="round"
221
+ stroke-linejoin="round"
222
+ >
223
+ <line x1="18" y1="6" x2="6" y2="18" />
224
+ <line x1="6" y1="6" x2="18" y2="18" />
225
+ </svg>
226
+ </button>
227
+ </div>
228
+ </div>
229
+ </div>
230
+ </template>
@@ -1,10 +1,11 @@
1
1
  <script setup lang="ts">
2
- import { computed, useSlots } from "vue"
2
+ import { computed, useSlots, useAttrs } from "vue"
3
3
  import { scv } from "css-variants"
4
4
  import { useUi, resolveClasses } from "../../utils"
5
5
  import type { ButtonProps } from "../../types/components/button"
6
6
  import buttonTheme from "../../themes/button.theme"
7
7
 
8
+ const attrs = useAttrs()
8
9
  const button = scv(buttonTheme)
9
10
 
10
11
  const {
@@ -79,7 +80,7 @@ const Tag = href ? "a" : "button"
79
80
  </script>
80
81
 
81
82
  <template>
82
- <component v-bind="$attrs" :is="Tag" :href="href" :class="resolvedClasses.root" data-slot="root">
83
+ <component v-bind="attrs" :is="Tag" :href="href" :class="resolvedClasses.root" data-slot="root">
83
84
  <slot name="leading" :ui="resolvedClasses">
84
85
  <span v-if="isLeading" :class="resolvedClasses.leadingIcon" data-slot="leading-icon">
85
86
  <span :class="[showLeadingIcon, leadingIconClass]" aria-hidden="true" />
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { computed } from "vue"
2
+ import { computed, useAttrs } from "vue"
3
3
  import { scv } from "css-variants"
4
4
  import { useUi, resolveClasses } from "../../utils"
5
5
  import type { CheckboxProps } from "../../types/components/checkbox"
@@ -22,6 +22,8 @@ const checked = computed({
22
22
  set: (val) => emit("update:modelValue", val)
23
23
  })
24
24
 
25
+ const attrs = useAttrs()
26
+
25
27
  const resolvedClasses = computed(() =>
26
28
  resolveClasses(
27
29
  checkbox,
@@ -47,7 +49,7 @@ function onChange(event: Event) {
47
49
  <label :class="resolvedClasses.root" data-slot="root">
48
50
  <div :class="resolvedClasses.container" data-slot="container">
49
51
  <input
50
- v-bind="$attrs"
52
+ v-bind="attrs"
51
53
  type="checkbox"
52
54
  :name="name"
53
55
  :checked="checked"
@@ -1,10 +1,11 @@
1
1
  <script setup lang="ts">
2
- import { computed } from "vue"
2
+ import { computed, useAttrs } from "vue"
3
3
  import { scv } from "css-variants"
4
4
  import { useUi, resolveClasses } from "../../utils"
5
5
  import type { FooterProps } from "../../types/components/footer"
6
6
  import footerTheme from "../../themes/footer.theme"
7
7
 
8
+ const attrs = useAttrs()
8
9
  const footer = scv(footerTheme)
9
10
 
10
11
  const { contain = false, ui: uiProp, class: className } = defineProps<FooterProps>()
@@ -21,7 +22,7 @@ const resolvedClasses = computed(() =>
21
22
  </script>
22
23
 
23
24
  <template>
24
- <footer :class="[resolvedClasses.root]" data-slot="root" v-bind="$attrs">
25
+ <footer :class="[resolvedClasses.root]" data-slot="root" v-bind="attrs">
25
26
  <div :class="resolvedClasses.container">
26
27
  <div :class="resolvedClasses.left" data-slot="left">
27
28
  <slot name="left" />
@@ -1,11 +1,12 @@
1
1
  <script setup lang="ts">
2
- import { computed, onMounted, onUnmounted, ref } from "vue"
2
+ import { computed, onMounted, onUnmounted, ref, useAttrs } from "vue"
3
3
  import { scv } from "css-variants"
4
4
  import { useUi, resolveClasses } from "../../utils"
5
5
  import type { HeaderProps } from "../../types/components/header"
6
6
  import headerTheme from "../../themes/header.theme"
7
7
  import { getHeaderStack } from "../../utils/headerStack"
8
8
 
9
+ const attrs = useAttrs()
9
10
  const header = scv(headerTheme)
10
11
 
11
12
  const {
@@ -102,7 +103,7 @@ onUnmounted(() => {
102
103
  :class="[resolvedClasses.root]"
103
104
  :style="fixedStyle"
104
105
  data-slot="root"
105
- v-bind="$attrs"
106
+ v-bind="attrs"
106
107
  >
107
108
  <div ref="contentRef" :class="resolvedClasses.content">
108
109
  <div :class="resolvedClasses.container">
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { computed } from "vue"
2
+ import { computed, useAttrs } from "vue"
3
3
  import { scv } from "css-variants"
4
4
  import { useUi, resolveClasses } from "../../utils"
5
5
  import type { IconProps } from "../../types/components/icon"
@@ -9,6 +9,8 @@ const icon = scv(iconTheme)
9
9
 
10
10
  const { name, size = "md", ui: uiProp, class: className } = defineProps<IconProps>()
11
11
 
12
+ const attrs = useAttrs()
13
+
12
14
  const resolvedClasses = computed(() =>
13
15
  resolveClasses(icon, { size }, useUi("icon", uiProp), className)
14
16
  )
@@ -19,7 +21,7 @@ defineSlots<{
19
21
  </script>
20
22
 
21
23
  <template>
22
- <span v-bind="$attrs" :class="[resolvedClasses.root, name]" data-slot="root" aria-hidden="true">
24
+ <span v-bind="attrs" :class="[resolvedClasses.root, name]" data-slot="root" aria-hidden="true">
23
25
  <slot />
24
26
  </span>
25
27
  </template>
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { computed, useSlots } from "vue"
2
+ import { computed, useSlots, useAttrs } from "vue"
3
3
  import { scv } from "css-variants"
4
4
  import { useUi, resolveClasses } from "../../utils"
5
5
  import type { InputProps } from "../../types/components/input"
@@ -21,6 +21,7 @@ const emit = defineEmits<{
21
21
  (e: "blur", event: FocusEvent): void
22
22
  }>()
23
23
 
24
+ const attrs = useAttrs()
24
25
  const slots = useSlots()
25
26
 
26
27
  const value = computed({
@@ -68,7 +69,7 @@ function onChange(event: Event) {
68
69
  </slot>
69
70
 
70
71
  <input
71
- v-bind="$attrs"
72
+ v-bind="attrs"
72
73
  :type="type"
73
74
  :name="name"
74
75
  :value="value"
@@ -80,8 +81,8 @@ function onChange(event: Event) {
80
81
  data-slot="input"
81
82
  @input="onInput"
82
83
  @change="onChange"
83
- @focus="emit('focus', $event)"
84
- @blur="emit('blur', $event)"
84
+ @focus="(e) => emit('focus', e)"
85
+ @blur="(e) => emit('blur', e)"
85
86
  />
86
87
 
87
88
  <slot name="trailing" :ui="resolvedClasses">
@@ -1,11 +1,12 @@
1
1
  <script setup lang="ts">
2
- import { computed } from "vue"
2
+ import { computed, useAttrs } from "vue"
3
3
  import { scv } from "css-variants"
4
4
  import { useUi, resolveClasses } from "../../utils"
5
5
  import type { LogoProps } from "../../types/components/logo"
6
6
  import logoTheme from "../../themes/logo.theme"
7
7
  import { getUIConfig } from "virtual:rimelight-ui"
8
8
 
9
+ const attrs = useAttrs()
9
10
  const logo = scv(logoTheme)
10
11
 
11
12
  const {
@@ -23,6 +24,26 @@ defineSlots<{
23
24
 
24
25
  const resolvedClasses = computed(() => resolveClasses(logo, {}, useUi("logo", uiProp), className))
25
26
 
27
+ const logoFiles = import.meta.glob<{ default: any }>(
28
+ "/src/assets/**/*.{svg,png,jpg,jpeg,webp,gif}",
29
+ { eager: true }
30
+ )
31
+
32
+ function resolveLogo(pathStr: string | null | undefined): any {
33
+ if (!pathStr) return null
34
+ let lookupPath = pathStr
35
+ if (lookupPath.startsWith("./")) {
36
+ lookupPath = lookupPath.substring(1)
37
+ } else if (!lookupPath.startsWith("/")) {
38
+ lookupPath = "/" + lookupPath
39
+ }
40
+ const file = logoFiles[lookupPath]
41
+ if (file) {
42
+ return file.default?.src || file.default
43
+ }
44
+ return pathStr
45
+ }
46
+
26
47
  const logoSrc = computed<string | null>(() => {
27
48
  const globalConfig = getUIConfig()
28
49
  const rcLogos = globalConfig.logos as Record<string, any>
@@ -35,7 +56,8 @@ const logoSrc = computed<string | null>(() => {
35
56
  }
36
57
  }
37
58
 
38
- if (src && typeof src === "string" && src) return src
59
+ const resolved = resolveLogo(src)
60
+ if (resolved && typeof resolved === "string" && resolved) return resolved
39
61
 
40
62
  return null
41
63
  })
@@ -52,7 +74,7 @@ const Tag = computed(() => (href ? "a" : "div"))
52
74
 
53
75
  <template>
54
76
  <component
55
- v-bind="$attrs"
77
+ v-bind="attrs"
56
78
  :is="Tag"
57
79
  :href="Tag === 'a' ? href : undefined"
58
80
  :aria-label="alt || variant"
@@ -1,10 +1,11 @@
1
1
  <script setup lang="ts">
2
- import { computed } from "vue"
2
+ import { computed, useAttrs } from "vue"
3
3
  import { scv } from "css-variants"
4
4
  import { useUi, resolveClasses } from "../../utils"
5
5
  import type { PlaceholderProps } from "../../types/components/placeholder"
6
6
  import placeholderTheme from "../../themes/placeholder.theme"
7
7
 
8
+ const attrs = useAttrs()
8
9
  const placeholder = scv(placeholderTheme)
9
10
 
10
11
  const { ui: uiProp, class: className } = defineProps<PlaceholderProps>()
@@ -22,7 +23,7 @@ const resolvedClasses = computed(() =>
22
23
  </script>
23
24
 
24
25
  <template>
25
- <div :class="resolvedClasses.base" v-bind="$attrs">
26
+ <div :class="resolvedClasses.base" v-bind="attrs">
26
27
  <svg :class="resolvedClasses.svg">
27
28
  <defs>
28
29
  <pattern
@@ -8,13 +8,19 @@ import postTheme from "../../themes/post.theme"
8
8
  const post = scv(postTheme)
9
9
 
10
10
  const props = withDefaults(defineProps<PostProps>(), {
11
- variant: "soft"
11
+ variant: "soft",
12
+ orientation: "vertical"
12
13
  })
13
14
 
14
15
  const slots = useSlots()
15
16
 
16
17
  const resolvedClasses = computed(() =>
17
- resolveClasses(post, { variant: props.variant }, useUi("post", props.ui), props.class)
18
+ resolveClasses(
19
+ post,
20
+ { variant: props.variant, orientation: props.orientation },
21
+ useUi("post", props.ui),
22
+ props.class
23
+ )
18
24
  )
19
25
 
20
26
  const Tag = props.to ? "a" : "div"
@@ -0,0 +1,60 @@
1
+ <script setup lang="ts">
2
+ import { computed } from "vue"
3
+ import { scv } from "css-variants"
4
+ import { useUi, resolveClasses } from "../../utils"
5
+ import type { ProgressProps } from "../../types/components/progress"
6
+ import progressTheme from "../../themes/progress.theme"
7
+
8
+ const progress = scv(progressTheme)
9
+
10
+ const props = withDefaults(defineProps<ProgressProps & { modelValue?: number }>(), {
11
+ modelValue: 0,
12
+ max: 100,
13
+ color: "primary",
14
+ size: "md"
15
+ })
16
+
17
+ const emit = defineEmits<{
18
+ (e: "update:modelValue", value: number): void
19
+ }>()
20
+
21
+ const value = computed({
22
+ get: () => props.value ?? props.modelValue ?? 0,
23
+ set: (val) => emit("update:modelValue", val)
24
+ })
25
+
26
+ const percentage = computed(() => {
27
+ if (props.max <= 0) return 0
28
+ return Math.min(100, Math.max(0, (value.value / props.max) * 100))
29
+ })
30
+
31
+ const resolvedClasses = computed(() =>
32
+ resolveClasses(
33
+ progress,
34
+ {
35
+ color: props.color,
36
+ size: props.size,
37
+ theme: props.theme
38
+ },
39
+ useUi("progress", props.ui),
40
+ props.class
41
+ )
42
+ )
43
+ </script>
44
+
45
+ <template>
46
+ <div
47
+ role="progressbar"
48
+ :aria-valuenow="value"
49
+ :aria-valuemin="0"
50
+ :aria-valuemax="max"
51
+ :class="resolvedClasses.root"
52
+ data-slot="root"
53
+ >
54
+ <div
55
+ :class="resolvedClasses.indicator"
56
+ :style="{ width: percentage + '%' }"
57
+ data-slot="indicator"
58
+ />
59
+ </div>
60
+ </template>