@reticlehq/browser 2.2.1 → 2.4.0
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/actions/actions-dom.d.ts +0 -1
- package/dist/actions/actions-dom.js +0 -1
- package/dist/actions/actions.d.ts +3 -1
- package/dist/actions/actions.js +55 -36
- package/dist/actions/scroll.d.ts +0 -1
- package/dist/actions/scroll.js +0 -1
- package/dist/actions/value-input.d.ts +33 -0
- package/dist/actions/value-input.js +63 -0
- package/dist/commands/commands.d.ts +0 -1
- package/dist/commands/commands.js +27 -7
- package/dist/connect-options.d.ts +97 -0
- package/dist/connect-options.js +1 -0
- package/dist/dom/a11y.d.ts +0 -2
- package/dist/dom/a11y.js +54 -24
- package/dist/dom/auto-anchor.d.ts +0 -1
- package/dist/dom/auto-anchor.js +0 -1
- package/dist/dom/blind-spots.d.ts +0 -1
- package/dist/dom/blind-spots.js +0 -1
- package/dist/dom/chart.d.ts +0 -1
- package/dist/dom/chart.js +0 -1
- package/dist/dom/desktop-capture.d.ts +36 -0
- package/dist/dom/desktop-capture.js +113 -0
- package/dist/dom/dom-ignore.d.ts +7 -1
- package/dist/dom/dom-ignore.js +1 -2
- package/dist/dom/occlusion.d.ts +0 -1
- package/dist/dom/occlusion.js +0 -1
- package/dist/dom/query.d.ts +0 -1
- package/dist/dom/query.js +61 -13
- package/dist/dom/realm.d.ts +30 -0
- package/dist/dom/realm.js +58 -0
- package/dist/dom/refs.d.ts +0 -1
- package/dist/dom/refs.js +0 -1
- package/dist/dom/shadow-registry.d.ts +40 -0
- package/dist/dom/shadow-registry.js +165 -0
- package/dist/dom/snapshot.d.ts +2 -2
- package/dist/dom/snapshot.js +21 -4
- package/dist/dom/source.d.ts +0 -1
- package/dist/dom/source.js +0 -1
- package/dist/dom/theme.d.ts +0 -1
- package/dist/dom/theme.js +0 -1
- package/dist/dom/virtualized.d.ts +19 -0
- package/dist/dom/virtualized.js +80 -0
- package/dist/index.d.ts +3 -4
- package/dist/index.js +2 -3
- package/dist/observers/animation.d.ts +0 -1
- package/dist/observers/animation.js +0 -1
- package/dist/observers/blind-spots.d.ts +16 -4
- package/dist/observers/blind-spots.js +65 -11
- package/dist/observers/console.d.ts +0 -1
- package/dist/observers/console.js +0 -1
- package/dist/observers/dom.d.ts +0 -2
- package/dist/observers/dom.js +67 -9
- package/dist/observers/download.d.ts +6 -0
- package/dist/observers/download.js +103 -0
- package/dist/observers/focus.d.ts +0 -1
- package/dist/observers/focus.js +0 -1
- package/dist/observers/frames.d.ts +12 -0
- package/dist/observers/frames.js +67 -0
- package/dist/observers/health.d.ts +0 -1
- package/dist/observers/health.js +30 -2
- package/dist/observers/install-all.d.ts +5 -0
- package/dist/observers/install-all.js +63 -0
- package/dist/observers/ipc.d.ts +22 -0
- package/dist/observers/ipc.js +121 -0
- package/dist/observers/network-body.d.ts +17 -1
- package/dist/observers/network-body.js +26 -1
- package/dist/observers/network-redact.d.ts +0 -1
- package/dist/observers/network-redact.js +6 -3
- package/dist/observers/network-stream.d.ts +23 -0
- package/dist/observers/network-stream.js +102 -0
- package/dist/observers/network.d.ts +11 -1
- package/dist/observers/network.js +7 -1
- package/dist/observers/perf.d.ts +0 -1
- package/dist/observers/perf.js +0 -1
- package/dist/observers/route.d.ts +0 -1
- package/dist/observers/route.js +0 -1
- package/dist/observers/scroll.d.ts +0 -1
- package/dist/observers/scroll.js +0 -1
- package/dist/observers/sdk-failure.d.ts +28 -0
- package/dist/observers/sdk-failure.js +60 -0
- package/dist/observers/state.d.ts +0 -1
- package/dist/observers/state.js +0 -1
- package/dist/observers/storage.d.ts +0 -1
- package/dist/observers/storage.js +0 -1
- package/dist/observers/types.d.ts +0 -1
- package/dist/observers/types.js +0 -1
- package/dist/patching/capture-method.d.ts +0 -1
- package/dist/patching/capture-method.js +0 -1
- package/dist/presenter/overlay.d.ts +0 -1
- package/dist/presenter/overlay.js +0 -1
- package/dist/presenter/presenter-config.d.ts +0 -1
- package/dist/presenter/presenter-config.js +0 -1
- package/dist/presenter/presenter-controls.d.ts +0 -1
- package/dist/presenter/presenter-controls.js +0 -1
- package/dist/presenter/presenter-effects.d.ts +0 -1
- package/dist/presenter/presenter-effects.js +0 -1
- package/dist/presenter/presenter-glow.d.ts +0 -1
- package/dist/presenter/presenter-glow.js +0 -1
- package/dist/presenter/presenter-log.d.ts +0 -1
- package/dist/presenter/presenter-log.js +0 -1
- package/dist/presenter/presenter-run-state.d.ts +0 -1
- package/dist/presenter/presenter-run-state.js +0 -1
- package/dist/presenter/presenter-styles.d.ts +0 -1
- package/dist/presenter/presenter-styles.js +0 -1
- package/dist/presenter/presenter-tally.d.ts +0 -1
- package/dist/presenter/presenter-tally.js +0 -1
- package/dist/presenter/presenter-test-helpers.d.ts +0 -1
- package/dist/presenter/presenter-test-helpers.js +0 -1
- package/dist/presenter/presenter-verbs.d.ts +0 -1
- package/dist/presenter/presenter-verbs.js +0 -1
- package/dist/presenter/presenter.d.ts +0 -1
- package/dist/presenter/presenter.js +0 -1
- package/dist/recorder/recorder-styles.d.ts +0 -1
- package/dist/recorder/recorder-styles.js +0 -1
- package/dist/recorder/recorder.d.ts +0 -1
- package/dist/recorder/recorder.js +0 -1
- package/dist/registry/adapters.d.ts +0 -1
- package/dist/registry/adapters.js +0 -1
- package/dist/registry/capabilities.d.ts +2 -1
- package/dist/registry/capabilities.js +16 -1
- package/dist/registry/commit-and-signal.d.ts +0 -1
- package/dist/registry/commit-and-signal.js +0 -1
- package/dist/registry/domains.d.ts +0 -1
- package/dist/registry/domains.js +0 -1
- package/dist/registry/emitter.d.ts +0 -1
- package/dist/registry/emitter.js +0 -1
- package/dist/registry/store-adapters.d.ts +141 -7
- package/dist/registry/store-adapters.js +178 -1
- package/dist/registry/stores.d.ts +0 -1
- package/dist/registry/stores.js +8 -1
- package/dist/reticle-presenter-helpers.d.ts +0 -1
- package/dist/reticle-presenter-helpers.js +0 -1
- package/dist/reticle.d.ts +5 -59
- package/dist/reticle.js +37 -33
- package/dist/review/annotator.d.ts +0 -1
- package/dist/review/annotator.js +0 -1
- package/dist/review/mark-anchor.d.ts +0 -1
- package/dist/review/mark-anchor.js +0 -1
- package/dist/security/serialization.d.ts +0 -1
- package/dist/security/serialization.js +0 -1
- package/dist/timers/clock.d.ts +0 -1
- package/dist/timers/clock.js +0 -1
- package/dist/timers/native-console.d.ts +0 -1
- package/dist/timers/native-console.js +0 -1
- package/dist/timers/native-timers.d.ts +0 -1
- package/dist/timers/native-timers.js +0 -1
- package/dist/transport/transport.d.ts +12 -6
- package/dist/transport/transport.js +107 -17
- package/package.json +13 -3
- package/dist/actions/actions-dom.d.ts.map +0 -1
- package/dist/actions/actions-dom.js.map +0 -1
- package/dist/actions/actions.d.ts.map +0 -1
- package/dist/actions/actions.js.map +0 -1
- package/dist/actions/scroll.d.ts.map +0 -1
- package/dist/actions/scroll.js.map +0 -1
- package/dist/commands/commands.d.ts.map +0 -1
- package/dist/commands/commands.js.map +0 -1
- package/dist/dom/a11y.d.ts.map +0 -1
- package/dist/dom/a11y.js.map +0 -1
- package/dist/dom/auto-anchor.d.ts.map +0 -1
- package/dist/dom/auto-anchor.js.map +0 -1
- package/dist/dom/blind-spots.d.ts.map +0 -1
- package/dist/dom/blind-spots.js.map +0 -1
- package/dist/dom/chart.d.ts.map +0 -1
- package/dist/dom/chart.js.map +0 -1
- package/dist/dom/dom-ignore.d.ts.map +0 -1
- package/dist/dom/dom-ignore.js.map +0 -1
- package/dist/dom/occlusion.d.ts.map +0 -1
- package/dist/dom/occlusion.js.map +0 -1
- package/dist/dom/query.d.ts.map +0 -1
- package/dist/dom/query.js.map +0 -1
- package/dist/dom/refs.d.ts.map +0 -1
- package/dist/dom/refs.js.map +0 -1
- package/dist/dom/snapshot.d.ts.map +0 -1
- package/dist/dom/snapshot.js.map +0 -1
- package/dist/dom/source.d.ts.map +0 -1
- package/dist/dom/source.js.map +0 -1
- package/dist/dom/theme.d.ts.map +0 -1
- package/dist/dom/theme.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/observers/animation.d.ts.map +0 -1
- package/dist/observers/animation.js.map +0 -1
- package/dist/observers/blind-spots.d.ts.map +0 -1
- package/dist/observers/blind-spots.js.map +0 -1
- package/dist/observers/console.d.ts.map +0 -1
- package/dist/observers/console.js.map +0 -1
- package/dist/observers/dom.d.ts.map +0 -1
- package/dist/observers/dom.js.map +0 -1
- package/dist/observers/focus.d.ts.map +0 -1
- package/dist/observers/focus.js.map +0 -1
- package/dist/observers/health.d.ts.map +0 -1
- package/dist/observers/health.js.map +0 -1
- package/dist/observers/network-body.d.ts.map +0 -1
- package/dist/observers/network-body.js.map +0 -1
- package/dist/observers/network-redact.d.ts.map +0 -1
- package/dist/observers/network-redact.js.map +0 -1
- package/dist/observers/network.d.ts.map +0 -1
- package/dist/observers/network.js.map +0 -1
- package/dist/observers/perf.d.ts.map +0 -1
- package/dist/observers/perf.js.map +0 -1
- package/dist/observers/route.d.ts.map +0 -1
- package/dist/observers/route.js.map +0 -1
- package/dist/observers/scroll.d.ts.map +0 -1
- package/dist/observers/scroll.js.map +0 -1
- package/dist/observers/state.d.ts.map +0 -1
- package/dist/observers/state.js.map +0 -1
- package/dist/observers/storage.d.ts.map +0 -1
- package/dist/observers/storage.js.map +0 -1
- package/dist/observers/types.d.ts.map +0 -1
- package/dist/observers/types.js.map +0 -1
- package/dist/patching/capture-method.d.ts.map +0 -1
- package/dist/patching/capture-method.js.map +0 -1
- package/dist/presenter/overlay.d.ts.map +0 -1
- package/dist/presenter/overlay.js.map +0 -1
- package/dist/presenter/presenter-config.d.ts.map +0 -1
- package/dist/presenter/presenter-config.js.map +0 -1
- package/dist/presenter/presenter-controls.d.ts.map +0 -1
- package/dist/presenter/presenter-controls.js.map +0 -1
- package/dist/presenter/presenter-effects.d.ts.map +0 -1
- package/dist/presenter/presenter-effects.js.map +0 -1
- package/dist/presenter/presenter-glow.d.ts.map +0 -1
- package/dist/presenter/presenter-glow.js.map +0 -1
- package/dist/presenter/presenter-log.d.ts.map +0 -1
- package/dist/presenter/presenter-log.js.map +0 -1
- package/dist/presenter/presenter-run-state.d.ts.map +0 -1
- package/dist/presenter/presenter-run-state.js.map +0 -1
- package/dist/presenter/presenter-styles.d.ts.map +0 -1
- package/dist/presenter/presenter-styles.js.map +0 -1
- package/dist/presenter/presenter-tally.d.ts.map +0 -1
- package/dist/presenter/presenter-tally.js.map +0 -1
- package/dist/presenter/presenter-test-helpers.d.ts.map +0 -1
- package/dist/presenter/presenter-test-helpers.js.map +0 -1
- package/dist/presenter/presenter-verbs.d.ts.map +0 -1
- package/dist/presenter/presenter-verbs.js.map +0 -1
- package/dist/presenter/presenter.d.ts.map +0 -1
- package/dist/presenter/presenter.js.map +0 -1
- package/dist/recorder/recorder-styles.d.ts.map +0 -1
- package/dist/recorder/recorder-styles.js.map +0 -1
- package/dist/recorder/recorder.d.ts.map +0 -1
- package/dist/recorder/recorder.js.map +0 -1
- package/dist/registry/adapters.d.ts.map +0 -1
- package/dist/registry/adapters.js.map +0 -1
- package/dist/registry/capabilities.d.ts.map +0 -1
- package/dist/registry/capabilities.js.map +0 -1
- package/dist/registry/commit-and-signal.d.ts.map +0 -1
- package/dist/registry/commit-and-signal.js.map +0 -1
- package/dist/registry/domains.d.ts.map +0 -1
- package/dist/registry/domains.js.map +0 -1
- package/dist/registry/emitter.d.ts.map +0 -1
- package/dist/registry/emitter.js.map +0 -1
- package/dist/registry/store-adapters.d.ts.map +0 -1
- package/dist/registry/store-adapters.js.map +0 -1
- package/dist/registry/stores.d.ts.map +0 -1
- package/dist/registry/stores.js.map +0 -1
- package/dist/reticle-presenter-helpers.d.ts.map +0 -1
- package/dist/reticle-presenter-helpers.js.map +0 -1
- package/dist/reticle.d.ts.map +0 -1
- package/dist/reticle.js.map +0 -1
- package/dist/review/annotator.d.ts.map +0 -1
- package/dist/review/annotator.js.map +0 -1
- package/dist/review/mark-anchor.d.ts.map +0 -1
- package/dist/review/mark-anchor.js.map +0 -1
- package/dist/security/serialization.d.ts.map +0 -1
- package/dist/security/serialization.js.map +0 -1
- package/dist/timers/clock.d.ts.map +0 -1
- package/dist/timers/clock.js.map +0 -1
- package/dist/timers/native-console.d.ts.map +0 -1
- package/dist/timers/native-console.js.map +0 -1
- package/dist/timers/native-timers.d.ts.map +0 -1
- package/dist/timers/native-timers.js.map +0 -1
- package/dist/transport/transport.d.ts.map +0 -1
- package/dist/transport/transport.js.map +0 -1
|
@@ -51,6 +51,9 @@ interface ActionResult {
|
|
|
51
51
|
* degraded role one — addressing the element across replays with zero hand-added testids.
|
|
52
52
|
*/
|
|
53
53
|
component?: string;
|
|
54
|
+
/** Role + accessible name — the anchor that identifies an INSTANCE, not a JSX site. */
|
|
55
|
+
role?: string;
|
|
56
|
+
name?: string;
|
|
54
57
|
source?: {
|
|
55
58
|
file: string;
|
|
56
59
|
line: number;
|
|
@@ -89,4 +92,3 @@ export declare function executeSequence(steps: ActionStep[]): Promise<{
|
|
|
89
92
|
steps: SequenceStepResult[];
|
|
90
93
|
}>;
|
|
91
94
|
export {};
|
|
92
|
-
//# sourceMappingURL=actions.d.ts.map
|
package/dist/actions/actions.js
CHANGED
|
@@ -1,26 +1,10 @@
|
|
|
1
1
|
import { ActionType, ActionWarning, DANGEROUS_ACTION_CONFIRM_ARG, ElementState, isDangerousActionText, SettleReason, } from '@reticlehq/core';
|
|
2
2
|
import { refs } from '../dom/refs.js';
|
|
3
|
-
import {
|
|
3
|
+
import { assertEditable, assertNotRichText, setNativeValue } from './value-input.js';
|
|
4
|
+
import { getAccessibleName, getRole, isVisible, getStates } from '../dom/a11y.js';
|
|
4
5
|
import { elementHasHoverHandlers, identifyComponent } from '../registry/adapters.js';
|
|
5
|
-
import {
|
|
6
|
+
import { isForm, isHtmlElement, isInput, isSelect, isTextArea } from '../dom/realm.js';
|
|
6
7
|
import { nativeSetTimeout, settle } from '../timers/native-timers.js';
|
|
7
|
-
/**
|
|
8
|
-
* Set a value on a controlled input the way React expects (native setter + input event).
|
|
9
|
-
* Returns the `input` event's dispatchEvent result (defaultPrevented of the primary event).
|
|
10
|
-
*/
|
|
11
|
-
function setNativeValue(el, value) {
|
|
12
|
-
const proto = el instanceof HTMLTextAreaElement ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype;
|
|
13
|
-
const setter = captureValueSetter(proto);
|
|
14
|
-
if (setter !== undefined) {
|
|
15
|
-
setter.call(el, value);
|
|
16
|
-
}
|
|
17
|
-
else {
|
|
18
|
-
el.value = value;
|
|
19
|
-
}
|
|
20
|
-
const notPrevented = el.dispatchEvent(new Event('input', { bubbles: true, cancelable: true }));
|
|
21
|
-
el.dispatchEvent(new Event('change', { bubbles: true }));
|
|
22
|
-
return !notPrevented;
|
|
23
|
-
}
|
|
24
8
|
function asString(value, fallback = '') {
|
|
25
9
|
return typeof value === 'string' ? value : fallback;
|
|
26
10
|
}
|
|
@@ -28,7 +12,7 @@ function requireElement(ref) {
|
|
|
28
12
|
const el = refs.resolve(ref);
|
|
29
13
|
if (el === null)
|
|
30
14
|
throw new Error(`ref '${ref}' no longer resolves to an element`);
|
|
31
|
-
if (!(el
|
|
15
|
+
if (!isHtmlElement(el))
|
|
32
16
|
throw new Error(`ref '${ref}' is not an HTMLElement`);
|
|
33
17
|
return el;
|
|
34
18
|
}
|
|
@@ -55,6 +39,12 @@ function anchorOf(el) {
|
|
|
55
39
|
out.component = component;
|
|
56
40
|
if (info?.source !== undefined)
|
|
57
41
|
out.source = info.source;
|
|
42
|
+
const role = getRole(el);
|
|
43
|
+
const name = getAccessibleName(el);
|
|
44
|
+
if (role.length > 0 && name.length > 0) {
|
|
45
|
+
out.role = role;
|
|
46
|
+
out.name = name;
|
|
47
|
+
}
|
|
58
48
|
return out;
|
|
59
49
|
}
|
|
60
50
|
const result = (ref, action, effect, settled, settleReason, anchor, warning) => {
|
|
@@ -77,6 +67,10 @@ const result = (ref, action, effect, settled, settleReason, anchor, warning) =>
|
|
|
77
67
|
base.component = anchor.component;
|
|
78
68
|
if (anchor.source !== undefined)
|
|
79
69
|
base.source = anchor.source;
|
|
70
|
+
if (anchor.role !== undefined)
|
|
71
|
+
base.role = anchor.role;
|
|
72
|
+
if (anchor.name !== undefined)
|
|
73
|
+
base.name = anchor.name;
|
|
80
74
|
if (warning !== undefined)
|
|
81
75
|
base.warning = warning;
|
|
82
76
|
return base;
|
|
@@ -116,7 +110,7 @@ function assertActionAllowed(el, action, args) {
|
|
|
116
110
|
action === ActionType.SUBMIT ||
|
|
117
111
|
(action === ActionType.PRESS && asString(args['key'], 'Enter') === 'Enter');
|
|
118
112
|
const dragTarget = action === ActionType.DRAG ? refs.resolve(asString(args['toRef'])) : null;
|
|
119
|
-
const context = dragTarget
|
|
113
|
+
const context = isHtmlElement(dragTarget)
|
|
120
114
|
? `${dangerousActionContext(el)} ${dangerousActionContext(dragTarget)}`
|
|
121
115
|
: dangerousActionContext(el);
|
|
122
116
|
if (canTrigger &&
|
|
@@ -133,9 +127,7 @@ function enabledOf(el) {
|
|
|
133
127
|
}
|
|
134
128
|
/** Current value for inputs/textareas/selects, else undefined. */
|
|
135
129
|
function valueOf(el) {
|
|
136
|
-
if (el
|
|
137
|
-
el instanceof HTMLTextAreaElement ||
|
|
138
|
-
el instanceof HTMLSelectElement) {
|
|
130
|
+
if (isInput(el) || isTextArea(el) || isSelect(el)) {
|
|
139
131
|
return el.value;
|
|
140
132
|
}
|
|
141
133
|
return undefined;
|
|
@@ -190,41 +182,69 @@ async function dispatchFor(el, action, args) {
|
|
|
190
182
|
el.dispatchEvent(new FocusEvent('focusout', { bubbles: true }));
|
|
191
183
|
return false;
|
|
192
184
|
case ActionType.FILL:
|
|
193
|
-
if (el
|
|
185
|
+
if (isInput(el) || isTextArea(el)) {
|
|
186
|
+
// A MISSING value is a malformed call, not a request to empty the field. `asString` defaults
|
|
187
|
+
// to '', which made such a fill indistinguishable from `clear`: it wiped what was there,
|
|
188
|
+
// dispatched a real input event so React committed the empty string to state, and reported
|
|
189
|
+
// ok:true with nothing flagged. The value is nested (`args:{value}`) at the tool boundary, so
|
|
190
|
+
// passing it at the top level lands here — measured on bench-app's login form, where
|
|
191
|
+
// "admin@reticle.dev" was destroyed by a fill that reported success. An explicit '' still
|
|
192
|
+
// clears, because that is someone asking for it.
|
|
193
|
+
if (typeof args['value'] !== 'string') {
|
|
194
|
+
throw new Error("fill requires a string `value` — pass it nested, as args: { value: '…' }. " +
|
|
195
|
+
'To empty a field on purpose use the `clear` action, or fill with an explicit "".');
|
|
196
|
+
}
|
|
197
|
+
assertEditable(el, 'fill');
|
|
194
198
|
el.focus(); // focus first so a later blur commits (onBlur editors)
|
|
195
|
-
return setNativeValue(el,
|
|
199
|
+
return setNativeValue(el, args['value']);
|
|
196
200
|
}
|
|
201
|
+
assertNotRichText(el, 'fill');
|
|
197
202
|
throw new Error(`cannot fill a <${el.tagName.toLowerCase()}>`);
|
|
198
203
|
case ActionType.TYPE:
|
|
199
|
-
if (el
|
|
204
|
+
if (isInput(el) || isTextArea(el)) {
|
|
205
|
+
// Same family as the valueless FILL: a missing `text` appended '' and reported ok:true, so an
|
|
206
|
+
// agent believed it had typed into a field nothing was written to.
|
|
207
|
+
if (typeof args['text'] !== 'string') {
|
|
208
|
+
throw new Error("type requires a string `text` — pass it nested, as args: { text: '…' }.");
|
|
209
|
+
}
|
|
210
|
+
assertEditable(el, 'type');
|
|
200
211
|
el.focus();
|
|
201
|
-
return setNativeValue(el, el.value +
|
|
212
|
+
return setNativeValue(el, el.value + args['text']);
|
|
202
213
|
}
|
|
214
|
+
assertNotRichText(el, 'type into');
|
|
203
215
|
throw new Error(`cannot type into a <${el.tagName.toLowerCase()}>`);
|
|
204
216
|
case ActionType.CLEAR:
|
|
205
|
-
if (el
|
|
217
|
+
if (isInput(el) || isTextArea(el)) {
|
|
206
218
|
return setNativeValue(el, '');
|
|
207
219
|
}
|
|
208
220
|
// Consistent with TYPE/SELECT/CHECK: clearing a non-field is not a silent success. Throwing
|
|
209
221
|
// surfaces the mismatch instead of reporting ok:true for an action that did nothing.
|
|
210
222
|
throw new Error(`cannot clear a <${el.tagName.toLowerCase()}>`);
|
|
211
223
|
case ActionType.SELECT:
|
|
212
|
-
if (el
|
|
213
|
-
|
|
224
|
+
if (isSelect(el)) {
|
|
225
|
+
// A MISSING value assigned '' to the <select>. No option carries that, so the browser sets
|
|
226
|
+
// selectedIndex to -1 — deselecting everything — from a call that was simply malformed.
|
|
227
|
+
// (Selecting a value that no option carries is a different case and is deliberately NOT
|
|
228
|
+
// refused: `actions.effect.test.ts` pins it as a detectable no-op, where the reported
|
|
229
|
+
// valueChanged delta is what tells the agent the option never took.)
|
|
230
|
+
if (typeof args['value'] !== 'string') {
|
|
231
|
+
throw new Error("select requires a string `value` — pass it nested, as args: { value: '…' }.");
|
|
232
|
+
}
|
|
233
|
+
el.value = args['value'];
|
|
214
234
|
el.dispatchEvent(new Event('change', { bubbles: true }));
|
|
215
235
|
return false; // change is not cancelable.
|
|
216
236
|
}
|
|
217
237
|
throw new Error(`cannot select on a <${el.tagName.toLowerCase()}>`);
|
|
218
238
|
case ActionType.CHECK:
|
|
219
239
|
case ActionType.UNCHECK:
|
|
220
|
-
if (el
|
|
240
|
+
if (isInput(el)) {
|
|
221
241
|
el.checked = action === ActionType.CHECK;
|
|
222
242
|
el.dispatchEvent(new Event('change', { bubbles: true }));
|
|
223
243
|
return false;
|
|
224
244
|
}
|
|
225
245
|
throw new Error(`cannot (un)check a <${el.tagName.toLowerCase()}>`);
|
|
226
246
|
case ActionType.SUBMIT: {
|
|
227
|
-
const form = el
|
|
247
|
+
const form = isForm(el) ? el : el.closest('form');
|
|
228
248
|
if (form === null)
|
|
229
249
|
throw new Error('no form to submit');
|
|
230
250
|
form.requestSubmit();
|
|
@@ -240,7 +260,7 @@ async function dispatchFor(el, action, args) {
|
|
|
240
260
|
el.scrollIntoView();
|
|
241
261
|
return false;
|
|
242
262
|
case ActionType.UPLOAD: {
|
|
243
|
-
if (!(el
|
|
263
|
+
if (!isInput(el) || el.type !== 'file') {
|
|
244
264
|
throw new Error('upload target must be a <input type="file">');
|
|
245
265
|
}
|
|
246
266
|
const file = new File([asString(args['content'], 'reticle test file')], asString(args['name'], 'file.txt'), {
|
|
@@ -258,7 +278,7 @@ async function dispatchFor(el, action, args) {
|
|
|
258
278
|
// asString falls back to '' (never undefined), so the old `!== undefined` was always true and
|
|
259
279
|
// handed '' to refs.resolve. A drag with no target ref is a free drag — resolve nothing.
|
|
260
280
|
const resolved = toRef !== '' ? refs.resolve(toRef) : null;
|
|
261
|
-
return await dragElement(el, resolved
|
|
281
|
+
return await dragElement(el, isHtmlElement(resolved) ? resolved : null, args['data']);
|
|
262
282
|
}
|
|
263
283
|
default:
|
|
264
284
|
throw new Error(`unknown action '${action}'`);
|
|
@@ -363,4 +383,3 @@ export async function executeSequence(steps) {
|
|
|
363
383
|
}
|
|
364
384
|
return { ok: true, count: steps.length, effects, steps: stepResults };
|
|
365
385
|
}
|
|
366
|
-
//# sourceMappingURL=actions.js.map
|
package/dist/actions/scroll.d.ts
CHANGED
package/dist/actions/scroll.js
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Writing a value into a field, and the two preconditions that make it honest.
|
|
3
|
+
*
|
|
4
|
+
* Lifted out of actions.ts when that file hit the 600-line cap. It is a cohesive unit: every export
|
|
5
|
+
* here exists so that a value write either lands as a real user's edit would, or is refused with a
|
|
6
|
+
* reason — never forced through while reporting success.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Set a value on a controlled input the way React expects (native setter + input event).
|
|
10
|
+
* Returns the `input` event's dispatchEvent result (defaultPrevented of the primary event).
|
|
11
|
+
*/
|
|
12
|
+
export declare function setNativeValue(el: HTMLInputElement | HTMLTextAreaElement, value: string): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Refuse to write to a field a person could not edit.
|
|
15
|
+
*
|
|
16
|
+
* `readonly` and `disabled` block USER input, not scripted assignment, so the prototype value setter
|
|
17
|
+
* writes straight through both. Measured: filling a readonly input reported `ok:true` and
|
|
18
|
+
* `valueChanged:true` with nothing in the effect block marking it read-only. That leaves the app in a
|
|
19
|
+
* state no user could reach, and every conclusion drawn from what follows is about software nobody
|
|
20
|
+
* can operate — the same reason the click path reports `occluded`, and the same choice Playwright
|
|
21
|
+
* makes when it refuses to fill a non-editable element.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* A rich-text target is UNSUPPORTED, not a mistake by the caller.
|
|
25
|
+
*
|
|
26
|
+
* Every rich-text editor (TipTap, Quill, ProseMirror, Slate, Lexical) is `[contenteditable]`, and
|
|
27
|
+
* these actions handle only input/textarea. `cannot fill a <div>` reads as "you picked the wrong
|
|
28
|
+
* element" and sends the reader hunting for a better selector that does not exist. Support is not
|
|
29
|
+
* faked: assigning textContent would update the DOM while the editor's own model kept the old value,
|
|
30
|
+
* so the tool would report success for content the app will never submit.
|
|
31
|
+
*/
|
|
32
|
+
export declare function assertNotRichText(el: HTMLElement, action: string): void;
|
|
33
|
+
export declare function assertEditable(el: HTMLInputElement | HTMLTextAreaElement, action: string): void;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { captureValueSetter } from '../patching/capture-method.js';
|
|
2
|
+
import { valuePrototypeOf } from '../dom/realm.js';
|
|
3
|
+
/**
|
|
4
|
+
* Writing a value into a field, and the two preconditions that make it honest.
|
|
5
|
+
*
|
|
6
|
+
* Lifted out of actions.ts when that file hit the 600-line cap. It is a cohesive unit: every export
|
|
7
|
+
* here exists so that a value write either lands as a real user's edit would, or is refused with a
|
|
8
|
+
* reason — never forced through while reporting success.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Set a value on a controlled input the way React expects (native setter + input event).
|
|
12
|
+
* Returns the `input` event's dispatchEvent result (defaultPrevented of the primary event).
|
|
13
|
+
*/
|
|
14
|
+
export function setNativeValue(el, value) {
|
|
15
|
+
// Realm-aware: a controlled input inside a same-origin frame has its own prototype.
|
|
16
|
+
const proto = valuePrototypeOf(el);
|
|
17
|
+
const setter = proto === undefined ? undefined : captureValueSetter(proto);
|
|
18
|
+
if (setter !== undefined) {
|
|
19
|
+
setter.call(el, value);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
el.value = value;
|
|
23
|
+
}
|
|
24
|
+
const notPrevented = el.dispatchEvent(new Event('input', { bubbles: true, cancelable: true }));
|
|
25
|
+
el.dispatchEvent(new Event('change', { bubbles: true }));
|
|
26
|
+
return !notPrevented;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Refuse to write to a field a person could not edit.
|
|
30
|
+
*
|
|
31
|
+
* `readonly` and `disabled` block USER input, not scripted assignment, so the prototype value setter
|
|
32
|
+
* writes straight through both. Measured: filling a readonly input reported `ok:true` and
|
|
33
|
+
* `valueChanged:true` with nothing in the effect block marking it read-only. That leaves the app in a
|
|
34
|
+
* state no user could reach, and every conclusion drawn from what follows is about software nobody
|
|
35
|
+
* can operate — the same reason the click path reports `occluded`, and the same choice Playwright
|
|
36
|
+
* makes when it refuses to fill a non-editable element.
|
|
37
|
+
*/
|
|
38
|
+
/**
|
|
39
|
+
* A rich-text target is UNSUPPORTED, not a mistake by the caller.
|
|
40
|
+
*
|
|
41
|
+
* Every rich-text editor (TipTap, Quill, ProseMirror, Slate, Lexical) is `[contenteditable]`, and
|
|
42
|
+
* these actions handle only input/textarea. `cannot fill a <div>` reads as "you picked the wrong
|
|
43
|
+
* element" and sends the reader hunting for a better selector that does not exist. Support is not
|
|
44
|
+
* faked: assigning textContent would update the DOM while the editor's own model kept the old value,
|
|
45
|
+
* so the tool would report success for content the app will never submit.
|
|
46
|
+
*/
|
|
47
|
+
export function assertNotRichText(el, action) {
|
|
48
|
+
// The ATTRIBUTE, not `isContentEditable`: jsdom does not implement the property, so a test would
|
|
49
|
+
// pass against a guard that never fires in the environment the unit suite runs in.
|
|
50
|
+
const flag = el.getAttribute('contenteditable');
|
|
51
|
+
if (el.isContentEditable || (flag !== null && flag !== 'false')) {
|
|
52
|
+
throw new Error(`cannot ${action} a contenteditable element — rich-text editors keep their own document model, ` +
|
|
53
|
+
'so writing to the DOM here would look right and submit the old content. This surface is not supported yet.');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export function assertEditable(el, action) {
|
|
57
|
+
if (el.disabled) {
|
|
58
|
+
throw new Error(`cannot ${action} a disabled <${el.tagName.toLowerCase()}> — a user could not edit it, so forcing the value would put the app in a state nobody can reach`);
|
|
59
|
+
}
|
|
60
|
+
if (el.readOnly) {
|
|
61
|
+
throw new Error(`cannot ${action} a readonly <${el.tagName.toLowerCase()}> — a user could not edit it, so forcing the value would put the app in a state nobody can reach`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -4,4 +4,3 @@ export declare const RELOAD_CACHE_BUST_PARAM = "_reticle_reload";
|
|
|
4
4
|
export declare function resolveNavigationUrl(rawUrl: string, baseUrl: string): string | null;
|
|
5
5
|
/** Map browser command names to handlers. Used by the transport on each COMMAND. */
|
|
6
6
|
export declare function createCommandRegistry(): Map<string, CommandHandler>;
|
|
7
|
-
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -3,10 +3,13 @@ import { buildSnapshot } from '../dom/snapshot.js';
|
|
|
3
3
|
import { matchQuery, runQuery } from '../dom/query.js';
|
|
4
4
|
import { executeAction, executeSequence, dispatchWebMcp, } from '../actions/actions.js';
|
|
5
5
|
import { describe } from '../dom/a11y.js';
|
|
6
|
+
import { sourceFor, formatSource } from '../dom/source.js';
|
|
6
7
|
import { themeReport } from '../dom/theme.js';
|
|
7
8
|
import { refs } from '../dom/refs.js';
|
|
9
|
+
import { isButton, isInput } from '../dom/realm.js';
|
|
8
10
|
import { hitTestOccluder } from '../dom/occlusion.js';
|
|
9
11
|
import { readStorage } from '../observers/storage.js';
|
|
12
|
+
import { captureDesktopWindow } from '../dom/desktop-capture.js';
|
|
10
13
|
import { identifyComponent, readComponentState } from '../registry/adapters.js';
|
|
11
14
|
import { readStoresWithTruncation, readStoresRaw, storeNames } from '../registry/stores.js';
|
|
12
15
|
import { sanitizeWithReport } from '../security/serialization.js';
|
|
@@ -24,6 +27,14 @@ function num(value) {
|
|
|
24
27
|
function record(value) {
|
|
25
28
|
return typeof value === 'object' && value !== null ? value : {};
|
|
26
29
|
}
|
|
30
|
+
function sourceLocation(value) {
|
|
31
|
+
if (typeof value !== 'object' || value === null)
|
|
32
|
+
return undefined;
|
|
33
|
+
const obj = value;
|
|
34
|
+
if (typeof obj['file'] !== 'string' || typeof obj['line'] !== 'number')
|
|
35
|
+
return undefined;
|
|
36
|
+
return { file: obj['file'], line: obj['line'], column: num(obj['column']) };
|
|
37
|
+
}
|
|
27
38
|
function queryFromArgs(args) {
|
|
28
39
|
return {
|
|
29
40
|
by: str(args['by']),
|
|
@@ -35,10 +46,12 @@ function queryFromArgs(args) {
|
|
|
35
46
|
placeholder: str(args['placeholder']),
|
|
36
47
|
testid: str(args['testid']),
|
|
37
48
|
alt: str(args['alt']),
|
|
49
|
+
component: str(args['component']),
|
|
38
50
|
scope: str(args['scope']),
|
|
39
51
|
attrs: Array.isArray(args['attrs'])
|
|
40
52
|
? args['attrs'].filter((a) => typeof a === 'string')
|
|
41
53
|
: undefined,
|
|
54
|
+
source: sourceLocation(args['source']),
|
|
42
55
|
};
|
|
43
56
|
}
|
|
44
57
|
function inspect(ref) {
|
|
@@ -62,16 +75,19 @@ function inspect(ref) {
|
|
|
62
75
|
visibility: cs.visibility,
|
|
63
76
|
}
|
|
64
77
|
: null;
|
|
78
|
+
// `describe()` carries the CHEAP source (the nearest babel-stamped ancestor), because it runs per
|
|
79
|
+
// element on paths that describe hundreds at once. inspect is a single-element path, so it takes
|
|
80
|
+
// the adapter's answer first — the component that actually RENDERED this element, not the nearest
|
|
81
|
+
// stamped host. `act` already did this; inspect did not, so the two tools disagreed about the same
|
|
82
|
+
// ref and inspect — the tool you reach for to ask where something lives — was the one saying null.
|
|
83
|
+
const source = formatSource(sourceFor(el, component?.source));
|
|
65
84
|
return {
|
|
66
85
|
...describe(el),
|
|
86
|
+
...(source !== undefined ? { source } : {}),
|
|
67
87
|
tag: el.tagName.toLowerCase(),
|
|
68
88
|
href: el.getAttribute('href') ?? undefined,
|
|
69
|
-
formAction: el
|
|
70
|
-
|
|
71
|
-
: undefined,
|
|
72
|
-
formText: el instanceof HTMLButtonElement || el instanceof HTMLInputElement
|
|
73
|
-
? (el.form?.textContent ?? undefined)
|
|
74
|
-
: undefined,
|
|
89
|
+
formAction: isButton(el) || isInput(el) ? (el.form?.getAttribute('action') ?? undefined) : undefined,
|
|
90
|
+
formText: isButton(el) || isInput(el) ? (el.form?.textContent ?? undefined) : undefined,
|
|
75
91
|
box: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },
|
|
76
92
|
// True when another element sits over this one's center point — the click would hit the overlay,
|
|
77
93
|
// not this control (a z-index/overlay bug the DOM tree cannot show).
|
|
@@ -124,6 +140,10 @@ function readState(ref, store, path, depth) {
|
|
|
124
140
|
// what keeps "the list is short" distinguishable from "I shortened the list".
|
|
125
141
|
...(projected.truncation === undefined ? {} : { truncation: projected.truncation }),
|
|
126
142
|
...('availableKeys' in selection ? { availableKeys: selection.availableKeys } : {}),
|
|
143
|
+
// How many keys there REALLY were, when the near-miss list is a sample. Without it, 50 names
|
|
144
|
+
// and no marker reads as "the key you asked for does not exist" — the strongest negative
|
|
145
|
+
// signal there is, and a false one when the key is simply number 51.
|
|
146
|
+
...('totalKeys' in selection ? { totalKeys: selection.totalKeys } : {}),
|
|
127
147
|
storeNames: names,
|
|
128
148
|
};
|
|
129
149
|
}
|
|
@@ -213,6 +233,7 @@ export function createCommandRegistry() {
|
|
|
213
233
|
reg.set(ReticleCommand.STATE_READ, (args) => readState(str(args['ref']), str(args['store']), str(args['path']), num(args['depth'])));
|
|
214
234
|
reg.set(ReticleCommand.STORAGE_READ, (args) => readStorage(str(args['area'])));
|
|
215
235
|
reg.set(ReticleCommand.CAPABILITIES, () => getCapabilities());
|
|
236
|
+
reg.set(ReticleCommand.CAPTURE, (args) => captureDesktopWindow(args['fullPage'] === true));
|
|
216
237
|
reg.set(ReticleCommand.SCROLL, (args) => {
|
|
217
238
|
const dy = args['dy'];
|
|
218
239
|
const fraction = args['fraction'];
|
|
@@ -242,4 +263,3 @@ export function createCommandRegistry() {
|
|
|
242
263
|
});
|
|
243
264
|
return reg;
|
|
244
265
|
}
|
|
245
|
-
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { RedactionConfig } from '@reticlehq/core';
|
|
2
|
+
/**
|
|
3
|
+
* What `reticle.connect()` accepts.
|
|
4
|
+
*
|
|
5
|
+
* Split out of reticle.ts when that file crossed the 600-line cap — the same move `session-info.ts`
|
|
6
|
+
* made for the server's Session. A pure description of the SDK's public entry contract has no reason
|
|
7
|
+
* to live inside the class that happens to consume it, and separating them keeps the surface every
|
|
8
|
+
* integrating app actually reads reviewable on its own.
|
|
9
|
+
*/
|
|
10
|
+
export interface ReticleConnectOptions {
|
|
11
|
+
/** WS endpoint of the local bridge. Defaults to ws://localhost:<port><path>. */
|
|
12
|
+
url?: string;
|
|
13
|
+
/** Human-friendly session label so the agent can target the right tab. */
|
|
14
|
+
session?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Stable project identity, normally stamped by the build plugin (e.g. "acme-web-9f3c1d"). Lets the
|
|
17
|
+
* agent scope to the right app even when its dev server boots on an unexpected port. Optional.
|
|
18
|
+
*/
|
|
19
|
+
projectId?: string;
|
|
20
|
+
/** Browser/bridge pairing token. Required when either endpoint is non-localhost. */
|
|
21
|
+
token?: string;
|
|
22
|
+
/** Explicitly allow Reticle on a non-localhost page or bridge. Requires token. */
|
|
23
|
+
allowNonLocalhost?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Escape hatch for the production backstop. Reticle is dev-only and refuses to connect when the
|
|
26
|
+
* build reports NODE_ENV=production (an SSR healthcheck or a prod bundle opened locally would
|
|
27
|
+
* otherwise activate). The real fix is to gate the import behind `import.meta.env.DEV` so it's
|
|
28
|
+
* tree-shaken out; this flag only exists for the rare intentional prod diagnostic.
|
|
29
|
+
*/
|
|
30
|
+
allowInProduction?: boolean;
|
|
31
|
+
/** Show a small in-page status chip (connection + event count). */
|
|
32
|
+
overlay?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Capture request/response bodies on net.request events (dev-only; text-like content only,
|
|
35
|
+
* sensitive keys redacted, per-body capped). Off by default — bodies cost tokens and can carry PII.
|
|
36
|
+
*/
|
|
37
|
+
captureNetworkBodies?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* The project root, so source paths report repo-relative instead of absolute.
|
|
40
|
+
*
|
|
41
|
+
* React's `_debugSource.fileName` is absolute; the babel stamp is repo-relative. Build plugins that
|
|
42
|
+
* can `define` a global set it themselves; frameworks that cannot (Next passes it through env,
|
|
43
|
+
* Astro through its own config) hand it here instead. Taking it as a connect OPTION is what keeps
|
|
44
|
+
* the generated app-side code plain JavaScript — the previous shape made the caller assign a global,
|
|
45
|
+
* and the TypeScript cast that needed shipped into a `.jsx` file and broke the build.
|
|
46
|
+
*/
|
|
47
|
+
root?: string;
|
|
48
|
+
/** Presenter mode: glow border, animated cursor, click/hover effects, narration HUD. */
|
|
49
|
+
present?: boolean;
|
|
50
|
+
/** Per-action pacing (ms) in presenter mode so a human can follow. Default 450. */
|
|
51
|
+
pace?: number;
|
|
52
|
+
/** Min ms each narration line stays visible before the next replaces it (presenter). Default 3000. */
|
|
53
|
+
narrationDwellMs?: number;
|
|
54
|
+
/**
|
|
55
|
+
* Border behavior in presenter mode: 'session' (default) persists the border for the whole
|
|
56
|
+
* session; 'busy' restores the fade-after-idle behavior.
|
|
57
|
+
*/
|
|
58
|
+
border?: 'session' | 'busy';
|
|
59
|
+
/** Max accumulated activity-log rows before the oldest are pruned (presenter). Default 50. */
|
|
60
|
+
logMax?: number;
|
|
61
|
+
/**
|
|
62
|
+
* Mount the floating human-recorder toolbar (Record/Stop/Annotate).
|
|
63
|
+
* Default off — purely additive, dev-only.
|
|
64
|
+
*/
|
|
65
|
+
recorder?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Mount the "Flag a bug" annotator: the human clicks an element that looks wrong, types what's
|
|
68
|
+
* wrong, and Reticle emits a HUMAN_MARK the agent drains via reticle_review. Defaults to ON with the
|
|
69
|
+
* presenter (it's the human's side of the look→act→assert loop); pass `annotate: false` to suppress.
|
|
70
|
+
*/
|
|
71
|
+
annotate?: boolean;
|
|
72
|
+
/** Live-control: overridable ended-border fade delay (native timer). Default 4000. */
|
|
73
|
+
endedFadeMs?: number;
|
|
74
|
+
/** Session auto-end after this much agent idle (presenter). Default 5min; agent-tunable via reticle_session. */
|
|
75
|
+
idleEndMs?: number;
|
|
76
|
+
/**
|
|
77
|
+
* Extend the redaction rules with your app's own vocabulary.
|
|
78
|
+
*
|
|
79
|
+
* ```ts
|
|
80
|
+
* reticle.connect({
|
|
81
|
+
* redact: {
|
|
82
|
+
* keys: ['deviceSecretRef', /^partner[-_]?code$/i], // also redact these
|
|
83
|
+
* allow: ['designToken'], // stop redacting this false positive
|
|
84
|
+
* },
|
|
85
|
+
* });
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* Additive only — there is no way to replace the built-in rule, because a config that could would
|
|
89
|
+
* eventually ship an app that leaks. `keys` strings match a key name exactly (case-insensitively);
|
|
90
|
+
* a RegExp is tested against it. `allow` exempts a key from the DEFAULT rule and loses to `keys`.
|
|
91
|
+
*
|
|
92
|
+
* Literal `keys` strings also cross the bridge, so the daemon redacts them on the driven path,
|
|
93
|
+
* where request bodies are captured raw from the network stack and never pass through this SDK.
|
|
94
|
+
* RegExp entries and `allow` do NOT cross — see docs/usage.md ("Extending the redaction rules") for why, and what that means.
|
|
95
|
+
*/
|
|
96
|
+
redact?: RedactionConfig;
|
|
97
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/dom/a11y.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ElementState, type ElementDescriptor } from '@reticlehq/core';
|
|
2
2
|
/** Compute the ARIA role (explicit wins, else implicit from the tag). */
|
|
3
3
|
export declare function getRole(el: Element): string;
|
|
4
|
-
/** Accessible name via a practical subset of the accname algorithm. */
|
|
5
4
|
export declare function getAccessibleName(el: Element): string;
|
|
6
5
|
/**
|
|
7
6
|
* The set of states relevant to assertions. `visible` is an O(depth) forced-style walk; callers that
|
|
@@ -28,4 +27,3 @@ export declare function isVisible(el: Element, memo?: Map<Element, boolean>): bo
|
|
|
28
27
|
/** Build the compact descriptor surfaced to the agent. `memo` (optional) shares the per-call
|
|
29
28
|
* visibility cache with the query's state filter so ancestors aren't re-walked per element. */
|
|
30
29
|
export declare function describe(el: Element, memo?: Map<Element, boolean>): ElementDescriptor;
|
|
31
|
-
//# sourceMappingURL=a11y.d.ts.map
|