web-mojo 2.4.4 → 2.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/dist/admin-models.cjs.js +1 -1
- package/dist/admin-models.cjs.js.map +1 -1
- package/dist/admin-models.es.js +1 -1
- package/dist/admin-models.es.js.map +1 -1
- package/dist/admin.cjs.js +1 -1
- package/dist/admin.css +258 -6
- package/dist/admin.es.js +1 -1
- package/dist/auth.cjs.js +1 -1
- package/dist/auth.es.js +1 -1
- package/dist/charts.cjs.js +1 -1
- package/dist/charts.es.js +1 -1
- package/dist/chat.css +5 -0
- package/dist/chunks/AssistantPanelView-C4ZyIQoH.js +2 -0
- package/dist/chunks/AssistantPanelView-C4ZyIQoH.js.map +1 -0
- package/dist/chunks/AssistantPanelView-DlBgWeM_.js +2 -0
- package/dist/chunks/AssistantPanelView-DlBgWeM_.js.map +1 -0
- package/dist/chunks/{ChatView-B0xHv7Nq.js → ChatView-CcR1GR30.js} +2 -2
- package/dist/chunks/{ChatView-CUmRTKna.js.map → ChatView-CcR1GR30.js.map} +1 -1
- package/dist/chunks/{ChatView-CUmRTKna.js → ChatView-ChyTcmrd.js} +2 -2
- package/dist/chunks/{ChatView-B0xHv7Nq.js.map → ChatView-ChyTcmrd.js.map} +1 -1
- package/dist/chunks/{Collection-7F3lsq4z.js → Collection-C0pHSKDH.js} +2 -2
- package/dist/chunks/{Collection-7F3lsq4z.js.map → Collection-C0pHSKDH.js.map} +1 -1
- package/dist/chunks/{Collection-Cgxbmj8G.js → Collection-DNmr743A.js} +2 -2
- package/dist/chunks/{Collection-Cgxbmj8G.js.map → Collection-DNmr743A.js.map} +1 -1
- package/dist/chunks/{ContextMenu-afYD0lFk.js → ContextMenu-BeveGkJr.js} +2 -2
- package/dist/chunks/{ContextMenu-afYD0lFk.js.map → ContextMenu-BeveGkJr.js.map} +1 -1
- package/dist/chunks/{ContextMenu-Ba4fjHxg.js → ContextMenu-T3yDdsIe.js} +2 -2
- package/dist/chunks/{ContextMenu-Ba4fjHxg.js.map → ContextMenu-T3yDdsIe.js.map} +1 -1
- package/dist/chunks/{DataView-DFGIE3wK.js → DataView-VZIXSsZa.js} +2 -2
- package/dist/chunks/{DataView-DFGIE3wK.js.map → DataView-VZIXSsZa.js.map} +1 -1
- package/dist/chunks/{DataView-fA6qQbvN.js → DataView-z2rxXk4L.js} +2 -2
- package/dist/chunks/{DataView-fA6qQbvN.js.map → DataView-z2rxXk4L.js.map} +1 -1
- package/dist/chunks/{FormView-CgnaTPkQ.js → FormView-COIPtbrd.js} +2 -2
- package/dist/chunks/{FormView-CgnaTPkQ.js.map → FormView-COIPtbrd.js.map} +1 -1
- package/dist/chunks/{FormView-LRb8scDI.js → FormView-DUXQruUZ.js} +2 -2
- package/dist/chunks/{FormView-LRb8scDI.js.map → FormView-DUXQruUZ.js.map} +1 -1
- package/dist/chunks/{ListView-Dsezts8J.js → ListView-BjsNHuZ1.js} +2 -2
- package/dist/chunks/{ListView-Dsezts8J.js.map → ListView-BjsNHuZ1.js.map} +1 -1
- package/dist/chunks/{ListView-Cu6iQ0aG.js → ListView-BxcxIwC3.js} +2 -2
- package/dist/chunks/{ListView-Cu6iQ0aG.js.map → ListView-BxcxIwC3.js.map} +1 -1
- package/dist/chunks/{MetricsCountryMapView-BsJoEsUE.js → MetricsCountryMapView-Bp3qoVHp.js} +2 -2
- package/dist/chunks/{MetricsCountryMapView-BsJoEsUE.js.map → MetricsCountryMapView-Bp3qoVHp.js.map} +1 -1
- package/dist/chunks/{MetricsCountryMapView-BkLDonK4.js → MetricsCountryMapView-CWjIEBJB.js} +2 -2
- package/dist/chunks/{MetricsCountryMapView-BkLDonK4.js.map → MetricsCountryMapView-CWjIEBJB.js.map} +1 -1
- package/dist/chunks/Modal-Bm1OQ8Ou.js +3 -0
- package/dist/chunks/{Modal-BRKy85bz.js.map → Modal-Bm1OQ8Ou.js.map} +1 -1
- package/dist/chunks/Modal-KnJhNZ1E.js +3 -0
- package/dist/chunks/{Modal-DKjxtaZI.js.map → Modal-KnJhNZ1E.js.map} +1 -1
- package/dist/chunks/Passkeys-DJn9yy-0.js +2 -0
- package/dist/chunks/Passkeys-DJn9yy-0.js.map +1 -0
- package/dist/chunks/Passkeys-WWAg5tKf.js +2 -0
- package/dist/chunks/Passkeys-WWAg5tKf.js.map +1 -0
- package/dist/chunks/TicketPanelView-DeeANyKv.js +2 -0
- package/dist/chunks/TicketPanelView-DeeANyKv.js.map +1 -0
- package/dist/chunks/TicketPanelView-if4ogL_D.js +2 -0
- package/dist/chunks/TicketPanelView-if4ogL_D.js.map +1 -0
- package/dist/chunks/{TokenManager-CWRL33UM.js → TokenManager-6atX9uKB.js} +2 -2
- package/dist/chunks/TokenManager-6atX9uKB.js.map +1 -0
- package/dist/chunks/{TokenManager-CVR3ENIS.js → TokenManager-CiNtJclo.js} +2 -2
- package/dist/chunks/TokenManager-CiNtJclo.js.map +1 -0
- package/dist/chunks/User-9qvKV7G6.js +2 -0
- package/dist/chunks/User-9qvKV7G6.js.map +1 -0
- package/dist/chunks/{User-BmS8zImI.js → User-BM76Ughk.js} +2 -2
- package/dist/chunks/User-BM76Ughk.js.map +1 -0
- package/dist/chunks/{UserProfileView-CrmACQjJ.js → UserProfileView-BPjz7uIp.js} +2 -2
- package/dist/chunks/{UserProfileView-CrmACQjJ.js.map → UserProfileView-BPjz7uIp.js.map} +1 -1
- package/dist/chunks/{UserProfileView-B56WeGL1.js → UserProfileView-udbSWe1S.js} +2 -2
- package/dist/chunks/{UserProfileView-B56WeGL1.js.map → UserProfileView-udbSWe1S.js.map} +1 -1
- package/dist/chunks/{View-gAghvPMN.js → View-BxlKR1IW.js} +2 -2
- package/dist/chunks/{View-gAghvPMN.js.map → View-BxlKR1IW.js.map} +1 -1
- package/dist/chunks/{View-IgBQlwd0.js → View-CPWwS19u.js} +2 -2
- package/dist/chunks/{View-IgBQlwd0.js.map → View-CPWwS19u.js.map} +1 -1
- package/dist/chunks/{WebApp-B6wrmIaj.js → WebApp-BdxhRnnT.js} +2 -2
- package/dist/chunks/WebApp-BdxhRnnT.js.map +1 -0
- package/dist/chunks/WebApp-Bo_egO0c.js +2 -0
- package/dist/chunks/WebApp-Bo_egO0c.js.map +1 -0
- package/dist/chunks/admin-C3-HqQvC.js +2 -0
- package/dist/chunks/admin-C3-HqQvC.js.map +1 -0
- package/dist/chunks/admin-DrFBTXnB.js +2 -0
- package/dist/chunks/admin-DrFBTXnB.js.map +1 -0
- package/dist/chunks/admin-models-CkHjtMHf.js +2 -0
- package/dist/chunks/admin-models-CkHjtMHf.js.map +1 -0
- package/dist/chunks/admin-models-DLtFboxy.js +2 -0
- package/dist/chunks/admin-models-DLtFboxy.js.map +1 -0
- package/dist/chunks/{exportChart-CmfLeCi8.js → exportChart-BTrEOM9j.js} +2 -2
- package/dist/chunks/{exportChart-CmfLeCi8.js.map → exportChart-BTrEOM9j.js.map} +1 -1
- package/dist/chunks/{exportChart-Ue-zU0_c.js → exportChart-BfzZUb1j.js} +2 -2
- package/dist/chunks/{exportChart-Ue-zU0_c.js.map → exportChart-BfzZUb1j.js.map} +1 -1
- package/dist/chunks/{index-NXnA6T-5.js → index-Byf1pa3Z.js} +2 -2
- package/dist/chunks/{index-NXnA6T-5.js.map → index-Byf1pa3Z.js.map} +1 -1
- package/dist/chunks/{index-DTXotoXw.js → index-dFX91Gwz.js} +2 -2
- package/dist/chunks/{index-DTXotoXw.js.map → index-dFX91Gwz.js.map} +1 -1
- package/dist/chunks/{version-CpR8sTVV.js → version-C9vC8_Oy.js} +2 -2
- package/dist/chunks/{version-CpR8sTVV.js.map → version-C9vC8_Oy.js.map} +1 -1
- package/dist/chunks/{version-CsLH6aiB.js → version-CjNfmLdK.js} +2 -2
- package/dist/chunks/{version-CsLH6aiB.js.map → version-CjNfmLdK.js.map} +1 -1
- package/dist/css/web-mojo.css +1 -1
- package/dist/docit.cjs.js +1 -1
- package/dist/docit.es.js +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +1 -1
- package/dist/index.es.js.map +1 -1
- package/dist/lightbox.cjs.js +1 -1
- package/dist/lightbox.es.js +1 -1
- package/dist/map.cjs.js +1 -1
- package/dist/map.es.js +1 -1
- package/dist/timeline.cjs.js +1 -1
- package/dist/timeline.es.js +1 -1
- package/dist/user-profile.cjs.js +1 -1
- package/dist/user-profile.es.js +1 -1
- package/dist/web-mojo.lite.iife.js +20 -4
- package/dist/web-mojo.lite.iife.js.map +1 -1
- package/dist/web-mojo.lite.iife.min.js +8 -8
- package/dist/web-mojo.lite.iife.min.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunks/AssistantPanelView-B3orPoag.js +0 -2
- package/dist/chunks/AssistantPanelView-B3orPoag.js.map +0 -1
- package/dist/chunks/AssistantPanelView-GeIHDvyN.js +0 -2
- package/dist/chunks/AssistantPanelView-GeIHDvyN.js.map +0 -1
- package/dist/chunks/Modal-BRKy85bz.js +0 -3
- package/dist/chunks/Modal-DKjxtaZI.js +0 -3
- package/dist/chunks/Passkeys-CMh9iSax.js +0 -2
- package/dist/chunks/Passkeys-CMh9iSax.js.map +0 -1
- package/dist/chunks/Passkeys-DF7mRGYj.js +0 -2
- package/dist/chunks/Passkeys-DF7mRGYj.js.map +0 -1
- package/dist/chunks/TokenManager-CVR3ENIS.js.map +0 -1
- package/dist/chunks/TokenManager-CWRL33UM.js.map +0 -1
- package/dist/chunks/User-BmS8zImI.js.map +0 -1
- package/dist/chunks/User-CayBjzMG.js +0 -2
- package/dist/chunks/User-CayBjzMG.js.map +0 -1
- package/dist/chunks/WebApp-B6wrmIaj.js.map +0 -1
- package/dist/chunks/WebApp-DeHPnmbD.js +0 -2
- package/dist/chunks/WebApp-DeHPnmbD.js.map +0 -1
- package/dist/chunks/admin-FvzwR-f7.js +0 -2
- package/dist/chunks/admin-FvzwR-f7.js.map +0 -1
- package/dist/chunks/admin-yjCkhxvU.js +0 -2
- package/dist/chunks/admin-yjCkhxvU.js.map +0 -1
|
@@ -11,7 +11,7 @@ var MOJO=(function(F){"use strict";class $e{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){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 X=new Intl.DateTimeFormat(n,{hour:"2-digit",minute:"2-digit",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(R=>R.type==="timeZoneName");if(k=X?X.value:"",k&&/^GMT[+-]/i.test(k))try{const ee=new Intl.DateTimeFormat(n,{timeStyle:"short",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(ws=>ws.type==="timeZoneName");ee&&ee.value&&!/^GMT[+-]/i.test(ee.value)&&(k=ee.value)}catch{}if(k&&/\s/.test(k)){const R=k.split(/\s+/).map(ee=>ee[0]).join("").toUpperCase();R.length>=2&&R.length<=4&&(k=R)}}catch{k=""}return k};if(!a){const k=this.date(r,t),Y=this.time(r,s),X=o();return k&&Y?`${k} ${Y} ${X}`.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(X=>X.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)):"",w=p?String(parseInt(p,10)):"",x=p?parseInt(p,10)%12||12:"",A=p?parseInt(p,10)>=12?"PM":"AM":"",E=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),O=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"long"}).format(r),re=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"short"}).format(r),fe={YYYY:h,YY:h?h.slice(-2):"",MMMM:j,MMM:M,MM:u,M:b,dddd:O,ddd:re,DD:m,D:y},ge={HH:p,H:w,hh:x!==""?String(x).padStart(2,"0"):"",h:x!==""?String(x):"",mm:f,m:f?String(parseInt(f,10)):"",ss:g,s:g?String(parseInt(g,10)):"",A,a:E},I=(k,Y)=>{if(!k)return"";const X=new RegExp(`(${Object.keys(Y).sort((R,ee)=>ee.length-R.length).join("|")})`,"g");return k.replace(X,R=>Y[R]??R)},q=I(t,fe),At=I(s,ge),ys=o();return q&&At?`${q} ${At} ${ys}`.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")||Dt,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 It;window.dataFormatter=V;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)return;if(!t.includes(".")){if(t in e){const r=e[t];return typeof r=="function"?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(i.hasOwnProperty(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(i.hasOwnProperty(n))i=i[n];else if(typeof i[n]=="function")i=i[n].call(i);else return}}return i}static isNullOrUndefined(e){return e==null}static deepClone(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(e instanceof Array)return e.map(t=>this.deepClone(t));if(e instanceof Object){const t={};for(const s in e)e.hasOwnProperty(s)&&(t[s]=this.deepClone(e[s]));return t}}static deepMerge(e,...t){if(!t.length)return e;const s=t.shift();if(this.isObject(e)&&this.isObject(s))for(const i in s)this.isObject(s[i])?(e[i]||Object.assign(e,{[i]:{}}),this.deepMerge(e[i],s[i])):Object.assign(e,{[i]:s[i]});return this.deepMerge(e,...t)}static isObject(e){return e&&typeof e=="object"&&!Array.isArray(e)}static debounce(e,t){let s;return function(...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={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};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 Ae(i,t):i):new Ae(e,t)}}class Ae{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&&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=Ae,typeof window<"u"&&(window.utils=$);const Mt=Object.prototype.toString,ne=Array.isArray||function(c){return Mt.call(c)==="[object Array]"},de=function(c){return typeof c=="function"},Xe=function(c){return c!==null&&typeof c=="object"};function kt(){return typeof window>"u"?null:window.MOJO?.dataFormatter?window.MOJO.dataFormatter:window.dataFormatter?window.dataFormatter:null}const et=function(c){const e={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};return String(c).replace(/[&<>"'`=\/]/g,function(t){return e[t]})};class tt{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 be{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 be(e,this)}lookup(e){if(this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;if(this.renderCache.has(i))return this.renderCache.get(i)}if(e===".")return this.view;if(e&&e.startsWith(".")){let i=e.substring(1),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&&de(o)&&(o=o.call(this.view))}catch{o=void 0}if(o===void 0&&i in this.view&&(o=this.view[i],de(o)&&(o=o.call(this.view))),n&&o!==void 0)try{const l=kt();l&&typeof l.pipe=="function"&&(o=l.pipe(o,n,this))}catch{}return ne(o)?r?o:o.length>0:Xe(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])||st(r,n[a])),r=r[n[a++]]}else a===n.length-1&&(o=Fe(r,n[a])||st(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(de(s)&&(s=s.call(this.view)),this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;this.renderCache.set(i,s)}return s}}function Fe(c,e){return c!=null&&typeof c=="object"&&e in c}function st(c,e){return c!=null&&typeof c!="object"&&c.hasOwnProperty&&c.hasOwnProperty(e)}class it{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 tt(e),n=[];let a,o,l,d,h;const u=new RegExp(Te(s)+"\\s*"),m=new RegExp("\\s*"+Te(i)),p=new RegExp("\\s*"+Te("}"+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===`
|
|
14
|
+
`}nl2br(e){return e==null?"":this.escapeHtml(String(e)).replace(/\r\n|\r|\n/g,"<br>")}code(e,t=""){if(e==null)return"";const s=t?`language-${this.escapeHtml(String(t))}`:"",i=this.escapeHtml(String(e));return`<pre class="bg-light p-2 rounded border"><code class="${s}">${i}</code></pre>`}register(e,t){if(typeof t!="function")throw new Error(`Formatter must be a function, got ${typeof t}`);return this.formatters.set(e.toLowerCase(),t),this}apply(e,t,...s){try{const i=this.formatters.get(e.toLowerCase());return i?i(t,...s):(console.warn(`Formatter '${e}' not found`),t)}catch(i){return console.error(`Error in formatter '${e}':`,i),t}}pipe(e,t,s=null){return t?this.parsePipeString(t,s).reduce((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 X=new Intl.DateTimeFormat(n,{hour:"2-digit",minute:"2-digit",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(q=>q.type==="timeZoneName");if(k=X?X.value:"",k&&/^GMT[+-]/i.test(k))try{const ee=new Intl.DateTimeFormat(n,{timeStyle:"short",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(ws=>ws.type==="timeZoneName");ee&&ee.value&&!/^GMT[+-]/i.test(ee.value)&&(k=ee.value)}catch{}if(k&&/\s/.test(k)){const q=k.split(/\s+/).map(ee=>ee[0]).join("").toUpperCase();q.length>=2&&q.length<=4&&(k=q)}}catch{k=""}return k};if(!a){const k=this.date(r,t),Y=this.time(r,s),X=o();return k&&Y?`${k} ${Y} ${X}`.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(X=>X.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)):"",w=p?String(parseInt(p,10)):"",x=p?parseInt(p,10)%12||12:"",A=p?parseInt(p,10)>=12?"PM":"AM":"",E=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),O=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"long"}).format(r),re=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"short"}).format(r),fe={YYYY:h,YY:h?h.slice(-2):"",MMMM:j,MMM:M,MM:u,M:b,dddd:O,ddd:re,DD:m,D:y},ge={HH:p,H:w,hh:x!==""?String(x).padStart(2,"0"):"",h:x!==""?String(x):"",mm:f,m:f?String(parseInt(f,10)):"",ss:g,s:g?String(parseInt(g,10)):"",A,a:E},I=(k,Y)=>{if(!k)return"";const X=new RegExp(`(${Object.keys(Y).sort((q,ee)=>ee.length-q.length).join("|")})`,"g");return k.replace(X,q=>Y[q]??q)},R=I(t,fe),At=I(s,ge),ys=o();return R&&At?`${R} ${At} ${ys}`.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")||Dt,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 It;window.dataFormatter=V;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)return;if(!t.includes(".")){if(t in e){const r=e[t];return typeof r=="function"?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(i.hasOwnProperty(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(i.hasOwnProperty(n))i=i[n];else if(typeof i[n]=="function")i=i[n].call(i);else return}}return i}static isNullOrUndefined(e){return e==null}static deepClone(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(e instanceof Array)return e.map(t=>this.deepClone(t));if(e instanceof Object){const t={};for(const s in e)e.hasOwnProperty(s)&&(t[s]=this.deepClone(e[s]));return t}}static deepMerge(e,...t){if(!t.length)return e;const s=t.shift();if(this.isObject(e)&&this.isObject(s))for(const i in s)this.isObject(s[i])?(e[i]||Object.assign(e,{[i]:{}}),this.deepMerge(e[i],s[i])):Object.assign(e,{[i]:s[i]});return this.deepMerge(e,...t)}static isObject(e){return e&&typeof e=="object"&&!Array.isArray(e)}static debounce(e,t){let s;return function(...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={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};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 Ae(i,t):i):new Ae(e,t)}}class Ae{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&&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=Ae,typeof window<"u"&&(window.utils=$);const Mt=Object.prototype.toString,ne=Array.isArray||function(c){return Mt.call(c)==="[object Array]"},de=function(c){return typeof c=="function"},Xe=function(c){return c!==null&&typeof c=="object"};function kt(){return typeof window>"u"?null:window.MOJO?.dataFormatter?window.MOJO.dataFormatter:window.dataFormatter?window.dataFormatter:null}const et=function(c){const e={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};return String(c).replace(/[&<>"'`=\/]/g,function(t){return e[t]})};class tt{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 be{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 be(e,this)}lookup(e){if(this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;if(this.renderCache.has(i))return this.renderCache.get(i)}if(e===".")return this.view;if(e&&e.startsWith(".")){let i=e.substring(1),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&&de(o)&&(o=o.call(this.view))}catch{o=void 0}if(o===void 0&&i in this.view&&(o=this.view[i],de(o)&&(o=o.call(this.view))),n&&o!==void 0)try{const l=kt();l&&typeof l.pipe=="function"&&(o=l.pipe(o,n,this))}catch{}return ne(o)?r?o:o.length>0:Xe(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])||st(r,n[a])),r=r[n[a++]]}else a===n.length-1&&(o=Fe(r,n[a])||st(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(de(s)&&(s=s.call(this.view)),this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;this.renderCache.set(i,s)}return s}}function Fe(c,e){return c!=null&&typeof c=="object"&&e in c}function st(c,e){return c!=null&&typeof c!="object"&&c.hasOwnProperty&&c.hasOwnProperty(e)}class it{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 tt(e),n=[];let a,o,l,d,h;const u=new RegExp(Te(s)+"\\s*"),m=new RegExp("\\s*"+Te(i)),p=new RegExp("\\s*"+Te("}"+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
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 be(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||!ne(h)){console.warn(`MUSTACHE WARNING - Section ${l[1]} has no child tokens:`,l);continue}if(ne(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(de(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||ne(d)&&d.length===0){const u=l[4];u&&ne(u)&&(a+=this.renderTokens(u,t,s,i,r,n))}break;case">":if(!s)continue;d=de(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+=et(d));break;case"text":a+=l[1];break}}return a}getConfigTags(e){return Xe(e)&&ne(e.tags)?e.tags:null}}function Te(c){return c.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}const Ee=new it,D={name:"MOJO Mustache",version:"1.0.0",tags:["{{","}}"],Scanner:tt,Context:be,Writer:it,escape:et,clearCache(){return Ee.clearCache()},parse(c,e){return Ee.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)),Ee.render(c,e,t,s)}};class Lt{constructor(e){this.view=e,this.domListeners=[],this.debounceTimers=new Map}bind(e){if(this.unbind(),!e)return;const t=async a=>{const o=a.target.closest("[data-action]");if(o&&this.shouldHandle(o,a)){const d=o.getAttribute("data-action");if(o.tagName==="A"&&a.preventDefault(),this.hideTooltip(o),await this.dispatch(d,a,o)){a.preventDefault(),a.stopPropagation(),a.handledByChild=!0;return}}const l=a.target.closest("a[href], [data-page]");if(l&&!l.hasAttribute("data-action")&&this.shouldHandle(l,a)){if(a.ctrlKey||a.metaKey||a.shiftKey||a.button===1)return;if(l.tagName==="A"){const d=l.getAttribute("href");if(d&&d!=="#"&&!d.startsWith("#")&&(this.view.isExternalLink(d)||l.hasAttribute("data-external")))return}this.hideTooltip(l),a.preventDefault(),a.stopPropagation(),a.handledByChild=!0,l.hasAttribute("data-page")?await this.view.handlePageNavigation(l):await this.view.handleHrefNavigation(l)}},s=a=>{const o=a.target.closest("[data-change-action]");if(o&&this.shouldHandle(o,a)){const d=o.getAttribute("data-change-action");this.dispatchChange(d,a,o).then(h=>{h&&(a.stopPropagation(),a.handledByChild=!0)});return}const l=a.target.closest("[data-action]");if(l&&this.isFormControl(l)&&this.shouldHandle(l,a)){const d=l.getAttribute("data-action");this.dispatch(d,a,l).then(h=>{h&&(a.stopPropagation(),a.handledByChild=!0)})}},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=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||!this.shouldHandle(o,a))return;let l=["Enter"];if(o.getAttribute("data-change-keys")&&(l=o.getAttribute("data-change-keys").split(",").map(d=>d.trim())),l.includes("*")||l.includes(a.key)){const d=o.getAttribute("data-keydown-action")||o.getAttribute("data-change-action");this.dispatch(d,a,o).then(h=>{h&&(a.preventDefault(),a.stopPropagation(),a.handledByChild=!0)})}},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 De={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 C{constructor(e={}){this.tagName=e.tagName??"div",this.className=e.className??"mojo-view",this.style=e.style??null,this.id=e.id??C._genId(),this.containerId=e.containerId??null,this.container=e.container??null,typeof this.container=="string"&&(this.containerId=this.container,this.container=null),this.parent=e.parent??null,this.children=e.children??{},this.template=e.template||e.templateUrl||"",this.data=e.data??{},this.isRendering=!1,this.lastRenderTime=0,this.mounted=!1,this.debug=e.debug??!1,this.app=e.app??null,this.cacheTemplate=e.cacheTemplate??!0,this.enableTooltips=e.enableTooltips??!1,this.options={...e},this.element=this._ensureElement(),this.events=new Lt(this),e.model&&this.setModel(e.model)}async onInit(){}async onInitView(){this.initialized||(this.initialized=!0,await this.onInit())}async onBeforeRender(){}async onAfterRender(){}async onBeforeMount(){}async onAfterMount(){}async onBeforeUnmount(){}async onAfterUnmount(){}async onBeforeDestroy(){}async onAfterDestroy(){}setModel(e={}){let t=e!==this.model;if(!t)return this;this.model&&this.model.off&&this.model.off("change",this._onModelChange,this),this.model=e,this.model&&this.model.on&&this.model.on("change",this._onModelChange,this);for(const s in this.children){const i=this.children[s];i&&typeof i.setModel=="function"&&i.setModel(e)}return t&&this._onModelChange(),this}_onModelChange(){this.isMounted()&&this.render()}setTemplate(e){return this.template=e??"",this}addChild(e,t){try{if(!e||typeof e!="object")return this;t&&((t.containerId||t.container)&&(e.containerId=t.containerId||t.container),t.id&&(e.id=t.id),t.lazyMount===!0&&(e._lazyMount=!0)),e.parent=this,this.getApp()&&(e.app=this.app),this.children[e.id]=e}catch(s){C._warn("addChild error",s)}return e}removeChild(e){try{const t=typeof e=="string"?e:e&&e.id;if(!t)return this;const s=this.children[t];s&&(Promise.resolve(s.destroy()).catch(i=>C._warn("removeChild destroy error",i)),delete this.children[t])}catch(t){C._warn("removeChild error",t)}return this}getChild(e){return this.children[e]}async updateData(e,t=!1){return Object.assign(this.data,e),t&&this.isMounted()&&await this.render(),this}toggleClass(e,t){return t===void 0&&(t=!this.element.classList.contains(e)),this.element.classList.toggle(e,t),this}addClass(e){return this.element.classList.add(e),this}setClass(e){return this.element.className=e,this}removeClass(e){return this.element.classList.remove(e),this}canRender(){if(this.isRendering)return!1;const e=Date.now();if(this.options.renderCooldown>0&&e-this.lastRenderTime<this.options.renderCooldown)return C._warn(`View ${this.id}: Render called too quickly, cooldown active`),!1;if(this.options.noAppend&&this.parent)if(this.parent.contains(this.containerId||this.container)){if(this.containerId&&!document.getElementById(this.containerId))return!1;if(this.container&&!document.contains(this.container))return!1}else return!1;return!0}async render(e=!0,t=null){const s=Date.now();if(!this.canRender())return this;this.isRendering=!0,this.lastRenderTime=s;try{this.initialized||await this.onInitView(),this.unbindEvents(),await this.onBeforeRender(),this.getViewData&&(this.data=await this.getViewData());const i=await this.renderTemplate();this.element.innerHTML=i,e&&!this.isMounted()&&await this.mount(t),await this._renderChildren(),await this.onAfterRender(),this.bindEvents()}catch(i){C._warn(`Render error in ${this.id}`,i)}finally{this.isRendering=!1}return this}async _renderChildren(){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=>C._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=>C._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=>C._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=>C._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=>C._warn(`Child destroy error (${e})`,s))}this.mounted=!1,this.element&&this.element.parentNode&&(await this.onBeforeDestroy(),this.element.parentNode&&this.element.parentNode.removeChild(this.element),await this.onAfterDestroy())}catch(e){C._warn(`Destroy error in ${this.id}`,e)}}_ensureElement(){try{if(this.element&&this.element.tagName?.toLowerCase()===this.tagName)return this._syncAttrs(),this.element;const e=document.createElement(this.tagName);return this.element=e,this.el=e,this._syncAttrs(),e}catch(e){C._warn("ensureElement error",e);const t=document.createElement("div");return t.id=this.id||C._genId(),t}}_syncAttrs(){try{if(!this.element)return;this.id&&(this.element.id=this.id),this.element.className=this.className||"",this.style==null?this.element.removeAttribute("style"):this.element.style.cssText=String(this.style)}catch(e){C._warn("_syncAttrs error",e)}}bindEvents(){this.events.bind(this.element),this.enableTooltips&&this.initializeTooltips()}unbindEvents(){this.events.unbind(),this.enableTooltips&&this.disposeTooltips()}async renderTemplate(){const e=await this.getTemplate();if(!e)return"";const t=this.getPartials();return 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){C._warn(`Failed to load template from ${e}: ${s}`),this.showError?.(`Failed to load template from ${e}: ${s.message}`)}else typeof e=="function"&&(t=await this.template(this.data,this.state));return this.cacheTemplate&&t&&(this._templateCache=t),t}getContextValue(e){const t=$.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(C.prototype,De);class _ extends C{static _openDialogs=[];static _baseZIndex={backdrop:1050,modal:1055};static getFullscreenAwareZIndex(){return document.querySelector(".table-fullscreen")?{backdrop:10040,modal:10050}:_._baseZIndex}static fixAllBackdropStacking(){const e=document.querySelectorAll(".modal-backdrop"),t=_._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(){_.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 C||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 C?(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 C)this.headerView=e,this.headerContent=null,this.addChild(this.headerView);else if(typeof e=="function")try{const t=e();t instanceof C?(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 C)this.footerView=e,this.footer=null,this.addChild(this.footerView);else if(typeof e=="function")try{const t=e();t instanceof C?(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">
|
|
@@ -199,7 +199,7 @@ var MOJO=(function(F){"use strict";class $e{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 qt{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 Me({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 le extends se{constructor(e={}){super(e,{endpoint:"/api/group"})}}class ke extends oe{constructor(e={}){super({ModelClass:le,endpoint:"/api/group",size:10,...e})}}const rt={org:"Organization",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"},Le=Object.entries(rt).map(([c,e])=>({value:c,label:e})),Pe={create:{title:"Create Group",fields:[{name:"name",type:"text",label:"Group Name",required:!0,placeholder:"Enter group name"},{name:"kind",type:"select",label:"Group Kind",required:!0,options:Le},{type:"collection",name:"parent",label:"Parent Group",Collection:ke,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300}]},edit:{title:"Edit Group",fields:[{name:"name",type:"text",label:"Group Name",required:!0,placeholder:"Enter group name"},{name:"kind",type:"select",label:"Group Kind",required:!0,options:Le},{type:"collection",name:"parent",label:"Parent Group",Collection:ke,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300},{name:"metadata.domain",type:"text",label:"Default Domain",placeholder:"Enter Domain"},{name:"metadata.portal",type:"text",label:"Default Portal",placeholder:"Enter Portal URL"},{name:"is_active",type:"switch",label:"Is Active",cols:4}]}};le.EDIT_FORM=Pe.edit,le.ADD_FORM=Pe.create,le.CREATE_FORM=Pe.create,le.GroupKindOptions=Le,le.GroupKinds=rt;class S extends se{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)||!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=S.GRANULAR_TO_CATEGORY[e];return!!(s&&t[s]==!0)}hasPerm(e){return this.hasPermission(e)}}S.CATEGORY_PERMISSIONS=[{name:"view_admin",label:"Admin Panel",tooltip:"Access the admin panel, assistant, 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:"AI Assistant",tooltip:"Access to the AI Assistant"},{name:"comms",label:"Communication",tooltip:"Ability to notify users"}],S.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"}]}],S.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"]},S.APP_CATEGORY_PERMISSIONS=[],S.APP_GRANULAR_PERMISSIONS=[],S._permSwitch=function(c){return{name:`permissions.${c.name}`,type:"switch",label:c.label,columns:6,...c.tooltip?{tooltip:c.tooltip}:{}}},S.PERMISSIONS=[],S.PERMISSION_FIELDS=[],S.CATEGORY_PERMISSION_FIELDS=[],S.GRANULAR_PERMISSION_FIELDS=[],S.GRANULAR_TO_CATEGORY={},S.rebuildPermissions=function(){const c=S._permSwitch;S.PERMISSIONS.length=0,S.PERMISSIONS.push(...S.CATEGORY_PERMISSIONS,...S.GRANULAR_PERMISSION_TABS.flatMap(s=>s.permissions),...S.APP_CATEGORY_PERMISSIONS,...S.APP_GRANULAR_PERMISSIONS),S.PERMISSION_FIELDS.length=0,S.PERMISSION_FIELDS.push(...S.PERMISSIONS.map(c));const e=[{label:"System",fields:S.CATEGORY_PERMISSIONS.map(c)}];S.APP_CATEGORY_PERMISSIONS.length>0&&e.push({label:"App",fields:S.APP_CATEGORY_PERMISSIONS.map(c)}),S.CATEGORY_PERMISSION_FIELDS.length=0,S.CATEGORY_PERMISSION_FIELDS.push({type:"tabset",tabs:e});const t=S.GRANULAR_PERMISSION_TABS.map(s=>({label:s.label,fields:s.permissions.map(c)}));S.APP_GRANULAR_PERMISSIONS.length>0&&t.push({label:"App",fields:S.APP_GRANULAR_PERMISSIONS.map(c)}),S.GRANULAR_PERMISSION_FIELDS.length=0,S.GRANULAR_PERMISSION_FIELDS.push({type:"tabset",tabs:t});for(const s of Object.keys(S.GRANULAR_TO_CATEGORY))delete S.GRANULAR_TO_CATEGORY[s];for(const[s,i]of Object.entries(S.CATEGORY_GRANULAR_MAP))for(const r of i)S.GRANULAR_TO_CATEGORY[r]=s},S.registerCategoryMap=function(c){if(!c)return;let e=!1;for(const[t,s]of Object.entries(c)){if(!Array.isArray(s))continue;const i=S.CATEGORY_GRANULAR_MAP[t]||[];S.CATEGORY_GRANULAR_MAP[t]=Array.from(new Set([...i,...s])),e=!0}e&&S.rebuildPermissions()},S.registerPermissions=function(c){if(c){if(Array.isArray(c.categories)&&S.APP_CATEGORY_PERMISSIONS.push(...c.categories),Array.isArray(c.granularPermissions)&&S.APP_GRANULAR_PERMISSIONS.push(...c.granularPermissions),Array.isArray(c.granularTabs)&&S.GRANULAR_PERMISSION_TABS.push(...c.granularTabs),c.categoryGranularMap)for(const[e,t]of Object.entries(c.categoryGranularMap)){if(!Array.isArray(t))continue;const s=S.CATEGORY_GRANULAR_MAP[e]||[];S.CATEGORY_GRANULAR_MAP[e]=Array.from(new Set([...s,...t]))}S.rebuildPermissions()}},S.rebuildPermissions();const nt={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:ke,labelField:"name",valueField:"id",columns:12}]},permissions:{fields:S.PERMISSION_FIELDS}},Rt={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}]}};S.DATA_VIEW=Rt.detailed,S.EDIT_FORM=nt.edit,S.ADD_FORM=nt.create;let zt=class extends se{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 qt(this,e)}};class v{static _renderAndAwait(e,{buttons:t=null,rejectOnDismiss:s=!1,onAction:i=null,cleanup:r=null}={}){const n=_.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 w=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(w)}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 w=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(w)}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 _({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 Rt{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 Me({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 le extends se{constructor(e={}){super(e,{endpoint:"/api/group"})}}class ke extends oe{constructor(e={}){super({ModelClass:le,endpoint:"/api/group",size:10,...e})}}const rt={org:"Organization",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"},Le=Object.entries(rt).map(([c,e])=>({value:c,label:e})),Pe={create:{title:"Create Group",fields:[{name:"name",type:"text",label:"Group Name",required:!0,placeholder:"Enter group name"},{name:"kind",type:"select",label:"Group Kind",required:!0,options:Le},{type:"collection",name:"parent",label:"Parent Group",Collection:ke,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300}]},edit:{title:"Edit Group",fields:[{name:"name",type:"text",label:"Group Name",required:!0,placeholder:"Enter group name"},{name:"kind",type:"select",label:"Group Kind",required:!0,options:Le},{type:"collection",name:"parent",label:"Parent Group",Collection:ke,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300},{name:"metadata.domain",type:"text",label:"Default Domain",placeholder:"Enter Domain"},{name:"metadata.portal",type:"text",label:"Default Portal",placeholder:"Enter Portal URL"},{name:"is_active",type:"switch",label:"Is Active",cols:4}]}};le.EDIT_FORM=Pe.edit,le.ADD_FORM=Pe.create,le.CREATE_FORM=Pe.create,le.GroupKindOptions=Le,le.GroupKinds=rt;class S extends se{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)||!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=S.GRANULAR_TO_CATEGORY[e];return!!(s&&t[s]==!0)}hasPerm(e){return this.hasPermission(e)}}S.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"},{name:"comms",label:"Communication",tooltip:"Ability to notify users"}],S.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"}]}],S.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"]},S.APP_CATEGORY_PERMISSIONS=[],S.APP_GRANULAR_PERMISSIONS=[],S._permSwitch=function(c){return{name:`permissions.${c.name}`,type:"switch",label:c.label,columns:6,...c.tooltip?{tooltip:c.tooltip}:{}}},S.PERMISSIONS=[],S.PERMISSION_FIELDS=[],S.CATEGORY_PERMISSION_FIELDS=[],S.GRANULAR_PERMISSION_FIELDS=[],S.GRANULAR_TO_CATEGORY={},S.rebuildPermissions=function(){const c=S._permSwitch;S.PERMISSIONS.length=0,S.PERMISSIONS.push(...S.CATEGORY_PERMISSIONS,...S.GRANULAR_PERMISSION_TABS.flatMap(s=>s.permissions),...S.APP_CATEGORY_PERMISSIONS,...S.APP_GRANULAR_PERMISSIONS),S.PERMISSION_FIELDS.length=0,S.PERMISSION_FIELDS.push(...S.PERMISSIONS.map(c));const e=[{label:"System",fields:S.CATEGORY_PERMISSIONS.map(c)}];S.APP_CATEGORY_PERMISSIONS.length>0&&e.push({label:"App",fields:S.APP_CATEGORY_PERMISSIONS.map(c)}),S.CATEGORY_PERMISSION_FIELDS.length=0,S.CATEGORY_PERMISSION_FIELDS.push({type:"tabset",tabs:e});const t=S.GRANULAR_PERMISSION_TABS.map(s=>({label:s.label,fields:s.permissions.map(c)}));S.APP_GRANULAR_PERMISSIONS.length>0&&t.push({label:"App",fields:S.APP_GRANULAR_PERMISSIONS.map(c)}),S.GRANULAR_PERMISSION_FIELDS.length=0,S.GRANULAR_PERMISSION_FIELDS.push({type:"tabset",tabs:t});for(const s of Object.keys(S.GRANULAR_TO_CATEGORY))delete S.GRANULAR_TO_CATEGORY[s];for(const[s,i]of Object.entries(S.CATEGORY_GRANULAR_MAP))for(const r of i)S.GRANULAR_TO_CATEGORY[r]=s},S.registerCategoryMap=function(c){if(!c)return;let e=!1;for(const[t,s]of Object.entries(c)){if(!Array.isArray(s))continue;const i=S.CATEGORY_GRANULAR_MAP[t]||[];S.CATEGORY_GRANULAR_MAP[t]=Array.from(new Set([...i,...s])),e=!0}e&&S.rebuildPermissions()},S.registerPermissions=function(c){if(c){if(Array.isArray(c.categories)&&S.APP_CATEGORY_PERMISSIONS.push(...c.categories),Array.isArray(c.granularPermissions)&&S.APP_GRANULAR_PERMISSIONS.push(...c.granularPermissions),Array.isArray(c.granularTabs)&&S.GRANULAR_PERMISSION_TABS.push(...c.granularTabs),c.categoryGranularMap)for(const[e,t]of Object.entries(c.categoryGranularMap)){if(!Array.isArray(t))continue;const s=S.CATEGORY_GRANULAR_MAP[e]||[];S.CATEGORY_GRANULAR_MAP[e]=Array.from(new Set([...s,...t]))}S.rebuildPermissions()}},S.rebuildPermissions();const nt={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:ke,labelField:"name",valueField:"id",columns:12}]},permissions:{fields:S.PERMISSION_FIELDS}},qt={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}]}};S.DATA_VIEW=qt.detailed,S.EDIT_FORM=nt.edit,S.ADD_FORM=nt.create;let zt=class extends se{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 Rt(this,e)}};class v{static _renderAndAwait(e,{buttons:t=null,rejectOnDismiss:s=!1,onAction:i=null,cleanup:r=null}={}){const n=_.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 w=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(w)}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 w=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(w)}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 _({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(F){"use strict";class $e{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(()=>_t)).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 _({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(()=>_t)).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 _({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(()=>bs)).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 _({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 he({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 _({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 Ot({html:t,height:r}),o=[{text:"Close",class:"btn-secondary",dismiss:!0}],l=new _({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 zt;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){Ie.show(e)}static hideLoading(e){Ie.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 ye{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 Ft,this.rest=te,this.modal=v,e.api&&this.rest.configure(e.api);const t=(this.name||"mojo").replace(/\s+/g,"_").toLowerCase();this.theme=new Tt({storageKey:`${t}:theme`,eventBus:this.events}),this.theme.init(),this.router=new $e({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.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,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}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)}setupRest(){this.rest=te,te.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 ye(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 ue extends C{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(()=>_t)).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 _({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(()=>_t)).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 _({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(()=>bs)).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 _({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 he({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 _({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 Ot({html:t,height:r}),o=[{text:"Close",class:"btn-secondary",dismiss:!0}],l=new _({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 zt;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){Ie.show(e)}static hideLoading(e){Ie.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 ye{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 Ft,this.rest=te,this.modal=v,e.api&&this.rest.configure(e.api);const t=(this.name||"mojo").replace(/\s+/g,"_").toLowerCase();this.theme=new Tt({storageKey:`${t}:theme`,eventBus:this.events}),this.theme.init(),this.router=new $e({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,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}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=te,te.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 ye(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 ue extends C{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=`
|
|
@@ -569,7 +569,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
|
|
|
569
569
|
</div>
|
|
570
570
|
</div>
|
|
571
571
|
</div>
|
|
572
|
-
`}buildFieldHTML(e){const{type:t,columns:s,class:i=""}=e;let r="";const n=Z&&typeof Z.getRenderer=="function"?Z.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;this.isAutoSizingField(e)?a=`col ${i}`.trim():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(([w,x])=>`${w}="${this.escapeHtml(x)}"`).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:this.escapeHtml(f),label:i?this.escapeHtml(i):null,placeholder:n?this.escapeHtml(n):null,help:u?this.escapeHtml(u):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:p?this.escapeHtml(p):null,required:a,disabled:o,readonly:l,attrs:g,showCopy:!!e.showCopy};if(t==="password"&&(e.showToggle||e.strengthMeter||e.capsLockWarning)){const w={...y,showToggle:!!e.showToggle,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,w)}if(t==="password"){const w={...y,showToggle:e.showToggle!==!1,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,w)}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(([x,A])=>`${x}="${this.escapeHtml(A)}"`).join(" "),y=this.getFieldId(t),w={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:y,name:t,fieldValue:g,label:s?this.escapeHtml(s):null,placeholder:r?this.escapeHtml(r):null,help:m?this.escapeHtml(m):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:f?this.escapeHtml(f):null,rows:l||3,required:n,disabled:a,readonly:o,showCopy:!!e.showCopy,attrs:b};return D.render(this.templates.textarea,w)}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(([w,x])=>`${w}="${this.escapeHtml(x)}"`).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?this.escapeHtml(s):null,placeholder:r?this.escapeHtml(r):null,help:u?this.escapeHtml(u):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:p?this.escapeHtml(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(([w,x])=>`${w}="${this.escapeHtml(x)}"`).join(" "),y={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,fieldValue:m,label:s?this.escapeHtml(s):null,placeholder:i?this.escapeHtml(i):null,help:h?this.escapeHtml(h):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:f?this.escapeHtml(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,w=`form-select ${d}`.trim(),x=this.errors[t],E=this.getFieldValue(t)??r,j=Object.entries(h).map(([I,q])=>`${I}="${this.escapeHtml(q)}"`).join(" "),M=this.getFieldId(t);let O=[...i];if(m!==void 0&&p!==void 0){const I=f!==void 0?f:1,q=this.generateSelectOptions(m,p,I,{format:g,prefix:b,suffix:y});O=[...O,...q]}let re="";Array.isArray(O)&&(re=O.map(I=>{if(typeof I=="string"){const q=I===E?"selected":"";return`<option value="${this.escapeHtml(I)}" ${q}>${this.escapeHtml(I)}</option>`}else if(I&&typeof I=="object"){const q=I.value==E?"selected":"";return`<option value="${this.escapeHtml(I.value)}" ${q}>${this.escapeHtml(I.label||I.text||I.value)}</option>`}return""}).join(""));const fe=l?`
|
|
572
|
+
`}buildFieldHTML(e){const{type:t,columns:s,class:i=""}=e;let r="";const n=Z&&typeof Z.getRenderer=="function"?Z.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;this.isAutoSizingField(e)?a=`col ${i}`.trim():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(([w,x])=>`${w}="${this.escapeHtml(x)}"`).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:this.escapeHtml(f),label:i?this.escapeHtml(i):null,placeholder:n?this.escapeHtml(n):null,help:u?this.escapeHtml(u):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:p?this.escapeHtml(p):null,required:a,disabled:o,readonly:l,attrs:g,showCopy:!!e.showCopy};if(t==="password"&&(e.showToggle||e.strengthMeter||e.capsLockWarning)){const w={...y,showToggle:!!e.showToggle,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,w)}if(t==="password"){const w={...y,showToggle:e.showToggle!==!1,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,w)}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(([x,A])=>`${x}="${this.escapeHtml(A)}"`).join(" "),y=this.getFieldId(t),w={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:y,name:t,fieldValue:g,label:s?this.escapeHtml(s):null,placeholder:r?this.escapeHtml(r):null,help:m?this.escapeHtml(m):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:f?this.escapeHtml(f):null,rows:l||3,required:n,disabled:a,readonly:o,showCopy:!!e.showCopy,attrs:b};return D.render(this.templates.textarea,w)}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(([w,x])=>`${w}="${this.escapeHtml(x)}"`).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?this.escapeHtml(s):null,placeholder:r?this.escapeHtml(r):null,help:u?this.escapeHtml(u):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:p?this.escapeHtml(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(([w,x])=>`${w}="${this.escapeHtml(x)}"`).join(" "),y={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,fieldValue:m,label:s?this.escapeHtml(s):null,placeholder:i?this.escapeHtml(i):null,help:h?this.escapeHtml(h):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:f?this.escapeHtml(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,w=`form-select ${d}`.trim(),x=this.errors[t],E=this.getFieldValue(t)??r,j=Object.entries(h).map(([I,R])=>`${I}="${this.escapeHtml(R)}"`).join(" "),M=this.getFieldId(t);let O=[...i];if(m!==void 0&&p!==void 0){const I=f!==void 0?f:1,R=this.generateSelectOptions(m,p,I,{format:g,prefix:b,suffix:y});O=[...O,...R]}let re="";Array.isArray(O)&&(re=O.map(I=>{if(typeof I=="string"){const R=I===E?"selected":"";return`<option value="${this.escapeHtml(I)}" ${R}>${this.escapeHtml(I)}</option>`}else if(I&&typeof I=="object"){const R=I.value==E?"selected":"";return`<option value="${this.escapeHtml(I.value)}" ${R}>${this.escapeHtml(I.label||I.text||I.value)}</option>`}return""}).join(""));const fe=l?`
|
|
573
573
|
<input type="text"
|
|
574
574
|
class="form-control form-control-sm mb-2"
|
|
575
575
|
placeholder="Search options..."
|
|
@@ -707,13 +707,13 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
|
|
|
707
707
|
${w?`<div class="${this.options.helpClass}">${this.escapeHtml(w)}</div>`:""}
|
|
708
708
|
${A?`<div class="${this.options.errorClass}">${this.escapeHtml(A)}</div>`:""}
|
|
709
709
|
</div>
|
|
710
|
-
`}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:w=" – ",months:x=null,presets:A=null,autoApply:E=!0,inline:j=!1,help:M=e.helpText||e.help||""}=e,O=this.getFieldId(t||s||"daterange"),re=this.errors[t],fe=s||(t?t+"_start":""),ge=i||(t?t+"_end":""),I=this.getFieldValue(fe)||a,
|
|
710
|
+
`}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:w=" – ",months:x=null,presets:A=null,autoApply:E=!0,inline:j=!1,help:M=e.helpText||e.help||""}=e,O=this.getFieldId(t||s||"daterange"),re=this.errors[t],fe=s||(t?t+"_start":""),ge=i||(t?t+"_end":""),I=this.getFieldValue(fe)||a,R=this.getFieldValue(ge)||o;return`
|
|
711
711
|
<div class="mojo-form-control">
|
|
712
712
|
${n?`<label for="${O}" class="${this.options.labelClass}">${this.escapeHtml(n)}${h?'<span class="text-danger">*</span>':""}${this.renderTooltipIcon(e)}</label>`:""}
|
|
713
713
|
<div class="date-range-picker-placeholder"
|
|
714
714
|
data-field-name="${t||s||"daterange"}"
|
|
715
715
|
data-field-type="daterange"
|
|
716
|
-
data-field-config='${JSON.stringify({name:t,startName:s,endName:i,fieldName:r,startDate:I,endDate:
|
|
716
|
+
data-field-config='${JSON.stringify({name:t,startName:s,endName:i,fieldName:r,startDate:I,endDate:R,precision:l,placeholder:d,min:p,max:f,format:g,displayFormat:b,outputFormat:y,separator:w,months:x,presets:A,autoApply:E,inline:j,disabled:u,readonly:m,required:h})}'></div>
|
|
717
717
|
${M?`<div class="${this.options.helpClass}">${this.escapeHtml(M)}</div>`:""}
|
|
718
718
|
${re?`<div class="${this.options.errorClass}">${this.escapeHtml(re)}</div>`:""}
|
|
719
719
|
</div>
|
|
@@ -1024,7 +1024,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
|
|
|
1024
1024
|
<div class="invalid-feedback d-block">{{error}}</div>
|
|
1025
1025
|
{{/error}}
|
|
1026
1026
|
</div>
|
|
1027
|
-
`,...e}),this.name=e.name||"multiselect",this.label=e.label||"",this.help=e.help||"",this.error=e.error||"",this.required=e.required||!1,this.disabled=e.disabled||!1,this.placeholder=e.placeholder||e.placeHolder||"Select...",this.maxHeight=e.maxHeight||300,this.showSelectedLabels=e.showSelectedLabels!==!1,this.maxLabelsToShow=e.maxLabelsToShow||3,this.options=e.options||[],this.selectedValues=Array.isArray(e.value)?e.value:[],this.buttonText=this.computeButtonText(),this.listView=null}computeButtonText(){const e=this.selectedValues.length;return e===0?this.placeholder||"Select...":this.showSelectedLabels&&e<=this.maxLabelsToShow?this.selectedValues.map(s=>{const i=this.options.find(r=>(typeof r=="string"?r:r.value)===s);return typeof i=="string"?i:i?.label||i?.value||s}).join(", "):`${e} selected`}async onAfterRender(){await super.onAfterRender(),this.createListView()}createListView(){const e=this.element?.querySelector('[data-container="items"]');if(!e)return;const t=this.options.map((s,i)=>{const r=typeof s=="string"?s:s.value,n=typeof s=="string"?s:s.label||s.text||s.value,a=typeof s=="object"?s.disabled:!1;return{id:`${this.name}_${i}`,value:r,label:n,index:i,selected:this.selectedValues.includes(r),disabled:a}});this.listView=new Zt({items:t,maxHeight:this.maxHeight}),this.listView.on("toggle",s=>{this.handleToggle(s)}),this.listView.on("close-dropdown",()=>{this.closeDropdown()}),this.listView.render(!0,e)}closeDropdown(){const e=this.element?.querySelector(".dropdown-toggle");if(e&&window.bootstrap?.Dropdown){const t=window.bootstrap.Dropdown.getInstance(e);t&&t.hide()}}handleToggle(e){const{value:t,selected:s}=e;s?this.selectedValues.includes(t)||this.selectedValues.push(t):this.selectedValues=this.selectedValues.filter(i=>i!==t),this.updateButtonText(),this.emit("change",{value:this.selectedValues,name:this.name})}updateButtonText(){const e=this.element?.querySelector(".multiselect-button-text");if(!e)return;const t=this.selectedValues.length;this.buttonText=this.computeButtonText(),e.textContent=this.buttonText,t===0?e.classList.add("text-muted"):e.classList.remove("text-muted")}getValue(){return this.selectedValues}setValue(e){this.selectedValues=Array.isArray(e)?e:e?[e]:[],this.listView&&this.listView.setValue(this.selectedValues),this.updateButtonText()}setOptions(e){if(this.options=e,this.listView){const t=this.options.map((s,i)=>{const r=typeof s=="string"?s:s.value,n=typeof s=="string"?s:s.label||s.text||s.value,a=typeof s=="object"?s.disabled:!1;return{id:`${this.name}_${i}`,value:r,label:n,index:i,selected:this.selectedValues.includes(r),disabled:a}});this.listView.updateItems(t)}}clear(){this.setValue([])}getFormValue(){return this.getValue()}setFormValue(e){this.setValue(e)}async onBeforeDestroy(){await super.onBeforeDestroy(),this.listView&&this.listView.destroy()}}const Ne=["January","February","March","April","May","June","July","August","September","October","November","December"],Oe=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function at(c){if(c==null||c==="")return null;const e=parseInt(String(c).slice(0,4),10);return Number.isFinite(e)?{y:e}:null}function we(c){if(c==null||c==="")return null;const e=String(c).split("-"),t=parseInt(e[0],10),s=parseInt(e[1],10);return!Number.isFinite(t)||!Number.isFinite(s)||s<1||s>12?null:{y:t,m:s}}function z(c){if(c==null||c==="")return null;if(c instanceof Date&&!isNaN(c.getTime()))return{y:c.getFullYear(),m:c.getMonth()+1,d:c.getDate()};const e=String(c).split("-"),t=parseInt(e[0],10),s=parseInt(e[1],10),i=parseInt(e[2],10);return!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(i)||s<1||s>12||i<1||i>31?null:{y:t,m:s,d:i}}function ot(c){const e=typeof c=="object"?c:at(c);return e?String(e.y):""}function je(c){const e=typeof c=="object"?c:we(c);return e?`${e.y}-${K(e.m)}`:""}function H(c){const e=typeof c=="object"?c:z(c);return e?`${e.y}-${K(e.m)}-${K(e.d)}`:""}function B(c,e){return e==="year"?ot(c):e==="month"?je(c):H(c)}function P(c,e){return e==="year"?at(c):e==="month"?we(c):z(c)}const Qt=/YYYY|YY|MMMM|MMM|MM|M|DD|D/g;function ce(c,e){if(!c)return"";const t=c.y,s=c.m,i=c.d;return String(e).replace(Qt,r=>{switch(r){case"YYYY":return String(t);case"YY":return String(t).slice(-2);case"MMMM":return s?Ne[s-1]:"";case"MMM":return s?Oe[s-1]:"";case"MM":return s?K(s):"";case"M":return s?String(s):"";case"DD":return i?K(i):"";case"D":return i?String(i):"";default:return r}})}function lt(c,e){return new Date(c,e,0).getDate()}function Xt(c,e,t,s=1){return((new Date(c,e-1,t).getDay()-s)%7+7)%7}function ie(c,e){if(!c)return null;let t=c.y,s=c.m+e;for(;s>12;)s-=12,t+=1;for(;s<1;)s+=12,t-=1;if(c.d==null)return{y:t,m:s};const i=lt(t,s);return{y:t,m:s,d:Math.min(c.d,i)}}function ct(c,e){return!c||!e?0:c.y!==e.y?c.y<e.y?-1:1:(c.m||0)!==(e.m||0)?(c.m||0)<(e.m||0)?-1:1:(c.d||0)!==(e.d||0)?(c.d||0)<(e.d||0)?-1:1:0}function dt(c,e){return!c||!e?0:c.y!==e.y?c.y<e.y?-1:1:(c.m||0)!==(e.m||0)?(c.m||0)<(e.m||0)?-1:1:0}function es(c,e){return!c||!e||c.y===e.y?0:c.y<e.y?-1:1}function U(c,e,t){return t==="year"?es(c,e):t==="month"?dt(c,e):ct(c,e)}function W(c){if(c==null||c==="")return null;if(typeof c=="object"&&c!==null){const d=parseInt(c.hours??c.h,10),h=parseInt(c.minutes??c.m,10);return!Number.isFinite(d)||!Number.isFinite(h)||d<0||d>23||h<0||h>59?null:{hours:d,minutes:h}}const e=String(c).trim(),t=e.indexOf(" "),s=t>-1?e.slice(0,t):e,r=(t>-1?e.slice(t+1).trim():"").match(/^(am|pm)$/i)||s.match(/(am|pm)$/i),a=s.replace(/(am|pm)$/i,"").trim().split(":");if(a.length<2)return null;let o=parseInt(a[0],10);const l=parseInt(a[1],10);if(!Number.isFinite(o)||!Number.isFinite(l)||l<0||l>59)return null;if(r){const d=r[1].toLowerCase()==="pm";if(o<1||o>12)return null;o===12?o=d?12:0:d&&(o+=12)}return o<0||o>23?null:{hours:o,minutes:l}}function G(c,e="24h"){if(!c)return"";const t=c.hours,s=c.minutes;if(!Number.isFinite(t)||!Number.isFinite(s))return"";if(e==="12h"){const i=t>=12?"PM":"AM";let r=t%12;return r===0&&(r=12),`${r}:${K(s)} ${i}`}return`${K(t)}:${K(s)}`}function ht(c,e){return!c||!e?0:c.hours!==e.hours?c.hours<e.hours?-1:1:c.minutes!==e.minutes?c.minutes<e.minutes?-1:1:0}function ts(c,e){if(!c)return null;let t=c.hours*60+c.minutes+e;return t=(t%1440+1440)%1440,{hours:Math.floor(t/60),minutes:t%60}}function ut(c,e){if(!c)return null;try{const t=e instanceof Date?e:new Date,r=new Intl.DateTimeFormat("en-US",{timeZone:c,timeZoneName:"shortOffset"}).formatToParts(t).find(h=>h.type==="timeZoneName");if(!r)return null;let n=r.value;if(n==="GMT"||n==="UTC")return"+00:00";n=n.replace(/^(GMT|UTC)/,"");const a=n.match(/^([+-])(\d{1,2})(?::(\d{2}))?$/);if(!a)return null;const o=a[1],l=a[2].padStart(2,"0"),d=a[3]||"00";return`${o}${l}:${d}`}catch{return null}}function mt(c){if(c==null||c==="")return null;if(typeof c=="object"&&!Array.isArray(c)&&!(c instanceof Date)){const h=c.date?z(c.date):null,u=c.time?W(c.time):null;return h?{date:h,time:u||{hours:0,minutes:0},timezone:c.timezone||null}:null}let e=String(c).trim();const t=e.match(/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})(?::\d{2}(?:\.\d+)?)?(Z|[+-]\d{2}:?\d{2})?$/);if(t){const[,h,u,m,p,f,g]=t;let b=null;return g&&(g==="Z"?b="+00:00":/^[+-]\d{4}$/.test(g)?b=`${g.slice(0,3)}:${g.slice(3)}`:b=g),{date:{y:+h,m:+u,d:+m},time:{hours:+p,minutes:+f},timezone:b}}let s,i;if(e.length>=11&&e.charAt(10)==="T")s=e.slice(0,10),i=e.slice(11);else{const h=e.indexOf(" ");if(h===-1){const u=z(e);return u?{date:u,time:{hours:0,minutes:0},timezone:null}:null}s=e.slice(0,h),i=e.slice(h+1)}const r=z(s);if(!r)return null;const n=i.trim();let a=null,o=n;const l=n.match(/\s+([A-Za-z][A-Za-z_+\-]*\/[A-Za-z][A-Za-z_+\-]*|UTC|GMT)$/);l&&(a=l[1],o=n.slice(0,l.index).trim());const d=W(o);return d?{date:r,time:d,timezone:a}:null}function T(){const c=new Date;return{y:c.getFullYear(),m:c.getMonth()+1,d:c.getDate()}}let ve=null,qe=null,Re=null;function pt(c="en-US",e="short"){if((!c||c==="en-US"||c==="en")&&e==="short")return Oe.slice();if((!c||c==="en-US"||c==="en")&&e==="long")return Ne.slice();if(typeof Intl>"u"||!Intl.DateTimeFormat)return e==="long"?Ne.slice():Oe.slice();if(ve===c+"/"+e&&qe)return qe.slice();const t=new Intl.DateTimeFormat(c,{month:e}),s=[];for(let i=0;i<12;i++)s.push(t.format(new Date(2024,i,15)));return ve=c+"/"+e,qe=s,s.slice()}function ss(c="en-US",e=1,t="short"){if(typeof Intl>"u"||!Intl.DateTimeFormat)return ft(["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],e);const s=c+"/"+e+"/"+t;if(ve===s&&Re)return Re.slice();const i=new Intl.DateTimeFormat(c,{weekday:t}),r=[];for(let a=0;a<7;a++)r.push(i.format(new Date(2024,0,7+a)));const n=ft(r,e);return ve=s,Re=n,n.slice()}function K(c){return c<10?"0"+c:String(c)}function ft(c,e){const t=(e%c.length+c.length)%c.length;return c.slice(t).concat(c.slice(0,t))}class ze extends C{constructor(e={}){const{precision:t="day",mode:s="single",months:i=1,value:r=null,startValue:n=null,endValue:a=null,min:o=null,max:l=null,disabledDates:d=[],firstDay:h=1,locale:u="en-US",excludeDisabledFromRange:m=!1,year:p=null,month:f=null,class:g="",...b}=e;super({tagName:"div",className:`mojo-calendar mojo-calendar-${t} ${g}`.trim(),...b}),this.precision=t,this.mode=s,this.months=Math.max(1,Math.min(2,i|0)),this.firstDay=h,this.locale=u,this.excludeDisabledFromRange=m,this.min=P(o,t)||(o?z(o):null),this.max=P(l,t)||(l?z(l):null),this.disabledDates=(d||[]).map(x=>H(z(x)||null)).filter(Boolean),s==="single"?this.selected=P(r,t):(this.start=P(n,t),this.end=P(a,t),this._anchor=null),this._hover=null,this.view=t;const y=T(),w=(s==="single"?this.selected:this.start||this.end)||y;this.pageY=p!=null?Number(p):w.y??y.y,this.pageM=f!=null?Number(f):w.m??y.m,this._onCellMouseEnter=this._onCellMouseEnter.bind(this),this._onCellMouseLeave=this._onCellMouseLeave.bind(this)}setMin(e){this.min=P(e,this.precision),this._rerender()}setMax(e){this.max=P(e,this.precision),this._rerender()}setValue(e){this.selected=P(e,this.precision),this.selected&&(this.pageY=this.selected.y,this.pageM=this.selected.m||this.pageM),this._rerender()}setRange(e,t){this.start=P(e,this.precision),this.end=P(t,this.precision),this._anchor=null,this._rerender()}getValue(){return this.selected?B(this.selected,this.precision):""}getRange(){return{start:this.start?B(this.start,this.precision):"",end:this.end?B(this.end,this.precision):""}}async renderTemplate(){return""}async onAfterRender(){this._eventsWired||(this._wireEvents(this.element),this._eventsWired=!0),this._renderInto(this.element)}_rerender(){this.element&&this._renderInto(this.element)}_renderInto(e){e.innerHTML="";const t=document.createElement("div");if(t.className=this.months>1&&this.view==="day"?"mojo-calendar-multi":"mojo-calendar-single",this.view==="day"){const s=this.months;for(let i=0;i<s;i++){let r=this.pageY,n=this.pageM+i;for(;n>12;)n-=12,r+=1;t.appendChild(this._buildDayPane(r,n,i===0,i===s-1))}}else this.view==="month"?t.appendChild(this._buildMonthPane(this.pageY)):this.view==="year"&&t.appendChild(this._buildYearPane(this._decadeStart(this.pageY)));e.appendChild(t)}_decadeStart(e){return Math.floor(e/10)*10}_buildDayPane(e,t,s,i){const r=document.createElement("div");return r.className="mojo-calendar-pane",r.appendChild(this._buildHead(this._dayHeadLabel(e,t),"day",s,i,e,t)),r.appendChild(this._buildWeekdayHeader()),r.appendChild(this._buildDayGrid(e,t)),r}_dayHeadLabel(e,t){return{kind:"day",year:e,month:t}}_buildWeekdayHeader(){const e=document.createElement("div");return e.className="mojo-calendar-grid mojo-calendar-grid-day",ss(this.locale,this.firstDay,"short").forEach(t=>{const s=document.createElement("div");s.className="mojo-calendar-weekday",s.textContent=t,e.appendChild(s)}),e}_buildDayGrid(e,t){const s=document.createElement("div");s.className="mojo-calendar-grid mojo-calendar-grid-day";const i=Xt(e,t,1,this.firstDay),r=lt(e,t),n=T();for(let a=0;a<i;a++){const o=document.createElement("div");o.className="mojo-calendar-cell mojo-calendar-cell-blank",s.appendChild(o)}for(let a=1;a<=r;a++){const o={y:e,m:t,d:a},l=document.createElement("button");l.type="button",l.className="mojo-calendar-cell",l.dataset.ymd=H(o),o.y===n.y&&o.m===n.m&&o.d===n.d&&l.classList.add("mojo-calendar-cell-today"),this._isDisabledAt(o,"day")&&(l.classList.add("mojo-calendar-cell-disabled"),l.disabled=!0),this.mode==="range"?this._applyRangeClasses(l,o,"day"):this.selected&&ct(o,this.selected)===0&&l.classList.add("mojo-calendar-cell-selected");const d=document.createElement("span");d.className="mojo-calendar-cell-inner",d.textContent=String(a),l.appendChild(d),s.appendChild(l)}return s}_buildMonthPane(e){const t=document.createElement("div");return t.className="mojo-calendar-pane",t.appendChild(this._buildHead(String(e),"month",!0,!0,e,1)),t.appendChild(this._buildMonthGrid(e)),t}_buildMonthGrid(e){const t=document.createElement("div");t.className="mojo-calendar-grid mojo-calendar-grid-month";const s=pt(this.locale,"short");for(let i=1;i<=12;i++){const r={y:e,m:i},n=document.createElement("button");n.type="button",n.className="mojo-calendar-cell",n.dataset.ym=je(r),this._isDisabledAt(r,"month")&&(n.classList.add("mojo-calendar-cell-disabled"),n.disabled=!0),this.precision==="month"&&this.mode==="range"?this._applyRangeClasses(n,r,"month"):this.precision==="month"&&this.mode==="single"&&this.selected&&dt(r,this.selected)===0&&n.classList.add("mojo-calendar-cell-selected");const a=document.createElement("span");a.className="mojo-calendar-cell-inner",a.textContent=s[i-1],n.appendChild(a),t.appendChild(n)}return t}_buildYearPane(e){const t=document.createElement("div");return t.className="mojo-calendar-pane",t.appendChild(this._buildHead(`${e} – ${e+11}`,"year",!0,!0,e,1)),t.appendChild(this._buildYearGrid(e)),t}_buildYearGrid(e){const t=document.createElement("div");t.className="mojo-calendar-grid mojo-calendar-grid-year";for(let s=0;s<12;s++){const i=e+s,r={y:i},n=document.createElement("button");n.type="button",n.className="mojo-calendar-cell",n.dataset.year=String(i),this._isDisabledAt(r,"year")&&(n.classList.add("mojo-calendar-cell-disabled"),n.disabled=!0),this.precision==="year"&&this.mode==="range"?this._applyRangeClasses(n,r,"year"):this.precision==="year"&&this.mode==="single"&&this.selected&&this.selected.y===i&&n.classList.add("mojo-calendar-cell-selected");const a=document.createElement("span");a.className="mojo-calendar-cell-inner",a.textContent=String(i),n.appendChild(a),t.appendChild(n)}return t}_applyRangeClasses(e,t,s){let i=this.start,r=this.end;if(this._anchor){const o=this._hover||this._anchor,l=U(this._anchor,o,s);i=l<=0?this._anchor:o,r=l<=0?o:this._anchor}if(!i||!r){this._anchor&&U(t,this._anchor,s)===0&&e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-solo");return}const n=U(t,i,s),a=U(t,r,s);n>0&&a<0&&e.classList.add(this._anchor?"mojo-calendar-cell-in-preview":"mojo-calendar-cell-in-range"),n===0&&(e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-start"),U(i,r,s)===0?e.classList.add("mojo-calendar-cell-anchor-solo"):e.classList.add(this._anchor?"mojo-calendar-cell-in-preview":"mojo-calendar-cell-in-range")),a===0&&U(i,r,s)!==0&&(e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-end"),e.classList.add(this._anchor?"mojo-calendar-cell-in-preview":"mojo-calendar-cell-in-range"))}_buildHead(e,t,s,i){const r=document.createElement("div");r.className="mojo-calendar-head";const n=document.createElement("button");if(n.type="button",n.className="mojo-calendar-head-label",n.dataset.level=t,n.dataset.action="zoom-out",typeof e=="string")n.textContent=e;else if(e&&e.kind==="day"){const o=pt(this.locale,"long");n.appendChild(document.createTextNode(`${o[e.month-1]} `));const l=document.createElement("span");l.className="mojo-calendar-year",l.textContent=String(e.year),n.appendChild(l)}r.appendChild(n);const a=document.createElement("div");return a.className="mojo-calendar-nav",s&&a.appendChild(this._navBtn("prev")),i&&a.appendChild(this._navBtn("next")),r.appendChild(a),r}_navBtn(e){const t=document.createElement("button");return t.type="button",t.className="mojo-calendar-nav-btn",t.dataset.action=`nav-${e}`,t.setAttribute("aria-label",e==="prev"?"Previous":"Next"),t.innerHTML=e==="prev"?"‹":"›",t}_wireEvents(e){e.addEventListener("click",t=>this._onClick(t)),e.addEventListener("mouseover",this._onCellMouseEnter),e.addEventListener("mouseleave",this._onCellMouseLeave),e.addEventListener("keydown",t=>this._onKeyDown(t))}_onClick(e){const t=e.target.closest("[data-action], .mojo-calendar-cell");if(!t||t.classList.contains("mojo-calendar-cell-blank")||t.disabled)return;const s=t.dataset.action;if(s==="nav-prev")return this._navigate(-1);if(s==="nav-next")return this._navigate(1);if(s==="zoom-out")return this._zoomOut(t.dataset.level);t.classList.contains("mojo-calendar-cell")&&this._onCellClick(t)}_onCellClick(e){if(this.view==="year"){const t=parseInt(e.dataset.year,10);if(!Number.isFinite(t))return;if(this.precision==="year")return this._commitValue({y:t});this.pageY=t,this.view="month",this.emit("view:change",{view:this.view}),this._rerender();return}if(this.view==="month"){const t=we(e.dataset.ym);if(!t)return;if(this.precision==="month")return this._commitValue(t);this.pageY=t.y,this.pageM=t.m,this.view="day",this.emit("view:change",{view:this.view}),this._rerender();return}if(this.view==="day"){const t=z(e.dataset.ymd);if(!t)return;this._commitValue(t)}}_commitValue(e){if(this.mode==="single"){this.selected=e,this.emit("select",{value:B(e,this.precision),parsed:e}),this._rerender();return}if(!this._anchor){this._anchor=e,this.start=null,this.end=null,this._hover=null,this.emit("range:start",{anchor:B(e,this.precision)}),this._rerender();return}const t=this._anchor,s=e,i=U(t,s,this.precision);this.start=i<=0?t:s,this.end=i<=0?s:t,this._anchor=null,this._hover=null,this.emit("range:select",{start:B(this.start,this.precision),end:B(this.end,this.precision)}),this._rerender()}_onCellMouseEnter(e){if(this.mode!=="range"||!this._anchor)return;const t=e.target.closest(".mojo-calendar-cell");if(!t||t.classList.contains("mojo-calendar-cell-blank")||t.disabled)return;let s=null;this.view==="day"&&t.dataset.ymd?s=z(t.dataset.ymd):this.view==="month"&&t.dataset.ym?s=we(t.dataset.ym):this.view==="year"&&t.dataset.year&&(s={y:parseInt(t.dataset.year,10)}),s&&(this._hover&&U(this._hover,s,this.view)===0||(this._hover=s,this._rerender()))}_onCellMouseLeave(){this.mode!=="range"||!this._anchor||this._hover&&(this._hover=null,this._rerender())}_navigate(e){if(this.view==="day"){const t=ie({y:this.pageY,m:this.pageM},e);this.pageY=t.y,this.pageM=t.m}else this.view==="month"?this.pageY+=e:this.view==="year"&&(this.pageY=this._decadeStart(this.pageY)+e*10);this.emit("navigate",{delta:e}),this._rerender()}_zoomOut(e){if(e==="day"){this.view="month",this.emit("view:change",{view:this.view}),this._rerender();return}e==="month"&&(this.view="year",this.emit("view:change",{view:this.view}),this._rerender())}_onKeyDown(e){const t=e.key;if(t==="Escape"){this._anchor&&(this._anchor=null,this._hover=null,this.emit("range:cancel"),this._rerender(),e.preventDefault());return}if(t==="PageUp"){this._navigate(-1),e.preventDefault();return}if(t==="PageDown"){this._navigate(1),e.preventDefault();return}}_isDisabledAt(e,t){if(this.min&&U(e,this.min,t)<0||this.max&&U(e,this.max,t)>0)return!0;if(t==="day"&&this.disabledDates.length){const s=H(e);if(this.disabledDates.includes(s))return!0}return!1}async onBeforeDestroy(){this.element&&(this.element.removeEventListener("mouseover",this._onCellMouseEnter),this.element.removeEventListener("mouseleave",this._onCellMouseLeave)),await super.onBeforeDestroy()}}class Ce{constructor(e={}){const{anchor:t=null,placement:s="bottom-start",gap:i=6,portal:r=!0,onOutsideClick:n=null,classNames:a=""}=e;this.anchor=t,this.placement=s,this.gap=i,this.portal=r,this.onOutsideClick=n,this.element=document.createElement("div"),this.element.className=`mojo-calendar-popover ${a}`.trim(),this.element.style.position="absolute",this.element.style.zIndex="10000",this.element.setAttribute("role","dialog"),this._open=!1,this._onDocClick=this._onDocClick.bind(this),this._onScroll=this._onScroll.bind(this),this._onResize=this._onResize.bind(this),this._onKey=this._onKey.bind(this)}setAnchor(e){this.anchor=e,this._open&&this._reposition()}setContent(e){this.element.innerHTML="",e&&this.element.appendChild(e)}open(){this._open||(this._open=!0,this.portal&&this.element.parentNode!==document.body&&document.body.appendChild(this.element),this.element.classList.add("is-open"),this._reposition(),setTimeout(()=>{document.addEventListener("mousedown",this._onDocClick,!0),document.addEventListener("keydown",this._onKey,!0),window.addEventListener("scroll",this._onScroll,!0),window.addEventListener("resize",this._onResize)},0))}close(){this._open&&(this._open=!1,this.element.classList.remove("is-open"),document.removeEventListener("mousedown",this._onDocClick,!0),document.removeEventListener("keydown",this._onKey,!0),window.removeEventListener("scroll",this._onScroll,!0),window.removeEventListener("resize",this._onResize),this.portal&&this.element.parentNode===document.body&&document.body.removeChild(this.element))}isOpen(){return this._open}destroy(){this.close(),this.element=null}_onDocClick(e){this.element.contains(e.target)||this.anchor&&this.anchor.contains(e.target)||(typeof this.onOutsideClick=="function"?this.onOutsideClick(e):this.close())}_onKey(e){e.key==="Escape"&&this.close()}_onScroll(){this._open&&this._reposition()}_onResize(){this._open&&this._reposition()}_reposition(){if(!this.anchor)return;const e=this.anchor.getBoundingClientRect(),t=this.element.getBoundingClientRect(),s=window.scrollX||window.pageXOffset||0,i=window.scrollY||window.pageYOffset||0;let r=e.bottom+i+this.gap,n=e.left+s;this.placement==="bottom-end"?n=e.right+s-t.width:this.placement==="top-start"?r=e.top+i-t.height-this.gap:this.placement==="top-end"&&(r=e.top+i-t.height-this.gap,n=e.right+s-t.width);const a=document.documentElement.clientWidth||window.innerWidth;n+t.width>s+a-8&&(n=s+a-t.width-8),n<s+8&&(n=s+8);const o=document.documentElement.clientHeight||window.innerHeight;r-i+t.height>o-8&&e.top-t.height-this.gap>8&&(r=e.top+i-t.height-this.gap),this.element.style.top=`${r}px`,this.element.style.left=`${n}px`}}const gt={day:"MMM DD, YYYY",month:"MMM YYYY",year:"YYYY"};class He extends C{constructor(e={}){const{name:t,value:s="",precision:i="day",format:r=null,displayFormat:n=null,min:a=null,max:o=null,placeholder:l=null,disabled:d=!1,readonly:h=!1,required:u=!1,class:m="",inputClass:p="form-control",inline:f=!1,disabledDates:g=[],firstDay:b=1,lang:y="en-US",autoApply:w=!0,...x}=e;super({tagName:"div",className:`mojo-date-picker mojo-date-picker-${i} ${m}`.trim(),...x}),this.name=t,this.precision=i,this.format=r,this.displayFormat=n||gt[i]||gt.day,this.min=a,this.max=o,this.placeholder=l??this._defaultPlaceholder(i),this.disabled=d,this.readonly=h,this.required=u,this.inputClass=p,this.inline=f,this.disabledDates=g,this.firstDay=b,this.lang=y,this.autoApply=w,this.currentValue=s||"",this._calendar=null,this._popover=null}_defaultPlaceholder(e){return e==="year"?"Select year...":e==="month"?"Select month...":"Select date..."}async renderTemplate(){const e=this._inputId(),t=this._displayText(this.currentValue),s=!this.currentValue;return this.inline?`
|
|
1027
|
+
`,...e}),this.name=e.name||"multiselect",this.label=e.label||"",this.help=e.help||"",this.error=e.error||"",this.required=e.required||!1,this.disabled=e.disabled||!1,this.placeholder=e.placeholder||e.placeHolder||"Select...",this.maxHeight=e.maxHeight||300,this.showSelectedLabels=e.showSelectedLabels!==!1,this.maxLabelsToShow=e.maxLabelsToShow||3,this.options=e.options||[],this.selectedValues=Array.isArray(e.value)?e.value:[],this.buttonText=this.computeButtonText(),this.listView=null}computeButtonText(){const e=this.selectedValues.length;return e===0?this.placeholder||"Select...":this.showSelectedLabels&&e<=this.maxLabelsToShow?this.selectedValues.map(s=>{const i=this.options.find(r=>(typeof r=="string"?r:r.value)===s);return typeof i=="string"?i:i?.label||i?.value||s}).join(", "):`${e} selected`}async onAfterRender(){await super.onAfterRender(),this.createListView()}createListView(){const e=this.element?.querySelector('[data-container="items"]');if(!e)return;const t=this.options.map((s,i)=>{const r=typeof s=="string"?s:s.value,n=typeof s=="string"?s:s.label||s.text||s.value,a=typeof s=="object"?s.disabled:!1;return{id:`${this.name}_${i}`,value:r,label:n,index:i,selected:this.selectedValues.includes(r),disabled:a}});this.listView=new Zt({items:t,maxHeight:this.maxHeight}),this.listView.on("toggle",s=>{this.handleToggle(s)}),this.listView.on("close-dropdown",()=>{this.closeDropdown()}),this.listView.render(!0,e)}closeDropdown(){const e=this.element?.querySelector(".dropdown-toggle");if(e&&window.bootstrap?.Dropdown){const t=window.bootstrap.Dropdown.getInstance(e);t&&t.hide()}}handleToggle(e){const{value:t,selected:s}=e;s?this.selectedValues.includes(t)||this.selectedValues.push(t):this.selectedValues=this.selectedValues.filter(i=>i!==t),this.updateButtonText(),this.emit("change",{value:this.selectedValues,name:this.name})}updateButtonText(){const e=this.element?.querySelector(".multiselect-button-text");if(!e)return;const t=this.selectedValues.length;this.buttonText=this.computeButtonText(),e.textContent=this.buttonText,t===0?e.classList.add("text-muted"):e.classList.remove("text-muted")}getValue(){return this.selectedValues}setValue(e){this.selectedValues=Array.isArray(e)?e:e?[e]:[],this.listView&&this.listView.setValue(this.selectedValues),this.updateButtonText()}setOptions(e){if(this.options=e,this.listView){const t=this.options.map((s,i)=>{const r=typeof s=="string"?s:s.value,n=typeof s=="string"?s:s.label||s.text||s.value,a=typeof s=="object"?s.disabled:!1;return{id:`${this.name}_${i}`,value:r,label:n,index:i,selected:this.selectedValues.includes(r),disabled:a}});this.listView.updateItems(t)}}clear(){this.setValue([])}getFormValue(){return this.getValue()}setFormValue(e){this.setValue(e)}async onBeforeDestroy(){await super.onBeforeDestroy(),this.listView&&this.listView.destroy()}}const Ne=["January","February","March","April","May","June","July","August","September","October","November","December"],Oe=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function at(c){if(c==null||c==="")return null;const e=parseInt(String(c).slice(0,4),10);return Number.isFinite(e)?{y:e}:null}function we(c){if(c==null||c==="")return null;const e=String(c).split("-"),t=parseInt(e[0],10),s=parseInt(e[1],10);return!Number.isFinite(t)||!Number.isFinite(s)||s<1||s>12?null:{y:t,m:s}}function z(c){if(c==null||c==="")return null;if(c instanceof Date&&!isNaN(c.getTime()))return{y:c.getFullYear(),m:c.getMonth()+1,d:c.getDate()};const e=String(c).split("-"),t=parseInt(e[0],10),s=parseInt(e[1],10),i=parseInt(e[2],10);return!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(i)||s<1||s>12||i<1||i>31?null:{y:t,m:s,d:i}}function ot(c){const e=typeof c=="object"?c:at(c);return e?String(e.y):""}function je(c){const e=typeof c=="object"?c:we(c);return e?`${e.y}-${K(e.m)}`:""}function H(c){const e=typeof c=="object"?c:z(c);return e?`${e.y}-${K(e.m)}-${K(e.d)}`:""}function B(c,e){return e==="year"?ot(c):e==="month"?je(c):H(c)}function P(c,e){return e==="year"?at(c):e==="month"?we(c):z(c)}const Qt=/YYYY|YY|MMMM|MMM|MM|M|DD|D/g;function ce(c,e){if(!c)return"";const t=c.y,s=c.m,i=c.d;return String(e).replace(Qt,r=>{switch(r){case"YYYY":return String(t);case"YY":return String(t).slice(-2);case"MMMM":return s?Ne[s-1]:"";case"MMM":return s?Oe[s-1]:"";case"MM":return s?K(s):"";case"M":return s?String(s):"";case"DD":return i?K(i):"";case"D":return i?String(i):"";default:return r}})}function lt(c,e){return new Date(c,e,0).getDate()}function Xt(c,e,t,s=1){return((new Date(c,e-1,t).getDay()-s)%7+7)%7}function ie(c,e){if(!c)return null;let t=c.y,s=c.m+e;for(;s>12;)s-=12,t+=1;for(;s<1;)s+=12,t-=1;if(c.d==null)return{y:t,m:s};const i=lt(t,s);return{y:t,m:s,d:Math.min(c.d,i)}}function ct(c,e){return!c||!e?0:c.y!==e.y?c.y<e.y?-1:1:(c.m||0)!==(e.m||0)?(c.m||0)<(e.m||0)?-1:1:(c.d||0)!==(e.d||0)?(c.d||0)<(e.d||0)?-1:1:0}function dt(c,e){return!c||!e?0:c.y!==e.y?c.y<e.y?-1:1:(c.m||0)!==(e.m||0)?(c.m||0)<(e.m||0)?-1:1:0}function es(c,e){return!c||!e||c.y===e.y?0:c.y<e.y?-1:1}function U(c,e,t){return t==="year"?es(c,e):t==="month"?dt(c,e):ct(c,e)}function W(c){if(c==null||c==="")return null;if(typeof c=="object"&&c!==null){const d=parseInt(c.hours??c.h,10),h=parseInt(c.minutes??c.m,10);return!Number.isFinite(d)||!Number.isFinite(h)||d<0||d>23||h<0||h>59?null:{hours:d,minutes:h}}const e=String(c).trim(),t=e.indexOf(" "),s=t>-1?e.slice(0,t):e,r=(t>-1?e.slice(t+1).trim():"").match(/^(am|pm)$/i)||s.match(/(am|pm)$/i),a=s.replace(/(am|pm)$/i,"").trim().split(":");if(a.length<2)return null;let o=parseInt(a[0],10);const l=parseInt(a[1],10);if(!Number.isFinite(o)||!Number.isFinite(l)||l<0||l>59)return null;if(r){const d=r[1].toLowerCase()==="pm";if(o<1||o>12)return null;o===12?o=d?12:0:d&&(o+=12)}return o<0||o>23?null:{hours:o,minutes:l}}function G(c,e="24h"){if(!c)return"";const t=c.hours,s=c.minutes;if(!Number.isFinite(t)||!Number.isFinite(s))return"";if(e==="12h"){const i=t>=12?"PM":"AM";let r=t%12;return r===0&&(r=12),`${r}:${K(s)} ${i}`}return`${K(t)}:${K(s)}`}function ht(c,e){return!c||!e?0:c.hours!==e.hours?c.hours<e.hours?-1:1:c.minutes!==e.minutes?c.minutes<e.minutes?-1:1:0}function ts(c,e){if(!c)return null;let t=c.hours*60+c.minutes+e;return t=(t%1440+1440)%1440,{hours:Math.floor(t/60),minutes:t%60}}function ut(c,e){if(!c)return null;try{const t=e instanceof Date?e:new Date,r=new Intl.DateTimeFormat("en-US",{timeZone:c,timeZoneName:"shortOffset"}).formatToParts(t).find(h=>h.type==="timeZoneName");if(!r)return null;let n=r.value;if(n==="GMT"||n==="UTC")return"+00:00";n=n.replace(/^(GMT|UTC)/,"");const a=n.match(/^([+-])(\d{1,2})(?::(\d{2}))?$/);if(!a)return null;const o=a[1],l=a[2].padStart(2,"0"),d=a[3]||"00";return`${o}${l}:${d}`}catch{return null}}function mt(c){if(c==null||c==="")return null;if(typeof c=="object"&&!Array.isArray(c)&&!(c instanceof Date)){const h=c.date?z(c.date):null,u=c.time?W(c.time):null;return h?{date:h,time:u||{hours:0,minutes:0},timezone:c.timezone||null}:null}let e=String(c).trim();const t=e.match(/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})(?::\d{2}(?:\.\d+)?)?(Z|[+-]\d{2}:?\d{2})?$/);if(t){const[,h,u,m,p,f,g]=t;let b=null;return g&&(g==="Z"?b="+00:00":/^[+-]\d{4}$/.test(g)?b=`${g.slice(0,3)}:${g.slice(3)}`:b=g),{date:{y:+h,m:+u,d:+m},time:{hours:+p,minutes:+f},timezone:b}}let s,i;if(e.length>=11&&e.charAt(10)==="T")s=e.slice(0,10),i=e.slice(11);else{const h=e.indexOf(" ");if(h===-1){const u=z(e);return u?{date:u,time:{hours:0,minutes:0},timezone:null}:null}s=e.slice(0,h),i=e.slice(h+1)}const r=z(s);if(!r)return null;const n=i.trim();let a=null,o=n;const l=n.match(/\s+([A-Za-z][A-Za-z_+\-]*\/[A-Za-z][A-Za-z_+\-]*|UTC|GMT)$/);l&&(a=l[1],o=n.slice(0,l.index).trim());const d=W(o);return d?{date:r,time:d,timezone:a}:null}function T(){const c=new Date;return{y:c.getFullYear(),m:c.getMonth()+1,d:c.getDate()}}let ve=null,Re=null,qe=null;function pt(c="en-US",e="short"){if((!c||c==="en-US"||c==="en")&&e==="short")return Oe.slice();if((!c||c==="en-US"||c==="en")&&e==="long")return Ne.slice();if(typeof Intl>"u"||!Intl.DateTimeFormat)return e==="long"?Ne.slice():Oe.slice();if(ve===c+"/"+e&&Re)return Re.slice();const t=new Intl.DateTimeFormat(c,{month:e}),s=[];for(let i=0;i<12;i++)s.push(t.format(new Date(2024,i,15)));return ve=c+"/"+e,Re=s,s.slice()}function ss(c="en-US",e=1,t="short"){if(typeof Intl>"u"||!Intl.DateTimeFormat)return ft(["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],e);const s=c+"/"+e+"/"+t;if(ve===s&&qe)return qe.slice();const i=new Intl.DateTimeFormat(c,{weekday:t}),r=[];for(let a=0;a<7;a++)r.push(i.format(new Date(2024,0,7+a)));const n=ft(r,e);return ve=s,qe=n,n.slice()}function K(c){return c<10?"0"+c:String(c)}function ft(c,e){const t=(e%c.length+c.length)%c.length;return c.slice(t).concat(c.slice(0,t))}class ze extends C{constructor(e={}){const{precision:t="day",mode:s="single",months:i=1,value:r=null,startValue:n=null,endValue:a=null,min:o=null,max:l=null,disabledDates:d=[],firstDay:h=1,locale:u="en-US",excludeDisabledFromRange:m=!1,year:p=null,month:f=null,class:g="",...b}=e;super({tagName:"div",className:`mojo-calendar mojo-calendar-${t} ${g}`.trim(),...b}),this.precision=t,this.mode=s,this.months=Math.max(1,Math.min(2,i|0)),this.firstDay=h,this.locale=u,this.excludeDisabledFromRange=m,this.min=P(o,t)||(o?z(o):null),this.max=P(l,t)||(l?z(l):null),this.disabledDates=(d||[]).map(x=>H(z(x)||null)).filter(Boolean),s==="single"?this.selected=P(r,t):(this.start=P(n,t),this.end=P(a,t),this._anchor=null),this._hover=null,this.view=t;const y=T(),w=(s==="single"?this.selected:this.start||this.end)||y;this.pageY=p!=null?Number(p):w.y??y.y,this.pageM=f!=null?Number(f):w.m??y.m,this._onCellMouseEnter=this._onCellMouseEnter.bind(this),this._onCellMouseLeave=this._onCellMouseLeave.bind(this)}setMin(e){this.min=P(e,this.precision),this._rerender()}setMax(e){this.max=P(e,this.precision),this._rerender()}setValue(e){this.selected=P(e,this.precision),this.selected&&(this.pageY=this.selected.y,this.pageM=this.selected.m||this.pageM),this._rerender()}setRange(e,t){this.start=P(e,this.precision),this.end=P(t,this.precision),this._anchor=null,this._rerender()}getValue(){return this.selected?B(this.selected,this.precision):""}getRange(){return{start:this.start?B(this.start,this.precision):"",end:this.end?B(this.end,this.precision):""}}async renderTemplate(){return""}async onAfterRender(){this._eventsWired||(this._wireEvents(this.element),this._eventsWired=!0),this._renderInto(this.element)}_rerender(){this.element&&this._renderInto(this.element)}_renderInto(e){e.innerHTML="";const t=document.createElement("div");if(t.className=this.months>1&&this.view==="day"?"mojo-calendar-multi":"mojo-calendar-single",this.view==="day"){const s=this.months;for(let i=0;i<s;i++){let r=this.pageY,n=this.pageM+i;for(;n>12;)n-=12,r+=1;t.appendChild(this._buildDayPane(r,n,i===0,i===s-1))}}else this.view==="month"?t.appendChild(this._buildMonthPane(this.pageY)):this.view==="year"&&t.appendChild(this._buildYearPane(this._decadeStart(this.pageY)));e.appendChild(t)}_decadeStart(e){return Math.floor(e/10)*10}_buildDayPane(e,t,s,i){const r=document.createElement("div");return r.className="mojo-calendar-pane",r.appendChild(this._buildHead(this._dayHeadLabel(e,t),"day",s,i,e,t)),r.appendChild(this._buildWeekdayHeader()),r.appendChild(this._buildDayGrid(e,t)),r}_dayHeadLabel(e,t){return{kind:"day",year:e,month:t}}_buildWeekdayHeader(){const e=document.createElement("div");return e.className="mojo-calendar-grid mojo-calendar-grid-day",ss(this.locale,this.firstDay,"short").forEach(t=>{const s=document.createElement("div");s.className="mojo-calendar-weekday",s.textContent=t,e.appendChild(s)}),e}_buildDayGrid(e,t){const s=document.createElement("div");s.className="mojo-calendar-grid mojo-calendar-grid-day";const i=Xt(e,t,1,this.firstDay),r=lt(e,t),n=T();for(let a=0;a<i;a++){const o=document.createElement("div");o.className="mojo-calendar-cell mojo-calendar-cell-blank",s.appendChild(o)}for(let a=1;a<=r;a++){const o={y:e,m:t,d:a},l=document.createElement("button");l.type="button",l.className="mojo-calendar-cell",l.dataset.ymd=H(o),o.y===n.y&&o.m===n.m&&o.d===n.d&&l.classList.add("mojo-calendar-cell-today"),this._isDisabledAt(o,"day")&&(l.classList.add("mojo-calendar-cell-disabled"),l.disabled=!0),this.mode==="range"?this._applyRangeClasses(l,o,"day"):this.selected&&ct(o,this.selected)===0&&l.classList.add("mojo-calendar-cell-selected");const d=document.createElement("span");d.className="mojo-calendar-cell-inner",d.textContent=String(a),l.appendChild(d),s.appendChild(l)}return s}_buildMonthPane(e){const t=document.createElement("div");return t.className="mojo-calendar-pane",t.appendChild(this._buildHead(String(e),"month",!0,!0,e,1)),t.appendChild(this._buildMonthGrid(e)),t}_buildMonthGrid(e){const t=document.createElement("div");t.className="mojo-calendar-grid mojo-calendar-grid-month";const s=pt(this.locale,"short");for(let i=1;i<=12;i++){const r={y:e,m:i},n=document.createElement("button");n.type="button",n.className="mojo-calendar-cell",n.dataset.ym=je(r),this._isDisabledAt(r,"month")&&(n.classList.add("mojo-calendar-cell-disabled"),n.disabled=!0),this.precision==="month"&&this.mode==="range"?this._applyRangeClasses(n,r,"month"):this.precision==="month"&&this.mode==="single"&&this.selected&&dt(r,this.selected)===0&&n.classList.add("mojo-calendar-cell-selected");const a=document.createElement("span");a.className="mojo-calendar-cell-inner",a.textContent=s[i-1],n.appendChild(a),t.appendChild(n)}return t}_buildYearPane(e){const t=document.createElement("div");return t.className="mojo-calendar-pane",t.appendChild(this._buildHead(`${e} – ${e+11}`,"year",!0,!0,e,1)),t.appendChild(this._buildYearGrid(e)),t}_buildYearGrid(e){const t=document.createElement("div");t.className="mojo-calendar-grid mojo-calendar-grid-year";for(let s=0;s<12;s++){const i=e+s,r={y:i},n=document.createElement("button");n.type="button",n.className="mojo-calendar-cell",n.dataset.year=String(i),this._isDisabledAt(r,"year")&&(n.classList.add("mojo-calendar-cell-disabled"),n.disabled=!0),this.precision==="year"&&this.mode==="range"?this._applyRangeClasses(n,r,"year"):this.precision==="year"&&this.mode==="single"&&this.selected&&this.selected.y===i&&n.classList.add("mojo-calendar-cell-selected");const a=document.createElement("span");a.className="mojo-calendar-cell-inner",a.textContent=String(i),n.appendChild(a),t.appendChild(n)}return t}_applyRangeClasses(e,t,s){let i=this.start,r=this.end;if(this._anchor){const o=this._hover||this._anchor,l=U(this._anchor,o,s);i=l<=0?this._anchor:o,r=l<=0?o:this._anchor}if(!i||!r){this._anchor&&U(t,this._anchor,s)===0&&e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-solo");return}const n=U(t,i,s),a=U(t,r,s);n>0&&a<0&&e.classList.add(this._anchor?"mojo-calendar-cell-in-preview":"mojo-calendar-cell-in-range"),n===0&&(e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-start"),U(i,r,s)===0?e.classList.add("mojo-calendar-cell-anchor-solo"):e.classList.add(this._anchor?"mojo-calendar-cell-in-preview":"mojo-calendar-cell-in-range")),a===0&&U(i,r,s)!==0&&(e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-end"),e.classList.add(this._anchor?"mojo-calendar-cell-in-preview":"mojo-calendar-cell-in-range"))}_buildHead(e,t,s,i){const r=document.createElement("div");r.className="mojo-calendar-head";const n=document.createElement("button");if(n.type="button",n.className="mojo-calendar-head-label",n.dataset.level=t,n.dataset.action="zoom-out",typeof e=="string")n.textContent=e;else if(e&&e.kind==="day"){const o=pt(this.locale,"long");n.appendChild(document.createTextNode(`${o[e.month-1]} `));const l=document.createElement("span");l.className="mojo-calendar-year",l.textContent=String(e.year),n.appendChild(l)}r.appendChild(n);const a=document.createElement("div");return a.className="mojo-calendar-nav",s&&a.appendChild(this._navBtn("prev")),i&&a.appendChild(this._navBtn("next")),r.appendChild(a),r}_navBtn(e){const t=document.createElement("button");return t.type="button",t.className="mojo-calendar-nav-btn",t.dataset.action=`nav-${e}`,t.setAttribute("aria-label",e==="prev"?"Previous":"Next"),t.innerHTML=e==="prev"?"‹":"›",t}_wireEvents(e){e.addEventListener("click",t=>this._onClick(t)),e.addEventListener("mouseover",this._onCellMouseEnter),e.addEventListener("mouseleave",this._onCellMouseLeave),e.addEventListener("keydown",t=>this._onKeyDown(t))}_onClick(e){const t=e.target.closest("[data-action], .mojo-calendar-cell");if(!t||t.classList.contains("mojo-calendar-cell-blank")||t.disabled)return;const s=t.dataset.action;if(s==="nav-prev")return this._navigate(-1);if(s==="nav-next")return this._navigate(1);if(s==="zoom-out")return this._zoomOut(t.dataset.level);t.classList.contains("mojo-calendar-cell")&&this._onCellClick(t)}_onCellClick(e){if(this.view==="year"){const t=parseInt(e.dataset.year,10);if(!Number.isFinite(t))return;if(this.precision==="year")return this._commitValue({y:t});this.pageY=t,this.view="month",this.emit("view:change",{view:this.view}),this._rerender();return}if(this.view==="month"){const t=we(e.dataset.ym);if(!t)return;if(this.precision==="month")return this._commitValue(t);this.pageY=t.y,this.pageM=t.m,this.view="day",this.emit("view:change",{view:this.view}),this._rerender();return}if(this.view==="day"){const t=z(e.dataset.ymd);if(!t)return;this._commitValue(t)}}_commitValue(e){if(this.mode==="single"){this.selected=e,this.emit("select",{value:B(e,this.precision),parsed:e}),this._rerender();return}if(!this._anchor){this._anchor=e,this.start=null,this.end=null,this._hover=null,this.emit("range:start",{anchor:B(e,this.precision)}),this._rerender();return}const t=this._anchor,s=e,i=U(t,s,this.precision);this.start=i<=0?t:s,this.end=i<=0?s:t,this._anchor=null,this._hover=null,this.emit("range:select",{start:B(this.start,this.precision),end:B(this.end,this.precision)}),this._rerender()}_onCellMouseEnter(e){if(this.mode!=="range"||!this._anchor)return;const t=e.target.closest(".mojo-calendar-cell");if(!t||t.classList.contains("mojo-calendar-cell-blank")||t.disabled)return;let s=null;this.view==="day"&&t.dataset.ymd?s=z(t.dataset.ymd):this.view==="month"&&t.dataset.ym?s=we(t.dataset.ym):this.view==="year"&&t.dataset.year&&(s={y:parseInt(t.dataset.year,10)}),s&&(this._hover&&U(this._hover,s,this.view)===0||(this._hover=s,this._rerender()))}_onCellMouseLeave(){this.mode!=="range"||!this._anchor||this._hover&&(this._hover=null,this._rerender())}_navigate(e){if(this.view==="day"){const t=ie({y:this.pageY,m:this.pageM},e);this.pageY=t.y,this.pageM=t.m}else this.view==="month"?this.pageY+=e:this.view==="year"&&(this.pageY=this._decadeStart(this.pageY)+e*10);this.emit("navigate",{delta:e}),this._rerender()}_zoomOut(e){if(e==="day"){this.view="month",this.emit("view:change",{view:this.view}),this._rerender();return}e==="month"&&(this.view="year",this.emit("view:change",{view:this.view}),this._rerender())}_onKeyDown(e){const t=e.key;if(t==="Escape"){this._anchor&&(this._anchor=null,this._hover=null,this.emit("range:cancel"),this._rerender(),e.preventDefault());return}if(t==="PageUp"){this._navigate(-1),e.preventDefault();return}if(t==="PageDown"){this._navigate(1),e.preventDefault();return}}_isDisabledAt(e,t){if(this.min&&U(e,this.min,t)<0||this.max&&U(e,this.max,t)>0)return!0;if(t==="day"&&this.disabledDates.length){const s=H(e);if(this.disabledDates.includes(s))return!0}return!1}async onBeforeDestroy(){this.element&&(this.element.removeEventListener("mouseover",this._onCellMouseEnter),this.element.removeEventListener("mouseleave",this._onCellMouseLeave)),await super.onBeforeDestroy()}}class Ce{constructor(e={}){const{anchor:t=null,placement:s="bottom-start",gap:i=6,portal:r=!0,onOutsideClick:n=null,classNames:a=""}=e;this.anchor=t,this.placement=s,this.gap=i,this.portal=r,this.onOutsideClick=n,this.element=document.createElement("div"),this.element.className=`mojo-calendar-popover ${a}`.trim(),this.element.style.position="absolute",this.element.style.zIndex="10000",this.element.setAttribute("role","dialog"),this._open=!1,this._onDocClick=this._onDocClick.bind(this),this._onScroll=this._onScroll.bind(this),this._onResize=this._onResize.bind(this),this._onKey=this._onKey.bind(this)}setAnchor(e){this.anchor=e,this._open&&this._reposition()}setContent(e){this.element.innerHTML="",e&&this.element.appendChild(e)}open(){this._open||(this._open=!0,this.portal&&this.element.parentNode!==document.body&&document.body.appendChild(this.element),this.element.classList.add("is-open"),this._reposition(),setTimeout(()=>{document.addEventListener("mousedown",this._onDocClick,!0),document.addEventListener("keydown",this._onKey,!0),window.addEventListener("scroll",this._onScroll,!0),window.addEventListener("resize",this._onResize)},0))}close(){this._open&&(this._open=!1,this.element.classList.remove("is-open"),document.removeEventListener("mousedown",this._onDocClick,!0),document.removeEventListener("keydown",this._onKey,!0),window.removeEventListener("scroll",this._onScroll,!0),window.removeEventListener("resize",this._onResize),this.portal&&this.element.parentNode===document.body&&document.body.removeChild(this.element))}isOpen(){return this._open}destroy(){this.close(),this.element=null}_onDocClick(e){this.element.contains(e.target)||this.anchor&&this.anchor.contains(e.target)||(typeof this.onOutsideClick=="function"?this.onOutsideClick(e):this.close())}_onKey(e){e.key==="Escape"&&this.close()}_onScroll(){this._open&&this._reposition()}_onResize(){this._open&&this._reposition()}_reposition(){if(!this.anchor)return;const e=this.anchor.getBoundingClientRect(),t=this.element.getBoundingClientRect(),s=window.scrollX||window.pageXOffset||0,i=window.scrollY||window.pageYOffset||0;let r=e.bottom+i+this.gap,n=e.left+s;this.placement==="bottom-end"?n=e.right+s-t.width:this.placement==="top-start"?r=e.top+i-t.height-this.gap:this.placement==="top-end"&&(r=e.top+i-t.height-this.gap,n=e.right+s-t.width);const a=document.documentElement.clientWidth||window.innerWidth;n+t.width>s+a-8&&(n=s+a-t.width-8),n<s+8&&(n=s+8);const o=document.documentElement.clientHeight||window.innerHeight;r-i+t.height>o-8&&e.top-t.height-this.gap>8&&(r=e.top+i-t.height-this.gap),this.element.style.top=`${r}px`,this.element.style.left=`${n}px`}}const gt={day:"MMM DD, YYYY",month:"MMM YYYY",year:"YYYY"};class He extends C{constructor(e={}){const{name:t,value:s="",precision:i="day",format:r=null,displayFormat:n=null,min:a=null,max:o=null,placeholder:l=null,disabled:d=!1,readonly:h=!1,required:u=!1,class:m="",inputClass:p="form-control",inline:f=!1,disabledDates:g=[],firstDay:b=1,lang:y="en-US",autoApply:w=!0,...x}=e;super({tagName:"div",className:`mojo-date-picker mojo-date-picker-${i} ${m}`.trim(),...x}),this.name=t,this.precision=i,this.format=r,this.displayFormat=n||gt[i]||gt.day,this.min=a,this.max=o,this.placeholder=l??this._defaultPlaceholder(i),this.disabled=d,this.readonly=h,this.required=u,this.inputClass=p,this.inline=f,this.disabledDates=g,this.firstDay=b,this.lang=y,this.autoApply=w,this.currentValue=s||"",this._calendar=null,this._popover=null}_defaultPlaceholder(e){return e==="year"?"Select year...":e==="month"?"Select month...":"Select date..."}async renderTemplate(){const e=this._inputId(),t=this._displayText(this.currentValue),s=!this.currentValue;return this.inline?`
|
|
1028
1028
|
<input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(this.currentValue)}" data-hidden-value />
|
|
1029
1029
|
<div data-cal-host class="mojo-date-picker-inline${this.hasError()?" is-invalid":""}"></div>
|
|
1030
1030
|
`:`
|
|
@@ -1267,7 +1267,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
|
|
|
1267
1267
|
</div>
|
|
1268
1268
|
</div>
|
|
1269
1269
|
</td>
|
|
1270
|
-
`),this.columns.forEach((t,s)=>{const i=t.class||t.className||"",r=this.getResponsiveClasses(t.visibility),n=t.editable?"editable-cell":"",a=this.tableView&&this.tableView.getAlignClass?this.tableView.getAlignClass(t.align):"",o=[i,r,n,a].filter(h=>h).join(" "),l=this.buildCellTemplate(t,s);let d=t.action;!d&&t.editable?d="edit-cell":!d&&this.tableView.rowAction&&(d=this.tableView.rowAction),d?e+=`<td class="${o}" data-action="${d}" data-column="${t.key}">${l}</td>`:e+=`<td class="${o}" data-column="${t.key}">${l}</td>`}),this.actions?e+=this.buildActionsTemplate():this.contextMenu&&(e+=this.buildContextMenuTemplate()),e}buildCellTemplate(e,t=0){const s=`model.${e.key}`,i=e.formatter||e.format;if(i){if(typeof i=="string")return
|
|
1270
|
+
`),this.columns.forEach((t,s)=>{const i=t.class||t.className||"",r=this.getResponsiveClasses(t.visibility),n=t.editable?"editable-cell":"",a=this.tableView&&this.tableView.getAlignClass?this.tableView.getAlignClass(t.align):"",o=[i,r,n,a].filter(h=>h).join(" "),l=this.buildCellTemplate(t,s);let d=t.action;!d&&t.editable?d="edit-cell":!d&&this.tableView.rowAction&&(d=this.tableView.rowAction),d?e+=`<td class="${o}" data-action="${d}" data-column="${t.key}">${l}</td>`:e+=`<td class="${o}" data-column="${t.key}">${l}</td>`}),this.actions?e+=this.buildActionsTemplate():this.contextMenu&&(e+=this.buildContextMenuTemplate()),e}buildCellTemplate(e,t=0){const s=`model.${e.key}`,i=e.formatter||e.format,r=e.editable?` class="cell-content" data-field="${e.key}"`:"";if(i){if(typeof i=="string")return e.editable?`<span${r}>{{{${s}|${i}}}}</span>`:`{{{${s}|${i}}}}`;if(typeof i=="function"){const n=e.editable?"cell-content":"",a=e.editable?` data-field="${e.key}"`:"";return`<span class="${n}" data-formatter="${e.key}" data-formatter-id="${t}"${a}>{{${s}}}</span>`}}return e.template?e.editable?`<span${r}>${e.template}</span>`:e.template:e.editable?`<span${r}>{{{${s}}}}</span>`:`{{{${s}}}}`}buildActionsTemplate(){return!this.actions||this.actions.length===0?"":`<td><div class="btn-group btn-group-sm">${this.actions.map(t=>{if(typeof t=="string")switch(t){case"view":return`
|
|
1271
1271
|
<button class="btn btn-sm btn-outline-primary"
|
|
1272
1272
|
data-action="view"
|
|
1273
1273
|
title="View">
|