@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.
Files changed (65) hide show
  1. package/package.json +8 -3
  2. package/src/components/Head.astro +199 -156
  3. package/src/components/astro/RLAAccordion.astro +22 -0
  4. package/src/components/astro/RLAButton.astro +104 -85
  5. package/src/components/astro/RLAFooter.astro +14 -40
  6. package/src/components/astro/RLAHeader.astro +18 -78
  7. package/src/components/astro/RLAIcon.astro +11 -36
  8. package/src/components/astro/RLALogo.astro +9 -44
  9. package/src/components/astro/RLAPlaceholder.astro +8 -33
  10. package/src/components/astro/RLAQuote.astro +15 -0
  11. package/src/components/astro/RLAScrollToTop.astro +171 -221
  12. package/src/components/astro/RLASection.astro +181 -0
  13. package/src/components/vue/RLVButton.vue +125 -50
  14. package/src/components/vue/RLVFooter.vue +12 -49
  15. package/src/components/vue/RLVHeader.vue +15 -98
  16. package/src/components/vue/RLVIcon.vue +11 -37
  17. package/src/components/vue/RLVLogo.vue +8 -56
  18. package/src/components/vue/RLVPlaceholder.vue +11 -33
  19. package/src/components/vue/RLVScrollToTop.vue +17 -88
  20. package/src/components/vue/RLVSection.vue +98 -0
  21. package/src/composables/index.ts +0 -1
  22. package/src/env.d.ts +5 -0
  23. package/src/integrations/ui.ts +2 -6
  24. package/src/nuxt-types.ts +3 -0
  25. package/src/plugins/index.ts +5 -2
  26. package/src/plugins/starlightAddons/index.ts +3 -64
  27. package/src/plugins/starlightDocsApi/components/ApiEmits.astro +46 -0
  28. package/src/plugins/starlightDocsApi/components/ApiProps.astro +47 -0
  29. package/src/plugins/starlightDocsApi/components/ApiSlots.astro +50 -0
  30. package/src/plugins/starlightDocsApi/components/ApiTheme.astro +27 -0
  31. package/src/plugins/starlightDocsApi/extract-vue.ts +286 -0
  32. package/src/plugins/starlightDocsApi/index.ts +265 -0
  33. package/src/plugins/starlightDocsApi/types.ts +40 -0
  34. package/src/plugins/starlightDocsApi/utils.ts +45 -0
  35. package/src/themes/button.theme.ts +179 -23
  36. package/src/themes/footer.theme.ts +4 -6
  37. package/src/themes/header.theme.ts +4 -28
  38. package/src/themes/icon.theme.ts +4 -2
  39. package/src/themes/index.ts +15 -20
  40. package/src/themes/logo.theme.ts +4 -2
  41. package/src/themes/placeholder.theme.ts +4 -6
  42. package/src/themes/scroll-to-top.theme.ts +4 -6
  43. package/src/themes/section.theme.ts +185 -0
  44. package/src/types/componentVariant.ts +10 -0
  45. package/src/types/index.ts +1 -0
  46. package/src/utils/defineTheme.ts +11 -0
  47. package/src/utils/index.ts +3 -0
  48. package/src/utils/resolveClasses.ts +21 -0
  49. package/src/utils/useUi.ts +19 -0
  50. package/src/composables/useUi.ts +0 -27
  51. package/src/plugins/starlightAddons/Sidebar.astro +0 -89
  52. package/src/plugins/starlightAddons/data.ts +0 -39
  53. package/src/plugins/starlightAddons/libs/config.ts +0 -107
  54. package/src/plugins/starlightAddons/libs/content.ts +0 -20
  55. package/src/plugins/starlightAddons/libs/i18n.ts +0 -51
  56. package/src/plugins/starlightAddons/libs/locals.ts +0 -12
  57. package/src/plugins/starlightAddons/libs/pathname.ts +0 -22
  58. package/src/plugins/starlightAddons/libs/plugin.ts +0 -9
  59. package/src/plugins/starlightAddons/libs/sidebar.ts +0 -183
  60. package/src/plugins/starlightAddons/libs/vite.ts +0 -46
  61. package/src/plugins/starlightAddons/locals.d.ts +0 -14
  62. package/src/plugins/starlightAddons/middleware.ts +0 -132
  63. package/src/plugins/starlightAddons/overrides/Sidebar.astro +0 -8
  64. package/src/plugins/starlightAddons/schema.ts +0 -13
  65. package/src/plugins/starlightAddons/virtual.d.ts +0 -13
@@ -1,221 +1,171 @@
1
- ---
2
- import { scv, cx } from "css-variants"
3
- import { twMerge } from "tailwind-merge"
4
- import defu from "defu"
5
- import { scrollToTopTheme } from "../../themes/scroll-to-top.theme.ts"
6
- import { getUIConfig } from "virtual:rimelight-ui"
7
-
8
- export interface RLAScrollToTopProps {
9
- /**
10
- * Button color.
11
- *
12
- * @default "primary"
13
- */
14
- color?: keyof typeof scrollToTopTheme.variants.color
15
- /**
16
- * Transition duration for the progress circle (in seconds).
17
- *
18
- * @default 0.1
19
- */
20
- duration?: number
21
- /**
22
- * Scroll threshold (in pixels) before the button becomes visible.
23
- *
24
- * @default 200
25
- */
26
- threshold?: number
27
- /**
28
- * Whether to show the scroll progress indicator.
29
- *
30
- * @default false
31
- */
32
- showProgress?: boolean
33
- /**
34
- * Stroke width of the progress circle.
35
- *
36
- * @default 6
37
- */
38
- progressWidth?: number
39
- /**
40
- * UI overrides for individual slots, derived from the scroll-to-top theme.
41
- */
42
- ui?: Partial<Record<keyof typeof scrollToTopTheme.base, string>>
43
- /**
44
- * External class — applied to the root element.
45
- */
46
- class?: string
47
- /**
48
- * Standard HTML attributes.
49
- */
50
- [key: string]: unknown
51
- }
52
-
53
- const scrollToTop = scv({
54
- slots: [...scrollToTopTheme.slots],
55
- base: scrollToTopTheme.base,
56
- variants: scrollToTopTheme.variants,
57
- compoundVariants: [...scrollToTopTheme.compoundVariants],
58
- defaultVariants: scrollToTopTheme.defaultVariants,
59
- classNameResolver: (...args) => twMerge(cx(...args))
60
- })
61
-
62
- const {
63
- color = "primary",
64
- progressWidth = 6,
65
- duration = 0.1,
66
- threshold = 200,
67
- showProgress = false,
68
- ui: uiProp,
69
- class: className,
70
- ...rest
71
- } = Astro.props as RLAScrollToTopProps
72
-
73
- const globalConfig = getUIConfig()
74
-
75
- const mergedUI = defu(
76
- uiProp ?? {},
77
- (globalConfig["scroll-to-top"] as Record<string, unknown>) ?? {}
78
- ) as Record<keyof typeof scrollToTopTheme.base, string | undefined>
79
-
80
- const { root, button, progressBase, svg: svgClass, iconContainer, icon } = scrollToTop({
81
- color
82
- })
83
-
84
- const circumference = 2 * Math.PI * 45
85
- const percentPx = circumference / 100
86
- ---
87
-
88
- <div
89
- class:list={["rla-scroll-to-top", "fixed bottom-6 right-6 z-50", twMerge(root, mergedUI.root, className)]}
90
- data-threshold={threshold}
91
- data-duration={duration}
92
- data-circle-stroke-width={progressWidth}
93
- {...rest}
94
- >
95
- <button
96
- type="button"
97
- class={twMerge(button, mergedUI.button)}
98
- aria-label="Scroll to top"
99
- data-scroll-to-top-button
100
- >
101
- <div class={twMerge(progressBase, mergedUI.progressBase)}>
102
- <svg class={twMerge(svgClass, mergedUI.svg)} viewBox="0 0 100 100" shape-rendering="geometricPrecision">
103
- <circle
104
- cx="50"
105
- cy="50"
106
- r="45"
107
- fill="var(--color-primary-950)"
108
- stroke-width={progressWidth}
109
- stroke-dashoffset="0"
110
- stroke-linecap="round"
111
- class="gauge-secondary-stroke opacity-100"
112
- />
113
- {showProgress && (
114
- <circle
115
- cx="50"
116
- cy="50"
117
- r="45"
118
- fill="transparent"
119
- stroke-width={progressWidth}
120
- stroke-dashoffset="0"
121
- stroke-linecap="round"
122
- class="gauge-primary-stroke opacity-100"
123
- data-progress-circle
124
- style={`--stroke-percent: 0; --percent-to-px: ${percentPx}px; --circumference: ${circumference}; --duration: ${duration}s`}
125
- />
126
- )}
127
- </svg>
128
- <div class={twMerge(iconContainer, mergedUI.iconContainer)}>
129
- <svg
130
- xmlns="http://www.w3.org/2000/svg"
131
- width="24"
132
- height="24"
133
- viewBox="0 0 24 24"
134
- fill="none"
135
- stroke="currentColor"
136
- stroke-width="2"
137
- stroke-linecap="round"
138
- stroke-linejoin="round"
139
- class={twMerge(icon, mergedUI.icon)}
140
- >
141
- <path d="m5 12 7-7 7 7" />
142
- <path d="M12 19V5" />
143
- </svg>
144
- </div>
145
- </div>
146
- </button>
147
- </div>
148
-
149
- <script>
150
- document.querySelectorAll('.rla-scroll-to-top').forEach((el) => {
151
- const element = el as HTMLElement
152
- const button = element.querySelector('[data-scroll-to-top-button]') as HTMLButtonElement | null
153
- const progressCircle = element.querySelector('[data-progress-circle]') as SVGCircleElement | null
154
-
155
- if (!button) return
156
-
157
- const threshold = Number(element.dataset.threshold) || 200
158
-
159
- function updateScrollState() {
160
- const scrollTop = window.scrollY || document.documentElement.scrollTop
161
- const scrollHeight = document.documentElement.scrollHeight - window.innerHeight
162
- const scrollPercentage = scrollHeight > 0 ? (scrollTop / scrollHeight) * 100 : 0
163
-
164
- if (scrollTop > threshold) {
165
- element.classList.add('visible')
166
- } else {
167
- element.classList.remove('visible')
168
- }
169
-
170
- if (progressCircle) {
171
- const circumference = 2 * Math.PI * 45
172
- const percentPx = circumference / 100
173
- const duration = element.dataset.duration || '0.1'
174
- progressCircle.style.setProperty('--stroke-percent', scrollPercentage.toString())
175
- progressCircle.style.setProperty('--percent-to-px', `${percentPx}px`)
176
- progressCircle.style.setProperty('--circumference', circumference.toString())
177
- progressCircle.style.setProperty('--duration', `${duration}s`)
178
- }
179
- }
180
-
181
- button.addEventListener('click', () => {
182
- window.scrollTo({ top: 0, behavior: 'smooth' })
183
- })
184
-
185
- window.addEventListener('scroll', updateScrollState, { passive: true })
186
- updateScrollState()
187
- })
188
- </script>
189
-
190
- <style>
191
- .rla-scroll-to-top {
192
- opacity: 0;
193
- pointer-events: none;
194
- transition: opacity 0.3s ease-in-out;
195
- }
196
-
197
- .rla-scroll-to-top.visible {
198
- opacity: 1;
199
- pointer-events: auto;
200
- }
201
-
202
- .progress-circle-base {
203
- transform: translateZ(0);
204
- }
205
-
206
- .gauge-primary-stroke {
207
- stroke: var(--color-primary-500);
208
- stroke-dasharray: calc(var(--stroke-percent, 0) * var(--percent-to-px, 2.826px)) var(--circumference, 282.6);
209
- transition: stroke-dasharray var(--duration, 0.1s) ease, stroke var(--duration, 0.1s) ease;
210
- transform: rotate(-90deg);
211
- transform-origin: center;
212
- shape-rendering: geometricPrecision;
213
- }
214
-
215
- .gauge-secondary-stroke {
216
- stroke: var(--color-primary-900);
217
- stroke-dasharray: 282.6;
218
- transform: rotate(-90deg);
219
- transform-origin: center;
220
- }
221
- </style>
1
+ ---
2
+ import { scv } from "css-variants"
3
+ import { useUi, resolveClasses } from "../../utils"
4
+ import type { ComponentVariants } from "../../types"
5
+ import scrollToTopTheme from "../../themes/scroll-to-top.theme"
6
+
7
+ const scrollToTop = scv(scrollToTopTheme)
8
+ type ScrollToTopVariants = ComponentVariants<typeof scrollToTopTheme>
9
+
10
+ export interface RLAScrollToTopProps {
11
+ color?: ScrollToTopVariants['color'];
12
+ progressWidth?: number;
13
+ duration?: number;
14
+ threshold?: number;
15
+ showProgress?: boolean;
16
+ ui?: Partial<Record<string, string>>;
17
+ class?: string;
18
+ [key: string]: unknown;
19
+ }
20
+
21
+ const {
22
+ color = "primary",
23
+ progressWidth = 6,
24
+ duration = 0.1,
25
+ threshold = 200,
26
+ showProgress = false,
27
+ ui: uiProp,
28
+ class: className,
29
+ ...rest
30
+ } = Astro.props as RLAScrollToTopProps
31
+
32
+ const classes = resolveClasses(scrollToTop, { color }, useUi("scrollToTop", uiProp), className)
33
+
34
+ const circumference = 2 * Math.PI * 45
35
+ const percentPx = circumference / 100
36
+ ---
37
+
38
+ <div
39
+ class:list={["rla-scroll-to-top", "fixed bottom-6 right-6 z-50", classes.root]}
40
+ data-threshold={threshold}
41
+ data-duration={duration}
42
+ data-circle-stroke-width={progressWidth}
43
+ {...rest}
44
+ >
45
+ <button
46
+ type="button"
47
+ class={classes.button}
48
+ aria-label="Scroll to top"
49
+ data-scroll-to-top-button
50
+ >
51
+ <div class={classes.progressBase}>
52
+ <svg class={classes.svg} viewBox="0 0 100 100" shape-rendering="geometricPrecision">
53
+ <circle
54
+ cx="50"
55
+ cy="50"
56
+ r="45"
57
+ fill="var(--color-primary-950)"
58
+ stroke-width={progressWidth}
59
+ stroke-dashoffset="0"
60
+ stroke-linecap="round"
61
+ class="gauge-secondary-stroke opacity-100"
62
+ />
63
+ {showProgress && (
64
+ <circle
65
+ cx="50"
66
+ cy="50"
67
+ r="45"
68
+ fill="transparent"
69
+ stroke-width={progressWidth}
70
+ stroke-dashoffset="0"
71
+ stroke-linecap="round"
72
+ class="gauge-primary-stroke opacity-100"
73
+ data-progress-circle
74
+ style={`--stroke-percent: 0; --percent-to-px: ${percentPx}px; --circumference: ${circumference}; --duration: ${duration}s`}
75
+ />
76
+ )}
77
+ </svg>
78
+ <div class={classes.iconContainer}>
79
+ <svg
80
+ xmlns="http://www.w3.org/2000/svg"
81
+ width="24"
82
+ height="24"
83
+ viewBox="0 0 24 24"
84
+ fill="none"
85
+ stroke="currentColor"
86
+ stroke-width="2"
87
+ stroke-linecap="round"
88
+ stroke-linejoin="round"
89
+ class={classes.icon}
90
+ >
91
+ <path d="m5 12 7-7 7 7" />
92
+ <path d="M12 19V5" />
93
+ </svg>
94
+ </div>
95
+ </div>
96
+ </button>
97
+ </div>
98
+
99
+ <script>
100
+ document.querySelectorAll('.rla-scroll-to-top').forEach((el) => {
101
+ const element = el as HTMLElement
102
+ const button = element.querySelector('[data-scroll-to-top-button]') as HTMLButtonElement | null
103
+ const progressCircle = element.querySelector('[data-progress-circle]') as SVGCircleElement | null
104
+
105
+ if (!button) return
106
+
107
+ const threshold = Number(element.dataset.threshold) || 200
108
+
109
+ function updateScrollState() {
110
+ const scrollTop = window.scrollY || document.documentElement.scrollTop
111
+ const scrollHeight = document.documentElement.scrollHeight - window.innerHeight
112
+ const scrollPercentage = scrollHeight > 0 ? (scrollTop / scrollHeight) * 100 : 0
113
+
114
+ if (scrollTop > threshold) {
115
+ element.classList.add('visible')
116
+ } else {
117
+ element.classList.remove('visible')
118
+ }
119
+
120
+ if (progressCircle) {
121
+ const circumference = 2 * Math.PI * 45
122
+ const percentPx = circumference / 100
123
+ const duration = element.dataset.duration || '0.1'
124
+ progressCircle.style.setProperty('--stroke-percent', scrollPercentage.toString())
125
+ progressCircle.style.setProperty('--percent-to-px', `${percentPx}px`)
126
+ progressCircle.style.setProperty('--circumference', circumference.toString())
127
+ progressCircle.style.setProperty('--duration', `${duration}s`)
128
+ }
129
+ }
130
+
131
+ button.addEventListener('click', () => {
132
+ window.scrollTo({ top: 0, behavior: 'smooth' })
133
+ })
134
+
135
+ window.addEventListener('scroll', updateScrollState, { passive: true })
136
+ updateScrollState()
137
+ })
138
+ </script>
139
+
140
+ <style>
141
+ .rla-scroll-to-top {
142
+ opacity: 0;
143
+ pointer-events: none;
144
+ transition: opacity 0.3s ease-in-out;
145
+ }
146
+
147
+ .rla-scroll-to-top.visible {
148
+ opacity: 1;
149
+ pointer-events: auto;
150
+ }
151
+
152
+ .progress-circle-base {
153
+ transform: translateZ(0);
154
+ }
155
+
156
+ .gauge-primary-stroke {
157
+ stroke: var(--color-primary-500);
158
+ stroke-dasharray: calc(var(--stroke-percent, 0) * var(--percent-to-px, 2.826px)) var(--circumference, 282.6);
159
+ transition: stroke-dasharray var(--duration, 0.1s) ease, stroke var(--duration, 0.1s) ease;
160
+ transform: rotate(-90deg);
161
+ transform-origin: center;
162
+ shape-rendering: geometricPrecision;
163
+ }
164
+
165
+ .gauge-secondary-stroke {
166
+ stroke: var(--color-primary-900);
167
+ stroke-dasharray: 282.6;
168
+ transform: rotate(-90deg);
169
+ transform-origin: center;
170
+ }
171
+ </style>
@@ -0,0 +1,181 @@
1
+ ---
2
+ import { scv } from "css-variants"
3
+ import { useUi, resolveClasses } from "../../utils"
4
+ import type { ComponentVariants } from "../../types"
5
+ import sectionTheme from "../../themes/section.theme"
6
+
7
+ const section = scv(sectionTheme)
8
+ type SectionVariants = ComponentVariants<typeof sectionTheme>
9
+
10
+ export interface RLASectionProps {
11
+ as?: string;
12
+ variant?: SectionVariants['variant'];
13
+ headline?: string;
14
+ icon?: string;
15
+ title?: string;
16
+ description?: string;
17
+ orientation?: SectionVariants['orientation'];
18
+ reverse?: boolean;
19
+ ctaVariant?: SectionVariants['ctaVariant'];
20
+ ui?: Partial<Record<string, string>>;
21
+ class?: string;
22
+ [key: string]: unknown;
23
+ }
24
+
25
+ const {
26
+ as = "section",
27
+ variant = "default",
28
+ orientation = "vertical",
29
+ reverse = false,
30
+ ctaVariant = "outline",
31
+ class: className,
32
+ ui: uiProp,
33
+ ...rest
34
+ } = Astro.props as RLASectionProps;
35
+
36
+ const classes = resolveClasses(section, {
37
+ variant,
38
+ orientation,
39
+ reverse,
40
+ ...(variant === "cta" && { ctaVariant }),
41
+ headline: Astro.slots.has("headline") || Astro.props.headline,
42
+ title: Astro.slots.has("title") || Astro.props.title,
43
+ description: Astro.slots.has("description") || Astro.props.description,
44
+ body: Astro.slots.has("body") || Astro.slots.has("features")
45
+ }, useUi("section", uiProp), className);
46
+
47
+ const Tag = as;
48
+ ---
49
+
50
+ <Tag
51
+ data-orientation={orientation}
52
+ data-slot="rla-section"
53
+ class:list={[classes.root]}
54
+ {...rest}
55
+ >
56
+ <slot name="background">
57
+ {Astro.slots.has("background") && (
58
+ <div class:list={[classes.background]} data-slot="background">
59
+ <slot name="background" />
60
+ </div>
61
+ )}
62
+ </slot>
63
+
64
+ <slot name="top" />
65
+
66
+ <div
67
+ data-slot="container"
68
+ class:list={[classes.container]}
69
+ >
70
+ {(Astro.slots.has("header") || Astro.props.icon || Astro.props.headline || Astro.props.title || Astro.props.description || Astro.slots.has("body") || Astro.slots.has("footer") || Astro.slots.has("links") || Astro.slots.has("features")) && (
71
+ <div
72
+ data-slot="wrapper"
73
+ class:list={[classes.wrapper]}
74
+ >
75
+ {(Astro.slots.has("header") || Astro.props.icon || Astro.props.headline || Astro.props.title || Astro.props.description) && (
76
+ <div
77
+ data-slot="header"
78
+ class:list={[classes.header]}
79
+ >
80
+ <slot name="header">
81
+ {(Astro.props.icon || Astro.slots.has("leading")) && (
82
+ <div
83
+ data-slot="leading"
84
+ class:list={[classes.leading]}
85
+ >
86
+ <slot name="leading" {...{ ui: classes }}>
87
+ {Astro.props.icon && (
88
+ <span
89
+ class:list={[classes.leadingIcon]}
90
+ data-slot="leading-icon"
91
+ >
92
+ <span class={Astro.props.icon} aria-hidden="true" />
93
+ </span>
94
+ )}
95
+ </slot>
96
+ </div>
97
+ )}
98
+
99
+ {(Astro.props.headline || Astro.slots.has("headline")) && (
100
+ <div
101
+ data-slot="headline"
102
+ class:list={[classes.headline]}
103
+ >
104
+ <slot name="headline">
105
+ {Astro.props.headline}
106
+ </slot>
107
+ </div>
108
+ )}
109
+
110
+ {(Astro.props.title || Astro.slots.has("title")) && (
111
+ <component
112
+ is={variant === "hero" ? "h1" : "h2"}
113
+ data-slot="title"
114
+ class:list={[classes.title]}
115
+ >
116
+ <slot name="title">
117
+ {Astro.props.title}
118
+ </slot>
119
+ </component>
120
+ )}
121
+
122
+ {(Astro.props.description || Astro.slots.has("description")) && (
123
+ <div
124
+ data-slot="description"
125
+ class:list={[classes.description]}
126
+ >
127
+ <slot name="description">
128
+ {Astro.props.description}
129
+ </slot>
130
+ </div>
131
+ )}
132
+ </slot>
133
+ </div>
134
+ )}
135
+
136
+ {(Astro.slots.has("body") || Astro.slots.has("features")) && (
137
+ <div
138
+ data-slot="body"
139
+ class:list={[classes.body]}
140
+ >
141
+ <slot name="body">
142
+ {Astro.slots.has("features") && (
143
+ <ul
144
+ data-slot="features"
145
+ class:list={[classes.features]}
146
+ >
147
+ <slot name="features" />
148
+ </ul>
149
+ )}
150
+ </slot>
151
+ </div>
152
+ )}
153
+
154
+ {(Astro.slots.has("footer") || Astro.slots.has("links")) && (
155
+ <div
156
+ data-slot="footer"
157
+ class:list={[classes.footer]}
158
+ >
159
+ <slot name="footer">
160
+ {Astro.slots.has("links") && (
161
+ <div
162
+ data-slot="links"
163
+ class:list={[classes.links]}
164
+ >
165
+ <slot name="links" />
166
+ </div>
167
+ )}
168
+ </slot>
169
+ </div>
170
+ )}
171
+ </div>
172
+ )}
173
+
174
+ <slot />
175
+ {orientation === "horizontal" && (
176
+ <div class="hidden lg:block" />
177
+ )}
178
+ </div>
179
+
180
+ <slot name="bottom" />
181
+ </Tag>