@yh-ui/theme 1.0.52 → 1.0.54

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.cjs CHANGED
@@ -420,8 +420,9 @@ const colorBlindPalettes = exports.colorBlindPalettes = {
420
420
  const THEME_TRANSITION_CLASS = "yh-theme-transitioning";
421
421
  const DEFAULT_TRANSITION_DURATION = 300;
422
422
  const DEFAULT_TRANSITION_TIMING = "cubic-bezier(0.4, 0, 0.2, 1)";
423
- function enableThemeTransition(duration = DEFAULT_TRANSITION_DURATION, timing = DEFAULT_TRANSITION_TIMING) {
423
+ function enableThemeTransition(duration = DEFAULT_TRANSITION_DURATION, timing = DEFAULT_TRANSITION_TIMING, el = null) {
424
424
  if (typeof document === "undefined") return;
425
+ const target = el || document.documentElement;
425
426
  const style = document.createElement("style");
426
427
  style.id = "yh-theme-transition";
427
428
  style.textContent = `
@@ -439,9 +440,9 @@ function enableThemeTransition(duration = DEFAULT_TRANSITION_DURATION, timing =
439
440
  }
440
441
  `;
441
442
  document.head.appendChild(style);
442
- document.documentElement.classList.add(THEME_TRANSITION_CLASS);
443
+ target.classList.add(THEME_TRANSITION_CLASS);
443
444
  setTimeout(() => {
444
- document.documentElement.classList.remove(THEME_TRANSITION_CLASS);
445
+ target.classList.remove(THEME_TRANSITION_CLASS);
445
446
  style.remove();
446
447
  }, duration);
447
448
  }
@@ -556,6 +557,7 @@ class ThemeManager {
556
557
  };
557
558
  themeHistory = [];
558
559
  maxHistoryLength = 10;
560
+ responsiveVars = /* @__PURE__ */new Map();
559
561
  // 响应式状态
560
562
  state = (0, _vue.reactive)({
561
563
  theme: "default",
@@ -668,11 +670,12 @@ class ThemeManager {
668
670
  setDarkMode(dark) {
669
671
  this.isDark = dark;
670
672
  this.state.dark = dark;
671
- if (typeof document !== "undefined") {
673
+ const el = this.targetEl || (typeof document !== "undefined" ? document.documentElement : null);
674
+ if (el) {
672
675
  if (dark) {
673
- document.documentElement.classList.add("dark");
676
+ el.classList.add("dark");
674
677
  } else {
675
- document.documentElement.classList.remove("dark");
678
+ el.classList.remove("dark");
676
679
  }
677
680
  }
678
681
  const currentColors = {
@@ -798,6 +801,8 @@ class ThemeManager {
798
801
  Object.entries(semanticColors).forEach(([state, value]) => {
799
802
  styles[`--yh-color-${cssVar}-${state}`] = value;
800
803
  });
804
+ const textContrastColor = getTextColorForBackground(baseColor);
805
+ styles[`--yh-color-${cssVar}-text`] = textContrastColor;
801
806
  const rgb = hexToRgb(baseColor);
802
807
  if (rgb) {
803
808
  styles[`--yh-color-${cssVar}-rgb`] = `${rgb.r}, ${rgb.g}, ${rgb.b}`;
@@ -919,7 +924,7 @@ class ThemeManager {
919
924
  try {
920
925
  const snapshot = JSON.parse(json);
921
926
  if (this.transitionEnabled) {
922
- enableThemeTransition(this.transitionConfig.duration, this.transitionConfig.timing);
927
+ enableThemeTransition(this.transitionConfig.duration, this.transitionConfig.timing, this.targetEl);
923
928
  }
924
929
  this.setPreset(snapshot.preset);
925
930
  if (snapshot.colors && Object.keys(snapshot.colors).length > 0) {
@@ -966,8 +971,8 @@ class ThemeManager {
966
971
  this.state.colorBlindMode = "none";
967
972
  this.state.algorithm = "default";
968
973
  this.state.componentThemeVersion += 1;
969
- document.documentElement.classList.remove("dark");
970
974
  const el = this.targetEl || document.documentElement;
975
+ el.classList.remove("dark");
971
976
  const colorTypes = ["primary", "success", "warning", "danger", "info"];
972
977
  const suffixes = ["", "light-1", "light-2", "light-3", "light-4", "light-5", "light-6", "light-7", "light-8", "light-9", "dark-2", "hover", "active", "disabled", "focus", "rgb"];
973
978
  colorTypes.forEach(type => {
@@ -985,7 +990,7 @@ class ThemeManager {
985
990
  /** 设置密度 */
986
991
  setDensity(density) {
987
992
  if (this.transitionEnabled) {
988
- enableThemeTransition(this.transitionConfig.duration, this.transitionConfig.timing);
993
+ enableThemeTransition(this.transitionConfig.duration, this.transitionConfig.timing, this.targetEl);
989
994
  }
990
995
  this.currentDensity = density;
991
996
  this.state.density = density;
@@ -1005,7 +1010,7 @@ class ThemeManager {
1005
1010
  /** 设置色盲友好模式 */
1006
1011
  setColorBlindMode(mode) {
1007
1012
  if (this.transitionEnabled) {
1008
- enableThemeTransition(this.transitionConfig.duration, this.transitionConfig.timing);
1013
+ enableThemeTransition(this.transitionConfig.duration, this.transitionConfig.timing, this.targetEl);
1009
1014
  }
1010
1015
  this.colorBlindMode = mode;
1011
1016
  this.state.colorBlindMode = mode;
@@ -1110,7 +1115,7 @@ class ThemeManager {
1110
1115
  duration: DEFAULT_TRANSITION_DURATION,
1111
1116
  timing: DEFAULT_TRANSITION_TIMING
1112
1117
  };
1113
- enableThemeTransition(transitionConfig.duration, transitionConfig.timing);
1118
+ enableThemeTransition(transitionConfig.duration, transitionConfig.timing, this.targetEl);
1114
1119
  }
1115
1120
  this.pushHistory();
1116
1121
  const snapshot = this.createTheme(config);
@@ -1195,6 +1200,7 @@ class ThemeManager {
1195
1200
  /** 设置响应式变量 (根据断点自动切换) */
1196
1201
  setResponsiveVar(name, values) {
1197
1202
  if (typeof document === "undefined") return;
1203
+ this.responsiveVars.set(name, values);
1198
1204
  let style = document.getElementById("yh-responsive-vars");
1199
1205
  if (!style) {
1200
1206
  style = document.createElement("style");
@@ -1202,23 +1208,25 @@ class ThemeManager {
1202
1208
  document.head.appendChild(style);
1203
1209
  }
1204
1210
  let css = "";
1205
- const orderedBreakpoints = ["xs", "sm", "md", "lg", "xl", "xxl"];
1206
- orderedBreakpoints.forEach(bp => {
1207
- if (values[bp]) {
1208
- if (bp === "xs") {
1209
- css += `
1210
- :root { ${name}: ${values[bp]}; }
1211
- `;
1212
- } else {
1213
- css += `
1214
- @media (min-width: ${breakpoints[bp]}px) {
1215
- :root { ${name}: ${values[bp]}; }
1216
- }
1217
- `;
1211
+ this.responsiveVars.forEach((vals, varName) => {
1212
+ const orderedBreakpoints = ["xs", "sm", "md", "lg", "xl", "xxl"];
1213
+ orderedBreakpoints.forEach(bp => {
1214
+ if (vals[bp]) {
1215
+ if (bp === "xs") {
1216
+ css += `
1217
+ :root { ${varName}: ${vals[bp]}; }
1218
+ `;
1219
+ } else {
1220
+ css += `
1221
+ @media (min-width: ${breakpoints[bp]}px) {
1222
+ :root { ${varName}: ${vals[bp]}; }
1223
+ }
1224
+ `;
1225
+ }
1218
1226
  }
1219
- }
1227
+ });
1220
1228
  });
1221
- style.textContent += css;
1229
+ style.textContent = css;
1222
1230
  }
1223
1231
  /** 销毁 */
1224
1232
  destroy() {
@@ -1230,6 +1238,7 @@ class ThemeManager {
1230
1238
  if (style) {
1231
1239
  style.remove();
1232
1240
  }
1241
+ this.responsiveVars.clear();
1233
1242
  }
1234
1243
  }
1235
1244
  exports.ThemeManager = ThemeManager;
package/dist/theme.d.ts CHANGED
@@ -148,6 +148,7 @@ export declare class ThemeManager {
148
148
  private transitionConfig;
149
149
  private themeHistory;
150
150
  private maxHistoryLength;
151
+ private responsiveVars;
151
152
  readonly state: {
152
153
  theme: PresetTheme;
153
154
  dark: boolean;
package/dist/theme.mjs CHANGED
@@ -391,8 +391,9 @@ const colorBlindPalettes = {
391
391
  const THEME_TRANSITION_CLASS = "yh-theme-transitioning";
392
392
  const DEFAULT_TRANSITION_DURATION = 300;
393
393
  const DEFAULT_TRANSITION_TIMING = "cubic-bezier(0.4, 0, 0.2, 1)";
394
- function enableThemeTransition(duration = DEFAULT_TRANSITION_DURATION, timing = DEFAULT_TRANSITION_TIMING) {
394
+ function enableThemeTransition(duration = DEFAULT_TRANSITION_DURATION, timing = DEFAULT_TRANSITION_TIMING, el = null) {
395
395
  if (typeof document === "undefined") return;
396
+ const target = el || document.documentElement;
396
397
  const style = document.createElement("style");
397
398
  style.id = "yh-theme-transition";
398
399
  style.textContent = `
@@ -410,9 +411,9 @@ function enableThemeTransition(duration = DEFAULT_TRANSITION_DURATION, timing =
410
411
  }
411
412
  `;
412
413
  document.head.appendChild(style);
413
- document.documentElement.classList.add(THEME_TRANSITION_CLASS);
414
+ target.classList.add(THEME_TRANSITION_CLASS);
414
415
  setTimeout(() => {
415
- document.documentElement.classList.remove(THEME_TRANSITION_CLASS);
416
+ target.classList.remove(THEME_TRANSITION_CLASS);
416
417
  style.remove();
417
418
  }, duration);
418
419
  }
@@ -497,6 +498,7 @@ export class ThemeManager {
497
498
  };
498
499
  themeHistory = [];
499
500
  maxHistoryLength = 10;
501
+ responsiveVars = /* @__PURE__ */ new Map();
500
502
  // 响应式状态
501
503
  state = reactive({
502
504
  theme: "default",
@@ -598,11 +600,12 @@ export class ThemeManager {
598
600
  setDarkMode(dark) {
599
601
  this.isDark = dark;
600
602
  this.state.dark = dark;
601
- if (typeof document !== "undefined") {
603
+ const el = this.targetEl || (typeof document !== "undefined" ? document.documentElement : null);
604
+ if (el) {
602
605
  if (dark) {
603
- document.documentElement.classList.add("dark");
606
+ el.classList.add("dark");
604
607
  } else {
605
- document.documentElement.classList.remove("dark");
608
+ el.classList.remove("dark");
606
609
  }
607
610
  }
608
611
  const currentColors = {
@@ -716,6 +719,8 @@ export class ThemeManager {
716
719
  Object.entries(semanticColors).forEach(([state, value]) => {
717
720
  styles[`--yh-color-${cssVar}-${state}`] = value;
718
721
  });
722
+ const textContrastColor = getTextColorForBackground(baseColor);
723
+ styles[`--yh-color-${cssVar}-text`] = textContrastColor;
719
724
  const rgb = hexToRgb(baseColor);
720
725
  if (rgb) {
721
726
  styles[`--yh-color-${cssVar}-rgb`] = `${rgb.r}, ${rgb.g}, ${rgb.b}`;
@@ -837,7 +842,11 @@ export class ThemeManager {
837
842
  try {
838
843
  const snapshot = JSON.parse(json);
839
844
  if (this.transitionEnabled) {
840
- enableThemeTransition(this.transitionConfig.duration, this.transitionConfig.timing);
845
+ enableThemeTransition(
846
+ this.transitionConfig.duration,
847
+ this.transitionConfig.timing,
848
+ this.targetEl
849
+ );
841
850
  }
842
851
  this.setPreset(snapshot.preset);
843
852
  if (snapshot.colors && Object.keys(snapshot.colors).length > 0) {
@@ -884,8 +893,8 @@ export class ThemeManager {
884
893
  this.state.colorBlindMode = "none";
885
894
  this.state.algorithm = "default";
886
895
  this.state.componentThemeVersion += 1;
887
- document.documentElement.classList.remove("dark");
888
896
  const el = this.targetEl || document.documentElement;
897
+ el.classList.remove("dark");
889
898
  const colorTypes = ["primary", "success", "warning", "danger", "info"];
890
899
  const suffixes = [
891
900
  "",
@@ -920,7 +929,11 @@ export class ThemeManager {
920
929
  /** 设置密度 */
921
930
  setDensity(density) {
922
931
  if (this.transitionEnabled) {
923
- enableThemeTransition(this.transitionConfig.duration, this.transitionConfig.timing);
932
+ enableThemeTransition(
933
+ this.transitionConfig.duration,
934
+ this.transitionConfig.timing,
935
+ this.targetEl
936
+ );
924
937
  }
925
938
  this.currentDensity = density;
926
939
  this.state.density = density;
@@ -940,7 +953,11 @@ export class ThemeManager {
940
953
  /** 设置色盲友好模式 */
941
954
  setColorBlindMode(mode) {
942
955
  if (this.transitionEnabled) {
943
- enableThemeTransition(this.transitionConfig.duration, this.transitionConfig.timing);
956
+ enableThemeTransition(
957
+ this.transitionConfig.duration,
958
+ this.transitionConfig.timing,
959
+ this.targetEl
960
+ );
944
961
  }
945
962
  this.colorBlindMode = mode;
946
963
  this.state.colorBlindMode = mode;
@@ -1035,7 +1052,7 @@ export class ThemeManager {
1035
1052
  applyFullConfig(config) {
1036
1053
  if (this.transitionEnabled || config.transition) {
1037
1054
  const transitionConfig = typeof config.transition === "object" ? config.transition : { duration: DEFAULT_TRANSITION_DURATION, timing: DEFAULT_TRANSITION_TIMING };
1038
- enableThemeTransition(transitionConfig.duration, transitionConfig.timing);
1055
+ enableThemeTransition(transitionConfig.duration, transitionConfig.timing, this.targetEl);
1039
1056
  }
1040
1057
  this.pushHistory();
1041
1058
  const snapshot = this.createTheme(config);
@@ -1118,6 +1135,7 @@ export class ThemeManager {
1118
1135
  /** 设置响应式变量 (根据断点自动切换) */
1119
1136
  setResponsiveVar(name, values) {
1120
1137
  if (typeof document === "undefined") return;
1138
+ this.responsiveVars.set(name, values);
1121
1139
  let style = document.getElementById("yh-responsive-vars");
1122
1140
  if (!style) {
1123
1141
  style = document.createElement("style");
@@ -1125,23 +1143,25 @@ export class ThemeManager {
1125
1143
  document.head.appendChild(style);
1126
1144
  }
1127
1145
  let css = "";
1128
- const orderedBreakpoints = ["xs", "sm", "md", "lg", "xl", "xxl"];
1129
- orderedBreakpoints.forEach((bp) => {
1130
- if (values[bp]) {
1131
- if (bp === "xs") {
1132
- css += `
1133
- :root { ${name}: ${values[bp]}; }
1134
- `;
1135
- } else {
1136
- css += `
1137
- @media (min-width: ${breakpoints[bp]}px) {
1138
- :root { ${name}: ${values[bp]}; }
1139
- }
1140
- `;
1146
+ this.responsiveVars.forEach((vals, varName) => {
1147
+ const orderedBreakpoints = ["xs", "sm", "md", "lg", "xl", "xxl"];
1148
+ orderedBreakpoints.forEach((bp) => {
1149
+ if (vals[bp]) {
1150
+ if (bp === "xs") {
1151
+ css += `
1152
+ :root { ${varName}: ${vals[bp]}; }
1153
+ `;
1154
+ } else {
1155
+ css += `
1156
+ @media (min-width: ${breakpoints[bp]}px) {
1157
+ :root { ${varName}: ${vals[bp]}; }
1158
+ }
1159
+ `;
1160
+ }
1141
1161
  }
1142
- }
1162
+ });
1143
1163
  });
1144
- style.textContent += css;
1164
+ style.textContent = css;
1145
1165
  }
1146
1166
  /** 销毁 */
1147
1167
  destroy() {
@@ -1153,6 +1173,7 @@ export class ThemeManager {
1153
1173
  if (style) {
1154
1174
  style.remove();
1155
1175
  }
1176
+ this.responsiveVars.clear();
1156
1177
  }
1157
1178
  }
1158
1179
  let globalThemeManager = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yh-ui/theme",
3
- "version": "1.0.52",
3
+ "version": "1.0.54",
4
4
  "description": "YH-UI theme and design tokens",
5
5
  "type": "module",
6
6
  "sideEffects": [