@reticlehq/browser 2.0.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.
Files changed (191) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +17 -0
  3. package/dist/actions/actions-dom.d.ts +29 -0
  4. package/dist/actions/actions-dom.d.ts.map +1 -0
  5. package/dist/actions/actions-dom.js +153 -0
  6. package/dist/actions/actions-dom.js.map +1 -0
  7. package/dist/actions/actions.d.ts +92 -0
  8. package/dist/actions/actions.d.ts.map +1 -0
  9. package/dist/actions/actions.js +348 -0
  10. package/dist/actions/actions.js.map +1 -0
  11. package/dist/actions/scroll.d.ts +19 -0
  12. package/dist/actions/scroll.d.ts.map +1 -0
  13. package/dist/actions/scroll.js +44 -0
  14. package/dist/actions/scroll.js.map +1 -0
  15. package/dist/commands/commands.d.ts +5 -0
  16. package/dist/commands/commands.d.ts.map +1 -0
  17. package/dist/commands/commands.js +246 -0
  18. package/dist/commands/commands.js.map +1 -0
  19. package/dist/dom/a11y.d.ts +20 -0
  20. package/dist/dom/a11y.d.ts.map +1 -0
  21. package/dist/dom/a11y.js +263 -0
  22. package/dist/dom/a11y.js.map +1 -0
  23. package/dist/dom/auto-anchor.d.ts +66 -0
  24. package/dist/dom/auto-anchor.d.ts.map +1 -0
  25. package/dist/dom/auto-anchor.js +75 -0
  26. package/dist/dom/auto-anchor.js.map +1 -0
  27. package/dist/dom/dom-ignore.d.ts +7 -0
  28. package/dist/dom/dom-ignore.d.ts.map +1 -0
  29. package/dist/dom/dom-ignore.js +21 -0
  30. package/dist/dom/dom-ignore.js.map +1 -0
  31. package/dist/dom/query.d.ts +6 -0
  32. package/dist/dom/query.d.ts.map +1 -0
  33. package/dist/dom/query.js +236 -0
  34. package/dist/dom/query.js.map +1 -0
  35. package/dist/dom/refs.d.ts +15 -0
  36. package/dist/dom/refs.d.ts.map +1 -0
  37. package/dist/dom/refs.js +36 -0
  38. package/dist/dom/refs.js.map +1 -0
  39. package/dist/dom/snapshot.d.ts +22 -0
  40. package/dist/dom/snapshot.d.ts.map +1 -0
  41. package/dist/dom/snapshot.js +171 -0
  42. package/dist/dom/snapshot.js.map +1 -0
  43. package/dist/dom/theme.d.ts +26 -0
  44. package/dist/dom/theme.d.ts.map +1 -0
  45. package/dist/dom/theme.js +90 -0
  46. package/dist/dom/theme.js.map +1 -0
  47. package/dist/index.d.ts +25 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +32 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/observers/animation.d.ts +4 -0
  52. package/dist/observers/animation.d.ts.map +1 -0
  53. package/dist/observers/animation.js +35 -0
  54. package/dist/observers/animation.js.map +1 -0
  55. package/dist/observers/console.d.ts +4 -0
  56. package/dist/observers/console.d.ts.map +1 -0
  57. package/dist/observers/console.js +58 -0
  58. package/dist/observers/console.js.map +1 -0
  59. package/dist/observers/dom.d.ts +4 -0
  60. package/dist/observers/dom.d.ts.map +1 -0
  61. package/dist/observers/dom.js +96 -0
  62. package/dist/observers/dom.js.map +1 -0
  63. package/dist/observers/health.d.ts +8 -0
  64. package/dist/observers/health.d.ts.map +1 -0
  65. package/dist/observers/health.js +33 -0
  66. package/dist/observers/health.js.map +1 -0
  67. package/dist/observers/network.d.ts +11 -0
  68. package/dist/observers/network.d.ts.map +1 -0
  69. package/dist/observers/network.js +128 -0
  70. package/dist/observers/network.js.map +1 -0
  71. package/dist/observers/route.d.ts +4 -0
  72. package/dist/observers/route.d.ts.map +1 -0
  73. package/dist/observers/route.js +56 -0
  74. package/dist/observers/route.js.map +1 -0
  75. package/dist/observers/scroll.d.ts +4 -0
  76. package/dist/observers/scroll.d.ts.map +1 -0
  77. package/dist/observers/scroll.js +42 -0
  78. package/dist/observers/scroll.js.map +1 -0
  79. package/dist/observers/types.d.ts +6 -0
  80. package/dist/observers/types.d.ts.map +1 -0
  81. package/dist/observers/types.js +2 -0
  82. package/dist/observers/types.js.map +1 -0
  83. package/dist/presenter/overlay.d.ts +12 -0
  84. package/dist/presenter/overlay.d.ts.map +1 -0
  85. package/dist/presenter/overlay.js +31 -0
  86. package/dist/presenter/overlay.js.map +1 -0
  87. package/dist/presenter/presenter-config.d.ts +86 -0
  88. package/dist/presenter/presenter-config.d.ts.map +1 -0
  89. package/dist/presenter/presenter-config.js +51 -0
  90. package/dist/presenter/presenter-config.js.map +1 -0
  91. package/dist/presenter/presenter-controls.d.ts +74 -0
  92. package/dist/presenter/presenter-controls.d.ts.map +1 -0
  93. package/dist/presenter/presenter-controls.js +360 -0
  94. package/dist/presenter/presenter-controls.js.map +1 -0
  95. package/dist/presenter/presenter-effects.d.ts +14 -0
  96. package/dist/presenter/presenter-effects.d.ts.map +1 -0
  97. package/dist/presenter/presenter-effects.js +40 -0
  98. package/dist/presenter/presenter-effects.js.map +1 -0
  99. package/dist/presenter/presenter-glow.d.ts +43 -0
  100. package/dist/presenter/presenter-glow.d.ts.map +1 -0
  101. package/dist/presenter/presenter-glow.js +126 -0
  102. package/dist/presenter/presenter-glow.js.map +1 -0
  103. package/dist/presenter/presenter-log.d.ts +43 -0
  104. package/dist/presenter/presenter-log.d.ts.map +1 -0
  105. package/dist/presenter/presenter-log.js +118 -0
  106. package/dist/presenter/presenter-log.js.map +1 -0
  107. package/dist/presenter/presenter-run-state.d.ts +48 -0
  108. package/dist/presenter/presenter-run-state.d.ts.map +1 -0
  109. package/dist/presenter/presenter-run-state.js +37 -0
  110. package/dist/presenter/presenter-run-state.js.map +1 -0
  111. package/dist/presenter/presenter-styles.d.ts +7 -0
  112. package/dist/presenter/presenter-styles.d.ts.map +1 -0
  113. package/dist/presenter/presenter-styles.js +118 -0
  114. package/dist/presenter/presenter-styles.js.map +1 -0
  115. package/dist/presenter/presenter-tally.d.ts +20 -0
  116. package/dist/presenter/presenter-tally.d.ts.map +1 -0
  117. package/dist/presenter/presenter-tally.js +38 -0
  118. package/dist/presenter/presenter-tally.js.map +1 -0
  119. package/dist/presenter/presenter-verbs.d.ts +2 -0
  120. package/dist/presenter/presenter-verbs.d.ts.map +1 -0
  121. package/dist/presenter/presenter-verbs.js +29 -0
  122. package/dist/presenter/presenter-verbs.js.map +1 -0
  123. package/dist/presenter/presenter.d.ts +89 -0
  124. package/dist/presenter/presenter.d.ts.map +1 -0
  125. package/dist/presenter/presenter.js +428 -0
  126. package/dist/presenter/presenter.js.map +1 -0
  127. package/dist/recorder/recorder-styles.d.ts +12 -0
  128. package/dist/recorder/recorder-styles.d.ts.map +1 -0
  129. package/dist/recorder/recorder-styles.js +45 -0
  130. package/dist/recorder/recorder-styles.js.map +1 -0
  131. package/dist/recorder/recorder.d.ts +60 -0
  132. package/dist/recorder/recorder.d.ts.map +1 -0
  133. package/dist/recorder/recorder.js +436 -0
  134. package/dist/recorder/recorder.js.map +1 -0
  135. package/dist/registry/adapters.d.ts +31 -0
  136. package/dist/registry/adapters.d.ts.map +1 -0
  137. package/dist/registry/adapters.js +47 -0
  138. package/dist/registry/adapters.js.map +1 -0
  139. package/dist/registry/capabilities.d.ts +25 -0
  140. package/dist/registry/capabilities.d.ts.map +1 -0
  141. package/dist/registry/capabilities.js +48 -0
  142. package/dist/registry/capabilities.js.map +1 -0
  143. package/dist/registry/commit-and-signal.d.ts +9 -0
  144. package/dist/registry/commit-and-signal.d.ts.map +1 -0
  145. package/dist/registry/commit-and-signal.js +12 -0
  146. package/dist/registry/commit-and-signal.js.map +1 -0
  147. package/dist/registry/domains.d.ts +15 -0
  148. package/dist/registry/domains.d.ts.map +1 -0
  149. package/dist/registry/domains.js +19 -0
  150. package/dist/registry/domains.js.map +1 -0
  151. package/dist/registry/emitter.d.ts +28 -0
  152. package/dist/registry/emitter.d.ts.map +1 -0
  153. package/dist/registry/emitter.js +27 -0
  154. package/dist/registry/emitter.js.map +1 -0
  155. package/dist/registry/stores.d.ts +9 -0
  156. package/dist/registry/stores.d.ts.map +1 -0
  157. package/dist/registry/stores.js +30 -0
  158. package/dist/registry/stores.js.map +1 -0
  159. package/dist/reticle-presenter-helpers.d.ts +19 -0
  160. package/dist/reticle-presenter-helpers.d.ts.map +1 -0
  161. package/dist/reticle-presenter-helpers.js +81 -0
  162. package/dist/reticle-presenter-helpers.js.map +1 -0
  163. package/dist/reticle.d.ts +113 -0
  164. package/dist/reticle.d.ts.map +1 -0
  165. package/dist/reticle.js +379 -0
  166. package/dist/reticle.js.map +1 -0
  167. package/dist/review/annotator.d.ts +36 -0
  168. package/dist/review/annotator.d.ts.map +1 -0
  169. package/dist/review/annotator.js +321 -0
  170. package/dist/review/annotator.js.map +1 -0
  171. package/dist/review/mark-anchor.d.ts +23 -0
  172. package/dist/review/mark-anchor.d.ts.map +1 -0
  173. package/dist/review/mark-anchor.js +74 -0
  174. package/dist/review/mark-anchor.js.map +1 -0
  175. package/dist/security/serialization.d.ts +6 -0
  176. package/dist/security/serialization.d.ts.map +1 -0
  177. package/dist/security/serialization.js +103 -0
  178. package/dist/security/serialization.js.map +1 -0
  179. package/dist/timers/clock.d.ts +6 -0
  180. package/dist/timers/clock.d.ts.map +1 -0
  181. package/dist/timers/clock.js +80 -0
  182. package/dist/timers/clock.js.map +1 -0
  183. package/dist/timers/native-timers.d.ts +37 -0
  184. package/dist/timers/native-timers.d.ts.map +1 -0
  185. package/dist/timers/native-timers.js +79 -0
  186. package/dist/timers/native-timers.js.map +1 -0
  187. package/dist/transport/transport.d.ts +54 -0
  188. package/dist/transport/transport.d.ts.map +1 -0
  189. package/dist/transport/transport.js +182 -0
  190. package/dist/transport/transport.js.map +1 -0
  191. package/package.json +52 -0
@@ -0,0 +1,348 @@
1
+ import { ActionType, ActionWarning, DANGEROUS_ACTION_CONFIRM_ARG, ElementState, isDangerousActionText, SettleReason, } from '@reticlehq/core';
2
+ import { refs } from '../dom/refs.js';
3
+ import { getAccessibleName, isVisible, getStates } from '../dom/a11y.js';
4
+ import { elementHasHoverHandlers, identifyComponent } from '../registry/adapters.js';
5
+ import { nativeSetTimeout, settle } from '../timers/native-timers.js';
6
+ /**
7
+ * Set a value on a controlled input the way React expects (native setter + input event).
8
+ * Returns the `input` event's dispatchEvent result (defaultPrevented of the primary event).
9
+ */
10
+ function setNativeValue(el, value) {
11
+ const proto = el instanceof HTMLTextAreaElement ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype;
12
+ // eslint-disable-next-line @typescript-eslint/unbound-method -- setter is invoked via .call(el)
13
+ const setter = Object.getOwnPropertyDescriptor(proto, 'value')?.set;
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
+ function asString(value, fallback = '') {
25
+ return typeof value === 'string' ? value : fallback;
26
+ }
27
+ function requireElement(ref) {
28
+ const el = refs.resolve(ref);
29
+ if (el === null)
30
+ throw new Error(`ref '${ref}' no longer resolves to an element`);
31
+ if (!(el instanceof HTMLElement))
32
+ throw new Error(`ref '${ref}' is not an HTMLElement`);
33
+ return el;
34
+ }
35
+ /**
36
+ * Capture an element's anchor BEFORE the action runs. Critical: a navigating/destructive action can
37
+ * unmount the target (login submit, a close button), after which it has no readable attribute — so
38
+ * reading the anchor post-settle would silently degrade the recorded step. We read it up front while
39
+ * the element is still mounted.
40
+ */
41
+ function anchorOf(el) {
42
+ const testid = el.getAttribute('data-testid') ?? undefined;
43
+ if (testid !== undefined)
44
+ return { testid };
45
+ const info = identifyComponent(el);
46
+ const out = {};
47
+ const component = info?.componentStack[0];
48
+ if (component !== undefined)
49
+ out.component = component;
50
+ if (info?.source !== undefined)
51
+ out.source = info.source;
52
+ return out;
53
+ }
54
+ const result = (ref, action, effect, settled, settleReason, anchor, warning) => {
55
+ const base = {
56
+ ok: true,
57
+ ref,
58
+ action,
59
+ dispatched: true,
60
+ settled,
61
+ settleReason,
62
+ effect,
63
+ };
64
+ if (anchor.testid !== undefined) {
65
+ base.testid = anchor.testid;
66
+ }
67
+ else {
68
+ // No testid — carry the auto-anchor so the recorded step stays stable, not degraded.
69
+ if (anchor.component !== undefined)
70
+ base.component = anchor.component;
71
+ if (anchor.source !== undefined)
72
+ base.source = anchor.source;
73
+ }
74
+ if (warning !== undefined)
75
+ base.warning = warning;
76
+ return base;
77
+ };
78
+ const FILL_LIKE = new Set([ActionType.FILL, ActionType.TYPE, ActionType.CLEAR]);
79
+ const isFillLike = (action) => FILL_LIKE.has(action);
80
+ /** Actions that resolve to a point and so benefit from off-viewport scroll + occlusion hit-test. */
81
+ const CLICK_LIKE = new Set([ActionType.CLICK, ActionType.DBLCLICK]);
82
+ function dangerousActionContext(el) {
83
+ const form = el.closest('form');
84
+ return [
85
+ getAccessibleName(el),
86
+ el.textContent ?? '',
87
+ el.getAttribute('value') ?? '',
88
+ el.getAttribute('title') ?? '',
89
+ el.getAttribute('aria-label') ?? '',
90
+ el.getAttribute('href') ?? '',
91
+ form?.getAttribute('action') ?? '',
92
+ form?.textContent ?? '',
93
+ ].join(' ');
94
+ }
95
+ function requiresDangerousConfirmation(text) {
96
+ return isDangerousActionText(text);
97
+ }
98
+ function assertActionAllowed(el, action, args) {
99
+ const canTrigger = action === ActionType.CLICK ||
100
+ action === ActionType.DBLCLICK ||
101
+ action === ActionType.DRAG ||
102
+ action === ActionType.SUBMIT ||
103
+ (action === ActionType.PRESS && asString(args['key'], 'Enter') === 'Enter');
104
+ const dragTarget = action === ActionType.DRAG ? refs.resolve(asString(args['toRef'])) : null;
105
+ const context = dragTarget instanceof HTMLElement
106
+ ? `${dangerousActionContext(el)} ${dangerousActionContext(dragTarget)}`
107
+ : dangerousActionContext(el);
108
+ if (canTrigger &&
109
+ requiresDangerousConfirmation(context) &&
110
+ args[DANGEROUS_ACTION_CONFIRM_ARG] !== true) {
111
+ throw new Error(`potentially destructive action blocked; retry with args.${DANGEROUS_ACTION_CONFIRM_ARG}=true`);
112
+ }
113
+ }
114
+ /** Best-effort click-point geometry. All-false default when there is nothing measurable to test. */
115
+ import { NO_GEOMETRY, fireClickSequence, clickGeometry, firePointer, firePointerNonBubbling, dragElement, } from './actions-dom.js';
116
+ /** Derive `enabled` from the shared a11y state logic (disabled prop + aria-disabled). */
117
+ function enabledOf(el) {
118
+ return !getStates(el).includes(ElementState.DISABLED);
119
+ }
120
+ /** Current value for inputs/textareas/selects, else undefined. */
121
+ function valueOf(el) {
122
+ if (el instanceof HTMLInputElement ||
123
+ el instanceof HTMLTextAreaElement ||
124
+ el instanceof HTMLSelectElement) {
125
+ return el.value;
126
+ }
127
+ return undefined;
128
+ }
129
+ /** Ref of the currently-focused element, treating body/null as "no focus". */
130
+ function activeRef(el) {
131
+ const active = el.ownerDocument.activeElement;
132
+ if (active === null || active === el.ownerDocument.body)
133
+ return null;
134
+ return refs.refFor(active);
135
+ }
136
+ /**
137
+ * Dispatch the action's events. Returns `defaultPrevented` of the primary cancelable event
138
+ * (false for actions whose primary event is non-cancelable or unobservable). Drag/hover-hold
139
+ * await internally; the probe wrapper builds the result once they resolve.
140
+ */
141
+ async function dispatchFor(el, action, args) {
142
+ switch (action) {
143
+ case ActionType.CLICK:
144
+ // Full pointer/mouse sequence (not a bare click) so pointer- and focus-gated handlers fire
145
+ // the way they do for a real user. Returns the click event's defaultPrevented.
146
+ return fireClickSequence(el);
147
+ case ActionType.DBLCLICK:
148
+ return !el.dispatchEvent(new MouseEvent('dblclick', { bubbles: true, cancelable: true }));
149
+ case ActionType.HOVER: {
150
+ const doc = el.ownerDocument;
151
+ // Best-effort "previous" node for relatedTarget so React's enter/leave synthesis has a "from".
152
+ const from = doc.activeElement ?? doc.body;
153
+ // Bubbling over/move with relatedTarget so React's delegated root can synthesize enter/leave.
154
+ firePointer(el, 'pointerover', from);
155
+ el.dispatchEvent(new MouseEvent('mouseover', { bubbles: true, relatedTarget: from }));
156
+ // Non-bubbling enter pair (per spec) for direct enter/onMouseEnter listeners.
157
+ firePointerNonBubbling(el, 'pointerenter', from);
158
+ el.dispatchEvent(new MouseEvent('mouseenter', { relatedTarget: from }));
159
+ firePointer(el, 'pointermove', from);
160
+ const moved = el.dispatchEvent(new MouseEvent('mousemove', { bubbles: true, cancelable: true }));
161
+ // hover-dwell: keep "hovering" for holdMs so timer-gated reveals can mount.
162
+ const holdMs = typeof args['holdMs'] === 'number' ? args['holdMs'] : 0;
163
+ if (holdMs > 0)
164
+ await sleep(holdMs);
165
+ return !moved;
166
+ }
167
+ case ActionType.FOCUS:
168
+ el.focus();
169
+ el.dispatchEvent(new FocusEvent('focusin', { bubbles: true }));
170
+ return false; // FocusEvents are not cancelable.
171
+ case ActionType.BLUR:
172
+ // Fire a bubbling focusout so React 19's delegated root listener runs onBlur
173
+ // (commit-on-blur). el.blur() alone only works if the element was truly focused.
174
+ el.blur();
175
+ el.dispatchEvent(new FocusEvent('blur'));
176
+ el.dispatchEvent(new FocusEvent('focusout', { bubbles: true }));
177
+ return false;
178
+ case ActionType.FILL:
179
+ if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
180
+ el.focus(); // focus first so a later blur commits (onBlur editors)
181
+ return setNativeValue(el, asString(args['value']));
182
+ }
183
+ throw new Error(`cannot fill a <${el.tagName.toLowerCase()}>`);
184
+ case ActionType.TYPE:
185
+ if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
186
+ el.focus();
187
+ return setNativeValue(el, el.value + asString(args['text']));
188
+ }
189
+ throw new Error(`cannot type into a <${el.tagName.toLowerCase()}>`);
190
+ case ActionType.CLEAR:
191
+ if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
192
+ return setNativeValue(el, '');
193
+ }
194
+ return false;
195
+ case ActionType.SELECT:
196
+ if (el instanceof HTMLSelectElement) {
197
+ el.value = asString(args['value']);
198
+ el.dispatchEvent(new Event('change', { bubbles: true }));
199
+ return false; // change is not cancelable.
200
+ }
201
+ throw new Error(`cannot select on a <${el.tagName.toLowerCase()}>`);
202
+ case ActionType.CHECK:
203
+ case ActionType.UNCHECK:
204
+ if (el instanceof HTMLInputElement) {
205
+ el.checked = action === ActionType.CHECK;
206
+ el.dispatchEvent(new Event('change', { bubbles: true }));
207
+ return false;
208
+ }
209
+ throw new Error(`cannot (un)check a <${el.tagName.toLowerCase()}>`);
210
+ case ActionType.SUBMIT: {
211
+ const form = el instanceof HTMLFormElement ? el : el.closest('form');
212
+ if (form === null)
213
+ throw new Error('no form to submit');
214
+ form.requestSubmit();
215
+ return false; // requestSubmit() returns void; the internal submit event is unobservable.
216
+ }
217
+ case ActionType.PRESS: {
218
+ const key = asString(args['key'], 'Enter');
219
+ const down = el.dispatchEvent(new KeyboardEvent('keydown', { key, bubbles: true, cancelable: true }));
220
+ el.dispatchEvent(new KeyboardEvent('keyup', { key, bubbles: true }));
221
+ return !down;
222
+ }
223
+ case ActionType.SCROLL_INTO_VIEW:
224
+ el.scrollIntoView();
225
+ return false;
226
+ case ActionType.UPLOAD: {
227
+ if (!(el instanceof HTMLInputElement) || el.type !== 'file') {
228
+ throw new Error('upload target must be a <input type="file">');
229
+ }
230
+ const file = new File([asString(args['content'], 'reticle test file')], asString(args['name'], 'file.txt'), {
231
+ type: asString(args['type'], 'text/plain'),
232
+ });
233
+ const dt = new DataTransfer();
234
+ dt.items.add(file);
235
+ el.files = dt.files;
236
+ const inputOk = el.dispatchEvent(new Event('input', { bubbles: true, cancelable: true }));
237
+ el.dispatchEvent(new Event('change', { bubbles: true }));
238
+ return !inputOk;
239
+ }
240
+ case ActionType.DRAG: {
241
+ const toRef = asString(args['toRef']);
242
+ const resolved = toRef !== undefined ? refs.resolve(toRef) : null;
243
+ return await dragElement(el, resolved instanceof HTMLElement ? resolved : null, args['data']);
244
+ }
245
+ default:
246
+ throw new Error(`unknown action '${action}'`);
247
+ }
248
+ }
249
+ /**
250
+ * Execute a single action against a ref and probe for best-effort evidence of effect.
251
+ * Always async: the MutationObserver read needs a microtask + rAF after dispatch.
252
+ */
253
+ export async function executeAction(ref, action, args = {}) {
254
+ const el = requireElement(ref);
255
+ assertActionAllowed(el, action, args);
256
+ // Capture the anchor while the element is still mounted — the action may unmount it (navigation).
257
+ const anchor = anchorOf(el);
258
+ const visible = isVisible(el);
259
+ const enabled = enabledOf(el);
260
+ const prevFocus = activeRef(el);
261
+ const valueBefore = valueOf(el);
262
+ // Click-like: scroll an off-viewport target in + hit-test the click point BEFORE installing the
263
+ // mutation observer (scroll/hit-test never mutate the DOM, but keep the probe window clean).
264
+ const geometry = CLICK_LIKE.has(action) ? clickGeometry(el) : NO_GEOMETRY;
265
+ let mutated = 0;
266
+ const obs = new MutationObserver((records) => {
267
+ mutated += records.length;
268
+ });
269
+ obs.observe(el.ownerDocument.documentElement, {
270
+ subtree: true,
271
+ childList: true,
272
+ attributes: true,
273
+ characterData: true,
274
+ });
275
+ let defaultPrevented = false;
276
+ let settled = false;
277
+ let settleReason = null;
278
+ try {
279
+ defaultPrevented = await dispatchFor(el, action, args);
280
+ }
281
+ finally {
282
+ // bounded settle — microtask + one BOUNDED frame so React's commit (and the resulting DOM
283
+ // mutations → dom.added/dom.text/dom.attr events) flush before we return, landing inside
284
+ // observe({ since }). Bounded so a throttled/background tab never hangs; a settle timeout NEVER
285
+ // rejects (only a real dispatch failure thrown above does). settle() can never throw.
286
+ const outcome = await settle();
287
+ settled = outcome.settled;
288
+ settleReason = outcome.settled ? null : SettleReason.TIMEOUT;
289
+ obs.disconnect();
290
+ }
291
+ const valueAfter = valueOf(el);
292
+ const nextFocus = activeRef(el);
293
+ const effect = {
294
+ dispatched: true,
295
+ targetMatched: el.isConnected,
296
+ visible,
297
+ enabled,
298
+ defaultPrevented,
299
+ focusMoved: prevFocus !== nextFocus ? `${prevFocus ?? 'null'}->${nextFocus ?? 'null'}` : null,
300
+ valueChanged: isFillLike(action) ? valueBefore !== valueAfter : false,
301
+ domMutatedWithin: mutated,
302
+ occluded: geometry.occluded,
303
+ occludedBy: geometry.occludedBy,
304
+ scrolledIntoView: geometry.scrolledIntoView,
305
+ };
306
+ // Honesty caveats: a visually-occluded click is reported even though synthetic dispatch landed;
307
+ // else synthetic hover may not fire framework enter/leave handlers (no native hit-test).
308
+ const warning = geometry.occluded
309
+ ? ActionWarning.CLICK_OCCLUDED
310
+ : action === ActionType.HOVER && elementHasHoverHandlers(el)
311
+ ? ActionWarning.HOVER_NATIVE_ENTER_LEAVE
312
+ : undefined;
313
+ return result(ref, action, effect, settled, settleReason, anchor, warning);
314
+ }
315
+ const sleep = (ms) => new Promise((r) => nativeSetTimeout(r, ms));
316
+ /** Best-effort WebMCP passthrough: call a navigator.modelContext tool if the site exposes one. */
317
+ export async function dispatchWebMcp(tool, params, confirmDangerous = false) {
318
+ if (requiresDangerousConfirmation(tool) && !confirmDangerous) {
319
+ throw new Error(`potentially destructive WebMCP tool blocked; retry with ${DANGEROUS_ACTION_CONFIRM_ARG}=true`);
320
+ }
321
+ const mc = navigator.modelContext;
322
+ if (mc === undefined || typeof mc.callTool !== 'function') {
323
+ throw new Error('WebMCP (navigator.modelContext) not available on this page');
324
+ }
325
+ return await mc.callTool(tool, params);
326
+ }
327
+ export async function executeSequence(steps) {
328
+ const effects = [];
329
+ const stepResults = [];
330
+ for (const step of steps) {
331
+ const res = await executeAction(step.ref, step.action, step.args ?? {});
332
+ effects.push(res.effect);
333
+ const stepBase = {
334
+ ref: res.ref,
335
+ action: res.action,
336
+ dispatched: res.dispatched,
337
+ settled: res.settled,
338
+ settleReason: res.settleReason,
339
+ };
340
+ if (res.testid !== undefined)
341
+ stepBase.testid = res.testid;
342
+ if (res.warning !== undefined)
343
+ stepBase.warning = res.warning;
344
+ stepResults.push(stepBase);
345
+ }
346
+ return { ok: true, count: steps.length, effects, steps: stepResults };
347
+ }
348
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/actions/actions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /** Outcome of one container scroll — enough for the server to drive a find loop. */
2
+ interface ScrollResult {
3
+ /** scrollTop actually moved (false ⇒ already at the end / not scrollable). */
4
+ scrolled: boolean;
5
+ scrollTop: number;
6
+ scrollHeight: number;
7
+ clientHeight: number;
8
+ /** At (or within 1px of) the bottom — no more rows to reveal by scrolling down. */
9
+ atEnd: boolean;
10
+ }
11
+ /**
12
+ * Scroll the container of `ref` (or the document) down by `dy` (default ~one viewport) so a
13
+ * virtualized list mounts its next window of rows. If `fraction` (0–1) is supplied, jumps
14
+ * directly to that fraction of scrollHeight instead of stepping — enables bisection for large
15
+ * lists where a specific row index is known (targetIndex / totalCount = fraction).
16
+ */
17
+ export declare function scrollContainer(ref: string | undefined, dy: number | undefined, fraction?: number): ScrollResult;
18
+ export {};
19
+ //# sourceMappingURL=scroll.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll.d.ts","sourceRoot":"","sources":["../../src/actions/scroll.ts"],"names":[],"mappings":"AAEA,oFAAoF;AACpF,UAAU,YAAY;IACpB,8EAA8E;IAC9E,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,KAAK,EAAE,OAAO,CAAC;CAChB;AAgBD;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,EAAE,EAAE,MAAM,GAAG,SAAS,EACtB,QAAQ,CAAC,EAAE,MAAM,GAChB,YAAY,CAwBd"}
@@ -0,0 +1,44 @@
1
+ import { refs } from '../dom/refs.js';
2
+ const FALLBACK_STEP_PX = 400;
3
+ const VIEWPORT_FRACTION = 0.8;
4
+ /** The nearest scrollable ancestor of `el` (inclusive), else the document scrolling element. */
5
+ function nearestScrollable(el) {
6
+ let cur = el;
7
+ while (cur !== null && cur !== document.body) {
8
+ const oy = getComputedStyle(cur).overflowY;
9
+ if ((oy === 'auto' || oy === 'scroll') && cur.scrollHeight > cur.clientHeight)
10
+ return cur;
11
+ cur = cur.parentElement;
12
+ }
13
+ return document.scrollingElement ?? document.documentElement;
14
+ }
15
+ /**
16
+ * Scroll the container of `ref` (or the document) down by `dy` (default ~one viewport) so a
17
+ * virtualized list mounts its next window of rows. If `fraction` (0–1) is supplied, jumps
18
+ * directly to that fraction of scrollHeight instead of stepping — enables bisection for large
19
+ * lists where a specific row index is known (targetIndex / totalCount = fraction).
20
+ */
21
+ export function scrollContainer(ref, dy, fraction) {
22
+ const base = ref !== undefined ? refs.resolve(ref) : null;
23
+ const target = base instanceof Element
24
+ ? nearestScrollable(base)
25
+ : (document.scrollingElement ?? document.documentElement);
26
+ const before = target.scrollTop;
27
+ if (fraction !== undefined && fraction >= 0 && fraction <= 1) {
28
+ target.scrollTop = Math.round(target.scrollHeight * fraction);
29
+ }
30
+ else {
31
+ const step = dy ?? (Math.round(target.clientHeight * VIEWPORT_FRACTION) || FALLBACK_STEP_PX);
32
+ target.scrollTop = before + step;
33
+ }
34
+ target.dispatchEvent(new Event('scroll', { bubbles: false }));
35
+ const after = target.scrollTop;
36
+ return {
37
+ scrolled: after !== before,
38
+ scrollTop: after,
39
+ scrollHeight: target.scrollHeight,
40
+ clientHeight: target.clientHeight,
41
+ atEnd: after + target.clientHeight >= target.scrollHeight - 1,
42
+ };
43
+ }
44
+ //# sourceMappingURL=scroll.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll.js","sourceRoot":"","sources":["../../src/actions/scroll.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAatC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAC7B,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B,gGAAgG;AAChG,SAAS,iBAAiB,CAAC,EAAW;IACpC,IAAI,GAAG,GAAmB,EAAE,CAAC;IAC7B,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC7C,MAAM,EAAE,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC;QAC3C,IAAI,CAAC,EAAE,KAAK,MAAM,IAAI,EAAE,KAAK,QAAQ,CAAC,IAAI,GAAG,CAAC,YAAY,GAAG,GAAG,CAAC,YAAY;YAAE,OAAO,GAAG,CAAC;QAC1F,GAAG,GAAG,GAAG,CAAC,aAAa,CAAC;IAC1B,CAAC;IACD,OAAO,QAAQ,CAAC,gBAAgB,IAAI,QAAQ,CAAC,eAAe,CAAC;AAC/D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAC7B,GAAuB,EACvB,EAAsB,EACtB,QAAiB;IAEjB,MAAM,IAAI,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1D,MAAM,MAAM,GACV,IAAI,YAAY,OAAO;QACrB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC;QACzB,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,IAAI,QAAQ,CAAC,eAAe,CAAC,CAAC;IAE9D,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;IAChC,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,IAAI,CAAC,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;QAC7D,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,GAAG,QAAQ,CAAC,CAAC;IAChE,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,GAAG,iBAAiB,CAAC,IAAI,gBAAgB,CAAC,CAAC;QAC7F,MAAM,CAAC,SAAS,GAAG,MAAM,GAAG,IAAI,CAAC;IACnC,CAAC;IACD,MAAM,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC;IAE/B,OAAO;QACL,QAAQ,EAAE,KAAK,KAAK,MAAM;QAC1B,SAAS,EAAE,KAAK;QAChB,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,YAAY,GAAG,CAAC;KAC9D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export type CommandHandler = (args: Record<string, unknown>) => unknown;
2
+ export declare function resolveNavigationUrl(rawUrl: string, baseUrl: string): string | null;
3
+ /** Map browser command names to handlers. Used by the transport on each COMMAND. */
4
+ export declare function createCommandRegistry(): Map<string, CommandHandler>;
5
+ //# sourceMappingURL=commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/commands/commands.ts"],"names":[],"mappings":"AA+BA,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;AAsLxE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQnF;AAED,oFAAoF;AACpF,wBAAgB,qBAAqB,IAAI,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CA2EnE"}