web-mojo 2.2.100 → 2.2.102

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 (195) hide show
  1. package/CHANGELOG.md +598 -0
  2. package/README.md +2 -2
  3. package/dist/admin-models.cjs.js +2 -0
  4. package/dist/admin-models.cjs.js.map +1 -0
  5. package/dist/admin-models.es.js +2 -0
  6. package/dist/admin-models.es.js.map +1 -0
  7. package/dist/admin.cjs.js +1 -1
  8. package/dist/admin.css +42 -0
  9. package/dist/admin.es.js +1 -1
  10. package/dist/auth.cjs.js +1 -1
  11. package/dist/auth.es.js +1 -1
  12. package/dist/charts.cjs.js +1 -1
  13. package/dist/charts.cjs.js.map +1 -1
  14. package/dist/charts.css +897 -1
  15. package/dist/charts.es.js +1 -1
  16. package/dist/charts.es.js.map +1 -1
  17. package/dist/chat.css +96 -0
  18. package/dist/chunks/AssistantPanelView-CMRTtoqS.js +2 -0
  19. package/dist/chunks/AssistantPanelView-CMRTtoqS.js.map +1 -0
  20. package/dist/chunks/AssistantPanelView-CaVkWhVD.js +2 -0
  21. package/dist/chunks/AssistantPanelView-CaVkWhVD.js.map +1 -0
  22. package/dist/chunks/ChatView-B73uox2v.js +2 -0
  23. package/dist/chunks/ChatView-B73uox2v.js.map +1 -0
  24. package/dist/chunks/ChatView-W8daOwIo.js +2 -0
  25. package/dist/chunks/ChatView-W8daOwIo.js.map +1 -0
  26. package/dist/chunks/Collection-BZlmtcuL.js +2 -0
  27. package/dist/chunks/Collection-BZlmtcuL.js.map +1 -0
  28. package/dist/chunks/Collection-Bwoq6muu.js +2 -0
  29. package/dist/chunks/Collection-Bwoq6muu.js.map +1 -0
  30. package/dist/chunks/ContextMenu-BPPtuqKk.js +2 -0
  31. package/dist/chunks/ContextMenu-BPPtuqKk.js.map +1 -0
  32. package/dist/chunks/ContextMenu-q76hjQb6.js +2 -0
  33. package/dist/chunks/ContextMenu-q76hjQb6.js.map +1 -0
  34. package/dist/chunks/DataView-BbrwHMV4.js +2 -0
  35. package/dist/chunks/{DataView-6lhf855r.js.map → DataView-BbrwHMV4.js.map} +1 -1
  36. package/dist/chunks/DataView-k-7wmk5_.js +2 -0
  37. package/dist/chunks/{DataView-Bb83ww5U.js.map → DataView-k-7wmk5_.js.map} +1 -1
  38. package/dist/chunks/FormView-DPSuwWMq.js +3 -0
  39. package/dist/chunks/{FormView-DEROOklJ.js.map → FormView-DPSuwWMq.js.map} +1 -1
  40. package/dist/chunks/FormView-Dcy7XOtC.js +3 -0
  41. package/dist/chunks/{FormView-UmvPskWT.js.map → FormView-Dcy7XOtC.js.map} +1 -1
  42. package/dist/chunks/ListView-DHC-yBIw.js +2 -0
  43. package/dist/chunks/ListView-DHC-yBIw.js.map +1 -0
  44. package/dist/chunks/ListView-iGBsD4a7.js +2 -0
  45. package/dist/chunks/ListView-iGBsD4a7.js.map +1 -0
  46. package/dist/chunks/MetricsCountryMapView-CAD9wR_T.js +2 -0
  47. package/dist/chunks/MetricsCountryMapView-CAD9wR_T.js.map +1 -0
  48. package/dist/chunks/MetricsCountryMapView-Dzk3Yrzx.js +2 -0
  49. package/dist/chunks/MetricsCountryMapView-Dzk3Yrzx.js.map +1 -0
  50. package/dist/chunks/Modal-DBJU16cc.js +3 -0
  51. package/dist/chunks/Modal-DBJU16cc.js.map +1 -0
  52. package/dist/chunks/Modal-DuULCMFZ.js +3 -0
  53. package/dist/chunks/Modal-DuULCMFZ.js.map +1 -0
  54. package/dist/chunks/Passkeys-CGRZ8ZMv.js +2 -0
  55. package/dist/chunks/{Passkeys-CIRjqi7n.js.map → Passkeys-CGRZ8ZMv.js.map} +1 -1
  56. package/dist/chunks/Passkeys-Dr8-oSm9.js +2 -0
  57. package/dist/chunks/{Passkeys-BPV1gNkR.js.map → Passkeys-Dr8-oSm9.js.map} +1 -1
  58. package/dist/chunks/TokenManager-CFsr1qUV.js +2 -0
  59. package/dist/chunks/TokenManager-CFsr1qUV.js.map +1 -0
  60. package/dist/chunks/TokenManager-CHQxK_e5.js +2 -0
  61. package/dist/chunks/TokenManager-CHQxK_e5.js.map +1 -0
  62. package/dist/chunks/User-DNQhdBtI.js +2 -0
  63. package/dist/chunks/User-DNQhdBtI.js.map +1 -0
  64. package/dist/chunks/User-Dg7xpYEI.js +2 -0
  65. package/dist/chunks/User-Dg7xpYEI.js.map +1 -0
  66. package/dist/chunks/UserProfileView-B5nczdfw.js +2 -0
  67. package/dist/chunks/UserProfileView-B5nczdfw.js.map +1 -0
  68. package/dist/chunks/UserProfileView-Bpz3VZmP.js +2 -0
  69. package/dist/chunks/UserProfileView-Bpz3VZmP.js.map +1 -0
  70. package/dist/chunks/View-C5n3sIFi.js +2 -0
  71. package/dist/chunks/View-C5n3sIFi.js.map +1 -0
  72. package/dist/chunks/View-Yazho7OL.js +2 -0
  73. package/dist/chunks/View-Yazho7OL.js.map +1 -0
  74. package/dist/chunks/WebApp-CeiDNV6L.js +2 -0
  75. package/dist/chunks/WebApp-CeiDNV6L.js.map +1 -0
  76. package/dist/chunks/WebApp-irKlhuFX.js +2 -0
  77. package/dist/chunks/WebApp-irKlhuFX.js.map +1 -0
  78. package/dist/chunks/admin-BkxeK68u.js +2 -0
  79. package/dist/chunks/admin-BkxeK68u.js.map +1 -0
  80. package/dist/chunks/admin-vjoNbv_1.js +2 -0
  81. package/dist/chunks/admin-vjoNbv_1.js.map +1 -0
  82. package/dist/chunks/exportChart-DbsHDCxw.js +2 -0
  83. package/dist/chunks/exportChart-DbsHDCxw.js.map +1 -0
  84. package/dist/chunks/exportChart-Dk8D_du5.js +2 -0
  85. package/dist/chunks/exportChart-Dk8D_du5.js.map +1 -0
  86. package/dist/chunks/index-BNjCQA7q.js +2 -0
  87. package/dist/chunks/{index-CSmG_P2r.js.map → index-BNjCQA7q.js.map} +1 -1
  88. package/dist/chunks/index-DBsIDOAa.js +2 -0
  89. package/dist/chunks/{index-uo77m1wt.js.map → index-DBsIDOAa.js.map} +1 -1
  90. package/dist/chunks/{version-CRfGMZSI.js → version-B0cBv8MN.js} +2 -2
  91. package/dist/chunks/{version-CRfGMZSI.js.map → version-B0cBv8MN.js.map} +1 -1
  92. package/dist/chunks/{version-D-5X69D6.js → version-DtqCY0ZY.js} +2 -2
  93. package/dist/chunks/{version-D-5X69D6.js.map → version-DtqCY0ZY.js.map} +1 -1
  94. package/dist/core.css +306 -0
  95. package/dist/css/web-mojo.css +1 -1
  96. package/dist/docit.cjs.js +1 -1
  97. package/dist/docit.cjs.js.map +1 -1
  98. package/dist/docit.es.js +1 -1
  99. package/dist/docit.es.js.map +1 -1
  100. package/dist/index.cjs.js +1 -1
  101. package/dist/index.cjs.js.map +1 -1
  102. package/dist/index.es.js +1 -1
  103. package/dist/index.es.js.map +1 -1
  104. package/dist/lightbox.cjs.js +1 -1
  105. package/dist/lightbox.cjs.js.map +1 -1
  106. package/dist/lightbox.es.js +1 -1
  107. package/dist/lightbox.es.js.map +1 -1
  108. package/dist/map.cjs.js +1 -1
  109. package/dist/map.cjs.js.map +1 -1
  110. package/dist/map.es.js +1 -1
  111. package/dist/map.es.js.map +1 -1
  112. package/dist/portal.css +86 -0
  113. package/dist/timeline.cjs.js +1 -1
  114. package/dist/timeline.cjs.js.map +1 -1
  115. package/dist/timeline.es.js +1 -1
  116. package/dist/timeline.es.js.map +1 -1
  117. package/dist/user-profile.cjs.js +1 -1
  118. package/dist/user-profile.es.js +1 -1
  119. package/dist/web-mojo.lite.iife.js +4185 -3872
  120. package/dist/web-mojo.lite.iife.js.map +1 -1
  121. package/dist/web-mojo.lite.iife.min.js +301 -323
  122. package/dist/web-mojo.lite.iife.min.js.map +1 -1
  123. package/package.json +7 -2
  124. package/dist/chunks/AssistantPanelView-CZhZmVSG.js +0 -2
  125. package/dist/chunks/AssistantPanelView-CZhZmVSG.js.map +0 -1
  126. package/dist/chunks/AssistantPanelView-WFHYQjq7.js +0 -2
  127. package/dist/chunks/AssistantPanelView-WFHYQjq7.js.map +0 -1
  128. package/dist/chunks/ChatView-Bj3Tvx7a.js +0 -2
  129. package/dist/chunks/ChatView-Bj3Tvx7a.js.map +0 -1
  130. package/dist/chunks/ChatView-Uoqp80PU.js +0 -2
  131. package/dist/chunks/ChatView-Uoqp80PU.js.map +0 -1
  132. package/dist/chunks/Collection-C39Oy2q0.js +0 -2
  133. package/dist/chunks/Collection-C39Oy2q0.js.map +0 -1
  134. package/dist/chunks/Collection-CyK0u557.js +0 -2
  135. package/dist/chunks/Collection-CyK0u557.js.map +0 -1
  136. package/dist/chunks/ContextMenu-D-C7V6J6.js +0 -2
  137. package/dist/chunks/ContextMenu-D-C7V6J6.js.map +0 -1
  138. package/dist/chunks/ContextMenu-hjqR1pGW.js +0 -2
  139. package/dist/chunks/ContextMenu-hjqR1pGW.js.map +0 -1
  140. package/dist/chunks/DataView-6lhf855r.js +0 -2
  141. package/dist/chunks/DataView-Bb83ww5U.js +0 -2
  142. package/dist/chunks/Dialog-B0r9puaZ.js +0 -3
  143. package/dist/chunks/Dialog-B0r9puaZ.js.map +0 -1
  144. package/dist/chunks/Dialog-GzCkpMad.js +0 -3
  145. package/dist/chunks/Dialog-GzCkpMad.js.map +0 -1
  146. package/dist/chunks/FormView-DEROOklJ.js +0 -3
  147. package/dist/chunks/FormView-UmvPskWT.js +0 -3
  148. package/dist/chunks/ListView-D_hOtfWZ.js +0 -2
  149. package/dist/chunks/ListView-D_hOtfWZ.js.map +0 -1
  150. package/dist/chunks/ListView-Jkke6pU1.js +0 -2
  151. package/dist/chunks/ListView-Jkke6pU1.js.map +0 -1
  152. package/dist/chunks/MetricsCountryMapView-UdvJWArx.js +0 -2
  153. package/dist/chunks/MetricsCountryMapView-UdvJWArx.js.map +0 -1
  154. package/dist/chunks/MetricsCountryMapView-jLWCL6Hm.js +0 -2
  155. package/dist/chunks/MetricsCountryMapView-jLWCL6Hm.js.map +0 -1
  156. package/dist/chunks/MetricsMiniChartWidget-CV-McxOl.js +0 -2
  157. package/dist/chunks/MetricsMiniChartWidget-CV-McxOl.js.map +0 -1
  158. package/dist/chunks/MetricsMiniChartWidget-DG0DeDuR.js +0 -2
  159. package/dist/chunks/MetricsMiniChartWidget-DG0DeDuR.js.map +0 -1
  160. package/dist/chunks/MiniPieChart-B3sM4Bjv.js +0 -2
  161. package/dist/chunks/MiniPieChart-B3sM4Bjv.js.map +0 -1
  162. package/dist/chunks/MiniPieChart-DL5Rynvm.js +0 -2
  163. package/dist/chunks/MiniPieChart-DL5Rynvm.js.map +0 -1
  164. package/dist/chunks/MiniSeriesChart-C4DPVbU_.js +0 -2
  165. package/dist/chunks/MiniSeriesChart-C4DPVbU_.js.map +0 -1
  166. package/dist/chunks/MiniSeriesChart-DdNMLwfh.js +0 -2
  167. package/dist/chunks/MiniSeriesChart-DdNMLwfh.js.map +0 -1
  168. package/dist/chunks/Modal-jWZGSSOo.js +0 -2
  169. package/dist/chunks/Modal-jWZGSSOo.js.map +0 -1
  170. package/dist/chunks/Modal-xSaurlfZ.js +0 -2
  171. package/dist/chunks/Modal-xSaurlfZ.js.map +0 -1
  172. package/dist/chunks/Passkeys-BPV1gNkR.js +0 -2
  173. package/dist/chunks/Passkeys-CIRjqi7n.js +0 -2
  174. package/dist/chunks/TokenManager-CKgK0MIz.js +0 -2
  175. package/dist/chunks/TokenManager-CKgK0MIz.js.map +0 -1
  176. package/dist/chunks/TokenManager-Cu0YmxAx.js +0 -2
  177. package/dist/chunks/TokenManager-Cu0YmxAx.js.map +0 -1
  178. package/dist/chunks/UserProfileView-BXT8COCF.js +0 -2
  179. package/dist/chunks/UserProfileView-BXT8COCF.js.map +0 -1
  180. package/dist/chunks/UserProfileView-Slj-9C__.js +0 -2
  181. package/dist/chunks/UserProfileView-Slj-9C__.js.map +0 -1
  182. package/dist/chunks/WebApp-CXkNqtZX.js +0 -2
  183. package/dist/chunks/WebApp-CXkNqtZX.js.map +0 -1
  184. package/dist/chunks/WebApp-m6YeJFWY.js +0 -2
  185. package/dist/chunks/WebApp-m6YeJFWY.js.map +0 -1
  186. package/dist/chunks/WebSocketClient-BQAZr8C4.js +0 -2
  187. package/dist/chunks/WebSocketClient-BQAZr8C4.js.map +0 -1
  188. package/dist/chunks/WebSocketClient-YR5d82h8.js +0 -2
  189. package/dist/chunks/WebSocketClient-YR5d82h8.js.map +0 -1
  190. package/dist/chunks/admin-CpLR06pX.js +0 -2
  191. package/dist/chunks/admin-CpLR06pX.js.map +0 -1
  192. package/dist/chunks/admin-JtLeoEHZ.js +0 -2
  193. package/dist/chunks/admin-JtLeoEHZ.js.map +0 -1
  194. package/dist/chunks/index-CSmG_P2r.js +0 -2
  195. package/dist/chunks/index-uo77m1wt.js +0 -2
package/dist/charts.es.js CHANGED
@@ -1,2 +1,2 @@
1
- import{B as t,M as e,a as s,b as i,c as r,P as o,S as a}from"./chunks/MetricsMiniChartWidget-DG0DeDuR.js";import{V as n,d as h}from"./chunks/Collection-C39Oy2q0.js";import{W as l}from"./chunks/WebApp-CXkNqtZX.js";import{B as c,V as u,a as g,b as d,c as m,d as p}from"./chunks/version-CRfGMZSI.js";class CircularProgress extends n{constructor(t={}){super({className:`circular-progress ${t.className||""}`,...t}),this.SIZE_PRESETS={xs:40,sm:60,md:80,lg:120,xl:180},this.STROKE_PRESETS={xs:4,sm:6,md:8,lg:12,xl:16},this.value=void 0!==t.value?t.value:0,this.min=void 0!==t.min?t.min:0,this.max=void 0!==t.max?t.max:100,this.sizePreset="string"==typeof t.size&&this.SIZE_PRESETS[t.size]?t.size:null,this.size=this.resolveSize(void 0!==t.size?t.size:"md"),this.strokeWidth="auto"===t.strokeWidth||void 0===t.strokeWidth?this.getAutoStrokeWidth(t.size):t.strokeWidth,this.theme=t.theme||"basic",this.variant=t.variant||"default",this.color=t.color,this.trackColor=t.trackColor,this.textColor=t.textColor,this.gradientColors=t.gradientColors||null,this.applyTheme(),this.applyVariant(),this.rotation=void 0!==t.rotation?t.rotation:-90,this.gap=t.gap||0,this.showValue=!1!==t.showValue,this.valueFormat=t.valueFormat||"percentage",this.valueFormatter=t.valueFormatter||null,this.label=t.label||null,this.labelHtml=t.labelHtml||null,this.icon=t.icon||null,this.animate=!1!==t.animate,this.animationDuration=t.animationDuration||600,this.animationEasing=t.animationEasing||"ease-out",this.rounded=!1!==t.rounded,this.shadow=t.shadow||!1,this.clickable=t.clickable||!1,this.tooltip=t.tooltip||null,this.tooltipPlacement=t.tooltipPlacement||"top",this.segments=t.segments||null,this.segmentGap=t.segmentGap||2,this.dataFormatter=h,this.svg=null,this.centerElement=null,this.popover=null,this.gradientId=`gradient-${Math.random().toString(36).substr(2,9)}`}resolveSize(t){return"string"==typeof t&&this.SIZE_PRESETS[t]?this.SIZE_PRESETS[t]:"number"==typeof t?t:this.SIZE_PRESETS.md}getAutoStrokeWidth(t){if("string"==typeof t&&this.STROKE_PRESETS[t])return this.STROKE_PRESETS[t];const e=this.resolveSize(t);return e<=40?4:e<=60?6:e<=80?8:e<=120?12:16}applyTheme(){const t={basic:{trackColor:"#e9ecef",textColor:null,backgroundColor:null},shadowed:{trackColor:"#d1d5db",textColor:null,backgroundColor:null,shadow:!0},dark:{trackColor:"#374151",textColor:"#e5e7eb",backgroundColor:"#1f2937"},light:{trackColor:"#f3f4f6",textColor:"#111827",backgroundColor:"#ffffff"}},e=t[this.theme]||t.basic;this.trackColor||(this.trackColor=e.trackColor),!this.textColor&&e.textColor&&(this.textColor=e.textColor),e.shadow&&!1===this.shadow&&(this.shadow=e.shadow)}applyVariant(){const t={success:{color:"#198754",trackColor:"rgba(25, 135, 84, 0.1)"},danger:{color:"#dc3545",trackColor:"rgba(220, 53, 69, 0.1)"},warning:{color:"#ffc107",trackColor:"rgba(255, 193, 7, 0.1)"},info:{color:"#0dcaf0",trackColor:"rgba(13, 202, 240, 0.1)"},default:{color:"#0d6efd"}};if(t[this.variant]){const e=t[this.variant];this.color||(this.color=e.color),e.trackColor&&this.trackColor===this.applyTheme.trackColor&&(this.trackColor=e.trackColor)}this.color||(this.color="#0d6efd")}getTemplate(){const t=this.sizePreset?`circular-progress-${this.sizePreset}`:"",e="default"!==this.variant?`circular-progress-${this.variant}`:"",s="basic"!==this.theme?`circular-progress-theme-${this.theme}`:"",i=this.clickable?"circular-progress-clickable":"",r=this.shadow?"circular-progress-shadow":"",o=this.textColor?`color: ${this.textColor};`:"";return`\n <div class="circular-progress-container ${t} ${e} ${s} ${i} ${r}"\n style="width: ${this.size}px; height: ${this.size}px;">\n <svg class="circular-progress-svg" \n width="${this.size}" \n height="${this.size}"\n viewBox="0 0 ${this.size} ${this.size}">\n </svg>\n <div class="circular-progress-center" style="${o}">\n <div class="circular-progress-content"></div>\n </div>\n </div>\n `}async onAfterRender(){this.svg=this.element.querySelector(".circular-progress-svg"),this.centerElement=this.element.querySelector(".circular-progress-content"),this.containerElement=this.element.querySelector(".circular-progress-container"),this.renderProgress(),this.renderCenterContent(),this.clickable&&this.setupClickHandler(),this.tooltip&&this.clickable&&this.setupTooltip()}renderProgress(){if(!this.svg)return;this.svg.innerHTML="";const t=this.size/2,e=(this.size-this.strokeWidth)/2,s=2*Math.PI*e;this.gradientColors&&this.gradientColors.length>1&&this.createGradient(),this.segments&&Array.isArray(this.segments)&&this.segments.length>0?this.renderSegments(t,e,s):this.renderSingleProgress(t,e,s)}renderSingleProgress(t,e,s){const i=(this.gap>0?360-this.gap:360)/360*s,r=this.createCircle(t,e,{stroke:this.trackColor,strokeWidth:this.strokeWidth,fill:"none",strokeLinecap:this.rounded?"round":"butt",strokeDasharray:this.gap>0?`${i} ${s}`:"none",transform:`rotate(${this.rotation} ${t} ${t})`});this.svg.appendChild(r);const o=i-this.getPercentage()/100*i,a=this.gradientColors?`url(#${this.gradientId})`:this.color,n=this.createCircle(t,e,{stroke:a,strokeWidth:this.strokeWidth,fill:"none",strokeLinecap:this.rounded?"round":"butt",strokeDasharray:`${i} ${s}`,strokeDashoffset:this.animate?i:o,transform:`rotate(${this.rotation} ${t} ${t})`,class:"circular-progress-bar"});this.svg.appendChild(n),this.animate&&this.animateProgress(n,o)}renderSegments(t,e,s){const i=(this.gap>0?360-this.gap:360)/360*s,r=this.createCircle(t,e,{stroke:this.trackColor,strokeWidth:this.strokeWidth,fill:"none",strokeLinecap:this.rounded?"round":"butt",strokeDasharray:this.gap>0?`${i} ${s}`:"none",transform:`rotate(${this.rotation} ${t} ${t})`});this.svg.appendChild(r),this.segments.reduce((t,e)=>t+(e.value||0),0)>this.max&&console.warn("CircularProgress: Segment total exceeds max value. Clamping to max.");let o=0;this.segments.forEach((r,a)=>{const n=(r.value||0)/(this.max-this.min)*100/100*i,h=this.segmentGap/360*s;if(n>0){const l=this.createCircle(t,e,{stroke:r.color||this.color,strokeWidth:this.strokeWidth,fill:"none",strokeLinecap:this.rounded?"round":"butt",strokeDasharray:`${n} ${s}`,strokeDashoffset:this.animate?i:-o,transform:`rotate(${this.rotation} ${t} ${t})`,class:`circular-progress-segment circular-progress-segment-${a}`,"data-segment-index":a});this.svg.appendChild(l),this.animate&&this.animateProgress(l,-o,100*a),o+=n+h}})}createCircle(t,e,s={}){const i=document.createElementNS("http://www.w3.org/2000/svg","circle");return i.setAttribute("cx",t),i.setAttribute("cy",t),i.setAttribute("r",e),Object.entries(s).forEach(([t,e])=>{"strokeWidth"===t?i.setAttribute("stroke-width",e):"strokeLinecap"===t?i.setAttribute("stroke-linecap",e):"strokeDasharray"===t?i.setAttribute("stroke-dasharray",e):"strokeDashoffset"===t?i.setAttribute("stroke-dashoffset",e):i.setAttribute(t,e)}),i}createGradient(){const t=document.createElementNS("http://www.w3.org/2000/svg","defs"),e=document.createElementNS("http://www.w3.org/2000/svg","linearGradient");e.setAttribute("id",this.gradientId),e.setAttribute("x1","0%"),e.setAttribute("y1","0%"),e.setAttribute("x2","100%"),e.setAttribute("y2","100%"),this.gradientColors.forEach((t,s)=>{const i=document.createElementNS("http://www.w3.org/2000/svg","stop"),r=s/(this.gradientColors.length-1)*100;i.setAttribute("offset",`${r}%`),i.setAttribute("stop-color",t),e.appendChild(i)}),t.appendChild(e),this.svg.appendChild(t)}animateProgress(t,e,s=0){setTimeout(()=>{t.style.transition=`stroke-dashoffset ${this.animationDuration}ms ${this.animationEasing}`,t.style.strokeDashoffset=e},s)}renderCenterContent(){if(this.centerElement)if(this.labelHtml)this.centerElement.innerHTML=this.labelHtml;else if(this.icon)this.centerElement.innerHTML=`<i class="${this.icon}"></i>`;else if(this.showValue){let t=`<div class="circular-progress-value">${this.getFormattedValue()}</div>`;this.label&&(t+=`<div class="circular-progress-label">${this.label}</div>`),this.centerElement.innerHTML=t}}getFormattedValue(){const t=this.value,e=this.min,s=this.max;if(this.valueFormatter&&"function"==typeof this.valueFormatter)return this.valueFormatter(t,e,s);switch(this.valueFormat){case"percentage":return`${Math.round(this.getPercentage())}%`;case"fraction":return`${t}/${s}`;case"value":return t.toString();default:if(this.dataFormatter)try{return this.dataFormatter.pipe(t,this.valueFormat)}catch(i){return console.warn("CircularProgress: DataFormatter error, falling back to percentage",i),`${Math.round(this.getPercentage())}%`}return`${Math.round(this.getPercentage())}%`}}getPercentage(){const t=this.max-this.min;return 0===t?0:(this.value-this.min)/t*100}setupClickHandler(){this.containerElement&&(this.containerElement.style.cursor="pointer",this.containerElement.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation();const e=this.getPercentage();this.emit("progress:clicked",{value:this.value,percentage:e,min:this.min,max:this.max}),this.tooltip&&this.togglePopover()}))}setupTooltip(){}togglePopover(){if(this.containerElement&&void 0!==window.bootstrap){if(!this.popover){const t=this.getTooltipContent(),e="object"==typeof this.tooltip&&this.tooltip.title?this.tooltip.title:void 0,s={content:t,html:!0,placement:this.tooltipPlacement,trigger:"manual",container:"body"};e&&(s.title=e),this.popover=new window.bootstrap.Popover(this.containerElement,s)}window.bootstrap.Popover.getInstance(this.containerElement)&&this.containerElement.getAttribute("aria-describedby")?this.popover.hide():(this.popover.setContent({".popover-body":this.getTooltipContent()}),this.popover.show())}else console.warn("CircularProgress: Bootstrap is required for tooltip support")}getTooltipContent(){return"function"==typeof this.tooltip?this.tooltip(this.value,{min:this.min,max:this.max,percentage:this.getPercentage()}):"object"==typeof this.tooltip?this.tooltip.html||this.tooltip.content||"":this.tooltip||""}setValue(t,e=!0){if(this.value,this.value=Math.max(this.min,Math.min(this.max,t)),this.renderCenterContent(),this.svg&&!this.segments){const t=this.svg.querySelector(".circular-progress-bar");if(t){const s=this.size/2-this.strokeWidth/2,i=2*Math.PI*s,r=(this.gap>0?360-this.gap:360)/360*i,o=r-this.getPercentage()/100*r;e?(t.style.transition=`stroke-dashoffset ${this.animationDuration}ms ${this.animationEasing}`,t.style.strokeDashoffset=o):(t.style.transition="none",t.style.strokeDashoffset=o)}}else{const t=this.animate;this.animate=e,this.renderProgress(),this.animate=t}}setRange(t,e){this.min=t,this.max=e,this.renderProgress(),this.renderCenterContent()}increment(t=1){this.setValue(this.value+t)}decrement(t=1){this.setValue(this.value-t)}setColor(t){if(this.color=t,this.gradientColors=null,this.svg&&!this.segments){const e=this.svg.querySelector(".circular-progress-bar");e&&e.setAttribute("stroke",t)}else this.renderProgress()}setGradient(t){Array.isArray(t)&&t.length>1&&(this.gradientColors=t,this.gradientId=`gradient-${Math.random().toString(36).substr(2,9)}`,this.renderProgress())}setSize(t){this.containerElement&&this.sizePreset&&this.containerElement.classList.remove(`circular-progress-${this.sizePreset}`),this.sizePreset="string"==typeof t&&this.SIZE_PRESETS[t]?t:null,this.size=this.resolveSize(t),this.strokeWidth=this.getAutoStrokeWidth(t),this.containerElement&&(this.containerElement.style.width=`${this.size}px`,this.containerElement.style.height=`${this.size}px`,this.sizePreset&&this.containerElement.classList.add(`circular-progress-${this.sizePreset}`)),this.svg&&(this.svg.setAttribute("width",this.size),this.svg.setAttribute("height",this.size),this.svg.setAttribute("viewBox",`0 0 ${this.size} ${this.size}`)),this.renderProgress()}animateTo(t,e=1e3){const s=this.value,i=t-s,r=performance.now(),o=a=>{const n=a-r,h=Math.min(n/e,1),l=1-Math.pow(1-h,3),c=s+i*l;this.setValue(c,!1),h<1?requestAnimationFrame(o):this.setValue(t,!1)};requestAnimationFrame(o)}pulse(){this.containerElement&&(this.containerElement.style.animation="none",setTimeout(()=>{this.containerElement.style.animation="circular-progress-pulse 0.5s ease-out"},10),setTimeout(()=>{this.containerElement.style.animation=""},500))}complete(){this.variant="success",this.applyVariant(),this.setValue(this.max),this.pulse()}reset(){this.setValue(this.min)}hide(){this.element&&(this.element.style.display="none")}show(){this.element&&(this.element.style.display="")}getValue(){return this.value}getPercentageValue(){return this.getPercentage()}async onBeforeDestroy(){this.popover&&(this.popover.dispose(),this.popover=null),await super.onBeforeDestroy()}}export{c as BUILD_TIME,t as BaseChart,CircularProgress,e as MetricsChart,s as MetricsMiniChart,i as MetricsMiniChartWidget,r as MiniChart,o as PieChart,a as SeriesChart,u as VERSION,g as VERSION_INFO,d as VERSION_MAJOR,m as VERSION_MINOR,p as VERSION_REVISION,l as WebApp};
1
+ import{M as t,a as e,b as s,c as i,P as r,S as o,e as a}from"./chunks/exportChart-DbsHDCxw.js";import{V as n}from"./chunks/View-C5n3sIFi.js";import{d as h}from"./chunks/Collection-Bwoq6muu.js";import{W as l}from"./chunks/WebApp-CeiDNV6L.js";import{B as c,V as u,a as g,b as d,c as m,d as p}from"./chunks/version-B0cBv8MN.js";class CircularProgress extends n{constructor(t={}){super({className:`circular-progress ${t.className||""}`,...t}),this.SIZE_PRESETS={xs:40,sm:60,md:80,lg:120,xl:180},this.STROKE_PRESETS={xs:4,sm:6,md:8,lg:12,xl:16},this.value=void 0!==t.value?t.value:0,this.min=void 0!==t.min?t.min:0,this.max=void 0!==t.max?t.max:100,this.sizePreset="string"==typeof t.size&&this.SIZE_PRESETS[t.size]?t.size:null,this.size=this.resolveSize(void 0!==t.size?t.size:"md"),this.strokeWidth="auto"===t.strokeWidth||void 0===t.strokeWidth?this.getAutoStrokeWidth(t.size):t.strokeWidth,this.theme=t.theme||"basic",this.variant=t.variant||"default",this.color=t.color,this.trackColor=t.trackColor,this.textColor=t.textColor,this.gradientColors=t.gradientColors||null,this.applyTheme(),this.applyVariant(),this.rotation=void 0!==t.rotation?t.rotation:-90,this.gap=t.gap||0,this.showValue=!1!==t.showValue,this.valueFormat=t.valueFormat||"percentage",this.valueFormatter=t.valueFormatter||null,this.label=t.label||null,this.labelHtml=t.labelHtml||null,this.icon=t.icon||null,this.animate=!1!==t.animate,this.animationDuration=t.animationDuration||600,this.animationEasing=t.animationEasing||"ease-out",this.rounded=!1!==t.rounded,this.shadow=t.shadow||!1,this.clickable=t.clickable||!1,this.tooltip=t.tooltip||null,this.tooltipPlacement=t.tooltipPlacement||"top",this.segments=t.segments||null,this.segmentGap=t.segmentGap||2,this.dataFormatter=h,this.svg=null,this.centerElement=null,this.popover=null,this.gradientId=`gradient-${Math.random().toString(36).substr(2,9)}`}resolveSize(t){return"string"==typeof t&&this.SIZE_PRESETS[t]?this.SIZE_PRESETS[t]:"number"==typeof t?t:this.SIZE_PRESETS.md}getAutoStrokeWidth(t){if("string"==typeof t&&this.STROKE_PRESETS[t])return this.STROKE_PRESETS[t];const e=this.resolveSize(t);return e<=40?4:e<=60?6:e<=80?8:e<=120?12:16}applyTheme(){const t={basic:{trackColor:"#e9ecef",textColor:null,backgroundColor:null},shadowed:{trackColor:"#d1d5db",textColor:null,backgroundColor:null,shadow:!0},dark:{trackColor:"#374151",textColor:"#e5e7eb",backgroundColor:"#1f2937"},light:{trackColor:"#f3f4f6",textColor:"#111827",backgroundColor:"#ffffff"}},e=t[this.theme]||t.basic;this.trackColor||(this.trackColor=e.trackColor),!this.textColor&&e.textColor&&(this.textColor=e.textColor),e.shadow&&!1===this.shadow&&(this.shadow=e.shadow)}applyVariant(){const t={success:{color:"#198754",trackColor:"rgba(25, 135, 84, 0.1)"},danger:{color:"#dc3545",trackColor:"rgba(220, 53, 69, 0.1)"},warning:{color:"#ffc107",trackColor:"rgba(255, 193, 7, 0.1)"},info:{color:"#0dcaf0",trackColor:"rgba(13, 202, 240, 0.1)"},default:{color:"#0d6efd"}};if(t[this.variant]){const e=t[this.variant];this.color||(this.color=e.color),e.trackColor&&this.trackColor===this.applyTheme.trackColor&&(this.trackColor=e.trackColor)}this.color||(this.color="#0d6efd")}getTemplate(){const t=this.sizePreset?`circular-progress-${this.sizePreset}`:"",e="default"!==this.variant?`circular-progress-${this.variant}`:"",s="basic"!==this.theme?`circular-progress-theme-${this.theme}`:"",i=this.clickable?"circular-progress-clickable":"",r=this.shadow?"circular-progress-shadow":"",o=this.textColor?`color: ${this.textColor};`:"";return`\n <div class="circular-progress-container ${t} ${e} ${s} ${i} ${r}"\n style="width: ${this.size}px; height: ${this.size}px;">\n <svg class="circular-progress-svg" \n width="${this.size}" \n height="${this.size}"\n viewBox="0 0 ${this.size} ${this.size}">\n </svg>\n <div class="circular-progress-center" style="${o}">\n <div class="circular-progress-content"></div>\n </div>\n </div>\n `}async onAfterRender(){this.svg=this.element.querySelector(".circular-progress-svg"),this.centerElement=this.element.querySelector(".circular-progress-content"),this.containerElement=this.element.querySelector(".circular-progress-container"),this.renderProgress(),this.renderCenterContent(),this.clickable&&this.setupClickHandler(),this.tooltip&&this.clickable&&this.setupTooltip()}renderProgress(){if(!this.svg)return;this.svg.innerHTML="";const t=this.size/2,e=(this.size-this.strokeWidth)/2,s=2*Math.PI*e;this.gradientColors&&this.gradientColors.length>1&&this.createGradient(),this.segments&&Array.isArray(this.segments)&&this.segments.length>0?this.renderSegments(t,e,s):this.renderSingleProgress(t,e,s)}renderSingleProgress(t,e,s){const i=(this.gap>0?360-this.gap:360)/360*s,r=this.createCircle(t,e,{stroke:this.trackColor,strokeWidth:this.strokeWidth,fill:"none",strokeLinecap:this.rounded?"round":"butt",strokeDasharray:this.gap>0?`${i} ${s}`:"none",transform:`rotate(${this.rotation} ${t} ${t})`});this.svg.appendChild(r);const o=i-this.getPercentage()/100*i,a=this.gradientColors?`url(#${this.gradientId})`:this.color,n=this.createCircle(t,e,{stroke:a,strokeWidth:this.strokeWidth,fill:"none",strokeLinecap:this.rounded?"round":"butt",strokeDasharray:`${i} ${s}`,strokeDashoffset:this.animate?i:o,transform:`rotate(${this.rotation} ${t} ${t})`,class:"circular-progress-bar"});this.svg.appendChild(n),this.animate&&this.animateProgress(n,o)}renderSegments(t,e,s){const i=(this.gap>0?360-this.gap:360)/360*s,r=this.createCircle(t,e,{stroke:this.trackColor,strokeWidth:this.strokeWidth,fill:"none",strokeLinecap:this.rounded?"round":"butt",strokeDasharray:this.gap>0?`${i} ${s}`:"none",transform:`rotate(${this.rotation} ${t} ${t})`});this.svg.appendChild(r),this.segments.reduce((t,e)=>t+(e.value||0),0)>this.max&&console.warn("CircularProgress: Segment total exceeds max value. Clamping to max.");let o=0;this.segments.forEach((r,a)=>{const n=(r.value||0)/(this.max-this.min)*100/100*i,h=this.segmentGap/360*s;if(n>0){const l=this.createCircle(t,e,{stroke:r.color||this.color,strokeWidth:this.strokeWidth,fill:"none",strokeLinecap:this.rounded?"round":"butt",strokeDasharray:`${n} ${s}`,strokeDashoffset:this.animate?i:-o,transform:`rotate(${this.rotation} ${t} ${t})`,class:`circular-progress-segment circular-progress-segment-${a}`,"data-segment-index":a});this.svg.appendChild(l),this.animate&&this.animateProgress(l,-o,100*a),o+=n+h}})}createCircle(t,e,s={}){const i=document.createElementNS("http://www.w3.org/2000/svg","circle");return i.setAttribute("cx",t),i.setAttribute("cy",t),i.setAttribute("r",e),Object.entries(s).forEach(([t,e])=>{"strokeWidth"===t?i.setAttribute("stroke-width",e):"strokeLinecap"===t?i.setAttribute("stroke-linecap",e):"strokeDasharray"===t?i.setAttribute("stroke-dasharray",e):"strokeDashoffset"===t?i.setAttribute("stroke-dashoffset",e):i.setAttribute(t,e)}),i}createGradient(){const t=document.createElementNS("http://www.w3.org/2000/svg","defs"),e=document.createElementNS("http://www.w3.org/2000/svg","linearGradient");e.setAttribute("id",this.gradientId),e.setAttribute("x1","0%"),e.setAttribute("y1","0%"),e.setAttribute("x2","100%"),e.setAttribute("y2","100%"),this.gradientColors.forEach((t,s)=>{const i=document.createElementNS("http://www.w3.org/2000/svg","stop"),r=s/(this.gradientColors.length-1)*100;i.setAttribute("offset",`${r}%`),i.setAttribute("stop-color",t),e.appendChild(i)}),t.appendChild(e),this.svg.appendChild(t)}animateProgress(t,e,s=0){setTimeout(()=>{t.style.transition=`stroke-dashoffset ${this.animationDuration}ms ${this.animationEasing}`,t.style.strokeDashoffset=e},s)}renderCenterContent(){if(this.centerElement)if(this.labelHtml)this.centerElement.innerHTML=this.labelHtml;else if(this.icon)this.centerElement.innerHTML=`<i class="${this.icon}"></i>`;else if(this.showValue){let t=`<div class="circular-progress-value">${this.getFormattedValue()}</div>`;this.label&&(t+=`<div class="circular-progress-label">${this.label}</div>`),this.centerElement.innerHTML=t}}getFormattedValue(){const t=this.value,e=this.min,s=this.max;if(this.valueFormatter&&"function"==typeof this.valueFormatter)return this.valueFormatter(t,e,s);switch(this.valueFormat){case"percentage":return`${Math.round(this.getPercentage())}%`;case"fraction":return`${t}/${s}`;case"value":return t.toString();default:if(this.dataFormatter)try{return this.dataFormatter.pipe(t,this.valueFormat)}catch(i){return console.warn("CircularProgress: DataFormatter error, falling back to percentage",i),`${Math.round(this.getPercentage())}%`}return`${Math.round(this.getPercentage())}%`}}getPercentage(){const t=this.max-this.min;return 0===t?0:(this.value-this.min)/t*100}setupClickHandler(){this.containerElement&&(this.containerElement.style.cursor="pointer",this.containerElement.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation();const e=this.getPercentage();this.emit("progress:clicked",{value:this.value,percentage:e,min:this.min,max:this.max}),this.tooltip&&this.togglePopover()}))}setupTooltip(){}togglePopover(){if(this.containerElement&&void 0!==window.bootstrap){if(!this.popover){const t=this.getTooltipContent(),e="object"==typeof this.tooltip&&this.tooltip.title?this.tooltip.title:void 0,s={content:t,html:!0,placement:this.tooltipPlacement,trigger:"manual",container:"body"};e&&(s.title=e),this.popover=new window.bootstrap.Popover(this.containerElement,s)}window.bootstrap.Popover.getInstance(this.containerElement)&&this.containerElement.getAttribute("aria-describedby")?this.popover.hide():(this.popover.setContent({".popover-body":this.getTooltipContent()}),this.popover.show())}else console.warn("CircularProgress: Bootstrap is required for tooltip support")}getTooltipContent(){return"function"==typeof this.tooltip?this.tooltip(this.value,{min:this.min,max:this.max,percentage:this.getPercentage()}):"object"==typeof this.tooltip?this.tooltip.html||this.tooltip.content||"":this.tooltip||""}setValue(t,e=!0){if(this.value,this.value=Math.max(this.min,Math.min(this.max,t)),this.renderCenterContent(),this.svg&&!this.segments){const t=this.svg.querySelector(".circular-progress-bar");if(t){const s=this.size/2-this.strokeWidth/2,i=2*Math.PI*s,r=(this.gap>0?360-this.gap:360)/360*i,o=r-this.getPercentage()/100*r;e?(t.style.transition=`stroke-dashoffset ${this.animationDuration}ms ${this.animationEasing}`,t.style.strokeDashoffset=o):(t.style.transition="none",t.style.strokeDashoffset=o)}}else{const t=this.animate;this.animate=e,this.renderProgress(),this.animate=t}}setRange(t,e){this.min=t,this.max=e,this.renderProgress(),this.renderCenterContent()}increment(t=1){this.setValue(this.value+t)}decrement(t=1){this.setValue(this.value-t)}setColor(t){if(this.color=t,this.gradientColors=null,this.svg&&!this.segments){const e=this.svg.querySelector(".circular-progress-bar");e&&e.setAttribute("stroke",t)}else this.renderProgress()}setGradient(t){Array.isArray(t)&&t.length>1&&(this.gradientColors=t,this.gradientId=`gradient-${Math.random().toString(36).substr(2,9)}`,this.renderProgress())}setSize(t){this.containerElement&&this.sizePreset&&this.containerElement.classList.remove(`circular-progress-${this.sizePreset}`),this.sizePreset="string"==typeof t&&this.SIZE_PRESETS[t]?t:null,this.size=this.resolveSize(t),this.strokeWidth=this.getAutoStrokeWidth(t),this.containerElement&&(this.containerElement.style.width=`${this.size}px`,this.containerElement.style.height=`${this.size}px`,this.sizePreset&&this.containerElement.classList.add(`circular-progress-${this.sizePreset}`)),this.svg&&(this.svg.setAttribute("width",this.size),this.svg.setAttribute("height",this.size),this.svg.setAttribute("viewBox",`0 0 ${this.size} ${this.size}`)),this.renderProgress()}animateTo(t,e=1e3){const s=this.value,i=t-s,r=performance.now(),o=a=>{const n=a-r,h=Math.min(n/e,1),l=1-Math.pow(1-h,3),c=s+i*l;this.setValue(c,!1),h<1?requestAnimationFrame(o):this.setValue(t,!1)};requestAnimationFrame(o)}pulse(){this.containerElement&&(this.containerElement.style.animation="none",setTimeout(()=>{this.containerElement.style.animation="circular-progress-pulse 0.5s ease-out"},10),setTimeout(()=>{this.containerElement.style.animation=""},500))}complete(){this.variant="success",this.applyVariant(),this.setValue(this.max),this.pulse()}reset(){this.setValue(this.min)}hide(){this.element&&(this.element.style.display="none")}show(){this.element&&(this.element.style.display="")}getValue(){return this.value}getPercentageValue(){return this.getPercentage()}async onBeforeDestroy(){this.popover&&(this.popover.dispose(),this.popover=null),await super.onBeforeDestroy()}}export{c as BUILD_TIME,CircularProgress,t as MetricsChart,e as MetricsMiniChart,s as MetricsMiniChartWidget,i as MiniChart,r as PieChart,o as SeriesChart,u as VERSION,g as VERSION_INFO,d as VERSION_MAJOR,m as VERSION_MINOR,p as VERSION_REVISION,l as WebApp,a as exportChartPng};
2
2
  //# sourceMappingURL=charts.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"charts.es.js","sources":["../src/extensions/charts/CircularProgress.js"],"sourcesContent":["/**\n * CircularProgress - Modern circular progress indicator component\n * Supports single/multi-segment progress, animations, gradients, and tooltips\n * Uses SVG for crisp rendering at any size\n */\n\nimport View from '@core/View.js';\nimport dataFormatter from '@core/utils/DataFormatter.js';\n\nexport default class CircularProgress extends View {\n constructor(options = {}) {\n super({\n className: `circular-progress ${options.className || ''}`,\n ...options\n });\n\n // Size presets\n this.SIZE_PRESETS = {\n 'xs': 40,\n 'sm': 60,\n 'md': 80,\n 'lg': 120,\n 'xl': 180\n };\n\n // Stroke width presets (auto-calculated based on size)\n this.STROKE_PRESETS = {\n 'xs': 4,\n 'sm': 6,\n 'md': 8,\n 'lg': 12,\n 'xl': 16\n };\n\n // Core configuration\n this.value = options.value !== undefined ? options.value : 0;\n this.min = options.min !== undefined ? options.min : 0;\n this.max = options.max !== undefined ? options.max : 100;\n\n // Dimensions\n this.sizePreset = (typeof options.size === 'string' && this.SIZE_PRESETS[options.size]) ? options.size : null;\n this.size = this.resolveSize(options.size !== undefined ? options.size : 'md');\n this.strokeWidth = options.strokeWidth === 'auto' || options.strokeWidth === undefined\n ? this.getAutoStrokeWidth(options.size)\n : options.strokeWidth;\n\n // Colors & Styling\n this.theme = options.theme || 'basic'; // 'basic', '3d', 'dark', 'light'\n this.variant = options.variant || 'default';\n this.color = options.color; // Will be set by applyVariant if not provided\n this.trackColor = options.trackColor; // Will be set by applyTheme if not provided\n this.textColor = options.textColor; // Custom text color\n this.gradientColors = options.gradientColors || null;\n\n // Apply theme (sets colors based on theme)\n this.applyTheme();\n \n // Apply variant colors (sets this.color if not provided)\n this.applyVariant();\n\n // Arc configuration\n this.rotation = options.rotation !== undefined ? options.rotation : -90; // Start at top\n this.gap = options.gap || 0; // Gap in degrees (0 = full circle)\n\n // Center content\n this.showValue = options.showValue !== false;\n this.valueFormat = options.valueFormat || 'percentage';\n this.valueFormatter = options.valueFormatter || null;\n this.label = options.label || null;\n this.labelHtml = options.labelHtml || null;\n this.icon = options.icon || null;\n\n // Animation\n this.animate = options.animate !== false;\n this.animationDuration = options.animationDuration || 600;\n this.animationEasing = options.animationEasing || 'ease-out';\n\n // Visual options\n this.rounded = options.rounded !== false;\n this.shadow = options.shadow || false;\n\n // Interaction\n this.clickable = options.clickable || false;\n this.tooltip = options.tooltip || null;\n this.tooltipPlacement = options.tooltipPlacement || 'top';\n\n // Multi-segment mode\n this.segments = options.segments || null;\n this.segmentGap = options.segmentGap || 2; // Gap between segments in degrees\n\n // DataFormatter instance\n this.dataFormatter = dataFormatter;\n\n // Internal state\n this.svg = null;\n this.centerElement = null;\n this.popover = null;\n this.gradientId = `gradient-${Math.random().toString(36).substr(2, 9)}`;\n }\n\n resolveSize(size) {\n if (typeof size === 'string' && this.SIZE_PRESETS[size]) {\n return this.SIZE_PRESETS[size];\n }\n return typeof size === 'number' ? size : this.SIZE_PRESETS.md;\n }\n\n getAutoStrokeWidth(size) {\n if (typeof size === 'string' && this.STROKE_PRESETS[size]) {\n return this.STROKE_PRESETS[size];\n }\n // Auto-calculate based on size\n const actualSize = this.resolveSize(size);\n if (actualSize <= 40) return 4;\n if (actualSize <= 60) return 6;\n if (actualSize <= 80) return 8;\n if (actualSize <= 120) return 12;\n return 16;\n }\n\n applyTheme() {\n const themes = {\n 'basic': {\n trackColor: '#e9ecef',\n textColor: null, // Use default\n backgroundColor: null\n },\n 'shadowed': {\n trackColor: '#d1d5db',\n textColor: null,\n backgroundColor: null,\n shadow: true\n },\n 'dark': {\n trackColor: '#374151',\n textColor: '#e5e7eb',\n backgroundColor: '#1f2937'\n },\n 'light': {\n trackColor: '#f3f4f6',\n textColor: '#111827',\n backgroundColor: '#ffffff'\n }\n };\n\n const themeConfig = themes[this.theme] || themes.basic;\n \n // Apply theme defaults if not explicitly set\n if (!this.trackColor) {\n this.trackColor = themeConfig.trackColor;\n }\n if (!this.textColor && themeConfig.textColor) {\n this.textColor = themeConfig.textColor;\n }\n if (themeConfig.shadow && this.shadow === false) {\n this.shadow = themeConfig.shadow;\n }\n }\n\n applyVariant() {\n const variants = {\n 'success': { color: '#198754', trackColor: 'rgba(25, 135, 84, 0.1)' },\n 'danger': { color: '#dc3545', trackColor: 'rgba(220, 53, 69, 0.1)' },\n 'warning': { color: '#ffc107', trackColor: 'rgba(255, 193, 7, 0.1)' },\n 'info': { color: '#0dcaf0', trackColor: 'rgba(13, 202, 240, 0.1)' },\n 'default': { color: '#0d6efd' } // Default blue color\n };\n\n if (variants[this.variant]) {\n const variantColors = variants[this.variant];\n if (!this.color) {\n this.color = variantColors.color;\n }\n if (variantColors.trackColor && this.trackColor === this.applyTheme.trackColor) {\n this.trackColor = variantColors.trackColor;\n }\n }\n \n // Fallback if no color is set\n if (!this.color) {\n this.color = '#0d6efd';\n }\n }\n\n getTemplate() {\n const sizeClass = this.sizePreset ? `circular-progress-${this.sizePreset}` : '';\n const variantClass = this.variant !== 'default' ? `circular-progress-${this.variant}` : '';\n const themeClass = this.theme !== 'basic' ? `circular-progress-theme-${this.theme}` : '';\n const clickableClass = this.clickable ? 'circular-progress-clickable' : '';\n const shadowClass = this.shadow ? 'circular-progress-shadow' : '';\n \n const textColorStyle = this.textColor ? `color: ${this.textColor};` : '';\n\n return `\n <div class=\"circular-progress-container ${sizeClass} ${variantClass} ${themeClass} ${clickableClass} ${shadowClass}\"\n style=\"width: ${this.size}px; height: ${this.size}px;\">\n <svg class=\"circular-progress-svg\" \n width=\"${this.size}\" \n height=\"${this.size}\"\n viewBox=\"0 0 ${this.size} ${this.size}\">\n </svg>\n <div class=\"circular-progress-center\" style=\"${textColorStyle}\">\n <div class=\"circular-progress-content\"></div>\n </div>\n </div>\n `;\n }\n\n async onAfterRender() {\n this.svg = this.element.querySelector('.circular-progress-svg');\n this.centerElement = this.element.querySelector('.circular-progress-content');\n this.containerElement = this.element.querySelector('.circular-progress-container');\n\n // Render the progress circle\n this.renderProgress();\n\n // Render center content\n this.renderCenterContent();\n\n // Setup interactions\n if (this.clickable) {\n this.setupClickHandler();\n }\n\n // Setup tooltip\n if (this.tooltip && this.clickable) {\n this.setupTooltip();\n }\n }\n\n renderProgress() {\n if (!this.svg) return;\n\n // Clear previous content\n this.svg.innerHTML = '';\n\n const center = this.size / 2;\n const radius = (this.size - this.strokeWidth) / 2;\n const circumference = 2 * Math.PI * radius;\n\n // Create gradient definition if needed\n if (this.gradientColors && this.gradientColors.length > 1) {\n this.createGradient();\n }\n\n // Determine if we're using segments or single progress\n if (this.segments && Array.isArray(this.segments) && this.segments.length > 0) {\n this.renderSegments(center, radius, circumference);\n } else {\n this.renderSingleProgress(center, radius, circumference);\n }\n }\n\n renderSingleProgress(center, radius, circumference) {\n // Calculate arc length\n const arcLength = this.gap > 0 ? (360 - this.gap) : 360;\n const arcCircumference = (arcLength / 360) * circumference;\n\n // Create track (background circle/arc)\n const track = this.createCircle(center, radius, {\n stroke: this.trackColor,\n strokeWidth: this.strokeWidth,\n fill: 'none',\n strokeLinecap: this.rounded ? 'round' : 'butt',\n strokeDasharray: this.gap > 0 ? `${arcCircumference} ${circumference}` : 'none',\n transform: `rotate(${this.rotation} ${center} ${center})`\n });\n this.svg.appendChild(track);\n\n // Create progress circle\n const percentage = this.getPercentage();\n const progressLength = (percentage / 100) * arcCircumference;\n const dashOffset = arcCircumference - progressLength;\n\n const strokeColor = this.gradientColors ? `url(#${this.gradientId})` : this.color;\n\n const progress = this.createCircle(center, radius, {\n stroke: strokeColor,\n strokeWidth: this.strokeWidth,\n fill: 'none',\n strokeLinecap: this.rounded ? 'round' : 'butt',\n strokeDasharray: `${arcCircumference} ${circumference}`,\n strokeDashoffset: this.animate ? arcCircumference : dashOffset,\n transform: `rotate(${this.rotation} ${center} ${center})`,\n class: 'circular-progress-bar'\n });\n\n this.svg.appendChild(progress);\n\n // Apply animation\n if (this.animate) {\n this.animateProgress(progress, dashOffset);\n }\n }\n\n renderSegments(center, radius, circumference) {\n // Calculate arc length\n const arcLength = this.gap > 0 ? (360 - this.gap) : 360;\n const arcCircumference = (arcLength / 360) * circumference;\n\n // Create track\n const track = this.createCircle(center, radius, {\n stroke: this.trackColor,\n strokeWidth: this.strokeWidth,\n fill: 'none',\n strokeLinecap: this.rounded ? 'round' : 'butt',\n strokeDasharray: this.gap > 0 ? `${arcCircumference} ${circumference}` : 'none',\n transform: `rotate(${this.rotation} ${center} ${center})`\n });\n this.svg.appendChild(track);\n\n // Validate segments total\n const total = this.segments.reduce((sum, seg) => sum + (seg.value || 0), 0);\n if (total > this.max) {\n console.warn('CircularProgress: Segment total exceeds max value. Clamping to max.');\n }\n\n // Render each segment\n let currentOffset = 0;\n\n this.segments.forEach((segment, index) => {\n const segmentPercentage = ((segment.value || 0) / (this.max - this.min)) * 100;\n const segmentLength = (segmentPercentage / 100) * arcCircumference;\n\n // Gap between segments (in circumference units)\n const gapLength = (this.segmentGap / 360) * circumference;\n\n if (segmentLength > 0) {\n const segmentCircle = this.createCircle(center, radius, {\n stroke: segment.color || this.color,\n strokeWidth: this.strokeWidth,\n fill: 'none',\n strokeLinecap: this.rounded ? 'round' : 'butt',\n strokeDasharray: `${segmentLength} ${circumference}`,\n strokeDashoffset: this.animate ? arcCircumference : -(currentOffset),\n transform: `rotate(${this.rotation} ${center} ${center})`,\n class: `circular-progress-segment circular-progress-segment-${index}`,\n 'data-segment-index': index\n });\n\n this.svg.appendChild(segmentCircle);\n\n // Apply animation\n if (this.animate) {\n this.animateProgress(segmentCircle, -(currentOffset), index * 100);\n }\n\n // Update offset for next segment\n currentOffset += segmentLength + gapLength;\n }\n });\n }\n\n createCircle(cx, cy, attributes = {}) {\n const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n circle.setAttribute('cx', cx);\n circle.setAttribute('cy', cx); // Use cx for cy since we pass center for both\n circle.setAttribute('r', cy); // cy parameter is actually the radius\n\n Object.entries(attributes).forEach(([key, value]) => {\n if (key === 'strokeWidth') {\n circle.setAttribute('stroke-width', value);\n } else if (key === 'strokeLinecap') {\n circle.setAttribute('stroke-linecap', value);\n } else if (key === 'strokeDasharray') {\n circle.setAttribute('stroke-dasharray', value);\n } else if (key === 'strokeDashoffset') {\n circle.setAttribute('stroke-dashoffset', value);\n } else {\n circle.setAttribute(key, value);\n }\n });\n\n return circle;\n }\n\n createGradient() {\n const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\n const gradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient');\n gradient.setAttribute('id', this.gradientId);\n gradient.setAttribute('x1', '0%');\n gradient.setAttribute('y1', '0%');\n gradient.setAttribute('x2', '100%');\n gradient.setAttribute('y2', '100%');\n\n this.gradientColors.forEach((color, index) => {\n const stop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\n const offset = (index / (this.gradientColors.length - 1)) * 100;\n stop.setAttribute('offset', `${offset}%`);\n stop.setAttribute('stop-color', color);\n gradient.appendChild(stop);\n });\n\n defs.appendChild(gradient);\n this.svg.appendChild(defs);\n }\n\n animateProgress(circle, targetOffset, delay = 0) {\n setTimeout(() => {\n circle.style.transition = `stroke-dashoffset ${this.animationDuration}ms ${this.animationEasing}`;\n circle.style.strokeDashoffset = targetOffset;\n }, delay);\n }\n\n renderCenterContent() {\n if (!this.centerElement) return;\n\n // Priority: labelHtml > icon > value/label\n if (this.labelHtml) {\n this.centerElement.innerHTML = this.labelHtml;\n } else if (this.icon) {\n this.centerElement.innerHTML = `<i class=\"${this.icon}\"></i>`;\n } else if (this.showValue) {\n const formattedValue = this.getFormattedValue();\n let html = `<div class=\"circular-progress-value\">${formattedValue}</div>`;\n \n if (this.label) {\n html += `<div class=\"circular-progress-label\">${this.label}</div>`;\n }\n\n this.centerElement.innerHTML = html;\n }\n }\n\n getFormattedValue() {\n const value = this.value;\n const min = this.min;\n const max = this.max;\n\n // Custom formatter function takes precedence\n if (this.valueFormatter && typeof this.valueFormatter === 'function') {\n return this.valueFormatter(value, min, max);\n }\n\n // Built-in formats\n switch (this.valueFormat) {\n case 'percentage':\n return `${Math.round(this.getPercentage())}%`;\n \n case 'fraction':\n return `${value}/${max}`;\n \n case 'value':\n return value.toString();\n \n default:\n // Try DataFormatter\n if (this.dataFormatter) {\n try {\n return this.dataFormatter.pipe(value, this.valueFormat);\n } catch (error) {\n console.warn('CircularProgress: DataFormatter error, falling back to percentage', error);\n return `${Math.round(this.getPercentage())}%`;\n }\n }\n return `${Math.round(this.getPercentage())}%`;\n }\n }\n\n getPercentage() {\n const range = this.max - this.min;\n if (range === 0) return 0;\n return ((this.value - this.min) / range) * 100;\n }\n\n setupClickHandler() {\n if (!this.containerElement) return;\n\n this.containerElement.style.cursor = 'pointer';\n \n this.containerElement.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n\n const percentage = this.getPercentage();\n \n this.emit('progress:clicked', {\n value: this.value,\n percentage,\n min: this.min,\n max: this.max\n });\n\n // Toggle popover if tooltip is configured\n if (this.tooltip) {\n this.togglePopover();\n }\n });\n }\n\n setupTooltip() {\n // Bootstrap popover will be initialized on first click\n // We'll create the popover content dynamically\n }\n\n togglePopover() {\n if (!this.containerElement || typeof window.bootstrap === 'undefined') {\n console.warn('CircularProgress: Bootstrap is required for tooltip support');\n return;\n }\n\n // Get or create popover instance\n if (!this.popover) {\n const content = this.getTooltipContent();\n const title = typeof this.tooltip === 'object' && this.tooltip.title ? this.tooltip.title : undefined;\n\n // Build config object, omitting title if undefined\n const popoverConfig = {\n content: content,\n html: true,\n placement: this.tooltipPlacement,\n trigger: 'manual',\n container: 'body'\n };\n \n // Only add title if it exists\n if (title) {\n popoverConfig.title = title;\n }\n\n this.popover = new window.bootstrap.Popover(this.containerElement, popoverConfig);\n }\n\n // Toggle visibility\n const popoverElement = window.bootstrap.Popover.getInstance(this.containerElement);\n if (popoverElement && this.containerElement.getAttribute('aria-describedby')) {\n this.popover.hide();\n } else {\n // Update content before showing\n this.popover.setContent({\n '.popover-body': this.getTooltipContent()\n });\n this.popover.show();\n }\n }\n\n getTooltipContent() {\n if (typeof this.tooltip === 'function') {\n return this.tooltip(this.value, {\n min: this.min,\n max: this.max,\n percentage: this.getPercentage()\n });\n }\n\n if (typeof this.tooltip === 'object') {\n return this.tooltip.html || this.tooltip.content || '';\n }\n\n return this.tooltip || '';\n }\n\n // Public API\n\n setValue(value, animate = true) {\n const oldValue = this.value;\n this.value = Math.max(this.min, Math.min(this.max, value));\n \n // Update center content\n this.renderCenterContent();\n \n // Update progress without full re-render\n if (this.svg && !this.segments) {\n const progressBar = this.svg.querySelector('.circular-progress-bar');\n if (progressBar) {\n const radius = (this.size / 2) - (this.strokeWidth / 2);\n const circumference = 2 * Math.PI * radius;\n const arcLength = this.gap > 0 ? (360 - this.gap) : 360;\n const arcCircumference = (arcLength / 360) * circumference;\n const percentage = this.getPercentage();\n const progressLength = (percentage / 100) * arcCircumference;\n const dashOffset = arcCircumference - progressLength;\n \n if (animate) {\n // Animate from current offset to new offset\n progressBar.style.transition = `stroke-dashoffset ${this.animationDuration}ms ${this.animationEasing}`;\n progressBar.style.strokeDashoffset = dashOffset;\n } else {\n // Update immediately without animation\n progressBar.style.transition = 'none';\n progressBar.style.strokeDashoffset = dashOffset;\n }\n }\n } else {\n // For segments or if no existing progress bar, do full re-render\n const oldAnimate = this.animate;\n this.animate = animate;\n this.renderProgress();\n this.animate = oldAnimate;\n }\n }\n\n setRange(min, max) {\n this.min = min;\n this.max = max;\n this.renderProgress();\n this.renderCenterContent();\n }\n\n increment(amount = 1) {\n this.setValue(this.value + amount);\n }\n\n decrement(amount = 1) {\n this.setValue(this.value - amount);\n }\n\n setColor(color) {\n this.color = color;\n this.gradientColors = null; // Clear gradient\n \n // Update color without full re-render\n if (this.svg && !this.segments) {\n const progressBar = this.svg.querySelector('.circular-progress-bar');\n if (progressBar) {\n progressBar.setAttribute('stroke', color);\n }\n } else {\n // For segments, need to re-render\n this.renderProgress();\n }\n }\n\n setGradient(colors) {\n if (Array.isArray(colors) && colors.length > 1) {\n this.gradientColors = colors;\n this.gradientId = `gradient-${Math.random().toString(36).substr(2, 9)}`;\n this.renderProgress();\n }\n }\n\n setSize(size) {\n // Remove old size class if it exists\n if (this.containerElement && this.sizePreset) {\n this.containerElement.classList.remove(`circular-progress-${this.sizePreset}`);\n }\n \n // Update size preset if the new size is a preset string\n this.sizePreset = (typeof size === 'string' && this.SIZE_PRESETS[size]) ? size : null;\n this.size = this.resolveSize(size);\n this.strokeWidth = this.getAutoStrokeWidth(size);\n \n // Add new size class if it's a preset\n if (this.containerElement) {\n this.containerElement.style.width = `${this.size}px`;\n this.containerElement.style.height = `${this.size}px`;\n \n if (this.sizePreset) {\n this.containerElement.classList.add(`circular-progress-${this.sizePreset}`);\n }\n }\n \n if (this.svg) {\n this.svg.setAttribute('width', this.size);\n this.svg.setAttribute('height', this.size);\n this.svg.setAttribute('viewBox', `0 0 ${this.size} ${this.size}`);\n }\n \n this.renderProgress();\n }\n\n animateTo(targetValue, duration = 1000) {\n const startValue = this.value;\n const diff = targetValue - startValue;\n const startTime = performance.now();\n\n const animate = (currentTime) => {\n const elapsed = currentTime - startTime;\n const progress = Math.min(elapsed / duration, 1);\n\n // Ease-out function\n const easeProgress = 1 - Math.pow(1 - progress, 3);\n \n const newValue = startValue + (diff * easeProgress);\n this.setValue(newValue, false);\n\n if (progress < 1) {\n requestAnimationFrame(animate);\n } else {\n this.setValue(targetValue, false);\n }\n };\n\n requestAnimationFrame(animate);\n }\n\n pulse() {\n if (!this.containerElement) return;\n\n this.containerElement.style.animation = 'none';\n setTimeout(() => {\n this.containerElement.style.animation = 'circular-progress-pulse 0.5s ease-out';\n }, 10);\n\n setTimeout(() => {\n this.containerElement.style.animation = '';\n }, 500);\n }\n\n complete() {\n this.variant = 'success';\n this.applyVariant();\n this.setValue(this.max);\n this.pulse();\n }\n\n reset() {\n this.setValue(this.min);\n }\n\n hide() {\n if (this.element) {\n this.element.style.display = 'none';\n }\n }\n\n show() {\n if (this.element) {\n this.element.style.display = '';\n }\n }\n\n getValue() {\n return this.value;\n }\n\n getPercentageValue() {\n return this.getPercentage();\n }\n\n async onBeforeDestroy() {\n // Clean up popover\n if (this.popover) {\n this.popover.dispose();\n this.popover = null;\n }\n\n await super.onBeforeDestroy();\n }\n}\n"],"names":["CircularProgress","View","constructor","options","super","className","this","SIZE_PRESETS","xs","sm","md","lg","xl","STROKE_PRESETS","value","min","max","sizePreset","size","resolveSize","strokeWidth","getAutoStrokeWidth","theme","variant","color","trackColor","textColor","gradientColors","applyTheme","applyVariant","rotation","gap","showValue","valueFormat","valueFormatter","label","labelHtml","icon","animate","animationDuration","animationEasing","rounded","shadow","clickable","tooltip","tooltipPlacement","segments","segmentGap","dataFormatter","svg","centerElement","popover","gradientId","Math","random","toString","substr","actualSize","themes","basic","backgroundColor","shadowed","dark","light","themeConfig","variants","success","danger","warning","info","default","variantColors","getTemplate","sizeClass","variantClass","themeClass","clickableClass","shadowClass","textColorStyle","onAfterRender","element","querySelector","containerElement","renderProgress","renderCenterContent","setupClickHandler","setupTooltip","innerHTML","center","radius","circumference","PI","length","createGradient","Array","isArray","renderSegments","renderSingleProgress","arcCircumference","track","createCircle","stroke","fill","strokeLinecap","strokeDasharray","transform","appendChild","dashOffset","getPercentage","strokeColor","progress","strokeDashoffset","class","animateProgress","reduce","sum","seg","console","warn","currentOffset","forEach","segment","index","segmentLength","gapLength","segmentCircle","cx","cy","attributes","circle","document","createElementNS","setAttribute","Object","entries","key","defs","gradient","stop","offset","targetOffset","delay","setTimeout","style","transition","html","getFormattedValue","round","pipe","error","range","cursor","addEventListener","e","preventDefault","stopPropagation","percentage","emit","togglePopover","window","bootstrap","content","getTooltipContent","title","popoverConfig","placement","trigger","container","Popover","getInstance","getAttribute","hide","setContent","show","setValue","progressBar","oldAnimate","setRange","increment","amount","decrement","setColor","setGradient","colors","setSize","classList","remove","width","height","add","animateTo","targetValue","duration","startValue","diff","startTime","performance","now","currentTime","elapsed","easeProgress","pow","newValue","requestAnimationFrame","pulse","animation","complete","reset","display","getValue","getPercentageValue","onBeforeDestroy","dispose"],"mappings":"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"}
1
+ {"version":3,"file":"charts.es.js","sources":["../src/extensions/charts/CircularProgress.js"],"sourcesContent":["/**\n * CircularProgress - Modern circular progress indicator component\n * Supports single/multi-segment progress, animations, gradients, and tooltips\n * Uses SVG for crisp rendering at any size\n */\n\nimport View from '@core/View.js';\nimport dataFormatter from '@core/utils/DataFormatter.js';\n\nexport default class CircularProgress extends View {\n constructor(options = {}) {\n super({\n className: `circular-progress ${options.className || ''}`,\n ...options\n });\n\n // Size presets\n this.SIZE_PRESETS = {\n 'xs': 40,\n 'sm': 60,\n 'md': 80,\n 'lg': 120,\n 'xl': 180\n };\n\n // Stroke width presets (auto-calculated based on size)\n this.STROKE_PRESETS = {\n 'xs': 4,\n 'sm': 6,\n 'md': 8,\n 'lg': 12,\n 'xl': 16\n };\n\n // Core configuration\n this.value = options.value !== undefined ? options.value : 0;\n this.min = options.min !== undefined ? options.min : 0;\n this.max = options.max !== undefined ? options.max : 100;\n\n // Dimensions\n this.sizePreset = (typeof options.size === 'string' && this.SIZE_PRESETS[options.size]) ? options.size : null;\n this.size = this.resolveSize(options.size !== undefined ? options.size : 'md');\n this.strokeWidth = options.strokeWidth === 'auto' || options.strokeWidth === undefined\n ? this.getAutoStrokeWidth(options.size)\n : options.strokeWidth;\n\n // Colors & Styling\n this.theme = options.theme || 'basic'; // 'basic', '3d', 'dark', 'light'\n this.variant = options.variant || 'default';\n this.color = options.color; // Will be set by applyVariant if not provided\n this.trackColor = options.trackColor; // Will be set by applyTheme if not provided\n this.textColor = options.textColor; // Custom text color\n this.gradientColors = options.gradientColors || null;\n\n // Apply theme (sets colors based on theme)\n this.applyTheme();\n \n // Apply variant colors (sets this.color if not provided)\n this.applyVariant();\n\n // Arc configuration\n this.rotation = options.rotation !== undefined ? options.rotation : -90; // Start at top\n this.gap = options.gap || 0; // Gap in degrees (0 = full circle)\n\n // Center content\n this.showValue = options.showValue !== false;\n this.valueFormat = options.valueFormat || 'percentage';\n this.valueFormatter = options.valueFormatter || null;\n this.label = options.label || null;\n this.labelHtml = options.labelHtml || null;\n this.icon = options.icon || null;\n\n // Animation\n this.animate = options.animate !== false;\n this.animationDuration = options.animationDuration || 600;\n this.animationEasing = options.animationEasing || 'ease-out';\n\n // Visual options\n this.rounded = options.rounded !== false;\n this.shadow = options.shadow || false;\n\n // Interaction\n this.clickable = options.clickable || false;\n this.tooltip = options.tooltip || null;\n this.tooltipPlacement = options.tooltipPlacement || 'top';\n\n // Multi-segment mode\n this.segments = options.segments || null;\n this.segmentGap = options.segmentGap || 2; // Gap between segments in degrees\n\n // DataFormatter instance\n this.dataFormatter = dataFormatter;\n\n // Internal state\n this.svg = null;\n this.centerElement = null;\n this.popover = null;\n this.gradientId = `gradient-${Math.random().toString(36).substr(2, 9)}`;\n }\n\n resolveSize(size) {\n if (typeof size === 'string' && this.SIZE_PRESETS[size]) {\n return this.SIZE_PRESETS[size];\n }\n return typeof size === 'number' ? size : this.SIZE_PRESETS.md;\n }\n\n getAutoStrokeWidth(size) {\n if (typeof size === 'string' && this.STROKE_PRESETS[size]) {\n return this.STROKE_PRESETS[size];\n }\n // Auto-calculate based on size\n const actualSize = this.resolveSize(size);\n if (actualSize <= 40) return 4;\n if (actualSize <= 60) return 6;\n if (actualSize <= 80) return 8;\n if (actualSize <= 120) return 12;\n return 16;\n }\n\n applyTheme() {\n const themes = {\n 'basic': {\n trackColor: '#e9ecef',\n textColor: null, // Use default\n backgroundColor: null\n },\n 'shadowed': {\n trackColor: '#d1d5db',\n textColor: null,\n backgroundColor: null,\n shadow: true\n },\n 'dark': {\n trackColor: '#374151',\n textColor: '#e5e7eb',\n backgroundColor: '#1f2937'\n },\n 'light': {\n trackColor: '#f3f4f6',\n textColor: '#111827',\n backgroundColor: '#ffffff'\n }\n };\n\n const themeConfig = themes[this.theme] || themes.basic;\n \n // Apply theme defaults if not explicitly set\n if (!this.trackColor) {\n this.trackColor = themeConfig.trackColor;\n }\n if (!this.textColor && themeConfig.textColor) {\n this.textColor = themeConfig.textColor;\n }\n if (themeConfig.shadow && this.shadow === false) {\n this.shadow = themeConfig.shadow;\n }\n }\n\n applyVariant() {\n const variants = {\n 'success': { color: '#198754', trackColor: 'rgba(25, 135, 84, 0.1)' },\n 'danger': { color: '#dc3545', trackColor: 'rgba(220, 53, 69, 0.1)' },\n 'warning': { color: '#ffc107', trackColor: 'rgba(255, 193, 7, 0.1)' },\n 'info': { color: '#0dcaf0', trackColor: 'rgba(13, 202, 240, 0.1)' },\n 'default': { color: '#0d6efd' } // Default blue color\n };\n\n if (variants[this.variant]) {\n const variantColors = variants[this.variant];\n if (!this.color) {\n this.color = variantColors.color;\n }\n if (variantColors.trackColor && this.trackColor === this.applyTheme.trackColor) {\n this.trackColor = variantColors.trackColor;\n }\n }\n \n // Fallback if no color is set\n if (!this.color) {\n this.color = '#0d6efd';\n }\n }\n\n getTemplate() {\n const sizeClass = this.sizePreset ? `circular-progress-${this.sizePreset}` : '';\n const variantClass = this.variant !== 'default' ? `circular-progress-${this.variant}` : '';\n const themeClass = this.theme !== 'basic' ? `circular-progress-theme-${this.theme}` : '';\n const clickableClass = this.clickable ? 'circular-progress-clickable' : '';\n const shadowClass = this.shadow ? 'circular-progress-shadow' : '';\n \n const textColorStyle = this.textColor ? `color: ${this.textColor};` : '';\n\n return `\n <div class=\"circular-progress-container ${sizeClass} ${variantClass} ${themeClass} ${clickableClass} ${shadowClass}\"\n style=\"width: ${this.size}px; height: ${this.size}px;\">\n <svg class=\"circular-progress-svg\" \n width=\"${this.size}\" \n height=\"${this.size}\"\n viewBox=\"0 0 ${this.size} ${this.size}\">\n </svg>\n <div class=\"circular-progress-center\" style=\"${textColorStyle}\">\n <div class=\"circular-progress-content\"></div>\n </div>\n </div>\n `;\n }\n\n async onAfterRender() {\n this.svg = this.element.querySelector('.circular-progress-svg');\n this.centerElement = this.element.querySelector('.circular-progress-content');\n this.containerElement = this.element.querySelector('.circular-progress-container');\n\n // Render the progress circle\n this.renderProgress();\n\n // Render center content\n this.renderCenterContent();\n\n // Setup interactions\n if (this.clickable) {\n this.setupClickHandler();\n }\n\n // Setup tooltip\n if (this.tooltip && this.clickable) {\n this.setupTooltip();\n }\n }\n\n renderProgress() {\n if (!this.svg) return;\n\n // Clear previous content\n this.svg.innerHTML = '';\n\n const center = this.size / 2;\n const radius = (this.size - this.strokeWidth) / 2;\n const circumference = 2 * Math.PI * radius;\n\n // Create gradient definition if needed\n if (this.gradientColors && this.gradientColors.length > 1) {\n this.createGradient();\n }\n\n // Determine if we're using segments or single progress\n if (this.segments && Array.isArray(this.segments) && this.segments.length > 0) {\n this.renderSegments(center, radius, circumference);\n } else {\n this.renderSingleProgress(center, radius, circumference);\n }\n }\n\n renderSingleProgress(center, radius, circumference) {\n // Calculate arc length\n const arcLength = this.gap > 0 ? (360 - this.gap) : 360;\n const arcCircumference = (arcLength / 360) * circumference;\n\n // Create track (background circle/arc)\n const track = this.createCircle(center, radius, {\n stroke: this.trackColor,\n strokeWidth: this.strokeWidth,\n fill: 'none',\n strokeLinecap: this.rounded ? 'round' : 'butt',\n strokeDasharray: this.gap > 0 ? `${arcCircumference} ${circumference}` : 'none',\n transform: `rotate(${this.rotation} ${center} ${center})`\n });\n this.svg.appendChild(track);\n\n // Create progress circle\n const percentage = this.getPercentage();\n const progressLength = (percentage / 100) * arcCircumference;\n const dashOffset = arcCircumference - progressLength;\n\n const strokeColor = this.gradientColors ? `url(#${this.gradientId})` : this.color;\n\n const progress = this.createCircle(center, radius, {\n stroke: strokeColor,\n strokeWidth: this.strokeWidth,\n fill: 'none',\n strokeLinecap: this.rounded ? 'round' : 'butt',\n strokeDasharray: `${arcCircumference} ${circumference}`,\n strokeDashoffset: this.animate ? arcCircumference : dashOffset,\n transform: `rotate(${this.rotation} ${center} ${center})`,\n class: 'circular-progress-bar'\n });\n\n this.svg.appendChild(progress);\n\n // Apply animation\n if (this.animate) {\n this.animateProgress(progress, dashOffset);\n }\n }\n\n renderSegments(center, radius, circumference) {\n // Calculate arc length\n const arcLength = this.gap > 0 ? (360 - this.gap) : 360;\n const arcCircumference = (arcLength / 360) * circumference;\n\n // Create track\n const track = this.createCircle(center, radius, {\n stroke: this.trackColor,\n strokeWidth: this.strokeWidth,\n fill: 'none',\n strokeLinecap: this.rounded ? 'round' : 'butt',\n strokeDasharray: this.gap > 0 ? `${arcCircumference} ${circumference}` : 'none',\n transform: `rotate(${this.rotation} ${center} ${center})`\n });\n this.svg.appendChild(track);\n\n // Validate segments total\n const total = this.segments.reduce((sum, seg) => sum + (seg.value || 0), 0);\n if (total > this.max) {\n console.warn('CircularProgress: Segment total exceeds max value. Clamping to max.');\n }\n\n // Render each segment\n let currentOffset = 0;\n\n this.segments.forEach((segment, index) => {\n const segmentPercentage = ((segment.value || 0) / (this.max - this.min)) * 100;\n const segmentLength = (segmentPercentage / 100) * arcCircumference;\n\n // Gap between segments (in circumference units)\n const gapLength = (this.segmentGap / 360) * circumference;\n\n if (segmentLength > 0) {\n const segmentCircle = this.createCircle(center, radius, {\n stroke: segment.color || this.color,\n strokeWidth: this.strokeWidth,\n fill: 'none',\n strokeLinecap: this.rounded ? 'round' : 'butt',\n strokeDasharray: `${segmentLength} ${circumference}`,\n strokeDashoffset: this.animate ? arcCircumference : -(currentOffset),\n transform: `rotate(${this.rotation} ${center} ${center})`,\n class: `circular-progress-segment circular-progress-segment-${index}`,\n 'data-segment-index': index\n });\n\n this.svg.appendChild(segmentCircle);\n\n // Apply animation\n if (this.animate) {\n this.animateProgress(segmentCircle, -(currentOffset), index * 100);\n }\n\n // Update offset for next segment\n currentOffset += segmentLength + gapLength;\n }\n });\n }\n\n createCircle(cx, cy, attributes = {}) {\n const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n circle.setAttribute('cx', cx);\n circle.setAttribute('cy', cx); // Use cx for cy since we pass center for both\n circle.setAttribute('r', cy); // cy parameter is actually the radius\n\n Object.entries(attributes).forEach(([key, value]) => {\n if (key === 'strokeWidth') {\n circle.setAttribute('stroke-width', value);\n } else if (key === 'strokeLinecap') {\n circle.setAttribute('stroke-linecap', value);\n } else if (key === 'strokeDasharray') {\n circle.setAttribute('stroke-dasharray', value);\n } else if (key === 'strokeDashoffset') {\n circle.setAttribute('stroke-dashoffset', value);\n } else {\n circle.setAttribute(key, value);\n }\n });\n\n return circle;\n }\n\n createGradient() {\n const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\n const gradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient');\n gradient.setAttribute('id', this.gradientId);\n gradient.setAttribute('x1', '0%');\n gradient.setAttribute('y1', '0%');\n gradient.setAttribute('x2', '100%');\n gradient.setAttribute('y2', '100%');\n\n this.gradientColors.forEach((color, index) => {\n const stop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\n const offset = (index / (this.gradientColors.length - 1)) * 100;\n stop.setAttribute('offset', `${offset}%`);\n stop.setAttribute('stop-color', color);\n gradient.appendChild(stop);\n });\n\n defs.appendChild(gradient);\n this.svg.appendChild(defs);\n }\n\n animateProgress(circle, targetOffset, delay = 0) {\n setTimeout(() => {\n circle.style.transition = `stroke-dashoffset ${this.animationDuration}ms ${this.animationEasing}`;\n circle.style.strokeDashoffset = targetOffset;\n }, delay);\n }\n\n renderCenterContent() {\n if (!this.centerElement) return;\n\n // Priority: labelHtml > icon > value/label\n if (this.labelHtml) {\n this.centerElement.innerHTML = this.labelHtml;\n } else if (this.icon) {\n this.centerElement.innerHTML = `<i class=\"${this.icon}\"></i>`;\n } else if (this.showValue) {\n const formattedValue = this.getFormattedValue();\n let html = `<div class=\"circular-progress-value\">${formattedValue}</div>`;\n \n if (this.label) {\n html += `<div class=\"circular-progress-label\">${this.label}</div>`;\n }\n\n this.centerElement.innerHTML = html;\n }\n }\n\n getFormattedValue() {\n const value = this.value;\n const min = this.min;\n const max = this.max;\n\n // Custom formatter function takes precedence\n if (this.valueFormatter && typeof this.valueFormatter === 'function') {\n return this.valueFormatter(value, min, max);\n }\n\n // Built-in formats\n switch (this.valueFormat) {\n case 'percentage':\n return `${Math.round(this.getPercentage())}%`;\n \n case 'fraction':\n return `${value}/${max}`;\n \n case 'value':\n return value.toString();\n \n default:\n // Try DataFormatter\n if (this.dataFormatter) {\n try {\n return this.dataFormatter.pipe(value, this.valueFormat);\n } catch (error) {\n console.warn('CircularProgress: DataFormatter error, falling back to percentage', error);\n return `${Math.round(this.getPercentage())}%`;\n }\n }\n return `${Math.round(this.getPercentage())}%`;\n }\n }\n\n getPercentage() {\n const range = this.max - this.min;\n if (range === 0) return 0;\n return ((this.value - this.min) / range) * 100;\n }\n\n setupClickHandler() {\n if (!this.containerElement) return;\n\n this.containerElement.style.cursor = 'pointer';\n \n this.containerElement.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n\n const percentage = this.getPercentage();\n \n this.emit('progress:clicked', {\n value: this.value,\n percentage,\n min: this.min,\n max: this.max\n });\n\n // Toggle popover if tooltip is configured\n if (this.tooltip) {\n this.togglePopover();\n }\n });\n }\n\n setupTooltip() {\n // Bootstrap popover will be initialized on first click\n // We'll create the popover content dynamically\n }\n\n togglePopover() {\n if (!this.containerElement || typeof window.bootstrap === 'undefined') {\n console.warn('CircularProgress: Bootstrap is required for tooltip support');\n return;\n }\n\n // Get or create popover instance\n if (!this.popover) {\n const content = this.getTooltipContent();\n const title = typeof this.tooltip === 'object' && this.tooltip.title ? this.tooltip.title : undefined;\n\n // Build config object, omitting title if undefined\n const popoverConfig = {\n content: content,\n html: true,\n placement: this.tooltipPlacement,\n trigger: 'manual',\n container: 'body'\n };\n \n // Only add title if it exists\n if (title) {\n popoverConfig.title = title;\n }\n\n this.popover = new window.bootstrap.Popover(this.containerElement, popoverConfig);\n }\n\n // Toggle visibility\n const popoverElement = window.bootstrap.Popover.getInstance(this.containerElement);\n if (popoverElement && this.containerElement.getAttribute('aria-describedby')) {\n this.popover.hide();\n } else {\n // Update content before showing\n this.popover.setContent({\n '.popover-body': this.getTooltipContent()\n });\n this.popover.show();\n }\n }\n\n getTooltipContent() {\n if (typeof this.tooltip === 'function') {\n return this.tooltip(this.value, {\n min: this.min,\n max: this.max,\n percentage: this.getPercentage()\n });\n }\n\n if (typeof this.tooltip === 'object') {\n return this.tooltip.html || this.tooltip.content || '';\n }\n\n return this.tooltip || '';\n }\n\n // Public API\n\n setValue(value, animate = true) {\n const oldValue = this.value;\n this.value = Math.max(this.min, Math.min(this.max, value));\n \n // Update center content\n this.renderCenterContent();\n \n // Update progress without full re-render\n if (this.svg && !this.segments) {\n const progressBar = this.svg.querySelector('.circular-progress-bar');\n if (progressBar) {\n const radius = (this.size / 2) - (this.strokeWidth / 2);\n const circumference = 2 * Math.PI * radius;\n const arcLength = this.gap > 0 ? (360 - this.gap) : 360;\n const arcCircumference = (arcLength / 360) * circumference;\n const percentage = this.getPercentage();\n const progressLength = (percentage / 100) * arcCircumference;\n const dashOffset = arcCircumference - progressLength;\n \n if (animate) {\n // Animate from current offset to new offset\n progressBar.style.transition = `stroke-dashoffset ${this.animationDuration}ms ${this.animationEasing}`;\n progressBar.style.strokeDashoffset = dashOffset;\n } else {\n // Update immediately without animation\n progressBar.style.transition = 'none';\n progressBar.style.strokeDashoffset = dashOffset;\n }\n }\n } else {\n // For segments or if no existing progress bar, do full re-render\n const oldAnimate = this.animate;\n this.animate = animate;\n this.renderProgress();\n this.animate = oldAnimate;\n }\n }\n\n setRange(min, max) {\n this.min = min;\n this.max = max;\n this.renderProgress();\n this.renderCenterContent();\n }\n\n increment(amount = 1) {\n this.setValue(this.value + amount);\n }\n\n decrement(amount = 1) {\n this.setValue(this.value - amount);\n }\n\n setColor(color) {\n this.color = color;\n this.gradientColors = null; // Clear gradient\n \n // Update color without full re-render\n if (this.svg && !this.segments) {\n const progressBar = this.svg.querySelector('.circular-progress-bar');\n if (progressBar) {\n progressBar.setAttribute('stroke', color);\n }\n } else {\n // For segments, need to re-render\n this.renderProgress();\n }\n }\n\n setGradient(colors) {\n if (Array.isArray(colors) && colors.length > 1) {\n this.gradientColors = colors;\n this.gradientId = `gradient-${Math.random().toString(36).substr(2, 9)}`;\n this.renderProgress();\n }\n }\n\n setSize(size) {\n // Remove old size class if it exists\n if (this.containerElement && this.sizePreset) {\n this.containerElement.classList.remove(`circular-progress-${this.sizePreset}`);\n }\n \n // Update size preset if the new size is a preset string\n this.sizePreset = (typeof size === 'string' && this.SIZE_PRESETS[size]) ? size : null;\n this.size = this.resolveSize(size);\n this.strokeWidth = this.getAutoStrokeWidth(size);\n \n // Add new size class if it's a preset\n if (this.containerElement) {\n this.containerElement.style.width = `${this.size}px`;\n this.containerElement.style.height = `${this.size}px`;\n \n if (this.sizePreset) {\n this.containerElement.classList.add(`circular-progress-${this.sizePreset}`);\n }\n }\n \n if (this.svg) {\n this.svg.setAttribute('width', this.size);\n this.svg.setAttribute('height', this.size);\n this.svg.setAttribute('viewBox', `0 0 ${this.size} ${this.size}`);\n }\n \n this.renderProgress();\n }\n\n animateTo(targetValue, duration = 1000) {\n const startValue = this.value;\n const diff = targetValue - startValue;\n const startTime = performance.now();\n\n const animate = (currentTime) => {\n const elapsed = currentTime - startTime;\n const progress = Math.min(elapsed / duration, 1);\n\n // Ease-out function\n const easeProgress = 1 - Math.pow(1 - progress, 3);\n \n const newValue = startValue + (diff * easeProgress);\n this.setValue(newValue, false);\n\n if (progress < 1) {\n requestAnimationFrame(animate);\n } else {\n this.setValue(targetValue, false);\n }\n };\n\n requestAnimationFrame(animate);\n }\n\n pulse() {\n if (!this.containerElement) return;\n\n this.containerElement.style.animation = 'none';\n setTimeout(() => {\n this.containerElement.style.animation = 'circular-progress-pulse 0.5s ease-out';\n }, 10);\n\n setTimeout(() => {\n this.containerElement.style.animation = '';\n }, 500);\n }\n\n complete() {\n this.variant = 'success';\n this.applyVariant();\n this.setValue(this.max);\n this.pulse();\n }\n\n reset() {\n this.setValue(this.min);\n }\n\n hide() {\n if (this.element) {\n this.element.style.display = 'none';\n }\n }\n\n show() {\n if (this.element) {\n this.element.style.display = '';\n }\n }\n\n getValue() {\n return this.value;\n }\n\n getPercentageValue() {\n return this.getPercentage();\n }\n\n async onBeforeDestroy() {\n // Clean up popover\n if (this.popover) {\n this.popover.dispose();\n this.popover = null;\n }\n\n await super.onBeforeDestroy();\n }\n}\n"],"names":["CircularProgress","View","constructor","options","super","className","this","SIZE_PRESETS","xs","sm","md","lg","xl","STROKE_PRESETS","value","min","max","sizePreset","size","resolveSize","strokeWidth","getAutoStrokeWidth","theme","variant","color","trackColor","textColor","gradientColors","applyTheme","applyVariant","rotation","gap","showValue","valueFormat","valueFormatter","label","labelHtml","icon","animate","animationDuration","animationEasing","rounded","shadow","clickable","tooltip","tooltipPlacement","segments","segmentGap","dataFormatter","svg","centerElement","popover","gradientId","Math","random","toString","substr","actualSize","themes","basic","backgroundColor","shadowed","dark","light","themeConfig","variants","success","danger","warning","info","default","variantColors","getTemplate","sizeClass","variantClass","themeClass","clickableClass","shadowClass","textColorStyle","onAfterRender","element","querySelector","containerElement","renderProgress","renderCenterContent","setupClickHandler","setupTooltip","innerHTML","center","radius","circumference","PI","length","createGradient","Array","isArray","renderSegments","renderSingleProgress","arcCircumference","track","createCircle","stroke","fill","strokeLinecap","strokeDasharray","transform","appendChild","dashOffset","getPercentage","strokeColor","progress","strokeDashoffset","class","animateProgress","reduce","sum","seg","console","warn","currentOffset","forEach","segment","index","segmentLength","gapLength","segmentCircle","cx","cy","attributes","circle","document","createElementNS","setAttribute","Object","entries","key","defs","gradient","stop","offset","targetOffset","delay","setTimeout","style","transition","html","getFormattedValue","round","pipe","error","range","cursor","addEventListener","e","preventDefault","stopPropagation","percentage","emit","togglePopover","window","bootstrap","content","getTooltipContent","title","popoverConfig","placement","trigger","container","Popover","getInstance","getAttribute","hide","setContent","show","setValue","progressBar","oldAnimate","setRange","increment","amount","decrement","setColor","setGradient","colors","setSize","classList","remove","width","height","add","animateTo","targetValue","duration","startValue","diff","startTime","performance","now","currentTime","elapsed","easeProgress","pow","newValue","requestAnimationFrame","pulse","animation","complete","reset","display","getValue","getPercentageValue","onBeforeDestroy","dispose"],"mappings":"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"}
package/dist/chat.css CHANGED
@@ -377,3 +377,99 @@
377
377
  font-size: 0.7rem;
378
378
  padding: 2px 6px;
379
379
  }
380
+
381
+ /* ========================================
382
+ Dark theme overrides
383
+
384
+ The base chat styles use hardcoded light-mode hex values (#fff, #f8f9fa,
385
+ #6c757d, …). When data-bs-theme="dark" is active we re-skin the same
386
+ surfaces using Bootstrap dark-mode tokens so the chat blends with the
387
+ rest of the page.
388
+ ======================================== */
389
+ [data-bs-theme="dark"] .chat-container {
390
+ background: var(--bs-body-bg);
391
+ border-color: var(--bs-border-color);
392
+ }
393
+
394
+ [data-bs-theme="dark"] .chat-messages {
395
+ background: var(--bs-body-bg);
396
+ }
397
+
398
+ [data-bs-theme="dark"] .chat-theme-compact .message-item {
399
+ border-bottom-color: var(--bs-border-color-translucent);
400
+ }
401
+
402
+ [data-bs-theme="dark"] .chat-theme-compact .message-item:hover {
403
+ background: var(--bs-tertiary-bg);
404
+ }
405
+
406
+ [data-bs-theme="dark"] .chat-theme-compact .message-author,
407
+ [data-bs-theme="dark"] .chat-theme-compact .message-text {
408
+ color: var(--bs-body-color);
409
+ }
410
+
411
+ [data-bs-theme="dark"] .chat-theme-compact .message-time,
412
+ [data-bs-theme="dark"] .chat-theme-bubbles .message-meta {
413
+ color: var(--bs-secondary-color);
414
+ }
415
+
416
+ [data-bs-theme="dark"] .chat-theme-compact .chat-message-system {
417
+ background: var(--bs-tertiary-bg);
418
+ }
419
+
420
+ [data-bs-theme="dark"] .chat-theme-bubbles .message-left .message-bubble {
421
+ background: var(--bs-tertiary-bg);
422
+ color: var(--bs-body-color);
423
+ }
424
+
425
+ /* `message-right` keeps `--bs-primary` from the base rule — looks correct
426
+ in both themes since Bootstrap's primary is theme-aware. */
427
+
428
+ [data-bs-theme="dark"] .chat-input-view {
429
+ background: var(--bs-tertiary-bg);
430
+ border-top-color: var(--bs-border-color);
431
+ }
432
+
433
+ [data-bs-theme="dark"] .chat-input-container.drag-over {
434
+ background: rgba(13, 110, 253, 0.12);
435
+ }
436
+
437
+ [data-bs-theme="dark"] .attachment-preview {
438
+ background: var(--bs-tertiary-bg);
439
+ color: var(--bs-body-color);
440
+ }
441
+
442
+ [data-bs-theme="dark"] .attachment-preview.upload-complete {
443
+ background: var(--bs-success-bg-subtle);
444
+ }
445
+
446
+ [data-bs-theme="dark"] .attachment-preview.upload-error {
447
+ background: var(--bs-danger-bg-subtle);
448
+ }
449
+
450
+ [data-bs-theme="dark"] .attachment-size {
451
+ color: var(--bs-secondary-color);
452
+ }
453
+
454
+ [data-bs-theme="dark"] .message-text .file-attachment,
455
+ [data-bs-theme="dark"] [data-container="attachments"] .file-attachment {
456
+ background: rgba(255, 255, 255, 0.06);
457
+ border-color: rgba(255, 255, 255, 0.12);
458
+ }
459
+
460
+ [data-bs-theme="dark"] .message-text .file-attachment:hover,
461
+ [data-bs-theme="dark"] [data-container="attachments"] .file-attachment:hover {
462
+ background: rgba(255, 255, 255, 0.12);
463
+ }
464
+
465
+ [data-bs-theme="dark"] .chat-messages::-webkit-scrollbar-track {
466
+ background: var(--bs-tertiary-bg);
467
+ }
468
+
469
+ [data-bs-theme="dark"] .chat-messages::-webkit-scrollbar-thumb {
470
+ background: var(--bs-secondary-color);
471
+ }
472
+
473
+ [data-bs-theme="dark"] .chat-messages::-webkit-scrollbar-thumb:hover {
474
+ background: var(--bs-emphasis-color);
475
+ }
@@ -0,0 +1,2 @@
1
+ import{V as t}from"./View-C5n3sIFi.js";import{C as s}from"./ChatView-W8daOwIo.js";import{AssistantConversationList as e,Assistant as n}from"../admin-models.es.js";import{A as i,a,b as o}from"./admin-vjoNbv_1.js";class AssistantPanelView extends t{constructor(t={}){super({className:"assistant-panel-view",...t}),this.app=t.app,this.ws=this.app?.ws,this.conversationId=t.conversationId||this.app?._assistantConversationId||null,this._wsHandlers={},this._messageIdCounter=0,this._hasMessages=!1,this._activePlans={},this._requestStartTime=null,this._showingHistory=!1}getTemplate(){return`\n <div class="assistant-panel-resize-handle" data-ref="resize-handle"></div>\n <div class="assistant-panel-layout">\n <div class="assistant-panel-header">\n <button class="assistant-panel-header-btn" data-action="toggle-history" type="button" title="Conversation history">\n <i class="bi bi-list"></i>\n </button>\n <span class="assistant-panel-title text-truncate" data-ref="panel-title">New conversation</span>\n <div class="d-flex gap-1 ms-auto">\n <button class="assistant-panel-header-btn" data-action="new-conversation" type="button" title="New conversation">\n <i class="bi bi-plus-lg"></i>\n </button>\n <button class="assistant-panel-header-btn" data-action="fullscreen" type="button" title="Open fullscreen">\n <i class="bi bi-arrows-fullscreen"></i>\n </button>\n <button class="assistant-panel-header-btn" data-action="pop-out" type="button" title="Open in popup window">\n <i class="bi bi-box-arrow-up-right"></i>\n </button>\n <button class="assistant-panel-header-btn" data-action="close-panel" type="button" title="Close">\n <i class="bi bi-x-lg"></i>\n </button>\n </div>\n </div>\n\n <div class="assistant-panel-history d-none" data-ref="history" data-container="conversation-list"></div>\n\n <div class="assistant-panel-chat" data-ref="chat-wrapper">\n <div class="assistant-welcome" data-ref="welcome">\n <div class="assistant-welcome-content">\n <div class="assistant-welcome-icon">\n <i class="bi bi-stars"></i>\n </div>\n <h3 class="assistant-welcome-title">Hi ${this._escapeHtml(this.app?.activeUser?.get("first_name")||"there")}</h3>\n <p class="assistant-welcome-subtitle">How can I help you today?</p>\n <div class="assistant-suggestions">\n <button class="assistant-suggestion" data-action="use-suggestion" data-text="Show me a summary of recent activity">\n <i class="bi bi-activity"></i>\n <span>Recent activity summary</span>\n </button>\n <button class="assistant-suggestion" data-action="use-suggestion" data-text="How many active users are there?">\n <i class="bi bi-people"></i>\n <span>Active user count</span>\n </button>\n </div>\n </div>\n </div>\n <div class="assistant-chat-area" data-container="chat-area"></div>\n <div class="assistant-input-wrapper">\n <div class="assistant-input-status d-none" data-ref="input-status"></div>\n <div class="assistant-input-box">\n <textarea class="assistant-input" placeholder="Message the assistant..." rows="1" data-ref="input"></textarea>\n <button class="assistant-send-btn" data-action="send" type="button" title="Send message" data-ref="send-btn">\n <i class="bi bi-arrow-up"></i>\n </button>\n <button class="assistant-stop-btn d-none" data-action="stop" type="button" title="Stop generating" data-ref="stop-btn">\n <i class="bi bi-stop-fill"></i>\n </button>\n </div>\n <div class="assistant-input-footer">\n <span class="assistant-connection-indicator" data-ref="status">\n <span class="status-dot connected"></span>\n </span>\n <span class="text-muted">Enter to send</span>\n </div>\n </div>\n </div>\n </div>\n `}async onInit(){this.conversations=new e,this.conversations.params.user=this.app?.activeUser?.id,this.conversationListView=new i({containerId:"conversation-list",collection:this.conversations}),this.addChild(this.conversationListView),this.chatView=new s({containerId:"chat-area",theme:"compact",messageViewClass:a,currentUserId:this.app?.activeUser?.id,showFileInput:!1,showInput:!1,adapter:this._createAdapter()}),this.addChild(this.chatView);const t=this.chatView.addMessage.bind(this.chatView);this.chatView.addMessage=(s,e)=>{t(s,e),"assistant"===s.role&&(s.content||s.blocks?.length)&&(this.chatView.hideThinking(),this._setInputEnabled(!0))},this.conversationListView.on("conversation:select",t=>{this._onConversationSelect(t),this._toggleHistory(!1)}),this.conversationListView.on("conversation:new",()=>{this._onNewConversation(),this._toggleHistory(!1)}),this.conversationListView.on("conversation:deleted",t=>this._onConversationDeleted(t)),this._subscribeWS()}async onAfterRender(){await super.onAfterRender();const t=this.element.querySelector('[data-ref="input"]');t&&(t.addEventListener("input",()=>this._autoResize(t)),t.addEventListener("keydown",t=>this._handleKeydown(t)),setTimeout(()=>t.focus(),100)),this.conversationId&&(this._showChatArea(),await this.chatView.refresh()),this._updateConnectionStatus(),this._updateTitle(),this._setupResizeHandle()}_setupResizeHandle(){const t=this.element?.querySelector('[data-ref="resize-handle"]');if(!t)return;const s="mojo:assistant_panel_width",e=localStorage.getItem(s);if(e){const t=parseInt(e,10);if(t>=300&&t<=700){const s=document.getElementById("assistant-panel");s&&(s.style.width=t+"px")}}let n,i;const a=t=>{const s=n-t.clientX,e=Math.min(700,Math.max(300,i+s)),a=document.getElementById("assistant-panel");a&&(a.style.width=e+"px")},o=()=>{document.removeEventListener("mousemove",a),document.removeEventListener("mouseup",o),document.body.style.cursor="",document.body.style.userSelect="";const t=document.getElementById("assistant-panel");t&&localStorage.setItem(s,parseInt(t.style.width,10))};t.addEventListener("mousedown",t=>{t.preventDefault(),n=t.clientX;const s=document.getElementById("assistant-panel");i=s?s.offsetWidth:500,document.body.style.cursor="col-resize",document.body.style.userSelect="none",document.addEventListener("mousemove",a),document.addEventListener("mouseup",o)})}onActionToggleHistory(){this._toggleHistory(!this._showingHistory)}onActionNewConversation(){this._onNewConversation(),this._showingHistory&&this._toggleHistory(!1)}onActionClosePanel(){this.emit("panel:close")}onActionFullscreen(){this.emit("panel:fullscreen",{conversationId:this.conversationId})}onActionPopOut(){this.emit("panel:popout",{conversationId:this.conversationId})}onActionUseSuggestion(t,s){const e=s.dataset.text||s.closest("[data-text]")?.dataset.text;if(!e)return;const n=this.element.querySelector('[data-ref="input"]');n&&(n.value=e,this._autoResize(n)),this._sendMessage()}onActionSend(){this._sendMessage()}onActionStop(){this.chatView.hideThinking(),this._setInputEnabled(!0),this._showSystemMessage("Response cancelled.");const t=this.element?.querySelector('[data-ref="input"]');t&&t.focus()}_toggleHistory(t){this._showingHistory=t;const s=this.element?.querySelector('[data-ref="history"]'),e=this.element?.querySelector('[data-ref="chat-wrapper"]'),n=this.element?.querySelector('[data-action="toggle-history"] i');s&&s.classList.toggle("d-none",!t),e&&e.classList.toggle("d-none",t),n&&(n.className=t?"bi bi-chat-dots":"bi bi-list"),t&&this.conversationListView.refresh()}_autoResize(t){t.style.height="auto",t.style.height=Math.min(t.scrollHeight,200)+"px"}_handleKeydown(t){"Enter"!==t.key||t.shiftKey||(t.preventDefault(),this._sendMessage())}async _sendMessage(){const t=this.element.querySelector('[data-ref="input"]');if(!t)return;const s=t.value.trim();s&&(t.value="",t.style.height="auto",this._showChatArea(),await this.chatView.adapter.addNote({text:s,files:[]}))}_showChatArea(){if(this._hasMessages)return;this._hasMessages=!0;const t=this.element.querySelector('[data-ref="welcome"]'),s=this.element.querySelector('[data-container="chat-area"]');t&&t.classList.add("d-none"),s&&s.classList.remove("d-none")}_showWelcome(){this._hasMessages=!1;const t=this.element.querySelector('[data-ref="welcome"]'),s=this.element.querySelector('[data-container="chat-area"]');t&&t.classList.remove("d-none"),s&&s.classList.add("d-none")}_setInputEnabled(t,s){const e=this.element?.querySelector('[data-ref="input"]'),n=this.element?.querySelector('[data-ref="send-btn"]'),i=this.element?.querySelector('[data-ref="stop-btn"]');e&&(e.disabled=!t),n&&n.classList.toggle("d-none",!t),i&&i.classList.toggle("d-none",t),this._setInputStatus(t?null:s),this._responseTimeout&&clearTimeout(this._responseTimeout),t?this._requestStartTime=null:this._responseTimeout=setTimeout(()=>this._onResponseTimeout(),6e4)}_setInputStatus(t){const s=this.element?.querySelector('[data-ref="input-status"]');s&&(t?(s.innerHTML=`${this._escapeHtml(t)} <span class="assistant-input-status-dismiss">Click to dismiss</span>`,s.classList.remove("d-none"),s._hasDismiss||(s._hasDismiss=!0,s.addEventListener("click",()=>{this.chatView.hideThinking(),this._setInputEnabled(!0);const t=this.element?.querySelector('[data-ref="input"]');t&&t.focus()}))):(s.classList.add("d-none"),s.innerHTML=""))}_onResponseTimeout(){this._responseTimeout=null,this.chatView.hideThinking(),this._setInputEnabled(!0),this._showSystemMessage("Request timed out. Please try again.")}_updateTitle(t){const s=this.element?.querySelector('[data-ref="panel-title"]');s&&(s.textContent=t||(this.conversationId?"Assistant":"New conversation"))}_createAdapter(){return{fetch:async()=>{if(!this.conversationId)return[];try{const t=new n({id:this.conversationId});await t.fetch({graph:"detail"});const s=t.get("title")||t.get("summary");s&&this._updateTitle(s);const e=(t.get("messages")||[]).map(t=>this._transformMessage(t)).filter(Boolean);return o._collapseMessages(e)}catch(t){return 404===t.status&&(this._onNewConversation(),this._showSystemMessage("Conversation not found.")),[]}},addNote:async t=>{if(!t.text||!t.text.trim())return{success:!1};const s={id:"local-"+ ++this._messageIdCounter,role:"user",author:{id:this.app?.activeUser?.id,name:this.app?.activeUser?.get("display_name")||"You"},content:t.text,timestamp:/* @__PURE__ */(new Date).toISOString()};if(this.chatView.addMessage(s),this.chatView.showThinking("Thinking..."),this._requestStartTime=Date.now(),this._setInputEnabled(!1,"Waiting for response…"),this.ws&&this.ws.isConnected)this.ws.send({type:"assistant_message",message:t.text,conversation_id:this.conversationId});else try{const s=await this.app.rest.post("/api/assistant",{message:t.text,conversation_id:this.conversationId}),e=s?.data?.data||s?.data||s;e.conversation_id&&(this.conversationId=e.conversation_id,this.app._assistantConversationId=this.conversationId),e.response&&this.chatView.addMessage(this._transformMessage(e.response)),this._setInputEnabled(!0)}catch(e){this._handleAPIError(e)}return{success:!0}}}}_subscribeWS(){this.ws&&(this._wsHandlers={thinking:t=>this._onThinking(t),text:t=>this._onText(t),tool_call:t=>this._onToolCall(t),response:t=>this._onResponse(t),error:t=>this._onError(t),plan:t=>this._onPlan(t),plan_update:t=>this._onPlanUpdate(t),message:t=>this._dispatchWSMessage(t),connected:()=>this._updateConnectionStatus(),disconnected:()=>this._updateConnectionStatus(),reconnecting:()=>this._updateConnectionStatus()},this.ws.on("message:assistant_thinking",this._wsHandlers.thinking),this.ws.on("message:assistant_text",this._wsHandlers.text),this.ws.on("message:assistant_tool_call",this._wsHandlers.tool_call),this.ws.on("message:assistant_response",this._wsHandlers.response),this.ws.on("message:assistant_error",this._wsHandlers.error),this.ws.on("message:assistant_plan",this._wsHandlers.plan),this.ws.on("message:assistant_plan_update",this._wsHandlers.plan_update),this.ws.on("message:message",this._wsHandlers.message),this.ws.on("connected",this._wsHandlers.connected),this.ws.on("disconnected",this._wsHandlers.disconnected),this.ws.on("reconnecting",this._wsHandlers.reconnecting))}_unsubscribeWS(){this.ws&&this._wsHandlers&&(this.ws.off("message:assistant_thinking",this._wsHandlers.thinking),this.ws.off("message:assistant_text",this._wsHandlers.text),this.ws.off("message:assistant_tool_call",this._wsHandlers.tool_call),this.ws.off("message:assistant_response",this._wsHandlers.response),this.ws.off("message:assistant_error",this._wsHandlers.error),this.ws.off("message:assistant_plan",this._wsHandlers.plan),this.ws.off("message:assistant_plan_update",this._wsHandlers.plan_update),this.ws.off("message:message",this._wsHandlers.message),this.ws.off("connected",this._wsHandlers.connected),this.ws.off("disconnected",this._wsHandlers.disconnected),this.ws.off("reconnecting",this._wsHandlers.reconnecting),this._wsHandlers={})}_dispatchWSMessage(t){const s=t?.data;if(s?.type)switch(s.type){case"assistant_thinking":this._onThinking(s);break;case"assistant_text":this._onText(s);break;case"assistant_tool_call":this._onToolCall(s);break;case"assistant_response":this._onResponse(s);break;case"assistant_error":this._onError(s);break;case"assistant_plan":this._onPlan(s);break;case"assistant_plan_update":this._onPlanUpdate(s)}}_isMyConversation(t){return!t.conversation_id||!this.conversationId||String(t.conversation_id)===String(this.conversationId)}_adoptConversationId(t){t.conversation_id&&!this.conversationId&&(this.conversationId=t.conversation_id,this.app._assistantConversationId=this.conversationId)}_onThinking(t){this._isMyConversation(t)&&(this._adoptConversationId(t),this._showChatArea(),this.chatView.showThinking("Thinking..."),this._setInputEnabled(!1,"Assistant is thinking…"))}_onText(t){if(!this._isMyConversation(t))return;this._adoptConversationId(t),this._resetResponseTimeout();const s=this._transformMessage({id:t.message_id||"text-"+ ++this._messageIdCounter,role:"assistant",content:t.text||"",blocks:t.blocks||[],tool_calls:[],created:t.created||t.timestamp||/* @__PURE__ */(new Date).toISOString()});s&&(s.content||s.blocks?.length)&&this.chatView.addMessage(s)}_onToolCall(t){this._isMyConversation(t)&&(this.chatView.showThinking(`Using ${t.tool||t.name||"tool"}...`),this._resetResponseTimeout())}_resetResponseTimeout(){if(this._responseTimeout){if(this._requestStartTime&&Date.now()-this._requestStartTime>=3e5)return void this._onResponseTimeout();clearTimeout(this._responseTimeout),this._responseTimeout=setTimeout(()=>this._onResponseTimeout(),6e4)}}_onResponse(t){if(!this._isMyConversation(t))return;this.chatView.hideThinking(),this._setInputEnabled(!0),this._adoptConversationId(t);const s=this.element?.querySelector('[data-ref="input"]');s&&s.focus();const e=this._transformMessage({id:t.message_id||"resp-"+ ++this._messageIdCounter,role:"assistant",content:t.response||t.content||t.message||"",blocks:t.blocks||[],tool_calls:t.tool_calls_made||t.tool_calls||[],created:t.created||t.timestamp||/* @__PURE__ */(new Date).toISOString()});e&&(e.content||e.blocks?.length||e.tool_calls?.length)&&this.chatView.addMessage(e)}_onError(t){if(!this._isMyConversation(t))return;this.chatView.hideThinking(),this._setInputEnabled(!0),this._adoptConversationId(t);const s=t.error||t.message||"An error occurred";this._showSystemMessage(s)}_onPlan(t){if(!this._isMyConversation(t))return;this._adoptConversationId(t),this._showChatArea();const s=t.plan;s&&(this._activePlans[s.plan_id]=s,this.chatView.addMessage({id:`plan-${s.plan_id}`,role:"assistant",author:{name:"Assistant"},content:"",timestamp:/* @__PURE__ */(new Date).toISOString(),blocks:[{type:"progress",...s}],tool_calls:[]}))}_onPlanUpdate(t){if(!this._isMyConversation(t))return;const s=this._activePlans[t.plan_id];if(s){const e=s.steps.find(s=>s.id===t.step_id);e&&(e.status=t.status,e.summary=t.summary)}const e=this.chatView.messageViews.get(`plan-${t.plan_id}`);e?.updateProgressStep&&e.updateProgressStep(t.plan_id,t.step_id,t.status,t.summary),this._resetResponseTimeout()}async _onConversationSelect(t){this.conversationId=t.id,this.app._assistantConversationId=this.conversationId,this.conversationListView.setActive(t.id),this._showChatArea(),this._updateTitle(t.model?.get("title")||t.model?.get("summary")),await this.chatView.refresh()}_onNewConversation(){this.conversationId=null,this.app._assistantConversationId=null,this.conversationListView.setActive(null),this.chatView.clearMessages(),this._setInputEnabled(!0),this._showWelcome(),this._updateTitle();const t=this.element?.querySelector('[data-ref="input"]');t&&t.focus()}_onConversationDeleted(t){String(t.id)===String(this.conversationId)&&this._onNewConversation()}_transformMessage(t){if("tool_result"===t.role)return null;let s=t.content||t.text||"",e=t.blocks||[],n=t.tool_calls||[];if(n.length>0){n=n.map(t=>!t.type&&t.tool?{type:"tool_use",name:t.tool,input:t.input}:t);const t=n.filter(t=>"text"===t.type&&t.text).map(t=>t.text);!s&&t.length>0&&(s=t.join("\n\n")),n=n.filter(t=>"tool_use"===t.type).filter(t=>!o.INTERNAL_TOOLS.has(t.name))}if(0===e.length&&s.includes("assistant_block")){const t=o._parseBlocks(s);s=t.content,e=t.blocks}const i=this.app?.activeUser?.id;return{id:t.id,role:t.role||"user",author:"assistant"===t.role?{name:"Assistant"}:t.author||{name:t.user?.display_name||this.app?.activeUser?.get("display_name")||"You",id:t.user?.id||i},content:s,timestamp:t.created||t.timestamp,blocks:e,tool_calls:n,_conversationId:this.conversationId}}_showSystemMessage(t){this._showChatArea(),this.chatView.addMessage({id:"sys-"+ ++this._messageIdCounter,type:"system_event",content:t,timestamp:/* @__PURE__ */(new Date).toISOString()})}_handleAPIError(t){404===t.status?this._showSystemMessage("Assistant is not enabled on this server."):503===t.status?this._showSystemMessage("LLM API key not configured. Contact your administrator."):this._showSystemMessage("Failed to send message. Please try again."),this._setInputEnabled(!0)}_updateConnectionStatus(){const t=this.element?.querySelector(".status-dot");t&&(this.ws?.isConnected?(t.className="status-dot connected",t.title="Connected",this._responseTimeout?this._setInputEnabled(!1,"Waiting for response…"):this._setInputEnabled(!0)):this.ws?.isReconnecting?(t.className="status-dot reconnecting",t.title="Reconnecting...",this._setInputEnabled(!1,"Reconnecting…"),this._responseTimeout&&(clearTimeout(this._responseTimeout),this._responseTimeout=null)):(t.className="status-dot disconnected",t.title="Disconnected",this._setInputEnabled(!1,"Disconnected — reconnecting…"),this._responseTimeout&&(clearTimeout(this._responseTimeout),this._responseTimeout=null)))}_escapeHtml(t){const s=document.createElement("div");return s.textContent=t,s.innerHTML}focusInput(){const t=this.element?.querySelector('[data-ref="input"]');t&&t.focus()}async onBeforeDestroy(){this._unsubscribeWS(),this._responseTimeout&&(clearTimeout(this._responseTimeout),this._responseTimeout=null)}}export{AssistantPanelView as default};
2
+ //# sourceMappingURL=AssistantPanelView-CMRTtoqS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssistantPanelView-CMRTtoqS.js","sources":["../../src/extensions/admin/assistant/AssistantPanelView.js"],"sourcesContent":["import View from '@core/View.js';\nimport ChatView from '@core/views/chat/ChatView.js';\nimport { AssistantConversation, AssistantConversationList } from '@ext/admin/models/Assistant.js';\nimport AssistantMessageView from './AssistantMessageView.js';\nimport AssistantConversationListView from './AssistantConversationListView.js';\nimport AssistantView from './AssistantView.js';\n\n/**\n * AssistantPanelView - Chat-only sidebar panel for the admin assistant\n *\n * Compact layout for the right sidebar panel. No conversation list by default —\n * a hamburger toggle switches between chat and conversation history.\n *\n * Emits:\n * panel:close — when the close button is clicked\n */\nclass AssistantPanelView extends View {\n constructor(options = {}) {\n super({\n className: 'assistant-panel-view',\n ...options\n });\n\n this.app = options.app;\n this.ws = this.app?.ws;\n this.conversationId = options.conversationId || this.app?._assistantConversationId || null;\n this._wsHandlers = {};\n this._messageIdCounter = 0;\n this._hasMessages = false;\n this._activePlans = {};\n this._requestStartTime = null;\n this._showingHistory = false;\n }\n\n getTemplate() {\n const userName = this._escapeHtml(\n this.app?.activeUser?.get('first_name') || 'there'\n );\n\n return `\n <div class=\"assistant-panel-resize-handle\" data-ref=\"resize-handle\"></div>\n <div class=\"assistant-panel-layout\">\n <div class=\"assistant-panel-header\">\n <button class=\"assistant-panel-header-btn\" data-action=\"toggle-history\" type=\"button\" title=\"Conversation history\">\n <i class=\"bi bi-list\"></i>\n </button>\n <span class=\"assistant-panel-title text-truncate\" data-ref=\"panel-title\">New conversation</span>\n <div class=\"d-flex gap-1 ms-auto\">\n <button class=\"assistant-panel-header-btn\" data-action=\"new-conversation\" type=\"button\" title=\"New conversation\">\n <i class=\"bi bi-plus-lg\"></i>\n </button>\n <button class=\"assistant-panel-header-btn\" data-action=\"fullscreen\" type=\"button\" title=\"Open fullscreen\">\n <i class=\"bi bi-arrows-fullscreen\"></i>\n </button>\n <button class=\"assistant-panel-header-btn\" data-action=\"pop-out\" type=\"button\" title=\"Open in popup window\">\n <i class=\"bi bi-box-arrow-up-right\"></i>\n </button>\n <button class=\"assistant-panel-header-btn\" data-action=\"close-panel\" type=\"button\" title=\"Close\">\n <i class=\"bi bi-x-lg\"></i>\n </button>\n </div>\n </div>\n\n <div class=\"assistant-panel-history d-none\" data-ref=\"history\" data-container=\"conversation-list\"></div>\n\n <div class=\"assistant-panel-chat\" data-ref=\"chat-wrapper\">\n <div class=\"assistant-welcome\" data-ref=\"welcome\">\n <div class=\"assistant-welcome-content\">\n <div class=\"assistant-welcome-icon\">\n <i class=\"bi bi-stars\"></i>\n </div>\n <h3 class=\"assistant-welcome-title\">Hi ${userName}</h3>\n <p class=\"assistant-welcome-subtitle\">How can I help you today?</p>\n <div class=\"assistant-suggestions\">\n <button class=\"assistant-suggestion\" data-action=\"use-suggestion\" data-text=\"Show me a summary of recent activity\">\n <i class=\"bi bi-activity\"></i>\n <span>Recent activity summary</span>\n </button>\n <button class=\"assistant-suggestion\" data-action=\"use-suggestion\" data-text=\"How many active users are there?\">\n <i class=\"bi bi-people\"></i>\n <span>Active user count</span>\n </button>\n </div>\n </div>\n </div>\n <div class=\"assistant-chat-area\" data-container=\"chat-area\"></div>\n <div class=\"assistant-input-wrapper\">\n <div class=\"assistant-input-status d-none\" data-ref=\"input-status\"></div>\n <div class=\"assistant-input-box\">\n <textarea class=\"assistant-input\" placeholder=\"Message the assistant...\" rows=\"1\" data-ref=\"input\"></textarea>\n <button class=\"assistant-send-btn\" data-action=\"send\" type=\"button\" title=\"Send message\" data-ref=\"send-btn\">\n <i class=\"bi bi-arrow-up\"></i>\n </button>\n <button class=\"assistant-stop-btn d-none\" data-action=\"stop\" type=\"button\" title=\"Stop generating\" data-ref=\"stop-btn\">\n <i class=\"bi bi-stop-fill\"></i>\n </button>\n </div>\n <div class=\"assistant-input-footer\">\n <span class=\"assistant-connection-indicator\" data-ref=\"status\">\n <span class=\"status-dot connected\"></span>\n </span>\n <span class=\"text-muted\">Enter to send</span>\n </div>\n </div>\n </div>\n </div>\n `;\n }\n\n async onInit() {\n // Conversation list for history panel\n this.conversations = new AssistantConversationList();\n this.conversations.params.user = this.app?.activeUser?.id;\n this.conversationListView = new AssistantConversationListView({\n containerId: 'conversation-list',\n collection: this.conversations\n });\n this.addChild(this.conversationListView);\n\n // Chat view\n this.chatView = new ChatView({\n containerId: 'chat-area',\n theme: 'compact',\n messageViewClass: AssistantMessageView,\n currentUserId: this.app?.activeUser?.id,\n showFileInput: false,\n showInput: false,\n adapter: this._createAdapter()\n });\n this.addChild(this.chatView);\n\n // Safety net: re-enable input on assistant message\n const origAddMessage = this.chatView.addMessage.bind(this.chatView);\n this.chatView.addMessage = (msg, scroll) => {\n origAddMessage(msg, scroll);\n if (msg.role === 'assistant' && (msg.content || msg.blocks?.length)) {\n this.chatView.hideThinking();\n this._setInputEnabled(true);\n }\n };\n\n // Wire conversation list events\n this.conversationListView.on('conversation:select', (data) => {\n this._onConversationSelect(data);\n this._toggleHistory(false);\n });\n this.conversationListView.on('conversation:new', () => {\n this._onNewConversation();\n this._toggleHistory(false);\n });\n this.conversationListView.on('conversation:deleted', (data) => this._onConversationDeleted(data));\n\n this._subscribeWS();\n }\n\n async onAfterRender() {\n await super.onAfterRender();\n\n const textarea = this.element.querySelector('[data-ref=\"input\"]');\n if (textarea) {\n textarea.addEventListener('input', () => this._autoResize(textarea));\n textarea.addEventListener('keydown', (e) => this._handleKeydown(e));\n setTimeout(() => textarea.focus(), 100);\n }\n\n // Load existing conversation after DOM is ready\n if (this.conversationId) {\n this._showChatArea();\n await this.chatView.refresh();\n }\n\n this._updateConnectionStatus();\n this._updateTitle();\n this._setupResizeHandle();\n }\n\n // ── Resize Handle ────────────────────────────────────────\n\n _setupResizeHandle() {\n const handle = this.element?.querySelector('[data-ref=\"resize-handle\"]');\n if (!handle) return;\n\n const MIN_WIDTH = 300;\n const MAX_WIDTH = 700;\n const STORAGE_KEY = 'mojo:assistant_panel_width';\n\n // Restore saved width\n const saved = localStorage.getItem(STORAGE_KEY);\n if (saved) {\n const w = parseInt(saved, 10);\n if (w >= MIN_WIDTH && w <= MAX_WIDTH) {\n const panelEl = document.getElementById('assistant-panel');\n if (panelEl) panelEl.style.width = w + 'px';\n }\n }\n\n let startX, startWidth;\n\n const onMouseMove = (e) => {\n const delta = startX - e.clientX;\n const newWidth = Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, startWidth + delta));\n const panelEl = document.getElementById('assistant-panel');\n if (panelEl) panelEl.style.width = newWidth + 'px';\n };\n\n const onMouseUp = () => {\n document.removeEventListener('mousemove', onMouseMove);\n document.removeEventListener('mouseup', onMouseUp);\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n\n // Save width\n const panelEl = document.getElementById('assistant-panel');\n if (panelEl) {\n localStorage.setItem(STORAGE_KEY, parseInt(panelEl.style.width, 10));\n }\n };\n\n handle.addEventListener('mousedown', (e) => {\n e.preventDefault();\n startX = e.clientX;\n const panelEl = document.getElementById('assistant-panel');\n startWidth = panelEl ? panelEl.offsetWidth : 500;\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp);\n });\n }\n\n // ── Actions ──────────────────────────────────────────────\n\n onActionToggleHistory() {\n this._toggleHistory(!this._showingHistory);\n }\n\n onActionNewConversation() {\n this._onNewConversation();\n if (this._showingHistory) this._toggleHistory(false);\n }\n\n onActionClosePanel() {\n this.emit('panel:close');\n }\n\n onActionFullscreen() {\n this.emit('panel:fullscreen', { conversationId: this.conversationId });\n }\n\n onActionPopOut() {\n this.emit('panel:popout', { conversationId: this.conversationId });\n }\n\n onActionUseSuggestion(_event, element) {\n const text = element.dataset.text || element.closest('[data-text]')?.dataset.text;\n if (!text) return;\n\n const textarea = this.element.querySelector('[data-ref=\"input\"]');\n if (textarea) {\n textarea.value = text;\n this._autoResize(textarea);\n }\n this._sendMessage();\n }\n\n onActionSend() {\n this._sendMessage();\n }\n\n onActionStop() {\n this.chatView.hideThinking();\n this._setInputEnabled(true);\n this._showSystemMessage('Response cancelled.');\n const textarea = this.element?.querySelector('[data-ref=\"input\"]');\n if (textarea) textarea.focus();\n }\n\n // ── History Toggle ───────────────────────────────────────\n\n _toggleHistory(show) {\n this._showingHistory = show;\n const history = this.element?.querySelector('[data-ref=\"history\"]');\n const chat = this.element?.querySelector('[data-ref=\"chat-wrapper\"]');\n const toggleBtn = this.element?.querySelector('[data-action=\"toggle-history\"] i');\n\n if (history) history.classList.toggle('d-none', !show);\n if (chat) chat.classList.toggle('d-none', show);\n if (toggleBtn) toggleBtn.className = show ? 'bi bi-chat-dots' : 'bi bi-list';\n\n if (show) {\n this.conversationListView.refresh();\n }\n }\n\n // ── Input Handling ───────────────────────────────────────\n\n _autoResize(textarea) {\n textarea.style.height = 'auto';\n textarea.style.height = Math.min(textarea.scrollHeight, 200) + 'px';\n }\n\n _handleKeydown(e) {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n this._sendMessage();\n }\n }\n\n async _sendMessage() {\n const textarea = this.element.querySelector('[data-ref=\"input\"]');\n if (!textarea) return;\n\n const text = textarea.value.trim();\n if (!text) return;\n\n textarea.value = '';\n textarea.style.height = 'auto';\n this._showChatArea();\n await this.chatView.adapter.addNote({ text, files: [] });\n }\n\n _showChatArea() {\n if (this._hasMessages) return;\n this._hasMessages = true;\n\n const welcome = this.element.querySelector('[data-ref=\"welcome\"]');\n const chatArea = this.element.querySelector('[data-container=\"chat-area\"]');\n if (welcome) welcome.classList.add('d-none');\n if (chatArea) chatArea.classList.remove('d-none');\n }\n\n _showWelcome() {\n this._hasMessages = false;\n\n const welcome = this.element.querySelector('[data-ref=\"welcome\"]');\n const chatArea = this.element.querySelector('[data-container=\"chat-area\"]');\n if (welcome) welcome.classList.remove('d-none');\n if (chatArea) chatArea.classList.add('d-none');\n }\n\n _setInputEnabled(enabled, reason) {\n const textarea = this.element?.querySelector('[data-ref=\"input\"]');\n const sendBtn = this.element?.querySelector('[data-ref=\"send-btn\"]');\n const stopBtn = this.element?.querySelector('[data-ref=\"stop-btn\"]');\n\n if (textarea) textarea.disabled = !enabled;\n if (sendBtn) sendBtn.classList.toggle('d-none', !enabled);\n if (stopBtn) stopBtn.classList.toggle('d-none', enabled);\n\n this._setInputStatus(enabled ? null : reason);\n\n if (this._responseTimeout) clearTimeout(this._responseTimeout);\n if (!enabled) {\n this._responseTimeout = setTimeout(() => this._onResponseTimeout(), 60000);\n } else {\n this._requestStartTime = null;\n }\n }\n\n _setInputStatus(message) {\n const el = this.element?.querySelector('[data-ref=\"input-status\"]');\n if (!el) return;\n if (message) {\n el.innerHTML = `${this._escapeHtml(message)} <span class=\"assistant-input-status-dismiss\">Click to dismiss</span>`;\n el.classList.remove('d-none');\n if (!el._hasDismiss) {\n el._hasDismiss = true;\n el.addEventListener('click', () => {\n this.chatView.hideThinking();\n this._setInputEnabled(true);\n const textarea = this.element?.querySelector('[data-ref=\"input\"]');\n if (textarea) textarea.focus();\n });\n }\n } else {\n el.classList.add('d-none');\n el.innerHTML = '';\n }\n }\n\n _onResponseTimeout() {\n this._responseTimeout = null;\n this.chatView.hideThinking();\n this._setInputEnabled(true);\n this._showSystemMessage('Request timed out. Please try again.');\n }\n\n // ── Title ────────────────────────────────────────────────\n\n _updateTitle(title) {\n const el = this.element?.querySelector('[data-ref=\"panel-title\"]');\n if (!el) return;\n el.textContent = title || (this.conversationId ? 'Assistant' : 'New conversation');\n }\n\n // ── Chat Adapter ─────────────────────────────────────────\n\n _createAdapter() {\n return {\n fetch: async () => {\n if (!this.conversationId) return [];\n try {\n const conversation = new AssistantConversation({ id: this.conversationId });\n await conversation.fetch({ graph: 'detail' });\n const title = conversation.get('title') || conversation.get('summary');\n if (title) this._updateTitle(title);\n const messages = conversation.get('messages') || [];\n const transformed = messages.map(msg => this._transformMessage(msg)).filter(Boolean);\n return AssistantView._collapseMessages(transformed);\n } catch (_err) {\n if (_err.status === 404) {\n this._onNewConversation();\n this._showSystemMessage('Conversation not found.');\n }\n return [];\n }\n },\n addNote: async (data) => {\n if (!data.text || !data.text.trim()) return { success: false };\n\n const userMsg = {\n id: `local-${++this._messageIdCounter}`,\n role: 'user',\n author: {\n id: this.app?.activeUser?.id,\n name: this.app?.activeUser?.get('display_name') || 'You'\n },\n content: data.text,\n timestamp: new Date().toISOString()\n };\n this.chatView.addMessage(userMsg);\n\n this.chatView.showThinking('Thinking...');\n this._requestStartTime = Date.now();\n this._setInputEnabled(false, 'Waiting for response…');\n\n if (this.ws && this.ws.isConnected) {\n this.ws.send({\n type: 'assistant_message',\n message: data.text,\n conversation_id: this.conversationId\n });\n } else {\n try {\n const resp = await this.app.rest.post('/api/assistant', {\n message: data.text,\n conversation_id: this.conversationId\n });\n const respData = resp?.data?.data || resp?.data || resp;\n if (respData.conversation_id) {\n this.conversationId = respData.conversation_id;\n this.app._assistantConversationId = this.conversationId;\n }\n if (respData.response) {\n this.chatView.addMessage(this._transformMessage(respData.response));\n }\n this._setInputEnabled(true);\n } catch (_err) {\n this._handleAPIError(_err);\n }\n }\n\n return { success: true };\n }\n };\n }\n\n // ── WebSocket Subscriptions ───────────────────────────────\n\n _subscribeWS() {\n if (!this.ws) return;\n\n this._wsHandlers = {\n thinking: (data) => this._onThinking(data),\n text: (data) => this._onText(data),\n tool_call: (data) => this._onToolCall(data),\n response: (data) => this._onResponse(data),\n error: (data) => this._onError(data),\n plan: (data) => this._onPlan(data),\n plan_update: (data) => this._onPlanUpdate(data),\n message: (envelope) => this._dispatchWSMessage(envelope),\n connected: () => this._updateConnectionStatus(),\n disconnected: () => this._updateConnectionStatus(),\n reconnecting: () => this._updateConnectionStatus()\n };\n\n this.ws.on('message:assistant_thinking', this._wsHandlers.thinking);\n this.ws.on('message:assistant_text', this._wsHandlers.text);\n this.ws.on('message:assistant_tool_call', this._wsHandlers.tool_call);\n this.ws.on('message:assistant_response', this._wsHandlers.response);\n this.ws.on('message:assistant_error', this._wsHandlers.error);\n this.ws.on('message:assistant_plan', this._wsHandlers.plan);\n this.ws.on('message:assistant_plan_update', this._wsHandlers.plan_update);\n this.ws.on('message:message', this._wsHandlers.message);\n this.ws.on('connected', this._wsHandlers.connected);\n this.ws.on('disconnected', this._wsHandlers.disconnected);\n this.ws.on('reconnecting', this._wsHandlers.reconnecting);\n }\n\n _unsubscribeWS() {\n if (!this.ws || !this._wsHandlers) return;\n\n this.ws.off('message:assistant_thinking', this._wsHandlers.thinking);\n this.ws.off('message:assistant_text', this._wsHandlers.text);\n this.ws.off('message:assistant_tool_call', this._wsHandlers.tool_call);\n this.ws.off('message:assistant_response', this._wsHandlers.response);\n this.ws.off('message:assistant_error', this._wsHandlers.error);\n this.ws.off('message:assistant_plan', this._wsHandlers.plan);\n this.ws.off('message:assistant_plan_update', this._wsHandlers.plan_update);\n this.ws.off('message:message', this._wsHandlers.message);\n this.ws.off('connected', this._wsHandlers.connected);\n this.ws.off('disconnected', this._wsHandlers.disconnected);\n this.ws.off('reconnecting', this._wsHandlers.reconnecting);\n\n this._wsHandlers = {};\n }\n\n // ── WS Event Handlers ────────────────────────────────────\n\n _dispatchWSMessage(envelope) {\n const inner = envelope?.data;\n if (!inner?.type) return;\n\n switch (inner.type) {\n case 'assistant_thinking': this._onThinking(inner); break;\n case 'assistant_text': this._onText(inner); break;\n case 'assistant_tool_call': this._onToolCall(inner); break;\n case 'assistant_response': this._onResponse(inner); break;\n case 'assistant_error': this._onError(inner); break;\n case 'assistant_plan': this._onPlan(inner); break;\n case 'assistant_plan_update': this._onPlanUpdate(inner); break;\n }\n }\n\n _isMyConversation(data) {\n if (!data.conversation_id) return true;\n if (!this.conversationId) return true;\n return String(data.conversation_id) === String(this.conversationId);\n }\n\n _adoptConversationId(data) {\n if (data.conversation_id && !this.conversationId) {\n this.conversationId = data.conversation_id;\n this.app._assistantConversationId = this.conversationId;\n }\n }\n\n _onThinking(data) {\n if (!this._isMyConversation(data)) return;\n this._adoptConversationId(data);\n this._showChatArea();\n this.chatView.showThinking('Thinking...');\n this._setInputEnabled(false, 'Assistant is thinking…');\n }\n\n /**\n * Intermediate prose alongside tool calls in the same turn. Renders as\n * an assistant bubble, but does NOT clear the thinking indicator or\n * re-enable input — `assistant_response` remains the terminal signal.\n * @private\n */\n _onText(data) {\n if (!this._isMyConversation(data)) return;\n this._adoptConversationId(data);\n // Server is still working — refresh the safety timeout.\n this._resetResponseTimeout();\n\n const msg = this._transformMessage({\n id: data.message_id || `text-${++this._messageIdCounter}`,\n role: 'assistant',\n content: data.text || '',\n blocks: data.blocks || [],\n tool_calls: [],\n created: data.created || data.timestamp || new Date().toISOString()\n });\n\n if (msg && (msg.content || msg.blocks?.length)) {\n this.chatView.addMessage(msg);\n }\n }\n\n _onToolCall(data) {\n if (!this._isMyConversation(data)) return;\n this.chatView.showThinking(`Using ${data.tool || data.name || 'tool'}...`);\n this._resetResponseTimeout();\n }\n\n _resetResponseTimeout() {\n if (this._responseTimeout) {\n if (this._requestStartTime && (Date.now() - this._requestStartTime) >= 300000) {\n this._onResponseTimeout();\n return;\n }\n clearTimeout(this._responseTimeout);\n this._responseTimeout = setTimeout(() => this._onResponseTimeout(), 60000);\n }\n }\n\n _onResponse(data) {\n if (!this._isMyConversation(data)) return;\n\n this.chatView.hideThinking();\n this._setInputEnabled(true);\n this._adoptConversationId(data);\n\n const textarea = this.element?.querySelector('[data-ref=\"input\"]');\n if (textarea) textarea.focus();\n\n const msg = this._transformMessage({\n id: data.message_id || `resp-${++this._messageIdCounter}`,\n role: 'assistant',\n content: data.response || data.content || data.message || '',\n blocks: data.blocks || [],\n tool_calls: data.tool_calls_made || data.tool_calls || [],\n created: data.created || data.timestamp || new Date().toISOString()\n });\n\n if (msg && (msg.content || msg.blocks?.length || msg.tool_calls?.length)) {\n this.chatView.addMessage(msg);\n }\n }\n\n _onError(data) {\n if (!this._isMyConversation(data)) return;\n\n this.chatView.hideThinking();\n this._setInputEnabled(true);\n this._adoptConversationId(data);\n\n const errorText = data.error || data.message || 'An error occurred';\n this._showSystemMessage(errorText);\n }\n\n _onPlan(data) {\n if (!this._isMyConversation(data)) return;\n this._adoptConversationId(data);\n this._showChatArea();\n\n const plan = data.plan;\n if (!plan) return;\n\n this._activePlans[plan.plan_id] = plan;\n\n this.chatView.addMessage({\n id: `plan-${plan.plan_id}`,\n role: 'assistant',\n author: { name: 'Assistant' },\n content: '',\n timestamp: new Date().toISOString(),\n blocks: [{ type: 'progress', ...plan }],\n tool_calls: []\n });\n }\n\n _onPlanUpdate(data) {\n if (!this._isMyConversation(data)) return;\n\n const plan = this._activePlans[data.plan_id];\n if (plan) {\n const step = plan.steps.find(s => s.id === data.step_id);\n if (step) {\n step.status = data.status;\n step.summary = data.summary;\n }\n }\n\n const msgView = this.chatView.messageViews.get(`plan-${data.plan_id}`);\n if (msgView?.updateProgressStep) {\n msgView.updateProgressStep(data.plan_id, data.step_id, data.status, data.summary);\n }\n this._resetResponseTimeout();\n }\n\n // ── Conversation Management ──────────────────────────────\n\n async _onConversationSelect(data) {\n this.conversationId = data.id;\n this.app._assistantConversationId = this.conversationId;\n this.conversationListView.setActive(data.id);\n this._showChatArea();\n this._updateTitle(data.model?.get('title') || data.model?.get('summary'));\n await this.chatView.refresh();\n }\n\n _onNewConversation() {\n this.conversationId = null;\n this.app._assistantConversationId = null;\n this.conversationListView.setActive(null);\n this.chatView.clearMessages();\n this._setInputEnabled(true);\n this._showWelcome();\n this._updateTitle();\n\n const textarea = this.element?.querySelector('[data-ref=\"input\"]');\n if (textarea) textarea.focus();\n }\n\n _onConversationDeleted(data) {\n if (String(data.id) === String(this.conversationId)) {\n this._onNewConversation();\n }\n }\n\n // ── Helpers ──────────────────────────────────────────────\n\n _transformMessage(msg) {\n if (msg.role === 'tool_result') return null;\n\n let content = msg.content || msg.text || '';\n let blocks = msg.blocks || [];\n let toolCalls = msg.tool_calls || [];\n\n if (toolCalls.length > 0) {\n // Normalize WS `tool_calls_made` shape `{ tool, input }` → Anthropic `{ type, name, input }`\n toolCalls = toolCalls.map(tc =>\n (!tc.type && tc.tool)\n ? { type: 'tool_use', name: tc.tool, input: tc.input }\n : tc\n );\n const textParts = toolCalls\n .filter(tc => tc.type === 'text' && tc.text)\n .map(tc => tc.text);\n if (!content && textParts.length > 0) {\n content = textParts.join('\\n\\n');\n }\n toolCalls = toolCalls\n .filter(tc => tc.type === 'tool_use')\n .filter(tc => !AssistantView.INTERNAL_TOOLS.has(tc.name));\n }\n\n if (blocks.length === 0 && content.includes('assistant_block')) {\n const parsed = AssistantView._parseBlocks(content);\n content = parsed.content;\n blocks = parsed.blocks;\n }\n\n const currentUserId = this.app?.activeUser?.id;\n\n return {\n id: msg.id,\n role: msg.role || 'user',\n author: msg.role === 'assistant'\n ? { name: 'Assistant' }\n : msg.author || {\n name: msg.user?.display_name || this.app?.activeUser?.get('display_name') || 'You',\n id: msg.user?.id || currentUserId\n },\n content,\n timestamp: msg.created || msg.timestamp,\n blocks,\n tool_calls: toolCalls,\n _conversationId: this.conversationId\n };\n }\n\n _showSystemMessage(text) {\n this._showChatArea();\n this.chatView.addMessage({\n id: `sys-${++this._messageIdCounter}`,\n type: 'system_event',\n content: text,\n timestamp: new Date().toISOString()\n });\n }\n\n _handleAPIError(_err) {\n if (_err.status === 404) {\n this._showSystemMessage('Assistant is not enabled on this server.');\n } else if (_err.status === 503) {\n this._showSystemMessage('LLM API key not configured. Contact your administrator.');\n } else {\n this._showSystemMessage('Failed to send message. Please try again.');\n }\n this._setInputEnabled(true);\n }\n\n _updateConnectionStatus() {\n const dot = this.element?.querySelector('.status-dot');\n if (!dot) return;\n\n if (this.ws?.isConnected) {\n dot.className = 'status-dot connected';\n dot.title = 'Connected';\n if (!this._responseTimeout) {\n this._setInputEnabled(true);\n } else {\n this._setInputEnabled(false, 'Waiting for response…');\n }\n } else if (this.ws?.isReconnecting) {\n dot.className = 'status-dot reconnecting';\n dot.title = 'Reconnecting...';\n this._setInputEnabled(false, 'Reconnecting…');\n if (this._responseTimeout) {\n clearTimeout(this._responseTimeout);\n this._responseTimeout = null;\n }\n } else {\n dot.className = 'status-dot disconnected';\n dot.title = 'Disconnected';\n this._setInputEnabled(false, 'Disconnected — reconnecting…');\n if (this._responseTimeout) {\n clearTimeout(this._responseTimeout);\n this._responseTimeout = null;\n }\n }\n }\n\n _escapeHtml(text) {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n\n /**\n * Focus the input textarea — called externally when reopening the panel.\n */\n focusInput() {\n const textarea = this.element?.querySelector('[data-ref=\"input\"]');\n if (textarea) textarea.focus();\n }\n\n async onBeforeDestroy() {\n this._unsubscribeWS();\n if (this._responseTimeout) {\n clearTimeout(this._responseTimeout);\n this._responseTimeout = null;\n }\n }\n}\n\nexport default AssistantPanelView;\n"],"names":["AssistantPanelView","View","constructor","options","super","className","this","app","ws","conversationId","_assistantConversationId","_wsHandlers","_messageIdCounter","_hasMessages","_activePlans","_requestStartTime","_showingHistory","getTemplate","_escapeHtml","activeUser","get","onInit","conversations","AssistantConversationList","params","user","id","conversationListView","AssistantConversationListView","containerId","collection","addChild","chatView","ChatView","theme","messageViewClass","AssistantMessageView","currentUserId","showFileInput","showInput","adapter","_createAdapter","origAddMessage","addMessage","bind","msg","scroll","role","content","blocks","length","hideThinking","_setInputEnabled","on","data","_onConversationSelect","_toggleHistory","_onNewConversation","_onConversationDeleted","_subscribeWS","onAfterRender","textarea","element","querySelector","addEventListener","_autoResize","e","_handleKeydown","setTimeout","focus","_showChatArea","refresh","_updateConnectionStatus","_updateTitle","_setupResizeHandle","handle","STORAGE_KEY","saved","localStorage","getItem","w","parseInt","panelEl","document","getElementById","style","width","startX","startWidth","onMouseMove","delta","clientX","newWidth","Math","min","max","onMouseUp","removeEventListener","body","cursor","userSelect","setItem","preventDefault","offsetWidth","onActionToggleHistory","onActionNewConversation","onActionClosePanel","emit","onActionFullscreen","onActionPopOut","onActionUseSuggestion","_event","text","dataset","closest","value","_sendMessage","onActionSend","onActionStop","_showSystemMessage","show","history","chat","toggleBtn","classList","toggle","height","scrollHeight","key","shiftKey","trim","addNote","files","welcome","chatArea","add","remove","_showWelcome","enabled","reason","sendBtn","stopBtn","disabled","_setInputStatus","_responseTimeout","clearTimeout","_onResponseTimeout","message","el","innerHTML","_hasDismiss","title","textContent","fetch","async","conversation","AssistantConversation","graph","transformed","map","_transformMessage","filter","Boolean","AssistantView","_collapseMessages","_err","status","success","userMsg","author","name","timestamp","Date","toISOString","showThinking","now","isConnected","send","type","conversation_id","resp","rest","post","respData","response","_handleAPIError","thinking","_onThinking","_onText","tool_call","_onToolCall","_onResponse","error","_onError","plan","_onPlan","plan_update","_onPlanUpdate","envelope","_dispatchWSMessage","connected","disconnected","reconnecting","_unsubscribeWS","off","inner","_isMyConversation","String","_adoptConversationId","_resetResponseTimeout","message_id","tool_calls","created","tool","tool_calls_made","errorText","plan_id","step","steps","find","s","step_id","summary","msgView","messageViews","updateProgressStep","setActive","model","clearMessages","toolCalls","tc","input","textParts","join","INTERNAL_TOOLS","has","includes","parsed","_parseBlocks","display_name","_conversationId","dot","isReconnecting","div","createElement","focusInput","onBeforeDestroy"],"mappings":"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"}