@modern-admin/web 0.3.2 → 0.3.4
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/dist/standalone/assets/action-component-host-CXIbN-8V.js +2 -0
- package/dist/standalone/assets/action-component-host-CXIbN-8V.js.br +0 -0
- package/dist/standalone/assets/action-component-host-CXIbN-8V.js.gz +0 -0
- package/dist/standalone/assets/action-component-host-CXIbN-8V.js.map +1 -0
- package/dist/standalone/assets/action-page-OsWfKQ6C.js +2 -0
- package/dist/standalone/assets/action-page-OsWfKQ6C.js.br +0 -0
- package/dist/standalone/assets/action-page-OsWfKQ6C.js.gz +0 -0
- package/dist/standalone/assets/action-page-OsWfKQ6C.js.map +1 -0
- package/dist/standalone/assets/{ai-assistant-widget-DU9YZkvm.js → ai-assistant-widget-Bt4Z7Fmr.js} +2 -2
- package/dist/standalone/assets/ai-assistant-widget-Bt4Z7Fmr.js.br +0 -0
- package/dist/standalone/assets/ai-assistant-widget-Bt4Z7Fmr.js.gz +0 -0
- package/dist/standalone/assets/{ai-assistant-widget-DU9YZkvm.js.map → ai-assistant-widget-Bt4Z7Fmr.js.map} +1 -1
- package/dist/standalone/assets/arrow-left-CI9hUPwJ.js +2 -0
- package/dist/standalone/assets/arrow-left-CI9hUPwJ.js.map +1 -0
- package/dist/standalone/assets/audit-log-page-2wuGiWg-.js +2 -0
- package/dist/standalone/assets/audit-log-page-2wuGiWg-.js.br +0 -0
- package/dist/standalone/assets/audit-log-page-2wuGiWg-.js.gz +0 -0
- package/dist/standalone/assets/{audit-log-page-8Gv2dmY7.js.map → audit-log-page-2wuGiWg-.js.map} +1 -1
- package/dist/standalone/assets/{calendar-BObEBLfG.js → calendar-BZVUWakC.js} +2 -2
- package/dist/standalone/assets/calendar-BZVUWakC.js.br +0 -0
- package/dist/standalone/assets/calendar-BZVUWakC.js.gz +0 -0
- package/dist/standalone/assets/{calendar-BObEBLfG.js.map → calendar-BZVUWakC.js.map} +1 -1
- package/dist/standalone/assets/chart-widget-BtJb6YXV.js +2 -0
- package/dist/standalone/assets/chart-widget-BtJb6YXV.js.br +0 -0
- package/dist/standalone/assets/chart-widget-BtJb6YXV.js.gz +0 -0
- package/dist/standalone/assets/{chart-widget-BWFpFuqE.js.map → chart-widget-BtJb6YXV.js.map} +1 -1
- package/dist/standalone/assets/circle-alert-0EyKeic4.js +2 -0
- package/dist/standalone/assets/circle-alert-0EyKeic4.js.map +1 -0
- package/dist/standalone/assets/{command-BXuvMfZb.js → command-BNF_evMy.js} +2 -2
- package/dist/standalone/assets/command-BNF_evMy.js.br +0 -0
- package/dist/standalone/assets/command-BNF_evMy.js.gz +0 -0
- package/dist/standalone/assets/{command-BXuvMfZb.js.map → command-BNF_evMy.js.map} +1 -1
- package/dist/standalone/assets/{date-picker-r8u06XBh.js → date-picker-LfbUehd1.js} +2 -2
- package/dist/standalone/assets/date-picker-LfbUehd1.js.br +0 -0
- package/dist/standalone/assets/date-picker-LfbUehd1.js.gz +0 -0
- package/dist/standalone/assets/{date-picker-r8u06XBh.js.map → date-picker-LfbUehd1.js.map} +1 -1
- package/dist/standalone/assets/{dist-CvKz-wgE.js → dist-BSbFjTlr.js} +2 -2
- package/dist/standalone/assets/dist-BSbFjTlr.js.br +0 -0
- package/dist/standalone/assets/dist-BSbFjTlr.js.gz +0 -0
- package/dist/standalone/assets/dist-BSbFjTlr.js.map +1 -0
- package/dist/standalone/assets/{dist-Dkym1-ts.js → dist-BcL2U6dT.js} +2 -2
- package/dist/standalone/assets/dist-BcL2U6dT.js.br +0 -0
- package/dist/standalone/assets/dist-BcL2U6dT.js.gz +0 -0
- package/dist/standalone/assets/{dist-Dkym1-ts.js.map → dist-BcL2U6dT.js.map} +1 -1
- package/dist/standalone/assets/edit-page-DCRB9Y_q.js +2 -0
- package/dist/standalone/assets/edit-page-DCRB9Y_q.js.br +0 -0
- package/dist/standalone/assets/edit-page-DCRB9Y_q.js.gz +0 -0
- package/dist/standalone/assets/edit-page-DCRB9Y_q.js.map +1 -0
- package/dist/standalone/assets/ellipsis-lEjcTxo0.js +2 -0
- package/dist/standalone/assets/ellipsis-lEjcTxo0.js.map +1 -0
- package/dist/standalone/assets/{empty-Ccn1VX37.js → empty-DAEAjFd3.js} +2 -2
- package/dist/standalone/assets/empty-DAEAjFd3.js.br +0 -0
- package/dist/standalone/assets/empty-DAEAjFd3.js.gz +0 -0
- package/dist/standalone/assets/{empty-Ccn1VX37.js.map → empty-DAEAjFd3.js.map} +1 -1
- package/dist/standalone/assets/global-search-dialog-HMLztOho.js +2 -0
- package/dist/standalone/assets/global-search-dialog-HMLztOho.js.br +0 -0
- package/dist/standalone/assets/global-search-dialog-HMLztOho.js.gz +0 -0
- package/dist/standalone/assets/{global-search-dialog-DdRt4k5C.js.map → global-search-dialog-HMLztOho.js.map} +1 -1
- package/dist/standalone/assets/{heavy-fields-CVzRBLt9.js → heavy-fields-ZuqfOFMv.js} +2 -2
- package/dist/standalone/assets/heavy-fields-ZuqfOFMv.js.br +0 -0
- package/dist/standalone/assets/heavy-fields-ZuqfOFMv.js.gz +0 -0
- package/dist/standalone/assets/{heavy-fields-CVzRBLt9.js.map → heavy-fields-ZuqfOFMv.js.map} +1 -1
- package/dist/standalone/assets/home-page-HmheewiP.js +3 -0
- package/dist/standalone/assets/home-page-HmheewiP.js.br +0 -0
- package/dist/standalone/assets/home-page-HmheewiP.js.gz +0 -0
- package/dist/standalone/assets/{home-page-DyNb5GLu.js.map → home-page-HmheewiP.js.map} +1 -1
- package/dist/standalone/assets/icon-registry-BV44--RL.js +2 -0
- package/dist/standalone/assets/icon-registry-BV44--RL.js.br +0 -0
- package/dist/standalone/assets/icon-registry-BV44--RL.js.gz +0 -0
- package/dist/standalone/assets/icon-registry-BV44--RL.js.map +1 -0
- package/dist/standalone/assets/{index-OvloY2cG.css → index-95cwJ2RY.css} +1 -1
- package/dist/standalone/assets/index-95cwJ2RY.css.br +0 -0
- package/dist/standalone/assets/index-95cwJ2RY.css.gz +0 -0
- package/dist/standalone/assets/index-t4woXGa-.js +15 -0
- package/dist/standalone/assets/index-t4woXGa-.js.br +0 -0
- package/dist/standalone/assets/index-t4woXGa-.js.gz +0 -0
- package/dist/standalone/assets/index-t4woXGa-.js.map +1 -0
- package/dist/standalone/assets/json-editor-sGw4fDoj.js +2 -0
- package/dist/standalone/assets/json-editor-sGw4fDoj.js.br +0 -0
- package/dist/standalone/assets/json-editor-sGw4fDoj.js.gz +0 -0
- package/dist/standalone/assets/{json-editor-D6vtFyYl.js.map → json-editor-sGw4fDoj.js.map} +1 -1
- package/dist/standalone/assets/property-renderer-DyCwdVkh.js +7 -0
- package/dist/standalone/assets/property-renderer-DyCwdVkh.js.br +0 -0
- package/dist/standalone/assets/property-renderer-DyCwdVkh.js.gz +0 -0
- package/dist/standalone/assets/property-renderer-DyCwdVkh.js.map +1 -0
- package/dist/standalone/assets/reference-Dfd804y3.js +2 -0
- package/dist/standalone/assets/reference-Dfd804y3.js.br +0 -0
- package/dist/standalone/assets/reference-Dfd804y3.js.gz +0 -0
- package/dist/standalone/assets/{reference-Dfum6XNs.js.map → reference-Dfd804y3.js.map} +1 -1
- package/dist/standalone/assets/refresh-cw-DHvUQTMb.js +2 -0
- package/dist/standalone/assets/refresh-cw-DHvUQTMb.js.map +1 -0
- package/dist/standalone/assets/revisions-button-DXZAh2Lu.js +2 -0
- package/dist/standalone/assets/revisions-button-DXZAh2Lu.js.br +0 -0
- package/dist/standalone/assets/revisions-button-DXZAh2Lu.js.gz +0 -0
- package/dist/standalone/assets/{revisions-button-B1CRVduG.js.map → revisions-button-DXZAh2Lu.js.map} +1 -1
- package/dist/standalone/assets/router-wFvtgo77.js +186 -0
- package/dist/standalone/assets/router-wFvtgo77.js.br +0 -0
- package/dist/standalone/assets/router-wFvtgo77.js.gz +0 -0
- package/dist/standalone/assets/router-wFvtgo77.js.map +1 -0
- package/dist/standalone/assets/select-BWf6walM.js +2 -0
- package/dist/standalone/assets/select-BWf6walM.js.br +0 -0
- package/dist/standalone/assets/select-BWf6walM.js.gz +0 -0
- package/dist/standalone/assets/{select-JdSGjgiW.js.map → select-BWf6walM.js.map} +1 -1
- package/dist/standalone/assets/settings-page-Co7sWbbL.js +2 -0
- package/dist/standalone/assets/settings-page-Co7sWbbL.js.br +0 -0
- package/dist/standalone/assets/settings-page-Co7sWbbL.js.gz +0 -0
- package/dist/standalone/assets/{settings-page-7eRUjHFt.js.map → settings-page-Co7sWbbL.js.map} +1 -1
- package/dist/standalone/assets/show-page-D-_vldWV.js +2 -0
- package/dist/standalone/assets/show-page-D-_vldWV.js.br +0 -0
- package/dist/standalone/assets/show-page-D-_vldWV.js.gz +0 -0
- package/dist/standalone/assets/show-page-D-_vldWV.js.map +1 -0
- package/dist/standalone/assets/{tabs-CfQ4jLnP.js → tabs-khcHka8W.js} +2 -2
- package/dist/standalone/assets/tabs-khcHka8W.js.br +0 -0
- package/dist/standalone/assets/tabs-khcHka8W.js.gz +0 -0
- package/dist/standalone/assets/{tabs-CfQ4jLnP.js.map → tabs-khcHka8W.js.map} +1 -1
- package/dist/standalone/assets/{zap-Be2c7_cs.js → upload-BVhXhZgn.js} +2 -2
- package/dist/standalone/assets/upload-BVhXhZgn.js.br +0 -0
- package/dist/standalone/assets/upload-BVhXhZgn.js.gz +0 -0
- package/dist/standalone/assets/upload-BVhXhZgn.js.map +1 -0
- package/dist/standalone/assets/{useQueries-CX5Gh6HV.js → useQueries-BCUhWYX4.js} +2 -2
- package/dist/standalone/assets/useQueries-BCUhWYX4.js.br +0 -0
- package/dist/standalone/assets/useQueries-BCUhWYX4.js.gz +0 -0
- package/dist/standalone/assets/{useQueries-CX5Gh6HV.js.map → useQueries-BCUhWYX4.js.map} +1 -1
- package/dist/standalone/assets/{user-directory-ZxAjN_q9.js → user-directory-9COoW6AO.js} +2 -2
- package/dist/standalone/assets/user-directory-9COoW6AO.js.br +0 -0
- package/dist/standalone/assets/user-directory-9COoW6AO.js.gz +0 -0
- package/dist/standalone/assets/{user-directory-ZxAjN_q9.js.map → user-directory-9COoW6AO.js.map} +1 -1
- package/dist/standalone/assets/{value-format-Jmqe1qUg.js → value-format-CPnbnlE6.js} +2 -2
- package/dist/standalone/assets/value-format-CPnbnlE6.js.br +0 -0
- package/dist/standalone/assets/value-format-CPnbnlE6.js.gz +0 -0
- package/dist/standalone/assets/{value-format-Jmqe1qUg.js.map → value-format-CPnbnlE6.js.map} +1 -1
- package/dist/standalone/assets/wand-sparkles-DWaFQeYS.js +2 -0
- package/dist/standalone/assets/wand-sparkles-DWaFQeYS.js.map +1 -0
- package/dist/standalone/assets/wizard-create-page-CFwMs8E3.js +2 -0
- package/dist/standalone/assets/wizard-create-page-CFwMs8E3.js.br +0 -0
- package/dist/standalone/assets/wizard-create-page-CFwMs8E3.js.gz +0 -0
- package/dist/standalone/assets/{wizard-create-page-Bvgp93cM.js.map → wizard-create-page-CFwMs8E3.js.map} +1 -1
- package/dist/standalone/assets/zap-b3saQVKc.js +2 -0
- package/dist/standalone/assets/zap-b3saQVKc.js.map +1 -0
- package/dist/standalone/assets/{zod-BE6onVrX.js → zod-BbfEBA4A.js} +2 -2
- package/dist/standalone/assets/zod-BbfEBA4A.js.br +0 -0
- package/dist/standalone/assets/zod-BbfEBA4A.js.gz +0 -0
- package/dist/standalone/assets/{zod-BE6onVrX.js.map → zod-BbfEBA4A.js.map} +1 -1
- package/dist/standalone/index.html +8 -8
- package/dist/standalone/index.html.br +0 -0
- package/dist/standalone/index.html.gz +0 -0
- package/package.json +5 -5
- package/dist/standalone/assets/ai-assistant-widget-DU9YZkvm.js.br +0 -0
- package/dist/standalone/assets/ai-assistant-widget-DU9YZkvm.js.gz +0 -0
- package/dist/standalone/assets/audit-log-page-8Gv2dmY7.js +0 -2
- package/dist/standalone/assets/audit-log-page-8Gv2dmY7.js.br +0 -0
- package/dist/standalone/assets/audit-log-page-8Gv2dmY7.js.gz +0 -0
- package/dist/standalone/assets/calendar-BObEBLfG.js.br +0 -0
- package/dist/standalone/assets/calendar-BObEBLfG.js.gz +0 -0
- package/dist/standalone/assets/chart-widget-BWFpFuqE.js +0 -2
- package/dist/standalone/assets/chart-widget-BWFpFuqE.js.br +0 -0
- package/dist/standalone/assets/chart-widget-BWFpFuqE.js.gz +0 -0
- package/dist/standalone/assets/command-BXuvMfZb.js.br +0 -0
- package/dist/standalone/assets/command-BXuvMfZb.js.gz +0 -0
- package/dist/standalone/assets/date-picker-r8u06XBh.js.br +0 -0
- package/dist/standalone/assets/date-picker-r8u06XBh.js.gz +0 -0
- package/dist/standalone/assets/dist-CvKz-wgE.js.br +0 -0
- package/dist/standalone/assets/dist-CvKz-wgE.js.gz +0 -0
- package/dist/standalone/assets/dist-CvKz-wgE.js.map +0 -1
- package/dist/standalone/assets/dist-Dkym1-ts.js.br +0 -0
- package/dist/standalone/assets/dist-Dkym1-ts.js.gz +0 -0
- package/dist/standalone/assets/edit-page-BmisHwux.js +0 -2
- package/dist/standalone/assets/edit-page-BmisHwux.js.br +0 -0
- package/dist/standalone/assets/edit-page-BmisHwux.js.gz +0 -0
- package/dist/standalone/assets/edit-page-BmisHwux.js.map +0 -1
- package/dist/standalone/assets/empty-Ccn1VX37.js.br +0 -0
- package/dist/standalone/assets/empty-Ccn1VX37.js.gz +0 -0
- package/dist/standalone/assets/global-search-dialog-DdRt4k5C.js +0 -2
- package/dist/standalone/assets/global-search-dialog-DdRt4k5C.js.br +0 -0
- package/dist/standalone/assets/global-search-dialog-DdRt4k5C.js.gz +0 -0
- package/dist/standalone/assets/heavy-fields-CVzRBLt9.js.br +0 -0
- package/dist/standalone/assets/heavy-fields-CVzRBLt9.js.gz +0 -0
- package/dist/standalone/assets/home-page-DyNb5GLu.js +0 -3
- package/dist/standalone/assets/home-page-DyNb5GLu.js.br +0 -0
- package/dist/standalone/assets/home-page-DyNb5GLu.js.gz +0 -0
- package/dist/standalone/assets/icon-registry-FPXh-kNm.js +0 -2
- package/dist/standalone/assets/icon-registry-FPXh-kNm.js.br +0 -0
- package/dist/standalone/assets/icon-registry-FPXh-kNm.js.gz +0 -0
- package/dist/standalone/assets/icon-registry-FPXh-kNm.js.map +0 -1
- package/dist/standalone/assets/index-CSV54Ic9.js +0 -15
- package/dist/standalone/assets/index-CSV54Ic9.js.br +0 -0
- package/dist/standalone/assets/index-CSV54Ic9.js.gz +0 -0
- package/dist/standalone/assets/index-CSV54Ic9.js.map +0 -1
- package/dist/standalone/assets/index-OvloY2cG.css.br +0 -0
- package/dist/standalone/assets/index-OvloY2cG.css.gz +0 -0
- package/dist/standalone/assets/json-editor-D6vtFyYl.js +0 -2
- package/dist/standalone/assets/json-editor-D6vtFyYl.js.br +0 -0
- package/dist/standalone/assets/json-editor-D6vtFyYl.js.gz +0 -0
- package/dist/standalone/assets/property-renderer-BGU_or5z.js +0 -7
- package/dist/standalone/assets/property-renderer-BGU_or5z.js.br +0 -0
- package/dist/standalone/assets/property-renderer-BGU_or5z.js.gz +0 -0
- package/dist/standalone/assets/property-renderer-BGU_or5z.js.map +0 -1
- package/dist/standalone/assets/reference-Dfum6XNs.js +0 -2
- package/dist/standalone/assets/reference-Dfum6XNs.js.br +0 -0
- package/dist/standalone/assets/reference-Dfum6XNs.js.gz +0 -0
- package/dist/standalone/assets/refresh-cw-B2G7AzZh.js +0 -2
- package/dist/standalone/assets/refresh-cw-B2G7AzZh.js.map +0 -1
- package/dist/standalone/assets/revisions-button-B1CRVduG.js +0 -2
- package/dist/standalone/assets/revisions-button-B1CRVduG.js.br +0 -0
- package/dist/standalone/assets/revisions-button-B1CRVduG.js.gz +0 -0
- package/dist/standalone/assets/router-DmBe_NWn.js +0 -186
- package/dist/standalone/assets/router-DmBe_NWn.js.br +0 -0
- package/dist/standalone/assets/router-DmBe_NWn.js.gz +0 -0
- package/dist/standalone/assets/router-DmBe_NWn.js.map +0 -1
- package/dist/standalone/assets/select-JdSGjgiW.js +0 -2
- package/dist/standalone/assets/select-JdSGjgiW.js.br +0 -0
- package/dist/standalone/assets/select-JdSGjgiW.js.gz +0 -0
- package/dist/standalone/assets/settings-page-7eRUjHFt.js +0 -2
- package/dist/standalone/assets/settings-page-7eRUjHFt.js.br +0 -0
- package/dist/standalone/assets/settings-page-7eRUjHFt.js.gz +0 -0
- package/dist/standalone/assets/show-page-CwO3Y0ej.js +0 -2
- package/dist/standalone/assets/show-page-CwO3Y0ej.js.br +0 -0
- package/dist/standalone/assets/show-page-CwO3Y0ej.js.gz +0 -0
- package/dist/standalone/assets/show-page-CwO3Y0ej.js.map +0 -1
- package/dist/standalone/assets/tabs-CfQ4jLnP.js.br +0 -0
- package/dist/standalone/assets/tabs-CfQ4jLnP.js.gz +0 -0
- package/dist/standalone/assets/useQueries-CX5Gh6HV.js.br +0 -0
- package/dist/standalone/assets/useQueries-CX5Gh6HV.js.gz +0 -0
- package/dist/standalone/assets/user-directory-ZxAjN_q9.js.br +0 -0
- package/dist/standalone/assets/user-directory-ZxAjN_q9.js.gz +0 -0
- package/dist/standalone/assets/value-format-Jmqe1qUg.js.br +0 -0
- package/dist/standalone/assets/value-format-Jmqe1qUg.js.gz +0 -0
- package/dist/standalone/assets/wand-sparkles-BDM69Lk9.js +0 -2
- package/dist/standalone/assets/wand-sparkles-BDM69Lk9.js.map +0 -1
- package/dist/standalone/assets/wizard-create-page-Bvgp93cM.js +0 -2
- package/dist/standalone/assets/wizard-create-page-Bvgp93cM.js.br +0 -0
- package/dist/standalone/assets/wizard-create-page-Bvgp93cM.js.gz +0 -0
- package/dist/standalone/assets/zap-Be2c7_cs.js.br +0 -0
- package/dist/standalone/assets/zap-Be2c7_cs.js.gz +0 -0
- package/dist/standalone/assets/zap-Be2c7_cs.js.map +0 -1
- package/dist/standalone/assets/zod-BE6onVrX.js.br +0 -0
- package/dist/standalone/assets/zod-BE6onVrX.js.gz +0 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as e,n as t}from"./createLucideIcon-CUopU_LC.js";import{S as n,g as r,s as i}from"./with-selector-NDLhu4dT.js";import{t as a}from"./circle-alert-0EyKeic4.js";import{t as o}from"./ellipsis-lEjcTxo0.js";import{t as s}from"./zap-b3saQVKc.js";import{s as c}from"./dist-Dpg8xy_r.js";import{B as l,D as u,K as d,R as f,U as p,et as m,it as h,n as g,z as _}from"./router-wFvtgo77.js";import{A as v,D as y,E as b,M as x,O as S,S as C,T as w,gt as T,i as E,j as D,k as O,lt as k,w as A}from"./index-t4woXGa-.js";var j=e(t(),1),M=n(),N=j.forwardRef((e,t)=>(0,M.jsx)(`nav`,{ref:t,"aria-label":`breadcrumb`,...e}));N.displayName=`Breadcrumb`;var P=j.forwardRef(({className:e,...t},n)=>(0,M.jsx)(`ol`,{ref:n,className:i(`flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5`,e),...t}));P.displayName=`BreadcrumbList`;var F=j.forwardRef(({className:e,...t},n)=>(0,M.jsx)(`li`,{ref:n,className:i(`inline-flex items-center gap-1.5`,e),...t}));F.displayName=`BreadcrumbItem`;var I=j.forwardRef(({asChild:e,className:t,...n},a)=>(0,M.jsx)(e?r:`a`,{ref:a,className:i(`transition-colors hover:text-foreground`,t),...n}));I.displayName=`BreadcrumbLink`;var L=j.forwardRef(({className:e,...t},n)=>(0,M.jsx)(`span`,{ref:n,role:`link`,"aria-disabled":`true`,"aria-current":`page`,className:i(`font-normal text-foreground`,e),...t}));L.displayName=`BreadcrumbPage`;var R=({children:e,className:t,...n})=>(0,M.jsx)(`li`,{role:`presentation`,"aria-hidden":`true`,className:i(`[&>svg]:size-3.5`,t),...n,children:e??(0,M.jsx)(T,{})});R.displayName=`BreadcrumbSeparator`;var z=({className:e,...t})=>(0,M.jsxs)(`span`,{role:`presentation`,"aria-hidden":`true`,className:i(`flex size-9 items-center justify-center`,e),...t,children:[(0,M.jsx)(o,{className:`size-4`}),(0,M.jsx)(`span`,{className:`sr-only`,children:`More`})]});z.displayName=`BreadcrumbEllipsis`;function B({items:e,className:t}){return e.length===0?null:(0,M.jsx)(N,{className:t,children:(0,M.jsx)(P,{children:e.map((t,n)=>{let r=n===e.length-1,i=(0,M.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[t.icon,(0,M.jsx)(`span`,{className:`truncate max-w-[8rem] sm:max-w-[16rem]`,children:t.label})]});return(0,M.jsxs)(j.Fragment,{children:[(0,M.jsx)(F,{children:r||!t.to?(0,M.jsx)(L,{children:i}):(0,M.jsx)(I,{asChild:!0,children:(0,M.jsx)(g,{to:t.to,children:i})})}),!r&&(0,M.jsx)(R,{})]},`${n}-${t.label}`)})})})}function V(e){return{label:e,to:{name:`home`},icon:(0,M.jsx)(k,{className:`size-3.5`})}}var H=(e,t)=>!t?.recordActions||t.recordActions.includes(e),U=(e,t)=>{if(!t?.recordActions)return e;let n=new Set(t.recordActions);return e.filter(e=>n.has(e.name))},W=e=>typeof e.custom?.label==`string`?e.custom.label:e.name,G=e=>{let t=[],n=new Map,r=(e,t,i)=>{if(i>=t.length)return e;let a=t[i],o=t.slice(0,i+1).map(e=>e.name).join(`>`),s=n.get(o);return s||(s={key:o,group:a,items:[]},n.set(o,s),e.push({kind:`group`,group:s})),r(s.items,t,i+1)};for(let n of e){let e=n.nesting??[];(e.length>0?r(t,e,0):t).push({kind:`action`,action:n})}return t},K=(e,t)=>e.map(e=>e.kind===`action`?(0,M.jsxs)(w,{onSelect:()=>t(e.action),children:[(0,M.jsx)(s,{className:`size-4`}),` `,W(e.action)]},e.action.name):(0,M.jsxs)(O,{children:[(0,M.jsx)(D,{children:e.group.group.name}),(0,M.jsx)(y,{children:(0,M.jsx)(v,{children:K(e.group.items,t)})})]},e.group.key));function q({actions:e,onAction:t}){let n=j.useMemo(()=>G(e),[e]);return n.length===0?null:(0,M.jsx)(M.Fragment,{children:K(n,t)})}function J({actions:e,onAction:t,t:n,trigger:r,menuLabel:i,align:a=`end`}){return j.useMemo(()=>G(e),[e]).length===0?null:(0,M.jsxs)(C,{children:[(0,M.jsx)(x,{asChild:!0,children:r??(0,M.jsxs)(c,{variant:`outline`,size:`sm`,children:[(0,M.jsx)(s,{className:`size-4`}),n(`common:actions`)]})}),(0,M.jsxs)(A,{align:a,children:[(0,M.jsx)(b,{children:i??n(`common:actions`)}),(0,M.jsx)(S,{}),(0,M.jsx)(q,{actions:e,onAction:t})]})]})}function Y(e,t){t&&e[t.type===`error`?`error`:t.type===`warning`?`warning`:t.type===`info`?`info`:`success`]({message:t.message})}function X({title:e,hint:t}){return(0,M.jsxs)(`div`,{role:`alert`,className:`flex items-start gap-3 rounded-lg border border-destructive/50 bg-destructive/10 p-4 dark:bg-destructive/15`,children:[(0,M.jsx)(a,{className:`mt-0.5 size-5 shrink-0 text-destructive`}),(0,M.jsxs)(`div`,{className:`space-y-1 text-sm`,children:[(0,M.jsx)(`p`,{className:`font-semibold text-destructive`,children:e}),t&&(0,M.jsx)(`p`,{className:`text-destructive/90`,children:t})]})]})}function Z({resourceId:e,actionName:t,recordId:n,recordIds:r,onClose:i,onSuccess:a}){let o=d(e),{components:s}=h(),{t:c}=m(),g=E(),v=o?.actions?.find(e=>e.name===t),y=v?.component??null,b=y?s?.get(y):void 0,x=u(e,t,{...n===void 0?{}:{recordId:n},...r===void 0?{}:{recordIds:r},enabled:!!v&&!!b}),S=p(e,n),C=_(e),w=l(e),T=f(e),D=C.isPending||w.isPending||T.isPending,O=j.useCallback(async(e={})=>{let i=n?await C.mutateAsync({recordId:n,actionName:t,payload:e}):r?.length?await T.mutateAsync({actionName:t,ids:r,payload:e}):await w.mutateAsync({actionName:t,payload:e});return Y(g,i.notice),a?.(),i},[n,r,t,C,T,w,g,a]);return o?v?!y||!b?(0,M.jsx)(X,{title:c(`action:componentMissing`,{component:y??t}),hint:c(`action:componentMissingHint`)}):x.isError?(0,M.jsx)(X,{title:c(`action:loadFailed`),hint:x.error instanceof Error?x.error.message:void 0}):(0,M.jsx)(b,{action:v,resource:o,resourceId:e,...n===void 0?{}:{recordId:n},...r===void 0?{}:{recordIds:r},...S.data?.record?{record:S.data.record}:{},...x.data?.records?{records:x.data.records}:{},...x.data?{data:x.data}:{},loading:x.isLoading||!!n&&S.isLoading,invoke:O,submitting:D,close:i}):(0,M.jsx)(X,{title:c(`action:notFound`,{action:t})}):(0,M.jsx)(`p`,{className:`text-muted-foreground`,children:c(`common:loading`)})}export{W as a,B as c,q as i,V as l,Y as n,H as o,J as r,U as s,Z as t};
|
|
2
|
+
//# sourceMappingURL=action-component-host-CXIbN-8V.js.map
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-component-host-CXIbN-8V.js","names":[],"sources":["../../../../ui/src/components/breadcrumb.tsx","../../../../react/src/breadcrumbs.tsx","../../../../react/src/action-menu.tsx","../../../../react/src/action-notice.ts","../../../../react/src/components/action-component-host.tsx"],"sourcesContent":["import * as React from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { ChevronRight, MoreHorizontal } from 'lucide-react'\nimport { cn } from '../lib/utils.js'\n\nexport const Breadcrumb = React.forwardRef<\n HTMLElement,\n React.ComponentPropsWithoutRef<'nav'>\n>((props, ref) => <nav ref={ref} aria-label=\"breadcrumb\" {...props} />)\nBreadcrumb.displayName = 'Breadcrumb'\n\nexport const BreadcrumbList = React.forwardRef<\n HTMLOListElement,\n React.ComponentPropsWithoutRef<'ol'>\n>(({ className, ...props }, ref) => (\n <ol\n ref={ref}\n className={cn(\n 'flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5',\n className,\n )}\n {...props}\n />\n))\nBreadcrumbList.displayName = 'BreadcrumbList'\n\nexport const BreadcrumbItem = React.forwardRef<\n HTMLLIElement,\n React.ComponentPropsWithoutRef<'li'>\n>(({ className, ...props }, ref) => (\n <li\n ref={ref}\n className={cn('inline-flex items-center gap-1.5', className)}\n {...props}\n />\n))\nBreadcrumbItem.displayName = 'BreadcrumbItem'\n\nexport const BreadcrumbLink = React.forwardRef<\n HTMLAnchorElement,\n React.ComponentPropsWithoutRef<'a'> & { asChild?: boolean }\n>(({ asChild, className, ...props }, ref) => {\n const Comp = asChild ? Slot : 'a'\n return (\n <Comp\n ref={ref}\n className={cn('transition-colors hover:text-foreground', className)}\n {...props}\n />\n )\n})\nBreadcrumbLink.displayName = 'BreadcrumbLink'\n\nexport const BreadcrumbPage = React.forwardRef<\n HTMLSpanElement,\n React.ComponentPropsWithoutRef<'span'>\n>(({ className, ...props }, ref) => (\n <span\n ref={ref}\n role=\"link\"\n aria-disabled=\"true\"\n aria-current=\"page\"\n className={cn('font-normal text-foreground', className)}\n {...props}\n />\n))\nBreadcrumbPage.displayName = 'BreadcrumbPage'\n\nexport const BreadcrumbSeparator = ({\n children,\n className,\n ...props\n}: React.ComponentPropsWithoutRef<'li'>): React.ReactElement => (\n <li\n role=\"presentation\"\n aria-hidden=\"true\"\n className={cn('[&>svg]:size-3.5', className)}\n {...props}\n >\n {children ?? <ChevronRight />}\n </li>\n)\nBreadcrumbSeparator.displayName = 'BreadcrumbSeparator'\n\nexport const BreadcrumbEllipsis = ({\n className,\n ...props\n}: React.ComponentPropsWithoutRef<'span'>): React.ReactElement => (\n <span\n role=\"presentation\"\n aria-hidden=\"true\"\n className={cn('flex size-9 items-center justify-center', className)}\n {...props}\n >\n <MoreHorizontal className=\"size-4\" />\n <span className=\"sr-only\">More</span>\n </span>\n)\nBreadcrumbEllipsis.displayName = 'BreadcrumbEllipsis'\n","// Page breadcrumb helper. Each page builds its own crumb chain (home →\n// resource → record → action) and hands it to <PageBreadcrumbs />, which\n// renders the shadcn primitives with separators, hash-router-aware Links\n// and a Home icon on the root crumb.\n\nimport * as React from 'react'\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from '@modern-admin/ui'\nimport { Home } from 'lucide-react'\nimport { Link } from './router.js'\nimport type { Route } from './router.js'\n\nexport interface BreadcrumbItemSpec {\n label: string\n /** When set, renders a hash-router link; otherwise the crumb is plain text. */\n to?: Route\n /** Optional leading icon. The home crumb gets one by default. */\n icon?: React.ReactNode\n}\n\nexport interface PageBreadcrumbsProps {\n items: BreadcrumbItemSpec[]\n className?: string\n}\n\nexport function PageBreadcrumbs({\n items,\n className,\n}: PageBreadcrumbsProps): React.ReactElement | null {\n if (items.length === 0) return null\n return (\n <Breadcrumb className={className}>\n <BreadcrumbList>\n {items.map((item, i) => {\n const isLast = i === items.length - 1\n const content = (\n <span className=\"inline-flex items-center gap-1.5\">\n {item.icon}\n <span className=\"truncate max-w-[8rem] sm:max-w-[16rem]\">{item.label}</span>\n </span>\n )\n return (\n <React.Fragment key={`${i}-${item.label}`}>\n <BreadcrumbItem>\n {isLast || !item.to ? (\n <BreadcrumbPage>{content}</BreadcrumbPage>\n ) : (\n <BreadcrumbLink asChild>\n <Link to={item.to}>{content}</Link>\n </BreadcrumbLink>\n )}\n </BreadcrumbItem>\n {!isLast && <BreadcrumbSeparator />}\n </React.Fragment>\n )\n })}\n </BreadcrumbList>\n </Breadcrumb>\n )\n}\n\n/** Default home crumb — used by every page; pass `homeLabel` to localize. */\nexport function homeCrumb(label: string): BreadcrumbItemSpec {\n return {\n label,\n to: { name: 'home' },\n icon: <Home className=\"size-3.5\" />,\n }\n}\n","import * as React from 'react'\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuPortal,\n DropdownMenuSeparator,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from '@modern-admin/ui'\nimport { MoreHorizontal, Zap } from 'lucide-react'\nimport type { ActionDescriptor, ActionGroup, RecordJSON } from './types.js'\n\ninterface ActionMenuGroupNode {\n key: string\n group: ActionGroup\n items: ActionMenuNode[]\n}\n\ntype ActionMenuNode =\n | { kind: 'action'; action: ActionDescriptor }\n | { kind: 'group'; group: ActionMenuGroupNode }\n\nexport interface ActionMenuProps {\n actions: ActionDescriptor[]\n onAction(action: ActionDescriptor): void\n t: (key: string, params?: Record<string, string | number>) => string\n trigger?: React.ReactElement\n menuLabel?: string\n align?: 'start' | 'center' | 'end'\n}\n\n/**\n * Whether a record-scoped action should be offered for a specific record.\n *\n * The server resolves `isVisible`/`isAccessible` per record and reports the\n * survivors in `RecordJSON.recordActions`. A record without that field made\n * it here outside the action pipeline (or from an older server) — that is\n * \"no opinion\", so everything stays visible rather than everything vanishing.\n */\nexport const isActionAllowedForRecord = (\n actionName: string,\n record: Pick<RecordJSON, 'recordActions'> | undefined,\n): boolean => !record?.recordActions || record.recordActions.includes(actionName)\n\n/** Narrow a resource's record actions down to the ones this record offers. */\nexport const visibleRecordActions = (\n actions: ActionDescriptor[],\n record: Pick<RecordJSON, 'recordActions'> | undefined,\n): ActionDescriptor[] => {\n if (!record?.recordActions) return actions\n const allowed = new Set(record.recordActions)\n return actions.filter((a) => allowed.has(a.name))\n}\n\n/** Display label for an action: the (already localized) `custom.label` set\n * by the metadata translator, falling back to the raw action name. */\nexport const getActionLabel = (action: ActionDescriptor): string =>\n typeof action.custom?.label === 'string' ? action.custom.label : action.name\n\nconst buildActionMenuTree = (actions: ActionDescriptor[]): ActionMenuNode[] => {\n const root: ActionMenuNode[] = []\n const groups = new Map<string, ActionMenuGroupNode>()\n\n const ensureGroup = (target: ActionMenuNode[], path: ActionGroup[], depth: number): ActionMenuNode[] => {\n if (depth >= path.length) return target\n const segment = path[depth]!\n const key = path\n .slice(0, depth + 1)\n .map((item) => item.name)\n .join('>')\n let group = groups.get(key)\n if (!group) {\n group = { key, group: segment, items: [] }\n groups.set(key, group)\n target.push({ kind: 'group', group })\n }\n return ensureGroup(group.items, path, depth + 1)\n }\n\n for (const action of actions) {\n const nesting = action.nesting ?? []\n const target = nesting.length > 0 ? ensureGroup(root, nesting, 0) : root\n target.push({ kind: 'action', action })\n }\n\n return root\n}\n\nconst renderNodes = (\n nodes: ActionMenuNode[],\n onAction: (action: ActionDescriptor) => void,\n): React.ReactNode =>\n nodes.map((node) => {\n if (node.kind === 'action') {\n return (\n <DropdownMenuItem\n key={node.action.name}\n onSelect={() => onAction(node.action)}\n >\n <Zap className=\"size-4\" /> {getActionLabel(node.action)}\n </DropdownMenuItem>\n )\n }\n return (\n <DropdownMenuSub key={node.group.key}>\n <DropdownMenuSubTrigger>\n {node.group.group.name}\n </DropdownMenuSubTrigger>\n <DropdownMenuPortal>\n <DropdownMenuSubContent>\n {renderNodes(node.group.items, onAction)}\n </DropdownMenuSubContent>\n </DropdownMenuPortal>\n </DropdownMenuSub>\n )\n })\n\nexport function ActionMenuItems({\n actions,\n onAction,\n}: {\n actions: ActionDescriptor[]\n onAction(action: ActionDescriptor): void\n}): React.ReactElement | null {\n const nodes = React.useMemo(() => buildActionMenuTree(actions), [actions])\n if (nodes.length === 0) return null\n return <>{renderNodes(nodes, onAction)}</>\n}\n\nexport function ActionMenu({\n actions,\n onAction,\n t,\n trigger,\n menuLabel,\n align = 'end',\n}: ActionMenuProps): React.ReactElement | null {\n const nodes = React.useMemo(() => buildActionMenuTree(actions), [actions])\n if (nodes.length === 0) return null\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n {trigger ?? (\n <Button variant=\"outline\" size=\"sm\">\n <Zap className=\"size-4\" />\n {t('common:actions')}\n </Button>\n )}\n </DropdownMenuTrigger>\n <DropdownMenuContent align={align}>\n <DropdownMenuLabel>{menuLabel ?? t('common:actions')}</DropdownMenuLabel>\n <DropdownMenuSeparator />\n <ActionMenuItems actions={actions} onAction={onAction} />\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\n\nexport function MoreActionsMenu({\n actions,\n onAction,\n t,\n menuLabel,\n}: Omit<ActionMenuProps, 'trigger' | 'align'>): React.ReactElement | null {\n if (actions.length === 0) return null\n return (\n <ActionMenu\n actions={actions}\n onAction={onAction}\n t={t}\n menuLabel={menuLabel}\n trigger={(\n <Button variant=\"ghost\" size=\"icon\" className=\"h-8 w-8\">\n <MoreHorizontal className=\"size-4\" />\n <span className=\"sr-only\">{t('common:openMenu')}</span>\n </Button>\n )}\n />\n )\n}\n","// Shared `notice` → toast plumbing for custom-action invocations.\n//\n// Every surface that fires a custom action (list toolbar, row menu, bulk\n// toolbar, show page, action component host) gets back the same\n// `CustomActionResponse` shape, so the mapping lives here rather than being\n// re-derived at each call site.\n\nimport type { useNotify } from './notify.js'\nimport type { CustomActionResponse } from './types.js'\n\ntype NotifyApi = ReturnType<typeof useNotify>\n\n/** Show a custom action's `notice` as the matching toast. Unrecognised\n * types fall back to a success toast; a missing notice is a no-op. */\nexport function showActionNotice(\n notify: NotifyApi,\n notice: CustomActionResponse['notice'],\n): void {\n if (!notice) return\n const type = notice.type === 'error' ? 'error'\n : notice.type === 'warning' ? 'warning'\n : notice.type === 'info' ? 'info'\n : 'success'\n notify[type]({ message: notice.message })\n}\n","// Runtime host for a custom action's UI component.\n//\n// An action declaring `component: 'MyForm'` (see `Action.component` in\n// @modern-admin/core) does not fire on click. Instead the operator lands\n// here: the named component is looked up on the ComponentLoader and rendered\n// with everything it needs to run the action — the priming `GET` response,\n// the record for record-scoped actions, and an `invoke(payload)` callback\n// that POSTs and surfaces the resulting `notice`.\n//\n// The host is presentation-neutral so the same code backs both surfaces:\n// the full `/resources/:id/actions/:name` page and the modal opened for\n// actions declaring `custom.showAs: 'dialog'`.\n\nimport * as React from 'react'\nimport { AlertCircle } from 'lucide-react'\nimport {\n useActionData,\n useInvokeBulkAction,\n useInvokeRecordAction,\n useInvokeResourceAction,\n useRecord,\n useResource,\n} from '../hooks.js'\nimport { useAdminContext } from '../provider.js'\nimport { useI18n } from '../i18n.js'\nimport { useNotify } from '../notify.js'\nimport { showActionNotice } from '../action-notice.js'\nimport type { ActionComponentProps, CustomActionResponse } from '../types.js'\n\nexport interface ActionComponentHostProps {\n resourceId: string\n actionName: string\n /** Set for record-scoped actions (`actionType: 'record'`). */\n recordId?: string\n /** Set for bulk-scoped actions (`actionType: 'bulk'`) — the selection. */\n recordIds?: string[]\n /** Dismiss the action — pop the page or close the dialog. */\n onClose(): void\n /** Fired after each successful `invoke()`. The bulk toolbar uses it to\n * clear its selection; in page mode the list has already unmounted, so\n * only dialog callers see it. */\n onSuccess?(): void\n}\n\nfunction HostError({ title, hint }: { title: string; hint?: string }): React.ReactElement {\n return (\n <div\n role=\"alert\"\n className=\"flex items-start gap-3 rounded-lg border border-destructive/50 bg-destructive/10 p-4 dark:bg-destructive/15\"\n >\n <AlertCircle className=\"mt-0.5 size-5 shrink-0 text-destructive\" />\n <div className=\"space-y-1 text-sm\">\n <p className=\"font-semibold text-destructive\">{title}</p>\n {hint && <p className=\"text-destructive/90\">{hint}</p>}\n </div>\n </div>\n )\n}\n\nexport function ActionComponentHost({\n resourceId,\n actionName,\n recordId,\n recordIds,\n onClose,\n onSuccess,\n}: ActionComponentHostProps): React.ReactElement {\n const resource = useResource(resourceId)\n const { components } = useAdminContext()\n const { t } = useI18n()\n const notify = useNotify()\n\n const action = resource?.actions?.find((a) => a.name === actionName)\n const componentName = action?.component ?? null\n const Custom = componentName ? components?.get(componentName) : undefined\n\n // Only prime once we know the action exists and its component resolved —\n // otherwise the page renders an error and the handler must not run.\n const primed = useActionData(resourceId, actionName, {\n ...(recordId !== undefined ? { recordId } : {}),\n ...(recordIds !== undefined ? { recordIds } : {}),\n enabled: Boolean(action) && Boolean(Custom),\n })\n const record = useRecord(resourceId, recordId)\n const invokeRecord = useInvokeRecordAction(resourceId)\n const invokeResource = useInvokeResourceAction(resourceId)\n const invokeBulk = useInvokeBulkAction(resourceId)\n\n const submitting = invokeRecord.isPending || invokeResource.isPending || invokeBulk.isPending\n const invoke = React.useCallback(\n async (payload: Record<string, unknown> = {}): Promise<CustomActionResponse> => {\n // Scope is decided by what the host was mounted with, not by the\n // action's declared `actionType` — a mismatch would build a request\n // the server can't route.\n const res = recordId\n ? await invokeRecord.mutateAsync({ recordId, actionName, payload })\n : recordIds?.length\n ? await invokeBulk.mutateAsync({ actionName, ids: recordIds, payload })\n : await invokeResource.mutateAsync({ actionName, payload })\n showActionNotice(notify, res.notice)\n onSuccess?.()\n return res\n },\n [recordId, recordIds, actionName, invokeRecord, invokeBulk, invokeResource, notify, onSuccess],\n )\n\n if (!resource) return <p className=\"text-muted-foreground\">{t('common:loading')}</p>\n if (!action) {\n return <HostError title={t('action:notFound', { action: actionName })} />\n }\n if (!componentName || !Custom) {\n return (\n <HostError\n title={t('action:componentMissing', { component: componentName ?? actionName })}\n hint={t('action:componentMissingHint')}\n />\n )\n }\n if (primed.isError) {\n return (\n <HostError\n title={t('action:loadFailed')}\n hint={primed.error instanceof Error ? primed.error.message : undefined}\n />\n )\n }\n\n const props: ActionComponentProps = {\n action,\n resource,\n resourceId,\n ...(recordId !== undefined ? { recordId } : {}),\n ...(recordIds !== undefined ? { recordIds } : {}),\n ...(record.data?.record ? { record: record.data.record } : {}),\n ...(primed.data?.records ? { records: primed.data.records } : {}),\n ...(primed.data ? { data: primed.data } : {}),\n loading: primed.isLoading || (Boolean(recordId) && record.isLoading),\n invoke,\n submitting,\n close: onClose,\n }\n return <Custom {...props} />\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as e,n as t}from"./createLucideIcon-CUopU_LC.js";import{S as n}from"./with-selector-NDLhu4dT.js";import{t as r}from"./arrow-left-CI9hUPwJ.js";import{s as i}from"./dist-Dpg8xy_r.js";import{K as a,U as o,et as s,i as c}from"./router-wFvtgo77.js";import{a as l,c as u,l as d,t as f}from"./action-component-host-CXIbN-8V.js";import{a as p,i as m,n as h,t as g}from"./card-4cS4uWCP.js";var _=e(t(),1),v=n();function y({resourceId:e,actionName:t,recordId:n,recordIds:y}){let b=a(e),x=o(e,n),{t:S}=s(),C=c(),w=b?.actions?.find(e=>e.name===t),T=w?l(w):t,E=_.useCallback(()=>{C(n?{name:`show`,resourceId:e,recordId:n}:{name:`list`,resourceId:e})},[C,e,n]),D=x.data?.record?.title||n;return(0,v.jsxs)(`div`,{className:`space-y-2 sm:space-y-4`,children:[(0,v.jsx)(u,{items:[d(S(`common:home`)),{label:b?.name??e,to:{name:`list`,resourceId:e}},...n?[{label:D??n,to:{name:`show`,resourceId:e,recordId:n}}]:[],{label:T}]}),(0,v.jsxs)(g,{children:[(0,v.jsxs)(m,{className:`flex flex-row items-center justify-between gap-3`,children:[(0,v.jsx)(p,{className:`truncate`,children:T}),(0,v.jsxs)(i,{variant:`outline`,size:`sm`,onClick:E,className:`shrink-0`,children:[(0,v.jsx)(r,{className:`size-4`}),(0,v.jsx)(`span`,{className:`hidden sm:inline`,children:S(`common:back`)})]})]}),(0,v.jsx)(h,{children:(0,v.jsx)(f,{resourceId:e,actionName:t,...n===void 0?{}:{recordId:n},...y===void 0?{}:{recordIds:y},onClose:E})})]})]})}export{y as ResourceActionPage};
|
|
2
|
+
//# sourceMappingURL=action-page-OsWfKQ6C.js.map
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-page-OsWfKQ6C.js","names":[],"sources":["../../../../react/src/pages/action-page.tsx"],"sourcesContent":["// Full-page surface for a custom action that declares a `component`.\n//\n// Routed at `/resources/:resourceId/actions/:actionName` (resource-scoped)\n// and `/resources/:resourceId/:recordId/actions/:actionName` (record-scoped).\n// The page owns the chrome — breadcrumbs, title, back button — and delegates\n// the action itself to `<ActionComponentHost/>`, which is also what the\n// dialog presentation (`custom.showAs: 'dialog'`) renders.\n\nimport * as React from 'react'\nimport { Button, Card, CardContent, CardHeader, CardTitle } from '@modern-admin/ui'\nimport { ArrowLeft } from 'lucide-react'\nimport { useRecord, useResource } from '../hooks.js'\nimport { useI18n } from '../i18n.js'\nimport { useNavigate } from '../router.js'\nimport { PageBreadcrumbs, homeCrumb } from '../breadcrumbs.js'\nimport { getActionLabel } from '../action-menu.js'\nimport { ActionComponentHost } from '../components/action-component-host.js'\n\nexport interface ResourceActionPageProps {\n resourceId: string\n actionName: string\n /** Present for record-scoped actions. */\n recordId?: string\n /** Present for bulk-scoped actions — read from `?recordIds=a,b,c`. */\n recordIds?: string[]\n}\n\nexport function ResourceActionPage({\n resourceId,\n actionName,\n recordId,\n recordIds,\n}: ResourceActionPageProps): React.ReactElement {\n const resource = useResource(resourceId)\n const record = useRecord(resourceId, recordId)\n const { t } = useI18n()\n const navigate = useNavigate()\n\n const action = resource?.actions?.find((a) => a.name === actionName)\n const title = action ? getActionLabel(action) : actionName\n\n // Dismissing returns to wherever the action was launched from: the record\n // for record-scoped actions, the list for resource-scoped ones.\n const close = React.useCallback(() => {\n if (recordId) navigate({ name: 'show', resourceId, recordId })\n else navigate({ name: 'list', resourceId })\n }, [navigate, resourceId, recordId])\n\n const recordLabel = record.data?.record?.title || recordId\n\n return (\n <div className=\"space-y-2 sm:space-y-4\">\n <PageBreadcrumbs\n items={[\n homeCrumb(t('common:home')),\n { label: resource?.name ?? resourceId, to: { name: 'list', resourceId } },\n ...(recordId\n ? [{ label: recordLabel ?? recordId, to: { name: 'show' as const, resourceId, recordId } }]\n : []),\n { label: title },\n ]}\n />\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between gap-3\">\n <CardTitle className=\"truncate\">{title}</CardTitle>\n <Button variant=\"outline\" size=\"sm\" onClick={close} className=\"shrink-0\">\n <ArrowLeft className=\"size-4\" />\n <span className=\"hidden sm:inline\">{t('common:back')}</span>\n </Button>\n </CardHeader>\n <CardContent>\n <ActionComponentHost\n resourceId={resourceId}\n actionName={actionName}\n {...(recordId !== undefined ? { recordId } : {})}\n {...(recordIds !== undefined ? { recordIds } : {})}\n onClose={close}\n />\n </CardContent>\n </Card>\n </div>\n )\n}\n"],"mappings":"2ZA2BA,SAAgB,EAAmB,CACjC,aACA,aACA,WACA,aAC8C,CAC9C,IAAM,EAAW,EAAY,CAAU,EACjC,EAAS,EAAU,EAAY,CAAQ,EACvC,CAAE,KAAM,EAAQ,EAChB,EAAW,EAAY,EAEvB,EAAS,GAAU,SAAS,KAAM,GAAM,EAAE,OAAS,CAAU,EAC7D,EAAQ,EAAS,EAAe,CAAM,EAAI,EAI1C,EAAA,EAAc,gBAAkB,CACtB,EAAV,EAAmB,CAAE,KAAM,OAAQ,aAAY,UAAS,EAC9C,CAAE,KAAM,OAAQ,YAAW,CAAC,CAC5C,EAAG,CAAC,EAAU,EAAY,CAAQ,CAAC,EAE7B,EAAc,EAAO,MAAM,QAAQ,OAAS,EAElD,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,kCAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,CACL,EAAU,EAAE,aAAa,CAAC,EAC1B,CAAE,MAAO,GAAU,MAAQ,EAAY,GAAI,CAAE,KAAM,OAAQ,YAAW,CAAE,EACxE,GAAI,EACA,CAAC,CAAE,MAAO,GAAe,EAAU,GAAI,CAAE,KAAM,OAAiB,aAAY,UAAS,CAAE,CAAC,EACxF,CAAC,EACL,CAAE,MAAO,CAAM,CACjB,CACD,CAAA,GACD,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAY,UAAU,4DAAtB,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,oBAAY,CAAiB,CAAA,GAClD,EAAA,EAAA,KAAA,CAAC,EAAD,CAAQ,QAAQ,UAAU,KAAK,KAAK,QAAS,EAAO,UAAU,oBAA9D,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,QAAU,CAAA,GAC/B,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,4BAAoB,EAAE,aAAa,CAAQ,CAAA,CACrD,GACE,KACZ,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,UACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACc,aACA,aACZ,GAAK,IAAa,IAAA,GAA2B,CAAC,EAAhB,CAAE,UAAS,EACzC,GAAK,IAAc,IAAA,GAA4B,CAAC,EAAjB,CAAE,WAAU,EAC3C,QAAS,CACV,CAAA,CACU,CAAA,CACT,CAAA,CAAA,CACH,GAET"}
|
package/dist/standalone/assets/{ai-assistant-widget-DU9YZkvm.js → ai-assistant-widget-Bt4Z7Fmr.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,n as t}from"./createLucideIcon-CUopU_LC.js";import{S as n}from"./with-selector-NDLhu4dT.js";import{t as r}from"./bot-DFDgGfNj.js";import{n as ee,t as te}from"./send-D4KHQGYj.js";import{t as i}from"./plus-Dk-FzitW.js";import{t as a}from"./x-C3kLunD6.js";import{s as o}from"./dist-Dpg8xy_r.js";import{t as s}from"./textarea-CX_0QVSz.js";import{$ as c,P as l,at as u,i as d,it as f,mt as p,nt as m,r as h}from"./router-DmBe_NWn.js";import{t as g}from"./badge-6nyM5Jft.js";import{n as ne,t as re}from"./card-4cS4uWCP.js";import{t as ie}from"./richtext-render-DnVcQ34I.js";import{t as _}from"./uuid-DLSnbsz2.js";import{n as ae}from"./use-dashboard-charts-Cr3OUSL5.js";import{E as oe,M as se,O as ce,S as le,T as v,U as ue,Z as y,at as de,c as b,d as x,f as S,i as fe,l as pe,lt as me,s as he,u as ge,w as _e}from"./index-CSV54Ic9.js";var C=e(t(),1),w=n(),T=()=>_(),E=5,D=(e,t)=>{let n=(Array.isArray(e.input?.messages)?e.input.messages:[]).map((t,n)=>({id:`${e.id}-input-${n}`,role:t.role,content:t.content}));if(e.output){let r=String(e.output.text??``).trim();n.push({id:`task-${e.id}`,role:`assistant`,content:r||t,citations:Array.isArray(e.output.citations)?e.output.citations:void 0})}return n};function O(){let e=m(),t=p(),n=fe(),_=d(),O=h(),{locale:k,t:A}=c(),[j,M]=C.useState(!1),[N,P]=C.useState(``),[F,I]=C.useState([]),[L,R]=C.useState(()=>T()),[z,B]=C.useState(null),[V,H]=C.useState([]),U=l().aiAssistant,W=u({queryKey:[`modern-admin`,`ai-assistant`,`settings`],queryFn:()=>e.getAiAssistantSettings(),enabled:U}),G=f({mutationFn:async t=>{let n=typeof window<`u`?window.location.pathname:void 0;return n&&O&&(n===O?n=`/`:n.startsWith(`${O}/`)&&(n=n.slice(O.length))),e.sendAiAssistantChat(t.messages,t.requestId,k,t.conversationId,n?{pathname:n}:void 0)},onSuccess:e=>{B(e.taskId),t.invalidateQueries({queryKey:[`modern-admin`,`ai-assistant`,`chats`]})},onError:e=>{n.error({message:e instanceof Error?e.message:String(e)})}}),K=u({queryKey:[`modern-admin`,`ai-assistant`,`chats`],queryFn:()=>e.listAiAssistantChats(),enabled:U&&j&&W.data?.configured===!0}),q=u({queryKey:[`modern-admin`,`ai-assistant`,`task`,z],queryFn:()=>e.getAiAssistantTask(z),enabled:!!z,refetchInterval:e=>{let t=e.state.data?.status;return t===`pending`||t===`running`?1200:!1}});C.useEffect(()=>{let e=q.data;if(!(!e||!z)){if(e.status===`succeeded`&&e.output!=null){I(t=>{if(t.some(t=>t.id===`task-${e.id}`))return t;let n=String(e.output?.text??``).trim();return[...t,{id:`task-${e.id}`,role:`assistant`,content:n||A(`aiAssistant:noText`),citations:Array.isArray(e.output?.citations)?e.output.citations:void 0}]}),B(null),t.invalidateQueries({queryKey:[`modern-admin`,`ai-assistant`,`chats`]});let n=Array.isArray(e.output?.uiActions)?e.output.uiActions:[];for(let e of n){if(e.kind===`refresh`&&e.target===`dashboard`){ae();continue}e.kind===`navigate`&&(M(!1),_(e.route))}return}(e.status===`failed`||e.status===`cancelled`)&&(n.error({message:e.error??A(`aiAssistant:taskFailed`)}),B(null))}},[z,_,n,t,q.data,A]);let J=C.useCallback(e=>{let t={id:T(),role:`user`,content:e},n=[...F,t];I(n),G.mutate({requestId:t.id,conversationId:L,messages:n.map(e=>({role:e.role,content:e.content}))})},[G,L,F]),ve=C.useCallback(()=>{R(T()),I([]),P(``),H([]),B(null)},[]),ye=C.useCallback(async t=>{try{let n=await e.getAiAssistantTask(t.taskId);R(t.conversationId),I(D(n,A(`aiAssistant:noText`))),H([]),P(``),B(n.status===`pending`||n.status===`running`?n.id:null)}catch(e){n.error({message:e instanceof Error?e.message:String(e)})}},[e,n,A]);if(C.useEffect(()=>{if(z!==null||G.isPending)return;let e=V[0];e&&(H(e=>e.slice(1)),J(e.content))},[z,G.isPending,V,J]),!U||W.isLoading||W.error||!W.data?.enabled||!W.data.canChat)return null;let Y=G.isPending||z!=null,X=V.length>=E,Z=()=>{let e=N.trim();if(e){if(Y){if(X)return;H(t=>[...t,{id:T(),content:e}]),P(``);return}P(``),J(e)}},Q=W.data.configured,be=Y||q.data?.status===`running`||q.data?.status===`pending`,$=typeof q.data?.progress==`number`?q.data.progress:null,xe=N.trim().length===0||Y&&X;return(0,w.jsxs)(w.Fragment,{children:[(0,w.jsx)(`div`,{className:`fixed bottom-4 right-4 z-40`,children:(0,w.jsxs)(o,{onClick:()=>M(!0),"aria-label":A(`aiAssistant:fab.label`),className:`group h-10 min-w-10 max-w-10 rounded-full pl-3 pr-3 shadow-lg justify-end gap-0 overflow-hidden opacity-70 hover:opacity-100 transition-[max-width,padding-left,opacity] duration-200 ease-in-out hover:max-w-36 hover:pl-4`,children:[(0,w.jsx)(`span`,{className:`max-w-0 overflow-hidden whitespace-nowrap text-sm font-medium transition-[max-width,padding-right] duration-200 ease-in-out group-hover:max-w-[5rem] group-hover:pr-2`,children:A(`aiAssistant:fab.short`)}),(0,w.jsx)(ee,{className:`size-4 shrink-0`})]})}),(0,w.jsx)(he,{open:j,onOpenChange:M,children:(0,w.jsxs)(pe,{hideCloseButton:!0,className:`flex w-full flex-col gap-0 sm:max-w-xl`,children:[(0,w.jsx)(x,{className:`border-b border-border pb-4`,children:(0,w.jsxs)(`div`,{className:`flex items-start gap-3`,children:[(0,w.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,w.jsxs)(S,{className:`flex items-center gap-2`,children:[(0,w.jsx)(r,{className:`size-5`}),A(`aiAssistant:title`)]}),(0,w.jsx)(ge,{children:A(`aiAssistant:description`)})]}),(0,w.jsxs)(`div`,{className:`flex shrink-0 items-center gap-0.5`,children:[Q&&(0,w.jsxs)(w.Fragment,{children:[(0,w.jsxs)(le,{children:[(0,w.jsx)(se,{asChild:!0,children:(0,w.jsx)(o,{type:`button`,variant:`ghost`,size:`icon`,"aria-label":A(`aiAssistant:history`),children:(0,w.jsx)(me,{className:`size-4`})})}),(0,w.jsxs)(_e,{align:`end`,className:`w-72`,children:[(0,w.jsx)(oe,{children:A(`aiAssistant:history`)}),(0,w.jsx)(ce,{}),K.isLoading&&(0,w.jsx)(v,{disabled:!0,children:A(`common:loading`)}),!K.isLoading&&(K.data?.length??0)===0&&(0,w.jsx)(v,{disabled:!0,children:A(`aiAssistant:history.empty`)}),K.data?.map(e=>(0,w.jsxs)(v,{className:`flex-col items-start gap-0 py-2`,onSelect:()=>{ye(e)},children:[(0,w.jsx)(`span`,{className:`line-clamp-1 w-full text-sm font-medium`,children:e.title}),(0,w.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:new Intl.DateTimeFormat(k,{dateStyle:`short`,timeStyle:`short`}).format(new Date(e.updatedAt))})]},e.conversationId))]})]}),(0,w.jsx)(o,{type:`button`,variant:`ghost`,size:`icon`,onClick:ve,"aria-label":A(`aiAssistant:newChat`),children:(0,w.jsx)(i,{className:`size-4`})})]}),(0,w.jsx)(b,{asChild:!0,children:(0,w.jsx)(o,{type:`button`,variant:`ghost`,size:`icon`,"aria-label":A(`common:close`),children:(0,w.jsx)(a,{className:`size-4`})})})]})]})}),Q?(0,w.jsxs)(w.Fragment,{children:[(0,w.jsx)(ue,{className:`flex-1 px-4 py-4`,children:(0,w.jsxs)(`div`,{className:`space-y-3`,children:[F.length===0&&(0,w.jsx)(re,{children:(0,w.jsxs)(ne,{className:`space-y-2 p-4 text-sm text-muted-foreground`,children:[(0,w.jsx)(`div`,{className:`font-medium text-foreground`,children:A(`aiAssistant:tryAsking`)}),(0,w.jsxs)(`div`,{children:[`- `,A(`aiAssistant:tryAsking.example1`)]}),(0,w.jsxs)(`div`,{children:[`- `,A(`aiAssistant:tryAsking.example2`)]}),(0,w.jsxs)(`div`,{children:[`- `,A(`aiAssistant:tryAsking.example3`)]})]})}),F.map(e=>(0,w.jsx)(`div`,{className:e.role===`user`?`flex justify-end`:`flex justify-start`,children:(0,w.jsxs)(`div`,{className:e.role===`user`?`max-w-[85%] rounded-2xl bg-primary px-4 py-3 text-sm text-primary-foreground`:`max-w-[85%] rounded-2xl border border-border bg-card px-4 py-3 text-sm`,children:[e.role===`assistant`?(0,w.jsx)(ie,{value:e.content,format:`markdown`,className:`text-sm [&_pre]:overflow-x-auto [&_pre]:text-xs`}):(0,w.jsx)(`div`,{className:`whitespace-pre-wrap`,children:e.content}),e.citations&&e.citations.length>0&&(0,w.jsx)(`div`,{className:`mt-3 flex flex-wrap gap-2`,children:e.citations.slice(0,6).map((e,t)=>{let n=`${e.resourceId}${e.recordId?`#${e.recordId}`:``}`,r=`${e.resourceId}-${e.recordId??`resource`}-${t}`;return e.recordId?(0,w.jsx)(`button`,{type:`button`,className:`cursor-pointer`,onClick:()=>{M(!1),_({name:`show`,resourceId:e.resourceId,recordId:e.recordId})},children:(0,w.jsx)(g,{variant:`outline`,children:n})},r):(0,w.jsx)(`button`,{type:`button`,className:`cursor-pointer`,onClick:()=>{M(!1),_({name:`list`,resourceId:e.resourceId})},children:(0,w.jsx)(g,{variant:`outline`,children:n})},r)})})]})},e.id)),be&&(0,w.jsx)(`div`,{className:`flex justify-start`,children:(0,w.jsxs)(`div`,{className:`inline-flex items-center gap-2 rounded-2xl border border-border bg-card px-4 py-3 text-sm text-muted-foreground`,children:[(0,w.jsx)(de,{className:`size-4 animate-spin`}),$==null?A(`aiAssistant:thinking`):A(`aiAssistant:thinkingProgress`,{progress:$})]})})]})}),(0,w.jsxs)(`div`,{className:`border-t border-border bg-background/95 px-3 py-2`,children:[V.length>0&&(0,w.jsx)(`div`,{className:`mb-2 space-y-1`,children:V.map((e,t)=>(0,w.jsxs)(`div`,{className:`flex items-center gap-2 rounded-md bg-muted/50 px-2 py-1 text-sm`,children:[(0,w.jsxs)(`span`,{className:`shrink-0 tabular-nums text-xs text-muted-foreground`,children:[`(`,t+1,`)`]}),(0,w.jsx)(`span`,{className:`flex-1 truncate`,title:e.content,children:e.content}),(0,w.jsx)(o,{type:`button`,variant:`ghost`,size:`icon`,className:`size-6 shrink-0`,onClick:()=>H(t=>t.filter(t=>t.id!==e.id)),"aria-label":A(`aiAssistant:queue.cancel`),children:(0,w.jsx)(a,{className:`size-3.5`})})]},e.id))}),(0,w.jsxs)(`form`,{onSubmit:e=>{e.preventDefault(),Z()},children:[(0,w.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,w.jsx)(s,{value:N,onChange:e=>P(e.target.value),onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&!e.nativeEvent.isComposing&&(e.preventDefault(),Z())},rows:1,placeholder:A(`aiAssistant:input.placeholder`),"aria-label":A(`aiAssistant:input.placeholder`),className:`flex-1 max-h-[10rem] min-h-0 resize-none border-0 bg-transparent px-1 py-2 text-sm shadow-none outline-none [field-sizing:content] focus-visible:ring-0 focus-visible:ring-offset-0`}),(0,w.jsx)(o,{type:`submit`,disabled:xe,"aria-label":A(`aiAssistant:send`),className:`size-8 shrink-0 rounded-full p-0`,children:(0,w.jsx)(te,{className:`size-4`})})]}),(0,w.jsx)(`p`,{className:`px-1 pb-1 text-xs text-muted-foreground`,children:A(`aiAssistant:input.hint`)})]})]})]}):(0,w.jsxs)(`div`,{className:`flex flex-1 flex-col items-center justify-center gap-4 px-4 text-center`,children:[(0,w.jsxs)(`div`,{className:`space-y-2`,children:[(0,w.jsx)(`div`,{className:`text-lg font-semibold`,children:A(`aiAssistant:notConfigured.title`)}),(0,w.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:A(`aiAssistant:notConfigured.description`)})]}),W.data.canManage&&(0,w.jsxs)(o,{variant:`outline`,onClick:()=>{M(!1),_({name:`settings`,section:`ai-assistant`})},children:[(0,w.jsx)(y,{className:`size-4`}),A(`aiAssistant:notConfigured.openSettings`)]})]})]})})]})}export{O as AiAssistantWidget};
|
|
2
|
-
//# sourceMappingURL=ai-assistant-widget-
|
|
1
|
+
import{a as e,n as t}from"./createLucideIcon-CUopU_LC.js";import{S as n}from"./with-selector-NDLhu4dT.js";import{t as r}from"./bot-DFDgGfNj.js";import{n as ee,t as te}from"./send-D4KHQGYj.js";import{t as i}from"./plus-Dk-FzitW.js";import{t as a}from"./x-C3kLunD6.js";import{s as o}from"./dist-Dpg8xy_r.js";import{t as s}from"./textarea-CX_0QVSz.js";import{F as c,at as l,et as u,ht as d,i as f,ot as p,r as m,rt as h}from"./router-wFvtgo77.js";import{t as g}from"./badge-6nyM5Jft.js";import{n as ne,t as re}from"./card-4cS4uWCP.js";import{t as ie}from"./richtext-render-DnVcQ34I.js";import{t as _}from"./uuid-DLSnbsz2.js";import{n as ae}from"./use-dashboard-charts-Cr3OUSL5.js";import{E as oe,M as se,O as ce,Q as le,S as ue,T as v,U as y,c as de,d as b,f as x,i as S,l as fe,ot as pe,s as me,u as he,ut as ge,w as _e}from"./index-t4woXGa-.js";var C=e(t(),1),w=n(),T=()=>_(),E=5,D=(e,t)=>{let n=(Array.isArray(e.input?.messages)?e.input.messages:[]).map((t,n)=>({id:`${e.id}-input-${n}`,role:t.role,content:t.content}));if(e.output){let r=String(e.output.text??``).trim();n.push({id:`task-${e.id}`,role:`assistant`,content:r||t,citations:Array.isArray(e.output.citations)?e.output.citations:void 0})}return n};function O(){let e=h(),t=d(),n=S(),_=f(),O=m(),{locale:k,t:A}=u(),[j,M]=C.useState(!1),[N,P]=C.useState(``),[F,I]=C.useState([]),[L,R]=C.useState(()=>T()),[z,B]=C.useState(null),[V,H]=C.useState([]),U=c().aiAssistant,W=p({queryKey:[`modern-admin`,`ai-assistant`,`settings`],queryFn:()=>e.getAiAssistantSettings(),enabled:U}),G=l({mutationFn:async t=>{let n=typeof window<`u`?window.location.pathname:void 0;return n&&O&&(n===O?n=`/`:n.startsWith(`${O}/`)&&(n=n.slice(O.length))),e.sendAiAssistantChat(t.messages,t.requestId,k,t.conversationId,n?{pathname:n}:void 0)},onSuccess:e=>{B(e.taskId),t.invalidateQueries({queryKey:[`modern-admin`,`ai-assistant`,`chats`]})},onError:e=>{n.error({message:e instanceof Error?e.message:String(e)})}}),K=p({queryKey:[`modern-admin`,`ai-assistant`,`chats`],queryFn:()=>e.listAiAssistantChats(),enabled:U&&j&&W.data?.configured===!0}),q=p({queryKey:[`modern-admin`,`ai-assistant`,`task`,z],queryFn:()=>e.getAiAssistantTask(z),enabled:!!z,refetchInterval:e=>{let t=e.state.data?.status;return t===`pending`||t===`running`?1200:!1}});C.useEffect(()=>{let e=q.data;if(!(!e||!z)){if(e.status===`succeeded`&&e.output!=null){I(t=>{if(t.some(t=>t.id===`task-${e.id}`))return t;let n=String(e.output?.text??``).trim();return[...t,{id:`task-${e.id}`,role:`assistant`,content:n||A(`aiAssistant:noText`),citations:Array.isArray(e.output?.citations)?e.output.citations:void 0}]}),B(null),t.invalidateQueries({queryKey:[`modern-admin`,`ai-assistant`,`chats`]});let n=Array.isArray(e.output?.uiActions)?e.output.uiActions:[];for(let e of n){if(e.kind===`refresh`&&e.target===`dashboard`){ae();continue}e.kind===`navigate`&&(M(!1),_(e.route))}return}(e.status===`failed`||e.status===`cancelled`)&&(n.error({message:e.error??A(`aiAssistant:taskFailed`)}),B(null))}},[z,_,n,t,q.data,A]);let J=C.useCallback(e=>{let t={id:T(),role:`user`,content:e},n=[...F,t];I(n),G.mutate({requestId:t.id,conversationId:L,messages:n.map(e=>({role:e.role,content:e.content}))})},[G,L,F]),ve=C.useCallback(()=>{R(T()),I([]),P(``),H([]),B(null)},[]),ye=C.useCallback(async t=>{try{let n=await e.getAiAssistantTask(t.taskId);R(t.conversationId),I(D(n,A(`aiAssistant:noText`))),H([]),P(``),B(n.status===`pending`||n.status===`running`?n.id:null)}catch(e){n.error({message:e instanceof Error?e.message:String(e)})}},[e,n,A]);if(C.useEffect(()=>{if(z!==null||G.isPending)return;let e=V[0];e&&(H(e=>e.slice(1)),J(e.content))},[z,G.isPending,V,J]),!U||W.isLoading||W.error||!W.data?.enabled||!W.data.canChat)return null;let Y=G.isPending||z!=null,X=V.length>=E,Z=()=>{let e=N.trim();if(e){if(Y){if(X)return;H(t=>[...t,{id:T(),content:e}]),P(``);return}P(``),J(e)}},Q=W.data.configured,be=Y||q.data?.status===`running`||q.data?.status===`pending`,$=typeof q.data?.progress==`number`?q.data.progress:null,xe=N.trim().length===0||Y&&X;return(0,w.jsxs)(w.Fragment,{children:[(0,w.jsx)(`div`,{className:`fixed bottom-4 right-4 z-40`,children:(0,w.jsxs)(o,{onClick:()=>M(!0),"aria-label":A(`aiAssistant:fab.label`),className:`group h-10 min-w-10 max-w-10 rounded-full pl-3 pr-3 shadow-lg justify-end gap-0 overflow-hidden opacity-70 hover:opacity-100 transition-[max-width,padding-left,opacity] duration-200 ease-in-out hover:max-w-36 hover:pl-4`,children:[(0,w.jsx)(`span`,{className:`max-w-0 overflow-hidden whitespace-nowrap text-sm font-medium transition-[max-width,padding-right] duration-200 ease-in-out group-hover:max-w-[5rem] group-hover:pr-2`,children:A(`aiAssistant:fab.short`)}),(0,w.jsx)(ee,{className:`size-4 shrink-0`})]})}),(0,w.jsx)(me,{open:j,onOpenChange:M,children:(0,w.jsxs)(fe,{hideCloseButton:!0,className:`flex w-full flex-col gap-0 sm:max-w-xl`,children:[(0,w.jsx)(b,{className:`border-b border-border pb-4`,children:(0,w.jsxs)(`div`,{className:`flex items-start gap-3`,children:[(0,w.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,w.jsxs)(x,{className:`flex items-center gap-2`,children:[(0,w.jsx)(r,{className:`size-5`}),A(`aiAssistant:title`)]}),(0,w.jsx)(he,{children:A(`aiAssistant:description`)})]}),(0,w.jsxs)(`div`,{className:`flex shrink-0 items-center gap-0.5`,children:[Q&&(0,w.jsxs)(w.Fragment,{children:[(0,w.jsxs)(ue,{children:[(0,w.jsx)(se,{asChild:!0,children:(0,w.jsx)(o,{type:`button`,variant:`ghost`,size:`icon`,"aria-label":A(`aiAssistant:history`),children:(0,w.jsx)(ge,{className:`size-4`})})}),(0,w.jsxs)(_e,{align:`end`,className:`w-72`,children:[(0,w.jsx)(oe,{children:A(`aiAssistant:history`)}),(0,w.jsx)(ce,{}),K.isLoading&&(0,w.jsx)(v,{disabled:!0,children:A(`common:loading`)}),!K.isLoading&&(K.data?.length??0)===0&&(0,w.jsx)(v,{disabled:!0,children:A(`aiAssistant:history.empty`)}),K.data?.map(e=>(0,w.jsxs)(v,{className:`flex-col items-start gap-0 py-2`,onSelect:()=>{ye(e)},children:[(0,w.jsx)(`span`,{className:`line-clamp-1 w-full text-sm font-medium`,children:e.title}),(0,w.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:new Intl.DateTimeFormat(k,{dateStyle:`short`,timeStyle:`short`}).format(new Date(e.updatedAt))})]},e.conversationId))]})]}),(0,w.jsx)(o,{type:`button`,variant:`ghost`,size:`icon`,onClick:ve,"aria-label":A(`aiAssistant:newChat`),children:(0,w.jsx)(i,{className:`size-4`})})]}),(0,w.jsx)(de,{asChild:!0,children:(0,w.jsx)(o,{type:`button`,variant:`ghost`,size:`icon`,"aria-label":A(`common:close`),children:(0,w.jsx)(a,{className:`size-4`})})})]})]})}),Q?(0,w.jsxs)(w.Fragment,{children:[(0,w.jsx)(y,{className:`flex-1 px-4 py-4`,children:(0,w.jsxs)(`div`,{className:`space-y-3`,children:[F.length===0&&(0,w.jsx)(re,{children:(0,w.jsxs)(ne,{className:`space-y-2 p-4 text-sm text-muted-foreground`,children:[(0,w.jsx)(`div`,{className:`font-medium text-foreground`,children:A(`aiAssistant:tryAsking`)}),(0,w.jsxs)(`div`,{children:[`- `,A(`aiAssistant:tryAsking.example1`)]}),(0,w.jsxs)(`div`,{children:[`- `,A(`aiAssistant:tryAsking.example2`)]}),(0,w.jsxs)(`div`,{children:[`- `,A(`aiAssistant:tryAsking.example3`)]})]})}),F.map(e=>(0,w.jsx)(`div`,{className:e.role===`user`?`flex justify-end`:`flex justify-start`,children:(0,w.jsxs)(`div`,{className:e.role===`user`?`max-w-[85%] rounded-2xl bg-primary px-4 py-3 text-sm text-primary-foreground`:`max-w-[85%] rounded-2xl border border-border bg-card px-4 py-3 text-sm`,children:[e.role===`assistant`?(0,w.jsx)(ie,{value:e.content,format:`markdown`,className:`text-sm [&_pre]:overflow-x-auto [&_pre]:text-xs`}):(0,w.jsx)(`div`,{className:`whitespace-pre-wrap`,children:e.content}),e.citations&&e.citations.length>0&&(0,w.jsx)(`div`,{className:`mt-3 flex flex-wrap gap-2`,children:e.citations.slice(0,6).map((e,t)=>{let n=`${e.resourceId}${e.recordId?`#${e.recordId}`:``}`,r=`${e.resourceId}-${e.recordId??`resource`}-${t}`;return e.recordId?(0,w.jsx)(`button`,{type:`button`,className:`cursor-pointer`,onClick:()=>{M(!1),_({name:`show`,resourceId:e.resourceId,recordId:e.recordId})},children:(0,w.jsx)(g,{variant:`outline`,children:n})},r):(0,w.jsx)(`button`,{type:`button`,className:`cursor-pointer`,onClick:()=>{M(!1),_({name:`list`,resourceId:e.resourceId})},children:(0,w.jsx)(g,{variant:`outline`,children:n})},r)})})]})},e.id)),be&&(0,w.jsx)(`div`,{className:`flex justify-start`,children:(0,w.jsxs)(`div`,{className:`inline-flex items-center gap-2 rounded-2xl border border-border bg-card px-4 py-3 text-sm text-muted-foreground`,children:[(0,w.jsx)(pe,{className:`size-4 animate-spin`}),$==null?A(`aiAssistant:thinking`):A(`aiAssistant:thinkingProgress`,{progress:$})]})})]})}),(0,w.jsxs)(`div`,{className:`border-t border-border bg-background/95 px-3 py-2`,children:[V.length>0&&(0,w.jsx)(`div`,{className:`mb-2 space-y-1`,children:V.map((e,t)=>(0,w.jsxs)(`div`,{className:`flex items-center gap-2 rounded-md bg-muted/50 px-2 py-1 text-sm`,children:[(0,w.jsxs)(`span`,{className:`shrink-0 tabular-nums text-xs text-muted-foreground`,children:[`(`,t+1,`)`]}),(0,w.jsx)(`span`,{className:`flex-1 truncate`,title:e.content,children:e.content}),(0,w.jsx)(o,{type:`button`,variant:`ghost`,size:`icon`,className:`size-6 shrink-0`,onClick:()=>H(t=>t.filter(t=>t.id!==e.id)),"aria-label":A(`aiAssistant:queue.cancel`),children:(0,w.jsx)(a,{className:`size-3.5`})})]},e.id))}),(0,w.jsxs)(`form`,{onSubmit:e=>{e.preventDefault(),Z()},children:[(0,w.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,w.jsx)(s,{value:N,onChange:e=>P(e.target.value),onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&!e.nativeEvent.isComposing&&(e.preventDefault(),Z())},rows:1,placeholder:A(`aiAssistant:input.placeholder`),"aria-label":A(`aiAssistant:input.placeholder`),className:`flex-1 max-h-[10rem] min-h-0 resize-none border-0 bg-transparent px-1 py-2 text-sm shadow-none outline-none [field-sizing:content] focus-visible:ring-0 focus-visible:ring-offset-0`}),(0,w.jsx)(o,{type:`submit`,disabled:xe,"aria-label":A(`aiAssistant:send`),className:`size-8 shrink-0 rounded-full p-0`,children:(0,w.jsx)(te,{className:`size-4`})})]}),(0,w.jsx)(`p`,{className:`px-1 pb-1 text-xs text-muted-foreground`,children:A(`aiAssistant:input.hint`)})]})]})]}):(0,w.jsxs)(`div`,{className:`flex flex-1 flex-col items-center justify-center gap-4 px-4 text-center`,children:[(0,w.jsxs)(`div`,{className:`space-y-2`,children:[(0,w.jsx)(`div`,{className:`text-lg font-semibold`,children:A(`aiAssistant:notConfigured.title`)}),(0,w.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:A(`aiAssistant:notConfigured.description`)})]}),W.data.canManage&&(0,w.jsxs)(o,{variant:`outline`,onClick:()=>{M(!1),_({name:`settings`,section:`ai-assistant`})},children:[(0,w.jsx)(le,{className:`size-4`}),A(`aiAssistant:notConfigured.openSettings`)]})]})]})})]})}export{O as AiAssistantWidget};
|
|
2
|
+
//# sourceMappingURL=ai-assistant-widget-Bt4Z7Fmr.js.map
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-assistant-widget-DU9YZkvm.js","names":[],"sources":["../../../../react/src/components/ai-assistant-widget.tsx"],"sourcesContent":["import * as React from 'react'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n RichtextRender,\n ScrollArea,\n Sheet,\n SheetClose,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n Textarea,\n} from '@modern-admin/ui'\nimport { Bot, History, Loader2, MessageSquare, Plus, Send, Settings, X } from 'lucide-react'\nimport { uuidv7 } from '@modern-admin/core'\nimport { useAdminClient } from '../provider.js'\nimport { useFeatures } from '../hooks.js'\nimport { useNotify } from '../notify.js'\nimport { useBasepath, useNavigate } from '../router.js'\nimport { useI18n } from '../i18n.js'\nimport type {\n AiAssistantChatHistoryItem,\n AiAssistantChatMessage,\n AiAssistantCitation,\n AiAssistantTask,\n AiUiAction,\n} from '../client.js'\nimport { emitDashboardReload } from '../use-dashboard-charts.js'\n\ninterface ChatItem {\n id: string\n role: 'user' | 'assistant'\n content: string\n citations?: AiAssistantCitation[]\n}\n\ninterface QueuedItem {\n id: string\n content: string\n}\n\nconst randomId = (): string => uuidv7()\n\nconst MAX_QUEUE = 5\n\nconst messagesFromTask = (task: AiAssistantTask, fallbackText: string): ChatItem[] => {\n const inputMessages = Array.isArray(task.input?.messages)\n ? task.input.messages as AiAssistantChatMessage[]\n : []\n const items: ChatItem[] = inputMessages.map((message, index) => ({\n id: `${task.id}-input-${index}`,\n role: message.role,\n content: message.content,\n }))\n if (task.output) {\n const text = String(task.output.text ?? '').trim()\n items.push({\n id: `task-${task.id}`,\n role: 'assistant',\n content: text || fallbackText,\n citations: Array.isArray(task.output.citations) ? task.output.citations : undefined,\n })\n }\n return items\n}\n\nexport function AiAssistantWidget(): React.ReactElement | null {\n const client = useAdminClient()\n const queryClient = useQueryClient()\n const notify = useNotify()\n const navigate = useNavigate()\n const basepath = useBasepath()\n const { locale, t } = useI18n()\n const [open, setOpen] = React.useState(false)\n const [input, setInput] = React.useState('')\n const [messages, setMessages] = React.useState<ChatItem[]>([])\n const [conversationId, setConversationId] = React.useState(() => randomId())\n const [activeTaskId, setActiveTaskId] = React.useState<string | null>(null)\n const [queue, setQueue] = React.useState<QueuedItem[]>([])\n\n // Capability gate: when the host hasn't wired `aiAssistant` in\n // `ModernAdminModule.forRoot`, the `/admin/api/ai-assistant/*`\n // controllers aren't even registered — issuing the settings query would\n // 404 every page load. Skip the query, the widget, and the chat sheet\n // entirely in that case.\n const features = useFeatures()\n const aiAvailable = features.aiAssistant\n\n const settings = useQuery({\n queryKey: ['modern-admin', 'ai-assistant', 'settings'],\n queryFn: () => client.getAiAssistantSettings(),\n enabled: aiAvailable,\n })\n\n const chat = useMutation({\n mutationFn: async (input: {\n requestId: string\n conversationId: string\n messages: AiAssistantChatMessage[]\n }) => {\n // Strip the admin's basepath so the backend receives a basepath-relative\n // path (e.g. `/resources/posts/123`, not `/admin/resources/posts/123`) —\n // the grounding prompt matches against the relative `/resources/...` form.\n // Boundary-aware: only strip a full segment match so basepath `/admin`\n // never mangles an unrelated path like `/administrators`.\n let pathname = typeof window !== 'undefined' ? window.location.pathname : undefined\n if (pathname && basepath) {\n if (pathname === basepath) {\n pathname = '/'\n } else if (pathname.startsWith(`${basepath}/`)) {\n pathname = pathname.slice(basepath.length)\n }\n }\n return client.sendAiAssistantChat(\n input.messages,\n input.requestId,\n locale,\n input.conversationId,\n pathname ? { pathname } : undefined,\n )\n },\n onSuccess: (response) => {\n setActiveTaskId(response.taskId)\n void queryClient.invalidateQueries({ queryKey: ['modern-admin', 'ai-assistant', 'chats'] })\n },\n onError: (err) => {\n notify.error({ message: err instanceof Error ? err.message : String(err) })\n },\n })\n\n const history = useQuery<AiAssistantChatHistoryItem[]>({\n queryKey: ['modern-admin', 'ai-assistant', 'chats'],\n queryFn: () => client.listAiAssistantChats(),\n enabled: aiAvailable && open && settings.data?.configured === true,\n })\n\n const task = useQuery<AiAssistantTask>({\n queryKey: ['modern-admin', 'ai-assistant', 'task', activeTaskId],\n queryFn: () => client.getAiAssistantTask(activeTaskId!),\n enabled: !!activeTaskId,\n refetchInterval: (query) => {\n const state = query.state.data?.status\n return state === 'pending' || state === 'running' ? 1200 : false\n },\n })\n\n React.useEffect(() => {\n const data = task.data\n if (!data || !activeTaskId) return\n if (data.status === 'succeeded' && data.output != null) {\n setMessages((prev) => {\n const alreadyExists = prev.some((item) => item.id === `task-${data.id}`)\n if (alreadyExists) return prev\n const text = String(data.output?.text ?? '').trim()\n return [\n ...prev,\n {\n id: `task-${data.id}`,\n role: 'assistant',\n content: text || t('aiAssistant:noText'),\n citations: Array.isArray(data.output?.citations) ? data.output.citations : undefined,\n },\n ]\n })\n setActiveTaskId(null)\n void queryClient.invalidateQueries({ queryKey: ['modern-admin', 'ai-assistant', 'chats'] })\n const uiActions = Array.isArray(data.output?.uiActions)\n ? (data.output.uiActions as AiUiAction[])\n : []\n for (const action of uiActions) {\n if (action.kind === 'refresh' && action.target === 'dashboard') {\n emitDashboardReload()\n continue\n }\n if (action.kind === 'navigate') {\n setOpen(false)\n navigate(action.route)\n }\n }\n return\n }\n if (data.status === 'failed' || data.status === 'cancelled') {\n notify.error({ message: data.error ?? t('aiAssistant:taskFailed') })\n setActiveTaskId(null)\n }\n }, [activeTaskId, navigate, notify, queryClient, task.data, t])\n\n // Send a user message immediately (assumes nothing is in flight).\n const sendChat = React.useCallback(\n (content: string): void => {\n const userMsg: ChatItem = { id: randomId(), role: 'user', content }\n const updated = [...messages, userMsg]\n setMessages(updated)\n chat.mutate({\n requestId: userMsg.id,\n conversationId,\n messages: updated.map((m) => ({ role: m.role, content: m.content })),\n })\n },\n [chat, conversationId, messages],\n )\n\n const startNewChat = React.useCallback((): void => {\n setConversationId(randomId())\n setMessages([])\n setInput('')\n setQueue([])\n setActiveTaskId(null)\n }, [])\n\n const selectChat = React.useCallback(\n async (item: AiAssistantChatHistoryItem): Promise<void> => {\n try {\n const selected = await client.getAiAssistantTask(item.taskId)\n setConversationId(item.conversationId)\n setMessages(messagesFromTask(selected, t('aiAssistant:noText')))\n setQueue([])\n setInput('')\n setActiveTaskId(\n selected.status === 'pending' || selected.status === 'running' ? selected.id : null,\n )\n } catch (err) {\n notify.error({ message: err instanceof Error ? err.message : String(err) })\n }\n },\n [client, notify, t],\n )\n\n // Auto-dequeue: when nothing is in flight and queue has items, send the head.\n React.useEffect(() => {\n if (activeTaskId !== null) return\n if (chat.isPending) return\n const next = queue[0]\n if (!next) return\n setQueue((q) => q.slice(1))\n sendChat(next.content)\n }, [activeTaskId, chat.isPending, queue, sendChat])\n\n if (!aiAvailable) return null\n if (settings.isLoading) return null\n if (settings.error) return null\n if (!settings.data?.enabled) return null\n if (!settings.data.canChat) return null\n\n const isProcessing = chat.isPending || activeTaskId != null\n const queueFull = queue.length >= MAX_QUEUE\n\n const submit = (): void => {\n const text = input.trim()\n if (!text) return\n if (isProcessing) {\n if (queueFull) return\n setQueue((q) => [...q, { id: randomId(), content: text }])\n setInput('')\n return\n }\n setInput('')\n sendChat(text)\n }\n\n const configured = settings.data.configured\n const isThinking =\n isProcessing ||\n task.data?.status === 'running' ||\n task.data?.status === 'pending'\n const progress = typeof task.data?.progress === 'number' ? task.data.progress : null\n const sendDisabled = input.trim().length === 0 || (isProcessing && queueFull)\n\n return (\n <>\n <div className=\"fixed bottom-4 right-4 z-40\">\n <Button\n onClick={() => setOpen(true)}\n aria-label={t('aiAssistant:fab.label')}\n className={\n 'group h-10 min-w-10 max-w-10 rounded-full pl-3 pr-3 shadow-lg ' +\n 'justify-end gap-0 overflow-hidden opacity-70 hover:opacity-100 ' +\n 'transition-[max-width,padding-left,opacity] duration-200 ease-in-out ' +\n 'hover:max-w-36 hover:pl-4'\n }\n >\n <span className=\"max-w-0 overflow-hidden whitespace-nowrap text-sm font-medium transition-[max-width,padding-right] duration-200 ease-in-out group-hover:max-w-[5rem] group-hover:pr-2\">\n {t('aiAssistant:fab.short')}\n </span>\n <MessageSquare className=\"size-4 shrink-0\" />\n </Button>\n </div>\n <Sheet open={open} onOpenChange={setOpen}>\n <SheetContent hideCloseButton className=\"flex w-full flex-col gap-0 sm:max-w-xl\">\n <SheetHeader className=\"border-b border-border pb-4\">\n <div className=\"flex items-start gap-3\">\n <div className=\"min-w-0 flex-1\">\n <SheetTitle className=\"flex items-center gap-2\">\n <Bot className=\"size-5\" />\n {t('aiAssistant:title')}\n </SheetTitle>\n <SheetDescription>{t('aiAssistant:description')}</SheetDescription>\n </div>\n <div className=\"flex shrink-0 items-center gap-0.5\">\n {configured && (\n <>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n aria-label={t('aiAssistant:history')}\n >\n <History className=\"size-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-72\">\n <DropdownMenuLabel>{t('aiAssistant:history')}</DropdownMenuLabel>\n <DropdownMenuSeparator />\n {history.isLoading && (\n <DropdownMenuItem disabled>{t('common:loading')}</DropdownMenuItem>\n )}\n {!history.isLoading && (history.data?.length ?? 0) === 0 && (\n <DropdownMenuItem disabled>{t('aiAssistant:history.empty')}</DropdownMenuItem>\n )}\n {history.data?.map((item) => (\n <DropdownMenuItem\n key={item.conversationId}\n className=\"flex-col items-start gap-0 py-2\"\n onSelect={() => {\n void selectChat(item)\n }}\n >\n <span className=\"line-clamp-1 w-full text-sm font-medium\">{item.title}</span>\n <span className=\"text-xs text-muted-foreground\">\n {new Intl.DateTimeFormat(locale, {\n dateStyle: 'short',\n timeStyle: 'short',\n }).format(new Date(item.updatedAt))}\n </span>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={startNewChat}\n aria-label={t('aiAssistant:newChat')}\n >\n <Plus className=\"size-4\" />\n </Button>\n </>\n )}\n <SheetClose asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n aria-label={t('common:close')}\n >\n <X className=\"size-4\" />\n </Button>\n </SheetClose>\n </div>\n </div>\n </SheetHeader>\n\n {!configured ? (\n <div className=\"flex flex-1 flex-col items-center justify-center gap-4 px-4 text-center\">\n <div className=\"space-y-2\">\n <div className=\"text-lg font-semibold\">\n {t('aiAssistant:notConfigured.title')}\n </div>\n <div className=\"text-sm text-muted-foreground\">\n {t('aiAssistant:notConfigured.description')}\n </div>\n </div>\n {settings.data.canManage && (\n <Button\n variant=\"outline\"\n onClick={() => {\n setOpen(false)\n navigate({ name: 'settings', section: 'ai-assistant' })\n }}\n >\n <Settings className=\"size-4\" />\n {t('aiAssistant:notConfigured.openSettings')}\n </Button>\n )}\n </div>\n ) : (\n <>\n <ScrollArea className=\"flex-1 px-4 py-4\">\n <div className=\"space-y-3\">\n {messages.length === 0 && (\n <Card>\n <CardContent className=\"space-y-2 p-4 text-sm text-muted-foreground\">\n <div className=\"font-medium text-foreground\">\n {t('aiAssistant:tryAsking')}\n </div>\n <div>- {t('aiAssistant:tryAsking.example1')}</div>\n <div>- {t('aiAssistant:tryAsking.example2')}</div>\n <div>- {t('aiAssistant:tryAsking.example3')}</div>\n </CardContent>\n </Card>\n )}\n {messages.map((message) => (\n <div\n key={message.id}\n className={message.role === 'user' ? 'flex justify-end' : 'flex justify-start'}\n >\n <div\n className={message.role === 'user'\n ? 'max-w-[85%] rounded-2xl bg-primary px-4 py-3 text-sm text-primary-foreground'\n : 'max-w-[85%] rounded-2xl border border-border bg-card px-4 py-3 text-sm'}\n >\n {message.role === 'assistant' ? (\n <RichtextRender\n value={message.content}\n format=\"markdown\"\n className=\"text-sm [&_pre]:overflow-x-auto [&_pre]:text-xs\"\n />\n ) : (\n <div className=\"whitespace-pre-wrap\">{message.content}</div>\n )}\n {message.citations && message.citations.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-2\">\n {message.citations.slice(0, 6).map((citation, index) => {\n const label = `${citation.resourceId}${citation.recordId ? `#${citation.recordId}` : ''}`\n const key = `${citation.resourceId}-${citation.recordId ?? 'resource'}-${index}`\n if (citation.recordId) {\n return (\n <button\n key={key}\n type=\"button\"\n className=\"cursor-pointer\"\n onClick={() => {\n setOpen(false)\n navigate({\n name: 'show',\n resourceId: citation.resourceId,\n recordId: citation.recordId!,\n })\n }}\n >\n <Badge variant=\"outline\">{label}</Badge>\n </button>\n )\n }\n return (\n <button\n key={key}\n type=\"button\"\n className=\"cursor-pointer\"\n onClick={() => {\n setOpen(false)\n navigate({ name: 'list', resourceId: citation.resourceId })\n }}\n >\n <Badge variant=\"outline\">{label}</Badge>\n </button>\n )\n })}\n </div>\n )}\n </div>\n </div>\n ))}\n {isThinking && (\n <div className=\"flex justify-start\">\n <div className=\"inline-flex items-center gap-2 rounded-2xl border border-border bg-card px-4 py-3 text-sm text-muted-foreground\">\n <Loader2 className=\"size-4 animate-spin\" />\n {progress != null\n ? t('aiAssistant:thinkingProgress', { progress })\n : t('aiAssistant:thinking')}\n </div>\n </div>\n )}\n </div>\n </ScrollArea>\n\n <div className=\"border-t border-border bg-background/95 px-3 py-2\">\n {queue.length > 0 && (\n <div className=\"mb-2 space-y-1\">\n {queue.map((item, index) => (\n <div\n key={item.id}\n className=\"flex items-center gap-2 rounded-md bg-muted/50 px-2 py-1 text-sm\"\n >\n <span className=\"shrink-0 tabular-nums text-xs text-muted-foreground\">\n ({index + 1})\n </span>\n <span className=\"flex-1 truncate\" title={item.content}>\n {item.content}\n </span>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-6 shrink-0\"\n onClick={() =>\n setQueue((q) => q.filter((entry) => entry.id !== item.id))\n }\n aria-label={t('aiAssistant:queue.cancel')}\n >\n <X className=\"size-3.5\" />\n </Button>\n </div>\n ))}\n </div>\n )}\n <form\n onSubmit={(e) => {\n e.preventDefault()\n submit()\n }}\n >\n <div className=\"flex items-center gap-1\">\n <Textarea\n value={input}\n onChange={(e) => setInput(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) {\n e.preventDefault()\n submit()\n }\n }}\n rows={1}\n placeholder={t('aiAssistant:input.placeholder')}\n aria-label={t('aiAssistant:input.placeholder')}\n className={\n 'flex-1 max-h-[10rem] min-h-0 resize-none border-0 bg-transparent px-1 py-2 ' +\n 'text-sm shadow-none outline-none [field-sizing:content] ' +\n 'focus-visible:ring-0 focus-visible:ring-offset-0'\n }\n />\n <Button\n type=\"submit\"\n disabled={sendDisabled}\n aria-label={t('aiAssistant:send')}\n className=\"size-8 shrink-0 rounded-full p-0\"\n >\n <Send className=\"size-4\" />\n </Button>\n </div>\n <p className=\"px-1 pb-1 text-xs text-muted-foreground\">\n {t('aiAssistant:input.hint')}\n </p>\n </form>\n </div>\n </>\n )}\n </SheetContent>\n </Sheet>\n </>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ai-assistant-widget-Bt4Z7Fmr.js","names":[],"sources":["../../../../react/src/components/ai-assistant-widget.tsx"],"sourcesContent":["import * as React from 'react'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n RichtextRender,\n ScrollArea,\n Sheet,\n SheetClose,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n Textarea,\n} from '@modern-admin/ui'\nimport { Bot, History, Loader2, MessageSquare, Plus, Send, Settings, X } from 'lucide-react'\nimport { uuidv7 } from '@modern-admin/core'\nimport { useAdminClient } from '../provider.js'\nimport { useFeatures } from '../hooks.js'\nimport { useNotify } from '../notify.js'\nimport { useBasepath, useNavigate } from '../router.js'\nimport { useI18n } from '../i18n.js'\nimport type {\n AiAssistantChatHistoryItem,\n AiAssistantChatMessage,\n AiAssistantCitation,\n AiAssistantTask,\n AiUiAction,\n} from '../client.js'\nimport { emitDashboardReload } from '../use-dashboard-charts.js'\n\ninterface ChatItem {\n id: string\n role: 'user' | 'assistant'\n content: string\n citations?: AiAssistantCitation[]\n}\n\ninterface QueuedItem {\n id: string\n content: string\n}\n\nconst randomId = (): string => uuidv7()\n\nconst MAX_QUEUE = 5\n\nconst messagesFromTask = (task: AiAssistantTask, fallbackText: string): ChatItem[] => {\n const inputMessages = Array.isArray(task.input?.messages)\n ? task.input.messages as AiAssistantChatMessage[]\n : []\n const items: ChatItem[] = inputMessages.map((message, index) => ({\n id: `${task.id}-input-${index}`,\n role: message.role,\n content: message.content,\n }))\n if (task.output) {\n const text = String(task.output.text ?? '').trim()\n items.push({\n id: `task-${task.id}`,\n role: 'assistant',\n content: text || fallbackText,\n citations: Array.isArray(task.output.citations) ? task.output.citations : undefined,\n })\n }\n return items\n}\n\nexport function AiAssistantWidget(): React.ReactElement | null {\n const client = useAdminClient()\n const queryClient = useQueryClient()\n const notify = useNotify()\n const navigate = useNavigate()\n const basepath = useBasepath()\n const { locale, t } = useI18n()\n const [open, setOpen] = React.useState(false)\n const [input, setInput] = React.useState('')\n const [messages, setMessages] = React.useState<ChatItem[]>([])\n const [conversationId, setConversationId] = React.useState(() => randomId())\n const [activeTaskId, setActiveTaskId] = React.useState<string | null>(null)\n const [queue, setQueue] = React.useState<QueuedItem[]>([])\n\n // Capability gate: when the host hasn't wired `aiAssistant` in\n // `ModernAdminModule.forRoot`, the `/admin/api/ai-assistant/*`\n // controllers aren't even registered — issuing the settings query would\n // 404 every page load. Skip the query, the widget, and the chat sheet\n // entirely in that case.\n const features = useFeatures()\n const aiAvailable = features.aiAssistant\n\n const settings = useQuery({\n queryKey: ['modern-admin', 'ai-assistant', 'settings'],\n queryFn: () => client.getAiAssistantSettings(),\n enabled: aiAvailable,\n })\n\n const chat = useMutation({\n mutationFn: async (input: {\n requestId: string\n conversationId: string\n messages: AiAssistantChatMessage[]\n }) => {\n // Strip the admin's basepath so the backend receives a basepath-relative\n // path (e.g. `/resources/posts/123`, not `/admin/resources/posts/123`) —\n // the grounding prompt matches against the relative `/resources/...` form.\n // Boundary-aware: only strip a full segment match so basepath `/admin`\n // never mangles an unrelated path like `/administrators`.\n let pathname = typeof window !== 'undefined' ? window.location.pathname : undefined\n if (pathname && basepath) {\n if (pathname === basepath) {\n pathname = '/'\n } else if (pathname.startsWith(`${basepath}/`)) {\n pathname = pathname.slice(basepath.length)\n }\n }\n return client.sendAiAssistantChat(\n input.messages,\n input.requestId,\n locale,\n input.conversationId,\n pathname ? { pathname } : undefined,\n )\n },\n onSuccess: (response) => {\n setActiveTaskId(response.taskId)\n void queryClient.invalidateQueries({ queryKey: ['modern-admin', 'ai-assistant', 'chats'] })\n },\n onError: (err) => {\n notify.error({ message: err instanceof Error ? err.message : String(err) })\n },\n })\n\n const history = useQuery<AiAssistantChatHistoryItem[]>({\n queryKey: ['modern-admin', 'ai-assistant', 'chats'],\n queryFn: () => client.listAiAssistantChats(),\n enabled: aiAvailable && open && settings.data?.configured === true,\n })\n\n const task = useQuery<AiAssistantTask>({\n queryKey: ['modern-admin', 'ai-assistant', 'task', activeTaskId],\n queryFn: () => client.getAiAssistantTask(activeTaskId!),\n enabled: !!activeTaskId,\n refetchInterval: (query) => {\n const state = query.state.data?.status\n return state === 'pending' || state === 'running' ? 1200 : false\n },\n })\n\n React.useEffect(() => {\n const data = task.data\n if (!data || !activeTaskId) return\n if (data.status === 'succeeded' && data.output != null) {\n setMessages((prev) => {\n const alreadyExists = prev.some((item) => item.id === `task-${data.id}`)\n if (alreadyExists) return prev\n const text = String(data.output?.text ?? '').trim()\n return [\n ...prev,\n {\n id: `task-${data.id}`,\n role: 'assistant',\n content: text || t('aiAssistant:noText'),\n citations: Array.isArray(data.output?.citations) ? data.output.citations : undefined,\n },\n ]\n })\n setActiveTaskId(null)\n void queryClient.invalidateQueries({ queryKey: ['modern-admin', 'ai-assistant', 'chats'] })\n const uiActions = Array.isArray(data.output?.uiActions)\n ? (data.output.uiActions as AiUiAction[])\n : []\n for (const action of uiActions) {\n if (action.kind === 'refresh' && action.target === 'dashboard') {\n emitDashboardReload()\n continue\n }\n if (action.kind === 'navigate') {\n setOpen(false)\n navigate(action.route)\n }\n }\n return\n }\n if (data.status === 'failed' || data.status === 'cancelled') {\n notify.error({ message: data.error ?? t('aiAssistant:taskFailed') })\n setActiveTaskId(null)\n }\n }, [activeTaskId, navigate, notify, queryClient, task.data, t])\n\n // Send a user message immediately (assumes nothing is in flight).\n const sendChat = React.useCallback(\n (content: string): void => {\n const userMsg: ChatItem = { id: randomId(), role: 'user', content }\n const updated = [...messages, userMsg]\n setMessages(updated)\n chat.mutate({\n requestId: userMsg.id,\n conversationId,\n messages: updated.map((m) => ({ role: m.role, content: m.content })),\n })\n },\n [chat, conversationId, messages],\n )\n\n const startNewChat = React.useCallback((): void => {\n setConversationId(randomId())\n setMessages([])\n setInput('')\n setQueue([])\n setActiveTaskId(null)\n }, [])\n\n const selectChat = React.useCallback(\n async (item: AiAssistantChatHistoryItem): Promise<void> => {\n try {\n const selected = await client.getAiAssistantTask(item.taskId)\n setConversationId(item.conversationId)\n setMessages(messagesFromTask(selected, t('aiAssistant:noText')))\n setQueue([])\n setInput('')\n setActiveTaskId(\n selected.status === 'pending' || selected.status === 'running' ? selected.id : null,\n )\n } catch (err) {\n notify.error({ message: err instanceof Error ? err.message : String(err) })\n }\n },\n [client, notify, t],\n )\n\n // Auto-dequeue: when nothing is in flight and queue has items, send the head.\n React.useEffect(() => {\n if (activeTaskId !== null) return\n if (chat.isPending) return\n const next = queue[0]\n if (!next) return\n setQueue((q) => q.slice(1))\n sendChat(next.content)\n }, [activeTaskId, chat.isPending, queue, sendChat])\n\n if (!aiAvailable) return null\n if (settings.isLoading) return null\n if (settings.error) return null\n if (!settings.data?.enabled) return null\n if (!settings.data.canChat) return null\n\n const isProcessing = chat.isPending || activeTaskId != null\n const queueFull = queue.length >= MAX_QUEUE\n\n const submit = (): void => {\n const text = input.trim()\n if (!text) return\n if (isProcessing) {\n if (queueFull) return\n setQueue((q) => [...q, { id: randomId(), content: text }])\n setInput('')\n return\n }\n setInput('')\n sendChat(text)\n }\n\n const configured = settings.data.configured\n const isThinking =\n isProcessing ||\n task.data?.status === 'running' ||\n task.data?.status === 'pending'\n const progress = typeof task.data?.progress === 'number' ? task.data.progress : null\n const sendDisabled = input.trim().length === 0 || (isProcessing && queueFull)\n\n return (\n <>\n <div className=\"fixed bottom-4 right-4 z-40\">\n <Button\n onClick={() => setOpen(true)}\n aria-label={t('aiAssistant:fab.label')}\n className={\n 'group h-10 min-w-10 max-w-10 rounded-full pl-3 pr-3 shadow-lg ' +\n 'justify-end gap-0 overflow-hidden opacity-70 hover:opacity-100 ' +\n 'transition-[max-width,padding-left,opacity] duration-200 ease-in-out ' +\n 'hover:max-w-36 hover:pl-4'\n }\n >\n <span className=\"max-w-0 overflow-hidden whitespace-nowrap text-sm font-medium transition-[max-width,padding-right] duration-200 ease-in-out group-hover:max-w-[5rem] group-hover:pr-2\">\n {t('aiAssistant:fab.short')}\n </span>\n <MessageSquare className=\"size-4 shrink-0\" />\n </Button>\n </div>\n <Sheet open={open} onOpenChange={setOpen}>\n <SheetContent hideCloseButton className=\"flex w-full flex-col gap-0 sm:max-w-xl\">\n <SheetHeader className=\"border-b border-border pb-4\">\n <div className=\"flex items-start gap-3\">\n <div className=\"min-w-0 flex-1\">\n <SheetTitle className=\"flex items-center gap-2\">\n <Bot className=\"size-5\" />\n {t('aiAssistant:title')}\n </SheetTitle>\n <SheetDescription>{t('aiAssistant:description')}</SheetDescription>\n </div>\n <div className=\"flex shrink-0 items-center gap-0.5\">\n {configured && (\n <>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n aria-label={t('aiAssistant:history')}\n >\n <History className=\"size-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-72\">\n <DropdownMenuLabel>{t('aiAssistant:history')}</DropdownMenuLabel>\n <DropdownMenuSeparator />\n {history.isLoading && (\n <DropdownMenuItem disabled>{t('common:loading')}</DropdownMenuItem>\n )}\n {!history.isLoading && (history.data?.length ?? 0) === 0 && (\n <DropdownMenuItem disabled>{t('aiAssistant:history.empty')}</DropdownMenuItem>\n )}\n {history.data?.map((item) => (\n <DropdownMenuItem\n key={item.conversationId}\n className=\"flex-col items-start gap-0 py-2\"\n onSelect={() => {\n void selectChat(item)\n }}\n >\n <span className=\"line-clamp-1 w-full text-sm font-medium\">{item.title}</span>\n <span className=\"text-xs text-muted-foreground\">\n {new Intl.DateTimeFormat(locale, {\n dateStyle: 'short',\n timeStyle: 'short',\n }).format(new Date(item.updatedAt))}\n </span>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={startNewChat}\n aria-label={t('aiAssistant:newChat')}\n >\n <Plus className=\"size-4\" />\n </Button>\n </>\n )}\n <SheetClose asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n aria-label={t('common:close')}\n >\n <X className=\"size-4\" />\n </Button>\n </SheetClose>\n </div>\n </div>\n </SheetHeader>\n\n {!configured ? (\n <div className=\"flex flex-1 flex-col items-center justify-center gap-4 px-4 text-center\">\n <div className=\"space-y-2\">\n <div className=\"text-lg font-semibold\">\n {t('aiAssistant:notConfigured.title')}\n </div>\n <div className=\"text-sm text-muted-foreground\">\n {t('aiAssistant:notConfigured.description')}\n </div>\n </div>\n {settings.data.canManage && (\n <Button\n variant=\"outline\"\n onClick={() => {\n setOpen(false)\n navigate({ name: 'settings', section: 'ai-assistant' })\n }}\n >\n <Settings className=\"size-4\" />\n {t('aiAssistant:notConfigured.openSettings')}\n </Button>\n )}\n </div>\n ) : (\n <>\n <ScrollArea className=\"flex-1 px-4 py-4\">\n <div className=\"space-y-3\">\n {messages.length === 0 && (\n <Card>\n <CardContent className=\"space-y-2 p-4 text-sm text-muted-foreground\">\n <div className=\"font-medium text-foreground\">\n {t('aiAssistant:tryAsking')}\n </div>\n <div>- {t('aiAssistant:tryAsking.example1')}</div>\n <div>- {t('aiAssistant:tryAsking.example2')}</div>\n <div>- {t('aiAssistant:tryAsking.example3')}</div>\n </CardContent>\n </Card>\n )}\n {messages.map((message) => (\n <div\n key={message.id}\n className={message.role === 'user' ? 'flex justify-end' : 'flex justify-start'}\n >\n <div\n className={message.role === 'user'\n ? 'max-w-[85%] rounded-2xl bg-primary px-4 py-3 text-sm text-primary-foreground'\n : 'max-w-[85%] rounded-2xl border border-border bg-card px-4 py-3 text-sm'}\n >\n {message.role === 'assistant' ? (\n <RichtextRender\n value={message.content}\n format=\"markdown\"\n className=\"text-sm [&_pre]:overflow-x-auto [&_pre]:text-xs\"\n />\n ) : (\n <div className=\"whitespace-pre-wrap\">{message.content}</div>\n )}\n {message.citations && message.citations.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-2\">\n {message.citations.slice(0, 6).map((citation, index) => {\n const label = `${citation.resourceId}${citation.recordId ? `#${citation.recordId}` : ''}`\n const key = `${citation.resourceId}-${citation.recordId ?? 'resource'}-${index}`\n if (citation.recordId) {\n return (\n <button\n key={key}\n type=\"button\"\n className=\"cursor-pointer\"\n onClick={() => {\n setOpen(false)\n navigate({\n name: 'show',\n resourceId: citation.resourceId,\n recordId: citation.recordId!,\n })\n }}\n >\n <Badge variant=\"outline\">{label}</Badge>\n </button>\n )\n }\n return (\n <button\n key={key}\n type=\"button\"\n className=\"cursor-pointer\"\n onClick={() => {\n setOpen(false)\n navigate({ name: 'list', resourceId: citation.resourceId })\n }}\n >\n <Badge variant=\"outline\">{label}</Badge>\n </button>\n )\n })}\n </div>\n )}\n </div>\n </div>\n ))}\n {isThinking && (\n <div className=\"flex justify-start\">\n <div className=\"inline-flex items-center gap-2 rounded-2xl border border-border bg-card px-4 py-3 text-sm text-muted-foreground\">\n <Loader2 className=\"size-4 animate-spin\" />\n {progress != null\n ? t('aiAssistant:thinkingProgress', { progress })\n : t('aiAssistant:thinking')}\n </div>\n </div>\n )}\n </div>\n </ScrollArea>\n\n <div className=\"border-t border-border bg-background/95 px-3 py-2\">\n {queue.length > 0 && (\n <div className=\"mb-2 space-y-1\">\n {queue.map((item, index) => (\n <div\n key={item.id}\n className=\"flex items-center gap-2 rounded-md bg-muted/50 px-2 py-1 text-sm\"\n >\n <span className=\"shrink-0 tabular-nums text-xs text-muted-foreground\">\n ({index + 1})\n </span>\n <span className=\"flex-1 truncate\" title={item.content}>\n {item.content}\n </span>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-6 shrink-0\"\n onClick={() =>\n setQueue((q) => q.filter((entry) => entry.id !== item.id))\n }\n aria-label={t('aiAssistant:queue.cancel')}\n >\n <X className=\"size-3.5\" />\n </Button>\n </div>\n ))}\n </div>\n )}\n <form\n onSubmit={(e) => {\n e.preventDefault()\n submit()\n }}\n >\n <div className=\"flex items-center gap-1\">\n <Textarea\n value={input}\n onChange={(e) => setInput(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) {\n e.preventDefault()\n submit()\n }\n }}\n rows={1}\n placeholder={t('aiAssistant:input.placeholder')}\n aria-label={t('aiAssistant:input.placeholder')}\n className={\n 'flex-1 max-h-[10rem] min-h-0 resize-none border-0 bg-transparent px-1 py-2 ' +\n 'text-sm shadow-none outline-none [field-sizing:content] ' +\n 'focus-visible:ring-0 focus-visible:ring-offset-0'\n }\n />\n <Button\n type=\"submit\"\n disabled={sendDisabled}\n aria-label={t('aiAssistant:send')}\n className=\"size-8 shrink-0 rounded-full p-0\"\n >\n <Send className=\"size-4\" />\n </Button>\n </div>\n <p className=\"px-1 pb-1 text-xs text-muted-foreground\">\n {t('aiAssistant:input.hint')}\n </p>\n </form>\n </div>\n </>\n )}\n </SheetContent>\n </Sheet>\n </>\n )\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arrow-left-CI9hUPwJ.js","names":[],"sources":["../../../../../node_modules/.bun/lucide-react@1.23.0+e14d3f224186685e/node_modules/lucide-react/dist/esm/icons/arrow-left.mjs"],"sourcesContent":["/**\n * @license lucide-react v1.23.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"m12 19-7-7 7-7\", key: \"1l729n\" }],\n [\"path\", { d: \"M19 12H5\", key: \"x3x0zl\" }]\n];\nconst ArrowLeft = createLucideIcon(\"arrow-left\", __iconNode);\n\nexport { __iconNode, ArrowLeft as default };\n//# sourceMappingURL=arrow-left.mjs.map\n"],"x_google_ignoreList":[0],"mappings":"mDAaA,IAAM,EAAY,EAAiB,aAAc,CAH/C,CAAC,OAAQ,CAAE,EAAG,iBAAkB,IAAK,QAAS,CAAC,EAC/C,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAS,CAAC,CAEM,CAAU"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as e,n as t}from"./createLucideIcon-CUopU_LC.js";import{S as n,s as r}from"./with-selector-NDLhu4dT.js";import{n as i,r as a,t as o}from"./key-lbuX0yk_.js";import{n as s,t as c}from"./trash-2-DhyKQCKv.js";import{n as l,t as u}from"./pencil-BO-k3yTG.js";import{t as d}from"./file-text-CcLZq8HA.js";import{t as f}from"./key-round-CQLp1Ua9.js";import{t as p}from"./x-C3kLunD6.js";import{s as m}from"./dist-Dpg8xy_r.js";import{a as h,i as g,n as _,r as v,t as y}from"./select-BWf6walM.js";import{a as b,c as x,i as S,n as C,o as w,r as T,s as E,t as D}from"./calendar-BZVUWakC.js";import{K as O,L as k,U as A,W as j,et as M,n as N,q as P}from"./router-wFvtgo77.js";import{a as ee,i as te,n as F}from"./useQueries-BCUhWYX4.js";import{a as I,i as L,n as R,t as z}from"./card-4cS4uWCP.js";import{a as ne,i as re,n as ie,r as ae,t as B}from"./user-directory-9COoW6AO.js";import{H as V,Y as H,at as oe,ot as se,vt as ce}from"./index-t4woXGa-.js";var U=e(t(),1),W=n(),G=`yyyy-MM-dd`,K=`MMM d, yyyy`;function q(e){if(!e)return;let t=e.length<=10?S(e,G,new Date):C(e);return E(t)?t:void 0}function J({from:e,to:t,onChange:n,disabled:i,className:o,labels:s={}}){let c=s.placeholder??`Select date range`,l=s.apply??`Apply`,u=s.clear??`Clear`,[d,f]=U.useState(!1),[h,g]=U.useState(()=>{let n=q(e),r=q(t);return n&&r?{from:n,to:r}:void 0});U.useEffect(()=>{let n=q(e),r=q(t);g(n??r?{from:n,to:r}:void 0)},[e,t]);let[_,v]=U.useState(()=>typeof window<`u`&&window.innerWidth>=640?2:1);U.useEffect(()=>{let e=window.matchMedia(`(min-width: 640px)`),t=e=>v(e.matches?2:1);return v(e.matches?2:1),e.addEventListener(`change`,t),()=>e.removeEventListener(`change`,t)},[]);let[y,S]=U.useState(()=>w(q(e)??new Date)),[C,E]=U.useState(()=>{let n=q(e),r=q(t),i=w(n??new Date);return r&&!T(i,r)?w(r):x(i,1)}),O=n=>{if(n){let n=q(e),r=q(t);g(n&&r?{from:n,to:r}:void 0);let i=w(n??new Date),a=r&&!T(i,r)?w(r):x(i,1);S(i),E(a)}else{let n=q(e),r=q(t);g(n??r?{from:n,to:r}:void 0)}f(n)},k=e=>{S(e),!T(e,C)&&e>C&&E(x(e,1))},A=e=>{E(e),!T(e,y)&&e<y&&S(x(e,-1))},j=e=>{g(e)},M=()=>{h?.from&&n(b(h.from,G),h.to?b(h.to,G):``),f(!1)},N=()=>{g(void 0),n(``,``),f(!1)},P=e=>{e.stopPropagation(),g(void 0),n(``,``)},I=q(e),L=q(t),R=!!(e||t),z=R?[I?b(I,K):`…`,L?b(L,K):`…`].join(` – `):null;return(0,W.jsxs)(F,{open:d,onOpenChange:O,children:[(0,W.jsx)(ee,{asChild:!0,children:(0,W.jsxs)(m,{type:`button`,variant:`outline`,disabled:i,className:r(`h-9 w-full justify-start gap-2 px-3 font-normal`,!R&&`text-muted-foreground`,o),children:[(0,W.jsx)(a,{className:`size-4 shrink-0 opacity-60`}),(0,W.jsx)(`span`,{className:`flex-1 truncate text-left text-sm`,children:z??c}),R&&(0,W.jsx)(`span`,{role:`button`,tabIndex:0,"aria-label":u,onClick:P,onKeyDown:e=>{(e.key===`Enter`||e.key===` `)&&P(e)},className:`ml-1 rounded-sm p-0.5 opacity-50 hover:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring`,children:(0,W.jsx)(p,{className:`size-3.5`})})]})}),(0,W.jsxs)(te,{className:`w-auto p-0`,align:`start`,children:[_===2?(0,W.jsxs)(`div`,{className:`flex flex-col sm:flex-row`,children:[(0,W.jsx)(D,{mode:`range`,selected:h,onSelect:j,numberOfMonths:1,month:y,onMonthChange:k,endMonth:C,autoFocus:!0}),(0,W.jsx)(D,{mode:`range`,selected:h,onSelect:j,numberOfMonths:1,month:C,onMonthChange:A,startMonth:y})]}):(0,W.jsx)(D,{mode:`range`,selected:h,onSelect:j,numberOfMonths:1,defaultMonth:h?.from??h?.to??void 0,autoFocus:!0}),(0,W.jsxs)(`div`,{className:`flex items-center justify-between border-t border-border px-3 py-2`,children:[(0,W.jsx)(m,{variant:`ghost`,size:`sm`,onClick:N,children:u}),(0,W.jsx)(m,{size:`sm`,onClick:M,disabled:!h?.from,children:l})]})]})]})}J.displayName=`DateRangeInput`;var Y=`__all__`,le=[`new`,`edit`,`delete`,`bulkDelete`,`login`,`apiKey.create`,`apiKey.update`,`apiKey.delete`],X={__auth__:`audit:virtualResource.auth`,__api_keys__:`audit:virtualResource.apiKeys`},ue={Icon:d,iconClass:`text-muted-foreground`,bgClass:`bg-muted`,titleKey:``},Z={new:{Icon:i,iconClass:`text-blue-600 dark:text-blue-300`,bgClass:`bg-blue-100 dark:bg-blue-950/40`,titleKey:`audit:action.new`},edit:{Icon:u,iconClass:`text-emerald-600 dark:text-emerald-300`,bgClass:`bg-emerald-100 dark:bg-emerald-950/40`,titleKey:`audit:action.edit`},delete:{Icon:c,iconClass:`text-rose-600 dark:text-rose-300`,bgClass:`bg-rose-100 dark:bg-rose-950/40`,titleKey:`audit:action.delete`},bulkDelete:{Icon:c,iconClass:`text-rose-600 dark:text-rose-300`,bgClass:`bg-rose-100 dark:bg-rose-950/40`,titleKey:`audit:action.bulkDelete`},login:{Icon:oe,iconClass:`text-violet-600 dark:text-violet-300`,bgClass:`bg-violet-100 dark:bg-violet-950/40`,titleKey:`audit:action.login`},"apiKey.create":{Icon:o,iconClass:`text-amber-600 dark:text-amber-300`,bgClass:`bg-amber-100 dark:bg-amber-950/40`,titleKey:`audit:action.apiKeyCreate`},"apiKey.update":{Icon:f,iconClass:`text-amber-600 dark:text-amber-300`,bgClass:`bg-amber-100 dark:bg-amber-950/40`,titleKey:`audit:action.apiKeyUpdate`},"apiKey.delete":{Icon:c,iconClass:`text-rose-600 dark:text-rose-300`,bgClass:`bg-rose-100 dark:bg-rose-950/40`,titleKey:`audit:action.apiKeyDelete`}};function de(e){let t=U.useMemo(()=>new Intl.RelativeTimeFormat(e,{numeric:`auto`}),[e]),n=U.useMemo(()=>new Intl.DateTimeFormat(e,{dateStyle:`medium`,timeStyle:`short`}),[e]);return U.useCallback((e,r)=>{let i=Math.round((r-e)/1e3);return i<45?t.format(-Math.max(i,0),`second`):i<3600?t.format(-Math.round(i/60),`minute`):i<86400?t.format(-Math.round(i/3600),`hour`):i<86400*7?t.format(-Math.round(i/86400),`day`):n.format(new Date(e))},[n,t])}var Q=e=>{let t=e.split(/\s+|[._@-]/).filter(Boolean);return t.length===0?`?`:t.length===1?t[0].slice(0,2).toUpperCase():(t[0][0]+t[1][0]).toUpperCase()},$=25;function fe(){let{t:e,locale:t}=M(),n=P(),[r,i]=U.useState({}),a=k(r,$),o=U.useMemo(()=>(a.data?.pages??[]).flatMap(e=>e.events.slice(0,$)),[a.data]),s=ie(U.useMemo(()=>Array.from(new Set(o.map(e=>e.userId).filter(e=>!!e))),[o])),c=U.useMemo(()=>{let e={};for(let t of n)e[t.id]=t;return e},[n]),l=n.some(e=>e.id===B),u=de(t),d=U.useCallback(e=>new Intl.DateTimeFormat(t,{dateStyle:`medium`,timeStyle:`short`}).format(new Date(e)),[t]),f=U.useMemo(()=>Date.now(),[o]),p=U.useRef(null),{hasNextPage:m,isFetchingNextPage:b,fetchNextPage:x}=a;U.useEffect(()=>{let e=p.current;if(!e)return;let t=new IntersectionObserver(e=>{e[0]?.isIntersecting&&m&&!b&&x()},{rootMargin:`200px`});return t.observe(e),()=>t.disconnect()},[m,b,x]);let S=e=>{i(t=>({...t,...e}))};return(0,W.jsxs)(`div`,{className:`space-y-2 sm:space-y-4`,children:[(0,W.jsxs)(z,{children:[(0,W.jsx)(L,{children:(0,W.jsx)(I,{children:e(`audit:title`)})}),(0,W.jsxs)(R,{className:`grid gap-3 sm:grid-cols-2 md:grid-cols-4`,children:[(0,W.jsxs)(y,{value:r.resourceId??Y,onValueChange:e=>S({resourceId:e===Y?void 0:e}),children:[(0,W.jsx)(g,{"aria-label":e(`audit:resource`),children:(0,W.jsx)(h,{})}),(0,W.jsxs)(_,{children:[(0,W.jsx)(v,{value:Y,children:e(`audit:allResources`)}),Object.entries(X).map(([t,n])=>(0,W.jsx)(v,{value:t,children:e(n)},t)),n.map(e=>(0,W.jsxs)(v,{value:e.id,children:[e.name,e.name!==e.id&&(0,W.jsxs)(`span`,{className:`ml-1.5 text-xs text-muted-foreground`,children:[`(`,e.id,`)`]})]},e.id))]})]}),(0,W.jsxs)(y,{value:r.actions?.[0]??Y,onValueChange:e=>S({actions:e===Y?void 0:[e]}),children:[(0,W.jsx)(g,{"aria-label":e(`audit:action`),children:(0,W.jsx)(h,{})}),(0,W.jsxs)(_,{children:[(0,W.jsx)(v,{value:Y,children:e(`audit:allActions`)}),le.map(t=>{let n=Z[t];return(0,W.jsx)(v,{value:t,children:n?.titleKey?e(n.titleKey):t},t)})]})]}),(0,W.jsx)(H,{value:r.recordId??``,placeholder:e(`audit:recordId`),onChange:e=>S({recordId:e.target.value||void 0})}),(0,W.jsx)(H,{value:r.userId??``,placeholder:e(`audit:userId`),onChange:e=>S({userId:e.target.value||void 0})}),(0,W.jsx)(J,{from:r.from,to:r.to,onChange:(e,t)=>S({from:e||void 0,to:t||void 0}),className:`sm:col-span-2 md:col-span-4`,labels:{placeholder:e(`audit:dateRangePlaceholder`),apply:e(`common:apply`),clear:e(`common:clear`)}})]})]}),(0,W.jsx)(z,{children:(0,W.jsxs)(R,{children:[a.isLoading?(0,W.jsxs)(`div`,{className:`space-y-3`,children:[(0,W.jsx)(V,{className:`h-20 w-full`}),(0,W.jsx)(V,{className:`h-20 w-full`}),(0,W.jsx)(V,{className:`h-20 w-full`})]}):a.isError?(0,W.jsx)(`div`,{className:`rounded-md border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive`,children:e(`audit:loadError`)}):o.length===0?(0,W.jsx)(`div`,{className:`rounded-md border border-dashed border-border p-6 text-center text-sm text-muted-foreground`,children:e(`audit:noEvents`)}):(0,W.jsx)(`ol`,{className:`space-y-3`,children:o.map((e,t)=>(0,W.jsx)(pe,{entry:e,resource:c[e.resourceId],user:e.userId?s.get(e.userId)??null:null,userResourceId:l?B:void 0,now:f,formatRelative:u,formatAbsolute:d},e.id??`${e.at}:${t}`))}),(0,W.jsx)(`div`,{ref:p,className:`h-1`,"aria-hidden":!0}),a.isFetchingNextPage&&(0,W.jsx)(`div`,{className:`flex justify-center py-4`,children:(0,W.jsx)(se,{className:`size-5 animate-spin text-muted-foreground`})})]})})]})}function pe({entry:e,resource:t,user:n,userResourceId:i,now:a,formatRelative:o,formatAbsolute:c}){let{t:u}=M(),[d,f]=U.useState(!1),p=Z[e.action]??ue,h=p.Icon,g=p.titleKey?u(p.titleKey):e.action,_=ae(n,e.userId??u(`history:unknownUser`)),v=u(`audit:by`,{user:`\0`}).split(`\0`),y=v[0]??``,b=v[1]??``,x=X[e.resourceId],S=x?u(x):t?.name??e.resourceId,C=e.action===`edit`&&!!e.recordId;return(0,W.jsx)(`li`,{className:`rounded-lg border border-border bg-card p-4 shadow-sm`,children:(0,W.jsxs)(`div`,{className:`flex items-start gap-3`,children:[(0,W.jsx)(`span`,{className:r(`flex size-10 shrink-0 items-center justify-center rounded-full`,p.bgClass),children:(0,W.jsx)(h,{className:r(`size-5`,p.iconClass)})}),(0,W.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,W.jsxs)(`div`,{className:`flex items-start justify-between gap-3`,children:[(0,W.jsxs)(`div`,{className:`min-w-0`,children:[(0,W.jsx)(`p`,{className:`truncate text-sm font-semibold`,children:g}),(0,W.jsxs)(`div`,{className:`mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-muted-foreground`,children:[(0,W.jsx)(`span`,{className:`font-medium`,children:S}),e.recordId&&(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(`span`,{"aria-hidden":!0,children:`·`}),t?(0,W.jsxs)(N,{to:{name:`show`,resourceId:e.resourceId,recordId:e.recordId},className:`inline-flex items-center gap-1 rounded bg-muted px-1.5 py-0.5 text-[11px] text-foreground hover:underline`,title:e.recordId,children:[(0,W.jsx)(`span`,{className:`truncate max-w-[12rem]`,children:e.recordTitle??`#${e.recordId}`}),(0,W.jsx)(l,{className:`size-3 shrink-0`})]}):e.recordTitle?(0,W.jsx)(`span`,{className:`truncate max-w-[12rem] rounded bg-muted px-1.5 py-0.5 text-[11px] text-foreground`,title:e.recordId,children:e.recordTitle}):null]}),!e.recordId&&e.recordIds?.length?(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(`span`,{"aria-hidden":!0,children:`·`}),(0,W.jsxs)(`span`,{children:[e.recordIds.length,` `,u(`audit:records`)]})]}):null]}),(0,W.jsxs)(`p`,{className:`mt-1 flex items-center gap-1.5 text-xs text-muted-foreground`,children:[(0,W.jsx)(`span`,{"aria-hidden":!0,className:`inline-flex size-5 shrink-0 items-center justify-center rounded-full bg-primary/10 text-[10px] font-semibold text-primary`,children:Q(_)}),(0,W.jsxs)(`span`,{className:`truncate`,children:[y,i&&e.userId?(0,W.jsx)(N,{to:{name:`show`,resourceId:i,recordId:e.userId},className:`font-medium text-foreground hover:underline`,children:_}):_,b]})]})]}),(0,W.jsx)(`time`,{className:`shrink-0 text-xs text-muted-foreground`,dateTime:new Date(e.at).toISOString(),title:c(e.at),children:o(e.at,a)})]}),C&&(0,W.jsxs)(`div`,{className:`mt-3`,children:[(0,W.jsxs)(m,{variant:`ghost`,size:`sm`,className:`-ml-2 h-7 px-2 text-xs`,onClick:()=>f(e=>!e),"aria-expanded":d,children:[d?(0,W.jsx)(s,{className:`size-3.5`}):(0,W.jsx)(ce,{className:`size-3.5`}),u(d?`audit:hideChanges`:`audit:viewChanges`)]}),d&&(0,W.jsx)(`div`,{className:`mt-2`,children:(0,W.jsx)(me,{resourceId:e.resourceId,recordId:e.recordId,atMs:e.at})})]})]})]})})}function me({resourceId:e,recordId:t,atMs:n}){let{t:r}=M(),i=O(e),a=j(e,t,{limit:50}),o=A(e,t),s=U.useMemo(()=>{let e={};for(let t of i?.properties??[])e[t.path]=t.label;return e},[i]);if(a.isLoading)return(0,W.jsx)(V,{className:`h-16 w-full`});if(a.isError)return(0,W.jsx)(`div`,{className:`rounded-md border border-destructive/50 bg-destructive/10 p-3 text-xs text-destructive`,children:r(`audit:loadDiffError`)});let c=ge(a.data?.revisions??[],n);if(!c)return(0,W.jsx)(`div`,{className:`rounded-md border border-dashed border-border p-3 text-xs text-muted-foreground`,children:r(`audit:noDiff`)});let l=re(c.snapshotBefore??{},c.snapshot).map(e=>({...e,label:s[e.path]})),u=o.data?.record?.title;return(0,W.jsxs)(`div`,{className:`space-y-2`,children:[u&&u!==t&&(0,W.jsx)(`p`,{className:`truncate text-xs text-muted-foreground`,title:u,children:u}),(0,W.jsx)(ne,{fields:l,labels:{added:r(`diff:added`),changed:r(`diff:changed`),removed:r(`diff:removed`),before:r(`diff:before`),after:r(`diff:after`),noChanges:r(`diff:noChanges`)}})]})}var he=6e4,ge=(e,t)=>{let n=null,r=1/0;for(let i of e){let e=new Date(i.createdAt).getTime();if(Number.isNaN(e))continue;let a=Math.abs(e-t);a<r&&a<=he&&(r=a,n=i)}return n};export{fe as AuditLogPage};
|
|
2
|
+
//# sourceMappingURL=audit-log-page-2wuGiWg-.js.map
|
|
Binary file
|
|
Binary file
|