@reticlehq/browser 3.5.0 → 3.7.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/action-report.d.ts +54 -0
- package/dist/actions/action-report.js +60 -0
- package/dist/actions/actions-dom.d.ts +1 -0
- package/dist/actions/actions-dom.js +56 -43
- package/dist/actions/actions-press.d.ts +11 -4
- package/dist/actions/actions-press.js +132 -17
- package/dist/actions/actions.d.ts +1 -35
- package/dist/actions/actions.js +32 -65
- package/dist/actions/appeared-text.js +3 -0
- package/dist/actions/danger-context.d.ts +2 -0
- package/dist/actions/danger-context.js +29 -3
- package/dist/actions/value-input.d.ts +1 -0
- package/dist/actions/value-input.js +11 -0
- package/dist/commands/commands.js +4 -0
- package/dist/connect-options.d.ts +1 -0
- package/dist/dom/a11y.js +264 -14
- package/dist/dom/addressing/coverage-markers.d.ts +6 -0
- package/dist/dom/addressing/coverage-markers.js +13 -0
- 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/dom-ignore.d.ts +2 -0
- package/dist/dom/dom-ignore.js +15 -2
- package/dist/dom/query.d.ts +2 -1
- package/dist/dom/query.js +116 -27
- package/dist/dom/render-page.d.ts +12 -0
- package/dist/dom/render-page.js +135 -0
- package/dist/dom/snapshot.js +56 -7
- package/dist/observers/departure.js +51 -9
- package/dist/observers/dom.js +35 -18
- package/dist/observers/field.js +5 -21
- 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 +57 -8
- package/dist/observers/perf.js +53 -1
- package/dist/observers/route.js +6 -5
- package/dist/observers/storage.js +6 -1
- package/dist/presenter/carousel/carousel.d.ts +5 -2
- package/dist/presenter/carousel/carousel.js +30 -8
- package/dist/presenter/carousel/panel-slides.d.ts +3 -4
- package/dist/presenter/carousel/panel-slides.js +48 -9
- 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 +13 -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 +12 -4
- package/dist/presenter/chrome/presenter-log.js +100 -10
- package/dist/presenter/chrome/presenter-morph.d.ts +1 -0
- package/dist/presenter/chrome/presenter-morph.js +34 -0
- package/dist/presenter/chrome/presenter-report-copy.d.ts +28 -5
- package/dist/presenter/chrome/presenter-report-copy.js +40 -5
- package/dist/presenter/hud-telemetry.js +83 -3
- 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-styles.js +3 -3
- package/dist/presenter/presenter-account.d.ts +31 -8
- package/dist/presenter/presenter-account.js +105 -15
- package/dist/presenter/presenter-agent-link.d.ts +9 -0
- package/dist/presenter/presenter-agent-link.js +62 -0
- package/dist/presenter/presenter-chat-views.d.ts +43 -0
- package/dist/presenter/presenter-chat-views.js +622 -0
- package/dist/presenter/presenter-config.d.ts +5 -2
- package/dist/presenter/presenter-config.js +5 -3
- package/dist/presenter/presenter-controls.d.ts +3 -2
- package/dist/presenter/presenter-controls.js +163 -61
- 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 +187 -0
- package/dist/presenter/presenter-harness-row.d.ts +67 -0
- package/dist/presenter/presenter-harness-row.js +209 -0
- package/dist/presenter/presenter-personas.d.ts +35 -0
- package/dist/presenter/presenter-personas.js +95 -0
- package/dist/presenter/presenter-plan.d.ts +10 -0
- package/dist/presenter/presenter-plan.js +186 -0
- package/dist/presenter/presenter-report-styles.js +46 -21
- package/dist/presenter/presenter-report.d.ts +2 -1
- package/dist/presenter/presenter-report.js +123 -20
- package/dist/presenter/presenter-settings-styles.js +18 -4
- package/dist/presenter/presenter-settings.d.ts +8 -2
- package/dist/presenter/presenter-settings.js +134 -33
- package/dist/presenter/presenter-shell-styles.js +48 -42
- package/dist/presenter/presenter-shell.d.ts +17 -4
- package/dist/presenter/presenter-shell.js +139 -79
- package/dist/presenter/presenter-styles.js +9 -3
- package/dist/presenter/presenter-workspace.js +10 -3
- package/dist/presenter/presenter.d.ts +6 -4
- package/dist/presenter/presenter.js +171 -22
- 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 +4 -0
- package/dist/reticle-inject.js +938 -494
- package/dist/reticle.d.ts +10 -1
- package/dist/reticle.js +109 -11
- 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 +15 -0
- package/dist/storage-keys.js +21 -0
- package/dist/transport/transport.js +5 -3
- package/dist/transport/unreachable-message.d.ts +1 -1
- package/dist/transport/unreachable-message.js +3 -5
- package/package.json +3 -2
- package/dist/presenter/carousel/offer-card.d.ts +0 -21
- package/dist/presenter/carousel/offer-card.js +0 -55
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { HarnessConfig } from '@reticlehq/core';
|
|
2
|
+
import type { HarnessGateView } from './presenter-harness-row.js';
|
|
2
3
|
import { SETTINGS_CSS } from './presenter-settings-styles.js';
|
|
4
|
+
import { type Credits } from '@reticlehq/core/hud';
|
|
3
5
|
import type { AccountState } from '@reticlehq/core';
|
|
4
6
|
import { type AccountDetails } from './presenter-account.js';
|
|
5
7
|
export { SETTINGS_CSS };
|
|
@@ -41,11 +43,15 @@ export interface PresenterSettings {
|
|
|
41
43
|
export declare function getPresenterSettings(): PresenterSettings;
|
|
42
44
|
export declare function loadPresenterSettings(): PresenterSettings;
|
|
43
45
|
export declare const SETTINGS_ACCOUNT_ATTR = "data-reticle-settings-account";
|
|
44
|
-
export declare
|
|
46
|
+
export declare const HARNESS_LOCKED_HELP = "The Harness is not available to this workspace right now: see Plan in your Reticle dashboard.";
|
|
47
|
+
export declare function creditsLeft(credits: Credits | undefined): string;
|
|
48
|
+
export declare function paintHarnessRow(root: ParentNode, config: HarnessConfig | undefined, gate?: HarnessGateView): void;
|
|
45
49
|
export declare function paintSettingsAccount(root: HTMLElement, account: AccountState | undefined, dashboardUrl: string | undefined, details?: AccountDetails): void;
|
|
50
|
+
export declare function paintSdkVersion(root: ParentNode, version: string | undefined): void;
|
|
46
51
|
export declare function settingsPanelHtml(): string;
|
|
47
52
|
export interface SettingsHost {
|
|
48
53
|
onHideUntilRestart?: () => void;
|
|
54
|
+
onKill?: () => void;
|
|
49
55
|
onHarness?: (enabled: boolean) => void;
|
|
50
56
|
onSettingsChange?: (settings: PresenterSettings) => void;
|
|
51
57
|
onBeforeOpen?: () => void;
|
|
@@ -57,7 +63,7 @@ export declare class PresenterSettingsPanel {
|
|
|
57
63
|
constructor(host?: SettingsHost);
|
|
58
64
|
contains(node: Node): boolean;
|
|
59
65
|
mount(root: HTMLElement): void;
|
|
60
|
-
paintHarness(config: HarnessConfig | undefined): void;
|
|
66
|
+
paintHarness(config: HarnessConfig | undefined, gate?: HarnessGateView): void;
|
|
61
67
|
teardown(): void;
|
|
62
68
|
isOpen(): boolean;
|
|
63
69
|
open(): void;
|
|
@@ -4,8 +4,9 @@ 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 { creditsLeftText, creditsSpent, creditsUsedText } from '@reticlehq/core/hud';
|
|
7
8
|
import { DISCOVERY_CALL_URL, FOUNDER_EMAIL, FOUNDER_MAILTO } from '@reticlehq/core';
|
|
8
|
-
import { accountControlHtml } from './presenter-account.js';
|
|
9
|
+
import { ACCOUNT_TEXT, accountControlHtml, paintAccountSlot, } from './presenter-account.js';
|
|
9
10
|
export { SETTINGS_CSS };
|
|
10
11
|
export const OutputDetail = {
|
|
11
12
|
MINIMAL: 'minimal',
|
|
@@ -131,30 +132,59 @@ function patchSettings(patch) {
|
|
|
131
132
|
function settingsHelpIcon() {
|
|
132
133
|
return hiIconHtml(PresenterIcon.HELP, PRESENTER_ICON_SIZE.HELP);
|
|
133
134
|
}
|
|
134
|
-
|
|
135
|
+
const SETTING_TEXT = {
|
|
136
|
+
outputDetail: ['Output detail', 'How much a copied run includes.'],
|
|
137
|
+
autoOpenChat: ['Open the log automatically', 'Opens this panel when a session starts.'],
|
|
138
|
+
showTimestamps: ['Show timestamps', 'Shows how long ago each log row happened.'],
|
|
139
|
+
showTally: ['Show pass/fail count', 'A score pill for this session in the toolbar.'],
|
|
140
|
+
reactComponents: ['React component names', 'Adds component names to copied runs.'],
|
|
141
|
+
blockPageInteractions: [
|
|
142
|
+
'Block page while adding notes',
|
|
143
|
+
'Clicks pin a note instead of using the app.',
|
|
144
|
+
],
|
|
145
|
+
clearOnCopy: ['Clear notes after copying', 'Starts fresh once your notes are copied.'],
|
|
146
|
+
hideUntilRestart: ['Hide until reload', 'Hides the HUD until this page reloads.'],
|
|
147
|
+
harnessEnabled: [
|
|
148
|
+
'Allow Reticle to drive',
|
|
149
|
+
'Off by default. Unlocks at 80% instrumentation; lets Run Harness test this project.',
|
|
150
|
+
],
|
|
151
|
+
reduceMotion: ['Reduce motion', 'Fewer HUD animations.'],
|
|
152
|
+
ambientGlow: ['Page glow', 'Tints the page edges while a session runs.'],
|
|
153
|
+
workspace: ['Workspace', 'The Reticle account this machine is signed in to.'],
|
|
154
|
+
};
|
|
155
|
+
function settingsLabel(text, helpTitle, desc = '') {
|
|
135
156
|
const help = settingsHelpIcon();
|
|
136
|
-
|
|
157
|
+
const line = '' === desc ? '' : `<span class="reticle-settings-desc">${desc}</span>`;
|
|
158
|
+
return `<span class="reticle-settings-labelcol"><span class="reticle-settings-label">${text}<button type="button" class="reticle-settings-help" data-reticle-settings-help title="${helpTitle}" aria-label="${helpTitle}">${help}</button></span>${line}</span>`;
|
|
137
159
|
}
|
|
138
|
-
function settingsToggleRow(key,
|
|
160
|
+
function settingsToggleRow(key, helpTitle, extra = '') {
|
|
161
|
+
const [label, desc] = SETTING_TEXT[key];
|
|
139
162
|
return `<div class="reticle-settings-row" ${extra}>
|
|
140
|
-
${settingsLabel(label, helpTitle)}
|
|
163
|
+
${settingsLabel(label, helpTitle, desc)}
|
|
141
164
|
<button type="button" class="reticle-settings-toggle" ${SETTING_KEY_ATTR}="${key}" role="switch" aria-checked="false"></button>
|
|
142
165
|
</div>`;
|
|
143
166
|
}
|
|
144
|
-
function settingsCheckRow(key,
|
|
167
|
+
function settingsCheckRow(key, checked) {
|
|
168
|
+
const [label, desc] = SETTING_TEXT[key];
|
|
145
169
|
const on = checked ? 'true' : 'false';
|
|
146
170
|
return `<label class="reticle-settings-checkrow" data-reticle-check-row="${key}">
|
|
147
171
|
<span class="reticle-settings-check" data-reticle-check="${key}" role="checkbox" aria-checked="${on}" tabindex="0"></span>
|
|
148
|
-
<span class="reticle-settings-check-label">${label}</span>
|
|
172
|
+
<span class="reticle-settings-labelcol"><span class="reticle-settings-check-label">${label}</span><span class="reticle-settings-desc">${desc}</span></span>
|
|
149
173
|
</label>`;
|
|
150
174
|
}
|
|
151
175
|
export const SETTINGS_ACCOUNT_ATTR = 'data-reticle-settings-account';
|
|
152
176
|
const SETTINGS_ACCOUNT_ROW_ATTR = 'data-reticle-settings-account-row';
|
|
177
|
+
const HELP_TEXT_ATTR = 'data-reticle-settings-helptext';
|
|
153
178
|
const SETTINGS_HARNESS_ROW_ATTR = 'data-reticle-settings-harness-row';
|
|
154
|
-
const HARNESS_HELP = 'Let Reticle
|
|
155
|
-
const HARNESS_LOCKED_HELP = '
|
|
156
|
-
|
|
157
|
-
|
|
179
|
+
const HARNESS_HELP = 'Let Reticle test this app by itself to find defects, from Run Harness or from your coding agent. Off blocks every run. Set here or in your dashboard — both write to the same place.';
|
|
180
|
+
export const HARNESS_LOCKED_HELP = 'The Harness is not available to this workspace right now: see Plan in your Reticle dashboard.';
|
|
181
|
+
export function creditsLeft(credits) {
|
|
182
|
+
if (credits === undefined)
|
|
183
|
+
return '';
|
|
184
|
+
return creditsSpent(credits) ? creditsUsedText(credits).said : creditsLeftText(credits);
|
|
185
|
+
}
|
|
186
|
+
const ACCOUNT_HELP = `Whether this machine is signed in to a Reticle workspace. Press ${ACCOUNT_TEXT.SIGNED_OUT} to sign in through your browser.`;
|
|
187
|
+
export function paintHarnessRow(root, config, gate) {
|
|
158
188
|
const row = root.querySelector(`[${SETTINGS_HARNESS_ROW_ATTR}]`);
|
|
159
189
|
if (!(row instanceof HTMLElement))
|
|
160
190
|
return;
|
|
@@ -166,12 +196,20 @@ export function paintHarnessRow(root, config) {
|
|
|
166
196
|
const toggle = row.querySelector(`[${SETTING_KEY_ATTR}="harnessEnabled"]`);
|
|
167
197
|
if (!(toggle instanceof HTMLElement))
|
|
168
198
|
return;
|
|
169
|
-
const
|
|
199
|
+
const locked = gate !== undefined && !gate.unlocked ? gate.reason : undefined;
|
|
200
|
+
const usable = config.harnessEntitled && locked === undefined;
|
|
170
201
|
toggle.setAttribute('aria-checked', config.harnessEnabled && usable ? 'true' : 'false');
|
|
171
202
|
toggle.setAttribute('aria-disabled', usable ? 'false' : 'true');
|
|
172
|
-
const help = row.querySelector('[data-reticle-help]');
|
|
203
|
+
const help = row.querySelector('[data-reticle-settings-help]');
|
|
204
|
+
const credits = creditsLeft(config.credits);
|
|
173
205
|
if (help instanceof HTMLElement)
|
|
174
|
-
help.title =
|
|
206
|
+
help.title =
|
|
207
|
+
locked ??
|
|
208
|
+
(usable
|
|
209
|
+
? [HARNESS_HELP, credits].filter((t) => 0 < t.length).join(' ')
|
|
210
|
+
: creditsSpent(config.credits)
|
|
211
|
+
? credits
|
|
212
|
+
: HARNESS_LOCKED_HELP);
|
|
175
213
|
}
|
|
176
214
|
export function paintSettingsAccount(root, account, dashboardUrl, details = {}) {
|
|
177
215
|
const row = root.querySelector(`[${SETTINGS_ACCOUNT_ROW_ATTR}]`);
|
|
@@ -180,7 +218,7 @@ export function paintSettingsAccount(root, account, dashboardUrl, details = {})
|
|
|
180
218
|
return;
|
|
181
219
|
const html = accountControlHtml(account, { ...details, dashboardUrl }, true);
|
|
182
220
|
row.hidden = 0 === html.length;
|
|
183
|
-
slot
|
|
221
|
+
paintAccountSlot(slot, html);
|
|
184
222
|
}
|
|
185
223
|
const FEEDBACK_TEXT = {
|
|
186
224
|
EMAIL: 'Email the founder',
|
|
@@ -188,6 +226,23 @@ const FEEDBACK_TEXT = {
|
|
|
188
226
|
CALL: 'Book a call',
|
|
189
227
|
CALL_TITLE: 'Pick a time to talk it through',
|
|
190
228
|
};
|
|
229
|
+
const KILL_ATTR = 'data-reticle-settings-kill';
|
|
230
|
+
const KILL_TEXT = {
|
|
231
|
+
LABEL: 'Kill Reticle',
|
|
232
|
+
ARMED: 'Click again to kill Reticle',
|
|
233
|
+
WARNING: 'Disconnects Reticle from this page: no HUD, no agent, nothing recorded. To bring it back, restart your dev server or reload the page.',
|
|
234
|
+
};
|
|
235
|
+
const SDK_VERSION_ATTR = 'data-reticle-sdk-version';
|
|
236
|
+
const SDK_VERSION_TEXT = {
|
|
237
|
+
UNKNOWN: 'Reticle SDK version unknown',
|
|
238
|
+
KNOWN: (version) => `Reticle SDK ${version}`,
|
|
239
|
+
};
|
|
240
|
+
export function paintSdkVersion(root, version) {
|
|
241
|
+
const line = root.querySelector(`[${SDK_VERSION_ATTR}]`);
|
|
242
|
+
if (line !== null)
|
|
243
|
+
line.textContent =
|
|
244
|
+
version === undefined ? SDK_VERSION_TEXT.UNKNOWN : SDK_VERSION_TEXT.KNOWN(version);
|
|
245
|
+
}
|
|
191
246
|
export function settingsPanelHtml() {
|
|
192
247
|
const close = hiIconHtml(PresenterIcon.REMOVE, PRESENTER_ICON_SIZE.MIN);
|
|
193
248
|
const caret = hiIconHtml(PresenterIcon.CARET_RIGHT, PRESENTER_ICON_SIZE.HELP);
|
|
@@ -209,34 +264,40 @@ export function settingsPanelHtml() {
|
|
|
209
264
|
<div class="reticle-settings-body">
|
|
210
265
|
<div class="reticle-settings-section">Session</div>
|
|
211
266
|
<div class="reticle-settings-row">
|
|
212
|
-
${settingsLabel(
|
|
267
|
+
${settingsLabel(SETTING_TEXT.outputDetail[0], outputHelp, SETTING_TEXT.outputDetail[1])}
|
|
213
268
|
<button type="button" class="reticle-settings-cycle" data-reticle-settings-cycle="outputDetail"><span data-reticle-cycle-label></span><span class="reticle-settings-dots" data-reticle-cycle-dots></span></button>
|
|
214
269
|
</div>
|
|
215
|
-
${settingsToggleRow('autoOpenChat',
|
|
216
|
-
${settingsToggleRow('showTimestamps',
|
|
217
|
-
${settingsToggleRow('showTally',
|
|
270
|
+
${settingsToggleRow('autoOpenChat', autoChatHelp)}
|
|
271
|
+
${settingsToggleRow('showTimestamps', timestampsHelp)}
|
|
272
|
+
${settingsToggleRow('showTally', tallyHelp)}
|
|
218
273
|
<div class="reticle-settings-section">Inspector</div>
|
|
219
|
-
${settingsToggleRow('reactComponents',
|
|
274
|
+
${settingsToggleRow('reactComponents', reactHelp, 'data-reticle-settings-react-row')}
|
|
220
275
|
<div class="reticle-settings-section">Interaction</div>
|
|
221
|
-
${settingsCheckRow('blockPageInteractions',
|
|
222
|
-
${settingsCheckRow('clearOnCopy',
|
|
223
|
-
${settingsToggleRow('hideUntilRestart',
|
|
224
|
-
${settingsToggleRow('harnessEnabled',
|
|
225
|
-
${settingsToggleRow('reduceMotion',
|
|
276
|
+
${settingsCheckRow('blockPageInteractions', true)}
|
|
277
|
+
${settingsCheckRow('clearOnCopy', false)}
|
|
278
|
+
${settingsToggleRow('hideUntilRestart', hideHelp)}
|
|
279
|
+
${settingsToggleRow('harnessEnabled', harnessHelp, `${SETTINGS_HARNESS_ROW_ATTR} hidden`)}
|
|
280
|
+
${settingsToggleRow('reduceMotion', motionHelp)}
|
|
226
281
|
<div class="reticle-settings-section">Account</div>
|
|
227
282
|
<div class="reticle-settings-row" ${SETTINGS_ACCOUNT_ROW_ATTR} hidden>
|
|
228
|
-
${settingsLabel(
|
|
283
|
+
${settingsLabel(SETTING_TEXT.workspace[0], ACCOUNT_HELP, SETTING_TEXT.workspace[1])}
|
|
229
284
|
<span ${SETTINGS_ACCOUNT_ATTR}></span>
|
|
230
285
|
</div>
|
|
231
286
|
<div class="reticle-settings-section">Status theme</div>
|
|
232
|
-
${settingsToggleRow('ambientGlow',
|
|
287
|
+
${settingsToggleRow('ambientGlow', glowHelp)}
|
|
233
288
|
<div class="reticle-settings-themes" data-reticle-settings-themes></div>
|
|
234
|
-
|
|
235
|
-
|
|
289
|
+
<div class="reticle-settings-section">Help</div>
|
|
290
|
+
<div class="reticle-settings-foot">
|
|
236
291
|
<button type="button" class="reticle-settings-reset" data-reticle-settings-reset>Reset HUD position</button>
|
|
237
|
-
<button type="button" class="reticle-settings-link" data-reticle-settings-mcp>
|
|
292
|
+
<button type="button" class="reticle-settings-link" data-reticle-settings-mcp>MCP setup guide<span class="reticle-settings-link-caret" aria-hidden="true">${caret}</span></button>
|
|
238
293
|
<a class="reticle-settings-link" data-reticle-feedback-email href="${FOUNDER_MAILTO}" target="_blank" rel="noopener noreferrer" title="${FEEDBACK_TEXT.EMAIL_TITLE}">${FEEDBACK_TEXT.EMAIL}<span class="reticle-settings-link-caret" aria-hidden="true">${caret}</span></a>
|
|
239
294
|
<a class="reticle-settings-link" data-reticle-feedback-call href="${DISCOVERY_CALL_URL}" target="_blank" rel="noopener noreferrer" title="${FEEDBACK_TEXT.CALL_TITLE}">${FEEDBACK_TEXT.CALL}<span class="reticle-settings-link-caret" aria-hidden="true">${caret}</span></a>
|
|
295
|
+
<p class="reticle-settings-kill-sub" ${SDK_VERSION_ATTR}>${SDK_VERSION_TEXT.UNKNOWN}</p>
|
|
296
|
+
<div class="reticle-settings-kill-row">
|
|
297
|
+
<button type="button" class="reticle-settings-kill" ${KILL_ATTR}><span data-reticle-kill-label>${KILL_TEXT.LABEL}</span></button>
|
|
298
|
+
<p class="reticle-settings-kill-sub">${KILL_TEXT.WARNING}</p>
|
|
299
|
+
</div>
|
|
300
|
+
</div>
|
|
240
301
|
</div>
|
|
241
302
|
</div>
|
|
242
303
|
</div>`;
|
|
@@ -294,10 +355,13 @@ export class PresenterSettingsPanel {
|
|
|
294
355
|
setHiIcon(closeBtn, PresenterIcon.REMOVE, PRESENTER_ICON_SIZE.MIN);
|
|
295
356
|
}
|
|
296
357
|
if (this.#btn !== undefined) {
|
|
358
|
+
const label = this.#btn.querySelector('.reticle-nav-label');
|
|
297
359
|
setHiIcon(this.#btn, PresenterIcon.GEAR, PRESENTER_ICON_SIZE.TOOLBAR);
|
|
360
|
+
if (null !== label)
|
|
361
|
+
this.#btn.append(label);
|
|
298
362
|
this.#btn.addEventListener('click', (e) => {
|
|
299
363
|
e.stopPropagation();
|
|
300
|
-
this.
|
|
364
|
+
this.open();
|
|
301
365
|
});
|
|
302
366
|
}
|
|
303
367
|
root
|
|
@@ -310,8 +374,24 @@ export class PresenterSettingsPanel {
|
|
|
310
374
|
this.#update({ outputDetail: next.value });
|
|
311
375
|
});
|
|
312
376
|
for (const help of root.querySelectorAll('.reticle-settings-help')) {
|
|
377
|
+
help.setAttribute('aria-expanded', 'false');
|
|
313
378
|
help.addEventListener('click', (e) => {
|
|
314
379
|
e.stopPropagation();
|
|
380
|
+
const row = help.closest('.reticle-settings-row');
|
|
381
|
+
if (null === row)
|
|
382
|
+
return;
|
|
383
|
+
const shown = row.querySelector(`[${HELP_TEXT_ATTR}]`);
|
|
384
|
+
if (null !== shown) {
|
|
385
|
+
shown.remove();
|
|
386
|
+
help.setAttribute('aria-expanded', 'false');
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
const text = document.createElement('p');
|
|
390
|
+
text.className = 'reticle-settings-helptext';
|
|
391
|
+
text.setAttribute(HELP_TEXT_ATTR, '');
|
|
392
|
+
text.textContent = help.getAttribute('title') ?? '';
|
|
393
|
+
row.appendChild(text);
|
|
394
|
+
help.setAttribute('aria-expanded', 'true');
|
|
315
395
|
});
|
|
316
396
|
}
|
|
317
397
|
for (const toggle of root.querySelectorAll(`[${SETTING_KEY_ATTR}]`)) {
|
|
@@ -399,6 +479,20 @@ export class PresenterSettingsPanel {
|
|
|
399
479
|
if (dock instanceof HTMLElement)
|
|
400
480
|
resetHudDockPosition(dock);
|
|
401
481
|
});
|
|
482
|
+
root.querySelector(`[${KILL_ATTR}]`)?.addEventListener('click', (e) => {
|
|
483
|
+
e.stopPropagation();
|
|
484
|
+
const kill = e.currentTarget;
|
|
485
|
+
if (!(kill instanceof HTMLElement))
|
|
486
|
+
return;
|
|
487
|
+
if ('1' === kill.getAttribute('data-armed')) {
|
|
488
|
+
this.#host.onKill?.();
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
kill.setAttribute('data-armed', '1');
|
|
492
|
+
const label = kill.querySelector('[data-reticle-kill-label]');
|
|
493
|
+
if (label !== null)
|
|
494
|
+
label.textContent = KILL_TEXT.ARMED;
|
|
495
|
+
});
|
|
402
496
|
closeBtn?.addEventListener('click', (e) => {
|
|
403
497
|
e.stopPropagation();
|
|
404
498
|
this.close();
|
|
@@ -408,11 +502,11 @@ export class PresenterSettingsPanel {
|
|
|
408
502
|
applyPresenterSettings(root, activeSettings);
|
|
409
503
|
this.#host.onSettingsChange?.(activeSettings);
|
|
410
504
|
}
|
|
411
|
-
paintHarness(config) {
|
|
505
|
+
paintHarness(config, gate) {
|
|
412
506
|
const root = this.#panel;
|
|
413
507
|
if (root === undefined)
|
|
414
508
|
return;
|
|
415
|
-
paintHarnessRow(root, config);
|
|
509
|
+
paintHarnessRow(root, config, gate);
|
|
416
510
|
}
|
|
417
511
|
teardown() {
|
|
418
512
|
this.#root = undefined;
|
|
@@ -434,6 +528,13 @@ export class PresenterSettingsPanel {
|
|
|
434
528
|
close() {
|
|
435
529
|
if (this.#root === undefined)
|
|
436
530
|
return;
|
|
531
|
+
const kill = this.#panel?.querySelector(`[${KILL_ATTR}]`);
|
|
532
|
+
if (kill instanceof HTMLElement) {
|
|
533
|
+
kill.removeAttribute('data-armed');
|
|
534
|
+
const label = kill.querySelector('[data-reticle-kill-label]');
|
|
535
|
+
if (label !== null)
|
|
536
|
+
label.textContent = KILL_TEXT.LABEL;
|
|
537
|
+
}
|
|
437
538
|
this.#root.setAttribute(SETTINGS_ATTR, '0');
|
|
438
539
|
this.#panel?.setAttribute('aria-hidden', 'true');
|
|
439
540
|
this.#btn?.setAttribute('data-active', '0');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
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 './chrome/presenter-hud-chrome.js';
|
|
4
|
+
import { HUD_DROP_SHADOW, HUD_GLASS_PAINT, 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';
|
|
@@ -23,57 +23,48 @@ export const SHELL_CSS = `
|
|
|
23
23
|
[${OVERLAY}][${STATE}="paused"]{--reticle-state:var(--reticle-c-idle);}
|
|
24
24
|
[${OVERLAY}][${STATE}="ended"]{--reticle-state:var(--reticle-c-ended);}
|
|
25
25
|
[${DOCK_ATTR}]{
|
|
26
|
-
--reticle-surface:
|
|
26
|
+
--reticle-surface:color-mix(in srgb,var(--reticle-hud-surface) 78%,transparent);
|
|
27
27
|
/* No literal here: --reticle-accent is published on the overlay from the chosen status theme.
|
|
28
28
|
Redefining it on the dock made every accented control - toolbar toggles, focus rings, the send
|
|
29
29
|
button - stay blue no matter which theme was picked, because the dock's value won for its own
|
|
30
30
|
subtree. The fallback only matters if the presenter is mounted without settings. */
|
|
31
31
|
--reticle-accent:var(--reticle-c-active,#3b82f6);
|
|
32
32
|
--reticle-accent-soft:color-mix(in srgb,var(--reticle-accent) 18%,transparent);
|
|
33
|
-
--reticle-bg
|
|
34
|
-
--reticle-fg
|
|
35
|
-
--reticle-line:
|
|
33
|
+
--reticle-bg:var(--reticle-hud-ground);--reticle-bg2:var(--reticle-hud-surface);
|
|
34
|
+
--reticle-fg:var(--reticle-hud-text);--reticle-muted:var(--reticle-hud-text-muted);--reticle-faint:var(--reticle-hud-text-faint);
|
|
35
|
+
--reticle-line:var(--reticle-hud-border-strong);--reticle-line2:color-mix(in srgb,var(--reticle-hud-border) 70%,transparent);
|
|
36
36
|
--reticle-read:#d4d4d4;--reticle-ok:#fafafa;--reticle-bad:#f5f5f5;
|
|
37
|
-
--reticle-font:
|
|
38
|
-
--reticle-shell-ease:
|
|
37
|
+
--reticle-font:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
|
|
38
|
+
--reticle-shell-ease:var(--reticle-hud-ease);
|
|
39
39
|
--reticle-shell-fast:.22s var(--reticle-shell-ease);
|
|
40
40
|
--reticle-mark-accent:var(--reticle-accent);
|
|
41
41
|
position:fixed;right:20px;bottom:20px;left:auto;
|
|
42
42
|
z-index:2147483647;pointer-events:none;display:flex;flex-direction:column;align-items:flex-end;gap:8px;
|
|
43
43
|
overflow:visible;max-width:calc(100vw - 24px);font-family:var(--reticle-font);-webkit-font-smoothing:antialiased;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
*/
|
|
48
|
-
/* ONE width for the chat, the capsule and the toolbar. It used to be 440 with a "compact" 340
|
|
49
|
-
toggle; 340 is the size that actually reads well beside an app, so it is simply the size. */
|
|
50
|
-
--reticle-dock-w:340px;
|
|
44
|
+
/* ONE width for the chat, the capsule and the toolbar: the dock-width token. Two widths made the
|
|
45
|
+
toolbar overhang the panel it belongs to, and the pair read as two unrelated widgets. */
|
|
46
|
+
--reticle-dock-w:var(--reticle-hud-dock-width,320px);
|
|
51
47
|
/* The log is the reason the panel exists, so it gets the height rather than the chrome. */
|
|
52
|
-
--reticle-chat-h:
|
|
48
|
+
--reticle-chat-h:var(--reticle-hud-panel-height,440px);
|
|
53
49
|
opacity:0;transform:translate3d(0,8px,0);transition:opacity var(--reticle-shell-fast),transform var(--reticle-shell-fast);}
|
|
54
50
|
[${DOCK_ATTR}][data-dragged="1"]{left:var(--reticle-hud-x);top:var(--reticle-hud-y);bottom:auto;right:auto;transform:none;}
|
|
55
51
|
[${DOCK_ATTR}][data-dragged="1"][data-on="1"]{transform:none;}
|
|
56
52
|
[${DOCK_ATTR}][data-on="1"]{opacity:1;transform:translate3d(0,0,0);pointer-events:none;}
|
|
57
53
|
[${DOCK_ATTR}][data-on="0"]{opacity:0;pointer-events:none;}
|
|
58
54
|
/**
|
|
59
|
-
* The panel is
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* thing in the whole SDK (+4pp of main thread on the hostile fixture), and the tint buys the look
|
|
63
|
-
* without the bill.
|
|
55
|
+
* The panel is painted by HUD_GLASS_PAINT: an opaque navy fill, lit by the state colour, with that
|
|
56
|
+
* colour glowing behind it. No backdrop-filter: blur(24px) here was measured as the single most
|
|
57
|
+
* expensive thing in the whole SDK.
|
|
64
58
|
*/
|
|
65
59
|
[${CHAT_PANEL}]{
|
|
66
|
-
|
|
67
|
-
radial-gradient(130% 90% at 50% 0%,color-mix(in srgb,var(--reticle-c-active) 18%,transparent),transparent 62%),
|
|
68
|
-
linear-gradient(180deg,rgba(13,15,22,.96),rgba(19,22,32,.94));
|
|
69
|
-
border:1px solid color-mix(in srgb,var(--reticle-c-active) 26%,rgba(255,255,255,.1));
|
|
60
|
+
${HUD_GLASS_PAINT}
|
|
70
61
|
display:none;position:absolute;right:0;left:auto;bottom:calc(100% + 8px);top:auto;z-index:5;
|
|
71
62
|
box-sizing:border-box;width:var(--reticle-dock-w);max-width:min(var(--reticle-dock-w),calc(100vw - 16px));
|
|
63
|
+
height:min(var(--reticle-chat-max-h,var(--reticle-chat-h)),calc(100vh - 120px));
|
|
72
64
|
max-height:min(var(--reticle-chat-max-h,var(--reticle-chat-h)),calc(100vh - 120px));
|
|
73
65
|
flex-direction:column;overflow:hidden;text-align:left;
|
|
74
66
|
color:var(--reticle-fg);font-size:13px;line-height:1.5;
|
|
75
|
-
border-radius:
|
|
76
|
-
box-shadow:${HUD_DROP_SHADOW},0 0 54px -18px var(--reticle-c-active);
|
|
67
|
+
border-radius:var(--reticle-hud-radius-lg);
|
|
77
68
|
contain:layout style paint;
|
|
78
69
|
transform:translateZ(0);
|
|
79
70
|
pointer-events:none;}
|
|
@@ -83,6 +74,9 @@ export const SHELL_CSS = `
|
|
|
83
74
|
right:auto;left:0;}
|
|
84
75
|
[${OVERLAY}][${CHAT_ATTR}="1"] [${CHAT_PANEL}]{
|
|
85
76
|
display:flex;pointer-events:auto;}
|
|
77
|
+
[${CHAT_PANEL}][hidden]{display:none!important;}
|
|
78
|
+
[${DOCK_ATTR}][${CHAT_PLACEMENT_ATTR}="below"] [data-reticle-page-panel]{bottom:auto;top:calc(100% + 8px);}
|
|
79
|
+
[${DOCK_ATTR}][${DOCK_ALIGN_ATTR}="start"] [data-reticle-page-panel]{right:auto;left:0;}
|
|
86
80
|
/**
|
|
87
81
|
* Idle, and not blocking the page: the card is not in use.
|
|
88
82
|
*
|
|
@@ -93,6 +87,9 @@ export const SHELL_CSS = `
|
|
|
93
87
|
[${OVERLAY}][data-reticle-mode="idle"][data-reticle-block="0"] [${CHAT_PANEL}],
|
|
94
88
|
[${OVERLAY}][data-reticle-mode="idle"][data-reticle-block="0"] [${CHAT_PANEL}] [data-reticle-log]{
|
|
95
89
|
pointer-events:none;}
|
|
90
|
+
/* ...except a log with more than it shows: a feed nobody can scroll back through is not a log. */
|
|
91
|
+
[${OVERLAY}][data-reticle-mode="idle"][data-reticle-block="0"] [${CHAT_PANEL}] [data-reticle-log][data-reticle-log-scrollable]{
|
|
92
|
+
pointer-events:auto;}
|
|
96
93
|
[${OVERLAY}][data-reticle-mode="idle"][data-reticle-block="0"] [${CHAT_PANEL}] :is(button,a,input,select,textarea){
|
|
97
94
|
pointer-events:auto;}
|
|
98
95
|
/**
|
|
@@ -134,8 +131,18 @@ export const SHELL_CSS = `
|
|
|
134
131
|
so the two never overlap. The :empty rule keeps the gap closed when no account state was sent. */
|
|
135
132
|
[${CHAT_PANEL}] .reticle-head-account{margin-left:auto;display:inline-flex;align-items:center;}
|
|
136
133
|
[${CHAT_PANEL}] .reticle-head-account:empty{display:none;}
|
|
134
|
+
/* The quiet way to the platform: one line of small text before the avatar, cut short before it pushes. */
|
|
135
|
+
[${CHAT_PANEL}] .reticle-head-team{margin-left:auto;min-width:0;display:inline-flex;}
|
|
136
|
+
[${CHAT_PANEL}] .reticle-head-team:empty{display:none;}
|
|
137
|
+
[${CHAT_PANEL}] .reticle-head-team:not(:empty) + .reticle-head-account{margin-left:0;}
|
|
138
|
+
[${CHAT_PANEL}] .reticle-team-link{min-width:0;max-width:100%;overflow:hidden;padding:0;border:0;background:none;cursor:pointer;font:inherit;font-size:var(--reticle-hud-size-xs);font-weight:500;color:var(--reticle-hud-text-muted);text-decoration:none;white-space:nowrap;text-overflow:ellipsis;}
|
|
139
|
+
[${CHAT_PANEL}] .reticle-team-link span{display:block;overflow:hidden;text-overflow:ellipsis;}
|
|
140
|
+
[${CHAT_PANEL}] .reticle-team-link:hover{color:var(--reticle-hud-brand);}
|
|
141
|
+
[${CHAT_PANEL}] .reticle-team-link:focus-visible{outline:2px solid var(--reticle-hud-brand);outline-offset:2px;border-radius:var(--reticle-hud-radius-sm);}
|
|
137
142
|
[${CHAT_PANEL}] .reticle-chat-brand .reticle-mark{height:14px;width:auto;}
|
|
138
143
|
[${CHAT_PANEL}] .reticle-chat-brandname{font-size:12.5px;font-weight:600;letter-spacing:.01em;}
|
|
144
|
+
[${CHAT_PANEL}] .reticle-view-heading{display:flex;justify-content:space-between;align-items:baseline;gap:8px;min-height:28px;box-sizing:border-box;padding:6px 12px 4px;border-bottom:1px solid var(--reticle-hud-border);}
|
|
145
|
+
[${CHAT_PANEL}] .reticle-view-heading strong{font-size:11px;font-weight:600;}
|
|
139
146
|
/* No state word here: the activity strip immediately below already says "idle · 21s", and the
|
|
140
147
|
dot in front of it carries the same colour. One fact, one place. */
|
|
141
148
|
[${CHAT_PILL_ATTR}] .reticle-chat-pill-text{
|
|
@@ -255,13 +262,13 @@ export const SHELL_CSS = `
|
|
|
255
262
|
[${HUD}] .reticle-toolbar-actions{
|
|
256
263
|
display:inline-flex;align-items:center;gap:2px;flex:none;
|
|
257
264
|
padding:2px;border-radius:999px;background:rgba(0,0,0,.2);}
|
|
258
|
-
[${HUD}] .reticle-toolbar-chrome{display:
|
|
265
|
+
[${HUD}] .reticle-toolbar-chrome{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);align-items:center;gap:var(--reticle-hud-space-1);flex:1;min-width:0;}
|
|
259
266
|
[${HUD}] .reticle-tb-sep{width:1px;height:14px;background:rgba(255,255,255,.12);margin:0 4px;flex:none;align-self:center;}
|
|
260
267
|
|
|
261
268
|
[${HUD}] .reticle-tb-wrap{position:relative;display:flex;align-items:center;justify-content:center;overflow:visible;}
|
|
262
269
|
[${HUD}] .reticle-tb-btn{
|
|
263
270
|
flex:none;display:inline-flex;align-items:center;justify-content:center;
|
|
264
|
-
width:
|
|
271
|
+
width:var(--reticle-hud-control-size);height:var(--reticle-hud-control-size);padding:0;border:none;border-radius:var(--reticle-hud-radius-pill);cursor:pointer;
|
|
265
272
|
background:transparent;color:rgba(255,255,255,.85);line-height:0;
|
|
266
273
|
transition:background-color .15s ease,color .15s ease,transform .1s ease,opacity .2s ease;}
|
|
267
274
|
[${HUD}] .reticle-tb-btn:hover{background:rgba(255,255,255,.12);color:#fff;}
|
|
@@ -294,18 +301,6 @@ export const SHELL_CSS = `
|
|
|
294
301
|
color:#fff;background:rgba(255,255,255,.14);}
|
|
295
302
|
[${HUD}] .reticle-tb-btn[data-danger]:hover:not(:disabled){color:#ff383c;
|
|
296
303
|
background:color-mix(in srgb, #ff383c 25%, transparent);}
|
|
297
|
-
/**
|
|
298
|
-
* The toolbar is a FIXED number of slots.
|
|
299
|
-
*
|
|
300
|
-
* Copy and Export appear when a session ends, and the bar is already full - eleven icons in a pill
|
|
301
|
-
* sized for nine renders the last one outside the rounded box. They take the two slots Pause and End
|
|
302
|
-
* vacate: neither can do anything to an ended session, so the bar swaps two dead controls for two
|
|
303
|
-
* live ones and never changes width.
|
|
304
|
-
*/
|
|
305
|
-
[${HUD}] .reticle-tb-btn--export{display:none;}
|
|
306
|
-
[${OVERLAY}][${STATE}="ended"] [${HUD}] .reticle-tb-btn--export{display:inline-flex;}
|
|
307
|
-
[${OVERLAY}][${STATE}="ended"] [${HUD}] [data-reticle-pause],
|
|
308
|
-
[${OVERLAY}][${STATE}="ended"] [${HUD}] [data-reticle-end]{display:none;}
|
|
309
304
|
[${HUD}] .reticle-tb-tip{
|
|
310
305
|
position:absolute;bottom:calc(100% + 14px);left:50%;transform:translateX(-50%) scale(.95);
|
|
311
306
|
padding:6px 10px;background:#1a1a1a;color:rgba(255,255,255,.9);font-size:12px;font-weight:500;
|
|
@@ -359,7 +354,7 @@ export const SHELL_CSS = `
|
|
|
359
354
|
[${HUD}] .reticle-hi-icon{display:inline-flex;align-items:center;justify-content:center;line-height:1;flex-shrink:0;color:inherit;}
|
|
360
355
|
[${HUD}] .reticle-hi-icon svg{display:block;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;}
|
|
361
356
|
[${HUD}] .reticle-live{display:none;}
|
|
362
|
-
[${CHAT_PANEL}] .reticle-act-strip{flex:none;display:flex;align-items:center;gap:
|
|
357
|
+
[${CHAT_PANEL}] .reticle-act-strip{flex:none;display:flex;align-items:center;gap:7px;min-height:36px;box-sizing:border-box;padding:4px 12px;
|
|
363
358
|
border-bottom:1px solid rgba(255,255,255,.07);background:rgba(0,0,0,.22);}
|
|
364
359
|
[${CHAT_PANEL}] .reticle-act-dot{flex:none;width:7px;height:7px;border-radius:50%;background:var(--reticle-faint);
|
|
365
360
|
box-shadow:0 0 0 2px rgba(255,255,255,.04);transition:background .2s,box-shadow .2s;}
|
|
@@ -382,11 +377,22 @@ export const SHELL_CSS = `
|
|
|
382
377
|
*/
|
|
383
378
|
[${OVERLAY}][${STATE}="unreachable"]{--reticle-state:var(--reticle-faint);}
|
|
384
379
|
[${OVERLAY}][${STATE}="unreachable"] [${CHAT_PANEL}] .reticle-act-dot{animation:none;}
|
|
380
|
+
/* The one status that is a sentence to act on: two lines, full contrast, the detail on hover. */
|
|
381
|
+
[${OVERLAY}][${STATE}="unreachable"] [${CHAT_PANEL}] .reticle-act{white-space:normal;line-height:1.35;color:var(--reticle-fg);cursor:help;}
|
|
385
382
|
[${OVERLAY}][${STATE}="paused"] [${CHAT_PANEL}] .reticle-act-dot,
|
|
386
383
|
[${OVERLAY}][${STATE}="ended"] [${CHAT_PANEL}] .reticle-act-dot{animation:none;}
|
|
387
384
|
@keyframes reticle-idle-pulse{0%,100%{opacity:.45;transform:scale(.92)}50%{opacity:1;transform:scale(1)}}
|
|
388
385
|
[${CHAT_PANEL}] .reticle-act{display:block;flex:1;min-width:0;color:var(--reticle-muted);font-size:11px;
|
|
389
386
|
font-variant-numeric:tabular-nums;letter-spacing:.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
|
387
|
+
[${CHAT_PANEL}] .reticle-act-actions{display:flex;align-items:center;gap:4px;flex:none;margin-left:auto;}
|
|
388
|
+
[${CHAT_PANEL}] .reticle-status-btn{position:relative;width:26px;height:26px;display:inline-flex;align-items:center;justify-content:center;
|
|
389
|
+
border:1px solid var(--reticle-line);border-radius:var(--reticle-hud-radius-sm);background:transparent;color:var(--reticle-muted);cursor:pointer;}
|
|
390
|
+
[${CHAT_PANEL}] .reticle-status-btn[hidden]{display:none;}
|
|
391
|
+
[${CHAT_PANEL}] .reticle-status-btn:hover:not(:disabled){background:var(--reticle-hud-hover);color:var(--reticle-fg);}
|
|
392
|
+
[${CHAT_PANEL}] .reticle-status-btn:focus-visible{outline:2px solid var(--reticle-accent);outline-offset:2px;}
|
|
393
|
+
[${CHAT_PANEL}] .reticle-status-btn:disabled{opacity:.35;cursor:not-allowed;}
|
|
394
|
+
[${CHAT_PANEL}] .reticle-status-stop:hover:not(:disabled){color:var(--reticle-state);border-color:var(--reticle-state);}
|
|
395
|
+
[${CHAT_PANEL}] .reticle-act-actions .reticle-pause-badge{display:none;position:static;transform:none;padding:2px 5px;font-size:8px;}
|
|
390
396
|
[${CHAT_PANEL}] .reticle-act-strip[data-liveness="active"] .reticle-act{color:var(--reticle-fg);}
|
|
391
397
|
[${HUD}] .reticle-pass{color:var(--reticle-ok);}[${HUD}] .reticle-fail{color:var(--reticle-bad);}
|
|
392
398
|
/**
|
|
@@ -408,6 +414,6 @@ export const SHELL_CSS = `
|
|
|
408
414
|
--reticle-accent:var(--reticle-state);
|
|
409
415
|
--reticle-accent-soft:color-mix(in srgb,var(--reticle-state) 18%,transparent);}
|
|
410
416
|
@media (max-width:480px){
|
|
411
|
-
[${CHAT_PANEL}]{width:min(100vw - 24px,320px);max-height:min(
|
|
417
|
+
[${CHAT_PANEL}]{width:min(100vw - 24px,320px);max-height:min(440px,calc(100vh - 100px));}
|
|
412
418
|
[${OVERLAY}][${MIN_ATTR}="0"] [${HUD}]{max-width:calc(100vw - 24px);}
|
|
413
419
|
}`;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import type { HarnessConfig } from '@reticlehq/core';
|
|
1
|
+
import type { AgentLink, HarnessConfig, HarnessDrive } from '@reticlehq/core';
|
|
2
|
+
import type { HarnessGateView } from './presenter-harness-row.js';
|
|
2
3
|
import { PresenterReport } from './presenter-report.js';
|
|
3
4
|
import type { AccountState } from '@reticlehq/core';
|
|
4
5
|
import { type AccountDetails } from './presenter-account.js';
|
|
5
|
-
import { type
|
|
6
|
+
import { type ChatView } from './presenter-chat-views.js';
|
|
7
|
+
import type { AnnotationItem } from '../review/annotator.js';
|
|
6
8
|
import { type SettingsHost } from './presenter-settings.js';
|
|
7
9
|
interface HudShellCallbacks {
|
|
8
10
|
onChatOpen?: () => void;
|
|
@@ -11,13 +13,24 @@ interface HudShellCallbacks {
|
|
|
11
13
|
onAnnotateToggle?: (on: boolean) => void;
|
|
12
14
|
onCollapse?: () => void;
|
|
13
15
|
onSyncNow?: () => void;
|
|
16
|
+
onHarness?: (enabled: boolean) => void;
|
|
17
|
+
onHarnessRun?: (persona?: string) => void;
|
|
18
|
+
onHarnessStop?: () => void;
|
|
19
|
+
onHarnessLink?: () => void;
|
|
20
|
+
onSignIn?: () => void;
|
|
14
21
|
settings?: SettingsHost;
|
|
15
22
|
}
|
|
16
23
|
export declare class HudShell {
|
|
17
24
|
#private;
|
|
18
|
-
|
|
25
|
+
setProjectId(projectId: string | undefined): void;
|
|
26
|
+
paintHarnessDrive(drive: HarnessDrive | undefined): void;
|
|
27
|
+
paintAgent(link: AgentLink | undefined): void;
|
|
28
|
+
paintHarness(config: HarnessConfig | undefined, gate?: HarnessGateView): void;
|
|
29
|
+
paintImpact(verdicts: number): void;
|
|
30
|
+
paintAnnotations(items: readonly AnnotationItem[]): void;
|
|
31
|
+
openView(view: ChatView): void;
|
|
19
32
|
paintAccount(account: AccountState | undefined, dashboardUrl: string | undefined, details?: AccountDetails): void;
|
|
20
|
-
|
|
33
|
+
paintNotices(notices?: readonly unknown[]): void;
|
|
21
34
|
constructor(callbacks?: HudShellCallbacks);
|
|
22
35
|
static dockHtml(actStripHtml: string, bannerHtml: string, logAttr: string, flowsHtml: string, footHtml: string): string;
|
|
23
36
|
get report(): PresenterReport;
|