@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/{chunk-TKBIGAR2.mjs → chunk-E322MVGC.mjs} +1370 -1298
- package/dist/{chunk-FF4AZQIQ.mjs → chunk-JUGDQQQ4.mjs} +12 -11
- 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 +18 -14
- package/dist/index.mjs +19 -14
- package/dist/jsx-dev-runtime.js +11 -11
- package/dist/jsx-dev-runtime.mjs +2 -2
- package/dist/jsx-runtime.js +11 -11
- 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/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';
|