@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.
- package/.env.example +5 -0
- package/.github/workflows/publish.yml +106 -0
- package/.gitignore +33 -0
- package/AGENTS.md +19 -0
- package/README.MD +61 -180
- package/dist/assets/{LineDraw-C0m1GONT.js → LineDraw-iG-ADes-.js} +1 -1
- package/dist/assets/{SymbolDraw-CCospe5G.js → SymbolDraw-DXoSw1tM.js} +1 -1
- package/dist/assets/VisualMapping-C_ee4Eht.js +1 -0
- package/dist/assets/auth-method-demo-DaOCuvsq.js +1 -0
- package/dist/assets/auto-login-provider-5Uxza9Ms.js +2 -0
- package/dist/assets/auto-login-provider-DyaPGK2D.js +1 -0
- package/dist/assets/auto-redirect-provider-CfwRvYOI.js +1 -0
- package/dist/assets/auto-redirect-provider-Cr3jmYts.js +1 -0
- package/dist/assets/auto-redirect-provider-QkJQRBbG.js +1 -0
- package/dist/assets/calendar-DjDRfD5t.js +1 -0
- package/dist/assets/card-DuQBOS6A.js +1 -0
- package/dist/assets/cas-sign-in-button-CyqG1QME.js +1 -0
- package/dist/assets/components-D-ptYjX_.js +20 -0
- package/dist/assets/configuration-gate-C08mkkiX.js +1 -0
- package/dist/assets/{createClipPathFromCoordSys-uEftn1Mq.js → createClipPathFromCoordSys-wj34-b1B.js} +1 -1
- package/dist/assets/createSeriesDataSimply-D0A6SAVQ.js +1 -0
- package/dist/assets/customGraphicKeyframeAnimation-DWrhrHL_.js +3 -0
- package/dist/assets/demo-BYWHeKUe.js +1 -0
- package/dist/assets/demo-CPWoNtx8.js +1 -0
- package/dist/assets/demo-CyvJk5zV.js +1 -0
- package/dist/assets/demo-D4OiKplc.js +1 -0
- package/dist/assets/demo-DBueJg0m.js +1 -0
- package/dist/assets/demo-DkIhyiRK.js +1 -0
- package/dist/assets/demo-tpTjO0sC.js +1 -0
- package/dist/assets/dingtalk-sign-in-button-DSWsSruv.js +1 -0
- package/dist/assets/echarts-preview-DxHNfq1C.js +1 -0
- package/dist/assets/{echarts-runtime-CEgJbv68.js → echarts-runtime-D8kXn6ME.js} +3 -3
- package/dist/assets/{echarts-runtime-advanced-Buhm2BHz.js → echarts-runtime-advanced-QY8v95qK.js} +1 -1
- package/dist/assets/{echarts-runtime-common-DLAdBAIa.js → echarts-runtime-common-D-yqAK-r.js} +1 -1
- package/dist/assets/{echarts-runtime-components-ypnyLkYx.js → echarts-runtime-components-P4-i8jPU.js} +1 -1
- package/dist/assets/{echarts-runtime-hierarchy-ClStquCF.js → echarts-runtime-hierarchy-ByQZ-DbP.js} +1 -1
- package/dist/assets/floating-BFVEyPEp.js +15 -0
- package/dist/assets/index-BgCbGDMc.js +43 -0
- package/dist/assets/index-Btk35Nx-.js +23 -0
- package/dist/assets/index-CwNxd66J.js +1 -0
- package/dist/assets/index-MB-jfQld.js +686 -0
- package/dist/assets/index-NH3aqqQz.css +1 -0
- package/dist/assets/index-gFtCXH3o.js +58 -0
- package/dist/assets/index-um5hdKdZ.js +23 -0
- package/dist/assets/{labelHelper-C137W5gU.js → labelHelper-DQqRy3a_.js} +1 -1
- package/dist/assets/ldap-sign-in-form--6Gt3yGq.js +1 -0
- package/dist/assets/oidc-sign-in-button-CQdRcR_p.js +1 -0
- package/dist/assets/{page-context-Cxx11gzg.js → page-context-CnQ4GYM7.js} +10 -10
- package/dist/assets/prompt-card-B2RS4nt2.js +1 -0
- package/dist/assets/prompt-output-DZHRM2ft.js +1 -0
- package/dist/assets/saml-sign-in-button-BHL5a0JV.js +1 -0
- package/dist/assets/{sectorHelper-Fqgz3uEk.js → sectorHelper-DN_Vv6OL.js} +1 -1
- package/dist/assets/shortcut-C5x5LQWU.js +47 -0
- package/dist/assets/sms-sign-in-form-DTX9GV2I.js +1 -0
- package/dist/assets/{static.browser-CfQQzERe.js → static.browser-jI1psK0d.js} +8 -8
- package/dist/assets/{switch-DrxImI8F.js → switch-CRL8PmRI.js} +1 -1
- package/dist/assets/{tool-cards-BGfsY8JF.js → tool-cards-DFttLAfo.js} +6 -7
- package/dist/assets/use-authenticator-sign-in-CRGjzXju.js +1 -0
- package/dist/assets/use-dingtalk-sign-in-8WYzJ2jf.js +1 -0
- package/dist/assets/use-wecom-sign-in-C9j8wfCD.js +1 -0
- package/dist/assets/wecom-sign-in-button-mIS1zGSU.js +1 -0
- package/dist/index.html +2 -2
- package/dist/index.raw.html +5 -2
- package/package.json +3 -5
- package/scripts/build-html.mjs +12 -0
- package/src/App.css +2 -0
- package/src/App.tsx +35 -186
- package/src/app/development.tsx +154 -0
- package/src/app/extension.ts +5 -0
- package/src/app/extensions.tsx +18 -4
- package/src/app/routes.tsx +65 -0
- package/src/components/access-control/acl-bootstrap.tsx +11 -3
- package/src/components/access-control/acl-gate.tsx +7 -6
- package/src/components/access-control/can-access.tsx +17 -0
- package/src/components/access-control/navigate-to-accessible-resource.tsx +8 -3
- package/src/components/app-shell/sidebar.tsx +21 -5
- package/src/components/auth/auto-redirect-provider.tsx +2 -1
- package/src/extensions/nocobase-acl/README.md +74 -0
- package/{registry → src/extensions}/nocobase-acl/components/acl-boundary.tsx +22 -25
- package/{registry → src/extensions}/nocobase-acl/components/role-switcher.tsx +26 -23
- package/src/extensions/nocobase-acl/demo/acl-preview-provider.tsx +81 -0
- package/{registry → src/extensions}/nocobase-acl/demo/boundary-api.tsx +58 -0
- package/{registry → src/extensions}/nocobase-acl/demo/index.tsx +243 -105
- package/{registry → src/extensions}/nocobase-acl/demo/prompt-generator.tsx +3 -1
- package/src/extensions/nocobase-acl/extension.tsx +73 -0
- package/{registry → src/extensions}/nocobase-ai/README.md +21 -5
- package/{registry → src/extensions}/nocobase-ai/components/chat/chat-composer.tsx +3 -1
- package/{registry → src/extensions}/nocobase-ai/components/chat/chat-messages.tsx +38 -3
- package/{registry → src/extensions}/nocobase-ai/components/chat/tool-call-card.tsx +1 -9
- package/{registry → src/extensions}/nocobase-ai/components/index.ts +5 -0
- package/src/extensions/nocobase-ai/components/surfaces/chat-dialog.tsx +17 -0
- package/src/extensions/nocobase-ai/components/surfaces/chat-side-panel.tsx +35 -0
- package/src/extensions/nocobase-ai/components/surfaces/chat-surface.tsx +108 -0
- package/{registry → src/extensions}/nocobase-ai/components/triggers/ai-chat-floating-trigger.tsx +2 -2
- package/{registry → src/extensions}/nocobase-ai/demo/configuration-gate.tsx +4 -1
- package/{registry → src/extensions}/nocobase-ai/demo/container-showcase.tsx +2 -2
- package/{registry → src/extensions}/nocobase-ai/demo/floating.tsx +45 -15
- package/{registry → src/extensions}/nocobase-ai/demo/index.tsx +116 -74
- package/{registry → src/extensions}/nocobase-ai/demo/prompt-generator.tsx +3 -3
- package/{registry → src/extensions}/nocobase-ai/demo/tool-cards.tsx +2 -3
- package/src/extensions/nocobase-ai/extension.tsx +160 -0
- package/{registry → src/extensions}/nocobase-ai/global-ai-chat.tsx +12 -28
- package/{registry → src/extensions}/nocobase-ai/providers/ai-provider.tsx +14 -1
- package/{registry → src/extensions}/nocobase-ai/providers/chat-context.tsx +1 -0
- package/{registry → src/extensions}/nocobase-ai/providers/chat-provider.tsx +29 -8
- package/{registry → src/extensions}/nocobase-ai/providers/use-chat-attachments.ts +6 -1
- package/{registry → src/extensions}/nocobase-ai/providers/use-chat-work-context.ts +4 -1
- package/{registry → src/extensions}/nocobase-route-surfaces/README.md +2 -1
- package/{registry → src/extensions}/nocobase-route-surfaces/demo/index.tsx +33 -7
- package/{registry → src/extensions}/nocobase-route-surfaces/demo/scenarios.ts +20 -14
- package/{registry → src/extensions}/nocobase-route-surfaces/extension.tsx +55 -52
- package/src/{pages/users → extensions/nocobase-users-example}/create.tsx +4 -4
- package/src/{pages/users → extensions/nocobase-users-example}/edit.tsx +5 -9
- package/src/extensions/nocobase-users-example/extension.tsx +109 -0
- package/src/{pages/users → extensions/nocobase-users-example}/form-context.ts +11 -9
- package/src/extensions/nocobase-users-example/layout.tsx +16 -0
- package/src/{pages/users → extensions/nocobase-users-example}/list.tsx +1 -1
- package/src/extensions/nocobase-users-example/locales/en-US.ts +77 -0
- package/src/extensions/nocobase-users-example/locales/index.ts +8 -0
- package/src/extensions/nocobase-users-example/locales/zh-CN.ts +73 -0
- package/src/extensions/nocobase-users-example/optional-ai.ts +67 -0
- package/src/{pages/users → extensions/nocobase-users-example}/role-detail.tsx +4 -15
- package/src/{pages/users → extensions/nocobase-users-example}/routes.ts +1 -4
- package/src/extensions/nocobase-users-example/show.tsx +266 -0
- package/src/lib/nocobase/acl/context.ts +32 -0
- package/src/lib/nocobase/acl/evaluator.ts +186 -0
- package/src/lib/nocobase/acl/hooks.ts +40 -0
- package/src/lib/nocobase/acl/index.ts +4 -1
- package/src/lib/nocobase/acl/menu.ts +6 -6
- package/src/lib/nocobase/acl/record-permissions.ts +37 -7
- package/src/lib/nocobase/acl/store-provider.tsx +14 -0
- package/src/lib/nocobase/acl/store.ts +92 -86
- package/src/lib/nocobase/acl/types.ts +52 -32
- package/src/lib/nocobase/auth-session.ts +128 -0
- package/src/lib/nocobase/client.ts +48 -50
- package/src/locales/en-US.ts +0 -78
- package/src/locales/index.ts +2 -7
- package/src/locales/zh-CN.ts +0 -74
- package/src/providers/access-control.ts +43 -8
- package/src/providers/auth-callback.ts +1 -0
- package/src/providers/auth.ts +24 -26
- package/src/providers/constants.ts +0 -4
- package/src/providers/data.ts +14 -26
- package/src/providers/runtime-config.ts +40 -0
- package/src/vite-env.d.ts +9 -0
- package/tests/auth-session-regression.mjs +101 -0
- package/tsconfig.json +2 -1
- package/vite.config.ts +9 -1
- package/dist/assets/VisualMapping-Cbv1v7Cd.js +0 -1
- package/dist/assets/ai-employee-shortcut-B253WWow.js +0 -1
- package/dist/assets/calendar-B3dXXyIv.js +0 -1
- package/dist/assets/chat-inline-xpQ9iq4p.js +0 -1
- package/dist/assets/chat-side-panel-layout-BVWsp5rr.js +0 -1
- package/dist/assets/components-ChhJaNRc.js +0 -20
- package/dist/assets/configuration-gate-Dwdq_lxf.js +0 -1
- package/dist/assets/createSeriesDataSimply-CI7l7Ufv.js +0 -1
- package/dist/assets/customGraphicKeyframeAnimation-DE3jSfMd.js +0 -3
- package/dist/assets/echarts-preview-C-cNUtJF.js +0 -1
- package/dist/assets/floating-BarTmn-b.js +0 -13
- package/dist/assets/index-BJIcYTdc.js +0 -53
- package/dist/assets/index-C6xNKxpg.js +0 -656
- package/dist/assets/index-D4JQi1TM.js +0 -54
- package/dist/assets/index-YA7-AUO8.css +0 -1
- package/dist/assets/index-g8zWVpP9.js +0 -23
- package/dist/assets/prompt-card-BsYMW_rq.js +0 -1
- package/dist/assets/shortcut-xtghDP63.js +0 -47
- package/registry/nocobase-acl/README.md +0 -19
- package/registry/nocobase-acl/extension.tsx +0 -71
- package/registry/nocobase-acl/tests/acl-regression.mjs +0 -314
- package/registry/nocobase-ai/components/surfaces/chat-dialog.tsx +0 -31
- package/registry/nocobase-ai/components/surfaces/chat-side-panel.tsx +0 -74
- package/registry/nocobase-ai/extension.tsx +0 -158
- package/registry/nocobase-ai/tests/business-report-regression.mjs +0 -70
- package/registry/nocobase-ai/tests/form-filler-regression.mjs +0 -129
- package/registry/nocobase-ai/tests/frontend-tool-regression.mjs +0 -128
- package/registry/nocobase-ai/tests/page-context-regression.mjs +0 -48
- package/registry/nocobase-ai/tests/stream-regression.mjs +0 -207
- package/registry/nocobase-auth-cas/README.md +0 -6
- package/registry/nocobase-auth-cas/cas-sign-in-button.tsx +0 -41
- package/registry/nocobase-auth-cas/demo.tsx +0 -20
- package/registry/nocobase-auth-cas/extension.tsx +0 -46
- package/registry/nocobase-auth-cas/index.ts +0 -1
- package/registry/nocobase-auth-cas/use-cas-sign-in.ts +0 -29
- package/registry/nocobase-auth-dingtalk/README.md +0 -7
- package/registry/nocobase-auth-dingtalk/auto-login-provider.tsx +0 -154
- package/registry/nocobase-auth-dingtalk/demo.tsx +0 -23
- package/registry/nocobase-auth-dingtalk/dingtalk-sign-in-button.tsx +0 -45
- package/registry/nocobase-auth-dingtalk/extension.tsx +0 -55
- package/registry/nocobase-auth-dingtalk/index.ts +0 -4
- package/registry/nocobase-auth-dingtalk/use-dingtalk-sign-in.ts +0 -64
- package/registry/nocobase-auth-ldap/README.md +0 -6
- package/registry/nocobase-auth-ldap/demo.tsx +0 -21
- package/registry/nocobase-auth-ldap/extension.tsx +0 -46
- package/registry/nocobase-auth-ldap/index.ts +0 -1
- package/registry/nocobase-auth-ldap/ldap-sign-in-form.tsx +0 -69
- package/registry/nocobase-auth-ldap/use-ldap-sign-in.ts +0 -5
- package/registry/nocobase-auth-oidc/README.md +0 -11
- package/registry/nocobase-auth-oidc/auto-redirect-provider.tsx +0 -13
- package/registry/nocobase-auth-oidc/demo.tsx +0 -20
- package/registry/nocobase-auth-oidc/extension.tsx +0 -51
- package/registry/nocobase-auth-oidc/index.ts +0 -1
- package/registry/nocobase-auth-oidc/oidc-sign-in-button.tsx +0 -44
- package/registry/nocobase-auth-oidc/use-oidc-sign-in.ts +0 -58
- package/registry/nocobase-auth-saml/README.md +0 -6
- package/registry/nocobase-auth-saml/auto-redirect-provider.tsx +0 -13
- package/registry/nocobase-auth-saml/demo.tsx +0 -20
- package/registry/nocobase-auth-saml/extension.tsx +0 -51
- package/registry/nocobase-auth-saml/index.ts +0 -1
- package/registry/nocobase-auth-saml/saml-sign-in-button.tsx +0 -43
- package/registry/nocobase-auth-saml/use-saml-sign-in.ts +0 -51
- package/registry/nocobase-auth-sms/README.md +0 -7
- package/registry/nocobase-auth-sms/demo.tsx +0 -25
- package/registry/nocobase-auth-sms/extension.tsx +0 -46
- package/registry/nocobase-auth-sms/index.ts +0 -1
- package/registry/nocobase-auth-sms/sms-sign-in-form.tsx +0 -107
- package/registry/nocobase-auth-sms/use-sms-sign-in.ts +0 -88
- package/registry/nocobase-auth-wecom/README.md +0 -6
- package/registry/nocobase-auth-wecom/auto-login-provider.tsx +0 -21
- package/registry/nocobase-auth-wecom/demo.tsx +0 -23
- package/registry/nocobase-auth-wecom/extension.tsx +0 -49
- package/registry/nocobase-auth-wecom/index.ts +0 -1
- package/registry/nocobase-auth-wecom/use-wecom-sign-in.ts +0 -62
- package/registry/nocobase-auth-wecom/wecom-sign-in-button.tsx +0 -70
- package/registry/nocobase-i18n/README.md +0 -44
- package/registry/nocobase-i18n/components/index.ts +0 -1
- package/registry/nocobase-i18n/components/language-switcher.tsx +0 -138
- package/registry/nocobase-i18n/demo/index.tsx +0 -209
- package/registry/nocobase-i18n/demo/prompt-generator.tsx +0 -132
- package/registry/nocobase-i18n/extension.tsx +0 -45
- package/registry/nocobase-i18n/index.ts +0 -7
- package/registry/nocobase-i18n/locales/en-US.ts +0 -39
- package/registry/nocobase-i18n/locales/index.ts +0 -8
- package/registry/nocobase-i18n/locales/zh-CN.ts +0 -35
- package/registry/nocobase-i18n/provider.tsx +0 -44
- package/registry/nocobase-i18n/server-resources.ts +0 -166
- package/registry/nocobase-i18n/tests/i18n-regression.mjs +0 -51
- package/registry.config.json +0 -302
- package/scripts/registry.mjs +0 -164
- package/src/components/access-control/resource-access-guard.tsx +0 -21
- package/src/components/access-control/use-acl-runtime.ts +0 -28
- package/src/lib/nocobase/acl/action.ts +0 -147
- package/src/pages/users/layout.tsx +0 -15
- package/src/pages/users/show.tsx +0 -278
- /package/{registry → src/extensions}/nocobase-acl/components/index.ts +0 -0
- /package/{registry → src/extensions}/nocobase-acl/components/role-options.ts +0 -0
- /package/{registry → src/extensions}/nocobase-acl/demo/components.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-acl/demo/lazy-route.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-acl/demo/role-switcher-prompt-generator.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-acl/demo/scenario-section.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-acl/index.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/adapters/react-hook-form.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/assets/nocobase-ai-chat.svg +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/ai-root-provider.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/chat/ai-employee-avatar.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-attachment.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-compact.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-empty-state.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-header.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-history-dialog.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-message.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-window.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/chat/conversation-list.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/chat/markdown-message.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/chat/model-select-options.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/chat/reasoning-panel.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/chat/sub-agent-conversation.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/chat/user-prompt-editor.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/chat/work-context-chip.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/page-elements/ai-form.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/page-elements/page-element-provider.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/surfaces/chat-inline.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/surfaces/chat-page.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/surfaces/chat-side-panel-layout.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/surfaces/chat-surface-actions.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/tools/builtin-tool-renderers.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/tools/business-report-dialog.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/tools/business-report-renderer.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/tools/business-report-utils.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/tools/chart-renderer.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-preview.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-runtime-advanced.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-runtime-common.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-runtime-components.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-runtime-hierarchy.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-runtime.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/tools/sub-agent-renderer.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/tools/suggestions-renderer.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/tools/tool-renderer-provider.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/tools/tool-renderer-utils.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/tools/workflow-renderer.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/components/triggers/ai-employee-shortcut.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/demo/interaction-showcase.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/demo/page-context-prompt-generator.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/demo/page-context.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/demo/page-element-showcase.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/demo/prompt-card.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/demo/shortcut.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/index.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/avatars.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/chat-controller.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/chat-message-utils.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/chat-reducer.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/chat-task-utils.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/chat-transport.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/form-registry.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/frontend-tool-registry.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/index.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/model.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/page-context.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/stream-coalescer.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/stream-event-utils.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/stream-parser.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/sub-agent-stream.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/types.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/ui-message-stream.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/use-automatic-tool-approval.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/use-chat-message-actions.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/use-chat-runtime.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/use-conversation-catalog.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/providers/use-conversation-history.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/services/index.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/services/nocobase-ai-service.ts +0 -0
- /package/{registry → src/extensions}/nocobase-ai/services/types.ts +0 -0
- /package/{registry → src/extensions}/nocobase-route-surfaces/demo/lazy-route.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-route-surfaces/demo/prompt-generator.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-route-surfaces/index.ts +0 -0
- /package/{registry → src/extensions}/nocobase-route-surfaces/route-dialog.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-route-surfaces/route-drawer.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-route-surfaces/route-page.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-route-surfaces/route-surface-context.ts +0 -0
- /package/{registry → src/extensions}/nocobase-route-surfaces/use-refine-unsaved-changes.tsx +0 -0
- /package/{registry → src/extensions}/nocobase-route-surfaces/use-route-surface-close.ts +0 -0
- /package/{registry → src/extensions}/nocobase-route-surfaces/use-route-surface-state.ts +0 -0
- /package/src/{pages/users → extensions/nocobase-users-example}/form-fields.tsx +0 -0
- /package/src/{pages/users → extensions/nocobase-users-example}/index.ts +0 -0
- /package/src/{pages/users → extensions/nocobase-users-example}/role-badges.tsx +0 -0
- /package/src/{pages/users → extensions/nocobase-users-example}/role-utils.ts +0 -0
- /package/src/{pages/users → extensions/nocobase-users-example}/types.ts +0 -0
|
@@ -9,7 +9,13 @@ import {
|
|
|
9
9
|
} from "../../providers";
|
|
10
10
|
import { cn } from "@/lib/utils";
|
|
11
11
|
import { ArrowDown } from "lucide-react";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
useEffect,
|
|
14
|
+
useLayoutEffect,
|
|
15
|
+
useRef,
|
|
16
|
+
useState,
|
|
17
|
+
type ReactNode,
|
|
18
|
+
} from "react";
|
|
13
19
|
import { ChatEmptyState } from "./chat-empty-state";
|
|
14
20
|
import { ChatMessage } from "./chat-message";
|
|
15
21
|
|
|
@@ -81,6 +87,7 @@ export function AIChatMessageList({
|
|
|
81
87
|
focusComposer,
|
|
82
88
|
}: AIChatMessageListProps) {
|
|
83
89
|
const viewportRef = useRef<HTMLDivElement>(null);
|
|
90
|
+
const bottomOffsetRef = useRef(0);
|
|
84
91
|
const [atBottom, setAtBottom] = useState(true);
|
|
85
92
|
|
|
86
93
|
const scrollToBottom = (behavior: ScrollBehavior = "smooth") => {
|
|
@@ -89,6 +96,31 @@ export function AIChatMessageList({
|
|
|
89
96
|
viewport.scrollTo({ top: viewport.scrollHeight, behavior });
|
|
90
97
|
};
|
|
91
98
|
|
|
99
|
+
useLayoutEffect(() => {
|
|
100
|
+
const viewport = viewportRef.current;
|
|
101
|
+
if (!viewport) return;
|
|
102
|
+
viewport.scrollTop = viewport.scrollHeight;
|
|
103
|
+
bottomOffsetRef.current = 0;
|
|
104
|
+
}, []);
|
|
105
|
+
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
const viewport = viewportRef.current;
|
|
108
|
+
if (!viewport || typeof ResizeObserver === "undefined") return;
|
|
109
|
+
|
|
110
|
+
const observer = new ResizeObserver(() => {
|
|
111
|
+
const maxScrollTop = Math.max(
|
|
112
|
+
0,
|
|
113
|
+
viewport.scrollHeight - viewport.clientHeight
|
|
114
|
+
);
|
|
115
|
+
viewport.scrollTop = Math.max(
|
|
116
|
+
0,
|
|
117
|
+
maxScrollTop - bottomOffsetRef.current
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
observer.observe(viewport);
|
|
121
|
+
return () => observer.disconnect();
|
|
122
|
+
}, []);
|
|
123
|
+
|
|
92
124
|
useEffect(() => {
|
|
93
125
|
if (atBottom) scrollToBottom(status === "streaming" ? "auto" : "smooth");
|
|
94
126
|
}, [atBottom, messages, status]);
|
|
@@ -107,9 +139,12 @@ export function AIChatMessageList({
|
|
|
107
139
|
className="absolute inset-0 overflow-x-hidden overflow-y-auto overscroll-contain"
|
|
108
140
|
onScroll={(event) => {
|
|
109
141
|
const element = event.currentTarget;
|
|
110
|
-
|
|
111
|
-
|
|
142
|
+
const bottomOffset = Math.max(
|
|
143
|
+
0,
|
|
144
|
+
element.scrollHeight - element.scrollTop - element.clientHeight
|
|
112
145
|
);
|
|
146
|
+
bottomOffsetRef.current = bottomOffset;
|
|
147
|
+
setAtBottom(bottomOffset < 48);
|
|
113
148
|
}}
|
|
114
149
|
>
|
|
115
150
|
{loading ? (
|
|
@@ -131,9 +131,7 @@ export function ToolCallCard({
|
|
|
131
131
|
const [deciding, setDeciding] = useState(false);
|
|
132
132
|
const renderer = useAIToolRenderer(getToolCallName(part));
|
|
133
133
|
const Renderer = renderer?.component;
|
|
134
|
-
const [open, setOpen] = useState(
|
|
135
|
-
part.state === "output-error" || Boolean(Renderer)
|
|
136
|
-
);
|
|
134
|
+
const [open, setOpen] = useState(false);
|
|
137
135
|
const toolStatus = getStatus(part);
|
|
138
136
|
const approvalRequired =
|
|
139
137
|
resolvedApproval?.required === true && approvalStatus === "pending";
|
|
@@ -152,12 +150,6 @@ export function ToolCallCard({
|
|
|
152
150
|
setApprovalStatus(resolvedApproval?.status ?? "pending");
|
|
153
151
|
}, [resolvedApproval?.status]);
|
|
154
152
|
|
|
155
|
-
useEffect(() => {
|
|
156
|
-
if (part.state === "output-error") {
|
|
157
|
-
setOpen(true);
|
|
158
|
-
}
|
|
159
|
-
}, [part.state]);
|
|
160
|
-
|
|
161
153
|
const decide = async (
|
|
162
154
|
decision: "approve" | "reject" | "edit",
|
|
163
155
|
input?: unknown
|
|
@@ -13,6 +13,11 @@ export {
|
|
|
13
13
|
} from "./chat/chat-messages";
|
|
14
14
|
export { AIModelSelectOptions } from "./chat/model-select-options";
|
|
15
15
|
export { ChatDialog } from "./surfaces/chat-dialog";
|
|
16
|
+
export {
|
|
17
|
+
ChatSurface,
|
|
18
|
+
type ChatSurfaceProps,
|
|
19
|
+
type ChatSurfaceVariant,
|
|
20
|
+
} from "./surfaces/chat-surface";
|
|
16
21
|
export { ChatSurfaceActions } from "./surfaces/chat-surface-actions";
|
|
17
22
|
export { ChatInline } from "./surfaces/chat-inline";
|
|
18
23
|
export { ChatPage } from "./surfaces/chat-page";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { PropsWithChildren } from "react";
|
|
2
|
+
import { ChatSurface } from "./chat-surface";
|
|
3
|
+
|
|
4
|
+
export function ChatDialog({
|
|
5
|
+
open,
|
|
6
|
+
onOpenChange,
|
|
7
|
+
children,
|
|
8
|
+
}: PropsWithChildren<{
|
|
9
|
+
open: boolean;
|
|
10
|
+
onOpenChange: (open: boolean) => void;
|
|
11
|
+
}>) {
|
|
12
|
+
return (
|
|
13
|
+
<ChatSurface open={open} variant="dialog" onOpenChange={onOpenChange}>
|
|
14
|
+
{children}
|
|
15
|
+
</ChatSurface>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { PropsWithChildren } from "react";
|
|
2
|
+
import { ChatSurface } from "./chat-surface";
|
|
3
|
+
|
|
4
|
+
export type ChatSidePanelProps = PropsWithChildren<{
|
|
5
|
+
open: boolean;
|
|
6
|
+
onOpenChange: (open: boolean) => void;
|
|
7
|
+
side?: "left" | "right";
|
|
8
|
+
width?: number | string;
|
|
9
|
+
closeOnEscape?: boolean;
|
|
10
|
+
showCloseHandle?: boolean;
|
|
11
|
+
}>;
|
|
12
|
+
|
|
13
|
+
export function ChatSidePanel({
|
|
14
|
+
open,
|
|
15
|
+
onOpenChange,
|
|
16
|
+
side = "right",
|
|
17
|
+
width = 450,
|
|
18
|
+
closeOnEscape = true,
|
|
19
|
+
showCloseHandle = true,
|
|
20
|
+
children,
|
|
21
|
+
}: ChatSidePanelProps) {
|
|
22
|
+
return (
|
|
23
|
+
<ChatSurface
|
|
24
|
+
open={open}
|
|
25
|
+
variant="side-panel"
|
|
26
|
+
onOpenChange={onOpenChange}
|
|
27
|
+
side={side}
|
|
28
|
+
width={width}
|
|
29
|
+
closeOnEscape={closeOnEscape}
|
|
30
|
+
showCloseHandle={showCloseHandle}
|
|
31
|
+
>
|
|
32
|
+
{children}
|
|
33
|
+
</ChatSurface>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { Button } from "@/components/ui/button";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
|
|
4
|
+
import { PanelLeftClose, PanelRightClose } from "lucide-react";
|
|
5
|
+
import type { CSSProperties, PropsWithChildren } from "react";
|
|
6
|
+
|
|
7
|
+
export type ChatSurfaceVariant = "side-panel" | "dialog";
|
|
8
|
+
|
|
9
|
+
export type ChatSurfaceProps = PropsWithChildren<{
|
|
10
|
+
open: boolean;
|
|
11
|
+
variant: ChatSurfaceVariant;
|
|
12
|
+
onOpenChange: (open: boolean) => void;
|
|
13
|
+
side?: "left" | "right";
|
|
14
|
+
width?: number | string;
|
|
15
|
+
closeOnEscape?: boolean;
|
|
16
|
+
showCloseHandle?: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
|
|
19
|
+
export function ChatSurface({
|
|
20
|
+
open,
|
|
21
|
+
variant,
|
|
22
|
+
onOpenChange,
|
|
23
|
+
side = "right",
|
|
24
|
+
width = 450,
|
|
25
|
+
closeOnEscape = true,
|
|
26
|
+
showCloseHandle = false,
|
|
27
|
+
children,
|
|
28
|
+
}: ChatSurfaceProps) {
|
|
29
|
+
const expanded = variant === "dialog";
|
|
30
|
+
const panelWidth = typeof width === "number" ? `${width}px` : width;
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<DialogPrimitive.Root
|
|
34
|
+
open={open}
|
|
35
|
+
modal={expanded}
|
|
36
|
+
disablePointerDismissal={!expanded}
|
|
37
|
+
onOpenChange={(nextOpen, eventDetails) => {
|
|
38
|
+
if (
|
|
39
|
+
!nextOpen &&
|
|
40
|
+
eventDetails.reason === "escape-key" &&
|
|
41
|
+
!closeOnEscape
|
|
42
|
+
) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
onOpenChange(nextOpen);
|
|
46
|
+
}}
|
|
47
|
+
>
|
|
48
|
+
<DialogPrimitive.Portal>
|
|
49
|
+
<DialogPrimitive.Backdrop
|
|
50
|
+
className={cn(
|
|
51
|
+
"fixed inset-0 isolate z-50 bg-black/10 supports-backdrop-filter:backdrop-blur-xs data-closed:pointer-events-none",
|
|
52
|
+
!expanded && "pointer-events-none opacity-0"
|
|
53
|
+
)}
|
|
54
|
+
/>
|
|
55
|
+
<DialogPrimitive.Popup
|
|
56
|
+
data-variant={variant}
|
|
57
|
+
data-side={side}
|
|
58
|
+
initialFocus={expanded}
|
|
59
|
+
className={cn(
|
|
60
|
+
"fixed z-50 flex max-w-full bg-background text-foreground shadow-2xl outline-none",
|
|
61
|
+
"data-closed:pointer-events-none data-closed:opacity-0",
|
|
62
|
+
expanded
|
|
63
|
+
? "top-1/2 left-1/2 h-[95svh] w-[95vw] -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-xl border"
|
|
64
|
+
: cn(
|
|
65
|
+
"inset-y-0 h-svh w-(--chat-surface-width) translate-x-0 translate-y-0 overflow-visible rounded-none",
|
|
66
|
+
side === "right"
|
|
67
|
+
? "right-0 border-l"
|
|
68
|
+
: "left-0 border-r"
|
|
69
|
+
)
|
|
70
|
+
)}
|
|
71
|
+
style={
|
|
72
|
+
{
|
|
73
|
+
"--chat-surface-width": panelWidth,
|
|
74
|
+
} as CSSProperties
|
|
75
|
+
}
|
|
76
|
+
>
|
|
77
|
+
<DialogPrimitive.Title className="sr-only">
|
|
78
|
+
NocoBase AI employee
|
|
79
|
+
</DialogPrimitive.Title>
|
|
80
|
+
<DialogPrimitive.Description className="sr-only">
|
|
81
|
+
{expanded
|
|
82
|
+
? "Expanded AI conversation window."
|
|
83
|
+
: "AI conversation side panel."}
|
|
84
|
+
</DialogPrimitive.Description>
|
|
85
|
+
{showCloseHandle && !expanded ? (
|
|
86
|
+
<Button
|
|
87
|
+
variant="outline"
|
|
88
|
+
size="icon-sm"
|
|
89
|
+
className={cn(
|
|
90
|
+
"absolute top-1/2 z-40 size-9 -translate-y-1/2 rounded-full bg-background shadow-md before:absolute before:-inset-2",
|
|
91
|
+
side === "right"
|
|
92
|
+
? "left-0 -translate-x-1/2"
|
|
93
|
+
: "right-0 translate-x-1/2"
|
|
94
|
+
)}
|
|
95
|
+
aria-label="Close side panel"
|
|
96
|
+
onClick={() => onOpenChange(false)}
|
|
97
|
+
>
|
|
98
|
+
{side === "right" ? <PanelRightClose /> : <PanelLeftClose />}
|
|
99
|
+
</Button>
|
|
100
|
+
) : null}
|
|
101
|
+
<div className="min-h-0 min-w-0 flex-1 overflow-hidden">
|
|
102
|
+
{children}
|
|
103
|
+
</div>
|
|
104
|
+
</DialogPrimitive.Popup>
|
|
105
|
+
</DialogPrimitive.Portal>
|
|
106
|
+
</DialogPrimitive.Root>
|
|
107
|
+
);
|
|
108
|
+
}
|
package/{registry → src/extensions}/nocobase-ai/components/triggers/ai-chat-floating-trigger.tsx
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import nocobaseAIChatIcon from "../../assets/nocobase-ai-chat.svg";
|
|
2
|
-
import { cn } from "@/lib/utils";
|
|
2
|
+
import { assetUrl, cn } from "@/lib/utils";
|
|
3
3
|
import {
|
|
4
4
|
useAI,
|
|
5
5
|
useAIChatControllerState,
|
|
@@ -57,7 +57,7 @@ export function AIChatFloatingTrigger({
|
|
|
57
57
|
<span className="relative flex size-[42px] items-center justify-center">
|
|
58
58
|
<span className="flex size-full overflow-hidden rounded-lg">
|
|
59
59
|
<img
|
|
60
|
-
src={nocobaseAIChatIcon}
|
|
60
|
+
src={assetUrl(nocobaseAIChatIcon)}
|
|
61
61
|
alt=""
|
|
62
62
|
className="size-full object-contain"
|
|
63
63
|
/>
|
|
@@ -65,7 +65,10 @@ const previewService: AIService = {
|
|
|
65
65
|
|
|
66
66
|
export function AIConfigurationGate({ children }: { children: ReactNode }) {
|
|
67
67
|
const { configurationStatus, hasEnabledModels, employees } = useAI();
|
|
68
|
-
const configured =
|
|
68
|
+
const configured =
|
|
69
|
+
configurationStatus === "ready" &&
|
|
70
|
+
hasEnabledModels &&
|
|
71
|
+
employees.length > 0;
|
|
69
72
|
|
|
70
73
|
if (configured) return children;
|
|
71
74
|
|
|
@@ -199,9 +199,9 @@ const containerComponent = (value: ChatContainer) => {
|
|
|
199
199
|
case "page":
|
|
200
200
|
return "<ChatPage />";
|
|
201
201
|
case "side-panel":
|
|
202
|
-
return
|
|
202
|
+
return '<ChatSurface variant="side-panel" />';
|
|
203
203
|
case "dialog":
|
|
204
|
-
return
|
|
204
|
+
return '<ChatSurface variant="dialog" />';
|
|
205
205
|
case "mobile":
|
|
206
206
|
return "<ChatInline /> · 390px";
|
|
207
207
|
default:
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AIChatFloatingTrigger,
|
|
3
3
|
AIChatWindow,
|
|
4
|
-
|
|
4
|
+
ChatSurface,
|
|
5
|
+
ChatSurfaceActions,
|
|
5
6
|
} from "../components";
|
|
6
7
|
import { Badge } from "@/components/ui/badge";
|
|
7
8
|
import { Card } from "@/components/ui/card";
|
|
@@ -12,19 +13,22 @@ import {
|
|
|
12
13
|
} from "../providers";
|
|
13
14
|
import { PromptCard } from "./prompt-card";
|
|
14
15
|
import { AIConfigurationGate } from "./configuration-gate";
|
|
16
|
+
import { useState, type CSSProperties } from "react";
|
|
15
17
|
|
|
16
18
|
const floatingPrompt = `Add the standard NocoBase AI floating chat entry to the application layout.
|
|
17
19
|
|
|
18
20
|
Requirements:
|
|
19
21
|
- Render AIChatFloatingTrigger at the lower-right edge of the application.
|
|
20
22
|
- Bind it to the global AI chat controller.
|
|
21
|
-
- Clicking the trigger opens a 450px
|
|
23
|
+
- Clicking the trigger opens ChatSurface with variant="side-panel" and a 450px width on the right.
|
|
22
24
|
- The side panel must push the desktop page narrower instead of blocking page interaction.
|
|
23
25
|
- Mobile may switch to an overlay presentation.
|
|
24
26
|
- Hide the floating trigger while the side panel is open.
|
|
25
27
|
- Support an unread-count badge.
|
|
26
28
|
- Start a new conversation with the configured default AI employee when opened.
|
|
27
|
-
-
|
|
29
|
+
- Put ChatSurfaceActions in the AIChatWindow header so expand/collapse and close stay in the upper-right corner.
|
|
30
|
+
- Keep one AIChatWindow mounted and change ChatSurface.variant to "dialog" when expanded.
|
|
31
|
+
- Keep the trigger and ChatSurface separate from AIChatWindow.
|
|
28
32
|
- Use shadcn/Base UI components and the existing AIProvider/AIChatProvider runtime.`;
|
|
29
33
|
|
|
30
34
|
export function FloatingChatPage() {
|
|
@@ -38,14 +42,24 @@ export function FloatingChatPage() {
|
|
|
38
42
|
function FloatingChatPageContent() {
|
|
39
43
|
const controller = useAIChatController();
|
|
40
44
|
const { open } = useAIChatControllerState(controller);
|
|
45
|
+
const [expanded, setExpanded] = useState(false);
|
|
46
|
+
|
|
47
|
+
const handleOpenChange = (nextOpen: boolean) => {
|
|
48
|
+
if (!nextOpen) setExpanded(false);
|
|
49
|
+
controller.setOpen(nextOpen);
|
|
50
|
+
};
|
|
41
51
|
|
|
42
52
|
return (
|
|
43
53
|
<AIChatProvider id="floating-chat-demo" controller={controller}>
|
|
44
|
-
<
|
|
45
|
-
open={open}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
54
|
+
<div
|
|
55
|
+
data-open={open && !expanded}
|
|
56
|
+
data-side="right"
|
|
57
|
+
className="chat-side-panel-layout @container min-w-0"
|
|
58
|
+
style={
|
|
59
|
+
{
|
|
60
|
+
"--chat-side-panel-width": "450px",
|
|
61
|
+
} as CSSProperties
|
|
62
|
+
}
|
|
49
63
|
>
|
|
50
64
|
<div className="space-y-12 pb-12">
|
|
51
65
|
<section className="flex flex-wrap items-start justify-between gap-5 border-b pb-8">
|
|
@@ -58,9 +72,9 @@ function FloatingChatPageContent() {
|
|
|
58
72
|
Floating AI Chat
|
|
59
73
|
</h1>
|
|
60
74
|
<p className="mt-3 max-w-3xl text-sm leading-6 text-muted-foreground">
|
|
61
|
-
A global lower-right entry for the shared AI conversation. It
|
|
62
|
-
|
|
63
|
-
|
|
75
|
+
A global lower-right entry for the shared AI conversation. It
|
|
76
|
+
opens as a push side panel and can expand into a focused dialog
|
|
77
|
+
without remounting the chat window.
|
|
64
78
|
</p>
|
|
65
79
|
</div>
|
|
66
80
|
</section>
|
|
@@ -71,7 +85,7 @@ function FloatingChatPageContent() {
|
|
|
71
85
|
Interactive preview
|
|
72
86
|
</p>
|
|
73
87
|
<h2 className="mt-2 text-xl font-semibold tracking-tight">
|
|
74
|
-
Global launcher and
|
|
88
|
+
Global launcher and adaptive chat surface
|
|
75
89
|
</h2>
|
|
76
90
|
<p className="mt-1.5 max-w-3xl text-sm leading-6 text-muted-foreground">
|
|
77
91
|
The trigger is constrained to this simulated application in the
|
|
@@ -83,7 +97,7 @@ function FloatingChatPageContent() {
|
|
|
83
97
|
<div className="flex h-12 items-center justify-between border-b px-4">
|
|
84
98
|
<span className="text-sm font-medium">Application shell</span>
|
|
85
99
|
<code className="rounded-md bg-muted px-2 py-1 text-xs text-muted-foreground">
|
|
86
|
-
AIChatFloatingTrigger →
|
|
100
|
+
AIChatFloatingTrigger → ChatSurface · side-panel/dialog
|
|
87
101
|
</code>
|
|
88
102
|
</div>
|
|
89
103
|
<div className="relative grid min-h-[560px] grid-cols-[190px_minmax(0,1fr)] overflow-hidden bg-background">
|
|
@@ -123,12 +137,28 @@ function FloatingChatPageContent() {
|
|
|
123
137
|
</div>
|
|
124
138
|
<PromptCard
|
|
125
139
|
title="Add a lower-right AI floating entry"
|
|
126
|
-
description="This prompt
|
|
140
|
+
description="This prompt configures the global trigger and its switchable side-panel/dialog surface."
|
|
127
141
|
prompt={floatingPrompt}
|
|
128
142
|
/>
|
|
129
143
|
</section>
|
|
130
144
|
</div>
|
|
131
|
-
|
|
145
|
+
<ChatSurface
|
|
146
|
+
open={open}
|
|
147
|
+
variant={expanded ? "dialog" : "side-panel"}
|
|
148
|
+
onOpenChange={handleOpenChange}
|
|
149
|
+
width={450}
|
|
150
|
+
>
|
|
151
|
+
<AIChatWindow
|
|
152
|
+
headerActions={
|
|
153
|
+
<ChatSurfaceActions
|
|
154
|
+
expanded={expanded}
|
|
155
|
+
onExpandedChange={setExpanded}
|
|
156
|
+
onClose={() => handleOpenChange(false)}
|
|
157
|
+
/>
|
|
158
|
+
}
|
|
159
|
+
/>
|
|
160
|
+
</ChatSurface>
|
|
161
|
+
</div>
|
|
132
162
|
</AIChatProvider>
|
|
133
163
|
);
|
|
134
164
|
}
|