@veltra/styles 1.0.7 → 1.0.9
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 +16 -0
- package/dist/theme/component-css-vars.js +77 -0
- package/dist/theme/component-css-vars.js.map +1 -0
- package/dist/theme/index.d.ts +2 -1
- package/dist/theme/index.js +2 -1
- package/dist/theme/type.d.ts +1 -1
- package/dist/theme/ui-theme.js +4 -3
- package/dist/theme/ui-theme.js.map +1 -1
- package/package.json +5 -10
- package/src/theme/component-css-vars.ts +80 -0
- package/src/theme/index.ts +7 -0
- package/src/theme/type.ts +1 -1
- package/src/theme/ui-theme.ts +10 -3
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/theme/component-css-vars.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* 桌面组件级 `--u-*` token,与内置主题一起在 `UITheme.injectBuiltInThemes` 中注入 `html`。
|
|
4
|
+
* 修改此处即可在 TS 侧统一调整组件外观,无需在各组件 `style.scss` 重复声明。
|
|
5
|
+
*/
|
|
6
|
+
/** 与 SCSS `fn.use-var($basename, $nodes...)` 输出一致 */
|
|
7
|
+
declare function themeTokenVar(basename: string, ...nodes: Array<string | number>): string;
|
|
8
|
+
/** 亮色(及与暗色相同的尺寸类)下组件 token */
|
|
9
|
+
declare const componentCssVarsLight: Record<string, string>;
|
|
10
|
+
/** 暗色下组件 token(含与亮色相同的尺寸项,保证暗色 html 块自洽) */
|
|
11
|
+
declare const componentCssVarsDark: Record<string, string>;
|
|
12
|
+
declare const componentCssVarsLightDecls: string[];
|
|
13
|
+
declare const componentCssVarsDarkDecls: string[];
|
|
14
|
+
//#endregion
|
|
15
|
+
export { componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, themeTokenVar };
|
|
16
|
+
//# sourceMappingURL=component-css-vars.d.ts.map
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
//#region src/theme/component-css-vars.ts
|
|
2
|
+
/**
|
|
3
|
+
* 桌面组件级 `--u-*` token,与内置主题一起在 `UITheme.injectBuiltInThemes` 中注入 `html`。
|
|
4
|
+
* 修改此处即可在 TS 侧统一调整组件外观,无需在各组件 `style.scss` 重复声明。
|
|
5
|
+
*/
|
|
6
|
+
/** 与 SCSS `fn.use-var($basename, $nodes...)` 输出一致 */
|
|
7
|
+
function themeTokenVar(basename, ...nodes) {
|
|
8
|
+
return `var(--u-${basename}${nodes.length ? `-${nodes.map(String).join("-")}` : ""})`;
|
|
9
|
+
}
|
|
10
|
+
const T = themeTokenVar;
|
|
11
|
+
/** 亮色(及与暗色相同的尺寸类)下组件 token */
|
|
12
|
+
const componentCssVarsLight = {
|
|
13
|
+
"--u-table-border-color": "#e9e9e9",
|
|
14
|
+
"--u-table-header-bg": "#f4f5f7",
|
|
15
|
+
"--u-table-header-color": T("text-color", "title"),
|
|
16
|
+
"--u-table-stripe-bg": "#f8fafc",
|
|
17
|
+
"--u-table-stripe-color": "inherit",
|
|
18
|
+
"--u-table-hover-bg": T("bg-color", "hover"),
|
|
19
|
+
"--u-table-hover-color": "inherit",
|
|
20
|
+
"--u-table-current-bg": T("bg-color", "hover"),
|
|
21
|
+
"--u-table-current-color": "inherit",
|
|
22
|
+
"--u-table-checked-bg": T("color", "primary", "light-9"),
|
|
23
|
+
"--u-table-checked-color": "inherit",
|
|
24
|
+
"--u-menu-color": "#0f172a",
|
|
25
|
+
"--u-menu-hover-bg": "rgba(148, 163, 184, 0.12)",
|
|
26
|
+
"--u-menu-hover-color": T("text-color", "title"),
|
|
27
|
+
"--u-menu-active-bg": "rgba(59, 130, 246, 0.12)",
|
|
28
|
+
"--u-menu-active-color": T("color", "primary", "dark", "1"),
|
|
29
|
+
"--u-menu-height-small": "32px",
|
|
30
|
+
"--u-menu-height-default": "36px",
|
|
31
|
+
"--u-menu-height-large": "40px",
|
|
32
|
+
"--u-menu-bg-color": T("bg-color", "top"),
|
|
33
|
+
"--u-menu-bg-blur": "none",
|
|
34
|
+
"--u-menu-bg-saturate": "none",
|
|
35
|
+
"--u-menu-bg-image": "none",
|
|
36
|
+
"--u-tag-small": "20px",
|
|
37
|
+
"--u-tag-default": "24px",
|
|
38
|
+
"--u-tag-large": "28px",
|
|
39
|
+
"--u-switch-height-small": "18px",
|
|
40
|
+
"--u-switch-height-default": "20px",
|
|
41
|
+
"--u-switch-height-large": "24px",
|
|
42
|
+
"--u-breadcrumb-small": "20px",
|
|
43
|
+
"--u-breadcrumb-default": "22px",
|
|
44
|
+
"--u-breadcrumb-large": "24px"
|
|
45
|
+
};
|
|
46
|
+
/** 暗色下组件 token(含与亮色相同的尺寸项,保证暗色 html 块自洽) */
|
|
47
|
+
const componentCssVarsDark = {
|
|
48
|
+
...componentCssVarsLight,
|
|
49
|
+
"--u-table-border-color": "#404040",
|
|
50
|
+
"--u-table-header-bg": "#2a2a2a",
|
|
51
|
+
"--u-table-header-color": T("text-color", "main"),
|
|
52
|
+
"--u-table-stripe-bg": "#2a2a2a",
|
|
53
|
+
"--u-table-stripe-color": T("text-color", "main"),
|
|
54
|
+
"--u-table-hover-bg": "#333333",
|
|
55
|
+
"--u-table-hover-color": T("text-color", "title"),
|
|
56
|
+
"--u-table-current-bg": T("bg-color", "hover"),
|
|
57
|
+
"--u-table-current-color": "inherit",
|
|
58
|
+
"--u-table-checked-bg": T("color", "primary", "dark", "1"),
|
|
59
|
+
"--u-table-checked-color": "inherit",
|
|
60
|
+
"--u-menu-color": T("text-color", "main"),
|
|
61
|
+
"--u-menu-hover-bg": "rgba(148, 163, 184, 0.14)",
|
|
62
|
+
"--u-menu-hover-color": T("text-color", "title"),
|
|
63
|
+
"--u-menu-active-bg": "rgba(96, 165, 250, 0.2)",
|
|
64
|
+
"--u-menu-active-color": T("text-color", "white"),
|
|
65
|
+
"--u-menu-bg-color": T("bg-color", "middle"),
|
|
66
|
+
"--u-radio-border": "#595959",
|
|
67
|
+
"--u-checkbox-border": "#595959"
|
|
68
|
+
};
|
|
69
|
+
function recordToDeclList(record) {
|
|
70
|
+
return Object.entries(record).map(([k, v]) => `${k}: ${v}`);
|
|
71
|
+
}
|
|
72
|
+
const componentCssVarsLightDecls = recordToDeclList(componentCssVarsLight);
|
|
73
|
+
const componentCssVarsDarkDecls = recordToDeclList(componentCssVarsDark);
|
|
74
|
+
//#endregion
|
|
75
|
+
export { componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, themeTokenVar };
|
|
76
|
+
|
|
77
|
+
//# sourceMappingURL=component-css-vars.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-css-vars.js","names":[],"sources":["../../src/theme/component-css-vars.ts"],"sourcesContent":["/**\n * 桌面组件级 `--u-*` token,与内置主题一起在 `UITheme.injectBuiltInThemes` 中注入 `html`。\n * 修改此处即可在 TS 侧统一调整组件外观,无需在各组件 `style.scss` 重复声明。\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-table-border-color': '#e9e9e9',\n '--u-table-header-bg': '#f4f5f7',\n '--u-table-header-color': T('text-color', 'title'),\n '--u-table-stripe-bg': '#f8fafc',\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 '--u-menu-color': '#0f172a',\n '--u-menu-hover-bg': 'rgba(148, 163, 184, 0.12)',\n '--u-menu-hover-color': T('text-color', 'title'),\n '--u-menu-active-bg': 'rgba(59, 130, 246, 0.12)',\n '--u-menu-active-color': T('color', 'primary', 'dark', '1'),\n '--u-menu-height-small': '32px',\n '--u-menu-height-default': '36px',\n '--u-menu-height-large': '40px',\n '--u-menu-bg-color': T('bg-color', 'top'),\n '--u-menu-bg-blur': 'none',\n '--u-menu-bg-saturate': 'none',\n '--u-menu-bg-image': 'none',\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}\n\n/** 暗色下组件 token(含与亮色相同的尺寸项,保证暗色 html 块自洽) */\nexport const componentCssVarsDark: Record<string, string> = {\n ...componentCssVarsLight,\n '--u-table-border-color': '#404040',\n '--u-table-header-bg': '#2a2a2a',\n '--u-table-header-color': T('text-color', 'main'),\n '--u-table-stripe-bg': '#2a2a2a',\n '--u-table-stripe-color': T('text-color', 'main'),\n '--u-table-hover-bg': '#333333',\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-menu-color': T('text-color', 'main'),\n '--u-menu-hover-bg': 'rgba(148, 163, 184, 0.14)',\n '--u-menu-hover-color': T('text-color', 'title'),\n '--u-menu-active-bg': 'rgba(96, 165, 250, 0.2)',\n '--u-menu-active-color': T('text-color', 'white'),\n '--u-menu-bg-color': T('bg-color', 'middle'),\n '--u-radio-border': '#595959',\n '--u-checkbox-border': '#595959'\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"],"mappings":";;;;;;AAMA,SAAgB,cAAc,UAAkB,GAAG,OAAuC;AAExF,QAAO,WAAW,WADH,MAAM,SAAS,IAAI,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI,KAAK,GAC9B;;AAGtC,MAAM,IAAI;;AAGV,MAAa,wBAAgD;CAC3D,0BAA0B;CAC1B,uBAAuB;CACvB,0BAA0B,EAAE,cAAc,QAAQ;CAClD,uBAAuB;CACvB,0BAA0B;CAC1B,sBAAsB,EAAE,YAAY,QAAQ;CAC5C,yBAAyB;CACzB,wBAAwB,EAAE,YAAY,QAAQ;CAC9C,2BAA2B;CAC3B,wBAAwB,EAAE,SAAS,WAAW,UAAU;CACxD,2BAA2B;CAC3B,kBAAkB;CAClB,qBAAqB;CACrB,wBAAwB,EAAE,cAAc,QAAQ;CAChD,sBAAsB;CACtB,yBAAyB,EAAE,SAAS,WAAW,QAAQ,IAAI;CAC3D,yBAAyB;CACzB,2BAA2B;CAC3B,yBAAyB;CACzB,qBAAqB,EAAE,YAAY,MAAM;CACzC,oBAAoB;CACpB,wBAAwB;CACxB,qBAAqB;CACrB,iBAAiB;CACjB,mBAAmB;CACnB,iBAAiB;CACjB,2BAA2B;CAC3B,6BAA6B;CAC7B,2BAA2B;CAC3B,wBAAwB;CACxB,0BAA0B;CAC1B,wBAAwB;CACzB;;AAGD,MAAa,uBAA+C;CAC1D,GAAG;CACH,0BAA0B;CAC1B,uBAAuB;CACvB,0BAA0B,EAAE,cAAc,OAAO;CACjD,uBAAuB;CACvB,0BAA0B,EAAE,cAAc,OAAO;CACjD,sBAAsB;CACtB,yBAAyB,EAAE,cAAc,QAAQ;CACjD,wBAAwB,EAAE,YAAY,QAAQ;CAC9C,2BAA2B;CAC3B,wBAAwB,EAAE,SAAS,WAAW,QAAQ,IAAI;CAC1D,2BAA2B;CAC3B,kBAAkB,EAAE,cAAc,OAAO;CACzC,qBAAqB;CACrB,wBAAwB,EAAE,cAAc,QAAQ;CAChD,sBAAsB;CACtB,yBAAyB,EAAE,cAAc,QAAQ;CACjD,qBAAqB,EAAE,YAAY,SAAS;CAC5C,oBAAoB;CACpB,uBAAuB;CACxB;AAED,SAAS,iBAAiB,QAA0C;AAClE,QAAO,OAAO,QAAQ,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,GAAG,EAAE,IAAI,IAAI;;AAG7D,MAAa,6BAAuC,iBAAiB,sBAAsB;AAE3F,MAAa,4BAAsC,iBAAiB,qBAAqB"}
|
package/dist/theme/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, themeTokenVar } from "./component-css-vars.js";
|
|
1
2
|
import { RGBColor, Theme } from "./type.js";
|
|
2
3
|
import { UITheme } from "./ui-theme.js";
|
|
3
4
|
import { lightTheme } from "./light.js";
|
|
4
5
|
import { darkTheme } from "./dark.js";
|
|
5
6
|
import { HEXToRGB, cssVar, defineBySize, mixColor } from "./helper.js";
|
|
6
7
|
import { currentTheme, loadTheme, setTheme } from "../load-theme.js";
|
|
7
|
-
export { HEXToRGB, RGBColor, Theme, UITheme, cssVar, currentTheme, darkTheme, defineBySize, lightTheme, loadTheme, mixColor, setTheme };
|
|
8
|
+
export { HEXToRGB, RGBColor, Theme, UITheme, componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, cssVar, currentTheme, darkTheme, defineBySize, lightTheme, loadTheme, mixColor, setTheme, themeTokenVar };
|
package/dist/theme/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, themeTokenVar } from "./component-css-vars.js";
|
|
1
2
|
import { HEXToRGB, cssVar, defineBySize, mixColor } from "./helper.js";
|
|
2
3
|
import { UITheme } from "./ui-theme.js";
|
|
3
4
|
import { lightTheme } from "./light.js";
|
|
4
5
|
import { darkTheme } from "./dark.js";
|
|
5
6
|
import { currentTheme, loadTheme, setTheme } from "../load-theme.js";
|
|
6
|
-
export { HEXToRGB, UITheme, cssVar, currentTheme, darkTheme, defineBySize, lightTheme, loadTheme, mixColor, setTheme };
|
|
7
|
+
export { HEXToRGB, UITheme, componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, cssVar, currentTheme, darkTheme, defineBySize, lightTheme, loadTheme, mixColor, setTheme, themeTokenVar };
|
package/dist/theme/type.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* RGB颜色[红,绿,蓝]
|
|
4
4
|
*/
|
|
5
5
|
type RGBColor = [number, number, number];
|
|
6
|
-
/** 仅含全局 token;组件级
|
|
6
|
+
/** 仅含全局 token;组件级 `--u-*` 由 `theme/component-css-vars.ts` 随 `loadTheme` 注入 */
|
|
7
7
|
type Theme = {
|
|
8
8
|
/** 主题色 */color: {
|
|
9
9
|
/** 主要颜色 */primary: string; /** 成功颜色 */
|
package/dist/theme/ui-theme.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { componentCssVarsDarkDecls, componentCssVarsLightDecls } from "./component-css-vars.js";
|
|
1
2
|
import { mixColor } from "./helper.js";
|
|
2
3
|
import { isObj, o, str } from "@cat-kit/core";
|
|
3
4
|
import { withUnit } from "@veltra/utils";
|
|
@@ -140,8 +141,8 @@ var UITheme = class UITheme {
|
|
|
140
141
|
}
|
|
141
142
|
/** 内置 light/dark:支持 data-theme 与 prefers-color-scheme */
|
|
142
143
|
static injectBuiltInThemes(light, dark) {
|
|
143
|
-
const lightDecls = light.themeToDeclarationList(toRaw(light.theme));
|
|
144
|
-
const darkDecls = dark.themeToDeclarationList(toRaw(dark.theme));
|
|
144
|
+
const lightDecls = [...light.themeToDeclarationList(toRaw(light.theme)), ...componentCssVarsLightDecls];
|
|
145
|
+
const darkDecls = [...dark.themeToDeclarationList(toRaw(dark.theme)), ...componentCssVarsDarkDecls];
|
|
145
146
|
const lightBlock = UITheme.declarationBlock(lightDecls);
|
|
146
147
|
const darkBlock = UITheme.declarationBlock(darkDecls);
|
|
147
148
|
const css = [
|
|
@@ -155,7 +156,7 @@ var UITheme = class UITheme {
|
|
|
155
156
|
UITheme.applyGlobalCSS(css);
|
|
156
157
|
}
|
|
157
158
|
render() {
|
|
158
|
-
const decls = this.themeToDeclarationList(toRaw(this.theme));
|
|
159
|
+
const decls = [...this.themeToDeclarationList(toRaw(this.theme)), ...componentCssVarsLightDecls];
|
|
159
160
|
const css = `html { ${UITheme.declarationBlock(decls)} }`;
|
|
160
161
|
UITheme.applyGlobalCSS(css);
|
|
161
162
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-theme.js","names":[],"sources":["../../src/theme/ui-theme.ts"],"sourcesContent":["import { isObj, o, str } from '@cat-kit/core'\nimport { withUnit } from '@veltra/utils'\nimport { reactive, toRaw, watch } from 'vue'\n\nimport { 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\nfunction isDevEnv(): boolean {\n try {\n if (typeof import.meta !== 'undefined') {\n const env = (import.meta as { env?: { DEV?: boolean } }).env\n if (env?.DEV === true) return true\n }\n } catch {\n /* ignore */\n }\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process\n return typeof proc !== 'undefined' && proc.env?.NODE_ENV !== 'production'\n}\n\nexport class UITheme {\n static themeID = 'ultra-ui-theme'\n\n private static legacyDeprecationWarned = false\n\n private static adoptedSheet: CSSStyleSheet | null = null\n\n readonly theme: Theme\n\n private readonly reactiveEnabled: boolean\n\n constructor(theme: Theme, options?: { reactive?: boolean }) {\n this.reactiveEnabled = options?.reactive !== false\n this.theme = reactive(theme) as Theme\n if (this.reactiveEnabled) {\n watch(this.theme, () => this.render(), { deep: true })\n }\n }\n\n static setTheme(mode: 'light' | 'dark' | 'auto'): void {\n if (typeof document === 'undefined') return\n const el = document.documentElement\n if (mode === 'auto') {\n delete el.dataset.theme\n } else {\n el.dataset.theme = mode\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 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 border = Object.keys(theme.border)\n .map((key) => `var(--u-border-${key})`)\n .join(' ')\n\n return `--u-border: ${border}`\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 return Object.keys(color)\n .map((type) => `--u-bg-color-${type}-alpha: ${color[type as keyof typeof color]}aa`)\n .join(';')\n }\n\n private renderBGFilter(theme: Theme): string {\n const { filter } = theme.bg\n return `--u-bg-filter: ${filter.blur} ${filter.saturate}`\n }\n\n /** 主题变量声明(不含 legacy 副本) */\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.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 withLegacyDuplicates(decls: string[]): string {\n const legacy: string[] = []\n for (const decl of decls) {\n const idx = decl.indexOf(':')\n if (idx === -1) continue\n const name = decl.slice(0, idx).trim()\n const value = decl.slice(idx + 1).trim()\n if (name.startsWith('--u-')) {\n legacy.push(`--${name.slice(4)}: ${value}`)\n }\n }\n return [...decls, ...legacy].join(';')\n }\n\n private static warnLegacyOnce(): void {\n if (!isDevEnv() || UITheme.legacyDeprecationWarned) return\n UITheme.legacyDeprecationWarned = true\n console.warn(\n '[@veltra/styles] Theme CSS variables now prefer the `--u-` namespace. ' +\n 'Unprefixed aliases (e.g. `--color-primary`) are deprecated and will be removed in a future major version.'\n )\n }\n\n private static declarationBlock(decls: string[]): string {\n const merged = UITheme.withLegacyDuplicates(decls)\n UITheme.warnLegacyOnce()\n return merged\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 /** 内置 light/dark:支持 data-theme 与 prefers-color-scheme */\n static injectBuiltInThemes(light: UITheme, dark: UITheme): void {\n const lightDecls = light.themeToDeclarationList(toRaw(light.theme))\n const darkDecls = dark.themeToDeclarationList(toRaw(dark.theme))\n const lightBlock = UITheme.declarationBlock(lightDecls)\n const darkBlock = UITheme.declarationBlock(darkDecls)\n\n const css = [\n `html { ${lightBlock} }`,\n `@media (prefers-color-scheme: dark) {`,\n ` html:not([data-theme=\"light\"]) { ${darkBlock} }`,\n `}`,\n `html[data-theme=\"light\"] { ${lightBlock} }`,\n `html[data-theme=\"dark\"] { ${darkBlock} }`\n ].join('\\n')\n\n UITheme.applyGlobalCSS(css)\n }\n\n render(): void {\n const decls = this.themeToDeclarationList(toRaw(this.theme))\n const block = UITheme.declarationBlock(decls)\n const css = `html { ${block} }`\n UITheme.applyGlobalCSS(css)\n }\n\n new(customTheme: RecursivePartial<Theme> = {}): 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 o(base).deepExtend(customTheme as Record<string, any>)\n return new UITheme(base as Theme, { reactive: this.reactiveEnabled })\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, o, str } from '@cat-kit/core'\nimport { withUnit } from '@veltra/utils'\nimport { reactive, toRaw, watch } from 'vue'\n\nimport { componentCssVarsDarkDecls, componentCssVarsLightDecls } from './component-css-vars'\nimport { 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\nfunction isDevEnv(): boolean {\n try {\n if (typeof import.meta !== 'undefined') {\n const env = (import.meta as { env?: { DEV?: boolean } }).env\n if (env?.DEV === true) return true\n }\n } catch {\n /* ignore */\n }\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process\n return typeof proc !== 'undefined' && proc.env?.NODE_ENV !== 'production'\n}\n\nexport class UITheme {\n static themeID = 'ultra-ui-theme'\n\n private static legacyDeprecationWarned = false\n\n private static adoptedSheet: CSSStyleSheet | null = null\n\n readonly theme: Theme\n\n private readonly reactiveEnabled: boolean\n\n constructor(theme: Theme, options?: { reactive?: boolean }) {\n this.reactiveEnabled = options?.reactive !== false\n this.theme = reactive(theme) as Theme\n if (this.reactiveEnabled) {\n watch(this.theme, () => this.render(), { deep: true })\n }\n }\n\n static setTheme(mode: 'light' | 'dark' | 'auto'): void {\n if (typeof document === 'undefined') return\n const el = document.documentElement\n if (mode === 'auto') {\n delete el.dataset.theme\n } else {\n el.dataset.theme = mode\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 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 border = Object.keys(theme.border)\n .map((key) => `var(--u-border-${key})`)\n .join(' ')\n\n return `--u-border: ${border}`\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 return Object.keys(color)\n .map((type) => `--u-bg-color-${type}-alpha: ${color[type as keyof typeof color]}aa`)\n .join(';')\n }\n\n private renderBGFilter(theme: Theme): string {\n const { filter } = theme.bg\n return `--u-bg-filter: ${filter.blur} ${filter.saturate}`\n }\n\n /** 主题变量声明(不含 legacy 副本) */\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.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 withLegacyDuplicates(decls: string[]): string {\n const legacy: string[] = []\n for (const decl of decls) {\n const idx = decl.indexOf(':')\n if (idx === -1) continue\n const name = decl.slice(0, idx).trim()\n const value = decl.slice(idx + 1).trim()\n if (name.startsWith('--u-')) {\n legacy.push(`--${name.slice(4)}: ${value}`)\n }\n }\n return [...decls, ...legacy].join(';')\n }\n\n private static warnLegacyOnce(): void {\n if (!isDevEnv() || UITheme.legacyDeprecationWarned) return\n UITheme.legacyDeprecationWarned = true\n console.warn(\n '[@veltra/styles] Theme CSS variables now prefer the `--u-` namespace. ' +\n 'Unprefixed aliases (e.g. `--color-primary`) are deprecated and will be removed in a future major version.'\n )\n }\n\n private static declarationBlock(decls: string[]): string {\n const merged = UITheme.withLegacyDuplicates(decls)\n UITheme.warnLegacyOnce()\n return merged\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 /** 内置 light/dark:支持 data-theme 与 prefers-color-scheme */\n static injectBuiltInThemes(light: UITheme, dark: UITheme): void {\n const lightDecls = [\n ...light.themeToDeclarationList(toRaw(light.theme)),\n ...componentCssVarsLightDecls\n ]\n const darkDecls = [\n ...dark.themeToDeclarationList(toRaw(dark.theme)),\n ...componentCssVarsDarkDecls\n ]\n const lightBlock = UITheme.declarationBlock(lightDecls)\n const darkBlock = UITheme.declarationBlock(darkDecls)\n\n const css = [\n `html { ${lightBlock} }`,\n `@media (prefers-color-scheme: dark) {`,\n ` html:not([data-theme=\"light\"]) { ${darkBlock} }`,\n `}`,\n `html[data-theme=\"light\"] { ${lightBlock} }`,\n `html[data-theme=\"dark\"] { ${darkBlock} }`\n ].join('\\n')\n\n UITheme.applyGlobalCSS(css)\n }\n\n render(): void {\n const decls = [...this.themeToDeclarationList(toRaw(this.theme)), ...componentCssVarsLightDecls]\n const block = UITheme.declarationBlock(decls)\n const css = `html { ${block} }`\n UITheme.applyGlobalCSS(css)\n }\n\n new(customTheme: RecursivePartial<Theme> = {}): 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 o(base).deepExtend(customTheme as Record<string, any>)\n return new UITheme(base as Theme, { reactive: this.reactiveEnabled })\n }\n}\n"],"mappings":";;;;;;AAYA,SAAS,WAAoB;AAC3B,KAAI;AACF,MAAI,OAAO,OAAO,SAAS;OACZ,OAAO,KAAqC,KAChD,QAAQ,KAAM,QAAO;;SAE1B;CAGR,MAAM,OAAQ,WAA0E;AACxF,QAAO,OAAO,SAAS,eAAe,KAAK,KAAK,aAAa;;AAG/D,IAAa,UAAb,MAAa,QAAQ;CACnB,OAAO,UAAU;CAEjB,OAAe,0BAA0B;CAEzC,OAAe,eAAqC;CAEpD;CAEA;CAEA,YAAY,OAAc,SAAkC;AAC1D,OAAK,kBAAkB,SAAS,aAAa;AAC7C,OAAK,QAAQ,SAAS,MAAM;AAC5B,MAAI,KAAK,gBACP,OAAM,KAAK,aAAa,KAAK,QAAQ,EAAE,EAAE,MAAM,MAAM,CAAC;;CAI1D,OAAO,SAAS,MAAuC;AACrD,MAAI,OAAO,aAAa,YAAa;EACrC,MAAM,KAAK,SAAS;AACpB,MAAI,SAAS,OACX,QAAO,GAAG,QAAQ;MAElB,IAAG,QAAQ,QAAQ;;CAIvB,WACE,OACA,aAAuB,EAAE,EACzB,YAAY,OACF;AACV,SAAO,KAAK,MAAM,CAAC,SAAS,QAAQ;GAClC,MAAM,QAAQ,MAAM;GACpB,MAAM,SAAS,GAAG,UAAU,WAAW,IAAI,GAAG,YAAY,IAAI,UAAU,CAAC,WAAW,CAAC,GAAG,IAAI,IAAI,CAAC,WAAW;AAC5G,OAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM,CACtE,MAAK,WAAW,OAAkC,YAAY,OAAO;YAEjE,SAAS,UAAU,GAAG;IACxB,MAAM,IAAI,SAAS,OAA0B,KAAK;AAClD,QAAI,MAAM,KAAA,EACR,YAAW,KAAK,GAAG,OAAO,IAAI,IAAI;;IAIxC;AAEF,SAAO;;CAGT,aAAqB,OAAsB;AAKzC,SAAO,eAJQ,OAAO,KAAK,MAAM,OAAO,CACrC,KAAK,QAAQ,kBAAkB,IAAI,GAAG,CACtC,KAAK,IAAI;;CAKd,gBAAwB,OAAsB;EAC5C,MAAM,EAAE,UAAU;EAElB,MAAM,QAAQ,OAAO,KAAK,MAAM;EAChC,MAAM,QAAQ;GAAC;GAAG;GAAG;GAAG;GAAG;GAAE;AAE7B,SAAO,MACJ,KAAK,SAAS;GACb,MAAM,aAAa,MAAM;AAEzB,UAAO,MACJ,KAAK,SAAS;AAWb,WAAO,GAVO,aAAa,KAAK,SAAS,KAAK,IAAI,SAChD,YACA,QACA,OAAO,GACR,GAMe,GALH,aAAa,KAAK,QAAQ,KAAK,IAAI,SAC9C,YACA,QACA,OAAO,GACR;KAED,CACD,KAAK,IAAI;IACZ,CACD,KAAK,IAAI;;CAGd,aAAqB,QAAuB;AAK1C,SAAO,eAJQ;GAAC;GAAK;GAAK;GAAQ;GAAU;GAAQ,CACjD,KAAK,MAAM,kBAAkB,EAAE,GAAG,CAClC,KAAK,IAAI;;CAKd,mBAA2B,OAAsB;EAC/C,MAAM,EAAE,UAAU,MAAM;AACxB,SAAO,OAAO,KAAK,MAAM,CACtB,KAAK,SAAS,gBAAgB,KAAK,UAAU,MAAM,MAA4B,IAAI,CACnF,KAAK,IAAI;;CAGd,eAAuB,OAAsB;EAC3C,MAAM,EAAE,WAAW,MAAM;AACzB,SAAO,kBAAkB,OAAO,KAAK,GAAG,OAAO;;;CAIjD,uBAAuB,OAAwB;EAC7C,MAAM,MAAM;EACZ,MAAM,QAAkB,CAAC,GAAG,KAAK,WAAW,IAAI,CAAC;EACjD,MAAM,SAAS;GACb,KAAK,gBAAgB,MAAM;GAC3B,KAAK,aAAa,MAAM;GACxB,KAAK,mBAAmB,MAAM;GAC9B,KAAK,eAAe,MAAM;GAC1B,KAAK,aAAa,MAAM;GACzB;AACD,OAAK,MAAM,KAAK,OACd,OAAM,KACJ,GAAG,EACA,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,OAAO,QAAQ,CACnB;AAEH,SAAO;;CAGT,OAAe,qBAAqB,OAAyB;EAC3D,MAAM,SAAmB,EAAE;AAC3B,OAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,MAAM,KAAK,QAAQ,IAAI;AAC7B,OAAI,QAAQ,GAAI;GAChB,MAAM,OAAO,KAAK,MAAM,GAAG,IAAI,CAAC,MAAM;GACtC,MAAM,QAAQ,KAAK,MAAM,MAAM,EAAE,CAAC,MAAM;AACxC,OAAI,KAAK,WAAW,OAAO,CACzB,QAAO,KAAK,KAAK,KAAK,MAAM,EAAE,CAAC,IAAI,QAAQ;;AAG/C,SAAO,CAAC,GAAG,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI;;CAGxC,OAAe,iBAAuB;AACpC,MAAI,CAAC,UAAU,IAAI,QAAQ,wBAAyB;AACpD,UAAQ,0BAA0B;AAClC,UAAQ,KACN,kLAED;;CAGH,OAAe,iBAAiB,OAAyB;EACvD,MAAM,SAAS,QAAQ,qBAAqB,MAAM;AAClD,UAAQ,gBAAgB;AACxB,SAAO;;CAGT,OAAe,uBAAuB,KAAqB;EACzD,MAAM,KAAK,IAAI,eAAe,QAAQ,QAAQ;AAC9C,MAAI,IAAI,WACN,IAAG,WAAW,YAAY,GAAG;;CAIjC,OAAe,eAAe,KAAmB;EAC/C,MAAM,MAAM,OAAO,aAAa,cAAc,WAAW,KAAA;AACzD,MAAI,CAAC,IAAK;AAKV,MAFE,OAAO,kBAAkB,eAAe,wBAAwB,SAAS,WAE7D;AACZ,WAAQ,uBAAuB,IAAI;AACnC,OAAI,CAAC,QAAQ,cAAc;AACzB,YAAQ,eAAe,IAAI,eAAe;AAC1C,QAAI,qBAAqB,CAAC,GAAG,IAAI,oBAAoB,QAAQ,aAAa;;AAE5E,WAAQ,aAAa,YAAY,IAAI;SAChC;AACL,OAAI,QAAQ,aACV,SAAQ,eAAe;GAEzB,IAAI,QAAQ,IAAI,eAAe,QAAQ,QAAQ;AAC/C,OAAI,CAAC,OAAO;AACV,YAAQ,IAAI,cAAc,QAAQ;AAClC,UAAM,KAAK,QAAQ;AACnB,QAAI,KAAK,YAAY,MAAM;;AAE7B,SAAM,cAAc;;;;CAKxB,OAAO,oBAAoB,OAAgB,MAAqB;EAC9D,MAAM,aAAa,CACjB,GAAG,MAAM,uBAAuB,MAAM,MAAM,MAAM,CAAC,EACnD,GAAG,2BACJ;EACD,MAAM,YAAY,CAChB,GAAG,KAAK,uBAAuB,MAAM,KAAK,MAAM,CAAC,EACjD,GAAG,0BACJ;EACD,MAAM,aAAa,QAAQ,iBAAiB,WAAW;EACvD,MAAM,YAAY,QAAQ,iBAAiB,UAAU;EAErD,MAAM,MAAM;GACV,UAAU,WAAW;GACrB;GACA,sCAAsC,UAAU;GAChD;GACA,8BAA8B,WAAW;GACzC,6BAA6B,UAAU;GACxC,CAAC,KAAK,KAAK;AAEZ,UAAQ,eAAe,IAAI;;CAG7B,SAAe;EACb,MAAM,QAAQ,CAAC,GAAG,KAAK,uBAAuB,MAAM,KAAK,MAAM,CAAC,EAAE,GAAG,2BAA2B;EAEhG,MAAM,MAAM,UADE,QAAQ,iBAAiB,MAAM,CACjB;AAC5B,UAAQ,eAAe,IAAI;;CAG7B,IAAI,cAAuC,EAAE,EAAW;EACtD,SAAS,SAAS,KAA8B;AAC9C,UAAO,KAAK,IAAI,CAAC,SAAS,QAAQ;IAChC,MAAM,QAAQ,IAAI;AAClB,QAAI,MAAM,MAAM,CACd,QAAO,SAAS,MAAiC;AAEnD,QAAI,CAAC,SAAS,UAAU,EACtB,QAAO,IAAI;KAEb;;AAGJ,WAAS,YAAuC;EAEhD,MAAM,OAAO,KAAK,MAAM,KAAK,UAAU,MAAM,KAAK,MAAM,CAAC,CAAC;AAC1D,IAAE,KAAK,CAAC,WAAW,YAAmC;AACtD,SAAO,IAAI,QAAQ,MAAe,EAAE,UAAU,KAAK,iBAAiB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@veltra/styles",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist",
|
|
6
6
|
"src"
|
|
@@ -59,16 +59,11 @@
|
|
|
59
59
|
"check-types": "tsc -p tsconfig.json --noEmit"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@cat-kit/core": "^1.
|
|
63
|
-
"@veltra/compositions": "1.0.
|
|
64
|
-
"@veltra/utils": "1.0.
|
|
65
|
-
},
|
|
66
|
-
"devDependencies": {
|
|
67
|
-
"@tsdown/css": "^0.21.7",
|
|
68
|
-
"sass-embedded": "^1.99.0",
|
|
69
|
-
"tsdown": "^0.21.7"
|
|
62
|
+
"@cat-kit/core": "^1.1.1",
|
|
63
|
+
"@veltra/compositions": "1.0.9",
|
|
64
|
+
"@veltra/utils": "1.0.9"
|
|
70
65
|
},
|
|
71
66
|
"peerDependencies": {
|
|
72
|
-
"vue": "^3.5.
|
|
67
|
+
"vue": "^3.5.33"
|
|
73
68
|
}
|
|
74
69
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 桌面组件级 `--u-*` token,与内置主题一起在 `UITheme.injectBuiltInThemes` 中注入 `html`。
|
|
3
|
+
* 修改此处即可在 TS 侧统一调整组件外观,无需在各组件 `style.scss` 重复声明。
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** 与 SCSS `fn.use-var($basename, $nodes...)` 输出一致 */
|
|
7
|
+
export function themeTokenVar(basename: string, ...nodes: Array<string | number>): string {
|
|
8
|
+
const suffix = nodes.length ? `-${nodes.map(String).join('-')}` : ''
|
|
9
|
+
return `var(--u-${basename}${suffix})`
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const T = themeTokenVar
|
|
13
|
+
|
|
14
|
+
/** 亮色(及与暗色相同的尺寸类)下组件 token */
|
|
15
|
+
export const componentCssVarsLight: Record<string, string> = {
|
|
16
|
+
'--u-table-border-color': '#e9e9e9',
|
|
17
|
+
'--u-table-header-bg': '#f4f5f7',
|
|
18
|
+
'--u-table-header-color': T('text-color', 'title'),
|
|
19
|
+
'--u-table-stripe-bg': '#f8fafc',
|
|
20
|
+
'--u-table-stripe-color': 'inherit',
|
|
21
|
+
'--u-table-hover-bg': T('bg-color', 'hover'),
|
|
22
|
+
'--u-table-hover-color': 'inherit',
|
|
23
|
+
'--u-table-current-bg': T('bg-color', 'hover'),
|
|
24
|
+
'--u-table-current-color': 'inherit',
|
|
25
|
+
'--u-table-checked-bg': T('color', 'primary', 'light-9'),
|
|
26
|
+
'--u-table-checked-color': 'inherit',
|
|
27
|
+
'--u-menu-color': '#0f172a',
|
|
28
|
+
'--u-menu-hover-bg': 'rgba(148, 163, 184, 0.12)',
|
|
29
|
+
'--u-menu-hover-color': T('text-color', 'title'),
|
|
30
|
+
'--u-menu-active-bg': 'rgba(59, 130, 246, 0.12)',
|
|
31
|
+
'--u-menu-active-color': T('color', 'primary', 'dark', '1'),
|
|
32
|
+
'--u-menu-height-small': '32px',
|
|
33
|
+
'--u-menu-height-default': '36px',
|
|
34
|
+
'--u-menu-height-large': '40px',
|
|
35
|
+
'--u-menu-bg-color': T('bg-color', 'top'),
|
|
36
|
+
'--u-menu-bg-blur': 'none',
|
|
37
|
+
'--u-menu-bg-saturate': 'none',
|
|
38
|
+
'--u-menu-bg-image': 'none',
|
|
39
|
+
'--u-tag-small': '20px',
|
|
40
|
+
'--u-tag-default': '24px',
|
|
41
|
+
'--u-tag-large': '28px',
|
|
42
|
+
'--u-switch-height-small': '18px',
|
|
43
|
+
'--u-switch-height-default': '20px',
|
|
44
|
+
'--u-switch-height-large': '24px',
|
|
45
|
+
'--u-breadcrumb-small': '20px',
|
|
46
|
+
'--u-breadcrumb-default': '22px',
|
|
47
|
+
'--u-breadcrumb-large': '24px'
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** 暗色下组件 token(含与亮色相同的尺寸项,保证暗色 html 块自洽) */
|
|
51
|
+
export const componentCssVarsDark: Record<string, string> = {
|
|
52
|
+
...componentCssVarsLight,
|
|
53
|
+
'--u-table-border-color': '#404040',
|
|
54
|
+
'--u-table-header-bg': '#2a2a2a',
|
|
55
|
+
'--u-table-header-color': T('text-color', 'main'),
|
|
56
|
+
'--u-table-stripe-bg': '#2a2a2a',
|
|
57
|
+
'--u-table-stripe-color': T('text-color', 'main'),
|
|
58
|
+
'--u-table-hover-bg': '#333333',
|
|
59
|
+
'--u-table-hover-color': T('text-color', 'title'),
|
|
60
|
+
'--u-table-current-bg': T('bg-color', 'hover'),
|
|
61
|
+
'--u-table-current-color': 'inherit',
|
|
62
|
+
'--u-table-checked-bg': T('color', 'primary', 'dark', '1'),
|
|
63
|
+
'--u-table-checked-color': 'inherit',
|
|
64
|
+
'--u-menu-color': T('text-color', 'main'),
|
|
65
|
+
'--u-menu-hover-bg': 'rgba(148, 163, 184, 0.14)',
|
|
66
|
+
'--u-menu-hover-color': T('text-color', 'title'),
|
|
67
|
+
'--u-menu-active-bg': 'rgba(96, 165, 250, 0.2)',
|
|
68
|
+
'--u-menu-active-color': T('text-color', 'white'),
|
|
69
|
+
'--u-menu-bg-color': T('bg-color', 'middle'),
|
|
70
|
+
'--u-radio-border': '#595959',
|
|
71
|
+
'--u-checkbox-border': '#595959'
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function recordToDeclList(record: Record<string, string>): string[] {
|
|
75
|
+
return Object.entries(record).map(([k, v]) => `${k}: ${v}`)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export const componentCssVarsLightDecls: string[] = recordToDeclList(componentCssVarsLight)
|
|
79
|
+
|
|
80
|
+
export const componentCssVarsDarkDecls: string[] = recordToDeclList(componentCssVarsDark)
|
package/src/theme/index.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
export {
|
|
2
|
+
componentCssVarsDark,
|
|
3
|
+
componentCssVarsDarkDecls,
|
|
4
|
+
componentCssVarsLight,
|
|
5
|
+
componentCssVarsLightDecls,
|
|
6
|
+
themeTokenVar
|
|
7
|
+
} from './component-css-vars'
|
|
1
8
|
export { UITheme } from './ui-theme'
|
|
2
9
|
export { lightTheme } from './light'
|
|
3
10
|
export { darkTheme } from './dark'
|
package/src/theme/type.ts
CHANGED
package/src/theme/ui-theme.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { isObj, o, str } from '@cat-kit/core'
|
|
|
2
2
|
import { withUnit } from '@veltra/utils'
|
|
3
3
|
import { reactive, toRaw, watch } from 'vue'
|
|
4
4
|
|
|
5
|
+
import { componentCssVarsDarkDecls, componentCssVarsLightDecls } from './component-css-vars'
|
|
5
6
|
import { mixColor } from './helper'
|
|
6
7
|
import type { Theme } from './type'
|
|
7
8
|
|
|
@@ -219,8 +220,14 @@ export class UITheme {
|
|
|
219
220
|
|
|
220
221
|
/** 内置 light/dark:支持 data-theme 与 prefers-color-scheme */
|
|
221
222
|
static injectBuiltInThemes(light: UITheme, dark: UITheme): void {
|
|
222
|
-
const lightDecls =
|
|
223
|
-
|
|
223
|
+
const lightDecls = [
|
|
224
|
+
...light.themeToDeclarationList(toRaw(light.theme)),
|
|
225
|
+
...componentCssVarsLightDecls
|
|
226
|
+
]
|
|
227
|
+
const darkDecls = [
|
|
228
|
+
...dark.themeToDeclarationList(toRaw(dark.theme)),
|
|
229
|
+
...componentCssVarsDarkDecls
|
|
230
|
+
]
|
|
224
231
|
const lightBlock = UITheme.declarationBlock(lightDecls)
|
|
225
232
|
const darkBlock = UITheme.declarationBlock(darkDecls)
|
|
226
233
|
|
|
@@ -237,7 +244,7 @@ export class UITheme {
|
|
|
237
244
|
}
|
|
238
245
|
|
|
239
246
|
render(): void {
|
|
240
|
-
const decls = this.themeToDeclarationList(toRaw(this.theme))
|
|
247
|
+
const decls = [...this.themeToDeclarationList(toRaw(this.theme)), ...componentCssVarsLightDecls]
|
|
241
248
|
const block = UITheme.declarationBlock(decls)
|
|
242
249
|
const css = `html { ${block} }`
|
|
243
250
|
UITheme.applyGlobalCSS(css)
|