@reticlehq/browser 2.14.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/actions-dom.d.ts +8 -0
- package/dist/actions/actions-dom.js +70 -3
- package/dist/actions/actions-press.d.ts +4 -0
- package/dist/actions/actions-press.js +46 -0
- package/dist/actions/actions.d.ts +1 -0
- package/dist/actions/actions.js +41 -8
- package/dist/actions/appeared-text.js +6 -0
- package/dist/actions/scroll.d.ts +8 -1
- package/dist/actions/scroll.js +28 -10
- package/dist/commands/commands.js +10 -3
- package/dist/dom/a11y.js +2 -2
- package/dist/dom/desktop-capture.js +1 -1
- package/dist/dom/dom-ignore.js +1 -1
- package/dist/dom/occlusion.js +31 -5
- package/dist/dom/paint-context.d.ts +6 -0
- package/dist/dom/paint-context.js +38 -0
- package/dist/dom/query.js +2 -2
- package/dist/dom/snapshot.js +1 -1
- package/dist/edit-epoch.d.ts +1 -1
- package/dist/edit-epoch.js +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.js +3 -5
- package/dist/observers/animation.js +1 -1
- package/dist/observers/blind-spots.js +1 -1
- package/dist/observers/dialogs.js +1 -1
- package/dist/observers/dom.js +28 -8
- package/dist/observers/download.js +1 -1
- package/dist/observers/health.js +1 -1
- package/dist/observers/{network-body.js → net-detail/network-body.js} +2 -2
- package/dist/observers/network-stream.js +2 -2
- package/dist/observers/network.d.ts +1 -1
- package/dist/observers/network.js +2 -2
- package/dist/observers/scroll.js +2 -2
- package/dist/presenter/chrome/layers.d.ts +2 -0
- package/dist/presenter/chrome/layers.js +2 -0
- package/dist/presenter/chrome/log-kinds.d.ts +12 -0
- package/dist/presenter/chrome/log-kinds.js +7 -0
- package/dist/presenter/{presenter-effects.js → chrome/presenter-effects.js} +1 -1
- package/dist/presenter/{presenter-log.d.ts → chrome/presenter-log.d.ts} +3 -12
- package/dist/presenter/{presenter-log.js → chrome/presenter-log.js} +4 -9
- package/dist/presenter/chrome/presenter-safe-html.d.ts +2 -0
- package/dist/presenter/chrome/presenter-safe-html.js +16 -0
- package/dist/presenter/{presenter-tally.js → chrome/presenter-tally.js} +1 -1
- package/dist/presenter/{presenter-heroicons-data.d.ts → icons/presenter-heroicons-data.d.ts} +1 -0
- package/dist/presenter/{presenter-heroicons-data.js → icons/presenter-heroicons-data.js} +1 -0
- package/dist/presenter/{presenter-icons.d.ts → icons/presenter-icons.d.ts} +1 -0
- package/dist/presenter/{presenter-icons.js → icons/presenter-icons.js} +1 -0
- package/dist/presenter/presenter-account-styles.d.ts +1 -0
- package/dist/presenter/presenter-account-styles.js +99 -0
- package/dist/presenter/presenter-account.d.ts +40 -0
- package/dist/presenter/presenter-account.js +178 -0
- package/dist/presenter/presenter-config.d.ts +9 -2
- package/dist/presenter/presenter-config.js +3 -1
- package/dist/presenter/presenter-controls.d.ts +1 -6
- package/dist/presenter/presenter-controls.js +7 -2
- package/dist/presenter/presenter-dock-layout.js +1 -1
- package/dist/presenter/presenter-drag.d.ts +1 -19
- package/dist/presenter/presenter-drag.js +3 -50
- package/dist/presenter/presenter-glow.js +1 -1
- package/dist/presenter/presenter-hud-position.d.ts +18 -0
- package/dist/presenter/presenter-hud-position.js +50 -0
- package/dist/presenter/presenter-report-styles.js +16 -1
- package/dist/presenter/presenter-report.d.ts +2 -1
- package/dist/presenter/presenter-report.js +29 -22
- package/dist/presenter/presenter-run-state.d.ts +1 -1
- package/dist/presenter/presenter-run-state.js +1 -1
- package/dist/presenter/presenter-settings-styles.js +2 -1
- package/dist/presenter/presenter-settings.d.ts +4 -0
- package/dist/presenter/presenter-settings.js +20 -2
- package/dist/presenter/presenter-shell-styles.js +21 -15
- package/dist/presenter/presenter-shell.d.ts +4 -0
- package/dist/presenter/presenter-shell.js +25 -4
- package/dist/presenter/presenter-styles.d.ts +2 -1
- package/dist/presenter/presenter-styles.js +6 -3
- package/dist/presenter/presenter-workspace.d.ts +4 -0
- package/dist/presenter/presenter-workspace.js +29 -2
- package/dist/presenter/presenter.d.ts +3 -3
- package/dist/presenter/presenter.js +25 -14
- package/dist/presenter/tour/tour-view.d.ts +33 -0
- package/dist/presenter/tour/tour-view.js +188 -0
- package/dist/presenter/tour/tour.d.ts +25 -0
- package/dist/presenter/tour/tour.js +245 -0
- package/dist/recorder/recorder.js +6 -0
- package/dist/registry/declared-channels.d.ts +2 -0
- package/dist/registry/declared-channels.js +14 -0
- package/dist/registry/declared-platform.d.ts +4 -0
- package/dist/registry/declared-platform.js +34 -0
- package/dist/registry/emitter.js +1 -1
- package/dist/registry/store-adapters.js +1 -1
- package/dist/registry/stores.js +1 -1
- package/dist/reticle-presenter-helpers.js +10 -6
- package/dist/reticle-singleton.d.ts +2 -0
- package/dist/reticle-singleton.js +3 -0
- package/dist/reticle.js +95 -35
- package/dist/review/annotator-styles.js +1 -1
- package/dist/review/annotator.js +2 -2
- package/dist/review/mark-anchor.js +3 -3
- package/dist/transport/transport.js +2 -2
- package/package.json +5 -4
- package/dist/presenter/presenter-test-helpers.d.ts +0 -14
- package/dist/presenter/presenter-test-helpers.js +0 -39
- /package/dist/actions/{synthetic-input.d.ts → synthetic/synthetic-input.d.ts} +0 -0
- /package/dist/actions/{synthetic-input.js → synthetic/synthetic-input.js} +0 -0
- /package/dist/dom/{auto-anchor.d.ts → addressing/auto-anchor.d.ts} +0 -0
- /package/dist/dom/{auto-anchor.js → addressing/auto-anchor.js} +0 -0
- /package/dist/dom/{refs.d.ts → addressing/refs.d.ts} +0 -0
- /package/dist/dom/{refs.js → addressing/refs.js} +0 -0
- /package/dist/dom/{source.d.ts → addressing/source.d.ts} +0 -0
- /package/dist/dom/{source.js → addressing/source.js} +0 -0
- /package/dist/observers/{network-body.d.ts → net-detail/network-body.d.ts} +0 -0
- /package/dist/observers/{network-redact.d.ts → net-detail/network-redact.d.ts} +0 -0
- /package/dist/observers/{network-redact.js → net-detail/network-redact.js} +0 -0
- /package/dist/presenter/{overlay.d.ts → chrome/overlay.d.ts} +0 -0
- /package/dist/presenter/{overlay.js → chrome/overlay.js} +0 -0
- /package/dist/presenter/{presenter-brand.d.ts → chrome/presenter-brand.d.ts} +0 -0
- /package/dist/presenter/{presenter-brand.js → chrome/presenter-brand.js} +0 -0
- /package/dist/presenter/{presenter-effects.d.ts → chrome/presenter-effects.d.ts} +0 -0
- /package/dist/presenter/{presenter-hud-chrome.d.ts → chrome/presenter-hud-chrome.d.ts} +0 -0
- /package/dist/presenter/{presenter-hud-chrome.js → chrome/presenter-hud-chrome.js} +0 -0
- /package/dist/presenter/{presenter-report-copy.d.ts → chrome/presenter-report-copy.d.ts} +0 -0
- /package/dist/presenter/{presenter-report-copy.js → chrome/presenter-report-copy.js} +0 -0
- /package/dist/presenter/{presenter-tally.d.ts → chrome/presenter-tally.d.ts} +0 -0
- /package/dist/presenter/{presenter-verbs.d.ts → chrome/presenter-verbs.d.ts} +0 -0
- /package/dist/presenter/{presenter-verbs.js → chrome/presenter-verbs.js} +0 -0
- /package/dist/registry/{adapters.d.ts → stores/adapters.d.ts} +0 -0
- /package/dist/registry/{adapters.js → stores/adapters.js} +0 -0
- /package/dist/timers/{native-console.d.ts → console/native-console.d.ts} +0 -0
- /package/dist/timers/{native-console.js → console/native-console.js} +0 -0
- /package/dist/timers/{native-timers.d.ts → native/native-timers.d.ts} +0 -0
- /package/dist/timers/{native-timers.js → native/native-timers.js} +0 -0
|
@@ -19,7 +19,9 @@ export const HEARTBEAT_MS = 1000;
|
|
|
19
19
|
export const IDLE_NOTICE_MS = 4000;
|
|
20
20
|
export const ACT_STRIP = {
|
|
21
21
|
READY: 'Ready',
|
|
22
|
-
|
|
22
|
+
PLANNING_PREFIX: 'planning next action · ',
|
|
23
|
+
STOPPED: 'stopped',
|
|
24
|
+
STOPPED_PREFIX: 'stopped · ',
|
|
23
25
|
NOW: 'now',
|
|
24
26
|
SINCE_LAST: ' since last action',
|
|
25
27
|
};
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { HumanControlKind, PresenterTone, SessionState } from '@reticlehq/core';
|
|
2
|
+
export type { ControlIntent, ControlHandler } from './presenter-config.js';
|
|
2
3
|
export declare const ENDED_FADE_MS = 4000;
|
|
3
|
-
export interface ControlIntent {
|
|
4
|
-
kind: HumanControlKind;
|
|
5
|
-
text?: string;
|
|
6
|
-
}
|
|
7
|
-
export type ControlHandler = (intent: ControlIntent) => void;
|
|
8
4
|
export declare const CONTROLS_CSS: string;
|
|
9
5
|
export declare const CONTROLS_TOOLBAR_HTML: string;
|
|
10
6
|
export declare const CONTROLS_BANNER_HTML = "<div data-reticle-banner class=\"reticle-banner\">Session ended</div>";
|
|
@@ -28,4 +24,3 @@ export declare class ControlPanel {
|
|
|
28
24
|
refilterFlows(): void;
|
|
29
25
|
setState(state: SessionState, text?: string, tone?: PresenterTone): void;
|
|
30
26
|
}
|
|
31
|
-
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { HumanControlKind, PresenterTone, SessionState } from '@reticlehq/core';
|
|
2
|
-
import { nativeSetTimeout, nativeClearTimeout } from '../timers/native-timers.js';
|
|
2
|
+
import { nativeSetTimeout, nativeClearTimeout } from '../timers/native/native-timers.js';
|
|
3
3
|
import { CHAT_TOGGLE_ATTR, CLEAR_MARKS_ATTR, MARKERS_BTN_ATTR } from './presenter-config.js';
|
|
4
|
-
import { PresenterIcon, PRESENTER_ICON_SIZE, hiIcon, hiIconHtml, hiToggleIconHtml, } from './presenter-icons.js';
|
|
4
|
+
import { PresenterIcon, PRESENTER_ICON_SIZE, hiIcon, hiIconHtml, hiToggleIconHtml, } from './icons/presenter-icons.js';
|
|
5
5
|
import { getPresenterSettings } from './presenter-settings.js';
|
|
6
6
|
import { mountWorkspaceSelector, workspaceRowHtml } from './presenter-workspace.js';
|
|
7
7
|
const DATA_RETICLE_STATE = 'data-reticle-state';
|
|
@@ -57,6 +57,11 @@ export const CONTROLS_CSS = `
|
|
|
57
57
|
background:rgba(255,255,255,.06);color:rgba(255,255,255,.7);cursor:pointer;line-height:0;transition:background .12s,color .12s;}
|
|
58
58
|
[data-reticle-chat-panel] .reticle-workspace-copy:hover:not(:disabled){background:rgba(255,255,255,.12);color:#fff;}
|
|
59
59
|
[data-reticle-chat-panel] .reticle-workspace-copy:disabled{opacity:.35;cursor:not-allowed;}
|
|
60
|
+
/* The account capsule, to the right of the menu title. Matches the local idiom in this block:
|
|
61
|
+
the workspace menu predates the design tokens used in the report panel and states its own
|
|
62
|
+
greys, so a token here would be the only one and would not match its neighbours. */
|
|
63
|
+
[data-reticle-chat-panel] .reticle-workspace-menu-actions{
|
|
64
|
+
display:flex;align-items:center;gap:6px;}
|
|
60
65
|
[data-reticle-chat-panel] .reticle-workspace-menu-row{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;padding:4px 0;}
|
|
61
66
|
[data-reticle-chat-panel] .reticle-workspace-menu-k{flex:none;color:rgba(255,255,255,.42);}
|
|
62
67
|
[data-reticle-chat-panel] .reticle-workspace-menu-v{min-width:0;text-align:right;color:rgba(255,255,255,.9);font-weight:500;word-break:break-all;}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CHAT_ATTR, CHAT_PANEL_ATTR, CHAT_PLACEMENT_ATTR, DOCK_ALIGN_ATTR, DOCK_ATTR, HUD_DOCK_MARGIN_PX, Placement, SETTINGS_ATTR, SETTINGS_PANEL_ATTR, SETTINGS_PLACEMENT_ATTR, } from './presenter-config.js';
|
|
2
|
-
import { applyHudPosition, isHudDragged, readHudPosition, relayoutHudPosition, } from './presenter-
|
|
2
|
+
import { applyHudPosition, isHudDragged, readHudPosition, relayoutHudPosition, } from './presenter-hud-position.js';
|
|
3
3
|
const HUD_ATTR = 'data-reticle-hud';
|
|
4
4
|
const DOCK_PANEL_GAP_PX = 8;
|
|
5
5
|
const DOCK_SETTINGS_GAP_PX = 12;
|
|
@@ -1,26 +1,8 @@
|
|
|
1
|
+
export { applyHudPosition, isHudDragged, readHudPosition, relayoutHudPosition, clampHudPosition, hudLayoutBox, resetHudDockPosition, } from './presenter-hud-position.js';
|
|
1
2
|
interface HudDragCallbacks {
|
|
2
3
|
onDragMove?: () => void;
|
|
3
4
|
onDragEnd?: (moved: boolean) => void;
|
|
4
5
|
}
|
|
5
|
-
export declare function isHudDragged(hud: HTMLElement): boolean;
|
|
6
|
-
export declare function clampHudPosition(left: number, top: number, width: number, height: number, viewportWidth: number, viewportHeight: number, margin?: number): {
|
|
7
|
-
left: number;
|
|
8
|
-
top: number;
|
|
9
|
-
};
|
|
10
|
-
export declare function applyHudPosition(hud: HTMLElement, left: number, top: number): void;
|
|
11
|
-
export declare function resetHudDockPosition(hud: HTMLElement): void;
|
|
12
|
-
export declare function hudLayoutBox(hud: HTMLElement): {
|
|
13
|
-
left: number;
|
|
14
|
-
top: number;
|
|
15
|
-
width: number;
|
|
16
|
-
height: number;
|
|
17
|
-
};
|
|
18
|
-
export declare function readHudPosition(hud: HTMLElement): {
|
|
19
|
-
left: number;
|
|
20
|
-
top: number;
|
|
21
|
-
};
|
|
22
|
-
export declare function relayoutHudPosition(hud: HTMLElement): void;
|
|
23
6
|
export declare function installHudPositionGuards(hud: HTMLElement, overlay: HTMLElement): () => void;
|
|
24
7
|
export declare function installHudDrag(hud: HTMLElement, head: HTMLElement, callbacks?: HudDragCallbacks): () => void;
|
|
25
8
|
export declare function installHudDragHandles(hud: HTMLElement, handles: HTMLElement[], callbacks?: HudDragCallbacks): () => void;
|
|
26
|
-
export {};
|
|
@@ -1,55 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HUD_DRAG_IGNORE_SEL, HUD_DRAG_THRESHOLD_PX, MIN_ATTR, CHAT_ATTR, SETTINGS_ATTR, } from './presenter-config.js';
|
|
2
2
|
import { scheduleSyncDockLayout } from './presenter-dock-layout.js';
|
|
3
|
+
import { applyHudPosition, clampHudPosition, hudLayoutBox, relayoutHudPosition, } from './presenter-hud-position.js';
|
|
4
|
+
export { applyHudPosition, isHudDragged, readHudPosition, relayoutHudPosition, clampHudPosition, hudLayoutBox, resetHudDockPosition, } from './presenter-hud-position.js';
|
|
3
5
|
const DRAG_HANDLE_DRAGGING_CLASS = 'reticle-drag-handle--dragging';
|
|
4
|
-
export function isHudDragged(hud) {
|
|
5
|
-
return '1' === hud.getAttribute(HUD_DRAGGED_ATTR);
|
|
6
|
-
}
|
|
7
|
-
export function clampHudPosition(left, top, width, height, viewportWidth, viewportHeight, margin = HUD_DOCK_MARGIN_PX) {
|
|
8
|
-
const minLeft = margin;
|
|
9
|
-
const minTop = margin;
|
|
10
|
-
const maxLeft = Math.max(minLeft, viewportWidth - width - margin);
|
|
11
|
-
const maxTop = Math.max(minTop, viewportHeight - height - margin);
|
|
12
|
-
return {
|
|
13
|
-
left: Math.max(minLeft, Math.min(left, maxLeft)),
|
|
14
|
-
top: Math.max(minTop, Math.min(top, maxTop)),
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
export function applyHudPosition(hud, left, top) {
|
|
18
|
-
hud.setAttribute(HUD_DRAGGED_ATTR, '1');
|
|
19
|
-
hud.style.setProperty(HUD_POS_X_VAR, `${String(left)}px`);
|
|
20
|
-
hud.style.setProperty(HUD_POS_Y_VAR, `${String(top)}px`);
|
|
21
|
-
}
|
|
22
|
-
export function resetHudDockPosition(hud) {
|
|
23
|
-
hud.removeAttribute(HUD_DRAGGED_ATTR);
|
|
24
|
-
hud.style.removeProperty(HUD_POS_X_VAR);
|
|
25
|
-
hud.style.removeProperty(HUD_POS_Y_VAR);
|
|
26
|
-
}
|
|
27
|
-
export function hudLayoutBox(hud) {
|
|
28
|
-
const rect = hud.getBoundingClientRect();
|
|
29
|
-
return {
|
|
30
|
-
left: rect.left,
|
|
31
|
-
top: rect.top,
|
|
32
|
-
width: rect.width,
|
|
33
|
-
height: rect.height,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
export function readHudPosition(hud) {
|
|
37
|
-
const x = hud.style.getPropertyValue(HUD_POS_X_VAR);
|
|
38
|
-
const y = hud.style.getPropertyValue(HUD_POS_Y_VAR);
|
|
39
|
-
if (x !== '' && y !== '') {
|
|
40
|
-
return { left: Number.parseFloat(x), top: Number.parseFloat(y) };
|
|
41
|
-
}
|
|
42
|
-
const rect = hud.getBoundingClientRect();
|
|
43
|
-
return { left: rect.left, top: rect.top };
|
|
44
|
-
}
|
|
45
|
-
export function relayoutHudPosition(hud) {
|
|
46
|
-
if (!isHudDragged(hud))
|
|
47
|
-
return;
|
|
48
|
-
const { left, top } = readHudPosition(hud);
|
|
49
|
-
const { width, height } = hudLayoutBox(hud);
|
|
50
|
-
const next = clampHudPosition(left, top, width, height, window.innerWidth, window.innerHeight);
|
|
51
|
-
applyHudPosition(hud, next.left, next.top);
|
|
52
|
-
}
|
|
53
6
|
export function installHudPositionGuards(hud, overlay) {
|
|
54
7
|
const scheduleRelayout = () => {
|
|
55
8
|
scheduleSyncDockLayout(hud, overlay);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PresenterMode } from '@reticlehq/core';
|
|
2
|
-
import { nativeSetTimeout, nativeClearTimeout } from '../timers/native-timers.js';
|
|
2
|
+
import { nativeSetTimeout, nativeClearTimeout } from '../timers/native/native-timers.js';
|
|
3
3
|
import { GlowPhase, BorderMode, DATA_BUSY, BUSY_ON, BUSY_OFF, GLOW_ON, GLOW_OFF, DATA_ON, } from './presenter-config.js';
|
|
4
4
|
export class GlowController {
|
|
5
5
|
#phase = GlowPhase.IDLE;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare function isHudDragged(hud: HTMLElement): boolean;
|
|
2
|
+
export declare function clampHudPosition(left: number, top: number, width: number, height: number, viewportWidth: number, viewportHeight: number, margin?: number): {
|
|
3
|
+
left: number;
|
|
4
|
+
top: number;
|
|
5
|
+
};
|
|
6
|
+
export declare function applyHudPosition(hud: HTMLElement, left: number, top: number): void;
|
|
7
|
+
export declare function resetHudDockPosition(hud: HTMLElement): void;
|
|
8
|
+
export declare function hudLayoutBox(hud: HTMLElement): {
|
|
9
|
+
left: number;
|
|
10
|
+
top: number;
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
};
|
|
14
|
+
export declare function readHudPosition(hud: HTMLElement): {
|
|
15
|
+
left: number;
|
|
16
|
+
top: number;
|
|
17
|
+
};
|
|
18
|
+
export declare function relayoutHudPosition(hud: HTMLElement): void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { HUD_DOCK_MARGIN_PX, HUD_DRAGGED_ATTR, HUD_POS_X_VAR, HUD_POS_Y_VAR, } from './presenter-config.js';
|
|
2
|
+
export function isHudDragged(hud) {
|
|
3
|
+
return '1' === hud.getAttribute(HUD_DRAGGED_ATTR);
|
|
4
|
+
}
|
|
5
|
+
export function clampHudPosition(left, top, width, height, viewportWidth, viewportHeight, margin = HUD_DOCK_MARGIN_PX) {
|
|
6
|
+
const minLeft = margin;
|
|
7
|
+
const minTop = margin;
|
|
8
|
+
const maxLeft = Math.max(minLeft, viewportWidth - width - margin);
|
|
9
|
+
const maxTop = Math.max(minTop, viewportHeight - height - margin);
|
|
10
|
+
return {
|
|
11
|
+
left: Math.max(minLeft, Math.min(left, maxLeft)),
|
|
12
|
+
top: Math.max(minTop, Math.min(top, maxTop)),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function applyHudPosition(hud, left, top) {
|
|
16
|
+
hud.setAttribute(HUD_DRAGGED_ATTR, '1');
|
|
17
|
+
hud.style.setProperty(HUD_POS_X_VAR, `${String(left)}px`);
|
|
18
|
+
hud.style.setProperty(HUD_POS_Y_VAR, `${String(top)}px`);
|
|
19
|
+
}
|
|
20
|
+
export function resetHudDockPosition(hud) {
|
|
21
|
+
hud.removeAttribute(HUD_DRAGGED_ATTR);
|
|
22
|
+
hud.style.removeProperty(HUD_POS_X_VAR);
|
|
23
|
+
hud.style.removeProperty(HUD_POS_Y_VAR);
|
|
24
|
+
}
|
|
25
|
+
export function hudLayoutBox(hud) {
|
|
26
|
+
const rect = hud.getBoundingClientRect();
|
|
27
|
+
return {
|
|
28
|
+
left: rect.left,
|
|
29
|
+
top: rect.top,
|
|
30
|
+
width: rect.width,
|
|
31
|
+
height: rect.height,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function readHudPosition(hud) {
|
|
35
|
+
const x = hud.style.getPropertyValue(HUD_POS_X_VAR);
|
|
36
|
+
const y = hud.style.getPropertyValue(HUD_POS_Y_VAR);
|
|
37
|
+
if (x !== '' && y !== '') {
|
|
38
|
+
return { left: Number.parseFloat(x), top: Number.parseFloat(y) };
|
|
39
|
+
}
|
|
40
|
+
const rect = hud.getBoundingClientRect();
|
|
41
|
+
return { left: rect.left, top: rect.top };
|
|
42
|
+
}
|
|
43
|
+
export function relayoutHudPosition(hud) {
|
|
44
|
+
if (!isHudDragged(hud))
|
|
45
|
+
return;
|
|
46
|
+
const { left, top } = readHudPosition(hud);
|
|
47
|
+
const { width, height } = hudLayoutBox(hud);
|
|
48
|
+
const next = clampHudPosition(left, top, width, height, window.innerWidth, window.innerHeight);
|
|
49
|
+
applyHudPosition(hud, next.left, next.top);
|
|
50
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HUD_DROP_SHADOW } from './presenter-hud-chrome.js';
|
|
1
|
+
import { HUD_DROP_SHADOW } from './chrome/presenter-hud-chrome.js';
|
|
2
2
|
import { DOCK_ALIGN_ATTR, DOCK_ATTR, REPORT_ATTR, REPORT_PANEL_ATTR } from './presenter-config.js';
|
|
3
3
|
const OVERLAY = 'data-reticle-overlay';
|
|
4
4
|
export const REPORT_CSS = `
|
|
@@ -123,4 +123,19 @@ export const REPORT_CSS = `
|
|
|
123
123
|
[${REPORT_PANEL_ATTR}] .reticle-report-links a{
|
|
124
124
|
color:var(--reticle-faint);font-size:10.5px;text-decoration:none;}
|
|
125
125
|
[${REPORT_PANEL_ATTR}] .reticle-report-links a:hover{color:var(--reticle-fg);text-decoration:underline;}
|
|
126
|
+
|
|
127
|
+
/* Who this record belongs to, and the push-now control. Tokens only — no literal colours. */
|
|
128
|
+
[${REPORT_PANEL_ATTR}] .reticle-report-identity{
|
|
129
|
+
display:flex;align-items:center;justify-content:flex-end;gap:6px;padding:10px 14px 0;min-height:0;}
|
|
130
|
+
[${REPORT_PANEL_ATTR}] .reticle-report-identity:empty{display:none;}
|
|
131
|
+
[${REPORT_PANEL_ATTR}] .reticle-sync-now{
|
|
132
|
+
display:inline-flex;align-items:center;justify-content:center;
|
|
133
|
+
border:none;background:transparent;color:var(--reticle-faint);cursor:pointer;line-height:0;padding:2px;}
|
|
134
|
+
[${REPORT_PANEL_ATTR}] .reticle-sync-now:hover{color:var(--reticle-fg);}
|
|
135
|
+
/* The one moment this control has an opinion: it says it is going, not that it has arrived. */
|
|
136
|
+
[${REPORT_PANEL_ATTR}] .reticle-sync-now[data-syncing="1"]{
|
|
137
|
+
color:var(--reticle-c-active);animation:reticle-sync-spin 900ms linear infinite;}
|
|
138
|
+
@keyframes reticle-sync-spin{to{transform:rotate(360deg);}}
|
|
139
|
+
@media (prefers-reduced-motion:reduce){
|
|
140
|
+
[${REPORT_PANEL_ATTR}] .reticle-sync-now[data-syncing="1"]{animation:none;}}
|
|
126
141
|
`;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { type AccountState, type ImpactScope, type ImpactSnapshot } from '@reticlehq/core';
|
|
2
2
|
export declare function reportPanelHtml(): string;
|
|
3
|
-
export declare function reportBodyHtml(scope: ImpactScope, dashboardUrl?: string, account?: AccountState): string;
|
|
3
|
+
export declare function reportBodyHtml(scope: ImpactScope, dashboardUrl?: string, account?: AccountState, projectName?: string): string;
|
|
4
4
|
interface ReportHost {
|
|
5
5
|
onBeforeOpen?: () => void;
|
|
6
|
+
onSyncNow?: () => void;
|
|
6
7
|
}
|
|
7
8
|
export declare class PresenterReport {
|
|
8
9
|
#private;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { IMPACT_DEFECT_LIMIT, } from '@reticlehq/core';
|
|
2
|
-
import { PresenterIcon, PRESENTER_ICON_SIZE, hiIconHtml } from './presenter-icons.js';
|
|
3
|
-
import { HUD_SURFACE_CLASS } from './presenter-hud-chrome.js';
|
|
2
|
+
import { PresenterIcon, PRESENTER_ICON_SIZE, hiIconHtml } from './icons/presenter-icons.js';
|
|
3
|
+
import { HUD_SURFACE_CLASS } from './chrome/presenter-hud-chrome.js';
|
|
4
|
+
import { esc, isSafeDashboardUrl } from './chrome/presenter-safe-html.js';
|
|
5
|
+
import { ACCOUNT_SIGNIN_ATTR, ACCOUNT_TEXT, SYNC_BTN_ATTR, accountControlHtml, syncButtonHtml, } from './presenter-account.js';
|
|
4
6
|
import { REPORT_PANEL_ATTR, REPORT_ATTR, REPORT_CLOSE_ATTR } from './presenter-config.js';
|
|
5
|
-
import { REPORT_LINKS, REPORT_TEXT, buildLinkedInShareUrl, buildReferralText, buildShareText, buildXShareUrl, compactDuration, compactNumber, } from './presenter-report-copy.js';
|
|
7
|
+
import { REPORT_LINKS, REPORT_TEXT, buildLinkedInShareUrl, buildReferralText, buildShareText, buildXShareUrl, compactDuration, compactNumber, } from './chrome/presenter-report-copy.js';
|
|
6
8
|
const SCOPE_ATTR = 'data-reticle-report-scope';
|
|
7
9
|
const SHARE_X_ATTR = 'data-reticle-share-x';
|
|
8
10
|
const SHARE_IN_ATTR = 'data-reticle-share-in';
|
|
@@ -55,22 +57,6 @@ function chart(scope) {
|
|
|
55
57
|
.join('');
|
|
56
58
|
return `<div class="reticle-report-chart-wrap"><span class="reticle-report-section">${REPORT_TEXT.CHART}</span><div class="reticle-report-chart">${bars}</div></div>`;
|
|
57
59
|
}
|
|
58
|
-
function esc(value) {
|
|
59
|
-
return value
|
|
60
|
-
.replace(/&/g, '&')
|
|
61
|
-
.replace(/</g, '<')
|
|
62
|
-
.replace(/>/g, '>')
|
|
63
|
-
.replace(/"/g, '"');
|
|
64
|
-
}
|
|
65
|
-
function isSafeDashboardUrl(raw) {
|
|
66
|
-
try {
|
|
67
|
-
const scheme = new URL(raw).protocol;
|
|
68
|
-
return 'https:' === scheme || 'http:' === scheme;
|
|
69
|
-
}
|
|
70
|
-
catch {
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
60
|
function defects(scope, dashboardUrl) {
|
|
75
61
|
const list = (scope.defects ?? []).slice(0, IMPACT_DEFECT_LIMIT);
|
|
76
62
|
if (0 === list.length)
|
|
@@ -95,7 +81,7 @@ function defects(scope, dashboardUrl) {
|
|
|
95
81
|
: `<a class="reticle-report-defects-more" href="${esc(dashboardUrl)}" target="_blank" rel="noreferrer noopener">${REPORT_TEXT.DEFECTS_MORE}${scope.counts.failed > list.length ? ` (${String(scope.counts.failed)})` : ''}</a>`;
|
|
96
82
|
return `<div class="reticle-report-defects-wrap"><span class="reticle-report-section">${REPORT_TEXT.DEFECTS}</span><ul class="reticle-report-defects">${rows}</ul>${more}</div>`;
|
|
97
83
|
}
|
|
98
|
-
export function reportBodyHtml(scope, dashboardUrl, account) {
|
|
84
|
+
export function reportBodyHtml(scope, dashboardUrl, account, projectName) {
|
|
99
85
|
const c = scope.counts;
|
|
100
86
|
if (0 === c.calls)
|
|
101
87
|
return `<p class="reticle-report-empty">${REPORT_TEXT.EMPTY}</p>`;
|
|
@@ -118,7 +104,8 @@ export function reportBodyHtml(scope, dashboardUrl, account) {
|
|
|
118
104
|
card(compactNumber(scope.savings.tokens.value), REPORT_TEXT.SAVED_TOKENS, scope.savings.tokens.basis),
|
|
119
105
|
card(compactDuration(scope.savings.minutes.value * 60_000), REPORT_TEXT.SAVED_MINUTES, scope.savings.minutes.basis),
|
|
120
106
|
].join('');
|
|
121
|
-
|
|
107
|
+
const identity = `<div class="reticle-report-identity">${accountControlHtml(account, { dashboardUrl, projectName, verdicts: c.verdicts, defects: c.failed })}${syncButtonHtml(dashboardUrl)}</div>`;
|
|
108
|
+
return `${identity}${streak}${hero}${verdicts}<div class="reticle-report-grid">${cards}</div>${defects(scope, dashboardUrl)}${chart(scope)}${localOnly(scope, dashboardUrl, account)}`;
|
|
122
109
|
}
|
|
123
110
|
function localOnly(scope, dashboardUrl, account) {
|
|
124
111
|
if (dashboardUrl !== undefined)
|
|
@@ -132,6 +119,8 @@ function localOnly(scope, dashboardUrl, account) {
|
|
|
132
119
|
: [REPORT_TEXT.LOCAL_ONLY, REPORT_TEXT.LOCAL_ONLY_ACTION, REPORT_TEXT.LOCAL_ONLY_TAIL];
|
|
133
120
|
return `<p class="reticle-report-local-only">${lead} <code>${action}</code> ${tail}</p>`;
|
|
134
121
|
}
|
|
122
|
+
const SYNC_SPIN_MS = 1_200;
|
|
123
|
+
const SYNCING_ATTR = 'data-syncing';
|
|
135
124
|
export class PresenterReport {
|
|
136
125
|
#panel;
|
|
137
126
|
#body;
|
|
@@ -175,6 +164,24 @@ export class PresenterReport {
|
|
|
175
164
|
e.stopPropagation();
|
|
176
165
|
void this.#copy(buildReferralText(), e.currentTarget);
|
|
177
166
|
});
|
|
167
|
+
root.addEventListener('click', (e) => {
|
|
168
|
+
const target = e.target;
|
|
169
|
+
if (!(target instanceof Element))
|
|
170
|
+
return;
|
|
171
|
+
const signin = target.closest(`[${ACCOUNT_SIGNIN_ATTR}]`);
|
|
172
|
+
if (signin !== null) {
|
|
173
|
+
e.stopPropagation();
|
|
174
|
+
void this.#copy(ACCOUNT_TEXT.SIGNIN_COMMAND, signin);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const sync = target.closest(`[${SYNC_BTN_ATTR}]`);
|
|
178
|
+
if (sync !== null) {
|
|
179
|
+
e.stopPropagation();
|
|
180
|
+
this.#host.onSyncNow?.();
|
|
181
|
+
sync.setAttribute(SYNCING_ATTR, '1');
|
|
182
|
+
setTimeout(() => sync.removeAttribute(SYNCING_ATTR), SYNC_SPIN_MS);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
178
185
|
}
|
|
179
186
|
setSnapshot(snapshot) {
|
|
180
187
|
this.#snapshot = snapshot;
|
|
@@ -229,7 +236,7 @@ export class PresenterReport {
|
|
|
229
236
|
this.#body.innerHTML =
|
|
230
237
|
scope === undefined
|
|
231
238
|
? `<p class="reticle-report-empty">${REPORT_TEXT.EMPTY}</p>`
|
|
232
|
-
: reportBodyHtml(scope, this.#snapshot?.dashboardUrl, this.#snapshot?.account);
|
|
239
|
+
: reportBodyHtml(scope, this.#snapshot?.dashboardUrl, this.#snapshot?.account, this.#snapshot?.projectName);
|
|
233
240
|
}
|
|
234
241
|
#openShare(url) {
|
|
235
242
|
window.open(url, '_blank', 'noopener,noreferrer');
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SessionState } from '@reticlehq/core';
|
|
2
|
-
import { type LogKind, type LogResult } from './presenter-log.js';
|
|
2
|
+
import { type LogKind, type LogResult } from './chrome/presenter-log.js';
|
|
3
3
|
import { type Capabilities } from '../registry/capabilities.js';
|
|
4
4
|
export interface PresenterRunState {
|
|
5
5
|
session: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SessionState } from '@reticlehq/core';
|
|
2
|
-
import { LOG_KIND, LOG_RESULT } from './presenter-log.js';
|
|
2
|
+
import { LOG_KIND, LOG_RESULT } from './chrome/presenter-log.js';
|
|
3
3
|
import { getCapabilities } from '../registry/capabilities.js';
|
|
4
4
|
export function buildRunState(input) {
|
|
5
5
|
const start = input.startMs ?? input.now;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SETTINGS_PANEL_ATTR, SETTINGS_ATTR, DOCK_ATTR, DOCK_ALIGN_ATTR, SETTINGS_PLACEMENT_ATTR, } from './presenter-config.js';
|
|
2
|
-
import { HUD_DROP_SHADOW, HUD_SURFACE_CLASS, HUD_SURFACE_PAINT } from './presenter-hud-chrome.js';
|
|
2
|
+
import { HUD_DROP_SHADOW, HUD_SURFACE_CLASS, HUD_SURFACE_PAINT, } from './chrome/presenter-hud-chrome.js';
|
|
3
3
|
export const SETTINGS_CSS = `
|
|
4
4
|
[${'data-reticle-overlay'}][${SETTINGS_ATTR}="1"] [${'data-reticle-chat-panel'}]{
|
|
5
5
|
display:none !important;visibility:hidden !important;pointer-events:none !important;}
|
|
@@ -149,4 +149,5 @@ export const SETTINGS_CSS = `
|
|
|
149
149
|
display:none;pointer-events:none;}
|
|
150
150
|
[${'data-reticle-overlay'}][data-reticle-hidden="1"] [${DOCK_ATTR}],
|
|
151
151
|
[${'data-reticle-overlay'}][data-reticle-hidden="1"] [${SETTINGS_PANEL_ATTR}]{display:none !important;}
|
|
152
|
+
|
|
152
153
|
`;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { SETTINGS_CSS } from './presenter-settings-styles.js';
|
|
2
|
+
import type { AccountState } from '@reticlehq/core';
|
|
3
|
+
import { type AccountDetails } from './presenter-account.js';
|
|
2
4
|
export { SETTINGS_CSS };
|
|
3
5
|
export declare const OutputDetail: {
|
|
4
6
|
readonly MINIMAL: "minimal";
|
|
@@ -38,6 +40,8 @@ export interface PresenterSettings {
|
|
|
38
40
|
}
|
|
39
41
|
export declare function getPresenterSettings(): PresenterSettings;
|
|
40
42
|
export declare function loadPresenterSettings(): PresenterSettings;
|
|
43
|
+
export declare const SETTINGS_ACCOUNT_ATTR = "data-reticle-settings-account";
|
|
44
|
+
export declare function paintSettingsAccount(root: HTMLElement, account: AccountState | undefined, dashboardUrl: string | undefined, details?: AccountDetails): void;
|
|
41
45
|
export declare function settingsPanelHtml(): string;
|
|
42
46
|
export interface SettingsHost {
|
|
43
47
|
onHideUntilRestart?: () => void;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { SETTINGS_ATTR, SETTINGS_BTN_ATTR, SETTINGS_PANEL_ATTR, SETTINGS_CLOSE_ATTR, SETTING_KEY_ATTR, SETTINGS_STORAGE_KEY, AMBIENT_GLOW_ATTR, BLOCK_ATTR, HIDDEN_UNTIL_RESTART_ATTR, LOG_TIMESTAMPS_ATTR, REDUCE_MOTION_ATTR, DOCK_ATTR, MCP_DOCS_URL, } from './presenter-config.js';
|
|
2
|
-
import { PresenterIcon, PRESENTER_ICON_SIZE, setHiIcon, hiIconHtml } from './presenter-icons.js';
|
|
3
|
-
import { HUD_SURFACE_CLASS } from './presenter-hud-chrome.js';
|
|
2
|
+
import { PresenterIcon, PRESENTER_ICON_SIZE, setHiIcon, hiIconHtml, } from './icons/presenter-icons.js';
|
|
3
|
+
import { HUD_SURFACE_CLASS } from './chrome/presenter-hud-chrome.js';
|
|
4
4
|
import { resetHudDockPosition } from './presenter-drag.js';
|
|
5
5
|
import { findDock, scheduleSyncDockLayout } from './presenter-dock-layout.js';
|
|
6
6
|
import { SETTINGS_CSS } from './presenter-settings-styles.js';
|
|
7
|
+
import { accountControlHtml } from './presenter-account.js';
|
|
7
8
|
export { SETTINGS_CSS };
|
|
8
9
|
export const OutputDetail = {
|
|
9
10
|
MINIMAL: 'minimal',
|
|
@@ -146,6 +147,18 @@ function settingsCheckRow(key, label, checked) {
|
|
|
146
147
|
<span class="reticle-settings-check-label">${label}</span>
|
|
147
148
|
</label>`;
|
|
148
149
|
}
|
|
150
|
+
export const SETTINGS_ACCOUNT_ATTR = 'data-reticle-settings-account';
|
|
151
|
+
const SETTINGS_ACCOUNT_ROW_ATTR = 'data-reticle-settings-account-row';
|
|
152
|
+
const ACCOUNT_HELP = 'Whether this machine is signed in to a Reticle workspace. Signing in happens in your terminal.';
|
|
153
|
+
export function paintSettingsAccount(root, account, dashboardUrl, details = {}) {
|
|
154
|
+
const row = root.querySelector(`[${SETTINGS_ACCOUNT_ROW_ATTR}]`);
|
|
155
|
+
const slot = root.querySelector(`[${SETTINGS_ACCOUNT_ATTR}]`);
|
|
156
|
+
if (!(row instanceof HTMLElement) || !(slot instanceof HTMLElement))
|
|
157
|
+
return;
|
|
158
|
+
const html = accountControlHtml(account, { ...details, dashboardUrl }, true);
|
|
159
|
+
row.hidden = 0 === html.length;
|
|
160
|
+
slot.innerHTML = html;
|
|
161
|
+
}
|
|
149
162
|
export function settingsPanelHtml() {
|
|
150
163
|
const close = hiIconHtml(PresenterIcon.REMOVE, PRESENTER_ICON_SIZE.MIN);
|
|
151
164
|
const caret = hiIconHtml(PresenterIcon.CARET_RIGHT, PRESENTER_ICON_SIZE.HELP);
|
|
@@ -179,6 +192,11 @@ export function settingsPanelHtml() {
|
|
|
179
192
|
${settingsCheckRow('clearOnCopy', 'Clear on copy/send', false)}
|
|
180
193
|
${settingsToggleRow('hideUntilRestart', 'Hide Until Restart', hideHelp)}
|
|
181
194
|
${settingsToggleRow('reduceMotion', 'Reduce motion', motionHelp)}
|
|
195
|
+
<div class="reticle-settings-section">Account</div>
|
|
196
|
+
<div class="reticle-settings-row" ${SETTINGS_ACCOUNT_ROW_ATTR} hidden>
|
|
197
|
+
${settingsLabel('Workspace', ACCOUNT_HELP)}
|
|
198
|
+
<span ${SETTINGS_ACCOUNT_ATTR}></span>
|
|
199
|
+
</div>
|
|
182
200
|
<div class="reticle-settings-section">Status theme</div>
|
|
183
201
|
${settingsToggleRow('ambientGlow', 'Page glow', glowHelp)}
|
|
184
202
|
<div class="reticle-settings-themes" data-reticle-settings-themes></div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { LOG_TIME_ATTR } from './presenter-log.js';
|
|
1
|
+
import { LOG_TIME_ATTR } from './chrome/presenter-log.js';
|
|
2
2
|
import { Z_HUD_TOOLTIP } from './presenter-config.js';
|
|
3
3
|
import { CHAT_ATTR, CHAT_PILL_ATTR, CHAT_PLACEMENT_ATTR, DOCK_ALIGN_ATTR, DOCK_ATTR, LOG_TIMESTAMPS_ATTR, MIN_ATTR, REDUCE_MOTION_ATTR, LIVENESS_ATTR, } from './presenter-config.js';
|
|
4
|
-
import { HUD_DROP_SHADOW, HUD_SURFACE_FILL } from './presenter-hud-chrome.js';
|
|
4
|
+
import { HUD_DROP_SHADOW, HUD_SURFACE_FILL } from './chrome/presenter-hud-chrome.js';
|
|
5
5
|
const OVERLAY = 'data-reticle-overlay';
|
|
6
6
|
const HUD = 'data-reticle-hud';
|
|
7
7
|
const CHAT_PANEL = 'data-reticle-chat-panel';
|
|
@@ -86,8 +86,8 @@ export const SHELL_CSS = `
|
|
|
86
86
|
/**
|
|
87
87
|
* Minimising the chat leaves a CAPSULE, not a hole: the same glass, the same state dot, the last
|
|
88
88
|
* thing the agent did - sitting directly above the toolbar capsule and reopening the panel when
|
|
89
|
-
* clicked.
|
|
90
|
-
*
|
|
89
|
+
* clicked. Leaving the toolbar alone above an empty gap would make a minimised session look
|
|
90
|
+
* identical to no session at all.
|
|
91
91
|
*/
|
|
92
92
|
[${CHAT_PILL_ATTR}]{
|
|
93
93
|
display:none;position:absolute;right:0;left:auto;bottom:calc(100% + 8px);z-index:5;
|
|
@@ -115,6 +115,13 @@ export const SHELL_CSS = `
|
|
|
115
115
|
flex:none;display:flex;align-items:center;gap:8px;padding:11px 44px 9px 14px;
|
|
116
116
|
border-bottom:1px solid rgba(255,255,255,.06);}
|
|
117
117
|
[${CHAT_PANEL}] .reticle-chat-brand{display:inline-flex;align-items:center;gap:7px;color:var(--reticle-fg);}
|
|
118
|
+
/* The account capsule lives in the header, not the toolbar. The toolbar row is already 13px over its
|
|
119
|
+
own width, so a 20px avatar there pushed the close button outside the panel. The header has the
|
|
120
|
+
space, is visible under exactly the same condition, and is where an account avatar belongs anyway.
|
|
121
|
+
margin-left:auto right-aligns it; the head reserves 44px of right padding for the caret above it,
|
|
122
|
+
so the two never overlap. The :empty rule keeps the gap closed when no account state was sent. */
|
|
123
|
+
[${CHAT_PANEL}] .reticle-head-account{margin-left:auto;display:inline-flex;align-items:center;}
|
|
124
|
+
[${CHAT_PANEL}] .reticle-head-account:empty{display:none;}
|
|
118
125
|
[${CHAT_PANEL}] .reticle-chat-brand .reticle-mark{height:14px;width:auto;}
|
|
119
126
|
[${CHAT_PANEL}] .reticle-chat-brandname{font-size:12.5px;font-weight:600;letter-spacing:.01em;}
|
|
120
127
|
/* No state word here: the activity strip immediately below already says "idle · 21s", and the
|
|
@@ -234,6 +241,7 @@ export const SHELL_CSS = `
|
|
|
234
241
|
padding:2px;border-radius:999px;background:rgba(0,0,0,.2);}
|
|
235
242
|
[${HUD}] .reticle-toolbar-chrome{display:inline-flex;align-items:center;gap:2px;flex:none;}
|
|
236
243
|
[${HUD}] .reticle-tb-sep{width:1px;height:14px;background:rgba(255,255,255,.12);margin:0 4px;flex:none;align-self:center;}
|
|
244
|
+
|
|
237
245
|
[${HUD}] .reticle-tb-wrap{position:relative;display:flex;align-items:center;justify-content:center;overflow:visible;}
|
|
238
246
|
[${HUD}] .reticle-tb-btn{
|
|
239
247
|
flex:none;display:inline-flex;align-items:center;justify-content:center;
|
|
@@ -259,10 +267,9 @@ export const SHELL_CSS = `
|
|
|
259
267
|
[${HUD}] .reticle-hi-toggle .reticle-hi-icon--solid svg{
|
|
260
268
|
transform:scale(1.12);transform-origin:center;}
|
|
261
269
|
/*
|
|
262
|
-
* Active toggles keep the OUTLINE icon.
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
* which is enough and does not change the icon's weight.
|
|
270
|
+
* Active toggles keep the OUTLINE icon. The solid heroicon is a filled glyph next to 1.5px strokes
|
|
271
|
+
* everywhere else, so a pressed button reads as a heavier typeface rather than as a state. Accent
|
|
272
|
+
* colour and the background above already carry the state without changing the icon's weight.
|
|
266
273
|
*/
|
|
267
274
|
[${HUD}] .reticle-tb-btn--toggle[data-active="1"] .reticle-hi-icon--outline{opacity:1;}
|
|
268
275
|
[${HUD}] .reticle-tb-btn--toggle .reticle-hi-icon--solid{opacity:0;}
|
|
@@ -274,10 +281,10 @@ export const SHELL_CSS = `
|
|
|
274
281
|
/**
|
|
275
282
|
* The toolbar is a FIXED number of slots.
|
|
276
283
|
*
|
|
277
|
-
* Copy and Export appear when a session ends, and
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
284
|
+
* Copy and Export appear when a session ends, and the bar is already full - eleven icons in a pill
|
|
285
|
+
* sized for nine renders the last one outside the rounded box. They take the two slots Pause and End
|
|
286
|
+
* vacate: neither can do anything to an ended session, so the bar swaps two dead controls for two
|
|
287
|
+
* live ones and never changes width.
|
|
281
288
|
*/
|
|
282
289
|
[${HUD}] .reticle-tb-btn--export{display:none;}
|
|
283
290
|
[${OVERLAY}][${STATE}="ended"] [${HUD}] .reticle-tb-btn--export{display:inline-flex;}
|
|
@@ -307,9 +314,8 @@ export const SHELL_CSS = `
|
|
|
307
314
|
* The mode, ON the status row rather than under it.
|
|
308
315
|
*
|
|
309
316
|
* The action text beside it is flex:1, so this claims the right edge of the row and takes its space
|
|
310
|
-
* from the elided action text. Nothing above or below moves:
|
|
311
|
-
*
|
|
312
|
-
* second UI appearing and leaving.
|
|
317
|
+
* from the elided action text. Nothing above or below moves: growing and shrinking by the height of
|
|
318
|
+
* this pill on every tool call makes one status line look like a second UI appearing and leaving.
|
|
313
319
|
*/
|
|
314
320
|
[${DOCK_ATTR}] .reticle-chip{display:none;flex:none;align-items:center;gap:4px;font-size:8px;font-weight:600;letter-spacing:.06em;
|
|
315
321
|
height:16px;padding:0 7px;line-height:1;border-radius:999px;text-transform:uppercase;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { PresenterReport } from './presenter-report.js';
|
|
2
|
+
import type { AccountState } from '@reticlehq/core';
|
|
3
|
+
import { type AccountDetails } from './presenter-account.js';
|
|
2
4
|
import { type SettingsHost } from './presenter-settings.js';
|
|
3
5
|
interface HudShellCallbacks {
|
|
4
6
|
onChatOpen?: () => void;
|
|
@@ -6,10 +8,12 @@ interface HudShellCallbacks {
|
|
|
6
8
|
onExpand?: () => void;
|
|
7
9
|
onAnnotateToggle?: (on: boolean) => void;
|
|
8
10
|
onCollapse?: () => void;
|
|
11
|
+
onSyncNow?: () => void;
|
|
9
12
|
settings?: SettingsHost;
|
|
10
13
|
}
|
|
11
14
|
export declare class HudShell {
|
|
12
15
|
#private;
|
|
16
|
+
paintAccount(account: AccountState | undefined, dashboardUrl: string | undefined, details?: AccountDetails): void;
|
|
13
17
|
constructor(callbacks?: HudShellCallbacks);
|
|
14
18
|
static dockHtml(actStripHtml: string, bannerHtml: string, logAttr: string, flowsHtml: string, footHtml: string): string;
|
|
15
19
|
get report(): PresenterReport;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { PresenterReport, reportPanelHtml } from './presenter-report.js';
|
|
2
|
+
import { paintToolbarAccount, TOOLBAR_ACCOUNT_ATTR } from './presenter-workspace.js';
|
|
3
|
+
import { mountAccountControl } from './presenter-account.js';
|
|
4
|
+
import { paintSettingsAccount } from './presenter-settings.js';
|
|
2
5
|
import { CHAT_MIN_ATTR, CHAT_PILL_ATTR, REPORT_ATTR, REPORT_BTN_ATTR, ANNOTATE_BTN_ATTR, CHAT_ATTR, CHAT_TOGGLE_ATTR, CHAT_PANEL_ATTR, DOCK_ATTR, FAB_ATTR, MIN_ATTR, SETTINGS_ATTR, SETTINGS_BTN_ATTR, } from './presenter-config.js';
|
|
3
|
-
import { BRAND_NAME, FAB_TOGGLE_HTML, MARK_SVG } from './presenter-brand.js';
|
|
4
|
-
import { settleLogAtLatest } from './presenter-log.js';
|
|
6
|
+
import { BRAND_NAME, FAB_TOGGLE_HTML, MARK_SVG } from './chrome/presenter-brand.js';
|
|
7
|
+
import { settleLogAtLatest } from './chrome/presenter-log.js';
|
|
5
8
|
import { installHudDragHandles, installHudPositionGuards } from './presenter-drag.js';
|
|
6
9
|
import { scheduleSyncDockLayout } from './presenter-dock-layout.js';
|
|
7
|
-
import { hiIconHtml, hiToggleIconHtml, PRESENTER_ICON_SIZE, PresenterIcon, } from './presenter-icons.js';
|
|
8
|
-
import { HUD_SURFACE_CLASS, HUD_LOG_WELL_CLASS } from './presenter-hud-chrome.js';
|
|
10
|
+
import { hiIconHtml, hiToggleIconHtml, PRESENTER_ICON_SIZE, PresenterIcon, } from './icons/presenter-icons.js';
|
|
11
|
+
import { HUD_SURFACE_CLASS, HUD_LOG_WELL_CLASS } from './chrome/presenter-hud-chrome.js';
|
|
9
12
|
import { CONTROLS_TOOLBAR_HTML } from './presenter-controls.js';
|
|
10
13
|
import { PresenterSettingsPanel, settingsPanelHtml, } from './presenter-settings.js';
|
|
11
14
|
const DRAG_HANDLE_CLASS = 'reticle-toolbar-drag';
|
|
@@ -37,8 +40,18 @@ export class HudShell {
|
|
|
37
40
|
this.#settings.close();
|
|
38
41
|
this.closeChat();
|
|
39
42
|
},
|
|
43
|
+
onSyncNow: () => this.#callbacks.onSyncNow?.(),
|
|
40
44
|
});
|
|
41
45
|
#callbacks;
|
|
46
|
+
#pushedAccount;
|
|
47
|
+
#accountTeardown;
|
|
48
|
+
paintAccount(account, dashboardUrl, details = {}) {
|
|
49
|
+
this.#pushedAccount = { account, dashboardUrl, details };
|
|
50
|
+
if (this.#root === undefined)
|
|
51
|
+
return;
|
|
52
|
+
paintToolbarAccount(this.#root, account, dashboardUrl, details);
|
|
53
|
+
paintSettingsAccount(this.#root, account, dashboardUrl, details);
|
|
54
|
+
}
|
|
42
55
|
constructor(callbacks = {}) {
|
|
43
56
|
this.#callbacks = callbacks;
|
|
44
57
|
this.#settings = new PresenterSettingsPanel({
|
|
@@ -59,6 +72,7 @@ export class HudShell {
|
|
|
59
72
|
<div ${CHAT_PANEL_ATTR} class="reticle-chat-panel ${HUD_SURFACE_CLASS}" role="region" aria-label="Reticle session" aria-hidden="true">
|
|
60
73
|
<div class="reticle-chat-head">
|
|
61
74
|
<span class="reticle-chat-brand">${MARK_SVG}<span class="reticle-chat-brandname">${BRAND_NAME}</span></span>
|
|
75
|
+
<span ${TOOLBAR_ACCOUNT_ATTR} class="reticle-head-account"></span>
|
|
62
76
|
</div>
|
|
63
77
|
<button type="button" ${CHAT_MIN_ATTR} class="reticle-chat-min" title="${CHAT_MIN_LABEL}" aria-label="${CHAT_MIN_LABEL}">${hiIconHtml(PresenterIcon.CARET_DOWN, PRESENTER_ICON_SIZE.TOOLBAR)}</button>
|
|
64
78
|
${actStripHtml}
|
|
@@ -209,8 +223,15 @@ export class HudShell {
|
|
|
209
223
|
}
|
|
210
224
|
document.addEventListener('pointerdown', this.#onDocPointerDown, { signal });
|
|
211
225
|
document.addEventListener('keydown', this.#onKeyDown, { signal });
|
|
226
|
+
this.#accountTeardown = mountAccountControl(root);
|
|
227
|
+
if (this.#pushedAccount !== undefined) {
|
|
228
|
+
const pushed = this.#pushedAccount;
|
|
229
|
+
this.paintAccount(pushed.account, pushed.dashboardUrl, pushed.details);
|
|
230
|
+
}
|
|
212
231
|
}
|
|
213
232
|
teardown() {
|
|
233
|
+
this.#accountTeardown?.();
|
|
234
|
+
this.#accountTeardown = undefined;
|
|
214
235
|
this.#listeners?.abort();
|
|
215
236
|
this.#listeners = undefined;
|
|
216
237
|
this.#toggleSync?.disconnect();
|