@kbach/react 1.0.0-beta.2 → 1.0.0-beta.21
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 +204 -16
- package/dist/chunk-43FOLRQA.mjs +234 -0
- package/dist/{chunk-PAJ6KHDB.mjs → chunk-5EXGGZMA.mjs} +1 -1
- package/dist/{chunk-ZQJKL2MV.mjs → chunk-BJEOK2VK.mjs} +18 -4
- package/dist/{chunk-N5HCQIBB.mjs → chunk-OVKVZA7B.mjs} +21 -1
- package/dist/chunk-QYTXXF22.mjs +690 -0
- package/dist/{config-BQ_b-qxF.d.mts → config-N74_lKa0.d.mts} +33 -2
- package/dist/{config-BQ_b-qxF.d.ts → config-N74_lKa0.d.ts} +33 -2
- package/dist/index.d.mts +67 -2
- package/dist/index.d.ts +67 -2
- package/dist/index.js +157 -69
- package/dist/index.mjs +55 -106
- package/dist/jsx-dev-runtime.js +30 -4
- package/dist/jsx-dev-runtime.mjs +3 -3
- package/dist/jsx-runtime.js +30 -4
- package/dist/jsx-runtime.mjs +3 -3
- package/dist/postcss-plugin.d.mts +36 -0
- package/dist/postcss-plugin.d.ts +36 -0
- package/dist/postcss-plugin.js +1253 -0
- package/dist/postcss-plugin.mjs +84 -0
- package/dist/vite-plugin.d.mts +94 -6
- package/dist/vite-plugin.d.ts +94 -6
- package/dist/vite-plugin.js +498 -910
- package/dist/vite-plugin.mjs +15 -1198
- package/package.json +26 -4
- package/dist/chunk-NKR3PSWO.mjs +0 -115
package/dist/vite-plugin.js
CHANGED
|
@@ -20,122 +20,19 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/vite-plugin/index.ts
|
|
21
21
|
var vite_plugin_exports = {};
|
|
22
22
|
__export(vite_plugin_exports, {
|
|
23
|
-
|
|
23
|
+
CSS_SYNC_DEBOUNCE_MS: () => CSS_SYNC_DEBOUNCE_MS,
|
|
24
|
+
DEFAULT_SCAN_DIRS: () => DEFAULT_SCAN_DIRS,
|
|
25
|
+
findMainCSSFile: () => findMainCSSFile,
|
|
26
|
+
kbach: () => kbach,
|
|
27
|
+
loadConfigFile: () => loadConfigFile,
|
|
28
|
+
resolveEffectiveTheme: () => resolveEffectiveTheme
|
|
24
29
|
});
|
|
25
30
|
module.exports = __toCommonJS(vite_plugin_exports);
|
|
26
|
-
var
|
|
27
|
-
var
|
|
31
|
+
var import_fs3 = require("fs");
|
|
32
|
+
var import_path4 = require("path");
|
|
33
|
+
var import_url = require("url");
|
|
28
34
|
var import_module = require("module");
|
|
29
35
|
|
|
30
|
-
// src/vite-plugin/wasmNode.ts
|
|
31
|
-
var import_node = require("@kbach/core-engine/node");
|
|
32
|
-
function generateCssForToken(token, themeJson) {
|
|
33
|
-
return JSON.parse((0, import_node.generate_css)(token, themeJson));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// src/vite-plugin/scan.ts
|
|
37
|
-
var import_fs = require("fs");
|
|
38
|
-
var import_path = require("path");
|
|
39
|
-
function splitClassTokens(str) {
|
|
40
|
-
return str.split(/\s+/).filter(Boolean);
|
|
41
|
-
}
|
|
42
|
-
var NOT_A_CLASS_NAME_RE = /[${}]|-$|^[?:&|!"'=<>]+$/;
|
|
43
|
-
function pushTokens(str, into) {
|
|
44
|
-
for (const tok of splitClassTokens(str)) {
|
|
45
|
-
if (tok && !NOT_A_CLASS_NAME_RE.test(tok)) into.add(tok);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
function pushTemplateLiteralBody(body, into) {
|
|
49
|
-
const interpolationRe = /\$\{(?:[^{}]|\{[^{}]*\})*\}/g;
|
|
50
|
-
let im;
|
|
51
|
-
while ((im = interpolationRe.exec(body)) !== null) {
|
|
52
|
-
pushClassLikeStrings(im[0], into);
|
|
53
|
-
}
|
|
54
|
-
pushTokens(body.replace(/\$\{(?:[^{}]|\{[^{}]*\})*\}/g, () => "$"), into);
|
|
55
|
-
}
|
|
56
|
-
function pushClassLikeStrings(text, into) {
|
|
57
|
-
const quotedStringRe = /(["'`])((?:(?!\1).)*)\1/g;
|
|
58
|
-
let qm;
|
|
59
|
-
while ((qm = quotedStringRe.exec(text)) !== null) {
|
|
60
|
-
const [, quote, content] = qm;
|
|
61
|
-
if (quote === "`") pushTemplateLiteralBody(content, into);
|
|
62
|
-
else pushTokens(content, into);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
var JSX_TAG_RE = /<([a-z][a-zA-Z0-9]*)[\s/>]/g;
|
|
66
|
-
function scanUsedTags(code) {
|
|
67
|
-
const tags = /* @__PURE__ */ new Set();
|
|
68
|
-
let m;
|
|
69
|
-
JSX_TAG_RE.lastIndex = 0;
|
|
70
|
-
while ((m = JSX_TAG_RE.exec(code)) !== null) tags.add(m[1]);
|
|
71
|
-
return tags;
|
|
72
|
-
}
|
|
73
|
-
function extractClassStrings(code) {
|
|
74
|
-
const found = /* @__PURE__ */ new Set();
|
|
75
|
-
const simpleRe = /(?:className|kb)=(["'])((?:(?!\1).)*)\1/g;
|
|
76
|
-
let m;
|
|
77
|
-
while ((m = simpleRe.exec(code)) !== null) pushTokens(m[2], found);
|
|
78
|
-
const jsxExprRe = /(?:className|kb)=\{/g;
|
|
79
|
-
while ((m = jsxExprRe.exec(code)) !== null) {
|
|
80
|
-
let depth = 1;
|
|
81
|
-
let i = m.index + m[0].length;
|
|
82
|
-
let block = "";
|
|
83
|
-
while (i < code.length && depth > 0) {
|
|
84
|
-
const ch = code[i];
|
|
85
|
-
if (ch === "{") depth++;
|
|
86
|
-
else if (ch === "}") {
|
|
87
|
-
if (--depth === 0) break;
|
|
88
|
-
}
|
|
89
|
-
block += ch;
|
|
90
|
-
i++;
|
|
91
|
-
}
|
|
92
|
-
jsxExprRe.lastIndex = i + 1;
|
|
93
|
-
pushClassLikeStrings(block, found);
|
|
94
|
-
}
|
|
95
|
-
const classComposerCallRe = /(?:clsx|cn|classnames|cx|kb)\(/g;
|
|
96
|
-
while ((m = classComposerCallRe.exec(code)) !== null) {
|
|
97
|
-
let depth = 1;
|
|
98
|
-
let i = m.index + m[0].length;
|
|
99
|
-
let block = "";
|
|
100
|
-
while (i < code.length && depth > 0) {
|
|
101
|
-
const ch = code[i];
|
|
102
|
-
if (ch === "(") depth++;
|
|
103
|
-
else if (ch === ")") {
|
|
104
|
-
if (--depth === 0) break;
|
|
105
|
-
}
|
|
106
|
-
block += ch;
|
|
107
|
-
i++;
|
|
108
|
-
}
|
|
109
|
-
classComposerCallRe.lastIndex = i + 1;
|
|
110
|
-
pushClassLikeStrings(block, found);
|
|
111
|
-
}
|
|
112
|
-
const templateRe = /`([^`]{1,2000})`/g;
|
|
113
|
-
while ((m = templateRe.exec(code)) !== null) pushTemplateLiteralBody(m[1], found);
|
|
114
|
-
return [...found];
|
|
115
|
-
}
|
|
116
|
-
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "dist", "build", "out", ".next", ".output", ".git", ".svn", ".cache", "coverage"]);
|
|
117
|
-
var MAX_SCAN_DEPTH = 10;
|
|
118
|
-
var DEFAULT_FILE_MATCH = /\.(tsx?|jsx?)$/;
|
|
119
|
-
function scanDir(dir, onFile, depth = 0, fileMatch = DEFAULT_FILE_MATCH) {
|
|
120
|
-
if (depth > MAX_SCAN_DEPTH) return;
|
|
121
|
-
let entries;
|
|
122
|
-
try {
|
|
123
|
-
entries = (0, import_fs.readdirSync)(dir);
|
|
124
|
-
} catch {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
for (const entry of entries) {
|
|
128
|
-
if (entry.startsWith(".") || SKIP_DIRS.has(entry)) continue;
|
|
129
|
-
const full = (0, import_path.join)(dir, entry);
|
|
130
|
-
try {
|
|
131
|
-
const st = (0, import_fs.statSync)(full);
|
|
132
|
-
if (st.isDirectory()) scanDir(full, onFile, depth + 1, fileMatch);
|
|
133
|
-
else if (fileMatch.test(entry)) onFile(full, (0, import_fs.readFileSync)(full, "utf-8"));
|
|
134
|
-
} catch {
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
36
|
// src/vite-plugin/cssVars.ts
|
|
140
37
|
function hexToRgbTriplet(hex) {
|
|
141
38
|
const h = hex.replace("#", "");
|
|
@@ -388,18 +285,16 @@ function formatKbachCSS(tokenRules, theme, usedTags) {
|
|
|
388
285
|
const spacingMap = buildSpacingVarMap(theme, compact);
|
|
389
286
|
const { text, declarations } = applyVarMap(compact, colorMap, spacingMap);
|
|
390
287
|
const lines = ["/* Generated by Kbach \u2014 do not edit */", "", buildResetCSS(usedTags)];
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
lines.push("}");
|
|
395
|
-
}
|
|
288
|
+
lines.push("", ":root {", ` --kb-dark-mode: ${theme.darkMode};`);
|
|
289
|
+
for (const [varName, val] of declarations) lines.push(` ${varName}: ${val};`);
|
|
290
|
+
lines.push("}");
|
|
396
291
|
lines.push("", prettifyCSS(text));
|
|
397
292
|
return lines.join("\n");
|
|
398
293
|
}
|
|
399
|
-
function writeKbachToFile(filePath, css,
|
|
294
|
+
function writeKbachToFile(filePath, css, readFile, writeFile) {
|
|
400
295
|
let existing = "";
|
|
401
296
|
try {
|
|
402
|
-
existing =
|
|
297
|
+
existing = readFile(filePath);
|
|
403
298
|
} catch {
|
|
404
299
|
}
|
|
405
300
|
const block = `${KBACH_START}
|
|
@@ -411,734 +306,10 @@ ${KBACH_END}`;
|
|
|
411
306
|
|
|
412
307
|
${block}` : block;
|
|
413
308
|
if (next === existing) return false;
|
|
414
|
-
|
|
309
|
+
writeFile(filePath, next);
|
|
415
310
|
return true;
|
|
416
311
|
}
|
|
417
312
|
|
|
418
|
-
// src/vite-plugin/unknownClassWarnings.ts
|
|
419
|
-
var import_path2 = require("path");
|
|
420
|
-
var CSS_CLASS_SELECTOR_RE = /\.(-?[a-zA-Z_][a-zA-Z0-9_-]*)/g;
|
|
421
|
-
var CSS_FILE_RE = /\.(css|scss|sass|less)$/;
|
|
422
|
-
var useColor = !!process.stdout?.isTTY && !process.env.NO_COLOR;
|
|
423
|
-
var paint = (code, s) => useColor ? `\x1B[${code}m${s}\x1B[0m` : s;
|
|
424
|
-
var green = (s) => paint("32", s);
|
|
425
|
-
var blue = (s) => paint("34", s);
|
|
426
|
-
var white = (s) => paint("97", s);
|
|
427
|
-
var gray = (s) => paint("90", s);
|
|
428
|
-
var bold = (s) => paint("1", s);
|
|
429
|
-
var ARROW = () => green("\u2192");
|
|
430
|
-
var TAG = () => bold(green("[kbach]"));
|
|
431
|
-
var highlight = (s) => bold(white(s));
|
|
432
|
-
function findLineCol(code, needle) {
|
|
433
|
-
const index = code.indexOf(needle);
|
|
434
|
-
if (index === -1) return null;
|
|
435
|
-
let line = 1;
|
|
436
|
-
let lastNewline = -1;
|
|
437
|
-
for (let i = 0; i < index; i++) {
|
|
438
|
-
if (code.charCodeAt(i) === 10) {
|
|
439
|
-
line++;
|
|
440
|
-
lastNewline = i;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
return { line, column: index - lastNewline };
|
|
444
|
-
}
|
|
445
|
-
function scanCssFileInto(code, into) {
|
|
446
|
-
const re = new RegExp(CSS_CLASS_SELECTOR_RE.source, "g");
|
|
447
|
-
let m;
|
|
448
|
-
while ((m = re.exec(code)) !== null) into.add(m[1]);
|
|
449
|
-
}
|
|
450
|
-
function scanProjectCssSelectors(root, includeDirs) {
|
|
451
|
-
const projectCssClasses = /* @__PURE__ */ new Set();
|
|
452
|
-
for (const dir of includeDirs) {
|
|
453
|
-
scanDir((0, import_path2.join)(root, dir), (_filePath, code) => scanCssFileInto(code, projectCssClasses), 0, CSS_FILE_RE);
|
|
454
|
-
}
|
|
455
|
-
return projectCssClasses;
|
|
456
|
-
}
|
|
457
|
-
function stripModifierPrefix(token) {
|
|
458
|
-
return token.replace(/^(?:[a-zA-Z0-9_/-]+:)+/, "");
|
|
459
|
-
}
|
|
460
|
-
var MARKER_CLASSES = /* @__PURE__ */ new Set(["group", "peer"]);
|
|
461
|
-
function warnIfUnknownClass(token, filePath, code, isResolvable, projectCssClasses, warnedTokens) {
|
|
462
|
-
if (isResolvable || warnedTokens.has(token)) return;
|
|
463
|
-
const base = stripModifierPrefix(token);
|
|
464
|
-
if (!base || projectCssClasses.has(base) || MARKER_CLASSES.has(base)) return;
|
|
465
|
-
warnedTokens.add(token);
|
|
466
|
-
const pos = findLineCol(code, token);
|
|
467
|
-
const location = pos ? `${blue(filePath)}${green(`:${pos.line}:${pos.column}`)}` : blue(filePath);
|
|
468
|
-
console.warn(
|
|
469
|
-
`${ARROW()} ${TAG()} ${gray("Unknown class")} ${highlight(token)} ${gray("\u2014 no Kbach utility or project CSS rule matches it. Typo?")}
|
|
470
|
-
${bold("at")} ${location}`
|
|
471
|
-
);
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
// src/vite-plugin/classNameHints.ts
|
|
475
|
-
var STRUCTURAL_TOKENS = [
|
|
476
|
-
// layout.rs
|
|
477
|
-
"flex",
|
|
478
|
-
"flex-row",
|
|
479
|
-
"flex-col",
|
|
480
|
-
"flex-row-reverse",
|
|
481
|
-
"flex-col-reverse",
|
|
482
|
-
"flex-wrap",
|
|
483
|
-
"flex-wrap-reverse",
|
|
484
|
-
"flex-nowrap",
|
|
485
|
-
"flex-1",
|
|
486
|
-
"flex-auto",
|
|
487
|
-
"flex-initial",
|
|
488
|
-
"flex-none",
|
|
489
|
-
"flex-grow",
|
|
490
|
-
"flex-grow-0",
|
|
491
|
-
"flex-shrink",
|
|
492
|
-
"flex-shrink-0",
|
|
493
|
-
"grow",
|
|
494
|
-
"grow-0",
|
|
495
|
-
"shrink",
|
|
496
|
-
"shrink-0",
|
|
497
|
-
"grid",
|
|
498
|
-
"block",
|
|
499
|
-
"inline-block",
|
|
500
|
-
"inline",
|
|
501
|
-
"inline-flex",
|
|
502
|
-
"inline-grid",
|
|
503
|
-
"contents",
|
|
504
|
-
"flow-root",
|
|
505
|
-
"hidden",
|
|
506
|
-
"items-center",
|
|
507
|
-
"items-start",
|
|
508
|
-
"items-end",
|
|
509
|
-
"items-baseline",
|
|
510
|
-
"items-stretch",
|
|
511
|
-
"justify-center",
|
|
512
|
-
"justify-start",
|
|
513
|
-
"justify-end",
|
|
514
|
-
"justify-between",
|
|
515
|
-
"justify-around",
|
|
516
|
-
"justify-evenly",
|
|
517
|
-
"content-start",
|
|
518
|
-
"content-end",
|
|
519
|
-
"content-center",
|
|
520
|
-
"content-between",
|
|
521
|
-
"content-around",
|
|
522
|
-
"content-evenly",
|
|
523
|
-
"content-stretch",
|
|
524
|
-
"self-auto",
|
|
525
|
-
"self-center",
|
|
526
|
-
"self-start",
|
|
527
|
-
"self-end",
|
|
528
|
-
"self-stretch",
|
|
529
|
-
"self-baseline",
|
|
530
|
-
"overflow-hidden",
|
|
531
|
-
"overflow-auto",
|
|
532
|
-
"overflow-scroll",
|
|
533
|
-
"overflow-visible",
|
|
534
|
-
"static",
|
|
535
|
-
"relative",
|
|
536
|
-
"absolute",
|
|
537
|
-
"fixed",
|
|
538
|
-
"sticky",
|
|
539
|
-
"aspect-square",
|
|
540
|
-
"aspect-video",
|
|
541
|
-
"w-full",
|
|
542
|
-
"h-full",
|
|
543
|
-
"min-w-full",
|
|
544
|
-
"max-w-full",
|
|
545
|
-
"min-h-full",
|
|
546
|
-
"max-h-full",
|
|
547
|
-
"w-screen",
|
|
548
|
-
"h-screen",
|
|
549
|
-
"min-w-screen",
|
|
550
|
-
"max-w-screen",
|
|
551
|
-
"min-h-screen",
|
|
552
|
-
"max-h-screen",
|
|
553
|
-
"w-auto",
|
|
554
|
-
"h-auto",
|
|
555
|
-
"m-auto",
|
|
556
|
-
"mx-auto",
|
|
557
|
-
"my-auto",
|
|
558
|
-
// grid.rs — web-only (see the module's own doc comment for why)
|
|
559
|
-
"grid-cols-none",
|
|
560
|
-
"grid-rows-none",
|
|
561
|
-
"grid-flow-row",
|
|
562
|
-
"grid-flow-col",
|
|
563
|
-
"grid-flow-dense",
|
|
564
|
-
"grid-flow-row-dense",
|
|
565
|
-
"grid-flow-col-dense",
|
|
566
|
-
"auto-cols-auto",
|
|
567
|
-
"auto-cols-min",
|
|
568
|
-
"auto-cols-max",
|
|
569
|
-
"auto-cols-fr",
|
|
570
|
-
"auto-rows-auto",
|
|
571
|
-
"auto-rows-min",
|
|
572
|
-
"auto-rows-max",
|
|
573
|
-
"auto-rows-fr",
|
|
574
|
-
"col-span-full",
|
|
575
|
-
"row-span-full",
|
|
576
|
-
"col-start-auto",
|
|
577
|
-
"col-end-auto",
|
|
578
|
-
"row-start-auto",
|
|
579
|
-
"row-end-auto",
|
|
580
|
-
"col",
|
|
581
|
-
"col-auto",
|
|
582
|
-
"row",
|
|
583
|
-
"row-auto",
|
|
584
|
-
"place-items-start",
|
|
585
|
-
"place-items-end",
|
|
586
|
-
"place-items-center",
|
|
587
|
-
"place-items-stretch",
|
|
588
|
-
"place-items-baseline",
|
|
589
|
-
"place-content-start",
|
|
590
|
-
"place-content-end",
|
|
591
|
-
"place-content-center",
|
|
592
|
-
"place-content-stretch",
|
|
593
|
-
"place-content-between",
|
|
594
|
-
"place-content-around",
|
|
595
|
-
"place-content-evenly",
|
|
596
|
-
"place-content-baseline",
|
|
597
|
-
"place-self-auto",
|
|
598
|
-
"place-self-start",
|
|
599
|
-
"place-self-end",
|
|
600
|
-
"place-self-center",
|
|
601
|
-
"place-self-stretch",
|
|
602
|
-
"justify-items-start",
|
|
603
|
-
"justify-items-end",
|
|
604
|
-
"justify-items-center",
|
|
605
|
-
"justify-items-stretch",
|
|
606
|
-
"justify-self-auto",
|
|
607
|
-
"justify-self-start",
|
|
608
|
-
"justify-self-end",
|
|
609
|
-
"justify-self-center",
|
|
610
|
-
"justify-self-stretch",
|
|
611
|
-
// transform.rs — web-only (see the module's own doc comment for why)
|
|
612
|
-
"transform-none",
|
|
613
|
-
"origin-center",
|
|
614
|
-
"origin-top",
|
|
615
|
-
"origin-top-right",
|
|
616
|
-
"origin-right",
|
|
617
|
-
"origin-bottom-right",
|
|
618
|
-
"origin-bottom",
|
|
619
|
-
"origin-bottom-left",
|
|
620
|
-
"origin-left",
|
|
621
|
-
"origin-top-left",
|
|
622
|
-
// filters.rs — web-only (see the module's own doc comment for why)
|
|
623
|
-
"blur",
|
|
624
|
-
"blur-sm",
|
|
625
|
-
"blur-md",
|
|
626
|
-
"blur-lg",
|
|
627
|
-
"blur-xl",
|
|
628
|
-
"blur-2xl",
|
|
629
|
-
"blur-3xl",
|
|
630
|
-
"blur-none",
|
|
631
|
-
"grayscale",
|
|
632
|
-
"grayscale-0",
|
|
633
|
-
"invert",
|
|
634
|
-
"invert-0",
|
|
635
|
-
"sepia",
|
|
636
|
-
"sepia-0",
|
|
637
|
-
"drop-shadow",
|
|
638
|
-
"drop-shadow-sm",
|
|
639
|
-
"drop-shadow-md",
|
|
640
|
-
"drop-shadow-lg",
|
|
641
|
-
"drop-shadow-xl",
|
|
642
|
-
"drop-shadow-2xl",
|
|
643
|
-
"drop-shadow-none",
|
|
644
|
-
"filter-none",
|
|
645
|
-
"backdrop-filter-none",
|
|
646
|
-
"backdrop-blur",
|
|
647
|
-
"backdrop-blur-sm",
|
|
648
|
-
"backdrop-blur-md",
|
|
649
|
-
"backdrop-blur-lg",
|
|
650
|
-
"backdrop-blur-xl",
|
|
651
|
-
"backdrop-blur-2xl",
|
|
652
|
-
"backdrop-blur-3xl",
|
|
653
|
-
"backdrop-blur-none",
|
|
654
|
-
"backdrop-grayscale",
|
|
655
|
-
"backdrop-grayscale-0",
|
|
656
|
-
"backdrop-invert",
|
|
657
|
-
"backdrop-invert-0",
|
|
658
|
-
"backdrop-sepia",
|
|
659
|
-
"backdrop-sepia-0",
|
|
660
|
-
// border.rs
|
|
661
|
-
"border",
|
|
662
|
-
"border-t",
|
|
663
|
-
"border-r",
|
|
664
|
-
"border-b",
|
|
665
|
-
"border-l",
|
|
666
|
-
"rounded",
|
|
667
|
-
"rounded-none",
|
|
668
|
-
"rounded-sm",
|
|
669
|
-
"rounded-md",
|
|
670
|
-
"rounded-lg",
|
|
671
|
-
"rounded-xl",
|
|
672
|
-
"rounded-2xl",
|
|
673
|
-
"rounded-3xl",
|
|
674
|
-
"rounded-full",
|
|
675
|
-
"ring",
|
|
676
|
-
"ring-0",
|
|
677
|
-
"ring-1",
|
|
678
|
-
"ring-2",
|
|
679
|
-
"ring-4",
|
|
680
|
-
"ring-8",
|
|
681
|
-
"ring-inset",
|
|
682
|
-
"ring-offset-0",
|
|
683
|
-
"ring-offset-1",
|
|
684
|
-
"ring-offset-2",
|
|
685
|
-
"ring-offset-4",
|
|
686
|
-
"ring-offset-8",
|
|
687
|
-
"outline",
|
|
688
|
-
"outline-none",
|
|
689
|
-
"border-solid",
|
|
690
|
-
"border-dashed",
|
|
691
|
-
"border-dotted",
|
|
692
|
-
"border-none",
|
|
693
|
-
// typography.rs
|
|
694
|
-
"font-thin",
|
|
695
|
-
"font-normal",
|
|
696
|
-
"font-medium",
|
|
697
|
-
"font-semibold",
|
|
698
|
-
"font-bold",
|
|
699
|
-
"font-extrabold",
|
|
700
|
-
"uppercase",
|
|
701
|
-
"lowercase",
|
|
702
|
-
"capitalize",
|
|
703
|
-
"underline",
|
|
704
|
-
"line-through",
|
|
705
|
-
"no-underline",
|
|
706
|
-
"truncate",
|
|
707
|
-
"text-xs",
|
|
708
|
-
"text-sm",
|
|
709
|
-
"text-base",
|
|
710
|
-
"text-lg",
|
|
711
|
-
"text-xl",
|
|
712
|
-
"text-2xl",
|
|
713
|
-
"text-3xl",
|
|
714
|
-
"text-4xl",
|
|
715
|
-
"text-left",
|
|
716
|
-
"text-center",
|
|
717
|
-
"text-right",
|
|
718
|
-
"text-justify",
|
|
719
|
-
// typography.rs — Phase 20 (typography completeness)
|
|
720
|
-
"italic",
|
|
721
|
-
"not-italic",
|
|
722
|
-
"leading-none",
|
|
723
|
-
"leading-tight",
|
|
724
|
-
"leading-snug",
|
|
725
|
-
"leading-normal",
|
|
726
|
-
"leading-relaxed",
|
|
727
|
-
"leading-loose",
|
|
728
|
-
"tracking-tighter",
|
|
729
|
-
"tracking-tight",
|
|
730
|
-
"tracking-normal",
|
|
731
|
-
"tracking-wide",
|
|
732
|
-
"tracking-wider",
|
|
733
|
-
"tracking-widest",
|
|
734
|
-
"decoration-auto",
|
|
735
|
-
"decoration-from-font",
|
|
736
|
-
"decoration-solid",
|
|
737
|
-
"decoration-dashed",
|
|
738
|
-
"decoration-dotted",
|
|
739
|
-
"decoration-double",
|
|
740
|
-
"decoration-wavy",
|
|
741
|
-
"underline-offset-auto",
|
|
742
|
-
"underline-offset-0",
|
|
743
|
-
"underline-offset-1",
|
|
744
|
-
"underline-offset-2",
|
|
745
|
-
"underline-offset-4",
|
|
746
|
-
"underline-offset-8",
|
|
747
|
-
"text-wrap",
|
|
748
|
-
"text-nowrap",
|
|
749
|
-
"text-balance",
|
|
750
|
-
"text-pretty",
|
|
751
|
-
"whitespace-normal",
|
|
752
|
-
"whitespace-nowrap",
|
|
753
|
-
"whitespace-pre",
|
|
754
|
-
"whitespace-pre-wrap",
|
|
755
|
-
"whitespace-pre-line",
|
|
756
|
-
"break-normal",
|
|
757
|
-
"break-words",
|
|
758
|
-
"break-all",
|
|
759
|
-
"align-baseline",
|
|
760
|
-
"align-top",
|
|
761
|
-
"align-middle",
|
|
762
|
-
"align-bottom",
|
|
763
|
-
"align-text-top",
|
|
764
|
-
"align-text-bottom",
|
|
765
|
-
"align-sub",
|
|
766
|
-
"align-super",
|
|
767
|
-
"list-none",
|
|
768
|
-
"list-disc",
|
|
769
|
-
"list-decimal",
|
|
770
|
-
"list-inside",
|
|
771
|
-
"list-outside",
|
|
772
|
-
"hyphens-none",
|
|
773
|
-
"hyphens-manual",
|
|
774
|
-
"hyphens-auto",
|
|
775
|
-
// effects.rs
|
|
776
|
-
"shadow",
|
|
777
|
-
"shadow-sm",
|
|
778
|
-
"shadow-md",
|
|
779
|
-
"shadow-lg",
|
|
780
|
-
"shadow-xl",
|
|
781
|
-
"shadow-2xl",
|
|
782
|
-
"shadow-inner",
|
|
783
|
-
"shadow-none",
|
|
784
|
-
"transition",
|
|
785
|
-
"transition-none",
|
|
786
|
-
"ease-linear",
|
|
787
|
-
"ease-in",
|
|
788
|
-
"ease-out",
|
|
789
|
-
"ease-in-out",
|
|
790
|
-
"cursor-pointer",
|
|
791
|
-
"cursor-default",
|
|
792
|
-
"cursor-not-allowed",
|
|
793
|
-
"cursor-wait",
|
|
794
|
-
"select-none",
|
|
795
|
-
"select-text",
|
|
796
|
-
"select-all",
|
|
797
|
-
"pointer-events-none",
|
|
798
|
-
"pointer-events-auto",
|
|
799
|
-
// effects.rs — Phase 22 (effects completeness)
|
|
800
|
-
"text-shadow",
|
|
801
|
-
"text-shadow-sm",
|
|
802
|
-
"text-shadow-lg",
|
|
803
|
-
"text-shadow-none",
|
|
804
|
-
"mix-blend-normal",
|
|
805
|
-
"mix-blend-multiply",
|
|
806
|
-
"mix-blend-screen",
|
|
807
|
-
"mix-blend-overlay",
|
|
808
|
-
"mix-blend-darken",
|
|
809
|
-
"mix-blend-lighten",
|
|
810
|
-
"mix-blend-color-dodge",
|
|
811
|
-
"mix-blend-color-burn",
|
|
812
|
-
"mix-blend-hard-light",
|
|
813
|
-
"mix-blend-soft-light",
|
|
814
|
-
"mix-blend-difference",
|
|
815
|
-
"mix-blend-exclusion",
|
|
816
|
-
"mix-blend-hue",
|
|
817
|
-
"mix-blend-saturation",
|
|
818
|
-
"mix-blend-color",
|
|
819
|
-
"mix-blend-luminosity",
|
|
820
|
-
"mix-blend-plus-lighter",
|
|
821
|
-
"bg-blend-normal",
|
|
822
|
-
"bg-blend-multiply",
|
|
823
|
-
"bg-blend-screen",
|
|
824
|
-
"bg-blend-overlay",
|
|
825
|
-
"bg-blend-darken",
|
|
826
|
-
"bg-blend-lighten",
|
|
827
|
-
"bg-blend-color-dodge",
|
|
828
|
-
"bg-blend-color-burn",
|
|
829
|
-
"bg-blend-hard-light",
|
|
830
|
-
"bg-blend-soft-light",
|
|
831
|
-
"bg-blend-difference",
|
|
832
|
-
"bg-blend-exclusion",
|
|
833
|
-
"bg-blend-hue",
|
|
834
|
-
"bg-blend-saturation",
|
|
835
|
-
"bg-blend-color",
|
|
836
|
-
"bg-blend-luminosity",
|
|
837
|
-
"bg-blend-plus-lighter",
|
|
838
|
-
"animate-spin",
|
|
839
|
-
"animate-ping",
|
|
840
|
-
"animate-pulse",
|
|
841
|
-
"animate-bounce",
|
|
842
|
-
"animate-none",
|
|
843
|
-
// interactivity.rs — Phase 23 (interactivity & sizing rest)
|
|
844
|
-
"resize",
|
|
845
|
-
"resize-none",
|
|
846
|
-
"resize-y",
|
|
847
|
-
"resize-x",
|
|
848
|
-
"touch-auto",
|
|
849
|
-
"touch-none",
|
|
850
|
-
"touch-pan-x",
|
|
851
|
-
"touch-pan-left",
|
|
852
|
-
"touch-pan-right",
|
|
853
|
-
"touch-pan-y",
|
|
854
|
-
"touch-pan-up",
|
|
855
|
-
"touch-pan-down",
|
|
856
|
-
"touch-pinch-zoom",
|
|
857
|
-
"touch-manipulation",
|
|
858
|
-
"will-change-auto",
|
|
859
|
-
"will-change-scroll",
|
|
860
|
-
"will-change-contents",
|
|
861
|
-
"will-change-transform",
|
|
862
|
-
"sr-only",
|
|
863
|
-
"not-sr-only",
|
|
864
|
-
"border-collapse",
|
|
865
|
-
"border-separate",
|
|
866
|
-
"table-auto",
|
|
867
|
-
"table-fixed",
|
|
868
|
-
"caption-top",
|
|
869
|
-
"caption-bottom",
|
|
870
|
-
"stroke-width-0",
|
|
871
|
-
"stroke-width-1",
|
|
872
|
-
"stroke-width-2",
|
|
873
|
-
// spacing.rs — Phase 23 (size-* shorthand + fraction-based width/height)
|
|
874
|
-
"size-full",
|
|
875
|
-
"size-auto",
|
|
876
|
-
"size-px",
|
|
877
|
-
"w-1/2",
|
|
878
|
-
"w-1/3",
|
|
879
|
-
"w-2/3",
|
|
880
|
-
"w-1/4",
|
|
881
|
-
"w-2/4",
|
|
882
|
-
"w-3/4",
|
|
883
|
-
"w-1/5",
|
|
884
|
-
"w-2/5",
|
|
885
|
-
"w-3/5",
|
|
886
|
-
"w-4/5",
|
|
887
|
-
"w-1/6",
|
|
888
|
-
"w-5/6",
|
|
889
|
-
"w-1/12",
|
|
890
|
-
"w-5/12",
|
|
891
|
-
"w-7/12",
|
|
892
|
-
"w-11/12",
|
|
893
|
-
"h-1/2",
|
|
894
|
-
"h-1/3",
|
|
895
|
-
"h-2/3",
|
|
896
|
-
"h-1/4",
|
|
897
|
-
"h-2/4",
|
|
898
|
-
"h-3/4",
|
|
899
|
-
"h-1/5",
|
|
900
|
-
"h-2/5",
|
|
901
|
-
"h-3/5",
|
|
902
|
-
"h-4/5",
|
|
903
|
-
"h-1/6",
|
|
904
|
-
"h-5/6",
|
|
905
|
-
// scroll.rs — Phase 23 (scroll-behavior/-margin/-padding, scroll-snap)
|
|
906
|
-
"scroll-auto",
|
|
907
|
-
"scroll-smooth",
|
|
908
|
-
"snap-start",
|
|
909
|
-
"snap-end",
|
|
910
|
-
"snap-center",
|
|
911
|
-
"snap-align-none",
|
|
912
|
-
"snap-normal",
|
|
913
|
-
"snap-always",
|
|
914
|
-
"snap-none",
|
|
915
|
-
"snap-x",
|
|
916
|
-
"snap-y",
|
|
917
|
-
"snap-both",
|
|
918
|
-
"snap-mandatory",
|
|
919
|
-
"snap-proximity",
|
|
920
|
-
// divide.rs
|
|
921
|
-
"divide-x",
|
|
922
|
-
"divide-y",
|
|
923
|
-
// background.rs — web-only (see the module's own doc comment for why)
|
|
924
|
-
"bg-top",
|
|
925
|
-
"bg-bottom",
|
|
926
|
-
"bg-left",
|
|
927
|
-
"bg-right",
|
|
928
|
-
"bg-center",
|
|
929
|
-
"bg-left-top",
|
|
930
|
-
"bg-left-bottom",
|
|
931
|
-
"bg-right-top",
|
|
932
|
-
"bg-right-bottom",
|
|
933
|
-
"bg-auto",
|
|
934
|
-
"bg-cover",
|
|
935
|
-
"bg-contain",
|
|
936
|
-
"bg-repeat",
|
|
937
|
-
"bg-no-repeat",
|
|
938
|
-
"bg-repeat-x",
|
|
939
|
-
"bg-repeat-y",
|
|
940
|
-
"bg-repeat-round",
|
|
941
|
-
"bg-repeat-space",
|
|
942
|
-
"bg-fixed",
|
|
943
|
-
"bg-local",
|
|
944
|
-
"bg-scroll",
|
|
945
|
-
"bg-clip-border",
|
|
946
|
-
"bg-clip-padding",
|
|
947
|
-
"bg-clip-content",
|
|
948
|
-
"bg-clip-text",
|
|
949
|
-
"bg-origin-border",
|
|
950
|
-
"bg-origin-padding",
|
|
951
|
-
"bg-origin-content",
|
|
952
|
-
"bg-none",
|
|
953
|
-
"bg-linear-to-t",
|
|
954
|
-
"bg-linear-to-tr",
|
|
955
|
-
"bg-linear-to-r",
|
|
956
|
-
"bg-linear-to-br",
|
|
957
|
-
"bg-linear-to-b",
|
|
958
|
-
"bg-linear-to-bl",
|
|
959
|
-
"bg-linear-to-l",
|
|
960
|
-
"bg-linear-to-tl",
|
|
961
|
-
"bg-radial",
|
|
962
|
-
"bg-conic",
|
|
963
|
-
// Ancestor/sibling-state marker classes — carry no styles of their own,
|
|
964
|
-
// just a selector target for group-hover:/peer-hover:/etc. below (see
|
|
965
|
-
// unknownClassWarnings.ts's MARKER_CLASSES for why they need special
|
|
966
|
-
// handling there too).
|
|
967
|
-
"group",
|
|
968
|
-
"peer",
|
|
969
|
-
// registry.rs modifiers — bare tokens only, not composed with a
|
|
970
|
-
// following utility (see this module's doc header / the Phase 15 plan).
|
|
971
|
-
"hover:",
|
|
972
|
-
"focus:",
|
|
973
|
-
"focus-visible:",
|
|
974
|
-
"focus-within:",
|
|
975
|
-
"active:",
|
|
976
|
-
"visited:",
|
|
977
|
-
"disabled:",
|
|
978
|
-
"checked:",
|
|
979
|
-
"group-hover:",
|
|
980
|
-
"group-focus:",
|
|
981
|
-
"peer-hover:",
|
|
982
|
-
"peer-focus:",
|
|
983
|
-
"peer-checked:",
|
|
984
|
-
"dark:",
|
|
985
|
-
"motion-safe:",
|
|
986
|
-
"motion-reduce:",
|
|
987
|
-
"print:",
|
|
988
|
-
"sm:",
|
|
989
|
-
"md:",
|
|
990
|
-
"lg:",
|
|
991
|
-
"xl:",
|
|
992
|
-
"2xl:",
|
|
993
|
-
// registry.rs modifiers — Phase 24 (expanded variant system), the
|
|
994
|
-
// FIXED/static additions only. Deliberately excluded: every genuinely
|
|
995
|
-
// parameterized modifier (has-[...]/group-has-[...]/peer-has-[...]/
|
|
996
|
-
// data-[...]/aria-[...]/not-[...]/min-[...]/max-[...], and the
|
|
997
|
-
// generalized group-<pseudo>/peer-<pseudo> beyond the five hardcoded
|
|
998
|
-
// combos above) — these have no finite enumerable set (their whole point
|
|
999
|
-
// is arbitrary user-supplied content), so there's nothing meaningful to
|
|
1000
|
-
// suggest beyond the bare prefix, same reasoning as every other
|
|
1001
|
-
// arbitrary-value exclusion in this file. `not-hover:`/`not-disabled:`/
|
|
1002
|
-
// etc. (wrapping a KNOWN static modifier) are excluded for the same
|
|
1003
|
-
// reason — enumerable in principle, but a full cross-product with every
|
|
1004
|
-
// modifier above would be more noise than signal for an editor hint list.
|
|
1005
|
-
"first:",
|
|
1006
|
-
"last:",
|
|
1007
|
-
"only:",
|
|
1008
|
-
"odd:",
|
|
1009
|
-
"even:",
|
|
1010
|
-
"open:",
|
|
1011
|
-
"inert:",
|
|
1012
|
-
"aria-checked:",
|
|
1013
|
-
"aria-disabled:",
|
|
1014
|
-
"aria-expanded:",
|
|
1015
|
-
"aria-hidden:",
|
|
1016
|
-
"aria-pressed:",
|
|
1017
|
-
"aria-readonly:",
|
|
1018
|
-
"aria-required:",
|
|
1019
|
-
"aria-selected:",
|
|
1020
|
-
"aria-busy:",
|
|
1021
|
-
// Phase 25 (container queries & arbitrary properties). "@container" is a
|
|
1022
|
-
// real UTILITY (container-type: inline-size), not a modifier — included
|
|
1023
|
-
// as a bare token like "flex"/"hidden" above, not with the trailing ":"
|
|
1024
|
-
// the modifier tokens below get. "@sm:"/"@md:"/"@lg:"/"@xl:"/"@2xl:" are
|
|
1025
|
-
// container-responsive modifiers (registry.rs's `is_container_responsive`),
|
|
1026
|
-
// and "starting:" wraps in @starting-style. Deliberately excluded, same
|
|
1027
|
-
// "no finite enumerable set" reasoning as Phase 24's exclusions:
|
|
1028
|
-
// "@min-[...]:"/"@max-[...]:" (arbitrary container breakpoints) and every
|
|
1029
|
-
// `[property:value]` arbitrary property — both are open-ended by design.
|
|
1030
|
-
"@container",
|
|
1031
|
-
"@sm:",
|
|
1032
|
-
"@md:",
|
|
1033
|
-
"@lg:",
|
|
1034
|
-
"@xl:",
|
|
1035
|
-
"@2xl:",
|
|
1036
|
-
"starting:"
|
|
1037
|
-
];
|
|
1038
|
-
var COLOR_PREFIXES = [
|
|
1039
|
-
"bg-",
|
|
1040
|
-
"text-",
|
|
1041
|
-
"border-",
|
|
1042
|
-
"divide-",
|
|
1043
|
-
"decoration-",
|
|
1044
|
-
"from-",
|
|
1045
|
-
"via-",
|
|
1046
|
-
"to-",
|
|
1047
|
-
"text-shadow-",
|
|
1048
|
-
"ring-",
|
|
1049
|
-
"ring-offset-",
|
|
1050
|
-
"caret-",
|
|
1051
|
-
"accent-",
|
|
1052
|
-
"fill-",
|
|
1053
|
-
"stroke-"
|
|
1054
|
-
];
|
|
1055
|
-
var SPACING_PREFIXES = [
|
|
1056
|
-
"p-",
|
|
1057
|
-
"px-",
|
|
1058
|
-
"py-",
|
|
1059
|
-
"pt-",
|
|
1060
|
-
"pr-",
|
|
1061
|
-
"pb-",
|
|
1062
|
-
"pl-",
|
|
1063
|
-
"m-",
|
|
1064
|
-
"mx-",
|
|
1065
|
-
"my-",
|
|
1066
|
-
"mt-",
|
|
1067
|
-
"mr-",
|
|
1068
|
-
"mb-",
|
|
1069
|
-
"ml-",
|
|
1070
|
-
"gap-",
|
|
1071
|
-
"gap-x-",
|
|
1072
|
-
"gap-y-",
|
|
1073
|
-
"w-",
|
|
1074
|
-
"h-",
|
|
1075
|
-
"min-w-",
|
|
1076
|
-
"max-w-",
|
|
1077
|
-
"min-h-",
|
|
1078
|
-
"max-h-",
|
|
1079
|
-
"size-",
|
|
1080
|
-
"top-",
|
|
1081
|
-
"right-",
|
|
1082
|
-
"bottom-",
|
|
1083
|
-
"left-",
|
|
1084
|
-
"inset-",
|
|
1085
|
-
"space-x-",
|
|
1086
|
-
"space-y-",
|
|
1087
|
-
"indent-",
|
|
1088
|
-
"scroll-m-",
|
|
1089
|
-
"scroll-mx-",
|
|
1090
|
-
"scroll-my-",
|
|
1091
|
-
"scroll-mt-",
|
|
1092
|
-
"scroll-mr-",
|
|
1093
|
-
"scroll-mb-",
|
|
1094
|
-
"scroll-ml-",
|
|
1095
|
-
"scroll-p-",
|
|
1096
|
-
"scroll-px-",
|
|
1097
|
-
"scroll-py-",
|
|
1098
|
-
"scroll-pt-",
|
|
1099
|
-
"scroll-pr-",
|
|
1100
|
-
"scroll-pb-",
|
|
1101
|
-
"scroll-pl-"
|
|
1102
|
-
];
|
|
1103
|
-
var SIZE_PREFIXES = ["w-", "h-", "min-w-", "max-w-", "min-h-", "max-h-", "size-"];
|
|
1104
|
-
var NAMED_SIZES = ["sm", "md", "lg", "xl", "2xl", "3xl", "4xl", "5xl", "6xl", "7xl", "8xl", "9xl"];
|
|
1105
|
-
function buildClassTokens(theme) {
|
|
1106
|
-
const tokens = new Set(STRUCTURAL_TOKENS);
|
|
1107
|
-
for (const colorKey of Object.keys(theme.colors)) {
|
|
1108
|
-
for (const prefix of COLOR_PREFIXES) tokens.add(`${prefix}${colorKey}`);
|
|
1109
|
-
}
|
|
1110
|
-
for (const spacingKey of Object.keys(theme.spacing)) {
|
|
1111
|
-
for (const prefix of SPACING_PREFIXES) tokens.add(`${prefix}${spacingKey}`);
|
|
1112
|
-
}
|
|
1113
|
-
for (const size of NAMED_SIZES) {
|
|
1114
|
-
for (const prefix of SIZE_PREFIXES) tokens.add(`${prefix}${size}`);
|
|
1115
|
-
}
|
|
1116
|
-
return Array.from(tokens).sort();
|
|
1117
|
-
}
|
|
1118
|
-
function buildClassNameHintsDts(tokens) {
|
|
1119
|
-
const literals = tokens.map((t) => ` | '${t}'`).join("\n");
|
|
1120
|
-
return [
|
|
1121
|
-
"// Generated by Kbach \u2014 do not edit",
|
|
1122
|
-
"// Editor autocomplete for className \u2014 see packages/react/src/vite-plugin/classNameHints.ts",
|
|
1123
|
-
"",
|
|
1124
|
-
"type KbachClassToken =",
|
|
1125
|
-
literals,
|
|
1126
|
-
";",
|
|
1127
|
-
"",
|
|
1128
|
-
"export type KbachClassName = KbachClassToken | `${string} ${KbachClassToken}` | (string & {});",
|
|
1129
|
-
"",
|
|
1130
|
-
"declare module 'react' {",
|
|
1131
|
-
" interface HTMLAttributes<T> {",
|
|
1132
|
-
" className?: KbachClassName | undefined;",
|
|
1133
|
-
" }",
|
|
1134
|
-
" interface SVGAttributes<T> {",
|
|
1135
|
-
" className?: KbachClassName | undefined;",
|
|
1136
|
-
" }",
|
|
1137
|
-
"}",
|
|
1138
|
-
""
|
|
1139
|
-
].join("\n");
|
|
1140
|
-
}
|
|
1141
|
-
|
|
1142
313
|
// src/generatedPalette.ts
|
|
1143
314
|
var PALETTE = {
|
|
1144
315
|
"amber-1": "#fffbeb",
|
|
@@ -1489,12 +660,39 @@ var defaultTheme = {
|
|
|
1489
660
|
serif: 'ui-serif, Georgia, Cambria, "Times New Roman", Times, serif',
|
|
1490
661
|
mono: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace'
|
|
1491
662
|
},
|
|
1492
|
-
darkMode:
|
|
663
|
+
// Matches real Tailwind's own default (`darkMode: 'media'`): pure
|
|
664
|
+
// `@media (prefers-color-scheme: dark)`, works with zero JS — a project
|
|
665
|
+
// using only static `className` strings gets working `dark:` classes
|
|
666
|
+
// out of the box, with no runtime import required to write `data-theme`/
|
|
667
|
+
// `.dark` onto `<html>` (see darkModeStore.ts's `applyToDom`). The
|
|
668
|
+
// tradeoff: `'media'` can't be overridden by a manual light/dark toggle —
|
|
669
|
+
// `useTheme()`/`toggleGlobalDarkMode()` still track `isDark` correctly
|
|
670
|
+
// for JS consumers, but flipping it has no visible effect on `dark:`
|
|
671
|
+
// classes, since the browser's media query only ever reflects the real
|
|
672
|
+
// OS setting. Opt into `darkMode: 'class'` or `'attribute'` explicitly
|
|
673
|
+
// (via `kbach.config.js` or the `config`/`theme` plugin option) as soon
|
|
674
|
+
// as an app wants a real in-app toggle.
|
|
675
|
+
darkMode: "media",
|
|
1493
676
|
// Empty by default, matching real Tailwind's own defaults (no forced
|
|
1494
677
|
// centering/padding) — see `ContainerConfig`'s own doc comment.
|
|
1495
678
|
container: {}
|
|
1496
679
|
};
|
|
680
|
+
var activeTheme = defaultTheme;
|
|
1497
681
|
var activeThemeJson = JSON.stringify(defaultTheme);
|
|
682
|
+
function setTheme(theme) {
|
|
683
|
+
activeTheme = theme;
|
|
684
|
+
activeThemeJson = JSON.stringify(theme);
|
|
685
|
+
}
|
|
686
|
+
function getTheme() {
|
|
687
|
+
return activeTheme;
|
|
688
|
+
}
|
|
689
|
+
var DARK_MODE_STRATEGIES = /* @__PURE__ */ new Set(["attribute", "class", "media"]);
|
|
690
|
+
function detectDarkModeStrategyFromDom() {
|
|
691
|
+
if (typeof document === "undefined") return;
|
|
692
|
+
const raw = getComputedStyle(document.documentElement).getPropertyValue("--kb-dark-mode").trim();
|
|
693
|
+
if (!DARK_MODE_STRATEGIES.has(raw) || raw === activeTheme.darkMode) return;
|
|
694
|
+
setTheme({ ...activeTheme, darkMode: raw });
|
|
695
|
+
}
|
|
1498
696
|
|
|
1499
697
|
// src/colorVariables.ts
|
|
1500
698
|
function parseHexRgb(hex) {
|
|
@@ -1506,6 +704,61 @@ function parseHexRgb(hex) {
|
|
|
1506
704
|
return [n >> 16 & 255, n >> 8 & 255, n & 255];
|
|
1507
705
|
}
|
|
1508
706
|
|
|
707
|
+
// src/darkModeStore.ts
|
|
708
|
+
var STORAGE_KEY = "kbach-theme";
|
|
709
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
710
|
+
function systemPrefersDark() {
|
|
711
|
+
if (typeof window === "undefined" || !window.matchMedia) return false;
|
|
712
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
713
|
+
}
|
|
714
|
+
function storage() {
|
|
715
|
+
return typeof window === "undefined" ? null : window.localStorage;
|
|
716
|
+
}
|
|
717
|
+
function readPersistedMode() {
|
|
718
|
+
const ls = storage();
|
|
719
|
+
if (!ls) return null;
|
|
720
|
+
try {
|
|
721
|
+
const raw = ls.getItem(STORAGE_KEY);
|
|
722
|
+
return raw === "light" || raw === "dark" || raw === "system" ? raw : null;
|
|
723
|
+
} catch {
|
|
724
|
+
return null;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
function resolveIsDark(m) {
|
|
728
|
+
return m === "system" ? systemPrefersDark() : m === "dark";
|
|
729
|
+
}
|
|
730
|
+
function applyToDom(dark) {
|
|
731
|
+
if (typeof document === "undefined") return;
|
|
732
|
+
const root = document.documentElement;
|
|
733
|
+
const strategy = getTheme().darkMode;
|
|
734
|
+
root.classList.toggle("dark", strategy === "class" && dark);
|
|
735
|
+
root.classList.toggle("light", strategy === "class" && !dark);
|
|
736
|
+
if (strategy === "attribute") {
|
|
737
|
+
root.setAttribute("data-theme", dark ? "dark" : "light");
|
|
738
|
+
} else {
|
|
739
|
+
root.removeAttribute("data-theme");
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
detectDarkModeStrategyFromDom();
|
|
743
|
+
var persistedMode = readPersistedMode();
|
|
744
|
+
var mode = persistedMode ?? "system";
|
|
745
|
+
var isDark = resolveIsDark(mode);
|
|
746
|
+
applyToDom(isDark);
|
|
747
|
+
if (typeof window !== "undefined" && window.matchMedia) {
|
|
748
|
+
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
749
|
+
const onSystemChange = (event) => {
|
|
750
|
+
if (mode !== "system") return;
|
|
751
|
+
isDark = event.matches;
|
|
752
|
+
applyToDom(isDark);
|
|
753
|
+
notify();
|
|
754
|
+
};
|
|
755
|
+
if (mq.addEventListener) mq.addEventListener("change", onSystemChange);
|
|
756
|
+
else mq.addListener(onSystemChange);
|
|
757
|
+
}
|
|
758
|
+
function notify() {
|
|
759
|
+
for (const listener of listeners) listener();
|
|
760
|
+
}
|
|
761
|
+
|
|
1509
762
|
// src/config.ts
|
|
1510
763
|
function applyOpacityToHex(hex, opacityText) {
|
|
1511
764
|
const rgb = parseHexRgb(hex);
|
|
@@ -1525,11 +778,29 @@ function resolveColorEntry(value, lookup) {
|
|
|
1525
778
|
return typeof base === "string" ? applyOpacityToHex(base, opacity) : { light: applyOpacityToHex(base.light, opacity), dark: applyOpacityToHex(base.dark, opacity) };
|
|
1526
779
|
}
|
|
1527
780
|
function resolveColors(extend, existing) {
|
|
781
|
+
const { dark: darkExtend, ...lightExtend } = extend;
|
|
1528
782
|
const resolved = {};
|
|
1529
783
|
const lookup = (name) => resolved[name] ?? existing[name];
|
|
1530
|
-
for (const [name, value] of Object.entries(
|
|
784
|
+
for (const [name, value] of Object.entries(lightExtend)) {
|
|
785
|
+
if (typeof value === "object" && value !== null && !("light" in value) && !("dark" in value)) continue;
|
|
1531
786
|
resolved[name] = resolveColorEntry(value, lookup);
|
|
1532
787
|
}
|
|
788
|
+
if (darkExtend) {
|
|
789
|
+
const resolvedDark = {};
|
|
790
|
+
const lookupDark = (name) => {
|
|
791
|
+
const found = resolvedDark[name] ?? existing[name];
|
|
792
|
+
return typeof found === "string" ? found : void 0;
|
|
793
|
+
};
|
|
794
|
+
for (const [name, value] of Object.entries(darkExtend)) {
|
|
795
|
+
const entry = resolveColorEntry(value, lookupDark);
|
|
796
|
+
resolvedDark[name] = typeof entry === "string" ? entry : entry.dark;
|
|
797
|
+
}
|
|
798
|
+
for (const [name, darkValue] of Object.entries(resolvedDark)) {
|
|
799
|
+
const lightEntry = resolved[name];
|
|
800
|
+
if (lightEntry === void 0 || typeof lightEntry !== "string") continue;
|
|
801
|
+
resolved[name] = { light: lightEntry, dark: darkValue };
|
|
802
|
+
}
|
|
803
|
+
}
|
|
1533
804
|
return resolved;
|
|
1534
805
|
}
|
|
1535
806
|
function resolveKbachConfig(config) {
|
|
@@ -1555,35 +826,275 @@ function resolveKbachConfig(config) {
|
|
|
1555
826
|
return theme;
|
|
1556
827
|
}
|
|
1557
828
|
|
|
1558
|
-
// src/
|
|
1559
|
-
var
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
829
|
+
// src/staticCss/engine.ts
|
|
830
|
+
var import_fs2 = require("fs");
|
|
831
|
+
var import_path3 = require("path");
|
|
832
|
+
|
|
833
|
+
// src/vite-plugin/wasmNode.ts
|
|
834
|
+
var import_node = require("@kbach/core-engine/node");
|
|
835
|
+
function generateCssForToken(token, themeJson) {
|
|
836
|
+
return JSON.parse((0, import_node.generate_css)(token, themeJson));
|
|
1563
837
|
}
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
838
|
+
|
|
839
|
+
// src/vite-plugin/scan.ts
|
|
840
|
+
var import_fs = require("fs");
|
|
841
|
+
var import_path = require("path");
|
|
842
|
+
function stripComments(code) {
|
|
843
|
+
let out = "";
|
|
844
|
+
let i = 0;
|
|
845
|
+
const n = code.length;
|
|
846
|
+
while (i < n) {
|
|
847
|
+
const two = code[i] + (code[i + 1] ?? "");
|
|
848
|
+
if (two === "//") {
|
|
849
|
+
i += 2;
|
|
850
|
+
while (i < n && code[i] !== "\n") i++;
|
|
851
|
+
continue;
|
|
852
|
+
}
|
|
853
|
+
if (two === "/*") {
|
|
854
|
+
i += 2;
|
|
855
|
+
while (i < n && code[i] + (code[i + 1] ?? "") !== "*/") i++;
|
|
856
|
+
i += 2;
|
|
857
|
+
continue;
|
|
858
|
+
}
|
|
859
|
+
const ch = code[i];
|
|
860
|
+
if (ch === '"' || ch === "'") {
|
|
861
|
+
out += ch;
|
|
862
|
+
i++;
|
|
863
|
+
while (i < n && code[i] !== ch) {
|
|
864
|
+
if (code[i] === "\\") {
|
|
865
|
+
out += code[i] + (code[i + 1] ?? "");
|
|
866
|
+
i += 2;
|
|
867
|
+
continue;
|
|
868
|
+
}
|
|
869
|
+
out += code[i];
|
|
870
|
+
i++;
|
|
871
|
+
}
|
|
872
|
+
out += code[i] ?? "";
|
|
873
|
+
i++;
|
|
874
|
+
continue;
|
|
875
|
+
}
|
|
876
|
+
if (ch === "`") {
|
|
877
|
+
out += ch;
|
|
878
|
+
i++;
|
|
879
|
+
let interpolationDepth = 0;
|
|
880
|
+
while (i < n) {
|
|
881
|
+
if (interpolationDepth === 0 && code[i] === "`") {
|
|
882
|
+
out += code[i];
|
|
883
|
+
i++;
|
|
884
|
+
break;
|
|
885
|
+
}
|
|
886
|
+
if (interpolationDepth === 0 && code[i] === "\\") {
|
|
887
|
+
out += code[i] + (code[i + 1] ?? "");
|
|
888
|
+
i += 2;
|
|
889
|
+
continue;
|
|
890
|
+
}
|
|
891
|
+
if (interpolationDepth === 0 && code[i] + (code[i + 1] ?? "") === "${") {
|
|
892
|
+
out += "${";
|
|
893
|
+
i += 2;
|
|
894
|
+
interpolationDepth = 1;
|
|
895
|
+
continue;
|
|
896
|
+
}
|
|
897
|
+
if (interpolationDepth > 0) {
|
|
898
|
+
if (code[i] === "{") interpolationDepth++;
|
|
899
|
+
else if (code[i] === "}") {
|
|
900
|
+
interpolationDepth--;
|
|
901
|
+
if (interpolationDepth === 0) {
|
|
902
|
+
out += "}";
|
|
903
|
+
i++;
|
|
904
|
+
continue;
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
out += code[i];
|
|
909
|
+
i++;
|
|
910
|
+
}
|
|
911
|
+
continue;
|
|
912
|
+
}
|
|
913
|
+
out += ch;
|
|
914
|
+
i++;
|
|
915
|
+
}
|
|
916
|
+
return out;
|
|
1567
917
|
}
|
|
1568
|
-
function
|
|
1569
|
-
|
|
918
|
+
function splitClassTokens(str) {
|
|
919
|
+
return str.split(/\s+/).filter(Boolean);
|
|
1570
920
|
}
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
921
|
+
var NOT_A_CLASS_NAME_RE = /[${}]|-$|^[?:&|!"'=<>]+$/;
|
|
922
|
+
function pushTokens(str, into) {
|
|
923
|
+
for (const tok of splitClassTokens(str)) {
|
|
924
|
+
if (tok && !NOT_A_CLASS_NAME_RE.test(tok)) into.add(tok);
|
|
925
|
+
}
|
|
1574
926
|
}
|
|
1575
|
-
function
|
|
1576
|
-
const
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
927
|
+
function pushTemplateLiteralBody(body, into) {
|
|
928
|
+
const interpolationRe = /\$\{(?:[^{}]|\{[^{}]*\})*\}/g;
|
|
929
|
+
let im;
|
|
930
|
+
while ((im = interpolationRe.exec(body)) !== null) {
|
|
931
|
+
pushClassLikeStrings(im[0], into);
|
|
932
|
+
}
|
|
933
|
+
pushTokens(body.replace(/\$\{(?:[^{}]|\{[^{}]*\})*\}/g, () => "$"), into);
|
|
1580
934
|
}
|
|
1581
|
-
function
|
|
1582
|
-
|
|
1583
|
-
let
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
935
|
+
function pushClassLikeStrings(text, into) {
|
|
936
|
+
const quotedStringRe = /(["'`])((?:(?!\1).)*)\1/g;
|
|
937
|
+
let qm;
|
|
938
|
+
while ((qm = quotedStringRe.exec(text)) !== null) {
|
|
939
|
+
const [, quote, content] = qm;
|
|
940
|
+
if (quote === "`") pushTemplateLiteralBody(content, into);
|
|
941
|
+
else pushTokens(content, into);
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
var JSX_TAG_RE = /<([a-z][a-zA-Z0-9]*)[\s/>]/g;
|
|
945
|
+
function scanUsedTags(code) {
|
|
946
|
+
const cleaned = stripComments(code);
|
|
947
|
+
const tags = /* @__PURE__ */ new Set();
|
|
948
|
+
let m;
|
|
949
|
+
JSX_TAG_RE.lastIndex = 0;
|
|
950
|
+
while ((m = JSX_TAG_RE.exec(cleaned)) !== null) tags.add(m[1]);
|
|
951
|
+
return tags;
|
|
952
|
+
}
|
|
953
|
+
function extractClassStrings(rawCode) {
|
|
954
|
+
const code = stripComments(rawCode);
|
|
955
|
+
const found = /* @__PURE__ */ new Set();
|
|
956
|
+
const simpleRe = /(?:className|kb)=(["'])((?:(?!\1).)*)\1/g;
|
|
957
|
+
let m;
|
|
958
|
+
while ((m = simpleRe.exec(code)) !== null) pushTokens(m[2], found);
|
|
959
|
+
const MAX_BLOCK_SCAN_LEN = 2e4;
|
|
960
|
+
const jsxExprRe = /\b(?:className|kb)=\{/g;
|
|
961
|
+
while ((m = jsxExprRe.exec(code)) !== null) {
|
|
962
|
+
let depth = 1;
|
|
963
|
+
let i = m.index + m[0].length;
|
|
964
|
+
const scanEnd = Math.min(code.length, i + MAX_BLOCK_SCAN_LEN);
|
|
965
|
+
let block = "";
|
|
966
|
+
while (i < scanEnd && depth > 0) {
|
|
967
|
+
const ch = code[i];
|
|
968
|
+
if (ch === "{") depth++;
|
|
969
|
+
else if (ch === "}") {
|
|
970
|
+
if (--depth === 0) break;
|
|
971
|
+
}
|
|
972
|
+
block += ch;
|
|
973
|
+
i++;
|
|
974
|
+
}
|
|
975
|
+
jsxExprRe.lastIndex = i + 1;
|
|
976
|
+
if (depth === 0) pushClassLikeStrings(block, found);
|
|
977
|
+
}
|
|
978
|
+
const classComposerCallRe = /\b(?:clsx|cn|classnames|cx|kb)\(/g;
|
|
979
|
+
while ((m = classComposerCallRe.exec(code)) !== null) {
|
|
980
|
+
let depth = 1;
|
|
981
|
+
let i = m.index + m[0].length;
|
|
982
|
+
const scanEnd = Math.min(code.length, i + MAX_BLOCK_SCAN_LEN);
|
|
983
|
+
let block = "";
|
|
984
|
+
while (i < scanEnd && depth > 0) {
|
|
985
|
+
const ch = code[i];
|
|
986
|
+
if (ch === "(") depth++;
|
|
987
|
+
else if (ch === ")") {
|
|
988
|
+
if (--depth === 0) break;
|
|
989
|
+
}
|
|
990
|
+
block += ch;
|
|
991
|
+
i++;
|
|
992
|
+
}
|
|
993
|
+
classComposerCallRe.lastIndex = i + 1;
|
|
994
|
+
if (depth === 0) pushClassLikeStrings(block, found);
|
|
995
|
+
}
|
|
996
|
+
const templateRe = /`([^`]{1,2000})`/g;
|
|
997
|
+
while ((m = templateRe.exec(code)) !== null) pushTemplateLiteralBody(m[1], found);
|
|
998
|
+
return [...found];
|
|
999
|
+
}
|
|
1000
|
+
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "dist", "build", "out", ".next", ".output", ".git", ".svn", ".cache", "coverage"]);
|
|
1001
|
+
var MAX_SCAN_DEPTH = 10;
|
|
1002
|
+
var DEFAULT_FILE_MATCH = /\.(tsx?|jsx?)$/;
|
|
1003
|
+
function scanDir(dir, onFile, depth = 0, fileMatch = DEFAULT_FILE_MATCH) {
|
|
1004
|
+
if (depth > MAX_SCAN_DEPTH) return;
|
|
1005
|
+
let entries;
|
|
1006
|
+
try {
|
|
1007
|
+
entries = (0, import_fs.readdirSync)(dir);
|
|
1008
|
+
} catch {
|
|
1009
|
+
return;
|
|
1010
|
+
}
|
|
1011
|
+
for (const entry of entries) {
|
|
1012
|
+
if (entry.startsWith(".") || SKIP_DIRS.has(entry)) continue;
|
|
1013
|
+
const full = (0, import_path.join)(dir, entry);
|
|
1014
|
+
try {
|
|
1015
|
+
const st = (0, import_fs.statSync)(full);
|
|
1016
|
+
if (st.isDirectory()) scanDir(full, onFile, depth + 1, fileMatch);
|
|
1017
|
+
else if (fileMatch.test(entry)) onFile(full, (0, import_fs.readFileSync)(full, "utf-8"));
|
|
1018
|
+
} catch {
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
// src/vite-plugin/unknownClassWarnings.ts
|
|
1024
|
+
var import_path2 = require("path");
|
|
1025
|
+
|
|
1026
|
+
// src/terminalWarn.ts
|
|
1027
|
+
var useColor = !!process.stdout?.isTTY && !process.env.NO_COLOR;
|
|
1028
|
+
var paint = (code, s) => useColor ? `\x1B[${code}m${s}\x1B[0m` : s;
|
|
1029
|
+
var green = (s) => paint("32", s);
|
|
1030
|
+
var blue = (s) => paint("34", s);
|
|
1031
|
+
var white = (s) => paint("97", s);
|
|
1032
|
+
var gray = (s) => paint("90", s);
|
|
1033
|
+
var bold = (s) => paint("1", s);
|
|
1034
|
+
var highlight = (s) => bold(white(s));
|
|
1035
|
+
function kbachTag() {
|
|
1036
|
+
return `${green("\u2192")} ${bold(green("[Kbach]"))}`;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
// src/vite-plugin/unknownClassWarnings.ts
|
|
1040
|
+
var CSS_CLASS_SELECTOR_RE = /\.(-?[a-zA-Z_][a-zA-Z0-9_-]*)/g;
|
|
1041
|
+
var CSS_FILE_RE = /\.(css|scss|sass|less)$/;
|
|
1042
|
+
function findLineCol(code, needle) {
|
|
1043
|
+
const index = code.indexOf(needle);
|
|
1044
|
+
if (index === -1) return null;
|
|
1045
|
+
let line = 1;
|
|
1046
|
+
let lastNewline = -1;
|
|
1047
|
+
for (let i = 0; i < index; i++) {
|
|
1048
|
+
if (code.charCodeAt(i) === 10) {
|
|
1049
|
+
line++;
|
|
1050
|
+
lastNewline = i;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
return { line, column: index - lastNewline };
|
|
1054
|
+
}
|
|
1055
|
+
function scanCssFileInto(code, into) {
|
|
1056
|
+
const re = new RegExp(CSS_CLASS_SELECTOR_RE.source, "g");
|
|
1057
|
+
let m;
|
|
1058
|
+
while ((m = re.exec(code)) !== null) into.add(m[1]);
|
|
1059
|
+
}
|
|
1060
|
+
function scanProjectCssSelectors(root, includeDirs) {
|
|
1061
|
+
const projectCssClasses = /* @__PURE__ */ new Set();
|
|
1062
|
+
for (const dir of includeDirs) {
|
|
1063
|
+
scanDir((0, import_path2.join)(root, dir), (_filePath, code) => scanCssFileInto(code, projectCssClasses), 0, CSS_FILE_RE);
|
|
1064
|
+
}
|
|
1065
|
+
return projectCssClasses;
|
|
1066
|
+
}
|
|
1067
|
+
function stripModifierPrefix(token) {
|
|
1068
|
+
return token.replace(/^(?:[a-zA-Z0-9_/-]+:)+/, "");
|
|
1069
|
+
}
|
|
1070
|
+
var MARKER_CLASSES = /* @__PURE__ */ new Set(["group", "peer"]);
|
|
1071
|
+
function isMarkerClass(base) {
|
|
1072
|
+
if (MARKER_CLASSES.has(base)) return true;
|
|
1073
|
+
const slashIdx = base.lastIndexOf("/");
|
|
1074
|
+
if (slashIdx === -1) return false;
|
|
1075
|
+
return MARKER_CLASSES.has(base.slice(0, slashIdx)) && slashIdx < base.length - 1;
|
|
1076
|
+
}
|
|
1077
|
+
function warnIfUnknownClass(token, filePath, code, isResolvable, projectCssClasses, warnedTokens) {
|
|
1078
|
+
if (isResolvable || warnedTokens.has(token)) return;
|
|
1079
|
+
const base = stripModifierPrefix(token);
|
|
1080
|
+
if (!base || projectCssClasses.has(base) || isMarkerClass(base)) return;
|
|
1081
|
+
warnedTokens.add(token);
|
|
1082
|
+
const pos = findLineCol(code, token);
|
|
1083
|
+
const location = pos ? `${blue(filePath)}${green(`:${pos.line}:${pos.column}`)}` : blue(filePath);
|
|
1084
|
+
console.warn(
|
|
1085
|
+
`${kbachTag()} ${gray("Unknown class")} ${highlight(token)} ${gray("\u2014 no Kbach utility or project CSS rule matches it. Typo?")}
|
|
1086
|
+
${bold("at")} ${location}`
|
|
1087
|
+
);
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
// src/staticCss/engine.ts
|
|
1091
|
+
function normPath(p) {
|
|
1092
|
+
const fwd = p.replace(/\\/g, "/");
|
|
1093
|
+
return process.platform === "win32" ? fwd.toLowerCase() : fwd;
|
|
1094
|
+
}
|
|
1095
|
+
var SAFELIST_KEY = "\0kbach-safelist";
|
|
1096
|
+
function createKbachStaticCssEngine(options) {
|
|
1097
|
+
const { root, theme, themeJson, includeDirs, safelist } = options;
|
|
1587
1098
|
const fileTokens = /* @__PURE__ */ new Map();
|
|
1588
1099
|
const tokenRules = /* @__PURE__ */ new Map();
|
|
1589
1100
|
const fileTags = /* @__PURE__ */ new Map();
|
|
@@ -1607,6 +1118,10 @@ function kbach(options = {}) {
|
|
|
1607
1118
|
fileTokens.set(normPath(filePath), tokens);
|
|
1608
1119
|
fileTags.set(normPath(filePath), scanUsedTags(code));
|
|
1609
1120
|
}
|
|
1121
|
+
function removeFile(filePath) {
|
|
1122
|
+
fileTokens.delete(normPath(filePath));
|
|
1123
|
+
fileTags.delete(normPath(filePath));
|
|
1124
|
+
}
|
|
1610
1125
|
function processSafelist() {
|
|
1611
1126
|
if (safelist.length === 0) return;
|
|
1612
1127
|
const tokens = new Set(safelist);
|
|
@@ -1630,50 +1145,121 @@ function kbach(options = {}) {
|
|
|
1630
1145
|
const rules = tokenRules.get(tok);
|
|
1631
1146
|
if (rules) view.set(tok, rules);
|
|
1632
1147
|
}
|
|
1633
|
-
return formatKbachCSS(view, theme, activeTags());
|
|
1634
|
-
}
|
|
1635
|
-
function mainCSSFile() {
|
|
1636
|
-
return (0, import_path3.join)(root, "src", "kbach.css");
|
|
1637
|
-
}
|
|
1638
|
-
function classNameHintsFile() {
|
|
1639
|
-
return (0, import_path3.join)(root, ".kbach", "kbach-classnames.d.ts");
|
|
1640
|
-
}
|
|
1641
|
-
function writeClassNameHints() {
|
|
1642
|
-
const dts = buildClassNameHintsDts(buildClassTokens(theme));
|
|
1643
|
-
writeFileEnsuringDir(classNameHintsFile(), dts);
|
|
1644
|
-
}
|
|
1645
|
-
function syncMainCSSFile(server) {
|
|
1646
|
-
const active = activeTokens();
|
|
1647
1148
|
for (const tok of tokenRules.keys()) {
|
|
1648
1149
|
if (!active.has(tok)) tokenRules.delete(tok);
|
|
1649
1150
|
}
|
|
1650
|
-
|
|
1651
|
-
if (changed && server) server.watcher.emit("change", mainCSSFile());
|
|
1151
|
+
return formatKbachCSS(view, theme, activeTags());
|
|
1652
1152
|
}
|
|
1653
1153
|
function initialScan() {
|
|
1654
1154
|
for (const dir of includeDirs) {
|
|
1655
1155
|
scanDir((0, import_path3.join)(root, dir), processFile);
|
|
1656
1156
|
}
|
|
1657
1157
|
}
|
|
1158
|
+
function scanProjectCssSelectorsOnce() {
|
|
1159
|
+
projectCssClasses = scanProjectCssSelectors(root, includeDirs);
|
|
1160
|
+
}
|
|
1161
|
+
return { processFile, removeFile, initialScan, processSafelist, generateCSS, scanProjectCssSelectorsOnce };
|
|
1162
|
+
}
|
|
1163
|
+
function readSourceFile(path) {
|
|
1164
|
+
return (0, import_fs2.readFileSync)(path, "utf-8");
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
// src/vite-plugin/index.ts
|
|
1168
|
+
function findMainCSSFile(root, includeDirs, explicitCssFile) {
|
|
1169
|
+
if (explicitCssFile) return (0, import_path4.join)(root, explicitCssFile);
|
|
1170
|
+
const searchDirs = [...includeDirs, "."];
|
|
1171
|
+
for (const dir of searchDirs) {
|
|
1172
|
+
const candidate = (0, import_path4.join)(root, dir, "kbach.css");
|
|
1173
|
+
if (!(0, import_fs3.existsSync)(candidate)) continue;
|
|
1174
|
+
try {
|
|
1175
|
+
const content = (0, import_fs3.readFileSync)(candidate, "utf-8");
|
|
1176
|
+
if (content.includes(KBACH_START) && content.includes(KBACH_END)) return candidate;
|
|
1177
|
+
} catch {
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
for (const dir of includeDirs) {
|
|
1181
|
+
const full = (0, import_path4.join)(root, dir);
|
|
1182
|
+
try {
|
|
1183
|
+
if ((0, import_fs3.statSync)(full).isDirectory()) return (0, import_path4.join)(full, "kbach.css");
|
|
1184
|
+
} catch {
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
return (0, import_path4.join)(root, includeDirs[0] ?? "src", "kbach.css");
|
|
1188
|
+
}
|
|
1189
|
+
var DEFAULT_SCAN_DIRS = ["src", "app", "pages", "components"];
|
|
1190
|
+
var CSS_SYNC_DEBOUNCE_MS = 50;
|
|
1191
|
+
function writeFileEnsuringDir(path, content) {
|
|
1192
|
+
(0, import_fs3.mkdirSync)((0, import_path4.dirname)(path), { recursive: true });
|
|
1193
|
+
(0, import_fs3.writeFileSync)(path, content, "utf-8");
|
|
1194
|
+
}
|
|
1195
|
+
function isEsmRequireFailure(err) {
|
|
1196
|
+
if (!(err instanceof Error)) return false;
|
|
1197
|
+
return err.code === "ERR_REQUIRE_ESM" || /is not defined in ES module scope/.test(err.message);
|
|
1198
|
+
}
|
|
1199
|
+
async function importConfigModule(path) {
|
|
1200
|
+
const mod = await import((0, import_url.pathToFileURL)(path).href);
|
|
1201
|
+
return mod.default ?? mod;
|
|
1202
|
+
}
|
|
1203
|
+
function requireConfigModule(root, path) {
|
|
1204
|
+
const mod = (0, import_module.createRequire)(root)(path);
|
|
1205
|
+
return mod.default ?? mod;
|
|
1206
|
+
}
|
|
1207
|
+
async function loadConfigFile(root) {
|
|
1208
|
+
const cjsPath = (0, import_path4.join)(root, "kbach.config.cjs");
|
|
1209
|
+
if ((0, import_fs3.existsSync)(cjsPath)) return requireConfigModule(root, cjsPath);
|
|
1210
|
+
const mjsPath = (0, import_path4.join)(root, "kbach.config.mjs");
|
|
1211
|
+
if ((0, import_fs3.existsSync)(mjsPath)) return importConfigModule(mjsPath);
|
|
1212
|
+
const jsPath = (0, import_path4.join)(root, "kbach.config.js");
|
|
1213
|
+
if (!(0, import_fs3.existsSync)(jsPath)) return void 0;
|
|
1214
|
+
try {
|
|
1215
|
+
return requireConfigModule(root, jsPath);
|
|
1216
|
+
} catch (err) {
|
|
1217
|
+
if (!isEsmRequireFailure(err)) throw err;
|
|
1218
|
+
return importConfigModule(jsPath);
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
async function resolveEffectiveTheme(root, options) {
|
|
1222
|
+
if (options.theme) return options.theme;
|
|
1223
|
+
if (options.config) return resolveKbachConfig(options.config);
|
|
1224
|
+
const discovered = await loadConfigFile(root);
|
|
1225
|
+
return discovered ? resolveKbachConfig(discovered) : defaultTheme;
|
|
1226
|
+
}
|
|
1227
|
+
function kbach(options = {}) {
|
|
1228
|
+
const includeDirs = options.include ?? DEFAULT_SCAN_DIRS;
|
|
1229
|
+
const safelist = options.safelist ?? [];
|
|
1230
|
+
let root = process.cwd();
|
|
1231
|
+
let theme = defaultTheme;
|
|
1232
|
+
let engine = createKbachStaticCssEngine({ root, theme, themeJson: JSON.stringify(theme), includeDirs, safelist });
|
|
1233
|
+
let mainCSSFilePath = (0, import_path4.join)(root, "src", "kbach.css");
|
|
1234
|
+
function mainCSSFile() {
|
|
1235
|
+
return mainCSSFilePath;
|
|
1236
|
+
}
|
|
1237
|
+
function syncMainCSSFile(server) {
|
|
1238
|
+
const changed = writeKbachToFile(mainCSSFile(), engine.generateCSS(), readSourceFile, writeFileEnsuringDir);
|
|
1239
|
+
if (changed && server) server.watcher.emit("change", mainCSSFile());
|
|
1240
|
+
}
|
|
1241
|
+
let syncTimer = null;
|
|
1242
|
+
function scheduleSync(server) {
|
|
1243
|
+
if (syncTimer) clearTimeout(syncTimer);
|
|
1244
|
+
syncTimer = setTimeout(() => {
|
|
1245
|
+
syncTimer = null;
|
|
1246
|
+
syncMainCSSFile(server);
|
|
1247
|
+
}, CSS_SYNC_DEBOUNCE_MS);
|
|
1248
|
+
}
|
|
1658
1249
|
return {
|
|
1659
1250
|
name: "kbach",
|
|
1660
1251
|
enforce: "pre",
|
|
1661
|
-
configResolved(resolved) {
|
|
1252
|
+
async configResolved(resolved) {
|
|
1662
1253
|
root = resolved.root;
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
theme = resolveKbachConfig(discovered);
|
|
1667
|
-
themeJson = JSON.stringify(theme);
|
|
1668
|
-
}
|
|
1669
|
-
}
|
|
1254
|
+
theme = await resolveEffectiveTheme(root, options);
|
|
1255
|
+
engine = createKbachStaticCssEngine({ root, theme, themeJson: JSON.stringify(theme), includeDirs, safelist });
|
|
1256
|
+
mainCSSFilePath = findMainCSSFile(root, includeDirs, options.cssFile);
|
|
1670
1257
|
},
|
|
1671
1258
|
buildStart() {
|
|
1672
|
-
|
|
1673
|
-
initialScan();
|
|
1674
|
-
processSafelist();
|
|
1675
|
-
writeKbachToFile(mainCSSFile(), generateCSS(),
|
|
1676
|
-
writeClassNameHints();
|
|
1259
|
+
engine.scanProjectCssSelectorsOnce();
|
|
1260
|
+
engine.initialScan();
|
|
1261
|
+
engine.processSafelist();
|
|
1262
|
+
writeKbachToFile(mainCSSFile(), engine.generateCSS(), readSourceFile, writeFileEnsuringDir);
|
|
1677
1263
|
},
|
|
1678
1264
|
// handleHotUpdate covers edits; add/unlink (create/delete) land on the
|
|
1679
1265
|
// raw watcher instead — Vite's handleHotUpdate hook only fires for
|
|
@@ -1683,17 +1269,15 @@ function kbach(options = {}) {
|
|
|
1683
1269
|
if (file.includes("node_modules")) return;
|
|
1684
1270
|
if (!/\.(tsx?|jsx?)$/.test(file)) return;
|
|
1685
1271
|
if (isUnlink) {
|
|
1686
|
-
|
|
1687
|
-
fileTags.delete(normPath(file));
|
|
1272
|
+
engine.removeFile(file);
|
|
1688
1273
|
} else {
|
|
1689
1274
|
try {
|
|
1690
|
-
processFile(file,
|
|
1275
|
+
engine.processFile(file, readSourceFile(file));
|
|
1691
1276
|
} catch {
|
|
1692
|
-
|
|
1693
|
-
fileTags.delete(normPath(file));
|
|
1277
|
+
engine.removeFile(file);
|
|
1694
1278
|
}
|
|
1695
1279
|
}
|
|
1696
|
-
|
|
1280
|
+
scheduleSync(server);
|
|
1697
1281
|
};
|
|
1698
1282
|
server.watcher.on("add", (file) => onAddOrUnlink(file, false));
|
|
1699
1283
|
server.watcher.on("unlink", (file) => onAddOrUnlink(file, true));
|
|
@@ -1702,16 +1286,20 @@ function kbach(options = {}) {
|
|
|
1702
1286
|
if (file.includes("node_modules")) return;
|
|
1703
1287
|
if (!/\.(tsx?|jsx?)$/.test(file)) return;
|
|
1704
1288
|
try {
|
|
1705
|
-
processFile(file,
|
|
1289
|
+
engine.processFile(file, readSourceFile(file));
|
|
1706
1290
|
} catch {
|
|
1707
|
-
|
|
1708
|
-
fileTags.delete(normPath(file));
|
|
1291
|
+
engine.removeFile(file);
|
|
1709
1292
|
}
|
|
1710
|
-
|
|
1293
|
+
scheduleSync(server);
|
|
1711
1294
|
}
|
|
1712
1295
|
};
|
|
1713
1296
|
}
|
|
1714
1297
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1715
1298
|
0 && (module.exports = {
|
|
1716
|
-
|
|
1299
|
+
CSS_SYNC_DEBOUNCE_MS,
|
|
1300
|
+
DEFAULT_SCAN_DIRS,
|
|
1301
|
+
findMainCSSFile,
|
|
1302
|
+
kbach,
|
|
1303
|
+
loadConfigFile,
|
|
1304
|
+
resolveEffectiveTheme
|
|
1717
1305
|
});
|