@qontinui/ui-bridge-native 0.7.1 → 0.8.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.
@@ -335,6 +335,164 @@ var UI_BRIDGE_NATIVE_ROUTES = {
335
335
  }
336
336
  };
337
337
 
338
+ // src/core/sha256.ts
339
+ var K = new Uint32Array([
340
+ 1116352408,
341
+ 1899447441,
342
+ 3049323471,
343
+ 3921009573,
344
+ 961987163,
345
+ 1508970993,
346
+ 2453635748,
347
+ 2870763221,
348
+ 3624381080,
349
+ 310598401,
350
+ 607225278,
351
+ 1426881987,
352
+ 1925078388,
353
+ 2162078206,
354
+ 2614888103,
355
+ 3248222580,
356
+ 3835390401,
357
+ 4022224774,
358
+ 264347078,
359
+ 604807628,
360
+ 770255983,
361
+ 1249150122,
362
+ 1555081692,
363
+ 1996064986,
364
+ 2554220882,
365
+ 2821834349,
366
+ 2952996808,
367
+ 3210313671,
368
+ 3336571891,
369
+ 3584528711,
370
+ 113926993,
371
+ 338241895,
372
+ 666307205,
373
+ 773529912,
374
+ 1294757372,
375
+ 1396182291,
376
+ 1695183700,
377
+ 1986661051,
378
+ 2177026350,
379
+ 2456956037,
380
+ 2730485921,
381
+ 2820302411,
382
+ 3259730800,
383
+ 3345764771,
384
+ 3516065817,
385
+ 3600352804,
386
+ 4094571909,
387
+ 275423344,
388
+ 430227734,
389
+ 506948616,
390
+ 659060556,
391
+ 883997877,
392
+ 958139571,
393
+ 1322822218,
394
+ 1537002063,
395
+ 1747873779,
396
+ 1955562222,
397
+ 2024104815,
398
+ 2227730452,
399
+ 2361852424,
400
+ 2428436474,
401
+ 2756734187,
402
+ 3204031479,
403
+ 3329325298
404
+ ]);
405
+ var H0 = [
406
+ 1779033703,
407
+ 3144134277,
408
+ 1013904242,
409
+ 2773480762,
410
+ 1359893119,
411
+ 2600822924,
412
+ 528734635,
413
+ 1541459225
414
+ ];
415
+ function utf8Bytes(input) {
416
+ const out = [];
417
+ for (let i = 0; i < input.length; i++) {
418
+ let cp = input.charCodeAt(i);
419
+ if (cp >= 55296 && cp <= 56319) {
420
+ const next = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
421
+ if (next >= 56320 && next <= 57343) {
422
+ cp = 65536 + (cp - 55296 << 10) + (next - 56320);
423
+ i++;
424
+ } else {
425
+ cp = 65533;
426
+ }
427
+ } else if (cp >= 56320 && cp <= 57343) {
428
+ cp = 65533;
429
+ }
430
+ if (cp < 128) {
431
+ out.push(cp);
432
+ } else if (cp < 2048) {
433
+ out.push(192 | cp >> 6, 128 | cp & 63);
434
+ } else if (cp < 65536) {
435
+ out.push(224 | cp >> 12, 128 | cp >> 6 & 63, 128 | cp & 63);
436
+ } else {
437
+ out.push(
438
+ 240 | cp >> 18,
439
+ 128 | cp >> 12 & 63,
440
+ 128 | cp >> 6 & 63,
441
+ 128 | cp & 63
442
+ );
443
+ }
444
+ }
445
+ return Uint8Array.from(out);
446
+ }
447
+ var rotr = (x, n) => x >>> n | x << 32 - n;
448
+ function sha256Hex(input) {
449
+ const bytes = utf8Bytes(input);
450
+ const blockBytes = Math.ceil((bytes.length + 9) / 64) * 64;
451
+ const buffer = new Uint8Array(blockBytes);
452
+ buffer.set(bytes);
453
+ buffer[bytes.length] = 128;
454
+ const view = new DataView(buffer.buffer);
455
+ const bitLength = bytes.length * 8;
456
+ view.setUint32(blockBytes - 8, Math.floor(bitLength / 4294967296));
457
+ view.setUint32(blockBytes - 4, bitLength >>> 0);
458
+ const h = H0.slice();
459
+ const w = new Uint32Array(64);
460
+ for (let block = 0; block < blockBytes; block += 64) {
461
+ for (let t = 0; t < 16; t++) w[t] = view.getUint32(block + t * 4);
462
+ for (let t = 16; t < 64; t++) {
463
+ const s0 = rotr(w[t - 15], 7) ^ rotr(w[t - 15], 18) ^ w[t - 15] >>> 3;
464
+ const s1 = rotr(w[t - 2], 17) ^ rotr(w[t - 2], 19) ^ w[t - 2] >>> 10;
465
+ w[t] = w[t - 16] + s0 + w[t - 7] + s1;
466
+ }
467
+ let [a, b, c, d, e, f, g, hh] = h;
468
+ for (let t = 0; t < 64; t++) {
469
+ const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
470
+ const ch = e & f ^ ~e & g;
471
+ const t1 = hh + S1 + ch + K[t] + w[t] | 0;
472
+ const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
473
+ const maj = a & b ^ a & c ^ b & c;
474
+ const t2 = S0 + maj | 0;
475
+ hh = g;
476
+ g = f;
477
+ f = e;
478
+ e = d + t1 | 0;
479
+ d = c;
480
+ c = b;
481
+ b = a;
482
+ a = t1 + t2 | 0;
483
+ }
484
+ h[0] = h[0] + a | 0;
485
+ h[1] = h[1] + b | 0;
486
+ h[2] = h[2] + c | 0;
487
+ h[3] = h[3] + d | 0;
488
+ h[4] = h[4] + e | 0;
489
+ h[5] = h[5] + f | 0;
490
+ h[6] = h[6] + g | 0;
491
+ h[7] = h[7] + hh | 0;
492
+ }
493
+ return h.map((word) => (word >>> 0).toString(16).padStart(8, "0")).join("");
494
+ }
495
+
338
496
  // src/core/vision-fields.ts
339
497
  var INTERACTIVE_HANDLER_NAMES = /* @__PURE__ */ new Set([
340
498
  "onPress",
@@ -418,13 +576,18 @@ var NAMED_COLORS = {
418
576
  gray: { r: 128, g: 128, b: 128 },
419
577
  grey: { r: 128, g: 128, b: 128 },
420
578
  silver: { r: 192, g: 192, b: 192 },
421
- transparent: { r: 0, g: 0, b: 0 },
422
579
  orange: { r: 255, g: 165, b: 0 },
423
580
  yellow: { r: 255, g: 255, b: 0 },
424
581
  purple: { r: 128, g: 0, b: 128 },
425
582
  navy: { r: 0, g: 0, b: 128 }
426
583
  };
427
584
  var clamp255 = (n) => Math.max(0, Math.min(255, Math.round(n)));
585
+ function parseAlpha(p) {
586
+ const pct = p.endsWith("%");
587
+ const n = parseFloat(pct ? p.slice(0, -1) : p);
588
+ if (!Number.isFinite(n)) return void 0;
589
+ return Math.min(1, pct ? n / 100 : n);
590
+ }
428
591
  function parseColorToRgb(input) {
429
592
  if (typeof input !== "string") return void 0;
430
593
  const raw = input.trim().toLowerCase();
@@ -435,6 +598,7 @@ function parseColorToRgb(input) {
435
598
  if (raw.startsWith("#")) {
436
599
  const hex = raw.slice(1);
437
600
  if (hex.length === 3 || hex.length === 4) {
601
+ if (hex.length === 4 && hex[3] !== "f") return void 0;
438
602
  const r = parseInt(hex[0] + hex[0], 16);
439
603
  const g = parseInt(hex[1] + hex[1], 16);
440
604
  const b = parseInt(hex[2] + hex[2], 16);
@@ -442,6 +606,7 @@ function parseColorToRgb(input) {
442
606
  return void 0;
443
607
  }
444
608
  if (hex.length === 6 || hex.length === 8) {
609
+ if (hex.length === 8 && hex.slice(6, 8) !== "ff") return void 0;
445
610
  const r = parseInt(hex.slice(0, 2), 16);
446
611
  const g = parseInt(hex.slice(2, 4), 16);
447
612
  const b = parseInt(hex.slice(4, 6), 16);
@@ -453,7 +618,11 @@ function parseColorToRgb(input) {
453
618
  const rgbMatch = raw.match(/^rgba?\(([^)]+)\)$/);
454
619
  if (rgbMatch) {
455
620
  const parts = rgbMatch[1].split(",").map((p) => p.trim());
456
- if (parts.length < 3) return void 0;
621
+ if (parts.length < 3 || parts.length > 4) return void 0;
622
+ if (parts.length === 4) {
623
+ const alpha = parseAlpha(parts[3]);
624
+ if (alpha === void 0 || alpha < 1) return void 0;
625
+ }
457
626
  const channel = (p) => {
458
627
  if (p.endsWith("%")) {
459
628
  const pct = parseFloat(p.slice(0, -1));
@@ -485,13 +654,87 @@ function parseFontSizePx(input) {
485
654
  }
486
655
  return void 0;
487
656
  }
657
+ var ASCII_WHITESPACE_EDGES = /^[\t\n\f\r ]+|[\t\n\f\r ]+$/g;
658
+ function nonEmptyString(v) {
659
+ return typeof v === "string" && v.length > 0 ? v : void 0;
660
+ }
661
+ var OBJECT_FIT_TO_RESIZE_MODE = /* @__PURE__ */ new Map([
662
+ ["contain", "contain"],
663
+ ["cover", "cover"],
664
+ ["fill", "stretch"],
665
+ ["scale-down", "contain"],
666
+ ["none", "none"]
667
+ ]);
668
+ var RESIZE_MODE_TO_OBJECT_FIT = /* @__PURE__ */ new Map([
669
+ ["cover", "cover"],
670
+ ["contain", "contain"],
671
+ ["stretch", "fill"],
672
+ ["center", "scale-down"],
673
+ ["none", "none"]
674
+ ]);
675
+ function resolveObjectFit(props, flatStyle) {
676
+ const styleFit = nonEmptyString(flatStyle?.objectFit);
677
+ const mode = (styleFit !== void 0 ? OBJECT_FIT_TO_RESIZE_MODE.get(styleFit) : void 0) ?? nonEmptyString(props?.resizeMode) ?? nonEmptyString(flatStyle?.resizeMode);
678
+ return mode !== void 0 ? RESIZE_MODE_TO_OBJECT_FIT.get(mode) : void 0;
679
+ }
680
+ function resolveImageSource(props) {
681
+ if (!props) return void 0;
682
+ if (props.srcSet !== void 0 && props.srcSet !== null) return void 0;
683
+ const src = nonEmptyString(props.src);
684
+ if (src !== void 0) return src;
685
+ const source = props.source;
686
+ const one = Array.isArray(source) ? source.length === 1 ? source[0] : void 0 : source;
687
+ if (one && typeof one === "object") {
688
+ return nonEmptyString(one.uri);
689
+ }
690
+ return void 0;
691
+ }
692
+ function isHiddenFromAccessibility(props) {
693
+ if (!props) return false;
694
+ return props.accessible === false && props.alt === void 0 || props.importantForAccessibility === "no" || props.importantForAccessibility === "no-hide-descendants" || props.accessibilityElementsHidden === true;
695
+ }
696
+ function resolveImageLabel(props, registryLabel) {
697
+ if (props === void 0) return registryLabel;
698
+ const own = props["aria-label"] ?? props.accessibilityLabel ?? props.alt;
699
+ return typeof own === "string" ? own : void 0;
700
+ }
701
+ function projectMedia(args) {
702
+ const { layout, props, flatStyle, accessibilityLabel, inViewport } = args;
703
+ const media = { kind: "img" };
704
+ if (layout && Number.isFinite(layout.width) && Number.isFinite(layout.height) && layout.width >= 0 && layout.height >= 0) {
705
+ media.rendered_px = { w: layout.width, h: layout.height };
706
+ }
707
+ const objectFit = resolveObjectFit(props, flatStyle);
708
+ if (objectFit !== void 0) media.object_fit = objectFit;
709
+ if (isHiddenFromAccessibility(props)) {
710
+ media.alt = { decorative: true };
711
+ } else {
712
+ const label = resolveImageLabel(props, accessibilityLabel);
713
+ const text = label?.replace(ASCII_WHITESPACE_EDGES, "");
714
+ if (text) media.alt = { decorative: false, text };
715
+ }
716
+ const src = resolveImageSource(props);
717
+ if (src !== void 0) media.src_digest = sha256Hex(src);
718
+ if (inViewport !== void 0) media.in_viewport = inViewport;
719
+ return media;
720
+ }
488
721
  function projectVisionFields(args) {
489
722
  const { type, label, handlerNames, state, flatStyle } = args;
490
723
  const fields = {
491
724
  interactable: deriveInteractable(type, handlerNames)
492
725
  };
493
- const text = deriveText(state, label);
494
- if (text !== void 0) fields.text = text;
726
+ if (type === "image") {
727
+ fields.media = projectMedia({
728
+ layout: state.layout,
729
+ props: args.props,
730
+ flatStyle,
731
+ accessibilityLabel: args.accessibilityLabel,
732
+ inViewport: args.inViewport
733
+ });
734
+ } else {
735
+ const text = deriveText(state, label);
736
+ if (text !== void 0) fields.text = text;
737
+ }
495
738
  const role = roleForType(type);
496
739
  if (role !== void 0) fields.role = role;
497
740
  if (flatStyle) {
@@ -585,11 +828,17 @@ function computeVisibility(state, clip) {
585
828
  if (!rect) {
586
829
  return { visibility: "visible" };
587
830
  }
588
- if (isEmptyRect(clip)) {
589
- return { visibility: "hidden", visibilityReason: "off-screen" };
590
- }
591
- const onScreen = spansOverlap(rect.left, rect.right, clip.left, clip.right) && spansOverlap(rect.top, rect.bottom, clip.top, clip.bottom);
592
- return onScreen ? { visibility: "visible" } : { visibility: "hidden", visibilityReason: "off-screen" };
831
+ return rectReachesClip(rect, clip) ? { visibility: "visible" } : { visibility: "hidden", visibilityReason: "off-screen" };
832
+ }
833
+ function rectReachesClip(rect, clip) {
834
+ if (isEmptyRect(clip)) return false;
835
+ return spansOverlap(rect.left, rect.right, clip.left, clip.right) && spansOverlap(rect.top, rect.bottom, clip.top, clip.bottom);
836
+ }
837
+ function computeInViewport(state, clip) {
838
+ if (!state.visible || !clip) return void 0;
839
+ const rect = pageRectOf(state);
840
+ if (!rect) return void 0;
841
+ return rectReachesClip(rect, clip);
593
842
  }
594
843
 
595
844
  // src/design/design-inspector-native.ts
@@ -1264,7 +1513,7 @@ var NATIVE_PAGE_HEALTH_PRODUCER_ID = "sdk-native/page-health";
1264
1513
  function defaultProducer() {
1265
1514
  return {
1266
1515
  id: NATIVE_PAGE_HEALTH_PRODUCER_ID,
1267
- version: "0.7.1"
1516
+ version: "0.8.0"
1268
1517
  };
1269
1518
  }
1270
1519
  function pageHealthUnknown(code, detail, options = {}) {
@@ -1833,10 +2082,9 @@ function createServerHandlers(registry, executor, config) {
1833
2082
  const elements = allElements.map((e) => {
1834
2083
  const handlers = extractHandlerNames(e.props);
1835
2084
  const state = e.getState();
1836
- const { visibility, visibilityReason } = computeVisibility(
1837
- state,
1838
- registry.getClipRectFor(e, viewport)
1839
- );
2085
+ const identifier = e.getIdentifier();
2086
+ const clip = registry.getClipRectFor(e, viewport);
2087
+ const { visibility, visibilityReason } = computeVisibility(state, clip);
1840
2088
  const bbox = projectBbox(state, visibility, registry.getPixelRatio());
1841
2089
  const vision = projectVisionFields({
1842
2090
  type: e.type,
@@ -1845,13 +2093,16 @@ function createServerHandlers(registry, executor, config) {
1845
2093
  // synthesize press/click onto every element. See projectVisionFields.
1846
2094
  handlerNames: handlers,
1847
2095
  state,
1848
- flatStyle: e.flatStyle
2096
+ flatStyle: e.flatStyle,
2097
+ props: e.props,
2098
+ accessibilityLabel: identifier.accessibilityLabel,
2099
+ inViewport: computeInViewport(state, clip)
1849
2100
  });
1850
2101
  return {
1851
2102
  id: e.id,
1852
2103
  type: e.type,
1853
2104
  label: e.label,
1854
- identifier: e.getIdentifier(),
2105
+ identifier,
1855
2106
  state,
1856
2107
  actions: e.actions,
1857
2108
  customActions: serializeElementCustomActions(e.customActions),
@@ -2559,7 +2810,7 @@ function createServerHandlers(registry, executor, config) {
2559
2810
  };
2560
2811
  if (config?.appInfo) {
2561
2812
  response.uiBridge = {
2562
- version: "0.7.1",
2813
+ version: "0.8.0",
2563
2814
  ...config.appInfo,
2564
2815
  capabilities: ["elements", "components", "actions", "design"],
2565
2816
  elementCount: stats.elements,