@kbach/ui 0.1.0-beta.7 → 1.0.0-beta.1

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.mjs CHANGED
@@ -1,601 +1,30 @@
1
- 'use client';
2
- import {
3
- BASE_RESET,
4
- EMPTY_BREAKPOINTS,
5
- InteractiveWrapper,
6
- RESET_STYLE_ID,
7
- __require,
8
- buildConfig,
9
- chain,
10
- clearCache,
11
- composeNativeStyle,
12
- defaultColors,
13
- defaultTheme,
14
- disableRuntimeCSS,
15
- flatten,
16
- generateKbachTypesDts,
17
- getActiveBreakpoints,
18
- getConfig,
19
- getEffectiveIsWeb,
20
- getGlobalScreens,
21
- getGlobalSingleton,
22
- getImpliedRNClasses,
23
- getWebTag,
24
- hasInteractiveBuckets,
25
- hasResponsiveBuckets,
26
- initConfig,
27
- isModeAwareColor,
28
- isNative,
29
- isRuntimeCSSDisabled,
30
- isWeb,
31
- kbachWarn,
32
- normalizeClassString,
33
- onConfigChange,
34
- parseClass,
35
- parseClasses,
36
- parseHexRgb,
37
- registerWebElement,
38
- resetConfig,
39
- resolve,
40
- setGlobalDarkMode,
41
- setGlobalWidth,
42
- setResolveTarget,
43
- splitClassTokens,
44
- syncGlobalDarkMode,
45
- syncGlobalScreens,
46
- syncGlobalWidth,
47
- transformToWebProps,
48
- updateConfig,
49
- useConditionalGlobalDarkMode,
50
- useConditionalWidth,
51
- useGlobalDarkMode,
52
- useGlobalWidth,
53
- useSyncExternalStore
54
- } from "./chunk-LY753XBX.mjs";
55
-
56
- // src/context.tsx
57
- import { createContext, useContext } from "react";
58
- var ThemeContext = getGlobalSingleton("themeContext", () => createContext(null));
59
- function useTheme() {
60
- const ctx = useContext(ThemeContext);
61
- if (!ctx) {
62
- throw new Error(
63
- "[Kbach] useTheme() must be called inside a <ThemeProvider>. Wrap your app root with <ThemeProvider>."
64
- );
65
- }
66
- return ctx;
67
- }
68
- function useIsDark() {
69
- return useTheme().isDark;
70
- }
71
-
72
- // src/useColors.ts
73
- import { useMemo } from "react";
74
- function applyOpacity(color, opacity) {
75
- const a = Math.max(0, Math.min(1, opacity / 100));
76
- if (color.startsWith("#")) {
77
- const rgb = parseHexRgb(color);
78
- if (!rgb) return color;
79
- const [r, g, b] = rgb;
80
- return `rgba(${r},${g},${b},${a})`;
81
- }
82
- if (color.startsWith("rgb(")) return color.replace("rgb(", "rgba(").replace(")", `,${a})`);
83
- if (color.startsWith("rgba(")) return color.replace(/,\s*[\d.]+\)$/, `,${a})`);
84
- return color;
85
- }
86
- function pickSide(value, isDark) {
87
- return isModeAwareColor(value) ? isDark ? value.dark : value.light : value;
88
- }
89
- function makeShadeProxy(shades, isDark) {
90
- return new Proxy(shades, {
91
- get(target, prop) {
92
- const key = String(prop);
93
- if (key === "then") return void 0;
94
- if (key.includes("/")) {
95
- const slash = key.indexOf("/");
96
- const shade = key.slice(0, slash);
97
- const op = Number(key.slice(slash + 1));
98
- const color2 = target[shade];
99
- return color2 !== void 0 ? applyOpacity(pickSide(color2, isDark), op) : void 0;
100
- }
101
- const color = target[key];
102
- return color !== void 0 ? pickSide(color, isDark) : void 0;
103
- }
104
- });
105
- }
106
- function wrapColors(rawColors, isDark = false) {
107
- const cache = /* @__PURE__ */ new Map();
108
- const alpha = (color, opacity) => opacity === void 0 ? color : applyOpacity(color, opacity);
109
- return new Proxy({ alpha }, {
110
- get(_, prop) {
111
- const key = String(prop);
112
- if (key === "then") return void 0;
113
- if (key === "alpha") return alpha;
114
- if (key.includes("/")) {
115
- const slash = key.indexOf("/");
116
- const name = key.slice(0, slash);
117
- const op = Number(key.slice(slash + 1));
118
- const entry2 = rawColors[name];
119
- return entry2 !== void 0 && (typeof entry2 === "string" || isModeAwareColor(entry2)) ? applyOpacity(pickSide(entry2, isDark), op) : void 0;
120
- }
121
- const entry = rawColors[key];
122
- if (entry === void 0) return void 0;
123
- if (typeof entry === "string" || isModeAwareColor(entry)) return pickSide(entry, isDark);
124
- const cacheKey = `${key}:${isDark}`;
125
- if (!cache.has(cacheKey)) cache.set(cacheKey, makeShadeProxy(entry, isDark));
126
- return cache.get(cacheKey);
127
- }
128
- });
129
- }
130
- function useColors() {
131
- const { config, isDark } = useTheme();
132
- return useMemo(() => wrapColors(config.theme.colors, isDark), [config.theme.colors, isDark]);
133
- }
134
-
135
- // src/useSpacing.ts
136
- import { useMemo as useMemo2 } from "react";
137
- function wrapSpacing(rawSpacing) {
138
- return rawSpacing;
139
- }
140
- function useSpacing() {
141
- const { config } = useTheme();
142
- return useMemo2(() => wrapSpacing(config.theme.spacing), [config.theme.spacing]);
143
- }
144
-
145
- // src/ThemeProvider.tsx
146
- import {
147
- useCallback,
148
- useEffect,
149
- useLayoutEffect,
150
- useMemo as useMemo3,
151
- useRef,
152
- useState
153
- } from "react";
154
- import { jsx } from "react/jsx-runtime";
155
- var useIsomorphicLayoutEffect = isWeb || isNative ? useLayoutEffect : useEffect;
156
- var STORAGE_KEY = "kbach-theme";
157
- var _mountedProviderCount = 0;
158
- var _warnedMultipleProviders = false;
159
- var _mountedConfigOverrideCount = 0;
160
- var _warnedConfigOverride = false;
161
- var _warnedMediaModeToggle = false;
162
- function loadPersistedMode() {
163
- try {
164
- if (isWeb) return localStorage.getItem(STORAGE_KEY);
165
- return null;
166
- } catch {
167
- return null;
168
- }
169
- }
170
- function persistMode(mode) {
171
- try {
172
- if (isWeb) localStorage.setItem(STORAGE_KEY, mode);
173
- } catch {
174
- }
175
- }
176
- function subscribeSystemScheme(callback) {
177
- if (!isWeb || typeof window === "undefined") return () => {
178
- };
179
- const mq = window.matchMedia?.("(prefers-color-scheme: dark)");
180
- if (!mq) return () => {
181
- };
182
- mq.addEventListener("change", callback);
183
- return () => mq.removeEventListener("change", callback);
184
- }
185
- function getSystemScheme() {
186
- if (!isWeb || typeof window === "undefined") return "light";
187
- return window.matchMedia?.("(prefers-color-scheme: dark)")?.matches ? "dark" : "light";
188
- }
189
- function getSystemSchemeServerSnapshot() {
190
- return "light";
191
- }
192
- function applyWebTheme(resolvedMode, strategy) {
193
- if (!isWeb) return;
194
- const root = document.documentElement;
195
- if (strategy === "attribute") {
196
- root.setAttribute("data-theme", resolvedMode);
197
- } else if (strategy === "class") {
198
- root.classList.toggle("dark", resolvedMode === "dark");
199
- root.classList.toggle("light", resolvedMode === "light");
200
- }
201
- }
202
- function ThemeProvider({
203
- children,
204
- defaultMode = "system",
205
- colorScheme,
206
- windowWidth: windowWidthProp,
207
- config: configOverride,
208
- disablePersistence = false
209
- }) {
210
- let nativeColorScheme = null;
211
- let nativeWindowWidth;
212
- if (isNative) {
213
- const { useColorScheme, useWindowDimensions } = __require("react-native");
214
- const raw = useColorScheme();
215
- nativeColorScheme = raw === "dark" ? "dark" : raw === "light" ? "light" : null;
216
- nativeWindowWidth = useWindowDimensions().width;
217
- }
218
- const [resolvedConfig, setResolvedConfig] = useState(
219
- () => configOverride ? buildConfig(configOverride) : getConfig()
220
- );
221
- const _prevConfigOverrideRef = useRef(void 0);
222
- if (configOverride && _prevConfigOverrideRef.current !== configOverride) {
223
- _prevConfigOverrideRef.current = configOverride;
224
- updateConfig(configOverride);
225
- const fresh = getConfig();
226
- if (fresh !== resolvedConfig) setResolvedConfig(fresh);
227
- }
228
- useEffect(() => {
229
- _mountedProviderCount++;
230
- if (configOverride) _mountedConfigOverrideCount++;
231
- if (process.env.NODE_ENV !== "production") {
232
- if (_mountedProviderCount > 1 && !_warnedMultipleProviders) {
233
- _warnedMultipleProviders = true;
234
- kbachWarn(
235
- "Multiple <ThemeProvider> instances are mounted at once. Dark mode and responsive width are shared through one global store, so whichever provider rendered most recently wins for every consumer \u2014 nested or per-section theming is not isolated between providers."
236
- );
237
- }
238
- if (_mountedConfigOverrideCount > 1 && !_warnedConfigOverride) {
239
- _warnedConfigOverride = true;
240
- kbachWarn(
241
- "Multiple <ThemeProvider config={...}> overrides are mounted at once. The resolved config is shared through the same global store as dark mode/width (see the multiple-providers warning), so per-tree config overrides are not actually isolated between providers \u2014 plain className/kb elements with no hover:/dark:/sm: modifier resolve against whichever override last committed, not necessarily their nearest ancestor <ThemeProvider>."
242
- );
243
- }
244
- }
245
- return () => {
246
- _mountedProviderCount--;
247
- if (configOverride) _mountedConfigOverrideCount--;
248
- if (_prevConfigOverrideRef.current !== void 0 && _mountedProviderCount === 0) {
249
- resetConfig();
250
- }
251
- };
252
- }, []);
253
- const [webWidth, setWebWidth] = useState(0);
254
- const effectiveWidth = getEffectiveIsWeb() ? webWidth : windowWidthProp ?? nativeWindowWidth ?? 0;
255
- const numericScreens = useMemo3(() => {
256
- const out = {};
257
- for (const [k, v] of Object.entries(resolvedConfig.theme.screens ?? {})) {
258
- out[k] = typeof v === "number" ? v : parseInt(String(v), 10);
259
- }
260
- return out;
261
- }, [resolvedConfig.theme.screens]);
262
- const _prevWidthRef = useRef(-1);
263
- if (_prevWidthRef.current !== effectiveWidth) {
264
- _prevWidthRef.current = effectiveWidth;
265
- syncGlobalWidth(effectiveWidth);
266
- }
267
- const _prevScreensRef = useRef(null);
268
- if (_prevScreensRef.current !== numericScreens) {
269
- _prevScreensRef.current = numericScreens;
270
- syncGlobalScreens(numericScreens);
271
- }
272
- useEffect(() => {
273
- setGlobalWidth(effectiveWidth);
274
- }, [effectiveWidth]);
275
- useEffect(() => {
276
- if (!isWeb || typeof window === "undefined") return;
277
- setWebWidth(window.innerWidth);
278
- let raf = 0;
279
- const update = () => {
280
- cancelAnimationFrame(raf);
281
- raf = requestAnimationFrame(() => {
282
- const w = window.innerWidth;
283
- setWebWidth(w);
284
- setGlobalWidth(w);
285
- });
286
- };
287
- window.addEventListener("resize", update);
288
- return () => {
289
- window.removeEventListener("resize", update);
290
- cancelAnimationFrame(raf);
291
- };
292
- }, []);
293
- const webScheme = useSyncExternalStore(
294
- subscribeSystemScheme,
295
- getSystemScheme,
296
- getSystemSchemeServerSnapshot
297
- );
298
- const systemScheme = getEffectiveIsWeb() ? webScheme : (colorScheme ?? nativeColorScheme) === "dark" ? "dark" : "light";
299
- const [mode, _setMode] = useState(defaultMode);
300
- useEffect(() => {
301
- if (disablePersistence) return;
302
- const persisted = loadPersistedMode();
303
- if (persisted) _setMode(persisted);
304
- }, []);
305
- useEffect(() => {
306
- if (disablePersistence || !isWeb || typeof window === "undefined") return;
307
- const onStorage = (e) => {
308
- if (e.key !== STORAGE_KEY || e.newValue == null) return;
309
- if (e.newValue === "light" || e.newValue === "dark" || e.newValue === "system") {
310
- _setMode(e.newValue);
311
- }
312
- };
313
- window.addEventListener("storage", onStorage);
314
- return () => window.removeEventListener("storage", onStorage);
315
- }, [disablePersistence]);
316
- const setMode = useCallback((next) => {
317
- if (process.env.NODE_ENV !== "production" && isWeb && resolvedConfig.darkMode === "media" && !_warnedMediaModeToggle) {
318
- _warnedMediaModeToggle = true;
319
- kbachWarn(
320
- 'setMode()/toggle() was called while darkMode is "media" \u2014 the resolved mode/isDark from useTheme()/useIsDark() will update, but the actual CSS stays driven by prefers-color-scheme and will not change to match. Use darkMode: "attribute" or "class" if the app needs manual toggling.'
321
- );
322
- }
323
- _setMode(next);
324
- if (!disablePersistence) persistMode(next);
325
- }, [disablePersistence, resolvedConfig.darkMode]);
326
- const toggle = useCallback(() => {
327
- setMode(mode === "dark" || mode === "system" && systemScheme === "dark" ? "light" : "dark");
328
- }, [mode, systemScheme, setMode]);
329
- const resolvedMode = mode === "system" ? systemScheme : mode;
330
- const isDark = resolvedMode === "dark";
331
- syncGlobalDarkMode(isDark);
332
- useIsomorphicLayoutEffect(() => {
333
- applyWebTheme(resolvedMode, resolvedConfig.darkMode);
334
- setGlobalDarkMode(isDark);
335
- }, [isDark, resolvedMode, resolvedConfig.darkMode]);
336
- useEffect(() => {
337
- if (configOverride) return;
338
- let mounted = true;
339
- const unsub = onConfigChange((config) => {
340
- if (mounted) setResolvedConfig(config);
341
- });
342
- return () => {
343
- mounted = false;
344
- unsub();
345
- };
346
- }, [configOverride]);
347
- const contextValue = useMemo3(
348
- () => ({ mode, resolvedMode, isDark, setMode, toggle, config: resolvedConfig }),
349
- [mode, resolvedMode, isDark, setMode, toggle, resolvedConfig]
350
- );
351
- return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: contextValue, children });
352
- }
353
-
354
- // src/KbachReset.tsx
355
- import { jsx as jsx2 } from "react/jsx-runtime";
356
- function KbachReset() {
357
- if (isNative) return null;
358
- if (isRuntimeCSSDisabled()) return null;
359
- return /* @__PURE__ */ jsx2("style", { id: RESET_STYLE_ID, children: BASE_RESET });
360
- }
361
-
362
- // src/styled.tsx
363
- import React2, {
364
- forwardRef,
365
- useState as useState2,
366
- useCallback as useCallback2,
367
- useMemo as useMemo4
368
- } from "react";
369
- function styled(Component, baseClasses = "") {
370
- const Styled = forwardRef(
371
- (props, ref) => {
372
- const {
373
- kb: extraClasses,
374
- style: styleProp,
375
- onPressIn,
376
- onPressOut,
377
- onPointerDown,
378
- onPointerUp,
379
- onPointerLeave,
380
- onPointerCancel,
381
- onMouseEnter,
382
- onMouseLeave,
383
- onFocus,
384
- onBlur,
385
- ...rest
386
- } = props;
387
- const disabled = !!props.disabled;
388
- const checked = !!props.checked;
389
- const { config } = useTheme();
390
- const isWebPlatform = getEffectiveIsWeb();
391
- const isDark = useConditionalGlobalDarkMode(!isWebPlatform);
392
- const [pressed, setPressed] = useState2(false);
393
- const [hovered, setHovered] = useState2(false);
394
- const [focused, setFocused] = useState2(false);
395
- const handlePressIn = useCallback2(chain(onPressIn, () => {
396
- if (!isWebPlatform) setPressed(true);
397
- }), [onPressIn, isWebPlatform]);
398
- const handlePressOut = useCallback2(chain(onPressOut, () => {
399
- if (!isWebPlatform) setPressed(false);
400
- }), [onPressOut, isWebPlatform]);
401
- const handlePointerDown = useCallback2(chain(onPointerDown, () => {
402
- if (!isWebPlatform) setPressed(true);
403
- }), [onPointerDown, isWebPlatform]);
404
- const handlePointerUp = useCallback2(chain(onPointerUp, () => {
405
- if (!isWebPlatform) setPressed(false);
406
- }), [onPointerUp, isWebPlatform]);
407
- const handlePointerLeave = useCallback2(chain(onPointerLeave, () => {
408
- if (!isWebPlatform) setPressed(false);
409
- }), [onPointerLeave, isWebPlatform]);
410
- const handlePointerCancel = useCallback2(chain(onPointerCancel, () => {
411
- if (!isWebPlatform) setPressed(false);
412
- }), [onPointerCancel, isWebPlatform]);
413
- const handleMouseEnter = useCallback2(chain(onMouseEnter, () => {
414
- if (!isWebPlatform) setHovered(true);
415
- }), [onMouseEnter, isWebPlatform]);
416
- const handleMouseLeave = useCallback2(chain(onMouseLeave, () => {
417
- if (!isWebPlatform) setHovered(false);
418
- }), [onMouseLeave, isWebPlatform]);
419
- const handleFocus = useCallback2(chain(onFocus, () => {
420
- if (!isWebPlatform) setFocused(true);
421
- }), [onFocus, isWebPlatform]);
422
- const handleBlur = useCallback2(chain(onBlur, () => {
423
- if (!isWebPlatform) setFocused(false);
424
- }), [onBlur, isWebPlatform]);
425
- const combined = extraClasses ? `${baseClasses} ${extraClasses}` : baseClasses;
426
- const firstPassResolved = useMemo4(() => resolve(combined, config.theme, config.darkMode), [combined, config.theme, config.darkMode]);
427
- const webTag = isWebPlatform ? getWebTag(Component, rest) : null;
428
- const impliedClasses = getImpliedRNClasses(webTag, firstPassResolved.base);
429
- const finalClassStr = impliedClasses ? `${combined} ${impliedClasses}` : combined;
430
- const resolved = useMemo4(() => resolve(finalClassStr, config.theme, config.darkMode), [finalClassStr, config.theme, config.darkMode]);
431
- const hasInteractive = useMemo4(() => hasInteractiveBuckets(resolved), [resolved]);
432
- const needsWidth = hasResponsiveBuckets(resolved);
433
- const width = useConditionalWidth(needsWidth && !isWebPlatform);
434
- const breakpoints = needsWidth ? getActiveBreakpoints(width) : EMPTY_BREAKPOINTS;
435
- const screens = getGlobalScreens();
436
- const computedStyle = useMemo4(
437
- () => isWebPlatform ? {} : flatten(resolved, isDark, { pressed, hover: hovered, focus: focused, disabled, checked }, breakpoints),
438
- [resolved, isDark, pressed, hovered, focused, disabled, checked, width, screens]
439
- // eslint-disable-line react-hooks/exhaustive-deps
440
- );
441
- const finalStyle = isWebPlatform ? (Array.isArray(styleProp) ? Object.assign({}, ...styleProp) : styleProp) ?? void 0 : composeNativeStyle(computedStyle, styleProp);
442
- const effectiveComponent = webTag ?? Component;
443
- const componentName2 = Component.displayName ?? Component.name ?? "";
444
- const effectiveRest = webTag && componentName2 ? transformToWebProps(componentName2, webTag, rest) : rest;
445
- return React2.createElement(effectiveComponent, {
446
- ref,
447
- ...effectiveRest,
448
- style: finalStyle,
449
- // className lets injected CSS rules (group-hover:, before:, print:, etc.) match the element.
450
- ...isWebPlatform && finalClassStr ? { className: normalizeClassString(finalClassStr) } : {},
451
- // Only attach state-tracking handlers when interactive modifiers are present.
452
- // Always forward user-provided handlers to avoid silently swallowing them.
453
- // Gated on isNative, not isWeb: isWeb is false during SSR too (no `window` there),
454
- // and onPressIn/onPressOut must stay excluded there as well — SSR is exactly where
455
- // getWebTag() above is skipped (it's isWeb-gated), so effectiveComponent may still be
456
- // a non-string RN-style reference server-side, and this used to forward onPressIn/
457
- // onPressOut to it unconditionally in that case (isWeb ? ... : ...'s false branch
458
- // covered both native AND SSR). onPressIn/onPressOut are RN-only prop names — a
459
- // non-string effectiveComponent on the web/SSR side is just as likely to be an
460
- // ordinary web component (React Router's <Link>, Next.js's <Link>, any custom
461
- // wrapper) as an actual react-native-web primitive, and "not a string" alone isn't a
462
- // reliable signal either way. Forwarding them made React DOM warn "Unknown event
463
- // handler property" the moment any such component got an interactive modifier
464
- // (hover:, active:, …), which is the common case, not the exception.
465
- ...!isNative ? hasInteractive ? {
466
- onPointerDown: handlePointerDown,
467
- onPointerUp: handlePointerUp,
468
- onPointerLeave: handlePointerLeave,
469
- onPointerCancel: handlePointerCancel
470
- } : {
471
- onPointerDown,
472
- onPointerUp,
473
- onPointerLeave,
474
- onPointerCancel
475
- } : hasInteractive ? { onPressIn: handlePressIn, onPressOut: handlePressOut } : { onPressIn, onPressOut },
476
- onMouseEnter: hasInteractive ? handleMouseEnter : onMouseEnter,
477
- onMouseLeave: hasInteractive ? handleMouseLeave : onMouseLeave,
478
- onFocus: hasInteractive ? handleFocus : onFocus,
479
- onBlur: hasInteractive ? handleBlur : onBlur
480
- });
481
- }
482
- );
483
- const componentName = Component.displayName ?? Component.name ?? "Component";
484
- Styled.displayName = `Styled(${componentName})`;
485
- return Styled;
486
- }
487
-
488
- // src/useStyles.ts
489
- import { useMemo as useMemo5 } from "react";
490
- function useStyles(classString, state = {}) {
491
- const { isDark, config } = useTheme();
492
- const width = useGlobalWidth();
493
- const normalised = Array.isArray(classString) ? classString.join(" ") : classString;
494
- return useMemo5(() => {
495
- const resolved = resolve(normalised, config.theme, config.darkMode);
496
- const breakpoints = getActiveBreakpoints(width);
497
- return flatten(resolved, isDark, state, breakpoints);
498
- }, [normalised, isDark, config.theme, config.darkMode, width, state.hover, state.focus, state.pressed, state.active, state.disabled, state.checked, state.visited, state.placeholder]);
499
- }
500
- function useResolvedStyle(classString) {
501
- const { config } = useTheme();
502
- const normalised = Array.isArray(classString) ? classString.join(" ") : classString;
503
- return useMemo5(
504
- () => resolve(normalised, config.theme, config.darkMode),
505
- [normalised, config]
506
- );
507
- }
508
-
509
- // src/useBreakpoint.ts
510
- import { useMemo as useMemo6 } from "react";
511
- function toNumericScreens(screens) {
512
- const out = {};
513
- for (const [name, v] of Object.entries(screens)) {
514
- const n = typeof v === "number" ? v : parseInt(String(v), 10);
515
- if (!Number.isNaN(n)) out[name] = n;
1
+ // src/index.ts
2
+ function clsx(...inputs) {
3
+ let out = "";
4
+ for (const input of inputs) {
5
+ const piece = resolveClassValue(input);
6
+ if (piece) out = out ? `${out} ${piece}` : piece;
516
7
  }
517
8
  return out;
518
9
  }
519
- function useBreakpoint() {
520
- const { config } = useTheme();
521
- const width = useGlobalWidth();
522
- const screens = config.theme.screens;
523
- const numericScreens = useMemo6(() => toNumericScreens(screens), [screens]);
524
- return useMemo6(() => {
525
- const active = getActiveBreakpoints(width, numericScreens);
526
- let best = null;
527
- let bestMinW = -Infinity;
528
- for (const name of active) {
529
- const minW = numericScreens[name];
530
- if (minW > bestMinW) {
531
- bestMinW = minW;
532
- best = name;
10
+ function resolveClassValue(value) {
11
+ if (!value) return "";
12
+ const type = typeof value;
13
+ if (type === "string" || type === "number" || type === "bigint") return String(value);
14
+ if (Array.isArray(value)) return clsx(...value);
15
+ if (type === "object") {
16
+ let out = "";
17
+ for (const key in value) {
18
+ if (Object.prototype.hasOwnProperty.call(value, key) && value[key]) {
19
+ out = out ? `${out} ${key}` : key;
533
20
  }
534
21
  }
535
- return best ?? "xs";
536
- }, [numericScreens, width]);
537
- }
538
- function useResponsive() {
539
- const { config } = useTheme();
540
- const width = useGlobalWidth();
541
- const screens = config.theme.screens;
542
- const numericScreens = useMemo6(() => toNumericScreens(screens), [screens]);
543
- return useMemo6(() => {
544
- const active = getActiveBreakpoints(width, numericScreens);
545
- const result = {};
546
- for (const name of Object.keys(numericScreens)) {
547
- result[name] = active.has(name);
548
- }
549
- return result;
550
- }, [numericScreens, width]);
551
- }
552
-
553
- // src/kb.ts
554
- function kb(classString, isDark = false) {
555
- const config = getConfig();
556
- const resolved = resolve(classString, config.theme, config.darkMode);
557
- if (getEffectiveIsWeb()) {
558
- return classString;
22
+ return out;
559
23
  }
560
- return flatten(resolved, isDark);
561
- }
562
- function cx(...classes) {
563
- return classes.filter(Boolean).join(" ");
24
+ return "";
564
25
  }
26
+ var src_default = clsx;
565
27
  export {
566
- InteractiveWrapper,
567
- KbachReset,
568
- ThemeContext,
569
- ThemeProvider,
570
- buildConfig,
571
- clearCache,
572
- cx,
573
- defaultColors,
574
- defaultTheme,
575
- disableRuntimeCSS,
576
- flatten,
577
- generateKbachTypesDts,
578
- getConfig,
579
- initConfig,
580
- kb,
581
- normalizeClassString,
582
- parseClass,
583
- parseClasses,
584
- registerWebElement,
585
- resolve,
586
- setResolveTarget,
587
- splitClassTokens,
588
- styled,
589
- updateConfig,
590
- useBreakpoint,
591
- useColors,
592
- useGlobalDarkMode,
593
- useIsDark,
594
- useResolvedStyle,
595
- useResponsive,
596
- useSpacing,
597
- useStyles,
598
- useTheme,
599
- wrapColors,
600
- wrapSpacing
28
+ clsx,
29
+ src_default as default
601
30
  };