@kbach/react 0.6.24 → 0.6.26

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/dist/index.d.ts CHANGED
@@ -1,224 +1,10 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { ReactNode, ComponentType, ForwardRefExoticComponent } from 'react';
3
+ import * as __core from './core';
4
+ import { ThemeMode, ResolvedConfig, DefaultColorName, defaultColors, ThemeColors, DefaultSpacingKey, ThemeSpacing, FrameworkConfig, StyleValue, ResolvedStyle } from './core';
5
+ export { DefaultColorName, DefaultSpacingKey, FrameworkConfig, ParsedClass, PluginAPI, ResolvedConfig, ResolvedStyle, StyleValue, ThemeConfig, ThemeMode, buildConfig, clearCache, defaultColors, defaultTheme, disableRuntimeCSS, flatten, getConfig, initConfig, normalizeClassString, parseClass, parseClasses, resolve, setResolveTarget, splitClassTokens, updateConfig } from './core';
3
6
  export { r as registerWebElement } from './web-substitute-CfpYFnE7.js';
4
7
 
5
- /**
6
- * Unified modifier registry — single source of truth for ALL modifier behavior.
7
- *
8
- * Adding a new modifier requires editing ONLY this file:
9
- * 1. Add an entry to BUILTIN_MODIFIERS with its CSS and JS behavior.
10
- * 2. Done — parser, resolver, CSS generator, and JSX runtime all derive
11
- * their behavior from this data automatically.
12
- *
13
- * Plugin authors can register custom modifiers via registerModifier().
14
- */
15
- interface ModifierDef {
16
- /** CSS pseudo-class or pseudo-element appended to the selector (e.g. ':hover', '::before') */
17
- pseudo?: string;
18
- /** Ancestor selector prefix INCLUDING trailing space (e.g. '.group:hover ', '.peer:focus ~ ') */
19
- ancestorSelector?: string;
20
- /** Directionality attribute selector prefix INCLUDING trailing space (e.g. '[dir="rtl"] ') */
21
- dirSelector?: string;
22
- /** @media query body WITHOUT the '@media ' prefix (e.g. 'print', '(orientation: landscape)') */
23
- mediaQuery?: string;
24
- /** Dark/light mode scheme — triggers the configured darkMode strategy in CSS output */
25
- darkScheme?: 'dark' | 'light';
26
- /** True for responsive modifiers — wraps in @media (min-width: theme.screens[name]) */
27
- isResponsive?: boolean;
28
- /**
29
- * Forces !important on all declarations in the generated CSS rule.
30
- * Applied automatically for structural / ancestor / media modifiers that must
31
- * win over base inline styles.
32
- */
33
- forcesImportant?: boolean;
34
- /**
35
- * How the JSX runtime routes this modifier:
36
- * 'interactive' — managed by InteractiveWrapper (hover, focus, pressed, …)
37
- * 'mode' — managed by DarkWrapper (dark, light, not-dark, …)
38
- * 'responsive' — managed by DarkWrapper (sm, md, lg, xl, 2xl)
39
- * 'css-only' — CSS injection only; matchModifier always returns false
40
- */
41
- jsBehavior: 'interactive' | 'mode' | 'responsive' | 'css-only';
42
- /**
43
- * Evaluates whether this modifier's condition is met at runtime.
44
- * Omit for 'css-only' modifiers — they never apply as inline styles.
45
- */
46
- jsMatch?: (isDark: boolean, state: Record<string, boolean | undefined>, breakpoints: Set<string>) => boolean;
47
- }
48
-
49
- type ThemeMode = 'light' | 'dark' | 'system';
50
- interface StyleValue {
51
- [key: string]: string | number | undefined | null | StyleValue | StyleValue[];
52
- }
53
- interface ParsedClass {
54
- /** The original class string, e.g. "dark:hover:bg-[#fff]" */
55
- original: string;
56
- /** Up to 3 modifier prefixes, e.g. ['dark', 'hover'] */
57
- modifiers: string[];
58
- /** Whether a leading `-` was present for negative values */
59
- negative: boolean;
60
- /** Whether a leading `!` was present — applies !important to all CSS declarations */
61
- important: boolean;
62
- /** The utility name, e.g. 'bg', 'p', 'text' */
63
- utility: string;
64
- /** The resolved value, e.g. 'white', '#fff', '4' */
65
- value: string;
66
- /** Whether the value was specified with bracket notation [value] */
67
- isArbitrary: boolean;
68
- }
69
- interface ResolvedStyle {
70
- /** Base styles applied unconditionally */
71
- base?: StyleValue;
72
- /** Styles keyed by modifier or modifier combo, e.g. 'dark', 'hover', 'dark:hover' */
73
- [modifierKey: string]: StyleValue | undefined;
74
- }
75
- type ColorShades = Record<string, string>;
76
- type ThemeColors = Record<string, string | ColorShades>;
77
- type ThemeSpacing = Record<string, number | string>;
78
- interface ThemeConfig {
79
- colors: ThemeColors;
80
- spacing: ThemeSpacing;
81
- fontSize: Record<string, number | string>;
82
- fontFamily: Record<string, string | string[]>;
83
- fontWeight: Record<string, string | number>;
84
- borderRadius: Record<string, number | string>;
85
- borderWidth: Record<string, number>;
86
- opacity: Record<string, number>;
87
- lineHeight: Record<string, number | string>;
88
- letterSpacing: Record<string, number | string>;
89
- zIndex: Record<string, number | string>;
90
- flex: Record<string, number | string>;
91
- shadow: Record<string, StyleValue>;
92
- screens: Record<string, string | number>;
93
- /**
94
- * Custom @keyframes, web only. Each key is a keyframe name, its value maps
95
- * percentage/from/to selectors to a plain CSS declaration object (camelCase
96
- * properties, same shape as an inline style object):
97
- * keyframes: { wiggle: { '0%, 100%': { transform: 'rotate(-3deg)' }, '50%': { transform: 'rotate(3deg)' } } }
98
- * Referenced from `animation` below, or directly via animate-[wiggle_1s_ease-in-out].
99
- */
100
- keyframes: Record<string, Record<string, StyleValue>>;
101
- /**
102
- * Named animation shorthands built on `keyframes` above, referenced via
103
- * animate-{name} (e.g. animate-wiggle):
104
- * animation: { wiggle: 'wiggle 1s ease-in-out infinite' }
105
- * The first word must match a `keyframes` key so its @keyframes rule can be
106
- * injected alongside the animation — a name with no matching keyframes entry
107
- * still sets the `animation` CSS property, it just won't animate anything.
108
- */
109
- animation: Record<string, string>;
110
- [key: string]: unknown;
111
- }
112
- /**
113
- * 'class' — toggles .dark class on <html>
114
- * 'media' — uses prefers-color-scheme media query
115
- * 'attribute' — uses data-theme="dark" attribute on <html>
116
- */
117
- type DarkMode = 'attribute' | 'class' | 'media';
118
- interface PluginAPI {
119
- addUtility(name: string, styles: StyleValue): void;
120
- /**
121
- * Register a custom variant.
122
- *
123
- * Pass a CSS selector string for simple cases — it is automatically
124
- * converted into a ModifierDef that generates correct CSS rules:
125
- * addVariant('hocus', ':hover, :focus') // pseudo
126
- * addVariant('supports-grid', '@media (display: grid)') // media
127
- * addVariant('dark-green', '.dark-green') // ancestor selector
128
- *
129
- * Pass a full ModifierDef object for advanced control (e.g. JS-trackable
130
- * interactive variants with custom jsMatch logic).
131
- */
132
- addVariant(name: string, selectorOrDef: string | ModifierDef): void;
133
- theme(path: string, defaultValue?: unknown): unknown;
134
- e(className: string): string;
135
- }
136
- interface FrameworkConfig {
137
- darkMode?: DarkMode;
138
- theme?: Partial<ThemeConfig>;
139
- /** Additive theme extension — accepts either `extend.theme.X` or `extend.X` directly. */
140
- extend?: {
141
- theme?: Partial<ThemeConfig>;
142
- } & Partial<ThemeConfig>;
143
- plugins?: Array<(api: PluginAPI) => void>;
144
- content?: string[];
145
- }
146
- interface ResolvedConfig {
147
- darkMode: DarkMode;
148
- theme: ThemeConfig;
149
- plugins: Array<(api: PluginAPI) => void>;
150
- }
151
-
152
- declare const defaultColors: ThemeColors;
153
- declare const defaultTheme: ThemeConfig;
154
-
155
- declare function setResolveTarget(target: 'web' | 'native' | null): void;
156
-
157
- declare function parseClass(className: string): ParsedClass | null;
158
- /**
159
- * Split a class string into tokens. Whitespace at bracket depth > 0 is STRIPPED
160
- * (not just skipped) so that arbitrary values like rgb(41, 172, 15) become valid
161
- * CSS class name tokens: bg-[rgb(41,172,15)].
162
- */
163
- declare function splitClassTokens(classString: string): string[];
164
- /**
165
- * Normalize a full class string so it is safe to use as an HTML className value.
166
- * Strips spaces inside brackets: "bg-[rgb(41, 172, 15)] p-4" → "bg-[rgb(41,172,15)] p-4"
167
- */
168
- declare function normalizeClassString(classString: string): string;
169
- /** Parse a space-separated class string into individual ParsedClass objects. */
170
- declare function parseClasses(classString: string): ParsedClass[];
171
-
172
- declare function disableRuntimeCSS(): void;
173
- /**
174
- * Resolve a class string to a ResolvedStyle object.
175
- *
176
- * Results are cached per (theme, classString, darkMode) — repeated calls with
177
- * the same arguments are O(1). Different theme objects each get their own
178
- * cache so concurrent ThemeProviders with different configs are always correct.
179
- */
180
- declare function resolve(classString: string, theme: ThemeConfig, darkMode?: 'attribute' | 'class' | 'media'): ResolvedStyle;
181
- /**
182
- * Flatten a ResolvedStyle into a single StyleValue for the current runtime state.
183
- * Used by useStyles() and styled().
184
- *
185
- * The sort step is memoized per resolved object reference (#6) — when resolve()
186
- * returns a cached object, getSortedEntries() is O(1) on all subsequent calls.
187
- */
188
- declare function flatten(resolved: ResolvedStyle, isDark: boolean, state?: {
189
- hover?: boolean;
190
- focus?: boolean;
191
- pressed?: boolean;
192
- active?: boolean;
193
- disabled?: boolean;
194
- checked?: boolean;
195
- visited?: boolean;
196
- placeholder?: boolean;
197
- }, breakpoints?: Set<string>): StyleValue;
198
- /**
199
- * Clear CSS injection state so stale rules are re-injected when the theme changes.
200
- *
201
- * The per-theme style cache (WeakMap) does not need to be cleared manually:
202
- * updateConfig() creates a new theme object, making the old cache entry
203
- * automatically unreachable for GC.
204
- */
205
- declare function clearCache(): void;
206
-
207
- /**
208
- * Load, merge, and cache the resolved config.
209
- * Call resetConfig() to force a reload (e.g. in tests or after live update).
210
- */
211
- declare function getConfig(): ResolvedConfig;
212
- declare function buildConfig(userConfig: FrameworkConfig): ResolvedConfig;
213
- declare function updateConfig(userConfig: FrameworkConfig): void;
214
- /**
215
- * Like updateConfig, but only calls it when the config object reference has
216
- * actually changed. Used by the Babel-injected IIFE so that:
217
- * - multiple files with kbach classes don't re-run the update on every load
218
- * - Fast Refresh DOES re-run when kbach.config.js changes (new module → new object)
219
- */
220
- declare function initConfig(userConfig: FrameworkConfig): void;
221
-
222
8
  interface ThemeContextValue {
223
9
  /** The user-selected mode ('light' | 'dark' | 'system') */
224
10
  mode: ThemeMode;
@@ -243,7 +29,19 @@ interface ColorScale {
243
29
  /** `colors.blue['6/50']` → shade 6 at 50% opacity */
244
30
  readonly [key: string]: string;
245
31
  }
246
- interface ColorsAPI {
32
+ type ColorValueFor<K extends string> = K extends keyof typeof defaultColors ? (typeof defaultColors)[K] extends string ? string : ColorScale : ColorScale | string;
33
+ /**
34
+ * `ColorName` defaults to the built-in theme's color names (`DefaultColorName`,
35
+ * derived from `defaultColors` in core/theme.ts), so `useColors()` gets full
36
+ * autocomplete and typo-catching out of the box for any project on the default
37
+ * theme. A customized `kbach.config.js` isn't visible to TypeScript (it's a
38
+ * plain .js file loaded at runtime, not a statically-analyzed module), so a
39
+ * project with extra colors needs to widen the type parameter explicitly:
40
+ * `useColors<DefaultColorName | 'brand'>()`.
41
+ */
42
+ type ColorsAPI<ColorName extends string = DefaultColorName> = {
43
+ readonly [K in ColorName]: ColorValueFor<K>;
44
+ } & {
247
45
  /**
248
46
  * Pass any CSS color through, optionally applying an opacity (0–100).
249
47
  * - `colors.alpha('#3b82f6', 50)` → `'rgba(59,130,246,0.5)'`
@@ -251,10 +49,38 @@ interface ColorsAPI {
251
49
  * - `colors.alpha('rgba(0,0,0,0.5)')` → `'rgba(0,0,0,0.5)'` (passthrough)
252
50
  */
253
51
  readonly alpha: (color: string, opacity?: number) => string;
254
- [color: string]: any;
255
- }
256
- declare function wrapColors(rawColors: ThemeColors): ColorsAPI;
257
- declare function useColors(): ColorsAPI;
52
+ };
53
+ declare function wrapColors<ColorName extends string = DefaultColorName>(rawColors: ThemeColors): ColorsAPI<ColorName>;
54
+ declare function useColors<ColorName extends string = DefaultColorName>(): ColorsAPI<ColorName>;
55
+
56
+ /**
57
+ * `SpacingKey` defaults to the built-in theme's spacing keys (`DefaultSpacingKey`,
58
+ * derived from `defaultTheme.spacing` in core/theme.ts), so `useSpacing()` gets
59
+ * full autocomplete and typo-catching out of the box for any project on the
60
+ * default scale. A customized `kbach.config.js` isn't visible to TypeScript
61
+ * (it's a plain .js file loaded at runtime, not a statically-analyzed module),
62
+ * so a project with extra spacing keys needs to widen the type parameter
63
+ * explicitly: `useSpacing<DefaultSpacingKey | '18'>()`.
64
+ */
65
+ type SpacingAPI<SpacingKey extends string = DefaultSpacingKey> = {
66
+ readonly [K in SpacingKey]: number | string;
67
+ };
68
+ declare function wrapSpacing<SpacingKey extends string = DefaultSpacingKey>(rawSpacing: ThemeSpacing): SpacingAPI<SpacingKey>;
69
+ /**
70
+ * Returns the active theme's spacing scale as a typed, autocomplete-friendly
71
+ * object — useful anywhere a raw JS number/string is needed instead of a
72
+ * className (Animated API distances, chart dimensions, FlatList separator
73
+ * heights, etc.). Values match exactly what `p-`/`m-`/`w-`/`h-`/`gap-` and
74
+ * other spacing-scale utilities resolve to.
75
+ *
76
+ * ```ts
77
+ * const spacing = useSpacing();
78
+ * spacing[4] // 16
79
+ * spacing.full // '100%'
80
+ * spacing['1/2'] // '50%'
81
+ * ```
82
+ */
83
+ declare function useSpacing<SpacingKey extends string = DefaultSpacingKey>(): SpacingAPI<SpacingKey>;
258
84
 
259
85
  interface ThemeProviderProps {
260
86
  children: ReactNode;
@@ -358,7 +184,7 @@ declare function useStyles(classString: string | string[], state?: InteractionSt
358
184
  * Returns the full ResolvedStyle bucket map (base, dark, hover, …).
359
185
  * Useful when you need to apply styles selectively or pass them to Animated.
360
186
  */
361
- declare function useResolvedStyle(classString: string | string[]): ResolvedStyle;
187
+ declare function useResolvedStyle(classString: string | string[]): __core.ResolvedStyle;
362
188
 
363
189
  /**
364
190
  * Subscribe to the global dark-mode store with React's concurrent-safe
@@ -452,4 +278,4 @@ declare function kb(classString: string, isDark?: boolean): StyleValue | string;
452
278
  */
453
279
  declare function cx(...classes: Array<string | false | null | undefined>): string;
454
280
 
455
- export { type ColorScale, type ColorsAPI, type FrameworkConfig, type InteractionState, InteractiveWrapper, type InteractiveWrapperProps, KbachReset, type ParsedClass, type PluginAPI, type ResolvedConfig, type ResolvedStyle, type StyleValue, type StyledProps, type ThemeConfig, ThemeContext, type ThemeContextValue, type ThemeMode, ThemeProvider, type ThemeProviderProps, buildConfig, clearCache, cx, defaultColors, defaultTheme, disableRuntimeCSS, flatten, getConfig, initConfig, kb, normalizeClassString, parseClass, parseClasses, resolve, setResolveTarget, splitClassTokens, styled, updateConfig, useBreakpoint, useColors, useGlobalDarkMode, useIsDark, useResolvedStyle, useResponsive, useStyles, useTheme, wrapColors };
281
+ export { type ColorScale, type ColorsAPI, type InteractionState, InteractiveWrapper, type InteractiveWrapperProps, KbachReset, type SpacingAPI, type StyledProps, ThemeContext, type ThemeContextValue, ThemeProvider, type ThemeProviderProps, cx, kb, styled, useBreakpoint, useColors, useGlobalDarkMode, useIsDark, useResolvedStyle, useResponsive, useSpacing, useStyles, useTheme, wrapColors, wrapSpacing };