@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/README.md +53 -27
- package/dist/{chunk-GJSZUC6Q.mjs → chunk-AKX6I7WP.mjs} +1303 -1297
- package/dist/{chunk-YUX2JPTM.mjs → chunk-NWQIZZCW.mjs} +6 -2
- package/dist/core/index.d.ts +1274 -0
- package/dist/core/index.js +3457 -0
- package/dist/index.d.ts +50 -224
- package/dist/index.js +215 -3443
- package/dist/index.mjs +77 -36
- package/dist/jsx-dev-runtime.js +54 -3279
- package/dist/jsx-dev-runtime.mjs +2 -2
- package/dist/jsx-runtime.js +54 -3279
- package/dist/jsx-runtime.mjs +2 -2
- package/dist/vite-plugin.js +1348 -1292
- package/dist/vite-plugin.mjs +1348 -1292
- package/kbach-react.md +15 -1
- package/package.json +4 -8
- package/dist/index.d.mts +0 -455
- package/dist/jsx-dev-runtime.d.mts +0 -21
- package/dist/jsx-runtime.d.mts +0 -17
- package/dist/vite-plugin-client.d.mts +0 -8
- package/dist/vite-plugin-client.d.ts +0 -8
- package/dist/web-substitute-CfpYFnE7.d.mts +0 -22
package/dist/index.mjs
CHANGED
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
useGlobalDarkMode,
|
|
43
43
|
useGlobalWidth,
|
|
44
44
|
useSyncExternalStore
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-AKX6I7WP.mjs";
|
|
46
46
|
|
|
47
47
|
// src/context.tsx
|
|
48
48
|
import { createContext, useContext } from "react";
|
|
@@ -118,12 +118,22 @@ function useColors() {
|
|
|
118
118
|
return useMemo(() => wrapColors(config.theme.colors), [config.theme.colors]);
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
// src/useSpacing.ts
|
|
122
|
+
import { useMemo as useMemo2 } from "react";
|
|
123
|
+
function wrapSpacing(rawSpacing) {
|
|
124
|
+
return rawSpacing;
|
|
125
|
+
}
|
|
126
|
+
function useSpacing() {
|
|
127
|
+
const { config } = useTheme();
|
|
128
|
+
return useMemo2(() => wrapSpacing(config.theme.spacing), [config.theme.spacing]);
|
|
129
|
+
}
|
|
130
|
+
|
|
121
131
|
// src/ThemeProvider.tsx
|
|
122
132
|
import {
|
|
123
133
|
useCallback,
|
|
124
134
|
useEffect,
|
|
125
135
|
useLayoutEffect,
|
|
126
|
-
useMemo as
|
|
136
|
+
useMemo as useMemo3,
|
|
127
137
|
useRef,
|
|
128
138
|
useState
|
|
129
139
|
} from "react";
|
|
@@ -132,6 +142,8 @@ var useIsomorphicLayoutEffect = isWeb || isNative ? useLayoutEffect : useEffect;
|
|
|
132
142
|
var STORAGE_KEY = "kbach-theme";
|
|
133
143
|
var _mountedProviderCount = 0;
|
|
134
144
|
var _warnedMultipleProviders = false;
|
|
145
|
+
var _mountedConfigOverrideCount = 0;
|
|
146
|
+
var _warnedConfigOverride = false;
|
|
135
147
|
function loadPersistedMode() {
|
|
136
148
|
try {
|
|
137
149
|
if (isWeb) return localStorage.getItem(STORAGE_KEY);
|
|
@@ -183,21 +195,38 @@ function ThemeProvider({
|
|
|
183
195
|
const [resolvedConfig, setResolvedConfig] = useState(
|
|
184
196
|
() => configOverride ? buildConfig(configOverride) : getConfig()
|
|
185
197
|
);
|
|
198
|
+
const _prevConfigOverrideRef = useRef(void 0);
|
|
199
|
+
if (configOverride && _prevConfigOverrideRef.current !== configOverride) {
|
|
200
|
+
_prevConfigOverrideRef.current = configOverride;
|
|
201
|
+
updateConfig(configOverride);
|
|
202
|
+
const fresh = getConfig();
|
|
203
|
+
if (fresh !== resolvedConfig) setResolvedConfig(fresh);
|
|
204
|
+
}
|
|
186
205
|
useEffect(() => {
|
|
187
206
|
_mountedProviderCount++;
|
|
188
|
-
if (
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
207
|
+
if (configOverride) _mountedConfigOverrideCount++;
|
|
208
|
+
if (process.env.NODE_ENV !== "production") {
|
|
209
|
+
if (_mountedProviderCount > 1 && !_warnedMultipleProviders) {
|
|
210
|
+
_warnedMultipleProviders = true;
|
|
211
|
+
kbachWarn(
|
|
212
|
+
"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."
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
if (_mountedConfigOverrideCount > 1 && !_warnedConfigOverride) {
|
|
216
|
+
_warnedConfigOverride = true;
|
|
217
|
+
kbachWarn(
|
|
218
|
+
"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>."
|
|
219
|
+
);
|
|
220
|
+
}
|
|
193
221
|
}
|
|
194
222
|
return () => {
|
|
195
223
|
_mountedProviderCount--;
|
|
224
|
+
if (configOverride) _mountedConfigOverrideCount--;
|
|
196
225
|
};
|
|
197
226
|
}, []);
|
|
198
227
|
const [webWidth, setWebWidth] = useState(0);
|
|
199
228
|
const effectiveWidth = windowWidthProp ?? (isWeb ? webWidth : 0);
|
|
200
|
-
const numericScreens =
|
|
229
|
+
const numericScreens = useMemo3(() => {
|
|
201
230
|
const out = {};
|
|
202
231
|
for (const [k, v] of Object.entries(resolvedConfig.theme.screens ?? {})) {
|
|
203
232
|
out[k] = typeof v === "number" ? v : parseInt(String(v), 10);
|
|
@@ -272,11 +301,6 @@ function ThemeProvider({
|
|
|
272
301
|
applyWebTheme(resolvedMode, resolvedConfig.darkMode);
|
|
273
302
|
setGlobalDarkMode(isDark);
|
|
274
303
|
}, [isDark, resolvedMode, resolvedConfig.darkMode]);
|
|
275
|
-
useEffect(() => {
|
|
276
|
-
if (!configOverride) return;
|
|
277
|
-
updateConfig(configOverride);
|
|
278
|
-
setResolvedConfig(getConfig());
|
|
279
|
-
}, [configOverride]);
|
|
280
304
|
useEffect(() => {
|
|
281
305
|
if (configOverride) return;
|
|
282
306
|
let mounted = true;
|
|
@@ -288,7 +312,7 @@ function ThemeProvider({
|
|
|
288
312
|
unsub();
|
|
289
313
|
};
|
|
290
314
|
}, [configOverride]);
|
|
291
|
-
const contextValue =
|
|
315
|
+
const contextValue = useMemo3(
|
|
292
316
|
() => ({ mode, resolvedMode, isDark, setMode, toggle, config: resolvedConfig }),
|
|
293
317
|
[mode, resolvedMode, isDark, setMode, toggle, resolvedConfig]
|
|
294
318
|
);
|
|
@@ -307,7 +331,7 @@ import React2, {
|
|
|
307
331
|
forwardRef,
|
|
308
332
|
useState as useState2,
|
|
309
333
|
useCallback as useCallback2,
|
|
310
|
-
useMemo as
|
|
334
|
+
useMemo as useMemo4
|
|
311
335
|
} from "react";
|
|
312
336
|
function styled(Component, baseClasses = "") {
|
|
313
337
|
const Styled = forwardRef(
|
|
@@ -366,12 +390,12 @@ function styled(Component, baseClasses = "") {
|
|
|
366
390
|
if (!isWebPlatform) setFocused(false);
|
|
367
391
|
}), [onBlur, isWebPlatform]);
|
|
368
392
|
const combined = extraClasses ? `${baseClasses} ${extraClasses}` : baseClasses;
|
|
369
|
-
const resolved =
|
|
370
|
-
const hasInteractive =
|
|
393
|
+
const resolved = useMemo4(() => resolve(combined, config.theme, config.darkMode), [combined, config.theme, config.darkMode]);
|
|
394
|
+
const hasInteractive = useMemo4(() => hasInteractiveBuckets(resolved), [resolved]);
|
|
371
395
|
const needsWidth = hasResponsiveBuckets(resolved);
|
|
372
396
|
const width = useConditionalWidth(needsWidth && !isWebPlatform);
|
|
373
397
|
const breakpoints = needsWidth ? getActiveBreakpoints(width) : EMPTY_BREAKPOINTS;
|
|
374
|
-
const computedStyle =
|
|
398
|
+
const computedStyle = useMemo4(
|
|
375
399
|
() => isWebPlatform ? {} : flatten(resolved, isDark, { pressed, hover: hovered, focus: focused, disabled, checked }, breakpoints),
|
|
376
400
|
[resolved, isDark, pressed, hovered, focused, disabled, checked, width]
|
|
377
401
|
// eslint-disable-line react-hooks/exhaustive-deps
|
|
@@ -426,12 +450,12 @@ function styled(Component, baseClasses = "") {
|
|
|
426
450
|
}
|
|
427
451
|
|
|
428
452
|
// src/useStyles.ts
|
|
429
|
-
import { useMemo as
|
|
453
|
+
import { useMemo as useMemo5 } from "react";
|
|
430
454
|
function useStyles(classString, state = {}) {
|
|
431
455
|
const { isDark, config } = useTheme();
|
|
432
456
|
const width = useGlobalWidth();
|
|
433
457
|
const normalised = Array.isArray(classString) ? classString.join(" ") : classString;
|
|
434
|
-
return
|
|
458
|
+
return useMemo5(() => {
|
|
435
459
|
const resolved = resolve(normalised, config.theme, config.darkMode);
|
|
436
460
|
const breakpoints = getActiveBreakpoints(width);
|
|
437
461
|
return flatten(resolved, isDark, state, breakpoints);
|
|
@@ -440,39 +464,54 @@ function useStyles(classString, state = {}) {
|
|
|
440
464
|
function useResolvedStyle(classString) {
|
|
441
465
|
const { config } = useTheme();
|
|
442
466
|
const normalised = Array.isArray(classString) ? classString.join(" ") : classString;
|
|
443
|
-
return
|
|
467
|
+
return useMemo5(
|
|
444
468
|
() => resolve(normalised, config.theme, config.darkMode),
|
|
445
469
|
[normalised, config]
|
|
446
470
|
);
|
|
447
471
|
}
|
|
448
472
|
|
|
449
473
|
// src/useBreakpoint.ts
|
|
450
|
-
import { useMemo as
|
|
474
|
+
import { useMemo as useMemo6 } from "react";
|
|
475
|
+
function toNumericScreens(screens) {
|
|
476
|
+
const out = {};
|
|
477
|
+
for (const [name, v] of Object.entries(screens)) {
|
|
478
|
+
const n = typeof v === "number" ? v : parseInt(String(v), 10);
|
|
479
|
+
if (!Number.isNaN(n)) out[name] = n;
|
|
480
|
+
}
|
|
481
|
+
return out;
|
|
482
|
+
}
|
|
451
483
|
function useBreakpoint() {
|
|
452
484
|
const { config } = useTheme();
|
|
453
485
|
const width = useGlobalWidth();
|
|
454
486
|
const screens = config.theme.screens;
|
|
455
|
-
const
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
487
|
+
const numericScreens = useMemo6(() => toNumericScreens(screens), [screens]);
|
|
488
|
+
return useMemo6(() => {
|
|
489
|
+
const active = getActiveBreakpoints(width, numericScreens);
|
|
490
|
+
let best = null;
|
|
491
|
+
let bestMinW = -Infinity;
|
|
492
|
+
for (const name of active) {
|
|
493
|
+
const minW = numericScreens[name];
|
|
494
|
+
if (minW > bestMinW) {
|
|
495
|
+
bestMinW = minW;
|
|
496
|
+
best = name;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return best ?? "xs";
|
|
500
|
+
}, [numericScreens, width]);
|
|
463
501
|
}
|
|
464
502
|
function useResponsive() {
|
|
465
503
|
const { config } = useTheme();
|
|
466
504
|
const width = useGlobalWidth();
|
|
467
505
|
const screens = config.theme.screens;
|
|
468
|
-
|
|
506
|
+
const numericScreens = useMemo6(() => toNumericScreens(screens), [screens]);
|
|
507
|
+
return useMemo6(() => {
|
|
508
|
+
const active = getActiveBreakpoints(width, numericScreens);
|
|
469
509
|
const result = {};
|
|
470
|
-
for (const
|
|
471
|
-
|
|
472
|
-
if (!Number.isNaN(minW)) result[name] = width >= minW;
|
|
510
|
+
for (const name of Object.keys(numericScreens)) {
|
|
511
|
+
result[name] = active.has(name);
|
|
473
512
|
}
|
|
474
513
|
return result;
|
|
475
|
-
}, [
|
|
514
|
+
}, [numericScreens, width]);
|
|
476
515
|
}
|
|
477
516
|
|
|
478
517
|
// src/kb.ts
|
|
@@ -517,7 +556,9 @@ export {
|
|
|
517
556
|
useIsDark,
|
|
518
557
|
useResolvedStyle,
|
|
519
558
|
useResponsive,
|
|
559
|
+
useSpacing,
|
|
520
560
|
useStyles,
|
|
521
561
|
useTheme,
|
|
522
|
-
wrapColors
|
|
562
|
+
wrapColors,
|
|
563
|
+
wrapSpacing
|
|
523
564
|
};
|