@plannotator/ui 0.28.0 → 0.29.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 (105) hide show
  1. package/README.md +6 -0
  2. package/components/AISettingsTab.tsx +5 -4
  3. package/components/ActionMenu.tsx +5 -1
  4. package/components/AgentsTab.tsx +10 -23
  5. package/components/AnnotationPanel.tsx +9 -5
  6. package/components/AnnotationToolbar.tsx +5 -13
  7. package/components/AnnotationToolstrip.tsx +2 -2
  8. package/components/ApproveDropdown.tsx +1 -1
  9. package/components/BlockRenderer.tsx +1 -1
  10. package/components/CodeFilePopout.tsx +5 -4
  11. package/components/CommentPopover.tsx +391 -65
  12. package/components/DocBadges.tsx +29 -11
  13. package/components/ExportModal.tsx +16 -8
  14. package/components/GraphvizBlock.tsx +1 -1
  15. package/components/InlineMarkdown.tsx +30 -13
  16. package/components/KeyboardShortcuts.tsx +37 -2
  17. package/components/Landing.tsx +7 -7
  18. package/components/MenuVersionSection.tsx +4 -4
  19. package/components/MermaidBlock.tsx +1 -1
  20. package/components/ModeToggle.tsx +7 -6
  21. package/components/OpenInAppButton.tsx +2 -5
  22. package/components/PinpointOverlay.tsx +9 -7
  23. package/components/PlanHeaderMenu.tsx +8 -8
  24. package/components/PopoutDialog.tsx +6 -1
  25. package/components/ResizeHandle.tsx +1 -0
  26. package/components/Settings.tsx +172 -12
  27. package/components/SkillReferenceMenu.tsx +260 -0
  28. package/components/StickyHeaderLane.tsx +7 -0
  29. package/components/ThemeProvider.tsx +131 -32
  30. package/components/ThemeTab.tsx +123 -77
  31. package/components/ToolbarButtons.tsx +29 -8
  32. package/components/Viewer.tsx +396 -130
  33. package/components/VimKeyHud.tsx +695 -0
  34. package/components/VimModeAnnouncementDialog.tsx +557 -0
  35. package/components/VimModeOverlay.tsx +235 -0
  36. package/components/VimTargetReticle.tsx +284 -0
  37. package/components/ai/DocumentAIChatPanel.tsx +1 -1
  38. package/components/blocks/CodeBlock.tsx +18 -18
  39. package/components/blocks/TablePopout.tsx +7 -8
  40. package/components/blocks/TableToolbar.tsx +7 -8
  41. package/components/goal-setup/GoalSetupSurface.tsx +16 -3
  42. package/components/html-viewer/HtmlViewer.tsx +450 -47
  43. package/components/html-viewer/annotationNumbering.ts +37 -0
  44. package/components/html-viewer/bridge-script.ts +4051 -298
  45. package/components/html-viewer/composerYield.ts +51 -0
  46. package/components/html-viewer/srcdoc.ts +18 -3
  47. package/components/html-viewer/useHtmlAnnotation.ts +457 -32
  48. package/components/icons/themeIcons.tsx +1 -1
  49. package/components/plan-diff/PlanCleanDiffView.tsx +9 -9
  50. package/components/plan-diff/PlanDiffBadge.tsx +22 -1
  51. package/components/settings/HooksTab.tsx +12 -8
  52. package/components/sidebar/FileBrowser.tsx +4 -1
  53. package/components/themeModes.tsx +28 -0
  54. package/config/configStore.ts +76 -1
  55. package/config/settings.ts +152 -0
  56. package/configure.ts +9 -0
  57. package/globals.d.ts +7 -1
  58. package/hooks/useAIChat.ts +5 -2
  59. package/hooks/useAIProviderActivation.ts +47 -0
  60. package/hooks/useAIProviderConfig.ts +5 -1
  61. package/hooks/useAgentSettings.ts +64 -23
  62. package/hooks/useAgents.ts +4 -4
  63. package/hooks/useAnnotationHighlighter.ts +100 -3
  64. package/hooks/useArchive.ts +2 -1
  65. package/hooks/useFenceTheme.ts +17 -0
  66. package/hooks/useLinkedDoc.ts +68 -1
  67. package/hooks/usePinpoint.ts +76 -75
  68. package/hooks/usePlanDiff.ts +73 -2
  69. package/hooks/useSkillReferenceAutocomplete.ts +239 -0
  70. package/hooks/useUpdateCheck.ts +1 -2
  71. package/hooks/useVimDocumentFocus.ts +116 -0
  72. package/hooks/useVimSelection.ts +1063 -0
  73. package/package.json +4 -4
  74. package/print.css +14 -13
  75. package/shortcuts/core.ts +38 -13
  76. package/shortcuts/index.ts +10 -0
  77. package/shortcuts/plan-review/commentPopover.shortcuts.ts +7 -0
  78. package/shortcuts/plan-review/vimSelection.shortcuts.ts +251 -0
  79. package/shortcuts/runtime.ts +111 -12
  80. package/styles.css +1 -1
  81. package/theme.css +504 -0
  82. package/themes/colorblind.css +89 -0
  83. package/themes/plannotator.css +2 -2
  84. package/types.ts +93 -10
  85. package/utils/agentSwitch.ts +33 -7
  86. package/utils/blockTargeting.ts +462 -178
  87. package/utils/clipboard.ts +110 -0
  88. package/utils/codeBlockMark.ts +50 -0
  89. package/utils/codeHighlight.ts +293 -0
  90. package/utils/codexModels.ts +79 -0
  91. package/utils/domSelection.ts +84 -0
  92. package/utils/htmlChrome.ts +73 -0
  93. package/utils/inputMethod.ts +79 -6
  94. package/utils/parser.ts +517 -21
  95. package/utils/preferenceTtl.ts +15 -0
  96. package/utils/sharing.ts +0 -1
  97. package/utils/skillCatalog.ts +269 -0
  98. package/utils/skillReferences.ts +475 -0
  99. package/utils/syntaxTheme.ts +83 -0
  100. package/utils/themeRegistry.ts +154 -0
  101. package/utils/vimHud.ts +263 -0
  102. package/utils/vimModeAnnouncement.ts +23 -0
  103. package/utils/vimNavigation.ts +417 -0
  104. package/utils/vimReticle.ts +88 -0
  105. package/utils/vimScroll.ts +162 -0
@@ -0,0 +1,116 @@
1
+ import { useEffect, useRef } from 'react';
2
+
3
+ const VIM_DOCUMENT_FOCUS_REQUEST = 'plannotator:vim-document-focus-request';
4
+
5
+ const EDITABLE_FOCUS_SELECTOR = [
6
+ 'input',
7
+ 'textarea',
8
+ 'select',
9
+ '[contenteditable]:not([contenteditable="false"])',
10
+ '[role="textbox"]',
11
+ '[role="combobox"]',
12
+ ].join(',');
13
+
14
+ const BLOCKING_OVERLAY_SELECTOR = [
15
+ '[role="dialog"]',
16
+ '[aria-modal="true"]',
17
+ // Some legacy Plannotator modals predate explicit dialog semantics. Keep
18
+ // Vim from focusing the obscured document underneath those full-screen
19
+ // overlays while they are brought onto the shared dialog primitive.
20
+ '.fixed.inset-0',
21
+ ].join(',');
22
+
23
+ /** Inputs for restoring keyboard ownership to a Vim-enabled document. */
24
+ export interface UseVimDocumentFocusOptions {
25
+ readonly enabled: boolean;
26
+ readonly blocked: boolean;
27
+ /** Focus the owning document surface and report whether focus moved to it. */
28
+ readonly focusDocument: () => boolean;
29
+ }
30
+
31
+ function pageFocusIsNeutral(): boolean {
32
+ return document.activeElement === document.body || document.activeElement === null;
33
+ }
34
+
35
+ function hasBlockingOverlay(): boolean {
36
+ return document.querySelector(BLOCKING_OVERLAY_SELECTOR) !== null;
37
+ }
38
+
39
+ function targetOwnsTextInput(target: EventTarget | null): boolean {
40
+ return target instanceof Element && target.closest(EDITABLE_FOCUS_SELECTOR) !== null;
41
+ }
42
+
43
+ /** Ask the active Vim document to reclaim focus after an owned UI closes. */
44
+ export function requestVimDocumentFocus(): void {
45
+ document.dispatchEvent(new Event(VIM_DOCUMENT_FOCUS_REQUEST, { cancelable: true }));
46
+ }
47
+
48
+ /**
49
+ * Give an enabled Vim document initial keyboard ownership and let Escape from
50
+ * neutral app chrome return to it.
51
+ *
52
+ * Editable controls and overlays retain first ownership of Escape. The hook
53
+ * only prevents the event after focus actually moves back to the document.
54
+ */
55
+ export function useVimDocumentFocus({
56
+ enabled,
57
+ blocked,
58
+ focusDocument,
59
+ }: UseVimDocumentFocusOptions): void {
60
+ const autoFocusAttemptedRef = useRef(false);
61
+
62
+ useEffect(() => {
63
+ if (!enabled) {
64
+ autoFocusAttemptedRef.current = false;
65
+ return;
66
+ }
67
+ if (autoFocusAttemptedRef.current) return;
68
+ autoFocusAttemptedRef.current = true;
69
+ if (blocked || !pageFocusIsNeutral() || hasBlockingOverlay()) return;
70
+ focusDocument();
71
+ }, [blocked, enabled, focusDocument]);
72
+
73
+ useEffect(() => {
74
+ if (!enabled) return;
75
+
76
+ const handleFocusRequest = (event: Event) => {
77
+ if (
78
+ !event.defaultPrevented
79
+ && !blocked
80
+ && !hasBlockingOverlay()
81
+ && focusDocument()
82
+ ) {
83
+ // One visible document owns each request when a host renders multiple
84
+ // Viewer instances.
85
+ event.preventDefault();
86
+ }
87
+ };
88
+ const handleEscape = (event: KeyboardEvent) => {
89
+ if (
90
+ event.key !== 'Escape'
91
+ || event.defaultPrevented
92
+ || event.isComposing
93
+ || event.ctrlKey
94
+ || event.metaKey
95
+ || event.altKey
96
+ || event.shiftKey
97
+ || blocked
98
+ || targetOwnsTextInput(event.target)
99
+ || hasBlockingOverlay()
100
+ ) {
101
+ return;
102
+ }
103
+
104
+ if (focusDocument()) {
105
+ event.preventDefault();
106
+ }
107
+ };
108
+
109
+ document.addEventListener(VIM_DOCUMENT_FOCUS_REQUEST, handleFocusRequest);
110
+ document.addEventListener('keydown', handleEscape);
111
+ return () => {
112
+ document.removeEventListener(VIM_DOCUMENT_FOCUS_REQUEST, handleFocusRequest);
113
+ document.removeEventListener('keydown', handleEscape);
114
+ };
115
+ }, [blocked, enabled, focusDocument]);
116
+ }