@kbach/react 0.5.27 → 0.5.28

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.
@@ -0,0 +1,304 @@
1
+ import * as React from 'react';
2
+ import React__default, { ReactNode, ComponentType, ForwardRefExoticComponent } from 'react';
3
+ import { T as ThemeColors, a as ThemeConfig, P as ParsedClass, R as ResolvedStyle, S as StyleValue, F as FrameworkConfig, b as ResolvedConfig, c as ThemeMode } from './types-CV5vXnSH.mjs';
4
+ export { d as PluginAPI } from './types-CV5vXnSH.mjs';
5
+
6
+ declare const defaultColors: ThemeColors;
7
+ declare const defaultTheme: ThemeConfig;
8
+
9
+ declare function parseClass(className: string): ParsedClass | null;
10
+ /** Parse a space-separated class string into individual ParsedClass objects. */
11
+ declare function parseClasses(classString: string): ParsedClass[];
12
+
13
+ /**
14
+ * Resolve a class string to a ResolvedStyle object.
15
+ *
16
+ * The result groups styles by modifier key:
17
+ * - 'base' → always-applied styles
18
+ * - 'dark' → dark-mode styles
19
+ * - 'hover' → hover styles
20
+ * - 'dark:hover' → combined dark + hover
21
+ * - etc.
22
+ *
23
+ * Results are cached — repeated calls with the same string are O(1).
24
+ */
25
+ declare function resolve(classString: string, theme: ThemeConfig, darkMode?: 'attribute' | 'class' | 'media'): ResolvedStyle;
26
+ /**
27
+ * Flatten a ResolvedStyle into a single StyleValue for the given runtime state.
28
+ * Used by useStyles() and styled().
29
+ *
30
+ * @param resolved Output of resolve()
31
+ * @param isDark Whether dark mode is currently active
32
+ * @param state Interaction state flags
33
+ * @param breakpoints Active breakpoint names (sm, md, lg, xl, 2xl). On web,
34
+ * pass an empty Set — CSS @media rules handle responsive.
35
+ */
36
+ declare function flatten(resolved: ResolvedStyle, isDark: boolean, state?: {
37
+ hover?: boolean;
38
+ focus?: boolean;
39
+ pressed?: boolean;
40
+ active?: boolean;
41
+ disabled?: boolean;
42
+ checked?: boolean;
43
+ visited?: boolean;
44
+ placeholder?: boolean;
45
+ }, breakpoints?: Set<string>): StyleValue;
46
+
47
+ /**
48
+ * Load, merge, and cache the resolved config.
49
+ * Call resetConfig() to force a reload (e.g. in tests or after live update).
50
+ */
51
+ declare function getConfig(): ResolvedConfig;
52
+ declare function buildConfig(userConfig: FrameworkConfig): ResolvedConfig;
53
+ declare function updateConfig(userConfig: FrameworkConfig): void;
54
+ /**
55
+ * Like updateConfig, but only calls it when the config object reference has
56
+ * actually changed. Used by the Babel-injected IIFE so that:
57
+ * - multiple files with kbach classes don't re-run the update on every load
58
+ * - Fast Refresh DOES re-run when kbach.config.js changes (new module → new object)
59
+ */
60
+ declare function initConfig(userConfig: FrameworkConfig): void;
61
+
62
+ interface ThemeContextValue {
63
+ /** The user-selected mode ('light' | 'dark' | 'system') */
64
+ mode: ThemeMode;
65
+ /** The effective resolved mode (never 'system') */
66
+ resolvedMode: 'light' | 'dark';
67
+ /** Convenience boolean */
68
+ isDark: boolean;
69
+ /** Change the theme mode programmatically */
70
+ setMode: (mode: ThemeMode) => void;
71
+ /** Toggle between light and dark (ignores system) */
72
+ toggle: () => void;
73
+ /** The fully resolved framework config (theme values, darkMode strategy, etc.) */
74
+ config: ResolvedConfig;
75
+ }
76
+ declare const ThemeContext: React.Context<ThemeContextValue | null>;
77
+ declare function useTheme(): ThemeContextValue;
78
+ declare function useIsDark(): boolean;
79
+
80
+ interface ColorScale {
81
+ /** `colors.blue[6]` → raw hex string */
82
+ readonly [shade: number]: string;
83
+ /** `colors.blue['6/50']` → shade 6 at 50% opacity */
84
+ readonly [key: string]: string;
85
+ }
86
+ interface ColorsAPI {
87
+ /**
88
+ * Pass any CSS color through, optionally applying an opacity (0–100).
89
+ * - `colors.alpha('#3b82f6', 50)` → `'rgba(59,130,246,0.5)'`
90
+ * - `colors.alpha('rgb(0,0,0)', 10)` → `'rgba(0,0,0,0.1)'`
91
+ * - `colors.alpha('rgba(0,0,0,0.5)')` → `'rgba(0,0,0,0.5)'` (passthrough)
92
+ */
93
+ readonly alpha: (color: string, opacity?: number) => string;
94
+ [color: string]: any;
95
+ }
96
+ declare function wrapColors(rawColors: ThemeColors): ColorsAPI;
97
+ declare function useColors(): ColorsAPI;
98
+
99
+ interface ThemeProviderProps {
100
+ children: ReactNode;
101
+ /** Initial mode. Falls back to persisted value, then 'system'. */
102
+ defaultMode?: ThemeMode;
103
+ /**
104
+ * System color scheme for native `defaultMode="system"`.
105
+ *
106
+ * Pass the value of `useColorScheme()` from `react-native`. When importing
107
+ * `ThemeProvider` from `@kbach/native` this is handled automatically.
108
+ *
109
+ * @example
110
+ * ```tsx
111
+ * import { useColorScheme } from 'react-native';
112
+ * const colorScheme = useColorScheme();
113
+ * <ThemeProvider defaultMode="system" colorScheme={colorScheme}>…</ThemeProvider>
114
+ * ```
115
+ */
116
+ colorScheme?: 'light' | 'dark' | null;
117
+ /**
118
+ * Current window/screen width in pixels for responsive breakpoints.
119
+ * On web this is read from `window.innerWidth` automatically.
120
+ * When importing `ThemeProvider` from `@kbach/native` this is provided
121
+ * automatically from `useWindowDimensions()`.
122
+ */
123
+ windowWidth?: number;
124
+ /** Override the config (useful for per-tree config). Defaults to global getConfig(). */
125
+ config?: FrameworkConfig;
126
+ /** Disable persistence to localStorage */
127
+ disablePersistence?: boolean;
128
+ }
129
+ declare function ThemeProvider({ children, defaultMode, colorScheme, windowWidth: windowWidthProp, config: configOverride, disablePersistence, }: ThemeProviderProps): React__default.JSX.Element;
130
+
131
+ type ToggleVariant = 'button' | 'switch' | 'icon-button';
132
+ interface ThemeToggleProps {
133
+ /** Visual variant. Default: 'button' */
134
+ variant?: ToggleVariant;
135
+ /** Override label text (button variant) */
136
+ label?: string;
137
+ /** Custom light-mode label */
138
+ lightLabel?: string;
139
+ /** Custom dark-mode label */
140
+ darkLabel?: string;
141
+ /** Show system mode option */
142
+ includeSystem?: boolean;
143
+ /** Custom styles applied to the root container */
144
+ style?: object;
145
+ /** Custom styles for the label text */
146
+ labelStyle?: object;
147
+ }
148
+ /**
149
+ * Drop-in theme toggle. Works on web and React Native.
150
+ *
151
+ * ```tsx
152
+ * <ThemeToggle />
153
+ * <ThemeToggle variant="switch" />
154
+ * <ThemeToggle variant="icon-button" lightLabel="☀️" darkLabel="🌙" />
155
+ * ```
156
+ */
157
+ declare function ThemeToggle({ variant, label, lightLabel, darkLabel, includeSystem, style, labelStyle, }: ThemeToggleProps): React__default.JSX.Element;
158
+
159
+ interface StyledProps {
160
+ /** Additional utility classes applied on top of the base classes */
161
+ kb?: string;
162
+ /** Merged with resolved kb styles; applied last */
163
+ style?: StyleValue | StyleValue[];
164
+ }
165
+ type OmittedKeys = 'style';
166
+ /**
167
+ * Create a styled component from any React / React Native component.
168
+ *
169
+ * ```tsx
170
+ * const Card = styled(View, 'bg-white dark:bg-gray-800 rounded-xl p-4 shadow-md');
171
+ * const Button = styled(TouchableOpacity, 'bg-blue-500 pressed:bg-blue-700 dark:bg-blue-600 rounded-lg p-3');
172
+ *
173
+ * // Use it:
174
+ * <Card kb="mt-4">...</Card>
175
+ * <Button onPress={handlePress} kb="w-full" />
176
+ * ```
177
+ */
178
+ declare function styled<T extends ComponentType<any>>(Component: T, baseClasses?: string): ForwardRefExoticComponent<Omit<React__default.ComponentPropsWithRef<T>, OmittedKeys> & StyledProps>;
179
+
180
+ interface InteractionState {
181
+ hover?: boolean;
182
+ focus?: boolean;
183
+ /** Maps to 'pressed' and 'active' modifiers */
184
+ pressed?: boolean;
185
+ active?: boolean;
186
+ disabled?: boolean;
187
+ checked?: boolean;
188
+ visited?: boolean;
189
+ placeholder?: boolean;
190
+ }
191
+ /**
192
+ * Resolve a utility class string to a style object for the current theme + state.
193
+ *
194
+ * ```tsx
195
+ * // Basic usage
196
+ * const styles = useStyles('bg-white dark:bg-gray-900 p-4');
197
+ *
198
+ * // With interaction state
199
+ * const [pressed, setPressed] = useState(false);
200
+ * const styles = useStyles('bg-blue-500 pressed:bg-blue-700', { pressed });
201
+ *
202
+ * // Multiple class strings (merged left-to-right)
203
+ * const styles = useStyles(['bg-white p-4', 'dark:bg-gray-900 rounded-xl']);
204
+ * ```
205
+ */
206
+ declare function useStyles(classString: string | string[], state?: InteractionState): StyleValue;
207
+ /**
208
+ * Returns the full ResolvedStyle bucket map (base, dark, hover, …).
209
+ * Useful when you need to apply styles selectively or pass them to Animated.
210
+ */
211
+ declare function useResolvedStyle(classString: string | string[]): ResolvedStyle;
212
+
213
+ /**
214
+ * Subscribe to the global dark-mode store with React's concurrent-safe
215
+ * useSyncExternalStore so that any component using className/kb re-renders
216
+ * immediately when the theme changes — without needing ThemeContext.
217
+ */
218
+ declare function useGlobalDarkMode(): boolean;
219
+
220
+ /**
221
+ * Returns the name of the currently active breakpoint — the largest breakpoint
222
+ * whose min-width the window satisfies, or `'xs'` when below all breakpoints.
223
+ *
224
+ * ```ts
225
+ * const bp = useBreakpoint(); // 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'
226
+ * ```
227
+ */
228
+ declare function useBreakpoint(): string;
229
+ /**
230
+ * Returns a record of boolean flags for each breakpoint — `true` when the
231
+ * window width satisfies that breakpoint's min-width threshold.
232
+ *
233
+ * ```ts
234
+ * const { sm, md, lg } = useResponsive();
235
+ * const padding = lg ? 32 : sm ? 16 : 8;
236
+ * ```
237
+ */
238
+ declare function useResponsive(): Record<string, boolean>;
239
+
240
+ interface InteractiveWrapperProps {
241
+ /** The real component to render (View, TouchableOpacity, div, a third-party button…) */
242
+ Component: React__default.ComponentType<any> | string;
243
+ /** Pre-resolved style buckets from resolve() */
244
+ resolvedStyle: ResolvedStyle;
245
+ /** On web: original class string so CSS pseudo-rules still fire */
246
+ className?: string;
247
+ /** Extra style prop passed by the user */
248
+ style?: StyleValue | StyleValue[];
249
+ children?: React__default.ReactNode;
250
+ onPressIn?: (...args: any[]) => void;
251
+ onPressOut?: (...args: any[]) => void;
252
+ onPointerDown?: (...args: any[]) => void;
253
+ onPointerUp?: (...args: any[]) => void;
254
+ onPointerLeave?: (...args: any[]) => void;
255
+ onMouseEnter?: (...args: any[]) => void;
256
+ onMouseLeave?: (...args: any[]) => void;
257
+ onFocus?: (...args: any[]) => void;
258
+ onBlur?: (...args: any[]) => void;
259
+ }
260
+ /**
261
+ * Thin wrapper rendered automatically by the JSX runtime whenever a className/kb
262
+ * string contains interactive modifiers (hover:, pressed:, focus:, active:, …).
263
+ *
264
+ * Manages interaction state locally and flattens the correct style bucket on
265
+ * every render. The wrapped component sees a plain `style` prop — it never
266
+ * knows it was wrapped.
267
+ *
268
+ * Refs are forwarded so the host component's imperative API still works.
269
+ */
270
+ declare const InteractiveWrapper: React__default.ForwardRefExoticComponent<InteractiveWrapperProps & React__default.RefAttributes<unknown>>;
271
+
272
+ /**
273
+ * Resolve a utility class string outside of a React component.
274
+ *
275
+ * On **native** — returns a StyleValue (style object) for the given mode.
276
+ * On **web** — injects CSS and returns the original class string (use as className).
277
+ *
278
+ * ```ts
279
+ * // Inside a component use useStyles() instead.
280
+ * // kb() is useful for StyleSheet.create() calls and static values.
281
+ *
282
+ * const styles = StyleSheet.create({
283
+ * container: kb('flex-1 bg-white p-4') as any,
284
+ * });
285
+ *
286
+ * // Web: use as className
287
+ * <div className={kb('bg-white dark:bg-gray-900 p-4') as string} />
288
+ * ```
289
+ *
290
+ * @param classString Space-separated utility classes
291
+ * @param isDark Whether dark mode is active (default: false)
292
+ */
293
+ declare function kb(classString: string, isDark?: boolean): StyleValue | string;
294
+ /**
295
+ * Conditionally join class names. Falsy values are ignored.
296
+ *
297
+ * ```ts
298
+ * cx('bg-white p-4', isActive && 'border-2 border-blue-500', undefined)
299
+ * // → 'bg-white p-4 border-2 border-blue-500'
300
+ * ```
301
+ */
302
+ declare function cx(...classes: Array<string | false | null | undefined>): string;
303
+
304
+ 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, parseClass, parseClasses, resolve, styled, updateConfig, useBreakpoint, useColors, useGlobalDarkMode, useIsDark, useResolvedStyle, useResponsive, useStyles, useTheme, wrapColors };
@@ -0,0 +1,304 @@
1
+ import * as React from 'react';
2
+ import React__default, { ReactNode, ComponentType, ForwardRefExoticComponent } from 'react';
3
+ import { T as ThemeColors, a as ThemeConfig, P as ParsedClass, R as ResolvedStyle, S as StyleValue, F as FrameworkConfig, b as ResolvedConfig, c as ThemeMode } from './types-CV5vXnSH.js';
4
+ export { d as PluginAPI } from './types-CV5vXnSH.js';
5
+
6
+ declare const defaultColors: ThemeColors;
7
+ declare const defaultTheme: ThemeConfig;
8
+
9
+ declare function parseClass(className: string): ParsedClass | null;
10
+ /** Parse a space-separated class string into individual ParsedClass objects. */
11
+ declare function parseClasses(classString: string): ParsedClass[];
12
+
13
+ /**
14
+ * Resolve a class string to a ResolvedStyle object.
15
+ *
16
+ * The result groups styles by modifier key:
17
+ * - 'base' → always-applied styles
18
+ * - 'dark' → dark-mode styles
19
+ * - 'hover' → hover styles
20
+ * - 'dark:hover' → combined dark + hover
21
+ * - etc.
22
+ *
23
+ * Results are cached — repeated calls with the same string are O(1).
24
+ */
25
+ declare function resolve(classString: string, theme: ThemeConfig, darkMode?: 'attribute' | 'class' | 'media'): ResolvedStyle;
26
+ /**
27
+ * Flatten a ResolvedStyle into a single StyleValue for the given runtime state.
28
+ * Used by useStyles() and styled().
29
+ *
30
+ * @param resolved Output of resolve()
31
+ * @param isDark Whether dark mode is currently active
32
+ * @param state Interaction state flags
33
+ * @param breakpoints Active breakpoint names (sm, md, lg, xl, 2xl). On web,
34
+ * pass an empty Set — CSS @media rules handle responsive.
35
+ */
36
+ declare function flatten(resolved: ResolvedStyle, isDark: boolean, state?: {
37
+ hover?: boolean;
38
+ focus?: boolean;
39
+ pressed?: boolean;
40
+ active?: boolean;
41
+ disabled?: boolean;
42
+ checked?: boolean;
43
+ visited?: boolean;
44
+ placeholder?: boolean;
45
+ }, breakpoints?: Set<string>): StyleValue;
46
+
47
+ /**
48
+ * Load, merge, and cache the resolved config.
49
+ * Call resetConfig() to force a reload (e.g. in tests or after live update).
50
+ */
51
+ declare function getConfig(): ResolvedConfig;
52
+ declare function buildConfig(userConfig: FrameworkConfig): ResolvedConfig;
53
+ declare function updateConfig(userConfig: FrameworkConfig): void;
54
+ /**
55
+ * Like updateConfig, but only calls it when the config object reference has
56
+ * actually changed. Used by the Babel-injected IIFE so that:
57
+ * - multiple files with kbach classes don't re-run the update on every load
58
+ * - Fast Refresh DOES re-run when kbach.config.js changes (new module → new object)
59
+ */
60
+ declare function initConfig(userConfig: FrameworkConfig): void;
61
+
62
+ interface ThemeContextValue {
63
+ /** The user-selected mode ('light' | 'dark' | 'system') */
64
+ mode: ThemeMode;
65
+ /** The effective resolved mode (never 'system') */
66
+ resolvedMode: 'light' | 'dark';
67
+ /** Convenience boolean */
68
+ isDark: boolean;
69
+ /** Change the theme mode programmatically */
70
+ setMode: (mode: ThemeMode) => void;
71
+ /** Toggle between light and dark (ignores system) */
72
+ toggle: () => void;
73
+ /** The fully resolved framework config (theme values, darkMode strategy, etc.) */
74
+ config: ResolvedConfig;
75
+ }
76
+ declare const ThemeContext: React.Context<ThemeContextValue | null>;
77
+ declare function useTheme(): ThemeContextValue;
78
+ declare function useIsDark(): boolean;
79
+
80
+ interface ColorScale {
81
+ /** `colors.blue[6]` → raw hex string */
82
+ readonly [shade: number]: string;
83
+ /** `colors.blue['6/50']` → shade 6 at 50% opacity */
84
+ readonly [key: string]: string;
85
+ }
86
+ interface ColorsAPI {
87
+ /**
88
+ * Pass any CSS color through, optionally applying an opacity (0–100).
89
+ * - `colors.alpha('#3b82f6', 50)` → `'rgba(59,130,246,0.5)'`
90
+ * - `colors.alpha('rgb(0,0,0)', 10)` → `'rgba(0,0,0,0.1)'`
91
+ * - `colors.alpha('rgba(0,0,0,0.5)')` → `'rgba(0,0,0,0.5)'` (passthrough)
92
+ */
93
+ readonly alpha: (color: string, opacity?: number) => string;
94
+ [color: string]: any;
95
+ }
96
+ declare function wrapColors(rawColors: ThemeColors): ColorsAPI;
97
+ declare function useColors(): ColorsAPI;
98
+
99
+ interface ThemeProviderProps {
100
+ children: ReactNode;
101
+ /** Initial mode. Falls back to persisted value, then 'system'. */
102
+ defaultMode?: ThemeMode;
103
+ /**
104
+ * System color scheme for native `defaultMode="system"`.
105
+ *
106
+ * Pass the value of `useColorScheme()` from `react-native`. When importing
107
+ * `ThemeProvider` from `@kbach/native` this is handled automatically.
108
+ *
109
+ * @example
110
+ * ```tsx
111
+ * import { useColorScheme } from 'react-native';
112
+ * const colorScheme = useColorScheme();
113
+ * <ThemeProvider defaultMode="system" colorScheme={colorScheme}>…</ThemeProvider>
114
+ * ```
115
+ */
116
+ colorScheme?: 'light' | 'dark' | null;
117
+ /**
118
+ * Current window/screen width in pixels for responsive breakpoints.
119
+ * On web this is read from `window.innerWidth` automatically.
120
+ * When importing `ThemeProvider` from `@kbach/native` this is provided
121
+ * automatically from `useWindowDimensions()`.
122
+ */
123
+ windowWidth?: number;
124
+ /** Override the config (useful for per-tree config). Defaults to global getConfig(). */
125
+ config?: FrameworkConfig;
126
+ /** Disable persistence to localStorage */
127
+ disablePersistence?: boolean;
128
+ }
129
+ declare function ThemeProvider({ children, defaultMode, colorScheme, windowWidth: windowWidthProp, config: configOverride, disablePersistence, }: ThemeProviderProps): React__default.JSX.Element;
130
+
131
+ type ToggleVariant = 'button' | 'switch' | 'icon-button';
132
+ interface ThemeToggleProps {
133
+ /** Visual variant. Default: 'button' */
134
+ variant?: ToggleVariant;
135
+ /** Override label text (button variant) */
136
+ label?: string;
137
+ /** Custom light-mode label */
138
+ lightLabel?: string;
139
+ /** Custom dark-mode label */
140
+ darkLabel?: string;
141
+ /** Show system mode option */
142
+ includeSystem?: boolean;
143
+ /** Custom styles applied to the root container */
144
+ style?: object;
145
+ /** Custom styles for the label text */
146
+ labelStyle?: object;
147
+ }
148
+ /**
149
+ * Drop-in theme toggle. Works on web and React Native.
150
+ *
151
+ * ```tsx
152
+ * <ThemeToggle />
153
+ * <ThemeToggle variant="switch" />
154
+ * <ThemeToggle variant="icon-button" lightLabel="☀️" darkLabel="🌙" />
155
+ * ```
156
+ */
157
+ declare function ThemeToggle({ variant, label, lightLabel, darkLabel, includeSystem, style, labelStyle, }: ThemeToggleProps): React__default.JSX.Element;
158
+
159
+ interface StyledProps {
160
+ /** Additional utility classes applied on top of the base classes */
161
+ kb?: string;
162
+ /** Merged with resolved kb styles; applied last */
163
+ style?: StyleValue | StyleValue[];
164
+ }
165
+ type OmittedKeys = 'style';
166
+ /**
167
+ * Create a styled component from any React / React Native component.
168
+ *
169
+ * ```tsx
170
+ * const Card = styled(View, 'bg-white dark:bg-gray-800 rounded-xl p-4 shadow-md');
171
+ * const Button = styled(TouchableOpacity, 'bg-blue-500 pressed:bg-blue-700 dark:bg-blue-600 rounded-lg p-3');
172
+ *
173
+ * // Use it:
174
+ * <Card kb="mt-4">...</Card>
175
+ * <Button onPress={handlePress} kb="w-full" />
176
+ * ```
177
+ */
178
+ declare function styled<T extends ComponentType<any>>(Component: T, baseClasses?: string): ForwardRefExoticComponent<Omit<React__default.ComponentPropsWithRef<T>, OmittedKeys> & StyledProps>;
179
+
180
+ interface InteractionState {
181
+ hover?: boolean;
182
+ focus?: boolean;
183
+ /** Maps to 'pressed' and 'active' modifiers */
184
+ pressed?: boolean;
185
+ active?: boolean;
186
+ disabled?: boolean;
187
+ checked?: boolean;
188
+ visited?: boolean;
189
+ placeholder?: boolean;
190
+ }
191
+ /**
192
+ * Resolve a utility class string to a style object for the current theme + state.
193
+ *
194
+ * ```tsx
195
+ * // Basic usage
196
+ * const styles = useStyles('bg-white dark:bg-gray-900 p-4');
197
+ *
198
+ * // With interaction state
199
+ * const [pressed, setPressed] = useState(false);
200
+ * const styles = useStyles('bg-blue-500 pressed:bg-blue-700', { pressed });
201
+ *
202
+ * // Multiple class strings (merged left-to-right)
203
+ * const styles = useStyles(['bg-white p-4', 'dark:bg-gray-900 rounded-xl']);
204
+ * ```
205
+ */
206
+ declare function useStyles(classString: string | string[], state?: InteractionState): StyleValue;
207
+ /**
208
+ * Returns the full ResolvedStyle bucket map (base, dark, hover, …).
209
+ * Useful when you need to apply styles selectively or pass them to Animated.
210
+ */
211
+ declare function useResolvedStyle(classString: string | string[]): ResolvedStyle;
212
+
213
+ /**
214
+ * Subscribe to the global dark-mode store with React's concurrent-safe
215
+ * useSyncExternalStore so that any component using className/kb re-renders
216
+ * immediately when the theme changes — without needing ThemeContext.
217
+ */
218
+ declare function useGlobalDarkMode(): boolean;
219
+
220
+ /**
221
+ * Returns the name of the currently active breakpoint — the largest breakpoint
222
+ * whose min-width the window satisfies, or `'xs'` when below all breakpoints.
223
+ *
224
+ * ```ts
225
+ * const bp = useBreakpoint(); // 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'
226
+ * ```
227
+ */
228
+ declare function useBreakpoint(): string;
229
+ /**
230
+ * Returns a record of boolean flags for each breakpoint — `true` when the
231
+ * window width satisfies that breakpoint's min-width threshold.
232
+ *
233
+ * ```ts
234
+ * const { sm, md, lg } = useResponsive();
235
+ * const padding = lg ? 32 : sm ? 16 : 8;
236
+ * ```
237
+ */
238
+ declare function useResponsive(): Record<string, boolean>;
239
+
240
+ interface InteractiveWrapperProps {
241
+ /** The real component to render (View, TouchableOpacity, div, a third-party button…) */
242
+ Component: React__default.ComponentType<any> | string;
243
+ /** Pre-resolved style buckets from resolve() */
244
+ resolvedStyle: ResolvedStyle;
245
+ /** On web: original class string so CSS pseudo-rules still fire */
246
+ className?: string;
247
+ /** Extra style prop passed by the user */
248
+ style?: StyleValue | StyleValue[];
249
+ children?: React__default.ReactNode;
250
+ onPressIn?: (...args: any[]) => void;
251
+ onPressOut?: (...args: any[]) => void;
252
+ onPointerDown?: (...args: any[]) => void;
253
+ onPointerUp?: (...args: any[]) => void;
254
+ onPointerLeave?: (...args: any[]) => void;
255
+ onMouseEnter?: (...args: any[]) => void;
256
+ onMouseLeave?: (...args: any[]) => void;
257
+ onFocus?: (...args: any[]) => void;
258
+ onBlur?: (...args: any[]) => void;
259
+ }
260
+ /**
261
+ * Thin wrapper rendered automatically by the JSX runtime whenever a className/kb
262
+ * string contains interactive modifiers (hover:, pressed:, focus:, active:, …).
263
+ *
264
+ * Manages interaction state locally and flattens the correct style bucket on
265
+ * every render. The wrapped component sees a plain `style` prop — it never
266
+ * knows it was wrapped.
267
+ *
268
+ * Refs are forwarded so the host component's imperative API still works.
269
+ */
270
+ declare const InteractiveWrapper: React__default.ForwardRefExoticComponent<InteractiveWrapperProps & React__default.RefAttributes<unknown>>;
271
+
272
+ /**
273
+ * Resolve a utility class string outside of a React component.
274
+ *
275
+ * On **native** — returns a StyleValue (style object) for the given mode.
276
+ * On **web** — injects CSS and returns the original class string (use as className).
277
+ *
278
+ * ```ts
279
+ * // Inside a component use useStyles() instead.
280
+ * // kb() is useful for StyleSheet.create() calls and static values.
281
+ *
282
+ * const styles = StyleSheet.create({
283
+ * container: kb('flex-1 bg-white p-4') as any,
284
+ * });
285
+ *
286
+ * // Web: use as className
287
+ * <div className={kb('bg-white dark:bg-gray-900 p-4') as string} />
288
+ * ```
289
+ *
290
+ * @param classString Space-separated utility classes
291
+ * @param isDark Whether dark mode is active (default: false)
292
+ */
293
+ declare function kb(classString: string, isDark?: boolean): StyleValue | string;
294
+ /**
295
+ * Conditionally join class names. Falsy values are ignored.
296
+ *
297
+ * ```ts
298
+ * cx('bg-white p-4', isActive && 'border-2 border-blue-500', undefined)
299
+ * // → 'bg-white p-4 border-2 border-blue-500'
300
+ * ```
301
+ */
302
+ declare function cx(...classes: Array<string | false | null | undefined>): string;
303
+
304
+ 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, parseClass, parseClasses, resolve, styled, updateConfig, useBreakpoint, useColors, useGlobalDarkMode, useIsDark, useResolvedStyle, useResponsive, useStyles, useTheme, wrapColors };
@@ -0,0 +1,19 @@
1
+ import { ReactElement } from 'react';
2
+ export { Fragment } from 'react';
3
+
4
+ /**
5
+ * @kbach/react/jsx-dev-runtime
6
+ *
7
+ * Development variant of the custom JSX runtime.
8
+ * Babel uses jsxDEV (instead of jsx/jsxs) in dev builds.
9
+ * We forward isStaticChildren so React's dev-mode key-warning suppression
10
+ * works correctly for compile-time static child arrays.
11
+ */
12
+
13
+ declare function jsxDEV(type: unknown, props: Record<string, unknown> | null, key?: string, isStaticChildren?: boolean, _source?: {
14
+ fileName: string;
15
+ lineNumber: number;
16
+ columnNumber: number;
17
+ }, _self?: unknown): ReactElement;
18
+
19
+ export { jsxDEV };
@@ -0,0 +1,19 @@
1
+ import { ReactElement } from 'react';
2
+ export { Fragment } from 'react';
3
+
4
+ /**
5
+ * @kbach/react/jsx-dev-runtime
6
+ *
7
+ * Development variant of the custom JSX runtime.
8
+ * Babel uses jsxDEV (instead of jsx/jsxs) in dev builds.
9
+ * We forward isStaticChildren so React's dev-mode key-warning suppression
10
+ * works correctly for compile-time static child arrays.
11
+ */
12
+
13
+ declare function jsxDEV(type: unknown, props: Record<string, unknown> | null, key?: string, isStaticChildren?: boolean, _source?: {
14
+ fileName: string;
15
+ lineNumber: number;
16
+ columnNumber: number;
17
+ }, _self?: unknown): ReactElement;
18
+
19
+ export { jsxDEV };
@@ -0,0 +1,17 @@
1
+ import { ReactElement } from 'react';
2
+ export { Fragment, JSX } from 'react';
3
+
4
+ /**
5
+ * @kbach/react/jsx-runtime
6
+ *
7
+ * Drop-in replacement for react/jsx-runtime.
8
+ * Intercepts `className` and `kb` props on EVERY JSX element — React Native
9
+ * built-ins, HTML elements on web, and any third-party library component.
10
+ */
11
+
12
+ /** jsx() — elements with 0–1 child or dynamic key. */
13
+ declare function jsx(type: unknown, props: Record<string, unknown> | null, key?: string): ReactElement;
14
+ /** jsxs() — elements with 2+ static children. Children array is compile-time stable. */
15
+ declare function jsxs(type: unknown, props: Record<string, unknown> | null, key?: string): ReactElement;
16
+
17
+ export { jsx, jsxs };
@@ -0,0 +1,17 @@
1
+ import { ReactElement } from 'react';
2
+ export { Fragment, JSX } from 'react';
3
+
4
+ /**
5
+ * @kbach/react/jsx-runtime
6
+ *
7
+ * Drop-in replacement for react/jsx-runtime.
8
+ * Intercepts `className` and `kb` props on EVERY JSX element — React Native
9
+ * built-ins, HTML elements on web, and any third-party library component.
10
+ */
11
+
12
+ /** jsx() — elements with 0–1 child or dynamic key. */
13
+ declare function jsx(type: unknown, props: Record<string, unknown> | null, key?: string): ReactElement;
14
+ /** jsxs() — elements with 2+ static children. Children array is compile-time stable. */
15
+ declare function jsxs(type: unknown, props: Record<string, unknown> | null, key?: string): ReactElement;
16
+
17
+ export { jsx, jsxs };
@@ -0,0 +1,70 @@
1
+ type ThemeMode = 'light' | 'dark' | 'system';
2
+ interface StyleValue {
3
+ [key: string]: string | number | undefined | null | StyleValue | unknown[];
4
+ }
5
+ interface ParsedClass {
6
+ /** The original class string, e.g. "dark:hover:bg-[#fff]" */
7
+ original: string;
8
+ /** Up to 3 modifier prefixes, e.g. ['dark', 'hover'] */
9
+ modifiers: string[];
10
+ /** Whether a leading `-` was present for negative values */
11
+ negative: boolean;
12
+ /** Whether a leading `!` was present — applies !important to all CSS declarations */
13
+ important: boolean;
14
+ /** The utility name, e.g. 'bg', 'p', 'text' */
15
+ utility: string;
16
+ /** The resolved value, e.g. 'white', '#fff', '4' */
17
+ value: string;
18
+ /** Whether the value was specified with bracket notation [value] */
19
+ isArbitrary: boolean;
20
+ }
21
+ interface ResolvedStyle {
22
+ /** Base styles applied unconditionally */
23
+ base?: StyleValue;
24
+ /** Styles keyed by modifier or modifier combo, e.g. 'dark', 'hover', 'dark:hover' */
25
+ [modifierKey: string]: StyleValue | undefined;
26
+ }
27
+ type ColorShades = Record<string, string>;
28
+ type ThemeColors = Record<string, string | ColorShades>;
29
+ type ThemeSpacing = Record<string, number | string>;
30
+ interface ThemeConfig {
31
+ colors: ThemeColors;
32
+ spacing: ThemeSpacing;
33
+ fontSize: Record<string, number | string>;
34
+ fontFamily: Record<string, string | string[]>;
35
+ fontWeight: Record<string, string | number>;
36
+ borderRadius: Record<string, number | string>;
37
+ borderWidth: Record<string, number>;
38
+ opacity: Record<string, number>;
39
+ lineHeight: Record<string, number | string>;
40
+ letterSpacing: Record<string, number | string>;
41
+ zIndex: Record<string, number | string>;
42
+ flex: Record<string, number>;
43
+ shadow: Record<string, StyleValue>;
44
+ screens: Record<string, string | number>;
45
+ [key: string]: unknown;
46
+ }
47
+ type DarkMode = 'attribute' | 'class' | 'media';
48
+ interface PluginAPI {
49
+ addUtility(name: string, styles: StyleValue): void;
50
+ addVariant(name: string, selector: string): void;
51
+ theme(path: string, defaultValue?: unknown): unknown;
52
+ e(className: string): string;
53
+ }
54
+ interface FrameworkConfig {
55
+ darkMode?: DarkMode;
56
+ theme?: Partial<ThemeConfig>;
57
+ /** Additive theme extension — accepts either `extend.theme.X` or `extend.X` directly. */
58
+ extend?: {
59
+ theme?: Partial<ThemeConfig>;
60
+ } & Partial<ThemeConfig>;
61
+ plugins?: Array<(api: PluginAPI) => void>;
62
+ content?: string[];
63
+ }
64
+ interface ResolvedConfig {
65
+ darkMode: DarkMode;
66
+ theme: ThemeConfig;
67
+ plugins: Array<(api: PluginAPI) => void>;
68
+ }
69
+
70
+ export type { FrameworkConfig as F, ParsedClass as P, ResolvedStyle as R, StyleValue as S, ThemeColors as T, ThemeConfig as a, ResolvedConfig as b, ThemeMode as c, PluginAPI as d };
@@ -0,0 +1,70 @@
1
+ type ThemeMode = 'light' | 'dark' | 'system';
2
+ interface StyleValue {
3
+ [key: string]: string | number | undefined | null | StyleValue | unknown[];
4
+ }
5
+ interface ParsedClass {
6
+ /** The original class string, e.g. "dark:hover:bg-[#fff]" */
7
+ original: string;
8
+ /** Up to 3 modifier prefixes, e.g. ['dark', 'hover'] */
9
+ modifiers: string[];
10
+ /** Whether a leading `-` was present for negative values */
11
+ negative: boolean;
12
+ /** Whether a leading `!` was present — applies !important to all CSS declarations */
13
+ important: boolean;
14
+ /** The utility name, e.g. 'bg', 'p', 'text' */
15
+ utility: string;
16
+ /** The resolved value, e.g. 'white', '#fff', '4' */
17
+ value: string;
18
+ /** Whether the value was specified with bracket notation [value] */
19
+ isArbitrary: boolean;
20
+ }
21
+ interface ResolvedStyle {
22
+ /** Base styles applied unconditionally */
23
+ base?: StyleValue;
24
+ /** Styles keyed by modifier or modifier combo, e.g. 'dark', 'hover', 'dark:hover' */
25
+ [modifierKey: string]: StyleValue | undefined;
26
+ }
27
+ type ColorShades = Record<string, string>;
28
+ type ThemeColors = Record<string, string | ColorShades>;
29
+ type ThemeSpacing = Record<string, number | string>;
30
+ interface ThemeConfig {
31
+ colors: ThemeColors;
32
+ spacing: ThemeSpacing;
33
+ fontSize: Record<string, number | string>;
34
+ fontFamily: Record<string, string | string[]>;
35
+ fontWeight: Record<string, string | number>;
36
+ borderRadius: Record<string, number | string>;
37
+ borderWidth: Record<string, number>;
38
+ opacity: Record<string, number>;
39
+ lineHeight: Record<string, number | string>;
40
+ letterSpacing: Record<string, number | string>;
41
+ zIndex: Record<string, number | string>;
42
+ flex: Record<string, number>;
43
+ shadow: Record<string, StyleValue>;
44
+ screens: Record<string, string | number>;
45
+ [key: string]: unknown;
46
+ }
47
+ type DarkMode = 'attribute' | 'class' | 'media';
48
+ interface PluginAPI {
49
+ addUtility(name: string, styles: StyleValue): void;
50
+ addVariant(name: string, selector: string): void;
51
+ theme(path: string, defaultValue?: unknown): unknown;
52
+ e(className: string): string;
53
+ }
54
+ interface FrameworkConfig {
55
+ darkMode?: DarkMode;
56
+ theme?: Partial<ThemeConfig>;
57
+ /** Additive theme extension — accepts either `extend.theme.X` or `extend.X` directly. */
58
+ extend?: {
59
+ theme?: Partial<ThemeConfig>;
60
+ } & Partial<ThemeConfig>;
61
+ plugins?: Array<(api: PluginAPI) => void>;
62
+ content?: string[];
63
+ }
64
+ interface ResolvedConfig {
65
+ darkMode: DarkMode;
66
+ theme: ThemeConfig;
67
+ plugins: Array<(api: PluginAPI) => void>;
68
+ }
69
+
70
+ export type { FrameworkConfig as F, ParsedClass as P, ResolvedStyle as R, StyleValue as S, ThemeColors as T, ThemeConfig as a, ResolvedConfig as b, ThemeMode as c, PluginAPI as d };
@@ -0,0 +1,8 @@
1
+ // TypeScript declarations for the Kbach Vite plugin virtual module.
2
+ // Add this to your tsconfig "types" array or via a triple-slash reference:
3
+ // /// <reference types="@kbach/react/vite/client" />
4
+
5
+ declare module 'virtual:kbach/styles.css' {
6
+ const css: string;
7
+ export default css;
8
+ }
@@ -0,0 +1,8 @@
1
+ // TypeScript declarations for the Kbach Vite plugin virtual module.
2
+ // Add this to your tsconfig "types" array or via a triple-slash reference:
3
+ // /// <reference types="@kbach/react/vite/client" />
4
+
5
+ declare module 'virtual:kbach/styles.css' {
6
+ const css: string;
7
+ export default css;
8
+ }
@@ -0,0 +1,7 @@
1
+ import { Plugin } from 'vite';
2
+ import { F as FrameworkConfig } from './types-CV5vXnSH.mjs';
3
+
4
+ declare const VIRTUAL_ID = "virtual:kbach/styles.css";
5
+ declare function kbach(userConfig?: FrameworkConfig): Plugin;
6
+
7
+ export { VIRTUAL_ID, kbach };
@@ -0,0 +1,7 @@
1
+ import { Plugin } from 'vite';
2
+ import { F as FrameworkConfig } from './types-CV5vXnSH.js';
3
+
4
+ declare const VIRTUAL_ID = "virtual:kbach/styles.css";
5
+ declare function kbach(userConfig?: FrameworkConfig): Plugin;
6
+
7
+ export { VIRTUAL_ID, kbach };
@@ -3388,7 +3388,7 @@ function formatKbachCSS(tokenCSS, theme) {
3388
3388
  const colorVars = buildColorVarMap(theme, allRaw);
3389
3389
  function applyVars(css) {
3390
3390
  for (const [val, varName] of colorVars) {
3391
- css = css.replaceAll(val, `var(${varName})`);
3391
+ css = css.split(val).join(`var(${varName})`);
3392
3392
  }
3393
3393
  return css;
3394
3394
  }
@@ -46,7 +46,7 @@ function formatKbachCSS(tokenCSS, theme) {
46
46
  const colorVars = buildColorVarMap(theme, allRaw);
47
47
  function applyVars(css) {
48
48
  for (const [val, varName] of colorVars) {
49
- css = css.replaceAll(val, `var(${varName})`);
49
+ css = css.split(val).join(`var(${varName})`);
50
50
  }
51
51
  return css;
52
52
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kbach/react",
3
- "version": "0.5.27",
3
+ "version": "0.5.28",
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",