@veltra/styles 1.7.0 → 1.7.1

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.
@@ -0,0 +1,24 @@
1
+ //#region src/theme/component-css-vars.d.ts
2
+ /**
3
+ * 桌面组件级 `--u-*` token,随 `UITheme.render()` 按主题系列(light/dark)注入 `html`。
4
+ * 修改此处即可在 TS 侧统一调整组件外观,无需在各组件 `style.scss` 重复声明。
5
+ * nav 系列:外观(底色/前景)不在此列表,由 `navSidebarCssVars` 按主题 `nav.variant`
6
+ * (dark 深底浅字 / light 浅底深字,默认 dark)与 `nav` 覆盖项注入,见 `ui-theme.ts`。
7
+ */
8
+ /** 与 SCSS `fn.use-var($basename, $nodes...)` 输出一致 */
9
+ declare function themeTokenVar(basename: string, ...nodes: Array<string | number>): string;
10
+ /** 亮色(及与暗色相同的尺寸类)下组件 token */
11
+ declare const componentCssVarsLight: Record<string, string>;
12
+ /** 暗色下组件 token(含与亮色相同的尺寸项,保证暗色 html 块自洽) */
13
+ declare const componentCssVarsDark: Record<string, string>;
14
+ declare const componentCssVarsLightDecls: string[];
15
+ declare const componentCssVarsDarkDecls: string[];
16
+ /** 侧栏外观变体:dark 深底浅字 / light 浅底深字 */
17
+ type NavSidebarVariant = 'dark' | 'light';
18
+ /** 某主题系列 + 侧栏变体下的 nav 外观 token(键为 `--u-nav-*`) */
19
+ declare function navSidebarTokens(series: 'light' | 'dark', variant: NavSidebarVariant): Record<string, string>;
20
+ /** 解析某主题系列 + 侧栏变体下的 nav 外观 token 声明列表 */
21
+ declare function resolveNavSidebarDecls(series: 'light' | 'dark', variant: NavSidebarVariant): string[];
22
+ //#endregion
23
+ export { NavSidebarVariant, componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, navSidebarTokens, resolveNavSidebarDecls, themeTokenVar };
24
+ //# sourceMappingURL=component-css-vars.d.ts.map
@@ -2,6 +2,8 @@
2
2
  /**
3
3
  * 桌面组件级 `--u-*` token,随 `UITheme.render()` 按主题系列(light/dark)注入 `html`。
4
4
  * 修改此处即可在 TS 侧统一调整组件外观,无需在各组件 `style.scss` 重复声明。
5
+ * nav 系列:外观(底色/前景)不在此列表,由 `navSidebarCssVars` 按主题 `nav.variant`
6
+ * (dark 深底浅字 / light 浅底深字,默认 dark)与 `nav` 覆盖项注入,见 `ui-theme.ts`。
5
7
  */
6
8
  /** 与 SCSS `fn.use-var($basename, $nodes...)` 输出一致 */
7
9
  function themeTokenVar(basename, ...nodes) {
@@ -22,15 +24,9 @@ const componentCssVarsLight = {
22
24
  "--u-table-current-color": "inherit",
23
25
  "--u-table-checked-bg": T("color", "primary", "light-9"),
24
26
  "--u-table-checked-color": "inherit",
25
- "--u-nav-color": T("text-color", "title"),
26
- "--u-nav-hover-bg": T("text-color", "title", "a", "8"),
27
- "--u-nav-hover-color": T("text-color", "title"),
28
- "--u-nav-active-bg": T("color", "primary", "a", "10"),
29
- "--u-nav-active-color": T("color", "primary", "dark", "1"),
30
27
  "--u-nav-height-small": "32px",
31
28
  "--u-nav-height-default": "36px",
32
29
  "--u-nav-height-large": "40px",
33
- "--u-nav-bg-color": T("bg-color", "top"),
34
30
  "--u-nav-bg-image": "none",
35
31
  "--u-nav-rail-width": "56px",
36
32
  "--u-nav-rail-labeled-width": "72px",
@@ -108,12 +104,6 @@ const componentCssVarsDark = {
108
104
  "--u-table-current-color": "inherit",
109
105
  "--u-table-checked-bg": T("color", "primary", "dark", "1"),
110
106
  "--u-table-checked-color": "inherit",
111
- "--u-nav-color": T("text-color", "main"),
112
- "--u-nav-hover-bg": T("text-color", "title", "a", "8"),
113
- "--u-nav-hover-color": T("text-color", "title"),
114
- "--u-nav-active-bg": T("color", "primary", "a", "16"),
115
- "--u-nav-active-color": T("text-color", "white"),
116
- "--u-nav-bg-color": T("bg-color", "middle"),
117
107
  "--u-radio-border": "#595959",
118
108
  "--u-checkbox-border": "#595959",
119
109
  "--u-button-primary-plain-bg": T("color", "primary", "dark", "9"),
@@ -162,7 +152,77 @@ function recordToDeclList(record) {
162
152
  }
163
153
  const componentCssVarsLightDecls = recordToDeclList(componentCssVarsLight);
164
154
  const componentCssVarsDarkDecls = recordToDeclList(componentCssVarsDark);
155
+ /** 深侧栏 · 浅色主题下:深底(text-color.title)+ 浅前景,与浅色内容区拉开区分度 */
156
+ const navSidebarDarkInLight = {
157
+ "--u-nav-bg-color": T("text-color", "title"),
158
+ "--u-nav-color": "rgba(255, 255, 255, 0.72)",
159
+ "--u-nav-hover-bg": "rgba(255, 255, 255, 0.08)",
160
+ "--u-nav-hover-color": T("text-color", "white"),
161
+ "--u-nav-active-bg": T("color", "primary", "a", "22"),
162
+ "--u-nav-active-color": T("text-color", "white"),
163
+ "--u-nav-strong-color": T("text-color", "white"),
164
+ "--u-nav-second-color": "rgba(255, 255, 255, 0.45)",
165
+ "--u-nav-sub-border-color": "rgba(255, 255, 255, 0.15)",
166
+ "--u-nav-rail-bg": "rgba(0, 0, 0, 0.2)"
167
+ };
168
+ /** 浅侧栏 · 浅色主题下:比内容区 top 低一档的浅底 + 深前景 */
169
+ const navSidebarLightInLight = {
170
+ "--u-nav-bg-color": T("bg-color", "middle"),
171
+ "--u-nav-color": T("text-color", "title"),
172
+ "--u-nav-hover-bg": T("text-color", "title", "a", "8"),
173
+ "--u-nav-hover-color": T("text-color", "title"),
174
+ "--u-nav-active-bg": T("color", "primary", "a", "10"),
175
+ "--u-nav-active-color": T("color", "primary", "dark", "1"),
176
+ "--u-nav-strong-color": T("text-color", "title"),
177
+ "--u-nav-second-color": T("text-color", "second"),
178
+ "--u-nav-sub-border-color": T("border", "color", "a", "52"),
179
+ "--u-nav-rail-bg": T("bg-color", "bottom")
180
+ };
181
+ /** 深侧栏 · 深色主题下:比内容区 top 深一档 */
182
+ const navSidebarDarkInDark = {
183
+ "--u-nav-bg-color": T("bg-color", "middle"),
184
+ "--u-nav-color": T("text-color", "main"),
185
+ "--u-nav-hover-bg": T("text-color", "title", "a", "8"),
186
+ "--u-nav-hover-color": T("text-color", "title"),
187
+ "--u-nav-active-bg": T("color", "primary", "a", "16"),
188
+ "--u-nav-active-color": T("text-color", "white"),
189
+ "--u-nav-strong-color": T("text-color", "title"),
190
+ "--u-nav-second-color": T("text-color", "second"),
191
+ "--u-nav-sub-border-color": T("border", "color", "a", "52"),
192
+ "--u-nav-rail-bg": T("bg-color", "bottom")
193
+ };
194
+ /** 浅侧栏 · 深色主题下:提亮侧栏(与深色内容区反向对比) */
195
+ const navSidebarLightInDark = {
196
+ "--u-nav-bg-color": T("bg-color", "top"),
197
+ "--u-nav-color": T("text-color", "title"),
198
+ "--u-nav-hover-bg": T("text-color", "title", "a", "8"),
199
+ "--u-nav-hover-color": T("text-color", "title"),
200
+ "--u-nav-active-bg": T("color", "primary", "a", "22"),
201
+ "--u-nav-active-color": T("color", "primary"),
202
+ "--u-nav-strong-color": T("text-color", "title"),
203
+ "--u-nav-second-color": T("text-color", "second"),
204
+ "--u-nav-sub-border-color": T("border", "color", "a", "52"),
205
+ "--u-nav-rail-bg": T("bg-color", "middle")
206
+ };
207
+ const navSidebarCssVars = {
208
+ light: {
209
+ dark: navSidebarDarkInLight,
210
+ light: navSidebarLightInLight
211
+ },
212
+ dark: {
213
+ dark: navSidebarDarkInDark,
214
+ light: navSidebarLightInDark
215
+ }
216
+ };
217
+ /** 某主题系列 + 侧栏变体下的 nav 外观 token(键为 `--u-nav-*`) */
218
+ function navSidebarTokens(series, variant) {
219
+ return { ...navSidebarCssVars[series][variant] };
220
+ }
221
+ /** 解析某主题系列 + 侧栏变体下的 nav 外观 token 声明列表 */
222
+ function resolveNavSidebarDecls(series, variant) {
223
+ return recordToDeclList(navSidebarCssVars[series][variant]);
224
+ }
165
225
  //#endregion
166
- export { componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, themeTokenVar };
226
+ export { componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, navSidebarTokens, resolveNavSidebarDecls, themeTokenVar };
167
227
 
168
228
  //# 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 */\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-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 '--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-height-small': '32px',\n '--u-nav-height-default': '36px',\n '--u-nav-height-large': '40px',\n '--u-nav-bg-color': T('bg-color', 'top'),\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\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 // ─── 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-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-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-bg-color': T('bg-color', 'middle'),\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 // ─── 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"],"mappings":";;;;;;AAMA,SAAgB,cAAc,UAAkB,GAAG,OAAuC;CAExF,OAAO,WAAW,WADH,MAAM,SAAS,IAAI,MAAM,IAAI,MAAM,CAAC,CAAC,KAAK,GAAG,MAAM,GAC9B;AACtC;AAEA,MAAM,IAAI;;AAGV,MAAa,wBAAgD;CAC3D,kBAAkB,aAAa,EAAE,SAAS,WAAW,KAAK,IAAI;CAC9D,0BAA0B,EAAE,UAAU,OAAO;CAC7C,uBAAuB,EAAE,YAAY,OAAO;CAC5C,0BAA0B,EAAE,cAAc,OAAO;CACjD,uBAAuB,EAAE,YAAY,QAAQ;CAC7C,0BAA0B;CAC1B,sBAAsB,EAAE,YAAY,OAAO;CAC3C,yBAAyB;CACzB,wBAAwB,EAAE,YAAY,OAAO;CAC7C,2BAA2B;CAC3B,wBAAwB,EAAE,SAAS,WAAW,SAAS;CACvD,2BAA2B;CAC3B,iBAAiB,EAAE,cAAc,OAAO;CACxC,oBAAoB,EAAE,cAAc,SAAS,KAAK,GAAG;CACrD,uBAAuB,EAAE,cAAc,OAAO;CAC9C,qBAAqB,EAAE,SAAS,WAAW,KAAK,IAAI;CACpD,wBAAwB,EAAE,SAAS,WAAW,QAAQ,GAAG;CACzD,wBAAwB;CACxB,0BAA0B;CAC1B,wBAAwB;CACxB,oBAAoB,EAAE,YAAY,KAAK;CACvC,oBAAoB;CACpB,sBAAsB;CACtB,8BAA8B;CAC9B,iBAAiB;CACjB,mBAAmB;CACnB,iBAAiB;CACjB,2BAA2B;CAC3B,6BAA6B;CAC7B,2BAA2B;CAC3B,wBAAwB;CACxB,0BAA0B;CAC1B,wBAAwB;CAGxB,yBAAyB,EAAE,YAAY,KAAK;CAC5C,6BAA6B,EAAE,UAAU,OAAO;CAChD,4BAA4B,EAAE,cAAc,MAAM;CAClD,+BAA+B,EAAE,YAAY,OAAO;CACpD,mCAAmC,EAAE,UAAU,OAAO;CACtD,+BAA+B,EAAE,SAAS,WAAW,SAAS,GAAG;CACjE,mCAAmC,EAAE,SAAS,WAAW,SAAS,GAAG;CACrE,+BAA+B,EAAE,SAAS,WAAW,SAAS,GAAG;CACjE,mCAAmC,EAAE,SAAS,WAAW,SAAS,GAAG;CACrE,+BAA+B,EAAE,SAAS,WAAW,SAAS,GAAG;CACjE,mCAAmC,EAAE,SAAS,WAAW,SAAS,GAAG;CACrE,8BAA8B,EAAE,SAAS,UAAU,SAAS,GAAG;CAC/D,kCAAkC,EAAE,SAAS,UAAU,SAAS,GAAG;CACnE,4BAA4B,EAAE,SAAS,QAAQ,SAAS,GAAG;CAC3D,gCAAgC,EAAE,SAAS,QAAQ,SAAS,GAAG;CAG/D,6BAA6B,EAAE,SAAS,WAAW,SAAS,GAAG;CAC/D,gCAAgC,EAAE,SAAS,SAAS;CAGpD,8BAA8B,EAAE,SAAS,WAAW,SAAS,GAAG;CAChE,iCAAiC,EAAE,SAAS,SAAS;CAGrD,iCAAiC,EAAE,SAAS,WAAW,SAAS,GAAG;CACnE,oCAAoC,EAAE,SAAS,SAAS;CAGxD,8BAA8B,EAAE,SAAS,WAAW,SAAS,GAAG;CAChE,iCAAiC,EAAE,cAAc,OAAO;CACxD,+BAA+B,EAAE,SAAS,WAAW,SAAS,GAAG;CACjE,kCAAkC,EAAE,SAAS,SAAS;CAGtD,mBAAmB,EAAE,YAAY,OAAO;CACxC,sBAAsB,EAAE,YAAY,KAAK;CAGzC,sBAAsB,EAAE,SAAS,WAAW,SAAS,GAAG;CACxD,yBAAyB,EAAE,SAAS,SAAS;CAC7C,0BAA0B,EAAE,SAAS,SAAS;CAC9C,sBAAsB,EAAE,SAAS,WAAW,SAAS,GAAG;CACxD,yBAAyB,EAAE,SAAS,SAAS;CAC7C,0BAA0B,EAAE,SAAS,SAAS;CAC9C,sBAAsB,EAAE,SAAS,WAAW,SAAS,GAAG;CACxD,yBAAyB,EAAE,SAAS,SAAS;CAC7C,0BAA0B,EAAE,SAAS,SAAS;CAC9C,qBAAqB,EAAE,SAAS,UAAU,SAAS,GAAG;CACtD,wBAAwB,EAAE,SAAS,QAAQ;CAC3C,yBAAyB,EAAE,SAAS,QAAQ;CAC5C,mBAAmB,EAAE,SAAS,QAAQ,SAAS,GAAG;CAClD,sBAAsB,EAAE,SAAS,MAAM;CACvC,uBAAuB,EAAE,SAAS,MAAM;CAGxC,4BAA4B,EAAE,SAAS,WAAW,SAAS,GAAG;CAC9D,sBAAsB;CACtB,sBAAsB;CACtB,0BAA0B;CAC1B,4BAA4B;CAC5B,0BAA0B;CAC1B,mBAAmB,EAAE,UAAU,OAAO;AACxC;;AAGA,MAAa,uBAA+C;CAC1D,GAAG;CACH,kBAAkB,aAAa,EAAE,SAAS,WAAW,KAAK,IAAI;CAC9D,0BAA0B,EAAE,UAAU,OAAO;CAC7C,uBAAuB,EAAE,YAAY,OAAO;CAC5C,0BAA0B,EAAE,cAAc,MAAM;CAChD,uBAAuB,EAAE,YAAY,QAAQ;CAC7C,0BAA0B,EAAE,cAAc,MAAM;CAChD,sBAAsB,EAAE,cAAc,SAAS,KAAK,GAAG;CACvD,yBAAyB,EAAE,cAAc,OAAO;CAChD,wBAAwB,EAAE,YAAY,OAAO;CAC7C,2BAA2B;CAC3B,wBAAwB,EAAE,SAAS,WAAW,QAAQ,GAAG;CACzD,2BAA2B;CAC3B,iBAAiB,EAAE,cAAc,MAAM;CACvC,oBAAoB,EAAE,cAAc,SAAS,KAAK,GAAG;CACrD,uBAAuB,EAAE,cAAc,OAAO;CAC9C,qBAAqB,EAAE,SAAS,WAAW,KAAK,IAAI;CACpD,wBAAwB,EAAE,cAAc,OAAO;CAC/C,oBAAoB,EAAE,YAAY,QAAQ;CAC1C,oBAAoB;CACpB,uBAAuB;CAGvB,+BAA+B,EAAE,SAAS,WAAW,QAAQ,GAAG;CAChE,mCAAmC,EAAE,SAAS,WAAW,QAAQ,GAAG;CACpE,+BAA+B,EAAE,SAAS,WAAW,QAAQ,GAAG;CAChE,mCAAmC,EAAE,SAAS,WAAW,QAAQ,GAAG;CACpE,+BAA+B,EAAE,SAAS,WAAW,QAAQ,GAAG;CAChE,mCAAmC,EAAE,SAAS,WAAW,QAAQ,GAAG;CACpE,8BAA8B,EAAE,SAAS,UAAU,QAAQ,GAAG;CAC9D,kCAAkC,EAAE,SAAS,UAAU,QAAQ,GAAG;CAClE,4BAA4B,EAAE,SAAS,QAAQ,QAAQ,GAAG;CAC1D,gCAAgC,EAAE,SAAS,QAAQ,QAAQ,GAAG;CAG9D,6BAA6B,EAAE,SAAS,WAAW,QAAQ,GAAG;CAC9D,gCAAgC,EAAE,SAAS,SAAS;CAGpD,8BAA8B,EAAE,SAAS,WAAW,QAAQ,GAAG;CAC/D,iCAAiC,EAAE,SAAS,SAAS;CAGrD,iCAAiC,EAAE,SAAS,WAAW,QAAQ,GAAG;CAClE,oCAAoC,EAAE,SAAS,SAAS;CAGxD,8BAA8B,EAAE,SAAS,WAAW,QAAQ,GAAG;CAC/D,iCAAiC,EAAE,SAAS,SAAS;CACrD,+BAA+B,EAAE,SAAS,WAAW,QAAQ,GAAG;CAChE,kCAAkC,EAAE,SAAS,SAAS;CAGtD,mBAAmB,EAAE,YAAY,QAAQ;CACzC,sBAAsB,EAAE,YAAY,KAAK;CAGzC,sBAAsB,EAAE,SAAS,WAAW,QAAQ,GAAG;CACvD,yBAAyB,EAAE,SAAS,SAAS;CAC7C,0BAA0B,EAAE,SAAS,SAAS;CAC9C,sBAAsB,EAAE,SAAS,WAAW,QAAQ,GAAG;CACvD,yBAAyB,EAAE,SAAS,SAAS;CAC7C,0BAA0B,EAAE,SAAS,SAAS;CAC9C,sBAAsB,EAAE,SAAS,WAAW,QAAQ,GAAG;CACvD,yBAAyB,EAAE,SAAS,SAAS;CAC7C,0BAA0B,EAAE,SAAS,SAAS;CAC9C,qBAAqB,EAAE,SAAS,UAAU,QAAQ,GAAG;CACrD,wBAAwB,EAAE,SAAS,QAAQ;CAC3C,yBAAyB,EAAE,SAAS,QAAQ;CAC5C,mBAAmB,EAAE,SAAS,QAAQ,QAAQ,GAAG;CACjD,sBAAsB,EAAE,SAAS,MAAM;CACvC,uBAAuB,EAAE,SAAS,MAAM;CAGxC,4BAA4B,EAAE,SAAS,WAAW,QAAQ,GAAG;CAC7D,sBAAsB;CACtB,sBAAsB;AACxB;AAEA,SAAS,iBAAiB,QAA0C;CAClE,OAAO,OAAO,QAAQ,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,GAAG,EAAE,IAAI,GAAG;AAC5D;AAEA,MAAa,6BAAuC,iBAAiB,qBAAqB;AAE1F,MAAa,4BAAsC,iBAAiB,oBAAoB"}
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-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\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 // ─── 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-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 // ─── 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,4 +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
3
  import { ThemeSeries, UITheme, UIThemeOptions } from "./ui-theme.js";
3
4
  import { lightTheme } from "./presets/light.js";
4
5
  import { darkTheme } from "./presets/dark.js";
@@ -11,4 +12,4 @@ import { midnightTheme } from "./presets/midnight.js";
11
12
  import { neonTheme } from "./presets/neon.js";
12
13
  import { currentTheme, loadTheme } from "./load-theme.js";
13
14
  import { HEXToRGB, cssVar, defineBySize, hexRgbOnly, hexWithAlpha, isHexColor, mixColor, mixColorWithAlpha } from "./helper.js";
14
- export { HEXToRGB, type RGBColor, type Theme, ThemeSeries, UITheme, UIThemeOptions, ancientTheme, cssVar, currentTheme, darkTheme, defineBySize, glassTheme, heroTheme, hexRgbOnly, hexWithAlpha, isHexColor, lightTheme, loadTheme, midnightTheme, mixColor, mixColorWithAlpha, neonTheme, oceanTheme, sakuraTheme };
15
+ 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 };
@@ -1,3 +1,4 @@
1
+ import { componentCssVarsDark, componentCssVarsDarkDecls, componentCssVarsLight, componentCssVarsLightDecls, navSidebarTokens, resolveNavSidebarDecls, themeTokenVar } from "./component-css-vars.js";
1
2
  import { HEXToRGB, cssVar, defineBySize, hexRgbOnly, hexWithAlpha, isHexColor, mixColor, mixColorWithAlpha } from "./helper.js";
2
3
  import { UITheme } from "./ui-theme.js";
3
4
  import { lightTheme } from "./presets/light.js";
@@ -10,4 +11,4 @@ import { oceanTheme } from "./presets/ocean.js";
10
11
  import { midnightTheme } from "./presets/midnight.js";
11
12
  import { neonTheme } from "./presets/neon.js";
12
13
  import { currentTheme, loadTheme } from "./load-theme.js";
13
- export { HEXToRGB, UITheme, ancientTheme, cssVar, currentTheme, darkTheme, defineBySize, glassTheme, heroTheme, hexRgbOnly, hexWithAlpha, isHexColor, lightTheme, loadTheme, midnightTheme, mixColor, mixColorWithAlpha, neonTheme, oceanTheme, sakuraTheme };
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 };
@@ -1,3 +1,4 @@
1
+ import { mixColor } from "../helper.js";
1
2
  import { lightTheme } from "./light.js";
2
3
  //#region src/theme/presets/ancient.ts
3
4
  /** 古风(松烟绿 + 宣纸底),天生适合浅色 */
@@ -32,7 +33,8 @@ const ancientTheme = lightTheme.new({
32
33
  y: 4,
33
34
  blur: 16,
34
35
  spread: -2
35
- }
36
+ },
37
+ nav: { "bg-color": mixColor("#2b2a26", "#3d6b58", .28) }
36
38
  });
37
39
  //#endregion
38
40
  export { ancientTheme };
@@ -1 +1 @@
1
- {"version":3,"file":"ancient.js","names":[],"sources":["../../../src/theme/presets/ancient.ts"],"sourcesContent":["import { 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})\n"],"mappings":";;;AAGA,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;AAC9E,CAAC"}
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 // 松烟墨侧栏:黛墨 + 松烟绿调和\n '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,YAAY,SAAS,WAAW,WAAW,GAAI,EACjD;AACF,CAAC"}
@@ -38,7 +38,8 @@ const heroTheme = lightTheme.new({
38
38
  spread: 0,
39
39
  emboss: "0 2px 4px 0 #0000000a,0 1px 2px 0 #0000000f,0 0 3px 0px #0000000f"
40
40
  },
41
- button: { "default-bg": "#ebebec" }
41
+ button: { "default-bg": "#ebebec" },
42
+ nav: { variant: "light" }
42
43
  });
43
44
  //#endregion
44
45
  export { heroTheme };
@@ -1 +1 @@
1
- {"version":3,"file":"hero.js","names":[],"sources":["../../../src/theme/presets/hero.ts"],"sourcesContent":["import { lightTheme } from './light'\n\n/** HeroUI 风格,天生适合浅色 */\nexport const heroTheme = lightTheme.new({\n color: {\n primary: '#7828c8', // purple\n success: '#17c964',\n warning: '#f5a524',\n danger: '#f31260',\n info: '#006fee',\n disabled: '#f4f4f5',\n default: '#f4f4f5'\n },\n border: { width: 2, color: '#dcdfe6', mutedColor: '#e4e4e7' },\n 'text-color': {\n title: '#11181C',\n main: '#11181C',\n second: '#71717A',\n placeholder: '#A1A1AA',\n assist: '#A1A1AA',\n disabled: '#A1A1AA',\n white: '#FFFFFF'\n },\n radius: { small: 8, default: 12, large: 14 },\n shadow: {\n color: '#00000014',\n x: 0,\n y: 4,\n blur: 14,\n spread: 0,\n emboss: '0 2px 4px 0 #0000000a,0 1px 2px 0 #0000000f,0 0 3px 0px #0000000f'\n },\n button: { 'default-bg': '#ebebec' }\n})\n"],"mappings":";;;AAGA,MAAa,YAAY,WAAW,IAAI;CACtC,OAAO;EACL,SAAS;EACT,SAAS;EACT,SAAS;EACT,QAAQ;EACR,MAAM;EACN,UAAU;EACV,SAAS;CACX;CACA,QAAQ;EAAE,OAAO;EAAG,OAAO;EAAW,YAAY;CAAU;CAC5D,cAAc;EACZ,OAAO;EACP,MAAM;EACN,QAAQ;EACR,aAAa;EACb,QAAQ;EACR,UAAU;EACV,OAAO;CACT;CACA,QAAQ;EAAE,OAAO;EAAG,SAAS;EAAI,OAAO;CAAG;CAC3C,QAAQ;EACN,OAAO;EACP,GAAG;EACH,GAAG;EACH,MAAM;EACN,QAAQ;EACR,QAAQ;CACV;CACA,QAAQ,EAAE,cAAc,UAAU;AACpC,CAAC"}
1
+ {"version":3,"file":"hero.js","names":[],"sources":["../../../src/theme/presets/hero.ts"],"sourcesContent":["import { lightTheme } from './light'\n\n/** HeroUI 风格,天生适合浅色 */\nexport const heroTheme = lightTheme.new({\n color: {\n primary: '#7828c8', // purple\n success: '#17c964',\n warning: '#f5a524',\n danger: '#f31260',\n info: '#006fee',\n disabled: '#f4f4f5',\n default: '#f4f4f5'\n },\n border: { width: 2, color: '#dcdfe6', mutedColor: '#e4e4e7' },\n 'text-color': {\n title: '#11181C',\n main: '#11181C',\n second: '#71717A',\n placeholder: '#A1A1AA',\n assist: '#A1A1AA',\n disabled: '#A1A1AA',\n white: '#FFFFFF'\n },\n radius: { small: 8, default: 12, large: 14 },\n shadow: {\n color: '#00000014',\n x: 0,\n y: 4,\n blur: 14,\n spread: 0,\n emboss: '0 2px 4px 0 #0000000a,0 1px 2px 0 #0000000f,0 0 3px 0px #0000000f'\n },\n button: { 'default-bg': '#ebebec' },\n // HeroUI 风浅灰侧栏(演示浅色变体)\n nav: { variant: 'light' }\n})\n"],"mappings":";;;AAGA,MAAa,YAAY,WAAW,IAAI;CACtC,OAAO;EACL,SAAS;EACT,SAAS;EACT,SAAS;EACT,QAAQ;EACR,MAAM;EACN,UAAU;EACV,SAAS;CACX;CACA,QAAQ;EAAE,OAAO;EAAG,OAAO;EAAW,YAAY;CAAU;CAC5D,cAAc;EACZ,OAAO;EACP,MAAM;EACN,QAAQ;EACR,aAAa;EACb,QAAQ;EACR,UAAU;EACV,OAAO;CACT;CACA,QAAQ;EAAE,OAAO;EAAG,SAAS;EAAI,OAAO;CAAG;CAC3C,QAAQ;EACN,OAAO;EACP,GAAG;EACH,GAAG;EACH,MAAM;EACN,QAAQ;EACR,QAAQ;CACV;CACA,QAAQ,EAAE,cAAc,UAAU;CAElC,KAAK,EAAE,SAAS,QAAQ;AAC1B,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { mixColor } from "../helper.js";
1
2
  import { lightTheme } from "./light.js";
2
3
  //#region src/theme/presets/ocean.ts
3
4
  /** 海盐(松石青 + 冷白底,利落的快缓动),天生适合浅色 */
@@ -47,7 +48,8 @@ const oceanTheme = lightTheme.new({
47
48
  transition: {
48
49
  fast: "0.12s",
49
50
  ease: "cubic-bezier(0.22, 1, 0.36, 1)"
50
- }
51
+ },
52
+ nav: { "bg-color": mixColor("#16302e", "#0d9488", .25) }
51
53
  });
52
54
  //#endregion
53
55
  export { oceanTheme };
@@ -1 +1 @@
1
- {"version":3,"file":"ocean.js","names":[],"sources":["../../../src/theme/presets/ocean.ts"],"sourcesContent":["import { 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})\n"],"mappings":";;;AAGA,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;AACtE,CAAC"}
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 // 深海礁侧栏:深礁 + 松石青调和\n '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,YAAY,SAAS,WAAW,WAAW,GAAI,EACjD;AACF,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { mixColor } from "../helper.js";
1
2
  import { lightTheme } from "./light.js";
2
3
  //#region src/theme/presets/sakura.ts
3
4
  /** 樱花(柔粉 + 花瓣底,大圆角、弹性缓动),天生适合浅色 */
@@ -49,7 +50,8 @@ const sakuraTheme = lightTheme.new({
49
50
  sm: "0 1px 2px 0 rgba(173, 58, 105, 0.08)",
50
51
  lg: "0 8px 24px 0 rgba(173, 58, 105, 0.14), 0 2px 6px 0 rgba(173, 58, 105, 0.08)"
51
52
  },
52
- transition: { easeOut: "cubic-bezier(0.34, 1.56, 0.64, 1)" }
53
+ transition: { easeOut: "cubic-bezier(0.34, 1.56, 0.64, 1)" },
54
+ nav: { "bg-color": mixColor("#43272f", "#e64980", .22) }
53
55
  });
54
56
  //#endregion
55
57
  export { sakuraTheme };
@@ -1 +1 @@
1
- {"version":3,"file":"sakura.js","names":[],"sources":["../../../src/theme/presets/sakura.ts"],"sourcesContent":["import { 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})\n"],"mappings":";;;AAGA,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;AAC7D,CAAC"}
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 // 深酒红侧栏:樱墨 + 樱粉调和\n '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,YAAY,SAAS,WAAW,WAAW,GAAI,EACjD;AACF,CAAC"}
@@ -176,6 +176,16 @@ type Theme = {
176
176
  'default-bg'?: string;
177
177
  [key: string]: any;
178
178
  };
179
+ /**
180
+ * 侧栏导航(nav / dual-nav / group-nav)组件级变量。
181
+ * variant 选择深/浅侧栏外观,其余键覆盖同名 `--u-nav-*` token
182
+ * (如 `'bg-color'` → `--u-nav-bg-color`),覆盖优先级高于 variant 内置值。
183
+ */
184
+ nav?: {
185
+ /** 侧栏外观:dark 深底浅字 / light 浅底深字,默认 dark */
186
+ variant?: 'dark' | 'light';
187
+ [key: string]: any;
188
+ };
179
189
  /** 折叠面板组件级变量 */
180
190
  collapse?: {
181
191
  /** 折叠项标题文字颜色 */
@@ -30,9 +30,14 @@ declare class UITheme {
30
30
  /** 主题变量声明列表,均为 `--u-` 前缀的 CSS 自定义属性 */
31
31
  themeToDeclarationList(theme: Theme): string[];
32
32
  private static declarationBlock;
33
+ /**
34
+ * nav 侧栏外观声明:按主题 `nav.variant`(默认 dark)取内置深/浅侧栏 token,
35
+ * 主题 `nav` 的其余键作为 `--u-nav-*` 覆盖追加在最后(同规则后者生效)。
36
+ */
37
+ navSidebarDecls(theme: Theme): string[];
33
38
  private static removeExistingStyleTag;
34
39
  private static applyGlobalCSS;
35
- /** 注入主题:全局 token + 与主题系列匹配的组件级 token,并写入 html[data-theme] */
40
+ /** 注入主题:全局 token + 与主题系列匹配的组件级 token + nav 侧栏外观,并写入 html[data-theme] */
36
41
  render(): void;
37
42
  new(customTheme?: RecursivePartial<Theme>, options?: {
38
43
  series?: ThemeSeries;
@@ -1,4 +1,4 @@
1
- import { componentCssVarsDarkDecls, componentCssVarsLightDecls } from "./component-css-vars.js";
1
+ import { componentCssVarsDarkDecls, componentCssVarsLightDecls, 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";
@@ -19,6 +19,7 @@ var UITheme = class UITheme {
19
19
  }
20
20
  renderBase(theme, themeRules = [], parentKey = "--u") {
21
21
  Object.keys(theme).forEach((key) => {
22
+ if (parentKey === "--u" && key === "nav") return;
22
23
  const value = theme[key];
23
24
  const varKey = `${parentKey.startsWith("-") ? parentKey : str(parentKey).kebabCase()}-${str(key).kebabCase()}`;
24
25
  if (typeof value === "object" && value !== null && !Array.isArray(value)) this.renderBase(value, themeRules, varKey);
@@ -157,6 +158,17 @@ var UITheme = class UITheme {
157
158
  static declarationBlock(decls) {
158
159
  return decls.join(";");
159
160
  }
161
+ /**
162
+ * nav 侧栏外观声明:按主题 `nav.variant`(默认 dark)取内置深/浅侧栏 token,
163
+ * 主题 `nav` 的其余键作为 `--u-nav-*` 覆盖追加在最后(同规则后者生效)。
164
+ */
165
+ navSidebarDecls(theme) {
166
+ const nav = theme.nav ?? {};
167
+ const variant = nav.variant === "light" ? "light" : "dark";
168
+ const decls = resolveNavSidebarDecls(this.series, variant);
169
+ const overrides = Object.keys(nav).filter((key) => key !== "variant" && typeof nav[key] === "string" && nav[key]).map((key) => `--u-nav-${str(key).kebabCase()}: ${nav[key]}`);
170
+ return [...decls, ...overrides];
171
+ }
160
172
  static removeExistingStyleTag(doc) {
161
173
  const el = doc.getElementById(UITheme.themeID);
162
174
  if (el?.parentNode) el.parentNode.removeChild(el);
@@ -182,10 +194,15 @@ var UITheme = class UITheme {
182
194
  style.textContent = css;
183
195
  }
184
196
  }
185
- /** 注入主题:全局 token + 与主题系列匹配的组件级 token,并写入 html[data-theme] */
197
+ /** 注入主题:全局 token + 与主题系列匹配的组件级 token + nav 侧栏外观,并写入 html[data-theme] */
186
198
  render() {
187
199
  const componentDecls = this.series === "dark" ? componentCssVarsDarkDecls : componentCssVarsLightDecls;
188
- const decls = [...this.themeToDeclarationList(toRaw(this.theme)), ...componentDecls];
200
+ const raw = toRaw(this.theme);
201
+ const decls = [
202
+ ...this.themeToDeclarationList(raw),
203
+ ...componentDecls,
204
+ ...this.navSidebarDecls(raw)
205
+ ];
189
206
  const css = `html { ${UITheme.declarationBlock(decls)} }`;
190
207
  UITheme.applyGlobalCSS(css);
191
208
  if (typeof document !== "undefined") document.documentElement.dataset.theme = this.series;
@@ -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 { componentCssVarsDarkDecls, componentCssVarsLightDecls } 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 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 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,并写入 html[data-theme] */\n render(): void {\n const componentDecls =\n this.series === 'dark' ? componentCssVarsDarkDecls : componentCssVarsLightDecls\n const decls = [...this.themeToDeclarationList(toRaw(this.theme)), ...componentDecls]\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 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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veltra/styles",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "homepage": "https://github.com/cabinet-fe/ultra-ui#readme",
5
5
  "bugs": {
6
6
  "url": "https://github.com/cabinet-fe/ultra-ui/issues"
@@ -51,8 +51,8 @@
51
51
  },
52
52
  "peerDependencies": {
53
53
  "@cat-kit/core": ">=1.1.8",
54
- "@veltra/compositions": "^1.7.0",
55
- "@veltra/utils": "^1.7.0",
54
+ "@veltra/compositions": "^1.7.1",
55
+ "@veltra/utils": "^1.7.1",
56
56
  "vue": ">=3.5.41"
57
57
  }
58
58
  }
@@ -82,6 +82,48 @@ describe('UITheme', () => {
82
82
  expect(componentCssVarsDark['--u-focus-ring']).toContain('--u-color-primary-a-')
83
83
  })
84
84
 
85
+ it('nav sidebar defaults to dark variant, resolved per series', () => {
86
+ // light 系列:深底(text-color.title)+ 浅前景,与浅色内容区拉开区分度
87
+ const lightDecls = lightTheme.navSidebarDecls(lightTheme.theme)
88
+ expect(lightDecls).toContain('--u-nav-bg-color: var(--u-text-color-title)')
89
+ expect(lightDecls).toContain('--u-nav-color: rgba(255, 255, 255, 0.72)')
90
+ // dark 系列:侧栏比内容区 top 深一档
91
+ const darkDecls = darkTheme.navSidebarDecls(darkTheme.theme)
92
+ expect(darkDecls).toContain('--u-nav-bg-color: var(--u-bg-color-middle)')
93
+ expect(darkDecls).toContain('--u-nav-color: var(--u-text-color-main)')
94
+ })
95
+
96
+ it('nav variant light switches to light sidebar tokens', () => {
97
+ const t = lightTheme.new({ nav: { variant: 'light' } })
98
+ const decls = t.navSidebarDecls(t.theme)
99
+ expect(decls).toContain('--u-nav-bg-color: var(--u-bg-color-middle)')
100
+ expect(decls).toContain('--u-nav-color: var(--u-text-color-title)')
101
+ })
102
+
103
+ it('hero preset defaults to light sidebar variant', () => {
104
+ const decls = heroTheme.navSidebarDecls(heroTheme.theme)
105
+ expect(decls).toContain('--u-nav-bg-color: var(--u-bg-color-middle)')
106
+ })
107
+
108
+ it('theme.nav overrides are appended after variant defaults and win', () => {
109
+ const t = lightTheme.new({ nav: { 'bg-color': '#123456' } })
110
+ const decls = t.navSidebarDecls(t.theme)
111
+ const bgDecls = decls.filter((d) => d.startsWith('--u-nav-bg-color:'))
112
+ expect(bgDecls.length).toBe(2)
113
+ expect(bgDecls[1]).toBe('--u-nav-bg-color: #123456')
114
+ })
115
+
116
+ it('renderBase skips the nav subtree (handled by navSidebarDecls)', () => {
117
+ const decls = sakuraTheme.themeToDeclarationList(sakuraTheme.theme)
118
+ expect(decls.some((d) => d.startsWith('--u-nav-'))).toBe(false)
119
+ })
120
+
121
+ it('sakura / ocean / ancient have themed dark sidebar colors', () => {
122
+ expect(sakuraTheme.navSidebarDecls(sakuraTheme.theme)).toContain('--u-nav-bg-color: #662e40')
123
+ expect(oceanTheme.navSidebarDecls(oceanTheme.theme)).toContain('--u-nav-bg-color: #134944')
124
+ expect(ancientTheme.navSidebarDecls(ancientTheme.theme)).toContain('--u-nav-bg-color: #303c34')
125
+ })
126
+
85
127
  it('no preset emits invalid NaN declarations', () => {
86
128
  const themes = [
87
129
  lightTheme,
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * 桌面组件级 `--u-*` token,随 `UITheme.render()` 按主题系列(light/dark)注入 `html`。
3
3
  * 修改此处即可在 TS 侧统一调整组件外观,无需在各组件 `style.scss` 重复声明。
4
+ * nav 系列:外观(底色/前景)不在此列表,由 `navSidebarCssVars` 按主题 `nav.variant`
5
+ * (dark 深底浅字 / light 浅底深字,默认 dark)与 `nav` 覆盖项注入,见 `ui-theme.ts`。
4
6
  */
5
7
 
6
8
  /** 与 SCSS `fn.use-var($basename, $nodes...)` 输出一致 */
@@ -25,15 +27,10 @@ export const componentCssVarsLight: Record<string, string> = {
25
27
  '--u-table-current-color': 'inherit',
26
28
  '--u-table-checked-bg': T('color', 'primary', 'light-9'),
27
29
  '--u-table-checked-color': 'inherit',
28
- '--u-nav-color': T('text-color', 'title'),
29
- '--u-nav-hover-bg': T('text-color', 'title', 'a', '8'),
30
- '--u-nav-hover-color': T('text-color', 'title'),
31
- '--u-nav-active-bg': T('color', 'primary', 'a', '10'),
32
- '--u-nav-active-color': T('color', 'primary', 'dark', '1'),
30
+ // ─── Nav 系列(nav / dual-nav / group-nav)尺寸与资源类;外观见文件底部 navSidebarCssVars ───
33
31
  '--u-nav-height-small': '32px',
34
32
  '--u-nav-height-default': '36px',
35
33
  '--u-nav-height-large': '40px',
36
- '--u-nav-bg-color': T('bg-color', 'top'),
37
34
  '--u-nav-bg-image': 'none',
38
35
  '--u-nav-rail-width': '56px',
39
36
  '--u-nav-rail-labeled-width': '72px',
@@ -128,12 +125,6 @@ export const componentCssVarsDark: Record<string, string> = {
128
125
  '--u-table-current-color': 'inherit',
129
126
  '--u-table-checked-bg': T('color', 'primary', 'dark', '1'),
130
127
  '--u-table-checked-color': 'inherit',
131
- '--u-nav-color': T('text-color', 'main'),
132
- '--u-nav-hover-bg': T('text-color', 'title', 'a', '8'),
133
- '--u-nav-hover-color': T('text-color', 'title'),
134
- '--u-nav-active-bg': T('color', 'primary', 'a', '16'),
135
- '--u-nav-active-color': T('text-color', 'white'),
136
- '--u-nav-bg-color': T('bg-color', 'middle'),
137
128
  '--u-radio-border': '#595959',
138
129
  '--u-checkbox-border': '#595959',
139
130
 
@@ -201,3 +192,89 @@ function recordToDeclList(record: Record<string, string>): string[] {
201
192
  export const componentCssVarsLightDecls: string[] = recordToDeclList(componentCssVarsLight)
202
193
 
203
194
  export const componentCssVarsDarkDecls: string[] = recordToDeclList(componentCssVarsDark)
195
+
196
+ // ─── Nav 侧栏外观:深/浅变体 × 明/暗主题系列 ───
197
+ // 由 UITheme 按主题 `nav.variant`(默认 dark)选择注入,主题 `nav` 的其余键可逐项覆盖。
198
+
199
+ /** 侧栏外观变体:dark 深底浅字 / light 浅底深字 */
200
+ export type NavSidebarVariant = 'dark' | 'light'
201
+
202
+ /** 深侧栏 · 浅色主题下:深底(text-color.title)+ 浅前景,与浅色内容区拉开区分度 */
203
+ const navSidebarDarkInLight: Record<string, string> = {
204
+ '--u-nav-bg-color': T('text-color', 'title'),
205
+ '--u-nav-color': 'rgba(255, 255, 255, 0.72)',
206
+ '--u-nav-hover-bg': 'rgba(255, 255, 255, 0.08)',
207
+ '--u-nav-hover-color': T('text-color', 'white'),
208
+ '--u-nav-active-bg': T('color', 'primary', 'a', '22'),
209
+ '--u-nav-active-color': T('text-color', 'white'),
210
+ '--u-nav-strong-color': T('text-color', 'white'),
211
+ '--u-nav-second-color': 'rgba(255, 255, 255, 0.45)',
212
+ '--u-nav-sub-border-color': 'rgba(255, 255, 255, 0.15)',
213
+ '--u-nav-rail-bg': 'rgba(0, 0, 0, 0.2)'
214
+ }
215
+
216
+ /** 浅侧栏 · 浅色主题下:比内容区 top 低一档的浅底 + 深前景 */
217
+ const navSidebarLightInLight: Record<string, string> = {
218
+ '--u-nav-bg-color': T('bg-color', 'middle'),
219
+ '--u-nav-color': T('text-color', 'title'),
220
+ '--u-nav-hover-bg': T('text-color', 'title', 'a', '8'),
221
+ '--u-nav-hover-color': T('text-color', 'title'),
222
+ '--u-nav-active-bg': T('color', 'primary', 'a', '10'),
223
+ '--u-nav-active-color': T('color', 'primary', 'dark', '1'),
224
+ '--u-nav-strong-color': T('text-color', 'title'),
225
+ '--u-nav-second-color': T('text-color', 'second'),
226
+ '--u-nav-sub-border-color': T('border', 'color', 'a', '52'),
227
+ '--u-nav-rail-bg': T('bg-color', 'bottom')
228
+ }
229
+
230
+ /** 深侧栏 · 深色主题下:比内容区 top 深一档 */
231
+ const navSidebarDarkInDark: Record<string, string> = {
232
+ '--u-nav-bg-color': T('bg-color', 'middle'),
233
+ '--u-nav-color': T('text-color', 'main'),
234
+ '--u-nav-hover-bg': T('text-color', 'title', 'a', '8'),
235
+ '--u-nav-hover-color': T('text-color', 'title'),
236
+ '--u-nav-active-bg': T('color', 'primary', 'a', '16'),
237
+ '--u-nav-active-color': T('text-color', 'white'),
238
+ '--u-nav-strong-color': T('text-color', 'title'),
239
+ '--u-nav-second-color': T('text-color', 'second'),
240
+ '--u-nav-sub-border-color': T('border', 'color', 'a', '52'),
241
+ '--u-nav-rail-bg': T('bg-color', 'bottom')
242
+ }
243
+
244
+ /** 浅侧栏 · 深色主题下:提亮侧栏(与深色内容区反向对比) */
245
+ const navSidebarLightInDark: Record<string, string> = {
246
+ '--u-nav-bg-color': T('bg-color', 'top'),
247
+ '--u-nav-color': T('text-color', 'title'),
248
+ '--u-nav-hover-bg': T('text-color', 'title', 'a', '8'),
249
+ '--u-nav-hover-color': T('text-color', 'title'),
250
+ '--u-nav-active-bg': T('color', 'primary', 'a', '22'),
251
+ '--u-nav-active-color': T('color', 'primary'),
252
+ '--u-nav-strong-color': T('text-color', 'title'),
253
+ '--u-nav-second-color': T('text-color', 'second'),
254
+ '--u-nav-sub-border-color': T('border', 'color', 'a', '52'),
255
+ '--u-nav-rail-bg': T('bg-color', 'middle')
256
+ }
257
+
258
+ const navSidebarCssVars: Record<
259
+ 'light' | 'dark',
260
+ Record<NavSidebarVariant, Record<string, string>>
261
+ > = {
262
+ light: { dark: navSidebarDarkInLight, light: navSidebarLightInLight },
263
+ dark: { dark: navSidebarDarkInDark, light: navSidebarLightInDark }
264
+ }
265
+
266
+ /** 某主题系列 + 侧栏变体下的 nav 外观 token(键为 `--u-nav-*`) */
267
+ export function navSidebarTokens(
268
+ series: 'light' | 'dark',
269
+ variant: NavSidebarVariant
270
+ ): Record<string, string> {
271
+ return { ...navSidebarCssVars[series][variant] }
272
+ }
273
+
274
+ /** 解析某主题系列 + 侧栏变体下的 nav 外观 token 声明列表 */
275
+ export function resolveNavSidebarDecls(
276
+ series: 'light' | 'dark',
277
+ variant: NavSidebarVariant
278
+ ): string[] {
279
+ return recordToDeclList(navSidebarCssVars[series][variant])
280
+ }
@@ -1,5 +1,7 @@
1
1
  export type * from './type'
2
2
 
3
+ export * from './component-css-vars'
4
+
3
5
  export * from './ui-theme'
4
6
 
5
7
  export * from './presets'
@@ -1,3 +1,4 @@
1
+ import { mixColor } from '../helper'
1
2
  import { lightTheme } from './light'
2
3
 
3
4
  /** 古风(松烟绿 + 宣纸底),天生适合浅色 */
@@ -22,5 +23,9 @@ export const ancientTheme = lightTheme.new({
22
23
  },
23
24
  border: { width: 1, color: '#e4dcc8', mutedColor: '#d2c8ac' },
24
25
  radius: { small: 4, default: 8, large: 12 },
25
- shadow: { color: 'rgba(64, 54, 32, 0.14)', x: 0, y: 4, blur: 16, spread: -2 }
26
+ shadow: { color: 'rgba(64, 54, 32, 0.14)', x: 0, y: 4, blur: 16, spread: -2 },
27
+ nav: {
28
+ // 松烟墨侧栏:黛墨 + 松烟绿调和
29
+ 'bg-color': mixColor('#2b2a26', '#3d6b58', 0.28)
30
+ }
26
31
  })
@@ -30,5 +30,7 @@ export const heroTheme = lightTheme.new({
30
30
  spread: 0,
31
31
  emboss: '0 2px 4px 0 #0000000a,0 1px 2px 0 #0000000f,0 0 3px 0px #0000000f'
32
32
  },
33
- button: { 'default-bg': '#ebebec' }
33
+ button: { 'default-bg': '#ebebec' },
34
+ // HeroUI 风浅灰侧栏(演示浅色变体)
35
+ nav: { variant: 'light' }
34
36
  })
@@ -1,3 +1,4 @@
1
+ import { mixColor } from '../helper'
1
2
  import { lightTheme } from './light'
2
3
 
3
4
  /** 海盐(松石青 + 冷白底,利落的快缓动),天生适合浅色 */
@@ -31,5 +32,9 @@ export const oceanTheme = lightTheme.new({
31
32
  sm: '0 1px 2px 0 rgba(21, 94, 89, 0.08)',
32
33
  lg: '0 8px 24px 0 rgba(21, 94, 89, 0.12), 0 2px 6px 0 rgba(21, 94, 89, 0.06)'
33
34
  },
34
- transition: { fast: '0.12s', ease: 'cubic-bezier(0.22, 1, 0.36, 1)' }
35
+ transition: { fast: '0.12s', ease: 'cubic-bezier(0.22, 1, 0.36, 1)' },
36
+ nav: {
37
+ // 深海礁侧栏:深礁 + 松石青调和
38
+ 'bg-color': mixColor('#16302e', '#0d9488', 0.25)
39
+ }
35
40
  })
@@ -1,3 +1,4 @@
1
+ import { mixColor } from '../helper'
1
2
  import { lightTheme } from './light'
2
3
 
3
4
  /** 樱花(柔粉 + 花瓣底,大圆角、弹性缓动),天生适合浅色 */
@@ -33,5 +34,9 @@ export const sakuraTheme = lightTheme.new({
33
34
  sm: '0 1px 2px 0 rgba(173, 58, 105, 0.08)',
34
35
  lg: '0 8px 24px 0 rgba(173, 58, 105, 0.14), 0 2px 6px 0 rgba(173, 58, 105, 0.08)'
35
36
  },
36
- transition: { easeOut: 'cubic-bezier(0.34, 1.56, 0.64, 1)' }
37
+ transition: { easeOut: 'cubic-bezier(0.34, 1.56, 0.64, 1)' },
38
+ nav: {
39
+ // 深酒红侧栏:樱墨 + 樱粉调和
40
+ 'bg-color': mixColor('#43272f', '#e64980', 0.22)
41
+ }
37
42
  })
package/src/theme/type.ts CHANGED
@@ -180,6 +180,16 @@ export type Theme = {
180
180
  'default-bg'?: string
181
181
  [key: string]: any
182
182
  }
183
+ /**
184
+ * 侧栏导航(nav / dual-nav / group-nav)组件级变量。
185
+ * variant 选择深/浅侧栏外观,其余键覆盖同名 `--u-nav-*` token
186
+ * (如 `'bg-color'` → `--u-nav-bg-color`),覆盖优先级高于 variant 内置值。
187
+ */
188
+ nav?: {
189
+ /** 侧栏外观:dark 深底浅字 / light 浅底深字,默认 dark */
190
+ variant?: 'dark' | 'light'
191
+ [key: string]: any
192
+ }
183
193
  /** 折叠面板组件级变量 */
184
194
  collapse?: {
185
195
  /** 折叠项标题文字颜色 */
@@ -2,7 +2,12 @@ import { isObj, 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
+ import {
6
+ componentCssVarsDarkDecls,
7
+ componentCssVarsLightDecls,
8
+ resolveNavSidebarDecls,
9
+ type NavSidebarVariant
10
+ } from './component-css-vars'
6
11
  import { hexRgbOnly, hexWithAlpha, isHexColor, mixColor } from './helper'
7
12
  import type { Theme } from './type'
8
13
 
@@ -47,6 +52,8 @@ export class UITheme {
47
52
  parentKey = '--u'
48
53
  ): string[] {
49
54
  Object.keys(theme).forEach((key) => {
55
+ // nav 由 navSidebarDecls 按 variant + 覆盖项单独注入(须晚于组件级 token 才生效)
56
+ if (parentKey === '--u' && key === 'nav') return
50
57
  const value = theme[key]
51
58
  const varKey = `${parentKey.startsWith('-') ? parentKey : str(parentKey).kebabCase()}-${str(key).kebabCase()}`
52
59
  if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
@@ -236,6 +243,20 @@ export class UITheme {
236
243
  return decls.join(';')
237
244
  }
238
245
 
246
+ /**
247
+ * nav 侧栏外观声明:按主题 `nav.variant`(默认 dark)取内置深/浅侧栏 token,
248
+ * 主题 `nav` 的其余键作为 `--u-nav-*` 覆盖追加在最后(同规则后者生效)。
249
+ */
250
+ navSidebarDecls(theme: Theme): string[] {
251
+ const nav = theme.nav ?? {}
252
+ const variant: NavSidebarVariant = nav.variant === 'light' ? 'light' : 'dark'
253
+ const decls = resolveNavSidebarDecls(this.series, variant)
254
+ const overrides = Object.keys(nav)
255
+ .filter((key) => key !== 'variant' && typeof nav[key] === 'string' && nav[key])
256
+ .map((key) => `--u-nav-${str(key).kebabCase()}: ${nav[key]}`)
257
+ return [...decls, ...overrides]
258
+ }
259
+
239
260
  private static removeExistingStyleTag(doc: Document): void {
240
261
  const el = doc.getElementById(UITheme.themeID)
241
262
  if (el?.parentNode) {
@@ -271,11 +292,16 @@ export class UITheme {
271
292
  }
272
293
  }
273
294
 
274
- /** 注入主题:全局 token + 与主题系列匹配的组件级 token,并写入 html[data-theme] */
295
+ /** 注入主题:全局 token + 与主题系列匹配的组件级 token + nav 侧栏外观,并写入 html[data-theme] */
275
296
  render(): void {
276
297
  const componentDecls =
277
298
  this.series === 'dark' ? componentCssVarsDarkDecls : componentCssVarsLightDecls
278
- const decls = [...this.themeToDeclarationList(toRaw(this.theme)), ...componentDecls]
299
+ const raw = toRaw(this.theme)
300
+ const decls = [
301
+ ...this.themeToDeclarationList(raw),
302
+ ...componentDecls,
303
+ ...this.navSidebarDecls(raw)
304
+ ]
279
305
  const block = UITheme.declarationBlock(decls)
280
306
  const css = `html { ${block} }`
281
307
  UITheme.applyGlobalCSS(css)