@plannotator/ui 0.53.1 → 0.54.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/HANDOFF.md +217 -11
- package/README.md +65 -10
- package/components/AgentToolAnnouncementDialog.tsx +1 -1
- package/components/AgentsTab.tsx +1 -1
- package/components/AnnotationPanel.tsx +142 -24
- package/components/AnnotationSidebar.tsx +1 -1
- package/components/AnnotationToolbar.tsx +64 -9
- package/components/ApproveDropdown.tsx +7 -9
- package/components/AskSessionAnnouncementDialog.tsx +1 -1
- package/components/AttachmentsButton.tsx +1 -1
- package/components/BlockRenderer.tsx +19 -5
- package/components/CodeFilePopout.tsx +139 -4
- package/components/CommentPopover.tsx +44 -8
- package/components/DecisionControl.tsx +31 -5
- package/components/DiagramBlock.tsx +17 -12
- package/components/EditorAnnotationCard.tsx +1 -1
- package/components/ExportModal.tsx +77 -7
- package/components/HostTitle.tsx +0 -4
- package/components/ImageAnnotator/Toolbar.tsx +25 -1
- package/components/ImageAnnotator/index.tsx +24 -4
- package/components/ImageLightbox.tsx +658 -120
- package/components/ImagePeek.tsx +38 -4
- package/components/ImageRegions.tsx +369 -0
- package/components/ImageThumbnail.tsx +1 -1
- package/components/ImageZoomStage.tsx +796 -0
- package/components/InboxAnnouncementDialog.tsx +202 -0
- package/components/InlineMarkdown.tsx +152 -24
- package/components/KeyboardShortcuts.tsx +23 -0
- package/components/LazyBlockBoundary.tsx +100 -0
- package/components/ListMarker.tsx +3 -3
- package/components/LookAndFeelAnnouncementDialog.tsx +12 -2
- package/components/MenuVersionSection.tsx +31 -9
- package/components/PlanDecisionMenuExtras.tsx +129 -0
- package/components/PlanHeaderMenu.tsx +15 -1
- package/components/ProviderIcons.tsx +8 -0
- package/components/RefHoverCard.tsx +913 -0
- package/components/SendFailureToast.tsx +126 -0
- package/components/Settings.tsx +617 -126
- package/components/TerminalToolsAnnouncementDialog.tsx +1 -1
- package/components/ThemeProvider.tsx +14 -1
- package/components/ThemeTab.tsx +16 -24
- package/components/Tooltip.tsx +49 -18
- package/components/Viewer.tsx +280 -41
- package/components/ai/DocumentAIChatPanel.tsx +29 -3
- package/components/ai/NewChatButton.tsx +74 -0
- package/components/blocks/CodeBlock.tsx +1 -1
- package/components/blocks/HtmlBlock.tsx +7 -1
- package/components/blocks/QuestionBlock.tsx +522 -62
- package/components/diagram/DiagramComposer.tsx +5 -1
- package/components/diagram/DiagramPending.tsx +12 -2
- package/components/diagram/DiagramViewer.tsx +19 -3
- package/components/html-embed/HtmlEmbedBlock.tsx +374 -0
- package/components/html-embed/SvgFenceBlock.tsx +46 -0
- package/components/html-embed/index.ts +3 -0
- package/components/html-embed/languages.ts +15 -0
- package/components/html-embed/loadGate.ts +107 -0
- package/components/html-viewer/HtmlViewer.tsx +47 -6
- package/components/html-viewer/bridge-script.asset.js +173 -1
- package/components/html-viewer/bridge-script.ts +173 -1
- package/components/html-viewer/useHtmlAnnotation.ts +125 -0
- package/components/imageZoom.ts +265 -0
- package/components/plan-diff/PlanCleanDiffView.tsx +1 -1
- package/components/plan-diff/PlanDiffViewer.tsx +13 -2
- package/components/plan-diff/PlanRawDiffView.tsx +1 -1
- package/components/sidebar/FileBrowser.tsx +16 -2
- package/components/sidebar/SidebarTabs.tsx +3 -0
- package/config/index.ts +3 -0
- package/config/reviewView.ts +41 -1
- package/config/settings.ts +155 -4
- package/configure.ts +28 -0
- package/hooks/pfm/useCodeFilePopout.ts +7 -1
- package/hooks/useAIChat.ts +72 -25
- package/hooks/useAnnotationDraft.ts +71 -6
- package/hooks/useAnnotationHighlighter.ts +57 -3
- package/hooks/useCodeAnnotationDraft.ts +113 -17
- package/hooks/useCookieHostSetting.ts +96 -0
- package/hooks/useDocumentFont.ts +17 -0
- package/hooks/useDocumentTextSize.ts +20 -0
- package/hooks/useFileBrowser.ts +10 -1
- package/hooks/useLinkedDoc.ts +226 -13
- package/hooks/usePackageChangesSetting.ts +90 -0
- package/hooks/usePlanLookDialog.ts +67 -0
- package/hooks/useSharing.ts +11 -7
- package/hooks/useThemePaletteHalves.ts +37 -0
- package/hooks/useUpdateCheck.ts +22 -4
- package/hooks/useUpdateToast.ts +1 -1
- package/package.json +23 -22
- package/shortcuts/code-review/annotationToolbar.shortcuts.ts +1 -0
- package/shortcuts/code-review/explorer.shortcuts.ts +82 -0
- package/shortcuts/core.ts +63 -4
- package/shortcuts/index.ts +1 -0
- package/shortcuts/plan-review/annotationPanel.shortcuts.ts +1 -1
- package/shortcuts/plan-review/commentPopover.shortcuts.ts +1 -0
- package/shortcuts/runtime.ts +4 -3
- package/styles.css +1 -1
- package/theme.css +179 -1
- package/themes/plannotator-graphite.css +66 -0
- package/types.ts +26 -9
- package/utils/agentSwitch.ts +41 -20
- package/utils/agentToolSetting.ts +1 -1
- package/utils/aiChatFormat.ts +23 -7
- package/utils/annotationOwnsHighlight.ts +4 -2
- package/utils/asciidocParser.ts +570 -0
- package/utils/autoUpdateNotice.ts +24 -0
- package/utils/belowTitleSlot.ts +174 -0
- package/utils/codeLineScroll.ts +100 -0
- package/utils/commentSubmitKey.ts +48 -0
- package/utils/cssFontFamily.ts +65 -0
- package/utils/decisionSpec.ts +190 -2
- package/utils/defaultNotesApp.ts +1 -1
- package/utils/diffFonts.ts +4 -1
- package/utils/documentFont.ts +68 -0
- package/utils/documentTextSize.ts +54 -0
- package/utils/fontDetect.ts +63 -0
- package/utils/inboxAnnouncement.ts +78 -0
- package/utils/lookAndFeelAnnouncement.ts +82 -5
- package/utils/markdownExtensions.ts +2 -2
- package/utils/mermaid.ts +20 -3
- package/utils/mermaidTheme.ts +3 -51
- package/utils/notion.ts +58 -0
- package/utils/parser.ts +28 -1
- package/utils/platform.ts +46 -0
- package/utils/refCard.ts +82 -0
- package/utils/richClipboard.ts +380 -0
- package/utils/richClipboardLists.ts +57 -0
- package/utils/richCopyPolicy.ts +22 -0
- package/utils/scrollAnchor.ts +82 -0
- package/utils/sectionRefs.ts +123 -0
- package/utils/selectionBoundary.ts +40 -0
- package/utils/sendFailure.ts +85 -0
- package/utils/sharing.ts +5 -2
- package/utils/themeRegistry.ts +10 -0
- package/utils/themeTokens.ts +74 -0
- package/utils/updateNotice.ts +30 -8
- package/utils/vscodePanel.ts +9 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import React, { useId } from 'react';
|
|
2
|
+
|
|
3
|
+
interface NewChatButtonProps {
|
|
4
|
+
onNewChat: () => void;
|
|
5
|
+
/** A question is in flight: a new chat would cut it off, so it waits. */
|
|
6
|
+
busy?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* A busy "Ask this session" answer still offers "Ask when it finishes" /
|
|
9
|
+
* "Interrupt and ask now": clearing would drop that question unasked.
|
|
10
|
+
*/
|
|
11
|
+
pendingChoice?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* "Ask this session": the agent session that opened Plannotator answers, and
|
|
14
|
+
* it keeps its own memory, so the button only clears the panel. The label
|
|
15
|
+
* says so instead of promising fresh context.
|
|
16
|
+
*/
|
|
17
|
+
sessionBridge?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function newChatLabels(sessionBridge: boolean): { label: string; title: string } {
|
|
21
|
+
return sessionBridge
|
|
22
|
+
? {
|
|
23
|
+
label: 'Clear chat',
|
|
24
|
+
title: 'Clear this panel. The session that opened Plannotator still remembers earlier questions.',
|
|
25
|
+
}
|
|
26
|
+
: {
|
|
27
|
+
label: 'New chat',
|
|
28
|
+
title: 'Clear this chat and start a fresh AI session',
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Why the button is unavailable right now; null when it can be used. */
|
|
33
|
+
export function newChatBlockedReason(options: { busy?: boolean; pendingChoice?: boolean }): string | null {
|
|
34
|
+
if (options.busy) return 'Wait for the answer, or stop it, before starting a new chat.';
|
|
35
|
+
if (options.pendingChoice) return 'First choose "Ask when it finishes" or "Interrupt and ask now" for the waiting question.';
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The Ask AI panel's "New chat" row (#1981). While unavailable it stays
|
|
41
|
+
* focusable (`aria-disabled`, clicks ignored) and its reason is its
|
|
42
|
+
* description, so keyboard and screen-reader users learn why.
|
|
43
|
+
*/
|
|
44
|
+
export const NewChatButton: React.FC<NewChatButtonProps> = ({
|
|
45
|
+
onNewChat,
|
|
46
|
+
busy = false,
|
|
47
|
+
pendingChoice = false,
|
|
48
|
+
sessionBridge = false,
|
|
49
|
+
}) => {
|
|
50
|
+
const { label, title } = newChatLabels(sessionBridge);
|
|
51
|
+
const blocked = newChatBlockedReason({ busy, pendingChoice });
|
|
52
|
+
const descriptionId = useId();
|
|
53
|
+
return (
|
|
54
|
+
<div className="flex items-center justify-end px-2 pt-1.5 pb-0.5" data-ai-new-chat-row>
|
|
55
|
+
<button
|
|
56
|
+
type="button"
|
|
57
|
+
onClick={() => { if (!blocked) onNewChat(); }}
|
|
58
|
+
aria-disabled={blocked ? true : undefined}
|
|
59
|
+
aria-describedby={descriptionId}
|
|
60
|
+
title={blocked ?? title}
|
|
61
|
+
data-ai-new-chat
|
|
62
|
+
className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded-md text-[11px] text-muted-foreground hover:text-foreground hover:bg-muted aria-disabled:opacity-40 aria-disabled:cursor-not-allowed aria-disabled:hover:bg-transparent aria-disabled:hover:text-muted-foreground transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/50"
|
|
63
|
+
>
|
|
64
|
+
<svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2} aria-hidden="true">
|
|
65
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
|
66
|
+
</svg>
|
|
67
|
+
{label}
|
|
68
|
+
</button>
|
|
69
|
+
<span id={descriptionId} className="sr-only" data-ai-new-chat-description>
|
|
70
|
+
{blocked ?? title}
|
|
71
|
+
</span>
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
};
|
|
@@ -54,7 +54,7 @@ export const CodeBlock: React.FC<CodeBlockProps> = ({ block, onHover, onLeave })
|
|
|
54
54
|
>
|
|
55
55
|
<button
|
|
56
56
|
onClick={handleCopy}
|
|
57
|
-
className="absolute top-2 right-2 p-1.5 rounded-md bg-muted/80 hover:bg-muted text-muted-foreground hover:text-foreground opacity-0 group-hover:opacity-100 transition-opacity z-10"
|
|
57
|
+
className="absolute top-2 right-2 p-1.5 rounded-md bg-muted/80 hover:bg-muted text-muted-foreground hover:text-foreground opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 [@media(hover:none)]:opacity-100 transition-opacity z-10"
|
|
58
58
|
title={copied ? 'Copied!' : 'Copy code'}
|
|
59
59
|
>
|
|
60
60
|
{copied ? (
|
|
@@ -86,7 +86,13 @@ function rewriteRelativeRefs(
|
|
|
86
86
|
// Media was already decided by the host before insertion (see
|
|
87
87
|
// resolveHostMedia); only the load-failure fallback is wired here.
|
|
88
88
|
root.querySelectorAll<HTMLImageElement>('img[data-host-image]').forEach((img) => {
|
|
89
|
-
|
|
89
|
+
// The raw HTML is not React's: replacing the <img> here cannot trip React's insertBefore.
|
|
90
|
+
// The placeholder's alt text is never quoted by a text comment (annotation-exclude).
|
|
91
|
+
const onError = () => {
|
|
92
|
+
const placeholder = unavailableMedia(img.ownerDocument, img.getAttribute('alt') || 'Image', IMAGE_NOT_FOUND_TITLE);
|
|
93
|
+
placeholder.classList.add('annotation-exclude');
|
|
94
|
+
img.replaceWith(placeholder);
|
|
95
|
+
};
|
|
90
96
|
img.addEventListener('error', onError);
|
|
91
97
|
cleanups.push(() => img.removeEventListener('error', onError));
|
|
92
98
|
});
|