@kbach/react-native 1.0.0-beta.16 → 1.0.0-beta.17
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 +75 -0
- package/dist/{chunk-XGQWM65X.mjs → chunk-45GOGUHJ.mjs} +36 -2
- package/dist/{chunk-6ML62O2R.mjs → chunk-MJWWZJMH.mjs} +1 -1
- package/dist/chunk-OGFB3OXS.mjs +552 -0
- package/dist/dynamicTokens.d.ts +35 -0
- package/dist/dynamicTokens.js +75 -0
- package/dist/index.d.ts +15 -1
- package/dist/index.js +223 -19
- package/dist/index.web.d.ts +2 -1
- package/dist/index.web.js +21 -1
- package/dist/index.web.mjs +17 -2
- package/dist/jsx-dev-runtime.js +222 -22
- package/dist/jsx-dev-runtime.web.js +2 -1
- package/dist/jsx-dev-runtime.web.mjs +3 -3
- package/dist/jsx-runtime.js +222 -22
- package/dist/jsx-runtime.web.js +1 -1
- package/dist/jsx-runtime.web.mjs +2 -2
- package/dist/{useColors-Br8QhIlE.d.ts → useDynamicToken-Dr15c88t.d.ts} +14 -1
- package/package.json +1 -1
- package/dist/chunk-3ED4FIO2.mjs +0 -552
package/dist/index.web.mjs
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
|
+
deleteDynamicToken,
|
|
3
|
+
getDynamicToken,
|
|
2
4
|
getGlobalDarkMode,
|
|
3
5
|
getGlobalThemeMode,
|
|
4
6
|
seedDefaultMode,
|
|
7
|
+
setDynamicToken,
|
|
5
8
|
setGlobalThemeMode,
|
|
9
|
+
subscribeDynamicTokens,
|
|
6
10
|
subscribeGlobalDarkMode,
|
|
7
11
|
toggleGlobalDarkMode
|
|
8
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-45GOGUHJ.mjs";
|
|
9
13
|
import {
|
|
10
14
|
defaultTheme,
|
|
11
15
|
getTheme,
|
|
12
16
|
resolveClassName,
|
|
13
17
|
setTheme
|
|
14
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-OGFB3OXS.mjs";
|
|
15
19
|
|
|
16
20
|
// src/config.ts
|
|
17
21
|
function parseHexRgb(hex) {
|
|
@@ -177,19 +181,30 @@ function useColors() {
|
|
|
177
181
|
const { isDark } = useTheme();
|
|
178
182
|
return makeColorsProxy(getTheme(), isDark);
|
|
179
183
|
}
|
|
184
|
+
|
|
185
|
+
// src/useDynamicToken.ts
|
|
186
|
+
import { useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
187
|
+
function useDynamicToken(name) {
|
|
188
|
+
return useSyncExternalStore2(subscribeDynamicTokens, () => getDynamicToken(name));
|
|
189
|
+
}
|
|
180
190
|
export {
|
|
181
191
|
ThemeProvider,
|
|
182
192
|
applyKbachConfig,
|
|
183
193
|
defaultTheme,
|
|
194
|
+
deleteDynamicToken,
|
|
195
|
+
getDynamicToken,
|
|
184
196
|
getGlobalDarkMode,
|
|
185
197
|
getGlobalThemeMode,
|
|
186
198
|
getTheme,
|
|
187
199
|
resolveClassName,
|
|
188
200
|
resolveKbachConfig,
|
|
201
|
+
setDynamicToken,
|
|
189
202
|
setGlobalThemeMode,
|
|
190
203
|
setTheme,
|
|
204
|
+
subscribeDynamicTokens,
|
|
191
205
|
subscribeGlobalDarkMode,
|
|
192
206
|
toggleGlobalDarkMode,
|
|
193
207
|
useColors,
|
|
208
|
+
useDynamicToken,
|
|
194
209
|
useTheme
|
|
195
210
|
};
|
package/dist/jsx-dev-runtime.js
CHANGED
|
@@ -30,12 +30,21 @@ var import_jsx_runtime = require("react/jsx-runtime");
|
|
|
30
30
|
var import_react = require("react");
|
|
31
31
|
var import_react_native = require("react-native");
|
|
32
32
|
var import_darkModeStore = require("./darkModeStore");
|
|
33
|
+
var import_dynamicTokens = require("./dynamicTokens");
|
|
33
34
|
var import_theme = require("./theme");
|
|
35
|
+
var DYNAMIC_TOKEN_MATCH_RE = /var\(--([a-zA-Z0-9-]+)\)/g;
|
|
36
|
+
function substituteDynamicTokens(classStrRaw) {
|
|
37
|
+
if (!classStrRaw.includes("var(--")) return classStrRaw;
|
|
38
|
+
return classStrRaw.replace(DYNAMIC_TOKEN_MATCH_RE, (whole, name) => {
|
|
39
|
+
const value = (0, import_dynamicTokens.getDynamicToken)(name);
|
|
40
|
+
return value ?? whole;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
34
43
|
function makeElement(isStaticChildren, type, props, key) {
|
|
35
44
|
return (isStaticChildren ? import_jsx_runtime.jsxs : import_jsx_runtime.jsx)(type, props, key);
|
|
36
45
|
}
|
|
37
46
|
function resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, pressed) {
|
|
38
|
-
const resolved = resolveStyle2(classStrRaw, pressed);
|
|
47
|
+
const resolved = resolveStyle2(substituteDynamicTokens(classStrRaw), pressed);
|
|
39
48
|
if (userStyle === void 0) {
|
|
40
49
|
return resolved;
|
|
41
50
|
}
|
|
@@ -60,6 +69,12 @@ function breakpointKeySuffix(classStrRaw, width) {
|
|
|
60
69
|
const state = present.map((name) => screens[name] !== void 0 && width >= screens[name] ? "1" : "0").join("");
|
|
61
70
|
return `:kb-bp-${state}`;
|
|
62
71
|
}
|
|
72
|
+
function dynamicTokenKeySuffix(classStrRaw) {
|
|
73
|
+
const matches = classStrRaw.match(DYNAMIC_TOKEN_MATCH_RE);
|
|
74
|
+
if (!matches) return "";
|
|
75
|
+
const values = matches.map((m) => (0, import_dynamicTokens.getDynamicToken)(m.slice("var(--".length, -1)) ?? "");
|
|
76
|
+
return `:kb-dt-${values.join("|")}`;
|
|
77
|
+
}
|
|
63
78
|
function ReactiveElement({
|
|
64
79
|
hostType,
|
|
65
80
|
hostRest,
|
|
@@ -70,9 +85,10 @@ function ReactiveElement({
|
|
|
70
85
|
isStaticChildren
|
|
71
86
|
}) {
|
|
72
87
|
(0, import_react.useSyncExternalStore)(import_darkModeStore.subscribeGlobalDarkMode, import_darkModeStore.getGlobalDarkMode);
|
|
88
|
+
(0, import_react.useSyncExternalStore)(import_dynamicTokens.subscribeDynamicTokens, import_dynamicTokens.getDynamicTokensVersion);
|
|
73
89
|
const { width } = (0, import_react_native.useWindowDimensions)();
|
|
74
90
|
const finalStyle = hostType === import_react_native.Pressable ? (state) => resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, state.pressed) : resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, false);
|
|
75
|
-
const suffix = darkModeKeySuffix(classStrRaw) + breakpointKeySuffix(classStrRaw, width);
|
|
91
|
+
const suffix = darkModeKeySuffix(classStrRaw) + breakpointKeySuffix(classStrRaw, width) + dynamicTokenKeySuffix(classStrRaw);
|
|
76
92
|
const finalKey = suffix ? `${elementKey ?? ""}${suffix}` : elementKey;
|
|
77
93
|
return makeElement(isStaticChildren, hostType, { ...hostRest, style: finalStyle }, finalKey);
|
|
78
94
|
}
|
|
@@ -84,7 +100,7 @@ function processElement(resolveStyle2, type, rawProps, key, isStaticChildren) {
|
|
|
84
100
|
if (typeof classStrRaw !== "string") {
|
|
85
101
|
return makeElement(isStaticChildren, type, rawProps, key);
|
|
86
102
|
}
|
|
87
|
-
if (DARK_MODIFIER_RE.test(classStrRaw) || BREAKPOINT_MODIFIER_RE.test(classStrRaw)) {
|
|
103
|
+
if (DARK_MODIFIER_RE.test(classStrRaw) || BREAKPOINT_MODIFIER_RE.test(classStrRaw) || classStrRaw.includes("var(--")) {
|
|
88
104
|
return (0, import_jsx_runtime.jsx)(
|
|
89
105
|
ReactiveElement,
|
|
90
106
|
{ hostType: type, hostRest: rest, classStrRaw, userStyle, resolveStyle: resolveStyle2, elementKey: key, isStaticChildren },
|
|
@@ -1215,6 +1231,153 @@ function resolveUtilityNative(parsed, theme) {
|
|
|
1215
1231
|
return resolveFlex(parsed, false) ?? resolve(parsed, theme) ?? resolve2(parsed, theme) ?? resolve3(parsed, theme) ?? resolveColorNative(parsed, theme) ?? resolveLeadingTrackingNative(parsed) ?? resolveTypographyNative(parsed) ?? nativeShadowDeclarations(parsed);
|
|
1216
1232
|
}
|
|
1217
1233
|
|
|
1234
|
+
// src/jsEngine/calc.ts
|
|
1235
|
+
function reduceConstantMath(raw) {
|
|
1236
|
+
const trimmed = raw.trim();
|
|
1237
|
+
const calc = stripCall(trimmed, "calc");
|
|
1238
|
+
if (calc !== null) {
|
|
1239
|
+
return new Evaluator(calc).parseExprToEnd();
|
|
1240
|
+
}
|
|
1241
|
+
const clamp = stripCall(trimmed, "clamp");
|
|
1242
|
+
if (clamp !== null) {
|
|
1243
|
+
const args = splitTopLevelCommas(clamp);
|
|
1244
|
+
if (args.length !== 3) return null;
|
|
1245
|
+
const [min2, preferred, max2] = args.map((a) => new Evaluator(a).parseExprToEnd());
|
|
1246
|
+
if (min2 === null || preferred === null || max2 === null) return null;
|
|
1247
|
+
return Math.max(min2, Math.min(preferred, max2));
|
|
1248
|
+
}
|
|
1249
|
+
const min = stripCall(trimmed, "min");
|
|
1250
|
+
if (min !== null) {
|
|
1251
|
+
const values = splitTopLevelCommas(min).map((a) => new Evaluator(a).parseExprToEnd());
|
|
1252
|
+
return values.some((v) => v === null) ? null : Math.min(...values);
|
|
1253
|
+
}
|
|
1254
|
+
const max = stripCall(trimmed, "max");
|
|
1255
|
+
if (max !== null) {
|
|
1256
|
+
const values = splitTopLevelCommas(max).map((a) => new Evaluator(a).parseExprToEnd());
|
|
1257
|
+
return values.some((v) => v === null) ? null : Math.max(...values);
|
|
1258
|
+
}
|
|
1259
|
+
return null;
|
|
1260
|
+
}
|
|
1261
|
+
function stripCall(raw, name) {
|
|
1262
|
+
if (!raw.startsWith(name)) return null;
|
|
1263
|
+
const afterName = raw.slice(name.length).trimStart();
|
|
1264
|
+
if (!afterName.startsWith("(") || !afterName.endsWith(")")) return null;
|
|
1265
|
+
return afterName.slice(1, -1);
|
|
1266
|
+
}
|
|
1267
|
+
function splitTopLevelCommas(s) {
|
|
1268
|
+
const parts = [];
|
|
1269
|
+
let depth = 0;
|
|
1270
|
+
let start = 0;
|
|
1271
|
+
for (let i = 0; i < s.length; i++) {
|
|
1272
|
+
const ch = s[i];
|
|
1273
|
+
if (ch === "(") depth++;
|
|
1274
|
+
else if (ch === ")") depth--;
|
|
1275
|
+
else if (ch === "," && depth === 0) {
|
|
1276
|
+
parts.push(s.slice(start, i).trim());
|
|
1277
|
+
start = i + 1;
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
parts.push(s.slice(start).trim());
|
|
1281
|
+
return parts;
|
|
1282
|
+
}
|
|
1283
|
+
var Evaluator = class {
|
|
1284
|
+
constructor(s) {
|
|
1285
|
+
this.pos = 0;
|
|
1286
|
+
this.s = s;
|
|
1287
|
+
}
|
|
1288
|
+
parseExprToEnd() {
|
|
1289
|
+
const value = this.expr();
|
|
1290
|
+
if (value === null) return null;
|
|
1291
|
+
this.skipWs();
|
|
1292
|
+
return this.pos === this.s.length ? value : null;
|
|
1293
|
+
}
|
|
1294
|
+
skipWs() {
|
|
1295
|
+
while (this.pos < this.s.length && /\s/.test(this.s[this.pos])) this.pos++;
|
|
1296
|
+
}
|
|
1297
|
+
peek() {
|
|
1298
|
+
this.skipWs();
|
|
1299
|
+
return this.s[this.pos];
|
|
1300
|
+
}
|
|
1301
|
+
expr() {
|
|
1302
|
+
let value = this.term();
|
|
1303
|
+
if (value === null) return null;
|
|
1304
|
+
for (; ; ) {
|
|
1305
|
+
const ch = this.peek();
|
|
1306
|
+
if (ch === "+") {
|
|
1307
|
+
this.pos++;
|
|
1308
|
+
const rhs = this.term();
|
|
1309
|
+
if (rhs === null) return null;
|
|
1310
|
+
value += rhs;
|
|
1311
|
+
} else if (ch === "-") {
|
|
1312
|
+
this.pos++;
|
|
1313
|
+
const rhs = this.term();
|
|
1314
|
+
if (rhs === null) return null;
|
|
1315
|
+
value -= rhs;
|
|
1316
|
+
} else {
|
|
1317
|
+
return value;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
term() {
|
|
1322
|
+
let value = this.factor();
|
|
1323
|
+
if (value === null) return null;
|
|
1324
|
+
for (; ; ) {
|
|
1325
|
+
const ch = this.peek();
|
|
1326
|
+
if (ch === "*") {
|
|
1327
|
+
this.pos++;
|
|
1328
|
+
const rhs = this.factor();
|
|
1329
|
+
if (rhs === null) return null;
|
|
1330
|
+
value *= rhs;
|
|
1331
|
+
} else if (ch === "/") {
|
|
1332
|
+
this.pos++;
|
|
1333
|
+
const divisor = this.factor();
|
|
1334
|
+
if (divisor === null || divisor === 0) return null;
|
|
1335
|
+
value /= divisor;
|
|
1336
|
+
} else {
|
|
1337
|
+
return value;
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
factor() {
|
|
1342
|
+
const ch = this.peek();
|
|
1343
|
+
if (ch === void 0) return null;
|
|
1344
|
+
if (ch === "(") {
|
|
1345
|
+
this.pos++;
|
|
1346
|
+
const value = this.expr();
|
|
1347
|
+
if (value === null || this.peek() !== ")") return null;
|
|
1348
|
+
this.pos++;
|
|
1349
|
+
return value;
|
|
1350
|
+
}
|
|
1351
|
+
if (ch === "-") {
|
|
1352
|
+
this.pos++;
|
|
1353
|
+
const value = this.factor();
|
|
1354
|
+
return value === null ? null : -value;
|
|
1355
|
+
}
|
|
1356
|
+
return this.numberWithUnit();
|
|
1357
|
+
}
|
|
1358
|
+
numberWithUnit() {
|
|
1359
|
+
this.skipWs();
|
|
1360
|
+
const start = this.pos;
|
|
1361
|
+
while (this.pos < this.s.length && (/[0-9]/.test(this.s[this.pos]) || this.s[this.pos] === ".")) this.pos++;
|
|
1362
|
+
if (this.pos === start) return null;
|
|
1363
|
+
const n = Number(this.s.slice(start, this.pos));
|
|
1364
|
+
if (!Number.isFinite(n)) return null;
|
|
1365
|
+
const unitStart = this.pos;
|
|
1366
|
+
while (this.pos < this.s.length && /[a-zA-Z]/.test(this.s[this.pos])) this.pos++;
|
|
1367
|
+
const unit = this.s.slice(unitStart, this.pos);
|
|
1368
|
+
switch (unit) {
|
|
1369
|
+
case "":
|
|
1370
|
+
return n;
|
|
1371
|
+
case "px":
|
|
1372
|
+
return n;
|
|
1373
|
+
case "rem":
|
|
1374
|
+
return n * 16;
|
|
1375
|
+
default:
|
|
1376
|
+
return null;
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
};
|
|
1380
|
+
|
|
1218
1381
|
// src/jsEngine/resolveStyle.ts
|
|
1219
1382
|
var RESPONSIVE_BREAKPOINTS = /* @__PURE__ */ new Set(["sm", "md", "lg", "xl", "2xl"]);
|
|
1220
1383
|
function nativeModifierState(modifier, theme, colorScheme, pressed, width) {
|
|
@@ -1284,25 +1447,41 @@ var NUMERIC_LENGTH_PROPS = /* @__PURE__ */ new Set([
|
|
|
1284
1447
|
"outline-width",
|
|
1285
1448
|
"outline-offset"
|
|
1286
1449
|
]);
|
|
1450
|
+
function isPlainPercentage(value) {
|
|
1451
|
+
if (!value.endsWith("%")) return false;
|
|
1452
|
+
let digits = value.slice(0, -1);
|
|
1453
|
+
if (digits.startsWith("-")) digits = digits.slice(1);
|
|
1454
|
+
return digits.length > 0 && /^[0-9.]+$/.test(digits);
|
|
1455
|
+
}
|
|
1287
1456
|
function rnStyleValue(property, value) {
|
|
1288
|
-
if (NUMERIC_LENGTH_PROPS.has(property)) {
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1457
|
+
if (!NUMERIC_LENGTH_PROPS.has(property)) {
|
|
1458
|
+
return { value, warning: null };
|
|
1459
|
+
}
|
|
1460
|
+
let px = null;
|
|
1461
|
+
if (value.endsWith("px")) {
|
|
1462
|
+
const n = Number(value.slice(0, -2));
|
|
1463
|
+
px = Number.isFinite(n) ? n : null;
|
|
1464
|
+
} else if (value.endsWith("rem")) {
|
|
1465
|
+
const n = Number(value.slice(0, -3));
|
|
1466
|
+
px = Number.isFinite(n) ? n * 16 : null;
|
|
1467
|
+
} else {
|
|
1468
|
+
const n = Number(value);
|
|
1469
|
+
px = value.trim() !== "" && Number.isFinite(n) ? n : null;
|
|
1470
|
+
}
|
|
1471
|
+
if (px !== null) return { value: px, warning: null };
|
|
1472
|
+
if (isPlainPercentage(value)) {
|
|
1473
|
+
return { value, warning: null };
|
|
1474
|
+
}
|
|
1475
|
+
const reduced = reduceConstantMath(value);
|
|
1476
|
+
if (reduced !== null) {
|
|
1477
|
+
return { value: reduced, warning: null };
|
|
1301
1478
|
}
|
|
1302
|
-
|
|
1479
|
+
const warning = `Kbach: "${value}" is not a valid native value for "${property}" \u2014 dropped. calc()/clamp()/min()/max() only resolve on native when every operand is a constant px/rem length (no %, vw, vh, var(), or other viewport/CSS-variable units \u2014 those need real layout/DOM, which doesn't exist on native at paint time). Use a plain px/rem calc, a fraction utility (e.g. w-1/2), or resolve this value in JS instead.`;
|
|
1480
|
+
return { value: null, warning };
|
|
1303
1481
|
}
|
|
1304
|
-
function
|
|
1482
|
+
function resolveStyleJsWithWarnings(classString, theme, colorScheme, pressed, width) {
|
|
1305
1483
|
const style = {};
|
|
1484
|
+
const warnings = [];
|
|
1306
1485
|
let shadowOffset = null;
|
|
1307
1486
|
for (const token of classString.split(/\s+/).filter(Boolean)) {
|
|
1308
1487
|
const parsed = parseClass(token);
|
|
@@ -1323,13 +1502,15 @@ function resolveStyleJs(classString, theme, colorScheme, pressed, width) {
|
|
|
1323
1502
|
shadowOffset[d.property === "shadow-offset-x" ? "width" : "height"] = n;
|
|
1324
1503
|
continue;
|
|
1325
1504
|
}
|
|
1326
|
-
|
|
1505
|
+
const { value, warning } = rnStyleValue(d.property, d.value);
|
|
1506
|
+
if (warning !== null) warnings.push(warning);
|
|
1507
|
+
if (value !== null) style[kebabToCamel(d.property)] = value;
|
|
1327
1508
|
}
|
|
1328
1509
|
}
|
|
1329
1510
|
if (shadowOffset !== null) {
|
|
1330
1511
|
style.shadowOffset = { width: shadowOffset.width ?? 0, height: shadowOffset.height ?? 0 };
|
|
1331
1512
|
}
|
|
1332
|
-
return style;
|
|
1513
|
+
return { style, warnings };
|
|
1333
1514
|
}
|
|
1334
1515
|
|
|
1335
1516
|
// src/nativeBridge.ts
|
|
@@ -1338,10 +1519,29 @@ function resolveStyle(classString, pressed = false) {
|
|
|
1338
1519
|
const width = import_react_native2.Dimensions.get("window").width;
|
|
1339
1520
|
const KbachModule = import_react_native2.TurboModuleRegistry.get("KbachModule");
|
|
1340
1521
|
if (!KbachModule) {
|
|
1341
|
-
|
|
1522
|
+
const { style: style2, warnings: warnings2 } = resolveStyleJsWithWarnings(classString, (0, import_theme2.getTheme)(), colorScheme, pressed, width);
|
|
1523
|
+
warnIfDev(classString, warnings2);
|
|
1524
|
+
return style2;
|
|
1342
1525
|
}
|
|
1343
1526
|
const json = KbachModule.resolveStyle(classString, (0, import_theme2.getThemeJson)(), colorScheme, pressed, width);
|
|
1344
|
-
|
|
1527
|
+
const style = JSON.parse(json);
|
|
1528
|
+
const warnings = style.__kbachWarnings;
|
|
1529
|
+
if (warnings !== void 0) {
|
|
1530
|
+
delete style.__kbachWarnings;
|
|
1531
|
+
warnIfDev(classString, warnings);
|
|
1532
|
+
}
|
|
1533
|
+
return style;
|
|
1534
|
+
}
|
|
1535
|
+
var warnedMessages = /* @__PURE__ */ new Set();
|
|
1536
|
+
function warnIfDev(classString, warnings) {
|
|
1537
|
+
if (warnings.length === 0) return;
|
|
1538
|
+
if (typeof __DEV__ !== "undefined" && !__DEV__) return;
|
|
1539
|
+
for (const warning of warnings) {
|
|
1540
|
+
const message = `${warning} (from className "${classString}")`;
|
|
1541
|
+
if (warnedMessages.has(message)) continue;
|
|
1542
|
+
warnedMessages.add(message);
|
|
1543
|
+
console.warn(message);
|
|
1544
|
+
}
|
|
1345
1545
|
}
|
|
1346
1546
|
|
|
1347
1547
|
// src/jsx-runtime.tsx
|