@kbach/react 0.5.62 → 0.6.0

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.
package/README.md CHANGED
@@ -12,6 +12,8 @@ Tailwind-like utility classes for React (web). Write classes as `className` stri
12
12
 
13
13
  ## Install
14
14
 
15
+ [npm package](https://www.npmjs.com/package/@kbach/react)
16
+
15
17
  ```
16
18
  npm install @kbach/react
17
19
  ```
@@ -226,15 +228,6 @@ colors['white/20'] // 'rgba(255,255,255,0.2)'
226
228
  colors.alpha('#ff6b35', 60) // 'rgba(255,107,53,0.6)'
227
229
  ```
228
230
 
229
- ### ThemeToggle
230
-
231
- ```jsx
232
- <ThemeToggle /> // button (default)
233
- <ThemeToggle variant="switch" /> // toggle switch
234
- <ThemeToggle variant="icon-button" /> // icon button
235
- <ThemeToggle variant="button" includeSystem /> // three-way selector
236
- ```
237
-
238
231
  ## Modifiers
239
232
 
240
233
  Chain modifiers in any order before the utility name:
@@ -1,10 +1,3 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
1
  // src/core/theme.ts
9
2
  var defaultColors = {
10
3
  transparent: "transparent",
@@ -3131,7 +3124,6 @@ var customVariants = new Proxy(
3131
3124
  );
3132
3125
 
3133
3126
  export {
3134
- __require,
3135
3127
  defaultColors,
3136
3128
  defaultTheme,
3137
3129
  isWeb,
@@ -6,7 +6,7 @@ import {
6
6
  transformToWebProps,
7
7
  useConditionalWidth,
8
8
  useGlobalDarkMode
9
- } from "./chunk-5MX3E4OL.mjs";
9
+ } from "./chunk-D4LJICWZ.mjs";
10
10
  import {
11
11
  flatten,
12
12
  getActiveBreakpoints,
@@ -22,7 +22,7 @@ import {
22
22
  normalizeClassString,
23
23
  onConfigChange,
24
24
  resolve
25
- } from "./chunk-BRCQK5DA.mjs";
25
+ } from "./chunk-6NED62DB.mjs";
26
26
 
27
27
  // src/jsx-runtime.tsx
28
28
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -7,7 +7,7 @@ import {
7
7
  isNative,
8
8
  isWeb,
9
9
  subscribeGlobalWidth
10
- } from "./chunk-BRCQK5DA.mjs";
10
+ } from "./chunk-6NED62DB.mjs";
11
11
 
12
12
  // src/core/darkModeStore.ts
13
13
  var KEY = "__kbach_dark_store__";
package/dist/index.d.mts CHANGED
@@ -133,34 +133,6 @@ interface ThemeProviderProps {
133
133
  }
134
134
  declare function ThemeProvider({ children, defaultMode, colorScheme, windowWidth: windowWidthProp, config: configOverride, disablePersistence, }: ThemeProviderProps): React__default.JSX.Element;
135
135
 
136
- type ToggleVariant = 'button' | 'switch' | 'icon-button';
137
- interface ThemeToggleProps {
138
- /** Visual variant. Default: 'button' */
139
- variant?: ToggleVariant;
140
- /** Override label text (button variant) */
141
- label?: string;
142
- /** Custom light-mode label */
143
- lightLabel?: string;
144
- /** Custom dark-mode label */
145
- darkLabel?: string;
146
- /** Show system mode option */
147
- includeSystem?: boolean;
148
- /** Custom styles applied to the root container */
149
- style?: object;
150
- /** Custom styles for the label text */
151
- labelStyle?: object;
152
- }
153
- /**
154
- * Drop-in theme toggle. Works on web and React Native.
155
- *
156
- * ```tsx
157
- * <ThemeToggle />
158
- * <ThemeToggle variant="switch" />
159
- * <ThemeToggle variant="icon-button" lightLabel="☀️" darkLabel="🌙" />
160
- * ```
161
- */
162
- declare function ThemeToggle({ variant, label, lightLabel, darkLabel, includeSystem, style, labelStyle, }: ThemeToggleProps): React__default.JSX.Element;
163
-
164
136
  interface StyledProps {
165
137
  /** Additional utility classes applied on top of the base classes */
166
138
  kb?: string;
@@ -306,4 +278,4 @@ declare function kb(classString: string, isDark?: boolean): StyleValue | string;
306
278
  */
307
279
  declare function cx(...classes: Array<string | false | null | undefined>): string;
308
280
 
309
- 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 };
281
+ 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, 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
@@ -133,34 +133,6 @@ interface ThemeProviderProps {
133
133
  }
134
134
  declare function ThemeProvider({ children, defaultMode, colorScheme, windowWidth: windowWidthProp, config: configOverride, disablePersistence, }: ThemeProviderProps): React__default.JSX.Element;
135
135
 
136
- type ToggleVariant = 'button' | 'switch' | 'icon-button';
137
- interface ThemeToggleProps {
138
- /** Visual variant. Default: 'button' */
139
- variant?: ToggleVariant;
140
- /** Override label text (button variant) */
141
- label?: string;
142
- /** Custom light-mode label */
143
- lightLabel?: string;
144
- /** Custom dark-mode label */
145
- darkLabel?: string;
146
- /** Show system mode option */
147
- includeSystem?: boolean;
148
- /** Custom styles applied to the root container */
149
- style?: object;
150
- /** Custom styles for the label text */
151
- labelStyle?: object;
152
- }
153
- /**
154
- * Drop-in theme toggle. Works on web and React Native.
155
- *
156
- * ```tsx
157
- * <ThemeToggle />
158
- * <ThemeToggle variant="switch" />
159
- * <ThemeToggle variant="icon-button" lightLabel="☀️" darkLabel="🌙" />
160
- * ```
161
- */
162
- declare function ThemeToggle({ variant, label, lightLabel, darkLabel, includeSystem, style, labelStyle, }: ThemeToggleProps): React__default.JSX.Element;
163
-
164
136
  interface StyledProps {
165
137
  /** Additional utility classes applied on top of the base classes */
166
138
  kb?: string;
@@ -306,4 +278,4 @@ declare function kb(classString: string, isDark?: boolean): StyleValue | string;
306
278
  */
307
279
  declare function cx(...classes: Array<string | false | null | undefined>): string;
308
280
 
309
- 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 };
281
+ 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, 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
@@ -33,7 +33,6 @@ __export(index_exports, {
33
33
  InteractiveWrapper: () => InteractiveWrapper,
34
34
  ThemeContext: () => ThemeContext,
35
35
  ThemeProvider: () => ThemeProvider,
36
- ThemeToggle: () => ThemeToggle,
37
36
  buildConfig: () => buildConfig,
38
37
  cx: () => cx,
39
38
  defaultColors: () => defaultColors,
@@ -3427,153 +3426,14 @@ function ThemeProvider({
3427
3426
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeContext.Provider, { value: contextValue, children });
3428
3427
  }
3429
3428
 
3430
- // src/ThemeToggle.tsx
3431
- var import_react4 = __toESM(require("react"));
3432
- function getPrimitives() {
3433
- try {
3434
- const RN = require("react-native");
3435
- return {
3436
- View: RN.View,
3437
- Text: RN.Text,
3438
- Touchable: RN.TouchableOpacity,
3439
- Switch: RN.Switch
3440
- };
3441
- } catch {
3442
- const View = ({ style, ...rest }) => import_react4.default.createElement("div", { style, ...rest });
3443
- const Text = ({ style, ...rest }) => import_react4.default.createElement("span", { style, ...rest });
3444
- const Touchable = ({ onPress, style, ...rest }) => import_react4.default.createElement("button", { onClick: onPress, style, ...rest });
3445
- const Switch = ({
3446
- value,
3447
- onValueChange,
3448
- accessibilityLabel
3449
- }) => import_react4.default.createElement("input", {
3450
- type: "checkbox",
3451
- checked: value,
3452
- onChange: (e) => onValueChange?.(e.target.checked),
3453
- "aria-label": accessibilityLabel
3454
- });
3455
- return { View, Text, Touchable, Switch };
3456
- }
3457
- }
3458
- var { View: _View, Text: _Text, Touchable: _Touchable, Switch: _Switch } = getPrimitives();
3459
- function ThemeToggle({
3460
- variant = "button",
3461
- label,
3462
- lightLabel = "Light",
3463
- darkLabel = "Dark",
3464
- includeSystem = false,
3465
- style,
3466
- labelStyle
3467
- }) {
3468
- const { mode, isDark, setMode, toggle } = useTheme();
3469
- const View = _View, Text = _Text, Touchable = _Touchable, Switch = _Switch;
3470
- if (variant === "switch") {
3471
- return import_react4.default.createElement(
3472
- View,
3473
- { style: { flexDirection: "row", alignItems: "center", gap: 8, ...style } },
3474
- import_react4.default.createElement(Text, { style: { fontSize: 14, ...labelStyle } }, lightLabel),
3475
- import_react4.default.createElement(Switch, {
3476
- value: isDark,
3477
- onValueChange: (v) => setMode(v ? "dark" : "light"),
3478
- trackColor: { false: "#d1d5db", true: "#6366f1" },
3479
- thumbColor: isDark ? "#ffffff" : "#f3f4f6",
3480
- ios_backgroundColor: "#d1d5db",
3481
- accessibilityLabel: "Toggle dark mode"
3482
- }),
3483
- import_react4.default.createElement(Text, { style: { fontSize: 14, ...labelStyle } }, darkLabel)
3484
- );
3485
- }
3486
- if (variant === "icon-button") {
3487
- const icon = isDark ? darkLabel : lightLabel;
3488
- return import_react4.default.createElement(
3489
- Touchable,
3490
- {
3491
- onPress: toggle,
3492
- style: {
3493
- padding: 8,
3494
- borderRadius: 8,
3495
- backgroundColor: isDark ? "#374151" : "#f3f4f6",
3496
- ...style
3497
- },
3498
- accessibilityRole: "button",
3499
- accessibilityLabel: `Switch to ${isDark ? "light" : "dark"} mode`,
3500
- accessibilityState: {}
3501
- },
3502
- import_react4.default.createElement(Text, { style: { fontSize: 18, ...labelStyle } }, icon)
3503
- );
3504
- }
3505
- if (includeSystem) {
3506
- const modes = [
3507
- { key: "light", label: lightLabel },
3508
- { key: "dark", label: darkLabel },
3509
- { key: "system", label: "System" }
3510
- ];
3511
- return import_react4.default.createElement(
3512
- View,
3513
- { style: { flexDirection: "row", gap: 4, ...style } },
3514
- ...modes.map(
3515
- ({ key, label: mLabel }) => import_react4.default.createElement(
3516
- Touchable,
3517
- {
3518
- key,
3519
- onPress: () => setMode(key),
3520
- style: {
3521
- paddingHorizontal: 12,
3522
- paddingVertical: 6,
3523
- borderRadius: 6,
3524
- backgroundColor: mode === key ? isDark ? "#6366f1" : "#3b82f6" : isDark ? "#374151" : "#e5e7eb"
3525
- },
3526
- accessibilityRole: "button",
3527
- accessibilityLabel: `Set ${key} theme`,
3528
- accessibilityState: { selected: mode === key }
3529
- },
3530
- import_react4.default.createElement(Text, {
3531
- style: {
3532
- fontSize: 13,
3533
- fontWeight: "500",
3534
- color: mode === key ? "#ffffff" : isDark ? "#d1d5db" : "#374151",
3535
- ...labelStyle
3536
- }
3537
- }, mLabel)
3538
- )
3539
- )
3540
- );
3541
- }
3542
- const currentLabel = label ?? (isDark ? darkLabel : lightLabel);
3543
- return import_react4.default.createElement(
3544
- Touchable,
3545
- {
3546
- onPress: toggle,
3547
- style: {
3548
- paddingHorizontal: 16,
3549
- paddingVertical: 8,
3550
- borderRadius: 8,
3551
- backgroundColor: isDark ? "#374151" : "#e5e7eb",
3552
- ...style
3553
- },
3554
- accessibilityRole: "button",
3555
- accessibilityLabel: `Switch to ${isDark ? "light" : "dark"} mode`,
3556
- accessibilityState: {}
3557
- },
3558
- import_react4.default.createElement(Text, {
3559
- style: {
3560
- fontSize: 14,
3561
- fontWeight: "500",
3562
- color: isDark ? "#f9fafb" : "#111827",
3563
- ...labelStyle
3564
- }
3565
- }, currentLabel)
3566
- );
3567
- }
3568
-
3569
3429
  // src/styled.tsx
3570
- var import_react7 = __toESM(require("react"));
3430
+ var import_react6 = __toESM(require("react"));
3571
3431
 
3572
3432
  // src/useGlobalDarkMode.ts
3573
- var import_react5 = __toESM(require("react"));
3574
- var useSyncExternalStore = import_react5.default.useSyncExternalStore ?? function useSyncExternalStoreFallback(subscribe, getSnapshot, _getServerSnapshot) {
3575
- const [, forceUpdate] = import_react5.default.useReducer((n) => n + 1, 0);
3576
- import_react5.default.useEffect(() => subscribe(forceUpdate), [subscribe]);
3433
+ var import_react4 = __toESM(require("react"));
3434
+ var useSyncExternalStore = import_react4.default.useSyncExternalStore ?? function useSyncExternalStoreFallback(subscribe, getSnapshot, _getServerSnapshot) {
3435
+ const [, forceUpdate] = import_react4.default.useReducer((n) => n + 1, 0);
3436
+ import_react4.default.useEffect(() => subscribe(forceUpdate), [subscribe]);
3577
3437
  return getSnapshot();
3578
3438
  };
3579
3439
  function useGlobalDarkMode() {
@@ -3586,10 +3446,10 @@ function useGlobalDarkMode() {
3586
3446
  }
3587
3447
 
3588
3448
  // src/useGlobalWidth.ts
3589
- var import_react6 = __toESM(require("react"));
3590
- var useSyncExternalStore2 = import_react6.default.useSyncExternalStore ?? function useSyncExternalStoreFallback2(subscribe, getSnapshot, _getServerSnapshot) {
3591
- const [, forceUpdate] = import_react6.default.useReducer((n) => n + 1, 0);
3592
- import_react6.default.useEffect(() => subscribe(forceUpdate), [subscribe]);
3449
+ var import_react5 = __toESM(require("react"));
3450
+ var useSyncExternalStore2 = import_react5.default.useSyncExternalStore ?? function useSyncExternalStoreFallback2(subscribe, getSnapshot, _getServerSnapshot) {
3451
+ const [, forceUpdate] = import_react5.default.useReducer((n) => n + 1, 0);
3452
+ import_react5.default.useEffect(() => subscribe(forceUpdate), [subscribe]);
3593
3453
  return getSnapshot();
3594
3454
  };
3595
3455
  var NOOP_SUB = (_) => () => {
@@ -3940,7 +3800,7 @@ function transformToWebProps(originalName, tag, props) {
3940
3800
 
3941
3801
  // src/styled.tsx
3942
3802
  function styled(Component, baseClasses = "") {
3943
- const Styled = (0, import_react7.forwardRef)(
3803
+ const Styled = (0, import_react6.forwardRef)(
3944
3804
  (props, ref) => {
3945
3805
  const {
3946
3806
  kb: extraClasses,
@@ -3960,52 +3820,52 @@ function styled(Component, baseClasses = "") {
3960
3820
  const checked = !!props.checked;
3961
3821
  const { config } = useTheme();
3962
3822
  const isDark = useGlobalDarkMode();
3963
- const [pressed, setPressed] = (0, import_react7.useState)(false);
3964
- const [hovered, setHovered] = (0, import_react7.useState)(false);
3965
- const [focused, setFocused] = (0, import_react7.useState)(false);
3966
- const handlePressIn = (0, import_react7.useCallback)((e) => {
3823
+ const [pressed, setPressed] = (0, import_react6.useState)(false);
3824
+ const [hovered, setHovered] = (0, import_react6.useState)(false);
3825
+ const [focused, setFocused] = (0, import_react6.useState)(false);
3826
+ const handlePressIn = (0, import_react6.useCallback)((e) => {
3967
3827
  setPressed(true);
3968
3828
  onPressIn?.(e);
3969
3829
  }, [onPressIn]);
3970
- const handlePressOut = (0, import_react7.useCallback)((e) => {
3830
+ const handlePressOut = (0, import_react6.useCallback)((e) => {
3971
3831
  setPressed(false);
3972
3832
  onPressOut?.(e);
3973
3833
  }, [onPressOut]);
3974
- const handlePointerDown = (0, import_react7.useCallback)((e) => {
3834
+ const handlePointerDown = (0, import_react6.useCallback)((e) => {
3975
3835
  setPressed(true);
3976
3836
  onPointerDown?.(e);
3977
3837
  }, [onPointerDown]);
3978
- const handlePointerUp = (0, import_react7.useCallback)((e) => {
3838
+ const handlePointerUp = (0, import_react6.useCallback)((e) => {
3979
3839
  setPressed(false);
3980
3840
  onPointerUp?.(e);
3981
3841
  }, [onPointerUp]);
3982
- const handlePointerLeave = (0, import_react7.useCallback)((e) => {
3842
+ const handlePointerLeave = (0, import_react6.useCallback)((e) => {
3983
3843
  setPressed(false);
3984
3844
  onPointerLeave?.(e);
3985
3845
  }, [onPointerLeave]);
3986
- const handleMouseEnter = (0, import_react7.useCallback)((e) => {
3846
+ const handleMouseEnter = (0, import_react6.useCallback)((e) => {
3987
3847
  setHovered(true);
3988
3848
  onMouseEnter?.(e);
3989
3849
  }, [onMouseEnter]);
3990
- const handleMouseLeave = (0, import_react7.useCallback)((e) => {
3850
+ const handleMouseLeave = (0, import_react6.useCallback)((e) => {
3991
3851
  setHovered(false);
3992
3852
  onMouseLeave?.(e);
3993
3853
  }, [onMouseLeave]);
3994
- const handleFocus = (0, import_react7.useCallback)((e) => {
3854
+ const handleFocus = (0, import_react6.useCallback)((e) => {
3995
3855
  setFocused(true);
3996
3856
  onFocus?.(e);
3997
3857
  }, [onFocus]);
3998
- const handleBlur = (0, import_react7.useCallback)((e) => {
3858
+ const handleBlur = (0, import_react6.useCallback)((e) => {
3999
3859
  setFocused(false);
4000
3860
  onBlur?.(e);
4001
3861
  }, [onBlur]);
4002
3862
  const combined = extraClasses ? `${baseClasses} ${extraClasses}` : baseClasses;
4003
- const resolved = (0, import_react7.useMemo)(() => resolve(combined, config.theme, config.darkMode), [combined, config.theme, config.darkMode]);
4004
- const hasInteractive = (0, import_react7.useMemo)(() => hasInteractiveBuckets(resolved), [resolved]);
3863
+ const resolved = (0, import_react6.useMemo)(() => resolve(combined, config.theme, config.darkMode), [combined, config.theme, config.darkMode]);
3864
+ const hasInteractive = (0, import_react6.useMemo)(() => hasInteractiveBuckets(resolved), [resolved]);
4005
3865
  const needsWidth = hasResponsiveBuckets(resolved);
4006
3866
  const width = useConditionalWidth(needsWidth);
4007
3867
  const breakpoints = needsWidth ? getActiveBreakpoints(width) : EMPTY_BREAKPOINTS;
4008
- const computedStyle = (0, import_react7.useMemo)(
3868
+ const computedStyle = (0, import_react6.useMemo)(
4009
3869
  () => isWeb ? {} : flatten(resolved, isDark, { pressed, hover: hovered, focus: focused, disabled, checked }, breakpoints),
4010
3870
  [resolved, isDark, pressed, hovered, focused, disabled, checked, width]
4011
3871
  // eslint-disable-line react-hooks/exhaustive-deps
@@ -4016,7 +3876,7 @@ function styled(Component, baseClasses = "") {
4016
3876
  const effectiveComponent = webTag ?? Component;
4017
3877
  const componentName2 = Component.displayName ?? Component.name ?? "";
4018
3878
  const effectiveRest = webTag && componentName2 ? transformToWebProps(componentName2, webTag, rest) : rest;
4019
- return import_react7.default.createElement(effectiveComponent, {
3879
+ return import_react6.default.createElement(effectiveComponent, {
4020
3880
  ref,
4021
3881
  ...effectiveRest,
4022
3882
  style: finalStyle,
@@ -4040,12 +3900,12 @@ function styled(Component, baseClasses = "") {
4040
3900
  }
4041
3901
 
4042
3902
  // src/useStyles.ts
4043
- var import_react8 = require("react");
3903
+ var import_react7 = require("react");
4044
3904
  function useStyles(classString, state = {}) {
4045
3905
  const { isDark, config } = useTheme();
4046
3906
  const width = useGlobalWidth();
4047
3907
  const normalised = Array.isArray(classString) ? classString.join(" ") : classString;
4048
- return (0, import_react8.useMemo)(() => {
3908
+ return (0, import_react7.useMemo)(() => {
4049
3909
  const resolved = resolve(normalised, config.theme, config.darkMode);
4050
3910
  const breakpoints = getActiveBreakpoints(width);
4051
3911
  return flatten(resolved, isDark, state, breakpoints);
@@ -4054,19 +3914,19 @@ function useStyles(classString, state = {}) {
4054
3914
  function useResolvedStyle(classString) {
4055
3915
  const { config } = useTheme();
4056
3916
  const normalised = Array.isArray(classString) ? classString.join(" ") : classString;
4057
- return (0, import_react8.useMemo)(
3917
+ return (0, import_react7.useMemo)(
4058
3918
  () => resolve(normalised, config.theme, config.darkMode),
4059
3919
  [normalised, config]
4060
3920
  );
4061
3921
  }
4062
3922
 
4063
3923
  // src/useBreakpoint.ts
4064
- var import_react9 = require("react");
3924
+ var import_react8 = require("react");
4065
3925
  function useBreakpoint() {
4066
3926
  const { config } = useTheme();
4067
3927
  const width = useGlobalWidth();
4068
3928
  const screens = config.theme.screens;
4069
- const sorted = (0, import_react9.useMemo)(
3929
+ const sorted = (0, import_react8.useMemo)(
4070
3930
  () => Object.entries(screens).filter((entry) => typeof entry[1] === "number").sort(([, a], [, b]) => b - a),
4071
3931
  [screens]
4072
3932
  );
@@ -4079,7 +3939,7 @@ function useResponsive() {
4079
3939
  const { config } = useTheme();
4080
3940
  const width = useGlobalWidth();
4081
3941
  const screens = config.theme.screens;
4082
- return (0, import_react9.useMemo)(() => {
3942
+ return (0, import_react8.useMemo)(() => {
4083
3943
  const result = {};
4084
3944
  for (const [name, minW] of Object.entries(screens)) {
4085
3945
  if (typeof minW === "number") result[name] = width >= minW;
@@ -4089,14 +3949,14 @@ function useResponsive() {
4089
3949
  }
4090
3950
 
4091
3951
  // src/InteractiveWrapper.tsx
4092
- var import_react10 = __toESM(require("react"));
3952
+ var import_react9 = __toESM(require("react"));
4093
3953
  function chain(original, extra) {
4094
3954
  return (...args) => {
4095
3955
  original?.(...args);
4096
3956
  extra();
4097
3957
  };
4098
3958
  }
4099
- var InteractiveWrapper = (0, import_react10.forwardRef)(
3959
+ var InteractiveWrapper = (0, import_react9.forwardRef)(
4100
3960
  function InteractiveWrapper2({
4101
3961
  Component,
4102
3962
  resolvedStyle,
@@ -4117,20 +3977,20 @@ var InteractiveWrapper = (0, import_react10.forwardRef)(
4117
3977
  const needsWidth = hasResponsiveBuckets(resolvedStyle);
4118
3978
  const width = useConditionalWidth(needsWidth);
4119
3979
  const breakpoints = needsWidth ? getActiveBreakpoints(width) : EMPTY_BREAKPOINTS;
4120
- const [pressed, setPressed] = (0, import_react10.useState)(false);
4121
- const [hovered, setHovered] = (0, import_react10.useState)(false);
4122
- const [focused, setFocused] = (0, import_react10.useState)(false);
4123
- const handlePressIn = (0, import_react10.useCallback)(chain(onPressIn, () => setPressed(true)), [onPressIn]);
4124
- const handlePressOut = (0, import_react10.useCallback)(chain(onPressOut, () => setPressed(false)), [onPressOut]);
4125
- const handlePointerDown = (0, import_react10.useCallback)(chain(onPointerDown, () => setPressed(true)), [onPointerDown]);
4126
- const handlePointerUp = (0, import_react10.useCallback)(chain(onPointerUp, () => setPressed(false)), [onPointerUp]);
4127
- const handlePointerLeave = (0, import_react10.useCallback)(chain(onPointerLeave, () => setPressed(false)), [onPointerLeave]);
4128
- const handleMouseEnter = (0, import_react10.useCallback)(chain(onMouseEnter, () => setHovered(true)), [onMouseEnter]);
4129
- const handleMouseLeave = (0, import_react10.useCallback)(chain(onMouseLeave, () => setHovered(false)), [onMouseLeave]);
4130
- const handleFocus = (0, import_react10.useCallback)(chain(onFocus, () => setFocused(true)), [onFocus]);
4131
- const handleBlur = (0, import_react10.useCallback)(chain(onBlur, () => setFocused(false)), [onBlur]);
3980
+ const [pressed, setPressed] = (0, import_react9.useState)(false);
3981
+ const [hovered, setHovered] = (0, import_react9.useState)(false);
3982
+ const [focused, setFocused] = (0, import_react9.useState)(false);
3983
+ const handlePressIn = (0, import_react9.useCallback)(chain(onPressIn, () => setPressed(true)), [onPressIn]);
3984
+ const handlePressOut = (0, import_react9.useCallback)(chain(onPressOut, () => setPressed(false)), [onPressOut]);
3985
+ const handlePointerDown = (0, import_react9.useCallback)(chain(onPointerDown, () => setPressed(true)), [onPointerDown]);
3986
+ const handlePointerUp = (0, import_react9.useCallback)(chain(onPointerUp, () => setPressed(false)), [onPointerUp]);
3987
+ const handlePointerLeave = (0, import_react9.useCallback)(chain(onPointerLeave, () => setPressed(false)), [onPointerLeave]);
3988
+ const handleMouseEnter = (0, import_react9.useCallback)(chain(onMouseEnter, () => setHovered(true)), [onMouseEnter]);
3989
+ const handleMouseLeave = (0, import_react9.useCallback)(chain(onMouseLeave, () => setHovered(false)), [onMouseLeave]);
3990
+ const handleFocus = (0, import_react9.useCallback)(chain(onFocus, () => setFocused(true)), [onFocus]);
3991
+ const handleBlur = (0, import_react9.useCallback)(chain(onBlur, () => setFocused(false)), [onBlur]);
4132
3992
  const { children, disabled, checked, ...restForComponent } = rest;
4133
- const computedStyle = (0, import_react10.useMemo)(
3993
+ const computedStyle = (0, import_react9.useMemo)(
4134
3994
  () => {
4135
3995
  if (isWeb) return {};
4136
3996
  const s = flatten(resolvedStyle, isDark, { pressed, hover: hovered, focus: focused, disabled: !!disabled, checked: !!checked }, breakpoints);
@@ -4184,7 +4044,7 @@ var InteractiveWrapper = (0, import_react10.forwardRef)(
4184
4044
  onFocus: handleFocus,
4185
4045
  onBlur: handleBlur
4186
4046
  };
4187
- return Array.isArray(children) ? import_react10.default.createElement(Component, componentProps, ...children) : import_react10.default.createElement(Component, componentProps, children);
4047
+ return Array.isArray(children) ? import_react9.default.createElement(Component, componentProps, ...children) : import_react9.default.createElement(Component, componentProps, children);
4188
4048
  }
4189
4049
  );
4190
4050
  InteractiveWrapper.displayName = "Kbach.InteractiveWrapper";
@@ -4206,7 +4066,6 @@ function cx(...classes) {
4206
4066
  InteractiveWrapper,
4207
4067
  ThemeContext,
4208
4068
  ThemeProvider,
4209
- ThemeToggle,
4210
4069
  buildConfig,
4211
4070
  cx,
4212
4071
  defaultColors,
package/dist/index.mjs CHANGED
@@ -11,9 +11,8 @@ import {
11
11
  useConditionalWidth,
12
12
  useGlobalDarkMode,
13
13
  useGlobalWidth
14
- } from "./chunk-5MX3E4OL.mjs";
14
+ } from "./chunk-D4LJICWZ.mjs";
15
15
  import {
16
- __require,
17
16
  buildConfig,
18
17
  defaultColors,
19
18
  defaultTheme,
@@ -33,7 +32,7 @@ import {
33
32
  syncGlobalScreens,
34
33
  syncGlobalWidth,
35
34
  updateConfig
36
- } from "./chunk-BRCQK5DA.mjs";
35
+ } from "./chunk-6NED62DB.mjs";
37
36
 
38
37
  // src/context.tsx
39
38
  import { createContext, useContext } from "react";
@@ -270,150 +269,11 @@ function ThemeProvider({
270
269
  return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: contextValue, children });
271
270
  }
272
271
 
273
- // src/ThemeToggle.tsx
274
- import React2 from "react";
275
- function getPrimitives() {
276
- try {
277
- const RN = __require("react-native");
278
- return {
279
- View: RN.View,
280
- Text: RN.Text,
281
- Touchable: RN.TouchableOpacity,
282
- Switch: RN.Switch
283
- };
284
- } catch {
285
- const View = ({ style, ...rest }) => React2.createElement("div", { style, ...rest });
286
- const Text = ({ style, ...rest }) => React2.createElement("span", { style, ...rest });
287
- const Touchable = ({ onPress, style, ...rest }) => React2.createElement("button", { onClick: onPress, style, ...rest });
288
- const Switch = ({
289
- value,
290
- onValueChange,
291
- accessibilityLabel
292
- }) => React2.createElement("input", {
293
- type: "checkbox",
294
- checked: value,
295
- onChange: (e) => onValueChange?.(e.target.checked),
296
- "aria-label": accessibilityLabel
297
- });
298
- return { View, Text, Touchable, Switch };
299
- }
300
- }
301
- var { View: _View, Text: _Text, Touchable: _Touchable, Switch: _Switch } = getPrimitives();
302
- function ThemeToggle({
303
- variant = "button",
304
- label,
305
- lightLabel = "Light",
306
- darkLabel = "Dark",
307
- includeSystem = false,
308
- style,
309
- labelStyle
310
- }) {
311
- const { mode, isDark, setMode, toggle } = useTheme();
312
- const View = _View, Text = _Text, Touchable = _Touchable, Switch = _Switch;
313
- if (variant === "switch") {
314
- return React2.createElement(
315
- View,
316
- { style: { flexDirection: "row", alignItems: "center", gap: 8, ...style } },
317
- React2.createElement(Text, { style: { fontSize: 14, ...labelStyle } }, lightLabel),
318
- React2.createElement(Switch, {
319
- value: isDark,
320
- onValueChange: (v) => setMode(v ? "dark" : "light"),
321
- trackColor: { false: "#d1d5db", true: "#6366f1" },
322
- thumbColor: isDark ? "#ffffff" : "#f3f4f6",
323
- ios_backgroundColor: "#d1d5db",
324
- accessibilityLabel: "Toggle dark mode"
325
- }),
326
- React2.createElement(Text, { style: { fontSize: 14, ...labelStyle } }, darkLabel)
327
- );
328
- }
329
- if (variant === "icon-button") {
330
- const icon = isDark ? darkLabel : lightLabel;
331
- return React2.createElement(
332
- Touchable,
333
- {
334
- onPress: toggle,
335
- style: {
336
- padding: 8,
337
- borderRadius: 8,
338
- backgroundColor: isDark ? "#374151" : "#f3f4f6",
339
- ...style
340
- },
341
- accessibilityRole: "button",
342
- accessibilityLabel: `Switch to ${isDark ? "light" : "dark"} mode`,
343
- accessibilityState: {}
344
- },
345
- React2.createElement(Text, { style: { fontSize: 18, ...labelStyle } }, icon)
346
- );
347
- }
348
- if (includeSystem) {
349
- const modes = [
350
- { key: "light", label: lightLabel },
351
- { key: "dark", label: darkLabel },
352
- { key: "system", label: "System" }
353
- ];
354
- return React2.createElement(
355
- View,
356
- { style: { flexDirection: "row", gap: 4, ...style } },
357
- ...modes.map(
358
- ({ key, label: mLabel }) => React2.createElement(
359
- Touchable,
360
- {
361
- key,
362
- onPress: () => setMode(key),
363
- style: {
364
- paddingHorizontal: 12,
365
- paddingVertical: 6,
366
- borderRadius: 6,
367
- backgroundColor: mode === key ? isDark ? "#6366f1" : "#3b82f6" : isDark ? "#374151" : "#e5e7eb"
368
- },
369
- accessibilityRole: "button",
370
- accessibilityLabel: `Set ${key} theme`,
371
- accessibilityState: { selected: mode === key }
372
- },
373
- React2.createElement(Text, {
374
- style: {
375
- fontSize: 13,
376
- fontWeight: "500",
377
- color: mode === key ? "#ffffff" : isDark ? "#d1d5db" : "#374151",
378
- ...labelStyle
379
- }
380
- }, mLabel)
381
- )
382
- )
383
- );
384
- }
385
- const currentLabel = label ?? (isDark ? darkLabel : lightLabel);
386
- return React2.createElement(
387
- Touchable,
388
- {
389
- onPress: toggle,
390
- style: {
391
- paddingHorizontal: 16,
392
- paddingVertical: 8,
393
- borderRadius: 8,
394
- backgroundColor: isDark ? "#374151" : "#e5e7eb",
395
- ...style
396
- },
397
- accessibilityRole: "button",
398
- accessibilityLabel: `Switch to ${isDark ? "light" : "dark"} mode`,
399
- accessibilityState: {}
400
- },
401
- React2.createElement(Text, {
402
- style: {
403
- fontSize: 14,
404
- fontWeight: "500",
405
- color: isDark ? "#f9fafb" : "#111827",
406
- ...labelStyle
407
- }
408
- }, currentLabel)
409
- );
410
- }
411
-
412
272
  // src/styled.tsx
413
- import React3, {
273
+ import React2, {
414
274
  forwardRef,
415
275
  useState as useState2,
416
- useCallback as useCallback3,
276
+ useCallback as useCallback2,
417
277
  useMemo as useMemo3
418
278
  } from "react";
419
279
  function styled(Component, baseClasses = "") {
@@ -440,39 +300,39 @@ function styled(Component, baseClasses = "") {
440
300
  const [pressed, setPressed] = useState2(false);
441
301
  const [hovered, setHovered] = useState2(false);
442
302
  const [focused, setFocused] = useState2(false);
443
- const handlePressIn = useCallback3((e) => {
303
+ const handlePressIn = useCallback2((e) => {
444
304
  setPressed(true);
445
305
  onPressIn?.(e);
446
306
  }, [onPressIn]);
447
- const handlePressOut = useCallback3((e) => {
307
+ const handlePressOut = useCallback2((e) => {
448
308
  setPressed(false);
449
309
  onPressOut?.(e);
450
310
  }, [onPressOut]);
451
- const handlePointerDown = useCallback3((e) => {
311
+ const handlePointerDown = useCallback2((e) => {
452
312
  setPressed(true);
453
313
  onPointerDown?.(e);
454
314
  }, [onPointerDown]);
455
- const handlePointerUp = useCallback3((e) => {
315
+ const handlePointerUp = useCallback2((e) => {
456
316
  setPressed(false);
457
317
  onPointerUp?.(e);
458
318
  }, [onPointerUp]);
459
- const handlePointerLeave = useCallback3((e) => {
319
+ const handlePointerLeave = useCallback2((e) => {
460
320
  setPressed(false);
461
321
  onPointerLeave?.(e);
462
322
  }, [onPointerLeave]);
463
- const handleMouseEnter = useCallback3((e) => {
323
+ const handleMouseEnter = useCallback2((e) => {
464
324
  setHovered(true);
465
325
  onMouseEnter?.(e);
466
326
  }, [onMouseEnter]);
467
- const handleMouseLeave = useCallback3((e) => {
327
+ const handleMouseLeave = useCallback2((e) => {
468
328
  setHovered(false);
469
329
  onMouseLeave?.(e);
470
330
  }, [onMouseLeave]);
471
- const handleFocus = useCallback3((e) => {
331
+ const handleFocus = useCallback2((e) => {
472
332
  setFocused(true);
473
333
  onFocus?.(e);
474
334
  }, [onFocus]);
475
- const handleBlur = useCallback3((e) => {
335
+ const handleBlur = useCallback2((e) => {
476
336
  setFocused(false);
477
337
  onBlur?.(e);
478
338
  }, [onBlur]);
@@ -493,7 +353,7 @@ function styled(Component, baseClasses = "") {
493
353
  const effectiveComponent = webTag ?? Component;
494
354
  const componentName2 = Component.displayName ?? Component.name ?? "";
495
355
  const effectiveRest = webTag && componentName2 ? transformToWebProps(componentName2, webTag, rest) : rest;
496
- return React3.createElement(effectiveComponent, {
356
+ return React2.createElement(effectiveComponent, {
497
357
  ref,
498
358
  ...effectiveRest,
499
359
  style: finalStyle,
@@ -581,7 +441,6 @@ export {
581
441
  InteractiveWrapper,
582
442
  ThemeContext,
583
443
  ThemeProvider,
584
- ThemeToggle,
585
444
  buildConfig,
586
445
  cx,
587
446
  defaultColors,
@@ -2,9 +2,9 @@ import {
2
2
  Fragment,
3
3
  jsx,
4
4
  jsxs
5
- } from "./chunk-MZKQ7H67.mjs";
6
- import "./chunk-5MX3E4OL.mjs";
7
- import "./chunk-BRCQK5DA.mjs";
5
+ } from "./chunk-AAAI37Y4.mjs";
6
+ import "./chunk-D4LJICWZ.mjs";
7
+ import "./chunk-6NED62DB.mjs";
8
8
 
9
9
  // src/jsx-dev-runtime.tsx
10
10
  function jsxDEV(type, props, key, isStaticChildren, source, self) {
@@ -3,11 +3,11 @@ import {
3
3
  _invalidateDefaultFontCache,
4
4
  jsx,
5
5
  jsxs
6
- } from "./chunk-MZKQ7H67.mjs";
6
+ } from "./chunk-AAAI37Y4.mjs";
7
7
  import {
8
8
  registerWebElement
9
- } from "./chunk-5MX3E4OL.mjs";
10
- import "./chunk-BRCQK5DA.mjs";
9
+ } from "./chunk-D4LJICWZ.mjs";
10
+ import "./chunk-6NED62DB.mjs";
11
11
  export {
12
12
  Fragment,
13
13
  _invalidateDefaultFontCache,
@@ -4,7 +4,7 @@ import {
4
4
  generateClassCSS,
5
5
  setCSSGenMode,
6
6
  splitClassTokens
7
- } from "./chunk-BRCQK5DA.mjs";
7
+ } from "./chunk-6NED62DB.mjs";
8
8
 
9
9
  // src/vite-plugin.ts
10
10
  import { readFileSync, writeFileSync, readdirSync, statSync } from "fs";
package/kbach-react.md CHANGED
@@ -163,14 +163,6 @@ colors['white/20'] // 'rgba(255,255,255,0.2)'
163
163
  colors.alpha('#ff6b35', 60) // 'rgba(255,107,53,0.6)'
164
164
  ```
165
165
 
166
- ### ThemeToggle
167
- ```jsx
168
- <ThemeToggle /> // button (default)
169
- <ThemeToggle variant="switch" /> // toggle switch
170
- <ThemeToggle variant="icon-button" /> // icon button
171
- <ThemeToggle variant="button" includeSystem /> // three-way light/dark/system
172
- ```
173
-
174
166
  ---
175
167
 
176
168
  ## Modifier System
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kbach/react",
3
- "version": "0.5.62",
3
+ "version": "0.6.0",
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",