@parhelia/core 0.1.12881 → 0.1.12882

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 (307) hide show
  1. package/dist/components/ui/card.d.ts +1 -3
  2. package/dist/components/ui/card.js +2 -2
  3. package/dist/components/ui/card.js.map +1 -1
  4. package/dist/components/ui/context-menu.js +2 -2
  5. package/dist/config/config.js +7 -8
  6. package/dist/config/config.js.map +1 -1
  7. package/dist/config/types.d.ts +7 -0
  8. package/dist/config/types.js.map +1 -1
  9. package/dist/editor/FieldActionsOverlay.d.ts +1 -0
  10. package/dist/editor/FieldActionsOverlay.js +45 -1
  11. package/dist/editor/FieldActionsOverlay.js.map +1 -1
  12. package/dist/editor/FieldListField.d.ts +1 -1
  13. package/dist/editor/FieldListField.js +18 -20
  14. package/dist/editor/FieldListField.js.map +1 -1
  15. package/dist/editor/ImageEditor.d.ts +1 -6
  16. package/dist/editor/ImageEditor.js +3 -19
  17. package/dist/editor/ImageEditor.js.map +1 -1
  18. package/dist/editor/PictureEditor.d.ts +1 -2
  19. package/dist/editor/PictureEditor.js +14 -5
  20. package/dist/editor/PictureEditor.js.map +1 -1
  21. package/dist/editor/ai/Agents.js +2 -2
  22. package/dist/editor/ai/Agents.js.map +1 -1
  23. package/dist/editor/ai/GuidanceOverlay.js +11 -1
  24. package/dist/editor/ai/GuidanceOverlay.js.map +1 -1
  25. package/dist/editor/ai/InlineAiDialog.js +11 -22
  26. package/dist/editor/ai/InlineAiDialog.js.map +1 -1
  27. package/dist/editor/ai/InlineAiTrigger.js +57 -17
  28. package/dist/editor/ai/InlineAiTrigger.js.map +1 -1
  29. package/dist/editor/ai/dialogs/capturePageDom.js +36 -66
  30. package/dist/editor/ai/dialogs/capturePageDom.js.map +1 -1
  31. package/dist/editor/ai/dialogs/capturePageScreenshot.js +162 -281
  32. package/dist/editor/ai/dialogs/capturePageScreenshot.js.map +1 -1
  33. package/dist/editor/ai/terminal/agentSessionState.d.ts +0 -3
  34. package/dist/editor/ai/terminal/agentSessionState.js +1 -3
  35. package/dist/editor/ai/terminal/agentSessionState.js.map +1 -1
  36. package/dist/editor/ai/terminal/agentStartRequest.d.ts +1 -2
  37. package/dist/editor/ai/terminal/agentStartRequest.js +1 -2
  38. package/dist/editor/ai/terminal/agentStartRequest.js.map +1 -1
  39. package/dist/editor/ai/terminal/components/AgentCostDisplay.js +1 -1
  40. package/dist/editor/ai/terminal/components/AgentCostDisplay.js.map +1 -1
  41. package/dist/editor/ai/terminal/components/AgentDocumentList.d.ts +0 -7
  42. package/dist/editor/ai/terminal/components/AgentDocumentList.js +13 -55
  43. package/dist/editor/ai/terminal/components/AgentDocumentList.js.map +1 -1
  44. package/dist/editor/ai/terminal/components/AgentFullPromptControls.d.ts +1 -3
  45. package/dist/editor/ai/terminal/components/AgentFullPromptControls.js +14 -22
  46. package/dist/editor/ai/terminal/components/AgentFullPromptControls.js.map +1 -1
  47. package/dist/editor/ai/terminal/components/AgentModeSelector.js +4 -4
  48. package/dist/editor/ai/terminal/components/AgentModeSelector.js.map +1 -1
  49. package/dist/editor/ai/terminal/components/AgentPromptActionButtons.js +4 -4
  50. package/dist/editor/ai/terminal/components/AgentPromptActionButtons.js.map +1 -1
  51. package/dist/editor/ai/terminal/components/AgentPromptComposer.js +1 -1
  52. package/dist/editor/ai/terminal/components/AgentPromptComposer.js.map +1 -1
  53. package/dist/editor/ai/terminal/components/AgentPromptInputArea.d.ts +1 -2
  54. package/dist/editor/ai/terminal/components/AgentPromptInputArea.js +11 -8
  55. package/dist/editor/ai/terminal/components/AgentPromptInputArea.js.map +1 -1
  56. package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.d.ts +4 -1
  57. package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.js +14 -31
  58. package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.js.map +1 -1
  59. package/dist/editor/ai/terminal/components/AgentSettingsPopover.js +1 -1
  60. package/dist/editor/ai/terminal/components/AgentSettingsPopover.js.map +1 -1
  61. package/dist/editor/ai/terminal/components/AgentTerminalFullLayout.d.ts +1 -2
  62. package/dist/editor/ai/terminal/components/AgentTerminalFullLayout.js +4 -2
  63. package/dist/editor/ai/terminal/components/AgentTerminalFullLayout.js.map +1 -1
  64. package/dist/editor/ai/terminal/components/AgentTerminalMessageGroups.js +1 -1
  65. package/dist/editor/ai/terminal/components/AgentTerminalMessageGroups.js.map +1 -1
  66. package/dist/editor/ai/terminal/components/AgentTerminalView.js +2 -13
  67. package/dist/editor/ai/terminal/components/AgentTerminalView.js.map +1 -1
  68. package/dist/editor/ai/terminal/components/AiResponseMessage.js +14 -16
  69. package/dist/editor/ai/terminal/components/AiResponseMessage.js.map +1 -1
  70. package/dist/editor/ai/terminal/components/ContextInfoBar.js +2 -22
  71. package/dist/editor/ai/terminal/components/ContextInfoBar.js.map +1 -1
  72. package/dist/editor/ai/terminal/components/QueuedPromptsPanel.js +26 -37
  73. package/dist/editor/ai/terminal/components/QueuedPromptsPanel.js.map +1 -1
  74. package/dist/editor/ai/terminal/components/UserMessage.d.ts +1 -2
  75. package/dist/editor/ai/terminal/components/UserMessage.js +8 -144
  76. package/dist/editor/ai/terminal/components/UserMessage.js.map +1 -1
  77. package/dist/editor/ai/terminal/useAgentPromptComposerHandlers.js +1 -1
  78. package/dist/editor/ai/terminal/useAgentPromptComposerHandlers.js.map +1 -1
  79. package/dist/editor/ai/terminal/useAgentSessionSync.d.ts +0 -1
  80. package/dist/editor/ai/terminal/useAgentSubmitHandlers.d.ts +1 -3
  81. package/dist/editor/ai/terminal/useAgentSubmitHandlers.js +3 -9
  82. package/dist/editor/ai/terminal/useAgentSubmitHandlers.js.map +1 -1
  83. package/dist/editor/ai/terminal/useAgentTerminalController.js +0 -7
  84. package/dist/editor/ai/terminal/useAgentTerminalController.js.map +1 -1
  85. package/dist/editor/ai/terminal/useAgentTerminalUiState.js +1 -1
  86. package/dist/editor/ai/terminal/useAgentTerminalUiState.js.map +1 -1
  87. package/dist/editor/ai/terminal/useAgentUserMessageSocketHandler.js +1 -3
  88. package/dist/editor/ai/terminal/useAgentUserMessageSocketHandler.js.map +1 -1
  89. package/dist/editor/ai/useInlineAiPosition.d.ts +1 -1
  90. package/dist/editor/ai/useInlineAiPosition.js +52 -22
  91. package/dist/editor/ai/useInlineAiPosition.js.map +1 -1
  92. package/dist/editor/ai-image-editor/AiImageResultOverlay.js +62 -30
  93. package/dist/editor/ai-image-editor/AiImageResultOverlay.js.map +1 -1
  94. package/dist/editor/client/EditorShell.d.ts +1 -5
  95. package/dist/editor/client/EditorShell.js +136 -285
  96. package/dist/editor/client/EditorShell.js.map +1 -1
  97. package/dist/editor/client/editContext.d.ts +5 -33
  98. package/dist/editor/client/editContext.js.map +1 -1
  99. package/dist/editor/client/hooks/useSocketMessageHandler.js +17 -14
  100. package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
  101. package/dist/editor/client/itemsRepository.d.ts +0 -2
  102. package/dist/editor/client/itemsRepository.js +8 -15
  103. package/dist/editor/client/itemsRepository.js.map +1 -1
  104. package/dist/editor/client/operations.d.ts +1 -1
  105. package/dist/editor/client/operations.js +17 -41
  106. package/dist/editor/client/operations.js.map +1 -1
  107. package/dist/editor/client/pageModelBuilder.js +7 -24
  108. package/dist/editor/client/pageModelBuilder.js.map +1 -1
  109. package/dist/editor/commands/handlers/uiActionHandlers.js +5 -1
  110. package/dist/editor/commands/handlers/uiActionHandlers.js.map +1 -1
  111. package/dist/editor/editor-warnings/FinalWorkflowStateReadOnly.js +5 -0
  112. package/dist/editor/editor-warnings/FinalWorkflowStateReadOnly.js.map +1 -1
  113. package/dist/editor/editor-warnings/ItemLocked.js +6 -3
  114. package/dist/editor/editor-warnings/ItemLocked.js.map +1 -1
  115. package/dist/editor/field-types/MultiLineText.js +3 -10
  116. package/dist/editor/field-types/MultiLineText.js.map +1 -1
  117. package/dist/editor/field-types/RawEditor.js +1 -8
  118. package/dist/editor/field-types/RawEditor.js.map +1 -1
  119. package/dist/editor/field-types/RichTextEditorComponent.js +45 -156
  120. package/dist/editor/field-types/RichTextEditorComponent.js.map +1 -1
  121. package/dist/editor/field-types/SingleLineText.js +3 -10
  122. package/dist/editor/field-types/SingleLineText.js.map +1 -1
  123. package/dist/editor/field-types/richtext/components/ReactSlate.js +2 -8
  124. package/dist/editor/field-types/richtext/components/ReactSlate.js.map +1 -1
  125. package/dist/editor/field-types/richtext/contextMenuFactory.d.ts +2 -1
  126. package/dist/editor/field-types/richtext/contextMenuFactory.js +303 -100
  127. package/dist/editor/field-types/richtext/contextMenuFactory.js.map +1 -1
  128. package/dist/editor/field-types/richtext/types.d.ts +0 -2
  129. package/dist/editor/field-types/richtext/types.js.map +1 -1
  130. package/dist/editor/media-selector/MediaFolderBrowser.d.ts +2 -1
  131. package/dist/editor/media-selector/MediaFolderBrowser.js +19 -9
  132. package/dist/editor/media-selector/MediaFolderBrowser.js.map +1 -1
  133. package/dist/editor/media-selector/TreeSelector.js +30 -24
  134. package/dist/editor/media-selector/TreeSelector.js.map +1 -1
  135. package/dist/editor/media-selector/UploadZone.d.ts +2 -1
  136. package/dist/editor/media-selector/UploadZone.js +21 -9
  137. package/dist/editor/media-selector/UploadZone.js.map +1 -1
  138. package/dist/editor/menubar/PageSelector.js +2 -8
  139. package/dist/editor/menubar/PageSelector.js.map +1 -1
  140. package/dist/editor/menubar/VersionPreviewCard.js +249 -4
  141. package/dist/editor/menubar/VersionPreviewCard.js.map +1 -1
  142. package/dist/editor/menubar/toolbar-sections/EditControls.js +2 -2
  143. package/dist/editor/menubar/toolbar-sections/EditControls.js.map +1 -1
  144. package/dist/editor/menubar/toolbar-sections/ManualBrowser.d.ts +10 -0
  145. package/dist/editor/menubar/toolbar-sections/ManualBrowser.js +462 -63
  146. package/dist/editor/menubar/toolbar-sections/ManualBrowser.js.map +1 -1
  147. package/dist/editor/menubar/toolbar-sections/ViewportControls.js +1 -1
  148. package/dist/editor/page-editor-chrome/CommentHighlightings.d.ts +2 -5
  149. package/dist/editor/page-editor-chrome/CommentHighlightings.js +215 -340
  150. package/dist/editor/page-editor-chrome/CommentHighlightings.js.map +1 -1
  151. package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.d.ts +1 -5
  152. package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.js +4 -11
  153. package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.js.map +1 -1
  154. package/dist/editor/page-editor-chrome/FieldActionIndicator.js +13 -21
  155. package/dist/editor/page-editor-chrome/FieldActionIndicator.js.map +1 -1
  156. package/dist/editor/page-editor-chrome/FieldEditedIndicator.js +29 -23
  157. package/dist/editor/page-editor-chrome/FieldEditedIndicator.js.map +1 -1
  158. package/dist/editor/page-editor-chrome/FrameMenu.js +19 -110
  159. package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
  160. package/dist/editor/page-editor-chrome/InlineEditor.d.ts +7 -0
  161. package/dist/editor/page-editor-chrome/InlineEditor.js +1719 -0
  162. package/dist/editor/page-editor-chrome/InlineEditor.js.map +1 -0
  163. package/dist/editor/page-editor-chrome/LockedFieldIndicator.d.ts +2 -3
  164. package/dist/editor/page-editor-chrome/LockedFieldIndicator.js +45 -148
  165. package/dist/editor/page-editor-chrome/LockedFieldIndicator.js.map +1 -1
  166. package/dist/editor/page-editor-chrome/PageEditorChrome.d.ts +0 -2
  167. package/dist/editor/page-editor-chrome/PageEditorChrome.js +21 -25
  168. package/dist/editor/page-editor-chrome/PageEditorChrome.js.map +1 -1
  169. package/dist/editor/page-editor-chrome/PictureEditorOverlay.js +128 -163
  170. package/dist/editor/page-editor-chrome/PictureEditorOverlay.js.map +1 -1
  171. package/dist/editor/page-editor-chrome/PlaceholderDropZone.d.ts +1 -1
  172. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +3 -6
  173. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
  174. package/dist/editor/page-editor-chrome/PlaceholderDropZones.d.ts +2 -1
  175. package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +146 -83
  176. package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
  177. package/dist/editor/page-editor-chrome/SuggestionHighlightings.d.ts +2 -5
  178. package/dist/editor/page-editor-chrome/SuggestionHighlightings.js +63 -144
  179. package/dist/editor/page-editor-chrome/SuggestionHighlightings.js.map +1 -1
  180. package/dist/editor/page-editor-chrome/VersionDiffHighlightings.d.ts +2 -1
  181. package/dist/editor/page-editor-chrome/VersionDiffHighlightings.js +30 -101
  182. package/dist/editor/page-editor-chrome/VersionDiffHighlightings.js.map +1 -1
  183. package/dist/editor/page-editor-chrome/overlay/IframeOverlayProvider.d.ts +1 -10
  184. package/dist/editor/page-editor-chrome/overlay/IframeOverlayProvider.js +122 -105
  185. package/dist/editor/page-editor-chrome/overlay/IframeOverlayProvider.js.map +1 -1
  186. package/dist/editor/page-editor-chrome/overlay/geometry.d.ts +4 -11
  187. package/dist/editor/page-editor-chrome/overlay/geometry.js +36 -139
  188. package/dist/editor/page-editor-chrome/overlay/geometry.js.map +1 -1
  189. package/dist/editor/page-editor-chrome/overlay/iframeAccess.d.ts +2 -0
  190. package/dist/editor/page-editor-chrome/overlay/iframeAccess.js +21 -0
  191. package/dist/editor/page-editor-chrome/overlay/iframeAccess.js.map +1 -0
  192. package/dist/editor/page-editor-chrome/useInlineAICompletion.d.ts +7 -0
  193. package/dist/editor/page-editor-chrome/useInlineAICompletion.js +758 -0
  194. package/dist/editor/page-editor-chrome/useInlineAICompletion.js.map +1 -0
  195. package/dist/editor/page-viewer/EditorForm.js +1 -17
  196. package/dist/editor/page-viewer/EditorForm.js.map +1 -1
  197. package/dist/editor/page-viewer/MiniMap.d.ts +2 -2
  198. package/dist/editor/page-viewer/MiniMap.js +364 -176
  199. package/dist/editor/page-viewer/MiniMap.js.map +1 -1
  200. package/dist/editor/page-viewer/PageViewer.js +13 -40
  201. package/dist/editor/page-viewer/PageViewer.js.map +1 -1
  202. package/dist/editor/page-viewer/PageViewerFrame.d.ts +5 -0
  203. package/dist/editor/page-viewer/PageViewerFrame.js +1509 -1527
  204. package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
  205. package/dist/editor/page-viewer/pageModelSkeletonBuilder.d.ts +3 -0
  206. package/dist/editor/page-viewer/pageModelSkeletonBuilder.js +796 -0
  207. package/dist/editor/page-viewer/pageModelSkeletonBuilder.js.map +1 -0
  208. package/dist/editor/page-viewer/pageViewContext.d.ts +0 -32
  209. package/dist/editor/page-viewer/pageViewContext.js +6 -37
  210. package/dist/editor/page-viewer/pageViewContext.js.map +1 -1
  211. package/dist/editor/reviews/Comment.d.ts +1 -2
  212. package/dist/editor/reviews/Comment.js +4 -9
  213. package/dist/editor/reviews/Comment.js.map +1 -1
  214. package/dist/editor/reviews/CommentEditor.js +1 -1
  215. package/dist/editor/reviews/CommentEditor.js.map +1 -1
  216. package/dist/editor/reviews/CommentPopover.js +9 -68
  217. package/dist/editor/reviews/CommentPopover.js.map +1 -1
  218. package/dist/editor/reviews/CommentView.js +4 -24
  219. package/dist/editor/reviews/CommentView.js.map +1 -1
  220. package/dist/editor/reviews/Comments.d.ts +2 -0
  221. package/dist/editor/reviews/Comments.js +30 -29
  222. package/dist/editor/reviews/Comments.js.map +1 -1
  223. package/dist/editor/reviews/FeedbackCard.d.ts +2 -4
  224. package/dist/editor/reviews/FeedbackCard.js +5 -5
  225. package/dist/editor/reviews/FeedbackCard.js.map +1 -1
  226. package/dist/editor/reviews/SuggestedEdit.js +6 -4
  227. package/dist/editor/reviews/SuggestedEdit.js.map +1 -1
  228. package/dist/editor/reviews/SuggestionDisplayPopover.js +2 -3
  229. package/dist/editor/reviews/SuggestionDisplayPopover.js.map +1 -1
  230. package/dist/editor/reviews/commentAi.js +27 -96
  231. package/dist/editor/reviews/commentAi.js.map +1 -1
  232. package/dist/editor/reviews/feedbackSelection.js +4 -32
  233. package/dist/editor/reviews/feedbackSelection.js.map +1 -1
  234. package/dist/editor/services/agentService.d.ts +0 -15
  235. package/dist/editor/services/agentService.js +1 -11
  236. package/dist/editor/services/agentService.js.map +1 -1
  237. package/dist/editor/services/contentService.d.ts +1 -0
  238. package/dist/editor/services/contentService.js.map +1 -1
  239. package/dist/editor/services/reviewsService.d.ts +2 -2
  240. package/dist/editor/services/reviewsService.js.map +1 -1
  241. package/dist/editor/settings/SettingsView.js +2 -2
  242. package/dist/editor/settings/SettingsView.js.map +1 -1
  243. package/dist/editor/settings/panels/ProjectTemplatesPanel.js +1 -1
  244. package/dist/editor/settings/panels/ProjectTemplatesPanel.js.map +1 -1
  245. package/dist/editor/settings/panels/ProvidersPanel.js +3 -2
  246. package/dist/editor/settings/panels/ProvidersPanel.js.map +1 -1
  247. package/dist/editor/sidebar/MorePanelsButton.js +1 -1
  248. package/dist/editor/sidebar/MorePanelsButton.js.map +1 -1
  249. package/dist/editor/sidebar/Workbox.js +1 -1
  250. package/dist/editor/sidebar/Workbox.js.map +1 -1
  251. package/dist/editor/ui/IconSelectorDialog.js +1 -1
  252. package/dist/editor/ui/IconSelectorDialog.js.map +1 -1
  253. package/dist/editor/ui/SimpleIconButton.d.ts +2 -2
  254. package/dist/editor/ui/SimpleIconButton.js +1 -1
  255. package/dist/editor/ui/SimpleIconButton.js.map +1 -1
  256. package/dist/editor/utils.d.ts +17 -1
  257. package/dist/editor/utils.js +143 -0
  258. package/dist/editor/utils.js.map +1 -1
  259. package/dist/editor/version-diff/versionDiffTargets.d.ts +8 -3
  260. package/dist/editor/version-diff/versionDiffTargets.js +94 -37
  261. package/dist/editor/version-diff/versionDiffTargets.js.map +1 -1
  262. package/dist/editor/views/MediaFolderEditView.js +1 -1
  263. package/dist/editor/views/MediaFolderEditView.js.map +1 -1
  264. package/dist/revision.d.ts +2 -2
  265. package/dist/revision.js +2 -2
  266. package/dist/splash-screen/DialogWrappers.js +2 -2
  267. package/dist/splash-screen/DialogWrappers.js.map +1 -1
  268. package/dist/splash-screen/ModernSplashScreen.js +3 -11
  269. package/dist/splash-screen/ModernSplashScreen.js.map +1 -1
  270. package/dist/splash-screen/NewPage.js +5 -7
  271. package/dist/splash-screen/NewPage.js.map +1 -1
  272. package/dist/splash-screen/OpenPage.js +3 -5
  273. package/dist/splash-screen/OpenPage.js.map +1 -1
  274. package/dist/splash-screen/RecentPages.js +3 -3
  275. package/dist/splash-screen/RecentPages.js.map +1 -1
  276. package/package.json +1 -2
  277. package/styles.css +0 -49
  278. package/dist/editor/ai/terminal/components/AgentEditHistoryButton.d.ts +0 -5
  279. package/dist/editor/ai/terminal/components/AgentEditHistoryButton.js +0 -12
  280. package/dist/editor/ai/terminal/components/AgentEditHistoryButton.js.map +0 -1
  281. package/dist/editor/bridge/BridgeClient.d.ts +0 -80
  282. package/dist/editor/bridge/BridgeClient.js +0 -417
  283. package/dist/editor/bridge/BridgeClient.js.map +0 -1
  284. package/dist/editor/field-types/useFormFieldCaretPresence.d.ts +0 -13
  285. package/dist/editor/field-types/useFormFieldCaretPresence.js +0 -92
  286. package/dist/editor/field-types/useFormFieldCaretPresence.js.map +0 -1
  287. package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.d.ts +0 -6
  288. package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.js +0 -123
  289. package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.js.map +0 -1
  290. package/dist/editor/page-editor-chrome/useBridgeInlineEditing.d.ts +0 -26
  291. package/dist/editor/page-editor-chrome/useBridgeInlineEditing.js +0 -222
  292. package/dist/editor/page-editor-chrome/useBridgeInlineEditing.js.map +0 -1
  293. package/dist/editor/page-viewer/bridgeFieldPatch.d.ts +0 -20
  294. package/dist/editor/page-viewer/bridgeFieldPatch.js +0 -33
  295. package/dist/editor/page-viewer/bridgeFieldPatch.js.map +0 -1
  296. package/dist/editor/reviews/commentTransientSelection.d.ts +0 -23
  297. package/dist/editor/reviews/commentTransientSelection.js +0 -7
  298. package/dist/editor/reviews/commentTransientSelection.js.map +0 -1
  299. package/dist/editor/reviews/feedbackOrdering.d.ts +0 -5
  300. package/dist/editor/reviews/feedbackOrdering.js +0 -27
  301. package/dist/editor/reviews/feedbackOrdering.js.map +0 -1
  302. package/dist/editor/reviews/suggestedEditState.d.ts +0 -12
  303. package/dist/editor/reviews/suggestedEditState.js +0 -90
  304. package/dist/editor/reviews/suggestedEditState.js.map +0 -1
  305. package/dist/editor/reviews/suggestionDisplayValue.d.ts +0 -43
  306. package/dist/editor/reviews/suggestionDisplayValue.js +0 -93
  307. package/dist/editor/reviews/suggestionDisplayValue.js.map +0 -1
@@ -17,6 +17,60 @@ function SvgIcon({ svg, size, className, }) {
17
17
  return (_jsx("span", { className: cn("inline-flex items-center justify-center [&>svg]:block [&>svg]:h-full [&>svg]:w-full", className), style: { width: size, height: size }, dangerouslySetInnerHTML: { __html: sanitizedSvg } }));
18
18
  }
19
19
  const HIGHLIGHT_DURATION_MS = 2000;
20
+ const EDITOR_FORM_SLIDER_SELECTOR = '[data-testid="editor-form-slider"]';
21
+ const EDITOR_FORM_HIDDEN_ATTRIBUTE = "aria-hidden";
22
+ const CLOSE_PANE_LABEL = "Close pane";
23
+ function waitForDelay(delayMs) {
24
+ return new Promise((resolve) => {
25
+ window.setTimeout(resolve, delayMs);
26
+ });
27
+ }
28
+ function getEditorFormSlider(elements = []) {
29
+ for (const element of elements) {
30
+ const slider = element.closest(EDITOR_FORM_SLIDER_SELECTOR);
31
+ if (slider) {
32
+ return slider;
33
+ }
34
+ }
35
+ return document.querySelector(EDITOR_FORM_SLIDER_SELECTOR);
36
+ }
37
+ function isEditorFormSliderHidden(slider) {
38
+ return slider?.getAttribute(EDITOR_FORM_HIDDEN_ATTRIBUTE) === "true";
39
+ }
40
+ async function waitForEditorFormSliderOpen(slider, timeoutMs = 1000) {
41
+ const startedAt = Date.now();
42
+ while (Date.now() - startedAt < timeoutMs) {
43
+ if (!isEditorFormSliderHidden(slider ?? getEditorFormSlider())) {
44
+ return;
45
+ }
46
+ await waitForDelay(50);
47
+ }
48
+ }
49
+ async function waitForResolvedElements(resolveElements, selector, timeoutMs = 1000) {
50
+ const startedAt = Date.now();
51
+ while (Date.now() - startedAt < timeoutMs) {
52
+ const elements = resolveElements(selector);
53
+ if (elements.length > 0) {
54
+ return elements;
55
+ }
56
+ await waitForDelay(50);
57
+ }
58
+ return resolveElements(selector);
59
+ }
60
+ // Wait until at least one element for the selector is actually VISIBLE (not just
61
+ // present). After a reveal/animation a target can be in the DOM but not yet laid
62
+ // out, which would otherwise cause highlightElement to skip it.
63
+ async function waitForVisibleElements(selector, timeoutMs = 1000) {
64
+ const startedAt = Date.now();
65
+ while (Date.now() - startedAt < timeoutMs) {
66
+ const elements = getVisibleElementsForSelector(selector);
67
+ if (elements.length > 0) {
68
+ return elements;
69
+ }
70
+ await waitForDelay(50);
71
+ }
72
+ return getVisibleElementsForSelector(selector);
73
+ }
20
74
  const manualMarkdownComponents = {
21
75
  h1: ({ children }) => (_jsx("h1", { className: "text-neutral-grey-100 mt-4 mb-0 text-xl font-bold", children: children })),
22
76
  h2: ({ children }) => (_jsx("h2", { className: "text-neutral-grey-100 mt-3 mb-0 text-lg font-semibold", children: children })),
@@ -52,7 +106,15 @@ export function parseUiSelectors(uiSelectors) {
52
106
  let beforeAction;
53
107
  let afterAction;
54
108
  let availabilitySelector;
109
+ let selectorOverride;
110
+ let tab;
111
+ let closeMode;
55
112
  for (const segment of segments) {
113
+ if (segment.startsWith("close=")) {
114
+ const value = segment.substring("close=".length).trim();
115
+ closeMode = value === "auto" ? "auto" : "click";
116
+ continue;
117
+ }
56
118
  if (segment.startsWith("beforeAction=")) {
57
119
  beforeAction = segment.substring("beforeAction=".length).trim();
58
120
  continue;
@@ -67,6 +129,14 @@ export function parseUiSelectors(uiSelectors) {
67
129
  .trim();
68
130
  continue;
69
131
  }
132
+ if (segment.startsWith("selector=")) {
133
+ selectorOverride = segment.substring("selector=".length).trim();
134
+ continue;
135
+ }
136
+ if (segment.startsWith("tab=")) {
137
+ tab = segment.substring("tab=".length).trim();
138
+ continue;
139
+ }
70
140
  if (!notFoundMessage) {
71
141
  notFoundMessage = segment;
72
142
  }
@@ -80,14 +150,16 @@ export function parseUiSelectors(uiSelectors) {
80
150
  : undefined;
81
151
  const parsed = {
82
152
  name,
83
- selector: isSidebarOnly ? "" : `@${name}`, // Empty selector for sidebar-only
153
+ selector: isSidebarOnly ? "" : selectorOverride || `@${name}`,
84
154
  availabilitySelector,
155
+ tab,
85
156
  description,
86
157
  notFoundMessage: notFoundMessage || undefined,
87
158
  location: isSidebarOnly ? sidebarId : undefined, // Use actual sidebar ID (without -sidebar suffix) for sidebar-only
88
159
  isSidebarOnly,
89
160
  beforeAction,
90
161
  afterAction,
162
+ closeMode,
91
163
  };
92
164
  // Primary key remains the selector name
93
165
  map.set(name, parsed);
@@ -99,8 +171,7 @@ function parseSelectorToken(selectorToken) {
99
171
  if (!selectorToken.startsWith("@"))
100
172
  return { selector: selectorToken };
101
173
  const raw = selectorToken.slice(1);
102
- // Preserve iframe: selectors as unavailable selectors. Page DOM inspection now
103
- // goes through the editing bridge instead of same-origin iframe probing.
174
+ // Preserve iframe: selectors (handled specially by expandSelector/highlightElement)
104
175
  if (raw.startsWith("iframe:"))
105
176
  return { selector: selectorToken };
106
177
  // Check for sidebar-only syntax: @sidebar-id-sidebar (e.g., @reviews-sidebar)
@@ -136,6 +207,7 @@ export function expandSelector(selectorShorthand) {
136
207
  return selector;
137
208
  }
138
209
  if (selector.startsWith("iframe:")) {
210
+ // Iframe selector: @iframe:selector → iframe:selector (handled by GuidanceOverlay)
139
211
  return selector;
140
212
  }
141
213
  // Default: data-testid selector: @name → [data-testid="name"]
@@ -144,10 +216,55 @@ export function expandSelector(selectorShorthand) {
144
216
  function getElementsForSelector(selector) {
145
217
  const cssSelector = expandSelector(selector);
146
218
  if (cssSelector.startsWith("iframe:")) {
147
- return [];
219
+ const iframeSelector = cssSelector.substring(7);
220
+ const iframe = document.querySelector("iframe.page-iframe");
221
+ if (!iframe?.contentDocument) {
222
+ return [];
223
+ }
224
+ return Array.from(iframe.contentDocument.querySelectorAll(iframeSelector));
148
225
  }
149
226
  return Array.from(document.querySelectorAll(cssSelector));
150
227
  }
228
+ // Determine whether an element is genuinely visible to the user, not merely
229
+ // present in the DOM. A target sitting inside a collapsed panel, a hidden
230
+ // sidebar (aria-hidden), or with `display:none` / `visibility:hidden` / zero
231
+ // size counts as NOT visible.
232
+ function isElementVisible(element) {
233
+ // Treat anything inside an explicitly aria-hidden container (e.g. a collapsed
234
+ // editor form slider) as not visible.
235
+ if (element.closest('[aria-hidden="true"]')) {
236
+ return false;
237
+ }
238
+ const candidate = element;
239
+ if (typeof candidate.checkVisibility === "function") {
240
+ if (!candidate.checkVisibility({
241
+ checkOpacity: true,
242
+ checkVisibilityCSS: true,
243
+ })) {
244
+ return false;
245
+ }
246
+ }
247
+ else {
248
+ // Fallback for environments without Element.checkVisibility (e.g. jsdom).
249
+ const style = window.getComputedStyle(element);
250
+ if (style.display === "none" ||
251
+ style.visibility === "hidden" ||
252
+ style.visibility === "collapse") {
253
+ return false;
254
+ }
255
+ // position:fixed elements have a null offsetParent but can still be visible.
256
+ if (element.offsetParent === null && style.position !== "fixed") {
257
+ return false;
258
+ }
259
+ }
260
+ // Reject zero-area elements (e.g. a width:0 collapsed panel).
261
+ const rect = element.getBoundingClientRect();
262
+ return rect.width > 0 && rect.height > 0;
263
+ }
264
+ // Return only the elements matching a selector that are currently visible.
265
+ function getVisibleElementsForSelector(selector) {
266
+ return getElementsForSelector(selector).filter(isElementVisible);
267
+ }
151
268
  function shouldSkipHighlightScroll(element) {
152
269
  const rect = element.getBoundingClientRect();
153
270
  const computedStyle = window.getComputedStyle(element);
@@ -185,6 +302,32 @@ async function waitForScrollToFinish(element) {
185
302
  previousRect = currentRect;
186
303
  }
187
304
  }
305
+ // Wait until an element's box (position and size) stops changing. This avoids
306
+ // drawing the highlight overlay mid-animation (e.g. while a sidebar panel is
307
+ // still expanding from its collapsed width).
308
+ async function waitForStableRect(element, timeoutMs = 1000) {
309
+ let previousRect = element.getBoundingClientRect();
310
+ let stableFrames = 0;
311
+ const startedAt = Date.now();
312
+ while (Date.now() - startedAt < timeoutMs) {
313
+ await waitForNextFrame();
314
+ const currentRect = element.getBoundingClientRect();
315
+ const changed = Math.abs(currentRect.width - previousRect.width) > 0.5 ||
316
+ Math.abs(currentRect.height - previousRect.height) > 0.5 ||
317
+ Math.abs(currentRect.top - previousRect.top) > 0.5 ||
318
+ Math.abs(currentRect.left - previousRect.left) > 0.5;
319
+ if (changed) {
320
+ stableFrames = 0;
321
+ }
322
+ else {
323
+ stableFrames += 1;
324
+ if (stableFrames >= 2) {
325
+ return;
326
+ }
327
+ }
328
+ previousRect = currentRect;
329
+ }
330
+ }
188
331
  async function scrollElementForHighlight(element) {
189
332
  if (shouldSkipHighlightScroll(element)) {
190
333
  return;
@@ -199,21 +342,57 @@ async function scrollElementForHighlight(element) {
199
342
  // Highlight an element temporarily
200
343
  export async function highlightElement(selector, duration = HIGHLIGHT_DURATION_MS) {
201
344
  const cssSelector = expandSelector(selector);
202
- const elements = getElementsForSelector(selector);
345
+ // Only ever highlight elements that are actually visible. A target inside a
346
+ // collapsed panel or hidden sidebar must not receive a stray overlay.
347
+ const elements = getElementsForSelector(selector).filter(isElementVisible);
203
348
  if (elements.length === 0)
204
349
  return;
350
+ if (cssSelector.startsWith("iframe:")) {
351
+ const iframe = document.querySelector("iframe.page-iframe");
352
+ const iframeRect = iframe?.getBoundingClientRect();
353
+ if (elements[0]) {
354
+ await scrollElementForHighlight(elements[0]);
355
+ await waitForStableRect(elements[0]);
356
+ }
357
+ elements.forEach((element) => {
358
+ const elementRect = element.getBoundingClientRect();
359
+ showHighlightOverlay(elementRect.left + (iframeRect?.left ?? 0), elementRect.top + (iframeRect?.top ?? 0), elementRect.width, elementRect.height, duration);
360
+ });
361
+ return;
362
+ }
205
363
  if (elements[0]) {
206
364
  await scrollElementForHighlight(elements[0]);
365
+ await waitForStableRect(elements[0]);
207
366
  }
208
367
  elements.forEach((element) => {
209
368
  const rect = element.getBoundingClientRect();
210
369
  showHighlightOverlay(rect.left, rect.top, rect.width, rect.height, duration);
211
370
  });
212
371
  }
213
- // Check if an element is currently available in the DOM
214
- function isElementAvailable(selector) {
372
+ // Check if an element is currently present in the DOM (regardless of visibility)
373
+ function isElementPresent(selector) {
215
374
  return getElementsForSelector(selector).length > 0;
216
375
  }
376
+ // Check if an element matching the selector is currently visible to the user
377
+ function isElementVisibleBySelector(selector) {
378
+ return getVisibleElementsForSelector(selector).length > 0;
379
+ }
380
+ export function deriveSelectorState(params) {
381
+ if (!params.isAnchorReachable) {
382
+ return "disabled";
383
+ }
384
+ // Sidebar-only selectors have no element to "see"; opening the sidebar is the action.
385
+ if (params.isSidebarOnly) {
386
+ return "show-action";
387
+ }
388
+ if (params.isTargetVisible) {
389
+ return "show";
390
+ }
391
+ if (params.hasRevealPath) {
392
+ return "show-action";
393
+ }
394
+ return "disabled";
395
+ }
217
396
  // Create a temporary highlight overlay
218
397
  function showHighlightOverlay(x, y, width, height, duration) {
219
398
  const padding = 4;
@@ -265,59 +444,187 @@ function showHighlightOverlay(x, y, width, height, duration) {
265
444
  overlay.remove();
266
445
  }, duration);
267
446
  }
447
+ let activeRevealController = null;
448
+ let revealControllerSeq = 0;
449
+ function registerActiveReveal(controller) {
450
+ const previous = activeRevealController;
451
+ activeRevealController = controller;
452
+ if (previous && previous.id !== controller.id) {
453
+ previous.close();
454
+ }
455
+ }
456
+ function clearActiveReveal(id) {
457
+ if (activeRevealController?.id === id) {
458
+ activeRevealController = null;
459
+ }
460
+ }
461
+ // Close the More-panels flyout if it is currently open (inverse of open-more-sidebars).
462
+ function closeMorePanelsIfOpen() {
463
+ if (!isElementPresent("@more-sidebars-panel"))
464
+ return;
465
+ const trigger = document.querySelector('[data-testid="more-sidebars-button"]');
466
+ trigger?.click();
467
+ }
268
468
  // Button component for "Show me" functionality with availability detection
269
469
  function SelectorButton({ selectorDef, keyProp, }) {
270
470
  const editContext = useEditContext();
271
471
  const manualActions = editContext?.configuration.editor.manualActions;
272
- const availabilitySelector = selectorDef.availabilitySelector || selectorDef.selector;
273
- // For sidebar-only selectors, we don't need to check for an element
274
- const isSidebarOnly = selectorDef.isSidebarOnly;
275
- // Initialize to true for sidebar-only, false otherwise to avoid hydration mismatch
276
- // (document.querySelector doesn't exist during SSR)
277
- const [isAvailable, setIsAvailable] = useState(isSidebarOnly ? true : false);
278
- // Can open sidebar if: sidebar-only selector
279
- const canAutoOpenSidebar = Boolean(isSidebarOnly && editContext?.openSidebar && selectorDef.location);
472
+ const isSidebarOnly = !!selectorDef.isSidebarOnly;
473
+ const targetSelector = selectorDef.selector;
474
+ // Anchor = explicit availabilitySelector only. It gates the disabled state.
475
+ const anchorSelector = selectorDef.availabilitySelector;
476
+ const hasAvailabilitySelector = Boolean(anchorSelector);
477
+ const closeMode = selectorDef.closeMode ?? "click";
478
+ // Keep a fresh reference to editContext for use inside reveal/restore closures.
479
+ const editContextRef = useRef(editContext);
480
+ editContextRef.current = editContext;
280
481
  const hasBeforeAction = Boolean(selectorDef.beforeAction &&
281
482
  manualActions?.[selectorDef.beforeAction] &&
282
483
  editContext);
283
- const isActionable = isSidebarOnly
284
- ? canAutoOpenSidebar || hasBeforeAction
285
- : isAvailable || canAutoOpenSidebar || hasBeforeAction;
286
- // Monitor for element availability changes (skip for sidebar-only selectors)
484
+ // A sidebar-only selector is reachable only when the current workspace
485
+ // supports sidebars and offers this specific sidebar (both are workspace-scoped).
486
+ const canAutoOpenSidebar = Boolean(isSidebarOnly &&
487
+ selectorDef.location &&
488
+ editContext?.openSidebar &&
489
+ editContext.workspace?.supportsSidebars &&
490
+ editContext.availableSidebars?.some((s) => s.id === selectorDef.location));
491
+ // Presence/visibility probes, kept up to date by the effect below.
492
+ // The anchor gates "is this relevant in the current context", so it checks
493
+ // presence (it may itself be a currently-collapsed container). The target
494
+ // checks visibility to distinguish "show" from "show-action".
495
+ const [isTargetPresent, setIsTargetPresent] = useState(false);
496
+ const [isTargetVisible, setIsTargetVisible] = useState(false);
497
+ const [isAnchorPresent, setIsAnchorPresent] = useState(false);
498
+ // True while THIS button has revealed a container (State 3 active -> green).
499
+ const [isActiveReveal, setIsActiveReveal] = useState(false);
500
+ const controllerIdRef = useRef(0);
501
+ const revealRef = useRef(null);
502
+ const isAnchorReachable = hasAvailabilitySelector
503
+ ? isAnchorPresent
504
+ : isSidebarOnly
505
+ ? canAutoOpenSidebar
506
+ : isTargetPresent || hasBeforeAction;
507
+ const hasRevealPath = isSidebarOnly || hasBeforeAction || canAutoOpenSidebar || isTargetPresent;
508
+ const state = deriveSelectorState({
509
+ isSidebarOnly,
510
+ isAnchorReachable,
511
+ isTargetVisible,
512
+ hasRevealPath,
513
+ });
514
+ const isDisabled = state === "disabled";
515
+ // Reset active (green) state WITHOUT running the undo steps. Used when the
516
+ // revealed container was closed by some other means.
517
+ const resetActiveState = useCallback(() => {
518
+ clearActiveReveal(controllerIdRef.current);
519
+ revealRef.current = null;
520
+ setIsActiveReveal(false);
521
+ }, []);
522
+ // Run the undo steps and reset. Used for explicit close (2nd click, auto
523
+ // timer, or being superseded by another reveal via mutual exclusion).
524
+ const runRestore = useCallback(() => {
525
+ const reveal = revealRef.current;
526
+ if (reveal) {
527
+ try {
528
+ reveal.restore();
529
+ }
530
+ catch {
531
+ // ignore restore failures
532
+ }
533
+ }
534
+ clearActiveReveal(reveal?.id ?? controllerIdRef.current);
535
+ revealRef.current = null;
536
+ setIsActiveReveal(false);
537
+ }, []);
538
+ const runRestoreRef = useRef(runRestore);
539
+ runRestoreRef.current = runRestore;
540
+ // Keep the presence/visibility probes fresh.
287
541
  useEffect(() => {
288
- // Sidebar-only selectors are always "available" if openSidebar exists
289
- if (isSidebarOnly) {
290
- setIsAvailable(true);
291
- return;
542
+ const check = () => {
543
+ setIsTargetPresent(targetSelector ? isElementPresent(targetSelector) : false);
544
+ setIsTargetVisible(targetSelector ? isElementVisibleBySelector(targetSelector) : false);
545
+ setIsAnchorPresent(anchorSelector ? isElementPresent(anchorSelector) : false);
546
+ };
547
+ check();
548
+ const attributeFilter = [
549
+ "data-testid",
550
+ "class",
551
+ "id",
552
+ "style",
553
+ "hidden",
554
+ "aria-hidden",
555
+ ];
556
+ const observer = new MutationObserver(check);
557
+ observer.observe(document.body, {
558
+ childList: true,
559
+ subtree: true,
560
+ attributes: true,
561
+ attributeFilter,
562
+ });
563
+ let iframeObserver = null;
564
+ const iframe = document.querySelector("iframe.page-iframe");
565
+ if (iframe?.contentDocument?.body) {
566
+ iframeObserver = new MutationObserver(check);
567
+ iframeObserver.observe(iframe.contentDocument.body, {
568
+ childList: true,
569
+ subtree: true,
570
+ attributes: true,
571
+ attributeFilter,
572
+ });
292
573
  }
293
- // Initial check
294
- const initialAvailable = isElementAvailable(availabilitySelector);
295
- setIsAvailable(initialAvailable);
296
- // Set up MutationObserver to watch for DOM changes
297
- const checkAvailability = () => {
298
- const available = isElementAvailable(availabilitySelector);
299
- setIsAvailable(available);
574
+ const intervalId = setInterval(check, 1000);
575
+ return () => {
576
+ observer.disconnect();
577
+ iframeObserver?.disconnect();
578
+ clearInterval(intervalId);
300
579
  };
301
- // Watch the main document for changes
302
- const observer = new MutationObserver(checkAvailability);
580
+ }, [targetSelector, anchorSelector]);
581
+ // While active, detect if the revealed container was closed externally and
582
+ // reset the button's active (green) state accordingly.
583
+ useEffect(() => {
584
+ if (!isActiveReveal)
585
+ return;
586
+ const check = () => {
587
+ const reveal = revealRef.current;
588
+ if (!reveal || !reveal.isStillOpen()) {
589
+ resetActiveState();
590
+ }
591
+ };
592
+ const observer = new MutationObserver(check);
303
593
  observer.observe(document.body, {
304
594
  childList: true,
305
595
  subtree: true,
306
596
  attributes: true,
307
- attributeFilter: ["data-testid", "class", "id"],
597
+ attributeFilter: [
598
+ EDITOR_FORM_HIDDEN_ATTRIBUTE,
599
+ "class",
600
+ "style",
601
+ "data-testid",
602
+ ],
308
603
  });
309
- // Also poll periodically as a fallback for async UI updates.
310
- const intervalId = setInterval(checkAvailability, 1000);
604
+ const intervalId = setInterval(check, 500);
311
605
  return () => {
312
606
  observer.disconnect();
313
607
  clearInterval(intervalId);
314
608
  };
315
- }, [availabilitySelector, isSidebarOnly]);
316
- const tooltipText = isActionable
317
- ? selectorDef.description
318
- : selectorDef.notFoundMessage || selectorDef.description;
319
- return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { "aria-label": "Show me", onClick: async () => {
320
- if (!isActionable)
609
+ }, [isActiveReveal, resetActiveState]);
610
+ // Clear the global active controller if this button unmounts while active.
611
+ useEffect(() => {
612
+ return () => {
613
+ clearActiveReveal(controllerIdRef.current);
614
+ };
615
+ }, []);
616
+ const tooltipText = isActiveReveal
617
+ ? CLOSE_PANE_LABEL
618
+ : isDisabled
619
+ ? selectorDef.notFoundMessage || selectorDef.description
620
+ : selectorDef.description;
621
+ return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { "aria-label": isActiveReveal ? CLOSE_PANE_LABEL : "Show me", onClick: async () => {
622
+ // Second click while active -> restore (close=click behaviour).
623
+ if (isActiveReveal) {
624
+ runRestore();
625
+ return;
626
+ }
627
+ if (isDisabled)
321
628
  return;
322
629
  const runId = globalThis.crypto?.randomUUID?.() ??
323
630
  `manual-${Date.now()}-${Math.random().toString(36).slice(2)}`;
@@ -337,34 +644,126 @@ function SelectorButton({ selectorDef, keyProp, }) {
337
644
  };
338
645
  await action(actionProps);
339
646
  };
340
- // If this selector is sidebar-only, open the sidebar before highlighting.
341
- // For sidebar-only selectors, location is the sidebar ID (without -sidebar suffix)
342
- if (selectorDef.isSidebarOnly &&
647
+ // Undo steps captured as we reveal, plus predicates telling whether
648
+ // the revealed container is still open.
649
+ const undoSteps = [];
650
+ const openPredicates = [];
651
+ // 1. Sidebar-only: open the sidebar.
652
+ if (isSidebarOnly &&
343
653
  editContext?.openSidebar &&
344
654
  selectorDef.location) {
345
655
  const sidebarId = selectorDef.location;
346
- const isSidebarAlreadyOpen = !!editContext.openSidebars?.includes(sidebarId);
347
- if (!isSidebarAlreadyOpen) {
656
+ const wasOpen = !!editContext.openSidebars?.includes(sidebarId);
657
+ if (!wasOpen) {
348
658
  editContext.openSidebar(sidebarId);
349
- // Give the sidebar a moment to render before querying/highlighting.
659
+ undoSteps.push(() => editContextRef.current?.toggleSidebar?.(sidebarId, {
660
+ forceClose: true,
661
+ }));
662
+ // Give the sidebar a moment to render before querying.
350
663
  await new Promise((resolve) => setTimeout(resolve, 150));
351
664
  }
665
+ openPredicates.push(() => !!editContextRef.current?.openSidebars?.includes(sidebarId));
666
+ }
667
+ const availabilityElements = anchorSelector
668
+ ? resolveElements(anchorSelector)
669
+ : [];
670
+ const relevantElements = !isSidebarOnly
671
+ ? [...resolveElements(), ...availabilityElements]
672
+ : availabilityElements;
673
+ const formSlider = getEditorFormSlider(relevantElements);
674
+ const shouldOpenEditorForm = !isSidebarOnly &&
675
+ !!formSlider &&
676
+ isEditorFormSliderHidden(formSlider);
677
+ if (selectorDef.tab) {
678
+ editContext?.setActiveEditorTab(selectorDef.tab);
679
+ }
680
+ // 2. Editor form slider.
681
+ if (shouldOpenEditorForm && editContext) {
682
+ const slotId = editContext.getActiveSlotId();
683
+ editContext.setEditorFormHiddenForSlot(slotId, false);
684
+ undoSteps.push(() => editContextRef.current?.setEditorFormHiddenForSlot(slotId, true));
685
+ openPredicates.push(() => !isEditorFormSliderHidden(getEditorFormSlider()));
686
+ await waitForEditorFormSliderOpen(formSlider);
687
+ }
688
+ else if (selectorDef.tab) {
689
+ await waitForNextFrame();
352
690
  }
353
- const resolvedElements = !isSidebarOnly ? resolveElements() : [];
354
- await runManualAction(selectorDef.beforeAction, resolvedElements);
355
- // For sidebar-only selectors, we just open the sidebar (done above)
356
- // For regular selectors, also highlight the element
357
- if (!isSidebarOnly && selectorDef.selector) {
358
- await highlightElement(selectorDef.selector, HIGHLIGHT_DURATION_MS);
691
+ // 3. beforeAction (may open the More-panels flyout, reveal fields, etc.).
692
+ const resolvedElements = !isSidebarOnly
693
+ ? await waitForResolvedElements(resolveElements, selectorDef.selector)
694
+ : [];
695
+ const actionElements = resolvedElements.length > 0
696
+ ? resolvedElements
697
+ : availabilityElements;
698
+ const morePanelsWasOpen = isElementPresent("@more-sidebars-panel");
699
+ await runManualAction(selectorDef.beforeAction, actionElements);
700
+ if (selectorDef.beforeAction === "open-more-sidebars") {
701
+ const morePanelsNowOpen = isElementPresent("@more-sidebars-panel");
702
+ if (!morePanelsWasOpen && morePanelsNowOpen) {
703
+ undoSteps.push(() => closeMorePanelsIfOpen());
704
+ openPredicates.push(() => isElementPresent("@more-sidebars-panel"));
705
+ }
359
706
  }
707
+ // afterAction is the declared inverse for custom reveals (e.g. field actions).
360
708
  if (selectorDef.afterAction) {
361
- window.setTimeout(() => {
362
- void runManualAction(selectorDef.afterAction, !isSidebarOnly ? resolveElements() : []);
363
- }, HIGHLIGHT_DURATION_MS);
709
+ undoSteps.push(() => {
710
+ void runManualAction(selectorDef.afterAction, !isSidebarOnly ? resolveElements() : availabilityElements);
711
+ });
712
+ }
713
+ // Highlight the target. For sidebar-only selectors there is no inner
714
+ // target, so we highlight the opened sidebar panel itself. Wait for
715
+ // it to become visible first, since a just-revealed element may be
716
+ // present but not yet laid out (highlightElement skips invisible ones).
717
+ const highlightSelector = isSidebarOnly
718
+ ? selectorDef.location
719
+ ? `@sidebar-panel-${selectorDef.location}`
720
+ : ""
721
+ : selectorDef.selector;
722
+ if (highlightSelector) {
723
+ const highlightTargets = await waitForVisibleElements(highlightSelector, 1500);
724
+ if (highlightTargets.length > 0) {
725
+ await highlightElement(highlightSelector, HIGHLIGHT_DURATION_MS);
726
+ }
727
+ }
728
+ // If we opened/undid anything, this was a State-3 reveal: keep the
729
+ // button active (green) and register it for mutual exclusion.
730
+ if (undoSteps.length > 0) {
731
+ const id = ++revealControllerSeq;
732
+ controllerIdRef.current = id;
733
+ revealRef.current = {
734
+ id,
735
+ restore: () => {
736
+ for (let i = undoSteps.length - 1; i >= 0; i -= 1) {
737
+ try {
738
+ undoSteps[i]?.();
739
+ }
740
+ catch {
741
+ // ignore individual undo failures
742
+ }
743
+ }
744
+ },
745
+ isStillOpen: () => openPredicates.length === 0
746
+ ? true
747
+ : openPredicates.some((predicate) => predicate()),
748
+ };
749
+ registerActiveReveal({
750
+ id,
751
+ close: () => runRestoreRef.current(),
752
+ });
753
+ setIsActiveReveal(true);
754
+ if (closeMode === "auto") {
755
+ window.setTimeout(() => {
756
+ if (controllerIdRef.current === id) {
757
+ runRestoreRef.current();
758
+ }
759
+ }, HIGHLIGHT_DURATION_MS);
760
+ }
364
761
  }
365
- }, disabled: !isActionable, className: cn("inline-flex h-5 w-5 items-center justify-center rounded border transition-colors", isActionable
366
- ? "border-feedback-blue bg-feedback-blue-light text-feedback-blue hover:bg-feedback-blue-light cursor-pointer"
367
- : "border-border-default bg-neutral-grey-5 text-neutral-grey-50 cursor-not-allowed"), children: [_jsx(LocateFixed, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }), _jsx("span", { className: "sr-only", children: "Show me" })] }, keyProp) }), _jsx(TooltipContent, { children: tooltipText })] }));
762
+ }, disabled: isDisabled && !isActiveReveal, className: cn("inline-flex h-5 w-5 items-center justify-center rounded border transition-colors", isActiveReveal
763
+ ? "border-feedback-green bg-feedback-green-light text-feedback-green hover:bg-feedback-green-light cursor-pointer"
764
+ : !isDisabled
765
+ ? "border-feedback-blue bg-feedback-blue-light text-feedback-blue hover:bg-feedback-blue-light cursor-pointer"
766
+ : "border-border-default bg-neutral-grey-5 text-neutral-grey-50 cursor-not-allowed"), children: [_jsx(LocateFixed, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }), _jsx("span", { className: "sr-only", children: "Show me" })] }, keyProp) }), _jsx(TooltipContent, { children: tooltipText })] }));
368
767
  }
369
768
  // Render markdown content with clickable selectors
370
769
  // Supports both {{selectorName}} syntax (looks up in uiSelectors) and legacy @selector syntax
@@ -407,10 +806,10 @@ function renderLineWithSelectors(text, uiSelectors, manualLinkTargets, onManualL
407
806
  function renderInlineSelectorsAndFormatting(text, uiSelectors) {
408
807
  const parts = [];
409
808
  let lastIndex = 0;
410
- // Combined regex for {{namedSelector}}, @selector, and **bold**.
411
- // @selector can include -sidebar suffix for sidebar-only selectors.
412
- // The matcher keeps legacy @iframe: tokens parseable, but they are unavailable.
413
- // Also matches optional parentheses around selectors: ({{name}}) or (@selector).
809
+ // Combined regex for {{namedSelector}}, @selector, and **bold**
810
+ // Note: @selector can include -sidebar suffix for sidebar-only selectors
811
+ // Also supports @iframe:selector syntax (iframe: is special and allowed)
812
+ // Now also matches optional parentheses around selectors: ({{name}}) or (@selector)
414
813
  const regex = /(\()?(\{\{([\w\-]+)\}\})|(\()?(@(?:iframe:[\w\-\.#\[\]=]*[\w\-#\[\]=]|[\w\-\.#\[\]=]*[\w\-#\[\]=]))|(\*\*(.+?)\*\*)/g;
415
814
  let match;
416
815
  while ((match = regex.exec(text)) !== null) {