@kbach/react 0.5.19 → 0.5.20

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.
@@ -4,15 +4,9 @@ import { F as FrameworkConfig } from './types-CV5vXnSH.mjs';
4
4
  /**
5
5
  * @kbach/react/vite
6
6
  *
7
- * Vite plugin — scans your source files for Kbach className/kb props and
8
- * appends the generated CSS to any CSS file already imported in your project.
9
- *
10
- * Zero setup beyond adding the plugin to vite.config.ts:
11
- *
12
- * import { kbach } from '@kbach/react/vite';
13
- * plugins: [kbach()]
14
- *
15
- * CSS is only generated for the classes you actually use (like Tailwind).
7
+ * Vite plugin — scans source files for Kbach className/kb props and generates CSS.
8
+ * Zero setup: just add kbach() to your plugins array. CSS is auto-injected.
9
+ * Only generates CSS for classes you actually use (like Tailwind).
16
10
  */
17
11
 
18
12
  declare const VIRTUAL_ID = "virtual:kbach/styles.css";
@@ -4,15 +4,9 @@ import { F as FrameworkConfig } from './types-CV5vXnSH.js';
4
4
  /**
5
5
  * @kbach/react/vite
6
6
  *
7
- * Vite plugin — scans your source files for Kbach className/kb props and
8
- * appends the generated CSS to any CSS file already imported in your project.
9
- *
10
- * Zero setup beyond adding the plugin to vite.config.ts:
11
- *
12
- * import { kbach } from '@kbach/react/vite';
13
- * plugins: [kbach()]
14
- *
15
- * CSS is only generated for the classes you actually use (like Tailwind).
7
+ * Vite plugin — scans source files for Kbach className/kb props and generates CSS.
8
+ * Zero setup: just add kbach() to your plugins array. CSS is auto-injected.
9
+ * Only generates CSS for classes you actually use (like Tailwind).
16
10
  */
17
11
 
18
12
  declare const VIRTUAL_ID = "virtual:kbach/styles.css";
@@ -3395,9 +3395,9 @@ 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();
3399
3398
  let root = process.cwd();
3400
3399
  let server = null;
3400
+ let isDev = false;
3401
3401
  function processClassString(classStr) {
3402
3402
  let added = false;
3403
3403
  for (const token of classStr.split(/\s+/).filter(Boolean)) {
@@ -3423,16 +3423,12 @@ function kbach(userConfig) {
3423
3423
  }
3424
3424
  return parts.join("\n");
3425
3425
  }
3426
- function invalidateCSSModules() {
3427
- if (!server) return;
3428
- for (const file of processedCSSFiles) {
3429
- const mod = server.moduleGraph.getModuleByFile(file);
3430
- if (mod) server.moduleGraph.invalidateModule(mod);
3431
- }
3432
- }
3433
3426
  return {
3434
3427
  name: "kbach",
3435
3428
  enforce: "pre",
3429
+ config(_c, env) {
3430
+ isDev = env.command === "serve";
3431
+ },
3436
3432
  configResolved(resolved) {
3437
3433
  root = resolved.root;
3438
3434
  },
@@ -3444,32 +3440,51 @@ function kbach(userConfig) {
3444
3440
  scanDir((0, import_path.join)(root, dir), (code) => extractFromCode(code));
3445
3441
  }
3446
3442
  },
3447
- resolveId(id) {
3448
- if (id === VIRTUAL_ID) return RESOLVED_ID;
3449
- },
3450
- load(id) {
3451
- if (id === RESOLVED_ID) return getAllCSS();
3443
+ // ── Primary injection: inject a <style> tag into every HTML response ──────
3444
+ // React Router v8's dev middleware calls server.transformIndexHtml() on
3445
+ // every SSR HTML response, so this hook fires on every page load.
3446
+ transformIndexHtml: {
3447
+ order: "post",
3448
+ handler() {
3449
+ const css = getAllCSS();
3450
+ if (!css) return [];
3451
+ return [{
3452
+ tag: "style",
3453
+ attrs: { "data-kbach": "" },
3454
+ children: css,
3455
+ injectTo: "head"
3456
+ }];
3457
+ }
3452
3458
  },
3459
+ // ── Secondary: also inject into CSS files (for production builds) ─────────
3460
+ // In production, Vite extracts CSS from JS into separate .css files.
3461
+ // Appending to the user's CSS ensures it ends up in the final CSS bundle.
3453
3462
  transform(code, id) {
3454
3463
  const cleanId = id.split("?")[0];
3455
3464
  if (cleanId.endsWith(".css") && !id.includes("node_modules") && !id.includes("\0")) {
3456
- processedCSSFiles.add(cleanId);
3457
3465
  const kbachCSS = getAllCSS();
3458
3466
  if (!kbachCSS) return null;
3459
- return { code: code + "\n/* kbach utilities */\n" + kbachCSS, map: null };
3467
+ return { code: code + "\n/* kbach */\n" + kbachCSS, map: null };
3460
3468
  }
3461
- if (/\.(tsx?|jsx?)$/.test(id) && !id.includes("node_modules")) {
3462
- const added = extractFromCode(code);
3463
- if (added && server && processedCSSFiles.size > 0) {
3464
- setTimeout(invalidateCSSModules, 0);
3465
- }
3469
+ if (/\.(tsx?|jsx?)$/.test(cleanId) && !id.includes("node_modules")) {
3470
+ extractFromCode(code);
3466
3471
  }
3467
3472
  },
3473
+ // ── Virtual module (opt-in explicit import) ───────────────────────────────
3474
+ resolveId(id) {
3475
+ if (id === VIRTUAL_ID) return RESOLVED_ID;
3476
+ },
3477
+ load(id) {
3478
+ if (id === RESOLVED_ID) return getAllCSS();
3479
+ },
3480
+ // ── HMR: full reload when new classes are added ───────────────────────────
3468
3481
  handleHotUpdate({ file }) {
3469
3482
  if (file.includes("node_modules") || !/\.(tsx?|jsx?)$/.test(file)) return;
3470
3483
  try {
3471
3484
  const added = extractFromCode((0, import_fs.readFileSync)(file, "utf-8"));
3472
- if (added) invalidateCSSModules();
3485
+ if (added && server) {
3486
+ server.hot?.send({ type: "full-reload" }) ?? server.ws?.send({ type: "full-reload" });
3487
+ }
3473
3488
  } catch {
3474
3489
  }
3475
3490
  }
@@ -53,9 +53,9 @@ 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();
57
56
  let root = process.cwd();
58
57
  let server = null;
58
+ let isDev = false;
59
59
  function processClassString(classStr) {
60
60
  let added = false;
61
61
  for (const token of classStr.split(/\s+/).filter(Boolean)) {
@@ -81,16 +81,12 @@ function kbach(userConfig) {
81
81
  }
82
82
  return parts.join("\n");
83
83
  }
84
- function invalidateCSSModules() {
85
- if (!server) return;
86
- for (const file of processedCSSFiles) {
87
- const mod = server.moduleGraph.getModuleByFile(file);
88
- if (mod) server.moduleGraph.invalidateModule(mod);
89
- }
90
- }
91
84
  return {
92
85
  name: "kbach",
93
86
  enforce: "pre",
87
+ config(_c, env) {
88
+ isDev = env.command === "serve";
89
+ },
94
90
  configResolved(resolved) {
95
91
  root = resolved.root;
96
92
  },
@@ -102,32 +98,51 @@ function kbach(userConfig) {
102
98
  scanDir(join(root, dir), (code) => extractFromCode(code));
103
99
  }
104
100
  },
105
- resolveId(id) {
106
- if (id === VIRTUAL_ID) return RESOLVED_ID;
107
- },
108
- load(id) {
109
- if (id === RESOLVED_ID) return getAllCSS();
101
+ // ── Primary injection: inject a <style> tag into every HTML response ──────
102
+ // React Router v8's dev middleware calls server.transformIndexHtml() on
103
+ // every SSR HTML response, so this hook fires on every page load.
104
+ transformIndexHtml: {
105
+ order: "post",
106
+ handler() {
107
+ const css = getAllCSS();
108
+ if (!css) return [];
109
+ return [{
110
+ tag: "style",
111
+ attrs: { "data-kbach": "" },
112
+ children: css,
113
+ injectTo: "head"
114
+ }];
115
+ }
110
116
  },
117
+ // ── Secondary: also inject into CSS files (for production builds) ─────────
118
+ // In production, Vite extracts CSS from JS into separate .css files.
119
+ // Appending to the user's CSS ensures it ends up in the final CSS bundle.
111
120
  transform(code, id) {
112
121
  const cleanId = id.split("?")[0];
113
122
  if (cleanId.endsWith(".css") && !id.includes("node_modules") && !id.includes("\0")) {
114
- processedCSSFiles.add(cleanId);
115
123
  const kbachCSS = getAllCSS();
116
124
  if (!kbachCSS) return null;
117
- return { code: code + "\n/* kbach utilities */\n" + kbachCSS, map: null };
125
+ return { code: code + "\n/* kbach */\n" + kbachCSS, map: null };
118
126
  }
119
- if (/\.(tsx?|jsx?)$/.test(id) && !id.includes("node_modules")) {
120
- const added = extractFromCode(code);
121
- if (added && server && processedCSSFiles.size > 0) {
122
- setTimeout(invalidateCSSModules, 0);
123
- }
127
+ if (/\.(tsx?|jsx?)$/.test(cleanId) && !id.includes("node_modules")) {
128
+ extractFromCode(code);
124
129
  }
125
130
  },
131
+ // ── Virtual module (opt-in explicit import) ───────────────────────────────
132
+ resolveId(id) {
133
+ if (id === VIRTUAL_ID) return RESOLVED_ID;
134
+ },
135
+ load(id) {
136
+ if (id === RESOLVED_ID) return getAllCSS();
137
+ },
138
+ // ── HMR: full reload when new classes are added ───────────────────────────
126
139
  handleHotUpdate({ file }) {
127
140
  if (file.includes("node_modules") || !/\.(tsx?|jsx?)$/.test(file)) return;
128
141
  try {
129
142
  const added = extractFromCode(readFileSync(file, "utf-8"));
130
- if (added) invalidateCSSModules();
143
+ if (added && server) {
144
+ server.hot?.send({ type: "full-reload" }) ?? server.ws?.send({ type: "full-reload" });
145
+ }
131
146
  } catch {
132
147
  }
133
148
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kbach/react",
3
- "version": "0.5.19",
3
+ "version": "0.5.20",
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",