@kbach/react 0.5.24 → 0.5.25

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.
@@ -3350,6 +3350,35 @@ var customVariants = new Proxy(
3350
3350
  // src/vite-plugin.ts
3351
3351
  var VIRTUAL_ID = "virtual:kbach/styles.css";
3352
3352
  var RESOLVED_ID = "\0virtual:kbach/styles.css";
3353
+ var KBACH_START = "/* kbach:start */";
3354
+ var KBACH_END = "/* kbach:end */";
3355
+ function findMainCSSFile(root) {
3356
+ const candidates = [
3357
+ (0, import_path.join)(root, "app", "app.css"),
3358
+ (0, import_path.join)(root, "src", "index.css"),
3359
+ (0, import_path.join)(root, "src", "app.css"),
3360
+ (0, import_path.join)(root, "app", "index.css")
3361
+ ];
3362
+ for (const c of candidates) {
3363
+ if ((0, import_fs.existsSync)(c)) return c;
3364
+ }
3365
+ return null;
3366
+ }
3367
+ function writeKbachToFile(filePath, css) {
3368
+ let existing = "";
3369
+ try {
3370
+ existing = (0, import_fs.readFileSync)(filePath, "utf-8");
3371
+ } catch {
3372
+ }
3373
+ const block = `${KBACH_START}
3374
+ ${css}
3375
+ ${KBACH_END}`;
3376
+ const re = new RegExp(`${KBACH_START}[\\s\\S]*?${KBACH_END}`);
3377
+ const next = existing.includes(KBACH_START) ? existing.replace(re, block) : existing ? `${existing}
3378
+
3379
+ ${block}` : block;
3380
+ if (next !== existing) (0, import_fs.writeFileSync)(filePath, next, "utf-8");
3381
+ }
3353
3382
  function toNumericScreens(screens) {
3354
3383
  const out = {};
3355
3384
  for (const [k, v] of Object.entries(screens)) {
@@ -3395,9 +3424,9 @@ function kbach(userConfig) {
3395
3424
  const cfg = buildConfig(userConfig ?? {});
3396
3425
  const screens = toNumericScreens(cfg.theme.screens ?? {});
3397
3426
  const tokenCSS = /* @__PURE__ */ new Map();
3398
- const processedCSSFiles = /* @__PURE__ */ new Set();
3399
3427
  let root = process.cwd();
3400
3428
  let server = null;
3429
+ let mainCSSFile = null;
3401
3430
  function processToken(token) {
3402
3431
  if (tokenCSS.has(token)) return false;
3403
3432
  tokenCSS.set(token, generateClassCSS(token, cfg.theme, cfg.darkMode, screens));
@@ -3421,19 +3450,6 @@ function kbach(userConfig) {
3421
3450
  }
3422
3451
  return parts.join("\n");
3423
3452
  }
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
- })) });
3436
- }
3437
3453
  return {
3438
3454
  name: "kbach",
3439
3455
  enforce: "pre",
@@ -3447,28 +3463,13 @@ function kbach(userConfig) {
3447
3463
  for (const dir of ["src", "app", "pages", "components", "views", "layouts"]) {
3448
3464
  scanDir((0, import_path.join)(root, dir), (code) => extractFromCode(code));
3449
3465
  }
3466
+ mainCSSFile = findMainCSSFile(root);
3467
+ if (mainCSSFile) writeKbachToFile(mainCSSFile, getAllCSS());
3450
3468
  },
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
3457
3469
  transform(code, id) {
3458
3470
  const cleanId = id.split("?")[0];
3459
- if (cleanId.endsWith(".css") && !id.includes("node_modules") && !id.includes("\0")) {
3460
- processedCSSFiles.add(cleanId);
3461
- const kbachCSS = getAllCSS();
3462
- if (!kbachCSS) return null;
3463
- return { code: `${code}
3464
- /* kbach */
3465
- ${kbachCSS}`, map: null };
3466
- }
3467
3471
  if (/\.(tsx?|jsx?)$/.test(cleanId) && !id.includes("node_modules")) {
3468
- const added = extractFromCode(code);
3469
- if (added && server && processedCSSFiles.size > 0) {
3470
- setTimeout(() => invalidateCSSModules(), 0);
3471
- }
3472
+ extractFromCode(code);
3472
3473
  }
3473
3474
  },
3474
3475
  // ── Virtual module (opt-in explicit import) ───────────────────────────────
@@ -3478,15 +3479,14 @@ ${kbachCSS}`, map: null };
3478
3479
  load(id) {
3479
3480
  if (id === RESOLVED_ID) return getAllCSS();
3480
3481
  },
3481
- // ── HMR: invalidate CSS when new classes are found in changed files ───────
3482
- handleHotUpdate({ file, server: s }) {
3482
+ // ── HMR: write updated CSS to file when new classes are found ────────────
3483
+ // Vite's own file watcher detects the change and hot-reloads the CSS —
3484
+ // no manual invalidation needed.
3485
+ handleHotUpdate({ file }) {
3483
3486
  if (file.includes("node_modules") || !/\.(tsx?|jsx?)$/.test(file)) return;
3484
3487
  try {
3485
3488
  const added = extractFromCode((0, import_fs.readFileSync)(file, "utf-8"));
3486
- if (added) {
3487
- server = s;
3488
- invalidateCSSModules();
3489
- }
3489
+ if (added && mainCSSFile) writeKbachToFile(mainCSSFile, getAllCSS());
3490
3490
  } catch {
3491
3491
  }
3492
3492
  }
@@ -4,10 +4,39 @@ import {
4
4
  } from "./chunk-SOBLKZGE.mjs";
5
5
 
6
6
  // src/vite-plugin.ts
7
- import { readFileSync, readdirSync, statSync } from "fs";
7
+ import { readFileSync, writeFileSync, existsSync, readdirSync, statSync } from "fs";
8
8
  import { join } from "path";
9
9
  var VIRTUAL_ID = "virtual:kbach/styles.css";
10
10
  var RESOLVED_ID = "\0virtual:kbach/styles.css";
11
+ var KBACH_START = "/* kbach:start */";
12
+ var KBACH_END = "/* kbach:end */";
13
+ function findMainCSSFile(root) {
14
+ const candidates = [
15
+ join(root, "app", "app.css"),
16
+ join(root, "src", "index.css"),
17
+ join(root, "src", "app.css"),
18
+ join(root, "app", "index.css")
19
+ ];
20
+ for (const c of candidates) {
21
+ if (existsSync(c)) return c;
22
+ }
23
+ return null;
24
+ }
25
+ function writeKbachToFile(filePath, css) {
26
+ let existing = "";
27
+ try {
28
+ existing = readFileSync(filePath, "utf-8");
29
+ } catch {
30
+ }
31
+ const block = `${KBACH_START}
32
+ ${css}
33
+ ${KBACH_END}`;
34
+ const re = new RegExp(`${KBACH_START}[\\s\\S]*?${KBACH_END}`);
35
+ const next = existing.includes(KBACH_START) ? existing.replace(re, block) : existing ? `${existing}
36
+
37
+ ${block}` : block;
38
+ if (next !== existing) writeFileSync(filePath, next, "utf-8");
39
+ }
11
40
  function toNumericScreens(screens) {
12
41
  const out = {};
13
42
  for (const [k, v] of Object.entries(screens)) {
@@ -53,9 +82,9 @@ function kbach(userConfig) {
53
82
  const cfg = buildConfig(userConfig ?? {});
54
83
  const screens = toNumericScreens(cfg.theme.screens ?? {});
55
84
  const tokenCSS = /* @__PURE__ */ new Map();
56
- const processedCSSFiles = /* @__PURE__ */ new Set();
57
85
  let root = process.cwd();
58
86
  let server = null;
87
+ let mainCSSFile = null;
59
88
  function processToken(token) {
60
89
  if (tokenCSS.has(token)) return false;
61
90
  tokenCSS.set(token, generateClassCSS(token, cfg.theme, cfg.darkMode, screens));
@@ -79,19 +108,6 @@ function kbach(userConfig) {
79
108
  }
80
109
  return parts.join("\n");
81
110
  }
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
- })) });
94
- }
95
111
  return {
96
112
  name: "kbach",
97
113
  enforce: "pre",
@@ -105,28 +121,13 @@ function kbach(userConfig) {
105
121
  for (const dir of ["src", "app", "pages", "components", "views", "layouts"]) {
106
122
  scanDir(join(root, dir), (code) => extractFromCode(code));
107
123
  }
124
+ mainCSSFile = findMainCSSFile(root);
125
+ if (mainCSSFile) writeKbachToFile(mainCSSFile, getAllCSS());
108
126
  },
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
115
127
  transform(code, id) {
116
128
  const cleanId = id.split("?")[0];
117
- if (cleanId.endsWith(".css") && !id.includes("node_modules") && !id.includes("\0")) {
118
- processedCSSFiles.add(cleanId);
119
- const kbachCSS = getAllCSS();
120
- if (!kbachCSS) return null;
121
- return { code: `${code}
122
- /* kbach */
123
- ${kbachCSS}`, map: null };
124
- }
125
129
  if (/\.(tsx?|jsx?)$/.test(cleanId) && !id.includes("node_modules")) {
126
- const added = extractFromCode(code);
127
- if (added && server && processedCSSFiles.size > 0) {
128
- setTimeout(() => invalidateCSSModules(), 0);
129
- }
130
+ extractFromCode(code);
130
131
  }
131
132
  },
132
133
  // ── Virtual module (opt-in explicit import) ───────────────────────────────
@@ -136,15 +137,14 @@ ${kbachCSS}`, map: null };
136
137
  load(id) {
137
138
  if (id === RESOLVED_ID) return getAllCSS();
138
139
  },
139
- // ── HMR: invalidate CSS when new classes are found in changed files ───────
140
- handleHotUpdate({ file, server: s }) {
140
+ // ── HMR: write updated CSS to file when new classes are found ────────────
141
+ // Vite's own file watcher detects the change and hot-reloads the CSS —
142
+ // no manual invalidation needed.
143
+ handleHotUpdate({ file }) {
141
144
  if (file.includes("node_modules") || !/\.(tsx?|jsx?)$/.test(file)) return;
142
145
  try {
143
146
  const added = extractFromCode(readFileSync(file, "utf-8"));
144
- if (added) {
145
- server = s;
146
- invalidateCSSModules();
147
- }
147
+ if (added && mainCSSFile) writeKbachToFile(mainCSSFile, getAllCSS());
148
148
  } catch {
149
149
  }
150
150
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kbach/react",
3
- "version": "0.5.24",
3
+ "version": "0.5.25",
4
4
  "description": "React / React Native components and hooks for the Kbach framework",
5
5
  "source": "./src/index.ts",
6
6
  "main": "./dist/index.js",