@qontinui/ui-bridge-native 0.7.0 → 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.
- package/dist/control/index.js +2 -0
- package/dist/control/index.js.map +1 -1
- package/dist/control/index.mjs +2 -0
- package/dist/control/index.mjs.map +1 -1
- package/dist/core/index.js +267 -15
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +267 -16
- package/dist/core/index.mjs.map +1 -1
- package/dist/core/registry.d.ts +13 -0
- package/dist/core/registry.d.ts.map +1 -1
- package/dist/core/sha256.d.ts +19 -0
- package/dist/core/sha256.d.ts.map +1 -0
- package/dist/core/types.d.ts +20 -7
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/vision-fields.d.ts +164 -11
- package/dist/core/vision-fields.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +320 -44
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +315 -45
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.js +314 -44
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +314 -44
- package/dist/react/index.mjs.map +1 -1
- package/dist/react/useRouteAwareness.d.ts.map +1 -1
- package/dist/server/handlers.d.ts.map +1 -1
- package/dist/server/index.js +303 -37
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +303 -37
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/page-health.d.ts +10 -1
- package/dist/server/page-health.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useRouteAwareness.d.ts","sourceRoot":"","sources":["../../src/react/useRouteAwareness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0FG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;
|
|
1
|
+
{"version":3,"file":"useRouteAwareness.d.ts","sourceRoot":"","sources":["../../src/react/useRouteAwareness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0FG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAWD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,GAAE,wBAA6B,GAAG,IAAI,CAwB/F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/server/handlers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAaH,OAAO,EACL,KAAK,sBAAsB,
|
|
1
|
+
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/server/handlers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAaH,OAAO,EACL,KAAK,sBAAsB,EAM5B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EAAwB,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACnF,OAAO,KAAK,EAQV,oBAAoB,EAKrB,MAAM,SAAS,CAAC;AAEjB,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AA4VhF;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,sBAAsB,EAChC,QAAQ,EAAE,oBAAoB,EAC9B,MAAM,CAAC,EAAE;IACP,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClF,iFAAiF;IACjF,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,iFAAiF;IACjF,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C;;;;;;;;;OASG;IACH,gBAAgB,CAAC,EAAE,MAAM;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5D,GACA,oBAAoB,CAqhCtB"}
|
package/dist/server/index.js
CHANGED
|
@@ -337,6 +337,164 @@ var UI_BRIDGE_NATIVE_ROUTES = {
|
|
|
337
337
|
}
|
|
338
338
|
};
|
|
339
339
|
|
|
340
|
+
// src/core/sha256.ts
|
|
341
|
+
var K = new Uint32Array([
|
|
342
|
+
1116352408,
|
|
343
|
+
1899447441,
|
|
344
|
+
3049323471,
|
|
345
|
+
3921009573,
|
|
346
|
+
961987163,
|
|
347
|
+
1508970993,
|
|
348
|
+
2453635748,
|
|
349
|
+
2870763221,
|
|
350
|
+
3624381080,
|
|
351
|
+
310598401,
|
|
352
|
+
607225278,
|
|
353
|
+
1426881987,
|
|
354
|
+
1925078388,
|
|
355
|
+
2162078206,
|
|
356
|
+
2614888103,
|
|
357
|
+
3248222580,
|
|
358
|
+
3835390401,
|
|
359
|
+
4022224774,
|
|
360
|
+
264347078,
|
|
361
|
+
604807628,
|
|
362
|
+
770255983,
|
|
363
|
+
1249150122,
|
|
364
|
+
1555081692,
|
|
365
|
+
1996064986,
|
|
366
|
+
2554220882,
|
|
367
|
+
2821834349,
|
|
368
|
+
2952996808,
|
|
369
|
+
3210313671,
|
|
370
|
+
3336571891,
|
|
371
|
+
3584528711,
|
|
372
|
+
113926993,
|
|
373
|
+
338241895,
|
|
374
|
+
666307205,
|
|
375
|
+
773529912,
|
|
376
|
+
1294757372,
|
|
377
|
+
1396182291,
|
|
378
|
+
1695183700,
|
|
379
|
+
1986661051,
|
|
380
|
+
2177026350,
|
|
381
|
+
2456956037,
|
|
382
|
+
2730485921,
|
|
383
|
+
2820302411,
|
|
384
|
+
3259730800,
|
|
385
|
+
3345764771,
|
|
386
|
+
3516065817,
|
|
387
|
+
3600352804,
|
|
388
|
+
4094571909,
|
|
389
|
+
275423344,
|
|
390
|
+
430227734,
|
|
391
|
+
506948616,
|
|
392
|
+
659060556,
|
|
393
|
+
883997877,
|
|
394
|
+
958139571,
|
|
395
|
+
1322822218,
|
|
396
|
+
1537002063,
|
|
397
|
+
1747873779,
|
|
398
|
+
1955562222,
|
|
399
|
+
2024104815,
|
|
400
|
+
2227730452,
|
|
401
|
+
2361852424,
|
|
402
|
+
2428436474,
|
|
403
|
+
2756734187,
|
|
404
|
+
3204031479,
|
|
405
|
+
3329325298
|
|
406
|
+
]);
|
|
407
|
+
var H0 = [
|
|
408
|
+
1779033703,
|
|
409
|
+
3144134277,
|
|
410
|
+
1013904242,
|
|
411
|
+
2773480762,
|
|
412
|
+
1359893119,
|
|
413
|
+
2600822924,
|
|
414
|
+
528734635,
|
|
415
|
+
1541459225
|
|
416
|
+
];
|
|
417
|
+
function utf8Bytes(input) {
|
|
418
|
+
const out = [];
|
|
419
|
+
for (let i = 0; i < input.length; i++) {
|
|
420
|
+
let cp = input.charCodeAt(i);
|
|
421
|
+
if (cp >= 55296 && cp <= 56319) {
|
|
422
|
+
const next = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
|
|
423
|
+
if (next >= 56320 && next <= 57343) {
|
|
424
|
+
cp = 65536 + (cp - 55296 << 10) + (next - 56320);
|
|
425
|
+
i++;
|
|
426
|
+
} else {
|
|
427
|
+
cp = 65533;
|
|
428
|
+
}
|
|
429
|
+
} else if (cp >= 56320 && cp <= 57343) {
|
|
430
|
+
cp = 65533;
|
|
431
|
+
}
|
|
432
|
+
if (cp < 128) {
|
|
433
|
+
out.push(cp);
|
|
434
|
+
} else if (cp < 2048) {
|
|
435
|
+
out.push(192 | cp >> 6, 128 | cp & 63);
|
|
436
|
+
} else if (cp < 65536) {
|
|
437
|
+
out.push(224 | cp >> 12, 128 | cp >> 6 & 63, 128 | cp & 63);
|
|
438
|
+
} else {
|
|
439
|
+
out.push(
|
|
440
|
+
240 | cp >> 18,
|
|
441
|
+
128 | cp >> 12 & 63,
|
|
442
|
+
128 | cp >> 6 & 63,
|
|
443
|
+
128 | cp & 63
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
return Uint8Array.from(out);
|
|
448
|
+
}
|
|
449
|
+
var rotr = (x, n) => x >>> n | x << 32 - n;
|
|
450
|
+
function sha256Hex(input) {
|
|
451
|
+
const bytes = utf8Bytes(input);
|
|
452
|
+
const blockBytes = Math.ceil((bytes.length + 9) / 64) * 64;
|
|
453
|
+
const buffer = new Uint8Array(blockBytes);
|
|
454
|
+
buffer.set(bytes);
|
|
455
|
+
buffer[bytes.length] = 128;
|
|
456
|
+
const view = new DataView(buffer.buffer);
|
|
457
|
+
const bitLength = bytes.length * 8;
|
|
458
|
+
view.setUint32(blockBytes - 8, Math.floor(bitLength / 4294967296));
|
|
459
|
+
view.setUint32(blockBytes - 4, bitLength >>> 0);
|
|
460
|
+
const h = H0.slice();
|
|
461
|
+
const w = new Uint32Array(64);
|
|
462
|
+
for (let block = 0; block < blockBytes; block += 64) {
|
|
463
|
+
for (let t = 0; t < 16; t++) w[t] = view.getUint32(block + t * 4);
|
|
464
|
+
for (let t = 16; t < 64; t++) {
|
|
465
|
+
const s0 = rotr(w[t - 15], 7) ^ rotr(w[t - 15], 18) ^ w[t - 15] >>> 3;
|
|
466
|
+
const s1 = rotr(w[t - 2], 17) ^ rotr(w[t - 2], 19) ^ w[t - 2] >>> 10;
|
|
467
|
+
w[t] = w[t - 16] + s0 + w[t - 7] + s1;
|
|
468
|
+
}
|
|
469
|
+
let [a, b, c, d, e, f, g, hh] = h;
|
|
470
|
+
for (let t = 0; t < 64; t++) {
|
|
471
|
+
const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
|
|
472
|
+
const ch = e & f ^ ~e & g;
|
|
473
|
+
const t1 = hh + S1 + ch + K[t] + w[t] | 0;
|
|
474
|
+
const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
|
|
475
|
+
const maj = a & b ^ a & c ^ b & c;
|
|
476
|
+
const t2 = S0 + maj | 0;
|
|
477
|
+
hh = g;
|
|
478
|
+
g = f;
|
|
479
|
+
f = e;
|
|
480
|
+
e = d + t1 | 0;
|
|
481
|
+
d = c;
|
|
482
|
+
c = b;
|
|
483
|
+
b = a;
|
|
484
|
+
a = t1 + t2 | 0;
|
|
485
|
+
}
|
|
486
|
+
h[0] = h[0] + a | 0;
|
|
487
|
+
h[1] = h[1] + b | 0;
|
|
488
|
+
h[2] = h[2] + c | 0;
|
|
489
|
+
h[3] = h[3] + d | 0;
|
|
490
|
+
h[4] = h[4] + e | 0;
|
|
491
|
+
h[5] = h[5] + f | 0;
|
|
492
|
+
h[6] = h[6] + g | 0;
|
|
493
|
+
h[7] = h[7] + hh | 0;
|
|
494
|
+
}
|
|
495
|
+
return h.map((word) => (word >>> 0).toString(16).padStart(8, "0")).join("");
|
|
496
|
+
}
|
|
497
|
+
|
|
340
498
|
// src/core/vision-fields.ts
|
|
341
499
|
var INTERACTIVE_HANDLER_NAMES = /* @__PURE__ */ new Set([
|
|
342
500
|
"onPress",
|
|
@@ -420,13 +578,18 @@ var NAMED_COLORS = {
|
|
|
420
578
|
gray: { r: 128, g: 128, b: 128 },
|
|
421
579
|
grey: { r: 128, g: 128, b: 128 },
|
|
422
580
|
silver: { r: 192, g: 192, b: 192 },
|
|
423
|
-
transparent: { r: 0, g: 0, b: 0 },
|
|
424
581
|
orange: { r: 255, g: 165, b: 0 },
|
|
425
582
|
yellow: { r: 255, g: 255, b: 0 },
|
|
426
583
|
purple: { r: 128, g: 0, b: 128 },
|
|
427
584
|
navy: { r: 0, g: 0, b: 128 }
|
|
428
585
|
};
|
|
429
586
|
var clamp255 = (n) => Math.max(0, Math.min(255, Math.round(n)));
|
|
587
|
+
function parseAlpha(p) {
|
|
588
|
+
const pct = p.endsWith("%");
|
|
589
|
+
const n = parseFloat(pct ? p.slice(0, -1) : p);
|
|
590
|
+
if (!Number.isFinite(n)) return void 0;
|
|
591
|
+
return Math.min(1, pct ? n / 100 : n);
|
|
592
|
+
}
|
|
430
593
|
function parseColorToRgb(input) {
|
|
431
594
|
if (typeof input !== "string") return void 0;
|
|
432
595
|
const raw = input.trim().toLowerCase();
|
|
@@ -437,6 +600,7 @@ function parseColorToRgb(input) {
|
|
|
437
600
|
if (raw.startsWith("#")) {
|
|
438
601
|
const hex = raw.slice(1);
|
|
439
602
|
if (hex.length === 3 || hex.length === 4) {
|
|
603
|
+
if (hex.length === 4 && hex[3] !== "f") return void 0;
|
|
440
604
|
const r = parseInt(hex[0] + hex[0], 16);
|
|
441
605
|
const g = parseInt(hex[1] + hex[1], 16);
|
|
442
606
|
const b = parseInt(hex[2] + hex[2], 16);
|
|
@@ -444,6 +608,7 @@ function parseColorToRgb(input) {
|
|
|
444
608
|
return void 0;
|
|
445
609
|
}
|
|
446
610
|
if (hex.length === 6 || hex.length === 8) {
|
|
611
|
+
if (hex.length === 8 && hex.slice(6, 8) !== "ff") return void 0;
|
|
447
612
|
const r = parseInt(hex.slice(0, 2), 16);
|
|
448
613
|
const g = parseInt(hex.slice(2, 4), 16);
|
|
449
614
|
const b = parseInt(hex.slice(4, 6), 16);
|
|
@@ -455,7 +620,11 @@ function parseColorToRgb(input) {
|
|
|
455
620
|
const rgbMatch = raw.match(/^rgba?\(([^)]+)\)$/);
|
|
456
621
|
if (rgbMatch) {
|
|
457
622
|
const parts = rgbMatch[1].split(",").map((p) => p.trim());
|
|
458
|
-
if (parts.length < 3) return void 0;
|
|
623
|
+
if (parts.length < 3 || parts.length > 4) return void 0;
|
|
624
|
+
if (parts.length === 4) {
|
|
625
|
+
const alpha = parseAlpha(parts[3]);
|
|
626
|
+
if (alpha === void 0 || alpha < 1) return void 0;
|
|
627
|
+
}
|
|
459
628
|
const channel = (p) => {
|
|
460
629
|
if (p.endsWith("%")) {
|
|
461
630
|
const pct = parseFloat(p.slice(0, -1));
|
|
@@ -487,13 +656,87 @@ function parseFontSizePx(input) {
|
|
|
487
656
|
}
|
|
488
657
|
return void 0;
|
|
489
658
|
}
|
|
659
|
+
var ASCII_WHITESPACE_EDGES = /^[\t\n\f\r ]+|[\t\n\f\r ]+$/g;
|
|
660
|
+
function nonEmptyString(v) {
|
|
661
|
+
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
662
|
+
}
|
|
663
|
+
var OBJECT_FIT_TO_RESIZE_MODE = /* @__PURE__ */ new Map([
|
|
664
|
+
["contain", "contain"],
|
|
665
|
+
["cover", "cover"],
|
|
666
|
+
["fill", "stretch"],
|
|
667
|
+
["scale-down", "contain"],
|
|
668
|
+
["none", "none"]
|
|
669
|
+
]);
|
|
670
|
+
var RESIZE_MODE_TO_OBJECT_FIT = /* @__PURE__ */ new Map([
|
|
671
|
+
["cover", "cover"],
|
|
672
|
+
["contain", "contain"],
|
|
673
|
+
["stretch", "fill"],
|
|
674
|
+
["center", "scale-down"],
|
|
675
|
+
["none", "none"]
|
|
676
|
+
]);
|
|
677
|
+
function resolveObjectFit(props, flatStyle) {
|
|
678
|
+
const styleFit = nonEmptyString(flatStyle?.objectFit);
|
|
679
|
+
const mode = (styleFit !== void 0 ? OBJECT_FIT_TO_RESIZE_MODE.get(styleFit) : void 0) ?? nonEmptyString(props?.resizeMode) ?? nonEmptyString(flatStyle?.resizeMode);
|
|
680
|
+
return mode !== void 0 ? RESIZE_MODE_TO_OBJECT_FIT.get(mode) : void 0;
|
|
681
|
+
}
|
|
682
|
+
function resolveImageSource(props) {
|
|
683
|
+
if (!props) return void 0;
|
|
684
|
+
if (props.srcSet !== void 0 && props.srcSet !== null) return void 0;
|
|
685
|
+
const src = nonEmptyString(props.src);
|
|
686
|
+
if (src !== void 0) return src;
|
|
687
|
+
const source = props.source;
|
|
688
|
+
const one = Array.isArray(source) ? source.length === 1 ? source[0] : void 0 : source;
|
|
689
|
+
if (one && typeof one === "object") {
|
|
690
|
+
return nonEmptyString(one.uri);
|
|
691
|
+
}
|
|
692
|
+
return void 0;
|
|
693
|
+
}
|
|
694
|
+
function isHiddenFromAccessibility(props) {
|
|
695
|
+
if (!props) return false;
|
|
696
|
+
return props.accessible === false && props.alt === void 0 || props.importantForAccessibility === "no" || props.importantForAccessibility === "no-hide-descendants" || props.accessibilityElementsHidden === true;
|
|
697
|
+
}
|
|
698
|
+
function resolveImageLabel(props, registryLabel) {
|
|
699
|
+
if (props === void 0) return registryLabel;
|
|
700
|
+
const own = props["aria-label"] ?? props.accessibilityLabel ?? props.alt;
|
|
701
|
+
return typeof own === "string" ? own : void 0;
|
|
702
|
+
}
|
|
703
|
+
function projectMedia(args) {
|
|
704
|
+
const { layout, props, flatStyle, accessibilityLabel, inViewport } = args;
|
|
705
|
+
const media = { kind: "img" };
|
|
706
|
+
if (layout && Number.isFinite(layout.width) && Number.isFinite(layout.height) && layout.width >= 0 && layout.height >= 0) {
|
|
707
|
+
media.rendered_px = { w: layout.width, h: layout.height };
|
|
708
|
+
}
|
|
709
|
+
const objectFit = resolveObjectFit(props, flatStyle);
|
|
710
|
+
if (objectFit !== void 0) media.object_fit = objectFit;
|
|
711
|
+
if (isHiddenFromAccessibility(props)) {
|
|
712
|
+
media.alt = { decorative: true };
|
|
713
|
+
} else {
|
|
714
|
+
const label = resolveImageLabel(props, accessibilityLabel);
|
|
715
|
+
const text = label?.replace(ASCII_WHITESPACE_EDGES, "");
|
|
716
|
+
if (text) media.alt = { decorative: false, text };
|
|
717
|
+
}
|
|
718
|
+
const src = resolveImageSource(props);
|
|
719
|
+
if (src !== void 0) media.src_digest = sha256Hex(src);
|
|
720
|
+
if (inViewport !== void 0) media.in_viewport = inViewport;
|
|
721
|
+
return media;
|
|
722
|
+
}
|
|
490
723
|
function projectVisionFields(args) {
|
|
491
724
|
const { type, label, handlerNames, state, flatStyle } = args;
|
|
492
725
|
const fields = {
|
|
493
726
|
interactable: deriveInteractable(type, handlerNames)
|
|
494
727
|
};
|
|
495
|
-
|
|
496
|
-
|
|
728
|
+
if (type === "image") {
|
|
729
|
+
fields.media = projectMedia({
|
|
730
|
+
layout: state.layout,
|
|
731
|
+
props: args.props,
|
|
732
|
+
flatStyle,
|
|
733
|
+
accessibilityLabel: args.accessibilityLabel,
|
|
734
|
+
inViewport: args.inViewport
|
|
735
|
+
});
|
|
736
|
+
} else {
|
|
737
|
+
const text = deriveText(state, label);
|
|
738
|
+
if (text !== void 0) fields.text = text;
|
|
739
|
+
}
|
|
497
740
|
const role = roleForType(type);
|
|
498
741
|
if (role !== void 0) fields.role = role;
|
|
499
742
|
if (flatStyle) {
|
|
@@ -587,11 +830,17 @@ function computeVisibility(state, clip) {
|
|
|
587
830
|
if (!rect) {
|
|
588
831
|
return { visibility: "visible" };
|
|
589
832
|
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
return
|
|
833
|
+
return rectReachesClip(rect, clip) ? { visibility: "visible" } : { visibility: "hidden", visibilityReason: "off-screen" };
|
|
834
|
+
}
|
|
835
|
+
function rectReachesClip(rect, clip) {
|
|
836
|
+
if (isEmptyRect(clip)) return false;
|
|
837
|
+
return spansOverlap(rect.left, rect.right, clip.left, clip.right) && spansOverlap(rect.top, rect.bottom, clip.top, clip.bottom);
|
|
838
|
+
}
|
|
839
|
+
function computeInViewport(state, clip) {
|
|
840
|
+
if (!state.visible || !clip) return void 0;
|
|
841
|
+
const rect = pageRectOf(state);
|
|
842
|
+
if (!rect) return void 0;
|
|
843
|
+
return rectReachesClip(rect, clip);
|
|
595
844
|
}
|
|
596
845
|
|
|
597
846
|
// src/design/design-inspector-native.ts
|
|
@@ -1266,7 +1515,7 @@ var NATIVE_PAGE_HEALTH_PRODUCER_ID = "sdk-native/page-health";
|
|
|
1266
1515
|
function defaultProducer() {
|
|
1267
1516
|
return {
|
|
1268
1517
|
id: NATIVE_PAGE_HEALTH_PRODUCER_ID,
|
|
1269
|
-
version: "0.
|
|
1518
|
+
version: "0.8.0"
|
|
1270
1519
|
};
|
|
1271
1520
|
}
|
|
1272
1521
|
function pageHealthUnknown(code, detail, options = {}) {
|
|
@@ -1308,14 +1557,7 @@ var LOADING_PHRASES = [
|
|
|
1308
1557
|
"initializing",
|
|
1309
1558
|
"fetching"
|
|
1310
1559
|
];
|
|
1311
|
-
var EMPTY_PHRASES = [
|
|
1312
|
-
"no data",
|
|
1313
|
-
"no results",
|
|
1314
|
-
"nothing here",
|
|
1315
|
-
"empty",
|
|
1316
|
-
"no items",
|
|
1317
|
-
"get started"
|
|
1318
|
-
];
|
|
1560
|
+
var EMPTY_PHRASES = ["no data", "no results", "nothing here", "empty", "no items", "get started"];
|
|
1319
1561
|
function severityRank(s) {
|
|
1320
1562
|
if (s === "CRITICAL") return 3;
|
|
1321
1563
|
if (s === "WARNING") return 2;
|
|
@@ -1390,20 +1632,44 @@ function observe(input, producer, evaluatedAt) {
|
|
|
1390
1632
|
}
|
|
1391
1633
|
return analyze(elements, viewport, base);
|
|
1392
1634
|
}
|
|
1635
|
+
function nothingOnScreenDetail(elements, visibleCount, visibilityUnstated) {
|
|
1636
|
+
if (visibilityUnstated === 0 && visibleCount > 0) {
|
|
1637
|
+
return `all ${visibleCount} visible element(s) have no measured layout yet, so spatial coverage, layout regions and visual anomalies cannot be measured`;
|
|
1638
|
+
}
|
|
1639
|
+
if (visibilityUnstated > 0) {
|
|
1640
|
+
const geometry = visibleCount > 0 ? ` and none of the ${visibleCount} visible one(s) has a measured layout` : "";
|
|
1641
|
+
return `${visibilityUnstated} of ${elements.length} element(s) carry no boolean \`state.visible\`${geometry}, so no element can be placed on screen; spatial coverage, layout regions and visual anomalies cannot be measured`;
|
|
1642
|
+
}
|
|
1643
|
+
const unmounted = elements.filter((el) => el.state?.mounted === false).length;
|
|
1644
|
+
return `all ${elements.length} registered element(s) report visible: false (unmounted=${unmounted}, off-screen route or otherwise=${elements.length - unmounted}), so whatever is on screen is not a registered element and there is nothing on screen to measure; this says nothing about whether the screen is blank`;
|
|
1645
|
+
}
|
|
1393
1646
|
function analyze(elements, viewport, base) {
|
|
1394
1647
|
const findings = [];
|
|
1395
|
-
const
|
|
1396
|
-
const
|
|
1648
|
+
const onScreen = elements.filter((el) => el.state?.visible === true);
|
|
1649
|
+
const visibilityUnstated = elements.filter(
|
|
1650
|
+
(el) => typeof el.state?.visible !== "boolean"
|
|
1651
|
+
).length;
|
|
1652
|
+
const visible = onScreen.flatMap((el) => {
|
|
1397
1653
|
const rect = normalizeRect(el.state, viewport);
|
|
1398
1654
|
return rect ? [{ el, rect }] : [];
|
|
1399
1655
|
});
|
|
1400
|
-
const withoutGeometry =
|
|
1401
|
-
const unmeasured =
|
|
1402
|
-
|
|
1403
|
-
|
|
1656
|
+
const withoutGeometry = onScreen.length - visible.length;
|
|
1657
|
+
const unmeasured = [];
|
|
1658
|
+
if (withoutGeometry > 0) {
|
|
1659
|
+
unmeasured.push({ dimension: "geometry", count: withoutGeometry, code: "input_missing" });
|
|
1660
|
+
}
|
|
1661
|
+
if (visibilityUnstated > 0) {
|
|
1662
|
+
unmeasured.push({ dimension: "visibility", count: visibilityUnstated, code: "input_missing" });
|
|
1663
|
+
}
|
|
1664
|
+
const coverage = {
|
|
1665
|
+
considered: onScreen.length + visibilityUnstated,
|
|
1666
|
+
measured: visible.length,
|
|
1667
|
+
unmeasured
|
|
1668
|
+
};
|
|
1669
|
+
if (elements.length > 0 && visible.length === 0) {
|
|
1404
1670
|
return Observation.unknown(
|
|
1405
1671
|
"input_missing",
|
|
1406
|
-
|
|
1672
|
+
nothingOnScreenDetail(elements, onScreen.length, visibilityUnstated),
|
|
1407
1673
|
Observation.provenance({ ...base, coverage })
|
|
1408
1674
|
);
|
|
1409
1675
|
}
|
|
@@ -1493,7 +1759,7 @@ function analyze(elements, viewport, base) {
|
|
|
1493
1759
|
for (const el of elements) {
|
|
1494
1760
|
const elType = el.type ?? "";
|
|
1495
1761
|
if (SKIP_TEXT_TYPES.has(elType)) continue;
|
|
1496
|
-
const text = (el.state
|
|
1762
|
+
const text = (el.state?.textContent ?? "").toString();
|
|
1497
1763
|
if (!text) continue;
|
|
1498
1764
|
const textLower = text.toLowerCase();
|
|
1499
1765
|
for (const p of ERROR_PHRASES) {
|
|
@@ -1534,7 +1800,7 @@ function analyze(elements, viewport, base) {
|
|
|
1534
1800
|
for (const el of elements) {
|
|
1535
1801
|
if (!INTERACTIVE_TYPES2.has(el.type)) continue;
|
|
1536
1802
|
interactiveTotal++;
|
|
1537
|
-
if (el.state
|
|
1803
|
+
if (el.state?.enabled === false) interactiveDisabled++;
|
|
1538
1804
|
}
|
|
1539
1805
|
const interactiveSeverity = interactiveTotal > 0 && interactiveDisabled / interactiveTotal > 0.5 ? "WARNING" : "OK";
|
|
1540
1806
|
findings.push({
|
|
@@ -1558,9 +1824,7 @@ function analyze(elements, viewport, base) {
|
|
|
1558
1824
|
detail: `zero_size=${zeroSize}, outside_viewport=${outsideViewport} (horizontal-overflow only; below/above-fold scrollable content is not an anomaly)`,
|
|
1559
1825
|
data: { zero_size: zeroSize, outside_viewport: outsideViewport }
|
|
1560
1826
|
});
|
|
1561
|
-
const heatmap = grid.map(
|
|
1562
|
-
(row) => row.map((cell) => cell ? "#" : ".").join("")
|
|
1563
|
-
);
|
|
1827
|
+
const heatmap = grid.map((row) => row.map((cell) => cell ? "#" : ".").join(""));
|
|
1564
1828
|
return Observation.measured(
|
|
1565
1829
|
{
|
|
1566
1830
|
summary: worstSeverity(findings),
|
|
@@ -1820,10 +2084,9 @@ function createServerHandlers(registry, executor, config) {
|
|
|
1820
2084
|
const elements = allElements.map((e) => {
|
|
1821
2085
|
const handlers = extractHandlerNames(e.props);
|
|
1822
2086
|
const state = e.getState();
|
|
1823
|
-
const
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
);
|
|
2087
|
+
const identifier = e.getIdentifier();
|
|
2088
|
+
const clip = registry.getClipRectFor(e, viewport);
|
|
2089
|
+
const { visibility, visibilityReason } = computeVisibility(state, clip);
|
|
1827
2090
|
const bbox = projectBbox(state, visibility, registry.getPixelRatio());
|
|
1828
2091
|
const vision = projectVisionFields({
|
|
1829
2092
|
type: e.type,
|
|
@@ -1832,13 +2095,16 @@ function createServerHandlers(registry, executor, config) {
|
|
|
1832
2095
|
// synthesize press/click onto every element. See projectVisionFields.
|
|
1833
2096
|
handlerNames: handlers,
|
|
1834
2097
|
state,
|
|
1835
|
-
flatStyle: e.flatStyle
|
|
2098
|
+
flatStyle: e.flatStyle,
|
|
2099
|
+
props: e.props,
|
|
2100
|
+
accessibilityLabel: identifier.accessibilityLabel,
|
|
2101
|
+
inViewport: computeInViewport(state, clip)
|
|
1836
2102
|
});
|
|
1837
2103
|
return {
|
|
1838
2104
|
id: e.id,
|
|
1839
2105
|
type: e.type,
|
|
1840
2106
|
label: e.label,
|
|
1841
|
-
identifier
|
|
2107
|
+
identifier,
|
|
1842
2108
|
state,
|
|
1843
2109
|
actions: e.actions,
|
|
1844
2110
|
customActions: serializeElementCustomActions(e.customActions),
|
|
@@ -2546,7 +2812,7 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2546
2812
|
};
|
|
2547
2813
|
if (config?.appInfo) {
|
|
2548
2814
|
response.uiBridge = {
|
|
2549
|
-
version: "0.
|
|
2815
|
+
version: "0.8.0",
|
|
2550
2816
|
...config.appInfo,
|
|
2551
2817
|
capabilities: ["elements", "components", "actions", "design"],
|
|
2552
2818
|
elementCount: stats.elements,
|