@veltra/styles 1.13.3 → 1.14.0
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/dist/theme/component-css-vars.d.ts +11 -2
- package/dist/theme/component-css-vars.js +58 -11
- package/dist/theme/component-css-vars.js.map +1 -1
- package/dist/theme/index.d.ts +2 -2
- package/dist/theme/index.js +2 -2
- package/dist/theme/presets/ancient.js +1 -1
- package/dist/theme/presets/ancient.js.map +1 -1
- package/dist/theme/presets/ocean.js +1 -1
- package/dist/theme/presets/ocean.js.map +1 -1
- package/dist/theme/presets/sakura.js +1 -1
- package/dist/theme/presets/sakura.js.map +1 -1
- package/dist/theme/type.d.ts +9 -3
- package/dist/theme/ui-theme.d.ts +31 -3
- package/dist/theme/ui-theme.js +86 -13
- package/dist/theme/ui-theme.js.map +1 -1
- package/package.json +1 -1
- package/src/theme/__test__/ui-theme.test.ts +100 -1
- package/src/theme/component-css-vars.ts +82 -8
- package/src/theme/presets/ancient.ts +2 -2
- package/src/theme/presets/ocean.ts +2 -2
- package/src/theme/presets/sakura.ts +2 -2
- package/src/theme/type.ts +9 -3
- package/src/theme/ui-theme.ts +101 -13
|
@@ -15,9 +15,18 @@ export declare const componentCssVarsLightDecls: string[];
|
|
|
15
15
|
export declare const componentCssVarsDarkDecls: string[];
|
|
16
16
|
/** 侧栏外观变体:dark 深底浅字 / light 浅底深字 */
|
|
17
17
|
export type NavSidebarVariant = 'dark' | 'light';
|
|
18
|
-
/**
|
|
18
|
+
/** 侧栏实际底色色调:dark 深底 / light 浅底 */
|
|
19
|
+
export type NavSurfaceTone = 'dark' | 'light';
|
|
20
|
+
/**
|
|
21
|
+
* 某主题系列 + 菜单变体下侧栏的实际底色色调。
|
|
22
|
+
* 深色系列主题的两个变体都是深底(light 变体只是比内容区提亮一档)。
|
|
23
|
+
*/
|
|
24
|
+
export declare function navSurfaceTone(series: 'light' | 'dark', variant: NavSidebarVariant): NavSurfaceTone;
|
|
25
|
+
/** 某主题系列 + 侧栏变体下的 nav token(外观 + 表面装饰,键为 `--u-nav-*`) */
|
|
19
26
|
export declare function navSidebarTokens(series: 'light' | 'dark', variant: NavSidebarVariant): Record<string, string>;
|
|
20
|
-
/**
|
|
27
|
+
/** 某主题系列 + 侧栏变体下的 nav 表面装饰 token(键为 `--u-nav-surface-*`) */
|
|
28
|
+
export declare function navSurfaceTokens(series: 'light' | 'dark', variant: NavSidebarVariant): Record<string, string>;
|
|
29
|
+
/** 解析某主题系列 + 侧栏变体下的 nav token 声明列表 */
|
|
21
30
|
export declare function resolveNavSidebarDecls(series: 'light' | 'dark', variant: NavSidebarVariant): string[];
|
|
22
31
|
//#endregion
|
|
23
32
|
//# sourceMappingURL=component-css-vars.d.ts.map
|
|
@@ -181,6 +181,49 @@ function recordToDeclList(record) {
|
|
|
181
181
|
}
|
|
182
182
|
const componentCssVarsLightDecls = recordToDeclList(componentCssVarsLight);
|
|
183
183
|
const componentCssVarsDarkDecls = recordToDeclList(componentCssVarsDark);
|
|
184
|
+
/**
|
|
185
|
+
* 某主题系列 + 菜单变体下侧栏的实际底色色调。
|
|
186
|
+
* 深色系列主题的两个变体都是深底(light 变体只是比内容区提亮一档)。
|
|
187
|
+
*/
|
|
188
|
+
function navSurfaceTone(series, variant) {
|
|
189
|
+
return series === "dark" || variant === "dark" ? "dark" : "light";
|
|
190
|
+
}
|
|
191
|
+
/** 深底侧栏的表面装饰 token */
|
|
192
|
+
const navSurfaceDarkTone = {
|
|
193
|
+
"--u-nav-surface-overlay": `radial-gradient(120% 70% at 0% 0%, ${T("color", "primary", "a", "16")}, transparent 62%), linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(0, 0, 0, 0.3))`,
|
|
194
|
+
"--u-nav-surface-hairline": "rgba(255, 255, 255, 0.07)",
|
|
195
|
+
"--u-nav-surface-chip-bg": "rgba(255, 255, 255, 0.055)",
|
|
196
|
+
"--u-nav-surface-chip-border": "rgba(255, 255, 255, 0.08)",
|
|
197
|
+
"--u-nav-surface-chip-hover-bg": "rgba(255, 255, 255, 0.09)",
|
|
198
|
+
"--u-nav-surface-mark-ring": "rgba(255, 255, 255, 0.14)",
|
|
199
|
+
"--u-nav-surface-active-gradient": `linear-gradient(90deg, ${T("color", "primary", "a", "35")}, ${T("color", "primary", "a", "5")})`,
|
|
200
|
+
"--u-nav-surface-active-ring": T("color", "primary", "a", "16"),
|
|
201
|
+
"--u-nav-surface-accent": T("color", "primary", "light", "5"),
|
|
202
|
+
"--u-nav-surface-scrollbar": "rgba(255, 255, 255, 0.22)",
|
|
203
|
+
"--u-nav-surface-scrollbar-hover": "rgba(255, 255, 255, 0.4)"
|
|
204
|
+
};
|
|
205
|
+
/** 浅底侧栏的表面装饰 token */
|
|
206
|
+
const navSurfaceLightTone = {
|
|
207
|
+
"--u-nav-surface-overlay": `radial-gradient(120% 70% at 0% 0%, ${T("color", "primary", "a", "8")}, transparent 62%), linear-gradient(180deg, rgba(255, 255, 255, 0.45), rgba(0, 0, 0, 0.02))`,
|
|
208
|
+
"--u-nav-surface-hairline": T("border", "color"),
|
|
209
|
+
"--u-nav-surface-chip-bg": "rgba(15, 23, 42, 0.04)",
|
|
210
|
+
"--u-nav-surface-chip-border": T("border", "color"),
|
|
211
|
+
"--u-nav-surface-chip-hover-bg": "rgba(15, 23, 42, 0.07)",
|
|
212
|
+
"--u-nav-surface-mark-ring": "rgba(15, 23, 42, 0.1)",
|
|
213
|
+
"--u-nav-surface-active-gradient": `linear-gradient(90deg, ${T("color", "primary", "a", "16")}, ${T("color", "primary", "a", "4")})`,
|
|
214
|
+
"--u-nav-surface-active-ring": T("color", "primary", "a", "8"),
|
|
215
|
+
"--u-nav-surface-accent": T("color", "primary"),
|
|
216
|
+
"--u-nav-surface-scrollbar": T("text-color", "assist", "a", "40"),
|
|
217
|
+
"--u-nav-surface-scrollbar-hover": T("text-color", "assist", "a", "60")
|
|
218
|
+
};
|
|
219
|
+
/** 给内置外观 token 补上与其实际底色色调匹配的表面装饰 token */
|
|
220
|
+
function withNavSurface(appearance, series, variant) {
|
|
221
|
+
const surface = navSurfaceTone(series, variant) === "dark" ? navSurfaceDarkTone : navSurfaceLightTone;
|
|
222
|
+
return {
|
|
223
|
+
...appearance,
|
|
224
|
+
...surface
|
|
225
|
+
};
|
|
226
|
+
}
|
|
184
227
|
/** 深侧栏 · 浅色主题下:深底(text-color.title)+ 浅前景,与浅色内容区拉开区分度 */
|
|
185
228
|
const navSidebarDarkInLight = {
|
|
186
229
|
"--u-nav-bg-color": T("text-color", "title"),
|
|
@@ -194,14 +237,14 @@ const navSidebarDarkInLight = {
|
|
|
194
237
|
"--u-nav-sub-border-color": "rgba(255, 255, 255, 0.15)",
|
|
195
238
|
"--u-nav-rail-bg": "rgba(0, 0, 0, 0.2)"
|
|
196
239
|
};
|
|
197
|
-
/** 浅侧栏 · 浅色主题下:比内容区 top 低一档的浅底 +
|
|
240
|
+
/** 浅侧栏 · 浅色主题下:比内容区 top 低一档的浅底 + 深前景;选中文字加深,保证 13px 正文的对比度 */
|
|
198
241
|
const navSidebarLightInLight = {
|
|
199
242
|
"--u-nav-bg-color": T("bg-color", "middle"),
|
|
200
243
|
"--u-nav-color": T("text-color", "title"),
|
|
201
244
|
"--u-nav-hover-bg": T("text-color", "title", "a", "8"),
|
|
202
245
|
"--u-nav-hover-color": T("text-color", "title"),
|
|
203
246
|
"--u-nav-active-bg": T("color", "primary", "a", "10"),
|
|
204
|
-
"--u-nav-active-color": T("color", "primary", "dark", "
|
|
247
|
+
"--u-nav-active-color": T("color", "primary", "dark", "3"),
|
|
205
248
|
"--u-nav-strong-color": T("text-color", "title"),
|
|
206
249
|
"--u-nav-second-color": T("text-color", "second"),
|
|
207
250
|
"--u-nav-sub-border-color": T("border", "color", "a", "52"),
|
|
@@ -220,14 +263,14 @@ const navSidebarDarkInDark = {
|
|
|
220
263
|
"--u-nav-sub-border-color": T("border", "color", "a", "52"),
|
|
221
264
|
"--u-nav-rail-bg": T("bg-color", "bottom")
|
|
222
265
|
};
|
|
223
|
-
/** 浅侧栏 ·
|
|
266
|
+
/** 浅侧栏 · 深色主题下:提亮侧栏(与深色内容区反向对比);表面仍是深底,选中文字用白色保证对比度 */
|
|
224
267
|
const navSidebarLightInDark = {
|
|
225
268
|
"--u-nav-bg-color": T("bg-color", "top"),
|
|
226
269
|
"--u-nav-color": T("text-color", "title"),
|
|
227
270
|
"--u-nav-hover-bg": T("text-color", "title", "a", "8"),
|
|
228
271
|
"--u-nav-hover-color": T("text-color", "title"),
|
|
229
272
|
"--u-nav-active-bg": T("color", "primary", "a", "22"),
|
|
230
|
-
"--u-nav-active-color": T("color", "
|
|
273
|
+
"--u-nav-active-color": T("text-color", "white"),
|
|
231
274
|
"--u-nav-strong-color": T("text-color", "title"),
|
|
232
275
|
"--u-nav-second-color": T("text-color", "second"),
|
|
233
276
|
"--u-nav-sub-border-color": T("border", "color", "a", "52"),
|
|
@@ -235,23 +278,27 @@ const navSidebarLightInDark = {
|
|
|
235
278
|
};
|
|
236
279
|
const navSidebarCssVars = {
|
|
237
280
|
light: {
|
|
238
|
-
dark: navSidebarDarkInLight,
|
|
239
|
-
light: navSidebarLightInLight
|
|
281
|
+
dark: withNavSurface(navSidebarDarkInLight, "light", "dark"),
|
|
282
|
+
light: withNavSurface(navSidebarLightInLight, "light", "light")
|
|
240
283
|
},
|
|
241
284
|
dark: {
|
|
242
|
-
dark: navSidebarDarkInDark,
|
|
243
|
-
light: navSidebarLightInDark
|
|
285
|
+
dark: withNavSurface(navSidebarDarkInDark, "dark", "dark"),
|
|
286
|
+
light: withNavSurface(navSidebarLightInDark, "dark", "light")
|
|
244
287
|
}
|
|
245
288
|
};
|
|
246
|
-
/** 某主题系列 + 侧栏变体下的 nav
|
|
289
|
+
/** 某主题系列 + 侧栏变体下的 nav token(外观 + 表面装饰,键为 `--u-nav-*`) */
|
|
247
290
|
function navSidebarTokens(series, variant) {
|
|
248
291
|
return { ...navSidebarCssVars[series][variant] };
|
|
249
292
|
}
|
|
250
|
-
/**
|
|
293
|
+
/** 某主题系列 + 侧栏变体下的 nav 表面装饰 token(键为 `--u-nav-surface-*`) */
|
|
294
|
+
function navSurfaceTokens(series, variant) {
|
|
295
|
+
return { ...navSurfaceTone(series, variant) === "dark" ? navSurfaceDarkTone : navSurfaceLightTone };
|
|
296
|
+
}
|
|
297
|
+
/** 解析某主题系列 + 侧栏变体下的 nav token 声明列表 */
|
|
251
298
|
function resolveNavSidebarDecls(series, variant) {
|
|
252
299
|
return recordToDeclList(navSidebarCssVars[series][variant]);
|
|
253
300
|
}
|
|
254
301
|
//#endregion
|
|
255
|
-
export { componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, navSidebarTokens, resolveNavSidebarDecls, themeTokenVar };
|
|
302
|
+
export { componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, navSidebarTokens, navSurfaceTokens, navSurfaceTone, resolveNavSidebarDecls, themeTokenVar };
|
|
256
303
|
|
|
257
304
|
//# sourceMappingURL=component-css-vars.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-css-vars.js","names":[],"sources":["../../src/theme/component-css-vars.ts"],"sourcesContent":["/**\n * 桌面组件级 `--u-*` token,随 `UITheme.render()` 按主题系列(light/dark)注入 `html`。\n * 修改此处即可在 TS 侧统一调整组件外观,无需在各组件 `style.scss` 重复声明。\n * nav 系列:外观(底色/前景)不在此列表,由 `navSidebarCssVars` 按主题 `nav.variant`\n * (dark 深底浅字 / light 浅底深字,默认 dark)与 `nav` 覆盖项注入,见 `ui-theme.ts`。\n */\n\n/** 与 SCSS `fn.use-var($basename, $nodes...)` 输出一致 */\nexport function themeTokenVar(basename: string, ...nodes: Array<string | number>): string {\n const suffix = nodes.length ? `-${nodes.map(String).join('-')}` : ''\n return `var(--u-${basename}${suffix})`\n}\n\nconst T = themeTokenVar\n\n/** 亮色(及与暗色相同的尺寸类)下组件 token */\nexport const componentCssVarsLight: Record<string, string> = {\n '--u-focus-ring': `0 0 0 3px ${T('color', 'primary', 'a', '28')}`,\n '--u-focus-ring-danger': `0 0 0 3px ${T('color', 'danger', 'a', '28')}`,\n '--u-table-border-color': T('border', 'color'),\n '--u-table-header-bg': T('bg-color', 'hover'),\n '--u-table-header-color': T('text-color', 'title'),\n '--u-table-stripe-bg': T('bg-color', 'middle'),\n '--u-table-stripe-color': 'inherit',\n '--u-table-hover-bg': T('bg-color', 'hover'),\n '--u-table-hover-color': 'inherit',\n '--u-table-current-bg': T('bg-color', 'hover'),\n '--u-table-current-color': 'inherit',\n '--u-table-checked-bg': T('color', 'primary', 'light-9'),\n '--u-table-checked-color': 'inherit',\n // ─── Nav 系列(nav / dual-nav / group-nav)尺寸与资源类;外观见文件底部 navSidebarCssVars ───\n '--u-nav-height-small': '32px',\n '--u-nav-height-default': '36px',\n '--u-nav-height-large': '40px',\n '--u-nav-bg-image': 'none',\n '--u-nav-rail-width': '56px',\n '--u-nav-rail-labeled-width': '72px',\n '--u-tag-small': '20px',\n '--u-tag-default': '24px',\n '--u-tag-large': '28px',\n '--u-switch-height-small': '18px',\n '--u-switch-height-default': '20px',\n '--u-switch-height-large': '24px',\n '--u-breadcrumb-small': '20px',\n '--u-breadcrumb-default': '22px',\n '--u-breadcrumb-large': '24px',\n '--u-drawer-size': '320px',\n\n // ─── Button (default & plain states) ───\n '--u-button-default-bg': T('bg-color', 'top'),\n '--u-button-default-border': T('border', 'color'),\n '--u-button-default-color': T('text-color', 'main'),\n '--u-button-default-hover-bg': T('bg-color', 'hover'),\n '--u-button-default-hover-border': T('border', 'color'),\n '--u-button-primary-plain-bg': T('color', 'primary', 'light', '9'),\n '--u-button-primary-plain-shadow': T('color', 'primary', 'light', '5'),\n '--u-button-success-plain-bg': T('color', 'success', 'light', '9'),\n '--u-button-success-plain-shadow': T('color', 'success', 'light', '5'),\n '--u-button-warning-plain-bg': T('color', 'warning', 'light', '9'),\n '--u-button-warning-plain-shadow': T('color', 'warning', 'light', '5'),\n '--u-button-danger-plain-bg': T('color', 'danger', 'light', '9'),\n '--u-button-danger-plain-shadow': T('color', 'danger', 'light', '5'),\n '--u-button-info-plain-bg': T('color', 'info', 'light', '9'),\n '--u-button-info-plain-shadow': T('color', 'info', 'light', '5'),\n\n // ─── Tree selection ───\n '--u-tree-node-selected-bg': T('color', 'primary', 'light', '9'),\n '--u-tree-node-selected-color': T('color', 'primary'),\n\n // ─── Cascade option active ───\n '--u-cascade-node-active-bg': T('color', 'primary', 'light', '9'),\n '--u-cascade-node-active-color': T('color', 'primary'),\n\n // ─── Select option ───\n '--u-select-option-hover-bg': T('bg-color', 'hover'),\n '--u-select-option-hover-color': T('text-color', 'title'),\n '--u-select-option-selected-bg': T('color', 'primary', 'light', '9'),\n '--u-select-option-selected-color': T('color', 'primary'),\n\n // ─── Auto Complete option ───\n '--u-auto-complete-option-hover-bg': T('bg-color', 'hover'),\n '--u-auto-complete-option-hover-color': T('text-color', 'title'),\n '--u-auto-complete-option-selected-bg': T('color', 'primary', 'light', '9'),\n '--u-auto-complete-option-selected-color': T('color', 'primary'),\n\n // ─── Contextmenu item ───\n '--u-contextmenu-item-hover-bg': T('bg-color', 'hover'),\n '--u-contextmenu-item-hover-color': T('text-color', 'title'),\n '--u-contextmenu-item-height-small': '24px',\n '--u-contextmenu-item-height-default': '28px',\n '--u-contextmenu-item-height-large': '32px',\n\n // ─── Expression Editor Chip ───\n '--u-expression-editor-chip-bg': T('color', 'primary', 'light', '9'),\n '--u-expression-editor-chip-color': T('color', 'primary'),\n\n // ─── Paginator active buttons ───\n '--u-paginator-btn-hover-bg': T('color', 'primary', 'light', '9'),\n '--u-paginator-btn-hover-color': T('text-color', 'title'),\n '--u-paginator-btn-active-bg': T('color', 'primary', 'light', '9'),\n '--u-paginator-btn-active-color': T('color', 'primary'),\n\n // ─── Tabs List background ───\n '--u-tabs-bar-bg': T('bg-color', 'hover'),\n '--u-tabs-active-bg': T('bg-color', 'top'),\n\n // ─── Tag Component Colors ───\n '--u-tag-primary-bg': T('color', 'primary', 'light', '9'),\n '--u-tag-primary-color': T('color', 'primary'),\n '--u-tag-primary-border': T('color', 'primary'),\n '--u-tag-success-bg': T('color', 'success', 'light', '9'),\n '--u-tag-success-color': T('color', 'success'),\n '--u-tag-success-border': T('color', 'success'),\n '--u-tag-warning-bg': T('color', 'warning', 'light', '9'),\n '--u-tag-warning-color': T('color', 'warning'),\n '--u-tag-warning-border': T('color', 'warning'),\n '--u-tag-danger-bg': T('color', 'danger', 'light', '9'),\n '--u-tag-danger-color': T('color', 'danger'),\n '--u-tag-danger-border': T('color', 'danger'),\n '--u-tag-info-bg': T('color', 'info', 'light', '9'),\n '--u-tag-info-color': T('color', 'info'),\n '--u-tag-info-border': T('color', 'info'),\n\n // ─── File Picker Colors ───\n '--u-file-picker-hover-bg': T('color', 'primary', 'light', '9'),\n '--u-card-header-bg': 'rgba(0, 0, 0, 0.015)',\n '--u-card-action-bg': 'rgba(0, 0, 0, 0.015)',\n '--u-card-padding-small': '8px',\n '--u-card-padding-default': '12px',\n '--u-card-padding-large': '16px',\n '--u-card-radius': T('radius', 'large')\n}\n\n/** 暗色下组件 token(含与亮色相同的尺寸项,保证暗色 html 块自洽) */\nexport const componentCssVarsDark: Record<string, string> = {\n ...componentCssVarsLight,\n '--u-focus-ring': `0 0 0 3px ${T('color', 'primary', 'a', '35')}`,\n '--u-focus-ring-danger': `0 0 0 3px ${T('color', 'danger', 'a', '35')}`,\n '--u-table-border-color': T('border', 'color'),\n '--u-table-header-bg': T('bg-color', 'hover'),\n '--u-table-header-color': T('text-color', 'main'),\n '--u-table-stripe-bg': T('bg-color', 'middle'),\n '--u-table-stripe-color': T('text-color', 'main'),\n '--u-table-hover-bg': T('text-color', 'title', 'a', '5'),\n '--u-table-hover-color': T('text-color', 'title'),\n '--u-table-current-bg': T('bg-color', 'hover'),\n '--u-table-current-color': 'inherit',\n '--u-table-checked-bg': T('color', 'primary', 'dark', '1'),\n '--u-table-checked-color': 'inherit',\n '--u-radio-border': '#595959',\n '--u-checkbox-border': '#595959',\n\n // ─── Button (plain & text colors in dark mode) ───\n '--u-button-primary-plain-bg': T('color', 'primary', 'dark', '9'),\n '--u-button-primary-plain-shadow': T('color', 'primary', 'dark', '7'),\n '--u-button-success-plain-bg': T('color', 'success', 'dark', '9'),\n '--u-button-success-plain-shadow': T('color', 'success', 'dark', '7'),\n '--u-button-warning-plain-bg': T('color', 'warning', 'dark', '9'),\n '--u-button-warning-plain-shadow': T('color', 'warning', 'dark', '7'),\n '--u-button-danger-plain-bg': T('color', 'danger', 'dark', '9'),\n '--u-button-danger-plain-shadow': T('color', 'danger', 'dark', '7'),\n '--u-button-info-plain-bg': T('color', 'info', 'dark', '9'),\n '--u-button-info-plain-shadow': T('color', 'info', 'dark', '7'),\n\n // ─── Tree selection ───\n '--u-tree-node-selected-bg': T('color', 'primary', 'dark', '9'),\n '--u-tree-node-selected-color': T('color', 'primary'),\n\n // ─── Cascade option active ───\n '--u-cascade-node-active-bg': T('color', 'primary', 'dark', '9'),\n '--u-cascade-node-active-color': T('color', 'primary'),\n\n // ─── Select option ───\n '--u-select-option-hover-bg': T('bg-color', 'hover'),\n '--u-select-option-hover-color': T('text-color', 'title'),\n '--u-select-option-selected-bg': T('color', 'primary', 'dark', '9'),\n '--u-select-option-selected-color': T('color', 'primary'),\n\n // ─── Auto Complete option ───\n '--u-auto-complete-option-hover-bg': T('bg-color', 'hover'),\n '--u-auto-complete-option-hover-color': T('text-color', 'title'),\n '--u-auto-complete-option-selected-bg': T('color', 'primary', 'dark', '9'),\n '--u-auto-complete-option-selected-color': T('color', 'primary'),\n\n // ─── Contextmenu item ───\n '--u-contextmenu-item-hover-bg': T('bg-color', 'hover'),\n '--u-contextmenu-item-hover-color': T('text-color', 'title'),\n '--u-contextmenu-item-height-small': '24px',\n '--u-contextmenu-item-height-default': '28px',\n '--u-contextmenu-item-height-large': '32px',\n\n // ─── Expression Editor Chip ───\n '--u-expression-editor-chip-bg': T('color', 'primary', 'dark', '9'),\n '--u-expression-editor-chip-color': T('color', 'primary'),\n\n // ─── Paginator active buttons ───\n '--u-paginator-btn-hover-bg': T('color', 'primary', 'dark', '9'),\n '--u-paginator-btn-hover-color': T('color', 'primary'),\n '--u-paginator-btn-active-bg': T('color', 'primary', 'dark', '9'),\n '--u-paginator-btn-active-color': T('color', 'primary'),\n\n // ─── Tabs List background (improved dark contrast) ───\n '--u-tabs-bar-bg': T('bg-color', 'bottom'),\n '--u-tabs-active-bg': T('bg-color', 'top'),\n\n // ─── Tag Component Colors ───\n '--u-tag-primary-bg': T('color', 'primary', 'dark', '9'),\n '--u-tag-primary-color': T('color', 'primary'),\n '--u-tag-primary-border': T('color', 'primary'),\n '--u-tag-success-bg': T('color', 'success', 'dark', '9'),\n '--u-tag-success-color': T('color', 'success'),\n '--u-tag-success-border': T('color', 'success'),\n '--u-tag-warning-bg': T('color', 'warning', 'dark', '9'),\n '--u-tag-warning-color': T('color', 'warning'),\n '--u-tag-warning-border': T('color', 'warning'),\n '--u-tag-danger-bg': T('color', 'danger', 'dark', '9'),\n '--u-tag-danger-color': T('color', 'danger'),\n '--u-tag-danger-border': T('color', 'danger'),\n '--u-tag-info-bg': T('color', 'info', 'dark', '9'),\n '--u-tag-info-color': T('color', 'info'),\n '--u-tag-info-border': T('color', 'info'),\n\n // ─── File Picker Colors ───\n '--u-file-picker-hover-bg': T('color', 'primary', 'dark', '9'),\n '--u-card-header-bg': 'rgba(255, 255, 255, 0.015)',\n '--u-card-action-bg': 'rgba(255, 255, 255, 0.015)'\n}\n\nfunction recordToDeclList(record: Record<string, string>): string[] {\n return Object.entries(record).map(([k, v]) => `${k}: ${v}`)\n}\n\nexport const componentCssVarsLightDecls: string[] = recordToDeclList(componentCssVarsLight)\n\nexport const componentCssVarsDarkDecls: string[] = recordToDeclList(componentCssVarsDark)\n\n// ─── Nav 侧栏外观:深/浅变体 × 明/暗主题系列 ───\n// 由 UITheme 按主题 `nav.variant`(默认 dark)选择注入,主题 `nav` 的其余键可逐项覆盖。\n\n/** 侧栏外观变体:dark 深底浅字 / light 浅底深字 */\nexport type NavSidebarVariant = 'dark' | 'light'\n\n/** 深侧栏 · 浅色主题下:深底(text-color.title)+ 浅前景,与浅色内容区拉开区分度 */\nconst navSidebarDarkInLight: Record<string, string> = {\n '--u-nav-bg-color': T('text-color', 'title'),\n '--u-nav-color': 'rgba(255, 255, 255, 0.72)',\n '--u-nav-hover-bg': 'rgba(255, 255, 255, 0.08)',\n '--u-nav-hover-color': T('text-color', 'white'),\n '--u-nav-active-bg': T('color', 'primary', 'a', '22'),\n '--u-nav-active-color': T('text-color', 'white'),\n '--u-nav-strong-color': T('text-color', 'white'),\n '--u-nav-second-color': 'rgba(255, 255, 255, 0.45)',\n '--u-nav-sub-border-color': 'rgba(255, 255, 255, 0.15)',\n '--u-nav-rail-bg': 'rgba(0, 0, 0, 0.2)'\n}\n\n/** 浅侧栏 · 浅色主题下:比内容区 top 低一档的浅底 + 深前景 */\nconst navSidebarLightInLight: Record<string, string> = {\n '--u-nav-bg-color': T('bg-color', 'middle'),\n '--u-nav-color': T('text-color', 'title'),\n '--u-nav-hover-bg': T('text-color', 'title', 'a', '8'),\n '--u-nav-hover-color': T('text-color', 'title'),\n '--u-nav-active-bg': T('color', 'primary', 'a', '10'),\n '--u-nav-active-color': T('color', 'primary', 'dark', '1'),\n '--u-nav-strong-color': T('text-color', 'title'),\n '--u-nav-second-color': T('text-color', 'second'),\n '--u-nav-sub-border-color': T('border', 'color', 'a', '52'),\n '--u-nav-rail-bg': T('bg-color', 'bottom')\n}\n\n/** 深侧栏 · 深色主题下:比内容区 top 深一档 */\nconst navSidebarDarkInDark: Record<string, string> = {\n '--u-nav-bg-color': T('bg-color', 'middle'),\n '--u-nav-color': T('text-color', 'main'),\n '--u-nav-hover-bg': T('text-color', 'title', 'a', '8'),\n '--u-nav-hover-color': T('text-color', 'title'),\n '--u-nav-active-bg': T('color', 'primary', 'a', '16'),\n '--u-nav-active-color': T('text-color', 'white'),\n '--u-nav-strong-color': T('text-color', 'title'),\n '--u-nav-second-color': T('text-color', 'second'),\n '--u-nav-sub-border-color': T('border', 'color', 'a', '52'),\n '--u-nav-rail-bg': T('bg-color', 'bottom')\n}\n\n/** 浅侧栏 · 深色主题下:提亮侧栏(与深色内容区反向对比) */\nconst navSidebarLightInDark: Record<string, string> = {\n '--u-nav-bg-color': T('bg-color', 'top'),\n '--u-nav-color': T('text-color', 'title'),\n '--u-nav-hover-bg': T('text-color', 'title', 'a', '8'),\n '--u-nav-hover-color': T('text-color', 'title'),\n '--u-nav-active-bg': T('color', 'primary', 'a', '22'),\n '--u-nav-active-color': T('color', 'primary'),\n '--u-nav-strong-color': T('text-color', 'title'),\n '--u-nav-second-color': T('text-color', 'second'),\n '--u-nav-sub-border-color': T('border', 'color', 'a', '52'),\n '--u-nav-rail-bg': T('bg-color', 'middle')\n}\n\nconst navSidebarCssVars: Record<\n 'light' | 'dark',\n Record<NavSidebarVariant, Record<string, string>>\n> = {\n light: { dark: navSidebarDarkInLight, light: navSidebarLightInLight },\n dark: { dark: navSidebarDarkInDark, light: navSidebarLightInDark }\n}\n\n/** 某主题系列 + 侧栏变体下的 nav 外观 token(键为 `--u-nav-*`) */\nexport function navSidebarTokens(\n series: 'light' | 'dark',\n variant: NavSidebarVariant\n): Record<string, string> {\n return { ...navSidebarCssVars[series][variant] }\n}\n\n/** 解析某主题系列 + 侧栏变体下的 nav 外观 token 声明列表 */\nexport function resolveNavSidebarDecls(\n series: 'light' | 'dark',\n variant: NavSidebarVariant\n): string[] {\n return recordToDeclList(navSidebarCssVars[series][variant])\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"component-css-vars.js","names":[],"sources":["../../src/theme/component-css-vars.ts"],"sourcesContent":["/**\n * 桌面组件级 `--u-*` token,随 `UITheme.render()` 按主题系列(light/dark)注入 `html`。\n * 修改此处即可在 TS 侧统一调整组件外观,无需在各组件 `style.scss` 重复声明。\n * nav 系列:外观(底色/前景)不在此列表,由 `navSidebarCssVars` 按主题 `nav.variant`\n * (dark 深底浅字 / light 浅底深字,默认 dark)与 `nav` 覆盖项注入,见 `ui-theme.ts`。\n */\n\n/** 与 SCSS `fn.use-var($basename, $nodes...)` 输出一致 */\nexport function themeTokenVar(basename: string, ...nodes: Array<string | number>): string {\n const suffix = nodes.length ? `-${nodes.map(String).join('-')}` : ''\n return `var(--u-${basename}${suffix})`\n}\n\nconst T = themeTokenVar\n\n/** 亮色(及与暗色相同的尺寸类)下组件 token */\nexport const componentCssVarsLight: Record<string, string> = {\n '--u-focus-ring': `0 0 0 3px ${T('color', 'primary', 'a', '28')}`,\n '--u-focus-ring-danger': `0 0 0 3px ${T('color', 'danger', 'a', '28')}`,\n '--u-table-border-color': T('border', 'color'),\n '--u-table-header-bg': T('bg-color', 'hover'),\n '--u-table-header-color': T('text-color', 'title'),\n '--u-table-stripe-bg': T('bg-color', 'middle'),\n '--u-table-stripe-color': 'inherit',\n '--u-table-hover-bg': T('bg-color', 'hover'),\n '--u-table-hover-color': 'inherit',\n '--u-table-current-bg': T('bg-color', 'hover'),\n '--u-table-current-color': 'inherit',\n '--u-table-checked-bg': T('color', 'primary', 'light-9'),\n '--u-table-checked-color': 'inherit',\n // ─── Nav 系列(nav / dual-nav / group-nav)尺寸与资源类;外观见文件底部 navSidebarCssVars ───\n '--u-nav-height-small': '32px',\n '--u-nav-height-default': '36px',\n '--u-nav-height-large': '40px',\n '--u-nav-bg-image': 'none',\n '--u-nav-rail-width': '56px',\n '--u-nav-rail-labeled-width': '72px',\n '--u-tag-small': '20px',\n '--u-tag-default': '24px',\n '--u-tag-large': '28px',\n '--u-switch-height-small': '18px',\n '--u-switch-height-default': '20px',\n '--u-switch-height-large': '24px',\n '--u-breadcrumb-small': '20px',\n '--u-breadcrumb-default': '22px',\n '--u-breadcrumb-large': '24px',\n '--u-drawer-size': '320px',\n\n // ─── Button (default & plain states) ───\n '--u-button-default-bg': T('bg-color', 'top'),\n '--u-button-default-border': T('border', 'color'),\n '--u-button-default-color': T('text-color', 'main'),\n '--u-button-default-hover-bg': T('bg-color', 'hover'),\n '--u-button-default-hover-border': T('border', 'color'),\n '--u-button-primary-plain-bg': T('color', 'primary', 'light', '9'),\n '--u-button-primary-plain-shadow': T('color', 'primary', 'light', '5'),\n '--u-button-success-plain-bg': T('color', 'success', 'light', '9'),\n '--u-button-success-plain-shadow': T('color', 'success', 'light', '5'),\n '--u-button-warning-plain-bg': T('color', 'warning', 'light', '9'),\n '--u-button-warning-plain-shadow': T('color', 'warning', 'light', '5'),\n '--u-button-danger-plain-bg': T('color', 'danger', 'light', '9'),\n '--u-button-danger-plain-shadow': T('color', 'danger', 'light', '5'),\n '--u-button-info-plain-bg': T('color', 'info', 'light', '9'),\n '--u-button-info-plain-shadow': T('color', 'info', 'light', '5'),\n\n // ─── Tree selection ───\n '--u-tree-node-selected-bg': T('color', 'primary', 'light', '9'),\n '--u-tree-node-selected-color': T('color', 'primary'),\n\n // ─── Cascade option active ───\n '--u-cascade-node-active-bg': T('color', 'primary', 'light', '9'),\n '--u-cascade-node-active-color': T('color', 'primary'),\n\n // ─── Select option ───\n '--u-select-option-hover-bg': T('bg-color', 'hover'),\n '--u-select-option-hover-color': T('text-color', 'title'),\n '--u-select-option-selected-bg': T('color', 'primary', 'light', '9'),\n '--u-select-option-selected-color': T('color', 'primary'),\n\n // ─── Auto Complete option ───\n '--u-auto-complete-option-hover-bg': T('bg-color', 'hover'),\n '--u-auto-complete-option-hover-color': T('text-color', 'title'),\n '--u-auto-complete-option-selected-bg': T('color', 'primary', 'light', '9'),\n '--u-auto-complete-option-selected-color': T('color', 'primary'),\n\n // ─── Contextmenu item ───\n '--u-contextmenu-item-hover-bg': T('bg-color', 'hover'),\n '--u-contextmenu-item-hover-color': T('text-color', 'title'),\n '--u-contextmenu-item-height-small': '24px',\n '--u-contextmenu-item-height-default': '28px',\n '--u-contextmenu-item-height-large': '32px',\n\n // ─── Expression Editor Chip ───\n '--u-expression-editor-chip-bg': T('color', 'primary', 'light', '9'),\n '--u-expression-editor-chip-color': T('color', 'primary'),\n\n // ─── Paginator active buttons ───\n '--u-paginator-btn-hover-bg': T('color', 'primary', 'light', '9'),\n '--u-paginator-btn-hover-color': T('text-color', 'title'),\n '--u-paginator-btn-active-bg': T('color', 'primary', 'light', '9'),\n '--u-paginator-btn-active-color': T('color', 'primary'),\n\n // ─── Tabs List background ───\n '--u-tabs-bar-bg': T('bg-color', 'hover'),\n '--u-tabs-active-bg': T('bg-color', 'top'),\n\n // ─── Tag Component Colors ───\n '--u-tag-primary-bg': T('color', 'primary', 'light', '9'),\n '--u-tag-primary-color': T('color', 'primary'),\n '--u-tag-primary-border': T('color', 'primary'),\n '--u-tag-success-bg': T('color', 'success', 'light', '9'),\n '--u-tag-success-color': T('color', 'success'),\n '--u-tag-success-border': T('color', 'success'),\n '--u-tag-warning-bg': T('color', 'warning', 'light', '9'),\n '--u-tag-warning-color': T('color', 'warning'),\n '--u-tag-warning-border': T('color', 'warning'),\n '--u-tag-danger-bg': T('color', 'danger', 'light', '9'),\n '--u-tag-danger-color': T('color', 'danger'),\n '--u-tag-danger-border': T('color', 'danger'),\n '--u-tag-info-bg': T('color', 'info', 'light', '9'),\n '--u-tag-info-color': T('color', 'info'),\n '--u-tag-info-border': T('color', 'info'),\n\n // ─── File Picker Colors ───\n '--u-file-picker-hover-bg': T('color', 'primary', 'light', '9'),\n '--u-card-header-bg': 'rgba(0, 0, 0, 0.015)',\n '--u-card-action-bg': 'rgba(0, 0, 0, 0.015)',\n '--u-card-padding-small': '8px',\n '--u-card-padding-default': '12px',\n '--u-card-padding-large': '16px',\n '--u-card-radius': T('radius', 'large')\n}\n\n/** 暗色下组件 token(含与亮色相同的尺寸项,保证暗色 html 块自洽) */\nexport const componentCssVarsDark: Record<string, string> = {\n ...componentCssVarsLight,\n '--u-focus-ring': `0 0 0 3px ${T('color', 'primary', 'a', '35')}`,\n '--u-focus-ring-danger': `0 0 0 3px ${T('color', 'danger', 'a', '35')}`,\n '--u-table-border-color': T('border', 'color'),\n '--u-table-header-bg': T('bg-color', 'hover'),\n '--u-table-header-color': T('text-color', 'main'),\n '--u-table-stripe-bg': T('bg-color', 'middle'),\n '--u-table-stripe-color': T('text-color', 'main'),\n '--u-table-hover-bg': T('text-color', 'title', 'a', '5'),\n '--u-table-hover-color': T('text-color', 'title'),\n '--u-table-current-bg': T('bg-color', 'hover'),\n '--u-table-current-color': 'inherit',\n '--u-table-checked-bg': T('color', 'primary', 'dark', '1'),\n '--u-table-checked-color': 'inherit',\n '--u-radio-border': '#595959',\n '--u-checkbox-border': '#595959',\n\n // ─── Button (plain & text colors in dark mode) ───\n '--u-button-primary-plain-bg': T('color', 'primary', 'dark', '9'),\n '--u-button-primary-plain-shadow': T('color', 'primary', 'dark', '7'),\n '--u-button-success-plain-bg': T('color', 'success', 'dark', '9'),\n '--u-button-success-plain-shadow': T('color', 'success', 'dark', '7'),\n '--u-button-warning-plain-bg': T('color', 'warning', 'dark', '9'),\n '--u-button-warning-plain-shadow': T('color', 'warning', 'dark', '7'),\n '--u-button-danger-plain-bg': T('color', 'danger', 'dark', '9'),\n '--u-button-danger-plain-shadow': T('color', 'danger', 'dark', '7'),\n '--u-button-info-plain-bg': T('color', 'info', 'dark', '9'),\n '--u-button-info-plain-shadow': T('color', 'info', 'dark', '7'),\n\n // ─── Tree selection ───\n '--u-tree-node-selected-bg': T('color', 'primary', 'dark', '9'),\n '--u-tree-node-selected-color': T('color', 'primary'),\n\n // ─── Cascade option active ───\n '--u-cascade-node-active-bg': T('color', 'primary', 'dark', '9'),\n '--u-cascade-node-active-color': T('color', 'primary'),\n\n // ─── Select option ───\n '--u-select-option-hover-bg': T('bg-color', 'hover'),\n '--u-select-option-hover-color': T('text-color', 'title'),\n '--u-select-option-selected-bg': T('color', 'primary', 'dark', '9'),\n '--u-select-option-selected-color': T('color', 'primary'),\n\n // ─── Auto Complete option ───\n '--u-auto-complete-option-hover-bg': T('bg-color', 'hover'),\n '--u-auto-complete-option-hover-color': T('text-color', 'title'),\n '--u-auto-complete-option-selected-bg': T('color', 'primary', 'dark', '9'),\n '--u-auto-complete-option-selected-color': T('color', 'primary'),\n\n // ─── Contextmenu item ───\n '--u-contextmenu-item-hover-bg': T('bg-color', 'hover'),\n '--u-contextmenu-item-hover-color': T('text-color', 'title'),\n '--u-contextmenu-item-height-small': '24px',\n '--u-contextmenu-item-height-default': '28px',\n '--u-contextmenu-item-height-large': '32px',\n\n // ─── Expression Editor Chip ───\n '--u-expression-editor-chip-bg': T('color', 'primary', 'dark', '9'),\n '--u-expression-editor-chip-color': T('color', 'primary'),\n\n // ─── Paginator active buttons ───\n '--u-paginator-btn-hover-bg': T('color', 'primary', 'dark', '9'),\n '--u-paginator-btn-hover-color': T('color', 'primary'),\n '--u-paginator-btn-active-bg': T('color', 'primary', 'dark', '9'),\n '--u-paginator-btn-active-color': T('color', 'primary'),\n\n // ─── Tabs List background (improved dark contrast) ───\n '--u-tabs-bar-bg': T('bg-color', 'bottom'),\n '--u-tabs-active-bg': T('bg-color', 'top'),\n\n // ─── Tag Component Colors ───\n '--u-tag-primary-bg': T('color', 'primary', 'dark', '9'),\n '--u-tag-primary-color': T('color', 'primary'),\n '--u-tag-primary-border': T('color', 'primary'),\n '--u-tag-success-bg': T('color', 'success', 'dark', '9'),\n '--u-tag-success-color': T('color', 'success'),\n '--u-tag-success-border': T('color', 'success'),\n '--u-tag-warning-bg': T('color', 'warning', 'dark', '9'),\n '--u-tag-warning-color': T('color', 'warning'),\n '--u-tag-warning-border': T('color', 'warning'),\n '--u-tag-danger-bg': T('color', 'danger', 'dark', '9'),\n '--u-tag-danger-color': T('color', 'danger'),\n '--u-tag-danger-border': T('color', 'danger'),\n '--u-tag-info-bg': T('color', 'info', 'dark', '9'),\n '--u-tag-info-color': T('color', 'info'),\n '--u-tag-info-border': T('color', 'info'),\n\n // ─── File Picker Colors ───\n '--u-file-picker-hover-bg': T('color', 'primary', 'dark', '9'),\n '--u-card-header-bg': 'rgba(255, 255, 255, 0.015)',\n '--u-card-action-bg': 'rgba(255, 255, 255, 0.015)'\n}\n\nfunction recordToDeclList(record: Record<string, string>): string[] {\n return Object.entries(record).map(([k, v]) => `${k}: ${v}`)\n}\n\nexport const componentCssVarsLightDecls: string[] = recordToDeclList(componentCssVarsLight)\n\nexport const componentCssVarsDarkDecls: string[] = recordToDeclList(componentCssVarsDark)\n\n// ─── Nav 侧栏外观:深/浅变体 × 明/暗主题系列 ───\n// 由 UITheme 按主题 `nav.variant`(默认 dark)选择注入,主题 `nav` 的其余键可逐项覆盖。\n// 同时注入实际底色色调(surface tone)与一组 `--u-nav-surface-*` 装饰 token:\n// 深色系列的任何变体、浅色系列的 dark 变体都是深底,应用壳绘制侧栏容器\n// (叠层渐变、分隔线、chip、品牌标记环、选中态、滚动条)可直接消费,无需写 [data-theme] 分支。\n\n/** 侧栏外观变体:dark 深底浅字 / light 浅底深字 */\nexport type NavSidebarVariant = 'dark' | 'light'\n\n/** 侧栏实际底色色调:dark 深底 / light 浅底 */\nexport type NavSurfaceTone = 'dark' | 'light'\n\n/**\n * 某主题系列 + 菜单变体下侧栏的实际底色色调。\n * 深色系列主题的两个变体都是深底(light 变体只是比内容区提亮一档)。\n */\nexport function navSurfaceTone(\n series: 'light' | 'dark',\n variant: NavSidebarVariant\n): NavSurfaceTone {\n return series === 'dark' || variant === 'dark' ? 'dark' : 'light'\n}\n\n/** 深底侧栏的表面装饰 token */\nconst navSurfaceDarkTone: Record<string, string> = {\n '--u-nav-surface-overlay': `radial-gradient(120% 70% at 0% 0%, ${T('color', 'primary', 'a', '16')}, transparent 62%), linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(0, 0, 0, 0.3))`,\n '--u-nav-surface-hairline': 'rgba(255, 255, 255, 0.07)',\n '--u-nav-surface-chip-bg': 'rgba(255, 255, 255, 0.055)',\n '--u-nav-surface-chip-border': 'rgba(255, 255, 255, 0.08)',\n '--u-nav-surface-chip-hover-bg': 'rgba(255, 255, 255, 0.09)',\n '--u-nav-surface-mark-ring': 'rgba(255, 255, 255, 0.14)',\n '--u-nav-surface-active-gradient': `linear-gradient(90deg, ${T('color', 'primary', 'a', '35')}, ${T('color', 'primary', 'a', '5')})`,\n '--u-nav-surface-active-ring': T('color', 'primary', 'a', '16'),\n '--u-nav-surface-accent': T('color', 'primary', 'light', '5'),\n '--u-nav-surface-scrollbar': 'rgba(255, 255, 255, 0.22)',\n '--u-nav-surface-scrollbar-hover': 'rgba(255, 255, 255, 0.4)'\n}\n\n/** 浅底侧栏的表面装饰 token */\nconst navSurfaceLightTone: Record<string, string> = {\n '--u-nav-surface-overlay': `radial-gradient(120% 70% at 0% 0%, ${T('color', 'primary', 'a', '8')}, transparent 62%), linear-gradient(180deg, rgba(255, 255, 255, 0.45), rgba(0, 0, 0, 0.02))`,\n '--u-nav-surface-hairline': T('border', 'color'),\n '--u-nav-surface-chip-bg': 'rgba(15, 23, 42, 0.04)',\n '--u-nav-surface-chip-border': T('border', 'color'),\n '--u-nav-surface-chip-hover-bg': 'rgba(15, 23, 42, 0.07)',\n '--u-nav-surface-mark-ring': 'rgba(15, 23, 42, 0.1)',\n '--u-nav-surface-active-gradient': `linear-gradient(90deg, ${T('color', 'primary', 'a', '16')}, ${T('color', 'primary', 'a', '4')})`,\n '--u-nav-surface-active-ring': T('color', 'primary', 'a', '8'),\n '--u-nav-surface-accent': T('color', 'primary'),\n '--u-nav-surface-scrollbar': T('text-color', 'assist', 'a', '40'),\n '--u-nav-surface-scrollbar-hover': T('text-color', 'assist', 'a', '60')\n}\n\n/** 给内置外观 token 补上与其实际底色色调匹配的表面装饰 token */\nfunction withNavSurface(\n appearance: Record<string, string>,\n series: 'light' | 'dark',\n variant: NavSidebarVariant\n): Record<string, string> {\n const surface =\n navSurfaceTone(series, variant) === 'dark' ? navSurfaceDarkTone : navSurfaceLightTone\n return { ...appearance, ...surface }\n}\n\n/** 深侧栏 · 浅色主题下:深底(text-color.title)+ 浅前景,与浅色内容区拉开区分度 */\nconst navSidebarDarkInLight: Record<string, string> = {\n '--u-nav-bg-color': T('text-color', 'title'),\n '--u-nav-color': 'rgba(255, 255, 255, 0.72)',\n '--u-nav-hover-bg': 'rgba(255, 255, 255, 0.08)',\n '--u-nav-hover-color': T('text-color', 'white'),\n '--u-nav-active-bg': T('color', 'primary', 'a', '22'),\n '--u-nav-active-color': T('text-color', 'white'),\n '--u-nav-strong-color': T('text-color', 'white'),\n '--u-nav-second-color': 'rgba(255, 255, 255, 0.45)',\n '--u-nav-sub-border-color': 'rgba(255, 255, 255, 0.15)',\n '--u-nav-rail-bg': 'rgba(0, 0, 0, 0.2)'\n}\n\n/** 浅侧栏 · 浅色主题下:比内容区 top 低一档的浅底 + 深前景;选中文字加深,保证 13px 正文的对比度 */\nconst navSidebarLightInLight: Record<string, string> = {\n '--u-nav-bg-color': T('bg-color', 'middle'),\n '--u-nav-color': T('text-color', 'title'),\n '--u-nav-hover-bg': T('text-color', 'title', 'a', '8'),\n '--u-nav-hover-color': T('text-color', 'title'),\n '--u-nav-active-bg': T('color', 'primary', 'a', '10'),\n '--u-nav-active-color': T('color', 'primary', 'dark', '3'),\n '--u-nav-strong-color': T('text-color', 'title'),\n '--u-nav-second-color': T('text-color', 'second'),\n '--u-nav-sub-border-color': T('border', 'color', 'a', '52'),\n '--u-nav-rail-bg': T('bg-color', 'bottom')\n}\n\n/** 深侧栏 · 深色主题下:比内容区 top 深一档 */\nconst navSidebarDarkInDark: Record<string, string> = {\n '--u-nav-bg-color': T('bg-color', 'middle'),\n '--u-nav-color': T('text-color', 'main'),\n '--u-nav-hover-bg': T('text-color', 'title', 'a', '8'),\n '--u-nav-hover-color': T('text-color', 'title'),\n '--u-nav-active-bg': T('color', 'primary', 'a', '16'),\n '--u-nav-active-color': T('text-color', 'white'),\n '--u-nav-strong-color': T('text-color', 'title'),\n '--u-nav-second-color': T('text-color', 'second'),\n '--u-nav-sub-border-color': T('border', 'color', 'a', '52'),\n '--u-nav-rail-bg': T('bg-color', 'bottom')\n}\n\n/** 浅侧栏 · 深色主题下:提亮侧栏(与深色内容区反向对比);表面仍是深底,选中文字用白色保证对比度 */\nconst navSidebarLightInDark: Record<string, string> = {\n '--u-nav-bg-color': T('bg-color', 'top'),\n '--u-nav-color': T('text-color', 'title'),\n '--u-nav-hover-bg': T('text-color', 'title', 'a', '8'),\n '--u-nav-hover-color': T('text-color', 'title'),\n '--u-nav-active-bg': T('color', 'primary', 'a', '22'),\n '--u-nav-active-color': T('text-color', 'white'),\n '--u-nav-strong-color': T('text-color', 'title'),\n '--u-nav-second-color': T('text-color', 'second'),\n '--u-nav-sub-border-color': T('border', 'color', 'a', '52'),\n '--u-nav-rail-bg': T('bg-color', 'middle')\n}\n\nconst navSidebarCssVars: Record<\n 'light' | 'dark',\n Record<NavSidebarVariant, Record<string, string>>\n> = {\n light: {\n dark: withNavSurface(navSidebarDarkInLight, 'light', 'dark'),\n light: withNavSurface(navSidebarLightInLight, 'light', 'light')\n },\n dark: {\n dark: withNavSurface(navSidebarDarkInDark, 'dark', 'dark'),\n light: withNavSurface(navSidebarLightInDark, 'dark', 'light')\n }\n}\n\n/** 某主题系列 + 侧栏变体下的 nav token(外观 + 表面装饰,键为 `--u-nav-*`) */\nexport function navSidebarTokens(\n series: 'light' | 'dark',\n variant: NavSidebarVariant\n): Record<string, string> {\n return { ...navSidebarCssVars[series][variant] }\n}\n\n/** 某主题系列 + 侧栏变体下的 nav 表面装饰 token(键为 `--u-nav-surface-*`) */\nexport function navSurfaceTokens(\n series: 'light' | 'dark',\n variant: NavSidebarVariant\n): Record<string, string> {\n const surface =\n navSurfaceTone(series, variant) === 'dark' ? navSurfaceDarkTone : navSurfaceLightTone\n return { ...surface }\n}\n\n/** 解析某主题系列 + 侧栏变体下的 nav token 声明列表 */\nexport function resolveNavSidebarDecls(\n series: 'light' | 'dark',\n variant: NavSidebarVariant\n): string[] {\n return recordToDeclList(navSidebarCssVars[series][variant])\n}\n"],"mappings":"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"}
|
package/dist/theme/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RGBColor, Theme } from "./type.js";
|
|
2
|
-
import { NavSidebarVariant, componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, navSidebarTokens, resolveNavSidebarDecls, themeTokenVar } from "./component-css-vars.js";
|
|
2
|
+
import { NavSidebarVariant, NavSurfaceTone, componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, navSidebarTokens, navSurfaceTokens, navSurfaceTone, resolveNavSidebarDecls, themeTokenVar } from "./component-css-vars.js";
|
|
3
3
|
import { ThemeSeries, UITheme, UIThemeOptions } from "./ui-theme.js";
|
|
4
4
|
import { lightTheme } from "./presets/light.js";
|
|
5
5
|
import { darkTheme } from "./presets/dark.js";
|
|
@@ -13,4 +13,4 @@ import { neonTheme } from "./presets/neon.js";
|
|
|
13
13
|
import "./presets/index.js";
|
|
14
14
|
import { currentTheme, loadTheme } from "./load-theme.js";
|
|
15
15
|
import { HEXToRGB, cssVar, defineBySize, hexRgbOnly, hexWithAlpha, isHexColor, mixColor, mixColorWithAlpha } from "./helper.js";
|
|
16
|
-
export { HEXToRGB, NavSidebarVariant, type RGBColor, type Theme, ThemeSeries, UITheme, UIThemeOptions, ancientTheme, componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, cssVar, currentTheme, darkTheme, defineBySize, glassTheme, heroTheme, hexRgbOnly, hexWithAlpha, isHexColor, lightTheme, loadTheme, midnightTheme, mixColor, mixColorWithAlpha, navSidebarTokens, neonTheme, oceanTheme, resolveNavSidebarDecls, sakuraTheme, themeTokenVar };
|
|
16
|
+
export { HEXToRGB, NavSidebarVariant, NavSurfaceTone, type RGBColor, type Theme, ThemeSeries, UITheme, UIThemeOptions, ancientTheme, componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, cssVar, currentTheme, darkTheme, defineBySize, glassTheme, heroTheme, hexRgbOnly, hexWithAlpha, isHexColor, lightTheme, loadTheme, midnightTheme, mixColor, mixColorWithAlpha, navSidebarTokens, navSurfaceTokens, navSurfaceTone, neonTheme, oceanTheme, resolveNavSidebarDecls, sakuraTheme, themeTokenVar };
|
package/dist/theme/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, navSidebarTokens, resolveNavSidebarDecls, themeTokenVar } from "./component-css-vars.js";
|
|
1
|
+
import { componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, navSidebarTokens, navSurfaceTokens, navSurfaceTone, resolveNavSidebarDecls, themeTokenVar } from "./component-css-vars.js";
|
|
2
2
|
import { HEXToRGB, cssVar, defineBySize, hexRgbOnly, hexWithAlpha, isHexColor, mixColor, mixColorWithAlpha } from "./helper.js";
|
|
3
3
|
import { UITheme } from "./ui-theme.js";
|
|
4
4
|
import { lightTheme } from "./presets/light.js";
|
|
@@ -11,4 +11,4 @@ import { oceanTheme } from "./presets/ocean.js";
|
|
|
11
11
|
import { midnightTheme } from "./presets/midnight.js";
|
|
12
12
|
import { neonTheme } from "./presets/neon.js";
|
|
13
13
|
import { currentTheme, loadTheme } from "./load-theme.js";
|
|
14
|
-
export { HEXToRGB, UITheme, ancientTheme, componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, cssVar, currentTheme, darkTheme, defineBySize, glassTheme, heroTheme, hexRgbOnly, hexWithAlpha, isHexColor, lightTheme, loadTheme, midnightTheme, mixColor, mixColorWithAlpha, navSidebarTokens, neonTheme, oceanTheme, resolveNavSidebarDecls, sakuraTheme, themeTokenVar };
|
|
14
|
+
export { HEXToRGB, UITheme, ancientTheme, componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, cssVar, currentTheme, darkTheme, defineBySize, glassTheme, heroTheme, hexRgbOnly, hexWithAlpha, isHexColor, lightTheme, loadTheme, midnightTheme, mixColor, mixColorWithAlpha, navSidebarTokens, navSurfaceTokens, navSurfaceTone, neonTheme, oceanTheme, resolveNavSidebarDecls, sakuraTheme, themeTokenVar };
|
|
@@ -34,7 +34,7 @@ const ancientTheme = lightTheme.new({
|
|
|
34
34
|
blur: 16,
|
|
35
35
|
spread: -2
|
|
36
36
|
},
|
|
37
|
-
nav: { "bg-color": mixColor("#2b2a26", "#3d6b58", .28) }
|
|
37
|
+
nav: { variants: { dark: { "bg-color": mixColor("#2b2a26", "#3d6b58", .28) } } }
|
|
38
38
|
});
|
|
39
39
|
//#endregion
|
|
40
40
|
export { ancientTheme };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ancient.js","names":[],"sources":["../../../src/theme/presets/ancient.ts"],"sourcesContent":["import { mixColor } from '../helper'\nimport { lightTheme } from './light'\n\n/** 古风(松烟绿 + 宣纸底),天生适合浅色 */\nexport const ancientTheme = lightTheme.new({\n color: {\n primary: '#3d6b58' // 松烟绿\n },\n bg: {\n color: {\n bottom: '#f1ede0', // 宣纸底\n middle: '#f7f4ea',\n top: '#fdfbf4',\n hover: '#e9e2cf'\n }\n },\n 'text-color': {\n title: '#2b2a26', // 黛墨\n main: '#403c34',\n second: '#7a7264',\n assist: '#a89f8c',\n placeholder: '#a89f8c'\n },\n border: { width: 1, color: '#e4dcc8', mutedColor: '#d2c8ac' },\n radius: { small: 4, default: 8, large: 12 },\n shadow: { color: 'rgba(64, 54, 32, 0.14)', x: 0, y: 4, blur: 16, spread: -2 },\n nav: {\n //
|
|
1
|
+
{"version":3,"file":"ancient.js","names":[],"sources":["../../../src/theme/presets/ancient.ts"],"sourcesContent":["import { mixColor } from '../helper'\nimport { lightTheme } from './light'\n\n/** 古风(松烟绿 + 宣纸底),天生适合浅色 */\nexport const ancientTheme = lightTheme.new({\n color: {\n primary: '#3d6b58' // 松烟绿\n },\n bg: {\n color: {\n bottom: '#f1ede0', // 宣纸底\n middle: '#f7f4ea',\n top: '#fdfbf4',\n hover: '#e9e2cf'\n }\n },\n 'text-color': {\n title: '#2b2a26', // 黛墨\n main: '#403c34',\n second: '#7a7264',\n assist: '#a89f8c',\n placeholder: '#a89f8c'\n },\n border: { width: 1, color: '#e4dcc8', mutedColor: '#d2c8ac' },\n radius: { small: 4, default: 8, large: 12 },\n shadow: { color: 'rgba(64, 54, 32, 0.14)', x: 0, y: 4, blur: 16, spread: -2 },\n nav: {\n // 松烟墨侧栏(深变体):黛墨 + 松烟绿调和;浅变体回落到主题宣纸底(bg middle)\n variants: { dark: { 'bg-color': mixColor('#2b2a26', '#3d6b58', 0.28) } }\n }\n})\n"],"mappings":";;;;AAIA,MAAa,eAAe,WAAW,IAAI;CACzC,OAAO,EACL,SAAS,UACX;CACA,IAAI,EACF,OAAO;EACL,QAAQ;EACR,QAAQ;EACR,KAAK;EACL,OAAO;CACT,EACF;CACA,cAAc;EACZ,OAAO;EACP,MAAM;EACN,QAAQ;EACR,QAAQ;EACR,aAAa;CACf;CACA,QAAQ;EAAE,OAAO;EAAG,OAAO;EAAW,YAAY;CAAU;CAC5D,QAAQ;EAAE,OAAO;EAAG,SAAS;EAAG,OAAO;CAAG;CAC1C,QAAQ;EAAE,OAAO;EAA0B,GAAG;EAAG,GAAG;EAAG,MAAM;EAAI,QAAQ;CAAG;CAC5E,KAAK,EAEH,UAAU,EAAE,MAAM,EAAE,YAAY,SAAS,WAAW,WAAW,GAAI,EAAE,EAAE,EACzE;AACF,CAAC"}
|
|
@@ -49,7 +49,7 @@ const oceanTheme = lightTheme.new({
|
|
|
49
49
|
fast: "0.12s",
|
|
50
50
|
ease: "cubic-bezier(0.22, 1, 0.36, 1)"
|
|
51
51
|
},
|
|
52
|
-
nav: { "bg-color": mixColor("#16302e", "#0d9488", .25) }
|
|
52
|
+
nav: { variants: { dark: { "bg-color": mixColor("#16302e", "#0d9488", .25) } } }
|
|
53
53
|
});
|
|
54
54
|
//#endregion
|
|
55
55
|
export { oceanTheme };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ocean.js","names":[],"sources":["../../../src/theme/presets/ocean.ts"],"sourcesContent":["import { mixColor } from '../helper'\nimport { lightTheme } from './light'\n\n/** 海盐(松石青 + 冷白底,利落的快缓动),天生适合浅色 */\nexport const oceanTheme = lightTheme.new({\n color: {\n primary: '#0d9488', // 松石青\n success: '#16a34a',\n warning: '#d97706',\n danger: '#dc2626',\n info: '#0284c7',\n disabled: '#eff6f5',\n default: '#eff6f5'\n },\n bg: { color: { bottom: '#eef6f5', middle: '#f5fafa', top: '#ffffff', hover: '#e0efee' } },\n 'text-color': {\n title: '#16302e', // 深礁\n main: '#2f4a48',\n second: '#5b7875',\n assist: '#c3d6d4',\n placeholder: '#7fa19e',\n disabled: '#a3bab7'\n },\n border: { width: 1, color: '#c2dedb', mutedColor: '#8fbcb7' },\n radius: { small: 6, default: 10, large: 14 },\n shadow: {\n color: 'rgba(21, 94, 89, 0.12)',\n x: 0,\n y: 2,\n blur: 10,\n spread: -1,\n sm: '0 1px 2px 0 rgba(21, 94, 89, 0.08)',\n lg: '0 8px 24px 0 rgba(21, 94, 89, 0.12), 0 2px 6px 0 rgba(21, 94, 89, 0.06)'\n },\n transition: { fast: '0.12s', ease: 'cubic-bezier(0.22, 1, 0.36, 1)' },\n nav: {\n //
|
|
1
|
+
{"version":3,"file":"ocean.js","names":[],"sources":["../../../src/theme/presets/ocean.ts"],"sourcesContent":["import { mixColor } from '../helper'\nimport { lightTheme } from './light'\n\n/** 海盐(松石青 + 冷白底,利落的快缓动),天生适合浅色 */\nexport const oceanTheme = lightTheme.new({\n color: {\n primary: '#0d9488', // 松石青\n success: '#16a34a',\n warning: '#d97706',\n danger: '#dc2626',\n info: '#0284c7',\n disabled: '#eff6f5',\n default: '#eff6f5'\n },\n bg: { color: { bottom: '#eef6f5', middle: '#f5fafa', top: '#ffffff', hover: '#e0efee' } },\n 'text-color': {\n title: '#16302e', // 深礁\n main: '#2f4a48',\n second: '#5b7875',\n assist: '#c3d6d4',\n placeholder: '#7fa19e',\n disabled: '#a3bab7'\n },\n border: { width: 1, color: '#c2dedb', mutedColor: '#8fbcb7' },\n radius: { small: 6, default: 10, large: 14 },\n shadow: {\n color: 'rgba(21, 94, 89, 0.12)',\n x: 0,\n y: 2,\n blur: 10,\n spread: -1,\n sm: '0 1px 2px 0 rgba(21, 94, 89, 0.08)',\n lg: '0 8px 24px 0 rgba(21, 94, 89, 0.12), 0 2px 6px 0 rgba(21, 94, 89, 0.06)'\n },\n transition: { fast: '0.12s', ease: 'cubic-bezier(0.22, 1, 0.36, 1)' },\n nav: {\n // 深海礁侧栏(深变体):深礁 + 松石青调和;浅变体回落到主题雾白底(bg middle)\n variants: { dark: { 'bg-color': mixColor('#16302e', '#0d9488', 0.25) } }\n }\n})\n"],"mappings":";;;;AAIA,MAAa,aAAa,WAAW,IAAI;CACvC,OAAO;EACL,SAAS;EACT,SAAS;EACT,SAAS;EACT,QAAQ;EACR,MAAM;EACN,UAAU;EACV,SAAS;CACX;CACA,IAAI,EAAE,OAAO;EAAE,QAAQ;EAAW,QAAQ;EAAW,KAAK;EAAW,OAAO;CAAU,EAAE;CACxF,cAAc;EACZ,OAAO;EACP,MAAM;EACN,QAAQ;EACR,QAAQ;EACR,aAAa;EACb,UAAU;CACZ;CACA,QAAQ;EAAE,OAAO;EAAG,OAAO;EAAW,YAAY;CAAU;CAC5D,QAAQ;EAAE,OAAO;EAAG,SAAS;EAAI,OAAO;CAAG;CAC3C,QAAQ;EACN,OAAO;EACP,GAAG;EACH,GAAG;EACH,MAAM;EACN,QAAQ;EACR,IAAI;EACJ,IAAI;CACN;CACA,YAAY;EAAE,MAAM;EAAS,MAAM;CAAiC;CACpE,KAAK,EAEH,UAAU,EAAE,MAAM,EAAE,YAAY,SAAS,WAAW,WAAW,GAAI,EAAE,EAAE,EACzE;AACF,CAAC"}
|
|
@@ -51,7 +51,7 @@ const sakuraTheme = lightTheme.new({
|
|
|
51
51
|
lg: "0 8px 24px 0 rgba(173, 58, 105, 0.14), 0 2px 6px 0 rgba(173, 58, 105, 0.08)"
|
|
52
52
|
},
|
|
53
53
|
transition: { easeOut: "cubic-bezier(0.34, 1.56, 0.64, 1)" },
|
|
54
|
-
nav: { "bg-color": mixColor("#43272f", "#e64980", .22) }
|
|
54
|
+
nav: { variants: { dark: { "bg-color": mixColor("#43272f", "#e64980", .22) } } }
|
|
55
55
|
});
|
|
56
56
|
//#endregion
|
|
57
57
|
export { sakuraTheme };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sakura.js","names":[],"sources":["../../../src/theme/presets/sakura.ts"],"sourcesContent":["import { mixColor } from '../helper'\nimport { lightTheme } from './light'\n\n/** 樱花(柔粉 + 花瓣底,大圆角、弹性缓动),天生适合浅色 */\nexport const sakuraTheme = lightTheme.new({\n color: {\n primary: '#e64980', // 樱粉\n success: '#2f9e6e',\n warning: '#e8890c',\n danger: '#e03131',\n info: '#7c6cf0',\n disabled: '#faf0f3',\n default: '#faf0f3'\n },\n bg: { color: { bottom: '#fdf1f5', middle: '#fef6f9', top: '#ffffff', hover: '#fbe4ec' } },\n 'text-color': {\n title: '#43272f', // 樱墨\n main: '#5f3d46',\n second: '#92616d',\n assist: '#dcc0c7',\n placeholder: '#b58694',\n disabled: '#c4a0aa'\n },\n border: { width: 1, color: '#f0c3d4', mutedColor: '#e09db6' },\n radius: { small: 8, default: 12, large: 16 },\n // 更宽松的表单控件,配合大圆角的柔和感\n 'form-component-height': { small: 26, default: 34, large: 42 },\n shadow: {\n color: 'rgba(173, 58, 105, 0.12)',\n x: 0,\n y: 4,\n blur: 14,\n spread: -2,\n sm: '0 1px 2px 0 rgba(173, 58, 105, 0.08)',\n lg: '0 8px 24px 0 rgba(173, 58, 105, 0.14), 0 2px 6px 0 rgba(173, 58, 105, 0.08)'\n },\n transition: { easeOut: 'cubic-bezier(0.34, 1.56, 0.64, 1)' },\n nav: {\n //
|
|
1
|
+
{"version":3,"file":"sakura.js","names":[],"sources":["../../../src/theme/presets/sakura.ts"],"sourcesContent":["import { mixColor } from '../helper'\nimport { lightTheme } from './light'\n\n/** 樱花(柔粉 + 花瓣底,大圆角、弹性缓动),天生适合浅色 */\nexport const sakuraTheme = lightTheme.new({\n color: {\n primary: '#e64980', // 樱粉\n success: '#2f9e6e',\n warning: '#e8890c',\n danger: '#e03131',\n info: '#7c6cf0',\n disabled: '#faf0f3',\n default: '#faf0f3'\n },\n bg: { color: { bottom: '#fdf1f5', middle: '#fef6f9', top: '#ffffff', hover: '#fbe4ec' } },\n 'text-color': {\n title: '#43272f', // 樱墨\n main: '#5f3d46',\n second: '#92616d',\n assist: '#dcc0c7',\n placeholder: '#b58694',\n disabled: '#c4a0aa'\n },\n border: { width: 1, color: '#f0c3d4', mutedColor: '#e09db6' },\n radius: { small: 8, default: 12, large: 16 },\n // 更宽松的表单控件,配合大圆角的柔和感\n 'form-component-height': { small: 26, default: 34, large: 42 },\n shadow: {\n color: 'rgba(173, 58, 105, 0.12)',\n x: 0,\n y: 4,\n blur: 14,\n spread: -2,\n sm: '0 1px 2px 0 rgba(173, 58, 105, 0.08)',\n lg: '0 8px 24px 0 rgba(173, 58, 105, 0.14), 0 2px 6px 0 rgba(173, 58, 105, 0.08)'\n },\n transition: { easeOut: 'cubic-bezier(0.34, 1.56, 0.64, 1)' },\n nav: {\n // 深酒红侧栏(深变体):樱墨 + 樱粉调和;浅变体回落到主题樱粉底(bg middle)\n variants: { dark: { 'bg-color': mixColor('#43272f', '#e64980', 0.22) } }\n }\n})\n"],"mappings":";;;;AAIA,MAAa,cAAc,WAAW,IAAI;CACxC,OAAO;EACL,SAAS;EACT,SAAS;EACT,SAAS;EACT,QAAQ;EACR,MAAM;EACN,UAAU;EACV,SAAS;CACX;CACA,IAAI,EAAE,OAAO;EAAE,QAAQ;EAAW,QAAQ;EAAW,KAAK;EAAW,OAAO;CAAU,EAAE;CACxF,cAAc;EACZ,OAAO;EACP,MAAM;EACN,QAAQ;EACR,QAAQ;EACR,aAAa;EACb,UAAU;CACZ;CACA,QAAQ;EAAE,OAAO;EAAG,OAAO;EAAW,YAAY;CAAU;CAC5D,QAAQ;EAAE,OAAO;EAAG,SAAS;EAAI,OAAO;CAAG;CAE3C,yBAAyB;EAAE,OAAO;EAAI,SAAS;EAAI,OAAO;CAAG;CAC7D,QAAQ;EACN,OAAO;EACP,GAAG;EACH,GAAG;EACH,MAAM;EACN,QAAQ;EACR,IAAI;EACJ,IAAI;CACN;CACA,YAAY,EAAE,SAAS,oCAAoC;CAC3D,KAAK,EAEH,UAAU,EAAE,MAAM,EAAE,YAAY,SAAS,WAAW,WAAW,GAAI,EAAE,EAAE,EACzE;AACF,CAAC"}
|
package/dist/theme/type.d.ts
CHANGED
|
@@ -178,12 +178,18 @@ export type Theme = {
|
|
|
178
178
|
};
|
|
179
179
|
/**
|
|
180
180
|
* 侧栏导航(nav / dual-nav / group-nav)组件级变量。
|
|
181
|
-
* variant
|
|
182
|
-
* (如 `'bg-color'` → `--u-nav-bg-color
|
|
181
|
+
* `variant` 选择默认深/浅侧栏外观;顶层其余字符串键对所有变体生效并覆盖同名
|
|
182
|
+
* `--u-nav-*` token(如 `'bg-color'` → `--u-nav-bg-color`);
|
|
183
|
+
* `variants` 可为两个变体分别定制外观,只在该变体生效且优先级最高。
|
|
183
184
|
*/
|
|
184
185
|
nav?: {
|
|
185
|
-
/**
|
|
186
|
+
/** 侧栏默认外观:dark 深底浅字 / light 浅底深字,默认 dark */
|
|
186
187
|
variant?: 'dark' | 'light';
|
|
188
|
+
/**
|
|
189
|
+
* 按变体定制的外观覆盖,键同 nav 顶层(如 `'bg-color'`)。
|
|
190
|
+
* 未声明的变体回落到内置「主题系列 × 变体」token。
|
|
191
|
+
*/
|
|
192
|
+
variants?: Partial<Record<'dark' | 'light', Record<string, string>>>;
|
|
187
193
|
[key: string]: any;
|
|
188
194
|
};
|
|
189
195
|
/** 折叠面板组件级变量 */
|
package/dist/theme/ui-theme.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Theme } from "./type.js";
|
|
2
|
+
import { NavSidebarVariant } from "./component-css-vars.js";
|
|
2
3
|
//#region src/theme/ui-theme.d.ts
|
|
3
4
|
type RecursivePartial<T> = { [P in keyof T]?: T[P] extends object ? RecursivePartial<T[P]> : T[P]; };
|
|
4
5
|
/** 主题系列:浅色或深色。决定组件级 token 与 html[data-theme] */
|
|
@@ -30,14 +31,41 @@ export declare class UITheme {
|
|
|
30
31
|
/** 主题变量声明列表,均为 `--u-` 前缀的 CSS 自定义属性 */
|
|
31
32
|
themeToDeclarationList(theme: Theme): string[];
|
|
32
33
|
private static declarationBlock;
|
|
34
|
+
/** 主题的默认菜单变体(未声明时为 dark) */
|
|
35
|
+
private navSidebarVariant;
|
|
33
36
|
/**
|
|
34
|
-
*
|
|
37
|
+
* 主题 nav 覆盖声明:顶层字符串键对所有变体生效;
|
|
38
|
+
* `nav.variants[variant]` 只对该变体生效,追加在最后(同规则后者生效)。
|
|
39
|
+
*/
|
|
40
|
+
private navOverrideDecls;
|
|
41
|
+
/** 指定系列 + 变体的 nav 声明(内置 token + 主题覆盖),供 html 级与容器级注入共用 */
|
|
42
|
+
private navSeriesDecls;
|
|
43
|
+
/**
|
|
44
|
+
* nav 侧栏外观声明:默认按主题 `nav.variant` 取内置深/浅侧栏 token,
|
|
35
45
|
* 主题 `nav` 的其余键作为 `--u-nav-*` 覆盖追加在最后(同规则后者生效)。
|
|
46
|
+
* @param variant 显式指定变体(容器级/预览取色用),不传取主题默认变体
|
|
47
|
+
*/
|
|
48
|
+
navSidebarDecls(theme: Theme, variant?: NavSidebarVariant): string[];
|
|
49
|
+
/**
|
|
50
|
+
* 派生指定菜单变体的主题。变体专属外观由 `nav.variants` 声明,
|
|
51
|
+
* 切换时不再需要手动展开 `navSidebarTokens` 覆盖预设个性色。
|
|
36
52
|
*/
|
|
37
|
-
|
|
53
|
+
withNavVariant(variant: NavSidebarVariant): UITheme;
|
|
54
|
+
private static toVariableMap;
|
|
55
|
+
/** 把 token 值里的 `var(--u-*)` 递归解析成具体色值(供主题预览/取色) */
|
|
56
|
+
private static resolveVarValue;
|
|
57
|
+
/**
|
|
58
|
+
* 解析当前主题某菜单变体的具体色值(键为去掉 `--u-nav-` 前缀的 token 名,
|
|
59
|
+
* 如 `'bg-color'`、`'active-color'`、`'surface-hairline'`)。
|
|
60
|
+
* 用于主题选择器预览等「主题未加载到 DOM 也要取色」的场景。
|
|
61
|
+
*/
|
|
62
|
+
navSidebarColors(variant?: NavSidebarVariant): Record<string, string>;
|
|
38
63
|
private static removeExistingStyleTag;
|
|
39
64
|
private static applyGlobalCSS;
|
|
40
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* 注入主题:全局 token + 与主题系列匹配的组件级 token + nav 侧栏外观,写入 html[data-theme];
|
|
67
|
+
* 同时注入容器级菜单变体规则(`[data-nav-variant]`)与实际底色色调 `html[data-nav-surface]`。
|
|
68
|
+
*/
|
|
41
69
|
render(): void;
|
|
42
70
|
new(customTheme?: RecursivePartial<Theme>, options?: {
|
|
43
71
|
series?: ThemeSeries;
|
package/dist/theme/ui-theme.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { componentCssVarsDarkDecls, componentCssVarsLightDecls, resolveNavSidebarDecls } from "./component-css-vars.js";
|
|
1
|
+
import { componentCssVarsDarkDecls, componentCssVarsLightDecls, navSurfaceTone, resolveNavSidebarDecls } from "./component-css-vars.js";
|
|
2
2
|
import { hexRgbOnly, hexWithAlpha, isHexColor, mixColor } from "./helper.js";
|
|
3
3
|
import { isObj, str } from "@cat-kit/core";
|
|
4
4
|
import { withUnit } from "@veltra/utils";
|
|
@@ -158,16 +158,79 @@ var UITheme = class UITheme {
|
|
|
158
158
|
static declarationBlock(decls) {
|
|
159
159
|
return decls.join(";");
|
|
160
160
|
}
|
|
161
|
+
/** 主题的默认菜单变体(未声明时为 dark) */
|
|
162
|
+
navSidebarVariant(theme) {
|
|
163
|
+
return theme.nav?.variant === "light" ? "light" : "dark";
|
|
164
|
+
}
|
|
161
165
|
/**
|
|
162
|
-
*
|
|
163
|
-
*
|
|
166
|
+
* 主题 nav 覆盖声明:顶层字符串键对所有变体生效;
|
|
167
|
+
* `nav.variants[variant]` 只对该变体生效,追加在最后(同规则后者生效)。
|
|
164
168
|
*/
|
|
165
|
-
|
|
169
|
+
navOverrideDecls(theme, variant) {
|
|
166
170
|
const nav = theme.nav ?? {};
|
|
167
|
-
const
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
+
const toDecls = (record) => Object.keys(record ?? {}).filter((key) => typeof record[key] === "string" && record[key]).map((key) => `--u-nav-${str(key).kebabCase()}: ${record[key]}`);
|
|
172
|
+
const topLevel = { ...nav };
|
|
173
|
+
delete topLevel.variant;
|
|
174
|
+
delete topLevel.variants;
|
|
175
|
+
return [...toDecls(topLevel), ...toDecls(nav.variants?.[variant])];
|
|
176
|
+
}
|
|
177
|
+
/** 指定系列 + 变体的 nav 声明(内置 token + 主题覆盖),供 html 级与容器级注入共用 */
|
|
178
|
+
navSeriesDecls(theme, series, variant) {
|
|
179
|
+
return [...resolveNavSidebarDecls(series, variant), ...this.navOverrideDecls(theme, variant)];
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* nav 侧栏外观声明:默认按主题 `nav.variant` 取内置深/浅侧栏 token,
|
|
183
|
+
* 主题 `nav` 的其余键作为 `--u-nav-*` 覆盖追加在最后(同规则后者生效)。
|
|
184
|
+
* @param variant 显式指定变体(容器级/预览取色用),不传取主题默认变体
|
|
185
|
+
*/
|
|
186
|
+
navSidebarDecls(theme, variant) {
|
|
187
|
+
return this.navSeriesDecls(theme, this.series, variant ?? this.navSidebarVariant(theme));
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* 派生指定菜单变体的主题。变体专属外观由 `nav.variants` 声明,
|
|
191
|
+
* 切换时不再需要手动展开 `navSidebarTokens` 覆盖预设个性色。
|
|
192
|
+
*/
|
|
193
|
+
withNavVariant(variant) {
|
|
194
|
+
return this.new({ nav: { variant } });
|
|
195
|
+
}
|
|
196
|
+
static toVariableMap(decls) {
|
|
197
|
+
const map = /* @__PURE__ */ new Map();
|
|
198
|
+
for (const decl of decls) {
|
|
199
|
+
const index = decl.indexOf(":");
|
|
200
|
+
if (index < 0) continue;
|
|
201
|
+
map.set(decl.slice(0, index).trim(), decl.slice(index + 1).trim());
|
|
202
|
+
}
|
|
203
|
+
return map;
|
|
204
|
+
}
|
|
205
|
+
/** 把 token 值里的 `var(--u-*)` 递归解析成具体色值(供主题预览/取色) */
|
|
206
|
+
static resolveVarValue(value, ...maps) {
|
|
207
|
+
let resolved = value;
|
|
208
|
+
for (let depth = 0; depth < 6 && resolved.includes("var(--u-"); depth += 1) {
|
|
209
|
+
const next = resolved.replace(/var\((--u-[\w-]+)\)/g, (raw, name) => {
|
|
210
|
+
for (const map of maps) {
|
|
211
|
+
const hit = map.get(name);
|
|
212
|
+
if (hit !== void 0) return hit;
|
|
213
|
+
}
|
|
214
|
+
return raw;
|
|
215
|
+
});
|
|
216
|
+
if (next === resolved) break;
|
|
217
|
+
resolved = next;
|
|
218
|
+
}
|
|
219
|
+
return resolved;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* 解析当前主题某菜单变体的具体色值(键为去掉 `--u-nav-` 前缀的 token 名,
|
|
223
|
+
* 如 `'bg-color'`、`'active-color'`、`'surface-hairline'`)。
|
|
224
|
+
* 用于主题选择器预览等「主题未加载到 DOM 也要取色」的场景。
|
|
225
|
+
*/
|
|
226
|
+
navSidebarColors(variant) {
|
|
227
|
+
const raw = toRaw(this.theme);
|
|
228
|
+
const target = variant ?? this.navSidebarVariant(raw);
|
|
229
|
+
const themeVars = UITheme.toVariableMap(this.themeToDeclarationList(raw));
|
|
230
|
+
const navVars = UITheme.toVariableMap(this.navSeriesDecls(raw, this.series, target));
|
|
231
|
+
const colors = {};
|
|
232
|
+
for (const [name, value] of navVars) colors[name.replace(/^--u-nav-/, "")] = UITheme.resolveVarValue(value, themeVars, navVars);
|
|
233
|
+
return colors;
|
|
171
234
|
}
|
|
172
235
|
static removeExistingStyleTag(doc) {
|
|
173
236
|
const el = doc.getElementById(UITheme.themeID);
|
|
@@ -194,18 +257,28 @@ var UITheme = class UITheme {
|
|
|
194
257
|
style.textContent = css;
|
|
195
258
|
}
|
|
196
259
|
}
|
|
197
|
-
/**
|
|
260
|
+
/**
|
|
261
|
+
* 注入主题:全局 token + 与主题系列匹配的组件级 token + nav 侧栏外观,写入 html[data-theme];
|
|
262
|
+
* 同时注入容器级菜单变体规则(`[data-nav-variant]`)与实际底色色调 `html[data-nav-surface]`。
|
|
263
|
+
*/
|
|
198
264
|
render() {
|
|
199
265
|
const componentDecls = this.series === "dark" ? componentCssVarsDarkDecls : componentCssVarsLightDecls;
|
|
200
266
|
const raw = toRaw(this.theme);
|
|
267
|
+
const activeVariant = this.navSidebarVariant(raw);
|
|
201
268
|
const decls = [
|
|
202
269
|
...this.themeToDeclarationList(raw),
|
|
203
270
|
...componentDecls,
|
|
204
|
-
...this.
|
|
271
|
+
...this.navSeriesDecls(raw, this.series, activeVariant)
|
|
205
272
|
];
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
273
|
+
const block = UITheme.declarationBlock(decls);
|
|
274
|
+
const variantRules = ["light", "dark"].flatMap((series) => ["dark", "light"].map((variant) => {
|
|
275
|
+
return `html[data-theme="${series}"] [data-nav-variant="${variant}"] { ${UITheme.declarationBlock(this.navSeriesDecls(raw, series, variant))} }`;
|
|
276
|
+
}));
|
|
277
|
+
UITheme.applyGlobalCSS([`html { ${block} }`, ...variantRules].join("\n"));
|
|
278
|
+
if (typeof document !== "undefined") {
|
|
279
|
+
document.documentElement.dataset.theme = this.series;
|
|
280
|
+
document.documentElement.dataset.navSurface = navSurfaceTone(this.series, activeVariant);
|
|
281
|
+
}
|
|
209
282
|
}
|
|
210
283
|
new(customTheme = {}, options) {
|
|
211
284
|
function delEmpty(obj) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-theme.js","names":[],"sources":["../../src/theme/ui-theme.ts"],"sourcesContent":["import { isObj, str } from '@cat-kit/core'\nimport { withUnit } from '@veltra/utils'\nimport { reactive, toRaw, watch } from 'vue'\n\nimport {\n componentCssVarsDarkDecls,\n componentCssVarsLightDecls,\n resolveNavSidebarDecls,\n type NavSidebarVariant\n} from './component-css-vars'\nimport { hexRgbOnly, hexWithAlpha, isHexColor, mixColor } from './helper'\nimport type { Theme } from './type'\n\ntype RecursivePartial<T> = {\n [P in keyof T]?: T[P] extends object ? RecursivePartial<T[P]> : T[P]\n}\n\n/** 主题系列:浅色或深色。决定组件级 token 与 html[data-theme] */\nexport type ThemeSeries = 'light' | 'dark'\n\nexport interface UIThemeOptions {\n /** 主题变更时是否自动重渲染,默认 true */\n reactive?: boolean\n /** 主题所属系列,默认 'light' */\n series?: ThemeSeries\n}\n\nexport class UITheme {\n static themeID = 'ultra-ui-theme'\n\n private static adoptedSheet: CSSStyleSheet | null = null\n\n readonly theme: Theme\n\n /** 主题所属系列:浅色 / 深色 */\n series: ThemeSeries\n\n private readonly reactiveEnabled: boolean\n\n constructor(theme: Theme, options?: UIThemeOptions) {\n this.reactiveEnabled = options?.reactive !== false\n this.series = options?.series ?? 'light'\n this.theme = reactive(theme) as Theme\n if (this.reactiveEnabled) {\n watch(this.theme, () => this.render(), { deep: true })\n }\n }\n\n private renderBase(\n theme: Record<string, unknown>,\n themeRules: string[] = [],\n parentKey = '--u'\n ): string[] {\n Object.keys(theme).forEach((key) => {\n // nav 由 navSidebarDecls 按 variant + 覆盖项单独注入(须晚于组件级 token 才生效)\n if (parentKey === '--u' && key === 'nav') return\n const value = theme[key]\n const varKey = `${parentKey.startsWith('-') ? parentKey : str(parentKey).kebabCase()}-${str(key).kebabCase()}`\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n this.renderBase(value as Record<string, unknown>, themeRules, varKey)\n } else {\n if (value || value === 0) {\n const v = withUnit(value as number | string, 'px')\n if (v !== undefined) {\n themeRules.push(`${varKey}: ${v}`)\n }\n }\n }\n })\n\n return themeRules\n }\n\n private renderBorder(theme: Theme): string {\n const shorthandKeys = (Object.keys(theme.border) as Array<keyof typeof theme.border>).filter(\n (key) => key !== 'mutedColor'\n )\n const border = shorthandKeys.map((key) => `var(--u-border-${key})`).join(' ')\n\n return [\n `--u-border: ${border}`,\n `--u-border-muted: var(--u-border-muted-color) var(--u-border-width) var(--u-border-style)`\n ].join(';')\n }\n\n private renderTypeColor(theme: Theme): string {\n const { color } = theme\n\n const types = Object.keys(color)\n const rates = [1, 3, 5, 7, 9]\n\n return types\n .map((type) => {\n const colorValue = color[type as keyof typeof color]! as `#${string}`\n\n return rates\n .map((rate) => {\n const light = `--u-color-${type}-light-${rate}: ${mixColor(\n colorValue,\n '#fff',\n rate / 10\n )}`\n const dark = `--u-color-${type}-dark-${rate}: ${mixColor(\n colorValue,\n '#000',\n rate / 10\n )}`\n return `${light};${dark}`\n })\n .join(';')\n })\n .join(';')\n }\n\n private renderShadow(_theme: Theme): string {\n const shadow = ['x', 'y', 'blur', 'spread', 'color']\n .map((k) => `var(--u-shadow-${k})`)\n .join(' ')\n\n return `--u-shadow: ${shadow}`\n }\n\n private renderBGColorAlpha(theme: Theme): string {\n const { color } = theme.bg\n const alphas = [70]\n const lines: string[] = []\n for (const type of Object.keys(color)) {\n const value = color[type as keyof typeof color]\n // 非 hex 颜色(如 glass 主题的 rgba())无法推导 alpha token,跳过避免生成 NaN 声明\n if (typeof value !== 'string' || !isHexColor(value)) continue\n const hex = value as `#${string}`\n lines.push(`--u-bg-color-${type}-alpha: ${hex}aa`)\n for (const a of alphas) {\n lines.push(`--u-bg-color-${type}-a-${a}: ${hexWithAlpha(hex, a)}`)\n }\n }\n return lines.join(';')\n }\n\n /** 语义色 / 边框 / 阴影 / 文本色的 alpha token(替代 color-mix + transparent) */\n private renderAlphaTokens(theme: Theme): string {\n const alphas = [4, 5, 8, 10, 11, 16, 22, 28, 35, 40, 50, 52, 60, 70, 86]\n const lines: string[] = []\n\n for (const type of Object.keys(theme.color)) {\n const value = theme.color[type as keyof typeof theme.color]\n if (typeof value !== 'string' || !isHexColor(value)) continue\n const hex = value as `#${string}`\n for (const a of alphas) {\n lines.push(`--u-color-${type}-a-${a}: ${hexWithAlpha(hex, a)}`)\n }\n }\n\n const borderHex = theme.border.color as `#${string}`\n if (isHexColor(borderHex)) {\n for (const a of alphas) {\n lines.push(`--u-border-color-a-${a}: ${hexWithAlpha(borderHex, a)}`)\n }\n }\n\n const shadowHex = hexRgbOnly(theme.shadow.color)\n // 阴影色非 hex(如 rgba())时无法推导 alpha token,跳过避免生成 NaN 声明\n if (isHexColor(shadowHex)) {\n for (const a of alphas) {\n lines.push(`--u-shadow-color-a-${a}: ${hexWithAlpha(shadowHex, a)}`)\n }\n }\n\n const textColor = theme['text-color']\n for (const type of Object.keys(textColor)) {\n const value = textColor[type as keyof typeof textColor]\n if (typeof value === 'string' && isHexColor(value)) {\n const hex = value as `#${string}`\n for (const a of alphas) {\n lines.push(`--u-text-color-${type}-a-${a}: ${hexWithAlpha(hex, a)}`)\n }\n }\n }\n\n return lines.join(';')\n }\n\n /** 组件级两色混合 token(batch-edit / kbd) */\n private renderComponentMixTokens(theme: Theme): string {\n const hover = theme.bg.color.hover as `#${string}`\n const top = theme.bg.color.top as `#${string}`\n const black = theme.bg.color.black as `#${string}`\n const borderColor = theme.border.color as `#${string}`\n const shadowColor = hexRgbOnly(theme.shadow.color)\n\n // 依赖色含非 hex 值(如 glass 主题的 rgba())时整体跳过,避免生成 NaN 声明;\n // 组件侧 var() fallback 会接管,行为等同于此前的无效声明\n if (![hover, top, black, borderColor].every(isHexColor)) return ''\n\n const formHeaderBg = mixColor(top, hover, 0.04)\n\n const kbdInset = mixColor(top, black, 0.25)\n const kbdDropShadow = isHexColor(shadowColor)\n ? hexWithAlpha(shadowColor, 60)\n : 'rgba(0, 0, 0, 0.6)'\n\n const lines = [\n `--u-batch-edit-form-header-bg: ${formHeaderBg}`,\n `--u-kbd-inset-shadow: ${kbdInset}`,\n `--u-kbd-border-shadow: ${hexWithAlpha(borderColor, 50)}`,\n `--u-kbd-drop-shadow: ${kbdDropShadow}`\n ]\n\n return lines.join(';')\n }\n\n private renderBGFilter(theme: Theme): string {\n const { filter } = theme.bg\n const value = filter.blur === 'none' ? 'none' : `${filter.blur} ${filter.saturate}`\n return `--u-bg-filter: ${value}`\n }\n\n /** 主题变量声明列表,均为 `--u-` 前缀的 CSS 自定义属性 */\n themeToDeclarationList(theme: Theme): string[] {\n const raw = theme as unknown as Record<string, unknown>\n const lines: string[] = [...this.renderBase(raw)]\n const chunks = [\n this.renderTypeColor(theme),\n this.renderShadow(theme),\n this.renderBGColorAlpha(theme),\n this.renderAlphaTokens(theme),\n this.renderComponentMixTokens(theme),\n this.renderBGFilter(theme),\n this.renderBorder(theme)\n ]\n for (const c of chunks) {\n lines.push(\n ...c\n .split(';')\n .map((s) => s.trim())\n .filter(Boolean)\n )\n }\n return lines\n }\n\n private static declarationBlock(decls: string[]): string {\n return decls.join(';')\n }\n\n /**\n * nav 侧栏外观声明:按主题 `nav.variant`(默认 dark)取内置深/浅侧栏 token,\n * 主题 `nav` 的其余键作为 `--u-nav-*` 覆盖追加在最后(同规则后者生效)。\n */\n navSidebarDecls(theme: Theme): string[] {\n const nav = theme.nav ?? {}\n const variant: NavSidebarVariant = nav.variant === 'light' ? 'light' : 'dark'\n const decls = resolveNavSidebarDecls(this.series, variant)\n const overrides = Object.keys(nav)\n .filter((key) => key !== 'variant' && typeof nav[key] === 'string' && nav[key])\n .map((key) => `--u-nav-${str(key).kebabCase()}: ${nav[key]}`)\n return [...decls, ...overrides]\n }\n\n private static removeExistingStyleTag(doc: Document): void {\n const el = doc.getElementById(UITheme.themeID)\n if (el?.parentNode) {\n el.parentNode.removeChild(el)\n }\n }\n\n private static applyGlobalCSS(css: string): void {\n const doc = typeof document !== 'undefined' ? document : undefined\n if (!doc) return\n\n const canAdopt =\n typeof CSSStyleSheet !== 'undefined' && 'adoptedStyleSheets' in Document.prototype\n\n if (canAdopt) {\n UITheme.removeExistingStyleTag(doc)\n if (!UITheme.adoptedSheet) {\n UITheme.adoptedSheet = new CSSStyleSheet()\n doc.adoptedStyleSheets = [...doc.adoptedStyleSheets, UITheme.adoptedSheet]\n }\n UITheme.adoptedSheet.replaceSync(css)\n } else {\n if (UITheme.adoptedSheet) {\n UITheme.adoptedSheet = null\n }\n let style = doc.getElementById(UITheme.themeID)\n if (!style) {\n style = doc.createElement('style')\n style.id = UITheme.themeID\n doc.head.appendChild(style)\n }\n style.textContent = css\n }\n }\n\n /** 注入主题:全局 token + 与主题系列匹配的组件级 token + nav 侧栏外观,并写入 html[data-theme] */\n render(): void {\n const componentDecls =\n this.series === 'dark' ? componentCssVarsDarkDecls : componentCssVarsLightDecls\n const raw = toRaw(this.theme)\n const decls = [\n ...this.themeToDeclarationList(raw),\n ...componentDecls,\n ...this.navSidebarDecls(raw)\n ]\n const block = UITheme.declarationBlock(decls)\n const css = `html { ${block} }`\n UITheme.applyGlobalCSS(css)\n if (typeof document !== 'undefined') {\n document.documentElement.dataset.theme = this.series\n }\n }\n\n new(customTheme: RecursivePartial<Theme> = {}, options?: { series?: ThemeSeries }): UITheme {\n function delEmpty(obj: Record<string, unknown>) {\n Object.keys(obj).forEach((key) => {\n const value = obj[key]\n if (isObj(value)) {\n return delEmpty(value as Record<string, unknown>)\n }\n if (!value && value !== 0) {\n delete obj[key]\n }\n })\n }\n\n delEmpty(customTheme as Record<string, unknown>)\n\n const base = JSON.parse(JSON.stringify(toRaw(this.theme))) as Record<string, any>\n\n function deepMerge(target: any, source: any) {\n if (typeof source !== 'object' || source === null) return\n Object.keys(source).forEach((key) => {\n const sourceVal = source[key]\n if (typeof sourceVal === 'object' && sourceVal !== null && !Array.isArray(sourceVal)) {\n if (typeof target[key] !== 'object' || target[key] === null) {\n target[key] = {}\n }\n deepMerge(target[key], sourceVal)\n } else {\n target[key] = sourceVal\n }\n })\n }\n\n deepMerge(base, customTheme)\n return new UITheme(base as Theme, {\n reactive: this.reactiveEnabled,\n series: options?.series ?? this.series\n })\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ui-theme.js","names":[],"sources":["../../src/theme/ui-theme.ts"],"sourcesContent":["import { isObj, str } from '@cat-kit/core'\nimport { withUnit } from '@veltra/utils'\nimport { reactive, toRaw, watch } from 'vue'\n\nimport {\n componentCssVarsDarkDecls,\n componentCssVarsLightDecls,\n navSurfaceTone,\n resolveNavSidebarDecls,\n type NavSidebarVariant\n} from './component-css-vars'\nimport { hexRgbOnly, hexWithAlpha, isHexColor, mixColor } from './helper'\nimport type { Theme } from './type'\n\ntype RecursivePartial<T> = {\n [P in keyof T]?: T[P] extends object ? RecursivePartial<T[P]> : T[P]\n}\n\n/** 主题系列:浅色或深色。决定组件级 token 与 html[data-theme] */\nexport type ThemeSeries = 'light' | 'dark'\n\nexport interface UIThemeOptions {\n /** 主题变更时是否自动重渲染,默认 true */\n reactive?: boolean\n /** 主题所属系列,默认 'light' */\n series?: ThemeSeries\n}\n\nexport class UITheme {\n static themeID = 'ultra-ui-theme'\n\n private static adoptedSheet: CSSStyleSheet | null = null\n\n readonly theme: Theme\n\n /** 主题所属系列:浅色 / 深色 */\n series: ThemeSeries\n\n private readonly reactiveEnabled: boolean\n\n constructor(theme: Theme, options?: UIThemeOptions) {\n this.reactiveEnabled = options?.reactive !== false\n this.series = options?.series ?? 'light'\n this.theme = reactive(theme) as Theme\n if (this.reactiveEnabled) {\n watch(this.theme, () => this.render(), { deep: true })\n }\n }\n\n private renderBase(\n theme: Record<string, unknown>,\n themeRules: string[] = [],\n parentKey = '--u'\n ): string[] {\n Object.keys(theme).forEach((key) => {\n // nav 由 navSidebarDecls 按 variant + 覆盖项单独注入(须晚于组件级 token 才生效)\n if (parentKey === '--u' && key === 'nav') return\n const value = theme[key]\n const varKey = `${parentKey.startsWith('-') ? parentKey : str(parentKey).kebabCase()}-${str(key).kebabCase()}`\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n this.renderBase(value as Record<string, unknown>, themeRules, varKey)\n } else {\n if (value || value === 0) {\n const v = withUnit(value as number | string, 'px')\n if (v !== undefined) {\n themeRules.push(`${varKey}: ${v}`)\n }\n }\n }\n })\n\n return themeRules\n }\n\n private renderBorder(theme: Theme): string {\n const shorthandKeys = (Object.keys(theme.border) as Array<keyof typeof theme.border>).filter(\n (key) => key !== 'mutedColor'\n )\n const border = shorthandKeys.map((key) => `var(--u-border-${key})`).join(' ')\n\n return [\n `--u-border: ${border}`,\n `--u-border-muted: var(--u-border-muted-color) var(--u-border-width) var(--u-border-style)`\n ].join(';')\n }\n\n private renderTypeColor(theme: Theme): string {\n const { color } = theme\n\n const types = Object.keys(color)\n const rates = [1, 3, 5, 7, 9]\n\n return types\n .map((type) => {\n const colorValue = color[type as keyof typeof color]! as `#${string}`\n\n return rates\n .map((rate) => {\n const light = `--u-color-${type}-light-${rate}: ${mixColor(\n colorValue,\n '#fff',\n rate / 10\n )}`\n const dark = `--u-color-${type}-dark-${rate}: ${mixColor(\n colorValue,\n '#000',\n rate / 10\n )}`\n return `${light};${dark}`\n })\n .join(';')\n })\n .join(';')\n }\n\n private renderShadow(_theme: Theme): string {\n const shadow = ['x', 'y', 'blur', 'spread', 'color']\n .map((k) => `var(--u-shadow-${k})`)\n .join(' ')\n\n return `--u-shadow: ${shadow}`\n }\n\n private renderBGColorAlpha(theme: Theme): string {\n const { color } = theme.bg\n const alphas = [70]\n const lines: string[] = []\n for (const type of Object.keys(color)) {\n const value = color[type as keyof typeof color]\n // 非 hex 颜色(如 glass 主题的 rgba())无法推导 alpha token,跳过避免生成 NaN 声明\n if (typeof value !== 'string' || !isHexColor(value)) continue\n const hex = value as `#${string}`\n lines.push(`--u-bg-color-${type}-alpha: ${hex}aa`)\n for (const a of alphas) {\n lines.push(`--u-bg-color-${type}-a-${a}: ${hexWithAlpha(hex, a)}`)\n }\n }\n return lines.join(';')\n }\n\n /** 语义色 / 边框 / 阴影 / 文本色的 alpha token(替代 color-mix + transparent) */\n private renderAlphaTokens(theme: Theme): string {\n const alphas = [4, 5, 8, 10, 11, 16, 22, 28, 35, 40, 50, 52, 60, 70, 86]\n const lines: string[] = []\n\n for (const type of Object.keys(theme.color)) {\n const value = theme.color[type as keyof typeof theme.color]\n if (typeof value !== 'string' || !isHexColor(value)) continue\n const hex = value as `#${string}`\n for (const a of alphas) {\n lines.push(`--u-color-${type}-a-${a}: ${hexWithAlpha(hex, a)}`)\n }\n }\n\n const borderHex = theme.border.color as `#${string}`\n if (isHexColor(borderHex)) {\n for (const a of alphas) {\n lines.push(`--u-border-color-a-${a}: ${hexWithAlpha(borderHex, a)}`)\n }\n }\n\n const shadowHex = hexRgbOnly(theme.shadow.color)\n // 阴影色非 hex(如 rgba())时无法推导 alpha token,跳过避免生成 NaN 声明\n if (isHexColor(shadowHex)) {\n for (const a of alphas) {\n lines.push(`--u-shadow-color-a-${a}: ${hexWithAlpha(shadowHex, a)}`)\n }\n }\n\n const textColor = theme['text-color']\n for (const type of Object.keys(textColor)) {\n const value = textColor[type as keyof typeof textColor]\n if (typeof value === 'string' && isHexColor(value)) {\n const hex = value as `#${string}`\n for (const a of alphas) {\n lines.push(`--u-text-color-${type}-a-${a}: ${hexWithAlpha(hex, a)}`)\n }\n }\n }\n\n return lines.join(';')\n }\n\n /** 组件级两色混合 token(batch-edit / kbd) */\n private renderComponentMixTokens(theme: Theme): string {\n const hover = theme.bg.color.hover as `#${string}`\n const top = theme.bg.color.top as `#${string}`\n const black = theme.bg.color.black as `#${string}`\n const borderColor = theme.border.color as `#${string}`\n const shadowColor = hexRgbOnly(theme.shadow.color)\n\n // 依赖色含非 hex 值(如 glass 主题的 rgba())时整体跳过,避免生成 NaN 声明;\n // 组件侧 var() fallback 会接管,行为等同于此前的无效声明\n if (![hover, top, black, borderColor].every(isHexColor)) return ''\n\n const formHeaderBg = mixColor(top, hover, 0.04)\n\n const kbdInset = mixColor(top, black, 0.25)\n const kbdDropShadow = isHexColor(shadowColor)\n ? hexWithAlpha(shadowColor, 60)\n : 'rgba(0, 0, 0, 0.6)'\n\n const lines = [\n `--u-batch-edit-form-header-bg: ${formHeaderBg}`,\n `--u-kbd-inset-shadow: ${kbdInset}`,\n `--u-kbd-border-shadow: ${hexWithAlpha(borderColor, 50)}`,\n `--u-kbd-drop-shadow: ${kbdDropShadow}`\n ]\n\n return lines.join(';')\n }\n\n private renderBGFilter(theme: Theme): string {\n const { filter } = theme.bg\n const value = filter.blur === 'none' ? 'none' : `${filter.blur} ${filter.saturate}`\n return `--u-bg-filter: ${value}`\n }\n\n /** 主题变量声明列表,均为 `--u-` 前缀的 CSS 自定义属性 */\n themeToDeclarationList(theme: Theme): string[] {\n const raw = theme as unknown as Record<string, unknown>\n const lines: string[] = [...this.renderBase(raw)]\n const chunks = [\n this.renderTypeColor(theme),\n this.renderShadow(theme),\n this.renderBGColorAlpha(theme),\n this.renderAlphaTokens(theme),\n this.renderComponentMixTokens(theme),\n this.renderBGFilter(theme),\n this.renderBorder(theme)\n ]\n for (const c of chunks) {\n lines.push(\n ...c\n .split(';')\n .map((s) => s.trim())\n .filter(Boolean)\n )\n }\n return lines\n }\n\n private static declarationBlock(decls: string[]): string {\n return decls.join(';')\n }\n\n /** 主题的默认菜单变体(未声明时为 dark) */\n private navSidebarVariant(theme: Theme): NavSidebarVariant {\n return theme.nav?.variant === 'light' ? 'light' : 'dark'\n }\n\n /**\n * 主题 nav 覆盖声明:顶层字符串键对所有变体生效;\n * `nav.variants[variant]` 只对该变体生效,追加在最后(同规则后者生效)。\n */\n private navOverrideDecls(theme: Theme, variant: NavSidebarVariant): string[] {\n const nav = theme.nav ?? {}\n const toDecls = (record: Record<string, any> | undefined) =>\n Object.keys(record ?? {})\n .filter((key) => typeof record![key] === 'string' && record![key])\n .map((key) => `--u-nav-${str(key).kebabCase()}: ${record![key]}`)\n\n const topLevel: Record<string, any> = { ...nav }\n delete topLevel.variant\n delete topLevel.variants\n\n return [...toDecls(topLevel), ...toDecls(nav.variants?.[variant])]\n }\n\n /** 指定系列 + 变体的 nav 声明(内置 token + 主题覆盖),供 html 级与容器级注入共用 */\n private navSeriesDecls(theme: Theme, series: ThemeSeries, variant: NavSidebarVariant): string[] {\n return [...resolveNavSidebarDecls(series, variant), ...this.navOverrideDecls(theme, variant)]\n }\n\n /**\n * nav 侧栏外观声明:默认按主题 `nav.variant` 取内置深/浅侧栏 token,\n * 主题 `nav` 的其余键作为 `--u-nav-*` 覆盖追加在最后(同规则后者生效)。\n * @param variant 显式指定变体(容器级/预览取色用),不传取主题默认变体\n */\n navSidebarDecls(theme: Theme, variant?: NavSidebarVariant): string[] {\n return this.navSeriesDecls(theme, this.series, variant ?? this.navSidebarVariant(theme))\n }\n\n /**\n * 派生指定菜单变体的主题。变体专属外观由 `nav.variants` 声明,\n * 切换时不再需要手动展开 `navSidebarTokens` 覆盖预设个性色。\n */\n withNavVariant(variant: NavSidebarVariant): UITheme {\n return this.new({ nav: { variant } })\n }\n\n private static toVariableMap(decls: string[]): Map<string, string> {\n const map = new Map<string, string>()\n for (const decl of decls) {\n const index = decl.indexOf(':')\n if (index < 0) continue\n map.set(decl.slice(0, index).trim(), decl.slice(index + 1).trim())\n }\n return map\n }\n\n /** 把 token 值里的 `var(--u-*)` 递归解析成具体色值(供主题预览/取色) */\n private static resolveVarValue(value: string, ...maps: Array<Map<string, string>>): string {\n let resolved = value\n // token 引用链通常只有一层(nav → 语义 token),限制次数避免异常数据死循环\n for (let depth = 0; depth < 6 && resolved.includes('var(--u-'); depth += 1) {\n const next = resolved.replace(/var\\((--u-[\\w-]+)\\)/g, (raw, name: string) => {\n for (const map of maps) {\n const hit = map.get(name)\n if (hit !== undefined) return hit\n }\n return raw\n })\n if (next === resolved) break\n resolved = next\n }\n return resolved\n }\n\n /**\n * 解析当前主题某菜单变体的具体色值(键为去掉 `--u-nav-` 前缀的 token 名,\n * 如 `'bg-color'`、`'active-color'`、`'surface-hairline'`)。\n * 用于主题选择器预览等「主题未加载到 DOM 也要取色」的场景。\n */\n navSidebarColors(variant?: NavSidebarVariant): Record<string, string> {\n const raw = toRaw(this.theme) as Theme\n const target = variant ?? this.navSidebarVariant(raw)\n const themeVars = UITheme.toVariableMap(this.themeToDeclarationList(raw))\n const navVars = UITheme.toVariableMap(this.navSeriesDecls(raw, this.series, target))\n const colors: Record<string, string> = {}\n for (const [name, value] of navVars) {\n colors[name.replace(/^--u-nav-/, '')] = UITheme.resolveVarValue(value, themeVars, navVars)\n }\n return colors\n }\n\n private static removeExistingStyleTag(doc: Document): void {\n const el = doc.getElementById(UITheme.themeID)\n if (el?.parentNode) {\n el.parentNode.removeChild(el)\n }\n }\n\n private static applyGlobalCSS(css: string): void {\n const doc = typeof document !== 'undefined' ? document : undefined\n if (!doc) return\n\n const canAdopt =\n typeof CSSStyleSheet !== 'undefined' && 'adoptedStyleSheets' in Document.prototype\n\n if (canAdopt) {\n UITheme.removeExistingStyleTag(doc)\n if (!UITheme.adoptedSheet) {\n UITheme.adoptedSheet = new CSSStyleSheet()\n doc.adoptedStyleSheets = [...doc.adoptedStyleSheets, UITheme.adoptedSheet]\n }\n UITheme.adoptedSheet.replaceSync(css)\n } else {\n if (UITheme.adoptedSheet) {\n UITheme.adoptedSheet = null\n }\n let style = doc.getElementById(UITheme.themeID)\n if (!style) {\n style = doc.createElement('style')\n style.id = UITheme.themeID\n doc.head.appendChild(style)\n }\n style.textContent = css\n }\n }\n\n /**\n * 注入主题:全局 token + 与主题系列匹配的组件级 token + nav 侧栏外观,写入 html[data-theme];\n * 同时注入容器级菜单变体规则(`[data-nav-variant]`)与实际底色色调 `html[data-nav-surface]`。\n */\n render(): void {\n const componentDecls =\n this.series === 'dark' ? componentCssVarsDarkDecls : componentCssVarsLightDecls\n const raw = toRaw(this.theme)\n const activeVariant = this.navSidebarVariant(raw)\n const decls = [\n ...this.themeToDeclarationList(raw),\n ...componentDecls,\n ...this.navSeriesDecls(raw, this.series, activeVariant)\n ]\n const block = UITheme.declarationBlock(decls)\n // 容器级变体:同一主题下任意子树加 data-nav-variant 即可切换菜单深浅,无需重建主题\n const variantRules = (['light', 'dark'] as const).flatMap((series) =>\n (['dark', 'light'] as const).map((variant) => {\n const variantBlock = UITheme.declarationBlock(this.navSeriesDecls(raw, series, variant))\n return `html[data-theme=\"${series}\"] [data-nav-variant=\"${variant}\"] { ${variantBlock} }`\n })\n )\n UITheme.applyGlobalCSS([`html { ${block} }`, ...variantRules].join('\\n'))\n if (typeof document !== 'undefined') {\n document.documentElement.dataset.theme = this.series\n document.documentElement.dataset.navSurface = navSurfaceTone(this.series, activeVariant)\n }\n }\n\n new(customTheme: RecursivePartial<Theme> = {}, options?: { series?: ThemeSeries }): UITheme {\n function delEmpty(obj: Record<string, unknown>) {\n Object.keys(obj).forEach((key) => {\n const value = obj[key]\n if (isObj(value)) {\n return delEmpty(value as Record<string, unknown>)\n }\n if (!value && value !== 0) {\n delete obj[key]\n }\n })\n }\n\n delEmpty(customTheme as Record<string, unknown>)\n\n const base = JSON.parse(JSON.stringify(toRaw(this.theme))) as Record<string, any>\n\n function deepMerge(target: any, source: any) {\n if (typeof source !== 'object' || source === null) return\n Object.keys(source).forEach((key) => {\n const sourceVal = source[key]\n if (typeof sourceVal === 'object' && sourceVal !== null && !Array.isArray(sourceVal)) {\n if (typeof target[key] !== 'object' || target[key] === null) {\n target[key] = {}\n }\n deepMerge(target[key], sourceVal)\n } else {\n target[key] = sourceVal\n }\n })\n }\n\n deepMerge(base, customTheme)\n return new UITheme(base as Theme, {\n reactive: this.reactiveEnabled,\n series: options?.series ?? this.series\n })\n }\n}\n"],"mappings":";;;;;;AA4BA,IAAa,UAAb,MAAa,QAAQ;CACnB,OAAO,UAAU;CAEjB,OAAe,eAAqC;CAEpD;;CAGA;CAEA;CAEA,YAAY,OAAc,SAA0B;EAClD,KAAK,kBAAkB,SAAS,aAAa;EAC7C,KAAK,SAAS,SAAS,UAAU;EACjC,KAAK,QAAQ,SAAS,KAAK;EAC3B,IAAI,KAAK,iBACP,MAAM,KAAK,aAAa,KAAK,OAAO,GAAG,EAAE,MAAM,KAAK,CAAC;CAEzD;CAEA,WACE,OACA,aAAuB,CAAC,GACxB,YAAY,OACF;EACV,OAAO,KAAK,KAAK,CAAC,CAAC,SAAS,QAAQ;GAElC,IAAI,cAAc,SAAS,QAAQ,OAAO;GAC1C,MAAM,QAAQ,MAAM;GACpB,MAAM,SAAS,GAAG,UAAU,WAAW,GAAG,IAAI,YAAY,IAAI,SAAS,CAAC,CAAC,UAAU,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU;GAC3G,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK,GACrE,KAAK,WAAW,OAAkC,YAAY,MAAM;QAEpE,IAAI,SAAS,UAAU,GAAG;IACxB,MAAM,IAAI,SAAS,OAA0B,IAAI;IACjD,IAAI,MAAM,KAAA,GACR,WAAW,KAAK,GAAG,OAAO,IAAI,GAAG;GAErC;EAEJ,CAAC;EAED,OAAO;CACT;CAEA,aAAqB,OAAsB;EAMzC,OAAO,CACL,eANqB,OAAO,KAAK,MAAM,MAAM,CAAC,CAAsC,QACnF,QAAQ,QAAQ,YAEQ,CAAC,CAAC,KAAK,QAAQ,kBAAkB,IAAI,EAAE,CAAC,CAAC,KAAK,GAGnD,KACpB,2FACF,CAAC,CAAC,KAAK,GAAG;CACZ;CAEA,gBAAwB,OAAsB;EAC5C,MAAM,EAAE,UAAU;EAElB,MAAM,QAAQ,OAAO,KAAK,KAAK;EAC/B,MAAM,QAAQ;GAAC;GAAG;GAAG;GAAG;GAAG;EAAC;EAE5B,OAAO,MACJ,KAAK,SAAS;GACb,MAAM,aAAa,MAAM;GAEzB,OAAO,MACJ,KAAK,SAAS;IAWb,OAAO,GAAG,aAViB,KAAK,SAAS,KAAK,IAAI,SAChD,YACA,QACA,OAAO,EACT,IAMgB,GAAG,aALO,KAAK,QAAQ,KAAK,IAAI,SAC9C,YACA,QACA,OAAO,EACT;GAEF,CAAC,CAAC,CACD,KAAK,GAAG;EACb,CAAC,CAAC,CACD,KAAK,GAAG;CACb;CAEA,aAAqB,QAAuB;EAK1C,OAAO,eAJQ;GAAC;GAAK;GAAK;GAAQ;GAAU;EAAO,CAAC,CACjD,KAAK,MAAM,kBAAkB,EAAE,EAAE,CAAC,CAClC,KAAK,GAEmB;CAC7B;CAEA,mBAA2B,OAAsB;EAC/C,MAAM,EAAE,UAAU,MAAM;EACxB,MAAM,SAAS,CAAC,EAAE;EAClB,MAAM,QAAkB,CAAC;EACzB,KAAK,MAAM,QAAQ,OAAO,KAAK,KAAK,GAAG;GACrC,MAAM,QAAQ,MAAM;GAEpB,IAAI,OAAO,UAAU,YAAY,CAAC,WAAW,KAAK,GAAG;GACrD,MAAM,MAAM;GACZ,MAAM,KAAK,gBAAgB,KAAK,UAAU,IAAI,GAAG;GACjD,KAAK,MAAM,KAAK,QACd,MAAM,KAAK,gBAAgB,KAAK,KAAK,EAAE,IAAI,aAAa,KAAK,CAAC,GAAG;EAErE;EACA,OAAO,MAAM,KAAK,GAAG;CACvB;;CAGA,kBAA0B,OAAsB;EAC9C,MAAM,SAAS;GAAC;GAAG;GAAG;GAAG;GAAI;GAAI;GAAI;GAAI;GAAI;GAAI;GAAI;GAAI;GAAI;GAAI;GAAI;EAAE;EACvE,MAAM,QAAkB,CAAC;EAEzB,KAAK,MAAM,QAAQ,OAAO,KAAK,MAAM,KAAK,GAAG;GAC3C,MAAM,QAAQ,MAAM,MAAM;GAC1B,IAAI,OAAO,UAAU,YAAY,CAAC,WAAW,KAAK,GAAG;GACrD,MAAM,MAAM;GACZ,KAAK,MAAM,KAAK,QACd,MAAM,KAAK,aAAa,KAAK,KAAK,EAAE,IAAI,aAAa,KAAK,CAAC,GAAG;EAElE;EAEA,MAAM,YAAY,MAAM,OAAO;EAC/B,IAAI,WAAW,SAAS,GACtB,KAAK,MAAM,KAAK,QACd,MAAM,KAAK,sBAAsB,EAAE,IAAI,aAAa,WAAW,CAAC,GAAG;EAIvE,MAAM,YAAY,WAAW,MAAM,OAAO,KAAK;EAE/C,IAAI,WAAW,SAAS,GACtB,KAAK,MAAM,KAAK,QACd,MAAM,KAAK,sBAAsB,EAAE,IAAI,aAAa,WAAW,CAAC,GAAG;EAIvE,MAAM,YAAY,MAAM;EACxB,KAAK,MAAM,QAAQ,OAAO,KAAK,SAAS,GAAG;GACzC,MAAM,QAAQ,UAAU;GACxB,IAAI,OAAO,UAAU,YAAY,WAAW,KAAK,GAAG;IAClD,MAAM,MAAM;IACZ,KAAK,MAAM,KAAK,QACd,MAAM,KAAK,kBAAkB,KAAK,KAAK,EAAE,IAAI,aAAa,KAAK,CAAC,GAAG;GAEvE;EACF;EAEA,OAAO,MAAM,KAAK,GAAG;CACvB;;CAGA,yBAAiC,OAAsB;EACrD,MAAM,QAAQ,MAAM,GAAG,MAAM;EAC7B,MAAM,MAAM,MAAM,GAAG,MAAM;EAC3B,MAAM,QAAQ,MAAM,GAAG,MAAM;EAC7B,MAAM,cAAc,MAAM,OAAO;EACjC,MAAM,cAAc,WAAW,MAAM,OAAO,KAAK;EAIjD,IAAI,CAAC;GAAC;GAAO;GAAK;GAAO;EAAW,CAAC,CAAC,MAAM,UAAU,GAAG,OAAO;EAEhE,MAAM,eAAe,SAAS,KAAK,OAAO,GAAI;EAE9C,MAAM,WAAW,SAAS,KAAK,OAAO,GAAI;EAC1C,MAAM,gBAAgB,WAAW,WAAW,IACxC,aAAa,aAAa,EAAE,IAC5B;EASJ,OAAO;GANL,kCAAkC;GAClC,yBAAyB;GACzB,0BAA0B,aAAa,aAAa,EAAE;GACtD,wBAAwB;EAGf,CAAC,CAAC,KAAK,GAAG;CACvB;CAEA,eAAuB,OAAsB;EAC3C,MAAM,EAAE,WAAW,MAAM;EAEzB,OAAO,kBADO,OAAO,SAAS,SAAS,SAAS,GAAG,OAAO,KAAK,GAAG,OAAO;CAE3E;;CAGA,uBAAuB,OAAwB;EAC7C,MAAM,MAAM;EACZ,MAAM,QAAkB,CAAC,GAAG,KAAK,WAAW,GAAG,CAAC;EAChD,MAAM,SAAS;GACb,KAAK,gBAAgB,KAAK;GAC1B,KAAK,aAAa,KAAK;GACvB,KAAK,mBAAmB,KAAK;GAC7B,KAAK,kBAAkB,KAAK;GAC5B,KAAK,yBAAyB,KAAK;GACnC,KAAK,eAAe,KAAK;GACzB,KAAK,aAAa,KAAK;EACzB;EACA,KAAK,MAAM,KAAK,QACd,MAAM,KACJ,GAAG,EACA,MAAM,GAAG,CAAC,CACV,KAAK,MAAM,EAAE,KAAK,CAAC,CAAC,CACpB,OAAO,OAAO,CACnB;EAEF,OAAO;CACT;CAEA,OAAe,iBAAiB,OAAyB;EACvD,OAAO,MAAM,KAAK,GAAG;CACvB;;CAGA,kBAA0B,OAAiC;EACzD,OAAO,MAAM,KAAK,YAAY,UAAU,UAAU;CACpD;;;;;CAMA,iBAAyB,OAAc,SAAsC;EAC3E,MAAM,MAAM,MAAM,OAAO,CAAC;EAC1B,MAAM,WAAW,WACf,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,CACtB,QAAQ,QAAQ,OAAO,OAAQ,SAAS,YAAY,OAAQ,IAAI,CAAC,CACjE,KAAK,QAAQ,WAAW,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,IAAI,OAAQ,MAAM;EAEpE,MAAM,WAAgC,EAAE,GAAG,IAAI;EAC/C,OAAO,SAAS;EAChB,OAAO,SAAS;EAEhB,OAAO,CAAC,GAAG,QAAQ,QAAQ,GAAG,GAAG,QAAQ,IAAI,WAAW,QAAQ,CAAC;CACnE;;CAGA,eAAuB,OAAc,QAAqB,SAAsC;EAC9F,OAAO,CAAC,GAAG,uBAAuB,QAAQ,OAAO,GAAG,GAAG,KAAK,iBAAiB,OAAO,OAAO,CAAC;CAC9F;;;;;;CAOA,gBAAgB,OAAc,SAAuC;EACnE,OAAO,KAAK,eAAe,OAAO,KAAK,QAAQ,WAAW,KAAK,kBAAkB,KAAK,CAAC;CACzF;;;;;CAMA,eAAe,SAAqC;EAClD,OAAO,KAAK,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;CACtC;CAEA,OAAe,cAAc,OAAsC;EACjE,MAAM,sBAAM,IAAI,IAAoB;EACpC,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,QAAQ,KAAK,QAAQ,GAAG;GAC9B,IAAI,QAAQ,GAAG;GACf,IAAI,IAAI,KAAK,MAAM,GAAG,KAAK,CAAC,CAAC,KAAK,GAAG,KAAK,MAAM,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;EACnE;EACA,OAAO;CACT;;CAGA,OAAe,gBAAgB,OAAe,GAAG,MAA0C;EACzF,IAAI,WAAW;EAEf,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,SAAS,SAAS,UAAU,GAAG,SAAS,GAAG;GAC1E,MAAM,OAAO,SAAS,QAAQ,yBAAyB,KAAK,SAAiB;IAC3E,KAAK,MAAM,OAAO,MAAM;KACtB,MAAM,MAAM,IAAI,IAAI,IAAI;KACxB,IAAI,QAAQ,KAAA,GAAW,OAAO;IAChC;IACA,OAAO;GACT,CAAC;GACD,IAAI,SAAS,UAAU;GACvB,WAAW;EACb;EACA,OAAO;CACT;;;;;;CAOA,iBAAiB,SAAqD;EACpE,MAAM,MAAM,MAAM,KAAK,KAAK;EAC5B,MAAM,SAAS,WAAW,KAAK,kBAAkB,GAAG;EACpD,MAAM,YAAY,QAAQ,cAAc,KAAK,uBAAuB,GAAG,CAAC;EACxE,MAAM,UAAU,QAAQ,cAAc,KAAK,eAAe,KAAK,KAAK,QAAQ,MAAM,CAAC;EACnF,MAAM,SAAiC,CAAC;EACxC,KAAK,MAAM,CAAC,MAAM,UAAU,SAC1B,OAAO,KAAK,QAAQ,aAAa,EAAE,KAAK,QAAQ,gBAAgB,OAAO,WAAW,OAAO;EAE3F,OAAO;CACT;CAEA,OAAe,uBAAuB,KAAqB;EACzD,MAAM,KAAK,IAAI,eAAe,QAAQ,OAAO;EAC7C,IAAI,IAAI,YACN,GAAG,WAAW,YAAY,EAAE;CAEhC;CAEA,OAAe,eAAe,KAAmB;EAC/C,MAAM,MAAM,OAAO,aAAa,cAAc,WAAW,KAAA;EACzD,IAAI,CAAC,KAAK;EAKV,IAFE,OAAO,kBAAkB,eAAe,wBAAwB,SAAS,WAE7D;GACZ,QAAQ,uBAAuB,GAAG;GAClC,IAAI,CAAC,QAAQ,cAAc;IACzB,QAAQ,eAAe,IAAI,cAAc;IACzC,IAAI,qBAAqB,CAAC,GAAG,IAAI,oBAAoB,QAAQ,YAAY;GAC3E;GACA,QAAQ,aAAa,YAAY,GAAG;EACtC,OAAO;GACL,IAAI,QAAQ,cACV,QAAQ,eAAe;GAEzB,IAAI,QAAQ,IAAI,eAAe,QAAQ,OAAO;GAC9C,IAAI,CAAC,OAAO;IACV,QAAQ,IAAI,cAAc,OAAO;IACjC,MAAM,KAAK,QAAQ;IACnB,IAAI,KAAK,YAAY,KAAK;GAC5B;GACA,MAAM,cAAc;EACtB;CACF;;;;;CAMA,SAAe;EACb,MAAM,iBACJ,KAAK,WAAW,SAAS,4BAA4B;EACvD,MAAM,MAAM,MAAM,KAAK,KAAK;EAC5B,MAAM,gBAAgB,KAAK,kBAAkB,GAAG;EAChD,MAAM,QAAQ;GACZ,GAAG,KAAK,uBAAuB,GAAG;GAClC,GAAG;GACH,GAAG,KAAK,eAAe,KAAK,KAAK,QAAQ,aAAa;EACxD;EACA,MAAM,QAAQ,QAAQ,iBAAiB,KAAK;EAE5C,MAAM,eAAgB,CAAC,SAAS,MAAM,CAAC,CAAW,SAAS,WACxD,CAAC,QAAQ,OAAO,CAAC,CAAW,KAAK,YAAY;GAE5C,OAAO,oBAAoB,OAAO,wBAAwB,QAAQ,OAD7C,QAAQ,iBAAiB,KAAK,eAAe,KAAK,QAAQ,OAAO,CACF,EAAE;EACxF,CAAC,CACH;EACA,QAAQ,eAAe,CAAC,UAAU,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,KAAK,IAAI,CAAC;EACxE,IAAI,OAAO,aAAa,aAAa;GACnC,SAAS,gBAAgB,QAAQ,QAAQ,KAAK;GAC9C,SAAS,gBAAgB,QAAQ,aAAa,eAAe,KAAK,QAAQ,aAAa;EACzF;CACF;CAEA,IAAI,cAAuC,CAAC,GAAG,SAA6C;EAC1F,SAAS,SAAS,KAA8B;GAC9C,OAAO,KAAK,GAAG,CAAC,CAAC,SAAS,QAAQ;IAChC,MAAM,QAAQ,IAAI;IAClB,IAAI,MAAM,KAAK,GACb,OAAO,SAAS,KAAgC;IAElD,IAAI,CAAC,SAAS,UAAU,GACtB,OAAO,IAAI;GAEf,CAAC;EACH;EAEA,SAAS,WAAsC;EAE/C,MAAM,OAAO,KAAK,MAAM,KAAK,UAAU,MAAM,KAAK,KAAK,CAAC,CAAC;EAEzD,SAAS,UAAU,QAAa,QAAa;GAC3C,IAAI,OAAO,WAAW,YAAY,WAAW,MAAM;GACnD,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,QAAQ;IACnC,MAAM,YAAY,OAAO;IACzB,IAAI,OAAO,cAAc,YAAY,cAAc,QAAQ,CAAC,MAAM,QAAQ,SAAS,GAAG;KACpF,IAAI,OAAO,OAAO,SAAS,YAAY,OAAO,SAAS,MACrD,OAAO,OAAO,CAAC;KAEjB,UAAU,OAAO,MAAM,SAAS;IAClC,OACE,OAAO,OAAO;GAElB,CAAC;EACH;EAEA,UAAU,MAAM,WAAW;EAC3B,OAAO,IAAI,QAAQ,MAAe;GAChC,UAAU,KAAK;GACf,QAAQ,SAAS,UAAU,KAAK;EAClC,CAAC;CACH;AACF"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
import { describe, expect, it } from 'vite-plus/test'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
componentCssVarsDark,
|
|
7
|
+
componentCssVarsLight,
|
|
8
|
+
navSidebarTokens,
|
|
9
|
+
navSurfaceTokens,
|
|
10
|
+
navSurfaceTone
|
|
11
|
+
} from '../component-css-vars'
|
|
6
12
|
import {
|
|
7
13
|
ancientTheme,
|
|
8
14
|
darkTheme,
|
|
@@ -170,4 +176,97 @@ describe('UITheme', () => {
|
|
|
170
176
|
}
|
|
171
177
|
}
|
|
172
178
|
})
|
|
179
|
+
|
|
180
|
+
it('nav.variants overrides apply only to their own variant', () => {
|
|
181
|
+
const t = ancientTheme.new({ nav: { variants: { light: { 'bg-color': '#f1ede0' } } } })
|
|
182
|
+
// 深变体(预设自带松烟墨)不受 light 变体覆盖影响
|
|
183
|
+
const darkDecls = t.navSidebarDecls(t.theme)
|
|
184
|
+
expect(darkDecls).toContain('--u-nav-bg-color: #303c34')
|
|
185
|
+
expect(darkDecls).not.toContain('--u-nav-bg-color: #f1ede0')
|
|
186
|
+
// 浅变体使用 variants.light 覆盖
|
|
187
|
+
const lightDecls = t.navSidebarDecls(t.theme, 'light')
|
|
188
|
+
expect(lightDecls).toContain('--u-nav-bg-color: #f1ede0')
|
|
189
|
+
expect(lightDecls).not.toContain('--u-nav-bg-color: #303c34')
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
it('nav top-level overrides still apply to every variant and lose to variants', () => {
|
|
193
|
+
const t = lightTheme.new({
|
|
194
|
+
nav: { 'hover-bg': '#111111', variants: { light: { 'hover-bg': '#222222' } } }
|
|
195
|
+
})
|
|
196
|
+
expect(t.navSidebarDecls(t.theme)).toContain('--u-nav-hover-bg: #111111')
|
|
197
|
+
const lightDecls = t.navSidebarDecls(t.theme, 'light')
|
|
198
|
+
expect(lightDecls).toContain('--u-nav-hover-bg: #111111')
|
|
199
|
+
expect(lightDecls).toContain('--u-nav-hover-bg: #222222')
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
it('withNavVariant derives a theme with the requested menu variant', () => {
|
|
203
|
+
const lightVariant = lightTheme.withNavVariant('light')
|
|
204
|
+
const lightDecls = lightVariant.navSidebarDecls(lightVariant.theme)
|
|
205
|
+
expect(lightDecls).toContain('--u-nav-bg-color: var(--u-bg-color-middle)')
|
|
206
|
+
// 浅底选中文字用更深的 primary,保证 13px 正文对比度
|
|
207
|
+
expect(lightDecls).toContain('--u-nav-active-color: var(--u-color-primary-dark-3)')
|
|
208
|
+
// hero 默认 light 变体,派生 dark 变体后回落到深墨侧栏
|
|
209
|
+
const heroDark = heroTheme.withNavVariant('dark')
|
|
210
|
+
expect(heroDark.navSidebarDecls(heroDark.theme)).toContain(
|
|
211
|
+
'--u-nav-bg-color: var(--u-text-color-title)'
|
|
212
|
+
)
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
it('nav surface tone reflects the real surface luminance', () => {
|
|
216
|
+
expect(navSurfaceTone('light', 'dark')).toBe('dark')
|
|
217
|
+
expect(navSurfaceTone('light', 'light')).toBe('light')
|
|
218
|
+
expect(navSurfaceTone('dark', 'dark')).toBe('dark')
|
|
219
|
+
// 深色系列的 light 变体只是提亮一档,表面仍是深底
|
|
220
|
+
expect(navSurfaceTone('dark', 'light')).toBe('dark')
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
it('nav tokens carry surface decoration tokens matching the surface tone', () => {
|
|
224
|
+
expect(navSidebarTokens('light', 'dark')['--u-nav-surface-hairline']).toBe(
|
|
225
|
+
'rgba(255, 255, 255, 0.07)'
|
|
226
|
+
)
|
|
227
|
+
expect(navSidebarTokens('light', 'light')['--u-nav-surface-hairline']).toBe(
|
|
228
|
+
'var(--u-border-color)'
|
|
229
|
+
)
|
|
230
|
+
// dark 系列的 light 变体表面仍是深底,装饰沿用深底那套
|
|
231
|
+
expect(navSidebarTokens('dark', 'light')['--u-nav-surface-hairline']).toBe(
|
|
232
|
+
'rgba(255, 255, 255, 0.07)'
|
|
233
|
+
)
|
|
234
|
+
expect(navSurfaceTokens('light', 'light')['--u-nav-surface-accent']).toBe(
|
|
235
|
+
'var(--u-color-primary)'
|
|
236
|
+
)
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
it('render emits container-level variant rules and html surface tone', () => {
|
|
240
|
+
if (typeof document === 'undefined') return
|
|
241
|
+
lightTheme.render()
|
|
242
|
+
const adopted = [...document.adoptedStyleSheets]
|
|
243
|
+
.flatMap((sheet) => sheet.cssRules.map((rule) => rule.cssText))
|
|
244
|
+
.join('\n')
|
|
245
|
+
const fallback = document.getElementById('ultra-ui-theme')?.textContent ?? ''
|
|
246
|
+
const css = adopted || fallback
|
|
247
|
+
expect(css).toContain('html[data-theme="light"] [data-nav-variant="dark"]')
|
|
248
|
+
expect(css).toContain('html[data-theme="dark"] [data-nav-variant="light"]')
|
|
249
|
+
// lightTheme 默认 dark 菜单:html 级实际底色色调为深底
|
|
250
|
+
expect(document.documentElement.dataset.navSurface).toBe('dark')
|
|
251
|
+
darkTheme.render()
|
|
252
|
+
expect(document.documentElement.dataset.navSurface).toBe('dark')
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
it('navSidebarColors resolves concrete colors for theme previews', () => {
|
|
256
|
+
const lightColors = lightTheme.navSidebarColors()
|
|
257
|
+
expect(lightColors['bg-color']).toBe('#18181b')
|
|
258
|
+
expect(lightColors['color']).toBe('rgba(255, 255, 255, 0.72)')
|
|
259
|
+
expect(lightColors['surface-hairline']).toBe('rgba(255, 255, 255, 0.07)')
|
|
260
|
+
|
|
261
|
+
const lightMenu = lightTheme.navSidebarColors('light')
|
|
262
|
+
expect(lightMenu['bg-color']).toBe('#fafafa')
|
|
263
|
+
expect(lightMenu['color']).toBe('#18181b')
|
|
264
|
+
expect(lightMenu['active-color']).toMatch(/^#[0-9a-f]{6}$/i)
|
|
265
|
+
|
|
266
|
+
// 预设个性侧栏色按变体隔离
|
|
267
|
+
expect(ancientTheme.navSidebarColors()['bg-color']).toBe('#303c34')
|
|
268
|
+
expect(ancientTheme.navSidebarColors('light')['bg-color']).toBe('#f7f4ea')
|
|
269
|
+
expect(heroTheme.navSidebarColors()['bg-color']).toBe('#fafafa')
|
|
270
|
+
expect(heroTheme.navSidebarColors('dark')['bg-color']).toBe('#11181C')
|
|
271
|
+
})
|
|
173
272
|
})
|
|
@@ -236,10 +236,68 @@ export const componentCssVarsDarkDecls: string[] = recordToDeclList(componentCss
|
|
|
236
236
|
|
|
237
237
|
// ─── Nav 侧栏外观:深/浅变体 × 明/暗主题系列 ───
|
|
238
238
|
// 由 UITheme 按主题 `nav.variant`(默认 dark)选择注入,主题 `nav` 的其余键可逐项覆盖。
|
|
239
|
+
// 同时注入实际底色色调(surface tone)与一组 `--u-nav-surface-*` 装饰 token:
|
|
240
|
+
// 深色系列的任何变体、浅色系列的 dark 变体都是深底,应用壳绘制侧栏容器
|
|
241
|
+
// (叠层渐变、分隔线、chip、品牌标记环、选中态、滚动条)可直接消费,无需写 [data-theme] 分支。
|
|
239
242
|
|
|
240
243
|
/** 侧栏外观变体:dark 深底浅字 / light 浅底深字 */
|
|
241
244
|
export type NavSidebarVariant = 'dark' | 'light'
|
|
242
245
|
|
|
246
|
+
/** 侧栏实际底色色调:dark 深底 / light 浅底 */
|
|
247
|
+
export type NavSurfaceTone = 'dark' | 'light'
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* 某主题系列 + 菜单变体下侧栏的实际底色色调。
|
|
251
|
+
* 深色系列主题的两个变体都是深底(light 变体只是比内容区提亮一档)。
|
|
252
|
+
*/
|
|
253
|
+
export function navSurfaceTone(
|
|
254
|
+
series: 'light' | 'dark',
|
|
255
|
+
variant: NavSidebarVariant
|
|
256
|
+
): NavSurfaceTone {
|
|
257
|
+
return series === 'dark' || variant === 'dark' ? 'dark' : 'light'
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** 深底侧栏的表面装饰 token */
|
|
261
|
+
const navSurfaceDarkTone: Record<string, string> = {
|
|
262
|
+
'--u-nav-surface-overlay': `radial-gradient(120% 70% at 0% 0%, ${T('color', 'primary', 'a', '16')}, transparent 62%), linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(0, 0, 0, 0.3))`,
|
|
263
|
+
'--u-nav-surface-hairline': 'rgba(255, 255, 255, 0.07)',
|
|
264
|
+
'--u-nav-surface-chip-bg': 'rgba(255, 255, 255, 0.055)',
|
|
265
|
+
'--u-nav-surface-chip-border': 'rgba(255, 255, 255, 0.08)',
|
|
266
|
+
'--u-nav-surface-chip-hover-bg': 'rgba(255, 255, 255, 0.09)',
|
|
267
|
+
'--u-nav-surface-mark-ring': 'rgba(255, 255, 255, 0.14)',
|
|
268
|
+
'--u-nav-surface-active-gradient': `linear-gradient(90deg, ${T('color', 'primary', 'a', '35')}, ${T('color', 'primary', 'a', '5')})`,
|
|
269
|
+
'--u-nav-surface-active-ring': T('color', 'primary', 'a', '16'),
|
|
270
|
+
'--u-nav-surface-accent': T('color', 'primary', 'light', '5'),
|
|
271
|
+
'--u-nav-surface-scrollbar': 'rgba(255, 255, 255, 0.22)',
|
|
272
|
+
'--u-nav-surface-scrollbar-hover': 'rgba(255, 255, 255, 0.4)'
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/** 浅底侧栏的表面装饰 token */
|
|
276
|
+
const navSurfaceLightTone: Record<string, string> = {
|
|
277
|
+
'--u-nav-surface-overlay': `radial-gradient(120% 70% at 0% 0%, ${T('color', 'primary', 'a', '8')}, transparent 62%), linear-gradient(180deg, rgba(255, 255, 255, 0.45), rgba(0, 0, 0, 0.02))`,
|
|
278
|
+
'--u-nav-surface-hairline': T('border', 'color'),
|
|
279
|
+
'--u-nav-surface-chip-bg': 'rgba(15, 23, 42, 0.04)',
|
|
280
|
+
'--u-nav-surface-chip-border': T('border', 'color'),
|
|
281
|
+
'--u-nav-surface-chip-hover-bg': 'rgba(15, 23, 42, 0.07)',
|
|
282
|
+
'--u-nav-surface-mark-ring': 'rgba(15, 23, 42, 0.1)',
|
|
283
|
+
'--u-nav-surface-active-gradient': `linear-gradient(90deg, ${T('color', 'primary', 'a', '16')}, ${T('color', 'primary', 'a', '4')})`,
|
|
284
|
+
'--u-nav-surface-active-ring': T('color', 'primary', 'a', '8'),
|
|
285
|
+
'--u-nav-surface-accent': T('color', 'primary'),
|
|
286
|
+
'--u-nav-surface-scrollbar': T('text-color', 'assist', 'a', '40'),
|
|
287
|
+
'--u-nav-surface-scrollbar-hover': T('text-color', 'assist', 'a', '60')
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** 给内置外观 token 补上与其实际底色色调匹配的表面装饰 token */
|
|
291
|
+
function withNavSurface(
|
|
292
|
+
appearance: Record<string, string>,
|
|
293
|
+
series: 'light' | 'dark',
|
|
294
|
+
variant: NavSidebarVariant
|
|
295
|
+
): Record<string, string> {
|
|
296
|
+
const surface =
|
|
297
|
+
navSurfaceTone(series, variant) === 'dark' ? navSurfaceDarkTone : navSurfaceLightTone
|
|
298
|
+
return { ...appearance, ...surface }
|
|
299
|
+
}
|
|
300
|
+
|
|
243
301
|
/** 深侧栏 · 浅色主题下:深底(text-color.title)+ 浅前景,与浅色内容区拉开区分度 */
|
|
244
302
|
const navSidebarDarkInLight: Record<string, string> = {
|
|
245
303
|
'--u-nav-bg-color': T('text-color', 'title'),
|
|
@@ -254,14 +312,14 @@ const navSidebarDarkInLight: Record<string, string> = {
|
|
|
254
312
|
'--u-nav-rail-bg': 'rgba(0, 0, 0, 0.2)'
|
|
255
313
|
}
|
|
256
314
|
|
|
257
|
-
/** 浅侧栏 · 浅色主题下:比内容区 top 低一档的浅底 +
|
|
315
|
+
/** 浅侧栏 · 浅色主题下:比内容区 top 低一档的浅底 + 深前景;选中文字加深,保证 13px 正文的对比度 */
|
|
258
316
|
const navSidebarLightInLight: Record<string, string> = {
|
|
259
317
|
'--u-nav-bg-color': T('bg-color', 'middle'),
|
|
260
318
|
'--u-nav-color': T('text-color', 'title'),
|
|
261
319
|
'--u-nav-hover-bg': T('text-color', 'title', 'a', '8'),
|
|
262
320
|
'--u-nav-hover-color': T('text-color', 'title'),
|
|
263
321
|
'--u-nav-active-bg': T('color', 'primary', 'a', '10'),
|
|
264
|
-
'--u-nav-active-color': T('color', 'primary', 'dark', '
|
|
322
|
+
'--u-nav-active-color': T('color', 'primary', 'dark', '3'),
|
|
265
323
|
'--u-nav-strong-color': T('text-color', 'title'),
|
|
266
324
|
'--u-nav-second-color': T('text-color', 'second'),
|
|
267
325
|
'--u-nav-sub-border-color': T('border', 'color', 'a', '52'),
|
|
@@ -282,14 +340,14 @@ const navSidebarDarkInDark: Record<string, string> = {
|
|
|
282
340
|
'--u-nav-rail-bg': T('bg-color', 'bottom')
|
|
283
341
|
}
|
|
284
342
|
|
|
285
|
-
/** 浅侧栏 ·
|
|
343
|
+
/** 浅侧栏 · 深色主题下:提亮侧栏(与深色内容区反向对比);表面仍是深底,选中文字用白色保证对比度 */
|
|
286
344
|
const navSidebarLightInDark: Record<string, string> = {
|
|
287
345
|
'--u-nav-bg-color': T('bg-color', 'top'),
|
|
288
346
|
'--u-nav-color': T('text-color', 'title'),
|
|
289
347
|
'--u-nav-hover-bg': T('text-color', 'title', 'a', '8'),
|
|
290
348
|
'--u-nav-hover-color': T('text-color', 'title'),
|
|
291
349
|
'--u-nav-active-bg': T('color', 'primary', 'a', '22'),
|
|
292
|
-
'--u-nav-active-color': T('color', '
|
|
350
|
+
'--u-nav-active-color': T('text-color', 'white'),
|
|
293
351
|
'--u-nav-strong-color': T('text-color', 'title'),
|
|
294
352
|
'--u-nav-second-color': T('text-color', 'second'),
|
|
295
353
|
'--u-nav-sub-border-color': T('border', 'color', 'a', '52'),
|
|
@@ -300,11 +358,17 @@ const navSidebarCssVars: Record<
|
|
|
300
358
|
'light' | 'dark',
|
|
301
359
|
Record<NavSidebarVariant, Record<string, string>>
|
|
302
360
|
> = {
|
|
303
|
-
light: {
|
|
304
|
-
|
|
361
|
+
light: {
|
|
362
|
+
dark: withNavSurface(navSidebarDarkInLight, 'light', 'dark'),
|
|
363
|
+
light: withNavSurface(navSidebarLightInLight, 'light', 'light')
|
|
364
|
+
},
|
|
365
|
+
dark: {
|
|
366
|
+
dark: withNavSurface(navSidebarDarkInDark, 'dark', 'dark'),
|
|
367
|
+
light: withNavSurface(navSidebarLightInDark, 'dark', 'light')
|
|
368
|
+
}
|
|
305
369
|
}
|
|
306
370
|
|
|
307
|
-
/** 某主题系列 + 侧栏变体下的 nav
|
|
371
|
+
/** 某主题系列 + 侧栏变体下的 nav token(外观 + 表面装饰,键为 `--u-nav-*`) */
|
|
308
372
|
export function navSidebarTokens(
|
|
309
373
|
series: 'light' | 'dark',
|
|
310
374
|
variant: NavSidebarVariant
|
|
@@ -312,7 +376,17 @@ export function navSidebarTokens(
|
|
|
312
376
|
return { ...navSidebarCssVars[series][variant] }
|
|
313
377
|
}
|
|
314
378
|
|
|
315
|
-
/**
|
|
379
|
+
/** 某主题系列 + 侧栏变体下的 nav 表面装饰 token(键为 `--u-nav-surface-*`) */
|
|
380
|
+
export function navSurfaceTokens(
|
|
381
|
+
series: 'light' | 'dark',
|
|
382
|
+
variant: NavSidebarVariant
|
|
383
|
+
): Record<string, string> {
|
|
384
|
+
const surface =
|
|
385
|
+
navSurfaceTone(series, variant) === 'dark' ? navSurfaceDarkTone : navSurfaceLightTone
|
|
386
|
+
return { ...surface }
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/** 解析某主题系列 + 侧栏变体下的 nav token 声明列表 */
|
|
316
390
|
export function resolveNavSidebarDecls(
|
|
317
391
|
series: 'light' | 'dark',
|
|
318
392
|
variant: NavSidebarVariant
|
|
@@ -25,7 +25,7 @@ export const ancientTheme = lightTheme.new({
|
|
|
25
25
|
radius: { small: 4, default: 8, large: 12 },
|
|
26
26
|
shadow: { color: 'rgba(64, 54, 32, 0.14)', x: 0, y: 4, blur: 16, spread: -2 },
|
|
27
27
|
nav: {
|
|
28
|
-
//
|
|
29
|
-
'bg-color': mixColor('#2b2a26', '#3d6b58', 0.28)
|
|
28
|
+
// 松烟墨侧栏(深变体):黛墨 + 松烟绿调和;浅变体回落到主题宣纸底(bg middle)
|
|
29
|
+
variants: { dark: { 'bg-color': mixColor('#2b2a26', '#3d6b58', 0.28) } }
|
|
30
30
|
}
|
|
31
31
|
})
|
|
@@ -34,7 +34,7 @@ export const oceanTheme = lightTheme.new({
|
|
|
34
34
|
},
|
|
35
35
|
transition: { fast: '0.12s', ease: 'cubic-bezier(0.22, 1, 0.36, 1)' },
|
|
36
36
|
nav: {
|
|
37
|
-
//
|
|
38
|
-
'bg-color': mixColor('#16302e', '#0d9488', 0.25)
|
|
37
|
+
// 深海礁侧栏(深变体):深礁 + 松石青调和;浅变体回落到主题雾白底(bg middle)
|
|
38
|
+
variants: { dark: { 'bg-color': mixColor('#16302e', '#0d9488', 0.25) } }
|
|
39
39
|
}
|
|
40
40
|
})
|
|
@@ -36,7 +36,7 @@ export const sakuraTheme = lightTheme.new({
|
|
|
36
36
|
},
|
|
37
37
|
transition: { easeOut: 'cubic-bezier(0.34, 1.56, 0.64, 1)' },
|
|
38
38
|
nav: {
|
|
39
|
-
//
|
|
40
|
-
'bg-color': mixColor('#43272f', '#e64980', 0.22)
|
|
39
|
+
// 深酒红侧栏(深变体):樱墨 + 樱粉调和;浅变体回落到主题樱粉底(bg middle)
|
|
40
|
+
variants: { dark: { 'bg-color': mixColor('#43272f', '#e64980', 0.22) } }
|
|
41
41
|
}
|
|
42
42
|
})
|
package/src/theme/type.ts
CHANGED
|
@@ -182,12 +182,18 @@ export type Theme = {
|
|
|
182
182
|
}
|
|
183
183
|
/**
|
|
184
184
|
* 侧栏导航(nav / dual-nav / group-nav)组件级变量。
|
|
185
|
-
* variant
|
|
186
|
-
* (如 `'bg-color'` → `--u-nav-bg-color
|
|
185
|
+
* `variant` 选择默认深/浅侧栏外观;顶层其余字符串键对所有变体生效并覆盖同名
|
|
186
|
+
* `--u-nav-*` token(如 `'bg-color'` → `--u-nav-bg-color`);
|
|
187
|
+
* `variants` 可为两个变体分别定制外观,只在该变体生效且优先级最高。
|
|
187
188
|
*/
|
|
188
189
|
nav?: {
|
|
189
|
-
/**
|
|
190
|
+
/** 侧栏默认外观:dark 深底浅字 / light 浅底深字,默认 dark */
|
|
190
191
|
variant?: 'dark' | 'light'
|
|
192
|
+
/**
|
|
193
|
+
* 按变体定制的外观覆盖,键同 nav 顶层(如 `'bg-color'`)。
|
|
194
|
+
* 未声明的变体回落到内置「主题系列 × 变体」token。
|
|
195
|
+
*/
|
|
196
|
+
variants?: Partial<Record<'dark' | 'light', Record<string, string>>>
|
|
191
197
|
[key: string]: any
|
|
192
198
|
}
|
|
193
199
|
/** 折叠面板组件级变量 */
|
package/src/theme/ui-theme.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { reactive, toRaw, watch } from 'vue'
|
|
|
5
5
|
import {
|
|
6
6
|
componentCssVarsDarkDecls,
|
|
7
7
|
componentCssVarsLightDecls,
|
|
8
|
+
navSurfaceTone,
|
|
8
9
|
resolveNavSidebarDecls,
|
|
9
10
|
type NavSidebarVariant
|
|
10
11
|
} from './component-css-vars'
|
|
@@ -243,18 +244,94 @@ export class UITheme {
|
|
|
243
244
|
return decls.join(';')
|
|
244
245
|
}
|
|
245
246
|
|
|
247
|
+
/** 主题的默认菜单变体(未声明时为 dark) */
|
|
248
|
+
private navSidebarVariant(theme: Theme): NavSidebarVariant {
|
|
249
|
+
return theme.nav?.variant === 'light' ? 'light' : 'dark'
|
|
250
|
+
}
|
|
251
|
+
|
|
246
252
|
/**
|
|
247
|
-
*
|
|
248
|
-
*
|
|
253
|
+
* 主题 nav 覆盖声明:顶层字符串键对所有变体生效;
|
|
254
|
+
* `nav.variants[variant]` 只对该变体生效,追加在最后(同规则后者生效)。
|
|
249
255
|
*/
|
|
250
|
-
|
|
256
|
+
private navOverrideDecls(theme: Theme, variant: NavSidebarVariant): string[] {
|
|
251
257
|
const nav = theme.nav ?? {}
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
+
const toDecls = (record: Record<string, any> | undefined) =>
|
|
259
|
+
Object.keys(record ?? {})
|
|
260
|
+
.filter((key) => typeof record![key] === 'string' && record![key])
|
|
261
|
+
.map((key) => `--u-nav-${str(key).kebabCase()}: ${record![key]}`)
|
|
262
|
+
|
|
263
|
+
const topLevel: Record<string, any> = { ...nav }
|
|
264
|
+
delete topLevel.variant
|
|
265
|
+
delete topLevel.variants
|
|
266
|
+
|
|
267
|
+
return [...toDecls(topLevel), ...toDecls(nav.variants?.[variant])]
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** 指定系列 + 变体的 nav 声明(内置 token + 主题覆盖),供 html 级与容器级注入共用 */
|
|
271
|
+
private navSeriesDecls(theme: Theme, series: ThemeSeries, variant: NavSidebarVariant): string[] {
|
|
272
|
+
return [...resolveNavSidebarDecls(series, variant), ...this.navOverrideDecls(theme, variant)]
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* nav 侧栏外观声明:默认按主题 `nav.variant` 取内置深/浅侧栏 token,
|
|
277
|
+
* 主题 `nav` 的其余键作为 `--u-nav-*` 覆盖追加在最后(同规则后者生效)。
|
|
278
|
+
* @param variant 显式指定变体(容器级/预览取色用),不传取主题默认变体
|
|
279
|
+
*/
|
|
280
|
+
navSidebarDecls(theme: Theme, variant?: NavSidebarVariant): string[] {
|
|
281
|
+
return this.navSeriesDecls(theme, this.series, variant ?? this.navSidebarVariant(theme))
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* 派生指定菜单变体的主题。变体专属外观由 `nav.variants` 声明,
|
|
286
|
+
* 切换时不再需要手动展开 `navSidebarTokens` 覆盖预设个性色。
|
|
287
|
+
*/
|
|
288
|
+
withNavVariant(variant: NavSidebarVariant): UITheme {
|
|
289
|
+
return this.new({ nav: { variant } })
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
private static toVariableMap(decls: string[]): Map<string, string> {
|
|
293
|
+
const map = new Map<string, string>()
|
|
294
|
+
for (const decl of decls) {
|
|
295
|
+
const index = decl.indexOf(':')
|
|
296
|
+
if (index < 0) continue
|
|
297
|
+
map.set(decl.slice(0, index).trim(), decl.slice(index + 1).trim())
|
|
298
|
+
}
|
|
299
|
+
return map
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/** 把 token 值里的 `var(--u-*)` 递归解析成具体色值(供主题预览/取色) */
|
|
303
|
+
private static resolveVarValue(value: string, ...maps: Array<Map<string, string>>): string {
|
|
304
|
+
let resolved = value
|
|
305
|
+
// token 引用链通常只有一层(nav → 语义 token),限制次数避免异常数据死循环
|
|
306
|
+
for (let depth = 0; depth < 6 && resolved.includes('var(--u-'); depth += 1) {
|
|
307
|
+
const next = resolved.replace(/var\((--u-[\w-]+)\)/g, (raw, name: string) => {
|
|
308
|
+
for (const map of maps) {
|
|
309
|
+
const hit = map.get(name)
|
|
310
|
+
if (hit !== undefined) return hit
|
|
311
|
+
}
|
|
312
|
+
return raw
|
|
313
|
+
})
|
|
314
|
+
if (next === resolved) break
|
|
315
|
+
resolved = next
|
|
316
|
+
}
|
|
317
|
+
return resolved
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* 解析当前主题某菜单变体的具体色值(键为去掉 `--u-nav-` 前缀的 token 名,
|
|
322
|
+
* 如 `'bg-color'`、`'active-color'`、`'surface-hairline'`)。
|
|
323
|
+
* 用于主题选择器预览等「主题未加载到 DOM 也要取色」的场景。
|
|
324
|
+
*/
|
|
325
|
+
navSidebarColors(variant?: NavSidebarVariant): Record<string, string> {
|
|
326
|
+
const raw = toRaw(this.theme) as Theme
|
|
327
|
+
const target = variant ?? this.navSidebarVariant(raw)
|
|
328
|
+
const themeVars = UITheme.toVariableMap(this.themeToDeclarationList(raw))
|
|
329
|
+
const navVars = UITheme.toVariableMap(this.navSeriesDecls(raw, this.series, target))
|
|
330
|
+
const colors: Record<string, string> = {}
|
|
331
|
+
for (const [name, value] of navVars) {
|
|
332
|
+
colors[name.replace(/^--u-nav-/, '')] = UITheme.resolveVarValue(value, themeVars, navVars)
|
|
333
|
+
}
|
|
334
|
+
return colors
|
|
258
335
|
}
|
|
259
336
|
|
|
260
337
|
private static removeExistingStyleTag(doc: Document): void {
|
|
@@ -292,21 +369,32 @@ export class UITheme {
|
|
|
292
369
|
}
|
|
293
370
|
}
|
|
294
371
|
|
|
295
|
-
/**
|
|
372
|
+
/**
|
|
373
|
+
* 注入主题:全局 token + 与主题系列匹配的组件级 token + nav 侧栏外观,写入 html[data-theme];
|
|
374
|
+
* 同时注入容器级菜单变体规则(`[data-nav-variant]`)与实际底色色调 `html[data-nav-surface]`。
|
|
375
|
+
*/
|
|
296
376
|
render(): void {
|
|
297
377
|
const componentDecls =
|
|
298
378
|
this.series === 'dark' ? componentCssVarsDarkDecls : componentCssVarsLightDecls
|
|
299
379
|
const raw = toRaw(this.theme)
|
|
380
|
+
const activeVariant = this.navSidebarVariant(raw)
|
|
300
381
|
const decls = [
|
|
301
382
|
...this.themeToDeclarationList(raw),
|
|
302
383
|
...componentDecls,
|
|
303
|
-
...this.
|
|
384
|
+
...this.navSeriesDecls(raw, this.series, activeVariant)
|
|
304
385
|
]
|
|
305
386
|
const block = UITheme.declarationBlock(decls)
|
|
306
|
-
|
|
307
|
-
|
|
387
|
+
// 容器级变体:同一主题下任意子树加 data-nav-variant 即可切换菜单深浅,无需重建主题
|
|
388
|
+
const variantRules = (['light', 'dark'] as const).flatMap((series) =>
|
|
389
|
+
(['dark', 'light'] as const).map((variant) => {
|
|
390
|
+
const variantBlock = UITheme.declarationBlock(this.navSeriesDecls(raw, series, variant))
|
|
391
|
+
return `html[data-theme="${series}"] [data-nav-variant="${variant}"] { ${variantBlock} }`
|
|
392
|
+
})
|
|
393
|
+
)
|
|
394
|
+
UITheme.applyGlobalCSS([`html { ${block} }`, ...variantRules].join('\n'))
|
|
308
395
|
if (typeof document !== 'undefined') {
|
|
309
396
|
document.documentElement.dataset.theme = this.series
|
|
397
|
+
document.documentElement.dataset.navSurface = navSurfaceTone(this.series, activeVariant)
|
|
310
398
|
}
|
|
311
399
|
}
|
|
312
400
|
|