@kbach/react 0.6.5 → 0.6.7
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/README.md +3 -1
- package/dist/{chunk-FXDK5Z6V.mjs → chunk-5YN6PIXQ.mjs} +1 -1
- package/dist/{chunk-BAUO36PM.mjs → chunk-LXOMVLQI.mjs} +13 -4
- package/dist/index.js +13 -4
- package/dist/index.mjs +1 -1
- package/dist/jsx-dev-runtime.js +13 -4
- package/dist/jsx-dev-runtime.mjs +2 -2
- package/dist/jsx-runtime.js +13 -4
- package/dist/jsx-runtime.mjs +2 -2
- package/dist/vite-plugin.js +72 -14
- package/dist/vite-plugin.mjs +73 -15
- package/kbach-react.md +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,6 +73,8 @@ export default defineConfig({
|
|
|
73
73
|
});
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
Adding the plugin also declares `@kbach/react` in Vite's `optimizeDeps.include` upfront, so Vite pre-bundles it during its initial dependency scan instead of discovering it lazily on the first page that imports it — avoiding a forced full-reload mid-render, which is what a rare "Invalid hook call"-style crash on first load (but never again after) usually turns out to be.
|
|
77
|
+
|
|
76
78
|
Then create an empty `kbach.css` anywhere in your project and import it once in your app entry:
|
|
77
79
|
|
|
78
80
|
```css
|
|
@@ -88,7 +90,7 @@ import './kbach.css';
|
|
|
88
90
|
|
|
89
91
|
The plugin scans your source files and writes generated CSS between the `/* kbach:start */`/`/* kbach:end */` markers. Importing `kbach.css` automatically disables runtime injection — all styles come from the file instead. On HMR, only the changed file is rescanned; unchanged tokens reuse cached CSS.
|
|
90
92
|
|
|
91
|
-
While it's scanning, the plugin also indexes every `.css`/`.scss`/`.sass`/`.less` file under the same directories and warns in the terminal (not the browser console) for any class that's neither a real Kbach utility nor defined anywhere in those stylesheets — likely a typo. A class you've defined yourself elsewhere (CSS Modules, styled-components, a third-party component's class) is recognized as soon as something in the project literally has a `.that-class-name` rule, so it won't get flagged just because Kbach itself doesn't know it.
|
|
93
|
+
While it's scanning, the plugin also indexes every `.css`/`.scss`/`.sass`/`.less` file under the same directories and warns in the terminal (not the browser console) for any class that's neither a real Kbach utility nor defined anywhere in those stylesheets — likely a typo. A class you've defined yourself elsewhere (CSS Modules, styled-components, a third-party component's class) is recognized as soon as something in the project literally has a `.that-class-name` rule, so it won't get flagged just because Kbach itself doesn't know it. Each warning includes a `file:line:column` location that most terminals (VS Code's integrated terminal included) turn into a clickable link straight to that class.
|
|
92
94
|
|
|
93
95
|
## Next.js
|
|
94
96
|
|
|
@@ -565,6 +565,15 @@ function escapeCSSSelector(cls) {
|
|
|
565
565
|
return cls.replace(/[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&");
|
|
566
566
|
}
|
|
567
567
|
|
|
568
|
+
// src/core/devWarn.ts
|
|
569
|
+
function kbachWarn(message) {
|
|
570
|
+
console.warn(
|
|
571
|
+
"%c[kbach]%c " + message,
|
|
572
|
+
"color:#8b5cf6;font-weight:700",
|
|
573
|
+
"color:inherit;font-weight:400"
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
|
|
568
577
|
// src/core/registry.ts
|
|
569
578
|
var BUILTIN_MODIFIERS = {
|
|
570
579
|
// ── Mode ─────────────────────────────────────────────────────────────────
|
|
@@ -640,7 +649,7 @@ function _invalidate() {
|
|
|
640
649
|
}
|
|
641
650
|
function registerModifier(name, def) {
|
|
642
651
|
if (process.env.NODE_ENV !== "production" && name in BUILTIN_MODIFIERS) {
|
|
643
|
-
|
|
652
|
+
kbachWarn(`"${name}" is built-in \u2014 pick another modifier name`);
|
|
644
653
|
return;
|
|
645
654
|
}
|
|
646
655
|
_pluginModifiers[name] = def;
|
|
@@ -2434,7 +2443,7 @@ function parseClass(className) {
|
|
|
2434
2443
|
}
|
|
2435
2444
|
if (remaining.endsWith("]") && bracketStart === -1) {
|
|
2436
2445
|
if (process.env.NODE_ENV !== "production") {
|
|
2437
|
-
|
|
2446
|
+
kbachWarn(`Unbalanced brackets: "${trimmed}"`);
|
|
2438
2447
|
}
|
|
2439
2448
|
}
|
|
2440
2449
|
if (remaining.startsWith("[") && remaining.endsWith("]")) {
|
|
@@ -2901,7 +2910,7 @@ function resolve(classString, theme, darkMode = "attribute") {
|
|
|
2901
2910
|
const styles = resolveUtility(parsed, theme);
|
|
2902
2911
|
if (!styles) {
|
|
2903
2912
|
if (process.env.NODE_ENV !== "production" && !parsed.isArbitrary && !isKnownUtility(parsed.utility) && !parsed.original.startsWith("__")) {
|
|
2904
|
-
|
|
2913
|
+
kbachWarn(`Unknown class "${parsed.original}"`);
|
|
2905
2914
|
}
|
|
2906
2915
|
continue;
|
|
2907
2916
|
}
|
|
@@ -3056,7 +3065,7 @@ function buildConfig(userConfig) {
|
|
|
3056
3065
|
for (const [key, value] of Object.entries(ext)) {
|
|
3057
3066
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
3058
3067
|
if (process.env.NODE_ENV !== "production") {
|
|
3059
|
-
|
|
3068
|
+
kbachWarn(`extend.${key} should be an object, got ${typeof value} \u2014 skipped`);
|
|
3060
3069
|
}
|
|
3061
3070
|
continue;
|
|
3062
3071
|
}
|
package/dist/index.js
CHANGED
|
@@ -690,6 +690,15 @@ function escapeCSSSelector(cls) {
|
|
|
690
690
|
return cls.replace(/[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&");
|
|
691
691
|
}
|
|
692
692
|
|
|
693
|
+
// src/core/devWarn.ts
|
|
694
|
+
function kbachWarn(message) {
|
|
695
|
+
console.warn(
|
|
696
|
+
"%c[kbach]%c " + message,
|
|
697
|
+
"color:#8b5cf6;font-weight:700",
|
|
698
|
+
"color:inherit;font-weight:400"
|
|
699
|
+
);
|
|
700
|
+
}
|
|
701
|
+
|
|
693
702
|
// src/core/registry.ts
|
|
694
703
|
var BUILTIN_MODIFIERS = {
|
|
695
704
|
// ── Mode ─────────────────────────────────────────────────────────────────
|
|
@@ -765,7 +774,7 @@ function _invalidate() {
|
|
|
765
774
|
}
|
|
766
775
|
function registerModifier(name, def) {
|
|
767
776
|
if (process.env.NODE_ENV !== "production" && name in BUILTIN_MODIFIERS) {
|
|
768
|
-
|
|
777
|
+
kbachWarn(`"${name}" is built-in \u2014 pick another modifier name`);
|
|
769
778
|
return;
|
|
770
779
|
}
|
|
771
780
|
_pluginModifiers[name] = def;
|
|
@@ -2553,7 +2562,7 @@ function parseClass(className) {
|
|
|
2553
2562
|
}
|
|
2554
2563
|
if (remaining.endsWith("]") && bracketStart === -1) {
|
|
2555
2564
|
if (process.env.NODE_ENV !== "production") {
|
|
2556
|
-
|
|
2565
|
+
kbachWarn(`Unbalanced brackets: "${trimmed}"`);
|
|
2557
2566
|
}
|
|
2558
2567
|
}
|
|
2559
2568
|
if (remaining.startsWith("[") && remaining.endsWith("]")) {
|
|
@@ -2979,7 +2988,7 @@ function resolve(classString, theme, darkMode = "attribute") {
|
|
|
2979
2988
|
const styles = resolveUtility(parsed, theme);
|
|
2980
2989
|
if (!styles) {
|
|
2981
2990
|
if (process.env.NODE_ENV !== "production" && !parsed.isArbitrary && !isKnownUtility(parsed.utility) && !parsed.original.startsWith("__")) {
|
|
2982
|
-
|
|
2991
|
+
kbachWarn(`Unknown class "${parsed.original}"`);
|
|
2983
2992
|
}
|
|
2984
2993
|
continue;
|
|
2985
2994
|
}
|
|
@@ -3134,7 +3143,7 @@ function buildConfig(userConfig) {
|
|
|
3134
3143
|
for (const [key, value] of Object.entries(ext)) {
|
|
3135
3144
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
3136
3145
|
if (process.env.NODE_ENV !== "production") {
|
|
3137
|
-
|
|
3146
|
+
kbachWarn(`extend.${key} should be an object, got ${typeof value} \u2014 skipped`);
|
|
3138
3147
|
}
|
|
3139
3148
|
continue;
|
|
3140
3149
|
}
|
package/dist/index.mjs
CHANGED
package/dist/jsx-dev-runtime.js
CHANGED
|
@@ -643,6 +643,15 @@ function escapeCSSSelector(cls) {
|
|
|
643
643
|
return cls.replace(/[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&");
|
|
644
644
|
}
|
|
645
645
|
|
|
646
|
+
// src/core/devWarn.ts
|
|
647
|
+
function kbachWarn(message) {
|
|
648
|
+
console.warn(
|
|
649
|
+
"%c[kbach]%c " + message,
|
|
650
|
+
"color:#8b5cf6;font-weight:700",
|
|
651
|
+
"color:inherit;font-weight:400"
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
|
|
646
655
|
// src/core/registry.ts
|
|
647
656
|
var BUILTIN_MODIFIERS = {
|
|
648
657
|
// ── Mode ─────────────────────────────────────────────────────────────────
|
|
@@ -718,7 +727,7 @@ function _invalidate() {
|
|
|
718
727
|
}
|
|
719
728
|
function registerModifier(name, def) {
|
|
720
729
|
if (process.env.NODE_ENV !== "production" && name in BUILTIN_MODIFIERS) {
|
|
721
|
-
|
|
730
|
+
kbachWarn(`"${name}" is built-in \u2014 pick another modifier name`);
|
|
722
731
|
return;
|
|
723
732
|
}
|
|
724
733
|
_pluginModifiers[name] = def;
|
|
@@ -2512,7 +2521,7 @@ function parseClass(className) {
|
|
|
2512
2521
|
}
|
|
2513
2522
|
if (remaining.endsWith("]") && bracketStart === -1) {
|
|
2514
2523
|
if (process.env.NODE_ENV !== "production") {
|
|
2515
|
-
|
|
2524
|
+
kbachWarn(`Unbalanced brackets: "${trimmed}"`);
|
|
2516
2525
|
}
|
|
2517
2526
|
}
|
|
2518
2527
|
if (remaining.startsWith("[") && remaining.endsWith("]")) {
|
|
@@ -2923,7 +2932,7 @@ function resolve(classString, theme, darkMode = "attribute") {
|
|
|
2923
2932
|
const styles = resolveUtility(parsed, theme);
|
|
2924
2933
|
if (!styles) {
|
|
2925
2934
|
if (process.env.NODE_ENV !== "production" && !parsed.isArbitrary && !isKnownUtility(parsed.utility) && !parsed.original.startsWith("__")) {
|
|
2926
|
-
|
|
2935
|
+
kbachWarn(`Unknown class "${parsed.original}"`);
|
|
2927
2936
|
}
|
|
2928
2937
|
continue;
|
|
2929
2938
|
}
|
|
@@ -3067,7 +3076,7 @@ function buildConfig(userConfig) {
|
|
|
3067
3076
|
for (const [key, value] of Object.entries(ext)) {
|
|
3068
3077
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
3069
3078
|
if (process.env.NODE_ENV !== "production") {
|
|
3070
|
-
|
|
3079
|
+
kbachWarn(`extend.${key} should be an object, got ${typeof value} \u2014 skipped`);
|
|
3071
3080
|
}
|
|
3072
3081
|
continue;
|
|
3073
3082
|
}
|
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-5YN6PIXQ.mjs";
|
|
7
|
+
import "./chunk-LXOMVLQI.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
|
@@ -644,6 +644,15 @@ function escapeCSSSelector(cls) {
|
|
|
644
644
|
return cls.replace(/[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&");
|
|
645
645
|
}
|
|
646
646
|
|
|
647
|
+
// src/core/devWarn.ts
|
|
648
|
+
function kbachWarn(message) {
|
|
649
|
+
console.warn(
|
|
650
|
+
"%c[kbach]%c " + message,
|
|
651
|
+
"color:#8b5cf6;font-weight:700",
|
|
652
|
+
"color:inherit;font-weight:400"
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
|
|
647
656
|
// src/core/registry.ts
|
|
648
657
|
var BUILTIN_MODIFIERS = {
|
|
649
658
|
// ── Mode ─────────────────────────────────────────────────────────────────
|
|
@@ -719,7 +728,7 @@ function _invalidate() {
|
|
|
719
728
|
}
|
|
720
729
|
function registerModifier(name, def) {
|
|
721
730
|
if (process.env.NODE_ENV !== "production" && name in BUILTIN_MODIFIERS) {
|
|
722
|
-
|
|
731
|
+
kbachWarn(`"${name}" is built-in \u2014 pick another modifier name`);
|
|
723
732
|
return;
|
|
724
733
|
}
|
|
725
734
|
_pluginModifiers[name] = def;
|
|
@@ -2513,7 +2522,7 @@ function parseClass(className) {
|
|
|
2513
2522
|
}
|
|
2514
2523
|
if (remaining.endsWith("]") && bracketStart === -1) {
|
|
2515
2524
|
if (process.env.NODE_ENV !== "production") {
|
|
2516
|
-
|
|
2525
|
+
kbachWarn(`Unbalanced brackets: "${trimmed}"`);
|
|
2517
2526
|
}
|
|
2518
2527
|
}
|
|
2519
2528
|
if (remaining.startsWith("[") && remaining.endsWith("]")) {
|
|
@@ -2924,7 +2933,7 @@ function resolve(classString, theme, darkMode = "attribute") {
|
|
|
2924
2933
|
const styles = resolveUtility(parsed, theme);
|
|
2925
2934
|
if (!styles) {
|
|
2926
2935
|
if (process.env.NODE_ENV !== "production" && !parsed.isArbitrary && !isKnownUtility(parsed.utility) && !parsed.original.startsWith("__")) {
|
|
2927
|
-
|
|
2936
|
+
kbachWarn(`Unknown class "${parsed.original}"`);
|
|
2928
2937
|
}
|
|
2929
2938
|
continue;
|
|
2930
2939
|
}
|
|
@@ -3068,7 +3077,7 @@ function buildConfig(userConfig) {
|
|
|
3068
3077
|
for (const [key, value] of Object.entries(ext)) {
|
|
3069
3078
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
3070
3079
|
if (process.env.NODE_ENV !== "production") {
|
|
3071
|
-
|
|
3080
|
+
kbachWarn(`extend.${key} should be an object, got ${typeof value} \u2014 skipped`);
|
|
3072
3081
|
}
|
|
3073
3082
|
continue;
|
|
3074
3083
|
}
|
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-5YN6PIXQ.mjs";
|
|
8
8
|
import {
|
|
9
9
|
registerWebElement
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-LXOMVLQI.mjs";
|
|
11
11
|
export {
|
|
12
12
|
Fragment,
|
|
13
13
|
_invalidateDefaultFontCache,
|
package/dist/vite-plugin.js
CHANGED
|
@@ -2307,6 +2307,15 @@ function getBuiltinStandaloneNames() {
|
|
|
2307
2307
|
return _standaloneNames;
|
|
2308
2308
|
}
|
|
2309
2309
|
|
|
2310
|
+
// src/core/devWarn.ts
|
|
2311
|
+
function kbachWarn(message) {
|
|
2312
|
+
console.warn(
|
|
2313
|
+
"%c[kbach]%c " + message,
|
|
2314
|
+
"color:#8b5cf6;font-weight:700",
|
|
2315
|
+
"color:inherit;font-weight:400"
|
|
2316
|
+
);
|
|
2317
|
+
}
|
|
2318
|
+
|
|
2310
2319
|
// src/core/registry.ts
|
|
2311
2320
|
var BUILTIN_MODIFIERS = {
|
|
2312
2321
|
// ── Mode ─────────────────────────────────────────────────────────────────
|
|
@@ -2382,7 +2391,7 @@ function _invalidate() {
|
|
|
2382
2391
|
}
|
|
2383
2392
|
function registerModifier(name, def) {
|
|
2384
2393
|
if (process.env.NODE_ENV !== "production" && name in BUILTIN_MODIFIERS) {
|
|
2385
|
-
|
|
2394
|
+
kbachWarn(`"${name}" is built-in \u2014 pick another modifier name`);
|
|
2386
2395
|
return;
|
|
2387
2396
|
}
|
|
2388
2397
|
_pluginModifiers[name] = def;
|
|
@@ -2461,7 +2470,7 @@ function parseClass(className) {
|
|
|
2461
2470
|
}
|
|
2462
2471
|
if (remaining.endsWith("]") && bracketStart === -1) {
|
|
2463
2472
|
if (process.env.NODE_ENV !== "production") {
|
|
2464
|
-
|
|
2473
|
+
kbachWarn(`Unbalanced brackets: "${trimmed}"`);
|
|
2465
2474
|
}
|
|
2466
2475
|
}
|
|
2467
2476
|
if (remaining.startsWith("[") && remaining.endsWith("]")) {
|
|
@@ -2897,7 +2906,7 @@ function buildConfig(userConfig) {
|
|
|
2897
2906
|
for (const [key, value] of Object.entries(ext)) {
|
|
2898
2907
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
2899
2908
|
if (process.env.NODE_ENV !== "production") {
|
|
2900
|
-
|
|
2909
|
+
kbachWarn(`extend.${key} should be an object, got ${typeof value} \u2014 skipped`);
|
|
2901
2910
|
}
|
|
2902
2911
|
continue;
|
|
2903
2912
|
}
|
|
@@ -2996,6 +3005,39 @@ function normPath(p) {
|
|
|
2996
3005
|
return process2.platform === "win32" ? fwd.toLowerCase() : fwd;
|
|
2997
3006
|
}
|
|
2998
3007
|
setCSSGenMode(true);
|
|
3008
|
+
var useColor = !!process2.stdout?.isTTY && !process2.env.NO_COLOR;
|
|
3009
|
+
var paint = (code, s) => useColor ? `\x1B[${code}m${s}\x1B[0m` : s;
|
|
3010
|
+
var purple = (s) => paint("35", s);
|
|
3011
|
+
var yellow = (s) => paint("33", s);
|
|
3012
|
+
var dim = (s) => paint("2", s);
|
|
3013
|
+
var bold = (s) => paint("1", s);
|
|
3014
|
+
var TAG = () => `${bold(purple("[kbach]"))}`;
|
|
3015
|
+
function warn(message) {
|
|
3016
|
+
console.warn(`${TAG()} ${yellow(message)}`);
|
|
3017
|
+
}
|
|
3018
|
+
function warnBlock(header, ...lines) {
|
|
3019
|
+
console.warn([`${TAG()} ${yellow(header)}`, ...lines].join("\n"));
|
|
3020
|
+
}
|
|
3021
|
+
function findLineCol(code, needle) {
|
|
3022
|
+
const index = code.indexOf(needle);
|
|
3023
|
+
if (index === -1) return null;
|
|
3024
|
+
let line = 1;
|
|
3025
|
+
let lastNewline = -1;
|
|
3026
|
+
for (let i = 0; i < index; i++) {
|
|
3027
|
+
if (code.charCodeAt(i) === 10) {
|
|
3028
|
+
line++;
|
|
3029
|
+
lastNewline = i;
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
return { line, column: index - lastNewline };
|
|
3033
|
+
}
|
|
3034
|
+
function warnAt(message, root, filePath, code, needle) {
|
|
3035
|
+
const pos = findLineCol(code, needle);
|
|
3036
|
+
const relPath = (0, import_path.relative)(root, filePath).replace(/\\/g, "/");
|
|
3037
|
+
const location = pos ? `${relPath}:${pos.line}:${pos.column}` : relPath;
|
|
3038
|
+
console.warn(`${TAG()} ${yellow(message)}
|
|
3039
|
+
${dim("at")} ${location}`);
|
|
3040
|
+
}
|
|
2999
3041
|
var KBACH_START = "/* kbach:start */";
|
|
3000
3042
|
var KBACH_END = "/* kbach:end */";
|
|
3001
3043
|
var GROUPS = [
|
|
@@ -3118,8 +3160,9 @@ function findKbachCSS(root) {
|
|
|
3118
3160
|
if (found.length === 0) return null;
|
|
3119
3161
|
found.sort((a, b) => a.split(/[\\/]/g).length - b.split(/[\\/]/g).length);
|
|
3120
3162
|
if (found.length > 1) {
|
|
3121
|
-
|
|
3122
|
-
|
|
3163
|
+
warnBlock(
|
|
3164
|
+
`Multiple kbach.css found, using the shallowest \u2014 remove the rest:`,
|
|
3165
|
+
...found.map((f) => dim(` ${f}`))
|
|
3123
3166
|
);
|
|
3124
3167
|
}
|
|
3125
3168
|
return found[0];
|
|
@@ -3208,7 +3251,7 @@ function scanDir(dir, onFile) {
|
|
|
3208
3251
|
entries = (0, import_fs.readdirSync)(dir);
|
|
3209
3252
|
} catch (err) {
|
|
3210
3253
|
if (err.code !== "ENOENT") {
|
|
3211
|
-
|
|
3254
|
+
warn(`Can't read ${dir}: ${err.message}`);
|
|
3212
3255
|
}
|
|
3213
3256
|
return;
|
|
3214
3257
|
}
|
|
@@ -3220,7 +3263,7 @@ function scanDir(dir, onFile) {
|
|
|
3220
3263
|
if (st.isDirectory()) scanDir(full, onFile);
|
|
3221
3264
|
else if (/\.(tsx?|jsx?)$/.test(entry)) onFile(full, (0, import_fs.readFileSync)(full, "utf-8"));
|
|
3222
3265
|
} catch (err) {
|
|
3223
|
-
|
|
3266
|
+
warn(`Can't process ${full}: ${err.message}`);
|
|
3224
3267
|
}
|
|
3225
3268
|
}
|
|
3226
3269
|
}
|
|
@@ -3272,16 +3315,14 @@ function kbach(userConfigOrOptions) {
|
|
|
3272
3315
|
const tokenCSS = /* @__PURE__ */ new Map();
|
|
3273
3316
|
const projectCssClasses = /* @__PURE__ */ new Set();
|
|
3274
3317
|
const warnedTokens = /* @__PURE__ */ new Set();
|
|
3275
|
-
function checkUnknownToken(tok) {
|
|
3318
|
+
function checkUnknownToken(tok, filePath, code) {
|
|
3276
3319
|
if (process2.env.NODE_ENV === "production" || warnedTokens.has(tok) || tok.startsWith("__")) return;
|
|
3277
3320
|
const parsed = parseClass(tok);
|
|
3278
3321
|
if (parsed && resolveUtility(parsed, cfg.theme) !== null) return;
|
|
3279
3322
|
const base = stripModifierPrefix(tok);
|
|
3280
3323
|
if (!base || projectCssClasses.has(base)) return;
|
|
3281
3324
|
warnedTokens.add(tok);
|
|
3282
|
-
|
|
3283
|
-
`[kbach] "${tok}" isn't a Kbach utility and no matching CSS rule was found anywhere in the project (checked .css/.scss/.sass/.less files) \u2014 possible typo? If this is intentional (a third-party class, one defined via CSS-in-JS, etc.), this warning is safe to ignore.`
|
|
3284
|
-
);
|
|
3325
|
+
warnAt(`Unknown class "${tok}" \u2014 no Kbach utility or project CSS rule matches it. Typo?`, root, filePath, code, tok);
|
|
3285
3326
|
}
|
|
3286
3327
|
function processFile(filePath, code) {
|
|
3287
3328
|
const key = normPath(filePath);
|
|
@@ -3291,7 +3332,7 @@ function kbach(userConfigOrOptions) {
|
|
|
3291
3332
|
if (!tokenCSS.has(tok)) {
|
|
3292
3333
|
tokenCSS.set(tok, generateClassCSS(tok, cfg.theme, cfg.darkMode, screens));
|
|
3293
3334
|
}
|
|
3294
|
-
checkUnknownToken(tok);
|
|
3335
|
+
checkUnknownToken(tok, filePath, code);
|
|
3295
3336
|
}
|
|
3296
3337
|
fileTokens.set(key, tokens);
|
|
3297
3338
|
}
|
|
@@ -3319,12 +3360,29 @@ function kbach(userConfigOrOptions) {
|
|
|
3319
3360
|
return {
|
|
3320
3361
|
name: "kbach",
|
|
3321
3362
|
enforce: "pre",
|
|
3363
|
+
// Without this, Vite only discovers @kbach/react needs pre-bundling once it
|
|
3364
|
+
// actually crawls into an import of it — typically the FIRST page load — and
|
|
3365
|
+
// has to stop, optimize it, and force a full reload mid-render. That reload
|
|
3366
|
+
// can land in the middle of a render pass (React hooks resolving against a
|
|
3367
|
+
// module graph that's being swapped out from under it), which is what an
|
|
3368
|
+
// "Invalid hook call" / hook-related crash on first load only usually is.
|
|
3369
|
+
// Declaring it here upfront means Vite pre-bundles it during its initial
|
|
3370
|
+
// dependency scan, before any page ever requests it — no mid-render reload.
|
|
3371
|
+
config() {
|
|
3372
|
+
return {
|
|
3373
|
+
optimizeDeps: {
|
|
3374
|
+
include: ["@kbach/react", "@kbach/react/jsx-runtime", "@kbach/react/jsx-dev-runtime"]
|
|
3375
|
+
}
|
|
3376
|
+
};
|
|
3377
|
+
},
|
|
3322
3378
|
configResolved(resolved) {
|
|
3323
3379
|
root = resolved.root;
|
|
3324
3380
|
const names = new Set(resolved.plugins.map((p) => p.name));
|
|
3325
3381
|
if (names.has("react-router") && names.has("vite:react-refresh")) {
|
|
3326
|
-
|
|
3327
|
-
|
|
3382
|
+
warnBlock(
|
|
3383
|
+
"@vitejs/plugin-react + reactRouter() conflict \u2014 page will crash before styles apply.",
|
|
3384
|
+
dim(' Both inject Fast Refresh ("RefreshRuntime already declared").'),
|
|
3385
|
+
dim(" Fix: remove react() from vite.config.ts \u2014 tsconfig jsxImportSource is enough.")
|
|
3328
3386
|
);
|
|
3329
3387
|
}
|
|
3330
3388
|
},
|
package/dist/vite-plugin.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/vite-plugin.ts
|
|
2
2
|
import { readFileSync, writeFileSync, readdirSync, statSync } from "fs";
|
|
3
|
-
import { join } from "path";
|
|
3
|
+
import { join, relative } from "path";
|
|
4
4
|
import processImport from "process";
|
|
5
5
|
|
|
6
6
|
// src/core/platform.ts
|
|
@@ -2273,6 +2273,15 @@ function getBuiltinStandaloneNames() {
|
|
|
2273
2273
|
return _standaloneNames;
|
|
2274
2274
|
}
|
|
2275
2275
|
|
|
2276
|
+
// src/core/devWarn.ts
|
|
2277
|
+
function kbachWarn(message) {
|
|
2278
|
+
console.warn(
|
|
2279
|
+
"%c[kbach]%c " + message,
|
|
2280
|
+
"color:#8b5cf6;font-weight:700",
|
|
2281
|
+
"color:inherit;font-weight:400"
|
|
2282
|
+
);
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2276
2285
|
// src/core/registry.ts
|
|
2277
2286
|
var BUILTIN_MODIFIERS = {
|
|
2278
2287
|
// ── Mode ─────────────────────────────────────────────────────────────────
|
|
@@ -2348,7 +2357,7 @@ function _invalidate() {
|
|
|
2348
2357
|
}
|
|
2349
2358
|
function registerModifier(name, def) {
|
|
2350
2359
|
if (process.env.NODE_ENV !== "production" && name in BUILTIN_MODIFIERS) {
|
|
2351
|
-
|
|
2360
|
+
kbachWarn(`"${name}" is built-in \u2014 pick another modifier name`);
|
|
2352
2361
|
return;
|
|
2353
2362
|
}
|
|
2354
2363
|
_pluginModifiers[name] = def;
|
|
@@ -2427,7 +2436,7 @@ function parseClass(className) {
|
|
|
2427
2436
|
}
|
|
2428
2437
|
if (remaining.endsWith("]") && bracketStart === -1) {
|
|
2429
2438
|
if (process.env.NODE_ENV !== "production") {
|
|
2430
|
-
|
|
2439
|
+
kbachWarn(`Unbalanced brackets: "${trimmed}"`);
|
|
2431
2440
|
}
|
|
2432
2441
|
}
|
|
2433
2442
|
if (remaining.startsWith("[") && remaining.endsWith("]")) {
|
|
@@ -2863,7 +2872,7 @@ function buildConfig(userConfig) {
|
|
|
2863
2872
|
for (const [key, value] of Object.entries(ext)) {
|
|
2864
2873
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
2865
2874
|
if (process.env.NODE_ENV !== "production") {
|
|
2866
|
-
|
|
2875
|
+
kbachWarn(`extend.${key} should be an object, got ${typeof value} \u2014 skipped`);
|
|
2867
2876
|
}
|
|
2868
2877
|
continue;
|
|
2869
2878
|
}
|
|
@@ -2962,6 +2971,39 @@ function normPath(p) {
|
|
|
2962
2971
|
return process2.platform === "win32" ? fwd.toLowerCase() : fwd;
|
|
2963
2972
|
}
|
|
2964
2973
|
setCSSGenMode(true);
|
|
2974
|
+
var useColor = !!process2.stdout?.isTTY && !process2.env.NO_COLOR;
|
|
2975
|
+
var paint = (code, s) => useColor ? `\x1B[${code}m${s}\x1B[0m` : s;
|
|
2976
|
+
var purple = (s) => paint("35", s);
|
|
2977
|
+
var yellow = (s) => paint("33", s);
|
|
2978
|
+
var dim = (s) => paint("2", s);
|
|
2979
|
+
var bold = (s) => paint("1", s);
|
|
2980
|
+
var TAG = () => `${bold(purple("[kbach]"))}`;
|
|
2981
|
+
function warn(message) {
|
|
2982
|
+
console.warn(`${TAG()} ${yellow(message)}`);
|
|
2983
|
+
}
|
|
2984
|
+
function warnBlock(header, ...lines) {
|
|
2985
|
+
console.warn([`${TAG()} ${yellow(header)}`, ...lines].join("\n"));
|
|
2986
|
+
}
|
|
2987
|
+
function findLineCol(code, needle) {
|
|
2988
|
+
const index = code.indexOf(needle);
|
|
2989
|
+
if (index === -1) return null;
|
|
2990
|
+
let line = 1;
|
|
2991
|
+
let lastNewline = -1;
|
|
2992
|
+
for (let i = 0; i < index; i++) {
|
|
2993
|
+
if (code.charCodeAt(i) === 10) {
|
|
2994
|
+
line++;
|
|
2995
|
+
lastNewline = i;
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
return { line, column: index - lastNewline };
|
|
2999
|
+
}
|
|
3000
|
+
function warnAt(message, root, filePath, code, needle) {
|
|
3001
|
+
const pos = findLineCol(code, needle);
|
|
3002
|
+
const relPath = relative(root, filePath).replace(/\\/g, "/");
|
|
3003
|
+
const location = pos ? `${relPath}:${pos.line}:${pos.column}` : relPath;
|
|
3004
|
+
console.warn(`${TAG()} ${yellow(message)}
|
|
3005
|
+
${dim("at")} ${location}`);
|
|
3006
|
+
}
|
|
2965
3007
|
var KBACH_START = "/* kbach:start */";
|
|
2966
3008
|
var KBACH_END = "/* kbach:end */";
|
|
2967
3009
|
var GROUPS = [
|
|
@@ -3084,8 +3126,9 @@ function findKbachCSS(root) {
|
|
|
3084
3126
|
if (found.length === 0) return null;
|
|
3085
3127
|
found.sort((a, b) => a.split(/[\\/]/g).length - b.split(/[\\/]/g).length);
|
|
3086
3128
|
if (found.length > 1) {
|
|
3087
|
-
|
|
3088
|
-
|
|
3129
|
+
warnBlock(
|
|
3130
|
+
`Multiple kbach.css found, using the shallowest \u2014 remove the rest:`,
|
|
3131
|
+
...found.map((f) => dim(` ${f}`))
|
|
3089
3132
|
);
|
|
3090
3133
|
}
|
|
3091
3134
|
return found[0];
|
|
@@ -3174,7 +3217,7 @@ function scanDir(dir, onFile) {
|
|
|
3174
3217
|
entries = readdirSync(dir);
|
|
3175
3218
|
} catch (err) {
|
|
3176
3219
|
if (err.code !== "ENOENT") {
|
|
3177
|
-
|
|
3220
|
+
warn(`Can't read ${dir}: ${err.message}`);
|
|
3178
3221
|
}
|
|
3179
3222
|
return;
|
|
3180
3223
|
}
|
|
@@ -3186,7 +3229,7 @@ function scanDir(dir, onFile) {
|
|
|
3186
3229
|
if (st.isDirectory()) scanDir(full, onFile);
|
|
3187
3230
|
else if (/\.(tsx?|jsx?)$/.test(entry)) onFile(full, readFileSync(full, "utf-8"));
|
|
3188
3231
|
} catch (err) {
|
|
3189
|
-
|
|
3232
|
+
warn(`Can't process ${full}: ${err.message}`);
|
|
3190
3233
|
}
|
|
3191
3234
|
}
|
|
3192
3235
|
}
|
|
@@ -3238,16 +3281,14 @@ function kbach(userConfigOrOptions) {
|
|
|
3238
3281
|
const tokenCSS = /* @__PURE__ */ new Map();
|
|
3239
3282
|
const projectCssClasses = /* @__PURE__ */ new Set();
|
|
3240
3283
|
const warnedTokens = /* @__PURE__ */ new Set();
|
|
3241
|
-
function checkUnknownToken(tok) {
|
|
3284
|
+
function checkUnknownToken(tok, filePath, code) {
|
|
3242
3285
|
if (process2.env.NODE_ENV === "production" || warnedTokens.has(tok) || tok.startsWith("__")) return;
|
|
3243
3286
|
const parsed = parseClass(tok);
|
|
3244
3287
|
if (parsed && resolveUtility(parsed, cfg.theme) !== null) return;
|
|
3245
3288
|
const base = stripModifierPrefix(tok);
|
|
3246
3289
|
if (!base || projectCssClasses.has(base)) return;
|
|
3247
3290
|
warnedTokens.add(tok);
|
|
3248
|
-
|
|
3249
|
-
`[kbach] "${tok}" isn't a Kbach utility and no matching CSS rule was found anywhere in the project (checked .css/.scss/.sass/.less files) \u2014 possible typo? If this is intentional (a third-party class, one defined via CSS-in-JS, etc.), this warning is safe to ignore.`
|
|
3250
|
-
);
|
|
3291
|
+
warnAt(`Unknown class "${tok}" \u2014 no Kbach utility or project CSS rule matches it. Typo?`, root, filePath, code, tok);
|
|
3251
3292
|
}
|
|
3252
3293
|
function processFile(filePath, code) {
|
|
3253
3294
|
const key = normPath(filePath);
|
|
@@ -3257,7 +3298,7 @@ function kbach(userConfigOrOptions) {
|
|
|
3257
3298
|
if (!tokenCSS.has(tok)) {
|
|
3258
3299
|
tokenCSS.set(tok, generateClassCSS(tok, cfg.theme, cfg.darkMode, screens));
|
|
3259
3300
|
}
|
|
3260
|
-
checkUnknownToken(tok);
|
|
3301
|
+
checkUnknownToken(tok, filePath, code);
|
|
3261
3302
|
}
|
|
3262
3303
|
fileTokens.set(key, tokens);
|
|
3263
3304
|
}
|
|
@@ -3285,12 +3326,29 @@ function kbach(userConfigOrOptions) {
|
|
|
3285
3326
|
return {
|
|
3286
3327
|
name: "kbach",
|
|
3287
3328
|
enforce: "pre",
|
|
3329
|
+
// Without this, Vite only discovers @kbach/react needs pre-bundling once it
|
|
3330
|
+
// actually crawls into an import of it — typically the FIRST page load — and
|
|
3331
|
+
// has to stop, optimize it, and force a full reload mid-render. That reload
|
|
3332
|
+
// can land in the middle of a render pass (React hooks resolving against a
|
|
3333
|
+
// module graph that's being swapped out from under it), which is what an
|
|
3334
|
+
// "Invalid hook call" / hook-related crash on first load only usually is.
|
|
3335
|
+
// Declaring it here upfront means Vite pre-bundles it during its initial
|
|
3336
|
+
// dependency scan, before any page ever requests it — no mid-render reload.
|
|
3337
|
+
config() {
|
|
3338
|
+
return {
|
|
3339
|
+
optimizeDeps: {
|
|
3340
|
+
include: ["@kbach/react", "@kbach/react/jsx-runtime", "@kbach/react/jsx-dev-runtime"]
|
|
3341
|
+
}
|
|
3342
|
+
};
|
|
3343
|
+
},
|
|
3288
3344
|
configResolved(resolved) {
|
|
3289
3345
|
root = resolved.root;
|
|
3290
3346
|
const names = new Set(resolved.plugins.map((p) => p.name));
|
|
3291
3347
|
if (names.has("react-router") && names.has("vite:react-refresh")) {
|
|
3292
|
-
|
|
3293
|
-
|
|
3348
|
+
warnBlock(
|
|
3349
|
+
"@vitejs/plugin-react + reactRouter() conflict \u2014 page will crash before styles apply.",
|
|
3350
|
+
dim(' Both inject Fast Refresh ("RefreshRuntime already declared").'),
|
|
3351
|
+
dim(" Fix: remove react() from vite.config.ts \u2014 tsconfig jsxImportSource is enough.")
|
|
3294
3352
|
);
|
|
3295
3353
|
}
|
|
3296
3354
|
},
|
package/kbach-react.md
CHANGED
|
@@ -67,7 +67,7 @@ The `kbach()` Vite plugin scans your source files and writes generated CSS betwe
|
|
|
67
67
|
- Runs on `buildStart` (initial load) and on every HMR file change
|
|
68
68
|
- Stateless: rescans all files fresh every time — removed classes are immediately evicted
|
|
69
69
|
- Output is grouped by category with CSS custom properties for theme colors
|
|
70
|
-
- Also indexes every `.css`/`.scss`/`.sass`/`.less` file the same `include` dirs cover, and warns (`console.warn`, dev-server terminal, not the browser) for any class that's neither a real Kbach utility NOR defined anywhere in those stylesheets — a likely typo. Classes intentionally handled elsewhere (CSS Modules, styled-components, a third-party component's own class) are recognized once anything in the project literally defines `.that-class-name` and stay silent.
|
|
70
|
+
- Also indexes every `.css`/`.scss`/`.sass`/`.less` file the same `include` dirs cover, and warns (`console.warn`, dev-server terminal, not the browser) for any class that's neither a real Kbach utility NOR defined anywhere in those stylesheets — a likely typo. Classes intentionally handled elsewhere (CSS Modules, styled-components, a third-party component's own class) are recognized once anything in the project literally defines `.that-class-name` and stay silent. Each warning prints a `file:line:column` location that terminals with clickable-link support (VS Code's included) turn into a jump-to-that-class link.
|
|
71
71
|
|
|
72
72
|
```ts
|
|
73
73
|
// vite.config.ts
|