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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,13 +9,13 @@ import {
9
9
  subscribeDynamicTokens,
10
10
  subscribeGlobalDarkMode,
11
11
  toggleGlobalDarkMode
12
- } from "./chunk-45GOGUHJ.mjs";
12
+ } from "./chunk-TS2EEVOE.mjs";
13
13
  import {
14
14
  defaultTheme,
15
15
  getTheme,
16
16
  resolveClassName,
17
17
  setTheme
18
- } from "./chunk-OGFB3OXS.mjs";
18
+ } from "./chunk-AG7ZQ2K4.mjs";
19
19
 
20
20
  // src/config.ts
21
21
  function parseHexRgb(hex) {
@@ -31,7 +31,6 @@ var import_react = require("react");
31
31
  var import_react_native = require("react-native");
32
32
  var import_darkModeStore = require("./darkModeStore");
33
33
  var import_dynamicTokens = require("./dynamicTokens");
34
- var import_theme = require("./theme");
35
34
 
36
35
  // src/jsEngine/calc.ts
37
36
  function reduceConstantMath(raw) {
@@ -207,157 +206,6 @@ function resolvePercentRelativeCalc(basisPx, calc) {
207
206
  return basisPx * calc.percentCoefficient / 100 + calc.constantPx;
208
207
  }
209
208
 
210
- // src/jsxRuntimeCore.ts
211
- var DYNAMIC_TOKEN_MATCH_RE = /var\(--([a-zA-Z0-9-]+)\)/g;
212
- function substituteDynamicTokens(classStrRaw) {
213
- if (!classStrRaw.includes("var(--")) return classStrRaw;
214
- return classStrRaw.replace(DYNAMIC_TOKEN_MATCH_RE, (whole, name) => {
215
- const value = (0, import_dynamicTokens.getDynamicToken)(name);
216
- return value ?? whole;
217
- });
218
- }
219
- var PERCENT_RELATIVE_CALC_HINT_RE = /[wh]-\[calc\([^)]*%[^)]*\)\]/;
220
- function extractPercentRelativeCalcs(classStrRaw) {
221
- const found = [];
222
- for (const token of classStrRaw.split(/\s+/)) {
223
- const parsed = parsePercentRelativeCalc(token);
224
- if (parsed) found.push(parsed);
225
- }
226
- return found;
227
- }
228
- function stripPercentRelativeCalcTokens(classStrRaw) {
229
- return classStrRaw.split(/\s+/).filter((token) => token && parsePercentRelativeCalc(token) === null).join(" ");
230
- }
231
- function makeElement(isStaticChildren, type, props, key) {
232
- return (isStaticChildren ? import_jsx_runtime.jsxs : import_jsx_runtime.jsx)(type, props, key);
233
- }
234
- function resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, pressed, layoutOverrides) {
235
- const cleaned = stripPercentRelativeCalcTokens(substituteDynamicTokens(classStrRaw));
236
- const resolved = resolveStyle2(cleaned, pressed);
237
- if (layoutOverrides) {
238
- Object.assign(resolved, layoutOverrides);
239
- }
240
- if (userStyle === void 0) {
241
- return resolved;
242
- }
243
- if (typeof userStyle === "function") {
244
- return [resolved, userStyle({ pressed })];
245
- }
246
- return [resolved, userStyle];
247
- }
248
- var DARK_MODIFIER_RE = /(^|\s)dark:/;
249
- var BREAKPOINT_MODIFIER_RE = /(^|\s)(sm|md|lg|xl|2xl):/;
250
- var BREAKPOINT_MODIFIER_MATCH_RE = /(?:^|\s)(sm|md|lg|xl|2xl):/g;
251
- function darkModeKeySuffix(classStrRaw) {
252
- return DARK_MODIFIER_RE.test(classStrRaw) ? `:kb-dark-${(0, import_darkModeStore.getGlobalDarkMode)()}` : "";
253
- }
254
- function breakpointKeySuffix(classStrRaw, width) {
255
- const matches = classStrRaw.match(BREAKPOINT_MODIFIER_MATCH_RE);
256
- if (!matches) {
257
- return "";
258
- }
259
- const screens = (0, import_theme.getTheme)().screens;
260
- const present = Array.from(new Set(matches.map((m) => m.trim().slice(0, -1))));
261
- const state = present.map((name) => screens[name] !== void 0 && width >= screens[name] ? "1" : "0").join("");
262
- return `:kb-bp-${state}`;
263
- }
264
- function dynamicTokenKeySuffix(classStrRaw) {
265
- const matches = classStrRaw.match(DYNAMIC_TOKEN_MATCH_RE);
266
- if (!matches) return "";
267
- const values = matches.map((m) => (0, import_dynamicTokens.getDynamicToken)(m.slice("var(--".length, -1)) ?? "");
268
- return `:kb-dt-${values.join("|")}`;
269
- }
270
- function percentCalcKeySuffix(percentCalcs, measuredBasis) {
271
- if (percentCalcs.length === 0) return "";
272
- const values = percentCalcs.map((calc) => {
273
- const basis = measuredBasis?.[calc.property];
274
- return basis === void 0 ? "pending" : resolvePercentRelativeCalc(basis, calc);
275
- });
276
- return `:kb-pc-${values.join("|")}`;
277
- }
278
- function ReactiveElement({
279
- hostType,
280
- hostRest,
281
- classStrRaw,
282
- userStyle,
283
- resolveStyle: resolveStyle2,
284
- elementKey,
285
- isStaticChildren
286
- }) {
287
- (0, import_react.useSyncExternalStore)(import_darkModeStore.subscribeGlobalDarkMode, import_darkModeStore.getGlobalDarkMode);
288
- (0, import_react.useSyncExternalStore)(import_dynamicTokens.subscribeDynamicTokens, import_dynamicTokens.getDynamicTokensVersion);
289
- const { width } = (0, import_react_native.useWindowDimensions)();
290
- const [measuredBasis, setMeasuredBasis] = (0, import_react.useState)(null);
291
- const measure = (0, import_react.useCallback)((e) => {
292
- const { width: w, height: h } = e.nativeEvent.layout;
293
- setMeasuredBasis((prev) => prev && prev.width === w && prev.height === h ? prev : { width: w, height: h });
294
- }, []);
295
- const percentCalcs = extractPercentRelativeCalcs(classStrRaw);
296
- let layoutOverrides;
297
- let hostRestWithLayout = hostRest;
298
- if (percentCalcs.length > 0) {
299
- layoutOverrides = {};
300
- for (const calc of percentCalcs) {
301
- const basis = measuredBasis?.[calc.property];
302
- layoutOverrides[calc.property] = basis === void 0 ? "100%" : resolvePercentRelativeCalc(basis, calc);
303
- }
304
- const userOnLayout = hostRest.onLayout;
305
- hostRestWithLayout = {
306
- ...hostRest,
307
- onLayout: userOnLayout ? (e) => {
308
- measure(e);
309
- userOnLayout(e);
310
- } : measure
311
- };
312
- }
313
- const finalStyle = hostType === import_react_native.Pressable ? (state) => resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, state.pressed, layoutOverrides) : resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, false, layoutOverrides);
314
- const suffix = darkModeKeySuffix(classStrRaw) + breakpointKeySuffix(classStrRaw, width) + dynamicTokenKeySuffix(classStrRaw) + percentCalcKeySuffix(percentCalcs, measuredBasis);
315
- const finalKey = suffix ? `${elementKey ?? ""}${suffix}` : elementKey;
316
- return makeElement(isStaticChildren, hostType, { ...hostRestWithLayout, style: finalStyle }, finalKey);
317
- }
318
- function processElement(resolveStyle2, type, rawProps, key, isStaticChildren) {
319
- if (type === null || typeof type === "symbol" || !rawProps) {
320
- return makeElement(isStaticChildren, type, rawProps ?? {}, key);
321
- }
322
- const { className: classStrRaw, style: userStyle, ...rest } = rawProps;
323
- if (typeof classStrRaw !== "string") {
324
- return makeElement(isStaticChildren, type, rawProps, key);
325
- }
326
- if (DARK_MODIFIER_RE.test(classStrRaw) || BREAKPOINT_MODIFIER_RE.test(classStrRaw) || classStrRaw.includes("var(--") || PERCENT_RELATIVE_CALC_HINT_RE.test(classStrRaw)) {
327
- return (0, import_jsx_runtime.jsx)(
328
- ReactiveElement,
329
- { hostType: type, hostRest: rest, classStrRaw, userStyle, resolveStyle: resolveStyle2, elementKey: key, isStaticChildren },
330
- key
331
- );
332
- }
333
- const finalStyle = type === import_react_native.Pressable ? (state) => resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, state.pressed) : resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, false);
334
- return makeElement(isStaticChildren, type, { ...rest, style: finalStyle }, key);
335
- }
336
- function createJsxFunctions(resolveStyle2) {
337
- function jsx2(type, props, key) {
338
- return processElement(resolveStyle2, type, props, key, false);
339
- }
340
- function jsxs2(type, props, key) {
341
- return processElement(resolveStyle2, type, props, key, true);
342
- }
343
- return { jsx: jsx2, jsxs: jsxs2 };
344
- }
345
- function createJsxDEV(jsx2, jsxs2) {
346
- return function jsxDEV2(type, props, key, isStaticChildren, source, self) {
347
- const element = (isStaticChildren ? jsxs2 : jsx2)(type, props, key);
348
- if (source && element && typeof element === "object" && Object.isExtensible(element)) {
349
- element._source = source;
350
- element._self = self;
351
- }
352
- return element;
353
- };
354
- }
355
-
356
- // src/nativeBridge.ts
357
- var import_react_native2 = require("react-native");
358
- var import_theme2 = require("./theme");
359
- var import_darkModeStore2 = require("./darkModeStore");
360
-
361
209
  // src/jsEngine/parser.ts
362
210
  var VALUE_PREFIXES = [
363
211
  "bg-opacity-",
@@ -445,11 +293,21 @@ var VALUE_PREFIXES = [
445
293
  "tracking-",
446
294
  "font-",
447
295
  "z-",
296
+ "inset-x-",
297
+ "inset-y-",
448
298
  "inset-",
449
299
  "top-",
450
300
  "right-",
451
301
  "bottom-",
452
302
  "left-",
303
+ "start-",
304
+ "end-",
305
+ "overflow-x-",
306
+ "overflow-y-",
307
+ "overscroll-x-",
308
+ "overscroll-y-",
309
+ "overscroll-",
310
+ "aspect-",
453
311
  "divide-color-",
454
312
  "space-x-",
455
313
  "space-y-",
@@ -604,6 +462,189 @@ function parseClass(token) {
604
462
  };
605
463
  }
606
464
 
465
+ // src/jsxRuntimeCore.ts
466
+ var DYNAMIC_TOKEN_MATCH_RE = /var\(--([a-zA-Z0-9-]+)\)/g;
467
+ function substituteDynamicTokens(classStrRaw) {
468
+ if (!classStrRaw.includes("var(--")) return classStrRaw;
469
+ return classStrRaw.replace(DYNAMIC_TOKEN_MATCH_RE, (whole, name) => {
470
+ const value = (0, import_dynamicTokens.getDynamicToken)(name);
471
+ return value ?? whole;
472
+ });
473
+ }
474
+ var PERCENT_RELATIVE_CALC_HINT_RE = /[wh]-\[calc\([^)]*%[^)]*\)\]/;
475
+ function extractPercentRelativeCalcs(classStrRaw) {
476
+ const found = [];
477
+ for (const token of classStrRaw.split(/\s+/)) {
478
+ const parsed = parsePercentRelativeCalc(token);
479
+ if (parsed) found.push(parsed);
480
+ }
481
+ return found;
482
+ }
483
+ function stripPercentRelativeCalcTokens(classStrRaw) {
484
+ return classStrRaw.split(/\s+/).filter((token) => token && parsePercentRelativeCalc(token) === null).join(" ");
485
+ }
486
+ var STATE_MODIFIER_NAMES = /* @__PURE__ */ new Set(["hover", "focus", "disabled"]);
487
+ var STATE_MODIFIER_HINT_RE = /(^|\s|:)(hover|focus|disabled):/;
488
+ function stripModifiers(parts, namesToStrip) {
489
+ const utility = parts[parts.length - 1] ?? "";
490
+ const modifiers = parts.slice(0, -1).filter((m) => !namesToStrip.has(m));
491
+ return [...modifiers, utility].join(":");
492
+ }
493
+ function substituteStateModifiers(classStrRaw, states) {
494
+ if (!STATE_MODIFIER_HINT_RE.test(classStrRaw)) return classStrRaw;
495
+ const kept = [];
496
+ for (const token of classStrRaw.split(/\s+/)) {
497
+ if (!token) continue;
498
+ const parts = splitRespectingBrackets(token);
499
+ const modifiers = parts.slice(0, -1);
500
+ const required = modifiers.filter((m) => STATE_MODIFIER_NAMES.has(m));
501
+ if (required.length === 0) {
502
+ kept.push(token);
503
+ continue;
504
+ }
505
+ if (required.every((m) => states[m])) {
506
+ kept.push(stripModifiers(parts, STATE_MODIFIER_NAMES));
507
+ }
508
+ }
509
+ return kept.join(" ");
510
+ }
511
+ function makeElement(isStaticChildren, type, props, key) {
512
+ return (isStaticChildren ? import_jsx_runtime.jsxs : import_jsx_runtime.jsx)(type, props, key);
513
+ }
514
+ function resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, pressed, layoutOverrides, states = { hover: false, focus: false, disabled: false }) {
515
+ const stateResolved = substituteStateModifiers(classStrRaw, states);
516
+ const cleaned = stripPercentRelativeCalcTokens(substituteDynamicTokens(stateResolved));
517
+ const resolved = resolveStyle2(cleaned, pressed);
518
+ if (layoutOverrides) {
519
+ Object.assign(resolved, layoutOverrides);
520
+ }
521
+ if (userStyle === void 0) {
522
+ return resolved;
523
+ }
524
+ if (typeof userStyle === "function") {
525
+ return [resolved, userStyle({ pressed })];
526
+ }
527
+ return [resolved, userStyle];
528
+ }
529
+ var DARK_MODIFIER_RE = /(^|\s|:)dark:/;
530
+ var BREAKPOINT_MODIFIER_RE = /(^|\s|:)(sm|md|lg|xl|2xl):/;
531
+ var HOVER_MODIFIER_RE = /(^|\s|:)hover:/;
532
+ var FOCUS_MODIFIER_RE = /(^|\s|:)focus:/;
533
+ function ReactiveElement({
534
+ hostType,
535
+ hostRest,
536
+ classStrRaw,
537
+ userStyle,
538
+ resolveStyle: resolveStyle2,
539
+ elementKey,
540
+ isStaticChildren
541
+ }) {
542
+ (0, import_react.useSyncExternalStore)(import_darkModeStore.subscribeGlobalDarkMode, import_darkModeStore.getGlobalDarkMode);
543
+ (0, import_react.useSyncExternalStore)(import_dynamicTokens.subscribeDynamicTokens, import_dynamicTokens.getDynamicTokensVersion);
544
+ (0, import_react_native.useWindowDimensions)();
545
+ const [measuredBasis, setMeasuredBasis] = (0, import_react.useState)(null);
546
+ const measure = (0, import_react.useCallback)((e) => {
547
+ const { width: w, height: h } = e.nativeEvent.layout;
548
+ setMeasuredBasis((prev) => prev && prev.width === w && prev.height === h ? prev : { width: w, height: h });
549
+ }, []);
550
+ const [isHovered, setIsHovered] = (0, import_react.useState)(false);
551
+ const [isFocused, setIsFocused] = (0, import_react.useState)(false);
552
+ const percentCalcs = extractPercentRelativeCalcs(classStrRaw);
553
+ let layoutOverrides;
554
+ let hostRestWithLayout = hostRest;
555
+ if (percentCalcs.length > 0) {
556
+ layoutOverrides = {};
557
+ for (const calc of percentCalcs) {
558
+ const basis = measuredBasis?.[calc.property];
559
+ layoutOverrides[calc.property] = basis === void 0 ? "100%" : resolvePercentRelativeCalc(basis, calc);
560
+ }
561
+ const userOnLayout = hostRest.onLayout;
562
+ hostRestWithLayout = {
563
+ ...hostRest,
564
+ onLayout: userOnLayout ? (e) => {
565
+ measure(e);
566
+ userOnLayout(e);
567
+ } : measure
568
+ };
569
+ }
570
+ if (HOVER_MODIFIER_RE.test(classStrRaw)) {
571
+ const userOnHoverIn = hostRestWithLayout.onHoverIn;
572
+ const userOnHoverOut = hostRestWithLayout.onHoverOut;
573
+ hostRestWithLayout = {
574
+ ...hostRestWithLayout,
575
+ onHoverIn: (e) => {
576
+ setIsHovered(true);
577
+ userOnHoverIn?.(e);
578
+ },
579
+ onHoverOut: (e) => {
580
+ setIsHovered(false);
581
+ userOnHoverOut?.(e);
582
+ }
583
+ };
584
+ }
585
+ if (FOCUS_MODIFIER_RE.test(classStrRaw)) {
586
+ const userOnFocus = hostRestWithLayout.onFocus;
587
+ const userOnBlur = hostRestWithLayout.onBlur;
588
+ hostRestWithLayout = {
589
+ ...hostRestWithLayout,
590
+ onFocus: (e) => {
591
+ setIsFocused(true);
592
+ userOnFocus?.(e);
593
+ },
594
+ onBlur: (e) => {
595
+ setIsFocused(false);
596
+ userOnBlur?.(e);
597
+ }
598
+ };
599
+ }
600
+ const states = { hover: isHovered, focus: isFocused, disabled: hostRest.disabled === true };
601
+ const finalStyle = hostType === import_react_native.Pressable ? (state) => resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, state.pressed, layoutOverrides, states) : resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, false, layoutOverrides, states);
602
+ return makeElement(isStaticChildren, hostType, { ...hostRestWithLayout, style: finalStyle }, elementKey);
603
+ }
604
+ function processElement(resolveStyle2, type, rawProps, key, isStaticChildren) {
605
+ if (type === null || typeof type === "symbol" || !rawProps) {
606
+ return makeElement(isStaticChildren, type, rawProps ?? {}, key);
607
+ }
608
+ const { className: classStrRaw, style: userStyle, ...rest } = rawProps;
609
+ if (typeof classStrRaw !== "string") {
610
+ return makeElement(isStaticChildren, type, rawProps, key);
611
+ }
612
+ 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)) {
613
+ return (0, import_jsx_runtime.jsx)(
614
+ ReactiveElement,
615
+ { hostType: type, hostRest: rest, classStrRaw, userStyle, resolveStyle: resolveStyle2, elementKey: key, isStaticChildren },
616
+ key
617
+ );
618
+ }
619
+ const staticStates = { hover: false, focus: false, disabled: rest.disabled === true };
620
+ 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);
621
+ return makeElement(isStaticChildren, type, { ...rest, style: finalStyle }, key);
622
+ }
623
+ function createJsxFunctions(resolveStyle2) {
624
+ function jsx2(type, props, key) {
625
+ return processElement(resolveStyle2, type, props, key, false);
626
+ }
627
+ function jsxs2(type, props, key) {
628
+ return processElement(resolveStyle2, type, props, key, true);
629
+ }
630
+ return { jsx: jsx2, jsxs: jsxs2 };
631
+ }
632
+ function createJsxDEV(jsx2, jsxs2) {
633
+ return function jsxDEV2(type, props, key, isStaticChildren, source, self) {
634
+ const element = (isStaticChildren ? jsxs2 : jsx2)(type, props, key);
635
+ if (source && element && typeof element === "object" && Object.isExtensible(element)) {
636
+ element._source = source;
637
+ element._self = self;
638
+ }
639
+ return element;
640
+ };
641
+ }
642
+
643
+ // src/nativeBridge.ts
644
+ var import_react_native2 = require("react-native");
645
+ var import_theme = require("./theme");
646
+ var import_darkModeStore2 = require("./darkModeStore");
647
+
607
648
  // src/jsEngine/shared.ts
608
649
  function decl(property, value) {
609
650
  return { property, value };
@@ -634,11 +675,42 @@ function resolveNegatableLength(theme, parsed) {
634
675
  if (px === 0) return "0px";
635
676
  return `-${px}px`;
636
677
  }
678
+ function resolvePercent(parsed) {
679
+ if (parsed.negative) return null;
680
+ const value = parsed.value;
681
+ if (value === null) return null;
682
+ if (parsed.isArbitrary) return value;
683
+ const pct = Number(value);
684
+ if (!Number.isFinite(pct) || value.trim() === "") return null;
685
+ return String(pct / 100);
686
+ }
637
687
 
638
688
  // src/jsEngine/resolvers/layout.ts
639
689
  function negateRaw(value, negative) {
640
690
  return negative ? `-${value}` : value;
641
691
  }
692
+ function overflowAxisValue(property, value) {
693
+ switch (value) {
694
+ case "auto":
695
+ case "hidden":
696
+ case "clip":
697
+ case "visible":
698
+ case "scroll":
699
+ return [decl(property, value)];
700
+ default:
701
+ return null;
702
+ }
703
+ }
704
+ function overscrollValue(property, value) {
705
+ switch (value) {
706
+ case "auto":
707
+ case "contain":
708
+ case "none":
709
+ return [decl(property, value)];
710
+ default:
711
+ return null;
712
+ }
713
+ }
642
714
  function resolve(parsed, theme) {
643
715
  switch (parsed.utility) {
644
716
  case "flex":
@@ -685,6 +757,12 @@ function resolve(parsed, theme) {
685
757
  return [decl("justify-content", "space-around")];
686
758
  case "justify-evenly":
687
759
  return [decl("justify-content", "space-evenly")];
760
+ case "justify-normal":
761
+ return [decl("justify-content", "normal")];
762
+ case "justify-stretch":
763
+ return [decl("justify-content", "stretch")];
764
+ case "content-normal":
765
+ return [decl("align-content", "normal")];
688
766
  case "content-start":
689
767
  return [decl("align-content", "flex-start")];
690
768
  case "content-end":
@@ -719,6 +797,18 @@ function resolve(parsed, theme) {
719
797
  return [decl("overflow", "scroll")];
720
798
  case "overflow-visible":
721
799
  return [decl("overflow", "visible")];
800
+ case "overflow-clip":
801
+ return [decl("overflow", "clip")];
802
+ case "overflow-x":
803
+ return parsed.value === null ? null : overflowAxisValue("overflow-x", parsed.value);
804
+ case "overflow-y":
805
+ return parsed.value === null ? null : overflowAxisValue("overflow-y", parsed.value);
806
+ case "overscroll":
807
+ return parsed.value === null ? null : overscrollValue("overscroll-behavior", parsed.value);
808
+ case "overscroll-x":
809
+ return parsed.value === null ? null : overscrollValue("overscroll-behavior-x", parsed.value);
810
+ case "overscroll-y":
811
+ return parsed.value === null ? null : overscrollValue("overscroll-behavior-y", parsed.value);
722
812
  case "static":
723
813
  return [decl("position", "static")];
724
814
  case "relative":
@@ -759,10 +849,43 @@ function resolve(parsed, theme) {
759
849
  const v = resolveNegatableLength(theme, parsed);
760
850
  return v === null ? null : [decl("inset", v)];
761
851
  }
762
- case "aspect-square":
763
- return [decl("aspect-ratio", "1 / 1")];
764
- case "aspect-video":
765
- return [decl("aspect-ratio", "16 / 9")];
852
+ case "inset-x": {
853
+ const v = resolveNegatableLength(theme, parsed);
854
+ return v === null ? null : [decl("left", v), decl("right", v)];
855
+ }
856
+ case "inset-y": {
857
+ const v = resolveNegatableLength(theme, parsed);
858
+ return v === null ? null : [decl("top", v), decl("bottom", v)];
859
+ }
860
+ // Logical inset — just a different CSS property name, same reasoning
861
+ // as Rust's layout.rs (no direction-tracking logic needed here).
862
+ case "start": {
863
+ const v = resolveNegatableLength(theme, parsed);
864
+ return v === null ? null : [decl("inset-inline-start", v)];
865
+ }
866
+ case "end": {
867
+ const v = resolveNegatableLength(theme, parsed);
868
+ return v === null ? null : [decl("inset-inline-end", v)];
869
+ }
870
+ // "aspect-" is a registered VALUE_PREFIXES entry (parser.ts), so
871
+ // "aspect-square"/"aspect-video"/"aspect-auto"/arbitrary all arrive
872
+ // here as utility="aspect" + a value, mirroring layout.rs's own
873
+ // "aspect" arm.
874
+ case "aspect": {
875
+ const value = parsed.value;
876
+ if (value === null) return null;
877
+ if (parsed.isArbitrary) return [decl("aspect-ratio", value)];
878
+ switch (value) {
879
+ case "square":
880
+ return [decl("aspect-ratio", "1 / 1")];
881
+ case "video":
882
+ return [decl("aspect-ratio", "16 / 9")];
883
+ case "auto":
884
+ return [decl("aspect-ratio", "auto")];
885
+ default:
886
+ return null;
887
+ }
888
+ }
766
889
  default:
767
890
  return null;
768
891
  }
@@ -1289,6 +1412,16 @@ function textSize(key) {
1289
1412
  return "1.875rem";
1290
1413
  case "4xl":
1291
1414
  return "2.25rem";
1415
+ case "5xl":
1416
+ return "3rem";
1417
+ case "6xl":
1418
+ return "3.75rem";
1419
+ case "7xl":
1420
+ return "4.5rem";
1421
+ case "8xl":
1422
+ return "6rem";
1423
+ case "9xl":
1424
+ return "8rem";
1292
1425
  default:
1293
1426
  return null;
1294
1427
  }
@@ -1325,6 +1458,12 @@ function textAlign(key) {
1325
1458
  return "right";
1326
1459
  case "justify":
1327
1460
  return "justify";
1461
+ // Logical alignment — same "no direction-tracking logic needed" reasoning
1462
+ // as layout.rs's start/end inset properties.
1463
+ case "start":
1464
+ return "start";
1465
+ case "end":
1466
+ return "end";
1328
1467
  default:
1329
1468
  return null;
1330
1469
  }
@@ -1333,6 +1472,10 @@ function fontWeight(key) {
1333
1472
  switch (key) {
1334
1473
  case "thin":
1335
1474
  return "100";
1475
+ case "extralight":
1476
+ return "200";
1477
+ case "light":
1478
+ return "300";
1336
1479
  case "normal":
1337
1480
  return "400";
1338
1481
  case "medium":
@@ -1343,6 +1486,22 @@ function fontWeight(key) {
1343
1486
  return "700";
1344
1487
  case "extrabold":
1345
1488
  return "800";
1489
+ case "black":
1490
+ return "900";
1491
+ default:
1492
+ return null;
1493
+ }
1494
+ }
1495
+ function fontFamilyValue(theme, key) {
1496
+ const fromTheme = theme.fontFamily?.[key];
1497
+ if (fromTheme !== void 0) return fromTheme;
1498
+ switch (key) {
1499
+ case "sans":
1500
+ return 'ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"';
1501
+ case "serif":
1502
+ return 'ui-serif, Georgia, Cambria, "Times New Roman", Times, serif';
1503
+ case "mono":
1504
+ return 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace';
1346
1505
  default:
1347
1506
  return null;
1348
1507
  }
@@ -1385,12 +1544,21 @@ function nativeShadowDeclarations(parsed) {
1385
1544
  }
1386
1545
 
1387
1546
  // src/jsEngine/resolveUtilityNative.ts
1388
- function resolveTypographyNative(parsed) {
1547
+ function firstFontName(stack) {
1548
+ const first = stack.split(",")[0] ?? stack;
1549
+ return first.trim().replace(/^["']|["']$/g, "");
1550
+ }
1551
+ function resolveTypographyNative(parsed, theme) {
1389
1552
  switch (parsed.utility) {
1390
1553
  case "font": {
1391
1554
  if (parsed.value === null) return null;
1555
+ if (parsed.isArbitrary) {
1556
+ return [decl("font-family", firstFontName(parsed.value))];
1557
+ }
1392
1558
  const w = fontWeight(parsed.value);
1393
- return w === null ? null : [decl("font-weight", w)];
1559
+ if (w !== null) return [decl("font-weight", w)];
1560
+ const family = fontFamilyValue(theme, parsed.value);
1561
+ return family === null ? null : [decl("font-family", firstFontName(family))];
1394
1562
  }
1395
1563
  case "uppercase":
1396
1564
  return [decl("text-transform", "uppercase")];
@@ -1450,8 +1618,13 @@ function resolveColorNative(parsed, theme) {
1450
1618
  return null;
1451
1619
  }
1452
1620
  }
1621
+ function resolveOpacityNative(parsed) {
1622
+ if (parsed.utility !== "opacity") return null;
1623
+ const v = resolvePercent(parsed);
1624
+ return v === null ? null : [decl("opacity", v)];
1625
+ }
1453
1626
  function resolveUtilityNative(parsed, theme) {
1454
- return resolveFlex(parsed, false) ?? resolve(parsed, theme) ?? resolve2(parsed, theme) ?? resolve3(parsed, theme) ?? resolveColorNative(parsed, theme) ?? resolveLeadingTrackingNative(parsed) ?? resolveTypographyNative(parsed) ?? nativeShadowDeclarations(parsed);
1627
+ 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);
1455
1628
  }
1456
1629
 
1457
1630
  // src/jsEngine/resolveStyle.ts
@@ -1508,6 +1681,7 @@ var NUMERIC_LENGTH_PROPS = /* @__PURE__ */ new Set([
1508
1681
  "shadow-opacity",
1509
1682
  "shadow-radius",
1510
1683
  "elevation",
1684
+ "opacity",
1511
1685
  // Per-side border width + per-corner radius — see resolvers/border.ts's
1512
1686
  // new borderSideValue/borderAxisValue/resolveRadiusSide additions; RN's
1513
1687
  // style system wants plain numbers for these exactly like the generic
@@ -1595,11 +1769,11 @@ function resolveStyle(classString, pressed = false) {
1595
1769
  const width = import_react_native2.Dimensions.get("window").width;
1596
1770
  const KbachModule = import_react_native2.TurboModuleRegistry.get("KbachModule");
1597
1771
  if (!KbachModule) {
1598
- const { style: style2, warnings: warnings2 } = resolveStyleJsWithWarnings(classString, (0, import_theme2.getTheme)(), colorScheme, pressed, width);
1772
+ const { style: style2, warnings: warnings2 } = resolveStyleJsWithWarnings(classString, (0, import_theme.getTheme)(), colorScheme, pressed, width);
1599
1773
  warnIfDev(classString, warnings2);
1600
1774
  return style2;
1601
1775
  }
1602
- const json = KbachModule.resolveStyle(classString, (0, import_theme2.getThemeJson)(), colorScheme, pressed, width);
1776
+ const json = KbachModule.resolveStyle(classString, (0, import_theme.getThemeJson)(), colorScheme, pressed, width);
1603
1777
  const style = JSON.parse(json);
1604
1778
  const warnings = style.__kbachWarnings;
1605
1779
  if (warnings !== void 0) {