@kbach/react 0.6.35 → 0.6.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-Y6JF3TZM.mjs → chunk-OUKVG4DI.mjs} +1 -1
- package/dist/{chunk-O7GFDFVJ.mjs → chunk-ZTDE7V7I.mjs} +84 -18
- package/dist/core/index.d.ts +28 -1
- package/dist/core/index.js +85 -18
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -0
- package/dist/index.mjs +3 -1
- package/dist/jsx-dev-runtime.mjs +2 -2
- package/dist/jsx-runtime.mjs +2 -2
- package/dist/vite-plugin.js +109 -18
- package/dist/vite-plugin.mjs +110 -19
- package/kbach-react.md +14 -5
- package/package.json +1 -1
|
@@ -2203,10 +2203,6 @@ function expandModeAwareColorClasses(classString, colors) {
|
|
|
2203
2203
|
out.push(token);
|
|
2204
2204
|
continue;
|
|
2205
2205
|
}
|
|
2206
|
-
if (parsed.modifiers.includes("dark") || parsed.modifiers.includes("light")) {
|
|
2207
|
-
out.push(token);
|
|
2208
|
-
continue;
|
|
2209
|
-
}
|
|
2210
2206
|
const slashIdx = parsed.value.indexOf("/");
|
|
2211
2207
|
const colorPart = slashIdx > 0 ? parsed.value.slice(0, slashIdx) : parsed.value;
|
|
2212
2208
|
const opacitySuffix = slashIdx > 0 ? parsed.value.slice(slashIdx) : "";
|
|
@@ -2218,6 +2214,12 @@ function expandModeAwareColorClasses(classString, colors) {
|
|
|
2218
2214
|
changed = true;
|
|
2219
2215
|
const bang = parsed.important ? "!" : "";
|
|
2220
2216
|
const modPrefix = parsed.modifiers.map((m) => `${m}:`).join("");
|
|
2217
|
+
const explicitScheme = parsed.modifiers.map((m) => getModifier(m)?.darkScheme).find((s) => s);
|
|
2218
|
+
if (explicitScheme) {
|
|
2219
|
+
const side = explicitScheme === "dark" ? pair.dark : pair.light;
|
|
2220
|
+
out.push(`${bang}${modPrefix}${parsed.utility}-[${side}]${opacitySuffix}`);
|
|
2221
|
+
continue;
|
|
2222
|
+
}
|
|
2221
2223
|
out.push(`${bang}${modPrefix}${parsed.utility}-[${pair.light}]${opacitySuffix}`);
|
|
2222
2224
|
out.push(`${bang}dark:${modPrefix}${parsed.utility}-[${pair.dark}]${opacitySuffix}`);
|
|
2223
2225
|
}
|
|
@@ -2773,6 +2775,48 @@ var defaultTheme = {
|
|
|
2773
2775
|
animation: {}
|
|
2774
2776
|
};
|
|
2775
2777
|
|
|
2778
|
+
// src/core/generateTypesDts.ts
|
|
2779
|
+
var HEADER = `// AUTO-GENERATED by Kbach from your kbach.config.js \u2014 do not edit by hand.
|
|
2780
|
+
// Regenerated automatically every time your dev server / Metro picks up a
|
|
2781
|
+
// change to that file. Safe (and recommended) to add to .gitignore.
|
|
2782
|
+
//
|
|
2783
|
+
// Gives useColors()/useSpacing() full autocomplete and typo-catching for your
|
|
2784
|
+
// custom colors/spacing keys with zero manual setup \u2014 see KbachCustomColors'
|
|
2785
|
+
// doc comment in @kbach/react if you'd rather hand-author this instead.
|
|
2786
|
+
import '@kbach/react';
|
|
2787
|
+
`;
|
|
2788
|
+
var IDENT_RE = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
2789
|
+
function propKey(name) {
|
|
2790
|
+
return IDENT_RE.test(name) ? name : JSON.stringify(name);
|
|
2791
|
+
}
|
|
2792
|
+
function generateKbachTypesDts(theme) {
|
|
2793
|
+
const colorLines = [];
|
|
2794
|
+
for (const [name, value] of Object.entries(theme.colors)) {
|
|
2795
|
+
if (name in defaultColors) continue;
|
|
2796
|
+
const isFlat = typeof value === "string" || isModeAwareColor(value);
|
|
2797
|
+
colorLines.push(` ${propKey(name)}: ${isFlat ? "string" : "ColorScale"};`);
|
|
2798
|
+
}
|
|
2799
|
+
const spacingLines = [];
|
|
2800
|
+
for (const key of Object.keys(theme.spacing)) {
|
|
2801
|
+
if (key in defaultTheme.spacing) continue;
|
|
2802
|
+
spacingLines.push(` ${propKey(key)}: true;`);
|
|
2803
|
+
}
|
|
2804
|
+
if (colorLines.length === 0 && spacingLines.length === 0) return "";
|
|
2805
|
+
const body = [
|
|
2806
|
+
colorLines.length > 0 ? ` interface KbachCustomColors {
|
|
2807
|
+
${colorLines.join("\n")}
|
|
2808
|
+
}` : null,
|
|
2809
|
+
spacingLines.length > 0 ? ` interface KbachCustomSpacing {
|
|
2810
|
+
${spacingLines.join("\n")}
|
|
2811
|
+
}` : null
|
|
2812
|
+
].filter((s) => s !== null).join("\n\n");
|
|
2813
|
+
return `${HEADER}
|
|
2814
|
+
declare module '@kbach/react' {
|
|
2815
|
+
${body}
|
|
2816
|
+
}
|
|
2817
|
+
`;
|
|
2818
|
+
}
|
|
2819
|
+
|
|
2776
2820
|
// src/core/reset.ts
|
|
2777
2821
|
var RESET_STYLE_ID = "kbach-reset";
|
|
2778
2822
|
var BASE_RESET = [
|
|
@@ -3225,30 +3269,51 @@ function getConfig() {
|
|
|
3225
3269
|
configStore.resolved = buildConfig({});
|
|
3226
3270
|
return configStore.resolved;
|
|
3227
3271
|
}
|
|
3228
|
-
function resolveOneRef(ref, colors) {
|
|
3229
|
-
const lastDash = ref.lastIndexOf("-");
|
|
3230
|
-
if (lastDash <= 0) return null;
|
|
3231
|
-
const name = ref.slice(0, lastDash);
|
|
3232
|
-
const shade = ref.slice(lastDash + 1);
|
|
3233
|
-
if (!/^\d+$/.test(shade)) return null;
|
|
3234
|
-
const entry = colors[name];
|
|
3235
|
-
if (!entry || typeof entry !== "object" || isModeAwareColor(entry)) return null;
|
|
3236
|
-
const target = entry[shade];
|
|
3237
|
-
return typeof target === "string" ? target : null;
|
|
3238
|
-
}
|
|
3239
3272
|
function resolveColorRefs(colors) {
|
|
3240
3273
|
const MAX_DEPTH = 5;
|
|
3241
|
-
function resolveChain(raw) {
|
|
3274
|
+
function resolveChain(raw, side) {
|
|
3242
3275
|
let current = raw;
|
|
3243
3276
|
for (let i = 0; i < MAX_DEPTH; i++) {
|
|
3244
|
-
const next = resolveOneRef(current,
|
|
3277
|
+
const next = resolveOneRef(current, side);
|
|
3245
3278
|
if (!next || next === current) break;
|
|
3246
3279
|
current = next;
|
|
3247
3280
|
}
|
|
3248
3281
|
return current;
|
|
3249
3282
|
}
|
|
3283
|
+
function resolveOneRef(ref, side) {
|
|
3284
|
+
const slashIdx = ref.indexOf("/");
|
|
3285
|
+
if (slashIdx > 0) {
|
|
3286
|
+
const baseName = ref.slice(0, slashIdx);
|
|
3287
|
+
const opacity = Number(ref.slice(slashIdx + 1));
|
|
3288
|
+
if (!Number.isFinite(opacity)) return null;
|
|
3289
|
+
let baseRef;
|
|
3290
|
+
const entry2 = colors[baseName];
|
|
3291
|
+
if (typeof entry2 === "string") {
|
|
3292
|
+
baseRef = entry2;
|
|
3293
|
+
} else if (isModeAwareColor(entry2)) {
|
|
3294
|
+
if (!side) return null;
|
|
3295
|
+
baseRef = entry2[side];
|
|
3296
|
+
} else if (entry2 && typeof entry2 === "object" && "6" in entry2) {
|
|
3297
|
+
const v = entry2["6"];
|
|
3298
|
+
baseRef = typeof v === "string" ? v : void 0;
|
|
3299
|
+
}
|
|
3300
|
+
if (baseRef === void 0) return null;
|
|
3301
|
+
const baseHex = resolveChain(baseRef, side);
|
|
3302
|
+
const a = opacity > 1 ? opacity / 100 : opacity;
|
|
3303
|
+
return hexToRgba(baseHex, a);
|
|
3304
|
+
}
|
|
3305
|
+
const lastDash = ref.lastIndexOf("-");
|
|
3306
|
+
if (lastDash <= 0) return null;
|
|
3307
|
+
const name = ref.slice(0, lastDash);
|
|
3308
|
+
const shade = ref.slice(lastDash + 1);
|
|
3309
|
+
if (!/^\d+$/.test(shade)) return null;
|
|
3310
|
+
const entry = colors[name];
|
|
3311
|
+
if (!entry || typeof entry !== "object" || isModeAwareColor(entry)) return null;
|
|
3312
|
+
const target = entry[shade];
|
|
3313
|
+
return typeof target === "string" ? target : null;
|
|
3314
|
+
}
|
|
3250
3315
|
function resolveValue(val) {
|
|
3251
|
-
return typeof val === "string" ? resolveChain(val) : { light: resolveChain(val.light), dark: resolveChain(val.dark) };
|
|
3316
|
+
return typeof val === "string" ? resolveChain(val, null) : { light: resolveChain(val.light, "light"), dark: resolveChain(val.dark, "dark") };
|
|
3252
3317
|
}
|
|
3253
3318
|
const out = {};
|
|
3254
3319
|
for (const [key, val] of Object.entries(colors)) {
|
|
@@ -3941,6 +4006,7 @@ export {
|
|
|
3941
4006
|
expandModeAwareColorClasses,
|
|
3942
4007
|
defaultColors,
|
|
3943
4008
|
defaultTheme,
|
|
4009
|
+
generateKbachTypesDts,
|
|
3944
4010
|
RESET_STYLE_ID,
|
|
3945
4011
|
BASE_RESET,
|
|
3946
4012
|
syncGlobalWidth,
|
package/dist/core/index.d.ts
CHANGED
|
@@ -190,6 +190,20 @@ declare function isModeAwareColor(v: unknown): v is {
|
|
|
190
190
|
* normal parsing — e.g. `bg-surface` becomes `bg-[#ffffff] dark:bg-[#111827]`.
|
|
191
191
|
* `bg-surface/50` becomes `bg-[#ffffff]/50 dark:bg-[#111827]/50` (the arbitrary-
|
|
192
192
|
* color-plus-opacity composition already resolveColor() already supports).
|
|
193
|
+
* `hover:bg-surface` becomes `hover:bg-[#ffffff] dark:hover:bg-[#111827]` —
|
|
194
|
+
* every other modifier already present on the token carries through onto
|
|
195
|
+
* both halves of the pair unchanged.
|
|
196
|
+
*
|
|
197
|
+
* A token that ALREADY carries an explicit dark:/light:/not-dark:/not-light:
|
|
198
|
+
* modifier (someone writes `dark:hover:bg-primary` on a `primary` that's
|
|
199
|
+
* already mode-aware, usually out of habit from before it was) isn't split
|
|
200
|
+
* into a pair — that would be redundant on top of an already-explicit
|
|
201
|
+
* choice. Instead the matching side is substituted in place and every
|
|
202
|
+
* modifier, including the dark:/light: itself, is left exactly as written,
|
|
203
|
+
* so `dark:hover:bg-primary` still only applies in dark mode, using the
|
|
204
|
+
* dark side (not the resolveColor()-level fallback's light side, which is
|
|
205
|
+
* only ever reached by a mode-aware pair that skipped this expansion
|
|
206
|
+
* entirely — not a path normal className resolution takes).
|
|
193
207
|
*
|
|
194
208
|
* Runs once, upfront, purely as a string rewrite — everything downstream
|
|
195
209
|
* (CSS generation, native bucketing/flatten(), the existing dark: reactivity
|
|
@@ -200,6 +214,19 @@ declare function isModeAwareColor(v: unknown): v is {
|
|
|
200
214
|
*/
|
|
201
215
|
declare function expandModeAwareColorClasses(classString: string, colors: ThemeColors): string;
|
|
202
216
|
|
|
217
|
+
/**
|
|
218
|
+
* Generates the KbachCustomColors/KbachCustomSpacing module-augmentation
|
|
219
|
+
* source for every color/spacing key `extend.theme` added beyond the built-in
|
|
220
|
+
* defaults. Called by both the Vite plugin and @kbach/native's Babel plugin —
|
|
221
|
+
* kept here, shared, so "which colors count as custom" and "flat string vs.
|
|
222
|
+
* ColorScale" can't drift between the two.
|
|
223
|
+
*
|
|
224
|
+
* Returns '' (nothing to write) when the theme adds no custom colors or
|
|
225
|
+
* spacing keys at all, so callers can skip writing/deleting a file for the
|
|
226
|
+
* common case of a project still on the stock theme.
|
|
227
|
+
*/
|
|
228
|
+
declare function generateKbachTypesDts(theme: ThemeConfig): string;
|
|
229
|
+
|
|
203
230
|
declare const defaultColors: {
|
|
204
231
|
transparent: string;
|
|
205
232
|
current: string;
|
|
@@ -1308,4 +1335,4 @@ declare function subscribeGlobalWidth(listener: WidthListener): () => void;
|
|
|
1308
1335
|
*/
|
|
1309
1336
|
declare function getActiveBreakpoints(width?: number, screens?: Record<string, number>): Set<string>;
|
|
1310
1337
|
|
|
1311
|
-
export { BASE_RESET, type ColorShades, type ColorValue, type DarkMode, type DefaultColorName, type DefaultSpacingKey, type FrameworkConfig, LRUCache, type ParsedClass, type Platform, type PluginAPI, RESET_STYLE_ID, type ResolvedConfig, type ResolvedStyle, type StyleValue, type ThemeColors, type ThemeConfig, type ThemeMode, type ThemeSpacing, buildConfig, clearCache, clearPluginModifiers, customVariants, defaultColors, defaultTheme, disableRuntimeCSS, escapeCSSSelector, expandModeAwareColorClasses, flatten, generateClassCSS, getActiveBreakpoints, getAllModifierNames, getBuiltinStandaloneNames, getBuiltinUtilityPrefixes, getConfig, getDefaultFontFamily, getEffectiveIsWeb, getGlobalDarkMode, getGlobalScreens, getGlobalWidth, getInteractiveModifiers, getModeModifiers, getModifier, getResponsiveModifiers, initConfig, isKnownModifier, isKnownUtility, isModeAwareColor, isNative, isRuntimeCSSDisabled, isWeb, kbachWarn, matchModifier, normalizeClassString, onConfigChange, parseClass, parseClasses, parseHexRgb, registerModifier, resetConfig, resolve, resolveColor, resolveSizing, resolveSpacing, resolveUtility, setDefaultFontFamily, setGlobalDarkMode, setGlobalWidth, setResolveTarget, splitClassTokens, subscribeGlobalDarkMode, subscribeGlobalWidth, syncGlobalDarkMode, syncGlobalScreens, syncGlobalWidth, toNativeValue, updateConfig };
|
|
1338
|
+
export { BASE_RESET, type ColorShades, type ColorValue, type DarkMode, type DefaultColorName, type DefaultSpacingKey, type FrameworkConfig, LRUCache, type ParsedClass, type Platform, type PluginAPI, RESET_STYLE_ID, type ResolvedConfig, type ResolvedStyle, type StyleValue, type ThemeColors, type ThemeConfig, type ThemeMode, type ThemeSpacing, buildConfig, clearCache, clearPluginModifiers, customVariants, defaultColors, defaultTheme, disableRuntimeCSS, escapeCSSSelector, expandModeAwareColorClasses, flatten, generateClassCSS, generateKbachTypesDts, getActiveBreakpoints, getAllModifierNames, getBuiltinStandaloneNames, getBuiltinUtilityPrefixes, getConfig, getDefaultFontFamily, getEffectiveIsWeb, getGlobalDarkMode, getGlobalScreens, getGlobalWidth, getInteractiveModifiers, getModeModifiers, getModifier, getResponsiveModifiers, initConfig, isKnownModifier, isKnownUtility, isModeAwareColor, isNative, isRuntimeCSSDisabled, isWeb, kbachWarn, matchModifier, normalizeClassString, onConfigChange, parseClass, parseClasses, parseHexRgb, registerModifier, resetConfig, resolve, resolveColor, resolveSizing, resolveSpacing, resolveUtility, setDefaultFontFamily, setGlobalDarkMode, setGlobalWidth, setResolveTarget, splitClassTokens, subscribeGlobalDarkMode, subscribeGlobalWidth, syncGlobalDarkMode, syncGlobalScreens, syncGlobalWidth, toNativeValue, updateConfig };
|
package/dist/core/index.js
CHANGED
|
@@ -34,6 +34,7 @@ __export(index_exports, {
|
|
|
34
34
|
expandModeAwareColorClasses: () => expandModeAwareColorClasses,
|
|
35
35
|
flatten: () => flatten,
|
|
36
36
|
generateClassCSS: () => generateClassCSS,
|
|
37
|
+
generateKbachTypesDts: () => generateKbachTypesDts,
|
|
37
38
|
getActiveBreakpoints: () => getActiveBreakpoints,
|
|
38
39
|
getAllModifierNames: () => getAllModifierNames,
|
|
39
40
|
getBuiltinStandaloneNames: () => getBuiltinStandaloneNames,
|
|
@@ -2291,10 +2292,6 @@ function expandModeAwareColorClasses(classString, colors) {
|
|
|
2291
2292
|
out.push(token);
|
|
2292
2293
|
continue;
|
|
2293
2294
|
}
|
|
2294
|
-
if (parsed.modifiers.includes("dark") || parsed.modifiers.includes("light")) {
|
|
2295
|
-
out.push(token);
|
|
2296
|
-
continue;
|
|
2297
|
-
}
|
|
2298
2295
|
const slashIdx = parsed.value.indexOf("/");
|
|
2299
2296
|
const colorPart = slashIdx > 0 ? parsed.value.slice(0, slashIdx) : parsed.value;
|
|
2300
2297
|
const opacitySuffix = slashIdx > 0 ? parsed.value.slice(slashIdx) : "";
|
|
@@ -2306,6 +2303,12 @@ function expandModeAwareColorClasses(classString, colors) {
|
|
|
2306
2303
|
changed = true;
|
|
2307
2304
|
const bang = parsed.important ? "!" : "";
|
|
2308
2305
|
const modPrefix = parsed.modifiers.map((m) => `${m}:`).join("");
|
|
2306
|
+
const explicitScheme = parsed.modifiers.map((m) => getModifier(m)?.darkScheme).find((s) => s);
|
|
2307
|
+
if (explicitScheme) {
|
|
2308
|
+
const side = explicitScheme === "dark" ? pair.dark : pair.light;
|
|
2309
|
+
out.push(`${bang}${modPrefix}${parsed.utility}-[${side}]${opacitySuffix}`);
|
|
2310
|
+
continue;
|
|
2311
|
+
}
|
|
2309
2312
|
out.push(`${bang}${modPrefix}${parsed.utility}-[${pair.light}]${opacitySuffix}`);
|
|
2310
2313
|
out.push(`${bang}dark:${modPrefix}${parsed.utility}-[${pair.dark}]${opacitySuffix}`);
|
|
2311
2314
|
}
|
|
@@ -2861,6 +2864,48 @@ var defaultTheme = {
|
|
|
2861
2864
|
animation: {}
|
|
2862
2865
|
};
|
|
2863
2866
|
|
|
2867
|
+
// src/core/generateTypesDts.ts
|
|
2868
|
+
var HEADER = `// AUTO-GENERATED by Kbach from your kbach.config.js \u2014 do not edit by hand.
|
|
2869
|
+
// Regenerated automatically every time your dev server / Metro picks up a
|
|
2870
|
+
// change to that file. Safe (and recommended) to add to .gitignore.
|
|
2871
|
+
//
|
|
2872
|
+
// Gives useColors()/useSpacing() full autocomplete and typo-catching for your
|
|
2873
|
+
// custom colors/spacing keys with zero manual setup \u2014 see KbachCustomColors'
|
|
2874
|
+
// doc comment in @kbach/react if you'd rather hand-author this instead.
|
|
2875
|
+
import '@kbach/react';
|
|
2876
|
+
`;
|
|
2877
|
+
var IDENT_RE = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
2878
|
+
function propKey(name) {
|
|
2879
|
+
return IDENT_RE.test(name) ? name : JSON.stringify(name);
|
|
2880
|
+
}
|
|
2881
|
+
function generateKbachTypesDts(theme) {
|
|
2882
|
+
const colorLines = [];
|
|
2883
|
+
for (const [name, value] of Object.entries(theme.colors)) {
|
|
2884
|
+
if (name in defaultColors) continue;
|
|
2885
|
+
const isFlat = typeof value === "string" || isModeAwareColor(value);
|
|
2886
|
+
colorLines.push(` ${propKey(name)}: ${isFlat ? "string" : "ColorScale"};`);
|
|
2887
|
+
}
|
|
2888
|
+
const spacingLines = [];
|
|
2889
|
+
for (const key of Object.keys(theme.spacing)) {
|
|
2890
|
+
if (key in defaultTheme.spacing) continue;
|
|
2891
|
+
spacingLines.push(` ${propKey(key)}: true;`);
|
|
2892
|
+
}
|
|
2893
|
+
if (colorLines.length === 0 && spacingLines.length === 0) return "";
|
|
2894
|
+
const body = [
|
|
2895
|
+
colorLines.length > 0 ? ` interface KbachCustomColors {
|
|
2896
|
+
${colorLines.join("\n")}
|
|
2897
|
+
}` : null,
|
|
2898
|
+
spacingLines.length > 0 ? ` interface KbachCustomSpacing {
|
|
2899
|
+
${spacingLines.join("\n")}
|
|
2900
|
+
}` : null
|
|
2901
|
+
].filter((s) => s !== null).join("\n\n");
|
|
2902
|
+
return `${HEADER}
|
|
2903
|
+
declare module '@kbach/react' {
|
|
2904
|
+
${body}
|
|
2905
|
+
}
|
|
2906
|
+
`;
|
|
2907
|
+
}
|
|
2908
|
+
|
|
2864
2909
|
// src/core/reset.ts
|
|
2865
2910
|
var RESET_STYLE_ID = "kbach-reset";
|
|
2866
2911
|
var BASE_RESET = [
|
|
@@ -3326,30 +3371,51 @@ function getConfig() {
|
|
|
3326
3371
|
function resetConfig() {
|
|
3327
3372
|
configStore.resolved = null;
|
|
3328
3373
|
}
|
|
3329
|
-
function resolveOneRef(ref, colors) {
|
|
3330
|
-
const lastDash = ref.lastIndexOf("-");
|
|
3331
|
-
if (lastDash <= 0) return null;
|
|
3332
|
-
const name = ref.slice(0, lastDash);
|
|
3333
|
-
const shade = ref.slice(lastDash + 1);
|
|
3334
|
-
if (!/^\d+$/.test(shade)) return null;
|
|
3335
|
-
const entry = colors[name];
|
|
3336
|
-
if (!entry || typeof entry !== "object" || isModeAwareColor(entry)) return null;
|
|
3337
|
-
const target = entry[shade];
|
|
3338
|
-
return typeof target === "string" ? target : null;
|
|
3339
|
-
}
|
|
3340
3374
|
function resolveColorRefs(colors) {
|
|
3341
3375
|
const MAX_DEPTH = 5;
|
|
3342
|
-
function resolveChain(raw) {
|
|
3376
|
+
function resolveChain(raw, side) {
|
|
3343
3377
|
let current = raw;
|
|
3344
3378
|
for (let i = 0; i < MAX_DEPTH; i++) {
|
|
3345
|
-
const next = resolveOneRef(current,
|
|
3379
|
+
const next = resolveOneRef(current, side);
|
|
3346
3380
|
if (!next || next === current) break;
|
|
3347
3381
|
current = next;
|
|
3348
3382
|
}
|
|
3349
3383
|
return current;
|
|
3350
3384
|
}
|
|
3385
|
+
function resolveOneRef(ref, side) {
|
|
3386
|
+
const slashIdx = ref.indexOf("/");
|
|
3387
|
+
if (slashIdx > 0) {
|
|
3388
|
+
const baseName = ref.slice(0, slashIdx);
|
|
3389
|
+
const opacity = Number(ref.slice(slashIdx + 1));
|
|
3390
|
+
if (!Number.isFinite(opacity)) return null;
|
|
3391
|
+
let baseRef;
|
|
3392
|
+
const entry2 = colors[baseName];
|
|
3393
|
+
if (typeof entry2 === "string") {
|
|
3394
|
+
baseRef = entry2;
|
|
3395
|
+
} else if (isModeAwareColor(entry2)) {
|
|
3396
|
+
if (!side) return null;
|
|
3397
|
+
baseRef = entry2[side];
|
|
3398
|
+
} else if (entry2 && typeof entry2 === "object" && "6" in entry2) {
|
|
3399
|
+
const v = entry2["6"];
|
|
3400
|
+
baseRef = typeof v === "string" ? v : void 0;
|
|
3401
|
+
}
|
|
3402
|
+
if (baseRef === void 0) return null;
|
|
3403
|
+
const baseHex = resolveChain(baseRef, side);
|
|
3404
|
+
const a = opacity > 1 ? opacity / 100 : opacity;
|
|
3405
|
+
return hexToRgba(baseHex, a);
|
|
3406
|
+
}
|
|
3407
|
+
const lastDash = ref.lastIndexOf("-");
|
|
3408
|
+
if (lastDash <= 0) return null;
|
|
3409
|
+
const name = ref.slice(0, lastDash);
|
|
3410
|
+
const shade = ref.slice(lastDash + 1);
|
|
3411
|
+
if (!/^\d+$/.test(shade)) return null;
|
|
3412
|
+
const entry = colors[name];
|
|
3413
|
+
if (!entry || typeof entry !== "object" || isModeAwareColor(entry)) return null;
|
|
3414
|
+
const target = entry[shade];
|
|
3415
|
+
return typeof target === "string" ? target : null;
|
|
3416
|
+
}
|
|
3351
3417
|
function resolveValue(val) {
|
|
3352
|
-
return typeof val === "string" ? resolveChain(val) : { light: resolveChain(val.light), dark: resolveChain(val.dark) };
|
|
3418
|
+
return typeof val === "string" ? resolveChain(val, null) : { light: resolveChain(val.light, "light"), dark: resolveChain(val.dark, "dark") };
|
|
3353
3419
|
}
|
|
3354
3420
|
const out = {};
|
|
3355
3421
|
for (const [key, val] of Object.entries(colors)) {
|
|
@@ -3502,6 +3568,7 @@ function subscribeGlobalDarkMode(callback) {
|
|
|
3502
3568
|
expandModeAwareColorClasses,
|
|
3503
3569
|
flatten,
|
|
3504
3570
|
generateClassCSS,
|
|
3571
|
+
generateKbachTypesDts,
|
|
3505
3572
|
getActiveBreakpoints,
|
|
3506
3573
|
getAllModifierNames,
|
|
3507
3574
|
getBuiltinStandaloneNames,
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
import React__default, { ReactNode, ComponentType, ForwardRefExoticComponent } from 'react';
|
|
3
3
|
import * as __core from './core';
|
|
4
4
|
import { ThemeMode, ResolvedConfig, DefaultColorName, defaultColors, ThemeColors, DefaultSpacingKey, ThemeSpacing, FrameworkConfig, StyleValue, ResolvedStyle } from './core';
|
|
5
|
-
export { DefaultColorName, DefaultSpacingKey, FrameworkConfig, ParsedClass, PluginAPI, ResolvedConfig, ResolvedStyle, StyleValue, ThemeConfig, ThemeMode, buildConfig, clearCache, defaultColors, defaultTheme, disableRuntimeCSS, flatten, getConfig, initConfig, normalizeClassString, parseClass, parseClasses, resolve, setResolveTarget, splitClassTokens, updateConfig } from './core';
|
|
5
|
+
export { DefaultColorName, DefaultSpacingKey, FrameworkConfig, ParsedClass, PluginAPI, ResolvedConfig, ResolvedStyle, StyleValue, ThemeConfig, ThemeMode, buildConfig, clearCache, defaultColors, defaultTheme, disableRuntimeCSS, flatten, generateKbachTypesDts, getConfig, initConfig, normalizeClassString, parseClass, parseClasses, resolve, setResolveTarget, splitClassTokens, updateConfig } from './core';
|
|
6
6
|
export { r as registerWebElement } from './web-substitute-CfpYFnE7.js';
|
|
7
7
|
|
|
8
8
|
interface ThemeContextValue {
|
package/dist/index.js
CHANGED
|
@@ -42,6 +42,7 @@ __export(index_exports, {
|
|
|
42
42
|
defaultTheme: () => import_core12.defaultTheme,
|
|
43
43
|
disableRuntimeCSS: () => import_core12.disableRuntimeCSS,
|
|
44
44
|
flatten: () => import_core12.flatten,
|
|
45
|
+
generateKbachTypesDts: () => import_core12.generateKbachTypesDts,
|
|
45
46
|
getConfig: () => import_core12.getConfig,
|
|
46
47
|
initConfig: () => import_core12.initConfig,
|
|
47
48
|
kb: () => kb,
|
|
@@ -1113,6 +1114,7 @@ var import_core12 = require("./core");
|
|
|
1113
1114
|
defaultTheme,
|
|
1114
1115
|
disableRuntimeCSS,
|
|
1115
1116
|
flatten,
|
|
1117
|
+
generateKbachTypesDts,
|
|
1116
1118
|
getConfig,
|
|
1117
1119
|
initConfig,
|
|
1118
1120
|
kb,
|
package/dist/index.mjs
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
defaultTheme,
|
|
12
12
|
disableRuntimeCSS,
|
|
13
13
|
flatten,
|
|
14
|
+
generateKbachTypesDts,
|
|
14
15
|
getActiveBreakpoints,
|
|
15
16
|
getConfig,
|
|
16
17
|
getEffectiveIsWeb,
|
|
@@ -44,7 +45,7 @@ import {
|
|
|
44
45
|
useGlobalDarkMode,
|
|
45
46
|
useGlobalWidth,
|
|
46
47
|
useSyncExternalStore
|
|
47
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-ZTDE7V7I.mjs";
|
|
48
49
|
|
|
49
50
|
// src/context.tsx
|
|
50
51
|
import { createContext, useContext } from "react";
|
|
@@ -549,6 +550,7 @@ export {
|
|
|
549
550
|
defaultTheme,
|
|
550
551
|
disableRuntimeCSS,
|
|
551
552
|
flatten,
|
|
553
|
+
generateKbachTypesDts,
|
|
552
554
|
getConfig,
|
|
553
555
|
initConfig,
|
|
554
556
|
kb,
|
package/dist/jsx-dev-runtime.mjs
CHANGED
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
Fragment,
|
|
4
4
|
jsx,
|
|
5
5
|
jsxs
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-OUKVG4DI.mjs";
|
|
7
|
+
import "./chunk-ZTDE7V7I.mjs";
|
|
8
8
|
|
|
9
9
|
// src/jsx-dev-runtime.tsx
|
|
10
10
|
function jsxDEV(type, props, key, isStaticChildren, source, self) {
|
package/dist/jsx-runtime.mjs
CHANGED
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
_invalidateDefaultFontCache,
|
|
5
5
|
jsx,
|
|
6
6
|
jsxs
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-OUKVG4DI.mjs";
|
|
8
8
|
import {
|
|
9
9
|
registerWebElement
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ZTDE7V7I.mjs";
|
|
11
11
|
export {
|
|
12
12
|
Fragment,
|
|
13
13
|
_invalidateDefaultFontCache,
|
package/dist/vite-plugin.js
CHANGED
|
@@ -2800,10 +2800,6 @@ function expandModeAwareColorClasses(classString, colors) {
|
|
|
2800
2800
|
out.push(token);
|
|
2801
2801
|
continue;
|
|
2802
2802
|
}
|
|
2803
|
-
if (parsed.modifiers.includes("dark") || parsed.modifiers.includes("light")) {
|
|
2804
|
-
out.push(token);
|
|
2805
|
-
continue;
|
|
2806
|
-
}
|
|
2807
2803
|
const slashIdx = parsed.value.indexOf("/");
|
|
2808
2804
|
const colorPart = slashIdx > 0 ? parsed.value.slice(0, slashIdx) : parsed.value;
|
|
2809
2805
|
const opacitySuffix = slashIdx > 0 ? parsed.value.slice(slashIdx) : "";
|
|
@@ -2815,6 +2811,12 @@ function expandModeAwareColorClasses(classString, colors) {
|
|
|
2815
2811
|
changed = true;
|
|
2816
2812
|
const bang = parsed.important ? "!" : "";
|
|
2817
2813
|
const modPrefix = parsed.modifiers.map((m) => `${m}:`).join("");
|
|
2814
|
+
const explicitScheme = parsed.modifiers.map((m) => getModifier(m)?.darkScheme).find((s) => s);
|
|
2815
|
+
if (explicitScheme) {
|
|
2816
|
+
const side = explicitScheme === "dark" ? pair.dark : pair.light;
|
|
2817
|
+
out.push(`${bang}${modPrefix}${parsed.utility}-[${side}]${opacitySuffix}`);
|
|
2818
|
+
continue;
|
|
2819
|
+
}
|
|
2818
2820
|
out.push(`${bang}${modPrefix}${parsed.utility}-[${pair.light}]${opacitySuffix}`);
|
|
2819
2821
|
out.push(`${bang}dark:${modPrefix}${parsed.utility}-[${pair.dark}]${opacitySuffix}`);
|
|
2820
2822
|
}
|
|
@@ -3070,30 +3072,51 @@ function deepMerge(base, override) {
|
|
|
3070
3072
|
return result;
|
|
3071
3073
|
}
|
|
3072
3074
|
var configStore = { resolved: null, listeners: /* @__PURE__ */ new Set(), customVariants: {} };
|
|
3073
|
-
function resolveOneRef(ref, colors) {
|
|
3074
|
-
const lastDash = ref.lastIndexOf("-");
|
|
3075
|
-
if (lastDash <= 0) return null;
|
|
3076
|
-
const name = ref.slice(0, lastDash);
|
|
3077
|
-
const shade = ref.slice(lastDash + 1);
|
|
3078
|
-
if (!/^\d+$/.test(shade)) return null;
|
|
3079
|
-
const entry = colors[name];
|
|
3080
|
-
if (!entry || typeof entry !== "object" || isModeAwareColor(entry)) return null;
|
|
3081
|
-
const target = entry[shade];
|
|
3082
|
-
return typeof target === "string" ? target : null;
|
|
3083
|
-
}
|
|
3084
3075
|
function resolveColorRefs(colors) {
|
|
3085
3076
|
const MAX_DEPTH = 5;
|
|
3086
|
-
function resolveChain(raw) {
|
|
3077
|
+
function resolveChain(raw, side) {
|
|
3087
3078
|
let current = raw;
|
|
3088
3079
|
for (let i = 0; i < MAX_DEPTH; i++) {
|
|
3089
|
-
const next = resolveOneRef(current,
|
|
3080
|
+
const next = resolveOneRef(current, side);
|
|
3090
3081
|
if (!next || next === current) break;
|
|
3091
3082
|
current = next;
|
|
3092
3083
|
}
|
|
3093
3084
|
return current;
|
|
3094
3085
|
}
|
|
3086
|
+
function resolveOneRef(ref, side) {
|
|
3087
|
+
const slashIdx = ref.indexOf("/");
|
|
3088
|
+
if (slashIdx > 0) {
|
|
3089
|
+
const baseName = ref.slice(0, slashIdx);
|
|
3090
|
+
const opacity = Number(ref.slice(slashIdx + 1));
|
|
3091
|
+
if (!Number.isFinite(opacity)) return null;
|
|
3092
|
+
let baseRef;
|
|
3093
|
+
const entry2 = colors[baseName];
|
|
3094
|
+
if (typeof entry2 === "string") {
|
|
3095
|
+
baseRef = entry2;
|
|
3096
|
+
} else if (isModeAwareColor(entry2)) {
|
|
3097
|
+
if (!side) return null;
|
|
3098
|
+
baseRef = entry2[side];
|
|
3099
|
+
} else if (entry2 && typeof entry2 === "object" && "6" in entry2) {
|
|
3100
|
+
const v = entry2["6"];
|
|
3101
|
+
baseRef = typeof v === "string" ? v : void 0;
|
|
3102
|
+
}
|
|
3103
|
+
if (baseRef === void 0) return null;
|
|
3104
|
+
const baseHex = resolveChain(baseRef, side);
|
|
3105
|
+
const a = opacity > 1 ? opacity / 100 : opacity;
|
|
3106
|
+
return hexToRgba(baseHex, a);
|
|
3107
|
+
}
|
|
3108
|
+
const lastDash = ref.lastIndexOf("-");
|
|
3109
|
+
if (lastDash <= 0) return null;
|
|
3110
|
+
const name = ref.slice(0, lastDash);
|
|
3111
|
+
const shade = ref.slice(lastDash + 1);
|
|
3112
|
+
if (!/^\d+$/.test(shade)) return null;
|
|
3113
|
+
const entry = colors[name];
|
|
3114
|
+
if (!entry || typeof entry !== "object" || isModeAwareColor(entry)) return null;
|
|
3115
|
+
const target = entry[shade];
|
|
3116
|
+
return typeof target === "string" ? target : null;
|
|
3117
|
+
}
|
|
3095
3118
|
function resolveValue(val) {
|
|
3096
|
-
return typeof val === "string" ? resolveChain(val) : { light: resolveChain(val.light), dark: resolveChain(val.dark) };
|
|
3119
|
+
return typeof val === "string" ? resolveChain(val, null) : { light: resolveChain(val.light, "light"), dark: resolveChain(val.dark, "dark") };
|
|
3097
3120
|
}
|
|
3098
3121
|
const out = {};
|
|
3099
3122
|
for (const [key, val] of Object.entries(colors)) {
|
|
@@ -3196,6 +3219,48 @@ function makePluginAPI(theme) {
|
|
|
3196
3219
|
}
|
|
3197
3220
|
var customVariants = configStore.customVariants;
|
|
3198
3221
|
|
|
3222
|
+
// src/core/generateTypesDts.ts
|
|
3223
|
+
var HEADER = `// AUTO-GENERATED by Kbach from your kbach.config.js \u2014 do not edit by hand.
|
|
3224
|
+
// Regenerated automatically every time your dev server / Metro picks up a
|
|
3225
|
+
// change to that file. Safe (and recommended) to add to .gitignore.
|
|
3226
|
+
//
|
|
3227
|
+
// Gives useColors()/useSpacing() full autocomplete and typo-catching for your
|
|
3228
|
+
// custom colors/spacing keys with zero manual setup \u2014 see KbachCustomColors'
|
|
3229
|
+
// doc comment in @kbach/react if you'd rather hand-author this instead.
|
|
3230
|
+
import '@kbach/react';
|
|
3231
|
+
`;
|
|
3232
|
+
var IDENT_RE = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
3233
|
+
function propKey(name) {
|
|
3234
|
+
return IDENT_RE.test(name) ? name : JSON.stringify(name);
|
|
3235
|
+
}
|
|
3236
|
+
function generateKbachTypesDts(theme) {
|
|
3237
|
+
const colorLines = [];
|
|
3238
|
+
for (const [name, value] of Object.entries(theme.colors)) {
|
|
3239
|
+
if (name in defaultColors) continue;
|
|
3240
|
+
const isFlat = typeof value === "string" || isModeAwareColor(value);
|
|
3241
|
+
colorLines.push(` ${propKey(name)}: ${isFlat ? "string" : "ColorScale"};`);
|
|
3242
|
+
}
|
|
3243
|
+
const spacingLines = [];
|
|
3244
|
+
for (const key of Object.keys(theme.spacing)) {
|
|
3245
|
+
if (key in defaultTheme.spacing) continue;
|
|
3246
|
+
spacingLines.push(` ${propKey(key)}: true;`);
|
|
3247
|
+
}
|
|
3248
|
+
if (colorLines.length === 0 && spacingLines.length === 0) return "";
|
|
3249
|
+
const body = [
|
|
3250
|
+
colorLines.length > 0 ? ` interface KbachCustomColors {
|
|
3251
|
+
${colorLines.join("\n")}
|
|
3252
|
+
}` : null,
|
|
3253
|
+
spacingLines.length > 0 ? ` interface KbachCustomSpacing {
|
|
3254
|
+
${spacingLines.join("\n")}
|
|
3255
|
+
}` : null
|
|
3256
|
+
].filter((s) => s !== null).join("\n\n");
|
|
3257
|
+
return `${HEADER}
|
|
3258
|
+
declare module '@kbach/react' {
|
|
3259
|
+
${body}
|
|
3260
|
+
}
|
|
3261
|
+
`;
|
|
3262
|
+
}
|
|
3263
|
+
|
|
3199
3264
|
// src/vite-plugin.ts
|
|
3200
3265
|
var process2 = import_node_process.default;
|
|
3201
3266
|
function normPath(p) {
|
|
@@ -3216,6 +3281,9 @@ function warn(message) {
|
|
|
3216
3281
|
function warnBlock(header, ...lines) {
|
|
3217
3282
|
console.warn([`${TAG()} ${yellow(header)}`, ...lines].join("\n"));
|
|
3218
3283
|
}
|
|
3284
|
+
function log(message) {
|
|
3285
|
+
console.log(`${TAG()} ${message}`);
|
|
3286
|
+
}
|
|
3219
3287
|
function findLineCol(code, needle) {
|
|
3220
3288
|
const index = code.indexOf(needle);
|
|
3221
3289
|
if (index === -1) return null;
|
|
@@ -3481,6 +3549,28 @@ ${block}` : block;
|
|
|
3481
3549
|
(0, import_fs.writeFileSync)(filePath, next, "utf-8");
|
|
3482
3550
|
return true;
|
|
3483
3551
|
}
|
|
3552
|
+
function writeKbachTypesDts(root, theme) {
|
|
3553
|
+
const filePath = (0, import_path.join)(root, "kbach-types.d.ts");
|
|
3554
|
+
const content = generateKbachTypesDts(theme);
|
|
3555
|
+
let existing = null;
|
|
3556
|
+
try {
|
|
3557
|
+
existing = (0, import_fs.readFileSync)(filePath, "utf-8");
|
|
3558
|
+
} catch {
|
|
3559
|
+
}
|
|
3560
|
+
if (content === (existing ?? "")) return;
|
|
3561
|
+
try {
|
|
3562
|
+
if (content === "") {
|
|
3563
|
+
(0, import_fs.unlinkSync)(filePath);
|
|
3564
|
+
} else {
|
|
3565
|
+
const isNew = existing === null;
|
|
3566
|
+
(0, import_fs.writeFileSync)(filePath, content, "utf-8");
|
|
3567
|
+
if (isNew) {
|
|
3568
|
+
log(`Generated kbach-types.d.ts \u2014 gives useColors()/useSpacing() autocomplete for your custom colors/spacing keys. Safe to add to .gitignore.`);
|
|
3569
|
+
}
|
|
3570
|
+
}
|
|
3571
|
+
} catch {
|
|
3572
|
+
}
|
|
3573
|
+
}
|
|
3484
3574
|
function toNumericScreens(screens) {
|
|
3485
3575
|
const out = {};
|
|
3486
3576
|
for (const [k, v] of Object.entries(screens)) {
|
|
@@ -3700,6 +3790,7 @@ function kbach(userConfigOrOptions) {
|
|
|
3700
3790
|
},
|
|
3701
3791
|
configResolved(resolved) {
|
|
3702
3792
|
root = resolved.root;
|
|
3793
|
+
writeKbachTypesDts(root, cfg.theme);
|
|
3703
3794
|
const names = new Set(resolved.plugins.map((p) => p.name));
|
|
3704
3795
|
if (names.has("react-router") && names.has("vite:react-refresh")) {
|
|
3705
3796
|
warnBlock(
|
package/dist/vite-plugin.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/vite-plugin.ts
|
|
2
|
-
import { readFileSync, writeFileSync, readdirSync, statSync } from "fs";
|
|
2
|
+
import { readFileSync, writeFileSync, unlinkSync, readdirSync, statSync } from "fs";
|
|
3
3
|
import { join, relative } from "path";
|
|
4
4
|
import processImport from "process";
|
|
5
5
|
|
|
@@ -2766,10 +2766,6 @@ function expandModeAwareColorClasses(classString, colors) {
|
|
|
2766
2766
|
out.push(token);
|
|
2767
2767
|
continue;
|
|
2768
2768
|
}
|
|
2769
|
-
if (parsed.modifiers.includes("dark") || parsed.modifiers.includes("light")) {
|
|
2770
|
-
out.push(token);
|
|
2771
|
-
continue;
|
|
2772
|
-
}
|
|
2773
2769
|
const slashIdx = parsed.value.indexOf("/");
|
|
2774
2770
|
const colorPart = slashIdx > 0 ? parsed.value.slice(0, slashIdx) : parsed.value;
|
|
2775
2771
|
const opacitySuffix = slashIdx > 0 ? parsed.value.slice(slashIdx) : "";
|
|
@@ -2781,6 +2777,12 @@ function expandModeAwareColorClasses(classString, colors) {
|
|
|
2781
2777
|
changed = true;
|
|
2782
2778
|
const bang = parsed.important ? "!" : "";
|
|
2783
2779
|
const modPrefix = parsed.modifiers.map((m) => `${m}:`).join("");
|
|
2780
|
+
const explicitScheme = parsed.modifiers.map((m) => getModifier(m)?.darkScheme).find((s) => s);
|
|
2781
|
+
if (explicitScheme) {
|
|
2782
|
+
const side = explicitScheme === "dark" ? pair.dark : pair.light;
|
|
2783
|
+
out.push(`${bang}${modPrefix}${parsed.utility}-[${side}]${opacitySuffix}`);
|
|
2784
|
+
continue;
|
|
2785
|
+
}
|
|
2784
2786
|
out.push(`${bang}${modPrefix}${parsed.utility}-[${pair.light}]${opacitySuffix}`);
|
|
2785
2787
|
out.push(`${bang}dark:${modPrefix}${parsed.utility}-[${pair.dark}]${opacitySuffix}`);
|
|
2786
2788
|
}
|
|
@@ -3036,30 +3038,51 @@ function deepMerge(base, override) {
|
|
|
3036
3038
|
return result;
|
|
3037
3039
|
}
|
|
3038
3040
|
var configStore = { resolved: null, listeners: /* @__PURE__ */ new Set(), customVariants: {} };
|
|
3039
|
-
function resolveOneRef(ref, colors) {
|
|
3040
|
-
const lastDash = ref.lastIndexOf("-");
|
|
3041
|
-
if (lastDash <= 0) return null;
|
|
3042
|
-
const name = ref.slice(0, lastDash);
|
|
3043
|
-
const shade = ref.slice(lastDash + 1);
|
|
3044
|
-
if (!/^\d+$/.test(shade)) return null;
|
|
3045
|
-
const entry = colors[name];
|
|
3046
|
-
if (!entry || typeof entry !== "object" || isModeAwareColor(entry)) return null;
|
|
3047
|
-
const target = entry[shade];
|
|
3048
|
-
return typeof target === "string" ? target : null;
|
|
3049
|
-
}
|
|
3050
3041
|
function resolveColorRefs(colors) {
|
|
3051
3042
|
const MAX_DEPTH = 5;
|
|
3052
|
-
function resolveChain(raw) {
|
|
3043
|
+
function resolveChain(raw, side) {
|
|
3053
3044
|
let current = raw;
|
|
3054
3045
|
for (let i = 0; i < MAX_DEPTH; i++) {
|
|
3055
|
-
const next = resolveOneRef(current,
|
|
3046
|
+
const next = resolveOneRef(current, side);
|
|
3056
3047
|
if (!next || next === current) break;
|
|
3057
3048
|
current = next;
|
|
3058
3049
|
}
|
|
3059
3050
|
return current;
|
|
3060
3051
|
}
|
|
3052
|
+
function resolveOneRef(ref, side) {
|
|
3053
|
+
const slashIdx = ref.indexOf("/");
|
|
3054
|
+
if (slashIdx > 0) {
|
|
3055
|
+
const baseName = ref.slice(0, slashIdx);
|
|
3056
|
+
const opacity = Number(ref.slice(slashIdx + 1));
|
|
3057
|
+
if (!Number.isFinite(opacity)) return null;
|
|
3058
|
+
let baseRef;
|
|
3059
|
+
const entry2 = colors[baseName];
|
|
3060
|
+
if (typeof entry2 === "string") {
|
|
3061
|
+
baseRef = entry2;
|
|
3062
|
+
} else if (isModeAwareColor(entry2)) {
|
|
3063
|
+
if (!side) return null;
|
|
3064
|
+
baseRef = entry2[side];
|
|
3065
|
+
} else if (entry2 && typeof entry2 === "object" && "6" in entry2) {
|
|
3066
|
+
const v = entry2["6"];
|
|
3067
|
+
baseRef = typeof v === "string" ? v : void 0;
|
|
3068
|
+
}
|
|
3069
|
+
if (baseRef === void 0) return null;
|
|
3070
|
+
const baseHex = resolveChain(baseRef, side);
|
|
3071
|
+
const a = opacity > 1 ? opacity / 100 : opacity;
|
|
3072
|
+
return hexToRgba(baseHex, a);
|
|
3073
|
+
}
|
|
3074
|
+
const lastDash = ref.lastIndexOf("-");
|
|
3075
|
+
if (lastDash <= 0) return null;
|
|
3076
|
+
const name = ref.slice(0, lastDash);
|
|
3077
|
+
const shade = ref.slice(lastDash + 1);
|
|
3078
|
+
if (!/^\d+$/.test(shade)) return null;
|
|
3079
|
+
const entry = colors[name];
|
|
3080
|
+
if (!entry || typeof entry !== "object" || isModeAwareColor(entry)) return null;
|
|
3081
|
+
const target = entry[shade];
|
|
3082
|
+
return typeof target === "string" ? target : null;
|
|
3083
|
+
}
|
|
3061
3084
|
function resolveValue(val) {
|
|
3062
|
-
return typeof val === "string" ? resolveChain(val) : { light: resolveChain(val.light), dark: resolveChain(val.dark) };
|
|
3085
|
+
return typeof val === "string" ? resolveChain(val, null) : { light: resolveChain(val.light, "light"), dark: resolveChain(val.dark, "dark") };
|
|
3063
3086
|
}
|
|
3064
3087
|
const out = {};
|
|
3065
3088
|
for (const [key, val] of Object.entries(colors)) {
|
|
@@ -3162,6 +3185,48 @@ function makePluginAPI(theme) {
|
|
|
3162
3185
|
}
|
|
3163
3186
|
var customVariants = configStore.customVariants;
|
|
3164
3187
|
|
|
3188
|
+
// src/core/generateTypesDts.ts
|
|
3189
|
+
var HEADER = `// AUTO-GENERATED by Kbach from your kbach.config.js \u2014 do not edit by hand.
|
|
3190
|
+
// Regenerated automatically every time your dev server / Metro picks up a
|
|
3191
|
+
// change to that file. Safe (and recommended) to add to .gitignore.
|
|
3192
|
+
//
|
|
3193
|
+
// Gives useColors()/useSpacing() full autocomplete and typo-catching for your
|
|
3194
|
+
// custom colors/spacing keys with zero manual setup \u2014 see KbachCustomColors'
|
|
3195
|
+
// doc comment in @kbach/react if you'd rather hand-author this instead.
|
|
3196
|
+
import '@kbach/react';
|
|
3197
|
+
`;
|
|
3198
|
+
var IDENT_RE = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
3199
|
+
function propKey(name) {
|
|
3200
|
+
return IDENT_RE.test(name) ? name : JSON.stringify(name);
|
|
3201
|
+
}
|
|
3202
|
+
function generateKbachTypesDts(theme) {
|
|
3203
|
+
const colorLines = [];
|
|
3204
|
+
for (const [name, value] of Object.entries(theme.colors)) {
|
|
3205
|
+
if (name in defaultColors) continue;
|
|
3206
|
+
const isFlat = typeof value === "string" || isModeAwareColor(value);
|
|
3207
|
+
colorLines.push(` ${propKey(name)}: ${isFlat ? "string" : "ColorScale"};`);
|
|
3208
|
+
}
|
|
3209
|
+
const spacingLines = [];
|
|
3210
|
+
for (const key of Object.keys(theme.spacing)) {
|
|
3211
|
+
if (key in defaultTheme.spacing) continue;
|
|
3212
|
+
spacingLines.push(` ${propKey(key)}: true;`);
|
|
3213
|
+
}
|
|
3214
|
+
if (colorLines.length === 0 && spacingLines.length === 0) return "";
|
|
3215
|
+
const body = [
|
|
3216
|
+
colorLines.length > 0 ? ` interface KbachCustomColors {
|
|
3217
|
+
${colorLines.join("\n")}
|
|
3218
|
+
}` : null,
|
|
3219
|
+
spacingLines.length > 0 ? ` interface KbachCustomSpacing {
|
|
3220
|
+
${spacingLines.join("\n")}
|
|
3221
|
+
}` : null
|
|
3222
|
+
].filter((s) => s !== null).join("\n\n");
|
|
3223
|
+
return `${HEADER}
|
|
3224
|
+
declare module '@kbach/react' {
|
|
3225
|
+
${body}
|
|
3226
|
+
}
|
|
3227
|
+
`;
|
|
3228
|
+
}
|
|
3229
|
+
|
|
3165
3230
|
// src/vite-plugin.ts
|
|
3166
3231
|
var process2 = processImport;
|
|
3167
3232
|
function normPath(p) {
|
|
@@ -3182,6 +3247,9 @@ function warn(message) {
|
|
|
3182
3247
|
function warnBlock(header, ...lines) {
|
|
3183
3248
|
console.warn([`${TAG()} ${yellow(header)}`, ...lines].join("\n"));
|
|
3184
3249
|
}
|
|
3250
|
+
function log(message) {
|
|
3251
|
+
console.log(`${TAG()} ${message}`);
|
|
3252
|
+
}
|
|
3185
3253
|
function findLineCol(code, needle) {
|
|
3186
3254
|
const index = code.indexOf(needle);
|
|
3187
3255
|
if (index === -1) return null;
|
|
@@ -3447,6 +3515,28 @@ ${block}` : block;
|
|
|
3447
3515
|
writeFileSync(filePath, next, "utf-8");
|
|
3448
3516
|
return true;
|
|
3449
3517
|
}
|
|
3518
|
+
function writeKbachTypesDts(root, theme) {
|
|
3519
|
+
const filePath = join(root, "kbach-types.d.ts");
|
|
3520
|
+
const content = generateKbachTypesDts(theme);
|
|
3521
|
+
let existing = null;
|
|
3522
|
+
try {
|
|
3523
|
+
existing = readFileSync(filePath, "utf-8");
|
|
3524
|
+
} catch {
|
|
3525
|
+
}
|
|
3526
|
+
if (content === (existing ?? "")) return;
|
|
3527
|
+
try {
|
|
3528
|
+
if (content === "") {
|
|
3529
|
+
unlinkSync(filePath);
|
|
3530
|
+
} else {
|
|
3531
|
+
const isNew = existing === null;
|
|
3532
|
+
writeFileSync(filePath, content, "utf-8");
|
|
3533
|
+
if (isNew) {
|
|
3534
|
+
log(`Generated kbach-types.d.ts \u2014 gives useColors()/useSpacing() autocomplete for your custom colors/spacing keys. Safe to add to .gitignore.`);
|
|
3535
|
+
}
|
|
3536
|
+
}
|
|
3537
|
+
} catch {
|
|
3538
|
+
}
|
|
3539
|
+
}
|
|
3450
3540
|
function toNumericScreens(screens) {
|
|
3451
3541
|
const out = {};
|
|
3452
3542
|
for (const [k, v] of Object.entries(screens)) {
|
|
@@ -3666,6 +3756,7 @@ function kbach(userConfigOrOptions) {
|
|
|
3666
3756
|
},
|
|
3667
3757
|
configResolved(resolved) {
|
|
3668
3758
|
root = resolved.root;
|
|
3759
|
+
writeKbachTypesDts(root, cfg.theme);
|
|
3669
3760
|
const names = new Set(resolved.plugins.map((p) => p.name));
|
|
3670
3761
|
if (names.has("react-router") && names.has("vite:react-refresh")) {
|
|
3671
3762
|
warnBlock(
|
package/kbach-react.md
CHANGED
|
@@ -189,7 +189,9 @@ colors.white // '#ffffff'
|
|
|
189
189
|
colors['white/20'] // 'rgba(255,255,255,0.2)'
|
|
190
190
|
colors.alpha('#ff6b35', 60) // 'rgba(255,107,53,0.6)'
|
|
191
191
|
```
|
|
192
|
-
Typed against the built-in theme by default — `colors.blu` (typo) is a compile error. Custom `kbach.config.js` colors
|
|
192
|
+
Typed against the built-in theme by default — `colors.blu` (typo) is a compile error. Custom `kbach.config.js` colors work too, with **zero setup**: the Vite plugin (and `@kbach/native`'s Babel plugin) automatically generate a `kbach-types.d.ts` next to your config, kept in sync every time the dev server / Metro picks up an edit to it — safe to add to `.gitignore`. `useColors()`/`useSpacing()` see your custom names immediately, no type parameter needed, same typo-catching as the built-in ones.
|
|
193
|
+
|
|
194
|
+
If you'd rather commit the types instead of generating them (a library package with no dev server/bundler step of its own, for instance), hand-author the same thing in any `.d.ts` your tsconfig includes:
|
|
193
195
|
|
|
194
196
|
```ts
|
|
195
197
|
import '@kbach/react'; // or '@kbach/native' — either works, native re-exports react's types
|
|
@@ -199,9 +201,12 @@ declare module '@kbach/react' {
|
|
|
199
201
|
accent: string; // a flat color, like the built-in white/black — also what a
|
|
200
202
|
// mode-aware { light, dark } config color resolves to at read time
|
|
201
203
|
}
|
|
204
|
+
interface KbachCustomSpacing {
|
|
205
|
+
18: true; // only the key is read — value is just a placeholder
|
|
206
|
+
}
|
|
202
207
|
}
|
|
203
208
|
```
|
|
204
|
-
|
|
209
|
+
A hand-authored file and the generated one both merge into the exact same interfaces, so either — or both at once — works.
|
|
205
210
|
|
|
206
211
|
---
|
|
207
212
|
|
|
@@ -735,17 +740,21 @@ extend: {
|
|
|
735
740
|
surface: { light: '#ffffff', dark: '#111827' },
|
|
736
741
|
// each side can itself be an alias — resolved independently
|
|
737
742
|
accent: { light: 'blue-6', dark: 'blue-4' },
|
|
743
|
+
// or derived from another color at an opacity — 'name/opacity', resolved
|
|
744
|
+
// once here instead of only being computable at runtime via colors.alpha()
|
|
745
|
+
accentSoft: { light: 'accent/30', dark: 'accent/40' },
|
|
738
746
|
},
|
|
739
747
|
},
|
|
740
748
|
},
|
|
741
749
|
```
|
|
742
750
|
|
|
743
751
|
```jsx
|
|
744
|
-
<div className="bg-surface text-accent" />
|
|
745
|
-
// equivalent to writing bg-white dark:bg-gray-9 text-blue-6 dark:text-blue-4
|
|
752
|
+
<div className="bg-surface text-accent hover:bg-accentSoft" />
|
|
753
|
+
// equivalent to writing bg-white dark:bg-gray-9 text-blue-6 dark:text-blue-4
|
|
754
|
+
// hover:bg-[rgba(...)] dark:hover:bg-[rgba(...)] by hand
|
|
746
755
|
```
|
|
747
756
|
|
|
748
|
-
Works everywhere a color does — `useColors()` (returns the active side directly), opacity composition (`bg-surface/50`),
|
|
757
|
+
Works everywhere a color does — `useColors()` (returns the active side directly), opacity composition (`bg-surface/50`), per-shade within a scale (`brand: { 6: { light: '#3b82f6', dark: '#60a5fa' } }`), and stacked under an explicit modifier (`dark:hover:bg-accent` correctly uses the dark side, still scoped to dark mode + hover — the modifier doesn't need to be there in the first place, but it's respected if it is).
|
|
749
758
|
|
|
750
759
|
### Runtime update
|
|
751
760
|
```js
|