@qontinui/ui-bridge-native 0.7.1 → 0.9.0

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.
@@ -460,6 +460,164 @@ function resolveActionEffect(action) {
460
460
  return action.effect ?? nativeStandardActionEffect(action.id);
461
461
  }
462
462
 
463
+ // src/core/sha256.ts
464
+ var K = new Uint32Array([
465
+ 1116352408,
466
+ 1899447441,
467
+ 3049323471,
468
+ 3921009573,
469
+ 961987163,
470
+ 1508970993,
471
+ 2453635748,
472
+ 2870763221,
473
+ 3624381080,
474
+ 310598401,
475
+ 607225278,
476
+ 1426881987,
477
+ 1925078388,
478
+ 2162078206,
479
+ 2614888103,
480
+ 3248222580,
481
+ 3835390401,
482
+ 4022224774,
483
+ 264347078,
484
+ 604807628,
485
+ 770255983,
486
+ 1249150122,
487
+ 1555081692,
488
+ 1996064986,
489
+ 2554220882,
490
+ 2821834349,
491
+ 2952996808,
492
+ 3210313671,
493
+ 3336571891,
494
+ 3584528711,
495
+ 113926993,
496
+ 338241895,
497
+ 666307205,
498
+ 773529912,
499
+ 1294757372,
500
+ 1396182291,
501
+ 1695183700,
502
+ 1986661051,
503
+ 2177026350,
504
+ 2456956037,
505
+ 2730485921,
506
+ 2820302411,
507
+ 3259730800,
508
+ 3345764771,
509
+ 3516065817,
510
+ 3600352804,
511
+ 4094571909,
512
+ 275423344,
513
+ 430227734,
514
+ 506948616,
515
+ 659060556,
516
+ 883997877,
517
+ 958139571,
518
+ 1322822218,
519
+ 1537002063,
520
+ 1747873779,
521
+ 1955562222,
522
+ 2024104815,
523
+ 2227730452,
524
+ 2361852424,
525
+ 2428436474,
526
+ 2756734187,
527
+ 3204031479,
528
+ 3329325298
529
+ ]);
530
+ var H0 = [
531
+ 1779033703,
532
+ 3144134277,
533
+ 1013904242,
534
+ 2773480762,
535
+ 1359893119,
536
+ 2600822924,
537
+ 528734635,
538
+ 1541459225
539
+ ];
540
+ function utf8Bytes(input) {
541
+ const out = [];
542
+ for (let i = 0; i < input.length; i++) {
543
+ let cp = input.charCodeAt(i);
544
+ if (cp >= 55296 && cp <= 56319) {
545
+ const next = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
546
+ if (next >= 56320 && next <= 57343) {
547
+ cp = 65536 + (cp - 55296 << 10) + (next - 56320);
548
+ i++;
549
+ } else {
550
+ cp = 65533;
551
+ }
552
+ } else if (cp >= 56320 && cp <= 57343) {
553
+ cp = 65533;
554
+ }
555
+ if (cp < 128) {
556
+ out.push(cp);
557
+ } else if (cp < 2048) {
558
+ out.push(192 | cp >> 6, 128 | cp & 63);
559
+ } else if (cp < 65536) {
560
+ out.push(224 | cp >> 12, 128 | cp >> 6 & 63, 128 | cp & 63);
561
+ } else {
562
+ out.push(
563
+ 240 | cp >> 18,
564
+ 128 | cp >> 12 & 63,
565
+ 128 | cp >> 6 & 63,
566
+ 128 | cp & 63
567
+ );
568
+ }
569
+ }
570
+ return Uint8Array.from(out);
571
+ }
572
+ var rotr = (x, n) => x >>> n | x << 32 - n;
573
+ function sha256Hex(input) {
574
+ const bytes = utf8Bytes(input);
575
+ const blockBytes = Math.ceil((bytes.length + 9) / 64) * 64;
576
+ const buffer = new Uint8Array(blockBytes);
577
+ buffer.set(bytes);
578
+ buffer[bytes.length] = 128;
579
+ const view = new DataView(buffer.buffer);
580
+ const bitLength = bytes.length * 8;
581
+ view.setUint32(blockBytes - 8, Math.floor(bitLength / 4294967296));
582
+ view.setUint32(blockBytes - 4, bitLength >>> 0);
583
+ const h = H0.slice();
584
+ const w = new Uint32Array(64);
585
+ for (let block = 0; block < blockBytes; block += 64) {
586
+ for (let t = 0; t < 16; t++) w[t] = view.getUint32(block + t * 4);
587
+ for (let t = 16; t < 64; t++) {
588
+ const s0 = rotr(w[t - 15], 7) ^ rotr(w[t - 15], 18) ^ w[t - 15] >>> 3;
589
+ const s1 = rotr(w[t - 2], 17) ^ rotr(w[t - 2], 19) ^ w[t - 2] >>> 10;
590
+ w[t] = w[t - 16] + s0 + w[t - 7] + s1;
591
+ }
592
+ let [a, b, c, d, e, f, g, hh] = h;
593
+ for (let t = 0; t < 64; t++) {
594
+ const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
595
+ const ch = e & f ^ ~e & g;
596
+ const t1 = hh + S1 + ch + K[t] + w[t] | 0;
597
+ const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
598
+ const maj = a & b ^ a & c ^ b & c;
599
+ const t2 = S0 + maj | 0;
600
+ hh = g;
601
+ g = f;
602
+ f = e;
603
+ e = d + t1 | 0;
604
+ d = c;
605
+ c = b;
606
+ b = a;
607
+ a = t1 + t2 | 0;
608
+ }
609
+ h[0] = h[0] + a | 0;
610
+ h[1] = h[1] + b | 0;
611
+ h[2] = h[2] + c | 0;
612
+ h[3] = h[3] + d | 0;
613
+ h[4] = h[4] + e | 0;
614
+ h[5] = h[5] + f | 0;
615
+ h[6] = h[6] + g | 0;
616
+ h[7] = h[7] + hh | 0;
617
+ }
618
+ return h.map((word) => (word >>> 0).toString(16).padStart(8, "0")).join("");
619
+ }
620
+
463
621
  // src/core/vision-fields.ts
464
622
  var INTERACTIVE_HANDLER_NAMES = /* @__PURE__ */ new Set([
465
623
  "onPress",
@@ -543,13 +701,18 @@ var NAMED_COLORS = {
543
701
  gray: { r: 128, g: 128, b: 128 },
544
702
  grey: { r: 128, g: 128, b: 128 },
545
703
  silver: { r: 192, g: 192, b: 192 },
546
- transparent: { r: 0, g: 0, b: 0 },
547
704
  orange: { r: 255, g: 165, b: 0 },
548
705
  yellow: { r: 255, g: 255, b: 0 },
549
706
  purple: { r: 128, g: 0, b: 128 },
550
707
  navy: { r: 0, g: 0, b: 128 }
551
708
  };
552
709
  var clamp255 = (n) => Math.max(0, Math.min(255, Math.round(n)));
710
+ function parseAlpha(p) {
711
+ const pct = p.endsWith("%");
712
+ const n = parseFloat(pct ? p.slice(0, -1) : p);
713
+ if (!Number.isFinite(n)) return void 0;
714
+ return Math.min(1, pct ? n / 100 : n);
715
+ }
553
716
  function parseColorToRgb(input) {
554
717
  if (typeof input !== "string") return void 0;
555
718
  const raw = input.trim().toLowerCase();
@@ -560,6 +723,7 @@ function parseColorToRgb(input) {
560
723
  if (raw.startsWith("#")) {
561
724
  const hex = raw.slice(1);
562
725
  if (hex.length === 3 || hex.length === 4) {
726
+ if (hex.length === 4 && hex[3] !== "f") return void 0;
563
727
  const r = parseInt(hex[0] + hex[0], 16);
564
728
  const g = parseInt(hex[1] + hex[1], 16);
565
729
  const b = parseInt(hex[2] + hex[2], 16);
@@ -567,6 +731,7 @@ function parseColorToRgb(input) {
567
731
  return void 0;
568
732
  }
569
733
  if (hex.length === 6 || hex.length === 8) {
734
+ if (hex.length === 8 && hex.slice(6, 8) !== "ff") return void 0;
570
735
  const r = parseInt(hex.slice(0, 2), 16);
571
736
  const g = parseInt(hex.slice(2, 4), 16);
572
737
  const b = parseInt(hex.slice(4, 6), 16);
@@ -578,7 +743,11 @@ function parseColorToRgb(input) {
578
743
  const rgbMatch = raw.match(/^rgba?\(([^)]+)\)$/);
579
744
  if (rgbMatch) {
580
745
  const parts = rgbMatch[1].split(",").map((p) => p.trim());
581
- if (parts.length < 3) return void 0;
746
+ if (parts.length < 3 || parts.length > 4) return void 0;
747
+ if (parts.length === 4) {
748
+ const alpha = parseAlpha(parts[3]);
749
+ if (alpha === void 0 || alpha < 1) return void 0;
750
+ }
582
751
  const channel = (p) => {
583
752
  if (p.endsWith("%")) {
584
753
  const pct = parseFloat(p.slice(0, -1));
@@ -610,13 +779,87 @@ function parseFontSizePx(input) {
610
779
  }
611
780
  return void 0;
612
781
  }
782
+ var ASCII_WHITESPACE_EDGES = /^[\t\n\f\r ]+|[\t\n\f\r ]+$/g;
783
+ function nonEmptyString(v) {
784
+ return typeof v === "string" && v.length > 0 ? v : void 0;
785
+ }
786
+ var OBJECT_FIT_TO_RESIZE_MODE = /* @__PURE__ */ new Map([
787
+ ["contain", "contain"],
788
+ ["cover", "cover"],
789
+ ["fill", "stretch"],
790
+ ["scale-down", "contain"],
791
+ ["none", "none"]
792
+ ]);
793
+ var RESIZE_MODE_TO_OBJECT_FIT = /* @__PURE__ */ new Map([
794
+ ["cover", "cover"],
795
+ ["contain", "contain"],
796
+ ["stretch", "fill"],
797
+ ["center", "scale-down"],
798
+ ["none", "none"]
799
+ ]);
800
+ function resolveObjectFit(props, flatStyle) {
801
+ const styleFit = nonEmptyString(flatStyle?.objectFit);
802
+ const mode = (styleFit !== void 0 ? OBJECT_FIT_TO_RESIZE_MODE.get(styleFit) : void 0) ?? nonEmptyString(props?.resizeMode) ?? nonEmptyString(flatStyle?.resizeMode);
803
+ return mode !== void 0 ? RESIZE_MODE_TO_OBJECT_FIT.get(mode) : void 0;
804
+ }
805
+ function resolveImageSource(props) {
806
+ if (!props) return void 0;
807
+ if (props.srcSet !== void 0 && props.srcSet !== null) return void 0;
808
+ const src = nonEmptyString(props.src);
809
+ if (src !== void 0) return src;
810
+ const source = props.source;
811
+ const one = Array.isArray(source) ? source.length === 1 ? source[0] : void 0 : source;
812
+ if (one && typeof one === "object") {
813
+ return nonEmptyString(one.uri);
814
+ }
815
+ return void 0;
816
+ }
817
+ function isHiddenFromAccessibility(props) {
818
+ if (!props) return false;
819
+ return props.accessible === false && props.alt === void 0 || props.importantForAccessibility === "no" || props.importantForAccessibility === "no-hide-descendants" || props.accessibilityElementsHidden === true;
820
+ }
821
+ function resolveImageLabel(props, registryLabel) {
822
+ if (props === void 0) return registryLabel;
823
+ const own = props["aria-label"] ?? props.accessibilityLabel ?? props.alt;
824
+ return typeof own === "string" ? own : void 0;
825
+ }
826
+ function projectMedia(args) {
827
+ const { layout, props, flatStyle, accessibilityLabel, inViewport } = args;
828
+ const media = { kind: "img" };
829
+ if (layout && Number.isFinite(layout.width) && Number.isFinite(layout.height) && layout.width >= 0 && layout.height >= 0) {
830
+ media.rendered_px = { w: layout.width, h: layout.height };
831
+ }
832
+ const objectFit = resolveObjectFit(props, flatStyle);
833
+ if (objectFit !== void 0) media.object_fit = objectFit;
834
+ if (isHiddenFromAccessibility(props)) {
835
+ media.alt = { decorative: true };
836
+ } else {
837
+ const label = resolveImageLabel(props, accessibilityLabel);
838
+ const text = label?.replace(ASCII_WHITESPACE_EDGES, "");
839
+ if (text) media.alt = { decorative: false, text };
840
+ }
841
+ const src = resolveImageSource(props);
842
+ if (src !== void 0) media.src_digest = sha256Hex(src);
843
+ if (inViewport !== void 0) media.in_viewport = inViewport;
844
+ return media;
845
+ }
613
846
  function projectVisionFields(args) {
614
847
  const { type, label, handlerNames, state, flatStyle } = args;
615
848
  const fields = {
616
849
  interactable: deriveInteractable(type, handlerNames)
617
850
  };
618
- const text = deriveText(state, label);
619
- if (text !== void 0) fields.text = text;
851
+ if (type === "image") {
852
+ fields.media = projectMedia({
853
+ layout: state.layout,
854
+ props: args.props,
855
+ flatStyle,
856
+ accessibilityLabel: args.accessibilityLabel,
857
+ inViewport: args.inViewport
858
+ });
859
+ } else {
860
+ const text = deriveText(state, label);
861
+ if (text !== void 0) fields.text = text;
862
+ }
620
863
  const role = roleForType(type);
621
864
  if (role !== void 0) fields.role = role;
622
865
  if (flatStyle) {
@@ -756,11 +999,17 @@ function computeVisibility(state, clip) {
756
999
  if (!rect) {
757
1000
  return { visibility: "visible" };
758
1001
  }
759
- if (isEmptyRect(clip)) {
760
- return { visibility: "hidden", visibilityReason: "off-screen" };
761
- }
762
- const onScreen = spansOverlap(rect.left, rect.right, clip.left, clip.right) && spansOverlap(rect.top, rect.bottom, clip.top, clip.bottom);
763
- return onScreen ? { visibility: "visible" } : { visibility: "hidden", visibilityReason: "off-screen" };
1002
+ return rectReachesClip(rect, clip) ? { visibility: "visible" } : { visibility: "hidden", visibilityReason: "off-screen" };
1003
+ }
1004
+ function rectReachesClip(rect, clip) {
1005
+ if (isEmptyRect(clip)) return false;
1006
+ return spansOverlap(rect.left, rect.right, clip.left, clip.right) && spansOverlap(rect.top, rect.bottom, clip.top, clip.bottom);
1007
+ }
1008
+ function computeInViewport(state, clip) {
1009
+ if (!state.visible || !clip) return void 0;
1010
+ const rect = pageRectOf(state);
1011
+ if (!rect) return void 0;
1012
+ return rectReachesClip(rect, clip);
764
1013
  }
765
1014
  function copyRouteInfo(info) {
766
1015
  const copy = { ...info };
@@ -1703,10 +1952,9 @@ var NativeUIBridgeRegistry = class {
1703
1952
  elements: elements.map((e) => {
1704
1953
  const handlers = extractHandlerNames(e.props);
1705
1954
  const state = e.getState();
1706
- const { visibility, visibilityReason } = computeVisibility(
1707
- state,
1708
- this.getClipRectFor(e, viewport)
1709
- );
1955
+ const identifier = e.getIdentifier();
1956
+ const clip = this.getClipRectFor(e, viewport);
1957
+ const { visibility, visibilityReason } = computeVisibility(state, clip);
1710
1958
  const bbox = projectBbox(state, visibility, this.pixelRatio);
1711
1959
  const vision = projectVisionFields({
1712
1960
  type: e.type,
@@ -1717,13 +1965,16 @@ var NativeUIBridgeRegistry = class {
1717
1965
  // using it would mark plain text/view nodes interactable.
1718
1966
  handlerNames: handlers,
1719
1967
  state,
1720
- flatStyle: e.flatStyle
1968
+ flatStyle: e.flatStyle,
1969
+ props: e.props,
1970
+ accessibilityLabel: identifier.accessibilityLabel,
1971
+ inViewport: computeInViewport(state, clip)
1721
1972
  });
1722
1973
  return {
1723
1974
  id: e.id,
1724
1975
  type: e.type,
1725
1976
  label: e.label,
1726
- identifier: e.getIdentifier(),
1977
+ identifier,
1727
1978
  state,
1728
1979
  actions: e.actions,
1729
1980
  customActions: serializeElementCustomActions(e.customActions),
@@ -1963,6 +2214,6 @@ function matchesIdentifier(identifier, criteria) {
1963
2214
  return true;
1964
2215
  }
1965
2216
 
1966
- export { DEFAULT_PARAM_VALIDATION_MODE, MAX_ACTION_TIMEOUT_MS, NATIVE_STANDARD_ACTION_EFFECTS, NativeUIBridgeRegistry, buildTreePath, computeVisibility, createNativeElementIdentifier, deriveActiveTabFromSegments, extractHandlerNames, findAllByPattern, findElementByIdentifier, formatParamValidationFailure, getDefaultParamValidationMode, getGlobalRegistry, inertAbortSignal, intersectRects, isEmptyRect, matchesCurrentRoute, matchesIdentifier, nativeStandardActionEffect, normalizeActionTimeoutMs, pageRectOf, parseTreePath, projectBbox, resetDefaultParamValidationMode, resetGlobalRegistry, resolveActionEffect, runAbortable, serializeElementCustomActions, setDefaultParamValidationMode, setGlobalRegistry, validateActionParams };
2217
+ export { DEFAULT_PARAM_VALIDATION_MODE, MAX_ACTION_TIMEOUT_MS, NATIVE_STANDARD_ACTION_EFFECTS, NativeUIBridgeRegistry, buildTreePath, computeInViewport, computeVisibility, createNativeElementIdentifier, deriveActiveTabFromSegments, extractHandlerNames, findAllByPattern, findElementByIdentifier, formatParamValidationFailure, getDefaultParamValidationMode, getGlobalRegistry, inertAbortSignal, intersectRects, isEmptyRect, matchesCurrentRoute, matchesIdentifier, nativeStandardActionEffect, normalizeActionTimeoutMs, pageRectOf, parseTreePath, projectBbox, resetDefaultParamValidationMode, resetGlobalRegistry, resolveActionEffect, runAbortable, serializeElementCustomActions, setDefaultParamValidationMode, setGlobalRegistry, validateActionParams };
1967
2218
  //# sourceMappingURL=index.mjs.map
1968
2219
  //# sourceMappingURL=index.mjs.map