@nocobase/portal-template-default 1.0.9 → 1.0.11

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 (338) hide show
  1. package/.env.example +5 -0
  2. package/.github/workflows/publish.yml +106 -0
  3. package/.gitignore +33 -0
  4. package/AGENTS.md +19 -0
  5. package/README.MD +61 -180
  6. package/dist/assets/{LineDraw-C0m1GONT.js → LineDraw-iG-ADes-.js} +1 -1
  7. package/dist/assets/{SymbolDraw-CCospe5G.js → SymbolDraw-DXoSw1tM.js} +1 -1
  8. package/dist/assets/VisualMapping-C_ee4Eht.js +1 -0
  9. package/dist/assets/auth-method-demo-DaOCuvsq.js +1 -0
  10. package/dist/assets/auto-login-provider-5Uxza9Ms.js +2 -0
  11. package/dist/assets/auto-login-provider-DyaPGK2D.js +1 -0
  12. package/dist/assets/auto-redirect-provider-CfwRvYOI.js +1 -0
  13. package/dist/assets/auto-redirect-provider-Cr3jmYts.js +1 -0
  14. package/dist/assets/auto-redirect-provider-QkJQRBbG.js +1 -0
  15. package/dist/assets/calendar-DjDRfD5t.js +1 -0
  16. package/dist/assets/card-DuQBOS6A.js +1 -0
  17. package/dist/assets/cas-sign-in-button-CyqG1QME.js +1 -0
  18. package/dist/assets/components-D-ptYjX_.js +20 -0
  19. package/dist/assets/configuration-gate-C08mkkiX.js +1 -0
  20. package/dist/assets/{createClipPathFromCoordSys-uEftn1Mq.js → createClipPathFromCoordSys-wj34-b1B.js} +1 -1
  21. package/dist/assets/createSeriesDataSimply-D0A6SAVQ.js +1 -0
  22. package/dist/assets/customGraphicKeyframeAnimation-DWrhrHL_.js +3 -0
  23. package/dist/assets/demo-BYWHeKUe.js +1 -0
  24. package/dist/assets/demo-CPWoNtx8.js +1 -0
  25. package/dist/assets/demo-CyvJk5zV.js +1 -0
  26. package/dist/assets/demo-D4OiKplc.js +1 -0
  27. package/dist/assets/demo-DBueJg0m.js +1 -0
  28. package/dist/assets/demo-DkIhyiRK.js +1 -0
  29. package/dist/assets/demo-tpTjO0sC.js +1 -0
  30. package/dist/assets/dingtalk-sign-in-button-DSWsSruv.js +1 -0
  31. package/dist/assets/echarts-preview-DxHNfq1C.js +1 -0
  32. package/dist/assets/{echarts-runtime-CEgJbv68.js → echarts-runtime-D8kXn6ME.js} +3 -3
  33. package/dist/assets/{echarts-runtime-advanced-Buhm2BHz.js → echarts-runtime-advanced-QY8v95qK.js} +1 -1
  34. package/dist/assets/{echarts-runtime-common-DLAdBAIa.js → echarts-runtime-common-D-yqAK-r.js} +1 -1
  35. package/dist/assets/{echarts-runtime-components-ypnyLkYx.js → echarts-runtime-components-P4-i8jPU.js} +1 -1
  36. package/dist/assets/{echarts-runtime-hierarchy-ClStquCF.js → echarts-runtime-hierarchy-ByQZ-DbP.js} +1 -1
  37. package/dist/assets/floating-BFVEyPEp.js +15 -0
  38. package/dist/assets/index-BgCbGDMc.js +43 -0
  39. package/dist/assets/index-Btk35Nx-.js +23 -0
  40. package/dist/assets/index-CwNxd66J.js +1 -0
  41. package/dist/assets/index-MB-jfQld.js +686 -0
  42. package/dist/assets/index-NH3aqqQz.css +1 -0
  43. package/dist/assets/index-gFtCXH3o.js +58 -0
  44. package/dist/assets/index-um5hdKdZ.js +23 -0
  45. package/dist/assets/{labelHelper-C137W5gU.js → labelHelper-DQqRy3a_.js} +1 -1
  46. package/dist/assets/ldap-sign-in-form--6Gt3yGq.js +1 -0
  47. package/dist/assets/oidc-sign-in-button-CQdRcR_p.js +1 -0
  48. package/dist/assets/{page-context-Cxx11gzg.js → page-context-CnQ4GYM7.js} +10 -10
  49. package/dist/assets/prompt-card-B2RS4nt2.js +1 -0
  50. package/dist/assets/prompt-output-DZHRM2ft.js +1 -0
  51. package/dist/assets/saml-sign-in-button-BHL5a0JV.js +1 -0
  52. package/dist/assets/{sectorHelper-Fqgz3uEk.js → sectorHelper-DN_Vv6OL.js} +1 -1
  53. package/dist/assets/shortcut-C5x5LQWU.js +47 -0
  54. package/dist/assets/sms-sign-in-form-DTX9GV2I.js +1 -0
  55. package/dist/assets/{static.browser-CfQQzERe.js → static.browser-jI1psK0d.js} +8 -8
  56. package/dist/assets/{switch-DrxImI8F.js → switch-CRL8PmRI.js} +1 -1
  57. package/dist/assets/{tool-cards-BGfsY8JF.js → tool-cards-DFttLAfo.js} +6 -7
  58. package/dist/assets/use-authenticator-sign-in-CRGjzXju.js +1 -0
  59. package/dist/assets/use-dingtalk-sign-in-8WYzJ2jf.js +1 -0
  60. package/dist/assets/use-wecom-sign-in-C9j8wfCD.js +1 -0
  61. package/dist/assets/wecom-sign-in-button-mIS1zGSU.js +1 -0
  62. package/dist/index.html +2 -2
  63. package/dist/index.raw.html +5 -2
  64. package/package.json +3 -5
  65. package/scripts/build-html.mjs +12 -0
  66. package/src/App.css +2 -0
  67. package/src/App.tsx +35 -186
  68. package/src/app/development.tsx +154 -0
  69. package/src/app/extension.ts +5 -0
  70. package/src/app/extensions.tsx +18 -4
  71. package/src/app/routes.tsx +65 -0
  72. package/src/components/access-control/acl-bootstrap.tsx +11 -3
  73. package/src/components/access-control/acl-gate.tsx +7 -6
  74. package/src/components/access-control/can-access.tsx +17 -0
  75. package/src/components/access-control/navigate-to-accessible-resource.tsx +8 -3
  76. package/src/components/app-shell/sidebar.tsx +21 -5
  77. package/src/components/auth/auto-redirect-provider.tsx +2 -1
  78. package/src/extensions/nocobase-acl/README.md +74 -0
  79. package/{registry → src/extensions}/nocobase-acl/components/acl-boundary.tsx +22 -25
  80. package/{registry → src/extensions}/nocobase-acl/components/role-switcher.tsx +26 -23
  81. package/src/extensions/nocobase-acl/demo/acl-preview-provider.tsx +81 -0
  82. package/{registry → src/extensions}/nocobase-acl/demo/boundary-api.tsx +58 -0
  83. package/{registry → src/extensions}/nocobase-acl/demo/index.tsx +243 -105
  84. package/{registry → src/extensions}/nocobase-acl/demo/prompt-generator.tsx +3 -1
  85. package/src/extensions/nocobase-acl/extension.tsx +73 -0
  86. package/{registry → src/extensions}/nocobase-ai/README.md +21 -5
  87. package/{registry → src/extensions}/nocobase-ai/components/chat/chat-composer.tsx +3 -1
  88. package/{registry → src/extensions}/nocobase-ai/components/chat/chat-messages.tsx +38 -3
  89. package/{registry → src/extensions}/nocobase-ai/components/chat/tool-call-card.tsx +1 -9
  90. package/{registry → src/extensions}/nocobase-ai/components/index.ts +5 -0
  91. package/src/extensions/nocobase-ai/components/surfaces/chat-dialog.tsx +17 -0
  92. package/src/extensions/nocobase-ai/components/surfaces/chat-side-panel.tsx +35 -0
  93. package/src/extensions/nocobase-ai/components/surfaces/chat-surface.tsx +108 -0
  94. package/{registry → src/extensions}/nocobase-ai/components/triggers/ai-chat-floating-trigger.tsx +2 -2
  95. package/{registry → src/extensions}/nocobase-ai/demo/configuration-gate.tsx +4 -1
  96. package/{registry → src/extensions}/nocobase-ai/demo/container-showcase.tsx +2 -2
  97. package/{registry → src/extensions}/nocobase-ai/demo/floating.tsx +45 -15
  98. package/{registry → src/extensions}/nocobase-ai/demo/index.tsx +116 -74
  99. package/{registry → src/extensions}/nocobase-ai/demo/prompt-generator.tsx +3 -3
  100. package/{registry → src/extensions}/nocobase-ai/demo/tool-cards.tsx +2 -3
  101. package/src/extensions/nocobase-ai/extension.tsx +160 -0
  102. package/{registry → src/extensions}/nocobase-ai/global-ai-chat.tsx +12 -28
  103. package/{registry → src/extensions}/nocobase-ai/providers/ai-provider.tsx +14 -1
  104. package/{registry → src/extensions}/nocobase-ai/providers/chat-context.tsx +1 -0
  105. package/{registry → src/extensions}/nocobase-ai/providers/chat-provider.tsx +29 -8
  106. package/{registry → src/extensions}/nocobase-ai/providers/use-chat-attachments.ts +6 -1
  107. package/{registry → src/extensions}/nocobase-ai/providers/use-chat-work-context.ts +4 -1
  108. package/{registry → src/extensions}/nocobase-route-surfaces/README.md +2 -1
  109. package/{registry → src/extensions}/nocobase-route-surfaces/demo/index.tsx +33 -7
  110. package/{registry → src/extensions}/nocobase-route-surfaces/demo/scenarios.ts +20 -14
  111. package/{registry → src/extensions}/nocobase-route-surfaces/extension.tsx +55 -52
  112. package/src/{pages/users → extensions/nocobase-users-example}/create.tsx +4 -4
  113. package/src/{pages/users → extensions/nocobase-users-example}/edit.tsx +5 -9
  114. package/src/extensions/nocobase-users-example/extension.tsx +109 -0
  115. package/src/{pages/users → extensions/nocobase-users-example}/form-context.ts +11 -9
  116. package/src/extensions/nocobase-users-example/layout.tsx +16 -0
  117. package/src/{pages/users → extensions/nocobase-users-example}/list.tsx +1 -1
  118. package/src/extensions/nocobase-users-example/locales/en-US.ts +77 -0
  119. package/src/extensions/nocobase-users-example/locales/index.ts +8 -0
  120. package/src/extensions/nocobase-users-example/locales/zh-CN.ts +73 -0
  121. package/src/extensions/nocobase-users-example/optional-ai.ts +67 -0
  122. package/src/{pages/users → extensions/nocobase-users-example}/role-detail.tsx +4 -15
  123. package/src/{pages/users → extensions/nocobase-users-example}/routes.ts +1 -4
  124. package/src/extensions/nocobase-users-example/show.tsx +266 -0
  125. package/src/lib/nocobase/acl/context.ts +32 -0
  126. package/src/lib/nocobase/acl/evaluator.ts +186 -0
  127. package/src/lib/nocobase/acl/hooks.ts +40 -0
  128. package/src/lib/nocobase/acl/index.ts +4 -1
  129. package/src/lib/nocobase/acl/menu.ts +6 -6
  130. package/src/lib/nocobase/acl/record-permissions.ts +37 -7
  131. package/src/lib/nocobase/acl/store-provider.tsx +14 -0
  132. package/src/lib/nocobase/acl/store.ts +92 -86
  133. package/src/lib/nocobase/acl/types.ts +52 -32
  134. package/src/lib/nocobase/auth-session.ts +128 -0
  135. package/src/lib/nocobase/client.ts +48 -50
  136. package/src/locales/en-US.ts +0 -78
  137. package/src/locales/index.ts +2 -7
  138. package/src/locales/zh-CN.ts +0 -74
  139. package/src/providers/access-control.ts +43 -8
  140. package/src/providers/auth-callback.ts +1 -0
  141. package/src/providers/auth.ts +24 -26
  142. package/src/providers/constants.ts +0 -4
  143. package/src/providers/data.ts +14 -26
  144. package/src/providers/runtime-config.ts +40 -0
  145. package/src/vite-env.d.ts +9 -0
  146. package/tests/auth-session-regression.mjs +101 -0
  147. package/tsconfig.json +2 -1
  148. package/vite.config.ts +9 -1
  149. package/dist/assets/VisualMapping-Cbv1v7Cd.js +0 -1
  150. package/dist/assets/ai-employee-shortcut-B253WWow.js +0 -1
  151. package/dist/assets/calendar-B3dXXyIv.js +0 -1
  152. package/dist/assets/chat-inline-xpQ9iq4p.js +0 -1
  153. package/dist/assets/chat-side-panel-layout-BVWsp5rr.js +0 -1
  154. package/dist/assets/components-ChhJaNRc.js +0 -20
  155. package/dist/assets/configuration-gate-Dwdq_lxf.js +0 -1
  156. package/dist/assets/createSeriesDataSimply-CI7l7Ufv.js +0 -1
  157. package/dist/assets/customGraphicKeyframeAnimation-DE3jSfMd.js +0 -3
  158. package/dist/assets/echarts-preview-C-cNUtJF.js +0 -1
  159. package/dist/assets/floating-BarTmn-b.js +0 -13
  160. package/dist/assets/index-BJIcYTdc.js +0 -53
  161. package/dist/assets/index-C6xNKxpg.js +0 -656
  162. package/dist/assets/index-D4JQi1TM.js +0 -54
  163. package/dist/assets/index-YA7-AUO8.css +0 -1
  164. package/dist/assets/index-g8zWVpP9.js +0 -23
  165. package/dist/assets/prompt-card-BsYMW_rq.js +0 -1
  166. package/dist/assets/shortcut-xtghDP63.js +0 -47
  167. package/registry/nocobase-acl/README.md +0 -19
  168. package/registry/nocobase-acl/extension.tsx +0 -71
  169. package/registry/nocobase-acl/tests/acl-regression.mjs +0 -314
  170. package/registry/nocobase-ai/components/surfaces/chat-dialog.tsx +0 -31
  171. package/registry/nocobase-ai/components/surfaces/chat-side-panel.tsx +0 -74
  172. package/registry/nocobase-ai/extension.tsx +0 -158
  173. package/registry/nocobase-ai/tests/business-report-regression.mjs +0 -70
  174. package/registry/nocobase-ai/tests/form-filler-regression.mjs +0 -129
  175. package/registry/nocobase-ai/tests/frontend-tool-regression.mjs +0 -128
  176. package/registry/nocobase-ai/tests/page-context-regression.mjs +0 -48
  177. package/registry/nocobase-ai/tests/stream-regression.mjs +0 -207
  178. package/registry/nocobase-auth-cas/README.md +0 -6
  179. package/registry/nocobase-auth-cas/cas-sign-in-button.tsx +0 -41
  180. package/registry/nocobase-auth-cas/demo.tsx +0 -20
  181. package/registry/nocobase-auth-cas/extension.tsx +0 -46
  182. package/registry/nocobase-auth-cas/index.ts +0 -1
  183. package/registry/nocobase-auth-cas/use-cas-sign-in.ts +0 -29
  184. package/registry/nocobase-auth-dingtalk/README.md +0 -7
  185. package/registry/nocobase-auth-dingtalk/auto-login-provider.tsx +0 -154
  186. package/registry/nocobase-auth-dingtalk/demo.tsx +0 -23
  187. package/registry/nocobase-auth-dingtalk/dingtalk-sign-in-button.tsx +0 -45
  188. package/registry/nocobase-auth-dingtalk/extension.tsx +0 -55
  189. package/registry/nocobase-auth-dingtalk/index.ts +0 -4
  190. package/registry/nocobase-auth-dingtalk/use-dingtalk-sign-in.ts +0 -64
  191. package/registry/nocobase-auth-ldap/README.md +0 -6
  192. package/registry/nocobase-auth-ldap/demo.tsx +0 -21
  193. package/registry/nocobase-auth-ldap/extension.tsx +0 -46
  194. package/registry/nocobase-auth-ldap/index.ts +0 -1
  195. package/registry/nocobase-auth-ldap/ldap-sign-in-form.tsx +0 -69
  196. package/registry/nocobase-auth-ldap/use-ldap-sign-in.ts +0 -5
  197. package/registry/nocobase-auth-oidc/README.md +0 -11
  198. package/registry/nocobase-auth-oidc/auto-redirect-provider.tsx +0 -13
  199. package/registry/nocobase-auth-oidc/demo.tsx +0 -20
  200. package/registry/nocobase-auth-oidc/extension.tsx +0 -51
  201. package/registry/nocobase-auth-oidc/index.ts +0 -1
  202. package/registry/nocobase-auth-oidc/oidc-sign-in-button.tsx +0 -44
  203. package/registry/nocobase-auth-oidc/use-oidc-sign-in.ts +0 -58
  204. package/registry/nocobase-auth-saml/README.md +0 -6
  205. package/registry/nocobase-auth-saml/auto-redirect-provider.tsx +0 -13
  206. package/registry/nocobase-auth-saml/demo.tsx +0 -20
  207. package/registry/nocobase-auth-saml/extension.tsx +0 -51
  208. package/registry/nocobase-auth-saml/index.ts +0 -1
  209. package/registry/nocobase-auth-saml/saml-sign-in-button.tsx +0 -43
  210. package/registry/nocobase-auth-saml/use-saml-sign-in.ts +0 -51
  211. package/registry/nocobase-auth-sms/README.md +0 -7
  212. package/registry/nocobase-auth-sms/demo.tsx +0 -25
  213. package/registry/nocobase-auth-sms/extension.tsx +0 -46
  214. package/registry/nocobase-auth-sms/index.ts +0 -1
  215. package/registry/nocobase-auth-sms/sms-sign-in-form.tsx +0 -107
  216. package/registry/nocobase-auth-sms/use-sms-sign-in.ts +0 -88
  217. package/registry/nocobase-auth-wecom/README.md +0 -6
  218. package/registry/nocobase-auth-wecom/auto-login-provider.tsx +0 -21
  219. package/registry/nocobase-auth-wecom/demo.tsx +0 -23
  220. package/registry/nocobase-auth-wecom/extension.tsx +0 -49
  221. package/registry/nocobase-auth-wecom/index.ts +0 -1
  222. package/registry/nocobase-auth-wecom/use-wecom-sign-in.ts +0 -62
  223. package/registry/nocobase-auth-wecom/wecom-sign-in-button.tsx +0 -70
  224. package/registry/nocobase-i18n/README.md +0 -44
  225. package/registry/nocobase-i18n/components/index.ts +0 -1
  226. package/registry/nocobase-i18n/components/language-switcher.tsx +0 -138
  227. package/registry/nocobase-i18n/demo/index.tsx +0 -209
  228. package/registry/nocobase-i18n/demo/prompt-generator.tsx +0 -132
  229. package/registry/nocobase-i18n/extension.tsx +0 -45
  230. package/registry/nocobase-i18n/index.ts +0 -7
  231. package/registry/nocobase-i18n/locales/en-US.ts +0 -39
  232. package/registry/nocobase-i18n/locales/index.ts +0 -8
  233. package/registry/nocobase-i18n/locales/zh-CN.ts +0 -35
  234. package/registry/nocobase-i18n/provider.tsx +0 -44
  235. package/registry/nocobase-i18n/server-resources.ts +0 -166
  236. package/registry/nocobase-i18n/tests/i18n-regression.mjs +0 -51
  237. package/registry.config.json +0 -302
  238. package/scripts/registry.mjs +0 -164
  239. package/src/components/access-control/resource-access-guard.tsx +0 -21
  240. package/src/components/access-control/use-acl-runtime.ts +0 -28
  241. package/src/lib/nocobase/acl/action.ts +0 -147
  242. package/src/pages/users/layout.tsx +0 -15
  243. package/src/pages/users/show.tsx +0 -278
  244. /package/{registry → src/extensions}/nocobase-acl/components/index.ts +0 -0
  245. /package/{registry → src/extensions}/nocobase-acl/components/role-options.ts +0 -0
  246. /package/{registry → src/extensions}/nocobase-acl/demo/components.tsx +0 -0
  247. /package/{registry → src/extensions}/nocobase-acl/demo/lazy-route.tsx +0 -0
  248. /package/{registry → src/extensions}/nocobase-acl/demo/role-switcher-prompt-generator.tsx +0 -0
  249. /package/{registry → src/extensions}/nocobase-acl/demo/scenario-section.tsx +0 -0
  250. /package/{registry → src/extensions}/nocobase-acl/index.ts +0 -0
  251. /package/{registry → src/extensions}/nocobase-ai/adapters/react-hook-form.ts +0 -0
  252. /package/{registry → src/extensions}/nocobase-ai/assets/nocobase-ai-chat.svg +0 -0
  253. /package/{registry → src/extensions}/nocobase-ai/components/ai-root-provider.tsx +0 -0
  254. /package/{registry → src/extensions}/nocobase-ai/components/chat/ai-employee-avatar.tsx +0 -0
  255. /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-attachment.tsx +0 -0
  256. /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-compact.tsx +0 -0
  257. /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-empty-state.tsx +0 -0
  258. /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-header.tsx +0 -0
  259. /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-history-dialog.tsx +0 -0
  260. /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-message.tsx +0 -0
  261. /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-window.tsx +0 -0
  262. /package/{registry → src/extensions}/nocobase-ai/components/chat/conversation-list.tsx +0 -0
  263. /package/{registry → src/extensions}/nocobase-ai/components/chat/markdown-message.tsx +0 -0
  264. /package/{registry → src/extensions}/nocobase-ai/components/chat/model-select-options.tsx +0 -0
  265. /package/{registry → src/extensions}/nocobase-ai/components/chat/reasoning-panel.tsx +0 -0
  266. /package/{registry → src/extensions}/nocobase-ai/components/chat/sub-agent-conversation.tsx +0 -0
  267. /package/{registry → src/extensions}/nocobase-ai/components/chat/user-prompt-editor.tsx +0 -0
  268. /package/{registry → src/extensions}/nocobase-ai/components/chat/work-context-chip.tsx +0 -0
  269. /package/{registry → src/extensions}/nocobase-ai/components/page-elements/ai-form.tsx +0 -0
  270. /package/{registry → src/extensions}/nocobase-ai/components/page-elements/page-element-provider.tsx +0 -0
  271. /package/{registry → src/extensions}/nocobase-ai/components/surfaces/chat-inline.tsx +0 -0
  272. /package/{registry → src/extensions}/nocobase-ai/components/surfaces/chat-page.tsx +0 -0
  273. /package/{registry → src/extensions}/nocobase-ai/components/surfaces/chat-side-panel-layout.tsx +0 -0
  274. /package/{registry → src/extensions}/nocobase-ai/components/surfaces/chat-surface-actions.tsx +0 -0
  275. /package/{registry → src/extensions}/nocobase-ai/components/tools/builtin-tool-renderers.tsx +0 -0
  276. /package/{registry → src/extensions}/nocobase-ai/components/tools/business-report-dialog.tsx +0 -0
  277. /package/{registry → src/extensions}/nocobase-ai/components/tools/business-report-renderer.tsx +0 -0
  278. /package/{registry → src/extensions}/nocobase-ai/components/tools/business-report-utils.tsx +0 -0
  279. /package/{registry → src/extensions}/nocobase-ai/components/tools/chart-renderer.tsx +0 -0
  280. /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-preview.tsx +0 -0
  281. /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-runtime-advanced.ts +0 -0
  282. /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-runtime-common.ts +0 -0
  283. /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-runtime-components.ts +0 -0
  284. /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-runtime-hierarchy.ts +0 -0
  285. /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-runtime.ts +0 -0
  286. /package/{registry → src/extensions}/nocobase-ai/components/tools/sub-agent-renderer.tsx +0 -0
  287. /package/{registry → src/extensions}/nocobase-ai/components/tools/suggestions-renderer.tsx +0 -0
  288. /package/{registry → src/extensions}/nocobase-ai/components/tools/tool-renderer-provider.tsx +0 -0
  289. /package/{registry → src/extensions}/nocobase-ai/components/tools/tool-renderer-utils.ts +0 -0
  290. /package/{registry → src/extensions}/nocobase-ai/components/tools/workflow-renderer.tsx +0 -0
  291. /package/{registry → src/extensions}/nocobase-ai/components/triggers/ai-employee-shortcut.tsx +0 -0
  292. /package/{registry → src/extensions}/nocobase-ai/demo/interaction-showcase.tsx +0 -0
  293. /package/{registry → src/extensions}/nocobase-ai/demo/page-context-prompt-generator.tsx +0 -0
  294. /package/{registry → src/extensions}/nocobase-ai/demo/page-context.tsx +0 -0
  295. /package/{registry → src/extensions}/nocobase-ai/demo/page-element-showcase.tsx +0 -0
  296. /package/{registry → src/extensions}/nocobase-ai/demo/prompt-card.tsx +0 -0
  297. /package/{registry → src/extensions}/nocobase-ai/demo/shortcut.tsx +0 -0
  298. /package/{registry → src/extensions}/nocobase-ai/index.ts +0 -0
  299. /package/{registry → src/extensions}/nocobase-ai/providers/avatars.ts +0 -0
  300. /package/{registry → src/extensions}/nocobase-ai/providers/chat-controller.ts +0 -0
  301. /package/{registry → src/extensions}/nocobase-ai/providers/chat-message-utils.ts +0 -0
  302. /package/{registry → src/extensions}/nocobase-ai/providers/chat-reducer.ts +0 -0
  303. /package/{registry → src/extensions}/nocobase-ai/providers/chat-task-utils.ts +0 -0
  304. /package/{registry → src/extensions}/nocobase-ai/providers/chat-transport.ts +0 -0
  305. /package/{registry → src/extensions}/nocobase-ai/providers/form-registry.tsx +0 -0
  306. /package/{registry → src/extensions}/nocobase-ai/providers/frontend-tool-registry.tsx +0 -0
  307. /package/{registry → src/extensions}/nocobase-ai/providers/index.ts +0 -0
  308. /package/{registry → src/extensions}/nocobase-ai/providers/model.ts +0 -0
  309. /package/{registry → src/extensions}/nocobase-ai/providers/page-context.tsx +0 -0
  310. /package/{registry → src/extensions}/nocobase-ai/providers/stream-coalescer.ts +0 -0
  311. /package/{registry → src/extensions}/nocobase-ai/providers/stream-event-utils.ts +0 -0
  312. /package/{registry → src/extensions}/nocobase-ai/providers/stream-parser.ts +0 -0
  313. /package/{registry → src/extensions}/nocobase-ai/providers/sub-agent-stream.ts +0 -0
  314. /package/{registry → src/extensions}/nocobase-ai/providers/types.ts +0 -0
  315. /package/{registry → src/extensions}/nocobase-ai/providers/ui-message-stream.ts +0 -0
  316. /package/{registry → src/extensions}/nocobase-ai/providers/use-automatic-tool-approval.ts +0 -0
  317. /package/{registry → src/extensions}/nocobase-ai/providers/use-chat-message-actions.ts +0 -0
  318. /package/{registry → src/extensions}/nocobase-ai/providers/use-chat-runtime.ts +0 -0
  319. /package/{registry → src/extensions}/nocobase-ai/providers/use-conversation-catalog.ts +0 -0
  320. /package/{registry → src/extensions}/nocobase-ai/providers/use-conversation-history.ts +0 -0
  321. /package/{registry → src/extensions}/nocobase-ai/services/index.ts +0 -0
  322. /package/{registry → src/extensions}/nocobase-ai/services/nocobase-ai-service.ts +0 -0
  323. /package/{registry → src/extensions}/nocobase-ai/services/types.ts +0 -0
  324. /package/{registry → src/extensions}/nocobase-route-surfaces/demo/lazy-route.tsx +0 -0
  325. /package/{registry → src/extensions}/nocobase-route-surfaces/demo/prompt-generator.tsx +0 -0
  326. /package/{registry → src/extensions}/nocobase-route-surfaces/index.ts +0 -0
  327. /package/{registry → src/extensions}/nocobase-route-surfaces/route-dialog.tsx +0 -0
  328. /package/{registry → src/extensions}/nocobase-route-surfaces/route-drawer.tsx +0 -0
  329. /package/{registry → src/extensions}/nocobase-route-surfaces/route-page.tsx +0 -0
  330. /package/{registry → src/extensions}/nocobase-route-surfaces/route-surface-context.ts +0 -0
  331. /package/{registry → src/extensions}/nocobase-route-surfaces/use-refine-unsaved-changes.tsx +0 -0
  332. /package/{registry → src/extensions}/nocobase-route-surfaces/use-route-surface-close.ts +0 -0
  333. /package/{registry → src/extensions}/nocobase-route-surfaces/use-route-surface-state.ts +0 -0
  334. /package/src/{pages/users → extensions/nocobase-users-example}/form-fields.tsx +0 -0
  335. /package/src/{pages/users → extensions/nocobase-users-example}/index.ts +0 -0
  336. /package/src/{pages/users → extensions/nocobase-users-example}/role-badges.tsx +0 -0
  337. /package/src/{pages/users → extensions/nocobase-users-example}/role-utils.ts +0 -0
  338. /package/src/{pages/users → extensions/nocobase-users-example}/types.ts +0 -0
@@ -0,0 +1,15 @@
1
+ import{j as e,a4 as o,a5 as l,b as c,Y as h,B as d,a6 as m,a2 as p,N as g,a3 as x}from"./index-MB-jfQld.js";import{C as u}from"./card-DuQBOS6A.js";import{P as f}from"./prompt-card-B2RS4nt2.js";import{A as j}from"./configuration-gate-C08mkkiX.js";import"./prompt-output-DZHRM2ft.js";const b=`Add the standard NocoBase AI floating chat entry to the application layout.
2
+
3
+ Requirements:
4
+ - Render AIChatFloatingTrigger at the lower-right edge of the application.
5
+ - Bind it to the global AI chat controller.
6
+ - Clicking the trigger opens ChatSurface with variant="side-panel" and a 450px width on the right.
7
+ - The side panel must push the desktop page narrower instead of blocking page interaction.
8
+ - Mobile may switch to an overlay presentation.
9
+ - Hide the floating trigger while the side panel is open.
10
+ - Support an unread-count badge.
11
+ - Start a new conversation with the configured default AI employee when opened.
12
+ - Put ChatSurfaceActions in the AIChatWindow header so expand/collapse and close stay in the upper-right corner.
13
+ - Keep one AIChatWindow mounted and change ChatSurface.variant to "dialog" when expanded.
14
+ - Keep the trigger and ChatSurface separate from AIChatWindow.
15
+ - Use shadcn/Base UI components and the existing AIProvider/AIChatProvider runtime.`;function y(){return e.jsx(j,{children:e.jsx(v,{})})}function v(){const a=o(),{open:s}=l(a),[t,n]=c.useState(!1),i=r=>{r||n(!1),a.setOpen(r)};return e.jsx(h,{id:"floating-chat-demo",controller:a,children:e.jsxs("div",{"data-open":s&&!t,"data-side":"right",className:"chat-side-panel-layout @container min-w-0",style:{"--chat-side-panel-width":"450px"},children:[e.jsxs("div",{className:"space-y-12 pb-12",children:[e.jsx("section",{className:"flex flex-wrap items-start justify-between gap-5 border-b pb-8",children:e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(d,{variant:"secondary",children:"AI Components"}),e.jsx(d,{variant:"outline",children:"Global entry"})]}),e.jsx("h1",{className:"mt-4 text-3xl font-semibold tracking-[-0.035em]",children:"Floating AI Chat"}),e.jsx("p",{className:"mt-3 max-w-3xl text-sm leading-6 text-muted-foreground",children:"A global lower-right entry for the shared AI conversation. It opens as a push side panel and can expand into a focused dialog without remounting the chat window."})]})}),e.jsxs("section",{className:"space-y-5",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground",children:"Interactive preview"}),e.jsx("h2",{className:"mt-2 text-xl font-semibold tracking-tight",children:"Global launcher and adaptive chat surface"}),e.jsx("p",{className:"mt-1.5 max-w-3xl text-sm leading-6 text-muted-foreground",children:"The trigger is constrained to this simulated application in the demo. In production its default positioning is fixed to the viewport."})]}),e.jsxs(u,{className:"gap-0 overflow-hidden py-0",children:[e.jsxs("div",{className:"flex h-12 items-center justify-between border-b px-4",children:[e.jsx("span",{className:"text-sm font-medium",children:"Application shell"}),e.jsx("code",{className:"rounded-md bg-muted px-2 py-1 text-xs text-muted-foreground",children:"AIChatFloatingTrigger → ChatSurface · side-panel/dialog"})]}),e.jsxs("div",{className:"relative grid min-h-[560px] grid-cols-[190px_minmax(0,1fr)] overflow-hidden bg-background",children:[e.jsxs("div",{className:"border-r bg-muted/25 p-4",children:[e.jsx("div",{className:"h-7 w-28 rounded bg-muted"}),e.jsxs("div",{className:"mt-8 space-y-3",children:[e.jsx("div",{className:"h-9 rounded-lg bg-muted"}),e.jsx("div",{className:"h-9 rounded-lg bg-muted/65"}),e.jsx("div",{className:"h-9 rounded-lg bg-muted/65"})]})]}),e.jsxs("div",{className:"p-6",children:[e.jsxs("div",{className:"grid gap-4 sm:grid-cols-3",children:[e.jsx("div",{className:"h-28 rounded-xl border bg-muted/15"}),e.jsx("div",{className:"h-28 rounded-xl border bg-muted/15"}),e.jsx("div",{className:"h-28 rounded-xl border bg-muted/15"})]}),e.jsx("div",{className:"mt-5 h-72 rounded-xl border bg-muted/10"})]}),e.jsx(m,{controller:a,unreadCount:3,position:"absolute"})]})]})]}),e.jsxs("section",{className:"space-y-5",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground",children:"Floating chat prompt"}),e.jsx("h2",{className:"mt-2 text-xl font-semibold tracking-tight",children:"Generate the global launcher separately"})]}),e.jsx(f,{title:"Add a lower-right AI floating entry",description:"This prompt configures the global trigger and its switchable side-panel/dialog surface.",prompt:b})]})]}),e.jsx(p,{open:s,variant:t?"dialog":"side-panel",onOpenChange:i,width:450,children:e.jsx(g,{headerActions:e.jsx(x,{expanded:t,onExpandedChange:n,onClose:()=>i(!1)})})})]})})}export{y as FloatingChatPage};
@@ -0,0 +1,43 @@
1
+ import{t as K,j as e,H as Y,M as ee,J as se,D as g,K as S,N as j,O as _,B as P,Q as ae,R as te,V as ne,W as oe,X as ie,Y as R,Z as H,_ as D,$ as F,a0 as G,b as l,a1 as V,I as re,d as O,e as z,f as U,g as B,i as v,a2 as le,l as ce,m as de,n as $,o as k,p as he,q as I,a3 as pe}from"./index-MB-jfQld.js";import{C as x,a as T,b as M,d as E}from"./card-DuQBOS6A.js";import{A as me}from"./configuration-gate-C08mkkiX.js";import{P as ue}from"./prompt-output-DZHRM2ft.js";import{S as xe}from"./switch-CRL8PmRI.js";/**
2
+ * @license lucide-react v0.487.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const ge=[["rect",{x:"2",y:"4",width:"20",height:"16",rx:"2",key:"izxlao"}],["path",{d:"M10 4v4",key:"pp8u80"}],["path",{d:"M2 8h20",key:"d11cs7"}],["path",{d:"M6 4v4",key:"1svtjw"}]],be=K("app-window",ge);/**
7
+ * @license lucide-react v0.487.0 - ISC
8
+ *
9
+ * This source code is licensed under the ISC license.
10
+ * See the LICENSE file in the root directory of this source tree.
11
+ */const fe=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M9 3v18",key:"fh3hqa"}],["path",{d:"M15 3v18",key:"14nvp0"}]],ve=K("columns-3",fe),L=[{value:"embedded",title:"Embedded block",description:"Place chat inside a dashboard, record page, or workspace region.",action:"Preview block",icon:ve},{value:"page",title:"Dedicated page",description:"Give the conversation a full route and the largest working area.",action:"Preview page",icon:be},{value:"side-panel",title:"Push side panel",description:"Keep the page operable while the content narrows for chat.",action:"Open panel",icon:Y},{value:"dialog",title:"Dialog",description:"Open a focused conversation from an action without changing route.",action:"Open dialog",icon:ee},{value:"mobile",title:"Mobile container",description:"Use the same component in a narrow, touch-friendly viewport.",action:"Preview mobile",icon:se}];function we({value:s,onValueChange:n,windowProps:o}){var c;return e.jsxs("div",{className:"space-y-5",children:[e.jsx("div",{className:"grid gap-3 sm:grid-cols-2 xl:grid-cols-5",children:L.map(i=>{const m=i.icon,u=i.value===s;return e.jsxs(x,{"data-active":u,className:"gap-0 py-0 transition-colors data-active:border-foreground/35 data-active:bg-muted/20",children:[e.jsxs(T,{className:"p-4",children:[e.jsx("div",{className:"mb-3 flex size-9 items-center justify-center rounded-lg border bg-background",children:e.jsx(m,{className:"size-4 text-muted-foreground"})}),e.jsx(M,{className:"text-sm",children:i.title}),e.jsx("p",{className:"min-h-15 text-xs leading-5 text-muted-foreground",children:i.description})]}),e.jsx(E,{className:"border-t p-3",children:e.jsx(g,{variant:u?"secondary":"ghost",size:"sm",className:"w-full",onClick:()=>n(i.value),children:i.action})})]},i.value)})}),e.jsxs(x,{className:"gap-0 py-0",children:[e.jsxs("div",{className:"flex min-h-12 items-center justify-between border-b px-4",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium",children:"Container preview"}),e.jsx("div",{className:"text-xs text-muted-foreground",children:(c=L.find(i=>i.value===s))==null?void 0:c.title})]}),e.jsx("code",{className:"rounded-md bg-muted px-2 py-1 text-xs text-muted-foreground",children:Ne(s)})]}),e.jsxs("div",{className:"flex min-h-[650px] justify-center bg-muted/15 p-3 sm:p-5",children:[s==="embedded"?e.jsx(S,{className:"h-[610px] w-full max-w-3xl shadow-sm",children:e.jsx(j,{...o})}):null,s==="page"?e.jsx(_,{className:"h-[610px] min-h-0 w-full",children:e.jsx(j,{...o})}):null,s==="mobile"?e.jsx("div",{className:"w-full max-w-[390px] rounded-[2rem] border-4 border-foreground/10 bg-background p-1 shadow-xl",children:e.jsx(S,{className:"h-[610px] rounded-[1.55rem] border-0",children:e.jsx(j,{...o})})}):null,s==="side-panel"||s==="dialog"?e.jsx(je,{mode:s,onOpen:()=>n(s)}):null]})]})]})}function je({mode:s,onOpen:n}){return e.jsxs("div",{className:"grid w-full max-w-4xl grid-cols-[200px_minmax(0,1fr)] overflow-hidden rounded-xl border bg-background shadow-sm",children:[e.jsxs("div",{className:"border-r bg-muted/30 p-4",children:[e.jsx("div",{className:"h-5 w-24 rounded bg-muted"}),e.jsxs("div",{className:"mt-6 space-y-3",children:[e.jsx("div",{className:"h-8 rounded bg-muted"}),e.jsx("div",{className:"h-8 rounded bg-muted/70"}),e.jsx("div",{className:"h-8 rounded bg-muted/70"})]})]}),e.jsx("div",{className:"flex items-center justify-center p-8",children:e.jsxs("div",{className:"max-w-sm text-center",children:[e.jsx("div",{className:"mx-auto mb-4 h-24 rounded-xl border bg-muted/20"}),e.jsx("h3",{className:"text-sm font-medium",children:s==="side-panel"?"Chat opens beside the current page":"Chat opens above the current page"}),e.jsx("p",{className:"mt-2 text-xs leading-5 text-muted-foreground",children:s==="side-panel"?"The live preview pushes this page narrower instead of blocking interaction.":"The live preview uses a focused dialog while preserving the page underneath."}),e.jsx(g,{className:"mt-4",size:"sm",onClick:n,children:s==="side-panel"?"Open side panel":"Open dialog"})]})})]})}const Ne=s=>{switch(s){case"page":return"<ChatPage />";case"side-panel":return'<ChatSurface variant="side-panel" />';case"dialog":return'<ChatSurface variant="dialog" />';case"mobile":return"<ChatInline /> · 390px";default:return"<ChatInline />"}},ye=[{id:"message-presentation-user",role:"user",parts:[{type:"text",text:"Review the support workspace and propose the most useful dashboard."}]},{id:"message-presentation-assistant",role:"assistant",parts:[{type:"reasoning",text:"I should inspect the existing collections first, then keep the recommendation focused on operational decisions.",state:"done"},{type:"dynamic-tool",toolName:"inspectDataModel",toolCallId:"message-presentation-tool",state:"output-available",input:{collections:["tickets","categories","users"]},output:{collectionsFound:3}},{type:"text",text:"Start with open workload, ownership gaps, SLA risk, and the created-versus-resolved trend. That gives the team one clear operational view without duplicating the underlying NocoBase rules."}]}],Ce=[{key:"web-search",label:"Web search",icon:e.jsx(D,{})}];function Ae(){return e.jsxs("div",{className:"grid items-start gap-4 xl:grid-cols-2",children:[e.jsxs(x,{className:"gap-0 py-0",children:[e.jsxs(T,{className:"border-b py-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(P,{variant:"outline",children:"Inline messages"}),e.jsx(M,{className:"text-base",children:"Standard conversation transcript"})]}),e.jsx("p",{className:"text-xs leading-5 text-muted-foreground",children:"This fixed example shows where reasoning, a normal tool call, and the final assistant response appear in one message sequence."})]}),e.jsx(E,{className:"bg-muted/15 p-4",children:e.jsx(S,{className:"h-[520px] bg-background shadow-sm",children:e.jsxs("div",{className:"flex h-full min-h-0 flex-col",children:[e.jsxs("div",{className:"relative flex h-12 shrink-0 items-center justify-between border-b px-2.5",children:[e.jsx(g,{variant:"ghost",size:"icon-sm","aria-label":"Conversations",children:e.jsx(ae,{})}),e.jsx("div",{className:"pointer-events-none absolute left-1/2 max-w-[55%] -translate-x-1/2 truncate text-sm font-medium",children:"Support workspace review"}),e.jsx(g,{variant:"ghost",size:"icon-sm","aria-label":"New conversation",children:e.jsx(te,{})})]}),e.jsx(ne,{className:"h-full",messages:ye,showMessageActions:!1}),e.jsx("div",{className:"shrink-0 bg-card px-4 pt-2 pb-3",children:e.jsxs("div",{className:"rounded-xl border bg-background px-3 py-2.5 shadow-sm",children:[e.jsx("div",{className:"min-h-10 text-sm text-muted-foreground",children:"Message your AI employee…"}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(g,{variant:"ghost",size:"icon-sm","aria-label":"Attach file",children:e.jsx(oe,{})}),e.jsx(g,{size:"icon-sm","aria-label":"Send message",children:e.jsx(ie,{})})]})]})})]})})})]}),e.jsxs(x,{className:"gap-0 py-0",children:[e.jsxs(T,{className:"border-b py-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(P,{variant:"outline",children:"Compact composer"}),e.jsx(M,{className:"text-base",children:"Open the transcript only when needed"})]}),e.jsx("p",{className:"text-xs leading-5 text-muted-foreground",children:"The compact variant keeps only the chat header and composer. Its history button opens a dialog with conversation switching and the selected transcript."})]}),e.jsx(E,{className:"bg-muted/15 p-4",children:e.jsx(R,{id:"message-presentation-compact-demo",children:e.jsx(H,{className:"bg-background",composerActions:Ce,showModelSelector:!1,disclaimer:!1})})})]})]})}const Z=[{value:"embedded",label:"Inside the page",description:"Embed chat in the selected content region."},{value:"page",label:"Dedicated page",description:"Create a full route for the AI conversation."},{value:"side-panel",label:"Right side panel",description:"Push the page narrower while chat is open."},{value:"dialog",label:"Dialog",description:"Open chat from a button or page action."},{value:"mobile",label:"Mobile region",description:"Optimize the embedded container for a narrow viewport."}],ke={conversationList:!0,employeeSelector:!0,modelSelector:!0,userPrompt:!0,pageElement:!0,upload:!0,webSearch:!0,panelExpansion:!0};function Ie(){return e.jsx(R,{id:"prompt-generator-preview",children:e.jsx(Se,{})})}function Se(){const{id:s,addWorkContext:n,focusComposer:o}=F(),{registeredCount:c,startPicking:i}=G(),[m,u]=l.useState("the current page's main content area"),[r,N]=l.useState("embedded"),[h,y]=l.useState("450"),[p,C]=l.useState("transcript"),[a,W]=l.useState(ke),A=l.useMemo(()=>{const t=[];return a.pageElement&&t.push({key:"pick-page-element",label:"Pick page element",icon:e.jsx(V,{}),disabled:c===0,onClick:()=>i({chatId:s,onSelect:f=>{n(f),o()}})}),a.webSearch&&t.push({key:"web-search",label:"Web search",icon:e.jsx(D,{})}),t},[n,a.pageElement,a.webSearch,s,o,c,i]),d=(t,f)=>{W(X=>({...X,[t]:f}))},J=l.useMemo(()=>{const t={embedded:"Render ChatInline inside the target content region and keep its width fluid within the parent container.",page:"Create a dedicated route and render ChatPage with AIChatWindow filling the available page content.","side-panel":`Use ChatSurface with variant="side-panel" on the right and a ${h}px width. Opening chat must push the page narrower instead of covering it on desktop; mobile may use an overlay.`,dialog:'Open ChatSurface with variant="dialog" from a page action. Keep conversation state in AIProvider/AIChatProvider so closing the dialog does not discard it.',mobile:"Render ChatInline in the target region with a mobile-first width around 390px and preserve the same responsive AIChatWindow API."}[r];return`Add the standard NocoBase AI conversation to ${m||"the target page"}.
12
+
13
+ Placement:
14
+ - ${t}
15
+ - Keep AIChatWindow position-independent. The surface wrapper owns placement and dimensions.
16
+
17
+ Message presentation:
18
+ - ${p==="transcript"?"Render the full AIChatMessageList inline as part of AIChatWindow.":"Use AIChatCompact for the working surface and open AIChatHistoryDialog when the user requests the full transcript."}
19
+
20
+ Conversation capabilities:
21
+ - Conversation list: ${a.conversationList}
22
+ - AI employee selector: ${a.employeeSelector}
23
+ - Model selector: ${a.modelSelector}
24
+ - Personalized prompt editor: ${a.userPrompt}
25
+ - Pick page element: ${a.pageElement}
26
+ - Upload action: ${a.upload}
27
+ - Web search action: ${a.webSearch}
28
+ - Side panel can expand to a 95% dialog and collapse back: ${a.panelExpansion}
29
+ - Tool approval follows NocoBase permissions. Always show Allow / Deny when the backend marks a tool as ASK.
30
+
31
+ Implementation requirements:
32
+ - Use AIProvider at application level and AIChatProvider with a stable id for this chat instance.
33
+ - Wrap the application content with AIPageElementProvider when page-element picking is enabled.
34
+ - Register selectable React components with useAIPageElement and return serializable business context from getContext.
35
+ - Reuse AIChatWindow and the existing providers; do not duplicate message, streaming, reasoning, or tool-call state.
36
+ - When the right panel is expandable, render one AIChatWindow inside ChatSurface and change only its variant between "side-panel" and "dialog". Put ChatSurfaceActions in the window header.
37
+ - Keep the generic Tool Call shell responsible for status, ASK approval, errors, and disclosure. Register business-specific bodies through AIToolRendererProvider.
38
+ - Include the built-in specialized Tool Card renderers. This is part of the standard AI chat capability, not an optional page setting.
39
+ - Register browser-side tool implementations through AIProvider.toolInvokers. After all interrupted calls are approved, the provider executes these handlers and sends their results when resuming the NocoBase conversation.
40
+ - Pass application actions through composerActions.
41
+ - AIChatProvider handles NocoBase ASK decisions and resumes tool execution. Use onToolCallDecision only for application-specific side effects or telemetry.
42
+ - Use shadcn/Base UI components only; do not introduce Ant Design, Radix, or Zustand.
43
+ - Match the existing NocoBase ChatBox behavior and black/white/gray visual system.`},[a,p,h,r,m]),b=p==="transcript"?e.jsx(j,{composerActions:A,showConversationToggle:a.conversationList,showEmployeeSelector:a.employeeSelector,showModelSelector:a.modelSelector,showUserPrompt:a.userPrompt,enableAttachments:a.upload,attachmentActionIndex:a.pageElement?1:0,disclaimer:!1,onToolCallDecision:async()=>{}}):e.jsx(H,{className:"h-full rounded-none border-0",composerActions:A,showEmployeeSelector:a.employeeSelector,showModelSelector:a.modelSelector,showUserPrompt:a.userPrompt,enableAttachments:a.upload,disclaimer:!1,onToolCallDecision:async()=>{}}),Q=r==="page"?e.jsx(_,{className:"h-[430px] min-h-0 w-full max-w-none",children:b}):r==="side-panel"?e.jsxs("div",{className:"flex h-[430px] w-full overflow-hidden rounded-xl border bg-card shadow-sm",children:[e.jsxs("div",{className:"hidden min-w-0 flex-1 space-y-4 bg-muted/20 p-5 sm:block",children:[e.jsx("div",{className:"h-7 w-40 rounded-md bg-muted"}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsx("div",{className:"h-24 rounded-lg border bg-background"}),e.jsx("div",{className:"h-24 rounded-lg border bg-background"})]}),e.jsx("div",{className:"h-48 rounded-lg border bg-background"})]}),e.jsx("aside",{className:"h-full max-w-full shrink-0 border-l bg-card",style:{width:`${h}px`},children:b})]}):r==="dialog"?e.jsxs("div",{className:"relative h-[430px] w-full overflow-hidden rounded-xl border bg-muted/30 p-5",children:[e.jsxs("div",{className:"space-y-3 opacity-45",children:[e.jsx("div",{className:"h-7 w-44 rounded bg-muted-foreground/20"}),e.jsx("div",{className:"h-24 rounded-lg bg-background"}),e.jsx("div",{className:"h-48 rounded-lg bg-background"})]}),e.jsx("div",{className:"absolute inset-4 overflow-hidden rounded-xl border bg-card shadow-2xl sm:inset-8",children:b})]}):r==="mobile"?e.jsx("div",{className:"h-[430px] w-full max-w-[390px] overflow-hidden rounded-[2rem] border-4 border-foreground/15 bg-card shadow-lg",children:b}):e.jsx(S,{className:"h-[430px] w-full max-w-2xl",children:b});return e.jsxs("div",{className:"grid items-start gap-5 xl:grid-cols-[360px_minmax(0,1fr)]",children:[e.jsxs(x,{className:"gap-0 py-0",children:[e.jsxs(T,{className:"border-b py-4",children:[e.jsx(M,{className:"text-base",children:"Describe the integration"}),e.jsx("p",{className:"text-xs leading-5 text-muted-foreground",children:"Choose where chat belongs and which capabilities the target page needs."})]}),e.jsxs(E,{className:"space-y-5 p-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx("label",{className:"text-xs font-medium",htmlFor:"ai-chat-target",children:"Target page or region"}),e.jsx(re,{id:"ai-chat-target",value:m,onChange:t=>u(t.target.value),placeholder:"e.g. the ticket detail page"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("div",{className:"text-xs font-medium",children:"Placement"}),e.jsx("div",{className:"grid gap-2 sm:grid-cols-2 xl:grid-cols-1",children:Z.map(t=>e.jsxs("button",{type:"button","data-active":r===t.value,className:"rounded-lg border px-3 py-2.5 text-left transition-colors hover:bg-muted/40 data-active:border-foreground/35 data-active:bg-muted/60",onClick:()=>N(t.value),children:[e.jsx("span",{className:"block text-sm font-medium",children:t.label}),e.jsx("span",{className:"mt-0.5 block text-xs leading-5 text-muted-foreground",children:t.description})]},t.value))})]}),r==="side-panel"?e.jsxs("div",{className:"space-y-2",children:[e.jsx("div",{className:"text-xs font-medium",children:"Side panel width"}),e.jsxs(O,{value:h,onValueChange:t=>t&&y(t),children:[e.jsx(z,{className:"w-full",children:e.jsxs(U,{children:[h,"px"]})}),e.jsxs(B,{children:[e.jsx(v,{value:"400",children:"400px"}),e.jsx(v,{value:"450",children:"450px · NocoBase default"}),e.jsx(v,{value:"520",children:"520px"})]})]})]}):null,e.jsxs("div",{className:"space-y-2",children:[e.jsx("div",{className:"text-xs font-medium",children:"Message presentation"}),e.jsxs(O,{value:p,onValueChange:t=>t&&C(t),children:[e.jsx(z,{className:"w-full",children:e.jsx(U,{children:p==="transcript"?"Full transcript":"Compact + history dialog"})}),e.jsxs(B,{children:[e.jsx(v,{value:"transcript",children:"Full transcript"}),e.jsx(v,{value:"compact-history-dialog",children:"Compact + history dialog"})]})]})]}),e.jsxs("div",{className:"space-y-1 border-t pt-4",children:[e.jsx("div",{className:"mb-2 text-xs font-medium",children:"Capabilities"}),Object.keys(a).map(t=>e.jsxs("label",{className:"flex items-center justify-between gap-4 py-1.5 text-sm",children:[e.jsx("span",{className:"min-w-0",children:e.jsx("span",{className:"block",children:Pe(t)})}),e.jsx(xe,{size:"sm",checked:a[t],onCheckedChange:f=>d(t,f)})]},t))]})]})]}),e.jsxs("div",{className:"space-y-5",children:[e.jsxs(x,{className:"gap-0 overflow-hidden py-0",children:[e.jsxs("div",{className:"flex items-center justify-between border-b px-4 py-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium",children:"Capabilities preview"}),e.jsx("div",{className:"text-xs text-muted-foreground",children:"The selected controls are rendered on the real AIChatWindow."})]}),e.jsx("code",{className:"rounded-md bg-muted px-2 py-1 text-xs text-muted-foreground",children:Te(r)})]}),e.jsx("div",{className:"flex justify-center bg-muted/20 p-3 sm:p-4",children:Q})]}),e.jsx(ue,{title:"Generated implementation prompt",description:"Updates from the selected page, placement, and capabilities.",prompt:J,promptClassName:"max-h-[760px] min-h-[520px]"})]})]})}const Pe=s=>({conversationList:"Conversation list",employeeSelector:"AI employee selector",modelSelector:"Model selector",userPrompt:"Personalized prompt editor",pageElement:"Pick page element",upload:"Upload files",webSearch:"Web search",panelExpansion:"Panel expand / collapse"})[s],Te=s=>{var n;return((n=Z.find(o=>o.value===s))==null?void 0:n.label)??s},Me=[["className","string","undefined","Adds layout or sizing classes to the root conversation window."],["headerActions","ReactNode","undefined","Adds surface actions such as expand, collapse, or close to the header."],["composerActions","AIChatComposerAction[]","[]","Application-specific buttons rendered in the composer toolbar."],["showConversationToggle","boolean","true","Shows the conversation-list control."],["showNewConversation","boolean","true","Shows the new-conversation action."],["showEmployeeSelector","boolean","true","Shows the AI employee selector in the composer."],["showModelSelector","boolean","true","Shows the model selector in the composer."],["showUserPrompt","boolean","true","Shows the personalized AI employee prompt editor."],["enableAttachments","boolean","false","Enables file picker, drag-and-drop, and pasted-image uploads."],["attachmentActionIndex","number","0","Places the attachment action at a specific position in the composer toolbar."],["onToolCallDecision","(decision: AIToolCallDecision) => void | Promise<void>","undefined","Observes approve, reject, or edit decisions after AIChatProvider has processed them; use it for application side effects or telemetry."],["placeholder","string","Message your AI employee…","Composer placeholder text."],["disclaimer","ReactNode | false","Default disclaimer","Customizes or hides the footer disclaimer."]],Ee=[["variant",'"side-panel" | "dialog"',"required","Changes only the outer presentation while keeping the same chat window mounted."],["open","boolean","required","Controls whether the surface is open."],["onOpenChange","(open: boolean) => void","required","Receives close requests from Escape, the dialog backdrop, or surface actions."],["side",'"left" | "right"','"right"',"Chooses the side used by the side-panel variant."],["width","number | string","450","Sets the width used by the side-panel variant."],["closeOnEscape","boolean","true","Allows Escape to close the active surface."],["showCloseHandle","boolean","false","Shows an outside close handle for the side-panel variant."]];function Be(){return e.jsx(me,{children:e.jsx(R,{id:"ai-chat-demo",children:e.jsx(We,{})})})}function We(){const[s,n]=l.useState("embedded"),[o,c]=l.useState(!1),[i,m]=l.useState(!1),{id:u,addWorkContext:r,focusComposer:N}=F(),{registeredCount:h,startPicking:y}=G(),p=l.useMemo(()=>[{key:"pick-page-element",label:"Pick page element",icon:e.jsx(V,{}),disabled:h===0,onClick:()=>{o&&s==="dialog"&&n("side-panel"),y({chatId:u,onSelect:d=>{r(d),N()}})}},{key:"web-search",label:"Web search",icon:e.jsx(D,{}),active:i,onClick:()=>{m(d=>!d)}}],[r,u,s,N,h,y,o,i]),C=l.useMemo(()=>({composerActions:p,enableAttachments:!0,attachmentActionIndex:1,onToolCallDecision:async()=>{}}),[p]),a=()=>{c(!1)},W={...C,headerActions:e.jsx(pe,{expanded:s==="dialog",onExpandedChange:d=>{n(d?"dialog":"side-panel")},onClose:a})},A=d=>{n(d),c(d==="side-panel"||d==="dialog")};return e.jsxs("div",{"data-open":o&&s==="side-panel","data-side":"right",className:"chat-side-panel-layout @container min-w-0",style:{"--chat-side-panel-width":"450px"},children:[e.jsxs("div",{className:"space-y-14 pb-12",children:[e.jsx("section",{className:"flex flex-wrap items-start justify-between gap-5 border-b pb-8",children:e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(P,{variant:"secondary",children:"AI Components"}),e.jsx(P,{variant:"outline",children:"Preview"})]}),e.jsx("h1",{className:"mt-4 text-3xl font-semibold tracking-[-0.035em]",children:"AI Chat Window"}),e.jsx("p",{className:"mt-3 max-w-3xl text-sm leading-6 text-muted-foreground",children:"A position-independent NocoBase AI employee conversation component. Explore message interactions independently, place the same chat in different containers, then generate an implementation prompt for a target page."})]})}),e.jsxs("section",{className:"space-y-5",children:[e.jsx(w,{eyebrow:"Container patterns",title:"Use the same conversation window wherever the product needs it",description:"The provider owns conversation state. Page, embedded block, push side panel, dialog, and mobile containers only decide placement and dimensions."}),e.jsx(we,{value:s,onValueChange:A,windowProps:C})]}),e.jsxs("section",{className:"space-y-5",children:[e.jsx(w,{eyebrow:"Message presentation",title:"Choose how much conversation history the page should expose",description:"Use the complete transcript for conversational work, or a compact worker surface that opens message history only when the user asks for it."}),e.jsx(Ae,{})]}),e.jsxs("section",{className:"space-y-5",children:[e.jsx(w,{eyebrow:"Prompt generator",title:"Describe where chat belongs, then copy an implementation prompt",description:"This replaces a generic prop configuration panel with a task-oriented generator: choose the target area, placement mode, and required capabilities."}),e.jsx(Ie,{})]}),e.jsxs("section",{className:"space-y-5",children:[e.jsx(w,{eyebrow:"Component API",title:"ChatSurface props",description:"Use variant as the single presentation switch. The child AIChatWindow remains the same React instance while the surface changes shape."}),e.jsx(q,{rows:Ee})]}),e.jsxs("section",{className:"space-y-5",children:[e.jsx(w,{eyebrow:"Component API",title:"AIChatWindow props",description:"The core window stays reusable while business pages provide placement, composer actions, and tool-approval behavior."}),e.jsx(q,{rows:Me})]})]}),e.jsx(le,{open:o,variant:s==="dialog"?"dialog":"side-panel",onOpenChange:c,width:450,children:e.jsx(j,{...W})})]})}function q({rows:s}){return e.jsx(x,{className:"gap-0 overflow-hidden py-0",children:e.jsxs(ce,{children:[e.jsx(de,{children:e.jsxs($,{children:[e.jsx(k,{children:"Prop"}),e.jsx(k,{children:"Type"}),e.jsx(k,{children:"Default"}),e.jsx(k,{children:"Description"})]})}),e.jsx(he,{children:s.map(([n,o,c,i])=>e.jsxs($,{children:[e.jsx(I,{className:"font-mono text-xs font-medium",children:n}),e.jsx(I,{className:"font-mono text-xs text-muted-foreground",children:o}),e.jsx(I,{className:"font-mono text-xs text-muted-foreground",children:c}),e.jsx(I,{className:"min-w-80 whitespace-normal text-muted-foreground",children:i})]},n))})]})})}function w({eyebrow:s,title:n,description:o}){return e.jsxs("div",{children:[e.jsx("p",{className:"text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground",children:s}),e.jsx("h2",{className:"mt-2 text-xl font-semibold tracking-tight",children:n}),e.jsx("p",{className:"mt-1.5 max-w-3xl text-sm leading-6 text-muted-foreground",children:o})]})}export{Be as AIChatPage};
@@ -0,0 +1,23 @@
1
+ import{t as E,b as c,bi as O,bj as B,j as e,bk as T,bl as G,bm as V,bn as _,bo as H,bp as M,bq as X,D as i,aO as J,c as A,k as L,d as Q,e as W,f as Y,g as Z,i as ee,I as te,br as x,bs as f,bt as b,B as g,b1 as ae,bu as se,bv as re,bw as oe}from"./index-MB-jfQld.js";import{C as v,a as y,b as C,c as R,d as D}from"./card-DuQBOS6A.js";import{P as ne}from"./prompt-output-DZHRM2ft.js";/**
2
+ * @license lucide-react v0.487.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const ie=[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"m12 5 7 7-7 7",key:"xquz4c"}]],N=E("arrow-right",ie);function U({title:t,description:a,actions:s,children:o,closeLabel:p,closeTo:w,beforeClose:r,className:I,nested:z}){const k=c.useContext(O),$=k>0,{open:S,setOpen:P,close:n,navigateAfterClose:q}=B({closeTo:w,beforeClose:r,animated:!0}),F=c.useCallback((d,K)=>{if(d){P(!0);return}K.cancel(),n()},[n,P]);return e.jsx(T.Provider,{value:n,children:e.jsx(O.Provider,{value:k+1,children:e.jsxs(G,{open:S,onOpenChange:F,onOpenChangeComplete:d=>{d||q()},children:[e.jsxs(V,{children:[$?e.jsx(le,{open:S,onClose:n}):e.jsx(_,{className:"fixed inset-0 isolate z-50 bg-black/10 duration-150 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",onClick:d=>{d.stopPropagation(),n()}}),e.jsxs(H,{className:A("fixed top-1/2 left-1/2 z-50 flex max-h-[calc(100dvh-2rem)] w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-xl bg-popover text-sm text-popover-foreground ring-1 ring-foreground/10 duration-150 outline-none sm:max-w-2xl data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",I),children:[e.jsxs("header",{className:"relative shrink-0 border-b px-5 py-4 pr-14 text-left",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0 space-y-1",children:[e.jsx(M,{className:"font-heading truncate text-lg font-medium",children:t}),a?e.jsx(X,{className:"text-sm text-muted-foreground",children:a}):null]}),s?e.jsx("div",{className:"flex shrink-0 items-center gap-2",children:s}):null]}),e.jsxs(i,{type:"button",variant:"ghost",size:"icon-sm",className:"absolute top-3 right-3",onClick:()=>void n(),children:[e.jsx(J,{}),e.jsx("span",{className:"sr-only",children:p})]})]}),o]})]}),z]})})})}function le({open:t,onClose:a}){return e.jsx("div",{role:"presentation","aria-hidden":"true",className:A("fixed inset-0 isolate z-50 bg-black/10 transition-opacity duration-150 supports-backdrop-filter:backdrop-blur-xs",t?"opacity-100":"pointer-events-none opacity-0"),onClick:s=>{s.stopPropagation(),a()}})}function de({children:t,closeTo:a,beforeClose:s}){const{close:o}=B({closeTo:a,beforeClose:s,animated:!1});return e.jsx(T.Provider,{value:o,children:t})}const m=[{id:"drawer",number:"1",title:"Drawer route",description:"Keep the current page mounted and open one URL-backed drawer.",path:"drawer",routeShape:"Page → Drawer"},{id:"dialog",number:"2",title:"Dialog route",description:"Open focused content in a modal while preserving the page URL history.",path:"dialog",routeShape:"Page → Dialog"},{id:"page",number:"3",title:"Child page",description:"Replace the current page instead of rendering the child inside an overlay.",path:"page",routeShape:"Page → Child page"},{id:"nested-drawers",number:"4",title:"Second-level drawer",description:"Push the lower drawer outward and keep the top drawer at a stable size.",path:"drawer/second",routeShape:"Page → Drawer → Drawer"},{id:"page-drawer-dialog",number:"5",title:"Page, drawer, and dialog",description:"Compose different presentation types without coupling business content to them.",path:"page/drawer/dialog",routeShape:"Child page → Drawer → Dialog"}];function ce(t,a){const s={drawer:"Keep the current page mounted and open the target content with RouteDrawer. Closing the drawer returns to the page route.",dialog:"Keep the current page mounted and open the target content with RouteDialog. The dialog route must be directly addressable and dismissible through the shared close lifecycle.",page:"Render the target content as a real child page with RoutePage. Register it as a page route branch rather than placing it inside a drawer outlet.","nested-drawers":"Create a parent RouteDrawer with an Outlet and pass the rendered child outlet through its nested prop. The second RouteDrawer must push the lower drawer outward, keep equal widths, and close back to the parent route.","page-drawer-dialog":"Render a RoutePage first, place a RouteDrawer route inside that page, then render a RouteDialog as the drawer's nested route. Closing each layer must return to the immediately lower URL."}[t.id];return`Build ${a||"the requested workflow"} with the installed NocoBase route surfaces.
7
+
8
+ Scenario:
9
+ - ${t.routeShape}
10
+ - ${s}
11
+
12
+ Implementation requirements:
13
+ - Import RouteDrawer, RouteDialog, RoutePage, and useRouteSurfaceClose from @/extensions/nocobase-route-surfaces as needed.
14
+ - Keep data loading, forms, ACL guards, route paths, and business copy in application-owned files.
15
+ - Keep business content independent from its presentation container so the same content can move between a drawer, dialog, or page.
16
+ - Every surface must have an explicit closeTo URL.
17
+ - Use nested React Router routes and Outlet only when the visual layer is genuinely nested.
18
+ - A full child page must be a page route branch, not an Outlet rendered inside a drawer.
19
+ - For editable forms, use useRefineUnsavedChangesGuard, pass its beforeClose callback to the surface, render its confirmation node, and use useRouteSurfaceClose for Cancel and successful submission.
20
+ - Direct URL entry, refresh, browser back/forward, Escape, the close button, and backdrop dismissal must all restore the correct layer stack.
21
+ - Apply Refine CanAccess with an AccessDenied fallback to each business resource/action independently; do not rely on a parent list permission for unrelated child pages.
22
+
23
+ Deliver the complete route definitions and React components using the application's existing design system.`}function ue(){const[t,a]=c.useState("drawer"),[s,o]=c.useState("a customer detail workflow"),p=m.find(r=>r.id===t)??m[0],w=c.useMemo(()=>ce(p,s),[p,s]);return e.jsxs(v,{children:[e.jsxs(y,{children:[e.jsx(C,{children:"Prompt generator"}),e.jsx(R,{children:"Generate a complete routing scenario, not just an isolated overlay component."})]}),e.jsxs(D,{className:"grid items-start gap-5 xl:grid-cols-[360px_minmax(0,1fr)]",children:[e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(L,{htmlFor:"route-surface-scenario",children:"Scenario"}),e.jsxs(Q,{value:t,onValueChange:r=>a(r),children:[e.jsx(W,{id:"route-surface-scenario",className:"w-full",children:e.jsx(Y,{})}),e.jsx(Z,{children:m.map(r=>e.jsxs(ee,{value:r.id,children:[r.number,". ",r.title]},r.id))})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(L,{htmlFor:"route-surface-target",children:"Business target"}),e.jsx(te,{id:"route-surface-target",value:s,onChange:r=>o(r.target.value)})]})]}),e.jsx(ne,{title:"Generated routing prompt",description:"Updates as you change the scenario and business target.",prompt:w,promptClassName:"min-h-80"})]})]})}const j="/route-surfaces";function l(){const{pathname:t}=ae(),a=t.indexOf(j);return a>=0?t.slice(0,a+j.length):j}function xe(){const t=x(),a=f();return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(g,{variant:"secondary",children:"Route surfaces"}),e.jsx("h1",{className:"font-heading text-3xl font-semibold tracking-tight",children:"URL-backed pages and overlays"}),e.jsx("p",{className:"max-w-3xl text-muted-foreground",children:"Keep business content independent from whether it appears as a page, drawer, dialog, or nested combination. Every preview below supports a direct URL and browser history."})]}),e.jsx("div",{className:"grid gap-4 lg:grid-cols-2 xl:grid-cols-3",children:m.map(s=>e.jsxs(v,{className:"flex flex-col",children:[e.jsxs(y,{children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs(g,{variant:"outline",children:["Scenario ",s.number]}),e.jsx("span",{className:"text-xs text-muted-foreground",children:s.routeShape})]}),e.jsx(C,{children:s.title}),e.jsx(R,{children:s.description})]}),e.jsx(D,{className:"mt-auto",children:e.jsxs(i,{type:"button",variant:"outline",className:"w-full",onClick:()=>t(s.path),children:["Open preview",e.jsx(N,{})]})})]},s.id))}),e.jsx(ue,{})]}),a]})}function fe(){const t=x(),a=f(),s=l();return e.jsx(b,{title:"Customer details",description:"A routed drawer keeps the scenario page mounted behind it.",closeLabel:"Close",closeTo:s,nested:a,children:e.jsx(u,{label:"Drawer",title:"Northwind renewal",description:"Business content does not know that it is rendered inside a drawer.",children:e.jsxs(i,{onClick:()=>t("second"),children:["Open second-level drawer",e.jsx(N,{})]})})})}function we(){const t=l();return e.jsx(b,{title:"Renewal activity",description:"The lower drawer is pushed outward and remains behind the layer mask.",closeLabel:"Close",closeTo:`${t}/drawer`,children:e.jsx(u,{label:"Second-level drawer",title:"Latest review",description:"Clicking this layer's backdrop closes only the top drawer."})})}function je(){const t=l();return e.jsx(U,{title:"Approve renewal",description:"A modal route for a focused decision.",closeLabel:"Close",closeTo:t,children:e.jsx(u,{label:"Dialog",title:"Approval required",description:"The page stays mounted while the URL represents the active dialog."})})}function be(){const t=f(),a=l();return e.jsx(de,{closeTo:a,children:e.jsx(pe,{nested:t})})}function pe({nested:t}){const a=se(),s=x();return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(g,{variant:"secondary",children:"Child page"}),e.jsx("h1",{className:"font-heading text-3xl font-semibold tracking-tight",children:"Customer workspace"}),e.jsx("p",{className:"text-muted-foreground",children:"This route replaces the Demo home instead of rendering inside its Outlet."})]}),e.jsxs(i,{variant:"outline",onClick:()=>void a(),children:[e.jsx(re,{}),"Back to scenarios"]})]}),e.jsxs(v,{children:[e.jsxs(y,{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(oe,{className:"size-5 text-primary"}),e.jsx(C,{children:"Page-owned workflow"})]}),e.jsx(R,{children:"A page can still host routed overlays without becoming coupled to their content."})]}),e.jsx(D,{children:e.jsx(i,{onClick:()=>s("drawer"),children:"Open page drawer"})})]})]}),t]})}function ve(){const t=x(),a=f(),s=l();return e.jsx(b,{title:"Customer activity",description:"This drawer belongs to the child page route.",closeLabel:"Close",closeTo:`${s}/page`,nested:a,children:e.jsx(u,{label:"Page drawer",title:"Renewal conversation",description:"Open a dialog above this drawer to test mixed presentation types.",children:e.jsxs(i,{onClick:()=>t("dialog"),children:["Open confirmation dialog",e.jsx(N,{})]})})})}function ye(){const t=l();return e.jsx(U,{title:"Confirm follow-up",description:"The dialog is nested in the drawer route subtree.",closeLabel:"Close",closeTo:`${t}/page/drawer`,children:e.jsx(u,{label:"Nested dialog",title:"Schedule a follow-up?",description:"Closing returns to the drawer; closing the drawer then returns to the page."})})}function u({label:t,title:a,description:s,children:o}){return e.jsx("div",{className:"min-h-0 flex-1 overflow-y-auto px-5 py-5",children:e.jsxs("div",{className:"space-y-5",children:[e.jsx(g,{variant:"outline",children:t}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("h2",{className:"text-xl font-semibold",children:a}),e.jsx("p",{className:"text-muted-foreground",children:s})]}),e.jsxs("div",{className:"grid gap-3 rounded-lg border bg-muted/30 p-4 sm:grid-cols-2",children:[e.jsx(h,{label:"Owner",value:"Ada Lovelace"}),e.jsx(h,{label:"Status",value:"In review"}),e.jsx(h,{label:"Value",value:"$48,000"}),e.jsx(h,{label:"Renewal",value:"September 30"})]}),o?e.jsx("div",{children:o}):null]})})}function h({label:t,value:a}){return e.jsxs("div",{className:"space-y-1",children:[e.jsx("div",{className:"text-xs text-muted-foreground",children:t}),e.jsx("div",{className:"font-medium",children:a})]})}export{je as DemoDialogRoute,fe as DemoDrawerRoute,ye as DemoPageDrawerDialogRoute,ve as DemoPageDrawerRoute,be as DemoPageRoute,we as DemoSecondDrawerRoute,xe as RouteSurfacesDemoHome};