@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/react/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":
|
|
@@ -988,6 +988,8 @@ var DefaultNativeActionExecutor = class {
|
|
|
988
988
|
return this.performDoubleTap(props);
|
|
989
989
|
case "type":
|
|
990
990
|
return this.performType(element, props, params);
|
|
991
|
+
case "setValue":
|
|
992
|
+
return this.performSetValue(element, props, params);
|
|
991
993
|
case "clear":
|
|
992
994
|
return this.performClear(element, props);
|
|
993
995
|
case "focus":
|
|
@@ -1080,6 +1082,38 @@ var DefaultNativeActionExecutor = class {
|
|
|
1080
1082
|
this.registry.updateElementState(element.id, { value: params.text });
|
|
1081
1083
|
}
|
|
1082
1084
|
}
|
|
1085
|
+
/**
|
|
1086
|
+
* Perform setValue action.
|
|
1087
|
+
*
|
|
1088
|
+
* Web/runner UI Bridge parity: `setValue` replaces the input's value
|
|
1089
|
+
* atomically in a single call (no per-character keystroke simulation),
|
|
1090
|
+
* mirroring the web bridge's `setValue` semantics. On native there is no
|
|
1091
|
+
* DOM value to assign, so we drive the controlled-input handler
|
|
1092
|
+
* (`onChangeText`, falling back to `onChange`) with the full string. The
|
|
1093
|
+
* registry's `state.value` is then synced so a subsequent GET on the
|
|
1094
|
+
* element reflects the new value.
|
|
1095
|
+
*
|
|
1096
|
+
* Unlike `type`, this does not append to existing content and ignores
|
|
1097
|
+
* `delay` — it is the deterministic "set the field to exactly this" action.
|
|
1098
|
+
*/
|
|
1099
|
+
async performSetValue(element, props, params) {
|
|
1100
|
+
const next = typeof params?.text === "string" ? params.text : typeof params?.value === "string" ? params.value : void 0;
|
|
1101
|
+
if (typeof next !== "string") {
|
|
1102
|
+
throw new Error('setValue action requires a string "text" (or "value") parameter');
|
|
1103
|
+
}
|
|
1104
|
+
if (typeof props.onChangeText === "function") {
|
|
1105
|
+
props.onChangeText(next);
|
|
1106
|
+
} else if (typeof props.onChange === "function") {
|
|
1107
|
+
props.onChange({
|
|
1108
|
+
nativeEvent: { text: next }
|
|
1109
|
+
});
|
|
1110
|
+
} else {
|
|
1111
|
+
throw new Error("No text change handler found on element");
|
|
1112
|
+
}
|
|
1113
|
+
if (element) {
|
|
1114
|
+
this.registry.updateElementState(element.id, { value: next });
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1083
1117
|
/**
|
|
1084
1118
|
* Perform clear action
|
|
1085
1119
|
*/
|
|
@@ -2845,7 +2879,8 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2845
2879
|
return success2({
|
|
2846
2880
|
entries: [],
|
|
2847
2881
|
count: 0,
|
|
2848
|
-
bufferSize: 0
|
|
2882
|
+
bufferSize: 0,
|
|
2883
|
+
installed: false
|
|
2849
2884
|
});
|
|
2850
2885
|
}
|
|
2851
2886
|
const entries = buf.entries({
|
|
@@ -2855,7 +2890,8 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2855
2890
|
return success2({
|
|
2856
2891
|
entries,
|
|
2857
2892
|
count: entries.length,
|
|
2858
|
-
bufferSize: buf.size()
|
|
2893
|
+
bufferSize: buf.size(),
|
|
2894
|
+
installed: buf.isInstalled()
|
|
2859
2895
|
});
|
|
2860
2896
|
},
|
|
2861
2897
|
getNetworkRequests: async (ctx) => {
|
|
@@ -2866,7 +2902,8 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2866
2902
|
return success2({
|
|
2867
2903
|
entries: [],
|
|
2868
2904
|
count: 0,
|
|
2869
|
-
bufferSize: 0
|
|
2905
|
+
bufferSize: 0,
|
|
2906
|
+
installed: false
|
|
2870
2907
|
});
|
|
2871
2908
|
}
|
|
2872
2909
|
const entries = buf.entries({
|
|
@@ -2876,7 +2913,8 @@ function createServerHandlers(registry, executor, config) {
|
|
|
2876
2913
|
return success2({
|
|
2877
2914
|
entries,
|
|
2878
2915
|
count: entries.length,
|
|
2879
|
-
bufferSize: buf.size()
|
|
2916
|
+
bufferSize: buf.size(),
|
|
2917
|
+
installed: buf.isInstalled()
|
|
2880
2918
|
});
|
|
2881
2919
|
},
|
|
2882
2920
|
// Test hooks — modal stack manipulation
|
|
@@ -3295,7 +3333,10 @@ var WS_ROUTES = [
|
|
|
3295
3333
|
// same handler at both paths to keep agents portable across platforms.
|
|
3296
3334
|
{ pattern: "ai/find", handler: "find", httpMethods: ["POST"] },
|
|
3297
3335
|
{ pattern: "control/snapshot", handler: "getSnapshot", httpMethods: ["GET"] },
|
|
3298
|
-
|
|
3336
|
+
// Discovery alias — web/runner parity with `POST /control/discover` (a
|
|
3337
|
+
// legacy alias for snapshot/find). Mounted on HTTP (GET+POST) so mobile
|
|
3338
|
+
// doesn't 404 where web returns 200; delegates to the snapshot handler.
|
|
3339
|
+
{ pattern: "control/discover", handler: "getSnapshot", httpMethods: ["GET", "POST"] },
|
|
3299
3340
|
// Page health — accepts both GET and POST so the canonical skill invocation
|
|
3300
3341
|
// (`POST .../control/page-health` with an empty body) and ad-hoc curls both
|
|
3301
3342
|
// work without a body-shape gotcha.
|
|
@@ -3389,19 +3430,26 @@ var WS_ROUTES = [
|
|
|
3389
3430
|
httpMethods: ["POST"],
|
|
3390
3431
|
requiresTestHooks: true
|
|
3391
3432
|
},
|
|
3392
|
-
// Observability — last-N console errors + network requests.
|
|
3393
|
-
//
|
|
3433
|
+
// Observability — last-N console errors + network requests.
|
|
3434
|
+
//
|
|
3435
|
+
// Always mounted (not testHooks-gated) so they return a schema-valid 200
|
|
3436
|
+
// on every build instead of a 404 that agents can't distinguish from a
|
|
3437
|
+
// missing route. The INVASIVE part — monkey-patching `console.error` /
|
|
3438
|
+
// `fetch` / `XMLHttpRequest` — stays gated behind `testHooks` (see
|
|
3439
|
+
// NativeUIBridgeServer.start → buffer.install()). When the patches aren't
|
|
3440
|
+
// installed the handlers report `installed: false` + empty entries, so
|
|
3441
|
+
// production builds expose the contract without observing real users'
|
|
3442
|
+
// console/network traffic. Set `features.testHooks` (typically on
|
|
3443
|
+
// `__DEV__`) to populate the buffers with live data.
|
|
3394
3444
|
{
|
|
3395
3445
|
pattern: "control/console-errors",
|
|
3396
3446
|
handler: "getConsoleErrors",
|
|
3397
|
-
httpMethods: ["GET"]
|
|
3398
|
-
requiresTestHooks: true
|
|
3447
|
+
httpMethods: ["GET"]
|
|
3399
3448
|
},
|
|
3400
3449
|
{
|
|
3401
3450
|
pattern: "sdk/network-requests",
|
|
3402
3451
|
handler: "getNetworkRequests",
|
|
3403
|
-
httpMethods: ["GET"]
|
|
3404
|
-
requiresTestHooks: true
|
|
3452
|
+
httpMethods: ["GET"]
|
|
3405
3453
|
}
|
|
3406
3454
|
];
|
|
3407
3455
|
var HANDLER_DESCRIPTIONS = {
|
|
@@ -3448,8 +3496,8 @@ var HANDLER_DESCRIPTIONS = {
|
|
|
3448
3496
|
typeInto: "App-agnostic: type into the input matching a label: body { label, text, clear?, visibleOnly? }. (selector form is web-only)",
|
|
3449
3497
|
readValue: "STUB \u2014 selector-based; NOT_SUPPORTED on native (no DOM). Use /control/element/:id/state to read a value.",
|
|
3450
3498
|
findByText: "App-agnostic: list elements matching free-text (no press): body { text, visibleOnly? }",
|
|
3451
|
-
getConsoleErrors: "
|
|
3452
|
-
getNetworkRequests: "
|
|
3499
|
+
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.",
|
|
3500
|
+
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.",
|
|
3453
3501
|
pushModal: "TEST HOOK \u2014 push a modal onto the snapshot.modalStack via the registry ModalDetector",
|
|
3454
3502
|
dismissModal: "TEST HOOK \u2014 dismiss a modal by id from the snapshot.modalStack via the registry ModalDetector",
|
|
3455
3503
|
keepAwake: "TEST HOOK \u2014 keep the device screen awake via the injected keepAwakeProvider: body { enabled: boolean, durationMs?: number }"
|
|
@@ -5620,7 +5668,8 @@ function useUIElement(options) {
|
|
|
5620
5668
|
parentPath,
|
|
5621
5669
|
style,
|
|
5622
5670
|
stateStyles: stateStylesProp,
|
|
5623
|
-
handlers: handlersProp
|
|
5671
|
+
handlers: handlersProp,
|
|
5672
|
+
value: valueProp
|
|
5624
5673
|
} = options;
|
|
5625
5674
|
const treePath = parentPath ? `${parentPath}/${id}` : id;
|
|
5626
5675
|
const bridgeProps = useMemo(
|
|
@@ -5646,9 +5695,12 @@ function useUIElement(options) {
|
|
|
5646
5695
|
});
|
|
5647
5696
|
registeredRef.current = true;
|
|
5648
5697
|
registeredIdRef.current = id;
|
|
5698
|
+
if (typeof valueProp === "string") {
|
|
5699
|
+
bridge.registry.updateElementState(id, { value: valueProp });
|
|
5700
|
+
}
|
|
5649
5701
|
setRegistered(true);
|
|
5650
5702
|
scheduleDeadButtonWarning(bridge, id, type);
|
|
5651
|
-
}, [bridge, id, type, label, actions, customActions, treePath, style, stateStylesProp]);
|
|
5703
|
+
}, [bridge, id, type, label, actions, customActions, treePath, style, stateStylesProp, valueProp]);
|
|
5652
5704
|
const unregister = useCallback(() => {
|
|
5653
5705
|
if (!bridge || !registeredRef.current) return;
|
|
5654
5706
|
bridge.registry.unregisterElement(registeredIdRef.current ?? id);
|
|
@@ -5778,6 +5830,13 @@ function useUIElement(options) {
|
|
|
5778
5830
|
}
|
|
5779
5831
|
};
|
|
5780
5832
|
}, [bridge, registered, id, handlersProp]);
|
|
5833
|
+
useEffect(() => {
|
|
5834
|
+
if (!bridge || !registered) return;
|
|
5835
|
+
if (typeof valueProp !== "string") return;
|
|
5836
|
+
const current = bridge.registry.getElement(id)?.getState().value;
|
|
5837
|
+
if (current === valueProp) return;
|
|
5838
|
+
bridge.registry.updateElementState(id, { value: valueProp });
|
|
5839
|
+
}, [bridge, registered, id, valueProp]);
|
|
5781
5840
|
useCallback(
|
|
5782
5841
|
(props) => {
|
|
5783
5842
|
propsRef.current = { ...propsRef.current, ...props };
|