@kbach/ui 0.1.0-beta.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/dist/index.js ADDED
@@ -0,0 +1,1191 @@
1
+ 'use client';
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/index.ts
32
+ var index_exports = {};
33
+ __export(index_exports, {
34
+ InteractiveWrapper: () => InteractiveWrapper,
35
+ KbachReset: () => KbachReset,
36
+ ThemeContext: () => ThemeContext,
37
+ ThemeProvider: () => ThemeProvider,
38
+ buildConfig: () => import_core12.buildConfig,
39
+ clearCache: () => import_core12.clearCache,
40
+ cx: () => cx,
41
+ defaultColors: () => import_core12.defaultColors,
42
+ defaultTheme: () => import_core12.defaultTheme,
43
+ disableRuntimeCSS: () => import_core12.disableRuntimeCSS,
44
+ flatten: () => import_core12.flatten,
45
+ generateKbachTypesDts: () => import_core12.generateKbachTypesDts,
46
+ getConfig: () => import_core12.getConfig,
47
+ initConfig: () => import_core12.initConfig,
48
+ kb: () => kb,
49
+ normalizeClassString: () => import_core12.normalizeClassString,
50
+ parseClass: () => import_core12.parseClass,
51
+ parseClasses: () => import_core12.parseClasses,
52
+ registerWebElement: () => registerWebElement,
53
+ resolve: () => import_core12.resolve,
54
+ setResolveTarget: () => import_core12.setResolveTarget,
55
+ splitClassTokens: () => import_core12.splitClassTokens,
56
+ styled: () => styled,
57
+ updateConfig: () => import_core12.updateConfig,
58
+ useBreakpoint: () => useBreakpoint,
59
+ useColors: () => useColors,
60
+ useGlobalDarkMode: () => useGlobalDarkMode,
61
+ useIsDark: () => useIsDark,
62
+ useResolvedStyle: () => useResolvedStyle,
63
+ useResponsive: () => useResponsive,
64
+ useSpacing: () => useSpacing,
65
+ useStyles: () => useStyles,
66
+ useTheme: () => useTheme,
67
+ wrapColors: () => wrapColors,
68
+ wrapSpacing: () => wrapSpacing
69
+ });
70
+ module.exports = __toCommonJS(index_exports);
71
+
72
+ // src/context.tsx
73
+ var import_react = require("react");
74
+ var ThemeContext = globalThis.__kbachThemeContext ?? (globalThis.__kbachThemeContext = (0, import_react.createContext)(null));
75
+ function useTheme() {
76
+ const ctx = (0, import_react.useContext)(ThemeContext);
77
+ if (!ctx) {
78
+ throw new Error(
79
+ "[Kbach] useTheme() must be called inside a <ThemeProvider>. Wrap your app root with <ThemeProvider>."
80
+ );
81
+ }
82
+ return ctx;
83
+ }
84
+ function useIsDark() {
85
+ return useTheme().isDark;
86
+ }
87
+
88
+ // src/useColors.ts
89
+ var import_react2 = require("react");
90
+ var import_core = require("./core");
91
+ function applyOpacity(color, opacity) {
92
+ const a = Math.max(0, Math.min(1, opacity / 100));
93
+ if (color.startsWith("#")) {
94
+ const rgb = (0, import_core.parseHexRgb)(color);
95
+ if (!rgb) return color;
96
+ const [r, g, b] = rgb;
97
+ return `rgba(${r},${g},${b},${a})`;
98
+ }
99
+ if (color.startsWith("rgb(")) return color.replace("rgb(", "rgba(").replace(")", `,${a})`);
100
+ if (color.startsWith("rgba(")) return color.replace(/,\s*[\d.]+\)$/, `,${a})`);
101
+ return color;
102
+ }
103
+ function pickSide(value, isDark) {
104
+ return (0, import_core.isModeAwareColor)(value) ? isDark ? value.dark : value.light : value;
105
+ }
106
+ function makeShadeProxy(shades, isDark) {
107
+ return new Proxy(shades, {
108
+ get(target, prop) {
109
+ const key = String(prop);
110
+ if (key === "then") return void 0;
111
+ if (key.includes("/")) {
112
+ const slash = key.indexOf("/");
113
+ const shade = key.slice(0, slash);
114
+ const op = Number(key.slice(slash + 1));
115
+ const color2 = target[shade];
116
+ return color2 !== void 0 ? applyOpacity(pickSide(color2, isDark), op) : void 0;
117
+ }
118
+ const color = target[key];
119
+ return color !== void 0 ? pickSide(color, isDark) : void 0;
120
+ }
121
+ });
122
+ }
123
+ function wrapColors(rawColors, isDark = false) {
124
+ const cache = /* @__PURE__ */ new Map();
125
+ const alpha = (color, opacity) => opacity === void 0 ? color : applyOpacity(color, opacity);
126
+ return new Proxy({ alpha }, {
127
+ get(_, prop) {
128
+ const key = String(prop);
129
+ if (key === "then") return void 0;
130
+ if (key === "alpha") return alpha;
131
+ if (key.includes("/")) {
132
+ const slash = key.indexOf("/");
133
+ const name = key.slice(0, slash);
134
+ const op = Number(key.slice(slash + 1));
135
+ const entry2 = rawColors[name];
136
+ return entry2 !== void 0 && (typeof entry2 === "string" || (0, import_core.isModeAwareColor)(entry2)) ? applyOpacity(pickSide(entry2, isDark), op) : void 0;
137
+ }
138
+ const entry = rawColors[key];
139
+ if (entry === void 0) return void 0;
140
+ if (typeof entry === "string" || (0, import_core.isModeAwareColor)(entry)) return pickSide(entry, isDark);
141
+ const cacheKey = `${key}:${isDark}`;
142
+ if (!cache.has(cacheKey)) cache.set(cacheKey, makeShadeProxy(entry, isDark));
143
+ return cache.get(cacheKey);
144
+ }
145
+ });
146
+ }
147
+ function useColors() {
148
+ const { config, isDark } = useTheme();
149
+ return (0, import_react2.useMemo)(() => wrapColors(config.theme.colors, isDark), [config.theme.colors, isDark]);
150
+ }
151
+
152
+ // src/useSpacing.ts
153
+ var import_react3 = require("react");
154
+ function wrapSpacing(rawSpacing) {
155
+ return rawSpacing;
156
+ }
157
+ function useSpacing() {
158
+ const { config } = useTheme();
159
+ return (0, import_react3.useMemo)(() => wrapSpacing(config.theme.spacing), [config.theme.spacing]);
160
+ }
161
+
162
+ // src/ThemeProvider.tsx
163
+ var import_react5 = require("react");
164
+
165
+ // src/useSyncExternalStoreShim.ts
166
+ var import_react4 = __toESM(require("react"));
167
+ var useSyncExternalStore = import_react4.default.useSyncExternalStore ?? function useSyncExternalStoreFallback(subscribe, getSnapshot, getServerSnapshot) {
168
+ const isServer = typeof window === "undefined";
169
+ const [, forceUpdate] = import_react4.default.useReducer((n) => n + 1, 0);
170
+ const value = isServer && getServerSnapshot ? getServerSnapshot() : getSnapshot();
171
+ import_react4.default.useEffect(() => {
172
+ if (getSnapshot() !== value) forceUpdate();
173
+ return subscribe(forceUpdate);
174
+ }, [subscribe]);
175
+ return value;
176
+ };
177
+
178
+ // src/ThemeProvider.tsx
179
+ var import_core2 = require("./core");
180
+ var import_jsx_runtime = require("react/jsx-runtime");
181
+ var useIsomorphicLayoutEffect = import_core2.isWeb || import_core2.isNative ? import_react5.useLayoutEffect : import_react5.useEffect;
182
+ var STORAGE_KEY = "kbach-theme";
183
+ var _mountedProviderCount = 0;
184
+ var _warnedMultipleProviders = false;
185
+ var _mountedConfigOverrideCount = 0;
186
+ var _warnedConfigOverride = false;
187
+ var _warnedMediaModeToggle = false;
188
+ function loadPersistedMode() {
189
+ try {
190
+ if (import_core2.isWeb) return localStorage.getItem(STORAGE_KEY);
191
+ return null;
192
+ } catch {
193
+ return null;
194
+ }
195
+ }
196
+ function persistMode(mode) {
197
+ try {
198
+ if (import_core2.isWeb) localStorage.setItem(STORAGE_KEY, mode);
199
+ } catch {
200
+ }
201
+ }
202
+ function subscribeSystemScheme(callback) {
203
+ if (!import_core2.isWeb || typeof window === "undefined") return () => {
204
+ };
205
+ const mq = window.matchMedia?.("(prefers-color-scheme: dark)");
206
+ if (!mq) return () => {
207
+ };
208
+ mq.addEventListener("change", callback);
209
+ return () => mq.removeEventListener("change", callback);
210
+ }
211
+ function getSystemScheme() {
212
+ if (!import_core2.isWeb || typeof window === "undefined") return "light";
213
+ return window.matchMedia?.("(prefers-color-scheme: dark)")?.matches ? "dark" : "light";
214
+ }
215
+ function getSystemSchemeServerSnapshot() {
216
+ return "light";
217
+ }
218
+ function applyWebTheme(resolvedMode, strategy) {
219
+ if (!import_core2.isWeb) return;
220
+ const root = document.documentElement;
221
+ if (strategy === "attribute") {
222
+ root.setAttribute("data-theme", resolvedMode);
223
+ } else if (strategy === "class") {
224
+ root.classList.toggle("dark", resolvedMode === "dark");
225
+ root.classList.toggle("light", resolvedMode === "light");
226
+ }
227
+ }
228
+ function ThemeProvider({
229
+ children,
230
+ defaultMode = "system",
231
+ colorScheme,
232
+ windowWidth: windowWidthProp,
233
+ config: configOverride,
234
+ disablePersistence = false
235
+ }) {
236
+ const [resolvedConfig, setResolvedConfig] = (0, import_react5.useState)(
237
+ () => configOverride ? (0, import_core2.buildConfig)(configOverride) : (0, import_core2.getConfig)()
238
+ );
239
+ const _prevConfigOverrideRef = (0, import_react5.useRef)(void 0);
240
+ if (configOverride && _prevConfigOverrideRef.current !== configOverride) {
241
+ _prevConfigOverrideRef.current = configOverride;
242
+ (0, import_core2.updateConfig)(configOverride);
243
+ const fresh = (0, import_core2.getConfig)();
244
+ if (fresh !== resolvedConfig) setResolvedConfig(fresh);
245
+ }
246
+ (0, import_react5.useEffect)(() => {
247
+ _mountedProviderCount++;
248
+ if (configOverride) _mountedConfigOverrideCount++;
249
+ if (process.env.NODE_ENV !== "production") {
250
+ if (_mountedProviderCount > 1 && !_warnedMultipleProviders) {
251
+ _warnedMultipleProviders = true;
252
+ (0, import_core2.kbachWarn)(
253
+ "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."
254
+ );
255
+ }
256
+ if (_mountedConfigOverrideCount > 1 && !_warnedConfigOverride) {
257
+ _warnedConfigOverride = true;
258
+ (0, import_core2.kbachWarn)(
259
+ "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>."
260
+ );
261
+ }
262
+ }
263
+ return () => {
264
+ _mountedProviderCount--;
265
+ if (configOverride) _mountedConfigOverrideCount--;
266
+ if (_prevConfigOverrideRef.current !== void 0 && _mountedProviderCount === 0) {
267
+ (0, import_core2.resetConfig)();
268
+ }
269
+ };
270
+ }, []);
271
+ const [webWidth, setWebWidth] = (0, import_react5.useState)(0);
272
+ const effectiveWidth = (0, import_core2.getEffectiveIsWeb)() ? webWidth : windowWidthProp ?? 0;
273
+ const numericScreens = (0, import_react5.useMemo)(() => {
274
+ const out = {};
275
+ for (const [k, v] of Object.entries(resolvedConfig.theme.screens ?? {})) {
276
+ out[k] = typeof v === "number" ? v : parseInt(String(v), 10);
277
+ }
278
+ return out;
279
+ }, [resolvedConfig.theme.screens]);
280
+ const _prevWidthRef = (0, import_react5.useRef)(-1);
281
+ if (_prevWidthRef.current !== effectiveWidth) {
282
+ _prevWidthRef.current = effectiveWidth;
283
+ (0, import_core2.syncGlobalWidth)(effectiveWidth);
284
+ }
285
+ const _prevScreensRef = (0, import_react5.useRef)(null);
286
+ if (_prevScreensRef.current !== numericScreens) {
287
+ _prevScreensRef.current = numericScreens;
288
+ (0, import_core2.syncGlobalScreens)(numericScreens);
289
+ }
290
+ (0, import_react5.useEffect)(() => {
291
+ (0, import_core2.setGlobalWidth)(effectiveWidth);
292
+ }, [effectiveWidth]);
293
+ (0, import_react5.useEffect)(() => {
294
+ if (!import_core2.isWeb || typeof window === "undefined") return;
295
+ setWebWidth(window.innerWidth);
296
+ let raf = 0;
297
+ const update = () => {
298
+ cancelAnimationFrame(raf);
299
+ raf = requestAnimationFrame(() => {
300
+ const w = window.innerWidth;
301
+ setWebWidth(w);
302
+ (0, import_core2.setGlobalWidth)(w);
303
+ });
304
+ };
305
+ window.addEventListener("resize", update);
306
+ return () => {
307
+ window.removeEventListener("resize", update);
308
+ cancelAnimationFrame(raf);
309
+ };
310
+ }, []);
311
+ const webScheme = useSyncExternalStore(
312
+ subscribeSystemScheme,
313
+ getSystemScheme,
314
+ getSystemSchemeServerSnapshot
315
+ );
316
+ const systemScheme = (0, import_core2.getEffectiveIsWeb)() ? webScheme : colorScheme === "dark" ? "dark" : "light";
317
+ const [mode, _setMode] = (0, import_react5.useState)(defaultMode);
318
+ (0, import_react5.useEffect)(() => {
319
+ if (disablePersistence) return;
320
+ const persisted = loadPersistedMode();
321
+ if (persisted) _setMode(persisted);
322
+ }, []);
323
+ (0, import_react5.useEffect)(() => {
324
+ if (disablePersistence || !import_core2.isWeb || typeof window === "undefined") return;
325
+ const onStorage = (e) => {
326
+ if (e.key !== STORAGE_KEY || e.newValue == null) return;
327
+ if (e.newValue === "light" || e.newValue === "dark" || e.newValue === "system") {
328
+ _setMode(e.newValue);
329
+ }
330
+ };
331
+ window.addEventListener("storage", onStorage);
332
+ return () => window.removeEventListener("storage", onStorage);
333
+ }, [disablePersistence]);
334
+ const setMode = (0, import_react5.useCallback)((next) => {
335
+ if (process.env.NODE_ENV !== "production" && import_core2.isWeb && resolvedConfig.darkMode === "media" && !_warnedMediaModeToggle) {
336
+ _warnedMediaModeToggle = true;
337
+ (0, import_core2.kbachWarn)(
338
+ '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.'
339
+ );
340
+ }
341
+ _setMode(next);
342
+ if (!disablePersistence) persistMode(next);
343
+ }, [disablePersistence, resolvedConfig.darkMode]);
344
+ const toggle = (0, import_react5.useCallback)(() => {
345
+ setMode(mode === "dark" || mode === "system" && systemScheme === "dark" ? "light" : "dark");
346
+ }, [mode, systemScheme, setMode]);
347
+ const resolvedMode = mode === "system" ? systemScheme : mode;
348
+ const isDark = resolvedMode === "dark";
349
+ (0, import_core2.syncGlobalDarkMode)(isDark);
350
+ useIsomorphicLayoutEffect(() => {
351
+ applyWebTheme(resolvedMode, resolvedConfig.darkMode);
352
+ (0, import_core2.setGlobalDarkMode)(isDark);
353
+ }, [isDark, resolvedMode, resolvedConfig.darkMode]);
354
+ (0, import_react5.useEffect)(() => {
355
+ if (configOverride) return;
356
+ let mounted = true;
357
+ const unsub = (0, import_core2.onConfigChange)((config) => {
358
+ if (mounted) setResolvedConfig(config);
359
+ });
360
+ return () => {
361
+ mounted = false;
362
+ unsub();
363
+ };
364
+ }, [configOverride]);
365
+ const contextValue = (0, import_react5.useMemo)(
366
+ () => ({ mode, resolvedMode, isDark, setMode, toggle, config: resolvedConfig }),
367
+ [mode, resolvedMode, isDark, setMode, toggle, resolvedConfig]
368
+ );
369
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeContext.Provider, { value: contextValue, children });
370
+ }
371
+
372
+ // src/KbachReset.tsx
373
+ var import_core3 = require("./core");
374
+ var import_jsx_runtime2 = require("react/jsx-runtime");
375
+ function KbachReset() {
376
+ if (import_core3.isNative) return null;
377
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { id: import_core3.RESET_STYLE_ID, children: import_core3.BASE_RESET });
378
+ }
379
+
380
+ // src/styled.tsx
381
+ var import_react6 = __toESM(require("react"));
382
+ var import_core7 = require("./core");
383
+
384
+ // src/useGlobalDarkMode.ts
385
+ var import_core4 = require("./core");
386
+ var NOOP_SUB = (_) => () => {
387
+ };
388
+ var FALSE_SNAP = () => false;
389
+ function useGlobalDarkMode() {
390
+ return useSyncExternalStore(
391
+ import_core4.subscribeGlobalDarkMode,
392
+ import_core4.getGlobalDarkMode,
393
+ () => false
394
+ // SSR: default light
395
+ );
396
+ }
397
+ function useConditionalGlobalDarkMode(active) {
398
+ return useSyncExternalStore(
399
+ active ? import_core4.subscribeGlobalDarkMode : NOOP_SUB,
400
+ active ? import_core4.getGlobalDarkMode : FALSE_SNAP,
401
+ FALSE_SNAP
402
+ );
403
+ }
404
+
405
+ // src/useGlobalWidth.ts
406
+ var import_core5 = require("./core");
407
+ var NOOP_SUB2 = (_) => () => {
408
+ };
409
+ var ZERO_SNAP = () => 0;
410
+ var EMPTY_BREAKPOINTS = /* @__PURE__ */ new Set();
411
+ var _webListeners = null;
412
+ var _webRaf = 0;
413
+ function _webResizeHandler() {
414
+ cancelAnimationFrame(_webRaf);
415
+ _webRaf = requestAnimationFrame(() => {
416
+ if (_webListeners) for (const cb of _webListeners) cb();
417
+ });
418
+ }
419
+ function subscribeWebWidth(cb) {
420
+ if (typeof window === "undefined") return () => {
421
+ };
422
+ if (!_webListeners) {
423
+ _webListeners = /* @__PURE__ */ new Set();
424
+ window.addEventListener("resize", _webResizeHandler);
425
+ }
426
+ _webListeners.add(cb);
427
+ return () => {
428
+ _webListeners.delete(cb);
429
+ if (_webListeners.size === 0) {
430
+ window.removeEventListener("resize", _webResizeHandler);
431
+ cancelAnimationFrame(_webRaf);
432
+ _webListeners = null;
433
+ }
434
+ };
435
+ }
436
+ function getWebWidth() {
437
+ return typeof window !== "undefined" ? window.innerWidth : 0;
438
+ }
439
+ function useGlobalWidth() {
440
+ return useSyncExternalStore(
441
+ import_core5.isWeb ? subscribeWebWidth : import_core5.subscribeGlobalWidth,
442
+ import_core5.isWeb ? getWebWidth : import_core5.getGlobalWidth,
443
+ ZERO_SNAP
444
+ );
445
+ }
446
+ function useConditionalWidth(active) {
447
+ return useSyncExternalStore(
448
+ active ? import_core5.isWeb ? subscribeWebWidth : import_core5.subscribeGlobalWidth : NOOP_SUB2,
449
+ active ? import_core5.isWeb ? getWebWidth : import_core5.getGlobalWidth : ZERO_SNAP,
450
+ ZERO_SNAP
451
+ );
452
+ }
453
+
454
+ // src/shared-utils.ts
455
+ var import_core6 = require("./core");
456
+ function hasResponsiveBuckets(resolved) {
457
+ const responsiveMods = (0, import_core6.getResponsiveModifiers)();
458
+ for (const key of Object.keys(resolved)) {
459
+ if (key === "base") continue;
460
+ for (const mod of key.split(":")) {
461
+ if (responsiveMods.has(mod)) return true;
462
+ }
463
+ }
464
+ return false;
465
+ }
466
+ function hasInteractiveBuckets(resolved) {
467
+ const interactiveMods = (0, import_core6.getInteractiveModifiers)();
468
+ for (const key of Object.keys(resolved)) {
469
+ if (key === "base") continue;
470
+ for (const mod of key.split(":")) {
471
+ if (interactiveMods.has(mod)) return true;
472
+ }
473
+ }
474
+ return false;
475
+ }
476
+ function chain(original, extra) {
477
+ return (...args) => {
478
+ original?.(...args);
479
+ extra();
480
+ };
481
+ }
482
+ function stripInternalMarkers(s) {
483
+ delete s.__divideX;
484
+ delete s.__divideY;
485
+ delete s.__divideColor;
486
+ delete s.__divideStyle;
487
+ delete s.__keyframe;
488
+ }
489
+ function stripWebOnlyProps(s) {
490
+ if (s.display === "grid" || s.display === "inline-grid") delete s.display;
491
+ delete s.gridTemplateColumns;
492
+ delete s.gridTemplateRows;
493
+ delete s.gridColumn;
494
+ delete s.gridRow;
495
+ delete s.gridArea;
496
+ delete s.gridColumnStart;
497
+ delete s.gridColumnEnd;
498
+ delete s.gridRowStart;
499
+ delete s.gridRowEnd;
500
+ delete s.gridAutoFlow;
501
+ delete s.gridAutoColumns;
502
+ delete s.gridAutoRows;
503
+ delete s.placeItems;
504
+ delete s.placeContent;
505
+ delete s.justifyItems;
506
+ delete s.placeSelf;
507
+ delete s.justifySelf;
508
+ if (s.position === "sticky" || s.position === "fixed" || s.position === "static") {
509
+ delete s.position;
510
+ }
511
+ }
512
+ function composeNativeStyle(computed, userStyle) {
513
+ if (!userStyle) return computed;
514
+ return Array.isArray(userStyle) ? [computed, ...userStyle] : [computed, userStyle];
515
+ }
516
+
517
+ // src/web-substitute.ts
518
+ var _rnToHtml = {
519
+ View: "div",
520
+ SafeAreaView: "div",
521
+ KeyboardAvoidingView: "div",
522
+ ScrollView: "div",
523
+ VirtualizedList: "div",
524
+ FlatList: "div",
525
+ SectionList: "div",
526
+ Text: "span",
527
+ TextInput: "input",
528
+ Image: "img",
529
+ ImageBackground: "div",
530
+ Pressable: "div",
531
+ TouchableOpacity: "div",
532
+ TouchableHighlight: "div",
533
+ TouchableWithoutFeedback: "div",
534
+ TouchableNativeFeedback: "div"
535
+ };
536
+ var _userMap = /* @__PURE__ */ new Map();
537
+ var _cache = /* @__PURE__ */ new WeakMap();
538
+ function registerWebElement(rnComponent, htmlTag) {
539
+ if (typeof rnComponent !== "object" && typeof rnComponent !== "function") return;
540
+ _userMap.set(rnComponent, htmlTag);
541
+ _cache.delete(rnComponent);
542
+ }
543
+ var _forwardRefOrMemoType = /* @__PURE__ */ new Set([
544
+ /* @__PURE__ */ Symbol.for("react.forward_ref"),
545
+ /* @__PURE__ */ Symbol.for("react.memo")
546
+ ]);
547
+ function looksLikeRealRNPrimitive(type) {
548
+ const t = type.$$typeof;
549
+ if (t !== void 0) return _forwardRefOrMemoType.has(t);
550
+ return !!type.prototype?.isReactComponent;
551
+ }
552
+ function getWebTag(type, props) {
553
+ if (typeof type === "string") return null;
554
+ if (type === null || typeof type !== "function" && typeof type !== "object") return null;
555
+ const obj = type;
556
+ if (_userMap.has(obj)) return _userMap.get(obj);
557
+ if (!looksLikeRealRNPrimitive(obj)) return null;
558
+ const name = obj.displayName ?? obj.name;
559
+ if (!name) {
560
+ _cache.set(obj, null);
561
+ return null;
562
+ }
563
+ if (name === "TextInput") {
564
+ const multiline = !!props && (props.multiline === true || Number(props.numberOfLines) > 1);
565
+ return multiline ? "textarea" : "input";
566
+ }
567
+ if (_cache.has(obj)) return _cache.get(obj);
568
+ const tag = _rnToHtml[name] ?? null;
569
+ _cache.set(obj, tag);
570
+ return tag;
571
+ }
572
+ function getImpliedRNClasses(webTag, resolvedBase) {
573
+ if (!webTag || !resolvedBase) return void 0;
574
+ const classes = [];
575
+ if (resolvedBase.position === void 0) classes.push("relative");
576
+ const explicitDisplay = resolvedBase.display;
577
+ const hasFlexItemProps = "flexGrow" in resolvedBase || "flexShrink" in resolvedBase || "flex" in resolvedBase || "gap" in resolvedBase || "columnGap" in resolvedBase || "rowGap" in resolvedBase;
578
+ const willBeFlex = explicitDisplay === "flex" || explicitDisplay === void 0 && hasFlexItemProps;
579
+ if (willBeFlex && (explicitDisplay === void 0 || resolvedBase.flexDirection === void 0)) {
580
+ classes.push("flex-col");
581
+ }
582
+ return classes.length > 0 ? classes.join(" ") : void 0;
583
+ }
584
+ var _rnOnlyProps = /* @__PURE__ */ new Set([
585
+ // Interaction
586
+ "onLongPress",
587
+ "delayLongPress",
588
+ "activeOpacity",
589
+ "underlayColor",
590
+ "hitSlop",
591
+ "pressRetentionOffset",
592
+ "android_ripple",
593
+ "android_disableSound",
594
+ "onHoverIn",
595
+ "onHoverOut",
596
+ "onHoverStart",
597
+ "onHoverEnd",
598
+ // Layout event
599
+ "onLayout",
600
+ // Accessibility
601
+ "accessible",
602
+ "accessibilityState",
603
+ "accessibilityLiveRegion",
604
+ "importantForAccessibility",
605
+ // Platform
606
+ "nativeID",
607
+ "collapsable",
608
+ "needsOffscreenAlphaCompositing",
609
+ "renderToHardwareTextureAndroid",
610
+ "shouldRasterizeIOS",
611
+ "focusable",
612
+ "hasTVPreferredFocus",
613
+ // 'pointerEvents' is handled in transformToWebProps (mapped to CSS style)
614
+ // Text
615
+ "selectable",
616
+ "allowFontScaling",
617
+ "adjustsFontSizeToFit",
618
+ "minimumFontScale",
619
+ "ellipsizeMode",
620
+ "numberOfLines",
621
+ "onTextLayout",
622
+ "textBreakStrategy",
623
+ "lineBreakStrategyIOS",
624
+ // TextInput
625
+ "multiline",
626
+ // NOTE: 'resizeMode' (Image's prop, not TextInput's) deliberately does NOT
627
+ // go here — it's handled below in the isImage branch (mapped to CSS
628
+ // object-fit). Blacklisting it here would make that branch unreachable.
629
+ "blurOnSubmit",
630
+ "clearButtonMode",
631
+ "clearTextOnFocus",
632
+ "enablesReturnKeyAutomatically",
633
+ "returnKeyType",
634
+ "spellCheck",
635
+ // ScrollView
636
+ "scrollEnabled",
637
+ "showsVerticalScrollIndicator",
638
+ "showsHorizontalScrollIndicator",
639
+ "contentContainerStyle",
640
+ // 'horizontal' is handled in transformToWebProps (converted to CSS overflow-x).
641
+ "keyboardShouldPersistTaps",
642
+ "keyboardDismissMode",
643
+ "pagingEnabled",
644
+ "scrollEventThrottle",
645
+ "decelerationRate",
646
+ "bounces",
647
+ "alwaysBounceHorizontal",
648
+ "alwaysBounceVertical",
649
+ "snapToAlignment",
650
+ "snapToInterval",
651
+ "snapToOffsets",
652
+ "removeClippedSubviews",
653
+ "overScrollMode",
654
+ "stickyHeaderIndices",
655
+ "invertStickyHeaders",
656
+ "onScrollBeginDrag",
657
+ "onScrollEndDrag",
658
+ "onMomentumScrollBegin",
659
+ "onMomentumScrollEnd",
660
+ "contentInset",
661
+ "contentInsetAdjustmentBehavior",
662
+ "automaticallyAdjustContentInsets",
663
+ "automaticallyAdjustsScrollIndicatorInsets",
664
+ // expo-image
665
+ "contentPosition",
666
+ "cachePolicy",
667
+ "recyclingKey",
668
+ "blurRadius",
669
+ "fadeDuration",
670
+ "responsivePolicy",
671
+ "tintColor",
672
+ "allowDownscaling",
673
+ "placeholderContentFit",
674
+ // FlatList / SectionList
675
+ "data",
676
+ "renderItem",
677
+ "keyExtractor",
678
+ "getItemLayout",
679
+ "initialScrollIndex",
680
+ "initialNumToRender",
681
+ "maxToRenderPerBatch",
682
+ "windowSize",
683
+ "updateCellsBatchingPeriod",
684
+ "onEndReached",
685
+ "onEndReachedThreshold",
686
+ "ListHeaderComponent",
687
+ "ListFooterComponent",
688
+ "ListEmptyComponent",
689
+ "ListHeaderComponentStyle",
690
+ "ListFooterComponentStyle",
691
+ "ItemSeparatorComponent",
692
+ "SectionSeparatorComponent",
693
+ "inverted",
694
+ "getItem",
695
+ "getItemCount"
696
+ ]);
697
+ var _pressableNames = /* @__PURE__ */ new Set([
698
+ "Pressable",
699
+ "TouchableOpacity",
700
+ "TouchableHighlight",
701
+ "TouchableWithoutFeedback",
702
+ "TouchableNativeFeedback"
703
+ ]);
704
+ var _keyboardTypeMap = {
705
+ "numeric": "number",
706
+ "number-pad": "number",
707
+ "decimal-pad": "decimal",
708
+ "email-address": "email",
709
+ "phone-pad": "tel",
710
+ "url": "url"
711
+ };
712
+ var _resizeModeMap = {
713
+ "contain": "contain",
714
+ "cover": "cover",
715
+ "stretch": "fill",
716
+ "center": "none",
717
+ "repeat": "none"
718
+ };
719
+ var PLACEHOLDER_RULE_ATTR = "data-kbach-ph";
720
+ var _placeholderRuleInjected = false;
721
+ function ensurePlaceholderColorRuleInjected() {
722
+ if (_placeholderRuleInjected || typeof document === "undefined") return;
723
+ _placeholderRuleInjected = true;
724
+ const style = document.createElement("style");
725
+ style.setAttribute("data-kbach-placeholder", "");
726
+ style.textContent = `[${PLACEHOLDER_RULE_ATTR}]::placeholder{color:var(--kbach-ph-color)}`;
727
+ document.head.appendChild(style);
728
+ }
729
+ function transformToWebProps(originalName, tag, props) {
730
+ const out = {};
731
+ const isPressable = _pressableNames.has(originalName);
732
+ const isTextInput = originalName === "TextInput";
733
+ const isImage = originalName === "Image" || originalName === "ImageBackground";
734
+ const isScrollable = originalName === "ScrollView" || originalName === "FlatList" || originalName === "SectionList";
735
+ let pendingStyle = null;
736
+ for (const [k, v] of Object.entries(props)) {
737
+ if (_rnOnlyProps.has(k)) continue;
738
+ if (k === "onPress") {
739
+ if (!("onClick" in props)) out.onClick = v;
740
+ continue;
741
+ }
742
+ if (k === "accessibilityLabel") {
743
+ if (out["aria-label"] == null) out["aria-label"] = v;
744
+ continue;
745
+ }
746
+ if (k === "accessibilityRole") {
747
+ if (out.role == null) out.role = v;
748
+ continue;
749
+ }
750
+ if (k === "testID") {
751
+ if (out["data-testid"] == null) out["data-testid"] = v;
752
+ continue;
753
+ }
754
+ if (isTextInput) {
755
+ if (k === "onChangeText") {
756
+ if (!("onChange" in props)) out.onChange = (e) => v(e.target.value);
757
+ continue;
758
+ }
759
+ if (k === "onSubmitEditing") {
760
+ if (!("onKeyDown" in props)) {
761
+ out.onKeyDown = (e) => {
762
+ if (e.key === "Enter") v();
763
+ };
764
+ }
765
+ continue;
766
+ }
767
+ if (k === "placeholderTextColor") {
768
+ if (v) {
769
+ ensurePlaceholderColorRuleInjected();
770
+ out[PLACEHOLDER_RULE_ATTR] = "";
771
+ pendingStyle = { ...pendingStyle ?? {}, "--kbach-ph-color": v };
772
+ }
773
+ continue;
774
+ }
775
+ if (k === "secureTextEntry") {
776
+ if (v && !("type" in props)) out.type = "password";
777
+ continue;
778
+ }
779
+ if (k === "keyboardType") {
780
+ if (!("type" in props) && !props.secureTextEntry) {
781
+ const mapped = _keyboardTypeMap[v];
782
+ if (mapped) out.type = mapped;
783
+ }
784
+ continue;
785
+ }
786
+ if (k === "editable") {
787
+ if (v === false) out.readOnly = true;
788
+ continue;
789
+ }
790
+ if (k === "maxLength") {
791
+ out.maxLength = v;
792
+ continue;
793
+ }
794
+ }
795
+ if (isScrollable && k === "horizontal") {
796
+ if (v) pendingStyle = { ...pendingStyle ?? {}, display: "flex", flexDirection: "row", overflowX: "auto" };
797
+ continue;
798
+ }
799
+ if (k === "pointerEvents") {
800
+ if (v === "none" || v === "auto") pendingStyle = { ...pendingStyle ?? {}, pointerEvents: v };
801
+ continue;
802
+ }
803
+ if (isImage) {
804
+ if (k === "source") {
805
+ if (typeof v === "string") {
806
+ out.src = v;
807
+ } else if (v && typeof v === "object" && "uri" in v) {
808
+ out.src = v.uri;
809
+ if (v.headers) out["crossOrigin"] = "anonymous";
810
+ }
811
+ continue;
812
+ }
813
+ if (k === "resizeMode") {
814
+ pendingStyle = { ...pendingStyle ?? {}, objectFit: _resizeModeMap[v] ?? "cover" };
815
+ continue;
816
+ }
817
+ if (k === "contentFit") {
818
+ pendingStyle = { ...pendingStyle ?? {}, objectFit: v };
819
+ continue;
820
+ }
821
+ if (k === "defaultSource") continue;
822
+ }
823
+ if (k === "style") {
824
+ if (Array.isArray(v)) {
825
+ out.style = Object.assign({}, ...v.filter(Boolean));
826
+ } else if (v != null) {
827
+ out.style = v;
828
+ }
829
+ continue;
830
+ }
831
+ out[k] = v;
832
+ }
833
+ if (pendingStyle) {
834
+ out.style = out.style ? { ...pendingStyle, ...out.style } : pendingStyle;
835
+ }
836
+ if (isPressable && !out.role) out.role = "button";
837
+ if (isImage && tag === "img" && out.alt == null) out.alt = "";
838
+ return out;
839
+ }
840
+
841
+ // src/styled.tsx
842
+ function styled(Component, baseClasses = "") {
843
+ const Styled = (0, import_react6.forwardRef)(
844
+ (props, ref) => {
845
+ const {
846
+ kb: extraClasses,
847
+ style: styleProp,
848
+ onPressIn,
849
+ onPressOut,
850
+ onPointerDown,
851
+ onPointerUp,
852
+ onPointerLeave,
853
+ onPointerCancel,
854
+ onMouseEnter,
855
+ onMouseLeave,
856
+ onFocus,
857
+ onBlur,
858
+ ...rest
859
+ } = props;
860
+ const disabled = !!props.disabled;
861
+ const checked = !!props.checked;
862
+ const { config } = useTheme();
863
+ const isWebPlatform = (0, import_core7.getEffectiveIsWeb)();
864
+ const isDark = useConditionalGlobalDarkMode(!isWebPlatform);
865
+ const [pressed, setPressed] = (0, import_react6.useState)(false);
866
+ const [hovered, setHovered] = (0, import_react6.useState)(false);
867
+ const [focused, setFocused] = (0, import_react6.useState)(false);
868
+ const handlePressIn = (0, import_react6.useCallback)(chain(onPressIn, () => {
869
+ if (!isWebPlatform) setPressed(true);
870
+ }), [onPressIn, isWebPlatform]);
871
+ const handlePressOut = (0, import_react6.useCallback)(chain(onPressOut, () => {
872
+ if (!isWebPlatform) setPressed(false);
873
+ }), [onPressOut, isWebPlatform]);
874
+ const handlePointerDown = (0, import_react6.useCallback)(chain(onPointerDown, () => {
875
+ if (!isWebPlatform) setPressed(true);
876
+ }), [onPointerDown, isWebPlatform]);
877
+ const handlePointerUp = (0, import_react6.useCallback)(chain(onPointerUp, () => {
878
+ if (!isWebPlatform) setPressed(false);
879
+ }), [onPointerUp, isWebPlatform]);
880
+ const handlePointerLeave = (0, import_react6.useCallback)(chain(onPointerLeave, () => {
881
+ if (!isWebPlatform) setPressed(false);
882
+ }), [onPointerLeave, isWebPlatform]);
883
+ const handlePointerCancel = (0, import_react6.useCallback)(chain(onPointerCancel, () => {
884
+ if (!isWebPlatform) setPressed(false);
885
+ }), [onPointerCancel, isWebPlatform]);
886
+ const handleMouseEnter = (0, import_react6.useCallback)(chain(onMouseEnter, () => {
887
+ if (!isWebPlatform) setHovered(true);
888
+ }), [onMouseEnter, isWebPlatform]);
889
+ const handleMouseLeave = (0, import_react6.useCallback)(chain(onMouseLeave, () => {
890
+ if (!isWebPlatform) setHovered(false);
891
+ }), [onMouseLeave, isWebPlatform]);
892
+ const handleFocus = (0, import_react6.useCallback)(chain(onFocus, () => {
893
+ if (!isWebPlatform) setFocused(true);
894
+ }), [onFocus, isWebPlatform]);
895
+ const handleBlur = (0, import_react6.useCallback)(chain(onBlur, () => {
896
+ if (!isWebPlatform) setFocused(false);
897
+ }), [onBlur, isWebPlatform]);
898
+ const combined = extraClasses ? `${baseClasses} ${extraClasses}` : baseClasses;
899
+ const firstPassResolved = (0, import_react6.useMemo)(() => (0, import_core7.resolve)(combined, config.theme, config.darkMode), [combined, config.theme, config.darkMode]);
900
+ const webTag = isWebPlatform ? getWebTag(Component, rest) : null;
901
+ const impliedClasses = getImpliedRNClasses(webTag, firstPassResolved.base);
902
+ const finalClassStr = impliedClasses ? `${combined} ${impliedClasses}` : combined;
903
+ const resolved = (0, import_react6.useMemo)(() => (0, import_core7.resolve)(finalClassStr, config.theme, config.darkMode), [finalClassStr, config.theme, config.darkMode]);
904
+ const hasInteractive = (0, import_react6.useMemo)(() => hasInteractiveBuckets(resolved), [resolved]);
905
+ const needsWidth = hasResponsiveBuckets(resolved);
906
+ const width = useConditionalWidth(needsWidth && !isWebPlatform);
907
+ const breakpoints = needsWidth ? (0, import_core7.getActiveBreakpoints)(width) : EMPTY_BREAKPOINTS;
908
+ const screens = (0, import_core7.getGlobalScreens)();
909
+ const computedStyle = (0, import_react6.useMemo)(
910
+ () => isWebPlatform ? {} : (0, import_core7.flatten)(resolved, isDark, { pressed, hover: hovered, focus: focused, disabled, checked }, breakpoints),
911
+ [resolved, isDark, pressed, hovered, focused, disabled, checked, width, screens]
912
+ // eslint-disable-line react-hooks/exhaustive-deps
913
+ );
914
+ const finalStyle = isWebPlatform ? (Array.isArray(styleProp) ? Object.assign({}, ...styleProp) : styleProp) ?? void 0 : composeNativeStyle(computedStyle, styleProp);
915
+ const effectiveComponent = webTag ?? Component;
916
+ const componentName2 = Component.displayName ?? Component.name ?? "";
917
+ const effectiveRest = webTag && componentName2 ? transformToWebProps(componentName2, webTag, rest) : rest;
918
+ return import_react6.default.createElement(effectiveComponent, {
919
+ ref,
920
+ ...effectiveRest,
921
+ style: finalStyle,
922
+ // className lets injected CSS rules (group-hover:, before:, print:, etc.) match the element.
923
+ ...isWebPlatform && finalClassStr ? { className: (0, import_core7.normalizeClassString)(finalClassStr) } : {},
924
+ // Only attach state-tracking handlers when interactive modifiers are present.
925
+ // Always forward user-provided handlers to avoid silently swallowing them.
926
+ // Gated on isNative, not isWeb: isWeb is false during SSR too (no `window` there),
927
+ // and onPressIn/onPressOut must stay excluded there as well — SSR is exactly where
928
+ // getWebTag() above is skipped (it's isWeb-gated), so effectiveComponent may still be
929
+ // a non-string RN-style reference server-side, and this used to forward onPressIn/
930
+ // onPressOut to it unconditionally in that case (isWeb ? ... : ...'s false branch
931
+ // covered both native AND SSR). onPressIn/onPressOut are RN-only prop names — a
932
+ // non-string effectiveComponent on the web/SSR side is just as likely to be an
933
+ // ordinary web component (React Router's <Link>, Next.js's <Link>, any custom
934
+ // wrapper) as an actual react-native-web primitive, and "not a string" alone isn't a
935
+ // reliable signal either way. Forwarding them made React DOM warn "Unknown event
936
+ // handler property" the moment any such component got an interactive modifier
937
+ // (hover:, active:, …), which is the common case, not the exception.
938
+ ...!import_core7.isNative ? hasInteractive ? {
939
+ onPointerDown: handlePointerDown,
940
+ onPointerUp: handlePointerUp,
941
+ onPointerLeave: handlePointerLeave,
942
+ onPointerCancel: handlePointerCancel
943
+ } : {
944
+ onPointerDown,
945
+ onPointerUp,
946
+ onPointerLeave,
947
+ onPointerCancel
948
+ } : hasInteractive ? { onPressIn: handlePressIn, onPressOut: handlePressOut } : { onPressIn, onPressOut },
949
+ onMouseEnter: hasInteractive ? handleMouseEnter : onMouseEnter,
950
+ onMouseLeave: hasInteractive ? handleMouseLeave : onMouseLeave,
951
+ onFocus: hasInteractive ? handleFocus : onFocus,
952
+ onBlur: hasInteractive ? handleBlur : onBlur
953
+ });
954
+ }
955
+ );
956
+ const componentName = Component.displayName ?? Component.name ?? "Component";
957
+ Styled.displayName = `Styled(${componentName})`;
958
+ return Styled;
959
+ }
960
+
961
+ // src/useStyles.ts
962
+ var import_react7 = require("react");
963
+ var import_core8 = require("./core");
964
+ function useStyles(classString, state = {}) {
965
+ const { isDark, config } = useTheme();
966
+ const width = useGlobalWidth();
967
+ const normalised = Array.isArray(classString) ? classString.join(" ") : classString;
968
+ return (0, import_react7.useMemo)(() => {
969
+ const resolved = (0, import_core8.resolve)(normalised, config.theme, config.darkMode);
970
+ const breakpoints = (0, import_core8.getActiveBreakpoints)(width);
971
+ return (0, import_core8.flatten)(resolved, isDark, state, breakpoints);
972
+ }, [normalised, isDark, config.theme, config.darkMode, width, state.hover, state.focus, state.pressed, state.active, state.disabled, state.checked, state.visited, state.placeholder]);
973
+ }
974
+ function useResolvedStyle(classString) {
975
+ const { config } = useTheme();
976
+ const normalised = Array.isArray(classString) ? classString.join(" ") : classString;
977
+ return (0, import_react7.useMemo)(
978
+ () => (0, import_core8.resolve)(normalised, config.theme, config.darkMode),
979
+ [normalised, config]
980
+ );
981
+ }
982
+
983
+ // src/useBreakpoint.ts
984
+ var import_react8 = require("react");
985
+ var import_core9 = require("./core");
986
+ function toNumericScreens(screens) {
987
+ const out = {};
988
+ for (const [name, v] of Object.entries(screens)) {
989
+ const n = typeof v === "number" ? v : parseInt(String(v), 10);
990
+ if (!Number.isNaN(n)) out[name] = n;
991
+ }
992
+ return out;
993
+ }
994
+ function useBreakpoint() {
995
+ const { config } = useTheme();
996
+ const width = useGlobalWidth();
997
+ const screens = config.theme.screens;
998
+ const numericScreens = (0, import_react8.useMemo)(() => toNumericScreens(screens), [screens]);
999
+ return (0, import_react8.useMemo)(() => {
1000
+ const active = (0, import_core9.getActiveBreakpoints)(width, numericScreens);
1001
+ let best = null;
1002
+ let bestMinW = -Infinity;
1003
+ for (const name of active) {
1004
+ const minW = numericScreens[name];
1005
+ if (minW > bestMinW) {
1006
+ bestMinW = minW;
1007
+ best = name;
1008
+ }
1009
+ }
1010
+ return best ?? "xs";
1011
+ }, [numericScreens, width]);
1012
+ }
1013
+ function useResponsive() {
1014
+ const { config } = useTheme();
1015
+ const width = useGlobalWidth();
1016
+ const screens = config.theme.screens;
1017
+ const numericScreens = (0, import_react8.useMemo)(() => toNumericScreens(screens), [screens]);
1018
+ return (0, import_react8.useMemo)(() => {
1019
+ const active = (0, import_core9.getActiveBreakpoints)(width, numericScreens);
1020
+ const result = {};
1021
+ for (const name of Object.keys(numericScreens)) {
1022
+ result[name] = active.has(name);
1023
+ }
1024
+ return result;
1025
+ }, [numericScreens, width]);
1026
+ }
1027
+
1028
+ // src/InteractiveWrapper.tsx
1029
+ var import_react9 = __toESM(require("react"));
1030
+ var import_core10 = require("./core");
1031
+ var InteractiveWrapper = (0, import_react9.forwardRef)(
1032
+ function InteractiveWrapper2({
1033
+ Component,
1034
+ resolvedStyle,
1035
+ className,
1036
+ style: styleProp,
1037
+ onPressIn,
1038
+ onPressOut,
1039
+ onPointerDown,
1040
+ onPointerUp,
1041
+ onPointerLeave,
1042
+ onPointerCancel,
1043
+ onMouseEnter,
1044
+ onMouseLeave,
1045
+ onFocus,
1046
+ onBlur,
1047
+ ...rest
1048
+ }, ref) {
1049
+ const isWebPlatform = (0, import_core10.getEffectiveIsWeb)();
1050
+ const isDark = useConditionalGlobalDarkMode(!isWebPlatform);
1051
+ const needsWidth = hasResponsiveBuckets(resolvedStyle);
1052
+ const width = useConditionalWidth(needsWidth && !isWebPlatform);
1053
+ const breakpoints = needsWidth ? (0, import_core10.getActiveBreakpoints)(width) : EMPTY_BREAKPOINTS;
1054
+ const screens = (0, import_core10.getGlobalScreens)();
1055
+ const [pressed, setPressed] = (0, import_react9.useState)(false);
1056
+ const [hovered, setHovered] = (0, import_react9.useState)(false);
1057
+ const [focused, setFocused] = (0, import_react9.useState)(false);
1058
+ const handlePressIn = (0, import_react9.useCallback)(chain(onPressIn, () => {
1059
+ if (!isWebPlatform) setPressed(true);
1060
+ }), [onPressIn, isWebPlatform]);
1061
+ const handlePressOut = (0, import_react9.useCallback)(chain(onPressOut, () => {
1062
+ if (!isWebPlatform) setPressed(false);
1063
+ }), [onPressOut, isWebPlatform]);
1064
+ const handlePointerDown = (0, import_react9.useCallback)(chain(onPointerDown, () => {
1065
+ if (!isWebPlatform) setPressed(true);
1066
+ }), [onPointerDown, isWebPlatform]);
1067
+ const handlePointerUp = (0, import_react9.useCallback)(chain(onPointerUp, () => {
1068
+ if (!isWebPlatform) setPressed(false);
1069
+ }), [onPointerUp, isWebPlatform]);
1070
+ const handlePointerLeave = (0, import_react9.useCallback)(chain(onPointerLeave, () => {
1071
+ if (!isWebPlatform) setPressed(false);
1072
+ }), [onPointerLeave, isWebPlatform]);
1073
+ const handlePointerCancel = (0, import_react9.useCallback)(chain(onPointerCancel, () => {
1074
+ if (!isWebPlatform) setPressed(false);
1075
+ }), [onPointerCancel, isWebPlatform]);
1076
+ const handleMouseEnter = (0, import_react9.useCallback)(chain(onMouseEnter, () => {
1077
+ if (!isWebPlatform) setHovered(true);
1078
+ }), [onMouseEnter, isWebPlatform]);
1079
+ const handleMouseLeave = (0, import_react9.useCallback)(chain(onMouseLeave, () => {
1080
+ if (!isWebPlatform) setHovered(false);
1081
+ }), [onMouseLeave, isWebPlatform]);
1082
+ const handleFocus = (0, import_react9.useCallback)(chain(onFocus, () => {
1083
+ if (!isWebPlatform) setFocused(true);
1084
+ }), [onFocus, isWebPlatform]);
1085
+ const handleBlur = (0, import_react9.useCallback)(chain(onBlur, () => {
1086
+ if (!isWebPlatform) setFocused(false);
1087
+ }), [onBlur, isWebPlatform]);
1088
+ const { children, disabled, checked, ...restForComponent } = rest;
1089
+ const isNonStringComponent = typeof Component !== "string";
1090
+ const computedStyle = (0, import_react9.useMemo)(
1091
+ () => {
1092
+ if (isWebPlatform) return {};
1093
+ const s = (0, import_core10.flatten)(resolvedStyle, isDark, { pressed, hover: hovered, focus: focused, disabled: !!disabled, checked: !!checked }, breakpoints);
1094
+ stripInternalMarkers(s);
1095
+ if (isNonStringComponent) stripWebOnlyProps(s);
1096
+ return s;
1097
+ },
1098
+ [resolvedStyle, isDark, pressed, hovered, focused, width, screens, disabled, checked, isNonStringComponent]
1099
+ );
1100
+ const skipComputedInline = isWebPlatform;
1101
+ const finalStyle = skipComputedInline ? styleProp ?? void 0 : composeNativeStyle(computedStyle, styleProp);
1102
+ const componentProps = {
1103
+ ref,
1104
+ ...restForComponent,
1105
+ ...disabled !== void 0 ? { disabled } : {},
1106
+ ...checked !== void 0 ? { checked } : {},
1107
+ style: finalStyle,
1108
+ ...!import_core10.isNative && className ? { className } : {},
1109
+ // On web, onPointerDown/Up drive the wrapper's own pressed state (covers mouse + touch) —
1110
+ // onPressIn/onPressOut are RN-only prop names and are never forwarded here, even when
1111
+ // Component isn't a literal HTML tag string. A non-string Component on web is just as
1112
+ // likely to be an ordinary web component (React Router's <Link>, Next.js's <Link>, any
1113
+ // custom wrapper) as an actual react-native-web primitive — "not a string" alone was never
1114
+ // a reliable signal that onPressIn/onPressOut are wanted, and forwarding them
1115
+ // unconditionally made React DOM warn "Unknown event handler property" the moment any web
1116
+ // component got an interactive modifier (hover:, active:, …), which is the common case,
1117
+ // not the exception. (A real react-native-web primitive would additionally have this pair
1118
+ // of props silently vanish after hydration anyway, once the browser-only web-substitution
1119
+ // in jsx-runtime.tsx swaps it for a plain host tag — so keeping them pre-hydration would
1120
+ // only have traded one prop-mismatch warning for another.) Genuinely native code paths
1121
+ // still get them via the isNative branch below.
1122
+ ...!import_core10.isNative ? {
1123
+ onPointerDown: handlePointerDown,
1124
+ onPointerUp: handlePointerUp,
1125
+ onPointerLeave: handlePointerLeave,
1126
+ onPointerCancel: handlePointerCancel
1127
+ } : { onPressIn: handlePressIn, onPressOut: handlePressOut },
1128
+ onMouseEnter: handleMouseEnter,
1129
+ onMouseLeave: handleMouseLeave,
1130
+ onFocus: handleFocus,
1131
+ onBlur: handleBlur
1132
+ };
1133
+ return Array.isArray(children) ? import_react9.default.createElement(Component, componentProps, ...children) : import_react9.default.createElement(Component, componentProps, children);
1134
+ }
1135
+ );
1136
+ InteractiveWrapper.displayName = "Kbach.InteractiveWrapper";
1137
+
1138
+ // src/kb.ts
1139
+ var import_core11 = require("./core");
1140
+ function kb(classString, isDark = false) {
1141
+ const config = (0, import_core11.getConfig)();
1142
+ const resolved = (0, import_core11.resolve)(classString, config.theme, config.darkMode);
1143
+ if ((0, import_core11.getEffectiveIsWeb)()) {
1144
+ return classString;
1145
+ }
1146
+ return (0, import_core11.flatten)(resolved, isDark);
1147
+ }
1148
+ function cx(...classes) {
1149
+ return classes.filter(Boolean).join(" ");
1150
+ }
1151
+
1152
+ // src/index.ts
1153
+ var import_core12 = require("./core");
1154
+ // Annotate the CommonJS export names for ESM import in node:
1155
+ 0 && (module.exports = {
1156
+ InteractiveWrapper,
1157
+ KbachReset,
1158
+ ThemeContext,
1159
+ ThemeProvider,
1160
+ buildConfig,
1161
+ clearCache,
1162
+ cx,
1163
+ defaultColors,
1164
+ defaultTheme,
1165
+ disableRuntimeCSS,
1166
+ flatten,
1167
+ generateKbachTypesDts,
1168
+ getConfig,
1169
+ initConfig,
1170
+ kb,
1171
+ normalizeClassString,
1172
+ parseClass,
1173
+ parseClasses,
1174
+ registerWebElement,
1175
+ resolve,
1176
+ setResolveTarget,
1177
+ splitClassTokens,
1178
+ styled,
1179
+ updateConfig,
1180
+ useBreakpoint,
1181
+ useColors,
1182
+ useGlobalDarkMode,
1183
+ useIsDark,
1184
+ useResolvedStyle,
1185
+ useResponsive,
1186
+ useSpacing,
1187
+ useStyles,
1188
+ useTheme,
1189
+ wrapColors,
1190
+ wrapSpacing
1191
+ });