web-mojo 2.3.2 → 2.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/CHANGELOG.md +192 -5
  2. package/dist/admin-models.cjs.js +1 -1
  3. package/dist/admin-models.es.js +1 -1
  4. package/dist/admin.cjs.js +1 -1
  5. package/dist/admin.es.js +1 -1
  6. package/dist/auth.cjs.js +1 -1
  7. package/dist/auth.es.js +1 -1
  8. package/dist/charts.cjs.js +1 -1
  9. package/dist/charts.es.js +1 -1
  10. package/dist/chunks/{AssistantPanelView-D-0f5hZS.js → AssistantPanelView-CvjzGGS8.js} +2 -2
  11. package/dist/chunks/{AssistantPanelView-D-0f5hZS.js.map → AssistantPanelView-CvjzGGS8.js.map} +1 -1
  12. package/dist/chunks/{AssistantPanelView-72i9d6rq.js → AssistantPanelView-D3WCWj5q.js} +2 -2
  13. package/dist/chunks/{AssistantPanelView-72i9d6rq.js.map → AssistantPanelView-D3WCWj5q.js.map} +1 -1
  14. package/dist/chunks/{ChatView-ys5MIiBf.js → ChatView-B-2JVhM3.js} +2 -2
  15. package/dist/chunks/{ChatView-ys5MIiBf.js.map → ChatView-B-2JVhM3.js.map} +1 -1
  16. package/dist/chunks/{ChatView-CXykdAV1.js → ChatView-oZ9FggEo.js} +2 -2
  17. package/dist/chunks/{ChatView-CXykdAV1.js.map → ChatView-oZ9FggEo.js.map} +1 -1
  18. package/dist/chunks/{Collection-CY6BblFn.js → Collection-BtSHP_BV.js} +2 -2
  19. package/dist/chunks/{Collection-CY6BblFn.js.map → Collection-BtSHP_BV.js.map} +1 -1
  20. package/dist/chunks/{Collection-BpUmNuDZ.js → Collection-CtSGTegm.js} +2 -2
  21. package/dist/chunks/{Collection-BpUmNuDZ.js.map → Collection-CtSGTegm.js.map} +1 -1
  22. package/dist/chunks/{ContextMenu-XQVFU0mL.js → ContextMenu-0KtfqyQm.js} +2 -2
  23. package/dist/chunks/{ContextMenu-XQVFU0mL.js.map → ContextMenu-0KtfqyQm.js.map} +1 -1
  24. package/dist/chunks/{ContextMenu-PtN50qH2.js → ContextMenu-DvQTJA49.js} +2 -2
  25. package/dist/chunks/{ContextMenu-PtN50qH2.js.map → ContextMenu-DvQTJA49.js.map} +1 -1
  26. package/dist/chunks/{DataView-BTi_BZHx.js → DataView-DJMOmlKN.js} +2 -2
  27. package/dist/chunks/{DataView-BTi_BZHx.js.map → DataView-DJMOmlKN.js.map} +1 -1
  28. package/dist/chunks/{DataView-WHRh1o6E.js → DataView-jHxX-6Gh.js} +2 -2
  29. package/dist/chunks/{DataView-WHRh1o6E.js.map → DataView-jHxX-6Gh.js.map} +1 -1
  30. package/dist/chunks/{FormView-DTD-Zy22.js → FormView-C_7xQuI4.js} +3 -3
  31. package/dist/chunks/{FormView-DTD-Zy22.js.map → FormView-C_7xQuI4.js.map} +1 -1
  32. package/dist/chunks/{FormView-BzaGMf5_.js → FormView-D8YrH2V4.js} +3 -3
  33. package/dist/chunks/{FormView-BzaGMf5_.js.map → FormView-D8YrH2V4.js.map} +1 -1
  34. package/dist/chunks/{ListView-BsnnTcmC.js → ListView-CjJ-4gD7.js} +2 -2
  35. package/dist/chunks/{ListView-BsnnTcmC.js.map → ListView-CjJ-4gD7.js.map} +1 -1
  36. package/dist/chunks/{ListView-Xf7kO6Me.js → ListView-mr1Kmuj-.js} +2 -2
  37. package/dist/chunks/{ListView-Xf7kO6Me.js.map → ListView-mr1Kmuj-.js.map} +1 -1
  38. package/dist/chunks/{MetricsCountryMapView-BzGOi1d2.js → MetricsCountryMapView-BIsfmvE0.js} +2 -2
  39. package/dist/chunks/{MetricsCountryMapView-BzGOi1d2.js.map → MetricsCountryMapView-BIsfmvE0.js.map} +1 -1
  40. package/dist/chunks/{MetricsCountryMapView-C-S00Wiw.js → MetricsCountryMapView-D9J4Gwdi.js} +2 -2
  41. package/dist/chunks/{MetricsCountryMapView-C-S00Wiw.js.map → MetricsCountryMapView-D9J4Gwdi.js.map} +1 -1
  42. package/dist/chunks/Modal-DF98u_sN.js +3 -0
  43. package/dist/chunks/Modal-DF98u_sN.js.map +1 -0
  44. package/dist/chunks/Modal-DYJadSN8.js +3 -0
  45. package/dist/chunks/Modal-DYJadSN8.js.map +1 -0
  46. package/dist/chunks/Passkeys-8ko7Rg8G.js +2 -0
  47. package/dist/chunks/Passkeys-8ko7Rg8G.js.map +1 -0
  48. package/dist/chunks/Passkeys-CD8RKUl8.js +2 -0
  49. package/dist/chunks/Passkeys-CD8RKUl8.js.map +1 -0
  50. package/dist/chunks/TokenManager-B-xR8zPl.js +2 -0
  51. package/dist/chunks/TokenManager-B-xR8zPl.js.map +1 -0
  52. package/dist/chunks/TokenManager-CZTL4OqZ.js +2 -0
  53. package/dist/chunks/TokenManager-CZTL4OqZ.js.map +1 -0
  54. package/dist/chunks/{User-KTBU_5cr.js → User-C6Tbn6vZ.js} +2 -2
  55. package/dist/chunks/User-C6Tbn6vZ.js.map +1 -0
  56. package/dist/chunks/{User-B_Urf7U7.js → User-DRbw-wOB.js} +2 -2
  57. package/dist/chunks/User-DRbw-wOB.js.map +1 -0
  58. package/dist/chunks/{UserProfileView-BmduMJ86.js → UserProfileView-DC70hRer.js} +2 -2
  59. package/dist/chunks/{UserProfileView-COxSyPB0.js.map → UserProfileView-DC70hRer.js.map} +1 -1
  60. package/dist/chunks/{UserProfileView-COxSyPB0.js → UserProfileView-TQ9BqUE2.js} +2 -2
  61. package/dist/chunks/{UserProfileView-BmduMJ86.js.map → UserProfileView-TQ9BqUE2.js.map} +1 -1
  62. package/dist/chunks/{View-C8UWvaSM.js → View-BWOE7WJm.js} +2 -2
  63. package/dist/chunks/{View-C8UWvaSM.js.map → View-BWOE7WJm.js.map} +1 -1
  64. package/dist/chunks/{View-Cvs2TY7b.js → View-D6Ug7M6k.js} +2 -2
  65. package/dist/chunks/{View-Cvs2TY7b.js.map → View-D6Ug7M6k.js.map} +1 -1
  66. package/dist/chunks/{WebApp-kbRq7dM_.js → WebApp-By80XfTK.js} +2 -2
  67. package/dist/chunks/{WebApp-kbRq7dM_.js.map → WebApp-By80XfTK.js.map} +1 -1
  68. package/dist/chunks/{WebApp-DuwanN2O.js → WebApp-CLTFSbto.js} +2 -2
  69. package/dist/chunks/{WebApp-DuwanN2O.js.map → WebApp-CLTFSbto.js.map} +1 -1
  70. package/dist/chunks/{admin-BcJ_hgzn.js → admin-CXA-Vkhf.js} +2 -2
  71. package/dist/chunks/{admin-BcJ_hgzn.js.map → admin-CXA-Vkhf.js.map} +1 -1
  72. package/dist/chunks/{admin-DtjMWe6R.js → admin-DcLy2QC2.js} +2 -2
  73. package/dist/chunks/{admin-DtjMWe6R.js.map → admin-DcLy2QC2.js.map} +1 -1
  74. package/dist/chunks/{exportChart-Dn2pioNl.js → exportChart-BQXkqsxe.js} +2 -2
  75. package/dist/chunks/{exportChart-Dn2pioNl.js.map → exportChart-BQXkqsxe.js.map} +1 -1
  76. package/dist/chunks/{exportChart-Bkxr7mCe.js → exportChart-UQ5nq_mR.js} +2 -2
  77. package/dist/chunks/{exportChart-Bkxr7mCe.js.map → exportChart-UQ5nq_mR.js.map} +1 -1
  78. package/dist/chunks/{index-CJeTVskY.js → index-C9wf7N-j.js} +2 -2
  79. package/dist/chunks/{index-CJeTVskY.js.map → index-C9wf7N-j.js.map} +1 -1
  80. package/dist/chunks/{index-BCWkcyOy.js → index-TqW1pAMX.js} +2 -2
  81. package/dist/chunks/{index-BCWkcyOy.js.map → index-TqW1pAMX.js.map} +1 -1
  82. package/dist/chunks/{version-DkxW4rIi.js → version-Bdrq2emC.js} +2 -2
  83. package/dist/chunks/{version-DkxW4rIi.js.map → version-Bdrq2emC.js.map} +1 -1
  84. package/dist/chunks/{version-CB0Ssm9c.js → version-xpJSWoyH.js} +2 -2
  85. package/dist/chunks/{version-CB0Ssm9c.js.map → version-xpJSWoyH.js.map} +1 -1
  86. package/dist/core.css +68 -209
  87. package/dist/css/web-mojo.css +1 -1
  88. package/dist/docit.cjs.js +1 -1
  89. package/dist/docit.es.js +1 -1
  90. package/dist/index.cjs.js +1 -1
  91. package/dist/index.cjs.js.map +1 -1
  92. package/dist/index.es.js +1 -1
  93. package/dist/index.es.js.map +1 -1
  94. package/dist/lightbox.cjs.js +1 -1
  95. package/dist/lightbox.es.js +1 -1
  96. package/dist/map.cjs.js +1 -1
  97. package/dist/map.es.js +1 -1
  98. package/dist/timeline.cjs.js +1 -1
  99. package/dist/timeline.es.js +1 -1
  100. package/dist/user-profile.cjs.js +1 -1
  101. package/dist/user-profile.es.js +1 -1
  102. package/dist/web-mojo.lite.iife.js +95 -168
  103. package/dist/web-mojo.lite.iife.js.map +1 -1
  104. package/dist/web-mojo.lite.iife.min.js +98 -98
  105. package/dist/web-mojo.lite.iife.min.js.map +1 -1
  106. package/package.json +3 -1
  107. package/dist/chunks/Modal-GWjyfcz5.js +0 -3
  108. package/dist/chunks/Modal-GWjyfcz5.js.map +0 -1
  109. package/dist/chunks/Modal-wrfWfQhv.js +0 -3
  110. package/dist/chunks/Modal-wrfWfQhv.js.map +0 -1
  111. package/dist/chunks/Passkeys-BviQX3_5.js +0 -2
  112. package/dist/chunks/Passkeys-BviQX3_5.js.map +0 -1
  113. package/dist/chunks/Passkeys-gXR1Rc6C.js +0 -2
  114. package/dist/chunks/Passkeys-gXR1Rc6C.js.map +0 -1
  115. package/dist/chunks/TokenManager-C6aXkRaI.js +0 -2
  116. package/dist/chunks/TokenManager-C6aXkRaI.js.map +0 -1
  117. package/dist/chunks/TokenManager-DgvhhTqN.js +0 -2
  118. package/dist/chunks/TokenManager-DgvhhTqN.js.map +0 -1
  119. package/dist/chunks/User-B_Urf7U7.js.map +0 -1
  120. package/dist/chunks/User-KTBU_5cr.js.map +0 -1
@@ -1,2 +1,2 @@
1
- import{U as e,P as t}from"./UserProfileView-COxSyPB0.js";import{a as i,b as s,c as o,d as l,e as a,f as r,g as n,h as c,i as d,j as g,k as f}from"./UserProfileView-COxSyPB0.js";import{V as m}from"./View-Cvs2TY7b.js";import{T as y,f as p,c as b}from"./Passkeys-BviQX3_5.js";class ActivityRow extends b{get logMessage(){const e=this.model?.get("log");if(!e)return"";if("string"==typeof e)try{const t=JSON.parse(e);return t.message||t.type||e.substring(0,120)}catch{return e.length>120?e.substring(0,120)+"…":e}return"object"==typeof e?e.message||e.type||JSON.stringify(e).substring(0,120):String(e)}get levelText(){return this.model?.get("level")||"log"}get levelBadgeClass(){const e=this.model?.get("level");return"error"===e?"bg-danger":"warn"===e?"bg-warning text-dark":"info"===e?"bg-info":"bg-secondary"}get methodPath(){const e=this.model?.get("method")||"",t=this.model?.get("path")||"";return e||t?`${e} ${t}`.trim():""}}class ProfileActivitySection extends m{constructor(e={}){super({className:"profile-activity-section",template:'<div id="activity-table"></div>',...e})}async onInit(){await super.onInit(),this.tableView=new y({containerId:"activity-table",collection:new p({size:10}),defaultQuery:{uid:this.model.id,sort:"-created"},hideActivePillNames:["uid","sort"],itemClass:ActivityRow,columns:[{key:"level",label:"Level",sortable:!0,template:'<span class="badge {{levelBadgeClass}}">{{levelText}}</span>',filter:{type:"select",options:["info","warn","error"]}},{key:"log",label:"Message",template:"{{logMessage}}"},{key:"kind",label:"Kind",sortable:!0,visibility:"md"},{key:"path",label:"Path",visibility:"lg",template:"{{methodPath}}"},{key:"ip",label:"IP",visibility:"xl"},{key:"created|relative",label:"Time",sortable:!0}],searchable:!0,sortable:!0,filterable:!0,paginated:!0,showAdd:!1,showExport:!1,tableOptions:{striped:!1,hover:!0,size:"sm"},emptyMessage:"No activity logs available"}),this.addChild(this.tableView)}}export{t as PasskeySetupView,ProfileActivitySection,i as ProfileApiKeysSection,s as ProfileConnectedSection,o as ProfileDevicesSection,l as ProfileGroupsSection,a as ProfileNotificationsSection,r as ProfileOverviewSection,n as ProfilePermissionsSection,c as ProfilePersonalSection,d as ProfileSecurityEventsSection,g as ProfileSecuritySection,f as ProfileSessionsSection,e as UserProfileView};
2
- //# sourceMappingURL=index-CJeTVskY.js.map
1
+ import{U as e,P as t}from"./UserProfileView-TQ9BqUE2.js";import{a as i,b as s,c as o,d as l,e as a,f as r,g as n,h as c,i as d,j as g,k as f}from"./UserProfileView-TQ9BqUE2.js";import{V as m}from"./View-D6Ug7M6k.js";import{T as y,f as p,c as b}from"./Passkeys-CD8RKUl8.js";class ActivityRow extends b{get logMessage(){const e=this.model?.get("log");if(!e)return"";if("string"==typeof e)try{const t=JSON.parse(e);return t.message||t.type||e.substring(0,120)}catch{return e.length>120?e.substring(0,120)+"…":e}return"object"==typeof e?e.message||e.type||JSON.stringify(e).substring(0,120):String(e)}get levelText(){return this.model?.get("level")||"log"}get levelBadgeClass(){const e=this.model?.get("level");return"error"===e?"bg-danger":"warn"===e?"bg-warning text-dark":"info"===e?"bg-info":"bg-secondary"}get methodPath(){const e=this.model?.get("method")||"",t=this.model?.get("path")||"";return e||t?`${e} ${t}`.trim():""}}class ProfileActivitySection extends m{constructor(e={}){super({className:"profile-activity-section",template:'<div id="activity-table"></div>',...e})}async onInit(){await super.onInit(),this.tableView=new y({containerId:"activity-table",collection:new p({size:10}),defaultQuery:{uid:this.model.id,sort:"-created"},hideActivePillNames:["uid","sort"],itemClass:ActivityRow,columns:[{key:"level",label:"Level",sortable:!0,template:'<span class="badge {{levelBadgeClass}}">{{levelText}}</span>',filter:{type:"select",options:["info","warn","error"]}},{key:"log",label:"Message",template:"{{logMessage}}"},{key:"kind",label:"Kind",sortable:!0,visibility:"md"},{key:"path",label:"Path",visibility:"lg",template:"{{methodPath}}"},{key:"ip",label:"IP",visibility:"xl"},{key:"created|relative",label:"Time",sortable:!0}],searchable:!0,sortable:!0,filterable:!0,paginated:!0,showAdd:!1,showExport:!1,tableOptions:{striped:!1,hover:!0,size:"sm"},emptyMessage:"No activity logs available"}),this.addChild(this.tableView)}}export{t as PasskeySetupView,ProfileActivitySection,i as ProfileApiKeysSection,s as ProfileConnectedSection,o as ProfileDevicesSection,l as ProfileGroupsSection,a as ProfileNotificationsSection,r as ProfileOverviewSection,n as ProfilePermissionsSection,c as ProfilePersonalSection,d as ProfileSecurityEventsSection,g as ProfileSecuritySection,f as ProfileSessionsSection,e as UserProfileView};
2
+ //# sourceMappingURL=index-C9wf7N-j.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-CJeTVskY.js","sources":["../../src/extensions/user-profile/views/ProfileActivitySection.js"],"sourcesContent":["/**\n * ProfileActivitySection - Activity log tab\n *\n * Uses TableView + LogList to show user activity\n * with parsed log messages, level badges, kind, path, and time.\n * Includes pagination, search, and level filtering.\n */\nimport View from '@core/View.js';\nimport TableView from '@core/views/table/TableView.js';\nimport TableRow from '@core/views/table/TableRow.js';\nimport { LogList } from '@core/models/Log.js';\n\nclass ActivityRow extends TableRow {\n get logMessage() {\n const log = this.model?.get('log');\n if (!log) return '';\n if (typeof log === 'string') {\n try {\n const parsed = JSON.parse(log);\n return parsed.message || parsed.type || log.substring(0, 120);\n } catch {\n return log.length > 120 ? log.substring(0, 120) + '…' : log;\n }\n }\n if (typeof log === 'object') {\n return log.message || log.type || JSON.stringify(log).substring(0, 120);\n }\n return String(log);\n }\n\n get levelText() {\n return this.model?.get('level') || 'log';\n }\n\n get levelBadgeClass() {\n const level = this.model?.get('level');\n if (level === 'error') return 'bg-danger';\n if (level === 'warn') return 'bg-warning text-dark';\n if (level === 'info') return 'bg-info';\n return 'bg-secondary';\n }\n\n get methodPath() {\n const method = this.model?.get('method') || '';\n const path = this.model?.get('path') || '';\n if (!method && !path) return '';\n return `${method} ${path}`.trim();\n }\n}\n\nexport default class ProfileActivitySection extends View {\n constructor(options = {}) {\n super({\n className: 'profile-activity-section',\n template: `<div id=\"activity-table\"></div>`,\n ...options\n });\n }\n\n async onInit() {\n await super.onInit();\n this.tableView = new TableView({\n containerId: 'activity-table',\n collection: new LogList({ size: 10 }),\n defaultQuery: { uid: this.model.id, sort: '-created' },\n hideActivePillNames: ['uid', 'sort'],\n itemClass: ActivityRow,\n columns: [\n {\n key: 'level',\n label: 'Level',\n sortable: true,\n template: '<span class=\"badge {{levelBadgeClass}}\">{{levelText}}</span>',\n filter: { type: 'select', options: ['info', 'warn', 'error'] }\n },\n {\n key: 'log',\n label: 'Message',\n template: '{{logMessage}}'\n },\n { key: 'kind', label: 'Kind', sortable: true, visibility: 'md' },\n {\n key: 'path',\n label: 'Path',\n visibility: 'lg',\n template: '{{methodPath}}'\n },\n { key: 'ip', label: 'IP', visibility: 'xl' },\n { key: 'created|relative', label: 'Time', sortable: true }\n ],\n searchable: true,\n sortable: true,\n filterable: true,\n paginated: true,\n showAdd: false,\n showExport: false,\n tableOptions: {\n striped: false,\n hover: true,\n size: 'sm'\n },\n emptyMessage: 'No activity logs available'\n });\n this.addChild(this.tableView);\n }\n}\n"],"names":["ActivityRow","TableRow","logMessage","log","this","model","get","parsed","JSON","parse","message","type","substring","length","stringify","String","levelText","levelBadgeClass","level","methodPath","method","path","trim","ProfileActivitySection","View","constructor","options","super","className","template","onInit","tableView","TableView","containerId","collection","LogList","size","defaultQuery","uid","id","sort","hideActivePillNames","itemClass","columns","key","label","sortable","filter","visibility","searchable","filterable","paginated","showAdd","showExport","tableOptions","striped","hover","emptyMessage","addChild"],"mappings":"iRAYA,MAAMA,oBAAoBC,EACtB,cAAIC,GACA,MAAMC,EAAMC,KAAKC,OAAOC,IAAI,OAC5B,IAAKH,EAAK,MAAO,GACjB,GAAmB,iBAARA,EACP,IACI,MAAMI,EAASC,KAAKC,MAAMN,GAC1B,OAAOI,EAAOG,SAAWH,EAAOI,MAAQR,EAAIS,UAAU,EAAG,IAC7D,CAAA,MACI,OAAOT,EAAIU,OAAS,IAAMV,EAAIS,UAAU,EAAG,KAAO,IAAMT,CAC5D,CAEJ,MAAmB,iBAARA,EACAA,EAAIO,SAAWP,EAAIQ,MAAQH,KAAKM,UAAUX,GAAKS,UAAU,EAAG,KAEhEG,OAAOZ,EAClB,CAEA,aAAIa,GACA,OAAOZ,KAAKC,OAAOC,IAAI,UAAY,KACvC,CAEA,mBAAIW,GACA,MAAMC,EAAQd,KAAKC,OAAOC,IAAI,SAC9B,MAAc,UAAVY,EAA0B,YAChB,SAAVA,EAAyB,uBACf,SAAVA,EAAyB,UACtB,cACX,CAEA,cAAIC,GACA,MAAMC,EAAShB,KAAKC,OAAOC,IAAI,WAAa,GACtCe,EAAOjB,KAAKC,OAAOC,IAAI,SAAW,GACxC,OAAKc,GAAWC,EACT,GAAGD,KAAUC,IAAOC,OADE,EAEjC,EAGW,MAAMC,+BAA+BC,EAChD,WAAAC,CAAYC,EAAU,IAClBC,MAAM,CACFC,UAAW,2BACXC,SAAU,qCACPH,GAEX,CAEA,YAAMI,SACIH,MAAMG,SACZ1B,KAAK2B,UAAY,IAAIC,EAAU,CAC3BC,YAAa,iBACbC,WAAY,IAAIC,EAAQ,CAAEC,KAAM,KAChCC,aAAc,CAAEC,IAAKlC,KAAKC,MAAMkC,GAAIC,KAAM,YAC1CC,oBAAqB,CAAC,MAAO,QAC7BC,UAAW1C,YACX2C,QAAS,CACL,CACIC,IAAK,QACLC,MAAO,QACPC,UAAU,EACVjB,SAAU,+DACVkB,OAAQ,CAAEpC,KAAM,SAAUe,QAAS,CAAC,OAAQ,OAAQ,WAExD,CACIkB,IAAK,MACLC,MAAO,UACPhB,SAAU,kBAEd,CAAEe,IAAK,OAAQC,MAAO,OAAQC,UAAU,EAAME,WAAY,MAC1D,CACIJ,IAAK,OACLC,MAAO,OACPG,WAAY,KACZnB,SAAU,kBAEd,CAAEe,IAAK,KAAMC,MAAO,KAAMG,WAAY,MACtC,CAAEJ,IAAK,mBAAoBC,MAAO,OAAQC,UAAU,IAExDG,YAAY,EACZH,UAAU,EACVI,YAAY,EACZC,WAAW,EACXC,SAAS,EACTC,YAAY,EACZC,aAAc,CACVC,SAAS,EACTC,OAAO,EACPpB,KAAM,MAEVqB,aAAc,+BAElBrD,KAAKsD,SAAStD,KAAK2B,UACvB"}
1
+ {"version":3,"file":"index-C9wf7N-j.js","sources":["../../src/extensions/user-profile/views/ProfileActivitySection.js"],"sourcesContent":["/**\n * ProfileActivitySection - Activity log tab\n *\n * Uses TableView + LogList to show user activity\n * with parsed log messages, level badges, kind, path, and time.\n * Includes pagination, search, and level filtering.\n */\nimport View from '@core/View.js';\nimport TableView from '@core/views/table/TableView.js';\nimport TableRow from '@core/views/table/TableRow.js';\nimport { LogList } from '@core/models/Log.js';\n\nclass ActivityRow extends TableRow {\n get logMessage() {\n const log = this.model?.get('log');\n if (!log) return '';\n if (typeof log === 'string') {\n try {\n const parsed = JSON.parse(log);\n return parsed.message || parsed.type || log.substring(0, 120);\n } catch {\n return log.length > 120 ? log.substring(0, 120) + '…' : log;\n }\n }\n if (typeof log === 'object') {\n return log.message || log.type || JSON.stringify(log).substring(0, 120);\n }\n return String(log);\n }\n\n get levelText() {\n return this.model?.get('level') || 'log';\n }\n\n get levelBadgeClass() {\n const level = this.model?.get('level');\n if (level === 'error') return 'bg-danger';\n if (level === 'warn') return 'bg-warning text-dark';\n if (level === 'info') return 'bg-info';\n return 'bg-secondary';\n }\n\n get methodPath() {\n const method = this.model?.get('method') || '';\n const path = this.model?.get('path') || '';\n if (!method && !path) return '';\n return `${method} ${path}`.trim();\n }\n}\n\nexport default class ProfileActivitySection extends View {\n constructor(options = {}) {\n super({\n className: 'profile-activity-section',\n template: `<div id=\"activity-table\"></div>`,\n ...options\n });\n }\n\n async onInit() {\n await super.onInit();\n this.tableView = new TableView({\n containerId: 'activity-table',\n collection: new LogList({ size: 10 }),\n defaultQuery: { uid: this.model.id, sort: '-created' },\n hideActivePillNames: ['uid', 'sort'],\n itemClass: ActivityRow,\n columns: [\n {\n key: 'level',\n label: 'Level',\n sortable: true,\n template: '<span class=\"badge {{levelBadgeClass}}\">{{levelText}}</span>',\n filter: { type: 'select', options: ['info', 'warn', 'error'] }\n },\n {\n key: 'log',\n label: 'Message',\n template: '{{logMessage}}'\n },\n { key: 'kind', label: 'Kind', sortable: true, visibility: 'md' },\n {\n key: 'path',\n label: 'Path',\n visibility: 'lg',\n template: '{{methodPath}}'\n },\n { key: 'ip', label: 'IP', visibility: 'xl' },\n { key: 'created|relative', label: 'Time', sortable: true }\n ],\n searchable: true,\n sortable: true,\n filterable: true,\n paginated: true,\n showAdd: false,\n showExport: false,\n tableOptions: {\n striped: false,\n hover: true,\n size: 'sm'\n },\n emptyMessage: 'No activity logs available'\n });\n this.addChild(this.tableView);\n }\n}\n"],"names":["ActivityRow","TableRow","logMessage","log","this","model","get","parsed","JSON","parse","message","type","substring","length","stringify","String","levelText","levelBadgeClass","level","methodPath","method","path","trim","ProfileActivitySection","View","constructor","options","super","className","template","onInit","tableView","TableView","containerId","collection","LogList","size","defaultQuery","uid","id","sort","hideActivePillNames","itemClass","columns","key","label","sortable","filter","visibility","searchable","filterable","paginated","showAdd","showExport","tableOptions","striped","hover","emptyMessage","addChild"],"mappings":"iRAYA,MAAMA,oBAAoBC,EACtB,cAAIC,GACA,MAAMC,EAAMC,KAAKC,OAAOC,IAAI,OAC5B,IAAKH,EAAK,MAAO,GACjB,GAAmB,iBAARA,EACP,IACI,MAAMI,EAASC,KAAKC,MAAMN,GAC1B,OAAOI,EAAOG,SAAWH,EAAOI,MAAQR,EAAIS,UAAU,EAAG,IAC7D,CAAA,MACI,OAAOT,EAAIU,OAAS,IAAMV,EAAIS,UAAU,EAAG,KAAO,IAAMT,CAC5D,CAEJ,MAAmB,iBAARA,EACAA,EAAIO,SAAWP,EAAIQ,MAAQH,KAAKM,UAAUX,GAAKS,UAAU,EAAG,KAEhEG,OAAOZ,EAClB,CAEA,aAAIa,GACA,OAAOZ,KAAKC,OAAOC,IAAI,UAAY,KACvC,CAEA,mBAAIW,GACA,MAAMC,EAAQd,KAAKC,OAAOC,IAAI,SAC9B,MAAc,UAAVY,EAA0B,YAChB,SAAVA,EAAyB,uBACf,SAAVA,EAAyB,UACtB,cACX,CAEA,cAAIC,GACA,MAAMC,EAAShB,KAAKC,OAAOC,IAAI,WAAa,GACtCe,EAAOjB,KAAKC,OAAOC,IAAI,SAAW,GACxC,OAAKc,GAAWC,EACT,GAAGD,KAAUC,IAAOC,OADE,EAEjC,EAGW,MAAMC,+BAA+BC,EAChD,WAAAC,CAAYC,EAAU,IAClBC,MAAM,CACFC,UAAW,2BACXC,SAAU,qCACPH,GAEX,CAEA,YAAMI,SACIH,MAAMG,SACZ1B,KAAK2B,UAAY,IAAIC,EAAU,CAC3BC,YAAa,iBACbC,WAAY,IAAIC,EAAQ,CAAEC,KAAM,KAChCC,aAAc,CAAEC,IAAKlC,KAAKC,MAAMkC,GAAIC,KAAM,YAC1CC,oBAAqB,CAAC,MAAO,QAC7BC,UAAW1C,YACX2C,QAAS,CACL,CACIC,IAAK,QACLC,MAAO,QACPC,UAAU,EACVjB,SAAU,+DACVkB,OAAQ,CAAEpC,KAAM,SAAUe,QAAS,CAAC,OAAQ,OAAQ,WAExD,CACIkB,IAAK,MACLC,MAAO,UACPhB,SAAU,kBAEd,CAAEe,IAAK,OAAQC,MAAO,OAAQC,UAAU,EAAME,WAAY,MAC1D,CACIJ,IAAK,OACLC,MAAO,OACPG,WAAY,KACZnB,SAAU,kBAEd,CAAEe,IAAK,KAAMC,MAAO,KAAMG,WAAY,MACtC,CAAEJ,IAAK,mBAAoBC,MAAO,OAAQC,UAAU,IAExDG,YAAY,EACZH,UAAU,EACVI,YAAY,EACZC,WAAW,EACXC,SAAS,EACTC,YAAY,EACZC,aAAc,CACVC,SAAS,EACTC,OAAO,EACPpB,KAAM,MAEVqB,aAAc,+BAElBrD,KAAKsD,SAAStD,KAAK2B,UACvB"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./UserProfileView-BmduMJ86.js"),t=require("./View-C8UWvaSM.js"),i=require("./Passkeys-gXR1Rc6C.js");class ActivityRow extends i.TableRow{get logMessage(){const e=this.model?.get("log");if(!e)return"";if("string"==typeof e)try{const t=JSON.parse(e);return t.message||t.type||e.substring(0,120)}catch{return e.length>120?e.substring(0,120)+"…":e}return"object"==typeof e?e.message||e.type||JSON.stringify(e).substring(0,120):String(e)}get levelText(){return this.model?.get("level")||"log"}get levelBadgeClass(){const e=this.model?.get("level");return"error"===e?"bg-danger":"warn"===e?"bg-warning text-dark":"info"===e?"bg-info":"bg-secondary"}get methodPath(){const e=this.model?.get("method")||"",t=this.model?.get("path")||"";return e||t?`${e} ${t}`.trim():""}}class ProfileActivitySection extends t.View{constructor(e={}){super({className:"profile-activity-section",template:'<div id="activity-table"></div>',...e})}async onInit(){await super.onInit(),this.tableView=new i.TableView({containerId:"activity-table",collection:new i.LogList({size:10}),defaultQuery:{uid:this.model.id,sort:"-created"},hideActivePillNames:["uid","sort"],itemClass:ActivityRow,columns:[{key:"level",label:"Level",sortable:!0,template:'<span class="badge {{levelBadgeClass}}">{{levelText}}</span>',filter:{type:"select",options:["info","warn","error"]}},{key:"log",label:"Message",template:"{{logMessage}}"},{key:"kind",label:"Kind",sortable:!0,visibility:"md"},{key:"path",label:"Path",visibility:"lg",template:"{{methodPath}}"},{key:"ip",label:"IP",visibility:"xl"},{key:"created|relative",label:"Time",sortable:!0}],searchable:!0,sortable:!0,filterable:!0,paginated:!0,showAdd:!1,showExport:!1,tableOptions:{striped:!1,hover:!0,size:"sm"},emptyMessage:"No activity logs available"}),this.addChild(this.tableView)}}exports.PasskeySetupView=e.PasskeySetupView,exports.ProfileApiKeysSection=e.ProfileApiKeysSection,exports.ProfileConnectedSection=e.ProfileConnectedSection,exports.ProfileDevicesSection=e.ProfileDevicesSection,exports.ProfileGroupsSection=e.ProfileGroupsSection,exports.ProfileNotificationsSection=e.ProfileNotificationsSection,exports.ProfileOverviewSection=e.ProfileOverviewSection,exports.ProfilePermissionsSection=e.ProfilePermissionsSection,exports.ProfilePersonalSection=e.ProfilePersonalSection,exports.ProfileSecurityEventsSection=e.ProfileSecurityEventsSection,exports.ProfileSecuritySection=e.ProfileSecuritySection,exports.ProfileSessionsSection=e.ProfileSessionsSection,exports.UserProfileView=e.UserProfileView,exports.ProfileActivitySection=ProfileActivitySection;
2
- //# sourceMappingURL=index-BCWkcyOy.js.map
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./UserProfileView-DC70hRer.js"),t=require("./View-BWOE7WJm.js"),i=require("./Passkeys-8ko7Rg8G.js");class ActivityRow extends i.TableRow{get logMessage(){const e=this.model?.get("log");if(!e)return"";if("string"==typeof e)try{const t=JSON.parse(e);return t.message||t.type||e.substring(0,120)}catch{return e.length>120?e.substring(0,120)+"…":e}return"object"==typeof e?e.message||e.type||JSON.stringify(e).substring(0,120):String(e)}get levelText(){return this.model?.get("level")||"log"}get levelBadgeClass(){const e=this.model?.get("level");return"error"===e?"bg-danger":"warn"===e?"bg-warning text-dark":"info"===e?"bg-info":"bg-secondary"}get methodPath(){const e=this.model?.get("method")||"",t=this.model?.get("path")||"";return e||t?`${e} ${t}`.trim():""}}class ProfileActivitySection extends t.View{constructor(e={}){super({className:"profile-activity-section",template:'<div id="activity-table"></div>',...e})}async onInit(){await super.onInit(),this.tableView=new i.TableView({containerId:"activity-table",collection:new i.LogList({size:10}),defaultQuery:{uid:this.model.id,sort:"-created"},hideActivePillNames:["uid","sort"],itemClass:ActivityRow,columns:[{key:"level",label:"Level",sortable:!0,template:'<span class="badge {{levelBadgeClass}}">{{levelText}}</span>',filter:{type:"select",options:["info","warn","error"]}},{key:"log",label:"Message",template:"{{logMessage}}"},{key:"kind",label:"Kind",sortable:!0,visibility:"md"},{key:"path",label:"Path",visibility:"lg",template:"{{methodPath}}"},{key:"ip",label:"IP",visibility:"xl"},{key:"created|relative",label:"Time",sortable:!0}],searchable:!0,sortable:!0,filterable:!0,paginated:!0,showAdd:!1,showExport:!1,tableOptions:{striped:!1,hover:!0,size:"sm"},emptyMessage:"No activity logs available"}),this.addChild(this.tableView)}}exports.PasskeySetupView=e.PasskeySetupView,exports.ProfileApiKeysSection=e.ProfileApiKeysSection,exports.ProfileConnectedSection=e.ProfileConnectedSection,exports.ProfileDevicesSection=e.ProfileDevicesSection,exports.ProfileGroupsSection=e.ProfileGroupsSection,exports.ProfileNotificationsSection=e.ProfileNotificationsSection,exports.ProfileOverviewSection=e.ProfileOverviewSection,exports.ProfilePermissionsSection=e.ProfilePermissionsSection,exports.ProfilePersonalSection=e.ProfilePersonalSection,exports.ProfileSecurityEventsSection=e.ProfileSecurityEventsSection,exports.ProfileSecuritySection=e.ProfileSecuritySection,exports.ProfileSessionsSection=e.ProfileSessionsSection,exports.UserProfileView=e.UserProfileView,exports.ProfileActivitySection=ProfileActivitySection;
2
+ //# sourceMappingURL=index-TqW1pAMX.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-BCWkcyOy.js","sources":["../../src/extensions/user-profile/views/ProfileActivitySection.js"],"sourcesContent":["/**\n * ProfileActivitySection - Activity log tab\n *\n * Uses TableView + LogList to show user activity\n * with parsed log messages, level badges, kind, path, and time.\n * Includes pagination, search, and level filtering.\n */\nimport View from '@core/View.js';\nimport TableView from '@core/views/table/TableView.js';\nimport TableRow from '@core/views/table/TableRow.js';\nimport { LogList } from '@core/models/Log.js';\n\nclass ActivityRow extends TableRow {\n get logMessage() {\n const log = this.model?.get('log');\n if (!log) return '';\n if (typeof log === 'string') {\n try {\n const parsed = JSON.parse(log);\n return parsed.message || parsed.type || log.substring(0, 120);\n } catch {\n return log.length > 120 ? log.substring(0, 120) + '…' : log;\n }\n }\n if (typeof log === 'object') {\n return log.message || log.type || JSON.stringify(log).substring(0, 120);\n }\n return String(log);\n }\n\n get levelText() {\n return this.model?.get('level') || 'log';\n }\n\n get levelBadgeClass() {\n const level = this.model?.get('level');\n if (level === 'error') return 'bg-danger';\n if (level === 'warn') return 'bg-warning text-dark';\n if (level === 'info') return 'bg-info';\n return 'bg-secondary';\n }\n\n get methodPath() {\n const method = this.model?.get('method') || '';\n const path = this.model?.get('path') || '';\n if (!method && !path) return '';\n return `${method} ${path}`.trim();\n }\n}\n\nexport default class ProfileActivitySection extends View {\n constructor(options = {}) {\n super({\n className: 'profile-activity-section',\n template: `<div id=\"activity-table\"></div>`,\n ...options\n });\n }\n\n async onInit() {\n await super.onInit();\n this.tableView = new TableView({\n containerId: 'activity-table',\n collection: new LogList({ size: 10 }),\n defaultQuery: { uid: this.model.id, sort: '-created' },\n hideActivePillNames: ['uid', 'sort'],\n itemClass: ActivityRow,\n columns: [\n {\n key: 'level',\n label: 'Level',\n sortable: true,\n template: '<span class=\"badge {{levelBadgeClass}}\">{{levelText}}</span>',\n filter: { type: 'select', options: ['info', 'warn', 'error'] }\n },\n {\n key: 'log',\n label: 'Message',\n template: '{{logMessage}}'\n },\n { key: 'kind', label: 'Kind', sortable: true, visibility: 'md' },\n {\n key: 'path',\n label: 'Path',\n visibility: 'lg',\n template: '{{methodPath}}'\n },\n { key: 'ip', label: 'IP', visibility: 'xl' },\n { key: 'created|relative', label: 'Time', sortable: true }\n ],\n searchable: true,\n sortable: true,\n filterable: true,\n paginated: true,\n showAdd: false,\n showExport: false,\n tableOptions: {\n striped: false,\n hover: true,\n size: 'sm'\n },\n emptyMessage: 'No activity logs available'\n });\n this.addChild(this.tableView);\n }\n}\n"],"names":["ActivityRow","TableRow","logMessage","log","this","model","get","parsed","JSON","parse","message","type","substring","length","stringify","String","levelText","levelBadgeClass","level","methodPath","method","path","trim","ProfileActivitySection","View","constructor","options","super","className","template","onInit","tableView","TableView","containerId","collection","LogList","size","defaultQuery","uid","id","sort","hideActivePillNames","itemClass","columns","key","label","sortable","filter","visibility","searchable","filterable","paginated","showAdd","showExport","tableOptions","striped","hover","emptyMessage","addChild"],"mappings":"qMAYA,MAAMA,oBAAoBC,EAAAA,SACtB,cAAIC,GACA,MAAMC,EAAMC,KAAKC,OAAOC,IAAI,OAC5B,IAAKH,EAAK,MAAO,GACjB,GAAmB,iBAARA,EACP,IACI,MAAMI,EAASC,KAAKC,MAAMN,GAC1B,OAAOI,EAAOG,SAAWH,EAAOI,MAAQR,EAAIS,UAAU,EAAG,IAC7D,CAAA,MACI,OAAOT,EAAIU,OAAS,IAAMV,EAAIS,UAAU,EAAG,KAAO,IAAMT,CAC5D,CAEJ,MAAmB,iBAARA,EACAA,EAAIO,SAAWP,EAAIQ,MAAQH,KAAKM,UAAUX,GAAKS,UAAU,EAAG,KAEhEG,OAAOZ,EAClB,CAEA,aAAIa,GACA,OAAOZ,KAAKC,OAAOC,IAAI,UAAY,KACvC,CAEA,mBAAIW,GACA,MAAMC,EAAQd,KAAKC,OAAOC,IAAI,SAC9B,MAAc,UAAVY,EAA0B,YAChB,SAAVA,EAAyB,uBACf,SAAVA,EAAyB,UACtB,cACX,CAEA,cAAIC,GACA,MAAMC,EAAShB,KAAKC,OAAOC,IAAI,WAAa,GACtCe,EAAOjB,KAAKC,OAAOC,IAAI,SAAW,GACxC,OAAKc,GAAWC,EACT,GAAGD,KAAUC,IAAOC,OADE,EAEjC,EAGW,MAAMC,+BAA+BC,EAAAA,KAChD,WAAAC,CAAYC,EAAU,IAClBC,MAAM,CACFC,UAAW,2BACXC,SAAU,qCACPH,GAEX,CAEA,YAAMI,SACIH,MAAMG,SACZ1B,KAAK2B,UAAY,IAAIC,YAAU,CAC3BC,YAAa,iBACbC,WAAY,IAAIC,EAAAA,QAAQ,CAAEC,KAAM,KAChCC,aAAc,CAAEC,IAAKlC,KAAKC,MAAMkC,GAAIC,KAAM,YAC1CC,oBAAqB,CAAC,MAAO,QAC7BC,UAAW1C,YACX2C,QAAS,CACL,CACIC,IAAK,QACLC,MAAO,QACPC,UAAU,EACVjB,SAAU,+DACVkB,OAAQ,CAAEpC,KAAM,SAAUe,QAAS,CAAC,OAAQ,OAAQ,WAExD,CACIkB,IAAK,MACLC,MAAO,UACPhB,SAAU,kBAEd,CAAEe,IAAK,OAAQC,MAAO,OAAQC,UAAU,EAAME,WAAY,MAC1D,CACIJ,IAAK,OACLC,MAAO,OACPG,WAAY,KACZnB,SAAU,kBAEd,CAAEe,IAAK,KAAMC,MAAO,KAAMG,WAAY,MACtC,CAAEJ,IAAK,mBAAoBC,MAAO,OAAQC,UAAU,IAExDG,YAAY,EACZH,UAAU,EACVI,YAAY,EACZC,WAAW,EACXC,SAAS,EACTC,YAAY,EACZC,aAAc,CACVC,SAAS,EACTC,OAAO,EACPpB,KAAM,MAEVqB,aAAc,+BAElBrD,KAAKsD,SAAStD,KAAK2B,UACvB"}
1
+ {"version":3,"file":"index-TqW1pAMX.js","sources":["../../src/extensions/user-profile/views/ProfileActivitySection.js"],"sourcesContent":["/**\n * ProfileActivitySection - Activity log tab\n *\n * Uses TableView + LogList to show user activity\n * with parsed log messages, level badges, kind, path, and time.\n * Includes pagination, search, and level filtering.\n */\nimport View from '@core/View.js';\nimport TableView from '@core/views/table/TableView.js';\nimport TableRow from '@core/views/table/TableRow.js';\nimport { LogList } from '@core/models/Log.js';\n\nclass ActivityRow extends TableRow {\n get logMessage() {\n const log = this.model?.get('log');\n if (!log) return '';\n if (typeof log === 'string') {\n try {\n const parsed = JSON.parse(log);\n return parsed.message || parsed.type || log.substring(0, 120);\n } catch {\n return log.length > 120 ? log.substring(0, 120) + '…' : log;\n }\n }\n if (typeof log === 'object') {\n return log.message || log.type || JSON.stringify(log).substring(0, 120);\n }\n return String(log);\n }\n\n get levelText() {\n return this.model?.get('level') || 'log';\n }\n\n get levelBadgeClass() {\n const level = this.model?.get('level');\n if (level === 'error') return 'bg-danger';\n if (level === 'warn') return 'bg-warning text-dark';\n if (level === 'info') return 'bg-info';\n return 'bg-secondary';\n }\n\n get methodPath() {\n const method = this.model?.get('method') || '';\n const path = this.model?.get('path') || '';\n if (!method && !path) return '';\n return `${method} ${path}`.trim();\n }\n}\n\nexport default class ProfileActivitySection extends View {\n constructor(options = {}) {\n super({\n className: 'profile-activity-section',\n template: `<div id=\"activity-table\"></div>`,\n ...options\n });\n }\n\n async onInit() {\n await super.onInit();\n this.tableView = new TableView({\n containerId: 'activity-table',\n collection: new LogList({ size: 10 }),\n defaultQuery: { uid: this.model.id, sort: '-created' },\n hideActivePillNames: ['uid', 'sort'],\n itemClass: ActivityRow,\n columns: [\n {\n key: 'level',\n label: 'Level',\n sortable: true,\n template: '<span class=\"badge {{levelBadgeClass}}\">{{levelText}}</span>',\n filter: { type: 'select', options: ['info', 'warn', 'error'] }\n },\n {\n key: 'log',\n label: 'Message',\n template: '{{logMessage}}'\n },\n { key: 'kind', label: 'Kind', sortable: true, visibility: 'md' },\n {\n key: 'path',\n label: 'Path',\n visibility: 'lg',\n template: '{{methodPath}}'\n },\n { key: 'ip', label: 'IP', visibility: 'xl' },\n { key: 'created|relative', label: 'Time', sortable: true }\n ],\n searchable: true,\n sortable: true,\n filterable: true,\n paginated: true,\n showAdd: false,\n showExport: false,\n tableOptions: {\n striped: false,\n hover: true,\n size: 'sm'\n },\n emptyMessage: 'No activity logs available'\n });\n this.addChild(this.tableView);\n }\n}\n"],"names":["ActivityRow","TableRow","logMessage","log","this","model","get","parsed","JSON","parse","message","type","substring","length","stringify","String","levelText","levelBadgeClass","level","methodPath","method","path","trim","ProfileActivitySection","View","constructor","options","super","className","template","onInit","tableView","TableView","containerId","collection","LogList","size","defaultQuery","uid","id","sort","hideActivePillNames","itemClass","columns","key","label","sortable","filter","visibility","searchable","filterable","paginated","showAdd","showExport","tableOptions","striped","hover","emptyMessage","addChild"],"mappings":"qMAYA,MAAMA,oBAAoBC,EAAAA,SACtB,cAAIC,GACA,MAAMC,EAAMC,KAAKC,OAAOC,IAAI,OAC5B,IAAKH,EAAK,MAAO,GACjB,GAAmB,iBAARA,EACP,IACI,MAAMI,EAASC,KAAKC,MAAMN,GAC1B,OAAOI,EAAOG,SAAWH,EAAOI,MAAQR,EAAIS,UAAU,EAAG,IAC7D,CAAA,MACI,OAAOT,EAAIU,OAAS,IAAMV,EAAIS,UAAU,EAAG,KAAO,IAAMT,CAC5D,CAEJ,MAAmB,iBAARA,EACAA,EAAIO,SAAWP,EAAIQ,MAAQH,KAAKM,UAAUX,GAAKS,UAAU,EAAG,KAEhEG,OAAOZ,EAClB,CAEA,aAAIa,GACA,OAAOZ,KAAKC,OAAOC,IAAI,UAAY,KACvC,CAEA,mBAAIW,GACA,MAAMC,EAAQd,KAAKC,OAAOC,IAAI,SAC9B,MAAc,UAAVY,EAA0B,YAChB,SAAVA,EAAyB,uBACf,SAAVA,EAAyB,UACtB,cACX,CAEA,cAAIC,GACA,MAAMC,EAAShB,KAAKC,OAAOC,IAAI,WAAa,GACtCe,EAAOjB,KAAKC,OAAOC,IAAI,SAAW,GACxC,OAAKc,GAAWC,EACT,GAAGD,KAAUC,IAAOC,OADE,EAEjC,EAGW,MAAMC,+BAA+BC,EAAAA,KAChD,WAAAC,CAAYC,EAAU,IAClBC,MAAM,CACFC,UAAW,2BACXC,SAAU,qCACPH,GAEX,CAEA,YAAMI,SACIH,MAAMG,SACZ1B,KAAK2B,UAAY,IAAIC,YAAU,CAC3BC,YAAa,iBACbC,WAAY,IAAIC,EAAAA,QAAQ,CAAEC,KAAM,KAChCC,aAAc,CAAEC,IAAKlC,KAAKC,MAAMkC,GAAIC,KAAM,YAC1CC,oBAAqB,CAAC,MAAO,QAC7BC,UAAW1C,YACX2C,QAAS,CACL,CACIC,IAAK,QACLC,MAAO,QACPC,UAAU,EACVjB,SAAU,+DACVkB,OAAQ,CAAEpC,KAAM,SAAUe,QAAS,CAAC,OAAQ,OAAQ,WAExD,CACIkB,IAAK,MACLC,MAAO,UACPhB,SAAU,kBAEd,CAAEe,IAAK,OAAQC,MAAO,OAAQC,UAAU,EAAME,WAAY,MAC1D,CACIJ,IAAK,OACLC,MAAO,OACPG,WAAY,KACZnB,SAAU,kBAEd,CAAEe,IAAK,KAAMC,MAAO,KAAMG,WAAY,MACtC,CAAEJ,IAAK,mBAAoBC,MAAO,OAAQC,UAAU,IAExDG,YAAY,EACZH,UAAU,EACVI,YAAY,EACZC,WAAW,EACXC,SAAS,EACTC,YAAY,EACZC,aAAc,CACVC,SAAS,EACTC,OAAO,EACPpB,KAAM,MAEVqB,aAAc,+BAElBrD,KAAKsD,SAAStD,KAAK2B,UACvB"}
@@ -1,2 +1,2 @@
1
- "use strict";const O="2.3.2",o="2026-05-01T18:05:48.004Z",i={full:O,major:2,minor:3,revision:2,buildTime:o,toString(){return this.full},compare(O){const o=O=>O.split(".").map(Number),[i,r,t]=o(this.full),[e,n,s]=o(O);return i!==e?i-e:r!==n?r-n:t-s}};"undefined"!=typeof window&&(window.MOJO=window.MOJO||{},window.MOJO.VERSION=O,window.MOJO.VERSION_INFO=i,window.MOJO.version=O),exports.BUILD_TIME=o,exports.VERSION=O,exports.VERSION_INFO=i,exports.VERSION_MAJOR=2,exports.VERSION_MINOR=3,exports.VERSION_REVISION=2;
2
- //# sourceMappingURL=version-DkxW4rIi.js.map
1
+ "use strict";const O="2.3.5",o="2026-05-03T23:48:01.374Z",i={full:O,major:2,minor:3,revision:5,buildTime:o,toString(){return this.full},compare(O){const o=O=>O.split(".").map(Number),[i,r,t]=o(this.full),[e,n,s]=o(O);return i!==e?i-e:r!==n?r-n:t-s}};"undefined"!=typeof window&&(window.MOJO=window.MOJO||{},window.MOJO.VERSION=O,window.MOJO.VERSION_INFO=i,window.MOJO.version=O),exports.BUILD_TIME=o,exports.VERSION=O,exports.VERSION_INFO=i,exports.VERSION_MAJOR=2,exports.VERSION_MINOR=3,exports.VERSION_REVISION=5;
2
+ //# sourceMappingURL=version-Bdrq2emC.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version-DkxW4rIi.js","sources":["../../src/version.js"],"sourcesContent":["/**\n * MOJO Framework Version Information\n * Auto-generated on 2026-05-01T18:05:48.004Z\n */\n\nexport const VERSION = '2.3.2';\nexport const VERSION_MAJOR = 2;\nexport const VERSION_MINOR = 3;\nexport const VERSION_REVISION = 2;\nexport const BUILD_TIME = '2026-05-01T18:05:48.004Z';\n\n// Version object for easy access\nexport const VERSION_INFO = {\n full: VERSION,\n major: VERSION_MAJOR,\n minor: VERSION_MINOR,\n revision: VERSION_REVISION,\n buildTime: BUILD_TIME,\n toString() {\n return this.full;\n },\n compare(other) {\n const parseVer = (v) => v.split('.').map(Number);\n const [a1, a2, a3] = parseVer(this.full);\n const [b1, b2, b3] = parseVer(other);\n\n if (a1 !== b1) return a1 - b1;\n if (a2 !== b2) return a2 - b2;\n return a3 - b3;\n }\n};\n\n// Make version globally available if in browser\nif (typeof window !== 'undefined') {\n window.MOJO = window.MOJO || {};\n window.MOJO.VERSION = VERSION;\n window.MOJO.VERSION_INFO = VERSION_INFO;\n\n // Also add to MOJO.version for convenience\n window.MOJO.version = VERSION;\n}\n\nexport default VERSION_INFO;\n"],"names":["VERSION","BUILD_TIME","VERSION_INFO","full","major","minor","revision","buildTime","toString","this","compare","other","parseVer","v","split","map","Number","a1","a2","a3","b1","b2","b3","window","MOJO","version"],"mappings":"aAKY,MAACA,EAAU,QAIVC,EAAa,2BAGbC,EAAe,CACxBC,KAAMH,EACNI,MARyB,EASzBC,MARyB,EASzBC,SAR4B,EAS5BC,UAAWN,EACX,QAAAO,GACI,OAAOC,KAAKN,IAChB,EACA,OAAAO,CAAQC,GACJ,MAAMC,EAAYC,GAAMA,EAAEC,MAAM,KAAKC,IAAIC,SAClCC,EAAIC,EAAIC,GAAMP,EAASH,KAAKN,OAC5BiB,EAAIC,EAAIC,GAAMV,EAASD,GAE9B,OAAIM,IAAOG,EAAWH,EAAKG,EACvBF,IAAOG,EAAWH,EAAKG,EACpBF,EAAKG,CAChB,GAIkB,oBAAXC,SACPA,OAAOC,KAAOD,OAAOC,MAAQ,CAAA,EAC7BD,OAAOC,KAAKxB,QAAUA,EACtBuB,OAAOC,KAAKtB,aAAeA,EAG3BqB,OAAOC,KAAKC,QAAUzB,uFAjCG,wBACA,2BACG"}
1
+ {"version":3,"file":"version-Bdrq2emC.js","sources":["../../src/version.js"],"sourcesContent":["/**\n * MOJO Framework Version Information\n * Auto-generated on 2026-05-03T23:48:01.374Z\n */\n\nexport const VERSION = '2.3.5';\nexport const VERSION_MAJOR = 2;\nexport const VERSION_MINOR = 3;\nexport const VERSION_REVISION = 5;\nexport const BUILD_TIME = '2026-05-03T23:48:01.374Z';\n\n// Version object for easy access\nexport const VERSION_INFO = {\n full: VERSION,\n major: VERSION_MAJOR,\n minor: VERSION_MINOR,\n revision: VERSION_REVISION,\n buildTime: BUILD_TIME,\n toString() {\n return this.full;\n },\n compare(other) {\n const parseVer = (v) => v.split('.').map(Number);\n const [a1, a2, a3] = parseVer(this.full);\n const [b1, b2, b3] = parseVer(other);\n\n if (a1 !== b1) return a1 - b1;\n if (a2 !== b2) return a2 - b2;\n return a3 - b3;\n }\n};\n\n// Make version globally available if in browser\nif (typeof window !== 'undefined') {\n window.MOJO = window.MOJO || {};\n window.MOJO.VERSION = VERSION;\n window.MOJO.VERSION_INFO = VERSION_INFO;\n\n // Also add to MOJO.version for convenience\n window.MOJO.version = VERSION;\n}\n\nexport default VERSION_INFO;\n"],"names":["VERSION","BUILD_TIME","VERSION_INFO","full","major","minor","revision","buildTime","toString","this","compare","other","parseVer","v","split","map","Number","a1","a2","a3","b1","b2","b3","window","MOJO","version"],"mappings":"aAKY,MAACA,EAAU,QAIVC,EAAa,2BAGbC,EAAe,CACxBC,KAAMH,EACNI,MARyB,EASzBC,MARyB,EASzBC,SAR4B,EAS5BC,UAAWN,EACX,QAAAO,GACI,OAAOC,KAAKN,IAChB,EACA,OAAAO,CAAQC,GACJ,MAAMC,EAAYC,GAAMA,EAAEC,MAAM,KAAKC,IAAIC,SAClCC,EAAIC,EAAIC,GAAMP,EAASH,KAAKN,OAC5BiB,EAAIC,EAAIC,GAAMV,EAASD,GAE9B,OAAIM,IAAOG,EAAWH,EAAKG,EACvBF,IAAOG,EAAWH,EAAKG,EACpBF,EAAKG,CAChB,GAIkB,oBAAXC,SACPA,OAAOC,KAAOD,OAAOC,MAAQ,CAAA,EAC7BD,OAAOC,KAAKxB,QAAUA,EACtBuB,OAAOC,KAAKtB,aAAeA,EAG3BqB,OAAOC,KAAKC,QAAUzB,uFAjCG,wBACA,2BACG"}
@@ -1,2 +1,2 @@
1
- const i="2.3.2",n=2,o=3,s=2,O="2026-05-01T18:05:48.004Z",r={full:i,major:2,minor:3,revision:2,buildTime:O,toString(){return this.full},compare(i){const n=i=>i.split(".").map(Number),[o,s,O]=n(this.full),[r,w,e]=n(i);return o!==r?o-r:s!==w?s-w:O-e}};"undefined"!=typeof window&&(window.MOJO=window.MOJO||{},window.MOJO.VERSION=i,window.MOJO.VERSION_INFO=r,window.MOJO.version=i);export{O as B,i as V,r as a,n as b,o as c,s as d};
2
- //# sourceMappingURL=version-CB0Ssm9c.js.map
1
+ const i="2.3.5",n=2,o=3,s=5,O="2026-05-03T23:48:01.374Z",r={full:i,major:2,minor:3,revision:5,buildTime:O,toString(){return this.full},compare(i){const n=i=>i.split(".").map(Number),[o,s,O]=n(this.full),[r,w,e]=n(i);return o!==r?o-r:s!==w?s-w:O-e}};"undefined"!=typeof window&&(window.MOJO=window.MOJO||{},window.MOJO.VERSION=i,window.MOJO.VERSION_INFO=r,window.MOJO.version=i);export{O as B,i as V,r as a,n as b,o as c,s as d};
2
+ //# sourceMappingURL=version-xpJSWoyH.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version-CB0Ssm9c.js","sources":["../../src/version.js"],"sourcesContent":["/**\n * MOJO Framework Version Information\n * Auto-generated on 2026-05-01T18:05:48.004Z\n */\n\nexport const VERSION = '2.3.2';\nexport const VERSION_MAJOR = 2;\nexport const VERSION_MINOR = 3;\nexport const VERSION_REVISION = 2;\nexport const BUILD_TIME = '2026-05-01T18:05:48.004Z';\n\n// Version object for easy access\nexport const VERSION_INFO = {\n full: VERSION,\n major: VERSION_MAJOR,\n minor: VERSION_MINOR,\n revision: VERSION_REVISION,\n buildTime: BUILD_TIME,\n toString() {\n return this.full;\n },\n compare(other) {\n const parseVer = (v) => v.split('.').map(Number);\n const [a1, a2, a3] = parseVer(this.full);\n const [b1, b2, b3] = parseVer(other);\n\n if (a1 !== b1) return a1 - b1;\n if (a2 !== b2) return a2 - b2;\n return a3 - b3;\n }\n};\n\n// Make version globally available if in browser\nif (typeof window !== 'undefined') {\n window.MOJO = window.MOJO || {};\n window.MOJO.VERSION = VERSION;\n window.MOJO.VERSION_INFO = VERSION_INFO;\n\n // Also add to MOJO.version for convenience\n window.MOJO.version = VERSION;\n}\n\nexport default VERSION_INFO;\n"],"names":["VERSION","VERSION_MAJOR","VERSION_MINOR","VERSION_REVISION","BUILD_TIME","VERSION_INFO","full","major","minor","revision","buildTime","toString","this","compare","other","parseVer","v","split","map","Number","a1","a2","a3","b1","b2","b3","window","MOJO","version"],"mappings":"AAKY,MAACA,EAAU,QACVC,EAAgB,EAChBC,EAAgB,EAChBC,EAAmB,EACnBC,EAAa,2BAGbC,EAAe,CACxBC,KAAMN,EACNO,MARyB,EASzBC,MARyB,EASzBC,SAR4B,EAS5BC,UAAWN,EACX,QAAAO,GACI,OAAOC,KAAKN,IAChB,EACA,OAAAO,CAAQC,GACJ,MAAMC,EAAYC,GAAMA,EAAEC,MAAM,KAAKC,IAAIC,SAClCC,EAAIC,EAAIC,GAAMP,EAASH,KAAKN,OAC5BiB,EAAIC,EAAIC,GAAMV,EAASD,GAE9B,OAAIM,IAAOG,EAAWH,EAAKG,EACvBF,IAAOG,EAAWH,EAAKG,EACpBF,EAAKG,CAChB,GAIkB,oBAAXC,SACPA,OAAOC,KAAOD,OAAOC,MAAQ,CAAA,EAC7BD,OAAOC,KAAK3B,QAAUA,EACtB0B,OAAOC,KAAKtB,aAAeA,EAG3BqB,OAAOC,KAAKC,QAAU5B"}
1
+ {"version":3,"file":"version-xpJSWoyH.js","sources":["../../src/version.js"],"sourcesContent":["/**\n * MOJO Framework Version Information\n * Auto-generated on 2026-05-03T23:48:01.374Z\n */\n\nexport const VERSION = '2.3.5';\nexport const VERSION_MAJOR = 2;\nexport const VERSION_MINOR = 3;\nexport const VERSION_REVISION = 5;\nexport const BUILD_TIME = '2026-05-03T23:48:01.374Z';\n\n// Version object for easy access\nexport const VERSION_INFO = {\n full: VERSION,\n major: VERSION_MAJOR,\n minor: VERSION_MINOR,\n revision: VERSION_REVISION,\n buildTime: BUILD_TIME,\n toString() {\n return this.full;\n },\n compare(other) {\n const parseVer = (v) => v.split('.').map(Number);\n const [a1, a2, a3] = parseVer(this.full);\n const [b1, b2, b3] = parseVer(other);\n\n if (a1 !== b1) return a1 - b1;\n if (a2 !== b2) return a2 - b2;\n return a3 - b3;\n }\n};\n\n// Make version globally available if in browser\nif (typeof window !== 'undefined') {\n window.MOJO = window.MOJO || {};\n window.MOJO.VERSION = VERSION;\n window.MOJO.VERSION_INFO = VERSION_INFO;\n\n // Also add to MOJO.version for convenience\n window.MOJO.version = VERSION;\n}\n\nexport default VERSION_INFO;\n"],"names":["VERSION","VERSION_MAJOR","VERSION_MINOR","VERSION_REVISION","BUILD_TIME","VERSION_INFO","full","major","minor","revision","buildTime","toString","this","compare","other","parseVer","v","split","map","Number","a1","a2","a3","b1","b2","b3","window","MOJO","version"],"mappings":"AAKY,MAACA,EAAU,QACVC,EAAgB,EAChBC,EAAgB,EAChBC,EAAmB,EACnBC,EAAa,2BAGbC,EAAe,CACxBC,KAAMN,EACNO,MARyB,EASzBC,MARyB,EASzBC,SAR4B,EAS5BC,UAAWN,EACX,QAAAO,GACI,OAAOC,KAAKN,IAChB,EACA,OAAAO,CAAQC,GACJ,MAAMC,EAAYC,GAAMA,EAAEC,MAAM,KAAKC,IAAIC,SAClCC,EAAIC,EAAIC,GAAMP,EAASH,KAAKN,OAC5BiB,EAAIC,EAAIC,GAAMV,EAASD,GAE9B,OAAIM,IAAOG,EAAWH,EAAKG,EACvBF,IAAOG,EAAWH,EAAKG,EACpBF,EAAKG,CAChB,GAIkB,oBAAXC,SACPA,OAAOC,KAAOD,OAAOC,MAAQ,CAAA,EAC7BD,OAAOC,KAAK3B,QAAUA,EACtB0B,OAAOC,KAAKtB,aAAeA,EAG3BqB,OAAOC,KAAKC,QAAU5B"}
package/dist/core.css CHANGED
@@ -1406,17 +1406,18 @@ button.dropdown-toggle:has(.multiselect-button-text)::after {
1406
1406
  /* ==============================================
1407
1407
  Dialog / Modal Chrome — "Hero Band + Tinted Card"
1408
1408
 
1409
- Direction picked from planning/mockups/modals/05-merged-refined.html.
1410
- - 6px colored hero band along the top of the card carries the type signal
1411
- - Tinted card background (5% accent on white, 10% accent on dark)
1412
- makes the type color felt across the whole surface, not just a stripe
1413
- - Header gets no separate tint the band + card-bg do the work
1414
- - The X close button sits inside the card, top-right
1415
- - Accent color comes from --mojo-dialog-accent (defaults to var(--bs-primary))
1416
- and the four typed variants (success/warning/error/danger) override it.
1417
- Modal.alert sets `modal-alert modal-alert-{type}` on the modal root.
1418
- - Untyped surfaces (Modal.show / Modal.showForm without a type, etc.) inherit
1419
- the default info accent, so every dialog reads as part of the same family.
1409
+ Direction picked from planning/mockups/modals/10-stripe-icon-tint.html.
1410
+ - Default modals = stock Bootstrap. No custom chrome at all.
1411
+ - Typed alerts (modal-alert + modal-alert-{success|warning|error|info})
1412
+ get three layered cues:
1413
+ 1) 4px top accent stripe in the type color (Stripe-style)
1414
+ 2) 1.25rem outline icon next to the title (Modal.alert injects the
1415
+ markup; CSS colors it via --mojo-current-accent)
1416
+ 3) Soft full-card tint (5% light / 10% dark) so the brand color
1417
+ is felt across the whole surface
1418
+ - Bootstrap's native border / radius / shadow / padding tokens drive
1419
+ everything else, so the card looks like a stock Bootstrap 5 modal
1420
+ with three small overlays on typed alerts only.
1420
1421
  ============================================== */
1421
1422
 
1422
1423
  :root {
@@ -1426,29 +1427,7 @@ button.dropdown-toggle:has(.multiselect-button-text)::after {
1426
1427
  --mojo-dialog-error: #dc3545;
1427
1428
  }
1428
1429
 
1429
- /* ── Card chrome ───────────────────────────────────────── */
1430
- /* The default modal eyebrow band is neutral and theme-aware (so it reads as
1431
- structural chrome, not a status signal). Typed alerts (.modal-alert.*)
1432
- override --mojo-current-accent / --mojo-current-tint at higher specificity
1433
- to paint vivid colored bands and tinted card backgrounds.
1434
-
1435
- --mojo-current-accent → band background color
1436
- --mojo-current-eyebrow-fg → eyebrow text color
1437
- --mojo-current-tint → card-background tint (felt across the surface) */
1438
- .modal-content {
1439
- --mojo-current-accent: var(--bs-secondary-bg);
1440
- --mojo-current-eyebrow-fg: var(--bs-secondary-color);
1441
- --mojo-current-tint: var(--mojo-dialog-accent);
1442
- background:
1443
- linear-gradient(
1444
- 180deg,
1445
- color-mix(in srgb, var(--mojo-current-tint) 5%, var(--bs-modal-bg, #fff)) 0%,
1446
- var(--bs-modal-bg, #fff) 100%
1447
- );
1448
- }
1449
-
1450
- /* No header/footer dividers — the band separates header from body, and the
1451
- footer's button cluster anchors itself. Removes Bootstrap's 1px lines. */
1430
+ /* No header/footer dividers modern OS-native sheets don't have them. */
1452
1431
  .modal-header { border-bottom: 0; }
1453
1432
  .modal-footer { border-top: 0; }
1454
1433
 
@@ -1460,50 +1439,63 @@ button.dropdown-toggle:has(.multiselect-button-text)::after {
1460
1439
  box-shadow:
1461
1440
  0 0 0 1px rgba(255, 255, 255, 0.08),
1462
1441
  0 24px 48px -12px rgba(0, 0, 0, 0.7);
1463
- background:
1464
- linear-gradient(
1465
- 180deg,
1466
- color-mix(in srgb, var(--mojo-current-tint) 10%, var(--bs-modal-bg, #14181f)) 0%,
1467
- var(--bs-modal-bg, #14181f) 100%
1468
- );
1469
1442
  }
1470
1443
 
1471
- /* Hero bandsolid colored slab across the top with the eyebrow label
1472
- centered and the close X anchored to the right. Eyebrow text comes from
1473
- `--mojo-eyebrow` (set per-modal). The band's top corners track Bootstrap's
1474
- inner radius so it always matches the card. */
1475
- .modal-content::before {
1476
- content: var(--mojo-eyebrow, "");
1477
- display: flex;
1478
- align-items: center;
1479
- justify-content: center;
1444
+ /* ── Typed alerts chrome scoped strictly to .modal.modal-alert ── */
1445
+
1446
+ /* 4px top accent stripe — Stripe-style. Hugs the card's inner radius so
1447
+ it never squares off against the rounded corners. */
1448
+ .modal.modal-alert .modal-content::before {
1449
+ content: "";
1480
1450
  position: absolute;
1481
1451
  top: 0;
1482
1452
  left: 0;
1483
1453
  right: 0;
1484
- height: 28px;
1485
- padding: 0 1.5rem;
1454
+ height: 4px;
1486
1455
  background: var(--mojo-current-accent);
1487
- color: var(--mojo-current-eyebrow-fg, #fff);
1488
- font-family: ui-monospace, "JetBrains Mono", "SF Mono", "SFMono-Regular", Menlo, Consolas, monospace;
1489
- font-size: 0.6875rem;
1490
- font-weight: 700;
1491
- letter-spacing: 0.16em;
1492
- text-transform: uppercase;
1493
- line-height: 1;
1494
- border-radius: var(--bs-modal-inner-border-radius) var(--bs-modal-inner-border-radius) 0 0;
1456
+ border-top-left-radius: var(--bs-modal-inner-border-radius);
1457
+ border-top-right-radius: var(--bs-modal-inner-border-radius);
1495
1458
  pointer-events: none;
1496
1459
  z-index: 1;
1497
- box-sizing: border-box;
1498
1460
  }
1499
1461
 
1500
- /* The eyebrow text comes from `--mojo-eyebrow` set inline on the modal
1501
- root by each Modal helper (alert / confirm / prompt / show / form / etc.).
1502
- No per-type CSS rules needed — every helper passes its own default. */
1462
+ /* Soft full-card tint felt across the surface without screaming.
1463
+ Light = 5% accent mix, dark = 10% (dark surfaces absorb color). */
1464
+ .modal.modal-alert .modal-content {
1465
+ background:
1466
+ linear-gradient(
1467
+ 180deg,
1468
+ color-mix(in srgb, var(--mojo-current-accent) 5%, var(--bs-modal-bg, #fff)) 0%,
1469
+ var(--bs-modal-bg, #fff) 100%
1470
+ );
1471
+ }
1472
+ [data-bs-theme="dark"] .modal.modal-alert .modal-content {
1473
+ background:
1474
+ linear-gradient(
1475
+ 180deg,
1476
+ color-mix(in srgb, var(--mojo-current-accent) 10%, var(--bs-modal-bg, #14181f)) 0%,
1477
+ var(--bs-modal-bg, #14181f) 100%
1478
+ );
1479
+ }
1503
1480
 
1504
- /* Primary action button picks up the type color so visual hierarchy is
1505
- consistent: red band red button, green band green button, etc.
1506
- --mojo-current-accent cascades from .modal-content. */
1481
+ /* Leading outline icon next to the title. Modal.alert injects
1482
+ <i class="bi bi-{icon} modal-alert-icon"></i> at the start of the title. */
1483
+ .modal-alert-icon {
1484
+ display: inline-block;
1485
+ font-size: 1.25rem;
1486
+ margin-right: 0.625rem;
1487
+ vertical-align: -0.15em;
1488
+ color: var(--mojo-current-accent);
1489
+ flex-shrink: 0;
1490
+ }
1491
+
1492
+ /* Per-type accent color — drives stripe, icon, tint, and primary button. */
1493
+ .modal.modal-alert.modal-alert-info .modal-content { --mojo-current-accent: var(--mojo-dialog-accent); }
1494
+ .modal.modal-alert.modal-alert-success .modal-content { --mojo-current-accent: var(--mojo-dialog-success); }
1495
+ .modal.modal-alert.modal-alert-warning .modal-content { --mojo-current-accent: var(--mojo-dialog-warning); }
1496
+ .modal.modal-alert.modal-alert-error .modal-content { --mojo-current-accent: var(--mojo-dialog-error); }
1497
+
1498
+ /* Primary action button picks up the type color. */
1507
1499
  .modal.modal-alert .modal-footer .btn-primary {
1508
1500
  --bs-btn-bg: var(--mojo-current-accent);
1509
1501
  --bs-btn-border-color: var(--mojo-current-accent);
@@ -1520,147 +1512,24 @@ button.dropdown-toggle:has(.multiselect-button-text)::after {
1520
1512
  --bs-btn-active-color: #1a1a1a;
1521
1513
  }
1522
1514
 
1523
- /* Header bump just the top padding so content clears the 28px band.
1524
- Bootstrap's other padding values (sides, bottom) come through unchanged
1525
- via --bs-modal-header-padding. */
1526
- .modal-header {
1527
- padding-top: calc(1rem + 28px);
1528
- }
1529
-
1530
- /* Close X — anchored to the right side of the hero band itself. The band has
1531
- pointer-events: none; the X sits above it (z-index) so clicks register.
1532
- Color/hover are left to Bootstrap (dark glyph in light mode, white in dark
1533
- via [data-bs-theme="dark"]) — typed alerts override below for the colored
1534
- bands where Bootstrap's default would be too dim. */
1535
- .modal-header .btn-close {
1536
- position: absolute;
1537
- top: 0;
1538
- right: 0.5rem;
1539
- width: 28px;
1540
- height: 28px;
1541
- padding: 0;
1542
- margin: 0;
1543
- background-color: transparent;
1544
- background-size: 10px;
1545
- border-radius: 6px;
1546
- z-index: 2;
1547
- }
1548
-
1549
- /* Typed alerts have a saturated band — force a white X with white-tinted
1550
- hover/focus so the close button reads against the accent color. */
1551
- .modal.modal-alert .modal-header .btn-close {
1552
- filter: brightness(0) invert(1);
1553
- transition: opacity 0.15s ease-in-out, background-color 0.15s ease-in-out;
1554
- }
1555
- .modal.modal-alert .modal-header .btn-close:hover {
1556
- background-color: rgba(255, 255, 255, 0.18);
1557
- }
1558
- .modal.modal-alert .modal-header .btn-close:focus {
1559
- outline: none;
1560
- box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.6);
1561
- }
1562
-
1563
- /* Warning band uses dark text → restore dark X glyph and dark hover tint */
1564
- .modal.modal-alert.modal-alert-warning .modal-header .btn-close {
1565
- filter: none;
1566
- }
1567
- .modal.modal-alert.modal-alert-warning .modal-header .btn-close:hover {
1568
- background-color: rgba(0, 0, 0, 0.1);
1569
- }
1570
-
1571
- /* Modals without a header still need the band to clear the body padding */
1572
- .modal-content > .modal-body:first-child {
1573
- padding-top: calc(1rem + 28px);
1574
- }
1575
-
1576
- /* Edge-to-edge body. Caller (ModalView with noBodyPadding) wants body content
1577
- flush against the modal walls. Top padding is exactly the band height when a
1578
- band is present so content starts right under the band; zero when bandless. */
1515
+ /* Edge-to-edge body. ModalView sets `modal-body-flush` when the caller
1516
+ passes `noBodyPadding: true`. The body paints to the card walls — top,
1517
+ sides, and bottom included. We round the bottom corners to match the
1518
+ card's inner radius so footerless flush bodies don't square off. */
1579
1519
  .modal-content > .modal-body.modal-body-flush {
1580
- padding: 28px 0 0 0;
1581
- }
1582
- .modal.modal-bandless .modal-content > .modal-body.modal-body-flush {
1583
1520
  padding: 0;
1584
1521
  }
1585
- /* Footerless flush body: clip its bottom corners to match Bootstrap's modal
1586
- inner radius so edge-to-edge content doesn't square off against the rounded
1587
- .modal-content. (overflow:hidden is scoped to the body itself — popovers from
1588
- .modal-content can still escape the card.) */
1589
1522
  .modal-content > .modal-body.modal-body-flush:last-child {
1590
1523
  border-bottom-left-radius: var(--bs-modal-inner-border-radius);
1591
1524
  border-bottom-right-radius: var(--bs-modal-inner-border-radius);
1592
1525
  overflow: hidden;
1593
1526
  }
1594
1527
 
1595
- /* Global eyebrow opt-out. Apps that don't want the colored hero band on any
1596
- modal can set `class="mojo-no-eyebrow"` on <html> or <body>. Mirrors the
1597
- per-modal `modal-bandless` rules across every .modal. */
1598
- .mojo-no-eyebrow .modal .modal-content::before { display: none; }
1599
- .mojo-no-eyebrow .modal .modal-header { padding-top: 1rem; }
1600
- .mojo-no-eyebrow .modal .modal-content > .modal-body:first-child { padding-top: 1rem; }
1601
- .mojo-no-eyebrow .modal .modal-content > .modal-body.modal-body-flush { padding: 0; }
1602
- /* No band → restore Bootstrap's default close button (in-flow, default glyph). */
1603
- .mojo-no-eyebrow .modal .modal-header .btn-close {
1604
- position: static;
1605
- width: 1em;
1606
- height: 1em;
1607
- filter: none;
1608
- background-color: transparent;
1609
- }
1610
- [data-bs-theme="dark"] .mojo-no-eyebrow .modal .modal-header .btn-close,
1611
- [data-bs-theme="dark"].mojo-no-eyebrow .modal .modal-header .btn-close {
1612
- filter: var(--bs-btn-close-white-filter);
1613
- }
1614
-
1615
- /* Bandless modals — caller supplied their own header content/view or disabled
1616
- the band per-modal via `eyebrow: false`. ModalView adds `modal-bandless`
1617
- to the .modal root. Hide the band, drop the band-related padding, and
1618
- restore Bootstrap's default close button (otherwise it stays pinned to
1619
- the corner with a white-on-white filter). */
1620
- .modal.modal-bandless .modal-content::before { display: none; }
1621
- .modal.modal-bandless .modal-header { padding-top: 1rem; }
1622
- .modal.modal-bandless .modal-content > .modal-body:first-child { padding-top: 1rem; }
1623
- .modal.modal-bandless .modal-header .btn-close {
1624
- position: static;
1625
- width: 1em;
1626
- height: 1em;
1627
- filter: none;
1628
- background-color: transparent;
1629
- }
1630
- [data-bs-theme="dark"] .modal.modal-bandless .modal-header .btn-close {
1631
- filter: var(--bs-btn-close-white-filter);
1632
- }
1633
-
1634
- /* ── Typed alerts ──────────────────────────────────────────
1635
- Root class (modal-alert modal-alert-{type}) is set by Modal.alert.
1636
- Each type swaps --mojo-current-accent (band/button color) and
1637
- --mojo-current-eyebrow-fg (eyebrow text). Default modals stay neutral. */
1638
-
1639
- .modal.modal-alert .modal-content {
1640
- --mojo-current-accent: var(--mojo-dialog-accent);
1641
- --mojo-current-eyebrow-fg: #fff;
1642
- /* tint defaults to --mojo-dialog-accent already; explicit for typed
1643
- alerts below where band and tint share the same type token */
1644
- }
1645
- .modal.modal-alert.modal-alert-success .modal-content {
1646
- --mojo-current-accent: var(--mojo-dialog-success);
1647
- --mojo-current-tint: var(--mojo-dialog-success);
1648
- }
1649
- .modal.modal-alert.modal-alert-warning .modal-content {
1650
- --mojo-current-accent: var(--mojo-dialog-warning);
1651
- --mojo-current-tint: var(--mojo-dialog-warning);
1652
- --mojo-current-eyebrow-fg: #1a1a1a;
1653
- }
1654
- .modal.modal-alert.modal-alert-error .modal-content {
1655
- --mojo-current-accent: var(--mojo-dialog-error);
1656
- --mojo-current-tint: var(--mojo-dialog-error);
1657
- }
1658
-
1659
- /* Title typography for typed alerts — eyebrow micro-label above headline.
1660
- Both spans live inside Bootstrap's <h5 class="modal-title"> wrapper; we
1661
- reset that h5 so our spans control the styling. */
1528
+ /* Typed-alert title typography let the modal-alert-headline span control
1529
+ the styling instead of Bootstrap's h5 defaults. */
1662
1530
  .modal.modal-alert .modal-title {
1663
- display: block;
1531
+ display: flex;
1532
+ align-items: center;
1664
1533
  font-size: inherit;
1665
1534
  font-weight: inherit;
1666
1535
  line-height: inherit;
@@ -1668,12 +1537,9 @@ button.dropdown-toggle:has(.multiselect-button-text)::after {
1668
1537
  padding-right: 1.75rem; /* clear the close X */
1669
1538
  }
1670
1539
 
1671
- /* Headline = the actual title text. The hero band's eyebrow carries the
1672
- type label; the headline is just the user-supplied title. */
1673
1540
  .modal-alert-headline {
1674
- display: block;
1675
- font-size: 1.125rem;
1676
- font-weight: 700;
1541
+ font-size: 1.0625rem;
1542
+ font-weight: 600;
1677
1543
  letter-spacing: -0.015em;
1678
1544
  line-height: 1.3;
1679
1545
  color: var(--bs-body-color, #212529);
@@ -1686,13 +1552,6 @@ button.dropdown-toggle:has(.multiselect-button-text)::after {
1686
1552
  color: var(--bs-secondary-color, #5b6478);
1687
1553
  }
1688
1554
 
1689
- /* Backwards-compat: any inline `<i class="bi">` still passed in via custom
1690
- title HTML just renders inline (no synthetic colored circle). */
1691
- .modal.modal-alert .modal-title i.bi {
1692
- margin-right: 0.4rem;
1693
- vertical-align: -0.05em;
1694
- }
1695
-
1696
1555
  /* ── Dark mode ─────────────────────────────────────────────
1697
1556
  Brighter accent tokens read against dark surfaces. The modal box-shadow
1698
1557
  is also adjusted in dark mode (see the .modal-content rule near the top)