@qontinui/ui-bridge-native 0.6.10 → 0.6.11
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 +232 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +232 -2
- package/dist/core/index.mjs.map +1 -1
- package/dist/core/registry.d.ts +46 -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 +311 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +307 -13
- package/dist/index.mjs.map +1 -1
- package/dist/react/UIBridgeNativeProvider.d.ts.map +1 -1
- package/dist/react/index.js +305 -11
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +306 -12
- 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 +217 -5
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +217 -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
|
// ============================================================================
|
|
@@ -660,6 +876,18 @@ var NativeUIBridgeRegistry = class {
|
|
|
660
876
|
const handlers = extractHandlerNames(e.props);
|
|
661
877
|
const state = e.getState();
|
|
662
878
|
const visibility = !state.visible ? "hidden" : state.layout !== null ? "visible" : "likely-visible";
|
|
879
|
+
const bbox = projectBbox(state, visibility, this.pixelRatio);
|
|
880
|
+
const vision = projectVisionFields({
|
|
881
|
+
type: e.type,
|
|
882
|
+
label: e.label,
|
|
883
|
+
// Real interactivity signal: the names of props that are actually
|
|
884
|
+
// functions (onPress/onChangeText/...). NOT `e.actions`, which
|
|
885
|
+
// `inferActions` synthesizes press/click onto for every element —
|
|
886
|
+
// using it would mark plain text/view nodes interactable.
|
|
887
|
+
handlerNames: handlers,
|
|
888
|
+
state,
|
|
889
|
+
flatStyle: e.flatStyle
|
|
890
|
+
});
|
|
663
891
|
return {
|
|
664
892
|
id: e.id,
|
|
665
893
|
type: e.type,
|
|
@@ -670,7 +898,9 @@ var NativeUIBridgeRegistry = class {
|
|
|
670
898
|
customActions: e.customActions ? Object.keys(e.customActions) : void 0,
|
|
671
899
|
registeredHandlers: handlers.length > 0 ? handlers : void 0,
|
|
672
900
|
registrationRoute: e.registrationRoute,
|
|
673
|
-
visibility
|
|
901
|
+
visibility,
|
|
902
|
+
...bbox ? { bbox } : {},
|
|
903
|
+
...vision
|
|
674
904
|
};
|
|
675
905
|
}),
|
|
676
906
|
components: this.getAllComponents().map((c) => ({
|
|
@@ -1844,7 +2074,7 @@ function createDesignHandlers(registry, viewportProvider) {
|
|
|
1844
2074
|
var GRID_SIZE = 20;
|
|
1845
2075
|
var NAV_TYPES = /* @__PURE__ */ new Set(["button", "heading", "badge", "status-message"]);
|
|
1846
2076
|
var SKIP_TEXT_TYPES = /* @__PURE__ */ new Set(["button", "link", "tab", "menuitem"]);
|
|
1847
|
-
var
|
|
2077
|
+
var INTERACTIVE_TYPES2 = /* @__PURE__ */ new Set([
|
|
1848
2078
|
"button",
|
|
1849
2079
|
"input",
|
|
1850
2080
|
"switch",
|
|
@@ -2041,7 +2271,7 @@ function diagnosePageHealth(elements, viewport) {
|
|
|
2041
2271
|
let interactiveTotal = 0;
|
|
2042
2272
|
let interactiveDisabled = 0;
|
|
2043
2273
|
for (const el of elements) {
|
|
2044
|
-
if (!
|
|
2274
|
+
if (!INTERACTIVE_TYPES2.has(el.type)) continue;
|
|
2045
2275
|
interactiveTotal++;
|
|
2046
2276
|
if (el.state.enabled === false) interactiveDisabled++;
|
|
2047
2277
|
}
|
|
@@ -2324,6 +2554,16 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2324
2554
|
const handlers = extractHandlerNames(e.props);
|
|
2325
2555
|
const state = e.getState();
|
|
2326
2556
|
const visibility = !state.visible ? "hidden" : state.layout !== null ? "visible" : "likely-visible";
|
|
2557
|
+
const bbox = projectBbox(state, visibility, registry.getPixelRatio());
|
|
2558
|
+
const vision = projectVisionFields({
|
|
2559
|
+
type: e.type,
|
|
2560
|
+
label: e.label,
|
|
2561
|
+
// Real handler names (onPress/...), NOT inferred actions which
|
|
2562
|
+
// synthesize press/click onto every element. See projectVisionFields.
|
|
2563
|
+
handlerNames: handlers,
|
|
2564
|
+
state,
|
|
2565
|
+
flatStyle: e.flatStyle
|
|
2566
|
+
});
|
|
2327
2567
|
return {
|
|
2328
2568
|
id: e.id,
|
|
2329
2569
|
type: e.type,
|
|
@@ -2334,7 +2574,9 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2334
2574
|
customActions: e.customActions ? Object.keys(e.customActions) : void 0,
|
|
2335
2575
|
registeredHandlers: handlers.length > 0 ? handlers : void 0,
|
|
2336
2576
|
registrationRoute: e.registrationRoute,
|
|
2337
|
-
visibility
|
|
2577
|
+
visibility,
|
|
2578
|
+
...bbox ? { bbox } : {},
|
|
2579
|
+
...vision
|
|
2338
2580
|
};
|
|
2339
2581
|
});
|
|
2340
2582
|
return success2({ elements });
|
|
@@ -3017,7 +3259,7 @@ function createServerHandlers(registry, executor, config) {
|
|
|
3017
3259
|
};
|
|
3018
3260
|
if (config?.appInfo) {
|
|
3019
3261
|
response.uiBridge = {
|
|
3020
|
-
version: "0.6.
|
|
3262
|
+
version: "0.6.11",
|
|
3021
3263
|
...config.appInfo,
|
|
3022
3264
|
capabilities: ["elements", "components", "actions", "design"],
|
|
3023
3265
|
elementCount: stats.elements,
|
|
@@ -3609,6 +3851,14 @@ var NativeUIBridgeServer = class {
|
|
|
3609
3851
|
};
|
|
3610
3852
|
};
|
|
3611
3853
|
}
|
|
3854
|
+
/**
|
|
3855
|
+
* Whether the console/network capture should be installed. The dedicated
|
|
3856
|
+
* `observability` flag wins when set; otherwise falls back to `testHooks`
|
|
3857
|
+
* so consumers predating the flag keep their exact behavior.
|
|
3858
|
+
*/
|
|
3859
|
+
observabilityEnabled() {
|
|
3860
|
+
return this.config.observability ?? this.config.testHooks === true;
|
|
3861
|
+
}
|
|
3612
3862
|
/**
|
|
3613
3863
|
* Set the server adapter
|
|
3614
3864
|
*/
|
|
@@ -3822,7 +4072,7 @@ var NativeUIBridgeServer = class {
|
|
|
3822
4072
|
console.warn("[ui-bridge-native] See documentation for supported adapters.");
|
|
3823
4073
|
return;
|
|
3824
4074
|
}
|
|
3825
|
-
if (this.
|
|
4075
|
+
if (this.observabilityEnabled()) {
|
|
3826
4076
|
this.consoleErrorBuffer.install();
|
|
3827
4077
|
this.networkRequestBuffer.install();
|
|
3828
4078
|
}
|
|
@@ -5324,6 +5574,7 @@ function UIBridgeNativeProvider({
|
|
|
5324
5574
|
verbose: config.verbose,
|
|
5325
5575
|
onEvent
|
|
5326
5576
|
});
|
|
5577
|
+
registryRef.current.setPixelRatio(reactNative.PixelRatio.get());
|
|
5327
5578
|
setGlobalRegistry(registryRef.current);
|
|
5328
5579
|
}
|
|
5329
5580
|
const registry = registryRef.current;
|
|
@@ -5354,6 +5605,10 @@ function UIBridgeNativeProvider({
|
|
|
5354
5605
|
cors: true,
|
|
5355
5606
|
appInfo: config.appInfo,
|
|
5356
5607
|
testHooks: features.testHooks === true,
|
|
5608
|
+
// Dedicated console/network-capture flag; the server defaults it to
|
|
5609
|
+
// the `testHooks` value when undefined, so passing it through verbatim
|
|
5610
|
+
// keeps existing consumers unchanged.
|
|
5611
|
+
observability: features.observability,
|
|
5357
5612
|
// Injected device-viewport getter for POST /control/page-health. The
|
|
5358
5613
|
// server doesn't import `react-native` itself — the require/import
|
|
5359
5614
|
// pattern there crashed the host RN app in 0.6.3/0.6.4 (Metro/Hermes
|
|
@@ -5421,6 +5676,7 @@ function UIBridgeNativeProvider({
|
|
|
5421
5676
|
}, [
|
|
5422
5677
|
features.server,
|
|
5423
5678
|
features.testHooks,
|
|
5679
|
+
features.observability,
|
|
5424
5680
|
config.serverPort,
|
|
5425
5681
|
config.appInfo,
|
|
5426
5682
|
registry,
|
|
@@ -5459,6 +5715,7 @@ function UIBridgeNativeProvider({
|
|
|
5459
5715
|
cors: true,
|
|
5460
5716
|
appInfo: config.appInfo,
|
|
5461
5717
|
testHooks: features.testHooks === true,
|
|
5718
|
+
observability: features.observability,
|
|
5462
5719
|
viewportProvider: () => {
|
|
5463
5720
|
const win = reactNative.Dimensions.get("window");
|
|
5464
5721
|
return { width: win.width, height: win.height };
|
|
@@ -5662,12 +5919,41 @@ function scheduleDeadButtonWarning(bridge, id, type) {
|
|
|
5662
5919
|
}
|
|
5663
5920
|
function useUIElement(options) {
|
|
5664
5921
|
const bridge = useUIBridgeNativeOptional();
|
|
5665
|
-
const ref = react.useRef(null);
|
|
5666
5922
|
const [registered, setRegistered] = react.useState(false);
|
|
5667
5923
|
const [_layout, setLayout] = react.useState(null);
|
|
5668
5924
|
const propsRef = react.useRef({});
|
|
5669
5925
|
const registeredRef = react.useRef(false);
|
|
5670
5926
|
const registeredIdRef = react.useRef(null);
|
|
5927
|
+
const bridgeRef = react.useRef(bridge);
|
|
5928
|
+
bridgeRef.current = bridge;
|
|
5929
|
+
const nodeRef = react.useRef(null);
|
|
5930
|
+
const refInterceptorRef = react.useRef(null);
|
|
5931
|
+
if (refInterceptorRef.current === null) {
|
|
5932
|
+
refInterceptorRef.current = {
|
|
5933
|
+
get current() {
|
|
5934
|
+
return nodeRef.current;
|
|
5935
|
+
},
|
|
5936
|
+
set current(node) {
|
|
5937
|
+
const prev = nodeRef.current;
|
|
5938
|
+
nodeRef.current = node;
|
|
5939
|
+
const liveBridge = bridgeRef.current;
|
|
5940
|
+
const registeredId = registeredIdRef.current;
|
|
5941
|
+
if (!liveBridge || !registeredRef.current || registeredId === null) return;
|
|
5942
|
+
if (node == null && prev != null) {
|
|
5943
|
+
const state = liveBridge.registry.getElement(registeredId)?.getState();
|
|
5944
|
+
if (state && state.visible !== false) {
|
|
5945
|
+
liveBridge.registry.updateElementState(registeredId, { visible: false });
|
|
5946
|
+
}
|
|
5947
|
+
} else if (node != null && prev == null) {
|
|
5948
|
+
const state = liveBridge.registry.getElement(registeredId)?.getState();
|
|
5949
|
+
if (state && state.visible !== true) {
|
|
5950
|
+
liveBridge.registry.updateElementState(registeredId, { visible: true });
|
|
5951
|
+
}
|
|
5952
|
+
}
|
|
5953
|
+
}
|
|
5954
|
+
};
|
|
5955
|
+
}
|
|
5956
|
+
const ref = refInterceptorRef.current;
|
|
5671
5957
|
const {
|
|
5672
5958
|
id,
|
|
5673
5959
|
type = "custom",
|
|
@@ -5711,7 +5997,7 @@ function useUIElement(options) {
|
|
|
5711
5997
|
}
|
|
5712
5998
|
setRegistered(true);
|
|
5713
5999
|
scheduleDeadButtonWarning(bridge, id, type);
|
|
5714
|
-
}, [bridge, id, type, label, actions, customActions, treePath, style, stateStylesProp, valueProp]);
|
|
6000
|
+
}, [bridge, id, type, label, actions, customActions, treePath, style, stateStylesProp, valueProp, ref]);
|
|
5715
6001
|
const unregister = react.useCallback(() => {
|
|
5716
6002
|
if (!bridge || !registeredRef.current) return;
|
|
5717
6003
|
bridge.registry.unregisterElement(registeredIdRef.current ?? id);
|
|
@@ -5747,7 +6033,8 @@ function useUIElement(options) {
|
|
|
5747
6033
|
writeLayout({ x, y, width, height, pageX: x, pageY: y });
|
|
5748
6034
|
}
|
|
5749
6035
|
},
|
|
5750
|
-
|
|
6036
|
+
// `ref` is the once-per-hook interceptor object — identity-stable.
|
|
6037
|
+
[bridge, id, ref]
|
|
5751
6038
|
);
|
|
5752
6039
|
const registerRef = react.useRef(register);
|
|
5753
6040
|
const unregisterRef = react.useRef(unregister);
|
|
@@ -5768,7 +6055,14 @@ function useUIElement(options) {
|
|
|
5768
6055
|
react.useEffect(() => {
|
|
5769
6056
|
if (!bridge || !registered) return;
|
|
5770
6057
|
const node = ref.current;
|
|
5771
|
-
if (!node
|
|
6058
|
+
if (!node) {
|
|
6059
|
+
const seeded = bridge.registry.getElement(id)?.getState();
|
|
6060
|
+
if (seeded && seeded.visible !== false) {
|
|
6061
|
+
bridge.registry.updateElementState(id, { visible: false });
|
|
6062
|
+
}
|
|
6063
|
+
return;
|
|
6064
|
+
}
|
|
6065
|
+
if (typeof node.measureInWindow !== "function") return;
|
|
5772
6066
|
let cancelled = false;
|
|
5773
6067
|
let pendingTimer = null;
|
|
5774
6068
|
const backoffMs = [50, 200, 500, 1e3, 2500];
|
|
@@ -5807,7 +6101,7 @@ function useUIElement(options) {
|
|
|
5807
6101
|
cancelled = true;
|
|
5808
6102
|
if (pendingTimer != null) clearTimeout(pendingTimer);
|
|
5809
6103
|
};
|
|
5810
|
-
}, [bridge, registered, id]);
|
|
6104
|
+
}, [bridge, registered, id, ref]);
|
|
5811
6105
|
const registeredHandlerKeysRef = react.useRef([]);
|
|
5812
6106
|
react.useEffect(() => {
|
|
5813
6107
|
if (!bridge || !registered || !handlersProp) return;
|