@qontinui/ui-bridge-native 0.6.8 → 0.6.9
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 +15 -0
- package/dist/control/action-executor.d.ts.map +1 -1
- package/dist/control/index.js +34 -0
- package/dist/control/index.js.map +1 -1
- package/dist/control/index.mjs +34 -0
- package/dist/control/index.mjs.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +1 -1
- package/dist/core/index.mjs.map +1 -1
- package/dist/core/types.d.ts +1 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.js +92 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +92 -16
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.js +75 -16
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +75 -16
- package/dist/react/index.mjs.map +1 -1
- package/dist/react/useUIElement.d.ts +10 -0
- 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.map +1 -1
- package/dist/server/index.js +44 -13
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +44 -13
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/types.d.ts +14 -0
- package/dist/server/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -26,7 +26,7 @@ function inferActions(type) {
|
|
|
26
26
|
case "pressable":
|
|
27
27
|
return [...baseActions, "click", "press", "longPress", "doubleTap"];
|
|
28
28
|
case "input":
|
|
29
|
-
return [...baseActions, "click", "press", "type", "clear"];
|
|
29
|
+
return [...baseActions, "click", "press", "type", "setValue", "clear"];
|
|
30
30
|
case "text":
|
|
31
31
|
return [...baseActions, "click", "press", "longPress"];
|
|
32
32
|
case "view":
|
|
@@ -1040,6 +1040,8 @@ var DefaultNativeActionExecutor = class {
|
|
|
1040
1040
|
return this.performDoubleTap(props);
|
|
1041
1041
|
case "type":
|
|
1042
1042
|
return this.performType(element, props, params);
|
|
1043
|
+
case "setValue":
|
|
1044
|
+
return this.performSetValue(element, props, params);
|
|
1043
1045
|
case "clear":
|
|
1044
1046
|
return this.performClear(element, props);
|
|
1045
1047
|
case "focus":
|
|
@@ -1132,6 +1134,38 @@ var DefaultNativeActionExecutor = class {
|
|
|
1132
1134
|
this.registry.updateElementState(element.id, { value: params.text });
|
|
1133
1135
|
}
|
|
1134
1136
|
}
|
|
1137
|
+
/**
|
|
1138
|
+
* Perform setValue action.
|
|
1139
|
+
*
|
|
1140
|
+
* Web/runner UI Bridge parity: `setValue` replaces the input's value
|
|
1141
|
+
* atomically in a single call (no per-character keystroke simulation),
|
|
1142
|
+
* mirroring the web bridge's `setValue` semantics. On native there is no
|
|
1143
|
+
* DOM value to assign, so we drive the controlled-input handler
|
|
1144
|
+
* (`onChangeText`, falling back to `onChange`) with the full string. The
|
|
1145
|
+
* registry's `state.value` is then synced so a subsequent GET on the
|
|
1146
|
+
* element reflects the new value.
|
|
1147
|
+
*
|
|
1148
|
+
* Unlike `type`, this does not append to existing content and ignores
|
|
1149
|
+
* `delay` — it is the deterministic "set the field to exactly this" action.
|
|
1150
|
+
*/
|
|
1151
|
+
async performSetValue(element, props, params) {
|
|
1152
|
+
const next = typeof params?.text === "string" ? params.text : typeof params?.value === "string" ? params.value : void 0;
|
|
1153
|
+
if (typeof next !== "string") {
|
|
1154
|
+
throw new Error('setValue action requires a string "text" (or "value") parameter');
|
|
1155
|
+
}
|
|
1156
|
+
if (typeof props.onChangeText === "function") {
|
|
1157
|
+
props.onChangeText(next);
|
|
1158
|
+
} else if (typeof props.onChange === "function") {
|
|
1159
|
+
props.onChange({
|
|
1160
|
+
nativeEvent: { text: next }
|
|
1161
|
+
});
|
|
1162
|
+
} else {
|
|
1163
|
+
throw new Error("No text change handler found on element");
|
|
1164
|
+
}
|
|
1165
|
+
if (element) {
|
|
1166
|
+
this.registry.updateElementState(element.id, { value: next });
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1135
1169
|
/**
|
|
1136
1170
|
* Perform clear action
|
|
1137
1171
|
*/
|
|
@@ -2897,7 +2931,8 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2897
2931
|
return success2({
|
|
2898
2932
|
entries: [],
|
|
2899
2933
|
count: 0,
|
|
2900
|
-
bufferSize: 0
|
|
2934
|
+
bufferSize: 0,
|
|
2935
|
+
installed: false
|
|
2901
2936
|
});
|
|
2902
2937
|
}
|
|
2903
2938
|
const entries = buf.entries({
|
|
@@ -2907,7 +2942,8 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2907
2942
|
return success2({
|
|
2908
2943
|
entries,
|
|
2909
2944
|
count: entries.length,
|
|
2910
|
-
bufferSize: buf.size()
|
|
2945
|
+
bufferSize: buf.size(),
|
|
2946
|
+
installed: buf.isInstalled()
|
|
2911
2947
|
});
|
|
2912
2948
|
},
|
|
2913
2949
|
getNetworkRequests: async (ctx) => {
|
|
@@ -2918,7 +2954,8 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2918
2954
|
return success2({
|
|
2919
2955
|
entries: [],
|
|
2920
2956
|
count: 0,
|
|
2921
|
-
bufferSize: 0
|
|
2957
|
+
bufferSize: 0,
|
|
2958
|
+
installed: false
|
|
2922
2959
|
});
|
|
2923
2960
|
}
|
|
2924
2961
|
const entries = buf.entries({
|
|
@@ -2928,7 +2965,8 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2928
2965
|
return success2({
|
|
2929
2966
|
entries,
|
|
2930
2967
|
count: entries.length,
|
|
2931
|
-
bufferSize: buf.size()
|
|
2968
|
+
bufferSize: buf.size(),
|
|
2969
|
+
installed: buf.isInstalled()
|
|
2932
2970
|
});
|
|
2933
2971
|
},
|
|
2934
2972
|
// Test hooks — modal stack manipulation
|
|
@@ -3347,7 +3385,10 @@ var WS_ROUTES = [
|
|
|
3347
3385
|
// same handler at both paths to keep agents portable across platforms.
|
|
3348
3386
|
{ pattern: "ai/find", handler: "find", httpMethods: ["POST"] },
|
|
3349
3387
|
{ pattern: "control/snapshot", handler: "getSnapshot", httpMethods: ["GET"] },
|
|
3350
|
-
|
|
3388
|
+
// Discovery alias — web/runner parity with `POST /control/discover` (a
|
|
3389
|
+
// legacy alias for snapshot/find). Mounted on HTTP (GET+POST) so mobile
|
|
3390
|
+
// doesn't 404 where web returns 200; delegates to the snapshot handler.
|
|
3391
|
+
{ pattern: "control/discover", handler: "getSnapshot", httpMethods: ["GET", "POST"] },
|
|
3351
3392
|
// Page health — accepts both GET and POST so the canonical skill invocation
|
|
3352
3393
|
// (`POST .../control/page-health` with an empty body) and ad-hoc curls both
|
|
3353
3394
|
// work without a body-shape gotcha.
|
|
@@ -3441,19 +3482,26 @@ var WS_ROUTES = [
|
|
|
3441
3482
|
httpMethods: ["POST"],
|
|
3442
3483
|
requiresTestHooks: true
|
|
3443
3484
|
},
|
|
3444
|
-
// Observability — last-N console errors + network requests.
|
|
3445
|
-
//
|
|
3485
|
+
// Observability — last-N console errors + network requests.
|
|
3486
|
+
//
|
|
3487
|
+
// Always mounted (not testHooks-gated) so they return a schema-valid 200
|
|
3488
|
+
// on every build instead of a 404 that agents can't distinguish from a
|
|
3489
|
+
// missing route. The INVASIVE part — monkey-patching `console.error` /
|
|
3490
|
+
// `fetch` / `XMLHttpRequest` — stays gated behind `testHooks` (see
|
|
3491
|
+
// NativeUIBridgeServer.start → buffer.install()). When the patches aren't
|
|
3492
|
+
// installed the handlers report `installed: false` + empty entries, so
|
|
3493
|
+
// production builds expose the contract without observing real users'
|
|
3494
|
+
// console/network traffic. Set `features.testHooks` (typically on
|
|
3495
|
+
// `__DEV__`) to populate the buffers with live data.
|
|
3446
3496
|
{
|
|
3447
3497
|
pattern: "control/console-errors",
|
|
3448
3498
|
handler: "getConsoleErrors",
|
|
3449
|
-
httpMethods: ["GET"]
|
|
3450
|
-
requiresTestHooks: true
|
|
3499
|
+
httpMethods: ["GET"]
|
|
3451
3500
|
},
|
|
3452
3501
|
{
|
|
3453
3502
|
pattern: "sdk/network-requests",
|
|
3454
3503
|
handler: "getNetworkRequests",
|
|
3455
|
-
httpMethods: ["GET"]
|
|
3456
|
-
requiresTestHooks: true
|
|
3504
|
+
httpMethods: ["GET"]
|
|
3457
3505
|
}
|
|
3458
3506
|
];
|
|
3459
3507
|
var HANDLER_DESCRIPTIONS = {
|
|
@@ -3500,8 +3548,8 @@ var HANDLER_DESCRIPTIONS = {
|
|
|
3500
3548
|
typeInto: "App-agnostic: type into the input matching a label: body { label, text, clear?, visibleOnly? }. (selector form is web-only)",
|
|
3501
3549
|
readValue: "STUB \u2014 selector-based; NOT_SUPPORTED on native (no DOM). Use /control/element/:id/state to read a value.",
|
|
3502
3550
|
findByText: "App-agnostic: list elements matching free-text (no press): body { text, visibleOnly? }",
|
|
3503
|
-
getConsoleErrors: "
|
|
3504
|
-
getNetworkRequests: "
|
|
3551
|
+
getConsoleErrors: "Last-N console.error/console.warn entries; ?since=<ms>&limit=<n>. `installed:false` when capture is off (no testHooks) \u2014 entries empty but schema-valid.",
|
|
3552
|
+
getNetworkRequests: "Last-N fetch/XHR entries with status + duration; ?since=<ms>&limit=<n>. `installed:false` when capture is off (no testHooks) \u2014 entries empty but schema-valid.",
|
|
3505
3553
|
pushModal: "TEST HOOK \u2014 push a modal onto the snapshot.modalStack via the registry ModalDetector",
|
|
3506
3554
|
dismissModal: "TEST HOOK \u2014 dismiss a modal by id from the snapshot.modalStack via the registry ModalDetector",
|
|
3507
3555
|
keepAwake: "TEST HOOK \u2014 keep the device screen awake via the injected keepAwakeProvider: body { enabled: boolean, durationMs?: number }"
|
|
@@ -5672,7 +5720,8 @@ function useUIElement(options) {
|
|
|
5672
5720
|
parentPath,
|
|
5673
5721
|
style,
|
|
5674
5722
|
stateStyles: stateStylesProp,
|
|
5675
|
-
handlers: handlersProp
|
|
5723
|
+
handlers: handlersProp,
|
|
5724
|
+
value: valueProp
|
|
5676
5725
|
} = options;
|
|
5677
5726
|
const treePath = parentPath ? `${parentPath}/${id}` : id;
|
|
5678
5727
|
const bridgeProps = useMemo(
|
|
@@ -5698,9 +5747,12 @@ function useUIElement(options) {
|
|
|
5698
5747
|
});
|
|
5699
5748
|
registeredRef.current = true;
|
|
5700
5749
|
registeredIdRef.current = id;
|
|
5750
|
+
if (typeof valueProp === "string") {
|
|
5751
|
+
bridge.registry.updateElementState(id, { value: valueProp });
|
|
5752
|
+
}
|
|
5701
5753
|
setRegistered(true);
|
|
5702
5754
|
scheduleDeadButtonWarning(bridge, id, type);
|
|
5703
|
-
}, [bridge, id, type, label, actions, customActions, treePath, style, stateStylesProp]);
|
|
5755
|
+
}, [bridge, id, type, label, actions, customActions, treePath, style, stateStylesProp, valueProp]);
|
|
5704
5756
|
const unregister = useCallback(() => {
|
|
5705
5757
|
if (!bridge || !registeredRef.current) return;
|
|
5706
5758
|
bridge.registry.unregisterElement(registeredIdRef.current ?? id);
|
|
@@ -5830,6 +5882,13 @@ function useUIElement(options) {
|
|
|
5830
5882
|
}
|
|
5831
5883
|
};
|
|
5832
5884
|
}, [bridge, registered, id, handlersProp]);
|
|
5885
|
+
useEffect(() => {
|
|
5886
|
+
if (!bridge || !registered) return;
|
|
5887
|
+
if (typeof valueProp !== "string") return;
|
|
5888
|
+
const current = bridge.registry.getElement(id)?.getState().value;
|
|
5889
|
+
if (current === valueProp) return;
|
|
5890
|
+
bridge.registry.updateElementState(id, { value: valueProp });
|
|
5891
|
+
}, [bridge, registered, id, valueProp]);
|
|
5833
5892
|
useCallback(
|
|
5834
5893
|
(props) => {
|
|
5835
5894
|
propsRef.current = { ...propsRef.current, ...props };
|
|
@@ -6221,6 +6280,11 @@ var UI_BRIDGE_NATIVE_ROUTES = {
|
|
|
6221
6280
|
path: "/ui-bridge/control/snapshot",
|
|
6222
6281
|
description: "Get full bridge snapshot"
|
|
6223
6282
|
},
|
|
6283
|
+
DISCOVER: {
|
|
6284
|
+
method: "GET",
|
|
6285
|
+
path: "/ui-bridge/control/discover",
|
|
6286
|
+
description: "Discover elements (alias for snapshot; web/runner parity)"
|
|
6287
|
+
},
|
|
6224
6288
|
PAGE_HEALTH: {
|
|
6225
6289
|
method: "POST",
|
|
6226
6290
|
path: "/ui-bridge/control/page-health",
|
|
@@ -6348,6 +6412,18 @@ var UI_BRIDGE_NATIVE_ROUTES = {
|
|
|
6348
6412
|
path: "/ui-bridge/control/modal/dismiss/:id",
|
|
6349
6413
|
description: "Dismiss a modal by id (testHooks)"
|
|
6350
6414
|
},
|
|
6415
|
+
// Observability — last-N ring buffers (always mounted; `installed:false`
|
|
6416
|
+
// when the console/network patches are off, i.e. no testHooks).
|
|
6417
|
+
CONSOLE_ERRORS: {
|
|
6418
|
+
method: "GET",
|
|
6419
|
+
path: "/ui-bridge/control/console-errors",
|
|
6420
|
+
description: "Last-N captured console.error/console.warn entries"
|
|
6421
|
+
},
|
|
6422
|
+
NETWORK_REQUESTS: {
|
|
6423
|
+
method: "GET",
|
|
6424
|
+
path: "/ui-bridge/sdk/network-requests",
|
|
6425
|
+
description: "Last-N captured fetch/XHR requests with status + duration"
|
|
6426
|
+
},
|
|
6351
6427
|
// Health
|
|
6352
6428
|
HEALTH: {
|
|
6353
6429
|
method: "GET",
|