@parhelia/core 0.1.12601 → 0.1.12602

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 (584) hide show
  1. package/dist/agents-view/AgentCard.d.ts +4 -6
  2. package/dist/agents-view/AgentCard.js +24 -143
  3. package/dist/agents-view/AgentCard.js.map +1 -1
  4. package/dist/agents-view/AgentsInbox.d.ts +1 -1
  5. package/dist/agents-view/AgentsInbox.js +92 -7
  6. package/dist/agents-view/AgentsInbox.js.map +1 -1
  7. package/dist/agents-view/AgentsTitlebar.js +2 -3
  8. package/dist/agents-view/AgentsTitlebar.js.map +1 -1
  9. package/dist/agents-view/AgentsView.d.ts +7 -6
  10. package/dist/agents-view/AgentsView.js +99 -191
  11. package/dist/agents-view/AgentsView.js.map +1 -1
  12. package/dist/agents-view/AgentsWorkspaceView.d.ts +6 -2
  13. package/dist/agents-view/AgentsWorkspaceView.js +113 -266
  14. package/dist/agents-view/AgentsWorkspaceView.js.map +1 -1
  15. package/dist/agents-view/ProfileAgentsGroup.d.ts +1 -2
  16. package/dist/agents-view/ProfileAgentsGroup.js +3 -4
  17. package/dist/agents-view/ProfileAgentsGroup.js.map +1 -1
  18. package/dist/components/ActionButton.d.ts +1 -1
  19. package/dist/components/ActionButton.js.map +1 -1
  20. package/dist/components/FilterInput.d.ts +1 -1
  21. package/dist/components/FilterInput.js +1 -1
  22. package/dist/components/FilterInput.js.map +1 -1
  23. package/dist/components/ui/LanguageSelector.js +4 -2
  24. package/dist/components/ui/LanguageSelector.js.map +1 -1
  25. package/dist/components/ui/PlaceholderInput.js +3 -3
  26. package/dist/components/ui/PlaceholderInput.js.map +1 -1
  27. package/dist/components/ui/PlaceholderInputTypes.js +1 -1
  28. package/dist/components/ui/PlaceholderInputTypes.js.map +1 -1
  29. package/dist/components/ui/alert-dialog.d.ts +1 -1
  30. package/dist/components/ui/alert-dialog.js +10 -6
  31. package/dist/components/ui/alert-dialog.js.map +1 -1
  32. package/dist/components/ui/button.d.ts +4 -4
  33. package/dist/components/ui/button.js +1 -4
  34. package/dist/components/ui/button.js.map +1 -1
  35. package/dist/components/ui/context-menu.d.ts +1 -1
  36. package/dist/components/ui/context-menu.js +4 -12
  37. package/dist/components/ui/context-menu.js.map +1 -1
  38. package/dist/components/ui/copy-button.d.ts +1 -2
  39. package/dist/components/ui/copy-button.js +2 -2
  40. package/dist/components/ui/copy-button.js.map +1 -1
  41. package/dist/components/ui/dialog.d.ts +1 -1
  42. package/dist/components/ui/dialog.js +126 -21
  43. package/dist/components/ui/dialog.js.map +1 -1
  44. package/dist/components/ui/input.d.ts +1 -1
  45. package/dist/components/ui/input.js +3 -5
  46. package/dist/components/ui/input.js.map +1 -1
  47. package/dist/components/ui/paste-button.d.ts +1 -2
  48. package/dist/components/ui/paste-button.js +2 -2
  49. package/dist/components/ui/paste-button.js.map +1 -1
  50. package/dist/components/ui/popover.js +9 -1
  51. package/dist/components/ui/popover.js.map +1 -1
  52. package/dist/components/ui/select.js +1 -1
  53. package/dist/components/ui/select.js.map +1 -1
  54. package/dist/components/ui/styled-dialog-title.js +1 -1
  55. package/dist/components/ui/styled-dialog-title.js.map +1 -1
  56. package/dist/components/ui/tabs.d.ts +1 -1
  57. package/dist/components/ui/tabs.js +11 -4
  58. package/dist/components/ui/tabs.js.map +1 -1
  59. package/dist/config/config.d.ts +2 -4
  60. package/dist/config/config.js +70 -250
  61. package/dist/config/config.js.map +1 -1
  62. package/dist/config/types/workspace.d.ts +0 -6
  63. package/dist/config/types.d.ts +12 -63
  64. package/dist/config/types.js.map +1 -1
  65. package/dist/editor/ComponentInfo.d.ts +4 -0
  66. package/dist/editor/ComponentInfo.js +41 -0
  67. package/dist/editor/ComponentInfo.js.map +1 -0
  68. package/dist/editor/ConfirmationDialog.js +4 -20
  69. package/dist/editor/ConfirmationDialog.js.map +1 -1
  70. package/dist/editor/ContentTree.d.ts +1 -2
  71. package/dist/editor/ContentTree.js +32 -93
  72. package/dist/editor/ContentTree.js.map +1 -1
  73. package/dist/editor/Editor.js +22 -87
  74. package/dist/editor/Editor.js.map +1 -1
  75. package/dist/editor/FieldHistory.js +36 -84
  76. package/dist/editor/FieldHistory.js.map +1 -1
  77. package/dist/editor/FieldListField.js +9 -21
  78. package/dist/editor/FieldListField.js.map +1 -1
  79. package/dist/editor/FieldListFieldWithFallbacks.js +2 -23
  80. package/dist/editor/FieldListFieldWithFallbacks.js.map +1 -1
  81. package/dist/editor/GlobalMenuBar.js +2 -29
  82. package/dist/editor/GlobalMenuBar.js.map +1 -1
  83. package/dist/editor/ImageEditor.js +2 -5
  84. package/dist/editor/ImageEditor.js.map +1 -1
  85. package/dist/editor/ItemInfo.js +1 -36
  86. package/dist/editor/ItemInfo.js.map +1 -1
  87. package/dist/editor/LinkEditorDialog.js +0 -3
  88. package/dist/editor/LinkEditorDialog.js.map +1 -1
  89. package/dist/editor/MainLayout.d.ts +2 -0
  90. package/dist/editor/MainLayout.js +8 -65
  91. package/dist/editor/MainLayout.js.map +1 -1
  92. package/dist/editor/MigrationsView.js +5 -29
  93. package/dist/editor/MigrationsView.js.map +1 -1
  94. package/dist/editor/MobileLayout.js +12 -37
  95. package/dist/editor/MobileLayout.js.map +1 -1
  96. package/dist/editor/PictureCropper.js +45 -54
  97. package/dist/editor/PictureCropper.js.map +1 -1
  98. package/dist/editor/PictureEditor.js +15 -17
  99. package/dist/editor/PictureEditor.js.map +1 -1
  100. package/dist/editor/QuickItemSwitcher.js +63 -37
  101. package/dist/editor/QuickItemSwitcher.js.map +1 -1
  102. package/dist/editor/SetupWizard.js +12 -52
  103. package/dist/editor/SetupWizard.js.map +1 -1
  104. package/dist/editor/Titlebar.js +2 -7
  105. package/dist/editor/Titlebar.js.map +1 -1
  106. package/dist/editor/ai/AgentCostDisplay.d.ts +0 -1
  107. package/dist/editor/ai/AgentCostDisplay.js +1 -1
  108. package/dist/editor/ai/AgentCostDisplay.js.map +1 -1
  109. package/dist/editor/ai/AgentDocumentList.js +14 -32
  110. package/dist/editor/ai/AgentDocumentList.js.map +1 -1
  111. package/dist/editor/ai/AgentGreeting.js +5 -6
  112. package/dist/editor/ai/AgentGreeting.js.map +1 -1
  113. package/dist/editor/ai/AgentProfileSelector.js +1 -2
  114. package/dist/editor/ai/AgentProfileSelector.js.map +1 -1
  115. package/dist/editor/ai/AgentStatusBadge.d.ts +5 -0
  116. package/dist/editor/ai/AgentStatusBadge.js +65 -67
  117. package/dist/editor/ai/AgentStatusBadge.js.map +1 -1
  118. package/dist/editor/ai/AgentTerminal.d.ts +2 -14
  119. package/dist/editor/ai/AgentTerminal.js +572 -2508
  120. package/dist/editor/ai/AgentTerminal.js.map +1 -1
  121. package/dist/editor/ai/AgentTerminalStatusBar.d.ts +4 -9
  122. package/dist/editor/ai/AgentTerminalStatusBar.js +56 -481
  123. package/dist/editor/ai/AgentTerminalStatusBar.js.map +1 -1
  124. package/dist/editor/ai/Agents.js +113 -161
  125. package/dist/editor/ai/Agents.js.map +1 -1
  126. package/dist/editor/ai/AiResponseMessage.d.ts +1 -10
  127. package/dist/editor/ai/AiResponseMessage.js +26 -267
  128. package/dist/editor/ai/AiResponseMessage.js.map +1 -1
  129. package/dist/editor/ai/ContextInfoBar.d.ts +3 -2
  130. package/dist/editor/ai/ContextInfoBar.js +7 -64
  131. package/dist/editor/ai/ContextInfoBar.js.map +1 -1
  132. package/dist/editor/ai/EditOperationsPanel.d.ts +2 -3
  133. package/dist/editor/ai/EditOperationsPanel.js +78 -21
  134. package/dist/editor/ai/EditOperationsPanel.js.map +1 -1
  135. package/dist/editor/ai/GuidanceOverlay.js +11 -17
  136. package/dist/editor/ai/GuidanceOverlay.js.map +1 -1
  137. package/dist/editor/ai/HelpTerminal.d.ts +5 -0
  138. package/dist/editor/ai/HelpTerminal.js +166 -0
  139. package/dist/editor/ai/HelpTerminal.js.map +1 -0
  140. package/dist/editor/ai/InlineAiDialog.d.ts +1 -1
  141. package/dist/editor/ai/InlineAiDialog.js +192 -514
  142. package/dist/editor/ai/InlineAiDialog.js.map +1 -1
  143. package/dist/editor/ai/InlineAiTrigger.js +12 -115
  144. package/dist/editor/ai/InlineAiTrigger.js.map +1 -1
  145. package/dist/editor/ai/MediaImage.js +8 -40
  146. package/dist/editor/ai/MediaImage.js.map +1 -1
  147. package/dist/editor/ai/SpawnedAgentsPanel.js +12 -10
  148. package/dist/editor/ai/SpawnedAgentsPanel.js.map +1 -1
  149. package/dist/editor/ai/ToolCallDisplay.d.ts +2 -22
  150. package/dist/editor/ai/ToolCallDisplay.js +202 -614
  151. package/dist/editor/ai/ToolCallDisplay.js.map +1 -1
  152. package/dist/editor/ai/dialogs/AgentDialogHandler.d.ts +8 -1
  153. package/dist/editor/ai/dialogs/AgentDialogHandler.js +42 -379
  154. package/dist/editor/ai/dialogs/AgentDialogHandler.js.map +1 -1
  155. package/dist/editor/ai/dialogs/QuestionnaireInline.d.ts +1 -5
  156. package/dist/editor/ai/dialogs/QuestionnaireInline.js +60 -628
  157. package/dist/editor/ai/dialogs/QuestionnaireInline.js.map +1 -1
  158. package/dist/editor/ai/dialogs/agentDialogTypes.d.ts +0 -117
  159. package/dist/editor/ai/dialogs/agentDialogTypes.js +0 -2
  160. package/dist/editor/ai/dialogs/agentDialogTypes.js.map +1 -1
  161. package/dist/editor/ai/types.d.ts +1 -3
  162. package/dist/editor/ai/useAgentStatus.d.ts +1 -2
  163. package/dist/editor/ai/useAgentStatus.js +100 -90
  164. package/dist/editor/ai/useAgentStatus.js.map +1 -1
  165. package/dist/editor/ai/useInlineAiPosition.js +5 -45
  166. package/dist/editor/ai/useInlineAiPosition.js.map +1 -1
  167. package/dist/editor/client/AboutDialog.js +2 -4
  168. package/dist/editor/client/AboutDialog.js.map +1 -1
  169. package/dist/editor/client/EditorShell.d.ts +1 -4
  170. package/dist/editor/client/EditorShell.js +258 -853
  171. package/dist/editor/client/EditorShell.js.map +1 -1
  172. package/dist/editor/client/editContext.d.ts +19 -33
  173. package/dist/editor/client/editContext.js.map +1 -1
  174. package/dist/editor/client/helpers.js +0 -6
  175. package/dist/editor/client/helpers.js.map +1 -1
  176. package/dist/editor/client/hooks/useEditorUrlSync.js +2 -1
  177. package/dist/editor/client/hooks/useEditorUrlSync.js.map +1 -1
  178. package/dist/editor/client/hooks/useEditorWebSocket.d.ts +0 -10
  179. package/dist/editor/client/hooks/useEditorWebSocket.js +14 -209
  180. package/dist/editor/client/hooks/useEditorWebSocket.js.map +1 -1
  181. package/dist/editor/client/hooks/useQuota.d.ts +0 -8
  182. package/dist/editor/client/hooks/useQuota.js.map +1 -1
  183. package/dist/editor/client/hooks/useSocketMessageHandler.js +15 -73
  184. package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
  185. package/dist/editor/client/itemsRepository.js +6 -10
  186. package/dist/editor/client/itemsRepository.js.map +1 -1
  187. package/dist/editor/client/operations.d.ts +3 -6
  188. package/dist/editor/client/operations.js +30 -208
  189. package/dist/editor/client/operations.js.map +1 -1
  190. package/dist/editor/client/pageModelBuilder.js +31 -4
  191. package/dist/editor/client/pageModelBuilder.js.map +1 -1
  192. package/dist/editor/client/ui/DevModeIndicator.js +2 -2
  193. package/dist/editor/client/ui/DevModeIndicator.js.map +1 -1
  194. package/dist/editor/client/ui/EditorChrome.d.ts +6 -0
  195. package/dist/editor/client/ui/EditorChrome.js +72 -55
  196. package/dist/editor/client/ui/EditorChrome.js.map +1 -1
  197. package/dist/editor/client/ui/FullscreenControls.js +3 -5
  198. package/dist/editor/client/ui/FullscreenControls.js.map +1 -1
  199. package/dist/editor/commands/commands.d.ts +1 -11
  200. package/dist/editor/commands/commands.js +1 -12
  201. package/dist/editor/commands/commands.js.map +1 -1
  202. package/dist/editor/commands/componentCommands.js +55 -109
  203. package/dist/editor/commands/componentCommands.js.map +1 -1
  204. package/dist/editor/commands/customCommandConverter.d.ts +1 -8
  205. package/dist/editor/commands/customCommandConverter.js +5 -35
  206. package/dist/editor/commands/customCommandConverter.js.map +1 -1
  207. package/dist/editor/commands/handlers/agentHandler.js +1 -2
  208. package/dist/editor/commands/handlers/agentHandler.js.map +1 -1
  209. package/dist/editor/commands/itemCommands.d.ts +0 -3
  210. package/dist/editor/commands/itemCommands.js +10 -93
  211. package/dist/editor/commands/itemCommands.js.map +1 -1
  212. package/dist/editor/commands/undo.d.ts +15 -9
  213. package/dist/editor/commands/undo.js +0 -24
  214. package/dist/editor/commands/undo.js.map +1 -1
  215. package/dist/editor/context-menu/InsertMenu.js +39 -83
  216. package/dist/editor/context-menu/InsertMenu.js.map +1 -1
  217. package/dist/editor/field-types/MultiLineText.js +1 -1
  218. package/dist/editor/field-types/MultiLineText.js.map +1 -1
  219. package/dist/editor/field-types/RawEditor.js +1 -1
  220. package/dist/editor/field-types/ReactQuill.d.ts +125 -0
  221. package/dist/editor/field-types/ReactQuill.js +385 -0
  222. package/dist/editor/field-types/ReactQuill.js.map +1 -0
  223. package/dist/editor/field-types/RichTextEditor.js +5 -13
  224. package/dist/editor/field-types/RichTextEditor.js.map +1 -1
  225. package/dist/editor/field-types/RichTextEditorComponent.js +3 -37
  226. package/dist/editor/field-types/RichTextEditorComponent.js.map +1 -1
  227. package/dist/editor/field-types/SingleLineText.js +1 -1
  228. package/dist/editor/field-types/TreeListEditor.js +2 -3
  229. package/dist/editor/field-types/TreeListEditor.js.map +1 -1
  230. package/dist/editor/field-types/richtext/components/ReactSlate.css +5 -23
  231. package/dist/editor/field-types/richtext/components/ReactSlate.d.ts +0 -2
  232. package/dist/editor/field-types/richtext/components/ReactSlate.js +4 -28
  233. package/dist/editor/field-types/richtext/components/ReactSlate.js.map +1 -1
  234. package/dist/editor/field-types/richtext/components/ToolbarButton.js +2 -4
  235. package/dist/editor/field-types/richtext/components/ToolbarButton.js.map +1 -1
  236. package/dist/editor/field-types/richtext/contextMenuFactory.d.ts +0 -13
  237. package/dist/editor/field-types/richtext/contextMenuFactory.js +24 -181
  238. package/dist/editor/field-types/richtext/contextMenuFactory.js.map +1 -1
  239. package/dist/editor/field-types/richtext/types.d.ts +0 -2
  240. package/dist/editor/field-types/richtext/types.js.map +1 -1
  241. package/dist/editor/field-types/richtext/utils/plugins.js +0 -4
  242. package/dist/editor/field-types/richtext/utils/plugins.js.map +1 -1
  243. package/dist/editor/field-types/textContextMenuFactory.js +2 -3
  244. package/dist/editor/field-types/textContextMenuFactory.js.map +1 -1
  245. package/dist/editor/media-selector/AiImageSearchPrompt.js +2 -4
  246. package/dist/editor/media-selector/AiImageSearchPrompt.js.map +1 -1
  247. package/dist/editor/media-selector/MediaFolderBrowser.js +1 -1
  248. package/dist/editor/media-selector/MediaFolderBrowser.js.map +1 -1
  249. package/dist/editor/media-selector/MediaSelector.js +1 -7
  250. package/dist/editor/media-selector/MediaSelector.js.map +1 -1
  251. package/dist/editor/media-selector/TreeSelector.js +35 -40
  252. package/dist/editor/media-selector/TreeSelector.js.map +1 -1
  253. package/dist/editor/menubar/ActiveUsers.js +1 -1
  254. package/dist/editor/menubar/ActiveUsers.js.map +1 -1
  255. package/dist/editor/menubar/GenericToolbar.js +2 -4
  256. package/dist/editor/menubar/GenericToolbar.js.map +1 -1
  257. package/dist/editor/menubar/ItemLanguageVersion.js +2 -2
  258. package/dist/editor/menubar/ItemLanguageVersion.js.map +1 -1
  259. package/dist/editor/menubar/PageSelector.js +147 -26
  260. package/dist/editor/menubar/PageSelector.js.map +1 -1
  261. package/dist/editor/menubar/Separator.js +1 -1
  262. package/dist/editor/menubar/VersionSelector.js +4 -2
  263. package/dist/editor/menubar/VersionSelector.js.map +1 -1
  264. package/dist/editor/menubar/WorkflowButton.js +12 -39
  265. package/dist/editor/menubar/WorkflowButton.js.map +1 -1
  266. package/dist/editor/menubar/toolbar-sections/CustomCommandsToolbar.js +38 -16
  267. package/dist/editor/menubar/toolbar-sections/CustomCommandsToolbar.js.map +1 -1
  268. package/dist/editor/menubar/toolbar-sections/EditControls.js +3 -3
  269. package/dist/editor/menubar/toolbar-sections/EditControls.js.map +1 -1
  270. package/dist/editor/menubar/toolbar-sections/HelpButton.js +0 -1
  271. package/dist/editor/menubar/toolbar-sections/HelpButton.js.map +1 -1
  272. package/dist/editor/menubar/toolbar-sections/ManualBrowser.d.ts +10 -6
  273. package/dist/editor/menubar/toolbar-sections/ManualBrowser.js +220 -597
  274. package/dist/editor/menubar/toolbar-sections/ManualBrowser.js.map +1 -1
  275. package/dist/editor/menubar/toolbar-sections/UtilityControls.js +2 -13
  276. package/dist/editor/menubar/toolbar-sections/UtilityControls.js.map +1 -1
  277. package/dist/editor/page-editor-chrome/CommentHighlighting.js +1 -42
  278. package/dist/editor/page-editor-chrome/CommentHighlighting.js.map +1 -1
  279. package/dist/editor/page-editor-chrome/FrameMenu.js +1 -1
  280. package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
  281. package/dist/editor/page-editor-chrome/InlineEditor.js +48 -97
  282. package/dist/editor/page-editor-chrome/InlineEditor.js.map +1 -1
  283. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +17 -38
  284. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
  285. package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +11 -17
  286. package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
  287. package/dist/editor/page-editor-chrome/useInlineAICompletion.js +301 -301
  288. package/dist/editor/page-editor-chrome/useInlineAICompletion.js.map +1 -1
  289. package/dist/editor/page-viewer/DeviceToolbar.js +1 -1
  290. package/dist/editor/page-viewer/DeviceToolbar.js.map +1 -1
  291. package/dist/editor/page-viewer/EditorForm.js +11 -69
  292. package/dist/editor/page-viewer/EditorForm.js.map +1 -1
  293. package/dist/editor/page-viewer/MiniMap.d.ts +4 -2
  294. package/dist/editor/page-viewer/MiniMap.js +28 -91
  295. package/dist/editor/page-viewer/MiniMap.js.map +1 -1
  296. package/dist/editor/page-viewer/PageViewer.d.ts +1 -3
  297. package/dist/editor/page-viewer/PageViewer.js +19 -92
  298. package/dist/editor/page-viewer/PageViewer.js.map +1 -1
  299. package/dist/editor/page-viewer/PageViewerFrame.d.ts +1 -2
  300. package/dist/editor/page-viewer/PageViewerFrame.js +115 -348
  301. package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
  302. package/dist/editor/page-viewer/pageModelSkeletonBuilder.js +49 -114
  303. package/dist/editor/page-viewer/pageModelSkeletonBuilder.js.map +1 -1
  304. package/dist/editor/page-viewer/pageViewContext.d.ts +0 -1
  305. package/dist/editor/page-viewer/pageViewContext.js +14 -51
  306. package/dist/editor/page-viewer/pageViewContext.js.map +1 -1
  307. package/dist/editor/pageModel.d.ts +1 -14
  308. package/dist/editor/reviews/Comment.d.ts +1 -2
  309. package/dist/editor/reviews/Comment.js +15 -92
  310. package/dist/editor/reviews/Comment.js.map +1 -1
  311. package/dist/editor/reviews/CommentDisplayPopover.js +5 -70
  312. package/dist/editor/reviews/CommentDisplayPopover.js.map +1 -1
  313. package/dist/editor/reviews/CommentView.d.ts +1 -3
  314. package/dist/editor/reviews/CommentView.js +6 -26
  315. package/dist/editor/reviews/CommentView.js.map +1 -1
  316. package/dist/editor/reviews/Comments.js +75 -140
  317. package/dist/editor/reviews/Comments.js.map +1 -1
  318. package/dist/editor/reviews/CreateReviewDialog.js +177 -281
  319. package/dist/editor/reviews/CreateReviewDialog.js.map +1 -1
  320. package/dist/editor/reviews/DecisionsMatrix.js +25 -96
  321. package/dist/editor/reviews/DecisionsMatrix.js.map +1 -1
  322. package/dist/editor/reviews/DiffView.js +14 -7
  323. package/dist/editor/reviews/DiffView.js.map +1 -1
  324. package/dist/editor/reviews/EditReviewSettingsDialog.js +4 -6
  325. package/dist/editor/reviews/EditReviewSettingsDialog.js.map +1 -1
  326. package/dist/editor/reviews/MultiReviewManager.js +3 -25
  327. package/dist/editor/reviews/MultiReviewManager.js.map +1 -1
  328. package/dist/editor/reviews/PagesPanel.js +15 -31
  329. package/dist/editor/reviews/PagesPanel.js.map +1 -1
  330. package/dist/editor/reviews/PreviewInfo.js +4 -1
  331. package/dist/editor/reviews/PreviewInfo.js.map +1 -1
  332. package/dist/editor/reviews/ReviewCard.js +7 -13
  333. package/dist/editor/reviews/ReviewCard.js.map +1 -1
  334. package/dist/editor/reviews/ReviewDetail.js +2 -3
  335. package/dist/editor/reviews/ReviewDetail.js.map +1 -1
  336. package/dist/editor/reviews/ReviewsList.js +3 -7
  337. package/dist/editor/reviews/ReviewsList.js.map +1 -1
  338. package/dist/editor/reviews/SuggestedEdit.js +3 -34
  339. package/dist/editor/reviews/SuggestedEdit.js.map +1 -1
  340. package/dist/editor/reviews/SuggestionDisplayPopover.js +5 -31
  341. package/dist/editor/reviews/SuggestionDisplayPopover.js.map +1 -1
  342. package/dist/editor/reviews/commentAi.js +6 -25
  343. package/dist/editor/reviews/commentAi.js.map +1 -1
  344. package/dist/editor/reviews/reviewCommands.js +1 -4
  345. package/dist/editor/reviews/reviewCommands.js.map +1 -1
  346. package/dist/editor/reviews/useMultiReview.js +2 -2
  347. package/dist/editor/reviews/useMultiReview.js.map +1 -1
  348. package/dist/editor/reviews/useReviews.d.ts +3 -4
  349. package/dist/editor/reviews/useReviews.js +32 -21
  350. package/dist/editor/reviews/useReviews.js.map +1 -1
  351. package/dist/editor/services/agentService.d.ts +5 -240
  352. package/dist/editor/services/agentService.js +39 -299
  353. package/dist/editor/services/agentService.js.map +1 -1
  354. package/dist/editor/services/aiService.d.ts +1 -57
  355. package/dist/editor/services/aiService.js +6 -79
  356. package/dist/editor/services/aiService.js.map +1 -1
  357. package/dist/editor/services/contentService.d.ts +3 -6
  358. package/dist/editor/services/contentService.js +12 -13
  359. package/dist/editor/services/contentService.js.map +1 -1
  360. package/dist/editor/services/editService.d.ts +1 -52
  361. package/dist/editor/services/editService.js +2 -94
  362. package/dist/editor/services/editService.js.map +1 -1
  363. package/dist/editor/services/indexService.js +1 -1
  364. package/dist/editor/services/indexService.js.map +1 -1
  365. package/dist/editor/services/reviewsService.d.ts +6 -3
  366. package/dist/editor/services/reviewsService.js +11 -2
  367. package/dist/editor/services/reviewsService.js.map +1 -1
  368. package/dist/editor/services/serviceHelper.d.ts +1 -2
  369. package/dist/editor/services/serviceHelper.js +20 -112
  370. package/dist/editor/services/serviceHelper.js.map +1 -1
  371. package/dist/editor/services/systemService.d.ts +1 -2
  372. package/dist/editor/services/systemService.js +0 -3
  373. package/dist/editor/services/systemService.js.map +1 -1
  374. package/dist/editor/services-server/api.d.ts +2 -1
  375. package/dist/editor/services-server/api.js +6 -11
  376. package/dist/editor/services-server/api.js.map +1 -1
  377. package/dist/editor/services-server/graphQL.d.ts +29 -0
  378. package/dist/editor/services-server/graphQL.js +53 -0
  379. package/dist/editor/services-server/graphQL.js.map +1 -0
  380. package/dist/editor/settings/About.js +3 -317
  381. package/dist/editor/settings/About.js.map +1 -1
  382. package/dist/editor/settings/AllAgentsPanel.d.ts +5 -0
  383. package/dist/editor/settings/AllAgentsPanel.js +139 -0
  384. package/dist/editor/settings/AllAgentsPanel.js.map +1 -0
  385. package/dist/editor/settings/IndexOverview.js +1 -3
  386. package/dist/editor/settings/IndexOverview.js.map +1 -1
  387. package/dist/editor/settings/LatestFeedback.d.ts +1 -0
  388. package/dist/editor/settings/LatestFeedback.js +136 -0
  389. package/dist/editor/settings/LatestFeedback.js.map +1 -0
  390. package/dist/editor/settings/QuotaInfo.js +4 -210
  391. package/dist/editor/settings/QuotaInfo.js.map +1 -1
  392. package/dist/editor/settings/SettingsView.js +23 -25
  393. package/dist/editor/settings/SettingsView.js.map +1 -1
  394. package/dist/editor/settings/Setup.d.ts +1 -0
  395. package/dist/editor/settings/Setup.js +211 -0
  396. package/dist/editor/settings/Setup.js.map +1 -0
  397. package/dist/editor/settings/Status.js +6 -7
  398. package/dist/editor/settings/Status.js.map +1 -1
  399. package/dist/editor/settings/index/useIndexStatus.js +22 -23
  400. package/dist/editor/settings/index/useIndexStatus.js.map +1 -1
  401. package/dist/editor/settings/panels/AgentsPanel.d.ts +4 -0
  402. package/dist/editor/settings/panels/AgentsPanel.js +121 -95
  403. package/dist/editor/settings/panels/AgentsPanel.js.map +1 -1
  404. package/dist/editor/settings/panels/DatabasePanel.d.ts +6 -0
  405. package/dist/editor/settings/panels/DatabasePanel.js +50 -0
  406. package/dist/editor/settings/panels/DatabasePanel.js.map +1 -0
  407. package/dist/editor/settings/panels/ModelsPanel.js +108 -324
  408. package/dist/editor/settings/panels/ModelsPanel.js.map +1 -1
  409. package/dist/editor/settings/panels/ProvidersPanel.d.ts +1 -1
  410. package/dist/editor/settings/panels/ProvidersPanel.js +59 -86
  411. package/dist/editor/settings/panels/ProvidersPanel.js.map +1 -1
  412. package/dist/editor/settings/panels/SearchConfigPanel.js +6 -67
  413. package/dist/editor/settings/panels/SearchConfigPanel.js.map +1 -1
  414. package/dist/editor/settings/panels/StatusPanel.js +2 -7
  415. package/dist/editor/settings/panels/StatusPanel.js.map +1 -1
  416. package/dist/editor/settings/panels/index.d.ts +2 -3
  417. package/dist/editor/settings/panels/index.js +2 -3
  418. package/dist/editor/settings/panels/index.js.map +1 -1
  419. package/dist/editor/settings/setup-steps/AiSetupStep/EmbeddingsModelSection.d.ts +2 -0
  420. package/dist/editor/settings/setup-steps/AiSetupStep/EmbeddingsModelSection.js +195 -0
  421. package/dist/editor/settings/setup-steps/AiSetupStep/EmbeddingsModelSection.js.map +1 -0
  422. package/dist/editor/settings/setup-steps/AiSetupStep/index.d.ts +2 -0
  423. package/dist/editor/settings/setup-steps/AiSetupStep/index.js +21 -0
  424. package/dist/editor/settings/setup-steps/AiSetupStep/index.js.map +1 -0
  425. package/dist/editor/settings/setup-steps/AiSetupStep/provider/ProviderSection.d.ts +1 -0
  426. package/dist/editor/settings/setup-steps/AiSetupStep/provider/ProviderSection.js +233 -0
  427. package/dist/editor/settings/setup-steps/AiSetupStep/provider/ProviderSection.js.map +1 -0
  428. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersList.d.ts +15 -0
  429. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersList.js +14 -0
  430. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersList.js.map +1 -0
  431. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.d.ts +1 -0
  432. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.js +94 -0
  433. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.js.map +1 -0
  434. package/dist/editor/settings/setup-steps/AiSetupStep/types.d.ts +1 -0
  435. package/dist/editor/settings/setup-steps/AiSetupStep/types.js +2 -0
  436. package/dist/editor/settings/setup-steps/AiSetupStep/types.js.map +1 -0
  437. package/dist/editor/settings/setup-steps/AiSetupStep/utils.d.ts +5 -0
  438. package/dist/editor/settings/setup-steps/AiSetupStep/utils.js +44 -0
  439. package/dist/editor/settings/setup-steps/AiSetupStep/utils.js.map +1 -0
  440. package/dist/editor/settings/setup-steps/IndexSetupStep.d.ts +2 -0
  441. package/dist/editor/settings/setup-steps/IndexSetupStep.js +36 -0
  442. package/dist/editor/settings/setup-steps/IndexSetupStep.js.map +1 -0
  443. package/dist/editor/settings/setup-steps/SettingsSetupStep.d.ts +2 -0
  444. package/dist/editor/settings/setup-steps/SettingsSetupStep.js +111 -0
  445. package/dist/editor/settings/setup-steps/SettingsSetupStep.js.map +1 -0
  446. package/dist/editor/settings/setup-steps/SetupOverview.d.ts +14 -0
  447. package/dist/editor/settings/setup-steps/SetupOverview.js +38 -0
  448. package/dist/editor/settings/setup-steps/SetupOverview.js.map +1 -0
  449. package/dist/editor/settings/status/coreStatusChecks.js +19 -124
  450. package/dist/editor/settings/status/coreStatusChecks.js.map +1 -1
  451. package/dist/editor/settings/status/useStartupChecks.d.ts +1 -3
  452. package/dist/editor/settings/status/useStartupChecks.js +5 -9
  453. package/dist/editor/settings/status/useStartupChecks.js.map +1 -1
  454. package/dist/editor/setup-wizard/steps/CompleteStep.d.ts +1 -2
  455. package/dist/editor/setup-wizard/steps/CompleteStep.js +1 -2
  456. package/dist/editor/setup-wizard/steps/CompleteStep.js.map +1 -1
  457. package/dist/editor/sidebar/ComponentPalette.js +1 -2
  458. package/dist/editor/sidebar/ComponentPalette.js.map +1 -1
  459. package/dist/editor/sidebar/ComponentTree.d.ts +1 -8
  460. package/dist/editor/sidebar/ComponentTree.js +69 -216
  461. package/dist/editor/sidebar/ComponentTree.js.map +1 -1
  462. package/dist/editor/sidebar/Debug.d.ts +1 -0
  463. package/dist/editor/sidebar/Debug.js +70 -0
  464. package/dist/editor/sidebar/Debug.js.map +1 -0
  465. package/dist/editor/sidebar/EditHistory.js +46 -22
  466. package/dist/editor/sidebar/EditHistory.js.map +1 -1
  467. package/dist/editor/sidebar/Favorites.js +8 -4
  468. package/dist/editor/sidebar/Favorites.js.map +1 -1
  469. package/dist/editor/sidebar/GraphQL.d.ts +2 -0
  470. package/dist/editor/sidebar/GraphQL.js +234 -0
  471. package/dist/editor/sidebar/GraphQL.js.map +1 -0
  472. package/dist/editor/sidebar/LeftToolbar.d.ts +1 -0
  473. package/dist/editor/sidebar/LeftToolbar.js +12 -0
  474. package/dist/editor/sidebar/LeftToolbar.js.map +1 -0
  475. package/dist/editor/sidebar/MainContentTree.js +3 -4
  476. package/dist/editor/sidebar/MainContentTree.js.map +1 -1
  477. package/dist/editor/sidebar/NavigationSidebar.d.ts +4 -0
  478. package/dist/editor/sidebar/NavigationSidebar.js +254 -0
  479. package/dist/editor/sidebar/NavigationSidebar.js.map +1 -0
  480. package/dist/editor/sidebar/OperationItem.js +7 -21
  481. package/dist/editor/sidebar/OperationItem.js.map +1 -1
  482. package/dist/editor/sidebar/SidebarPanel.d.ts +1 -3
  483. package/dist/editor/sidebar/SidebarPanel.js +12 -44
  484. package/dist/editor/sidebar/SidebarPanel.js.map +1 -1
  485. package/dist/editor/sidebar/SidebarStack.d.ts +1 -2
  486. package/dist/editor/sidebar/SidebarStack.js +3 -4
  487. package/dist/editor/sidebar/SidebarStack.js.map +1 -1
  488. package/dist/editor/sidebar/Validation.js +12 -24
  489. package/dist/editor/sidebar/Validation.js.map +1 -1
  490. package/dist/editor/sidebar/Workbox.js +3 -53
  491. package/dist/editor/sidebar/Workbox.js.map +1 -1
  492. package/dist/editor/sidebar/WorkspaceRail.d.ts +1 -0
  493. package/dist/editor/sidebar/WorkspaceRail.js +167 -56
  494. package/dist/editor/sidebar/WorkspaceRail.js.map +1 -1
  495. package/dist/editor/tree-indicators/GutterColumns.d.ts +1 -3
  496. package/dist/editor/tree-indicators/GutterColumns.js +5 -26
  497. package/dist/editor/tree-indicators/GutterColumns.js.map +1 -1
  498. package/dist/editor/tree-indicators/GutterContext.d.ts +0 -4
  499. package/dist/editor/tree-indicators/GutterContext.js +0 -23
  500. package/dist/editor/tree-indicators/GutterContext.js.map +1 -1
  501. package/dist/editor/tree-indicators/GutterSelector.d.ts +5 -0
  502. package/dist/editor/tree-indicators/GutterSelector.js +91 -0
  503. package/dist/editor/tree-indicators/GutterSelector.js.map +1 -0
  504. package/dist/editor/tree-indicators/index.d.ts +1 -0
  505. package/dist/editor/tree-indicators/index.js +1 -0
  506. package/dist/editor/tree-indicators/index.js.map +1 -1
  507. package/dist/editor/tree-indicators/types.d.ts +1 -12
  508. package/dist/editor/ui/CopyMoveTargetSelectorDialog.js +1 -1
  509. package/dist/editor/ui/CopyMoveTargetSelectorDialog.js.map +1 -1
  510. package/dist/editor/ui/Icons.js +1 -1
  511. package/dist/editor/ui/Icons.js.map +1 -1
  512. package/dist/editor/ui/ItemNameDialogNew.d.ts +0 -2
  513. package/dist/editor/ui/ItemNameDialogNew.js +17 -33
  514. package/dist/editor/ui/ItemNameDialogNew.js.map +1 -1
  515. package/dist/editor/ui/ItemSearch.js +11 -7
  516. package/dist/editor/ui/ItemSearch.js.map +1 -1
  517. package/dist/editor/ui/SimpleIconButton.js +1 -1
  518. package/dist/editor/ui/SimpleIconButton.js.map +1 -1
  519. package/dist/editor/ui/SimpleTabs.d.ts +0 -1
  520. package/dist/editor/ui/SimpleTabs.js +25 -45
  521. package/dist/editor/ui/SimpleTabs.js.map +1 -1
  522. package/dist/editor/ui/Splitter.d.ts +0 -1
  523. package/dist/editor/ui/Splitter.js +86 -102
  524. package/dist/editor/ui/Splitter.js.map +1 -1
  525. package/dist/editor/ui/TemplateSelectorDialog.js +4 -4
  526. package/dist/editor/ui/TemplateSelectorDialog.js.map +1 -1
  527. package/dist/editor/ui/TreeListSelector.d.ts +1 -6
  528. package/dist/editor/ui/TreeListSelector.js +2 -2
  529. package/dist/editor/ui/TreeListSelector.js.map +1 -1
  530. package/dist/editor/utils/keyboardNavigation.d.ts +20 -6
  531. package/dist/editor/utils/keyboardNavigation.js +140 -48
  532. package/dist/editor/utils/keyboardNavigation.js.map +1 -1
  533. package/dist/editor/utils.js +9 -19
  534. package/dist/editor/utils.js.map +1 -1
  535. package/dist/editor/views/CompareView.d.ts +1 -3
  536. package/dist/editor/views/CompareView.js +5 -7
  537. package/dist/editor/views/CompareView.js.map +1 -1
  538. package/dist/editor/views/EditView.js +1 -1
  539. package/dist/editor/views/EditView.js.map +1 -1
  540. package/dist/editor/views/EditorSlot.js +34 -27
  541. package/dist/editor/views/EditorSlot.js.map +1 -1
  542. package/dist/editor/views/ItemEditor.js +3 -7
  543. package/dist/editor/views/ItemEditor.js.map +1 -1
  544. package/dist/editor/views/MediaFolderEditView.js +1 -1
  545. package/dist/editor/views/MediaFolderEditView.js.map +1 -1
  546. package/dist/editor/views/ParheliaView.js +6 -5
  547. package/dist/editor/views/ParheliaView.js.map +1 -1
  548. package/dist/editor/views/SingleEditView.d.ts +1 -2
  549. package/dist/editor/views/SingleEditView.js +8 -10
  550. package/dist/editor/views/SingleEditView.js.map +1 -1
  551. package/dist/editor/views/editorSlotContext.js +6 -35
  552. package/dist/editor/views/editorSlotContext.js.map +1 -1
  553. package/dist/index.d.ts +2 -16
  554. package/dist/index.js +0 -11
  555. package/dist/index.js.map +1 -1
  556. package/dist/revision.d.ts +2 -2
  557. package/dist/revision.js +2 -2
  558. package/dist/setup/services/setupWizardService.d.ts +14 -48
  559. package/dist/setup/services/setupWizardService.js +17 -52
  560. package/dist/setup/services/setupWizardService.js.map +1 -1
  561. package/dist/setup/wizard/steps/AddModelDialog.js +3 -12
  562. package/dist/setup/wizard/steps/AddModelDialog.js.map +1 -1
  563. package/dist/setup/wizard/steps/ImportModelDialog.js +22 -46
  564. package/dist/setup/wizard/steps/ImportModelDialog.js.map +1 -1
  565. package/dist/splash-screen/ModernSplashScreen.js +32 -112
  566. package/dist/splash-screen/ModernSplashScreen.js.map +1 -1
  567. package/dist/splash-screen/NewPage.js +50 -33
  568. package/dist/splash-screen/NewPage.js.map +1 -1
  569. package/dist/splash-screen/OpenPage.js +6 -2
  570. package/dist/splash-screen/OpenPage.js.map +1 -1
  571. package/dist/splash-screen/ParheliaAssistantChat.js +29 -12
  572. package/dist/splash-screen/ParheliaAssistantChat.js.map +1 -1
  573. package/dist/splash-screen/ParheliaLogo.js +37 -87
  574. package/dist/splash-screen/ParheliaLogo.js.map +1 -1
  575. package/dist/splash-screen/RecentPages.js +3 -3
  576. package/dist/splash-screen/RecentPages.js.map +1 -1
  577. package/dist/tour/Tour.d.ts +1 -2
  578. package/dist/tour/Tour.js +75 -256
  579. package/dist/tour/Tour.js.map +1 -1
  580. package/dist/tour/default-tour.js +96 -222
  581. package/dist/tour/default-tour.js.map +1 -1
  582. package/dist/types.d.ts +29 -70
  583. package/package.json +15 -19
  584. package/styles.css +10 -39
@@ -1,17 +1,15 @@
1
1
  "use client";
2
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import React, { useState, useEffect, useRef, useCallback, useSyncExternalStore, useMemo, startTransition, } from "react";
4
4
  import { toast } from "sonner";
5
- import { EditContextProvider, FieldsEditContextProvider, OperationsContextProvider, useEditContext, } from "./editContext";
5
+ import { EditContextProvider, FieldsEditContextProvider, OperationsContextProvider, } from "./editContext";
6
6
  import { fieldModificationStore } from "./fieldModificationStore";
7
- import { useRouter, useSearchParams, usePathname } from "./navigation";
7
+ import { useRouter, useSearchParams, usePathname } from "next/navigation";
8
8
  import { findComponent, getComponentById } from "../componentTreeHelper";
9
9
  import { getOperationsContext } from "./operations";
10
10
  import { handleErrorResult } from "./helpers";
11
- import { executeFieldAction as executeFieldServerAction, connectSocket, getEditHistory, getRunningOperations, reconnectSession, releaseFieldLocks, validateItems, } from "../services/editService";
11
+ import { executeFieldAction as executeFieldServerAction, connectSocket, getEditHistory, getRunningOperations, releaseFieldLocks, validateItems, } from "../services/editService";
12
12
  import { useEditorWebSocket } from "./hooks/useEditorWebSocket";
13
- import { createEditorSocketDiagnostics, } from "./socketDiagnostics";
14
- import { localStorageService } from "../services/localStorageService";
15
13
  import { useSocketMessageHandler } from "./hooks/useSocketMessageHandler";
16
14
  import "react-json-view-lite/dist/index.css";
17
15
  import { MediaSelector, } from "../media-selector/MediaSelector";
@@ -22,7 +20,6 @@ import { getItemDescriptor } from "../utils";
22
20
  import { EditContextMenu } from "../ContextMenu";
23
21
  import { InlineAiTrigger } from "../ai/InlineAiTrigger";
24
22
  import { FieldEditorPopup } from "../FieldEditorPopup";
25
- import { ConcurrentUserLimitDialog } from "../ConcurrentUserLimitDialog";
26
23
  import { post } from "../services/serviceHelper";
27
24
  import { PageViewerFrame } from "../page-viewer/PageViewerFrame";
28
25
  import { useItemsRepository } from "./itemsRepository";
@@ -36,7 +33,6 @@ import { GuidanceOverlay } from "../ai/GuidanceOverlay";
36
33
  import { AgentDialogHandler } from "../ai/dialogs";
37
34
  import { usePageViewContext, } from "../page-viewer/pageViewContext";
38
35
  import { QuickItemSwitcher } from "../QuickItemSwitcher";
39
- import { useEditorSlotContext, } from "../views/editorSlotContext";
40
36
  import { getComments, getAvailableCommentTags, } from "../services/reviewsService";
41
37
  import { useReviews } from "../reviews/useReviews";
42
38
  import uuid from "react-uuid";
@@ -53,33 +49,7 @@ import { useWorkbox } from "./hooks/useWorkbox";
53
49
  import { useMediaSelector } from "./hooks/useMediaSelector";
54
50
  import { useGlobalEditorKeyDown } from "./hooks/useGlobalEditorKeyDown";
55
51
  import { useStartupChecks } from "../settings/status/index";
56
- import { FeatureGate, LicenseFeatures, LicenseProvider, LicenseOverlay, } from "../../licensing";
57
- function AgentsSlotContextBridge({ slot }) {
58
- const editContext = useEditContext();
59
- const slotContext = useEditorSlotContext({
60
- slotId: slot.slotId,
61
- itemDescriptor: slot.itemDescriptor,
62
- refreshToken: slot.refreshToken,
63
- });
64
- if (!editContext || !slotContext)
65
- return null;
66
- useEffect(() => {
67
- editContext.registerSlotContext(slot.slotId, slotContext);
68
- return () => {
69
- editContext.unregisterSlotContext(slot.slotId);
70
- };
71
- }, [
72
- slot.slotId,
73
- slotContext,
74
- editContext.registerSlotContext,
75
- editContext.unregisterSlotContext,
76
- ]);
77
- return null;
78
- }
79
- function AgentsSlotContextBridgeHost({ slots }) {
80
- return (_jsx(_Fragment, { children: slots.map((slot) => (_jsx(AgentsSlotContextBridge, { slot: slot }, `agents-slot-bridge-${slot.slotId}`))) }));
81
- }
82
- export function EditorShell({ configuration, className, item: loadItemDescriptor, sessionId, userInfo, userPreferences, initialLicenseStatus, initialLicenseStatusLoaded, parheliaSettings, setUserPreferences, children, }) {
52
+ export function EditorShell({ configuration, className, item: loadItemDescriptor, sessionId, userInfo, userPreferences, parheliaSettings, setUserPreferences, children, }) {
83
53
  const router = useRouter();
84
54
  const pathname = usePathname();
85
55
  const searchParams = useSearchParams();
@@ -127,7 +97,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
127
97
  const [historyMode, setHistoryMode] = useState("global");
128
98
  const [showOnlyMyChanges, setShowOnlyMyChanges] = useState(true);
129
99
  const [filterByCurrentLanguage, setFilterByCurrentLanguage] = useState(true);
130
- const [historySearchQuery, setHistorySearchQuery] = useState("");
131
100
  const [recentEdits, setRecentEdits] = useState([]);
132
101
  const addRecentEdit = useCallback((edit) => {
133
102
  setRecentEdits((prevEditedFields) => {
@@ -155,14 +124,14 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
155
124
  if (typeof window !== "undefined")
156
125
  sessionStorage?.setItem("sessionId", sessionId);
157
126
  // Workspace state
158
- // Note: "reviews" is a sidebar, not a workspace. If workspace=reviews, we should
127
+ // Note: "reviews" is a sidebar, not a workspace. If view/workspace=reviews, we should
159
128
  // set workspace to "editor" and open the reviews sidebar instead.
160
129
  // Memoize searchParams reads to avoid triggering Router state updates during render
161
130
  // (Next.js App Router uses startTransition internally for URL changes)
162
- const rawWorkspace = useMemo(() => searchParams.get("workspace"), [searchParams]);
131
+ const rawWorkspace = useMemo(() => searchParams.get("workspace") ?? searchParams.get("view"), [searchParams]);
163
132
  const isReviewsSidebarRequest = rawWorkspace === "reviews";
164
133
  const [workspaceId, setWorkspaceId] = useState(
165
- // If workspace=reviews, use "editor" workspace (reviews is a sidebar, not a workspace)
134
+ // If view=reviews, use "editor" workspace (reviews is a sidebar, not a workspace)
166
135
  isReviewsSidebarRequest
167
136
  ? "editor"
168
137
  : (rawWorkspace ??
@@ -184,7 +153,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
184
153
  else {
185
154
  sidebars = [...(configuration.editor.defaultOpenSidebars ?? [])];
186
155
  }
187
- // If workspace=reviews was requested, ensure reviews sidebar is open
156
+ // If view/workspace=reviews was requested, ensure reviews sidebar is open
188
157
  if (isReviewsSidebarRequest && !sidebars.includes("reviews")) {
189
158
  sidebars.push("reviews");
190
159
  }
@@ -192,11 +161,17 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
192
161
  });
193
162
  // Toolbar pinned sidebars - icons always visible in toolbar (defined early so callbacks can access)
194
163
  const [pinnedSidebars, setPinnedSidebars] = useState(userInfo.preferences?.pinnedSidebars || []);
195
- const pinnedSidebarsRef = useRef(pinnedSidebars);
196
164
  // Locked sidebars - open panels that stay visible when selecting another sidebar
197
165
  const [lockedSidebars, setLockedSidebars] = useState(() => {
166
+ if (typeof window === "undefined") {
167
+ return [];
168
+ }
198
169
  try {
199
- const parsed = localStorageService.getOrSetItem("editor.lockedSidebars", []);
170
+ const stored = window.localStorage.getItem("editor.lockedSidebars");
171
+ if (!stored) {
172
+ return [];
173
+ }
174
+ const parsed = JSON.parse(stored);
200
175
  if (!Array.isArray(parsed) ||
201
176
  !parsed.every((id) => typeof id === "string")) {
202
177
  return [];
@@ -212,9 +187,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
212
187
  useEffect(() => {
213
188
  lockedSidebarsRef.current = lockedSidebars;
214
189
  }, [lockedSidebars]);
215
- useEffect(() => {
216
- pinnedSidebarsRef.current = pinnedSidebars;
217
- }, [pinnedSidebars]);
218
190
  // Filter locked sidebars to only include currently open sidebars
219
191
  useEffect(() => {
220
192
  const openSet = new Set(openSidebars);
@@ -276,11 +248,15 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
276
248
  // Group open sidebars into vertical stacks (each stack shares one left column).
277
249
  const [sidebarStacks, setSidebarStacks] = useState(() => {
278
250
  const defaultStacks = openSidebars.map((id) => [id]);
251
+ if (typeof window === "undefined") {
252
+ return normalizeSidebarStacks(openSidebars, defaultStacks);
253
+ }
279
254
  try {
280
- const parsed = localStorageService.getItem("editor.sidebarStacks");
281
- if (!parsed) {
255
+ const stored = window.localStorage.getItem("editor.sidebarStacks");
256
+ if (!stored) {
282
257
  return normalizeSidebarStacks(openSidebars, defaultStacks);
283
258
  }
259
+ const parsed = JSON.parse(stored);
284
260
  if (!Array.isArray(parsed) ||
285
261
  !parsed.every((x) => Array.isArray(x) && x.every((id) => typeof id === "string"))) {
286
262
  return normalizeSidebarStacks(openSidebars, defaultStacks);
@@ -302,19 +278,28 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
302
278
  }, [openSidebars, normalizeSidebarStacks]);
303
279
  // Persist stacks independently of the URL (user layout preference).
304
280
  useEffect(() => {
281
+ if (typeof window === "undefined")
282
+ return;
305
283
  try {
306
- localStorageService.setItem("editor.sidebarStacks", sidebarStacks);
284
+ window.localStorage.setItem("editor.sidebarStacks", JSON.stringify(sidebarStacks));
307
285
  }
308
286
  catch { }
309
287
  }, [sidebarStacks]);
310
288
  // Persist locked sidebars to localStorage.
311
289
  useEffect(() => {
290
+ if (typeof window === "undefined")
291
+ return;
312
292
  try {
313
- localStorageService.setItem("editor.lockedSidebars", lockedSidebars);
293
+ window.localStorage.setItem("editor.lockedSidebars", JSON.stringify(lockedSidebars));
314
294
  }
315
295
  catch { }
316
296
  }, [lockedSidebars]);
297
+ // Legacy aliases for backwards compatibility
317
298
  const viewName = workspaceId;
299
+ const setViewName = setWorkspaceId;
300
+ const viewNameRef = workspaceIdRef;
301
+ const previousViewName = previousWorkspaceId;
302
+ const setPreviousViewName = setPreviousWorkspaceId;
318
303
  const [compareMode, setCompareModeState] = useState(false);
319
304
  const [componentDesignerComponent, setComponentDesignerComponent] = useState();
320
305
  const [componentDesignerRendering, setComponentDesignerRendering] = useState();
@@ -322,7 +307,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
322
307
  const [ignoreBlur, setIgnoreBlur] = useState(false);
323
308
  const [currentItemDescriptor, setCurrentItemDescriptor] = useState();
324
309
  const currentItemDescriptorRef = useRef(undefined);
325
- const latestGlobalLoadKeyRef = useRef(null);
326
310
  const [editorSlots, setEditorSlots] = useState(() => {
327
311
  // Always start with empty slots - don't persist the number of slots
328
312
  return [];
@@ -342,29 +326,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
342
326
  activeSlotIdRef.current = activeSlotId;
343
327
  }, [activeSlotId]);
344
328
  const [slotContexts, setSlotContexts] = useState(() => new Map());
345
- const promptSessionReconnect = useCallback((reason) => {
346
- const description = reason && reason !== "session-revoked"
347
- ? `${reason}. Click reconnect to continue in this browser.`
348
- : "You were disconnected because this account is active in another browser.";
349
- toast.error("Session disconnected", {
350
- id: "session-revoked",
351
- description,
352
- action: {
353
- label: "Reconnect",
354
- onClick: async () => {
355
- const result = await reconnectSession(sessionId);
356
- if (result.type === "success") {
357
- window.location.reload();
358
- return;
359
- }
360
- toast.error("Reconnect failed", {
361
- description: "Could not claim this browser session. Try again.",
362
- });
363
- },
364
- },
365
- duration: Infinity,
366
- });
367
- }, [sessionId]);
368
329
  // Track previous item ID to detect actual navigation between pages
369
330
  const previousItemIdRef = useRef(undefined);
370
331
  useEffect(() => {
@@ -393,18 +354,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
393
354
  // Ref to track when we're handling a popstate event (browser back/forward)
394
355
  // This prevents the URL sync effect from pushing new history entries during back navigation
395
356
  const isHandlingPopStateRef = useRef(false);
396
- // When switchWorkspace already pushed a URL entry, the follow-up URL sync
397
- // effect should only *replace* that entry (not push a second one).
398
- const switchWorkspacePushedRef = useRef(false);
399
- // Ref to track the last known URL for the popstate handler.
400
- // Uses pathname+search (not full href) so comparisons are consistent with the
401
- // relative URLs produced by the URL sync effect and updateUrl.
402
- const lastUrlRef = useRef(typeof window !== "undefined"
403
- ? `${window.location.pathname}${window.location.search}`
404
- : "");
405
- // The very first URL sync after initial load should replaceState (not pushState)
406
- // so the initial bare URL isn't left as a dead-end history entry.
407
- const isFirstUrlSyncRef = useRef(true);
357
+ // Ref to track the last known URL for the popstate handler
358
+ // This is updated both when the popstate handler runs AND when the URL sync effect pushes a new URL
359
+ // Without this, the popstate handler would have a stale lastUrl value after pushState calls
360
+ const lastUrlRef = useRef(typeof window !== "undefined" ? window.location.href : "");
408
361
  const [inlineEditingFieldElement, setInlineEditingFieldElement] = useState();
409
362
  const [lockedField, setLockedField] = useState();
410
363
  const [itemLanguages, setItemLanguages] = useState([]);
@@ -417,16 +370,26 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
417
370
  const [showSuggestedEditsDiff, setShowSuggestedEditsDiff] = useState(false);
418
371
  const [availableCommentTags, setAvailableCommentTags] = useState([]);
419
372
  const [showComments, setShowComments] = useState(() => {
420
- return localStorageService.getOrSetItem("editor.showComments", true);
373
+ const savedShowComments = typeof window !== "undefined"
374
+ ? localStorage.getItem("editor.showComments")
375
+ : null;
376
+ return savedShowComments ? JSON.parse(savedShowComments) : true;
421
377
  });
422
378
  useEffect(() => {
423
- localStorageService.setItem("editor.showComments", showComments);
379
+ if (typeof window !== "undefined") {
380
+ localStorage.setItem("editor.showComments", JSON.stringify(showComments));
381
+ }
424
382
  }, [showComments]);
425
383
  const [showResolvedComments, setShowResolvedComments] = useState(() => {
426
- return localStorageService.getOrSetItem("editor.showResolvedComments", false);
384
+ const saved = typeof window !== "undefined"
385
+ ? localStorage.getItem("editor.showResolvedComments")
386
+ : null;
387
+ return saved ? JSON.parse(saved) : false;
427
388
  });
428
389
  useEffect(() => {
429
- localStorageService.setItem("editor.showResolvedComments", showResolvedComments);
390
+ if (typeof window !== "undefined") {
391
+ localStorage.setItem("editor.showResolvedComments", JSON.stringify(showResolvedComments));
392
+ }
430
393
  }, [showResolvedComments]);
431
394
  const [selectedComment, setSelectedComment] = useState();
432
395
  const [browseHistory, setBrowseHistory] = useState(() => {
@@ -445,12 +408,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
445
408
  visitedAt: entry.visitedAt,
446
409
  }));
447
410
  });
448
- // Navigation history for browser history (workspace + item combinations)
411
+ // Navigation history for browser history (view + item combinations)
449
412
  const [navigationHistory, setNavigationHistory] = useState(() => {
450
- // Initialize from browse history with the current workspace
413
+ // Initialize from browse history with current view
451
414
  if (!userInfo.browseHistory)
452
415
  return [];
453
416
  const defaultWorkspaceId = searchParams.get("workspace") ??
417
+ searchParams.get("view") ??
454
418
  configuration.editor.defaultWorkspace ??
455
419
  configuration.editor.workspaces?.[0]?.id ??
456
420
  "editor";
@@ -482,43 +446,20 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
482
446
  const [statusMessage, setStatusMessage] = useState("");
483
447
  const [focusFieldComponentId, setFocusFieldComponentId] = useState();
484
448
  const [enableCompletions, setEnableCompletions] = useState(false);
485
- const [showComponentNavigatorDefault, setShowComponentNavigatorDefault] = useState(userPreferences.showComponentNavigator ?? false);
486
- const [slotComponentNavigatorVisibility, setSlotComponentNavigatorVisibility] = useState({});
487
- useEffect(() => {
488
- setSlotComponentNavigatorVisibility((prev) => {
489
- const next = {};
490
- let changed = false;
491
- for (const slot of editorSlots) {
492
- if (Object.prototype.hasOwnProperty.call(prev, slot.slotId)) {
493
- next[slot.slotId] = prev[slot.slotId];
494
- }
495
- else {
496
- next[slot.slotId] = showComponentNavigatorDefault;
497
- changed = true;
498
- }
499
- }
500
- if (Object.keys(prev).length !== editorSlots.length) {
501
- changed = true;
502
- }
503
- return changed ? next : prev;
504
- });
505
- }, [editorSlots, showComponentNavigatorDefault]);
449
+ const [showComponentNavigator, setShowComponentNavigator] = useState(userPreferences.showComponentNavigator ?? false);
506
450
  const [showAgentsPanel, setShowAgentsPanel] = useState(userPreferences.showAgentsPanel ?? false);
507
451
  const [showMinimap, setShowMinimap] = useState(userPreferences.showMinimap ?? true);
508
452
  const [showHelpTerminal, setShowHelpTerminal] = useState(false);
509
453
  const [helpTerminalInitialPrompt, setHelpTerminalInitialPrompt] = useState(undefined);
510
454
  const [helpTerminalProfileName, setHelpTerminalProfileName] = useState(undefined);
511
455
  const [helpTerminalActiveTab, setHelpTerminalActiveTab] = useState(undefined);
512
- const [selectedHelpSectionId, setSelectedHelpSectionId] = useState(null);
513
- const [showAgentsWorkspaceEditor, setShowAgentsWorkspaceEditor] = useState(false);
514
- const [selectedAgentsWorkspaceAgentId, setSelectedAgentsWorkspaceAgentId] = useState(null);
456
+ const [showAgentsWorkspaceEditor, setShowAgentsWorkspaceEditor] = useState(true);
515
457
  const [activeEditorTab, setActiveEditorTab] = useState(null);
516
458
  const [showLayoutComponents, setShowLayoutComponents] = useState(userPreferences.showLayoutComponents ?? false);
517
459
  const { quotaInfo, setQuotaInfo, isQuotaExceeded, getQuotaWarningMessage } = useQuota({
518
460
  showError: ({ summary, details }) => showErrorToast({ summary, details }),
519
461
  });
520
462
  const [webSocketMessages, setWebSocketMessages] = useState([]);
521
- const [socketDiagnostics, setSocketDiagnostics] = useState(() => createEditorSocketDiagnostics(sessionId));
522
463
  const [favorites, setFavorites] = useState([]);
523
464
  // Quick item switcher state
524
465
  const [quickSwitcherVisible, setQuickSwitcherVisible] = useState(false);
@@ -536,12 +477,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
536
477
  if (!startupChecks.hasBlockingIssues)
537
478
  return;
538
479
  // Don't redirect if already in settings workspace - let user navigate freely within settings
539
- const currentWorkspace = searchParams.get("workspace");
480
+ const currentWorkspace = searchParams.get("workspace") ?? searchParams.get("view");
540
481
  if (currentWorkspace === "settings")
541
482
  return;
542
483
  // Redirect to the status panel (where user can see all issues and navigate to fixes)
543
484
  const url = new URL(window.location.href);
544
485
  url.searchParams.set("workspace", "settings");
486
+ url.searchParams.delete("view"); // Remove legacy param
545
487
  url.searchParams.set("ccpanel", "status");
546
488
  router.push(url.toString(), { scroll: false });
547
489
  }, [
@@ -559,16 +501,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
559
501
  setMode(queryMode);
560
502
  }
561
503
  }, [searchParams, isInitialLoad]);
562
- useEffect(() => {
563
- if (!isInitialLoad)
564
- return;
565
- const helpParam = searchParams.get("help");
566
- if (helpParam) {
567
- setHelpTerminalActiveTab("manual");
568
- setShowHelpTerminal(true);
569
- setSelectedHelpSectionId(helpParam === "contents" || helpParam === "true" ? null : helpParam);
570
- }
571
- }, [searchParams, isInitialLoad]);
572
504
  useEffect(() => {
573
505
  if (mode === "suggestions") {
574
506
  // Ensure we're in the editor workspace and open the feedback sidebar
@@ -615,19 +547,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
615
547
  setSlotContexts((prev) => {
616
548
  if (!prev.has(slotId))
617
549
  return prev;
618
- if (slotId === activeSlotIdRef.current) {
619
- const activeCtx = prev.get(slotId);
620
- if (activeCtx) {
621
- lastActiveSlotContextRef.current = activeCtx;
622
- }
623
- }
624
550
  const next = new Map(prev);
625
551
  next.delete(slotId);
626
552
  return next;
627
553
  });
628
554
  }, []);
629
555
  const slotContextsRef = useRef(slotContexts);
630
- const lastActiveSlotContextRef = useRef(null);
631
556
  useEffect(() => {
632
557
  slotContextsRef.current = slotContexts;
633
558
  }, [slotContexts]);
@@ -653,12 +578,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
653
578
  const activeSlotContext = activeSlotId
654
579
  ? slotContexts.get(activeSlotId)
655
580
  : undefined;
656
- const isComponentNavigatorOpenForSlot = useCallback((slotId) => {
657
- if (!slotId)
658
- return showComponentNavigatorDefault;
659
- return (slotComponentNavigatorVisibility[slotId] ?? showComponentNavigatorDefault);
660
- }, [slotComponentNavigatorVisibility, showComponentNavigatorDefault]);
661
- const showComponentNavigator = isComponentNavigatorOpenForSlot(activeSlotId);
662
581
  // Sync global compareMode from the active slot's compareMode for URL syncing
663
582
  useEffect(() => {
664
583
  if (activeSlotContext && activeSlotContext.compareMode !== compareMode) {
@@ -706,9 +625,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
706
625
  const isItemUsedInCurrentPage = useCallback((item) => pageItemsSetRef.current.has(makeItemKey(item)), [makeItemKey]);
707
626
  const socketMessageListeners = useRef(new Set());
708
627
  const [socketConnectionVersion, setSocketConnectionVersion] = useState(0);
709
- useEffect(() => {
710
- setSocketDiagnostics(createEditorSocketDiagnostics(sessionId));
711
- }, [sessionId]);
712
628
  const addSocketMessageListener = useCallback((callback) => {
713
629
  socketMessageListeners.current.add(callback);
714
630
  return () => socketMessageListeners.current.delete(callback);
@@ -754,11 +670,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
754
670
  catch { }
755
671
  };
756
672
  }, [addSocketMessageListener]);
757
- const shouldLoadReviews = openSidebars.includes("reviews") ||
758
- workspaceId === "reviews" ||
759
- workspaceId === "comments";
760
673
  const reviews = useReviews({
761
- enabled: shouldLoadReviews,
762
674
  currentItemDescriptor,
763
675
  addSocketMessageListener: addSocketMessageListener,
764
676
  });
@@ -797,13 +709,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
797
709
  console.error(`No workspace found for id: ${workspaceId}`);
798
710
  return null;
799
711
  }
800
- const activeKeyboardCommands = useMemo(() => {
801
- const activeCommandIds = new Set(currentWorkspace.keyboardCommandIds ?? []);
802
- return (configuration.commands.keyboardCommands ?? []).filter((command) => activeCommandIds.has(command.id));
803
- }, [
804
- currentWorkspace.keyboardCommandIds,
805
- configuration.commands.keyboardCommands,
806
- ]);
712
+ // Legacy alias for backwards compatibility
713
+ const currentView = currentWorkspace;
807
714
  useEffect(() => {
808
715
  if (currentWorkspace?.component) {
809
716
  setCenterPanelView(currentWorkspace.component);
@@ -831,45 +738,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
831
738
  const sendClientInfo = useCallback(() => {
832
739
  debouncedSendClientInfo();
833
740
  }, [debouncedSendClientInfo]);
834
- const getCurrentHistoryState = useCallback(() => {
835
- if (typeof window === "undefined") {
836
- return null;
837
- }
838
- return window.history.state;
839
- }, []);
840
- useEffect(() => {
841
- if (isInitialLoad) {
842
- return;
843
- }
844
- const itemid = searchParams.get("itemid");
845
- const language = searchParams.get("lang") ?? searchParams.get("language");
846
- const versionParam = searchParams.get("version");
847
- const version = versionParam ? parseInt(versionParam, 10) : 0;
848
- const itemId = cleanId(itemid ?? undefined);
849
- if (!itemId || !language) {
850
- return;
851
- }
852
- const currentDescriptor = currentItemDescriptorRef.current;
853
- const matchesCurrentDescriptor = currentDescriptor?.id === itemId &&
854
- currentDescriptor?.language === language &&
855
- (!version || currentDescriptor?.version === version);
856
- if (matchesCurrentDescriptor) {
857
- return;
858
- }
859
- isHandlingPopStateRef.current = true;
860
- loadItemRef
861
- .current({
862
- id: itemId,
863
- language,
864
- version,
865
- }, {
866
- addToBrowseHistory: false,
867
- skipViewChange: true,
868
- })
869
- .finally(() => {
870
- isHandlingPopStateRef.current = false;
871
- });
872
- }, [isInitialLoad, searchParams]);
873
741
  const startTour = useCallback(() => {
874
742
  setIsTourActive(true);
875
743
  // Persist tour state to URL so it survives navigation/remounts
@@ -877,61 +745,32 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
877
745
  const params = new URLSearchParams(window.location.search);
878
746
  params.set("tour", "active");
879
747
  const newUrl = `${window.location.pathname}?${params.toString()}`;
880
- window.history.replaceState(getCurrentHistoryState(), "", newUrl);
748
+ window.history.replaceState(null, "", newUrl);
881
749
  }, [setIsTourActive]);
882
- const isMobile = useMediaQuery("(max-width: 767px)");
883
- // On mobile, clear all locked sidebars and keep only the last-opened panel.
884
- // Handles viewport resize: desktop -> mobile unlocks everything and trims to one panel.
885
- useEffect(() => {
886
- if (isMobile) {
887
- setLockedSidebars([]);
888
- const current = openSidebarsRef.current;
889
- const lastSidebar = current[current.length - 1];
890
- if (current.length > 1 && lastSidebar) {
891
- const trimmed = [lastSidebar];
892
- openSidebarsRef.current = trimmed;
893
- setOpenSidebars(trimmed);
894
- }
895
- }
896
- }, [isMobile]);
897
- const setComponentNavigatorOpenForSlot = useCallback((slotId, value) => {
898
- const previousValue = isComponentNavigatorOpenForSlot(slotId);
899
- const newValue = typeof value === "function" ? value(previousValue) : value;
900
- if (slotId) {
901
- setSlotComponentNavigatorVisibility((prev) => {
902
- const currentValue = prev[slotId] ?? showComponentNavigatorDefault;
903
- if (currentValue === newValue && prev[slotId] !== undefined) {
904
- return prev;
905
- }
906
- return {
907
- ...prev,
908
- [slotId]: newValue,
909
- };
910
- });
911
- }
912
- setShowComponentNavigatorDefault(newValue);
750
+ const isMobile = useMediaQuery("(max-width: 768px)");
751
+ const handleSetShowComponentNavigator = useCallback((value) => {
752
+ const newValue = typeof value === "function" ? value(showComponentNavigator) : value;
753
+ setShowComponentNavigator(newValue);
913
754
  setUserPreferences({ showComponentNavigator: newValue });
755
+ // On mobile, close Agents Panel when opening Component Navigator
914
756
  if (isMobile && newValue) {
915
757
  setShowAgentsPanel(false);
916
758
  setUserPreferences({ showAgentsPanel: false });
917
759
  }
918
760
  }, [
919
- isComponentNavigatorOpenForSlot,
920
- showComponentNavigatorDefault,
761
+ showComponentNavigator,
762
+ setShowComponentNavigator,
921
763
  setUserPreferences,
922
764
  isMobile,
923
765
  setShowAgentsPanel,
924
766
  ]);
925
- const handleSetShowComponentNavigator = useCallback((value) => {
926
- setComponentNavigatorOpenForSlot(activeSlotIdRef.current, value);
927
- }, [setComponentNavigatorOpenForSlot]);
928
767
  const handleSetShowAgentsPanel = useCallback((value) => {
929
768
  const newValue = typeof value === "function" ? value(showAgentsPanel) : value;
930
769
  setShowAgentsPanel(newValue);
931
770
  setUserPreferences({ showAgentsPanel: newValue });
932
771
  // On mobile, close Component Navigator when opening Agents Panel
933
772
  if (isMobile && newValue) {
934
- setComponentNavigatorOpenForSlot(activeSlotIdRef.current, false);
773
+ setShowComponentNavigator(false);
935
774
  setUserPreferences({ showComponentNavigator: false });
936
775
  }
937
776
  }, [
@@ -939,40 +778,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
939
778
  setShowAgentsPanel,
940
779
  setUserPreferences,
941
780
  isMobile,
942
- setComponentNavigatorOpenForSlot,
781
+ setShowComponentNavigator,
943
782
  ]);
944
- // Mobile editor panel state (EditorForm shown in bottom panel on mobile)
945
- const [mobileEditorPanelOpen, setMobileEditorPanelOpenRaw] = useState(false);
946
- const [dismissedMobilePanelToken, setDismissedMobilePanelToken] = useState(null);
947
- const previousActiveSlotIdRef = useRef(null);
948
- const mobilePanelDismissToken = useMemo(() => {
949
- const selectionKey = selection.join(",");
950
- return [
951
- activeSlotId || "no-slot",
952
- selectionKey,
953
- insertMode ? "insert" : "browse",
954
- ].join("|");
955
- }, [activeSlotId, insertMode, selection]);
956
- useEffect(() => {
957
- const previousActiveSlotId = previousActiveSlotIdRef.current;
958
- if (previousActiveSlotId !== activeSlotId) {
959
- setDismissedMobilePanelToken(null);
960
- }
961
- previousActiveSlotIdRef.current = activeSlotId;
962
- }, [activeSlotId]);
963
- const handleSetMobileEditorPanelOpen = useCallback((open) => {
964
- setMobileEditorPanelOpenRaw(open);
965
- if (!open) {
966
- setDismissedMobilePanelToken(mobilePanelDismissToken);
967
- return;
968
- }
969
- setDismissedMobilePanelToken(null);
970
- if (open && isMobile) {
971
- // Close all sidebars when opening the editor panel on mobile
972
- openSidebarsRef.current = [];
973
- setOpenSidebars([]);
974
- }
975
- }, [isMobile, mobilePanelDismissToken]);
976
783
  const handleSetShowMinimap = useCallback((value) => {
977
784
  const newValue = typeof value === "function" ? value(showMinimap) : value;
978
785
  setShowMinimap(newValue);
@@ -986,7 +793,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
986
793
  setHelpTerminalInitialPrompt(undefined);
987
794
  setHelpTerminalProfileName(undefined);
988
795
  setHelpTerminalActiveTab(undefined);
989
- setSelectedHelpSectionId(null);
990
796
  }
991
797
  }, [showHelpTerminal]);
992
798
  const toggleHelpTerminal = useCallback((options) => {
@@ -1029,27 +835,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1029
835
  setOpenSidebars(newOrder);
1030
836
  setSidebarStacks((prev) => normalizeSidebarStacks(newOrder, prev));
1031
837
  }, []);
1032
- const ensureSidebarPinned = useCallback((sidebarId) => {
1033
- const currentPinnedSidebars = pinnedSidebarsRef.current;
1034
- if (currentPinnedSidebars.includes(sidebarId)) {
1035
- return;
1036
- }
1037
- const newPinnedSidebars = [...currentPinnedSidebars, sidebarId];
1038
- pinnedSidebarsRef.current = newPinnedSidebars;
1039
- setPinnedSidebars(newPinnedSidebars);
1040
- setUserPreferences({ pinnedSidebars: newPinnedSidebars });
1041
- }, [setUserPreferences]);
1042
838
  // messageHandler is defined after loadItem/loadHistory declarations to avoid temporal dead zones
1043
839
  const user = activeSessions.find((x) => x.sessionId === sessionId)?.user ||
1044
840
  userInfo.user;
1045
- // Self-heal if our session disappears (e.g., after HMR). Skip when concurrent user limit
1046
- // is showing so we don't spam recovery attempts when the connection was rejected.
841
+ // Self-heal if our session disappears (e.g., after HMR)
1047
842
  const missingSessionRecoveryTimerRef = useRef(null);
1048
843
  const missingSessionRecoveryAttemptsRef = useRef(0);
1049
- const concurrentUserLimitErrorRef = useRef(null);
1050
844
  useEffect(() => {
1051
- if (concurrentUserLimitErrorRef.current !== null)
1052
- return;
1053
845
  const hasMySession = activeSessions.some((s) => s.sessionId === sessionId);
1054
846
  if (hasMySession) {
1055
847
  // Reset recovery state when we see ourselves again
@@ -1065,6 +857,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1065
857
  return;
1066
858
  const attempt = missingSessionRecoveryAttemptsRef.current + 1;
1067
859
  const delay = Math.min(250 * Math.pow(2, attempt - 1), 2000);
860
+ console.warn(`⚠️ Current session not present in active sessions. Recovery attempt ${attempt} in ${delay}ms...`);
1068
861
  missingSessionRecoveryTimerRef.current = setTimeout(() => {
1069
862
  missingSessionRecoveryTimerRef.current = null;
1070
863
  missingSessionRecoveryAttemptsRef.current = attempt;
@@ -1073,7 +866,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1073
866
  }
1074
867
  else {
1075
868
  // Force a reconnect to refresh presence after several failed nudges
1076
- console.warn("Session presence did not recover after retries. Forcing reconnect.");
1077
869
  try {
1078
870
  globalThis.editorSocket?.close(4000, "recover-presence");
1079
871
  }
@@ -1093,15 +885,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1093
885
  // Initialize lastUrlRef to current URL on mount
1094
886
  lastUrlRef.current = window.location.href;
1095
887
  const keepAliveUrl = "/parhelia/keepalive";
1096
- const runSessionCheck = () => {
888
+ const interval = setInterval(() => {
1097
889
  fetch(keepAliveUrl + "?ts=" + Date.now())
1098
890
  .then((response) => {
1099
- if (response.headers.get("X-Parhelia-Session-Revoked") === "true") {
1100
- window.dispatchEvent(new CustomEvent("parhelia:session-revoked", {
1101
- detail: { reason: "session-revoked" },
1102
- }));
1103
- return;
1104
- }
1105
891
  if (response.status === 401 || response.status === 403) {
1106
892
  toast.error("Your session has expired", {
1107
893
  description: "Please login again to continue editing.",
@@ -1114,24 +900,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1114
900
  }
1115
901
  })
1116
902
  .catch((error) => console.error("Keep Alive error:", error));
1117
- };
1118
- const keepaliveIntervalMs = (() => {
1119
- const param = new URLSearchParams(window.location.search).get("keepaliveIntervalMs");
1120
- if (!param)
1121
- return 5 * 60 * 1000;
1122
- const ms = parseInt(param, 10);
1123
- return Number.isFinite(ms) && ms >= 2000 && ms <= 60000
1124
- ? ms
1125
- : 5 * 60 * 1000;
1126
- })();
1127
- const interval = setInterval(() => {
1128
- runSessionCheck();
1129
- }, keepaliveIntervalMs);
1130
- const handleVisibilityChange = () => {
1131
- if (document.visibilityState === "visible") {
1132
- runSessionCheck();
1133
- }
1134
- };
903
+ }, 5 * 60 * 1000);
1135
904
  const handleMessage = (event) => {
1136
905
  if (event.data.type === "componentsSelected") {
1137
906
  setSelection(event.data.componentIds);
@@ -1139,44 +908,35 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1139
908
  };
1140
909
  // Listen for browser navigation events (back/forward buttons)
1141
910
  const handlePopState = (event) => {
1142
- const newUrl = `${window.location.pathname}${window.location.search}`;
911
+ const newUrl = window.location.href;
1143
912
  if (newUrl !== lastUrlRef.current) {
1144
913
  lastUrlRef.current = newUrl;
1145
914
  // Mark that we're handling a popstate to prevent URL sync from pushing to history
1146
915
  isHandlingPopStateRef.current = true;
1147
916
  // Sync URL parameters back to component state for browser navigation
1148
917
  const urlParams = new URLSearchParams(window.location.search);
1149
- const urlWorkspace = urlParams.get("workspace");
1150
- if (urlWorkspace && urlWorkspace !== workspaceIdRef.current) {
918
+ // Handle workspace changes (with legacy view fallback)
919
+ const urlWorkspace = urlParams.get("workspace") ?? urlParams.get("view");
920
+ if (urlWorkspace && urlWorkspace !== viewNameRef.current) {
1151
921
  setWorkspaceId(urlWorkspace);
1152
922
  }
1153
- // Handle sidebar changes — clear when absent so state matches the URL
923
+ // Handle sidebar changes
1154
924
  const sidebarParam = urlParams.get("sidebar");
1155
- const newSidebars = sidebarParam
1156
- ? sidebarParam.split(",").filter(Boolean)
1157
- : [];
1158
- setOpenSidebars(newSidebars);
925
+ if (sidebarParam !== null) {
926
+ const newSidebars = sidebarParam.split(",").filter(Boolean);
927
+ setOpenSidebars(newSidebars);
928
+ }
1159
929
  // Handle wizard ID changes
1160
930
  const wizardId = urlParams.get("wizardid");
1161
931
  setCurrentWizardId(wizardId);
1162
- // Handle compare mode changes — always set to avoid stale-closure mismatch
1163
- // (React skips re-render when the value is unchanged)
1164
- setCompareMode(urlParams.get("compare") === "true");
1165
- // Handle help panel changes
1166
- const helpParam = urlParams.get("help");
1167
- if (helpParam) {
1168
- setHelpTerminalActiveTab("manual");
1169
- setShowHelpTerminal(true);
1170
- setSelectedHelpSectionId(helpParam === "contents" || helpParam === "true"
1171
- ? null
1172
- : helpParam);
1173
- }
1174
- else {
1175
- handleSetShowHelpTerminal(false);
932
+ // Handle compare mode changes
933
+ const compareValue = urlParams.get("compare") === "true";
934
+ if (compareValue !== compareMode) {
935
+ setCompareMode(compareValue);
1176
936
  }
1177
- // Handle mode changes — always set to avoid stale-closure mismatch
937
+ // Handle mode changes
1178
938
  const urlMode = urlParams.get("mode");
1179
- if (urlMode) {
939
+ if (urlMode && urlMode !== mode) {
1180
940
  setMode(urlMode);
1181
941
  }
1182
942
  // Handle fullscreen changes (shell-level state)
@@ -1229,11 +989,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1229
989
  };
1230
990
  window.addEventListener("message", handleMessage);
1231
991
  window.addEventListener("popstate", handlePopState);
1232
- window.addEventListener("visibilitychange", handleVisibilityChange);
1233
992
  return () => {
1234
993
  window.removeEventListener("message", handleMessage);
1235
994
  window.removeEventListener("popstate", handlePopState);
1236
- window.removeEventListener("visibilitychange", handleVisibilityChange);
1237
995
  clearInterval(interval);
1238
996
  };
1239
997
  }, []);
@@ -1243,34 +1001,14 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1243
1001
  if (searchParams.get("noTour") !== null) {
1244
1002
  return;
1245
1003
  }
1246
- // Don't start tour when there are setup errors (user is or will be on system status page)
1247
- if (startupChecks.state === "complete" && startupChecks.hasBlockingIssues) {
1248
- return;
1249
- }
1250
- // Don't start tour when already on settings system status page
1251
- if (viewName === "settings" && searchParams.get("ccpanel") === "status") {
1252
- return;
1253
- }
1254
- // Wait for startup checks so we know whether we'll redirect to status
1255
- if (startupChecks.state !== "complete") {
1256
- return;
1257
- }
1258
1004
  const tour = configuration.activeTour;
1259
1005
  const key = tour === "default" ? "editor.tourShown" : "editor.tourShown." + tour;
1260
- const tourShown = localStorageService.getString(key);
1006
+ const tourShown = localStorage.getItem(key);
1261
1007
  if (!tourShown) {
1262
1008
  startTour();
1263
- localStorageService.setString(key, "true");
1009
+ localStorage.setItem(key, "true");
1264
1010
  }
1265
- }, [
1266
- user,
1267
- startupChecks.state,
1268
- startupChecks.hasBlockingIssues,
1269
- viewName,
1270
- searchParams,
1271
- configuration.activeTour,
1272
- startTour,
1273
- ]);
1011
+ }, [user]);
1274
1012
  // WebSocket initialization is performed after messageHandler is defined
1275
1013
  // Defer URL sync until loadItem is defined below
1276
1014
  // Mark end of initial load phase
@@ -1402,8 +1140,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1402
1140
  const loadComments = useCallback(async () => {
1403
1141
  if (!currentItemDescriptor)
1404
1142
  return;
1405
- const reviewId = searchParams.get("reviewId");
1406
- const result = await getComments(currentItemDescriptor.id, currentItemDescriptor.language, currentItemDescriptor.version, reviewId ?? undefined);
1143
+ const result = await getComments(currentItemDescriptor.id, currentItemDescriptor.language, currentItemDescriptor.version);
1407
1144
  if (handleErrorResult(result, ui, state))
1408
1145
  return;
1409
1146
  setComments((x) => {
@@ -1416,7 +1153,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1416
1153
  allComments.sort((a, b) => a.position - b.position);
1417
1154
  return allComments;
1418
1155
  });
1419
- }, [currentItemDescriptor, searchParams]);
1156
+ }, [currentItemDescriptor]);
1420
1157
  // Assuming currentItemDescriptor, ui, state, handleErrorResult, and setSuggestedEdits
1421
1158
  // are available in your component context.
1422
1159
  const loadSuggestedEdits = useCallback(async () => {
@@ -1425,8 +1162,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1425
1162
  const result = await getSuggestedEdits(item.descriptor.id, item.descriptor.language, item.descriptor.version);
1426
1163
  if (handleErrorResult(result, ui, state))
1427
1164
  return;
1428
- const edits = result.data || [];
1429
- setSuggestedEdits(edits);
1165
+ setSuggestedEdits(result.data || []);
1430
1166
  }, [item]);
1431
1167
  const loadFavorites = useCallback(async () => {
1432
1168
  try {
@@ -1500,25 +1236,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1500
1236
  return idB.localeCompare(idA);
1501
1237
  });
1502
1238
  }, []);
1503
- const normalizeEditHistoryPayload = useCallback((value) => {
1504
- if (Array.isArray(value)) {
1505
- return value;
1506
- }
1507
- if (value && typeof value === "object") {
1508
- const payload = value;
1509
- const candidates = [
1510
- payload.operations,
1511
- payload.history,
1512
- payload.items,
1513
- payload.data,
1514
- ];
1515
- const firstArray = candidates.find((candidate) => Array.isArray(candidate));
1516
- if (Array.isArray(firstArray)) {
1517
- return firstArray;
1518
- }
1519
- }
1520
- return [];
1521
- }, []);
1522
1239
  useEffect(() => {
1523
1240
  // Read fresh page from the mutable slot context ref chain.
1524
1241
  // The slot context uses a stable ref that is mutated in-place (see editorSlotContext.ts),
@@ -1541,7 +1258,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1541
1258
  if (handleErrorResult(result, ui, state))
1542
1259
  return;
1543
1260
  setEditHistory((prev) => {
1544
- const next = normalizeEditHistoryPayload(result.data);
1261
+ const next = result.data || [];
1545
1262
  if (!prev.length)
1546
1263
  return sortEditHistoryByDateDesc(next);
1547
1264
  if (!next.length)
@@ -1600,8 +1317,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1600
1317
  const shouldFilterByLanguage = filterByLanguage !== undefined
1601
1318
  ? filterByLanguage
1602
1319
  : filterByCurrentLanguage;
1603
- const trimmedHistoryQuery = historySearchQuery.trim();
1604
- const historyQuery = trimmedHistoryQuery.length > 0 ? trimmedHistoryQuery : undefined;
1605
1320
  if (currentMode === "global") {
1606
1321
  // Global mode: optionally filter by session and/or language
1607
1322
  const currentLanguage = item?.descriptor?.language || currentItemDescriptor?.language;
@@ -1611,14 +1326,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1611
1326
  language: shouldFilterByLanguage && currentLanguage
1612
1327
  ? currentLanguage
1613
1328
  : undefined,
1614
- query: historyQuery,
1615
1329
  });
1616
1330
  if (handleErrorResult(result, ui, state)) {
1617
1331
  console.error("[EditorShell] Failed to load history:", result);
1618
1332
  return;
1619
1333
  }
1620
1334
  setEditHistory((prev) => {
1621
- const next = normalizeEditHistoryPayload(result.data);
1335
+ const next = result.data || [];
1622
1336
  const scope = {
1623
1337
  mode: currentMode,
1624
1338
  filterBySession: shouldFilterBySession,
@@ -1629,12 +1343,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1629
1343
  };
1630
1344
  if (!prev.length)
1631
1345
  return sortEditHistoryByDateDesc(next.filter((op) => matchesHistoryScope(op, scope)));
1632
- if (!next.length) {
1633
- // When searching, respect the empty result — don't fall back to previous items
1634
- if (historyQuery)
1635
- return [];
1346
+ if (!next.length)
1636
1347
  return sortEditHistoryByDateDesc(prev.filter((op) => matchesHistoryScope(op, scope)));
1637
- }
1638
1348
  const prevById = new Map(prev.map((x) => [x.id, x]));
1639
1349
  const nextById = new Set(next.map((x) => x.id));
1640
1350
  const merged = next
@@ -1670,12 +1380,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1670
1380
  return mergedOp;
1671
1381
  });
1672
1382
  // Preserve operations that arrived via WebSocket during the fetch window
1673
- // but not when filtering by search query — search results are authoritative
1674
- if (!historyQuery) {
1675
- for (const [id, priorOp] of prevById) {
1676
- if (!nextById.has(id) && matchesHistoryScope(priorOp, scope)) {
1677
- merged.push(priorOp);
1678
- }
1383
+ for (const [id, priorOp] of prevById) {
1384
+ if (!nextById.has(id) && matchesHistoryScope(priorOp, scope)) {
1385
+ merged.push(priorOp);
1679
1386
  }
1680
1387
  }
1681
1388
  return sortEditHistoryByDateDesc(merged);
@@ -1698,13 +1405,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1698
1405
  const result = await getEditHistory({
1699
1406
  item: itemFilter,
1700
1407
  sessionId: shouldFilterBySession ? sessionId : undefined,
1701
- query: historyQuery,
1702
1408
  });
1703
1409
  if (handleErrorResult(result, ui, state)) {
1704
1410
  console.error("[EditorShell] Failed to load item history:", result);
1705
1411
  return;
1706
1412
  }
1707
- let operations = normalizeEditHistoryPayload(result.data);
1413
+ let operations = result.data || [];
1708
1414
  // Client-side version filtering for current-version mode
1709
1415
  if (currentMode === "current-version") {
1710
1416
  // Defensive filter: only include operations for the current version
@@ -1727,11 +1433,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1727
1433
  };
1728
1434
  if (!prev.length)
1729
1435
  return sortEditHistoryByDateDesc(operations.filter((op) => matchesHistoryScope(op, scope)));
1730
- if (!operations.length) {
1731
- if (historyQuery)
1732
- return [];
1436
+ if (!operations.length)
1733
1437
  return sortEditHistoryByDateDesc(prev.filter((op) => matchesHistoryScope(op, scope)));
1734
- }
1735
1438
  const prevById = new Map(prev.map((x) => [x.id, x]));
1736
1439
  const nextById = new Set(operations.map((x) => x.id));
1737
1440
  const merged = operations
@@ -1767,12 +1470,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1767
1470
  return mergedOp;
1768
1471
  });
1769
1472
  // Preserve operations that arrived via WebSocket during the fetch window
1770
- // but not when filtering by search query — search results are authoritative
1771
- if (!historyQuery) {
1772
- for (const [id, priorOp] of prevById) {
1773
- if (!nextById.has(id) && matchesHistoryScope(priorOp, scope)) {
1774
- merged.push(priorOp);
1775
- }
1473
+ for (const [id, priorOp] of prevById) {
1474
+ if (!nextById.has(id) && matchesHistoryScope(priorOp, scope)) {
1475
+ merged.push(priorOp);
1776
1476
  }
1777
1477
  }
1778
1478
  return sortEditHistoryByDateDesc(merged);
@@ -1783,11 +1483,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1783
1483
  historyMode,
1784
1484
  showOnlyMyChanges,
1785
1485
  filterByCurrentLanguage,
1786
- historySearchQuery,
1787
1486
  item,
1788
1487
  currentItemDescriptor,
1789
1488
  matchesHistoryScope,
1790
- normalizeEditHistoryPayload,
1791
1489
  sortEditHistoryByDateDesc,
1792
1490
  ]);
1793
1491
  // Debounced history refresh to avoid hammering `/parhelia/editHistory` on rapid UI changes.
@@ -1853,14 +1551,13 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1853
1551
  }
1854
1552
  }
1855
1553
  else if (historyMode !== "global" && currentItemDescriptor) {
1856
- // Always load immediately for page-centric/current-version/timeline so we don't show
1857
- // an empty history list for the debounce window (e.g. 600ms). The effect only runs on
1858
- // mode or item id/lang/version change, not on every keystroke, so this avoids flaky
1859
- // undo/redo tests and improves UX when switching to page-centric.
1860
1554
  if (!historyInitialLoadDoneRef.current) {
1861
1555
  historyInitialLoadDoneRef.current = true;
1556
+ refreshHistoryRef.current(historyMode);
1557
+ }
1558
+ else {
1559
+ debouncedRefreshHistoryRef.current(historyMode);
1862
1560
  }
1863
- refreshHistoryRef.current(historyMode);
1864
1561
  }
1865
1562
  else if (historyMode !== "global" && !currentItemDescriptor) {
1866
1563
  // Clear history if no item loaded in page-centric modes
@@ -1873,7 +1570,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1873
1570
  historyMode,
1874
1571
  showOnlyMyChanges,
1875
1572
  filterByCurrentLanguage,
1876
- historySearchQuery,
1877
1573
  currentItemDescriptor?.id,
1878
1574
  currentItemDescriptor?.language,
1879
1575
  currentItemDescriptor?.version,
@@ -1938,9 +1634,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1938
1634
  if (isInitialLoad)
1939
1635
  return;
1940
1636
  const current = new URLSearchParams(window.location.search);
1941
- const urlWorkspace = current.get("workspace");
1942
- const urlView = current.get("view");
1943
- const isWorkspaceTransitioning = !!urlWorkspace && urlWorkspace !== viewName;
1944
1637
  // Sync item-related parameters only when an item is selected
1945
1638
  if (currentItemDescriptor) {
1946
1639
  if (current.get("itemid") !== currentItemDescriptor.id) {
@@ -1971,9 +1664,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1971
1664
  // If reviewId or urlItemId exists, preserve itemid/lang/version from URL
1972
1665
  }
1973
1666
  // Always sync workspace-related parameters regardless of item selection
1974
- if (!isWorkspaceTransitioning && current.get("workspace") !== viewName) {
1667
+ if (current.get("workspace") !== viewName) {
1975
1668
  current.set("workspace", viewName);
1976
1669
  }
1670
+ current.delete("view"); // Remove legacy view param
1977
1671
  // Sync sidebar state
1978
1672
  const currentSidebars = current.get("sidebar") ?? "";
1979
1673
  const newSidebars = openSidebars.join(",");
@@ -1985,12 +1679,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
1985
1679
  current.delete("sidebar");
1986
1680
  }
1987
1681
  }
1988
- if (showHelpTerminal) {
1989
- current.set("help", selectedHelpSectionId ?? "contents");
1990
- }
1991
- else {
1992
- current.delete("help");
1993
- }
1994
1682
  if (!compareMode) {
1995
1683
  current.delete("compare");
1996
1684
  current.delete("compareLanguage");
@@ -2015,15 +1703,15 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2015
1703
  else {
2016
1704
  current.delete("wizardid");
2017
1705
  }
2018
- // Preserve settings-specific parameters while transitioning into Settings too.
2019
- // Some callers update the URL first and switch the workspace state a moment later.
2020
- const isSettingsNavigation = viewName === "settings" ||
2021
- urlWorkspace === "settings" ||
2022
- urlView === "settings";
2023
- if (!isSettingsNavigation) {
1706
+ // Only preserve ccpanel parameter when on settings view, remove it otherwise
1707
+ if (viewName === "settings") {
1708
+ const ccpanel = current.get("ccpanel");
1709
+ if (ccpanel) {
1710
+ current.set("ccpanel", ccpanel);
1711
+ }
1712
+ }
1713
+ else {
2024
1714
  current.delete("ccpanel");
2025
- current.delete("providerId");
2026
- current.delete("modelId");
2027
1715
  }
2028
1716
  // Preserve reviewId parameter if it exists (for review links)
2029
1717
  // This ensures review links don't lose the reviewId when URL is synced
@@ -2036,42 +1724,17 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2036
1724
  const browserPathname = typeof window !== "undefined" ? window.location.pathname : pathname;
2037
1725
  const newUrl = `${browserPathname}?${current.toString()}`;
2038
1726
  const oldUrl = `${browserPathname}${window.location.search}`;
2039
- const isRestoringLastSyncedUrl = newUrl === lastUrlRef.current;
2040
1727
  // Skip pushing to history if we're handling a popstate event (browser back/forward)
2041
1728
  // This prevents the URL sync from overwriting the history during back navigation
2042
1729
  if (isHandlingPopStateRef.current) {
2043
1730
  return;
2044
1731
  }
2045
1732
  if (newUrl !== oldUrl) {
2046
- if (isFirstUrlSyncRef.current ||
2047
- switchWorkspacePushedRef.current ||
2048
- isRestoringLastSyncedUrl) {
2049
- window.history.replaceState(getCurrentHistoryState(), "", newUrl);
2050
- isFirstUrlSyncRef.current = false;
2051
- switchWorkspacePushedRef.current = false;
2052
- }
2053
- else {
2054
- window.history.pushState(getCurrentHistoryState(), "", newUrl);
2055
- }
1733
+ window.history.pushState(null, "", newUrl);
1734
+ // Update lastUrlRef so the popstate handler knows the current URL
1735
+ // This fixes the issue where goBack() wouldn't work because lastUrl was stale
2056
1736
  lastUrlRef.current = newUrl;
2057
1737
  }
2058
- else {
2059
- // Even when the first sync is a no-op (URL already matches state), consume
2060
- // the first-sync flag. Otherwise the *next* real change (e.g. user selecting
2061
- // a different item) would hit the replaceState branch and overwrite the
2062
- // landing history entry — eating the "back" target and making browser back
2063
- // skip past the initial page.
2064
- if (isFirstUrlSyncRef.current) {
2065
- isFirstUrlSyncRef.current = false;
2066
- lastUrlRef.current = newUrl;
2067
- }
2068
- if (switchWorkspacePushedRef.current) {
2069
- // A workspace change may already have pushed the exact target URL. If we leave
2070
- // this flag set, the next unrelated item navigation will incorrectly replace
2071
- // history instead of pushing a new entry, which breaks browser back/forward.
2072
- switchWorkspacePushedRef.current = false;
2073
- }
2074
- }
2075
1738
  }, [
2076
1739
  currentItemDescriptor,
2077
1740
  viewName,
@@ -2083,8 +1746,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2083
1746
  fullscreen,
2084
1747
  currentWizardId,
2085
1748
  openSidebars,
2086
- showHelpTerminal,
2087
- selectedHelpSectionId,
2088
1749
  ]);
2089
1750
  useEffect(() => {
2090
1751
  async function load() {
@@ -2181,9 +1842,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2181
1842
  "en",
2182
1843
  version: 0,
2183
1844
  };
1845
+ const loadedItem = await itemsRepository.getItem(itemToLoad);
1846
+ if (!loadedItem) {
1847
+ return undefined;
1848
+ }
2184
1849
  // ensure this is object has no additional properties
2185
1850
  itemToLoad = getItemDescriptor(itemToLoad);
2186
- const requestedItemKey = makeItemKey(itemToLoad);
2187
1851
  // Check if item is already open in any slot - if so, reuse that slot instead of creating a new one
2188
1852
  const existingSlotForItem = editorSlots.find((s) => s.itemDescriptor.id === itemToLoad.id &&
2189
1853
  s.itemDescriptor.language === itemToLoad.language &&
@@ -2194,17 +1858,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2194
1858
  !options?.openInNewSlot &&
2195
1859
  !options?.targetSlotId) {
2196
1860
  const isExistingSlotActive = existingSlotForItem.slotId === activeSlotIdRef.current;
2197
- if (isExistingSlotActive) {
2198
- latestGlobalLoadKeyRef.current = requestedItemKey;
2199
- }
2200
- const loadedItem = await itemsRepository.getItem(itemToLoad);
2201
- if (!loadedItem) {
2202
- return undefined;
2203
- }
2204
- if (isExistingSlotActive &&
2205
- latestGlobalLoadKeyRef.current !== requestedItemKey) {
2206
- return loadedItem;
2207
- }
2208
1861
  // If forceRefresh is true, update the slot with a new refreshToken to trigger a reload
2209
1862
  if (options?.forceRefresh) {
2210
1863
  setEditorSlots((prev) => {
@@ -2275,30 +1928,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2275
1928
  return next;
2276
1929
  });
2277
1930
  // Decide whether this load should update the global "current item" state.
2278
- // - If we're loading into an inactive slot we won't normally touch, do NOT update URL/tree/controls.
2279
- // - If the slot is active, becoming active as the first slot, or is a brand-new
2280
- // slot the caller explicitly opened, do update.
1931
+ // - If we're loading into an inactive slot (e.g. openInNewSlot), do NOT update URL/tree/controls.
1932
+ // - If the slot is active (or is becoming active as the first slot), do update.
2281
1933
  const isFirstSlot = editorSlots.length === 0;
2282
- const isExplicitNewSlot = options?.openInNewSlot === true && !options?.targetSlotId;
2283
- const shouldUpdateGlobalCurrentItem = isFirstSlot ||
2284
- isExplicitNewSlot ||
2285
- targetSlotId === activeSlotIdRef.current;
2286
- if (shouldUpdateGlobalCurrentItem) {
2287
- latestGlobalLoadKeyRef.current = requestedItemKey;
2288
- }
2289
- const loadedItem = await itemsRepository.getItem(itemToLoad);
2290
- if (!loadedItem) {
2291
- return undefined;
2292
- }
2293
- if (shouldUpdateGlobalCurrentItem &&
2294
- latestGlobalLoadKeyRef.current !== requestedItemKey) {
2295
- return loadedItem;
2296
- }
2297
- // Activate the new slot when this is either the initial first slot, or the
2298
- // caller explicitly opened the item in a new slot — focus follows the action so
2299
- // the user immediately sees what they just opened. Beyond that, slot focus is
2300
- // driven by mouse hover/click.
2301
- if (isFirstSlot || isExplicitNewSlot) {
1934
+ const shouldUpdateGlobalCurrentItem = isFirstSlot || targetSlotId === activeSlotIdRef.current;
1935
+ // Active slot is controlled ONLY by mouse hover - only activate the first slot on initial load
1936
+ if (isFirstSlot) {
2302
1937
  activeSlotIdRef.current = targetSlotId;
2303
1938
  setActiveSlotId(targetSlotId);
2304
1939
  }
@@ -2404,10 +2039,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2404
2039
  useEffect(() => {
2405
2040
  if (fullscreen &&
2406
2041
  !searchParams.get("fullscreen") &&
2407
- !configuration.forceFullscreen &&
2408
- !isMobile)
2042
+ !configuration.forceFullscreen)
2409
2043
  setShowFullscreenHint(true);
2410
- }, [fullscreen, configuration.forceFullscreen, searchParams, isMobile]);
2044
+ }, [fullscreen, configuration.forceFullscreen, searchParams]);
2411
2045
  const state = {
2412
2046
  page,
2413
2047
  configuration,
@@ -2506,35 +2140,20 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2506
2140
  ? existingOp.progress
2507
2141
  : op.progress;
2508
2142
  // IMPORTANT: Once canUndo becomes true, never downgrade it to false,
2509
- // UNLESS this update indicates the operation was undone.
2510
- // Runtime logs show long-running undo completion can arrive as:
2511
- // - existing: canUndo=true, executionStatus=executing
2512
- // - incoming: canUndo=false, executionStatus=completed
2513
- // without explicit undone/canRedo flags yet.
2514
- const isExplicitUndoUpdate = op.undone === true || op.canRedo === true;
2515
- const isInferredUndoCompletion = existingOp.executionStatus === "executing" &&
2516
- op.executionStatus === "completed" &&
2517
- existingOp.canUndo === true &&
2518
- op.canUndo === false;
2519
- const isUndoUpdate = isExplicitUndoUpdate || isInferredUndoCompletion;
2143
+ // UNLESS this update indicates the operation was undone. When an undo
2144
+ // completes, the server sends canUndo: false and canRedo: true (or undone: true).
2145
+ // We must respect that transition so the UI reflects the undo.
2146
+ const isUndoUpdate = op.undone === true || op.canRedo === true;
2520
2147
  const mergedCanUndo = isUndoUpdate
2521
2148
  ? false
2522
2149
  : existingOp.canUndo === true
2523
2150
  ? true
2524
2151
  : op.canUndo;
2525
- const mergedCanRedo = isUndoUpdate
2526
- ? true
2527
- : op.canRedo ?? existingOp.canRedo;
2528
- const mergedUndone = isUndoUpdate
2529
- ? true
2530
- : op.undone ?? existingOp.undone;
2531
2152
  const mergedOp = {
2532
2153
  ...existingOp,
2533
2154
  ...op,
2534
2155
  progress: mergedProgress,
2535
2156
  canUndo: mergedCanUndo,
2536
- canRedo: mergedCanRedo,
2537
- undone: mergedUndone,
2538
2157
  };
2539
2158
  // Ensure undone operations always have canRedo: true.
2540
2159
  if (mergedOp.undone && !mergedOp.canRedo) {
@@ -2588,6 +2207,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2588
2207
  });
2589
2208
  // Ref for markOperationComplete callback (needed because operationsContext is created later)
2590
2209
  const markOperationCompleteRef = useRef(null);
2210
+ // When the websocket is reconnecting, we can briefly lose the ability to send messages.
2211
+ // Agent dialog responses (e.g. questionnaire cancel/submit) must not be dropped, otherwise
2212
+ // the backend tool call can remain pending and tests/users will hang.
2213
+ const pendingAgentDialogResponsesRef = useRef([]);
2591
2214
  // WebSocket message handler and connection
2592
2215
  const messageHandler = useSocketMessageHandler({
2593
2216
  sessionId,
@@ -2613,31 +2236,28 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2613
2236
  markOperationCompleteRef.current?.(operationId);
2614
2237
  },
2615
2238
  });
2616
- // Concurrent user limit error state
2617
- const [concurrentUserLimitError, setConcurrentUserLimitError] = useState(null);
2618
- concurrentUserLimitErrorRef.current = concurrentUserLimitError;
2619
- const handleRetryConnection = useCallback(() => {
2620
- setConcurrentUserLimitError(null);
2621
- // Force reconnection by triggering a new connection attempt
2622
- // The useEditorWebSocket hook will check availability again
2623
- const socket = globalThis.editorSocket;
2624
- if (socket) {
2625
- socket.close();
2626
- delete globalThis.editorSocket;
2627
- }
2628
- // The hook will automatically attempt to reconnect
2629
- }, []);
2630
2239
  const { socketRef: socketInstanceRef } = useEditorWebSocket({
2631
2240
  sessionId,
2632
2241
  onMessage: messageHandler,
2633
2242
  onOpen: async () => {
2634
- // Clear concurrent user limit error on successful connection
2635
- setConcurrentUserLimitError(null);
2636
- // Startup WebSocket probe may have failed with a blocking error while seats were full;
2637
- // re-run status checks quietly so "1 error" does not stick after a successful connect.
2638
- void startupChecks.recheckQuiet();
2639
2243
  // Increment socket connection version to trigger re-subscriptions
2640
2244
  setSocketConnectionVersion((v) => v + 1);
2245
+ // Flush any queued agent dialog responses now that the socket is open.
2246
+ // Keep this early so pending tool calls unblock ASAP.
2247
+ try {
2248
+ if (socketInstanceRef.current &&
2249
+ socketInstanceRef.current.readyState === WebSocket.OPEN &&
2250
+ pendingAgentDialogResponsesRef.current.length > 0) {
2251
+ // FIFO flush
2252
+ while (pendingAgentDialogResponsesRef.current.length > 0) {
2253
+ const queued = pendingAgentDialogResponsesRef.current.shift();
2254
+ socketInstanceRef.current.send(JSON.stringify(queued));
2255
+ }
2256
+ }
2257
+ }
2258
+ catch (e) {
2259
+ console.error("Failed to flush queued agent dialog responses:", e);
2260
+ }
2641
2261
  // Fetch any running operations on (re)connect for auto-resume
2642
2262
  // This ensures the UI shows operations that are still executing
2643
2263
  try {
@@ -2653,37 +2273,24 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2653
2273
  }
2654
2274
  },
2655
2275
  onError: (error) => console.error("WebSocket error:", error),
2656
- onConcurrentUserLimit: (error) => {
2657
- setConcurrentUserLimitError(error);
2658
- },
2659
- onSessionRevoked: () => promptSessionReconnect("session-revoked"),
2660
2276
  connectSocket,
2661
2277
  requestQuota,
2662
2278
  sendClientInfo,
2663
- setSocketDiagnostics,
2664
2279
  });
2665
- useEffect(() => {
2666
- const hasMySession = activeSessions.some((s) => s.sessionId === sessionId);
2667
- if (hasMySession &&
2668
- socketInstanceRef.current?.readyState === WebSocket.OPEN) {
2669
- toast.dismiss("session-revoked");
2670
- }
2671
- }, [activeSessions, sessionId, socketConnectionVersion, socketInstanceRef]);
2672
- useEffect(() => {
2673
- const handleRevoked = (event) => {
2674
- const customEvent = event;
2675
- promptSessionReconnect(customEvent?.detail?.reason);
2676
- };
2677
- window.addEventListener("parhelia:session-revoked", handleRevoked);
2678
- return () => {
2679
- window.removeEventListener("parhelia:session-revoked", handleRevoked);
2680
- };
2681
- }, [promptSessionReconnect]);
2682
2280
  const sendSocketMessage = useCallback((message) => {
2683
2281
  if (socketInstanceRef.current &&
2684
2282
  socketInstanceRef.current.readyState === WebSocket.OPEN) {
2685
2283
  socketInstanceRef.current.send(JSON.stringify(message));
2686
2284
  }
2285
+ else if (message.type === "agent-dialog-response") {
2286
+ // Queue dialog responses to avoid losing them during reconnects.
2287
+ pendingAgentDialogResponsesRef.current.push(message);
2288
+ // Prevent unbounded growth in pathological scenarios.
2289
+ if (pendingAgentDialogResponsesRef.current.length > 50) {
2290
+ pendingAgentDialogResponsesRef.current =
2291
+ pendingAgentDialogResponsesRef.current.slice(-50);
2292
+ }
2293
+ }
2687
2294
  }, [socketInstanceRef]);
2688
2295
  // URL update helper - defined early so it can be used by workspace/sidebar functions
2689
2296
  const updateUrl = useCallback((params) => {
@@ -2702,8 +2309,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2702
2309
  ? `${browserPathname}?${queryString}`
2703
2310
  : browserPathname;
2704
2311
  if (typeof window !== "undefined") {
2705
- window.history.pushState(getCurrentHistoryState(), "", newUrl);
2706
- lastUrlRef.current = newUrl;
2312
+ window.history.pushState(null, "", newUrl);
2707
2313
  }
2708
2314
  else {
2709
2315
  router.push(newUrl, { scroll: false });
@@ -2728,13 +2334,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2728
2334
  if (!options?.skipNavigationHistory) {
2729
2335
  addNavigationEntry(targetWorkspaceId, item);
2730
2336
  }
2731
- // Mark that we're pushing from switchWorkspace so the URL sync effect
2732
- // will replaceState instead of pushing a second history entry.
2733
- switchWorkspacePushedRef.current = true;
2734
- updateUrl({
2735
- workspace: targetWorkspaceId,
2736
- ...options?.urlParams,
2737
- });
2337
+ // Update URL
2338
+ updateUrl({ workspace: targetWorkspaceId });
2738
2339
  if (typeof document.startViewTransition === "function") {
2739
2340
  document.startViewTransition(() => {
2740
2341
  flushSync(() => {
@@ -2754,6 +2355,14 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2754
2355
  updateUrl,
2755
2356
  handleSetShowAgentsPanel,
2756
2357
  ]);
2358
+ // Legacy alias for backwards compatibility
2359
+ const switchView = useCallback((viewName, options) => {
2360
+ // Handle ccpanel for settings workspace
2361
+ if (options?.ccpanel) {
2362
+ updateUrl({ ccpanel: options.ccpanel, workspace: viewName });
2363
+ }
2364
+ switchWorkspace(viewName, options);
2365
+ }, [switchWorkspace, updateUrl]);
2757
2366
  // Helper: get all sidebar IDs that should be preserved (locked sidebars + their stack mates)
2758
2367
  const getPreservedSidebarIds = useCallback(() => {
2759
2368
  const lockedSet = new Set(lockedSidebarsRef.current);
@@ -2791,9 +2400,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2791
2400
  setOpenSidebars(newSidebars);
2792
2401
  setLockedSidebars((locked) => locked.filter((id) => id !== sidebarId));
2793
2402
  setSidebarStacks((prevStacks) => normalizeSidebarStacks(newSidebars, prevStacks));
2794
- if (sidebarId === "agents-panel") {
2795
- setUserPreferences({ showAgentsPanel: false });
2796
- }
2797
2403
  startTransition(() => {
2798
2404
  updateUrl({ sidebar: newSidebars.join(",") || undefined });
2799
2405
  });
@@ -2808,69 +2414,34 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2808
2414
  ];
2809
2415
  openSidebarsRef.current = newSidebars;
2810
2416
  setOpenSidebars(newSidebars);
2811
- ensureSidebarPinned(sidebarId);
2812
2417
  setSidebarStacks((prevStacks) => normalizeSidebarStacks(newSidebars, prevStacks));
2813
- if (sidebarId === "agents-panel") {
2814
- setUserPreferences({ showAgentsPanel: true });
2815
- }
2816
- // On mobile, close the editor form panel when opening a sidebar
2817
- if (isMobile) {
2818
- setMobileEditorPanelOpenRaw(false);
2819
- }
2820
2418
  startTransition(() => {
2821
2419
  updateUrl({ sidebar: newSidebars.join(",") || undefined });
2822
2420
  });
2823
- }, [
2824
- updateUrl,
2825
- getPreservedSidebarIds,
2826
- normalizeSidebarStacks,
2827
- ensureSidebarPinned,
2828
- setUserPreferences,
2829
- isMobile,
2830
- ]);
2421
+ }, [updateUrl, getPreservedSidebarIds, normalizeSidebarStacks]);
2831
2422
  // Ensure a sidebar is open (without toggling it closed if already open)
2832
- const openSidebar = useCallback((sidebarId, options) => {
2423
+ const openSidebar = useCallback((sidebarId) => {
2833
2424
  const currentOpenSidebars = openSidebarsRef.current;
2834
2425
  if (currentOpenSidebars.includes(sidebarId)) {
2835
2426
  // Already open, nothing to do
2836
2427
  return;
2837
2428
  }
2838
- const preservedSet = options?.preserveOpenSidebars
2839
- ? undefined
2840
- : getPreservedSidebarIds();
2841
- const newSidebars = options?.preserveOpenSidebars
2842
- ? [...currentOpenSidebars, sidebarId]
2843
- : [
2844
- ...currentOpenSidebars.filter((id) => preservedSet?.has(id)),
2845
- sidebarId,
2846
- ];
2429
+ // Keep sidebars that are locked OR in a stack with a locked sidebar
2430
+ const preservedSet = getPreservedSidebarIds();
2431
+ const newSidebars = [
2432
+ ...currentOpenSidebars.filter((id) => preservedSet.has(id)), // Keep locked stacks
2433
+ sidebarId, // Add the new one
2434
+ ];
2847
2435
  openSidebarsRef.current = newSidebars;
2848
2436
  setOpenSidebars(newSidebars);
2849
- ensureSidebarPinned(sidebarId);
2850
2437
  setSidebarStacks((prevStacks) => normalizeSidebarStacks(newSidebars, prevStacks));
2851
- if (sidebarId === "agents-panel") {
2852
- setUserPreferences({ showAgentsPanel: true });
2853
- }
2854
- // On mobile, close the editor form panel when opening a sidebar
2855
- if (isMobile) {
2856
- setMobileEditorPanelOpenRaw(false);
2857
- }
2858
2438
  startTransition(() => {
2859
2439
  updateUrl({ sidebar: newSidebars.join(",") || undefined });
2860
2440
  });
2861
- }, [
2862
- updateUrl,
2863
- getPreservedSidebarIds,
2864
- normalizeSidebarStacks,
2865
- ensureSidebarPinned,
2866
- setUserPreferences,
2867
- isMobile,
2868
- ]);
2441
+ }, [updateUrl, getPreservedSidebarIds, normalizeSidebarStacks]);
2869
2442
  // Toggle lock state for a sidebar stack (keeps it visible when selecting another)
2870
2443
  // When toggling any sidebar, we toggle the entire stack it belongs to
2871
2444
  const toggleSidebarLock = useCallback((sidebarId) => {
2872
- if (isMobile)
2873
- return;
2874
2445
  const currentStacks = sidebarStacksRef.current;
2875
2446
  const stackContainingSidebar = currentStacks.find((stack) => stack.includes(sidebarId));
2876
2447
  const sidebarIdsToToggle = stackContainingSidebar || [sidebarId];
@@ -2888,7 +2459,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2888
2459
  ];
2889
2460
  }
2890
2461
  });
2891
- }, [isMobile]);
2462
+ }, []);
2892
2463
  const stackSidebar = useCallback((sidebarId, targetSidebarId, position = "after") => {
2893
2464
  if (!sidebarId || !targetSidebarId || sidebarId === targetSidebarId)
2894
2465
  return;
@@ -2920,38 +2491,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2920
2491
  return normalizeSidebarStacks(openIds, next);
2921
2492
  });
2922
2493
  }, [normalizeSidebarStacks]);
2923
- const moveSidebarToColumn = useCallback((sidebarId, targetSidebarId, position = "after") => {
2924
- if (!sidebarId || !targetSidebarId || sidebarId === targetSidebarId) {
2925
- return;
2926
- }
2927
- const currentOpen = openSidebarsRef.current;
2928
- const baseOpen = currentOpen.filter((id) => id !== sidebarId);
2929
- const targetIndex = baseOpen.indexOf(targetSidebarId);
2930
- if (targetIndex === -1) {
2931
- return;
2932
- }
2933
- const insertIndex = position === "before" ? targetIndex : targetIndex + 1;
2934
- const nextOpen = [...baseOpen];
2935
- nextOpen.splice(insertIndex, 0, sidebarId);
2936
- openSidebarsRef.current = nextOpen;
2937
- setOpenSidebars(nextOpen);
2938
- startTransition(() => {
2939
- updateUrl({ sidebar: nextOpen.join(",") || undefined });
2940
- });
2941
- setSidebarStacks((prev) => {
2942
- const normalized = normalizeSidebarStacks(nextOpen, prev);
2943
- const next = normalized
2944
- .map((stack) => stack.filter((id) => id !== sidebarId))
2945
- .filter((stack) => stack.length > 0);
2946
- const targetStackIndex = next.findIndex((stack) => stack.includes(targetSidebarId));
2947
- if (targetStackIndex === -1) {
2948
- next.push([sidebarId]);
2949
- return normalizeSidebarStacks(nextOpen, next);
2950
- }
2951
- next.splice(position === "before" ? targetStackIndex : targetStackIndex + 1, 0, [sidebarId]);
2952
- return normalizeSidebarStacks(nextOpen, next);
2953
- });
2954
- }, [normalizeSidebarStacks, updateUrl]);
2955
2494
  const unstackSidebar = useCallback((sidebarId) => {
2956
2495
  setSidebarStacks((prev) => {
2957
2496
  const openIds = openSidebarsRef.current;
@@ -2997,34 +2536,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
2997
2536
  // Get resolved sidebar (with panels materialized)
2998
2537
  // Note: This is defined as a function that will be called later when editContext is available
2999
2538
  const sidebars = configuration.editor.sidebars ?? [];
3000
- const taskboardSidebarIds = new Set([
3001
- "taskboard-project-list",
3002
- "taskboard-my-tasks",
3003
- ]);
3004
- const getSidebarsForWorkspace = useCallback((targetWorkspaceId) => {
3005
- const isTaskboardWorkspace = targetWorkspaceId === "taskboard";
3006
- const workspaceAllowedSidebarIds = userInfo.workspaces?.find((w) => w.id === targetWorkspaceId)
3007
- ?.sidebars ?? [];
3008
- return sidebars.filter((s) => {
3009
- const isTaskboardSidebar = taskboardSidebarIds.has(s.id);
3010
- if (isTaskboardWorkspace && !isTaskboardSidebar)
3011
- return false;
3012
- if (!isTaskboardWorkspace && isTaskboardSidebar)
3013
- return false;
3014
- // Always show agents-panel regardless of workspace settings.
3015
- if (s.id === "agents-panel") {
3016
- return true;
3017
- }
3018
- // If no workspace settings or no sidebars defined for current workspace, show all.
3019
- if (workspaceAllowedSidebarIds.length === 0) {
3020
- return true;
3021
- }
3022
- // Only show sidebars that are in the allowed list for the current workspace.
3023
- return workspaceAllowedSidebarIds.includes(s.id);
3024
- });
3025
- }, [sidebars, userInfo.workspaces]);
3026
2539
  const getResolvedSidebar = useCallback((sidebarId) => {
3027
- const sidebar = getSidebarsForWorkspace(workspaceId).find((s) => s.id === sidebarId);
2540
+ const sidebar = sidebars.find((s) => s.id === sidebarId);
3028
2541
  if (!sidebar)
3029
2542
  return undefined;
3030
2543
  // Resolve panel factories using editContextRef to avoid circular dependency
@@ -3038,35 +2551,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
3038
2551
  ...sidebar,
3039
2552
  panels: resolvedPanels,
3040
2553
  };
3041
- }, [getSidebarsForWorkspace, workspaceId]);
3042
- useEffect(() => {
3043
- if (!currentWorkspace.supportsSidebars) {
3044
- return;
3045
- }
3046
- const allowedIds = new Set(getSidebarsForWorkspace(workspaceId).map((sidebar) => sidebar.id));
3047
- const currentOpen = openSidebarsRef.current;
3048
- let nextOpen = currentOpen.filter((id) => allowedIds.has(id));
3049
- if (nextOpen.length === 0 && currentWorkspace.defaultSidebars?.length) {
3050
- nextOpen = currentWorkspace.defaultSidebars.filter((id) => allowedIds.has(id));
3051
- }
3052
- const unchanged = nextOpen.length === currentOpen.length &&
3053
- nextOpen.every((id, index) => id === currentOpen[index]);
3054
- if (unchanged) {
3055
- return;
3056
- }
3057
- openSidebarsRef.current = nextOpen;
3058
- setOpenSidebars(nextOpen);
3059
- setSidebarStacks((prev) => normalizeSidebarStacks(nextOpen, prev));
3060
- startTransition(() => {
3061
- updateUrl({ sidebar: nextOpen.join(",") || undefined });
3062
- });
3063
- }, [
3064
- currentWorkspace,
3065
- getSidebarsForWorkspace,
3066
- normalizeSidebarStacks,
3067
- updateUrl,
3068
- workspaceId,
3069
- ]);
2554
+ }, [sidebars]);
3070
2555
  // Listen for switch-workspace and open-sidebar commands from agents via websocket
3071
2556
  useEffect(() => {
3072
2557
  const handleAgentMessage = (message) => {
@@ -3280,45 +2765,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
3280
2765
  }
3281
2766
  return true;
3282
2767
  }, [operations, ignoreBlur, sessionId]);
3283
- const quickSwitcherEntries = useMemo(() => {
3284
- const entries = [];
3285
- const seen = new Set();
3286
- const pushEntry = (entry) => {
3287
- const key = entry.item
3288
- ? `${entry.workspaceId}:${entry.item.id}:${entry.item.language}:${entry.item.version}`
3289
- : `${entry.workspaceId}:no-item`;
3290
- if (seen.has(key))
3291
- return;
3292
- seen.add(key);
3293
- entries.push(entry);
3294
- };
3295
- for (const entry of navigationHistory) {
3296
- pushEntry(entry);
3297
- }
3298
- for (const entry of browseHistory) {
3299
- if (!entry.id || !entry.language)
3300
- continue;
3301
- pushEntry({
3302
- workspaceId,
3303
- item: {
3304
- id: entry.id,
3305
- language: entry.language,
3306
- version: entry.version ?? 0,
3307
- },
3308
- timestamp: entry.visitedAt
3309
- ? new Date(entry.visitedAt).getTime()
3310
- : Date.now(),
3311
- displayName: entry.name || workspaceId,
3312
- itemName: entry.name,
3313
- itemPath: entry.path,
3314
- itemIcon: entry.icon,
3315
- });
3316
- }
3317
- return entries.slice(0, 25);
3318
- }, [navigationHistory, browseHistory, workspaceId]);
3319
2768
  // Quick switcher handlers
3320
2769
  const showQuickSwitcher = useCallback((show) => {
3321
- if (show && quickSwitcherEntries.length > 1) {
2770
+ if (show && navigationHistory.length > 1) {
3322
2771
  setQuickSwitcherVisible(true);
3323
2772
  // Start with index 1 (second entry - previous entry) for quick switching
3324
2773
  setQuickSwitcherSelectedIndex(1);
@@ -3326,11 +2775,11 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
3326
2775
  else {
3327
2776
  setQuickSwitcherVisible(false);
3328
2777
  }
3329
- }, [quickSwitcherEntries]);
2778
+ }, [navigationHistory]);
3330
2779
  const cycleQuickSwitcher = useCallback((direction) => {
3331
2780
  if (!quickSwitcherVisible)
3332
2781
  return;
3333
- const maxItems = Math.min(5, quickSwitcherEntries.length);
2782
+ const maxItems = Math.min(5, navigationHistory.length);
3334
2783
  setQuickSwitcherSelectedIndex((current) => {
3335
2784
  let newIndex = current;
3336
2785
  // Determine grid layout (responsive columns)
@@ -3375,9 +2824,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
3375
2824
  }
3376
2825
  return newIndex;
3377
2826
  });
3378
- }, [quickSwitcherVisible, quickSwitcherEntries]);
2827
+ }, [quickSwitcherVisible, navigationHistory]);
3379
2828
  const handleQuickSwitcherSelect = useCallback((index) => {
3380
- const selectedEntry = quickSwitcherEntries[index];
2829
+ const selectedEntry = navigationHistory[index];
3381
2830
  if (selectedEntry) {
3382
2831
  // Determine target workspace: entries with items should go to "editor" workspace
3383
2832
  // (fixes issue where browse history entries initialized with wrong workspaceId)
@@ -3429,46 +2878,23 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
3429
2878
  }
3430
2879
  setQuickSwitcherVisible(false);
3431
2880
  }, [
3432
- quickSwitcherEntries,
2881
+ navigationHistory,
3433
2882
  loadItem,
3434
2883
  switchWorkspace,
3435
2884
  workspaceId,
3436
2885
  item,
3437
2886
  setNavigationHistory,
3438
2887
  ]);
3439
- useEffect(() => {
3440
- if (typeof window === "undefined" ||
3441
- process.env.PARHELIA_DEV_MODE !== "true") {
3442
- return;
3443
- }
3444
- window.__parheliaQuickSwitcherTestApi = {
3445
- open: () => showQuickSwitcher(true),
3446
- cycle: (direction = "next") => cycleQuickSwitcher(direction),
3447
- closeWithoutSelection: () => setQuickSwitcherVisible(false),
3448
- selectCurrent: () => handleQuickSwitcherSelect(quickSwitcherSelectedIndex),
3449
- getState: () => ({
3450
- visible: quickSwitcherVisible,
3451
- selectedIndex: quickSwitcherSelectedIndex,
3452
- entryCount: quickSwitcherEntries.length,
3453
- entries: quickSwitcherEntries.map((entry) => ({
3454
- workspaceId: entry.workspaceId,
3455
- itemId: entry.item?.id,
3456
- displayName: entry.displayName,
3457
- })),
3458
- }),
3459
- };
3460
- return () => {
3461
- delete window.__parheliaQuickSwitcherTestApi;
3462
- };
3463
- }, [
3464
- showQuickSwitcher,
3465
- cycleQuickSwitcher,
3466
- handleQuickSwitcherSelect,
3467
- quickSwitcherSelectedIndex,
3468
- ]);
3469
2888
  const { handleKeyDown } = useKeyboardNavigation({
3470
2889
  editContextRef,
3471
- keyboardCommands: activeKeyboardCommands,
2890
+ operations,
2891
+ pageViewContext: activePageViewContext,
2892
+ configuration,
2893
+ item,
2894
+ browseHistory,
2895
+ loadItem,
2896
+ showInfoToast,
2897
+ showErrorToast,
3472
2898
  executeCommand,
3473
2899
  showQuickSwitcher,
3474
2900
  cycleQuickSwitcher,
@@ -3588,19 +3014,10 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
3588
3014
  }
3589
3015
  return null;
3590
3016
  };
3591
- let modifierWasPressedOnMouseDown = false;
3592
- const handleMouseDown = (event) => {
3593
- modifierWasPressedOnMouseDown = event.ctrlKey || event.metaKey;
3594
- };
3595
3017
  const handleCtrlClick = async (event) => {
3596
- // Only proceed if Ctrl/Cmd was already pressed when the mouse interaction started.
3597
- // This avoids accidental navigation when users press Ctrl after selecting text to copy.
3598
- if (!modifierWasPressedOnMouseDown)
3599
- return;
3600
- // Also require the modifier to still be held for the final click event.
3018
+ // Only proceed if Ctrl (or Cmd on Mac) is pressed
3601
3019
  if (!event.ctrlKey && !event.metaKey)
3602
3020
  return;
3603
- modifierWasPressedOnMouseDown = false;
3604
3021
  const target = event.target;
3605
3022
  const text = getTextFromElement(target);
3606
3023
  if (text && isGuid(text)) {
@@ -3615,7 +3032,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
3615
3032
  skipViewChange: true,
3616
3033
  });
3617
3034
  if (item) {
3618
- switchWorkspace("editor", {
3035
+ // Switch to the editor view
3036
+ switchView("editor", {
3619
3037
  skipNavigationHistory: true,
3620
3038
  });
3621
3039
  showInfoToast({
@@ -3641,14 +3059,12 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
3641
3059
  }
3642
3060
  };
3643
3061
  if (typeof document !== "undefined") {
3644
- document.addEventListener("mousedown", handleMouseDown, true);
3645
3062
  document.addEventListener("click", handleCtrlClick, true);
3646
3063
  return () => {
3647
- document.removeEventListener("mousedown", handleMouseDown, true);
3648
3064
  document.removeEventListener("click", handleCtrlClick, true);
3649
3065
  };
3650
3066
  }
3651
- }, [loadItem, switchWorkspace, showInfoToast, showErrorToast]);
3067
+ }, [loadItem, switchView, showInfoToast, showErrorToast]);
3652
3068
  useEffect(() => {
3653
3069
  const handleGlobalBlur = () => {
3654
3070
  operations.onFieldBlur?.();
@@ -3686,6 +3102,21 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
3686
3102
  // Otherwise, only show workspaces that are in the settings
3687
3103
  return workspaceIdsFromSettings.includes(w.id) && !w.visible;
3688
3104
  });
3105
+ // Get sidebars allowed for the current workspace from settings
3106
+ const currentWorkspaceSettings = userInfo.workspaces?.find((w) => w.id === workspaceId);
3107
+ const allowedSidebarIds = currentWorkspaceSettings?.sidebars ?? [];
3108
+ // Legacy: Calculate visible views for backwards compatibility
3109
+ const allViews = (configuration.editor.views ?? [])
3110
+ .filter((x) => {
3111
+ return !x.visible && !x.hidden;
3112
+ })
3113
+ .filter((x) => !userInfo.views ||
3114
+ userInfo.views.map((view) => view.name).includes(x.name));
3115
+ const pinnedViews = userInfo.preferences?.pinnedViews ||
3116
+ configuration.editor.defaultPinnedViews ||
3117
+ [];
3118
+ // Legacy visibleViews for backwards compatibility
3119
+ const visibleViews = allViews.filter((view) => view.name === viewName || pinnedViews.includes(view.name));
3689
3120
  // Handle initial mode setup from URL (only on initial load)
3690
3121
  useEffect(() => {
3691
3122
  if (!isInitialLoad)
@@ -3730,7 +3161,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
3730
3161
  // This is especially important when called from the tour, where the current workspace
3731
3162
  // might be the editor and URL-only navigation would get "corrected" back.
3732
3163
  try {
3733
- switchWorkspace("home", {
3164
+ switchView("home", {
3734
3165
  skipConfirmation: true,
3735
3166
  skipNavigationHistory: true,
3736
3167
  });
@@ -3777,6 +3208,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
3777
3208
  const current = new URLSearchParams(searchParams.toString());
3778
3209
  current.delete("version");
3779
3210
  current.delete("itemid");
3211
+ current.delete("view"); // Remove legacy param
3780
3212
  current.delete("workspace"); // Clear workspace
3781
3213
  current.set("create", "1");
3782
3214
  const newUrl = `${pathname}?${current.toString()}`;
@@ -4056,8 +3488,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4056
3488
  setShowOnlyMyChanges,
4057
3489
  filterByCurrentLanguage,
4058
3490
  setFilterByCurrentLanguage,
4059
- historySearchQuery,
4060
- setHistorySearchQuery,
4061
3491
  refreshHistory,
4062
3492
  isRefreshing,
4063
3493
  activeSessions,
@@ -4095,8 +3525,19 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4095
3525
  workspaceId,
4096
3526
  previousWorkspaceId,
4097
3527
  switchWorkspace,
4098
- // Sidebar state
4099
- availableSidebars: getSidebarsForWorkspace(workspaceId),
3528
+ // Sidebar state - filter by workspace settings if available
3529
+ availableSidebars: (configuration.editor.sidebars ?? []).filter((s) => {
3530
+ // Always show agents-panel regardless of workspace settings
3531
+ if (s.id === "agents-panel") {
3532
+ return true;
3533
+ }
3534
+ // If no workspace settings or no sidebars defined for current workspace, show all
3535
+ if (!allowedSidebarIds || allowedSidebarIds.length === 0) {
3536
+ return true;
3537
+ }
3538
+ // Only show sidebars that are in the allowed list for the current workspace
3539
+ return allowedSidebarIds.includes(s.id);
3540
+ }),
4100
3541
  openSidebars,
4101
3542
  pinnedSidebars,
4102
3543
  lockedSidebars,
@@ -4106,12 +3547,17 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4106
3547
  toggleSidebarPin,
4107
3548
  toggleSidebarLock,
4108
3549
  stackSidebar,
4109
- moveSidebarToColumn,
4110
3550
  unstackSidebar,
4111
3551
  reorderSidebarInStack,
4112
3552
  reorderPinnedSidebars,
4113
3553
  reorderOpenSidebars,
4114
3554
  getResolvedSidebar,
3555
+ // Legacy compatibility (deprecated)
3556
+ viewName,
3557
+ previousViewName,
3558
+ switchView,
3559
+ view: currentView,
3560
+ visibleViews,
4115
3561
  compareMode,
4116
3562
  setCompareMode,
4117
3563
  fullscreen,
@@ -4151,7 +3597,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4151
3597
  addSocketMessageListener,
4152
3598
  sendSocketMessage,
4153
3599
  socketConnectionVersion,
4154
- socketDiagnostics,
4155
3600
  currentItemDescriptor,
4156
3601
  editorSlots,
4157
3602
  activeSlotId,
@@ -4164,7 +3609,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4164
3609
  setActiveSlot,
4165
3610
  revision,
4166
3611
  notifyPageModelReady,
4167
- pageModelReadyToken,
4168
3612
  selectedComment,
4169
3613
  setSelectedComment,
4170
3614
  comments,
@@ -4243,8 +3687,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4243
3687
  setEnableCompletions,
4244
3688
  showComponentNavigator,
4245
3689
  setShowComponentNavigator: handleSetShowComponentNavigator,
4246
- isComponentNavigatorOpenForSlot,
4247
- setComponentNavigatorOpenForSlot,
4248
3690
  showAgentsPanel,
4249
3691
  setShowAgentsPanel: handleSetShowAgentsPanel,
4250
3692
  showMinimap,
@@ -4256,12 +3698,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4256
3698
  helpTerminalProfileName,
4257
3699
  helpTerminalActiveTab,
4258
3700
  setHelpTerminalActiveTab,
4259
- selectedHelpSectionId,
4260
- setSelectedHelpSectionId,
4261
3701
  showAgentsWorkspaceEditor,
4262
3702
  setShowAgentsWorkspaceEditor: handleSetShowAgentsWorkspaceEditor,
4263
- selectedAgentsWorkspaceAgentId,
4264
- setSelectedAgentsWorkspaceAgentId,
4265
3703
  activeEditorTab,
4266
3704
  setActiveEditorTab,
4267
3705
  showLayoutComponents,
@@ -4270,8 +3708,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4270
3708
  isQuotaExceeded: isQuotaExceeded(),
4271
3709
  getQuotaWarningMessage,
4272
3710
  isMobile,
4273
- mobileEditorPanelOpen,
4274
- setMobileEditorPanelOpen: handleSetMobileEditorPanelOpen,
4275
3711
  openDialog,
4276
3712
  webSocketMessages,
4277
3713
  clearWebSocketMessages: () => setWebSocketMessages([]),
@@ -4310,6 +3746,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4310
3746
  configuration,
4311
3747
  updateUrl,
4312
3748
  workspaceId,
3749
+ switchView,
4313
3750
  pathname,
4314
3751
  router,
4315
3752
  item,
@@ -4339,6 +3776,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4339
3776
  currentWorkspace,
4340
3777
  previousWorkspaceId,
4341
3778
  switchWorkspace,
3779
+ allowedSidebarIds,
4342
3780
  openSidebars,
4343
3781
  pinnedSidebars,
4344
3782
  lockedSidebars,
@@ -4350,6 +3788,9 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4350
3788
  reorderOpenSidebars,
4351
3789
  getResolvedSidebar,
4352
3790
  viewName,
3791
+ previousViewName,
3792
+ currentView,
3793
+ visibleViews,
4353
3794
  compareMode,
4354
3795
  // Important: in multi-slot mode the active PageViewContext can change
4355
3796
  // without the base `pageViewContext` identity changing (e.g. switching slots).
@@ -4374,7 +3815,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4374
3815
  currentItemDescriptor,
4375
3816
  revision,
4376
3817
  notifyPageModelReady,
4377
- pageModelReadyToken,
4378
3818
  selectedComment,
4379
3819
  comments,
4380
3820
  availableCommentTags,
@@ -4393,7 +3833,6 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4393
3833
  quickSwitcherSelectedIndex,
4394
3834
  handleQuickSwitcherSelect,
4395
3835
  webSocketMessages,
4396
- socketDiagnostics,
4397
3836
  factoriesRef,
4398
3837
  user,
4399
3838
  statusMessage,
@@ -4402,11 +3841,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4402
3841
  isQuotaExceeded,
4403
3842
  getQuotaWarningMessage,
4404
3843
  isMobile,
4405
- mobileEditorPanelOpen,
4406
- handleSetMobileEditorPanelOpen,
4407
3844
  showComponentNavigator,
4408
- isComponentNavigatorOpenForSlot,
4409
- setComponentNavigatorOpenForSlot,
4410
3845
  handleSetShowComponentNavigator,
4411
3846
  showAgentsPanel,
4412
3847
  handleSetShowAgentsPanel,
@@ -4418,9 +3853,7 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4418
3853
  helpTerminalProfileName,
4419
3854
  helpTerminalActiveTab,
4420
3855
  setHelpTerminalActiveTab,
4421
- selectedHelpSectionId,
4422
3856
  showAgentsWorkspaceEditor,
4423
- selectedAgentsWorkspaceAgentId,
4424
3857
  activeEditorTab,
4425
3858
  showLayoutComponents,
4426
3859
  openDialog,
@@ -4665,40 +4098,18 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4665
4098
  // prevDependencies.current = currentDependencies;
4666
4099
  // editContextRef.current = editContext;
4667
4100
  // }, [editContext]);
4668
- // Auto-open the mobile editor panel for new selection/intent changes, but
4669
- // keep a manual close sticky for the exact same context.
4670
- useEffect(() => {
4671
- if (!isMobile || workspaceId !== "editor")
4672
- return;
4673
- if (activeEditorTab) {
4674
- handleSetMobileEditorPanelOpen(true);
4675
- return;
4676
- }
4677
- if (!(selection.length > 0 || insertMode))
4678
- return;
4679
- if (dismissedMobilePanelToken === mobilePanelDismissToken)
4680
- return;
4681
- handleSetMobileEditorPanelOpen(true);
4682
- }, [
4683
- activeEditorTab,
4684
- dismissedMobilePanelToken,
4685
- handleSetMobileEditorPanelOpen,
4686
- insertMode,
4687
- isMobile,
4688
- mobilePanelDismissToken,
4689
- selection,
4690
- workspaceId,
4691
- ]);
4692
4101
  useEffect(() => {
4693
4102
  fieldsEditContext.clearModifiedFields();
4694
4103
  }, [currentItemDescriptor]);
4695
- if (!currentWorkspace)
4104
+ if (!currentView)
4696
4105
  return null;
4697
- const editorUi = fullscreen ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "fixed inset-0 flex", children: [_jsx(PageViewerFrame, { compareView: compareMode, pageViewContext: activePageViewContext }), _jsx(FullscreenControls, { device: activePageViewContext.device, setDevice: (d) => activePageViewContext.setDevice(d), canExit: !configuration.forceFullscreen, onExit: () => setFullscreen(false), firstMobileDeviceName: configuration.devices[0]?.name })] }), showFullscreenHint && !configuration.forceFullscreen && !isMobile && (_jsx("div", { className: "fixed inset-0 z-10000", onMouseMoveCapture: () => {
4106
+ const editorUi = fullscreen ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "fixed inset-0 flex", children: [_jsx(PageViewerFrame, { compareView: compareMode, pageViewContext: activePageViewContext }), _jsx(FullscreenControls, { device: activePageViewContext.device, setDevice: (d) => activePageViewContext.setDevice(d), canExit: !configuration.forceFullscreen, onExit: () => setFullscreen(false), firstMobileDeviceName: configuration.devices[0]?.name })] }), showFullscreenHint && !configuration.forceFullscreen && (_jsx("div", { className: "fixed inset-0", onMouseMoveCapture: () => {
4698
4107
  setTimeout(() => {
4699
4108
  setShowFullscreenHint(false);
4700
4109
  }, 600);
4701
- }, "data-testid": "fullscreen-hint-overlay", children: _jsxs("div", { className: "fixed top-6 left-1/2 -translate-x-1/2 transform rounded-full bg-black/60 px-6 py-2.5 text-sm font-medium text-white shadow-2xl backdrop-blur-md transition-all duration-500", children: ["Press", " ", _jsx("kbd", { className: "mx-1 rounded bg-white/20 px-1.5 py-0.5 text-xs font-semibold", children: "Ctrl + F11" }), " ", "to exit fullscreen"] }) }))] })) : (_jsxs(_Fragment, { children: [_jsx(EditorChrome, { className: className, currentWorkspace: currentWorkspace, centerPanelView: centerPanelView, editContext: editContext, showAgentsPanel: showAgentsPanel, handleSetShowAgentsPanel: handleSetShowAgentsPanel, workspaceId: workspaceId }), isTourActive && (_jsx(Tour, { tourStopCallback: () => {
4110
+ }, "data-testid": "fullscreen-hint-overlay", children: _jsxs("div", { className: "fixed top-6 left-1/2 -translate-x-1/2 transform rounded-full bg-black/60 px-6 py-2.5 text-sm font-medium text-white shadow-2xl backdrop-blur-md transition-all duration-500", children: ["Press", " ", _jsx("kbd", { className: "mx-1 rounded bg-white/20 px-1.5 py-0.5 text-xs font-semibold", children: "Ctrl + F11" }), " ", "to exit fullscreen"] }) }))] })) : (_jsxs(_Fragment, { children: [_jsx(EditorChrome, { className: className, currentWorkspace: currentWorkspace, centerPanelView: centerPanelView, editContext: editContext, showComponentNavigator: showComponentNavigator, handleSetShowComponentNavigator: handleSetShowComponentNavigator, showAgentsPanel: showAgentsPanel, handleSetShowAgentsPanel: handleSetShowAgentsPanel, workspaceId: workspaceId,
4111
+ // Legacy props for backwards compatibility
4112
+ currentView: currentView, viewName: viewName }), isTourActive && (_jsx(Tour, { tourStopCallback: () => {
4702
4113
  setIsTourActive(false);
4703
4114
  // Remove tour state from URL
4704
4115
  // Use history.replaceState instead of router.replace to avoid triggering React navigation
@@ -4708,14 +4119,8 @@ export function EditorShell({ configuration, className, item: loadItemDescriptor
4708
4119
  const newUrl = queryString
4709
4120
  ? `${window.location.pathname}?${queryString}`
4710
4121
  : window.location.pathname;
4711
- window.history.replaceState(getCurrentHistoryState(), "", newUrl);
4712
- }, configuration: configuration, restoredFromUrl: tourRestoredRef.current })), _jsx(FeatureGate, { feature: LicenseFeatures.AI, children: _jsx(GuidanceOverlay, {}) }), _jsx(FeatureGate, { feature: LicenseFeatures.AI, children: _jsx(AgentDialogHandler, {}) })] }));
4713
- return (_jsx(LicenseProvider, { initialLicenseStatus: initialLicenseStatus, initialStatusLoaded: initialLicenseStatusLoaded, children: _jsx("div", { className: `editor h-full w-full`, children: _jsx(OperationsContextProvider, { value: operationsContext.context, children: _jsx(FieldsEditContextProvider, { value: fieldsEditContext, children: _jsxs(EditContextProvider, { value: editContext, children: [_jsx(DevModeIndicator, {}), startupChecks.state === "loading" && (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-white/70 backdrop-blur-[1px]", children: _jsx("div", { className: "flex items-center gap-3 rounded-md border border-gray-200 bg-white px-4 py-3 text-gray-700 shadow-sm", children: _jsx(Spinner, { size: "xl" }) }) })), editContext.isRefreshing && (_jsx("div", { className: "pointer-events-none fixed right-0 bottom-0 flex h-24 w-24 items-center justify-center text-gray-600 opacity-50 select-none", children: _jsx(Spinner, {}) })), (currentWorkspace.id === "agents" ||
4714
- currentWorkspace.id === "taskboard") &&
4715
- showAgentsWorkspaceEditor && (_jsx(AgentsSlotContextBridgeHost, { slots: editorSlots })), startupChecks.state !== "loading" && (children || editorUi), startupChecks.state !== "loading" && dialog, _jsx(Toaster, { position: "top-center" }), " ", _jsx(ConfirmationDialog, { ref: confirmationDialogRef }), _jsx(ConcurrentUserLimitDialog, { open: concurrentUserLimitError !== null, onOpenChange: (open) => {
4716
- if (!open) {
4717
- setConcurrentUserLimitError(null);
4718
- }
4719
- }, sessionId: sessionId, currentUsers: concurrentUserLimitError?.currentUsers ?? 0, maxUsers: concurrentUserLimitError?.maxUsers ?? 0, message: concurrentUserLimitError?.message ?? "", onRetry: handleRetryConnection, isAdministrator: userInfo.user.isAdministrator === true }), _jsx(QuickItemSwitcher, { visible: quickSwitcherVisible, entries: quickSwitcherEntries.slice(0, 5), selectedIndex: quickSwitcherSelectedIndex, onSelect: handleQuickSwitcherSelect, onClose: () => setQuickSwitcherVisible(false) }), _jsx(EditContextMenu, { ref: contextMenuRef }), _jsx(FeatureGate, { feature: LicenseFeatures.AI, children: _jsx(InlineAiTrigger, {}) }), media.mediaSelectorVisible && (_jsx(MediaSelector, { language: editContext.currentItemDescriptor.language, visible: media.mediaSelectorVisible, onHide: media.handleHide, onMediaSelected: media.onMediaSelect, selectedIdPath: media.selectedMediaIdPath, mode: media.mediaSelectorMode, initialSearchTerm: media.initialSearchTerm })), _jsx(FieldEditorPopup, { ref: fieldEditorPopupRef }), _jsx(LicenseOverlay, {})] }) }) }) }) }));
4122
+ window.history.replaceState(null, "", newUrl);
4123
+ }, configuration: configuration, restoredFromUrl: tourRestoredRef.current })), _jsx(GuidanceOverlay, {}), _jsx(AgentDialogHandler, { sendWebSocketMessage: (type, payload) => sendSocketMessage({ type, payload }) })] }));
4124
+ return (_jsx("div", { className: `editor h-full w-full`, children: _jsx(OperationsContextProvider, { value: operationsContext.context, children: _jsx(FieldsEditContextProvider, { value: fieldsEditContext, children: _jsxs(EditContextProvider, { value: editContext, children: [_jsx(DevModeIndicator, {}), startupChecks.state === "loading" && (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-white/70 backdrop-blur-[1px]", children: _jsx("div", { className: "flex items-center gap-3 rounded-md border border-gray-200 bg-white px-4 py-3 text-gray-700 shadow-sm", children: _jsx(Spinner, { size: "xl" }) }) })), editContext.isRefreshing && (_jsx("div", { className: "pointer-events-none fixed right-0 bottom-0 flex h-24 w-24 items-center justify-center text-gray-600 opacity-50 select-none", children: _jsx(Spinner, {}) })), children || editorUi, dialog, _jsx(Toaster, { position: "top-center" }), " ", _jsx(ConfirmationDialog, { ref: confirmationDialogRef }), _jsx(QuickItemSwitcher, { visible: quickSwitcherVisible, entries: navigationHistory.slice(0, 5), selectedIndex: quickSwitcherSelectedIndex, onSelect: handleQuickSwitcherSelect, onClose: () => setQuickSwitcherVisible(false) }), _jsx(EditContextMenu, { ref: contextMenuRef }), _jsx(InlineAiTrigger, {}), media.mediaSelectorVisible && (_jsx(MediaSelector, { language: editContext.currentItemDescriptor.language, visible: media.mediaSelectorVisible, onHide: media.handleHide, onMediaSelected: media.onMediaSelect, selectedIdPath: media.selectedMediaIdPath, mode: media.mediaSelectorMode, initialSearchTerm: media.initialSearchTerm })), _jsx(FieldEditorPopup, { ref: fieldEditorPopupRef })] }) }) }) }));
4720
4125
  }
4721
4126
  //# sourceMappingURL=EditorShell.js.map