@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.
@@ -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) {
@@ -206,157 +205,46 @@ function parsePercentRelativeCalc(token) {
206
205
  function resolvePercentRelativeCalc(basisPx, calc) {
207
206
  return basisPx * calc.percentCoefficient / 100 + calc.constantPx;
208
207
  }
209
-
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);
208
+ var PERCENT_MIN_MAX_CLAMP_TOKEN_RE = /^(w|h)-\[(min|max|clamp)\(([^)]+)\)\]$/;
209
+ function parseOperand(arg) {
210
+ const trimmed = arg.trim();
211
+ const pct = /^(-?[\d.]+)%$/.exec(trimmed);
212
+ if (pct) {
213
+ const percentCoefficient = Number(pct[1]);
214
+ return Number.isFinite(percentCoefficient) ? { percentCoefficient, constantPx: 0 } : null;
339
215
  }
340
- function jsxs2(type, props, key) {
341
- return processElement(resolveStyle2, type, props, key, true);
342
- }
343
- return { jsx: jsx2, jsxs: jsxs2 };
216
+ const constantPx = reduceConstantMath(`calc(${trimmed})`);
217
+ return constantPx === null ? null : { percentCoefficient: 0, constantPx };
344
218
  }
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;
219
+ function parsePercentRelativeMinMaxClamp(token) {
220
+ const m = PERCENT_MIN_MAX_CLAMP_TOKEN_RE.exec(token);
221
+ if (!m) return null;
222
+ const property = m[1] === "w" ? "width" : "height";
223
+ const kind = m[2];
224
+ const args = splitTopLevelCommas(m[3].replace(/_/g, " "));
225
+ if (kind === "clamp" && args.length !== 3) return null;
226
+ if (kind !== "clamp" && args.length < 1) return null;
227
+ const operands = args.map(parseOperand);
228
+ if (operands.some((o) => o === null)) return null;
229
+ const resolved = operands;
230
+ if (!resolved.some((o) => o.percentCoefficient !== 0)) return null;
231
+ const resolveOperand = (o, basisPx) => basisPx * o.percentCoefficient / 100 + o.constantPx;
232
+ return {
233
+ property,
234
+ resolve(basisPx) {
235
+ const values = resolved.map((o) => resolveOperand(o, basisPx));
236
+ if (kind === "min") return Math.min(...values);
237
+ if (kind === "max") return Math.max(...values);
238
+ const [min, preferred, max] = values;
239
+ return Math.max(min, Math.min(preferred, max));
351
240
  }
352
- return element;
353
241
  };
354
242
  }
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");
243
+ function parsePercentRelativeExpr(token) {
244
+ const calc = parsePercentRelativeCalc(token);
245
+ if (calc) return { property: calc.property, resolve: (basisPx) => resolvePercentRelativeCalc(basisPx, calc) };
246
+ return parsePercentRelativeMinMaxClamp(token);
247
+ }
360
248
 
361
249
  // src/jsEngine/parser.ts
362
250
  var VALUE_PREFIXES = [
@@ -445,11 +333,21 @@ var VALUE_PREFIXES = [
445
333
  "tracking-",
446
334
  "font-",
447
335
  "z-",
336
+ "inset-x-",
337
+ "inset-y-",
448
338
  "inset-",
449
339
  "top-",
450
340
  "right-",
451
341
  "bottom-",
452
342
  "left-",
343
+ "start-",
344
+ "end-",
345
+ "overflow-x-",
346
+ "overflow-y-",
347
+ "overscroll-x-",
348
+ "overscroll-y-",
349
+ "overscroll-",
350
+ "aspect-",
453
351
  "divide-color-",
454
352
  "space-x-",
455
353
  "space-y-",
@@ -604,6 +502,189 @@ function parseClass(token) {
604
502
  };
605
503
  }
606
504
 
505
+ // src/jsxRuntimeCore.ts
506
+ var DYNAMIC_TOKEN_MATCH_RE = /var\(--([a-zA-Z0-9-]+)\)/g;
507
+ function substituteDynamicTokens(classStrRaw) {
508
+ if (!classStrRaw.includes("var(--")) return classStrRaw;
509
+ return classStrRaw.replace(DYNAMIC_TOKEN_MATCH_RE, (whole, name) => {
510
+ const value = (0, import_dynamicTokens.getDynamicToken)(name);
511
+ return value ?? whole;
512
+ });
513
+ }
514
+ var PERCENT_RELATIVE_CALC_HINT_RE = /[wh]-\[(calc|min|max|clamp)\([^)]*%[^)]*\)\]/;
515
+ function extractPercentRelativeCalcs(classStrRaw) {
516
+ const found = [];
517
+ for (const token of classStrRaw.split(/\s+/)) {
518
+ const parsed = parsePercentRelativeExpr(token);
519
+ if (parsed) found.push(parsed);
520
+ }
521
+ return found;
522
+ }
523
+ function stripPercentRelativeCalcTokens(classStrRaw) {
524
+ return classStrRaw.split(/\s+/).filter((token) => token && parsePercentRelativeExpr(token) === null).join(" ");
525
+ }
526
+ var STATE_MODIFIER_NAMES = /* @__PURE__ */ new Set(["hover", "focus", "disabled"]);
527
+ var STATE_MODIFIER_HINT_RE = /(^|\s|:)(hover|focus|disabled):/;
528
+ function stripModifiers(parts, namesToStrip) {
529
+ const utility = parts[parts.length - 1] ?? "";
530
+ const modifiers = parts.slice(0, -1).filter((m) => !namesToStrip.has(m));
531
+ return [...modifiers, utility].join(":");
532
+ }
533
+ function substituteStateModifiers(classStrRaw, states) {
534
+ if (!STATE_MODIFIER_HINT_RE.test(classStrRaw)) return classStrRaw;
535
+ const kept = [];
536
+ for (const token of classStrRaw.split(/\s+/)) {
537
+ if (!token) continue;
538
+ const parts = splitRespectingBrackets(token);
539
+ const modifiers = parts.slice(0, -1);
540
+ const required = modifiers.filter((m) => STATE_MODIFIER_NAMES.has(m));
541
+ if (required.length === 0) {
542
+ kept.push(token);
543
+ continue;
544
+ }
545
+ if (required.every((m) => states[m])) {
546
+ kept.push(stripModifiers(parts, STATE_MODIFIER_NAMES));
547
+ }
548
+ }
549
+ return kept.join(" ");
550
+ }
551
+ function makeElement(isStaticChildren, type, props, key) {
552
+ return (isStaticChildren ? import_jsx_runtime.jsxs : import_jsx_runtime.jsx)(type, props, key);
553
+ }
554
+ function resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, pressed, layoutOverrides, states = { hover: false, focus: false, disabled: false }) {
555
+ const stateResolved = substituteStateModifiers(classStrRaw, states);
556
+ const cleaned = stripPercentRelativeCalcTokens(substituteDynamicTokens(stateResolved));
557
+ const resolved = resolveStyle2(cleaned, pressed);
558
+ if (layoutOverrides) {
559
+ Object.assign(resolved, layoutOverrides);
560
+ }
561
+ if (userStyle === void 0) {
562
+ return resolved;
563
+ }
564
+ if (typeof userStyle === "function") {
565
+ return [resolved, userStyle({ pressed })];
566
+ }
567
+ return [resolved, userStyle];
568
+ }
569
+ var DARK_MODIFIER_RE = /(^|\s|:)dark:/;
570
+ var BREAKPOINT_MODIFIER_RE = /(^|\s|:)(sm|md|lg|xl|2xl):/;
571
+ var HOVER_MODIFIER_RE = /(^|\s|:)hover:/;
572
+ var FOCUS_MODIFIER_RE = /(^|\s|:)focus:/;
573
+ function ReactiveElement({
574
+ hostType,
575
+ hostRest,
576
+ classStrRaw,
577
+ userStyle,
578
+ resolveStyle: resolveStyle2,
579
+ elementKey,
580
+ isStaticChildren
581
+ }) {
582
+ (0, import_react.useSyncExternalStore)(import_darkModeStore.subscribeGlobalDarkMode, import_darkModeStore.getGlobalDarkMode);
583
+ (0, import_react.useSyncExternalStore)(import_dynamicTokens.subscribeDynamicTokens, import_dynamicTokens.getDynamicTokensVersion);
584
+ (0, import_react_native.useWindowDimensions)();
585
+ const [measuredBasis, setMeasuredBasis] = (0, import_react.useState)(null);
586
+ const measure = (0, import_react.useCallback)((e) => {
587
+ const { width: w, height: h } = e.nativeEvent.layout;
588
+ setMeasuredBasis((prev) => prev && prev.width === w && prev.height === h ? prev : { width: w, height: h });
589
+ }, []);
590
+ const [isHovered, setIsHovered] = (0, import_react.useState)(false);
591
+ const [isFocused, setIsFocused] = (0, import_react.useState)(false);
592
+ const percentCalcs = extractPercentRelativeCalcs(classStrRaw);
593
+ let layoutOverrides;
594
+ let hostRestWithLayout = hostRest;
595
+ if (percentCalcs.length > 0) {
596
+ layoutOverrides = {};
597
+ for (const calc of percentCalcs) {
598
+ const basis = measuredBasis?.[calc.property];
599
+ layoutOverrides[calc.property] = basis === void 0 ? "100%" : calc.resolve(basis);
600
+ }
601
+ const userOnLayout = hostRest.onLayout;
602
+ hostRestWithLayout = {
603
+ ...hostRest,
604
+ onLayout: userOnLayout ? (e) => {
605
+ measure(e);
606
+ userOnLayout(e);
607
+ } : measure
608
+ };
609
+ }
610
+ if (HOVER_MODIFIER_RE.test(classStrRaw)) {
611
+ const userOnHoverIn = hostRestWithLayout.onHoverIn;
612
+ const userOnHoverOut = hostRestWithLayout.onHoverOut;
613
+ hostRestWithLayout = {
614
+ ...hostRestWithLayout,
615
+ onHoverIn: (e) => {
616
+ setIsHovered(true);
617
+ userOnHoverIn?.(e);
618
+ },
619
+ onHoverOut: (e) => {
620
+ setIsHovered(false);
621
+ userOnHoverOut?.(e);
622
+ }
623
+ };
624
+ }
625
+ if (FOCUS_MODIFIER_RE.test(classStrRaw)) {
626
+ const userOnFocus = hostRestWithLayout.onFocus;
627
+ const userOnBlur = hostRestWithLayout.onBlur;
628
+ hostRestWithLayout = {
629
+ ...hostRestWithLayout,
630
+ onFocus: (e) => {
631
+ setIsFocused(true);
632
+ userOnFocus?.(e);
633
+ },
634
+ onBlur: (e) => {
635
+ setIsFocused(false);
636
+ userOnBlur?.(e);
637
+ }
638
+ };
639
+ }
640
+ const states = { hover: isHovered, focus: isFocused, disabled: hostRest.disabled === true };
641
+ const finalStyle = hostType === import_react_native.Pressable ? (state) => resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, state.pressed, layoutOverrides, states) : resolvedStyleFor(resolveStyle2, classStrRaw, userStyle, false, layoutOverrides, states);
642
+ return makeElement(isStaticChildren, hostType, { ...hostRestWithLayout, style: finalStyle }, elementKey);
643
+ }
644
+ function processElement(resolveStyle2, type, rawProps, key, isStaticChildren) {
645
+ if (type === null || typeof type === "symbol" || !rawProps) {
646
+ return makeElement(isStaticChildren, type, rawProps ?? {}, key);
647
+ }
648
+ const { className: classStrRaw, style: userStyle, ...rest } = rawProps;
649
+ if (typeof classStrRaw !== "string") {
650
+ return makeElement(isStaticChildren, type, rawProps, key);
651
+ }
652
+ 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)) {
653
+ return (0, import_jsx_runtime.jsx)(
654
+ ReactiveElement,
655
+ { hostType: type, hostRest: rest, classStrRaw, userStyle, resolveStyle: resolveStyle2, elementKey: key, isStaticChildren },
656
+ key
657
+ );
658
+ }
659
+ const staticStates = { hover: false, focus: false, disabled: rest.disabled === true };
660
+ 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);
661
+ return makeElement(isStaticChildren, type, { ...rest, style: finalStyle }, key);
662
+ }
663
+ function createJsxFunctions(resolveStyle2) {
664
+ function jsx2(type, props, key) {
665
+ return processElement(resolveStyle2, type, props, key, false);
666
+ }
667
+ function jsxs2(type, props, key) {
668
+ return processElement(resolveStyle2, type, props, key, true);
669
+ }
670
+ return { jsx: jsx2, jsxs: jsxs2 };
671
+ }
672
+ function createJsxDEV(jsx2, jsxs2) {
673
+ return function jsxDEV2(type, props, key, isStaticChildren, source, self) {
674
+ const element = (isStaticChildren ? jsxs2 : jsx2)(type, props, key);
675
+ if (source && element && typeof element === "object" && Object.isExtensible(element)) {
676
+ element._source = source;
677
+ element._self = self;
678
+ }
679
+ return element;
680
+ };
681
+ }
682
+
683
+ // src/nativeBridge.ts
684
+ var import_react_native2 = require("react-native");
685
+ var import_theme = require("./theme");
686
+ var import_darkModeStore2 = require("./darkModeStore");
687
+
607
688
  // src/jsEngine/shared.ts
608
689
  function decl(property, value) {
609
690
  return { property, value };
@@ -634,11 +715,42 @@ function resolveNegatableLength(theme, parsed) {
634
715
  if (px === 0) return "0px";
635
716
  return `-${px}px`;
636
717
  }
718
+ function resolvePercent(parsed) {
719
+ if (parsed.negative) return null;
720
+ const value = parsed.value;
721
+ if (value === null) return null;
722
+ if (parsed.isArbitrary) return value;
723
+ const pct = Number(value);
724
+ if (!Number.isFinite(pct) || value.trim() === "") return null;
725
+ return String(pct / 100);
726
+ }
637
727
 
638
728
  // src/jsEngine/resolvers/layout.ts
639
729
  function negateRaw(value, negative) {
640
730
  return negative ? `-${value}` : value;
641
731
  }
732
+ function overflowAxisValue(property, value) {
733
+ switch (value) {
734
+ case "auto":
735
+ case "hidden":
736
+ case "clip":
737
+ case "visible":
738
+ case "scroll":
739
+ return [decl(property, value)];
740
+ default:
741
+ return null;
742
+ }
743
+ }
744
+ function overscrollValue(property, value) {
745
+ switch (value) {
746
+ case "auto":
747
+ case "contain":
748
+ case "none":
749
+ return [decl(property, value)];
750
+ default:
751
+ return null;
752
+ }
753
+ }
642
754
  function resolve(parsed, theme) {
643
755
  switch (parsed.utility) {
644
756
  case "flex":
@@ -685,6 +797,12 @@ function resolve(parsed, theme) {
685
797
  return [decl("justify-content", "space-around")];
686
798
  case "justify-evenly":
687
799
  return [decl("justify-content", "space-evenly")];
800
+ case "justify-normal":
801
+ return [decl("justify-content", "normal")];
802
+ case "justify-stretch":
803
+ return [decl("justify-content", "stretch")];
804
+ case "content-normal":
805
+ return [decl("align-content", "normal")];
688
806
  case "content-start":
689
807
  return [decl("align-content", "flex-start")];
690
808
  case "content-end":
@@ -719,6 +837,18 @@ function resolve(parsed, theme) {
719
837
  return [decl("overflow", "scroll")];
720
838
  case "overflow-visible":
721
839
  return [decl("overflow", "visible")];
840
+ case "overflow-clip":
841
+ return [decl("overflow", "clip")];
842
+ case "overflow-x":
843
+ return parsed.value === null ? null : overflowAxisValue("overflow-x", parsed.value);
844
+ case "overflow-y":
845
+ return parsed.value === null ? null : overflowAxisValue("overflow-y", parsed.value);
846
+ case "overscroll":
847
+ return parsed.value === null ? null : overscrollValue("overscroll-behavior", parsed.value);
848
+ case "overscroll-x":
849
+ return parsed.value === null ? null : overscrollValue("overscroll-behavior-x", parsed.value);
850
+ case "overscroll-y":
851
+ return parsed.value === null ? null : overscrollValue("overscroll-behavior-y", parsed.value);
722
852
  case "static":
723
853
  return [decl("position", "static")];
724
854
  case "relative":
@@ -759,10 +889,43 @@ function resolve(parsed, theme) {
759
889
  const v = resolveNegatableLength(theme, parsed);
760
890
  return v === null ? null : [decl("inset", v)];
761
891
  }
762
- case "aspect-square":
763
- return [decl("aspect-ratio", "1 / 1")];
764
- case "aspect-video":
765
- return [decl("aspect-ratio", "16 / 9")];
892
+ case "inset-x": {
893
+ const v = resolveNegatableLength(theme, parsed);
894
+ return v === null ? null : [decl("left", v), decl("right", v)];
895
+ }
896
+ case "inset-y": {
897
+ const v = resolveNegatableLength(theme, parsed);
898
+ return v === null ? null : [decl("top", v), decl("bottom", v)];
899
+ }
900
+ // Logical inset — just a different CSS property name, same reasoning
901
+ // as Rust's layout.rs (no direction-tracking logic needed here).
902
+ case "start": {
903
+ const v = resolveNegatableLength(theme, parsed);
904
+ return v === null ? null : [decl("inset-inline-start", v)];
905
+ }
906
+ case "end": {
907
+ const v = resolveNegatableLength(theme, parsed);
908
+ return v === null ? null : [decl("inset-inline-end", v)];
909
+ }
910
+ // "aspect-" is a registered VALUE_PREFIXES entry (parser.ts), so
911
+ // "aspect-square"/"aspect-video"/"aspect-auto"/arbitrary all arrive
912
+ // here as utility="aspect" + a value, mirroring layout.rs's own
913
+ // "aspect" arm.
914
+ case "aspect": {
915
+ const value = parsed.value;
916
+ if (value === null) return null;
917
+ if (parsed.isArbitrary) return [decl("aspect-ratio", value)];
918
+ switch (value) {
919
+ case "square":
920
+ return [decl("aspect-ratio", "1 / 1")];
921
+ case "video":
922
+ return [decl("aspect-ratio", "16 / 9")];
923
+ case "auto":
924
+ return [decl("aspect-ratio", "auto")];
925
+ default:
926
+ return null;
927
+ }
928
+ }
766
929
  default:
767
930
  return null;
768
931
  }
@@ -1289,6 +1452,16 @@ function textSize(key) {
1289
1452
  return "1.875rem";
1290
1453
  case "4xl":
1291
1454
  return "2.25rem";
1455
+ case "5xl":
1456
+ return "3rem";
1457
+ case "6xl":
1458
+ return "3.75rem";
1459
+ case "7xl":
1460
+ return "4.5rem";
1461
+ case "8xl":
1462
+ return "6rem";
1463
+ case "9xl":
1464
+ return "8rem";
1292
1465
  default:
1293
1466
  return null;
1294
1467
  }
@@ -1325,6 +1498,12 @@ function textAlign(key) {
1325
1498
  return "right";
1326
1499
  case "justify":
1327
1500
  return "justify";
1501
+ // Logical alignment — same "no direction-tracking logic needed" reasoning
1502
+ // as layout.rs's start/end inset properties.
1503
+ case "start":
1504
+ return "start";
1505
+ case "end":
1506
+ return "end";
1328
1507
  default:
1329
1508
  return null;
1330
1509
  }
@@ -1333,6 +1512,10 @@ function fontWeight(key) {
1333
1512
  switch (key) {
1334
1513
  case "thin":
1335
1514
  return "100";
1515
+ case "extralight":
1516
+ return "200";
1517
+ case "light":
1518
+ return "300";
1336
1519
  case "normal":
1337
1520
  return "400";
1338
1521
  case "medium":
@@ -1343,6 +1526,22 @@ function fontWeight(key) {
1343
1526
  return "700";
1344
1527
  case "extrabold":
1345
1528
  return "800";
1529
+ case "black":
1530
+ return "900";
1531
+ default:
1532
+ return null;
1533
+ }
1534
+ }
1535
+ function fontFamilyValue(theme, key) {
1536
+ const fromTheme = theme.fontFamily?.[key];
1537
+ if (fromTheme !== void 0) return fromTheme;
1538
+ switch (key) {
1539
+ case "sans":
1540
+ return 'ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"';
1541
+ case "serif":
1542
+ return 'ui-serif, Georgia, Cambria, "Times New Roman", Times, serif';
1543
+ case "mono":
1544
+ return 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace';
1346
1545
  default:
1347
1546
  return null;
1348
1547
  }
@@ -1385,12 +1584,21 @@ function nativeShadowDeclarations(parsed) {
1385
1584
  }
1386
1585
 
1387
1586
  // src/jsEngine/resolveUtilityNative.ts
1388
- function resolveTypographyNative(parsed) {
1587
+ function firstFontName(stack) {
1588
+ const first = stack.split(",")[0] ?? stack;
1589
+ return first.trim().replace(/^["']|["']$/g, "");
1590
+ }
1591
+ function resolveTypographyNative(parsed, theme) {
1389
1592
  switch (parsed.utility) {
1390
1593
  case "font": {
1391
1594
  if (parsed.value === null) return null;
1595
+ if (parsed.isArbitrary) {
1596
+ return [decl("font-family", firstFontName(parsed.value))];
1597
+ }
1392
1598
  const w = fontWeight(parsed.value);
1393
- return w === null ? null : [decl("font-weight", w)];
1599
+ if (w !== null) return [decl("font-weight", w)];
1600
+ const family = fontFamilyValue(theme, parsed.value);
1601
+ return family === null ? null : [decl("font-family", firstFontName(family))];
1394
1602
  }
1395
1603
  case "uppercase":
1396
1604
  return [decl("text-transform", "uppercase")];
@@ -1450,8 +1658,13 @@ function resolveColorNative(parsed, theme) {
1450
1658
  return null;
1451
1659
  }
1452
1660
  }
1661
+ function resolveOpacityNative(parsed) {
1662
+ if (parsed.utility !== "opacity") return null;
1663
+ const v = resolvePercent(parsed);
1664
+ return v === null ? null : [decl("opacity", v)];
1665
+ }
1453
1666
  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);
1667
+ 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
1668
  }
1456
1669
 
1457
1670
  // src/jsEngine/resolveStyle.ts
@@ -1508,6 +1721,7 @@ var NUMERIC_LENGTH_PROPS = /* @__PURE__ */ new Set([
1508
1721
  "shadow-opacity",
1509
1722
  "shadow-radius",
1510
1723
  "elevation",
1724
+ "opacity",
1511
1725
  // Per-side border width + per-corner radius — see resolvers/border.ts's
1512
1726
  // new borderSideValue/borderAxisValue/resolveRadiusSide additions; RN's
1513
1727
  // style system wants plain numbers for these exactly like the generic
@@ -1595,11 +1809,11 @@ function resolveStyle(classString, pressed = false) {
1595
1809
  const width = import_react_native2.Dimensions.get("window").width;
1596
1810
  const KbachModule = import_react_native2.TurboModuleRegistry.get("KbachModule");
1597
1811
  if (!KbachModule) {
1598
- const { style: style2, warnings: warnings2 } = resolveStyleJsWithWarnings(classString, (0, import_theme2.getTheme)(), colorScheme, pressed, width);
1812
+ const { style: style2, warnings: warnings2 } = resolveStyleJsWithWarnings(classString, (0, import_theme.getTheme)(), colorScheme, pressed, width);
1599
1813
  warnIfDev(classString, warnings2);
1600
1814
  return style2;
1601
1815
  }
1602
- const json = KbachModule.resolveStyle(classString, (0, import_theme2.getThemeJson)(), colorScheme, pressed, width);
1816
+ const json = KbachModule.resolveStyle(classString, (0, import_theme.getThemeJson)(), colorScheme, pressed, width);
1603
1817
  const style = JSON.parse(json);
1604
1818
  const warnings = style.__kbachWarnings;
1605
1819
  if (warnings !== void 0) {