@kbach/react 1.0.0-beta.12 → 1.0.0-beta.14
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 +36 -22
- package/dist/{chunk-L6B4DTLD.mjs → chunk-D7OC2AE7.mjs} +1 -1
- package/dist/{chunk-ROKZPEHA.mjs → chunk-KJY3W4GF.mjs} +17 -3
- package/dist/{chunk-EOSN5CYG.mjs → chunk-OVKVZA7B.mjs} +8 -0
- package/dist/{chunk-4Y2QXNJY.mjs → chunk-OWWJ2PME.mjs} +102 -1
- package/dist/{chunk-J2M6QWJW.mjs → chunk-XV2ZLURB.mjs} +5 -7
- package/dist/{config-BQ_b-qxF.d.mts → config-B00tH6vN.d.mts} +12 -1
- package/dist/{config-BQ_b-qxF.d.ts → config-B00tH6vN.d.ts} +12 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +90 -64
- package/dist/index.mjs +21 -103
- package/dist/jsx-dev-runtime.js +16 -2
- package/dist/jsx-dev-runtime.mjs +3 -3
- package/dist/jsx-runtime.js +16 -2
- package/dist/jsx-runtime.mjs +3 -3
- package/dist/postcss-plugin.d.mts +1 -1
- package/dist/postcss-plugin.d.ts +1 -1
- package/dist/postcss-plugin.js +73 -5
- package/dist/postcss-plugin.mjs +3 -3
- package/dist/vite-plugin.d.mts +1 -1
- package/dist/vite-plugin.d.ts +1 -1
- package/dist/vite-plugin.js +73 -5
- package/dist/vite-plugin.mjs +3 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -199,31 +199,24 @@ imports anything from `@kbach/react`'s runtime:
|
|
|
199
199
|
This default (`darkMode: 'media'`) can't be overridden by an in-app toggle —
|
|
200
200
|
`@media (prefers-color-scheme)` only ever reflects the real OS setting. To
|
|
201
201
|
add a manual light/dark switcher, opt into `darkMode: 'class'` or
|
|
202
|
-
`'attribute'` (writes `.dark`/`data-theme` onto `<html>` instead)
|
|
203
|
-
needs setting in **two places**, since they solve two different problems:
|
|
204
|
-
|
|
205
|
-
1. **Build-time**, via `kbach.config.js` or the plugin's `config`/`theme`
|
|
206
|
-
option — controls which selector the generated CSS for `dark:` classes
|
|
207
|
-
compiles to (`[data-theme="dark"] .dark\:bg-neutral-12` vs
|
|
208
|
-
`.dark .dark\:bg-neutral-12` vs a plain `@media` query).
|
|
209
|
-
2. **Runtime**, via `applyKbachConfig()` — controls what `useTheme()`'s
|
|
210
|
-
`toggle()`/`setMode()` actually write to the DOM. This is a *separate*
|
|
211
|
-
module from the build step above (it has to be: the plugin runs in
|
|
212
|
-
Node during your build, this runs in the browser) — setting only the
|
|
213
|
-
plugin option compiles the right CSS but leaves the toggle a silent
|
|
214
|
-
no-op, since the runtime still thinks the strategy is the `'media'`
|
|
215
|
-
default and has nothing to write to the DOM for it.
|
|
202
|
+
`'attribute'` (writes `.dark`/`data-theme` onto `<html>` instead):
|
|
216
203
|
|
|
217
204
|
```js
|
|
218
|
-
// kbach.config.js —
|
|
205
|
+
// kbach.config.js — a plain object, auto-discovered by the plugin at your
|
|
206
|
+
// project root, no import needed in vite.config.ts/postcss.config.js
|
|
219
207
|
export default { darkMode: 'attribute' };
|
|
220
208
|
```
|
|
221
209
|
|
|
222
|
-
```
|
|
223
|
-
//
|
|
224
|
-
import {
|
|
210
|
+
```ts
|
|
211
|
+
// vite.config.ts — no `config`/`theme` option needed
|
|
212
|
+
import { kbach } from '@kbach/react/vite';
|
|
225
213
|
|
|
226
|
-
|
|
214
|
+
export default defineConfig({ plugins: [kbach(), react()] });
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
```tsx
|
|
218
|
+
// app entry — no applyKbachConfig() call needed either
|
|
219
|
+
import { useTheme } from '@kbach/react';
|
|
227
220
|
|
|
228
221
|
function ThemeToggle() {
|
|
229
222
|
const { mode, isDark, setMode, toggle } = useTheme();
|
|
@@ -231,13 +224,34 @@ function ThemeToggle() {
|
|
|
231
224
|
}
|
|
232
225
|
```
|
|
233
226
|
|
|
227
|
+
That's the whole setup — one file, no runtime call. The generated CSS
|
|
228
|
+
carries the strategy it was built with (as a `--kb-dark-mode` custom
|
|
229
|
+
property), and `useTheme()`'s store reads it back from the DOM at startup,
|
|
230
|
+
so build-time and runtime always agree automatically.
|
|
231
|
+
|
|
232
|
+
If you're not using the static plugin at all (a pure runtime `kb()` setup,
|
|
233
|
+
with no build step generating `dark:` CSS ahead of time), there's nothing
|
|
234
|
+
for the runtime to auto-detect — call `applyKbachConfig({ darkMode: '...' })`
|
|
235
|
+
yourself instead, once, before your first render:
|
|
236
|
+
|
|
237
|
+
```tsx
|
|
238
|
+
import { applyKbachConfig, useTheme } from '@kbach/react';
|
|
239
|
+
|
|
240
|
+
applyKbachConfig({ darkMode: 'attribute' });
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
An explicit `applyKbachConfig()` call always overrides whatever was
|
|
244
|
+
auto-detected, if you ever need one — e.g. switching strategy at runtime for
|
|
245
|
+
some reason. Keep the value in one shared `kbach.config.js` and import it on
|
|
246
|
+
both sides rather than typing the same literal twice, if you do reach for it.
|
|
247
|
+
|
|
234
248
|
Works anywhere, no provider needed. `<ThemeProvider defaultMode="dark">` is
|
|
235
249
|
optional, for seeding a startup default. Outside React (plain functions,
|
|
236
250
|
event handlers), use `getGlobalDarkMode()`/`toggleGlobalDarkMode()` instead.
|
|
237
251
|
Note: `useTheme()`/`toggleGlobalDarkMode()` still track `isDark` correctly
|
|
238
|
-
under the default `'media'` strategy too (and even without
|
|
239
|
-
|
|
240
|
-
|
|
252
|
+
under the default `'media'` strategy too (and even without any of the above)
|
|
253
|
+
— they just won't visibly affect `dark:` classes unless the runtime has also
|
|
254
|
+
learned about `'class'`/`'attribute'`, one way or another.
|
|
241
255
|
|
|
242
256
|
## Theming
|
|
243
257
|
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
BASE_RESET,
|
|
3
3
|
RESET_STYLE_ID,
|
|
4
4
|
getThemeJson
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-OVKVZA7B.mjs";
|
|
6
6
|
|
|
7
7
|
// src/wasmLoader.ts
|
|
8
8
|
import init, { generate_css as wasmGenerateCss } from "@kbach/core-engine";
|
|
@@ -79,9 +79,23 @@ function ensureResetInjected() {
|
|
|
79
79
|
el.textContent = BASE_RESET;
|
|
80
80
|
document.head.insertBefore(el, document.head.firstChild);
|
|
81
81
|
}
|
|
82
|
+
var KB_CACHE_MAX = 500;
|
|
83
|
+
var kbCache = /* @__PURE__ */ new Map();
|
|
84
|
+
var cachedForThemeJson = null;
|
|
82
85
|
function kb(classString) {
|
|
83
|
-
const
|
|
84
|
-
|
|
86
|
+
const themeJson = getThemeJson();
|
|
87
|
+
if (themeJson !== cachedForThemeJson) {
|
|
88
|
+
kbCache.clear();
|
|
89
|
+
cachedForThemeJson = themeJson;
|
|
90
|
+
}
|
|
91
|
+
let result = kbCache.get(classString);
|
|
92
|
+
if (result === void 0) {
|
|
93
|
+
const json = generateCss(classString, themeJson);
|
|
94
|
+
result = JSON.parse(json);
|
|
95
|
+
if (kbCache.size >= KB_CACHE_MAX) kbCache.clear();
|
|
96
|
+
kbCache.set(classString, result);
|
|
97
|
+
}
|
|
98
|
+
const { className, rules } = result;
|
|
85
99
|
if (!runtimeCSSDisabled) {
|
|
86
100
|
ensureResetInjected();
|
|
87
101
|
for (const { rule, order } of rules) {
|
|
@@ -377,6 +377,13 @@ function getTheme() {
|
|
|
377
377
|
function getThemeJson() {
|
|
378
378
|
return activeThemeJson;
|
|
379
379
|
}
|
|
380
|
+
var DARK_MODE_STRATEGIES = /* @__PURE__ */ new Set(["attribute", "class", "media"]);
|
|
381
|
+
function detectDarkModeStrategyFromDom() {
|
|
382
|
+
if (typeof document === "undefined") return;
|
|
383
|
+
const raw = getComputedStyle(document.documentElement).getPropertyValue("--kb-dark-mode").trim();
|
|
384
|
+
if (!DARK_MODE_STRATEGIES.has(raw) || raw === activeTheme.darkMode) return;
|
|
385
|
+
setTheme({ ...activeTheme, darkMode: raw });
|
|
386
|
+
}
|
|
380
387
|
|
|
381
388
|
// src/reset.ts
|
|
382
389
|
var RESET_STYLE_ID = "kbach-reset";
|
|
@@ -467,6 +474,7 @@ export {
|
|
|
467
474
|
setTheme,
|
|
468
475
|
getTheme,
|
|
469
476
|
getThemeJson,
|
|
477
|
+
detectDarkModeStrategyFromDom,
|
|
470
478
|
RESET_STYLE_ID,
|
|
471
479
|
BASE_RESET,
|
|
472
480
|
buildResetCSS
|
|
@@ -1,7 +1,101 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defaultTheme,
|
|
3
|
+
detectDarkModeStrategyFromDom,
|
|
4
|
+
getTheme,
|
|
3
5
|
setTheme
|
|
4
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-OVKVZA7B.mjs";
|
|
7
|
+
|
|
8
|
+
// src/darkModeStore.ts
|
|
9
|
+
var STORAGE_KEY = "kbach-theme";
|
|
10
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
11
|
+
function systemPrefersDark() {
|
|
12
|
+
if (typeof window === "undefined" || !window.matchMedia) return false;
|
|
13
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
14
|
+
}
|
|
15
|
+
function storage() {
|
|
16
|
+
return typeof window === "undefined" ? null : window.localStorage;
|
|
17
|
+
}
|
|
18
|
+
function readPersistedMode() {
|
|
19
|
+
const ls = storage();
|
|
20
|
+
if (!ls) return null;
|
|
21
|
+
try {
|
|
22
|
+
const raw = ls.getItem(STORAGE_KEY);
|
|
23
|
+
return raw === "light" || raw === "dark" || raw === "system" ? raw : null;
|
|
24
|
+
} catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function resolveIsDark(m) {
|
|
29
|
+
return m === "system" ? systemPrefersDark() : m === "dark";
|
|
30
|
+
}
|
|
31
|
+
function applyToDom(dark) {
|
|
32
|
+
if (typeof document === "undefined") return;
|
|
33
|
+
const root = document.documentElement;
|
|
34
|
+
const strategy = getTheme().darkMode;
|
|
35
|
+
root.classList.toggle("dark", strategy === "class" && dark);
|
|
36
|
+
root.classList.toggle("light", strategy === "class" && !dark);
|
|
37
|
+
if (strategy === "attribute") {
|
|
38
|
+
root.setAttribute("data-theme", dark ? "dark" : "light");
|
|
39
|
+
} else {
|
|
40
|
+
root.removeAttribute("data-theme");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
detectDarkModeStrategyFromDom();
|
|
44
|
+
var persistedMode = readPersistedMode();
|
|
45
|
+
var hadPersistedMode = persistedMode !== null;
|
|
46
|
+
var mode = persistedMode ?? "system";
|
|
47
|
+
var isDark = resolveIsDark(mode);
|
|
48
|
+
applyToDom(isDark);
|
|
49
|
+
if (typeof window !== "undefined" && window.matchMedia) {
|
|
50
|
+
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
51
|
+
const onSystemChange = (event) => {
|
|
52
|
+
if (mode !== "system") return;
|
|
53
|
+
isDark = event.matches;
|
|
54
|
+
applyToDom(isDark);
|
|
55
|
+
notify();
|
|
56
|
+
};
|
|
57
|
+
if (mq.addEventListener) mq.addEventListener("change", onSystemChange);
|
|
58
|
+
else mq.addListener(onSystemChange);
|
|
59
|
+
}
|
|
60
|
+
function notify() {
|
|
61
|
+
for (const listener of listeners) listener();
|
|
62
|
+
}
|
|
63
|
+
function resyncDomWithActiveTheme() {
|
|
64
|
+
applyToDom(isDark);
|
|
65
|
+
}
|
|
66
|
+
function getGlobalDarkMode() {
|
|
67
|
+
return isDark;
|
|
68
|
+
}
|
|
69
|
+
function getGlobalThemeMode() {
|
|
70
|
+
return mode;
|
|
71
|
+
}
|
|
72
|
+
function setGlobalThemeMode(nextMode) {
|
|
73
|
+
mode = nextMode;
|
|
74
|
+
isDark = resolveIsDark(nextMode);
|
|
75
|
+
applyToDom(isDark);
|
|
76
|
+
const ls = storage();
|
|
77
|
+
if (ls) {
|
|
78
|
+
try {
|
|
79
|
+
ls.setItem(STORAGE_KEY, nextMode);
|
|
80
|
+
} catch {
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
notify();
|
|
84
|
+
}
|
|
85
|
+
function toggleGlobalDarkMode() {
|
|
86
|
+
setGlobalThemeMode(isDark ? "light" : "dark");
|
|
87
|
+
}
|
|
88
|
+
function subscribeGlobalDarkMode(listener) {
|
|
89
|
+
listeners.add(listener);
|
|
90
|
+
return () => listeners.delete(listener);
|
|
91
|
+
}
|
|
92
|
+
function seedDefaultMode(fallback) {
|
|
93
|
+
if (hadPersistedMode || mode === fallback) return;
|
|
94
|
+
mode = fallback;
|
|
95
|
+
isDark = resolveIsDark(fallback);
|
|
96
|
+
applyToDom(isDark);
|
|
97
|
+
notify();
|
|
98
|
+
}
|
|
5
99
|
|
|
6
100
|
// src/colorVariables.ts
|
|
7
101
|
function parseHexRgb(hex) {
|
|
@@ -104,12 +198,19 @@ function resolveKbachConfig(config) {
|
|
|
104
198
|
function applyKbachConfig(config) {
|
|
105
199
|
const theme = resolveKbachConfig(config);
|
|
106
200
|
setTheme(theme);
|
|
201
|
+
resyncDomWithActiveTheme();
|
|
107
202
|
return theme;
|
|
108
203
|
}
|
|
109
204
|
|
|
110
205
|
export {
|
|
111
206
|
parseHexRgb,
|
|
112
207
|
ensureColorVariablesInjected,
|
|
208
|
+
getGlobalDarkMode,
|
|
209
|
+
getGlobalThemeMode,
|
|
210
|
+
setGlobalThemeMode,
|
|
211
|
+
toggleGlobalDarkMode,
|
|
212
|
+
subscribeGlobalDarkMode,
|
|
213
|
+
seedDefaultMode,
|
|
113
214
|
resolveKbachConfig,
|
|
114
215
|
applyKbachConfig
|
|
115
216
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveKbachConfig
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-OWWJ2PME.mjs";
|
|
4
4
|
import {
|
|
5
5
|
buildResetCSS,
|
|
6
6
|
defaultTheme
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-OVKVZA7B.mjs";
|
|
8
8
|
|
|
9
9
|
// src/vite-plugin/index.ts
|
|
10
10
|
import { readFileSync as readFileSync3, writeFileSync, mkdirSync, existsSync, statSync as statSync2 } from "fs";
|
|
@@ -181,11 +181,9 @@ function formatKbachCSS(tokenRules, theme, usedTags) {
|
|
|
181
181
|
const spacingMap = buildSpacingVarMap(theme, compact);
|
|
182
182
|
const { text, declarations } = applyVarMap(compact, colorMap, spacingMap);
|
|
183
183
|
const lines = ["/* Generated by Kbach \u2014 do not edit */", "", buildResetCSS(usedTags)];
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
lines.push("}");
|
|
188
|
-
}
|
|
184
|
+
lines.push("", ":root {", ` --kb-dark-mode: ${theme.darkMode};`);
|
|
185
|
+
for (const [varName, val] of declarations) lines.push(` ${varName}: ${val};`);
|
|
186
|
+
lines.push("}");
|
|
189
187
|
lines.push("", prettifyCSS(text));
|
|
190
188
|
return lines.join("\n");
|
|
191
189
|
}
|
|
@@ -99,7 +99,18 @@ interface KbachConfig {
|
|
|
99
99
|
}
|
|
100
100
|
/** Merges a `KbachConfig` into `defaultTheme` — a pure function, no side effects. */
|
|
101
101
|
declare function resolveKbachConfig(config: KbachConfig): ThemeConfig;
|
|
102
|
-
/**
|
|
102
|
+
/**
|
|
103
|
+
* `resolveKbachConfig()` + `setTheme()` in one call — the usual entry point
|
|
104
|
+
* from app code. Returns the resolved theme (e.g. to also hand to the Vite
|
|
105
|
+
* plugin's own `theme` option).
|
|
106
|
+
*
|
|
107
|
+
* Also re-syncs the DOM to the CURRENT dark-mode state right after
|
|
108
|
+
* `setTheme()` — see `resyncDomWithActiveTheme`'s own doc comment for why
|
|
109
|
+
* this is required, not optional: without it, an app that configures
|
|
110
|
+
* `darkMode: 'attribute'`/`'class'` here can silently never apply its
|
|
111
|
+
* `dark:` classes on initial load (even though `useTheme().isDark` reads
|
|
112
|
+
* correctly) until some later, unrelated dark-mode event happens to fire.
|
|
113
|
+
*/
|
|
103
114
|
declare function applyKbachConfig(config: KbachConfig): ThemeConfig;
|
|
104
115
|
|
|
105
116
|
export { type ColorEntry as C, type DarkModeStrategy as D, type KbachConfig as K, type ThemeConfig as T, type ContainerConfig as a, applyKbachConfig as b, defaultTheme as d, getTheme as g, resolveKbachConfig as r, setTheme as s };
|
|
@@ -99,7 +99,18 @@ interface KbachConfig {
|
|
|
99
99
|
}
|
|
100
100
|
/** Merges a `KbachConfig` into `defaultTheme` — a pure function, no side effects. */
|
|
101
101
|
declare function resolveKbachConfig(config: KbachConfig): ThemeConfig;
|
|
102
|
-
/**
|
|
102
|
+
/**
|
|
103
|
+
* `resolveKbachConfig()` + `setTheme()` in one call — the usual entry point
|
|
104
|
+
* from app code. Returns the resolved theme (e.g. to also hand to the Vite
|
|
105
|
+
* plugin's own `theme` option).
|
|
106
|
+
*
|
|
107
|
+
* Also re-syncs the DOM to the CURRENT dark-mode state right after
|
|
108
|
+
* `setTheme()` — see `resyncDomWithActiveTheme`'s own doc comment for why
|
|
109
|
+
* this is required, not optional: without it, an app that configures
|
|
110
|
+
* `darkMode: 'attribute'`/`'class'` here can silently never apply its
|
|
111
|
+
* `dark:` classes on initial load (even though `useTheme().isDark` reads
|
|
112
|
+
* correctly) until some later, unrelated dark-mode event happens to fire.
|
|
113
|
+
*/
|
|
103
114
|
declare function applyKbachConfig(config: KbachConfig): ThemeConfig;
|
|
104
115
|
|
|
105
116
|
export { type ColorEntry as C, type DarkModeStrategy as D, type KbachConfig as K, type ThemeConfig as T, type ContainerConfig as a, applyKbachConfig as b, defaultTheme as d, getTheme as g, resolveKbachConfig as r, setTheme as s };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { C as ColorEntry, a as ContainerConfig, D as DarkModeStrategy, K as KbachConfig, T as ThemeConfig, b as applyKbachConfig, d as defaultTheme, g as getTheme, r as resolveKbachConfig, s as setTheme } from './config-
|
|
1
|
+
export { C as ColorEntry, a as ContainerConfig, D as DarkModeStrategy, K as KbachConfig, T as ThemeConfig, b as applyKbachConfig, d as defaultTheme, g as getTheme, r as resolveKbachConfig, s as setTheme } from './config-B00tH6vN.mjs';
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
4
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { C as ColorEntry, a as ContainerConfig, D as DarkModeStrategy, K as KbachConfig, T as ThemeConfig, b as applyKbachConfig, d as defaultTheme, g as getTheme, r as resolveKbachConfig, s as setTheme } from './config-
|
|
1
|
+
export { C as ColorEntry, a as ContainerConfig, D as DarkModeStrategy, K as KbachConfig, T as ThemeConfig, b as applyKbachConfig, d as defaultTheme, g as getTheme, r as resolveKbachConfig, s as setTheme } from './config-B00tH6vN.js';
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
4
|
|
package/dist/index.js
CHANGED
|
@@ -455,6 +455,13 @@ function getTheme() {
|
|
|
455
455
|
function getThemeJson() {
|
|
456
456
|
return activeThemeJson;
|
|
457
457
|
}
|
|
458
|
+
var DARK_MODE_STRATEGIES = /* @__PURE__ */ new Set(["attribute", "class", "media"]);
|
|
459
|
+
function detectDarkModeStrategyFromDom() {
|
|
460
|
+
if (typeof document === "undefined") return;
|
|
461
|
+
const raw = getComputedStyle(document.documentElement).getPropertyValue("--kb-dark-mode").trim();
|
|
462
|
+
if (!DARK_MODE_STRATEGIES.has(raw) || raw === activeTheme.darkMode) return;
|
|
463
|
+
setTheme({ ...activeTheme, darkMode: raw });
|
|
464
|
+
}
|
|
458
465
|
|
|
459
466
|
// src/reset.ts
|
|
460
467
|
var RESET_STYLE_ID = "kbach-reset";
|
|
@@ -587,9 +594,23 @@ function ensureResetInjected() {
|
|
|
587
594
|
el.textContent = BASE_RESET;
|
|
588
595
|
document.head.insertBefore(el, document.head.firstChild);
|
|
589
596
|
}
|
|
597
|
+
var KB_CACHE_MAX = 500;
|
|
598
|
+
var kbCache = /* @__PURE__ */ new Map();
|
|
599
|
+
var cachedForThemeJson = null;
|
|
590
600
|
function kb(classString) {
|
|
591
|
-
const
|
|
592
|
-
|
|
601
|
+
const themeJson = getThemeJson();
|
|
602
|
+
if (themeJson !== cachedForThemeJson) {
|
|
603
|
+
kbCache.clear();
|
|
604
|
+
cachedForThemeJson = themeJson;
|
|
605
|
+
}
|
|
606
|
+
let result = kbCache.get(classString);
|
|
607
|
+
if (result === void 0) {
|
|
608
|
+
const json = generateCss(classString, themeJson);
|
|
609
|
+
result = JSON.parse(json);
|
|
610
|
+
if (kbCache.size >= KB_CACHE_MAX) kbCache.clear();
|
|
611
|
+
kbCache.set(classString, result);
|
|
612
|
+
}
|
|
613
|
+
const { className, rules } = result;
|
|
593
614
|
if (!runtimeCSSDisabled) {
|
|
594
615
|
ensureResetInjected();
|
|
595
616
|
for (const { rule, order } of rules) {
|
|
@@ -656,63 +677,6 @@ function ensureColorVariablesInjected(theme) {
|
|
|
656
677
|
${wrapDarkDecls(theme.darkMode, darkDecls.join(" "))}`;
|
|
657
678
|
}
|
|
658
679
|
|
|
659
|
-
// src/config.ts
|
|
660
|
-
function applyOpacityToHex(hex, opacityText) {
|
|
661
|
-
const rgb = parseHexRgb(hex);
|
|
662
|
-
if (!rgb) return hex;
|
|
663
|
-
const a = Number(opacityText) / 100;
|
|
664
|
-
const clamped = Number.isFinite(a) ? Math.min(1, Math.max(0, a)) : 1;
|
|
665
|
-
return `rgba(${rgb.join(",")},${clamped})`;
|
|
666
|
-
}
|
|
667
|
-
function resolveColorEntry(value, lookup) {
|
|
668
|
-
if (typeof value !== "string") return value;
|
|
669
|
-
const slash = value.indexOf("/");
|
|
670
|
-
const name = slash === -1 ? value : value.slice(0, slash);
|
|
671
|
-
const opacity = slash === -1 ? void 0 : value.slice(slash + 1);
|
|
672
|
-
const base = lookup(name);
|
|
673
|
-
if (base === void 0) return value;
|
|
674
|
-
if (opacity === void 0) return base;
|
|
675
|
-
return typeof base === "string" ? applyOpacityToHex(base, opacity) : { light: applyOpacityToHex(base.light, opacity), dark: applyOpacityToHex(base.dark, opacity) };
|
|
676
|
-
}
|
|
677
|
-
function resolveColors(extend, existing) {
|
|
678
|
-
const resolved = {};
|
|
679
|
-
const lookup = (name) => resolved[name] ?? existing[name];
|
|
680
|
-
for (const [name, value] of Object.entries(extend)) {
|
|
681
|
-
resolved[name] = resolveColorEntry(value, lookup);
|
|
682
|
-
}
|
|
683
|
-
return resolved;
|
|
684
|
-
}
|
|
685
|
-
function resolveKbachConfig(config) {
|
|
686
|
-
let theme = { ...defaultTheme, ...config.theme };
|
|
687
|
-
if (config.extend?.colors) {
|
|
688
|
-
theme = { ...theme, colors: { ...theme.colors, ...resolveColors(config.extend.colors, theme.colors) } };
|
|
689
|
-
}
|
|
690
|
-
if (config.extend?.spacing) {
|
|
691
|
-
theme = { ...theme, spacing: { ...theme.spacing, ...config.extend.spacing } };
|
|
692
|
-
}
|
|
693
|
-
if (config.extend?.screens) {
|
|
694
|
-
theme = { ...theme, screens: { ...theme.screens, ...config.extend.screens } };
|
|
695
|
-
}
|
|
696
|
-
if (config.extend?.fontFamily) {
|
|
697
|
-
theme = { ...theme, fontFamily: { ...theme.fontFamily, ...config.extend.fontFamily } };
|
|
698
|
-
}
|
|
699
|
-
if (config.extend?.container) {
|
|
700
|
-
theme = { ...theme, container: { ...theme.container, ...config.extend.container } };
|
|
701
|
-
}
|
|
702
|
-
if (config.darkMode) {
|
|
703
|
-
theme = { ...theme, darkMode: config.darkMode };
|
|
704
|
-
}
|
|
705
|
-
return theme;
|
|
706
|
-
}
|
|
707
|
-
function applyKbachConfig(config) {
|
|
708
|
-
const theme = resolveKbachConfig(config);
|
|
709
|
-
setTheme(theme);
|
|
710
|
-
return theme;
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
// src/useTheme.ts
|
|
714
|
-
var import_react = require("react");
|
|
715
|
-
|
|
716
680
|
// src/darkModeStore.ts
|
|
717
681
|
var STORAGE_KEY = "kbach-theme";
|
|
718
682
|
var listeners = /* @__PURE__ */ new Set();
|
|
@@ -740,13 +704,15 @@ function applyToDom(dark) {
|
|
|
740
704
|
if (typeof document === "undefined") return;
|
|
741
705
|
const root = document.documentElement;
|
|
742
706
|
const strategy = getTheme().darkMode;
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
} else if (strategy === "attribute") {
|
|
707
|
+
root.classList.toggle("dark", strategy === "class" && dark);
|
|
708
|
+
root.classList.toggle("light", strategy === "class" && !dark);
|
|
709
|
+
if (strategy === "attribute") {
|
|
747
710
|
root.setAttribute("data-theme", dark ? "dark" : "light");
|
|
711
|
+
} else {
|
|
712
|
+
root.removeAttribute("data-theme");
|
|
748
713
|
}
|
|
749
714
|
}
|
|
715
|
+
detectDarkModeStrategyFromDom();
|
|
750
716
|
var persistedMode = readPersistedMode();
|
|
751
717
|
var hadPersistedMode = persistedMode !== null;
|
|
752
718
|
var mode = persistedMode ?? "system";
|
|
@@ -766,6 +732,9 @@ if (typeof window !== "undefined" && window.matchMedia) {
|
|
|
766
732
|
function notify() {
|
|
767
733
|
for (const listener of listeners) listener();
|
|
768
734
|
}
|
|
735
|
+
function resyncDomWithActiveTheme() {
|
|
736
|
+
applyToDom(isDark);
|
|
737
|
+
}
|
|
769
738
|
function getGlobalDarkMode() {
|
|
770
739
|
return isDark;
|
|
771
740
|
}
|
|
@@ -800,7 +769,63 @@ function seedDefaultMode(fallback) {
|
|
|
800
769
|
notify();
|
|
801
770
|
}
|
|
802
771
|
|
|
772
|
+
// src/config.ts
|
|
773
|
+
function applyOpacityToHex(hex, opacityText) {
|
|
774
|
+
const rgb = parseHexRgb(hex);
|
|
775
|
+
if (!rgb) return hex;
|
|
776
|
+
const a = Number(opacityText) / 100;
|
|
777
|
+
const clamped = Number.isFinite(a) ? Math.min(1, Math.max(0, a)) : 1;
|
|
778
|
+
return `rgba(${rgb.join(",")},${clamped})`;
|
|
779
|
+
}
|
|
780
|
+
function resolveColorEntry(value, lookup) {
|
|
781
|
+
if (typeof value !== "string") return value;
|
|
782
|
+
const slash = value.indexOf("/");
|
|
783
|
+
const name = slash === -1 ? value : value.slice(0, slash);
|
|
784
|
+
const opacity = slash === -1 ? void 0 : value.slice(slash + 1);
|
|
785
|
+
const base = lookup(name);
|
|
786
|
+
if (base === void 0) return value;
|
|
787
|
+
if (opacity === void 0) return base;
|
|
788
|
+
return typeof base === "string" ? applyOpacityToHex(base, opacity) : { light: applyOpacityToHex(base.light, opacity), dark: applyOpacityToHex(base.dark, opacity) };
|
|
789
|
+
}
|
|
790
|
+
function resolveColors(extend, existing) {
|
|
791
|
+
const resolved = {};
|
|
792
|
+
const lookup = (name) => resolved[name] ?? existing[name];
|
|
793
|
+
for (const [name, value] of Object.entries(extend)) {
|
|
794
|
+
resolved[name] = resolveColorEntry(value, lookup);
|
|
795
|
+
}
|
|
796
|
+
return resolved;
|
|
797
|
+
}
|
|
798
|
+
function resolveKbachConfig(config) {
|
|
799
|
+
let theme = { ...defaultTheme, ...config.theme };
|
|
800
|
+
if (config.extend?.colors) {
|
|
801
|
+
theme = { ...theme, colors: { ...theme.colors, ...resolveColors(config.extend.colors, theme.colors) } };
|
|
802
|
+
}
|
|
803
|
+
if (config.extend?.spacing) {
|
|
804
|
+
theme = { ...theme, spacing: { ...theme.spacing, ...config.extend.spacing } };
|
|
805
|
+
}
|
|
806
|
+
if (config.extend?.screens) {
|
|
807
|
+
theme = { ...theme, screens: { ...theme.screens, ...config.extend.screens } };
|
|
808
|
+
}
|
|
809
|
+
if (config.extend?.fontFamily) {
|
|
810
|
+
theme = { ...theme, fontFamily: { ...theme.fontFamily, ...config.extend.fontFamily } };
|
|
811
|
+
}
|
|
812
|
+
if (config.extend?.container) {
|
|
813
|
+
theme = { ...theme, container: { ...theme.container, ...config.extend.container } };
|
|
814
|
+
}
|
|
815
|
+
if (config.darkMode) {
|
|
816
|
+
theme = { ...theme, darkMode: config.darkMode };
|
|
817
|
+
}
|
|
818
|
+
return theme;
|
|
819
|
+
}
|
|
820
|
+
function applyKbachConfig(config) {
|
|
821
|
+
const theme = resolveKbachConfig(config);
|
|
822
|
+
setTheme(theme);
|
|
823
|
+
resyncDomWithActiveTheme();
|
|
824
|
+
return theme;
|
|
825
|
+
}
|
|
826
|
+
|
|
803
827
|
// src/useTheme.ts
|
|
828
|
+
var import_react = require("react");
|
|
804
829
|
function useTheme() {
|
|
805
830
|
const isDark2 = (0, import_react.useSyncExternalStore)(subscribeGlobalDarkMode, getGlobalDarkMode, () => false);
|
|
806
831
|
const mode2 = (0, import_react.useSyncExternalStore)(subscribeGlobalDarkMode, getGlobalThemeMode, () => "system");
|
|
@@ -838,6 +863,7 @@ function ThemeProvider({ children, defaultMode = "system" }) {
|
|
|
838
863
|
}
|
|
839
864
|
|
|
840
865
|
// src/useColors.ts
|
|
866
|
+
var import_react3 = require("react");
|
|
841
867
|
function applyOpacity(color, opacity) {
|
|
842
868
|
const a = Math.max(0, Math.min(1, opacity / 100));
|
|
843
869
|
const varMatch = /^rgb\(var\((--[\w-]+)\)\)$/.exec(color);
|
|
@@ -898,7 +924,7 @@ function useColors() {
|
|
|
898
924
|
const { isDark: isDark2 } = useTheme();
|
|
899
925
|
const theme = getTheme();
|
|
900
926
|
ensureColorVariablesInjected(theme);
|
|
901
|
-
return makeColorsProxy(theme, isDark2);
|
|
927
|
+
return (0, import_react3.useMemo)(() => makeColorsProxy(theme, isDark2), [theme, isDark2]);
|
|
902
928
|
}
|
|
903
929
|
// Annotate the CommonJS export names for ESM import in node:
|
|
904
930
|
0 && (module.exports = {
|
package/dist/index.mjs
CHANGED
|
@@ -4,20 +4,26 @@ import {
|
|
|
4
4
|
isKbachReady,
|
|
5
5
|
isRuntimeCSSDisabled,
|
|
6
6
|
kb
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-KJY3W4GF.mjs";
|
|
8
8
|
import {
|
|
9
9
|
applyKbachConfig,
|
|
10
10
|
ensureColorVariablesInjected,
|
|
11
|
+
getGlobalDarkMode,
|
|
12
|
+
getGlobalThemeMode,
|
|
11
13
|
parseHexRgb,
|
|
12
|
-
resolveKbachConfig
|
|
13
|
-
|
|
14
|
+
resolveKbachConfig,
|
|
15
|
+
seedDefaultMode,
|
|
16
|
+
setGlobalThemeMode,
|
|
17
|
+
subscribeGlobalDarkMode,
|
|
18
|
+
toggleGlobalDarkMode
|
|
19
|
+
} from "./chunk-OWWJ2PME.mjs";
|
|
14
20
|
import {
|
|
15
21
|
BASE_RESET,
|
|
16
22
|
RESET_STYLE_ID,
|
|
17
23
|
defaultTheme,
|
|
18
24
|
getTheme,
|
|
19
25
|
setTheme
|
|
20
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-OVKVZA7B.mjs";
|
|
21
27
|
|
|
22
28
|
// src/KbachReset.tsx
|
|
23
29
|
import { jsx } from "react/jsx-runtime";
|
|
@@ -28,101 +34,12 @@ function KbachReset() {
|
|
|
28
34
|
|
|
29
35
|
// src/useTheme.ts
|
|
30
36
|
import { useMemo, useSyncExternalStore } from "react";
|
|
31
|
-
|
|
32
|
-
// src/darkModeStore.ts
|
|
33
|
-
var STORAGE_KEY = "kbach-theme";
|
|
34
|
-
var listeners = /* @__PURE__ */ new Set();
|
|
35
|
-
function systemPrefersDark() {
|
|
36
|
-
if (typeof window === "undefined" || !window.matchMedia) return false;
|
|
37
|
-
return window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
38
|
-
}
|
|
39
|
-
function storage() {
|
|
40
|
-
return typeof window === "undefined" ? null : window.localStorage;
|
|
41
|
-
}
|
|
42
|
-
function readPersistedMode() {
|
|
43
|
-
const ls = storage();
|
|
44
|
-
if (!ls) return null;
|
|
45
|
-
try {
|
|
46
|
-
const raw = ls.getItem(STORAGE_KEY);
|
|
47
|
-
return raw === "light" || raw === "dark" || raw === "system" ? raw : null;
|
|
48
|
-
} catch {
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
function resolveIsDark(m) {
|
|
53
|
-
return m === "system" ? systemPrefersDark() : m === "dark";
|
|
54
|
-
}
|
|
55
|
-
function applyToDom(dark) {
|
|
56
|
-
if (typeof document === "undefined") return;
|
|
57
|
-
const root = document.documentElement;
|
|
58
|
-
const strategy = getTheme().darkMode;
|
|
59
|
-
if (strategy === "class") {
|
|
60
|
-
root.classList.toggle("dark", dark);
|
|
61
|
-
root.classList.toggle("light", !dark);
|
|
62
|
-
} else if (strategy === "attribute") {
|
|
63
|
-
root.setAttribute("data-theme", dark ? "dark" : "light");
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
var persistedMode = readPersistedMode();
|
|
67
|
-
var hadPersistedMode = persistedMode !== null;
|
|
68
|
-
var mode = persistedMode ?? "system";
|
|
69
|
-
var isDark = resolveIsDark(mode);
|
|
70
|
-
applyToDom(isDark);
|
|
71
|
-
if (typeof window !== "undefined" && window.matchMedia) {
|
|
72
|
-
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
73
|
-
const onSystemChange = (event) => {
|
|
74
|
-
if (mode !== "system") return;
|
|
75
|
-
isDark = event.matches;
|
|
76
|
-
applyToDom(isDark);
|
|
77
|
-
notify();
|
|
78
|
-
};
|
|
79
|
-
if (mq.addEventListener) mq.addEventListener("change", onSystemChange);
|
|
80
|
-
else mq.addListener(onSystemChange);
|
|
81
|
-
}
|
|
82
|
-
function notify() {
|
|
83
|
-
for (const listener of listeners) listener();
|
|
84
|
-
}
|
|
85
|
-
function getGlobalDarkMode() {
|
|
86
|
-
return isDark;
|
|
87
|
-
}
|
|
88
|
-
function getGlobalThemeMode() {
|
|
89
|
-
return mode;
|
|
90
|
-
}
|
|
91
|
-
function setGlobalThemeMode(nextMode) {
|
|
92
|
-
mode = nextMode;
|
|
93
|
-
isDark = resolveIsDark(nextMode);
|
|
94
|
-
applyToDom(isDark);
|
|
95
|
-
const ls = storage();
|
|
96
|
-
if (ls) {
|
|
97
|
-
try {
|
|
98
|
-
ls.setItem(STORAGE_KEY, nextMode);
|
|
99
|
-
} catch {
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
notify();
|
|
103
|
-
}
|
|
104
|
-
function toggleGlobalDarkMode() {
|
|
105
|
-
setGlobalThemeMode(isDark ? "light" : "dark");
|
|
106
|
-
}
|
|
107
|
-
function subscribeGlobalDarkMode(listener) {
|
|
108
|
-
listeners.add(listener);
|
|
109
|
-
return () => listeners.delete(listener);
|
|
110
|
-
}
|
|
111
|
-
function seedDefaultMode(fallback) {
|
|
112
|
-
if (hadPersistedMode || mode === fallback) return;
|
|
113
|
-
mode = fallback;
|
|
114
|
-
isDark = resolveIsDark(fallback);
|
|
115
|
-
applyToDom(isDark);
|
|
116
|
-
notify();
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// src/useTheme.ts
|
|
120
37
|
function useTheme() {
|
|
121
|
-
const
|
|
122
|
-
const
|
|
38
|
+
const isDark = useSyncExternalStore(subscribeGlobalDarkMode, getGlobalDarkMode, () => false);
|
|
39
|
+
const mode = useSyncExternalStore(subscribeGlobalDarkMode, getGlobalThemeMode, () => "system");
|
|
123
40
|
return useMemo(
|
|
124
|
-
() => ({ mode
|
|
125
|
-
[
|
|
41
|
+
() => ({ mode, isDark, setMode: setGlobalThemeMode, toggle: toggleGlobalDarkMode }),
|
|
42
|
+
[mode, isDark]
|
|
126
43
|
);
|
|
127
44
|
}
|
|
128
45
|
|
|
@@ -154,6 +71,7 @@ function ThemeProvider({ children, defaultMode = "system" }) {
|
|
|
154
71
|
}
|
|
155
72
|
|
|
156
73
|
// src/useColors.ts
|
|
74
|
+
import { useMemo as useMemo2 } from "react";
|
|
157
75
|
function applyOpacity(color, opacity) {
|
|
158
76
|
const a = Math.max(0, Math.min(1, opacity / 100));
|
|
159
77
|
const varMatch = /^rgb\(var\((--[\w-]+)\)\)$/.exec(color);
|
|
@@ -166,14 +84,14 @@ function applyOpacity(color, opacity) {
|
|
|
166
84
|
if (color.startsWith("rgba(")) return color.replace(/,\s*[\d.]+\)$/, `,${a})`);
|
|
167
85
|
return color;
|
|
168
86
|
}
|
|
169
|
-
function resolveEntry(name, entry,
|
|
87
|
+
function resolveEntry(name, entry, isDark) {
|
|
170
88
|
if (typeof entry === "string") return entry;
|
|
171
89
|
const light = parseHexRgb(entry.light);
|
|
172
90
|
const dark = parseHexRgb(entry.dark);
|
|
173
91
|
if (light && dark) return `rgb(var(--kb-color-${name}))`;
|
|
174
|
-
return
|
|
92
|
+
return isDark ? entry.dark : entry.light;
|
|
175
93
|
}
|
|
176
|
-
function makeColorsProxy(theme,
|
|
94
|
+
function makeColorsProxy(theme, isDark) {
|
|
177
95
|
const alpha = (color, opacity) => opacity === void 0 ? color : applyOpacity(color, opacity);
|
|
178
96
|
const cache = /* @__PURE__ */ new Map();
|
|
179
97
|
function resolveNamed(key) {
|
|
@@ -186,7 +104,7 @@ function makeColorsProxy(theme, isDark2) {
|
|
|
186
104
|
}
|
|
187
105
|
const entry = theme.colors[name];
|
|
188
106
|
if (entry === void 0) return void 0;
|
|
189
|
-
const value = resolveEntry(name, entry,
|
|
107
|
+
const value = resolveEntry(name, entry, isDark);
|
|
190
108
|
return opacity === void 0 ? value : applyOpacity(value, opacity);
|
|
191
109
|
}
|
|
192
110
|
function makeFamilyProxy(family) {
|
|
@@ -211,10 +129,10 @@ function makeColorsProxy(theme, isDark2) {
|
|
|
211
129
|
});
|
|
212
130
|
}
|
|
213
131
|
function useColors() {
|
|
214
|
-
const { isDark
|
|
132
|
+
const { isDark } = useTheme();
|
|
215
133
|
const theme = getTheme();
|
|
216
134
|
ensureColorVariablesInjected(theme);
|
|
217
|
-
return makeColorsProxy(theme,
|
|
135
|
+
return useMemo2(() => makeColorsProxy(theme, isDark), [theme, isDark]);
|
|
218
136
|
}
|
|
219
137
|
export {
|
|
220
138
|
KbachReset,
|
package/dist/jsx-dev-runtime.js
CHANGED
|
@@ -548,9 +548,23 @@ function ensureResetInjected() {
|
|
|
548
548
|
el.textContent = BASE_RESET;
|
|
549
549
|
document.head.insertBefore(el, document.head.firstChild);
|
|
550
550
|
}
|
|
551
|
+
var KB_CACHE_MAX = 500;
|
|
552
|
+
var kbCache = /* @__PURE__ */ new Map();
|
|
553
|
+
var cachedForThemeJson = null;
|
|
551
554
|
function kb(classString) {
|
|
552
|
-
const
|
|
553
|
-
|
|
555
|
+
const themeJson = getThemeJson();
|
|
556
|
+
if (themeJson !== cachedForThemeJson) {
|
|
557
|
+
kbCache.clear();
|
|
558
|
+
cachedForThemeJson = themeJson;
|
|
559
|
+
}
|
|
560
|
+
let result = kbCache.get(classString);
|
|
561
|
+
if (result === void 0) {
|
|
562
|
+
const json = generateCss(classString, themeJson);
|
|
563
|
+
result = JSON.parse(json);
|
|
564
|
+
if (kbCache.size >= KB_CACHE_MAX) kbCache.clear();
|
|
565
|
+
kbCache.set(classString, result);
|
|
566
|
+
}
|
|
567
|
+
const { className, rules } = result;
|
|
554
568
|
if (!runtimeCSSDisabled) {
|
|
555
569
|
ensureResetInjected();
|
|
556
570
|
for (const { rule, order } of rules) {
|
package/dist/jsx-dev-runtime.mjs
CHANGED
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
Fragment,
|
|
3
3
|
jsx,
|
|
4
4
|
jsxs
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-D7OC2AE7.mjs";
|
|
6
|
+
import "./chunk-KJY3W4GF.mjs";
|
|
7
|
+
import "./chunk-OVKVZA7B.mjs";
|
|
8
8
|
|
|
9
9
|
// src/jsx-dev-runtime.tsx
|
|
10
10
|
function jsxDEV(type, props, key, isStaticChildren, source, self) {
|
package/dist/jsx-runtime.js
CHANGED
|
@@ -547,9 +547,23 @@ function ensureResetInjected() {
|
|
|
547
547
|
el.textContent = BASE_RESET;
|
|
548
548
|
document.head.insertBefore(el, document.head.firstChild);
|
|
549
549
|
}
|
|
550
|
+
var KB_CACHE_MAX = 500;
|
|
551
|
+
var kbCache = /* @__PURE__ */ new Map();
|
|
552
|
+
var cachedForThemeJson = null;
|
|
550
553
|
function kb(classString) {
|
|
551
|
-
const
|
|
552
|
-
|
|
554
|
+
const themeJson = getThemeJson();
|
|
555
|
+
if (themeJson !== cachedForThemeJson) {
|
|
556
|
+
kbCache.clear();
|
|
557
|
+
cachedForThemeJson = themeJson;
|
|
558
|
+
}
|
|
559
|
+
let result = kbCache.get(classString);
|
|
560
|
+
if (result === void 0) {
|
|
561
|
+
const json = generateCss(classString, themeJson);
|
|
562
|
+
result = JSON.parse(json);
|
|
563
|
+
if (kbCache.size >= KB_CACHE_MAX) kbCache.clear();
|
|
564
|
+
kbCache.set(classString, result);
|
|
565
|
+
}
|
|
566
|
+
const { className, rules } = result;
|
|
553
567
|
if (!runtimeCSSDisabled) {
|
|
554
568
|
ensureResetInjected();
|
|
555
569
|
for (const { rule, order } of rules) {
|
package/dist/jsx-runtime.mjs
CHANGED
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
Fragment,
|
|
3
3
|
jsx,
|
|
4
4
|
jsxs
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-D7OC2AE7.mjs";
|
|
6
|
+
import "./chunk-KJY3W4GF.mjs";
|
|
7
|
+
import "./chunk-OVKVZA7B.mjs";
|
|
8
8
|
export {
|
|
9
9
|
Fragment,
|
|
10
10
|
jsx,
|
package/dist/postcss-plugin.d.ts
CHANGED
package/dist/postcss-plugin.js
CHANGED
|
@@ -476,11 +476,9 @@ function formatKbachCSS(tokenRules, theme, usedTags) {
|
|
|
476
476
|
const spacingMap = buildSpacingVarMap(theme, compact);
|
|
477
477
|
const { text, declarations } = applyVarMap(compact, colorMap, spacingMap);
|
|
478
478
|
const lines = ["/* Generated by Kbach \u2014 do not edit */", "", buildResetCSS(usedTags)];
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
lines.push("}");
|
|
483
|
-
}
|
|
479
|
+
lines.push("", ":root {", ` --kb-dark-mode: ${theme.darkMode};`);
|
|
480
|
+
for (const [varName, val] of declarations) lines.push(` ${varName}: ${val};`);
|
|
481
|
+
lines.push("}");
|
|
484
482
|
lines.push("", prettifyCSS(text));
|
|
485
483
|
return lines.join("\n");
|
|
486
484
|
}
|
|
@@ -988,7 +986,22 @@ var defaultTheme = {
|
|
|
988
986
|
// centering/padding) — see `ContainerConfig`'s own doc comment.
|
|
989
987
|
container: {}
|
|
990
988
|
};
|
|
989
|
+
var activeTheme = defaultTheme;
|
|
991
990
|
var activeThemeJson = JSON.stringify(defaultTheme);
|
|
991
|
+
function setTheme(theme) {
|
|
992
|
+
activeTheme = theme;
|
|
993
|
+
activeThemeJson = JSON.stringify(theme);
|
|
994
|
+
}
|
|
995
|
+
function getTheme() {
|
|
996
|
+
return activeTheme;
|
|
997
|
+
}
|
|
998
|
+
var DARK_MODE_STRATEGIES = /* @__PURE__ */ new Set(["attribute", "class", "media"]);
|
|
999
|
+
function detectDarkModeStrategyFromDom() {
|
|
1000
|
+
if (typeof document === "undefined") return;
|
|
1001
|
+
const raw = getComputedStyle(document.documentElement).getPropertyValue("--kb-dark-mode").trim();
|
|
1002
|
+
if (!DARK_MODE_STRATEGIES.has(raw) || raw === activeTheme.darkMode) return;
|
|
1003
|
+
setTheme({ ...activeTheme, darkMode: raw });
|
|
1004
|
+
}
|
|
992
1005
|
|
|
993
1006
|
// src/colorVariables.ts
|
|
994
1007
|
function parseHexRgb(hex) {
|
|
@@ -1000,6 +1013,61 @@ function parseHexRgb(hex) {
|
|
|
1000
1013
|
return [n >> 16 & 255, n >> 8 & 255, n & 255];
|
|
1001
1014
|
}
|
|
1002
1015
|
|
|
1016
|
+
// src/darkModeStore.ts
|
|
1017
|
+
var STORAGE_KEY = "kbach-theme";
|
|
1018
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
1019
|
+
function systemPrefersDark() {
|
|
1020
|
+
if (typeof window === "undefined" || !window.matchMedia) return false;
|
|
1021
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
1022
|
+
}
|
|
1023
|
+
function storage() {
|
|
1024
|
+
return typeof window === "undefined" ? null : window.localStorage;
|
|
1025
|
+
}
|
|
1026
|
+
function readPersistedMode() {
|
|
1027
|
+
const ls = storage();
|
|
1028
|
+
if (!ls) return null;
|
|
1029
|
+
try {
|
|
1030
|
+
const raw = ls.getItem(STORAGE_KEY);
|
|
1031
|
+
return raw === "light" || raw === "dark" || raw === "system" ? raw : null;
|
|
1032
|
+
} catch {
|
|
1033
|
+
return null;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
function resolveIsDark(m) {
|
|
1037
|
+
return m === "system" ? systemPrefersDark() : m === "dark";
|
|
1038
|
+
}
|
|
1039
|
+
function applyToDom(dark) {
|
|
1040
|
+
if (typeof document === "undefined") return;
|
|
1041
|
+
const root = document.documentElement;
|
|
1042
|
+
const strategy = getTheme().darkMode;
|
|
1043
|
+
root.classList.toggle("dark", strategy === "class" && dark);
|
|
1044
|
+
root.classList.toggle("light", strategy === "class" && !dark);
|
|
1045
|
+
if (strategy === "attribute") {
|
|
1046
|
+
root.setAttribute("data-theme", dark ? "dark" : "light");
|
|
1047
|
+
} else {
|
|
1048
|
+
root.removeAttribute("data-theme");
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
detectDarkModeStrategyFromDom();
|
|
1052
|
+
var persistedMode = readPersistedMode();
|
|
1053
|
+
var mode = persistedMode ?? "system";
|
|
1054
|
+
var isDark = resolveIsDark(mode);
|
|
1055
|
+
applyToDom(isDark);
|
|
1056
|
+
if (typeof window !== "undefined" && window.matchMedia) {
|
|
1057
|
+
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
1058
|
+
const onSystemChange = (event) => {
|
|
1059
|
+
if (mode !== "system") return;
|
|
1060
|
+
isDark = event.matches;
|
|
1061
|
+
applyToDom(isDark);
|
|
1062
|
+
notify();
|
|
1063
|
+
};
|
|
1064
|
+
if (mq.addEventListener) mq.addEventListener("change", onSystemChange);
|
|
1065
|
+
else mq.addListener(onSystemChange);
|
|
1066
|
+
}
|
|
1067
|
+
function notify() {
|
|
1068
|
+
for (const listener of listeners) listener();
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1003
1071
|
// src/config.ts
|
|
1004
1072
|
function applyOpacityToHex(hex, opacityText) {
|
|
1005
1073
|
const rgb = parseHexRgb(hex);
|
package/dist/postcss-plugin.mjs
CHANGED
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
DEFAULT_SCAN_DIRS,
|
|
3
3
|
createKbachStaticCssEngine,
|
|
4
4
|
resolveEffectiveTheme
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-XV2ZLURB.mjs";
|
|
6
|
+
import "./chunk-OWWJ2PME.mjs";
|
|
7
|
+
import "./chunk-OVKVZA7B.mjs";
|
|
8
8
|
|
|
9
9
|
// src/postcss-plugin/index.ts
|
|
10
10
|
import postcss from "postcss";
|
package/dist/vite-plugin.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
|
-
import { T as ThemeConfig, K as KbachConfig } from './config-
|
|
2
|
+
import { T as ThemeConfig, K as KbachConfig } from './config-B00tH6vN.mjs';
|
|
3
3
|
|
|
4
4
|
interface KbachPluginOptions {
|
|
5
5
|
/** Defaults to the same defaultTheme the runtime uses — pass your own to keep both in sync. */
|
package/dist/vite-plugin.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
|
-
import { T as ThemeConfig, K as KbachConfig } from './config-
|
|
2
|
+
import { T as ThemeConfig, K as KbachConfig } from './config-B00tH6vN.js';
|
|
3
3
|
|
|
4
4
|
interface KbachPluginOptions {
|
|
5
5
|
/** Defaults to the same defaultTheme the runtime uses — pass your own to keep both in sync. */
|
package/dist/vite-plugin.js
CHANGED
|
@@ -285,11 +285,9 @@ function formatKbachCSS(tokenRules, theme, usedTags) {
|
|
|
285
285
|
const spacingMap = buildSpacingVarMap(theme, compact);
|
|
286
286
|
const { text, declarations } = applyVarMap(compact, colorMap, spacingMap);
|
|
287
287
|
const lines = ["/* Generated by Kbach \u2014 do not edit */", "", buildResetCSS(usedTags)];
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
lines.push("}");
|
|
292
|
-
}
|
|
288
|
+
lines.push("", ":root {", ` --kb-dark-mode: ${theme.darkMode};`);
|
|
289
|
+
for (const [varName, val] of declarations) lines.push(` ${varName}: ${val};`);
|
|
290
|
+
lines.push("}");
|
|
293
291
|
lines.push("", prettifyCSS(text));
|
|
294
292
|
return lines.join("\n");
|
|
295
293
|
}
|
|
@@ -1382,7 +1380,22 @@ var defaultTheme = {
|
|
|
1382
1380
|
// centering/padding) — see `ContainerConfig`'s own doc comment.
|
|
1383
1381
|
container: {}
|
|
1384
1382
|
};
|
|
1383
|
+
var activeTheme = defaultTheme;
|
|
1385
1384
|
var activeThemeJson = JSON.stringify(defaultTheme);
|
|
1385
|
+
function setTheme(theme) {
|
|
1386
|
+
activeTheme = theme;
|
|
1387
|
+
activeThemeJson = JSON.stringify(theme);
|
|
1388
|
+
}
|
|
1389
|
+
function getTheme() {
|
|
1390
|
+
return activeTheme;
|
|
1391
|
+
}
|
|
1392
|
+
var DARK_MODE_STRATEGIES = /* @__PURE__ */ new Set(["attribute", "class", "media"]);
|
|
1393
|
+
function detectDarkModeStrategyFromDom() {
|
|
1394
|
+
if (typeof document === "undefined") return;
|
|
1395
|
+
const raw = getComputedStyle(document.documentElement).getPropertyValue("--kb-dark-mode").trim();
|
|
1396
|
+
if (!DARK_MODE_STRATEGIES.has(raw) || raw === activeTheme.darkMode) return;
|
|
1397
|
+
setTheme({ ...activeTheme, darkMode: raw });
|
|
1398
|
+
}
|
|
1386
1399
|
|
|
1387
1400
|
// src/colorVariables.ts
|
|
1388
1401
|
function parseHexRgb(hex) {
|
|
@@ -1394,6 +1407,61 @@ function parseHexRgb(hex) {
|
|
|
1394
1407
|
return [n >> 16 & 255, n >> 8 & 255, n & 255];
|
|
1395
1408
|
}
|
|
1396
1409
|
|
|
1410
|
+
// src/darkModeStore.ts
|
|
1411
|
+
var STORAGE_KEY = "kbach-theme";
|
|
1412
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
1413
|
+
function systemPrefersDark() {
|
|
1414
|
+
if (typeof window === "undefined" || !window.matchMedia) return false;
|
|
1415
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
1416
|
+
}
|
|
1417
|
+
function storage() {
|
|
1418
|
+
return typeof window === "undefined" ? null : window.localStorage;
|
|
1419
|
+
}
|
|
1420
|
+
function readPersistedMode() {
|
|
1421
|
+
const ls = storage();
|
|
1422
|
+
if (!ls) return null;
|
|
1423
|
+
try {
|
|
1424
|
+
const raw = ls.getItem(STORAGE_KEY);
|
|
1425
|
+
return raw === "light" || raw === "dark" || raw === "system" ? raw : null;
|
|
1426
|
+
} catch {
|
|
1427
|
+
return null;
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
function resolveIsDark(m) {
|
|
1431
|
+
return m === "system" ? systemPrefersDark() : m === "dark";
|
|
1432
|
+
}
|
|
1433
|
+
function applyToDom(dark) {
|
|
1434
|
+
if (typeof document === "undefined") return;
|
|
1435
|
+
const root = document.documentElement;
|
|
1436
|
+
const strategy = getTheme().darkMode;
|
|
1437
|
+
root.classList.toggle("dark", strategy === "class" && dark);
|
|
1438
|
+
root.classList.toggle("light", strategy === "class" && !dark);
|
|
1439
|
+
if (strategy === "attribute") {
|
|
1440
|
+
root.setAttribute("data-theme", dark ? "dark" : "light");
|
|
1441
|
+
} else {
|
|
1442
|
+
root.removeAttribute("data-theme");
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
detectDarkModeStrategyFromDom();
|
|
1446
|
+
var persistedMode = readPersistedMode();
|
|
1447
|
+
var mode = persistedMode ?? "system";
|
|
1448
|
+
var isDark = resolveIsDark(mode);
|
|
1449
|
+
applyToDom(isDark);
|
|
1450
|
+
if (typeof window !== "undefined" && window.matchMedia) {
|
|
1451
|
+
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
1452
|
+
const onSystemChange = (event) => {
|
|
1453
|
+
if (mode !== "system") return;
|
|
1454
|
+
isDark = event.matches;
|
|
1455
|
+
applyToDom(isDark);
|
|
1456
|
+
notify();
|
|
1457
|
+
};
|
|
1458
|
+
if (mq.addEventListener) mq.addEventListener("change", onSystemChange);
|
|
1459
|
+
else mq.addListener(onSystemChange);
|
|
1460
|
+
}
|
|
1461
|
+
function notify() {
|
|
1462
|
+
for (const listener of listeners) listener();
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1397
1465
|
// src/config.ts
|
|
1398
1466
|
function applyOpacityToHex(hex, opacityText) {
|
|
1399
1467
|
const rgb = parseHexRgb(hex);
|
package/dist/vite-plugin.mjs
CHANGED
|
@@ -5,9 +5,9 @@ import {
|
|
|
5
5
|
kbach,
|
|
6
6
|
loadConfigFile,
|
|
7
7
|
resolveEffectiveTheme
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-XV2ZLURB.mjs";
|
|
9
|
+
import "./chunk-OWWJ2PME.mjs";
|
|
10
|
+
import "./chunk-OVKVZA7B.mjs";
|
|
11
11
|
export {
|
|
12
12
|
CSS_SYNC_DEBOUNCE_MS,
|
|
13
13
|
DEFAULT_SCAN_DIRS,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kbach/react",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.14",
|
|
4
4
|
"description": "A utility-first styling engine for React, powered by a real Rust/WASM core — Tailwind CSS v4 feature parity with Kbach's own color palette.",
|
|
5
5
|
"keywords": ["css", "react", "tailwind", "utility-first", "wasm", "styling"],
|
|
6
6
|
"license": "MIT",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"generate:colors": "node ../core-engine/scripts/generate-palette.mjs src/generatedPalette.ts"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@kbach/core-engine": "1.0.0-beta.
|
|
65
|
+
"@kbach/core-engine": "1.0.0-beta.8"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@types/react": "^19.2.0",
|