@qontinui/ui-bridge-native 0.6.9 → 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/control/action-executor.d.ts.map +1 -1
- package/dist/control/index.js +2 -1
- package/dist/control/index.js.map +1 -1
- package/dist/control/index.mjs +2 -1
- package/dist/control/index.mjs.map +1 -1
- 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 +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +371 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +365 -22
- package/dist/index.mjs.map +1 -1
- package/dist/react/UIBridgeNativeProvider.d.ts.map +1 -1
- package/dist/react/index.js +323 -20
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +324 -21
- package/dist/react/index.mjs.map +1 -1
- package/dist/react/useUIElement.d.ts.map +1 -1
- package/dist/server/bind-retry.d.ts +64 -0
- package/dist/server/bind-retry.d.ts.map +1 -0
- 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.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +275 -13
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +274 -14
- 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) => ({
|
|
@@ -935,9 +1165,10 @@ var DefaultNativeActionExecutor = class {
|
|
|
935
1165
|
requestId: request.requestId,
|
|
936
1166
|
durationMs: successTime - startTime
|
|
937
1167
|
});
|
|
1168
|
+
const fresh = this.registry.getElement(registered.id) ?? registered;
|
|
938
1169
|
return {
|
|
939
1170
|
success: true,
|
|
940
|
-
elementState:
|
|
1171
|
+
elementState: fresh.getState(),
|
|
941
1172
|
result,
|
|
942
1173
|
durationMs: successTime - startTime,
|
|
943
1174
|
timestamp: successTime,
|
|
@@ -1843,7 +2074,7 @@ function createDesignHandlers(registry, viewportProvider) {
|
|
|
1843
2074
|
var GRID_SIZE = 20;
|
|
1844
2075
|
var NAV_TYPES = /* @__PURE__ */ new Set(["button", "heading", "badge", "status-message"]);
|
|
1845
2076
|
var SKIP_TEXT_TYPES = /* @__PURE__ */ new Set(["button", "link", "tab", "menuitem"]);
|
|
1846
|
-
var
|
|
2077
|
+
var INTERACTIVE_TYPES2 = /* @__PURE__ */ new Set([
|
|
1847
2078
|
"button",
|
|
1848
2079
|
"input",
|
|
1849
2080
|
"switch",
|
|
@@ -2040,7 +2271,7 @@ function diagnosePageHealth(elements, viewport) {
|
|
|
2040
2271
|
let interactiveTotal = 0;
|
|
2041
2272
|
let interactiveDisabled = 0;
|
|
2042
2273
|
for (const el of elements) {
|
|
2043
|
-
if (!
|
|
2274
|
+
if (!INTERACTIVE_TYPES2.has(el.type)) continue;
|
|
2044
2275
|
interactiveTotal++;
|
|
2045
2276
|
if (el.state.enabled === false) interactiveDisabled++;
|
|
2046
2277
|
}
|
|
@@ -2108,6 +2339,13 @@ function matchElementsByText(registry, text, opts) {
|
|
|
2108
2339
|
scored.sort((a, b) => a.rank - b.rank);
|
|
2109
2340
|
return scored.map((s) => s.element);
|
|
2110
2341
|
}
|
|
2342
|
+
function resolveElementState(element) {
|
|
2343
|
+
const state = element.getState();
|
|
2344
|
+
if (element.type === "input" && state.value === void 0 && typeof element.props?.value === "string") {
|
|
2345
|
+
return { ...state, value: element.props.value };
|
|
2346
|
+
}
|
|
2347
|
+
return state;
|
|
2348
|
+
}
|
|
2111
2349
|
async function executeWorkflowStep(step, registry, executor) {
|
|
2112
2350
|
const startTime = Date.now();
|
|
2113
2351
|
try {
|
|
@@ -2316,6 +2554,16 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2316
2554
|
const handlers = extractHandlerNames(e.props);
|
|
2317
2555
|
const state = e.getState();
|
|
2318
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
|
+
});
|
|
2319
2567
|
return {
|
|
2320
2568
|
id: e.id,
|
|
2321
2569
|
type: e.type,
|
|
@@ -2326,7 +2574,9 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2326
2574
|
customActions: e.customActions ? Object.keys(e.customActions) : void 0,
|
|
2327
2575
|
registeredHandlers: handlers.length > 0 ? handlers : void 0,
|
|
2328
2576
|
registrationRoute: e.registrationRoute,
|
|
2329
|
-
visibility
|
|
2577
|
+
visibility,
|
|
2578
|
+
...bbox ? { bbox } : {},
|
|
2579
|
+
...vision
|
|
2330
2580
|
};
|
|
2331
2581
|
});
|
|
2332
2582
|
return success2({ elements });
|
|
@@ -2344,7 +2594,7 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2344
2594
|
type: element.type,
|
|
2345
2595
|
label: element.label,
|
|
2346
2596
|
identifier: element.getIdentifier(),
|
|
2347
|
-
state: element
|
|
2597
|
+
state: resolveElementState(element),
|
|
2348
2598
|
actions: element.actions,
|
|
2349
2599
|
customActions: element.customActions ? Object.keys(element.customActions) : void 0,
|
|
2350
2600
|
registeredHandlers: handlers.length > 0 ? handlers : void 0,
|
|
@@ -2358,18 +2608,19 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2358
2608
|
if (!element) {
|
|
2359
2609
|
return error2(`Element not found: ${id}`, "ELEMENT_NOT_FOUND");
|
|
2360
2610
|
}
|
|
2361
|
-
return success2({ state: element
|
|
2611
|
+
return success2({ state: resolveElementState(element) });
|
|
2362
2612
|
},
|
|
2363
2613
|
executeAction: async (ctx) => {
|
|
2364
|
-
const
|
|
2365
|
-
const
|
|
2366
|
-
|
|
2614
|
+
const rawBody = ctx.body ?? {};
|
|
2615
|
+
const envelope = rawBody.request && typeof rawBody.request === "object" ? rawBody.request : rawBody;
|
|
2616
|
+
const id = ctx.params.id ?? rawBody.id ?? "";
|
|
2617
|
+
if (!envelope?.action) {
|
|
2367
2618
|
return error2("Action is required", "INVALID_REQUEST");
|
|
2368
2619
|
}
|
|
2369
2620
|
const response = await executor.executeAction(id, {
|
|
2370
|
-
action:
|
|
2371
|
-
params:
|
|
2372
|
-
waitOptions:
|
|
2621
|
+
action: envelope.action,
|
|
2622
|
+
params: envelope.params,
|
|
2623
|
+
waitOptions: envelope.waitOptions
|
|
2373
2624
|
});
|
|
2374
2625
|
if (!response.success) {
|
|
2375
2626
|
return error2(response.error || "Action failed", "ACTION_FAILED");
|
|
@@ -3008,7 +3259,7 @@ function createServerHandlers(registry, executor, config) {
|
|
|
3008
3259
|
};
|
|
3009
3260
|
if (config?.appInfo) {
|
|
3010
3261
|
response.uiBridge = {
|
|
3011
|
-
version: "0.
|
|
3262
|
+
version: "0.6.11",
|
|
3012
3263
|
...config.appInfo,
|
|
3013
3264
|
capabilities: ["elements", "components", "actions", "design"],
|
|
3014
3265
|
elementCount: stats.elements,
|
|
@@ -3600,6 +3851,14 @@ var NativeUIBridgeServer = class {
|
|
|
3600
3851
|
};
|
|
3601
3852
|
};
|
|
3602
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
|
+
}
|
|
3603
3862
|
/**
|
|
3604
3863
|
* Set the server adapter
|
|
3605
3864
|
*/
|
|
@@ -3813,7 +4072,7 @@ var NativeUIBridgeServer = class {
|
|
|
3813
4072
|
console.warn("[ui-bridge-native] See documentation for supported adapters.");
|
|
3814
4073
|
return;
|
|
3815
4074
|
}
|
|
3816
|
-
if (this.
|
|
4075
|
+
if (this.observabilityEnabled()) {
|
|
3817
4076
|
this.consoleErrorBuffer.install();
|
|
3818
4077
|
this.networkRequestBuffer.install();
|
|
3819
4078
|
}
|
|
@@ -5315,6 +5574,7 @@ function UIBridgeNativeProvider({
|
|
|
5315
5574
|
verbose: config.verbose,
|
|
5316
5575
|
onEvent
|
|
5317
5576
|
});
|
|
5577
|
+
registryRef.current.setPixelRatio(reactNative.PixelRatio.get());
|
|
5318
5578
|
setGlobalRegistry(registryRef.current);
|
|
5319
5579
|
}
|
|
5320
5580
|
const registry = registryRef.current;
|
|
@@ -5345,6 +5605,10 @@ function UIBridgeNativeProvider({
|
|
|
5345
5605
|
cors: true,
|
|
5346
5606
|
appInfo: config.appInfo,
|
|
5347
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,
|
|
5348
5612
|
// Injected device-viewport getter for POST /control/page-health. The
|
|
5349
5613
|
// server doesn't import `react-native` itself — the require/import
|
|
5350
5614
|
// pattern there crashed the host RN app in 0.6.3/0.6.4 (Metro/Hermes
|
|
@@ -5412,6 +5676,7 @@ function UIBridgeNativeProvider({
|
|
|
5412
5676
|
}, [
|
|
5413
5677
|
features.server,
|
|
5414
5678
|
features.testHooks,
|
|
5679
|
+
features.observability,
|
|
5415
5680
|
config.serverPort,
|
|
5416
5681
|
config.appInfo,
|
|
5417
5682
|
registry,
|
|
@@ -5450,6 +5715,7 @@ function UIBridgeNativeProvider({
|
|
|
5450
5715
|
cors: true,
|
|
5451
5716
|
appInfo: config.appInfo,
|
|
5452
5717
|
testHooks: features.testHooks === true,
|
|
5718
|
+
observability: features.observability,
|
|
5453
5719
|
viewportProvider: () => {
|
|
5454
5720
|
const win = reactNative.Dimensions.get("window");
|
|
5455
5721
|
return { width: win.width, height: win.height };
|
|
@@ -5653,12 +5919,41 @@ function scheduleDeadButtonWarning(bridge, id, type) {
|
|
|
5653
5919
|
}
|
|
5654
5920
|
function useUIElement(options) {
|
|
5655
5921
|
const bridge = useUIBridgeNativeOptional();
|
|
5656
|
-
const ref = react.useRef(null);
|
|
5657
5922
|
const [registered, setRegistered] = react.useState(false);
|
|
5658
5923
|
const [_layout, setLayout] = react.useState(null);
|
|
5659
5924
|
const propsRef = react.useRef({});
|
|
5660
5925
|
const registeredRef = react.useRef(false);
|
|
5661
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;
|
|
5662
5957
|
const {
|
|
5663
5958
|
id,
|
|
5664
5959
|
type = "custom",
|
|
@@ -5702,7 +5997,7 @@ function useUIElement(options) {
|
|
|
5702
5997
|
}
|
|
5703
5998
|
setRegistered(true);
|
|
5704
5999
|
scheduleDeadButtonWarning(bridge, id, type);
|
|
5705
|
-
}, [bridge, id, type, label, actions, customActions, treePath, style, stateStylesProp, valueProp]);
|
|
6000
|
+
}, [bridge, id, type, label, actions, customActions, treePath, style, stateStylesProp, valueProp, ref]);
|
|
5706
6001
|
const unregister = react.useCallback(() => {
|
|
5707
6002
|
if (!bridge || !registeredRef.current) return;
|
|
5708
6003
|
bridge.registry.unregisterElement(registeredIdRef.current ?? id);
|
|
@@ -5738,7 +6033,8 @@ function useUIElement(options) {
|
|
|
5738
6033
|
writeLayout({ x, y, width, height, pageX: x, pageY: y });
|
|
5739
6034
|
}
|
|
5740
6035
|
},
|
|
5741
|
-
|
|
6036
|
+
// `ref` is the once-per-hook interceptor object — identity-stable.
|
|
6037
|
+
[bridge, id, ref]
|
|
5742
6038
|
);
|
|
5743
6039
|
const registerRef = react.useRef(register);
|
|
5744
6040
|
const unregisterRef = react.useRef(unregister);
|
|
@@ -5759,7 +6055,14 @@ function useUIElement(options) {
|
|
|
5759
6055
|
react.useEffect(() => {
|
|
5760
6056
|
if (!bridge || !registered) return;
|
|
5761
6057
|
const node = ref.current;
|
|
5762
|
-
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;
|
|
5763
6066
|
let cancelled = false;
|
|
5764
6067
|
let pendingTimer = null;
|
|
5765
6068
|
const backoffMs = [50, 200, 500, 1e3, 2500];
|
|
@@ -5798,7 +6101,7 @@ function useUIElement(options) {
|
|
|
5798
6101
|
cancelled = true;
|
|
5799
6102
|
if (pendingTimer != null) clearTimeout(pendingTimer);
|
|
5800
6103
|
};
|
|
5801
|
-
}, [bridge, registered, id]);
|
|
6104
|
+
}, [bridge, registered, id, ref]);
|
|
5802
6105
|
const registeredHandlerKeysRef = react.useRef([]);
|
|
5803
6106
|
react.useEffect(() => {
|
|
5804
6107
|
if (!bridge || !registered || !handlersProp) return;
|