@nextclaw/ui 0.25.3 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/.vite/manifest.json +1146 -1390
  3. package/dist/assets/{abnfDiagram-VRR7QNED-DX_u5BBX.js → abnfDiagram-VRR7QNED-Bjrmb5-o.js} +1 -1
  4. package/dist/assets/account-panel-C1S3xtUB.js +1 -0
  5. package/dist/assets/{aiden0z-pptx-renderer.es-C-E9e5yB.js → aiden0z-pptx-renderer.es-DO4DCX3e.js} +1 -1
  6. package/dist/assets/api-D9e9cHtW.js +20 -0
  7. package/dist/assets/app-presenter-provider-J9IgTbc9.js +124 -0
  8. package/dist/assets/appearance-settings-page-BljTr6nB.js +1 -0
  9. package/dist/assets/{arc-Cxwa624o.js → arc-g4XaP3S4.js} +1 -1
  10. package/dist/assets/architecture-TIHT7OUA-BWywYH_m.js +1 -0
  11. package/dist/assets/{architectureDiagram-ZJ3FMSHR-D8mCj0H1.js → architectureDiagram-ZJ3FMSHR-CAP7YDux.js} +1 -1
  12. package/dist/assets/{blockDiagram-677ZJIJ3-CbGC1IHl.js → blockDiagram-677ZJIJ3-DhaP0zUG.js} +1 -1
  13. package/dist/assets/{book-open-xqEj1OLE.js → book-open-vxpV2eSM.js} +1 -1
  14. package/dist/assets/{c4Diagram-LMCZKHZV-BQhGC1Vc.js → c4Diagram-LMCZKHZV-DHCQJJkD.js} +1 -1
  15. package/dist/assets/card-D9NYhSdf.js +1 -0
  16. package/dist/assets/channel-1nKIAEXr.js +1 -0
  17. package/dist/assets/channels-list-page-BiHA1zZd.js +8 -0
  18. package/dist/assets/chunk-2Q5K7J3B-CAwv72v4.js +1 -0
  19. package/dist/assets/{chunk-32BRIVSS-B74ZZwYG.js → chunk-32BRIVSS-BcQlxl4v.js} +1 -1
  20. package/dist/assets/{chunk-52WLFC77-BvmxW_f_.js → chunk-52WLFC77-ClPpG-2S.js} +1 -1
  21. package/dist/assets/{chunk-5FCAYU7R-DQvBRnwL.js → chunk-5FCAYU7R-B_qmYOdX.js} +1 -1
  22. package/dist/assets/{chunk-5HE753X5-CDIH0_y3.js → chunk-5HE753X5-DTO-V56q.js} +1 -1
  23. package/dist/assets/{chunk-5JV3BV7I-CcevlKd-.js → chunk-5JV3BV7I-CU1SOaaG.js} +1 -1
  24. package/dist/assets/{chunk-5TONJI2A-_3dxVdnY.js → chunk-5TONJI2A-CzSDkWNa.js} +1 -1
  25. package/dist/assets/{chunk-5VM5RSS4-pGO5vvo-.js → chunk-5VM5RSS4-ChkfqIRE.js} +1 -1
  26. package/dist/assets/{chunk-7BUUIJ7U-DEKF5uAN.js → chunk-7BUUIJ7U-Du3Ozi62.js} +1 -1
  27. package/dist/assets/{chunk-BIQX33UG-CjBFgq2r.js → chunk-BIQX33UG-C-HVafHB.js} +1 -1
  28. package/dist/assets/{chunk-C7G6YPKG-e_K9OGTz.js → chunk-C7G6YPKG-BSjZ86D0.js} +1 -1
  29. package/dist/assets/{chunk-CQNSW5MT-C2IiHyHz.js → chunk-CQNSW5MT-1D1W2lF6.js} +1 -1
  30. package/dist/assets/{chunk-CYSBUYHQ-DCC6KmGp.js → chunk-CYSBUYHQ-ISpyj_lK.js} +1 -1
  31. package/dist/assets/{chunk-EMLP6XTP-BYGgekQ0.js → chunk-EMLP6XTP-Cp8iUBt2.js} +1 -1
  32. package/dist/assets/{chunk-EX3LRPZG-FGcwuVsA.js → chunk-EX3LRPZG-BN5RzF5j.js} +1 -1
  33. package/dist/assets/{chunk-FWX5IMBZ-CV3Ih_Os.js → chunk-FWX5IMBZ-DecJDW4r.js} +2 -2
  34. package/dist/assets/{chunk-HOUHSVGY-CXpq_hfV.js → chunk-HOUHSVGY-BE_XNgGk.js} +1 -1
  35. package/dist/assets/{chunk-ICXQ74PX-CZIpjupq.js → chunk-ICXQ74PX-BFOKMkWV.js} +1 -1
  36. package/dist/assets/{chunk-JG7HCLWE-CdgwBpW7.js → chunk-JG7HCLWE-DL-pl8VB.js} +1 -1
  37. package/dist/assets/{chunk-JWPE2WC7-BPjAZpOQ.js → chunk-JWPE2WC7-B-bcwfmh.js} +1 -1
  38. package/dist/assets/{chunk-MOJQB5TN-DbJDm8to.js → chunk-MOJQB5TN-BC0taFro.js} +1 -1
  39. package/dist/assets/{chunk-MOZMSUNE-BUa1fqKn.js → chunk-MOZMSUNE-RrhfU6MO.js} +1 -1
  40. package/dist/assets/{chunk-OGEWGWER-CtnzLgRu.js → chunk-OGEWGWER-TuI7SR7i.js} +1 -1
  41. package/dist/assets/{chunk-OSBZ3O6U-fUgdpTUM.js → chunk-OSBZ3O6U-C5jMBKlU.js} +1 -1
  42. package/dist/assets/{chunk-PUDLZKDR-CtDWZT9-.js → chunk-PUDLZKDR-C5lMBn0K.js} +1 -1
  43. package/dist/assets/{chunk-Q4XR5HBZ-BxnK2qxr.js → chunk-Q4XR5HBZ-B-kzUbwT.js} +1 -1
  44. package/dist/assets/{chunk-QBLGF6JB-CH4UKoCF.js → chunk-QBLGF6JB-CRb_WAEj.js} +1 -1
  45. package/dist/assets/{chunk-R7FJI6CG-BxwFoF1v.js → chunk-R7FJI6CG-De6Y7ozO.js} +1 -1
  46. package/dist/assets/{chunk-RYQCIY6F-DpHAmq7O.js → chunk-RYQCIY6F-Igv92q8k.js} +1 -1
  47. package/dist/assets/{chunk-U6XO7XAA-BjH2VUHU.js → chunk-U6XO7XAA-bCjRshkT.js} +1 -1
  48. package/dist/assets/{chunk-V7JOEXUC-DKJZ3HGj.js → chunk-V7JOEXUC-0J1s_Kgq.js} +1 -1
  49. package/dist/assets/chunk-VAUOI2AC-DnaryNw2.js +1 -0
  50. package/dist/assets/{chunk-VR4S4FIN-Cf-o2GtI.js → chunk-VR4S4FIN-DX6lXnNx.js} +1 -1
  51. package/dist/assets/{chunk-WYO6CB5R-zeNXGm20.js → chunk-WYO6CB5R-DLqMXfFC.js} +3 -3
  52. package/dist/assets/chunk-XXDRQBXY-BToo1uqb.js +1 -0
  53. package/dist/assets/{chunk-YOTPTUD7-Ck87Kqxe.js → chunk-YOTPTUD7-CY4obsV0.js} +1 -1
  54. package/dist/assets/{chunk-ZGVPDNZ5-BbfK6Bfd.js → chunk-ZGVPDNZ5-BleImZKe.js} +1 -1
  55. package/dist/assets/{chunk-ZIRB5QZD-BDpzh4Yl.js → chunk-ZIRB5QZD-C1TfdjpX.js} +1 -1
  56. package/dist/assets/{circle-dashed-CU3yApvP.js → circle-dashed-CEEssYIw.js} +1 -1
  57. package/dist/assets/classDiagram-OUVF2IWQ-D_TusZGx.js +1 -0
  58. package/dist/assets/classDiagram-v2-EOCWNBFH-B1NFZTmS.js +1 -0
  59. package/dist/assets/client-C6YQx7A-.js +1 -0
  60. package/dist/assets/config-split-page-DKPelvjR.js +1 -0
  61. package/dist/assets/confirm-dialog-BCGeh61X.js +1 -0
  62. package/dist/assets/{cose-bilkent-JH36ORCC-CQfMxKCT.js → cose-bilkent-JH36ORCC-CVgUHXkj.js} +1 -1
  63. package/dist/assets/createLucideIcon-CF8U9dh7.js +1 -0
  64. package/dist/assets/cynefin-VYW2F7L2-CJZSs5s_.js +1 -0
  65. package/dist/assets/{cynefinDiagram-TSTJHNR4-CxFTiC-p.js → cynefinDiagram-TSTJHNR4-cdfImbfI.js} +1 -1
  66. package/dist/assets/{dagre-CaBNMcB1.js → dagre-CHNN9L9I.js} +1 -1
  67. package/dist/assets/{dagre-VKFMJZFB-S_7Hc7bI.js → dagre-VKFMJZFB-PscaENwr.js} +1 -1
  68. package/dist/assets/desktop-capabilities-page-BENHdKfk.js +1 -0
  69. package/dist/assets/desktop-update-config-BJMTQMRS.js +1 -0
  70. package/dist/assets/{diagram-FQU43EPY-C7zENvFb.js → diagram-FQU43EPY-CH_wye41.js} +1 -1
  71. package/dist/assets/{diagram-G47NLZAW-DqYTCqZA.js → diagram-G47NLZAW-Dtjpmi6D.js} +1 -1
  72. package/dist/assets/{diagram-NH7WQ7WH-BfSJtXRc.js → diagram-NH7WQ7WH-UdjLHyaz.js} +1 -1
  73. package/dist/assets/{diagram-OA4YK3LP-CFO-j67H.js → diagram-OA4YK3LP-DYsToEaL.js} +1 -1
  74. package/dist/assets/{diagram-WEI45ONY-DBQDbTaJ.js → diagram-WEI45ONY-CA7kuIer.js} +1 -1
  75. package/dist/assets/dialog-DQXou6pg.js +5 -0
  76. package/dist/assets/dist-CiC9Fd9J.js +1 -0
  77. package/dist/assets/doc-browser-CCYS_csH.js +1 -0
  78. package/dist/assets/doc-browser-context-CPLWVFLd.js +1 -0
  79. package/dist/assets/{docx-preview-B4-aDfvO.js → docx-preview-D--EsUWi.js} +1 -1
  80. package/dist/assets/{ebnfDiagram-CCIWWBDH-CfDNIXFN.js → ebnfDiagram-CCIWWBDH-BrjaoOuq.js} +1 -1
  81. package/dist/assets/{erDiagram-Q63AITRT-D95rFXMM.js → erDiagram-Q63AITRT-nZQa2kCM.js} +1 -1
  82. package/dist/assets/es2015-DHRpDU-q.js +41 -0
  83. package/dist/assets/eventmodeling-45OFAUF4-rc7kUq4V.js +1 -0
  84. package/dist/assets/extensions-CsWT7x3v.js +1 -0
  85. package/dist/assets/{eye-C84inPcV.js → eye-DJtw5KJ5.js} +1 -1
  86. package/dist/assets/flowDiagram-23GEKE2U-DAjaeGO8.js +1 -0
  87. package/dist/assets/form-actions-DDQk0END.js +1 -0
  88. package/dist/assets/{ganttDiagram-NO4QXBWP-Bawg0P0r.js → ganttDiagram-NO4QXBWP-CyFZHIHN.js} +1 -1
  89. package/dist/assets/gitGraph-TEB2WS4Q-Ce0gf6ps.js +1 -0
  90. package/dist/assets/{gitGraphDiagram-IHSO6WYX-BbKh9nbL.js → gitGraphDiagram-IHSO6WYX-Dfpq3z2M.js} +1 -1
  91. package/dist/assets/{i18n-20rSH40D.js → i18n-BjPkAKMQ.js} +2 -2
  92. package/dist/assets/info-DKCQHKI2-Cp-Tr78m.js +1 -0
  93. package/dist/assets/{infoDiagram-FWYZ7A6U-DPffZXYh.js → infoDiagram-FWYZ7A6U-Diiz0k1E.js} +1 -1
  94. package/dist/assets/{ishikawaDiagram-FXEZZL3T-CBMsLwZ2.js → ishikawaDiagram-FXEZZL3T-B3R3SN4M.js} +1 -1
  95. package/dist/assets/{journeyDiagram-5HDEW3XC-Mz5U4OzU.js → journeyDiagram-5HDEW3XC-DFOLKiNv.js} +1 -1
  96. package/dist/assets/{kanban-definition-HUTT4EX6-FXZq2k19.js → kanban-definition-HUTT4EX6-BMXpDp3g.js} +1 -1
  97. package/dist/assets/katex-B4FQSo9k.js +1 -0
  98. package/dist/assets/keyboard-shortcuts-settings-page-hqTP7akj.js +1 -0
  99. package/dist/assets/{line-BZwCgT9K.js → line-64_FhCoJ.js} +1 -1
  100. package/dist/assets/{linear-CTe9mKUw.js → linear-aF1fg7bK.js} +1 -1
  101. package/dist/assets/loader-circle-B-4WwzBj.js +1 -0
  102. package/dist/assets/login-page-BUwshAq4.js +1 -0
  103. package/dist/assets/login-page-CdlI6B8e.js +1 -0
  104. package/dist/assets/main-BVYdyT60.css +1 -0
  105. package/dist/assets/main-DYEALeoQ.js +2 -0
  106. package/dist/assets/main-i18n-catalog.config-1o2hjZ0m.js +1 -0
  107. package/dist/assets/{map-Ci48ZwAp.js → map-BC3Amra3.js} +1 -1
  108. package/dist/assets/mcp-marketplace-page-CRRQT6SP.js +1 -0
  109. package/dist/assets/{mermaid-parser.core-CzPD3U_z.js → mermaid-parser.core-DdMcZwnE.js} +2 -2
  110. package/dist/assets/{mermaid.core-geIMNPbV.js → mermaid.core-BHdiEBbI.js} +3 -3
  111. package/dist/assets/{mindmap-definition-LN4V7U3C-xqlKxsr_.js → mindmap-definition-LN4V7U3C-CtHVaZyV.js} +1 -1
  112. package/dist/assets/model-config-page-BSsHOhV7.js +1 -0
  113. package/dist/assets/navigation-history-CyawyVz0.js +1 -0
  114. package/dist/assets/navigation-link-D-fxdv0i.js +3 -0
  115. package/dist/assets/{ordinal-MxnX8yhv.js → ordinal-6b3jw4cz.js} +1 -1
  116. package/dist/assets/packet-7NZHBO7P-BOJuCraS.js +1 -0
  117. package/dist/assets/panel-app-i18n-catalog.config-kQO7QAwH.js +1 -0
  118. package/dist/assets/panelStandalone-BeI0Ndsx.js +2 -0
  119. package/dist/assets/{pegDiagram-2B236MQR-D50MFTN1.js → pegDiagram-2B236MQR-BtbG3Bgu.js} +1 -1
  120. package/dist/assets/pie-RZYD4A2V-D-FEO81x.js +1 -0
  121. package/dist/assets/{pieDiagram-ENE6RG2P-CpA13oiC.js → pieDiagram-ENE6RG2P-FmLl2hzN.js} +1 -1
  122. package/dist/assets/privacy-settings-page-pW_1naDz.js +1 -0
  123. package/dist/assets/projects-k6SLda_A.js +1 -0
  124. package/dist/assets/provider-models-mVzuEQBS.js +1 -0
  125. package/dist/assets/provider-scoped-model-input-CVbtT8L9.js +1 -0
  126. package/dist/assets/providers-config-page-rBlVrHkb.js +1 -0
  127. package/dist/assets/{puzzle-D6gulz7u.js → puzzle-kKiVft9-.js} +1 -1
  128. package/dist/assets/pwa-BgGM4kkY.js +1 -0
  129. package/dist/assets/{quadrantDiagram-ABIIQ3AL-CYCgaj4l.js → quadrantDiagram-ABIIQ3AL-7-OzMNpF.js} +1 -1
  130. package/dist/assets/radar-I7S5WNFK-Bq3eK1vK.js +1 -0
  131. package/dist/assets/railroad-3IZDKUUU-C3uZ1esg.js +1 -0
  132. package/dist/assets/railroad-abnf-AHOZXSZD-D3iZd1KT.js +1 -0
  133. package/dist/assets/railroad-ebnf-EBAXGLYW-Dl0FWqZu.js +1 -0
  134. package/dist/assets/railroad-peg-LSFZ7HO6-B51SbzGp.js +1 -0
  135. package/dist/assets/{railroadDiagram-RFXS5EU6-4LKDGlXN.js → railroadDiagram-RFXS5EU6-B_UVtLJO.js} +1 -1
  136. package/dist/assets/{refresh-cw-h9Xq3LY3.js → refresh-cw-BeG0y6yZ.js} +1 -1
  137. package/dist/assets/remote-wYWqir2w.js +1 -0
  138. package/dist/assets/{requirementDiagram-TGXJPOKE-CxNOU0JH.js → requirementDiagram-TGXJPOKE-D8TO2YeZ.js} +1 -1
  139. package/dist/assets/{rotate-cw-B6xm41Wn.js → rotate-cw-Ci2dcTO5.js} +1 -1
  140. package/dist/assets/runtime-config-page-DCXN0nkS.js +1 -0
  141. package/dist/assets/{sankeyDiagram-HTMAVEWB-DbCBDe2S.js → sankeyDiagram-HTMAVEWB-CUzIcq0B.js} +1 -1
  142. package/dist/assets/{save-fff_WpY2.js → save-Cr895abt.js} +1 -1
  143. package/dist/assets/search-config-page-CNQd481d.js +1 -0
  144. package/dist/assets/secrets-config-page--q7M58L8.js +3 -0
  145. package/dist/assets/security-config-CJb2pK2O.js +1 -0
  146. package/dist/assets/select-Bq-UmfCK.js +1 -0
  147. package/dist/assets/{sequenceDiagram-DBY2YBRQ-DA6W2BS_.js → sequenceDiagram-DBY2YBRQ-kqJzXbwu.js} +1 -1
  148. package/dist/assets/service-apps-panel-iLLEByRF.js +1 -0
  149. package/dist/assets/{settings-2-CE3ELQyk.js → settings-2-IodCcaXd.js} +1 -1
  150. package/dist/assets/{sizeCapture-X5ZJPWSS-T_q_d_VW.js → sizeCapture-X5ZJPWSS-D9ISogq1.js} +1 -1
  151. package/dist/assets/{src-CYpUlx-4.js → src-Bc0PoUJ1.js} +1 -1
  152. package/dist/assets/{stateDiagram-2N3HPSRC-mi8z2G0a.js → stateDiagram-2N3HPSRC-CqH5xc9W.js} +1 -1
  153. package/dist/assets/stateDiagram-v2-6OUMAXLB-CcOGfDdx.js +1 -0
  154. package/dist/assets/status-dot-DUYSKRCU.js +1 -0
  155. package/dist/assets/{swimlanes-5IMT3BWC-DkBEhWE4.js → swimlanes-5IMT3BWC-mwejV-rW.js} +2 -2
  156. package/dist/assets/swimlanesDiagram-G3AALYLV-BMI2k8RZ.js +8 -0
  157. package/dist/assets/tag-chip-CQU51ST3.js +1 -0
  158. package/dist/assets/theme-provider-D-zZkXxS.js +1 -0
  159. package/dist/assets/{timeline-definition-FHXFAJF6-BoFmqBw1.js → timeline-definition-FHXFAJF6-CuikIDlX.js} +1 -1
  160. package/dist/assets/trash-2-BDdqDh6E.js +1 -0
  161. package/dist/assets/treeView-QDETBFTQ-C0_07QI1.js +1 -0
  162. package/dist/assets/treemap-6X3UGDF4-Djpx6ccG.js +1 -0
  163. package/dist/assets/use-config-Bxx7DdaL.js +1 -0
  164. package/dist/assets/{use-desktop-capabilities-BkuRd2cY.js → use-desktop-capabilities-BTgdFgJy.js} +1 -1
  165. package/dist/assets/use-viewport-layout-CDcca0YL.js +1 -0
  166. package/dist/assets/{vennDiagram-L72KCM5P-BlZ3Or5U.js → vennDiagram-L72KCM5P-BD0P0qHh.js} +1 -1
  167. package/dist/assets/wardley-OPB4EBWU-DZVFxu81.js +1 -0
  168. package/dist/assets/{wardleyDiagram-EHGQE667-yDfr33i3.js → wardleyDiagram-EHGQE667-C6ma3t5D.js} +1 -1
  169. package/dist/assets/x-LUUwl8rK.js +1 -0
  170. package/dist/assets/{xychartDiagram-FW5EYKEG-mIXwIGAQ.js → xychartDiagram-FW5EYKEG-D7E40NBk.js} +1 -1
  171. package/dist/index.html +37 -54
  172. package/dist/panel-standalone.html +11 -15
  173. package/package.json +5 -5
  174. package/src/app/components/layout/__tests__/app-layout.test.tsx +8 -0
  175. package/src/app/components/layout/app-layout.tsx +18 -46
  176. package/src/app/configs/__tests__/app-navigation.config.test.ts +4 -0
  177. package/src/app/configs/app-navigation.config.ts +2 -0
  178. package/src/app/configs/page-resource-renderers.config.ts +13 -0
  179. package/src/app/hooks/__tests__/use-app-event-consumers.test.ts +66 -3
  180. package/src/app/hooks/use-app-event-consumers.ts +5 -0
  181. package/src/app/index.tsx +4 -0
  182. package/src/app/presenters/app.presenter.ts +13 -2
  183. package/src/features/agents/components/__tests__/agents-page.test.tsx +4 -0
  184. package/src/features/agents/components/agent-details-dialog.tsx +3 -0
  185. package/src/features/agents/components/agents-page.tsx +7 -3
  186. package/src/features/apps/components/app-package-card.tsx +2 -2
  187. package/src/features/chat/components/conversation/chat-conversation-content.tsx +32 -19
  188. package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +1 -0
  189. package/src/features/chat/components/conversation/chat-conversation-header.tsx +1 -1
  190. package/src/features/chat/components/conversation/chat-conversation-panel.tsx +2 -2
  191. package/src/features/chat/components/conversation/chat-conversation-workspace-section.tsx +1 -0
  192. package/src/features/chat/components/layout/__tests__/chat-page-shell.test.tsx +7 -6
  193. package/src/features/chat/components/layout/__tests__/chat-sidebar-toolbar.test.tsx +14 -12
  194. package/src/features/chat/components/layout/chat-page-shell.tsx +33 -64
  195. package/src/features/chat/components/layout/chat-sidebar-desktop-layout.tsx +8 -4
  196. package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +64 -256
  197. package/src/features/chat/components/layout/chat-sidebar.tsx +8 -30
  198. package/src/features/chat/components/providers/chat-runtime.provider.tsx +62 -0
  199. package/src/features/chat/features/conversation/components/__tests__/floating-session-conversation.test.tsx +70 -0
  200. package/src/features/chat/features/conversation/components/floating-session-conversation.tsx +27 -0
  201. package/src/features/chat/features/conversation/components/session-conversation-area.tsx +1 -0
  202. package/src/features/chat/features/conversation/components/session-conversation-panel-tab.tsx +25 -0
  203. package/src/features/chat/features/conversation/hooks/use-chat-composer-reference-intent.ts +2 -1
  204. package/src/features/chat/features/message/components/__tests__/chat-inline-panel-app-card.test.tsx +2 -1
  205. package/src/features/chat/features/message/components/__tests__/chat-message-assistant-header.container.test.tsx +3 -0
  206. package/src/features/chat/features/message/components/__tests__/chat-message-list-skill-preview.container.test.tsx +3 -0
  207. package/src/features/chat/features/message/components/__tests__/chat-message-list.container.test.tsx +3 -0
  208. package/src/features/chat/features/message/hooks/use-chat-inline-token-actions.ts +7 -3
  209. package/src/features/chat/features/ncp/hooks/__tests__/use-ncp-session-list-view.test.tsx +44 -1
  210. package/src/features/chat/features/ncp/hooks/use-ncp-child-session-tabs-view.ts +10 -2
  211. package/src/features/chat/features/ncp/hooks/use-ncp-session-list-view.ts +6 -2
  212. package/src/features/chat/features/session/components/__tests__/chat-sidebar-session-item.test.tsx +20 -0
  213. package/src/features/chat/features/session/components/chat-mobile-session-row.tsx +61 -0
  214. package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +0 -35
  215. package/src/features/chat/features/session/components/chat-sidebar-session-entry.tsx +2 -0
  216. package/src/features/chat/features/session/components/chat-sidebar-session-item.tsx +13 -5
  217. package/src/features/chat/features/session/components/chat-sidebar-session-list.tsx +5 -3
  218. package/src/features/chat/features/session/components/session-header/__tests__/chat-session-header-actions.test.tsx +8 -0
  219. package/src/features/chat/features/session/components/session-header/chat-session-header-actions.tsx +3 -0
  220. package/src/features/chat/features/session/components/session-header/chat-session-more-actions-menu.tsx +6 -0
  221. package/src/features/chat/features/session/utils/chat-session-route.utils.ts +12 -0
  222. package/src/features/chat/features/workspace/components/__tests__/chat-session-child-sessions.test.tsx +28 -0
  223. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-file-preview.test.tsx +9 -0
  224. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel-content.test.tsx +6 -2
  225. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel.test.tsx +49 -12
  226. package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +13 -6
  227. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +6 -0
  228. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-nav.tsx +21 -36
  229. package/src/features/chat/features/workspace/components/chat-session-workspace-panel.tsx +40 -31
  230. package/src/features/chat/features/workspace/components/child-sessions/chat-session-child-sessions.tsx +6 -1
  231. package/src/features/chat/features/workspace/components/project-files/workspace-directory-tree.tsx +2 -2
  232. package/src/features/chat/features/workspace/components/project-files/workspace-project-files-toolbar.tsx +2 -2
  233. package/src/features/chat/features/workspace/utils/__tests__/chat-workspace-panel-view-model.utils.test.ts +27 -0
  234. package/src/features/chat/features/workspace/utils/__tests__/workspace-file-panel-route.utils.test.ts +94 -0
  235. package/src/features/chat/features/workspace/utils/chat-workspace-file-tab-persistence.utils.ts +2 -0
  236. package/src/features/chat/features/workspace/utils/chat-workspace-file-tab.utils.ts +15 -0
  237. package/src/features/chat/features/workspace/utils/chat-workspace-panel-view-model.utils.ts +11 -0
  238. package/src/features/chat/features/workspace/utils/workspace-file-panel-route.utils.ts +147 -0
  239. package/src/features/chat/index.ts +20 -4
  240. package/src/features/chat/managers/__tests__/chat-completion-notification.manager.test.ts +8 -0
  241. package/src/features/chat/managers/__tests__/chat-thread-workspace.manager.test.ts +7 -2
  242. package/src/features/chat/managers/__tests__/session-surface.manager.test.ts +45 -0
  243. package/src/features/chat/managers/chat-completion-notification.manager.ts +5 -0
  244. package/src/features/chat/managers/chat-composer-intent.manager.ts +16 -0
  245. package/src/features/chat/managers/chat-thread.manager.ts +18 -27
  246. package/src/features/chat/managers/session-surface.manager.ts +46 -0
  247. package/src/features/chat/pages/__tests__/ncp-chat-page.test.tsx +23 -5
  248. package/src/features/chat/pages/ncp-chat-page.tsx +6 -86
  249. package/src/features/chat/presenters/chat.presenter.ts +2 -1
  250. package/src/features/chat/stores/__tests__/chat-thread.store.test.ts +2 -2
  251. package/src/features/chat/stores/chat-session-list.store.ts +27 -1
  252. package/src/features/chat/stores/chat-thread.store.ts +7 -1
  253. package/src/features/chat/stores/floating-session.store.ts +11 -0
  254. package/src/features/cron/components/__tests__/cron-config.test.tsx +4 -0
  255. package/src/features/cron/components/cron-job-detail-dialog.tsx +3 -1
  256. package/src/features/cron/components/cron-job-row.tsx +5 -1
  257. package/src/features/inbox/components/inbox-reader-dialog.test.tsx +3 -0
  258. package/src/features/inbox/components/inbox-reader-dialog.tsx +3 -0
  259. package/src/features/inbox/pages/inbox-page.test.ts +3 -0
  260. package/src/features/inbox/pages/inbox-page.tsx +3 -0
  261. package/src/features/marketplace/components/__tests__/marketplace-page-detail.test.tsx +5 -1
  262. package/src/features/marketplace/components/__tests__/marketplace-page.test.tsx +3 -0
  263. package/src/features/marketplace/components/curated-shelves/__tests__/marketplace-curated-scene-route.test.tsx +2 -0
  264. package/src/features/marketplace/components/marketplace-list-card.tsx +4 -0
  265. package/src/features/marketplace/components/mcp/__tests__/mcp-marketplace-page.test.tsx +2 -0
  266. package/src/features/marketplace/components/mcp/mcp-marketplace-card.tsx +3 -0
  267. package/src/features/notifications/components/__tests__/app-notification-toast.test.tsx +19 -0
  268. package/src/features/notifications/components/app-notification-toast.tsx +33 -15
  269. package/src/features/notifications/managers/app-notification.manager.ts +2 -0
  270. package/src/features/panel-apps/components/__tests__/panel-app-list-item.test.tsx +11 -4
  271. package/src/features/panel-apps/components/__tests__/panel-app-toolbar.test.tsx +11 -5
  272. package/src/features/panel-apps/components/panel-app-main-sidebar-menu-item.tsx +5 -38
  273. package/src/features/panel-apps/index.ts +1 -1
  274. package/src/features/projects/components/project-materials.test.tsx +2 -0
  275. package/src/features/projects/components/project-skills.tsx +7 -3
  276. package/src/features/projects/components/work/project-work-item-drawer.test.tsx +2 -0
  277. package/src/features/projects/components/work/project-work-item-drawer.tsx +3 -1
  278. package/src/features/right-panel-resources/components/__tests__/page-resource-icon.test.tsx +67 -0
  279. package/src/features/right-panel-resources/components/__tests__/page-resource-sidebar-nav.test.tsx +158 -0
  280. package/src/features/right-panel-resources/components/__tests__/system-object-resource.test.tsx +42 -0
  281. package/src/features/right-panel-resources/components/current-page-actions.tsx +36 -0
  282. package/src/features/right-panel-resources/components/page-resource-actions-menu.tsx +71 -0
  283. package/src/features/right-panel-resources/components/page-resource-icon.tsx +245 -0
  284. package/src/features/right-panel-resources/components/page-resource-sidebar-nav.tsx +122 -0
  285. package/src/features/right-panel-resources/components/system-object-resource.tsx +100 -0
  286. package/src/features/right-panel-resources/components/workspace-file-resource.tsx +56 -0
  287. package/src/features/right-panel-resources/configs/right-panel-resource-routes.config.ts +46 -3
  288. package/src/features/right-panel-resources/hooks/use-page-resource-actions.ts +137 -0
  289. package/src/features/right-panel-resources/index.ts +22 -8
  290. package/src/features/right-panel-resources/managers/__tests__/page-resource.manager.test.ts +149 -0
  291. package/src/features/right-panel-resources/managers/page-resource.manager.ts +342 -0
  292. package/src/features/right-panel-resources/pages/resource-page.tsx +114 -0
  293. package/src/features/right-panel-resources/stores/page-navigation.store.ts +55 -0
  294. package/src/features/right-panel-resources/types/page-resource.types.ts +11 -0
  295. package/src/features/right-panel-resources/utils/__tests__/right-panel-resource-route-resolver.utils.test.ts +10 -0
  296. package/src/features/right-panel-resources/utils/page-resource-identity.utils.ts +61 -0
  297. package/src/features/right-panel-resources/utils/right-panel-resource-uri.utils.ts +2 -6
  298. package/src/features/service-apps/components/__tests__/service-apps-panel.test.tsx +2 -0
  299. package/src/features/service-apps/components/service-app-list-item.tsx +5 -1
  300. package/src/features/settings/pages/providers-config-page.tsx +2 -2
  301. package/src/features/side-dock/components/__tests__/side-dock.test.tsx +9 -8
  302. package/src/features/side-dock/components/side-dock.tsx +14 -47
  303. package/src/features/side-dock/managers/side-dock.manager.ts +2 -0
  304. package/src/platforms/desktop/components/__tests__/desktop-app-shell.test.tsx +3 -0
  305. package/src/platforms/desktop/components/desktop-app-shell.tsx +5 -14
  306. package/src/platforms/mobile/components/__tests__/mobile-app-shell.test.tsx +1 -0
  307. package/src/platforms/mobile/components/__tests__/mobile-bottom-nav.test.tsx +3 -2
  308. package/src/platforms/mobile/components/mobile-app-shell.tsx +5 -4
  309. package/src/platforms/mobile/components/mobile-bottom-nav.tsx +7 -7
  310. package/src/platforms/mobile/components/mobile-topbar.tsx +4 -4
  311. package/src/shared/components/doc-browser/__tests__/doc-browser-context.test.tsx +4 -3
  312. package/src/shared/components/doc-browser/__tests__/doc-browser-tab-strip.test.tsx +0 -5
  313. package/src/shared/components/doc-browser/__tests__/doc-browser.test.tsx +57 -73
  314. package/src/shared/components/doc-browser/__tests__/resource-link-interceptor.test.tsx +104 -0
  315. package/src/shared/components/doc-browser/doc-browser-context.tsx +5 -1
  316. package/src/shared/components/doc-browser/doc-browser-panel-parts.tsx +1 -1
  317. package/src/shared/components/doc-browser/doc-browser-tab-strip.tsx +6 -118
  318. package/src/shared/components/doc-browser/doc-browser.tsx +30 -194
  319. package/src/shared/components/doc-browser/hooks/use-doc-browser-scroll-restoration.ts +1 -1
  320. package/src/shared/components/doc-browser/managers/doc-browser.manager.ts +11 -1
  321. package/src/shared/components/doc-browser/stores/doc-browser.store.ts +3 -7
  322. package/src/shared/components/doc-browser/types/doc-browser.types.ts +8 -1
  323. package/src/shared/components/doc-browser/use-doc-link-interceptor.ts +30 -32
  324. package/src/shared/components/doc-browser/utils/doc-browser-state.utils.ts +6 -6
  325. package/src/shared/components/ui/context-menu/__tests__/context-menu.test.tsx +22 -0
  326. package/src/shared/components/ui/context-menu/context-menu.tsx +18 -10
  327. package/src/shared/components/workbench/__tests__/workbench-surface.manager.test.ts +70 -0
  328. package/src/shared/components/workbench/__tests__/workbench-surface.test.tsx +111 -0
  329. package/src/shared/components/workbench/managers/workbench-surface.manager.ts +120 -0
  330. package/src/shared/components/workbench/stores/workbench-surface.store.ts +83 -0
  331. package/src/shared/components/workbench/types/workbench-surface.types.ts +32 -0
  332. package/src/shared/components/workbench/utils/workbench-surface-geometry.utils.ts +46 -0
  333. package/src/shared/components/workbench/workbench-surface-toolbar.tsx +102 -0
  334. package/src/shared/components/workbench/workbench-surface.tsx +401 -0
  335. package/src/shared/hooks/use-panel-app-scroll-restoration.test.tsx +19 -0
  336. package/src/shared/hooks/use-panel-app-scroll-restoration.ts +8 -6
  337. package/src/shared/hooks/use-scroll-restoration.test.tsx +39 -2
  338. package/src/shared/hooks/use-scroll-restoration.ts +33 -33
  339. package/src/shared/lib/api/marketplace.types.ts +1 -0
  340. package/src/shared/lib/i18n/locales/en-US/chat.json +38 -0
  341. package/src/shared/lib/i18n/locales/en-US/doc-browser.json +1 -1
  342. package/src/shared/lib/i18n/locales/zh-CN/chat.json +38 -0
  343. package/src/shared/lib/navigation-history/index.ts +1 -0
  344. package/src/shared/lib/navigation-history/navigation-history.utils.ts +1 -1
  345. package/src/shared/lib/navigation-history/scroll-restoration.manager.test.ts +11 -0
  346. package/src/shared/lib/navigation-history/scroll-restoration.manager.ts +36 -7
  347. package/src/shared/lib/navigation-history/view-memory-storage.store.test.ts +37 -0
  348. package/src/shared/lib/navigation-history/view-memory-storage.store.ts +21 -0
  349. package/src/shared/lib/ui-document-title/index.ts +1 -0
  350. package/dist/assets/account-panel-BXTCFv7d.js +0 -1
  351. package/dist/assets/api-DqzQ-_3w.js +0 -13
  352. package/dist/assets/app-data-C54N2p8b.js +0 -1
  353. package/dist/assets/app-presenter-provider-V0xnU_Wb.js +0 -115
  354. package/dist/assets/appearance-settings-page-83T2AtVm.js +0 -1
  355. package/dist/assets/architecture-TIHT7OUA-DEt0Abz9.js +0 -1
  356. package/dist/assets/boxes-D6uPnkGo.js +0 -1
  357. package/dist/assets/card-BhfAZv5L.js +0 -1
  358. package/dist/assets/channel-CxQkbwRD.js +0 -1
  359. package/dist/assets/channels-list-page-Bv7CVSqV.js +0 -8
  360. package/dist/assets/chevron-down-BL-yMYcX.js +0 -1
  361. package/dist/assets/chunk-2Q5K7J3B-ClVhziok.js +0 -1
  362. package/dist/assets/chunk-VAUOI2AC-DZQxkIsv.js +0 -1
  363. package/dist/assets/chunk-XXDRQBXY-BkExtw5C.js +0 -1
  364. package/dist/assets/circle-alert-lSa3LRvS.js +0 -1
  365. package/dist/assets/classDiagram-OUVF2IWQ-Bd6apBb-.js +0 -1
  366. package/dist/assets/classDiagram-v2-EOCWNBFH-CYxUZGCI.js +0 -1
  367. package/dist/assets/client-BtGBwLTs.js +0 -1
  368. package/dist/assets/config-split-page-DqAXKLmG.js +0 -1
  369. package/dist/assets/confirm-dialog-BTKCWMn6.js +0 -1
  370. package/dist/assets/createLucideIcon-BNKf0_kc.js +0 -1
  371. package/dist/assets/cynefin-VYW2F7L2-CV0bFLH9.js +0 -1
  372. package/dist/assets/desktop-capabilities-page-zLzCSB7A.js +0 -1
  373. package/dist/assets/desktop-update-config-PmofcFf6.js +0 -1
  374. package/dist/assets/dialog-Xe73hpQz.js +0 -5
  375. package/dist/assets/dist-BiIcnf9j.js +0 -1
  376. package/dist/assets/dist-C5I0v8Qn.js +0 -1
  377. package/dist/assets/dist-czPa8xFO.js +0 -1
  378. package/dist/assets/doc-browser-BJrre2S_.js +0 -1
  379. package/dist/assets/doc-browser-BPqA-zQx.js +0 -1
  380. package/dist/assets/doc-browser-context-TILuCY5c.js +0 -1
  381. package/dist/assets/ellipsis-C5YXdOUx.js +0 -1
  382. package/dist/assets/es2015-cuwbYI-l.js +0 -41
  383. package/dist/assets/eventmodeling-45OFAUF4-BzkLWWdP.js +0 -1
  384. package/dist/assets/extensions-CVUFK6Jj.js +0 -1
  385. package/dist/assets/flowDiagram-23GEKE2U-ukkCsB0j.js +0 -1
  386. package/dist/assets/form-actions-BRESe-m_.js +0 -1
  387. package/dist/assets/gitGraph-TEB2WS4Q-BYFhT0Q5.js +0 -1
  388. package/dist/assets/i18n-provider-BPRq6S7O.js +0 -1
  389. package/dist/assets/info-DKCQHKI2-CTmlJdcH.js +0 -1
  390. package/dist/assets/katex-DbZC06Q5.js +0 -1
  391. package/dist/assets/keyboard-shortcuts-settings-page-CkQbSKwI.js +0 -1
  392. package/dist/assets/loader-circle-K1BDdHR5.js +0 -1
  393. package/dist/assets/login-page-Dlyvp-81.js +0 -1
  394. package/dist/assets/login-page-f8qQ4xKY.js +0 -1
  395. package/dist/assets/logo-badge-C-5-zim6.js +0 -1
  396. package/dist/assets/main-D2dWy8fM.css +0 -1
  397. package/dist/assets/main-i18n-catalog.config-DZ-5ollN.js +0 -1
  398. package/dist/assets/main-ky5Efhq1.js +0 -2
  399. package/dist/assets/mcp-marketplace-page-FfIfEo6w.js +0 -10
  400. package/dist/assets/mcp-marketplace-page-sH7VptN_.js +0 -1
  401. package/dist/assets/model-config-page-Bcm6-pCX.js +0 -1
  402. package/dist/assets/navigation-link-BAQjgx2F.js +0 -3
  403. package/dist/assets/packet-7NZHBO7P-BbrI0ZlN.js +0 -1
  404. package/dist/assets/panel-app-i18n-catalog.config-p3qAY_Eq.js +0 -1
  405. package/dist/assets/panelStandalone-By-6dDXS.js +0 -2
  406. package/dist/assets/pie-RZYD4A2V-B7zE1ZIr.js +0 -1
  407. package/dist/assets/plus-LA8-jpxP.js +0 -1
  408. package/dist/assets/popover-NkrFlWHp.js +0 -1
  409. package/dist/assets/privacy-settings-page-B1sHLAc1.js +0 -1
  410. package/dist/assets/projects-O3GTERwP.js +0 -1
  411. package/dist/assets/provider-models-hrHMcHqg.js +0 -1
  412. package/dist/assets/provider-scoped-model-input-BQsugx1v.js +0 -1
  413. package/dist/assets/providers-config-page-BDEdHJbw.js +0 -1
  414. package/dist/assets/pwa-D_nZUwG0.js +0 -1
  415. package/dist/assets/radar-I7S5WNFK-1X_q11Ed.js +0 -1
  416. package/dist/assets/railroad-3IZDKUUU-CIXnuFyE.js +0 -1
  417. package/dist/assets/railroad-abnf-AHOZXSZD-D6ImKl2r.js +0 -1
  418. package/dist/assets/railroad-ebnf-EBAXGLYW-2j9d3twU.js +0 -1
  419. package/dist/assets/railroad-peg-LSFZ7HO6-DMVaJGbm.js +0 -1
  420. package/dist/assets/remote-CFWp4wyH.js +0 -1
  421. package/dist/assets/runtime-config-page-BHTKwgDi.js +0 -1
  422. package/dist/assets/search-CUe41wjm.js +0 -1
  423. package/dist/assets/search-config-page-DWKlMHgH.js +0 -1
  424. package/dist/assets/secrets-config-page-DiQL088Y.js +0 -3
  425. package/dist/assets/security-config-DmTDKKY4.js +0 -1
  426. package/dist/assets/select-CG5YWnwe.js +0 -1
  427. package/dist/assets/service-apps-panel-CEnyYsQp.js +0 -1
  428. package/dist/assets/skeleton-Drvn83YW.js +0 -1
  429. package/dist/assets/stateDiagram-v2-6OUMAXLB-OlIMT57r.js +0 -1
  430. package/dist/assets/swimlanesDiagram-G3AALYLV-sLThrh07.js +0 -8
  431. package/dist/assets/tabs-BuE0qKMh.js +0 -1
  432. package/dist/assets/tag-chip-B1AYPOKL.js +0 -1
  433. package/dist/assets/theme-provider-DzvAi3pe.js +0 -1
  434. package/dist/assets/tooltip-DYcuWhuP.js +0 -1
  435. package/dist/assets/trash-2-BPPYt2NV.js +0 -1
  436. package/dist/assets/treeView-QDETBFTQ-CCFyazDE.js +0 -1
  437. package/dist/assets/treemap-6X3UGDF4-D6wvq1Hz.js +0 -1
  438. package/dist/assets/use-config-BEdbtpD4.js +0 -1
  439. package/dist/assets/use-panel-app-scroll-restoration-ZnicIfo3.js +0 -1
  440. package/dist/assets/use-viewport-layout-BS18drMT.js +0 -1
  441. package/dist/assets/utils-CBZPzC_b.js +0 -8
  442. package/dist/assets/wardley-OPB4EBWU-BRzaRyFf.js +0 -1
  443. package/dist/assets/x-DdXOqLnX.js +0 -1
  444. package/src/features/panel-apps/components/__tests__/panel-app-main-sidebar-nav.test.tsx +0 -219
  445. package/src/features/panel-apps/components/panel-app-main-sidebar-nav.tsx +0 -258
  446. package/src/shared/components/doc-browser/utils/doc-browser-floating-panel.utils.ts +0 -83
  447. /package/dist/assets/{array-D0DyKZdT.js → array-B0sEvCP9.js} +0 -0
  448. /package/dist/assets/{chunk-KEIR6QF5-CuZFOa6q.js → chunk-KEIR6QF5-BeO7fxDQ.js} +0 -0
  449. /package/dist/assets/{chunk-Y2CYZVJY-Frut-1TF.js → chunk-Y2CYZVJY-JQfgEV36.js} +0 -0
  450. /package/dist/assets/{config-hints-B_C9DAp5.js → config-hints-D3OuwoEY.js} +0 -0
  451. /package/dist/assets/{cytoscape.esm-BibuhnZD.js → cytoscape.esm-CzJ9uXgi.js} +0 -0
  452. /package/dist/assets/{defaultLocale-q7sRUXPc.js → defaultLocale-USmzX3VG.js} +0 -0
  453. /package/dist/assets/{dist-DhMddrrH.js → dist-BYF6XVna.js} +0 -0
  454. /package/dist/assets/{graphlib-BM63WsW3.js → graphlib-DEFMkHdW.js} +0 -0
  455. /package/dist/assets/{host-capabilities-B107nwS3.js → host-capabilities-C0MmWd3M.js} +0 -0
  456. /package/dist/assets/{init-CRMkf9sL.js → init-04ErALoz.js} +0 -0
  457. /package/dist/assets/{jszip.min-6thm2J_a.js → jszip.min-BnQ5NRy2.js} +0 -0
  458. /package/dist/assets/{katex-B26hhTOT.js → katex-CsAM73R9.js} +0 -0
  459. /package/dist/assets/{middleware-0o3JF3tS.js → middleware-CAXxl-af.js} +0 -0
  460. /package/dist/assets/{panel-app-B39rJPj8.js → panel-app-2EACRB8p.js} +0 -0
  461. /package/dist/assets/{path-BFMmafCM.js → path-CzxQ9n2G.js} +0 -0
  462. /package/dist/assets/{rough.esm-5Tjchx1D.js → rough.esm-pT9fdsW3.js} +0 -0
  463. /package/dist/assets/{xlsx-BC8ibjXK.js → xlsx-BRpCSiE4.js} +0 -0
@@ -18,18 +18,11 @@ import {
18
18
  DocBrowserFrameContent,
19
19
  } from './doc-browser-panel-parts';
20
20
  import { DocBrowserTabStrip } from './doc-browser-tab-strip';
21
- import {
22
- createInitialFloatingPanelRect,
23
- moveFloatingPanelRect,
24
- resizeFloatingPanelRect,
25
- type FloatingPanelRect,
26
- type FloatingPanelResizeEdge,
27
- } from './utils/doc-browser-floating-panel.utils';
28
- import { ResizableRightPanel } from '@/shared/components/resizable-right-panel/resizable-right-panel';
29
- import { cn } from '@/shared/lib/utils';
21
+ import { WorkbenchSurface } from '@/shared/components/workbench/workbench-surface';
22
+ import { GLOBAL_WORKBENCH_SURFACE } from '@/shared/components/workbench/types/workbench-surface.types';
23
+ import { getAppPresenter } from '@/app/presenters/app.presenter';
30
24
  import { t } from '@/shared/lib/i18n';
31
25
  import type { ContextMenuGroup } from '@/shared/components/ui/context-menu/context-menu';
32
- import { GripVertical } from 'lucide-react';
33
26
  import {
34
27
  DOC_BROWSER_DOCKED_MAX_WIDTH,
35
28
  DOC_BROWSER_DOCKED_MIN_WIDTH,
@@ -44,16 +37,8 @@ type DocBrowserProps = {
44
37
 
45
38
  export type DocBrowserTabMenuGroupsResolver = NonNullable<DocBrowserProps['getTabMenuGroups']>;
46
39
 
47
- type FloatingPanelInteraction = {
48
- startX: number;
49
- startY: number;
50
- startRect: FloatingPanelRect;
51
- } & (
52
- | { kind: 'drag' }
53
- | { kind: 'resize'; edge: FloatingPanelResizeEdge }
54
- );
55
40
 
56
- const DEFAULT_DOCS_IFRAME_SANDBOX = 'allow-same-origin allow-scripts allow-popups allow-forms';
41
+
57
42
 
58
43
  function resolveContentUrlInput(input: string, currentUrl: string): string {
59
44
  if (input.startsWith('/')) {
@@ -72,20 +57,6 @@ function resolveContentUrlInput(input: string, currentUrl: string): string {
72
57
  return `https://${input}`;
73
58
  }
74
59
 
75
- function resolveIframeSandbox(
76
- customRenderer: DocBrowserCustomTabRenderers[string] | undefined,
77
- currentTab: DocBrowserTab | undefined,
78
- ): string | undefined {
79
- if (!currentTab) {
80
- return DEFAULT_DOCS_IFRAME_SANDBOX;
81
- }
82
- const customSandbox = customRenderer?.getIframeSandbox?.(currentTab);
83
- if (customSandbox !== undefined) {
84
- return customSandbox;
85
- }
86
- return currentTab.kind === 'content' ? undefined : DEFAULT_DOCS_IFRAME_SANDBOX;
87
- }
88
-
89
60
  function useDocBrowserDockAction(
90
61
  dockControls: DocBrowserDockControls | undefined,
91
62
  currentTab: DocBrowserTab | undefined,
@@ -172,7 +143,6 @@ export function DocBrowser({
172
143
  }: DocBrowserProps) {
173
144
  const {
174
145
  isOpen,
175
- mode,
176
146
  dockedWidth,
177
147
  tabs,
178
148
  activeTabId,
@@ -183,7 +153,6 @@ export function DocBrowser({
183
153
  openTarget,
184
154
  openNewTab,
185
155
  close,
186
- toggleMode,
187
156
  setDockedWidth,
188
157
  goBack,
189
158
  goForward,
@@ -194,8 +163,6 @@ export function DocBrowser({
194
163
  } = useDocBrowser();
195
164
 
196
165
  const [iframeReloadVersion, setIframeReloadVersion] = useState(0);
197
- const [floatRect, setFloatRect] = useState<FloatingPanelRect>(createInitialFloatingPanelRect);
198
- const [floatInteraction, setFloatInteraction] = useState<FloatingPanelInteraction | null>(null);
199
166
  const iframeRef = useRef<HTMLIFrameElement>(null);
200
167
  const currentUrl = currentTab?.currentUrl ?? getDefaultDocsUrl();
201
168
  const navVersion = currentTab?.navVersion ?? 0;
@@ -251,7 +218,7 @@ export function DocBrowser({
251
218
 
252
219
  useEffect(() => {
253
220
  const handler = (e: MessageEvent) => {
254
- if (!isDocsTab) {
221
+ if (!isDocsTab || e.source !== iframeRef.current?.contentWindow) {
255
222
  return;
256
223
  }
257
224
  if (e.data?.type === 'docs-route-change' && typeof e.data.url === 'string') {
@@ -283,65 +250,13 @@ export function DocBrowser({
283
250
  return () => window.removeEventListener('message', handler);
284
251
  }, [currentTab, customRenderer, iframeInstanceId]);
285
252
 
286
- const startFloatDrag = useCallback((event: React.PointerEvent<HTMLElement>) => {
287
- event.preventDefault();
288
- setFloatInteraction({
289
- kind: 'drag',
290
- startX: event.clientX,
291
- startY: event.clientY,
292
- startRect: floatRect,
293
- });
294
- }, [floatRect]);
295
-
296
- const startFloatResize = useCallback((edge: FloatingPanelResizeEdge) => (event: React.PointerEvent<HTMLElement>) => {
297
- event.preventDefault();
298
- event.stopPropagation();
299
- setFloatInteraction({
300
- kind: 'resize',
301
- edge,
302
- startX: event.clientX,
303
- startY: event.clientY,
304
- startRect: floatRect,
305
- });
306
- }, [floatRect]);
307
-
308
- useEffect(() => {
309
- if (!floatInteraction) return;
310
-
311
- const onMove = (event: PointerEvent) => {
312
- const { startRect, startX, startY } = floatInteraction;
313
- const dx = event.clientX - startX;
314
- const dy = event.clientY - startY;
315
-
316
- if (floatInteraction.kind === 'drag') {
317
- setFloatRect(moveFloatingPanelRect(startRect, dx, dy));
318
- return;
319
- }
320
-
321
- setFloatRect(resizeFloatingPanelRect(floatInteraction.edge, startRect, dx, dy));
322
- };
323
-
324
- const onEnd = () => setFloatInteraction(null);
325
-
326
- window.addEventListener('pointermove', onMove);
327
- window.addEventListener('pointerup', onEnd);
328
- window.addEventListener('pointercancel', onEnd);
329
- return () => {
330
- window.removeEventListener('pointermove', onMove);
331
- window.removeEventListener('pointerup', onEnd);
332
- window.removeEventListener('pointercancel', onEnd);
333
- };
334
- }, [floatInteraction]);
335
-
336
253
  const refreshIframe = useCallback(() => {
337
254
  setIframeReloadVersion((version) => version + 1);
338
255
  }, []);
339
256
 
340
257
  const handleToggleDock = useDocBrowserDockAction(dockControls, currentTab, dockState);
341
258
 
342
- if (!isOpen) return null;
343
259
 
344
- const isDocked = mode === 'docked';
345
260
  const isFullscreen = displayMode === 'fullscreen';
346
261
  const customRenderParams = currentTab ? {
347
262
  currentUrl,
@@ -354,29 +269,11 @@ export function DocBrowser({
354
269
  const customContent = customRenderParams
355
270
  ? customRenderer?.renderContent?.(customRenderParams) ?? (isHomeTab ? <DocBrowserHomePage /> : null)
356
271
  : null;
357
- const iframeSandbox = resolveIframeSandbox(customRenderer, currentTab);
272
+ const iframeSandbox = currentTab ? customRenderer?.getIframeSandbox?.(currentTab) : undefined;
358
273
 
359
274
  const panelContent = (
360
275
  <>
361
- <DocBrowserTabStrip
362
- tabs={tabs}
363
- activeTabId={activeTabId}
364
- canGoBack={canGoBack}
365
- canGoForward={canGoForward}
366
- dockState={dockState}
367
- isDocked={isDocked}
368
- isFullscreen={isFullscreen}
369
- onGoBack={goBack}
370
- onGoForward={goForward}
371
- onOpenNewTab={openNewTab}
372
- onToggleDock={handleToggleDock}
373
- onSetActiveTab={setActiveTab}
374
- onCloseTab={closeTab}
375
- onClose={close}
376
- onDragStart={startFloatDrag}
377
- onToggleMode={toggleMode}
378
- getTabMenuGroups={getTabMenuGroups}
379
- />
276
+
380
277
 
381
278
  <DocBrowserAddressToolbar
382
279
  isVisible={isAddressToolbarTab}
@@ -396,8 +293,8 @@ export function DocBrowser({
396
293
  iframeRef={iframeRef}
397
294
  iframeInstanceId={iframeInstanceId}
398
295
  iframeSandbox={iframeSandbox}
399
- isDragging={floatInteraction?.kind === 'drag'}
400
- isResizing={floatInteraction?.kind === 'resize'}
296
+ isDragging={false}
297
+ isResizing={false}
401
298
  onIframeLoad={restoreScroll}
402
299
  onIframePointerOver={customRenderer?.onIframePointerOver}
403
300
  />
@@ -406,89 +303,28 @@ export function DocBrowser({
406
303
  </>
407
304
  );
408
305
 
409
- if (isDocked && !isFullscreen) {
410
- return (
411
- <ResizableRightPanel
412
- data-testid="doc-browser-panel"
413
- data-theme-surface="doc-browser"
414
- defaultWidth={dockedWidth}
415
- width={dockedWidth}
416
- minWidth={DOC_BROWSER_DOCKED_MIN_WIDTH}
417
- maxWidth={DOC_BROWSER_DOCKED_MAX_WIDTH}
418
- onWidthCommit={setDockedWidth}
419
- >
420
- {panelContent}
421
- </ResizableRightPanel>
422
- );
423
- }
424
-
425
306
  return (
426
- <div
427
- data-testid="doc-browser-panel"
428
- data-theme-surface="doc-browser"
429
- className={cn(
430
- 'relative flex flex-col overflow-hidden bg-card text-card-foreground',
431
- isFullscreen
432
- ? 'fixed inset-0 z-[var(--z-floating-panel)] h-[100dvh] w-screen rounded-none border-0 shadow-2xl'
433
- : 'rounded-2xl border border-border shadow-2xl',
434
- )}
435
- style={
436
- isFullscreen
437
- ? undefined
438
- : {
439
- position: 'fixed',
440
- left: floatRect.x,
441
- top: floatRect.y,
442
- width: floatRect.w,
443
- height: floatRect.h,
444
- zIndex: 'var(--z-floating-panel)',
445
- }
446
- }
447
- >
307
+ <WorkbenchSurface id={GLOBAL_WORKBENCH_SURFACE} manager={getAppPresenter().workbenchSurfaceManager}
308
+ title={currentTab?.title || t('workbenchGlobalGroup')} testId="doc-browser-panel"
309
+ width={dockedWidth} minWidth={DOC_BROWSER_DOCKED_MIN_WIDTH} maxWidth={DOC_BROWSER_DOCKED_MAX_WIDTH}
310
+ onWidthCommit={setDockedWidth} onClose={close} closeLabel={t('workbenchHideGroup')}
311
+ hidden={!isOpen} fullscreen={isFullscreen} navigation={
312
+ <DocBrowserTabStrip
313
+ tabs={tabs}
314
+ activeTabId={activeTabId}
315
+ canGoBack={canGoBack}
316
+ canGoForward={canGoForward}
317
+ dockState={dockState}
318
+ onGoBack={goBack}
319
+ onGoForward={goForward}
320
+ onOpenNewTab={openNewTab}
321
+ onToggleDock={handleToggleDock}
322
+ onSetActiveTab={setActiveTab}
323
+ onCloseTab={closeTab}
324
+ getTabMenuGroups={getTabMenuGroups}
325
+ />
326
+ }>
448
327
  {panelContent}
449
-
450
- {!isDocked && !isFullscreen && (
451
- <>
452
- <div className="absolute top-0 left-0 h-3 w-full cursor-ns-resize z-20 hover:bg-primary/10 transition-colors" data-testid="doc-browser-resize-top" onPointerDown={startFloatResize('top')} />
453
- <div
454
- className="absolute top-0 left-0 w-3 h-full cursor-ew-resize z-20 hover:bg-primary/10 transition-colors"
455
- data-testid="doc-browser-resize-left"
456
- onPointerDown={startFloatResize('left')}
457
- />
458
- <div
459
- className="absolute top-0 right-0 w-3 h-full cursor-ew-resize z-20 hover:bg-primary/10 transition-colors"
460
- data-testid="doc-browser-resize-right"
461
- onPointerDown={startFloatResize('right')}
462
- />
463
- <div
464
- className="absolute bottom-0 left-0 h-3 w-full cursor-ns-resize z-20 hover:bg-primary/10 transition-colors"
465
- data-testid="doc-browser-resize-bottom"
466
- onPointerDown={startFloatResize('bottom')}
467
- />
468
- <div
469
- className="absolute top-0 left-0 z-30 h-4 w-4 cursor-nw-resize hover:bg-primary/10 transition-colors"
470
- data-testid="doc-browser-resize-top-left"
471
- onPointerDown={startFloatResize('top-left')}
472
- />
473
- <div
474
- className="absolute top-0 right-0 z-30 h-4 w-4 cursor-ne-resize hover:bg-primary/10 transition-colors"
475
- data-testid="doc-browser-resize-top-right"
476
- onPointerDown={startFloatResize('top-right')}
477
- />
478
- <div
479
- className="absolute bottom-0 left-0 z-30 h-4 w-4 cursor-sw-resize hover:bg-primary/10 transition-colors"
480
- data-testid="doc-browser-resize-bottom-left"
481
- onPointerDown={startFloatResize('bottom-left')}
482
- />
483
- <div
484
- className="absolute bottom-0 right-0 z-30 flex h-4 w-4 cursor-se-resize items-center justify-center text-muted-foreground/45 transition-colors hover:text-muted-foreground"
485
- data-testid="doc-browser-resize-bottom-right"
486
- onPointerDown={startFloatResize('bottom-right')}
487
- >
488
- <GripVertical className="w-3 h-3 rotate-[-45deg]" />
489
- </div>
490
- </>
491
- )}
492
- </div>
328
+ </WorkbenchSurface>
493
329
  );
494
330
  }
@@ -17,6 +17,6 @@ export function useDocBrowserScrollRestoration({
17
17
  currentUrl: currentTab?.currentUrl ?? null,
18
18
  iframeRef,
19
19
  isEnabled,
20
- restorationKey: currentTab ? `panel-app:doc-browser:${currentTab.id}` : null,
20
+ restorationKey: currentTab ? `panel-app:resource:${currentTab.dedupeKey ?? currentTab.resourceUri ?? currentTab.currentUrl}` : null,
21
21
  });
22
22
  }
@@ -1,3 +1,5 @@
1
+ import type { WorkbenchSurfaceManager } from '@/shared/components/workbench/managers/workbench-surface.manager';
2
+ import { GLOBAL_WORKBENCH_SURFACE } from '@/shared/components/workbench/types/workbench-surface.types';
1
3
  import type {
2
4
  DocBrowserActiveHistoryEntry,
3
5
  DocBrowserOpenOptions,
@@ -187,6 +189,7 @@ function openResolvedDocBrowserState(
187
189
  target.resourceUri ?? target.url,
188
190
  options?.dockIcon ?? target.dockIcon,
189
191
  target.contentParams,
192
+ options?.viewState ?? target.viewState,
190
193
  );
191
194
  if (isClosedDefaultHomeState(prev, activeTab)) {
192
195
  const nextState = {
@@ -244,6 +247,7 @@ function openDocBrowserState(
244
247
 
245
248
  export class DocBrowserManager {
246
249
  constructor(
250
+ private readonly surfaces: WorkbenchSurfaceManager,
247
251
  private readonly routeResolver: DocBrowserRouteResolver = defaultDocBrowserRouteResolver,
248
252
  private readonly onRightPanelOpened?: RightPanelOpenedHandler,
249
253
  ) {}
@@ -254,6 +258,8 @@ export class DocBrowserManager {
254
258
 
255
259
  readonly open = (url?: string, options?: DocBrowserOpenOptions): void => {
256
260
  this.setSnapshot((prev) => openDocBrowserState(this.routeResolver, prev, url, options));
261
+ if (options?.placement) this.surfaces.place(GLOBAL_WORKBENCH_SURFACE, options.placement);
262
+ this.surfaces.restore(GLOBAL_WORKBENCH_SURFACE);
257
263
  this.onRightPanelOpened?.();
258
264
  };
259
265
 
@@ -264,6 +270,8 @@ export class DocBrowserManager {
264
270
  kind: options?.kind ?? target.kind,
265
271
  title: options?.title ?? target.title,
266
272
  }));
273
+ if (options?.placement) this.surfaces.place(GLOBAL_WORKBENCH_SURFACE, options.placement);
274
+ this.surfaces.restore(GLOBAL_WORKBENCH_SURFACE);
267
275
  this.onRightPanelOpened?.();
268
276
  };
269
277
 
@@ -289,7 +297,9 @@ export class DocBrowserManager {
289
297
  };
290
298
 
291
299
  readonly toggleMode = (): void => {
292
- this.setSnapshot((prev) => ({ ...prev, mode: prev.mode === 'floating' ? 'docked' : 'floating' }));
300
+ const { surfaces } = this;
301
+ surfaces.place(GLOBAL_WORKBENCH_SURFACE, surfaces.get(GLOBAL_WORKBENCH_SURFACE).placement === 'floating' ? 'docked' : 'floating');
302
+ this.surfaces.restore(GLOBAL_WORKBENCH_SURFACE);
293
303
  this.onRightPanelOpened?.();
294
304
  };
295
305
 
@@ -1,9 +1,9 @@
1
+ import { ViewMemoryStorage } from '@/shared/lib/navigation-history';
1
2
  import { create } from 'zustand';
2
3
  import { createJSONStorage, persist } from 'zustand/middleware';
3
4
  import type {
4
5
  DocBrowserActiveHistoryEntry,
5
6
  DocBrowserDockIcon,
6
- DocBrowserMode,
7
7
  DocBrowserState,
8
8
  DocBrowserStateUpdate,
9
9
  DocBrowserTab,
@@ -28,9 +28,6 @@ function isRecord(value: unknown): value is Record<string, unknown> {
28
28
  return !!value && typeof value === 'object';
29
29
  }
30
30
 
31
- function isDocBrowserMode(value: unknown): value is DocBrowserMode {
32
- return value === 'floating' || value === 'docked';
33
- }
34
31
 
35
32
  function normalizePersistedStringList(value: unknown, fallback: string): string[] {
36
33
  if (!Array.isArray(value)) {
@@ -91,6 +88,7 @@ function normalizePersistedDocBrowserTab(value: unknown): DocBrowserTab | null {
91
88
  currentUrl: history[historyIndex] ?? value.currentUrl,
92
89
  resourceUri,
93
90
  dockIcon,
91
+ viewState: value.viewState,
94
92
  dedupeKey,
95
93
  history,
96
94
  historyIndex,
@@ -170,7 +168,6 @@ function normalizePersistedDocBrowserState(value: unknown): DocBrowserState | nu
170
168
 
171
169
  return {
172
170
  isOpen: value.isOpen === true,
173
- mode: isDocBrowserMode(value.mode) ? value.mode : 'docked',
174
171
  dockedWidth: normalizeDocBrowserDockedWidth(value.dockedWidth),
175
172
  tabs,
176
173
  activeTabId: resolvedActiveTabId,
@@ -197,11 +194,10 @@ export const useDocBrowserStore = create<DocBrowserStore>()(
197
194
  {
198
195
  name: DOC_BROWSER_STORAGE_KEY,
199
196
  version: DOC_BROWSER_STORAGE_VERSION,
200
- storage: createJSONStorage(() => window.localStorage),
197
+ storage: createJSONStorage(() => new ViewMemoryStorage()),
201
198
  partialize: (state): { snapshot: PersistedDocBrowserState } => ({
202
199
  snapshot: {
203
200
  isOpen: state.snapshot.isOpen,
204
- mode: state.snapshot.mode,
205
201
  dockedWidth: state.snapshot.dockedWidth,
206
202
  tabs: state.snapshot.tabs.slice(-DOC_BROWSER_MAX_PERSISTED_TABS),
207
203
  activeTabId: state.snapshot.activeTabId,
@@ -10,6 +10,8 @@ export type DocBrowserTab = {
10
10
  currentUrl: string;
11
11
  resourceUri?: string;
12
12
  contentParams?: UiContentParams;
13
+ /** Serializable renderer-owned view context; validated by the renderer. */
14
+ viewState?: unknown;
13
15
  dockIcon?: DocBrowserDockIcon;
14
16
  dedupeKey?: string;
15
17
  history: string[];
@@ -25,6 +27,8 @@ export type DocBrowserRouteTarget = {
25
27
  kind: DocBrowserTabKind;
26
28
  resourceUri?: string;
27
29
  contentParams?: UiContentParams;
30
+ /** Serializable renderer-owned view context; validated by the renderer. */
31
+ viewState?: unknown;
28
32
  title: string;
29
33
  url: string;
30
34
  };
@@ -69,6 +73,7 @@ export type DocBrowserActiveHistoryEntry = {
69
73
  };
70
74
 
71
75
  export type DocBrowserOpenOptions = {
76
+ placement?: DocBrowserMode;
72
77
  activate?: boolean;
73
78
  dedupeKey?: string;
74
79
  dockIcon?: DocBrowserDockIcon;
@@ -76,11 +81,12 @@ export type DocBrowserOpenOptions = {
76
81
  title?: string;
77
82
  kind?: DocBrowserTabKind;
78
83
  contentParams?: UiContentParams;
84
+ /** Serializable renderer-owned view context; validated by the renderer. */
85
+ viewState?: unknown;
79
86
  };
80
87
 
81
88
  export type DocBrowserState = {
82
89
  isOpen: boolean;
83
- mode: DocBrowserMode;
84
90
  dockedWidth: number;
85
91
  tabs: DocBrowserTab[];
86
92
  activeTabId: string;
@@ -106,5 +112,6 @@ export type DocBrowserActions = {
106
112
  };
107
113
 
108
114
  export type DocBrowserContextValue = DocBrowserState & DocBrowserActions & {
115
+ mode: DocBrowserMode;
109
116
  currentTab?: DocBrowserTab;
110
117
  };
@@ -1,36 +1,34 @@
1
1
  import { useEffect } from 'react';
2
- import { isDocsUrl, useDocBrowser } from './doc-browser-context';
2
+ import { useNavigate } from 'react-router-dom';
3
+ import { useAppPresenter } from '@/app/components/app-presenter-provider';
4
+ import { isDocsUrl } from './doc-browser-context';
5
+ import { toast } from 'sonner';
6
+ import { t } from '@/shared/lib/i18n';
3
7
 
4
- /**
5
- * Global click interceptor for docs links.
6
- * Captures clicks on <a> tags pointing to the docs domain
7
- * and opens them in the in-app micro-browser instead.
8
- */
8
+ /** Resource links use the same opening policy as navigation and page menus. */
9
9
  export function useDocLinkInterceptor() {
10
- const docBrowser = useDocBrowser();
11
-
12
- useEffect(() => {
13
- const handler = (e: MouseEvent) => {
14
- // Walk up from the click target to find an anchor
15
- const anchor = (e.target as HTMLElement).closest<HTMLAnchorElement>('a[href]');
16
- if (!anchor) return;
17
-
18
- const href = anchor.getAttribute('href') || '';
19
- if (!isDocsUrl(href)) return;
20
-
21
- // Don't intercept links explicitly marked for external opening
22
- if (anchor.hasAttribute('data-doc-external')) return;
23
-
24
- // Don't intercept if modifier keys are held (user wants new tab behavior)
25
- if (e.ctrlKey || e.metaKey || e.shiftKey) return;
26
-
27
- e.preventDefault();
28
- e.stopPropagation();
29
- docBrowser.open(href);
30
- };
31
-
32
- // Use capture phase to intercept before React's synthetic events
33
- document.addEventListener('click', handler, true);
34
- return () => document.removeEventListener('click', handler, true);
35
- }, [docBrowser]);
10
+ const app = useAppPresenter();
11
+ const navigate = useNavigate();
12
+ useEffect(() => {
13
+ const handler = (event: MouseEvent) => {
14
+ if (event.defaultPrevented || event.button !== 0 || event.ctrlKey || event.metaKey || event.shiftKey || event.altKey) return;
15
+ const anchor = event.target instanceof Element ? event.target.closest<HTMLAnchorElement>('a[href]') : null;
16
+ if (!anchor || anchor.hasAttribute('data-doc-external') || anchor.hasAttribute('download')) return;
17
+ const href = anchor.getAttribute('href') ?? '';
18
+ if (!href.startsWith('nextclaw://') && !isDocsUrl(href)) return;
19
+ event.preventDefault();
20
+ event.stopPropagation();
21
+ const origin = anchor.closest<HTMLElement>('[data-resource-session]');
22
+ const page = app.pageResourceManager.resolve(href, { workingDir: origin?.dataset.resourceWorkingDir, sessionKey: origin?.dataset.resourceSession });
23
+ if (page) {
24
+ const label = anchor.cloneNode(true) as HTMLAnchorElement;
25
+ label.querySelectorAll('[aria-hidden="true"]').forEach((element) => element.remove());
26
+ const title = label.textContent?.trim();
27
+ app.pageResourceManager.open(title ? { ...page, title, target: { ...page.target, title } } : page, 'default', navigate);
28
+ }
29
+ else toast.error(t('pageUnavailable'));
30
+ };
31
+ document.addEventListener('click', handler, true);
32
+ return () => document.removeEventListener('click', handler, true);
33
+ }, [app, navigate]);
36
34
  }
@@ -13,6 +13,7 @@ import {
13
13
  DOC_BROWSER_HOME_URL,
14
14
  inferTabTitle,
15
15
  } from './doc-browser-url.utils';
16
+ import { pushNavigationHistoryEntry } from '@/shared/lib/navigation-history';
16
17
  import { t } from '@/shared/lib/i18n';
17
18
  import {
18
19
  createUiContentParamsWindowName,
@@ -44,6 +45,7 @@ export function createDocBrowserTab(
44
45
  resourceUri?: string,
45
46
  dockIcon?: DocBrowserDockIcon,
46
47
  contentParams?: UiContentParams,
48
+ viewState?: unknown,
47
49
  ): DocBrowserTab {
48
50
  const tabTitle = title?.trim() || inferTabTitle(url, kind, kind === 'docs' ? t('docBrowserHelp') : 'Detail');
49
51
  const normalizedResourceUri = resourceUri?.trim();
@@ -55,6 +57,7 @@ export function createDocBrowserTab(
55
57
  currentUrl: url,
56
58
  resourceUri: normalizedResourceUri ? normalizedResourceUri : undefined,
57
59
  contentParams,
60
+ viewState,
58
61
  dockIcon,
59
62
  dedupeKey,
60
63
  history: [url],
@@ -67,11 +70,8 @@ export function appendManualNavigation(
67
70
  tab: DocBrowserTab,
68
71
  url: string,
69
72
  ): Pick<DocBrowserTab, 'history' | 'historyIndex'> {
70
- const history = [...tab.history.slice(0, tab.historyIndex + 1), url];
71
- return {
72
- history,
73
- historyIndex: history.length - 1,
74
- };
73
+ const next = pushNavigationHistoryEntry({ entries: tab.history, index: tab.historyIndex }, url);
74
+ return { history: [...next.entries], historyIndex: next.index };
75
75
  }
76
76
 
77
77
  export function updateTabForOpen(
@@ -89,6 +89,7 @@ export function updateTabForOpen(
89
89
  dockIcon: options?.dockIcon ?? target.dockIcon,
90
90
  dedupeKey,
91
91
  contentParams: target.contentParams,
92
+ viewState: options?.viewState ?? target.viewState ?? tab.viewState,
92
93
  };
93
94
  const hasSameUrl = routeResolver.areUrlsEquivalent(
94
95
  tab.currentUrl,
@@ -130,7 +131,6 @@ export function createDefaultDocBrowserState(): DocBrowserState {
130
131
  const initialTab = createDocBrowserTab(DOC_BROWSER_HOME_URL, DOC_BROWSER_HOME_TAB_KIND, t('docBrowserHomeTitle'));
131
132
  return {
132
133
  isOpen: false,
133
- mode: 'docked',
134
134
  dockedWidth: DOC_BROWSER_DOCKED_DEFAULT_WIDTH,
135
135
  tabs: [initialTab],
136
136
  activeTabId: initialTab.id,
@@ -4,6 +4,28 @@ import { describe, expect, it, vi } from 'vitest';
4
4
  import { ContextMenu, ContextMenuTrigger } from '@/shared/components/ui/context-menu/context-menu';
5
5
 
6
6
  describe('ContextMenu', () => {
7
+ it('keeps modal actions inside the dialog focus boundary and consumes Escape', async () => {
8
+ const onSelect = vi.fn();
9
+ const onDialogKeyDown = vi.fn();
10
+ render(
11
+ <div role="dialog" onKeyDown={onDialogKeyDown}>
12
+ <ContextMenu label="Resource actions" groups={[{ key: 'open', items: [{ key: 'open', label: 'Open resource', onSelect }] }]}>
13
+ <div><ContextMenuTrigger><button type="button">Actions</button></ContextMenuTrigger></div>
14
+ </ContextMenu>
15
+ </div>,
16
+ );
17
+ await userEvent.click(screen.getByRole('button', { name: 'Actions' }));
18
+ const menu = screen.getByRole('menu');
19
+ expect(menu.closest('[role="dialog"]')).toBe(screen.getByRole('dialog'));
20
+ expect(menu.parentElement?.className).toContain('pointer-events-auto');
21
+ await userEvent.keyboard('{Escape}');
22
+ expect(screen.queryByRole('menu')).toBeNull();
23
+ expect(onDialogKeyDown).not.toHaveBeenCalled();
24
+ await userEvent.click(screen.getByRole('button', { name: 'Actions' }));
25
+ await userEvent.click(screen.getByRole('menuitem', { name: 'Open resource' }));
26
+ expect(onSelect).toHaveBeenCalledOnce();
27
+ });
28
+
7
29
  it('opens at the trigger and supports keyboard selection', async () => {
8
30
  const onSelect = vi.fn();
9
31
  render(