@kbach/react-native 1.0.0-beta.20 → 1.0.0-beta.22

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.
@@ -1,10 +1,10 @@
1
- import "./chunk-45GOGUHJ.mjs";
1
+ import "./chunk-TS2EEVOE.mjs";
2
2
  import {
3
3
  Fragment,
4
4
  jsx,
5
5
  jsxs
6
- } from "./chunk-MJWWZJMH.mjs";
7
- import "./chunk-OGFB3OXS.mjs";
6
+ } from "./chunk-OS7EPBH5.mjs";
7
+ import "./chunk-AG7ZQ2K4.mjs";
8
8
 
9
9
  // src/jsxRuntimeCore.ts
10
10
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -32,7 +32,6 @@ var import_react = require("react");
32
32
  var import_react_native = require("react-native");
33
33
  var import_darkModeStore = require("./darkModeStore");
34
34
  var import_dynamicTokens = require("./dynamicTokens");
35
- var import_theme = require("./theme");
36
35
 
37
36
  // src/jsEngine/calc.ts
38
37
  function reduceConstantMath(raw) {
@@ -207,148 +206,47 @@ function parsePercentRelativeCalc(token) {
207
206
  function resolvePercentRelativeCalc(basisPx, calc) {
208
207
  return basisPx * calc.percentCoefficient / 100 + calc.constantPx;
209
208
  }
210
-
211
- // src/jsxRuntimeCore.ts
212
- var DYNAMIC_TOKEN_MATCH_RE = /var\(--([a-zA-Z0-9-]+)\)/g;
213
- function substituteDynamicTokens(classStrRaw) {
214
- if (!classStrRaw.includes("var(--")) return classStrRaw;
215
- return classStrRaw.replace(DYNAMIC_TOKEN_MATCH_RE, (whole, name) => {
216
- const value = (0, import_dynamicTokens.getDynamicToken)(name);
217
- return value ?? whole;
218
- });
219
- }
220
- var PERCENT_RELATIVE_CALC_HINT_RE = /[wh]-\[calc\([^)]*%[^)]*\)\]/;
221
- function extractPercentRelativeCalcs(classStrRaw) {
222
- const found = [];
223
- for (const token of classStrRaw.split(/\s+/)) {
224
- const parsed = parsePercentRelativeCalc(token);
225
- if (parsed) found.push(parsed);
209
+ var PERCENT_MIN_MAX_CLAMP_TOKEN_RE = /^(w|h)-\[(min|max|clamp)\(([^)]+)\)\]$/;
210
+ function parseOperand(arg) {
211
+ const trimmed = arg.trim();
212
+ const pct = /^(-?[\d.]+)%$/.exec(trimmed);
213
+ if (pct) {
214
+ const percentCoefficient = Number(pct[1]);
215
+ return Number.isFinite(percentCoefficient) ? { percentCoefficient, constantPx: 0 } : null;
226
216
  }
227
- return found;
217
+ const constantPx = reduceConstantMath(`calc(${trimmed})`);
218
+ return constantPx === null ? null : { percentCoefficient: 0, constantPx };
228
219
  }
229
- function stripPercentRelativeCalcTokens(classStrRaw) {
230
- return classStrRaw.split(/\s+/).filter((token) => token && parsePercentRelativeCalc(token) === null).join(" ");
231
- }
232
- function makeElement(isStaticChildren, type, props, key) {
233
- return (isStaticChildren ? import_jsx_runtime.jsxs : import_jsx_runtime.jsx)(type, props, key);
234
- }
235
- function resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, pressed, layoutOverrides) {
236
- const cleaned = stripPercentRelativeCalcTokens(substituteDynamicTokens(classStrRaw));
237
- const resolved = resolveStyle2(cleaned, pressed);
238
- if (layoutOverrides) {
239
- Object.assign(resolved, layoutOverrides);
240
- }
241
- if (userStyle === void 0) {
242
- return resolved;
243
- }
244
- if (typeof userStyle === "function") {
245
- return [resolved, userStyle({ pressed })];
246
- }
247
- return [resolved, userStyle];
248
- }
249
- var DARK_MODIFIER_RE = /(^|\s)dark:/;
250
- var BREAKPOINT_MODIFIER_RE = /(^|\s)(sm|md|lg|xl|2xl):/;
251
- var BREAKPOINT_MODIFIER_MATCH_RE = /(?:^|\s)(sm|md|lg|xl|2xl):/g;
252
- function darkModeKeySuffix(classStrRaw) {
253
- return DARK_MODIFIER_RE.test(classStrRaw) ? `:kb-dark-${(0, import_darkModeStore.getGlobalDarkMode)()}` : "";
254
- }
255
- function breakpointKeySuffix(classStrRaw, width) {
256
- const matches = classStrRaw.match(BREAKPOINT_MODIFIER_MATCH_RE);
257
- if (!matches) {
258
- return "";
259
- }
260
- const screens = (0, import_theme.getTheme)().screens;
261
- const present = Array.from(new Set(matches.map((m) => m.trim().slice(0, -1))));
262
- const state = present.map((name) => screens[name] !== void 0 && width >= screens[name] ? "1" : "0").join("");
263
- return `:kb-bp-${state}`;
264
- }
265
- function dynamicTokenKeySuffix(classStrRaw) {
266
- const matches = classStrRaw.match(DYNAMIC_TOKEN_MATCH_RE);
267
- if (!matches) return "";
268
- const values = matches.map((m) => (0, import_dynamicTokens.getDynamicToken)(m.slice("var(--".length, -1)) ?? "");
269
- return `:kb-dt-${values.join("|")}`;
270
- }
271
- function percentCalcKeySuffix(percentCalcs, measuredBasis) {
272
- if (percentCalcs.length === 0) return "";
273
- const values = percentCalcs.map((calc) => {
274
- const basis = measuredBasis?.[calc.property];
275
- return basis === void 0 ? "pending" : resolvePercentRelativeCalc(basis, calc);
276
- });
277
- return `:kb-pc-${values.join("|")}`;
278
- }
279
- function ReactiveElement({
280
- hostType,
281
- hostRest,
282
- classStrRaw,
283
- userStyle,
284
- resolveStyle: resolveStyle2,
285
- elementKey,
286
- isStaticChildren
287
- }) {
288
- (0, import_react.useSyncExternalStore)(import_darkModeStore.subscribeGlobalDarkMode, import_darkModeStore.getGlobalDarkMode);
289
- (0, import_react.useSyncExternalStore)(import_dynamicTokens.subscribeDynamicTokens, import_dynamicTokens.getDynamicTokensVersion);
290
- const { width } = (0, import_react_native.useWindowDimensions)();
291
- const [measuredBasis, setMeasuredBasis] = (0, import_react.useState)(null);
292
- const measure = (0, import_react.useCallback)((e) => {
293
- const { width: w, height: h } = e.nativeEvent.layout;
294
- setMeasuredBasis((prev) => prev && prev.width === w && prev.height === h ? prev : { width: w, height: h });
295
- }, []);
296
- const percentCalcs = extractPercentRelativeCalcs(classStrRaw);
297
- let layoutOverrides;
298
- let hostRestWithLayout = hostRest;
299
- if (percentCalcs.length > 0) {
300
- layoutOverrides = {};
301
- for (const calc of percentCalcs) {
302
- const basis = measuredBasis?.[calc.property];
303
- layoutOverrides[calc.property] = basis === void 0 ? "100%" : resolvePercentRelativeCalc(basis, calc);
220
+ function parsePercentRelativeMinMaxClamp(token) {
221
+ const m = PERCENT_MIN_MAX_CLAMP_TOKEN_RE.exec(token);
222
+ if (!m) return null;
223
+ const property = m[1] === "w" ? "width" : "height";
224
+ const kind = m[2];
225
+ const args = splitTopLevelCommas(m[3].replace(/_/g, " "));
226
+ if (kind === "clamp" && args.length !== 3) return null;
227
+ if (kind !== "clamp" && args.length < 1) return null;
228
+ const operands = args.map(parseOperand);
229
+ if (operands.some((o) => o === null)) return null;
230
+ const resolved = operands;
231
+ if (!resolved.some((o) => o.percentCoefficient !== 0)) return null;
232
+ const resolveOperand = (o, basisPx) => basisPx * o.percentCoefficient / 100 + o.constantPx;
233
+ return {
234
+ property,
235
+ resolve(basisPx) {
236
+ const values = resolved.map((o) => resolveOperand(o, basisPx));
237
+ if (kind === "min") return Math.min(...values);
238
+ if (kind === "max") return Math.max(...values);
239
+ const [min, preferred, max] = values;
240
+ return Math.max(min, Math.min(preferred, max));
304
241
  }
305
- const userOnLayout = hostRest.onLayout;
306
- hostRestWithLayout = {
307
- ...hostRest,
308
- onLayout: userOnLayout ? (e) => {
309
- measure(e);
310
- userOnLayout(e);
311
- } : measure
312
- };
313
- }
314
- const finalStyle = hostType === import_react_native.Pressable ? (state) => resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, state.pressed, layoutOverrides) : resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, false, layoutOverrides);
315
- const suffix = darkModeKeySuffix(classStrRaw) + breakpointKeySuffix(classStrRaw, width) + dynamicTokenKeySuffix(classStrRaw) + percentCalcKeySuffix(percentCalcs, measuredBasis);
316
- const finalKey = suffix ? `${elementKey ?? ""}${suffix}` : elementKey;
317
- return makeElement(isStaticChildren, hostType, { ...hostRestWithLayout, style: finalStyle }, finalKey);
318
- }
319
- function processElement(resolveStyle2, type, rawProps, key, isStaticChildren) {
320
- if (type === null || typeof type === "symbol" || !rawProps) {
321
- return makeElement(isStaticChildren, type, rawProps ?? {}, key);
322
- }
323
- const { className: classStrRaw, style: userStyle, ...rest } = rawProps;
324
- if (typeof classStrRaw !== "string") {
325
- return makeElement(isStaticChildren, type, rawProps, key);
326
- }
327
- if (DARK_MODIFIER_RE.test(classStrRaw) || BREAKPOINT_MODIFIER_RE.test(classStrRaw) || classStrRaw.includes("var(--") || PERCENT_RELATIVE_CALC_HINT_RE.test(classStrRaw)) {
328
- return (0, import_jsx_runtime.jsx)(
329
- ReactiveElement,
330
- { hostType: type, hostRest: rest, classStrRaw, userStyle, resolveStyle: resolveStyle2, elementKey: key, isStaticChildren },
331
- key
332
- );
333
- }
334
- const finalStyle = type === import_react_native.Pressable ? (state) => resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, state.pressed) : resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, false);
335
- return makeElement(isStaticChildren, type, { ...rest, style: finalStyle }, key);
242
+ };
336
243
  }
337
- function createJsxFunctions(resolveStyle2) {
338
- function jsx2(type, props, key) {
339
- return processElement(resolveStyle2, type, props, key, false);
340
- }
341
- function jsxs2(type, props, key) {
342
- return processElement(resolveStyle2, type, props, key, true);
343
- }
344
- return { jsx: jsx2, jsxs: jsxs2 };
244
+ function parsePercentRelativeExpr(token) {
245
+ const calc = parsePercentRelativeCalc(token);
246
+ if (calc) return { property: calc.property, resolve: (basisPx) => resolvePercentRelativeCalc(basisPx, calc) };
247
+ return parsePercentRelativeMinMaxClamp(token);
345
248
  }
346
249
 
347
- // src/nativeBridge.ts
348
- var import_react_native2 = require("react-native");
349
- var import_theme2 = require("./theme");
350
- var import_darkModeStore2 = require("./darkModeStore");
351
-
352
250
  // src/jsEngine/parser.ts
353
251
  var VALUE_PREFIXES = [
354
252
  "bg-opacity-",
@@ -436,11 +334,21 @@ var VALUE_PREFIXES = [
436
334
  "tracking-",
437
335
  "font-",
438
336
  "z-",
337
+ "inset-x-",
338
+ "inset-y-",
439
339
  "inset-",
440
340
  "top-",
441
341
  "right-",
442
342
  "bottom-",
443
343
  "left-",
344
+ "start-",
345
+ "end-",
346
+ "overflow-x-",
347
+ "overflow-y-",
348
+ "overscroll-x-",
349
+ "overscroll-y-",
350
+ "overscroll-",
351
+ "aspect-",
444
352
  "divide-color-",
445
353
  "space-x-",
446
354
  "space-y-",
@@ -595,6 +503,179 @@ function parseClass(token) {
595
503
  };
596
504
  }
597
505
 
506
+ // src/jsxRuntimeCore.ts
507
+ var DYNAMIC_TOKEN_MATCH_RE = /var\(--([a-zA-Z0-9-]+)\)/g;
508
+ function substituteDynamicTokens(classStrRaw) {
509
+ if (!classStrRaw.includes("var(--")) return classStrRaw;
510
+ return classStrRaw.replace(DYNAMIC_TOKEN_MATCH_RE, (whole, name) => {
511
+ const value = (0, import_dynamicTokens.getDynamicToken)(name);
512
+ return value ?? whole;
513
+ });
514
+ }
515
+ var PERCENT_RELATIVE_CALC_HINT_RE = /[wh]-\[(calc|min|max|clamp)\([^)]*%[^)]*\)\]/;
516
+ function extractPercentRelativeCalcs(classStrRaw) {
517
+ const found = [];
518
+ for (const token of classStrRaw.split(/\s+/)) {
519
+ const parsed = parsePercentRelativeExpr(token);
520
+ if (parsed) found.push(parsed);
521
+ }
522
+ return found;
523
+ }
524
+ function stripPercentRelativeCalcTokens(classStrRaw) {
525
+ return classStrRaw.split(/\s+/).filter((token) => token && parsePercentRelativeExpr(token) === null).join(" ");
526
+ }
527
+ var STATE_MODIFIER_NAMES = /* @__PURE__ */ new Set(["hover", "focus", "disabled"]);
528
+ var STATE_MODIFIER_HINT_RE = /(^|\s|:)(hover|focus|disabled):/;
529
+ function stripModifiers(parts, namesToStrip) {
530
+ const utility = parts[parts.length - 1] ?? "";
531
+ const modifiers = parts.slice(0, -1).filter((m) => !namesToStrip.has(m));
532
+ return [...modifiers, utility].join(":");
533
+ }
534
+ function substituteStateModifiers(classStrRaw, states) {
535
+ if (!STATE_MODIFIER_HINT_RE.test(classStrRaw)) return classStrRaw;
536
+ const kept = [];
537
+ for (const token of classStrRaw.split(/\s+/)) {
538
+ if (!token) continue;
539
+ const parts = splitRespectingBrackets(token);
540
+ const modifiers = parts.slice(0, -1);
541
+ const required = modifiers.filter((m) => STATE_MODIFIER_NAMES.has(m));
542
+ if (required.length === 0) {
543
+ kept.push(token);
544
+ continue;
545
+ }
546
+ if (required.every((m) => states[m])) {
547
+ kept.push(stripModifiers(parts, STATE_MODIFIER_NAMES));
548
+ }
549
+ }
550
+ return kept.join(" ");
551
+ }
552
+ function makeElement(isStaticChildren, type, props, key) {
553
+ return (isStaticChildren ? import_jsx_runtime.jsxs : import_jsx_runtime.jsx)(type, props, key);
554
+ }
555
+ function resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, pressed, layoutOverrides, states = { hover: false, focus: false, disabled: false }) {
556
+ const stateResolved = substituteStateModifiers(classStrRaw, states);
557
+ const cleaned = stripPercentRelativeCalcTokens(substituteDynamicTokens(stateResolved));
558
+ const resolved = resolveStyle2(cleaned, pressed);
559
+ if (layoutOverrides) {
560
+ Object.assign(resolved, layoutOverrides);
561
+ }
562
+ if (userStyle === void 0) {
563
+ return resolved;
564
+ }
565
+ if (typeof userStyle === "function") {
566
+ return [resolved, userStyle({ pressed })];
567
+ }
568
+ return [resolved, userStyle];
569
+ }
570
+ var DARK_MODIFIER_RE = /(^|\s|:)dark:/;
571
+ var BREAKPOINT_MODIFIER_RE = /(^|\s|:)(sm|md|lg|xl|2xl):/;
572
+ var HOVER_MODIFIER_RE = /(^|\s|:)hover:/;
573
+ var FOCUS_MODIFIER_RE = /(^|\s|:)focus:/;
574
+ function ReactiveElement({
575
+ hostType,
576
+ hostRest,
577
+ classStrRaw,
578
+ userStyle,
579
+ resolveStyle: resolveStyle2,
580
+ elementKey,
581
+ isStaticChildren
582
+ }) {
583
+ (0, import_react.useSyncExternalStore)(import_darkModeStore.subscribeGlobalDarkMode, import_darkModeStore.getGlobalDarkMode);
584
+ (0, import_react.useSyncExternalStore)(import_dynamicTokens.subscribeDynamicTokens, import_dynamicTokens.getDynamicTokensVersion);
585
+ (0, import_react_native.useWindowDimensions)();
586
+ const [measuredBasis, setMeasuredBasis] = (0, import_react.useState)(null);
587
+ const measure = (0, import_react.useCallback)((e) => {
588
+ const { width: w, height: h } = e.nativeEvent.layout;
589
+ setMeasuredBasis((prev) => prev && prev.width === w && prev.height === h ? prev : { width: w, height: h });
590
+ }, []);
591
+ const [isHovered, setIsHovered] = (0, import_react.useState)(false);
592
+ const [isFocused, setIsFocused] = (0, import_react.useState)(false);
593
+ const percentCalcs = extractPercentRelativeCalcs(classStrRaw);
594
+ let layoutOverrides;
595
+ let hostRestWithLayout = hostRest;
596
+ if (percentCalcs.length > 0) {
597
+ layoutOverrides = {};
598
+ for (const calc of percentCalcs) {
599
+ const basis = measuredBasis?.[calc.property];
600
+ layoutOverrides[calc.property] = basis === void 0 ? "100%" : calc.resolve(basis);
601
+ }
602
+ const userOnLayout = hostRest.onLayout;
603
+ hostRestWithLayout = {
604
+ ...hostRest,
605
+ onLayout: userOnLayout ? (e) => {
606
+ measure(e);
607
+ userOnLayout(e);
608
+ } : measure
609
+ };
610
+ }
611
+ if (HOVER_MODIFIER_RE.test(classStrRaw)) {
612
+ const userOnHoverIn = hostRestWithLayout.onHoverIn;
613
+ const userOnHoverOut = hostRestWithLayout.onHoverOut;
614
+ hostRestWithLayout = {
615
+ ...hostRestWithLayout,
616
+ onHoverIn: (e) => {
617
+ setIsHovered(true);
618
+ userOnHoverIn?.(e);
619
+ },
620
+ onHoverOut: (e) => {
621
+ setIsHovered(false);
622
+ userOnHoverOut?.(e);
623
+ }
624
+ };
625
+ }
626
+ if (FOCUS_MODIFIER_RE.test(classStrRaw)) {
627
+ const userOnFocus = hostRestWithLayout.onFocus;
628
+ const userOnBlur = hostRestWithLayout.onBlur;
629
+ hostRestWithLayout = {
630
+ ...hostRestWithLayout,
631
+ onFocus: (e) => {
632
+ setIsFocused(true);
633
+ userOnFocus?.(e);
634
+ },
635
+ onBlur: (e) => {
636
+ setIsFocused(false);
637
+ userOnBlur?.(e);
638
+ }
639
+ };
640
+ }
641
+ const states = { hover: isHovered, focus: isFocused, disabled: hostRest.disabled === true };
642
+ const finalStyle = hostType === import_react_native.Pressable ? (state) => resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, state.pressed, layoutOverrides, states) : resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, false, layoutOverrides, states);
643
+ return makeElement(isStaticChildren, hostType, { ...hostRestWithLayout, style: finalStyle }, elementKey);
644
+ }
645
+ function processElement(resolveStyle2, type, rawProps, key, isStaticChildren) {
646
+ if (type === null || typeof type === "symbol" || !rawProps) {
647
+ return makeElement(isStaticChildren, type, rawProps ?? {}, key);
648
+ }
649
+ const { className: classStrRaw, style: userStyle, ...rest } = rawProps;
650
+ if (typeof classStrRaw !== "string") {
651
+ return makeElement(isStaticChildren, type, rawProps, key);
652
+ }
653
+ if (DARK_MODIFIER_RE.test(classStrRaw) || BREAKPOINT_MODIFIER_RE.test(classStrRaw) || HOVER_MODIFIER_RE.test(classStrRaw) || FOCUS_MODIFIER_RE.test(classStrRaw) || classStrRaw.includes("var(--") || PERCENT_RELATIVE_CALC_HINT_RE.test(classStrRaw)) {
654
+ return (0, import_jsx_runtime.jsx)(
655
+ ReactiveElement,
656
+ { hostType: type, hostRest: rest, classStrRaw, userStyle, resolveStyle: resolveStyle2, elementKey: key, isStaticChildren },
657
+ key
658
+ );
659
+ }
660
+ const staticStates = { hover: false, focus: false, disabled: rest.disabled === true };
661
+ const finalStyle = type === import_react_native.Pressable ? (state) => resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, state.pressed, void 0, staticStates) : resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, false, void 0, staticStates);
662
+ return makeElement(isStaticChildren, type, { ...rest, style: finalStyle }, key);
663
+ }
664
+ function createJsxFunctions(resolveStyle2) {
665
+ function jsx2(type, props, key) {
666
+ return processElement(resolveStyle2, type, props, key, false);
667
+ }
668
+ function jsxs2(type, props, key) {
669
+ return processElement(resolveStyle2, type, props, key, true);
670
+ }
671
+ return { jsx: jsx2, jsxs: jsxs2 };
672
+ }
673
+
674
+ // src/nativeBridge.ts
675
+ var import_react_native2 = require("react-native");
676
+ var import_theme = require("./theme");
677
+ var import_darkModeStore2 = require("./darkModeStore");
678
+
598
679
  // src/jsEngine/shared.ts
599
680
  function decl(property, value) {
600
681
  return { property, value };
@@ -625,11 +706,42 @@ function resolveNegatableLength(theme, parsed) {
625
706
  if (px === 0) return "0px";
626
707
  return `-${px}px`;
627
708
  }
709
+ function resolvePercent(parsed) {
710
+ if (parsed.negative) return null;
711
+ const value = parsed.value;
712
+ if (value === null) return null;
713
+ if (parsed.isArbitrary) return value;
714
+ const pct = Number(value);
715
+ if (!Number.isFinite(pct) || value.trim() === "") return null;
716
+ return String(pct / 100);
717
+ }
628
718
 
629
719
  // src/jsEngine/resolvers/layout.ts
630
720
  function negateRaw(value, negative) {
631
721
  return negative ? `-${value}` : value;
632
722
  }
723
+ function overflowAxisValue(property, value) {
724
+ switch (value) {
725
+ case "auto":
726
+ case "hidden":
727
+ case "clip":
728
+ case "visible":
729
+ case "scroll":
730
+ return [decl(property, value)];
731
+ default:
732
+ return null;
733
+ }
734
+ }
735
+ function overscrollValue(property, value) {
736
+ switch (value) {
737
+ case "auto":
738
+ case "contain":
739
+ case "none":
740
+ return [decl(property, value)];
741
+ default:
742
+ return null;
743
+ }
744
+ }
633
745
  function resolve(parsed, theme) {
634
746
  switch (parsed.utility) {
635
747
  case "flex":
@@ -676,6 +788,12 @@ function resolve(parsed, theme) {
676
788
  return [decl("justify-content", "space-around")];
677
789
  case "justify-evenly":
678
790
  return [decl("justify-content", "space-evenly")];
791
+ case "justify-normal":
792
+ return [decl("justify-content", "normal")];
793
+ case "justify-stretch":
794
+ return [decl("justify-content", "stretch")];
795
+ case "content-normal":
796
+ return [decl("align-content", "normal")];
679
797
  case "content-start":
680
798
  return [decl("align-content", "flex-start")];
681
799
  case "content-end":
@@ -710,6 +828,18 @@ function resolve(parsed, theme) {
710
828
  return [decl("overflow", "scroll")];
711
829
  case "overflow-visible":
712
830
  return [decl("overflow", "visible")];
831
+ case "overflow-clip":
832
+ return [decl("overflow", "clip")];
833
+ case "overflow-x":
834
+ return parsed.value === null ? null : overflowAxisValue("overflow-x", parsed.value);
835
+ case "overflow-y":
836
+ return parsed.value === null ? null : overflowAxisValue("overflow-y", parsed.value);
837
+ case "overscroll":
838
+ return parsed.value === null ? null : overscrollValue("overscroll-behavior", parsed.value);
839
+ case "overscroll-x":
840
+ return parsed.value === null ? null : overscrollValue("overscroll-behavior-x", parsed.value);
841
+ case "overscroll-y":
842
+ return parsed.value === null ? null : overscrollValue("overscroll-behavior-y", parsed.value);
713
843
  case "static":
714
844
  return [decl("position", "static")];
715
845
  case "relative":
@@ -750,10 +880,43 @@ function resolve(parsed, theme) {
750
880
  const v = resolveNegatableLength(theme, parsed);
751
881
  return v === null ? null : [decl("inset", v)];
752
882
  }
753
- case "aspect-square":
754
- return [decl("aspect-ratio", "1 / 1")];
755
- case "aspect-video":
756
- return [decl("aspect-ratio", "16 / 9")];
883
+ case "inset-x": {
884
+ const v = resolveNegatableLength(theme, parsed);
885
+ return v === null ? null : [decl("left", v), decl("right", v)];
886
+ }
887
+ case "inset-y": {
888
+ const v = resolveNegatableLength(theme, parsed);
889
+ return v === null ? null : [decl("top", v), decl("bottom", v)];
890
+ }
891
+ // Logical inset — just a different CSS property name, same reasoning
892
+ // as Rust's layout.rs (no direction-tracking logic needed here).
893
+ case "start": {
894
+ const v = resolveNegatableLength(theme, parsed);
895
+ return v === null ? null : [decl("inset-inline-start", v)];
896
+ }
897
+ case "end": {
898
+ const v = resolveNegatableLength(theme, parsed);
899
+ return v === null ? null : [decl("inset-inline-end", v)];
900
+ }
901
+ // "aspect-" is a registered VALUE_PREFIXES entry (parser.ts), so
902
+ // "aspect-square"/"aspect-video"/"aspect-auto"/arbitrary all arrive
903
+ // here as utility="aspect" + a value, mirroring layout.rs's own
904
+ // "aspect" arm.
905
+ case "aspect": {
906
+ const value = parsed.value;
907
+ if (value === null) return null;
908
+ if (parsed.isArbitrary) return [decl("aspect-ratio", value)];
909
+ switch (value) {
910
+ case "square":
911
+ return [decl("aspect-ratio", "1 / 1")];
912
+ case "video":
913
+ return [decl("aspect-ratio", "16 / 9")];
914
+ case "auto":
915
+ return [decl("aspect-ratio", "auto")];
916
+ default:
917
+ return null;
918
+ }
919
+ }
757
920
  default:
758
921
  return null;
759
922
  }
@@ -1280,6 +1443,16 @@ function textSize(key) {
1280
1443
  return "1.875rem";
1281
1444
  case "4xl":
1282
1445
  return "2.25rem";
1446
+ case "5xl":
1447
+ return "3rem";
1448
+ case "6xl":
1449
+ return "3.75rem";
1450
+ case "7xl":
1451
+ return "4.5rem";
1452
+ case "8xl":
1453
+ return "6rem";
1454
+ case "9xl":
1455
+ return "8rem";
1283
1456
  default:
1284
1457
  return null;
1285
1458
  }
@@ -1316,6 +1489,12 @@ function textAlign(key) {
1316
1489
  return "right";
1317
1490
  case "justify":
1318
1491
  return "justify";
1492
+ // Logical alignment — same "no direction-tracking logic needed" reasoning
1493
+ // as layout.rs's start/end inset properties.
1494
+ case "start":
1495
+ return "start";
1496
+ case "end":
1497
+ return "end";
1319
1498
  default:
1320
1499
  return null;
1321
1500
  }
@@ -1324,6 +1503,10 @@ function fontWeight(key) {
1324
1503
  switch (key) {
1325
1504
  case "thin":
1326
1505
  return "100";
1506
+ case "extralight":
1507
+ return "200";
1508
+ case "light":
1509
+ return "300";
1327
1510
  case "normal":
1328
1511
  return "400";
1329
1512
  case "medium":
@@ -1334,6 +1517,22 @@ function fontWeight(key) {
1334
1517
  return "700";
1335
1518
  case "extrabold":
1336
1519
  return "800";
1520
+ case "black":
1521
+ return "900";
1522
+ default:
1523
+ return null;
1524
+ }
1525
+ }
1526
+ function fontFamilyValue(theme, key) {
1527
+ const fromTheme = theme.fontFamily?.[key];
1528
+ if (fromTheme !== void 0) return fromTheme;
1529
+ switch (key) {
1530
+ case "sans":
1531
+ return 'ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"';
1532
+ case "serif":
1533
+ return 'ui-serif, Georgia, Cambria, "Times New Roman", Times, serif';
1534
+ case "mono":
1535
+ return 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace';
1337
1536
  default:
1338
1537
  return null;
1339
1538
  }
@@ -1376,12 +1575,21 @@ function nativeShadowDeclarations(parsed) {
1376
1575
  }
1377
1576
 
1378
1577
  // src/jsEngine/resolveUtilityNative.ts
1379
- function resolveTypographyNative(parsed) {
1578
+ function firstFontName(stack) {
1579
+ const first = stack.split(",")[0] ?? stack;
1580
+ return first.trim().replace(/^["']|["']$/g, "");
1581
+ }
1582
+ function resolveTypographyNative(parsed, theme) {
1380
1583
  switch (parsed.utility) {
1381
1584
  case "font": {
1382
1585
  if (parsed.value === null) return null;
1586
+ if (parsed.isArbitrary) {
1587
+ return [decl("font-family", firstFontName(parsed.value))];
1588
+ }
1383
1589
  const w = fontWeight(parsed.value);
1384
- return w === null ? null : [decl("font-weight", w)];
1590
+ if (w !== null) return [decl("font-weight", w)];
1591
+ const family = fontFamilyValue(theme, parsed.value);
1592
+ return family === null ? null : [decl("font-family", firstFontName(family))];
1385
1593
  }
1386
1594
  case "uppercase":
1387
1595
  return [decl("text-transform", "uppercase")];
@@ -1441,8 +1649,13 @@ function resolveColorNative(parsed, theme) {
1441
1649
  return null;
1442
1650
  }
1443
1651
  }
1652
+ function resolveOpacityNative(parsed) {
1653
+ if (parsed.utility !== "opacity") return null;
1654
+ const v = resolvePercent(parsed);
1655
+ return v === null ? null : [decl("opacity", v)];
1656
+ }
1444
1657
  function resolveUtilityNative(parsed, theme) {
1445
- return resolveFlex(parsed, false) ?? resolve(parsed, theme) ?? resolve2(parsed, theme) ?? resolve3(parsed, theme) ?? resolveColorNative(parsed, theme) ?? resolveLeadingTrackingNative(parsed) ?? resolveTypographyNative(parsed) ?? nativeShadowDeclarations(parsed);
1658
+ return resolveFlex(parsed, false) ?? resolve(parsed, theme) ?? resolve2(parsed, theme) ?? resolve3(parsed, theme) ?? resolveColorNative(parsed, theme) ?? resolveLeadingTrackingNative(parsed) ?? resolveTypographyNative(parsed, theme) ?? resolveOpacityNative(parsed) ?? nativeShadowDeclarations(parsed);
1446
1659
  }
1447
1660
 
1448
1661
  // src/jsEngine/resolveStyle.ts
@@ -1499,6 +1712,7 @@ var NUMERIC_LENGTH_PROPS = /* @__PURE__ */ new Set([
1499
1712
  "shadow-opacity",
1500
1713
  "shadow-radius",
1501
1714
  "elevation",
1715
+ "opacity",
1502
1716
  // Per-side border width + per-corner radius — see resolvers/border.ts's
1503
1717
  // new borderSideValue/borderAxisValue/resolveRadiusSide additions; RN's
1504
1718
  // style system wants plain numbers for these exactly like the generic
@@ -1586,11 +1800,11 @@ function resolveStyle(classString, pressed = false) {
1586
1800
  const width = import_react_native2.Dimensions.get("window").width;
1587
1801
  const KbachModule = import_react_native2.TurboModuleRegistry.get("KbachModule");
1588
1802
  if (!KbachModule) {
1589
- const { style: style2, warnings: warnings2 } = resolveStyleJsWithWarnings(classString, (0, import_theme2.getTheme)(), colorScheme, pressed, width);
1803
+ const { style: style2, warnings: warnings2 } = resolveStyleJsWithWarnings(classString, (0, import_theme.getTheme)(), colorScheme, pressed, width);
1590
1804
  warnIfDev(classString, warnings2);
1591
1805
  return style2;
1592
1806
  }
1593
- const json = KbachModule.resolveStyle(classString, (0, import_theme2.getThemeJson)(), colorScheme, pressed, width);
1807
+ const json = KbachModule.resolveStyle(classString, (0, import_theme.getThemeJson)(), colorScheme, pressed, width);
1594
1808
  const style = JSON.parse(json);
1595
1809
  const warnings = style.__kbachWarnings;
1596
1810
  if (warnings !== void 0) {