@plannotator/ui 0.22.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/README.md +60 -0
- package/assets/diff-options.png +0 -0
- package/assets/icon-codex.png +0 -0
- package/assets/look-flat.png +0 -0
- package/assets/look-grid.png +0 -0
- package/assets/review-sections.png +0 -0
- package/assets/review-tree.png +0 -0
- package/assets/workspaces.webp +0 -0
- package/components/AISettingsTab.tsx +145 -0
- package/components/ActionMenu.tsx +101 -0
- package/components/AgentControls.tsx +216 -0
- package/components/AgentsTab.tsx +1294 -0
- package/components/AnnotationPanel.tsx +731 -0
- package/components/AnnotationSidebar.tsx +86 -0
- package/components/AnnotationToolbar.tsx +323 -0
- package/components/AnnotationToolstrip.tsx +355 -0
- package/components/ApproveDropdown.tsx +170 -0
- package/components/AttachmentsButton.tsx +410 -0
- package/components/BlockRenderer.tsx +163 -0
- package/components/BorderTrail.tsx +38 -0
- package/components/CodeFilePicker.tsx +64 -0
- package/components/CodeFilePopout.tsx +602 -0
- package/components/CodePathValidationContext.tsx +14 -0
- package/components/CommentPopover.tsx +512 -0
- package/components/CompletionOverlay.tsx +99 -0
- package/components/ConfirmDialog.tsx +128 -0
- package/components/DocBadges.tsx +231 -0
- package/components/EditorAnnotationCard.tsx +65 -0
- package/components/ExportModal.tsx +565 -0
- package/components/FloatingQuickLabelPicker.tsx +144 -0
- package/components/GitHubIcon.tsx +16 -0
- package/components/GitLabIcon.tsx +30 -0
- package/components/GraphvizBlock.tsx +511 -0
- package/components/ImageAnnotator/Canvas.tsx +118 -0
- package/components/ImageAnnotator/Toolbar.tsx +218 -0
- package/components/ImageAnnotator/index.tsx +272 -0
- package/components/ImageAnnotator/types.ts +39 -0
- package/components/ImageAnnotator/utils.ts +147 -0
- package/components/ImageThumbnail.tsx +126 -0
- package/components/ImportModal.tsx +146 -0
- package/components/InlineMarkdown.tsx +1094 -0
- package/components/KeyboardShortcuts.tsx +208 -0
- package/components/Landing.tsx +496 -0
- package/components/ListItemBody.tsx +62 -0
- package/components/ListMarker.tsx +73 -0
- package/components/LookAndFeelAnnouncementDialog.tsx +230 -0
- package/components/MarkdownEditor.tsx +44 -0
- package/components/MenuVersionSection.tsx +91 -0
- package/components/MermaidBlock.tsx +579 -0
- package/components/ModeToggle.tsx +68 -0
- package/components/OpenInAppButton.tsx +299 -0
- package/components/OverlayScrollArea.tsx +82 -0
- package/components/PermissionModeSetup.tsx +92 -0
- package/components/PinpointOverlay.tsx +99 -0
- package/components/PlanAIAnnouncementDialog.tsx +187 -0
- package/components/PlanHeaderMenu.tsx +299 -0
- package/components/PopoutDialog.tsx +91 -0
- package/components/Popover.tsx +27 -0
- package/components/ProviderIcons.tsx +51 -0
- package/components/PullRequestIcon.tsx +12 -0
- package/components/QuickLabelDropdown.tsx +63 -0
- package/components/RenderedMarkdown.tsx +54 -0
- package/components/RepoIcon.tsx +12 -0
- package/components/ResizeHandle.tsx +86 -0
- package/components/ReviewAgentsIcon.tsx +18 -0
- package/components/SearchableSelect.tsx +157 -0
- package/components/Settings.tsx +2220 -0
- package/components/SparklesIcon.tsx +45 -0
- package/components/StickyHeaderLane.tsx +260 -0
- package/components/TableOfContents.tsx +157 -0
- package/components/TaterSpritePullup.tsx +34 -0
- package/components/TaterSpriteRunning.tsx +54 -0
- package/components/TaterSpriteSitting.tsx +37 -0
- package/components/TextShimmer.tsx +57 -0
- package/components/ThemeProvider.tsx +162 -0
- package/components/ThemeTab.tsx +139 -0
- package/components/ToolbarButtons.tsx +116 -0
- package/components/Tooltip.tsx +45 -0
- package/components/Viewer.tsx +977 -0
- package/components/ai/AIProviderBar.tsx +95 -0
- package/components/ai/DocumentAIChatPanel.tsx +313 -0
- package/components/blocks/AlertBlock.tsx +58 -0
- package/components/blocks/Callout.tsx +60 -0
- package/components/blocks/CodeBlock.tsx +75 -0
- package/components/blocks/HtmlBlock.tsx +122 -0
- package/components/blocks/MathBlock.tsx +36 -0
- package/components/blocks/TableBlock.tsx +146 -0
- package/components/blocks/TablePopout.tsx +279 -0
- package/components/blocks/TableToolbar.tsx +153 -0
- package/components/blocks/proseBody.tsx +102 -0
- package/components/core/button.tsx +44 -0
- package/components/core/textarea.tsx +26 -0
- package/components/diagramLanguages.ts +14 -0
- package/components/goal-setup/GoalSetupSurface.tsx +1354 -0
- package/components/html-viewer/HtmlViewer.tsx +386 -0
- package/components/html-viewer/bridge-script.ts +505 -0
- package/components/html-viewer/index.ts +1 -0
- package/components/html-viewer/useHtmlAnnotation.ts +400 -0
- package/components/icons/AgentIcons.tsx +66 -0
- package/components/icons/AppIcon.tsx +56 -0
- package/components/icons/MessagesIcon.tsx +11 -0
- package/components/icons/ObsidianIcons.tsx +208 -0
- package/components/icons/app/android-studio.svg +369 -0
- package/components/icons/app/antigravity.svg +97 -0
- package/components/icons/app/cursor.svg +16 -0
- package/components/icons/app/file-explorer.svg +20 -0
- package/components/icons/app/finder.png +0 -0
- package/components/icons/app/ghostty.svg +13 -0
- package/components/icons/app/iterm2.svg +13 -0
- package/components/icons/app/powershell.svg +14 -0
- package/components/icons/app/sublime-text.svg +17 -0
- package/components/icons/app/terminal.png +0 -0
- package/components/icons/app/textmate.png +0 -0
- package/components/icons/app/vscode.svg +39 -0
- package/components/icons/app/warp.png +0 -0
- package/components/icons/app/xcode.png +0 -0
- package/components/icons/app/zed-dark.svg +15 -0
- package/components/icons/app/zed.svg +15 -0
- package/components/icons/themeIcons.tsx +47 -0
- package/components/mermaidSvg.ts +33 -0
- package/components/plan-diff/PlanCleanDiffView.tsx +884 -0
- package/components/plan-diff/PlanDiffBadge.tsx +48 -0
- package/components/plan-diff/PlanDiffModeSwitcher.tsx +103 -0
- package/components/plan-diff/PlanDiffViewer.tsx +214 -0
- package/components/plan-diff/PlanRawDiffView.tsx +102 -0
- package/components/plan-diff/VSCodeIcon.tsx +132 -0
- package/components/settings/HooksTab.tsx +208 -0
- package/components/sidebar/ArchiveBrowser.tsx +98 -0
- package/components/sidebar/CountBadge.tsx +12 -0
- package/components/sidebar/FileBrowser.tsx +498 -0
- package/components/sidebar/MessagesBrowser.tsx +109 -0
- package/components/sidebar/SidebarContainer.tsx +353 -0
- package/components/sidebar/SidebarTabs.tsx +155 -0
- package/components/sidebar/VersionBrowser.tsx +141 -0
- package/components/types.d.ts +7 -0
- package/components/ui/badge.tsx +44 -0
- package/components/ui/button.tsx +83 -0
- package/components/ui/card.tsx +58 -0
- package/components/ui/dialog.tsx +106 -0
- package/components/ui/dropdown-menu.tsx +240 -0
- package/components/ui/state-pill.tsx +45 -0
- package/components/ui/tabs.tsx +46 -0
- package/components/ui/textarea.tsx +25 -0
- package/config/configStore.ts +214 -0
- package/config/index.ts +4 -0
- package/config/reviewView.ts +42 -0
- package/config/settings.ts +310 -0
- package/config/useConfig.ts +20 -0
- package/configure.ts +69 -0
- package/globals.d.ts +14 -0
- package/hooks/pfm/useCodeFilePopout.ts +111 -0
- package/hooks/useAIChat.ts +532 -0
- package/hooks/useAIProviderConfig.ts +115 -0
- package/hooks/useActiveSection.ts +78 -0
- package/hooks/useAgentJobs.ts +306 -0
- package/hooks/useAgentSettings.ts +579 -0
- package/hooks/useAgents.ts +90 -0
- package/hooks/useAnnotationDraft.ts +523 -0
- package/hooks/useAnnotationHighlighter.ts +1170 -0
- package/hooks/useArchive.ts +171 -0
- package/hooks/useAutoClose.ts +104 -0
- package/hooks/useCodeAnnotationDraft.ts +194 -0
- package/hooks/useCodeFilePopout.ts +1 -0
- package/hooks/useDismissOnOutsideAndEscape.ts +50 -0
- package/hooks/useDraggable.ts +108 -0
- package/hooks/useEditorAnnotations.ts +64 -0
- package/hooks/useExternalAnnotationHighlights.ts +105 -0
- package/hooks/useExternalAnnotations.ts +268 -0
- package/hooks/useFileBrowser.ts +402 -0
- package/hooks/useInputMethodSwitch.ts +89 -0
- package/hooks/useIsMobile.ts +17 -0
- package/hooks/useLinkedDoc.ts +494 -0
- package/hooks/useOverlayViewport.ts +36 -0
- package/hooks/usePinpoint.ts +182 -0
- package/hooks/usePlanDiff.ts +176 -0
- package/hooks/usePrintMode.ts +27 -0
- package/hooks/useResizablePanel.ts +173 -0
- package/hooks/useScrollViewport.ts +38 -0
- package/hooks/useSharing.ts +441 -0
- package/hooks/useSidebar.ts +55 -0
- package/hooks/useUpdateCheck.ts +132 -0
- package/hooks/useValidatedCodePaths.ts +94 -0
- package/icons/GitUser.tsx +17 -0
- package/lib/utils.ts +11 -0
- package/package.json +117 -0
- package/plannotator.webp +0 -0
- package/print.css +427 -0
- package/shortcuts/code-review/ai.shortcuts.ts +25 -0
- package/shortcuts/code-review/allFilesDiff.shortcuts.ts +46 -0
- package/shortcuts/code-review/annotationToolbar.shortcuts.ts +30 -0
- package/shortcuts/code-review/fileTree.shortcuts.ts +35 -0
- package/shortcuts/code-review/prComments.shortcuts.ts +18 -0
- package/shortcuts/code-review/suggestionModal.shortcuts.ts +25 -0
- package/shortcuts/code-review/tourDialog.shortcuts.ts +18 -0
- package/shortcuts/core.ts +399 -0
- package/shortcuts/index.ts +21 -0
- package/shortcuts/plan-review/annotationPanel.shortcuts.ts +25 -0
- package/shortcuts/plan-review/annotationToolbar.shortcuts.ts +39 -0
- package/shortcuts/plan-review/commentPopover.shortcuts.ts +21 -0
- package/shortcuts/plan-review/goalSetup.shortcuts.ts +10 -0
- package/shortcuts/plan-review/imageAnnotator.shortcuts.ts +42 -0
- package/shortcuts/plan-review/inputMethod.shortcuts.ts +30 -0
- package/shortcuts/plan-review/sidebar.shortcuts.ts +34 -0
- package/shortcuts/plan-review/viewer.shortcuts.ts +24 -0
- package/shortcuts/runtime.ts +259 -0
- package/sprite_package_additional/index.html +34 -0
- package/sprite_package_additional/sprite.png +0 -0
- package/sprite_package_new/index.html +34 -0
- package/sprite_package_new/sprite.png +0 -0
- package/sprite_package_pulluphang/index.html +34 -0
- package/sprite_package_pulluphang/sprite.png +0 -0
- package/styles.css +1 -0
- package/theme.css +893 -0
- package/themes/adwaita.css +62 -0
- package/themes/andromeeda.css +66 -0
- package/themes/aurora-x.css +66 -0
- package/themes/ayu-dark.css +66 -0
- package/themes/caffeine.css +113 -0
- package/themes/catppuccin.css +62 -0
- package/themes/claude-plus.css +60 -0
- package/themes/cursor-hc.css +34 -0
- package/themes/cursor-midnight.css +34 -0
- package/themes/cursor.css +62 -0
- package/themes/dark-plus.css +66 -0
- package/themes/doom-64.css +109 -0
- package/themes/dracula.css +33 -0
- package/themes/everforest-hard.css +62 -0
- package/themes/everforest-soft.css +62 -0
- package/themes/everforest.css +62 -0
- package/themes/github.css +66 -0
- package/themes/gruvbox.css +62 -0
- package/themes/houston.css +66 -0
- package/themes/kanagawa-dragon.css +34 -0
- package/themes/kanagawa-lotus.css +34 -0
- package/themes/kanagawa-wave.css +34 -0
- package/themes/laserwave.css +66 -0
- package/themes/material.css +62 -0
- package/themes/min.css +66 -0
- package/themes/monokai-pro.css +34 -0
- package/themes/neutral.css +59 -0
- package/themes/night-owl.css +66 -0
- package/themes/nord.css +66 -0
- package/themes/one-dark-pro.css +66 -0
- package/themes/one-light.css +66 -0
- package/themes/paulmillr.css +34 -0
- package/themes/plannotator.css +60 -0
- package/themes/plastic.css +66 -0
- package/themes/poimandres.css +66 -0
- package/themes/quantum-rose.css +109 -0
- package/themes/red.css +66 -0
- package/themes/rose-pine.css +62 -0
- package/themes/simple.css +124 -0
- package/themes/slack.css +66 -0
- package/themes/snazzy-light.css +66 -0
- package/themes/soft-pop.css +60 -0
- package/themes/solar-dusk.css +109 -0
- package/themes/solarized.css +66 -0
- package/themes/synthwave-84.css +34 -0
- package/themes/terminal.css +62 -0
- package/themes/tinacious.css +57 -0
- package/themes/tokyo-night.css +62 -0
- package/themes/vesper.css +62 -0
- package/themes/vitesse-black.css +66 -0
- package/themes/vitesse.css +62 -0
- package/types.ts +264 -0
- package/utils/agentSwitch.ts +71 -0
- package/utils/aiChatFormat.ts +33 -0
- package/utils/aiPrompt.ts +29 -0
- package/utils/aiProvider.ts +217 -0
- package/utils/anchors.ts +11 -0
- package/utils/annotateAgentTerminal.ts +29 -0
- package/utils/annotationHelpers.ts +101 -0
- package/utils/bear.ts +59 -0
- package/utils/blockTargeting.ts +240 -0
- package/utils/callback.ts +99 -0
- package/utils/commentContent.ts +8 -0
- package/utils/defaultNotesApp.ts +20 -0
- package/utils/diffFonts.ts +33 -0
- package/utils/editorMode.ts +31 -0
- package/utils/fileBrowser.ts +40 -0
- package/utils/generateId.ts +7 -0
- package/utils/generateIdentity.ts +29 -0
- package/utils/identity.ts +112 -0
- package/utils/inlineTransforms.ts +41 -0
- package/utils/inputMethod.ts +17 -0
- package/utils/lookAndFeelAnnouncement.ts +18 -0
- package/utils/obsidian.ts +201 -0
- package/utils/octarine.ts +53 -0
- package/utils/parser.ts +991 -0
- package/utils/permissionMode.ts +77 -0
- package/utils/planAIAnnouncement.ts +17 -0
- package/utils/planAgentInstructions.ts +137 -0
- package/utils/planDiffEngine.ts +590 -0
- package/utils/planSave.ts +49 -0
- package/utils/platform.ts +11 -0
- package/utils/quickLabels.ts +77 -0
- package/utils/reviewAgentInstructions.ts +182 -0
- package/utils/sanitizeHtml.ts +45 -0
- package/utils/sharing.ts +350 -0
- package/utils/slugify.ts +37 -0
- package/utils/storage.ts +141 -0
- package/utils/themeRegistry.ts +567 -0
- package/utils/uiPreferences.ts +34 -0
- package/utils/upload.ts +56 -0
- package/utils/wideMode.ts +48 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { FAVICON_SVG } from '@plannotator/core/favicon';
|
|
3
|
+
|
|
4
|
+
interface HooksStatus {
|
|
5
|
+
pfmReminder: { enabled: boolean };
|
|
6
|
+
improvementHook: {
|
|
7
|
+
present: boolean;
|
|
8
|
+
filePath: string | null;
|
|
9
|
+
fileSize: number | null;
|
|
10
|
+
content: string | null;
|
|
11
|
+
};
|
|
12
|
+
composedLength: number | null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function displayPath(filePath: string): string {
|
|
16
|
+
const idx = filePath.indexOf('/.plannotator/');
|
|
17
|
+
if (idx >= 0) return '~' + filePath.slice(idx);
|
|
18
|
+
return filePath;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const CopyPathButton: React.FC<{ filePath: string }> = ({ filePath }) => {
|
|
22
|
+
const [copied, setCopied] = useState(false);
|
|
23
|
+
|
|
24
|
+
const copy = () => {
|
|
25
|
+
navigator.clipboard.writeText(filePath).then(() => {
|
|
26
|
+
setCopied(true);
|
|
27
|
+
setTimeout(() => setCopied(false), 1500);
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<button
|
|
33
|
+
onClick={copy}
|
|
34
|
+
title="Copy path"
|
|
35
|
+
className="inline-flex items-center gap-1.5 mt-1.5 px-2 py-1 rounded bg-muted/60 hover:bg-muted border border-border/50 transition-colors group max-w-full"
|
|
36
|
+
>
|
|
37
|
+
<code className="text-[10px] text-muted-foreground font-mono truncate">
|
|
38
|
+
{displayPath(filePath)}
|
|
39
|
+
</code>
|
|
40
|
+
<span className="flex-shrink-0 text-muted-foreground/60 group-hover:text-muted-foreground transition-colors">
|
|
41
|
+
{copied ? (
|
|
42
|
+
<svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M13.25 4.75 6 12 2.75 8.75" /></svg>
|
|
43
|
+
) : (
|
|
44
|
+
<svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><rect x="5.5" y="5.5" width="8" height="8" rx="1.5" /><path d="M10.5 5.5V3a1.5 1.5 0 0 0-1.5-1.5H3A1.5 1.5 0 0 0 1.5 3v6A1.5 1.5 0 0 0 3 10.5h2.5" /></svg>
|
|
45
|
+
)}
|
|
46
|
+
</span>
|
|
47
|
+
</button>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const HooksTab: React.FC = () => {
|
|
52
|
+
const [status, setStatus] = useState<HooksStatus | null>(null);
|
|
53
|
+
const [pfmEnabled, setPfmEnabled] = useState(false);
|
|
54
|
+
const [hookExpanded, setHookExpanded] = useState(false);
|
|
55
|
+
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
fetch('/api/hooks/status')
|
|
58
|
+
.then(r => r.json())
|
|
59
|
+
.then((data: HooksStatus) => {
|
|
60
|
+
setStatus(data);
|
|
61
|
+
setPfmEnabled(data.pfmReminder.enabled);
|
|
62
|
+
})
|
|
63
|
+
.catch(() => {});
|
|
64
|
+
}, []);
|
|
65
|
+
|
|
66
|
+
const togglePfm = async () => {
|
|
67
|
+
const next = !pfmEnabled;
|
|
68
|
+
setPfmEnabled(next);
|
|
69
|
+
await fetch('/api/config', {
|
|
70
|
+
method: 'POST',
|
|
71
|
+
headers: { 'Content-Type': 'application/json' },
|
|
72
|
+
body: JSON.stringify({ pfmReminder: next }),
|
|
73
|
+
}).catch(() => setPfmEnabled(!next));
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
if (!status) {
|
|
77
|
+
return <div className="text-sm text-muted-foreground py-4">Loading hook status…</div>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<div className="space-y-4">
|
|
82
|
+
<p className="text-xs text-muted-foreground">
|
|
83
|
+
These hooks inject context into your planning agent before it writes a plan.
|
|
84
|
+
</p>
|
|
85
|
+
|
|
86
|
+
{/* PFM Reminder Card */}
|
|
87
|
+
<div className="rounded-lg border border-border bg-card p-4 space-y-3">
|
|
88
|
+
<div className="flex items-start gap-3">
|
|
89
|
+
<div
|
|
90
|
+
className="w-8 h-8 flex-shrink-0 rounded-md overflow-hidden"
|
|
91
|
+
dangerouslySetInnerHTML={{ __html: FAVICON_SVG }}
|
|
92
|
+
/>
|
|
93
|
+
<div className="flex-1 min-w-0">
|
|
94
|
+
<div className="flex items-center justify-between gap-2">
|
|
95
|
+
<h3 className="text-sm font-semibold text-foreground">Plannotator Flavored Markdown</h3>
|
|
96
|
+
<button
|
|
97
|
+
onClick={togglePfm}
|
|
98
|
+
className={`relative inline-flex h-5 w-9 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors ${
|
|
99
|
+
pfmEnabled ? 'bg-primary' : 'bg-muted'
|
|
100
|
+
}`}
|
|
101
|
+
>
|
|
102
|
+
<span
|
|
103
|
+
className={`pointer-events-none inline-block h-4 w-4 transform rounded-full bg-white shadow ring-0 transition-transform ${
|
|
104
|
+
pfmEnabled ? 'translate-x-4' : 'translate-x-0'
|
|
105
|
+
}`}
|
|
106
|
+
/>
|
|
107
|
+
</button>
|
|
108
|
+
</div>
|
|
109
|
+
<p className="text-xs text-muted-foreground mt-1 leading-relaxed">
|
|
110
|
+
Inspired by GitHub Flavored Markdown, PFM extends it with interactive tables, SVG diagrams
|
|
111
|
+
(custom, Mermaid & Graphviz), code-file links that open in your editor, callouts, task lists, and more.
|
|
112
|
+
This reminder tells the planning agent what the renderer supports so it can use these features
|
|
113
|
+
naturally. <strong>No extra tokens</strong> — the agent still writes markdown as it normally would,
|
|
114
|
+
just with enhanced syntax that Plannotator renders richer.
|
|
115
|
+
</p>
|
|
116
|
+
<div className="mt-2">
|
|
117
|
+
<span className={`inline-flex items-center gap-1 text-[10px] font-medium px-1.5 py-0.5 rounded-full ${
|
|
118
|
+
pfmEnabled
|
|
119
|
+
? 'bg-primary/15 text-primary'
|
|
120
|
+
: 'bg-muted text-muted-foreground'
|
|
121
|
+
}`}>
|
|
122
|
+
<span className={`w-1.5 h-1.5 rounded-full ${pfmEnabled ? 'bg-primary' : 'bg-muted-foreground/50'}`} />
|
|
123
|
+
{pfmEnabled ? 'Enabled' : 'Disabled'}
|
|
124
|
+
</span>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
{/* Compound Improvement Hook Card */}
|
|
131
|
+
<div className="rounded-lg border border-border bg-card p-4 space-y-3">
|
|
132
|
+
<div className="flex items-start gap-3">
|
|
133
|
+
<div
|
|
134
|
+
className="w-8 h-8 flex-shrink-0 rounded-md overflow-hidden"
|
|
135
|
+
dangerouslySetInnerHTML={{ __html: FAVICON_SVG }}
|
|
136
|
+
/>
|
|
137
|
+
<div className="flex-1 min-w-0">
|
|
138
|
+
<div className="flex items-center justify-between gap-2">
|
|
139
|
+
<h3 className="text-sm font-semibold text-foreground">Improvement Hook</h3>
|
|
140
|
+
<span className={`inline-flex items-center gap-1 text-[10px] font-medium px-1.5 py-0.5 rounded-full ${
|
|
141
|
+
status.improvementHook.present
|
|
142
|
+
? 'bg-primary/15 text-primary'
|
|
143
|
+
: 'bg-muted text-muted-foreground'
|
|
144
|
+
}`}>
|
|
145
|
+
<span className={`w-1.5 h-1.5 rounded-full ${status.improvementHook.present ? 'bg-primary' : 'bg-muted-foreground/50'}`} />
|
|
146
|
+
{status.improvementHook.present ? 'Active' : 'Not found'}
|
|
147
|
+
</span>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
{status.improvementHook.present ? (
|
|
151
|
+
<>
|
|
152
|
+
<p className="text-xs text-muted-foreground mt-1 leading-relaxed">
|
|
153
|
+
Corrective planning instructions generated from your plan denial history.
|
|
154
|
+
{status.improvementHook.fileSize != null && (
|
|
155
|
+
<span className="text-muted-foreground/70"> · {(status.improvementHook.fileSize / 1024).toFixed(1)}KB</span>
|
|
156
|
+
)}
|
|
157
|
+
</p>
|
|
158
|
+
{status.improvementHook.filePath && (
|
|
159
|
+
<CopyPathButton filePath={status.improvementHook.filePath} />
|
|
160
|
+
)}
|
|
161
|
+
<p className="text-[11px] text-muted-foreground/70 mt-2 leading-relaxed">
|
|
162
|
+
Edit this file directly to customize, or
|
|
163
|
+
run <code className="text-[10px] bg-muted px-1 py-0.5 rounded">/plannotator-compound</code> to
|
|
164
|
+
regenerate from recent denial history.
|
|
165
|
+
</p>
|
|
166
|
+
<button
|
|
167
|
+
onClick={() => setHookExpanded(!hookExpanded)}
|
|
168
|
+
className="text-xs text-primary hover:text-primary/80 mt-1.5 transition-colors"
|
|
169
|
+
>
|
|
170
|
+
{hookExpanded ? '▾ Hide content' : '▸ Show content'}
|
|
171
|
+
</button>
|
|
172
|
+
{hookExpanded && status.improvementHook.content && (
|
|
173
|
+
<pre className="mt-2 p-3 rounded-md bg-muted/50 border border-border text-[11px] text-foreground/80 overflow-auto max-h-64 whitespace-pre-wrap font-mono leading-relaxed">
|
|
174
|
+
{status.improvementHook.content}
|
|
175
|
+
</pre>
|
|
176
|
+
)}
|
|
177
|
+
</>
|
|
178
|
+
) : (
|
|
179
|
+
<>
|
|
180
|
+
<p className="text-xs text-muted-foreground mt-1 leading-relaxed">
|
|
181
|
+
No improvement hook found. This file injects corrective planning instructions
|
|
182
|
+
before your agent writes a plan — the more you review, the better your agent plans.
|
|
183
|
+
</p>
|
|
184
|
+
{status.improvementHook.filePath && (
|
|
185
|
+
<CopyPathButton filePath={status.improvementHook.filePath} />
|
|
186
|
+
)}
|
|
187
|
+
<p className="text-[11px] text-muted-foreground/70 mt-2 leading-relaxed">
|
|
188
|
+
Run <code className="text-[10px] bg-muted px-1 py-0.5 rounded">/plannotator-compound</code> to
|
|
189
|
+
auto-generate from your denial history, or create a plain text file at the path above with
|
|
190
|
+
your own instructions.{' '}
|
|
191
|
+
<a
|
|
192
|
+
href="https://plannotator.ai/blog/continuously-improve-claude-code-plans/"
|
|
193
|
+
target="_blank"
|
|
194
|
+
rel="noopener noreferrer"
|
|
195
|
+
className="text-primary hover:text-primary/80 underline underline-offset-2"
|
|
196
|
+
>
|
|
197
|
+
Learn more
|
|
198
|
+
</a>
|
|
199
|
+
</p>
|
|
200
|
+
</>
|
|
201
|
+
)}
|
|
202
|
+
</div>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
|
|
206
|
+
</div>
|
|
207
|
+
);
|
|
208
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ArchiveBrowser — Browsable list of saved plan decisions
|
|
3
|
+
*
|
|
4
|
+
* Reusable in both standalone archive mode and as a sidebar tab
|
|
5
|
+
* during normal plan review sessions.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React from "react";
|
|
9
|
+
import type { ArchivedPlan } from "@plannotator/core/storage-types";
|
|
10
|
+
|
|
11
|
+
export type { ArchivedPlan };
|
|
12
|
+
|
|
13
|
+
interface ArchiveBrowserProps {
|
|
14
|
+
plans: ArchivedPlan[];
|
|
15
|
+
selectedFile: string | null;
|
|
16
|
+
onSelect: (filename: string) => void;
|
|
17
|
+
isLoading: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function relativeTime(dateStr: string): string {
|
|
21
|
+
if (!dateStr) return "";
|
|
22
|
+
const now = Date.now();
|
|
23
|
+
const then = new Date(dateStr + "T12:00:00").getTime();
|
|
24
|
+
const diff = now - then;
|
|
25
|
+
|
|
26
|
+
if (diff < 86_400_000) return "today";
|
|
27
|
+
if (diff < 172_800_000) return "yesterday";
|
|
28
|
+
if (diff < 604_800_000) return `${Math.floor(diff / 86_400_000)}d ago`;
|
|
29
|
+
if (diff < 2_592_000_000) return `${Math.floor(diff / 604_800_000)}w ago`;
|
|
30
|
+
return dateStr;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const ArchiveBrowser: React.FC<ArchiveBrowserProps> = ({
|
|
34
|
+
plans,
|
|
35
|
+
selectedFile,
|
|
36
|
+
onSelect,
|
|
37
|
+
isLoading,
|
|
38
|
+
}) => {
|
|
39
|
+
if (isLoading) {
|
|
40
|
+
return (
|
|
41
|
+
<div className="p-4 text-xs text-muted-foreground text-center">
|
|
42
|
+
Loading archive...
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (plans.length === 0) {
|
|
48
|
+
return (
|
|
49
|
+
<div className="p-4 text-xs text-muted-foreground text-center">
|
|
50
|
+
No archived plans found.
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<div className="p-2">
|
|
57
|
+
<div className="space-y-0.5">
|
|
58
|
+
{plans.map((plan, i) => {
|
|
59
|
+
const showDateHeader = i === 0 || plan.date !== plans[i - 1].date;
|
|
60
|
+
|
|
61
|
+
const isSelected = selectedFile === plan.filename;
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<React.Fragment key={plan.filename}>
|
|
65
|
+
{showDateHeader && (
|
|
66
|
+
<div className="text-[10px] font-medium text-muted-foreground uppercase tracking-wider px-2 pt-2 pb-1">
|
|
67
|
+
{relativeTime(plan.date)} — {plan.date}
|
|
68
|
+
</div>
|
|
69
|
+
)}
|
|
70
|
+
<button
|
|
71
|
+
onClick={() => onSelect(plan.filename)}
|
|
72
|
+
className={`w-full text-left px-2 py-1.5 rounded text-xs transition-colors ${
|
|
73
|
+
isSelected
|
|
74
|
+
? "bg-primary/10 text-primary border border-primary/30"
|
|
75
|
+
: "text-foreground hover:bg-muted/50 border border-transparent"
|
|
76
|
+
}`}
|
|
77
|
+
>
|
|
78
|
+
<div className="flex items-center gap-1.5">
|
|
79
|
+
<span
|
|
80
|
+
className={`inline-block w-1.5 h-1.5 rounded-full flex-shrink-0 ${
|
|
81
|
+
plan.status === "approved"
|
|
82
|
+
? "bg-green-500"
|
|
83
|
+
: plan.status === "denied"
|
|
84
|
+
? "bg-red-500"
|
|
85
|
+
: "bg-muted-foreground"
|
|
86
|
+
}`}
|
|
87
|
+
title={plan.status}
|
|
88
|
+
/>
|
|
89
|
+
<span className="font-medium truncate">{plan.title}</span>
|
|
90
|
+
</div>
|
|
91
|
+
</button>
|
|
92
|
+
</React.Fragment>
|
|
93
|
+
);
|
|
94
|
+
})}
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
);
|
|
98
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
/** Compact annotation count badge for sidebar file trees and TOC */
|
|
4
|
+
export const CountBadge: React.FC<{ count: number; active?: boolean; className?: string }> = ({ count, active, className }) => (
|
|
5
|
+
<span
|
|
6
|
+
className={`flex-shrink-0 min-w-[18px] h-[18px] px-1 rounded flex items-center justify-center text-[10px] font-mono leading-none ${
|
|
7
|
+
active ? 'text-primary bg-primary/15' : 'text-muted-foreground bg-muted/70'
|
|
8
|
+
} ${className ?? ''}`}
|
|
9
|
+
>
|
|
10
|
+
{count}
|
|
11
|
+
</span>
|
|
12
|
+
);
|