@nextclaw/ui 0.24.0 → 0.24.2

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 (333) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/.vite/manifest.json +2477 -0
  3. package/dist/assets/{abnfDiagram-VRR7QNED-BcFJp_1X.js → abnfDiagram-VRR7QNED-Kzlh3ZEC.js} +1 -1
  4. package/dist/assets/account-panel-BxMlLXYH.js +1 -0
  5. package/dist/assets/{aiden0z-pptx-renderer.es-Dp2ezlQn.js → aiden0z-pptx-renderer.es-k1xZLzeo.js} +1 -1
  6. package/dist/assets/api-Utt-xzrT.js +13 -0
  7. package/dist/assets/app-data-DYXDL6X2.js +1 -0
  8. package/dist/assets/app-presenter-provider-CLsFiXvV.js +109 -0
  9. package/dist/assets/app-presenter-provider-D3BuuOyZ.css +1 -0
  10. package/dist/assets/appearance-settings-page-BfYznAK5.js +1 -0
  11. package/dist/assets/{arc-CkgyPMyW.js → arc-CpivM836.js} +1 -1
  12. package/dist/assets/architecture-TIHT7OUA-CVRF_cYQ.js +1 -0
  13. package/dist/assets/{architectureDiagram-ZJ3FMSHR-CMd4cIjI.js → architectureDiagram-ZJ3FMSHR-ifjW1qjI.js} +1 -1
  14. package/dist/assets/{blockDiagram-677ZJIJ3-Bz3tbhet.js → blockDiagram-677ZJIJ3-C_zeJrKF.js} +1 -1
  15. package/dist/assets/{book-open-o2x7OLiO.js → book-open-DDW_3XpM.js} +1 -1
  16. package/dist/assets/boxes-DwJeuK_h.js +1 -0
  17. package/dist/assets/{c4Diagram-LMCZKHZV-D9hFNAGv.js → c4Diagram-LMCZKHZV-CpapRftp.js} +1 -1
  18. package/dist/assets/card-IevY2nm-.js +1 -0
  19. package/dist/assets/channel-CBrWRr4N.js +1 -0
  20. package/dist/assets/channels-list-page-DitnqbMR.js +8 -0
  21. package/dist/assets/chevron-down-An7Km-t4.js +1 -0
  22. package/dist/assets/chunk-2Q5K7J3B-B8mmRk7d.js +1 -0
  23. package/dist/assets/{chunk-32BRIVSS-7NrjEITq.js → chunk-32BRIVSS-BKBwdmKR.js} +1 -1
  24. package/dist/assets/{chunk-52WLFC77-viIcqj9q.js → chunk-52WLFC77-BgZRCpDx.js} +1 -1
  25. package/dist/assets/{chunk-5FCAYU7R-Vsu4J-VM.js → chunk-5FCAYU7R-YWfOINJi.js} +1 -1
  26. package/dist/assets/{chunk-5HE753X5-C-w6CQZK.js → chunk-5HE753X5-BZ6I07d2.js} +1 -1
  27. package/dist/assets/{chunk-5JV3BV7I-CuKgJQ4W.js → chunk-5JV3BV7I-B7QYgZU5.js} +1 -1
  28. package/dist/assets/{chunk-5TONJI2A-CYeiWZKb.js → chunk-5TONJI2A-DjyQwgL2.js} +1 -1
  29. package/dist/assets/{chunk-5VM5RSS4-DRCbfwIn.js → chunk-5VM5RSS4-DheHV7X2.js} +1 -1
  30. package/dist/assets/{chunk-7BUUIJ7U-BvydOcm3.js → chunk-7BUUIJ7U-D6bq2PKF.js} +1 -1
  31. package/dist/assets/{chunk-BIQX33UG-RlppOXKo.js → chunk-BIQX33UG-CL9x0ibm.js} +1 -1
  32. package/dist/assets/{chunk-C7G6YPKG-DAizzYwr.js → chunk-C7G6YPKG-8z3B6RUH.js} +1 -1
  33. package/dist/assets/{chunk-CQNSW5MT-5eChJHca.js → chunk-CQNSW5MT-DpHkxY3n.js} +1 -1
  34. package/dist/assets/{chunk-CYSBUYHQ-YHPr53fv.js → chunk-CYSBUYHQ-DIJDLsdJ.js} +1 -1
  35. package/dist/assets/{chunk-EMLP6XTP-CK4D7Hz5.js → chunk-EMLP6XTP-B-LjAyVd.js} +1 -1
  36. package/dist/assets/{chunk-EX3LRPZG-BmlDFIRW.js → chunk-EX3LRPZG-BChuEPvO.js} +1 -1
  37. package/dist/assets/{chunk-FWX5IMBZ-D0ksHZZ9.js → chunk-FWX5IMBZ-fBFt0u3f.js} +2 -2
  38. package/dist/assets/{chunk-HOUHSVGY-DPkq8FCm.js → chunk-HOUHSVGY-MD0SpW5A.js} +1 -1
  39. package/dist/assets/{chunk-ICXQ74PX-FAatv5fC.js → chunk-ICXQ74PX-DvCcw_hz.js} +1 -1
  40. package/dist/assets/{chunk-JG7HCLWE-DLkIi4F7.js → chunk-JG7HCLWE-B8zqBnU9.js} +1 -1
  41. package/dist/assets/{chunk-JWPE2WC7-DawOjNE3.js → chunk-JWPE2WC7-C9efnkGb.js} +1 -1
  42. package/dist/assets/{chunk-MOJQB5TN-Di52TorW.js → chunk-MOJQB5TN-gXbfqoqq.js} +1 -1
  43. package/dist/assets/{chunk-MOZMSUNE-PfyK9w1-.js → chunk-MOZMSUNE-twIwdkqC.js} +1 -1
  44. package/dist/assets/{chunk-OGEWGWER-C3jdH3Ty.js → chunk-OGEWGWER-DdR0_cWK.js} +1 -1
  45. package/dist/assets/{chunk-OSBZ3O6U-CecHo-f0.js → chunk-OSBZ3O6U-D7D58Foa.js} +1 -1
  46. package/dist/assets/{chunk-PUDLZKDR-f3IJh3sN.js → chunk-PUDLZKDR-DPILgOVY.js} +1 -1
  47. package/dist/assets/{chunk-Q4XR5HBZ-DQFeUPxZ.js → chunk-Q4XR5HBZ-C0JJx7lW.js} +1 -1
  48. package/dist/assets/{chunk-QBLGF6JB-BhUeG0y2.js → chunk-QBLGF6JB-Dbsf69ng.js} +1 -1
  49. package/dist/assets/{chunk-R7FJI6CG-C3XpZ-2u.js → chunk-R7FJI6CG-Bb8n616-.js} +1 -1
  50. package/dist/assets/{chunk-RYQCIY6F-CAqa5klQ.js → chunk-RYQCIY6F-1HOsOrSl.js} +1 -1
  51. package/dist/assets/{chunk-U6XO7XAA-D_WXezeD.js → chunk-U6XO7XAA-BAFDVb1v.js} +1 -1
  52. package/dist/assets/{chunk-V7JOEXUC-CZ70oOtp.js → chunk-V7JOEXUC-8-g68lu5.js} +1 -1
  53. package/dist/assets/chunk-VAUOI2AC-Cpml0inz.js +1 -0
  54. package/dist/assets/{chunk-VR4S4FIN-B7AHEYYk.js → chunk-VR4S4FIN-P6UGmaYd.js} +1 -1
  55. package/dist/assets/{chunk-WYO6CB5R-Dn9To_OI.js → chunk-WYO6CB5R-6wjFTXNP.js} +2 -2
  56. package/dist/assets/chunk-XXDRQBXY-nCiqnCpF.js +1 -0
  57. package/dist/assets/{chunk-YOTPTUD7-BYEgRBk3.js → chunk-YOTPTUD7-CLYXVZAi.js} +1 -1
  58. package/dist/assets/{chunk-ZGVPDNZ5-C6YtZDU0.js → chunk-ZGVPDNZ5-BRTmSAhp.js} +1 -1
  59. package/dist/assets/{chunk-ZIRB5QZD-DMuYtnHF.js → chunk-ZIRB5QZD-CH_1eoSV.js} +1 -1
  60. package/dist/assets/circle-alert-CDXqELuo.js +1 -0
  61. package/dist/assets/circle-dashed-CapXEpiV.js +1 -0
  62. package/dist/assets/classDiagram-OUVF2IWQ-C-DRqAaW.js +1 -0
  63. package/dist/assets/classDiagram-v2-EOCWNBFH-DXCcZ42U.js +1 -0
  64. package/dist/assets/client-B0krol7A.js +1 -0
  65. package/dist/assets/config-split-page-BtnkqWVp.js +1 -0
  66. package/dist/assets/confirm-dialog-DFt4jpN7.js +1 -0
  67. package/dist/assets/{cose-bilkent-JH36ORCC-Bc2Ex5Y3.js → cose-bilkent-JH36ORCC-L7w_qScX.js} +1 -1
  68. package/dist/assets/{createLucideIcon-rwwpqyks.js → createLucideIcon-BTHK0Ot9.js} +1 -1
  69. package/dist/assets/cynefin-VYW2F7L2-2SOTgxxC.js +1 -0
  70. package/dist/assets/{cynefinDiagram-TSTJHNR4-DVysQoGz.js → cynefinDiagram-TSTJHNR4-Bay7uDSR.js} +1 -1
  71. package/dist/assets/{dagre-CMhQ1cAG.js → dagre-CJ_hX8xv.js} +1 -1
  72. package/dist/assets/{dagre-VKFMJZFB-RYyWpPJZ.js → dagre-VKFMJZFB-DDhk-2B3.js} +1 -1
  73. package/dist/assets/desktop-capabilities-page-CCf14WId.js +1 -0
  74. package/dist/assets/desktop-update-config-DVoVgfFi.js +1 -0
  75. package/dist/assets/{diagram-FQU43EPY-BD6KONdF.js → diagram-FQU43EPY-somFq5y8.js} +1 -1
  76. package/dist/assets/{diagram-G47NLZAW-CGB2ptRR.js → diagram-G47NLZAW-hzgyQsPd.js} +1 -1
  77. package/dist/assets/{diagram-NH7WQ7WH-DnkOI6cU.js → diagram-NH7WQ7WH-BkJ4gEQJ.js} +1 -1
  78. package/dist/assets/{diagram-OA4YK3LP-DF82RZ7P.js → diagram-OA4YK3LP-CS3ZkK4w.js} +1 -1
  79. package/dist/assets/{diagram-WEI45ONY-Be2v7Ck9.js → diagram-WEI45ONY-BApo-JHS.js} +1 -1
  80. package/dist/assets/dialog-BFN_1DBH.js +5 -0
  81. package/dist/assets/dist-Bc9hOVNN.js +1 -0
  82. package/dist/assets/dist-CEhIDAnr.js +1 -0
  83. package/dist/assets/{dist--ta5rX12.js → dist-Cnhwure9.js} +1 -1
  84. package/dist/assets/{dist-aNN3iQxV.js → dist-hkVPP1th.js} +1 -1
  85. package/dist/assets/doc-browser-BNUxmwD6.js +1 -0
  86. package/dist/assets/doc-browser-context-C4yQrKrH.js +1 -0
  87. package/dist/assets/doc-browser-w4eGZXLu.js +1 -0
  88. package/dist/assets/{docx-preview-BqwAjrj3.js → docx-preview-ByCKKIVT.js} +1 -1
  89. package/dist/assets/{ebnfDiagram-CCIWWBDH-CP98OYk8.js → ebnfDiagram-CCIWWBDH-DWjfeEie.js} +1 -1
  90. package/dist/assets/ellipsis-BRI6ROeu.js +1 -0
  91. package/dist/assets/{erDiagram-Q63AITRT-ZLlx8xfs.js → erDiagram-Q63AITRT-DR7vWYHM.js} +1 -1
  92. package/dist/assets/es2015-MOCbM0Eu.js +41 -0
  93. package/dist/assets/eventmodeling-45OFAUF4-CXZNG56U.js +1 -0
  94. package/dist/assets/extensions-DxUBMtHW.js +1 -0
  95. package/dist/assets/eye-cnynUDGt.js +1 -0
  96. package/dist/assets/flowDiagram-23GEKE2U-2065oyKr.js +1 -0
  97. package/dist/assets/form-actions-gQ0JEUwB.js +1 -0
  98. package/dist/assets/{ganttDiagram-NO4QXBWP-DXCDjHR2.js → ganttDiagram-NO4QXBWP-E3l9tuaL.js} +1 -1
  99. package/dist/assets/gitGraph-TEB2WS4Q-B0Ln3ZuK.js +1 -0
  100. package/dist/assets/{gitGraphDiagram-IHSO6WYX-l2HWrTJp.js → gitGraphDiagram-IHSO6WYX-DiMvbHKf.js} +1 -1
  101. package/dist/assets/i18n-B9yXA8KO.js +2 -0
  102. package/dist/assets/i18n-provider-BYBJua91.js +1 -0
  103. package/dist/assets/info-DKCQHKI2-B06uqGM4.js +1 -0
  104. package/dist/assets/{infoDiagram-FWYZ7A6U-D-DjX-bn.js → infoDiagram-FWYZ7A6U-BZDL0NDJ.js} +1 -1
  105. package/dist/assets/{ishikawaDiagram-FXEZZL3T-y_Xy128F.js → ishikawaDiagram-FXEZZL3T-BZ9WvJb2.js} +1 -1
  106. package/dist/assets/{journeyDiagram-5HDEW3XC-DJn5xYcQ.js → journeyDiagram-5HDEW3XC-C3TZvKM8.js} +1 -1
  107. package/dist/assets/{jszip.min-8hyJpgpx.js → jszip.min-D_AtKL_8.js} +1 -1
  108. package/dist/assets/{kanban-definition-HUTT4EX6-DJVIOR21.js → kanban-definition-HUTT4EX6-9FqauDEi.js} +1 -1
  109. package/dist/assets/{line-Cos7PIOj.js → line-Ca49mj80.js} +1 -1
  110. package/dist/assets/{linear-BtDLqtzF.js → linear-DlCeG66S.js} +1 -1
  111. package/dist/assets/loader-circle-rWr5Yo0E.js +1 -0
  112. package/dist/assets/login-page-CfMSkOsg.js +1 -0
  113. package/dist/assets/login-page-CqrHhzaN.js +1 -0
  114. package/dist/assets/logo-badge-Cr03YceJ.js +1 -0
  115. package/dist/assets/main-8cVkMfgE.css +1 -0
  116. package/dist/assets/main-Bys58GxY.js +2 -0
  117. package/dist/assets/main-i18n-catalog.config-BSq9yiUQ.js +1 -0
  118. package/dist/assets/{map-BKnQyvd0.js → map-WMnNq9UV.js} +1 -1
  119. package/dist/assets/mcp-marketplace-page-CifiVgFD.js +10 -0
  120. package/dist/assets/mcp-marketplace-page-DX5VE3mU.js +1 -0
  121. package/dist/assets/{mermaid-parser.core-XUNZhr2W.js → mermaid-parser.core-B8xk4hpS.js} +2 -2
  122. package/dist/assets/{mermaid.core-ySrvolIe.js → mermaid.core-CFPiczKH.js} +3 -3
  123. package/dist/assets/{mindmap-definition-LN4V7U3C-BypL9tei.js → mindmap-definition-LN4V7U3C-CnxA52L6.js} +1 -1
  124. package/dist/assets/model-config-page-C6jVNbSj.js +1 -0
  125. package/dist/assets/{navigation-link-C_6oj3zz.js → navigation-link-kbCLRSr_.js} +1 -1
  126. package/dist/assets/{ordinal-CxxVWxYU.js → ordinal-PgiFlfBJ.js} +1 -1
  127. package/dist/assets/packet-7NZHBO7P-CHx-igbz.js +1 -0
  128. package/dist/assets/panel-app-BUUle0gP.js +1 -0
  129. package/dist/assets/panel-app-i18n-catalog.config-C2St67SP.js +1 -0
  130. package/dist/assets/panelStandalone-DMBnYyTw.js +2 -0
  131. package/dist/assets/panelStandalone-Y91OJkgV.css +1 -0
  132. package/dist/assets/{pegDiagram-2B236MQR-D-U2KBGv.js → pegDiagram-2B236MQR-A8oz7dTH.js} +1 -1
  133. package/dist/assets/pie-RZYD4A2V-DOaMc-x9.js +1 -0
  134. package/dist/assets/{pieDiagram-ENE6RG2P-CBi3GusJ.js → pieDiagram-ENE6RG2P-mtBnkYY0.js} +1 -1
  135. package/dist/assets/plus-BHnKwuPq.js +1 -0
  136. package/dist/assets/popover-XVDgjxcl.js +1 -0
  137. package/dist/assets/privacy-settings-page-BN27MBVA.js +1 -0
  138. package/dist/assets/projects-DV3UuJMS.js +1 -0
  139. package/dist/assets/provider-models-5PGHb6mP.js +1 -0
  140. package/dist/assets/provider-scoped-model-input-BGZMCThn.js +1 -0
  141. package/dist/assets/providers-config-page-D5aBwbOD.js +1 -0
  142. package/dist/assets/puzzle-D5Dhacmb.js +1 -0
  143. package/dist/assets/pwa-ClQK56Qe.js +1 -0
  144. package/dist/assets/{quadrantDiagram-ABIIQ3AL-H0ZuvnZL.js → quadrantDiagram-ABIIQ3AL-DE1VybGO.js} +1 -1
  145. package/dist/assets/radar-I7S5WNFK-CXsdndDk.js +1 -0
  146. package/dist/assets/railroad-3IZDKUUU-DxgXdrYP.js +1 -0
  147. package/dist/assets/railroad-abnf-AHOZXSZD-CR1tnyjz.js +1 -0
  148. package/dist/assets/railroad-ebnf-EBAXGLYW-CjjxZR2U.js +1 -0
  149. package/dist/assets/railroad-peg-LSFZ7HO6-DgVGJCHN.js +1 -0
  150. package/dist/assets/{railroadDiagram-RFXS5EU6-D7Y2EqSd.js → railroadDiagram-RFXS5EU6-u9EMg14B.js} +1 -1
  151. package/dist/assets/{refresh-cw-DsT2kvXi.js → refresh-cw-Bw5BY7vp.js} +1 -1
  152. package/dist/assets/remote-Bl005fzu.js +1 -0
  153. package/dist/assets/{requirementDiagram-TGXJPOKE-BiXNX1NN.js → requirementDiagram-TGXJPOKE-BAWHAqEi.js} +1 -1
  154. package/dist/assets/{rotate-cw-BCAs6c3R.js → rotate-cw-BksCLAeE.js} +1 -1
  155. package/dist/assets/runtime-config-page-CmktQcMW.js +1 -0
  156. package/dist/assets/{sankeyDiagram-HTMAVEWB-qzDeLztW.js → sankeyDiagram-HTMAVEWB-aDy-jdwF.js} +1 -1
  157. package/dist/assets/{save-CadRMTMQ.js → save-CVi8VWzb.js} +1 -1
  158. package/dist/assets/{search-B6tB4fzB.js → search-DN-f7IIC.js} +1 -1
  159. package/dist/assets/search-config-page-BmuZTVxs.js +1 -0
  160. package/dist/assets/secrets-config-page-NPHpg9sb.js +3 -0
  161. package/dist/assets/security-config-Djptuyf2.js +1 -0
  162. package/dist/assets/select-CmDTqk2C.js +1 -0
  163. package/dist/assets/{sequenceDiagram-DBY2YBRQ-BtRbPQtL.js → sequenceDiagram-DBY2YBRQ-DwHC4mbX.js} +1 -1
  164. package/dist/assets/service-apps-panel-BYGJ9_pO.js +1 -0
  165. package/dist/assets/settings-2-B62YtZon.js +1 -0
  166. package/dist/assets/{sizeCapture-X5ZJPWSS-CMYvM3SL.js → sizeCapture-X5ZJPWSS-oOMY0Fag.js} +1 -1
  167. package/dist/assets/skeleton-Eh64l4T2.js +1 -0
  168. package/dist/assets/{src-Bw-mzbQb.js → src-CLPoo5iL.js} +1 -1
  169. package/dist/assets/{stateDiagram-2N3HPSRC-BJ-mFeOz.js → stateDiagram-2N3HPSRC-B0Epk-VR.js} +1 -1
  170. package/dist/assets/stateDiagram-v2-6OUMAXLB-Ct4zTw8P.js +1 -0
  171. package/dist/assets/{swimlanes-5IMT3BWC-BsucVOO2.js → swimlanes-5IMT3BWC-T0w-Iuzf.js} +2 -2
  172. package/dist/assets/swimlanesDiagram-G3AALYLV-CdmN0PBd.js +8 -0
  173. package/dist/assets/tabs-Bk_mG7ql.js +1 -0
  174. package/dist/assets/{tag-chip-BZKk0UkK.js → tag-chip-DgqKlI5D.js} +1 -1
  175. package/dist/assets/theme-provider-CeBY2pyu.js +1 -0
  176. package/dist/assets/{timeline-definition-FHXFAJF6-Bicewlzo.js → timeline-definition-FHXFAJF6-BEonB5Np.js} +1 -1
  177. package/dist/assets/tooltip-CgGbBdYf.js +1 -0
  178. package/dist/assets/trash-2-CVOev8yc.js +1 -0
  179. package/dist/assets/treeView-QDETBFTQ-Dad4_Wc7.js +1 -0
  180. package/dist/assets/treemap-6X3UGDF4-9_GWWZsY.js +1 -0
  181. package/dist/assets/use-config-b2DN67gs.js +1 -0
  182. package/dist/assets/use-desktop-capabilities-B3tLU1yl.js +1 -0
  183. package/dist/assets/use-panel-app-scroll-restoration-BekzoX6z.js +1 -0
  184. package/dist/assets/use-viewport-layout-CUA3jQsA.js +1 -0
  185. package/dist/assets/utils-UBHTdG5Q.js +8 -0
  186. package/dist/assets/{vennDiagram-L72KCM5P-BxOOnO9x.js → vennDiagram-L72KCM5P-BDvcOCo2.js} +1 -1
  187. package/dist/assets/wardley-OPB4EBWU-BXpvyee9.js +1 -0
  188. package/dist/assets/{wardleyDiagram-EHGQE667-Cl7NltMv.js → wardleyDiagram-EHGQE667-jMLMgjzE.js} +1 -1
  189. package/dist/assets/x-C0iaOsRW.js +1 -0
  190. package/dist/assets/{xychartDiagram-FW5EYKEG-DiMIxQ7N.js → xychartDiagram-FW5EYKEG-pzrpclEv.js} +1 -1
  191. package/dist/index.html +56 -25
  192. package/dist/panel-standalone.html +30 -0
  193. package/package.json +3 -3
  194. package/panel-standalone.html +13 -0
  195. package/panel-standalone.tailwind.config.js +16 -0
  196. package/src/app/components/app-presenter-provider.tsx +8 -1
  197. package/src/app/components/theme-provider.tsx +0 -5
  198. package/src/app/index.tsx +18 -4
  199. package/src/app/presenters/app.presenter.ts +4 -4
  200. package/src/app/styles/panel-app-standalone.css +31 -0
  201. package/src/app/test/vitest-setup.ts +3 -0
  202. package/src/features/account/hooks/use-auth.ts +7 -57
  203. package/src/features/account/index.ts +3 -2
  204. package/src/features/apps/components/__tests__/apps-panel.test.tsx +7 -5
  205. package/src/features/apps/components/apps-panel.tsx +9 -3
  206. package/src/features/chat/features/session/utils/__tests__/chat-sidebar-session-groups.utils.test.ts +27 -2
  207. package/src/features/chat/features/session/utils/chat-sidebar-session-groups.utils.ts +0 -11
  208. package/src/features/panel-apps/components/__tests__/panel-app-list-item.test.tsx +18 -0
  209. package/src/features/panel-apps/components/__tests__/panel-app-open-standalone-menu-item.test.tsx +56 -0
  210. package/src/features/panel-apps/components/__tests__/panel-app-toolbar.test.tsx +15 -0
  211. package/src/features/panel-apps/components/panel-app-list-item.tsx +5 -0
  212. package/src/features/panel-apps/components/panel-app-open-standalone-menu-item.tsx +29 -0
  213. package/src/features/panel-apps/components/panel-app-runtime-surface.tsx +141 -0
  214. package/src/features/{service-apps/components/service-action-authorization-dialog.tsx → panel-apps/components/panel-app-service-action-authorization-dialog.tsx} +4 -4
  215. package/src/features/panel-apps/components/panel-app-toolbar.tsx +5 -0
  216. package/src/features/panel-apps/hooks/use-panel-app-client-grant.ts +2 -2
  217. package/src/features/panel-apps/hooks/{use-panel-app-main-runtime.ts → use-panel-app-runtime.ts} +7 -5
  218. package/src/features/panel-apps/hooks/use-panel-apps.ts +14 -0
  219. package/src/features/panel-apps/index.ts +5 -0
  220. package/src/features/panel-apps/managers/__tests__/panel-app-bridge.manager.test.ts +2 -2
  221. package/src/features/panel-apps/managers/panel-app-bridge.manager.ts +2 -2
  222. package/src/features/panel-apps/managers/panel-app-service-action-authorization.manager.ts +10 -0
  223. package/src/features/panel-apps/pages/__tests__/panel-app-main-page.test.tsx +12 -3
  224. package/src/features/panel-apps/pages/__tests__/panel-app-standalone-page.test.tsx +63 -0
  225. package/src/features/panel-apps/pages/panel-app-main-page.tsx +9 -121
  226. package/src/features/panel-apps/pages/panel-app-standalone-page.tsx +29 -0
  227. package/src/features/panel-apps/presenters/panel-app-host.presenter.ts +9 -0
  228. package/src/features/panel-apps/providers/panel-app-host.provider.tsx +45 -0
  229. package/src/features/panel-apps/routes/__tests__/panel-app-standalone.route.test.tsx +50 -0
  230. package/src/features/panel-apps/routes/panel-app-standalone.route.tsx +94 -0
  231. package/src/features/{service-apps/stores/service-action-authorization.store.ts → panel-apps/stores/panel-app-service-action-authorization.store.ts} +6 -6
  232. package/src/features/projects/components/project-overview.test.tsx +70 -0
  233. package/src/features/projects/components/project-overview.tsx +114 -56
  234. package/src/features/projects/components/work/project-work-item-drawer.tsx +8 -10
  235. package/src/features/projects/components/work/project-work-items.test.tsx +168 -4
  236. package/src/features/projects/components/work/project-work-items.tsx +277 -49
  237. package/src/features/projects/components/work/project-work-state-settings.tsx +7 -3
  238. package/src/features/projects/hooks/use-project-work.test.tsx +108 -6
  239. package/src/features/projects/hooks/use-project-work.ts +82 -9
  240. package/src/features/projects/pages/project-home-page.tsx +45 -6
  241. package/src/features/projects/pages/projects-page.test.tsx +56 -0
  242. package/src/features/projects/utils/project-artifact-view.utils.test.ts +30 -18
  243. package/src/features/projects/utils/project-artifact-view.utils.ts +29 -12
  244. package/src/features/projects/utils/project-work-state-label.utils.test.ts +28 -0
  245. package/src/features/projects/utils/project-work-state-label.utils.ts +20 -0
  246. package/src/features/service-apps/index.ts +3 -3
  247. package/src/main.tsx +3 -0
  248. package/src/shared/hooks/use-auth-status.ts +49 -0
  249. package/src/shared/hooks/use-projects.ts +15 -1
  250. package/src/shared/lib/api/projects/project.utils.ts +4 -0
  251. package/src/shared/lib/i18n/configs/main-i18n-catalog.config.ts +78 -0
  252. package/src/shared/lib/i18n/configs/panel-app-i18n-catalog.config.ts +12 -0
  253. package/src/shared/lib/i18n/index.ts +30 -82
  254. package/src/shared/lib/i18n/locales/en-US/doc-browser.json +0 -55
  255. package/src/shared/lib/i18n/locales/en-US/panel-app.json +59 -0
  256. package/src/shared/lib/i18n/locales/en-US/projects.json +16 -0
  257. package/src/shared/lib/i18n/locales/zh-CN/doc-browser.json +0 -55
  258. package/src/shared/lib/i18n/locales/zh-CN/panel-app.json +59 -0
  259. package/src/shared/lib/i18n/locales/zh-CN/projects.json +16 -0
  260. package/vite.config.ts +36 -1
  261. package/dist/assets/api-BqVIq0lF.js +0 -13
  262. package/dist/assets/appearance-settings-page-CTWn1eAT.js +0 -1
  263. package/dist/assets/architecture-TIHT7OUA-DO2x53FK.js +0 -1
  264. package/dist/assets/channel-nBvMaVyP.js +0 -1
  265. package/dist/assets/channels-list-page-Bzn-pzyJ.js +0 -8
  266. package/dist/assets/chunk-2Q5K7J3B-CJgqFDS4.js +0 -1
  267. package/dist/assets/chunk-VAUOI2AC-BGvh3yIx.js +0 -1
  268. package/dist/assets/chunk-XXDRQBXY-DaBxG5gs.js +0 -1
  269. package/dist/assets/classDiagram-OUVF2IWQ-P6N03G2R.js +0 -1
  270. package/dist/assets/classDiagram-v2-EOCWNBFH-B1_uLvMv.js +0 -1
  271. package/dist/assets/config-split-page-CnRbXXlh.js +0 -1
  272. package/dist/assets/confirm-dialog-B_Hbcra2.js +0 -5
  273. package/dist/assets/cynefin-VYW2F7L2-B-H8Qp-n.js +0 -1
  274. package/dist/assets/desktop-capabilities-page-C2ayYQTr.js +0 -1
  275. package/dist/assets/desktop-update-config-C13czpyL.js +0 -1
  276. package/dist/assets/dist-BsF3hfOi.js +0 -1
  277. package/dist/assets/doc-browser-D8dIOo9E.js +0 -1
  278. package/dist/assets/doc-browser-DcuOOtpP.js +0 -1
  279. package/dist/assets/doc-browser-context-Dhsit2Ma.js +0 -1
  280. package/dist/assets/eventmodeling-45OFAUF4-YVtShyFA.js +0 -1
  281. package/dist/assets/extensions-CD6xvKF_.js +0 -1
  282. package/dist/assets/flowDiagram-23GEKE2U-BeKXabVO.js +0 -1
  283. package/dist/assets/form-actions-CC4Wz_lL.js +0 -1
  284. package/dist/assets/gitGraph-TEB2WS4Q-jTSiBj-p.js +0 -1
  285. package/dist/assets/index-BTsbdtv6.js +0 -109
  286. package/dist/assets/index-Bcfy2kTh.css +0 -1
  287. package/dist/assets/info-DKCQHKI2-BIporNWb.js +0 -1
  288. package/dist/assets/loader-circle-B6aFbB-8.js +0 -1
  289. package/dist/assets/mcp-marketplace-page-BtUAypA7.js +0 -1
  290. package/dist/assets/mcp-marketplace-page-r2MmD9xO.js +0 -10
  291. package/dist/assets/model-config-page-DboxoT-I.js +0 -1
  292. package/dist/assets/packet-7NZHBO7P-CuFMADV0.js +0 -1
  293. package/dist/assets/pie-RZYD4A2V-XUeIXhM9.js +0 -1
  294. package/dist/assets/plus-DRsq9Kvs.js +0 -1
  295. package/dist/assets/privacy-settings-page-C2sDBqhb.js +0 -1
  296. package/dist/assets/projects-BcPcx-uD.js +0 -1
  297. package/dist/assets/providers-config-page-CmUFl9RF.js +0 -1
  298. package/dist/assets/radar-I7S5WNFK-D-NNGh1k.js +0 -1
  299. package/dist/assets/railroad-3IZDKUUU-C67_uDaM.js +0 -1
  300. package/dist/assets/railroad-abnf-AHOZXSZD-BZ8Yflnd.js +0 -1
  301. package/dist/assets/railroad-ebnf-EBAXGLYW-B7zO7RoK.js +0 -1
  302. package/dist/assets/railroad-peg-LSFZ7HO6-R63PTgLz.js +0 -1
  303. package/dist/assets/react-BjO9I4WZ.js +0 -8
  304. package/dist/assets/remote-Ci6x91ES.js +0 -1
  305. package/dist/assets/runtime-config-page-cQKNeAjL.js +0 -1
  306. package/dist/assets/search-config-page-C8lOIkxn.js +0 -1
  307. package/dist/assets/secrets-config-page-8clzAag2.js +0 -3
  308. package/dist/assets/security-config-DPbM6IVT.js +0 -1
  309. package/dist/assets/select-CO9S_C2C.js +0 -41
  310. package/dist/assets/skeleton-IHILNhIW.js +0 -1
  311. package/dist/assets/stateDiagram-v2-6OUMAXLB-BE-HqxOK.js +0 -1
  312. package/dist/assets/swimlanesDiagram-G3AALYLV-Dr1H9LJH.js +0 -8
  313. package/dist/assets/treeView-QDETBFTQ-npJ5dbqS.js +0 -1
  314. package/dist/assets/treemap-6X3UGDF4-pYrBx6oa.js +0 -1
  315. package/dist/assets/wardley-OPB4EBWU-CmSRKLR8.js +0 -1
  316. package/dist/assets/x-BuvHIb1d.js +0 -1
  317. package/src/features/service-apps/managers/service-action-authorization.manager.ts +0 -10
  318. /package/dist/assets/{array-BQVzeGRt.js → array-BHDgItFN.js} +0 -0
  319. /package/dist/assets/{chunk-DseTPa7n.js → chunk-DF37yw5_.js} +0 -0
  320. /package/dist/assets/{chunk-KEIR6QF5-f9psyCXK.js → chunk-KEIR6QF5-DstBw0Hk.js} +0 -0
  321. /package/dist/assets/{chunk-Y2CYZVJY-D1mAU_Po.js → chunk-Y2CYZVJY-CA3ymQuH.js} +0 -0
  322. /package/dist/assets/{config-hints-nV5HPOvq.js → config-hints-CBPHrfYk.js} +0 -0
  323. /package/dist/assets/{cytoscape.esm-0uDtdD0l.js → cytoscape.esm-C7xr90o_.js} +0 -0
  324. /package/dist/assets/{defaultLocale-DSWXGgt0.js → defaultLocale-BG1oDVag.js} +0 -0
  325. /package/dist/assets/{graphlib-CQ6QV4yP.js → graphlib-CNMGfuTb.js} +0 -0
  326. /package/dist/assets/{host-capabilities-Tk038i04.js → host-capabilities-B107nwS3.js} +0 -0
  327. /package/dist/assets/{init-Y6h9jGtZ.js → init-wQIZuRSH.js} +0 -0
  328. /package/dist/assets/{katex-ARhY9PS1.js → katex-J8JuvgNl.js} +0 -0
  329. /package/dist/assets/{middleware-DXsbf9xI.js → middleware-0o3JF3tS.js} +0 -0
  330. /package/dist/assets/{path-10BjdyLh.js → path-N-C4MRP0.js} +0 -0
  331. /package/dist/assets/{preload-helper-D4M6sveU.js → preload-helper-ca-nBW7U.js} +0 -0
  332. /package/dist/assets/{rough.esm-DxgC_14r.js → rough.esm-BeWA068d.js} +0 -0
  333. /package/dist/assets/{xlsx-DrDuDNAa.js → xlsx-CwUXNtD3.js} +0 -0
@@ -1,21 +1,125 @@
1
1
  import { useState } from "react";
2
- import type { ProjectWorkItemDetail } from "@nextclaw/client-sdk";
3
- import { LayoutGrid, List, Plus, Settings2 } from "lucide-react";
2
+ import type {
3
+ ProjectWorkItemListEntry,
4
+ ProjectWorkState,
5
+ } from "@nextclaw/client-sdk";
6
+ import {
7
+ CheckCircle2,
8
+ ChevronDown,
9
+ ChevronRight,
10
+ Circle,
11
+ CircleDashed,
12
+ CircleX,
13
+ LayoutGrid,
14
+ List,
15
+ Plus,
16
+ Settings2,
17
+ } from "lucide-react";
4
18
  import { toast } from "sonner";
5
19
  import { Button } from "@/shared/components/ui/button";
6
20
  import { Input } from "@/shared/components/ui/input";
7
21
  import { t } from "@/shared/lib/i18n";
8
22
  import {
23
+ sortProjectWorkStates,
24
+ sortProjectWorkStatesForList,
9
25
  useProjectWork,
10
26
  useProjectWorkActions,
27
+ useProjectWorkEvents,
28
+ useProjectWorkStates,
11
29
  } from "@/features/projects/hooks/use-project-work";
30
+ import { getProjectWorkStateLabel } from "@/features/projects/utils/project-work-state-label.utils";
12
31
  import { ProjectWorkStateSettings } from "./project-work-state-settings";
13
32
 
33
+ function ProjectWorkStateIcon({
34
+ startedProgress,
35
+ state,
36
+ }: {
37
+ startedProgress: number | null;
38
+ state: ProjectWorkState;
39
+ }) {
40
+ if (state.category === "backlog")
41
+ return (
42
+ <span
43
+ aria-hidden="true"
44
+ data-state-visual="backlog"
45
+ className="inline-flex h-4 w-4 shrink-0 items-center justify-center text-muted-foreground/65"
46
+ >
47
+ <CircleDashed className="h-4 w-4" />
48
+ </span>
49
+ );
50
+ if (state.category === "unstarted")
51
+ return (
52
+ <span
53
+ aria-hidden="true"
54
+ data-state-visual="unstarted"
55
+ className="inline-flex h-4 w-4 shrink-0 items-center justify-center text-muted-foreground"
56
+ >
57
+ <Circle className="h-4 w-4" strokeWidth={2} />
58
+ </span>
59
+ );
60
+ if (state.category === "completed")
61
+ return (
62
+ <span
63
+ aria-hidden="true"
64
+ data-state-visual="completed"
65
+ className="inline-flex h-4 w-4 shrink-0 items-center justify-center text-emerald-600 dark:text-emerald-400"
66
+ >
67
+ <CheckCircle2 className="h-4 w-4" strokeWidth={2.25} />
68
+ </span>
69
+ );
70
+ if (state.category === "canceled")
71
+ return (
72
+ <span
73
+ aria-hidden="true"
74
+ data-state-visual="canceled"
75
+ className="inline-flex h-4 w-4 shrink-0 items-center justify-center text-muted-foreground/65"
76
+ >
77
+ <CircleX className="h-4 w-4" />
78
+ </span>
79
+ );
80
+ const progress = Math.round((startedProgress ?? 0.5) * 100);
81
+ const tone =
82
+ progress >= 67
83
+ ? "text-emerald-600 dark:text-emerald-400"
84
+ : progress >= 40
85
+ ? "text-orange-500 dark:text-orange-400"
86
+ : "text-amber-500 dark:text-amber-400";
87
+ return (
88
+ <span
89
+ aria-hidden="true"
90
+ data-state-visual="started"
91
+ className={`inline-flex h-4 w-4 shrink-0 items-center justify-center ${tone}`}
92
+ >
93
+ <svg className="h-4 w-4" viewBox="0 0 16 16" fill="none">
94
+ <circle
95
+ cx="8"
96
+ cy="8"
97
+ r="5.5"
98
+ stroke="currentColor"
99
+ strokeWidth="1.75"
100
+ opacity="0.22"
101
+ />
102
+ <circle
103
+ cx="8"
104
+ cy="8"
105
+ r="5.5"
106
+ pathLength="100"
107
+ stroke="currentColor"
108
+ strokeWidth="2"
109
+ strokeLinecap="round"
110
+ strokeDasharray={`${progress} ${100 - progress}`}
111
+ transform="rotate(-90 8 8)"
112
+ />
113
+ </svg>
114
+ </span>
115
+ );
116
+ }
117
+
14
118
  function WorkItemButton({
15
119
  item,
16
120
  onOpen,
17
121
  }: {
18
- item: ProjectWorkItemDetail;
122
+ item: ProjectWorkItemListEntry;
19
123
  onOpen: () => void;
20
124
  }) {
21
125
  return (
@@ -26,7 +130,7 @@ function WorkItemButton({
26
130
  >
27
131
  <span className="block font-medium">{item.title}</span>
28
132
  <span className="mt-1 flex flex-wrap items-center gap-1.5 text-xs text-muted-foreground">
29
- <span>{item.state.name}</span>
133
+ <span>{getProjectWorkStateLabel(item.state.name)}</span>
30
134
  {item.attention !== "none" ? (
31
135
  <span className="rounded-full bg-amber-500/15 px-2 py-0.5 text-amber-700 dark:text-amber-300">
32
136
  {t(`projectsWorkAttention_${item.attention}`)}
@@ -38,6 +142,138 @@ function WorkItemButton({
38
142
  );
39
143
  }
40
144
 
145
+ function ProjectWorkStateGroupBody({
146
+ hasNextPage,
147
+ isError,
148
+ isFetchingNextPage,
149
+ isLoading,
150
+ items,
151
+ onLoadMore,
152
+ onOpenWorkItem,
153
+ }: {
154
+ hasNextPage: boolean;
155
+ isError: boolean;
156
+ isFetchingNextPage: boolean;
157
+ isLoading: boolean;
158
+ items: ProjectWorkItemListEntry[];
159
+ onLoadMore: () => void;
160
+ onOpenWorkItem: (workItemId: string) => void;
161
+ }) {
162
+ if (isLoading)
163
+ return (
164
+ <p className="py-3 text-xs text-muted-foreground">
165
+ {t("projectsLoading")}
166
+ </p>
167
+ );
168
+ if (isError)
169
+ return (
170
+ <p className="py-3 text-xs text-destructive">{t("projectsLoadFailed")}</p>
171
+ );
172
+ return (
173
+ <>
174
+ {items.length ? (
175
+ items.map((item) => (
176
+ <WorkItemButton
177
+ key={item.id}
178
+ item={item}
179
+ onOpen={() => onOpenWorkItem(item.id)}
180
+ />
181
+ ))
182
+ ) : (
183
+ <p className="py-3 text-xs text-muted-foreground">
184
+ {t("projectsNoData")}
185
+ </p>
186
+ )}
187
+ {hasNextPage ? (
188
+ <Button
189
+ type="button"
190
+ variant="ghost"
191
+ size="sm"
192
+ className="w-full"
193
+ disabled={isFetchingNextPage}
194
+ onClick={onLoadMore}
195
+ >
196
+ {isFetchingNextPage
197
+ ? t("projectsLoading")
198
+ : t("projectsWorkLoadMore")}
199
+ </Button>
200
+ ) : null}
201
+ </>
202
+ );
203
+ }
204
+
205
+ function ProjectWorkStateGroup({
206
+ includeDeleted,
207
+ onOpenWorkItem,
208
+ state,
209
+ startedProgress,
210
+ view,
211
+ }: {
212
+ includeDeleted: boolean;
213
+ onOpenWorkItem: (workItemId: string) => void;
214
+ state: ProjectWorkState;
215
+ startedProgress: number | null;
216
+ view: "list" | "board";
217
+ }) {
218
+ const [collapsed, setCollapsed] = useState(false);
219
+ const work = useProjectWork(state.projectId, {
220
+ stateId: state.id,
221
+ includeDeleted,
222
+ limit: 20,
223
+ });
224
+ const items = work.data?.pages.flatMap((page) => page.items) ?? [];
225
+ const total = work.data?.pages[0]?.total;
226
+ return (
227
+ <section
228
+ className={
229
+ view === "board"
230
+ ? "flex h-full min-h-0 min-w-0 flex-col overflow-hidden rounded-xl bg-muted/25"
231
+ : "min-w-0 overflow-hidden rounded-xl border border-border/60"
232
+ }
233
+ aria-label={getProjectWorkStateLabel(state.name)}
234
+ >
235
+ <button
236
+ type="button"
237
+ className="flex w-full shrink-0 items-center gap-2 bg-muted/30 px-3 py-2.5 text-left transition-colors hover:bg-[var(--interaction-hover)] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border"
238
+ aria-expanded={!collapsed}
239
+ onClick={() => setCollapsed((value) => !value)}
240
+ >
241
+ {collapsed ? (
242
+ <ChevronRight className="h-4 w-4 shrink-0" />
243
+ ) : (
244
+ <ChevronDown className="h-4 w-4 shrink-0" />
245
+ )}
246
+ <ProjectWorkStateIcon state={state} startedProgress={startedProgress} />
247
+ <span className="min-w-0 truncate text-sm font-semibold">
248
+ {getProjectWorkStateLabel(state.name)}
249
+ </span>
250
+ <span className="inline-flex min-w-6 shrink-0 items-center justify-center rounded-full bg-background/85 px-1.5 py-0.5 text-xs font-semibold tabular-nums text-foreground ring-1 ring-border/60">
251
+ {total ?? "…"}
252
+ </span>
253
+ </button>
254
+ {!collapsed ? (
255
+ <div
256
+ className={
257
+ view === "board"
258
+ ? "min-h-0 flex-1 space-y-2 overflow-y-auto overscroll-contain p-3"
259
+ : "space-y-2 p-3"
260
+ }
261
+ >
262
+ <ProjectWorkStateGroupBody
263
+ hasNextPage={work.hasNextPage}
264
+ isError={work.isError}
265
+ isFetchingNextPage={work.isFetchingNextPage}
266
+ isLoading={work.isLoading}
267
+ items={items}
268
+ onLoadMore={() => void work.fetchNextPage()}
269
+ onOpenWorkItem={onOpenWorkItem}
270
+ />
271
+ </div>
272
+ ) : null}
273
+ </section>
274
+ );
275
+ }
276
+
41
277
  export function ProjectWorkItems({
42
278
  onOpenWorkItem,
43
279
  projectId,
@@ -49,7 +285,8 @@ export function ProjectWorkItems({
49
285
  const [includeDeleted, setIncludeDeleted] = useState(false);
50
286
  const [newTitle, setNewTitle] = useState("");
51
287
  const [settingsOpen, setSettingsOpen] = useState(false);
52
- const work = useProjectWork(projectId, includeDeleted);
288
+ useProjectWorkEvents(projectId);
289
+ const states = useProjectWorkStates(projectId);
53
290
  const actions = useProjectWorkActions(projectId);
54
291
  const create = async () => {
55
292
  if (!newTitle.trim()) return;
@@ -67,19 +304,29 @@ export function ProjectWorkItems({
67
304
  );
68
305
  }
69
306
  };
70
- if (work.isLoading)
307
+ if (states.isLoading)
71
308
  return (
72
309
  <div className="rounded-xl border border-border/60 p-5 text-sm text-muted-foreground">
73
310
  {t("projectsLoading")}
74
311
  </div>
75
312
  );
76
- if (work.isError)
313
+ if (states.isError)
77
314
  return (
78
315
  <div className="rounded-xl border border-destructive/40 p-5 text-sm text-destructive">
79
316
  {t("projectsLoadFailed")}
80
317
  </div>
81
318
  );
82
- const data = work.data!;
319
+ const sortedStates = sortProjectWorkStates(states.data ?? []);
320
+ const listStates = sortProjectWorkStatesForList(states.data ?? []);
321
+ const startedStates = sortedStates.filter(
322
+ (state) => state.category === "started",
323
+ );
324
+ const startedProgressById = new Map(
325
+ startedStates.map((state, index) => [
326
+ state.id,
327
+ (index + 1) / (startedStates.length + 1),
328
+ ]),
329
+ );
83
330
  return (
84
331
  <section aria-label={t("projectsWork")} className="min-w-0 space-y-4">
85
332
  <div className="flex flex-wrap items-center gap-2">
@@ -141,58 +388,39 @@ export function ProjectWorkItems({
141
388
  />
142
389
  {t("projectsWorkShowDeleted")}
143
390
  </label>
144
- {!data.items.length ? (
145
- <div className="rounded-xl border border-dashed border-border/60 p-8 text-center text-sm text-muted-foreground">
146
- {t("projectsWorkEmpty")}
147
- </div>
148
- ) : null}
149
- {view === "list" && data.items.length ? (
391
+ {view === "list" ? (
150
392
  <div className="space-y-2">
151
- {data.items.map((item) => (
152
- <WorkItemButton
153
- key={item.id}
154
- item={item}
155
- onOpen={() => onOpenWorkItem(item.id)}
393
+ {listStates.map((state) => (
394
+ <ProjectWorkStateGroup
395
+ key={state.id}
396
+ state={state}
397
+ startedProgress={startedProgressById.get(state.id) ?? null}
398
+ view={view}
399
+ includeDeleted={includeDeleted}
400
+ onOpenWorkItem={onOpenWorkItem}
156
401
  />
157
402
  ))}
158
403
  </div>
159
404
  ) : null}
160
- {view === "board" && data.items.length ? (
161
- <div className="grid min-w-0 gap-3 md:grid-cols-2 xl:grid-cols-3">
162
- {data.states.map((state) => {
163
- const items = data.items.filter(
164
- (item) => item.stateId === state.id,
165
- );
166
- return (
167
- <section
168
- key={state.id}
169
- className="min-w-0 rounded-xl bg-muted/35 p-3"
170
- >
171
- <div className="mb-3 flex items-center justify-between gap-2">
172
- <h3 className="text-sm font-semibold">{state.name}</h3>
173
- <span className="text-xs text-muted-foreground">
174
- {items.length}
175
- </span>
176
- </div>
177
- <div className="space-y-2">
178
- {items.map((item) => (
179
- <WorkItemButton
180
- key={item.id}
181
- item={item}
182
- onOpen={() => onOpenWorkItem(item.id)}
183
- />
184
- ))}
185
- </div>
186
- </section>
187
- );
188
- })}
405
+ {view === "board" ? (
406
+ <div className="grid h-[calc(100dvh-17rem)] min-h-[28rem] max-h-[52rem] min-w-0 auto-cols-[minmax(18rem,1fr)] grid-flow-col items-stretch gap-3 overflow-x-auto overflow-y-hidden pb-2">
407
+ {sortedStates.map((state) => (
408
+ <ProjectWorkStateGroup
409
+ key={state.id}
410
+ state={state}
411
+ startedProgress={startedProgressById.get(state.id) ?? null}
412
+ view={view}
413
+ includeDeleted={includeDeleted}
414
+ onOpenWorkItem={onOpenWorkItem}
415
+ />
416
+ ))}
189
417
  </div>
190
418
  ) : null}
191
419
  <ProjectWorkStateSettings
192
420
  open={settingsOpen}
193
421
  onOpenChange={setSettingsOpen}
194
422
  projectId={projectId}
195
- states={data.states}
423
+ states={sortedStates}
196
424
  />
197
425
  </section>
198
426
  );
@@ -27,6 +27,7 @@ import {
27
27
  sortProjectWorkStates,
28
28
  useProjectWorkActions,
29
29
  } from "@/features/projects/hooks/use-project-work";
30
+ import { getProjectWorkStateLabel } from "@/features/projects/utils/project-work-state-label.utils";
30
31
 
31
32
  const CATEGORIES: ProjectWorkStateCategory[] = [
32
33
  "backlog",
@@ -103,10 +104,13 @@ export function ProjectWorkStateSettings({
103
104
  >
104
105
  <Input
105
106
  aria-label={t("projectsWorkStateName")}
106
- defaultValue={state.name}
107
+ defaultValue={getProjectWorkStateLabel(state.name)}
107
108
  onBlur={(event) => {
108
109
  const nextName = event.currentTarget.value.trim();
109
- if (nextName && nextName !== state.name)
110
+ if (
111
+ nextName &&
112
+ nextName !== getProjectWorkStateLabel(state.name)
113
+ )
110
114
  void run(() =>
111
115
  actions.updateState.mutateAsync({
112
116
  stateId: state.id,
@@ -252,7 +256,7 @@ export function ProjectWorkStateSettings({
252
256
  .filter((state) => state.id !== deleting?.id)
253
257
  .map((state) => (
254
258
  <SelectItem key={state.id} value={state.id}>
255
- {state.name}
259
+ {getProjectWorkStateLabel(state.name)}
256
260
  </SelectItem>
257
261
  ))}
258
262
  </SelectContent>
@@ -1,8 +1,14 @@
1
1
  import type { ReactNode } from "react";
2
2
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
3
- import { renderHook, waitFor } from "@testing-library/react";
3
+ import { act, renderHook, waitFor } from "@testing-library/react";
4
4
  import { beforeEach, describe, expect, it, vi } from "vitest";
5
- import { useProjectWork } from "./use-project-work";
5
+ import type { ProjectWorkState } from "@nextclaw/client-sdk";
6
+ import {
7
+ sortProjectWorkStates,
8
+ sortProjectWorkStatesForList,
9
+ useProjectWork,
10
+ useProjectWorkEvents,
11
+ } from "./use-project-work";
6
12
 
7
13
  const mocks = vi.hoisted(() => ({
8
14
  handler: null as
@@ -31,7 +37,7 @@ vi.mock("@/shared/lib/api", () => ({
31
37
  describe("useProjectWork", () => {
32
38
  beforeEach(() => {
33
39
  mocks.listWork.mockReset();
34
- mocks.listWork.mockResolvedValue({ items: [], states: [], total: 0 });
40
+ mocks.listWork.mockResolvedValue({ items: [], nextCursor: null, total: 0 });
35
41
  });
36
42
 
37
43
  it("refreshes the project query from committed work events only for the matching project", async () => {
@@ -41,9 +47,15 @@ describe("useProjectWork", () => {
41
47
  const wrapper = ({ children }: { children: ReactNode }) => (
42
48
  <QueryClientProvider client={client}>{children}</QueryClientProvider>
43
49
  );
44
- const { unmount } = renderHook(() => useProjectWork("project-1"), {
45
- wrapper,
46
- });
50
+ const { unmount } = renderHook(
51
+ () => {
52
+ useProjectWorkEvents("project-1");
53
+ return useProjectWork("project-1", { stateId: "planned", limit: 20 });
54
+ },
55
+ {
56
+ wrapper,
57
+ },
58
+ );
47
59
  await waitFor(() => expect(mocks.listWork).toHaveBeenCalledTimes(1));
48
60
 
49
61
  mocks.handler?.({ projectId: "project-2" });
@@ -55,4 +67,94 @@ describe("useProjectWork", () => {
55
67
  unmount();
56
68
  expect(mocks.handler).toBeNull();
57
69
  });
70
+
71
+ it("loads the next opaque cursor without changing the state-scoped query", async () => {
72
+ mocks.listWork
73
+ .mockResolvedValueOnce({
74
+ items: [{ id: "one" }],
75
+ nextCursor: "next",
76
+ total: 2,
77
+ })
78
+ .mockResolvedValueOnce({
79
+ items: [{ id: "two" }],
80
+ nextCursor: null,
81
+ total: 2,
82
+ });
83
+ const client = new QueryClient({
84
+ defaultOptions: { queries: { retry: false } },
85
+ });
86
+ const wrapper = ({ children }: { children: ReactNode }) => (
87
+ <QueryClientProvider client={client}>{children}</QueryClientProvider>
88
+ );
89
+ const { result } = renderHook(
90
+ () => useProjectWork("project-1", { stateId: "planned", limit: 20 }),
91
+ { wrapper },
92
+ );
93
+ await waitFor(() => expect(result.current.hasNextPage).toBe(true));
94
+
95
+ await act(async () => await result.current.fetchNextPage());
96
+
97
+ expect(mocks.listWork).toHaveBeenNthCalledWith(1, "project-1", {
98
+ stateId: "planned",
99
+ limit: 20,
100
+ });
101
+ expect(mocks.listWork).toHaveBeenNthCalledWith(2, "project-1", {
102
+ stateId: "planned",
103
+ limit: 20,
104
+ cursor: "next",
105
+ });
106
+ await waitFor(() => expect(result.current.data?.pages).toHaveLength(2));
107
+ });
108
+ });
109
+
110
+ describe("project work state ordering", () => {
111
+ const state = (
112
+ name: string,
113
+ category: ProjectWorkState["category"],
114
+ position: number,
115
+ ): ProjectWorkState => ({
116
+ id: name,
117
+ projectId: "project-1",
118
+ name,
119
+ category,
120
+ position,
121
+ isDefault: false,
122
+ createdAt: "2026-09-01T00:00:00.000Z",
123
+ updatedAt: "2026-09-01T00:00:00.000Z",
124
+ });
125
+ const states = [
126
+ state("Backlog", "backlog", 0),
127
+ state("Planned", "unstarted", 1),
128
+ state("In Progress", "started", 2),
129
+ state("In Review", "started", 3),
130
+ state("Awaiting Acceptance", "started", 4),
131
+ state("Completed", "completed", 5),
132
+ state("Canceled", "canceled", 6),
133
+ ];
134
+
135
+ it("surfaces active states closest to done in list view", () => {
136
+ expect(
137
+ sortProjectWorkStatesForList(states).map(({ name }) => name),
138
+ ).toEqual([
139
+ "Awaiting Acceptance",
140
+ "In Review",
141
+ "In Progress",
142
+ "Planned",
143
+ "Backlog",
144
+ "Completed",
145
+ "Canceled",
146
+ ]);
147
+ });
148
+
149
+ it("keeps workflow order for board and state settings", () => {
150
+ expect(sortProjectWorkStates(states).map(({ name }) => name)).toEqual([
151
+ "Backlog",
152
+ "Planned",
153
+ "In Progress",
154
+ "In Review",
155
+ "Awaiting Acceptance",
156
+ "Completed",
157
+ "Canceled",
158
+ ]);
159
+ });
58
160
  });