web-mojo 2.2.97 → 2.2.98

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 (114) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/dist/admin.cjs.js +1 -1
  3. package/dist/admin.es.js +1 -1
  4. package/dist/auth.cjs.js +1 -1
  5. package/dist/auth.es.js +1 -1
  6. package/dist/charts.cjs.js +1 -1
  7. package/dist/charts.es.js +1 -1
  8. package/dist/chunks/{AssistantPanelView-BR17_qm2.js → AssistantPanelView-BGuG2-e7.js} +2 -2
  9. package/dist/chunks/{AssistantPanelView-BR17_qm2.js.map → AssistantPanelView-BGuG2-e7.js.map} +1 -1
  10. package/dist/chunks/{AssistantPanelView-DFcOLZn2.js → AssistantPanelView-ti3iZFZJ.js} +2 -2
  11. package/dist/chunks/{AssistantPanelView-DFcOLZn2.js.map → AssistantPanelView-ti3iZFZJ.js.map} +1 -1
  12. package/dist/chunks/{ChatView-E-Y3ZAn2.js → ChatView-DCFwLZjg.js} +2 -2
  13. package/dist/chunks/{ChatView-E-Y3ZAn2.js.map → ChatView-DCFwLZjg.js.map} +1 -1
  14. package/dist/chunks/{ChatView-DzdJkSRe.js → ChatView-DQljthdV.js} +2 -2
  15. package/dist/chunks/{ChatView-DzdJkSRe.js.map → ChatView-DQljthdV.js.map} +1 -1
  16. package/dist/chunks/{Collection-DXcf6bOu.js → Collection-C39Oy2q0.js} +2 -2
  17. package/dist/chunks/{Collection-DXcf6bOu.js.map → Collection-C39Oy2q0.js.map} +1 -1
  18. package/dist/chunks/{Collection-DwIvN0yq.js → Collection-CyK0u557.js} +2 -2
  19. package/dist/chunks/{Collection-DwIvN0yq.js.map → Collection-CyK0u557.js.map} +1 -1
  20. package/dist/chunks/{ContextMenu-BWDMrvKJ.js → ContextMenu-D-C7V6J6.js} +2 -2
  21. package/dist/chunks/{ContextMenu-BWDMrvKJ.js.map → ContextMenu-D-C7V6J6.js.map} +1 -1
  22. package/dist/chunks/{ContextMenu-oonPaMfx.js → ContextMenu-hjqR1pGW.js} +2 -2
  23. package/dist/chunks/{ContextMenu-oonPaMfx.js.map → ContextMenu-hjqR1pGW.js.map} +1 -1
  24. package/dist/chunks/{DataView-DdrFwbjE.js → DataView-6lhf855r.js} +2 -2
  25. package/dist/chunks/{DataView-DdrFwbjE.js.map → DataView-6lhf855r.js.map} +1 -1
  26. package/dist/chunks/{DataView-BqQhHIhZ.js → DataView-Bb83ww5U.js} +2 -2
  27. package/dist/chunks/{DataView-BqQhHIhZ.js.map → DataView-Bb83ww5U.js.map} +1 -1
  28. package/dist/chunks/{Dialog-BO06wfM8.js → Dialog-99_2o2h6.js} +3 -3
  29. package/dist/chunks/{Dialog-BO06wfM8.js.map → Dialog-99_2o2h6.js.map} +1 -1
  30. package/dist/chunks/{Dialog-DVabZtKC.js → Dialog-C1p6V5qV.js} +3 -3
  31. package/dist/chunks/{Dialog-DVabZtKC.js.map → Dialog-C1p6V5qV.js.map} +1 -1
  32. package/dist/chunks/{FormView-CW7sg6-U.js → FormView-56cBWH2j.js} +3 -3
  33. package/dist/chunks/{FormView-CW7sg6-U.js.map → FormView-56cBWH2j.js.map} +1 -1
  34. package/dist/chunks/{FormView-DbxACn7-.js → FormView-Ej9wQv4A.js} +3 -3
  35. package/dist/chunks/{FormView-DbxACn7-.js.map → FormView-Ej9wQv4A.js.map} +1 -1
  36. package/dist/chunks/{ListView-ZsMVvvUQ.js → ListView-D_hOtfWZ.js} +2 -2
  37. package/dist/chunks/{ListView-ZsMVvvUQ.js.map → ListView-D_hOtfWZ.js.map} +1 -1
  38. package/dist/chunks/{ListView-DLyS4Nfd.js → ListView-Jkke6pU1.js} +2 -2
  39. package/dist/chunks/{ListView-DLyS4Nfd.js.map → ListView-Jkke6pU1.js.map} +1 -1
  40. package/dist/chunks/{MetricsCountryMapView-197-WHEu.js → MetricsCountryMapView-UdvJWArx.js} +2 -2
  41. package/dist/chunks/{MetricsCountryMapView-197-WHEu.js.map → MetricsCountryMapView-UdvJWArx.js.map} +1 -1
  42. package/dist/chunks/{MetricsCountryMapView-BgLr-rjI.js → MetricsCountryMapView-jLWCL6Hm.js} +2 -2
  43. package/dist/chunks/{MetricsCountryMapView-BgLr-rjI.js.map → MetricsCountryMapView-jLWCL6Hm.js.map} +1 -1
  44. package/dist/chunks/{MetricsMiniChartWidget-DrIFgvOj.js → MetricsMiniChartWidget-C7u5jcb0.js} +2 -2
  45. package/dist/chunks/{MetricsMiniChartWidget-DrIFgvOj.js.map → MetricsMiniChartWidget-C7u5jcb0.js.map} +1 -1
  46. package/dist/chunks/{MetricsMiniChartWidget-BMF6wIF9.js → MetricsMiniChartWidget-VIBJZ4wn.js} +2 -2
  47. package/dist/chunks/{MetricsMiniChartWidget-BMF6wIF9.js.map → MetricsMiniChartWidget-VIBJZ4wn.js.map} +1 -1
  48. package/dist/chunks/{MiniPieChart-eTjaZQGx.js → MiniPieChart-B3sM4Bjv.js} +2 -2
  49. package/dist/chunks/{MiniPieChart-eTjaZQGx.js.map → MiniPieChart-B3sM4Bjv.js.map} +1 -1
  50. package/dist/chunks/{MiniPieChart-DOFUDyEj.js → MiniPieChart-DL5Rynvm.js} +2 -2
  51. package/dist/chunks/{MiniPieChart-DOFUDyEj.js.map → MiniPieChart-DL5Rynvm.js.map} +1 -1
  52. package/dist/chunks/{MiniSeriesChart-DPwiySbr.js → MiniSeriesChart-C4DPVbU_.js} +2 -2
  53. package/dist/chunks/{MiniSeriesChart-DPwiySbr.js.map → MiniSeriesChart-C4DPVbU_.js.map} +1 -1
  54. package/dist/chunks/{MiniSeriesChart-Cs8F8j0y.js → MiniSeriesChart-DdNMLwfh.js} +2 -2
  55. package/dist/chunks/{MiniSeriesChart-Cs8F8j0y.js.map → MiniSeriesChart-DdNMLwfh.js.map} +1 -1
  56. package/dist/chunks/{Modal-D_bVwX-V.js → Modal-BLaJTwNQ.js} +2 -2
  57. package/dist/chunks/{Modal-D_bVwX-V.js.map → Modal-BLaJTwNQ.js.map} +1 -1
  58. package/dist/chunks/{Modal-MSmE_82x.js → Modal-IG_UGRMf.js} +2 -2
  59. package/dist/chunks/{Modal-MSmE_82x.js.map → Modal-IG_UGRMf.js.map} +1 -1
  60. package/dist/chunks/{PDFViewer-b0l9yCQw.js → PDFViewer-D5QdfNWT.js} +2 -2
  61. package/dist/chunks/{PDFViewer-b0l9yCQw.js.map → PDFViewer-D5QdfNWT.js.map} +1 -1
  62. package/dist/chunks/{PDFViewer-Dv2OEqy0.js → PDFViewer-Erds3gKx.js} +2 -2
  63. package/dist/chunks/{PDFViewer-Dv2OEqy0.js.map → PDFViewer-Erds3gKx.js.map} +1 -1
  64. package/dist/chunks/{Passkeys-CZ_oTngY.js → Passkeys-BIV_WQTC.js} +2 -2
  65. package/dist/chunks/{Passkeys-CZ_oTngY.js.map → Passkeys-BIV_WQTC.js.map} +1 -1
  66. package/dist/chunks/{Passkeys-C6VT-snT.js → Passkeys-CbIVCcrV.js} +2 -2
  67. package/dist/chunks/{Passkeys-C6VT-snT.js.map → Passkeys-CbIVCcrV.js.map} +1 -1
  68. package/dist/chunks/{TokenManager-BUzSwY3u.js → TokenManager-CHlIEAGa.js} +2 -2
  69. package/dist/chunks/{TokenManager-BUzSwY3u.js.map → TokenManager-CHlIEAGa.js.map} +1 -1
  70. package/dist/chunks/{TokenManager-BzMDp2Ym.js → TokenManager-DrIJVcOt.js} +2 -2
  71. package/dist/chunks/{TokenManager-BzMDp2Ym.js.map → TokenManager-DrIJVcOt.js.map} +1 -1
  72. package/dist/chunks/{UserProfileView-NpL2wU6h.js → UserProfileView-6oMkhsyq.js} +2 -2
  73. package/dist/chunks/{UserProfileView-NpL2wU6h.js.map → UserProfileView-6oMkhsyq.js.map} +1 -1
  74. package/dist/chunks/{UserProfileView-CxrYFgMl.js → UserProfileView-BhaajMo4.js} +2 -2
  75. package/dist/chunks/{UserProfileView-CxrYFgMl.js.map → UserProfileView-BhaajMo4.js.map} +1 -1
  76. package/dist/chunks/{WebApp-DpuN7rZ3.js → WebApp-Bb7bEVO-.js} +2 -2
  77. package/dist/chunks/{WebApp-DpuN7rZ3.js.map → WebApp-Bb7bEVO-.js.map} +1 -1
  78. package/dist/chunks/{WebApp-CyeQb4cM.js → WebApp-CXZl59le.js} +2 -2
  79. package/dist/chunks/{WebApp-CyeQb4cM.js.map → WebApp-CXZl59le.js.map} +1 -1
  80. package/dist/chunks/{WebSocketClient-CPJGeiPN.js → WebSocketClient-BQAZr8C4.js} +2 -2
  81. package/dist/chunks/{WebSocketClient-CPJGeiPN.js.map → WebSocketClient-BQAZr8C4.js.map} +1 -1
  82. package/dist/chunks/{WebSocketClient-Cjmr5C_u.js → WebSocketClient-YR5d82h8.js} +2 -2
  83. package/dist/chunks/{WebSocketClient-Cjmr5C_u.js.map → WebSocketClient-YR5d82h8.js.map} +1 -1
  84. package/dist/chunks/{admin-B4J2Qfvt.js → admin-BHppr_L3.js} +2 -2
  85. package/dist/chunks/admin-BHppr_L3.js.map +1 -0
  86. package/dist/chunks/{admin-CYy-fnPz.js → admin-DkDOQQa1.js} +2 -2
  87. package/dist/chunks/admin-DkDOQQa1.js.map +1 -0
  88. package/dist/chunks/{index-D3v4btI8.js → index-5KtcUYiX.js} +2 -2
  89. package/dist/chunks/{index-D3v4btI8.js.map → index-5KtcUYiX.js.map} +1 -1
  90. package/dist/chunks/{index-BPn9cZzq.js → index-BHEAlNEb.js} +2 -2
  91. package/dist/chunks/{index-BPn9cZzq.js.map → index-BHEAlNEb.js.map} +1 -1
  92. package/dist/chunks/{version-hgKnkQjn.js → version-C8bxzJU0.js} +2 -2
  93. package/dist/chunks/{version-hgKnkQjn.js.map → version-C8bxzJU0.js.map} +1 -1
  94. package/dist/chunks/{version-CT8Bg3nZ.js → version-nBNoiDmZ.js} +2 -2
  95. package/dist/chunks/{version-CT8Bg3nZ.js.map → version-nBNoiDmZ.js.map} +1 -1
  96. package/dist/docit.cjs.js +1 -1
  97. package/dist/docit.es.js +1 -1
  98. package/dist/index.cjs.js +1 -1
  99. package/dist/index.es.js +1 -1
  100. package/dist/lightbox.cjs.js +1 -1
  101. package/dist/lightbox.es.js +1 -1
  102. package/dist/map.cjs.js +1 -1
  103. package/dist/map.es.js +1 -1
  104. package/dist/timeline.cjs.js +1 -1
  105. package/dist/timeline.es.js +1 -1
  106. package/dist/user-profile.cjs.js +1 -1
  107. package/dist/user-profile.es.js +1 -1
  108. package/dist/web-mojo.lite.iife.js +8 -2
  109. package/dist/web-mojo.lite.iife.js.map +1 -1
  110. package/dist/web-mojo.lite.iife.min.js +1 -1
  111. package/dist/web-mojo.lite.iife.min.js.map +1 -1
  112. package/package.json +1 -1
  113. package/dist/chunks/admin-B4J2Qfvt.js.map +0 -1
  114. package/dist/chunks/admin-CYy-fnPz.js.map +0 -1
@@ -12,7 +12,7 @@ var MOJO=(function(A){"use strict";class re{constructor(e={}){this.defaultRoute=
12
12
  ${r}
13
13
  </span>
14
14
  `}nl2br(e){return e==null?"":this.escapeHtml(String(e)).replace(/\r\n|\r|\n/g,"<br>")}code(e,t=""){if(e==null)return"";const s=t?`language-${this.escapeHtml(String(t))}`:"",i=this.escapeHtml(String(e));return`<pre class="bg-light p-2 rounded border"><code class="${s}">${i}</code></pre>`}register(e,t){if(typeof t!="function")throw new Error(`Formatter must be a function, got ${typeof t}`);return this.formatters.set(e.toLowerCase(),t),this}apply(e,t,...s){try{const i=this.formatters.get(e.toLowerCase());return i?i(t,...s):(console.warn(`Formatter '${e}' not found`),t)}catch(i){return console.error(`Error in formatter '${e}':`,i),t}}pipe(e,t,s=null){return t?this.parsePipeString(t,s).reduce((a,r)=>this.apply(r.name,a,...r.args),e):e}parsePipeString(e,t=null){const s=[],i=e.split("|").map(a=>a.trim());for(const a of i){const r=this.parseFormatter(a,t);r&&s.push(r)}return s}parseFormatter(e,t=null){const s=e.match(/^([a-zA-Z_]\w*)\s*\((.*)\)$/);if(s){const[,a,r]=s,n=r?this.parseArguments(r,t):[];return{name:a,args:n}}const i=e.match(/^([a-zA-Z_]\w*)(?::(.+))?$/);if(i){const[,a,r]=i,n=r?this.parseColonArguments(r,t):[];return{name:a,args:n}}return null}parseArguments(e,t=null){const s=[];let i="",a=!1,r=null,n=0;for(let o=0;o<e.length;o++){const l=e[o];!a&&(l==='"'||l==="'")?(a=!0,r=l,i+=l):a&&l===r&&e[o-1]!=="\\"?(a=!1,r=null,i+=l):!a&&l==="{"?(n++,i+=l):!a&&l==="}"?(n--,i+=l):!a&&n===0&&l===","?(s.push(this.parseValue(i.trim(),t)),i=""):i+=l}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseColonArguments(e,t=null){const s=[];let i="",a=!1,r=null;for(let n=0;n<e.length;n++){const o=e[n];!a&&(o==='"'||o==="'")?(a=!0,r=o,i+=o):a&&o===r&&e[n-1]!=="\\"?(a=!1,r=null,i+=o):!a&&o===":"?(s.push(this.parseValue(i.trim(),t)),i=""):i+=o}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseValue(e,t=null){if(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);if(e==="true")return!0;if(e==="false")return!1;if(e==="null")return null;if(e!=="undefined"){if(!isNaN(e)&&e!=="")return Number(e);if(e.startsWith("{")&&e.endsWith("}"))try{return JSON.parse(e)}catch{}if(t&&this.isIdentifier(e)){if(!e.includes(".")&&Object.prototype.hasOwnProperty.call(t,e))return t[e];if(t.get&&typeof t.get=="function"){const s=t.get(e);if(s!==void 0)return s}if(t.getContextValue&&typeof t.getContextValue=="function"){const s=t.getContextValue(e);if(s!==void 0)return s}if(e.includes(".")){const s=window.MOJOUtils||(typeof require<"u"?require("./MOJOUtils.js").default:null);if(s){const i=s.getNestedValue(t,e);if(i!==void 0)return i}}}return e}}isIdentifier(e){return/^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/.test(e)}date(e,t="MM/DD/YYYY"){if(!e)return"";e=this.normalizeEpoch(e);let s;if(e instanceof Date)s=e;else if(typeof e=="string")if(/^\d{4}-\d{2}-\d{2}$/.test(e)){const[n,o,l]=e.split("-").map(Number);s=new Date(n,o-1,l)}else s=new Date(e);else s=new Date(e);if(isNaN(s.getTime()))return String(e);const i={YYYY:s.getFullYear(),YY:String(s.getFullYear()).slice(-2),MMMM:s.toLocaleDateString("en-US",{month:"long"}),MMM:s.toLocaleDateString("en-US",{month:"short"}),MM:String(s.getMonth()+1).padStart(2,"0"),M:s.getMonth()+1,dddd:s.toLocaleDateString("en-US",{weekday:"long"}),ddd:s.toLocaleDateString("en-US",{weekday:"short"}),DD:String(s.getDate()).padStart(2,"0"),D:s.getDate()};let a=t;const r=new RegExp(`(${Object.keys(i).join("|")})`,"g");return a=a.replace(r,n=>i[n]||n),a}time(e,t="HH:mm:ss"){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const i=s.getHours(),a={HH:String(i).padStart(2,"0"),H:i,hh:String(i%12||12).padStart(2,"0"),h:i%12||12,mm:String(s.getMinutes()).padStart(2,"0"),m:s.getMinutes(),ss:String(s.getSeconds()).padStart(2,"0"),s:s.getSeconds(),A:i>=12?"PM":"AM",a:i>=12?"pm":"am"};let r=t;const n=Object.keys(a).sort((o,l)=>l.length-o.length);for(const o of n)r=r.replace(new RegExp(o,"g"),a[o]);return r}datetime(e,t="MM/DD/YYYY",s="HH:mm:ss"){e=this.normalizeEpoch(e);const i=this.date(e,t),a=this.time(e,s);return i&&a?`${i} ${a}`:""}datetime_tz(e,t="MM/DD/YYYY",s="HH:mm:ss",i={}){if(!e)return"";e=this.normalizeEpoch(e);const a=e instanceof Date?e:new Date(e);if(isNaN(a.getTime()))return String(e);const r=i&&i.locale||"en-US",n=i&&i.timeZone?i.timeZone:void 0,o=()=>{let M="";try{const z=new Intl.DateTimeFormat(r,{hour:"2-digit",minute:"2-digit",timeZoneName:"short",...n?{timeZone:n}:{}}).formatToParts(a).find(O=>O.type==="timeZoneName");if(M=z?z.value:"",M&&/^GMT[+-]/i.test(M))try{const B=new Intl.DateTimeFormat(r,{timeStyle:"short",timeZoneName:"short",...n?{timeZone:n}:{}}).formatToParts(a).find(dt=>dt.type==="timeZoneName");B&&B.value&&!/^GMT[+-]/i.test(B.value)&&(M=B.value)}catch{}if(M&&/\s/.test(M)){const O=M.split(/\s+/).map(B=>B[0]).join("").toUpperCase();O.length>=2&&O.length<=4&&(M=O)}}catch{M=""}return M};if(!n){const M=this.date(a,t),H=this.time(a,s),z=o();return M&&H?`${M} ${H} ${z}`.trim():""}const l=new Intl.DateTimeFormat(r,{timeZone:n,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hourCycle:"h23"}).formatToParts(a),c=M=>{const H=l.find(z=>z.type===M);return H?H.value:""},d=c("year"),h=c("month"),m=c("day"),p=c("hour"),f=c("minute"),g=c("second"),y=h?String(parseInt(h,10)):"",b=m?String(parseInt(m,10)):"",v=p?String(parseInt(p,10)):"",S=p?parseInt(p,10)%12||12:"",F=p?parseInt(p,10)>=12?"PM":"AM":"",D=F?F.toLowerCase():"",V=new Intl.DateTimeFormat(r,{timeZone:n,month:"long"}).format(a),P=new Intl.DateTimeFormat(r,{timeZone:n,month:"short"}).format(a),I=new Intl.DateTimeFormat(r,{timeZone:n,weekday:"long"}).format(a),Z=new Intl.DateTimeFormat(r,{timeZone:n,weekday:"short"}).format(a),xe={YYYY:d,YY:d?d.slice(-2):"",MMMM:V,MMM:P,MM:h,M:y,dddd:I,ddd:Z,DD:m,D:b},$e={HH:p,H:v,hh:S!==""?String(S).padStart(2,"0"):"",h:S!==""?String(S):"",mm:f,m:f?String(parseInt(f,10)):"",ss:g,s:g?String(parseInt(g,10)):"",A:F,a:D},k=(M,H)=>{if(!M)return"";const z=new RegExp(`(${Object.keys(H).sort((O,B)=>B.length-O.length).join("|")})`,"g");return M.replace(z,O=>H[O]??O)},q=k(t,xe),Le=k(s,$e),ct=o();return q&&Le?`${q} ${Le} ${ct}`.trim():""}normalizeEpoch(e){if(typeof e!="number"&&(e=Number(e)),isNaN(e))return"";if(e<1e11)return e*1e3;if(e>1e12&&e<1e13)return e;throw new Error("Value doesn't look like epoch seconds or ms")}date_range(e,t=null,s="MM/DD/YYYY"){if(!e)return"";const i=t||new Date,a=this.date(e,s),r=this.date(i,s);return!a||!r?"":`${a} - ${r}`}datetime_range(e,t=null,s="MM/DD/YYYY",i="HH:mm"){if(!e)return"";const a=t||new Date,r=this.datetime(e,s,i),n=this.datetime(a,s,i);return!r||!n?"":`${r} - ${n}`}relative(e,t=!1){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const a=s-new Date,r=Math.abs(a),n=Math.floor(r/1e3),o=Math.floor(n/60),l=Math.floor(o/60),c=Math.floor(l/24),d=a>0;if(t)return c>365?Math.floor(c/365)+"y":c>30?Math.floor(c/30)+"mo":c>7?Math.floor(c/7)+"w":c>0?c+"d":l>0?l+"h":o>0?o+"m":"now";if(c>365){const h=Math.floor(c/365),m=d?"in ":"",p=d?"":" ago";return m+h+" year"+(h>1?"s":"")+p}if(c>30){const h=Math.floor(c/30),m=d?"in ":"",p=d?"":" ago";return m+h+" month"+(h>1?"s":"")+p}if(c>7){const h=Math.floor(c/7),m=d?"in ":"",p=d?"":" ago";return m+h+" week"+(h>1?"s":"")+p}if(c===1)return d?"tomorrow":"yesterday";if(c>0){const h=d?"in ":"",m=d?"":" ago";return h+c+" days"+m}if(l>0){const h=d?"in ":"",m=d?"":" ago";return h+l+" hour"+(l>1?"s":"")+m}if(o>0){const h=d?"in ":"",m=d?"":" ago";return h+o+" minute"+(o>1?"s":"")+m}if(n>30){const h=d?"in ":"",m=d?"":" ago";return h+n+" seconds"+m}return"just now"}iso(e,t=!1){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);return isNaN(s.getTime())?String(e):t?s.toISOString().split("T")[0]:s.toISOString()}number(e,t=2,s="en-US"){const i=parseFloat(e);return isNaN(i)?String(e):i.toLocaleString(s,{minimumFractionDigits:t,maximumFractionDigits:t})}currency(e,t="$",s=2){const i=parseInt(e);if(isNaN(i))return String(e);const a=Math.abs(i).toString(),r=i<0?"-":"";let n,o;a.length<=2?(n="0",o=a.padStart(2,"0")):(n=a.slice(0,-2),o=a.slice(-2)),n=n.replace(/\B(?=(\d{3})+(?!\d))/g,",");let l;if(s===0)parseInt(o)>=50&&(n=(parseInt(n.replace(/,/g,""))+1).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")),l=n;else if(s===2)l=`${n}.${o}`;else{const c=o.slice(0,s).padEnd(s,"0");l=`${n}.${c}`}return r+t+l}percent(e,t=0,s=!0){const i=parseFloat(e);if(isNaN(i))return String(e);const a=s?i*100:i;return this.number(a,t)+"%"}filesize(e,t=!1,s=1){const i=parseInt(e);if(isNaN(i))return String(e);const a=t?["B","KiB","MiB","GiB","TiB"]:["B","KB","MB","GB","TB"],r=t?1024:1e3;let n=i,o=0;for(;n>=r&&o<a.length-1;)n/=r,o++;const l=o===0?0:s;return`${n.toFixed(l)} ${a[o]}`}ordinal(e,t=!1){const s=parseInt(e);if(isNaN(s))return String(e);const i=s%10,a=s%100;let r="th";return i===1&&a!==11?r="st":i===2&&a!==12?r="nd":i===3&&a!==13&&(r="rd"),t?r:s+r}compact(e,t=1){const s=parseFloat(e);if(isNaN(s))return String(e);const i=Math.abs(s),a=s<0?"-":"";return i>=1e9?a+(i/1e9).toFixed(t)+"B":i>=1e6?a+(i/1e6).toFixed(t)+"M":i>=1e3?a+(i/1e3).toFixed(t)+"K":String(s)}add(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s+i}subtract(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s-i}multiply(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s*i}divide(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)||i===0?e:s/i}capitalize(e,t=!0){const s=String(e);return s?t?s.replace(/\b\w/g,i=>i.toUpperCase()):s.charAt(0).toUpperCase()+s.slice(1):""}replace(e,t,s="",i="g"){if(e==null)return"";const a=String(e);if(t==null||t==="")return a;if(t instanceof RegExp)return a.replace(t,String(s));const r=String(t),n=r.match(/^\/(.+)\/([a-z]*)$/i);if(n){const[,o,l]=n;try{return a.replace(new RegExp(o,l),String(s))}catch{}}return String(i).includes("g")?a.split(r).join(String(s)):a.replace(r,String(s))}truncate(e,t=50,s="..."){const i=String(e);return i.length<=t?i:i.substring(0,t)+s}truncate_front(e,t=8,s="..."){const i=String(e);return i.length<=t?i:`${s}${i.slice(-t)}`}truncate_middle(e,t=8,s="***"){const i=String(e);if(i.length<=t)return i;const a=Math.floor(t/2),r=i.substring(0,a),n=i.substring(i.length-a);return`${r}${s}${n}`}slug(e,t="-"){return String(e).toLowerCase().replace(/[^\w\s-]/g,"").replace(/\s+/g,t).replace(new RegExp(`${t}+`,"g"),t).replace(new RegExp(`^${t}|${t}$`,"g"),"")}initials(e,t=2){return String(e).split(/\s+/).filter(a=>a.length>0).slice(0,t).map(a=>a.charAt(0).toUpperCase()).join("")}mask(e,t="*",s=4){const i=String(e);if(i.length<=s)return i;const a=t.repeat(Math.max(0,i.length-s)),r=i.slice(-s);return a+r}email(e,t={}){const s=String(e).trim();if(!s)return"";if(t.link===!1)return s;const i=t.subject?`?subject=${encodeURIComponent(t.subject)}`:"",a=t.body?`&body=${encodeURIComponent(t.body)}`:"",r=t.class?` class="${t.class}"`:"";return`<a href="mailto:${s}${i}${a}"${r}>${s}</a>`}phone(e,t="US",s=!0){let i=String(e).replace(/\D/g,""),a=i;return t==="US"&&(i.length===10?a=`(${i.slice(0,3)}) ${i.slice(3,6)}-${i.slice(6)}`:i.length===11&&i[0]==="1"&&(a=`+1 (${i.slice(1,4)}) ${i.slice(4,7)}-${i.slice(7)}`)),s?`<a href="tel:${i}">${a}</a>`:a}url(e,t=null,s=!0){let i=String(e).trim();return i?(/^https?:\/\//.test(i)||(i="https://"+i),`<a href="${i}"${s?' target="_blank"':""}${s?' rel="noopener noreferrer"':""}>${t||i}</a>`):""}badge(e,t="auto"){if(Array.isArray(e))return e.map(r=>this.badge(r,t)).join(" ");const s=String(e);if(typeof t=="string"&&t.includes("=")){const r=Object.fromEntries(t.split(",").map(l=>l.split("=").map(c=>c.trim()))),n=r[s]||r[s.toLowerCase()]||this.inferBadgeType(s);return`<span class="badge ${n?`bg-${n}`:"bg-secondary"}">${s}</span>`}const i=t==="auto"?this.inferBadgeType(s):t;return`<span class="badge ${i?`bg-${i}`:"bg-secondary"}">${s}</span>`}badgeClass(e,t="auto"){const s=String(e),i=t==="auto"?this.inferBadgeType(s):t;return i?`bg-${i}`:"bg-secondary"}inferBadgeType(e){const t=e.toLowerCase();return["active","pass","success","complete","completed","approved","done","true","on","yes"].includes(t)?"success":["error","failed","fail","rejected","deleted","cancelled","false","off","no","declined"].includes(t)?"danger":["warning","pending","review","processing","uploading"].includes(t)?"warning":["info","new","draft"].includes(t)?"info":(["inactive","disabled","archived","suspended"].includes(t),"secondary")}status(e){return this._status(e)}status_icon(e){return this._status(e,{},{},!1,!0)}status_text(e){return this._status(e,{},{},!0,!1)}_status(e,t={},s={},i=!1,a=!1){const r=String(e).toLowerCase(),n={active:"bi bi-check-circle-fill",approved:"bi bi-check-circle-fill",declined:"bi bi-x-circle-fill",inactive:"bi bi-pause-circle-fill",pending:"bi bi-clock-fill",success:"bi bi-check-circle-fill",error:"bi bi-exclamation-triangle-fill",warning:"bi bi-exclamation-triangle-fill"},o={active:"success",approved:"success",declined:"danger",inactive:"secondary",pending:"warning",success:"success",error:"danger",warning:"warning"},l=t[r]||n[r]||"",c=s[r]||o[r]||"secondary";let d="";!i&&l&&(d=`<i class="${l}"></i>`);let h="";return a||(h=e),`<span class="text-${c}">${d}${d?" ":""}${h}</span>`}boolean(e,t="True",s="False",i=!1){const a=e?t:s;return i?`<span class="text-${e?"success":"danger"}">${a}</span>`:a}bool(e){return e==null||e===0||e===""||e===!1||e==="false"?!1:e===!0||e==="true"?!0:!(Array.isArray(e)&&e.length===0||e&&typeof e=="object"&&e.constructor===Object&&Object.keys(e).length===0)}icon(e,t={}){const s=String(e).toLowerCase(),i=t[s]||"";return i?`<i class="${i}"></i>`:""}yesnoicon(e,t="bi bi-check-circle-fill text-success",s="bi bi-x-circle-fill text-danger"){return e?`<i class="${t}"></i>`:`<i class="${s}"></i>`}image(e,t="thumbnail",s="img-fluid",i=""){const a=this._extractImageUrl(e,t);return a?`<img src="${a}" class="${s}" alt="${i}" />`:""}avatar(e,t="md",s="rounded-circle",i=""){const a=this._extractImageUrl(e,"square_sm")||Oe,r={xs:"width: 1.5rem; height: 1.5rem;",sm:"width: 2rem; height: 2rem;",md:"width: 3rem; height: 3rem;",lg:"width: 4rem; height: 4rem;",xl:"width: 5rem; height: 5rem;"},n=r[t]||r.md,l=`object-fit-cover ${s}`.trim();return`<img src="${a}" class="${l}" style="${n}" alt="${i}" />`}tooltip(e,t="",s="top",i=""){if(e==null)return"";const a=String(e),r=i==="html"?t:this.escapeHtml(t);return`<span data-bs-toggle="tooltip" data-bs-placement="${s}" ${i==="html"?'data-bs-html="true"':""} data-bs-title="${r}">${a}</span>`}_extractImageUrl(e,t="thumbnail"){if(!e)return null;if(typeof e=="string")return e;if(typeof e=="object"){if(e.attributes&&(e=e.attributes),t==="thumbnail"&&e.thumbnail&&typeof e.thumbnail=="string")return e.thumbnail;if(e.renditions&&typeof e.renditions=="object"){const s=e.renditions[t];if(s&&s.url)return s.url;const i=Object.values(e.renditions);if(i.length>0&&i[0].url)return i[0].url}if(e.url)return e.url}return null}default(e,t=""){return e==null||e===""?t:e}equals(e,t,s,i=""){return e==t?s:i}plural(e,t,s=null,i=!0){if(e==null||t===null||t===void 0)return i?`${e} ${t}`:t||"";const a=parseInt(e);if(isNaN(a))return i?`${e} ${t}`:t||"";const r=Math.abs(a)===1?t:s||t+"s";return i?`${a} ${r}`:r}formatList(e,t={}){if(!Array.isArray(e))return String(e);const{conjunction:s="and",limit:i=null,moreText:a="others"}=t;if(e.length===0)return"";if(e.length===1)return String(e[0]);let r=e.slice(),n=!1;if(i&&e.length>i&&(r=e.slice(0,i),n=!0),n){const o=e.length-i;return`${r.join(", ")}, ${s} ${o} ${a}`}return r.length===2?`${r[0]} ${s} ${r[1]}`:`${r.slice(0,-1).join(", ")}, ${s} ${r[r.length-1]}`}duration(e,t="ms",s=!1,i=2){if(e==null)return"";const a=parseFloat(e);if(isNaN(a))return String(e);let r;switch(t){case"s":case"sec":case"seconds":r=a*1e3;break;case"m":case"min":case"minutes":r=a*6e4;break;case"h":case"hr":case"hours":r=a*36e5;break;case"d":case"day":case"days":r=a*864e5;break;default:r=a}const n=[{name:"day",short:"d",value:864e5},{name:"hour",short:"h",value:36e5},{name:"minute",short:"m",value:6e4},{name:"second",short:"s",value:1e3}];if(r===0)return s?"0s":"0 seconds";const o=Math.abs(r),l=r<0?"-":"",c=[];let d=o;for(const h of n)if(d>=h.value){const m=Math.floor(d/h.value);d=d%h.value;const p=s?h.short:m===1?h.name:h.name+"s";if(c.push(s?`${m}${p}`:`${m} ${p}`),c.length>=i)break}return c.length===0?s?`${Math.round(o)}ms`:`${Math.round(o)} milliseconds`:l+(s?c.join(""):c.join(" "))}hash(e,t=8,s="",i="..."){if(e==null)return"";const a=String(e);return a.length<=t?s+a:s+a.substring(0,t)+i}stripHtml(e){return e==null?"":String(e).replace(/<[^>]*>/g,"")}highlight(e,t,s="highlight"){if(e==null||!t)return String(e||"");const i=String(t).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),a=new RegExp(`(${i})`,"gi");return String(e).replace(a,`<mark class="${s}">$1</mark>`)}hex(e,t=!1,s=!1){if(e==null)return"";let i="";const a=r=>Array.from(r).map(n=>n.toString(16).padStart(2,"0")).join("");if(typeof e=="number"){let r=Math.abs(Math.trunc(e)).toString(16);r.length%2&&(r="0"+r),i=r}else if(e instanceof Uint8Array)i=a(e);else if(e instanceof ArrayBuffer)i=a(new Uint8Array(e));else if(Array.isArray(e)&&e.every(r=>typeof r=="number"))i=a(Uint8Array.from(e.map(r=>r&255)));else{const n=new TextEncoder().encode(String(e));i=a(n)}return t&&(i=i.toUpperCase()),(s?"0x":"")+i}unhex(e){if(e==null)return"";let t=String(e).trim();if((t.startsWith("0x")||t.startsWith("0X"))&&(t=t.slice(2)),t=t.replace(/\s+/g,""),t.length===0)return"";t.length%2!==0&&(t="0"+t);const s=new Uint8Array(t.length/2);for(let i=0;i<t.length;i+=2){const a=parseInt(t.slice(i,i+2),16);if(Number.isNaN(a))return String(e);s[i/2]=a}try{return new TextDecoder().decode(s)}catch{let a="";for(const r of s)a+=String.fromCharCode(r);return a}}json(e,t=2){try{return JSON.stringify(e,null,t)}catch{return String(e)}}has(e){return this.formatters.has(e.toLowerCase())}unregister(e){return this.formatters.delete(e.toLowerCase())}listFormatters(){return Array.from(this.formatters.keys()).sort()}iter(e){return e==null?[]:Array.isArray(e)?e:typeof e=="object"?Object.entries(e).map(([t,s])=>({key:t,value:s})):[{key:"0",value:e}]}}const L=new qe;window.dataFormatter=L;class x{static getContextData(e,t){if(!t||e==null)return;let s=t,i="",a=0,r=-1;for(let o=0;o<t.length;o++){const l=t[o];if(l==="(")a++;else if(l===")")a--;else if(l==="|"&&a===0){r=o;break}}r>-1&&(s=t.substring(0,r).trim(),i=t.substring(r+1).trim());const n=this.getNestedValue(e,s);return i?L.pipe(n,i,e):n}static getNestedValue(e,t){if(!t||e==null)return;if(!t.includes(".")){if(t in e){const a=e[t];return typeof a=="function"?a.call(e):a}return}const s=t.split(".");let i=e;for(let a=0;a<s.length;a++){const r=s[a];if(i==null)return;if(a===0)if(i.hasOwnProperty(r)){const n=i[r];typeof n=="function"?i=n.call(e):i=n}else return;else{if(i&&typeof i.getContextValue=="function"){const n=s.slice(a).join(".");return i.getContextValue(n)}if(Array.isArray(i)&&!isNaN(r))i=i[parseInt(r)];else if(i.hasOwnProperty(r))i=i[r];else if(typeof i[r]=="function")i=i[r].call(i);else return}}return i}static isNullOrUndefined(e){return e==null}static deepClone(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(e instanceof Array)return e.map(t=>this.deepClone(t));if(e instanceof Object){const t={};for(const s in e)e.hasOwnProperty(s)&&(t[s]=this.deepClone(e[s]));return t}}static deepMerge(e,...t){if(!t.length)return e;const s=t.shift();if(this.isObject(e)&&this.isObject(s))for(const i in s)this.isObject(s[i])?(e[i]||Object.assign(e,{[i]:{}}),this.deepMerge(e[i],s[i])):Object.assign(e,{[i]:s[i]});return this.deepMerge(e,...t)}static isObject(e){return e&&typeof e=="object"&&!Array.isArray(e)}static debounce(e,t){let s;return function(...a){const r=()=>{clearTimeout(s),e(...a)};clearTimeout(s),s=setTimeout(r,t)}}static throttle(e,t){let s;return function(...i){s||(e.apply(this,i),s=!0,setTimeout(()=>s=!1,t))}}static generateId(e=""){const t=Date.now().toString(36),s=Math.random().toString(36).substr(2,9);return e?`${e}_${t}_${s}`:`${t}_${s}`}static escapeHtml(e){const t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(e).replace(/[&<>"'`=\/]/g,s=>t[s])}static checkPasswordStrength(e){if(!e||typeof e!="string")return{score:0,strength:"invalid",feedback:["Password must be a non-empty string"],details:{length:0,hasLowercase:!1,hasUppercase:!1,hasNumbers:!1,hasSpecialChars:!1,hasCommonPatterns:!1,isCommonPassword:!1}};const t=[],s={length:e.length,hasLowercase:/[a-z]/.test(e),hasUppercase:/[A-Z]/.test(e),hasNumbers:/[0-9]/.test(e),hasSpecialChars:/[^a-zA-Z0-9]/.test(e),hasCommonPatterns:!1,isCommonPassword:!1};let i=0;e.length<6?t.push("Password should be at least 6 characters long"):e.length<8?(i+=1,t.push("Consider using at least 8 characters for better security")):e.length<12?i+=3:i+=4,s.hasLowercase?i+=1:t.push("Include lowercase letters"),s.hasUppercase?i+=1:t.push("Include uppercase letters"),s.hasNumbers?i+=1:t.push("Include numbers"),s.hasSpecialChars?i+=2:t.push("Include special characters (!@#$%^&* etc.)");const a=[/123/,/abc/i,/qwerty/i,/asdf/i,/(.)\1{2,}/,/password/i,/admin/i,/user/i,/login/i];for(const o of a)if(o.test(e)){s.hasCommonPatterns=!0,i-=1,t.push("Avoid common patterns and dictionary words");break}["123456","password","123456789","12345678","12345","1234567","1234567890","qwerty","abc123","111111","123123","admin","letmein","welcome","monkey","password123","123qwe","qwerty123","000000","dragon","sunshine","princess","azerty","1234","iloveyou","trustno1","superman","shadow","master","jennifer"].includes(e.toLowerCase())&&(s.isCommonPassword=!0,i=Math.max(0,i-3),t.push("This password is too common and easily guessed"));let n;return i<2?n="very-weak":i<4?n="weak":i<6?n="fair":i<8?n="good":n="strong",i>=7&&t.length===0?t.push("Strong password! Consider using a password manager."):i>=5&&t.length<=1&&t.push("Good password strength. Consider adding more variety."),{score:Math.max(0,i),strength:n,feedback:t,details:s}}static generatePassword(e={}){const s={...{length:12,includeLowercase:!0,includeUppercase:!0,includeNumbers:!0,includeSpecialChars:!0,customChars:"",excludeAmbiguous:!1},...e};if(s.length<4)throw new Error("Password length must be at least 4 characters");let i="abcdefghijklmnopqrstuvwxyz",a="ABCDEFGHIJKLMNOPQRSTUVWXYZ",r="0123456789",n="!@#$%^&*()_+-=[]{}|;:,.<>?";s.excludeAmbiguous&&(i=i.replace(/[il]/g,""),a=a.replace(/[IOL]/g,""),r=r.replace(/[01]/g,""),n=n.replace(/[|]/g,""));let o="";const l=[];if(s.customChars?o=s.customChars:(s.includeLowercase&&(o+=i,l.push(i[Math.floor(Math.random()*i.length)])),s.includeUppercase&&(o+=a,l.push(a[Math.floor(Math.random()*a.length)])),s.includeNumbers&&(o+=r,l.push(r[Math.floor(Math.random()*r.length)])),s.includeSpecialChars&&(o+=n,l.push(n[Math.floor(Math.random()*n.length)]))),!o)throw new Error("No character types selected for password generation");let c="";for(const d of l)c+=d;for(let d=c.length;d<s.length;d++)c+=o[Math.floor(Math.random()*o.length)];return c.split("").sort(()=>Math.random()-.5).join("")}static parseQueryString(e){const t={},s=new URLSearchParams(e);for(const[i,a]of s.entries())t[i]=a;return t}static toQueryString(e){return new URLSearchParams(e).toString()}static wrapData(e,t=null,s=3){return!e||typeof e!="object"||e instanceof Date||e instanceof RegExp||e instanceof Error||s<=0||typeof e.getContextValue=="function"?e:Array.isArray(e)?e.map(i=>i&&typeof i=="object"&&!i.getContextValue?new ne(i,t):i):new ne(e,t)}}class ne{constructor(e,t=null){if(Object.defineProperty(this,"_data",{value:e,writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(this,"_rootContext",{value:t,writable:!1,enumerable:!1,configurable:!1}),e&&typeof e=="object"){for(const s in e)if(e.hasOwnProperty(s)){const i=e[s];this[s]=x.wrapData(i,t)}}}getContextValue(e){let t=e,s="",i=0,a=-1;for(let n=0;n<e.length;n++){const o=e[n];if(o==="(")i++;else if(o===")")i--;else if(o==="|"&&i===0){a=n;break}}a>-1&&(t=e.substring(0,a).trim(),s=e.substring(a+1).trim());let r;return t in this&&t!=="_data"&&t!=="_rootContext"?r=this[t]:r=x.getNestedValue(this._data,t),s&&r!==void 0?L.pipe(r,s,this._rootContext||this._data):r}has(e){return this._data&&this._data.hasOwnProperty(e)}toJSON(){return this._data}}x.DataWrapper=ne,typeof window<"u"&&(window.utils=x);const He=Object.prototype.toString,W=Array.isArray||function(u){return He.call(u)==="[object Array]"},K=function(u){return typeof u=="function"},Fe=function(u){return u!==null&&typeof u=="object"};function Re(){return typeof window>"u"?null:window.MOJO?.dataFormatter?window.MOJO.dataFormatter:window.dataFormatter?window.dataFormatter:null}const De=function(u){const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(u).replace(/[&<>"'`=\/]/g,function(t){return e[t]})};class Ee{constructor(e){this.string=e,this.tail=e,this.pos=0}eos(){return this.tail===""}scan(e){const t=this.tail.match(e);if(!t||t.index!==0)return"";const s=t[0];return this.tail=this.tail.substring(s.length),this.pos+=s.length,s}scanUntil(e){const t=this.tail.search(e);let s;switch(t){case-1:s=this.tail,this.tail="";break;case 0:s="";break;default:s=this.tail.substring(0,t),this.tail=this.tail.substring(t)}return this.pos+=s.length,s}}class te{constructor(e,t){this.view=e,this.cache={".":this.view},this.parent=t,this.view?._cacheId||this.view&&typeof this.view=="object"&&(this.view._cacheId=Math.random().toString(36).substring(2))}push(e){return new te(e,this)}lookup(e){if(this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;if(this.renderCache.has(i))return this.renderCache.get(i)}if(e===".")return this.view;if(e&&e.startsWith(".")){let i=e.substring(1),a=!1,r=null;const n=i.indexOf("|");if(n!==-1&&(r=i.substring(n+1).trim(),i=i.substring(0,n).trim()),i.endsWith("|iter")&&(i=i.substring(0,i.length-5),a=!0),this.view&&typeof this.view=="object"){let o;if(typeof this.view.getContextValue=="function")try{o=this.view.getContextValue(i),o!==void 0&&K(o)&&(o=o.call(this.view))}catch{o=void 0}if(o===void 0&&i in this.view&&(o=this.view[i],K(o)&&(o=o.call(this.view))),r&&o!==void 0)try{const l=Re();l&&typeof l.pipe=="function"&&(o=l.pipe(o,r,this))}catch{}return W(o)?a?o:o.length>0:Fe(o)?a?Object.entries(o).map(([l,c])=>({key:l,value:c})):Object.keys(o).length>0:o}return}const t=this.cache;let s;if(t.hasOwnProperty(e))s=t[e];else{let i=this,a,r,n,o=!1;for(;i;){if(i.view&&typeof i.view.getContextValue=="function")try{a=i.view.getContextValue(e),a!==void 0&&(o=!0)}catch{o=!1}if(!o)if(e.indexOf(".")>0)for(a=i.view,r=e.split("."),n=0;a!=null&&n<r.length;)if(a&&typeof a.getContextValue=="function"&&n<r.length)try{const l=r.slice(n).join(".");a=a.getContextValue(l),n=r.length,a!==void 0&&(o=!0)}catch{n===r.length-1&&(o=oe(a,r[n])||Ae(a,r[n])),a=a[r[n++]]}else n===r.length-1&&(o=oe(a,r[n])||Ae(a,r[n])),a=a[r[n++]];else a=i.view[e],o=oe(i.view,e);if(o){s=a;break}i=i.parent}t[e]=s}if(K(s)&&(s=s.call(this.view)),this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;this.renderCache.set(i,s)}return s}}function oe(u,e){return u!=null&&typeof u=="object"&&e in u}function Ae(u,e){return u!=null&&typeof u!="object"&&u.hasOwnProperty&&u.hasOwnProperty(e)}class Te{constructor(){this.templateCache=new Map}clearCache(){this.templateCache.clear()}parse(e,t){t=t||["{{","}}"];const s=e+":"+t.join(":");let i=this.templateCache.get(s);return i==null&&(i=this.parseTemplate(e,t),this.templateCache.set(s,i)),i}parseTemplate(e,t){if(!e)return[];const s=t[0],i=t[1],a=new Ee(e),r=[];let n,o,l,c,d;const h=new RegExp(le(s)+"\\s*"),m=new RegExp("\\s*"+le(i)),p=new RegExp("\\s*"+le("}"+i));for(;!a.eos();){if(n=a.pos,l=a.scanUntil(h),l)for(let f=0;f<l.length;++f)c=l.charAt(f),c===`
15
- `?r.push(["text",c]):r.push(["text",c]);if(!a.scan(h))break;if(o=a.scan(/[#^\/>{&=!]/),o||(o="name"),a.scan(/\s*/),o==="="?(l=a.scanUntil(/\s*=/),a.scan(/\s*=/),a.scanUntil(m)):o==="{"?(l=a.scanUntil(p),a.scan(p),o="&"):l=a.scanUntil(m),a.scan(m),o==="#"||o==="^")d=[o,l,n,a.pos],r.push(d);else if(o==="/"){let f;for(let g=r.length-1;g>=0;--g)if((r[g][0]==="#"||r[g][0]==="^")&&r[g][1]===l){f=r[g];break}f&&f.length===4&&f.push(a.pos),r.push([o,l,n,a.pos])}else r.push([o,l,n,a.pos])}return this.nestSections(this.squashTokens(r))}squashTokens(e){const t=[];let s,i;for(let a=0;a<e.length;++a)s=e[a],s&&(s[0]==="text"&&i&&i[0]==="text"?(i[1]+=s[1],i[3]=s[3]):(t.push(s),i=s));return t}nestSections(e){const t=[];let s=t;const i=[];for(let a=0;a<e.length;++a){const r=e[a];switch(r[0]){case"#":case"^":const n=[r[0],r[1],r[2],r[3],[],r[4]||null];s.push(n),i.push(n),s=n[4];break;case"/":const o=i.pop();o&&(o[5]=r[2],s=i.length>0?i[i.length-1][4]:t);break;default:s.push(r)}}return t}render(e,t,s,i){const a=this.getConfigTags(i)||["{{","}}"],r=this.parse(e,a),n=new Map;return this.renderTokens(r,new te(t),s,e,i,n)}renderTokens(e,t,s,i,a,r){r&&!t.renderCache&&(t.renderCache=r);let n="";for(let o=0;o<e.length;++o){const l=e[o];let c;switch(l[0]){case"#":if(c=t.lookup(l[1]),!c)continue;const d=l[4];if(!d||!W(d)){console.warn(`MUSTACHE WARNING - Section ${l[1]} has no child tokens:`,l);continue}if(W(c))for(let h=0;h<c.length;++h){const m=t.push(c[h]);t.renderCache&&(m.renderCache=t.renderCache);const p=this.renderTokens(d,m,s,i,a,r);n+=p}else if(typeof c=="object"||typeof c=="string"||typeof c=="number"){const h=t.push(c);t.renderCache&&(h.renderCache=t.renderCache),n+=this.renderTokens(d,h,s,i,a,r)}else if(K(c)){const h=i==null?null:i.slice(l[3],l[5]);c=c.call(t.view,h,m=>this.render(m,t.view,s,a)),c!=null&&(n+=c)}else c&&(n+=this.renderTokens(d,t,s,i,a,r));break;case"^":if(c=t.lookup(l[1]),!c||W(c)&&c.length===0){const h=l[4];h&&W(h)&&(n+=this.renderTokens(h,t,s,i,a,r))}break;case">":if(!s)continue;c=K(s)?s(l[1]):s[l[1]],c!=null&&(n+=this.render(c,t.view,s,a));break;case"&":c=t.lookup(l[1]),c!=null&&(n+=c);break;case"name":c=t.lookup(l[1]),c!=null&&(n+=De(c));break;case"text":n+=l[1];break}}return n}getConfigTags(e){return Fe(e)&&W(e.tags)?e.tags:null}}function le(u){return u.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}const ce=new Te,T={name:"MOJO Mustache",version:"1.0.0",tags:["{{","}}"],Scanner:Ee,Context:te,Writer:Te,escape:De,clearCache(){return ce.clearCache()},parse(u,e){return ce.parse(u,e)},render(u,e,t,s){if(typeof u!="string")throw new TypeError('Invalid template! Template should be a "string"');return e&&typeof e=="object"&&!e.getContextValue&&typeof e.toJSON!="function"&&(e=x.wrapData(e)),ce.render(u,e,t,s)}};class je{constructor(e){this.view=e,this.domListeners=[],this.debounceTimers=new Map}bind(e){if(this.unbind(),!e)return;const t=async n=>{const o=n.target.closest("[data-action]");if(o&&this.shouldHandle(o,n)){const c=o.getAttribute("data-action");if(o.tagName==="A"&&n.preventDefault(),this.hideTooltip(o),await this.dispatch(c,n,o)){n.preventDefault(),n.stopPropagation(),n.handledByChild=!0;return}}const l=n.target.closest("a[href], [data-page]");if(l&&!l.hasAttribute("data-action")&&this.shouldHandle(l,n)){if(n.ctrlKey||n.metaKey||n.shiftKey||n.button===1)return;if(l.tagName==="A"){const c=l.getAttribute("href");if(c&&c!=="#"&&!c.startsWith("#")&&(this.view.isExternalLink(c)||l.hasAttribute("data-external")))return}this.hideTooltip(l),n.preventDefault(),n.stopPropagation(),n.handledByChild=!0,l.hasAttribute("data-page")?await this.view.handlePageNavigation(l):await this.view.handleHrefNavigation(l)}},s=n=>{const o=n.target.closest("[data-change-action]");if(!o||!this.shouldHandle(o,n))return;const l=o.getAttribute("data-change-action");this.dispatchChange(l,n,o).then(c=>{c&&(n.stopPropagation(),n.handledByChild=!0)})},i=n=>{const o=n.target.closest("[data-change-action]");if(!o||!this.shouldHandle(o,n)||!n.target.matches('[data-filter="live-search"]'))return;const c=o.getAttribute("data-change-action"),d=parseInt(o.getAttribute("data-filter-debounce"))||300,h=`${c}-${o.getAttribute("data-container")||"default"}`;this.debounceTimers.has(h)&&clearTimeout(this.debounceTimers.get(h));const m=setTimeout(()=>{this.debounceTimers.delete(h),this.dispatchChange(c,n,o).then(p=>{p&&(n.stopPropagation(),n.handledByChild=!0)})},d);this.debounceTimers.set(h,m)},a=n=>{if(n.target.matches('[data-filter="search"]'))return;const o=n.target.closest("[data-keydown-action]")||n.target.closest("[data-change-action]");if(!o||!this.shouldHandle(o,n))return;let l=["Enter"];if(o.getAttribute("data-change-keys")&&(l=o.getAttribute("data-change-keys").split(",").map(c=>c.trim())),l.includes("*")||l.includes(n.key)){const c=o.getAttribute("data-keydown-action")||o.getAttribute("data-change-action");this.dispatch(c,n,o).then(d=>{d&&(n.preventDefault(),n.stopPropagation(),n.handledByChild=!0)})}},r=n=>{const o=n.target.closest("form[data-action]");if(!o||!this.shouldHandle(o,n))return;n.preventDefault();const l=o.getAttribute("data-action");this.dispatch(l,n,o)};e.addEventListener("click",t),e.addEventListener("change",s),e.addEventListener("input",i),e.addEventListener("keydown",a),e.addEventListener("submit",r),this.domListeners.push({el:e,type:"click",fn:t},{el:e,type:"change",fn:s},{el:e,type:"input",fn:i},{el:e,type:"keydown",fn:a},{el:e,type:"submit",fn:r})}unbind(){for(const{el:e,type:t,fn:s}of this.domListeners)e.removeEventListener(t,s);this.domListeners=[];for(const e of this.debounceTimers.values())clearTimeout(e);this.debounceTimers.clear()}hideDropdown(e){const s=e.closest(".dropdown-menu").closest(".dropdown");if(!s)return;const i=s.querySelector('[data-bs-toggle="dropdown"]');i&&window.bootstrap?.Dropdown&&window.bootstrap.Dropdown.getInstance(i)?.hide()}hideTooltip(e){if(e&&window.bootstrap?.Tooltip){const t=window.bootstrap.Tooltip.getInstance(e);t&&t.dispose()}}hideAllTooltips(){window.bootstrap?.Tooltip&&document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.hide()})}async dispatch(e,t,s){const i=this.view,a=l=>l.includes("-")?l.split("-").map(c=>c[0].toUpperCase()+c.slice(1)).join(""):l[0].toUpperCase()+l.slice(1),r=`handleAction${a(e)}`;if(typeof i[r]=="function")try{return t.preventDefault(),await i[r](t,s),!0}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const n=`onAction${a(e)}`;if(typeof i[n]=="function")try{return await i[n](t,s)?(s.closest(".dropdown-menu")&&this.hideDropdown(s),t.preventDefault(),t.stopPropagation(),!0):!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const o=`onPassThruAction${a(e)}`;if(typeof i[o]=="function")try{return await i[o](t,s),!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}if(typeof i.onActionDefault=="function")try{return await i.onActionDefault(e,t,s)}catch(l){return console.error(`Error in default action handler for ${e}:`,l),i.handleActionError(e,l,t,s),!0}return i.emit?.(`action:${e}`,{action:e,event:t,element:s}),!1}async dispatchChange(e,t,s){const i=this.view,r=`onChange${(n=>n.includes("-")?n.split("-").map(o=>o[0].toUpperCase()+o.slice(1)).join(""):n[0].toUpperCase()+n.slice(1))(e)}`;if(typeof i[r]=="function")try{return await i[r](t,s),!0}catch(n){return console.error(`Error in onChange ${e}:`,n),i.handleActionError?.(e,n,t,s),!0}return await this.dispatch(e,t,s)}shouldHandle(e,t){return!!(this.owns(e)||this.contains(e)&&!t.handledByChild)}owns(e){const t=this.view.element;if(!t||!t.contains(e))return!1;for(const s of Object.values(this.view.children))if(s.element&&s.element.contains(e))return!1;return!0}contains(e){return!!this.view.element&&this.view.element.contains(e)}}const de={on(u,e,t){this._listeners||(this._listeners={}),this._listeners[u]||(this._listeners[u]=[]);const s={callback:e,context:t,fn:t?e.bind(t):e};return this._listeners[u].push(s),this},off(u,e,t){return!this._listeners||!this._listeners[u]?this:(e?(this._listeners[u]=this._listeners[u].filter(s=>s.callback!==e||arguments.length===3&&s.context!==t),this._listeners[u].length===0&&delete this._listeners[u]):delete this._listeners[u],this)},once(u,e,t){const s=(...i)=>{this.off(u,s),(t?e.bind(t):e).apply(t||this,i)};return this.on(u,s),this},emit(u,...e){if(!this._listeners||!this._listeners[u])return this;const t=this._listeners[u].slice();for(const s of t)try{s.fn.apply(s.context||this,e)}catch(i){console&&console.error&&console.error(`Error in ${u} event handler:`,i)}return this}};typeof window<"u"&&(window.Mustache=T);class C{constructor(e={}){this.tagName=e.tagName??"div",this.className=e.className??"mojo-view",this.style=e.style??null,this.id=e.id??C._genId(),this.containerId=e.containerId??null,this.container=e.container??null,typeof this.container=="string"&&(this.containerId=this.container,this.container=null),this.parent=e.parent??null,this.children=e.children??{},this.template=e.template||e.templateUrl||"",this.data=e.data??{},this.isRendering=!1,this.lastRenderTime=0,this.mounted=!1,this.debug=e.debug??!1,this.app=e.app??null,this.cacheTemplate=e.cacheTemplate??!0,this.enableTooltips=e.enableTooltips??!1,this.options={...e},this.element=this._ensureElement(),this.events=new je(this),e.model&&this.setModel(e.model)}async onInit(){}async onInitView(){this.initialized||(this.initialized=!0,await this.onInit())}async onBeforeRender(){}async onAfterRender(){}async onBeforeMount(){}async onAfterMount(){}async onBeforeUnmount(){}async onAfterUnmount(){}async onBeforeDestroy(){}async onAfterDestroy(){}setModel(e={}){let t=e!==this.model;if(!t)return this;this.model&&this.model.off&&this.model.off("change",this._onModelChange,this),this.model=e,this.model&&this.model.on&&this.model.on("change",this._onModelChange,this);for(const s in this.children){const i=this.children[s];i&&typeof i.setModel=="function"&&i.setModel(e)}return t&&this._onModelChange(),this}_onModelChange(){this.isMounted()&&this.render()}setTemplate(e){return this.template=e??"",this}addChild(e,t){try{if(!e||typeof e!="object")return this;t&&((t.containerId||t.container)&&(e.containerId=t.containerId||t.container),t.id&&(e.id=t.id)),e.parent=this,this.getApp()&&(e.app=this.app),this.children[e.id]=e}catch(s){C._warn("addChild error",s)}return e}removeChild(e){try{const t=typeof e=="string"?e:e&&e.id;if(!t)return this;const s=this.children[t];s&&(Promise.resolve(s.destroy()).catch(i=>C._warn("removeChild destroy error",i)),delete this.children[t])}catch(t){C._warn("removeChild error",t)}return this}getChild(e){return this.children[e]}async updateData(e,t=!1){return Object.assign(this.data,e),t&&this.isMounted()&&await this.render(),this}toggleClass(e,t){return t===void 0&&(t=!this.element.classList.contains(e)),this.element.classList.toggle(e,t),this}addClass(e){return this.element.classList.add(e),this}setClass(e){return this.element.className=e,this}removeClass(e){return this.element.classList.remove(e),this}canRender(){if(this.isRendering)return!1;const e=Date.now();if(this.options.renderCooldown>0&&e-this.lastRenderTime<this.options.renderCooldown)return C._warn(`View ${this.id}: Render called too quickly, cooldown active`),!1;if(this.options.noAppend&&this.parent)if(this.parent.contains(this.containerId||this.container)){if(this.containerId&&!document.getElementById(this.containerId))return!1;if(this.container&&!document.contains(this.container))return!1}else return!1;return!0}async render(e=!0,t=null){const s=Date.now();if(!this.canRender())return this;this.isRendering=!0,this.lastRenderTime=s;try{this.initialized||await this.onInitView(),this.unbindEvents(),await this.onBeforeRender(),this.getViewData&&(this.data=await this.getViewData());const i=await this.renderTemplate();this.element.innerHTML=i,e&&!this.isMounted()&&await this.mount(t),await this._renderChildren(),await this.onAfterRender(),this.bindEvents()}catch(i){C._warn(`Render error in ${this.id}`,i)}finally{this.isRendering=!1}return this}async _renderChildren(){for(const e in this.children){const t=this.children[e];t&&(t.parent=this,await Promise.resolve(t.render()).catch(s=>C._warn(`Child render error (${e})`,s)))}}async _unmountChildren(){for(const e in this.children){const t=this.children[e];t&&t.unbindEvents()}}isMounted(){return this.element?.isConnected}getChildElementById(e,t=null){const s=e.startsWith("#")?e.substring(1):e;return t?t.querySelector(`#${s}`):this.element.querySelector(`#${s}`)}getChildElement(e){if(e.startsWith("#"))return this.getChildElementById(e);let t=this.element?.querySelector(`[data-container="${e}"]`);return t||this.getChildElementById(e)}getContainer(){return this.replaceById?this.parent?this.parent.getChildElementById(this.id):null:this.containerId?this.parent?this.parent.getChildElement(this.containerId):this.getChildElementById(this.containerId,document.body):null}async mount(e=null){if(await this.onBeforeMount(),e||(e=this.getContainer()),this.containerId&&!e){console.error(`Container not found for ${this.containerId}`);return}e&&this.replaceById?e.replaceWith(this.element):e?e.replaceChildren(this.element):!this.containerId&&this.parent?this.parent.element.appendChild(this.element):!this.containerId&&!this.parent&&this.options.allowAppendToBody?(console.log("APPENDING TO BODY!!!!"),document.body.appendChild(this.element)):console.error(`Container not found for ${this.containerId}`),await this.onAfterMount(),this.mounted=!0}async unmount(){!this.element||!this.element.parentNode||(await this.onBeforeUnmount(),await this._unmountChildren(),this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.events.unbind(),await this.onAfterUnmount(),this.mounted=!1)}async destroy(){try{this.events.unbind();for(const e in this.children){const t=this.children[e];t&&await Promise.resolve(t.destroy()).catch(s=>C._warn(`Child destroy error (${e})`,s))}this.mounted=!1,this.element&&this.element.parentNode&&(await this.onBeforeDestroy(),this.element.parentNode&&this.element.parentNode.removeChild(this.element),await this.onAfterDestroy())}catch(e){C._warn(`Destroy error in ${this.id}`,e)}}_ensureElement(){try{if(this.element&&this.element.tagName?.toLowerCase()===this.tagName)return this._syncAttrs(),this.element;const e=document.createElement(this.tagName);return this.element=e,this.el=e,this._syncAttrs(),e}catch(e){C._warn("ensureElement error",e);const t=document.createElement("div");return t.id=this.id||C._genId(),t}}_syncAttrs(){try{if(!this.element)return;this.id&&(this.element.id=this.id),this.element.className=this.className||"",this.style==null?this.element.removeAttribute("style"):this.element.style.cssText=String(this.style)}catch(e){C._warn("_syncAttrs error",e)}}bindEvents(){this.events.bind(this.element),this.enableTooltips&&this.initializeTooltips()}unbindEvents(){this.events.unbind(),this.enableTooltips&&this.disposeTooltips()}async renderTemplate(){const e=await this.getTemplate();if(!e)return"";const t=this.getPartials();return T.render(e,this,t)}renderTemplateString(e,t,s){return T.render(e,t,s)}getPartials(){return{}}async getTemplate(){if(this._templateCache&&this.cacheTemplate)return this._templateCache;const e=this.template||this.templateUrl;if(!e)throw new Error("Template not found");let t="";if(typeof e=="string")if(e.includes("<")||e.includes("{"))t=e;else try{let s=e;this.app||(this.app=this.getApp()),this.app&&this.app.basePath&&!s.startsWith("/")&&!s.startsWith("http://")&&!s.startsWith("https://")&&(s=`${this.app.basePath.endsWith("/")?this.app.basePath.slice(0,-1):this.app.basePath}/${s}`);const i=await fetch(s);if(!i.ok)throw new Error(`HTTP ${i.status}: ${i.statusText}`);t=await i.text()}catch(s){C._warn(`Failed to load template from ${e}: ${s}`),this.showError?.(`Failed to load template from ${e}: ${s.message}`)}else typeof e=="function"&&(t=await this.template(this.data,this.state));return this.cacheTemplate&&t&&(this._templateCache=t),t}getContextValue(e){const t=x.getContextData(this,e);return e&&e.startsWith("data.")&&t&&typeof t=="object"?x.wrapData(t,this):e&&e.startsWith("model.")&&e!=="model"&&t&&typeof t=="object"&&typeof t.getContextValue!="function"?x.wrapData(t,null):t}async handlePageNavigation(e){const t=e.getAttribute("data-page"),s=e.getAttribute("data-params");let i={};if(s)try{i=JSON.parse(s)}catch{console.warn("Invalid JSON in data-params:",s)}const a=this.getApp();if(a){a.showPage(t,i);return}const r=this.findRouter();r&&typeof r.navigateToPage=="function"?await r.navigateToPage(t,i):console.error(`No router found for page navigation to '${t}'`)}async handleHrefNavigation(e){const t=e.getAttribute("href");if(this.isExternalLink(t)||e.hasAttribute("data-external"))return;const s=this.findRouter();if(s){if(s.options&&s.options.mode==="param"&&t.startsWith("?")){const a="/"+t;await s.navigate(a);return}if(s.options&&s.options.mode==="hash"&&t.startsWith("#")){await s.navigate(t);return}const i=this.hrefToRoutePath(t);await s.navigate(i)}else console.warn("No router found for navigation, using default behavior"),window.location.href=t}isExternalLink(e){return e?e.startsWith("/")&&this.getApp()?!e.startsWith(this.findRouter().basePath):e.startsWith("#")||e.startsWith("mailto:")||e.startsWith("tel:")||e.startsWith("http://")||e.startsWith("https://")||e.startsWith("//"):!0}hrefToRoutePath(e){if(e.startsWith("/")){const t=this.findRouter();if(t&&t.options&&t.options.base){const s=t.options.base;if(e.startsWith(s))return e.substring(s.length)||"/"}return e}return e.startsWith("./")?e.substring(2):e}findRouter(){return this.getApp(),this.app?.router||null}getApp(){if(this.app)return this.app;const e=[window.__app__,window.MOJO?.app,window.APP,window.app,window.WebApp,window.matchUUID?window[window.matchUUID]():window[window.matchUUID]];return this.app=e.find(t=>t&&typeof t.showPage=="function")||null,this.app}handleActionError(e,t,s,i){this.showError(`Action '${e}' failed: ${t}`,s,i)}escapeHtml(e){if(typeof e!="string")return e;const t=document.createElement("div");return t.textContent=e,t.innerHTML}contains(e){if(typeof e=="string"){if(!this.element)return!1;e=document.getElementById(e)}return e?this.element.contains(e):!1}initializeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.disposeTooltips(),[...this.element.querySelectorAll('[data-bs-toggle="tooltip"]')].map(t=>{const s=t.getAttribute("data-tooltip-theme"),i=t.getAttribute("data-tooltip-size");let a="";s&&(a+=`tooltip-${s} `),i&&(a+=`tooltip-${i}`);const r={},n=a.trim();return n&&(r.customClass=n),new window.bootstrap.Tooltip(t,r)})}disposeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.element.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.dispose()})}async showError(e){console.error(`View ${this.id} error:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showError=="function"){await t.showError(e);return}alert(`Error: ${e}`)}async showSuccess(e){this.debug&&console.log(`View ${this.id} success:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showSuccess=="function"){await t.showSuccess(e);return}alert(`Success: ${e}`)}async showInfo(e){console.info(`View ${this.id} info:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showInfo=="function"){await t.showInfo(e);return}alert(`Info: ${e}`)}async showWarning(e){console.warn(`View ${this.id} warning:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showWarning=="function"){await t.showWarning(e);return}alert(`Warning: ${e}`)}async onActionCopyToClipboard(e,t){try{const i=(t?.closest("[data-clipboard]")||t)?.getAttribute("data-clipboard")||"";if(!i)return!0;if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(i);else{const n=document.createElement("textarea");n.value=i,document.body.appendChild(n),n.select(),document.execCommand("copy"),document.body.removeChild(n)}const a=t.querySelector("i"),r=a&&a.className;return a&&(a.className="bi bi-check",setTimeout(()=>{a.className=r},1e3)),!0}catch(s){return console.warn("Copy to clipboard failed:",s),!0}}static _genId(){return`view_${Math.random().toString(36).substr(2,9)}`}static _warn(e,t){try{t?console.warn(`[View] ${e}:`,t):console.warn(`[View] ${e}`)}catch{}}}Object.assign(C.prototype,de);class Y{constructor(e={},t={}){this.endpoint=t.endpoint||this.constructor.endpoint||"",this.id=e.id||null,this.attributes={...e},this._=this.attributes,this.originalAttributes={...e},this.errors={},this.loading=!1,this.rest=U,this.options={idAttribute:"id",timestamps:!0,...t}}getContextValue(e){return this.get(e)}get(e){return!e.includes(".")&&!e.includes("|")&&this[e]!==void 0?typeof this[e]=="function"?this[e]():this[e]:x.getContextData(this.attributes,e)}set(e,t,s={}){const i=JSON.parse(JSON.stringify(this.attributes));let a=!1;if(e!=null){if(typeof e=="object"){for(const[r,n]of Object.entries(e))a=this._setNestedAttribute(r,n)||a;e.id!==void 0&&(this.id=e.id)}else e==="id"?(this.id=t,a=!0):a=this._setNestedAttribute(e,t);if(a&&!s.silent)if(this.emit("change",this),typeof e=="string")this.emit(`change:${e}`,t,this);else for(const[r,n]of Object.entries(e)){const o=this._getNestedValue(r);JSON.stringify(this._getNestedValue(r,i))!==JSON.stringify(o)&&this.emit(`change:${r}`,o,this)}}}_setNestedAttribute(e,t){if(!e.includes(".")){const l=this.attributes[e];return this.attributes[e]=t,this[e]=t,l!==t}const s=e.split("."),i=s[0];(!this.attributes[i]||typeof this.attributes[i]!="object")&&(this.attributes[i]={}),(!this[i]||typeof this[i]!="object")&&(this[i]={});const a=this._getNestedValue(e);let r=this.attributes[i],n=this[i];for(let l=1;l<s.length-1;l++){const c=s[l];(!r[c]||typeof r[c]!="object")&&(r[c]={}),(!n[c]||typeof n[c]!="object")&&(n[c]={}),r=r[c],n=n[c]}const o=s[s.length-1];return r[o]=t,n[o]=t,JSON.stringify(a)!==JSON.stringify(t)}_getNestedValue(e,t=this.attributes){if(!e.includes("."))return t[e];const s=e.split(".");let i=t;for(const a of s){if(i==null||typeof i!="object")return;i=i[a]}return i}getData(){return this.attributes}getId(){return this.id}async fetch(e={}){let t=e.url;if(!t){const r=e.id||this.getId();if(!r&&this.options.requiresId!==!1)throw new Error("Model: ID is required for fetching");t=this.buildUrl(r)}const s=JSON.stringify({url:t,params:e.params});if(e.debounceMs&&e.debounceMs>0)return this._debouncedFetch(s,e);if(this.currentRequest&&this.currentRequestKey!==s&&(console.info("Model: Cancelling previous request for new parameters"),this.abortController?.abort(),this.currentRequest=null),this.currentRequest&&this.currentRequestKey===s)return console.info("Model: Duplicate request in progress, returning existing promise"),this.currentRequest;const i=Date.now();if(this.lastFetchTime&&i-this.lastFetchTime<100)return console.info("Model: Rate limited, skipping fetch"),this;this.loading=!0,this.errors={},this.lastFetchTime=i,this.currentRequestKey=s,this.abortController=new AbortController,this.currentRequest=this._performFetch(t,e,this.abortController);try{return await this.currentRequest}catch(r){if(r.name==="AbortError")return console.info("Model: Request was cancelled"),this;throw r}finally{this.currentRequest=null,this.currentRequestKey=null,this.abortController=null}}async _debouncedFetch(e,t){return this.debouncedFetchTimeout&&clearTimeout(this.debouncedFetchTimeout),this.cancel(),new Promise((s,i)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const a=await this.fetch({...t,debounceMs:0});s(a)}catch(a){i(a)}},t.debounceMs)})}async _performFetch(e,t,s){try{t.graph&&(!t.params||!t.params.graph)&&(t.params||(t.params={}),t.params.graph=t.graph);const i=await this.rest.GET(e,t.params,{signal:s.signal});return i.success?i.data.status?(this.originalAttributes={...this.attributes},i.data.data&&this.set(i.data.data),this.errors={}):this.errors=i.data:this.errors=i.errors||{},i}catch(i){if(i.name==="AbortError")throw console.info("Model: Fetch was cancelled"),i;return this.errors={fetch:i.message},{success:!1,error:i.message,status:i.status||500}}finally{this.loading=!1}}async save(e,t={}){const s=!this.id,i=s?"POST":"PUT",a=s?this.buildUrl():this.buildUrl(this.id);this.loading=!0,this.errors={};try{const r=await this.rest[i](a,e,t.params);return r.success?r.data.status?(this.originalAttributes={...this.attributes},this.set(r.data.data),this.errors={}):this.errors=r.data:this.errors=r.errors||{},r}catch(r){return{success:!1,error:r.message,status:r.status||500}}finally{this.loading=!1}}async destroy(e={}){if(!this.id)return this.errors={destroy:"Cannot destroy model without ID"},{success:!1,error:"Cannot destroy model without ID",status:400};const t=this.buildUrl(this.id);this.loading=!0,this.errors={};try{const s=await this.rest.DELETE(t,e.params);return s.success?(this.attributes={},this.originalAttributes={},this.id=null,this.errors={}):this.errors=s.errors||{},s}catch(s){return this.errors={destroy:s.message},{success:!1,error:s.message,status:s.status||500}}finally{this.loading=!1}}isDirty(){return JSON.stringify(this.attributes)!==JSON.stringify(this.originalAttributes)}getChangedAttributes(){const e={};for(const[t,s]of Object.entries(this.attributes))this.originalAttributes[t]!==s&&(e[t]=s);return e}reset(){this.attributes={...this.originalAttributes},this._=this.attributes,this.errors={}}buildUrl(e=null){let t=this.endpoint;return e&&(t=t.endsWith("/")?`${t}${e}`:`${t}/${e}`),t}toJSON(){return{id:this.id,...this.attributes}}validate(){if(this.errors={},this.constructor.validations)for(const[e,t]of Object.entries(this.constructor.validations))this.validateField(e,t);return Object.keys(this.errors).length===0}validateField(e,t){const s=this.get(e),i=Array.isArray(t)?t:[t];for(const a of i)if(typeof a=="function"){const r=a(s,this);if(r!==!0){this.errors[e]=r||`${e} is invalid`;break}}else if(typeof a=="object"){if(a.required&&(s==null||s==="")){this.errors[e]=a.message||`${e} is required`;break}if(a.minLength&&s&&s.length<a.minLength){this.errors[e]=a.message||`${e} must be at least ${a.minLength} characters`;break}if(a.maxLength&&s&&s.length>a.maxLength){this.errors[e]=a.message||`${e} must be no more than ${a.maxLength} characters`;break}if(a.pattern&&s&&!a.pattern.test(s)){this.errors[e]=a.message||`${e} format is invalid`;break}}}static async find(e,t={}){const s=new this({},t);return await s.fetch({id:e,...t}),s}static create(e={},t={}){return new this(e,t)}cancel(){return this.currentRequest&&this.abortController?(console.info("Model: Manually cancelling active request"),this.abortController.abort(),!0):this.debouncedFetchTimeout?(clearTimeout(this.debouncedFetchTimeout),this.debouncedFetchTimeout=null,!0):!1}isFetching(){return!!this.currentRequest}async showError(e){await Dialog.alert(e,"Error",{size:"md",class:"text-danger"})}}Object.assign(Y.prototype,de);class J{constructor(e={},t=null){if(Array.isArray(e)?(t=e,e=t||{}):t=t||e.data||[],this.ModelClass=e.ModelClass||Y,this.models=[],this.loading=!1,this.errors={},this.meta={},this.rest=U,t&&this.add(t),this.params={start:0,size:e.size||10,...e.params},this.endpoint=e.endpoint||this.ModelClass.endpoint||"",!this.endpoint){let s=new this.ModelClass;this.endpoint=s.endpoint}this.restEnabled=!!this.endpoint,e.restEnabled!==void 0&&(this.restEnabled=e.restEnabled),this.options={parse:!0,reset:!0,preloaded:!1,...e}}getModelName(){return this.ModelClass.name}async fetch(e={}){const t=JSON.stringify({...this.params,...e});if(this.currentRequest&&this.currentRequestKey!==t&&(console.info("Collection: Cancelling previous request for new parameters"),this.abortController?.abort(),this.currentRequest=null),this.currentRequest&&this.currentRequestKey===t)return console.info("Collection: Duplicate request in progress, returning existing promise"),this.currentRequest;const s=Date.now();if(this.options.rateLimiting&&this.lastFetchTime&&s-this.lastFetchTime<100)return console.info("Collection: Rate limited, skipping fetch"),{success:!0,message:"Rate limited, skipping fetch",data:{data:this.toJSON()}};if(!this.restEnabled)return console.info("Collection: REST disabled, skipping fetch"),{success:!0,message:"REST disabled, skipping fetch",data:{data:this.toJSON()}};if(this.options.preloaded&&this.models.length>0)return console.info("Collection: Using preloaded data, skipping fetch"),{success:!0,message:"Using preloaded data, skipping fetch",data:{data:this.toJSON()}};const a=this.buildUrl();this.loading=!0,this.errors={},this.lastFetchTime=s,this.currentRequestKey=t,this.abortController=new AbortController,this.currentRequest=this._performFetch(a,e,this.abortController);try{return await this.currentRequest}catch(r){return r.name==="AbortError"?(console.info("Collection: Request was cancelled"),{success:!1,error:"Request cancelled",status:0}):{success:!1,error:r.message,status:r.status||500}}finally{this.currentRequest=null,this.currentRequestKey=null,this.abortController=null}}async _performFetch(e,t,s){const i={...this.params,...t};console.log("Fetching collection data from",e,i);try{this.emit("fetch:start");const a=await this.rest.GET(e,i,{signal:s.signal});if(a.success&&a.data.status){const r=this.options.parse?this.parse(a):a.data;(this.options.reset||t.reset!==!1)&&this.reset(),this.add(r,{silent:t.silent}),this.errors={},this.emit("fetch:success")}else a.data&&a.data.error?(this.errors=a.data,this.emit("fetch:error",{message:a.data.error,error:a.data})):(this.errors=a.errors||{},this.emit("fetch:error",{error:a.errors}));return a}catch(a){return a.name==="AbortError"?(console.info("Collection: Fetch was cancelled"),{success:!1,error:"Request cancelled",status:0}):(this.errors={fetch:a.message},this.emit("fetch:error",{message:a.message,error:a}),{success:!1,error:a.message,status:a.status||500})}finally{this.loading=!1,this.emit("fetch:end")}}async updateParams(e,t=!1,s=0){return await this.setParams({...this.params,...e},t,s)}async setParams(e,t=!1,s=0){return this.params=e,t&&this.restEnabled?s>0?(this.debouncedFetchTimeout&&clearTimeout(this.debouncedFetchTimeout),this.cancel(),new Promise((i,a)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const r=await this.fetch();i(r)}catch(r){a(r)}},s)})):this.fetch():Promise.resolve(this)}async fetchOne(e,t={}){if(!e)return console.warn("Collection: fetchOne requires an ID"),null;if(!this.restEnabled)return console.info("Collection: REST disabled, cannot fetch single item"),null;try{const s=new this.ModelClass({id:e},{endpoint:this.endpoint,collection:this}),i=await s.fetch(t);if(i.success){if(t.addToCollection===!0){const a=this.get(s.id);a?t.merge!==!1&&a.set(s.attributes):this.add(s,{silent:t.silent})}return s}else return console.warn("Collection: fetchOne failed -",i.error||"Unknown error"),null}catch(s){return console.error("Collection: fetchOne error -",s.message),null}}async download(e="json",t={}){if(!this.restEnabled)return console.warn("Collection: REST is not enabled, cannot download from remote."),{success:!1,message:"Remote downloads are not enabled for this collection."};const s=this.buildUrl(),i={...this.params};delete i.start,delete i.size,i.download_format=e;const a=`export-${this.getModelName().toLowerCase()}`,r=this._buildDateRangeSuffix(i),n=`${a}${r}.${e}`,l={json:"application/json",csv:"text/csv"}[e]||"*/*";return i.filename=n,this.rest.download(s,i,{...t,filename:n,headers:{Accept:l}})}_buildDateRangeSuffix(e={}){const t=e.dr_start,s=e.dr_end;if(!t&&!s)return"";const i=n=>n?String(n).replace(/[^\dA-Za-z_-]/g,"-"):"",a=[],r=e.dr_field||"daterange";return a.push(i(r)),t&&a.push(`from-${i(e.dr_start)}`),s&&a.push(`to-${i(e.dr_end)}`),`-${a.filter(Boolean).join("-")}`}parse(e){return e.data&&Array.isArray(e.data.data)?(this.meta={size:e.data.size||10,start:e.data.start||0,count:e.data.count||0,status:e.data.status,graph:e.data.graph,...e.meta},e.data.data):Array.isArray(e.data)?e.data:Array.isArray(e)?e:[e]}add(e,t={}){const s=Array.isArray(e)?e:[e],i=[];for(const a of s){let r;a instanceof this.ModelClass?r=a:r=new this.ModelClass(a,{endpoint:this.endpoint,collection:this});const n=this.models.findIndex(o=>o.id===r.id);n!==-1?t.merge!==!1&&this.models[n].set(r.attributes):(this.models.push(r),i.push(r))}return!t.silent&&i.length>0&&(this.emit("add",{models:i,collection:this}),this.emit("update",{collection:this})),i}remove(e,t={}){const s=Array.isArray(e)?e:[e],i=[];for(const a of s){let r=-1;if(typeof a=="string"||typeof a=="number"?r=this.models.findIndex(n=>n.id==a):r=this.models.indexOf(a),r!==-1){const n=this.models.splice(r,1)[0];i.push(n)}}return!t.silent&&i.length>0&&(this.emit("remove",{models:i,collection:this}),this.emit("update",{collection:this})),i}reset(e=null,t={}){const s=[...this.models];return this.models=[],e&&this.add(e,{silent:!0,...t}),t.silent||this.emit("reset",{collection:this,previousModels:s}),this}get(e){return this.models.find(t=>t.id==e)}at(e){return this.models[e]}length(){return this.models.length}isEmpty(){return this.models.length===0}where(e){return typeof e=="function"?this.models.filter(e):typeof e=="object"?this.models.filter(t=>Object.entries(e).every(([s,i])=>t.get(s)===i)):[]}findWhere(e){const t=this.where(e);return t.length>0?t[0]:void 0}forEach(e,t){if(typeof e!="function")throw new TypeError("Callback must be a function");return this.models.forEach((s,i)=>{e.call(t,s,i,this)}),this}sort(e,t={}){if(typeof e=="string"){const s=e;e=(i,a)=>{const r=i.get(s),n=a.get(s);return r<n?-1:r>n?1:0}}return this.models.sort(e),t.silent||this.trigger("sort",{collection:this}),this}toJSON(){return this.models.map(e=>e.toJSON())}cancel(){return this.currentRequest&&this.abortController?(console.info("Collection: Manually cancelling active request"),this.abortController.abort(),!0):!1}isFetching(){return!!this.currentRequest}buildUrl(){return this.endpoint}*[Symbol.iterator](){for(const e of this.models)yield e}static fromArray(e,t=[],s={}){const i=new this(e,s);return i.add(t,{silent:!0}),i}}Object.assign(J.prototype,de);class ze{constructor(e={}){this.options={containerId:"toast-container",position:"top-end",autohide:!0,defaultDelay:3e3,maxToasts:5,...e},this.toasts=new Map,this.toastCounter=0,this.init()}init(){this.createContainer()}createContainer(){let e=document.getElementById(this.options.containerId);e||(e=document.createElement("div"),e.id=this.options.containerId,e.className=`toast-container position-fixed ${this.getPositionClasses()}`,e.style.zIndex="1070",e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true"),document.body.appendChild(e)),this.container=e}getPositionClasses(){const e={"top-start":"top-0 start-0 p-3","top-center":"top-0 start-50 translate-middle-x p-3","top-end":"top-0 end-0 p-3","middle-start":"top-50 start-0 translate-middle-y p-3","middle-center":"top-50 start-50 translate-middle p-3","middle-end":"top-50 end-0 translate-middle-y p-3","bottom-start":"bottom-0 start-0 p-3","bottom-center":"bottom-0 start-50 translate-middle-x p-3","bottom-end":"bottom-0 end-0 p-3"};return e[this.options.position]||e["top-end"]}success(e,t={}){return this.show(e,"success",{icon:"bi-check-circle-fill",...t})}error(e,t={}){return this.show(e,"error",{icon:"bi-exclamation-triangle-fill",autohide:!0,...t})}info(e,t={}){return this.show(e,"info",{icon:"bi-info-circle-fill",...t})}warning(e,t={}){return this.show(e,"warning",{icon:"bi-exclamation-triangle-fill",...t})}plain(e,t={}){return this.show(e,"plain",{...t})}show(e,t="info",s={}){this.enforceMaxToasts();const i=`toast-${++this.toastCounter}`,a={title:this.getDefaultTitle(t),icon:this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,...s},r=this.createToastElement(i,e,t,a);if(this.container.appendChild(r),typeof bootstrap>"u")throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const n=new bootstrap.Toast(r,{autohide:a.autohide,delay:a.delay});return this.toasts.set(i,{element:r,bootstrap:n,type:t,message:e}),r.addEventListener("hidden.bs.toast",()=>{this.cleanup(i)}),n.show(),{id:i,hide:()=>{try{n.hide()}catch(o){console.warn("Error hiding toast:",o)}},dispose:()=>this.cleanup(i),updateProgress:s.updateProgress||null}}showView(e,t="info",s={}){this.enforceMaxToasts();const i=`toast-${++this.toastCounter}`,a={title:s.title||this.getDefaultTitle(t),icon:s.icon||this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,size:"md",...s},r=this.createViewToastElement(i,e,t,a);if(this.container.appendChild(r),typeof bootstrap>"u")throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const n=new bootstrap.Toast(r,{autohide:a.autohide,delay:a.delay});this.toasts.set(i,{element:r,bootstrap:n,type:t,view:e,message:"View toast"}),r.addEventListener("hidden.bs.toast",()=>{this.cleanupView(i)});const o=r.querySelector(".toast-view-body");return o&&e&&e.render(!0,o),n.show(),{id:i,view:e,hide:()=>{try{n.hide()}catch(l){console.warn("Error hiding view toast:",l)}},dispose:()=>this.cleanupView(i),updateProgress:l=>{e&&typeof e.updateProgress=="function"&&e.updateProgress(l)}}}createToastElement(e,t,s,i){const a=document.createElement("div");a.id=e,a.className=`toast toast-service-${s}${i.size?` toast-${i.size}`:""}`,a.setAttribute("role","alert"),a.setAttribute("aria-live","assertive"),a.setAttribute("aria-atomic","true");const r=i.title||i.icon?this.createToastHeader(i,s):"",n=this.createToastBody(t,i.icon&&!i.title);return a.innerHTML=`
15
+ `?r.push(["text",c]):r.push(["text",c]);if(!a.scan(h))break;if(o=a.scan(/[#^\/>{&=!]/),o||(o="name"),a.scan(/\s*/),o==="="?(l=a.scanUntil(/\s*=/),a.scan(/\s*=/),a.scanUntil(m)):o==="{"?(l=a.scanUntil(p),a.scan(p),o="&"):l=a.scanUntil(m),a.scan(m),o==="#"||o==="^")d=[o,l,n,a.pos],r.push(d);else if(o==="/"){let f;for(let g=r.length-1;g>=0;--g)if((r[g][0]==="#"||r[g][0]==="^")&&r[g][1]===l){f=r[g];break}f&&f.length===4&&f.push(a.pos),r.push([o,l,n,a.pos])}else r.push([o,l,n,a.pos])}return this.nestSections(this.squashTokens(r))}squashTokens(e){const t=[];let s,i;for(let a=0;a<e.length;++a)s=e[a],s&&(s[0]==="text"&&i&&i[0]==="text"?(i[1]+=s[1],i[3]=s[3]):(t.push(s),i=s));return t}nestSections(e){const t=[];let s=t;const i=[];for(let a=0;a<e.length;++a){const r=e[a];switch(r[0]){case"#":case"^":const n=[r[0],r[1],r[2],r[3],[],r[4]||null];s.push(n),i.push(n),s=n[4];break;case"/":const o=i.pop();o&&(o[5]=r[2],s=i.length>0?i[i.length-1][4]:t);break;default:s.push(r)}}return t}render(e,t,s,i){const a=this.getConfigTags(i)||["{{","}}"],r=this.parse(e,a),n=new Map;return this.renderTokens(r,new te(t),s,e,i,n)}renderTokens(e,t,s,i,a,r){r&&!t.renderCache&&(t.renderCache=r);let n="";for(let o=0;o<e.length;++o){const l=e[o];let c;switch(l[0]){case"#":if(c=t.lookup(l[1]),!c)continue;const d=l[4];if(!d||!W(d)){console.warn(`MUSTACHE WARNING - Section ${l[1]} has no child tokens:`,l);continue}if(W(c))for(let h=0;h<c.length;++h){const m=t.push(c[h]);t.renderCache&&(m.renderCache=t.renderCache);const p=this.renderTokens(d,m,s,i,a,r);n+=p}else if(typeof c=="object"||typeof c=="string"||typeof c=="number"){const h=t.push(c);t.renderCache&&(h.renderCache=t.renderCache),n+=this.renderTokens(d,h,s,i,a,r)}else if(K(c)){const h=i==null?null:i.slice(l[3],l[5]);c=c.call(t.view,h,m=>this.render(m,t.view,s,a)),c!=null&&(n+=c)}else c&&(n+=this.renderTokens(d,t,s,i,a,r));break;case"^":if(c=t.lookup(l[1]),!c||W(c)&&c.length===0){const h=l[4];h&&W(h)&&(n+=this.renderTokens(h,t,s,i,a,r))}break;case">":if(!s)continue;c=K(s)?s(l[1]):s[l[1]],c!=null&&(n+=this.render(c,t.view,s,a));break;case"&":c=t.lookup(l[1]),c!=null&&(n+=c);break;case"name":c=t.lookup(l[1]),c!=null&&(n+=De(c));break;case"text":n+=l[1];break}}return n}getConfigTags(e){return Fe(e)&&W(e.tags)?e.tags:null}}function le(u){return u.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}const ce=new Te,T={name:"MOJO Mustache",version:"1.0.0",tags:["{{","}}"],Scanner:Ee,Context:te,Writer:Te,escape:De,clearCache(){return ce.clearCache()},parse(u,e){return ce.parse(u,e)},render(u,e,t,s){if(typeof u!="string")throw new TypeError('Invalid template! Template should be a "string"');return e&&typeof e=="object"&&!e.getContextValue&&typeof e.toJSON!="function"&&(e=x.wrapData(e)),ce.render(u,e,t,s)}};class je{constructor(e){this.view=e,this.domListeners=[],this.debounceTimers=new Map}bind(e){if(this.unbind(),!e)return;const t=async n=>{const o=n.target.closest("[data-action]");if(o&&this.shouldHandle(o,n)){const c=o.getAttribute("data-action");if(o.tagName==="A"&&n.preventDefault(),this.hideTooltip(o),await this.dispatch(c,n,o)){n.preventDefault(),n.stopPropagation(),n.handledByChild=!0;return}}const l=n.target.closest("a[href], [data-page]");if(l&&!l.hasAttribute("data-action")&&this.shouldHandle(l,n)){if(n.ctrlKey||n.metaKey||n.shiftKey||n.button===1)return;if(l.tagName==="A"){const c=l.getAttribute("href");if(c&&c!=="#"&&!c.startsWith("#")&&(this.view.isExternalLink(c)||l.hasAttribute("data-external")))return}this.hideTooltip(l),n.preventDefault(),n.stopPropagation(),n.handledByChild=!0,l.hasAttribute("data-page")?await this.view.handlePageNavigation(l):await this.view.handleHrefNavigation(l)}},s=n=>{const o=n.target.closest("[data-change-action]");if(!o||!this.shouldHandle(o,n))return;const l=o.getAttribute("data-change-action");this.dispatchChange(l,n,o).then(c=>{c&&(n.stopPropagation(),n.handledByChild=!0)})},i=n=>{const o=n.target.closest("[data-change-action]");if(!o||!this.shouldHandle(o,n)||!n.target.matches('[data-filter="live-search"]'))return;const c=o.getAttribute("data-change-action"),d=parseInt(o.getAttribute("data-filter-debounce"))||300,h=`${c}-${o.getAttribute("data-container")||"default"}`;this.debounceTimers.has(h)&&clearTimeout(this.debounceTimers.get(h));const m=setTimeout(()=>{this.debounceTimers.delete(h),this.dispatchChange(c,n,o).then(p=>{p&&(n.stopPropagation(),n.handledByChild=!0)})},d);this.debounceTimers.set(h,m)},a=n=>{if(n.target.matches('[data-filter="search"]'))return;const o=n.target.closest("[data-keydown-action]")||n.target.closest("[data-change-action]");if(!o||!this.shouldHandle(o,n))return;let l=["Enter"];if(o.getAttribute("data-change-keys")&&(l=o.getAttribute("data-change-keys").split(",").map(c=>c.trim())),l.includes("*")||l.includes(n.key)){const c=o.getAttribute("data-keydown-action")||o.getAttribute("data-change-action");this.dispatch(c,n,o).then(d=>{d&&(n.preventDefault(),n.stopPropagation(),n.handledByChild=!0)})}},r=n=>{const o=n.target.closest("form[data-action]");if(!o||!this.shouldHandle(o,n))return;n.preventDefault();const l=o.getAttribute("data-action");this.dispatch(l,n,o)};e.addEventListener("click",t),e.addEventListener("change",s),e.addEventListener("input",i),e.addEventListener("keydown",a),e.addEventListener("submit",r),this.domListeners.push({el:e,type:"click",fn:t},{el:e,type:"change",fn:s},{el:e,type:"input",fn:i},{el:e,type:"keydown",fn:a},{el:e,type:"submit",fn:r})}unbind(){for(const{el:e,type:t,fn:s}of this.domListeners)e.removeEventListener(t,s);this.domListeners=[];for(const e of this.debounceTimers.values())clearTimeout(e);this.debounceTimers.clear()}hideDropdown(e){const s=e.closest(".dropdown-menu").closest(".dropdown");if(!s)return;const i=s.querySelector('[data-bs-toggle="dropdown"]');i&&window.bootstrap?.Dropdown&&window.bootstrap.Dropdown.getInstance(i)?.hide()}hideTooltip(e){if(e&&window.bootstrap?.Tooltip){const t=window.bootstrap.Tooltip.getInstance(e);t&&t.dispose()}}hideAllTooltips(){window.bootstrap?.Tooltip&&document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.hide()})}async dispatch(e,t,s){const i=this.view,a=l=>l.includes("-")?l.split("-").map(c=>c[0].toUpperCase()+c.slice(1)).join(""):l[0].toUpperCase()+l.slice(1),r=`handleAction${a(e)}`;if(typeof i[r]=="function")try{return t.preventDefault(),await i[r](t,s),!0}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const n=`onAction${a(e)}`;if(typeof i[n]=="function")try{return await i[n](t,s)?(s.closest(".dropdown-menu")&&this.hideDropdown(s),t.preventDefault(),t.stopPropagation(),!0):!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const o=`onPassThruAction${a(e)}`;if(typeof i[o]=="function")try{return await i[o](t,s),!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}if(typeof i.onActionDefault=="function")try{return await i.onActionDefault(e,t,s)}catch(l){return console.error(`Error in default action handler for ${e}:`,l),i.handleActionError(e,l,t,s),!0}return i.emit?.(`action:${e}`,{action:e,event:t,element:s}),!1}async dispatchChange(e,t,s){const i=this.view,r=`onChange${(n=>n.includes("-")?n.split("-").map(o=>o[0].toUpperCase()+o.slice(1)).join(""):n[0].toUpperCase()+n.slice(1))(e)}`;if(typeof i[r]=="function")try{return await i[r](t,s),!0}catch(n){return console.error(`Error in onChange ${e}:`,n),i.handleActionError?.(e,n,t,s),!0}return await this.dispatch(e,t,s)}shouldHandle(e,t){return!!(this.owns(e)||this.contains(e)&&!t.handledByChild)}owns(e){const t=this.view.element;if(!t||!t.contains(e))return!1;for(const s of Object.values(this.view.children))if(s.element&&s.element.contains(e))return!1;return!0}contains(e){return!!this.view.element&&this.view.element.contains(e)}}const de={on(u,e,t){this._listeners||(this._listeners={}),this._listeners[u]||(this._listeners[u]=[]);const s={callback:e,context:t,fn:t?e.bind(t):e};return this._listeners[u].push(s),this},off(u,e,t){return!this._listeners||!this._listeners[u]?this:(e?(this._listeners[u]=this._listeners[u].filter(s=>s.callback!==e||arguments.length===3&&s.context!==t),this._listeners[u].length===0&&delete this._listeners[u]):delete this._listeners[u],this)},once(u,e,t){const s=(...i)=>{this.off(u,s),(t?e.bind(t):e).apply(t||this,i)};return this.on(u,s),this},emit(u,...e){if(!this._listeners||!this._listeners[u])return this;const t=this._listeners[u].slice();for(const s of t)try{s.fn.apply(s.context||this,e)}catch(i){console&&console.error&&console.error(`Error in ${u} event handler:`,i)}return this}};typeof window<"u"&&(window.Mustache=T);class C{constructor(e={}){this.tagName=e.tagName??"div",this.className=e.className??"mojo-view",this.style=e.style??null,this.id=e.id??C._genId(),this.containerId=e.containerId??null,this.container=e.container??null,typeof this.container=="string"&&(this.containerId=this.container,this.container=null),this.parent=e.parent??null,this.children=e.children??{},this.template=e.template||e.templateUrl||"",this.data=e.data??{},this.isRendering=!1,this.lastRenderTime=0,this.mounted=!1,this.debug=e.debug??!1,this.app=e.app??null,this.cacheTemplate=e.cacheTemplate??!0,this.enableTooltips=e.enableTooltips??!1,this.options={...e},this.element=this._ensureElement(),this.events=new je(this),e.model&&this.setModel(e.model)}async onInit(){}async onInitView(){this.initialized||(this.initialized=!0,await this.onInit())}async onBeforeRender(){}async onAfterRender(){}async onBeforeMount(){}async onAfterMount(){}async onBeforeUnmount(){}async onAfterUnmount(){}async onBeforeDestroy(){}async onAfterDestroy(){}setModel(e={}){let t=e!==this.model;if(!t)return this;this.model&&this.model.off&&this.model.off("change",this._onModelChange,this),this.model=e,this.model&&this.model.on&&this.model.on("change",this._onModelChange,this);for(const s in this.children){const i=this.children[s];i&&typeof i.setModel=="function"&&i.setModel(e)}return t&&this._onModelChange(),this}_onModelChange(){this.isMounted()&&this.render()}setTemplate(e){return this.template=e??"",this}addChild(e,t){try{if(!e||typeof e!="object")return this;t&&((t.containerId||t.container)&&(e.containerId=t.containerId||t.container),t.id&&(e.id=t.id)),e.parent=this,this.getApp()&&(e.app=this.app),this.children[e.id]=e}catch(s){C._warn("addChild error",s)}return e}removeChild(e){try{const t=typeof e=="string"?e:e&&e.id;if(!t)return this;const s=this.children[t];s&&(Promise.resolve(s.destroy()).catch(i=>C._warn("removeChild destroy error",i)),delete this.children[t])}catch(t){C._warn("removeChild error",t)}return this}getChild(e){return this.children[e]}async updateData(e,t=!1){return Object.assign(this.data,e),t&&this.isMounted()&&await this.render(),this}toggleClass(e,t){return t===void 0&&(t=!this.element.classList.contains(e)),this.element.classList.toggle(e,t),this}addClass(e){return this.element.classList.add(e),this}setClass(e){return this.element.className=e,this}removeClass(e){return this.element.classList.remove(e),this}canRender(){if(this.isRendering)return!1;const e=Date.now();if(this.options.renderCooldown>0&&e-this.lastRenderTime<this.options.renderCooldown)return C._warn(`View ${this.id}: Render called too quickly, cooldown active`),!1;if(this.options.noAppend&&this.parent)if(this.parent.contains(this.containerId||this.container)){if(this.containerId&&!document.getElementById(this.containerId))return!1;if(this.container&&!document.contains(this.container))return!1}else return!1;return!0}async render(e=!0,t=null){const s=Date.now();if(!this.canRender())return this;this.isRendering=!0,this.lastRenderTime=s;try{this.initialized||await this.onInitView(),this.unbindEvents(),await this.onBeforeRender(),this.getViewData&&(this.data=await this.getViewData());const i=await this.renderTemplate();this.element.innerHTML=i,e&&!this.isMounted()&&await this.mount(t),await this._renderChildren(),await this.onAfterRender(),this.bindEvents()}catch(i){C._warn(`Render error in ${this.id}`,i)}finally{this.isRendering=!1}return this}async _renderChildren(){for(const e in this.children){const t=this.children[e];t&&(t.parent=this,await Promise.resolve(t.render()).catch(s=>C._warn(`Child render error (${e})`,s)))}}async _unmountChildren(){for(const e in this.children){const t=this.children[e];t&&t.unbindEvents()}}isMounted(){return this.element?.isConnected}getChildElementById(e,t=null){const s=e.startsWith("#")?e.substring(1):e;return t?t.querySelector(`#${s}`):this.element.querySelector(`#${s}`)}getChildElement(e){if(e.startsWith("#"))return this.getChildElementById(e);let t=this.element?.querySelector(`[data-container="${e}"]`);return t||this.getChildElementById(e)}getContainer(){return this.replaceById?this.parent?this.parent.getChildElementById(this.id):null:this.containerId?this.parent?this.parent.getChildElement(this.containerId):this.getChildElementById(this.containerId,document.body):null}async mount(e=null){if(await this.onBeforeMount(),e||(e=this.getContainer()),this.containerId&&!e){console.error(`Container not found for ${this.containerId}`);return}e&&this.replaceById?e.replaceWith(this.element):e?e.replaceChildren(this.element):!this.containerId&&this.parent?this.parent.element.appendChild(this.element):!this.containerId&&!this.parent&&this.options.allowAppendToBody?(console.log("APPENDING TO BODY!!!!"),document.body.appendChild(this.element)):console.error(`Container not found for ${this.containerId}`),await this.onAfterMount(),this.mounted=!0}async unmount(){!this.element||!this.element.parentNode||(await this.onBeforeUnmount(),await this._unmountChildren(),this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.events.unbind(),await this.onAfterUnmount(),this.mounted=!1)}async destroy(){try{this.events.unbind();for(const e in this.children){const t=this.children[e];t&&await Promise.resolve(t.destroy()).catch(s=>C._warn(`Child destroy error (${e})`,s))}this.mounted=!1,this.element&&this.element.parentNode&&(await this.onBeforeDestroy(),this.element.parentNode&&this.element.parentNode.removeChild(this.element),await this.onAfterDestroy())}catch(e){C._warn(`Destroy error in ${this.id}`,e)}}_ensureElement(){try{if(this.element&&this.element.tagName?.toLowerCase()===this.tagName)return this._syncAttrs(),this.element;const e=document.createElement(this.tagName);return this.element=e,this.el=e,this._syncAttrs(),e}catch(e){C._warn("ensureElement error",e);const t=document.createElement("div");return t.id=this.id||C._genId(),t}}_syncAttrs(){try{if(!this.element)return;this.id&&(this.element.id=this.id),this.element.className=this.className||"",this.style==null?this.element.removeAttribute("style"):this.element.style.cssText=String(this.style)}catch(e){C._warn("_syncAttrs error",e)}}bindEvents(){this.events.bind(this.element),this.enableTooltips&&this.initializeTooltips()}unbindEvents(){this.events.unbind(),this.enableTooltips&&this.disposeTooltips()}async renderTemplate(){const e=await this.getTemplate();if(!e)return"";const t=this.getPartials();return T.render(e,this,t)}renderTemplateString(e,t,s){return T.render(e,t,s)}getPartials(){return{}}async getTemplate(){if(this._templateCache&&this.cacheTemplate)return this._templateCache;const e=this.template||this.templateUrl;if(!e)throw new Error("Template not found");let t="";if(typeof e=="string")if(e.includes("<")||e.includes("{"))t=e;else try{let s=e;this.app||(this.app=this.getApp()),this.app&&this.app.basePath&&!s.startsWith("/")&&!s.startsWith("http://")&&!s.startsWith("https://")&&(s=`${this.app.basePath.endsWith("/")?this.app.basePath.slice(0,-1):this.app.basePath}/${s}`);const i=await fetch(s);if(!i.ok)throw new Error(`HTTP ${i.status}: ${i.statusText}`);t=await i.text()}catch(s){C._warn(`Failed to load template from ${e}: ${s}`),this.showError?.(`Failed to load template from ${e}: ${s.message}`)}else typeof e=="function"&&(t=await this.template(this.data,this.state));return this.cacheTemplate&&t&&(this._templateCache=t),t}getContextValue(e){const t=x.getContextData(this,e);return e&&e.startsWith("data.")&&t&&typeof t=="object"?x.wrapData(t,this):e&&e.startsWith("model.")&&e!=="model"&&t&&typeof t=="object"&&typeof t.getContextValue!="function"?x.wrapData(t,null):t}async handlePageNavigation(e){const t=e.getAttribute("data-page"),s=e.getAttribute("data-params");let i={};if(s)try{i=JSON.parse(s)}catch{console.warn("Invalid JSON in data-params:",s)}const a=this.getApp();if(a){a.showPage(t,i);return}const r=this.findRouter();r&&typeof r.navigateToPage=="function"?await r.navigateToPage(t,i):console.error(`No router found for page navigation to '${t}'`)}async handleHrefNavigation(e){const t=e.getAttribute("href");if(this.isExternalLink(t)||e.hasAttribute("data-external"))return;const s=this.findRouter();if(s){if(s.options&&s.options.mode==="param"&&t.startsWith("?")){const a="/"+t;await s.navigate(a);return}if(s.options&&s.options.mode==="hash"&&t.startsWith("#")){await s.navigate(t);return}const i=this.hrefToRoutePath(t);await s.navigate(i)}else console.warn("No router found for navigation, using default behavior"),window.location.href=t}isExternalLink(e){return e?e.startsWith("/")&&this.getApp()?!e.startsWith(this.findRouter().basePath):e.startsWith("#")||e.startsWith("mailto:")||e.startsWith("tel:")||e.startsWith("http://")||e.startsWith("https://")||e.startsWith("//"):!0}hrefToRoutePath(e){if(e.startsWith("/")){const t=this.findRouter();if(t&&t.options&&t.options.base){const s=t.options.base;if(e.startsWith(s))return e.substring(s.length)||"/"}return e}return e.startsWith("./")?e.substring(2):e}findRouter(){return this.getApp(),this.app?.router||null}getApp(){if(this.app)return this.app;const e=[window.__app__,window.MOJO?.app,window.APP,window.app,window.WebApp,window.matchUUID?window[window.matchUUID]():window[window.matchUUID]];return this.app=e.find(t=>t&&typeof t.showPage=="function")||null,this.app}handleActionError(e,t,s,i){this.showError(`Action '${e}' failed: ${t}`,s,i)}escapeHtml(e){if(typeof e!="string")return e;const t=document.createElement("div");return t.textContent=e,t.innerHTML}contains(e){if(typeof e=="string"){if(!this.element)return!1;e=document.getElementById(e)}return e?this.element.contains(e):!1}initializeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.disposeTooltips(),[...this.element.querySelectorAll('[data-bs-toggle="tooltip"]')].map(t=>{const s=t.getAttribute("data-tooltip-theme"),i=t.getAttribute("data-tooltip-size");let a="";s&&(a+=`tooltip-${s} `),i&&(a+=`tooltip-${i}`);const r={},n=a.trim();return n&&(r.customClass=n),new window.bootstrap.Tooltip(t,r)})}disposeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.element.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.dispose()})}async showError(e){console.error(`View ${this.id} error:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showError=="function"){await t.showError(e);return}alert(`Error: ${e}`)}async showSuccess(e){this.debug&&console.log(`View ${this.id} success:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showSuccess=="function"){await t.showSuccess(e);return}alert(`Success: ${e}`)}async showInfo(e){console.info(`View ${this.id} info:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showInfo=="function"){await t.showInfo(e);return}alert(`Info: ${e}`)}async showWarning(e){console.warn(`View ${this.id} warning:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showWarning=="function"){await t.showWarning(e);return}alert(`Warning: ${e}`)}async onActionCopyToClipboard(e,t){try{const i=(t?.closest("[data-clipboard]")||t)?.getAttribute("data-clipboard")||"";if(!i)return!0;if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(i);else{const n=document.createElement("textarea");n.value=i,document.body.appendChild(n),n.select(),document.execCommand("copy"),document.body.removeChild(n)}const a=t.querySelector("i"),r=a&&a.className;return a&&(a.className="bi bi-check",setTimeout(()=>{a.className=r},1e3)),!0}catch(s){return console.warn("Copy to clipboard failed:",s),!0}}static _genId(){return`view_${Math.random().toString(36).substr(2,9)}`}static _warn(e,t){try{t?console.warn(`[View] ${e}:`,t):console.warn(`[View] ${e}`)}catch{}}}Object.assign(C.prototype,de);class Y{constructor(e={},t={}){this.endpoint=t.endpoint||this.constructor.endpoint||"",this.id=e.id||null,this.attributes={...e},this._=this.attributes,this.originalAttributes={...e},this.errors={},this.loading=!1,this.rest=U,this.options={idAttribute:"id",timestamps:!0,...t}}getContextValue(e){return this.get(e)}get(e){return!e.includes(".")&&!e.includes("|")&&this[e]!==void 0?typeof this[e]=="function"?this[e]():this[e]:x.getContextData(this.attributes,e)}set(e,t,s={}){const i=JSON.parse(JSON.stringify(this.attributes));let a=!1;if(e!=null){if(typeof e=="object"){for(const[r,n]of Object.entries(e))a=this._setNestedAttribute(r,n)||a;e.id!==void 0&&(this.id=e.id)}else e==="id"?(this.id=t,a=!0):a=this._setNestedAttribute(e,t);if(a&&!s.silent)if(this.emit("change",this),typeof e=="string")this.emit(`change:${e}`,t,this);else for(const[r,n]of Object.entries(e)){const o=this._getNestedValue(r);JSON.stringify(this._getNestedValue(r,i))!==JSON.stringify(o)&&this.emit(`change:${r}`,o,this)}}}_setNestedAttribute(e,t){if(!e.includes(".")){const l=this.attributes[e];return this.attributes[e]=t,this[e]=t,l!==t}const s=e.split("."),i=s[0];(!this.attributes[i]||typeof this.attributes[i]!="object")&&(this.attributes[i]={}),(!this[i]||typeof this[i]!="object")&&(this[i]={});const a=this._getNestedValue(e);let r=this.attributes[i],n=this[i];for(let l=1;l<s.length-1;l++){const c=s[l];(!r[c]||typeof r[c]!="object")&&(r[c]={}),(!n[c]||typeof n[c]!="object")&&(n[c]={}),r=r[c],n=n[c]}const o=s[s.length-1];return r[o]=t,n[o]=t,JSON.stringify(a)!==JSON.stringify(t)}_getNestedValue(e,t=this.attributes){if(!e.includes("."))return t[e];const s=e.split(".");let i=t;for(const a of s){if(i==null||typeof i!="object")return;i=i[a]}return i}getData(){return this.attributes}getId(){return this.id}async fetch(e={}){let t=e.url;if(!t){const r=e.id||this.getId();if(!r&&this.options.requiresId!==!1)throw new Error("Model: ID is required for fetching");t=this.buildUrl(r)}const s=JSON.stringify({url:t,params:e.params});if(e.debounceMs&&e.debounceMs>0)return this._debouncedFetch(s,e);if(this.currentRequest&&this.currentRequestKey!==s&&(console.info("Model: Cancelling previous request for new parameters"),this.abortController?.abort(),this.currentRequest=null),this.currentRequest&&this.currentRequestKey===s)return console.info("Model: Duplicate request in progress, returning existing promise"),this.currentRequest;const i=Date.now();if(this.lastFetchTime&&i-this.lastFetchTime<100)return console.info("Model: Rate limited, skipping fetch"),this;this.loading=!0,this.errors={},this.lastFetchTime=i,this.currentRequestKey=s,this.abortController=new AbortController,this.currentRequest=this._performFetch(t,e,this.abortController);try{return await this.currentRequest}catch(r){if(r.name==="AbortError")return console.info("Model: Request was cancelled"),this;throw r}finally{this.currentRequest=null,this.currentRequestKey=null,this.abortController=null}}async _debouncedFetch(e,t){return this.debouncedFetchTimeout&&clearTimeout(this.debouncedFetchTimeout),this.cancel(),new Promise((s,i)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const a=await this.fetch({...t,debounceMs:0});s(a)}catch(a){i(a)}},t.debounceMs)})}async _performFetch(e,t,s){try{t.graph&&(!t.params||!t.params.graph)&&(t.params||(t.params={}),t.params.graph=t.graph);const i=await this.rest.GET(e,t.params,{signal:s.signal});return i.success?i.data.status?(this.originalAttributes={...this.attributes},i.data.data&&this.set(i.data.data),this.errors={}):this.errors=i.data:this.errors=i.errors||{},i}catch(i){if(i.name==="AbortError")throw console.info("Model: Fetch was cancelled"),i;return this.errors={fetch:i.message},{success:!1,error:i.message,status:i.status||500}}finally{this.loading=!1}}async save(e,t={}){const s=!this.id,i=s?"POST":"PUT",a=s?this.buildUrl():this.buildUrl(this.id);this.loading=!0,this.errors={};try{const r=await this.rest[i](a,e,t.params);return r.success?r.data.status?(this.originalAttributes={...this.attributes},this.set(r.data.data),this.errors={}):this.errors=r.data:this.errors=r.errors||{},r}catch(r){return{success:!1,error:r.message,status:r.status||500}}finally{this.loading=!1}}async destroy(e={}){if(!this.id)return this.errors={destroy:"Cannot destroy model without ID"},{success:!1,error:"Cannot destroy model without ID",status:400};const t=this.buildUrl(this.id);this.loading=!0,this.errors={};try{const s=await this.rest.DELETE(t,e.params);return s.success?(this.attributes={},this.originalAttributes={},this.id=null,this.errors={}):this.errors=s.errors||{},s}catch(s){return this.errors={destroy:s.message},{success:!1,error:s.message,status:s.status||500}}finally{this.loading=!1}}isDirty(){return JSON.stringify(this.attributes)!==JSON.stringify(this.originalAttributes)}getChangedAttributes(){const e={};for(const[t,s]of Object.entries(this.attributes))this.originalAttributes[t]!==s&&(e[t]=s);return e}reset(){for(const e of Object.keys(this.attributes))e in this.originalAttributes||delete this[e];for(const[e,t]of Object.entries(this.originalAttributes))this[e]=t;this.attributes={...this.originalAttributes},this._=this.attributes,this.errors={}}buildUrl(e=null){let t=this.endpoint;return e&&(t=t.endsWith("/")?`${t}${e}`:`${t}/${e}`),t}toJSON(){return{id:this.id,...this.attributes}}validate(){if(this.errors={},this.constructor.validations)for(const[e,t]of Object.entries(this.constructor.validations))this.validateField(e,t);return Object.keys(this.errors).length===0}validateField(e,t){const s=this.get(e),i=Array.isArray(t)?t:[t];for(const a of i)if(typeof a=="function"){const r=a(s,this);if(r!==!0){this.errors[e]=r||`${e} is invalid`;break}}else if(typeof a=="object"){if(a.required&&(s==null||s==="")){this.errors[e]=a.message||`${e} is required`;break}if(a.minLength&&s&&s.length<a.minLength){this.errors[e]=a.message||`${e} must be at least ${a.minLength} characters`;break}if(a.maxLength&&s&&s.length>a.maxLength){this.errors[e]=a.message||`${e} must be no more than ${a.maxLength} characters`;break}if(a.pattern&&s&&!a.pattern.test(s)){this.errors[e]=a.message||`${e} format is invalid`;break}}}static async find(e,t={}){const s=new this({},t);return await s.fetch({id:e,...t}),s}static create(e={},t={}){return new this(e,t)}cancel(){return this.currentRequest&&this.abortController?(console.info("Model: Manually cancelling active request"),this.abortController.abort(),!0):this.debouncedFetchTimeout?(clearTimeout(this.debouncedFetchTimeout),this.debouncedFetchTimeout=null,!0):!1}isFetching(){return!!this.currentRequest}async showError(e){await Dialog.alert(e,"Error",{size:"md",class:"text-danger"})}}Object.assign(Y.prototype,de);class J{constructor(e={},t=null){if(Array.isArray(e)?(t=e,e=t||{}):t=t||e.data||[],this.ModelClass=e.ModelClass||Y,this.models=[],this.loading=!1,this.errors={},this.meta={},this.rest=U,t&&this.add(t),this.params={start:0,size:e.size||10,...e.params},this.endpoint=e.endpoint||this.ModelClass.endpoint||"",!this.endpoint){let s=new this.ModelClass;this.endpoint=s.endpoint}this.restEnabled=!!this.endpoint,e.restEnabled!==void 0&&(this.restEnabled=e.restEnabled),this.options={parse:!0,reset:!0,preloaded:!1,...e}}getModelName(){return this.ModelClass.name}async fetch(e={}){const t=JSON.stringify({...this.params,...e});if(this.currentRequest&&this.currentRequestKey!==t&&(console.info("Collection: Cancelling previous request for new parameters"),this.abortController?.abort(),this.currentRequest=null),this.currentRequest&&this.currentRequestKey===t)return console.info("Collection: Duplicate request in progress, returning existing promise"),this.currentRequest;const s=Date.now();if(this.options.rateLimiting&&this.lastFetchTime&&s-this.lastFetchTime<100)return console.info("Collection: Rate limited, skipping fetch"),{success:!0,message:"Rate limited, skipping fetch",data:{data:this.toJSON()}};if(!this.restEnabled)return console.info("Collection: REST disabled, skipping fetch"),{success:!0,message:"REST disabled, skipping fetch",data:{data:this.toJSON()}};if(this.options.preloaded&&this.models.length>0)return console.info("Collection: Using preloaded data, skipping fetch"),{success:!0,message:"Using preloaded data, skipping fetch",data:{data:this.toJSON()}};const a=this.buildUrl();this.loading=!0,this.errors={},this.lastFetchTime=s,this.currentRequestKey=t,this.abortController=new AbortController,this.currentRequest=this._performFetch(a,e,this.abortController);try{return await this.currentRequest}catch(r){return r.name==="AbortError"?(console.info("Collection: Request was cancelled"),{success:!1,error:"Request cancelled",status:0}):{success:!1,error:r.message,status:r.status||500}}finally{this.currentRequest=null,this.currentRequestKey=null,this.abortController=null}}async _performFetch(e,t,s){const i={...this.params,...t};console.log("Fetching collection data from",e,i);try{this.emit("fetch:start");const a=await this.rest.GET(e,i,{signal:s.signal});if(a.success&&a.data.status){const r=this.options.parse?this.parse(a):a.data;(this.options.reset||t.reset!==!1)&&this.reset(),this.add(r,{silent:t.silent}),this.errors={},this.emit("fetch:success")}else a.data&&a.data.error?(this.errors=a.data,this.emit("fetch:error",{message:a.data.error,error:a.data})):(this.errors=a.errors||{},this.emit("fetch:error",{error:a.errors}));return a}catch(a){return a.name==="AbortError"?(console.info("Collection: Fetch was cancelled"),{success:!1,error:"Request cancelled",status:0}):(this.errors={fetch:a.message},this.emit("fetch:error",{message:a.message,error:a}),{success:!1,error:a.message,status:a.status||500})}finally{this.loading=!1,this.emit("fetch:end")}}async updateParams(e,t=!1,s=0){return await this.setParams({...this.params,...e},t,s)}async setParams(e,t=!1,s=0){return this.params=e,t&&this.restEnabled?s>0?(this.debouncedFetchTimeout&&clearTimeout(this.debouncedFetchTimeout),this.cancel(),new Promise((i,a)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const r=await this.fetch();i(r)}catch(r){a(r)}},s)})):this.fetch():Promise.resolve(this)}async fetchOne(e,t={}){if(!e)return console.warn("Collection: fetchOne requires an ID"),null;if(!this.restEnabled)return console.info("Collection: REST disabled, cannot fetch single item"),null;try{const s=new this.ModelClass({id:e},{endpoint:this.endpoint,collection:this}),i=await s.fetch(t);if(i.success){if(t.addToCollection===!0){const a=this.get(s.id);a?t.merge!==!1&&a.set(s.attributes):this.add(s,{silent:t.silent})}return s}else return console.warn("Collection: fetchOne failed -",i.error||"Unknown error"),null}catch(s){return console.error("Collection: fetchOne error -",s.message),null}}async download(e="json",t={}){if(!this.restEnabled)return console.warn("Collection: REST is not enabled, cannot download from remote."),{success:!1,message:"Remote downloads are not enabled for this collection."};const s=this.buildUrl(),i={...this.params};delete i.start,delete i.size,i.download_format=e;const a=`export-${this.getModelName().toLowerCase()}`,r=this._buildDateRangeSuffix(i),n=`${a}${r}.${e}`,l={json:"application/json",csv:"text/csv"}[e]||"*/*";return i.filename=n,this.rest.download(s,i,{...t,filename:n,headers:{Accept:l}})}_buildDateRangeSuffix(e={}){const t=e.dr_start,s=e.dr_end;if(!t&&!s)return"";const i=n=>n?String(n).replace(/[^\dA-Za-z_-]/g,"-"):"",a=[],r=e.dr_field||"daterange";return a.push(i(r)),t&&a.push(`from-${i(e.dr_start)}`),s&&a.push(`to-${i(e.dr_end)}`),`-${a.filter(Boolean).join("-")}`}parse(e){return e.data&&Array.isArray(e.data.data)?(this.meta={size:e.data.size||10,start:e.data.start||0,count:e.data.count||0,status:e.data.status,graph:e.data.graph,...e.meta},e.data.data):Array.isArray(e.data)?e.data:Array.isArray(e)?e:[e]}add(e,t={}){const s=Array.isArray(e)?e:[e],i=[];for(const a of s){let r;a instanceof this.ModelClass?r=a:r=new this.ModelClass(a,{endpoint:this.endpoint,collection:this});const n=this.models.findIndex(o=>o.id===r.id);n!==-1?t.merge!==!1&&this.models[n].set(r.attributes):(this.models.push(r),i.push(r))}return!t.silent&&i.length>0&&(this.emit("add",{models:i,collection:this}),this.emit("update",{collection:this})),i}remove(e,t={}){const s=Array.isArray(e)?e:[e],i=[];for(const a of s){let r=-1;if(typeof a=="string"||typeof a=="number"?r=this.models.findIndex(n=>n.id==a):r=this.models.indexOf(a),r!==-1){const n=this.models.splice(r,1)[0];i.push(n)}}return!t.silent&&i.length>0&&(this.emit("remove",{models:i,collection:this}),this.emit("update",{collection:this})),i}reset(e=null,t={}){const s=[...this.models];return this.models=[],e&&this.add(e,{silent:!0,...t}),t.silent||this.emit("reset",{collection:this,previousModels:s}),this}get(e){return this.models.find(t=>t.id==e)}at(e){return this.models[e]}length(){return this.models.length}isEmpty(){return this.models.length===0}where(e){return typeof e=="function"?this.models.filter(e):typeof e=="object"?this.models.filter(t=>Object.entries(e).every(([s,i])=>t.get(s)===i)):[]}findWhere(e){const t=this.where(e);return t.length>0?t[0]:void 0}forEach(e,t){if(typeof e!="function")throw new TypeError("Callback must be a function");return this.models.forEach((s,i)=>{e.call(t,s,i,this)}),this}sort(e,t={}){if(typeof e=="string"){const s=e;e=(i,a)=>{const r=i.get(s),n=a.get(s);return r<n?-1:r>n?1:0}}return this.models.sort(e),t.silent||this.emit("sort",{collection:this}),this}toJSON(){return this.models.map(e=>e.toJSON())}cancel(){return this.currentRequest&&this.abortController?(console.info("Collection: Manually cancelling active request"),this.abortController.abort(),!0):!1}isFetching(){return!!this.currentRequest}buildUrl(){return this.endpoint}*[Symbol.iterator](){for(const e of this.models)yield e}static fromArray(e,t=[],s={}){const i=new this({ModelClass:e,...s});return i.add(t,{silent:!0}),i}}Object.assign(J.prototype,de);class ze{constructor(e={}){this.options={containerId:"toast-container",position:"top-end",autohide:!0,defaultDelay:3e3,maxToasts:5,...e},this.toasts=new Map,this.toastCounter=0,this.init()}init(){this.createContainer()}createContainer(){let e=document.getElementById(this.options.containerId);e||(e=document.createElement("div"),e.id=this.options.containerId,e.className=`toast-container position-fixed ${this.getPositionClasses()}`,e.style.zIndex="1070",e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true"),document.body.appendChild(e)),this.container=e}getPositionClasses(){const e={"top-start":"top-0 start-0 p-3","top-center":"top-0 start-50 translate-middle-x p-3","top-end":"top-0 end-0 p-3","middle-start":"top-50 start-0 translate-middle-y p-3","middle-center":"top-50 start-50 translate-middle p-3","middle-end":"top-50 end-0 translate-middle-y p-3","bottom-start":"bottom-0 start-0 p-3","bottom-center":"bottom-0 start-50 translate-middle-x p-3","bottom-end":"bottom-0 end-0 p-3"};return e[this.options.position]||e["top-end"]}success(e,t={}){return this.show(e,"success",{icon:"bi-check-circle-fill",...t})}error(e,t={}){return this.show(e,"error",{icon:"bi-exclamation-triangle-fill",autohide:!0,...t})}info(e,t={}){return this.show(e,"info",{icon:"bi-info-circle-fill",...t})}warning(e,t={}){return this.show(e,"warning",{icon:"bi-exclamation-triangle-fill",...t})}plain(e,t={}){return this.show(e,"plain",{...t})}show(e,t="info",s={}){this.enforceMaxToasts();const i=`toast-${++this.toastCounter}`,a={title:this.getDefaultTitle(t),icon:this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,...s},r=this.createToastElement(i,e,t,a);if(this.container.appendChild(r),typeof bootstrap>"u")throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const n=new bootstrap.Toast(r,{autohide:a.autohide,delay:a.delay});return this.toasts.set(i,{element:r,bootstrap:n,type:t,message:e}),r.addEventListener("hidden.bs.toast",()=>{this.cleanup(i)}),n.show(),{id:i,hide:()=>{try{n.hide()}catch(o){console.warn("Error hiding toast:",o)}},dispose:()=>this.cleanup(i),updateProgress:s.updateProgress||null}}showView(e,t="info",s={}){this.enforceMaxToasts();const i=`toast-${++this.toastCounter}`,a={title:s.title||this.getDefaultTitle(t),icon:s.icon||this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,size:"md",...s},r=this.createViewToastElement(i,e,t,a);if(this.container.appendChild(r),typeof bootstrap>"u")throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const n=new bootstrap.Toast(r,{autohide:a.autohide,delay:a.delay});this.toasts.set(i,{element:r,bootstrap:n,type:t,view:e,message:"View toast"}),r.addEventListener("hidden.bs.toast",()=>{this.cleanupView(i)});const o=r.querySelector(".toast-view-body");return o&&e&&e.render(!0,o),n.show(),{id:i,view:e,hide:()=>{try{n.hide()}catch(l){console.warn("Error hiding view toast:",l)}},dispose:()=>this.cleanupView(i),updateProgress:l=>{e&&typeof e.updateProgress=="function"&&e.updateProgress(l)}}}createToastElement(e,t,s,i){const a=document.createElement("div");a.id=e,a.className=`toast toast-service-${s}${i.size?` toast-${i.size}`:""}`,a.setAttribute("role","alert"),a.setAttribute("aria-live","assertive"),a.setAttribute("aria-atomic","true");const r=i.title||i.icon?this.createToastHeader(i,s):"",n=this.createToastBody(t,i.icon&&!i.title);return a.innerHTML=`
16
16
  ${r}
17
17
  ${n}
18
18
  `,a}createViewToastElement(e,t,s,i){const a=document.createElement("div");a.id=e,a.className=`toast toast-service-${s}${i.size?` toast-${i.size}`:""}`,a.setAttribute("role","alert"),a.setAttribute("aria-live","assertive"),a.setAttribute("aria-atomic","true");const r=i.title||i.icon?this.createToastHeader(i,s):"",n=this.createViewToastBody();return a.innerHTML=`