@kbach/react 1.0.0-beta.28 → 1.0.0-beta.29
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/AGENTS.md +214 -162
- package/dist/{chunk-UP7MWEU5.mjs → chunk-6KXERZP3.mjs} +1 -1
- package/dist/{chunk-OVKVZA7B.mjs → chunk-FBYS4BI3.mjs} +76 -0
- package/dist/{chunk-DJKDEDPE.mjs → chunk-K6AUD64N.mjs} +70 -6
- package/dist/{chunk-KTRJZDVE.mjs → chunk-NHWKWY2T.mjs} +71 -17
- package/dist/{chunk-43FOLRQA.mjs → chunk-UK5S55DF.mjs} +9 -54
- package/dist/index.d.mts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +144 -55
- package/dist/index.mjs +5 -5
- package/dist/jsx-dev-runtime.js +141 -4
- package/dist/jsx-dev-runtime.mjs +3 -3
- package/dist/jsx-runtime.js +141 -4
- package/dist/jsx-runtime.mjs +3 -3
- package/dist/postcss-plugin.js +99 -21
- package/dist/postcss-plugin.mjs +8 -4
- package/dist/vite-plugin.d.mts +3 -1
- package/dist/vite-plugin.d.ts +3 -1
- package/dist/vite-plugin.js +125 -23
- package/dist/vite-plugin.mjs +5 -3
- package/package.json +2 -2
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveKbachConfig
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UK5S55DF.mjs";
|
|
4
4
|
import {
|
|
5
5
|
buildResetCSS,
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
colorVariablesCss,
|
|
7
|
+
defaultTheme,
|
|
8
|
+
withColorVariables
|
|
9
|
+
} from "./chunk-FBYS4BI3.mjs";
|
|
8
10
|
|
|
9
11
|
// src/vite-plugin/index.ts
|
|
10
12
|
import { readFileSync as readFileSync3, writeFileSync, mkdirSync, existsSync, statSync as statSync2 } from "fs";
|
|
11
|
-
import { join as join4, dirname } from "path";
|
|
13
|
+
import { join as join4, dirname, basename } from "path";
|
|
12
14
|
import { pathToFileURL } from "url";
|
|
13
15
|
import { createRequire } from "module";
|
|
14
16
|
|
|
@@ -184,6 +186,8 @@ function formatKbachCSS(tokenRules, theme, usedTags) {
|
|
|
184
186
|
lines.push("", ":root {", ` --kb-dark-mode: ${theme.darkMode};`);
|
|
185
187
|
for (const [varName, val] of declarations) lines.push(` ${varName}: ${val};`);
|
|
186
188
|
lines.push("}");
|
|
189
|
+
const colorVars = colorVariablesCss(theme);
|
|
190
|
+
if (colorVars) lines.push("", prettifyCSS(colorVars));
|
|
187
191
|
lines.push("", prettifyCSS(text));
|
|
188
192
|
return lines.join("\n");
|
|
189
193
|
}
|
|
@@ -211,10 +215,13 @@ import { readFileSync as readFileSync2 } from "fs";
|
|
|
211
215
|
import { join as join3 } from "path";
|
|
212
216
|
|
|
213
217
|
// src/vite-plugin/wasmNode.ts
|
|
214
|
-
import { generate_css } from "@kbach/core-engine/node";
|
|
218
|
+
import { generate_css, suggest_class } from "@kbach/core-engine/node";
|
|
215
219
|
function generateCssForToken(token, themeJson) {
|
|
216
220
|
return JSON.parse(generate_css(token, themeJson));
|
|
217
221
|
}
|
|
222
|
+
function suggestClassForToken(token, themeJson) {
|
|
223
|
+
return suggest_class(token, themeJson) || null;
|
|
224
|
+
}
|
|
218
225
|
|
|
219
226
|
// src/vite-plugin/scan.ts
|
|
220
227
|
import { readdirSync, readFileSync, statSync } from "fs";
|
|
@@ -474,17 +481,18 @@ function isMarkerClass(base) {
|
|
|
474
481
|
if (slashIdx === -1) return false;
|
|
475
482
|
return MARKER_CLASSES.has(base.slice(0, slashIdx)) && slashIdx < base.length - 1;
|
|
476
483
|
}
|
|
477
|
-
|
|
484
|
+
var TAILWIND_SHADE = /-(?:50|[1-9]00|950)(?:\/|$)/;
|
|
485
|
+
function warnIfUnknownClass(token, filePath, code, isResolvable, projectCssClasses, warnedTokens, suggest) {
|
|
478
486
|
if (isResolvable || warnedTokens.has(token)) return;
|
|
479
487
|
const base = stripModifierPrefix(token);
|
|
480
488
|
if (!base || projectCssClasses.has(base) || isMarkerClass(base)) return;
|
|
481
489
|
warnedTokens.add(token);
|
|
482
490
|
const pos = findLineCol(code, token);
|
|
483
491
|
const location = pos ? `${blue(filePath)}${green(`:${pos.line}:${pos.column}`)}` : blue(filePath);
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
${
|
|
487
|
-
);
|
|
492
|
+
const suggestion = suggest?.(token) ?? null;
|
|
493
|
+
const hint = suggestion ? `${gray("\u2014 did you mean")} ${highlight(suggestion)}${gray("?")}${TAILWIND_SHADE.test(token) ? gray(" Kbach color shades run 1\u201312, not 50\u2013950.") : ""}` : gray("\u2014 no Kbach utility or project CSS rule matches it. Typo?");
|
|
494
|
+
console.warn(`${kbachTag()} ${gray("Unknown class")} ${highlight(token)} ${hint}
|
|
495
|
+
${bold("at")} ${location}`);
|
|
488
496
|
}
|
|
489
497
|
|
|
490
498
|
// src/staticCss/engine.ts
|
|
@@ -494,7 +502,8 @@ function normPath(p) {
|
|
|
494
502
|
}
|
|
495
503
|
var SAFELIST_KEY = "\0kbach-safelist";
|
|
496
504
|
function createKbachStaticCssEngine(options) {
|
|
497
|
-
const { root, theme,
|
|
505
|
+
const { root, theme, includeDirs, safelist } = options;
|
|
506
|
+
const themeJson = JSON.stringify(withColorVariables(theme));
|
|
498
507
|
const fileTokens = /* @__PURE__ */ new Map();
|
|
499
508
|
const tokenRules = /* @__PURE__ */ new Map();
|
|
500
509
|
const fileTags = /* @__PURE__ */ new Map();
|
|
@@ -512,7 +521,7 @@ function createKbachStaticCssEngine(options) {
|
|
|
512
521
|
tokens.add(tok);
|
|
513
522
|
const rules = resolveToken(tok);
|
|
514
523
|
if (process.env.NODE_ENV !== "production") {
|
|
515
|
-
warnIfUnknownClass(tok, filePath, code, rules.length > 0, projectCssClasses, warnedTokens);
|
|
524
|
+
warnIfUnknownClass(tok, filePath, code, rules.length > 0, projectCssClasses, warnedTokens, (t) => suggestClassForToken(t, themeJson));
|
|
516
525
|
}
|
|
517
526
|
}
|
|
518
527
|
fileTokens.set(normPath(filePath), tokens);
|
|
@@ -597,13 +606,27 @@ function isEsmRequireFailure(err) {
|
|
|
597
606
|
return err.code === "ERR_REQUIRE_ESM" || /is not defined in ES module scope/.test(err.message);
|
|
598
607
|
}
|
|
599
608
|
async function importConfigModule(path) {
|
|
600
|
-
const
|
|
609
|
+
const url = pathToFileURL(path).href;
|
|
610
|
+
let mod;
|
|
611
|
+
try {
|
|
612
|
+
mod = await nativeImport(url + "?t=" + Date.now());
|
|
613
|
+
} catch (err) {
|
|
614
|
+
if (err.code !== "ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING") throw err;
|
|
615
|
+
mod = await import(url);
|
|
616
|
+
}
|
|
601
617
|
return mod.default ?? mod;
|
|
602
618
|
}
|
|
619
|
+
var nativeImport = new Function("url", "return import(url)");
|
|
603
620
|
function requireConfigModule(root, path) {
|
|
604
|
-
const
|
|
621
|
+
const req = createRequire(root);
|
|
622
|
+
delete req.cache[req.resolve(path)];
|
|
623
|
+
const mod = req(path);
|
|
605
624
|
return mod.default ?? mod;
|
|
606
625
|
}
|
|
626
|
+
function isConfigFile(root, file) {
|
|
627
|
+
const norm = (p) => p.replace(/\\/g, "/").toLowerCase();
|
|
628
|
+
return /^kbach\.config\.(c|m)?js$/.test(basename(file)) && norm(dirname(file)) === norm(root);
|
|
629
|
+
}
|
|
607
630
|
async function loadConfigFile(root) {
|
|
608
631
|
const cjsPath = join4(root, "kbach.config.cjs");
|
|
609
632
|
if (existsSync(cjsPath)) return requireConfigModule(root, cjsPath);
|
|
@@ -611,6 +634,7 @@ async function loadConfigFile(root) {
|
|
|
611
634
|
if (existsSync(mjsPath)) return importConfigModule(mjsPath);
|
|
612
635
|
const jsPath = join4(root, "kbach.config.js");
|
|
613
636
|
if (!existsSync(jsPath)) return void 0;
|
|
637
|
+
if (isEsmProject(root)) return importConfigModule(jsPath);
|
|
614
638
|
try {
|
|
615
639
|
return requireConfigModule(root, jsPath);
|
|
616
640
|
} catch (err) {
|
|
@@ -618,6 +642,13 @@ async function loadConfigFile(root) {
|
|
|
618
642
|
return importConfigModule(jsPath);
|
|
619
643
|
}
|
|
620
644
|
}
|
|
645
|
+
function isEsmProject(root) {
|
|
646
|
+
try {
|
|
647
|
+
return JSON.parse(readFileSync3(join4(root, "package.json"), "utf-8")).type === "module";
|
|
648
|
+
} catch {
|
|
649
|
+
return false;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
621
652
|
async function resolveEffectiveTheme(root, options) {
|
|
622
653
|
if (options.theme) return options.theme;
|
|
623
654
|
if (options.config) return resolveKbachConfig(options.config);
|
|
@@ -629,7 +660,7 @@ function kbach(options = {}) {
|
|
|
629
660
|
const safelist = options.safelist ?? [];
|
|
630
661
|
let root = process.cwd();
|
|
631
662
|
let theme = defaultTheme;
|
|
632
|
-
let engine = createKbachStaticCssEngine({ root, theme,
|
|
663
|
+
let engine = createKbachStaticCssEngine({ root, theme, includeDirs, safelist });
|
|
633
664
|
let mainCSSFilePath = join4(root, "src", "kbach.css");
|
|
634
665
|
function mainCSSFile() {
|
|
635
666
|
return mainCSSFilePath;
|
|
@@ -646,13 +677,27 @@ function kbach(options = {}) {
|
|
|
646
677
|
syncMainCSSFile(server);
|
|
647
678
|
}, CSS_SYNC_DEBOUNCE_MS);
|
|
648
679
|
}
|
|
680
|
+
async function reloadConfig(server) {
|
|
681
|
+
if (options.theme || options.config) return;
|
|
682
|
+
try {
|
|
683
|
+
theme = await resolveEffectiveTheme(root, options);
|
|
684
|
+
} catch (err) {
|
|
685
|
+
console.warn(`${kbachTag()} Couldn't reload kbach.config: ${err.message}`);
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
engine = createKbachStaticCssEngine({ root, theme, includeDirs, safelist });
|
|
689
|
+
engine.scanProjectCssSelectorsOnce();
|
|
690
|
+
engine.initialScan();
|
|
691
|
+
engine.processSafelist();
|
|
692
|
+
syncMainCSSFile(server);
|
|
693
|
+
}
|
|
649
694
|
return {
|
|
650
695
|
name: "kbach",
|
|
651
696
|
enforce: "pre",
|
|
652
697
|
async configResolved(resolved) {
|
|
653
698
|
root = resolved.root;
|
|
654
699
|
theme = await resolveEffectiveTheme(root, options);
|
|
655
|
-
engine = createKbachStaticCssEngine({ root, theme,
|
|
700
|
+
engine = createKbachStaticCssEngine({ root, theme, includeDirs, safelist });
|
|
656
701
|
mainCSSFilePath = findMainCSSFile(root, includeDirs, options.cssFile);
|
|
657
702
|
},
|
|
658
703
|
buildStart() {
|
|
@@ -667,6 +712,10 @@ function kbach(options = {}) {
|
|
|
667
712
|
configureServer(server) {
|
|
668
713
|
const onAddOrUnlink = (file, isUnlink) => {
|
|
669
714
|
if (file.includes("node_modules")) return;
|
|
715
|
+
if (isConfigFile(root, file)) {
|
|
716
|
+
void reloadConfig(server);
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
670
719
|
if (!/\.(tsx?|jsx?)$/.test(file)) return;
|
|
671
720
|
if (isUnlink) {
|
|
672
721
|
engine.removeFile(file);
|
|
@@ -682,8 +731,12 @@ function kbach(options = {}) {
|
|
|
682
731
|
server.watcher.on("add", (file) => onAddOrUnlink(file, false));
|
|
683
732
|
server.watcher.on("unlink", (file) => onAddOrUnlink(file, true));
|
|
684
733
|
},
|
|
685
|
-
handleHotUpdate({ file, server }) {
|
|
734
|
+
async handleHotUpdate({ file, server }) {
|
|
686
735
|
if (file.includes("node_modules")) return;
|
|
736
|
+
if (isConfigFile(root, file)) {
|
|
737
|
+
await reloadConfig(server);
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
687
740
|
if (!/\.(tsx?|jsx?)$/.test(file)) return;
|
|
688
741
|
try {
|
|
689
742
|
engine.processFile(file, readSourceFile(file));
|
|
@@ -704,6 +757,7 @@ export {
|
|
|
704
757
|
findMainCSSFile,
|
|
705
758
|
DEFAULT_SCAN_DIRS,
|
|
706
759
|
CSS_SYNC_DEBOUNCE_MS,
|
|
760
|
+
isConfigFile,
|
|
707
761
|
loadConfigFile,
|
|
708
762
|
resolveEffectiveTheme,
|
|
709
763
|
kbach
|
|
@@ -2,8 +2,9 @@ import {
|
|
|
2
2
|
defaultTheme,
|
|
3
3
|
detectDarkModeStrategyFromDom,
|
|
4
4
|
getTheme,
|
|
5
|
+
parseHexRgb,
|
|
5
6
|
setTheme
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-FBYS4BI3.mjs";
|
|
7
8
|
|
|
8
9
|
// src/darkModeStore.ts
|
|
9
10
|
var STORAGE_KEY = "kbach-theme";
|
|
@@ -97,56 +98,6 @@ function seedDefaultMode(fallback) {
|
|
|
97
98
|
notify();
|
|
98
99
|
}
|
|
99
100
|
|
|
100
|
-
// src/colorVariables.ts
|
|
101
|
-
function parseHexRgb(hex) {
|
|
102
|
-
const m = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(hex.trim());
|
|
103
|
-
if (!m) return null;
|
|
104
|
-
let h = m[1];
|
|
105
|
-
if (h.length === 3) h = h.split("").map((c) => c + c).join("");
|
|
106
|
-
const n = parseInt(h, 16);
|
|
107
|
-
return [n >> 16 & 255, n >> 8 & 255, n & 255];
|
|
108
|
-
}
|
|
109
|
-
function wrapDarkDecls(strategy, decls) {
|
|
110
|
-
switch (strategy) {
|
|
111
|
-
case "class":
|
|
112
|
-
return `.dark { ${decls} }`;
|
|
113
|
-
case "media":
|
|
114
|
-
return `@media (prefers-color-scheme: dark) { :root { ${decls} } }`;
|
|
115
|
-
case "attribute":
|
|
116
|
-
default:
|
|
117
|
-
return `[data-theme="dark"] { ${decls} }`;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
var STYLE_ID = "kbach-colors";
|
|
121
|
-
var injectedForTheme = null;
|
|
122
|
-
function ensureColorVariablesInjected(theme) {
|
|
123
|
-
if (typeof document === "undefined") return;
|
|
124
|
-
if (injectedForTheme === theme) return;
|
|
125
|
-
injectedForTheme = theme;
|
|
126
|
-
const lightDecls = [];
|
|
127
|
-
const darkDecls = [];
|
|
128
|
-
for (const [name, value] of Object.entries(theme.colors)) {
|
|
129
|
-
if (typeof value === "string") continue;
|
|
130
|
-
const light = parseHexRgb(value.light);
|
|
131
|
-
const dark = parseHexRgb(value.dark);
|
|
132
|
-
if (!light || !dark) continue;
|
|
133
|
-
lightDecls.push(`--kb-color-${name}: ${light.join(",")};`);
|
|
134
|
-
darkDecls.push(`--kb-color-${name}: ${dark.join(",")};`);
|
|
135
|
-
}
|
|
136
|
-
let el = document.getElementById(STYLE_ID);
|
|
137
|
-
if (lightDecls.length === 0) {
|
|
138
|
-
el?.remove();
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
if (!el) {
|
|
142
|
-
el = document.createElement("style");
|
|
143
|
-
el.id = STYLE_ID;
|
|
144
|
-
document.head.insertBefore(el, document.head.firstChild);
|
|
145
|
-
}
|
|
146
|
-
el.textContent = `:root { ${lightDecls.join(" ")} }
|
|
147
|
-
${wrapDarkDecls(theme.darkMode, darkDecls.join(" "))}`;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
101
|
// src/config.ts
|
|
151
102
|
function applyOpacityToHex(hex, opacityText) {
|
|
152
103
|
const rgb = parseHexRgb(hex);
|
|
@@ -156,7 +107,13 @@ function applyOpacityToHex(hex, opacityText) {
|
|
|
156
107
|
return `rgba(${rgb.join(",")},${clamped})`;
|
|
157
108
|
}
|
|
158
109
|
function resolveColorEntry(value, lookup) {
|
|
159
|
-
if (typeof value !== "string")
|
|
110
|
+
if (typeof value !== "string") {
|
|
111
|
+
const side = (v, mode2) => {
|
|
112
|
+
const r = resolveColorEntry(v, lookup);
|
|
113
|
+
return typeof r === "string" ? r : r[mode2];
|
|
114
|
+
};
|
|
115
|
+
return { light: side(value.light, "light"), dark: side(value.dark, "dark") };
|
|
116
|
+
}
|
|
160
117
|
const slash = value.indexOf("/");
|
|
161
118
|
const name = slash === -1 ? value : value.slice(0, slash);
|
|
162
119
|
const opacity = slash === -1 ? void 0 : value.slice(slash + 1);
|
|
@@ -221,8 +178,6 @@ function applyKbachConfig(config) {
|
|
|
221
178
|
}
|
|
222
179
|
|
|
223
180
|
export {
|
|
224
|
-
parseHexRgb,
|
|
225
|
-
ensureColorVariablesInjected,
|
|
226
181
|
getGlobalDarkMode,
|
|
227
182
|
getGlobalThemeMode,
|
|
228
183
|
setGlobalThemeMode,
|
package/dist/index.d.mts
CHANGED
|
@@ -16,7 +16,13 @@ declare function isRuntimeCSSDisabled(): boolean;
|
|
|
16
16
|
/**
|
|
17
17
|
* Resolves a Kbach class string via the Rust/WASM engine, cascade-order-safe
|
|
18
18
|
* injects the resulting CSS rules into a single `<style data-kbach>` tag,
|
|
19
|
-
* and returns the class string
|
|
19
|
+
* and returns the class string to use as `className` (the input, except
|
|
20
|
+
* for a mode-aware color whose values aren't hex, which the engine still
|
|
21
|
+
* expands into per-mode classes).
|
|
22
|
+
*
|
|
23
|
+
* Classes the page's static kbach.css already defines are left to it (see
|
|
24
|
+
* `staticClasses`), and mode-aware colors use the same CSS variables as the
|
|
25
|
+
* static build (see `refreshEngineTheme`), so kb() and kbach.css agree.
|
|
20
26
|
*
|
|
21
27
|
* Must be called after `await initKbach()` resolves — see wasmLoader.ts.
|
|
22
28
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,13 @@ declare function isRuntimeCSSDisabled(): boolean;
|
|
|
16
16
|
/**
|
|
17
17
|
* Resolves a Kbach class string via the Rust/WASM engine, cascade-order-safe
|
|
18
18
|
* injects the resulting CSS rules into a single `<style data-kbach>` tag,
|
|
19
|
-
* and returns the class string
|
|
19
|
+
* and returns the class string to use as `className` (the input, except
|
|
20
|
+
* for a mode-aware color whose values aren't hex, which the engine still
|
|
21
|
+
* expands into per-mode classes).
|
|
22
|
+
*
|
|
23
|
+
* Classes the page's static kbach.css already defines are left to it (see
|
|
24
|
+
* `staticClasses`), and mode-aware colors use the same CSS variables as the
|
|
25
|
+
* static build (see `refreshEngineTheme`), so kb() and kbach.css agree.
|
|
20
26
|
*
|
|
21
27
|
* Must be called after `await initKbach()` resolves — see wasmLoader.ts.
|
|
22
28
|
*/
|
package/dist/index.js
CHANGED
|
@@ -467,6 +467,78 @@ function detectDarkModeStrategyFromDom() {
|
|
|
467
467
|
setTheme({ ...activeTheme, darkMode: raw });
|
|
468
468
|
}
|
|
469
469
|
|
|
470
|
+
// src/colorVariables.ts
|
|
471
|
+
function parseHexRgb(hex) {
|
|
472
|
+
const m = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(hex.trim());
|
|
473
|
+
if (!m) return null;
|
|
474
|
+
let h = m[1];
|
|
475
|
+
if (h.length === 3) h = h.split("").map((c) => c + c).join("");
|
|
476
|
+
const n = parseInt(h, 16);
|
|
477
|
+
return [n >> 16 & 255, n >> 8 & 255, n & 255];
|
|
478
|
+
}
|
|
479
|
+
function wrapDarkDecls(strategy, decls) {
|
|
480
|
+
switch (strategy) {
|
|
481
|
+
case "class":
|
|
482
|
+
return `.dark { ${decls} }`;
|
|
483
|
+
case "media":
|
|
484
|
+
return `@media (prefers-color-scheme: dark) { :root { ${decls} } }`;
|
|
485
|
+
case "attribute":
|
|
486
|
+
default:
|
|
487
|
+
return `[data-theme="dark"] { ${decls} }`;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
function modeAwareDecls(theme) {
|
|
491
|
+
const light = [];
|
|
492
|
+
const dark = [];
|
|
493
|
+
for (const [name, value] of Object.entries(theme.colors)) {
|
|
494
|
+
if (typeof value === "string") continue;
|
|
495
|
+
const l = parseHexRgb(value.light);
|
|
496
|
+
const d = parseHexRgb(value.dark);
|
|
497
|
+
if (!l || !d) continue;
|
|
498
|
+
light.push(`--kb-color-${name}: ${l.join(",")};`);
|
|
499
|
+
dark.push(`--kb-color-${name}: ${d.join(",")};`);
|
|
500
|
+
}
|
|
501
|
+
return { light, dark };
|
|
502
|
+
}
|
|
503
|
+
function colorVariablesCss(theme) {
|
|
504
|
+
const { light, dark } = modeAwareDecls(theme);
|
|
505
|
+
if (light.length === 0) return "";
|
|
506
|
+
return `:root { ${light.join(" ")} }
|
|
507
|
+
${wrapDarkDecls(theme.darkMode, dark.join(" "))}`;
|
|
508
|
+
}
|
|
509
|
+
function withColorVariables(theme) {
|
|
510
|
+
let changed = false;
|
|
511
|
+
const colors = {};
|
|
512
|
+
for (const [name, value] of Object.entries(theme.colors)) {
|
|
513
|
+
if (typeof value !== "string" && parseHexRgb(value.light) && parseHexRgb(value.dark)) {
|
|
514
|
+
colors[name] = `rgb(var(--kb-color-${name}))`;
|
|
515
|
+
changed = true;
|
|
516
|
+
} else {
|
|
517
|
+
colors[name] = value;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return changed ? { ...theme, colors } : theme;
|
|
521
|
+
}
|
|
522
|
+
var STYLE_ID = "kbach-colors";
|
|
523
|
+
var injectedForTheme = null;
|
|
524
|
+
function ensureColorVariablesInjected(theme) {
|
|
525
|
+
if (typeof document === "undefined") return;
|
|
526
|
+
if (injectedForTheme === theme) return;
|
|
527
|
+
injectedForTheme = theme;
|
|
528
|
+
const css = colorVariablesCss(theme);
|
|
529
|
+
let el = document.getElementById(STYLE_ID);
|
|
530
|
+
if (!css) {
|
|
531
|
+
el?.remove();
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
if (!el) {
|
|
535
|
+
el = document.createElement("style");
|
|
536
|
+
el.id = STYLE_ID;
|
|
537
|
+
document.head.insertBefore(el, document.head.firstChild);
|
|
538
|
+
}
|
|
539
|
+
el.textContent = css;
|
|
540
|
+
}
|
|
541
|
+
|
|
470
542
|
// src/reset.ts
|
|
471
543
|
var RESET_STYLE_ID = "kbach-reset";
|
|
472
544
|
var RESET_RULES = [
|
|
@@ -601,27 +673,88 @@ function ensureResetInjected() {
|
|
|
601
673
|
var KB_CACHE_MAX = 500;
|
|
602
674
|
var kbCache = /* @__PURE__ */ new Map();
|
|
603
675
|
var cachedForThemeJson = null;
|
|
676
|
+
var engineThemeJson = "";
|
|
677
|
+
var hasModeAware = false;
|
|
678
|
+
function refreshEngineTheme() {
|
|
679
|
+
const theme = getTheme();
|
|
680
|
+
const withVars = withColorVariables(theme);
|
|
681
|
+
hasModeAware = withVars !== theme;
|
|
682
|
+
engineThemeJson = hasModeAware ? JSON.stringify(withVars) : getThemeJson();
|
|
683
|
+
}
|
|
684
|
+
var staticOwner = null;
|
|
685
|
+
var staticSheet = null;
|
|
686
|
+
var staticRuleCount = -1;
|
|
687
|
+
var staticTokens = /* @__PURE__ */ new Set();
|
|
688
|
+
function unescapeCssIdent(s) {
|
|
689
|
+
return s.replace(/\\([0-9a-fA-F]{1,6})\s?/g, (_, hex) => String.fromCodePoint(parseInt(hex, 16))).replace(/\\(.)/g, "$1");
|
|
690
|
+
}
|
|
691
|
+
function isStaticKbachSheet(sheet) {
|
|
692
|
+
try {
|
|
693
|
+
return Array.from(sheet.cssRules).some((r) => r instanceof CSSStyleRule && r.selectorText === ":root" && r.cssText.includes("--kb-dark-mode"));
|
|
694
|
+
} catch {
|
|
695
|
+
return false;
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
function collectClasses(rules, into) {
|
|
699
|
+
for (const r of Array.from(rules)) {
|
|
700
|
+
if (r instanceof CSSStyleRule) {
|
|
701
|
+
for (const m of r.selectorText.matchAll(/\.((?:\\[0-9a-fA-F]{1,6}\s?|\\.|[\w-])+)/g)) into.add(unescapeCssIdent(m[1]));
|
|
702
|
+
} else if ("cssRules" in r) {
|
|
703
|
+
collectClasses(r.cssRules, into);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
function staticClasses() {
|
|
708
|
+
if (typeof document === "undefined") return staticTokens;
|
|
709
|
+
let sheet = staticOwner && staticOwner.sheet;
|
|
710
|
+
if (!sheet || !isStaticKbachSheet(sheet)) {
|
|
711
|
+
sheet = Array.from(document.styleSheets).find((s) => s !== styleEl?.sheet && isStaticKbachSheet(s)) ?? null;
|
|
712
|
+
staticOwner = sheet?.ownerNode ?? null;
|
|
713
|
+
}
|
|
714
|
+
if (!sheet) {
|
|
715
|
+
staticSheet = null;
|
|
716
|
+
staticTokens = /* @__PURE__ */ new Set();
|
|
717
|
+
return staticTokens;
|
|
718
|
+
}
|
|
719
|
+
if (sheet !== staticSheet || sheet.cssRules.length !== staticRuleCount) {
|
|
720
|
+
staticSheet = sheet;
|
|
721
|
+
staticRuleCount = sheet.cssRules.length;
|
|
722
|
+
staticTokens = /* @__PURE__ */ new Set();
|
|
723
|
+
collectClasses(sheet.cssRules, staticTokens);
|
|
724
|
+
}
|
|
725
|
+
return staticTokens;
|
|
726
|
+
}
|
|
604
727
|
function kb(classString) {
|
|
605
728
|
const themeJson = getThemeJson();
|
|
606
729
|
if (themeJson !== cachedForThemeJson) {
|
|
607
730
|
kbCache.clear();
|
|
608
731
|
cachedForThemeJson = themeJson;
|
|
732
|
+
refreshEngineTheme();
|
|
733
|
+
}
|
|
734
|
+
const statics = runtimeCSSDisabled ? null : staticClasses();
|
|
735
|
+
let toResolve = classString;
|
|
736
|
+
let alreadyStatic = "";
|
|
737
|
+
if (statics && statics.size > 0) {
|
|
738
|
+
const tokens = classString.split(/\s+/).filter(Boolean);
|
|
739
|
+
toResolve = tokens.filter((t) => !statics.has(t)).join(" ");
|
|
740
|
+
alreadyStatic = tokens.filter((t) => statics.has(t)).join(" ");
|
|
609
741
|
}
|
|
610
|
-
let result = kbCache.get(
|
|
742
|
+
let result = kbCache.get(toResolve);
|
|
611
743
|
if (result === void 0) {
|
|
612
|
-
const json = generateCss(
|
|
744
|
+
const json = generateCss(toResolve, engineThemeJson);
|
|
613
745
|
result = JSON.parse(json);
|
|
614
746
|
if (kbCache.size >= KB_CACHE_MAX) kbCache.clear();
|
|
615
|
-
kbCache.set(
|
|
747
|
+
kbCache.set(toResolve, result);
|
|
616
748
|
}
|
|
617
749
|
const { className, rules } = result;
|
|
618
750
|
if (!runtimeCSSDisabled) {
|
|
619
751
|
ensureResetInjected();
|
|
752
|
+
if (hasModeAware) ensureColorVariablesInjected(getTheme());
|
|
620
753
|
for (const { rule, order } of rules) {
|
|
621
754
|
injectRule(rule, order);
|
|
622
755
|
}
|
|
623
756
|
}
|
|
624
|
-
return className;
|
|
757
|
+
return alreadyStatic ? (alreadyStatic + " " + className).trim() : className;
|
|
625
758
|
}
|
|
626
759
|
|
|
627
760
|
// src/KbachReset.tsx
|
|
@@ -631,56 +764,6 @@ function KbachReset() {
|
|
|
631
764
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { id: RESET_STYLE_ID, children: BASE_RESET });
|
|
632
765
|
}
|
|
633
766
|
|
|
634
|
-
// src/colorVariables.ts
|
|
635
|
-
function parseHexRgb(hex) {
|
|
636
|
-
const m = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(hex.trim());
|
|
637
|
-
if (!m) return null;
|
|
638
|
-
let h = m[1];
|
|
639
|
-
if (h.length === 3) h = h.split("").map((c) => c + c).join("");
|
|
640
|
-
const n = parseInt(h, 16);
|
|
641
|
-
return [n >> 16 & 255, n >> 8 & 255, n & 255];
|
|
642
|
-
}
|
|
643
|
-
function wrapDarkDecls(strategy, decls) {
|
|
644
|
-
switch (strategy) {
|
|
645
|
-
case "class":
|
|
646
|
-
return `.dark { ${decls} }`;
|
|
647
|
-
case "media":
|
|
648
|
-
return `@media (prefers-color-scheme: dark) { :root { ${decls} } }`;
|
|
649
|
-
case "attribute":
|
|
650
|
-
default:
|
|
651
|
-
return `[data-theme="dark"] { ${decls} }`;
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
var STYLE_ID = "kbach-colors";
|
|
655
|
-
var injectedForTheme = null;
|
|
656
|
-
function ensureColorVariablesInjected(theme) {
|
|
657
|
-
if (typeof document === "undefined") return;
|
|
658
|
-
if (injectedForTheme === theme) return;
|
|
659
|
-
injectedForTheme = theme;
|
|
660
|
-
const lightDecls = [];
|
|
661
|
-
const darkDecls = [];
|
|
662
|
-
for (const [name, value] of Object.entries(theme.colors)) {
|
|
663
|
-
if (typeof value === "string") continue;
|
|
664
|
-
const light = parseHexRgb(value.light);
|
|
665
|
-
const dark = parseHexRgb(value.dark);
|
|
666
|
-
if (!light || !dark) continue;
|
|
667
|
-
lightDecls.push(`--kb-color-${name}: ${light.join(",")};`);
|
|
668
|
-
darkDecls.push(`--kb-color-${name}: ${dark.join(",")};`);
|
|
669
|
-
}
|
|
670
|
-
let el = document.getElementById(STYLE_ID);
|
|
671
|
-
if (lightDecls.length === 0) {
|
|
672
|
-
el?.remove();
|
|
673
|
-
return;
|
|
674
|
-
}
|
|
675
|
-
if (!el) {
|
|
676
|
-
el = document.createElement("style");
|
|
677
|
-
el.id = STYLE_ID;
|
|
678
|
-
document.head.insertBefore(el, document.head.firstChild);
|
|
679
|
-
}
|
|
680
|
-
el.textContent = `:root { ${lightDecls.join(" ")} }
|
|
681
|
-
${wrapDarkDecls(theme.darkMode, darkDecls.join(" "))}`;
|
|
682
|
-
}
|
|
683
|
-
|
|
684
767
|
// src/darkModeStore.ts
|
|
685
768
|
var STORAGE_KEY = "kbach-theme";
|
|
686
769
|
var listeners = /* @__PURE__ */ new Set();
|
|
@@ -782,7 +865,13 @@ function applyOpacityToHex(hex, opacityText) {
|
|
|
782
865
|
return `rgba(${rgb.join(",")},${clamped})`;
|
|
783
866
|
}
|
|
784
867
|
function resolveColorEntry(value, lookup) {
|
|
785
|
-
if (typeof value !== "string")
|
|
868
|
+
if (typeof value !== "string") {
|
|
869
|
+
const side = (v, mode2) => {
|
|
870
|
+
const r = resolveColorEntry(v, lookup);
|
|
871
|
+
return typeof r === "string" ? r : r[mode2];
|
|
872
|
+
};
|
|
873
|
+
return { light: side(value.light, "light"), dark: side(value.dark, "dark") };
|
|
874
|
+
}
|
|
786
875
|
const slash = value.indexOf("/");
|
|
787
876
|
const name = slash === -1 ? value : value.slice(0, slash);
|
|
788
877
|
const opacity = slash === -1 ? void 0 : value.slice(slash + 1);
|
package/dist/index.mjs
CHANGED
|
@@ -4,26 +4,26 @@ import {
|
|
|
4
4
|
isKbachReady,
|
|
5
5
|
isRuntimeCSSDisabled,
|
|
6
6
|
kb
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-K6AUD64N.mjs";
|
|
8
8
|
import {
|
|
9
9
|
applyKbachConfig,
|
|
10
|
-
ensureColorVariablesInjected,
|
|
11
10
|
getGlobalDarkMode,
|
|
12
11
|
getGlobalThemeMode,
|
|
13
|
-
parseHexRgb,
|
|
14
12
|
resolveKbachConfig,
|
|
15
13
|
seedDefaultMode,
|
|
16
14
|
setGlobalThemeMode,
|
|
17
15
|
subscribeGlobalDarkMode,
|
|
18
16
|
toggleGlobalDarkMode
|
|
19
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-UK5S55DF.mjs";
|
|
20
18
|
import {
|
|
21
19
|
BASE_RESET,
|
|
22
20
|
RESET_STYLE_ID,
|
|
23
21
|
defaultTheme,
|
|
22
|
+
ensureColorVariablesInjected,
|
|
24
23
|
getTheme,
|
|
24
|
+
parseHexRgb,
|
|
25
25
|
setTheme
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-FBYS4BI3.mjs";
|
|
27
27
|
|
|
28
28
|
// src/KbachReset.tsx
|
|
29
29
|
import { jsx } from "react/jsx-runtime";
|