@kbach/react 0.5.23 → 0.5.24
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/vite-plugin.d.mts +7 -0
- package/dist/vite-plugin.d.ts +7 -0
- package/dist/vite-plugin.js +42 -86
- package/dist/vite-plugin.mjs +42 -86
- package/package.json +1 -1
package/dist/vite-plugin.d.mts
CHANGED
|
@@ -7,6 +7,13 @@ import { F as FrameworkConfig } from './types-CV5vXnSH.mjs';
|
|
|
7
7
|
* Vite plugin — scans source files for Kbach className/kb props and generates CSS.
|
|
8
8
|
* Zero setup: just add kbach() to your plugins array.
|
|
9
9
|
* Only generates CSS for classes you actually use (like Tailwind).
|
|
10
|
+
*
|
|
11
|
+
* How it works (same as Tailwind):
|
|
12
|
+
* 1. Scans your source files at startup for className/kb props
|
|
13
|
+
* 2. Generates CSS rules for only those classes
|
|
14
|
+
* 3. Appends them to your imported CSS file (e.g. app.css) via Vite's transform
|
|
15
|
+
* 4. Vite serves the CSS through its normal pipeline → <link rel="stylesheet">
|
|
16
|
+
* 5. When you add a new class in dev, the CSS file is hot-reloaded
|
|
10
17
|
*/
|
|
11
18
|
|
|
12
19
|
declare const VIRTUAL_ID = "virtual:kbach/styles.css";
|
package/dist/vite-plugin.d.ts
CHANGED
|
@@ -7,6 +7,13 @@ import { F as FrameworkConfig } from './types-CV5vXnSH.js';
|
|
|
7
7
|
* Vite plugin — scans source files for Kbach className/kb props and generates CSS.
|
|
8
8
|
* Zero setup: just add kbach() to your plugins array.
|
|
9
9
|
* Only generates CSS for classes you actually use (like Tailwind).
|
|
10
|
+
*
|
|
11
|
+
* How it works (same as Tailwind):
|
|
12
|
+
* 1. Scans your source files at startup for className/kb props
|
|
13
|
+
* 2. Generates CSS rules for only those classes
|
|
14
|
+
* 3. Appends them to your imported CSS file (e.g. app.css) via Vite's transform
|
|
15
|
+
* 4. Vite serves the CSS through its normal pipeline → <link rel="stylesheet">
|
|
16
|
+
* 5. When you add a new class in dev, the CSS file is hot-reloaded
|
|
10
17
|
*/
|
|
11
18
|
|
|
12
19
|
declare const VIRTUAL_ID = "virtual:kbach/styles.css";
|
package/dist/vite-plugin.js
CHANGED
|
@@ -3395,21 +3395,20 @@ function kbach(userConfig) {
|
|
|
3395
3395
|
const cfg = buildConfig(userConfig ?? {});
|
|
3396
3396
|
const screens = toNumericScreens(cfg.theme.screens ?? {});
|
|
3397
3397
|
const tokenCSS = /* @__PURE__ */ new Map();
|
|
3398
|
+
const processedCSSFiles = /* @__PURE__ */ new Set();
|
|
3398
3399
|
let root = process.cwd();
|
|
3399
3400
|
let server = null;
|
|
3400
|
-
function
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
tokenCSS.set(token, generateClassCSS(token, cfg.theme, cfg.darkMode, screens));
|
|
3405
|
-
added = true;
|
|
3406
|
-
}
|
|
3407
|
-
return added;
|
|
3401
|
+
function processToken(token) {
|
|
3402
|
+
if (tokenCSS.has(token)) return false;
|
|
3403
|
+
tokenCSS.set(token, generateClassCSS(token, cfg.theme, cfg.darkMode, screens));
|
|
3404
|
+
return true;
|
|
3408
3405
|
}
|
|
3409
3406
|
function extractFromCode(code) {
|
|
3410
3407
|
let added = false;
|
|
3411
3408
|
for (const cls of extractClassStrings(code)) {
|
|
3412
|
-
|
|
3409
|
+
for (const token of cls.split(/\s+/).filter(Boolean)) {
|
|
3410
|
+
if (processToken(token)) added = true;
|
|
3411
|
+
}
|
|
3413
3412
|
}
|
|
3414
3413
|
return added;
|
|
3415
3414
|
}
|
|
@@ -3422,10 +3421,18 @@ function kbach(userConfig) {
|
|
|
3422
3421
|
}
|
|
3423
3422
|
return parts.join("\n");
|
|
3424
3423
|
}
|
|
3425
|
-
function
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3424
|
+
function invalidateCSSModules() {
|
|
3425
|
+
if (!server) return;
|
|
3426
|
+
for (const id of processedCSSFiles) {
|
|
3427
|
+
const mod = server.moduleGraph?.getModuleById(id);
|
|
3428
|
+
if (mod) server.moduleGraph.invalidateModule(mod);
|
|
3429
|
+
}
|
|
3430
|
+
server.hot?.send({ type: "update", updates: [...processedCSSFiles].map((id) => ({
|
|
3431
|
+
type: "js-update",
|
|
3432
|
+
path: id,
|
|
3433
|
+
acceptedPath: id,
|
|
3434
|
+
timestamp: Date.now()
|
|
3435
|
+
})) });
|
|
3429
3436
|
}
|
|
3430
3437
|
return {
|
|
3431
3438
|
name: "kbach",
|
|
@@ -3433,87 +3440,35 @@ function kbach(userConfig) {
|
|
|
3433
3440
|
configResolved(resolved) {
|
|
3434
3441
|
root = resolved.root;
|
|
3435
3442
|
},
|
|
3443
|
+
configureServer(s) {
|
|
3444
|
+
server = s;
|
|
3445
|
+
},
|
|
3436
3446
|
buildStart() {
|
|
3437
3447
|
for (const dir of ["src", "app", "pages", "components", "views", "layouts"]) {
|
|
3438
3448
|
scanDir((0, import_path.join)(root, dir), (code) => extractFromCode(code));
|
|
3439
3449
|
}
|
|
3440
3450
|
},
|
|
3441
|
-
// ──
|
|
3442
|
-
//
|
|
3443
|
-
//
|
|
3444
|
-
//
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
s.middlewares.use((req, res, next) => {
|
|
3448
|
-
const url = req.url ?? "";
|
|
3449
|
-
if (/\.(js|ts|jsx|tsx|css|png|jpg|svg|ico|woff2?|ttf|json|map)(\?|$)/.test(url) || url.startsWith("/@") || url.startsWith("/__")) {
|
|
3450
|
-
return next();
|
|
3451
|
-
}
|
|
3452
|
-
const origWrite = res.write.bind(res);
|
|
3453
|
-
const origEnd = res.end.bind(res);
|
|
3454
|
-
const chunks = [];
|
|
3455
|
-
let done = false;
|
|
3456
|
-
function toBuffer(chunk, enc) {
|
|
3457
|
-
if (chunk == null) return Buffer.alloc(0);
|
|
3458
|
-
if (typeof chunk === "string") {
|
|
3459
|
-
return Buffer.from(chunk, typeof enc === "string" ? enc : "utf-8");
|
|
3460
|
-
}
|
|
3461
|
-
if (ArrayBuffer.isView(chunk)) {
|
|
3462
|
-
return Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength);
|
|
3463
|
-
}
|
|
3464
|
-
if (chunk instanceof ArrayBuffer) return Buffer.from(chunk);
|
|
3465
|
-
return Buffer.from(String(chunk));
|
|
3466
|
-
}
|
|
3467
|
-
res.write = function(chunk, enc, cb) {
|
|
3468
|
-
if (done) return origWrite(chunk, enc, cb);
|
|
3469
|
-
if (chunk != null) chunks.push(toBuffer(chunk, enc));
|
|
3470
|
-
if (typeof enc === "function") enc();
|
|
3471
|
-
else if (typeof cb === "function") cb();
|
|
3472
|
-
return true;
|
|
3473
|
-
};
|
|
3474
|
-
res.end = function(chunk, enc, cb) {
|
|
3475
|
-
done = true;
|
|
3476
|
-
if (typeof chunk === "function") {
|
|
3477
|
-
cb = chunk;
|
|
3478
|
-
chunk = null;
|
|
3479
|
-
enc = null;
|
|
3480
|
-
} else if (typeof enc === "function") {
|
|
3481
|
-
cb = enc;
|
|
3482
|
-
enc = null;
|
|
3483
|
-
}
|
|
3484
|
-
if (chunk != null) chunks.push(toBuffer(chunk, enc));
|
|
3485
|
-
if (chunks.length > 0) {
|
|
3486
|
-
const html = Buffer.concat(chunks).toString("utf-8");
|
|
3487
|
-
if (html.includes("</head>")) {
|
|
3488
|
-
const injected = injectIntoHtml(html);
|
|
3489
|
-
const buf = Buffer.from(injected, "utf-8");
|
|
3490
|
-
try {
|
|
3491
|
-
res.removeHeader("transfer-encoding");
|
|
3492
|
-
} catch {
|
|
3493
|
-
}
|
|
3494
|
-
try {
|
|
3495
|
-
res.setHeader("content-length", buf.length);
|
|
3496
|
-
} catch {
|
|
3497
|
-
}
|
|
3498
|
-
return origEnd(buf, cb);
|
|
3499
|
-
}
|
|
3500
|
-
return origEnd(Buffer.concat(chunks), enc, cb);
|
|
3501
|
-
}
|
|
3502
|
-
return origEnd(void 0, enc, cb);
|
|
3503
|
-
};
|
|
3504
|
-
next();
|
|
3505
|
-
});
|
|
3506
|
-
},
|
|
3507
|
-
// ── PROD: append to CSS files so they land in the extracted CSS bundle ────
|
|
3451
|
+
// ── CSS transform: append generated rules to the user's CSS file ──────────
|
|
3452
|
+
// Works exactly like Tailwind's PostCSS plugin:
|
|
3453
|
+
// - Your app.css content stays untouched (empty or your own rules)
|
|
3454
|
+
// - Kbach appends its generated rules to the transform output
|
|
3455
|
+
// - Vite serves the result via its normal CSS pipeline (<link rel="stylesheet">)
|
|
3456
|
+
// - In production, it lands in the extracted CSS bundle file
|
|
3508
3457
|
transform(code, id) {
|
|
3509
3458
|
const cleanId = id.split("?")[0];
|
|
3510
3459
|
if (cleanId.endsWith(".css") && !id.includes("node_modules") && !id.includes("\0")) {
|
|
3460
|
+
processedCSSFiles.add(cleanId);
|
|
3511
3461
|
const kbachCSS = getAllCSS();
|
|
3512
3462
|
if (!kbachCSS) return null;
|
|
3513
|
-
return { code: code
|
|
3463
|
+
return { code: `${code}
|
|
3464
|
+
/* kbach */
|
|
3465
|
+
${kbachCSS}`, map: null };
|
|
3514
3466
|
}
|
|
3515
3467
|
if (/\.(tsx?|jsx?)$/.test(cleanId) && !id.includes("node_modules")) {
|
|
3516
|
-
extractFromCode(code);
|
|
3468
|
+
const added = extractFromCode(code);
|
|
3469
|
+
if (added && server && processedCSSFiles.size > 0) {
|
|
3470
|
+
setTimeout(() => invalidateCSSModules(), 0);
|
|
3471
|
+
}
|
|
3517
3472
|
}
|
|
3518
3473
|
},
|
|
3519
3474
|
// ── Virtual module (opt-in explicit import) ───────────────────────────────
|
|
@@ -3523,13 +3478,14 @@ function kbach(userConfig) {
|
|
|
3523
3478
|
load(id) {
|
|
3524
3479
|
if (id === RESOLVED_ID) return getAllCSS();
|
|
3525
3480
|
},
|
|
3526
|
-
// ── HMR:
|
|
3527
|
-
handleHotUpdate({ file }) {
|
|
3481
|
+
// ── HMR: invalidate CSS when new classes are found in changed files ───────
|
|
3482
|
+
handleHotUpdate({ file, server: s }) {
|
|
3528
3483
|
if (file.includes("node_modules") || !/\.(tsx?|jsx?)$/.test(file)) return;
|
|
3529
3484
|
try {
|
|
3530
3485
|
const added = extractFromCode((0, import_fs.readFileSync)(file, "utf-8"));
|
|
3531
|
-
if (added
|
|
3532
|
-
|
|
3486
|
+
if (added) {
|
|
3487
|
+
server = s;
|
|
3488
|
+
invalidateCSSModules();
|
|
3533
3489
|
}
|
|
3534
3490
|
} catch {
|
|
3535
3491
|
}
|
package/dist/vite-plugin.mjs
CHANGED
|
@@ -53,21 +53,20 @@ function kbach(userConfig) {
|
|
|
53
53
|
const cfg = buildConfig(userConfig ?? {});
|
|
54
54
|
const screens = toNumericScreens(cfg.theme.screens ?? {});
|
|
55
55
|
const tokenCSS = /* @__PURE__ */ new Map();
|
|
56
|
+
const processedCSSFiles = /* @__PURE__ */ new Set();
|
|
56
57
|
let root = process.cwd();
|
|
57
58
|
let server = null;
|
|
58
|
-
function
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
tokenCSS.set(token, generateClassCSS(token, cfg.theme, cfg.darkMode, screens));
|
|
63
|
-
added = true;
|
|
64
|
-
}
|
|
65
|
-
return added;
|
|
59
|
+
function processToken(token) {
|
|
60
|
+
if (tokenCSS.has(token)) return false;
|
|
61
|
+
tokenCSS.set(token, generateClassCSS(token, cfg.theme, cfg.darkMode, screens));
|
|
62
|
+
return true;
|
|
66
63
|
}
|
|
67
64
|
function extractFromCode(code) {
|
|
68
65
|
let added = false;
|
|
69
66
|
for (const cls of extractClassStrings(code)) {
|
|
70
|
-
|
|
67
|
+
for (const token of cls.split(/\s+/).filter(Boolean)) {
|
|
68
|
+
if (processToken(token)) added = true;
|
|
69
|
+
}
|
|
71
70
|
}
|
|
72
71
|
return added;
|
|
73
72
|
}
|
|
@@ -80,10 +79,18 @@ function kbach(userConfig) {
|
|
|
80
79
|
}
|
|
81
80
|
return parts.join("\n");
|
|
82
81
|
}
|
|
83
|
-
function
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
function invalidateCSSModules() {
|
|
83
|
+
if (!server) return;
|
|
84
|
+
for (const id of processedCSSFiles) {
|
|
85
|
+
const mod = server.moduleGraph?.getModuleById(id);
|
|
86
|
+
if (mod) server.moduleGraph.invalidateModule(mod);
|
|
87
|
+
}
|
|
88
|
+
server.hot?.send({ type: "update", updates: [...processedCSSFiles].map((id) => ({
|
|
89
|
+
type: "js-update",
|
|
90
|
+
path: id,
|
|
91
|
+
acceptedPath: id,
|
|
92
|
+
timestamp: Date.now()
|
|
93
|
+
})) });
|
|
87
94
|
}
|
|
88
95
|
return {
|
|
89
96
|
name: "kbach",
|
|
@@ -91,87 +98,35 @@ function kbach(userConfig) {
|
|
|
91
98
|
configResolved(resolved) {
|
|
92
99
|
root = resolved.root;
|
|
93
100
|
},
|
|
101
|
+
configureServer(s) {
|
|
102
|
+
server = s;
|
|
103
|
+
},
|
|
94
104
|
buildStart() {
|
|
95
105
|
for (const dir of ["src", "app", "pages", "components", "views", "layouts"]) {
|
|
96
106
|
scanDir(join(root, dir), (code) => extractFromCode(code));
|
|
97
107
|
}
|
|
98
108
|
},
|
|
99
|
-
// ──
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
s.middlewares.use((req, res, next) => {
|
|
106
|
-
const url = req.url ?? "";
|
|
107
|
-
if (/\.(js|ts|jsx|tsx|css|png|jpg|svg|ico|woff2?|ttf|json|map)(\?|$)/.test(url) || url.startsWith("/@") || url.startsWith("/__")) {
|
|
108
|
-
return next();
|
|
109
|
-
}
|
|
110
|
-
const origWrite = res.write.bind(res);
|
|
111
|
-
const origEnd = res.end.bind(res);
|
|
112
|
-
const chunks = [];
|
|
113
|
-
let done = false;
|
|
114
|
-
function toBuffer(chunk, enc) {
|
|
115
|
-
if (chunk == null) return Buffer.alloc(0);
|
|
116
|
-
if (typeof chunk === "string") {
|
|
117
|
-
return Buffer.from(chunk, typeof enc === "string" ? enc : "utf-8");
|
|
118
|
-
}
|
|
119
|
-
if (ArrayBuffer.isView(chunk)) {
|
|
120
|
-
return Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength);
|
|
121
|
-
}
|
|
122
|
-
if (chunk instanceof ArrayBuffer) return Buffer.from(chunk);
|
|
123
|
-
return Buffer.from(String(chunk));
|
|
124
|
-
}
|
|
125
|
-
res.write = function(chunk, enc, cb) {
|
|
126
|
-
if (done) return origWrite(chunk, enc, cb);
|
|
127
|
-
if (chunk != null) chunks.push(toBuffer(chunk, enc));
|
|
128
|
-
if (typeof enc === "function") enc();
|
|
129
|
-
else if (typeof cb === "function") cb();
|
|
130
|
-
return true;
|
|
131
|
-
};
|
|
132
|
-
res.end = function(chunk, enc, cb) {
|
|
133
|
-
done = true;
|
|
134
|
-
if (typeof chunk === "function") {
|
|
135
|
-
cb = chunk;
|
|
136
|
-
chunk = null;
|
|
137
|
-
enc = null;
|
|
138
|
-
} else if (typeof enc === "function") {
|
|
139
|
-
cb = enc;
|
|
140
|
-
enc = null;
|
|
141
|
-
}
|
|
142
|
-
if (chunk != null) chunks.push(toBuffer(chunk, enc));
|
|
143
|
-
if (chunks.length > 0) {
|
|
144
|
-
const html = Buffer.concat(chunks).toString("utf-8");
|
|
145
|
-
if (html.includes("</head>")) {
|
|
146
|
-
const injected = injectIntoHtml(html);
|
|
147
|
-
const buf = Buffer.from(injected, "utf-8");
|
|
148
|
-
try {
|
|
149
|
-
res.removeHeader("transfer-encoding");
|
|
150
|
-
} catch {
|
|
151
|
-
}
|
|
152
|
-
try {
|
|
153
|
-
res.setHeader("content-length", buf.length);
|
|
154
|
-
} catch {
|
|
155
|
-
}
|
|
156
|
-
return origEnd(buf, cb);
|
|
157
|
-
}
|
|
158
|
-
return origEnd(Buffer.concat(chunks), enc, cb);
|
|
159
|
-
}
|
|
160
|
-
return origEnd(void 0, enc, cb);
|
|
161
|
-
};
|
|
162
|
-
next();
|
|
163
|
-
});
|
|
164
|
-
},
|
|
165
|
-
// ── PROD: append to CSS files so they land in the extracted CSS bundle ────
|
|
109
|
+
// ── CSS transform: append generated rules to the user's CSS file ──────────
|
|
110
|
+
// Works exactly like Tailwind's PostCSS plugin:
|
|
111
|
+
// - Your app.css content stays untouched (empty or your own rules)
|
|
112
|
+
// - Kbach appends its generated rules to the transform output
|
|
113
|
+
// - Vite serves the result via its normal CSS pipeline (<link rel="stylesheet">)
|
|
114
|
+
// - In production, it lands in the extracted CSS bundle file
|
|
166
115
|
transform(code, id) {
|
|
167
116
|
const cleanId = id.split("?")[0];
|
|
168
117
|
if (cleanId.endsWith(".css") && !id.includes("node_modules") && !id.includes("\0")) {
|
|
118
|
+
processedCSSFiles.add(cleanId);
|
|
169
119
|
const kbachCSS = getAllCSS();
|
|
170
120
|
if (!kbachCSS) return null;
|
|
171
|
-
return { code: code
|
|
121
|
+
return { code: `${code}
|
|
122
|
+
/* kbach */
|
|
123
|
+
${kbachCSS}`, map: null };
|
|
172
124
|
}
|
|
173
125
|
if (/\.(tsx?|jsx?)$/.test(cleanId) && !id.includes("node_modules")) {
|
|
174
|
-
extractFromCode(code);
|
|
126
|
+
const added = extractFromCode(code);
|
|
127
|
+
if (added && server && processedCSSFiles.size > 0) {
|
|
128
|
+
setTimeout(() => invalidateCSSModules(), 0);
|
|
129
|
+
}
|
|
175
130
|
}
|
|
176
131
|
},
|
|
177
132
|
// ── Virtual module (opt-in explicit import) ───────────────────────────────
|
|
@@ -181,13 +136,14 @@ function kbach(userConfig) {
|
|
|
181
136
|
load(id) {
|
|
182
137
|
if (id === RESOLVED_ID) return getAllCSS();
|
|
183
138
|
},
|
|
184
|
-
// ── HMR:
|
|
185
|
-
handleHotUpdate({ file }) {
|
|
139
|
+
// ── HMR: invalidate CSS when new classes are found in changed files ───────
|
|
140
|
+
handleHotUpdate({ file, server: s }) {
|
|
186
141
|
if (file.includes("node_modules") || !/\.(tsx?|jsx?)$/.test(file)) return;
|
|
187
142
|
try {
|
|
188
143
|
const added = extractFromCode(readFileSync(file, "utf-8"));
|
|
189
|
-
if (added
|
|
190
|
-
|
|
144
|
+
if (added) {
|
|
145
|
+
server = s;
|
|
146
|
+
invalidateCSSModules();
|
|
191
147
|
}
|
|
192
148
|
} catch {
|
|
193
149
|
}
|