@plannotator/ui 0.28.0 → 0.29.1
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/README.md +6 -0
- package/components/AISettingsTab.tsx +5 -4
- package/components/ActionMenu.tsx +5 -1
- package/components/AgentsTab.tsx +10 -23
- package/components/AnnotationPanel.tsx +9 -5
- package/components/AnnotationToolbar.tsx +5 -13
- package/components/AnnotationToolstrip.tsx +2 -2
- package/components/ApproveDropdown.tsx +1 -1
- package/components/BlockRenderer.tsx +1 -1
- package/components/CodeFilePopout.tsx +5 -4
- package/components/CommentPopover.tsx +391 -65
- package/components/DocBadges.tsx +29 -11
- package/components/ExportModal.tsx +16 -8
- package/components/GraphvizBlock.tsx +1 -1
- package/components/InlineMarkdown.tsx +30 -13
- package/components/KeyboardShortcuts.tsx +37 -2
- package/components/Landing.tsx +7 -7
- package/components/MenuVersionSection.tsx +4 -4
- package/components/MermaidBlock.tsx +1 -1
- package/components/ModeToggle.tsx +7 -6
- package/components/OpenInAppButton.tsx +2 -5
- package/components/PinpointOverlay.tsx +9 -7
- package/components/PlanHeaderMenu.tsx +8 -8
- package/components/PopoutDialog.tsx +6 -1
- package/components/ResizeHandle.tsx +1 -0
- package/components/Settings.tsx +172 -12
- package/components/SkillReferenceMenu.tsx +260 -0
- package/components/StickyHeaderLane.tsx +7 -0
- package/components/ThemeProvider.tsx +131 -32
- package/components/ThemeTab.tsx +123 -77
- package/components/ToolbarButtons.tsx +29 -8
- package/components/Viewer.tsx +396 -130
- package/components/VimKeyHud.tsx +695 -0
- package/components/VimModeAnnouncementDialog.tsx +557 -0
- package/components/VimModeOverlay.tsx +235 -0
- package/components/VimTargetReticle.tsx +284 -0
- package/components/ai/DocumentAIChatPanel.tsx +1 -1
- package/components/blocks/CodeBlock.tsx +18 -18
- package/components/blocks/TablePopout.tsx +7 -8
- package/components/blocks/TableToolbar.tsx +7 -8
- package/components/goal-setup/GoalSetupSurface.tsx +16 -3
- package/components/html-viewer/HtmlViewer.tsx +450 -47
- package/components/html-viewer/annotationNumbering.ts +37 -0
- package/components/html-viewer/bridge-script.ts +4051 -298
- package/components/html-viewer/composerYield.ts +51 -0
- package/components/html-viewer/srcdoc.ts +18 -3
- package/components/html-viewer/useHtmlAnnotation.ts +457 -32
- package/components/icons/themeIcons.tsx +1 -1
- package/components/plan-diff/PlanCleanDiffView.tsx +9 -9
- package/components/plan-diff/PlanDiffBadge.tsx +22 -1
- package/components/settings/HooksTab.tsx +12 -8
- package/components/sidebar/FileBrowser.tsx +4 -1
- package/components/themeModes.tsx +28 -0
- package/config/configStore.ts +76 -1
- package/config/settings.ts +152 -0
- package/configure.ts +9 -0
- package/globals.d.ts +7 -1
- package/hooks/useAIChat.ts +5 -2
- package/hooks/useAIProviderActivation.ts +47 -0
- package/hooks/useAIProviderConfig.ts +5 -1
- package/hooks/useAgentSettings.ts +64 -23
- package/hooks/useAgents.ts +4 -4
- package/hooks/useAnnotationHighlighter.ts +100 -3
- package/hooks/useArchive.ts +2 -1
- package/hooks/useFenceTheme.ts +17 -0
- package/hooks/useLinkedDoc.ts +68 -1
- package/hooks/usePinpoint.ts +76 -75
- package/hooks/usePlanDiff.ts +73 -2
- package/hooks/useSkillReferenceAutocomplete.ts +239 -0
- package/hooks/useUpdateCheck.ts +1 -2
- package/hooks/useVimDocumentFocus.ts +116 -0
- package/hooks/useVimSelection.ts +1063 -0
- package/package.json +4 -4
- package/print.css +14 -13
- package/shortcuts/core.ts +38 -13
- package/shortcuts/index.ts +10 -0
- package/shortcuts/plan-review/commentPopover.shortcuts.ts +7 -0
- package/shortcuts/plan-review/vimSelection.shortcuts.ts +251 -0
- package/shortcuts/runtime.ts +111 -12
- package/styles.css +1 -1
- package/theme.css +504 -0
- package/themes/colorblind.css +89 -0
- package/themes/plannotator.css +2 -2
- package/types.ts +93 -10
- package/utils/agentSwitch.ts +33 -7
- package/utils/blockTargeting.ts +462 -178
- package/utils/clipboard.ts +110 -0
- package/utils/codeBlockMark.ts +50 -0
- package/utils/codeHighlight.ts +293 -0
- package/utils/codexModels.ts +79 -0
- package/utils/domSelection.ts +84 -0
- package/utils/htmlChrome.ts +73 -0
- package/utils/inputMethod.ts +79 -6
- package/utils/parser.ts +517 -21
- package/utils/preferenceTtl.ts +15 -0
- package/utils/sharing.ts +0 -1
- package/utils/skillCatalog.ts +269 -0
- package/utils/skillReferences.ts +475 -0
- package/utils/syntaxTheme.ts +83 -0
- package/utils/themeRegistry.ts +154 -0
- package/utils/vimHud.ts +263 -0
- package/utils/vimModeAnnouncement.ts +23 -0
- package/utils/vimNavigation.ts +417 -0
- package/utils/vimReticle.ts +88 -0
- package/utils/vimScroll.ts +162 -0
package/types.ts
CHANGED
|
@@ -25,6 +25,38 @@ export interface ImageAttachment {
|
|
|
25
25
|
name: string;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/** DOM-relative text position used to restore a document annotation selection. */
|
|
29
|
+
export interface AnnotationTextMeta {
|
|
30
|
+
parentTagName: string;
|
|
31
|
+
parentIndex: number;
|
|
32
|
+
textOffset: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Durable, media-specific location for a note created in the PR artifact viewer. */
|
|
36
|
+
export type ArtifactAnnotationAnchor =
|
|
37
|
+
| {
|
|
38
|
+
kind: 'document';
|
|
39
|
+
originalText: string;
|
|
40
|
+
blockId: string;
|
|
41
|
+
startOffset: number;
|
|
42
|
+
endOffset: number;
|
|
43
|
+
startMeta?: AnnotationTextMeta;
|
|
44
|
+
endMeta?: AnnotationTextMeta;
|
|
45
|
+
}
|
|
46
|
+
| { kind: 'image'; x: number; y: number }
|
|
47
|
+
| { kind: 'video'; timestamp: number }
|
|
48
|
+
| { kind: 'page' };
|
|
49
|
+
|
|
50
|
+
/** Context shared by description and comment annotations created on a PR artifact. */
|
|
51
|
+
export interface ArtifactAnnotationMeta {
|
|
52
|
+
artifactId: string;
|
|
53
|
+
artifactName: string;
|
|
54
|
+
artifactUrl: string;
|
|
55
|
+
artifactKind: 'image' | 'gif' | 'video' | 'html' | 'markdown';
|
|
56
|
+
sourceUrl: string;
|
|
57
|
+
anchor: ArtifactAnnotationAnchor;
|
|
58
|
+
}
|
|
59
|
+
|
|
28
60
|
export interface Annotation {
|
|
29
61
|
id: string;
|
|
30
62
|
blockId: string; // Legacy - not used with web-highlighter
|
|
@@ -40,23 +72,56 @@ export interface Annotation {
|
|
|
40
72
|
isQuickLabel?: boolean; // true if created via quick label chip
|
|
41
73
|
quickLabelTip?: string; // optional instruction tip from the label definition
|
|
42
74
|
diffContext?: 'added' | 'removed' | 'modified'; // set when annotation created in plan diff view
|
|
75
|
+
artifact?: ArtifactAnnotationMeta; // code-review artifact viewer anchor + source context
|
|
43
76
|
mathTargets?: Array<{
|
|
44
77
|
blockId: string;
|
|
45
78
|
tex: string;
|
|
46
79
|
displayMode: boolean;
|
|
47
80
|
}>; // math elements covered by a mixed text+formula selection
|
|
48
81
|
prUrl?: string; // code-review PR mode: the PR this note belongs to, so it isn't shown/exported against another PR after an in-place switch
|
|
82
|
+
htmlAnchor?: HtmlElementAnchor; // raw-HTML pinpoint: serialized element anchor for reliable restoration
|
|
83
|
+
htmlAdditionalTargets?: HtmlAnnotationTarget[]; // raw-HTML shift-click multi-select: extra elements this one comment covers (primary stays htmlAnchor/originalText)
|
|
49
84
|
// web-highlighter metadata for cross-element selections
|
|
50
|
-
startMeta?:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
85
|
+
startMeta?: AnnotationTextMeta;
|
|
86
|
+
endMeta?: AnnotationTextMeta;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Serialized element anchor for annotations created on the raw-HTML surface
|
|
91
|
+
* (pinpoint mode). Built inside the sandboxed viewer bridge: a verified-unique
|
|
92
|
+
* CSS selector plus a fingerprint (tag + normalized text snapshot) used to
|
|
93
|
+
* fail closed when a weak selector no longer matches the same content.
|
|
94
|
+
* Additive — annotations without one restore via document-wide text search.
|
|
95
|
+
*/
|
|
96
|
+
export interface HtmlElementAnchor {
|
|
97
|
+
selector: string;
|
|
98
|
+
tagName: string;
|
|
99
|
+
text?: string;
|
|
100
|
+
/**
|
|
101
|
+
* The user's selected point inside the target element's rect, normalized to
|
|
102
|
+
* 0..1 on each axis. Placed comment markers reproject it against the
|
|
103
|
+
* element's CURRENT rect, so the marker follows the element through
|
|
104
|
+
* responsive movement instead of pinning stale pixels. Additive — anchors
|
|
105
|
+
* without one (older records, keyboard-driven selections) fall back to the
|
|
106
|
+
* target rect center.
|
|
107
|
+
*/
|
|
108
|
+
point?: { x: number; y: number };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* One additional element covered by a multi-target raw-HTML pinpoint comment
|
|
113
|
+
* (shift-click multi-select). Carries what the export and composer chips need
|
|
114
|
+
* even when anchoring failed closed: the semantic label from the pinpoint
|
|
115
|
+
* hover cascade and the element's text (or `[element: …]` description).
|
|
116
|
+
* Additive — annotations without the array behave exactly as before.
|
|
117
|
+
*/
|
|
118
|
+
export interface HtmlAnnotationTarget {
|
|
119
|
+
/** Semantic label from the hover-label cascade (e.g. "Button", "rowchip"). */
|
|
120
|
+
label?: string;
|
|
121
|
+
/** The target element's capped text, or an element description when text-less. */
|
|
122
|
+
text: string;
|
|
123
|
+
/** Element anchor for restoration; absent when the bridge failed closed. */
|
|
124
|
+
anchor?: HtmlElementAnchor;
|
|
60
125
|
}
|
|
61
126
|
|
|
62
127
|
export type AlertKind = 'note' | 'tip' | 'warning' | 'caution' | 'important';
|
|
@@ -122,6 +187,7 @@ export interface CommentAnnotation {
|
|
|
122
187
|
text: string; // the reviewer's note
|
|
123
188
|
createdAt: number;
|
|
124
189
|
prUrl?: string; // the PR this note belongs to (see Annotation.prUrl)
|
|
190
|
+
artifact?: ArtifactAnnotationMeta; // optional artifact anchor within this source comment
|
|
125
191
|
}
|
|
126
192
|
|
|
127
193
|
export interface CodeAnnotation {
|
|
@@ -139,6 +205,15 @@ export interface CodeAnnotation {
|
|
|
139
205
|
charStart?: number; // Character offset within lineStart (token-level selection)
|
|
140
206
|
charEnd?: number; // Character offset within lineEnd (token-level selection)
|
|
141
207
|
tokenText?: string; // Selected token/span text (token-level selection)
|
|
208
|
+
/** Exact text highlighted when the comment was created inside an edit
|
|
209
|
+
* session (captured from the editor selection). Exported alongside the
|
|
210
|
+
* comment so the agent sees what was highlighted even when it differs
|
|
211
|
+
* from the anchored diff lines. */
|
|
212
|
+
selectedText?: string;
|
|
213
|
+
/** True when the edit-session selection overlapped in-session edits: the
|
|
214
|
+
* line anchor maps to the pristine lines those edits replace, so it is
|
|
215
|
+
* approximate and the export labels it as such. */
|
|
216
|
+
selectedTextFromEdits?: boolean;
|
|
142
217
|
createdAt: number;
|
|
143
218
|
author?: string;
|
|
144
219
|
source?: string; // External tool identifier (e.g., "eslint") — set when annotation comes from external API
|
|
@@ -159,6 +234,14 @@ export interface CodeAnnotation {
|
|
|
159
234
|
commitSha?: string;
|
|
160
235
|
/** The commit's one-line subject, captured for readable export labels. */
|
|
161
236
|
commitSubject?: string;
|
|
237
|
+
/** GitButler target that supplied this annotation's line coordinates. */
|
|
238
|
+
gitButlerDiffType?: string;
|
|
239
|
+
/** Human-readable GitButler target label captured with the annotation. */
|
|
240
|
+
gitButlerDiffLabel?: string;
|
|
241
|
+
/** GitButler merge base active when the annotation was created. */
|
|
242
|
+
gitButlerBase?: string;
|
|
243
|
+
/** Exact server snapshot that supplied the GitButler line coordinates. */
|
|
244
|
+
gitButlerSnapshotId?: string;
|
|
162
245
|
}
|
|
163
246
|
|
|
164
247
|
/** Token-level metadata passed from selection to annotation creation. */
|
package/utils/agentSwitch.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Agent Switch Settings Utility
|
|
3
3
|
*
|
|
4
|
-
* Manages settings for automatic agent switching after plan approval
|
|
5
|
-
* Supports
|
|
4
|
+
* Manages settings for automatic agent switching after plan approval and after
|
|
5
|
+
* sending code review feedback. Supports discovered agents, disabled, or custom
|
|
6
|
+
* agent names.
|
|
7
|
+
*
|
|
8
|
+
* The stored value is shared across surfaces, but the default when nothing is
|
|
9
|
+
* stored is surface-specific: plan approval keeps its historical hand-off to the
|
|
10
|
+
* build agent, while review feedback stays on the current agent.
|
|
6
11
|
*
|
|
7
12
|
* Uses cookies (not localStorage) because each hook invocation runs on a
|
|
8
13
|
* random port, and localStorage is scoped by origin including port.
|
|
@@ -28,14 +33,32 @@ export const AGENT_OPTIONS: { value: string; label: string; description: string
|
|
|
28
33
|
{ value: 'disabled', label: 'Disabled', description: 'Stay on current agent after approval' },
|
|
29
34
|
];
|
|
30
35
|
|
|
31
|
-
|
|
36
|
+
/** UI surface asking for the setting — only affects the unset default. */
|
|
37
|
+
export type AgentSwitchSurface = 'plan' | 'review';
|
|
38
|
+
|
|
39
|
+
const PLAN_DEFAULT_SETTINGS: AgentSwitchSettings = {
|
|
32
40
|
switchTo: 'build',
|
|
33
41
|
};
|
|
34
42
|
|
|
43
|
+
const REVIEW_DEFAULT_SETTINGS: AgentSwitchSettings = {
|
|
44
|
+
switchTo: 'disabled',
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Default used when the user has never picked an agent switch setting.
|
|
49
|
+
* Plan approval hands off to the build agent (historical behavior); review
|
|
50
|
+
* feedback stays on the current agent.
|
|
51
|
+
*/
|
|
52
|
+
export function getAgentSwitchDefaults(surface: AgentSwitchSurface = 'plan'): AgentSwitchSettings {
|
|
53
|
+
return surface === 'review' ? REVIEW_DEFAULT_SETTINGS : PLAN_DEFAULT_SETTINGS;
|
|
54
|
+
}
|
|
55
|
+
|
|
35
56
|
/**
|
|
36
|
-
* Get current agent switch settings from storage
|
|
57
|
+
* Get current agent switch settings from storage.
|
|
58
|
+
* An explicit user choice applies to every surface; only the unset default
|
|
59
|
+
* varies by surface.
|
|
37
60
|
*/
|
|
38
|
-
export function getAgentSwitchSettings(): AgentSwitchSettings {
|
|
61
|
+
export function getAgentSwitchSettings(surface: AgentSwitchSurface = 'plan'): AgentSwitchSettings {
|
|
39
62
|
const stored = storage.getItem(STORAGE_KEY);
|
|
40
63
|
const customName = storage.getItem(CUSTOM_NAME_KEY) || undefined;
|
|
41
64
|
|
|
@@ -43,7 +66,7 @@ export function getAgentSwitchSettings(): AgentSwitchSettings {
|
|
|
43
66
|
if (stored) {
|
|
44
67
|
return { switchTo: stored, customName };
|
|
45
68
|
}
|
|
46
|
-
return
|
|
69
|
+
return getAgentSwitchDefaults(surface);
|
|
47
70
|
}
|
|
48
71
|
|
|
49
72
|
/**
|
|
@@ -67,5 +90,8 @@ export function getEffectiveAgentName(settings: AgentSwitchSettings): string | u
|
|
|
67
90
|
if (settings.switchTo === 'custom' && settings.customName) {
|
|
68
91
|
return settings.customName;
|
|
69
92
|
}
|
|
70
|
-
|
|
93
|
+
if (settings.switchTo === 'custom') {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
return settings.switchTo;
|
|
71
97
|
}
|