@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.
Files changed (135) hide show
  1. package/HANDOFF.md +217 -11
  2. package/README.md +65 -10
  3. package/components/AgentToolAnnouncementDialog.tsx +1 -1
  4. package/components/AgentsTab.tsx +1 -1
  5. package/components/AnnotationPanel.tsx +142 -24
  6. package/components/AnnotationSidebar.tsx +1 -1
  7. package/components/AnnotationToolbar.tsx +64 -9
  8. package/components/ApproveDropdown.tsx +7 -9
  9. package/components/AskSessionAnnouncementDialog.tsx +1 -1
  10. package/components/AttachmentsButton.tsx +1 -1
  11. package/components/BlockRenderer.tsx +19 -5
  12. package/components/CodeFilePopout.tsx +139 -4
  13. package/components/CommentPopover.tsx +44 -8
  14. package/components/DecisionControl.tsx +31 -5
  15. package/components/DiagramBlock.tsx +17 -12
  16. package/components/EditorAnnotationCard.tsx +1 -1
  17. package/components/ExportModal.tsx +77 -7
  18. package/components/HostTitle.tsx +0 -4
  19. package/components/ImageAnnotator/Toolbar.tsx +25 -1
  20. package/components/ImageAnnotator/index.tsx +24 -4
  21. package/components/ImageLightbox.tsx +658 -120
  22. package/components/ImagePeek.tsx +38 -4
  23. package/components/ImageRegions.tsx +369 -0
  24. package/components/ImageThumbnail.tsx +1 -1
  25. package/components/ImageZoomStage.tsx +796 -0
  26. package/components/InboxAnnouncementDialog.tsx +202 -0
  27. package/components/InlineMarkdown.tsx +152 -24
  28. package/components/KeyboardShortcuts.tsx +23 -0
  29. package/components/LazyBlockBoundary.tsx +100 -0
  30. package/components/ListMarker.tsx +3 -3
  31. package/components/LookAndFeelAnnouncementDialog.tsx +12 -2
  32. package/components/MenuVersionSection.tsx +31 -9
  33. package/components/PlanDecisionMenuExtras.tsx +129 -0
  34. package/components/PlanHeaderMenu.tsx +15 -1
  35. package/components/ProviderIcons.tsx +8 -0
  36. package/components/RefHoverCard.tsx +913 -0
  37. package/components/SendFailureToast.tsx +126 -0
  38. package/components/Settings.tsx +617 -126
  39. package/components/TerminalToolsAnnouncementDialog.tsx +1 -1
  40. package/components/ThemeProvider.tsx +14 -1
  41. package/components/ThemeTab.tsx +16 -24
  42. package/components/Tooltip.tsx +49 -18
  43. package/components/Viewer.tsx +280 -41
  44. package/components/ai/DocumentAIChatPanel.tsx +29 -3
  45. package/components/ai/NewChatButton.tsx +74 -0
  46. package/components/blocks/CodeBlock.tsx +1 -1
  47. package/components/blocks/HtmlBlock.tsx +7 -1
  48. package/components/blocks/QuestionBlock.tsx +522 -62
  49. package/components/diagram/DiagramComposer.tsx +5 -1
  50. package/components/diagram/DiagramPending.tsx +12 -2
  51. package/components/diagram/DiagramViewer.tsx +19 -3
  52. package/components/html-embed/HtmlEmbedBlock.tsx +374 -0
  53. package/components/html-embed/SvgFenceBlock.tsx +46 -0
  54. package/components/html-embed/index.ts +3 -0
  55. package/components/html-embed/languages.ts +15 -0
  56. package/components/html-embed/loadGate.ts +107 -0
  57. package/components/html-viewer/HtmlViewer.tsx +47 -6
  58. package/components/html-viewer/bridge-script.asset.js +173 -1
  59. package/components/html-viewer/bridge-script.ts +173 -1
  60. package/components/html-viewer/useHtmlAnnotation.ts +125 -0
  61. package/components/imageZoom.ts +265 -0
  62. package/components/plan-diff/PlanCleanDiffView.tsx +1 -1
  63. package/components/plan-diff/PlanDiffViewer.tsx +13 -2
  64. package/components/plan-diff/PlanRawDiffView.tsx +1 -1
  65. package/components/sidebar/FileBrowser.tsx +16 -2
  66. package/components/sidebar/SidebarTabs.tsx +3 -0
  67. package/config/index.ts +3 -0
  68. package/config/reviewView.ts +41 -1
  69. package/config/settings.ts +155 -4
  70. package/configure.ts +28 -0
  71. package/hooks/pfm/useCodeFilePopout.ts +7 -1
  72. package/hooks/useAIChat.ts +72 -25
  73. package/hooks/useAnnotationDraft.ts +71 -6
  74. package/hooks/useAnnotationHighlighter.ts +57 -3
  75. package/hooks/useCodeAnnotationDraft.ts +113 -17
  76. package/hooks/useCookieHostSetting.ts +96 -0
  77. package/hooks/useDocumentFont.ts +17 -0
  78. package/hooks/useDocumentTextSize.ts +20 -0
  79. package/hooks/useFileBrowser.ts +10 -1
  80. package/hooks/useLinkedDoc.ts +226 -13
  81. package/hooks/usePackageChangesSetting.ts +90 -0
  82. package/hooks/usePlanLookDialog.ts +67 -0
  83. package/hooks/useSharing.ts +11 -7
  84. package/hooks/useThemePaletteHalves.ts +37 -0
  85. package/hooks/useUpdateCheck.ts +22 -4
  86. package/hooks/useUpdateToast.ts +1 -1
  87. package/package.json +23 -22
  88. package/shortcuts/code-review/annotationToolbar.shortcuts.ts +1 -0
  89. package/shortcuts/code-review/explorer.shortcuts.ts +82 -0
  90. package/shortcuts/core.ts +63 -4
  91. package/shortcuts/index.ts +1 -0
  92. package/shortcuts/plan-review/annotationPanel.shortcuts.ts +1 -1
  93. package/shortcuts/plan-review/commentPopover.shortcuts.ts +1 -0
  94. package/shortcuts/runtime.ts +4 -3
  95. package/styles.css +1 -1
  96. package/theme.css +179 -1
  97. package/themes/plannotator-graphite.css +66 -0
  98. package/types.ts +26 -9
  99. package/utils/agentSwitch.ts +41 -20
  100. package/utils/agentToolSetting.ts +1 -1
  101. package/utils/aiChatFormat.ts +23 -7
  102. package/utils/annotationOwnsHighlight.ts +4 -2
  103. package/utils/asciidocParser.ts +570 -0
  104. package/utils/autoUpdateNotice.ts +24 -0
  105. package/utils/belowTitleSlot.ts +174 -0
  106. package/utils/codeLineScroll.ts +100 -0
  107. package/utils/commentSubmitKey.ts +48 -0
  108. package/utils/cssFontFamily.ts +65 -0
  109. package/utils/decisionSpec.ts +190 -2
  110. package/utils/defaultNotesApp.ts +1 -1
  111. package/utils/diffFonts.ts +4 -1
  112. package/utils/documentFont.ts +68 -0
  113. package/utils/documentTextSize.ts +54 -0
  114. package/utils/fontDetect.ts +63 -0
  115. package/utils/inboxAnnouncement.ts +78 -0
  116. package/utils/lookAndFeelAnnouncement.ts +82 -5
  117. package/utils/markdownExtensions.ts +2 -2
  118. package/utils/mermaid.ts +20 -3
  119. package/utils/mermaidTheme.ts +3 -51
  120. package/utils/notion.ts +58 -0
  121. package/utils/parser.ts +28 -1
  122. package/utils/platform.ts +46 -0
  123. package/utils/refCard.ts +82 -0
  124. package/utils/richClipboard.ts +380 -0
  125. package/utils/richClipboardLists.ts +57 -0
  126. package/utils/richCopyPolicy.ts +22 -0
  127. package/utils/scrollAnchor.ts +82 -0
  128. package/utils/sectionRefs.ts +123 -0
  129. package/utils/selectionBoundary.ts +40 -0
  130. package/utils/sendFailure.ts +85 -0
  131. package/utils/sharing.ts +5 -2
  132. package/utils/themeRegistry.ts +10 -0
  133. package/utils/themeTokens.ts +74 -0
  134. package/utils/updateNotice.ts +30 -8
  135. package/utils/vscodePanel.ts +9 -0
@@ -0,0 +1,126 @@
1
+ import { useState } from 'react';
2
+ import { toast } from 'sonner';
3
+ import { copyTextToClipboard } from '../utils/clipboard';
4
+ import { canRetrySend, describeSendFailure, sendFailureOf } from '../utils/sendFailure';
5
+
6
+ /**
7
+ * The one message a review page shows when a decision did not reach the
8
+ * agent (#1392): which decision, why, Retry, and Copy feedback. It stays until
9
+ * dismissed (the person may not be looking when it fails) and a second
10
+ * failure replaces it rather than stacking. The page itself is untouched:
11
+ * the handlers that call this keep every annotation and never show a
12
+ * "sent" screen.
13
+ *
14
+ * The handlers bracket every send with `sendStarted()` / `sendSettled()`: a
15
+ * new send takes the message down (it no longer describes the page), and
16
+ * Retry does nothing while a send is in flight, so it can never post a
17
+ * second decision beside the one already going.
18
+ */
19
+
20
+ /**
21
+ * Each failure is a new toast with its own id, and the one before it is
22
+ * dismissed. Reusing one id races sonner: a dismissal reaches the Toaster a
23
+ * frame or two late, so a failure that lands within that window (a refused
24
+ * connection fails in milliseconds) would be marked deleted as it appears.
25
+ */
26
+ let failures = 0;
27
+ /** The failure toast on screen, if any. */
28
+ let currentId: string | null = null;
29
+ /** Decision sends in flight on this page. */
30
+ let inFlight = 0;
31
+
32
+ /** A decision send begins: the old failure no longer applies. */
33
+ export function sendStarted(): void {
34
+ inFlight += 1;
35
+ dismissSendFailureToast();
36
+ }
37
+
38
+ /** A decision send ended, however it ended. */
39
+ export function sendSettled(): void {
40
+ inFlight = Math.max(0, inFlight - 1);
41
+ }
42
+
43
+ /** The failure no longer applies (a send started, or the review was decided). */
44
+ export function dismissSendFailureToast(): void {
45
+ if (currentId === null) return;
46
+ toast.dismiss(currentId);
47
+ currentId = null;
48
+ }
49
+
50
+ /**
51
+ * Copy feedback stays inside the toast after a click (a plain sonner `cancel`
52
+ * button would close it and take the failure message with it). The data
53
+ * attributes give it sonner's own secondary-button shape; the colors come
54
+ * from the theme, since the Toasters run sonner's light theme and its
55
+ * secondary fill disappears on a dark card.
56
+ */
57
+ function CopyFeedbackButton({ getText }: { getText: () => string | undefined }) {
58
+ const [state, setState] = useState<'idle' | 'copied' | 'failed'>('idle');
59
+ return (
60
+ <button
61
+ type="button"
62
+ data-button=""
63
+ data-cancel=""
64
+ data-send-failure-copy=""
65
+ className="!bg-foreground/10 !text-foreground"
66
+ onClick={() => {
67
+ const text = getText();
68
+ if (!text) {
69
+ setState('failed');
70
+ return;
71
+ }
72
+ void copyTextToClipboard(text).then((copied) => setState(copied ? 'copied' : 'failed'));
73
+ }}
74
+ >
75
+ {state === 'copied' ? 'Copied' : state === 'failed' ? 'Copy failed' : 'Copy feedback'}
76
+ </button>
77
+ );
78
+ }
79
+
80
+ export function showSendFailureToast(options: {
81
+ /** What did not go out: names the toast's title. */
82
+ what: 'feedback' | 'approval';
83
+ /** The error the send threw (`DecisionSendError` says why). */
84
+ error: unknown;
85
+ /** Sends the same decision again, from the page as it is now. */
86
+ onRetry: () => void;
87
+ /** The text Retry would send now, as the page's Copy feedback copies it.
88
+ * Omitted when the decision carries no text (a bare approval). */
89
+ copyText?: () => string | undefined;
90
+ }): void {
91
+ const { what, error, onRetry, copyText } = options;
92
+ const failure = sendFailureOf(error);
93
+ dismissSendFailureToast(); // replaced, never stacked
94
+ const id = `plannotator-send-failure-${++failures}`;
95
+ currentId = id;
96
+ const forget = () => {
97
+ if (currentId === id) currentId = null;
98
+ };
99
+ toast.error(what === 'approval' ? 'Approval not sent' : 'Feedback not sent', {
100
+ id,
101
+ onDismiss: forget,
102
+ description: describeSendFailure(failure),
103
+ duration: Infinity,
104
+ // It stays up, so it sits at the bottom, clear of the header's decision
105
+ // control and the annotation panel the reviewer may want to read.
106
+ position: 'bottom-center',
107
+ closeButton: true,
108
+ cancel: copyText ? <CopyFeedbackButton getText={copyText} /> : undefined,
109
+ // An already-decided review cannot take the decision again.
110
+ action: canRetrySend(failure)
111
+ ? {
112
+ label: 'Retry',
113
+ onClick: () => {
114
+ if (inFlight > 0) return;
115
+ onRetry();
116
+ },
117
+ }
118
+ : undefined,
119
+ // 420px on a desktop (sonner's 356px wraps the reason onto three lines),
120
+ // re-centred on sonner's column; phones keep sonner's full-width layout.
121
+ classNames: {
122
+ toast: 'sm:!w-[420px] sm:![margin-left:calc((var(--width)_-_420px)_/_2)]',
123
+ description: '!text-foreground/70',
124
+ },
125
+ });
126
+ }