@kbach/react 0.5.18 → 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,31 +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
- if (id.endsWith(".css") && !id.includes("node_modules") && !id.includes("\0")) {
3455
- processedCSSFiles.add(id);
3463
+ const cleanId = id.split("?")[0];
3464
+ if (cleanId.endsWith(".css") && !id.includes("node_modules") && !id.includes("\0")) {
3456
3465
  const kbachCSS = getAllCSS();
3457
3466
  if (!kbachCSS) return null;
3458
- return { code: code + "\n/* kbach utilities */\n" + kbachCSS, map: null };
3467
+ return { code: code + "\n/* kbach */\n" + kbachCSS, map: null };
3459
3468
  }
3460
- if (/\.(tsx?|jsx?)$/.test(id) && !id.includes("node_modules")) {
3461
- const added = extractFromCode(code);
3462
- if (added && server && processedCSSFiles.size > 0) {
3463
- setTimeout(invalidateCSSModules, 0);
3464
- }
3469
+ if (/\.(tsx?|jsx?)$/.test(cleanId) && !id.includes("node_modules")) {
3470
+ extractFromCode(code);
3465
3471
  }
3466
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 ───────────────────────────
3467
3481
  handleHotUpdate({ file }) {
3468
3482
  if (file.includes("node_modules") || !/\.(tsx?|jsx?)$/.test(file)) return;
3469
3483
  try {
3470
3484
  const added = extractFromCode((0, import_fs.readFileSync)(file, "utf-8"));
3471
- if (added) invalidateCSSModules();
3485
+ if (added && server) {
3486
+ server.hot?.send({ type: "full-reload" }) ?? server.ws?.send({ type: "full-reload" });
3487
+ }
3472
3488
  } catch {
3473
3489
  }
3474
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,31 +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
- if (id.endsWith(".css") && !id.includes("node_modules") && !id.includes("\0")) {
113
- processedCSSFiles.add(id);
121
+ const cleanId = id.split("?")[0];
122
+ if (cleanId.endsWith(".css") && !id.includes("node_modules") && !id.includes("\0")) {
114
123
  const kbachCSS = getAllCSS();
115
124
  if (!kbachCSS) return null;
116
- return { code: code + "\n/* kbach utilities */\n" + kbachCSS, map: null };
125
+ return { code: code + "\n/* kbach */\n" + kbachCSS, map: null };
117
126
  }
118
- if (/\.(tsx?|jsx?)$/.test(id) && !id.includes("node_modules")) {
119
- const added = extractFromCode(code);
120
- if (added && server && processedCSSFiles.size > 0) {
121
- setTimeout(invalidateCSSModules, 0);
122
- }
127
+ if (/\.(tsx?|jsx?)$/.test(cleanId) && !id.includes("node_modules")) {
128
+ extractFromCode(code);
123
129
  }
124
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 ───────────────────────────
125
139
  handleHotUpdate({ file }) {
126
140
  if (file.includes("node_modules") || !/\.(tsx?|jsx?)$/.test(file)) return;
127
141
  try {
128
142
  const added = extractFromCode(readFileSync(file, "utf-8"));
129
- if (added) invalidateCSSModules();
143
+ if (added && server) {
144
+ server.hot?.send({ type: "full-reload" }) ?? server.ws?.send({ type: "full-reload" });
145
+ }
130
146
  } catch {
131
147
  }
132
148
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kbach/react",
3
- "version": "0.5.18",
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",