@kbach/react 0.6.30 → 0.6.32

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/index.d.ts CHANGED
@@ -50,7 +50,7 @@ type ColorsAPI<ColorName extends string = DefaultColorName> = {
50
50
  */
51
51
  readonly alpha: (color: string, opacity?: number) => string;
52
52
  };
53
- declare function wrapColors<ColorName extends string = DefaultColorName>(rawColors: ThemeColors): ColorsAPI<ColorName>;
53
+ declare function wrapColors<ColorName extends string = DefaultColorName>(rawColors: ThemeColors, isDark?: boolean): ColorsAPI<ColorName>;
54
54
  declare function useColors<ColorName extends string = DefaultColorName>(): ColorsAPI<ColorName>;
55
55
 
56
56
  /**
package/dist/index.js CHANGED
@@ -99,7 +99,10 @@ function applyOpacity(color, opacity) {
99
99
  if (color.startsWith("rgba(")) return color.replace(/,\s*[\d.]+\)$/, `,${a})`);
100
100
  return color;
101
101
  }
102
- function makeShadeProxy(shades) {
102
+ function pickSide(value, isDark) {
103
+ return (0, import_core.isModeAwareColor)(value) ? isDark ? value.dark : value.light : value;
104
+ }
105
+ function makeShadeProxy(shades, isDark) {
103
106
  return new Proxy(shades, {
104
107
  get(target, prop) {
105
108
  const key = String(prop);
@@ -108,14 +111,15 @@ function makeShadeProxy(shades) {
108
111
  const slash = key.indexOf("/");
109
112
  const shade = key.slice(0, slash);
110
113
  const op = Number(key.slice(slash + 1));
111
- const color = target[shade];
112
- return typeof color === "string" ? applyOpacity(color, op) : void 0;
114
+ const color2 = target[shade];
115
+ return color2 !== void 0 ? applyOpacity(pickSide(color2, isDark), op) : void 0;
113
116
  }
114
- return target[key];
117
+ const color = target[key];
118
+ return color !== void 0 ? pickSide(color, isDark) : void 0;
115
119
  }
116
120
  });
117
121
  }
118
- function wrapColors(rawColors) {
122
+ function wrapColors(rawColors, isDark = false) {
119
123
  const cache = /* @__PURE__ */ new Map();
120
124
  const alpha = (color, opacity) => opacity === void 0 ? color : applyOpacity(color, opacity);
121
125
  return new Proxy({ alpha }, {
@@ -128,19 +132,20 @@ function wrapColors(rawColors) {
128
132
  const name = key.slice(0, slash);
129
133
  const op = Number(key.slice(slash + 1));
130
134
  const entry2 = rawColors[name];
131
- return typeof entry2 === "string" ? applyOpacity(entry2, op) : void 0;
135
+ return entry2 !== void 0 && (typeof entry2 === "string" || (0, import_core.isModeAwareColor)(entry2)) ? applyOpacity(pickSide(entry2, isDark), op) : void 0;
132
136
  }
133
137
  const entry = rawColors[key];
134
138
  if (entry === void 0) return void 0;
135
- if (typeof entry === "string") return entry;
136
- if (!cache.has(key)) cache.set(key, makeShadeProxy(entry));
137
- return cache.get(key);
139
+ if (typeof entry === "string" || (0, import_core.isModeAwareColor)(entry)) return pickSide(entry, isDark);
140
+ const cacheKey = `${key}:${isDark}`;
141
+ if (!cache.has(cacheKey)) cache.set(cacheKey, makeShadeProxy(entry, isDark));
142
+ return cache.get(cacheKey);
138
143
  }
139
144
  });
140
145
  }
141
146
  function useColors() {
142
- const { config } = useTheme();
143
- return (0, import_react2.useMemo)(() => wrapColors(config.theme.colors), [config.theme.colors]);
147
+ const { config, isDark } = useTheme();
148
+ return (0, import_react2.useMemo)(() => wrapColors(config.theme.colors, isDark), [config.theme.colors, isDark]);
144
149
  }
145
150
 
146
151
  // src/useSpacing.ts
@@ -837,8 +842,7 @@ function styled(Component, baseClasses = "") {
837
842
  [resolved, isDark, pressed, hovered, focused, disabled, checked, width]
838
843
  // eslint-disable-line react-hooks/exhaustive-deps
839
844
  );
840
- const extraStyle = Array.isArray(styleProp) ? Object.assign({}, ...styleProp) : styleProp;
841
- const finalStyle = isWebPlatform ? extraStyle ?? void 0 : extraStyle ? { ...computedStyle, ...extraStyle } : computedStyle;
845
+ const finalStyle = isWebPlatform ? (Array.isArray(styleProp) ? Object.assign({}, ...styleProp) : styleProp) ?? void 0 : styleProp ? Array.isArray(styleProp) ? [computedStyle, ...styleProp] : [computedStyle, styleProp] : computedStyle;
842
846
  const webTag = isWebPlatform ? getWebTag(Component, rest) : null;
843
847
  const effectiveComponent = webTag ?? Component;
844
848
  const componentName2 = Component.displayName ?? Component.name ?? "";
@@ -1025,7 +1029,7 @@ var InteractiveWrapper = (0, import_react9.forwardRef)(
1025
1029
  [resolvedStyle, isDark, pressed, hovered, focused, width, disabled, checked, isNonStringComponent]
1026
1030
  );
1027
1031
  const skipComputedInline = isWebPlatform;
1028
- const finalStyle = skipComputedInline ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
1032
+ const finalStyle = skipComputedInline ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? [computedStyle, ...styleProp] : [computedStyle, styleProp] : computedStyle;
1029
1033
  const componentProps = {
1030
1034
  ref,
1031
1035
  ...restForComponent,
package/dist/index.mjs CHANGED
@@ -18,6 +18,7 @@ import {
18
18
  hasInteractiveBuckets,
19
19
  hasResponsiveBuckets,
20
20
  initConfig,
21
+ isModeAwareColor,
21
22
  isNative,
22
23
  isWeb,
23
24
  kbachWarn,
@@ -42,7 +43,7 @@ import {
42
43
  useGlobalDarkMode,
43
44
  useGlobalWidth,
44
45
  useSyncExternalStore
45
- } from "./chunk-TKBIGAR2.mjs";
46
+ } from "./chunk-E322MVGC.mjs";
46
47
 
47
48
  // src/context.tsx
48
49
  import { createContext, useContext } from "react";
@@ -74,7 +75,10 @@ function applyOpacity(color, opacity) {
74
75
  if (color.startsWith("rgba(")) return color.replace(/,\s*[\d.]+\)$/, `,${a})`);
75
76
  return color;
76
77
  }
77
- function makeShadeProxy(shades) {
78
+ function pickSide(value, isDark) {
79
+ return isModeAwareColor(value) ? isDark ? value.dark : value.light : value;
80
+ }
81
+ function makeShadeProxy(shades, isDark) {
78
82
  return new Proxy(shades, {
79
83
  get(target, prop) {
80
84
  const key = String(prop);
@@ -83,14 +87,15 @@ function makeShadeProxy(shades) {
83
87
  const slash = key.indexOf("/");
84
88
  const shade = key.slice(0, slash);
85
89
  const op = Number(key.slice(slash + 1));
86
- const color = target[shade];
87
- return typeof color === "string" ? applyOpacity(color, op) : void 0;
90
+ const color2 = target[shade];
91
+ return color2 !== void 0 ? applyOpacity(pickSide(color2, isDark), op) : void 0;
88
92
  }
89
- return target[key];
93
+ const color = target[key];
94
+ return color !== void 0 ? pickSide(color, isDark) : void 0;
90
95
  }
91
96
  });
92
97
  }
93
- function wrapColors(rawColors) {
98
+ function wrapColors(rawColors, isDark = false) {
94
99
  const cache = /* @__PURE__ */ new Map();
95
100
  const alpha = (color, opacity) => opacity === void 0 ? color : applyOpacity(color, opacity);
96
101
  return new Proxy({ alpha }, {
@@ -103,19 +108,20 @@ function wrapColors(rawColors) {
103
108
  const name = key.slice(0, slash);
104
109
  const op = Number(key.slice(slash + 1));
105
110
  const entry2 = rawColors[name];
106
- return typeof entry2 === "string" ? applyOpacity(entry2, op) : void 0;
111
+ return entry2 !== void 0 && (typeof entry2 === "string" || isModeAwareColor(entry2)) ? applyOpacity(pickSide(entry2, isDark), op) : void 0;
107
112
  }
108
113
  const entry = rawColors[key];
109
114
  if (entry === void 0) return void 0;
110
- if (typeof entry === "string") return entry;
111
- if (!cache.has(key)) cache.set(key, makeShadeProxy(entry));
112
- return cache.get(key);
115
+ if (typeof entry === "string" || isModeAwareColor(entry)) return pickSide(entry, isDark);
116
+ const cacheKey = `${key}:${isDark}`;
117
+ if (!cache.has(cacheKey)) cache.set(cacheKey, makeShadeProxy(entry, isDark));
118
+ return cache.get(cacheKey);
113
119
  }
114
120
  });
115
121
  }
116
122
  function useColors() {
117
- const { config } = useTheme();
118
- return useMemo(() => wrapColors(config.theme.colors), [config.theme.colors]);
123
+ const { config, isDark } = useTheme();
124
+ return useMemo(() => wrapColors(config.theme.colors, isDark), [config.theme.colors, isDark]);
119
125
  }
120
126
 
121
127
  // src/useSpacing.ts
@@ -400,8 +406,7 @@ function styled(Component, baseClasses = "") {
400
406
  [resolved, isDark, pressed, hovered, focused, disabled, checked, width]
401
407
  // eslint-disable-line react-hooks/exhaustive-deps
402
408
  );
403
- const extraStyle = Array.isArray(styleProp) ? Object.assign({}, ...styleProp) : styleProp;
404
- const finalStyle = isWebPlatform ? extraStyle ?? void 0 : extraStyle ? { ...computedStyle, ...extraStyle } : computedStyle;
409
+ const finalStyle = isWebPlatform ? (Array.isArray(styleProp) ? Object.assign({}, ...styleProp) : styleProp) ?? void 0 : styleProp ? Array.isArray(styleProp) ? [computedStyle, ...styleProp] : [computedStyle, styleProp] : computedStyle;
405
410
  const webTag = isWebPlatform ? getWebTag(Component, rest) : null;
406
411
  const effectiveComponent = webTag ?? Component;
407
412
  const componentName2 = Component.displayName ?? Component.name ?? "";
@@ -234,7 +234,7 @@ var InteractiveWrapper = (0, import_react2.forwardRef)(
234
234
  [resolvedStyle, isDark, pressed, hovered, focused, width, disabled, checked, isNonStringComponent]
235
235
  );
236
236
  const skipComputedInline = isWebPlatform;
237
- const finalStyle = skipComputedInline ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
237
+ const finalStyle = skipComputedInline ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? [computedStyle, ...styleProp] : [computedStyle, styleProp] : computedStyle;
238
238
  const componentProps = {
239
239
  ref,
240
240
  ...restForComponent,
@@ -291,7 +291,7 @@ var DarkWrapper = import_react3.default.forwardRef(
291
291
  return s;
292
292
  }, [resolvedStyle, isDark, width, screens, isNonStringComponent]);
293
293
  const skipComputedInline = isWebPlatform;
294
- const finalStyle = skipComputedInline ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
294
+ const finalStyle = skipComputedInline ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? [computedStyle, ...styleProp] : [computedStyle, styleProp] : computedStyle;
295
295
  const props = { ref, ...rest, style: finalStyle };
296
296
  return Array.isArray(children) ? import_react3.default.createElement(Component, props, ...children) : import_react3.default.createElement(Component, props, children);
297
297
  }
@@ -619,8 +619,7 @@ function omitConsumed(props) {
619
619
  }
620
620
  function mergeStyle(computed, userStyle) {
621
621
  if (!userStyle) return computed;
622
- if (Array.isArray(userStyle)) return Object.assign({}, computed, ...userStyle);
623
- return { ...computed, ...userStyle };
622
+ return Array.isArray(userStyle) ? [computed, ...userStyle] : [computed, userStyle];
624
623
  }
625
624
  function withImpliedFlexIfNeeded(webTag, resolvedBase, userStyle) {
626
625
  if (!webTag || !resolvedBase) return userStyle;
@@ -650,11 +649,13 @@ function processElement(type, rawProps, key, isStaticChildren) {
650
649
  return makeElement(isStaticChildren, effectiveType, workingProps, key);
651
650
  }
652
651
  const classStr = classStrRaw;
653
- if (!import_core6.isNative && (0, import_core6.isRuntimeCSSDisabled)() && classStr && !__kbachStyles) {
652
+ const config = (0, import_core6.getConfig)();
653
+ const expandedClassStr = classStr ? (0, import_core6.expandModeAwareColorClasses)(classStr, config.theme.colors) : classStr;
654
+ if (!import_core6.isNative && (0, import_core6.isRuntimeCSSDisabled)() && expandedClassStr && !__kbachStyles) {
654
655
  const { style: userStyle2, ...passProps2 } = omitConsumed(workingProps);
655
656
  return makeElement(isStaticChildren, effectiveType, {
656
657
  ...passProps2,
657
- className: (0, import_core6.normalizeClassString)(classStr),
658
+ className: (0, import_core6.normalizeClassString)(expandedClassStr),
658
659
  ...userStyle2 !== void 0 ? { style: userStyle2 } : {}
659
660
  }, key);
660
661
  }
@@ -674,8 +675,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
674
675
  const finalStyle2 = userStyle2 ? Array.isArray(userStyle2) ? { fontFamily: defaultFont, ...Object.assign({}, ...userStyle2) } : { fontFamily: defaultFont, ...userStyle2 } : { fontFamily: defaultFont };
675
676
  return makeElement(isStaticChildren, effectiveType, { ...passProps2, style: finalStyle2 }, key);
676
677
  }
677
- const config = (0, import_core6.getConfig)();
678
- const resolved = !import_core6.isWeb && __kbachStyles != null ? __kbachStyles : classStr ? (0, import_core6.resolve)(classStr, config.theme, config.darkMode) : {};
678
+ const resolved = !import_core6.isWeb && __kbachStyles != null ? __kbachStyles : expandedClassStr ? (0, import_core6.resolve)(expandedClassStr, config.theme, config.darkMode) : {};
679
679
  const { style: rawUserStyle, ...passProps } = omitConsumed(workingProps);
680
680
  const userStyle = withImpliedFlexIfNeeded(webTag, resolved.base, rawUserStyle);
681
681
  const { interactive, modeOrResponsive } = bucketMods(resolved);
@@ -683,7 +683,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
683
683
  return (0, import_jsx_runtime.jsx)(InteractiveWrapper, {
684
684
  Component: effectiveType,
685
685
  resolvedStyle: resolved,
686
- ...!import_core6.isNative && classStr ? { className: (0, import_core6.normalizeClassString)(classStr) } : {},
686
+ ...!import_core6.isNative && expandedClassStr ? { className: (0, import_core6.normalizeClassString)(expandedClassStr) } : {},
687
687
  style: userStyle,
688
688
  ...passProps
689
689
  }, key);
@@ -692,7 +692,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
692
692
  return (0, import_jsx_runtime.jsx)(DarkWrapper, {
693
693
  Component: effectiveType,
694
694
  resolvedStyle: resolved,
695
- ...!import_core6.isNative && classStr ? { className: (0, import_core6.normalizeClassString)(classStr) } : {},
695
+ ...!import_core6.isNative && expandedClassStr ? { className: (0, import_core6.normalizeClassString)(expandedClassStr) } : {},
696
696
  style: userStyle,
697
697
  ...passProps
698
698
  }, key);
@@ -710,7 +710,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
710
710
  return makeElement(isStaticChildren, effectiveType, {
711
711
  ...passProps,
712
712
  ...finalStyle !== void 0 ? { style: finalStyle } : {},
713
- ...!import_core6.isNative && classStr ? { className: (0, import_core6.normalizeClassString)(classStr) } : {}
713
+ ...!import_core6.isNative && expandedClassStr ? { className: (0, import_core6.normalizeClassString)(expandedClassStr) } : {}
714
714
  }, key);
715
715
  }
716
716
  function jsx(type, props, key) {
@@ -3,8 +3,8 @@ import {
3
3
  Fragment,
4
4
  jsx,
5
5
  jsxs
6
- } from "./chunk-FF4AZQIQ.mjs";
7
- import "./chunk-TKBIGAR2.mjs";
6
+ } from "./chunk-JUGDQQQ4.mjs";
7
+ import "./chunk-E322MVGC.mjs";
8
8
 
9
9
  // src/jsx-dev-runtime.tsx
10
10
  function jsxDEV(type, props, key, isStaticChildren, source, self) {
@@ -235,7 +235,7 @@ var InteractiveWrapper = (0, import_react2.forwardRef)(
235
235
  [resolvedStyle, isDark, pressed, hovered, focused, width, disabled, checked, isNonStringComponent]
236
236
  );
237
237
  const skipComputedInline = isWebPlatform;
238
- const finalStyle = skipComputedInline ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
238
+ const finalStyle = skipComputedInline ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? [computedStyle, ...styleProp] : [computedStyle, styleProp] : computedStyle;
239
239
  const componentProps = {
240
240
  ref,
241
241
  ...restForComponent,
@@ -292,7 +292,7 @@ var DarkWrapper = import_react3.default.forwardRef(
292
292
  return s;
293
293
  }, [resolvedStyle, isDark, width, screens, isNonStringComponent]);
294
294
  const skipComputedInline = isWebPlatform;
295
- const finalStyle = skipComputedInline ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
295
+ const finalStyle = skipComputedInline ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? [computedStyle, ...styleProp] : [computedStyle, styleProp] : computedStyle;
296
296
  const props = { ref, ...rest, style: finalStyle };
297
297
  return Array.isArray(children) ? import_react3.default.createElement(Component, props, ...children) : import_react3.default.createElement(Component, props, children);
298
298
  }
@@ -625,8 +625,7 @@ function omitConsumed(props) {
625
625
  }
626
626
  function mergeStyle(computed, userStyle) {
627
627
  if (!userStyle) return computed;
628
- if (Array.isArray(userStyle)) return Object.assign({}, computed, ...userStyle);
629
- return { ...computed, ...userStyle };
628
+ return Array.isArray(userStyle) ? [computed, ...userStyle] : [computed, userStyle];
630
629
  }
631
630
  function withImpliedFlexIfNeeded(webTag, resolvedBase, userStyle) {
632
631
  if (!webTag || !resolvedBase) return userStyle;
@@ -656,11 +655,13 @@ function processElement(type, rawProps, key, isStaticChildren) {
656
655
  return makeElement(isStaticChildren, effectiveType, workingProps, key);
657
656
  }
658
657
  const classStr = classStrRaw;
659
- if (!import_core6.isNative && (0, import_core6.isRuntimeCSSDisabled)() && classStr && !__kbachStyles) {
658
+ const config = (0, import_core6.getConfig)();
659
+ const expandedClassStr = classStr ? (0, import_core6.expandModeAwareColorClasses)(classStr, config.theme.colors) : classStr;
660
+ if (!import_core6.isNative && (0, import_core6.isRuntimeCSSDisabled)() && expandedClassStr && !__kbachStyles) {
660
661
  const { style: userStyle2, ...passProps2 } = omitConsumed(workingProps);
661
662
  return makeElement(isStaticChildren, effectiveType, {
662
663
  ...passProps2,
663
- className: (0, import_core6.normalizeClassString)(classStr),
664
+ className: (0, import_core6.normalizeClassString)(expandedClassStr),
664
665
  ...userStyle2 !== void 0 ? { style: userStyle2 } : {}
665
666
  }, key);
666
667
  }
@@ -680,8 +681,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
680
681
  const finalStyle2 = userStyle2 ? Array.isArray(userStyle2) ? { fontFamily: defaultFont, ...Object.assign({}, ...userStyle2) } : { fontFamily: defaultFont, ...userStyle2 } : { fontFamily: defaultFont };
681
682
  return makeElement(isStaticChildren, effectiveType, { ...passProps2, style: finalStyle2 }, key);
682
683
  }
683
- const config = (0, import_core6.getConfig)();
684
- const resolved = !import_core6.isWeb && __kbachStyles != null ? __kbachStyles : classStr ? (0, import_core6.resolve)(classStr, config.theme, config.darkMode) : {};
684
+ const resolved = !import_core6.isWeb && __kbachStyles != null ? __kbachStyles : expandedClassStr ? (0, import_core6.resolve)(expandedClassStr, config.theme, config.darkMode) : {};
685
685
  const { style: rawUserStyle, ...passProps } = omitConsumed(workingProps);
686
686
  const userStyle = withImpliedFlexIfNeeded(webTag, resolved.base, rawUserStyle);
687
687
  const { interactive, modeOrResponsive } = bucketMods(resolved);
@@ -689,7 +689,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
689
689
  return (0, import_jsx_runtime.jsx)(InteractiveWrapper, {
690
690
  Component: effectiveType,
691
691
  resolvedStyle: resolved,
692
- ...!import_core6.isNative && classStr ? { className: (0, import_core6.normalizeClassString)(classStr) } : {},
692
+ ...!import_core6.isNative && expandedClassStr ? { className: (0, import_core6.normalizeClassString)(expandedClassStr) } : {},
693
693
  style: userStyle,
694
694
  ...passProps
695
695
  }, key);
@@ -698,7 +698,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
698
698
  return (0, import_jsx_runtime.jsx)(DarkWrapper, {
699
699
  Component: effectiveType,
700
700
  resolvedStyle: resolved,
701
- ...!import_core6.isNative && classStr ? { className: (0, import_core6.normalizeClassString)(classStr) } : {},
701
+ ...!import_core6.isNative && expandedClassStr ? { className: (0, import_core6.normalizeClassString)(expandedClassStr) } : {},
702
702
  style: userStyle,
703
703
  ...passProps
704
704
  }, key);
@@ -716,7 +716,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
716
716
  return makeElement(isStaticChildren, effectiveType, {
717
717
  ...passProps,
718
718
  ...finalStyle !== void 0 ? { style: finalStyle } : {},
719
- ...!import_core6.isNative && classStr ? { className: (0, import_core6.normalizeClassString)(classStr) } : {}
719
+ ...!import_core6.isNative && expandedClassStr ? { className: (0, import_core6.normalizeClassString)(expandedClassStr) } : {}
720
720
  }, key);
721
721
  }
722
722
  function jsx(type, props, key) {
@@ -4,10 +4,10 @@ import {
4
4
  _invalidateDefaultFontCache,
5
5
  jsx,
6
6
  jsxs
7
- } from "./chunk-FF4AZQIQ.mjs";
7
+ } from "./chunk-JUGDQQQ4.mjs";
8
8
  import {
9
9
  registerWebElement
10
- } from "./chunk-TKBIGAR2.mjs";
10
+ } from "./chunk-E322MVGC.mjs";
11
11
  export {
12
12
  Fragment,
13
13
  _invalidateDefaultFontCache,
@@ -47,8 +47,17 @@ interface ModifierDef {
47
47
  interface StyleValue {
48
48
  [key: string]: string | number | undefined | null | StyleValue | StyleValue[];
49
49
  }
50
- type ColorShades = Record<string, string>;
51
- type ThemeColors = Record<string, string | ColorShades>;
50
+ /**
51
+ * A color value is either a plain string (hex/rgb/alias-to-another-color-name)
52
+ * or a mode-aware pair — resolved to `light` or `dark` per the active theme
53
+ * mode wherever it's actually used (className resolution, useColors()).
54
+ */
55
+ type ColorValue = string | {
56
+ light: string;
57
+ dark: string;
58
+ };
59
+ type ColorShades = Record<string, ColorValue>;
60
+ type ThemeColors = Record<string, ColorValue | ColorShades>;
52
61
  type ThemeSpacing = Record<string, number | string>;
53
62
  interface ThemeConfig {
54
63
  colors: ThemeColors;
@@ -47,8 +47,17 @@ interface ModifierDef {
47
47
  interface StyleValue {
48
48
  [key: string]: string | number | undefined | null | StyleValue | StyleValue[];
49
49
  }
50
- type ColorShades = Record<string, string>;
51
- type ThemeColors = Record<string, string | ColorShades>;
50
+ /**
51
+ * A color value is either a plain string (hex/rgb/alias-to-another-color-name)
52
+ * or a mode-aware pair — resolved to `light` or `dark` per the active theme
53
+ * mode wherever it's actually used (className resolution, useColors()).
54
+ */
55
+ type ColorValue = string | {
56
+ light: string;
57
+ dark: string;
58
+ };
59
+ type ColorShades = Record<string, ColorValue>;
60
+ type ThemeColors = Record<string, ColorValue | ColorShades>;
52
61
  type ThemeSpacing = Record<string, number | string>;
53
62
  interface ThemeConfig {
54
63
  colors: ThemeColors;
@@ -649,7 +649,15 @@ var defaultTheme = {
649
649
  animation: {}
650
650
  };
651
651
 
652
+ // src/core/colorValue.ts
653
+ function isModeAwareColor(v) {
654
+ return typeof v === "object" && v !== null && "light" in v && "dark" in v;
655
+ }
656
+
652
657
  // src/core/resolvers/color.ts
658
+ function pickModeAwareFallback(v) {
659
+ return isModeAwareColor(v) ? v.light : v;
660
+ }
653
661
  function resolveColor(value, colors, isArbitrary) {
654
662
  if (isArbitrary) return value;
655
663
  const slashIdx = value.indexOf("/");
@@ -661,15 +669,17 @@ function resolveColor(value, colors, isArbitrary) {
661
669
  } else if (colorPart in colors) {
662
670
  const entry = colors[colorPart];
663
671
  if (typeof entry === "string") hex = entry;
664
- else if (typeof entry === "object" && "6" in entry) hex = entry["6"];
672
+ else if (isModeAwareColor(entry)) hex = pickModeAwareFallback(entry);
673
+ else if (typeof entry === "object" && "6" in entry) hex = pickModeAwareFallback(entry["6"]);
665
674
  } else {
666
675
  const lastDash = colorPart.lastIndexOf("-");
667
676
  if (lastDash > 0) {
668
677
  const colorName = colorPart.slice(0, lastDash);
669
678
  const shade = colorPart.slice(lastDash + 1);
670
679
  const scale = colors[colorName];
671
- if (scale && typeof scale === "object" && shade in scale) {
672
- hex = scale[shade] ?? null;
680
+ if (scale && typeof scale === "object" && !isModeAwareColor(scale) && shade in scale) {
681
+ const shadeVal = scale[shade];
682
+ hex = shadeVal !== void 0 ? pickModeAwareFallback(shadeVal) : null;
673
683
  }
674
684
  }
675
685
  }
@@ -2755,6 +2765,62 @@ function findOuterColon(s) {
2755
2765
  return -1;
2756
2766
  }
2757
2767
 
2768
+ // src/core/modeAwareColors.ts
2769
+ var _modeAwareMapCache = /* @__PURE__ */ new WeakMap();
2770
+ function buildModeAwareMap(colors) {
2771
+ const map = /* @__PURE__ */ new Map();
2772
+ for (const [name, entry] of Object.entries(colors)) {
2773
+ if (isModeAwareColor(entry)) {
2774
+ map.set(name, entry);
2775
+ } else if (entry && typeof entry === "object") {
2776
+ for (const [shade, val] of Object.entries(entry)) {
2777
+ if (isModeAwareColor(val)) map.set(`${name}-${shade}`, val);
2778
+ }
2779
+ }
2780
+ }
2781
+ return map;
2782
+ }
2783
+ function getModeAwareMap(colors) {
2784
+ let map = _modeAwareMapCache.get(colors);
2785
+ if (!map) {
2786
+ map = buildModeAwareMap(colors);
2787
+ _modeAwareMapCache.set(colors, map);
2788
+ }
2789
+ return map;
2790
+ }
2791
+ function expandModeAwareColorClasses(classString, colors) {
2792
+ const map = getModeAwareMap(colors);
2793
+ if (map.size === 0) return classString;
2794
+ const tokens = splitClassTokens(classString);
2795
+ let changed = false;
2796
+ const out = [];
2797
+ for (const token of tokens) {
2798
+ const parsed = parseClass(token);
2799
+ if (!parsed || parsed.isArbitrary) {
2800
+ out.push(token);
2801
+ continue;
2802
+ }
2803
+ if (parsed.modifiers.includes("dark") || parsed.modifiers.includes("light")) {
2804
+ out.push(token);
2805
+ continue;
2806
+ }
2807
+ const slashIdx = parsed.value.indexOf("/");
2808
+ const colorPart = slashIdx > 0 ? parsed.value.slice(0, slashIdx) : parsed.value;
2809
+ const opacitySuffix = slashIdx > 0 ? parsed.value.slice(slashIdx) : "";
2810
+ const pair = map.get(colorPart);
2811
+ if (!pair) {
2812
+ out.push(token);
2813
+ continue;
2814
+ }
2815
+ changed = true;
2816
+ const bang = parsed.important ? "!" : "";
2817
+ const modPrefix = parsed.modifiers.map((m) => `${m}:`).join("");
2818
+ out.push(`${bang}${modPrefix}${parsed.utility}-[${pair.light}]${opacitySuffix}`);
2819
+ out.push(`${bang}dark:${modPrefix}${parsed.utility}-[${pair.dark}]${opacitySuffix}`);
2820
+ }
2821
+ return changed ? out.join(" ") : classString;
2822
+ }
2823
+
2758
2824
  // src/core/resolver.ts
2759
2825
  var _defaultFontFamily;
2760
2826
  function setDefaultFontFamily(font) {
@@ -2977,7 +3043,7 @@ function buildClassCSSRules(cls, bucketKey, styles, darkMode, important, screens
2977
3043
  }
2978
3044
  function generateClassCSS(classString, theme, darkMode = "attribute", screens = {}) {
2979
3045
  const rules = [];
2980
- for (const parsed of parseClasses(classString)) {
3046
+ for (const parsed of parseClasses(expandModeAwareColorClasses(classString, theme.colors))) {
2981
3047
  const styles = resolveUtility(parsed, theme);
2982
3048
  if (!styles) continue;
2983
3049
  const bucketKey = parsed.modifiers.length === 0 ? "base" : parsed.modifiers.join(":");
@@ -3011,8 +3077,9 @@ function resolveOneRef(ref, colors) {
3011
3077
  const shade = ref.slice(lastDash + 1);
3012
3078
  if (!/^\d+$/.test(shade)) return null;
3013
3079
  const entry = colors[name];
3014
- if (!entry || typeof entry !== "object") return null;
3015
- return entry[shade] ?? null;
3080
+ if (!entry || typeof entry !== "object" || isModeAwareColor(entry)) return null;
3081
+ const target = entry[shade];
3082
+ return typeof target === "string" ? target : null;
3016
3083
  }
3017
3084
  function resolveColorRefs(colors) {
3018
3085
  const MAX_DEPTH = 5;
@@ -3025,14 +3092,17 @@ function resolveColorRefs(colors) {
3025
3092
  }
3026
3093
  return current;
3027
3094
  }
3095
+ function resolveValue(val) {
3096
+ return typeof val === "string" ? resolveChain(val) : { light: resolveChain(val.light), dark: resolveChain(val.dark) };
3097
+ }
3028
3098
  const out = {};
3029
3099
  for (const [key, val] of Object.entries(colors)) {
3030
- if (typeof val === "string") {
3031
- out[key] = resolveChain(val);
3100
+ if (typeof val === "string" || isModeAwareColor(val)) {
3101
+ out[key] = resolveValue(val);
3032
3102
  } else {
3033
3103
  const shades = {};
3034
- for (const [shade, hex] of Object.entries(val)) {
3035
- shades[shade] = resolveChain(hex);
3104
+ for (const [shade, v] of Object.entries(val)) {
3105
+ shades[shade] = resolveValue(v);
3036
3106
  }
3037
3107
  out[key] = shades;
3038
3108
  }