@kbach/react 0.5.16 → 0.5.18

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.
@@ -3222,11 +3222,16 @@ var CSS_UNITLESS = /* @__PURE__ */ new Set([
3222
3222
  "gridRowStart",
3223
3223
  "gridRowEnd"
3224
3224
  ]);
3225
+ var RN_SHORTHAND_EXPAND = {
3226
+ marginHorizontal: ["margin-left", "margin-right"],
3227
+ marginVertical: ["margin-top", "margin-bottom"],
3228
+ paddingHorizontal: ["padding-left", "padding-right"],
3229
+ paddingVertical: ["padding-top", "padding-bottom"]
3230
+ };
3225
3231
  function styleValueToCSS(styles, forceImportant = false) {
3226
- return Object.entries(styles).filter(
3227
- ([prop, v]) => v !== void 0 && v !== null && typeof v !== "object" && !RN_ONLY_PROPS.has(prop)
3228
- ).map(([prop, val]) => {
3229
- const cssProp = camelToKebab(prop);
3232
+ const parts = [];
3233
+ for (const [prop, val] of Object.entries(styles)) {
3234
+ if (val === void 0 || val === null || typeof val === "object" || RN_ONLY_PROPS.has(prop)) continue;
3230
3235
  let cssVal;
3231
3236
  if (typeof val === "number") {
3232
3237
  cssVal = val === 0 || CSS_UNITLESS.has(prop) ? String(val) : `${val}px`;
@@ -3234,8 +3239,15 @@ function styleValueToCSS(styles, forceImportant = false) {
3234
3239
  cssVal = String(val);
3235
3240
  }
3236
3241
  const imp = forceImportant || prop === "display" && (cssVal === "grid" || cssVal === "inline-grid") || prop === "position" && (cssVal === "sticky" || cssVal === "fixed" || cssVal === "static") ? " !important" : "";
3237
- return `${cssProp}: ${cssVal}${imp}`;
3238
- }).join("; ");
3242
+ if (prop in RN_SHORTHAND_EXPAND) {
3243
+ const [p1, p2] = RN_SHORTHAND_EXPAND[prop];
3244
+ parts.push(`${p1}: ${cssVal}${imp}`);
3245
+ parts.push(`${p2}: ${cssVal}${imp}`);
3246
+ continue;
3247
+ }
3248
+ parts.push(`${camelToKebab(prop)}: ${cssVal}${imp}`);
3249
+ }
3250
+ return parts.join("; ");
3239
3251
  }
3240
3252
  function camelToKebab(str) {
3241
3253
  return str.replace(/([A-Z])/g, "-$1").toLowerCase();
@@ -3,7 +3,7 @@ import {
3
3
  InteractiveWrapper,
4
4
  useConditionalWidth,
5
5
  useGlobalDarkMode
6
- } from "./chunk-RMZIFMWE.mjs";
6
+ } from "./chunk-X6FH5QTD.mjs";
7
7
  import {
8
8
  flatten,
9
9
  getActiveBreakpoints,
@@ -11,7 +11,7 @@ import {
11
11
  getDefaultFontFamily,
12
12
  isWeb,
13
13
  resolve
14
- } from "./chunk-SHQPNCQ7.mjs";
14
+ } from "./chunk-SOBLKZGE.mjs";
15
15
 
16
16
  // src/jsx-runtime.tsx
17
17
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -4,7 +4,7 @@ import {
4
4
  getGlobalWidth,
5
5
  isWeb,
6
6
  subscribeGlobalWidth
7
- } from "./chunk-SHQPNCQ7.mjs";
7
+ } from "./chunk-SOBLKZGE.mjs";
8
8
 
9
9
  // src/core/darkModeStore.ts
10
10
  var KEY = "__kbach_dark_store__";
package/dist/index.js CHANGED
@@ -3342,11 +3342,16 @@ var CSS_UNITLESS = /* @__PURE__ */ new Set([
3342
3342
  "gridRowStart",
3343
3343
  "gridRowEnd"
3344
3344
  ]);
3345
+ var RN_SHORTHAND_EXPAND = {
3346
+ marginHorizontal: ["margin-left", "margin-right"],
3347
+ marginVertical: ["margin-top", "margin-bottom"],
3348
+ paddingHorizontal: ["padding-left", "padding-right"],
3349
+ paddingVertical: ["padding-top", "padding-bottom"]
3350
+ };
3345
3351
  function styleValueToCSS(styles, forceImportant = false) {
3346
- return Object.entries(styles).filter(
3347
- ([prop, v]) => v !== void 0 && v !== null && typeof v !== "object" && !RN_ONLY_PROPS.has(prop)
3348
- ).map(([prop, val]) => {
3349
- const cssProp = camelToKebab(prop);
3352
+ const parts = [];
3353
+ for (const [prop, val] of Object.entries(styles)) {
3354
+ if (val === void 0 || val === null || typeof val === "object" || RN_ONLY_PROPS.has(prop)) continue;
3350
3355
  let cssVal;
3351
3356
  if (typeof val === "number") {
3352
3357
  cssVal = val === 0 || CSS_UNITLESS.has(prop) ? String(val) : `${val}px`;
@@ -3354,8 +3359,15 @@ function styleValueToCSS(styles, forceImportant = false) {
3354
3359
  cssVal = String(val);
3355
3360
  }
3356
3361
  const imp = forceImportant || prop === "display" && (cssVal === "grid" || cssVal === "inline-grid") || prop === "position" && (cssVal === "sticky" || cssVal === "fixed" || cssVal === "static") ? " !important" : "";
3357
- return `${cssProp}: ${cssVal}${imp}`;
3358
- }).join("; ");
3362
+ if (prop in RN_SHORTHAND_EXPAND) {
3363
+ const [p1, p2] = RN_SHORTHAND_EXPAND[prop];
3364
+ parts.push(`${p1}: ${cssVal}${imp}`);
3365
+ parts.push(`${p2}: ${cssVal}${imp}`);
3366
+ continue;
3367
+ }
3368
+ parts.push(`${camelToKebab(prop)}: ${cssVal}${imp}`);
3369
+ }
3370
+ return parts.join("; ");
3359
3371
  }
3360
3372
  function camelToKebab(str) {
3361
3373
  return str.replace(/([A-Z])/g, "-$1").toLowerCase();
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  useConditionalWidth,
7
7
  useGlobalDarkMode,
8
8
  useGlobalWidth
9
- } from "./chunk-RMZIFMWE.mjs";
9
+ } from "./chunk-X6FH5QTD.mjs";
10
10
  import {
11
11
  __require,
12
12
  buildConfig,
@@ -25,7 +25,7 @@ import {
25
25
  syncGlobalScreens,
26
26
  syncGlobalWidth,
27
27
  updateConfig
28
- } from "./chunk-SHQPNCQ7.mjs";
28
+ } from "./chunk-SOBLKZGE.mjs";
29
29
 
30
30
  // src/context.tsx
31
31
  import { createContext, useContext } from "react";
@@ -3234,11 +3234,16 @@ var CSS_UNITLESS = /* @__PURE__ */ new Set([
3234
3234
  "gridRowStart",
3235
3235
  "gridRowEnd"
3236
3236
  ]);
3237
+ var RN_SHORTHAND_EXPAND = {
3238
+ marginHorizontal: ["margin-left", "margin-right"],
3239
+ marginVertical: ["margin-top", "margin-bottom"],
3240
+ paddingHorizontal: ["padding-left", "padding-right"],
3241
+ paddingVertical: ["padding-top", "padding-bottom"]
3242
+ };
3237
3243
  function styleValueToCSS(styles, forceImportant = false) {
3238
- return Object.entries(styles).filter(
3239
- ([prop, v]) => v !== void 0 && v !== null && typeof v !== "object" && !RN_ONLY_PROPS.has(prop)
3240
- ).map(([prop, val]) => {
3241
- const cssProp = camelToKebab(prop);
3244
+ const parts = [];
3245
+ for (const [prop, val] of Object.entries(styles)) {
3246
+ if (val === void 0 || val === null || typeof val === "object" || RN_ONLY_PROPS.has(prop)) continue;
3242
3247
  let cssVal;
3243
3248
  if (typeof val === "number") {
3244
3249
  cssVal = val === 0 || CSS_UNITLESS.has(prop) ? String(val) : `${val}px`;
@@ -3246,8 +3251,15 @@ function styleValueToCSS(styles, forceImportant = false) {
3246
3251
  cssVal = String(val);
3247
3252
  }
3248
3253
  const imp = forceImportant || prop === "display" && (cssVal === "grid" || cssVal === "inline-grid") || prop === "position" && (cssVal === "sticky" || cssVal === "fixed" || cssVal === "static") ? " !important" : "";
3249
- return `${cssProp}: ${cssVal}${imp}`;
3250
- }).join("; ");
3254
+ if (prop in RN_SHORTHAND_EXPAND) {
3255
+ const [p1, p2] = RN_SHORTHAND_EXPAND[prop];
3256
+ parts.push(`${p1}: ${cssVal}${imp}`);
3257
+ parts.push(`${p2}: ${cssVal}${imp}`);
3258
+ continue;
3259
+ }
3260
+ parts.push(`${camelToKebab(prop)}: ${cssVal}${imp}`);
3261
+ }
3262
+ return parts.join("; ");
3251
3263
  }
3252
3264
  function camelToKebab(str) {
3253
3265
  return str.replace(/([A-Z])/g, "-$1").toLowerCase();
@@ -2,9 +2,9 @@ import {
2
2
  Fragment,
3
3
  jsx,
4
4
  jsxs
5
- } from "./chunk-HTPCUYNH.mjs";
6
- import "./chunk-RMZIFMWE.mjs";
7
- import "./chunk-SHQPNCQ7.mjs";
5
+ } from "./chunk-VZD4672I.mjs";
6
+ import "./chunk-X6FH5QTD.mjs";
7
+ import "./chunk-SOBLKZGE.mjs";
8
8
 
9
9
  // src/jsx-dev-runtime.tsx
10
10
  function jsxDEV(type, props, key, isStaticChildren, _source, _self) {
@@ -3233,11 +3233,16 @@ var CSS_UNITLESS = /* @__PURE__ */ new Set([
3233
3233
  "gridRowStart",
3234
3234
  "gridRowEnd"
3235
3235
  ]);
3236
+ var RN_SHORTHAND_EXPAND = {
3237
+ marginHorizontal: ["margin-left", "margin-right"],
3238
+ marginVertical: ["margin-top", "margin-bottom"],
3239
+ paddingHorizontal: ["padding-left", "padding-right"],
3240
+ paddingVertical: ["padding-top", "padding-bottom"]
3241
+ };
3236
3242
  function styleValueToCSS(styles, forceImportant = false) {
3237
- return Object.entries(styles).filter(
3238
- ([prop, v]) => v !== void 0 && v !== null && typeof v !== "object" && !RN_ONLY_PROPS.has(prop)
3239
- ).map(([prop, val]) => {
3240
- const cssProp = camelToKebab(prop);
3243
+ const parts = [];
3244
+ for (const [prop, val] of Object.entries(styles)) {
3245
+ if (val === void 0 || val === null || typeof val === "object" || RN_ONLY_PROPS.has(prop)) continue;
3241
3246
  let cssVal;
3242
3247
  if (typeof val === "number") {
3243
3248
  cssVal = val === 0 || CSS_UNITLESS.has(prop) ? String(val) : `${val}px`;
@@ -3245,8 +3250,15 @@ function styleValueToCSS(styles, forceImportant = false) {
3245
3250
  cssVal = String(val);
3246
3251
  }
3247
3252
  const imp = forceImportant || prop === "display" && (cssVal === "grid" || cssVal === "inline-grid") || prop === "position" && (cssVal === "sticky" || cssVal === "fixed" || cssVal === "static") ? " !important" : "";
3248
- return `${cssProp}: ${cssVal}${imp}`;
3249
- }).join("; ");
3253
+ if (prop in RN_SHORTHAND_EXPAND) {
3254
+ const [p1, p2] = RN_SHORTHAND_EXPAND[prop];
3255
+ parts.push(`${p1}: ${cssVal}${imp}`);
3256
+ parts.push(`${p2}: ${cssVal}${imp}`);
3257
+ continue;
3258
+ }
3259
+ parts.push(`${camelToKebab(prop)}: ${cssVal}${imp}`);
3260
+ }
3261
+ return parts.join("; ");
3250
3262
  }
3251
3263
  function camelToKebab(str) {
3252
3264
  return str.replace(/([A-Z])/g, "-$1").toLowerCase();
@@ -2,9 +2,9 @@ import {
2
2
  Fragment,
3
3
  jsx,
4
4
  jsxs
5
- } from "./chunk-HTPCUYNH.mjs";
6
- import "./chunk-RMZIFMWE.mjs";
7
- import "./chunk-SHQPNCQ7.mjs";
5
+ } from "./chunk-VZD4672I.mjs";
6
+ import "./chunk-X6FH5QTD.mjs";
7
+ import "./chunk-SOBLKZGE.mjs";
8
8
  export {
9
9
  Fragment,
10
10
  jsx,
@@ -4,15 +4,15 @@ import { F as FrameworkConfig } from './types-CV5vXnSH.mjs';
4
4
  /**
5
5
  * @kbach/react/vite
6
6
  *
7
- * Vite plugin that scans source files for Kbach className/kb props and
8
- * generates a static CSS stylesheet — no JSX runtime replacement needed.
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:
9
11
  *
10
- * Usage in vite.config.ts:
11
12
  * import { kbach } from '@kbach/react/vite';
12
13
  * plugins: [kbach()]
13
14
  *
14
- * Import the generated stylesheet once in your app entry (e.g. app/root.tsx):
15
- * import 'virtual:kbach/styles.css';
15
+ * CSS is only generated for the classes you actually use (like Tailwind).
16
16
  */
17
17
 
18
18
  declare const VIRTUAL_ID = "virtual:kbach/styles.css";
@@ -4,15 +4,15 @@ import { F as FrameworkConfig } from './types-CV5vXnSH.js';
4
4
  /**
5
5
  * @kbach/react/vite
6
6
  *
7
- * Vite plugin that scans source files for Kbach className/kb props and
8
- * generates a static CSS stylesheet — no JSX runtime replacement needed.
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:
9
11
  *
10
- * Usage in vite.config.ts:
11
12
  * import { kbach } from '@kbach/react/vite';
12
13
  * plugins: [kbach()]
13
14
  *
14
- * Import the generated stylesheet once in your app entry (e.g. app/root.tsx):
15
- * import 'virtual:kbach/styles.css';
15
+ * CSS is only generated for the classes you actually use (like Tailwind).
16
16
  */
17
17
 
18
18
  declare const VIRTUAL_ID = "virtual:kbach/styles.css";
@@ -3183,11 +3183,16 @@ var CSS_UNITLESS = /* @__PURE__ */ new Set([
3183
3183
  "gridRowStart",
3184
3184
  "gridRowEnd"
3185
3185
  ]);
3186
+ var RN_SHORTHAND_EXPAND = {
3187
+ marginHorizontal: ["margin-left", "margin-right"],
3188
+ marginVertical: ["margin-top", "margin-bottom"],
3189
+ paddingHorizontal: ["padding-left", "padding-right"],
3190
+ paddingVertical: ["padding-top", "padding-bottom"]
3191
+ };
3186
3192
  function styleValueToCSS(styles, forceImportant = false) {
3187
- return Object.entries(styles).filter(
3188
- ([prop, v]) => v !== void 0 && v !== null && typeof v !== "object" && !RN_ONLY_PROPS.has(prop)
3189
- ).map(([prop, val]) => {
3190
- const cssProp = camelToKebab(prop);
3193
+ const parts = [];
3194
+ for (const [prop, val] of Object.entries(styles)) {
3195
+ if (val === void 0 || val === null || typeof val === "object" || RN_ONLY_PROPS.has(prop)) continue;
3191
3196
  let cssVal;
3192
3197
  if (typeof val === "number") {
3193
3198
  cssVal = val === 0 || CSS_UNITLESS.has(prop) ? String(val) : `${val}px`;
@@ -3195,8 +3200,15 @@ function styleValueToCSS(styles, forceImportant = false) {
3195
3200
  cssVal = String(val);
3196
3201
  }
3197
3202
  const imp = forceImportant || prop === "display" && (cssVal === "grid" || cssVal === "inline-grid") || prop === "position" && (cssVal === "sticky" || cssVal === "fixed" || cssVal === "static") ? " !important" : "";
3198
- return `${cssProp}: ${cssVal}${imp}`;
3199
- }).join("; ");
3203
+ if (prop in RN_SHORTHAND_EXPAND) {
3204
+ const [p1, p2] = RN_SHORTHAND_EXPAND[prop];
3205
+ parts.push(`${p1}: ${cssVal}${imp}`);
3206
+ parts.push(`${p2}: ${cssVal}${imp}`);
3207
+ continue;
3208
+ }
3209
+ parts.push(`${camelToKebab(prop)}: ${cssVal}${imp}`);
3210
+ }
3211
+ return parts.join("; ");
3200
3212
  }
3201
3213
  function camelToKebab(str) {
3202
3214
  return str.replace(/([A-Z])/g, "-$1").toLowerCase();
@@ -3337,7 +3349,7 @@ var customVariants = new Proxy(
3337
3349
 
3338
3350
  // src/vite-plugin.ts
3339
3351
  var VIRTUAL_ID = "virtual:kbach/styles.css";
3340
- var RESOLVED_ID = "\0" + VIRTUAL_ID;
3352
+ var RESOLVED_ID = "\0virtual:kbach/styles.css";
3341
3353
  function toNumericScreens(screens) {
3342
3354
  const out = {};
3343
3355
  for (const [k, v] of Object.entries(screens)) {
@@ -3382,20 +3394,23 @@ function buildGlobalCSS(theme) {
3382
3394
  function kbach(userConfig) {
3383
3395
  const cfg = buildConfig(userConfig ?? {});
3384
3396
  const screens = toNumericScreens(cfg.theme.screens ?? {});
3385
- const cssMap = /* @__PURE__ */ new Map();
3397
+ const tokenCSS = /* @__PURE__ */ new Map();
3398
+ const processedCSSFiles = /* @__PURE__ */ new Set();
3386
3399
  let root = process.cwd();
3387
- let isDev = false;
3400
+ let server = null;
3388
3401
  function processClassString(classStr) {
3389
- if (cssMap.has(classStr)) return;
3390
- cssMap.set(classStr, generateClassCSS(classStr, cfg.theme, cfg.darkMode, screens));
3402
+ let added = false;
3403
+ for (const token of classStr.split(/\s+/).filter(Boolean)) {
3404
+ if (tokenCSS.has(token)) continue;
3405
+ tokenCSS.set(token, generateClassCSS(token, cfg.theme, cfg.darkMode, screens));
3406
+ added = true;
3407
+ }
3408
+ return added;
3391
3409
  }
3392
3410
  function extractFromCode(code) {
3393
3411
  let added = false;
3394
3412
  for (const cls of extractClassStrings(code)) {
3395
- if (!cssMap.has(cls)) {
3396
- processClassString(cls);
3397
- added = true;
3398
- }
3413
+ if (processClassString(cls)) added = true;
3399
3414
  }
3400
3415
  return added;
3401
3416
  }
@@ -3403,22 +3418,29 @@ function kbach(userConfig) {
3403
3418
  const parts = [];
3404
3419
  const global = buildGlobalCSS(cfg.theme);
3405
3420
  if (global) parts.push(global);
3406
- for (const css of cssMap.values()) {
3421
+ for (const css of tokenCSS.values()) {
3407
3422
  if (css) parts.push(css);
3408
3423
  }
3409
3424
  return parts.join("\n");
3410
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
+ }
3411
3433
  return {
3412
3434
  name: "kbach",
3413
3435
  enforce: "pre",
3414
- config(_c, env) {
3415
- isDev = env.command === "serve";
3416
- },
3417
3436
  configResolved(resolved) {
3418
3437
  root = resolved.root;
3419
3438
  },
3439
+ configureServer(s) {
3440
+ server = s;
3441
+ },
3420
3442
  buildStart() {
3421
- for (const dir of ["src", "app", "pages", "components"]) {
3443
+ for (const dir of ["src", "app", "pages", "components", "views", "layouts"]) {
3422
3444
  scanDir((0, import_path.join)(root, dir), (code) => extractFromCode(code));
3423
3445
  }
3424
3446
  },
@@ -3429,23 +3451,24 @@ function kbach(userConfig) {
3429
3451
  if (id === RESOLVED_ID) return getAllCSS();
3430
3452
  },
3431
3453
  transform(code, id) {
3432
- if (id.includes("node_modules") || !/\.(tsx?|jsx?)$/.test(id)) return;
3433
- const added = extractFromCode(code);
3434
- if (isDev && added) {
3454
+ if (id.endsWith(".css") && !id.includes("node_modules") && !id.includes("\0")) {
3455
+ processedCSSFiles.add(id);
3456
+ const kbachCSS = getAllCSS();
3457
+ if (!kbachCSS) return null;
3458
+ return { code: code + "\n/* kbach utilities */\n" + kbachCSS, map: null };
3459
+ }
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
+ }
3435
3465
  }
3436
3466
  },
3437
- handleHotUpdate({ file, server }) {
3467
+ handleHotUpdate({ file }) {
3438
3468
  if (file.includes("node_modules") || !/\.(tsx?|jsx?)$/.test(file)) return;
3439
3469
  try {
3440
- const code = (0, import_fs.readFileSync)(file, "utf-8");
3441
- const added = extractFromCode(code);
3442
- if (added) {
3443
- const mod = server.moduleGraph.getModuleById(RESOLVED_ID);
3444
- if (mod) {
3445
- server.moduleGraph.invalidateModule(mod);
3446
- return [mod];
3447
- }
3448
- }
3470
+ const added = extractFromCode((0, import_fs.readFileSync)(file, "utf-8"));
3471
+ if (added) invalidateCSSModules();
3449
3472
  } catch {
3450
3473
  }
3451
3474
  }
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  buildConfig,
3
3
  generateClassCSS
4
- } from "./chunk-SHQPNCQ7.mjs";
4
+ } from "./chunk-SOBLKZGE.mjs";
5
5
 
6
6
  // src/vite-plugin.ts
7
7
  import { readFileSync, readdirSync, statSync } from "fs";
8
8
  import { join } from "path";
9
9
  var VIRTUAL_ID = "virtual:kbach/styles.css";
10
- var RESOLVED_ID = "\0" + VIRTUAL_ID;
10
+ var RESOLVED_ID = "\0virtual:kbach/styles.css";
11
11
  function toNumericScreens(screens) {
12
12
  const out = {};
13
13
  for (const [k, v] of Object.entries(screens)) {
@@ -52,20 +52,23 @@ function buildGlobalCSS(theme) {
52
52
  function kbach(userConfig) {
53
53
  const cfg = buildConfig(userConfig ?? {});
54
54
  const screens = toNumericScreens(cfg.theme.screens ?? {});
55
- const cssMap = /* @__PURE__ */ new Map();
55
+ const tokenCSS = /* @__PURE__ */ new Map();
56
+ const processedCSSFiles = /* @__PURE__ */ new Set();
56
57
  let root = process.cwd();
57
- let isDev = false;
58
+ let server = null;
58
59
  function processClassString(classStr) {
59
- if (cssMap.has(classStr)) return;
60
- cssMap.set(classStr, generateClassCSS(classStr, cfg.theme, cfg.darkMode, screens));
60
+ let added = false;
61
+ for (const token of classStr.split(/\s+/).filter(Boolean)) {
62
+ if (tokenCSS.has(token)) continue;
63
+ tokenCSS.set(token, generateClassCSS(token, cfg.theme, cfg.darkMode, screens));
64
+ added = true;
65
+ }
66
+ return added;
61
67
  }
62
68
  function extractFromCode(code) {
63
69
  let added = false;
64
70
  for (const cls of extractClassStrings(code)) {
65
- if (!cssMap.has(cls)) {
66
- processClassString(cls);
67
- added = true;
68
- }
71
+ if (processClassString(cls)) added = true;
69
72
  }
70
73
  return added;
71
74
  }
@@ -73,22 +76,29 @@ function kbach(userConfig) {
73
76
  const parts = [];
74
77
  const global = buildGlobalCSS(cfg.theme);
75
78
  if (global) parts.push(global);
76
- for (const css of cssMap.values()) {
79
+ for (const css of tokenCSS.values()) {
77
80
  if (css) parts.push(css);
78
81
  }
79
82
  return parts.join("\n");
80
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
+ }
81
91
  return {
82
92
  name: "kbach",
83
93
  enforce: "pre",
84
- config(_c, env) {
85
- isDev = env.command === "serve";
86
- },
87
94
  configResolved(resolved) {
88
95
  root = resolved.root;
89
96
  },
97
+ configureServer(s) {
98
+ server = s;
99
+ },
90
100
  buildStart() {
91
- for (const dir of ["src", "app", "pages", "components"]) {
101
+ for (const dir of ["src", "app", "pages", "components", "views", "layouts"]) {
92
102
  scanDir(join(root, dir), (code) => extractFromCode(code));
93
103
  }
94
104
  },
@@ -99,23 +109,24 @@ function kbach(userConfig) {
99
109
  if (id === RESOLVED_ID) return getAllCSS();
100
110
  },
101
111
  transform(code, id) {
102
- if (id.includes("node_modules") || !/\.(tsx?|jsx?)$/.test(id)) return;
103
- const added = extractFromCode(code);
104
- if (isDev && added) {
112
+ if (id.endsWith(".css") && !id.includes("node_modules") && !id.includes("\0")) {
113
+ processedCSSFiles.add(id);
114
+ const kbachCSS = getAllCSS();
115
+ if (!kbachCSS) return null;
116
+ return { code: code + "\n/* kbach utilities */\n" + kbachCSS, map: null };
117
+ }
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
+ }
105
123
  }
106
124
  },
107
- handleHotUpdate({ file, server }) {
125
+ handleHotUpdate({ file }) {
108
126
  if (file.includes("node_modules") || !/\.(tsx?|jsx?)$/.test(file)) return;
109
127
  try {
110
- const code = readFileSync(file, "utf-8");
111
- const added = extractFromCode(code);
112
- if (added) {
113
- const mod = server.moduleGraph.getModuleById(RESOLVED_ID);
114
- if (mod) {
115
- server.moduleGraph.invalidateModule(mod);
116
- return [mod];
117
- }
118
- }
128
+ const added = extractFromCode(readFileSync(file, "utf-8"));
129
+ if (added) invalidateCSSModules();
119
130
  } catch {
120
131
  }
121
132
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
- {
1
+ {
2
2
  "name": "@kbach/react",
3
- "version": "0.5.16",
3
+ "version": "0.5.18",
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",