@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
package/dist/index.js
CHANGED
|
@@ -11,6 +11,164 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
11
11
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
+
// src/core/sha256.ts
|
|
15
|
+
var K = new Uint32Array([
|
|
16
|
+
1116352408,
|
|
17
|
+
1899447441,
|
|
18
|
+
3049323471,
|
|
19
|
+
3921009573,
|
|
20
|
+
961987163,
|
|
21
|
+
1508970993,
|
|
22
|
+
2453635748,
|
|
23
|
+
2870763221,
|
|
24
|
+
3624381080,
|
|
25
|
+
310598401,
|
|
26
|
+
607225278,
|
|
27
|
+
1426881987,
|
|
28
|
+
1925078388,
|
|
29
|
+
2162078206,
|
|
30
|
+
2614888103,
|
|
31
|
+
3248222580,
|
|
32
|
+
3835390401,
|
|
33
|
+
4022224774,
|
|
34
|
+
264347078,
|
|
35
|
+
604807628,
|
|
36
|
+
770255983,
|
|
37
|
+
1249150122,
|
|
38
|
+
1555081692,
|
|
39
|
+
1996064986,
|
|
40
|
+
2554220882,
|
|
41
|
+
2821834349,
|
|
42
|
+
2952996808,
|
|
43
|
+
3210313671,
|
|
44
|
+
3336571891,
|
|
45
|
+
3584528711,
|
|
46
|
+
113926993,
|
|
47
|
+
338241895,
|
|
48
|
+
666307205,
|
|
49
|
+
773529912,
|
|
50
|
+
1294757372,
|
|
51
|
+
1396182291,
|
|
52
|
+
1695183700,
|
|
53
|
+
1986661051,
|
|
54
|
+
2177026350,
|
|
55
|
+
2456956037,
|
|
56
|
+
2730485921,
|
|
57
|
+
2820302411,
|
|
58
|
+
3259730800,
|
|
59
|
+
3345764771,
|
|
60
|
+
3516065817,
|
|
61
|
+
3600352804,
|
|
62
|
+
4094571909,
|
|
63
|
+
275423344,
|
|
64
|
+
430227734,
|
|
65
|
+
506948616,
|
|
66
|
+
659060556,
|
|
67
|
+
883997877,
|
|
68
|
+
958139571,
|
|
69
|
+
1322822218,
|
|
70
|
+
1537002063,
|
|
71
|
+
1747873779,
|
|
72
|
+
1955562222,
|
|
73
|
+
2024104815,
|
|
74
|
+
2227730452,
|
|
75
|
+
2361852424,
|
|
76
|
+
2428436474,
|
|
77
|
+
2756734187,
|
|
78
|
+
3204031479,
|
|
79
|
+
3329325298
|
|
80
|
+
]);
|
|
81
|
+
var H0 = [
|
|
82
|
+
1779033703,
|
|
83
|
+
3144134277,
|
|
84
|
+
1013904242,
|
|
85
|
+
2773480762,
|
|
86
|
+
1359893119,
|
|
87
|
+
2600822924,
|
|
88
|
+
528734635,
|
|
89
|
+
1541459225
|
|
90
|
+
];
|
|
91
|
+
function utf8Bytes(input) {
|
|
92
|
+
const out = [];
|
|
93
|
+
for (let i = 0; i < input.length; i++) {
|
|
94
|
+
let cp = input.charCodeAt(i);
|
|
95
|
+
if (cp >= 55296 && cp <= 56319) {
|
|
96
|
+
const next = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
|
|
97
|
+
if (next >= 56320 && next <= 57343) {
|
|
98
|
+
cp = 65536 + (cp - 55296 << 10) + (next - 56320);
|
|
99
|
+
i++;
|
|
100
|
+
} else {
|
|
101
|
+
cp = 65533;
|
|
102
|
+
}
|
|
103
|
+
} else if (cp >= 56320 && cp <= 57343) {
|
|
104
|
+
cp = 65533;
|
|
105
|
+
}
|
|
106
|
+
if (cp < 128) {
|
|
107
|
+
out.push(cp);
|
|
108
|
+
} else if (cp < 2048) {
|
|
109
|
+
out.push(192 | cp >> 6, 128 | cp & 63);
|
|
110
|
+
} else if (cp < 65536) {
|
|
111
|
+
out.push(224 | cp >> 12, 128 | cp >> 6 & 63, 128 | cp & 63);
|
|
112
|
+
} else {
|
|
113
|
+
out.push(
|
|
114
|
+
240 | cp >> 18,
|
|
115
|
+
128 | cp >> 12 & 63,
|
|
116
|
+
128 | cp >> 6 & 63,
|
|
117
|
+
128 | cp & 63
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return Uint8Array.from(out);
|
|
122
|
+
}
|
|
123
|
+
var rotr = (x, n) => x >>> n | x << 32 - n;
|
|
124
|
+
function sha256Hex(input) {
|
|
125
|
+
const bytes = utf8Bytes(input);
|
|
126
|
+
const blockBytes = Math.ceil((bytes.length + 9) / 64) * 64;
|
|
127
|
+
const buffer = new Uint8Array(blockBytes);
|
|
128
|
+
buffer.set(bytes);
|
|
129
|
+
buffer[bytes.length] = 128;
|
|
130
|
+
const view = new DataView(buffer.buffer);
|
|
131
|
+
const bitLength = bytes.length * 8;
|
|
132
|
+
view.setUint32(blockBytes - 8, Math.floor(bitLength / 4294967296));
|
|
133
|
+
view.setUint32(blockBytes - 4, bitLength >>> 0);
|
|
134
|
+
const h = H0.slice();
|
|
135
|
+
const w = new Uint32Array(64);
|
|
136
|
+
for (let block = 0; block < blockBytes; block += 64) {
|
|
137
|
+
for (let t = 0; t < 16; t++) w[t] = view.getUint32(block + t * 4);
|
|
138
|
+
for (let t = 16; t < 64; t++) {
|
|
139
|
+
const s0 = rotr(w[t - 15], 7) ^ rotr(w[t - 15], 18) ^ w[t - 15] >>> 3;
|
|
140
|
+
const s1 = rotr(w[t - 2], 17) ^ rotr(w[t - 2], 19) ^ w[t - 2] >>> 10;
|
|
141
|
+
w[t] = w[t - 16] + s0 + w[t - 7] + s1;
|
|
142
|
+
}
|
|
143
|
+
let [a, b, c, d, e, f, g, hh] = h;
|
|
144
|
+
for (let t = 0; t < 64; t++) {
|
|
145
|
+
const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
|
|
146
|
+
const ch = e & f ^ ~e & g;
|
|
147
|
+
const t1 = hh + S1 + ch + K[t] + w[t] | 0;
|
|
148
|
+
const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
|
|
149
|
+
const maj = a & b ^ a & c ^ b & c;
|
|
150
|
+
const t2 = S0 + maj | 0;
|
|
151
|
+
hh = g;
|
|
152
|
+
g = f;
|
|
153
|
+
f = e;
|
|
154
|
+
e = d + t1 | 0;
|
|
155
|
+
d = c;
|
|
156
|
+
c = b;
|
|
157
|
+
b = a;
|
|
158
|
+
a = t1 + t2 | 0;
|
|
159
|
+
}
|
|
160
|
+
h[0] = h[0] + a | 0;
|
|
161
|
+
h[1] = h[1] + b | 0;
|
|
162
|
+
h[2] = h[2] + c | 0;
|
|
163
|
+
h[3] = h[3] + d | 0;
|
|
164
|
+
h[4] = h[4] + e | 0;
|
|
165
|
+
h[5] = h[5] + f | 0;
|
|
166
|
+
h[6] = h[6] + g | 0;
|
|
167
|
+
h[7] = h[7] + hh | 0;
|
|
168
|
+
}
|
|
169
|
+
return h.map((word) => (word >>> 0).toString(16).padStart(8, "0")).join("");
|
|
170
|
+
}
|
|
171
|
+
|
|
14
172
|
// src/core/vision-fields.ts
|
|
15
173
|
var INTERACTIVE_HANDLER_NAMES = /* @__PURE__ */ new Set([
|
|
16
174
|
"onPress",
|
|
@@ -94,13 +252,18 @@ var NAMED_COLORS = {
|
|
|
94
252
|
gray: { r: 128, g: 128, b: 128 },
|
|
95
253
|
grey: { r: 128, g: 128, b: 128 },
|
|
96
254
|
silver: { r: 192, g: 192, b: 192 },
|
|
97
|
-
transparent: { r: 0, g: 0, b: 0 },
|
|
98
255
|
orange: { r: 255, g: 165, b: 0 },
|
|
99
256
|
yellow: { r: 255, g: 255, b: 0 },
|
|
100
257
|
purple: { r: 128, g: 0, b: 128 },
|
|
101
258
|
navy: { r: 0, g: 0, b: 128 }
|
|
102
259
|
};
|
|
103
260
|
var clamp255 = (n) => Math.max(0, Math.min(255, Math.round(n)));
|
|
261
|
+
function parseAlpha(p) {
|
|
262
|
+
const pct = p.endsWith("%");
|
|
263
|
+
const n = parseFloat(pct ? p.slice(0, -1) : p);
|
|
264
|
+
if (!Number.isFinite(n)) return void 0;
|
|
265
|
+
return Math.min(1, pct ? n / 100 : n);
|
|
266
|
+
}
|
|
104
267
|
function parseColorToRgb(input) {
|
|
105
268
|
if (typeof input !== "string") return void 0;
|
|
106
269
|
const raw = input.trim().toLowerCase();
|
|
@@ -111,6 +274,7 @@ function parseColorToRgb(input) {
|
|
|
111
274
|
if (raw.startsWith("#")) {
|
|
112
275
|
const hex = raw.slice(1);
|
|
113
276
|
if (hex.length === 3 || hex.length === 4) {
|
|
277
|
+
if (hex.length === 4 && hex[3] !== "f") return void 0;
|
|
114
278
|
const r = parseInt(hex[0] + hex[0], 16);
|
|
115
279
|
const g = parseInt(hex[1] + hex[1], 16);
|
|
116
280
|
const b = parseInt(hex[2] + hex[2], 16);
|
|
@@ -118,6 +282,7 @@ function parseColorToRgb(input) {
|
|
|
118
282
|
return void 0;
|
|
119
283
|
}
|
|
120
284
|
if (hex.length === 6 || hex.length === 8) {
|
|
285
|
+
if (hex.length === 8 && hex.slice(6, 8) !== "ff") return void 0;
|
|
121
286
|
const r = parseInt(hex.slice(0, 2), 16);
|
|
122
287
|
const g = parseInt(hex.slice(2, 4), 16);
|
|
123
288
|
const b = parseInt(hex.slice(4, 6), 16);
|
|
@@ -129,7 +294,11 @@ function parseColorToRgb(input) {
|
|
|
129
294
|
const rgbMatch = raw.match(/^rgba?\(([^)]+)\)$/);
|
|
130
295
|
if (rgbMatch) {
|
|
131
296
|
const parts = rgbMatch[1].split(",").map((p) => p.trim());
|
|
132
|
-
if (parts.length < 3) return void 0;
|
|
297
|
+
if (parts.length < 3 || parts.length > 4) return void 0;
|
|
298
|
+
if (parts.length === 4) {
|
|
299
|
+
const alpha = parseAlpha(parts[3]);
|
|
300
|
+
if (alpha === void 0 || alpha < 1) return void 0;
|
|
301
|
+
}
|
|
133
302
|
const channel = (p) => {
|
|
134
303
|
if (p.endsWith("%")) {
|
|
135
304
|
const pct = parseFloat(p.slice(0, -1));
|
|
@@ -161,13 +330,87 @@ function parseFontSizePx(input) {
|
|
|
161
330
|
}
|
|
162
331
|
return void 0;
|
|
163
332
|
}
|
|
333
|
+
var ASCII_WHITESPACE_EDGES = /^[\t\n\f\r ]+|[\t\n\f\r ]+$/g;
|
|
334
|
+
function nonEmptyString(v) {
|
|
335
|
+
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
336
|
+
}
|
|
337
|
+
var OBJECT_FIT_TO_RESIZE_MODE = /* @__PURE__ */ new Map([
|
|
338
|
+
["contain", "contain"],
|
|
339
|
+
["cover", "cover"],
|
|
340
|
+
["fill", "stretch"],
|
|
341
|
+
["scale-down", "contain"],
|
|
342
|
+
["none", "none"]
|
|
343
|
+
]);
|
|
344
|
+
var RESIZE_MODE_TO_OBJECT_FIT = /* @__PURE__ */ new Map([
|
|
345
|
+
["cover", "cover"],
|
|
346
|
+
["contain", "contain"],
|
|
347
|
+
["stretch", "fill"],
|
|
348
|
+
["center", "scale-down"],
|
|
349
|
+
["none", "none"]
|
|
350
|
+
]);
|
|
351
|
+
function resolveObjectFit(props, flatStyle) {
|
|
352
|
+
const styleFit = nonEmptyString(flatStyle?.objectFit);
|
|
353
|
+
const mode = (styleFit !== void 0 ? OBJECT_FIT_TO_RESIZE_MODE.get(styleFit) : void 0) ?? nonEmptyString(props?.resizeMode) ?? nonEmptyString(flatStyle?.resizeMode);
|
|
354
|
+
return mode !== void 0 ? RESIZE_MODE_TO_OBJECT_FIT.get(mode) : void 0;
|
|
355
|
+
}
|
|
356
|
+
function resolveImageSource(props) {
|
|
357
|
+
if (!props) return void 0;
|
|
358
|
+
if (props.srcSet !== void 0 && props.srcSet !== null) return void 0;
|
|
359
|
+
const src = nonEmptyString(props.src);
|
|
360
|
+
if (src !== void 0) return src;
|
|
361
|
+
const source = props.source;
|
|
362
|
+
const one = Array.isArray(source) ? source.length === 1 ? source[0] : void 0 : source;
|
|
363
|
+
if (one && typeof one === "object") {
|
|
364
|
+
return nonEmptyString(one.uri);
|
|
365
|
+
}
|
|
366
|
+
return void 0;
|
|
367
|
+
}
|
|
368
|
+
function isHiddenFromAccessibility(props) {
|
|
369
|
+
if (!props) return false;
|
|
370
|
+
return props.accessible === false && props.alt === void 0 || props.importantForAccessibility === "no" || props.importantForAccessibility === "no-hide-descendants" || props.accessibilityElementsHidden === true;
|
|
371
|
+
}
|
|
372
|
+
function resolveImageLabel(props, registryLabel) {
|
|
373
|
+
if (props === void 0) return registryLabel;
|
|
374
|
+
const own = props["aria-label"] ?? props.accessibilityLabel ?? props.alt;
|
|
375
|
+
return typeof own === "string" ? own : void 0;
|
|
376
|
+
}
|
|
377
|
+
function projectMedia(args) {
|
|
378
|
+
const { layout, props, flatStyle, accessibilityLabel, inViewport } = args;
|
|
379
|
+
const media = { kind: "img" };
|
|
380
|
+
if (layout && Number.isFinite(layout.width) && Number.isFinite(layout.height) && layout.width >= 0 && layout.height >= 0) {
|
|
381
|
+
media.rendered_px = { w: layout.width, h: layout.height };
|
|
382
|
+
}
|
|
383
|
+
const objectFit = resolveObjectFit(props, flatStyle);
|
|
384
|
+
if (objectFit !== void 0) media.object_fit = objectFit;
|
|
385
|
+
if (isHiddenFromAccessibility(props)) {
|
|
386
|
+
media.alt = { decorative: true };
|
|
387
|
+
} else {
|
|
388
|
+
const label = resolveImageLabel(props, accessibilityLabel);
|
|
389
|
+
const text = label?.replace(ASCII_WHITESPACE_EDGES, "");
|
|
390
|
+
if (text) media.alt = { decorative: false, text };
|
|
391
|
+
}
|
|
392
|
+
const src = resolveImageSource(props);
|
|
393
|
+
if (src !== void 0) media.src_digest = sha256Hex(src);
|
|
394
|
+
if (inViewport !== void 0) media.in_viewport = inViewport;
|
|
395
|
+
return media;
|
|
396
|
+
}
|
|
164
397
|
function projectVisionFields(args) {
|
|
165
398
|
const { type, label, handlerNames, state, flatStyle } = args;
|
|
166
399
|
const fields = {
|
|
167
400
|
interactable: deriveInteractable(type, handlerNames)
|
|
168
401
|
};
|
|
169
|
-
|
|
170
|
-
|
|
402
|
+
if (type === "image") {
|
|
403
|
+
fields.media = projectMedia({
|
|
404
|
+
layout: state.layout,
|
|
405
|
+
props: args.props,
|
|
406
|
+
flatStyle,
|
|
407
|
+
accessibilityLabel: args.accessibilityLabel,
|
|
408
|
+
inViewport: args.inViewport
|
|
409
|
+
});
|
|
410
|
+
} else {
|
|
411
|
+
const text = deriveText(state, label);
|
|
412
|
+
if (text !== void 0) fields.text = text;
|
|
413
|
+
}
|
|
171
414
|
const role = roleForType(type);
|
|
172
415
|
if (role !== void 0) fields.role = role;
|
|
173
416
|
if (flatStyle) {
|
|
@@ -307,11 +550,17 @@ function computeVisibility(state, clip) {
|
|
|
307
550
|
if (!rect) {
|
|
308
551
|
return { visibility: "visible" };
|
|
309
552
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
return
|
|
553
|
+
return rectReachesClip(rect, clip) ? { visibility: "visible" } : { visibility: "hidden", visibilityReason: "off-screen" };
|
|
554
|
+
}
|
|
555
|
+
function rectReachesClip(rect, clip) {
|
|
556
|
+
if (isEmptyRect(clip)) return false;
|
|
557
|
+
return spansOverlap(rect.left, rect.right, clip.left, clip.right) && spansOverlap(rect.top, rect.bottom, clip.top, clip.bottom);
|
|
558
|
+
}
|
|
559
|
+
function computeInViewport(state, clip) {
|
|
560
|
+
if (!state.visible || !clip) return void 0;
|
|
561
|
+
const rect = pageRectOf(state);
|
|
562
|
+
if (!rect) return void 0;
|
|
563
|
+
return rectReachesClip(rect, clip);
|
|
315
564
|
}
|
|
316
565
|
function copyRouteInfo(info) {
|
|
317
566
|
const copy = { ...info };
|
|
@@ -1254,10 +1503,9 @@ var NativeUIBridgeRegistry = class {
|
|
|
1254
1503
|
elements: elements.map((e) => {
|
|
1255
1504
|
const handlers = extractHandlerNames(e.props);
|
|
1256
1505
|
const state = e.getState();
|
|
1257
|
-
const
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
);
|
|
1506
|
+
const identifier = e.getIdentifier();
|
|
1507
|
+
const clip = this.getClipRectFor(e, viewport);
|
|
1508
|
+
const { visibility, visibilityReason } = computeVisibility(state, clip);
|
|
1261
1509
|
const bbox = projectBbox(state, visibility, this.pixelRatio);
|
|
1262
1510
|
const vision = projectVisionFields({
|
|
1263
1511
|
type: e.type,
|
|
@@ -1268,13 +1516,16 @@ var NativeUIBridgeRegistry = class {
|
|
|
1268
1516
|
// using it would mark plain text/view nodes interactable.
|
|
1269
1517
|
handlerNames: handlers,
|
|
1270
1518
|
state,
|
|
1271
|
-
flatStyle: e.flatStyle
|
|
1519
|
+
flatStyle: e.flatStyle,
|
|
1520
|
+
props: e.props,
|
|
1521
|
+
accessibilityLabel: identifier.accessibilityLabel,
|
|
1522
|
+
inViewport: computeInViewport(state, clip)
|
|
1272
1523
|
});
|
|
1273
1524
|
return {
|
|
1274
1525
|
id: e.id,
|
|
1275
1526
|
type: e.type,
|
|
1276
1527
|
label: e.label,
|
|
1277
|
-
identifier
|
|
1528
|
+
identifier,
|
|
1278
1529
|
state,
|
|
1279
1530
|
actions: e.actions,
|
|
1280
1531
|
customActions: serializeElementCustomActions(e.customActions),
|
|
@@ -3444,7 +3695,7 @@ var NATIVE_PAGE_HEALTH_PRODUCER_ID = "sdk-native/page-health";
|
|
|
3444
3695
|
function defaultProducer() {
|
|
3445
3696
|
return {
|
|
3446
3697
|
id: NATIVE_PAGE_HEALTH_PRODUCER_ID,
|
|
3447
|
-
version: "0.
|
|
3698
|
+
version: "0.8.0"
|
|
3448
3699
|
};
|
|
3449
3700
|
}
|
|
3450
3701
|
function pageHealthUnknown(code, detail, options = {}) {
|
|
@@ -3486,14 +3737,7 @@ var LOADING_PHRASES = [
|
|
|
3486
3737
|
"initializing",
|
|
3487
3738
|
"fetching"
|
|
3488
3739
|
];
|
|
3489
|
-
var EMPTY_PHRASES = [
|
|
3490
|
-
"no data",
|
|
3491
|
-
"no results",
|
|
3492
|
-
"nothing here",
|
|
3493
|
-
"empty",
|
|
3494
|
-
"no items",
|
|
3495
|
-
"get started"
|
|
3496
|
-
];
|
|
3740
|
+
var EMPTY_PHRASES = ["no data", "no results", "nothing here", "empty", "no items", "get started"];
|
|
3497
3741
|
function severityRank(s) {
|
|
3498
3742
|
if (s === "CRITICAL") return 3;
|
|
3499
3743
|
if (s === "WARNING") return 2;
|
|
@@ -3568,20 +3812,44 @@ function observe(input, producer, evaluatedAt) {
|
|
|
3568
3812
|
}
|
|
3569
3813
|
return analyze(elements, viewport, base);
|
|
3570
3814
|
}
|
|
3815
|
+
function nothingOnScreenDetail(elements, visibleCount, visibilityUnstated) {
|
|
3816
|
+
if (visibilityUnstated === 0 && visibleCount > 0) {
|
|
3817
|
+
return `all ${visibleCount} visible element(s) have no measured layout yet, so spatial coverage, layout regions and visual anomalies cannot be measured`;
|
|
3818
|
+
}
|
|
3819
|
+
if (visibilityUnstated > 0) {
|
|
3820
|
+
const geometry = visibleCount > 0 ? ` and none of the ${visibleCount} visible one(s) has a measured layout` : "";
|
|
3821
|
+
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`;
|
|
3822
|
+
}
|
|
3823
|
+
const unmounted = elements.filter((el) => el.state?.mounted === false).length;
|
|
3824
|
+
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`;
|
|
3825
|
+
}
|
|
3571
3826
|
function analyze(elements, viewport, base) {
|
|
3572
3827
|
const findings = [];
|
|
3573
|
-
const
|
|
3574
|
-
const
|
|
3828
|
+
const onScreen = elements.filter((el) => el.state?.visible === true);
|
|
3829
|
+
const visibilityUnstated = elements.filter(
|
|
3830
|
+
(el) => typeof el.state?.visible !== "boolean"
|
|
3831
|
+
).length;
|
|
3832
|
+
const visible = onScreen.flatMap((el) => {
|
|
3575
3833
|
const rect = normalizeRect(el.state, viewport);
|
|
3576
3834
|
return rect ? [{ el, rect }] : [];
|
|
3577
3835
|
});
|
|
3578
|
-
const withoutGeometry =
|
|
3579
|
-
const unmeasured =
|
|
3580
|
-
|
|
3581
|
-
|
|
3836
|
+
const withoutGeometry = onScreen.length - visible.length;
|
|
3837
|
+
const unmeasured = [];
|
|
3838
|
+
if (withoutGeometry > 0) {
|
|
3839
|
+
unmeasured.push({ dimension: "geometry", count: withoutGeometry, code: "input_missing" });
|
|
3840
|
+
}
|
|
3841
|
+
if (visibilityUnstated > 0) {
|
|
3842
|
+
unmeasured.push({ dimension: "visibility", count: visibilityUnstated, code: "input_missing" });
|
|
3843
|
+
}
|
|
3844
|
+
const coverage = {
|
|
3845
|
+
considered: onScreen.length + visibilityUnstated,
|
|
3846
|
+
measured: visible.length,
|
|
3847
|
+
unmeasured
|
|
3848
|
+
};
|
|
3849
|
+
if (elements.length > 0 && visible.length === 0) {
|
|
3582
3850
|
return Observation.unknown(
|
|
3583
3851
|
"input_missing",
|
|
3584
|
-
|
|
3852
|
+
nothingOnScreenDetail(elements, onScreen.length, visibilityUnstated),
|
|
3585
3853
|
Observation.provenance({ ...base, coverage })
|
|
3586
3854
|
);
|
|
3587
3855
|
}
|
|
@@ -3671,7 +3939,7 @@ function analyze(elements, viewport, base) {
|
|
|
3671
3939
|
for (const el of elements) {
|
|
3672
3940
|
const elType = el.type ?? "";
|
|
3673
3941
|
if (SKIP_TEXT_TYPES.has(elType)) continue;
|
|
3674
|
-
const text = (el.state
|
|
3942
|
+
const text = (el.state?.textContent ?? "").toString();
|
|
3675
3943
|
if (!text) continue;
|
|
3676
3944
|
const textLower = text.toLowerCase();
|
|
3677
3945
|
for (const p of ERROR_PHRASES) {
|
|
@@ -3712,7 +3980,7 @@ function analyze(elements, viewport, base) {
|
|
|
3712
3980
|
for (const el of elements) {
|
|
3713
3981
|
if (!INTERACTIVE_TYPES2.has(el.type)) continue;
|
|
3714
3982
|
interactiveTotal++;
|
|
3715
|
-
if (el.state
|
|
3983
|
+
if (el.state?.enabled === false) interactiveDisabled++;
|
|
3716
3984
|
}
|
|
3717
3985
|
const interactiveSeverity = interactiveTotal > 0 && interactiveDisabled / interactiveTotal > 0.5 ? "WARNING" : "OK";
|
|
3718
3986
|
findings.push({
|
|
@@ -3736,9 +4004,7 @@ function analyze(elements, viewport, base) {
|
|
|
3736
4004
|
detail: `zero_size=${zeroSize}, outside_viewport=${outsideViewport} (horizontal-overflow only; below/above-fold scrollable content is not an anomaly)`,
|
|
3737
4005
|
data: { zero_size: zeroSize, outside_viewport: outsideViewport }
|
|
3738
4006
|
});
|
|
3739
|
-
const heatmap = grid.map(
|
|
3740
|
-
(row) => row.map((cell) => cell ? "#" : ".").join("")
|
|
3741
|
-
);
|
|
4007
|
+
const heatmap = grid.map((row) => row.map((cell) => cell ? "#" : ".").join(""));
|
|
3742
4008
|
return Observation.measured(
|
|
3743
4009
|
{
|
|
3744
4010
|
summary: worstSeverity(findings),
|
|
@@ -3998,10 +4264,9 @@ function createServerHandlers(registry, executor, config) {
|
|
|
3998
4264
|
const elements = allElements.map((e) => {
|
|
3999
4265
|
const handlers = extractHandlerNames(e.props);
|
|
4000
4266
|
const state = e.getState();
|
|
4001
|
-
const
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
);
|
|
4267
|
+
const identifier = e.getIdentifier();
|
|
4268
|
+
const clip = registry.getClipRectFor(e, viewport);
|
|
4269
|
+
const { visibility, visibilityReason } = computeVisibility(state, clip);
|
|
4005
4270
|
const bbox = projectBbox(state, visibility, registry.getPixelRatio());
|
|
4006
4271
|
const vision = projectVisionFields({
|
|
4007
4272
|
type: e.type,
|
|
@@ -4010,13 +4275,16 @@ function createServerHandlers(registry, executor, config) {
|
|
|
4010
4275
|
// synthesize press/click onto every element. See projectVisionFields.
|
|
4011
4276
|
handlerNames: handlers,
|
|
4012
4277
|
state,
|
|
4013
|
-
flatStyle: e.flatStyle
|
|
4278
|
+
flatStyle: e.flatStyle,
|
|
4279
|
+
props: e.props,
|
|
4280
|
+
accessibilityLabel: identifier.accessibilityLabel,
|
|
4281
|
+
inViewport: computeInViewport(state, clip)
|
|
4014
4282
|
});
|
|
4015
4283
|
return {
|
|
4016
4284
|
id: e.id,
|
|
4017
4285
|
type: e.type,
|
|
4018
4286
|
label: e.label,
|
|
4019
|
-
identifier
|
|
4287
|
+
identifier,
|
|
4020
4288
|
state,
|
|
4021
4289
|
actions: e.actions,
|
|
4022
4290
|
customActions: serializeElementCustomActions(e.customActions),
|
|
@@ -4724,7 +4992,7 @@ function createServerHandlers(registry, executor, config) {
|
|
|
4724
4992
|
};
|
|
4725
4993
|
if (config?.appInfo) {
|
|
4726
4994
|
response.uiBridge = {
|
|
4727
|
-
version: "0.
|
|
4995
|
+
version: "0.8.0",
|
|
4728
4996
|
...config.appInfo,
|
|
4729
4997
|
capabilities: ["elements", "components", "actions", "design"],
|
|
4730
4998
|
elementCount: stats.elements,
|
|
@@ -8222,7 +8490,9 @@ function useUIBridgeModal(opts) {
|
|
|
8222
8490
|
}, [modalDetector, id, title, type, blocking, dismissible]);
|
|
8223
8491
|
}
|
|
8224
8492
|
function effectiveInfo(info, unmatched) {
|
|
8225
|
-
|
|
8493
|
+
if (!unmatched) return info;
|
|
8494
|
+
const { params: _dropped, ...rest } = info;
|
|
8495
|
+
return { ...rest, pattern: null };
|
|
8226
8496
|
}
|
|
8227
8497
|
function useRouteAwareness(info, options = {}) {
|
|
8228
8498
|
const bridge = useUIBridgeNativeOptional();
|
|
@@ -9476,6 +9746,7 @@ exports.buildUpgradeResponse = buildUpgradeResponse;
|
|
|
9476
9746
|
exports.captureNativeResponsiveSnapshot = captureNativeResponsiveSnapshot;
|
|
9477
9747
|
exports.captureNativeStateVariations = captureNativeStateVariations;
|
|
9478
9748
|
exports.computeAcceptKey = computeAcceptKey;
|
|
9749
|
+
exports.computeInViewport = computeInViewport;
|
|
9479
9750
|
exports.computeVisibility = computeVisibility;
|
|
9480
9751
|
exports.createDesignHandlers = createDesignHandlers;
|
|
9481
9752
|
exports.createNativeActionExecutor = createNativeActionExecutor;
|
|
@@ -9499,6 +9770,7 @@ exports.intersectRects = intersectRects;
|
|
|
9499
9770
|
exports.isAddrInUseError = isAddrInUseError;
|
|
9500
9771
|
exports.isEmptyRect = isEmptyRect;
|
|
9501
9772
|
exports.isExpoRouterUnmatched = isExpoRouterUnmatched;
|
|
9773
|
+
exports.isHiddenFromAccessibility = isHiddenFromAccessibility;
|
|
9502
9774
|
exports.mapNativeStyleToExtended = mapNativeStyleToExtended;
|
|
9503
9775
|
exports.matchesIdentifier = matchesIdentifier;
|
|
9504
9776
|
exports.nativeStandardActionEffect = nativeStandardActionEffect;
|
|
@@ -9507,11 +9779,15 @@ exports.pageRectOf = pageRectOf;
|
|
|
9507
9779
|
exports.parseColorToRgb = parseColorToRgb;
|
|
9508
9780
|
exports.parseFontSizePx = parseFontSizePx;
|
|
9509
9781
|
exports.parseTreePath = parseTreePath;
|
|
9782
|
+
exports.projectMedia = projectMedia;
|
|
9510
9783
|
exports.projectVisionFields = projectVisionFields;
|
|
9511
9784
|
exports.reactNavigationPattern = reactNavigationPattern;
|
|
9512
9785
|
exports.resetDefaultParamValidationMode = resetDefaultParamValidationMode;
|
|
9513
9786
|
exports.resetGlobalRegistry = resetGlobalRegistry;
|
|
9514
9787
|
exports.resolveActionEffect = resolveActionEffect;
|
|
9788
|
+
exports.resolveImageLabel = resolveImageLabel;
|
|
9789
|
+
exports.resolveImageSource = resolveImageSource;
|
|
9790
|
+
exports.resolveObjectFit = resolveObjectFit;
|
|
9515
9791
|
exports.roleForType = roleForType;
|
|
9516
9792
|
exports.runAbortable = runAbortable;
|
|
9517
9793
|
exports.setDefaultParamValidationMode = setDefaultParamValidationMode;
|