@kbach/react 0.6.0 → 0.6.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,6 +1,7 @@
1
1
  import {
2
2
  EMPTY_BREAKPOINTS,
3
3
  InteractiveWrapper,
4
+ chain,
4
5
  getWebTag,
5
6
  hasInteractiveBuckets,
6
7
  hasResponsiveBuckets,
@@ -10,10 +11,12 @@ import {
10
11
  transformToWebProps,
11
12
  useConditionalWidth,
12
13
  useGlobalDarkMode,
13
- useGlobalWidth
14
- } from "./chunk-D4LJICWZ.mjs";
14
+ useGlobalWidth,
15
+ useSyncExternalStore
16
+ } from "./chunk-36QRQNPL.mjs";
15
17
  import {
16
18
  buildConfig,
19
+ clearCache,
17
20
  defaultColors,
18
21
  defaultTheme,
19
22
  disableRuntimeCSS,
@@ -26,13 +29,15 @@ import {
26
29
  onConfigChange,
27
30
  parseClass,
28
31
  parseClasses,
32
+ parseHexRgb,
29
33
  resolve,
30
34
  setGlobalWidth,
35
+ setResolveTarget,
31
36
  splitClassTokens,
32
37
  syncGlobalScreens,
33
38
  syncGlobalWidth,
34
39
  updateConfig
35
- } from "./chunk-6NED62DB.mjs";
40
+ } from "./chunk-MPHPB357.mjs";
36
41
 
37
42
  // src/context.tsx
38
43
  import { createContext, useContext } from "react";
@@ -55,22 +60,10 @@ import { useMemo } from "react";
55
60
  function applyOpacity(color, opacity) {
56
61
  const a = Math.max(0, Math.min(1, opacity / 100));
57
62
  if (color.startsWith("#")) {
58
- const h = color.slice(1);
59
- let rs, gs, bs;
60
- if (h.length === 3 || h.length === 4) {
61
- rs = h[0] + h[0];
62
- gs = h[1] + h[1];
63
- bs = h[2] + h[2];
64
- } else if (h.length === 8) {
65
- rs = h.slice(0, 2);
66
- gs = h.slice(2, 4);
67
- bs = h.slice(4, 6);
68
- } else {
69
- rs = h.slice(0, 2);
70
- gs = h.slice(2, 4);
71
- bs = h.slice(4, 6);
72
- }
73
- return `rgba(${parseInt(rs, 16)},${parseInt(gs, 16)},${parseInt(bs, 16)},${a})`;
63
+ const rgb = parseHexRgb(color);
64
+ if (!rgb) return color;
65
+ const [r, g, b] = rgb;
66
+ return `rgba(${r},${g},${b},${a})`;
74
67
  }
75
68
  if (color.startsWith("rgb(")) return color.replace("rgb(", "rgba(").replace(")", `,${a})`);
76
69
  if (color.startsWith("rgba(")) return color.replace(/,\s*[\d.]+\)$/, `,${a})`);
@@ -144,6 +137,22 @@ function persistMode(mode) {
144
137
  } catch {
145
138
  }
146
139
  }
140
+ function subscribeSystemScheme(callback) {
141
+ if (!isWeb || typeof window === "undefined") return () => {
142
+ };
143
+ const mq = window.matchMedia?.("(prefers-color-scheme: dark)");
144
+ if (!mq) return () => {
145
+ };
146
+ mq.addEventListener("change", callback);
147
+ return () => mq.removeEventListener("change", callback);
148
+ }
149
+ function getSystemScheme() {
150
+ if (!isWeb || typeof window === "undefined") return "light";
151
+ return window.matchMedia?.("(prefers-color-scheme: dark)")?.matches ? "dark" : "light";
152
+ }
153
+ function getSystemSchemeServerSnapshot() {
154
+ return "light";
155
+ }
147
156
  function applyWebTheme(resolvedMode, strategy) {
148
157
  if (!isWeb) return;
149
158
  const root = document.documentElement;
@@ -165,9 +174,7 @@ function ThemeProvider({
165
174
  const [resolvedConfig, setResolvedConfig] = useState(
166
175
  () => configOverride ? buildConfig(configOverride) : getConfig()
167
176
  );
168
- const [webWidth, setWebWidth] = useState(
169
- () => isWeb && typeof window !== "undefined" ? window.innerWidth : 0
170
- );
177
+ const [webWidth, setWebWidth] = useState(0);
171
178
  const effectiveWidth = windowWidthProp ?? (isWeb ? webWidth : 0);
172
179
  const numericScreens = useMemo2(() => {
173
180
  const out = {};
@@ -191,6 +198,7 @@ function ThemeProvider({
191
198
  }, [effectiveWidth]);
192
199
  useEffect(() => {
193
200
  if (!isWeb || typeof window === "undefined") return;
201
+ setWebWidth(window.innerWidth);
194
202
  let raf = 0;
195
203
  const update = () => {
196
204
  cancelAnimationFrame(raf);
@@ -206,20 +214,18 @@ function ThemeProvider({
206
214
  cancelAnimationFrame(raf);
207
215
  };
208
216
  }, []);
209
- const [webScheme, setWebScheme] = useState(() => {
210
- if (isWeb && typeof window !== "undefined") {
211
- return window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
212
- }
213
- return "light";
214
- });
217
+ const webScheme = useSyncExternalStore(
218
+ subscribeSystemScheme,
219
+ getSystemScheme,
220
+ getSystemSchemeServerSnapshot
221
+ );
215
222
  const systemScheme = isWeb ? webScheme : colorScheme === "dark" ? "dark" : "light";
216
- const [mode, _setMode] = useState(() => {
217
- if (!disablePersistence) {
218
- const persisted = loadPersistedMode();
219
- if (persisted) return persisted;
220
- }
221
- return defaultMode;
222
- });
223
+ const [mode, _setMode] = useState(defaultMode);
224
+ useEffect(() => {
225
+ if (disablePersistence) return;
226
+ const persisted = loadPersistedMode();
227
+ if (persisted) _setMode(persisted);
228
+ }, []);
223
229
  const setMode = useCallback((next) => {
224
230
  _setMode(next);
225
231
  if (!disablePersistence) persistMode(next);
@@ -234,18 +240,6 @@ function ThemeProvider({
234
240
  applyWebTheme(resolvedMode, resolvedConfig.darkMode);
235
241
  setGlobalDarkMode(isDark);
236
242
  }, [isDark, resolvedMode, resolvedConfig.darkMode]);
237
- const setWebSchemeRef = useRef(setWebScheme);
238
- setWebSchemeRef.current = setWebScheme;
239
- useEffect(() => {
240
- if (!isWeb || typeof window === "undefined") return;
241
- const mq = window.matchMedia?.("(prefers-color-scheme: dark)");
242
- if (!mq) return;
243
- const handler = (e) => {
244
- setWebSchemeRef.current(e.matches ? "dark" : "light");
245
- };
246
- mq.addEventListener("change", handler);
247
- return () => mq.removeEventListener("change", handler);
248
- }, []);
249
243
  useEffect(() => {
250
244
  if (!configOverride) return;
251
245
  updateConfig(configOverride);
@@ -287,6 +281,7 @@ function styled(Component, baseClasses = "") {
287
281
  onPointerDown,
288
282
  onPointerUp,
289
283
  onPointerLeave,
284
+ onPointerCancel,
290
285
  onMouseEnter,
291
286
  onMouseLeave,
292
287
  onFocus,
@@ -300,42 +295,16 @@ function styled(Component, baseClasses = "") {
300
295
  const [pressed, setPressed] = useState2(false);
301
296
  const [hovered, setHovered] = useState2(false);
302
297
  const [focused, setFocused] = useState2(false);
303
- const handlePressIn = useCallback2((e) => {
304
- setPressed(true);
305
- onPressIn?.(e);
306
- }, [onPressIn]);
307
- const handlePressOut = useCallback2((e) => {
308
- setPressed(false);
309
- onPressOut?.(e);
310
- }, [onPressOut]);
311
- const handlePointerDown = useCallback2((e) => {
312
- setPressed(true);
313
- onPointerDown?.(e);
314
- }, [onPointerDown]);
315
- const handlePointerUp = useCallback2((e) => {
316
- setPressed(false);
317
- onPointerUp?.(e);
318
- }, [onPointerUp]);
319
- const handlePointerLeave = useCallback2((e) => {
320
- setPressed(false);
321
- onPointerLeave?.(e);
322
- }, [onPointerLeave]);
323
- const handleMouseEnter = useCallback2((e) => {
324
- setHovered(true);
325
- onMouseEnter?.(e);
326
- }, [onMouseEnter]);
327
- const handleMouseLeave = useCallback2((e) => {
328
- setHovered(false);
329
- onMouseLeave?.(e);
330
- }, [onMouseLeave]);
331
- const handleFocus = useCallback2((e) => {
332
- setFocused(true);
333
- onFocus?.(e);
334
- }, [onFocus]);
335
- const handleBlur = useCallback2((e) => {
336
- setFocused(false);
337
- onBlur?.(e);
338
- }, [onBlur]);
298
+ const handlePressIn = useCallback2(chain(onPressIn, () => setPressed(true)), [onPressIn]);
299
+ const handlePressOut = useCallback2(chain(onPressOut, () => setPressed(false)), [onPressOut]);
300
+ const handlePointerDown = useCallback2(chain(onPointerDown, () => setPressed(true)), [onPointerDown]);
301
+ const handlePointerUp = useCallback2(chain(onPointerUp, () => setPressed(false)), [onPointerUp]);
302
+ const handlePointerLeave = useCallback2(chain(onPointerLeave, () => setPressed(false)), [onPointerLeave]);
303
+ const handlePointerCancel = useCallback2(chain(onPointerCancel, () => setPressed(false)), [onPointerCancel]);
304
+ const handleMouseEnter = useCallback2(chain(onMouseEnter, () => setHovered(true)), [onMouseEnter]);
305
+ const handleMouseLeave = useCallback2(chain(onMouseLeave, () => setHovered(false)), [onMouseLeave]);
306
+ const handleFocus = useCallback2(chain(onFocus, () => setFocused(true)), [onFocus]);
307
+ const handleBlur = useCallback2(chain(onBlur, () => setFocused(false)), [onBlur]);
339
308
  const combined = extraClasses ? `${baseClasses} ${extraClasses}` : baseClasses;
340
309
  const resolved = useMemo3(() => resolve(combined, config.theme, config.darkMode), [combined, config.theme, config.darkMode]);
341
310
  const hasInteractive = useMemo3(() => hasInteractiveBuckets(resolved), [resolved]);
@@ -363,7 +332,7 @@ function styled(Component, baseClasses = "") {
363
332
  // Always forward user-provided handlers to avoid silently swallowing them.
364
333
  // onPressIn/onPressOut are forwarded on web too (not just native) since
365
334
  // react-native-web components rely on receiving them directly.
366
- ...isWeb ? hasInteractive ? { onPointerDown: handlePointerDown, onPointerUp: handlePointerUp, onPointerLeave: handlePointerLeave, onPointerCancel: handlePointerLeave, onPressIn, onPressOut } : { onPointerDown, onPointerUp, onPointerLeave, onPressIn, onPressOut } : hasInteractive ? { onPressIn: handlePressIn, onPressOut: handlePressOut } : { onPressIn, onPressOut },
335
+ ...isWeb ? hasInteractive ? { onPointerDown: handlePointerDown, onPointerUp: handlePointerUp, onPointerLeave: handlePointerLeave, onPointerCancel: handlePointerCancel, onPressIn, onPressOut } : { onPointerDown, onPointerUp, onPointerLeave, onPointerCancel, onPressIn, onPressOut } : hasInteractive ? { onPressIn: handlePressIn, onPressOut: handlePressOut } : { onPressIn, onPressOut },
367
336
  onMouseEnter: hasInteractive ? handleMouseEnter : onMouseEnter,
368
337
  onMouseLeave: hasInteractive ? handleMouseLeave : onMouseLeave,
369
338
  onFocus: hasInteractive ? handleFocus : onFocus,
@@ -404,7 +373,7 @@ function useBreakpoint() {
404
373
  const width = useGlobalWidth();
405
374
  const screens = config.theme.screens;
406
375
  const sorted = useMemo5(
407
- () => Object.entries(screens).filter((entry) => typeof entry[1] === "number").sort(([, a], [, b]) => b - a),
376
+ () => Object.entries(screens).map(([name, v]) => [name, typeof v === "number" ? v : parseInt(String(v), 10)]).filter(([, minW]) => !Number.isNaN(minW)).sort(([, a], [, b]) => b - a),
408
377
  [screens]
409
378
  );
410
379
  for (const [name, minW] of sorted) {
@@ -418,8 +387,9 @@ function useResponsive() {
418
387
  const screens = config.theme.screens;
419
388
  return useMemo5(() => {
420
389
  const result = {};
421
- for (const [name, minW] of Object.entries(screens)) {
422
- if (typeof minW === "number") result[name] = width >= minW;
390
+ for (const [name, v] of Object.entries(screens)) {
391
+ const minW = typeof v === "number" ? v : parseInt(String(v), 10);
392
+ if (!Number.isNaN(minW)) result[name] = width >= minW;
423
393
  }
424
394
  return result;
425
395
  }, [screens, width]);
@@ -442,6 +412,7 @@ export {
442
412
  ThemeContext,
443
413
  ThemeProvider,
444
414
  buildConfig,
415
+ clearCache,
445
416
  cx,
446
417
  defaultColors,
447
418
  defaultTheme,
@@ -455,6 +426,7 @@ export {
455
426
  parseClasses,
456
427
  registerWebElement,
457
428
  resolve,
429
+ setResolveTarget,
458
430
  splitClassTokens,
459
431
  styled,
460
432
  updateConfig,