@kbach/react 0.5.42 → 0.5.44

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.
@@ -2351,6 +2351,10 @@ function parseClass(className) {
2351
2351
  const value = remaining.slice(bracketStart + 2, -1).replace(/_/g, " ");
2352
2352
  return { original: trimmed, modifiers, negative, important, utility, value, isArbitrary: true };
2353
2353
  }
2354
+ if (remaining.startsWith("[") && remaining.endsWith("]")) {
2355
+ const value = remaining.slice(1, -1).replace(/_/g, " ");
2356
+ return { original: trimmed, modifiers, negative, important, utility: "", value, isArbitrary: true };
2357
+ }
2354
2358
  if (getBuiltinStandaloneNames().has(remaining)) {
2355
2359
  return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
2356
2360
  }
@@ -2545,6 +2549,13 @@ function getDefaultFontFamily() {
2545
2549
  }
2546
2550
  var _styleEl = null;
2547
2551
  var _injectedRules = new LRUCache(5e4);
2552
+ var _CSS_DISABLED_KEY = "__kbach_runtime_css_disabled__";
2553
+ function disableRuntimeCSS() {
2554
+ globalThis[_CSS_DISABLED_KEY] = true;
2555
+ }
2556
+ function isRuntimeCSSDisabled() {
2557
+ return !!globalThis[_CSS_DISABLED_KEY];
2558
+ }
2548
2559
  function getStyleEl() {
2549
2560
  if (_styleEl) return _styleEl;
2550
2561
  _styleEl = document.createElement("style");
@@ -2553,6 +2564,7 @@ function getStyleEl() {
2553
2564
  return _styleEl;
2554
2565
  }
2555
2566
  function injectRule(rule) {
2567
+ if (isRuntimeCSSDisabled()) return;
2556
2568
  if (_injectedRules.has(rule)) return;
2557
2569
  _injectedRules.set(rule, true);
2558
2570
  try {
@@ -2569,7 +2581,7 @@ function getGlobalStyleEl() {
2569
2581
  return _globalStyleEl;
2570
2582
  }
2571
2583
  function injectGlobalStyles(theme) {
2572
- if (typeof document === "undefined") return;
2584
+ if (typeof document === "undefined" || isRuntimeCSSDisabled()) return;
2573
2585
  const rules = [];
2574
2586
  const ff = theme.fontFamily;
2575
2587
  if (ff.sans && ff.sans !== "System") {
@@ -2916,7 +2928,7 @@ function buildConfig(userConfig) {
2916
2928
  for (const plugin of resolved.plugins) {
2917
2929
  plugin(pluginAPI);
2918
2930
  }
2919
- const rawSans = theme.fontFamily.sans;
2931
+ const rawSans = theme.fontFamily?.sans;
2920
2932
  const sansFontValue = Array.isArray(rawSans) ? rawSans[0] : rawSans;
2921
2933
  setDefaultFontFamily(sansFontValue && sansFontValue !== "System" ? sansFontValue : void 0);
2922
2934
  injectGlobalStyles(resolved.theme);
@@ -2940,7 +2952,8 @@ function makePluginAPI(theme) {
2940
2952
  },
2941
2953
  addVariant(name, selectorOrDef) {
2942
2954
  const def = typeof selectorOrDef === "string" ? _selectorToModifierDef(selectorOrDef) : selectorOrDef;
2943
- customVariants[name] = typeof selectorOrDef === "string" ? selectorOrDef : name;
2955
+ const selector = typeof selectorOrDef === "string" ? selectorOrDef : selectorOrDef.pseudo ?? selectorOrDef.mediaQuery ?? selectorOrDef.ancestorSelector ?? name;
2956
+ customVariants[name] = selector;
2944
2957
  registerModifier(name, def);
2945
2958
  },
2946
2959
  theme(path, defaultValue) {
@@ -3017,6 +3030,8 @@ export {
3017
3030
  subscribeGlobalWidth,
3018
3031
  getActiveBreakpoints,
3019
3032
  getDefaultFontFamily,
3033
+ disableRuntimeCSS,
3034
+ isRuntimeCSSDisabled,
3020
3035
  generateClassCSS,
3021
3036
  resolve,
3022
3037
  flatten,
@@ -6,7 +6,7 @@ import {
6
6
  isNative,
7
7
  isWeb,
8
8
  subscribeGlobalWidth
9
- } from "./chunk-VCNP57PR.mjs";
9
+ } from "./chunk-52N32L7A.mjs";
10
10
 
11
11
  // src/core/darkModeStore.ts
12
12
  var KEY = "__kbach_dark_store__";
@@ -198,7 +198,8 @@ var InteractiveWrapper = forwardRef(
198
198
  [resolvedStyle, isDark, pressed, hovered, focused, width]
199
199
  // eslint-disable-line react-hooks/exhaustive-deps
200
200
  );
201
- const finalStyle = styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
201
+ const isWebHTMLElement = !isNative && typeof Component === "string";
202
+ const finalStyle = isWebHTMLElement ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
202
203
  const { children, ...restWithoutChildren } = rest;
203
204
  const componentProps = {
204
205
  ref,
@@ -4,7 +4,7 @@ import {
4
4
  hasResponsiveBuckets,
5
5
  useConditionalWidth,
6
6
  useGlobalDarkMode
7
- } from "./chunk-GOQNOKFN.mjs";
7
+ } from "./chunk-BBI6IU22.mjs";
8
8
  import {
9
9
  flatten,
10
10
  getActiveBreakpoints,
@@ -14,9 +14,10 @@ import {
14
14
  getModeModifiers,
15
15
  getResponsiveModifiers,
16
16
  isNative,
17
+ isRuntimeCSSDisabled,
17
18
  normalizeClassString,
18
19
  resolve
19
- } from "./chunk-VCNP57PR.mjs";
20
+ } from "./chunk-52N32L7A.mjs";
20
21
 
21
22
  // src/jsx-runtime.tsx
22
23
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -33,7 +34,8 @@ var DarkWrapper = React.forwardRef(
33
34
  const computedStyle = flatten(resolvedStyle, isDark, {}, breakpoints);
34
35
  stripInternalMarkers(computedStyle);
35
36
  if (typeof Component !== "string") stripWebOnlyProps(computedStyle);
36
- const finalStyle = styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
37
+ const isWebHTMLElement = !isNative && typeof Component === "string";
38
+ const finalStyle = isWebHTMLElement ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
37
39
  const props = { ref, ...rest, style: finalStyle };
38
40
  return Array.isArray(children) ? React.createElement(Component, props, ...children) : React.createElement(Component, props, children);
39
41
  }
@@ -121,27 +123,6 @@ function mergeStyle(computed, userStyle) {
121
123
  function makeElement(isStaticChildren, type, props, key) {
122
124
  return (isStaticChildren ? _jsxs : _jsx)(type, props, key);
123
125
  }
124
- function hasGridStyles(resolved) {
125
- for (const styles of Object.values(resolved)) {
126
- if (!styles) continue;
127
- if (styles.display === "grid" || styles.display === "inline-grid") return true;
128
- if ("gridTemplateColumns" in styles || "gridTemplateRows" in styles) return true;
129
- if ("gridColumn" in styles || "gridRow" in styles) return true;
130
- if ("gridColumnStart" in styles || "gridColumnEnd" in styles) return true;
131
- if ("gridRowStart" in styles || "gridRowEnd" in styles) return true;
132
- if ("gridAutoFlow" in styles || "gridAutoColumns" in styles || "gridAutoRows" in styles) return true;
133
- if ("placeItems" in styles || "placeContent" in styles || "justifyItems" in styles) return true;
134
- if ("placeSelf" in styles || "justifySelf" in styles) return true;
135
- }
136
- return false;
137
- }
138
- function hasWebPositionStyles(resolved) {
139
- for (const styles of Object.values(resolved)) {
140
- if (!styles) continue;
141
- if (styles.position === "sticky" || styles.position === "fixed" || styles.position === "static") return true;
142
- }
143
- return false;
144
- }
145
126
  function stripInternalMarkers2(s) {
146
127
  delete s.__divideX;
147
128
  delete s.__divideY;
@@ -177,6 +158,14 @@ function processElement(type, rawProps, key, isStaticChildren) {
177
158
  if (!rawProps) return _jsx(type, null, key);
178
159
  const { className, kb: kbProp, __kbachStyles, __kbachClasses } = rawProps;
179
160
  const classStr = className ?? kbProp ?? __kbachClasses;
161
+ if (!isNative && isRuntimeCSSDisabled() && classStr && !__kbachStyles) {
162
+ const { style: userStyle2, ...passProps2 } = omitConsumed(rawProps);
163
+ return makeElement(isStaticChildren, type, {
164
+ ...passProps2,
165
+ className: normalizeClassString(classStr),
166
+ ...userStyle2 !== void 0 ? { style: userStyle2 } : {}
167
+ }, key);
168
+ }
180
169
  if (!classStr && !__kbachStyles) {
181
170
  const defaultFont = getCachedDefaultFont();
182
171
  if (!defaultFont) return makeElement(isStaticChildren, type, rawProps, key);
@@ -188,12 +177,9 @@ function processElement(type, rawProps, key, isStaticChildren) {
188
177
  const resolved = __kbachStyles ?? (classStr ? resolve(classStr, config.theme, config.darkMode) : {});
189
178
  const { style: userStyle, ...passProps } = omitConsumed(rawProps);
190
179
  const { interactive, modeOrResponsive } = bucketMods(resolved);
191
- const onWeb = typeof document !== "undefined";
192
- const needsDiv = onWeb && (hasGridStyles(resolved) || hasWebPositionStyles(resolved));
193
- const actualType = needsDiv ? "div" : type;
194
180
  if (interactive) {
195
181
  return _jsx(InteractiveWrapper, {
196
- Component: actualType,
182
+ Component: type,
197
183
  resolvedStyle: resolved,
198
184
  ...!isNative && classStr ? { className: normalizeClassString(classStr) } : {},
199
185
  style: userStyle,
@@ -202,18 +188,24 @@ function processElement(type, rawProps, key, isStaticChildren) {
202
188
  }
203
189
  if (modeOrResponsive) {
204
190
  return _jsx(DarkWrapper, {
205
- Component: actualType,
191
+ Component: type,
206
192
  resolvedStyle: resolved,
207
193
  ...!isNative && classStr ? { className: normalizeClassString(classStr) } : {},
208
194
  style: userStyle,
209
195
  ...passProps
210
196
  }, key);
211
197
  }
212
- const computedStyle = flatten(resolved, false);
213
- stripInternalMarkers2(computedStyle);
214
- if (typeof actualType !== "string") stripWebOnlyInlineProps(computedStyle);
215
- const finalStyle = mergeStyle(computedStyle, userStyle);
216
- return makeElement(isStaticChildren, actualType, {
198
+ const isWebHTMLElement = !isNative && typeof type === "string";
199
+ let finalStyle;
200
+ if (!isWebHTMLElement) {
201
+ const computedStyle = flatten(resolved, false);
202
+ stripInternalMarkers2(computedStyle);
203
+ if (typeof type !== "string") stripWebOnlyInlineProps(computedStyle);
204
+ finalStyle = mergeStyle(computedStyle, userStyle);
205
+ } else {
206
+ finalStyle = userStyle ?? void 0;
207
+ }
208
+ return makeElement(isStaticChildren, type, {
217
209
  ...passProps,
218
210
  style: finalStyle,
219
211
  ...!isNative && classStr ? { className: normalizeClassString(classStr) } : {}
package/dist/index.d.mts CHANGED
@@ -21,6 +21,7 @@ declare function normalizeClassString(classString: string): string;
21
21
  /** Parse a space-separated class string into individual ParsedClass objects. */
22
22
  declare function parseClasses(classString: string): ParsedClass[];
23
23
 
24
+ declare function disableRuntimeCSS(): void;
24
25
  /**
25
26
  * Resolve a class string to a ResolvedStyle object.
26
27
  *
@@ -304,4 +305,4 @@ declare function kb(classString: string, isDark?: boolean): StyleValue | string;
304
305
  */
305
306
  declare function cx(...classes: Array<string | false | null | undefined>): string;
306
307
 
307
- export { type ColorScale, type ColorsAPI, FrameworkConfig, type InteractionState, InteractiveWrapper, type InteractiveWrapperProps, ParsedClass, ResolvedConfig, ResolvedStyle, StyleValue, type StyledProps, ThemeConfig, ThemeContext, type ThemeContextValue, ThemeMode, ThemeProvider, type ThemeProviderProps, ThemeToggle, type ThemeToggleProps, type ToggleVariant, buildConfig, cx, defaultColors, defaultTheme, flatten, getConfig, initConfig, kb, normalizeClassString, parseClass, parseClasses, resolve, splitClassTokens, styled, updateConfig, useBreakpoint, useColors, useGlobalDarkMode, useIsDark, useResolvedStyle, useResponsive, useStyles, useTheme, wrapColors };
308
+ export { type ColorScale, type ColorsAPI, FrameworkConfig, type InteractionState, InteractiveWrapper, type InteractiveWrapperProps, ParsedClass, ResolvedConfig, ResolvedStyle, StyleValue, type StyledProps, ThemeConfig, ThemeContext, type ThemeContextValue, ThemeMode, ThemeProvider, type ThemeProviderProps, ThemeToggle, type ThemeToggleProps, type ToggleVariant, buildConfig, cx, defaultColors, defaultTheme, disableRuntimeCSS, flatten, getConfig, initConfig, kb, normalizeClassString, parseClass, parseClasses, resolve, splitClassTokens, styled, updateConfig, useBreakpoint, useColors, useGlobalDarkMode, useIsDark, useResolvedStyle, useResponsive, useStyles, useTheme, wrapColors };
package/dist/index.d.ts CHANGED
@@ -21,6 +21,7 @@ declare function normalizeClassString(classString: string): string;
21
21
  /** Parse a space-separated class string into individual ParsedClass objects. */
22
22
  declare function parseClasses(classString: string): ParsedClass[];
23
23
 
24
+ declare function disableRuntimeCSS(): void;
24
25
  /**
25
26
  * Resolve a class string to a ResolvedStyle object.
26
27
  *
@@ -304,4 +305,4 @@ declare function kb(classString: string, isDark?: boolean): StyleValue | string;
304
305
  */
305
306
  declare function cx(...classes: Array<string | false | null | undefined>): string;
306
307
 
307
- export { type ColorScale, type ColorsAPI, FrameworkConfig, type InteractionState, InteractiveWrapper, type InteractiveWrapperProps, ParsedClass, ResolvedConfig, ResolvedStyle, StyleValue, type StyledProps, ThemeConfig, ThemeContext, type ThemeContextValue, ThemeMode, ThemeProvider, type ThemeProviderProps, ThemeToggle, type ThemeToggleProps, type ToggleVariant, buildConfig, cx, defaultColors, defaultTheme, flatten, getConfig, initConfig, kb, normalizeClassString, parseClass, parseClasses, resolve, splitClassTokens, styled, updateConfig, useBreakpoint, useColors, useGlobalDarkMode, useIsDark, useResolvedStyle, useResponsive, useStyles, useTheme, wrapColors };
308
+ export { type ColorScale, type ColorsAPI, FrameworkConfig, type InteractionState, InteractiveWrapper, type InteractiveWrapperProps, ParsedClass, ResolvedConfig, ResolvedStyle, StyleValue, type StyledProps, ThemeConfig, ThemeContext, type ThemeContextValue, ThemeMode, ThemeProvider, type ThemeProviderProps, ThemeToggle, type ThemeToggleProps, type ToggleVariant, buildConfig, cx, defaultColors, defaultTheme, disableRuntimeCSS, flatten, getConfig, initConfig, kb, normalizeClassString, parseClass, parseClasses, resolve, splitClassTokens, styled, updateConfig, useBreakpoint, useColors, useGlobalDarkMode, useIsDark, useResolvedStyle, useResponsive, useStyles, useTheme, wrapColors };
package/dist/index.js CHANGED
@@ -38,6 +38,7 @@ __export(index_exports, {
38
38
  cx: () => cx,
39
39
  defaultColors: () => defaultColors,
40
40
  defaultTheme: () => defaultTheme,
41
+ disableRuntimeCSS: () => disableRuntimeCSS,
41
42
  flatten: () => flatten,
42
43
  getConfig: () => getConfig,
43
44
  initConfig: () => initConfig,
@@ -2521,6 +2522,10 @@ function parseClass(className) {
2521
2522
  const value = remaining.slice(bracketStart + 2, -1).replace(/_/g, " ");
2522
2523
  return { original: trimmed, modifiers, negative, important, utility, value, isArbitrary: true };
2523
2524
  }
2525
+ if (remaining.startsWith("[") && remaining.endsWith("]")) {
2526
+ const value = remaining.slice(1, -1).replace(/_/g, " ");
2527
+ return { original: trimmed, modifiers, negative, important, utility: "", value, isArbitrary: true };
2528
+ }
2524
2529
  if (getBuiltinStandaloneNames().has(remaining)) {
2525
2530
  return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
2526
2531
  }
@@ -2675,6 +2680,13 @@ function getDefaultFontFamily() {
2675
2680
  }
2676
2681
  var _styleEl = null;
2677
2682
  var _injectedRules = new LRUCache(5e4);
2683
+ var _CSS_DISABLED_KEY = "__kbach_runtime_css_disabled__";
2684
+ function disableRuntimeCSS() {
2685
+ globalThis[_CSS_DISABLED_KEY] = true;
2686
+ }
2687
+ function isRuntimeCSSDisabled() {
2688
+ return !!globalThis[_CSS_DISABLED_KEY];
2689
+ }
2678
2690
  function getStyleEl() {
2679
2691
  if (_styleEl) return _styleEl;
2680
2692
  _styleEl = document.createElement("style");
@@ -2683,6 +2695,7 @@ function getStyleEl() {
2683
2695
  return _styleEl;
2684
2696
  }
2685
2697
  function injectRule(rule) {
2698
+ if (isRuntimeCSSDisabled()) return;
2686
2699
  if (_injectedRules.has(rule)) return;
2687
2700
  _injectedRules.set(rule, true);
2688
2701
  try {
@@ -2699,7 +2712,7 @@ function getGlobalStyleEl() {
2699
2712
  return _globalStyleEl;
2700
2713
  }
2701
2714
  function injectGlobalStyles(theme) {
2702
- if (typeof document === "undefined") return;
2715
+ if (typeof document === "undefined" || isRuntimeCSSDisabled()) return;
2703
2716
  const rules = [];
2704
2717
  const ff = theme.fontFamily;
2705
2718
  if (ff.sans && ff.sans !== "System") {
@@ -3036,7 +3049,7 @@ function buildConfig(userConfig) {
3036
3049
  for (const plugin of resolved.plugins) {
3037
3050
  plugin(pluginAPI);
3038
3051
  }
3039
- const rawSans = theme.fontFamily.sans;
3052
+ const rawSans = theme.fontFamily?.sans;
3040
3053
  const sansFontValue = Array.isArray(rawSans) ? rawSans[0] : rawSans;
3041
3054
  setDefaultFontFamily(sansFontValue && sansFontValue !== "System" ? sansFontValue : void 0);
3042
3055
  injectGlobalStyles(resolved.theme);
@@ -3060,7 +3073,8 @@ function makePluginAPI(theme) {
3060
3073
  },
3061
3074
  addVariant(name, selectorOrDef) {
3062
3075
  const def = typeof selectorOrDef === "string" ? _selectorToModifierDef(selectorOrDef) : selectorOrDef;
3063
- customVariants[name] = typeof selectorOrDef === "string" ? selectorOrDef : name;
3076
+ const selector = typeof selectorOrDef === "string" ? selectorOrDef : selectorOrDef.pseudo ?? selectorOrDef.mediaQuery ?? selectorOrDef.ancestorSelector ?? name;
3077
+ customVariants[name] = selector;
3064
3078
  registerModifier(name, def);
3065
3079
  },
3066
3080
  theme(path, defaultValue) {
@@ -3713,7 +3727,8 @@ var InteractiveWrapper = (0, import_react10.forwardRef)(
3713
3727
  [resolvedStyle, isDark, pressed, hovered, focused, width]
3714
3728
  // eslint-disable-line react-hooks/exhaustive-deps
3715
3729
  );
3716
- const finalStyle = styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
3730
+ const isWebHTMLElement = !isNative && typeof Component === "string";
3731
+ const finalStyle = isWebHTMLElement ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
3717
3732
  const { children, ...restWithoutChildren } = rest;
3718
3733
  const componentProps = {
3719
3734
  ref,
@@ -3755,6 +3770,7 @@ function cx(...classes) {
3755
3770
  cx,
3756
3771
  defaultColors,
3757
3772
  defaultTheme,
3773
+ disableRuntimeCSS,
3758
3774
  flatten,
3759
3775
  getConfig,
3760
3776
  initConfig,
package/dist/index.mjs CHANGED
@@ -7,12 +7,13 @@ import {
7
7
  useConditionalWidth,
8
8
  useGlobalDarkMode,
9
9
  useGlobalWidth
10
- } from "./chunk-GOQNOKFN.mjs";
10
+ } from "./chunk-BBI6IU22.mjs";
11
11
  import {
12
12
  __require,
13
13
  buildConfig,
14
14
  defaultColors,
15
15
  defaultTheme,
16
+ disableRuntimeCSS,
16
17
  flatten,
17
18
  getActiveBreakpoints,
18
19
  getConfig,
@@ -28,7 +29,7 @@ import {
28
29
  syncGlobalScreens,
29
30
  syncGlobalWidth,
30
31
  updateConfig
31
- } from "./chunk-VCNP57PR.mjs";
32
+ } from "./chunk-52N32L7A.mjs";
32
33
 
33
34
  // src/context.tsx
34
35
  import { createContext, useContext } from "react";
@@ -557,6 +558,7 @@ export {
557
558
  cx,
558
559
  defaultColors,
559
560
  defaultTheme,
561
+ disableRuntimeCSS,
560
562
  flatten,
561
563
  getConfig,
562
564
  initConfig,
@@ -2422,6 +2422,10 @@ function parseClass(className) {
2422
2422
  const value = remaining.slice(bracketStart + 2, -1).replace(/_/g, " ");
2423
2423
  return { original: trimmed, modifiers, negative, important, utility, value, isArbitrary: true };
2424
2424
  }
2425
+ if (remaining.startsWith("[") && remaining.endsWith("]")) {
2426
+ const value = remaining.slice(1, -1).replace(/_/g, " ");
2427
+ return { original: trimmed, modifiers, negative, important, utility: "", value, isArbitrary: true };
2428
+ }
2425
2429
  if (getBuiltinStandaloneNames().has(remaining)) {
2426
2430
  return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
2427
2431
  }
@@ -2564,6 +2568,10 @@ function getDefaultFontFamily() {
2564
2568
  }
2565
2569
  var _styleEl = null;
2566
2570
  var _injectedRules = new LRUCache(5e4);
2571
+ var _CSS_DISABLED_KEY = "__kbach_runtime_css_disabled__";
2572
+ function isRuntimeCSSDisabled() {
2573
+ return !!globalThis[_CSS_DISABLED_KEY];
2574
+ }
2567
2575
  function getStyleEl() {
2568
2576
  if (_styleEl) return _styleEl;
2569
2577
  _styleEl = document.createElement("style");
@@ -2572,6 +2580,7 @@ function getStyleEl() {
2572
2580
  return _styleEl;
2573
2581
  }
2574
2582
  function injectRule(rule) {
2583
+ if (isRuntimeCSSDisabled()) return;
2575
2584
  if (_injectedRules.has(rule)) return;
2576
2585
  _injectedRules.set(rule, true);
2577
2586
  try {
@@ -2588,7 +2597,7 @@ function getGlobalStyleEl() {
2588
2597
  return _globalStyleEl;
2589
2598
  }
2590
2599
  function injectGlobalStyles(theme) {
2591
- if (typeof document === "undefined") return;
2600
+ if (typeof document === "undefined" || isRuntimeCSSDisabled()) return;
2592
2601
  const rules = [];
2593
2602
  const ff = theme.fontFamily;
2594
2603
  if (ff.sans && ff.sans !== "System") {
@@ -2918,7 +2927,7 @@ function buildConfig(userConfig) {
2918
2927
  for (const plugin of resolved.plugins) {
2919
2928
  plugin(pluginAPI);
2920
2929
  }
2921
- const rawSans = theme.fontFamily.sans;
2930
+ const rawSans = theme.fontFamily?.sans;
2922
2931
  const sansFontValue = Array.isArray(rawSans) ? rawSans[0] : rawSans;
2923
2932
  setDefaultFontFamily(sansFontValue && sansFontValue !== "System" ? sansFontValue : void 0);
2924
2933
  injectGlobalStyles(resolved.theme);
@@ -2942,7 +2951,8 @@ function makePluginAPI(theme) {
2942
2951
  },
2943
2952
  addVariant(name, selectorOrDef) {
2944
2953
  const def = typeof selectorOrDef === "string" ? _selectorToModifierDef(selectorOrDef) : selectorOrDef;
2945
- customVariants[name] = typeof selectorOrDef === "string" ? selectorOrDef : name;
2954
+ const selector = typeof selectorOrDef === "string" ? selectorOrDef : selectorOrDef.pseudo ?? selectorOrDef.mediaQuery ?? selectorOrDef.ancestorSelector ?? name;
2955
+ customVariants[name] = selector;
2946
2956
  registerModifier(name, def);
2947
2957
  },
2948
2958
  theme(path, defaultValue) {
@@ -3153,7 +3163,8 @@ var InteractiveWrapper = (0, import_react3.forwardRef)(
3153
3163
  [resolvedStyle, isDark, pressed, hovered, focused, width]
3154
3164
  // eslint-disable-line react-hooks/exhaustive-deps
3155
3165
  );
3156
- const finalStyle = styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
3166
+ const isWebHTMLElement = !isNative && typeof Component === "string";
3167
+ const finalStyle = isWebHTMLElement ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
3157
3168
  const { children, ...restWithoutChildren } = rest;
3158
3169
  const componentProps = {
3159
3170
  ref,
@@ -3184,7 +3195,8 @@ var DarkWrapper = import_react4.default.forwardRef(
3184
3195
  const computedStyle = flatten(resolvedStyle, isDark, {}, breakpoints);
3185
3196
  stripInternalMarkers(computedStyle);
3186
3197
  if (typeof Component !== "string") stripWebOnlyProps(computedStyle);
3187
- const finalStyle = styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
3198
+ const isWebHTMLElement = !isNative && typeof Component === "string";
3199
+ const finalStyle = isWebHTMLElement ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
3188
3200
  const props = { ref, ...rest, style: finalStyle };
3189
3201
  return Array.isArray(children) ? import_react4.default.createElement(Component, props, ...children) : import_react4.default.createElement(Component, props, children);
3190
3202
  }
@@ -3269,27 +3281,6 @@ function mergeStyle(computed, userStyle) {
3269
3281
  function makeElement(isStaticChildren, type, props, key) {
3270
3282
  return (isStaticChildren ? import_jsx_runtime.jsxs : import_jsx_runtime.jsx)(type, props, key);
3271
3283
  }
3272
- function hasGridStyles(resolved) {
3273
- for (const styles of Object.values(resolved)) {
3274
- if (!styles) continue;
3275
- if (styles.display === "grid" || styles.display === "inline-grid") return true;
3276
- if ("gridTemplateColumns" in styles || "gridTemplateRows" in styles) return true;
3277
- if ("gridColumn" in styles || "gridRow" in styles) return true;
3278
- if ("gridColumnStart" in styles || "gridColumnEnd" in styles) return true;
3279
- if ("gridRowStart" in styles || "gridRowEnd" in styles) return true;
3280
- if ("gridAutoFlow" in styles || "gridAutoColumns" in styles || "gridAutoRows" in styles) return true;
3281
- if ("placeItems" in styles || "placeContent" in styles || "justifyItems" in styles) return true;
3282
- if ("placeSelf" in styles || "justifySelf" in styles) return true;
3283
- }
3284
- return false;
3285
- }
3286
- function hasWebPositionStyles(resolved) {
3287
- for (const styles of Object.values(resolved)) {
3288
- if (!styles) continue;
3289
- if (styles.position === "sticky" || styles.position === "fixed" || styles.position === "static") return true;
3290
- }
3291
- return false;
3292
- }
3293
3284
  function stripInternalMarkers2(s) {
3294
3285
  delete s.__divideX;
3295
3286
  delete s.__divideY;
@@ -3325,6 +3316,14 @@ function processElement(type, rawProps, key, isStaticChildren) {
3325
3316
  if (!rawProps) return (0, import_jsx_runtime.jsx)(type, null, key);
3326
3317
  const { className, kb: kbProp, __kbachStyles, __kbachClasses } = rawProps;
3327
3318
  const classStr = className ?? kbProp ?? __kbachClasses;
3319
+ if (!isNative && isRuntimeCSSDisabled() && classStr && !__kbachStyles) {
3320
+ const { style: userStyle2, ...passProps2 } = omitConsumed(rawProps);
3321
+ return makeElement(isStaticChildren, type, {
3322
+ ...passProps2,
3323
+ className: normalizeClassString(classStr),
3324
+ ...userStyle2 !== void 0 ? { style: userStyle2 } : {}
3325
+ }, key);
3326
+ }
3328
3327
  if (!classStr && !__kbachStyles) {
3329
3328
  const defaultFont = getCachedDefaultFont();
3330
3329
  if (!defaultFont) return makeElement(isStaticChildren, type, rawProps, key);
@@ -3336,12 +3335,9 @@ function processElement(type, rawProps, key, isStaticChildren) {
3336
3335
  const resolved = __kbachStyles ?? (classStr ? resolve(classStr, config.theme, config.darkMode) : {});
3337
3336
  const { style: userStyle, ...passProps } = omitConsumed(rawProps);
3338
3337
  const { interactive, modeOrResponsive } = bucketMods(resolved);
3339
- const onWeb = typeof document !== "undefined";
3340
- const needsDiv = onWeb && (hasGridStyles(resolved) || hasWebPositionStyles(resolved));
3341
- const actualType = needsDiv ? "div" : type;
3342
3338
  if (interactive) {
3343
3339
  return (0, import_jsx_runtime.jsx)(InteractiveWrapper, {
3344
- Component: actualType,
3340
+ Component: type,
3345
3341
  resolvedStyle: resolved,
3346
3342
  ...!isNative && classStr ? { className: normalizeClassString(classStr) } : {},
3347
3343
  style: userStyle,
@@ -3350,18 +3346,24 @@ function processElement(type, rawProps, key, isStaticChildren) {
3350
3346
  }
3351
3347
  if (modeOrResponsive) {
3352
3348
  return (0, import_jsx_runtime.jsx)(DarkWrapper, {
3353
- Component: actualType,
3349
+ Component: type,
3354
3350
  resolvedStyle: resolved,
3355
3351
  ...!isNative && classStr ? { className: normalizeClassString(classStr) } : {},
3356
3352
  style: userStyle,
3357
3353
  ...passProps
3358
3354
  }, key);
3359
3355
  }
3360
- const computedStyle = flatten(resolved, false);
3361
- stripInternalMarkers2(computedStyle);
3362
- if (typeof actualType !== "string") stripWebOnlyInlineProps(computedStyle);
3363
- const finalStyle = mergeStyle(computedStyle, userStyle);
3364
- return makeElement(isStaticChildren, actualType, {
3356
+ const isWebHTMLElement = !isNative && typeof type === "string";
3357
+ let finalStyle;
3358
+ if (!isWebHTMLElement) {
3359
+ const computedStyle = flatten(resolved, false);
3360
+ stripInternalMarkers2(computedStyle);
3361
+ if (typeof type !== "string") stripWebOnlyInlineProps(computedStyle);
3362
+ finalStyle = mergeStyle(computedStyle, userStyle);
3363
+ } else {
3364
+ finalStyle = userStyle ?? void 0;
3365
+ }
3366
+ return makeElement(isStaticChildren, type, {
3365
3367
  ...passProps,
3366
3368
  style: finalStyle,
3367
3369
  ...!isNative && classStr ? { className: normalizeClassString(classStr) } : {}
@@ -2,9 +2,9 @@ import {
2
2
  Fragment,
3
3
  jsx,
4
4
  jsxs
5
- } from "./chunk-AAPA3CRV.mjs";
6
- import "./chunk-GOQNOKFN.mjs";
7
- import "./chunk-VCNP57PR.mjs";
5
+ } from "./chunk-MIBPTKXT.mjs";
6
+ import "./chunk-BBI6IU22.mjs";
7
+ import "./chunk-52N32L7A.mjs";
8
8
 
9
9
  // src/jsx-dev-runtime.tsx
10
10
  function jsxDEV(type, props, key, isStaticChildren, source, self) {
@@ -2422,6 +2422,10 @@ function parseClass(className) {
2422
2422
  const value = remaining.slice(bracketStart + 2, -1).replace(/_/g, " ");
2423
2423
  return { original: trimmed, modifiers, negative, important, utility, value, isArbitrary: true };
2424
2424
  }
2425
+ if (remaining.startsWith("[") && remaining.endsWith("]")) {
2426
+ const value = remaining.slice(1, -1).replace(/_/g, " ");
2427
+ return { original: trimmed, modifiers, negative, important, utility: "", value, isArbitrary: true };
2428
+ }
2425
2429
  if (getBuiltinStandaloneNames().has(remaining)) {
2426
2430
  return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
2427
2431
  }
@@ -2564,6 +2568,10 @@ function getDefaultFontFamily() {
2564
2568
  }
2565
2569
  var _styleEl = null;
2566
2570
  var _injectedRules = new LRUCache(5e4);
2571
+ var _CSS_DISABLED_KEY = "__kbach_runtime_css_disabled__";
2572
+ function isRuntimeCSSDisabled() {
2573
+ return !!globalThis[_CSS_DISABLED_KEY];
2574
+ }
2567
2575
  function getStyleEl() {
2568
2576
  if (_styleEl) return _styleEl;
2569
2577
  _styleEl = document.createElement("style");
@@ -2572,6 +2580,7 @@ function getStyleEl() {
2572
2580
  return _styleEl;
2573
2581
  }
2574
2582
  function injectRule(rule) {
2583
+ if (isRuntimeCSSDisabled()) return;
2575
2584
  if (_injectedRules.has(rule)) return;
2576
2585
  _injectedRules.set(rule, true);
2577
2586
  try {
@@ -2588,7 +2597,7 @@ function getGlobalStyleEl() {
2588
2597
  return _globalStyleEl;
2589
2598
  }
2590
2599
  function injectGlobalStyles(theme) {
2591
- if (typeof document === "undefined") return;
2600
+ if (typeof document === "undefined" || isRuntimeCSSDisabled()) return;
2592
2601
  const rules = [];
2593
2602
  const ff = theme.fontFamily;
2594
2603
  if (ff.sans && ff.sans !== "System") {
@@ -2918,7 +2927,7 @@ function buildConfig(userConfig) {
2918
2927
  for (const plugin of resolved.plugins) {
2919
2928
  plugin(pluginAPI);
2920
2929
  }
2921
- const rawSans = theme.fontFamily.sans;
2930
+ const rawSans = theme.fontFamily?.sans;
2922
2931
  const sansFontValue = Array.isArray(rawSans) ? rawSans[0] : rawSans;
2923
2932
  setDefaultFontFamily(sansFontValue && sansFontValue !== "System" ? sansFontValue : void 0);
2924
2933
  injectGlobalStyles(resolved.theme);
@@ -2942,7 +2951,8 @@ function makePluginAPI(theme) {
2942
2951
  },
2943
2952
  addVariant(name, selectorOrDef) {
2944
2953
  const def = typeof selectorOrDef === "string" ? _selectorToModifierDef(selectorOrDef) : selectorOrDef;
2945
- customVariants[name] = typeof selectorOrDef === "string" ? selectorOrDef : name;
2954
+ const selector = typeof selectorOrDef === "string" ? selectorOrDef : selectorOrDef.pseudo ?? selectorOrDef.mediaQuery ?? selectorOrDef.ancestorSelector ?? name;
2955
+ customVariants[name] = selector;
2946
2956
  registerModifier(name, def);
2947
2957
  },
2948
2958
  theme(path, defaultValue) {
@@ -3153,7 +3163,8 @@ var InteractiveWrapper = (0, import_react3.forwardRef)(
3153
3163
  [resolvedStyle, isDark, pressed, hovered, focused, width]
3154
3164
  // eslint-disable-line react-hooks/exhaustive-deps
3155
3165
  );
3156
- const finalStyle = styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
3166
+ const isWebHTMLElement = !isNative && typeof Component === "string";
3167
+ const finalStyle = isWebHTMLElement ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
3157
3168
  const { children, ...restWithoutChildren } = rest;
3158
3169
  const componentProps = {
3159
3170
  ref,
@@ -3184,7 +3195,8 @@ var DarkWrapper = import_react4.default.forwardRef(
3184
3195
  const computedStyle = flatten(resolvedStyle, isDark, {}, breakpoints);
3185
3196
  stripInternalMarkers(computedStyle);
3186
3197
  if (typeof Component !== "string") stripWebOnlyProps(computedStyle);
3187
- const finalStyle = styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
3198
+ const isWebHTMLElement = !isNative && typeof Component === "string";
3199
+ const finalStyle = isWebHTMLElement ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
3188
3200
  const props = { ref, ...rest, style: finalStyle };
3189
3201
  return Array.isArray(children) ? import_react4.default.createElement(Component, props, ...children) : import_react4.default.createElement(Component, props, children);
3190
3202
  }
@@ -3272,27 +3284,6 @@ function mergeStyle(computed, userStyle) {
3272
3284
  function makeElement(isStaticChildren, type, props, key) {
3273
3285
  return (isStaticChildren ? import_jsx_runtime.jsxs : import_jsx_runtime.jsx)(type, props, key);
3274
3286
  }
3275
- function hasGridStyles(resolved) {
3276
- for (const styles of Object.values(resolved)) {
3277
- if (!styles) continue;
3278
- if (styles.display === "grid" || styles.display === "inline-grid") return true;
3279
- if ("gridTemplateColumns" in styles || "gridTemplateRows" in styles) return true;
3280
- if ("gridColumn" in styles || "gridRow" in styles) return true;
3281
- if ("gridColumnStart" in styles || "gridColumnEnd" in styles) return true;
3282
- if ("gridRowStart" in styles || "gridRowEnd" in styles) return true;
3283
- if ("gridAutoFlow" in styles || "gridAutoColumns" in styles || "gridAutoRows" in styles) return true;
3284
- if ("placeItems" in styles || "placeContent" in styles || "justifyItems" in styles) return true;
3285
- if ("placeSelf" in styles || "justifySelf" in styles) return true;
3286
- }
3287
- return false;
3288
- }
3289
- function hasWebPositionStyles(resolved) {
3290
- for (const styles of Object.values(resolved)) {
3291
- if (!styles) continue;
3292
- if (styles.position === "sticky" || styles.position === "fixed" || styles.position === "static") return true;
3293
- }
3294
- return false;
3295
- }
3296
3287
  function stripInternalMarkers2(s) {
3297
3288
  delete s.__divideX;
3298
3289
  delete s.__divideY;
@@ -3328,6 +3319,14 @@ function processElement(type, rawProps, key, isStaticChildren) {
3328
3319
  if (!rawProps) return (0, import_jsx_runtime.jsx)(type, null, key);
3329
3320
  const { className, kb: kbProp, __kbachStyles, __kbachClasses } = rawProps;
3330
3321
  const classStr = className ?? kbProp ?? __kbachClasses;
3322
+ if (!isNative && isRuntimeCSSDisabled() && classStr && !__kbachStyles) {
3323
+ const { style: userStyle2, ...passProps2 } = omitConsumed(rawProps);
3324
+ return makeElement(isStaticChildren, type, {
3325
+ ...passProps2,
3326
+ className: normalizeClassString(classStr),
3327
+ ...userStyle2 !== void 0 ? { style: userStyle2 } : {}
3328
+ }, key);
3329
+ }
3331
3330
  if (!classStr && !__kbachStyles) {
3332
3331
  const defaultFont = getCachedDefaultFont();
3333
3332
  if (!defaultFont) return makeElement(isStaticChildren, type, rawProps, key);
@@ -3339,12 +3338,9 @@ function processElement(type, rawProps, key, isStaticChildren) {
3339
3338
  const resolved = __kbachStyles ?? (classStr ? resolve(classStr, config.theme, config.darkMode) : {});
3340
3339
  const { style: userStyle, ...passProps } = omitConsumed(rawProps);
3341
3340
  const { interactive, modeOrResponsive } = bucketMods(resolved);
3342
- const onWeb = typeof document !== "undefined";
3343
- const needsDiv = onWeb && (hasGridStyles(resolved) || hasWebPositionStyles(resolved));
3344
- const actualType = needsDiv ? "div" : type;
3345
3341
  if (interactive) {
3346
3342
  return (0, import_jsx_runtime.jsx)(InteractiveWrapper, {
3347
- Component: actualType,
3343
+ Component: type,
3348
3344
  resolvedStyle: resolved,
3349
3345
  ...!isNative && classStr ? { className: normalizeClassString(classStr) } : {},
3350
3346
  style: userStyle,
@@ -3353,18 +3349,24 @@ function processElement(type, rawProps, key, isStaticChildren) {
3353
3349
  }
3354
3350
  if (modeOrResponsive) {
3355
3351
  return (0, import_jsx_runtime.jsx)(DarkWrapper, {
3356
- Component: actualType,
3352
+ Component: type,
3357
3353
  resolvedStyle: resolved,
3358
3354
  ...!isNative && classStr ? { className: normalizeClassString(classStr) } : {},
3359
3355
  style: userStyle,
3360
3356
  ...passProps
3361
3357
  }, key);
3362
3358
  }
3363
- const computedStyle = flatten(resolved, false);
3364
- stripInternalMarkers2(computedStyle);
3365
- if (typeof actualType !== "string") stripWebOnlyInlineProps(computedStyle);
3366
- const finalStyle = mergeStyle(computedStyle, userStyle);
3367
- return makeElement(isStaticChildren, actualType, {
3359
+ const isWebHTMLElement = !isNative && typeof type === "string";
3360
+ let finalStyle;
3361
+ if (!isWebHTMLElement) {
3362
+ const computedStyle = flatten(resolved, false);
3363
+ stripInternalMarkers2(computedStyle);
3364
+ if (typeof type !== "string") stripWebOnlyInlineProps(computedStyle);
3365
+ finalStyle = mergeStyle(computedStyle, userStyle);
3366
+ } else {
3367
+ finalStyle = userStyle ?? void 0;
3368
+ }
3369
+ return makeElement(isStaticChildren, type, {
3368
3370
  ...passProps,
3369
3371
  style: finalStyle,
3370
3372
  ...!isNative && classStr ? { className: normalizeClassString(classStr) } : {}
@@ -3,9 +3,9 @@ import {
3
3
  _invalidateDefaultFontCache,
4
4
  jsx,
5
5
  jsxs
6
- } from "./chunk-AAPA3CRV.mjs";
7
- import "./chunk-GOQNOKFN.mjs";
8
- import "./chunk-VCNP57PR.mjs";
6
+ } from "./chunk-MIBPTKXT.mjs";
7
+ import "./chunk-BBI6IU22.mjs";
8
+ import "./chunk-52N32L7A.mjs";
9
9
  export {
10
10
  Fragment,
11
11
  _invalidateDefaultFontCache,
@@ -2345,6 +2345,10 @@ function parseClass(className) {
2345
2345
  const value = remaining.slice(bracketStart + 2, -1).replace(/_/g, " ");
2346
2346
  return { original: trimmed, modifiers, negative, important, utility, value, isArbitrary: true };
2347
2347
  }
2348
+ if (remaining.startsWith("[") && remaining.endsWith("]")) {
2349
+ const value = remaining.slice(1, -1).replace(/_/g, " ");
2350
+ return { original: trimmed, modifiers, negative, important, utility: "", value, isArbitrary: true };
2351
+ }
2348
2352
  if (getBuiltinStandaloneNames().has(remaining)) {
2349
2353
  return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
2350
2354
  }
@@ -2467,6 +2471,10 @@ function setDefaultFontFamily(font) {
2467
2471
  }
2468
2472
  var _styleEl = null;
2469
2473
  var _injectedRules = new LRUCache(5e4);
2474
+ var _CSS_DISABLED_KEY = "__kbach_runtime_css_disabled__";
2475
+ function isRuntimeCSSDisabled() {
2476
+ return !!globalThis[_CSS_DISABLED_KEY];
2477
+ }
2470
2478
  function getStyleEl() {
2471
2479
  if (_styleEl) return _styleEl;
2472
2480
  _styleEl = document.createElement("style");
@@ -2483,7 +2491,7 @@ function getGlobalStyleEl() {
2483
2491
  return _globalStyleEl;
2484
2492
  }
2485
2493
  function injectGlobalStyles(theme) {
2486
- if (typeof document === "undefined") return;
2494
+ if (typeof document === "undefined" || isRuntimeCSSDisabled()) return;
2487
2495
  const rules = [];
2488
2496
  const ff = theme.fontFamily;
2489
2497
  if (ff.sans && ff.sans !== "System") {
@@ -2742,7 +2750,7 @@ function buildConfig(userConfig) {
2742
2750
  for (const plugin of resolved.plugins) {
2743
2751
  plugin(pluginAPI);
2744
2752
  }
2745
- const rawSans = theme.fontFamily.sans;
2753
+ const rawSans = theme.fontFamily?.sans;
2746
2754
  const sansFontValue = Array.isArray(rawSans) ? rawSans[0] : rawSans;
2747
2755
  setDefaultFontFamily(sansFontValue && sansFontValue !== "System" ? sansFontValue : void 0);
2748
2756
  injectGlobalStyles(resolved.theme);
@@ -2766,7 +2774,8 @@ function makePluginAPI(theme) {
2766
2774
  },
2767
2775
  addVariant(name, selectorOrDef) {
2768
2776
  const def = typeof selectorOrDef === "string" ? _selectorToModifierDef(selectorOrDef) : selectorOrDef;
2769
- customVariants[name] = typeof selectorOrDef === "string" ? selectorOrDef : name;
2777
+ const selector = typeof selectorOrDef === "string" ? selectorOrDef : selectorOrDef.pseudo ?? selectorOrDef.mediaQuery ?? selectorOrDef.ancestorSelector ?? name;
2778
+ customVariants[name] = selector;
2770
2779
  registerModifier(name, def);
2771
2780
  },
2772
2781
  theme(path, defaultValue) {
@@ -2822,9 +2831,9 @@ var GROUPS = [
2822
2831
  ["Effects", /^(shadow|opacity|blur|brightness|contrast|grayscale|transition|duration|ease|delay|animate|scale|rotate|translate|transform|cursor|pointer|select-)/]
2823
2832
  ];
2824
2833
  var GROUP_ORDER = ["Layout", "Sizing", "Spacing", "Typography", "Colors", "Borders", "Effects", "Utilities", "Dark Mode", "Responsive"];
2825
- function classifyToken(token) {
2834
+ function classifyToken(token, responsiveRe) {
2826
2835
  if (/^dark:/.test(token)) return "Dark Mode";
2827
- if (/^(sm|md|lg|xl|2xl):/.test(token)) return "Responsive";
2836
+ if (responsiveRe.test(token)) return "Responsive";
2828
2837
  const base = token.replace(/^(hover|focus|active|group-hover|peer-hover):/, "");
2829
2838
  for (const [label, re] of GROUPS) {
2830
2839
  if (re.test(base)) return label;
@@ -2849,7 +2858,7 @@ function buildColorVarMap(theme, usedCSS) {
2849
2858
  }
2850
2859
  return map;
2851
2860
  }
2852
- function formatKbachCSS(tokenCSS, theme) {
2861
+ function formatKbachCSS(tokenCSS, theme, responsiveRe) {
2853
2862
  const allRaw = [...tokenCSS.values()].filter(Boolean).join("\n");
2854
2863
  const colorVars = buildColorVarMap(theme, allRaw);
2855
2864
  function applyVars(css) {
@@ -2860,7 +2869,7 @@ function formatKbachCSS(tokenCSS, theme) {
2860
2869
  const groups = new Map(GROUP_ORDER.map((g) => [g, []]));
2861
2870
  for (const [token, css] of tokenCSS) {
2862
2871
  if (!css) continue;
2863
- const label = classifyToken(token);
2872
+ const label = classifyToken(token, responsiveRe);
2864
2873
  if (!groups.has(label)) groups.set(label, []);
2865
2874
  groups.get(label).push(applyVars(css));
2866
2875
  }
@@ -2889,16 +2898,50 @@ function buildThemeGlobal(theme) {
2889
2898
  const family = Array.isArray(ff.sans) ? ff.sans.join(", ") : ff.sans;
2890
2899
  return `body { font-family: ${family}; }`;
2891
2900
  }
2892
- function findMainCSSFile(root) {
2893
- for (const c of [
2894
- (0, import_path.join)(root, "app", "app.css"),
2895
- (0, import_path.join)(root, "src", "index.css"),
2896
- (0, import_path.join)(root, "src", "app.css"),
2897
- (0, import_path.join)(root, "app", "index.css")
2898
- ]) {
2899
- if ((0, import_fs.existsSync)(c)) return c;
2901
+ var SKIP_DIRS = /* @__PURE__ */ new Set([
2902
+ "node_modules",
2903
+ "dist",
2904
+ "build",
2905
+ "out",
2906
+ ".next",
2907
+ ".nuxt",
2908
+ ".output",
2909
+ ".git",
2910
+ ".svn",
2911
+ ".cache",
2912
+ "coverage",
2913
+ "__pycache__"
2914
+ ]);
2915
+ function findKbachCSS(root) {
2916
+ const found = [];
2917
+ function scan(dir, depth) {
2918
+ if (depth > 10) return;
2919
+ let entries;
2920
+ try {
2921
+ entries = (0, import_fs.readdirSync)(dir);
2922
+ } catch {
2923
+ return;
2924
+ }
2925
+ for (const entry of entries) {
2926
+ if (entry.startsWith(".") || SKIP_DIRS.has(entry)) continue;
2927
+ const full = (0, import_path.join)(dir, entry);
2928
+ try {
2929
+ const st = (0, import_fs.statSync)(full);
2930
+ if (st.isDirectory()) scan(full, depth + 1);
2931
+ else if (entry === "kbach.css") found.push(full);
2932
+ } catch {
2933
+ }
2934
+ }
2900
2935
  }
2901
- return null;
2936
+ scan(root, 0);
2937
+ if (found.length === 0) return null;
2938
+ found.sort((a, b) => a.split(/[\\/]/g).length - b.split(/[\\/]/g).length);
2939
+ if (found.length > 1) {
2940
+ console.warn(
2941
+ "[kbach] Multiple kbach.css files found \u2014 only the shallowest will receive generated styles.\n Remove duplicates to avoid confusion:\n" + found.map((f) => ` ${f}`).join("\n")
2942
+ );
2943
+ }
2944
+ return found[0];
2902
2945
  }
2903
2946
  function writeKbachToFile(filePath, css) {
2904
2947
  let existing = "";
@@ -2914,7 +2957,9 @@ ${KBACH_END}`;
2914
2957
  const next = start !== -1 && end !== -1 ? existing.slice(0, start) + block + existing.slice(end + KBACH_END.length) : existing ? `${existing}
2915
2958
 
2916
2959
  ${block}` : block;
2917
- if (next !== existing) (0, import_fs.writeFileSync)(filePath, next, "utf-8");
2960
+ if (next === existing) return false;
2961
+ (0, import_fs.writeFileSync)(filePath, next, "utf-8");
2962
+ return true;
2918
2963
  }
2919
2964
  function toNumericScreens(screens) {
2920
2965
  const out = {};
@@ -2928,11 +2973,21 @@ function extractClassStrings(code) {
2928
2973
  const simpleRe = /(?:className|kb)=["']([^"']+)["']/g;
2929
2974
  let m;
2930
2975
  while ((m = simpleRe.exec(code)) !== null) pushTokens(m[1], found);
2931
- const exprLiteralRe = /(?:className|kb)=\{["'`]([^"'`}]+)["'`]\}/g;
2932
- while ((m = exprLiteralRe.exec(code)) !== null) pushTokens(m[1], found);
2933
- const ternaryBlockRe = /(?:className|kb)=\{([^}]{1,500})\}/g;
2934
- while ((m = ternaryBlockRe.exec(code)) !== null) {
2935
- const block = m[1];
2976
+ const jsxExprRe = /(?:className|kb)=\{/g;
2977
+ while ((m = jsxExprRe.exec(code)) !== null) {
2978
+ let depth = 1;
2979
+ let i = m.index + m[0].length;
2980
+ let block = "";
2981
+ while (i < code.length && depth > 0) {
2982
+ const ch = code[i];
2983
+ if (ch === "{") depth++;
2984
+ else if (ch === "}") {
2985
+ if (--depth === 0) break;
2986
+ }
2987
+ block += ch;
2988
+ i++;
2989
+ }
2990
+ jsxExprRe.lastIndex = i + 1;
2936
2991
  const innerStrings = block.match(/["'`]([^"'`]{1,300})["'`]/g) ?? [];
2937
2992
  for (const s of innerStrings) pushTokens(s.slice(1, -1), found);
2938
2993
  }
@@ -2955,23 +3010,31 @@ function pushTokens(str, into) {
2955
3010
  }
2956
3011
  }
2957
3012
  function scanDir(dir, onFile) {
3013
+ let entries;
2958
3014
  try {
2959
- for (const entry of (0, import_fs.readdirSync)(dir)) {
2960
- if (entry.startsWith(".") || entry === "node_modules") continue;
2961
- const full = (0, import_path.join)(dir, entry);
2962
- try {
2963
- const st = (0, import_fs.statSync)(full);
2964
- if (st.isDirectory()) scanDir(full, onFile);
2965
- else if (/\.(tsx?|jsx?)$/.test(entry)) onFile(full, (0, import_fs.readFileSync)(full, "utf-8"));
2966
- } catch {
2967
- }
3015
+ entries = (0, import_fs.readdirSync)(dir);
3016
+ } catch (err) {
3017
+ console.warn(`[kbach] Cannot read directory ${dir}:`, err.message);
3018
+ return;
3019
+ }
3020
+ for (const entry of entries) {
3021
+ if (entry.startsWith(".") || entry === "node_modules") continue;
3022
+ const full = (0, import_path.join)(dir, entry);
3023
+ try {
3024
+ const st = (0, import_fs.statSync)(full);
3025
+ if (st.isDirectory()) scanDir(full, onFile);
3026
+ else if (/\.(tsx?|jsx?)$/.test(entry)) onFile(full, (0, import_fs.readFileSync)(full, "utf-8"));
3027
+ } catch (err) {
3028
+ console.warn(`[kbach] Cannot process ${full}:`, err.message);
2968
3029
  }
2969
- } catch {
2970
3030
  }
2971
3031
  }
2972
3032
  function kbach(userConfig) {
2973
3033
  const cfg = buildConfig(userConfig ?? {});
2974
3034
  const screens = toNumericScreens(cfg.theme.screens ?? {});
3035
+ const screenKeys = Object.keys(cfg.theme.screens ?? {});
3036
+ const responsivePattern = screenKeys.length ? screenKeys.map((k) => k.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|") : "sm|md|lg|xl|2xl";
3037
+ const responsiveRe = new RegExp(`^(${responsivePattern}):`);
2975
3038
  let root = process.cwd();
2976
3039
  let mainCSSFile = null;
2977
3040
  const fileTokens = /* @__PURE__ */ new Map();
@@ -3005,7 +3068,7 @@ function kbach(userConfig) {
3005
3068
  }
3006
3069
  }
3007
3070
  function generateCSS() {
3008
- return formatKbachCSS(buildTokenCSSView(), cfg.theme);
3071
+ return formatKbachCSS(buildTokenCSSView(), cfg.theme, responsiveRe);
3009
3072
  }
3010
3073
  return {
3011
3074
  name: "kbach",
@@ -3013,19 +3076,39 @@ function kbach(userConfig) {
3013
3076
  configResolved(resolved) {
3014
3077
  root = resolved.root;
3015
3078
  },
3079
+ // When any JS/TS file imports kbach.css, prepend a disableRuntimeCSS() call
3080
+ // so styles come solely from the static stylesheet — no duplicate injection.
3081
+ transform(code, id) {
3082
+ if (!/\.(tsx?|jsx?|mjs?)$/.test(id)) return;
3083
+ if (!/['"].*kbach\.css['"]/i.test(code)) return;
3084
+ return {
3085
+ code: `import { disableRuntimeCSS } from '@kbach/react';
3086
+ disableRuntimeCSS();
3087
+ ${code}`,
3088
+ map: null
3089
+ };
3090
+ },
3016
3091
  buildStart() {
3017
- mainCSSFile = findMainCSSFile(root);
3092
+ mainCSSFile = findKbachCSS(root);
3018
3093
  initialScan();
3019
3094
  if (mainCSSFile) writeKbachToFile(mainCSSFile, generateCSS());
3020
3095
  },
3021
- handleHotUpdate({ file }) {
3096
+ handleHotUpdate({ file, server }) {
3022
3097
  if (file.includes("node_modules") || !/\.(tsx?|jsx?)$/.test(file)) return;
3023
3098
  try {
3024
3099
  processFile(file, (0, import_fs.readFileSync)(file, "utf-8"));
3025
3100
  } catch {
3026
3101
  fileTokens.delete(normPath(file));
3027
3102
  }
3028
- if (mainCSSFile) writeKbachToFile(mainCSSFile, generateCSS());
3103
+ const active = /* @__PURE__ */ new Set();
3104
+ for (const tokens of fileTokens.values()) for (const t of tokens) active.add(t);
3105
+ for (const tok of tokenCSS.keys()) {
3106
+ if (!active.has(tok)) tokenCSS.delete(tok);
3107
+ }
3108
+ if (mainCSSFile) {
3109
+ const changed = writeKbachToFile(mainCSSFile, generateCSS());
3110
+ if (changed) server.watcher.emit("change", mainCSSFile);
3111
+ }
3029
3112
  }
3030
3113
  };
3031
3114
  }
@@ -3,10 +3,10 @@ import {
3
3
  generateClassCSS,
4
4
  setCSSGenMode,
5
5
  splitClassTokens
6
- } from "./chunk-VCNP57PR.mjs";
6
+ } from "./chunk-52N32L7A.mjs";
7
7
 
8
8
  // src/vite-plugin.ts
9
- import { readFileSync, writeFileSync, existsSync, readdirSync, statSync } from "fs";
9
+ import { readFileSync, writeFileSync, readdirSync, statSync } from "fs";
10
10
  import { join } from "path";
11
11
  function normPath(p) {
12
12
  const fwd = p.replace(/\\/g, "/");
@@ -25,9 +25,9 @@ var GROUPS = [
25
25
  ["Effects", /^(shadow|opacity|blur|brightness|contrast|grayscale|transition|duration|ease|delay|animate|scale|rotate|translate|transform|cursor|pointer|select-)/]
26
26
  ];
27
27
  var GROUP_ORDER = ["Layout", "Sizing", "Spacing", "Typography", "Colors", "Borders", "Effects", "Utilities", "Dark Mode", "Responsive"];
28
- function classifyToken(token) {
28
+ function classifyToken(token, responsiveRe) {
29
29
  if (/^dark:/.test(token)) return "Dark Mode";
30
- if (/^(sm|md|lg|xl|2xl):/.test(token)) return "Responsive";
30
+ if (responsiveRe.test(token)) return "Responsive";
31
31
  const base = token.replace(/^(hover|focus|active|group-hover|peer-hover):/, "");
32
32
  for (const [label, re] of GROUPS) {
33
33
  if (re.test(base)) return label;
@@ -52,7 +52,7 @@ function buildColorVarMap(theme, usedCSS) {
52
52
  }
53
53
  return map;
54
54
  }
55
- function formatKbachCSS(tokenCSS, theme) {
55
+ function formatKbachCSS(tokenCSS, theme, responsiveRe) {
56
56
  const allRaw = [...tokenCSS.values()].filter(Boolean).join("\n");
57
57
  const colorVars = buildColorVarMap(theme, allRaw);
58
58
  function applyVars(css) {
@@ -63,7 +63,7 @@ function formatKbachCSS(tokenCSS, theme) {
63
63
  const groups = new Map(GROUP_ORDER.map((g) => [g, []]));
64
64
  for (const [token, css] of tokenCSS) {
65
65
  if (!css) continue;
66
- const label = classifyToken(token);
66
+ const label = classifyToken(token, responsiveRe);
67
67
  if (!groups.has(label)) groups.set(label, []);
68
68
  groups.get(label).push(applyVars(css));
69
69
  }
@@ -92,16 +92,50 @@ function buildThemeGlobal(theme) {
92
92
  const family = Array.isArray(ff.sans) ? ff.sans.join(", ") : ff.sans;
93
93
  return `body { font-family: ${family}; }`;
94
94
  }
95
- function findMainCSSFile(root) {
96
- for (const c of [
97
- join(root, "app", "app.css"),
98
- join(root, "src", "index.css"),
99
- join(root, "src", "app.css"),
100
- join(root, "app", "index.css")
101
- ]) {
102
- if (existsSync(c)) return c;
103
- }
104
- return null;
95
+ var SKIP_DIRS = /* @__PURE__ */ new Set([
96
+ "node_modules",
97
+ "dist",
98
+ "build",
99
+ "out",
100
+ ".next",
101
+ ".nuxt",
102
+ ".output",
103
+ ".git",
104
+ ".svn",
105
+ ".cache",
106
+ "coverage",
107
+ "__pycache__"
108
+ ]);
109
+ function findKbachCSS(root) {
110
+ const found = [];
111
+ function scan(dir, depth) {
112
+ if (depth > 10) return;
113
+ let entries;
114
+ try {
115
+ entries = readdirSync(dir);
116
+ } catch {
117
+ return;
118
+ }
119
+ for (const entry of entries) {
120
+ if (entry.startsWith(".") || SKIP_DIRS.has(entry)) continue;
121
+ const full = join(dir, entry);
122
+ try {
123
+ const st = statSync(full);
124
+ if (st.isDirectory()) scan(full, depth + 1);
125
+ else if (entry === "kbach.css") found.push(full);
126
+ } catch {
127
+ }
128
+ }
129
+ }
130
+ scan(root, 0);
131
+ if (found.length === 0) return null;
132
+ found.sort((a, b) => a.split(/[\\/]/g).length - b.split(/[\\/]/g).length);
133
+ if (found.length > 1) {
134
+ console.warn(
135
+ "[kbach] Multiple kbach.css files found \u2014 only the shallowest will receive generated styles.\n Remove duplicates to avoid confusion:\n" + found.map((f) => ` ${f}`).join("\n")
136
+ );
137
+ }
138
+ return found[0];
105
139
  }
106
140
  function writeKbachToFile(filePath, css) {
107
141
  let existing = "";
@@ -117,7 +151,9 @@ ${KBACH_END}`;
117
151
  const next = start !== -1 && end !== -1 ? existing.slice(0, start) + block + existing.slice(end + KBACH_END.length) : existing ? `${existing}
118
152
 
119
153
  ${block}` : block;
120
- if (next !== existing) writeFileSync(filePath, next, "utf-8");
154
+ if (next === existing) return false;
155
+ writeFileSync(filePath, next, "utf-8");
156
+ return true;
121
157
  }
122
158
  function toNumericScreens(screens) {
123
159
  const out = {};
@@ -131,11 +167,21 @@ function extractClassStrings(code) {
131
167
  const simpleRe = /(?:className|kb)=["']([^"']+)["']/g;
132
168
  let m;
133
169
  while ((m = simpleRe.exec(code)) !== null) pushTokens(m[1], found);
134
- const exprLiteralRe = /(?:className|kb)=\{["'`]([^"'`}]+)["'`]\}/g;
135
- while ((m = exprLiteralRe.exec(code)) !== null) pushTokens(m[1], found);
136
- const ternaryBlockRe = /(?:className|kb)=\{([^}]{1,500})\}/g;
137
- while ((m = ternaryBlockRe.exec(code)) !== null) {
138
- const block = m[1];
170
+ const jsxExprRe = /(?:className|kb)=\{/g;
171
+ while ((m = jsxExprRe.exec(code)) !== null) {
172
+ let depth = 1;
173
+ let i = m.index + m[0].length;
174
+ let block = "";
175
+ while (i < code.length && depth > 0) {
176
+ const ch = code[i];
177
+ if (ch === "{") depth++;
178
+ else if (ch === "}") {
179
+ if (--depth === 0) break;
180
+ }
181
+ block += ch;
182
+ i++;
183
+ }
184
+ jsxExprRe.lastIndex = i + 1;
139
185
  const innerStrings = block.match(/["'`]([^"'`]{1,300})["'`]/g) ?? [];
140
186
  for (const s of innerStrings) pushTokens(s.slice(1, -1), found);
141
187
  }
@@ -158,23 +204,31 @@ function pushTokens(str, into) {
158
204
  }
159
205
  }
160
206
  function scanDir(dir, onFile) {
207
+ let entries;
161
208
  try {
162
- for (const entry of readdirSync(dir)) {
163
- if (entry.startsWith(".") || entry === "node_modules") continue;
164
- const full = join(dir, entry);
165
- try {
166
- const st = statSync(full);
167
- if (st.isDirectory()) scanDir(full, onFile);
168
- else if (/\.(tsx?|jsx?)$/.test(entry)) onFile(full, readFileSync(full, "utf-8"));
169
- } catch {
170
- }
209
+ entries = readdirSync(dir);
210
+ } catch (err) {
211
+ console.warn(`[kbach] Cannot read directory ${dir}:`, err.message);
212
+ return;
213
+ }
214
+ for (const entry of entries) {
215
+ if (entry.startsWith(".") || entry === "node_modules") continue;
216
+ const full = join(dir, entry);
217
+ try {
218
+ const st = statSync(full);
219
+ if (st.isDirectory()) scanDir(full, onFile);
220
+ else if (/\.(tsx?|jsx?)$/.test(entry)) onFile(full, readFileSync(full, "utf-8"));
221
+ } catch (err) {
222
+ console.warn(`[kbach] Cannot process ${full}:`, err.message);
171
223
  }
172
- } catch {
173
224
  }
174
225
  }
175
226
  function kbach(userConfig) {
176
227
  const cfg = buildConfig(userConfig ?? {});
177
228
  const screens = toNumericScreens(cfg.theme.screens ?? {});
229
+ const screenKeys = Object.keys(cfg.theme.screens ?? {});
230
+ const responsivePattern = screenKeys.length ? screenKeys.map((k) => k.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|") : "sm|md|lg|xl|2xl";
231
+ const responsiveRe = new RegExp(`^(${responsivePattern}):`);
178
232
  let root = process.cwd();
179
233
  let mainCSSFile = null;
180
234
  const fileTokens = /* @__PURE__ */ new Map();
@@ -208,7 +262,7 @@ function kbach(userConfig) {
208
262
  }
209
263
  }
210
264
  function generateCSS() {
211
- return formatKbachCSS(buildTokenCSSView(), cfg.theme);
265
+ return formatKbachCSS(buildTokenCSSView(), cfg.theme, responsiveRe);
212
266
  }
213
267
  return {
214
268
  name: "kbach",
@@ -216,19 +270,39 @@ function kbach(userConfig) {
216
270
  configResolved(resolved) {
217
271
  root = resolved.root;
218
272
  },
273
+ // When any JS/TS file imports kbach.css, prepend a disableRuntimeCSS() call
274
+ // so styles come solely from the static stylesheet — no duplicate injection.
275
+ transform(code, id) {
276
+ if (!/\.(tsx?|jsx?|mjs?)$/.test(id)) return;
277
+ if (!/['"].*kbach\.css['"]/i.test(code)) return;
278
+ return {
279
+ code: `import { disableRuntimeCSS } from '@kbach/react';
280
+ disableRuntimeCSS();
281
+ ${code}`,
282
+ map: null
283
+ };
284
+ },
219
285
  buildStart() {
220
- mainCSSFile = findMainCSSFile(root);
286
+ mainCSSFile = findKbachCSS(root);
221
287
  initialScan();
222
288
  if (mainCSSFile) writeKbachToFile(mainCSSFile, generateCSS());
223
289
  },
224
- handleHotUpdate({ file }) {
290
+ handleHotUpdate({ file, server }) {
225
291
  if (file.includes("node_modules") || !/\.(tsx?|jsx?)$/.test(file)) return;
226
292
  try {
227
293
  processFile(file, readFileSync(file, "utf-8"));
228
294
  } catch {
229
295
  fileTokens.delete(normPath(file));
230
296
  }
231
- if (mainCSSFile) writeKbachToFile(mainCSSFile, generateCSS());
297
+ const active = /* @__PURE__ */ new Set();
298
+ for (const tokens of fileTokens.values()) for (const t of tokens) active.add(t);
299
+ for (const tok of tokenCSS.keys()) {
300
+ if (!active.has(tok)) tokenCSS.delete(tok);
301
+ }
302
+ if (mainCSSFile) {
303
+ const changed = writeKbachToFile(mainCSSFile, generateCSS());
304
+ if (changed) server.watcher.emit("change", mainCSSFile);
305
+ }
232
306
  }
233
307
  };
234
308
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kbach/react",
3
- "version": "0.5.42",
3
+ "version": "0.5.44",
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",
@@ -54,7 +54,7 @@
54
54
  "vitest": "^1.0.0"
55
55
  },
56
56
  "peerDependencies": {
57
- "react": ">=17.0.0",
57
+ "react": ">=18.0.0",
58
58
  "react-native": ">=0.70.0",
59
59
  "vite": ">=4.0.0"
60
60
  },