web-mojo 2.5.22 → 2.5.23

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 (100) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/admin-models.cjs.js +1 -1
  3. package/dist/admin-models.es.js +1 -1
  4. package/dist/admin.cjs.js +1 -1
  5. package/dist/admin.es.js +1 -1
  6. package/dist/auth.cjs.js +1 -1
  7. package/dist/auth.es.js +1 -1
  8. package/dist/charts.cjs.js +1 -1
  9. package/dist/charts.es.js +1 -1
  10. package/dist/chunks/ChatView-CrTMIyOV.js +2 -0
  11. package/dist/chunks/ChatView-CrTMIyOV.js.map +1 -0
  12. package/dist/chunks/ChatView-DWKXtKJd.js +2 -0
  13. package/dist/chunks/ChatView-DWKXtKJd.js.map +1 -0
  14. package/dist/chunks/{ContextMenu-DErGabOQ.js → ContextMenu-D38E2eQ_.js} +2 -2
  15. package/dist/chunks/{ContextMenu-DErGabOQ.js.map → ContextMenu-D38E2eQ_.js.map} +1 -1
  16. package/dist/chunks/{ContextMenu-CuMPRavw.js → ContextMenu-DVn4aUxG.js} +2 -2
  17. package/dist/chunks/{ContextMenu-CuMPRavw.js.map → ContextMenu-DVn4aUxG.js.map} +1 -1
  18. package/dist/chunks/{DataView-ByYwczrk.js → DataView-BUCPV7uM.js} +2 -2
  19. package/dist/chunks/{DataView-ByYwczrk.js.map → DataView-BUCPV7uM.js.map} +1 -1
  20. package/dist/chunks/{DataView-BdVCiAp9.js → DataView-vlcIjDQU.js} +2 -2
  21. package/dist/chunks/{DataView-BdVCiAp9.js.map → DataView-vlcIjDQU.js.map} +1 -1
  22. package/dist/chunks/{FormView-DgFp-jxi.js → FormView-CIKrLod9.js} +2 -2
  23. package/dist/chunks/{FormView-DgFp-jxi.js.map → FormView-CIKrLod9.js.map} +1 -1
  24. package/dist/chunks/{FormView-BhtVKwL9.js → FormView-DJ5dlZel.js} +2 -2
  25. package/dist/chunks/{FormView-BhtVKwL9.js.map → FormView-DJ5dlZel.js.map} +1 -1
  26. package/dist/chunks/{ListView-gdCMcQIE.js → ListView-Bn5Ri8LL.js} +2 -2
  27. package/dist/chunks/{ListView-CjPzUY3T.js.map → ListView-Bn5Ri8LL.js.map} +1 -1
  28. package/dist/chunks/{ListView-CjPzUY3T.js → ListView-jMZAX1m1.js} +2 -2
  29. package/dist/chunks/{ListView-gdCMcQIE.js.map → ListView-jMZAX1m1.js.map} +1 -1
  30. package/dist/chunks/{MetricsCountryMapView-DZ7mV3K_.js → MetricsCountryMapView-BjrWZ2wR.js} +2 -2
  31. package/dist/chunks/{MetricsCountryMapView-DZ7mV3K_.js.map → MetricsCountryMapView-BjrWZ2wR.js.map} +1 -1
  32. package/dist/chunks/{MetricsCountryMapView-Bz2-6GXP.js → MetricsCountryMapView-zMbQosqx.js} +2 -2
  33. package/dist/chunks/{MetricsCountryMapView-Bz2-6GXP.js.map → MetricsCountryMapView-zMbQosqx.js.map} +1 -1
  34. package/dist/chunks/{Modal-BK-B8pvg.js → Modal-C4FlQpgV.js} +3 -3
  35. package/dist/chunks/{Modal-BK-B8pvg.js.map → Modal-C4FlQpgV.js.map} +1 -1
  36. package/dist/chunks/{Modal-BAEK2ub4.js → Modal-D98v6vDY.js} +3 -3
  37. package/dist/chunks/{Modal-BAEK2ub4.js.map → Modal-D98v6vDY.js.map} +1 -1
  38. package/dist/chunks/Passkeys-7jk0vVKB.js +2 -0
  39. package/dist/chunks/Passkeys-7jk0vVKB.js.map +1 -0
  40. package/dist/chunks/Passkeys-BWKWmIru.js +2 -0
  41. package/dist/chunks/Passkeys-BWKWmIru.js.map +1 -0
  42. package/dist/chunks/{TokenManager-C_MSIpHm.js → TokenManager-BnH97low.js} +2 -2
  43. package/dist/chunks/{TokenManager-C_MSIpHm.js.map → TokenManager-BnH97low.js.map} +1 -1
  44. package/dist/chunks/{TokenManager-Dt6BcbMV.js → TokenManager-zrSKHIM_.js} +2 -2
  45. package/dist/chunks/{TokenManager-Dt6BcbMV.js.map → TokenManager-zrSKHIM_.js.map} +1 -1
  46. package/dist/chunks/{User-BghEdscC.js → User-C_7_KCNq.js} +2 -2
  47. package/dist/chunks/User-C_7_KCNq.js.map +1 -0
  48. package/dist/chunks/{User-8dMZt39a.js → User-J99brn_P.js} +2 -2
  49. package/dist/chunks/User-J99brn_P.js.map +1 -0
  50. package/dist/chunks/{UserProfileView-BmWgWJMm.js → UserProfileView-4V7IpMEa.js} +2 -2
  51. package/dist/chunks/{UserProfileView-BmWgWJMm.js.map → UserProfileView-4V7IpMEa.js.map} +1 -1
  52. package/dist/chunks/{UserProfileView-CkE4VkPs.js → UserProfileView-Bx5dx9Qz.js} +2 -2
  53. package/dist/chunks/{UserProfileView-CkE4VkPs.js.map → UserProfileView-Bx5dx9Qz.js.map} +1 -1
  54. package/dist/chunks/{WebApp-SFmx4IhA.js → WebApp-C0uVAJD6.js} +2 -2
  55. package/dist/chunks/{WebApp-SFmx4IhA.js.map → WebApp-C0uVAJD6.js.map} +1 -1
  56. package/dist/chunks/{WebApp-BNlf4v3h.js → WebApp-DOI4CVxV.js} +2 -2
  57. package/dist/chunks/{WebApp-BNlf4v3h.js.map → WebApp-DOI4CVxV.js.map} +1 -1
  58. package/dist/chunks/{admin-models-DU-YmVqA.js → admin-models-DcgLYzHL.js} +2 -2
  59. package/dist/chunks/{admin-models-DU-YmVqA.js.map → admin-models-DcgLYzHL.js.map} +1 -1
  60. package/dist/chunks/{admin-models-DAztlbwB.js → admin-models-UnmoIgjw.js} +2 -2
  61. package/dist/chunks/{admin-models-DAztlbwB.js.map → admin-models-UnmoIgjw.js.map} +1 -1
  62. package/dist/chunks/{exportChart-_YXZlTpb.js → exportChart-BmDfoM3q.js} +2 -2
  63. package/dist/chunks/{exportChart-_YXZlTpb.js.map → exportChart-BmDfoM3q.js.map} +1 -1
  64. package/dist/chunks/{exportChart-DBUjlLsc.js → exportChart-tiJR9qNi.js} +2 -2
  65. package/dist/chunks/{exportChart-DBUjlLsc.js.map → exportChart-tiJR9qNi.js.map} +1 -1
  66. package/dist/chunks/{index-SAcE49b3.js → index-CxLk1Oj_.js} +2 -2
  67. package/dist/chunks/{index-SAcE49b3.js.map → index-CxLk1Oj_.js.map} +1 -1
  68. package/dist/chunks/{index-CokBDrQ-.js → index-z-tJqAEB.js} +2 -2
  69. package/dist/chunks/{index-CokBDrQ-.js.map → index-z-tJqAEB.js.map} +1 -1
  70. package/dist/chunks/{version-CraQlYEB.js → version-Ci7oBATv.js} +2 -2
  71. package/dist/chunks/{version-CraQlYEB.js.map → version-Ci7oBATv.js.map} +1 -1
  72. package/dist/chunks/{version-E6pgkslg.js → version-Dd81GuME.js} +2 -2
  73. package/dist/chunks/{version-E6pgkslg.js.map → version-Dd81GuME.js.map} +1 -1
  74. package/dist/docit.cjs.js +1 -1
  75. package/dist/docit.es.js +1 -1
  76. package/dist/index.cjs.js +1 -1
  77. package/dist/index.es.js +1 -1
  78. package/dist/lightbox.cjs.js +1 -1
  79. package/dist/lightbox.es.js +1 -1
  80. package/dist/map.cjs.js +1 -1
  81. package/dist/map.es.js +1 -1
  82. package/dist/timeline.cjs.js +1 -1
  83. package/dist/timeline.es.js +1 -1
  84. package/dist/user-profile.cjs.js +1 -1
  85. package/dist/user-profile.es.js +1 -1
  86. package/dist/web-mojo.lite.iife.js +70 -19
  87. package/dist/web-mojo.lite.iife.js.map +1 -1
  88. package/dist/web-mojo.lite.iife.min.js +29 -29
  89. package/dist/web-mojo.lite.iife.min.js.map +1 -1
  90. package/package.json +1 -1
  91. package/dist/chunks/ChatView-C9_eY2ow.js +0 -2
  92. package/dist/chunks/ChatView-C9_eY2ow.js.map +0 -1
  93. package/dist/chunks/ChatView-DoCBGAM0.js +0 -2
  94. package/dist/chunks/ChatView-DoCBGAM0.js.map +0 -1
  95. package/dist/chunks/Passkeys-BrX-55UB.js +0 -2
  96. package/dist/chunks/Passkeys-BrX-55UB.js.map +0 -1
  97. package/dist/chunks/Passkeys-DXYu8Plj.js +0 -2
  98. package/dist/chunks/Passkeys-DXYu8Plj.js.map +0 -1
  99. package/dist/chunks/User-8dMZt39a.js.map +0 -1
  100. package/dist/chunks/User-BghEdscC.js.map +0 -1
@@ -11,8 +11,8 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
11
11
  ${r?`<span class="font-monospace">${i}</span>`:""}
12
12
  ${n}
13
13
  </span>
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){if(Array.isArray(t)&&t.every(i=>typeof i=="string"))return t.reduce((i,r)=>this.apply(r,i,...s),e);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((r,n)=>this.apply(n.name,r,...n.args),e):e}parsePipeString(e,t=null){const s=[],i=e.split("|").map(r=>r.trim());for(const r of i){const n=this.parseFormatter(r,t);n&&s.push(n)}return s}parseFormatter(e,t=null){const s=e.match(/^([a-zA-Z_]\w*)\s*\((.*)\)$/);if(s){const[,r,n]=s,a=n?this.parseArguments(n,t):[];return{name:r,args:a}}const i=e.match(/^([a-zA-Z_]\w*)(?::(.+))?$/);if(i){const[,r,n]=i,a=n?this.parseColonArguments(n,t):[];return{name:r,args:a}}return null}parseArguments(e,t=null){const s=[];let i="",r=!1,n=null,a=0;for(let o=0;o<e.length;o++){const l=e[o];!r&&(l==='"'||l==="'")?(r=!0,n=l,i+=l):r&&l===n&&e[o-1]!=="\\"?(r=!1,n=null,i+=l):!r&&l==="{"?(a++,i+=l):!r&&l==="}"?(a--,i+=l):!r&&a===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="",r=!1,n=null;for(let a=0;a<e.length;a++){const o=e[a];!r&&(o==='"'||o==="'")?(r=!0,n=o,i+=o):r&&o===n&&e[a-1]!=="\\"?(r=!1,n=null,i+=o):!r&&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[a,o,l]=e.split("-").map(Number);s=new Date(a,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 r=t;const n=new RegExp(`(${Object.keys(i).join("|")})`,"g");return r=r.replace(n,a=>i[a]||a),r}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(),r={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 n=t;const a=Object.keys(r).sort((o,l)=>l.length-o.length);for(const o of a)n=n.replace(new RegExp(o,"g"),r[o]);return n}datetime(e,t="MM/DD/YYYY",s="HH:mm:ss"){e=this.normalizeEpoch(e);const i=this.date(e,t),r=this.time(e,s);return i&&r?`${i} ${r}`:""}datetime_tz(e,t="MM/DD/YYYY",s="HH:mm:ss",i={}){if(!e)return"";e=this.normalizeEpoch(e);const r=e instanceof Date?e:new Date(e);if(isNaN(r.getTime()))return String(e);const n=i&&i.locale||"en-US",a=i&&i.timeZone?i.timeZone:void 0,o=()=>{let k="";try{const ie=new Intl.DateTimeFormat(n,{hour:"2-digit",minute:"2-digit",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(H=>H.type==="timeZoneName");if(k=ie?ie.value:"",k&&/^GMT[+-]/i.test(k))try{const re=new Intl.DateTimeFormat(n,{timeStyle:"short",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(Is=>Is.type==="timeZoneName");re&&re.value&&!/^GMT[+-]/i.test(re.value)&&(k=re.value)}catch{}if(k&&/\s/.test(k)){const H=k.split(/\s+/).map(re=>re[0]).join("").toUpperCase();H.length>=2&&H.length<=4&&(k=H)}}catch{k=""}return k};if(!a){const k=this.date(r,t),Y=this.time(r,s),ie=o();return k&&Y?`${k} ${Y} ${ie}`.trim():""}const l=new Intl.DateTimeFormat(n,{timeZone:a,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hourCycle:"h23"}).formatToParts(r),d=k=>{const Y=l.find(ie=>ie.type===k);return Y?Y.value:""},h=d("year"),u=d("month"),m=d("day"),p=d("hour"),f=d("minute"),g=d("second"),b=u?String(parseInt(u,10)):"",y=m?String(parseInt(m,10)):"",C=p?String(parseInt(p,10)):"",_=p?parseInt(p,10)%12||12:"",A=p?parseInt(p,10)>=12?"PM":"AM":"",F=A?A.toLowerCase():"",j=new Intl.DateTimeFormat(n,{timeZone:a,month:"long"}).format(r),M=new Intl.DateTimeFormat(n,{timeZone:a,month:"short"}).format(r),R=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"long"}).format(r),oe=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"short"}).format(r),be={YYYY:h,YY:h?h.slice(-2):"",MMMM:j,MMM:M,MM:u,M:b,dddd:R,ddd:oe,DD:m,D:y},ye={HH:p,H:C,hh:_!==""?String(_).padStart(2,"0"):"",h:_!==""?String(_):"",mm:f,m:f?String(parseInt(f,10)):"",ss:g,s:g?String(parseInt(g,10)):"",A,a:F},I=(k,Y)=>{if(!k)return"";const ie=new RegExp(`(${Object.keys(Y).sort((H,re)=>re.length-H.length).join("|")})`,"g");return k.replace(ie,H=>Y[H]??H)},z=I(t,be),Pt=I(s,ye),Ds=o();return z&&Pt?`${z} ${Pt} ${Ds}`.trim():""}normalizeEpoch(e){if(e instanceof Date)return e;if(typeof e=="string"){const t=Number(e);if(Number.isFinite(t))e=t;else{const s=Date.parse(e);return Number.isFinite(s)?s:""}}else typeof e!="number"&&(e=Number(e));if(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,r=this.date(e,s),n=this.date(i,s);return!r||!n?"":`${r} - ${n}`}datetime_range(e,t=null,s="MM/DD/YYYY",i="HH:mm"){if(!e)return"";const r=t||new Date,n=this.datetime(e,s,i),a=this.datetime(r,s,i);return!n||!a?"":`${n} - ${a}`}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 r=s-new Date,n=Math.abs(r),a=Math.floor(n/1e3),o=Math.floor(a/60),l=Math.floor(o/60),d=Math.floor(l/24),h=r>0;if(t)return d>365?Math.floor(d/365)+"y":d>30?Math.floor(d/30)+"mo":d>7?Math.floor(d/7)+"w":d>0?d+"d":l>0?l+"h":o>0?o+"m":"now";if(d>365){const u=Math.floor(d/365),m=h?"in ":"",p=h?"":" ago";return m+u+" year"+(u>1?"s":"")+p}if(d>30){const u=Math.floor(d/30),m=h?"in ":"",p=h?"":" ago";return m+u+" month"+(u>1?"s":"")+p}if(d>7){const u=Math.floor(d/7),m=h?"in ":"",p=h?"":" ago";return m+u+" week"+(u>1?"s":"")+p}if(d===1)return h?"tomorrow":"yesterday";if(d>0){const u=h?"in ":"",m=h?"":" ago";return u+d+" days"+m}if(l>0){const u=h?"in ":"",m=h?"":" ago";return u+l+" hour"+(l>1?"s":"")+m}if(o>0){const u=h?"in ":"",m=h?"":" ago";return u+o+" minute"+(o>1?"s":"")+m}if(a>30){const u=h?"in ":"",m=h?"":" ago";return u+a+" 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 r=Math.abs(i).toString(),n=i<0?"-":"";let a,o;r.length<=2?(a="0",o=r.padStart(2,"0")):(a=r.slice(0,-2),o=r.slice(-2)),a=a.replace(/\B(?=(\d{3})+(?!\d))/g,",");let l;if(s===0)parseInt(o)>=50&&(a=(parseInt(a.replace(/,/g,""))+1).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")),l=a;else if(s===2)l=`${a}.${o}`;else{const d=o.slice(0,s).padEnd(s,"0");l=`${a}.${d}`}return n+t+l}percent(e,t=0,s=!0){const i=parseFloat(e);if(isNaN(i))return String(e);const r=s?i*100:i;return this.number(r,t)+"%"}filesize(e,t=!1,s=1){const i=parseInt(e);if(isNaN(i))return String(e);const r=t?["B","KiB","MiB","GiB","TiB"]:["B","KB","MB","GB","TB"],n=t?1024:1e3;let a=i,o=0;for(;a>=n&&o<r.length-1;)a/=n,o++;const l=o===0?0:s;return`${a.toFixed(l)} ${r[o]}`}ordinal(e,t=!1){const s=parseInt(e);if(isNaN(s))return String(e);const i=s%10,r=s%100;let n="th";return i===1&&r!==11?n="st":i===2&&r!==12?n="nd":i===3&&r!==13&&(n="rd"),t?n:s+n}compact(e,t=1){const s=parseFloat(e);if(isNaN(s))return String(e);const i=Math.abs(s),r=s<0?"-":"";return i>=1e9?r+(i/1e9).toFixed(t)+"B":i>=1e6?r+(i/1e6).toFixed(t)+"M":i>=1e3?r+(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 r=String(e);if(t==null||t==="")return r;if(t instanceof RegExp)return r.replace(t,String(s));const n=String(t),a=n.match(/^\/(.+)\/([a-z]*)$/i);if(a){const[,o,l]=a;try{return r.replace(new RegExp(o,l),String(s))}catch{}}return String(i).includes("g")?r.split(n).join(String(s)):r.replace(n,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 r=Math.floor(t/2),n=i.substring(0,r),a=i.substring(i.length-r);return`${n}${s}${a}`}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(r=>r.length>0).slice(0,t).map(r=>r.charAt(0).toUpperCase()).join("")}mask(e,t="*",s=4){const i=String(e);if(i.length<=s)return i;const r=t.repeat(Math.max(0,i.length-s)),n=i.slice(-s);return r+n}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)}`:"",r=t.body?`&body=${encodeURIComponent(t.body)}`:"",n=t.class?` class="${t.class}"`:"";return`<a href="mailto:${s}${i}${r}"${n}>${s}</a>`}phone(e,t="US",s=!0){let i=String(e).replace(/\D/g,""),r=i;return t==="US"&&(i.length===10?r=`(${i.slice(0,3)}) ${i.slice(3,6)}-${i.slice(6)}`:i.length===11&&i[0]==="1"&&(r=`+1 (${i.slice(1,4)}) ${i.slice(4,7)}-${i.slice(7)}`)),s?`<a href="tel:${i}">${r}</a>`:r}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(n=>this.badge(n,t)).join(" ");const s=String(e);if(typeof t=="string"&&t.includes("=")){const n=Object.fromEntries(t.split(",").map(l=>l.split("=").map(d=>d.trim()))),a=n[s]||n[s.toLowerCase()]||this.inferBadgeType(s);return`<span class="badge ${a?`bg-${a}`:"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,r=!1){const n=String(e).toLowerCase(),a={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[n]||a[n]||"",d=s[n]||o[n]||"secondary";let h="";!i&&l&&(h=`<i class="${l}"></i>`);let u="";return r||(u=e),`<span class="text-${d}">${h}${h?" ":""}${u}</span>`}boolean(e,t="True",s="False",i=!1){const r=e?t:s;return i?`<span class="text-${e?"success":"danger"}">${r}</span>`:r}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 r=this._extractImageUrl(e,t);return r?`<img src="${r}" class="${s}" alt="${i}" />`:""}avatar(e,t="md",s="rounded-circle",i=""){const r=this._extractImageUrl(e,"square_sm")||Rt,n={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;"},a=n[t]||n.md,l=`object-fit-cover ${s}`.trim();return`<img src="${r}" class="${l}" style="${a}" alt="${i}" />`}tooltip(e,t="",s="top",i=""){if(e==null)return"";const r=String(e),n=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="${n}">${r}</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 r=parseInt(e);if(isNaN(r))return i?`${e} ${t}`:t||"";const n=Math.abs(r)===1?t:s||t+"s";return i?`${r} ${n}`:n}formatList(e,t={}){if(!Array.isArray(e))return String(e);const{conjunction:s="and",limit:i=null,moreText:r="others"}=t;if(e.length===0)return"";if(e.length===1)return String(e[0]);let n=e.slice(),a=!1;if(i&&e.length>i&&(n=e.slice(0,i),a=!0),a){const o=e.length-i;return`${n.join(", ")}, ${s} ${o} ${r}`}return n.length===2?`${n[0]} ${s} ${n[1]}`:`${n.slice(0,-1).join(", ")}, ${s} ${n[n.length-1]}`}duration(e,t="ms",s=!1,i=2){if(e==null)return"";const r=parseFloat(e);if(isNaN(r))return String(e);let n;switch(t){case"s":case"sec":case"seconds":n=r*1e3;break;case"m":case"min":case"minutes":n=r*6e4;break;case"h":case"hr":case"hours":n=r*36e5;break;case"d":case"day":case"days":n=r*864e5;break;default:n=r}const a=[{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(n===0)return s?"0s":"0 seconds";const o=Math.abs(n),l=n<0?"-":"",d=[];let h=o;for(const u of a)if(h>=u.value){const m=Math.floor(h/u.value);h=h%u.value;const p=s?u.short:m===1?u.name:u.name+"s";if(d.push(s?`${m}${p}`:`${m} ${p}`),d.length>=i)break}return d.length===0?s?`${Math.round(o)}ms`:`${Math.round(o)} milliseconds`:l+(s?d.join(""):d.join(" "))}hash(e,t=8,s="",i="..."){if(e==null)return"";const r=String(e);return r.length<=t?s+r:s+r.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,"\\$&"),r=new RegExp(`(${i})`,"gi");return String(e).replace(r,`<mark class="${s}">$1</mark>`)}hex(e,t=!1,s=!1){if(e==null)return"";let i="";const r=n=>Array.from(n).map(a=>a.toString(16).padStart(2,"0")).join("");if(typeof e=="number"){let n=Math.abs(Math.trunc(e)).toString(16);n.length%2&&(n="0"+n),i=n}else if(e instanceof Uint8Array)i=r(e);else if(e instanceof ArrayBuffer)i=r(new Uint8Array(e));else if(Array.isArray(e)&&e.every(n=>typeof n=="number"))i=r(Uint8Array.from(e.map(n=>n&255)));else{const a=new TextEncoder().encode(String(e));i=r(a)}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 r=parseInt(t.slice(i,i+2),16);if(Number.isNaN(r))return String(e);s[i/2]=r}try{return new TextDecoder().decode(s)}catch{let r="";for(const n of s)r+=String.fromCharCode(n);return r}}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 V=new jt;window.dataFormatter=V;const Qe=new Set(["__proto__","constructor","prototype"]),Xe=(c,e)=>c!=null&&Object.prototype.hasOwnProperty.call(c,e);class ${static getContextData(e,t){if(!t||e==null)return;let s=t,i="",r=0,n=-1;for(let o=0;o<t.length;o++){const l=t[o];if(l==="(")r++;else if(l===")")r--;else if(l==="|"&&r===0){n=o;break}}n>-1&&(s=t.substring(0,n).trim(),i=t.substring(n+1).trim());const a=this.getNestedValue(e,s);return i?V.pipe(a,i,e):a}static getNestedValue(e,t){if(!t||e==null||t.split(".").some(r=>Qe.has(r)))return;if(!t.includes(".")){if(t in e){const r=e[t];return typeof r=="function"?r===Object.prototype[t]?void 0:r.call(e):r}return}const s=t.split(".");let i=e;for(let r=0;r<s.length;r++){const n=s[r];if(i==null)return;if(r===0)if(Xe(i,n)){const a=i[n];typeof a=="function"?i=a.call(e):i=a}else return;else{if(i&&typeof i.getContextValue=="function"){const a=s.slice(r).join(".");return i.getContextValue(a)}if(Array.isArray(i)&&!isNaN(n))i=i[parseInt(n)];else if(Xe(i,n))i=i[n];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(...r){const n=()=>{clearTimeout(s),e(...r)};clearTimeout(s),s=setTimeout(n,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 r=[/123/,/abc/i,/qwerty/i,/asdf/i,/(.)\1{2,}/,/password/i,/admin/i,/user/i,/login/i];for(const o of r)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 a;return i<2?a="very-weak":i<4?a="weak":i<6?a="fair":i<8?a="good":a="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:a,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",r="ABCDEFGHIJKLMNOPQRSTUVWXYZ",n="0123456789",a="!@#$%^&*()_+-=[]{}|;:,.<>?";s.excludeAmbiguous&&(i=i.replace(/[il]/g,""),r=r.replace(/[IOL]/g,""),n=n.replace(/[01]/g,""),a=a.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+=r,l.push(r[Math.floor(Math.random()*r.length)])),s.includeNumbers&&(o+=n,l.push(n[Math.floor(Math.random()*n.length)])),s.includeSpecialChars&&(o+=a,l.push(a[Math.floor(Math.random()*a.length)]))),!o)throw new Error("No character types selected for password generation");let d="";for(const h of l)d+=h;for(let h=d.length;h<s.length;h++)d+=o[Math.floor(Math.random()*o.length)];return d.split("").sort(()=>Math.random()-.5).join("")}static parseQueryString(e){const t={},s=new URLSearchParams(e);for(const[i,r]of s.entries())t[i]=r;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 Ee(i,t):i):new Ee(e,t)}}class Ee{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]=$.wrapData(i,t)}}}getContextValue(e){let t=e,s="",i=0,r=-1;for(let a=0;a<e.length;a++){const o=e[a];if(o==="(")i++;else if(o===")")i--;else if(o==="|"&&i===0){r=a;break}}r>-1&&(t=e.substring(0,r).trim(),s=e.substring(r+1).trim());let n;return t in this&&!Qe.has(t)&&t!=="_data"&&t!=="_rootContext"?n=this[t]:n=$.getNestedValue(this._data,t),s&&n!==void 0?V.pipe(n,s,this._rootContext||this._data):n}has(e){return this._data&&this._data.hasOwnProperty(e)}toJSON(){return this._data}}$.DataWrapper=Ee,typeof window<"u"&&(window.utils=$);const zt=new Set(["__proto__","constructor","prototype"]),Ht=Object.prototype.toString,le=Array.isArray||function(c){return Ht.call(c)==="[object Array]"},ue=function(c){return typeof c=="function"},et=function(c){return c!==null&&typeof c=="object"};function qt(){return typeof window>"u"?null:window.MOJO?.dataFormatter?window.MOJO.dataFormatter:window.dataFormatter?window.dataFormatter:null}const tt=function(c){const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(c).replace(/[&<>"'`=\/]/g,function(t){return e[t]})};class st{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 we{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 we(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(".")?e.slice(1):e).split("|")[0].split(".").some(r=>zt.has(r)))return;if(e&&e.startsWith(".")){let i=e.substring(1),r=!1,n=null;const a=i.indexOf("|");if(a!==-1&&(n=i.substring(a+1).trim(),i=i.substring(0,a).trim()),i.endsWith("|iter")&&(i=i.substring(0,i.length-5),r=!0),this.view&&typeof this.view=="object"){let o;if(typeof this.view.getContextValue=="function")try{o=this.view.getContextValue(i),o!==void 0&&ue(o)&&(o=o.call(this.view))}catch{o=void 0}if(o===void 0&&(i.indexOf(".")>0?o=$.getNestedValue(this.view,i):i in this.view&&(o=this.view[i],ue(o)&&(o===Object.prototype[i]?o=void 0:o=o.call(this.view)))),n&&o!==void 0)try{const l=qt();l&&typeof l.pipe=="function"&&(o=l.pipe(o,n,this))}catch{}return le(o)?r?o:o.length>0:et(o)?r?Object.entries(o).map(([l,d])=>({key:l,value:d})):Object.keys(o).length>0:o}return}const t=this.cache;let s;if(t.hasOwnProperty(e))s=t[e];else{let i=this,r,n,a,o=!1;for(;i;){if(i.view&&typeof i.view.getContextValue=="function")try{r=i.view.getContextValue(e),r!==void 0&&(o=!0)}catch{o=!1}if(!o)if(e.indexOf(".")>0)for(r=i.view,n=e.split("."),a=0;r!=null&&a<n.length;)if(r&&typeof r.getContextValue=="function"&&a<n.length)try{const l=n.slice(a).join(".");r=r.getContextValue(l),a=n.length,r!==void 0&&(o=!0)}catch{a===n.length-1&&(o=Fe(r,n[a])||it(r,n[a])),r=r[n[a++]]}else a===n.length-1&&(o=Fe(r,n[a])||it(r,n[a])),r=r[n[a++]];else r=i.view[e],o=Fe(i.view,e);if(o){s=r;break}i=i.parent}t[e]=s}if(ue(s)){const i=e.split("|")[0].split(".").pop();if(s===Object.prototype[i])s=void 0;else try{s=s.call(this.view)}catch(r){if(r instanceof TypeError&&/^Class constructor /.test(r.message))s=void 0;else throw r}}if(this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;this.renderCache.set(i,s)}return s}}function Fe(c,e){return c!=null&&typeof c=="object"&&e in c}function it(c,e){return c!=null&&typeof c!="object"&&c.hasOwnProperty&&c.hasOwnProperty(e)}class rt{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],r=new st(e),n=[];let a,o,l,d,h;const u=new RegExp(De(s)+"\\s*"),m=new RegExp("\\s*"+De(i)),p=new RegExp("\\s*"+De("}"+i));for(;!r.eos();){if(a=r.pos,l=r.scanUntil(u),l)for(let f=0;f<l.length;++f)d=l.charAt(f),d===`
15
- `?n.push(["text",d]):n.push(["text",d]);if(!r.scan(u))break;if(o=r.scan(/[#^\/>{&=!]/),o||(o="name"),r.scan(/\s*/),o==="="?(l=r.scanUntil(/\s*=/),r.scan(/\s*=/),r.scanUntil(m)):o==="{"?(l=r.scanUntil(p),r.scan(p),o="&"):l=r.scanUntil(m),r.scan(m),o==="#"||o==="^")h=[o,l,a,r.pos],n.push(h);else if(o==="/"){let f;for(let g=n.length-1;g>=0;--g)if((n[g][0]==="#"||n[g][0]==="^")&&n[g][1]===l){f=n[g];break}f&&f.length===4&&f.push(r.pos),n.push([o,l,a,r.pos])}else n.push([o,l,a,r.pos])}return this.nestSections(this.squashTokens(n))}squashTokens(e){const t=[];let s,i;for(let r=0;r<e.length;++r)s=e[r],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 r=0;r<e.length;++r){const n=e[r];switch(n[0]){case"#":case"^":const a=[n[0],n[1],n[2],n[3],[],n[4]||null];s.push(a),i.push(a),s=a[4];break;case"/":const o=i.pop();o&&(o[5]=n[2],s=i.length>0?i[i.length-1][4]:t);break;default:s.push(n)}}return t}render(e,t,s,i){const r=this.getConfigTags(i)||["{{","}}"],n=this.parse(e,r),a=new Map;return this.renderTokens(n,new we(t),s,e,i,a)}renderTokens(e,t,s,i,r,n){n&&!t.renderCache&&(t.renderCache=n);let a="";for(let o=0;o<e.length;++o){const l=e[o];let d;switch(l[0]){case"#":if(d=t.lookup(l[1]),!d)continue;const h=l[4];if(!h||!le(h)){console.warn(`MUSTACHE WARNING - Section ${l[1]} has no child tokens:`,l);continue}if(le(d))for(let u=0;u<d.length;++u){const m=t.push(d[u]);t.renderCache&&(m.renderCache=t.renderCache);const p=this.renderTokens(h,m,s,i,r,n);a+=p}else if(typeof d=="object"||typeof d=="string"||typeof d=="number"){const u=t.push(d);t.renderCache&&(u.renderCache=t.renderCache),a+=this.renderTokens(h,u,s,i,r,n)}else if(ue(d)){const u=i==null?null:i.slice(l[3],l[5]);d=d.call(t.view,u,m=>this.render(m,t.view,s,r)),d!=null&&(a+=d)}else d&&(a+=this.renderTokens(h,t,s,i,r,n));break;case"^":if(d=t.lookup(l[1]),!d||le(d)&&d.length===0){const u=l[4];u&&le(u)&&(a+=this.renderTokens(u,t,s,i,r,n))}break;case">":if(!s)continue;d=ue(s)?s(l[1]):s[l[1]],d!=null&&(a+=this.render(d,t.view,s,r));break;case"&":d=t.lookup(l[1]),d!=null&&(a+=d);break;case"name":d=t.lookup(l[1]),d!=null&&(a+=tt(d));break;case"text":a+=l[1];break}}return a}getConfigTags(e){return et(e)&&le(e.tags)?e.tags:null}}function De(c){return c.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}const Ie=new rt,D={name:"MOJO Mustache",version:"1.0.0",tags:["{{","}}"],Scanner:st,Context:we,Writer:rt,escape:tt,clearCache(){return Ie.clearCache()},parse(c,e){return Ie.parse(c,e)},render(c,e,t,s){if(typeof c!="string")throw new TypeError('Invalid template! Template should be a "string"');return e&&typeof e=="object"&&!e.getContextValue&&typeof e.toJSON!="function"&&(e=$.wrapData(e)),Ie.render(c,e,t,s)}};class Bt{constructor(e){this.view=e,this.domListeners=[],this.debounceTimers=new Map}_enterDispatchChain(e){const t=e._mojoDispatch;let s;return e._mojoDispatch=new Promise(i=>{s=i}),{prior:t,done:s}}bind(e){if(this.unbind(),!e)return;const t=async a=>{const{prior:o,done:l}=this._enterDispatchChain(a);try{o&&await o;const d=a.target.closest("[data-action]");if(d&&this.shouldHandle(d,a)){const u=d.getAttribute("data-action");if(d.tagName==="A"&&a.preventDefault(),this.hideTooltip(d),await this.dispatch(u,a,d)){a.preventDefault(),a.stopPropagation(),a.handledByChild=!0;return}}const h=a.target.closest("a[href], [data-page]");if(h&&!h.hasAttribute("data-action")&&this.shouldHandle(h,a)){if(a.ctrlKey||a.metaKey||a.shiftKey||a.button===1)return;if(h.tagName==="A"){const u=h.getAttribute("href");if(u&&u!=="#"&&!u.startsWith("#")&&(this.view.isExternalLink(u)||h.hasAttribute("data-external")))return}this.hideTooltip(h),a.preventDefault(),a.stopPropagation(),a.handledByChild=!0,h.hasAttribute("data-page")?await this.view.handlePageNavigation(h):await this.view.handleHrefNavigation(h)}}finally{l()}},s=async a=>{const{prior:o,done:l}=this._enterDispatchChain(a);try{o&&await o;const d=a.target.closest("[data-change-action]");if(d&&this.shouldHandle(d,a)){const u=d.getAttribute("data-change-action");await this.dispatchChange(u,a,d)&&(a.stopPropagation(),a.handledByChild=!0);return}const h=a.target.closest("[data-action]");if(h&&this.isFormControl(h)&&this.shouldHandle(h,a)){const u=h.getAttribute("data-action");await this.dispatch(u,a,h)&&(a.stopPropagation(),a.handledByChild=!0)}}finally{l()}},i=a=>{const o=a.target.closest("[data-change-action]");if(o&&this.shouldHandle(o,a)&&a.target.matches('[data-filter="live-search"]')){const m=o.getAttribute("data-change-action"),p=parseInt(o.getAttribute("data-filter-debounce"))||300,f=`change-${m}-${o.getAttribute("data-container")||"default"}`;this.debounceTimers.has(f)&&clearTimeout(this.debounceTimers.get(f));const g=setTimeout(()=>{this.debounceTimers.delete(f),this.dispatchChange(m,a,o).then(b=>{b&&(a.stopPropagation(),a.handledByChild=!0)})},p);this.debounceTimers.set(f,g);return}const l=a.target.closest("[data-action]");if(!l||!this.isFormControl(l)||l.hasAttribute("data-change-action")||!this.shouldHandle(l,a))return;const d=l.getAttribute("data-action"),h=l.getAttribute("data-action-debounce"),u=h!=null&&parseInt(h)||0;if(u>0){const m=`action-${d}-${l.getAttribute("data-container")||"default"}`;this.debounceTimers.has(m)&&clearTimeout(this.debounceTimers.get(m));const p=setTimeout(()=>{this.debounceTimers.delete(m),this.dispatch(d,a,l).then(f=>{f&&(a.stopPropagation(),a.handledByChild=!0)})},u);this.debounceTimers.set(m,p);return}this.dispatch(d,a,l).then(m=>{m&&(a.stopPropagation(),a.handledByChild=!0)})},r=async a=>{if(a.target.matches('[data-filter="search"]'))return;const o=a.target.closest("[data-keydown-action]")||a.target.closest("[data-change-action]");if(!o)return;const{prior:l,done:d}=this._enterDispatchChain(a);try{if(l&&await l,!this.shouldHandle(o,a))return;let h=["Enter"];if(o.getAttribute("data-change-keys")&&(h=o.getAttribute("data-change-keys").split(",").map(u=>u.trim())),h.includes("*")||h.includes(a.key)){const u=o.getAttribute("data-keydown-action")||o.getAttribute("data-change-action");await this.dispatch(u,a,o)&&(a.preventDefault(),a.stopPropagation(),a.handledByChild=!0)}}finally{d()}},n=a=>{const o=a.target.closest("form[data-action]");if(!o||!this.shouldHandle(o,a))return;a.preventDefault();const l=o.getAttribute("data-action");this.dispatch(l,a,o)};e.addEventListener("click",t),e.addEventListener("change",s),e.addEventListener("input",i),e.addEventListener("keydown",r),e.addEventListener("submit",n),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:r},{el:e,type:"submit",fn:n})}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,r=l=>l.includes("-")?l.split("-").map(d=>d[0].toUpperCase()+d.slice(1)).join(""):l[0].toUpperCase()+l.slice(1),n=`handleAction${r(e)}`;if(typeof i[n]=="function")try{return t.preventDefault(),await i[n](t,s),!0}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const a=`onAction${r(e)}`;if(typeof i[a]=="function")try{return await i[a](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${r(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,n=`onChange${(a=>a.includes("-")?a.split("-").map(o=>o[0].toUpperCase()+o.slice(1)).join(""):a[0].toUpperCase()+a.slice(1))(e)}`;if(typeof i[n]=="function")try{return await i[n](t,s),!0}catch(a){return console.error(`Error in onChange ${e}:`,a),i.handleActionError?.(e,a,t,s),!0}return await this.dispatch(e,t,s)}isFormControl(e){if(!e||!e.tagName)return!1;const t=e.tagName;return t==="INPUT"||t==="TEXTAREA"||t==="SELECT"}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 Me={on(c,e,t){this._listeners||(this._listeners={}),this._listeners[c]||(this._listeners[c]=[]);const s={callback:e,context:t,fn:t?e.bind(t):e};return this._listeners[c].push(s),this},off(c,e,t){return!this._listeners||!this._listeners[c]?this:(e?(this._listeners[c]=this._listeners[c].filter(s=>s.callback!==e||arguments.length===3&&s.context!==t),this._listeners[c].length===0&&delete this._listeners[c]):delete this._listeners[c],this)},once(c,e,t){const s=(...i)=>{this.off(c,s),(t?e.bind(t):e).apply(t||this,i)};return this.on(c,s),this},emit(c,...e){if(!this._listeners||!this._listeners[c])return this;const t=this._listeners[c].slice();for(const s of t)try{s.fn.apply(s.context||this,e)}catch(i){console&&console.error&&console.error(`Error in ${c} event handler:`,i)}return this}};typeof window<"u"&&(window.Mustache=D);class S{constructor(e={}){this.tagName=e.tagName??"div",this.className=e.className??"mojo-view",this.style=e.style??null,this.id=e.id??S._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 Bt(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(e,t){t&&t.skipRender||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),t.lazyMount===!0&&(e._lazyMount=!0)),e.parent=this,this.getApp()&&(e.app=this.app),this.children[e.id]=e}catch(s){S._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=>S._warn("removeChild destroy error",i)),delete this.children[t])}catch(t){S._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 S._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){S._warn(`Render error in ${this.id}`,i)}finally{this.isRendering=!1}return this}async _renderChildren(){const e=[];for(const t in this.children){const s=this.children[t];if(s){if(s.parent=this,s._lazyMount&&!s._lazyTriggered){e.push(s);continue}await Promise.resolve(s.render()).catch(i=>S._warn(`Child render error (${t})`,i))}}e.length&&this._setupLazyMountObserver(e)}_setupLazyMountObserver(e){if(typeof IntersectionObserver>"u"){e.forEach(t=>{t._lazyTriggered=!0,Promise.resolve(t.render()).catch(s=>S._warn(`Lazy child render error (${t.id})`,s))});return}this._lazyObserver||(this._lazyObserver=new IntersectionObserver((t,s)=>{for(const i of t){if(!i.isIntersecting)continue;const r=i.target.__mojoLazyChild;s.unobserve(i.target),!(!r||r._lazyTriggered)&&(r._lazyTriggered=!0,Promise.resolve(r.render()).catch(n=>S._warn(`Lazy child render error (${r.id})`,n)))}},{rootMargin:"120px 0px",threshold:.01}));for(const t of e){const s=this.getChildElement(t.containerId);s&&(s.__mojoLazyChild=t,s.style.minHeight||(s.classList.add("mojo-lazy-placeholder"),s.style.minHeight="1px"),this._lazyObserver.observe(s),requestAnimationFrame(()=>{if(t._lazyTriggered)return;const i=s.getBoundingClientRect(),r=typeof window<"u"?window.innerHeight:0,n=typeof window<"u"?window.innerWidth:0;i.top<r+120&&i.bottom>-120&&i.left<n&&i.right>0&&(t._lazyTriggered=!0,this._lazyObserver?.unobserve(s),Promise.resolve(t.render()).catch(o=>S._warn(`Lazy child render error (${t.id})`,o)))}))}}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(),this._lazyObserver&&(this._lazyObserver.disconnect(),this._lazyObserver=null);for(const e in this.children){const t=this.children[e];t&&await Promise.resolve(t.destroy()).catch(s=>S._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){S._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){S._warn("ensureElement error",e);const t=document.createElement("div");return t.id=this.id||S._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){S._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 D.render(e,this,t)}renderTemplateString(e,t,s){return D.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){S._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&&typeof e!="function"&&(this._templateCache=t),t}getContextValue(e){const t=$.getContextData(this,e);return e&&e.startsWith("data.")&&t&&typeof t=="object"?$.wrapData(t,this):e&&e.startsWith("model.")&&e!=="model"&&t&&typeof t=="object"&&typeof t.getContextValue!="function"?$.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 r=this.getApp();if(r){r.showPage(t,i);return}const n=this.findRouter();n&&typeof n.navigateToPage=="function"?await n.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 r="/"+t;await s.navigate(r);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 r="";s&&(r+=`tooltip-${s} `),i&&(r+=`tooltip-${i}`);const n={},a=r.trim();return a&&(n.customClass=a),new window.bootstrap.Tooltip(t,n)})}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 a=document.createElement("textarea");a.value=i,document.body.appendChild(a),a.select(),document.execCommand("copy"),document.body.removeChild(a)}const r=t.querySelector("i"),n=r&&r.className;return r&&(r.className="bi bi-check",setTimeout(()=>{r.className=n},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(S.prototype,Me);class x extends S{static _openDialogs=[];static _baseZIndex={backdrop:1050,modal:1055};static getFullscreenAwareZIndex(){return document.querySelector(".table-fullscreen")?{backdrop:10040,modal:10050}:x._baseZIndex}static fixAllBackdropStacking(){const e=document.querySelectorAll(".modal-backdrop"),t=x._openDialogs;if(e.length===0||t.length===0)return;const s=[...t].sort((n,a)=>(n._dialogZIndex||0)-(a._dialogZIndex||0)),r=document.querySelector(".table-fullscreen")||document.body;e.forEach((n,a)=>{if(a>=s.length)return;const o=s[a];n.style.zIndex=o._dialogZIndex-5,n.parentNode!==r&&r.appendChild(n)})}static updateAllBackdropStacking(){x.fixAllBackdropStacking()}static getMountTarget(){return document.querySelector(".table-fullscreen")||document.body}constructor(e={}){const t=e.id||`modal-${Date.now()}-${Math.random().toString(36).slice(2,7)}`;super({...e,id:t,tagName:"div",className:`modal ${e.fade!==!1?"fade":""} ${e.className||""}`.trim().replace(/\s+/g," "),attributes:{tabindex:"-1","aria-hidden":"true","aria-labelledby":e.labelledBy||`${t}-label`,"aria-describedby":e.describedBy||null,...e.attributes}}),this.modalId=t,this.title=e.title||"",this.titleId=`${this.modalId}-label`,this.size=e.size||"",this.centered=e.centered!==void 0?e.centered:!1,this.scrollable=e.scrollable!==void 0?e.scrollable:!1,this.autoSize=e.autoSize||e.size==="auto",this.backdrop=e.backdrop!==void 0?e.backdrop:!0,this.keyboard=e.keyboard!==void 0?e.keyboard:!0,this.focus=e.focus!==void 0?e.focus:!0,this.header=e.header!==void 0?e.header:!0,this.headerContent=e.headerContent||null,this.headerView=null,this.closeButton=e.closeButton!==void 0?e.closeButton:!0,this.contextMenu=e.contextMenu||null,this._processHeaderContent(this.headerContent),this.body=e.body??e.view??e.message??e.content??"",this.bodyView=null,this.bodyClass=e.bodyClass||"",this.noBodyPadding=e.noBodyPadding||!1,this.minWidth=e.minWidth||300,this.minHeight=e.minHeight||200,e.maxHeight&&(this.maxHeight=e.maxHeight),this.maxWidthPercent=e.maxWidthPercent||.9,this.maxHeightPercent=e.maxHeightPercent||.8,this._processBodyContent(this.body),this.footer=e.footer||null,this.footerView=null,this.footerClass=e.footerClass||"",this._processFooterContent(this.footer),this.buttons=e.buttons||null,this.onShow=e.onShow||null,this.onShown=e.onShown||null,this.onHide=e.onHide||null,this.onHidden=e.onHidden||null,this.onHidePrevented=e.onHidePrevented||null,this.autoShow=e.autoShow!==void 0?e.autoShow:!1,this.modal=null,this.relatedTarget=e.relatedTarget||null}_processBodyContent(e){if(e instanceof S||e&&typeof e=="object"&&typeof e.render=="function")this.bodyView=e,this.body="",this.addChild(this.bodyView);else if(typeof e=="function")try{const t=e();t instanceof S?(this.bodyView=t,this.body="",this.addChild(this.bodyView)):t instanceof Promise?(this.bodyPromise=t,this.body='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.body=t}catch(t){console.error("ModalView: error processing body function:",t),this.body=e}else this.body=e}_processHeaderContent(e){if(e instanceof S)this.headerView=e,this.headerContent=null,this.addChild(this.headerView);else if(typeof e=="function")try{const t=e();t instanceof S?(this.headerView=t,this.headerContent=null,this.addChild(this.headerView)):t instanceof Promise?(this.headerPromise=t,this.headerContent='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.headerContent=t}catch(t){console.error("ModalView: error processing headerContent function:",t),this.headerContent=e}else this.headerContent=e}_processFooterContent(e){if(e instanceof S)this.footerView=e,this.footer=null,this.addChild(this.footerView);else if(typeof e=="function")try{const t=e();t instanceof S?(this.footerView=t,this.footer=null,this.addChild(this.footerView)):t instanceof Promise?(this.footerPromise=t,this.footer='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.footer=t}catch(t){console.error("ModalView: error processing footer function:",t),this.footer=e}else this.footer=e}async getTemplate(){const e=["modal-dialog"];return this.size&&this.size!=="auto"&&(this.size.startsWith("fullscreen")?e.push(`modal-${this.size}`):["sm","lg","xl","xxl"].includes(this.size)&&(e.push(`modal-${this.size}`),["lg","xl","xxl"].includes(this.size)&&e.push("modal-fullscreen-sm-down"))),this.centered&&e.push("modal-dialog-centered"),this.scrollable&&(this.maxHeight?e.push("overflow-hidden"):e.push("modal-dialog-scrollable")),`
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){if(Array.isArray(t)&&t.every(i=>typeof i=="string"))return t.reduce((i,r)=>this.apply(r,i,...s),e);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((r,n)=>this.apply(n.name,r,...n.args),e):e}parsePipeString(e,t=null){const s=[],i=e.split("|").map(r=>r.trim());for(const r of i){const n=this.parseFormatter(r,t);n&&s.push(n)}return s}parseFormatter(e,t=null){const s=e.match(/^([a-zA-Z_]\w*)\s*\((.*)\)$/);if(s){const[,r,n]=s,a=n?this.parseArguments(n,t):[];return{name:r,args:a}}const i=e.match(/^([a-zA-Z_]\w*)(?::(.+))?$/);if(i){const[,r,n]=i,a=n?this.parseColonArguments(n,t):[];return{name:r,args:a}}return null}parseArguments(e,t=null){const s=[];let i="",r=!1,n=null,a=0;for(let o=0;o<e.length;o++){const l=e[o];!r&&(l==='"'||l==="'")?(r=!0,n=l,i+=l):r&&l===n&&e[o-1]!=="\\"?(r=!1,n=null,i+=l):!r&&l==="{"?(a++,i+=l):!r&&l==="}"?(a--,i+=l):!r&&a===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="",r=!1,n=null;for(let a=0;a<e.length;a++){const o=e[a];!r&&(o==='"'||o==="'")?(r=!0,n=o,i+=o):r&&o===n&&e[a-1]!=="\\"?(r=!1,n=null,i+=o):!r&&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[a,o,l]=e.split("-").map(Number);s=new Date(a,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 r=t;const n=new RegExp(`(${Object.keys(i).join("|")})`,"g");return r=r.replace(n,a=>i[a]||a),r}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(),r={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 n=t;const a=Object.keys(r).sort((o,l)=>l.length-o.length);for(const o of a)n=n.replace(new RegExp(o,"g"),r[o]);return n}datetime(e,t="MM/DD/YYYY",s="HH:mm:ss"){e=this.normalizeEpoch(e);const i=this.date(e,t),r=this.time(e,s);return i&&r?`${i} ${r}`:""}datetime_tz(e,t="MM/DD/YYYY",s="HH:mm:ss",i={}){if(!e)return"";e=this.normalizeEpoch(e);const r=e instanceof Date?e:new Date(e);if(isNaN(r.getTime()))return String(e);const n=i&&i.locale||"en-US",a=i&&i.timeZone?i.timeZone:void 0,o=()=>{let k="";try{const ie=new Intl.DateTimeFormat(n,{hour:"2-digit",minute:"2-digit",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(H=>H.type==="timeZoneName");if(k=ie?ie.value:"",k&&/^GMT[+-]/i.test(k))try{const re=new Intl.DateTimeFormat(n,{timeStyle:"short",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(Ms=>Ms.type==="timeZoneName");re&&re.value&&!/^GMT[+-]/i.test(re.value)&&(k=re.value)}catch{}if(k&&/\s/.test(k)){const H=k.split(/\s+/).map(re=>re[0]).join("").toUpperCase();H.length>=2&&H.length<=4&&(k=H)}}catch{k=""}return k};if(!a){const k=this.date(r,t),Y=this.time(r,s),ie=o();return k&&Y?`${k} ${Y} ${ie}`.trim():""}const l=new Intl.DateTimeFormat(n,{timeZone:a,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hourCycle:"h23"}).formatToParts(r),d=k=>{const Y=l.find(ie=>ie.type===k);return Y?Y.value:""},h=d("year"),u=d("month"),m=d("day"),p=d("hour"),f=d("minute"),g=d("second"),b=u?String(parseInt(u,10)):"",y=m?String(parseInt(m,10)):"",C=p?String(parseInt(p,10)):"",_=p?parseInt(p,10)%12||12:"",A=p?parseInt(p,10)>=12?"PM":"AM":"",F=A?A.toLowerCase():"",j=new Intl.DateTimeFormat(n,{timeZone:a,month:"long"}).format(r),I=new Intl.DateTimeFormat(n,{timeZone:a,month:"short"}).format(r),R=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"long"}).format(r),oe=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"short"}).format(r),be={YYYY:h,YY:h?h.slice(-2):"",MMMM:j,MMM:I,MM:u,M:b,dddd:R,ddd:oe,DD:m,D:y},ye={HH:p,H:C,hh:_!==""?String(_).padStart(2,"0"):"",h:_!==""?String(_):"",mm:f,m:f?String(parseInt(f,10)):"",ss:g,s:g?String(parseInt(g,10)):"",A,a:F},M=(k,Y)=>{if(!k)return"";const ie=new RegExp(`(${Object.keys(Y).sort((H,re)=>re.length-H.length).join("|")})`,"g");return k.replace(ie,H=>Y[H]??H)},z=M(t,be),Pt=M(s,ye),Ds=o();return z&&Pt?`${z} ${Pt} ${Ds}`.trim():""}normalizeEpoch(e){if(e instanceof Date)return e;if(typeof e=="string"){const t=Number(e);if(Number.isFinite(t))e=t;else{const s=Date.parse(e);return Number.isFinite(s)?s:""}}else typeof e!="number"&&(e=Number(e));if(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,r=this.date(e,s),n=this.date(i,s);return!r||!n?"":`${r} - ${n}`}datetime_range(e,t=null,s="MM/DD/YYYY",i="HH:mm"){if(!e)return"";const r=t||new Date,n=this.datetime(e,s,i),a=this.datetime(r,s,i);return!n||!a?"":`${n} - ${a}`}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 r=s-new Date,n=Math.abs(r),a=Math.floor(n/1e3),o=Math.floor(a/60),l=Math.floor(o/60),d=Math.floor(l/24),h=r>0;if(t)return d>365?Math.floor(d/365)+"y":d>30?Math.floor(d/30)+"mo":d>7?Math.floor(d/7)+"w":d>0?d+"d":l>0?l+"h":o>0?o+"m":"now";if(d>365){const u=Math.floor(d/365),m=h?"in ":"",p=h?"":" ago";return m+u+" year"+(u>1?"s":"")+p}if(d>30){const u=Math.floor(d/30),m=h?"in ":"",p=h?"":" ago";return m+u+" month"+(u>1?"s":"")+p}if(d>7){const u=Math.floor(d/7),m=h?"in ":"",p=h?"":" ago";return m+u+" week"+(u>1?"s":"")+p}if(d===1)return h?"tomorrow":"yesterday";if(d>0){const u=h?"in ":"",m=h?"":" ago";return u+d+" days"+m}if(l>0){const u=h?"in ":"",m=h?"":" ago";return u+l+" hour"+(l>1?"s":"")+m}if(o>0){const u=h?"in ":"",m=h?"":" ago";return u+o+" minute"+(o>1?"s":"")+m}if(a>30){const u=h?"in ":"",m=h?"":" ago";return u+a+" 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 r=Math.abs(i).toString(),n=i<0?"-":"";let a,o;r.length<=2?(a="0",o=r.padStart(2,"0")):(a=r.slice(0,-2),o=r.slice(-2)),a=a.replace(/\B(?=(\d{3})+(?!\d))/g,",");let l;if(s===0)parseInt(o)>=50&&(a=(parseInt(a.replace(/,/g,""))+1).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")),l=a;else if(s===2)l=`${a}.${o}`;else{const d=o.slice(0,s).padEnd(s,"0");l=`${a}.${d}`}return n+t+l}percent(e,t=0,s=!0){const i=parseFloat(e);if(isNaN(i))return String(e);const r=s?i*100:i;return this.number(r,t)+"%"}filesize(e,t=!1,s=1){const i=parseInt(e);if(isNaN(i))return String(e);const r=t?["B","KiB","MiB","GiB","TiB"]:["B","KB","MB","GB","TB"],n=t?1024:1e3;let a=i,o=0;for(;a>=n&&o<r.length-1;)a/=n,o++;const l=o===0?0:s;return`${a.toFixed(l)} ${r[o]}`}ordinal(e,t=!1){const s=parseInt(e);if(isNaN(s))return String(e);const i=s%10,r=s%100;let n="th";return i===1&&r!==11?n="st":i===2&&r!==12?n="nd":i===3&&r!==13&&(n="rd"),t?n:s+n}compact(e,t=1){const s=parseFloat(e);if(isNaN(s))return String(e);const i=Math.abs(s),r=s<0?"-":"";return i>=1e9?r+(i/1e9).toFixed(t)+"B":i>=1e6?r+(i/1e6).toFixed(t)+"M":i>=1e3?r+(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 r=String(e);if(t==null||t==="")return r;if(t instanceof RegExp)return r.replace(t,String(s));const n=String(t),a=n.match(/^\/(.+)\/([a-z]*)$/i);if(a){const[,o,l]=a;try{return r.replace(new RegExp(o,l),String(s))}catch{}}return String(i).includes("g")?r.split(n).join(String(s)):r.replace(n,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 r=Math.floor(t/2),n=i.substring(0,r),a=i.substring(i.length-r);return`${n}${s}${a}`}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(r=>r.length>0).slice(0,t).map(r=>r.charAt(0).toUpperCase()).join("")}mask(e,t="*",s=4){const i=String(e);if(i.length<=s)return i;const r=t.repeat(Math.max(0,i.length-s)),n=i.slice(-s);return r+n}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)}`:"",r=t.body?`&body=${encodeURIComponent(t.body)}`:"",n=t.class?` class="${t.class}"`:"";return`<a href="mailto:${s}${i}${r}"${n}>${s}</a>`}phone(e,t="US",s=!0){let i=String(e).replace(/\D/g,""),r=i;return t==="US"&&(i.length===10?r=`(${i.slice(0,3)}) ${i.slice(3,6)}-${i.slice(6)}`:i.length===11&&i[0]==="1"&&(r=`+1 (${i.slice(1,4)}) ${i.slice(4,7)}-${i.slice(7)}`)),s?`<a href="tel:${i}">${r}</a>`:r}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(n=>this.badge(n,t)).join(" ");const s=String(e);if(typeof t=="string"&&t.includes("=")){const n=Object.fromEntries(t.split(",").map(l=>l.split("=").map(d=>d.trim()))),a=n[s]||n[s.toLowerCase()]||this.inferBadgeType(s);return`<span class="badge ${a?`bg-${a}`:"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,r=!1){const n=String(e).toLowerCase(),a={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[n]||a[n]||"",d=s[n]||o[n]||"secondary";let h="";!i&&l&&(h=`<i class="${l}"></i>`);let u="";return r||(u=e),`<span class="text-${d}">${h}${h?" ":""}${u}</span>`}boolean(e,t="True",s="False",i=!1){const r=e?t:s;return i?`<span class="text-${e?"success":"danger"}">${r}</span>`:r}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 r=this._extractImageUrl(e,t);return r?`<img src="${r}" class="${s}" alt="${i}" />`:""}avatar(e,t="md",s="rounded-circle",i=""){const r=this._extractImageUrl(e,"square_sm")||Rt,n={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;"},a=n[t]||n.md,l=`object-fit-cover ${s}`.trim();return`<img src="${r}" class="${l}" style="${a}" alt="${i}" />`}tooltip(e,t="",s="top",i=""){if(e==null)return"";const r=String(e),n=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="${n}">${r}</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 r=parseInt(e);if(isNaN(r))return i?`${e} ${t}`:t||"";const n=Math.abs(r)===1?t:s||t+"s";return i?`${r} ${n}`:n}formatList(e,t={}){if(!Array.isArray(e))return String(e);const{conjunction:s="and",limit:i=null,moreText:r="others"}=t;if(e.length===0)return"";if(e.length===1)return String(e[0]);let n=e.slice(),a=!1;if(i&&e.length>i&&(n=e.slice(0,i),a=!0),a){const o=e.length-i;return`${n.join(", ")}, ${s} ${o} ${r}`}return n.length===2?`${n[0]} ${s} ${n[1]}`:`${n.slice(0,-1).join(", ")}, ${s} ${n[n.length-1]}`}duration(e,t="ms",s=!1,i=2){if(e==null)return"";const r=parseFloat(e);if(isNaN(r))return String(e);let n;switch(t){case"s":case"sec":case"seconds":n=r*1e3;break;case"m":case"min":case"minutes":n=r*6e4;break;case"h":case"hr":case"hours":n=r*36e5;break;case"d":case"day":case"days":n=r*864e5;break;default:n=r}const a=[{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(n===0)return s?"0s":"0 seconds";const o=Math.abs(n),l=n<0?"-":"",d=[];let h=o;for(const u of a)if(h>=u.value){const m=Math.floor(h/u.value);h=h%u.value;const p=s?u.short:m===1?u.name:u.name+"s";if(d.push(s?`${m}${p}`:`${m} ${p}`),d.length>=i)break}return d.length===0?s?`${Math.round(o)}ms`:`${Math.round(o)} milliseconds`:l+(s?d.join(""):d.join(" "))}hash(e,t=8,s="",i="..."){if(e==null)return"";const r=String(e);return r.length<=t?s+r:s+r.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,"\\$&"),r=new RegExp(`(${i})`,"gi");return String(e).replace(r,`<mark class="${s}">$1</mark>`)}hex(e,t=!1,s=!1){if(e==null)return"";let i="";const r=n=>Array.from(n).map(a=>a.toString(16).padStart(2,"0")).join("");if(typeof e=="number"){let n=Math.abs(Math.trunc(e)).toString(16);n.length%2&&(n="0"+n),i=n}else if(e instanceof Uint8Array)i=r(e);else if(e instanceof ArrayBuffer)i=r(new Uint8Array(e));else if(Array.isArray(e)&&e.every(n=>typeof n=="number"))i=r(Uint8Array.from(e.map(n=>n&255)));else{const a=new TextEncoder().encode(String(e));i=r(a)}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 r=parseInt(t.slice(i,i+2),16);if(Number.isNaN(r))return String(e);s[i/2]=r}try{return new TextDecoder().decode(s)}catch{let r="";for(const n of s)r+=String.fromCharCode(n);return r}}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 V=new jt;window.dataFormatter=V;const Qe=new Set(["__proto__","constructor","prototype"]),Xe=(c,e)=>c!=null&&Object.prototype.hasOwnProperty.call(c,e);class ${static getContextData(e,t){if(!t||e==null)return;let s=t,i="",r=0,n=-1;for(let o=0;o<t.length;o++){const l=t[o];if(l==="(")r++;else if(l===")")r--;else if(l==="|"&&r===0){n=o;break}}n>-1&&(s=t.substring(0,n).trim(),i=t.substring(n+1).trim());const a=this.getNestedValue(e,s);return i?V.pipe(a,i,e):a}static getNestedValue(e,t){if(!t||e==null||t.split(".").some(r=>Qe.has(r)))return;if(!t.includes(".")){if(t in e){const r=e[t];return typeof r=="function"?r===Object.prototype[t]?void 0:r.call(e):r}return}const s=t.split(".");let i=e;for(let r=0;r<s.length;r++){const n=s[r];if(i==null)return;if(r===0)if(Xe(i,n)){const a=i[n];typeof a=="function"?i=a.call(e):i=a}else return;else{if(i&&typeof i.getContextValue=="function"){const a=s.slice(r).join(".");return i.getContextValue(a)}if(Array.isArray(i)&&!isNaN(n))i=i[parseInt(n)];else if(Xe(i,n))i=i[n];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(...r){const n=()=>{clearTimeout(s),e(...r)};clearTimeout(s),s=setTimeout(n,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 r=[/123/,/abc/i,/qwerty/i,/asdf/i,/(.)\1{2,}/,/password/i,/admin/i,/user/i,/login/i];for(const o of r)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 a;return i<2?a="very-weak":i<4?a="weak":i<6?a="fair":i<8?a="good":a="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:a,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",r="ABCDEFGHIJKLMNOPQRSTUVWXYZ",n="0123456789",a="!@#$%^&*()_+-=[]{}|;:,.<>?";s.excludeAmbiguous&&(i=i.replace(/[il]/g,""),r=r.replace(/[IOL]/g,""),n=n.replace(/[01]/g,""),a=a.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+=r,l.push(r[Math.floor(Math.random()*r.length)])),s.includeNumbers&&(o+=n,l.push(n[Math.floor(Math.random()*n.length)])),s.includeSpecialChars&&(o+=a,l.push(a[Math.floor(Math.random()*a.length)]))),!o)throw new Error("No character types selected for password generation");let d="";for(const h of l)d+=h;for(let h=d.length;h<s.length;h++)d+=o[Math.floor(Math.random()*o.length)];return d.split("").sort(()=>Math.random()-.5).join("")}static parseQueryString(e){const t={},s=new URLSearchParams(e);for(const[i,r]of s.entries())t[i]=r;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 Ee(i,t):i):new Ee(e,t)}}class Ee{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]=$.wrapData(i,t)}}}getContextValue(e){let t=e,s="",i=0,r=-1;for(let a=0;a<e.length;a++){const o=e[a];if(o==="(")i++;else if(o===")")i--;else if(o==="|"&&i===0){r=a;break}}r>-1&&(t=e.substring(0,r).trim(),s=e.substring(r+1).trim());let n;return t in this&&!Qe.has(t)&&t!=="_data"&&t!=="_rootContext"?n=this[t]:n=$.getNestedValue(this._data,t),s&&n!==void 0?V.pipe(n,s,this._rootContext||this._data):n}has(e){return this._data&&this._data.hasOwnProperty(e)}toJSON(){return this._data}}$.DataWrapper=Ee,typeof window<"u"&&(window.utils=$);const zt=new Set(["__proto__","constructor","prototype"]),Ht=Object.prototype.toString,le=Array.isArray||function(c){return Ht.call(c)==="[object Array]"},ue=function(c){return typeof c=="function"},et=function(c){return c!==null&&typeof c=="object"};function qt(){return typeof window>"u"?null:window.MOJO?.dataFormatter?window.MOJO.dataFormatter:window.dataFormatter?window.dataFormatter:null}const tt=function(c){const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(c).replace(/[&<>"'`=\/]/g,function(t){return e[t]})};class st{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 we{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 we(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(".")?e.slice(1):e).split("|")[0].split(".").some(r=>zt.has(r)))return;if(e&&e.startsWith(".")){let i=e.substring(1),r=!1,n=null;const a=i.indexOf("|");if(a!==-1&&(n=i.substring(a+1).trim(),i=i.substring(0,a).trim()),i.endsWith("|iter")&&(i=i.substring(0,i.length-5),r=!0),this.view&&typeof this.view=="object"){let o;if(typeof this.view.getContextValue=="function")try{o=this.view.getContextValue(i),o!==void 0&&ue(o)&&(o=o.call(this.view))}catch{o=void 0}if(o===void 0&&(i.indexOf(".")>0?o=$.getNestedValue(this.view,i):i in this.view&&(o=this.view[i],ue(o)&&(o===Object.prototype[i]?o=void 0:o=o.call(this.view)))),n&&o!==void 0)try{const l=qt();l&&typeof l.pipe=="function"&&(o=l.pipe(o,n,this))}catch{}return le(o)?r?o:o.length>0:et(o)?r?Object.entries(o).map(([l,d])=>({key:l,value:d})):Object.keys(o).length>0:o}return}const t=this.cache;let s;if(t.hasOwnProperty(e))s=t[e];else{let i=this,r,n,a,o=!1;for(;i;){if(i.view&&typeof i.view.getContextValue=="function")try{r=i.view.getContextValue(e),r!==void 0&&(o=!0)}catch{o=!1}if(!o)if(e.indexOf(".")>0)for(r=i.view,n=e.split("."),a=0;r!=null&&a<n.length;)if(r&&typeof r.getContextValue=="function"&&a<n.length)try{const l=n.slice(a).join(".");r=r.getContextValue(l),a=n.length,r!==void 0&&(o=!0)}catch{a===n.length-1&&(o=Fe(r,n[a])||it(r,n[a])),r=r[n[a++]]}else a===n.length-1&&(o=Fe(r,n[a])||it(r,n[a])),r=r[n[a++]];else r=i.view[e],o=Fe(i.view,e);if(o){s=r;break}i=i.parent}t[e]=s}if(ue(s)){const i=e.split("|")[0].split(".").pop();if(s===Object.prototype[i])s=void 0;else try{s=s.call(this.view)}catch(r){if(r instanceof TypeError&&/^Class constructor /.test(r.message))s=void 0;else throw r}}if(this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;this.renderCache.set(i,s)}return s}}function Fe(c,e){return c!=null&&typeof c=="object"&&e in c}function it(c,e){return c!=null&&typeof c!="object"&&c.hasOwnProperty&&c.hasOwnProperty(e)}class rt{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],r=new st(e),n=[];let a,o,l,d,h;const u=new RegExp(De(s)+"\\s*"),m=new RegExp("\\s*"+De(i)),p=new RegExp("\\s*"+De("}"+i));for(;!r.eos();){if(a=r.pos,l=r.scanUntil(u),l)for(let f=0;f<l.length;++f)d=l.charAt(f),d===`
15
+ `?n.push(["text",d]):n.push(["text",d]);if(!r.scan(u))break;if(o=r.scan(/[#^\/>{&=!]/),o||(o="name"),r.scan(/\s*/),o==="="?(l=r.scanUntil(/\s*=/),r.scan(/\s*=/),r.scanUntil(m)):o==="{"?(l=r.scanUntil(p),r.scan(p),o="&"):l=r.scanUntil(m),r.scan(m),o==="#"||o==="^")h=[o,l,a,r.pos],n.push(h);else if(o==="/"){let f;for(let g=n.length-1;g>=0;--g)if((n[g][0]==="#"||n[g][0]==="^")&&n[g][1]===l){f=n[g];break}f&&f.length===4&&f.push(r.pos),n.push([o,l,a,r.pos])}else n.push([o,l,a,r.pos])}return this.nestSections(this.squashTokens(n))}squashTokens(e){const t=[];let s,i;for(let r=0;r<e.length;++r)s=e[r],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 r=0;r<e.length;++r){const n=e[r];switch(n[0]){case"#":case"^":const a=[n[0],n[1],n[2],n[3],[],n[4]||null];s.push(a),i.push(a),s=a[4];break;case"/":const o=i.pop();o&&(o[5]=n[2],s=i.length>0?i[i.length-1][4]:t);break;default:s.push(n)}}return t}render(e,t,s,i){const r=this.getConfigTags(i)||["{{","}}"],n=this.parse(e,r),a=new Map;return this.renderTokens(n,new we(t),s,e,i,a)}renderTokens(e,t,s,i,r,n){n&&!t.renderCache&&(t.renderCache=n);let a="";for(let o=0;o<e.length;++o){const l=e[o];let d;switch(l[0]){case"#":if(d=t.lookup(l[1]),!d)continue;const h=l[4];if(!h||!le(h)){console.warn(`MUSTACHE WARNING - Section ${l[1]} has no child tokens:`,l);continue}if(le(d))for(let u=0;u<d.length;++u){const m=t.push(d[u]);t.renderCache&&(m.renderCache=t.renderCache);const p=this.renderTokens(h,m,s,i,r,n);a+=p}else if(typeof d=="object"||typeof d=="string"||typeof d=="number"){const u=t.push(d);t.renderCache&&(u.renderCache=t.renderCache),a+=this.renderTokens(h,u,s,i,r,n)}else if(ue(d)){const u=i==null?null:i.slice(l[3],l[5]);d=d.call(t.view,u,m=>this.render(m,t.view,s,r)),d!=null&&(a+=d)}else d&&(a+=this.renderTokens(h,t,s,i,r,n));break;case"^":if(d=t.lookup(l[1]),!d||le(d)&&d.length===0){const u=l[4];u&&le(u)&&(a+=this.renderTokens(u,t,s,i,r,n))}break;case">":if(!s)continue;d=ue(s)?s(l[1]):s[l[1]],d!=null&&(a+=this.render(d,t.view,s,r));break;case"&":d=t.lookup(l[1]),d!=null&&(a+=d);break;case"name":d=t.lookup(l[1]),d!=null&&(a+=tt(d));break;case"text":a+=l[1];break}}return a}getConfigTags(e){return et(e)&&le(e.tags)?e.tags:null}}function De(c){return c.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}const Me=new rt,D={name:"MOJO Mustache",version:"1.0.0",tags:["{{","}}"],Scanner:st,Context:we,Writer:rt,escape:tt,clearCache(){return Me.clearCache()},parse(c,e){return Me.parse(c,e)},render(c,e,t,s){if(typeof c!="string")throw new TypeError('Invalid template! Template should be a "string"');return e&&typeof e=="object"&&!e.getContextValue&&typeof e.toJSON!="function"&&(e=$.wrapData(e)),Me.render(c,e,t,s)}};class Bt{constructor(e){this.view=e,this.domListeners=[],this.debounceTimers=new Map}_enterDispatchChain(e){const t=e._mojoDispatch;let s;return e._mojoDispatch=new Promise(i=>{s=i}),{prior:t,done:s}}bind(e){if(this.unbind(),!e)return;const t=async a=>{const{prior:o,done:l}=this._enterDispatchChain(a);try{o&&await o;const d=a.target.closest("[data-action]");if(d&&this.shouldHandle(d,a)){const u=d.getAttribute("data-action");if(d.tagName==="A"&&a.preventDefault(),this.hideTooltip(d),await this.dispatch(u,a,d)){a.preventDefault(),a.stopPropagation(),a.handledByChild=!0;return}}const h=a.target.closest("a[href], [data-page]");if(h&&!h.hasAttribute("data-action")&&this.shouldHandle(h,a)){if(a.ctrlKey||a.metaKey||a.shiftKey||a.button===1)return;if(h.tagName==="A"){const u=h.getAttribute("href");if(u&&u!=="#"&&!u.startsWith("#")&&(this.view.isExternalLink(u)||h.hasAttribute("data-external")))return}this.hideTooltip(h),a.preventDefault(),a.stopPropagation(),a.handledByChild=!0,h.hasAttribute("data-page")?await this.view.handlePageNavigation(h):await this.view.handleHrefNavigation(h)}}finally{l()}},s=async a=>{const{prior:o,done:l}=this._enterDispatchChain(a);try{o&&await o;const d=a.target.closest("[data-change-action]");if(d&&this.shouldHandle(d,a)){const u=d.getAttribute("data-change-action");await this.dispatchChange(u,a,d)&&(a.stopPropagation(),a.handledByChild=!0);return}const h=a.target.closest("[data-action]");if(h&&this.isFormControl(h)&&this.shouldHandle(h,a)){const u=h.getAttribute("data-action");await this.dispatch(u,a,h)&&(a.stopPropagation(),a.handledByChild=!0)}}finally{l()}},i=a=>{const o=a.target.closest("[data-change-action]");if(o&&this.shouldHandle(o,a)&&a.target.matches('[data-filter="live-search"]')){const m=o.getAttribute("data-change-action"),p=parseInt(o.getAttribute("data-filter-debounce"))||300,f=`change-${m}-${o.getAttribute("data-container")||"default"}`;this.debounceTimers.has(f)&&clearTimeout(this.debounceTimers.get(f));const g=setTimeout(()=>{this.debounceTimers.delete(f),this.dispatchChange(m,a,o).then(b=>{b&&(a.stopPropagation(),a.handledByChild=!0)})},p);this.debounceTimers.set(f,g);return}const l=a.target.closest("[data-action]");if(!l||!this.isFormControl(l)||l.hasAttribute("data-change-action")||!this.shouldHandle(l,a))return;const d=l.getAttribute("data-action"),h=l.getAttribute("data-action-debounce"),u=h!=null&&parseInt(h)||0;if(u>0){const m=`action-${d}-${l.getAttribute("data-container")||"default"}`;this.debounceTimers.has(m)&&clearTimeout(this.debounceTimers.get(m));const p=setTimeout(()=>{this.debounceTimers.delete(m),this.dispatch(d,a,l).then(f=>{f&&(a.stopPropagation(),a.handledByChild=!0)})},u);this.debounceTimers.set(m,p);return}this.dispatch(d,a,l).then(m=>{m&&(a.stopPropagation(),a.handledByChild=!0)})},r=async a=>{if(a.target.matches('[data-filter="search"]'))return;const o=a.target.closest("[data-keydown-action]")||a.target.closest("[data-change-action]");if(!o)return;const{prior:l,done:d}=this._enterDispatchChain(a);try{if(l&&await l,!this.shouldHandle(o,a))return;let h=["Enter"];if(o.getAttribute("data-change-keys")&&(h=o.getAttribute("data-change-keys").split(",").map(u=>u.trim())),h.includes("*")||h.includes(a.key)){const u=o.getAttribute("data-keydown-action")||o.getAttribute("data-change-action");await this.dispatch(u,a,o)&&(a.preventDefault(),a.stopPropagation(),a.handledByChild=!0)}}finally{d()}},n=a=>{const o=a.target.closest("form[data-action]");if(!o||!this.shouldHandle(o,a))return;a.preventDefault();const l=o.getAttribute("data-action");this.dispatch(l,a,o)};e.addEventListener("click",t),e.addEventListener("change",s),e.addEventListener("input",i),e.addEventListener("keydown",r),e.addEventListener("submit",n),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:r},{el:e,type:"submit",fn:n})}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,r=l=>l.includes("-")?l.split("-").map(d=>d[0].toUpperCase()+d.slice(1)).join(""):l[0].toUpperCase()+l.slice(1),n=`handleAction${r(e)}`;if(typeof i[n]=="function")try{return t.preventDefault(),await i[n](t,s),!0}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const a=`onAction${r(e)}`;if(typeof i[a]=="function")try{return await i[a](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${r(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,n=`onChange${(a=>a.includes("-")?a.split("-").map(o=>o[0].toUpperCase()+o.slice(1)).join(""):a[0].toUpperCase()+a.slice(1))(e)}`;if(typeof i[n]=="function")try{return await i[n](t,s),!0}catch(a){return console.error(`Error in onChange ${e}:`,a),i.handleActionError?.(e,a,t,s),!0}return await this.dispatch(e,t,s)}isFormControl(e){if(!e||!e.tagName)return!1;const t=e.tagName;return t==="INPUT"||t==="TEXTAREA"||t==="SELECT"}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 Ie={on(c,e,t){this._listeners||(this._listeners={}),this._listeners[c]||(this._listeners[c]=[]);const s={callback:e,context:t,fn:t?e.bind(t):e};return this._listeners[c].push(s),this},off(c,e,t){return!this._listeners||!this._listeners[c]?this:(e?(this._listeners[c]=this._listeners[c].filter(s=>s.callback!==e||arguments.length===3&&s.context!==t),this._listeners[c].length===0&&delete this._listeners[c]):delete this._listeners[c],this)},once(c,e,t){const s=(...i)=>{this.off(c,s),(t?e.bind(t):e).apply(t||this,i)};return this.on(c,s),this},emit(c,...e){if(!this._listeners||!this._listeners[c])return this;const t=this._listeners[c].slice();for(const s of t)try{s.fn.apply(s.context||this,e)}catch(i){console&&console.error&&console.error(`Error in ${c} event handler:`,i)}return this}};typeof window<"u"&&(window.Mustache=D);class S{constructor(e={}){this.tagName=e.tagName??"div",this.className=e.className??"mojo-view",this.style=e.style??null,this.id=e.id??S._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 Bt(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(e,t){t&&t.skipRender||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),t.lazyMount===!0&&(e._lazyMount=!0)),e.parent=this,this.getApp()&&(e.app=this.app),this.children[e.id]=e}catch(s){S._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=>S._warn("removeChild destroy error",i)),delete this.children[t])}catch(t){S._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 S._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){S._warn(`Render error in ${this.id}`,i)}finally{this.isRendering=!1}return this}async _renderChildren(){const e=[];for(const t in this.children){const s=this.children[t];if(s){if(s.parent=this,s._lazyMount&&!s._lazyTriggered){e.push(s);continue}await Promise.resolve(s.render()).catch(i=>S._warn(`Child render error (${t})`,i))}}e.length&&this._setupLazyMountObserver(e)}_setupLazyMountObserver(e){if(typeof IntersectionObserver>"u"){e.forEach(t=>{t._lazyTriggered=!0,Promise.resolve(t.render()).catch(s=>S._warn(`Lazy child render error (${t.id})`,s))});return}this._lazyObserver||(this._lazyObserver=new IntersectionObserver((t,s)=>{for(const i of t){if(!i.isIntersecting)continue;const r=i.target.__mojoLazyChild;s.unobserve(i.target),!(!r||r._lazyTriggered)&&(r._lazyTriggered=!0,Promise.resolve(r.render()).catch(n=>S._warn(`Lazy child render error (${r.id})`,n)))}},{rootMargin:"120px 0px",threshold:.01}));for(const t of e){const s=this.getChildElement(t.containerId);s&&(s.__mojoLazyChild=t,s.style.minHeight||(s.classList.add("mojo-lazy-placeholder"),s.style.minHeight="1px"),this._lazyObserver.observe(s),requestAnimationFrame(()=>{if(t._lazyTriggered)return;const i=s.getBoundingClientRect(),r=typeof window<"u"?window.innerHeight:0,n=typeof window<"u"?window.innerWidth:0;i.top<r+120&&i.bottom>-120&&i.left<n&&i.right>0&&(t._lazyTriggered=!0,this._lazyObserver?.unobserve(s),Promise.resolve(t.render()).catch(o=>S._warn(`Lazy child render error (${t.id})`,o)))}))}}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(),this._lazyObserver&&(this._lazyObserver.disconnect(),this._lazyObserver=null);for(const e in this.children){const t=this.children[e];t&&await Promise.resolve(t.destroy()).catch(s=>S._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){S._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){S._warn("ensureElement error",e);const t=document.createElement("div");return t.id=this.id||S._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){S._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 D.render(e,this,t)}renderTemplateString(e,t,s){return D.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){S._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&&typeof e!="function"&&(this._templateCache=t),t}getContextValue(e){const t=$.getContextData(this,e);return e&&e.startsWith("data.")&&t&&typeof t=="object"?$.wrapData(t,this):e&&e.startsWith("model.")&&e!=="model"&&t&&typeof t=="object"&&typeof t.getContextValue!="function"?$.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 r=this.getApp();if(r){r.showPage(t,i);return}const n=this.findRouter();n&&typeof n.navigateToPage=="function"?await n.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 r="/"+t;await s.navigate(r);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}checkPermissions(e){if(!e)return!0;const t=this.getApp()?.activeUser;return!!(t&&typeof t.hasPermission=="function"&&t.hasPermission(e))}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 r="";s&&(r+=`tooltip-${s} `),i&&(r+=`tooltip-${i}`);const n={},a=r.trim();return a&&(n.customClass=a),new window.bootstrap.Tooltip(t,n)})}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 a=document.createElement("textarea");a.value=i,document.body.appendChild(a),a.select(),document.execCommand("copy"),document.body.removeChild(a)}const r=t.querySelector("i"),n=r&&r.className;return r&&(r.className="bi bi-check",setTimeout(()=>{r.className=n},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(S.prototype,Ie);class x extends S{static _openDialogs=[];static _baseZIndex={backdrop:1050,modal:1055};static getFullscreenAwareZIndex(){return document.querySelector(".table-fullscreen")?{backdrop:10040,modal:10050}:x._baseZIndex}static fixAllBackdropStacking(){const e=document.querySelectorAll(".modal-backdrop"),t=x._openDialogs;if(e.length===0||t.length===0)return;const s=[...t].sort((n,a)=>(n._dialogZIndex||0)-(a._dialogZIndex||0)),r=document.querySelector(".table-fullscreen")||document.body;e.forEach((n,a)=>{if(a>=s.length)return;const o=s[a];n.style.zIndex=o._dialogZIndex-5,n.parentNode!==r&&r.appendChild(n)})}static updateAllBackdropStacking(){x.fixAllBackdropStacking()}static getMountTarget(){return document.querySelector(".table-fullscreen")||document.body}constructor(e={}){const t=e.id||`modal-${Date.now()}-${Math.random().toString(36).slice(2,7)}`;super({...e,id:t,tagName:"div",className:`modal ${e.fade!==!1?"fade":""} ${e.className||""}`.trim().replace(/\s+/g," "),attributes:{tabindex:"-1","aria-hidden":"true","aria-labelledby":e.labelledBy||`${t}-label`,"aria-describedby":e.describedBy||null,...e.attributes}}),this.modalId=t,this.title=e.title||"",this.titleId=`${this.modalId}-label`,this.size=e.size||"",this.centered=e.centered!==void 0?e.centered:!1,this.scrollable=e.scrollable!==void 0?e.scrollable:!1,this.autoSize=e.autoSize||e.size==="auto",this.backdrop=e.backdrop!==void 0?e.backdrop:!0,this.keyboard=e.keyboard!==void 0?e.keyboard:!0,this.focus=e.focus!==void 0?e.focus:!0,this.header=e.header!==void 0?e.header:!0,this.headerContent=e.headerContent||null,this.headerView=null,this.closeButton=e.closeButton!==void 0?e.closeButton:!0,this.contextMenu=e.contextMenu||null,this._processHeaderContent(this.headerContent),this.body=e.body??e.view??e.message??e.content??"",this.bodyView=null,this.bodyClass=e.bodyClass||"",this.noBodyPadding=e.noBodyPadding||!1,this.minWidth=e.minWidth||300,this.minHeight=e.minHeight||200,e.maxHeight&&(this.maxHeight=e.maxHeight),this.maxWidthPercent=e.maxWidthPercent||.9,this.maxHeightPercent=e.maxHeightPercent||.8,this._processBodyContent(this.body),this.footer=e.footer||null,this.footerView=null,this.footerClass=e.footerClass||"",this._processFooterContent(this.footer),this.buttons=e.buttons||null,this.onShow=e.onShow||null,this.onShown=e.onShown||null,this.onHide=e.onHide||null,this.onHidden=e.onHidden||null,this.onHidePrevented=e.onHidePrevented||null,this.autoShow=e.autoShow!==void 0?e.autoShow:!1,this.modal=null,this.relatedTarget=e.relatedTarget||null}_processBodyContent(e){if(e instanceof S||e&&typeof e=="object"&&typeof e.render=="function")this.bodyView=e,this.body="",this.addChild(this.bodyView);else if(typeof e=="function")try{const t=e();t instanceof S?(this.bodyView=t,this.body="",this.addChild(this.bodyView)):t instanceof Promise?(this.bodyPromise=t,this.body='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.body=t}catch(t){console.error("ModalView: error processing body function:",t),this.body=e}else this.body=e}_processHeaderContent(e){if(e instanceof S)this.headerView=e,this.headerContent=null,this.addChild(this.headerView);else if(typeof e=="function")try{const t=e();t instanceof S?(this.headerView=t,this.headerContent=null,this.addChild(this.headerView)):t instanceof Promise?(this.headerPromise=t,this.headerContent='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.headerContent=t}catch(t){console.error("ModalView: error processing headerContent function:",t),this.headerContent=e}else this.headerContent=e}_processFooterContent(e){if(e instanceof S)this.footerView=e,this.footer=null,this.addChild(this.footerView);else if(typeof e=="function")try{const t=e();t instanceof S?(this.footerView=t,this.footer=null,this.addChild(this.footerView)):t instanceof Promise?(this.footerPromise=t,this.footer='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.footer=t}catch(t){console.error("ModalView: error processing footer function:",t),this.footer=e}else this.footer=e}async getTemplate(){const e=["modal-dialog"];return this.size&&this.size!=="auto"&&(this.size.startsWith("fullscreen")?e.push(`modal-${this.size}`):["sm","lg","xl","xxl"].includes(this.size)&&(e.push(`modal-${this.size}`),["lg","xl","xxl"].includes(this.size)&&e.push("modal-fullscreen-sm-down"))),this.centered&&e.push("modal-dialog-centered"),this.scrollable&&(this.maxHeight?e.push("overflow-hidden"):e.push("modal-dialog-scrollable")),`
16
16
  <div class="${e.join(" ")}">
17
17
  <div class="modal-content">
18
18
  ${await this.buildHeader()}
@@ -139,7 +139,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
139
139
  frameborder="0"
140
140
  ></iframe>
141
141
  </div>
142
- `}async onAfterMount(){await super.onAfterMount(),this._writeIframe()}onActionRefresh(){this._writeIframe()}_writeIframe(){const e=this.element?.querySelector(".mojo-html-preview-frame");if(!e)return;const t=e.contentDocument||e.contentWindow?.document;t&&(t.open(),t.write(this.html),t.close())}setHtml(e){this.html=e,this._writeIframe()}}class Q{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=ne,this.collection=t.collection||null,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]:$.getContextData(this.attributes,e)}set(e,t,s={}){const i=JSON.parse(JSON.stringify(this.attributes));let r=!1;if(e!=null){if(typeof e=="object"){for(const[n,a]of Object.entries(e))r=this._setNestedAttribute(n,a)||r;e.id!==void 0&&(this.id=e.id)}else e==="id"?(this.id=t,r=!0):r=this._setNestedAttribute(e,t);if(r&&!s.silent)if(this.emit("change",this,s),typeof e=="string")this.emit(`change:${e}`,t,this);else for(const[n,a]of Object.entries(e)){const o=this._getNestedValue(n);JSON.stringify(this._getNestedValue(n,i))!==JSON.stringify(o)&&this.emit(`change:${n}`,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 r=this._getNestedValue(e);let n=this.attributes[i],a=this[i];for(let l=1;l<s.length-1;l++){const d=s[l];(!n[d]||typeof n[d]!="object")&&(n[d]={}),(!a[d]||typeof a[d]!="object")&&(a[d]={}),n=n[d],a=a[d]}const o=s[s.length-1];return n[o]=t,a[o]=t,JSON.stringify(r)!==JSON.stringify(t)}_getNestedValue(e,t=this.attributes){if(!e.includes("."))return t[e];const s=e.split(".");let i=t;for(const r of s){if(i==null||typeof i!="object")return;i=i[r]}return i}getData(){return this.attributes}getId(){return this.id}async fetch(e={}){let t=e.url;if(!t){const n=e.id||this.getId();if(!n&&this.options.requiresId!==!1)throw new Error("Model: ID is required for fetching");t=this.buildUrl(n)}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(n){if(n.name==="AbortError")return console.info("Model: Request was cancelled"),this;throw n}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 r=await this.fetch({...t,debounceMs:0});s(r)}catch(r){i(r)}},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",r=s?this.buildUrl():this.buildUrl(this.id);this.loading=!0,this.errors={};try{const n=await this.rest[i](r,e,t.params);return n.success?n.data.status?(this.originalAttributes={...this.attributes},this.set(n.data.data,null,t),this.errors={}):this.errors=n.data:this.errors=n.errors||{},n}catch(n){return{success:!1,error:n.message,status:n.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 r of i)if(typeof r=="function"){const n=r(s,this);if(n!==!0){this.errors[e]=n||`${e} is invalid`;break}}else if(typeof r=="object"){if(r.required&&(s==null||s==="")){this.errors[e]=r.message||`${e} is required`;break}if(r.minLength&&s&&s.length<r.minLength){this.errors[e]=r.message||`${e} must be at least ${r.minLength} characters`;break}if(r.maxLength&&s&&s.length>r.maxLength){this.errors[e]=r.message||`${e} must be no more than ${r.maxLength} characters`;break}if(r.pattern&&s&&!r.pattern.test(s)){this.errors[e]=r.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(await Promise.resolve().then(()=>N)).default.alert(e,"Error",{size:"md",class:"text-danger"})}}Object.assign(Q.prototype,Me);class de{constructor(e={},t=null){if(Array.isArray(e)?(t=e,e=t||{}):t=t||e.data||[],this.ModelClass=e.ModelClass||Q,this.models=[],this.loading=!1,this.errors={},this.meta={},this.rest=ne,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 r=this.buildUrl();this.loading=!0,this.errors={},this.lastFetchTime=s,this.currentRequestKey=t,this.abortController=new AbortController,this.currentRequest=this._performFetch(r,e,this.abortController);try{return await this.currentRequest}catch(n){return n.name==="AbortError"?(console.info("Collection: Request was cancelled"),{success:!1,error:"Request cancelled",status:0}):{success:!1,error:n.message,status:n.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 r=await this.rest.GET(e,i,{signal:s.signal});if(r.success&&r.data.status){const n=this.options.parse?this.parse(r):r.data;t.reset!==!1&&this.options.reset&&this.reset(),this.add(n,{silent:t.silent}),this.errors={},this.emit("fetch:success")}else r.data&&r.data.error?(this.errors=r.data,this.emit("fetch:error",{message:r.data.error,error:r.data})):(this.errors=r.errors||{},this.emit("fetch:error",{error:r.errors}));return r}catch(r){return r.name==="AbortError"?(console.info("Collection: Fetch was cancelled"),{success:!1,error:"Request cancelled",status:0}):(this.errors={fetch:r.message},this.emit("fetch:error",{message:r.message,error:r}),{success:!1,error:r.message,status:r.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,r)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const n=await this.fetch();i(n)}catch(n){r(n)}},s)})):this.fetch():Promise.resolve(this)}async fetchMore({pageDelta:e=1}={}){if(!this.restEnabled)return{success:!1,message:"REST disabled, cannot fetchMore"};const t=this.params.size||10,s=this.params.start||0,i=s+e*t;return this.meta&&typeof this.meta.count=="number"&&i>=this.meta.count?{success:!0,message:"No more results",data:{data:[],status:"ok",count:this.meta.count,start:s,size:t}}:(this.params={...this.params,start:i},this.emit("fetch:more",{start:i,pageDelta:e,collection:this}),this.fetch({reset:!1}))}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 r=this.get(s.id);r?t.merge!==!1&&r.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 r=`export-${this.getModelName().toLowerCase()}`,n=this._buildDateRangeSuffix(i),a=`${r}${n}.${e}`,l={json:"application/json",csv:"text/csv"}[e]||"*/*";return i.filename=a,this.rest.download(s,i,{...t,filename:a,headers:{Accept:l}})}_buildDateRangeSuffix(e={}){const t=e.dr_start,s=e.dr_end;if(!t&&!s)return"";const i=a=>a?String(a).replace(/[^\dA-Za-z_-]/g,"-"):"",r=[],n=e.dr_field||"daterange";return r.push(i(n)),t&&r.push(`from-${i(e.dr_start)}`),s&&r.push(`to-${i(e.dr_end)}`),`-${r.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 r of s){let n;r instanceof this.ModelClass?(n=r,n.collection||(n.collection=this)):n=new this.ModelClass(r,{endpoint:this.endpoint,collection:this});const a=this.models.findIndex(o=>o.id===n.id);a!==-1?t.merge!==!1&&this.models[a].set(n.attributes):(this.models.push(n),i.push(n))}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 r of s){let n=-1;if(typeof r=="string"||typeof r=="number"?n=this.models.findIndex(a=>a.id==r):n=this.models.indexOf(r),n!==-1){const a=this.models.splice(n,1)[0];a.collection===this&&(a.collection=null),i.push(a)}}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,r)=>{const n=i.get(s),a=r.get(s);return n<a?-1:n>a?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(de.prototype,Me);class Jt{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}`,r={title:this.getDefaultTitle(t),icon:this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,...s},n=this.createToastElement(i,e,t,r);if(this.container.appendChild(n),typeof bootstrap>"u")throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const a=new bootstrap.Toast(n,{autohide:r.autohide,delay:r.delay});return this.toasts.set(i,{element:n,bootstrap:a,type:t,message:e}),n.addEventListener("hidden.bs.toast",()=>{this.cleanup(i)}),a.show(),{id:i,hide:()=>{try{a.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}`,r={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},n=this.createViewToastElement(i,e,t,r);if(this.container.appendChild(n),typeof bootstrap>"u")throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const a=new bootstrap.Toast(n,{autohide:r.autohide,delay:r.delay});this.toasts.set(i,{element:n,bootstrap:a,type:t,view:e,message:"View toast"}),n.addEventListener("hidden.bs.toast",()=>{this.cleanupView(i)});const o=n.querySelector(".toast-view-body");return o&&e&&e.render(!0,o),a.show(),{id:i,view:e,hide:()=>{try{a.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 r=document.createElement("div");r.id=e,r.className=`toast toast-service-${s}${i.size?` toast-${i.size}`:""}`,r.setAttribute("role","alert"),r.setAttribute("aria-live","assertive"),r.setAttribute("aria-atomic","true");const n=i.title||i.icon?this.createToastHeader(i,s):"",a=this.createToastBody(t,i.icon&&!i.title);return r.innerHTML=`
142
+ `}async onAfterMount(){await super.onAfterMount(),this._writeIframe()}onActionRefresh(){this._writeIframe()}_writeIframe(){const e=this.element?.querySelector(".mojo-html-preview-frame");if(!e)return;const t=e.contentDocument||e.contentWindow?.document;t&&(t.open(),t.write(this.html),t.close())}setHtml(e){this.html=e,this._writeIframe()}}class Q{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=ne,this.collection=t.collection||null,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]:$.getContextData(this.attributes,e)}set(e,t,s={}){const i=JSON.parse(JSON.stringify(this.attributes));let r=!1;if(e!=null){if(typeof e=="object"){for(const[n,a]of Object.entries(e))r=this._setNestedAttribute(n,a)||r;e.id!==void 0&&(this.id=e.id)}else e==="id"?(this.id=t,r=!0):r=this._setNestedAttribute(e,t);if(r&&!s.silent)if(this.emit("change",this,s),typeof e=="string")this.emit(`change:${e}`,t,this);else for(const[n,a]of Object.entries(e)){const o=this._getNestedValue(n);JSON.stringify(this._getNestedValue(n,i))!==JSON.stringify(o)&&this.emit(`change:${n}`,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 r=this._getNestedValue(e);let n=this.attributes[i],a=this[i];for(let l=1;l<s.length-1;l++){const d=s[l];(!n[d]||typeof n[d]!="object")&&(n[d]={}),(!a[d]||typeof a[d]!="object")&&(a[d]={}),n=n[d],a=a[d]}const o=s[s.length-1];return n[o]=t,a[o]=t,JSON.stringify(r)!==JSON.stringify(t)}_getNestedValue(e,t=this.attributes){if(!e.includes("."))return t[e];const s=e.split(".");let i=t;for(const r of s){if(i==null||typeof i!="object")return;i=i[r]}return i}getData(){return this.attributes}getId(){return this.id}async fetch(e={}){let t=e.url;if(!t){const n=e.id||this.getId();if(!n&&this.options.requiresId!==!1)throw new Error("Model: ID is required for fetching");t=this.buildUrl(n)}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(n){if(n.name==="AbortError")return console.info("Model: Request was cancelled"),this;throw n}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 r=await this.fetch({...t,debounceMs:0});s(r)}catch(r){i(r)}},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",r=s?this.buildUrl():this.buildUrl(this.id);this.loading=!0,this.errors={};try{const n=await this.rest[i](r,e,t.params);return n.success?n.data.status?(this.originalAttributes={...this.attributes},this.set(n.data.data,null,t),this.errors={}):this.errors=n.data:this.errors=n.errors||{},n}catch(n){return{success:!1,error:n.message,status:n.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 r of i)if(typeof r=="function"){const n=r(s,this);if(n!==!0){this.errors[e]=n||`${e} is invalid`;break}}else if(typeof r=="object"){if(r.required&&(s==null||s==="")){this.errors[e]=r.message||`${e} is required`;break}if(r.minLength&&s&&s.length<r.minLength){this.errors[e]=r.message||`${e} must be at least ${r.minLength} characters`;break}if(r.maxLength&&s&&s.length>r.maxLength){this.errors[e]=r.message||`${e} must be no more than ${r.maxLength} characters`;break}if(r.pattern&&s&&!r.pattern.test(s)){this.errors[e]=r.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(await Promise.resolve().then(()=>N)).default.alert(e,"Error",{size:"md",class:"text-danger"})}}Object.assign(Q.prototype,Ie);class de{constructor(e={},t=null){if(Array.isArray(e)?(t=e,e=t||{}):t=t||e.data||[],this.ModelClass=e.ModelClass||Q,this.models=[],this.loading=!1,this.errors={},this.meta={},this.rest=ne,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 r=this.buildUrl();this.loading=!0,this.errors={},this.lastFetchTime=s,this.currentRequestKey=t,this.abortController=new AbortController,this.currentRequest=this._performFetch(r,e,this.abortController);try{return await this.currentRequest}catch(n){return n.name==="AbortError"?(console.info("Collection: Request was cancelled"),{success:!1,error:"Request cancelled",status:0}):{success:!1,error:n.message,status:n.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 r=await this.rest.GET(e,i,{signal:s.signal});if(r.success&&r.data.status){const n=this.options.parse?this.parse(r):r.data;t.reset!==!1&&this.options.reset&&this.reset(),this.add(n,{silent:t.silent}),this.errors={},this.emit("fetch:success")}else r.data&&r.data.error?(this.errors=r.data,this.emit("fetch:error",{message:r.data.error,error:r.data})):(this.errors=r.errors||{},this.emit("fetch:error",{error:r.errors}));return r}catch(r){return r.name==="AbortError"?(console.info("Collection: Fetch was cancelled"),{success:!1,error:"Request cancelled",status:0}):(this.errors={fetch:r.message},this.emit("fetch:error",{message:r.message,error:r}),{success:!1,error:r.message,status:r.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,r)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const n=await this.fetch();i(n)}catch(n){r(n)}},s)})):this.fetch():Promise.resolve(this)}async fetchMore({pageDelta:e=1}={}){if(!this.restEnabled)return{success:!1,message:"REST disabled, cannot fetchMore"};const t=this.params.size||10,s=this.params.start||0,i=s+e*t;return this.meta&&typeof this.meta.count=="number"&&i>=this.meta.count?{success:!0,message:"No more results",data:{data:[],status:"ok",count:this.meta.count,start:s,size:t}}:(this.params={...this.params,start:i},this.emit("fetch:more",{start:i,pageDelta:e,collection:this}),this.fetch({reset:!1}))}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 r=this.get(s.id);r?t.merge!==!1&&r.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 r=`export-${this.getModelName().toLowerCase()}`,n=this._buildDateRangeSuffix(i),a=`${r}${n}.${e}`,l={json:"application/json",csv:"text/csv"}[e]||"*/*";return i.filename=a,this.rest.download(s,i,{...t,filename:a,headers:{Accept:l}})}_buildDateRangeSuffix(e={}){const t=e.dr_start,s=e.dr_end;if(!t&&!s)return"";const i=a=>a?String(a).replace(/[^\dA-Za-z_-]/g,"-"):"",r=[],n=e.dr_field||"daterange";return r.push(i(n)),t&&r.push(`from-${i(e.dr_start)}`),s&&r.push(`to-${i(e.dr_end)}`),`-${r.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 r of s){let n;r instanceof this.ModelClass?(n=r,n.collection||(n.collection=this)):n=new this.ModelClass(r,{endpoint:this.endpoint,collection:this});const a=this.models.findIndex(o=>o.id===n.id);a!==-1?t.merge!==!1&&this.models[a].set(n.attributes):(this.models.push(n),i.push(n))}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 r of s){let n=-1;if(typeof r=="string"||typeof r=="number"?n=this.models.findIndex(a=>a.id==r):n=this.models.indexOf(r),n!==-1){const a=this.models.splice(n,1)[0];a.collection===this&&(a.collection=null),i.push(a)}}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,r)=>{const n=i.get(s),a=r.get(s);return n<a?-1:n>a?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(de.prototype,Ie);class Jt{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}`,r={title:this.getDefaultTitle(t),icon:this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,...s},n=this.createToastElement(i,e,t,r);if(this.container.appendChild(n),typeof bootstrap>"u")throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const a=new bootstrap.Toast(n,{autohide:r.autohide,delay:r.delay});return this.toasts.set(i,{element:n,bootstrap:a,type:t,message:e}),n.addEventListener("hidden.bs.toast",()=>{this.cleanup(i)}),a.show(),{id:i,hide:()=>{try{a.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}`,r={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},n=this.createViewToastElement(i,e,t,r);if(this.container.appendChild(n),typeof bootstrap>"u")throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const a=new bootstrap.Toast(n,{autohide:r.autohide,delay:r.delay});this.toasts.set(i,{element:n,bootstrap:a,type:t,view:e,message:"View toast"}),n.addEventListener("hidden.bs.toast",()=>{this.cleanupView(i)});const o=n.querySelector(".toast-view-body");return o&&e&&e.render(!0,o),a.show(),{id:i,view:e,hide:()=>{try{a.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 r=document.createElement("div");r.id=e,r.className=`toast toast-service-${s}${i.size?` toast-${i.size}`:""}`,r.setAttribute("role","alert"),r.setAttribute("aria-live","assertive"),r.setAttribute("aria-atomic","true");const n=i.title||i.icon?this.createToastHeader(i,s):"",a=this.createToastBody(t,i.icon&&!i.title);return r.innerHTML=`
143
143
  ${n}
144
144
  ${a}
145
145
  `,r}createViewToastElement(e,t,s,i){const r=document.createElement("div");r.id=e,r.className=`toast toast-service-${s}${i.size?` toast-${i.size}`:""}`,r.setAttribute("role","alert"),r.setAttribute("aria-live","assertive"),r.setAttribute("aria-atomic","true");const n=i.title||i.icon?this.createToastHeader(i,s):"",a=this.createViewToastBody();return r.innerHTML=`
@@ -199,7 +199,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
199
199
  </small>
200
200
  </div>
201
201
  </div>
202
- `}updateProgress(e){this.cancelled||this.completed||(this.progress=e.progress,this.percentage=e.percentage,this.loaded=e.loaded,this.total=e.total||this.filesize,this.loadedFormatted=V.pipe(this.loaded,"filesize"),this.totalFormatted=V.pipe(this.total,"filesize"),this.percentage<100?this.status=`Uploading... ${this.percentage}%`:this.status="Finalizing upload...",this.render())}markCompleted(e="Upload completed!"){this.completed=!0,this.progress=1,this.percentage=100,this.status=e,this.render()}markFailed(e="Upload failed"){this.status=e,this.render()}markCancelled(){this.cancelled=!0,this.status="Upload cancelled",this.render()}async onActionCancel(e,t,s){if(!(this.cancelled||this.completed)&&(s.disabled=!0,this.markCancelled(),this.emit("cancel"),typeof this.onCancel=="function"))try{await this.onCancel()}catch(i){console.error("Error in cancel callback:",i)}}setFilename(e){this.filename=e,this.render()}setFilesize(e){this.filesize=e,this.filesizeFormatted=V.pipe(e,"filesize"),this.total=e,this.totalFormatted=this.filesizeFormatted,this.render()}getPercentage(){return this.percentage}isCompleted(){return this.completed}isCancelled(){return this.cancelled}getStats(){return{filename:this.filename,filesize:this.filesize,progress:this.progress,percentage:this.percentage,loaded:this.loaded,total:this.total,cancelled:this.cancelled,completed:this.completed,status:this.status}}}class Zt{constructor(e,t={}){if(this.fileModel=e,this.options={file:null,name:null,group:null,description:null,onProgress:null,onComplete:null,onError:null,showToast:!0,...t},!this.options.file||!(this.options.file instanceof File))throw new Error("FileUpload requires a valid File object");this.cancelled=!1,this.uploadRequest=null,this.progressToast=null,this.progressView=null,this.toastService=null,this.options.showToast&&(this.toastService=new Jt),this.promise=this._startUpload()}async _startUpload(){try{this.options.showToast&&this._showProgressToast();let e;try{e=await this._initiateUpload()}catch(i){throw new Error(`Failed to initiate upload: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");if(!e||!e.upload_url)throw new Error("Invalid upload response: missing upload URL");let t;if(typeof e.upload_url=="string")t={url:e.upload_url,method:"PUT",fields:null,headers:{}};else if(e.upload_url&&typeof e.upload_url=="object"&&e.upload_url.upload_url)t={url:e.upload_url.upload_url,method:e.upload_url.method||"POST",fields:e.upload_url.fields||null,headers:e.upload_url.headers||{}};else throw new Error(`Invalid upload response: unrecognised upload_url format. Server returned: ${JSON.stringify(e.upload_url)}`);let s;try{s=await this._performUpload(t)}catch(i){throw new Error(`File upload failed: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");try{await this._completeUpload()}catch(i){console.warn("Failed to mark upload as completed:",i)}return this._onComplete(this.fileModel),this.fileModel}catch(e){throw e.message!=="Upload cancelled"&&this._onError(e),e}}async _initiateUpload(){try{const e={filename:this.options.name||this.options.file.name,file_size:this.options.file.size,content_type:this.options.file.type};this.options.group&&(e.group=this.options.group),this.options.description&&(e.description=this.options.description);const t=await this.fileModel.rest.POST("/api/fileman/upload/initiate",e);if(!t)throw new Error("No response from upload initiation API");if(!t.data)throw new Error("Upload initiation response missing data");if(!t.data.status){const s=t.data.error||"Upload initiation failed";throw new Error(s)}if(!t.data.data)throw new Error("Upload initiation response missing data payload");return t.data.data.id&&this.fileModel.set("id",t.data.data.id),t.data.data}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload initiation. Please check your connection."):e}}async _performUpload(e){return new Promise((t,s)=>{if(!(this.options.file instanceof File)){s(new Error("Only single File objects are supported"));return}const{url:i,method:r,fields:n,headers:a}=e,o=r==="POST"&&n!==null,l=new XMLHttpRequest;this.uploadRequest=l,l.upload.onprogress=u=>{this.cancelled||this._onProgress({progress:u.loaded/u.total,loaded:u.loaded,total:u.total,percentage:Math.round(u.loaded/u.total*100)})},l.onload=()=>{l.status>=200&&l.status<300?t({data:l.response,status:l.status,statusText:l.statusText,xhr:l}):s(new Error(`Upload failed: ${l.status} ${l.statusText}`))},l.onerror=()=>s(new Error("Upload failed: Network error")),l.ontimeout=()=>s(new Error("Upload timed out — file may be too large or connection too slow")),l.onabort=()=>s(new Error("Upload cancelled"));let d=i;i.startsWith("/")&&!i.startsWith("/api/")&&(d="/api"+i);const h=this.fileModel.rest.buildUrl(d);if(l.open(r,h),l.timeout=3e4,o){for(const[m,p]of Object.entries(a||{}))m.toLowerCase()!=="content-type"&&l.setRequestHeader(m,p);const u=new FormData;for(const[m,p]of Object.entries(n))u.append(m,p);u.append("file",this.options.file),l.send(u)}else{l.setRequestHeader("Content-Type",this.options.file.type);for(const[u,m]of Object.entries(a||{}))u.toLowerCase()!=="content-type"&&l.setRequestHeader(u,m);l.send(this.options.file)}})}async _completeUpload(){try{const e=await this.fileModel.save({action:"mark_as_completed"});if(!e)throw new Error("No response from upload completion API");if(e.data&&!e.data.status){const t=e.data.error||"Failed to mark upload as completed";throw new Error(t)}return e}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload completion. The file may have uploaded successfully."):e}}_onProgress(e){this.progressToast&&this.progressToast.updateProgress&&this.progressToast.updateProgress(e),typeof this.options.onProgress=="function"&&this.options.onProgress(e)}_onComplete(e){this.progressView&&this.progressView.markCompleted("Upload completed successfully!"),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast:",t)}},2e3),typeof this.options.onComplete=="function"&&this.options.onComplete(e)}_onError(e){if(this.progressToast)try{this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast on error:",t)}this.toastService&&this.toastService.error(`Upload failed: ${e.message}`),typeof this.options.onError=="function"&&this.options.onError(e)}_showProgressToast(){this.progressView=new Le({filename:this.options.name||this.options.file.name,filesize:this.options.file.size,showCancel:!0,onCancel:()=>this.cancel()}),this.progressToast=this.toastService.showView(this.progressView,"info",{title:"File Upload",autohide:!1,dismissible:!1})}cancel(){return this.cancelled?!1:(this.cancelled=!0,this.uploadRequest&&typeof this.uploadRequest.abort=="function"&&this.uploadRequest.abort(),this.progressView&&this.progressView.markCancelled(),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(e){console.warn("Error hiding progress toast on cancel:",e)}},1500),!0)}isCancelled(){return this.cancelled}then(e,t){return this.promise.then(e,t)}catch(e){return this.promise.catch(e)}finally(e){return this.promise.finally(e)}getStats(){return{filename:this.options.file.name,size:this.options.file.size,type:this.options.file.type,cancelled:this.cancelled,group:this.options.group,description:this.options.description}}}class G extends Q{constructor(e={}){super(e,{endpoint:"/api/group"})}}class nt extends de{constructor(e={}){super({ModelClass:G,endpoint:"/api/group",size:10,...e})}}const at={org:"Organization",platform:"Platform",division:"Division",department:"Department",team:"Team",merchant:"Merchant",partner:"Partner",client:"Client",iso:"ISO",sales:"Sales",reseller:"Reseller",location:"Location",region:"Region",route:"Route",project:"Project",inventory:"Inventory",test:"Testing",misc:"Miscellaneous",qa:"Quality Assurance"},ot=Object.entries(at).map(([c,e])=>({value:c,label:e})),lt=[{value:"America/New_York",label:"Eastern Time (ET)"},{value:"America/Chicago",label:"Central Time (CT)"},{value:"America/Denver",label:"Mountain Time (MT)"},{value:"America/Los_Angeles",label:"Pacific Time (PT)"},{value:"America/Anchorage",label:"Alaska Time (AKT)"},{value:"Pacific/Honolulu",label:"Hawaii Time (HT)"},{value:"UTC",label:"UTC"},{value:"Europe/London",label:"London (GMT/BST)"},{value:"Europe/Paris",label:"Paris (CET/CEST)"},{value:"Europe/Berlin",label:"Berlin (CET/CEST)"},{value:"Asia/Tokyo",label:"Tokyo (JST)"},{value:"Asia/Shanghai",label:"Shanghai (CST)"},{value:"Australia/Sydney",label:"Sydney (AEST)"}],ct=Array.from({length:24},(c,e)=>{let t;return e===0?t="Midnight":e===12?t="Noon":t=`${e%12===0?12:e%12} ${e<12?"AM":"PM"}`,{value:e,label:t}});function dt(){return{avatar:{type:"image",name:"avatar",size:"lg",imageSize:{width:200,height:200},placeholder:"Upload your avatar",help:"Square images work best",columns:12},name:{name:"name",type:"text",label:"Group Name",required:!0,placeholder:"Enter group name",columns:12},kind:{name:"kind",type:"combo",label:"Group Kind",required:!0,placeholder:"Type or select kind...",options:ot,columns:12},parent:{type:"collection",name:"parent",label:"Parent Group",Collection:nt,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300,columns:12},isActive:{name:"is_active",type:"switch",label:"Is Active",columns:12},uuid:{name:"uuid",type:"text",label:"UUID",placeholder:"32-character hex string",columns:12},shortName:{name:"metadata.short_name",type:"text",label:"Short Name",placeholder:"Enter short name",columns:6},domain:{name:"metadata.domain",type:"text",label:"Default Domain",placeholder:"Enter domain",columns:6},authDomain:{name:"metadata.auth_domain",type:"text",label:"Auth Domain",placeholder:"auth.example.com",help:"Used for white-label login pages.",columns:6},portal:{name:"metadata.portal",type:"text",label:"Default Portal",placeholder:"https://…",columns:6},timezone:{name:"metadata.timezone",type:"select",label:"Timezone",options:lt,columns:6},eodHour:{name:"metadata.eod_hour",type:"select",label:"End of Day Hour",options:ct,columns:6},emailTemplate:{name:"metadata.email_template",type:"text",label:"Email Template (Prefix)",placeholder:"Enter template prefix",columns:12}}}const Pe={get create(){const c=dt();return{title:"Create Group",fields:[c.name,c.kind,c.parent]}},get edit(){return{...this.detailed,title:"Edit Group"}},get detailed(){const c=dt();return{title:"Group Details",fields:[{type:"tabset",name:"group-detail",tabs:[{label:"Profile",fields:[c.name,c.kind,c.parent,c.isActive]},{label:"Identity",fields:[c.uuid,c.shortName,c.domain,c.authDomain,c.portal]},{label:"Localization",fields:[c.timezone,c.eodHour]},{label:"Branding",fields:[c.emailTemplate]},{label:"Avatar",fields:[c.avatar]}]}]}}};G.EDIT_FORM=Pe.edit,G.ADD_FORM=Pe.create,G.CREATE_FORM=Pe.create,G.FORM_DIALOG_CONFIG={size:"lg"},G.GroupKindOptions=ot,G.GroupKinds=at,G.TimezoneOptions=lt,G.EodHourOptions=ct;class w extends Q{constructor(e={}){super(e,{endpoint:"/api/user"})}hasPermission(e){if(this.get("is_superuser"))return!0;if(Array.isArray(e))return e.some(i=>this.hasPermission(i));const t=e.startsWith("sys."),s=t?e.substring(4):e;return!!(this._hasPermission(s)||this._hasPermission("admin")||!t&&this.member&&this.member.hasPermission(e))}_hasPermission(e){const t=this.get("permissions");if(!t)return!1;if(t[e]==!0)return!0;const s=w.GRANULAR_TO_CATEGORY[e];return!!(s&&t[s]==!0)}hasPerm(e){return this.hasPermission(e)}}w.CATEGORY_PERMISSIONS=[{name:"view_admin",label:"Admin Panel",tooltip:"Access the admin panel, Mojo, and system tools"},{name:"security",label:"Security",tooltip:"Incidents, events, rules, tickets, firewall, bouncer, GeoIP, system logs"},{name:"users",label:"Users",tooltip:"User records, passkeys, TOTP, API keys, OAuth, devices, locations"},{name:"groups",label:"Groups",tooltip:"Groups, members, group API keys, settings"},{name:"comms",label:"Communications",tooltip:"Email, phone, SMS, push notifications, chat, notifications"},{name:"jobs",label:"Jobs",tooltip:"Jobs, job events, job logs, runners, queue control, system stats"},{name:"metrics",label:"Metrics",tooltip:"Metrics recording, fetching, categories, values, permissions"},{name:"files",label:"Files",tooltip:"File managers, files, renditions, vault files, vault data, S3 buckets"},{name:"assistant",label:"Mojo",tooltip:"Access to Mojo"}],w.GRANULAR_PERMISSION_TABS=[{label:"Account",permissions:[{name:"view_users",label:"View Users"},{name:"manage_users",label:"Manage Users"},{name:"view_groups",label:"View Groups"},{name:"manage_groups",label:"Manage Groups"},{name:"manage_group",label:"Manage Own Group"},{name:"view_members",label:"View Members"},{name:"manage_settings",label:"Manage Settings"}]},{label:"Communication",permissions:[{name:"manage_chat",label:"Manage Chat"},{name:"manage_aws",label:"Manage Email (AWS)"},{name:"view_notifications",label:"View Notifications"},{name:"manage_notifications",label:"Manage Notifications"},{name:"send_notifications",label:"Send Notifications"},{name:"view_devices",label:"View Push Devices"},{name:"manage_devices",label:"Manage Push Devices"},{name:"manage_push_config",label:"Push Config"},{name:"view_phone_numbers",label:"View Phone Numbers"},{name:"manage_phone_numbers",label:"Manage Phone Numbers"},{name:"manage_phone_config",label:"Phone Config"},{name:"view_sms",label:"View SMS"},{name:"manage_sms",label:"Manage SMS"},{name:"send_sms",label:"Send SMS"}]},{label:"Platform",permissions:[{name:"view_security",label:"View Security"},{name:"manage_security",label:"Manage Security"},{name:"admin",label:"Log Admin"},{name:"view_logs",label:"View Logs"},{name:"manage_logs",label:"Manage Logs"},{name:"view_jobs",label:"View Jobs"},{name:"manage_jobs",label:"Manage Jobs"},{name:"view_metrics",label:"View Metrics"},{name:"manage_metrics",label:"Manage Metrics"},{name:"write_metrics",label:"Write Metrics"},{name:"view_fileman",label:"View File Managers"},{name:"manage_files",label:"Manage Files"},{name:"view_vault",label:"View Vault"},{name:"manage_vault",label:"Manage Vault"},{name:"manage_docit",label:"Manage Docs"},{name:"manage_shortlinks",label:"Manage Shortlinks"}]}],w.CATEGORY_GRANULAR_MAP={security:["view_security","manage_security"],users:["view_users","manage_users","view_members"],groups:["view_groups","manage_groups","manage_group"],comms:["manage_chat","manage_aws","view_notifications","manage_notifications","send_notifications","view_devices","manage_devices","manage_push_config","view_phone_numbers","manage_phone_numbers","manage_phone_config","view_sms","manage_sms","send_sms"],jobs:["view_jobs","manage_jobs"],metrics:["view_metrics","manage_metrics","write_metrics"],files:["view_fileman","manage_files","view_vault","manage_vault"]},w.APP_CATEGORY_PERMISSIONS=[],w.APP_GRANULAR_PERMISSIONS=[],w._permSwitch=function(c){return{name:`permissions.${c.name}`,type:"switch",label:c.label,columns:6,...c.tooltip?{tooltip:c.tooltip}:{}}},w.PERMISSIONS=[],w.PERMISSION_FIELDS=[],w.CATEGORY_PERMISSION_FIELDS=[],w.GRANULAR_PERMISSION_FIELDS=[],w.SYSTEM_PERMISSION_FIELDS=[],w.APP_PERMISSION_FIELDS=[],w.GRANULAR_TO_CATEGORY={},w.rebuildPermissions=function(){const c=w._permSwitch;w.PERMISSIONS.length=0,w.PERMISSIONS.push(...w.CATEGORY_PERMISSIONS,...w.GRANULAR_PERMISSION_TABS.flatMap(i=>i.permissions),...w.APP_CATEGORY_PERMISSIONS,...w.APP_GRANULAR_PERMISSIONS),w.PERMISSION_FIELDS.length=0,w.PERMISSION_FIELDS.push(...w.PERMISSIONS.map(c));const e=[{label:"System",fields:w.CATEGORY_PERMISSIONS.map(c)}];w.APP_CATEGORY_PERMISSIONS.length>0&&e.push({label:"App",fields:w.APP_CATEGORY_PERMISSIONS.map(c)}),w.CATEGORY_PERMISSION_FIELDS.length=0,w.CATEGORY_PERMISSION_FIELDS.push({type:"tabset",tabs:e});const t=w.GRANULAR_PERMISSION_TABS.map(i=>({label:i.label,fields:i.permissions.map(c)}));w.APP_GRANULAR_PERMISSIONS.length>0&&t.push({label:"App",fields:w.APP_GRANULAR_PERMISSIONS.map(c)}),w.GRANULAR_PERMISSION_FIELDS.length=0,w.GRANULAR_PERMISSION_FIELDS.push({type:"tabset",tabs:t}),w.SYSTEM_PERMISSION_FIELDS.length=0,w.SYSTEM_PERMISSION_FIELDS.push({type:"tabset",tabs:[{label:"System",fields:w.CATEGORY_PERMISSIONS.map(c)},...w.GRANULAR_PERMISSION_TABS.map(i=>({label:i.label,fields:i.permissions.map(c)}))]}),w.APP_PERMISSION_FIELDS.length=0;const s=[];w.APP_CATEGORY_PERMISSIONS.length>0&&s.push({label:"Categories",fields:w.APP_CATEGORY_PERMISSIONS.map(c)}),w.APP_GRANULAR_PERMISSIONS.length>0&&s.push({label:"Permissions",fields:w.APP_GRANULAR_PERMISSIONS.map(c)}),s.length>0&&w.APP_PERMISSION_FIELDS.push({type:"tabset",tabs:s});for(const i of Object.keys(w.GRANULAR_TO_CATEGORY))delete w.GRANULAR_TO_CATEGORY[i];for(const[i,r]of Object.entries(w.CATEGORY_GRANULAR_MAP))for(const n of r)w.GRANULAR_TO_CATEGORY[n]=i},w.registerCategoryMap=function(c){if(!c)return;let e=!1;for(const[t,s]of Object.entries(c)){if(!Array.isArray(s))continue;const i=w.CATEGORY_GRANULAR_MAP[t]||[];w.CATEGORY_GRANULAR_MAP[t]=Array.from(new Set([...i,...s])),e=!0}e&&w.rebuildPermissions()},w.registerPermissions=function(c){if(c){if(Array.isArray(c.categories)&&w.APP_CATEGORY_PERMISSIONS.push(...c.categories),Array.isArray(c.granularPermissions)&&w.APP_GRANULAR_PERMISSIONS.push(...c.granularPermissions),Array.isArray(c.granularTabs)&&w.GRANULAR_PERMISSION_TABS.push(...c.granularTabs),c.categoryGranularMap)for(const[e,t]of Object.entries(c.categoryGranularMap)){if(!Array.isArray(t))continue;const s=w.CATEGORY_GRANULAR_MAP[e]||[];w.CATEGORY_GRANULAR_MAP[e]=Array.from(new Set([...s,...t]))}w.rebuildPermissions()}},w.rebuildPermissions();const ht={create:{title:"Create User",fields:[{name:"email",type:"text",label:"Email",required:!0},{name:"phone_number",type:"text",label:"Phone number",columns:12},{name:"display_name",type:"text",label:"Display Name"}]},edit:{title:"Edit User",fields:[{name:"email",type:"email",label:"Email",columns:12},{name:"display_name",type:"text",label:"Display Name",columns:12},{name:"phone_number",type:"text",label:"Phone number",columns:12},{type:"collection",name:"org",label:"Organization",Collection:nt,labelField:"name",valueField:"id",columns:12}]},permissions:{fields:w.PERMISSION_FIELDS}},Kt={detailed:{title:"Detailed User Information",columns:2,showEmptyValues:!0,emptyValueText:"Not set",fields:[{name:"id",label:"User ID",type:"number",colSize:3},{name:"display_name",label:"Display Name",type:"text",format:'capitalize|default("Unnamed User")',colSize:9},{name:"username",label:"Username",type:"text",format:"lowercase",colSize:6},{name:"email",label:"Email Address",type:"email",colSize:6},{name:"phone_number",label:"Phone Number",type:"phone",format:'phone|default("Not provided")',colSize:6},{name:"is_active",label:"Account Status",type:"boolean",colSize:6},{name:"last_login",label:"Last Login",type:"datetime",format:"relative",colSize:6},{name:"last_activity",label:"Last Activity",type:"datetime",format:"relative",colSize:6},{name:"avatar.url",label:"Avatar",type:"url",colSize:12},{name:"permissions",label:"User Permissions",type:"dataview",dataViewColumns:2,showEmptyValues:!1},{name:"metadata",label:"User Metadata",type:"dataview",dataViewColumns:1},{name:"avatar",label:"Avatar Details",type:"dataview",dataViewColumns:1}]}};w.DATA_VIEW=Kt.detailed,w.EDIT_FORM=ht.edit,w.ADD_FORM=ht.create;class ut extends Q{constructor(e={}){super(e,{endpoint:"/api/fileman/manager"})}}const mt={create:{title:"Add Storage Backend",fields:[{name:"name",type:"text",label:"Display Name",placeholder:"Enter Display Name",cols:12},{name:"use",type:"text",label:"Use",placeholder:"Enter User or Leave Blank",cols:12},{name:"backend_url",type:"text",label:"Backend URL",required:!0,value:"s3://BUCKET_NAME/OPTION_FOLDER",placeholder:"s3://bucket_name/optional folder",help:"Format: service://path. Valid services: s3",cols:12},{name:"aws_region",type:"select",label:"AWS Region (optional)",value:"us-east-1",options:[{value:"",text:"System Default"},{value:"us-east-1",text:"US East (N. Virginia)"},{value:"us-east-2",text:"US East (Ohio)"},{value:"us-west-1",text:"US West (N. California)"},{value:"us-west-2",text:"US West (Oregon)"},{value:"ca-central-1",text:"Canada (Central)"},{value:"eu-west-1",text:"Europe (Ireland)"},{value:"eu-west-2",text:"Europe (London)"},{value:"eu-west-3",text:"Europe (Paris)"},{value:"eu-central-1",text:"Europe (Frankfurt)"},{value:"eu-north-1",text:"Europe (Stockholm)"},{value:"eu-south-1",text:"Europe (Milan)"},{value:"ap-southeast-2",text:"Asia Pacific (Sydney)"}],columns:12,help:"Optional. Defaults to project AWS_REGION if omitted."},{name:"aws_key",type:"text",label:"AWS Key (optional)",placeholder:"enter your AWS Key with S3 permissions",columns:12,help:"Optional, AWS Key with S3 permissions"},{name:"aws_secret",type:"text",label:"AWS Secret (optional)",placeholder:"enter your AWS Secret with S3 permissions",columns:12,help:"Optional, AWS Secret with S3 permissions"},{name:"is_default",type:"switch",label:"Is Default",cols:6},{name:"is_active",type:"switch",label:"Is Active",default:!0,cols:6}]},edit:{title:"Edit Storage Backend",fields:[{name:"name",type:"text",label:"Display Name",placeholder:"Enter Display Name",cols:12},{name:"use",type:"text",label:"Use",placeholder:"Enter User or Leave Blank",cols:12},{name:"backend_url",type:"text",label:"Backend URL",required:!0,placeholder:"s3://bucket_name/optional folder",help:"Format: service://path. Valid services: s3",cols:12},{name:"allowed_origins",type:"text",label:"Domains Who Can Upload",cols:12},{name:"is_default",type:"switch",label:"Is Default",cols:6},{name:"is_active",type:"switch",label:"Is Active",default:!0,cols:6},{name:"is_public",type:"switch",label:"Is Public",default:!0,cols:6}]}};let pt=class extends Q{constructor(e={}){super(e,{endpoint:"/api/fileman/file"})}isImage(){return this.get("category")==="image"}getCategory(){return this.get("category")||this._inferCategoryFromContentType()}_inferCategoryFromContentType(){const e=(this.get("content_type")||"").toLowerCase();return e?e.startsWith("image/")?"image":e.startsWith("video/")?"video":e.startsWith("audio/")?"audio":e==="application/pdf"?"pdf":e.startsWith("text/")||e==="application/msword"||e.startsWith("application/vnd.openxmlformats-officedocument.wordprocessingml")||e==="application/vnd.oasis.opendocument.text"?"document":e==="application/vnd.ms-excel"||e.startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml")||e==="application/vnd.oasis.opendocument.spreadsheet"?"spreadsheet":e==="application/vnd.ms-powerpoint"||e.startsWith("application/vnd.openxmlformats-officedocument.presentationml")||e==="application/vnd.oasis.opendocument.presentation"?"presentation":e==="application/zip"||e==="application/x-rar-compressed"||e==="application/x-7z-compressed"||e==="application/x-tar"||e==="application/gzip"?"archive":"other":"other"}hasRenditions(){const e=this.get("renditions");return!!(e&&Object.keys(e).length)}isUploadPending(){const e=this.get("upload_status");return!!(e&&e!=="completed"&&e!=="failed")}regenerateRenditions(e){const t=this.id||this.get("id");if(!t)return Promise.reject(new Error("Cannot regenerate renditions on an unsaved file"));const s=Array.isArray(e)&&e.length?{regenerate_renditions:e}:{regenerate_renditions:!0};return this.rest.POST(`${this.endpoint}/${t}`,s)}share(e=!0){const t=this.id||this.get("id");return t?this.rest.POST(`${this.endpoint}/${t}`,{share:e}):Promise.reject(new Error("Cannot share an unsaved file"))}getRenditions(){const e=this.get("renditions");return e?Object.values(e):[]}getBestImageRendition(){const e=this.getRenditions().filter(t=>t&&typeof t.content_type=="string"&&t.content_type.startsWith("image/"));return e.length?e.reduce((t,s)=>{const i=(parseInt(t.width)||0)*(parseInt(t.height)||0);return(parseInt(s.width)||0)*(parseInt(s.height)||0)>i?s:t}):null}getThumbnailUrl(){const e=this.get("renditions")||{};if(e.thumbnail&&e.thumbnail.url)return e.thumbnail.url;const t=this.getBestImageRendition();return t?t.url:null}upload(e={}){return new Zt(this,e)}};const Qt={edit:{title:"Edit File Backend",fields:[]}};ut.ADD_FORM=mt.create,ut.EDIT_FORM=mt.edit,pt.EDIT_FORM=Qt.edit;class v{static _renderAndAwait(e,{buttons:t=null,rejectOnDismiss:s=!1,onAction:i=null,cleanup:r=null}={}){const n=x.getMountTarget();return new Promise((a,o)=>{let l=!1;const d=u=>{l||(l=!0,a(u))},h=u=>{l||(l=!0,o(u))};(async()=>{try{await e.render(!0,n)}catch(u){h(u);return}t&&t.length>0&&e.element&&e.element.querySelectorAll(".modal-footer button").forEach((m,p)=>{const f=t[p];f&&m.addEventListener("click",async g=>{if(l)return;const b=f.value!==void 0?f.value:f.action??p;if(typeof f.handler=="function"){try{const y=await f.handler({dialog:e,button:f,index:p,event:g});if(y===null||y===!1)return;const C=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(C)}catch(y){console.error("Modal button handler error:",y)}return}if(typeof i=="function"&&f.action){try{const y=await i(f.action,{dialog:e,button:f,index:p,event:g});if(y===null||y===!1)return;const C=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(C)}catch(y){console.error("Modal onAction error:",y)}return}f.dismiss||e.hide(),d(b)})}),e.on("hidden",()=>{l||(s?h(new Error("Dialog dismissed")):d(null)),setTimeout(async()=>{try{typeof r=="function"&&await r(e)}catch(u){console.error("Modal cleanup error:",u)}try{await e.destroy()}catch(u){console.error("Modal destroy error:",u)}e.element?.parentNode&&e.element.parentNode.removeChild(e.element)},100)}),e.show()})()})}static async dialog(e={}){if(typeof e=="string"){const p=arguments[0],f=arguments[1]||"Alert";e={...arguments[2]||{},body:p,title:f}}const{title:t="Dialog",content:s,body:i,view:r,message:n,size:a="md",centered:o=!0,buttons:l=[{text:"OK",class:"btn-primary",value:!0}],rejectOnDismiss:d=!1,...h}=e,u=i??r??n??s??"",m=new x({title:t,body:u,size:a,centered:o,buttons:l,...h});return v._renderAndAwait(m,{buttons:l,rejectOnDismiss:d})}static async drawer(e={}){const{eyebrow:t,title:s,meta:i=[],view:r,body:n,size:a="lg",...o}=e,l=i.length?`
202
+ `}updateProgress(e){this.cancelled||this.completed||(this.progress=e.progress,this.percentage=e.percentage,this.loaded=e.loaded,this.total=e.total||this.filesize,this.loadedFormatted=V.pipe(this.loaded,"filesize"),this.totalFormatted=V.pipe(this.total,"filesize"),this.percentage<100?this.status=`Uploading... ${this.percentage}%`:this.status="Finalizing upload...",this.render())}markCompleted(e="Upload completed!"){this.completed=!0,this.progress=1,this.percentage=100,this.status=e,this.render()}markFailed(e="Upload failed"){this.status=e,this.render()}markCancelled(){this.cancelled=!0,this.status="Upload cancelled",this.render()}async onActionCancel(e,t,s){if(!(this.cancelled||this.completed)&&(s.disabled=!0,this.markCancelled(),this.emit("cancel"),typeof this.onCancel=="function"))try{await this.onCancel()}catch(i){console.error("Error in cancel callback:",i)}}setFilename(e){this.filename=e,this.render()}setFilesize(e){this.filesize=e,this.filesizeFormatted=V.pipe(e,"filesize"),this.total=e,this.totalFormatted=this.filesizeFormatted,this.render()}getPercentage(){return this.percentage}isCompleted(){return this.completed}isCancelled(){return this.cancelled}getStats(){return{filename:this.filename,filesize:this.filesize,progress:this.progress,percentage:this.percentage,loaded:this.loaded,total:this.total,cancelled:this.cancelled,completed:this.completed,status:this.status}}}class Zt{constructor(e,t={}){if(this.fileModel=e,this.options={file:null,name:null,group:null,description:null,onProgress:null,onComplete:null,onError:null,showToast:!0,...t},!this.options.file||!(this.options.file instanceof File))throw new Error("FileUpload requires a valid File object");this.cancelled=!1,this.uploadRequest=null,this.progressToast=null,this.progressView=null,this.toastService=null,this.options.showToast&&(this.toastService=new Jt),this.promise=this._startUpload()}async _startUpload(){try{this.options.showToast&&this._showProgressToast();let e;try{e=await this._initiateUpload()}catch(i){throw new Error(`Failed to initiate upload: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");if(!e||!e.upload_url)throw new Error("Invalid upload response: missing upload URL");let t;if(typeof e.upload_url=="string")t={url:e.upload_url,method:"PUT",fields:null,headers:{}};else if(e.upload_url&&typeof e.upload_url=="object"&&e.upload_url.upload_url)t={url:e.upload_url.upload_url,method:e.upload_url.method||"POST",fields:e.upload_url.fields||null,headers:e.upload_url.headers||{}};else throw new Error(`Invalid upload response: unrecognised upload_url format. Server returned: ${JSON.stringify(e.upload_url)}`);let s;try{s=await this._performUpload(t)}catch(i){throw new Error(`File upload failed: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");try{await this._completeUpload()}catch(i){console.warn("Failed to mark upload as completed:",i)}return this._onComplete(this.fileModel),this.fileModel}catch(e){throw e.message!=="Upload cancelled"&&this._onError(e),e}}async _initiateUpload(){try{const e={filename:this.options.name||this.options.file.name,file_size:this.options.file.size,content_type:this.options.file.type};this.options.group&&(e.group=this.options.group),this.options.description&&(e.description=this.options.description);const t=await this.fileModel.rest.POST("/api/fileman/upload/initiate",e);if(!t)throw new Error("No response from upload initiation API");if(!t.data)throw new Error("Upload initiation response missing data");if(!t.data.status){const s=t.data.error||"Upload initiation failed";throw new Error(s)}if(!t.data.data)throw new Error("Upload initiation response missing data payload");return t.data.data.id&&this.fileModel.set("id",t.data.data.id),t.data.data}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload initiation. Please check your connection."):e}}async _performUpload(e){return new Promise((t,s)=>{if(!(this.options.file instanceof File)){s(new Error("Only single File objects are supported"));return}const{url:i,method:r,fields:n,headers:a}=e,o=r==="POST"&&n!==null,l=new XMLHttpRequest;this.uploadRequest=l,l.upload.onprogress=u=>{this.cancelled||this._onProgress({progress:u.loaded/u.total,loaded:u.loaded,total:u.total,percentage:Math.round(u.loaded/u.total*100)})},l.onload=()=>{l.status>=200&&l.status<300?t({data:l.response,status:l.status,statusText:l.statusText,xhr:l}):s(new Error(`Upload failed: ${l.status} ${l.statusText}`))},l.onerror=()=>s(new Error("Upload failed: Network error")),l.ontimeout=()=>s(new Error("Upload timed out — file may be too large or connection too slow")),l.onabort=()=>s(new Error("Upload cancelled"));let d=i;i.startsWith("/")&&!i.startsWith("/api/")&&(d="/api"+i);const h=this.fileModel.rest.buildUrl(d);if(l.open(r,h),l.timeout=3e4,o){for(const[m,p]of Object.entries(a||{}))m.toLowerCase()!=="content-type"&&l.setRequestHeader(m,p);const u=new FormData;for(const[m,p]of Object.entries(n))u.append(m,p);u.append("file",this.options.file),l.send(u)}else{l.setRequestHeader("Content-Type",this.options.file.type);for(const[u,m]of Object.entries(a||{}))u.toLowerCase()!=="content-type"&&l.setRequestHeader(u,m);l.send(this.options.file)}})}async _completeUpload(){try{const e=await this.fileModel.save({action:"mark_as_completed"});if(!e)throw new Error("No response from upload completion API");if(e.data&&!e.data.status){const t=e.data.error||"Failed to mark upload as completed";throw new Error(t)}return e}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload completion. The file may have uploaded successfully."):e}}_onProgress(e){this.progressToast&&this.progressToast.updateProgress&&this.progressToast.updateProgress(e),typeof this.options.onProgress=="function"&&this.options.onProgress(e)}_onComplete(e){this.progressView&&this.progressView.markCompleted("Upload completed successfully!"),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast:",t)}},2e3),typeof this.options.onComplete=="function"&&this.options.onComplete(e)}_onError(e){if(this.progressToast)try{this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast on error:",t)}this.toastService&&this.toastService.error(`Upload failed: ${e.message}`),typeof this.options.onError=="function"&&this.options.onError(e)}_showProgressToast(){this.progressView=new Le({filename:this.options.name||this.options.file.name,filesize:this.options.file.size,showCancel:!0,onCancel:()=>this.cancel()}),this.progressToast=this.toastService.showView(this.progressView,"info",{title:"File Upload",autohide:!1,dismissible:!1})}cancel(){return this.cancelled?!1:(this.cancelled=!0,this.uploadRequest&&typeof this.uploadRequest.abort=="function"&&this.uploadRequest.abort(),this.progressView&&this.progressView.markCancelled(),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(e){console.warn("Error hiding progress toast on cancel:",e)}},1500),!0)}isCancelled(){return this.cancelled}then(e,t){return this.promise.then(e,t)}catch(e){return this.promise.catch(e)}finally(e){return this.promise.finally(e)}getStats(){return{filename:this.options.file.name,size:this.options.file.size,type:this.options.file.type,cancelled:this.cancelled,group:this.options.group,description:this.options.description}}}class G extends Q{constructor(e={}){super(e,{endpoint:"/api/group"})}}class nt extends de{constructor(e={}){super({ModelClass:G,endpoint:"/api/group",size:10,...e})}}const at={org:"Organization",platform:"Platform",division:"Division",department:"Department",team:"Team",merchant:"Merchant",partner:"Partner",client:"Client",iso:"ISO",sales:"Sales",reseller:"Reseller",location:"Location",region:"Region",route:"Route",project:"Project",inventory:"Inventory",test:"Testing",misc:"Miscellaneous",qa:"Quality Assurance"},ot=Object.entries(at).map(([c,e])=>({value:c,label:e})),lt=[{value:"America/New_York",label:"Eastern Time (ET)"},{value:"America/Chicago",label:"Central Time (CT)"},{value:"America/Denver",label:"Mountain Time (MT)"},{value:"America/Los_Angeles",label:"Pacific Time (PT)"},{value:"America/Anchorage",label:"Alaska Time (AKT)"},{value:"Pacific/Honolulu",label:"Hawaii Time (HT)"},{value:"UTC",label:"UTC"},{value:"Europe/London",label:"London (GMT/BST)"},{value:"Europe/Paris",label:"Paris (CET/CEST)"},{value:"Europe/Berlin",label:"Berlin (CET/CEST)"},{value:"Asia/Tokyo",label:"Tokyo (JST)"},{value:"Asia/Shanghai",label:"Shanghai (CST)"},{value:"Australia/Sydney",label:"Sydney (AEST)"}],ct=Array.from({length:24},(c,e)=>{let t;return e===0?t="Midnight":e===12?t="Noon":t=`${e%12===0?12:e%12} ${e<12?"AM":"PM"}`,{value:e,label:t}});function dt(){return{avatar:{type:"image",name:"avatar",size:"lg",imageSize:{width:200,height:200},placeholder:"Upload your avatar",help:"Square images work best",columns:12},name:{name:"name",type:"text",label:"Group Name",required:!0,placeholder:"Enter group name",columns:12},kind:{name:"kind",type:"combo",label:"Group Kind",required:!0,placeholder:"Type or select kind...",options:ot,columns:12},parent:{type:"collection",name:"parent",label:"Parent Group",Collection:nt,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300,columns:12},isActive:{name:"is_active",type:"switch",label:"Is Active",columns:12},uuid:{name:"uuid",type:"text",label:"UUID",placeholder:"32-character hex string",columns:12},shortName:{name:"metadata.short_name",type:"text",label:"Short Name",placeholder:"Enter short name",columns:6},domain:{name:"metadata.domain",type:"text",label:"Default Domain",placeholder:"Enter domain",columns:6},authDomain:{name:"metadata.auth_domain",type:"text",label:"Auth Domain",placeholder:"auth.example.com",help:"Used for white-label login pages.",columns:6},portal:{name:"metadata.portal",type:"text",label:"Default Portal",placeholder:"https://…",columns:6},timezone:{name:"metadata.timezone",type:"select",label:"Timezone",options:lt,columns:6},eodHour:{name:"metadata.eod_hour",type:"select",label:"End of Day Hour",options:ct,columns:6},emailTemplate:{name:"metadata.email_template",type:"text",label:"Email Template (Prefix)",placeholder:"Enter template prefix",columns:12}}}const Pe={get create(){const c=dt();return{title:"Create Group",fields:[c.name,c.kind,c.parent]}},get edit(){return{...this.detailed,title:"Edit Group"}},get detailed(){const c=dt();return{title:"Group Details",fields:[{type:"tabset",name:"group-detail",tabs:[{label:"Profile",fields:[c.name,c.kind,c.parent,c.isActive]},{label:"Identity",fields:[c.uuid,c.shortName,c.domain,c.authDomain,c.portal]},{label:"Localization",fields:[c.timezone,c.eodHour]},{label:"Branding",fields:[c.emailTemplate]},{label:"Avatar",fields:[c.avatar]}]}]}}};G.EDIT_FORM=Pe.edit,G.ADD_FORM=Pe.create,G.CREATE_FORM=Pe.create,G.FORM_DIALOG_CONFIG={size:"lg"},G.GroupKindOptions=ot,G.GroupKinds=at,G.TimezoneOptions=lt,G.EodHourOptions=ct;class w extends Q{constructor(e={}){super(e,{endpoint:"/api/user"})}hasPermission(e){if(this.get("is_superuser"))return!0;if(Array.isArray(e))return e.some(i=>this.hasPermission(i));const t=e.startsWith("sys."),s=t?e.substring(4):e;return!!(this._hasPermission(s)||this._hasPermission("admin")||!t&&this.member&&this.member.hasPermission(e))}_hasPermission(e){const t=this.get("permissions");if(!t)return!1;if(t[e]==!0)return!0;const s=w.GRANULAR_TO_CATEGORY[e];return!!(s&&t[s]==!0)}hasPerm(e){return this.hasPermission(e)}}w.CATEGORY_PERMISSIONS=[{name:"admin",label:"System Admin",tooltip:"Full access to everything — permission equivalent of superuser"},{name:"view_admin",label:"Admin Panel",tooltip:"Access the admin panel, Mojo, and system tools"},{name:"security",label:"Security",tooltip:"Incidents, events, rules, tickets, firewall, bouncer, GeoIP, system logs"},{name:"users",label:"Users",tooltip:"User records, passkeys, TOTP, API keys, OAuth, devices, locations"},{name:"groups",label:"Groups",tooltip:"Groups, members, group API keys, settings"},{name:"comms",label:"Communications",tooltip:"Email, phone, SMS, push notifications, chat, notifications"},{name:"jobs",label:"Jobs",tooltip:"Jobs, job events, job logs, runners, queue control, system stats"},{name:"metrics",label:"Metrics",tooltip:"Metrics recording, fetching, categories, values, permissions"},{name:"files",label:"Files",tooltip:"File managers, files, renditions, vault files, vault data, S3 buckets"},{name:"assistant",label:"Mojo",tooltip:"Access to Mojo"}],w.GRANULAR_PERMISSION_TABS=[{label:"Account",permissions:[{name:"view_users",label:"View Users"},{name:"manage_users",label:"Manage Users"},{name:"view_groups",label:"View Groups"},{name:"manage_groups",label:"Manage Groups"},{name:"manage_group",label:"Manage Own Group"},{name:"view_members",label:"View Members"},{name:"manage_settings",label:"Manage Settings"}]},{label:"Communication",permissions:[{name:"manage_chat",label:"Manage Chat"},{name:"manage_aws",label:"Manage Email (AWS)"},{name:"view_notifications",label:"View Notifications"},{name:"manage_notifications",label:"Manage Notifications"},{name:"send_notifications",label:"Send Notifications"},{name:"view_devices",label:"View Push Devices"},{name:"manage_devices",label:"Manage Push Devices"},{name:"manage_push_config",label:"Push Config"},{name:"view_phone_numbers",label:"View Phone Numbers"},{name:"manage_phone_numbers",label:"Manage Phone Numbers"},{name:"manage_phone_config",label:"Phone Config"},{name:"view_sms",label:"View SMS"},{name:"manage_sms",label:"Manage SMS"},{name:"send_sms",label:"Send SMS"}]},{label:"Platform",permissions:[{name:"view_security",label:"View Security"},{name:"manage_security",label:"Manage Security"},{name:"view_logs",label:"View Logs"},{name:"manage_logs",label:"Manage Logs"},{name:"view_jobs",label:"View Jobs"},{name:"manage_jobs",label:"Manage Jobs"},{name:"view_metrics",label:"View Metrics"},{name:"manage_metrics",label:"Manage Metrics"},{name:"write_metrics",label:"Write Metrics"},{name:"view_fileman",label:"View File Managers"},{name:"manage_files",label:"Manage Files"},{name:"view_vault",label:"View Vault"},{name:"manage_vault",label:"Manage Vault"},{name:"manage_docit",label:"Manage Docs"},{name:"manage_shortlinks",label:"Manage Shortlinks"}]}],w.CATEGORY_GRANULAR_MAP={security:["view_security","manage_security"],users:["view_users","manage_users","view_members"],groups:["view_groups","manage_groups","manage_group"],comms:["manage_chat","manage_aws","view_notifications","manage_notifications","send_notifications","view_devices","manage_devices","manage_push_config","view_phone_numbers","manage_phone_numbers","manage_phone_config","view_sms","manage_sms","send_sms"],jobs:["view_jobs","manage_jobs"],metrics:["view_metrics","manage_metrics","write_metrics"],files:["view_fileman","manage_files","view_vault","manage_vault"]},w.APP_CATEGORY_PERMISSIONS=[],w.APP_GRANULAR_PERMISSIONS=[],w._permSwitch=function(c){return{name:`permissions.${c.name}`,type:"switch",label:c.label,columns:6,...c.tooltip?{tooltip:c.tooltip}:{}}},w.PERMISSIONS=[],w.PERMISSION_FIELDS=[],w.CATEGORY_PERMISSION_FIELDS=[],w.GRANULAR_PERMISSION_FIELDS=[],w.SYSTEM_PERMISSION_FIELDS=[],w.APP_PERMISSION_FIELDS=[],w.GRANULAR_TO_CATEGORY={},w.rebuildPermissions=function(){const c=w._permSwitch;w.PERMISSIONS.length=0,w.PERMISSIONS.push(...w.CATEGORY_PERMISSIONS,...w.GRANULAR_PERMISSION_TABS.flatMap(i=>i.permissions),...w.APP_CATEGORY_PERMISSIONS,...w.APP_GRANULAR_PERMISSIONS),w.PERMISSION_FIELDS.length=0,w.PERMISSION_FIELDS.push(...w.PERMISSIONS.map(c));const e=[{label:"System",fields:w.CATEGORY_PERMISSIONS.map(c)}];w.APP_CATEGORY_PERMISSIONS.length>0&&e.push({label:"App",fields:w.APP_CATEGORY_PERMISSIONS.map(c)}),w.CATEGORY_PERMISSION_FIELDS.length=0,w.CATEGORY_PERMISSION_FIELDS.push({type:"tabset",tabs:e});const t=w.GRANULAR_PERMISSION_TABS.map(i=>({label:i.label,fields:i.permissions.map(c)}));w.APP_GRANULAR_PERMISSIONS.length>0&&t.push({label:"App",fields:w.APP_GRANULAR_PERMISSIONS.map(c)}),w.GRANULAR_PERMISSION_FIELDS.length=0,w.GRANULAR_PERMISSION_FIELDS.push({type:"tabset",tabs:t}),w.SYSTEM_PERMISSION_FIELDS.length=0,w.SYSTEM_PERMISSION_FIELDS.push({type:"tabset",tabs:[{label:"System",fields:w.CATEGORY_PERMISSIONS.map(c)},...w.GRANULAR_PERMISSION_TABS.map(i=>({label:i.label,fields:i.permissions.map(c)}))]}),w.APP_PERMISSION_FIELDS.length=0;const s=[];w.APP_CATEGORY_PERMISSIONS.length>0&&s.push({label:"Categories",fields:w.APP_CATEGORY_PERMISSIONS.map(c)}),w.APP_GRANULAR_PERMISSIONS.length>0&&s.push({label:"Permissions",fields:w.APP_GRANULAR_PERMISSIONS.map(c)}),s.length>0&&w.APP_PERMISSION_FIELDS.push({type:"tabset",tabs:s});for(const i of Object.keys(w.GRANULAR_TO_CATEGORY))delete w.GRANULAR_TO_CATEGORY[i];for(const[i,r]of Object.entries(w.CATEGORY_GRANULAR_MAP))for(const n of r)w.GRANULAR_TO_CATEGORY[n]=i},w.registerCategoryMap=function(c){if(!c)return;let e=!1;for(const[t,s]of Object.entries(c)){if(!Array.isArray(s))continue;const i=w.CATEGORY_GRANULAR_MAP[t]||[];w.CATEGORY_GRANULAR_MAP[t]=Array.from(new Set([...i,...s])),e=!0}e&&w.rebuildPermissions()},w.registerPermissions=function(c){if(c){if(Array.isArray(c.categories)&&w.APP_CATEGORY_PERMISSIONS.push(...c.categories),Array.isArray(c.granularPermissions)&&w.APP_GRANULAR_PERMISSIONS.push(...c.granularPermissions),Array.isArray(c.granularTabs)&&w.GRANULAR_PERMISSION_TABS.push(...c.granularTabs),c.categoryGranularMap)for(const[e,t]of Object.entries(c.categoryGranularMap)){if(!Array.isArray(t))continue;const s=w.CATEGORY_GRANULAR_MAP[e]||[];w.CATEGORY_GRANULAR_MAP[e]=Array.from(new Set([...s,...t]))}w.rebuildPermissions()}},w.rebuildPermissions();const ht={create:{title:"Create User",fields:[{name:"email",type:"text",label:"Email",required:!0},{name:"phone_number",type:"text",label:"Phone number",columns:12},{name:"display_name",type:"text",label:"Display Name"}]},edit:{title:"Edit User",fields:[{name:"email",type:"email",label:"Email",columns:12},{name:"display_name",type:"text",label:"Display Name",columns:12},{name:"phone_number",type:"text",label:"Phone number",columns:12},{type:"collection",name:"org",label:"Organization",Collection:nt,labelField:"name",valueField:"id",columns:12}]},permissions:{fields:w.PERMISSION_FIELDS}},Kt={detailed:{title:"Detailed User Information",columns:2,showEmptyValues:!0,emptyValueText:"Not set",fields:[{name:"id",label:"User ID",type:"number",colSize:3},{name:"display_name",label:"Display Name",type:"text",format:'capitalize|default("Unnamed User")',colSize:9},{name:"username",label:"Username",type:"text",format:"lowercase",colSize:6},{name:"email",label:"Email Address",type:"email",colSize:6},{name:"phone_number",label:"Phone Number",type:"phone",format:'phone|default("Not provided")',colSize:6},{name:"is_active",label:"Account Status",type:"boolean",colSize:6},{name:"last_login",label:"Last Login",type:"datetime",format:"relative",colSize:6},{name:"last_activity",label:"Last Activity",type:"datetime",format:"relative",colSize:6},{name:"avatar.url",label:"Avatar",type:"url",colSize:12},{name:"permissions",label:"User Permissions",type:"dataview",dataViewColumns:2,showEmptyValues:!1},{name:"metadata",label:"User Metadata",type:"dataview",dataViewColumns:1},{name:"avatar",label:"Avatar Details",type:"dataview",dataViewColumns:1}]}};w.DATA_VIEW=Kt.detailed,w.EDIT_FORM=ht.edit,w.ADD_FORM=ht.create;class ut extends Q{constructor(e={}){super(e,{endpoint:"/api/fileman/manager"})}}const mt={create:{title:"Add Storage Backend",fields:[{name:"name",type:"text",label:"Display Name",placeholder:"Enter Display Name",cols:12},{name:"use",type:"text",label:"Use",placeholder:"Enter User or Leave Blank",cols:12},{name:"backend_url",type:"text",label:"Backend URL",required:!0,value:"s3://BUCKET_NAME/OPTION_FOLDER",placeholder:"s3://bucket_name/optional folder",help:"Format: service://path. Valid services: s3",cols:12},{name:"aws_region",type:"select",label:"AWS Region (optional)",value:"us-east-1",options:[{value:"",text:"System Default"},{value:"us-east-1",text:"US East (N. Virginia)"},{value:"us-east-2",text:"US East (Ohio)"},{value:"us-west-1",text:"US West (N. California)"},{value:"us-west-2",text:"US West (Oregon)"},{value:"ca-central-1",text:"Canada (Central)"},{value:"eu-west-1",text:"Europe (Ireland)"},{value:"eu-west-2",text:"Europe (London)"},{value:"eu-west-3",text:"Europe (Paris)"},{value:"eu-central-1",text:"Europe (Frankfurt)"},{value:"eu-north-1",text:"Europe (Stockholm)"},{value:"eu-south-1",text:"Europe (Milan)"},{value:"ap-southeast-2",text:"Asia Pacific (Sydney)"}],columns:12,help:"Optional. Defaults to project AWS_REGION if omitted."},{name:"aws_key",type:"text",label:"AWS Key (optional)",placeholder:"enter your AWS Key with S3 permissions",columns:12,help:"Optional, AWS Key with S3 permissions"},{name:"aws_secret",type:"text",label:"AWS Secret (optional)",placeholder:"enter your AWS Secret with S3 permissions",columns:12,help:"Optional, AWS Secret with S3 permissions"},{name:"is_default",type:"switch",label:"Is Default",cols:6},{name:"is_active",type:"switch",label:"Is Active",default:!0,cols:6}]},edit:{title:"Edit Storage Backend",fields:[{name:"name",type:"text",label:"Display Name",placeholder:"Enter Display Name",cols:12},{name:"use",type:"text",label:"Use",placeholder:"Enter User or Leave Blank",cols:12},{name:"backend_url",type:"text",label:"Backend URL",required:!0,placeholder:"s3://bucket_name/optional folder",help:"Format: service://path. Valid services: s3",cols:12},{name:"allowed_origins",type:"text",label:"Domains Who Can Upload",cols:12},{name:"is_default",type:"switch",label:"Is Default",cols:6},{name:"is_active",type:"switch",label:"Is Active",default:!0,cols:6},{name:"is_public",type:"switch",label:"Is Public",default:!0,cols:6}]}};let pt=class extends Q{constructor(e={}){super(e,{endpoint:"/api/fileman/file"})}isImage(){return this.get("category")==="image"}getCategory(){return this.get("category")||this._inferCategoryFromContentType()}_inferCategoryFromContentType(){const e=(this.get("content_type")||"").toLowerCase();return e?e.startsWith("image/")?"image":e.startsWith("video/")?"video":e.startsWith("audio/")?"audio":e==="application/pdf"?"pdf":e.startsWith("text/")||e==="application/msword"||e.startsWith("application/vnd.openxmlformats-officedocument.wordprocessingml")||e==="application/vnd.oasis.opendocument.text"?"document":e==="application/vnd.ms-excel"||e.startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml")||e==="application/vnd.oasis.opendocument.spreadsheet"?"spreadsheet":e==="application/vnd.ms-powerpoint"||e.startsWith("application/vnd.openxmlformats-officedocument.presentationml")||e==="application/vnd.oasis.opendocument.presentation"?"presentation":e==="application/zip"||e==="application/x-rar-compressed"||e==="application/x-7z-compressed"||e==="application/x-tar"||e==="application/gzip"?"archive":"other":"other"}hasRenditions(){const e=this.get("renditions");return!!(e&&Object.keys(e).length)}isUploadPending(){const e=this.get("upload_status");return!!(e&&e!=="completed"&&e!=="failed")}regenerateRenditions(e){const t=this.id||this.get("id");if(!t)return Promise.reject(new Error("Cannot regenerate renditions on an unsaved file"));const s=Array.isArray(e)&&e.length?{regenerate_renditions:e}:{regenerate_renditions:!0};return this.rest.POST(`${this.endpoint}/${t}`,s)}share(e=!0){const t=this.id||this.get("id");return t?this.rest.POST(`${this.endpoint}/${t}`,{share:e}):Promise.reject(new Error("Cannot share an unsaved file"))}getRenditions(){const e=this.get("renditions");return e?Object.values(e):[]}getBestImageRendition(){const e=this.getRenditions().filter(t=>t&&typeof t.content_type=="string"&&t.content_type.startsWith("image/"));return e.length?e.reduce((t,s)=>{const i=(parseInt(t.width)||0)*(parseInt(t.height)||0);return(parseInt(s.width)||0)*(parseInt(s.height)||0)>i?s:t}):null}getThumbnailUrl(){const e=this.get("renditions")||{};if(e.thumbnail&&e.thumbnail.url)return e.thumbnail.url;const t=this.getBestImageRendition();return t?t.url:null}upload(e={}){return new Zt(this,e)}};const Qt={edit:{title:"Edit File Backend",fields:[]}};ut.ADD_FORM=mt.create,ut.EDIT_FORM=mt.edit,pt.EDIT_FORM=Qt.edit;class v{static _renderAndAwait(e,{buttons:t=null,rejectOnDismiss:s=!1,onAction:i=null,cleanup:r=null}={}){const n=x.getMountTarget();return new Promise((a,o)=>{let l=!1;const d=u=>{l||(l=!0,a(u))},h=u=>{l||(l=!0,o(u))};(async()=>{try{await e.render(!0,n)}catch(u){h(u);return}t&&t.length>0&&e.element&&e.element.querySelectorAll(".modal-footer button").forEach((m,p)=>{const f=t[p];f&&m.addEventListener("click",async g=>{if(l)return;const b=f.value!==void 0?f.value:f.action??p;if(typeof f.handler=="function"){try{const y=await f.handler({dialog:e,button:f,index:p,event:g});if(y===null||y===!1)return;const C=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(C)}catch(y){console.error("Modal button handler error:",y)}return}if(typeof i=="function"&&f.action){try{const y=await i(f.action,{dialog:e,button:f,index:p,event:g});if(y===null||y===!1)return;const C=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(C)}catch(y){console.error("Modal onAction error:",y)}return}f.dismiss||e.hide(),d(b)})}),e.on("hidden",()=>{l||(s?h(new Error("Dialog dismissed")):d(null)),setTimeout(async()=>{try{typeof r=="function"&&await r(e)}catch(u){console.error("Modal cleanup error:",u)}try{await e.destroy()}catch(u){console.error("Modal destroy error:",u)}e.element?.parentNode&&e.element.parentNode.removeChild(e.element)},100)}),e.show()})()})}static async dialog(e={}){if(typeof e=="string"){const p=arguments[0],f=arguments[1]||"Alert";e={...arguments[2]||{},body:p,title:f}}const{title:t="Dialog",content:s,body:i,view:r,message:n,size:a="md",centered:o=!0,buttons:l=[{text:"OK",class:"btn-primary",value:!0}],rejectOnDismiss:d=!1,...h}=e,u=i??r??n??s??"",m=new x({title:t,body:u,size:a,centered:o,buttons:l,...h});return v._renderAndAwait(m,{buttons:l,rejectOnDismiss:d})}static async drawer(e={}){const{eyebrow:t,title:s,meta:i=[],view:r,body:n,size:a="lg",...o}=e,l=i.length?`
203
203
  <div class="modal-drawer-meta">
204
204
  ${i.map(u=>typeof u=="string"?`<span>${v._esc(u)}</span>`:`<span>${u.icon?`<i class="${v._esc(u.icon)} me-1"></i>`:""}${v._esc(u.text||"")}</span>`).join("")}
205
205
  </div>`:"",d=`
@@ -215,7 +215,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
215
215
  id="${i}"
216
216
  value="${r}"
217
217
  placeholder="${a}">
218
- `,size:s.size||"sm",centered:!0,backdrop:"static",buttons:o,...s});return l.on("shown",()=>{const d=l.element.querySelector(`#${i}`);d&&(d.focus(),d.select())}),v._renderAndAwait(l,{buttons:o,onAction:async d=>{if(d!=="ok")return null;const h=l.element.querySelector(`#${i}`);return h?h.value:null}})}static showError(e){return v.alert(e,"Error",{type:"error"})}static async form(e={}){const{title:t="Form",formConfig:s={},size:i="md",centered:r=!0,submitText:n="Submit",cancelText:a="Cancel",...o}=e,l=(await Promise.resolve().then(()=>Mt)).default,d=new l({fileHandling:e.fileHandling||"base64",data:e.data,defaults:e.defaults,model:e.model,formConfig:{fields:s.fields||e.fields,...s,submitButton:!1,resetButton:!1}}),h=[{text:a,class:"btn-secondary",action:"cancel"},{text:n,class:"btn-primary",action:"submit"}],u=new x({title:t,body:d,size:i,centered:r,buttons:h,...o});return v._renderAndAwait(u,{buttons:h,onAction:async m=>{if(m==="cancel")return u.hide(),null;if(m!=="submit")return null;if(!d.validate())return d.focusFirstError(),!1;if(e.autoSave&&e.model){u.setLoading(!0);const p=await d.saveModel();return p.success?p:(u.setLoading(!1),await u.render(),u.getApp()?.toast?.error(p.message),!1)}try{return await d.getFormData()}catch(p){return console.error("Modal.form: error collecting form data:",p),d.showError("Error collecting form data"),!1}},cleanup:async()=>{try{await d.destroy()}catch{}}})}static async modelForm(e={}){const{title:t="Edit",formConfig:s={},size:i="md",centered:r=!0,submitText:n="Save",cancelText:a="Cancel",model:o,fields:l,...d}=e;if(!o)throw new Error("Modal.modelForm requires a model");const h=(await Promise.resolve().then(()=>Mt)).default,u=new h({fileHandling:e.fileHandling||"base64",model:o,data:e.data,defaults:e.defaults,formConfig:{fields:l||s.fields||[],...s,submitButton:!1,resetButton:!1}}),m=[{text:a,class:"btn-secondary",action:"cancel"},{text:n,class:"btn-primary",action:"submit"}],p=new x({title:t,body:u,size:i,centered:r,buttons:m,...d});return v._renderAndAwait(p,{buttons:m,onAction:async f=>{if(f==="cancel")return p.hide(),null;if(f!=="submit")return null;p.setLoading(!0,"Saving...");try{const g=await u.handleSubmit();if(g.success)return g;p.setLoading(!1);let b=g.error;return g.data?.error&&(b=g.data.error),p.getApp()?.toast?.error(b),!1}catch(g){return console.error("Modal.modelForm: error saving:",g),await p.setContent(u),u.showError(g.message||"An error occurred while saving"),!1}},cleanup:async()=>{try{await u.destroy()}catch{}}})}static async data(e={}){const{title:t="Data View",data:s={},model:i=null,fields:r=[],columns:n=2,responsive:a=!0,showEmptyValues:o=!1,emptyValueText:l="—",size:d="lg",centered:h=!0,closeText:u="Close",...m}=e,p=(await Promise.resolve().then(()=>Fs)).default,f=new p({data:s,model:i,fields:r,columns:n,responsive:a,showEmptyValues:o,emptyValueText:l}),g=[{text:u,class:"btn-secondary",value:"close"}],b=new x({title:t,body:f,size:d,centered:h,buttons:g,...m});return f.on("field:click",y=>b.emit("dataview:field:click",y)),f.on("error",y=>b.emit("dataview:error",y)),v._renderAndAwait(b,{buttons:g,cleanup:async()=>{try{await f.destroy()}catch{}}})}static async code(e={}){const{code:t="",language:s="javascript",title:i="Source Code",size:r="lg",...n}=e,a=new me({code:t,language:s}),o=[{text:"Copy to Clipboard",class:"btn-primary",icon:"bi-clipboard",action:"copy"},{text:"Close",class:"btn-secondary",dismiss:!0}],l=new x({title:i,body:a,size:r,scrollable:!0,buttons:o,...n});return v._renderAndAwait(l,{buttons:o,onAction:async d=>{if(d!=="copy")return null;if(!navigator.clipboard)return!1;try{await navigator.clipboard.writeText(t),v._showCopySuccess(l)}catch(h){console.error("Modal.code: clipboard write failed:",h)}return!1}})}static _showCopySuccess(e){const t=e.element?.querySelector('[data-action="copy"]');if(!t)return;const s=t.innerHTML;t.innerHTML='<i class="bi bi-check me-1"></i>Copied!',t.classList.remove("btn-primary"),t.classList.add("btn-success"),t.disabled=!0,setTimeout(()=>{t.innerHTML=s,t.classList.remove("btn-success"),t.classList.add("btn-primary"),t.disabled=!1},2e3)}static async htmlPreview(e={}){const{html:t=e.content||"",title:s="HTML Preview",size:i="lg",height:r=500,...n}=e,a=new Gt({html:t,height:r}),o=[{text:"Close",class:"btn-secondary",dismiss:!0}],l=new x({title:s,body:a,size:i,scrollable:!1,buttons:o,...n});return v._renderAndAwait(l,{buttons:o})}static async updateModelImage(e={},t={}){const s=e.upload||!1,i=t.name||e.field||"image",r={title:"Upload Your Avatar",model:null,autoSave:!s,size:"sm",fields:[{type:"image",name:i,size:"lg",imageSize:{width:200,height:200},placeholder:"Upload your image",...t}],...e},n=await v.form(r);if(!s||!n||!e.model)return n;const a=n[i];if(!a||!a.startsWith("data:"))return n;const o=a.split(","),d=o[0]?.match(/:(.*?);/)?.[1]||"image/png",h=atob(o[1]);let u=h.length;const m=new Uint8Array(u);for(;u--;)m[u]=h.charCodeAt(u);const p=d.split("/")[1]||"png",f=typeof window<"u"&&window.File||globalThis.File;if(!f)throw new Error("File API is not available in this environment");const g=new f([m],`${i}.${p}`,{type:d}),b=new pt;return await b.upload({file:g,name:`${i}.${p}`,description:e.uploadDescription||`${i} upload`,showToast:!0}),e.model.save({[i]:b.id})}static loading(e){ke.show(e)}static hideLoading(e){ke.hide(e)}static showBusy(e){return v.loading(e)}static hideBusy(e){return v.hideLoading(e)}}const N=Object.freeze(Object.defineProperty({__proto__:null,default:v},Symbol.toStringTag,{value:"Module"}));class ve{constructor(e={}){this.config=e,this.initPluginRegistry(),this.name=e.name||"MOJO App",this.version=e.version||"1.0.0",this.debug=e.debug||!1,this.container=e.container||"#app",this.layoutType=e.layout||"portal",this.layoutConfig=e.layoutConfig||{},e.sidebar&&(this.layoutConfig.sidebarConfig=e.sidebar),e.topbar&&(this.layoutConfig.topbarConfig=e.topbar),this.layout=null,this.layoutConfig.containerId=this.container||this.containerId||"#app",this.pageContainer=e.pageContainer||"#page-container",this.basePath=e.basePath||"",this.routerMode=e.routerMode||e.router?.mode||"param",this.basePath=e.basePath||e.router?.base||"",this.defaultRoute=e.defaultRoute||"home",this.session=e.session||{},this.router=null,this.navigation=e.navigation||{},this.state={currentPage:null,previousPage:null,loading:!1},this.events=new Vt,this.rest=ne,this.modal=v,e.api&&this.rest.configure(e.api);const t=(this.name||"mojo").replace(/\s+/g,"_").toLowerCase();this.theme=new Nt({storageKey:`${t}:theme`,eventBus:this.events}),this.theme.init(),this.router=new Te({mode:this.routerMode==="param"?"params":this.routerMode,basePath:this.basePath,defaultRoute:this.defaultRoute,eventEmitter:this.events}),this.events.on("route:changed",async s=>{const{pageName:i,params:r,query:n}=s;await this.showPage(i,n,r,{fromRouter:!0})}),typeof window<"u"&&(window.MOJO=window.MOJO||{},window.MOJO.router=this.router),this.setupFocusTracking(),this.pageCache=new Map,this.pageClasses=new Map,this.componentClasses=new Map,this.modelClasses=new Map,this.modelRefClasses=new Map,this.currentPage=null,this.isStarted=!1,window.matchUUID?window[window.matchUUID]=this:window.MOJO?window.MOJO.app=this:window.__app__=this}async start(){if(this.isStarted){console.warn("WebApp already started");return}try{this.setupPageContainer(),this.validateDefaultRoute(),await this.setupRouter(),this.isStarted=!0,this.router.allowPopState=!1,this.events.emit("app:ready",{app:this})}catch(e){throw console.error(`Failed to start ${this.name}:`,e),this.showError("Failed to start application"),e}}async setupRouter(){if(!this.router){console.error("Router not initialized");return}this.events.on("route:notfound",async e=>{console.warn(`Route not found: ${e.path}`),this._show404(e.path)}),this.router.start(),console.log(`Router started in ${this.routerMode} mode`)}setupPageContainer(){const e=typeof this.container=="string"?document.querySelector(this.container):this.container;e&&!e.querySelector("#page-container")&&(e.innerHTML='<div id="page-container"></div>'),this.pageContainer="#page-container"}registerPage(e,t,s={}){if(typeof e!="string"||!e)return console.error("registerPage: pageName must be a non-empty string"),this;if(typeof t!="function")return console.error("registerPage: PageClass must be a constructor function"),this;if(s.containerId||(s.containerId=this.pageContainer),this.pageClasses.set(e,{PageClass:t,constructorOptions:s}),this.router){let i=s.route||`/${e}`;i.startsWith("/")||(i=`/${i}`),s.route=i,this.router.addRoute(i,e)}return this}getPage(e){return this.pageCache.get(e)}getPagePermissions(e){if(this.pageCache.has(e))return this.pageCache.get(e).permissions;const t=this.pageClasses.get(e);if(!t)return null;const{PageClass:s,constructorOptions:i}=t;return i?i.permissions:null}getOrCreatePage(e){if(this.pageCache.has(e))return this.pageCache.get(e);const t=this.pageClasses.get(e);if(!t)return console.error(`Page not registered: ${e}`),null;const{PageClass:s,constructorOptions:i}=t;try{const r={pageName:e,...i,app:this},n=new s(r);return i.route&&(n.route=i.route),this.pageCache.set(e,n),console.log(`Created page: ${e} with route: ${n.route}`),n}catch(r){return console.error(`Failed to create page ${e}:`,r),null}}async showPage(e,t={},s={},i={}){const{fromRouter:r=!1,replace:n=!1,force:a=!1}=i;try{let o,l;typeof e=="string"?(l=e,o=this.getOrCreatePage(e)):e&&typeof e=="object"&&(o=e,l=e.pageName);const d=this.currentPage;if(!o){this._show404(l,s,t,r);return}if(this.events.emit("page:showing",{page:o,pageName:o.pageName,params:s,query:t,fromRouter:r}),!o.canEnter()){this._showDeniedPage(o,s,t,r);return}d&&d!==o&&await this._exitOldPage(d),await o.onParams(s,t),d!==o&&await o.onEnter(),o.syncUrl(),this.events.emit("page:show",{page:o,pageName:o.pageName,params:s,query:t,fromRouter:r}),await o.render(),this.currentPage=o,console.log(`✅ Showing page: ${o.pageName}`,{query:t,params:s})}catch(o){console.error("Error in showPage:",o),this.showError(`Failed to load page: ${o.message}`),e!=="error"&&await this.showPage("error",{},{error:o,originalPage:e},{fromRouter:r})}}async _show404(e,t,s,i){const r=this.getOrCreatePage("404");r&&(r.setInfo&&r.setInfo(e),await this._exitOldPage(this.currentPage),await r.render(),this.currentPage=r,this.events.emit("page:404",{page:null,pageName:e,params:t,query:s,fromRouter:i}))}async _showDeniedPage(e,t,s,i){const r=this.getOrCreatePage("denied");r.setDeniedPage&&r.setDeniedPage(e),await this._exitOldPage(this.currentPage),await r.render(),this.currentPage=r,this.events.emit("page:denied",{page:e,pageName:e.pageName,params:t,query:s,fromRouter:i})}async _exitOldPage(e){if(e)try{await e.onExit(),await e.unmount(),this.events.emit("page:hide",{page:e})}catch(t){console.error(`Error exiting page ${e.pageName}:`,t)}}async navigate(e,t={},s={}){if(!this.router){console.error("Router not initialized");return}let i=e;if(Object.keys(t).length>0){const r=new URLSearchParams(t).toString();i+=(e.includes("?")?"&":"?")+r}return await this.router.navigate(i,s)}async navigateToDefault(e={}){return await this.showPage(this.defaultRoute,{},{},e)}back(){this.router?this.router.back():console.warn("Router not initialized")}forward(){this.router?this.router.forward():console.warn("Router not initialized")}getCurrentPage(){return this.currentPage}getPageContainer(){return this.layout&&this.layout.getPageContainer?this.layout.getPageContainer():typeof this.pageContainer=="string"?document.querySelector(this.pageContainer):this.pageContainer}async showError(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Error",{size:"md",type:"error"})}catch(t){this.events.emit("notification",{message:e,type:"error"}),typeof window<"u"&&window?.console&&console.error("[WebApp] showError fallback:",t),typeof window<"u"&&alert(`Error: ${e}`)}}async showSuccess(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Success",{size:"md",type:"success"})}catch(t){this.events.emit("notification",{message:e,type:"success"}),typeof window<"u"&&window?.console&&console.warn("[WebApp] showSuccess fallback:",t),typeof window<"u"&&alert(`Success: ${e}`)}}async showInfo(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Information",{size:"md",type:"info"})}catch(t){this.events.emit("notification",{message:e,type:"info"}),typeof window<"u"&&window?.console&&console.info("[WebApp] showInfo fallback:",t),typeof window<"u"&&alert(`Info: ${e}`)}}async showWarning(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Warning",{size:"md",type:"warning"})}catch(t){this.events.emit("notification",{message:e,type:"warning"}),typeof window<"u"&&window?.console&&console.warn("[WebApp] showWarning fallback:",t),typeof window<"u"&&alert(`Warning: ${e}`)}}showNotification(e,t="info"){this.events.emit("notification",{message:e,type:t})}async showLoading(e={}){typeof e=="string"&&(e={message:e});try{(await Promise.resolve().then(()=>N)).default.showBusy(e)}catch(t){typeof window<"u"&&window?.console&&console.warn("[WebApp] showLoading fallback:",t,e),this.events.emit("notification",{message:e.message||"Loading...",type:"info"})}}async hideLoading(){try{(await Promise.resolve().then(()=>N)).default.hideBusy()}catch(e){typeof window<"u"&&window?.console&&console.warn("[WebApp] hideLoading fallback:",e)}}async showModelView(e,t={}){try{return await(await Promise.resolve().then(()=>N)).default.showModelView(e,t)}catch(s){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showModelForm failed:",s),s}}async showModelForm(e={}){try{return await(await Promise.resolve().then(()=>N)).default.modelForm(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showModelForm failed:",t),t}}async showForm(e={}){try{return await(await Promise.resolve().then(()=>N)).default.form(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showForm failed:",t),t}}async showDialog(e={}){try{return await(await Promise.resolve().then(()=>N)).default.dialog(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showDialog failed:",t),t}}async showAlert(e={}){try{return await(await Promise.resolve().then(()=>N)).default.dialog(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showDialog failed:",t),t}}async confirm(e,t="Confirm",s={}){return await(await Promise.resolve().then(()=>N)).default.confirm(e,t,s)}setTheme(e){return this.theme.set(e),this}getTheme(){return this.theme.getPreference()}getResolvedTheme(){return this.theme.getResolved()}setupFocusTracking(){if(typeof window>"u")return;this.isFocused=!document.hidden;const e=()=>{const i=this.isFocused;this.isFocused=!document.hidden,i!==this.isFocused&&(this.isFocused?this.events.emit("browser:focus"):this.events.emit("browser:blur"))},t=()=>{this.isFocused||(this.isFocused=!0,this.events.emit("browser:focus"))},s=()=>{this.isFocused&&(this.isFocused=!1,this.events.emit("browser:blur"))};document.addEventListener("visibilitychange",e),window.addEventListener("focus",t),window.addEventListener("blur",s),this._focusHandlers={visibilitychange:e,focus:t,blur:s}}setupErrorHandling(){window.addEventListener("error",e=>{console.error("Global error:",e.error),this.debug&&this.showError(`Error: ${e.error?.message||"Unknown error"}`)}),window.addEventListener("unhandledrejection",e=>{console.error("Unhandled promise rejection:",e.reason),this.debug&&this.showError(`Promise rejected: ${e.reason?.message||"Unknown error"}`)})}escapeHtml(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}getState(e){return e?this.state[e]:this.state}setState(e){const t={...this.state};Object.assign(this.state,e),this.events.emit("state:changed",{oldState:t,newState:this.state,updates:e})}registerComponent(e,t){this.componentClasses.set(e,t)}getComponent(e){return this.componentClasses.get(e)}registerModel(e,t){this.modelClasses.set(e,t)}getModel(e){return this.modelClasses.get(e)}registerModelRef(e,t){this.modelRefClasses.set(e,t)}getModelByRef(e){return this.modelRefClasses.get(e)}setupRest(){this.rest=ne,ne.configure(this.api)}async destroy(){console.log("Destroying WebApp..."),this.router&&this.router.stop(),this._focusHandlers&&typeof window<"u"&&(document.removeEventListener("visibilitychange",this._focusHandlers.visibilitychange),window.removeEventListener("focus",this._focusHandlers.focus),window.removeEventListener("blur",this._focusHandlers.blur));const e=Array.from(this.pageCache.values());if(await Promise.allSettled(e.map(async t=>{try{t.destroy&&await t.destroy()}catch(s){console.error("Error destroying page:",s)}})),this.layout&&this.layout.destroy)try{await this.layout.destroy()}catch(t){console.error("Error destroying layout:",t)}this.pageCache.clear(),this.pageClasses.clear(),this.componentClasses.clear(),this.modelClasses.clear(),typeof window<"u"&&window.MOJO&&delete window.MOJO.router,this.isStarted=!1,console.log(`✨ ${this.name} destroyed`)}buildPagePath(e,t,s){let i=e.route||`/${e.pageName.toLowerCase()}`;if(Object.keys(t).forEach(r=>{(typeof t[r]=="string"||typeof t[r]=="number")&&(i=i.replace(`:${r}`,t[r]))}),s&&Object.keys(s).length>0){const r=new URLSearchParams(s).toString();i+=(i.includes("?")?"&":"?")+r}return i}validateDefaultRoute(){this.pageClasses.has(this.defaultRoute)?console.log(`✅ Default route '${this.defaultRoute}' is registered`):(console.warn(`⚠️ Default route '${this.defaultRoute}' is not registered!`),console.warn(` Please register a page: app.registerPage('${this.defaultRoute}', YourPageClass);`),console.warn(" Or change default route: new WebApp({ defaultRoute: 'your-page' });"))}findFallbackPage(){const e=["404","error","denied"];for(const[t]of this.pageClasses.entries())if(!e.includes(t))return t;return null}static create(e={}){return new ve(e)}initPluginRegistry(){typeof window<"u"&&(window.MOJO||(window.MOJO={}),window.MOJO.plugins||(window.MOJO.plugins={}),window.MOJO.app=this)}static registerPlugin(e,t){typeof window<"u"&&(window.MOJO||(window.MOJO={}),window.MOJO.plugins||(window.MOJO.plugins={}),window.MOJO.plugins[e]=t,console.debug(`MOJO Plugin registered: ${e}`))}}class pe extends S{constructor(e={}){e.tagName=e.tagName||"main",e.className=e.className||"mojo-page";const t=e.pageName||"";t&&!e.id&&(e.id="page_"+t.toLowerCase().replace(/\s+/g,"_")),super(e),this.pageName=e.pageName||this.constructor.pageName||"",this.route=e.route||this.constructor.route||"",this.title=e.title||this.pageName||"",!this.id&&this.constructor.pageName&&!e.pageName&&(this.id="page_"+this.constructor.pageName.toLowerCase().replace(/\s+/g,"_")),this.pageIcon=e.icon||e.pageIcon||this.constructor.pageIcon||"bi bi-file-text",this.displayName=e.displayName||this.constructor.displayName||this.pageName||"",this.pageDescription=e.pageDescription||this.constructor.pageDescription||"",this.params={},this.query={},this.matched=!1,this.isActive=!1,this.pageOptions={title:e.title||this.pageName||"Untitled Page",description:e.description||"",requiresAuth:e.requiresAuth||!1,...e.pageOptions},this.savedState=null,console.log(`Page ${this.pageName} constructed with route: ${this.route}`)}async onParams(e={},t={}){this.params=e,this.query=t}canEnter(){if(this.options.permissions){const e=this.getApp().activeUser;if(!e||!e.hasPermission(this.options.permissions))return!1}return!(this.options.requiresGroup&&!this.getApp().activeGroup)}async onEnter(){this.isActive=!0,this._wasExited=!1,await this.onInitView(),this.savedState&&(this.restoreState(this.savedState),this.savedState=null),this.pageOptions&&this.pageOptions.title&&typeof document<"u"&&(document.title=this.pageOptions.title),this.emit("activated",{page:this.getMetadata()}),console.log(`Page ${this.pageName} entered`)}async onExit(){this.savedState=this.captureState(),this.isActive=!1,this._wasExited=!0,this._clearScheduledRefreshes(),this.emit("deactivated",{page:this.getMetadata()}),console.log(`Page ${this.pageName} exiting`)}scheduleRefresh(e,t,s={}){if(this._scheduledRefreshes||(this._scheduledRefreshes=[]),typeof e!="function"||!(t>0))return null;const i=async()=>{try{await e()}catch(a){console.warn(`[Page ${this.pageName}] scheduleRefresh handler error:`,a)}};s.immediate&&i();const r=setInterval(i,t),n={id:r,tier:s.tier||null,handler:i,intervalMs:t};return this._scheduledRefreshes.push(n),{cancel:()=>{clearInterval(r),this._scheduledRefreshes=(this._scheduledRefreshes||[]).filter(a=>a!==n)}}}async runScheduledRefreshes(e=null){const t=this._scheduledRefreshes||[],s=e?t.filter(i=>i.tier===e):t;await Promise.allSettled(s.map(i=>i.handler()))}_clearScheduledRefreshes(){if(this._scheduledRefreshes){for(const e of this._scheduledRefreshes)clearInterval(e.id);this._scheduledRefreshes=[]}}async render(e=!0,t=null){return this._wasExited&&!this.isActive?this:super.render(e,t)}async onGroupChange(e){}getMetadata(){return{name:this.pageName,displayName:this.displayName||this.pageName,icon:this.pageIcon,description:this.pageDescription,route:this.route,isActive:this.isActive}}async onActionDefault(e){console.log(`Default action '${e}' triggered on page: ${this.pageName}`)}async makeActive(){this.getApp().showPage(this)}async onActionNavigate(e,t){e.preventDefault();const s=t.dataset.page;this.getApp().showPage(s)}captureState(){return this.element?{scrollTop:this.element.scrollTop,formData:this.captureFormData(),custom:this.captureCustomState()}:null}restoreState(e){!e||!this.element||(this.element.scrollTop=e.scrollTop||0,this.restoreFormData(e.formData),e.custom&&this.restoreCustomState(e.custom))}captureFormData(){const e={};return this.element&&this.element.querySelectorAll("input, select, textarea").forEach(t=>{t.name&&(t.type==="checkbox"?e[t.name]=t.checked:t.type==="radio"?t.checked&&(e[t.name]=t.value):e[t.name]=t.value)}),e}restoreFormData(e){!e||!this.element||Object.entries(e).forEach(([t,s])=>{const i=this.element.querySelector(`[name="${t}"]`);if(i)if(i.type==="checkbox")i.checked=s;else if(i.type==="radio"){const r=this.element.querySelector(`[name="${t}"][value="${s}"]`);r&&(r.checked=!0)}else i.value=s})}captureCustomState(){return{}}restoreCustomState(e){}setMeta(e={}){if(!(typeof document>"u")){if(e.title&&(document.title=e.title,this.pageOptions.title=e.title),e.description){let t=document.querySelector('meta[name="description"]');t||(t=document.createElement("meta"),t.name="description",document.head.appendChild(t)),t.content=e.description,this.pageOptions.description=e.description}Object.entries(e).forEach(([t,s])=>{if(t!=="title"&&t!=="description"){let i=document.querySelector(`meta[name="${t}"]`);i||(i=document.createElement("meta"),i.name=t,document.head.appendChild(i)),i.content=s}})}}showError(e){if(super.showError(e),this.element){const t=document.createElement("div");t.className="alert alert-danger alert-dismissible fade show",t.innerHTML=`
218
+ `,size:s.size||"sm",centered:!0,backdrop:"static",buttons:o,...s});return l.on("shown",()=>{const d=l.element.querySelector(`#${i}`);d&&(d.focus(),d.select())}),v._renderAndAwait(l,{buttons:o,onAction:async d=>{if(d!=="ok")return null;const h=l.element.querySelector(`#${i}`);return h?h.value:null}})}static showError(e){return v.alert(e,"Error",{type:"error"})}static async form(e={}){const{title:t="Form",formConfig:s={},size:i="md",centered:r=!0,submitText:n="Submit",cancelText:a="Cancel",...o}=e,l=(await Promise.resolve().then(()=>It)).default,d=new l({fileHandling:e.fileHandling||"base64",data:e.data,defaults:e.defaults,model:e.model,formConfig:{fields:s.fields||e.fields,...s,submitButton:!1,resetButton:!1}}),h=[{text:a,class:"btn-secondary",action:"cancel"},{text:n,class:"btn-primary",action:"submit"}],u=new x({title:t,body:d,size:i,centered:r,buttons:h,...o});return v._renderAndAwait(u,{buttons:h,onAction:async m=>{if(m==="cancel")return u.hide(),null;if(m!=="submit")return null;if(!d.validate())return d.focusFirstError(),!1;if(e.autoSave&&e.model){u.setLoading(!0);const p=await d.saveModel();return p.success?p:(u.setLoading(!1),await u.render(),u.getApp()?.toast?.error(p.message),!1)}try{return await d.getFormData()}catch(p){return console.error("Modal.form: error collecting form data:",p),d.showError("Error collecting form data"),!1}},cleanup:async()=>{try{await d.destroy()}catch{}}})}static async modelForm(e={}){const{title:t="Edit",formConfig:s={},size:i="md",centered:r=!0,submitText:n="Save",cancelText:a="Cancel",model:o,fields:l,...d}=e;if(!o)throw new Error("Modal.modelForm requires a model");const h=(await Promise.resolve().then(()=>It)).default,u=new h({fileHandling:e.fileHandling||"base64",model:o,data:e.data,defaults:e.defaults,formConfig:{fields:l||s.fields||[],...s,submitButton:!1,resetButton:!1}}),m=[{text:a,class:"btn-secondary",action:"cancel"},{text:n,class:"btn-primary",action:"submit"}],p=new x({title:t,body:u,size:i,centered:r,buttons:m,...d});return v._renderAndAwait(p,{buttons:m,onAction:async f=>{if(f==="cancel")return p.hide(),null;if(f!=="submit")return null;p.setLoading(!0,"Saving...");try{const g=await u.handleSubmit();if(g.success)return g;p.setLoading(!1);let b=g.error;return g.data?.error&&(b=g.data.error),p.getApp()?.toast?.error(b),!1}catch(g){return console.error("Modal.modelForm: error saving:",g),await p.setContent(u),u.showError(g.message||"An error occurred while saving"),!1}},cleanup:async()=>{try{await u.destroy()}catch{}}})}static async data(e={}){const{title:t="Data View",data:s={},model:i=null,fields:r=[],columns:n=2,responsive:a=!0,showEmptyValues:o=!1,emptyValueText:l="—",size:d="lg",centered:h=!0,closeText:u="Close",...m}=e,p=(await Promise.resolve().then(()=>Fs)).default,f=new p({data:s,model:i,fields:r,columns:n,responsive:a,showEmptyValues:o,emptyValueText:l}),g=[{text:u,class:"btn-secondary",value:"close"}],b=new x({title:t,body:f,size:d,centered:h,buttons:g,...m});return f.on("field:click",y=>b.emit("dataview:field:click",y)),f.on("error",y=>b.emit("dataview:error",y)),v._renderAndAwait(b,{buttons:g,cleanup:async()=>{try{await f.destroy()}catch{}}})}static async code(e={}){const{code:t="",language:s="javascript",title:i="Source Code",size:r="lg",...n}=e,a=new me({code:t,language:s}),o=[{text:"Copy to Clipboard",class:"btn-primary",icon:"bi-clipboard",action:"copy"},{text:"Close",class:"btn-secondary",dismiss:!0}],l=new x({title:i,body:a,size:r,scrollable:!0,buttons:o,...n});return v._renderAndAwait(l,{buttons:o,onAction:async d=>{if(d!=="copy")return null;if(!navigator.clipboard)return!1;try{await navigator.clipboard.writeText(t),v._showCopySuccess(l)}catch(h){console.error("Modal.code: clipboard write failed:",h)}return!1}})}static _showCopySuccess(e){const t=e.element?.querySelector('[data-action="copy"]');if(!t)return;const s=t.innerHTML;t.innerHTML='<i class="bi bi-check me-1"></i>Copied!',t.classList.remove("btn-primary"),t.classList.add("btn-success"),t.disabled=!0,setTimeout(()=>{t.innerHTML=s,t.classList.remove("btn-success"),t.classList.add("btn-primary"),t.disabled=!1},2e3)}static async htmlPreview(e={}){const{html:t=e.content||"",title:s="HTML Preview",size:i="lg",height:r=500,...n}=e,a=new Gt({html:t,height:r}),o=[{text:"Close",class:"btn-secondary",dismiss:!0}],l=new x({title:s,body:a,size:i,scrollable:!1,buttons:o,...n});return v._renderAndAwait(l,{buttons:o})}static async updateModelImage(e={},t={}){const s=e.upload||!1,i=t.name||e.field||"image",r={title:"Upload Your Avatar",model:null,autoSave:!s,size:"sm",fields:[{type:"image",name:i,size:"lg",imageSize:{width:200,height:200},placeholder:"Upload your image",...t}],...e},n=await v.form(r);if(!s||!n||!e.model)return n;const a=n[i];if(!a||!a.startsWith("data:"))return n;const o=a.split(","),d=o[0]?.match(/:(.*?);/)?.[1]||"image/png",h=atob(o[1]);let u=h.length;const m=new Uint8Array(u);for(;u--;)m[u]=h.charCodeAt(u);const p=d.split("/")[1]||"png",f=typeof window<"u"&&window.File||globalThis.File;if(!f)throw new Error("File API is not available in this environment");const g=new f([m],`${i}.${p}`,{type:d}),b=new pt;return await b.upload({file:g,name:`${i}.${p}`,description:e.uploadDescription||`${i} upload`,showToast:!0}),e.model.save({[i]:b.id})}static loading(e){ke.show(e)}static hideLoading(e){ke.hide(e)}static showBusy(e){return v.loading(e)}static hideBusy(e){return v.hideLoading(e)}}const N=Object.freeze(Object.defineProperty({__proto__:null,default:v},Symbol.toStringTag,{value:"Module"}));class ve{constructor(e={}){this.config=e,this.initPluginRegistry(),this.name=e.name||"MOJO App",this.version=e.version||"1.0.0",this.debug=e.debug||!1,this.container=e.container||"#app",this.layoutType=e.layout||"portal",this.layoutConfig=e.layoutConfig||{},e.sidebar&&(this.layoutConfig.sidebarConfig=e.sidebar),e.topbar&&(this.layoutConfig.topbarConfig=e.topbar),this.layout=null,this.layoutConfig.containerId=this.container||this.containerId||"#app",this.pageContainer=e.pageContainer||"#page-container",this.basePath=e.basePath||"",this.routerMode=e.routerMode||e.router?.mode||"param",this.basePath=e.basePath||e.router?.base||"",this.defaultRoute=e.defaultRoute||"home",this.session=e.session||{},this.router=null,this.navigation=e.navigation||{},this.state={currentPage:null,previousPage:null,loading:!1},this.events=new Vt,this.rest=ne,this.modal=v,e.api&&this.rest.configure(e.api);const t=(this.name||"mojo").replace(/\s+/g,"_").toLowerCase();this.theme=new Nt({storageKey:`${t}:theme`,eventBus:this.events}),this.theme.init(),this.router=new Te({mode:this.routerMode==="param"?"params":this.routerMode,basePath:this.basePath,defaultRoute:this.defaultRoute,eventEmitter:this.events}),this.events.on("route:changed",async s=>{const{pageName:i,params:r,query:n}=s;await this.showPage(i,n,r,{fromRouter:!0})}),typeof window<"u"&&(window.MOJO=window.MOJO||{},window.MOJO.router=this.router),this.setupFocusTracking(),this.pageCache=new Map,this.pageClasses=new Map,this.componentClasses=new Map,this.modelClasses=new Map,this.modelRefClasses=new Map,this.currentPage=null,this.isStarted=!1,window.matchUUID?window[window.matchUUID]=this:window.MOJO?window.MOJO.app=this:window.__app__=this}async start(){if(this.isStarted){console.warn("WebApp already started");return}try{this.setupPageContainer(),this.validateDefaultRoute(),await this.setupRouter(),this.isStarted=!0,this.router.allowPopState=!1,this.events.emit("app:ready",{app:this})}catch(e){throw console.error(`Failed to start ${this.name}:`,e),this.showError("Failed to start application"),e}}async setupRouter(){if(!this.router){console.error("Router not initialized");return}this.events.on("route:notfound",async e=>{console.warn(`Route not found: ${e.path}`),this._show404(e.path)}),this.router.start(),console.log(`Router started in ${this.routerMode} mode`)}setupPageContainer(){const e=typeof this.container=="string"?document.querySelector(this.container):this.container;e&&!e.querySelector("#page-container")&&(e.innerHTML='<div id="page-container"></div>'),this.pageContainer="#page-container"}registerPage(e,t,s={}){if(typeof e!="string"||!e)return console.error("registerPage: pageName must be a non-empty string"),this;if(typeof t!="function")return console.error("registerPage: PageClass must be a constructor function"),this;if(s.containerId||(s.containerId=this.pageContainer),this.pageClasses.set(e,{PageClass:t,constructorOptions:s}),this.router){let i=s.route||`/${e}`;i.startsWith("/")||(i=`/${i}`),s.route=i,this.router.addRoute(i,e)}return this}getPage(e){return this.pageCache.get(e)}getPagePermissions(e){if(this.pageCache.has(e))return this.pageCache.get(e).permissions;const t=this.pageClasses.get(e);if(!t)return null;const{PageClass:s,constructorOptions:i}=t;return i?i.permissions:null}getOrCreatePage(e){if(this.pageCache.has(e))return this.pageCache.get(e);const t=this.pageClasses.get(e);if(!t)return console.error(`Page not registered: ${e}`),null;const{PageClass:s,constructorOptions:i}=t;try{const r={pageName:e,...i,app:this},n=new s(r);return i.route&&(n.route=i.route),this.pageCache.set(e,n),console.log(`Created page: ${e} with route: ${n.route}`),n}catch(r){return console.error(`Failed to create page ${e}:`,r),null}}async showPage(e,t={},s={},i={}){const{fromRouter:r=!1,replace:n=!1,force:a=!1}=i;try{let o,l;typeof e=="string"?(l=e,o=this.getOrCreatePage(e)):e&&typeof e=="object"&&(o=e,l=e.pageName);const d=this.currentPage;if(!o){this._show404(l,s,t,r);return}if(this.events.emit("page:showing",{page:o,pageName:o.pageName,params:s,query:t,fromRouter:r}),!o.canEnter()){this._showDeniedPage(o,s,t,r);return}d&&d!==o&&await this._exitOldPage(d),await o.onParams(s,t),d!==o&&await o.onEnter(),o.syncUrl(),this.events.emit("page:show",{page:o,pageName:o.pageName,params:s,query:t,fromRouter:r}),await o.render(),this.currentPage=o,console.log(`✅ Showing page: ${o.pageName}`,{query:t,params:s})}catch(o){console.error("Error in showPage:",o),this.showError(`Failed to load page: ${o.message}`),e!=="error"&&await this.showPage("error",{},{error:o,originalPage:e},{fromRouter:r})}}async _show404(e,t,s,i){const r=this.getOrCreatePage("404");r&&(r.setInfo&&r.setInfo(e),await this._exitOldPage(this.currentPage),await r.render(),this.currentPage=r,this.events.emit("page:404",{page:null,pageName:e,params:t,query:s,fromRouter:i}))}async _showDeniedPage(e,t,s,i){const r=this.getOrCreatePage("denied");r.setDeniedPage&&r.setDeniedPage(e),await this._exitOldPage(this.currentPage),await r.render(),this.currentPage=r,this.events.emit("page:denied",{page:e,pageName:e.pageName,params:t,query:s,fromRouter:i})}async _exitOldPage(e){if(e)try{await e.onExit(),await e.unmount(),this.events.emit("page:hide",{page:e})}catch(t){console.error(`Error exiting page ${e.pageName}:`,t)}}async navigate(e,t={},s={}){if(!this.router){console.error("Router not initialized");return}let i=e;if(Object.keys(t).length>0){const r=new URLSearchParams(t).toString();i+=(e.includes("?")?"&":"?")+r}return await this.router.navigate(i,s)}async navigateToDefault(e={}){return await this.showPage(this.defaultRoute,{},{},e)}back(){this.router?this.router.back():console.warn("Router not initialized")}forward(){this.router?this.router.forward():console.warn("Router not initialized")}getCurrentPage(){return this.currentPage}getPageContainer(){return this.layout&&this.layout.getPageContainer?this.layout.getPageContainer():typeof this.pageContainer=="string"?document.querySelector(this.pageContainer):this.pageContainer}async showError(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Error",{size:"md",type:"error"})}catch(t){this.events.emit("notification",{message:e,type:"error"}),typeof window<"u"&&window?.console&&console.error("[WebApp] showError fallback:",t),typeof window<"u"&&alert(`Error: ${e}`)}}async showSuccess(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Success",{size:"md",type:"success"})}catch(t){this.events.emit("notification",{message:e,type:"success"}),typeof window<"u"&&window?.console&&console.warn("[WebApp] showSuccess fallback:",t),typeof window<"u"&&alert(`Success: ${e}`)}}async showInfo(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Information",{size:"md",type:"info"})}catch(t){this.events.emit("notification",{message:e,type:"info"}),typeof window<"u"&&window?.console&&console.info("[WebApp] showInfo fallback:",t),typeof window<"u"&&alert(`Info: ${e}`)}}async showWarning(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Warning",{size:"md",type:"warning"})}catch(t){this.events.emit("notification",{message:e,type:"warning"}),typeof window<"u"&&window?.console&&console.warn("[WebApp] showWarning fallback:",t),typeof window<"u"&&alert(`Warning: ${e}`)}}showNotification(e,t="info"){this.events.emit("notification",{message:e,type:t})}async showLoading(e={}){typeof e=="string"&&(e={message:e});try{(await Promise.resolve().then(()=>N)).default.showBusy(e)}catch(t){typeof window<"u"&&window?.console&&console.warn("[WebApp] showLoading fallback:",t,e),this.events.emit("notification",{message:e.message||"Loading...",type:"info"})}}async hideLoading(){try{(await Promise.resolve().then(()=>N)).default.hideBusy()}catch(e){typeof window<"u"&&window?.console&&console.warn("[WebApp] hideLoading fallback:",e)}}async showModelView(e,t={}){try{return await(await Promise.resolve().then(()=>N)).default.showModelView(e,t)}catch(s){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showModelForm failed:",s),s}}async showModelForm(e={}){try{return await(await Promise.resolve().then(()=>N)).default.modelForm(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showModelForm failed:",t),t}}async showForm(e={}){try{return await(await Promise.resolve().then(()=>N)).default.form(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showForm failed:",t),t}}async showDialog(e={}){try{return await(await Promise.resolve().then(()=>N)).default.dialog(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showDialog failed:",t),t}}async showAlert(e={}){try{return await(await Promise.resolve().then(()=>N)).default.dialog(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showDialog failed:",t),t}}async confirm(e,t="Confirm",s={}){return await(await Promise.resolve().then(()=>N)).default.confirm(e,t,s)}setTheme(e){return this.theme.set(e),this}getTheme(){return this.theme.getPreference()}getResolvedTheme(){return this.theme.getResolved()}setupFocusTracking(){if(typeof window>"u")return;this.isFocused=!document.hidden;const e=()=>{const i=this.isFocused;this.isFocused=!document.hidden,i!==this.isFocused&&(this.isFocused?this.events.emit("browser:focus"):this.events.emit("browser:blur"))},t=()=>{this.isFocused||(this.isFocused=!0,this.events.emit("browser:focus"))},s=()=>{this.isFocused&&(this.isFocused=!1,this.events.emit("browser:blur"))};document.addEventListener("visibilitychange",e),window.addEventListener("focus",t),window.addEventListener("blur",s),this._focusHandlers={visibilitychange:e,focus:t,blur:s}}setupErrorHandling(){window.addEventListener("error",e=>{console.error("Global error:",e.error),this.debug&&this.showError(`Error: ${e.error?.message||"Unknown error"}`)}),window.addEventListener("unhandledrejection",e=>{console.error("Unhandled promise rejection:",e.reason),this.debug&&this.showError(`Promise rejected: ${e.reason?.message||"Unknown error"}`)})}escapeHtml(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}getState(e){return e?this.state[e]:this.state}setState(e){const t={...this.state};Object.assign(this.state,e),this.events.emit("state:changed",{oldState:t,newState:this.state,updates:e})}registerComponent(e,t){this.componentClasses.set(e,t)}getComponent(e){return this.componentClasses.get(e)}registerModel(e,t){this.modelClasses.set(e,t)}getModel(e){return this.modelClasses.get(e)}registerModelRef(e,t){this.modelRefClasses.set(e,t)}getModelByRef(e){return this.modelRefClasses.get(e)}setupRest(){this.rest=ne,ne.configure(this.api)}async destroy(){console.log("Destroying WebApp..."),this.router&&this.router.stop(),this._focusHandlers&&typeof window<"u"&&(document.removeEventListener("visibilitychange",this._focusHandlers.visibilitychange),window.removeEventListener("focus",this._focusHandlers.focus),window.removeEventListener("blur",this._focusHandlers.blur));const e=Array.from(this.pageCache.values());if(await Promise.allSettled(e.map(async t=>{try{t.destroy&&await t.destroy()}catch(s){console.error("Error destroying page:",s)}})),this.layout&&this.layout.destroy)try{await this.layout.destroy()}catch(t){console.error("Error destroying layout:",t)}this.pageCache.clear(),this.pageClasses.clear(),this.componentClasses.clear(),this.modelClasses.clear(),typeof window<"u"&&window.MOJO&&delete window.MOJO.router,this.isStarted=!1,console.log(`✨ ${this.name} destroyed`)}buildPagePath(e,t,s){let i=e.route||`/${e.pageName.toLowerCase()}`;if(Object.keys(t).forEach(r=>{(typeof t[r]=="string"||typeof t[r]=="number")&&(i=i.replace(`:${r}`,t[r]))}),s&&Object.keys(s).length>0){const r=new URLSearchParams(s).toString();i+=(i.includes("?")?"&":"?")+r}return i}validateDefaultRoute(){this.pageClasses.has(this.defaultRoute)?console.log(`✅ Default route '${this.defaultRoute}' is registered`):(console.warn(`⚠️ Default route '${this.defaultRoute}' is not registered!`),console.warn(` Please register a page: app.registerPage('${this.defaultRoute}', YourPageClass);`),console.warn(" Or change default route: new WebApp({ defaultRoute: 'your-page' });"))}findFallbackPage(){const e=["404","error","denied"];for(const[t]of this.pageClasses.entries())if(!e.includes(t))return t;return null}static create(e={}){return new ve(e)}initPluginRegistry(){typeof window<"u"&&(window.MOJO||(window.MOJO={}),window.MOJO.plugins||(window.MOJO.plugins={}),window.MOJO.app=this)}static registerPlugin(e,t){typeof window<"u"&&(window.MOJO||(window.MOJO={}),window.MOJO.plugins||(window.MOJO.plugins={}),window.MOJO.plugins[e]=t,console.debug(`MOJO Plugin registered: ${e}`))}}class pe extends S{constructor(e={}){e.tagName=e.tagName||"main",e.className=e.className||"mojo-page";const t=e.pageName||"";t&&!e.id&&(e.id="page_"+t.toLowerCase().replace(/\s+/g,"_")),super(e),this.pageName=e.pageName||this.constructor.pageName||"",this.route=e.route||this.constructor.route||"",this.title=e.title||this.pageName||"",!this.id&&this.constructor.pageName&&!e.pageName&&(this.id="page_"+this.constructor.pageName.toLowerCase().replace(/\s+/g,"_")),this.pageIcon=e.icon||e.pageIcon||this.constructor.pageIcon||"bi bi-file-text",this.displayName=e.displayName||this.constructor.displayName||this.pageName||"",this.pageDescription=e.pageDescription||this.constructor.pageDescription||"",this.params={},this.query={},this.matched=!1,this.isActive=!1,this.pageOptions={title:e.title||this.pageName||"Untitled Page",description:e.description||"",requiresAuth:e.requiresAuth||!1,...e.pageOptions},this.savedState=null,console.log(`Page ${this.pageName} constructed with route: ${this.route}`)}async onParams(e={},t={}){this.params=e,this.query=t}canEnter(){if(this.options.permissions){const e=this.getApp().activeUser;if(!e||!e.hasPermission(this.options.permissions))return!1}return!(this.options.requiresGroup&&!this.getApp().activeGroup)}async onEnter(){this.isActive=!0,this._wasExited=!1,await this.onInitView(),this.savedState&&(this.restoreState(this.savedState),this.savedState=null),this.pageOptions&&this.pageOptions.title&&typeof document<"u"&&(document.title=this.pageOptions.title),this.emit("activated",{page:this.getMetadata()}),console.log(`Page ${this.pageName} entered`)}async onExit(){this.savedState=this.captureState(),this.isActive=!1,this._wasExited=!0,this._clearScheduledRefreshes(),this.emit("deactivated",{page:this.getMetadata()}),console.log(`Page ${this.pageName} exiting`)}scheduleRefresh(e,t,s={}){if(this._scheduledRefreshes||(this._scheduledRefreshes=[]),typeof e!="function"||!(t>0))return null;const i=async()=>{try{await e()}catch(a){console.warn(`[Page ${this.pageName}] scheduleRefresh handler error:`,a)}};s.immediate&&i();const r=setInterval(i,t),n={id:r,tier:s.tier||null,handler:i,intervalMs:t};return this._scheduledRefreshes.push(n),{cancel:()=>{clearInterval(r),this._scheduledRefreshes=(this._scheduledRefreshes||[]).filter(a=>a!==n)}}}async runScheduledRefreshes(e=null){const t=this._scheduledRefreshes||[],s=e?t.filter(i=>i.tier===e):t;await Promise.allSettled(s.map(i=>i.handler()))}_clearScheduledRefreshes(){if(this._scheduledRefreshes){for(const e of this._scheduledRefreshes)clearInterval(e.id);this._scheduledRefreshes=[]}}async render(e=!0,t=null){return this._wasExited&&!this.isActive?this:super.render(e,t)}async onGroupChange(e){}getMetadata(){return{name:this.pageName,displayName:this.displayName||this.pageName,icon:this.pageIcon,description:this.pageDescription,route:this.route,isActive:this.isActive}}async onActionDefault(e){console.log(`Default action '${e}' triggered on page: ${this.pageName}`)}async makeActive(){this.getApp().showPage(this)}async onActionNavigate(e,t){e.preventDefault();const s=t.dataset.page;this.getApp().showPage(s)}captureState(){return this.element?{scrollTop:this.element.scrollTop,formData:this.captureFormData(),custom:this.captureCustomState()}:null}restoreState(e){!e||!this.element||(this.element.scrollTop=e.scrollTop||0,this.restoreFormData(e.formData),e.custom&&this.restoreCustomState(e.custom))}captureFormData(){const e={};return this.element&&this.element.querySelectorAll("input, select, textarea").forEach(t=>{t.name&&(t.type==="checkbox"?e[t.name]=t.checked:t.type==="radio"?t.checked&&(e[t.name]=t.value):e[t.name]=t.value)}),e}restoreFormData(e){!e||!this.element||Object.entries(e).forEach(([t,s])=>{const i=this.element.querySelector(`[name="${t}"]`);if(i)if(i.type==="checkbox")i.checked=s;else if(i.type==="radio"){const r=this.element.querySelector(`[name="${t}"][value="${s}"]`);r&&(r.checked=!0)}else i.value=s})}captureCustomState(){return{}}restoreCustomState(e){}setMeta(e={}){if(!(typeof document>"u")){if(e.title&&(document.title=e.title,this.pageOptions.title=e.title),e.description){let t=document.querySelector('meta[name="description"]');t||(t=document.createElement("meta"),t.name="description",document.head.appendChild(t)),t.content=e.description,this.pageOptions.description=e.description}Object.entries(e).forEach(([t,s])=>{if(t!=="title"&&t!=="description"){let i=document.querySelector(`meta[name="${t}"]`);i||(i=document.createElement("meta"),i.name=t,document.head.appendChild(i)),i.content=s}})}}showError(e){if(super.showError(e),this.element){const t=document.createElement("div");t.className="alert alert-danger alert-dismissible fade show",t.innerHTML=`
219
219
  ${e}
220
220
  <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
221
221
  `,this.element.insertBefore(t,this.element.firstChild),setTimeout(()=>{t.parentNode&&t.parentNode.removeChild(t)},5e3)}}showSuccess(e){if(super.showSuccess(e),this.element){const t=document.createElement("div");t.className="alert alert-success alert-dismissible fade show",t.innerHTML=`
@@ -660,14 +660,14 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
660
660
  </div>
661
661
  </div>
662
662
  </div>
663
- `}buildFieldHTML(e){const{type:t,columns:s,class:i=""}=e;let r="";const n=X&&typeof X.getRenderer=="function"?X.getRenderer(t):null;if(typeof n=="function")try{const d=n(this,e);d!=null&&(r=String(d))}catch(d){console.error("FormPlugins custom renderer error:",d)}if(!r)switch(t){case"text":r=this.renderTextField(e);break;case"email":r=this.renderEmailField(e);break;case"password":r=this.renderPasswordField(e);break;case"number":r=this.renderNumberField(e);break;case"tel":r=this.renderTelField(e);break;case"url":r=this.renderUrlField(e);break;case"search":r=this.renderSearchField(e);break;case"hex":r=this.renderHexField(e);break;case"textarea":r=this.renderTextareaField(e);break;case"htmlpreview":r=this.renderHtmlPreviewField(e);break;case"json":r=this.renderJsonField(e);break;case"select":r=this.renderSelectField(e);break;case"multiselect":r=this.renderMultiSelectField(e);break;case"checkbox":r=this.renderCheckboxField(e);break;case"toggle":case"switch":r=this.renderSwitchField(e);break;case"radio":r=this.renderRadioField(e);break;case"date":r=this.renderDateField(e);break;case"datetime":r=this.renderDateTimeField(e);break;case"time":r=this.renderTimeField(e);break;case"file":r=this.renderFileField(e);break;case"image":r=this.renderImageField(e);break;case"color":r=this.renderColorField(e);break;case"range":r=this.renderRangeField(e);break;case"hidden":r=this.renderHiddenField(e);break;case"button":r=this.renderButton(e);break;case"divider":r=this.renderDivider(e);break;case"html":r=this.renderHtmlField(e);break;case"heading":case"header":r=this.renderHeaderField(e);break;case"tag":case"tags":r=this.renderTagField(e);break;case"collection":r=this.renderCollectionField(e);break;case"collectionmultiselect":case"collection-multiselect":r=this.renderCollectionMultiSelectField(e);break;case"datepicker":r=this.renderDatePickerField(e);break;case"monthpicker":r=this.renderDatePickerField({...e,precision:"month"});break;case"yearpicker":r=this.renderDatePickerField({...e,precision:"year"});break;case"daterange":r=this.renderDateRangeField(e);break;case"monthrange":r=this.renderDateRangeField({...e,precision:"month"});break;case"yearrange":r=this.renderDateRangeField({...e,precision:"year"});break;case"timepicker":r=this.renderTimePickerField(e);break;case"datetimepicker":r=this.renderDateTimePickerField(e);break;case"checklistdropdown":r=this.renderChecklistDropdownField(e);break;case"buttongroup":r=this.renderButtonGroupField(e);break;case"combo":case"combobox":case"autocomplete":r=this.renderComboField(e);break;case"tabset":r=this.renderTabsetField(e);break;default:console.warn(`Unknown field type: ${t}`),r=this.renderTextField(e)}let a;if(this.isAutoSizingField(e))a=`col ${i}`.trim();else if(typeof s=="object"&&s!==null){const d=[];s.xs&&d.push(`col-${s.xs}`),s.sm&&d.push(`col-sm-${s.sm}`),s.md&&d.push(`col-md-${s.md}`),s.lg&&d.push(`col-lg-${s.lg}`),s.xl&&d.push(`col-xl-${s.xl}`),s.xxl&&d.push(`col-xxl-${s.xxl}`),d.length===0&&d.push("col-12"),i&&d.push(i),a=d.join(" ")}else a=`col-${s} ${i}`.trim();let o="",l="";if(e.showWhen){const d=e.showWhen,h=Array.isArray(d.value)?d.value:[d.value];o=` data-show-when-field="${d.field}" data-show-when-value="${h.join(",")}"`,d.negate&&(o+=' data-show-when-negate="true"');let u=this.data[d.field];if(u==null){const g=this._findField(d.field,this.fields);g&&(u=g.value)}const m=String(u??""),p=h.map(String).includes(m);(d.negate?!p:p)||(l=' style="display:none"')}return`<div class="${a}"${o}${l}>${r}</div>`}_findField(e,t){for(const s of t){if(s.name===e)return s;if(s.fields){const i=this._findField(e,s.fields);if(i)return i}if(s.tabs){for(const i of s.tabs)if(i.fields){const r=this._findField(e,i.fields);if(r)return r}}}return null}getFieldId(e){return e?`field_${e.replace(/[.\s\[\]]/g,"_")}`:`field_${Math.random().toString(36).substr(2,9)}`}renderTextField(e){return this.renderInputField(e,"text")}renderEmailField(e){return this.renderInputField(e,"email")}renderPasswordField(e){const t=e.passwordUsage||"current",s=t==="new"||t==="new-password"?"new-password":"current-password",i={...e.attributes||{},autocomplete:e.attributes&&e.attributes.autocomplete||s};return this.renderInputField({...e,showToggle:e.showToggle!==!1,attributes:i},"password")}renderNumberField(e){const{min:t,max:s,step:i=1,...r}=e,n=[];return t!==void 0&&n.push(`min="${t}"`),s!==void 0&&n.push(`max="${s}"`),i!==void 0&&n.push(`step="${i}"`),this.renderInputField({...r,attributes:{...r.attributes,...n.reduce((a,o)=>{const[l,d]=o.split("=");return a[l]=d.replace(/"/g,""),a},{})}},"number")}renderTelField(e){return this.renderInputField(e,"tel")}renderUrlField(e){return this.renderInputField(e,"url")}renderSearchField(e){const t={...e,attributes:{"data-filter":"live-search","data-change-action":"filter-search","data-filter-debounce":e.debounce||"300",...e.attributes}};return this.renderInputField(t,"search")}renderHexField(e){const{hexType:t="color",allowPrefix:s=!0,minLength:i,maxLength:r,...n}=e;let a,o,l,d,h;switch(t){case"color":a=s?"^#?[0-9A-Fa-f]{6}$":"^[0-9A-Fa-f]{6}$",o=6,l=s?7:6,d=s?"#FF0000":"FF0000",h=h||"Enter a valid hex color (e.g., "+d+")";break;case"color-short":a=s?"^#?[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$":"^[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$",o=s?4:3,l=s?7:6,d=s?"#F00 or #FF0000":"F00 or FF0000",h=h||"Enter a valid hex color (3 or 6 digits)";break;case"string":a="^[0-9A-Fa-f]+$",o=i||1,l=r||64,d="ABCDEF123456",h=h||"Only hexadecimal characters (0-9, A-F) allowed";break;default:a=s?"^#?[0-9A-Fa-f]+$":"^[0-9A-Fa-f]+$",o=i||1,l=r||64,d=s?"#ABCDEF or ABCDEF":"ABCDEF",h=h||"Enter hexadecimal characters only"}const u={...n,pattern:a,minLength:o,maxLength:l,placeholder:n.placeholder||d,help:n.help||h,attributes:{"data-hex-type":t,"data-allow-prefix":s,style:"text-transform: uppercase;",...n.attributes}};return this.renderInputField(u,"text")}renderInputField(e,t="text"){const{name:s,label:i,value:r="",placeholder:n="",required:a=!1,disabled:o=!1,readonly:l=!1,class:d="",attributes:h={},help:u=e.helpText||e.help||""}=e,m=`${this.options.inputClass} ${d}`.trim(),p=this.errors[s],f=this.getFieldValue(s)??r,g=Object.entries(h).map(([C,_])=>`${C}="${this.escapeHtml(_)}"`).join(" "),b=this.getFieldId(s),y={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:b,name:s,type:t,fieldValue:f,label:i||null,placeholder:n||null,help:u||null,tooltip:e.tooltip||null,error:p||null,required:a,disabled:o,readonly:l,attrs:g,showCopy:!!e.showCopy};if(t==="password"&&(e.showToggle||e.strengthMeter||e.capsLockWarning)){const C={...y,showToggle:!!e.showToggle,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,C)}if(t==="password"){const C={...y,showToggle:e.showToggle!==!1,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,C)}return D.render(this.templates.input,y)}renderTextareaField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,rows:l=3,cols:d,class:h="",attributes:u={},help:m=e.helpText||e.help||""}=e,p=`${this.options.inputClass} ${h}`.trim(),f=this.errors[t],g=this.getFieldValue(t)??i,b=Object.entries(u).map(([_,A])=>`${_}="${this.escapeHtml(A)}"`).join(" "),y=this.getFieldId(t),C={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:y,name:t,fieldValue:g,label:s||null,placeholder:r||null,help:m||null,tooltip:e.tooltip||null,error:f||null,rows:l||3,required:n,disabled:a,readonly:o,showCopy:!!e.showCopy,attrs:b};return D.render(this.templates.textarea,C)}renderHtmlPreviewField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,rows:l=5,class:d="",attributes:h={},help:u=e.helpText||e.help||""}=e,m=`${this.options.inputClass} ${d}`.trim(),p=this.errors[t],f=this.getFieldValue(t)??i,g=Object.entries(h).map(([C,_])=>`${C}="${this.escapeHtml(_)}"`).join(" "),b=this.getFieldId(t),y={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:b,name:t,fieldValue:f,label:s||null,placeholder:r||null,help:u||null,tooltip:e.tooltip||null,error:p||null,rows:l||5,required:n,disabled:a,readonly:o,attrs:g,showCopy:!!e.showCopy};return D.render(this.templates.htmlpreview,y)}renderJsonField(e){const{name:t,label:s,placeholder:i="",required:r=!1,disabled:n=!1,readonly:a=!1,rows:o=3,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=this.getFieldValue(e.name)??e.value??{};let m=u;if(typeof u=="object"&&u!==null)try{m=JSON.stringify(u,null,2)}catch{m="{}"}else typeof u!="string"&&(m=String(u));const p=`${this.options.inputClass} ${l}`.trim(),f=this.errors[t],g=this.getFieldId(t),b=Object.entries({...d,"data-field-type":"json"}).map(([C,_])=>`${C}="${this.escapeHtml(_)}"`).join(" "),y={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,fieldValue:m,label:s||null,placeholder:i||null,help:h||null,tooltip:e.tooltip||null,error:f||null,rows:o||3,required:r,disabled:n,readonly:a,attrs:b};return D.render(this.templates.textarea,y)}renderSelectField(e){const{name:t,label:s,options:i=[],value:r="",required:n=!1,disabled:a=!1,multiple:o=!1,searchable:l=!1,class:d="",attributes:h={},help:u=e.helpText||e.help||"",start:m=e.start,end:p=e.end,step:f=e.step,format:g=e.format,prefix:b=e.prefix,suffix:y=e.suffix}=e,C=`form-select ${d}`.trim(),_=this.errors[t],F=this.getFieldValue(t)??r,j=Object.entries(h).map(([I,z])=>`${I}="${this.escapeHtml(z)}"`).join(" "),M=this.getFieldId(t);let R=[...i];if(m!==void 0&&p!==void 0){const I=f!==void 0?f:1,z=this.generateSelectOptions(m,p,I,{format:g,prefix:b,suffix:y});R=[...R,...z]}let oe="";Array.isArray(R)&&(oe=R.map(I=>{if(typeof I=="string"){const z=I===F?"selected":"";return`<option value="${this.escapeHtml(I)}" ${z}>${this.escapeHtml(I)}</option>`}else if(I&&typeof I=="object"){const z=I.value==F?"selected":"";return`<option value="${this.escapeHtml(I.value)}" ${z}>${this.escapeHtml(I.label||I.text||I.value)}</option>`}return""}).join(""));const be=l?`
663
+ `}buildFieldHTML(e){const{type:t,columns:s,class:i=""}=e;let r="";const n=X&&typeof X.getRenderer=="function"?X.getRenderer(t):null;if(typeof n=="function")try{const d=n(this,e);d!=null&&(r=String(d))}catch(d){console.error("FormPlugins custom renderer error:",d)}if(!r)switch(t){case"text":r=this.renderTextField(e);break;case"email":r=this.renderEmailField(e);break;case"password":r=this.renderPasswordField(e);break;case"number":r=this.renderNumberField(e);break;case"tel":r=this.renderTelField(e);break;case"url":r=this.renderUrlField(e);break;case"search":r=this.renderSearchField(e);break;case"hex":r=this.renderHexField(e);break;case"textarea":r=this.renderTextareaField(e);break;case"htmlpreview":r=this.renderHtmlPreviewField(e);break;case"json":r=this.renderJsonField(e);break;case"select":r=this.renderSelectField(e);break;case"multiselect":r=this.renderMultiSelectField(e);break;case"checkbox":r=this.renderCheckboxField(e);break;case"toggle":case"switch":r=this.renderSwitchField(e);break;case"radio":r=this.renderRadioField(e);break;case"date":r=this.renderDateField(e);break;case"datetime":r=this.renderDateTimeField(e);break;case"time":r=this.renderTimeField(e);break;case"file":r=this.renderFileField(e);break;case"image":r=this.renderImageField(e);break;case"color":r=this.renderColorField(e);break;case"range":r=this.renderRangeField(e);break;case"hidden":r=this.renderHiddenField(e);break;case"button":r=this.renderButton(e);break;case"divider":r=this.renderDivider(e);break;case"html":r=this.renderHtmlField(e);break;case"heading":case"header":r=this.renderHeaderField(e);break;case"tag":case"tags":r=this.renderTagField(e);break;case"collection":r=this.renderCollectionField(e);break;case"collectionmultiselect":case"collection-multiselect":r=this.renderCollectionMultiSelectField(e);break;case"datepicker":r=this.renderDatePickerField(e);break;case"monthpicker":r=this.renderDatePickerField({...e,precision:"month"});break;case"yearpicker":r=this.renderDatePickerField({...e,precision:"year"});break;case"daterange":r=this.renderDateRangeField(e);break;case"monthrange":r=this.renderDateRangeField({...e,precision:"month"});break;case"yearrange":r=this.renderDateRangeField({...e,precision:"year"});break;case"timepicker":r=this.renderTimePickerField(e);break;case"datetimepicker":r=this.renderDateTimePickerField(e);break;case"checklistdropdown":r=this.renderChecklistDropdownField(e);break;case"buttongroup":r=this.renderButtonGroupField(e);break;case"combo":case"combobox":case"autocomplete":r=this.renderComboField(e);break;case"tabset":r=this.renderTabsetField(e);break;default:console.warn(`Unknown field type: ${t}`),r=this.renderTextField(e)}let a;if(this.isAutoSizingField(e))a=`col ${i}`.trim();else if(typeof s=="object"&&s!==null){const d=[];s.xs&&d.push(`col-${s.xs}`),s.sm&&d.push(`col-sm-${s.sm}`),s.md&&d.push(`col-md-${s.md}`),s.lg&&d.push(`col-lg-${s.lg}`),s.xl&&d.push(`col-xl-${s.xl}`),s.xxl&&d.push(`col-xxl-${s.xxl}`),d.length===0&&d.push("col-12"),i&&d.push(i),a=d.join(" ")}else a=`col-${s} ${i}`.trim();let o="",l="";if(e.showWhen){const d=e.showWhen,h=Array.isArray(d.value)?d.value:[d.value];o=` data-show-when-field="${d.field}" data-show-when-value="${h.join(",")}"`,d.negate&&(o+=' data-show-when-negate="true"');let u=this.data[d.field];if(u==null){const g=this._findField(d.field,this.fields);g&&(u=g.value)}const m=String(u??""),p=h.map(String).includes(m);(d.negate?!p:p)||(l=' style="display:none"')}return`<div class="${a}"${o}${l}>${r}</div>`}_findField(e,t){for(const s of t){if(s.name===e)return s;if(s.fields){const i=this._findField(e,s.fields);if(i)return i}if(s.tabs){for(const i of s.tabs)if(i.fields){const r=this._findField(e,i.fields);if(r)return r}}}return null}getFieldId(e){return e?`field_${e.replace(/[.\s\[\]]/g,"_")}`:`field_${Math.random().toString(36).substr(2,9)}`}renderTextField(e){return this.renderInputField(e,"text")}renderEmailField(e){return this.renderInputField(e,"email")}renderPasswordField(e){const t=e.passwordUsage||"current",s=t==="new"||t==="new-password"?"new-password":"current-password",i={...e.attributes||{},autocomplete:e.attributes&&e.attributes.autocomplete||s};return this.renderInputField({...e,showToggle:e.showToggle!==!1,attributes:i},"password")}renderNumberField(e){const{min:t,max:s,step:i=1,...r}=e,n=[];return t!==void 0&&n.push(`min="${t}"`),s!==void 0&&n.push(`max="${s}"`),i!==void 0&&n.push(`step="${i}"`),this.renderInputField({...r,attributes:{...r.attributes,...n.reduce((a,o)=>{const[l,d]=o.split("=");return a[l]=d.replace(/"/g,""),a},{})}},"number")}renderTelField(e){return this.renderInputField(e,"tel")}renderUrlField(e){return this.renderInputField(e,"url")}renderSearchField(e){const t={...e,attributes:{"data-filter":"live-search","data-change-action":"filter-search","data-filter-debounce":e.debounce||"300",...e.attributes}};return this.renderInputField(t,"search")}renderHexField(e){const{hexType:t="color",allowPrefix:s=!0,minLength:i,maxLength:r,...n}=e;let a,o,l,d,h;switch(t){case"color":a=s?"^#?[0-9A-Fa-f]{6}$":"^[0-9A-Fa-f]{6}$",o=6,l=s?7:6,d=s?"#FF0000":"FF0000",h=h||"Enter a valid hex color (e.g., "+d+")";break;case"color-short":a=s?"^#?[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$":"^[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$",o=s?4:3,l=s?7:6,d=s?"#F00 or #FF0000":"F00 or FF0000",h=h||"Enter a valid hex color (3 or 6 digits)";break;case"string":a="^[0-9A-Fa-f]+$",o=i||1,l=r||64,d="ABCDEF123456",h=h||"Only hexadecimal characters (0-9, A-F) allowed";break;default:a=s?"^#?[0-9A-Fa-f]+$":"^[0-9A-Fa-f]+$",o=i||1,l=r||64,d=s?"#ABCDEF or ABCDEF":"ABCDEF",h=h||"Enter hexadecimal characters only"}const u={...n,pattern:a,minLength:o,maxLength:l,placeholder:n.placeholder||d,help:n.help||h,attributes:{"data-hex-type":t,"data-allow-prefix":s,style:"text-transform: uppercase;",...n.attributes}};return this.renderInputField(u,"text")}renderInputField(e,t="text"){const{name:s,label:i,value:r="",placeholder:n="",required:a=!1,disabled:o=!1,readonly:l=!1,class:d="",attributes:h={},help:u=e.helpText||e.help||""}=e,m=`${this.options.inputClass} ${d}`.trim(),p=this.errors[s],f=this.getFieldValue(s)??r,g=Object.entries(h).map(([C,_])=>`${C}="${this.escapeHtml(_)}"`).join(" "),b=this.getFieldId(s),y={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:b,name:s,type:t,fieldValue:f,label:i||null,placeholder:n||null,help:u||null,tooltip:e.tooltip||null,error:p||null,required:a,disabled:o,readonly:l,attrs:g,showCopy:!!e.showCopy};if(t==="password"&&(e.showToggle||e.strengthMeter||e.capsLockWarning)){const C={...y,showToggle:!!e.showToggle,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,C)}if(t==="password"){const C={...y,showToggle:e.showToggle!==!1,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,C)}return D.render(this.templates.input,y)}renderTextareaField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,rows:l=3,cols:d,class:h="",attributes:u={},help:m=e.helpText||e.help||""}=e,p=`${this.options.inputClass} ${h}`.trim(),f=this.errors[t],g=this.getFieldValue(t)??i,b=Object.entries(u).map(([_,A])=>`${_}="${this.escapeHtml(A)}"`).join(" "),y=this.getFieldId(t),C={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:y,name:t,fieldValue:g,label:s||null,placeholder:r||null,help:m||null,tooltip:e.tooltip||null,error:f||null,rows:l||3,required:n,disabled:a,readonly:o,showCopy:!!e.showCopy,attrs:b};return D.render(this.templates.textarea,C)}renderHtmlPreviewField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,rows:l=5,class:d="",attributes:h={},help:u=e.helpText||e.help||""}=e,m=`${this.options.inputClass} ${d}`.trim(),p=this.errors[t],f=this.getFieldValue(t)??i,g=Object.entries(h).map(([C,_])=>`${C}="${this.escapeHtml(_)}"`).join(" "),b=this.getFieldId(t),y={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:b,name:t,fieldValue:f,label:s||null,placeholder:r||null,help:u||null,tooltip:e.tooltip||null,error:p||null,rows:l||5,required:n,disabled:a,readonly:o,attrs:g,showCopy:!!e.showCopy};return D.render(this.templates.htmlpreview,y)}renderJsonField(e){const{name:t,label:s,placeholder:i="",required:r=!1,disabled:n=!1,readonly:a=!1,rows:o=3,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=this.getFieldValue(e.name)??e.value??{};let m=u;if(typeof u=="object"&&u!==null)try{m=JSON.stringify(u,null,2)}catch{m="{}"}else typeof u!="string"&&(m=String(u));const p=`${this.options.inputClass} ${l}`.trim(),f=this.errors[t],g=this.getFieldId(t),b=Object.entries({...d,"data-field-type":"json"}).map(([C,_])=>`${C}="${this.escapeHtml(_)}"`).join(" "),y={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,fieldValue:m,label:s||null,placeholder:i||null,help:h||null,tooltip:e.tooltip||null,error:f||null,rows:o||3,required:r,disabled:n,readonly:a,attrs:b};return D.render(this.templates.textarea,y)}renderSelectField(e){const{name:t,label:s,options:i=[],value:r="",required:n=!1,disabled:a=!1,multiple:o=!1,searchable:l=!1,class:d="",attributes:h={},help:u=e.helpText||e.help||"",start:m=e.start,end:p=e.end,step:f=e.step,format:g=e.format,prefix:b=e.prefix,suffix:y=e.suffix}=e,C=`form-select ${d}`.trim(),_=this.errors[t],F=this.getFieldValue(t)??r,j=Object.entries(h).map(([M,z])=>`${M}="${this.escapeHtml(z)}"`).join(" "),I=this.getFieldId(t);let R=[...i];if(m!==void 0&&p!==void 0){const M=f!==void 0?f:1,z=this.generateSelectOptions(m,p,M,{format:g,prefix:b,suffix:y});R=[...R,...z]}let oe="";Array.isArray(R)&&(oe=R.map(M=>{if(typeof M=="string"){const z=M===F?"selected":"";return`<option value="${this.escapeHtml(M)}" ${z}>${this.escapeHtml(M)}</option>`}else if(M&&typeof M=="object"){const z=M.value==F?"selected":"";return`<option value="${this.escapeHtml(M.value)}" ${z}>${this.escapeHtml(M.label||M.text||M.value)}</option>`}return""}).join(""));const be=l?`
664
664
  <input type="text"
665
665
  class="form-control form-control-sm mb-2"
666
666
  placeholder="Search options..."
667
667
  data-filter="live-search"
668
668
  data-change-action="filter-select-options"
669
- data-target="${M}">
670
- `:"",ye={labelClass:this.options.labelClass,inputClass:C,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:M,name:t,label:s||null,help:u||null,tooltip:e.tooltip||null,error:_||null,searchInput:l?be:null,optionsHTML:oe,required:n,disabled:a,multiple:o,attrs:j};return D.render(this.templates.select,ye)}renderMultiSelectField(e){const{name:t,label:s,options:i=[],value:r=[],required:n=!1,disabled:a=!1,maxHeight:o=300,help:l=e.helpText||e.help||""}=e,d=e.placeholder||e.placeHolder||"Select...";this.getFieldId(t);const h=this.errors[t],u=e.value??this.getFieldValue(t)??r;return`
669
+ data-target="${I}">
670
+ `:"",ye={labelClass:this.options.labelClass,inputClass:C,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:I,name:t,label:s||null,help:u||null,tooltip:e.tooltip||null,error:_||null,searchInput:l?be:null,optionsHTML:oe,required:n,disabled:a,multiple:o,attrs:j};return D.render(this.templates.select,ye)}renderMultiSelectField(e){const{name:t,label:s,options:i=[],value:r=[],required:n=!1,disabled:a=!1,maxHeight:o=300,help:l=e.helpText||e.help||""}=e,d=e.placeholder||e.placeHolder||"Select...";this.getFieldId(t);const h=this.errors[t],u=e.value??this.getFieldValue(t)??r;return`
671
671
  <div class="multiselect-placeholder"
672
672
  data-field-name="${t}"
673
673
  data-field-type="multiselect"
@@ -709,7 +709,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
709
709
  ${d?`<div class="${this.options.helpClass}">${this.escapeHtml(d)}</div>`:""}
710
710
  ${h?`<div class="${this.options.errorClass}">${this.escapeHtml(h)}</div>`:""}
711
711
  </div>
712
- `}renderDateField(e){return this.renderInputField(e,"date")}renderDateTimeField(e){return this.renderInputField(e,"datetime-local")}renderTimeField(e){return this.renderInputField(e,"time")}renderFileField(e){const{name:t,label:s,required:i=!1,disabled:r=!1,multiple:n=!1,accept:a="*/*",class:o="",attributes:l={},help:d=e.helpText||e.help||""}=e,h=`${this.options.inputClass} ${o}`.trim(),u=this.errors[t],m=Object.entries(l).map(([g,b])=>`${g}="${this.escapeHtml(b)}"`).join(" "),p=this.getFieldId(t),f={labelClass:this.options.labelClass,inputClass:h,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:p,name:t,label:s||null,help:d||null,tooltip:e.tooltip||null,error:u||null,accept:a,required:i,disabled:r,multiple:n,attrs:m};return D.render(this.templates.file,f)}renderImageField(e){const{name:t,label:s,required:i=!1,disabled:r=!1,accept:n="image/*",class:a="",attributes:o={},help:l=e.helpText||e.help||"",size:d="md",allowDrop:h=!0,placeholder:u="Drop image here or click to upload"}=e,m=`${this.options.inputClass} ${a}`.trim(),p=this.errors[t],f=this.getFieldId(t),g=`${f}_dropzone`,b=`${f}_preview`,y={xs:{width:48,height:48,containerClass:"image-field-xs"},sm:{width:96,height:96,containerClass:"image-field-sm"},md:{width:150,height:150,containerClass:"image-field-md"},lg:{width:200,height:200,containerClass:"image-field-lg"},xl:{width:300,height:300,containerClass:"image-field-xl"}},C=y[d]||y.md,_=Object.entries(o).map(([M,R])=>`${M}="${this.escapeHtml(R)}"`).join(" "),A=this.getFieldValue(t),F=this.extractImageUrl(A,d),j={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:f,name:t,label:s||null,help:l||null,tooltip:e.tooltip||null,error:p||null,dropZoneId:g,previewId:b,containerClass:C.containerClass,width:C.width,height:C.height,accept:n,imageUrl:F,placeholderText:r?"No image":u||"",cursor:r?"default":"pointer",allowDrop:h,showRemove:!r,required:i,disabled:r,attrs:_};return D.render(this.templates.image,j)}extractImageUrl(e,t="md"){if(!e)return null;if(typeof e=="string")return e;if(typeof e=="object"&&e.url){if(e.renditions){const s={xs:["thumbnail_sm","thumbnail","square_sm"],sm:["thumbnail","thumbnail_sm","square_sm"],md:["thumbnail_md","thumbnail","thumbnail_lg"],lg:["thumbnail_lg","thumbnail_md","thumbnail"],xl:["original","thumbnail_lg"]},i=s[t]||s.md;for(const r of i)if(e.renditions[r]&&e.renditions[r].url)return e.renditions[r].url}return e.url}return null}renderColorField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=`${this.options.inputClass} ${l}`.trim(),m=this.errors[t],p=this.getFieldValue(t)??i,f=Object.entries(d).map(([y,C])=>`${y}="${this.escapeHtml(C)}"`).join(" "),g=this.getFieldId(t),b={labelClass:this.options.labelClass,inputClass:u,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,fieldValue:p,label:s||null,placeholder:r||null,help:h||null,tooltip:e.tooltip||null,error:m||null,required:n,disabled:a,readonly:o,attrs:f};return D.render(this.templates.color,b)}renderRangeField(e){const{name:t,label:s,min:i=0,max:r=100,step:n=1,value:a=i,disabled:o=!1,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=`${this.options.inputClass} ${l}`.trim(),m=this.errors[t],p=this.getFieldValue(t)??a,f=Object.entries(d).map(([y,C])=>`${y}="${this.escapeHtml(C)}"`).join(" "),g=this.getFieldId(t),b={labelClass:this.options.labelClass,inputClass:u,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,label:s||null,help:h||null,tooltip:e.tooltip||null,error:m||null,min:i,max:r,step:n,fieldValue:p,disabled:o,attrs:f};return D.render(this.templates.range,b)}renderHiddenField(e){const{name:t,value:s=""}=e,i=this.getFieldValue(t)??s;return`<input type="hidden" name="${t}" value="${this.escapeHtml(i)}">`}renderButton(e){const{name:t="",label:s="Button",type:i="button",action:r="",class:n="btn-secondary",disabled:a=!1,attributes:o={}}=e;let l=r;l||(i==="submit"?l="submit-form":i==="reset"&&(l="reset-form"));const d=Object.entries(o).map(([h,u])=>`${h}="${this.escapeHtml(u)}"`).join(" ");return`
712
+ `}renderDateField(e){return this.renderInputField(e,"date")}renderDateTimeField(e){return this.renderInputField(e,"datetime-local")}renderTimeField(e){return this.renderInputField(e,"time")}renderFileField(e){const{name:t,label:s,required:i=!1,disabled:r=!1,multiple:n=!1,accept:a="*/*",class:o="",attributes:l={},help:d=e.helpText||e.help||""}=e,h=`${this.options.inputClass} ${o}`.trim(),u=this.errors[t],m=Object.entries(l).map(([g,b])=>`${g}="${this.escapeHtml(b)}"`).join(" "),p=this.getFieldId(t),f={labelClass:this.options.labelClass,inputClass:h,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:p,name:t,label:s||null,help:d||null,tooltip:e.tooltip||null,error:u||null,accept:a,required:i,disabled:r,multiple:n,attrs:m};return D.render(this.templates.file,f)}renderImageField(e){const{name:t,label:s,required:i=!1,disabled:r=!1,accept:n="image/*",class:a="",attributes:o={},help:l=e.helpText||e.help||"",size:d="md",allowDrop:h=!0,placeholder:u="Drop image here or click to upload"}=e,m=`${this.options.inputClass} ${a}`.trim(),p=this.errors[t],f=this.getFieldId(t),g=`${f}_dropzone`,b=`${f}_preview`,y={xs:{width:48,height:48,containerClass:"image-field-xs"},sm:{width:96,height:96,containerClass:"image-field-sm"},md:{width:150,height:150,containerClass:"image-field-md"},lg:{width:200,height:200,containerClass:"image-field-lg"},xl:{width:300,height:300,containerClass:"image-field-xl"}},C=y[d]||y.md,_=Object.entries(o).map(([I,R])=>`${I}="${this.escapeHtml(R)}"`).join(" "),A=this.getFieldValue(t),F=this.extractImageUrl(A,d),j={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:f,name:t,label:s||null,help:l||null,tooltip:e.tooltip||null,error:p||null,dropZoneId:g,previewId:b,containerClass:C.containerClass,width:C.width,height:C.height,accept:n,imageUrl:F,placeholderText:r?"No image":u||"",cursor:r?"default":"pointer",allowDrop:h,showRemove:!r,required:i,disabled:r,attrs:_};return D.render(this.templates.image,j)}extractImageUrl(e,t="md"){if(!e)return null;if(typeof e=="string")return e;if(typeof e=="object"&&e.url){if(e.renditions){const s={xs:["thumbnail_sm","thumbnail","square_sm"],sm:["thumbnail","thumbnail_sm","square_sm"],md:["thumbnail_md","thumbnail","thumbnail_lg"],lg:["thumbnail_lg","thumbnail_md","thumbnail"],xl:["original","thumbnail_lg"]},i=s[t]||s.md;for(const r of i)if(e.renditions[r]&&e.renditions[r].url)return e.renditions[r].url}return e.url}return null}renderColorField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=`${this.options.inputClass} ${l}`.trim(),m=this.errors[t],p=this.getFieldValue(t)??i,f=Object.entries(d).map(([y,C])=>`${y}="${this.escapeHtml(C)}"`).join(" "),g=this.getFieldId(t),b={labelClass:this.options.labelClass,inputClass:u,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,fieldValue:p,label:s||null,placeholder:r||null,help:h||null,tooltip:e.tooltip||null,error:m||null,required:n,disabled:a,readonly:o,attrs:f};return D.render(this.templates.color,b)}renderRangeField(e){const{name:t,label:s,min:i=0,max:r=100,step:n=1,value:a=i,disabled:o=!1,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=`${this.options.inputClass} ${l}`.trim(),m=this.errors[t],p=this.getFieldValue(t)??a,f=Object.entries(d).map(([y,C])=>`${y}="${this.escapeHtml(C)}"`).join(" "),g=this.getFieldId(t),b={labelClass:this.options.labelClass,inputClass:u,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,label:s||null,help:h||null,tooltip:e.tooltip||null,error:m||null,min:i,max:r,step:n,fieldValue:p,disabled:o,attrs:f};return D.render(this.templates.range,b)}renderHiddenField(e){const{name:t,value:s=""}=e,i=this.getFieldValue(t)??s;return`<input type="hidden" name="${t}" value="${this.escapeHtml(i)}">`}renderButton(e){const{name:t="",label:s="Button",type:i="button",action:r="",class:n="btn-secondary",disabled:a=!1,attributes:o={}}=e;let l=r;l||(i==="submit"?l="submit-form":i==="reset"&&(l="reset-form"));const d=Object.entries(o).map(([h,u])=>`${h}="${this.escapeHtml(u)}"`).join(" ");return`
713
713
  <button
714
714
  type="button"
715
715
  ${t?`name="${t}"`:""}
@@ -798,14 +798,14 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
798
798
  ${C?`<div class="${this.options.helpClass}">${this.escapeHtml(C)}</div>`:""}
799
799
  ${A?`<div class="${this.options.errorClass}">${this.escapeHtml(A)}</div>`:""}
800
800
  </div>
801
- `}renderDateRangeField(e){const{name:t,startName:s,endName:i,fieldName:r,label:n,startDate:a="",endDate:o="",precision:l="day",placeholder:d,required:h=!1,disabled:u=!1,readonly:m=!1,min:p=null,max:f=null,format:g=null,displayFormat:b=null,outputFormat:y="date",separator:C=" – ",months:_=null,presets:A=null,autoApply:F=!0,inline:j=!1,help:M=e.helpText||e.help||""}=e,R=this.getFieldId(t||s||"daterange"),oe=this.errors[t],be=s||(t?t+"_start":""),ye=i||(t?t+"_end":""),I=this.getFieldValue(be)||a,z=this.getFieldValue(ye)||o;return`
801
+ `}renderDateRangeField(e){const{name:t,startName:s,endName:i,fieldName:r,label:n,startDate:a="",endDate:o="",precision:l="day",placeholder:d,required:h=!1,disabled:u=!1,readonly:m=!1,min:p=null,max:f=null,format:g=null,displayFormat:b=null,outputFormat:y="date",separator:C=" – ",months:_=null,presets:A=null,autoApply:F=!0,inline:j=!1,help:I=e.helpText||e.help||""}=e,R=this.getFieldId(t||s||"daterange"),oe=this.errors[t],be=s||(t?t+"_start":""),ye=i||(t?t+"_end":""),M=this.getFieldValue(be)||a,z=this.getFieldValue(ye)||o;return`
802
802
  <div class="mojo-form-control">
803
803
  ${n?`<label for="${R}" class="${this.options.labelClass}">${this.escapeHtml(n)}${h?'<span class="text-danger">*</span>':""}${this.renderTooltipIcon(e)}</label>`:""}
804
804
  <div class="date-range-picker-placeholder"
805
805
  data-field-name="${t||s||"daterange"}"
806
806
  data-field-type="daterange"
807
- data-field-config='${JSON.stringify({name:t,startName:s,endName:i,fieldName:r,startDate:I,endDate:z,precision:l,placeholder:d,min:p,max:f,format:g,displayFormat:b,outputFormat:y,separator:C,months:_,presets:A,autoApply:F,inline:j,disabled:u,readonly:m,required:h})}'></div>
808
- ${M?`<div class="${this.options.helpClass}">${this.escapeHtml(M)}</div>`:""}
807
+ data-field-config='${JSON.stringify({name:t,startName:s,endName:i,fieldName:r,startDate:M,endDate:z,precision:l,placeholder:d,min:p,max:f,format:g,displayFormat:b,outputFormat:y,separator:C,months:_,presets:A,autoApply:F,inline:j,disabled:u,readonly:m,required:h})}'></div>
808
+ ${I?`<div class="${this.options.helpClass}">${this.escapeHtml(I)}</div>`:""}
809
809
  ${oe?`<div class="${this.options.errorClass}">${this.escapeHtml(oe)}</div>`:""}
810
810
  </div>
811
811
  `}renderTimePickerField(e){const{name:t,label:s,value:i="",format:r="24h",step:n=1,min:a=null,max:o=null,placeholder:l,required:d=!1,disabled:h=!1,readonly:u=!1,timezone:m=!1,timezones:p=null,outputFormat:f="string",autoApply:g=!1,inline:b=!1,help:y=e.helpText||e.help||""}=e,C=this.getFieldId(t),_=this.errors[t],A=this.getFieldValue(t)??i;return`
@@ -818,7 +818,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
818
818
  ${y?`<div class="${this.options.helpClass}">${this.escapeHtml(y)}</div>`:""}
819
819
  ${_?`<div class="${this.options.errorClass}">${this.escapeHtml(_)}</div>`:""}
820
820
  </div>
821
- `}renderDateTimePickerField(e){const{name:t,label:s,value:i="",displayFormat:r=null,timeFormat:n="24h",timeStep:a=1,min:o=null,max:l=null,placeholder:d,required:h=!1,disabled:u=!1,readonly:m=!1,disabledDates:p=[],firstDay:f=1,lang:g="en-US",timezone:b=!1,timezones:y=null,outputFormat:C="string",autoApply:_=!1,inline:A=!1,help:F=e.helpText||e.help||""}=e,j=this.getFieldId(t),M=this.errors[t],R=this.getFieldValue(t)??i;return`
821
+ `}renderDateTimePickerField(e){const{name:t,label:s,value:i="",displayFormat:r=null,timeFormat:n="24h",timeStep:a=1,min:o=null,max:l=null,placeholder:d,required:h=!1,disabled:u=!1,readonly:m=!1,disabledDates:p=[],firstDay:f=1,lang:g="en-US",timezone:b=!1,timezones:y=null,outputFormat:C="string",autoApply:_=!1,inline:A=!1,help:F=e.helpText||e.help||""}=e,j=this.getFieldId(t),I=this.errors[t],R=this.getFieldValue(t)??i;return`
822
822
  <div class="mojo-form-control">
823
823
  ${s?`<label for="${j}" class="${this.options.labelClass}">${this.escapeHtml(s)}${h?'<span class="text-danger">*</span>':""}${this.renderTooltipIcon(e)}</label>`:""}
824
824
  <div class="datetime-picker-placeholder"
@@ -826,7 +826,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
826
826
  data-field-type="datetimepicker"
827
827
  data-field-config='${JSON.stringify({name:t,value:R,displayFormat:r,timeFormat:n,timeStep:a,min:o,max:l,placeholder:d,disabledDates:p,firstDay:f,lang:g,timezone:b,timezones:y,outputFormat:C,autoApply:_,inline:A,disabled:u,readonly:m,required:h})}'></div>
828
828
  ${F?`<div class="${this.options.helpClass}">${this.escapeHtml(F)}</div>`:""}
829
- ${M?`<div class="${this.options.errorClass}">${this.escapeHtml(M)}</div>`:""}
829
+ ${I?`<div class="${this.options.errorClass}">${this.escapeHtml(I)}</div>`:""}
830
830
  </div>
831
831
  `}renderChecklistDropdownField(e){const t=this.getFieldId(e.name),s=this.getFieldValue(e.name)??[],i={fieldId:t,fieldName:e.name,buttonText:e.buttonText||"Select Options",buttonIcon:e.buttonIcon||"bi-chevron-down",buttonClass:e.buttonClass||"btn btn-outline-secondary btn-sm dropdown-toggle",dropdownClass:e.dropdownClass||"dropdown-menu p-2",minWidth:e.minWidth||"200px",options:e.options.map(r=>({value:r.value,label:r.label,id:`${e.name}-${r.value}`,checked:s.includes(r.value)}))};return D.render(this.templates.checklistdropdown,i)}renderButtonGroupField(e){const t=this.getFieldId(e.name),s=this.getFieldValue(e.name)??e.value,i={fieldId:t,fieldName:e.name,size:e.size||"sm",variant:e.variant||"outline-primary",options:e.options.map(r=>({value:r.value,label:r.label,action:r.action,active:r.value===s,buttonClass:this.getButtonClass(r.value===s,e.variant)}))};return D.render(this.templates.buttongroup,i)}getButtonClass(e,t="outline-primary"){return e?`btn btn-${t.replace("outline-","")}`:`btn btn-${t}`}renderComboField(e){const{name:t,label:s,value:i="",required:r=!1,disabled:n=!1,maxHeight:a=300,help:o=e.helpText||e.help||""}=e,l=e.placeholder||e.placeHolder||"Type or select...",d=e.allowCustom!==!1;this.getFieldId(t);const h=this.errors[t],u=e.value??this.getFieldValue(t)??i;return`
832
832
  <div class="mojo-form-control">
@@ -1127,7 +1127,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1127
1127
  ${!this.required&&!this.disabled&&!this.readonly?'<button type="button" class="mojo-date-trigger-clear" data-clear aria-label="Clear" tabindex="-1">&#x2715;</button>':""}
1128
1128
  </button>
1129
1129
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(this.currentValue)}" data-hidden-value />
1130
- `}async onAfterRender(){this.inline?this._mountCalendarInline():this._wireTrigger()}_wireTrigger(){const e=this.element.querySelector("[data-trigger]"),t=this.element.querySelector("[data-clear]");e&&(e.addEventListener("click",s=>{s.target.closest("[data-clear]")||this._togglePopover(e)}),t&&t.addEventListener("click",s=>{s.stopPropagation(),this._setValue("")}))}_togglePopover(e){if(!(this.disabled||this.readonly)){if(this._popover?this._popover.setAnchor(e):this._popover=new _e({anchor:e}),this._popover.isOpen()){this._popover.close();return}this._calendar||(this._calendar=this._buildCalendar()),this._popover.setContent(this._calendar.element),this._popover.open(),this._calendar.render(!1)}}_mountCalendarInline(){const e=this.element.querySelector("[data-cal-host]");e&&(this._calendar||(this._calendar=this._buildCalendar()),e.appendChild(this._calendar.element),this._calendar.render(!1))}_buildCalendar(){const e=new He({precision:this.precision,mode:"single",months:1,value:this.currentValue||null,min:this.min,max:this.max,disabledDates:this.disabledDates,firstDay:this.firstDay,locale:this.lang});return e.on("select",({value:t})=>{this._setValue(t),this.autoApply&&this._popover&&this._popover.isOpen()&&this._popover.close()}),e}_setValue(e){const t=this.currentValue;let s="";if(e){const a=P(e,this.precision);a&&(s=U(a,this.precision))}this.currentValue=s;const i=this._displayText(s),r=this.element.querySelector("[data-trigger-text]");r&&(r.textContent=i||this.placeholder,r.classList.toggle("is-empty",!s));const n=this.element.querySelector("[data-hidden-value]");n&&(n.value=s),this._calendar&&this._calendar.setValue(s),t!==s&&(this.emit("change",{value:s,formatted:i,oldValue:t}),this.emit("date:changed",{value:s,oldValue:t}))}_displayText(e){if(!e)return"";const t=P(e,this.precision);return t?he(t,this._stripIncompatibleTokens(this.displayFormat)):""}_stripIncompatibleTokens(e){return this.precision==="day"?e:this.precision==="month"?e.replace(/\bDD\b|\bD\b/g,"").replace(/[\s\-\/]+$/,"").trim():this.precision==="year"?e.replace(/MMMM|MMM|MM|M|DD|D/g,"").replace(/[\s\-\/]+$/,"").trim()||"YYYY":e}setValue(e){this._setValue(e)}getValue(){return this.currentValue}getFormattedValue(){return this._displayText(this.currentValue)}clear(){this._setValue("")}setMin(e){this.min=e,this._calendar&&this._calendar.setMin(e)}setMax(e){this.max=e,this._calendar&&this._calendar.setMax(e)}setEnabled(e){this.disabled=!e;const t=this.element.querySelector("[data-trigger]");t&&(t.disabled=!e),!e&&this._popover&&this._popover.isOpen()&&this._popover.close()}setReadonly(e){this.readonly=e,e&&this._popover&&this._popover.isOpen()&&this._popover.close()}focus(){const e=this.element.querySelector("[data-trigger]");e&&e.focus()}show(){const e=this.element.querySelector("[data-trigger]");e&&this._togglePopover(e)}hide(){this._popover&&this._popover.close()}getFormValue(){return this.getValue()}async setFormValue(e){this._setValue(e)}hasError(){return!1}_inputId(){return this.name?`mojo-date-${this.name}-${this.id}`:`mojo-date-${this.id}`}_attr(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}async onBeforeDestroy(){this._popover&&(this._popover.destroy(),this._popover=null),this._calendar=null,await super.onBeforeDestroy()}static create(e={}){return new qe(e)}}function ms(){return[{label:"Today",range:()=>{const c=E();return{start:c,end:c}}},{label:"Yesterday",range:()=>{const c=E(),e=xe(c,-1);return{start:e,end:e}}},{label:"Last 7 days",range:()=>{const c=E();return{start:xe(c,-6),end:c}}},{label:"Last 30 days",range:()=>{const c=E();return{start:xe(c,-29),end:c}}},{label:"Last 90 days",range:()=>{const c=E();return{start:xe(c,-89),end:c}}},{divider:!0},{label:"This month",range:()=>{const c=E();return{start:{y:c.y,m:c.m,d:1},end:c}}},{label:"Last month",range:()=>{const c=E(),e=ae({y:c.y,m:c.m,d:1},-1),t=ae(e,1);t.d=0;const s=new Date(t.y,t.m,0).getDate();return{start:{...e,d:1},end:{...e,d:s}}}},{label:"This year",range:()=>{const c=E();return{start:{y:c.y,m:1,d:1},end:c}}}]}function ps(){return[{label:"This month",range:()=>{const c=E();return{start:{y:c.y,m:c.m},end:{y:c.y,m:c.m}}}},{label:"Last month",range:()=>{const c=E(),e=ae({y:c.y,m:c.m},-1);return{start:e,end:e}}},{label:"Last 3 months",range:()=>{const c=E();return{start:ae({y:c.y,m:c.m},-2),end:{y:c.y,m:c.m}}}},{label:"Last 6 months",range:()=>{const c=E();return{start:ae({y:c.y,m:c.m},-5),end:{y:c.y,m:c.m}}}},{label:"YTD",range:()=>{const c=E();return{start:{y:c.y,m:1},end:{y:c.y,m:c.m}}}},{label:"Last 12 months",range:()=>{const c=E();return{start:ae({y:c.y,m:c.m},-11),end:{y:c.y,m:c.m}}}}]}function fs(){return[{label:"This year",range:()=>{const c=E();return{start:{y:c.y},end:{y:c.y}}}},{label:"Last year",range:()=>{const c=E();return{start:{y:c.y-1},end:{y:c.y-1}}}},{label:"Last 3 years",range:()=>{const c=E();return{start:{y:c.y-2},end:{y:c.y}}}},{label:"Last 5 years",range:()=>{const c=E();return{start:{y:c.y-4},end:{y:c.y}}}},{label:"Last 10 years",range:()=>{const c=E();return{start:{y:c.y-9},end:{y:c.y}}}}]}function xe(c,e){if(!c)return null;const t=new Date(c.y,c.m-1,c.d+e);return{y:t.getFullYear(),m:t.getMonth()+1,d:t.getDate()}}function At(c){return c==="year"?fs():c==="month"?ps():ms()}class gs extends S{constructor(e={}){const{precision:t="day",presets:s="default",eyebrow:i="Quick range",...r}=e;super({tagName:"div",className:"mojo-calendar-presets",...r}),this.precision=t,this.eyebrow=i,this.activeIndex=-1,this.presets=s===!0||s==="default"?At(t):Array.isArray(s)?s:At(t)}setActive(e){this.activeIndex=e,this._highlight()}async renderTemplate(){return""}async onAfterRender(){this._renderInto(this.element)}_renderInto(e){if(e.innerHTML="",this.eyebrow){const t=document.createElement("div");t.className="mojo-calendar-presets-eyebrow",t.textContent=this.eyebrow,e.appendChild(t)}this.presets.forEach((t,s)=>{if(t.divider){const r=document.createElement("div");r.className="mojo-calendar-presets-divider",e.appendChild(r);return}const i=document.createElement("button");i.type="button",i.className="mojo-calendar-preset"+(this.activeIndex===s?" is-active":""),i.dataset.presetIndex=String(s),i.textContent=t.label,e.appendChild(i)}),e.addEventListener("click",t=>{const s=t.target.closest(".mojo-calendar-preset");if(!s)return;const i=parseInt(s.dataset.presetIndex,10),r=this.presets[i];if(!r||typeof r.range!="function")return;const n=r.range();this.activeIndex=i,this._highlight();const a=this.precision==="year"?gt:this.precision==="month"?Re:B;this.emit("preset:select",{index:i,label:r.label,start:a(n.start),end:a(n.end),parsed:n})})}_highlight(){this.element&&this.element.querySelectorAll(".mojo-calendar-preset").forEach(e=>{const t=parseInt(e.dataset.presetIndex,10);e.classList.toggle("is-active",t===this.activeIndex)})}}const Tt={day:"MMM DD, YYYY",month:"MMM YYYY",year:"YYYY"};class Be extends S{constructor(e={}){const{name:t,startName:s,endName:i,fieldName:r,startDate:n="",endDate:a="",precision:o="day",format:l=null,displayFormat:d=null,outputFormat:h="date",min:u=null,max:m=null,placeholder:p=null,disabled:f=!1,readonly:g=!1,required:b=!1,class:y="",inputClass:C="form-control",inline:_=!1,separator:A=" – ",autoApply:F=!0,months:j=null,presets:M=null,...R}=e;super({tagName:"div",className:`mojo-date-picker mojo-date-range-picker mojo-date-picker-${o} ${y}`.trim(),...R}),this.name=t,this.startName=s,this.endName=i,this.fieldName=r,this.precision=o,this.format=l,this.displayFormat=d||Tt[o]||Tt.day,this.outputFormat=h,this.min=u,this.max=m,this.placeholder=p??this._defaultPlaceholder(o),this.disabled=f,this.readonly=g,this.required=b,this.inputClass=C,this.inline=_,this.separator=A,this.autoApply=F,this.months=j??(o==="day"?2:1),this.presets=M,this.currentStartDate=n||"",this.currentEndDate=a||"",this._calendar=null,this._popover=null,this._presetSidebar=null}_defaultPlaceholder(e){return e==="year"?"Select year range...":e==="month"?"Select month range...":"Select date range..."}async renderTemplate(){const e=this._inputId(),t=this._displayText(),s=!this.currentStartDate,i=this.startName||(this.name?`${this.name}_start`:""),r=this.endName||(this.name?`${this.name}_end`:""),n=`
1130
+ `}async onAfterRender(){this.inline?this._mountCalendarInline():this._wireTrigger()}_wireTrigger(){const e=this.element.querySelector("[data-trigger]"),t=this.element.querySelector("[data-clear]");e&&(e.addEventListener("click",s=>{s.target.closest("[data-clear]")||this._togglePopover(e)}),t&&t.addEventListener("click",s=>{s.stopPropagation(),this._setValue("")}))}_togglePopover(e){if(!(this.disabled||this.readonly)){if(this._popover?this._popover.setAnchor(e):this._popover=new _e({anchor:e}),this._popover.isOpen()){this._popover.close();return}this._calendar||(this._calendar=this._buildCalendar()),this._popover.setContent(this._calendar.element),this._popover.open(),this._calendar.render(!1)}}_mountCalendarInline(){const e=this.element.querySelector("[data-cal-host]");e&&(this._calendar||(this._calendar=this._buildCalendar()),e.appendChild(this._calendar.element),this._calendar.render(!1))}_buildCalendar(){const e=new He({precision:this.precision,mode:"single",months:1,value:this.currentValue||null,min:this.min,max:this.max,disabledDates:this.disabledDates,firstDay:this.firstDay,locale:this.lang});return e.on("select",({value:t})=>{this._setValue(t),this.autoApply&&this._popover&&this._popover.isOpen()&&this._popover.close()}),e}_setValue(e){const t=this.currentValue;let s="";if(e){const a=P(e,this.precision);a&&(s=U(a,this.precision))}this.currentValue=s;const i=this._displayText(s),r=this.element.querySelector("[data-trigger-text]");r&&(r.textContent=i||this.placeholder,r.classList.toggle("is-empty",!s));const n=this.element.querySelector("[data-hidden-value]");n&&(n.value=s),this._calendar&&this._calendar.setValue(s),t!==s&&(this.emit("change",{value:s,formatted:i,oldValue:t}),this.emit("date:changed",{value:s,oldValue:t}))}_displayText(e){if(!e)return"";const t=P(e,this.precision);return t?he(t,this._stripIncompatibleTokens(this.displayFormat)):""}_stripIncompatibleTokens(e){return this.precision==="day"?e:this.precision==="month"?e.replace(/\bDD\b|\bD\b/g,"").replace(/[\s\-\/]+$/,"").trim():this.precision==="year"?e.replace(/MMMM|MMM|MM|M|DD|D/g,"").replace(/[\s\-\/]+$/,"").trim()||"YYYY":e}setValue(e){this._setValue(e)}getValue(){return this.currentValue}getFormattedValue(){return this._displayText(this.currentValue)}clear(){this._setValue("")}setMin(e){this.min=e,this._calendar&&this._calendar.setMin(e)}setMax(e){this.max=e,this._calendar&&this._calendar.setMax(e)}setEnabled(e){this.disabled=!e;const t=this.element.querySelector("[data-trigger]");t&&(t.disabled=!e),!e&&this._popover&&this._popover.isOpen()&&this._popover.close()}setReadonly(e){this.readonly=e,e&&this._popover&&this._popover.isOpen()&&this._popover.close()}focus(){const e=this.element.querySelector("[data-trigger]");e&&e.focus()}show(){const e=this.element.querySelector("[data-trigger]");e&&this._togglePopover(e)}hide(){this._popover&&this._popover.close()}getFormValue(){return this.getValue()}async setFormValue(e){this._setValue(e)}hasError(){return!1}_inputId(){return this.name?`mojo-date-${this.name}-${this.id}`:`mojo-date-${this.id}`}_attr(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}async onBeforeDestroy(){this._popover&&(this._popover.destroy(),this._popover=null),this._calendar=null,await super.onBeforeDestroy()}static create(e={}){return new qe(e)}}function ms(){return[{label:"Today",range:()=>{const c=E();return{start:c,end:c}}},{label:"Yesterday",range:()=>{const c=E(),e=xe(c,-1);return{start:e,end:e}}},{label:"Last 7 days",range:()=>{const c=E();return{start:xe(c,-6),end:c}}},{label:"Last 30 days",range:()=>{const c=E();return{start:xe(c,-29),end:c}}},{label:"Last 90 days",range:()=>{const c=E();return{start:xe(c,-89),end:c}}},{divider:!0},{label:"This month",range:()=>{const c=E();return{start:{y:c.y,m:c.m,d:1},end:c}}},{label:"Last month",range:()=>{const c=E(),e=ae({y:c.y,m:c.m,d:1},-1),t=ae(e,1);t.d=0;const s=new Date(t.y,t.m,0).getDate();return{start:{...e,d:1},end:{...e,d:s}}}},{label:"This year",range:()=>{const c=E();return{start:{y:c.y,m:1,d:1},end:c}}}]}function ps(){return[{label:"This month",range:()=>{const c=E();return{start:{y:c.y,m:c.m},end:{y:c.y,m:c.m}}}},{label:"Last month",range:()=>{const c=E(),e=ae({y:c.y,m:c.m},-1);return{start:e,end:e}}},{label:"Last 3 months",range:()=>{const c=E();return{start:ae({y:c.y,m:c.m},-2),end:{y:c.y,m:c.m}}}},{label:"Last 6 months",range:()=>{const c=E();return{start:ae({y:c.y,m:c.m},-5),end:{y:c.y,m:c.m}}}},{label:"YTD",range:()=>{const c=E();return{start:{y:c.y,m:1},end:{y:c.y,m:c.m}}}},{label:"Last 12 months",range:()=>{const c=E();return{start:ae({y:c.y,m:c.m},-11),end:{y:c.y,m:c.m}}}}]}function fs(){return[{label:"This year",range:()=>{const c=E();return{start:{y:c.y},end:{y:c.y}}}},{label:"Last year",range:()=>{const c=E();return{start:{y:c.y-1},end:{y:c.y-1}}}},{label:"Last 3 years",range:()=>{const c=E();return{start:{y:c.y-2},end:{y:c.y}}}},{label:"Last 5 years",range:()=>{const c=E();return{start:{y:c.y-4},end:{y:c.y}}}},{label:"Last 10 years",range:()=>{const c=E();return{start:{y:c.y-9},end:{y:c.y}}}}]}function xe(c,e){if(!c)return null;const t=new Date(c.y,c.m-1,c.d+e);return{y:t.getFullYear(),m:t.getMonth()+1,d:t.getDate()}}function At(c){return c==="year"?fs():c==="month"?ps():ms()}class gs extends S{constructor(e={}){const{precision:t="day",presets:s="default",eyebrow:i="Quick range",...r}=e;super({tagName:"div",className:"mojo-calendar-presets",...r}),this.precision=t,this.eyebrow=i,this.activeIndex=-1,this.presets=s===!0||s==="default"?At(t):Array.isArray(s)?s:At(t)}setActive(e){this.activeIndex=e,this._highlight()}async renderTemplate(){return""}async onAfterRender(){this._renderInto(this.element)}_renderInto(e){if(e.innerHTML="",this.eyebrow){const t=document.createElement("div");t.className="mojo-calendar-presets-eyebrow",t.textContent=this.eyebrow,e.appendChild(t)}this.presets.forEach((t,s)=>{if(t.divider){const r=document.createElement("div");r.className="mojo-calendar-presets-divider",e.appendChild(r);return}const i=document.createElement("button");i.type="button",i.className="mojo-calendar-preset"+(this.activeIndex===s?" is-active":""),i.dataset.presetIndex=String(s),i.textContent=t.label,e.appendChild(i)}),e.addEventListener("click",t=>{const s=t.target.closest(".mojo-calendar-preset");if(!s)return;const i=parseInt(s.dataset.presetIndex,10),r=this.presets[i];if(!r||typeof r.range!="function")return;const n=r.range();this.activeIndex=i,this._highlight();const a=this.precision==="year"?gt:this.precision==="month"?Re:B;this.emit("preset:select",{index:i,label:r.label,start:a(n.start),end:a(n.end),parsed:n})})}_highlight(){this.element&&this.element.querySelectorAll(".mojo-calendar-preset").forEach(e=>{const t=parseInt(e.dataset.presetIndex,10);e.classList.toggle("is-active",t===this.activeIndex)})}}const Tt={day:"MMM DD, YYYY",month:"MMM YYYY",year:"YYYY"};class Be extends S{constructor(e={}){const{name:t,startName:s,endName:i,fieldName:r,startDate:n="",endDate:a="",precision:o="day",format:l=null,displayFormat:d=null,outputFormat:h="date",min:u=null,max:m=null,placeholder:p=null,disabled:f=!1,readonly:g=!1,required:b=!1,class:y="",inputClass:C="form-control",inline:_=!1,separator:A=" – ",autoApply:F=!0,months:j=null,presets:I=null,...R}=e;super({tagName:"div",className:`mojo-date-picker mojo-date-range-picker mojo-date-picker-${o} ${y}`.trim(),...R}),this.name=t,this.startName=s,this.endName=i,this.fieldName=r,this.precision=o,this.format=l,this.displayFormat=d||Tt[o]||Tt.day,this.outputFormat=h,this.min=u,this.max=m,this.placeholder=p??this._defaultPlaceholder(o),this.disabled=f,this.readonly=g,this.required=b,this.inputClass=C,this.inline=_,this.separator=A,this.autoApply=F,this.months=j??(o==="day"?2:1),this.presets=I,this.currentStartDate=n||"",this.currentEndDate=a||"",this._calendar=null,this._popover=null,this._presetSidebar=null}_defaultPlaceholder(e){return e==="year"?"Select year range...":e==="month"?"Select month range...":"Select date range..."}async renderTemplate(){const e=this._inputId(),t=this._displayText(),s=!this.currentStartDate,i=this.startName||(this.name?`${this.name}_start`:""),r=this.endName||(this.name?`${this.name}_end`:""),n=`
1131
1131
  ${this.name?`<input type="hidden" name="${this._attr(this.name)}" value="${this._attr(this.getCombinedValue())}" data-combined-value />`:""}
1132
1132
  ${i?`<input type="hidden" name="${this._attr(i)}" value="${this._attr(this.currentStartDate)}" data-start-value />`:""}
1133
1133
  ${r?`<input type="hidden" name="${this._attr(r)}" value="${this._attr(this.currentEndDate)}" data-end-value />`:""}
@@ -1193,7 +1193,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1193
1193
  ${!this.required&&!this.disabled&&!this.readonly?'<button type="button" class="mojo-time-trigger-clear" data-clear aria-label="Clear" tabindex="-1">&#x2715;</button>':""}
1194
1194
  </button>
1195
1195
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(i)}" data-hidden-value />
1196
- `}async onAfterRender(){this.inline?this._mountInline():this._wireTrigger()}_wireTrigger(){const e=this.element.querySelector("[data-trigger]"),t=this.element.querySelector("[data-clear]");e&&(e.addEventListener("click",s=>{s.target.closest("[data-clear]")||this._togglePopover(e)}),t&&t.addEventListener("click",s=>{s.stopPropagation(),this.clear()}))}_togglePopover(e){if(this.disabled||this.readonly)return;if(this._popover?this._popover.setAnchor(e):this._popover=new _e({anchor:e,classNames:"mojo-time-popover"}),this._popover.isOpen()){this._popover.close();return}const t=this._buildSpinnerContent();this._popover.setContent(t),this._popover.open(),this.timezone&&this._mountTimezoneSelect()}_mountInline(){const e=this.element.querySelector("[data-time-host]");if(!e)return;const t=this._buildSpinnerContent();e.appendChild(t),this.timezone&&this._mountTimezoneSelect()}_buildSpinnerContent(){const e=document.createElement("div");e.className="mojo-time-popover-inner";const t=document.createElement("div");t.className="mojo-time-stepper-row";const s=this.currentTime||{hours:0,minutes:0},i=this._hourDisplay(s.hours);t.appendChild(this._buildStepper("hour",i,"Hour"));const r=document.createElement("div");if(r.className="mojo-time-stepper-sep",r.textContent=":",t.appendChild(r),t.appendChild(this._buildStepper("minute",Ue(s.minutes),"Minute")),this.format==="12h"&&t.appendChild(this._buildAmPmToggle(s.hours)),e.appendChild(t),this.timezone){const n=document.createElement("div");n.className="mojo-time-tz-host",n.setAttribute("data-tz-host",""),e.appendChild(n)}if(this.showFooter){const n=document.createElement("div");n.className="mojo-time-foot";const a=document.createElement("button");a.type="button",a.className="btn btn-link btn-sm mojo-time-now",a.textContent="Now",a.addEventListener("click",l=>{l.preventDefault();const d=new Date;this._commitTime({hours:d.getHours(),minutes:d.getMinutes()}),this._refreshSpinnerDisplay()}),n.appendChild(a);const o=document.createElement("button");o.type="button",o.className="btn btn-primary btn-sm mojo-time-apply",o.textContent="Set",o.addEventListener("click",l=>{l.preventDefault(),this.currentTime||this._commitTime({hours:0,minutes:0}),this._popover&&this._popover.isOpen()&&this._popover.close()}),n.appendChild(o),e.appendChild(n)}return this._spinner=e,e}_buildStepper(e,t,s){const i=document.createElement("div");i.className=`mojo-time-stepper mojo-time-stepper-${e}`;const r=document.createElement("button");r.type="button",r.className="mojo-time-stepper-btn",r.setAttribute("aria-label",`Increase ${s.toLowerCase()}`),r.innerHTML='<i class="bi bi-chevron-up" aria-hidden="true"></i>',r.addEventListener("click",l=>{l.preventDefault(),this._step(e,1)});const n=document.createElement("input");n.type="text",n.className="mojo-time-stepper-value",n.value=t,n.setAttribute("inputmode","numeric"),n.setAttribute("aria-label",s),n.maxLength=2,n.addEventListener("focus",()=>n.select()),n.addEventListener("keydown",l=>this._onValueKey(e,n,l)),n.addEventListener("blur",()=>this._onValueBlur(e,n));const a=document.createElement("button");a.type="button",a.className="mojo-time-stepper-btn",a.setAttribute("aria-label",`Decrease ${s.toLowerCase()}`),a.innerHTML='<i class="bi bi-chevron-down" aria-hidden="true"></i>',a.addEventListener("click",l=>{l.preventDefault(),this._step(e,-1)});const o=document.createElement("div");return o.className="mojo-time-stepper-label",o.textContent=s,i.appendChild(r),i.appendChild(n),i.appendChild(a),i.appendChild(o),i}_buildAmPmToggle(e){const t=document.createElement("div");t.className="mojo-time-ampm";const s=e>=12,i=document.createElement("button");i.type="button",i.className=`mojo-time-ampm-btn${s?"":" is-active"}`,i.textContent="AM",i.addEventListener("click",n=>{n.preventDefault(),this._setAmPm("am")});const r=document.createElement("button");return r.type="button",r.className=`mojo-time-ampm-btn${s?" is-active":""}`,r.textContent="PM",r.addEventListener("click",n=>{n.preventDefault(),this._setAmPm("pm")}),t.appendChild(i),t.appendChild(r),t}_mountTimezoneSelect(){if(!this.timezone)return;const e=this.inline?this.element.querySelector("[data-time-host] [data-tz-host]"):this._spinner&&this._spinner.querySelector("[data-tz-host]");if(e){if(this._tzSelect)try{this._tzSelect.destroy&&this._tzSelect.destroy()}catch{}e.innerHTML="",this._tzSelect=new Dt({name:"timezone",value:this.currentTimezone,timezones:this.timezoneList}),this._tzSelect.render(!0,e),this._tzSelect.on("change",({value:t})=>{const s=this.currentTimezone;this.currentTimezone=t||null,s!==this.currentTimezone&&this._syncOutputs()})}}_step(e,t){const s=this.currentTime||{hours:0,minutes:0};let{hours:i,minutes:r}=s;if(e==="hour")i=((i+t)%24+24)%24;else{const a=i*60+r,o=t*this.step,l=((a+o)%1440+1440)%1440;i=Math.floor(l/60),r=l%60}const n=this._clampToBounds({hours:i,minutes:r});this._commitTime(n),this._refreshSpinnerDisplay()}_setAmPm(e){if(!this.currentTime)this._commitTime({hours:e==="pm"?12:0,minutes:0});else{const{hours:t,minutes:s}=this.currentTime;let i=t;e==="am"&&i>=12?i-=12:e==="pm"&&i<12&&(i+=12),this._commitTime(this._clampToBounds({hours:i,minutes:s}))}this._refreshSpinnerDisplay()}_onValueKey(e,t,s){s.key==="ArrowUp"?(s.preventDefault(),this._step(e,1),t.focus(),t.select()):s.key==="ArrowDown"?(s.preventDefault(),this._step(e,-1),t.focus(),t.select()):s.key==="Enter"?(s.preventDefault(),t.blur()):s.key==="Tab"||!/^[0-9]$/.test(s.key)&&!["Backspace","Delete","ArrowLeft","ArrowRight","Home","End"].includes(s.key)&&s.preventDefault()}_onValueBlur(e,t){const s=(t.value||"").replace(/\D/g,"");if(s===""){this._refreshSpinnerDisplay();return}let i=parseInt(s,10);const r=this.currentTime||{hours:0,minutes:0};let{hours:n,minutes:a}=r;if(e==="hour")if(this.format==="12h"){i<1&&(i=1),i>12&&(i=12);const o=r.hours>=12;i===12?n=o?12:0:n=o?i+12:i}else i<0&&(i=0),i>23&&(i=23),n=i;else i<0&&(i=0),i>59&&(i=59),a=i;this._commitTime(this._clampToBounds({hours:n,minutes:a})),this._refreshSpinnerDisplay()}_hourDisplay(e){if(this.format==="12h"){let t=e%12;return t===0&&(t=12),String(t)}return Ue(e)}_refreshSpinnerDisplay(){if(!this._spinner)return;const e=this.currentTime||{hours:0,minutes:0},t=this._spinner.querySelector(".mojo-time-stepper-hour .mojo-time-stepper-value"),s=this._spinner.querySelector(".mojo-time-stepper-minute .mojo-time-stepper-value");if(t&&(t.value=this._hourDisplay(e.hours)),s&&(s.value=Ue(e.minutes)),this.format==="12h"){const i=e.hours>=12,r=this._spinner.querySelector(".mojo-time-ampm-btn:nth-child(1)"),n=this._spinner.querySelector(".mojo-time-ampm-btn:nth-child(2)");r&&r.classList.toggle("is-active",!i),n&&n.classList.toggle("is-active",i)}}_clampToBounds(e){const t=this.min?J(this.min):null,s=this.max?J(this.max):null;return t&&vt(e,t)<0?t:s&&vt(e,s)>0?s:e}_commitTime(e){const t=this._serialize();this.currentTime=e?{hours:e.hours,minutes:e.minutes}:null,this._syncOutputs(t)}_syncOutputs(e){const t=this._serialize(),s=this._displayText(),i=this.element&&this.element.querySelector("[data-trigger-text]");i&&(i.textContent=s||this.placeholder,i.classList.toggle("is-empty",!this.currentTime));const r=this.element&&this.element.querySelector("[data-hidden-value]");r&&(r.value=t),e!==void 0&&e!==t&&(this.emit("change",{value:this.getValue(),formatted:s,oldValue:e}),this.emit("time:changed",{value:this.getValue()}))}_serialize(){if(!this.currentTime)return"";const e=Z(this.currentTime,"24h");if(!this.timezone||!this.currentTimezone)return e;if(this.outputFormat==="iana")return`${e} ${this.currentTimezone}`;const t=Ct(this.currentTimezone,new Date);return t?`${e}${t}`:e}_displayText(){if(!this.currentTime)return"";const e=Z(this.currentTime,this.format);return this.timezone&&this.currentTimezone?`${e} ${this.currentTimezone}`:e}getValue(){return this.currentTime?this.timezone&&this.outputFormat==="object"?{time:Z(this.currentTime,"24h"),timezone:this.currentTimezone||null}:this._serialize():this.outputFormat==="object"?null:""}setValue(e){const t=this._serialize(),s=this._parseInitial(e);this.currentTime=s.time,s.timezone&&(this.currentTimezone=s.timezone),this._refreshSpinnerDisplay(),this._syncOutputs(t)}getFormattedValue(){return this._displayText()}clear(){if(!this.currentTime&&!this.element.querySelector("[data-hidden-value]")?.value)return;const e=this._serialize();this.currentTime=null,this._syncOutputs(e)}setMin(e){this.min=e}setMax(e){this.max=e}setEnabled(e){this.disabled=!e;const t=this.element.querySelector("[data-trigger]");t&&(t.disabled=!e),!e&&this._popover&&this._popover.isOpen()&&this._popover.close()}setReadonly(e){this.readonly=e,e&&this._popover&&this._popover.isOpen()&&this._popover.close()}focus(){const e=this.element.querySelector("[data-trigger]");e&&e.focus()}show(){const e=this.element.querySelector("[data-trigger]");e&&this._togglePopover(e)}hide(){this._popover&&this._popover.close()}getFormValue(){return this.getValue()}async setFormValue(e){this.setValue(e)}hasError(){return!1}_inputId(){return this.name?`mojo-time-${this.name}-${this.id}`:`mojo-time-${this.id}`}_attr(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}async onBeforeDestroy(){if(this._popover){try{this._popover.destroy()}catch{}this._popover=null}if(this._tzSelect){try{await this._tzSelect.destroy()}catch{}this._tzSelect=null}this._spinner=null,await super.onBeforeDestroy()}static addMinutes(e,t){return hs(e,t)}static create(e={}){return new $e(e)}}function Ue(c){return c<10?"0"+c:String(c)}function vs(){try{return new Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}catch{return"UTC"}}const Cs="MMM DD, YYYY";class We extends S{constructor(e={}){const{name:t,value:s="",format:i=null,displayFormat:r=null,timeFormat:n="24h",timeStep:a=1,min:o=null,max:l=null,placeholder:d=null,disabled:h=!1,readonly:u=!1,required:m=!1,class:p="",inline:f=!1,disabledDates:g=[],firstDay:b=1,lang:y="en-US",autoApply:C=!1,timezone:_=!1,timezones:A=null,outputFormat:F="iso",...j}=e;super({tagName:"div",className:`mojo-datetime-picker ${p}`.trim(),...j}),this.name=t,this.format=i,this.displayFormat=r||Cs,this.timeFormat=n==="12h"?"12h":"24h",this.timeStep=Math.max(1,parseInt(a,10)||1),this.min=o,this.max=l,this.placeholder=d??"Pick date & time...",this.disabled=h,this.readonly=u,this.required=m,this.inline=f,this.disabledDates=g,this.firstDay=b,this.lang=y,this.autoApply=C,this.timezone=_===!0||Array.isArray(_),this.timezoneList=Array.isArray(_)?_:A,this.outputFormat=["object","iana","iso"].includes(F)?F:"iso";const M=this._parseInitial(s);this.currentDate=M.date,this.currentTime=M.time,this.currentTimezone=M.timezone||(this.timezone?It():null),this._calendar=null,this._timePicker=null,this._tzSelect=null,this._popover=null,this._popoverContent=null}_parseInitial(e){return e==null||e===""?{date:null,time:null,timezone:null}:typeof e=="object"&&!Array.isArray(e)&&!(e instanceof Date)?St(e)||{date:null,time:null,timezone:null}:St(e)||{date:null,time:null,timezone:null}}async renderTemplate(){const e=this._inputId(),t=this._displayText(),s=!this.currentDate,i=this._serialize();return this.inline?`
1196
+ `}async onAfterRender(){this.inline?this._mountInline():this._wireTrigger()}_wireTrigger(){const e=this.element.querySelector("[data-trigger]"),t=this.element.querySelector("[data-clear]");e&&(e.addEventListener("click",s=>{s.target.closest("[data-clear]")||this._togglePopover(e)}),t&&t.addEventListener("click",s=>{s.stopPropagation(),this.clear()}))}_togglePopover(e){if(this.disabled||this.readonly)return;if(this._popover?this._popover.setAnchor(e):this._popover=new _e({anchor:e,classNames:"mojo-time-popover"}),this._popover.isOpen()){this._popover.close();return}const t=this._buildSpinnerContent();this._popover.setContent(t),this._popover.open(),this.timezone&&this._mountTimezoneSelect()}_mountInline(){const e=this.element.querySelector("[data-time-host]");if(!e)return;const t=this._buildSpinnerContent();e.appendChild(t),this.timezone&&this._mountTimezoneSelect()}_buildSpinnerContent(){const e=document.createElement("div");e.className="mojo-time-popover-inner";const t=document.createElement("div");t.className="mojo-time-stepper-row";const s=this.currentTime||{hours:0,minutes:0},i=this._hourDisplay(s.hours);t.appendChild(this._buildStepper("hour",i,"Hour"));const r=document.createElement("div");if(r.className="mojo-time-stepper-sep",r.textContent=":",t.appendChild(r),t.appendChild(this._buildStepper("minute",Ue(s.minutes),"Minute")),this.format==="12h"&&t.appendChild(this._buildAmPmToggle(s.hours)),e.appendChild(t),this.timezone){const n=document.createElement("div");n.className="mojo-time-tz-host",n.setAttribute("data-tz-host",""),e.appendChild(n)}if(this.showFooter){const n=document.createElement("div");n.className="mojo-time-foot";const a=document.createElement("button");a.type="button",a.className="btn btn-link btn-sm mojo-time-now",a.textContent="Now",a.addEventListener("click",l=>{l.preventDefault();const d=new Date;this._commitTime({hours:d.getHours(),minutes:d.getMinutes()}),this._refreshSpinnerDisplay()}),n.appendChild(a);const o=document.createElement("button");o.type="button",o.className="btn btn-primary btn-sm mojo-time-apply",o.textContent="Set",o.addEventListener("click",l=>{l.preventDefault(),this.currentTime||this._commitTime({hours:0,minutes:0}),this._popover&&this._popover.isOpen()&&this._popover.close()}),n.appendChild(o),e.appendChild(n)}return this._spinner=e,e}_buildStepper(e,t,s){const i=document.createElement("div");i.className=`mojo-time-stepper mojo-time-stepper-${e}`;const r=document.createElement("button");r.type="button",r.className="mojo-time-stepper-btn",r.setAttribute("aria-label",`Increase ${s.toLowerCase()}`),r.innerHTML='<i class="bi bi-chevron-up" aria-hidden="true"></i>',r.addEventListener("click",l=>{l.preventDefault(),this._step(e,1)});const n=document.createElement("input");n.type="text",n.className="mojo-time-stepper-value",n.value=t,n.setAttribute("inputmode","numeric"),n.setAttribute("aria-label",s),n.maxLength=2,n.addEventListener("focus",()=>n.select()),n.addEventListener("keydown",l=>this._onValueKey(e,n,l)),n.addEventListener("blur",()=>this._onValueBlur(e,n));const a=document.createElement("button");a.type="button",a.className="mojo-time-stepper-btn",a.setAttribute("aria-label",`Decrease ${s.toLowerCase()}`),a.innerHTML='<i class="bi bi-chevron-down" aria-hidden="true"></i>',a.addEventListener("click",l=>{l.preventDefault(),this._step(e,-1)});const o=document.createElement("div");return o.className="mojo-time-stepper-label",o.textContent=s,i.appendChild(r),i.appendChild(n),i.appendChild(a),i.appendChild(o),i}_buildAmPmToggle(e){const t=document.createElement("div");t.className="mojo-time-ampm";const s=e>=12,i=document.createElement("button");i.type="button",i.className=`mojo-time-ampm-btn${s?"":" is-active"}`,i.textContent="AM",i.addEventListener("click",n=>{n.preventDefault(),this._setAmPm("am")});const r=document.createElement("button");return r.type="button",r.className=`mojo-time-ampm-btn${s?" is-active":""}`,r.textContent="PM",r.addEventListener("click",n=>{n.preventDefault(),this._setAmPm("pm")}),t.appendChild(i),t.appendChild(r),t}_mountTimezoneSelect(){if(!this.timezone)return;const e=this.inline?this.element.querySelector("[data-time-host] [data-tz-host]"):this._spinner&&this._spinner.querySelector("[data-tz-host]");if(e){if(this._tzSelect)try{this._tzSelect.destroy&&this._tzSelect.destroy()}catch{}e.innerHTML="",this._tzSelect=new Dt({name:"timezone",value:this.currentTimezone,timezones:this.timezoneList}),this._tzSelect.render(!0,e),this._tzSelect.on("change",({value:t})=>{const s=this.currentTimezone;this.currentTimezone=t||null,s!==this.currentTimezone&&this._syncOutputs()})}}_step(e,t){const s=this.currentTime||{hours:0,minutes:0};let{hours:i,minutes:r}=s;if(e==="hour")i=((i+t)%24+24)%24;else{const a=i*60+r,o=t*this.step,l=((a+o)%1440+1440)%1440;i=Math.floor(l/60),r=l%60}const n=this._clampToBounds({hours:i,minutes:r});this._commitTime(n),this._refreshSpinnerDisplay()}_setAmPm(e){if(!this.currentTime)this._commitTime({hours:e==="pm"?12:0,minutes:0});else{const{hours:t,minutes:s}=this.currentTime;let i=t;e==="am"&&i>=12?i-=12:e==="pm"&&i<12&&(i+=12),this._commitTime(this._clampToBounds({hours:i,minutes:s}))}this._refreshSpinnerDisplay()}_onValueKey(e,t,s){s.key==="ArrowUp"?(s.preventDefault(),this._step(e,1),t.focus(),t.select()):s.key==="ArrowDown"?(s.preventDefault(),this._step(e,-1),t.focus(),t.select()):s.key==="Enter"?(s.preventDefault(),t.blur()):s.key==="Tab"||!/^[0-9]$/.test(s.key)&&!["Backspace","Delete","ArrowLeft","ArrowRight","Home","End"].includes(s.key)&&s.preventDefault()}_onValueBlur(e,t){const s=(t.value||"").replace(/\D/g,"");if(s===""){this._refreshSpinnerDisplay();return}let i=parseInt(s,10);const r=this.currentTime||{hours:0,minutes:0};let{hours:n,minutes:a}=r;if(e==="hour")if(this.format==="12h"){i<1&&(i=1),i>12&&(i=12);const o=r.hours>=12;i===12?n=o?12:0:n=o?i+12:i}else i<0&&(i=0),i>23&&(i=23),n=i;else i<0&&(i=0),i>59&&(i=59),a=i;this._commitTime(this._clampToBounds({hours:n,minutes:a})),this._refreshSpinnerDisplay()}_hourDisplay(e){if(this.format==="12h"){let t=e%12;return t===0&&(t=12),String(t)}return Ue(e)}_refreshSpinnerDisplay(){if(!this._spinner)return;const e=this.currentTime||{hours:0,minutes:0},t=this._spinner.querySelector(".mojo-time-stepper-hour .mojo-time-stepper-value"),s=this._spinner.querySelector(".mojo-time-stepper-minute .mojo-time-stepper-value");if(t&&(t.value=this._hourDisplay(e.hours)),s&&(s.value=Ue(e.minutes)),this.format==="12h"){const i=e.hours>=12,r=this._spinner.querySelector(".mojo-time-ampm-btn:nth-child(1)"),n=this._spinner.querySelector(".mojo-time-ampm-btn:nth-child(2)");r&&r.classList.toggle("is-active",!i),n&&n.classList.toggle("is-active",i)}}_clampToBounds(e){const t=this.min?J(this.min):null,s=this.max?J(this.max):null;return t&&vt(e,t)<0?t:s&&vt(e,s)>0?s:e}_commitTime(e){const t=this._serialize();this.currentTime=e?{hours:e.hours,minutes:e.minutes}:null,this._syncOutputs(t)}_syncOutputs(e){const t=this._serialize(),s=this._displayText(),i=this.element&&this.element.querySelector("[data-trigger-text]");i&&(i.textContent=s||this.placeholder,i.classList.toggle("is-empty",!this.currentTime));const r=this.element&&this.element.querySelector("[data-hidden-value]");r&&(r.value=t),e!==void 0&&e!==t&&(this.emit("change",{value:this.getValue(),formatted:s,oldValue:e}),this.emit("time:changed",{value:this.getValue()}))}_serialize(){if(!this.currentTime)return"";const e=Z(this.currentTime,"24h");if(!this.timezone||!this.currentTimezone)return e;if(this.outputFormat==="iana")return`${e} ${this.currentTimezone}`;const t=Ct(this.currentTimezone,new Date);return t?`${e}${t}`:e}_displayText(){if(!this.currentTime)return"";const e=Z(this.currentTime,this.format);return this.timezone&&this.currentTimezone?`${e} ${this.currentTimezone}`:e}getValue(){return this.currentTime?this.timezone&&this.outputFormat==="object"?{time:Z(this.currentTime,"24h"),timezone:this.currentTimezone||null}:this._serialize():this.outputFormat==="object"?null:""}setValue(e){const t=this._serialize(),s=this._parseInitial(e);this.currentTime=s.time,s.timezone&&(this.currentTimezone=s.timezone),this._refreshSpinnerDisplay(),this._syncOutputs(t)}getFormattedValue(){return this._displayText()}clear(){if(!this.currentTime&&!this.element.querySelector("[data-hidden-value]")?.value)return;const e=this._serialize();this.currentTime=null,this._syncOutputs(e)}setMin(e){this.min=e}setMax(e){this.max=e}setEnabled(e){this.disabled=!e;const t=this.element.querySelector("[data-trigger]");t&&(t.disabled=!e),!e&&this._popover&&this._popover.isOpen()&&this._popover.close()}setReadonly(e){this.readonly=e,e&&this._popover&&this._popover.isOpen()&&this._popover.close()}focus(){const e=this.element.querySelector("[data-trigger]");e&&e.focus()}show(){const e=this.element.querySelector("[data-trigger]");e&&this._togglePopover(e)}hide(){this._popover&&this._popover.close()}getFormValue(){return this.getValue()}async setFormValue(e){this.setValue(e)}hasError(){return!1}_inputId(){return this.name?`mojo-time-${this.name}-${this.id}`:`mojo-time-${this.id}`}_attr(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}async onBeforeDestroy(){if(this._popover){try{this._popover.destroy()}catch{}this._popover=null}if(this._tzSelect){try{await this._tzSelect.destroy()}catch{}this._tzSelect=null}this._spinner=null,await super.onBeforeDestroy()}static addMinutes(e,t){return hs(e,t)}static create(e={}){return new $e(e)}}function Ue(c){return c<10?"0"+c:String(c)}function vs(){try{return new Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}catch{return"UTC"}}const Cs="MMM DD, YYYY";class We extends S{constructor(e={}){const{name:t,value:s="",format:i=null,displayFormat:r=null,timeFormat:n="24h",timeStep:a=1,min:o=null,max:l=null,placeholder:d=null,disabled:h=!1,readonly:u=!1,required:m=!1,class:p="",inline:f=!1,disabledDates:g=[],firstDay:b=1,lang:y="en-US",autoApply:C=!1,timezone:_=!1,timezones:A=null,outputFormat:F="iso",...j}=e;super({tagName:"div",className:`mojo-datetime-picker ${p}`.trim(),...j}),this.name=t,this.format=i,this.displayFormat=r||Cs,this.timeFormat=n==="12h"?"12h":"24h",this.timeStep=Math.max(1,parseInt(a,10)||1),this.min=o,this.max=l,this.placeholder=d??"Pick date & time...",this.disabled=h,this.readonly=u,this.required=m,this.inline=f,this.disabledDates=g,this.firstDay=b,this.lang=y,this.autoApply=C,this.timezone=_===!0||Array.isArray(_),this.timezoneList=Array.isArray(_)?_:A,this.outputFormat=["object","iana","iso"].includes(F)?F:"iso";const I=this._parseInitial(s);this.currentDate=I.date,this.currentTime=I.time,this.currentTimezone=I.timezone||(this.timezone?Mt():null),this._calendar=null,this._timePicker=null,this._tzSelect=null,this._popover=null,this._popoverContent=null}_parseInitial(e){return e==null||e===""?{date:null,time:null,timezone:null}:typeof e=="object"&&!Array.isArray(e)&&!(e instanceof Date)?St(e)||{date:null,time:null,timezone:null}:St(e)||{date:null,time:null,timezone:null}}async renderTemplate(){const e=this._inputId(),t=this._displayText(),s=!this.currentDate,i=this._serialize();return this.inline?`
1197
1197
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(i)}" data-hidden-value />
1198
1198
  <div data-dt-host class="mojo-datetime-picker-inline${this.hasError()?" is-invalid":""}"></div>
1199
1199
  `:`
@@ -1205,7 +1205,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1205
1205
  ${!this.required&&!this.disabled&&!this.readonly?'<button type="button" class="mojo-datetime-trigger-clear" data-clear aria-label="Clear" tabindex="-1">&#x2715;</button>':""}
1206
1206
  </button>
1207
1207
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(i)}" data-hidden-value />
1208
- `}async onAfterRender(){this.inline?this._mountInline():this._wireTrigger()}_wireTrigger(){const e=this.element.querySelector("[data-trigger]"),t=this.element.querySelector("[data-clear]");e&&(e.addEventListener("click",s=>{s.target.closest("[data-clear]")||this._togglePopover(e)}),t&&t.addEventListener("click",s=>{s.stopPropagation(),this.clear()}))}_togglePopover(e){if(!(this.disabled||this.readonly)){if(this._popover?this._popover.setAnchor(e):this._popover=new _e({anchor:e,classNames:"mojo-datetime-popover"}),this._popover.isOpen()){this._popover.close();return}this._popoverContent||(this._popoverContent=this._buildContent()),this._popover.setContent(this._popoverContent),this._popover.open(),this._calendar&&this._calendar.render(!1)}}_mountInline(){const e=this.element.querySelector("[data-dt-host]");e&&(this._popoverContent||(this._popoverContent=this._buildContent()),e.appendChild(this._popoverContent),this._calendar&&this._calendar.render(!1))}_buildContent(){const e=document.createElement("div");e.className="mojo-datetime-popover-inner";const t=document.createElement("div");t.className="mojo-datetime-row";const s=document.createElement("div");s.className="mojo-datetime-cal-col",t.appendChild(s);const i=document.createElement("div");i.className="mojo-datetime-time-col",t.appendChild(i),e.appendChild(t),this._calendar=new He({precision:"day",mode:"single",months:1,value:this.currentDate?B(this.currentDate):null,min:this._dateBound(this.min),max:this._dateBound(this.max),disabledDates:this.disabledDates,firstDay:this.firstDay,locale:this.lang}),s.appendChild(this._calendar.element),this._calendar.on("select",({value:l})=>{const d=q(l);this.currentDate=d,this.currentTime||(this.currentTime={hours:0,minutes:0}),this._refreshTimezoneDefault(),this._syncOutputs()}),this._timePicker=new $e({name:null,value:this.currentTime?Z(this.currentTime,"24h"):"",format:this.timeFormat,step:this.timeStep,timezone:!1,inline:!0,autoApply:!1,showFooter:!1});const r=document.createElement("div");if(r.className="mojo-datetime-time-head",r.textContent="Time",i.appendChild(r),i.appendChild(this._timePicker.element),this._timePicker.on("change",()=>{const l=this._timePicker.currentTime;if(this.currentTime=l?{...l}:null,this.currentTime&&!this.currentDate){const d=new Date;this.currentDate={y:d.getFullYear(),m:d.getMonth()+1,d:d.getDate()},this._calendar&&this._calendar.setValue(B(this.currentDate))}this._syncOutputs()}),this._timePicker.render(!1),this.timezone){const l=document.createElement("div");l.className="mojo-datetime-tz-row";const d=document.createElement("div");d.className="mojo-datetime-tz-label",d.textContent="Timezone",l.appendChild(d);const h=document.createElement("div");h.className="mojo-datetime-tz-host",l.appendChild(h),e.appendChild(l),this._tzSelect=new Dt({name:"timezone",value:this.currentTimezone,timezones:Array.isArray(this.timezoneList)?this.timezoneList:null}),this._tzSelect.render(!0,h),this._tzSelect.on("change",({value:u})=>{const m=this.currentTimezone;this.currentTimezone=u||null,m!==this.currentTimezone&&this._syncOutputs()})}const n=document.createElement("div");n.className="mojo-datetime-foot";const a=document.createElement("button");a.type="button",a.className="btn btn-link btn-sm",a.textContent="Now",a.addEventListener("click",l=>{l.preventDefault();const d=new Date;this.currentDate={y:d.getFullYear(),m:d.getMonth()+1,d:d.getDate()},this.currentTime={hours:d.getHours(),minutes:d.getMinutes()},this._calendar&&this._calendar.setValue(B(this.currentDate)),this._timePicker&&this._timePicker.setValue(Z(this.currentTime,"24h")),this._syncOutputs()}),n.appendChild(a);const o=document.createElement("button");return o.type="button",o.className="btn btn-primary btn-sm",o.textContent="Done",o.addEventListener("click",l=>{l.preventDefault(),this._popover&&this._popover.isOpen()&&this._popover.close()}),n.appendChild(o),e.appendChild(n),e}_refreshTimezoneDefault(){this.timezone&&!this.currentTimezone&&this._timePicker&&(this.currentTimezone=this._timePicker.currentTimezone||It())}_timePickerValue(){if(!this.currentTime&&!this.currentTimezone)return"";const e=this.currentTime?Z(this.currentTime,"24h"):"00:00";return this.timezone&&this.currentTimezone?`${e} ${this.currentTimezone}`:e}_dateBound(e){return e?String(e).trim().split(/[ T]/)[0]:null}_syncOutputs(e){const t=this._serialize(),s=this._displayText(),i=this.element&&this.element.querySelector("[data-trigger-text]");i&&(i.textContent=s||this.placeholder,i.classList.toggle("is-empty",!this.currentDate));const r=this.element&&this.element.querySelector("[data-hidden-value]");r&&(r.value=t),e!==void 0&&e!==t?(this.emit("change",{value:this.getValue(),formatted:s,oldValue:e}),this.emit("datetime:changed",{value:this.getValue()})):e===void 0&&this.emit("change",{value:this.getValue(),formatted:s,oldValue:null})}_serialize(){if(!this.currentDate)return"";const e=B(this.currentDate),t=this.currentTime?Z(this.currentTime,"24h"):"00:00";if(this.outputFormat==="iana"){let i=`${e} ${t}`;return this.timezone&&this.currentTimezone&&(i+=` ${this.currentTimezone}`),i}let s=`${e}T${t}:00`;if(this.timezone&&this.currentTimezone){const i=new Date(this.currentDate.y,this.currentDate.m-1,this.currentDate.d,this.currentTime?.hours||0,this.currentTime?.minutes||0),r=Ct(this.currentTimezone,i);r&&(s+=r)}return s}_displayText(){if(!this.currentDate)return"";const e=he(this.currentDate,this.displayFormat),t=this.currentTime?Z(this.currentTime,this.timeFormat):this.timeFormat==="12h"?"12:00 AM":"00:00";let s=`${e} ${t}`;return this.timezone&&this.currentTimezone&&(s+=` ${this.currentTimezone}`),s}getValue(){if(!this.currentDate)return this.outputFormat==="object"?null:"";if(this.outputFormat==="object"){const e={date:B(this.currentDate),time:this.currentTime?Z(this.currentTime,"24h"):"00:00"};return this.timezone&&(e.timezone=this.currentTimezone||null),e}return this._serialize()}setValue(e){const t=this._parseInitial(e);this.currentDate=t.date,this.currentTime=t.time,t.timezone&&(this.currentTimezone=t.timezone),this._calendar&&this.currentDate&&this._calendar.setValue(B(this.currentDate)),this._timePicker&&this._timePicker.setValue(this._timePickerValue()),this._syncOutputs()}getFormattedValue(){return this._displayText()}clear(){const e=this._serialize();this.currentDate=null,this.currentTime=null,this._calendar&&this._calendar.setValue(null),this._timePicker&&this._timePicker.clear(),this._syncOutputs(e)}setMin(e){this.min=e,this._calendar&&this._calendar.setMin(this._dateBound(e))}setMax(e){this.max=e,this._calendar&&this._calendar.setMax(this._dateBound(e))}setEnabled(e){this.disabled=!e;const t=this.element.querySelector("[data-trigger]");t&&(t.disabled=!e),!e&&this._popover&&this._popover.isOpen()&&this._popover.close()}setReadonly(e){this.readonly=e,e&&this._popover&&this._popover.isOpen()&&this._popover.close()}focus(){const e=this.element.querySelector("[data-trigger]");e&&e.focus()}show(){const e=this.element.querySelector("[data-trigger]");e&&this._togglePopover(e)}hide(){this._popover&&this._popover.close()}getFormValue(){return this.getValue()}async setFormValue(e){this.setValue(e)}hasError(){return!1}_inputId(){return this.name?`mojo-datetime-${this.name}-${this.id}`:`mojo-datetime-${this.id}`}_attr(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}async onBeforeDestroy(){if(this._popover){try{this._popover.destroy()}catch{}this._popover=null}if(this._timePicker){try{await this._timePicker.destroy()}catch{}this._timePicker=null}if(this._tzSelect){try{await this._tzSelect.destroy()}catch{}this._tzSelect=null}this._calendar=null,this._popoverContent=null,await super.onBeforeDestroy()}static create(e={}){return new We(e)}}function It(){try{return new Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}catch{return"UTC"}}class Ye extends S{constructor(e={}){const{name:t,value:s="",placeholder:i="Select or type...",options:r=[],allowCustom:n=!0,showDescription:a=!0,minChars:o=0,maxSuggestions:l=10,disabled:d=!1,readonly:h=!1,required:u=!1,class:m="",inputClass:p="form-control",onSelect:f=null,onChange:g=null,...b}=e;super({tagName:"div",className:`combo-input ${m}`,...b}),this.name=t,this.placeholder=i,this.options=this.normalizeOptions(r),this.allowCustom=n,this.showDescription=a,this.minChars=o,this.maxSuggestions=l,this.disabled=d,this.readonly=h,this.required=u,this.inputClass=p,this.onSelectCallback=f,this.onChangeCallback=g,this.currentValue=s,this.inputValue=this.getDisplayValue(s),this.filteredOptions=[],this.highlightedIndex=-1,this.isOpen=!1,this.selectedOption=this.findOptionByValue(s)}normalizeOptions(e){return Array.isArray(e)?e.map(t=>typeof t=="string"?{value:t,label:t}:typeof t=="object"&&t.value!==void 0?{value:t.value,label:t.label||String(t.value),description:t.description||t.label||"",meta:t.meta||{}}:null).filter(t=>t!==null):[]}findOptionByValue(e){return this.options.find(t=>t.value===e)||null}getDisplayValue(e){const t=this.findOptionByValue(e);return t?t.label:e}async renderTemplate(){return`
1208
+ `}async onAfterRender(){this.inline?this._mountInline():this._wireTrigger()}_wireTrigger(){const e=this.element.querySelector("[data-trigger]"),t=this.element.querySelector("[data-clear]");e&&(e.addEventListener("click",s=>{s.target.closest("[data-clear]")||this._togglePopover(e)}),t&&t.addEventListener("click",s=>{s.stopPropagation(),this.clear()}))}_togglePopover(e){if(!(this.disabled||this.readonly)){if(this._popover?this._popover.setAnchor(e):this._popover=new _e({anchor:e,classNames:"mojo-datetime-popover"}),this._popover.isOpen()){this._popover.close();return}this._popoverContent||(this._popoverContent=this._buildContent()),this._popover.setContent(this._popoverContent),this._popover.open(),this._calendar&&this._calendar.render(!1)}}_mountInline(){const e=this.element.querySelector("[data-dt-host]");e&&(this._popoverContent||(this._popoverContent=this._buildContent()),e.appendChild(this._popoverContent),this._calendar&&this._calendar.render(!1))}_buildContent(){const e=document.createElement("div");e.className="mojo-datetime-popover-inner";const t=document.createElement("div");t.className="mojo-datetime-row";const s=document.createElement("div");s.className="mojo-datetime-cal-col",t.appendChild(s);const i=document.createElement("div");i.className="mojo-datetime-time-col",t.appendChild(i),e.appendChild(t),this._calendar=new He({precision:"day",mode:"single",months:1,value:this.currentDate?B(this.currentDate):null,min:this._dateBound(this.min),max:this._dateBound(this.max),disabledDates:this.disabledDates,firstDay:this.firstDay,locale:this.lang}),s.appendChild(this._calendar.element),this._calendar.on("select",({value:l})=>{const d=q(l);this.currentDate=d,this.currentTime||(this.currentTime={hours:0,minutes:0}),this._refreshTimezoneDefault(),this._syncOutputs()}),this._timePicker=new $e({name:null,value:this.currentTime?Z(this.currentTime,"24h"):"",format:this.timeFormat,step:this.timeStep,timezone:!1,inline:!0,autoApply:!1,showFooter:!1});const r=document.createElement("div");if(r.className="mojo-datetime-time-head",r.textContent="Time",i.appendChild(r),i.appendChild(this._timePicker.element),this._timePicker.on("change",()=>{const l=this._timePicker.currentTime;if(this.currentTime=l?{...l}:null,this.currentTime&&!this.currentDate){const d=new Date;this.currentDate={y:d.getFullYear(),m:d.getMonth()+1,d:d.getDate()},this._calendar&&this._calendar.setValue(B(this.currentDate))}this._syncOutputs()}),this._timePicker.render(!1),this.timezone){const l=document.createElement("div");l.className="mojo-datetime-tz-row";const d=document.createElement("div");d.className="mojo-datetime-tz-label",d.textContent="Timezone",l.appendChild(d);const h=document.createElement("div");h.className="mojo-datetime-tz-host",l.appendChild(h),e.appendChild(l),this._tzSelect=new Dt({name:"timezone",value:this.currentTimezone,timezones:Array.isArray(this.timezoneList)?this.timezoneList:null}),this._tzSelect.render(!0,h),this._tzSelect.on("change",({value:u})=>{const m=this.currentTimezone;this.currentTimezone=u||null,m!==this.currentTimezone&&this._syncOutputs()})}const n=document.createElement("div");n.className="mojo-datetime-foot";const a=document.createElement("button");a.type="button",a.className="btn btn-link btn-sm",a.textContent="Now",a.addEventListener("click",l=>{l.preventDefault();const d=new Date;this.currentDate={y:d.getFullYear(),m:d.getMonth()+1,d:d.getDate()},this.currentTime={hours:d.getHours(),minutes:d.getMinutes()},this._calendar&&this._calendar.setValue(B(this.currentDate)),this._timePicker&&this._timePicker.setValue(Z(this.currentTime,"24h")),this._syncOutputs()}),n.appendChild(a);const o=document.createElement("button");return o.type="button",o.className="btn btn-primary btn-sm",o.textContent="Done",o.addEventListener("click",l=>{l.preventDefault(),this._popover&&this._popover.isOpen()&&this._popover.close()}),n.appendChild(o),e.appendChild(n),e}_refreshTimezoneDefault(){this.timezone&&!this.currentTimezone&&this._timePicker&&(this.currentTimezone=this._timePicker.currentTimezone||Mt())}_timePickerValue(){if(!this.currentTime&&!this.currentTimezone)return"";const e=this.currentTime?Z(this.currentTime,"24h"):"00:00";return this.timezone&&this.currentTimezone?`${e} ${this.currentTimezone}`:e}_dateBound(e){return e?String(e).trim().split(/[ T]/)[0]:null}_syncOutputs(e){const t=this._serialize(),s=this._displayText(),i=this.element&&this.element.querySelector("[data-trigger-text]");i&&(i.textContent=s||this.placeholder,i.classList.toggle("is-empty",!this.currentDate));const r=this.element&&this.element.querySelector("[data-hidden-value]");r&&(r.value=t),e!==void 0&&e!==t?(this.emit("change",{value:this.getValue(),formatted:s,oldValue:e}),this.emit("datetime:changed",{value:this.getValue()})):e===void 0&&this.emit("change",{value:this.getValue(),formatted:s,oldValue:null})}_serialize(){if(!this.currentDate)return"";const e=B(this.currentDate),t=this.currentTime?Z(this.currentTime,"24h"):"00:00";if(this.outputFormat==="iana"){let i=`${e} ${t}`;return this.timezone&&this.currentTimezone&&(i+=` ${this.currentTimezone}`),i}let s=`${e}T${t}:00`;if(this.timezone&&this.currentTimezone){const i=new Date(this.currentDate.y,this.currentDate.m-1,this.currentDate.d,this.currentTime?.hours||0,this.currentTime?.minutes||0),r=Ct(this.currentTimezone,i);r&&(s+=r)}return s}_displayText(){if(!this.currentDate)return"";const e=he(this.currentDate,this.displayFormat),t=this.currentTime?Z(this.currentTime,this.timeFormat):this.timeFormat==="12h"?"12:00 AM":"00:00";let s=`${e} ${t}`;return this.timezone&&this.currentTimezone&&(s+=` ${this.currentTimezone}`),s}getValue(){if(!this.currentDate)return this.outputFormat==="object"?null:"";if(this.outputFormat==="object"){const e={date:B(this.currentDate),time:this.currentTime?Z(this.currentTime,"24h"):"00:00"};return this.timezone&&(e.timezone=this.currentTimezone||null),e}return this._serialize()}setValue(e){const t=this._parseInitial(e);this.currentDate=t.date,this.currentTime=t.time,t.timezone&&(this.currentTimezone=t.timezone),this._calendar&&this.currentDate&&this._calendar.setValue(B(this.currentDate)),this._timePicker&&this._timePicker.setValue(this._timePickerValue()),this._syncOutputs()}getFormattedValue(){return this._displayText()}clear(){const e=this._serialize();this.currentDate=null,this.currentTime=null,this._calendar&&this._calendar.setValue(null),this._timePicker&&this._timePicker.clear(),this._syncOutputs(e)}setMin(e){this.min=e,this._calendar&&this._calendar.setMin(this._dateBound(e))}setMax(e){this.max=e,this._calendar&&this._calendar.setMax(this._dateBound(e))}setEnabled(e){this.disabled=!e;const t=this.element.querySelector("[data-trigger]");t&&(t.disabled=!e),!e&&this._popover&&this._popover.isOpen()&&this._popover.close()}setReadonly(e){this.readonly=e,e&&this._popover&&this._popover.isOpen()&&this._popover.close()}focus(){const e=this.element.querySelector("[data-trigger]");e&&e.focus()}show(){const e=this.element.querySelector("[data-trigger]");e&&this._togglePopover(e)}hide(){this._popover&&this._popover.close()}getFormValue(){return this.getValue()}async setFormValue(e){this.setValue(e)}hasError(){return!1}_inputId(){return this.name?`mojo-datetime-${this.name}-${this.id}`:`mojo-datetime-${this.id}`}_attr(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}async onBeforeDestroy(){if(this._popover){try{this._popover.destroy()}catch{}this._popover=null}if(this._timePicker){try{await this._timePicker.destroy()}catch{}this._timePicker=null}if(this._tzSelect){try{await this._tzSelect.destroy()}catch{}this._tzSelect=null}this._calendar=null,this._popoverContent=null,await super.onBeforeDestroy()}static create(e={}){return new We(e)}}function Mt(){try{return new Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}catch{return"UTC"}}class Ye extends S{constructor(e={}){const{name:t,value:s="",placeholder:i="Select or type...",options:r=[],allowCustom:n=!0,showDescription:a=!0,minChars:o=0,maxSuggestions:l=10,disabled:d=!1,readonly:h=!1,required:u=!1,class:m="",inputClass:p="form-control",onSelect:f=null,onChange:g=null,...b}=e;super({tagName:"div",className:`combo-input ${m}`,...b}),this.name=t,this.placeholder=i,this.options=this.normalizeOptions(r),this.allowCustom=n,this.showDescription=a,this.minChars=o,this.maxSuggestions=l,this.disabled=d,this.readonly=h,this.required=u,this.inputClass=p,this.onSelectCallback=f,this.onChangeCallback=g,this.currentValue=s,this.inputValue=this.getDisplayValue(s),this.filteredOptions=[],this.highlightedIndex=-1,this.isOpen=!1,this.selectedOption=this.findOptionByValue(s)}normalizeOptions(e){return Array.isArray(e)?e.map(t=>typeof t=="string"?{value:t,label:t}:typeof t=="object"&&t.value!==void 0?{value:t.value,label:t.label||String(t.value),description:t.description||t.label||"",meta:t.meta||{}}:null).filter(t=>t!==null):[]}findOptionByValue(e){return this.options.find(t=>t.value===e)||null}getDisplayValue(e){const t=this.findOptionByValue(e);return t?t.label:e}async renderTemplate(){return`
1209
1209
  <div class="combo-input-container position-relative">
1210
1210
  <div class="input-wrapper position-relative">
1211
1211
  ${this.renderInput()}
@@ -1315,7 +1315,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1315
1315
  </div>
1316
1316
  <i class="bi bi-check-circle text-success d-none" data-status="saved"></i>
1317
1317
  <i class="bi bi-exclamation-circle text-danger d-none" data-status="error"></i>
1318
- `}showStatus(e,t={}){this.clearTimeout(e),this.showStandardStatus(e,t)}showStandardStatus(e,t={}){this.hideAllStatuses();const s=this.statusContainer.querySelector(`[data-status="${e}"]`);s&&(s.classList.remove("d-none"),s.classList.add("d-inline-block","show"),e==="saved"?this.setTimeout(e,()=>this.hideStatus(e),2500):e==="error"&&(t.message&&(s.title=t.message),this.setTimeout(e,()=>this.hideStatus(e),6e3)))}showFullOverlayStatus(e,t={}){this.statusContainer.querySelectorAll(".saving-indicator, .success-indicator, .error-indicator").forEach(r=>r.classList.add("d-none")),this.statusContainer.classList.remove("d-none");let i;switch(e){case"saving":i=".saving-indicator";break;case"saved":i=".success-indicator",this.setTimeout(e,()=>this.hideStatus(e),2500);break;case"error":if(i=".error-indicator",t.message){const r=this.statusContainer.querySelector(".error-indicator span");r&&(r.textContent=t.message)}this.setTimeout(e,()=>this.hideStatus(e),6e3);break}if(i){const r=this.statusContainer.querySelector(i);r&&r.classList.remove("d-none")}}hideStatus(e){const t=this.statusContainer.querySelector(`[data-status="${e}"]`);t&&(t.classList.remove("show"),t.classList.add("hide"),setTimeout(()=>{t.classList.add("d-none"),t.classList.remove("d-inline-block","hide"),t.title=""},300))}hideAllStatuses(){this.statusContainer.querySelectorAll("[data-status]").forEach(t=>{t.classList.add("d-none"),t.classList.remove("d-inline-block","show","hide"),t.title=""})}setTimeout(e,t,s){const i=setTimeout(t,s);this.timeouts.set(e,i)}clearTimeout(e){this.timeouts.has(e)&&(clearTimeout(this.timeouts.get(e)),this.timeouts.delete(e))}destroy(){this.timeouts.forEach(e=>clearTimeout(e)),this.timeouts.clear()}}es(te);const Mt=Object.freeze(Object.defineProperty({__proto__:null,FormView:te,default:te},Symbol.toStringTag,{value:"Module"}));class _s extends pe{constructor(e={}){super({title:"Form Page",description:"A page for submitting forms",icon:"form",fields:[],template:'<div data-container="form-view-container"></div>',className:"form-page container-sm",...e})}async onInit(){await super.onInit(),await this.recreateFormView()}async onEnter(){await super.onEnter(),this.formView&&await this.recreateFormView()}async onGroupChange(e){this.formView&&await this.recreateFormView()}async getModel(){return this.model?this.model:this.getApp().activeGroup?this.getApp().activeGroup:null}async recreateFormView(){this.formView&&(await this.formView.destroy(),this.removeChild(this.formView)),this.formView=new te({containerId:"form-view-container",fields:this.options.fields,autosaveModelField:!0}),this.addChild(this.formView);const e=await this.getModel();e&&this.formView.setModel(e)}}x.showDialog=(...c)=>v.dialog(...c),x.alert=(...c)=>v.alert(...c),x.confirm=(...c)=>v.confirm(...c),x.prompt=(...c)=>v.prompt(...c),x.showError=(...c)=>v.showError(...c),x.showForm=(...c)=>v.form(...c),x.showModelForm=(...c)=>v.modelForm(...c),x.showData=(...c)=>v.data(...c),x.showModelView=(...c)=>v.showModelView(...c),x.updateModelImage=(...c)=>v.updateModelImage(...c),x.showCode=(...c)=>v.code(...c),x.showHtmlPreview=(...c)=>v.htmlPreview(...c),x.formatCode=(...c)=>me.formatCode(...c),x.highlightCodeBlocks=(...c)=>me.highlightCodeBlocks(...c),x.showBusy=(...c)=>v.showBusy(...c),x.hideBusy=(...c)=>v.hideBusy(...c),x.showConfirm=x.confirm;class xs extends S{constructor(e={}){const{options:t=[],value:s,size:i="sm",ariaLabel:r="Segment control",...n}=e;super({tagName:"div",className:"segment-control",...n}),this.items=t,this.value=s!==void 0?s:t[0]&&t[0].value,this.size=i==="md"?"":"sm",this.ariaLabel=r,this.template=()=>this._buildTemplate()}_buildTemplate(){const e=this.size?`btn-group-${this.size}`:"",t=this.items.map(s=>{const i=s.value===this.value,r=i?"btn btn-primary":"btn btn-outline-secondary",n=s.icon?`<i class="bi ${this.escapeHtml(s.icon)} me-1"></i>`:"";return`<button type="button"
1318
+ `}showStatus(e,t={}){this.clearTimeout(e),this.showStandardStatus(e,t)}showStandardStatus(e,t={}){this.hideAllStatuses();const s=this.statusContainer.querySelector(`[data-status="${e}"]`);s&&(s.classList.remove("d-none"),s.classList.add("d-inline-block","show"),e==="saved"?this.setTimeout(e,()=>this.hideStatus(e),2500):e==="error"&&(t.message&&(s.title=t.message),this.setTimeout(e,()=>this.hideStatus(e),6e3)))}showFullOverlayStatus(e,t={}){this.statusContainer.querySelectorAll(".saving-indicator, .success-indicator, .error-indicator").forEach(r=>r.classList.add("d-none")),this.statusContainer.classList.remove("d-none");let i;switch(e){case"saving":i=".saving-indicator";break;case"saved":i=".success-indicator",this.setTimeout(e,()=>this.hideStatus(e),2500);break;case"error":if(i=".error-indicator",t.message){const r=this.statusContainer.querySelector(".error-indicator span");r&&(r.textContent=t.message)}this.setTimeout(e,()=>this.hideStatus(e),6e3);break}if(i){const r=this.statusContainer.querySelector(i);r&&r.classList.remove("d-none")}}hideStatus(e){const t=this.statusContainer.querySelector(`[data-status="${e}"]`);t&&(t.classList.remove("show"),t.classList.add("hide"),setTimeout(()=>{t.classList.add("d-none"),t.classList.remove("d-inline-block","hide"),t.title=""},300))}hideAllStatuses(){this.statusContainer.querySelectorAll("[data-status]").forEach(t=>{t.classList.add("d-none"),t.classList.remove("d-inline-block","show","hide"),t.title=""})}setTimeout(e,t,s){const i=setTimeout(t,s);this.timeouts.set(e,i)}clearTimeout(e){this.timeouts.has(e)&&(clearTimeout(this.timeouts.get(e)),this.timeouts.delete(e))}destroy(){this.timeouts.forEach(e=>clearTimeout(e)),this.timeouts.clear()}}es(te);const It=Object.freeze(Object.defineProperty({__proto__:null,FormView:te,default:te},Symbol.toStringTag,{value:"Module"}));class _s extends pe{constructor(e={}){super({title:"Form Page",description:"A page for submitting forms",icon:"form",fields:[],template:'<div data-container="form-view-container"></div>',className:"form-page container-sm",...e})}async onInit(){await super.onInit(),await this.recreateFormView()}async onEnter(){await super.onEnter(),this.formView&&await this.recreateFormView()}async onGroupChange(e){this.formView&&await this.recreateFormView()}async getModel(){return this.model?this.model:this.getApp().activeGroup?this.getApp().activeGroup:null}async recreateFormView(){this.formView&&(await this.formView.destroy(),this.removeChild(this.formView)),this.formView=new te({containerId:"form-view-container",fields:this.options.fields,autosaveModelField:!0}),this.addChild(this.formView);const e=await this.getModel();e&&this.formView.setModel(e)}}x.showDialog=(...c)=>v.dialog(...c),x.alert=(...c)=>v.alert(...c),x.confirm=(...c)=>v.confirm(...c),x.prompt=(...c)=>v.prompt(...c),x.showError=(...c)=>v.showError(...c),x.showForm=(...c)=>v.form(...c),x.showModelForm=(...c)=>v.modelForm(...c),x.showData=(...c)=>v.data(...c),x.showModelView=(...c)=>v.showModelView(...c),x.updateModelImage=(...c)=>v.updateModelImage(...c),x.showCode=(...c)=>v.code(...c),x.showHtmlPreview=(...c)=>v.htmlPreview(...c),x.formatCode=(...c)=>me.formatCode(...c),x.highlightCodeBlocks=(...c)=>me.highlightCodeBlocks(...c),x.showBusy=(...c)=>v.showBusy(...c),x.hideBusy=(...c)=>v.hideBusy(...c),x.showConfirm=x.confirm;class xs extends S{constructor(e={}){const{options:t=[],value:s,size:i="sm",ariaLabel:r="Segment control",...n}=e;super({tagName:"div",className:"segment-control",...n}),this.items=t,this.value=s!==void 0?s:t[0]&&t[0].value,this.size=i==="md"?"":"sm",this.ariaLabel=r,this.template=()=>this._buildTemplate()}_buildTemplate(){const e=this.size?`btn-group-${this.size}`:"",t=this.items.map(s=>{const i=s.value===this.value,r=i?"btn btn-primary":"btn btn-outline-secondary",n=s.icon?`<i class="bi ${this.escapeHtml(s.icon)} me-1"></i>`:"";return`<button type="button"
1319
1319
  class="${r}"
1320
1320
  data-action="select"
1321
1321
  data-value="${this.escapeHtml(String(s.value))}"
@@ -1597,7 +1597,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1597
1597
  <i class="bi bi-chevron-right"></i>
1598
1598
  </a>
1599
1599
  </li>
1600
- `),e.innerHTML=l.join("")}async onActionPage(e,t){e.preventDefault();const s=parseInt(t.getAttribute("data-page"),10),i=this.collection.params?.size||10,r=this.collection.meta?.count||this.collection.length(),n=Math.max(1,Math.ceil(r/i));let a=isNaN(s)?1:s;a<1&&(a=n),a>n&&(a=1),this.collection.setParams({...this.collection.params,start:(a-1)*i}),this.collection.restEnabled?await this.collection.fetch():this.render(),this.emit("list:page",{page:a,event:e}),this.emit("params-changed")}async onChangePageSize(e,t){const s=parseInt(t.value,10);this.collection&&(this.collection.setParams({...this.collection.params,start:0,size:s}),this.collection.restEnabled&&await this.collection.fetch(),this.render()),this.emit("list:pagesize",{size:s}),this.emit("params-changed")}_computeHasMore(){if(this.paginationMode!=="more"||!this.collection)return!1;const e=this.collection.meta?.count;return typeof e!="number"?!1:this.collection.length()<e}async onActionShowMore(e,t){if(!this.loadingMore){if(!this.collection||typeof this.collection.fetchMore!="function"){console.warn("ListView: collection does not support fetchMore()");return}this.loadingMore=!0,this.isMounted()&&await this.render();try{const s=await this.collection.fetchMore();this.emit("list:show-more",{response:s})}catch(s){console.error("ListView: fetchMore failed",s)}finally{this.loadingMore=!1,this.isMounted()&&await this.render()}}}async onActionSortOption(e,t){e.preventDefault();const s=t.getAttribute("data-sort");this.collection&&(this.collection.setParams({...this.collection.params,sort:s||void 0,start:0}),this.collection.restEnabled?await this.collection.fetch():this.render()),this.emit("list:sort",{sort:s}),this.emit("params-changed")}async onActionCustomToolbarButton(e,t){const s=parseInt(t.getAttribute("data-button-index"),10),i=this.toolbarButtons[s];i&&typeof i.handler=="function"&&await i.handler.call(this,e,t)}async onActionAddFilter(e,t){const s=t.getAttribute("data-filter-key"),i=this.getFilterConfig(s),r=this.getActiveFilters()[s];if(!i){console.warn("No filter config found for key:",s);return}const n=await v.form({title:`${r!==void 0&&r!==""?"Edit":"Add"} ${this.getFilterLabel(s)} Filter`,size:"md",fields:[this.buildFilterDialogField(i,r,s)]});if(n){const a=this.extractFilterValue(i,n);this.setFilter(s,a),await this.applyFilters()}}async onActionEditFilter(e,t){const s=t.getAttribute("data-filter"),{field:i}=ge(s),r=this.getFilterConfig(i)||this.getFilterConfig(s),n=this.getActiveFilters(),a=n[s]||n[i];if(!r){console.warn("No filter config found for key:",s,"or field:",i);return}const o={filter_value:a};if(r.type==="daterange"&&a&&typeof a=="object"){const d=r.startName||"dr_start",h=r.endName||"dr_end";o[d]=a.start||"",o[h]=a.end||""}const l=await v.form({title:`Edit ${this.getFilterLabel(i)} Filter`,size:"md",data:o,fields:[this.buildFilterDialogField(r,a,i)]});if(l){const d=this.extractFilterValue(r,l);this.setFilter(s,d),await this.applyFilters()}}async onActionRemoveFilter(e,t){const s=t.getAttribute("data-filter"),{field:i}=ge(s);this.setFilter(s,null),s==="search"&&this.updateSearchInputs(""),this.collection?.restEnabled&&await this.collection.fetch(),this.render(),this.updateFilterPills(),this.emit("filter:remove",{key:s,field:i}),this.emit("params-changed")}async onActionClearAllFilters(e,t){if(!this.collection)return;const{start:s,size:i,sort:r}=this.collection.params,n={start:s,size:i};r&&(n.sort=r),Array.isArray(this.hideActivePillNames)&&this.hideActivePillNames.length>0&&this.hideActivePillNames.forEach(a=>{this.collection.params[a]!==void 0&&(n[a]=this.collection.params[a]);const o=this.getFilterConfig(a);if(o&&o.type==="daterange"){const l=o.startName||"dr_start",d=o.endName||"dr_end",h=o.fieldName||"dr_field";this.collection.params[l]!==void 0&&(n[l]=this.collection.params[l]),this.collection.params[d]!==void 0&&(n[d]=this.collection.params[d]),this.collection.params[h]!==void 0&&(n[h]=this.collection.params[h])}}),this.collection.params=n,this.updateSearchInputs(""),this.collection.restEnabled&&await this.collection.fetch(),this.render(),this.updateFilterPills(),this.emit("filters:clear"),this.emit("params-changed")}async applyFilters(){if(this.collection&&(this.collection.params.start=0),this.collection?.restEnabled)try{await this.collection.fetch(),await this.render()}catch(e){console.error("Failed to fetch filtered data:",e),await this.render()}else await this.render();this.updateFilterPills(),this.emit("params-changed")}getActiveFilters(){if(!this.collection?.params)return{};const{start:e,size:t,sort:s,...i}=this.collection.params,r={},n=new Set;return this.getAllAvailableFilters().forEach(o=>{if(o.config?.type==="daterange"){const l=o.key,d=o.config.startName||"dr_start",h=o.config.endName||"dr_end",u=o.config.fieldName||"dr_field";i[u]===l&&(i[d]||i[h])&&(r[l]={start:i[d]||"",end:i[h]||""},n.add(d),n.add(h),n.add(u))}}),Object.keys(i).forEach(o=>{n.has(o)||(r[o]=i[o])}),Object.keys(r).forEach(o=>{const l=`${o}__in`;Object.prototype.hasOwnProperty.call(r,l)&&delete r[o]}),r}setFilter(e,t){if(!this.collection)return;const s=this.getFilterConfig(e);if(s&&s.type==="daterange"){const i=s.startName||"dr_start",r=s.endName||"dr_end",n=s.fieldName||"dr_field";delete this.collection.params[i],delete this.collection.params[r],delete this.collection.params[n],t&&typeof t=="object"&&(t.start||t.end)&&(t.start&&(this.collection.params[i]=t.start),t.end&&(this.collection.params[r]=t.end),this.collection.params[n]=e)}else{const{field:i}=ge(e);if(delete this.collection.params[e],delete this.collection.params[i],delete this.collection.params[`${i}__in`],!t||Array.isArray(t)&&t.length===0)return;Array.isArray(t)?t.length===1?this.collection.params[i]=t[0]:this.collection.params[`${i}__in`]=t.join(","):this.collection.params[e]=t}}getAllAvailableFilters(){const e=[];return Object.entries(this.filters||{}).forEach(([t,s])=>{e.push({key:t,label:s.label||t,type:s.type,config:s})}),this.additionalFilters&&Array.isArray(this.additionalFilters)&&this.additionalFilters.forEach(t=>{e.push({key:t.name||t.key,label:t.label,type:t.type,config:t})}),e}getFilterConfig(e){if(this.filters&&this.filters[e])return this.filters[e];if(this.additionalFilters&&Array.isArray(this.additionalFilters)){const t=this.additionalFilters.find(s=>(s.name||s.key)===e);if(t)return t}return null}getFilterLabel(e){if(e==="search")return"Search";const t=this.filters?.[e];if(t&&t.label)return t.label;const s=this.additionalFilters?.find(i=>(i.name||i.key)===e);return s&&s.label?s.label:e.charAt(0).toUpperCase()+e.slice(1)}getFilterIcon(e){return{text:"search",select:"funnel",date:"calendar",daterange:"calendar-range",number:"123",boolean:"toggle-on"}[e]||"filter"}buildFilterDialogField(e,t,s){const{name:i,value:r,...n}=e,a={...n,name:"filter_value",label:n.label,value:t,placeholder:n.placeholder||n.placeHolder};if(e.type==="daterange"){if(a.startName=a.startName||"dr_start",a.endName=a.endName||"dr_end",a.fieldName=a.fieldName||"dr_field",a.format=a.format||"YYYY-MM-DD",a.displayFormat=a.displayFormat||"MMM DD, YYYY",a.separator=a.separator||" to ",a.label=a.label||"Date Range",t&&typeof t=="object"){const o=l=>{if(!l&&l!==0)return"";if(l instanceof Date&&!isNaN(l))return l.toISOString().slice(0,10);const d=String(l).trim();if(!d)return"";if(/^-?\d+$/.test(d)){const u=Number(d),m=d.length<=10?u*1e3:u,p=new Date(m);if(!isNaN(p))return p.toISOString().slice(0,10)}const h=new Date(d);return isNaN(h)?d:h.toISOString().slice(0,10)};a.startDate=o(t.start||t.from||t.begin||""),a.endDate=o(t.end||t.to||t.finish||"")}}else if(e.type==="multiselect"){let o=[];t&&(Array.isArray(t)?o=t:typeof t=="string"&&(o=t.split(",").map(l=>l.trim()).filter(l=>l))),a.value=o,!a.placeholder&&!a.placeHolder&&(e.placeholder||e.placeHolder?a.placeholder=e.placeholder||e.placeHolder:e.label&&(a.placeholder=`Select ${e.label}...`))}else if(e.type==="boolean"||e.type==="switch"||e.type==="toggle"){a.type="select";const o=t!=null&&t!==""?t:e.defaultValue,l=o===!0?"true":o===!1?"false":o==null?"":String(o);a.value=l;const d=e.trueLabel||"True",h=e.falseLabel||"False";a.options=[{value:"true",text:d},{value:"false",text:h}],!a.placeholder&&!a.placeHolder&&(a.placeholder=e.label?`Filter by ${e.label}…`:"Select…")}return a}extractFilterValue(e,t){if(e.type==="daterange"){const s=e.startName||"dr_start",i=e.endName||"dr_end";return{start:t[s],end:t[i]}}return e.type==="multiselect",t.filter_value}setTitle(e){this.title=e||null;const t=this.element?.querySelector(".rs-table-title");t&&(t.textContent=this.title||"")}setEyebrow(e){this.eyebrow=e||null;const t=this.element?.querySelector(".rs-table-eyebrow");t&&(t.textContent=this.eyebrow||"")}checkPermissions(e){return!0}escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}async destroy(){this.collection&&(this.collection.off("add",this._onModelsAdded,this),this.collection.off("remove",this._onModelsRemoved,this),this.collection.off("reset",this._onCollectionReset,this),this.collection.off("fetch:start",this._onFetchStart,this),this.collection.off("fetch:end",this._onFetchEnd,this)),this._clearItems(),await super.destroy()}}class Ge extends Ae{constructor(e={}){super({tagName:"tr",className:"table-row",enableTooltips:!0,...e}),this.columns=e.columns||[],this.actions=e.actions||null,this.contextMenu=e.contextMenu||null,this.batchActions=e.batchActions||null,this.tableView=e.tableView||e.listView||null,this.editingCells=new Set,this.template=this.buildRowTemplate()}getResponsiveClasses(e){if(!e)return"";const t=["sm","md","lg","xl","xxl"];if(typeof e=="string")return t.includes(e)?`d-none d-${e}-table-cell`:(console.warn(`Invalid visibility breakpoint: ${e}. Valid options are: ${t.join(", ")}`),"");if(typeof e=="object"){const s=[];if(e.hide){if(!t.includes(e.hide))return console.warn(`Invalid hide breakpoint: ${e.hide}. Valid options are: ${t.join(", ")}`),"";s.push(`d-table-cell d-${e.hide}-none`)}if(e.show){if(!t.includes(e.show))return console.warn(`Invalid show breakpoint: ${e.show}. Valid options are: ${t.join(", ")}`),"";e.hide?s.push(`d-${e.show}-table-cell`):s.push(`d-none d-${e.show}-table-cell`)}return s.join(" ")}return""}buildRowTemplate(){let e="";return this.tableView&&this.tableView.isSelectable()&&(e+=`
1600
+ `),e.innerHTML=l.join("")}async onActionPage(e,t){e.preventDefault();const s=parseInt(t.getAttribute("data-page"),10),i=this.collection.params?.size||10,r=this.collection.meta?.count||this.collection.length(),n=Math.max(1,Math.ceil(r/i));let a=isNaN(s)?1:s;a<1&&(a=n),a>n&&(a=1),this.collection.setParams({...this.collection.params,start:(a-1)*i}),this.collection.restEnabled?await this.collection.fetch():this.render(),this.emit("list:page",{page:a,event:e}),this.emit("params-changed")}async onChangePageSize(e,t){const s=parseInt(t.value,10);this.collection&&(this.collection.setParams({...this.collection.params,start:0,size:s}),this.collection.restEnabled&&await this.collection.fetch(),this.render()),this.emit("list:pagesize",{size:s}),this.emit("params-changed")}_computeHasMore(){if(this.paginationMode!=="more"||!this.collection)return!1;const e=this.collection.meta?.count;return typeof e!="number"?!1:this.collection.length()<e}async onActionShowMore(e,t){if(!this.loadingMore){if(!this.collection||typeof this.collection.fetchMore!="function"){console.warn("ListView: collection does not support fetchMore()");return}this.loadingMore=!0,this.isMounted()&&await this.render();try{const s=await this.collection.fetchMore();this.emit("list:show-more",{response:s})}catch(s){console.error("ListView: fetchMore failed",s)}finally{this.loadingMore=!1,this.isMounted()&&await this.render()}}}async onActionSortOption(e,t){e.preventDefault();const s=t.getAttribute("data-sort");this.collection&&(this.collection.setParams({...this.collection.params,sort:s||void 0,start:0}),this.collection.restEnabled?await this.collection.fetch():this.render()),this.emit("list:sort",{sort:s}),this.emit("params-changed")}async onActionCustomToolbarButton(e,t){const s=parseInt(t.getAttribute("data-button-index"),10),i=this.toolbarButtons[s];i&&typeof i.handler=="function"&&await i.handler.call(this,e,t)}async onActionAddFilter(e,t){const s=t.getAttribute("data-filter-key"),i=this.getFilterConfig(s),r=this.getActiveFilters()[s];if(!i){console.warn("No filter config found for key:",s);return}const n=await v.form({title:`${r!==void 0&&r!==""?"Edit":"Add"} ${this.getFilterLabel(s)} Filter`,size:"md",fields:[this.buildFilterDialogField(i,r,s)]});if(n){const a=this.extractFilterValue(i,n);this.setFilter(s,a),await this.applyFilters()}}async onActionEditFilter(e,t){const s=t.getAttribute("data-filter"),{field:i}=ge(s),r=this.getFilterConfig(i)||this.getFilterConfig(s),n=this.getActiveFilters(),a=n[s]||n[i];if(!r){console.warn("No filter config found for key:",s,"or field:",i);return}const o={filter_value:a};if(r.type==="daterange"&&a&&typeof a=="object"){const d=r.startName||"dr_start",h=r.endName||"dr_end";o[d]=a.start||"",o[h]=a.end||""}const l=await v.form({title:`Edit ${this.getFilterLabel(i)} Filter`,size:"md",data:o,fields:[this.buildFilterDialogField(r,a,i)]});if(l){const d=this.extractFilterValue(r,l);this.setFilter(s,d),await this.applyFilters()}}async onActionRemoveFilter(e,t){const s=t.getAttribute("data-filter"),{field:i}=ge(s);this.setFilter(s,null),s==="search"&&this.updateSearchInputs(""),this.collection?.restEnabled&&await this.collection.fetch(),this.render(),this.updateFilterPills(),this.emit("filter:remove",{key:s,field:i}),this.emit("params-changed")}async onActionClearAllFilters(e,t){if(!this.collection)return;const{start:s,size:i,sort:r}=this.collection.params,n={start:s,size:i};r&&(n.sort=r),Array.isArray(this.hideActivePillNames)&&this.hideActivePillNames.length>0&&this.hideActivePillNames.forEach(a=>{this.collection.params[a]!==void 0&&(n[a]=this.collection.params[a]);const o=this.getFilterConfig(a);if(o&&o.type==="daterange"){const l=o.startName||"dr_start",d=o.endName||"dr_end",h=o.fieldName||"dr_field";this.collection.params[l]!==void 0&&(n[l]=this.collection.params[l]),this.collection.params[d]!==void 0&&(n[d]=this.collection.params[d]),this.collection.params[h]!==void 0&&(n[h]=this.collection.params[h])}}),this.collection.params=n,this.updateSearchInputs(""),this.collection.restEnabled&&await this.collection.fetch(),this.render(),this.updateFilterPills(),this.emit("filters:clear"),this.emit("params-changed")}async applyFilters(){if(this.collection&&(this.collection.params.start=0),this.collection?.restEnabled)try{await this.collection.fetch(),await this.render()}catch(e){console.error("Failed to fetch filtered data:",e),await this.render()}else await this.render();this.updateFilterPills(),this.emit("params-changed")}getActiveFilters(){if(!this.collection?.params)return{};const{start:e,size:t,sort:s,...i}=this.collection.params,r={},n=new Set;return this.getAllAvailableFilters().forEach(o=>{if(o.config?.type==="daterange"){const l=o.key,d=o.config.startName||"dr_start",h=o.config.endName||"dr_end",u=o.config.fieldName||"dr_field";i[u]===l&&(i[d]||i[h])&&(r[l]={start:i[d]||"",end:i[h]||""},n.add(d),n.add(h),n.add(u))}}),Object.keys(i).forEach(o=>{n.has(o)||(r[o]=i[o])}),Object.keys(r).forEach(o=>{const l=`${o}__in`;Object.prototype.hasOwnProperty.call(r,l)&&delete r[o]}),r}setFilter(e,t){if(!this.collection)return;const s=this.getFilterConfig(e);if(s&&s.type==="daterange"){const i=s.startName||"dr_start",r=s.endName||"dr_end",n=s.fieldName||"dr_field";delete this.collection.params[i],delete this.collection.params[r],delete this.collection.params[n],t&&typeof t=="object"&&(t.start||t.end)&&(t.start&&(this.collection.params[i]=t.start),t.end&&(this.collection.params[r]=t.end),this.collection.params[n]=e)}else{const{field:i}=ge(e);if(delete this.collection.params[e],delete this.collection.params[i],delete this.collection.params[`${i}__in`],!t||Array.isArray(t)&&t.length===0)return;Array.isArray(t)?t.length===1?this.collection.params[i]=t[0]:this.collection.params[`${i}__in`]=t.join(","):this.collection.params[e]=t}}getAllAvailableFilters(){const e=[];return Object.entries(this.filters||{}).forEach(([t,s])=>{e.push({key:t,label:s.label||t,type:s.type,config:s})}),this.additionalFilters&&Array.isArray(this.additionalFilters)&&this.additionalFilters.forEach(t=>{e.push({key:t.name||t.key,label:t.label,type:t.type,config:t})}),e}getFilterConfig(e){if(this.filters&&this.filters[e])return this.filters[e];if(this.additionalFilters&&Array.isArray(this.additionalFilters)){const t=this.additionalFilters.find(s=>(s.name||s.key)===e);if(t)return t}return null}getFilterLabel(e){if(e==="search")return"Search";const t=this.filters?.[e];if(t&&t.label)return t.label;const s=this.additionalFilters?.find(i=>(i.name||i.key)===e);return s&&s.label?s.label:e.charAt(0).toUpperCase()+e.slice(1)}getFilterIcon(e){return{text:"search",select:"funnel",date:"calendar",daterange:"calendar-range",number:"123",boolean:"toggle-on"}[e]||"filter"}buildFilterDialogField(e,t,s){const{name:i,value:r,...n}=e,a={...n,name:"filter_value",label:n.label,value:t,placeholder:n.placeholder||n.placeHolder};if(e.type==="daterange"){if(a.startName=a.startName||"dr_start",a.endName=a.endName||"dr_end",a.fieldName=a.fieldName||"dr_field",a.format=a.format||"YYYY-MM-DD",a.displayFormat=a.displayFormat||"MMM DD, YYYY",a.separator=a.separator||" to ",a.label=a.label||"Date Range",t&&typeof t=="object"){const o=l=>{if(!l&&l!==0)return"";if(l instanceof Date&&!isNaN(l))return l.toISOString().slice(0,10);const d=String(l).trim();if(!d)return"";if(/^-?\d+$/.test(d)){const u=Number(d),m=d.length<=10?u*1e3:u,p=new Date(m);if(!isNaN(p))return p.toISOString().slice(0,10)}const h=new Date(d);return isNaN(h)?d:h.toISOString().slice(0,10)};a.startDate=o(t.start||t.from||t.begin||""),a.endDate=o(t.end||t.to||t.finish||"")}}else if(e.type==="multiselect"){let o=[];t&&(Array.isArray(t)?o=t:typeof t=="string"&&(o=t.split(",").map(l=>l.trim()).filter(l=>l))),a.value=o,!a.placeholder&&!a.placeHolder&&(e.placeholder||e.placeHolder?a.placeholder=e.placeholder||e.placeHolder:e.label&&(a.placeholder=`Select ${e.label}...`))}else if(e.type==="boolean"||e.type==="switch"||e.type==="toggle"){a.type="select";const o=t!=null&&t!==""?t:e.defaultValue,l=o===!0?"true":o===!1?"false":o==null?"":String(o);a.value=l;const d=e.trueLabel||"True",h=e.falseLabel||"False";a.options=[{value:"true",text:d},{value:"false",text:h}],!a.placeholder&&!a.placeHolder&&(a.placeholder=e.label?`Filter by ${e.label}…`:"Select…")}return a}extractFilterValue(e,t){if(e.type==="daterange"){const s=e.startName||"dr_start",i=e.endName||"dr_end";return{start:t[s],end:t[i]}}return e.type==="multiselect",t.filter_value}setTitle(e){this.title=e||null;const t=this.element?.querySelector(".rs-table-title");t&&(t.textContent=this.title||"")}setEyebrow(e){this.eyebrow=e||null;const t=this.element?.querySelector(".rs-table-eyebrow");t&&(t.textContent=this.eyebrow||"")}escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}async destroy(){this.collection&&(this.collection.off("add",this._onModelsAdded,this),this.collection.off("remove",this._onModelsRemoved,this),this.collection.off("reset",this._onCollectionReset,this),this.collection.off("fetch:start",this._onFetchStart,this),this.collection.off("fetch:end",this._onFetchEnd,this)),this._clearItems(),await super.destroy()}}class Ge extends Ae{constructor(e={}){super({tagName:"tr",className:"table-row",enableTooltips:!0,...e}),this.columns=e.columns||[],this.actions=e.actions||null,this.contextMenu=e.contextMenu||null,this.batchActions=e.batchActions||null,this.tableView=e.tableView||e.listView||null,this.editingCells=new Set,this.template=this.buildRowTemplate()}getResponsiveClasses(e){if(!e)return"";const t=["sm","md","lg","xl","xxl"];if(typeof e=="string")return t.includes(e)?`d-none d-${e}-table-cell`:(console.warn(`Invalid visibility breakpoint: ${e}. Valid options are: ${t.join(", ")}`),"");if(typeof e=="object"){const s=[];if(e.hide){if(!t.includes(e.hide))return console.warn(`Invalid hide breakpoint: ${e.hide}. Valid options are: ${t.join(", ")}`),"";s.push(`d-table-cell d-${e.hide}-none`)}if(e.show){if(!t.includes(e.show))return console.warn(`Invalid show breakpoint: ${e.show}. Valid options are: ${t.join(", ")}`),"";e.hide?s.push(`d-${e.show}-table-cell`):s.push(`d-none d-${e.show}-table-cell`)}return s.join(" ")}return""}buildRowTemplate(){let e="";return this.tableView&&this.tableView.isSelectable()&&(e+=`
1601
1601
  <td style="padding: 0;">
1602
1602
  <div class="mojo-select-cell {{#selected}}selected{{/selected}}"
1603
1603
  data-action="select">
@@ -1632,7 +1632,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1632
1632
  ${t.icon?`<i class="${t.icon}"></i>`:""}
1633
1633
  ${t.label&&!t.icon?t.label:""}
1634
1634
  </button>
1635
- `;return""}).join("")}</div></td>`}buildContextMenuTemplate(){return!this.contextMenu||this.contextMenu.length===0?"":`
1635
+ `;return""}).join("")}</div></td>`}buildContextMenuTemplate(){if(!this.contextMenu||this.contextMenu.length===0)return"";const e=this.buildContextMenuItems();return e?`
1636
1636
  <td class="text-end" style="width: 1px;">
1637
1637
  <div class="dropdown">
1638
1638
  <button class="btn btn-sm btn-link border-0"
@@ -1643,21 +1643,21 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1643
1643
  <i class="bi bi-three-dots-vertical"></i>
1644
1644
  </button>
1645
1645
  <ul class="dropdown-menu dropdown-menu-end shadow-sm">
1646
- ${this.buildContextMenuItems()}
1646
+ ${e}
1647
1647
  </ul>
1648
1648
  </div>
1649
1649
  </td>
1650
- `}buildContextMenuItems(){return this.contextMenu.map(e=>{if(e.separator||e.divider)return'<li><hr class="dropdown-divider"></li>';let t="dropdown-item";return(e.action==="delete"||e.danger)&&(t+=" text-danger"),e.disabled&&(t+=" disabled"),`
1650
+ `:""}isMenuItemVisible(e){if(e.permissions&&!this.checkPermissions(e.permissions))return!1;if(typeof e.visible=="function")try{if(!e.visible(this.model))return!1}catch(t){return console.warn(`TableRow contextMenu visible() threw for "${e.label||e.action}"; hiding item:`,t),!1}return!0}buildContextMenuItems(){const e=this.contextMenu.map((t,s)=>({menuItem:t,index:s})).filter(({menuItem:t})=>this.isMenuItemVisible(t));return e.some(({menuItem:t})=>!(t.separator||t.divider))?e.map(({menuItem:t,index:s})=>{if(t.separator||t.divider)return'<li><hr class="dropdown-divider"></li>';let i="dropdown-item";(t.action==="delete"||t.danger)&&(i+=" text-danger"),t.disabled&&(i+=" disabled");const r=typeof t.action=="function"?`data-action="row-context-menu-item" data-menu-index="${s}"`:`data-action="${this.escapeHtml(t.action)}"`;return`
1651
1651
  <li>
1652
- <a class="${t}" href="#"
1652
+ <a class="${i}" href="#"
1653
1653
  data-id="{{model.id}}"
1654
- data-action="${e.action}"
1655
- ${e.disabled?'aria-disabled="true" tabindex="-1"':""}>
1656
- ${e.icon?`<i class="${e.icon} me-2"></i>`:""}
1657
- ${e.label}
1654
+ ${r}
1655
+ ${t.disabled?'aria-disabled="true" tabindex="-1"':""}>
1656
+ ${t.icon?`<i class="${this.escapeHtml(t.icon)} me-2"></i>`:""}
1657
+ ${this.escapeHtml(t.label)}
1658
1658
  </a>
1659
1659
  </li>
1660
- `}).join("")}async onAfterRender(){await super.onAfterRender(),this.columns.forEach((t,s)=>{if(t.formatter&&typeof t.formatter=="function"){let i=this.element.querySelector(`[data-formatter-id="${s}"]`);if(i||(i=this.element.querySelector(`[data-formatter="${t.key}"]`)),i){const r=this.model.get?this.model.get(t.key):this.model[t.key],n={value:r,row:this.model,model:this.model,column:t,table:this.tableView,index:this.index};try{i.innerHTML=t.formatter(r,n)}catch(a){console.error(`Error formatting cell for column ${t.key}:`,a)}}}}),this.selected&&this.element.classList.add("selected");const e=this.model.get?this.model.get("id"):this.model.id;e&&this.element.setAttribute("data-id",e)}async onActionEditCell(e,t){e.stopPropagation();const s=t.getAttribute("data-column"),i=this.columns.find(r=>r.key===s);!i||!i.editable||this.editingCells.has(s)||await this.enterEditMode(s,i,t)}async onActionRowClick(e,t){e.target.closest(".btn-group")||e.target.closest(".dropdown")||e.target.closest(".cell-editor")||(this.emit("row:click",{row:this,model:this.model,column:t.getAttribute("data-column"),event:e}),this.tableView&&this.tableView.emit("row:click",{row:this,model:this.model,column:t.getAttribute("data-column"),event:e}))}async onActionView(e,t){e.stopPropagation(),this.emit("row:view",{row:this,model:this.model,event:e}),this.tableView&&this.tableView.emit("row:view",{row:this,model:this.model,event:e})}async onActionEdit(e,t){return e.stopPropagation(),this.emit("row:edit",{row:this,model:this.model,event:e}),this.tableView&&this.tableView.emit("row:edit",{row:this,model:this.model,event:e}),!0}async onActionDelete(e,t){e.stopPropagation(),this.emit("row:delete",{row:this,model:this.model,event:e}),this.tableView&&this.tableView.emit("row:delete",{row:this,model:this.model,event:e})}async enterEditMode(e,t,s){const i=s.querySelector(".cell-content");if(!i)return;this.editingCells.add(e);const r=this.model.get?this.model.get(e):this.model[e],n=this.createCellEditor(t,r),a=i.innerHTML;i.style.display="none";const o=document.createElement("div");o.className="cell-editor",o.innerHTML=n,s.appendChild(o);const l=o.querySelector("input, select, .form-check-input");l&&(l.focus(),(l.type==="text"||l.type==="textarea")&&l.select()),o.dataset.originalContent=a,o.dataset.columnKey=e,this.setupEditorEvents(o,e,t),this.emit("cell:edit",{row:this,model:this.model,column:e,originalValue:r})}createCellEditor(e,t){const s=e.editableOptions||{};switch(s.type){case"select":return this.createSelectEditor(s,t);case"switch":case"checkbox":return this.createSwitchEditor(s,t);case"textarea":return this.createTextareaEditor(s,t);default:return this.createTextEditor(s,t)}}createTextEditor(e,t){const s=e.placeholder||"";return`
1660
+ `}).join(""):""}async onActionRowContextMenuItem(e,t){e.stopPropagation();const s=parseInt(t.getAttribute("data-menu-index"),10),i=this.contextMenu&&this.contextMenu[s];!i||typeof i.action!="function"||await i.action(this.model,this.getApp())}async onAfterRender(){await super.onAfterRender(),this.columns.forEach((t,s)=>{if(t.formatter&&typeof t.formatter=="function"){let i=this.element.querySelector(`[data-formatter-id="${s}"]`);if(i||(i=this.element.querySelector(`[data-formatter="${t.key}"]`)),i){const r=this.model.get?this.model.get(t.key):this.model[t.key],n={value:r,row:this.model,model:this.model,column:t,table:this.tableView,index:this.index};try{i.innerHTML=t.formatter(r,n)}catch(a){console.error(`Error formatting cell for column ${t.key}:`,a)}}}}),this.selected&&this.element.classList.add("selected");const e=this.model.get?this.model.get("id"):this.model.id;e&&this.element.setAttribute("data-id",e)}async onActionEditCell(e,t){e.stopPropagation();const s=t.getAttribute("data-column"),i=this.columns.find(r=>r.key===s);!i||!i.editable||this.editingCells.has(s)||await this.enterEditMode(s,i,t)}async onActionRowClick(e,t){e.target.closest(".btn-group")||e.target.closest(".dropdown")||e.target.closest(".cell-editor")||(this.emit("row:click",{row:this,model:this.model,column:t.getAttribute("data-column"),event:e}),this.tableView&&this.tableView.emit("row:click",{row:this,model:this.model,column:t.getAttribute("data-column"),event:e}))}async onActionView(e,t){e.stopPropagation(),this.emit("row:view",{row:this,model:this.model,event:e}),this.tableView&&this.tableView.emit("row:view",{row:this,model:this.model,event:e})}async onActionEdit(e,t){return e.stopPropagation(),this.emit("row:edit",{row:this,model:this.model,event:e}),this.tableView&&this.tableView.emit("row:edit",{row:this,model:this.model,event:e}),!0}async onActionDelete(e,t){e.stopPropagation(),this.emit("row:delete",{row:this,model:this.model,event:e}),this.tableView&&this.tableView.emit("row:delete",{row:this,model:this.model,event:e})}async enterEditMode(e,t,s){const i=s.querySelector(".cell-content");if(!i)return;this.editingCells.add(e);const r=this.model.get?this.model.get(e):this.model[e],n=this.createCellEditor(t,r),a=i.innerHTML;i.style.display="none";const o=document.createElement("div");o.className="cell-editor",o.innerHTML=n,s.appendChild(o);const l=o.querySelector("input, select, .form-check-input");l&&(l.focus(),(l.type==="text"||l.type==="textarea")&&l.select()),o.dataset.originalContent=a,o.dataset.columnKey=e,this.setupEditorEvents(o,e,t),this.emit("cell:edit",{row:this,model:this.model,column:e,originalValue:r})}createCellEditor(e,t){const s=e.editableOptions||{};switch(s.type){case"select":return this.createSelectEditor(s,t);case"switch":case"checkbox":return this.createSwitchEditor(s,t);case"textarea":return this.createTextareaEditor(s,t);default:return this.createTextEditor(s,t)}}createTextEditor(e,t){const s=e.placeholder||"";return`
1661
1661
  <div class="d-flex gap-1 align-items-center">
1662
1662
  <input type="${e.inputType||"text"}"
1663
1663
  class="form-control form-control-sm cell-input"
@@ -1710,7 +1710,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1710
1710
  </button>
1711
1711
  </div>
1712
1712
  </div>
1713
- `}setupEditorEvents(e,t,s){const i=e.querySelector(".cell-input"),r=e.querySelector(".cell-save"),n=e.querySelector(".cell-cancel");i&&(i.type==="text"||i.type==="email"||i.type==="number")&&i.addEventListener("keydown",a=>{a.key==="Enter"?(a.preventDefault(),this.saveCellEdit(e,t,s)):a.key==="Escape"&&(a.preventDefault(),this.cancelCellEdit(e,t))}),i&&(i.type==="checkbox"||i.tagName==="SELECT")&&s.autoSave!==!1&&i.addEventListener("change",()=>{this.saveCellEdit(e,t,s)}),r?.addEventListener("click",()=>{this.saveCellEdit(e,t,s)}),n?.addEventListener("click",()=>{this.cancelCellEdit(e,t)})}async saveCellEdit(e,t,s){const i=e.querySelector(".cell-input");if(!i)return;let r;i.type==="checkbox"?r=i.checked:(i.tagName,r=i.value);const n=this.model.get?this.model.get(t):this.model[t];try{this.model.save?await this.model.save({[t]:r}):this.model[t]=r,this.exitEditMode(e,t,r),this.emit("cell:save",{row:this,model:this.model,column:t,oldValue:n,newValue:r})}catch(a){console.error("Failed to save cell edit:",a),this.emit("cell:save:error",{row:this,model:this.model,column:t,oldValue:n,newValue:r,error:a}),e.classList.add("saving-error"),setTimeout(()=>e.classList.remove("saving-error"),3e3)}}cancelCellEdit(e,t){const s=e.dataset.originalContent;this.exitEditMode(e,t,null,s),this.emit("cell:cancel",{row:this,model:this.model,column:t})}exitEditMode(e,t,s=null,i=null){const n=e.closest("td").querySelector(".cell-content");if(n){if(s!==null){const a=this.columns.find(l=>l.key===t);let o=s;a&&a.formatter&&typeof a.formatter=="string"&&(o=V.pipe(s,a.formatter)),n.innerHTML=this.escapeHtml(o)}else i&&(n.innerHTML=i);n.style.display=""}e.remove(),this.editingCells.delete(t)}escapeHtml(e){if(e==null)return"";const t=document.createElement("div");return t.textContent=e,t.innerHTML}select(){super.select(),this.addClass("selected");const e=this.element?.querySelector(".mojo-select-cell");e&&e.classList.add("selected")}deselect(){super.deselect(),this.removeClass("selected");const e=this.element?.querySelector(".mojo-select-cell");e&&e.classList.remove("selected")}}class Lt extends se{constructor(e={}){const t={className:"table-view-component",itemClass:e.itemClass||Ge,selectionMode:e.selectable?"multiple":"none",emptyMessage:e.emptyMessage||"No data available",addButtonIcon:e.addButtonIcon||"bi bi-plus-circle",...e};super(t),this.isFullscreen=!1,this.columns=e.columns||[],this.actions=e.actions||null,this.contextMenu=e.contextMenu||null,this.batchActions=e.batchActions||null,this.searchable=e.searchable!==!1,this.sortable=e.sortable!==!1,this.filterable=e.filterable!==!1,this.paginated=e.paginated!==!1,this.paginationMode=e.paginationMode||"pages",this.persistSelection=e.persistSelection===!0,this.clickAction=e.clickAction||"view",this.fetchOnView=e.fetchOnView!==!1,this.itemView=e.itemView,this.addForm=e.addForm,this.editForm=e.editForm,this.deleteTemplate=e.deleteTemplate,this.formDialogConfig=e.formDialogConfig||{},this.viewDialogOptions=e.viewDialogOptions||{},this.exportOptions=e.exportOptions||null,this.options.showExport&&!this.exportOptions&&(this.exportOptions=[{format:"csv",label:"Export as CSV",icon:"bi bi-file-earmark-spreadsheet"},{format:"json",label:"Export as JSON",icon:"bi bi-file-earmark-code"}]),this.exportSource=e.exportSource||"remote",this.filters={},this.additionalFilters=e.filters||[],this.hideActivePills=e.hideActivePills===!0,this.hideActivePillNames=e.hideActivePillNames||[],this.rowAction=e.rowAction||"row-click",this.batchBarLocation=e.batchBarLocation||"bottom",this.options.addButtonLabel=e.addButtonLabel||"Add",this.toolbarButtons=e.toolbarButtons||[],this.toolbarRight=e.toolbarRight||null,this.title=e.title||null,this.eyebrow=e.eyebrow||null,this.showRefresh=e.showRefresh!==!1,this.showFullscreen=e.showFullscreen!==!1,this.tableOptions={striped:!0,bordered:!1,hover:!0,responsive:!1,size:null,...e.tableOptions},this.searchPlacement=e.searchPlacement||"toolbar",this.searchPlaceholder=e.searchPlaceholder||"Search...",this.initializeColumns(),this.extractColumnFilters(),this.footerTotalColumns=this.columns.filter(s=>s.footer_total===!0),this.hasFooterTotals=this.footerTotalColumns.length>0,this.template=this.buildTableTemplate(),this.setupCollectionListeners()}setupCollectionListeners(){this.hasFooterTotals&&this.collection&&this.collection.on("reset add remove change",()=>{this.updateFooterTotals()})}initializeColumns(){this.columns.forEach(e=>{!e.key&&e.name&&(e.key=e.name),!e.label&&!e.title&&(e.label=e.key.charAt(0).toUpperCase()+e.key.slice(1))})}getResponsiveClasses(e){if(!e)return"";const t=["sm","md","lg","xl","xxl"];if(typeof e=="string")return t.includes(e)?`d-none d-${e}-table-cell`:(console.warn(`Invalid visibility breakpoint: ${e}. Valid options are: ${t.join(", ")}`),"");if(typeof e=="object"){const s=[];if(e.hide){if(!t.includes(e.hide))return console.warn(`Invalid hide breakpoint: ${e.hide}. Valid options are: ${t.join(", ")}`),"";s.push(`d-table-cell d-${e.hide}-none`)}if(e.show){if(!t.includes(e.show))return console.warn(`Invalid show breakpoint: ${e.show}. Valid options are: ${t.join(", ")}`),"";e.hide?s.push(`d-${e.show}-table-cell`):s.push(`d-none d-${e.show}-table-cell`)}return s.join(" ")}return""}getAlignClass(e){if(!e)return"";const s={left:"text-start",start:"text-start",center:"text-center",right:"text-end",end:"text-end"}[String(e).toLowerCase()];return s||(console.warn(`Invalid column align: ${e}. Valid options are: left, center, right`),"")}parseColumnKey(e){const t=e.split("|");return{fieldKey:t[0],formatter:t[1]||null}}updateFooterTotals(){if(!this.hasFooterTotals||!this.element)return;const e=this.calculateFooterTotals();let t=0;this.columns.forEach(s=>{if(s.footer_total){const i=`col_${t}`,r=this.element.querySelector(`[data-total-column="${i}"]`);if(r&&e[i]){const n=this.parseColumnKey(s.key).formatter||s.formatter;let a;n&&typeof n=="string"?a=this.formatValue(e[i].value,n):a=e[i].value,r.textContent=a}t++}})}formatValue(e,t){try{return V.pipe(e,t)}catch(s){return console.warn("Error formatting value:",s),e}}calculateFooterTotals(){if(!this.hasFooterTotals||!this.collection||this.collection.length===0)return{};const e={};return this.footerTotalColumns.forEach((t,s)=>{const{fieldKey:i,formatter:r}=this.parseColumnKey(t.key);let n=0;this.collection.forEach(o=>{const l=o.get?o.get(i):o[i],d=parseFloat(l)||0;n+=d});const a=`col_${s}`;e[a]={value:n,formatter:r||t.formatter,fieldKey:i,originalKey:t.key}}),e}extractColumnFilters(){this.filters={},this.columns.forEach(e=>{if(e.filter){const{fieldKey:t}=this.parseColumnKey(e.key);this.filters[t]={...e.filter,label:e.filter.label||e.label||t}}})}isSelectable(){return this.batchActions&&this.batchActions.length>0&&this.selectionMode==="multiple"}buildTableTemplate(){const e=this.batchBarLocation==="top"?this.buildBatchActionsPanel():"",t=this.batchBarLocation==="bottom"?this.buildBatchActionsPanel():"",s=(()=>{const i=this.tableOptions&&this.tableOptions.fontSize!=null?this.tableOptions.fontSize:this.options&&this.options.fontSize,r=i==="sm"?"0.9rem":i==="xs"?"0.8rem":i?String(i):null;return r?` style="font-size: ${r};"`:""})();return`
1713
+ `}setupEditorEvents(e,t,s){const i=e.querySelector(".cell-input"),r=e.querySelector(".cell-save"),n=e.querySelector(".cell-cancel");i&&(i.type==="text"||i.type==="email"||i.type==="number")&&i.addEventListener("keydown",a=>{a.key==="Enter"?(a.preventDefault(),this.saveCellEdit(e,t,s)):a.key==="Escape"&&(a.preventDefault(),this.cancelCellEdit(e,t))}),i&&(i.type==="checkbox"||i.tagName==="SELECT")&&s.autoSave!==!1&&i.addEventListener("change",()=>{this.saveCellEdit(e,t,s)}),r?.addEventListener("click",()=>{this.saveCellEdit(e,t,s)}),n?.addEventListener("click",()=>{this.cancelCellEdit(e,t)})}async saveCellEdit(e,t,s){const i=e.querySelector(".cell-input");if(!i)return;let r;i.type==="checkbox"?r=i.checked:(i.tagName,r=i.value);const n=this.model.get?this.model.get(t):this.model[t];try{this.model.save?await this.model.save({[t]:r}):this.model[t]=r,this.exitEditMode(e,t,r),this.emit("cell:save",{row:this,model:this.model,column:t,oldValue:n,newValue:r})}catch(a){console.error("Failed to save cell edit:",a),this.emit("cell:save:error",{row:this,model:this.model,column:t,oldValue:n,newValue:r,error:a}),e.classList.add("saving-error"),setTimeout(()=>e.classList.remove("saving-error"),3e3)}}cancelCellEdit(e,t){const s=e.dataset.originalContent;this.exitEditMode(e,t,null,s),this.emit("cell:cancel",{row:this,model:this.model,column:t})}exitEditMode(e,t,s=null,i=null){const n=e.closest("td").querySelector(".cell-content");if(n){if(s!==null){const a=this.columns.find(l=>l.key===t);let o=s;a&&a.formatter&&typeof a.formatter=="string"&&(o=V.pipe(s,a.formatter)),n.innerHTML=this.escapeHtml(o)}else i&&(n.innerHTML=i);n.style.display=""}e.remove(),this.editingCells.delete(t)}escapeHtml(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}select(){super.select(),this.addClass("selected");const e=this.element?.querySelector(".mojo-select-cell");e&&e.classList.add("selected")}deselect(){super.deselect(),this.removeClass("selected");const e=this.element?.querySelector(".mojo-select-cell");e&&e.classList.remove("selected")}}class Lt extends se{constructor(e={}){const t={className:"table-view-component",itemClass:e.itemClass||Ge,selectionMode:e.selectable?"multiple":"none",emptyMessage:e.emptyMessage||"No data available",addButtonIcon:e.addButtonIcon||"bi bi-plus-circle",...e};super(t),this.isFullscreen=!1,this.columns=e.columns||[],this.actions=e.actions||null,this.contextMenu=e.contextMenu||e.rowContextMenu||null,this.batchActions=e.batchActions||null,this.searchable=e.searchable!==!1,this.sortable=e.sortable!==!1,this.filterable=e.filterable!==!1,this.paginated=e.paginated!==!1,this.paginationMode=e.paginationMode||"pages",this.persistSelection=e.persistSelection===!0,this.clickAction=e.clickAction||"view",this.fetchOnView=e.fetchOnView!==!1,this.itemView=e.itemView,this.addForm=e.addForm,this.editForm=e.editForm,this.deleteTemplate=e.deleteTemplate,this.formDialogConfig=e.formDialogConfig||{},this.viewDialogOptions=e.viewDialogOptions||{},this.exportOptions=e.exportOptions||null,this.options.showExport&&!this.exportOptions&&(this.exportOptions=[{format:"csv",label:"Export as CSV",icon:"bi bi-file-earmark-spreadsheet"},{format:"json",label:"Export as JSON",icon:"bi bi-file-earmark-code"}]),this.exportSource=e.exportSource||"remote",this.filters={},this.additionalFilters=e.filters||[],this.hideActivePills=e.hideActivePills===!0,this.hideActivePillNames=e.hideActivePillNames||[],this.rowAction=e.rowAction||"row-click",this.batchBarLocation=e.batchBarLocation||"bottom",this.options.addButtonLabel=e.addButtonLabel||"Add",this.toolbarButtons=e.toolbarButtons||[],this.toolbarRight=e.toolbarRight||null,this.title=e.title||null,this.eyebrow=e.eyebrow||null,this.showRefresh=e.showRefresh!==!1,this.showFullscreen=e.showFullscreen!==!1,this.tableOptions={striped:!0,bordered:!1,hover:!0,responsive:!1,size:null,...e.tableOptions},this.searchPlacement=e.searchPlacement||"toolbar",this.searchPlaceholder=e.searchPlaceholder||"Search...",this.initializeColumns(),this.extractColumnFilters(),this.footerTotalColumns=this.columns.filter(s=>s.footer_total===!0),this.hasFooterTotals=this.footerTotalColumns.length>0,this.template=this.buildTableTemplate(),this.setupCollectionListeners()}setupCollectionListeners(){this.hasFooterTotals&&this.collection&&this.collection.on("reset add remove change",()=>{this.updateFooterTotals()})}initializeColumns(){this.columns.forEach(e=>{!e.key&&e.name&&(e.key=e.name),!e.label&&!e.title&&(e.label=e.key.charAt(0).toUpperCase()+e.key.slice(1))})}getResponsiveClasses(e){if(!e)return"";const t=["sm","md","lg","xl","xxl"];if(typeof e=="string")return t.includes(e)?`d-none d-${e}-table-cell`:(console.warn(`Invalid visibility breakpoint: ${e}. Valid options are: ${t.join(", ")}`),"");if(typeof e=="object"){const s=[];if(e.hide){if(!t.includes(e.hide))return console.warn(`Invalid hide breakpoint: ${e.hide}. Valid options are: ${t.join(", ")}`),"";s.push(`d-table-cell d-${e.hide}-none`)}if(e.show){if(!t.includes(e.show))return console.warn(`Invalid show breakpoint: ${e.show}. Valid options are: ${t.join(", ")}`),"";e.hide?s.push(`d-${e.show}-table-cell`):s.push(`d-none d-${e.show}-table-cell`)}return s.join(" ")}return""}getAlignClass(e){if(!e)return"";const s={left:"text-start",start:"text-start",center:"text-center",right:"text-end",end:"text-end"}[String(e).toLowerCase()];return s||(console.warn(`Invalid column align: ${e}. Valid options are: left, center, right`),"")}parseColumnKey(e){const t=e.split("|");return{fieldKey:t[0],formatter:t[1]||null}}updateFooterTotals(){if(!this.hasFooterTotals||!this.element)return;const e=this.calculateFooterTotals();let t=0;this.columns.forEach(s=>{if(s.footer_total){const i=`col_${t}`,r=this.element.querySelector(`[data-total-column="${i}"]`);if(r&&e[i]){const n=this.parseColumnKey(s.key).formatter||s.formatter;let a;n&&typeof n=="string"?a=this.formatValue(e[i].value,n):a=e[i].value,r.textContent=a}t++}})}formatValue(e,t){try{return V.pipe(e,t)}catch(s){return console.warn("Error formatting value:",s),e}}calculateFooterTotals(){if(!this.hasFooterTotals||!this.collection||this.collection.length===0)return{};const e={};return this.footerTotalColumns.forEach((t,s)=>{const{fieldKey:i,formatter:r}=this.parseColumnKey(t.key);let n=0;this.collection.forEach(o=>{const l=o.get?o.get(i):o[i],d=parseFloat(l)||0;n+=d});const a=`col_${s}`;e[a]={value:n,formatter:r||t.formatter,fieldKey:i,originalKey:t.key}}),e}extractColumnFilters(){this.filters={},this.columns.forEach(e=>{if(e.filter){const{fieldKey:t}=this.parseColumnKey(e.key);this.filters[t]={...e.filter,label:e.filter.label||e.label||t}}})}isSelectable(){return this.batchActions&&this.batchActions.length>0&&this.selectionMode==="multiple"}buildTableTemplate(){const e=this.batchBarLocation==="top"?this.buildBatchActionsPanel():"",t=this.batchBarLocation==="bottom"?this.buildBatchActionsPanel():"",s=(()=>{const i=this.tableOptions&&this.tableOptions.fontSize!=null?this.tableOptions.fontSize:this.options&&this.options.fontSize,r=i==="sm"?"0.9rem":i==="xs"?"0.8rem":i?String(i):null;return r?` style="font-size: ${r};"`:""})();return`
1714
1714
  <div class="mojo-table-wrapper">
1715
1715
  ${this.buildToolbarTemplate()}
1716
1716
  ${e}