@rimelight/ui 0.0.23 → 0.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +8 -3
- package/src/components/Head.astro +199 -156
- package/src/components/astro/RLAAccordion.astro +22 -0
- package/src/components/astro/RLAButton.astro +104 -85
- package/src/components/astro/RLAFooter.astro +14 -40
- package/src/components/astro/RLAHeader.astro +18 -78
- package/src/components/astro/RLAIcon.astro +11 -36
- package/src/components/astro/RLALogo.astro +9 -44
- package/src/components/astro/RLAPlaceholder.astro +8 -33
- package/src/components/astro/RLAQuote.astro +15 -0
- package/src/components/astro/RLAScrollToTop.astro +171 -221
- package/src/components/astro/RLASection.astro +181 -0
- package/src/components/vue/RLVButton.vue +125 -50
- package/src/components/vue/RLVFooter.vue +12 -49
- package/src/components/vue/RLVHeader.vue +15 -98
- package/src/components/vue/RLVIcon.vue +11 -37
- package/src/components/vue/RLVLogo.vue +8 -56
- package/src/components/vue/RLVPlaceholder.vue +11 -33
- package/src/components/vue/RLVScrollToTop.vue +17 -88
- package/src/components/vue/RLVSection.vue +98 -0
- package/src/composables/index.ts +0 -1
- package/src/env.d.ts +5 -0
- package/src/integrations/ui.ts +2 -6
- package/src/nuxt-types.ts +3 -0
- package/src/plugins/index.ts +5 -2
- package/src/plugins/starlightAddons/index.ts +3 -64
- package/src/plugins/starlightDocsApi/components/ApiEmits.astro +46 -0
- package/src/plugins/starlightDocsApi/components/ApiProps.astro +47 -0
- package/src/plugins/starlightDocsApi/components/ApiSlots.astro +50 -0
- package/src/plugins/starlightDocsApi/components/ApiTheme.astro +27 -0
- package/src/plugins/starlightDocsApi/extract-vue.ts +286 -0
- package/src/plugins/starlightDocsApi/index.ts +265 -0
- package/src/plugins/starlightDocsApi/types.ts +40 -0
- package/src/plugins/starlightDocsApi/utils.ts +45 -0
- package/src/themes/button.theme.ts +179 -23
- package/src/themes/footer.theme.ts +4 -6
- package/src/themes/header.theme.ts +4 -28
- package/src/themes/icon.theme.ts +4 -2
- package/src/themes/index.ts +15 -20
- package/src/themes/logo.theme.ts +4 -2
- package/src/themes/placeholder.theme.ts +4 -6
- package/src/themes/scroll-to-top.theme.ts +4 -6
- package/src/themes/section.theme.ts +185 -0
- package/src/types/componentVariant.ts +10 -0
- package/src/types/index.ts +1 -0
- package/src/utils/defineTheme.ts +11 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/resolveClasses.ts +21 -0
- package/src/utils/useUi.ts +19 -0
- package/src/composables/useUi.ts +0 -27
- package/src/plugins/starlightAddons/Sidebar.astro +0 -89
- package/src/plugins/starlightAddons/data.ts +0 -39
- package/src/plugins/starlightAddons/libs/config.ts +0 -107
- package/src/plugins/starlightAddons/libs/content.ts +0 -20
- package/src/plugins/starlightAddons/libs/i18n.ts +0 -51
- package/src/plugins/starlightAddons/libs/locals.ts +0 -12
- package/src/plugins/starlightAddons/libs/pathname.ts +0 -22
- package/src/plugins/starlightAddons/libs/plugin.ts +0 -9
- package/src/plugins/starlightAddons/libs/sidebar.ts +0 -183
- package/src/plugins/starlightAddons/libs/vite.ts +0 -46
- package/src/plugins/starlightAddons/locals.d.ts +0 -14
- package/src/plugins/starlightAddons/middleware.ts +0 -132
- package/src/plugins/starlightAddons/overrides/Sidebar.astro +0 -8
- package/src/plugins/starlightAddons/schema.ts +0 -13
- package/src/plugins/starlightAddons/virtual.d.ts +0 -13
|
@@ -1,53 +1,71 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
2
|
+
import { computed, useSlots } from "vue"
|
|
3
|
+
import { scv } from "css-variants"
|
|
4
|
+
import { useUi, resolveClasses } from "../../utils"
|
|
5
|
+
import type { ComponentVariants } from "../../types"
|
|
6
|
+
import buttonTheme from "../../themes/button.theme"
|
|
7
7
|
|
|
8
|
-
const button = scv(
|
|
9
|
-
|
|
10
|
-
base: buttonTheme.base,
|
|
11
|
-
variants: buttonTheme.variants,
|
|
12
|
-
compoundVariants: [...buttonTheme.compoundVariants],
|
|
13
|
-
defaultVariants: buttonTheme.defaultVariants,
|
|
14
|
-
classNameResolver: (...args) => twMerge(cx(...args))
|
|
15
|
-
})
|
|
8
|
+
const button = scv(buttonTheme)
|
|
9
|
+
type ButtonVariants = ComponentVariants<typeof buttonTheme>
|
|
16
10
|
|
|
17
11
|
export interface RLVButtonProps {
|
|
18
12
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* @default "solid"
|
|
13
|
+
* The visual style variant of the button
|
|
22
14
|
*/
|
|
23
|
-
variant?:
|
|
15
|
+
variant?: ButtonVariants["variant"]
|
|
24
16
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* @default "primary"
|
|
17
|
+
* The color scheme applied to the button
|
|
28
18
|
*/
|
|
29
|
-
color?:
|
|
19
|
+
color?: ButtonVariants["color"]
|
|
30
20
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* @default "md"
|
|
21
|
+
* The size scale of the button
|
|
34
22
|
*/
|
|
35
|
-
size?:
|
|
23
|
+
size?: ButtonVariants["size"]
|
|
36
24
|
/**
|
|
37
|
-
* When provided, renders as
|
|
25
|
+
* When provided, renders the button as an anchor link
|
|
38
26
|
*/
|
|
39
27
|
href?: string
|
|
40
28
|
/**
|
|
41
|
-
*
|
|
29
|
+
* The text label displayed inside the button
|
|
42
30
|
*/
|
|
43
|
-
|
|
31
|
+
label?: string
|
|
44
32
|
/**
|
|
45
|
-
*
|
|
33
|
+
* Icon name displayed before the label
|
|
46
34
|
*/
|
|
47
|
-
|
|
35
|
+
leadingIcon?: string
|
|
36
|
+
/**
|
|
37
|
+
* Icon name displayed after the label
|
|
38
|
+
*/
|
|
39
|
+
trailingIcon?: string
|
|
40
|
+
/**
|
|
41
|
+
* Shows a loading spinner animation
|
|
42
|
+
*/
|
|
43
|
+
loading?: boolean
|
|
44
|
+
/**
|
|
45
|
+
* Renders a square button with equal padding
|
|
46
|
+
*/
|
|
47
|
+
square?: boolean
|
|
48
|
+
/**
|
|
49
|
+
* Makes the button stretch to full width
|
|
50
|
+
*/
|
|
51
|
+
block?: boolean
|
|
52
|
+
/**
|
|
53
|
+
* Applies active state styling
|
|
54
|
+
*/
|
|
55
|
+
active?: boolean
|
|
56
|
+
/**
|
|
57
|
+
* Color used when button is in active state
|
|
58
|
+
*/
|
|
59
|
+
activeColor?: ButtonVariants["color"]
|
|
60
|
+
/**
|
|
61
|
+
* Variant used when button is in active state
|
|
62
|
+
*/
|
|
63
|
+
activeVariant?: ButtonVariants["variant"]
|
|
48
64
|
/**
|
|
49
|
-
*
|
|
65
|
+
* Component-specific CSS class overrides
|
|
50
66
|
*/
|
|
67
|
+
ui?: Partial<Record<string, string>>
|
|
68
|
+
class?: string
|
|
51
69
|
[key: string]: unknown
|
|
52
70
|
}
|
|
53
71
|
|
|
@@ -57,30 +75,68 @@ const {
|
|
|
57
75
|
size = "md",
|
|
58
76
|
class: className,
|
|
59
77
|
ui: uiProp,
|
|
60
|
-
href
|
|
78
|
+
href,
|
|
79
|
+
label,
|
|
80
|
+
leadingIcon,
|
|
81
|
+
trailingIcon,
|
|
82
|
+
loading = false,
|
|
83
|
+
square = false,
|
|
84
|
+
block = false,
|
|
85
|
+
active = false,
|
|
86
|
+
activeColor,
|
|
87
|
+
activeVariant
|
|
61
88
|
} = defineProps<RLVButtonProps>()
|
|
62
89
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
90
|
+
const slots = useSlots()
|
|
91
|
+
|
|
92
|
+
const isLeading = computed(() => !!(leadingIcon || slots.leading) || loading)
|
|
93
|
+
const isTrailing = computed(
|
|
94
|
+
() => !!(trailingIcon || slots.trailing) || (loading && !isLeading.value)
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
const showLeadingIcon = computed(() => {
|
|
98
|
+
if (loading) return "i-lucide-loader-circle"
|
|
99
|
+
return leadingIcon
|
|
100
|
+
})
|
|
69
101
|
|
|
70
|
-
const
|
|
102
|
+
const showTrailingIcon = computed(() => {
|
|
103
|
+
if (loading) return "i-lucide-loader-circle"
|
|
104
|
+
return trailingIcon
|
|
105
|
+
})
|
|
71
106
|
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
) as Record<keyof typeof buttonTheme.base, string | undefined>
|
|
107
|
+
const leadingIconClass = computed(() => {
|
|
108
|
+
return loading && isLeading.value ? "animate-spin" : ""
|
|
109
|
+
})
|
|
76
110
|
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
color,
|
|
80
|
-
size
|
|
111
|
+
const trailingIconClass = computed(() => {
|
|
112
|
+
return loading && isTrailing.value ? "animate-spin" : ""
|
|
81
113
|
})
|
|
82
114
|
|
|
83
|
-
|
|
115
|
+
defineSlots<{
|
|
116
|
+
default(props: { ui: Record<string, string> }): any
|
|
117
|
+
leading(props: { ui: Record<string, string> }): any
|
|
118
|
+
trailing(props: { ui: Record<string, string> }): any
|
|
119
|
+
}>()
|
|
120
|
+
|
|
121
|
+
const resolvedClasses = computed(() =>
|
|
122
|
+
resolveClasses(
|
|
123
|
+
button,
|
|
124
|
+
{
|
|
125
|
+
variant: active && activeVariant ? activeVariant : variant,
|
|
126
|
+
color: active && activeColor ? activeColor : color,
|
|
127
|
+
size,
|
|
128
|
+
block,
|
|
129
|
+
square: square || (!label && !slots.default),
|
|
130
|
+
leading: isLeading.value,
|
|
131
|
+
trailing: isTrailing.value,
|
|
132
|
+
loading,
|
|
133
|
+
active
|
|
134
|
+
},
|
|
135
|
+
useUi("button", uiProp),
|
|
136
|
+
className
|
|
137
|
+
)
|
|
138
|
+
)
|
|
139
|
+
|
|
84
140
|
const Tag = href ? "a" : "button"
|
|
85
141
|
</script>
|
|
86
142
|
|
|
@@ -89,9 +145,28 @@ const Tag = href ? "a" : "button"
|
|
|
89
145
|
v-bind="$attrs"
|
|
90
146
|
:is="Tag"
|
|
91
147
|
:href="href"
|
|
92
|
-
:class="
|
|
148
|
+
:class="resolvedClasses.root"
|
|
93
149
|
data-slot="rlv-button"
|
|
94
150
|
>
|
|
95
|
-
<slot
|
|
151
|
+
<slot name="leading" :ui="resolvedClasses">
|
|
152
|
+
<span v-if="isLeading" :class="resolvedClasses.leadingIcon" data-slot="leading-icon">
|
|
153
|
+
<span :class="[showLeadingIcon, leadingIconClass]" aria-hidden="true" />
|
|
154
|
+
</span>
|
|
155
|
+
</slot>
|
|
156
|
+
|
|
157
|
+
<span
|
|
158
|
+
v-if="label !== undefined && label !== null"
|
|
159
|
+
:class="resolvedClasses.label"
|
|
160
|
+
data-slot="label"
|
|
161
|
+
>
|
|
162
|
+
{{ label }}
|
|
163
|
+
</span>
|
|
164
|
+
<slot v-else />
|
|
165
|
+
|
|
166
|
+
<slot name="trailing" :ui="resolvedClasses">
|
|
167
|
+
<span v-if="isTrailing" :class="resolvedClasses.trailingIcon" data-slot="trailing-icon">
|
|
168
|
+
<span :class="[showTrailingIcon, trailingIconClass]" aria-hidden="true" />
|
|
169
|
+
</span>
|
|
170
|
+
</slot>
|
|
96
171
|
</component>
|
|
97
172
|
</template>
|
|
@@ -1,71 +1,34 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed } from "vue"
|
|
3
|
-
import { scv
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
3
|
+
import { scv } from "css-variants"
|
|
4
|
+
import { useUi, resolveClasses } from "../../utils"
|
|
5
|
+
import type { ComponentVariants } from "../../types"
|
|
6
|
+
import footerTheme from "../../themes/footer.theme"
|
|
7
7
|
|
|
8
|
-
const footer = scv(
|
|
9
|
-
|
|
10
|
-
base: footerTheme.base,
|
|
11
|
-
variants: footerTheme.variants,
|
|
12
|
-
defaultVariants: footerTheme.defaultVariants,
|
|
13
|
-
classNameResolver: (...args) => twMerge(cx(...args))
|
|
14
|
-
})
|
|
8
|
+
const footer = scv(footerTheme)
|
|
9
|
+
type FooterVariants = ComponentVariants<typeof footerTheme>
|
|
15
10
|
|
|
16
11
|
export interface RLVFooterProps {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
*
|
|
20
|
-
* @default false
|
|
21
|
-
*/
|
|
22
|
-
contain?: boolean
|
|
23
|
-
/**
|
|
24
|
-
* UI overrides for individual slots, derived from the footer theme.
|
|
25
|
-
*/
|
|
26
|
-
ui?: Partial<Record<keyof typeof footerTheme.base, string>>
|
|
27
|
-
/**
|
|
28
|
-
* External class — applied to the root element.
|
|
29
|
-
*/
|
|
12
|
+
contain?: FooterVariants["contain"]
|
|
13
|
+
ui?: Partial<Record<string, string>>
|
|
30
14
|
class?: string
|
|
31
15
|
}
|
|
32
16
|
|
|
33
17
|
const { contain = false, class: className, ui: uiProp } = defineProps<RLVFooterProps>()
|
|
34
18
|
|
|
35
19
|
defineSlots<{
|
|
36
|
-
/**
|
|
37
|
-
* Content to display on the left side of the footer.
|
|
38
|
-
*/
|
|
39
20
|
left(props: {}): any
|
|
40
|
-
/**
|
|
41
|
-
* Content to display in the center of the footer.
|
|
42
|
-
*/
|
|
43
21
|
center(props: {}): any
|
|
44
|
-
/**
|
|
45
|
-
* Content to display on the right side of the footer.
|
|
46
|
-
*/
|
|
47
22
|
right(props: {}): any
|
|
48
23
|
}>()
|
|
49
24
|
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const classes = footer({
|
|
54
|
-
contain
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
return {
|
|
58
|
-
root: twMerge(classes.root, mergedUI.value.root as string | undefined),
|
|
59
|
-
container: twMerge(classes.container, mergedUI.value.container as string | undefined),
|
|
60
|
-
left: twMerge(classes.left, mergedUI.value.left as string | undefined),
|
|
61
|
-
center: twMerge(classes.center, mergedUI.value.center as string | undefined),
|
|
62
|
-
right: twMerge(classes.right, mergedUI.value.right as string | undefined)
|
|
63
|
-
}
|
|
64
|
-
})
|
|
25
|
+
const resolvedClasses = computed(() =>
|
|
26
|
+
resolveClasses(footer, { contain }, useUi("footer", uiProp), className)
|
|
27
|
+
)
|
|
65
28
|
</script>
|
|
66
29
|
|
|
67
30
|
<template>
|
|
68
|
-
<footer :class="[resolvedClasses.root
|
|
31
|
+
<footer :class="[resolvedClasses.root]" data-slot="rlv-footer" v-bind="$attrs">
|
|
69
32
|
<div :class="resolvedClasses.container">
|
|
70
33
|
<div :class="resolvedClasses.left" data-slot="footer-left">
|
|
71
34
|
<slot name="left" />
|
|
@@ -1,64 +1,21 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, onMounted, onUnmounted, ref } from "vue"
|
|
3
|
-
import { scv
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import { getHeaderStack } from "../../utils/headerStack
|
|
8
|
-
|
|
9
|
-
// ── Style engine ─────────────────────────────────────────────────────────────
|
|
10
|
-
|
|
11
|
-
const header = scv({
|
|
12
|
-
slots: [...headerTheme.slots],
|
|
13
|
-
base: headerTheme.base,
|
|
14
|
-
variants: headerTheme.variants,
|
|
15
|
-
defaultVariants: headerTheme.defaultVariants,
|
|
16
|
-
classNameResolver: (...args) => twMerge(cx(...args))
|
|
17
|
-
})
|
|
3
|
+
import { scv } from "css-variants"
|
|
4
|
+
import { useUi, resolveClasses } from "../../utils"
|
|
5
|
+
import type { ComponentVariants } from "../../types"
|
|
6
|
+
import headerTheme from "../../themes/header.theme"
|
|
7
|
+
import { getHeaderStack } from "../../utils/headerStack"
|
|
18
8
|
|
|
19
|
-
|
|
9
|
+
const header = scv(headerTheme)
|
|
10
|
+
type HeaderVariants = ComponentVariants<typeof headerTheme>
|
|
20
11
|
|
|
21
12
|
export interface RLVHeaderProps {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
* @default true
|
|
26
|
-
*/
|
|
27
|
-
contain?: boolean
|
|
28
|
-
/**
|
|
29
|
-
* Sticky positioning when `fixed` is false.
|
|
30
|
-
*
|
|
31
|
-
* @default true
|
|
32
|
-
*/
|
|
33
|
-
sticky?: boolean
|
|
34
|
-
/**
|
|
35
|
-
* Switches to `position: fixed; left: 0; right: 0` (layer mode). When true, `top` and
|
|
36
|
-
* `stackIndex` control the exact position.
|
|
37
|
-
*
|
|
38
|
-
* @default false
|
|
39
|
-
*/
|
|
40
|
-
fixed?: boolean
|
|
41
|
-
/**
|
|
42
|
-
* Controls z-index when `fixed` is true: `z-index = 100 - stackIndex`. Lower index = higher in
|
|
43
|
-
* the visual stack.
|
|
44
|
-
*
|
|
45
|
-
* @default 0
|
|
46
|
-
*/
|
|
13
|
+
contain?: HeaderVariants["contain"]
|
|
14
|
+
sticky?: HeaderVariants["sticky"]
|
|
15
|
+
fixed?: HeaderVariants["fixed"]
|
|
47
16
|
stackIndex?: number
|
|
48
|
-
/**
|
|
49
|
-
* When true, hides the header on scroll-down and shows it on scroll-up. Uses a passive `scroll`
|
|
50
|
-
* event listener — no external dependencies. Only meaningful when `fixed` is true.
|
|
51
|
-
*
|
|
52
|
-
* @default false
|
|
53
|
-
*/
|
|
54
17
|
hideOnScroll?: boolean
|
|
55
|
-
|
|
56
|
-
* UI overrides for individual slots, derived from the header theme.
|
|
57
|
-
*/
|
|
58
|
-
ui?: Partial<Record<keyof typeof headerTheme.base, string>>
|
|
59
|
-
/**
|
|
60
|
-
* External class — applied to the root element.
|
|
61
|
-
*/
|
|
18
|
+
ui?: Partial<Record<string, string>>
|
|
62
19
|
class?: string
|
|
63
20
|
}
|
|
64
21
|
|
|
@@ -72,42 +29,15 @@ const {
|
|
|
72
29
|
ui: uiProp
|
|
73
30
|
} = defineProps<RLVHeaderProps>()
|
|
74
31
|
|
|
75
|
-
// ── Slots ─────────────────────────────────────────────────────────────────────
|
|
76
|
-
|
|
77
32
|
defineSlots<{
|
|
78
|
-
/**
|
|
79
|
-
* Content to display on the left side of the header (e.g., Logo).
|
|
80
|
-
*/
|
|
81
33
|
left(props: {}): any
|
|
82
|
-
/**
|
|
83
|
-
* Content to display in the center of the header (e.g., Navigation Links).
|
|
84
|
-
*/
|
|
85
34
|
center(props: {}): any
|
|
86
|
-
/**
|
|
87
|
-
* Content to display on the right side of the header (e.g., User Menu, Theme Toggle).
|
|
88
|
-
*/
|
|
89
35
|
right(props: {}): any
|
|
90
36
|
}>()
|
|
91
37
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
// ── Resolved classes ──────────────────────────────────────────────────────────
|
|
97
|
-
|
|
98
|
-
const resolvedClasses = computed(() => {
|
|
99
|
-
const classes = header({ contain, sticky, fixed })
|
|
100
|
-
return {
|
|
101
|
-
root: twMerge(classes.root, mergedUI.value.root as string | undefined),
|
|
102
|
-
content: twMerge(classes.content, mergedUI.value.content as string | undefined),
|
|
103
|
-
container: twMerge(classes.container, mergedUI.value.container as string | undefined),
|
|
104
|
-
left: twMerge(classes.left, mergedUI.value.left as string | undefined),
|
|
105
|
-
center: twMerge(classes.center, mergedUI.value.center as string | undefined),
|
|
106
|
-
right: twMerge(classes.right, mergedUI.value.right as string | undefined)
|
|
107
|
-
}
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
// ── Fixed-mode state ──────────────────────────────────────────────────────────
|
|
38
|
+
const resolvedClasses = computed(() =>
|
|
39
|
+
resolveClasses(header, { contain, sticky, fixed }, useUi("header", uiProp), className)
|
|
40
|
+
)
|
|
111
41
|
|
|
112
42
|
const id = `rlv-header-${Math.random().toString(36).slice(2, 8)}`
|
|
113
43
|
const rootRef = ref<HTMLElement | null>(null)
|
|
@@ -115,9 +45,6 @@ const contentRef = ref<HTMLElement | null>(null)
|
|
|
115
45
|
const naturalHeight = ref(0)
|
|
116
46
|
const isVisible = ref(true)
|
|
117
47
|
|
|
118
|
-
/**
|
|
119
|
-
* Inline style applied to the root element in fixed mode.
|
|
120
|
-
*/
|
|
121
48
|
const fixedStyle = computed(() => {
|
|
122
49
|
if (!fixed) return {}
|
|
123
50
|
return {
|
|
@@ -125,8 +52,6 @@ const fixedStyle = computed(() => {
|
|
|
125
52
|
}
|
|
126
53
|
})
|
|
127
54
|
|
|
128
|
-
// ── Lifecycle: height measurement + scroll listener ───────────────────────────
|
|
129
|
-
|
|
130
55
|
let resizeObserver: ResizeObserver | null = null
|
|
131
56
|
let scrollHandler: (() => void) | null = null
|
|
132
57
|
|
|
@@ -139,7 +64,6 @@ onMounted(() => {
|
|
|
139
64
|
stack.register(id, stackIndex, naturalHeight.value, isVisible.value, rootRef.value)
|
|
140
65
|
}
|
|
141
66
|
|
|
142
|
-
// Measure natural height via ResizeObserver
|
|
143
67
|
if (contentRef.value) {
|
|
144
68
|
naturalHeight.value = contentRef.value.getBoundingClientRect().height
|
|
145
69
|
resizeObserver = new ResizeObserver((entries) => {
|
|
@@ -152,14 +76,12 @@ onMounted(() => {
|
|
|
152
76
|
resizeObserver.observe(contentRef.value)
|
|
153
77
|
}
|
|
154
78
|
|
|
155
|
-
// Raw scroll listener for hideOnScroll
|
|
156
79
|
if (hideOnScroll) {
|
|
157
80
|
let localLastScrollY = window.scrollY
|
|
158
81
|
scrollHandler = () => {
|
|
159
82
|
const current = window.scrollY
|
|
160
83
|
const diff = current - localLastScrollY
|
|
161
84
|
|
|
162
|
-
// Ignore tiny jitter
|
|
163
85
|
if (Math.abs(diff) < 10) return
|
|
164
86
|
|
|
165
87
|
const newVisible = current <= 50 ? true : diff <= 0
|
|
@@ -188,16 +110,11 @@ onUnmounted(() => {
|
|
|
188
110
|
<header
|
|
189
111
|
ref="rootRef"
|
|
190
112
|
:id="id"
|
|
191
|
-
:class="[resolvedClasses.root
|
|
113
|
+
:class="[resolvedClasses.root]"
|
|
192
114
|
:style="fixedStyle"
|
|
193
115
|
data-slot="rlv-header"
|
|
194
116
|
v-bind="$attrs"
|
|
195
117
|
>
|
|
196
|
-
<!--
|
|
197
|
-
content wrapper: always rendered, but only meaningful in fixed mode.
|
|
198
|
-
The ResizeObserver targets this element so the `<header>` root's padding/border
|
|
199
|
-
don't interfere with the height measurement.
|
|
200
|
-
-->
|
|
201
118
|
<div ref="contentRef" :class="resolvedClasses.content">
|
|
202
119
|
<div :class="resolvedClasses.container">
|
|
203
120
|
<div :class="resolvedClasses.left" data-slot="header-left">
|
|
@@ -1,51 +1,25 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed } from "vue"
|
|
3
|
-
import { scv
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
3
|
+
import { scv } from "css-variants"
|
|
4
|
+
import { useUi, resolveClasses } from "../../utils"
|
|
5
|
+
import type { ComponentVariants } from "../../types"
|
|
6
|
+
import iconTheme from "../../themes/icon.theme"
|
|
7
7
|
|
|
8
|
-
const icon = scv(
|
|
9
|
-
|
|
10
|
-
base: iconTheme.base,
|
|
11
|
-
variants: iconTheme.variants,
|
|
12
|
-
defaultVariants: iconTheme.defaultVariants,
|
|
13
|
-
classNameResolver: (...args) => twMerge(cx(...args))
|
|
14
|
-
})
|
|
8
|
+
const icon = scv(iconTheme)
|
|
9
|
+
type IconVariants = ComponentVariants<typeof iconTheme>
|
|
15
10
|
|
|
16
11
|
export interface RLVIconProps {
|
|
17
|
-
/**
|
|
18
|
-
* Icon name following the UnoCSS icons format. Can be a string like "i-lucide-home" or a Vue
|
|
19
|
-
* component.
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* "i-lucide-home"
|
|
23
|
-
*/
|
|
24
12
|
name: string
|
|
25
|
-
|
|
26
|
-
* Size variant for the icon.
|
|
27
|
-
*/
|
|
28
|
-
size?: keyof typeof iconTheme.variants.size
|
|
29
|
-
/**
|
|
30
|
-
* External class applied to the root element.
|
|
31
|
-
*/
|
|
13
|
+
size?: IconVariants["size"]
|
|
32
14
|
class?: string
|
|
33
|
-
|
|
34
|
-
* UI overrides for individual slots.
|
|
35
|
-
*/
|
|
36
|
-
ui?: Partial<Record<keyof typeof iconTheme.base, string>>
|
|
15
|
+
ui?: Partial<Record<string, string>>
|
|
37
16
|
}
|
|
38
17
|
|
|
39
18
|
const { name, size = "md", class: className, ui: uiProp } = defineProps<RLVIconProps>()
|
|
40
19
|
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const { root } = icon({ size })
|
|
45
|
-
return {
|
|
46
|
-
root: twMerge(root, mergedUI.value.root, className)
|
|
47
|
-
}
|
|
48
|
-
})
|
|
20
|
+
const resolvedClasses = computed(() =>
|
|
21
|
+
resolveClasses(icon, { size }, useUi("icon", uiProp), className)
|
|
22
|
+
)
|
|
49
23
|
|
|
50
24
|
defineSlots<{
|
|
51
25
|
default(props: {}): any
|
|
@@ -1,51 +1,19 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed } from "vue"
|
|
3
|
-
import { scv
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import { logoTheme } from "../../themes/logo.theme.ts"
|
|
3
|
+
import { scv } from "css-variants"
|
|
4
|
+
import { useUi, resolveClasses } from "../../utils"
|
|
5
|
+
import logoTheme from "../../themes/logo.theme"
|
|
7
6
|
import { getUIConfig } from "virtual:rimelight-ui"
|
|
8
7
|
|
|
9
|
-
const logo = scv(
|
|
10
|
-
slots: [...logoTheme.slots],
|
|
11
|
-
base: logoTheme.base,
|
|
12
|
-
variants: logoTheme.variants,
|
|
13
|
-
defaultVariants: logoTheme.defaultVariants,
|
|
14
|
-
classNameResolver: (...args) => twMerge(cx(...args))
|
|
15
|
-
})
|
|
8
|
+
const logo = scv(logoTheme)
|
|
16
9
|
|
|
17
10
|
export interface RLVLogoProps {
|
|
18
|
-
/**
|
|
19
|
-
* The variant of the logo to display.
|
|
20
|
-
*
|
|
21
|
-
* @default "logomark"
|
|
22
|
-
*/
|
|
23
11
|
variant?: string
|
|
24
|
-
/**
|
|
25
|
-
* Override the color mode.
|
|
26
|
-
*/
|
|
27
12
|
mode?: "color" | "white" | "black"
|
|
28
|
-
/**
|
|
29
|
-
* The URL to link to.
|
|
30
|
-
*
|
|
31
|
-
* @default "/"
|
|
32
|
-
*/
|
|
33
13
|
href?: string
|
|
34
|
-
|
|
35
|
-
* UI overrides for individual slots, derived from the logo theme.
|
|
36
|
-
*/
|
|
37
|
-
ui?: Partial<Record<keyof typeof logoTheme.base, string>>
|
|
38
|
-
/**
|
|
39
|
-
* External class — applied to the root element.
|
|
40
|
-
*/
|
|
14
|
+
ui?: Partial<Record<string, string>>
|
|
41
15
|
class?: string
|
|
42
|
-
/**
|
|
43
|
-
* The alt text for the logo image.
|
|
44
|
-
*/
|
|
45
16
|
alt?: string
|
|
46
|
-
/**
|
|
47
|
-
* Standard HTML attributes for <a>
|
|
48
|
-
*/
|
|
49
17
|
[key: string]: unknown
|
|
50
18
|
}
|
|
51
19
|
|
|
@@ -55,30 +23,15 @@ const props = withDefaults(defineProps<RLVLogoProps>(), {
|
|
|
55
23
|
})
|
|
56
24
|
|
|
57
25
|
defineSlots<{
|
|
58
|
-
/**
|
|
59
|
-
* The default slot for the logo content (e.g., text, custom elements).
|
|
60
|
-
*/
|
|
61
26
|
default(props: {}): any
|
|
62
27
|
}>()
|
|
63
28
|
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
const mergedUI = computed(
|
|
67
|
-
() =>
|
|
68
|
-
defu(props.ui ?? {}, (globalConfig.logo as Record<string, unknown>) ?? {}) as Record<
|
|
69
|
-
keyof typeof logoTheme.base,
|
|
70
|
-
string | undefined
|
|
71
|
-
>
|
|
29
|
+
const resolvedClasses = computed(() =>
|
|
30
|
+
resolveClasses(logo, {}, useUi("logo", props.ui), props.class)
|
|
72
31
|
)
|
|
73
32
|
|
|
74
|
-
const resolvedClasses = computed(() => {
|
|
75
|
-
const { root } = logo()
|
|
76
|
-
return {
|
|
77
|
-
root: twMerge(root, mergedUI.value.root, props.class)
|
|
78
|
-
}
|
|
79
|
-
})
|
|
80
|
-
|
|
81
33
|
const logoSrc = computed<string | null>(() => {
|
|
34
|
+
const globalConfig = getUIConfig()
|
|
82
35
|
const rcLogos = globalConfig.logos as Record<string, any>
|
|
83
36
|
let src: any = null
|
|
84
37
|
|
|
@@ -114,7 +67,6 @@ const Tag = computed(() => (props.href ? "a" : "div"))
|
|
|
114
67
|
data-slot="rlv-logo"
|
|
115
68
|
>
|
|
116
69
|
<template v-if="logoSrc">
|
|
117
|
-
<!-- Using mode='svg' pattern is not strictly needed for UnoCSS icons -->
|
|
118
70
|
<span v-if="isIcon" :class="[logoSrc, 'size-full block shrink-0']" aria-hidden="true" />
|
|
119
71
|
<img v-else :src="logoSrc" :alt="alt || ''" class="size-full block object-contain shrink-0" />
|
|
120
72
|
</template>
|