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