@reticlehq/browser 3.4.0 → 3.6.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.js +44 -43
- package/dist/actions/actions-press.d.ts +10 -4
- package/dist/actions/actions-press.js +108 -17
- package/dist/actions/actions.d.ts +2 -1
- package/dist/actions/actions.js +25 -26
- package/dist/actions/danger-context.js +1 -1
- package/dist/commands/commands.js +2 -6
- package/dist/connect-options.d.ts +1 -0
- package/dist/dom/a11y.js +43 -11
- package/dist/dom/addressing/refs.js +2 -1
- package/dist/dom/addressing/testid-attr.d.ts +4 -0
- package/dist/dom/addressing/testid-attr.js +14 -0
- package/dist/dom/occlusion.js +5 -1
- package/dist/dom/query.d.ts +1 -0
- package/dist/dom/query.js +42 -15
- package/dist/dom/snapshot.js +1 -0
- package/dist/observers/departure.js +51 -9
- package/dist/observers/dom.js +3 -2
- package/dist/observers/field.js +5 -3
- package/dist/observers/health.js +63 -2
- package/dist/observers/network-stream.d.ts +1 -1
- package/dist/observers/network-stream.js +3 -3
- package/dist/observers/network.js +1 -1
- package/dist/observers/storage.js +6 -1
- package/dist/presenter/carousel/carousel.d.ts +5 -2
- package/dist/presenter/carousel/carousel.js +34 -7
- package/dist/presenter/carousel/offer-card.d.ts +2 -2
- package/dist/presenter/carousel/offer-card.js +2 -1
- package/dist/presenter/carousel/panel-slides.d.ts +4 -3
- package/dist/presenter/carousel/panel-slides.js +43 -6
- package/dist/presenter/carousel/talk-card.d.ts +1 -1
- package/dist/presenter/chrome/log-kinds.d.ts +5 -0
- package/dist/presenter/chrome/log-kinds.js +1 -0
- package/dist/presenter/chrome/log-memory.d.ts +12 -0
- package/dist/presenter/chrome/log-memory.js +39 -0
- package/dist/presenter/chrome/presenter-hud-chrome.d.ts +1 -0
- package/dist/presenter/chrome/presenter-hud-chrome.js +7 -1
- package/dist/presenter/chrome/presenter-log.d.ts +5 -4
- package/dist/presenter/chrome/presenter-log.js +55 -5
- package/dist/presenter/chrome/presenter-report-copy.d.ts +11 -1
- package/dist/presenter/chrome/presenter-report-copy.js +14 -1
- package/dist/presenter/hud-telemetry.js +31 -2
- package/dist/presenter/icons/presenter-heroicons-data.d.ts +1 -0
- package/dist/presenter/icons/presenter-heroicons-data.js +4 -3
- package/dist/presenter/icons/presenter-icons.d.ts +2 -0
- package/dist/presenter/icons/presenter-icons.js +2 -0
- package/dist/presenter/presenter-account.d.ts +5 -4
- package/dist/presenter/presenter-account.js +23 -10
- package/dist/presenter/presenter-chat-views.d.ts +21 -0
- package/dist/presenter/presenter-chat-views.js +382 -0
- package/dist/presenter/presenter-config.d.ts +3 -2
- package/dist/presenter/presenter-config.js +4 -3
- package/dist/presenter/presenter-controls.d.ts +4 -2
- package/dist/presenter/presenter-controls.js +231 -51
- package/dist/presenter/presenter-design-tokens.d.ts +1 -0
- package/dist/presenter/presenter-design-tokens.js +34 -0
- package/dist/presenter/presenter-dock-layout.js +1 -1
- package/dist/presenter/presenter-frame.d.ts +12 -0
- package/dist/presenter/presenter-frame.js +189 -0
- package/dist/presenter/presenter-plan.d.ts +10 -0
- package/dist/presenter/presenter-plan.js +185 -0
- package/dist/presenter/presenter-report-styles.js +7 -0
- package/dist/presenter/presenter-report.d.ts +1 -1
- package/dist/presenter/presenter-report.js +53 -16
- package/dist/presenter/presenter-settings-styles.js +10 -0
- package/dist/presenter/presenter-settings.d.ts +5 -0
- package/dist/presenter/presenter-settings.js +71 -11
- package/dist/presenter/presenter-shell-styles.js +39 -42
- package/dist/presenter/presenter-shell.d.ts +8 -1
- package/dist/presenter/presenter-shell.js +124 -72
- package/dist/presenter/presenter-styles.js +9 -1
- package/dist/presenter/presenter.d.ts +4 -3
- package/dist/presenter/presenter.js +101 -13
- package/dist/presenter/tour/tour.d.ts +4 -1
- package/dist/presenter/tour/tour.js +6 -4
- package/dist/recorder/recorder.js +2 -2
- package/dist/registry/auto-testids.js +3 -4
- package/dist/registry/declared-platform.js +2 -0
- package/dist/reticle-inject.js +880 -513
- package/dist/reticle.d.ts +10 -1
- package/dist/reticle.js +73 -9
- package/dist/review/annotator-styles.d.ts +1 -1
- package/dist/review/annotator.d.ts +7 -0
- package/dist/review/annotator.js +20 -2
- package/dist/review/mark-anchor.js +2 -2
- package/dist/session-continuity.js +2 -1
- package/dist/storage-keys.d.ts +14 -0
- package/dist/storage-keys.js +17 -0
- package/package.json +3 -2
package/dist/reticle.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import { EventType, RETICLE_URL_PARAM, type ReticleEvent } from '@reticlehq/core';
|
|
1
|
+
import { EventType, RETICLE_URL_PARAM, HudVisibility, type ReticleEvent } from '@reticlehq/core';
|
|
2
2
|
import { type CapabilitiesInput } from './registry/capabilities.js';
|
|
3
3
|
import type { ReticleConnectOptions } from './connect-options.js';
|
|
4
4
|
export type { ReticleConnectOptions };
|
|
5
5
|
export declare function shouldBlockProduction(nodeEnv: string | undefined, allowInProduction: boolean): boolean;
|
|
6
|
+
export declare function withBridgePath(bridgeUrl: string): {
|
|
7
|
+
url: string;
|
|
8
|
+
adjusted: boolean;
|
|
9
|
+
};
|
|
6
10
|
export declare function connectionPolicy(pageHostname: string, bridgeUrl: string, allowNonLocalhost: boolean, token: string | undefined, pageProtocol?: string): {
|
|
7
11
|
allowed: boolean;
|
|
8
12
|
reason?: string;
|
|
@@ -12,6 +16,11 @@ export { RETICLE_URL_PARAM };
|
|
|
12
16
|
export declare function reticleParamsFromSearch(search: string): {
|
|
13
17
|
session?: string;
|
|
14
18
|
projectId?: string;
|
|
19
|
+
hud?: HudVisibility;
|
|
20
|
+
};
|
|
21
|
+
export declare function hudWithoutPanel(hud: HudVisibility | undefined): {
|
|
22
|
+
remember?: HudVisibility;
|
|
23
|
+
placed: HudVisibility[];
|
|
15
24
|
};
|
|
16
25
|
export declare function resolveConnectIdentity(options: {
|
|
17
26
|
session?: string;
|
package/dist/reticle.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { setPresenterVisible } from './dom/dom-ignore.js';
|
|
2
|
-
import { EventType, RETICLE_DEFAULT_PORT, RETICLE_PROTOCOL_VERSION, RETICLE_URL_PARAM, bridgeWsUrl, ReticleCommand, MessageKind, SESSION_AUTO, SessionState, TRANSPORT_LIMITS, buildRedactionPolicy, isLoopbackHostname, isLocalPage, setActiveRedactionPolicy, wireRedactionKeys, RETICLE_ROOT_GLOBAL, RETICLE_SDK_VERSION_GLOBAL, CONTRACT_FINGERPRINT, CONTRACT_PARTS, newDocumentId, NO_EDITS_OBSERVED, PresenterMode, } from '@reticlehq/core';
|
|
2
|
+
import { EventType, RETICLE_DEFAULT_PORT, RETICLE_PROTOCOL_VERSION, RETICLE_URL_PARAM, RETICLE_WS_PATH, bridgeWsUrl, ReticleCommand, MessageKind, SESSION_AUTO, SessionState, TRANSPORT_LIMITS, buildRedactionPolicy, isLoopbackHostname, isLocalPage, setActiveRedactionPolicy, wireRedactionKeys, RETICLE_ROOT_GLOBAL, RETICLE_SDK_VERSION_GLOBAL, CONTRACT_FINGERPRINT, CONTRACT_PARTS, newDocumentId, NO_EDITS_OBSERVED, PresenterMode, CommandActor, HudCorner, HudVisibility, } from '@reticlehq/core';
|
|
3
3
|
import { rememberSessionLabel } from './session-continuity.js';
|
|
4
4
|
import { editEpoch } from './edit-epoch.js';
|
|
5
5
|
import { createCommandRegistry, RELOAD_CACHE_BUST_PARAM, } from './commands/commands.js';
|
|
@@ -10,9 +10,10 @@ import { declaredChannels } from './registry/declared-channels.js';
|
|
|
10
10
|
import { declaredCommands, declaredPlatform } from './registry/declared-platform.js';
|
|
11
11
|
import { registerCapabilities, setCapabilitiesListener, hasCapabilities, } from './registry/capabilities.js';
|
|
12
12
|
import { installAllObservers, runTeardowns } from './observers/install-all.js';
|
|
13
|
+
import { setTestIdAttr } from './dom/addressing/testid-attr.js';
|
|
13
14
|
import { setNetworkBodyMaxChars } from './observers/net-detail/network-body.js';
|
|
14
15
|
import { installOverlay } from './presenter/chrome/overlay.js';
|
|
15
|
-
import { LOG_KIND, LOG_RESULT } from './presenter/chrome/log-kinds.js';
|
|
16
|
+
import { LOG_ACTOR, LOG_KIND, LOG_RESULT } from './presenter/chrome/log-kinds.js';
|
|
16
17
|
import { actionVerb } from './presenter/chrome/presenter-verbs.js';
|
|
17
18
|
import { str, refLabel, modeForCommand, presentStatus } from './reticle-presenter-helpers.js';
|
|
18
19
|
import { resetClock } from './timers/clock.js';
|
|
@@ -22,6 +23,21 @@ import { Annotator } from './review/annotator.js';
|
|
|
22
23
|
export function shouldBlockProduction(nodeEnv, allowInProduction) {
|
|
23
24
|
return 'production' === nodeEnv && !allowInProduction;
|
|
24
25
|
}
|
|
26
|
+
export function withBridgePath(bridgeUrl) {
|
|
27
|
+
let parsed;
|
|
28
|
+
try {
|
|
29
|
+
parsed = new URL(bridgeUrl);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return { url: bridgeUrl, adjusted: false };
|
|
33
|
+
}
|
|
34
|
+
if ((parsed.protocol !== 'ws:' && parsed.protocol !== 'wss:') ||
|
|
35
|
+
(parsed.pathname !== '' && parsed.pathname !== '/')) {
|
|
36
|
+
return { url: bridgeUrl, adjusted: false };
|
|
37
|
+
}
|
|
38
|
+
parsed.pathname = RETICLE_WS_PATH;
|
|
39
|
+
return { url: parsed.toString(), adjusted: true };
|
|
40
|
+
}
|
|
25
41
|
export function connectionPolicy(pageHostname, bridgeUrl, allowNonLocalhost, token, pageProtocol = 'http:') {
|
|
26
42
|
let bridge;
|
|
27
43
|
try {
|
|
@@ -57,6 +73,7 @@ export function connectionPolicy(pageHostname, bridgeUrl, allowNonLocalhost, tok
|
|
|
57
73
|
}
|
|
58
74
|
return { allowed: true };
|
|
59
75
|
}
|
|
76
|
+
const KILLED_MESSAGE = '[Reticle] killed for this page. Restart your dev server or reload the page to bring it back.';
|
|
60
77
|
const BRIDGE_LOST_SUMMARY = 'Session ended - lost connection to Reticle (the agent is no longer running).';
|
|
61
78
|
export function resolveSessionLabel(option, gen) {
|
|
62
79
|
return option === undefined || option === SESSION_AUTO ? gen() : option;
|
|
@@ -78,12 +95,20 @@ export function reticleParamsFromSearch(search) {
|
|
|
78
95
|
const out = {};
|
|
79
96
|
const session = params.get(RETICLE_URL_PARAM.SESSION);
|
|
80
97
|
const projectId = params.get(RETICLE_URL_PARAM.PROJECT);
|
|
98
|
+
const hud = oneOf(HudVisibility, params.get(RETICLE_URL_PARAM.HUD));
|
|
81
99
|
if (session !== null && session.length > 0)
|
|
82
100
|
out.session = session;
|
|
83
101
|
if (projectId !== null && projectId.length > 0)
|
|
84
102
|
out.projectId = projectId;
|
|
103
|
+
if (hud !== undefined)
|
|
104
|
+
out.hud = hud;
|
|
85
105
|
return out;
|
|
86
106
|
}
|
|
107
|
+
export function hudWithoutPanel(hud) {
|
|
108
|
+
if (hud === undefined)
|
|
109
|
+
return { placed: [] };
|
|
110
|
+
return { remember: hud, placed: HudVisibility.SHOWN === hud ? [] : [hud] };
|
|
111
|
+
}
|
|
87
112
|
export function resolveConnectIdentity(options, search) {
|
|
88
113
|
const url = reticleParamsFromSearch(search);
|
|
89
114
|
const explicitSession = options.session !== undefined && options.session !== SESSION_AUTO ? options.session : undefined;
|
|
@@ -116,6 +141,7 @@ export class Reticle {
|
|
|
116
141
|
#overlay;
|
|
117
142
|
#presenter;
|
|
118
143
|
#pendingPushes = new Map();
|
|
144
|
+
#pendingHud;
|
|
119
145
|
#readPanelSettings;
|
|
120
146
|
#panelRequested = false;
|
|
121
147
|
#bridgeConnected = false;
|
|
@@ -142,7 +168,11 @@ export class Reticle {
|
|
|
142
168
|
return;
|
|
143
169
|
}
|
|
144
170
|
stripReloadCacheBustParam();
|
|
145
|
-
const
|
|
171
|
+
const bridge = withBridgePath(options.url ?? bridgeWsUrl(RETICLE_DEFAULT_PORT));
|
|
172
|
+
const url = bridge.url;
|
|
173
|
+
if (bridge.adjusted) {
|
|
174
|
+
globalThis.console.warn(`[Reticle] bridge URL has no path; using ${url} (the bridge only accepts WebSocket upgrades on ${RETICLE_WS_PATH}).`);
|
|
175
|
+
}
|
|
146
176
|
const policy = connectionPolicy(window.location.hostname, url, true === options.allowNonLocalhost, options.token, window.location.protocol);
|
|
147
177
|
if (!policy.allowed) {
|
|
148
178
|
globalThis.console.warn(`[Reticle] ${policy.reason ?? 'connection blocked'}`);
|
|
@@ -188,6 +218,7 @@ export class Reticle {
|
|
|
188
218
|
});
|
|
189
219
|
setCapabilitiesListener(() => this.#transport?.reannounce());
|
|
190
220
|
setPresenterVisible(true === options.exposePresenter);
|
|
221
|
+
setTestIdAttr(options.testIdAttribute);
|
|
191
222
|
if (options.networkBodyMaxChars !== undefined) {
|
|
192
223
|
setNetworkBodyMaxChars(options.networkBodyMaxChars);
|
|
193
224
|
}
|
|
@@ -205,7 +236,8 @@ export class Reticle {
|
|
|
205
236
|
this.#overlay = installOverlay();
|
|
206
237
|
this.#overlay.update({ connected: true, events: 0 });
|
|
207
238
|
}
|
|
208
|
-
|
|
239
|
+
this.#pendingHud = reticleParamsFromSearch(window.location.search).hud;
|
|
240
|
+
if (options.present !== false && HudVisibility.REMOVED !== this.#pendingHud)
|
|
209
241
|
this.#fetchAndShowPanel(options);
|
|
210
242
|
if (true === options.recorder) {
|
|
211
243
|
this.#recorder = installRecorder({ emit, now: () => Date.now() });
|
|
@@ -215,7 +247,7 @@ export class Reticle {
|
|
|
215
247
|
this.#annotator = new Annotator({
|
|
216
248
|
emit,
|
|
217
249
|
now: () => Date.now(),
|
|
218
|
-
onMark: (mark) => this.#presenter?.log(LOG_KIND.HUMAN, `🚩 #${String(mark.index)} ${mark.
|
|
250
|
+
onMark: (mark) => this.#presenter?.log(LOG_KIND.HUMAN, `🚩 #${String(mark.index)} ${mark.label}${mark.source !== undefined ? ` · ${mark.source}` : ''} — ${mark.note}`),
|
|
219
251
|
shouldBlock: () => this.#readPanelSettings?.().blockPageInteractions ?? true,
|
|
220
252
|
});
|
|
221
253
|
this.#annotator.mount();
|
|
@@ -253,12 +285,19 @@ export class Reticle {
|
|
|
253
285
|
? { kind: intent.kind, text: intent.text }
|
|
254
286
|
: { kind: intent.kind });
|
|
255
287
|
panelOptions.onHudUse = (use) => this.#emit(EventType.HUD_USED, { ...use });
|
|
288
|
+
panelOptions.onKill = () => {
|
|
289
|
+
this.disconnect();
|
|
290
|
+
nativeWarn(KILLED_MESSAGE);
|
|
291
|
+
};
|
|
256
292
|
const panel = new Presenter(panelOptions);
|
|
257
293
|
this.#presenter = panel;
|
|
258
294
|
panel.mount();
|
|
259
295
|
for (const buffered of this.#pendingPushes.values())
|
|
260
296
|
panel.handlePush(buffered);
|
|
261
297
|
this.#pendingPushes.clear();
|
|
298
|
+
if (this.#pendingHud !== undefined)
|
|
299
|
+
panel.placeHud(this.#pendingHud, undefined);
|
|
300
|
+
this.#pendingHud = undefined;
|
|
262
301
|
void import('./presenter/tour/tour.js').then((tour) => {
|
|
263
302
|
if (!this.#connected)
|
|
264
303
|
return;
|
|
@@ -393,10 +432,31 @@ export class Reticle {
|
|
|
393
432
|
const idleEndMs = command.args['idleEndMs'];
|
|
394
433
|
if ('number' === typeof idleEndMs)
|
|
395
434
|
this.#presenter?.setIdleEndMs(idleEndMs);
|
|
396
|
-
|
|
435
|
+
const hud = oneOf(HudVisibility, command.args['hud']);
|
|
436
|
+
const corner = oneOf(HudCorner, command.args['corner']);
|
|
437
|
+
const presenter = this.#presenter;
|
|
438
|
+
let placed;
|
|
439
|
+
if (presenter !== undefined)
|
|
440
|
+
placed = presenter.placeHud(hud, corner);
|
|
441
|
+
else {
|
|
442
|
+
const early = hudWithoutPanel(hud);
|
|
443
|
+
if (early.remember !== undefined)
|
|
444
|
+
this.#pendingHud = early.remember;
|
|
445
|
+
placed = early.placed;
|
|
446
|
+
}
|
|
447
|
+
return {
|
|
448
|
+
ok: true,
|
|
449
|
+
result: {
|
|
450
|
+
applied: this.#presenter !== undefined,
|
|
451
|
+
idleEndMs,
|
|
452
|
+
...(0 < placed.length ? { hud: placed } : {}),
|
|
453
|
+
},
|
|
454
|
+
};
|
|
397
455
|
}
|
|
398
456
|
if (command.name === ReticleCommand.PRESENTER ||
|
|
399
457
|
command.name === ReticleCommand.FLOWS ||
|
|
458
|
+
command.name === ReticleCommand.FLOW_PROGRESS ||
|
|
459
|
+
command.name === ReticleCommand.PLAN ||
|
|
400
460
|
command.name === ReticleCommand.IMPACT) {
|
|
401
461
|
if (this.#presenter === undefined) {
|
|
402
462
|
this.#pendingPushes.set(command.name, command);
|
|
@@ -431,10 +491,11 @@ export class Reticle {
|
|
|
431
491
|
return;
|
|
432
492
|
p.setMode(modeForCommand(command.name));
|
|
433
493
|
this.#actHandle = undefined;
|
|
494
|
+
const actor = CommandActor.HARNESS === command.by ? LOG_ACTOR.HARNESS : LOG_ACTOR.AGENT;
|
|
434
495
|
if (command.name === ReticleCommand.ACT) {
|
|
435
496
|
const ref = str(command.args['ref']);
|
|
436
497
|
const label = refLabel(ref);
|
|
437
|
-
this.#actHandle = p.log(LOG_KIND.ACT, `${actionVerb(str(command.args['action']))} ${label}
|
|
498
|
+
this.#actHandle = p.log(LOG_KIND.ACT, `${actionVerb(str(command.args['action']))} ${label}`, undefined, actor);
|
|
438
499
|
await p.beforeAct(ref, str(command.args['action']), label);
|
|
439
500
|
}
|
|
440
501
|
else if (command.name === ReticleCommand.ACT_SEQUENCE) {
|
|
@@ -443,14 +504,17 @@ export class Reticle {
|
|
|
443
504
|
const s = step;
|
|
444
505
|
const ref = str(s.ref);
|
|
445
506
|
const label = refLabel(ref);
|
|
446
|
-
this.#actHandle = p.log(LOG_KIND.ACT, `${actionVerb(str(s.action))} ${label}
|
|
507
|
+
this.#actHandle = p.log(LOG_KIND.ACT, `${actionVerb(str(s.action))} ${label}`, undefined, actor);
|
|
447
508
|
await p.beforeAct(ref, str(s.action), label);
|
|
448
509
|
}
|
|
449
510
|
}
|
|
450
511
|
else {
|
|
451
512
|
const label = presentStatus(command.name, command.args);
|
|
452
513
|
p.status(label);
|
|
453
|
-
p.log(LOG_KIND.READ, label);
|
|
514
|
+
p.log(LOG_KIND.READ, label, undefined, actor);
|
|
454
515
|
}
|
|
455
516
|
}
|
|
456
517
|
}
|
|
518
|
+
function oneOf(values, raw) {
|
|
519
|
+
return Object.values(values).includes(raw) ? raw : undefined;
|
|
520
|
+
}
|
|
@@ -3,4 +3,4 @@ export declare const MARK_SUBMIT = "Add";
|
|
|
3
3
|
export declare const MARK_CANCEL = "Cancel";
|
|
4
4
|
export declare const MARK_PENDING_GLYPH = "+";
|
|
5
5
|
export declare const ANNOTATOR_CSS: string;
|
|
6
|
-
export declare const ANNOTATOR_ROOT_HTML
|
|
6
|
+
export declare const ANNOTATOR_ROOT_HTML: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EventType } from '@reticlehq/core';
|
|
2
|
+
import type { MarkForAgent } from './marks-for-agent.js';
|
|
2
3
|
interface MarkReport {
|
|
3
4
|
note: string;
|
|
4
5
|
anchor: string;
|
|
@@ -19,12 +20,18 @@ export interface AnnotatorChrome {
|
|
|
19
20
|
copyRow?: HTMLElement;
|
|
20
21
|
countEl?: HTMLElement;
|
|
21
22
|
onCount?: (count: number) => void;
|
|
23
|
+
onMarksChange?: (marks: readonly AnnotationItem[]) => void;
|
|
24
|
+
}
|
|
25
|
+
export interface AnnotationItem extends MarkForAgent {
|
|
26
|
+
id: string;
|
|
27
|
+
createdAt: number;
|
|
22
28
|
}
|
|
23
29
|
export declare class Annotator {
|
|
24
30
|
#private;
|
|
25
31
|
constructor(deps: AnnotatorDeps);
|
|
26
32
|
get active(): boolean;
|
|
27
33
|
get markCount(): number;
|
|
34
|
+
annotations(): AnnotationItem[];
|
|
28
35
|
mount(): void;
|
|
29
36
|
setAccent(hex: string): void;
|
|
30
37
|
attachChrome(chrome: AnnotatorChrome): void;
|
package/dist/review/annotator.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readTestId } from '../dom/addressing/testid-attr.js';
|
|
1
2
|
import { isSyntheticInput } from '../actions/synthetic/synthetic-input.js';
|
|
2
3
|
import { EventType } from '@reticlehq/core';
|
|
3
4
|
import { isReticleUi, isReticleOverlay } from '../dom/dom-ignore.js';
|
|
@@ -36,6 +37,7 @@ export class Annotator {
|
|
|
36
37
|
#clearBtn;
|
|
37
38
|
#copyRow;
|
|
38
39
|
#onChromeCount;
|
|
40
|
+
#onMarksChange;
|
|
39
41
|
#countEl;
|
|
40
42
|
#accent;
|
|
41
43
|
#ac;
|
|
@@ -53,6 +55,17 @@ export class Annotator {
|
|
|
53
55
|
get markCount() {
|
|
54
56
|
return this.#marks.length;
|
|
55
57
|
}
|
|
58
|
+
annotations() {
|
|
59
|
+
return this.#marks.map(({ id, createdAt, note, label, anchor, route, source }) => ({
|
|
60
|
+
id,
|
|
61
|
+
createdAt,
|
|
62
|
+
note,
|
|
63
|
+
label,
|
|
64
|
+
anchor,
|
|
65
|
+
route,
|
|
66
|
+
...(source === undefined ? {} : { source }),
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
56
69
|
mount() {
|
|
57
70
|
if (this.#root !== undefined || 'undefined' === typeof document)
|
|
58
71
|
return;
|
|
@@ -99,6 +112,7 @@ export class Annotator {
|
|
|
99
112
|
this.#clearBtn = chrome.clearBtn;
|
|
100
113
|
this.#copyRow = chrome.copyRow;
|
|
101
114
|
this.#onChromeCount = chrome.onCount;
|
|
115
|
+
this.#onMarksChange = chrome.onMarksChange;
|
|
102
116
|
this.#countEl = chrome.countEl;
|
|
103
117
|
this.#markersBtn?.addEventListener('click', (e) => {
|
|
104
118
|
e.stopPropagation();
|
|
@@ -184,6 +198,7 @@ export class Annotator {
|
|
|
184
198
|
}
|
|
185
199
|
this.#clearBtn?.toggleAttribute('disabled', 0 === n);
|
|
186
200
|
this.#onChromeCount?.(n);
|
|
201
|
+
this.#onMarksChange?.(this.annotations());
|
|
187
202
|
if (this.#copyRow !== undefined) {
|
|
188
203
|
this.#copyRow.hidden = 0 === n;
|
|
189
204
|
const text = this.#copyRow.querySelector('[data-reticle-marks-text]');
|
|
@@ -406,6 +421,7 @@ export class Annotator {
|
|
|
406
421
|
route: editing.route,
|
|
407
422
|
});
|
|
408
423
|
this.#report(note, editing.anchor, editing.label, this.#marks.indexOf(editing) + 1, editing.source);
|
|
424
|
+
this.#syncChrome();
|
|
409
425
|
this.#closePopover();
|
|
410
426
|
return;
|
|
411
427
|
}
|
|
@@ -480,8 +496,10 @@ export class Annotator {
|
|
|
480
496
|
pin.style.left = `${String((x / window.innerWidth) * 100)}%`;
|
|
481
497
|
pin.style.top = `${String(isFixed ? y : yDoc - window.scrollY)}px`;
|
|
482
498
|
this.#root.appendChild(pin);
|
|
499
|
+
const createdAt = this.#now();
|
|
483
500
|
const mark = {
|
|
484
|
-
id: `${resolved.anchor}:${String(
|
|
501
|
+
id: `${resolved.anchor}:${String(createdAt)}:${String(n)}`,
|
|
502
|
+
createdAt,
|
|
485
503
|
note,
|
|
486
504
|
label: resolved.label,
|
|
487
505
|
anchor: resolved.anchor,
|
|
@@ -593,7 +611,7 @@ function clampPop(x, y) {
|
|
|
593
611
|
return { left, top };
|
|
594
612
|
}
|
|
595
613
|
function describeEl(el) {
|
|
596
|
-
const testid = el
|
|
614
|
+
const testid = readTestId(el);
|
|
597
615
|
if (testid !== null && testid.length > 0)
|
|
598
616
|
return testid;
|
|
599
617
|
const tag = el.tagName.toLowerCase();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { readTestId } from '../dom/addressing/testid-attr.js';
|
|
1
2
|
import { MarkAnchorStrategy } from '@reticlehq/core';
|
|
2
3
|
import { AnchorStrategy, synthesizeAnchor, } from '../dom/addressing/auto-anchor.js';
|
|
3
4
|
import { getAccessibleName, getRole } from '../dom/a11y.js';
|
|
4
5
|
import { identifyComponent } from '../registry/stores/adapters.js';
|
|
5
6
|
import { sourceFor } from '../dom/addressing/source.js';
|
|
6
|
-
const TESTID_ATTR = 'data-testid';
|
|
7
7
|
const STRATEGY = {
|
|
8
8
|
[AnchorStrategy.TESTID]: MarkAnchorStrategy.TESTID,
|
|
9
9
|
[AnchorStrategy.COMPONENT]: MarkAnchorStrategy.COMPONENT,
|
|
@@ -16,7 +16,7 @@ function labelFor(el, role, name) {
|
|
|
16
16
|
return role.length > 0 ? role : el.tagName.toLowerCase();
|
|
17
17
|
}
|
|
18
18
|
export function resolveMarkAnchor(el) {
|
|
19
|
-
const testid = el
|
|
19
|
+
const testid = readTestId(el) ?? undefined;
|
|
20
20
|
const info = identifyComponent(el);
|
|
21
21
|
const component = info?.componentStack[0];
|
|
22
22
|
const source = sourceFor(el, info?.source);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const ReticleStorageKey: {
|
|
2
|
+
readonly SESSION: "__reticle_session";
|
|
3
|
+
readonly REF_BASE: "__reticle_ref_base";
|
|
4
|
+
readonly PRESENTER_LOG: "reticle-presenter-log";
|
|
5
|
+
readonly PRESENTER_LOG_OWNER: "reticle-presenter-log-owner";
|
|
6
|
+
readonly PRESENTER_SETTINGS: "reticle-presenter-settings";
|
|
7
|
+
readonly PRESENTER_MINIMISED: "reticle-presenter-minimised";
|
|
8
|
+
readonly CAROUSEL_DISMISSED: "reticle.carousel.dismissed";
|
|
9
|
+
readonly HARNESS_OFFER_DISMISSED: "reticle.harnessOffer.dismissed";
|
|
10
|
+
readonly ANNOTATION_HISTORY: "reticle.annotations.history.v1";
|
|
11
|
+
readonly RECENT_PLAYS: "reticle.flow.recent.v1";
|
|
12
|
+
};
|
|
13
|
+
export declare const TOUR_SEEN_KEY_PREFIX = "reticle.tour.seen.";
|
|
14
|
+
export declare function isReticleStorageKey(key: string): boolean;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const ReticleStorageKey = {
|
|
2
|
+
SESSION: '__reticle_session',
|
|
3
|
+
REF_BASE: '__reticle_ref_base',
|
|
4
|
+
PRESENTER_LOG: 'reticle-presenter-log',
|
|
5
|
+
PRESENTER_LOG_OWNER: 'reticle-presenter-log-owner',
|
|
6
|
+
PRESENTER_SETTINGS: 'reticle-presenter-settings',
|
|
7
|
+
PRESENTER_MINIMISED: 'reticle-presenter-minimised',
|
|
8
|
+
CAROUSEL_DISMISSED: 'reticle.carousel.dismissed',
|
|
9
|
+
HARNESS_OFFER_DISMISSED: 'reticle.harnessOffer.dismissed',
|
|
10
|
+
ANNOTATION_HISTORY: 'reticle.annotations.history.v1',
|
|
11
|
+
RECENT_PLAYS: 'reticle.flow.recent.v1',
|
|
12
|
+
};
|
|
13
|
+
export const TOUR_SEEN_KEY_PREFIX = 'reticle.tour.seen.';
|
|
14
|
+
const OWN_KEYS = new Set(Object.values(ReticleStorageKey));
|
|
15
|
+
export function isReticleStorageKey(key) {
|
|
16
|
+
return OWN_KEYS.has(key) || key.startsWith(TOUR_SEEN_KEY_PREFIX);
|
|
17
|
+
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reticlehq/browser",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.0",
|
|
4
4
|
"description": "Reticle browser SDK — installs observers, builds semantic snapshots, executes actions, talks to the bridge.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/reticle-inject.js",
|
|
7
8
|
"types": "./dist/index.d.ts",
|
|
8
9
|
"exports": {
|
|
9
10
|
".": {
|
|
@@ -17,7 +18,7 @@
|
|
|
17
18
|
}
|
|
18
19
|
},
|
|
19
20
|
"dependencies": {
|
|
20
|
-
"@reticlehq/core": "3.
|
|
21
|
+
"@reticlehq/core": "3.6.0"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
|
23
24
|
"@iconify-json/heroicons-outline": "^1.2.1",
|