@rimelight/ui 0.0.9 → 0.0.13

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rimelight/ui",
3
- "version": "0.0.9",
3
+ "version": "0.0.13",
4
4
  "private": false,
5
5
  "description": "Rimelight Entertainment UI Library.",
6
6
  "homepage": "https://rimelight.com/docs",
@@ -34,11 +34,15 @@
34
34
  "./utils": "./src/utils/index.ts",
35
35
  "./utils/*": "./src/utils/*",
36
36
  "./integrations": "./src/integrations/index.ts",
37
- "./integrations/vue-entrypoint": "./src/integrations/vue-entrypoint.ts",
38
37
  "./integrations/*": "./src/integrations/*",
38
+ "./integrations/vue-entrypoint": "./src/integrations/vue-entrypoint.ts",
39
+ "./plugins": "./src/plugins/index.ts",
40
+ "./plugins/*": "./src/plugins/*",
39
41
  "./middleware": "./src/middleware/index.ts",
40
42
  "./middleware/*": "./src/middleware/*",
41
43
  "./nuxt": "./src/nuxt.ts",
44
+ "./presets": "./src/presets/index.ts",
45
+ "./presets/*": "./src/presets/*",
42
46
  "./*": "./src/*"
43
47
  },
44
48
  "publishConfig": {
@@ -49,12 +53,16 @@
49
53
  "@iconify-json/lucide": "^1.2.102",
50
54
  "@nuxt/ui": "4.6.1",
51
55
  "@tailwindcss/vite": "^4.2.3",
56
+ "@unocss/astro": "^66.6.8",
52
57
  "css-variants": "2.3.5",
53
58
  "defu": "6.1.6",
54
59
  "embla-carousel": "8.6.0",
55
60
  "tailwind-merge": "^3.3.1",
56
61
  "tailwindcss": "^4.2.3",
57
- "unplugin-icons": "23.0.1"
62
+ "turndown": "^7.2.4",
63
+ "turndown-plugin-gfm": "^1.0.2",
64
+ "unplugin-icons": "23.0.1",
65
+ "vite-plugin-virtual": "^0.5.0"
58
66
  },
59
67
  "devDependencies": {
60
68
  "@astrojs/check": "0.9.8",
@@ -62,12 +70,13 @@
62
70
  "@e18e/eslint-plugin": "0.3.0",
63
71
  "@types/node": "25.5.2",
64
72
  "@unocss/eslint-plugin": "66.6.8",
65
- "astro": "6.1.4",
73
+ "astro": "6.1.8",
66
74
  "eslint-plugin-regexp": "3.1.0",
67
75
  "unocss": "66.6.8",
68
- "vite-plus": "0.1.18"
76
+ "vite-plus": "0.1.19"
69
77
  },
70
78
  "peerDependencies": {
79
+ "@astrojs/starlight": ">=0.5.0",
71
80
  "astro": ">=6.0.0",
72
81
  "vue": ">=3.4.0"
73
82
  },
@@ -2,7 +2,7 @@
2
2
  import { scv, cx } from "css-variants"
3
3
  import { twMerge } from "tailwind-merge"
4
4
  import defu from "defu"
5
- import { buttonTheme } from "@/themes/button.theme.ts"
5
+ import { buttonTheme } from "../../themes/button.theme.ts"
6
6
  import { getUIConfig } from "virtual:rimelight-ui"
7
7
 
8
8
  const button = scv({
@@ -2,7 +2,7 @@
2
2
  import { scv, cx } from "css-variants"
3
3
  import { twMerge } from "tailwind-merge"
4
4
  import defu from "defu"
5
- import { buttonTheme } from "@/themes/button.theme.ts"
5
+ import { buttonTheme } from "../../themes/button.theme.ts"
6
6
  import { getUIConfig } from "virtual:rimelight-ui"
7
7
 
8
8
  const button = scv({
@@ -60,6 +60,13 @@ const {
60
60
  href
61
61
  } = defineProps<RLVButtonProps>()
62
62
 
63
+ defineSlots<{
64
+ /**
65
+ * The default slot for the button content (e.g., text, icons).
66
+ */
67
+ default(props: {}): any
68
+ }>()
69
+
63
70
  const globalConfig = getUIConfig()
64
71
 
65
72
  const mergedUI = defu(
@@ -43,6 +43,21 @@ const {
43
43
  ui: uiProp
44
44
  } = defineProps<RLVHeaderProps>()
45
45
 
46
+ defineSlots<{
47
+ /**
48
+ * Content to display on the left side of the header (e.g., Logo).
49
+ */
50
+ left(props: {}): any
51
+ /**
52
+ * Content to display in the center of the header (e.g., Navigation Links).
53
+ */
54
+ center(props: {}): any
55
+ /**
56
+ * Content to display on the right side of the header (e.g., User Menu, Theme Toggle).
57
+ */
58
+ right(props: {}): any
59
+ }>()
60
+
46
61
  const mergedUI = useUi("header", uiProp as Record<string, unknown> | undefined)
47
62
 
48
63
  const resolvedClasses = computed(() => {
@@ -1,4 +1,5 @@
1
1
  import type { AstroIntegration } from "astro"
2
+ import UnoCSS from "unocss/astro"
2
3
  import vue from "@astrojs/vue"
3
4
  import uiPlugin from "@nuxt/ui/vite"
4
5
  import defu from "defu"
@@ -50,60 +51,64 @@ export function ui(options: UIOptions = {}): AstroIntegration[] {
50
51
  const virtualModuleId = "virtual:rimelight-ui"
51
52
  const resolvedVirtualModuleId = "\0" + virtualModuleId
52
53
 
54
+ function setViteConfig(updateConfig: (config: Record<string, unknown>) => void) {
55
+ updateConfig({
56
+ vite: {
57
+ optimizeDeps: {
58
+ exclude: [
59
+ "@rimelight/ui",
60
+ "@rimelight/ui/vue-plugin",
61
+ "@rimelight/ui/integrations/vue-entrypoint",
62
+ "@nuxt/ui"
63
+ ]
64
+ },
65
+ ssr: {
66
+ noExternal: ["@rimelight/ui", "@nuxt/ui"],
67
+ optimizeDeps: {
68
+ exclude: ["@rimelight/ui/vue-plugin", "@rimelight/ui/integrations/vue-entrypoint"]
69
+ }
70
+ },
71
+ plugins: [
72
+ uiPlugin({
73
+ router: false,
74
+ scanPackages: ["@rimelight/ui"]
75
+ }),
76
+ Icons({
77
+ compiler: "astro",
78
+ autoInstall: true
79
+ }),
80
+ tailwindcss(),
81
+ {
82
+ name: "vite-plugin-rimelight-ui-config",
83
+ enforce: "pre",
84
+ resolveId(id: string) {
85
+ if (id === virtualModuleId) return resolvedVirtualModuleId
86
+ return null
87
+ },
88
+ load(id: string) {
89
+ if (id === resolvedVirtualModuleId) {
90
+ return `export const getUIConfig = () => (${JSON.stringify(resolvedConfig)});`
91
+ }
92
+ return null
93
+ }
94
+ }
95
+ ]
96
+ }
97
+ })
98
+ }
99
+
53
100
  const rimelightUIIntegration: AstroIntegration = {
54
101
  name: "@rimelight/ui",
55
102
  hooks: {
56
103
  "astro:config:setup": ({ updateConfig, logger }) => {
57
104
  logger.info("Initializing @rimelight/ui core")
58
-
59
- updateConfig({
60
- vite: {
61
- optimizeDeps: {
62
- exclude: [
63
- "@rimelight/ui",
64
- "@rimelight/ui/vue-plugin",
65
- "@rimelight/ui/integrations/vue-entrypoint",
66
- "@nuxt/ui"
67
- ]
68
- },
69
- ssr: {
70
- noExternal: ["@rimelight/ui", "@nuxt/ui"],
71
- optimizeDeps: {
72
- exclude: ["@rimelight/ui/vue-plugin", "@rimelight/ui/integrations/vue-entrypoint"]
73
- }
74
- },
75
- plugins: [
76
- uiPlugin({
77
- router: false,
78
- scanPackages: ["@rimelight/ui"]
79
- }),
80
- Icons({
81
- compiler: "astro",
82
- autoInstall: true
83
- }),
84
- tailwindcss(),
85
- {
86
- name: "vite-plugin-rimelight-ui-config",
87
- enforce: "pre",
88
- resolveId(id: string) {
89
- if (id === virtualModuleId) return resolvedVirtualModuleId
90
- return null
91
- },
92
- load(id: string) {
93
- if (id === resolvedVirtualModuleId) {
94
- return `export const getUIConfig = () => (${JSON.stringify(resolvedConfig)});`
95
- }
96
- return null
97
- }
98
- }
99
- ] as any
100
- }
101
- })
105
+ setViteConfig(updateConfig)
102
106
  }
103
107
  }
104
108
  }
105
109
 
106
110
  return [
111
+ UnoCSS(),
107
112
  vue({
108
113
  appEntrypoint: "@rimelight/ui/integrations/vue-entrypoint"
109
114
  }),
@@ -0,0 +1,2 @@
1
+ export { default as starlightAddons } from "../plugins/starlightAddons"
2
+ export type { StarlightAddonsConfig } from "../plugins/starlightAddons"
@@ -0,0 +1,114 @@
1
+ ---
2
+ import DefaultPageTitle from "@astrojs/starlight/components/PageTitle.astro";
3
+ import config from "virtual:rimelight-starlight-addons-config";
4
+
5
+ const { copy = true, share = true } = config ?? {};
6
+
7
+ const currentUrl = Astro.url.href;
8
+ const currentTitle = (Astro.locals as any).starlightRoute?.entry?.data?.title || "";
9
+ ---
10
+
11
+ <DefaultPageTitle />
12
+ {(copy || share) && (
13
+ <div class="rl-addons">
14
+ {copy && (
15
+ <button class="rl-addon-btn" id="rl-copy-markdown" title="Copy Markdown">
16
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>
17
+ </button>
18
+ )}
19
+ {share && (
20
+ <button class="rl-addon-btn" id="rl-share" title="Share">
21
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" x2="15.42" y1="13.51" y2="17.49"/><line x1="15.41" x2="8.59" y1="6.51" y2="10.49"/></svg>
22
+ </button>
23
+ )}
24
+ </div>
25
+ )}
26
+
27
+ <style>
28
+ .rl-addons {
29
+ display: flex;
30
+ gap: 0.5rem;
31
+ align-items: center;
32
+ }
33
+
34
+ .rl-addon-btn {
35
+ background-color: var(--sl-color-gray-6);
36
+ color: var(--sl-color-white);
37
+ border: 1px solid var(--sl-color-gray-5);
38
+ padding: 0.5rem;
39
+ border-radius: 0.25rem;
40
+ cursor: pointer;
41
+ display: flex;
42
+ align-items: center;
43
+ justify-content: center;
44
+ transition: background-color 0.2s ease;
45
+ height: 2rem;
46
+ width: 2rem;
47
+ }
48
+
49
+ .rl-addon-btn:hover {
50
+ background-color: var(--sl-color-gray-5);
51
+ }
52
+
53
+ .rl-addon-btn:disabled {
54
+ opacity: 0.7;
55
+ cursor: not-allowed;
56
+ }
57
+ </style>
58
+
59
+ <script>
60
+ import TurndownService from "turndown";
61
+ import { gfm } from "turndown-plugin-gfm";
62
+
63
+ const turndown = new TurndownService({
64
+ headingStyle: "atx",
65
+ codeBlockStyle: "fenced",
66
+ bulletListMarker: "-",
67
+ });
68
+ turndown.use(gfm);
69
+
70
+ const copyBtn = document.getElementById("rl-copy-markdown");
71
+ const shareBtn = document.getElementById("rl-share");
72
+
73
+ if (copyBtn) {
74
+ copyBtn.addEventListener("click", async () => {
75
+ try {
76
+ copyBtn.disabled = true;
77
+ const contentEl = document.querySelector("main .sl-markdown-content");
78
+ if (!contentEl) {
79
+ throw new Error("Content not found");
80
+ }
81
+ const clone = contentEl.cloneNode(true);
82
+ clone.querySelectorAll("script, style, noscript, .sl-anchor-link, [data-pagefind-ignore]").forEach(el => el.remove());
83
+ const markdown = turndown.turndown(clone as HTMLElement);
84
+ await navigator.clipboard.writeText(markdown);
85
+ copyBtn.classList.add("copied");
86
+ setTimeout(() => copyBtn.classList.remove("copied"), 2000);
87
+ } catch (err) {
88
+ console.error("Failed to copy:", err);
89
+ } finally {
90
+ copyBtn.disabled = false;
91
+ }
92
+ });
93
+ }
94
+
95
+ if (shareBtn) {
96
+ shareBtn.addEventListener("click", async () => {
97
+ if (navigator.share) {
98
+ try {
99
+ await navigator.share({ title: document.title, url: window.location.href });
100
+ } catch (err) {
101
+ if (err.name !== "AbortError") {
102
+ console.error("Share failed:", err);
103
+ }
104
+ }
105
+ } else {
106
+ try {
107
+ await navigator.clipboard.writeText(window.location.href);
108
+ } catch (err) {
109
+ console.error("Failed to copy link:", err);
110
+ }
111
+ }
112
+ });
113
+ }
114
+ </script>
@@ -0,0 +1,57 @@
1
+ import type { StarlightPlugin } from "@astrojs/starlight/types"
2
+ import virtual from "vite-plugin-virtual"
3
+ import path from "node:path"
4
+ import { fileURLToPath } from "node:url"
5
+
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
7
+
8
+ export interface StarlightAddonsConfig {
9
+ copy?: boolean
10
+ share?: boolean
11
+ }
12
+
13
+ export default function starlightAddons(userConfig?: StarlightAddonsConfig): StarlightPlugin {
14
+ const defaultConfig: StarlightAddonsConfig = {
15
+ copy: true,
16
+ share: true
17
+ }
18
+
19
+ const config: StarlightAddonsConfig = {
20
+ ...defaultConfig,
21
+ ...userConfig
22
+ }
23
+
24
+ return {
25
+ name: "rimelight-ui-starlight-addons",
26
+ hooks: {
27
+ "config:setup"({ addIntegration, updateConfig, logger }) {
28
+ if (!config.copy && !config.share) {
29
+ logger.warn("StarlightAddons: Nothing enabled.")
30
+ }
31
+
32
+ addIntegration({
33
+ name: "rimelight-ui-starlight-addons-integration",
34
+ hooks: {
35
+ "astro:config:setup": ({ updateConfig: updateAstroConfig }) => {
36
+ updateAstroConfig({
37
+ vite: {
38
+ plugins: [
39
+ virtual({
40
+ "virtual:rimelight-starlight-addons-config": `export default ${JSON.stringify(config)}`
41
+ })
42
+ ]
43
+ }
44
+ } as Record<string, unknown>)
45
+ }
46
+ }
47
+ })
48
+
49
+ updateConfig({
50
+ components: {
51
+ PageTitle: path.join(__dirname, "PageTitle.astro")
52
+ }
53
+ })
54
+ }
55
+ }
56
+ }
57
+ }
package/src/preset.ts ADDED
@@ -0,0 +1,408 @@
1
+ import {
2
+ definePreset,
3
+ presetTypography,
4
+ presetWind4,
5
+ transformerDirectives,
6
+ transformerVariantGroup
7
+ } from "unocss"
8
+
9
+ export default definePreset(() => {
10
+ return {
11
+ name: "rimelight-ui",
12
+ presets: [
13
+ presetWind4(),
14
+ presetTypography({
15
+ cssExtend: {
16
+ "h1,h2,h3,h4,h5,h6": {
17
+ "font-family": "var(--font-sans), system-ui, sans-serif"
18
+ },
19
+ "p,li,blockquote,code": {
20
+ "font-family": "var(--font-sans), system-ui, sans-serif"
21
+ },
22
+ "pre,code": {
23
+ "font-family": "var(--font-mono), monospace"
24
+ }
25
+ }
26
+ })
27
+ ],
28
+ transformers: [transformerDirectives(), transformerVariantGroup()],
29
+
30
+ // Enable CSS Cascade Layers for better specificity control
31
+ outputToCssLayers: true,
32
+ layers: {
33
+ theme: 1,
34
+ preflights: 2,
35
+ shortcuts: 3,
36
+ default: 4
37
+ },
38
+
39
+ // Tighten content scanning for better performance
40
+ content: {
41
+ pipeline: {
42
+ include: [
43
+ /\.(vue|svelte|[jt]sx|mdx?|astro|elm|php|phtml|html)($|\?)/,
44
+ "src/**/*.{js,ts,jsx,tsx,vue,svelte,astro}",
45
+ "../ui/src/**/*.{js,ts,jsx,tsx,vue,svelte,astro}"
46
+ ]
47
+ },
48
+ filesystem: ["../ui/src/**/*", "src/components/**/*", "src/pages/**/*"]
49
+ },
50
+
51
+ shortcuts: {
52
+ // Layout & Components
53
+ "container": "mx-auto w-full max-w-90rem px-md",
54
+ "sr-only":
55
+ "absolute w-px h-px p-0 m-0 overflow-hidden clip-rect-1-1-1-1 whitespace-nowrap border-0"
56
+ },
57
+ rules: [
58
+ [
59
+ /^clip-rect-(\d+)-(\d+)-(\d+)-(\d+)$/,
60
+ ([, t, r, b, l]) => ({ clip: `rect(${t}px, ${r}px, ${b}px, ${l}px)` })
61
+ ],
62
+ [
63
+ /^([hw])-(6xs|5xs|4xs|3xs|2xs|xs|sm|md|lg|xl|2xl|3xl|4xl|5xl|6xl)$/,
64
+ ([, prop, s], { theme }) => {
65
+ if (!s) return
66
+ const val = (theme as { spacing?: Record<string, string> }).spacing?.[s]
67
+ if (!val) return
68
+ return prop === "h" ? { height: val } : { width: val }
69
+ }
70
+ ]
71
+ ],
72
+
73
+ theme: {
74
+ spacing: {
75
+ // 2px
76
+ "6xs": "0.125rem",
77
+ // 4px
78
+ "5xs": "0.25rem",
79
+ // 6px
80
+ "4xs": "0.375rem",
81
+ // 8px
82
+ "3xs": "0.5rem",
83
+ // 10px
84
+ "2xs": "0.625rem",
85
+ // 12px
86
+ "xs": "0.75rem",
87
+ // 14px
88
+ "sm": "0.875rem",
89
+ // 16px
90
+ "md": "1rem",
91
+ // 20px
92
+ "lg": "1.25rem",
93
+ // 24px
94
+ "xl": "1.5rem",
95
+ // 32px
96
+ "2xl": "2rem",
97
+ // 48px
98
+ "3xl": "3rem",
99
+ // 64px
100
+ "4xl": "4rem",
101
+ // 96px
102
+ "5xl": "6rem",
103
+ // 128px
104
+ "6xl": "8rem"
105
+ },
106
+ colors: {
107
+ "background": "var(--background)",
108
+ "foreground": "var(--foreground)",
109
+ "card": {
110
+ DEFAULT: "var(--card)",
111
+ foreground: "var(--card-foreground)"
112
+ },
113
+ "popover": {
114
+ DEFAULT: "var(--popover)",
115
+ foreground: "var(--popover-foreground)"
116
+ },
117
+ "primary": {
118
+ DEFAULT: "var(--primary)",
119
+ foreground: "var(--primary-foreground)",
120
+ accent: "var(--primary-accent)"
121
+ },
122
+ "secondary": {
123
+ DEFAULT: "var(--secondary)",
124
+ foreground: "var(--secondary-foreground)",
125
+ accent: "var(--secondary-accent)"
126
+ },
127
+ "muted": {
128
+ DEFAULT: "var(--muted)",
129
+ foreground: "var(--muted-foreground)"
130
+ },
131
+ "accent": {
132
+ DEFAULT: "var(--accent)",
133
+ foreground: "var(--accent-foreground)"
134
+ },
135
+ "info": {
136
+ DEFAULT: "var(--info)",
137
+ foreground: "var(--info-foreground)"
138
+ },
139
+ "success": {
140
+ DEFAULT: "var(--success)",
141
+ foreground: "var(--success-foreground)"
142
+ },
143
+ "warning": {
144
+ DEFAULT: "var(--warning)",
145
+ foreground: "var(--warning-foreground)"
146
+ },
147
+ "error": {
148
+ DEFAULT: "var(--error)",
149
+ foreground: "var(--error-foreground)"
150
+ },
151
+ "commentary": {
152
+ DEFAULT: "var(--commentary)",
153
+ foreground: "var(--commentary-foreground)"
154
+ },
155
+ "ideation": {
156
+ DEFAULT: "var(--ideation)",
157
+ foreground: "var(--ideation-foreground)"
158
+ },
159
+ "source": {
160
+ DEFAULT: "var(--source)",
161
+ foreground: "var(--source-foreground)"
162
+ },
163
+ "border": "var(--border)",
164
+ "input": "var(--input)",
165
+ "outline": "var(--outline)",
166
+ "ring": "var(--ring)",
167
+ "destructive": {
168
+ DEFAULT: "var(--destructive)",
169
+ subtle: "var(--color-destructive-subtle)"
170
+ },
171
+ "sidebar": {
172
+ DEFAULT: "var(--sidebar)",
173
+ foreground: "var(--sidebar-foreground)",
174
+ primary: {
175
+ DEFAULT: "var(--sidebar-primary)",
176
+ foreground: "var(--sidebar-primary-foreground)"
177
+ },
178
+ accent: {
179
+ DEFAULT: "var(--sidebar-accent)",
180
+ foreground: "var(--sidebar-accent-foreground)"
181
+ },
182
+ border: "var(--sidebar-border)",
183
+ ring: "var(--sidebar-ring)"
184
+ },
185
+ "chart": {
186
+ "1": "var(--chart-1)",
187
+ "2": "var(--chart-2)",
188
+ "3": "var(--chart-3)",
189
+ "4": "var(--chart-4)",
190
+ "5": "var(--chart-5)"
191
+ },
192
+ "hover": "var(--color-hover)",
193
+ "surface": "var(--color-surface)",
194
+ "muted-strong": "var(--color-muted-strong)",
195
+ "foreground-secondary": "var(--color-foreground-secondary)",
196
+ "foreground-tertiary": "var(--color-foreground-tertiary)",
197
+ "placeholder": "var(--color-placeholder)",
198
+ "input-border": "var(--color-input-border)",
199
+ "accent-subtle": "var(--color-accent-subtle)"
200
+ },
201
+ radius: {
202
+ "xs": "calc(var(--radius) - 0.375rem)",
203
+ "sm": "calc(var(--radius) - 0.25rem)",
204
+ "md": "calc(var(--radius) - 0.125rem)",
205
+ "lg": "var(--radius)",
206
+ "xl": "calc(var(--radius) + 0.25rem)",
207
+ "2xl": "calc(var(--radius) + 0.5rem)",
208
+ "3xl": "calc(var(--radius) + 1rem)"
209
+ },
210
+ animation: {
211
+ keyframes: {
212
+ "accordion-down":
213
+ "{ from { height: 0; } to { height: var(--starwind-accordion-content-height); } }",
214
+ "accordion-up":
215
+ "{ from { height: var(--starwind-accordion-content-height); } to { height: 0; } }",
216
+ "marquee": "{ from { transform: translateX(0); } to { transform: translateX(-100%); } }"
217
+ },
218
+ durations: {
219
+ "accordion-down": "0.2s",
220
+ "accordion-up": "0.2s",
221
+ "marquee": "30s"
222
+ },
223
+ timingFns: {
224
+ "accordion-down": "ease-out",
225
+ "accordion-up": "ease-out",
226
+ "marquee": "linear"
227
+ },
228
+ counts: { marquee: "infinite" }
229
+ }
230
+ },
231
+
232
+ preflights: [
233
+ {
234
+ getCSS: () => `
235
+ :root {
236
+ --background: #ffffff;
237
+ --foreground: #030712;
238
+ --card: #ffffff;
239
+ --card-foreground: #030712;
240
+ --popover: #ffffff;
241
+ --popover-foreground: #030712;
242
+ --primary: #f97316;
243
+ --primary-foreground: #f9fafb;
244
+ --primary-accent: #ea580c;
245
+ --secondary: #8b5cf6;
246
+ --secondary-foreground: #f9fafb;
247
+ --secondary-accent: #7c3aed;
248
+ --muted: #f3f4f6;
249
+ --muted-foreground: #4b5563;
250
+ --accent: #f3f4f6;
251
+ --accent-foreground: #111827;
252
+ --info: #3b82f6;
253
+ --info-foreground: #ffffff;
254
+ --success: #22c55e;
255
+ --success-foreground: #ffffff;
256
+ --warning: #f59e0b;
257
+ --warning-foreground: #000000;
258
+ --error: #ef4444;
259
+ --error-foreground: #f9fafb;
260
+ --commentary: #ec4899;
261
+ --commentary-foreground: #f9fafb;
262
+ --ideation: #8b5cf6;
263
+ --ideation-foreground: #f9fafb;
264
+ --source: #38bdf8;
265
+ --source-foreground: #0f172a;
266
+ --border: #e5e7eb;
267
+ --input: #e5e7eb;
268
+ --outline: #9ca3af;
269
+ --ring: #9ca3af;
270
+ --radius: 0.625rem;
271
+ --sidebar: #f9fafb;
272
+ --sidebar-foreground: #030712;
273
+ --sidebar-primary: #1d4ed8;
274
+ --sidebar-primary-foreground: #f9fafb;
275
+ --sidebar-accent: #f3f4f6;
276
+ --sidebar-accent-foreground: #111827;
277
+ --sidebar-border: #e5e7eb;
278
+ --sidebar-ring: #9ca3af;
279
+ --chart-1: #3b82f6;
280
+ --chart-2: #6366f1;
281
+ --chart-3: #8b5cf6;
282
+ --chart-4: #a855f7;
283
+ --chart-5: #ec4899;
284
+ --destructive: #ef4444;
285
+ --color-surface: #ffffff;
286
+ --color-muted-strong: #e5e7eb;
287
+ --color-foreground-secondary: #4b5563;
288
+ --color-foreground-tertiary: #6b7280;
289
+ --color-placeholder: #9ca3af;
290
+ --color-input-border: #d1d5db;
291
+ --color-hover: #f3f4f6;
292
+ --color-destructive-subtle: #fef2f2;
293
+ --color-accent-subtle: #eff6ff;
294
+ --font-sans: "Noto Sans", sans-serif;
295
+ --font-serif: "Noto Serif", serif;
296
+ --font-mono: "Noto Sans Mono", monospace;
297
+ }
298
+
299
+ .dark {
300
+ --background: #030712;
301
+ --foreground: #f9fafb;
302
+ --card: #111827;
303
+ --card-foreground: #f9fafb;
304
+ --popover: #1f2937;
305
+ --popover-foreground: #f9fafb;
306
+ --primary: #f97316;
307
+ --primary-foreground: #f9fafb;
308
+ --primary-accent: #fb923c;
309
+ --secondary: #8b5cf6;
310
+ --secondary-foreground: #f9fafb;
311
+ --secondary-accent: #a78bfa;
312
+ --muted: #1f2937;
313
+ --muted-foreground: #9ca3af;
314
+ --accent: #374151;
315
+ --accent-foreground: #f3f4f6;
316
+ --info: #3b82f6;
317
+ --info-foreground: #ffffff;
318
+ --success: #22c55e;
319
+ --success-foreground: #ffffff;
320
+ --warning: #f59e0b;
321
+ --warning-foreground: #000000;
322
+ --error: #ef4444;
323
+ --error-foreground: #f9fafb;
324
+ --commentary: #f472b6;
325
+ --commentary-foreground: #0f172a;
326
+ --ideation: #a78bfa;
327
+ --ideation-foreground: #0f172a;
328
+ --source: #7dd3fc;
329
+ --source-foreground: #0f172a;
330
+ --border: rgba(249, 250, 251, 0.1);
331
+ --input: rgba(249, 250, 251, 0.15);
332
+ --outline: #6b7280;
333
+ --ring: #6b7280;
334
+ --sidebar: #111827;
335
+ --sidebar-foreground: #f9fafb;
336
+ --sidebar-primary: #1d4ed8;
337
+ --sidebar-primary-foreground: #f9fafb;
338
+ --sidebar-accent: #1f2937;
339
+ --sidebar-accent-foreground: #f3f4f6;
340
+ --sidebar-border: #1f2937;
341
+ --sidebar-ring: #6b7280;
342
+ --chart-1: #60a5fa;
343
+ --chart-2: #818cf8;
344
+ --chart-3: #a78bfa;
345
+ --chart-4: #c084fc;
346
+ --chart-5: #f472b6;
347
+ --destructive: #f87171;
348
+ --color-surface: #1f2937;
349
+ --color-muted-strong: #374151;
350
+ --color-foreground-secondary: #d1d5db;
351
+ --color-foreground-tertiary: #9ca3af;
352
+ --color-placeholder: #6b7280;
353
+ --color-input-border: #4b5563;
354
+ --color-hover: #374151;
355
+ --color-destructive-subtle: #451a1a;
356
+ --color-accent-subtle: #1e293b;
357
+ }
358
+
359
+ * {
360
+ border-color: var(--border);
361
+ outline-color: rgba(156, 163, 175, 0.5);
362
+ }
363
+
364
+ body {
365
+ background-color: var(--background);
366
+ color: var(--foreground);
367
+ font-family: var(--font-sans);
368
+ }
369
+
370
+ button {
371
+ cursor: pointer;
372
+ }
373
+
374
+ ::selection {
375
+ background-color: var(--primary);
376
+ color: var(--primary-foreground);
377
+ }
378
+
379
+ @view-transition {
380
+ navigation: auto;
381
+ }
382
+ `
383
+ }
384
+ ],
385
+
386
+ async configResolved(config) {
387
+ // Only log in dev mode and only once per process
388
+ if (process.env.NODE_ENV === "development" && !process.env.UNO_CONFIG_LOGGED) {
389
+ process.env.UNO_CONFIG_LOGGED = "true"
390
+
391
+ console.log(
392
+ `[UnoCSS] Config resolved. Presets: ${config.presets.map((p) => p.name).join(", ")}`
393
+ )
394
+ console.log(`[UnoCSS] Total rules: ${config.rules.length}`)
395
+ console.log(`[UnoCSS] Total shortcuts: ${Object.keys(config.shortcuts).length}`)
396
+
397
+ // Collision Detection: Identify potential conflicting regex rules
398
+ const ruleNames = config.rules.map((r) => (Array.isArray(r) ? r[0].toString() : "dynamic"))
399
+ const duplicates = ruleNames.filter((item, index) => ruleNames.indexOf(item) !== index)
400
+ const filteredDuplicates = duplicates.filter((d) => d !== "/^(.+?)-(\\$.+)$/")
401
+
402
+ if (filteredDuplicates.length > 0) {
403
+ console.warn(`[UnoCSS] Potential Rule Collisions: ${filteredDuplicates.join(", ")}`)
404
+ }
405
+ }
406
+ }
407
+ }
408
+ })
@@ -0,0 +1,379 @@
1
+ import {
2
+ definePreset,
3
+ presetTypography,
4
+ presetWind4,
5
+ transformerDirectives,
6
+ transformerVariantGroup
7
+ } from "unocss"
8
+
9
+ export default definePreset(() => {
10
+ return {
11
+ name: "rimelight-ui",
12
+ presets: [
13
+ presetWind4(),
14
+ presetTypography({
15
+ cssExtend: {
16
+ "h1,h2,h3,h4,h5,h6": {
17
+ "font-family": "var(--font-sans), system-ui, sans-serif"
18
+ },
19
+ "p,li,blockquote,code": {
20
+ "font-family": "var(--font-sans), system-ui, sans-serif"
21
+ },
22
+ "pre,code": {
23
+ "font-family": "var(--font-mono), monospace"
24
+ }
25
+ }
26
+ })
27
+ ],
28
+ transformers: [transformerDirectives(), transformerVariantGroup()],
29
+
30
+ outputToCssLayers: true,
31
+ layers: {
32
+ theme: 1,
33
+ preflights: 2,
34
+ shortcuts: 3,
35
+ default: 4
36
+ },
37
+
38
+ content: {
39
+ pipeline: {
40
+ include: [
41
+ /\.(vue|svelte|[jt]sx|mdx?|astro|elm|php|phtml|html)($|\?)/,
42
+ "src/**/*.{js,ts,jsx,tsx,vue,svelte,astro}",
43
+ "../ui/src/**/*.{js,ts,jsx,tsx,vue,svelte,astro}"
44
+ ]
45
+ },
46
+ filesystem: ["../ui/src/**/*", "src/components/**/*", "src/pages/**/*"]
47
+ },
48
+
49
+ shortcuts: {
50
+ "container": "mx-auto w-full max-w-90rem px-md",
51
+ "sr-only":
52
+ "absolute w-px h-px p-0 m-0 overflow-hidden clip-rect-1-1-1-1 whitespace-nowrap border-0"
53
+ },
54
+ rules: [
55
+ [
56
+ /^clip-rect-(\d+)-(\d+)-(\d+)-(\d+)$/,
57
+ ([, t, r, b, l]) => ({ clip: `rect(${t}px, ${r}px, ${b}px, ${l}px)` })
58
+ ]
59
+ ],
60
+
61
+ theme: {
62
+ spacing: {
63
+ "6xs": "0.125rem",
64
+ "5xs": "0.25rem",
65
+ "4xs": "0.375rem",
66
+ "3xs": "0.5rem",
67
+ "2xs": "0.625rem",
68
+ "xs": "0.75rem",
69
+ "sm": "0.875rem",
70
+ "md": "1rem",
71
+ "lg": "1.25rem",
72
+ "xl": "1.5rem",
73
+ "2xl": "2rem",
74
+ "3xl": "3rem",
75
+ "4xl": "4rem",
76
+ "5xl": "6rem",
77
+ "6xl": "8rem"
78
+ },
79
+ colors: {
80
+ "background": "var(--background)",
81
+ "foreground": "var(--foreground)",
82
+ "card": {
83
+ DEFAULT: "var(--card)",
84
+ foreground: "var(--card-foreground)"
85
+ },
86
+ "popover": {
87
+ DEFAULT: "var(--popover)",
88
+ foreground: "var(--popover-foreground)"
89
+ },
90
+ "primary": {
91
+ DEFAULT: "var(--primary)",
92
+ foreground: "var(--primary-foreground)",
93
+ accent: "var(--primary-accent)"
94
+ },
95
+ "secondary": {
96
+ DEFAULT: "var(--secondary)",
97
+ foreground: "var(--secondary-foreground)",
98
+ accent: "var(--secondary-accent)"
99
+ },
100
+ "muted": {
101
+ DEFAULT: "var(--muted)",
102
+ foreground: "var(--muted-foreground)"
103
+ },
104
+ "accent": {
105
+ DEFAULT: "var(--accent)",
106
+ foreground: "var(--accent-foreground)"
107
+ },
108
+ "info": {
109
+ DEFAULT: "var(--info)",
110
+ foreground: "var(--info-foreground)"
111
+ },
112
+ "success": {
113
+ DEFAULT: "var(--success)",
114
+ foreground: "var(--success-foreground)"
115
+ },
116
+ "warning": {
117
+ DEFAULT: "var(--warning)",
118
+ foreground: "var(--warning-foreground)"
119
+ },
120
+ "error": {
121
+ DEFAULT: "var(--error)",
122
+ foreground: "var(--error-foreground)"
123
+ },
124
+ "commentary": {
125
+ DEFAULT: "var(--commentary)",
126
+ foreground: "var(--commentary-foreground)"
127
+ },
128
+ "ideation": {
129
+ DEFAULT: "var(--ideation)",
130
+ foreground: "var(--ideation-foreground)"
131
+ },
132
+ "source": {
133
+ DEFAULT: "var(--source)",
134
+ foreground: "var(--source-foreground)"
135
+ },
136
+ "border": "var(--border)",
137
+ "input": "var(--input)",
138
+ "outline": "var(--outline)",
139
+ "ring": "var(--ring)",
140
+ "destructive": {
141
+ DEFAULT: "var(--destructive)",
142
+ subtle: "var(--color-destructive-subtle)"
143
+ },
144
+ "sidebar": {
145
+ DEFAULT: "var(--sidebar)",
146
+ foreground: "var(--sidebar-foreground)",
147
+ primary: {
148
+ DEFAULT: "var(--sidebar-primary)",
149
+ foreground: "var(--sidebar-primary-foreground)"
150
+ },
151
+ accent: {
152
+ DEFAULT: "var(--sidebar-accent)",
153
+ foreground: "var(--sidebar-accent-foreground)"
154
+ },
155
+ border: "var(--sidebar-border)",
156
+ ring: "var(--sidebar-ring)"
157
+ },
158
+ "chart": {
159
+ "1": "var(--chart-1)",
160
+ "2": "var(--chart-2)",
161
+ "3": "var(--chart-3)",
162
+ "4": "var(--chart-4)",
163
+ "5": "var(--chart-5)"
164
+ },
165
+ "hover": "var(--color-hover)",
166
+ "surface": "var(--color-surface)",
167
+ "muted-strong": "var(--color-muted-strong)",
168
+ "foreground-secondary": "var(--color-foreground-secondary)",
169
+ "foreground-tertiary": "var(--color-foreground-tertiary)",
170
+ "placeholder": "var(--color-placeholder)",
171
+ "input-border": "var(--color-input-border)",
172
+ "accent-subtle": "var(--color-accent-subtle)"
173
+ },
174
+ radius: {
175
+ "xs": "calc(var(--radius) - 0.375rem)",
176
+ "sm": "calc(var(--radius) - 0.25rem)",
177
+ "md": "calc(var(--radius) - 0.125rem)",
178
+ "lg": "var(--radius)",
179
+ "xl": "calc(var(--radius) + 0.25rem)",
180
+ "2xl": "calc(var(--radius) + 0.5rem)",
181
+ "3xl": "calc(var(--radius) + 1rem)"
182
+ },
183
+ animation: {
184
+ keyframes: {
185
+ "accordion-down":
186
+ "{ from { height: 0; } to { height: var(--starwind-accordion-content-height); } }",
187
+ "accordion-up":
188
+ "{ from { height: var(--starwind-accordion-content-height); } to { height: 0; } }",
189
+ "marquee": "{ from { transform: translateX(0); } to { transform: translateX(-100%); } }"
190
+ },
191
+ durations: {
192
+ "accordion-down": "0.2s",
193
+ "accordion-up": "0.2s",
194
+ "marquee": "30s"
195
+ },
196
+ timingFns: {
197
+ "accordion-down": "ease-out",
198
+ "accordion-up": "ease-out",
199
+ "marquee": "linear"
200
+ },
201
+ counts: { marquee: "infinite" }
202
+ }
203
+ },
204
+
205
+ preflights: [
206
+ {
207
+ getCSS: () => `
208
+ :root {
209
+ --background: #ffffff;
210
+ --foreground: #030712;
211
+ --card: #ffffff;
212
+ --card-foreground: #030712;
213
+ --popover: #ffffff;
214
+ --popover-foreground: #030712;
215
+ --primary: #f97316;
216
+ --primary-foreground: #f9fafb;
217
+ --primary-accent: #ea580c;
218
+ --secondary: #8b5cf6;
219
+ --secondary-foreground: #f9fafb;
220
+ --secondary-accent: #7c3aed;
221
+ --muted: #f3f4f6;
222
+ --muted-foreground: #4b5563;
223
+ --accent: #f3f4f6;
224
+ --accent-foreground: #111827;
225
+ --info: #3b82f6;
226
+ --info-foreground: #ffffff;
227
+ --success: #22c55e;
228
+ --success-foreground: #ffffff;
229
+ --warning: #f59e0b;
230
+ --warning-foreground: #000000;
231
+ --error: #ef4444;
232
+ --error-foreground: #f9fafb;
233
+ --commentary: #ec4899;
234
+ --commentary-foreground: #f9fafb;
235
+ --ideation: #8b5cf6;
236
+ --ideation-foreground: #f9fafb;
237
+ --source: #38bdf8;
238
+ --source-foreground: #0f172a;
239
+ --border: #e5e7eb;
240
+ --input: #e5e7eb;
241
+ --outline: #9ca3af;
242
+ --ring: #9ca3af;
243
+ --radius: 0.625rem;
244
+ --sidebar: #f9fafb;
245
+ --sidebar-foreground: #030712;
246
+ --sidebar-primary: #1d4ed8;
247
+ --sidebar-primary-foreground: #f9fafb;
248
+ --sidebar-accent: #f3f4f6;
249
+ --sidebar-accent-foreground: #111827;
250
+ --sidebar-border: #e5e7eb;
251
+ --sidebar-ring: #9ca3af;
252
+ --chart-1: #3b82f6;
253
+ --chart-2: #6366f1;
254
+ --chart-3: #8b5cf6;
255
+ --chart-4: #a855f7;
256
+ --chart-5: #ec4899;
257
+ --destructive: #ef4444;
258
+ --color-surface: #ffffff;
259
+ --color-muted-strong: #e5e7eb;
260
+ --color-foreground-secondary: #4b5563;
261
+ --color-foreground-tertiary: #6b7280;
262
+ --color-placeholder: #9ca3af;
263
+ --color-input-border: #d1d5db;
264
+ --color-hover: #f3f4f6;
265
+ --color-destructive-subtle: #fef2f2;
266
+ --color-accent-subtle: #eff6ff;
267
+ --font-sans: "Noto Sans", sans-serif;
268
+ --font-serif: "Noto Serif", serif;
269
+ --font-mono: "Noto Sans Mono", monospace;
270
+ }
271
+
272
+ .dark {
273
+ --background: #030712;
274
+ --foreground: #f9fafb;
275
+ --card: #111827;
276
+ --card-foreground: #f9fafb;
277
+ --popover: #1f2937;
278
+ --popover-foreground: #f9fafb;
279
+ --primary: #f97316;
280
+ --primary-foreground: #f9fafb;
281
+ --primary-accent: #fb923c;
282
+ --secondary: #8b5cf6;
283
+ --secondary-foreground: #f9fafb;
284
+ --secondary-accent: #a78bfa;
285
+ --muted: #1f2937;
286
+ --muted-foreground: #9ca3af;
287
+ --accent: #374151;
288
+ --accent-foreground: #f3f4f6;
289
+ --info: #3b82f6;
290
+ --info-foreground: #ffffff;
291
+ --success: #22c55e;
292
+ --success-foreground: #ffffff;
293
+ --warning: #f59e0b;
294
+ --warning-foreground: #000000;
295
+ --error: #ef4444;
296
+ --error-foreground: #f9fafb;
297
+ --commentary: #f472b6;
298
+ --commentary-foreground: #0f172a;
299
+ --ideation: #a78bfa;
300
+ --ideation-foreground: #0f172a;
301
+ --source: #7dd3fc;
302
+ --source-foreground: #0f172a;
303
+ --border: rgba(249, 250, 251, 0.1);
304
+ --input: rgba(249, 250, 251, 0.15);
305
+ --outline: #6b7280;
306
+ --ring: #6b7280;
307
+ --sidebar: #111827;
308
+ --sidebar-foreground: #f9fafb;
309
+ --sidebar-primary: #1d4ed8;
310
+ --sidebar-primary-foreground: #f9fafb;
311
+ --sidebar-accent: #1f2937;
312
+ --sidebar-accent-foreground: #f3f4f6;
313
+ --sidebar-border: #1f2937;
314
+ --sidebar-ring: #6b7280;
315
+ --chart-1: #60a5fa;
316
+ --chart-2: #818cf8;
317
+ --chart-3: #a78bfa;
318
+ --chart-4: #c084fc;
319
+ --chart-5: #f472b6;
320
+ --destructive: #f87171;
321
+ --color-surface: #1f2937;
322
+ --color-muted-strong: #374151;
323
+ --color-foreground-secondary: #d1d5db;
324
+ --color-foreground-tertiary: #9ca3af;
325
+ --color-placeholder: #6b7280;
326
+ --color-input-border: #4b5563;
327
+ --color-hover: #374151;
328
+ --color-destructive-subtle: #451a1a;
329
+ --color-accent-subtle: #1e293b;
330
+ }
331
+
332
+ * {
333
+ border-color: var(--border);
334
+ outline-color: rgba(156, 163, 175, 0.5);
335
+ }
336
+
337
+ body {
338
+ background-color: var(--background);
339
+ color: var(--foreground);
340
+ font-family: var(--font-sans);
341
+ }
342
+
343
+ button {
344
+ cursor: pointer;
345
+ }
346
+
347
+ ::selection {
348
+ background-color: var(--primary);
349
+ color: var(--primary-foreground);
350
+ }
351
+
352
+ @view-transition {
353
+ navigation: auto;
354
+ }
355
+ `
356
+ }
357
+ ],
358
+
359
+ async configResolved(config) {
360
+ if (process.env.NODE_ENV === "development" && !process.env.UNO_CONFIG_LOGGED) {
361
+ process.env.UNO_CONFIG_LOGGED = "true"
362
+
363
+ console.log(
364
+ `[UnoCSS] Config resolved. Presets: ${config.presets.map((p) => p.name).join(", ")}`
365
+ )
366
+ console.log(`[UnoCSS] Total rules: ${config.rules.length}`)
367
+ console.log(`[UnoCSS] Total shortcuts: ${Object.keys(config.shortcuts).length}`)
368
+
369
+ const ruleNames = config.rules.map((r) => (Array.isArray(r) ? r[0].toString() : "dynamic"))
370
+ const duplicates = ruleNames.filter((item, index) => ruleNames.indexOf(item) !== index)
371
+ const filteredDuplicates = duplicates.filter((d) => d !== "/^(.+?)-(\\$.+)$/")
372
+
373
+ if (filteredDuplicates.length > 0) {
374
+ console.warn(`[UnoCSS] Potential Rule Collisions: ${filteredDuplicates.join(", ")}`)
375
+ }
376
+ }
377
+ }
378
+ }
379
+ })
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Theme configuration for the Button component. Defines the slots, base styles, and an extensive
3
+ * set of variants including color logic.
4
+ */
1
5
  export const buttonTheme = {
2
6
  slots: ["root"],
3
7
  base: {
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Theme configuration for the Header component. Defines the slots, base styles, and variants for
3
+ * layout management.
4
+ */
1
5
  export const headerTheme = {
2
6
  slots: ["root", "container", "left", "center", "right"],
3
7
  base: {