@rimelight/ui 0.0.24 → 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 (64) hide show
  1. package/package.json +7 -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 -118
  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 +172 -139
  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/plugins/index.ts +5 -2
  25. package/src/plugins/starlightAddons/index.ts +3 -64
  26. package/src/plugins/starlightDocsApi/components/ApiEmits.astro +46 -0
  27. package/src/plugins/starlightDocsApi/components/ApiProps.astro +47 -0
  28. package/src/plugins/starlightDocsApi/components/ApiSlots.astro +50 -0
  29. package/src/plugins/starlightDocsApi/components/ApiTheme.astro +27 -0
  30. package/src/plugins/starlightDocsApi/extract-vue.ts +286 -0
  31. package/src/plugins/starlightDocsApi/index.ts +265 -0
  32. package/src/plugins/starlightDocsApi/types.ts +40 -0
  33. package/src/plugins/starlightDocsApi/utils.ts +45 -0
  34. package/src/themes/button.theme.ts +29 -14
  35. package/src/themes/footer.theme.ts +4 -6
  36. package/src/themes/header.theme.ts +4 -28
  37. package/src/themes/icon.theme.ts +4 -2
  38. package/src/themes/index.ts +15 -20
  39. package/src/themes/logo.theme.ts +4 -2
  40. package/src/themes/placeholder.theme.ts +4 -6
  41. package/src/themes/scroll-to-top.theme.ts +4 -6
  42. package/src/themes/section.theme.ts +185 -0
  43. package/src/types/componentVariant.ts +10 -0
  44. package/src/types/index.ts +1 -0
  45. package/src/utils/defineTheme.ts +11 -0
  46. package/src/utils/index.ts +3 -0
  47. package/src/utils/resolveClasses.ts +21 -0
  48. package/src/utils/useUi.ts +19 -0
  49. package/src/composables/useUi.ts +0 -27
  50. package/src/plugins/starlightAddons/Sidebar.astro +0 -89
  51. package/src/plugins/starlightAddons/data.ts +0 -39
  52. package/src/plugins/starlightAddons/libs/config.ts +0 -107
  53. package/src/plugins/starlightAddons/libs/content.ts +0 -20
  54. package/src/plugins/starlightAddons/libs/i18n.ts +0 -51
  55. package/src/plugins/starlightAddons/libs/locals.ts +0 -12
  56. package/src/plugins/starlightAddons/libs/pathname.ts +0 -22
  57. package/src/plugins/starlightAddons/libs/plugin.ts +0 -9
  58. package/src/plugins/starlightAddons/libs/sidebar.ts +0 -183
  59. package/src/plugins/starlightAddons/libs/vite.ts +0 -46
  60. package/src/plugins/starlightAddons/locals.d.ts +0 -14
  61. package/src/plugins/starlightAddons/middleware.ts +0 -132
  62. package/src/plugins/starlightAddons/overrides/Sidebar.astro +0 -8
  63. package/src/plugins/starlightAddons/schema.ts +0 -13
  64. package/src/plugins/starlightAddons/virtual.d.ts +0 -13
@@ -0,0 +1,45 @@
1
+ import type { PropMeta, ThemeMeta } from "./types"
2
+
3
+ export function kebabToPascal(name: string): string {
4
+ return name
5
+ .split("-")
6
+ .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
7
+ .join("")
8
+ }
9
+
10
+ export function filterProps(
11
+ props: PropMeta[],
12
+ options: { hide?: string[]; show?: string[] }
13
+ ): PropMeta[] {
14
+ if (options.show?.length) {
15
+ return props.filter((p) => options.show!.includes(p.name))
16
+ }
17
+ if (options.hide?.length) {
18
+ return props.filter((p) => !options.hide!.includes(p.name))
19
+ }
20
+ return props
21
+ }
22
+
23
+ export function generateThemeCode(componentName: string, theme: ThemeMeta): string {
24
+ const componentConfig: Record<string, unknown> = {
25
+ ...(theme.slots.length ? { slots: theme.slots } : {}),
26
+ ...(Object.keys(theme.base).length ? { base: theme.base } : {}),
27
+ ...(Object.keys(theme.variants).length ? { variants: theme.variants } : {}),
28
+ ...(theme.compoundVariants.length ? { compoundVariants: theme.compoundVariants } : {}),
29
+ ...(Object.keys(theme.defaultVariants).length ? { defaultVariants: theme.defaultVariants } : {})
30
+ }
31
+
32
+ return `// astro.config.ts
33
+ import { ui } from "@rimelight/ui"
34
+ import { defineConfig } from "astro/config"
35
+
36
+ export default defineConfig({
37
+ integrations: [
38
+ ui({
39
+ components: {
40
+ ${componentName}: ${JSON.stringify(componentConfig, null, 6).replace(/\n/g, "\n ")}
41
+ }
42
+ })
43
+ ]
44
+ })`
45
+ }
@@ -1,8 +1,6 @@
1
- /**
2
- * Theme configuration for the Button component. Defines the slots, base styles, and an extensive
3
- * set of variants including color logic.
4
- */
5
- export const buttonTheme = {
1
+ import { defineTheme } from "../utils/defineTheme"
2
+
3
+ export default defineTheme({
6
4
  slots: ["root", "label", "leadingIcon", "trailingIcon"],
7
5
  base: {
8
6
  root: [
@@ -37,11 +35,31 @@ export const buttonTheme = {
37
35
  source: { root: "" }
38
36
  },
39
37
  size: {
40
- xs: { root: "h-7 px-2xs text-xs [&_svg]:size-3.5", leadingIcon: "[&_svg]:size-3.5", trailingIcon: "[&_svg]:size-3.5" },
41
- sm: { root: "h-8 px-xs text-sm [&_svg]:size-4", leadingIcon: "[&_svg]:size-4", trailingIcon: "[&_svg]:size-4" },
42
- md: { root: "h-9 px-sm text-sm [&_svg]:size-4", leadingIcon: "[&_svg]:size-4", trailingIcon: "[&_svg]:size-4" },
43
- lg: { root: "h-10 px-md text-base [&_svg]:size-4.5", leadingIcon: "[&_svg]:size-4.5", trailingIcon: "[&_svg]:size-4.5" },
44
- xl: { root: "h-11 px-lg text-base [&_svg]:size-5", leadingIcon: "[&_svg]:size-5", trailingIcon: "[&_svg]:size-5" }
38
+ xs: {
39
+ root: "h-7 px-2xs text-xs [&_svg]:size-3.5",
40
+ leadingIcon: "[&_svg]:size-3.5",
41
+ trailingIcon: "[&_svg]:size-3.5"
42
+ },
43
+ sm: {
44
+ root: "h-8 px-xs text-sm [&_svg]:size-4",
45
+ leadingIcon: "[&_svg]:size-4",
46
+ trailingIcon: "[&_svg]:size-4"
47
+ },
48
+ md: {
49
+ root: "h-9 px-sm text-sm [&_svg]:size-4",
50
+ leadingIcon: "[&_svg]:size-4",
51
+ trailingIcon: "[&_svg]:size-4"
52
+ },
53
+ lg: {
54
+ root: "h-10 px-md text-base [&_svg]:size-4.5",
55
+ leadingIcon: "[&_svg]:size-4.5",
56
+ trailingIcon: "[&_svg]:size-4.5"
57
+ },
58
+ xl: {
59
+ root: "h-11 px-lg text-base [&_svg]:size-5",
60
+ leadingIcon: "[&_svg]:size-5",
61
+ trailingIcon: "[&_svg]:size-5"
62
+ }
45
63
  },
46
64
  block: {
47
65
  true: { root: "w-full justify-center", trailingIcon: "ms-auto" }
@@ -373,7 +391,6 @@ export const buttonTheme = {
373
391
  root: "text-source-600 hover:underline hover:decoration-source/30"
374
392
  }
375
393
  },
376
- // soft variant compound variants
377
394
  {
378
395
  variant: "soft",
379
396
  color: "primary",
@@ -437,7 +454,6 @@ export const buttonTheme = {
437
454
  root: "text-source-600 bg-source/10 hover:bg-source/20 focus-visible:ring-source/40"
438
455
  }
439
456
  },
440
- // square + size compound variants (explicit width to match height)
441
457
  {
442
458
  square: true,
443
459
  size: "xs",
@@ -473,7 +489,6 @@ export const buttonTheme = {
473
489
  root: "p-2 w-11"
474
490
  }
475
491
  },
476
- // loading compound variants
477
492
  {
478
493
  loading: true,
479
494
  leading: true,
@@ -503,4 +518,4 @@ export const buttonTheme = {
503
518
  color: "primary",
504
519
  size: "md"
505
520
  }
506
- } as const
521
+ })
@@ -1,8 +1,6 @@
1
- /**
2
- * Theme configuration for the Footer component. Defines the slots, base styles, and variants for
3
- * layout management.
4
- */
5
- export const footerTheme = {
1
+ import { defineTheme } from "../utils/defineTheme"
2
+
3
+ export default defineTheme({
6
4
  slots: ["root", "container", "left", "center", "right"],
7
5
  base: {
8
6
  root: "py-8 lg:py-12",
@@ -26,4 +24,4 @@ export const footerTheme = {
26
24
  defaultVariants: {
27
25
  contain: false
28
26
  }
29
- } as const
27
+ })
@@ -1,25 +1,6 @@
1
- /**
2
- * Theme configuration for the Header component. Defines the slots, base styles, and variants for
3
- * layout management.
4
- *
5
- * Slots:
6
- *
7
- * - `root` — the `<header>` element
8
- * - `content` — inner wrapper div used for height measurement (fixed/hideOnScroll mode)
9
- * - `container` — max-width flex row
10
- * - `left` — left region
11
- * - `center` — center region
12
- * - `right` — right region
13
- *
14
- * Variants:
15
- *
16
- * - `contain` — constrains container to max-w-7xl
17
- * - `sticky` — sticky positioning (ignored when `fixed` variant is true)
18
- * - `fixed` — position: fixed with left/right 0 and smooth top/opacity transition; used for stacked
19
- * header layers. Top offset and z-index are applied via inline style (top prop + stackIndex prop)
20
- * rather than theme classes.
21
- */
22
- export const headerTheme = {
1
+ import { defineTheme } from "../utils/defineTheme"
2
+
3
+ export default defineTheme({
23
4
  slots: ["root", "content", "container", "left", "center", "right"],
24
5
  base: {
25
6
  root: "w-full",
@@ -47,11 +28,6 @@ export const headerTheme = {
47
28
  root: "relative"
48
29
  }
49
30
  },
50
- /**
51
- * Fixed-layer mode. When true, overrides sticky/relative positioning with `position: fixed` and
52
- * enables smooth transitions. `top` and `z-index` are applied via inline `:style` on the
53
- * component.
54
- */
55
31
  fixed: {
56
32
  true: {
57
33
  root: "fixed left-0 right-0 transition-[top,opacity] duration-200 ease-in-out"
@@ -64,4 +40,4 @@ export const headerTheme = {
64
40
  sticky: true,
65
41
  fixed: false
66
42
  }
67
- } as const
43
+ })
@@ -1,4 +1,6 @@
1
- export const iconTheme = {
1
+ import { defineTheme } from "../utils/defineTheme"
2
+
3
+ export default defineTheme({
2
4
  slots: ["root"],
3
5
  base: {
4
6
  root: ["inline-block", "align-middle"]
@@ -15,4 +17,4 @@ export const iconTheme = {
15
17
  defaultVariants: {
16
18
  size: "md"
17
19
  }
18
- } as const
20
+ })
@@ -1,23 +1,18 @@
1
- import { headerTheme } from "./header.theme"
2
- import { footerTheme } from "./footer.theme"
3
- import { scrollToTopTheme } from "./scroll-to-top.theme"
4
- import { buttonTheme } from "./button.theme"
5
- import { logoTheme } from "./logo.theme"
6
- import { iconTheme } from "./icon.theme"
7
- import { placeholderTheme } from "./placeholder.theme"
1
+ import type { ComponentTheme } from "../utils/defineTheme"
8
2
 
9
- /**
10
- * Default UI configuration for all components. This is the baseline that gets merged with
11
- * user-provided overrides via the Astro integration options.
12
- */
13
- export const defaultUIConfig = {
14
- "header": headerTheme,
15
- "footer": footerTheme,
16
- "logo": logoTheme,
17
- "scroll-to-top": scrollToTopTheme,
18
- "button": buttonTheme,
19
- "icon": iconTheme,
20
- "placeholder": placeholderTheme
21
- } as const
3
+ const themeModules = import.meta.glob<{ default: ComponentTheme }>("./*.theme.ts", { eager: true })
4
+
5
+ function kebabToCamel(str: string): string {
6
+ return str.replace(/-([a-z])/g, (_, char) => char.toUpperCase())
7
+ }
8
+
9
+ function themeNameFromFile(path: string): string {
10
+ const fileName = path.replace(/^\.\/|\.theme\.ts$/g, "")
11
+ return kebabToCamel(fileName)
12
+ }
13
+
14
+ export const defaultUIConfig: Record<string, ComponentTheme> = Object.fromEntries(
15
+ Object.entries(themeModules).map(([path, module]) => [themeNameFromFile(path), module.default])
16
+ )
22
17
 
23
18
  export type DefaultUIConfig = typeof defaultUIConfig
@@ -1,8 +1,10 @@
1
- export const logoTheme = {
1
+ import { defineTheme } from "../utils/defineTheme"
2
+
3
+ export default defineTheme({
2
4
  slots: ["root"],
3
5
  base: {
4
6
  root: "flex items-center justify-center transition-opacity hover:opacity-80 shrink-0 select-none overflow-hidden"
5
7
  },
6
8
  variants: {},
7
9
  defaultVariants: {}
8
- } as const
10
+ })
@@ -1,8 +1,6 @@
1
- /**
2
- * Theme configuration for the Placeholder component. Defines the slots, base styles for a
3
- * placeholder container with a decorative SVG pattern overlay.
4
- */
5
- export const placeholderTheme = {
1
+ import { defineTheme } from "../utils/defineTheme"
2
+
3
+ export default defineTheme({
6
4
  slots: ["base", "svg"],
7
5
  base: {
8
6
  base: "relative flex items-center justify-center overflow-hidden rounded-sm border-1 border-dashed border-primary px-4 opacity-75",
@@ -11,4 +9,4 @@ export const placeholderTheme = {
11
9
  variants: {},
12
10
  compoundVariants: [],
13
11
  defaultVariants: {}
14
- } as const
12
+ })
@@ -1,8 +1,6 @@
1
- /**
2
- * Theme configuration for the ScrollToTop component. Defines the slots, base styles, and variants
3
- * for the scroll-to-top button with progress indicator.
4
- */
5
- export const scrollToTopTheme = {
1
+ import { defineTheme } from "../utils/defineTheme"
2
+
3
+ export default defineTheme({
6
4
  slots: ["root", "button", "progressBase", "svg", "iconContainer", "icon"],
7
5
  base: {
8
6
  root: "fixed bottom-6 right-6 z-50",
@@ -45,4 +43,4 @@ export const scrollToTopTheme = {
45
43
  defaultVariants: {
46
44
  color: "primary"
47
45
  }
48
- } as const
46
+ })
@@ -0,0 +1,185 @@
1
+ import { defineTheme } from "../utils/defineTheme"
2
+
3
+ export default defineTheme({
4
+ slots: [
5
+ "root",
6
+ "background",
7
+ "container",
8
+ "wrapper",
9
+ "header",
10
+ "leading",
11
+ "leadingIcon",
12
+ "headline",
13
+ "title",
14
+ "description",
15
+ "body",
16
+ "features",
17
+ "footer",
18
+ "links"
19
+ ],
20
+ base: {
21
+ root: "relative isolate",
22
+ background: "absolute inset-0 -z-1 overflow-hidden",
23
+ container: "flex flex-col lg:grid gap-8 sm:gap-16",
24
+ wrapper: "",
25
+ header: "",
26
+ leading: "flex items-center mb-6",
27
+ leadingIcon: "size-10 shrink-0 text-primary",
28
+ headline: "mb-3",
29
+ title: "text-pretty tracking-tight font-bold text-highlighted",
30
+ description: "text-muted",
31
+ body: "mt-8",
32
+ features: "grid gap-8",
33
+ footer: "mt-8",
34
+ links: "flex flex-wrap gap-x-6 gap-y-3"
35
+ },
36
+ variants: {
37
+ variant: {
38
+ default: {
39
+ container: "py-16 sm:py-24 lg:py-32",
40
+ title: "text-3xl sm:text-4xl lg:text-5xl",
41
+ description: "text-base sm:text-lg",
42
+ features: "sm:grid-cols-2 lg:grid-cols-3"
43
+ },
44
+ hero: {
45
+ container: "py-24 sm:py-32 lg:py-40 gap-16 sm:gap-y-24",
46
+ title: "text-5xl sm:text-7xl",
47
+ description: "text-lg sm:text-xl/8",
48
+ headline: "mb-4",
49
+ leading: "mb-6",
50
+ body: "mt-10",
51
+ footer: "mt-10",
52
+ links: "mt-10"
53
+ },
54
+ cta: {
55
+ root: "rounded-xl overflow-hidden",
56
+ container: "px-6 py-12 sm:px-12 sm:py-24 lg:px-16 lg:py-24 gap-8 sm:gap-16",
57
+ title: "text-3xl sm:text-4xl",
58
+ description: "text-base sm:text-lg"
59
+ }
60
+ },
61
+ orientation: {
62
+ horizontal: {
63
+ container: "lg:grid-cols-2 lg:items-center",
64
+ description: "text-pretty",
65
+ features: "gap-4"
66
+ },
67
+ vertical: {
68
+ container: "",
69
+ headline: "justify-center",
70
+ leading: "justify-center",
71
+ title: "text-center",
72
+ description: "text-center text-balance",
73
+ links: "justify-center",
74
+ features: ""
75
+ }
76
+ },
77
+ reverse: {
78
+ true: {
79
+ wrapper: "order-last"
80
+ }
81
+ },
82
+ ctaVariant: {
83
+ solid: {
84
+ root: "bg-inverted text-inverted",
85
+ title: "text-inverted",
86
+ description: "text-dimmed"
87
+ },
88
+ outline: {
89
+ root: "bg-default ring ring-default",
90
+ description: "text-muted"
91
+ },
92
+ soft: {
93
+ root: "bg-elevated/50",
94
+ description: "text-toned"
95
+ },
96
+ subtle: {
97
+ root: "bg-elevated/50 ring ring-default",
98
+ description: "text-toned"
99
+ },
100
+ naked: {
101
+ description: "text-muted"
102
+ }
103
+ },
104
+ headline: {
105
+ true: {
106
+ headline: "font-semibold text-primary flex items-center gap-1.5"
107
+ }
108
+ },
109
+ title: {
110
+ true: {
111
+ description: "mt-6"
112
+ }
113
+ },
114
+ description: {
115
+ true: {}
116
+ },
117
+ body: {
118
+ true: {}
119
+ }
120
+ },
121
+ compoundVariants: [
122
+ {
123
+ variant: "default",
124
+ orientation: "vertical",
125
+ title: true,
126
+ classNames: {
127
+ body: "mt-16"
128
+ }
129
+ },
130
+ {
131
+ variant: "default",
132
+ orientation: "vertical",
133
+ description: true,
134
+ classNames: {
135
+ body: "mt-16"
136
+ }
137
+ },
138
+ {
139
+ variant: "default",
140
+ orientation: "vertical",
141
+ body: true,
142
+ classNames: {
143
+ footer: "mt-16"
144
+ }
145
+ },
146
+ {
147
+ variant: "cta",
148
+ ctaVariant: "outline",
149
+ classNames: {
150
+ root: "bg-default ring ring-default",
151
+ description: "text-muted"
152
+ }
153
+ },
154
+ {
155
+ variant: "cta",
156
+ ctaVariant: "solid",
157
+ classNames: {
158
+ root: "bg-inverted text-inverted",
159
+ title: "text-inverted",
160
+ description: "text-dimmed"
161
+ }
162
+ },
163
+ {
164
+ variant: "cta",
165
+ ctaVariant: "soft",
166
+ classNames: {
167
+ root: "bg-elevated/50",
168
+ description: "text-toned"
169
+ }
170
+ },
171
+ {
172
+ variant: "cta",
173
+ ctaVariant: "subtle",
174
+ classNames: {
175
+ root: "bg-elevated/50 ring ring-default",
176
+ description: "text-toned"
177
+ }
178
+ }
179
+ ],
180
+ defaultVariants: {
181
+ variant: "default",
182
+ orientation: "vertical",
183
+ ctaVariant: "outline"
184
+ }
185
+ })
@@ -0,0 +1,10 @@
1
+ export type ComponentVariants<T extends { variants?: Record<string, Record<string, unknown>> }> =
2
+ T["variants"] extends Record<string, Record<string, unknown>>
3
+ ? {
4
+ [K in keyof T["variants"]]?: T["variants"][K] extends { true: unknown; false: unknown }
5
+ ? boolean
6
+ : T["variants"][K] extends { true: unknown }
7
+ ? boolean
8
+ : keyof T["variants"][K]
9
+ }
10
+ : never
@@ -0,0 +1 @@
1
+ export * from "./componentVariant"
@@ -0,0 +1,11 @@
1
+ export interface ComponentTheme {
2
+ slots: string[]
3
+ base: Record<string, string | string[]>
4
+ variants?: Record<string, Record<string, Record<string, string | string[]>>>
5
+ compoundVariants?: Record<string, unknown>[]
6
+ defaultVariants?: Record<string, unknown>
7
+ }
8
+
9
+ export function defineTheme<const T extends ComponentTheme>(theme: T): T {
10
+ return theme
11
+ }
@@ -1 +1,4 @@
1
+ export * from "./defineTheme"
2
+ export * from "./resolveClasses"
3
+ export * from "./useUi.ts"
1
4
  export * from "./embed"
@@ -0,0 +1,21 @@
1
+ import { cx } from "css-variants"
2
+
3
+ export function resolveClasses<T extends (...args: never[]) => Record<string, string>>(
4
+ themeFn: T,
5
+ variants: Parameters<T>[0],
6
+ mergedUI: Record<string, string | undefined>,
7
+ rootClass?: string
8
+ ): Record<string, string> {
9
+ const resolved = themeFn(variants)
10
+ const result: Record<string, string> = {}
11
+
12
+ for (const [slot, value] of Object.entries(resolved)) {
13
+ result[slot] = cx(value, mergedUI[slot])
14
+ }
15
+
16
+ if (rootClass) {
17
+ result.root = cx(result.root ?? "", rootClass)
18
+ }
19
+
20
+ return result
21
+ }
@@ -0,0 +1,19 @@
1
+ import defu from "defu"
2
+ import { getUIConfig } from "virtual:rimelight-ui"
3
+ import type { DefaultUIConfig } from "../themes"
4
+
5
+ export function useUi(
6
+ componentName: keyof DefaultUIConfig,
7
+ uiProp?: Record<string, string | undefined>
8
+ ): Record<string, string | undefined> {
9
+ const globalConfig = getUIConfig()
10
+ const defaults = globalConfig[componentName] ?? {}
11
+ const merged = defu(uiProp ?? {}, defaults)
12
+
13
+ return Object.fromEntries(
14
+ Object.entries(merged).map(([key, value]) => [
15
+ key,
16
+ typeof value === "string" ? value : undefined
17
+ ])
18
+ )
19
+ }
@@ -1,27 +0,0 @@
1
- import { computed, type ComputedRef } from "vue"
2
- import defu from "defu"
3
- import { getUIConfig } from "virtual:rimelight-ui"
4
- import type { DefaultUIConfig } from "@/themes"
5
-
6
- /**
7
- * Reactive UI config merge composable for Vue components.
8
- *
9
- * Merges (highest priority first): 1. Local `ui` prop override 2. Global config from integration
10
- * (virtual:rimelight-ui)
11
- *
12
- * @param componentName - The component key in the config (e.g. 'button')
13
- * @param uiProp - The local `ui` prop from defineProps
14
- * @returns ComputedRef of merged UI overrides
15
- */
16
- export function useUi(
17
- componentName: keyof DefaultUIConfig,
18
- uiProp: Record<string, unknown> | undefined
19
- ): ComputedRef<Record<string, unknown>> {
20
- const globalConfig = getUIConfig()
21
-
22
- return computed(() => {
23
- const componentConfig = globalConfig[componentName]
24
-
25
- return defu(uiProp ?? {}, componentConfig ?? {})
26
- })
27
- }
@@ -1,89 +0,0 @@
1
- ---
2
- import { Badge, Icon } from '@astrojs/starlight/components'
3
-
4
- const { hasSidebar } = Astro.locals.starlightRoute
5
- const { isPageWithTopic, topics } = Astro.locals.starlightSidebarTopics
6
- ---
7
-
8
- {hasSidebar && isPageWithTopic && (
9
- <ul class="starlight-sidebar-topics">
10
- {topics.map((topic, index) => (
11
- <li key={index}>
12
- <a href={topic.link} class:list={{ 'starlight-sidebar-topics-current': topic.isCurrent }}>
13
- {topic.icon && (
14
- <div class="starlight-sidebar-topics-icon">
15
- <Icon name={topic.icon} />
16
- </div>
17
- )}
18
- <div>
19
- {topic.label}
20
- {topic.badge && (
21
- <Badge class="starlight-sidebar-topics-badge" text={topic.badge.text} variant={topic.badge.variant} />
22
- )}
23
- </div>
24
- </a>
25
- </li>
26
- ))}
27
- </ul>
28
- )}
29
- <style>
30
- ul {
31
- list-style: none;
32
- padding: 0;
33
- }
34
-
35
- ul::after {
36
- content: '';
37
- display: block;
38
- margin-top: 1rem;
39
- height: 1px;
40
- border-top: 1px solid var(--sl-color-hairline-light);
41
- }
42
-
43
- li {
44
- overflow-wrap: anywhere;
45
- }
46
-
47
- li + li {
48
- margin-top: 0.25rem;
49
- }
50
-
51
- a {
52
- align-items: center;
53
- color: var(--sl-color-white);
54
- display: flex;
55
- font-size: var(--sl-text-base);
56
- font-weight: 600;
57
- gap: 0.5rem;
58
- line-height: 1.5;
59
- padding: 0.3em 0.5rem;
60
- text-decoration: none;
61
- }
62
-
63
- a:is(.starlight-sidebar-topics-current, :hover, :focus-visible) {
64
- color: var(--sl-color-accent-high);
65
- }
66
-
67
- :global([data-theme='light']) a.starlight-sidebar-topics-current {
68
- color: var(--sl-color-accent);
69
- }
70
-
71
- .starlight-sidebar-topics-icon {
72
- align-items: center;
73
- border-radius: 0.25rem;
74
- border: 1px solid var(--sl-color-gray-4);
75
- display: flex;
76
- justify-content: center;
77
- padding: 0.25rem;
78
- }
79
-
80
- a:is(.starlight-sidebar-topics-current, :hover, :focus-visible) .starlight-sidebar-topics-icon {
81
- background-color: var(--sl-color-text-accent);
82
- border-color: var(--sl-color-text-accent);
83
- color: var(--sl-color-text-invert);
84
- }
85
-
86
- .starlight-sidebar-topics-badge {
87
- margin-inline-start: 0.25em;
88
- }
89
- </style>