@kbach/react 1.0.0-beta.17 → 1.0.0-beta.19

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.
@@ -166,11 +166,29 @@ function resolveColorEntry(value, lookup) {
166
166
  return typeof base === "string" ? applyOpacityToHex(base, opacity) : { light: applyOpacityToHex(base.light, opacity), dark: applyOpacityToHex(base.dark, opacity) };
167
167
  }
168
168
  function resolveColors(extend, existing) {
169
+ const { dark: darkExtend, ...lightExtend } = extend;
169
170
  const resolved = {};
170
171
  const lookup = (name) => resolved[name] ?? existing[name];
171
- for (const [name, value] of Object.entries(extend)) {
172
+ for (const [name, value] of Object.entries(lightExtend)) {
173
+ if (typeof value === "object" && value !== null && !("light" in value) && !("dark" in value)) continue;
172
174
  resolved[name] = resolveColorEntry(value, lookup);
173
175
  }
176
+ if (darkExtend) {
177
+ const resolvedDark = {};
178
+ const lookupDark = (name) => {
179
+ const found = resolvedDark[name] ?? existing[name];
180
+ return typeof found === "string" ? found : void 0;
181
+ };
182
+ for (const [name, value] of Object.entries(darkExtend)) {
183
+ const entry = resolveColorEntry(value, lookupDark);
184
+ resolvedDark[name] = typeof entry === "string" ? entry : entry.dark;
185
+ }
186
+ for (const [name, darkValue] of Object.entries(resolvedDark)) {
187
+ const lightEntry = resolved[name];
188
+ if (lightEntry === void 0 || typeof lightEntry !== "string") continue;
189
+ resolved[name] = { light: lightEntry, dark: darkValue };
190
+ }
191
+ }
174
192
  return resolved;
175
193
  }
176
194
  function resolveKbachConfig(config) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveKbachConfig
3
- } from "./chunk-OWWJ2PME.mjs";
3
+ } from "./chunk-43FOLRQA.mjs";
4
4
  import {
5
5
  buildResetCSS,
6
6
  defaultTheme
@@ -445,10 +445,16 @@ function stripModifierPrefix(token) {
445
445
  return token.replace(/^(?:[a-zA-Z0-9_/-]+:)+/, "");
446
446
  }
447
447
  var MARKER_CLASSES = /* @__PURE__ */ new Set(["group", "peer"]);
448
+ function isMarkerClass(base) {
449
+ if (MARKER_CLASSES.has(base)) return true;
450
+ const slashIdx = base.lastIndexOf("/");
451
+ if (slashIdx === -1) return false;
452
+ return MARKER_CLASSES.has(base.slice(0, slashIdx)) && slashIdx < base.length - 1;
453
+ }
448
454
  function warnIfUnknownClass(token, filePath, code, isResolvable, projectCssClasses, warnedTokens) {
449
455
  if (isResolvable || warnedTokens.has(token)) return;
450
456
  const base = stripModifierPrefix(token);
451
- if (!base || projectCssClasses.has(base) || MARKER_CLASSES.has(base)) return;
457
+ if (!base || projectCssClasses.has(base) || isMarkerClass(base)) return;
452
458
  warnedTokens.add(token);
453
459
  const pos = findLineCol(code, token);
454
460
  const location = pos ? `${blue(filePath)}${green(`:${pos.line}:${pos.column}`)}` : blue(filePath);
@@ -87,8 +87,28 @@ interface KbachConfig {
87
87
  * already-defined-above) is treated as a literal CSS value instead
88
88
  * (`accent: 'red'` — REAL CSS `red`, since there's no color named "red"
89
89
  * to alias), never an error either way.
90
+ *
91
+ * `dark` is a reserved key, not a color name — a SECOND way to write a
92
+ * mode-aware color, as a group instead of per-color: `{ surface:
93
+ * 'gray-2', card: 'white', dark: { surface: 'gray-11', card: 'gray-9' } }`
94
+ * makes `surface`/`card` mode-aware, while a name never mentioned under
95
+ * `dark` (like a hypothetical always-the-same `brand` here) stays a
96
+ * plain, mode-independent color. Equivalent to writing `surface: {
97
+ * light: 'gray-2', dark: 'gray-11' }` directly — pick whichever reads
98
+ * better for your config: per-color pairs when only a couple of colors
99
+ * are mode-aware, the grouped block when most of them are and writing
100
+ * "light"/"dark" twice per line would be repetitive. A name under
101
+ * `dark` with no matching top-level (light) entry is skipped — mode-
102
+ * aware colors need both sides written out. References inside `dark`
103
+ * resolve against the built-in palette and OTHER entries within `dark`
104
+ * itself (not the light-side custom colors, and not a light-side color
105
+ * already written as a `{ light, dark }` pair) — self-contained, the
106
+ * same way the light side already resolves independently of it.
90
107
  */
91
- colors?: Record<string, ColorEntry | string>;
108
+ colors?: {
109
+ [colorName: string]: ColorEntry | string | Record<string, string> | undefined;
110
+ dark?: Record<string, string>;
111
+ };
92
112
  spacing?: Record<string, number>;
93
113
  screens?: Record<string, number>;
94
114
  /** Named font stacks, e.g. `{ display: '"Cal Sans", sans-serif' }` — adds to (or overrides one of) `defaultTheme.fontFamily`'s three names. */
@@ -87,8 +87,28 @@ interface KbachConfig {
87
87
  * already-defined-above) is treated as a literal CSS value instead
88
88
  * (`accent: 'red'` — REAL CSS `red`, since there's no color named "red"
89
89
  * to alias), never an error either way.
90
+ *
91
+ * `dark` is a reserved key, not a color name — a SECOND way to write a
92
+ * mode-aware color, as a group instead of per-color: `{ surface:
93
+ * 'gray-2', card: 'white', dark: { surface: 'gray-11', card: 'gray-9' } }`
94
+ * makes `surface`/`card` mode-aware, while a name never mentioned under
95
+ * `dark` (like a hypothetical always-the-same `brand` here) stays a
96
+ * plain, mode-independent color. Equivalent to writing `surface: {
97
+ * light: 'gray-2', dark: 'gray-11' }` directly — pick whichever reads
98
+ * better for your config: per-color pairs when only a couple of colors
99
+ * are mode-aware, the grouped block when most of them are and writing
100
+ * "light"/"dark" twice per line would be repetitive. A name under
101
+ * `dark` with no matching top-level (light) entry is skipped — mode-
102
+ * aware colors need both sides written out. References inside `dark`
103
+ * resolve against the built-in palette and OTHER entries within `dark`
104
+ * itself (not the light-side custom colors, and not a light-side color
105
+ * already written as a `{ light, dark }` pair) — self-contained, the
106
+ * same way the light side already resolves independently of it.
90
107
  */
91
- colors?: Record<string, ColorEntry | string>;
108
+ colors?: {
109
+ [colorName: string]: ColorEntry | string | Record<string, string> | undefined;
110
+ dark?: Record<string, string>;
111
+ };
92
112
  spacing?: Record<string, number>;
93
113
  screens?: Record<string, number>;
94
114
  /** Named font stacks, e.g. `{ display: '"Cal Sans", sans-serif' }` — adds to (or overrides one of) `defaultTheme.fontFamily`'s three names. */
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- export { C as ColorEntry, a as ContainerConfig, D as DarkModeStrategy, K as KbachConfig, T as ThemeConfig, b as applyKbachConfig, d as defaultTheme, g as getTheme, r as resolveKbachConfig, s as setTheme } from './config-B00tH6vN.mjs';
1
+ export { C as ColorEntry, a as ContainerConfig, D as DarkModeStrategy, K as KbachConfig, T as ThemeConfig, b as applyKbachConfig, d as defaultTheme, g as getTheme, r as resolveKbachConfig, s as setTheme } from './config-N74_lKa0.mjs';
2
2
  import * as react from 'react';
3
3
  import { ReactNode } from 'react';
4
4
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { C as ColorEntry, a as ContainerConfig, D as DarkModeStrategy, K as KbachConfig, T as ThemeConfig, b as applyKbachConfig, d as defaultTheme, g as getTheme, r as resolveKbachConfig, s as setTheme } from './config-B00tH6vN.js';
1
+ export { C as ColorEntry, a as ContainerConfig, D as DarkModeStrategy, K as KbachConfig, T as ThemeConfig, b as applyKbachConfig, d as defaultTheme, g as getTheme, r as resolveKbachConfig, s as setTheme } from './config-N74_lKa0.js';
2
2
  import * as react from 'react';
3
3
  import { ReactNode } from 'react';
4
4
 
package/dist/index.js CHANGED
@@ -789,11 +789,29 @@ function resolveColorEntry(value, lookup) {
789
789
  return typeof base === "string" ? applyOpacityToHex(base, opacity) : { light: applyOpacityToHex(base.light, opacity), dark: applyOpacityToHex(base.dark, opacity) };
790
790
  }
791
791
  function resolveColors(extend, existing) {
792
+ const { dark: darkExtend, ...lightExtend } = extend;
792
793
  const resolved = {};
793
794
  const lookup = (name) => resolved[name] ?? existing[name];
794
- for (const [name, value] of Object.entries(extend)) {
795
+ for (const [name, value] of Object.entries(lightExtend)) {
796
+ if (typeof value === "object" && value !== null && !("light" in value) && !("dark" in value)) continue;
795
797
  resolved[name] = resolveColorEntry(value, lookup);
796
798
  }
799
+ if (darkExtend) {
800
+ const resolvedDark = {};
801
+ const lookupDark = (name) => {
802
+ const found = resolvedDark[name] ?? existing[name];
803
+ return typeof found === "string" ? found : void 0;
804
+ };
805
+ for (const [name, value] of Object.entries(darkExtend)) {
806
+ const entry = resolveColorEntry(value, lookupDark);
807
+ resolvedDark[name] = typeof entry === "string" ? entry : entry.dark;
808
+ }
809
+ for (const [name, darkValue] of Object.entries(resolvedDark)) {
810
+ const lightEntry = resolved[name];
811
+ if (lightEntry === void 0 || typeof lightEntry !== "string") continue;
812
+ resolved[name] = { light: lightEntry, dark: darkValue };
813
+ }
814
+ }
797
815
  return resolved;
798
816
  }
799
817
  function resolveKbachConfig(config) {
package/dist/index.mjs CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  setGlobalThemeMode,
17
17
  subscribeGlobalDarkMode,
18
18
  toggleGlobalDarkMode
19
- } from "./chunk-OWWJ2PME.mjs";
19
+ } from "./chunk-43FOLRQA.mjs";
20
20
  import {
21
21
  BASE_RESET,
22
22
  RESET_STYLE_ID,
@@ -1,5 +1,5 @@
1
1
  import { Plugin } from 'postcss';
2
- import { T as ThemeConfig, K as KbachConfig } from './config-B00tH6vN.mjs';
2
+ import { T as ThemeConfig, K as KbachConfig } from './config-N74_lKa0.mjs';
3
3
 
4
4
  interface KbachPostcssPluginOptions {
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { Plugin } from 'postcss';
2
- import { T as ThemeConfig, K as KbachConfig } from './config-B00tH6vN.js';
2
+ import { T as ThemeConfig, K as KbachConfig } from './config-N74_lKa0.js';
3
3
 
4
4
  interface KbachPostcssPluginOptions {
5
5
  /**
@@ -531,10 +531,16 @@ function stripModifierPrefix(token) {
531
531
  return token.replace(/^(?:[a-zA-Z0-9_/-]+:)+/, "");
532
532
  }
533
533
  var MARKER_CLASSES = /* @__PURE__ */ new Set(["group", "peer"]);
534
+ function isMarkerClass(base) {
535
+ if (MARKER_CLASSES.has(base)) return true;
536
+ const slashIdx = base.lastIndexOf("/");
537
+ if (slashIdx === -1) return false;
538
+ return MARKER_CLASSES.has(base.slice(0, slashIdx)) && slashIdx < base.length - 1;
539
+ }
534
540
  function warnIfUnknownClass(token, filePath, code, isResolvable, projectCssClasses, warnedTokens) {
535
541
  if (isResolvable || warnedTokens.has(token)) return;
536
542
  const base = stripModifierPrefix(token);
537
- if (!base || projectCssClasses.has(base) || MARKER_CLASSES.has(base)) return;
543
+ if (!base || projectCssClasses.has(base) || isMarkerClass(base)) return;
538
544
  warnedTokens.add(token);
539
545
  const pos = findLineCol(code, token);
540
546
  const location = pos ? `${blue(filePath)}${green(`:${pos.line}:${pos.column}`)}` : blue(filePath);
@@ -1092,11 +1098,29 @@ function resolveColorEntry(value, lookup) {
1092
1098
  return typeof base === "string" ? applyOpacityToHex(base, opacity) : { light: applyOpacityToHex(base.light, opacity), dark: applyOpacityToHex(base.dark, opacity) };
1093
1099
  }
1094
1100
  function resolveColors(extend, existing) {
1101
+ const { dark: darkExtend, ...lightExtend } = extend;
1095
1102
  const resolved = {};
1096
1103
  const lookup = (name) => resolved[name] ?? existing[name];
1097
- for (const [name, value] of Object.entries(extend)) {
1104
+ for (const [name, value] of Object.entries(lightExtend)) {
1105
+ if (typeof value === "object" && value !== null && !("light" in value) && !("dark" in value)) continue;
1098
1106
  resolved[name] = resolveColorEntry(value, lookup);
1099
1107
  }
1108
+ if (darkExtend) {
1109
+ const resolvedDark = {};
1110
+ const lookupDark = (name) => {
1111
+ const found = resolvedDark[name] ?? existing[name];
1112
+ return typeof found === "string" ? found : void 0;
1113
+ };
1114
+ for (const [name, value] of Object.entries(darkExtend)) {
1115
+ const entry = resolveColorEntry(value, lookupDark);
1116
+ resolvedDark[name] = typeof entry === "string" ? entry : entry.dark;
1117
+ }
1118
+ for (const [name, darkValue] of Object.entries(resolvedDark)) {
1119
+ const lightEntry = resolved[name];
1120
+ if (lightEntry === void 0 || typeof lightEntry !== "string") continue;
1121
+ resolved[name] = { light: lightEntry, dark: darkValue };
1122
+ }
1123
+ }
1100
1124
  return resolved;
1101
1125
  }
1102
1126
  function resolveKbachConfig(config) {
@@ -6,8 +6,8 @@ import {
6
6
  highlight,
7
7
  kbachTag,
8
8
  resolveEffectiveTheme
9
- } from "./chunk-CQKDEA6F.mjs";
10
- import "./chunk-OWWJ2PME.mjs";
9
+ } from "./chunk-MRBB55KV.mjs";
10
+ import "./chunk-43FOLRQA.mjs";
11
11
  import "./chunk-OVKVZA7B.mjs";
12
12
 
13
13
  // src/postcss-plugin/index.ts
@@ -1,5 +1,5 @@
1
1
  import { Plugin } from 'vite';
2
- import { T as ThemeConfig, K as KbachConfig } from './config-B00tH6vN.mjs';
2
+ import { T as ThemeConfig, K as KbachConfig } from './config-N74_lKa0.mjs';
3
3
 
4
4
  interface KbachPluginOptions {
5
5
  /** Defaults to the same defaultTheme the runtime uses — pass your own to keep both in sync. */
@@ -1,5 +1,5 @@
1
1
  import { Plugin } from 'vite';
2
- import { T as ThemeConfig, K as KbachConfig } from './config-B00tH6vN.js';
2
+ import { T as ThemeConfig, K as KbachConfig } from './config-N74_lKa0.js';
3
3
 
4
4
  interface KbachPluginOptions {
5
5
  /** Defaults to the same defaultTheme the runtime uses — pass your own to keep both in sync. */
@@ -778,11 +778,29 @@ function resolveColorEntry(value, lookup) {
778
778
  return typeof base === "string" ? applyOpacityToHex(base, opacity) : { light: applyOpacityToHex(base.light, opacity), dark: applyOpacityToHex(base.dark, opacity) };
779
779
  }
780
780
  function resolveColors(extend, existing) {
781
+ const { dark: darkExtend, ...lightExtend } = extend;
781
782
  const resolved = {};
782
783
  const lookup = (name) => resolved[name] ?? existing[name];
783
- for (const [name, value] of Object.entries(extend)) {
784
+ for (const [name, value] of Object.entries(lightExtend)) {
785
+ if (typeof value === "object" && value !== null && !("light" in value) && !("dark" in value)) continue;
784
786
  resolved[name] = resolveColorEntry(value, lookup);
785
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
+ }
786
804
  return resolved;
787
805
  }
788
806
  function resolveKbachConfig(config) {
@@ -1047,10 +1065,16 @@ function stripModifierPrefix(token) {
1047
1065
  return token.replace(/^(?:[a-zA-Z0-9_/-]+:)+/, "");
1048
1066
  }
1049
1067
  var MARKER_CLASSES = /* @__PURE__ */ new Set(["group", "peer"]);
1068
+ function isMarkerClass(base) {
1069
+ if (MARKER_CLASSES.has(base)) return true;
1070
+ const slashIdx = base.lastIndexOf("/");
1071
+ if (slashIdx === -1) return false;
1072
+ return MARKER_CLASSES.has(base.slice(0, slashIdx)) && slashIdx < base.length - 1;
1073
+ }
1050
1074
  function warnIfUnknownClass(token, filePath, code, isResolvable, projectCssClasses, warnedTokens) {
1051
1075
  if (isResolvable || warnedTokens.has(token)) return;
1052
1076
  const base = stripModifierPrefix(token);
1053
- if (!base || projectCssClasses.has(base) || MARKER_CLASSES.has(base)) return;
1077
+ if (!base || projectCssClasses.has(base) || isMarkerClass(base)) return;
1054
1078
  warnedTokens.add(token);
1055
1079
  const pos = findLineCol(code, token);
1056
1080
  const location = pos ? `${blue(filePath)}${green(`:${pos.line}:${pos.column}`)}` : blue(filePath);
@@ -5,8 +5,8 @@ import {
5
5
  kbach,
6
6
  loadConfigFile,
7
7
  resolveEffectiveTheme
8
- } from "./chunk-CQKDEA6F.mjs";
9
- import "./chunk-OWWJ2PME.mjs";
8
+ } from "./chunk-MRBB55KV.mjs";
9
+ import "./chunk-43FOLRQA.mjs";
10
10
  import "./chunk-OVKVZA7B.mjs";
11
11
  export {
12
12
  CSS_SYNC_DEBOUNCE_MS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kbach/react",
3
- "version": "1.0.0-beta.17",
3
+ "version": "1.0.0-beta.19",
4
4
  "description": "A utility-first styling engine for React, powered by a real Rust/WASM core — Tailwind CSS v4 feature parity with Kbach's own color palette.",
5
5
  "keywords": [
6
6
  "css",
@@ -72,7 +72,7 @@
72
72
  "generate:colors": "node ../core-engine/scripts/generate-palette.mjs src/generatedPalette.ts"
73
73
  },
74
74
  "dependencies": {
75
- "@kbach/core-engine": "1.0.0-beta.10"
75
+ "@kbach/core-engine": "1.0.0-beta.11"
76
76
  },
77
77
  "devDependencies": {
78
78
  "@types/react": "^19.2.0",