@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.
- package/LICENSE +202 -0
- package/README.md +17 -0
- package/dist/actions/actions-dom.d.ts +29 -0
- package/dist/actions/actions-dom.d.ts.map +1 -0
- package/dist/actions/actions-dom.js +153 -0
- package/dist/actions/actions-dom.js.map +1 -0
- package/dist/actions/actions.d.ts +92 -0
- package/dist/actions/actions.d.ts.map +1 -0
- package/dist/actions/actions.js +348 -0
- package/dist/actions/actions.js.map +1 -0
- package/dist/actions/scroll.d.ts +19 -0
- package/dist/actions/scroll.d.ts.map +1 -0
- package/dist/actions/scroll.js +44 -0
- package/dist/actions/scroll.js.map +1 -0
- package/dist/commands/commands.d.ts +5 -0
- package/dist/commands/commands.d.ts.map +1 -0
- package/dist/commands/commands.js +246 -0
- package/dist/commands/commands.js.map +1 -0
- package/dist/dom/a11y.d.ts +20 -0
- package/dist/dom/a11y.d.ts.map +1 -0
- package/dist/dom/a11y.js +263 -0
- package/dist/dom/a11y.js.map +1 -0
- package/dist/dom/auto-anchor.d.ts +66 -0
- package/dist/dom/auto-anchor.d.ts.map +1 -0
- package/dist/dom/auto-anchor.js +75 -0
- package/dist/dom/auto-anchor.js.map +1 -0
- package/dist/dom/dom-ignore.d.ts +7 -0
- package/dist/dom/dom-ignore.d.ts.map +1 -0
- package/dist/dom/dom-ignore.js +21 -0
- package/dist/dom/dom-ignore.js.map +1 -0
- package/dist/dom/query.d.ts +6 -0
- package/dist/dom/query.d.ts.map +1 -0
- package/dist/dom/query.js +236 -0
- package/dist/dom/query.js.map +1 -0
- package/dist/dom/refs.d.ts +15 -0
- package/dist/dom/refs.d.ts.map +1 -0
- package/dist/dom/refs.js +36 -0
- package/dist/dom/refs.js.map +1 -0
- package/dist/dom/snapshot.d.ts +22 -0
- package/dist/dom/snapshot.d.ts.map +1 -0
- package/dist/dom/snapshot.js +171 -0
- package/dist/dom/snapshot.js.map +1 -0
- package/dist/dom/theme.d.ts +26 -0
- package/dist/dom/theme.d.ts.map +1 -0
- package/dist/dom/theme.js +90 -0
- package/dist/dom/theme.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/observers/animation.d.ts +4 -0
- package/dist/observers/animation.d.ts.map +1 -0
- package/dist/observers/animation.js +35 -0
- package/dist/observers/animation.js.map +1 -0
- package/dist/observers/console.d.ts +4 -0
- package/dist/observers/console.d.ts.map +1 -0
- package/dist/observers/console.js +58 -0
- package/dist/observers/console.js.map +1 -0
- package/dist/observers/dom.d.ts +4 -0
- package/dist/observers/dom.d.ts.map +1 -0
- package/dist/observers/dom.js +96 -0
- package/dist/observers/dom.js.map +1 -0
- package/dist/observers/health.d.ts +8 -0
- package/dist/observers/health.d.ts.map +1 -0
- package/dist/observers/health.js +33 -0
- package/dist/observers/health.js.map +1 -0
- package/dist/observers/network.d.ts +11 -0
- package/dist/observers/network.d.ts.map +1 -0
- package/dist/observers/network.js +128 -0
- package/dist/observers/network.js.map +1 -0
- package/dist/observers/route.d.ts +4 -0
- package/dist/observers/route.d.ts.map +1 -0
- package/dist/observers/route.js +56 -0
- package/dist/observers/route.js.map +1 -0
- package/dist/observers/scroll.d.ts +4 -0
- package/dist/observers/scroll.d.ts.map +1 -0
- package/dist/observers/scroll.js +42 -0
- package/dist/observers/scroll.js.map +1 -0
- package/dist/observers/types.d.ts +6 -0
- package/dist/observers/types.d.ts.map +1 -0
- package/dist/observers/types.js +2 -0
- package/dist/observers/types.js.map +1 -0
- package/dist/presenter/overlay.d.ts +12 -0
- package/dist/presenter/overlay.d.ts.map +1 -0
- package/dist/presenter/overlay.js +31 -0
- package/dist/presenter/overlay.js.map +1 -0
- package/dist/presenter/presenter-config.d.ts +86 -0
- package/dist/presenter/presenter-config.d.ts.map +1 -0
- package/dist/presenter/presenter-config.js +51 -0
- package/dist/presenter/presenter-config.js.map +1 -0
- package/dist/presenter/presenter-controls.d.ts +74 -0
- package/dist/presenter/presenter-controls.d.ts.map +1 -0
- package/dist/presenter/presenter-controls.js +360 -0
- package/dist/presenter/presenter-controls.js.map +1 -0
- package/dist/presenter/presenter-effects.d.ts +14 -0
- package/dist/presenter/presenter-effects.d.ts.map +1 -0
- package/dist/presenter/presenter-effects.js +40 -0
- package/dist/presenter/presenter-effects.js.map +1 -0
- package/dist/presenter/presenter-glow.d.ts +43 -0
- package/dist/presenter/presenter-glow.d.ts.map +1 -0
- package/dist/presenter/presenter-glow.js +126 -0
- package/dist/presenter/presenter-glow.js.map +1 -0
- package/dist/presenter/presenter-log.d.ts +43 -0
- package/dist/presenter/presenter-log.d.ts.map +1 -0
- package/dist/presenter/presenter-log.js +118 -0
- package/dist/presenter/presenter-log.js.map +1 -0
- package/dist/presenter/presenter-run-state.d.ts +48 -0
- package/dist/presenter/presenter-run-state.d.ts.map +1 -0
- package/dist/presenter/presenter-run-state.js +37 -0
- package/dist/presenter/presenter-run-state.js.map +1 -0
- package/dist/presenter/presenter-styles.d.ts +7 -0
- package/dist/presenter/presenter-styles.d.ts.map +1 -0
- package/dist/presenter/presenter-styles.js +118 -0
- package/dist/presenter/presenter-styles.js.map +1 -0
- package/dist/presenter/presenter-tally.d.ts +20 -0
- package/dist/presenter/presenter-tally.d.ts.map +1 -0
- package/dist/presenter/presenter-tally.js +38 -0
- package/dist/presenter/presenter-tally.js.map +1 -0
- package/dist/presenter/presenter-verbs.d.ts +2 -0
- package/dist/presenter/presenter-verbs.d.ts.map +1 -0
- package/dist/presenter/presenter-verbs.js +29 -0
- package/dist/presenter/presenter-verbs.js.map +1 -0
- package/dist/presenter/presenter.d.ts +89 -0
- package/dist/presenter/presenter.d.ts.map +1 -0
- package/dist/presenter/presenter.js +428 -0
- package/dist/presenter/presenter.js.map +1 -0
- package/dist/recorder/recorder-styles.d.ts +12 -0
- package/dist/recorder/recorder-styles.d.ts.map +1 -0
- package/dist/recorder/recorder-styles.js +45 -0
- package/dist/recorder/recorder-styles.js.map +1 -0
- package/dist/recorder/recorder.d.ts +60 -0
- package/dist/recorder/recorder.d.ts.map +1 -0
- package/dist/recorder/recorder.js +436 -0
- package/dist/recorder/recorder.js.map +1 -0
- package/dist/registry/adapters.d.ts +31 -0
- package/dist/registry/adapters.d.ts.map +1 -0
- package/dist/registry/adapters.js +47 -0
- package/dist/registry/adapters.js.map +1 -0
- package/dist/registry/capabilities.d.ts +25 -0
- package/dist/registry/capabilities.d.ts.map +1 -0
- package/dist/registry/capabilities.js +48 -0
- package/dist/registry/capabilities.js.map +1 -0
- package/dist/registry/commit-and-signal.d.ts +9 -0
- package/dist/registry/commit-and-signal.d.ts.map +1 -0
- package/dist/registry/commit-and-signal.js +12 -0
- package/dist/registry/commit-and-signal.js.map +1 -0
- package/dist/registry/domains.d.ts +15 -0
- package/dist/registry/domains.d.ts.map +1 -0
- package/dist/registry/domains.js +19 -0
- package/dist/registry/domains.js.map +1 -0
- package/dist/registry/emitter.d.ts +28 -0
- package/dist/registry/emitter.d.ts.map +1 -0
- package/dist/registry/emitter.js +27 -0
- package/dist/registry/emitter.js.map +1 -0
- package/dist/registry/stores.d.ts +9 -0
- package/dist/registry/stores.d.ts.map +1 -0
- package/dist/registry/stores.js +30 -0
- package/dist/registry/stores.js.map +1 -0
- package/dist/reticle-presenter-helpers.d.ts +19 -0
- package/dist/reticle-presenter-helpers.d.ts.map +1 -0
- package/dist/reticle-presenter-helpers.js +81 -0
- package/dist/reticle-presenter-helpers.js.map +1 -0
- package/dist/reticle.d.ts +113 -0
- package/dist/reticle.d.ts.map +1 -0
- package/dist/reticle.js +379 -0
- package/dist/reticle.js.map +1 -0
- package/dist/review/annotator.d.ts +36 -0
- package/dist/review/annotator.d.ts.map +1 -0
- package/dist/review/annotator.js +321 -0
- package/dist/review/annotator.js.map +1 -0
- package/dist/review/mark-anchor.d.ts +23 -0
- package/dist/review/mark-anchor.d.ts.map +1 -0
- package/dist/review/mark-anchor.js +74 -0
- package/dist/review/mark-anchor.js.map +1 -0
- package/dist/security/serialization.d.ts +6 -0
- package/dist/security/serialization.d.ts.map +1 -0
- package/dist/security/serialization.js +103 -0
- package/dist/security/serialization.js.map +1 -0
- package/dist/timers/clock.d.ts +6 -0
- package/dist/timers/clock.d.ts.map +1 -0
- package/dist/timers/clock.js +80 -0
- package/dist/timers/clock.js.map +1 -0
- package/dist/timers/native-timers.d.ts +37 -0
- package/dist/timers/native-timers.d.ts.map +1 -0
- package/dist/timers/native-timers.js +79 -0
- package/dist/timers/native-timers.js.map +1 -0
- package/dist/transport/transport.d.ts +54 -0
- package/dist/transport/transport.d.ts.map +1 -0
- package/dist/transport/transport.js +182 -0
- package/dist/transport/transport.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { ActionType, ComponentStateReason, DANGEROUS_ACTION_CONFIRM_ARG, ElementQuerySchema, ReticleCommand, SnapshotMode, TRANSPORT_LIMITS, selectPath, capDepth, } from '@reticlehq/core';
|
|
2
|
+
import { buildSnapshot } from '../dom/snapshot.js';
|
|
3
|
+
import { matchQuery, runQuery } from '../dom/query.js';
|
|
4
|
+
import { executeAction, executeSequence, dispatchWebMcp, } from '../actions/actions.js';
|
|
5
|
+
import { describe } from '../dom/a11y.js';
|
|
6
|
+
import { themeReport } from '../dom/theme.js';
|
|
7
|
+
import { refs } from '../dom/refs.js';
|
|
8
|
+
import { identifyComponent, readComponentState } from '../registry/adapters.js';
|
|
9
|
+
import { readStores, storeNames } from '../registry/stores.js';
|
|
10
|
+
import { getCapabilities } from '../registry/capabilities.js';
|
|
11
|
+
import { freezeClock, advanceClock, resetClock, isClockFrozen } from '../timers/clock.js';
|
|
12
|
+
import { scrollContainer } from '../actions/scroll.js';
|
|
13
|
+
/** Query param appended on a hard reload to bypass the browser cache. */
|
|
14
|
+
const RELOAD_CACHE_BUST_PARAM = '_reticle_reload';
|
|
15
|
+
function str(value) {
|
|
16
|
+
return typeof value === 'string' ? value : undefined;
|
|
17
|
+
}
|
|
18
|
+
function num(value) {
|
|
19
|
+
return typeof value === 'number' ? value : undefined;
|
|
20
|
+
}
|
|
21
|
+
function record(value) {
|
|
22
|
+
return typeof value === 'object' && value !== null ? value : {};
|
|
23
|
+
}
|
|
24
|
+
function queryFromArgs(args) {
|
|
25
|
+
return {
|
|
26
|
+
by: str(args['by']),
|
|
27
|
+
value: str(args['value']),
|
|
28
|
+
role: str(args['role']),
|
|
29
|
+
name: str(args['name']),
|
|
30
|
+
text: str(args['text']),
|
|
31
|
+
label: str(args['label']),
|
|
32
|
+
placeholder: str(args['placeholder']),
|
|
33
|
+
testid: str(args['testid']),
|
|
34
|
+
alt: str(args['alt']),
|
|
35
|
+
scope: str(args['scope']),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function inspect(ref) {
|
|
39
|
+
const el = refs.resolve(ref);
|
|
40
|
+
if (el === null)
|
|
41
|
+
return { error: `ref '${ref}' no longer resolves` };
|
|
42
|
+
const rect = el.getBoundingClientRect();
|
|
43
|
+
const component = identifyComponent(el);
|
|
44
|
+
const view = el.ownerDocument.defaultView;
|
|
45
|
+
const cs = view !== null ? view.getComputedStyle(el) : null;
|
|
46
|
+
// Computed style the a11y tree is blind to — `cursor` (does it look interactive?), display/
|
|
47
|
+
// visibility, and color/opacity — so a UI bug that leaves the element "present but unusable"
|
|
48
|
+
// (dead cursor, invisible, recolored) is observable in one inspect call.
|
|
49
|
+
const styles = cs !== null
|
|
50
|
+
? {
|
|
51
|
+
color: cs.color,
|
|
52
|
+
backgroundColor: cs.backgroundColor,
|
|
53
|
+
opacity: cs.opacity,
|
|
54
|
+
cursor: cs.cursor,
|
|
55
|
+
display: cs.display,
|
|
56
|
+
visibility: cs.visibility,
|
|
57
|
+
}
|
|
58
|
+
: null;
|
|
59
|
+
return {
|
|
60
|
+
...describe(el),
|
|
61
|
+
tag: el.tagName.toLowerCase(),
|
|
62
|
+
href: el.getAttribute('href') ?? undefined,
|
|
63
|
+
formAction: el instanceof HTMLButtonElement || el instanceof HTMLInputElement
|
|
64
|
+
? (el.form?.getAttribute('action') ?? undefined)
|
|
65
|
+
: undefined,
|
|
66
|
+
formText: el instanceof HTMLButtonElement || el instanceof HTMLInputElement
|
|
67
|
+
? (el.form?.textContent ?? undefined)
|
|
68
|
+
: undefined,
|
|
69
|
+
box: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },
|
|
70
|
+
// True when another element sits over this one's center point — the click would hit the overlay,
|
|
71
|
+
// not this control (a z-index/overlay bug the DOM tree cannot show).
|
|
72
|
+
occluded: isOccluded(el, rect),
|
|
73
|
+
styles,
|
|
74
|
+
// Theme compliance vs the app's design tokens (off-theme colors a DOM tool can't judge).
|
|
75
|
+
theme: cs !== null ? themeReport(cs) : null,
|
|
76
|
+
component,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** True if the node (or an ancestor) is part of Reticle's own injected UI (HUD, glow, cursor, flag
|
|
80
|
+
* button, …). Reticle's overlay must never count as occluding the app — a control sitting under the
|
|
81
|
+
* HUD is a false "occluded" reading, since the HUD is not part of the app the user actually sees. */
|
|
82
|
+
function isReticleUi(node) {
|
|
83
|
+
for (let n = node; n !== null; n = n.parentElement) {
|
|
84
|
+
for (const attr of Array.from(n.attributes)) {
|
|
85
|
+
if (attr.name.startsWith('data-reticle'))
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
/** Whether a NON-Reticle element covers this one's center point (a transparent overlay / z-index bug). */
|
|
92
|
+
function isOccluded(el, rect) {
|
|
93
|
+
if (rect.width === 0 || rect.height === 0)
|
|
94
|
+
return false; // a 0×0 box is a different bug (size)
|
|
95
|
+
const doc = el.ownerDocument;
|
|
96
|
+
if (typeof doc.elementFromPoint !== 'function')
|
|
97
|
+
return false;
|
|
98
|
+
const top = doc.elementFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
|
|
99
|
+
// Reticle's own HUD sits at a high z-index and must never read as occluding the app.
|
|
100
|
+
if (top === null || isReticleUi(top))
|
|
101
|
+
return false;
|
|
102
|
+
return top !== el && !el.contains(top);
|
|
103
|
+
}
|
|
104
|
+
/** Narrowing guard: an adapter returned a ComponentStateResult (has a boolean `ok`). */
|
|
105
|
+
function isComponentStateResult(value) {
|
|
106
|
+
return (typeof value === 'object' && value !== null && 'ok' in value && typeof value.ok === 'boolean');
|
|
107
|
+
}
|
|
108
|
+
const COMPONENT_UNAVAILABLE = {
|
|
109
|
+
ok: false,
|
|
110
|
+
reason: ComponentStateReason.UNAVAILABLE,
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Stores are the reliable path. The `ref` component read is bounded: a stale ref, no
|
|
114
|
+
* adapter, or an adapter returning a non-conforming value all collapse to a structured
|
|
115
|
+
* `{ ok: false, reason }` — never a raw (possibly circular) object that could hang serialization.
|
|
116
|
+
*
|
|
117
|
+
* `path`/`depth` are applied HERE, in the page, BEFORE the value crosses the transport — so a scoped
|
|
118
|
+
* read of a huge store (e.g. `deployments.0.status` on a 500-row store) returns only the small
|
|
119
|
+
* sub-tree and is never truncated. (Previously selection ran server-side, AFTER the whole store had
|
|
120
|
+
* already been size-capped in transit, which silently lost any field after a large array.)
|
|
121
|
+
*/
|
|
122
|
+
function readState(ref, store, path, depth) {
|
|
123
|
+
const stores = readStores(store);
|
|
124
|
+
const names = storeNames();
|
|
125
|
+
// Scoped read: walk `path` into the named store (or the whole {stores} when no store is given) and
|
|
126
|
+
// cap depth — entirely in-page, so only the result crosses the wire.
|
|
127
|
+
if (path !== undefined || depth !== undefined) {
|
|
128
|
+
const base = store !== undefined ? stores[store] : { stores, storeNames: names };
|
|
129
|
+
const selection = path !== undefined ? selectPath(base, path) : { found: true, value: base };
|
|
130
|
+
const value = selection.found && depth !== undefined ? capDepth(selection.value, depth) : selection.value;
|
|
131
|
+
return {
|
|
132
|
+
store,
|
|
133
|
+
path,
|
|
134
|
+
found: selection.found,
|
|
135
|
+
value,
|
|
136
|
+
...('availableKeys' in selection ? { availableKeys: selection.availableKeys } : {}),
|
|
137
|
+
storeNames: names,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const result = {
|
|
141
|
+
stores,
|
|
142
|
+
storeNames: names,
|
|
143
|
+
};
|
|
144
|
+
if (ref !== undefined && ref.length > 0) {
|
|
145
|
+
const el = refs.resolve(ref);
|
|
146
|
+
if (el === null) {
|
|
147
|
+
result.component = COMPONENT_UNAVAILABLE;
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
const state = readComponentState(el);
|
|
151
|
+
result.component = isComponentStateResult(state) ? state : COMPONENT_UNAVAILABLE;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
function listAnimations() {
|
|
157
|
+
const doc = document;
|
|
158
|
+
if (typeof doc.getAnimations !== 'function')
|
|
159
|
+
return { animations: [] };
|
|
160
|
+
const animations = doc.getAnimations().map((a) => {
|
|
161
|
+
const effect = a.effect;
|
|
162
|
+
const timing = effect?.getTiming();
|
|
163
|
+
return {
|
|
164
|
+
playState: a.playState,
|
|
165
|
+
currentTime: a.currentTime,
|
|
166
|
+
duration: timing?.duration,
|
|
167
|
+
};
|
|
168
|
+
});
|
|
169
|
+
return { animations };
|
|
170
|
+
}
|
|
171
|
+
export function resolveNavigationUrl(rawUrl, baseUrl) {
|
|
172
|
+
if (rawUrl.length === 0 || rawUrl.length > TRANSPORT_LIMITS.MAX_URL_LENGTH)
|
|
173
|
+
return null;
|
|
174
|
+
try {
|
|
175
|
+
const url = new URL(rawUrl, baseUrl);
|
|
176
|
+
return url.protocol === 'http:' || url.protocol === 'https:' ? url.toString() : null;
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/** Map browser command names to handlers. Used by the transport on each COMMAND. */
|
|
183
|
+
export function createCommandRegistry() {
|
|
184
|
+
const reg = new Map();
|
|
185
|
+
reg.set(ReticleCommand.SNAPSHOT, (args) => buildSnapshot({
|
|
186
|
+
scope: str(args['scope']),
|
|
187
|
+
mode: str(args['mode']) ?? SnapshotMode.FULL,
|
|
188
|
+
}));
|
|
189
|
+
reg.set(ReticleCommand.QUERY, (args) => runQuery(queryFromArgs(args)));
|
|
190
|
+
reg.set(ReticleCommand.MATCH, (args) => matchQuery(ElementQuerySchema.parse(record(args['query'])), str(args['state'])));
|
|
191
|
+
reg.set(ReticleCommand.ACT, (args) => {
|
|
192
|
+
const action = str(args['action']) ?? '';
|
|
193
|
+
if (action === ActionType.WEBMCP) {
|
|
194
|
+
const inner = record(args['args']);
|
|
195
|
+
return dispatchWebMcp(str(inner['tool']) ?? '', record(inner['params']), inner[DANGEROUS_ACTION_CONFIRM_ARG] === true);
|
|
196
|
+
}
|
|
197
|
+
return executeAction(str(args['ref']) ?? '', action, record(args['args']));
|
|
198
|
+
});
|
|
199
|
+
reg.set(ReticleCommand.ACT_SEQUENCE, (args) => executeSequence((Array.isArray(args['steps']) ? args['steps'] : [])));
|
|
200
|
+
reg.set(ReticleCommand.INSPECT, (args) => inspect(str(args['ref']) ?? ''));
|
|
201
|
+
reg.set(ReticleCommand.ANIMATIONS, () => listAnimations());
|
|
202
|
+
reg.set(ReticleCommand.CLOCK, (args) => {
|
|
203
|
+
if (args['reset'] === true) {
|
|
204
|
+
resetClock();
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
if (args['freeze'] === true)
|
|
208
|
+
freezeClock();
|
|
209
|
+
const adv = args['advanceMs'];
|
|
210
|
+
if (typeof adv === 'number')
|
|
211
|
+
advanceClock(adv);
|
|
212
|
+
}
|
|
213
|
+
return { frozen: isClockFrozen() };
|
|
214
|
+
});
|
|
215
|
+
reg.set(ReticleCommand.STATE_READ, (args) => readState(str(args['ref']), str(args['store']), str(args['path']), num(args['depth'])));
|
|
216
|
+
reg.set(ReticleCommand.CAPABILITIES, () => getCapabilities());
|
|
217
|
+
reg.set(ReticleCommand.SCROLL, (args) => {
|
|
218
|
+
const dy = args['dy'];
|
|
219
|
+
const fraction = args['fraction'];
|
|
220
|
+
return scrollContainer(str(args['ref']), typeof dy === 'number' ? dy : undefined, typeof fraction === 'number' ? fraction : undefined);
|
|
221
|
+
});
|
|
222
|
+
reg.set(ReticleCommand.NAVIGATE, (args) => {
|
|
223
|
+
const rawUrl = str(args['url']);
|
|
224
|
+
if (rawUrl === undefined || rawUrl.length === 0)
|
|
225
|
+
return { ok: false, reason: 'url required' };
|
|
226
|
+
const url = resolveNavigationUrl(rawUrl, window.location.href);
|
|
227
|
+
if (url === null)
|
|
228
|
+
return { ok: false, reason: 'only http(s) navigation is allowed' };
|
|
229
|
+
window.location.assign(url);
|
|
230
|
+
return { ok: true, url };
|
|
231
|
+
});
|
|
232
|
+
reg.set(ReticleCommand.REFRESH, (args) => {
|
|
233
|
+
if (args['hard'] === true) {
|
|
234
|
+
// Hard reload: navigate to self with a cache-busting param then replace history.
|
|
235
|
+
const url = new URL(window.location.href);
|
|
236
|
+
url.searchParams.set(RELOAD_CACHE_BUST_PARAM, String(Date.now()));
|
|
237
|
+
window.location.replace(url.toString());
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
window.location.reload();
|
|
241
|
+
}
|
|
242
|
+
return { ok: true };
|
|
243
|
+
});
|
|
244
|
+
return reg;
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/commands/commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ElementState, type ElementDescriptor } from '@reticlehq/core';
|
|
2
|
+
/** Compute the ARIA role (explicit wins, else implicit from the tag). */
|
|
3
|
+
export declare function getRole(el: Element): string;
|
|
4
|
+
/** Accessible name via a practical subset of the accname algorithm. */
|
|
5
|
+
export declare function getAccessibleName(el: Element): string;
|
|
6
|
+
/** The set of states relevant to assertions (plan/06). */
|
|
7
|
+
export declare function getStates(el: Element): ElementState[];
|
|
8
|
+
/**
|
|
9
|
+
* True when a form field holds a secret the SDK must never capture verbatim — a password input, a
|
|
10
|
+
* sensitive `autocomplete` (cc-number, one-time-code, …), or a name/id/testid/aria-label that trips
|
|
11
|
+
* `isSensitiveKey`. The single source of truth for both live-snapshot redaction (`getValue`) and the
|
|
12
|
+
* flow recorder's fill-value redaction, so recorded flows never persist typed passwords/OTPs/keys.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isSensitiveField(el: Element): boolean;
|
|
15
|
+
export declare function getValue(el: Element): string | undefined;
|
|
16
|
+
/** Whether the element is actually visible (not display:none/hidden/aria-hidden/opacity:0). */
|
|
17
|
+
export declare function isVisible(el: Element): boolean;
|
|
18
|
+
/** Build the compact descriptor surfaced to the agent. */
|
|
19
|
+
export declare function describe(el: Element): ElementDescriptor;
|
|
20
|
+
//# sourceMappingURL=a11y.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a11y.d.ts","sourceRoot":"","sources":["../../src/dom/a11y.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAkB,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAsCvF,yEAAyE;AACzE,wBAAgB,OAAO,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,CAkD3C;AAkBD,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,CAwCrD;AAQD,0DAA0D;AAC1D,wBAAgB,SAAS,CAAC,EAAE,EAAE,OAAO,GAAG,YAAY,EAAE,CAqBrD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAsBrD;AAED,wBAAgB,QAAQ,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAWxD;AAED,+FAA+F;AAC/F,wBAAgB,SAAS,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAqB9C;AASD,0DAA0D;AAC1D,wBAAgB,QAAQ,CAAC,EAAE,EAAE,OAAO,GAAG,iBAAiB,CAcvD"}
|
package/dist/dom/a11y.js
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { ElementState, REDACTED_VALUE } from '@reticlehq/core';
|
|
2
|
+
import { refs } from './refs.js';
|
|
3
|
+
import { isSensitiveKey } from '../security/serialization.js';
|
|
4
|
+
/** Roles whose accessible name comes from their text content. */
|
|
5
|
+
const NAME_FROM_CONTENT = new Set([
|
|
6
|
+
'button',
|
|
7
|
+
'link',
|
|
8
|
+
'heading',
|
|
9
|
+
'option',
|
|
10
|
+
'listitem',
|
|
11
|
+
'cell',
|
|
12
|
+
'columnheader',
|
|
13
|
+
'rowheader',
|
|
14
|
+
'tab',
|
|
15
|
+
'menuitem',
|
|
16
|
+
'menuitemcheckbox',
|
|
17
|
+
'menuitemradio',
|
|
18
|
+
'treeitem',
|
|
19
|
+
'gridcell',
|
|
20
|
+
'switch',
|
|
21
|
+
'status',
|
|
22
|
+
'alert',
|
|
23
|
+
]);
|
|
24
|
+
const INPUT_TEXT_TYPES = new Set(['text', 'email', 'tel', 'url', 'search', 'password', '']);
|
|
25
|
+
function inputRole(input) {
|
|
26
|
+
const type = input.type.toLowerCase();
|
|
27
|
+
if (INPUT_TEXT_TYPES.has(type))
|
|
28
|
+
return 'textbox';
|
|
29
|
+
if (type === 'checkbox')
|
|
30
|
+
return 'checkbox';
|
|
31
|
+
if (type === 'radio')
|
|
32
|
+
return 'radio';
|
|
33
|
+
if (type === 'range')
|
|
34
|
+
return 'slider';
|
|
35
|
+
if (type === 'number')
|
|
36
|
+
return 'spinbutton';
|
|
37
|
+
if (type === 'submit' || type === 'button' || type === 'reset')
|
|
38
|
+
return 'button';
|
|
39
|
+
return 'textbox';
|
|
40
|
+
}
|
|
41
|
+
/** Compute the ARIA role (explicit wins, else implicit from the tag). */
|
|
42
|
+
export function getRole(el) {
|
|
43
|
+
const explicit = el.getAttribute('role');
|
|
44
|
+
if (explicit !== null && explicit.trim().length > 0)
|
|
45
|
+
return explicit.trim();
|
|
46
|
+
const tag = el.tagName.toLowerCase();
|
|
47
|
+
switch (tag) {
|
|
48
|
+
case 'a':
|
|
49
|
+
return el.hasAttribute('href') ? 'link' : 'generic';
|
|
50
|
+
case 'button':
|
|
51
|
+
return 'button';
|
|
52
|
+
case 'input':
|
|
53
|
+
return inputRole(el);
|
|
54
|
+
case 'textarea':
|
|
55
|
+
return 'textbox';
|
|
56
|
+
case 'select':
|
|
57
|
+
return el.multiple ? 'listbox' : 'combobox';
|
|
58
|
+
case 'h1':
|
|
59
|
+
case 'h2':
|
|
60
|
+
case 'h3':
|
|
61
|
+
case 'h4':
|
|
62
|
+
case 'h5':
|
|
63
|
+
case 'h6':
|
|
64
|
+
return 'heading';
|
|
65
|
+
case 'ul':
|
|
66
|
+
case 'ol':
|
|
67
|
+
return 'list';
|
|
68
|
+
case 'li':
|
|
69
|
+
return 'listitem';
|
|
70
|
+
case 'nav':
|
|
71
|
+
return 'navigation';
|
|
72
|
+
case 'main':
|
|
73
|
+
return 'main';
|
|
74
|
+
case 'aside':
|
|
75
|
+
return 'complementary';
|
|
76
|
+
case 'dialog':
|
|
77
|
+
return 'dialog';
|
|
78
|
+
case 'img':
|
|
79
|
+
return 'img';
|
|
80
|
+
case 'table':
|
|
81
|
+
return 'table';
|
|
82
|
+
case 'form':
|
|
83
|
+
return 'form';
|
|
84
|
+
case 'p':
|
|
85
|
+
return 'paragraph';
|
|
86
|
+
case 'header':
|
|
87
|
+
return 'banner';
|
|
88
|
+
case 'footer':
|
|
89
|
+
return 'contentinfo';
|
|
90
|
+
default:
|
|
91
|
+
return 'generic';
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function collapse(text) {
|
|
95
|
+
return text.replace(/\s+/g, ' ').trim();
|
|
96
|
+
}
|
|
97
|
+
function labelledByText(el) {
|
|
98
|
+
const ids = el.getAttribute('aria-labelledby');
|
|
99
|
+
if (ids === null)
|
|
100
|
+
return null;
|
|
101
|
+
const parts = [];
|
|
102
|
+
for (const id of ids.split(/\s+/)) {
|
|
103
|
+
const ref = el.ownerDocument.getElementById(id);
|
|
104
|
+
if (ref !== null)
|
|
105
|
+
parts.push(collapse(ref.textContent ?? ''));
|
|
106
|
+
}
|
|
107
|
+
const joined = parts.join(' ').trim();
|
|
108
|
+
return joined.length > 0 ? joined : null;
|
|
109
|
+
}
|
|
110
|
+
/** Accessible name via a practical subset of the accname algorithm. */
|
|
111
|
+
export function getAccessibleName(el) {
|
|
112
|
+
const labelled = labelledByText(el);
|
|
113
|
+
if (labelled !== null)
|
|
114
|
+
return labelled;
|
|
115
|
+
const ariaLabel = el.getAttribute('aria-label');
|
|
116
|
+
if (ariaLabel !== null && ariaLabel.trim().length > 0)
|
|
117
|
+
return ariaLabel.trim();
|
|
118
|
+
if (el instanceof HTMLImageElement) {
|
|
119
|
+
const alt = el.getAttribute('alt');
|
|
120
|
+
if (alt !== null)
|
|
121
|
+
return alt.trim();
|
|
122
|
+
}
|
|
123
|
+
if (el instanceof HTMLInputElement ||
|
|
124
|
+
el instanceof HTMLTextAreaElement ||
|
|
125
|
+
el instanceof HTMLSelectElement) {
|
|
126
|
+
const labels = el.labels;
|
|
127
|
+
if (labels !== null && labels.length > 0) {
|
|
128
|
+
const text = [...labels]
|
|
129
|
+
.map((l) => collapse(l.textContent ?? ''))
|
|
130
|
+
.join(' ')
|
|
131
|
+
.trim();
|
|
132
|
+
if (text.length > 0)
|
|
133
|
+
return text;
|
|
134
|
+
}
|
|
135
|
+
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
|
|
136
|
+
const placeholder = el.getAttribute('placeholder');
|
|
137
|
+
if (placeholder !== null && placeholder.trim().length > 0)
|
|
138
|
+
return placeholder.trim();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (NAME_FROM_CONTENT.has(getRole(el))) {
|
|
142
|
+
const text = collapse(el.textContent ?? '');
|
|
143
|
+
if (text.length > 0)
|
|
144
|
+
return text;
|
|
145
|
+
}
|
|
146
|
+
const title = el.getAttribute('title');
|
|
147
|
+
if (title !== null && title.trim().length > 0)
|
|
148
|
+
return title.trim();
|
|
149
|
+
return '';
|
|
150
|
+
}
|
|
151
|
+
function ariaBool(el, attr) {
|
|
152
|
+
const value = el.getAttribute(attr);
|
|
153
|
+
if (value === null)
|
|
154
|
+
return undefined;
|
|
155
|
+
return value === 'true';
|
|
156
|
+
}
|
|
157
|
+
/** The set of states relevant to assertions (plan/06). */
|
|
158
|
+
export function getStates(el) {
|
|
159
|
+
const states = [ElementState.PRESENT];
|
|
160
|
+
if (isVisible(el))
|
|
161
|
+
states.push(ElementState.VISIBLE);
|
|
162
|
+
else
|
|
163
|
+
states.push(ElementState.HIDDEN);
|
|
164
|
+
const disabledProp = (el instanceof HTMLButtonElement ||
|
|
165
|
+
el instanceof HTMLInputElement ||
|
|
166
|
+
el instanceof HTMLSelectElement ||
|
|
167
|
+
el instanceof HTMLTextAreaElement) &&
|
|
168
|
+
el.disabled;
|
|
169
|
+
const disabled = disabledProp || ariaBool(el, 'aria-disabled') === true;
|
|
170
|
+
states.push(disabled ? ElementState.DISABLED : ElementState.ENABLED);
|
|
171
|
+
const checkedProp = el instanceof HTMLInputElement && (el.type === 'checkbox' || el.type === 'radio') && el.checked;
|
|
172
|
+
if (checkedProp || ariaBool(el, 'aria-checked') === true)
|
|
173
|
+
states.push(ElementState.CHECKED);
|
|
174
|
+
if (ariaBool(el, 'aria-expanded') === true)
|
|
175
|
+
states.push(ElementState.EXPANDED);
|
|
176
|
+
if (el.ownerDocument.activeElement === el)
|
|
177
|
+
states.push(ElementState.FOCUSED);
|
|
178
|
+
return states;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* True when a form field holds a secret the SDK must never capture verbatim — a password input, a
|
|
182
|
+
* sensitive `autocomplete` (cc-number, one-time-code, …), or a name/id/testid/aria-label that trips
|
|
183
|
+
* `isSensitiveKey`. The single source of truth for both live-snapshot redaction (`getValue`) and the
|
|
184
|
+
* flow recorder's fill-value redaction, so recorded flows never persist typed passwords/OTPs/keys.
|
|
185
|
+
*/
|
|
186
|
+
export function isSensitiveField(el) {
|
|
187
|
+
if (!(el instanceof HTMLInputElement) &&
|
|
188
|
+
!(el instanceof HTMLTextAreaElement) &&
|
|
189
|
+
!(el instanceof HTMLSelectElement)) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
const autocomplete = el.getAttribute('autocomplete') ?? '';
|
|
193
|
+
const identifiers = [
|
|
194
|
+
el.getAttribute('name') ?? '',
|
|
195
|
+
el.id,
|
|
196
|
+
el.getAttribute('data-testid') ?? '',
|
|
197
|
+
el.getAttribute('aria-label') ?? '',
|
|
198
|
+
];
|
|
199
|
+
const sensitiveAutocomplete = /current-password|new-password|cc-number|cc-csc|one-time-code/i.test(autocomplete);
|
|
200
|
+
return ((el instanceof HTMLInputElement && el.type.toLowerCase() === 'password') ||
|
|
201
|
+
sensitiveAutocomplete ||
|
|
202
|
+
identifiers.some(isSensitiveKey));
|
|
203
|
+
}
|
|
204
|
+
export function getValue(el) {
|
|
205
|
+
if (el instanceof HTMLInputElement ||
|
|
206
|
+
el instanceof HTMLTextAreaElement ||
|
|
207
|
+
el instanceof HTMLSelectElement) {
|
|
208
|
+
if (isSensitiveField(el))
|
|
209
|
+
return REDACTED_VALUE;
|
|
210
|
+
return el.value;
|
|
211
|
+
}
|
|
212
|
+
const valueNow = el.getAttribute('aria-valuenow');
|
|
213
|
+
return valueNow ?? undefined;
|
|
214
|
+
}
|
|
215
|
+
/** Whether the element is actually visible (not display:none/hidden/aria-hidden/opacity:0). */
|
|
216
|
+
export function isVisible(el) {
|
|
217
|
+
if (!el.isConnected)
|
|
218
|
+
return false;
|
|
219
|
+
let node = el;
|
|
220
|
+
while (node !== null) {
|
|
221
|
+
if (node.getAttribute('aria-hidden') === 'true')
|
|
222
|
+
return false;
|
|
223
|
+
if (node instanceof HTMLElement && node.hidden)
|
|
224
|
+
return false;
|
|
225
|
+
const view = node.ownerDocument.defaultView;
|
|
226
|
+
if (view !== null) {
|
|
227
|
+
const style = view.getComputedStyle(node);
|
|
228
|
+
if (style.display === 'none' ||
|
|
229
|
+
style.visibility === 'hidden' ||
|
|
230
|
+
style.visibility === 'collapse') {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
if (Number.parseFloat(style.opacity || '1') === 0)
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
node = node.parentElement;
|
|
237
|
+
}
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
const MAX_TEXT = 80;
|
|
241
|
+
function getVisibleText(el) {
|
|
242
|
+
const text = collapse(el.textContent ?? '');
|
|
243
|
+
return text.length > MAX_TEXT ? `${text.slice(0, MAX_TEXT)}…` : text;
|
|
244
|
+
}
|
|
245
|
+
/** Build the compact descriptor surfaced to the agent. */
|
|
246
|
+
export function describe(el) {
|
|
247
|
+
const value = getValue(el);
|
|
248
|
+
const text = getVisibleText(el);
|
|
249
|
+
const name = getAccessibleName(el);
|
|
250
|
+
const base = {
|
|
251
|
+
ref: refs.refFor(el),
|
|
252
|
+
role: getRole(el),
|
|
253
|
+
name,
|
|
254
|
+
states: getStates(el),
|
|
255
|
+
visible: isVisible(el),
|
|
256
|
+
};
|
|
257
|
+
if (value !== undefined && value.length > 0)
|
|
258
|
+
base.value = value;
|
|
259
|
+
if (text.length > 0 && text !== name)
|
|
260
|
+
base.text = text;
|
|
261
|
+
return base;
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=a11y.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a11y.js","sourceRoot":"","sources":["../../src/dom/a11y.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-anchor synthesis — derive a STABLE way to address any element WITHOUT a hand-added
|
|
3
|
+
* data-testid. This is the brain of zero-config integration: given what the framework already knows
|
|
4
|
+
* about an element (its component name + source location from the fiber, its role + accessible name,
|
|
5
|
+
* its position), pick the most durable anchor so a flow can re-find the element across refactors.
|
|
6
|
+
*
|
|
7
|
+
* Pure and framework-agnostic: it takes a plain descriptor (the React adapter, or a future Vue/Svelte
|
|
8
|
+
* adapter, fills it in) and returns the chosen anchor + whether it is stable. No DOM, no fiber here.
|
|
9
|
+
*
|
|
10
|
+
* Priority (most → least durable). Each tier is only used when the one above is unavailable:
|
|
11
|
+
* 1. testid — explicit, author-chosen, the gold standard. Stable.
|
|
12
|
+
* 2. component@source — component display name + source file:line. Survives text/markup/style
|
|
13
|
+
* changes; uniquely identifies WHERE in the source the element comes from.
|
|
14
|
+
* Stable (a move that changes the source line is a real change worth re-pinning).
|
|
15
|
+
* 3. component+role/name — component name plus role/accessible-name when no source is available.
|
|
16
|
+
* Stable enough: the component identity anchors it, role/name disambiguate.
|
|
17
|
+
* 4. role+name — semantic but content-dependent: an accessible name can change with copy.
|
|
18
|
+
* NOT marked stable (a healed locator could drift to a renamed element).
|
|
19
|
+
* 5. role / position — last resort. NOT stable; surfaced so the element is still addressable, but
|
|
20
|
+
* a flow built on it should be flagged (the recorder marks the step degraded).
|
|
21
|
+
*
|
|
22
|
+
* The point: tiers 1–3 are "stable" (a flow anchored on them can be trusted to re-resolve to the
|
|
23
|
+
* same element); tiers 4–5 are best-effort. Today most elements without a testid fall to role/text
|
|
24
|
+
* (degraded). With component+source, the SAME elements become tier-2 stable anchors — that is how
|
|
25
|
+
* integration becomes universal without the app author adding a single testid.
|
|
26
|
+
*/
|
|
27
|
+
/** Which signal produced the anchor — also its durability tier. */
|
|
28
|
+
export declare const AnchorStrategy: {
|
|
29
|
+
readonly TESTID: "testid";
|
|
30
|
+
readonly COMPONENT: "component";
|
|
31
|
+
readonly ROLE: "role";
|
|
32
|
+
readonly POSITION: "position";
|
|
33
|
+
};
|
|
34
|
+
export type AnchorStrategy = (typeof AnchorStrategy)[keyof typeof AnchorStrategy];
|
|
35
|
+
/** What an adapter knows about an element — any subset; richer input yields a more durable anchor. */
|
|
36
|
+
export interface AnchorInput {
|
|
37
|
+
/** Explicit data-testid, if the author added one. */
|
|
38
|
+
testid?: string;
|
|
39
|
+
/** Nearest component display name (React fiber / Vue instance / …). */
|
|
40
|
+
component?: string;
|
|
41
|
+
/** Source location stamped by the framework's compiler/plugin. */
|
|
42
|
+
source?: {
|
|
43
|
+
file: string;
|
|
44
|
+
line: number;
|
|
45
|
+
};
|
|
46
|
+
/** ARIA role. */
|
|
47
|
+
role?: string;
|
|
48
|
+
/** Accessible name (label / text). */
|
|
49
|
+
name?: string;
|
|
50
|
+
/** Index among same-component-or-role siblings — a positional tiebreaker. */
|
|
51
|
+
nth?: number;
|
|
52
|
+
}
|
|
53
|
+
interface SynthesizedAnchor {
|
|
54
|
+
strategy: AnchorStrategy;
|
|
55
|
+
/** A compact, human-legible, re-resolvable anchor string. */
|
|
56
|
+
value: string;
|
|
57
|
+
/** True when a flow can trust this anchor to re-resolve to the same element (tiers 1–3). */
|
|
58
|
+
stable: boolean;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Choose the most durable anchor for an element from whatever the adapter could observe. Always
|
|
62
|
+
* returns something addressable (falls through to position), with `stable` marking tiers 1–3.
|
|
63
|
+
*/
|
|
64
|
+
export declare function synthesizeAnchor(input: AnchorInput): SynthesizedAnchor;
|
|
65
|
+
export {};
|
|
66
|
+
//# sourceMappingURL=auto-anchor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-anchor.d.ts","sourceRoot":"","sources":["../../src/dom/auto-anchor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,mEAAmE;AACnE,eAAO,MAAM,cAAc;;;;;CAKjB,CAAC;AACX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC;AAElF,sGAAsG;AACtG,MAAM,WAAW,WAAW;IAC1B,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,iBAAiB;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,UAAU,iBAAiB;IACzB,QAAQ,EAAE,cAAc,CAAC;IACzB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,4FAA4F;IAC5F,MAAM,EAAE,OAAO,CAAC;CACjB;AAYD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,iBAAiB,CA4BtE"}
|