@kbach/react 0.5.46 → 0.5.48

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.
@@ -10,7 +10,18 @@ export { Fragment, JSX } from 'react';
10
10
  */
11
11
 
12
12
  declare function _invalidateDefaultFontCache(): void;
13
+ /**
14
+ * Register a custom React Native component → HTML tag substitution.
15
+ * Call this once at app startup (before first render).
16
+ *
17
+ * ```ts
18
+ * import { Animated } from 'react-native';
19
+ * import { registerWebElement } from '@kbach/react/jsx-runtime';
20
+ * registerWebElement(Animated.View, 'div');
21
+ * ```
22
+ */
23
+ declare function registerWebElement(rnComponent: unknown, htmlTag: string): void;
13
24
  declare function jsx(type: unknown, props: Record<string, unknown> | null, key?: string): ReactElement;
14
25
  declare function jsxs(type: unknown, props: Record<string, unknown> | null, key?: string): ReactElement;
15
26
 
16
- export { _invalidateDefaultFontCache, jsx, jsxs };
27
+ export { _invalidateDefaultFontCache, jsx, jsxs, registerWebElement };
@@ -10,7 +10,18 @@ export { Fragment, JSX } from 'react';
10
10
  */
11
11
 
12
12
  declare function _invalidateDefaultFontCache(): void;
13
+ /**
14
+ * Register a custom React Native component → HTML tag substitution.
15
+ * Call this once at app startup (before first render).
16
+ *
17
+ * ```ts
18
+ * import { Animated } from 'react-native';
19
+ * import { registerWebElement } from '@kbach/react/jsx-runtime';
20
+ * registerWebElement(Animated.View, 'div');
21
+ * ```
22
+ */
23
+ declare function registerWebElement(rnComponent: unknown, htmlTag: string): void;
13
24
  declare function jsx(type: unknown, props: Record<string, unknown> | null, key?: string): ReactElement;
14
25
  declare function jsxs(type: unknown, props: Record<string, unknown> | null, key?: string): ReactElement;
15
26
 
16
- export { _invalidateDefaultFontCache, jsx, jsxs };
27
+ export { _invalidateDefaultFontCache, jsx, jsxs, registerWebElement };
@@ -33,7 +33,8 @@ __export(jsx_runtime_exports, {
33
33
  Fragment: () => import_react5.Fragment,
34
34
  _invalidateDefaultFontCache: () => _invalidateDefaultFontCache,
35
35
  jsx: () => jsx,
36
- jsxs: () => jsxs
36
+ jsxs: () => jsxs,
37
+ registerWebElement: () => registerWebElement
37
38
  });
38
39
  module.exports = __toCommonJS(jsx_runtime_exports);
39
40
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -787,7 +788,12 @@ function resolveColor(value, colors, isArbitrary) {
787
788
  }
788
789
  }
789
790
  if (!hex) return null;
790
- if (!opacityPart) return hex;
791
+ if (!opacityPart) {
792
+ if (!isWeb && hex.startsWith("#") && hex.length === 9) {
793
+ return hexToRgba(hex, Math.round(parseInt(hex.slice(7, 9), 16) / 255 * 1e3) / 1e3);
794
+ }
795
+ return hex;
796
+ }
791
797
  let alpha;
792
798
  if (opacityPart.startsWith("[") && opacityPart.endsWith("]")) {
793
799
  const v = parseFloat(opacityPart.slice(1, -1));
@@ -2350,12 +2356,6 @@ var RESOLVERS = {
2350
2356
  function resolveUtility(parsed, theme) {
2351
2357
  if (!parsed.value) {
2352
2358
  if (parsed.utility in PLUGIN_STANDALONE) return PLUGIN_STANDALONE[parsed.utility] ?? null;
2353
- if (parsed.utility === "grd" || parsed.utility === "grid") {
2354
- return getEffectiveIsWeb() ? { display: "grid" } : null;
2355
- }
2356
- if (parsed.utility === "inline-grid") {
2357
- return getEffectiveIsWeb() ? { display: "inline-grid" } : null;
2358
- }
2359
2359
  if (parsed.utility in getStandalone()) return getStandalone()[parsed.utility] ?? null;
2360
2360
  }
2361
2361
  const resolver = PLUGIN_RESOLVERS[parsed.utility] ?? RESOLVERS[parsed.utility];
@@ -2506,16 +2506,18 @@ function findOuterColon(s) {
2506
2506
 
2507
2507
  // src/core/reset.ts
2508
2508
  var BASE_RESET = [
2509
- "*, *::before, *::after { box-sizing: border-box; }",
2509
+ // border-style: solid means border-N utilities show a visible border without an extra border-solid class.
2510
+ // border-width: 0 keeps all elements borderless by default.
2511
+ "*, *::before, *::after { box-sizing: border-box; border-width: 0; border-style: solid; border-color: currentColor; }",
2510
2512
  "body { margin: 0; padding: 0; }",
2511
2513
  "h1, h2, h3, h4, h5, h6 { margin: 0; font-size: inherit; font-weight: inherit; }",
2512
2514
  "p { margin: 0; }",
2513
2515
  "a { color: inherit; text-decoration: none; }",
2514
2516
  "ul, ol { margin: 0; padding: 0; list-style: none; }",
2515
2517
  "img, video, svg { display: block; max-width: 100%; }",
2516
- "input, textarea, select { appearance: none; -webkit-appearance: none; background: transparent; border: 0; padding: 0; margin: 0; font: inherit; color: inherit; line-height: inherit; }",
2517
- "button { appearance: none; -webkit-appearance: none; background: transparent; border: 0; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer; line-height: inherit; text-align: inherit; }",
2518
- "fieldset { border: 0; padding: 0; margin: 0; }",
2518
+ "input, textarea, select { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; line-height: inherit; }",
2519
+ "button { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer; line-height: inherit; text-align: inherit; }",
2520
+ "fieldset { padding: 0; margin: 0; }",
2519
2521
  "table { border-collapse: collapse; border-spacing: 0; }"
2520
2522
  ].join("\n");
2521
2523
 
@@ -2938,6 +2940,8 @@ function buildConfig(userConfig) {
2938
2940
  };
2939
2941
  clearPluginUtilities();
2940
2942
  clearPluginModifiers();
2943
+ const _store = getConfigStore();
2944
+ for (const k of Object.keys(_store.customVariants)) delete _store.customVariants[k];
2941
2945
  const pluginAPI = makePluginAPI(resolved.theme);
2942
2946
  for (const plugin of resolved.plugins) {
2943
2947
  plugin(pluginAPI);
@@ -3144,7 +3148,7 @@ var InteractiveWrapper = (0, import_react3.forwardRef)(
3144
3148
  const handleBlur = (0, import_react3.useCallback)(chain(onBlur, () => setFocused(false)), [onBlur]);
3145
3149
  const computedStyle = (0, import_react3.useMemo)(
3146
3150
  () => {
3147
- const s = flatten(resolvedStyle, isDark, { pressed, hover: hovered, focus: focused }, breakpoints);
3151
+ const s = flatten(resolvedStyle, isDark, { pressed, hover: hovered, focus: focused, disabled: !!rest.disabled, checked: !!rest.checked }, breakpoints);
3148
3152
  delete s.__divideX;
3149
3153
  delete s.__divideY;
3150
3154
  delete s.__divideColor;
@@ -3178,8 +3182,8 @@ var InteractiveWrapper = (0, import_react3.forwardRef)(
3178
3182
  [resolvedStyle, isDark, pressed, hovered, focused, width]
3179
3183
  // eslint-disable-line react-hooks/exhaustive-deps
3180
3184
  );
3181
- const isWebHTMLElement = !isNative && typeof Component === "string";
3182
- const finalStyle = isWebHTMLElement ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
3185
+ const skipComputedInline = isWeb || !isNative && typeof Component === "string";
3186
+ const finalStyle = skipComputedInline ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
3183
3187
  const { children, ...restWithoutChildren } = rest;
3184
3188
  const componentProps = {
3185
3189
  ref,
@@ -3207,11 +3211,15 @@ var DarkWrapper = import_react4.default.forwardRef(
3207
3211
  const needsWidth = hasResponsiveBuckets(resolvedStyle);
3208
3212
  const width = useConditionalWidth(needsWidth);
3209
3213
  const breakpoints = needsWidth ? getActiveBreakpoints(width) : EMPTY_BREAKPOINTS2;
3210
- const computedStyle = flatten(resolvedStyle, isDark, {}, breakpoints);
3211
- stripInternalMarkers(computedStyle);
3212
- if (typeof Component !== "string") stripWebOnlyProps(computedStyle);
3213
- const isWebHTMLElement = !isNative && typeof Component === "string";
3214
- const finalStyle = isWebHTMLElement ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
3214
+ const isNonStringComponent = typeof Component !== "string";
3215
+ const computedStyle = (0, import_react4.useMemo)(() => {
3216
+ const s = flatten(resolvedStyle, isDark, {}, breakpoints);
3217
+ stripInternalMarkers(s);
3218
+ if (isNonStringComponent) stripWebOnlyProps(s);
3219
+ return s;
3220
+ }, [resolvedStyle, isDark, width, isNonStringComponent]);
3221
+ const skipComputedInline = isWeb || !isNative && typeof Component === "string";
3222
+ const finalStyle = skipComputedInline ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
3215
3223
  const props = { ref, ...rest, style: finalStyle };
3216
3224
  return Array.isArray(children) ? import_react4.default.createElement(Component, props, ...children) : import_react4.default.createElement(Component, props, children);
3217
3225
  }
@@ -3329,14 +3337,101 @@ function stripWebOnlyInlineProps(s) {
3329
3337
  delete s.position;
3330
3338
  }
3331
3339
  }
3340
+ var _rnToHtml = {
3341
+ View: "div",
3342
+ SafeAreaView: "div",
3343
+ KeyboardAvoidingView: "div",
3344
+ ScrollView: "div",
3345
+ VirtualizedList: "div",
3346
+ Text: "span",
3347
+ Pressable: "div",
3348
+ TouchableOpacity: "div",
3349
+ TouchableHighlight: "div",
3350
+ TouchableWithoutFeedback: "div",
3351
+ TouchableNativeFeedback: "div"
3352
+ };
3353
+ var _userWebTypeMap = /* @__PURE__ */ new Map();
3354
+ var _webTypeCache = /* @__PURE__ */ new WeakMap();
3355
+ function registerWebElement(rnComponent, htmlTag) {
3356
+ if (typeof rnComponent !== "object" && typeof rnComponent !== "function") return;
3357
+ _userWebTypeMap.set(rnComponent, htmlTag);
3358
+ _webTypeCache.delete(rnComponent);
3359
+ }
3360
+ function getWebTag(type) {
3361
+ if (typeof type === "string") return null;
3362
+ if (type === null || typeof type !== "function" && typeof type !== "object") return null;
3363
+ const obj = type;
3364
+ if (_userWebTypeMap.has(obj)) return _userWebTypeMap.get(obj);
3365
+ if (_webTypeCache.has(obj)) return _webTypeCache.get(obj);
3366
+ const name = obj.displayName ?? obj.name;
3367
+ const tag = name ? _rnToHtml[name] ?? null : null;
3368
+ _webTypeCache.set(obj, tag);
3369
+ return tag;
3370
+ }
3371
+ var _rnOnlyProps = /* @__PURE__ */ new Set([
3372
+ "onLongPress",
3373
+ "delayLongPress",
3374
+ "activeOpacity",
3375
+ "underlayColor",
3376
+ "hitSlop",
3377
+ "pressRetentionOffset",
3378
+ "accessible",
3379
+ "accessibilityState",
3380
+ "accessibilityLiveRegion",
3381
+ "importantForAccessibility",
3382
+ "nativeID",
3383
+ "collapsable",
3384
+ "needsOffscreenAlphaCompositing",
3385
+ "renderToHardwareTextureAndroid",
3386
+ "shouldRasterizeIOS",
3387
+ "pointerEvents"
3388
+ // RN prop — values differ from HTML pointer-events CSS
3389
+ ]);
3390
+ var _pressableDisplayNames = /* @__PURE__ */ new Set([
3391
+ "Pressable",
3392
+ "TouchableOpacity",
3393
+ "TouchableHighlight",
3394
+ "TouchableWithoutFeedback",
3395
+ "TouchableNativeFeedback"
3396
+ ]);
3397
+ function transformToWebProps(originalName, props) {
3398
+ const out = {};
3399
+ const isPressable = _pressableDisplayNames.has(originalName);
3400
+ for (const [k, v] of Object.entries(props)) {
3401
+ if (_rnOnlyProps.has(k)) continue;
3402
+ if (k === "onPress") {
3403
+ if (!("onClick" in props)) out.onClick = v;
3404
+ continue;
3405
+ }
3406
+ if (k === "accessibilityLabel") {
3407
+ if (out["aria-label"] == null) out["aria-label"] = v;
3408
+ continue;
3409
+ }
3410
+ if (k === "accessibilityRole") {
3411
+ if (out.role == null) out.role = v;
3412
+ continue;
3413
+ }
3414
+ if (k === "testID") {
3415
+ if (out["data-testid"] == null) out["data-testid"] = v;
3416
+ continue;
3417
+ }
3418
+ out[k] = v;
3419
+ }
3420
+ if (isPressable && !out.role) out.role = "button";
3421
+ return out;
3422
+ }
3332
3423
  function processElement(type, rawProps, key, isStaticChildren) {
3333
3424
  if (typeof type === "symbol") return makeElement(isStaticChildren, type, rawProps ?? {}, key);
3334
- if (!rawProps) return (0, import_jsx_runtime.jsx)(type, null, key);
3335
- const { className, kb: kbProp, __kbachStyles, __kbachClasses } = rawProps;
3425
+ const webTag = isWeb ? getWebTag(type) : null;
3426
+ const effectiveType = webTag ?? type;
3427
+ const originalName = webTag ? type?.displayName ?? type?.name : void 0;
3428
+ if (!rawProps) return (0, import_jsx_runtime.jsx)(effectiveType, null, key);
3429
+ const workingProps = webTag && originalName ? transformToWebProps(originalName, rawProps) : rawProps;
3430
+ const { className, kb: kbProp, __kbachStyles, __kbachClasses } = workingProps;
3336
3431
  const classStr = className ?? kbProp ?? __kbachClasses;
3337
3432
  if (!isNative && isRuntimeCSSDisabled() && classStr && !__kbachStyles) {
3338
- const { style: userStyle2, ...passProps2 } = omitConsumed(rawProps);
3339
- return makeElement(isStaticChildren, type, {
3433
+ const { style: userStyle2, ...passProps2 } = omitConsumed(workingProps);
3434
+ return makeElement(isStaticChildren, effectiveType, {
3340
3435
  ...passProps2,
3341
3436
  className: normalizeClassString(classStr),
3342
3437
  ...userStyle2 !== void 0 ? { style: userStyle2 } : {}
@@ -3344,18 +3439,18 @@ function processElement(type, rawProps, key, isStaticChildren) {
3344
3439
  }
3345
3440
  if (!classStr && !__kbachStyles) {
3346
3441
  const defaultFont = getCachedDefaultFont();
3347
- if (!defaultFont) return makeElement(isStaticChildren, type, rawProps, key);
3348
- const { style: userStyle2, ...passProps2 } = omitConsumed(rawProps);
3442
+ if (!defaultFont) return makeElement(isStaticChildren, effectiveType, workingProps, key);
3443
+ const { style: userStyle2, ...passProps2 } = omitConsumed(workingProps);
3349
3444
  const finalStyle2 = userStyle2 ? Array.isArray(userStyle2) ? { fontFamily: defaultFont, ...Object.assign({}, ...userStyle2) } : { fontFamily: defaultFont, ...userStyle2 } : { fontFamily: defaultFont };
3350
- return makeElement(isStaticChildren, type, { ...passProps2, style: finalStyle2 }, key);
3445
+ return makeElement(isStaticChildren, effectiveType, { ...passProps2, style: finalStyle2 }, key);
3351
3446
  }
3352
3447
  const config = getConfig();
3353
3448
  const resolved = __kbachStyles ?? (classStr ? resolve(classStr, config.theme, config.darkMode) : {});
3354
- const { style: userStyle, ...passProps } = omitConsumed(rawProps);
3449
+ const { style: userStyle, ...passProps } = omitConsumed(workingProps);
3355
3450
  const { interactive, modeOrResponsive } = bucketMods(resolved);
3356
3451
  if (interactive) {
3357
3452
  return (0, import_jsx_runtime.jsx)(InteractiveWrapper, {
3358
- Component: type,
3453
+ Component: effectiveType,
3359
3454
  resolvedStyle: resolved,
3360
3455
  ...!isNative && classStr ? { className: normalizeClassString(classStr) } : {},
3361
3456
  style: userStyle,
@@ -3364,24 +3459,24 @@ function processElement(type, rawProps, key, isStaticChildren) {
3364
3459
  }
3365
3460
  if (modeOrResponsive) {
3366
3461
  return (0, import_jsx_runtime.jsx)(DarkWrapper, {
3367
- Component: type,
3462
+ Component: effectiveType,
3368
3463
  resolvedStyle: resolved,
3369
3464
  ...!isNative && classStr ? { className: normalizeClassString(classStr) } : {},
3370
3465
  style: userStyle,
3371
3466
  ...passProps
3372
3467
  }, key);
3373
3468
  }
3374
- const isWebHTMLElement = !isNative && typeof type === "string";
3469
+ const skipComputedInline = isWeb || !isNative && typeof effectiveType === "string";
3375
3470
  let finalStyle;
3376
- if (!isWebHTMLElement) {
3471
+ if (!skipComputedInline) {
3377
3472
  const computedStyle = flatten(resolved, false);
3378
3473
  stripInternalMarkers2(computedStyle);
3379
- if (typeof type !== "string") stripWebOnlyInlineProps(computedStyle);
3474
+ if (typeof effectiveType !== "string") stripWebOnlyInlineProps(computedStyle);
3380
3475
  finalStyle = mergeStyle(computedStyle, userStyle);
3381
3476
  } else {
3382
3477
  finalStyle = userStyle ?? void 0;
3383
3478
  }
3384
- return makeElement(isStaticChildren, type, {
3479
+ return makeElement(isStaticChildren, effectiveType, {
3385
3480
  ...passProps,
3386
3481
  style: finalStyle,
3387
3482
  ...!isNative && classStr ? { className: normalizeClassString(classStr) } : {}
@@ -3398,5 +3493,6 @@ function jsxs(type, props, key) {
3398
3493
  Fragment,
3399
3494
  _invalidateDefaultFontCache,
3400
3495
  jsx,
3401
- jsxs
3496
+ jsxs,
3497
+ registerWebElement
3402
3498
  });
@@ -2,13 +2,14 @@ import {
2
2
  Fragment,
3
3
  _invalidateDefaultFontCache,
4
4
  jsx,
5
- jsxs
6
- } from "./chunk-ZN5E7I56.mjs";
7
- import "./chunk-ISCQQRG5.mjs";
8
- import "./chunk-G76344ZQ.mjs";
5
+ jsxs,
6
+ registerWebElement
7
+ } from "./chunk-YZNSWFJT.mjs";
8
+ import "./chunk-BKSXIWL7.mjs";
9
9
  export {
10
10
  Fragment,
11
11
  _invalidateDefaultFontCache,
12
12
  jsx,
13
- jsxs
13
+ jsxs,
14
+ registerWebElement
14
15
  };
@@ -49,16 +49,18 @@ function escapeCSSSelector(cls) {
49
49
 
50
50
  // src/core/reset.ts
51
51
  var BASE_RESET = [
52
- "*, *::before, *::after { box-sizing: border-box; }",
52
+ // border-style: solid means border-N utilities show a visible border without an extra border-solid class.
53
+ // border-width: 0 keeps all elements borderless by default.
54
+ "*, *::before, *::after { box-sizing: border-box; border-width: 0; border-style: solid; border-color: currentColor; }",
53
55
  "body { margin: 0; padding: 0; }",
54
56
  "h1, h2, h3, h4, h5, h6 { margin: 0; font-size: inherit; font-weight: inherit; }",
55
57
  "p { margin: 0; }",
56
58
  "a { color: inherit; text-decoration: none; }",
57
59
  "ul, ol { margin: 0; padding: 0; list-style: none; }",
58
60
  "img, video, svg { display: block; max-width: 100%; }",
59
- "input, textarea, select { appearance: none; -webkit-appearance: none; background: transparent; border: 0; padding: 0; margin: 0; font: inherit; color: inherit; line-height: inherit; }",
60
- "button { appearance: none; -webkit-appearance: none; background: transparent; border: 0; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer; line-height: inherit; text-align: inherit; }",
61
- "fieldset { border: 0; padding: 0; margin: 0; }",
61
+ "input, textarea, select { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; line-height: inherit; }",
62
+ "button { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer; line-height: inherit; text-align: inherit; }",
63
+ "fieldset { padding: 0; margin: 0; }",
62
64
  "table { border-collapse: collapse; border-spacing: 0; }"
63
65
  ].join("\n");
64
66
 
@@ -640,7 +642,12 @@ function resolveColor(value, colors, isArbitrary) {
640
642
  }
641
643
  }
642
644
  if (!hex) return null;
643
- if (!opacityPart) return hex;
645
+ if (!opacityPart) {
646
+ if (!isWeb && hex.startsWith("#") && hex.length === 9) {
647
+ return hexToRgba(hex, Math.round(parseInt(hex.slice(7, 9), 16) / 255 * 1e3) / 1e3);
648
+ }
649
+ return hex;
650
+ }
644
651
  let alpha;
645
652
  if (opacityPart.startsWith("[") && opacityPart.endsWith("]")) {
646
653
  const v = parseFloat(opacityPart.slice(1, -1));
@@ -2203,12 +2210,6 @@ var RESOLVERS = {
2203
2210
  function resolveUtility(parsed, theme) {
2204
2211
  if (!parsed.value) {
2205
2212
  if (parsed.utility in PLUGIN_STANDALONE) return PLUGIN_STANDALONE[parsed.utility] ?? null;
2206
- if (parsed.utility === "grd" || parsed.utility === "grid") {
2207
- return getEffectiveIsWeb() ? { display: "grid" } : null;
2208
- }
2209
- if (parsed.utility === "inline-grid") {
2210
- return getEffectiveIsWeb() ? { display: "inline-grid" } : null;
2211
- }
2212
2213
  if (parsed.utility in getStandalone()) return getStandalone()[parsed.utility] ?? null;
2213
2214
  }
2214
2215
  const resolver = PLUGIN_RESOLVERS[parsed.utility] ?? RESOLVERS[parsed.utility];
@@ -2761,6 +2762,8 @@ function buildConfig(userConfig) {
2761
2762
  };
2762
2763
  clearPluginUtilities();
2763
2764
  clearPluginModifiers();
2765
+ const _store = getConfigStore();
2766
+ for (const k of Object.keys(_store.customVariants)) delete _store.customVariants[k];
2764
2767
  const pluginAPI = makePluginAPI(resolved.theme);
2765
2768
  for (const plugin of resolved.plugins) {
2766
2769
  plugin(pluginAPI);
@@ -3006,13 +3009,25 @@ function extractClassStrings(code) {
3006
3009
  i++;
3007
3010
  }
3008
3011
  jsxExprRe.lastIndex = i + 1;
3009
- const innerStrings = block.match(/["'`]([^"'`]{1,300})["'`]/g) ?? [];
3012
+ const innerStrings = block.match(/["'`]([^"'`]{1,2000})["'`]/g) ?? [];
3010
3013
  for (const s of innerStrings) pushTokens(s.slice(1, -1), found);
3011
3014
  }
3012
- const clsxRe = /(?:clsx|cn|classnames|cx)\(([^)]{1,1000})\)/g;
3013
- while ((m = clsxRe.exec(code)) !== null) {
3014
- const block = m[1];
3015
- const innerStrings = block.match(/["'`]([^"'`]{1,300})["'`]/g) ?? [];
3015
+ const clsxCallRe = /(?:clsx|cn|classnames|cx)\(/g;
3016
+ while ((m = clsxCallRe.exec(code)) !== null) {
3017
+ let depth = 1;
3018
+ let i = m.index + m[0].length;
3019
+ let block = "";
3020
+ while (i < code.length && depth > 0) {
3021
+ const ch = code[i];
3022
+ if (ch === "(") depth++;
3023
+ else if (ch === ")") {
3024
+ if (--depth === 0) break;
3025
+ }
3026
+ block += ch;
3027
+ i++;
3028
+ }
3029
+ clsxCallRe.lastIndex = i + 1;
3030
+ const innerStrings = block.match(/["'`]([^"'`]{1,2000})["'`]/g) ?? [];
3016
3031
  for (const s of innerStrings) pushTokens(s.slice(1, -1), found);
3017
3032
  }
3018
3033
  const templateRe = /`([^`]{1,2000})`/g;
@@ -3062,12 +3077,10 @@ function kbach(userConfig) {
3062
3077
  function processFile(filePath, code) {
3063
3078
  const key = normPath(filePath);
3064
3079
  const tokens = /* @__PURE__ */ new Set();
3065
- for (const cls of extractClassStrings(code)) {
3066
- for (const tok of splitClassTokens(cls)) {
3067
- tokens.add(tok);
3068
- if (!tokenCSS.has(tok)) {
3069
- tokenCSS.set(tok, generateClassCSS(tok, cfg.theme, cfg.darkMode, screens));
3070
- }
3080
+ for (const tok of extractClassStrings(code)) {
3081
+ tokens.add(tok);
3082
+ if (!tokenCSS.has(tok)) {
3083
+ tokenCSS.set(tok, generateClassCSS(tok, cfg.theme, cfg.darkMode, screens));
3071
3084
  }
3072
3085
  }
3073
3086
  fileTokens.set(key, tokens);
@@ -4,7 +4,7 @@ import {
4
4
  generateClassCSS,
5
5
  setCSSGenMode,
6
6
  splitClassTokens
7
- } from "./chunk-G76344ZQ.mjs";
7
+ } from "./chunk-BKSXIWL7.mjs";
8
8
 
9
9
  // src/vite-plugin.ts
10
10
  import { readFileSync, writeFileSync, readdirSync, statSync } from "fs";
@@ -186,13 +186,25 @@ function extractClassStrings(code) {
186
186
  i++;
187
187
  }
188
188
  jsxExprRe.lastIndex = i + 1;
189
- const innerStrings = block.match(/["'`]([^"'`]{1,300})["'`]/g) ?? [];
189
+ const innerStrings = block.match(/["'`]([^"'`]{1,2000})["'`]/g) ?? [];
190
190
  for (const s of innerStrings) pushTokens(s.slice(1, -1), found);
191
191
  }
192
- const clsxRe = /(?:clsx|cn|classnames|cx)\(([^)]{1,1000})\)/g;
193
- while ((m = clsxRe.exec(code)) !== null) {
194
- const block = m[1];
195
- const innerStrings = block.match(/["'`]([^"'`]{1,300})["'`]/g) ?? [];
192
+ const clsxCallRe = /(?:clsx|cn|classnames|cx)\(/g;
193
+ while ((m = clsxCallRe.exec(code)) !== null) {
194
+ let depth = 1;
195
+ let i = m.index + m[0].length;
196
+ let block = "";
197
+ while (i < code.length && depth > 0) {
198
+ const ch = code[i];
199
+ if (ch === "(") depth++;
200
+ else if (ch === ")") {
201
+ if (--depth === 0) break;
202
+ }
203
+ block += ch;
204
+ i++;
205
+ }
206
+ clsxCallRe.lastIndex = i + 1;
207
+ const innerStrings = block.match(/["'`]([^"'`]{1,2000})["'`]/g) ?? [];
196
208
  for (const s of innerStrings) pushTokens(s.slice(1, -1), found);
197
209
  }
198
210
  const templateRe = /`([^`]{1,2000})`/g;
@@ -242,12 +254,10 @@ function kbach(userConfig) {
242
254
  function processFile(filePath, code) {
243
255
  const key = normPath(filePath);
244
256
  const tokens = /* @__PURE__ */ new Set();
245
- for (const cls of extractClassStrings(code)) {
246
- for (const tok of splitClassTokens(cls)) {
247
- tokens.add(tok);
248
- if (!tokenCSS.has(tok)) {
249
- tokenCSS.set(tok, generateClassCSS(tok, cfg.theme, cfg.darkMode, screens));
250
- }
257
+ for (const tok of extractClassStrings(code)) {
258
+ tokens.add(tok);
259
+ if (!tokenCSS.has(tok)) {
260
+ tokenCSS.set(tok, generateClassCSS(tok, cfg.theme, cfg.darkMode, screens));
251
261
  }
252
262
  }
253
263
  fileTokens.set(key, tokens);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kbach/react",
3
- "version": "0.5.46",
3
+ "version": "0.5.48",
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",