@kbach/react 0.6.30 → 0.6.31
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/{chunk-FF4AZQIQ.mjs → chunk-MOWXWICC.mjs} +10 -8
- package/dist/{chunk-TKBIGAR2.mjs → chunk-OIJ6RP4F.mjs} +1369 -1297
- package/dist/core/index.d.ts +40 -3
- package/dist/core/index.js +1465 -1391
- package/dist/index.d.ts +1 -1
- package/dist/index.js +16 -11
- package/dist/index.mjs +18 -12
- package/dist/jsx-dev-runtime.js +8 -7
- package/dist/jsx-dev-runtime.mjs +2 -2
- package/dist/jsx-runtime.js +8 -7
- package/dist/jsx-runtime.mjs +2 -2
- package/dist/vite-plugin.d.mts +11 -2
- package/dist/vite-plugin.d.ts +11 -2
- package/dist/vite-plugin.js +80 -10
- package/dist/vite-plugin.mjs +80 -10
- package/kbach-react.md +23 -0
- package/package.json +1 -1
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
|
|
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
|
|
112
|
-
return
|
|
114
|
+
const color2 = target[shade];
|
|
115
|
+
return color2 !== void 0 ? applyOpacity(pickSide(color2, isDark), op) : void 0;
|
|
113
116
|
}
|
|
114
|
-
|
|
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
|
-
|
|
137
|
-
|
|
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
|
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-
|
|
46
|
+
} from "./chunk-OIJ6RP4F.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
|
|
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
|
|
87
|
-
return
|
|
90
|
+
const color2 = target[shade];
|
|
91
|
+
return color2 !== void 0 ? applyOpacity(pickSide(color2, isDark), op) : void 0;
|
|
88
92
|
}
|
|
89
|
-
|
|
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
|
-
|
|
112
|
-
|
|
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
|
package/dist/jsx-dev-runtime.js
CHANGED
|
@@ -650,11 +650,13 @@ function processElement(type, rawProps, key, isStaticChildren) {
|
|
|
650
650
|
return makeElement(isStaticChildren, effectiveType, workingProps, key);
|
|
651
651
|
}
|
|
652
652
|
const classStr = classStrRaw;
|
|
653
|
-
|
|
653
|
+
const config = (0, import_core6.getConfig)();
|
|
654
|
+
const expandedClassStr = classStr ? (0, import_core6.expandModeAwareColorClasses)(classStr, config.theme.colors) : classStr;
|
|
655
|
+
if (!import_core6.isNative && (0, import_core6.isRuntimeCSSDisabled)() && expandedClassStr && !__kbachStyles) {
|
|
654
656
|
const { style: userStyle2, ...passProps2 } = omitConsumed(workingProps);
|
|
655
657
|
return makeElement(isStaticChildren, effectiveType, {
|
|
656
658
|
...passProps2,
|
|
657
|
-
className: (0, import_core6.normalizeClassString)(
|
|
659
|
+
className: (0, import_core6.normalizeClassString)(expandedClassStr),
|
|
658
660
|
...userStyle2 !== void 0 ? { style: userStyle2 } : {}
|
|
659
661
|
}, key);
|
|
660
662
|
}
|
|
@@ -674,8 +676,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
|
|
|
674
676
|
const finalStyle2 = userStyle2 ? Array.isArray(userStyle2) ? { fontFamily: defaultFont, ...Object.assign({}, ...userStyle2) } : { fontFamily: defaultFont, ...userStyle2 } : { fontFamily: defaultFont };
|
|
675
677
|
return makeElement(isStaticChildren, effectiveType, { ...passProps2, style: finalStyle2 }, key);
|
|
676
678
|
}
|
|
677
|
-
const
|
|
678
|
-
const resolved = !import_core6.isWeb && __kbachStyles != null ? __kbachStyles : classStr ? (0, import_core6.resolve)(classStr, config.theme, config.darkMode) : {};
|
|
679
|
+
const resolved = !import_core6.isWeb && __kbachStyles != null ? __kbachStyles : expandedClassStr ? (0, import_core6.resolve)(expandedClassStr, config.theme, config.darkMode) : {};
|
|
679
680
|
const { style: rawUserStyle, ...passProps } = omitConsumed(workingProps);
|
|
680
681
|
const userStyle = withImpliedFlexIfNeeded(webTag, resolved.base, rawUserStyle);
|
|
681
682
|
const { interactive, modeOrResponsive } = bucketMods(resolved);
|
|
@@ -683,7 +684,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
|
|
|
683
684
|
return (0, import_jsx_runtime.jsx)(InteractiveWrapper, {
|
|
684
685
|
Component: effectiveType,
|
|
685
686
|
resolvedStyle: resolved,
|
|
686
|
-
...!import_core6.isNative &&
|
|
687
|
+
...!import_core6.isNative && expandedClassStr ? { className: (0, import_core6.normalizeClassString)(expandedClassStr) } : {},
|
|
687
688
|
style: userStyle,
|
|
688
689
|
...passProps
|
|
689
690
|
}, key);
|
|
@@ -692,7 +693,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
|
|
|
692
693
|
return (0, import_jsx_runtime.jsx)(DarkWrapper, {
|
|
693
694
|
Component: effectiveType,
|
|
694
695
|
resolvedStyle: resolved,
|
|
695
|
-
...!import_core6.isNative &&
|
|
696
|
+
...!import_core6.isNative && expandedClassStr ? { className: (0, import_core6.normalizeClassString)(expandedClassStr) } : {},
|
|
696
697
|
style: userStyle,
|
|
697
698
|
...passProps
|
|
698
699
|
}, key);
|
|
@@ -710,7 +711,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
|
|
|
710
711
|
return makeElement(isStaticChildren, effectiveType, {
|
|
711
712
|
...passProps,
|
|
712
713
|
...finalStyle !== void 0 ? { style: finalStyle } : {},
|
|
713
|
-
...!import_core6.isNative &&
|
|
714
|
+
...!import_core6.isNative && expandedClassStr ? { className: (0, import_core6.normalizeClassString)(expandedClassStr) } : {}
|
|
714
715
|
}, key);
|
|
715
716
|
}
|
|
716
717
|
function jsx(type, props, key) {
|
package/dist/jsx-dev-runtime.mjs
CHANGED
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
Fragment,
|
|
4
4
|
jsx,
|
|
5
5
|
jsxs
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-MOWXWICC.mjs";
|
|
7
|
+
import "./chunk-OIJ6RP4F.mjs";
|
|
8
8
|
|
|
9
9
|
// src/jsx-dev-runtime.tsx
|
|
10
10
|
function jsxDEV(type, props, key, isStaticChildren, source, self) {
|
package/dist/jsx-runtime.js
CHANGED
|
@@ -656,11 +656,13 @@ function processElement(type, rawProps, key, isStaticChildren) {
|
|
|
656
656
|
return makeElement(isStaticChildren, effectiveType, workingProps, key);
|
|
657
657
|
}
|
|
658
658
|
const classStr = classStrRaw;
|
|
659
|
-
|
|
659
|
+
const config = (0, import_core6.getConfig)();
|
|
660
|
+
const expandedClassStr = classStr ? (0, import_core6.expandModeAwareColorClasses)(classStr, config.theme.colors) : classStr;
|
|
661
|
+
if (!import_core6.isNative && (0, import_core6.isRuntimeCSSDisabled)() && expandedClassStr && !__kbachStyles) {
|
|
660
662
|
const { style: userStyle2, ...passProps2 } = omitConsumed(workingProps);
|
|
661
663
|
return makeElement(isStaticChildren, effectiveType, {
|
|
662
664
|
...passProps2,
|
|
663
|
-
className: (0, import_core6.normalizeClassString)(
|
|
665
|
+
className: (0, import_core6.normalizeClassString)(expandedClassStr),
|
|
664
666
|
...userStyle2 !== void 0 ? { style: userStyle2 } : {}
|
|
665
667
|
}, key);
|
|
666
668
|
}
|
|
@@ -680,8 +682,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
|
|
|
680
682
|
const finalStyle2 = userStyle2 ? Array.isArray(userStyle2) ? { fontFamily: defaultFont, ...Object.assign({}, ...userStyle2) } : { fontFamily: defaultFont, ...userStyle2 } : { fontFamily: defaultFont };
|
|
681
683
|
return makeElement(isStaticChildren, effectiveType, { ...passProps2, style: finalStyle2 }, key);
|
|
682
684
|
}
|
|
683
|
-
const
|
|
684
|
-
const resolved = !import_core6.isWeb && __kbachStyles != null ? __kbachStyles : classStr ? (0, import_core6.resolve)(classStr, config.theme, config.darkMode) : {};
|
|
685
|
+
const resolved = !import_core6.isWeb && __kbachStyles != null ? __kbachStyles : expandedClassStr ? (0, import_core6.resolve)(expandedClassStr, config.theme, config.darkMode) : {};
|
|
685
686
|
const { style: rawUserStyle, ...passProps } = omitConsumed(workingProps);
|
|
686
687
|
const userStyle = withImpliedFlexIfNeeded(webTag, resolved.base, rawUserStyle);
|
|
687
688
|
const { interactive, modeOrResponsive } = bucketMods(resolved);
|
|
@@ -689,7 +690,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
|
|
|
689
690
|
return (0, import_jsx_runtime.jsx)(InteractiveWrapper, {
|
|
690
691
|
Component: effectiveType,
|
|
691
692
|
resolvedStyle: resolved,
|
|
692
|
-
...!import_core6.isNative &&
|
|
693
|
+
...!import_core6.isNative && expandedClassStr ? { className: (0, import_core6.normalizeClassString)(expandedClassStr) } : {},
|
|
693
694
|
style: userStyle,
|
|
694
695
|
...passProps
|
|
695
696
|
}, key);
|
|
@@ -698,7 +699,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
|
|
|
698
699
|
return (0, import_jsx_runtime.jsx)(DarkWrapper, {
|
|
699
700
|
Component: effectiveType,
|
|
700
701
|
resolvedStyle: resolved,
|
|
701
|
-
...!import_core6.isNative &&
|
|
702
|
+
...!import_core6.isNative && expandedClassStr ? { className: (0, import_core6.normalizeClassString)(expandedClassStr) } : {},
|
|
702
703
|
style: userStyle,
|
|
703
704
|
...passProps
|
|
704
705
|
}, key);
|
|
@@ -716,7 +717,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
|
|
|
716
717
|
return makeElement(isStaticChildren, effectiveType, {
|
|
717
718
|
...passProps,
|
|
718
719
|
...finalStyle !== void 0 ? { style: finalStyle } : {},
|
|
719
|
-
...!import_core6.isNative &&
|
|
720
|
+
...!import_core6.isNative && expandedClassStr ? { className: (0, import_core6.normalizeClassString)(expandedClassStr) } : {}
|
|
720
721
|
}, key);
|
|
721
722
|
}
|
|
722
723
|
function jsx(type, props, key) {
|
package/dist/jsx-runtime.mjs
CHANGED
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
_invalidateDefaultFontCache,
|
|
5
5
|
jsx,
|
|
6
6
|
jsxs
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-MOWXWICC.mjs";
|
|
8
8
|
import {
|
|
9
9
|
registerWebElement
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-OIJ6RP4F.mjs";
|
|
11
11
|
export {
|
|
12
12
|
Fragment,
|
|
13
13
|
_invalidateDefaultFontCache,
|
package/dist/vite-plugin.d.mts
CHANGED
|
@@ -47,8 +47,17 @@ interface ModifierDef {
|
|
|
47
47
|
interface StyleValue {
|
|
48
48
|
[key: string]: string | number | undefined | null | StyleValue | StyleValue[];
|
|
49
49
|
}
|
|
50
|
-
|
|
51
|
-
|
|
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;
|
package/dist/vite-plugin.d.ts
CHANGED
|
@@ -47,8 +47,17 @@ interface ModifierDef {
|
|
|
47
47
|
interface StyleValue {
|
|
48
48
|
[key: string]: string | number | undefined | null | StyleValue | StyleValue[];
|
|
49
49
|
}
|
|
50
|
-
|
|
51
|
-
|
|
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;
|
package/dist/vite-plugin.js
CHANGED
|
@@ -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 (
|
|
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
|
-
|
|
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
|
-
|
|
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] =
|
|
3100
|
+
if (typeof val === "string" || isModeAwareColor(val)) {
|
|
3101
|
+
out[key] = resolveValue(val);
|
|
3032
3102
|
} else {
|
|
3033
3103
|
const shades = {};
|
|
3034
|
-
for (const [shade,
|
|
3035
|
-
shades[shade] =
|
|
3104
|
+
for (const [shade, v] of Object.entries(val)) {
|
|
3105
|
+
shades[shade] = resolveValue(v);
|
|
3036
3106
|
}
|
|
3037
3107
|
out[key] = shades;
|
|
3038
3108
|
}
|
package/dist/vite-plugin.mjs
CHANGED
|
@@ -615,7 +615,15 @@ var defaultTheme = {
|
|
|
615
615
|
animation: {}
|
|
616
616
|
};
|
|
617
617
|
|
|
618
|
+
// src/core/colorValue.ts
|
|
619
|
+
function isModeAwareColor(v) {
|
|
620
|
+
return typeof v === "object" && v !== null && "light" in v && "dark" in v;
|
|
621
|
+
}
|
|
622
|
+
|
|
618
623
|
// src/core/resolvers/color.ts
|
|
624
|
+
function pickModeAwareFallback(v) {
|
|
625
|
+
return isModeAwareColor(v) ? v.light : v;
|
|
626
|
+
}
|
|
619
627
|
function resolveColor(value, colors, isArbitrary) {
|
|
620
628
|
if (isArbitrary) return value;
|
|
621
629
|
const slashIdx = value.indexOf("/");
|
|
@@ -627,15 +635,17 @@ function resolveColor(value, colors, isArbitrary) {
|
|
|
627
635
|
} else if (colorPart in colors) {
|
|
628
636
|
const entry = colors[colorPart];
|
|
629
637
|
if (typeof entry === "string") hex = entry;
|
|
630
|
-
else if (
|
|
638
|
+
else if (isModeAwareColor(entry)) hex = pickModeAwareFallback(entry);
|
|
639
|
+
else if (typeof entry === "object" && "6" in entry) hex = pickModeAwareFallback(entry["6"]);
|
|
631
640
|
} else {
|
|
632
641
|
const lastDash = colorPart.lastIndexOf("-");
|
|
633
642
|
if (lastDash > 0) {
|
|
634
643
|
const colorName = colorPart.slice(0, lastDash);
|
|
635
644
|
const shade = colorPart.slice(lastDash + 1);
|
|
636
645
|
const scale = colors[colorName];
|
|
637
|
-
if (scale && typeof scale === "object" && shade in scale) {
|
|
638
|
-
|
|
646
|
+
if (scale && typeof scale === "object" && !isModeAwareColor(scale) && shade in scale) {
|
|
647
|
+
const shadeVal = scale[shade];
|
|
648
|
+
hex = shadeVal !== void 0 ? pickModeAwareFallback(shadeVal) : null;
|
|
639
649
|
}
|
|
640
650
|
}
|
|
641
651
|
}
|
|
@@ -2721,6 +2731,62 @@ function findOuterColon(s) {
|
|
|
2721
2731
|
return -1;
|
|
2722
2732
|
}
|
|
2723
2733
|
|
|
2734
|
+
// src/core/modeAwareColors.ts
|
|
2735
|
+
var _modeAwareMapCache = /* @__PURE__ */ new WeakMap();
|
|
2736
|
+
function buildModeAwareMap(colors) {
|
|
2737
|
+
const map = /* @__PURE__ */ new Map();
|
|
2738
|
+
for (const [name, entry] of Object.entries(colors)) {
|
|
2739
|
+
if (isModeAwareColor(entry)) {
|
|
2740
|
+
map.set(name, entry);
|
|
2741
|
+
} else if (entry && typeof entry === "object") {
|
|
2742
|
+
for (const [shade, val] of Object.entries(entry)) {
|
|
2743
|
+
if (isModeAwareColor(val)) map.set(`${name}-${shade}`, val);
|
|
2744
|
+
}
|
|
2745
|
+
}
|
|
2746
|
+
}
|
|
2747
|
+
return map;
|
|
2748
|
+
}
|
|
2749
|
+
function getModeAwareMap(colors) {
|
|
2750
|
+
let map = _modeAwareMapCache.get(colors);
|
|
2751
|
+
if (!map) {
|
|
2752
|
+
map = buildModeAwareMap(colors);
|
|
2753
|
+
_modeAwareMapCache.set(colors, map);
|
|
2754
|
+
}
|
|
2755
|
+
return map;
|
|
2756
|
+
}
|
|
2757
|
+
function expandModeAwareColorClasses(classString, colors) {
|
|
2758
|
+
const map = getModeAwareMap(colors);
|
|
2759
|
+
if (map.size === 0) return classString;
|
|
2760
|
+
const tokens = splitClassTokens(classString);
|
|
2761
|
+
let changed = false;
|
|
2762
|
+
const out = [];
|
|
2763
|
+
for (const token of tokens) {
|
|
2764
|
+
const parsed = parseClass(token);
|
|
2765
|
+
if (!parsed || parsed.isArbitrary) {
|
|
2766
|
+
out.push(token);
|
|
2767
|
+
continue;
|
|
2768
|
+
}
|
|
2769
|
+
if (parsed.modifiers.includes("dark") || parsed.modifiers.includes("light")) {
|
|
2770
|
+
out.push(token);
|
|
2771
|
+
continue;
|
|
2772
|
+
}
|
|
2773
|
+
const slashIdx = parsed.value.indexOf("/");
|
|
2774
|
+
const colorPart = slashIdx > 0 ? parsed.value.slice(0, slashIdx) : parsed.value;
|
|
2775
|
+
const opacitySuffix = slashIdx > 0 ? parsed.value.slice(slashIdx) : "";
|
|
2776
|
+
const pair = map.get(colorPart);
|
|
2777
|
+
if (!pair) {
|
|
2778
|
+
out.push(token);
|
|
2779
|
+
continue;
|
|
2780
|
+
}
|
|
2781
|
+
changed = true;
|
|
2782
|
+
const bang = parsed.important ? "!" : "";
|
|
2783
|
+
const modPrefix = parsed.modifiers.map((m) => `${m}:`).join("");
|
|
2784
|
+
out.push(`${bang}${modPrefix}${parsed.utility}-[${pair.light}]${opacitySuffix}`);
|
|
2785
|
+
out.push(`${bang}dark:${modPrefix}${parsed.utility}-[${pair.dark}]${opacitySuffix}`);
|
|
2786
|
+
}
|
|
2787
|
+
return changed ? out.join(" ") : classString;
|
|
2788
|
+
}
|
|
2789
|
+
|
|
2724
2790
|
// src/core/resolver.ts
|
|
2725
2791
|
var _defaultFontFamily;
|
|
2726
2792
|
function setDefaultFontFamily(font) {
|
|
@@ -2943,7 +3009,7 @@ function buildClassCSSRules(cls, bucketKey, styles, darkMode, important, screens
|
|
|
2943
3009
|
}
|
|
2944
3010
|
function generateClassCSS(classString, theme, darkMode = "attribute", screens = {}) {
|
|
2945
3011
|
const rules = [];
|
|
2946
|
-
for (const parsed of parseClasses(classString)) {
|
|
3012
|
+
for (const parsed of parseClasses(expandModeAwareColorClasses(classString, theme.colors))) {
|
|
2947
3013
|
const styles = resolveUtility(parsed, theme);
|
|
2948
3014
|
if (!styles) continue;
|
|
2949
3015
|
const bucketKey = parsed.modifiers.length === 0 ? "base" : parsed.modifiers.join(":");
|
|
@@ -2977,8 +3043,9 @@ function resolveOneRef(ref, colors) {
|
|
|
2977
3043
|
const shade = ref.slice(lastDash + 1);
|
|
2978
3044
|
if (!/^\d+$/.test(shade)) return null;
|
|
2979
3045
|
const entry = colors[name];
|
|
2980
|
-
if (!entry || typeof entry !== "object") return null;
|
|
2981
|
-
|
|
3046
|
+
if (!entry || typeof entry !== "object" || isModeAwareColor(entry)) return null;
|
|
3047
|
+
const target = entry[shade];
|
|
3048
|
+
return typeof target === "string" ? target : null;
|
|
2982
3049
|
}
|
|
2983
3050
|
function resolveColorRefs(colors) {
|
|
2984
3051
|
const MAX_DEPTH = 5;
|
|
@@ -2991,14 +3058,17 @@ function resolveColorRefs(colors) {
|
|
|
2991
3058
|
}
|
|
2992
3059
|
return current;
|
|
2993
3060
|
}
|
|
3061
|
+
function resolveValue(val) {
|
|
3062
|
+
return typeof val === "string" ? resolveChain(val) : { light: resolveChain(val.light), dark: resolveChain(val.dark) };
|
|
3063
|
+
}
|
|
2994
3064
|
const out = {};
|
|
2995
3065
|
for (const [key, val] of Object.entries(colors)) {
|
|
2996
|
-
if (typeof val === "string") {
|
|
2997
|
-
out[key] =
|
|
3066
|
+
if (typeof val === "string" || isModeAwareColor(val)) {
|
|
3067
|
+
out[key] = resolveValue(val);
|
|
2998
3068
|
} else {
|
|
2999
3069
|
const shades = {};
|
|
3000
|
-
for (const [shade,
|
|
3001
|
-
shades[shade] =
|
|
3070
|
+
for (const [shade, v] of Object.entries(val)) {
|
|
3071
|
+
shades[shade] = resolveValue(v);
|
|
3002
3072
|
}
|
|
3003
3073
|
out[key] = shades;
|
|
3004
3074
|
}
|
package/kbach-react.md
CHANGED
|
@@ -712,6 +712,29 @@ module.exports = {
|
|
|
712
712
|
|
|
713
713
|
**Global default font (web):** Setting `fontFamily.sans` to anything other than `'System'` auto-injects `body { font-family: <font> }`.
|
|
714
714
|
|
|
715
|
+
### Mode-aware colors (dark mode without `dark:`)
|
|
716
|
+
|
|
717
|
+
A color value can be `{ light, dark }` instead of a plain string — define it once, and every class using that color automatically picks the right side, with no `dark:` variant needed at the call site:
|
|
718
|
+
|
|
719
|
+
```js
|
|
720
|
+
extend: {
|
|
721
|
+
theme: {
|
|
722
|
+
colors: {
|
|
723
|
+
surface: { light: '#ffffff', dark: '#111827' },
|
|
724
|
+
// each side can itself be an alias — resolved independently
|
|
725
|
+
accent: { light: 'blue-6', dark: 'blue-4' },
|
|
726
|
+
},
|
|
727
|
+
},
|
|
728
|
+
},
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
```jsx
|
|
732
|
+
<div className="bg-surface text-accent" />
|
|
733
|
+
// equivalent to writing bg-white dark:bg-gray-9 text-blue-6 dark:text-blue-4 by hand
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
Works everywhere a color does — `useColors()` (returns the active side directly), opacity composition (`bg-surface/50`), and per-shade within a scale (`brand: { 6: { light: '#3b82f6', dark: '#60a5fa' } }`). An explicit `dark:`/`light:` modifier stacked on an already mode-aware color is not supported (falls back to the light side) — the whole point is not needing `dark:` for these.
|
|
737
|
+
|
|
715
738
|
### Runtime update
|
|
716
739
|
```js
|
|
717
740
|
import { updateConfig, clearCache } from '@kbach/react';
|