@timurproko/a1 0.2.7-dev.1252 → 0.2.7-dev.1264
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/bin/ui.js +3 -3
- package/dist/app/session-shell/clipboard-diagnostics.d.ts +2 -2
- package/dist/app/session-shell/clipboard-image.d.ts +0 -1
- package/dist/app/session-shell/clipboard-image.js +1 -1
- package/dist/app/session-shell/dialog-coordinator.d.ts +6 -5
- package/dist/app/session-shell/dialog-coordinator.js +3 -4
- package/dist/app/session-shell/dock-chrome.d.ts +11 -6
- package/dist/app/session-shell/dock-chrome.js +5 -8
- package/dist/app/session-shell/editor-hyperlink-budget.d.ts +0 -2
- package/dist/app/session-shell/editor-hyperlink-budget.js +1 -1
- package/dist/app/session-shell/exit-notice.d.ts +2 -2
- package/dist/app/session-shell/exit-notice.js +1 -1
- package/dist/app/session-shell/extension-surface.d.ts +8 -7
- package/dist/app/session-shell/helper-pool.d.ts +3 -4
- package/dist/app/session-shell/helper-pool.js +1 -1
- package/dist/app/session-shell/image-preparation-client.d.ts +4 -3
- package/dist/app/session-shell/image-preparation.d.ts +0 -2
- package/dist/app/session-shell/image-preparation.js +2 -2
- package/dist/app/session-shell/image-source.d.ts +2 -3
- package/dist/app/session-shell/image-source.js +2 -2
- package/dist/app/session-shell/input-surface-switch.d.ts +9 -7
- package/dist/app/session-shell/input-surface-switch.js +1 -2
- package/dist/app/session-shell/login-interaction.d.ts +5 -4
- package/dist/app/session-shell/login-interaction.js +2 -3
- package/dist/app/session-shell/paste-executor.d.ts +4 -8
- package/dist/app/session-shell/paste-executor.js +2 -2
- package/dist/app/session-shell/paste-protocol.d.ts +2 -2
- package/dist/app/session-shell/path-chip-presentation.d.ts +0 -5
- package/dist/app/session-shell/path-chip-presentation.js +3 -3
- package/dist/app/session-shell/prompt-chips.d.ts +8 -7
- package/dist/app/session-shell/prompt-history-controller.d.ts +3 -3
- package/dist/app/session-shell/prompt-submission.d.ts +5 -2
- package/dist/app/session-shell/prompt-submission.js +13 -14
- package/dist/app/session-shell/quit-outro-effects.d.ts +3 -3
- package/dist/app/session-shell/quit-outro-effects.js +1 -4
- package/dist/app/session-shell/quit-outro.d.ts +9 -12
- package/dist/app/session-shell/quit-outro.js +11 -11
- package/dist/app/session-shell/resource-labels.d.ts +2 -0
- package/dist/app/session-shell/resource-labels.js +158 -0
- package/dist/app/session-shell/response-copy-protocol.d.ts +3 -2
- package/dist/app/session-shell/response-copy-transport.d.ts +2 -14
- package/dist/app/session-shell/response-copy-transport.js +1 -1
- package/dist/app/session-shell/session-lifecycle.d.ts +2 -1
- package/dist/app/session-shell/session-prompt-history.d.ts +29 -0
- package/dist/app/session-shell/session-prompt-history.js +80 -0
- package/dist/app/session-shell/session-selectors.d.ts +46 -0
- package/dist/app/session-shell/session-selectors.js +269 -0
- package/dist/app/session-shell/session-shell-root.d.ts +76 -113
- package/dist/app/session-shell/session-shell-root.js +103 -329
- package/dist/app/session-shell/session-shell.d.ts +14 -37
- package/dist/app/session-shell/session-shell.js +177 -612
- package/dist/app/session-shell/session-viewport-controller.d.ts +9 -16
- package/dist/app/session-shell/session-viewport-controller.js +42 -320
- package/dist/app/session-shell/settings-bindings.d.ts +25 -3
- package/dist/app/session-shell/settings-bindings.js +26 -2
- package/dist/app/session-shell/share-operation.d.ts +3 -3
- package/dist/app/session-shell/share-operation.js +4 -6
- package/dist/app/session-shell/shell-clipboard.d.ts +59 -0
- package/dist/app/session-shell/shell-clipboard.js +119 -0
- package/dist/app/session-shell/shell-editor-factory.d.ts +8 -4
- package/dist/app/session-shell/shell-editor-factory.js +13 -15
- package/dist/app/session-shell/shell-host.d.ts +16 -17
- package/dist/app/session-shell/shell-host.js +18 -19
- package/dist/app/session-shell/shell-layout.d.ts +2 -2
- package/dist/app/session-shell/shell-prompt-suggestions.d.ts +26 -0
- package/dist/app/session-shell/shell-prompt-suggestions.js +48 -0
- package/dist/app/session-shell/suggestion-surface.d.ts +1 -6
- package/dist/app/session-shell/suggestion-surface.js +1 -1
- package/dist/app/session-shell/system-clipboard.d.ts +2 -14
- package/dist/app/session-shell/system-clipboard.js +2 -7
- package/dist/app/session-shell/transcript-document.d.ts +11 -8
- package/dist/app/session-shell/transcript-document.js +13 -14
- package/dist/app/session-shell/viewport-layout.d.ts +2 -2
- package/dist/app/session-shell/viewport-pointer.d.ts +83 -0
- package/dist/app/session-shell/viewport-pointer.js +361 -0
- package/dist/app/session-shell/workflow-output.d.ts +5 -3
- package/dist/app/session-shell/workflow-output.js +13 -15
- package/dist/cli/package-messages.d.ts +0 -1
- package/dist/cli/package-messages.js +1 -1
- package/dist/cli/session-context.d.ts +1 -1
- package/dist/cli/uninstall.d.ts +3 -2
- package/dist/composition/owned-settings.d.ts +2 -1
- package/dist/composition/owned-settings.js +0 -3
- package/dist/composition/owned-ui.d.ts +1 -1
- package/dist/composition/owned-ui.js +77 -73
- package/dist/composition/reference-selection-options.d.ts +1 -1
- package/dist/composition/reference-selection-options.js +1 -1
- package/dist/composition/session-runtime-registry.d.ts +2 -1
- package/dist/composition/settings-route-host.js +3 -10
- package/dist/composition/settings-search-input.d.ts +2 -1
- package/dist/composition/startup-route.d.ts +2 -2
- package/dist/composition/startup-route.js +2 -2
- package/dist/contracts/owned-ui/extension-ui.d.ts +2 -1
- package/dist/contracts/owned-ui/index.d.ts +2 -1
- package/dist/contracts/owned-ui/index.js +1 -1
- package/dist/contracts/owned-ui/session-presenters.d.ts +3 -0
- package/dist/contracts/owned-ui/shell-components.d.ts +543 -0
- package/dist/contracts/owned-ui/validation.d.ts +1 -11
- package/dist/contracts/owned-ui/validation.js +8 -104
- package/dist/contracts/presentation/component.d.ts +17 -0
- package/dist/contracts/presentation/component.js +8 -0
- package/dist/contracts/presentation/index.d.ts +6 -15
- package/dist/contracts/presentation/index.js +2 -0
- package/dist/contracts/presentation/terminal.d.ts +284 -0
- package/dist/contracts/presentation/terminal.js +1 -0
- package/dist/contracts/presentation/theme.d.ts +46 -0
- package/dist/contracts/presentation/theme.js +1 -0
- package/dist/features/launch/development-launch.js +1 -1
- package/dist/features/launch/runtime-selection.d.ts +2 -2
- package/dist/features/launch/runtime-selection.js +2 -2
- package/dist/features/owned-ui/project-trust-prompt.d.ts +2 -2
- package/dist/features/owned-ui/project-trust-prompt.js +1 -1
- package/dist/features/owned-ui/release-note-state.d.ts +2 -1
- package/dist/features/owned-ui/settings-app.js +49 -425
- package/dist/features/owned-ui/settings-edits.d.ts +31 -0
- package/dist/features/owned-ui/settings-edits.js +139 -0
- package/dist/features/owned-ui/settings-model-dialog.d.ts +41 -0
- package/dist/features/owned-ui/settings-model-dialog.js +194 -0
- package/dist/features/owned-ui/settings-scroll-rail.d.ts +29 -0
- package/dist/features/owned-ui/settings-scroll-rail.js +79 -0
- package/dist/features/owned-ui/settings-search-input.d.ts +2 -1
- package/dist/features/prompt-history/service.d.ts +3 -2
- package/dist/foundation/lifecycle/claim-gate.d.ts +2 -1
- package/dist/foundation/release/automatic-update.d.ts +5 -14
- package/dist/foundation/release/automatic-update.js +15 -22
- package/dist/foundation/release/bootstrap.js +4 -4
- package/dist/foundation/release/dependency-certification.d.ts +0 -1
- package/dist/foundation/release/dependency-certification.js +1 -1
- package/dist/foundation/release/dependency-layer.js +3 -3
- package/dist/foundation/release/early-accent.d.ts +2 -2
- package/dist/foundation/release/early-accent.js +1 -1
- package/dist/foundation/release/index.d.ts +2 -2
- package/dist/foundation/release/index.js +1 -1
- package/dist/foundation/release/latest-release.d.ts +3 -18
- package/dist/foundation/release/latest-release.js +11 -11
- package/dist/foundation/release/managed-path.d.ts +10 -0
- package/dist/foundation/release/managed-path.js +26 -0
- package/dist/foundation/release/ordinary-launch-selection.d.ts +1 -1
- package/dist/foundation/release/ordinary-launch-selection.js +1 -1
- package/dist/foundation/release/release-gc.d.ts +3 -3
- package/dist/foundation/release/release-gc.js +10 -12
- package/dist/foundation/release/{cohort-state.d.ts → release-state.d.ts} +23 -23
- package/dist/foundation/release/{cohort-state.js → release-state.js} +8 -8
- package/dist/foundation/release/restart-certification.js +3 -4
- package/dist/foundation/release/update-activation.js +3 -3
- package/dist/foundation/release/update-execution-lease.d.ts +2 -3
- package/dist/foundation/release/update-execution-lease.js +2 -8
- package/dist/foundation/release/update-installer.d.ts +45 -0
- package/dist/foundation/release/update-installer.js +57 -0
- package/dist/foundation/release/update-launch.d.ts +2 -2
- package/dist/foundation/release/update-recovery.js +2 -9
- package/dist/foundation/release/update.d.ts +4 -25
- package/dist/foundation/release/update.js +164 -183
- package/dist/foundation/startup/startup-budget.d.ts +5 -5
- package/dist/foundation/startup/startup-budget.js +2 -2
- package/dist/integrations/pi/components/bracketed-paste.d.ts +33 -0
- package/dist/integrations/pi/components/bracketed-paste.js +123 -0
- package/dist/integrations/pi/components/editor-interaction.d.ts +4 -12
- package/dist/integrations/pi/components/index.d.ts +15 -9
- package/dist/integrations/pi/components/index.js +9 -5
- package/dist/integrations/pi/components/lazy-selectors.d.ts +2 -10
- package/dist/integrations/pi/components/lazy-selectors.js +1 -1
- package/dist/integrations/pi/components/modal-frame.d.ts +5 -22
- package/dist/integrations/pi/components/modal-frame.js +3 -23
- package/dist/integrations/pi/components/owned-editor-ux.d.ts +4 -3
- package/dist/integrations/pi/components/owned-editor-ux.js +46 -140
- package/dist/integrations/pi/components/prompt-input-port.d.ts +2 -19
- package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -1
- package/dist/integrations/pi/components/shell-editor-autocomplete.d.ts +3 -2
- package/dist/integrations/pi/components/shell-footer-status.d.ts +2 -2
- package/dist/integrations/pi/components/shell-footer-status.js +3 -2
- package/dist/integrations/pi/components/shell-presenters-info.d.ts +6 -5
- package/dist/integrations/pi/components/shell-presenters-info.js +2 -1
- package/dist/integrations/pi/components/shell-session-info-reference.d.ts +2 -1
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +33 -227
- package/dist/integrations/pi/components/shell-shared-facade.js +8 -1
- package/dist/integrations/pi/components/skills-command.d.ts +1 -9
- package/dist/integrations/pi/components/skills-command.js +5 -5
- package/dist/integrations/pi/components/theme.d.ts +9 -2
- package/dist/integrations/pi/components/theme.js +17 -2
- package/dist/integrations/pi/components/thinking-selector-dialog.d.ts +2 -1
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +2 -2
- package/dist/integrations/pi/engine/adapter.d.ts +4 -13
- package/dist/integrations/pi/engine/adapter.js +9 -61
- package/dist/integrations/pi/engine/changelog.d.ts +2 -2
- package/dist/integrations/pi/engine/changelog.js +3 -3
- package/dist/integrations/pi/engine/compaction-progress.d.ts +2 -3
- package/dist/integrations/pi/engine/compaction-progress.js +1 -1
- package/dist/integrations/pi/engine/conformance.d.ts +2 -1
- package/dist/integrations/pi/engine/default-model-setting.d.ts +0 -2
- package/dist/integrations/pi/engine/default-model-setting.js +1 -2
- package/dist/integrations/pi/engine/event-delivery.d.ts +2 -1
- package/dist/integrations/pi/engine/extension-ui-binding.d.ts +2 -1
- package/dist/integrations/pi/engine/host.js +3 -3
- package/dist/integrations/pi/engine/message-values.d.ts +0 -1
- package/dist/integrations/pi/engine/message-values.js +1 -1
- package/dist/integrations/pi/engine/pending-delivery.d.ts +0 -4
- package/dist/integrations/pi/engine/pending-delivery.js +3 -3
- package/dist/integrations/pi/engine/ports.d.ts +7 -1
- package/dist/integrations/pi/engine/ports.js +4 -0
- package/dist/integrations/pi/engine/project-trust-preflight.d.ts +2 -1
- package/dist/integrations/pi/engine/prompt-suggestions.d.ts +3 -2
- package/dist/integrations/pi/engine/provider-authentication.d.ts +1 -1
- package/dist/integrations/pi/engine/public-main-entry.d.ts +1 -5
- package/dist/integrations/pi/engine/public-main-entry.js +1 -1
- package/dist/integrations/pi/engine/repository-metadata.d.ts +49 -0
- package/dist/integrations/pi/engine/repository-metadata.js +189 -0
- package/dist/integrations/pi/engine/repository-pr-rest.d.ts +1 -9
- package/dist/integrations/pi/engine/repository-pr-rest.js +2 -2
- package/dist/integrations/pi/engine/repository-pr.d.ts +1 -3
- package/dist/integrations/pi/engine/repository-pr.js +1 -1
- package/dist/integrations/pi/engine/resource-catalog.d.ts +2 -1
- package/dist/integrations/pi/engine/session-integration.d.ts +1 -1
- package/dist/integrations/pi/engine/session-runtime.d.ts +7 -12
- package/dist/integrations/pi/engine/session-runtime.js +21 -178
- package/dist/integrations/pi/engine/settings-bridge.d.ts +0 -2
- package/dist/integrations/pi/engine/settings-bridge.js +1 -1
- package/dist/integrations/pi/engine/settings-port.d.ts +3 -2
- package/dist/integrations/pi/engine/transcript-projection.d.ts +2 -1
- package/dist/integrations/pi/engine/view-state.d.ts +21 -2
- package/dist/integrations/pi/engine/view-state.js +129 -1
- package/dist/integrations/pi/engine/workflow-contexts.d.ts +1 -1
- package/dist/integrations/pi/engine/workflow-runner.d.ts +1 -2
- package/dist/integrations/pi/engine/workflow-runner.js +254 -365
- package/dist/integrations/pi/engine/workflow-share.d.ts +9 -0
- package/dist/integrations/pi/engine/workflow-share.js +168 -0
- package/dist/integrations/pi/engine/workflow-support.d.ts +0 -20
- package/dist/integrations/pi/engine/workflow-support.js +4 -65
- package/dist/integrations/pi/engine/workflows.d.ts +5 -5
- package/dist/integrations/pi/session-presenters/components.d.ts +3 -0
- package/dist/integrations/pi/session-presenters/components.js +75 -0
- package/dist/integrations/pi/session-presenters/index.d.ts +1 -0
- package/dist/integrations/pi/session-presenters/index.js +1 -0
- package/dist/integrations/pi/session-presenters/presentation.d.ts +3 -0
- package/dist/integrations/pi/session-presenters/presentation.js +10 -0
- package/dist/integrations/pi/session-presenters/presenters.d.ts +2 -1
- package/dist/integrations/pi/session-presenters/presenters.js +3 -1
- package/dist/integrations/pi/tui-runtime/adapter.d.ts +9 -19
- package/dist/integrations/pi/tui-runtime/adapter.js +56 -174
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +9 -44
- package/dist/integrations/pi/tui-runtime/index.d.ts +1 -1
- package/dist/integrations/pi/tui-runtime/index.js +1 -0
- package/dist/integrations/pi/tui-runtime/input-presentation-coordinator.d.ts +4 -6
- package/dist/integrations/pi/tui-runtime/overlay-geometry.d.ts +4 -10
- package/dist/integrations/pi/tui-runtime/overlay-geometry.js +3 -9
- package/dist/integrations/pi/tui-runtime/presentation-adapter.d.ts +2 -2
- package/dist/integrations/pi/tui-runtime/runtime-factory.d.ts +3 -0
- package/dist/integrations/pi/tui-runtime/runtime-factory.js +11 -0
- package/dist/ui/components/index.d.ts +2 -2
- package/dist/ui/components/index.js +1 -1
- package/dist/ui/components/selection-copy.d.ts +0 -1
- package/dist/ui/components/selection-copy.js +0 -12
- package/dist/ui/components/theme.d.ts +4 -19
- package/dist/ui/components/theme.js +6 -0
- package/dist/ui/components/transcript-viewport-frame.d.ts +120 -0
- package/dist/ui/components/transcript-viewport-frame.js +314 -0
- package/dist/ui/components/transcript-viewport-types.d.ts +147 -0
- package/dist/ui/components/transcript-viewport-types.js +1 -0
- package/dist/ui/components/transcript-viewport.d.ts +2 -147
- package/dist/ui/components/transcript-viewport.js +87 -315
- package/dist/ui/settings/declarations.d.ts +2 -3
- package/dist/ui/settings/declarations.js +2 -3
- package/dist/ui/settings/early-accent.js +1 -1
- package/dist/ui/settings/index.d.ts +3 -5
- package/dist/ui/settings/index.js +2 -3
- package/dist/ui/settings/manager.d.ts +0 -4
- package/dist/ui/settings/manager.js +6 -62
- package/dist/ui/settings/resolution.d.ts +6 -18
- package/dist/ui/settings/resolution.js +4 -103
- package/dist/ui/settings/sections.d.ts +0 -4
- package/dist/ui/settings/sections.js +1 -1
- package/docs/architecture/boundaries.md +2 -2
- package/docs/architecture/internal-naming.md +2 -0
- package/docs/architecture/project-structure.md +4 -2
- package/docs/validation.md +1 -1
- package/package.json +3 -4
- package/dist/integrations/pi/components/components.d.ts +0 -4
- package/dist/integrations/pi/components/components.js +0 -48
- package/dist/integrations/pi/components/conformance.d.ts +0 -18
- package/dist/integrations/pi/components/conformance.js +0 -70
- package/dist/integrations/pi/components/shell-components.d.ts +0 -7
- package/dist/integrations/pi/components/shell-components.js +0 -7
- package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +0 -33
- package/dist/integrations/pi/components/upstream/theme/theme-controller.js +0 -114
- package/dist/integrations/pi/engine/diagnostics-state.d.ts +0 -9
- package/dist/integrations/pi/engine/diagnostics-state.js +0 -34
- package/dist/integrations/pi/engine/usage-view.d.ts +0 -4
- package/dist/integrations/pi/engine/usage-view.js +0 -56
- package/dist/integrations/pi/tui-runtime/contracts.d.ts +0 -166
- package/dist/ui/settings/migrations.d.ts +0 -19
- package/dist/ui/settings/migrations.js +0 -225
- package/dist/ui/settings/progress-palette.generated.d.ts +0 -139
- package/dist/ui/settings/progress-palette.generated.js +0 -139
- /package/dist/{integrations/pi/tui-runtime/contracts.js → contracts/owned-ui/shell-components.js} +0 -0
- /package/dist/{foundation/release → contracts/presentation}/progress-palette.generated.d.ts +0 -0
- /package/dist/{foundation/release → contracts/presentation}/progress-palette.generated.js +0 -0
|
@@ -5,11 +5,6 @@ import { assertSourceBytes } from "./image-source.js";
|
|
|
5
5
|
const MAX_CLIPBOARD_BYTES = 16 * 1024 * 1024;
|
|
6
6
|
let nativeClipboardPromise;
|
|
7
7
|
let pendingClipboardWrite = Promise.resolve();
|
|
8
|
-
/** Load the native adapter during shell startup so the first paste is warm. */
|
|
9
|
-
export function preloadSystemClipboard() {
|
|
10
|
-
if (process.platform === "win32" || process.platform === "darwin")
|
|
11
|
-
void nativeClipboard();
|
|
12
|
-
}
|
|
13
8
|
/**
|
|
14
9
|
* Reads plain text through platform clipboard commands without importing Pi's
|
|
15
10
|
* private clipboard module. Failures are deliberately non-fatal: a denied or
|
|
@@ -38,7 +33,7 @@ export async function readSystemClipboardContent(signal, strict = false) {
|
|
|
38
33
|
const text = await readSystemClipboardText(signal, strict);
|
|
39
34
|
return text === null ? null : { kind: "text", text };
|
|
40
35
|
}
|
|
41
|
-
|
|
36
|
+
async function readSystemClipboardImage(reader) {
|
|
42
37
|
if (!reader.hasImage())
|
|
43
38
|
return null;
|
|
44
39
|
if (reader.getImageBinary !== undefined) {
|
|
@@ -74,7 +69,7 @@ export async function readSystemClipboardImage(reader) {
|
|
|
74
69
|
}
|
|
75
70
|
return null;
|
|
76
71
|
}
|
|
77
|
-
|
|
72
|
+
async function readSystemClipboardText(signal, strict = false) {
|
|
78
73
|
// Concurrency: Ctrl+C/Ctrl+X and Ctrl+V can arrive in adjacent input turns. Serialize the
|
|
79
74
|
// read behind our native write so paste never observes the previous value.
|
|
80
75
|
await pendingClipboardWrite;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { OwnedUiShellComponents, OwnedUiShellTranscriptComponentPort } from "../../contracts/owned-ui/index.js";
|
|
1
2
|
import type { OwnedUiSessionViewModel } from "../../contracts/owned-ui/index.js";
|
|
3
|
+
import type { ThemeSource } from "../../contracts/presentation/index.js";
|
|
2
4
|
import type { TranscriptPromptAnchor } from "../../ui/components/transcript-viewport.js";
|
|
3
|
-
import type { PiShellTranscriptComponentPort } from "../../integrations/pi/components/shell-shared-facade.js";
|
|
4
5
|
type TranscriptBlock = OwnedUiSessionViewModel["transcript"][number];
|
|
5
6
|
export interface TranscriptDocumentLayout {
|
|
6
7
|
readonly rows: readonly string[];
|
|
@@ -13,7 +14,7 @@ export interface TranscriptDocumentLayout {
|
|
|
13
14
|
*/
|
|
14
15
|
export type TranscriptInvalidation = "editor-padding" | "diagnostics" | "workflow-status" | "extension-header" | "viewport-config" | "extension-renderers" | "block-presentation" | "tools-expanded" | "repaint";
|
|
15
16
|
/** What the document reads from the shell around it on every uncached layout. */
|
|
16
|
-
|
|
17
|
+
interface TranscriptDocumentChrome {
|
|
17
18
|
diagnostics(): OwnedUiSessionViewModel["diagnostics"];
|
|
18
19
|
/** The extension header's rows when one is set, else the built-in header's rows for this layout. */
|
|
19
20
|
headerRows(width: number): readonly string[];
|
|
@@ -23,11 +24,13 @@ export interface TranscriptDocumentChrome {
|
|
|
23
24
|
hasExtensionHeader(): boolean;
|
|
24
25
|
thinkingVisible(): boolean;
|
|
25
26
|
}
|
|
26
|
-
|
|
27
|
+
interface TranscriptDocumentOptions {
|
|
28
|
+
readonly theme: ThemeSource;
|
|
29
|
+
readonly components: Pick<OwnedUiShellComponents, "info" | "transcript">;
|
|
27
30
|
readonly customViewport: boolean;
|
|
28
31
|
readonly cwd: string;
|
|
29
32
|
/** Creates the component for a newly seen block; its change callback should call `blockChanged`. */
|
|
30
|
-
mount(block: TranscriptBlock):
|
|
33
|
+
mount(block: TranscriptBlock): OwnedUiShellTranscriptComponentPort;
|
|
31
34
|
readonly chrome: TranscriptDocumentChrome;
|
|
32
35
|
}
|
|
33
36
|
/**
|
|
@@ -40,8 +43,8 @@ export declare class TranscriptDocument {
|
|
|
40
43
|
/** Block component renders since construction, for rendering evidence. */
|
|
41
44
|
get renderCount(): number;
|
|
42
45
|
get lastId(): string | undefined;
|
|
43
|
-
component(id: string):
|
|
44
|
-
components(): IterableIterator<
|
|
46
|
+
component(id: string): OwnedUiShellTranscriptComponentPort | undefined;
|
|
47
|
+
components(): IterableIterator<OwnedUiShellTranscriptComponentPort>;
|
|
45
48
|
anchorOf(id: string): number | undefined;
|
|
46
49
|
/**
|
|
47
50
|
* Applies one block: its component is created or updated in place and the order grows
|
|
@@ -52,7 +55,7 @@ export declare class TranscriptDocument {
|
|
|
52
55
|
/** Replaces the whole transcript with the view's blocks, keeping anchored workflow output in place. */
|
|
53
56
|
sync(blocks: OwnedUiSessionViewModel["transcript"]): void;
|
|
54
57
|
/** Appends workflow output anchored after the transcript's first `anchor` blocks. */
|
|
55
|
-
appendAnchored(id: string, component:
|
|
58
|
+
appendAnchored(id: string, component: OwnedUiShellTranscriptComponentPort, anchor: number): void;
|
|
56
59
|
/** Disposes every anchored workflow output and drops it from the order. */
|
|
57
60
|
removeAnchored(): void;
|
|
58
61
|
/** One block's component drew something new: drop its rows and every layout that contains them. */
|
|
@@ -73,5 +76,5 @@ export declare function parseReleaseUpdateDiagnostic(message: string): {
|
|
|
73
76
|
changelogUrl: string | null;
|
|
74
77
|
} | null;
|
|
75
78
|
/** Web URLs use link blue; file targets retain A1's cyan interactive accent. */
|
|
76
|
-
export declare function
|
|
79
|
+
export declare function transcriptLinkColor(theme: ThemeSource): (text: string, target: string) => string;
|
|
77
80
|
export {};
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { acceptsTranscriptUpdate } from "../../contracts/owned-ui/index.js";
|
|
2
2
|
import { nativeHyperlinkStyle } from "../../ui/components/spans.js";
|
|
3
|
-
import { createPiShellChangelog, createPiShellCollapsedChangelog, renderPiShellPackageUpdateNotice, renderPiShellReleaseUpdateNotice, } from "../../integrations/pi/components/shell-presenters-info.js";
|
|
4
|
-
import { isPiPromptStyleCompaction, renderPiShellStartupDiagnostic, renderPiShellTranscriptBlock, } from "../../integrations/pi/components/shell-presenters-transcript.js";
|
|
5
|
-
import { piTheme } from "../../integrations/pi/components/upstream/theme/theme.js";
|
|
6
3
|
const LAYOUT_ONLY = new Set(["editor-padding", "diagnostics", "workflow-status", "extension-header"]);
|
|
7
4
|
const WORKFLOW_STATUS_PREFIX = "workflow-status-";
|
|
8
5
|
/**
|
|
@@ -19,8 +16,10 @@ export class TranscriptDocument {
|
|
|
19
16
|
// Performance: document layouts are shared by wheel, rail, jump, and selection frames.
|
|
20
17
|
#layouts = new Map();
|
|
21
18
|
#renders = 0;
|
|
19
|
+
#linkColor;
|
|
22
20
|
constructor(options) {
|
|
23
21
|
this.#options = options;
|
|
22
|
+
this.#linkColor = transcriptLinkColor(options.theme);
|
|
24
23
|
}
|
|
25
24
|
/** Block component renders since construction, for rendering evidence. */
|
|
26
25
|
get renderCount() {
|
|
@@ -171,7 +170,7 @@ export class TranscriptDocument {
|
|
|
171
170
|
// bare A1 presents them in its prompt-adjacent notice dock instead.
|
|
172
171
|
.filter(diagnostic => diagnostic.code === "engine-startup"
|
|
173
172
|
|| !customViewport && diagnostic.code === "project-trust")
|
|
174
|
-
.flatMap(diagnostic =>
|
|
173
|
+
.flatMap(diagnostic => this.#options.components.transcript.renderStartupDiagnostic(diagnostic, width));
|
|
175
174
|
const resourceRows = [...chrome.resourceRows(width)];
|
|
176
175
|
if (resourceRows.at(-1) === "")
|
|
177
176
|
resourceRows.pop();
|
|
@@ -191,7 +190,7 @@ export class TranscriptDocument {
|
|
|
191
190
|
if (!thinkingVisible && block?.kind === "thinking")
|
|
192
191
|
continue;
|
|
193
192
|
const promptLike = block !== undefined
|
|
194
|
-
&& (block.kind === "user" || customViewport &&
|
|
193
|
+
&& (block.kind === "user" || customViewport && this.#options.components.transcript.isPromptStyleCompaction(block));
|
|
195
194
|
// Invariant: the custom viewport has already removed its rail gutter from this width.
|
|
196
195
|
// Prompt-like and ordinary blocks therefore share one right content edge.
|
|
197
196
|
const blockWidth = width;
|
|
@@ -240,11 +239,11 @@ export class TranscriptDocument {
|
|
|
240
239
|
.filter(diagnostic => !customViewport && diagnostic.code === "release-update")
|
|
241
240
|
.flatMap(diagnostic => {
|
|
242
241
|
const release = parseReleaseUpdateDiagnostic(diagnostic.message);
|
|
243
|
-
return release === null ? [] :
|
|
242
|
+
return release === null ? [] : this.#options.components.info.releaseUpdateNotice(release, width);
|
|
244
243
|
}));
|
|
245
244
|
rows.push(...diagnostics
|
|
246
245
|
.filter(diagnostic => diagnostic.code === "package-updates")
|
|
247
|
-
.flatMap(diagnostic =>
|
|
246
|
+
.flatMap(diagnostic => this.#options.components.info.packageUpdateNotice(diagnostic.message.split("\n").filter(line => line.startsWith("- ")).map(line => line.slice(2)), width)));
|
|
248
247
|
rows.push(...diagnostics
|
|
249
248
|
.filter(diagnostic => diagnostic.code === "changelog-collapsed" || diagnostic.code === "changelog-expanded")
|
|
250
249
|
// Rationale: bare A1 translates either startup diagnostic into transient dock chrome;
|
|
@@ -252,8 +251,8 @@ export class TranscriptDocument {
|
|
|
252
251
|
.flatMap(diagnostic => customViewport
|
|
253
252
|
? []
|
|
254
253
|
: diagnostic.code === "changelog-collapsed"
|
|
255
|
-
?
|
|
256
|
-
:
|
|
254
|
+
? this.#options.components.info.collapsedChangelog().render(width)
|
|
255
|
+
: this.#options.components.info.changelog(diagnostic.message).render(width)));
|
|
257
256
|
rows.push(...diagnostics
|
|
258
257
|
.filter(diagnostic => diagnostic.code !== "engine-startup" && diagnostic.code !== "project-trust"
|
|
259
258
|
&& diagnostic.code !== "release-update" && diagnostic.code !== "release-update-installed"
|
|
@@ -261,7 +260,7 @@ export class TranscriptDocument {
|
|
|
261
260
|
&& diagnostic.code !== "package-updates" && diagnostic.code !== "changelog-collapsed"
|
|
262
261
|
&& diagnostic.code !== "changelog-expanded")
|
|
263
262
|
.slice(-3)
|
|
264
|
-
.flatMap(diagnostic =>
|
|
263
|
+
.flatMap(diagnostic => this.#options.components.transcript.renderBlock({
|
|
265
264
|
id: `diagnostic-${diagnostic.sequence}`,
|
|
266
265
|
kind: diagnostic.severity === "error" ? "error" : "system",
|
|
267
266
|
status: "finalized",
|
|
@@ -280,7 +279,7 @@ export class TranscriptDocument {
|
|
|
280
279
|
const block = this.#blocks.get(id);
|
|
281
280
|
if (block === undefined || (!thinkingVisible && block.kind === "thinking"))
|
|
282
281
|
continue;
|
|
283
|
-
if (rows.length > 0 && (block.kind === "user" || this.#options.customViewport &&
|
|
282
|
+
if (rows.length > 0 && (block.kind === "user" || this.#options.customViewport && this.#options.components.transcript.isPromptStyleCompaction(block)))
|
|
284
283
|
rows.push("");
|
|
285
284
|
rows.push(...this.#blockRows(id, block, width).map(sanitizeExitTranscriptRow));
|
|
286
285
|
}
|
|
@@ -298,7 +297,7 @@ export class TranscriptDocument {
|
|
|
298
297
|
const rows = component.render(width);
|
|
299
298
|
if (!this.#options.customViewport || block?.kind === "user")
|
|
300
299
|
return rows;
|
|
301
|
-
return rows.map(row => nativeHyperlinkStyle(row,
|
|
300
|
+
return rows.map(row => nativeHyperlinkStyle(row, this.#linkColor));
|
|
302
301
|
};
|
|
303
302
|
if (block === undefined || block.status !== "finalized")
|
|
304
303
|
return render();
|
|
@@ -336,6 +335,6 @@ function sanitizeExitTranscriptRow(row) {
|
|
|
336
335
|
return row.replace(KITTY_IMAGE_CONTROL, "").replace(ITERM_IMAGE_CONTROL, "");
|
|
337
336
|
}
|
|
338
337
|
/** Web URLs use link blue; file targets retain A1's cyan interactive accent. */
|
|
339
|
-
export function
|
|
340
|
-
return
|
|
338
|
+
export function transcriptLinkColor(theme) {
|
|
339
|
+
return (text, target) => theme.current().fg(/^file:/iu.test(target) ? "accent" : "mdLink", text);
|
|
341
340
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import type { OwnedUiShellComponentPort } from "../../contracts/owned-ui/index.js";
|
|
1
2
|
import type { TranscriptPromptAnchor, TranscriptViewportFrameInput } from "../../ui/components/transcript-viewport.js";
|
|
2
|
-
import type { PiShellComponentPort } from "../../integrations/pi/components/shell-shared-facade.js";
|
|
3
3
|
import type { ShellLayout, ShellLayoutPorts } from "./shell-layout.js";
|
|
4
4
|
interface VisibleViewportSnapshot {
|
|
5
5
|
readonly width: number;
|
|
@@ -8,7 +8,7 @@ interface VisibleViewportSnapshot {
|
|
|
8
8
|
readonly transientSignature: string;
|
|
9
9
|
readonly promptAnchors: readonly TranscriptPromptAnchor[];
|
|
10
10
|
readonly dockLength: number;
|
|
11
|
-
readonly inputSurface:
|
|
11
|
+
readonly inputSurface: OwnedUiShellComponentPort;
|
|
12
12
|
readonly viewportRevision: number;
|
|
13
13
|
readonly selectionRevision: number;
|
|
14
14
|
readonly pointerPosition: TranscriptViewportFrameInput["pointerPosition"];
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { OwnedUiShellEditorPort, OwnedUiViewportSettings } from "../../contracts/owned-ui/index.js";
|
|
2
|
+
import type { TerminalPointerSurface } from "../../contracts/presentation/index.js";
|
|
3
|
+
import { type RoutedMouseInput } from "../../ui/components/mouse.js";
|
|
4
|
+
import type { SelectionCopySnapshot } from "../../ui/components/selection-copy.js";
|
|
5
|
+
import type { TranscriptViewport, TranscriptViewportFrame } from "../../ui/components/transcript-viewport.js";
|
|
6
|
+
/** One-based, inclusive terminal cells of a clickable viewport-tail control. */
|
|
7
|
+
export interface TailControlRegion {
|
|
8
|
+
readonly rowStart: number;
|
|
9
|
+
readonly rowEnd: number;
|
|
10
|
+
readonly columnStart: number;
|
|
11
|
+
readonly columnEnd: number;
|
|
12
|
+
}
|
|
13
|
+
export type TailControl = TailControlRegion & {
|
|
14
|
+
readonly activate: () => void;
|
|
15
|
+
};
|
|
16
|
+
export declare function withinTailControl(region: TailControlRegion, column: number, row: number): boolean;
|
|
17
|
+
export interface ViewportPointerPorts {
|
|
18
|
+
readonly viewport: TranscriptViewport;
|
|
19
|
+
readonly editor: OwnedUiShellEditorPort;
|
|
20
|
+
config(): OwnedUiViewportSettings;
|
|
21
|
+
copyOnSelect(): boolean;
|
|
22
|
+
/** False while replacement input or overlay bounds have not been painted yet. */
|
|
23
|
+
inputGeometryReady(): boolean;
|
|
24
|
+
/** The topmost overlay or input surface under a cell. */
|
|
25
|
+
modalAt(column: number, row: number): TerminalPointerSurface | undefined;
|
|
26
|
+
/** The editor rows of the most recent composition. */
|
|
27
|
+
editorFrame(): {
|
|
28
|
+
readonly rowStart: number;
|
|
29
|
+
readonly rowEnd: number;
|
|
30
|
+
} | undefined;
|
|
31
|
+
tailControl(): TailControl | undefined;
|
|
32
|
+
clearTailControl(): void;
|
|
33
|
+
requestRender(): void;
|
|
34
|
+
requestHyperlinkCleanup(rows?: readonly number[]): void;
|
|
35
|
+
updateSelectionAutoScroll(column: number, row: number, viewportHeight: number, frameHeight: number): void;
|
|
36
|
+
stopSelectionAutoScroll(): void;
|
|
37
|
+
/** A right-click on the editor pastes the clipboard. */
|
|
38
|
+
pasteFromPointer(): void;
|
|
39
|
+
}
|
|
40
|
+
/** How one input chunk's mouse reports changed the viewport. */
|
|
41
|
+
export interface ViewportPointerOutcome {
|
|
42
|
+
repaint: boolean;
|
|
43
|
+
forceRepaint: boolean;
|
|
44
|
+
activity: boolean;
|
|
45
|
+
completedCopy: SelectionCopySnapshot | undefined;
|
|
46
|
+
}
|
|
47
|
+
interface PointerCall {
|
|
48
|
+
readonly allowWheel: boolean;
|
|
49
|
+
readonly now: number;
|
|
50
|
+
readonly editorActive: boolean;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The pointer gestures of the session viewport: which surface a gesture is latched to, the
|
|
54
|
+
* suppression of a gesture begun on the dock or a control, the editor click that waits for drag
|
|
55
|
+
* or release, the rail drag offset, the pointer position and the hovered link. Each report is
|
|
56
|
+
* routed in the same order of checks, and its effect is reported as an outcome.
|
|
57
|
+
*/
|
|
58
|
+
export declare class ViewportPointerGestures {
|
|
59
|
+
#private;
|
|
60
|
+
constructor(ports: ViewportPointerPorts);
|
|
61
|
+
get position(): {
|
|
62
|
+
readonly column: number;
|
|
63
|
+
readonly row: number;
|
|
64
|
+
} | undefined;
|
|
65
|
+
get editorSelecting(): boolean;
|
|
66
|
+
/** A gesture is latched to a surface or a selection is being dragged. */
|
|
67
|
+
get held(): boolean;
|
|
68
|
+
/** No pointer position or hovered link is remembered. */
|
|
69
|
+
get idle(): boolean;
|
|
70
|
+
/** Forget every latch. */
|
|
71
|
+
clear(): void;
|
|
72
|
+
/** Swallow the rest of a held gesture until its release. */
|
|
73
|
+
drain(): void;
|
|
74
|
+
/** Before the first paint, a left press and its motion and release belong to no surface. */
|
|
75
|
+
routeUnpainted(data: string): RoutedMouseInput;
|
|
76
|
+
route(data: string, frame: TranscriptViewportFrame, call: PointerCall): {
|
|
77
|
+
readonly routed: RoutedMouseInput;
|
|
78
|
+
readonly outcome: ViewportPointerOutcome;
|
|
79
|
+
};
|
|
80
|
+
/** A newly composed frame may move a link away from a stationary pointer. */
|
|
81
|
+
refreshHover(frame: TranscriptViewportFrame): void;
|
|
82
|
+
}
|
|
83
|
+
export {};
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { routeMouseInput } from "../../ui/components/mouse.js";
|
|
2
|
+
import { scrollForThumbRow, scrollForTrackPage, scrollbarWheelRows } from "../../ui/components/scrollbar.js";
|
|
3
|
+
import { readVisibleHyperlinks } from "../../ui/components/visible-hyperlinks.js";
|
|
4
|
+
export function withinTailControl(region, column, row) {
|
|
5
|
+
return row >= region.rowStart && row <= region.rowEnd && column >= region.columnStart && column <= region.columnEnd;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The pointer gestures of the session viewport: which surface a gesture is latched to, the
|
|
9
|
+
* suppression of a gesture begun on the dock or a control, the editor click that waits for drag
|
|
10
|
+
* or release, the rail drag offset, the pointer position and the hovered link. Each report is
|
|
11
|
+
* routed in the same order of checks, and its effect is reported as an outcome.
|
|
12
|
+
*/
|
|
13
|
+
export class ViewportPointerGestures {
|
|
14
|
+
#ports;
|
|
15
|
+
#dragGrabOffset = null;
|
|
16
|
+
#owner;
|
|
17
|
+
// Invariant: a right-click editor gesture remains owned by the dock.
|
|
18
|
+
#dockSuppressed = false;
|
|
19
|
+
// Invariant: a gesture begun on an explicit control remains owned by that control.
|
|
20
|
+
#tailSuppressed = false;
|
|
21
|
+
// Invariant: editor selection remains true only while its left button is held.
|
|
22
|
+
#editorSelecting = false;
|
|
23
|
+
// Invariant: no-drag editor presses replay on release; distinct motion promotes frame selection.
|
|
24
|
+
#pendingEditorClick;
|
|
25
|
+
#position;
|
|
26
|
+
#hoveredHyperlinkKey;
|
|
27
|
+
constructor(ports) {
|
|
28
|
+
this.#ports = ports;
|
|
29
|
+
}
|
|
30
|
+
get position() {
|
|
31
|
+
return this.#position;
|
|
32
|
+
}
|
|
33
|
+
get editorSelecting() {
|
|
34
|
+
return this.#editorSelecting;
|
|
35
|
+
}
|
|
36
|
+
/** A gesture is latched to a surface or a selection is being dragged. */
|
|
37
|
+
get held() {
|
|
38
|
+
return this.#owner !== undefined || this.#ports.viewport.selectionActive || this.#editorSelecting;
|
|
39
|
+
}
|
|
40
|
+
/** No pointer position or hovered link is remembered. */
|
|
41
|
+
get idle() {
|
|
42
|
+
return this.#position === undefined && this.#hoveredHyperlinkKey === undefined;
|
|
43
|
+
}
|
|
44
|
+
/** Forget every latch. */
|
|
45
|
+
clear() {
|
|
46
|
+
this.#dragGrabOffset = null;
|
|
47
|
+
this.#dockSuppressed = false;
|
|
48
|
+
this.#tailSuppressed = false;
|
|
49
|
+
this.#editorSelecting = false;
|
|
50
|
+
this.#pendingEditorClick = undefined;
|
|
51
|
+
this.#position = undefined;
|
|
52
|
+
this.#hoveredHyperlinkKey = undefined;
|
|
53
|
+
this.#owner = undefined;
|
|
54
|
+
}
|
|
55
|
+
/** Swallow the rest of a held gesture until its release. */
|
|
56
|
+
drain() {
|
|
57
|
+
this.#owner = "drain";
|
|
58
|
+
}
|
|
59
|
+
/** Before the first paint, a left press and its motion and release belong to no surface. */
|
|
60
|
+
routeUnpainted(data) {
|
|
61
|
+
// Invariant: a not-yet-painted A1 screen is not Pi's selection surface.
|
|
62
|
+
return routeMouseInput(data, event => {
|
|
63
|
+
if (event.kind === "press" && event.button === 0)
|
|
64
|
+
this.#tailSuppressed = true;
|
|
65
|
+
if (event.kind === "release")
|
|
66
|
+
this.#tailSuppressed = false;
|
|
67
|
+
return event.kind === "motion" || event.kind === "release" || (event.kind === "press" && event.button === 0);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
route(data, frame, call) {
|
|
71
|
+
const outcome = { repaint: false, forceRepaint: false, activity: false, completedCopy: undefined };
|
|
72
|
+
const routed = routeMouseInput(data, (event, report) => this.#report(event, report, frame, call, outcome));
|
|
73
|
+
return { routed, outcome };
|
|
74
|
+
}
|
|
75
|
+
/** A newly composed frame may move a link away from a stationary pointer. */
|
|
76
|
+
refreshHover(frame) {
|
|
77
|
+
const pointer = this.#position;
|
|
78
|
+
if (pointer === undefined || this.#ports.viewport.selectionActive || this.#editorSelecting)
|
|
79
|
+
return;
|
|
80
|
+
const next = hyperlinkKeyAt(frame, pointer.column, pointer.row);
|
|
81
|
+
if (this.#hoveredHyperlinkKey !== undefined && next !== this.#hoveredHyperlinkKey) {
|
|
82
|
+
// Platform: Windows Terminal can leave its solid native-hover underline behind
|
|
83
|
+
// when a following viewport moves the link away from a stationary pointer.
|
|
84
|
+
this.#ports.requestHyperlinkCleanup([pointer.row]);
|
|
85
|
+
this.#ports.requestRender();
|
|
86
|
+
}
|
|
87
|
+
this.#hoveredHyperlinkKey = next;
|
|
88
|
+
}
|
|
89
|
+
#report(event, report, frame, call, outcome) {
|
|
90
|
+
const viewport = this.#ports.viewport;
|
|
91
|
+
const hits = frame.hits;
|
|
92
|
+
const overModal = this.#ports.modalAt(event.column, event.row);
|
|
93
|
+
const wheel = event.kind === "wheel-up" || event.kind === "wheel-down";
|
|
94
|
+
// Invariant: latch each gesture to one surface.
|
|
95
|
+
if (this.#owner === "drain" || !this.#ports.inputGeometryReady()) {
|
|
96
|
+
if (event.kind === "release")
|
|
97
|
+
this.#owner = undefined;
|
|
98
|
+
else if (event.kind === "press")
|
|
99
|
+
this.#owner = "drain";
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
const owner = !wheel && this.#owner !== undefined ? this.#owner : overModal;
|
|
103
|
+
if (owner !== undefined && owner !== "viewport") {
|
|
104
|
+
if (event.kind === "press")
|
|
105
|
+
this.#owner = owner;
|
|
106
|
+
if (event.kind === "release")
|
|
107
|
+
this.#owner = undefined;
|
|
108
|
+
if (event.kind === "press" && viewport.clearSelection())
|
|
109
|
+
outcome.repaint = true;
|
|
110
|
+
viewport.setRailHovered(false);
|
|
111
|
+
viewport.setStickyHovered(false);
|
|
112
|
+
this.#position = undefined;
|
|
113
|
+
owner.component.handleInput?.(report);
|
|
114
|
+
outcome.repaint = true;
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
if (event.kind === "press")
|
|
118
|
+
this.#owner = "viewport";
|
|
119
|
+
if (event.kind === "release")
|
|
120
|
+
this.#owner = undefined;
|
|
121
|
+
const tailControl = this.#ports.tailControl();
|
|
122
|
+
const target = {
|
|
123
|
+
frame,
|
|
124
|
+
overRail: overModal === undefined && hits.rail !== null
|
|
125
|
+
&& event.column === hits.rail.column
|
|
126
|
+
&& event.row >= hits.rail.rowStart
|
|
127
|
+
&& event.row < hits.rail.rowStart + hits.rail.trackHeight,
|
|
128
|
+
overSticky: overModal === undefined && hits.sticky !== null && event.row === hits.sticky.row && event.column <= hits.sticky.width,
|
|
129
|
+
overBottom: overModal === undefined && hits.bottom !== null && event.row === hits.bottom.row
|
|
130
|
+
&& event.column >= hits.bottom.columnStart && event.column <= hits.bottom.columnEnd,
|
|
131
|
+
tailControl,
|
|
132
|
+
overTailControl: overModal === undefined && tailControl !== undefined
|
|
133
|
+
&& withinTailControl(tailControl, event.column, event.row),
|
|
134
|
+
};
|
|
135
|
+
this.#track(event, target, outcome);
|
|
136
|
+
switch (event.kind) {
|
|
137
|
+
case "motion": return this.#motion(event, target, call, outcome);
|
|
138
|
+
case "wheel-up":
|
|
139
|
+
case "wheel-down": return this.#wheel(event, frame, call, outcome);
|
|
140
|
+
case "press": return this.#press(event, target, call, outcome);
|
|
141
|
+
case "release": return this.#release(event, call, outcome);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Rationale: every report updates the pointer position, the hover of the bottom and tail controls, and the hovered link.
|
|
145
|
+
#track(event, target, outcome) {
|
|
146
|
+
const hits = target.frame.hits;
|
|
147
|
+
const tailControl = target.tailControl;
|
|
148
|
+
const previousPointer = this.#position;
|
|
149
|
+
const wasOverBottom = hits.bottom !== null && previousPointer !== undefined
|
|
150
|
+
&& previousPointer.row === hits.bottom.row
|
|
151
|
+
&& previousPointer.column >= hits.bottom.columnStart && previousPointer.column <= hits.bottom.columnEnd;
|
|
152
|
+
// Invariant: every report updates the pointer position.
|
|
153
|
+
this.#position = { column: event.column, row: event.row };
|
|
154
|
+
outcome.repaint ||= wasOverBottom !== target.overBottom;
|
|
155
|
+
const wasOverTailControl = tailControl !== undefined && previousPointer !== undefined
|
|
156
|
+
&& withinTailControl(tailControl, previousPointer.column, previousPointer.row);
|
|
157
|
+
outcome.repaint ||= wasOverTailControl !== target.overTailControl;
|
|
158
|
+
if (!this.#ports.viewport.selectionActive && !this.#editorSelecting) {
|
|
159
|
+
const nextHyperlink = hyperlinkKeyAt(target.frame, event.column, event.row);
|
|
160
|
+
if (this.#hoveredHyperlinkKey !== undefined && nextHyperlink !== this.#hoveredHyperlinkKey) {
|
|
161
|
+
// Platform: overwrite Windows Terminal's cached native-hover underline exactly once.
|
|
162
|
+
this.#ports.requestHyperlinkCleanup(previousPointer === undefined ? undefined : [previousPointer.row]);
|
|
163
|
+
outcome.repaint = true;
|
|
164
|
+
}
|
|
165
|
+
this.#hoveredHyperlinkKey = nextHyperlink;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
#motion(event, target, call, outcome) {
|
|
169
|
+
const viewport = this.#ports.viewport;
|
|
170
|
+
const { frame } = target;
|
|
171
|
+
const hits = frame.hits;
|
|
172
|
+
viewport.setRailHovered(target.overRail);
|
|
173
|
+
viewport.setStickyHovered(target.overSticky);
|
|
174
|
+
outcome.repaint = true;
|
|
175
|
+
const editorFrame = this.#ports.editorFrame();
|
|
176
|
+
if (call.editorActive && this.#editorSelecting && editorFrame !== undefined) {
|
|
177
|
+
this.#ports.editor.handlePointer({
|
|
178
|
+
kind: "motion",
|
|
179
|
+
button: event.button,
|
|
180
|
+
column: event.column,
|
|
181
|
+
row: event.row - editorFrame.rowStart + 1,
|
|
182
|
+
});
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
if (this.#dockSuppressed || this.#tailSuppressed)
|
|
186
|
+
return true;
|
|
187
|
+
const pendingEditorClick = this.#pendingEditorClick;
|
|
188
|
+
if (pendingEditorClick !== undefined) {
|
|
189
|
+
if (event.column === pendingEditorClick.column && event.row === pendingEditorClick.row)
|
|
190
|
+
return true;
|
|
191
|
+
this.#pendingEditorClick = undefined;
|
|
192
|
+
const activeEditorFrame = call.editorActive ? editorFrame : undefined;
|
|
193
|
+
if (activeEditorFrame !== undefined && this.#ports.editor.handlePointer({ kind: "press", button: 0, column: pendingEditorClick.column, row: pendingEditorClick.row - activeEditorFrame.rowStart + 1 })) {
|
|
194
|
+
this.#editorSelecting = true;
|
|
195
|
+
this.#ports.editor.handlePointer({ kind: "motion", button: event.button, column: event.column, row: event.row - activeEditorFrame.rowStart + 1 });
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
viewport.pressSelection(pendingEditorClick.column, pendingEditorClick.row, call.now, { continueMultiClick: false });
|
|
199
|
+
viewport.extendSelection(event.column, event.row, call.now, false);
|
|
200
|
+
this.#ports.updateSelectionAutoScroll(event.column, event.row, hits.viewportHeight, frame.rows.length);
|
|
201
|
+
outcome.activity = true;
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
if (viewport.selectionActive) {
|
|
205
|
+
viewport.extendSelection(event.column, event.row, call.now, false);
|
|
206
|
+
this.#ports.updateSelectionAutoScroll(event.column, event.row, hits.viewportHeight, frame.rows.length);
|
|
207
|
+
outcome.activity = true;
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
if (this.#dragGrabOffset !== null && hits.rail !== null) {
|
|
211
|
+
const scroll = scrollForThumbRow(hits.rail.geometry, event.row - hits.rail.rowStart - this.#dragGrabOffset);
|
|
212
|
+
viewport.scrollTo(scroll, call.now);
|
|
213
|
+
outcome.activity = true;
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
return target.overRail || target.overSticky || target.overBottom || target.overTailControl;
|
|
217
|
+
}
|
|
218
|
+
#wheel(event, frame, call, outcome) {
|
|
219
|
+
if (!call.allowWheel || event.row < 1 || event.row > frame.hits.viewportHeight)
|
|
220
|
+
return false;
|
|
221
|
+
const distance = scrollbarWheelRows(this.#ports.config().scrollbarSpeed);
|
|
222
|
+
this.#ports.viewport.scrollBy(event.kind === "wheel-up" ? -distance : distance, call.now);
|
|
223
|
+
outcome.activity = true;
|
|
224
|
+
outcome.repaint = true;
|
|
225
|
+
outcome.forceRepaint = true;
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
#press(event, target, call, outcome) {
|
|
229
|
+
const viewport = this.#ports.viewport;
|
|
230
|
+
const { frame } = target;
|
|
231
|
+
const hits = frame.hits;
|
|
232
|
+
const editorFrame = call.editorActive ? this.#ports.editorFrame() : undefined;
|
|
233
|
+
if (event.button === 2 && editorFrame !== undefined
|
|
234
|
+
&& event.row >= editorFrame.rowStart && event.row <= editorFrame.rowEnd) {
|
|
235
|
+
this.#ports.stopSelectionAutoScroll();
|
|
236
|
+
if (viewport.clearSelection())
|
|
237
|
+
outcome.repaint = true;
|
|
238
|
+
this.#ports.pasteFromPointer();
|
|
239
|
+
this.#dockSuppressed = true;
|
|
240
|
+
outcome.repaint = true;
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
if (event.button !== 0)
|
|
244
|
+
return false;
|
|
245
|
+
this.#dockSuppressed = false;
|
|
246
|
+
this.#tailSuppressed = false;
|
|
247
|
+
this.#pendingEditorClick = undefined;
|
|
248
|
+
this.#ports.stopSelectionAutoScroll();
|
|
249
|
+
if (viewport.clearSelection())
|
|
250
|
+
outcome.repaint = true;
|
|
251
|
+
if (target.overTailControl && target.tailControl !== undefined) {
|
|
252
|
+
this.#ports.clearTailControl();
|
|
253
|
+
target.tailControl.activate();
|
|
254
|
+
this.#tailSuppressed = true;
|
|
255
|
+
outcome.repaint = true;
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
if (target.overBottom) {
|
|
259
|
+
viewport.scrollToEnd(call.now);
|
|
260
|
+
this.#tailSuppressed = true;
|
|
261
|
+
outcome.activity = true;
|
|
262
|
+
outcome.repaint = true;
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
if (target.overSticky && hits.sticky !== null) {
|
|
266
|
+
viewport.scrollTo(hits.sticky.target, call.now);
|
|
267
|
+
this.#tailSuppressed = true;
|
|
268
|
+
outcome.activity = true;
|
|
269
|
+
outcome.repaint = true;
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
272
|
+
if (target.overRail && hits.rail !== null) {
|
|
273
|
+
const trackRow = event.row - hits.rail.rowStart;
|
|
274
|
+
const geometry = hits.rail.geometry;
|
|
275
|
+
if (trackRow >= geometry.thumbTop && trackRow < geometry.thumbTop + geometry.thumbHeight) {
|
|
276
|
+
this.#dragGrabOffset = trackRow - geometry.thumbTop;
|
|
277
|
+
viewport.setRailDragging(true);
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
viewport.scrollTo(scrollForTrackPage(geometry, trackRow, frame.scrollTop, hits.viewportHeight), call.now);
|
|
281
|
+
this.#tailSuppressed = true;
|
|
282
|
+
}
|
|
283
|
+
outcome.activity = true;
|
|
284
|
+
outcome.repaint = true;
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
if (event.row >= 1 && event.row <= frame.rows.length && event.column <= frame.descriptor.width) {
|
|
288
|
+
if (editorFrame !== undefined && event.row >= editorFrame.rowStart && event.row <= editorFrame.rowEnd) {
|
|
289
|
+
// Invariant: no-drag clicks remain editor-owned; first motion latches an editor drag.
|
|
290
|
+
this.#pendingEditorClick = { column: event.column, row: event.row };
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
viewport.pressSelection(event.column, event.row, call.now);
|
|
294
|
+
}
|
|
295
|
+
outcome.repaint = true;
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
this.#tailSuppressed = true;
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
#release(event, call, outcome) {
|
|
302
|
+
const viewport = this.#ports.viewport;
|
|
303
|
+
const editorFrame = this.#ports.editorFrame();
|
|
304
|
+
if (call.editorActive && this.#editorSelecting && editorFrame !== undefined) {
|
|
305
|
+
this.#ports.editor.handlePointer({
|
|
306
|
+
kind: "release",
|
|
307
|
+
button: event.button,
|
|
308
|
+
column: event.column,
|
|
309
|
+
row: event.row - editorFrame.rowStart + 1,
|
|
310
|
+
});
|
|
311
|
+
this.#editorSelecting = false;
|
|
312
|
+
outcome.forceRepaint = true;
|
|
313
|
+
outcome.repaint = true;
|
|
314
|
+
return true;
|
|
315
|
+
}
|
|
316
|
+
const pendingEditorClick = this.#pendingEditorClick;
|
|
317
|
+
if (pendingEditorClick !== undefined) {
|
|
318
|
+
this.#pendingEditorClick = undefined;
|
|
319
|
+
if (editorFrame !== undefined) {
|
|
320
|
+
const editorRow = pendingEditorClick.row - editorFrame.rowStart + 1;
|
|
321
|
+
this.#ports.editor.handlePointer({ kind: "press", button: 0, column: pendingEditorClick.column, row: editorRow });
|
|
322
|
+
this.#ports.editor.handlePointer({ kind: "release", button: 0, column: pendingEditorClick.column, row: editorRow });
|
|
323
|
+
}
|
|
324
|
+
outcome.forceRepaint = true;
|
|
325
|
+
outcome.repaint = true;
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
if (viewport.releaseSelection()) {
|
|
329
|
+
this.#ports.stopSelectionAutoScroll();
|
|
330
|
+
if (this.#ports.copyOnSelect())
|
|
331
|
+
outcome.completedCopy = viewport.captureSelectedText() ?? undefined;
|
|
332
|
+
// Platform: restore OSC 8 links only after the held-button selection paint has
|
|
333
|
+
// ended, then overwrite any terminal-cached hover cells immediately.
|
|
334
|
+
outcome.forceRepaint = true;
|
|
335
|
+
outcome.repaint = true;
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
if (this.#dragGrabOffset !== null) {
|
|
339
|
+
this.#dragGrabOffset = null;
|
|
340
|
+
viewport.setRailDragging(false);
|
|
341
|
+
outcome.repaint = true;
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
if (this.#dockSuppressed) {
|
|
345
|
+
this.#dockSuppressed = false;
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
if (this.#tailSuppressed) {
|
|
349
|
+
this.#tailSuppressed = false;
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
function hyperlinkKeyAt(frame, column, row) {
|
|
356
|
+
if (row < 1 || row > frame.rows.length || column < 1)
|
|
357
|
+
return undefined;
|
|
358
|
+
const range = readVisibleHyperlinks(frame.rows[row - 1] ?? "").ranges
|
|
359
|
+
.find(candidate => column - 1 >= candidate.from && column - 1 < candidate.to);
|
|
360
|
+
return range === undefined ? undefined : JSON.stringify([row, range]);
|
|
361
|
+
}
|