@qontinui/ui-bridge-native 0.6.10 → 0.6.12
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/core/index.js +329 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +329 -2
- package/dist/core/index.mjs.map +1 -1
- package/dist/core/registry.d.ts +91 -1
- package/dist/core/registry.d.ts.map +1 -1
- package/dist/core/types.d.ts +114 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/vision-fields.d.ts +142 -0
- package/dist/core/vision-fields.d.ts.map +1 -0
- package/dist/debug/index.js.map +1 -1
- package/dist/debug/index.mjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +412 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +408 -14
- package/dist/index.mjs.map +1 -1
- package/dist/react/UIBridgeNativeProvider.d.ts.map +1 -1
- package/dist/react/index.js +406 -12
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +407 -13
- package/dist/react/index.mjs.map +1 -1
- package/dist/react/useUIElement.d.ts.map +1 -1
- package/dist/server/handlers.d.ts.map +1 -1
- package/dist/server/http-server.d.ts +9 -1
- package/dist/server/http-server.d.ts.map +1 -1
- package/dist/server/index.js +220 -5
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +220 -5
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/observability.d.ts +4 -3
- package/dist/server/observability.d.ts.map +1 -1
- package/dist/server/types.d.ts +10 -0
- package/dist/server/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UIBridgeNativeProvider.d.ts","sourceRoot":"","sources":["../../src/react/UIBridgeNativeProvider.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"UIBridgeNativeProvider.d.ts","sourceRoot":"","sources":["../../src/react/UIBridgeNativeProvider.tsx"],"names":[],"mappings":"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"}
|
package/dist/react/index.js
CHANGED
|
@@ -11,6 +11,179 @@ 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/vision-fields.ts
|
|
15
|
+
var INTERACTIVE_HANDLER_NAMES = /* @__PURE__ */ new Set([
|
|
16
|
+
"onPress",
|
|
17
|
+
"onPressIn",
|
|
18
|
+
"onPressOut",
|
|
19
|
+
"onLongPress",
|
|
20
|
+
"onChangeText",
|
|
21
|
+
"onValueChange",
|
|
22
|
+
"onChange",
|
|
23
|
+
"onSubmitEditing",
|
|
24
|
+
"onClick",
|
|
25
|
+
"onTouchStart",
|
|
26
|
+
"onTouchEnd"
|
|
27
|
+
]);
|
|
28
|
+
var INTERACTIVE_TYPES = /* @__PURE__ */ new Set([
|
|
29
|
+
"button",
|
|
30
|
+
"input",
|
|
31
|
+
"switch",
|
|
32
|
+
"checkbox",
|
|
33
|
+
"radio",
|
|
34
|
+
"touchable",
|
|
35
|
+
"pressable",
|
|
36
|
+
"listItem"
|
|
37
|
+
]);
|
|
38
|
+
function roleForType(type) {
|
|
39
|
+
switch (type) {
|
|
40
|
+
case "button":
|
|
41
|
+
case "touchable":
|
|
42
|
+
case "pressable":
|
|
43
|
+
return "button";
|
|
44
|
+
case "input":
|
|
45
|
+
return "textbox";
|
|
46
|
+
case "text":
|
|
47
|
+
return "text";
|
|
48
|
+
case "switch":
|
|
49
|
+
return "switch";
|
|
50
|
+
case "checkbox":
|
|
51
|
+
return "checkbox";
|
|
52
|
+
case "radio":
|
|
53
|
+
return "radio";
|
|
54
|
+
case "image":
|
|
55
|
+
return "img";
|
|
56
|
+
case "list":
|
|
57
|
+
return "list";
|
|
58
|
+
case "listItem":
|
|
59
|
+
return "listitem";
|
|
60
|
+
case "modal":
|
|
61
|
+
return "dialog";
|
|
62
|
+
case "scroll":
|
|
63
|
+
case "view":
|
|
64
|
+
case "custom":
|
|
65
|
+
default:
|
|
66
|
+
return void 0;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function deriveInteractable(type, handlerNames) {
|
|
70
|
+
if (INTERACTIVE_TYPES.has(type)) return true;
|
|
71
|
+
if (handlerNames) {
|
|
72
|
+
for (const name of handlerNames) {
|
|
73
|
+
if (INTERACTIVE_HANDLER_NAMES.has(name)) return true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
function deriveText(state, label) {
|
|
79
|
+
const candidates = [state.value, state.textContent, label];
|
|
80
|
+
for (const c of candidates) {
|
|
81
|
+
if (typeof c === "string") {
|
|
82
|
+
const trimmed = c.trim();
|
|
83
|
+
if (trimmed.length > 0) return trimmed;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return void 0;
|
|
87
|
+
}
|
|
88
|
+
var NAMED_COLORS = {
|
|
89
|
+
black: { r: 0, g: 0, b: 0 },
|
|
90
|
+
white: { r: 255, g: 255, b: 255 },
|
|
91
|
+
red: { r: 255, g: 0, b: 0 },
|
|
92
|
+
green: { r: 0, g: 128, b: 0 },
|
|
93
|
+
blue: { r: 0, g: 0, b: 255 },
|
|
94
|
+
gray: { r: 128, g: 128, b: 128 },
|
|
95
|
+
grey: { r: 128, g: 128, b: 128 },
|
|
96
|
+
silver: { r: 192, g: 192, b: 192 },
|
|
97
|
+
transparent: { r: 0, g: 0, b: 0 },
|
|
98
|
+
orange: { r: 255, g: 165, b: 0 },
|
|
99
|
+
yellow: { r: 255, g: 255, b: 0 },
|
|
100
|
+
purple: { r: 128, g: 0, b: 128 },
|
|
101
|
+
navy: { r: 0, g: 0, b: 128 }
|
|
102
|
+
};
|
|
103
|
+
var clamp255 = (n) => Math.max(0, Math.min(255, Math.round(n)));
|
|
104
|
+
function parseColorToRgb(input) {
|
|
105
|
+
if (typeof input !== "string") return void 0;
|
|
106
|
+
const raw = input.trim().toLowerCase();
|
|
107
|
+
if (raw.length === 0) return void 0;
|
|
108
|
+
if (Object.prototype.hasOwnProperty.call(NAMED_COLORS, raw)) {
|
|
109
|
+
return NAMED_COLORS[raw];
|
|
110
|
+
}
|
|
111
|
+
if (raw.startsWith("#")) {
|
|
112
|
+
const hex = raw.slice(1);
|
|
113
|
+
if (hex.length === 3 || hex.length === 4) {
|
|
114
|
+
const r = parseInt(hex[0] + hex[0], 16);
|
|
115
|
+
const g = parseInt(hex[1] + hex[1], 16);
|
|
116
|
+
const b = parseInt(hex[2] + hex[2], 16);
|
|
117
|
+
if ([r, g, b].every((v) => Number.isFinite(v))) return { r, g, b };
|
|
118
|
+
return void 0;
|
|
119
|
+
}
|
|
120
|
+
if (hex.length === 6 || hex.length === 8) {
|
|
121
|
+
const r = parseInt(hex.slice(0, 2), 16);
|
|
122
|
+
const g = parseInt(hex.slice(2, 4), 16);
|
|
123
|
+
const b = parseInt(hex.slice(4, 6), 16);
|
|
124
|
+
if ([r, g, b].every((v) => Number.isFinite(v))) return { r, g, b };
|
|
125
|
+
return void 0;
|
|
126
|
+
}
|
|
127
|
+
return void 0;
|
|
128
|
+
}
|
|
129
|
+
const rgbMatch = raw.match(/^rgba?\(([^)]+)\)$/);
|
|
130
|
+
if (rgbMatch) {
|
|
131
|
+
const parts = rgbMatch[1].split(",").map((p) => p.trim());
|
|
132
|
+
if (parts.length < 3) return void 0;
|
|
133
|
+
const channel = (p) => {
|
|
134
|
+
if (p.endsWith("%")) {
|
|
135
|
+
const pct = parseFloat(p.slice(0, -1));
|
|
136
|
+
if (!Number.isFinite(pct)) return void 0;
|
|
137
|
+
return clamp255(pct / 100 * 255);
|
|
138
|
+
}
|
|
139
|
+
const n = parseFloat(p);
|
|
140
|
+
if (!Number.isFinite(n)) return void 0;
|
|
141
|
+
return clamp255(n);
|
|
142
|
+
};
|
|
143
|
+
const r = channel(parts[0]);
|
|
144
|
+
const g = channel(parts[1]);
|
|
145
|
+
const b = channel(parts[2]);
|
|
146
|
+
if (r === void 0 || g === void 0 || b === void 0) return void 0;
|
|
147
|
+
return { r, g, b };
|
|
148
|
+
}
|
|
149
|
+
return void 0;
|
|
150
|
+
}
|
|
151
|
+
function parseFontSizePx(input) {
|
|
152
|
+
if (typeof input === "number") {
|
|
153
|
+
return Number.isFinite(input) && input > 0 ? input : void 0;
|
|
154
|
+
}
|
|
155
|
+
if (typeof input === "string") {
|
|
156
|
+
const m = input.trim().match(/^(-?\d*\.?\d+)/);
|
|
157
|
+
if (m) {
|
|
158
|
+
const n = parseFloat(m[1]);
|
|
159
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return void 0;
|
|
163
|
+
}
|
|
164
|
+
function projectVisionFields(args) {
|
|
165
|
+
const { type, label, handlerNames, state, flatStyle } = args;
|
|
166
|
+
const fields = {
|
|
167
|
+
interactable: deriveInteractable(type, handlerNames)
|
|
168
|
+
};
|
|
169
|
+
const text = deriveText(state, label);
|
|
170
|
+
if (text !== void 0) fields.text = text;
|
|
171
|
+
const role = roleForType(type);
|
|
172
|
+
if (role !== void 0) fields.role = role;
|
|
173
|
+
if (flatStyle) {
|
|
174
|
+
const fg = parseColorToRgb(flatStyle.color);
|
|
175
|
+
if (fg !== void 0) fields.fg_color = fg;
|
|
176
|
+
const bg = parseColorToRgb(flatStyle.backgroundColor);
|
|
177
|
+
if (bg !== void 0) fields.bg_color = bg;
|
|
178
|
+
const size = parseFontSizePx(flatStyle.fontSize);
|
|
179
|
+
if (size !== void 0) fields.font_size_px = size;
|
|
180
|
+
if (typeof flatStyle.fontFamily === "string" && flatStyle.fontFamily.trim().length > 0) {
|
|
181
|
+
fields.font_family = flatStyle.fontFamily;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return fields;
|
|
185
|
+
}
|
|
186
|
+
|
|
14
187
|
// src/core/registry.ts
|
|
15
188
|
function extractHandlerNames(props) {
|
|
16
189
|
if (!props) return [];
|
|
@@ -20,6 +193,25 @@ function matchesCurrentRoute(registrationRoute, currentRoute) {
|
|
|
20
193
|
if (registrationRoute == null || registrationRoute === "") return true;
|
|
21
194
|
return registrationRoute === currentRoute;
|
|
22
195
|
}
|
|
196
|
+
function projectBbox(state, visibility, pixelRatio = 1) {
|
|
197
|
+
if (visibility !== "visible") return void 0;
|
|
198
|
+
const layout = state.layout;
|
|
199
|
+
if (!layout) return void 0;
|
|
200
|
+
const ratio = pixelRatio > 0 && Number.isFinite(pixelRatio) ? pixelRatio : 1;
|
|
201
|
+
const toPx = (v) => Math.max(0, Math.round(v * ratio));
|
|
202
|
+
const hasPage = typeof layout.pageX === "number" && typeof layout.pageY === "number" && Number.isFinite(layout.pageX) && Number.isFinite(layout.pageY);
|
|
203
|
+
const originX = hasPage ? layout.pageX : layout.x;
|
|
204
|
+
const originY = hasPage ? layout.pageY : layout.y;
|
|
205
|
+
if (typeof originX !== "number" || typeof originY !== "number" || typeof layout.width !== "number" || typeof layout.height !== "number" || !Number.isFinite(originX) || !Number.isFinite(originY) || !Number.isFinite(layout.width) || !Number.isFinite(layout.height)) {
|
|
206
|
+
return void 0;
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
x: toPx(originX),
|
|
210
|
+
y: toPx(originY),
|
|
211
|
+
w: toPx(layout.width),
|
|
212
|
+
h: toPx(layout.height)
|
|
213
|
+
};
|
|
214
|
+
}
|
|
23
215
|
function inferActions(type) {
|
|
24
216
|
const baseActions = ["focus", "blur"];
|
|
25
217
|
switch (type) {
|
|
@@ -84,6 +276,15 @@ var NativeUIBridgeRegistry = class {
|
|
|
84
276
|
* already installs.
|
|
85
277
|
*/
|
|
86
278
|
this.routeProvider = null;
|
|
279
|
+
/**
|
|
280
|
+
* Device pixel ratio used to project `state.layout` (logical dp) into the
|
|
281
|
+
* physical-pixel `bbox` emitted on each snapshot element. Defaults to `1`
|
|
282
|
+
* (dp ≈ px) so callers/tests that never inject a ratio still get a usable
|
|
283
|
+
* box; the React provider wires the real `PixelRatio.get()` via
|
|
284
|
+
* {@link setPixelRatio}. Read from a non-React core module on purpose — see
|
|
285
|
+
* the `projectBbox` doc comment for why we don't import `react-native` here.
|
|
286
|
+
*/
|
|
287
|
+
this.pixelRatio = 1;
|
|
87
288
|
/**
|
|
88
289
|
* Sticky flag: flips `true` the first time any element is registered and
|
|
89
290
|
* stays `true` even after elements are unregistered. Lets agents distinguish
|
|
@@ -121,6 +322,21 @@ var NativeUIBridgeRegistry = class {
|
|
|
121
322
|
getRouteProvider() {
|
|
122
323
|
return this.routeProvider;
|
|
123
324
|
}
|
|
325
|
+
/**
|
|
326
|
+
* Set the device pixel ratio used to project per-element `bbox` geometry
|
|
327
|
+
* into physical pixels. The React provider passes `PixelRatio.get()` here
|
|
328
|
+
* once at startup. Ignores non-finite / non-positive values (keeps the
|
|
329
|
+
* previous ratio) so a bad call can't zero out every bbox.
|
|
330
|
+
*/
|
|
331
|
+
setPixelRatio(ratio) {
|
|
332
|
+
if (typeof ratio === "number" && Number.isFinite(ratio) && ratio > 0) {
|
|
333
|
+
this.pixelRatio = ratio;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/** Read-only accessor for the device pixel ratio used for bbox projection. */
|
|
337
|
+
getPixelRatio() {
|
|
338
|
+
return this.pixelRatio;
|
|
339
|
+
}
|
|
124
340
|
// ============================================================================
|
|
125
341
|
// Snapshot Enricher Slots
|
|
126
342
|
// ============================================================================
|
|
@@ -346,6 +562,103 @@ var NativeUIBridgeRegistry = class {
|
|
|
346
562
|
console.log(`[ui-bridge-native] Marked ${cleared} elements offscreen for route: ${route}`);
|
|
347
563
|
}
|
|
348
564
|
}
|
|
565
|
+
/**
|
|
566
|
+
* Re-measure every mounted-visible element's geometry via its stored React
|
|
567
|
+
* ref and write the fresh coordinates into the registry ("measure-on-
|
|
568
|
+
* snapshot").
|
|
569
|
+
*
|
|
570
|
+
* Why: element geometry is otherwise captured ONCE at mount time
|
|
571
|
+
* (`onLayout` + `measureInWindow` in `useUIElement`) and RN never re-fires
|
|
572
|
+
* `onLayout` on pure translation — scrolling a virtualized list
|
|
573
|
+
* (FlashList), recycling a cell, a keyboard shift or an orientation change
|
|
574
|
+
* all move elements WITHOUT updating the stored `state.layout`. Snapshot
|
|
575
|
+
* consumers (vision analyzers hit-testing `bbox`, coord-based tap) then
|
|
576
|
+
* operate on stale positions. Re-measuring at READ time is correct
|
|
577
|
+
* regardless of what moved the element and needs zero per-consumer wiring:
|
|
578
|
+
* every registry entry already stores its ref (see `registerElement`).
|
|
579
|
+
*
|
|
580
|
+
* Per-element outcomes:
|
|
581
|
+
* - non-zero dims → write a fresh full layout (same state shape as the
|
|
582
|
+
* mount-time measure loop in `useUIElement`); counted as `measured`.
|
|
583
|
+
* - zero dims AND the element previously had a non-null `state.layout` →
|
|
584
|
+
* the view collapsed / left the screen; clear to
|
|
585
|
+
* `{ visible: false, layout: null }` (same shape `markRouteOffscreen`
|
|
586
|
+
* writes); counted as `cleared`.
|
|
587
|
+
* - zero dims and it never had a layout → leave state untouched (element
|
|
588
|
+
* in the mount→first-onLayout gap; don't demote `likely-visible`);
|
|
589
|
+
* counted as `skipped`.
|
|
590
|
+
* - no ref / no callable `measureInWindow` (test fixtures, web) → leave
|
|
591
|
+
* untouched; counted as `skipped`.
|
|
592
|
+
*
|
|
593
|
+
* The whole sweep races an overall timeout (default 250 ms) so a dead ref
|
|
594
|
+
* whose `measureInWindow` never calls back can never hang a snapshot: the
|
|
595
|
+
* returned promise resolves at the deadline with whatever counts have
|
|
596
|
+
* accumulated. Late callbacks may still write state afterwards — harmless,
|
|
597
|
+
* freshest data wins. Never throws.
|
|
598
|
+
*
|
|
599
|
+
* Non-React core module on purpose — `measureInWindow` is duck-typed off
|
|
600
|
+
* the stored ref rather than imported from `react-native` (see the
|
|
601
|
+
* `projectBbox` doc comment for why this file must not import RN).
|
|
602
|
+
*/
|
|
603
|
+
async refreshMeasurements(options) {
|
|
604
|
+
const timeoutMs = typeof options?.timeoutMs === "number" && Number.isFinite(options.timeoutMs) && options.timeoutMs > 0 ? options.timeoutMs : 250;
|
|
605
|
+
const counts = { measured: 0, cleared: 0, skipped: 0 };
|
|
606
|
+
const pending = [];
|
|
607
|
+
for (const element of this.getMountedVisibleElements()) {
|
|
608
|
+
const node = element.ref?.current;
|
|
609
|
+
if (!node || typeof node.measureInWindow !== "function") {
|
|
610
|
+
counts.skipped++;
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
613
|
+
const id = element.id;
|
|
614
|
+
pending.push(
|
|
615
|
+
new Promise((resolve) => {
|
|
616
|
+
let settled = false;
|
|
617
|
+
try {
|
|
618
|
+
node.measureInWindow((pageX, pageY, w, h) => {
|
|
619
|
+
if (settled) return;
|
|
620
|
+
settled = true;
|
|
621
|
+
try {
|
|
622
|
+
if (w > 0 && h > 0) {
|
|
623
|
+
this.updateElementState(id, {
|
|
624
|
+
mounted: true,
|
|
625
|
+
visible: true,
|
|
626
|
+
enabled: true,
|
|
627
|
+
focused: false,
|
|
628
|
+
layout: { x: pageX, y: pageY, width: w, height: h, pageX, pageY }
|
|
629
|
+
});
|
|
630
|
+
counts.measured++;
|
|
631
|
+
} else if (this.elements.get(id)?.getState().layout != null) {
|
|
632
|
+
this.updateElementState(id, { visible: false, layout: null });
|
|
633
|
+
counts.cleared++;
|
|
634
|
+
} else {
|
|
635
|
+
counts.skipped++;
|
|
636
|
+
}
|
|
637
|
+
} finally {
|
|
638
|
+
resolve();
|
|
639
|
+
}
|
|
640
|
+
});
|
|
641
|
+
} catch {
|
|
642
|
+
if (!settled) {
|
|
643
|
+
settled = true;
|
|
644
|
+
counts.skipped++;
|
|
645
|
+
resolve();
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
})
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
if (pending.length > 0) {
|
|
652
|
+
await new Promise((resolve) => {
|
|
653
|
+
const timer = setTimeout(resolve, timeoutMs);
|
|
654
|
+
void Promise.all(pending).then(() => {
|
|
655
|
+
clearTimeout(timer);
|
|
656
|
+
resolve();
|
|
657
|
+
});
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
return counts;
|
|
661
|
+
}
|
|
349
662
|
/**
|
|
350
663
|
* Update element state
|
|
351
664
|
*/
|
|
@@ -660,6 +973,18 @@ var NativeUIBridgeRegistry = class {
|
|
|
660
973
|
const handlers = extractHandlerNames(e.props);
|
|
661
974
|
const state = e.getState();
|
|
662
975
|
const visibility = !state.visible ? "hidden" : state.layout !== null ? "visible" : "likely-visible";
|
|
976
|
+
const bbox = projectBbox(state, visibility, this.pixelRatio);
|
|
977
|
+
const vision = projectVisionFields({
|
|
978
|
+
type: e.type,
|
|
979
|
+
label: e.label,
|
|
980
|
+
// Real interactivity signal: the names of props that are actually
|
|
981
|
+
// functions (onPress/onChangeText/...). NOT `e.actions`, which
|
|
982
|
+
// `inferActions` synthesizes press/click onto for every element —
|
|
983
|
+
// using it would mark plain text/view nodes interactable.
|
|
984
|
+
handlerNames: handlers,
|
|
985
|
+
state,
|
|
986
|
+
flatStyle: e.flatStyle
|
|
987
|
+
});
|
|
663
988
|
return {
|
|
664
989
|
id: e.id,
|
|
665
990
|
type: e.type,
|
|
@@ -670,7 +995,9 @@ var NativeUIBridgeRegistry = class {
|
|
|
670
995
|
customActions: e.customActions ? Object.keys(e.customActions) : void 0,
|
|
671
996
|
registeredHandlers: handlers.length > 0 ? handlers : void 0,
|
|
672
997
|
registrationRoute: e.registrationRoute,
|
|
673
|
-
visibility
|
|
998
|
+
visibility,
|
|
999
|
+
...bbox ? { bbox } : {},
|
|
1000
|
+
...vision
|
|
674
1001
|
};
|
|
675
1002
|
}),
|
|
676
1003
|
components: this.getAllComponents().map((c) => ({
|
|
@@ -1844,7 +2171,7 @@ function createDesignHandlers(registry, viewportProvider) {
|
|
|
1844
2171
|
var GRID_SIZE = 20;
|
|
1845
2172
|
var NAV_TYPES = /* @__PURE__ */ new Set(["button", "heading", "badge", "status-message"]);
|
|
1846
2173
|
var SKIP_TEXT_TYPES = /* @__PURE__ */ new Set(["button", "link", "tab", "menuitem"]);
|
|
1847
|
-
var
|
|
2174
|
+
var INTERACTIVE_TYPES2 = /* @__PURE__ */ new Set([
|
|
1848
2175
|
"button",
|
|
1849
2176
|
"input",
|
|
1850
2177
|
"switch",
|
|
@@ -2041,7 +2368,7 @@ function diagnosePageHealth(elements, viewport) {
|
|
|
2041
2368
|
let interactiveTotal = 0;
|
|
2042
2369
|
let interactiveDisabled = 0;
|
|
2043
2370
|
for (const el of elements) {
|
|
2044
|
-
if (!
|
|
2371
|
+
if (!INTERACTIVE_TYPES2.has(el.type)) continue;
|
|
2045
2372
|
interactiveTotal++;
|
|
2046
2373
|
if (el.state.enabled === false) interactiveDisabled++;
|
|
2047
2374
|
}
|
|
@@ -2314,6 +2641,7 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2314
2641
|
return {
|
|
2315
2642
|
// Elements
|
|
2316
2643
|
getElements: async (ctx) => {
|
|
2644
|
+
await registry.refreshMeasurements();
|
|
2317
2645
|
const visibleOnly = ctx.query?.visibleOnly === "true" || ctx.body?.visibleOnly === true;
|
|
2318
2646
|
const forRoute = ctx.query?.route || ctx.body?.route;
|
|
2319
2647
|
let allElements = visibleOnly ? registry.getMountedVisibleElements() : registry.getAllElements();
|
|
@@ -2324,6 +2652,16 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2324
2652
|
const handlers = extractHandlerNames(e.props);
|
|
2325
2653
|
const state = e.getState();
|
|
2326
2654
|
const visibility = !state.visible ? "hidden" : state.layout !== null ? "visible" : "likely-visible";
|
|
2655
|
+
const bbox = projectBbox(state, visibility, registry.getPixelRatio());
|
|
2656
|
+
const vision = projectVisionFields({
|
|
2657
|
+
type: e.type,
|
|
2658
|
+
label: e.label,
|
|
2659
|
+
// Real handler names (onPress/...), NOT inferred actions which
|
|
2660
|
+
// synthesize press/click onto every element. See projectVisionFields.
|
|
2661
|
+
handlerNames: handlers,
|
|
2662
|
+
state,
|
|
2663
|
+
flatStyle: e.flatStyle
|
|
2664
|
+
});
|
|
2327
2665
|
return {
|
|
2328
2666
|
id: e.id,
|
|
2329
2667
|
type: e.type,
|
|
@@ -2334,7 +2672,9 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2334
2672
|
customActions: e.customActions ? Object.keys(e.customActions) : void 0,
|
|
2335
2673
|
registeredHandlers: handlers.length > 0 ? handlers : void 0,
|
|
2336
2674
|
registrationRoute: e.registrationRoute,
|
|
2337
|
-
visibility
|
|
2675
|
+
visibility,
|
|
2676
|
+
...bbox ? { bbox } : {},
|
|
2677
|
+
...vision
|
|
2338
2678
|
};
|
|
2339
2679
|
});
|
|
2340
2680
|
return success2({ elements });
|
|
@@ -2495,6 +2835,7 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2495
2835
|
});
|
|
2496
2836
|
},
|
|
2497
2837
|
getSnapshot: async (ctx) => {
|
|
2838
|
+
await registry.refreshMeasurements();
|
|
2498
2839
|
const visibleOnly = ctx.query?.visibleOnly === "true" || ctx.body?.visibleOnly === true;
|
|
2499
2840
|
const currentRouteOnly = ctx.query?.currentRouteOnly === "true" || ctx.body?.currentRouteOnly === true;
|
|
2500
2841
|
const snapshot = registry.createSnapshot(void 0, { visibleOnly, currentRouteOnly });
|
|
@@ -2810,6 +3151,7 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2810
3151
|
// that don't measure (the fallback only matches single-rooted screens but
|
|
2811
3152
|
// is good enough for the unit suite).
|
|
2812
3153
|
tapAt: async (ctx) => {
|
|
3154
|
+
await registry.refreshMeasurements();
|
|
2813
3155
|
const body = ctx.body;
|
|
2814
3156
|
const x = body?.x;
|
|
2815
3157
|
const y = body?.y;
|
|
@@ -3017,7 +3359,7 @@ function createServerHandlers(registry, executor, config) {
|
|
|
3017
3359
|
};
|
|
3018
3360
|
if (config?.appInfo) {
|
|
3019
3361
|
response.uiBridge = {
|
|
3020
|
-
version: "0.6.
|
|
3362
|
+
version: "0.6.12",
|
|
3021
3363
|
...config.appInfo,
|
|
3022
3364
|
capabilities: ["elements", "components", "actions", "design"],
|
|
3023
3365
|
elementCount: stats.elements,
|
|
@@ -3609,6 +3951,14 @@ var NativeUIBridgeServer = class {
|
|
|
3609
3951
|
};
|
|
3610
3952
|
};
|
|
3611
3953
|
}
|
|
3954
|
+
/**
|
|
3955
|
+
* Whether the console/network capture should be installed. The dedicated
|
|
3956
|
+
* `observability` flag wins when set; otherwise falls back to `testHooks`
|
|
3957
|
+
* so consumers predating the flag keep their exact behavior.
|
|
3958
|
+
*/
|
|
3959
|
+
observabilityEnabled() {
|
|
3960
|
+
return this.config.observability ?? this.config.testHooks === true;
|
|
3961
|
+
}
|
|
3612
3962
|
/**
|
|
3613
3963
|
* Set the server adapter
|
|
3614
3964
|
*/
|
|
@@ -3822,7 +4172,7 @@ var NativeUIBridgeServer = class {
|
|
|
3822
4172
|
console.warn("[ui-bridge-native] See documentation for supported adapters.");
|
|
3823
4173
|
return;
|
|
3824
4174
|
}
|
|
3825
|
-
if (this.
|
|
4175
|
+
if (this.observabilityEnabled()) {
|
|
3826
4176
|
this.consoleErrorBuffer.install();
|
|
3827
4177
|
this.networkRequestBuffer.install();
|
|
3828
4178
|
}
|
|
@@ -5324,6 +5674,7 @@ function UIBridgeNativeProvider({
|
|
|
5324
5674
|
verbose: config.verbose,
|
|
5325
5675
|
onEvent
|
|
5326
5676
|
});
|
|
5677
|
+
registryRef.current.setPixelRatio(reactNative.PixelRatio.get());
|
|
5327
5678
|
setGlobalRegistry(registryRef.current);
|
|
5328
5679
|
}
|
|
5329
5680
|
const registry = registryRef.current;
|
|
@@ -5354,6 +5705,10 @@ function UIBridgeNativeProvider({
|
|
|
5354
5705
|
cors: true,
|
|
5355
5706
|
appInfo: config.appInfo,
|
|
5356
5707
|
testHooks: features.testHooks === true,
|
|
5708
|
+
// Dedicated console/network-capture flag; the server defaults it to
|
|
5709
|
+
// the `testHooks` value when undefined, so passing it through verbatim
|
|
5710
|
+
// keeps existing consumers unchanged.
|
|
5711
|
+
observability: features.observability,
|
|
5357
5712
|
// Injected device-viewport getter for POST /control/page-health. The
|
|
5358
5713
|
// server doesn't import `react-native` itself — the require/import
|
|
5359
5714
|
// pattern there crashed the host RN app in 0.6.3/0.6.4 (Metro/Hermes
|
|
@@ -5421,6 +5776,7 @@ function UIBridgeNativeProvider({
|
|
|
5421
5776
|
}, [
|
|
5422
5777
|
features.server,
|
|
5423
5778
|
features.testHooks,
|
|
5779
|
+
features.observability,
|
|
5424
5780
|
config.serverPort,
|
|
5425
5781
|
config.appInfo,
|
|
5426
5782
|
registry,
|
|
@@ -5459,6 +5815,7 @@ function UIBridgeNativeProvider({
|
|
|
5459
5815
|
cors: true,
|
|
5460
5816
|
appInfo: config.appInfo,
|
|
5461
5817
|
testHooks: features.testHooks === true,
|
|
5818
|
+
observability: features.observability,
|
|
5462
5819
|
viewportProvider: () => {
|
|
5463
5820
|
const win = reactNative.Dimensions.get("window");
|
|
5464
5821
|
return { width: win.width, height: win.height };
|
|
@@ -5662,12 +6019,41 @@ function scheduleDeadButtonWarning(bridge, id, type) {
|
|
|
5662
6019
|
}
|
|
5663
6020
|
function useUIElement(options) {
|
|
5664
6021
|
const bridge = useUIBridgeNativeOptional();
|
|
5665
|
-
const ref = react.useRef(null);
|
|
5666
6022
|
const [registered, setRegistered] = react.useState(false);
|
|
5667
6023
|
const [_layout, setLayout] = react.useState(null);
|
|
5668
6024
|
const propsRef = react.useRef({});
|
|
5669
6025
|
const registeredRef = react.useRef(false);
|
|
5670
6026
|
const registeredIdRef = react.useRef(null);
|
|
6027
|
+
const bridgeRef = react.useRef(bridge);
|
|
6028
|
+
bridgeRef.current = bridge;
|
|
6029
|
+
const nodeRef = react.useRef(null);
|
|
6030
|
+
const refInterceptorRef = react.useRef(null);
|
|
6031
|
+
if (refInterceptorRef.current === null) {
|
|
6032
|
+
refInterceptorRef.current = {
|
|
6033
|
+
get current() {
|
|
6034
|
+
return nodeRef.current;
|
|
6035
|
+
},
|
|
6036
|
+
set current(node) {
|
|
6037
|
+
const prev = nodeRef.current;
|
|
6038
|
+
nodeRef.current = node;
|
|
6039
|
+
const liveBridge = bridgeRef.current;
|
|
6040
|
+
const registeredId = registeredIdRef.current;
|
|
6041
|
+
if (!liveBridge || !registeredRef.current || registeredId === null) return;
|
|
6042
|
+
if (node == null && prev != null) {
|
|
6043
|
+
const state = liveBridge.registry.getElement(registeredId)?.getState();
|
|
6044
|
+
if (state && state.visible !== false) {
|
|
6045
|
+
liveBridge.registry.updateElementState(registeredId, { visible: false });
|
|
6046
|
+
}
|
|
6047
|
+
} else if (node != null && prev == null) {
|
|
6048
|
+
const state = liveBridge.registry.getElement(registeredId)?.getState();
|
|
6049
|
+
if (state && state.visible !== true) {
|
|
6050
|
+
liveBridge.registry.updateElementState(registeredId, { visible: true });
|
|
6051
|
+
}
|
|
6052
|
+
}
|
|
6053
|
+
}
|
|
6054
|
+
};
|
|
6055
|
+
}
|
|
6056
|
+
const ref = refInterceptorRef.current;
|
|
5671
6057
|
const {
|
|
5672
6058
|
id,
|
|
5673
6059
|
type = "custom",
|
|
@@ -5711,7 +6097,7 @@ function useUIElement(options) {
|
|
|
5711
6097
|
}
|
|
5712
6098
|
setRegistered(true);
|
|
5713
6099
|
scheduleDeadButtonWarning(bridge, id, type);
|
|
5714
|
-
}, [bridge, id, type, label, actions, customActions, treePath, style, stateStylesProp, valueProp]);
|
|
6100
|
+
}, [bridge, id, type, label, actions, customActions, treePath, style, stateStylesProp, valueProp, ref]);
|
|
5715
6101
|
const unregister = react.useCallback(() => {
|
|
5716
6102
|
if (!bridge || !registeredRef.current) return;
|
|
5717
6103
|
bridge.registry.unregisterElement(registeredIdRef.current ?? id);
|
|
@@ -5747,7 +6133,8 @@ function useUIElement(options) {
|
|
|
5747
6133
|
writeLayout({ x, y, width, height, pageX: x, pageY: y });
|
|
5748
6134
|
}
|
|
5749
6135
|
},
|
|
5750
|
-
|
|
6136
|
+
// `ref` is the once-per-hook interceptor object — identity-stable.
|
|
6137
|
+
[bridge, id, ref]
|
|
5751
6138
|
);
|
|
5752
6139
|
const registerRef = react.useRef(register);
|
|
5753
6140
|
const unregisterRef = react.useRef(unregister);
|
|
@@ -5764,11 +6151,18 @@ function useUIElement(options) {
|
|
|
5764
6151
|
unregisterRef.current();
|
|
5765
6152
|
}
|
|
5766
6153
|
};
|
|
5767
|
-
}, [autoRegister, bridge]);
|
|
6154
|
+
}, [autoRegister, bridge, id]);
|
|
5768
6155
|
react.useEffect(() => {
|
|
5769
6156
|
if (!bridge || !registered) return;
|
|
5770
6157
|
const node = ref.current;
|
|
5771
|
-
if (!node
|
|
6158
|
+
if (!node) {
|
|
6159
|
+
const seeded = bridge.registry.getElement(id)?.getState();
|
|
6160
|
+
if (seeded && seeded.visible !== false) {
|
|
6161
|
+
bridge.registry.updateElementState(id, { visible: false });
|
|
6162
|
+
}
|
|
6163
|
+
return;
|
|
6164
|
+
}
|
|
6165
|
+
if (typeof node.measureInWindow !== "function") return;
|
|
5772
6166
|
let cancelled = false;
|
|
5773
6167
|
let pendingTimer = null;
|
|
5774
6168
|
const backoffMs = [50, 200, 500, 1e3, 2500];
|
|
@@ -5807,7 +6201,7 @@ function useUIElement(options) {
|
|
|
5807
6201
|
cancelled = true;
|
|
5808
6202
|
if (pendingTimer != null) clearTimeout(pendingTimer);
|
|
5809
6203
|
};
|
|
5810
|
-
}, [bridge, registered, id]);
|
|
6204
|
+
}, [bridge, registered, id, ref]);
|
|
5811
6205
|
const registeredHandlerKeysRef = react.useRef([]);
|
|
5812
6206
|
react.useEffect(() => {
|
|
5813
6207
|
if (!bridge || !registered || !handlersProp) return;
|