web-mojo 2.4.15 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/dist/admin-models.es.js +1 -1
  3. package/dist/admin.cjs.js +1 -1
  4. package/dist/admin.cjs.js.map +1 -1
  5. package/dist/admin.css +264 -0
  6. package/dist/admin.es.js +1 -1
  7. package/dist/admin.es.js.map +1 -1
  8. package/dist/auth.cjs.js +1 -1
  9. package/dist/auth.es.js +1 -1
  10. package/dist/charts.cjs.js +1 -1
  11. package/dist/charts.es.js +1 -1
  12. package/dist/chunks/{ChatView-BGxrltgS.js → ChatView-BPJGwNB-.js} +2 -2
  13. package/dist/chunks/{ChatView-BGxrltgS.js.map → ChatView-BPJGwNB-.js.map} +1 -1
  14. package/dist/chunks/{ChatView-DDuK43lX.js → ChatView-CmYaZjsO.js} +2 -2
  15. package/dist/chunks/{ChatView-DDuK43lX.js.map → ChatView-CmYaZjsO.js.map} +1 -1
  16. package/dist/chunks/{ListView-DnxrGclm.js → ListView-CdKbQdEF.js} +2 -2
  17. package/dist/chunks/ListView-CdKbQdEF.js.map +1 -0
  18. package/dist/chunks/{ListView-KWvdL4OZ.js → ListView-DbLe2wcm.js} +2 -2
  19. package/dist/chunks/ListView-DbLe2wcm.js.map +1 -0
  20. package/dist/chunks/{Passkeys-CAkLWzxp.js → Passkeys-1N9xo02Z.js} +2 -2
  21. package/dist/chunks/{Passkeys-CAkLWzxp.js.map → Passkeys-1N9xo02Z.js.map} +1 -1
  22. package/dist/chunks/{Passkeys-Dmq0wWpl.js → Passkeys-BDQrfTmM.js} +2 -2
  23. package/dist/chunks/{Passkeys-Dmq0wWpl.js.map → Passkeys-BDQrfTmM.js.map} +1 -1
  24. package/dist/chunks/{UserProfileView-DnP_6G6d.js → UserProfileView-C1N4iFlc.js} +2 -2
  25. package/dist/chunks/{UserProfileView-DnP_6G6d.js.map → UserProfileView-C1N4iFlc.js.map} +1 -1
  26. package/dist/chunks/{UserProfileView-DrsRZ-bF.js → UserProfileView-a-V2S8Ni.js} +2 -2
  27. package/dist/chunks/{UserProfileView-DrsRZ-bF.js.map → UserProfileView-a-V2S8Ni.js.map} +1 -1
  28. package/dist/chunks/{admin-models-bi4jz-nJ.js → admin-models-D5jSlGb1.js} +2 -2
  29. package/dist/chunks/{admin-models-bi4jz-nJ.js.map → admin-models-D5jSlGb1.js.map} +1 -1
  30. package/dist/chunks/{index-CgBfI613.js → index-C413ywKj.js} +2 -2
  31. package/dist/chunks/{index-CgBfI613.js.map → index-C413ywKj.js.map} +1 -1
  32. package/dist/chunks/{index-Cq2rbYiD.js → index-CaVoKADD.js} +2 -2
  33. package/dist/chunks/{index-Cq2rbYiD.js.map → index-CaVoKADD.js.map} +1 -1
  34. package/dist/chunks/version-CF2xCjqJ.js +2 -0
  35. package/dist/chunks/version-CF2xCjqJ.js.map +1 -0
  36. package/dist/chunks/version-Cndfrmgr.js +2 -0
  37. package/dist/chunks/version-Cndfrmgr.js.map +1 -0
  38. package/dist/css/web-mojo.css +1 -1
  39. package/dist/docit.cjs.js +1 -1
  40. package/dist/docit.es.js +1 -1
  41. package/dist/index.cjs.js +1 -1
  42. package/dist/index.es.js +1 -1
  43. package/dist/lightbox.cjs.js +1 -1
  44. package/dist/lightbox.es.js +1 -1
  45. package/dist/timeline.cjs.js +1 -1
  46. package/dist/timeline.es.js +1 -1
  47. package/dist/user-profile.cjs.js +1 -1
  48. package/dist/user-profile.es.js +1 -1
  49. package/dist/web-mojo.lite.iife.js +2 -0
  50. package/dist/web-mojo.lite.iife.js.map +1 -1
  51. package/dist/web-mojo.lite.iife.min.js +18 -18
  52. package/dist/web-mojo.lite.iife.min.js.map +1 -1
  53. package/package.json +1 -1
  54. package/dist/chunks/ListView-DnxrGclm.js.map +0 -1
  55. package/dist/chunks/ListView-KWvdL4OZ.js.map +0 -1
  56. package/dist/chunks/version-BrCGCscn.js +0 -2
  57. package/dist/chunks/version-BrCGCscn.js.map +0 -1
  58. package/dist/chunks/version-DrH-7xNr.js +0 -2
  59. package/dist/chunks/version-DrH-7xNr.js.map +0 -1
@@ -11,8 +11,8 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
11
11
  ${r?`<span class="font-monospace">${i}</span>`:""}
12
12
  ${n}
13
13
  </span>
14
- `}nl2br(e){return e==null?"":this.escapeHtml(String(e)).replace(/\r\n|\r|\n/g,"<br>")}code(e,t=""){if(e==null)return"";const s=t?`language-${this.escapeHtml(String(t))}`:"",i=this.escapeHtml(String(e));return`<pre class="bg-light p-2 rounded border"><code class="${s}">${i}</code></pre>`}register(e,t){if(typeof t!="function")throw new Error(`Formatter must be a function, got ${typeof t}`);return this.formatters.set(e.toLowerCase(),t),this}apply(e,t,...s){if(Array.isArray(t)&&t.every(i=>typeof i=="string"))return t.reduce((i,r)=>this.apply(r,i,...s),e);try{const i=this.formatters.get(e.toLowerCase());return i?i(t,...s):(console.warn(`Formatter '${e}' not found`),t)}catch(i){return console.error(`Error in formatter '${e}':`,i),t}}pipe(e,t,s=null){return t?this.parsePipeString(t,s).reduce((r,n)=>this.apply(n.name,r,...n.args),e):e}parsePipeString(e,t=null){const s=[],i=e.split("|").map(r=>r.trim());for(const r of i){const n=this.parseFormatter(r,t);n&&s.push(n)}return s}parseFormatter(e,t=null){const s=e.match(/^([a-zA-Z_]\w*)\s*\((.*)\)$/);if(s){const[,r,n]=s,a=n?this.parseArguments(n,t):[];return{name:r,args:a}}const i=e.match(/^([a-zA-Z_]\w*)(?::(.+))?$/);if(i){const[,r,n]=i,a=n?this.parseColonArguments(n,t):[];return{name:r,args:a}}return null}parseArguments(e,t=null){const s=[];let i="",r=!1,n=null,a=0;for(let o=0;o<e.length;o++){const l=e[o];!r&&(l==='"'||l==="'")?(r=!0,n=l,i+=l):r&&l===n&&e[o-1]!=="\\"?(r=!1,n=null,i+=l):!r&&l==="{"?(a++,i+=l):!r&&l==="}"?(a--,i+=l):!r&&a===0&&l===","?(s.push(this.parseValue(i.trim(),t)),i=""):i+=l}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseColonArguments(e,t=null){const s=[];let i="",r=!1,n=null;for(let a=0;a<e.length;a++){const o=e[a];!r&&(o==='"'||o==="'")?(r=!0,n=o,i+=o):r&&o===n&&e[a-1]!=="\\"?(r=!1,n=null,i+=o):!r&&o===":"?(s.push(this.parseValue(i.trim(),t)),i=""):i+=o}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseValue(e,t=null){if(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);if(e==="true")return!0;if(e==="false")return!1;if(e==="null")return null;if(e!=="undefined"){if(!isNaN(e)&&e!=="")return Number(e);if(e.startsWith("{")&&e.endsWith("}"))try{return JSON.parse(e)}catch{}if(t&&this.isIdentifier(e)){if(!e.includes(".")&&Object.prototype.hasOwnProperty.call(t,e))return t[e];if(t.get&&typeof t.get=="function"){const s=t.get(e);if(s!==void 0)return s}if(t.getContextValue&&typeof t.getContextValue=="function"){const s=t.getContextValue(e);if(s!==void 0)return s}if(e.includes(".")){const s=window.MOJOUtils||(typeof require<"u"?require("./MOJOUtils.js").default:null);if(s){const i=s.getNestedValue(t,e);if(i!==void 0)return i}}}return e}}isIdentifier(e){return/^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/.test(e)}date(e,t="MM/DD/YYYY"){if(!e)return"";e=this.normalizeEpoch(e);let s;if(e instanceof Date)s=e;else if(typeof e=="string")if(/^\d{4}-\d{2}-\d{2}$/.test(e)){const[a,o,l]=e.split("-").map(Number);s=new Date(a,o-1,l)}else s=new Date(e);else s=new Date(e);if(isNaN(s.getTime()))return String(e);const i={YYYY:s.getFullYear(),YY:String(s.getFullYear()).slice(-2),MMMM:s.toLocaleDateString("en-US",{month:"long"}),MMM:s.toLocaleDateString("en-US",{month:"short"}),MM:String(s.getMonth()+1).padStart(2,"0"),M:s.getMonth()+1,dddd:s.toLocaleDateString("en-US",{weekday:"long"}),ddd:s.toLocaleDateString("en-US",{weekday:"short"}),DD:String(s.getDate()).padStart(2,"0"),D:s.getDate()};let r=t;const n=new RegExp(`(${Object.keys(i).join("|")})`,"g");return r=r.replace(n,a=>i[a]||a),r}time(e,t="HH:mm:ss"){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const i=s.getHours(),r={HH:String(i).padStart(2,"0"),H:i,hh:String(i%12||12).padStart(2,"0"),h:i%12||12,mm:String(s.getMinutes()).padStart(2,"0"),m:s.getMinutes(),ss:String(s.getSeconds()).padStart(2,"0"),s:s.getSeconds(),A:i>=12?"PM":"AM",a:i>=12?"pm":"am"};let n=t;const a=Object.keys(r).sort((o,l)=>l.length-o.length);for(const o of a)n=n.replace(new RegExp(o,"g"),r[o]);return n}datetime(e,t="MM/DD/YYYY",s="HH:mm:ss"){e=this.normalizeEpoch(e);const i=this.date(e,t),r=this.time(e,s);return i&&r?`${i} ${r}`:""}datetime_tz(e,t="MM/DD/YYYY",s="HH:mm:ss",i={}){if(!e)return"";e=this.normalizeEpoch(e);const r=e instanceof Date?e:new Date(e);if(isNaN(r.getTime()))return String(e);const n=i&&i.locale||"en-US",a=i&&i.timeZone?i.timeZone:void 0,o=()=>{let k="";try{const te=new Intl.DateTimeFormat(n,{hour:"2-digit",minute:"2-digit",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(z=>z.type==="timeZoneName");if(k=te?te.value:"",k&&/^GMT[+-]/i.test(k))try{const se=new Intl.DateTimeFormat(n,{timeStyle:"short",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(Fs=>Fs.type==="timeZoneName");se&&se.value&&!/^GMT[+-]/i.test(se.value)&&(k=se.value)}catch{}if(k&&/\s/.test(k)){const z=k.split(/\s+/).map(se=>se[0]).join("").toUpperCase();z.length>=2&&z.length<=4&&(k=z)}}catch{k=""}return k};if(!a){const k=this.date(r,t),Y=this.time(r,s),te=o();return k&&Y?`${k} ${Y} ${te}`.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(te=>te.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)):"",v=p?String(parseInt(p,10)):"",_=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),R=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"long"}).format(r),ne=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"short"}).format(r),be={YYYY:h,YY:h?h.slice(-2):"",MMMM:j,MMM:M,MM:u,M:b,dddd:R,ddd:ne,DD:m,D:y},ye={HH:p,H:v,hh:_!==""?String(_).padStart(2,"0"):"",h:_!==""?String(_):"",mm:f,m:f?String(parseInt(f,10)):"",ss:g,s:g?String(parseInt(g,10)):"",A,a:E},I=(k,Y)=>{if(!k)return"";const te=new RegExp(`(${Object.keys(Y).sort((z,se)=>se.length-z.length).join("|")})`,"g");return k.replace(te,z=>Y[z]??z)},H=I(t,be),Mt=I(s,ye),Ts=o();return H&&Mt?`${H} ${Mt} ${Ts}`.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")||Pt,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 P=new Nt;window.dataFormatter=P;const et=new Set(["__proto__","constructor","prototype"]),tt=(c,e)=>c!=null&&Object.prototype.hasOwnProperty.call(c,e);class ${static getContextData(e,t){if(!t||e==null)return;let s=t,i="",r=0,n=-1;for(let o=0;o<t.length;o++){const l=t[o];if(l==="(")r++;else if(l===")")r--;else if(l==="|"&&r===0){n=o;break}}n>-1&&(s=t.substring(0,n).trim(),i=t.substring(n+1).trim());const a=this.getNestedValue(e,s);return i?P.pipe(a,i,e):a}static getNestedValue(e,t){if(!t||e==null||t.split(".").some(r=>et.has(r)))return;if(!t.includes(".")){if(t in e){const r=e[t];return typeof r=="function"?r===Object.prototype[t]?void 0:r.call(e):r}return}const s=t.split(".");let i=e;for(let r=0;r<s.length;r++){const n=s[r];if(i==null)return;if(r===0)if(tt(i,n)){const a=i[n];typeof a=="function"?i=a.call(e):i=a}else return;else{if(i&&typeof i.getContextValue=="function"){const a=s.slice(r).join(".");return i.getContextValue(a)}if(Array.isArray(i)&&!isNaN(n))i=i[parseInt(n)];else if(tt(i,n))i=i[n];else return}}return i}static isNullOrUndefined(e){return e==null}static deepClone(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(e instanceof Array)return e.map(t=>this.deepClone(t));if(e instanceof Object){const t={};for(const s in e)e.hasOwnProperty(s)&&(t[s]=this.deepClone(e[s]));return t}}static deepMerge(e,...t){if(!t.length)return e;const s=t.shift();if(this.isObject(e)&&this.isObject(s))for(const i in s)this.isObject(s[i])?(e[i]||Object.assign(e,{[i]:{}}),this.deepMerge(e[i],s[i])):Object.assign(e,{[i]:s[i]});return this.deepMerge(e,...t)}static isObject(e){return e&&typeof e=="object"&&!Array.isArray(e)}static debounce(e,t){let s;return function(...r){const n=()=>{clearTimeout(s),e(...r)};clearTimeout(s),s=setTimeout(n,t)}}static throttle(e,t){let s;return function(...i){s||(e.apply(this,i),s=!0,setTimeout(()=>s=!1,t))}}static generateId(e=""){const t=Date.now().toString(36),s=Math.random().toString(36).substr(2,9);return e?`${e}_${t}_${s}`:`${t}_${s}`}static escapeHtml(e){const t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(e).replace(/[&<>"'`=\/]/g,s=>t[s])}static checkPasswordStrength(e){if(!e||typeof e!="string")return{score:0,strength:"invalid",feedback:["Password must be a non-empty string"],details:{length:0,hasLowercase:!1,hasUppercase:!1,hasNumbers:!1,hasSpecialChars:!1,hasCommonPatterns:!1,isCommonPassword:!1}};const t=[],s={length:e.length,hasLowercase:/[a-z]/.test(e),hasUppercase:/[A-Z]/.test(e),hasNumbers:/[0-9]/.test(e),hasSpecialChars:/[^a-zA-Z0-9]/.test(e),hasCommonPatterns:!1,isCommonPassword:!1};let i=0;e.length<6?t.push("Password should be at least 6 characters long"):e.length<8?(i+=1,t.push("Consider using at least 8 characters for better security")):e.length<12?i+=3:i+=4,s.hasLowercase?i+=1:t.push("Include lowercase letters"),s.hasUppercase?i+=1:t.push("Include uppercase letters"),s.hasNumbers?i+=1:t.push("Include numbers"),s.hasSpecialChars?i+=2:t.push("Include special characters (!@#$%^&* etc.)");const r=[/123/,/abc/i,/qwerty/i,/asdf/i,/(.)\1{2,}/,/password/i,/admin/i,/user/i,/login/i];for(const o of r)if(o.test(e)){s.hasCommonPatterns=!0,i-=1,t.push("Avoid common patterns and dictionary words");break}["123456","password","123456789","12345678","12345","1234567","1234567890","qwerty","abc123","111111","123123","admin","letmein","welcome","monkey","password123","123qwe","qwerty123","000000","dragon","sunshine","princess","azerty","1234","iloveyou","trustno1","superman","shadow","master","jennifer"].includes(e.toLowerCase())&&(s.isCommonPassword=!0,i=Math.max(0,i-3),t.push("This password is too common and easily guessed"));let a;return i<2?a="very-weak":i<4?a="weak":i<6?a="fair":i<8?a="good":a="strong",i>=7&&t.length===0?t.push("Strong password! Consider using a password manager."):i>=5&&t.length<=1&&t.push("Good password strength. Consider adding more variety."),{score:Math.max(0,i),strength:a,feedback:t,details:s}}static generatePassword(e={}){const s={...{length:12,includeLowercase:!0,includeUppercase:!0,includeNumbers:!0,includeSpecialChars:!0,customChars:"",excludeAmbiguous:!1},...e};if(s.length<4)throw new Error("Password length must be at least 4 characters");let i="abcdefghijklmnopqrstuvwxyz",r="ABCDEFGHIJKLMNOPQRSTUVWXYZ",n="0123456789",a="!@#$%^&*()_+-=[]{}|;:,.<>?";s.excludeAmbiguous&&(i=i.replace(/[il]/g,""),r=r.replace(/[IOL]/g,""),n=n.replace(/[01]/g,""),a=a.replace(/[|]/g,""));let o="";const l=[];if(s.customChars?o=s.customChars:(s.includeLowercase&&(o+=i,l.push(i[Math.floor(Math.random()*i.length)])),s.includeUppercase&&(o+=r,l.push(r[Math.floor(Math.random()*r.length)])),s.includeNumbers&&(o+=n,l.push(n[Math.floor(Math.random()*n.length)])),s.includeSpecialChars&&(o+=a,l.push(a[Math.floor(Math.random()*a.length)]))),!o)throw new Error("No character types selected for password generation");let d="";for(const h of l)d+=h;for(let h=d.length;h<s.length;h++)d+=o[Math.floor(Math.random()*o.length)];return d.split("").sort(()=>Math.random()-.5).join("")}static parseQueryString(e){const t={},s=new URLSearchParams(e);for(const[i,r]of s.entries())t[i]=r;return t}static toQueryString(e){return new URLSearchParams(e).toString()}static wrapData(e,t=null,s=3){return!e||typeof e!="object"||e instanceof Date||e instanceof RegExp||e instanceof Error||s<=0||typeof e.getContextValue=="function"?e:Array.isArray(e)?e.map(i=>i&&typeof i=="object"&&!i.getContextValue?new Fe(i,t):i):new Fe(e,t)}}class Fe{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&&!et.has(t)&&t!=="_data"&&t!=="_rootContext"?n=this[t]:n=$.getNestedValue(this._data,t),s&&n!==void 0?P.pipe(n,s,this._rootContext||this._data):n}has(e){return this._data&&this._data.hasOwnProperty(e)}toJSON(){return this._data}}$.DataWrapper=Fe,typeof window<"u"&&(window.utils=$);const Ot=new Set(["__proto__","constructor","prototype"]),Rt=Object.prototype.toString,ae=Array.isArray||function(c){return Rt.call(c)==="[object Array]"},ue=function(c){return typeof c=="function"},st=function(c){return c!==null&&typeof c=="object"};function jt(){return typeof window>"u"?null:window.MOJO?.dataFormatter?window.MOJO.dataFormatter:window.dataFormatter?window.dataFormatter:null}const it=function(c){const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(c).replace(/[&<>"'`=\/]/g,function(t){return e[t]})};class rt{constructor(e){this.string=e,this.tail=e,this.pos=0}eos(){return this.tail===""}scan(e){const t=this.tail.match(e);if(!t||t.index!==0)return"";const s=t[0];return this.tail=this.tail.substring(s.length),this.pos+=s.length,s}scanUntil(e){const t=this.tail.search(e);let s;switch(t){case-1:s=this.tail,this.tail="";break;case 0:s="";break;default:s=this.tail.substring(0,t),this.tail=this.tail.substring(t)}return this.pos+=s.length,s}}class we{constructor(e,t){this.view=e,this.cache={".":this.view},this.parent=t,this.view?._cacheId||this.view&&typeof this.view=="object"&&(this.view._cacheId=Math.random().toString(36).substring(2))}push(e){return new we(e,this)}lookup(e){if(this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;if(this.renderCache.has(i))return this.renderCache.get(i)}if(e===".")return this.view;if(e&&(e.startsWith(".")?e.slice(1):e).split("|")[0].split(".").some(r=>Ot.has(r)))return;if(e&&e.startsWith(".")){let i=e.substring(1),r=!1,n=null;const a=i.indexOf("|");if(a!==-1&&(n=i.substring(a+1).trim(),i=i.substring(0,a).trim()),i.endsWith("|iter")&&(i=i.substring(0,i.length-5),r=!0),this.view&&typeof this.view=="object"){let o;if(typeof this.view.getContextValue=="function")try{o=this.view.getContextValue(i),o!==void 0&&ue(o)&&(o=o.call(this.view))}catch{o=void 0}if(o===void 0&&(i.indexOf(".")>0?o=$.getNestedValue(this.view,i):i in this.view&&(o=this.view[i],ue(o)&&(o===Object.prototype[i]?o=void 0:o=o.call(this.view)))),n&&o!==void 0)try{const l=jt();l&&typeof l.pipe=="function"&&(o=l.pipe(o,n,this))}catch{}return ae(o)?r?o:o.length>0:st(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=Ee(r,n[a])||nt(r,n[a])),r=r[n[a++]]}else a===n.length-1&&(o=Ee(r,n[a])||nt(r,n[a])),r=r[n[a++]];else r=i.view[e],o=Ee(i.view,e);if(o){s=r;break}i=i.parent}t[e]=s}if(ue(s)){const i=e.split("|")[0].split(".").pop();if(s===Object.prototype[i])s=void 0;else try{s=s.call(this.view)}catch(r){if(r instanceof TypeError&&/^Class constructor /.test(r.message))s=void 0;else throw r}}if(this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;this.renderCache.set(i,s)}return s}}function Ee(c,e){return c!=null&&typeof c=="object"&&e in c}function nt(c,e){return c!=null&&typeof c!="object"&&c.hasOwnProperty&&c.hasOwnProperty(e)}class at{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 rt(e),n=[];let a,o,l,d,h;const u=new RegExp(De(s)+"\\s*"),m=new RegExp("\\s*"+De(i)),p=new RegExp("\\s*"+De("}"+i));for(;!r.eos();){if(a=r.pos,l=r.scanUntil(u),l)for(let f=0;f<l.length;++f)d=l.charAt(f),d===`
15
- `?n.push(["text",d]):n.push(["text",d]);if(!r.scan(u))break;if(o=r.scan(/[#^\/>{&=!]/),o||(o="name"),r.scan(/\s*/),o==="="?(l=r.scanUntil(/\s*=/),r.scan(/\s*=/),r.scanUntil(m)):o==="{"?(l=r.scanUntil(p),r.scan(p),o="&"):l=r.scanUntil(m),r.scan(m),o==="#"||o==="^")h=[o,l,a,r.pos],n.push(h);else if(o==="/"){let f;for(let g=n.length-1;g>=0;--g)if((n[g][0]==="#"||n[g][0]==="^")&&n[g][1]===l){f=n[g];break}f&&f.length===4&&f.push(r.pos),n.push([o,l,a,r.pos])}else n.push([o,l,a,r.pos])}return this.nestSections(this.squashTokens(n))}squashTokens(e){const t=[];let s,i;for(let r=0;r<e.length;++r)s=e[r],s&&(s[0]==="text"&&i&&i[0]==="text"?(i[1]+=s[1],i[3]=s[3]):(t.push(s),i=s));return t}nestSections(e){const t=[];let s=t;const i=[];for(let r=0;r<e.length;++r){const n=e[r];switch(n[0]){case"#":case"^":const a=[n[0],n[1],n[2],n[3],[],n[4]||null];s.push(a),i.push(a),s=a[4];break;case"/":const o=i.pop();o&&(o[5]=n[2],s=i.length>0?i[i.length-1][4]:t);break;default:s.push(n)}}return t}render(e,t,s,i){const r=this.getConfigTags(i)||["{{","}}"],n=this.parse(e,r),a=new Map;return this.renderTokens(n,new we(t),s,e,i,a)}renderTokens(e,t,s,i,r,n){n&&!t.renderCache&&(t.renderCache=n);let a="";for(let o=0;o<e.length;++o){const l=e[o];let d;switch(l[0]){case"#":if(d=t.lookup(l[1]),!d)continue;const h=l[4];if(!h||!ae(h)){console.warn(`MUSTACHE WARNING - Section ${l[1]} has no child tokens:`,l);continue}if(ae(d))for(let u=0;u<d.length;++u){const m=t.push(d[u]);t.renderCache&&(m.renderCache=t.renderCache);const p=this.renderTokens(h,m,s,i,r,n);a+=p}else if(typeof d=="object"||typeof d=="string"||typeof d=="number"){const u=t.push(d);t.renderCache&&(u.renderCache=t.renderCache),a+=this.renderTokens(h,u,s,i,r,n)}else if(ue(d)){const u=i==null?null:i.slice(l[3],l[5]);d=d.call(t.view,u,m=>this.render(m,t.view,s,r)),d!=null&&(a+=d)}else d&&(a+=this.renderTokens(h,t,s,i,r,n));break;case"^":if(d=t.lookup(l[1]),!d||ae(d)&&d.length===0){const u=l[4];u&&ae(u)&&(a+=this.renderTokens(u,t,s,i,r,n))}break;case">":if(!s)continue;d=ue(s)?s(l[1]):s[l[1]],d!=null&&(a+=this.render(d,t.view,s,r));break;case"&":d=t.lookup(l[1]),d!=null&&(a+=d);break;case"name":d=t.lookup(l[1]),d!=null&&(a+=it(d));break;case"text":a+=l[1];break}}return a}getConfigTags(e){return st(e)&&ae(e.tags)?e.tags:null}}function De(c){return c.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}const Ie=new at,D={name:"MOJO Mustache",version:"1.0.0",tags:["{{","}}"],Scanner:rt,Context:we,Writer:at,escape:it,clearCache(){return Ie.clearCache()},parse(c,e){return Ie.parse(c,e)},render(c,e,t,s){if(typeof c!="string")throw new TypeError('Invalid template! Template should be a "string"');return e&&typeof e=="object"&&!e.getContextValue&&typeof e.toJSON!="function"&&(e=$.wrapData(e)),Ie.render(c,e,t,s)}};class Ht{constructor(e){this.view=e,this.domListeners=[],this.debounceTimers=new Map}_enterDispatchChain(e){const t=e._mojoDispatch;let s;return e._mojoDispatch=new Promise(i=>{s=i}),{prior:t,done:s}}bind(e){if(this.unbind(),!e)return;const t=async a=>{const{prior:o,done:l}=this._enterDispatchChain(a);try{o&&await o;const d=a.target.closest("[data-action]");if(d&&this.shouldHandle(d,a)){const u=d.getAttribute("data-action");if(d.tagName==="A"&&a.preventDefault(),this.hideTooltip(d),await this.dispatch(u,a,d)){a.preventDefault(),a.stopPropagation(),a.handledByChild=!0;return}}const h=a.target.closest("a[href], [data-page]");if(h&&!h.hasAttribute("data-action")&&this.shouldHandle(h,a)){if(a.ctrlKey||a.metaKey||a.shiftKey||a.button===1)return;if(h.tagName==="A"){const u=h.getAttribute("href");if(u&&u!=="#"&&!u.startsWith("#")&&(this.view.isExternalLink(u)||h.hasAttribute("data-external")))return}this.hideTooltip(h),a.preventDefault(),a.stopPropagation(),a.handledByChild=!0,h.hasAttribute("data-page")?await this.view.handlePageNavigation(h):await this.view.handleHrefNavigation(h)}}finally{l()}},s=async a=>{const{prior:o,done:l}=this._enterDispatchChain(a);try{o&&await o;const d=a.target.closest("[data-change-action]");if(d&&this.shouldHandle(d,a)){const u=d.getAttribute("data-change-action");await this.dispatchChange(u,a,d)&&(a.stopPropagation(),a.handledByChild=!0);return}const h=a.target.closest("[data-action]");if(h&&this.isFormControl(h)&&this.shouldHandle(h,a)){const u=h.getAttribute("data-action");await this.dispatch(u,a,h)&&(a.stopPropagation(),a.handledByChild=!0)}}finally{l()}},i=a=>{const o=a.target.closest("[data-change-action]");if(o&&this.shouldHandle(o,a)&&a.target.matches('[data-filter="live-search"]')){const m=o.getAttribute("data-change-action"),p=parseInt(o.getAttribute("data-filter-debounce"))||300,f=`change-${m}-${o.getAttribute("data-container")||"default"}`;this.debounceTimers.has(f)&&clearTimeout(this.debounceTimers.get(f));const g=setTimeout(()=>{this.debounceTimers.delete(f),this.dispatchChange(m,a,o).then(b=>{b&&(a.stopPropagation(),a.handledByChild=!0)})},p);this.debounceTimers.set(f,g);return}const l=a.target.closest("[data-action]");if(!l||!this.isFormControl(l)||l.hasAttribute("data-change-action")||!this.shouldHandle(l,a))return;const d=l.getAttribute("data-action"),h=l.getAttribute("data-action-debounce"),u=h!=null&&parseInt(h)||0;if(u>0){const m=`action-${d}-${l.getAttribute("data-container")||"default"}`;this.debounceTimers.has(m)&&clearTimeout(this.debounceTimers.get(m));const p=setTimeout(()=>{this.debounceTimers.delete(m),this.dispatch(d,a,l).then(f=>{f&&(a.stopPropagation(),a.handledByChild=!0)})},u);this.debounceTimers.set(m,p);return}this.dispatch(d,a,l).then(m=>{m&&(a.stopPropagation(),a.handledByChild=!0)})},r=async a=>{if(a.target.matches('[data-filter="search"]'))return;const o=a.target.closest("[data-keydown-action]")||a.target.closest("[data-change-action]");if(!o)return;const{prior:l,done:d}=this._enterDispatchChain(a);try{if(l&&await l,!this.shouldHandle(o,a))return;let h=["Enter"];if(o.getAttribute("data-change-keys")&&(h=o.getAttribute("data-change-keys").split(",").map(u=>u.trim())),h.includes("*")||h.includes(a.key)){const u=o.getAttribute("data-keydown-action")||o.getAttribute("data-change-action");await this.dispatch(u,a,o)&&(a.preventDefault(),a.stopPropagation(),a.handledByChild=!0)}}finally{d()}},n=a=>{const o=a.target.closest("form[data-action]");if(!o||!this.shouldHandle(o,a))return;a.preventDefault();const l=o.getAttribute("data-action");this.dispatch(l,a,o)};e.addEventListener("click",t),e.addEventListener("change",s),e.addEventListener("input",i),e.addEventListener("keydown",r),e.addEventListener("submit",n),this.domListeners.push({el:e,type:"click",fn:t},{el:e,type:"change",fn:s},{el:e,type:"input",fn:i},{el:e,type:"keydown",fn:r},{el:e,type:"submit",fn:n})}unbind(){for(const{el:e,type:t,fn:s}of this.domListeners)e.removeEventListener(t,s);this.domListeners=[];for(const e of this.debounceTimers.values())clearTimeout(e);this.debounceTimers.clear()}hideDropdown(e){const s=e.closest(".dropdown-menu").closest(".dropdown");if(!s)return;const i=s.querySelector('[data-bs-toggle="dropdown"]');i&&window.bootstrap?.Dropdown&&window.bootstrap.Dropdown.getInstance(i)?.hide()}hideTooltip(e){if(e&&window.bootstrap?.Tooltip){const t=window.bootstrap.Tooltip.getInstance(e);t&&t.dispose()}}hideAllTooltips(){window.bootstrap?.Tooltip&&document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.hide()})}async dispatch(e,t,s){const i=this.view,r=l=>l.includes("-")?l.split("-").map(d=>d[0].toUpperCase()+d.slice(1)).join(""):l[0].toUpperCase()+l.slice(1),n=`handleAction${r(e)}`;if(typeof i[n]=="function")try{return t.preventDefault(),await i[n](t,s),!0}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const a=`onAction${r(e)}`;if(typeof i[a]=="function")try{return await i[a](t,s)?(s.closest(".dropdown-menu")&&this.hideDropdown(s),t.preventDefault(),t.stopPropagation(),!0):!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const o=`onPassThruAction${r(e)}`;if(typeof i[o]=="function")try{return await i[o](t,s),!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}if(typeof i.onActionDefault=="function")try{return await i.onActionDefault(e,t,s)}catch(l){return console.error(`Error in default action handler for ${e}:`,l),i.handleActionError(e,l,t,s),!0}return i.emit?.(`action:${e}`,{action:e,event:t,element:s}),!1}async dispatchChange(e,t,s){const i=this.view,n=`onChange${(a=>a.includes("-")?a.split("-").map(o=>o[0].toUpperCase()+o.slice(1)).join(""):a[0].toUpperCase()+a.slice(1))(e)}`;if(typeof i[n]=="function")try{return await i[n](t,s),!0}catch(a){return console.error(`Error in onChange ${e}:`,a),i.handleActionError?.(e,a,t,s),!0}return await this.dispatch(e,t,s)}isFormControl(e){if(!e||!e.tagName)return!1;const t=e.tagName;return t==="INPUT"||t==="TEXTAREA"||t==="SELECT"}shouldHandle(e,t){return!!(this.owns(e)||this.contains(e)&&!t.handledByChild)}owns(e){const t=this.view.element;if(!t||!t.contains(e))return!1;for(const s of Object.values(this.view.children))if(s.element&&s.element.contains(e))return!1;return!0}contains(e){return!!this.view.element&&this.view.element.contains(e)}}const Me={on(c,e,t){this._listeners||(this._listeners={}),this._listeners[c]||(this._listeners[c]=[]);const s={callback:e,context:t,fn:t?e.bind(t):e};return this._listeners[c].push(s),this},off(c,e,t){return!this._listeners||!this._listeners[c]?this:(e?(this._listeners[c]=this._listeners[c].filter(s=>s.callback!==e||arguments.length===3&&s.context!==t),this._listeners[c].length===0&&delete this._listeners[c]):delete this._listeners[c],this)},once(c,e,t){const s=(...i)=>{this.off(c,s),(t?e.bind(t):e).apply(t||this,i)};return this.on(c,s),this},emit(c,...e){if(!this._listeners||!this._listeners[c])return this;const t=this._listeners[c].slice();for(const s of t)try{s.fn.apply(s.context||this,e)}catch(i){console&&console.error&&console.error(`Error in ${c} event handler:`,i)}return this}};typeof window<"u"&&(window.Mustache=D);class 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 Ht(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&&typeof e!="function"&&(this._templateCache=t),t}getContextValue(e){const t=$.getContextData(this,e);return e&&e.startsWith("data.")&&t&&typeof t=="object"?$.wrapData(t,this):e&&e.startsWith("model.")&&e!=="model"&&t&&typeof t=="object"&&typeof t.getContextValue!="function"?$.wrapData(t,null):t}async handlePageNavigation(e){const t=e.getAttribute("data-page"),s=e.getAttribute("data-params");let i={};if(s)try{i=JSON.parse(s)}catch{console.warn("Invalid JSON in data-params:",s)}const r=this.getApp();if(r){r.showPage(t,i);return}const n=this.findRouter();n&&typeof n.navigateToPage=="function"?await n.navigateToPage(t,i):console.error(`No router found for page navigation to '${t}'`)}async handleHrefNavigation(e){const t=e.getAttribute("href");if(this.isExternalLink(t)||e.hasAttribute("data-external"))return;const s=this.findRouter();if(s){if(s.options&&s.options.mode==="param"&&t.startsWith("?")){const r="/"+t;await s.navigate(r);return}if(s.options&&s.options.mode==="hash"&&t.startsWith("#")){await s.navigate(t);return}const i=this.hrefToRoutePath(t);await s.navigate(i)}else console.warn("No router found for navigation, using default behavior"),window.location.href=t}isExternalLink(e){return e?e.startsWith("/")&&this.getApp()?!e.startsWith(this.findRouter().basePath):e.startsWith("#")||e.startsWith("mailto:")||e.startsWith("tel:")||e.startsWith("http://")||e.startsWith("https://")||e.startsWith("//"):!0}hrefToRoutePath(e){if(e.startsWith("/")){const t=this.findRouter();if(t&&t.options&&t.options.base){const s=t.options.base;if(e.startsWith(s))return e.substring(s.length)||"/"}return e}return e.startsWith("./")?e.substring(2):e}findRouter(){return this.getApp(),this.app?.router||null}getApp(){if(this.app)return this.app;const e=[window.__app__,window.MOJO?.app,window.APP,window.app,window.WebApp,window.matchUUID?window[window.matchUUID]():window[window.matchUUID]];return this.app=e.find(t=>t&&typeof t.showPage=="function")||null,this.app}handleActionError(e,t,s,i){this.showError(`Action '${e}' failed: ${t}`,s,i)}escapeHtml(e){if(typeof e!="string")return e;const t=document.createElement("div");return t.textContent=e,t.innerHTML}contains(e){if(typeof e=="string"){if(!this.element)return!1;e=document.getElementById(e)}return e?this.element.contains(e):!1}initializeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.disposeTooltips(),[...this.element.querySelectorAll('[data-bs-toggle="tooltip"]')].map(t=>{const s=t.getAttribute("data-tooltip-theme"),i=t.getAttribute("data-tooltip-size");let r="";s&&(r+=`tooltip-${s} `),i&&(r+=`tooltip-${i}`);const n={},a=r.trim();return a&&(n.customClass=a),new window.bootstrap.Tooltip(t,n)})}disposeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.element.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.dispose()})}async showError(e){console.error(`View ${this.id} error:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showError=="function"){await t.showError(e);return}alert(`Error: ${e}`)}async showSuccess(e){this.debug&&console.log(`View ${this.id} success:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showSuccess=="function"){await t.showSuccess(e);return}alert(`Success: ${e}`)}async showInfo(e){console.info(`View ${this.id} info:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showInfo=="function"){await t.showInfo(e);return}alert(`Info: ${e}`)}async showWarning(e){console.warn(`View ${this.id} warning:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showWarning=="function"){await t.showWarning(e);return}alert(`Warning: ${e}`)}async onActionCopyToClipboard(e,t){try{const i=(t?.closest("[data-clipboard]")||t)?.getAttribute("data-clipboard")||"";if(!i)return!0;if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(i);else{const a=document.createElement("textarea");a.value=i,document.body.appendChild(a),a.select(),document.execCommand("copy"),document.body.removeChild(a)}const r=t.querySelector("i"),n=r&&r.className;return r&&(r.className="bi bi-check",setTimeout(()=>{r.className=n},1e3)),!0}catch(s){return console.warn("Copy to clipboard failed:",s),!0}}static _genId(){return`view_${Math.random().toString(36).substr(2,9)}`}static _warn(e,t){try{t?console.warn(`[View] ${e}:`,t):console.warn(`[View] ${e}`)}catch{}}}Object.assign(C.prototype,Me);class x extends C{static _openDialogs=[];static _baseZIndex={backdrop:1050,modal:1055};static getFullscreenAwareZIndex(){return document.querySelector(".table-fullscreen")?{backdrop:10040,modal:10050}:x._baseZIndex}static fixAllBackdropStacking(){const e=document.querySelectorAll(".modal-backdrop"),t=x._openDialogs;if(e.length===0||t.length===0)return;const s=[...t].sort((n,a)=>(n._dialogZIndex||0)-(a._dialogZIndex||0)),r=document.querySelector(".table-fullscreen")||document.body;e.forEach((n,a)=>{if(a>=s.length)return;const o=s[a];n.style.zIndex=o._dialogZIndex-5,n.parentNode!==r&&r.appendChild(n)})}static updateAllBackdropStacking(){x.fixAllBackdropStacking()}static getMountTarget(){return document.querySelector(".table-fullscreen")||document.body}constructor(e={}){const t=e.id||`modal-${Date.now()}-${Math.random().toString(36).slice(2,7)}`;super({...e,id:t,tagName:"div",className:`modal ${e.fade!==!1?"fade":""} ${e.className||""}`.trim().replace(/\s+/g," "),attributes:{tabindex:"-1","aria-hidden":"true","aria-labelledby":e.labelledBy||`${t}-label`,"aria-describedby":e.describedBy||null,...e.attributes}}),this.modalId=t,this.title=e.title||"",this.titleId=`${this.modalId}-label`,this.size=e.size||"",this.centered=e.centered!==void 0?e.centered:!1,this.scrollable=e.scrollable!==void 0?e.scrollable:!1,this.autoSize=e.autoSize||e.size==="auto",this.backdrop=e.backdrop!==void 0?e.backdrop:!0,this.keyboard=e.keyboard!==void 0?e.keyboard:!0,this.focus=e.focus!==void 0?e.focus:!0,this.header=e.header!==void 0?e.header:!0,this.headerContent=e.headerContent||null,this.headerView=null,this.closeButton=e.closeButton!==void 0?e.closeButton:!0,this.contextMenu=e.contextMenu||null,this._processHeaderContent(this.headerContent),this.body=e.body??e.view??e.message??e.content??"",this.bodyView=null,this.bodyClass=e.bodyClass||"",this.noBodyPadding=e.noBodyPadding||!1,this.minWidth=e.minWidth||300,this.minHeight=e.minHeight||200,e.maxHeight&&(this.maxHeight=e.maxHeight),this.maxWidthPercent=e.maxWidthPercent||.9,this.maxHeightPercent=e.maxHeightPercent||.8,this._processBodyContent(this.body),this.footer=e.footer||null,this.footerView=null,this.footerClass=e.footerClass||"",this._processFooterContent(this.footer),this.buttons=e.buttons||null,this.onShow=e.onShow||null,this.onShown=e.onShown||null,this.onHide=e.onHide||null,this.onHidden=e.onHidden||null,this.onHidePrevented=e.onHidePrevented||null,this.autoShow=e.autoShow!==void 0?e.autoShow:!1,this.modal=null,this.relatedTarget=e.relatedTarget||null}_processBodyContent(e){if(e instanceof 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")),`
14
+ `}nl2br(e){return e==null?"":this.escapeHtml(String(e)).replace(/\r\n|\r|\n/g,"<br>")}code(e,t=""){if(e==null)return"";const s=t?`language-${this.escapeHtml(String(t))}`:"",i=this.escapeHtml(String(e));return`<pre class="bg-light p-2 rounded border"><code class="${s}">${i}</code></pre>`}register(e,t){if(typeof t!="function")throw new Error(`Formatter must be a function, got ${typeof t}`);return this.formatters.set(e.toLowerCase(),t),this}apply(e,t,...s){if(Array.isArray(t)&&t.every(i=>typeof i=="string"))return t.reduce((i,r)=>this.apply(r,i,...s),e);try{const i=this.formatters.get(e.toLowerCase());return i?i(t,...s):(console.warn(`Formatter '${e}' not found`),t)}catch(i){return console.error(`Error in formatter '${e}':`,i),t}}pipe(e,t,s=null){return t?this.parsePipeString(t,s).reduce((r,n)=>this.apply(n.name,r,...n.args),e):e}parsePipeString(e,t=null){const s=[],i=e.split("|").map(r=>r.trim());for(const r of i){const n=this.parseFormatter(r,t);n&&s.push(n)}return s}parseFormatter(e,t=null){const s=e.match(/^([a-zA-Z_]\w*)\s*\((.*)\)$/);if(s){const[,r,n]=s,a=n?this.parseArguments(n,t):[];return{name:r,args:a}}const i=e.match(/^([a-zA-Z_]\w*)(?::(.+))?$/);if(i){const[,r,n]=i,a=n?this.parseColonArguments(n,t):[];return{name:r,args:a}}return null}parseArguments(e,t=null){const s=[];let i="",r=!1,n=null,a=0;for(let o=0;o<e.length;o++){const l=e[o];!r&&(l==='"'||l==="'")?(r=!0,n=l,i+=l):r&&l===n&&e[o-1]!=="\\"?(r=!1,n=null,i+=l):!r&&l==="{"?(a++,i+=l):!r&&l==="}"?(a--,i+=l):!r&&a===0&&l===","?(s.push(this.parseValue(i.trim(),t)),i=""):i+=l}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseColonArguments(e,t=null){const s=[];let i="",r=!1,n=null;for(let a=0;a<e.length;a++){const o=e[a];!r&&(o==='"'||o==="'")?(r=!0,n=o,i+=o):r&&o===n&&e[a-1]!=="\\"?(r=!1,n=null,i+=o):!r&&o===":"?(s.push(this.parseValue(i.trim(),t)),i=""):i+=o}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseValue(e,t=null){if(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);if(e==="true")return!0;if(e==="false")return!1;if(e==="null")return null;if(e!=="undefined"){if(!isNaN(e)&&e!=="")return Number(e);if(e.startsWith("{")&&e.endsWith("}"))try{return JSON.parse(e)}catch{}if(t&&this.isIdentifier(e)){if(!e.includes(".")&&Object.prototype.hasOwnProperty.call(t,e))return t[e];if(t.get&&typeof t.get=="function"){const s=t.get(e);if(s!==void 0)return s}if(t.getContextValue&&typeof t.getContextValue=="function"){const s=t.getContextValue(e);if(s!==void 0)return s}if(e.includes(".")){const s=window.MOJOUtils||(typeof require<"u"?require("./MOJOUtils.js").default:null);if(s){const i=s.getNestedValue(t,e);if(i!==void 0)return i}}}return e}}isIdentifier(e){return/^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/.test(e)}date(e,t="MM/DD/YYYY"){if(!e)return"";e=this.normalizeEpoch(e);let s;if(e instanceof Date)s=e;else if(typeof e=="string")if(/^\d{4}-\d{2}-\d{2}$/.test(e)){const[a,o,l]=e.split("-").map(Number);s=new Date(a,o-1,l)}else s=new Date(e);else s=new Date(e);if(isNaN(s.getTime()))return String(e);const i={YYYY:s.getFullYear(),YY:String(s.getFullYear()).slice(-2),MMMM:s.toLocaleDateString("en-US",{month:"long"}),MMM:s.toLocaleDateString("en-US",{month:"short"}),MM:String(s.getMonth()+1).padStart(2,"0"),M:s.getMonth()+1,dddd:s.toLocaleDateString("en-US",{weekday:"long"}),ddd:s.toLocaleDateString("en-US",{weekday:"short"}),DD:String(s.getDate()).padStart(2,"0"),D:s.getDate()};let r=t;const n=new RegExp(`(${Object.keys(i).join("|")})`,"g");return r=r.replace(n,a=>i[a]||a),r}time(e,t="HH:mm:ss"){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const i=s.getHours(),r={HH:String(i).padStart(2,"0"),H:i,hh:String(i%12||12).padStart(2,"0"),h:i%12||12,mm:String(s.getMinutes()).padStart(2,"0"),m:s.getMinutes(),ss:String(s.getSeconds()).padStart(2,"0"),s:s.getSeconds(),A:i>=12?"PM":"AM",a:i>=12?"pm":"am"};let n=t;const a=Object.keys(r).sort((o,l)=>l.length-o.length);for(const o of a)n=n.replace(new RegExp(o,"g"),r[o]);return n}datetime(e,t="MM/DD/YYYY",s="HH:mm:ss"){e=this.normalizeEpoch(e);const i=this.date(e,t),r=this.time(e,s);return i&&r?`${i} ${r}`:""}datetime_tz(e,t="MM/DD/YYYY",s="HH:mm:ss",i={}){if(!e)return"";e=this.normalizeEpoch(e);const r=e instanceof Date?e:new Date(e);if(isNaN(r.getTime()))return String(e);const n=i&&i.locale||"en-US",a=i&&i.timeZone?i.timeZone:void 0,o=()=>{let k="";try{const te=new Intl.DateTimeFormat(n,{hour:"2-digit",minute:"2-digit",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(z=>z.type==="timeZoneName");if(k=te?te.value:"",k&&/^GMT[+-]/i.test(k))try{const se=new Intl.DateTimeFormat(n,{timeStyle:"short",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(Fs=>Fs.type==="timeZoneName");se&&se.value&&!/^GMT[+-]/i.test(se.value)&&(k=se.value)}catch{}if(k&&/\s/.test(k)){const z=k.split(/\s+/).map(se=>se[0]).join("").toUpperCase();z.length>=2&&z.length<=4&&(k=z)}}catch{k=""}return k};if(!a){const k=this.date(r,t),Y=this.time(r,s),te=o();return k&&Y?`${k} ${Y} ${te}`.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(te=>te.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)):"",v=p?String(parseInt(p,10)):"",_=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),I=new Intl.DateTimeFormat(n,{timeZone:a,month:"short"}).format(r),R=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"long"}).format(r),ne=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"short"}).format(r),be={YYYY:h,YY:h?h.slice(-2):"",MMMM:j,MMM:I,MM:u,M:b,dddd:R,ddd:ne,DD:m,D:y},ye={HH:p,H:v,hh:_!==""?String(_).padStart(2,"0"):"",h:_!==""?String(_):"",mm:f,m:f?String(parseInt(f,10)):"",ss:g,s:g?String(parseInt(g,10)):"",A,a:E},M=(k,Y)=>{if(!k)return"";const te=new RegExp(`(${Object.keys(Y).sort((z,se)=>se.length-z.length).join("|")})`,"g");return k.replace(te,z=>Y[z]??z)},H=M(t,be),It=M(s,ye),Ts=o();return H&&It?`${H} ${It} ${Ts}`.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")||Pt,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 P=new Nt;window.dataFormatter=P;const et=new Set(["__proto__","constructor","prototype"]),tt=(c,e)=>c!=null&&Object.prototype.hasOwnProperty.call(c,e);class ${static getContextData(e,t){if(!t||e==null)return;let s=t,i="",r=0,n=-1;for(let o=0;o<t.length;o++){const l=t[o];if(l==="(")r++;else if(l===")")r--;else if(l==="|"&&r===0){n=o;break}}n>-1&&(s=t.substring(0,n).trim(),i=t.substring(n+1).trim());const a=this.getNestedValue(e,s);return i?P.pipe(a,i,e):a}static getNestedValue(e,t){if(!t||e==null||t.split(".").some(r=>et.has(r)))return;if(!t.includes(".")){if(t in e){const r=e[t];return typeof r=="function"?r===Object.prototype[t]?void 0:r.call(e):r}return}const s=t.split(".");let i=e;for(let r=0;r<s.length;r++){const n=s[r];if(i==null)return;if(r===0)if(tt(i,n)){const a=i[n];typeof a=="function"?i=a.call(e):i=a}else return;else{if(i&&typeof i.getContextValue=="function"){const a=s.slice(r).join(".");return i.getContextValue(a)}if(Array.isArray(i)&&!isNaN(n))i=i[parseInt(n)];else if(tt(i,n))i=i[n];else return}}return i}static isNullOrUndefined(e){return e==null}static deepClone(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(e instanceof Array)return e.map(t=>this.deepClone(t));if(e instanceof Object){const t={};for(const s in e)e.hasOwnProperty(s)&&(t[s]=this.deepClone(e[s]));return t}}static deepMerge(e,...t){if(!t.length)return e;const s=t.shift();if(this.isObject(e)&&this.isObject(s))for(const i in s)this.isObject(s[i])?(e[i]||Object.assign(e,{[i]:{}}),this.deepMerge(e[i],s[i])):Object.assign(e,{[i]:s[i]});return this.deepMerge(e,...t)}static isObject(e){return e&&typeof e=="object"&&!Array.isArray(e)}static debounce(e,t){let s;return function(...r){const n=()=>{clearTimeout(s),e(...r)};clearTimeout(s),s=setTimeout(n,t)}}static throttle(e,t){let s;return function(...i){s||(e.apply(this,i),s=!0,setTimeout(()=>s=!1,t))}}static generateId(e=""){const t=Date.now().toString(36),s=Math.random().toString(36).substr(2,9);return e?`${e}_${t}_${s}`:`${t}_${s}`}static escapeHtml(e){const t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(e).replace(/[&<>"'`=\/]/g,s=>t[s])}static checkPasswordStrength(e){if(!e||typeof e!="string")return{score:0,strength:"invalid",feedback:["Password must be a non-empty string"],details:{length:0,hasLowercase:!1,hasUppercase:!1,hasNumbers:!1,hasSpecialChars:!1,hasCommonPatterns:!1,isCommonPassword:!1}};const t=[],s={length:e.length,hasLowercase:/[a-z]/.test(e),hasUppercase:/[A-Z]/.test(e),hasNumbers:/[0-9]/.test(e),hasSpecialChars:/[^a-zA-Z0-9]/.test(e),hasCommonPatterns:!1,isCommonPassword:!1};let i=0;e.length<6?t.push("Password should be at least 6 characters long"):e.length<8?(i+=1,t.push("Consider using at least 8 characters for better security")):e.length<12?i+=3:i+=4,s.hasLowercase?i+=1:t.push("Include lowercase letters"),s.hasUppercase?i+=1:t.push("Include uppercase letters"),s.hasNumbers?i+=1:t.push("Include numbers"),s.hasSpecialChars?i+=2:t.push("Include special characters (!@#$%^&* etc.)");const r=[/123/,/abc/i,/qwerty/i,/asdf/i,/(.)\1{2,}/,/password/i,/admin/i,/user/i,/login/i];for(const o of r)if(o.test(e)){s.hasCommonPatterns=!0,i-=1,t.push("Avoid common patterns and dictionary words");break}["123456","password","123456789","12345678","12345","1234567","1234567890","qwerty","abc123","111111","123123","admin","letmein","welcome","monkey","password123","123qwe","qwerty123","000000","dragon","sunshine","princess","azerty","1234","iloveyou","trustno1","superman","shadow","master","jennifer"].includes(e.toLowerCase())&&(s.isCommonPassword=!0,i=Math.max(0,i-3),t.push("This password is too common and easily guessed"));let a;return i<2?a="very-weak":i<4?a="weak":i<6?a="fair":i<8?a="good":a="strong",i>=7&&t.length===0?t.push("Strong password! Consider using a password manager."):i>=5&&t.length<=1&&t.push("Good password strength. Consider adding more variety."),{score:Math.max(0,i),strength:a,feedback:t,details:s}}static generatePassword(e={}){const s={...{length:12,includeLowercase:!0,includeUppercase:!0,includeNumbers:!0,includeSpecialChars:!0,customChars:"",excludeAmbiguous:!1},...e};if(s.length<4)throw new Error("Password length must be at least 4 characters");let i="abcdefghijklmnopqrstuvwxyz",r="ABCDEFGHIJKLMNOPQRSTUVWXYZ",n="0123456789",a="!@#$%^&*()_+-=[]{}|;:,.<>?";s.excludeAmbiguous&&(i=i.replace(/[il]/g,""),r=r.replace(/[IOL]/g,""),n=n.replace(/[01]/g,""),a=a.replace(/[|]/g,""));let o="";const l=[];if(s.customChars?o=s.customChars:(s.includeLowercase&&(o+=i,l.push(i[Math.floor(Math.random()*i.length)])),s.includeUppercase&&(o+=r,l.push(r[Math.floor(Math.random()*r.length)])),s.includeNumbers&&(o+=n,l.push(n[Math.floor(Math.random()*n.length)])),s.includeSpecialChars&&(o+=a,l.push(a[Math.floor(Math.random()*a.length)]))),!o)throw new Error("No character types selected for password generation");let d="";for(const h of l)d+=h;for(let h=d.length;h<s.length;h++)d+=o[Math.floor(Math.random()*o.length)];return d.split("").sort(()=>Math.random()-.5).join("")}static parseQueryString(e){const t={},s=new URLSearchParams(e);for(const[i,r]of s.entries())t[i]=r;return t}static toQueryString(e){return new URLSearchParams(e).toString()}static wrapData(e,t=null,s=3){return!e||typeof e!="object"||e instanceof Date||e instanceof RegExp||e instanceof Error||s<=0||typeof e.getContextValue=="function"?e:Array.isArray(e)?e.map(i=>i&&typeof i=="object"&&!i.getContextValue?new Fe(i,t):i):new Fe(e,t)}}class Fe{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&&!et.has(t)&&t!=="_data"&&t!=="_rootContext"?n=this[t]:n=$.getNestedValue(this._data,t),s&&n!==void 0?P.pipe(n,s,this._rootContext||this._data):n}has(e){return this._data&&this._data.hasOwnProperty(e)}toJSON(){return this._data}}$.DataWrapper=Fe,typeof window<"u"&&(window.utils=$);const Ot=new Set(["__proto__","constructor","prototype"]),Rt=Object.prototype.toString,ae=Array.isArray||function(c){return Rt.call(c)==="[object Array]"},ue=function(c){return typeof c=="function"},st=function(c){return c!==null&&typeof c=="object"};function jt(){return typeof window>"u"?null:window.MOJO?.dataFormatter?window.MOJO.dataFormatter:window.dataFormatter?window.dataFormatter:null}const it=function(c){const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(c).replace(/[&<>"'`=\/]/g,function(t){return e[t]})};class rt{constructor(e){this.string=e,this.tail=e,this.pos=0}eos(){return this.tail===""}scan(e){const t=this.tail.match(e);if(!t||t.index!==0)return"";const s=t[0];return this.tail=this.tail.substring(s.length),this.pos+=s.length,s}scanUntil(e){const t=this.tail.search(e);let s;switch(t){case-1:s=this.tail,this.tail="";break;case 0:s="";break;default:s=this.tail.substring(0,t),this.tail=this.tail.substring(t)}return this.pos+=s.length,s}}class we{constructor(e,t){this.view=e,this.cache={".":this.view},this.parent=t,this.view?._cacheId||this.view&&typeof this.view=="object"&&(this.view._cacheId=Math.random().toString(36).substring(2))}push(e){return new we(e,this)}lookup(e){if(this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;if(this.renderCache.has(i))return this.renderCache.get(i)}if(e===".")return this.view;if(e&&(e.startsWith(".")?e.slice(1):e).split("|")[0].split(".").some(r=>Ot.has(r)))return;if(e&&e.startsWith(".")){let i=e.substring(1),r=!1,n=null;const a=i.indexOf("|");if(a!==-1&&(n=i.substring(a+1).trim(),i=i.substring(0,a).trim()),i.endsWith("|iter")&&(i=i.substring(0,i.length-5),r=!0),this.view&&typeof this.view=="object"){let o;if(typeof this.view.getContextValue=="function")try{o=this.view.getContextValue(i),o!==void 0&&ue(o)&&(o=o.call(this.view))}catch{o=void 0}if(o===void 0&&(i.indexOf(".")>0?o=$.getNestedValue(this.view,i):i in this.view&&(o=this.view[i],ue(o)&&(o===Object.prototype[i]?o=void 0:o=o.call(this.view)))),n&&o!==void 0)try{const l=jt();l&&typeof l.pipe=="function"&&(o=l.pipe(o,n,this))}catch{}return ae(o)?r?o:o.length>0:st(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=Ee(r,n[a])||nt(r,n[a])),r=r[n[a++]]}else a===n.length-1&&(o=Ee(r,n[a])||nt(r,n[a])),r=r[n[a++]];else r=i.view[e],o=Ee(i.view,e);if(o){s=r;break}i=i.parent}t[e]=s}if(ue(s)){const i=e.split("|")[0].split(".").pop();if(s===Object.prototype[i])s=void 0;else try{s=s.call(this.view)}catch(r){if(r instanceof TypeError&&/^Class constructor /.test(r.message))s=void 0;else throw r}}if(this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;this.renderCache.set(i,s)}return s}}function Ee(c,e){return c!=null&&typeof c=="object"&&e in c}function nt(c,e){return c!=null&&typeof c!="object"&&c.hasOwnProperty&&c.hasOwnProperty(e)}class at{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 rt(e),n=[];let a,o,l,d,h;const u=new RegExp(De(s)+"\\s*"),m=new RegExp("\\s*"+De(i)),p=new RegExp("\\s*"+De("}"+i));for(;!r.eos();){if(a=r.pos,l=r.scanUntil(u),l)for(let f=0;f<l.length;++f)d=l.charAt(f),d===`
15
+ `?n.push(["text",d]):n.push(["text",d]);if(!r.scan(u))break;if(o=r.scan(/[#^\/>{&=!]/),o||(o="name"),r.scan(/\s*/),o==="="?(l=r.scanUntil(/\s*=/),r.scan(/\s*=/),r.scanUntil(m)):o==="{"?(l=r.scanUntil(p),r.scan(p),o="&"):l=r.scanUntil(m),r.scan(m),o==="#"||o==="^")h=[o,l,a,r.pos],n.push(h);else if(o==="/"){let f;for(let g=n.length-1;g>=0;--g)if((n[g][0]==="#"||n[g][0]==="^")&&n[g][1]===l){f=n[g];break}f&&f.length===4&&f.push(r.pos),n.push([o,l,a,r.pos])}else n.push([o,l,a,r.pos])}return this.nestSections(this.squashTokens(n))}squashTokens(e){const t=[];let s,i;for(let r=0;r<e.length;++r)s=e[r],s&&(s[0]==="text"&&i&&i[0]==="text"?(i[1]+=s[1],i[3]=s[3]):(t.push(s),i=s));return t}nestSections(e){const t=[];let s=t;const i=[];for(let r=0;r<e.length;++r){const n=e[r];switch(n[0]){case"#":case"^":const a=[n[0],n[1],n[2],n[3],[],n[4]||null];s.push(a),i.push(a),s=a[4];break;case"/":const o=i.pop();o&&(o[5]=n[2],s=i.length>0?i[i.length-1][4]:t);break;default:s.push(n)}}return t}render(e,t,s,i){const r=this.getConfigTags(i)||["{{","}}"],n=this.parse(e,r),a=new Map;return this.renderTokens(n,new we(t),s,e,i,a)}renderTokens(e,t,s,i,r,n){n&&!t.renderCache&&(t.renderCache=n);let a="";for(let o=0;o<e.length;++o){const l=e[o];let d;switch(l[0]){case"#":if(d=t.lookup(l[1]),!d)continue;const h=l[4];if(!h||!ae(h)){console.warn(`MUSTACHE WARNING - Section ${l[1]} has no child tokens:`,l);continue}if(ae(d))for(let u=0;u<d.length;++u){const m=t.push(d[u]);t.renderCache&&(m.renderCache=t.renderCache);const p=this.renderTokens(h,m,s,i,r,n);a+=p}else if(typeof d=="object"||typeof d=="string"||typeof d=="number"){const u=t.push(d);t.renderCache&&(u.renderCache=t.renderCache),a+=this.renderTokens(h,u,s,i,r,n)}else if(ue(d)){const u=i==null?null:i.slice(l[3],l[5]);d=d.call(t.view,u,m=>this.render(m,t.view,s,r)),d!=null&&(a+=d)}else d&&(a+=this.renderTokens(h,t,s,i,r,n));break;case"^":if(d=t.lookup(l[1]),!d||ae(d)&&d.length===0){const u=l[4];u&&ae(u)&&(a+=this.renderTokens(u,t,s,i,r,n))}break;case">":if(!s)continue;d=ue(s)?s(l[1]):s[l[1]],d!=null&&(a+=this.render(d,t.view,s,r));break;case"&":d=t.lookup(l[1]),d!=null&&(a+=d);break;case"name":d=t.lookup(l[1]),d!=null&&(a+=it(d));break;case"text":a+=l[1];break}}return a}getConfigTags(e){return st(e)&&ae(e.tags)?e.tags:null}}function De(c){return c.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}const Me=new at,D={name:"MOJO Mustache",version:"1.0.0",tags:["{{","}}"],Scanner:rt,Context:we,Writer:at,escape:it,clearCache(){return Me.clearCache()},parse(c,e){return Me.parse(c,e)},render(c,e,t,s){if(typeof c!="string")throw new TypeError('Invalid template! Template should be a "string"');return e&&typeof e=="object"&&!e.getContextValue&&typeof e.toJSON!="function"&&(e=$.wrapData(e)),Me.render(c,e,t,s)}};class Ht{constructor(e){this.view=e,this.domListeners=[],this.debounceTimers=new Map}_enterDispatchChain(e){const t=e._mojoDispatch;let s;return e._mojoDispatch=new Promise(i=>{s=i}),{prior:t,done:s}}bind(e){if(this.unbind(),!e)return;const t=async a=>{const{prior:o,done:l}=this._enterDispatchChain(a);try{o&&await o;const d=a.target.closest("[data-action]");if(d&&this.shouldHandle(d,a)){const u=d.getAttribute("data-action");if(d.tagName==="A"&&a.preventDefault(),this.hideTooltip(d),await this.dispatch(u,a,d)){a.preventDefault(),a.stopPropagation(),a.handledByChild=!0;return}}const h=a.target.closest("a[href], [data-page]");if(h&&!h.hasAttribute("data-action")&&this.shouldHandle(h,a)){if(a.ctrlKey||a.metaKey||a.shiftKey||a.button===1)return;if(h.tagName==="A"){const u=h.getAttribute("href");if(u&&u!=="#"&&!u.startsWith("#")&&(this.view.isExternalLink(u)||h.hasAttribute("data-external")))return}this.hideTooltip(h),a.preventDefault(),a.stopPropagation(),a.handledByChild=!0,h.hasAttribute("data-page")?await this.view.handlePageNavigation(h):await this.view.handleHrefNavigation(h)}}finally{l()}},s=async a=>{const{prior:o,done:l}=this._enterDispatchChain(a);try{o&&await o;const d=a.target.closest("[data-change-action]");if(d&&this.shouldHandle(d,a)){const u=d.getAttribute("data-change-action");await this.dispatchChange(u,a,d)&&(a.stopPropagation(),a.handledByChild=!0);return}const h=a.target.closest("[data-action]");if(h&&this.isFormControl(h)&&this.shouldHandle(h,a)){const u=h.getAttribute("data-action");await this.dispatch(u,a,h)&&(a.stopPropagation(),a.handledByChild=!0)}}finally{l()}},i=a=>{const o=a.target.closest("[data-change-action]");if(o&&this.shouldHandle(o,a)&&a.target.matches('[data-filter="live-search"]')){const m=o.getAttribute("data-change-action"),p=parseInt(o.getAttribute("data-filter-debounce"))||300,f=`change-${m}-${o.getAttribute("data-container")||"default"}`;this.debounceTimers.has(f)&&clearTimeout(this.debounceTimers.get(f));const g=setTimeout(()=>{this.debounceTimers.delete(f),this.dispatchChange(m,a,o).then(b=>{b&&(a.stopPropagation(),a.handledByChild=!0)})},p);this.debounceTimers.set(f,g);return}const l=a.target.closest("[data-action]");if(!l||!this.isFormControl(l)||l.hasAttribute("data-change-action")||!this.shouldHandle(l,a))return;const d=l.getAttribute("data-action"),h=l.getAttribute("data-action-debounce"),u=h!=null&&parseInt(h)||0;if(u>0){const m=`action-${d}-${l.getAttribute("data-container")||"default"}`;this.debounceTimers.has(m)&&clearTimeout(this.debounceTimers.get(m));const p=setTimeout(()=>{this.debounceTimers.delete(m),this.dispatch(d,a,l).then(f=>{f&&(a.stopPropagation(),a.handledByChild=!0)})},u);this.debounceTimers.set(m,p);return}this.dispatch(d,a,l).then(m=>{m&&(a.stopPropagation(),a.handledByChild=!0)})},r=async a=>{if(a.target.matches('[data-filter="search"]'))return;const o=a.target.closest("[data-keydown-action]")||a.target.closest("[data-change-action]");if(!o)return;const{prior:l,done:d}=this._enterDispatchChain(a);try{if(l&&await l,!this.shouldHandle(o,a))return;let h=["Enter"];if(o.getAttribute("data-change-keys")&&(h=o.getAttribute("data-change-keys").split(",").map(u=>u.trim())),h.includes("*")||h.includes(a.key)){const u=o.getAttribute("data-keydown-action")||o.getAttribute("data-change-action");await this.dispatch(u,a,o)&&(a.preventDefault(),a.stopPropagation(),a.handledByChild=!0)}}finally{d()}},n=a=>{const o=a.target.closest("form[data-action]");if(!o||!this.shouldHandle(o,a))return;a.preventDefault();const l=o.getAttribute("data-action");this.dispatch(l,a,o)};e.addEventListener("click",t),e.addEventListener("change",s),e.addEventListener("input",i),e.addEventListener("keydown",r),e.addEventListener("submit",n),this.domListeners.push({el:e,type:"click",fn:t},{el:e,type:"change",fn:s},{el:e,type:"input",fn:i},{el:e,type:"keydown",fn:r},{el:e,type:"submit",fn:n})}unbind(){for(const{el:e,type:t,fn:s}of this.domListeners)e.removeEventListener(t,s);this.domListeners=[];for(const e of this.debounceTimers.values())clearTimeout(e);this.debounceTimers.clear()}hideDropdown(e){const s=e.closest(".dropdown-menu").closest(".dropdown");if(!s)return;const i=s.querySelector('[data-bs-toggle="dropdown"]');i&&window.bootstrap?.Dropdown&&window.bootstrap.Dropdown.getInstance(i)?.hide()}hideTooltip(e){if(e&&window.bootstrap?.Tooltip){const t=window.bootstrap.Tooltip.getInstance(e);t&&t.dispose()}}hideAllTooltips(){window.bootstrap?.Tooltip&&document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.hide()})}async dispatch(e,t,s){const i=this.view,r=l=>l.includes("-")?l.split("-").map(d=>d[0].toUpperCase()+d.slice(1)).join(""):l[0].toUpperCase()+l.slice(1),n=`handleAction${r(e)}`;if(typeof i[n]=="function")try{return t.preventDefault(),await i[n](t,s),!0}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const a=`onAction${r(e)}`;if(typeof i[a]=="function")try{return await i[a](t,s)?(s.closest(".dropdown-menu")&&this.hideDropdown(s),t.preventDefault(),t.stopPropagation(),!0):!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const o=`onPassThruAction${r(e)}`;if(typeof i[o]=="function")try{return await i[o](t,s),!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}if(typeof i.onActionDefault=="function")try{return await i.onActionDefault(e,t,s)}catch(l){return console.error(`Error in default action handler for ${e}:`,l),i.handleActionError(e,l,t,s),!0}return i.emit?.(`action:${e}`,{action:e,event:t,element:s}),!1}async dispatchChange(e,t,s){const i=this.view,n=`onChange${(a=>a.includes("-")?a.split("-").map(o=>o[0].toUpperCase()+o.slice(1)).join(""):a[0].toUpperCase()+a.slice(1))(e)}`;if(typeof i[n]=="function")try{return await i[n](t,s),!0}catch(a){return console.error(`Error in onChange ${e}:`,a),i.handleActionError?.(e,a,t,s),!0}return await this.dispatch(e,t,s)}isFormControl(e){if(!e||!e.tagName)return!1;const t=e.tagName;return t==="INPUT"||t==="TEXTAREA"||t==="SELECT"}shouldHandle(e,t){return!!(this.owns(e)||this.contains(e)&&!t.handledByChild)}owns(e){const t=this.view.element;if(!t||!t.contains(e))return!1;for(const s of Object.values(this.view.children))if(s.element&&s.element.contains(e))return!1;return!0}contains(e){return!!this.view.element&&this.view.element.contains(e)}}const Ie={on(c,e,t){this._listeners||(this._listeners={}),this._listeners[c]||(this._listeners[c]=[]);const s={callback:e,context:t,fn:t?e.bind(t):e};return this._listeners[c].push(s),this},off(c,e,t){return!this._listeners||!this._listeners[c]?this:(e?(this._listeners[c]=this._listeners[c].filter(s=>s.callback!==e||arguments.length===3&&s.context!==t),this._listeners[c].length===0&&delete this._listeners[c]):delete this._listeners[c],this)},once(c,e,t){const s=(...i)=>{this.off(c,s),(t?e.bind(t):e).apply(t||this,i)};return this.on(c,s),this},emit(c,...e){if(!this._listeners||!this._listeners[c])return this;const t=this._listeners[c].slice();for(const s of t)try{s.fn.apply(s.context||this,e)}catch(i){console&&console.error&&console.error(`Error in ${c} event handler:`,i)}return this}};typeof window<"u"&&(window.Mustache=D);class 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 Ht(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&&typeof e!="function"&&(this._templateCache=t),t}getContextValue(e){const t=$.getContextData(this,e);return e&&e.startsWith("data.")&&t&&typeof t=="object"?$.wrapData(t,this):e&&e.startsWith("model.")&&e!=="model"&&t&&typeof t=="object"&&typeof t.getContextValue!="function"?$.wrapData(t,null):t}async handlePageNavigation(e){const t=e.getAttribute("data-page"),s=e.getAttribute("data-params");let i={};if(s)try{i=JSON.parse(s)}catch{console.warn("Invalid JSON in data-params:",s)}const r=this.getApp();if(r){r.showPage(t,i);return}const n=this.findRouter();n&&typeof n.navigateToPage=="function"?await n.navigateToPage(t,i):console.error(`No router found for page navigation to '${t}'`)}async handleHrefNavigation(e){const t=e.getAttribute("href");if(this.isExternalLink(t)||e.hasAttribute("data-external"))return;const s=this.findRouter();if(s){if(s.options&&s.options.mode==="param"&&t.startsWith("?")){const r="/"+t;await s.navigate(r);return}if(s.options&&s.options.mode==="hash"&&t.startsWith("#")){await s.navigate(t);return}const i=this.hrefToRoutePath(t);await s.navigate(i)}else console.warn("No router found for navigation, using default behavior"),window.location.href=t}isExternalLink(e){return e?e.startsWith("/")&&this.getApp()?!e.startsWith(this.findRouter().basePath):e.startsWith("#")||e.startsWith("mailto:")||e.startsWith("tel:")||e.startsWith("http://")||e.startsWith("https://")||e.startsWith("//"):!0}hrefToRoutePath(e){if(e.startsWith("/")){const t=this.findRouter();if(t&&t.options&&t.options.base){const s=t.options.base;if(e.startsWith(s))return e.substring(s.length)||"/"}return e}return e.startsWith("./")?e.substring(2):e}findRouter(){return this.getApp(),this.app?.router||null}getApp(){if(this.app)return this.app;const e=[window.__app__,window.MOJO?.app,window.APP,window.app,window.WebApp,window.matchUUID?window[window.matchUUID]():window[window.matchUUID]];return this.app=e.find(t=>t&&typeof t.showPage=="function")||null,this.app}handleActionError(e,t,s,i){this.showError(`Action '${e}' failed: ${t}`,s,i)}escapeHtml(e){if(typeof e!="string")return e;const t=document.createElement("div");return t.textContent=e,t.innerHTML}contains(e){if(typeof e=="string"){if(!this.element)return!1;e=document.getElementById(e)}return e?this.element.contains(e):!1}initializeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.disposeTooltips(),[...this.element.querySelectorAll('[data-bs-toggle="tooltip"]')].map(t=>{const s=t.getAttribute("data-tooltip-theme"),i=t.getAttribute("data-tooltip-size");let r="";s&&(r+=`tooltip-${s} `),i&&(r+=`tooltip-${i}`);const n={},a=r.trim();return a&&(n.customClass=a),new window.bootstrap.Tooltip(t,n)})}disposeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.element.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.dispose()})}async showError(e){console.error(`View ${this.id} error:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showError=="function"){await t.showError(e);return}alert(`Error: ${e}`)}async showSuccess(e){this.debug&&console.log(`View ${this.id} success:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showSuccess=="function"){await t.showSuccess(e);return}alert(`Success: ${e}`)}async showInfo(e){console.info(`View ${this.id} info:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showInfo=="function"){await t.showInfo(e);return}alert(`Info: ${e}`)}async showWarning(e){console.warn(`View ${this.id} warning:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showWarning=="function"){await t.showWarning(e);return}alert(`Warning: ${e}`)}async onActionCopyToClipboard(e,t){try{const i=(t?.closest("[data-clipboard]")||t)?.getAttribute("data-clipboard")||"";if(!i)return!0;if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(i);else{const a=document.createElement("textarea");a.value=i,document.body.appendChild(a),a.select(),document.execCommand("copy"),document.body.removeChild(a)}const r=t.querySelector("i"),n=r&&r.className;return r&&(r.className="bi bi-check",setTimeout(()=>{r.className=n},1e3)),!0}catch(s){return console.warn("Copy to clipboard failed:",s),!0}}static _genId(){return`view_${Math.random().toString(36).substr(2,9)}`}static _warn(e,t){try{t?console.warn(`[View] ${e}:`,t):console.warn(`[View] ${e}`)}catch{}}}Object.assign(C.prototype,Ie);class x extends C{static _openDialogs=[];static _baseZIndex={backdrop:1050,modal:1055};static getFullscreenAwareZIndex(){return document.querySelector(".table-fullscreen")?{backdrop:10040,modal:10050}:x._baseZIndex}static fixAllBackdropStacking(){const e=document.querySelectorAll(".modal-backdrop"),t=x._openDialogs;if(e.length===0||t.length===0)return;const s=[...t].sort((n,a)=>(n._dialogZIndex||0)-(a._dialogZIndex||0)),r=document.querySelector(".table-fullscreen")||document.body;e.forEach((n,a)=>{if(a>=s.length)return;const o=s[a];n.style.zIndex=o._dialogZIndex-5,n.parentNode!==r&&r.appendChild(n)})}static updateAllBackdropStacking(){x.fixAllBackdropStacking()}static getMountTarget(){return document.querySelector(".table-fullscreen")||document.body}constructor(e={}){const t=e.id||`modal-${Date.now()}-${Math.random().toString(36).slice(2,7)}`;super({...e,id:t,tagName:"div",className:`modal ${e.fade!==!1?"fade":""} ${e.className||""}`.trim().replace(/\s+/g," "),attributes:{tabindex:"-1","aria-hidden":"true","aria-labelledby":e.labelledBy||`${t}-label`,"aria-describedby":e.describedBy||null,...e.attributes}}),this.modalId=t,this.title=e.title||"",this.titleId=`${this.modalId}-label`,this.size=e.size||"",this.centered=e.centered!==void 0?e.centered:!1,this.scrollable=e.scrollable!==void 0?e.scrollable:!1,this.autoSize=e.autoSize||e.size==="auto",this.backdrop=e.backdrop!==void 0?e.backdrop:!0,this.keyboard=e.keyboard!==void 0?e.keyboard:!0,this.focus=e.focus!==void 0?e.focus:!0,this.header=e.header!==void 0?e.header:!0,this.headerContent=e.headerContent||null,this.headerView=null,this.closeButton=e.closeButton!==void 0?e.closeButton:!0,this.contextMenu=e.contextMenu||null,this._processHeaderContent(this.headerContent),this.body=e.body??e.view??e.message??e.content??"",this.bodyView=null,this.bodyClass=e.bodyClass||"",this.noBodyPadding=e.noBodyPadding||!1,this.minWidth=e.minWidth||300,this.minHeight=e.minHeight||200,e.maxHeight&&(this.maxHeight=e.maxHeight),this.maxWidthPercent=e.maxWidthPercent||.9,this.maxHeightPercent=e.maxHeightPercent||.8,this._processBodyContent(this.body),this.footer=e.footer||null,this.footerView=null,this.footerClass=e.footerClass||"",this._processFooterContent(this.footer),this.buttons=e.buttons||null,this.onShow=e.onShow||null,this.onShown=e.onShown||null,this.onHide=e.onHide||null,this.onHidden=e.onHidden||null,this.onHidePrevented=e.onHidePrevented||null,this.autoShow=e.autoShow!==void 0?e.autoShow:!1,this.modal=null,this.relatedTarget=e.relatedTarget||null}_processBodyContent(e){if(e instanceof 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">
18
18
  ${await this.buildHeader()}
@@ -139,7 +139,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
139
139
  frameborder="0"
140
140
  ></iframe>
141
141
  </div>
142
- `}async onAfterMount(){await super.onAfterMount(),this._writeIframe()}onActionRefresh(){this._writeIframe()}_writeIframe(){const e=this.element?.querySelector(".mojo-html-preview-frame");if(!e)return;const t=e.contentDocument||e.contentWindow?.document;t&&(t.open(),t.write(this.html),t.close())}setHtml(e){this.html=e,this._writeIframe()}}class K{constructor(e={},t={}){this.endpoint=t.endpoint||this.constructor.endpoint||"",this.id=e.id||null,this.attributes={...e},this._=this.attributes,this.originalAttributes={...e},this.errors={},this.loading=!1,this.rest=ie,this.collection=t.collection||null,this.options={idAttribute:"id",timestamps:!0,...t}}getContextValue(e){return this.get(e)}get(e){return!e.includes(".")&&!e.includes("|")&&this[e]!==void 0?typeof this[e]=="function"?this[e]():this[e]:$.getContextData(this.attributes,e)}set(e,t,s={}){const i=JSON.parse(JSON.stringify(this.attributes));let r=!1;if(e!=null){if(typeof e=="object"){for(const[n,a]of Object.entries(e))r=this._setNestedAttribute(n,a)||r;e.id!==void 0&&(this.id=e.id)}else e==="id"?(this.id=t,r=!0):r=this._setNestedAttribute(e,t);if(r&&!s.silent)if(this.emit("change",this),typeof e=="string")this.emit(`change:${e}`,t,this);else for(const[n,a]of Object.entries(e)){const o=this._getNestedValue(n);JSON.stringify(this._getNestedValue(n,i))!==JSON.stringify(o)&&this.emit(`change:${n}`,o,this)}}}_setNestedAttribute(e,t){if(!e.includes(".")){const l=this.attributes[e];return this.attributes[e]=t,this[e]=t,l!==t}const s=e.split("."),i=s[0];(!this.attributes[i]||typeof this.attributes[i]!="object")&&(this.attributes[i]={}),(!this[i]||typeof this[i]!="object")&&(this[i]={});const r=this._getNestedValue(e);let n=this.attributes[i],a=this[i];for(let l=1;l<s.length-1;l++){const d=s[l];(!n[d]||typeof n[d]!="object")&&(n[d]={}),(!a[d]||typeof a[d]!="object")&&(a[d]={}),n=n[d],a=a[d]}const o=s[s.length-1];return n[o]=t,a[o]=t,JSON.stringify(r)!==JSON.stringify(t)}_getNestedValue(e,t=this.attributes){if(!e.includes("."))return t[e];const s=e.split(".");let i=t;for(const r of s){if(i==null||typeof i!="object")return;i=i[r]}return i}getData(){return this.attributes}getId(){return this.id}async fetch(e={}){let t=e.url;if(!t){const n=e.id||this.getId();if(!n&&this.options.requiresId!==!1)throw new Error("Model: ID is required for fetching");t=this.buildUrl(n)}const s=JSON.stringify({url:t,params:e.params});if(e.debounceMs&&e.debounceMs>0)return this._debouncedFetch(s,e);if(this.currentRequest&&this.currentRequestKey!==s&&(console.info("Model: Cancelling previous request for new parameters"),this.abortController?.abort(),this.currentRequest=null),this.currentRequest&&this.currentRequestKey===s)return console.info("Model: Duplicate request in progress, returning existing promise"),this.currentRequest;const i=Date.now();if(this.lastFetchTime&&i-this.lastFetchTime<100)return console.info("Model: Rate limited, skipping fetch"),this;this.loading=!0,this.errors={},this.lastFetchTime=i,this.currentRequestKey=s,this.abortController=new AbortController,this.currentRequest=this._performFetch(t,e,this.abortController);try{return await this.currentRequest}catch(n){if(n.name==="AbortError")return console.info("Model: Request was cancelled"),this;throw n}finally{this.currentRequest=null,this.currentRequestKey=null,this.abortController=null}}async _debouncedFetch(e,t){return this.debouncedFetchTimeout&&clearTimeout(this.debouncedFetchTimeout),this.cancel(),new Promise((s,i)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const r=await this.fetch({...t,debounceMs:0});s(r)}catch(r){i(r)}},t.debounceMs)})}async _performFetch(e,t,s){try{t.graph&&(!t.params||!t.params.graph)&&(t.params||(t.params={}),t.params.graph=t.graph);const i=await this.rest.GET(e,t.params,{signal:s.signal});return i.success?i.data.status?(this.originalAttributes={...this.attributes},i.data.data&&this.set(i.data.data),this.errors={}):this.errors=i.data:this.errors=i.errors||{},i}catch(i){if(i.name==="AbortError")throw console.info("Model: Fetch was cancelled"),i;return this.errors={fetch:i.message},{success:!1,error:i.message,status:i.status||500}}finally{this.loading=!1}}async save(e,t={}){const s=!this.id,i=s?"POST":"PUT",r=s?this.buildUrl():this.buildUrl(this.id);this.loading=!0,this.errors={};try{const n=await this.rest[i](r,e,t.params);return n.success?n.data.status?(this.originalAttributes={...this.attributes},this.set(n.data.data),this.errors={}):this.errors=n.data:this.errors=n.errors||{},n}catch(n){return{success:!1,error:n.message,status:n.status||500}}finally{this.loading=!1}}async destroy(e={}){if(!this.id)return this.errors={destroy:"Cannot destroy model without ID"},{success:!1,error:"Cannot destroy model without ID",status:400};const t=this.buildUrl(this.id);this.loading=!0,this.errors={};try{const s=await this.rest.DELETE(t,e.params);return s.success?(this.attributes={},this.originalAttributes={},this.id=null,this.errors={}):this.errors=s.errors||{},s}catch(s){return this.errors={destroy:s.message},{success:!1,error:s.message,status:s.status||500}}finally{this.loading=!1}}isDirty(){return JSON.stringify(this.attributes)!==JSON.stringify(this.originalAttributes)}getChangedAttributes(){const e={};for(const[t,s]of Object.entries(this.attributes))this.originalAttributes[t]!==s&&(e[t]=s);return e}reset(){for(const e of Object.keys(this.attributes))e in this.originalAttributes||delete this[e];for(const[e,t]of Object.entries(this.originalAttributes))this[e]=t;this.attributes={...this.originalAttributes},this._=this.attributes,this.errors={}}buildUrl(e=null){let t=this.endpoint;return e&&(t=t.endsWith("/")?`${t}${e}`:`${t}/${e}`),t}toJSON(){return{id:this.id,...this.attributes}}validate(){if(this.errors={},this.constructor.validations)for(const[e,t]of Object.entries(this.constructor.validations))this.validateField(e,t);return Object.keys(this.errors).length===0}validateField(e,t){const s=this.get(e),i=Array.isArray(t)?t:[t];for(const r of i)if(typeof r=="function"){const n=r(s,this);if(n!==!0){this.errors[e]=n||`${e} is invalid`;break}}else if(typeof r=="object"){if(r.required&&(s==null||s==="")){this.errors[e]=r.message||`${e} is required`;break}if(r.minLength&&s&&s.length<r.minLength){this.errors[e]=r.message||`${e} must be at least ${r.minLength} characters`;break}if(r.maxLength&&s&&s.length>r.maxLength){this.errors[e]=r.message||`${e} must be no more than ${r.maxLength} characters`;break}if(r.pattern&&s&&!r.pattern.test(s)){this.errors[e]=r.message||`${e} format is invalid`;break}}}static async find(e,t={}){const s=new this({},t);return await s.fetch({id:e,...t}),s}static create(e={},t={}){return new this(e,t)}cancel(){return this.currentRequest&&this.abortController?(console.info("Model: Manually cancelling active request"),this.abortController.abort(),!0):this.debouncedFetchTimeout?(clearTimeout(this.debouncedFetchTimeout),this.debouncedFetchTimeout=null,!0):!1}isFetching(){return!!this.currentRequest}async showError(e){await(await Promise.resolve().then(()=>N)).default.alert(e,"Error",{size:"md",class:"text-danger"})}}Object.assign(K.prototype,Me);class le{constructor(e={},t=null){if(Array.isArray(e)?(t=e,e=t||{}):t=t||e.data||[],this.ModelClass=e.ModelClass||K,this.models=[],this.loading=!1,this.errors={},this.meta={},this.rest=ie,t&&this.add(t),this.params={start:0,size:e.size||10,...e.params},this.endpoint=e.endpoint||this.ModelClass.endpoint||"",!this.endpoint){let s=new this.ModelClass;this.endpoint=s.endpoint}this.restEnabled=!!this.endpoint,e.restEnabled!==void 0&&(this.restEnabled=e.restEnabled),this.options={parse:!0,reset:!0,preloaded:!1,...e}}getModelName(){return this.ModelClass.name}async fetch(e={}){const t=JSON.stringify({...this.params,...e});if(this.currentRequest&&this.currentRequestKey!==t&&(console.info("Collection: Cancelling previous request for new parameters"),this.abortController?.abort(),this.currentRequest=null),this.currentRequest&&this.currentRequestKey===t)return console.info("Collection: Duplicate request in progress, returning existing promise"),this.currentRequest;const s=Date.now();if(this.options.rateLimiting&&this.lastFetchTime&&s-this.lastFetchTime<100)return console.info("Collection: Rate limited, skipping fetch"),{success:!0,message:"Rate limited, skipping fetch",data:{data:this.toJSON()}};if(!this.restEnabled)return console.info("Collection: REST disabled, skipping fetch"),{success:!0,message:"REST disabled, skipping fetch",data:{data:this.toJSON()}};if(this.options.preloaded&&this.models.length>0)return console.info("Collection: Using preloaded data, skipping fetch"),{success:!0,message:"Using preloaded data, skipping fetch",data:{data:this.toJSON()}};const r=this.buildUrl();this.loading=!0,this.errors={},this.lastFetchTime=s,this.currentRequestKey=t,this.abortController=new AbortController,this.currentRequest=this._performFetch(r,e,this.abortController);try{return await this.currentRequest}catch(n){return n.name==="AbortError"?(console.info("Collection: Request was cancelled"),{success:!1,error:"Request cancelled",status:0}):{success:!1,error:n.message,status:n.status||500}}finally{this.currentRequest=null,this.currentRequestKey=null,this.abortController=null}}async _performFetch(e,t,s){const i={...this.params,...t};console.log("Fetching collection data from",e,i);try{this.emit("fetch:start");const r=await this.rest.GET(e,i,{signal:s.signal});if(r.success&&r.data.status){const n=this.options.parse?this.parse(r):r.data;t.reset!==!1&&this.options.reset&&this.reset(),this.add(n,{silent:t.silent}),this.errors={},this.emit("fetch:success")}else r.data&&r.data.error?(this.errors=r.data,this.emit("fetch:error",{message:r.data.error,error:r.data})):(this.errors=r.errors||{},this.emit("fetch:error",{error:r.errors}));return r}catch(r){return r.name==="AbortError"?(console.info("Collection: Fetch was cancelled"),{success:!1,error:"Request cancelled",status:0}):(this.errors={fetch:r.message},this.emit("fetch:error",{message:r.message,error:r}),{success:!1,error:r.message,status:r.status||500})}finally{this.loading=!1,this.emit("fetch:end")}}async updateParams(e,t=!1,s=0){return await this.setParams({...this.params,...e},t,s)}async setParams(e,t=!1,s=0){return this.params=e,t&&this.restEnabled?s>0?(this.debouncedFetchTimeout&&clearTimeout(this.debouncedFetchTimeout),this.cancel(),new Promise((i,r)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const n=await this.fetch();i(n)}catch(n){r(n)}},s)})):this.fetch():Promise.resolve(this)}async fetchMore({pageDelta:e=1}={}){if(!this.restEnabled)return{success:!1,message:"REST disabled, cannot fetchMore"};const t=this.params.size||10,s=this.params.start||0,i=s+e*t;return this.meta&&typeof this.meta.count=="number"&&i>=this.meta.count?{success:!0,message:"No more results",data:{data:[],status:"ok",count:this.meta.count,start:s,size:t}}:(this.params={...this.params,start:i},this.emit("fetch:more",{start:i,pageDelta:e,collection:this}),this.fetch({reset:!1}))}async fetchOne(e,t={}){if(!e)return console.warn("Collection: fetchOne requires an ID"),null;if(!this.restEnabled)return console.info("Collection: REST disabled, cannot fetch single item"),null;try{const s=new this.ModelClass({id:e},{endpoint:this.endpoint,collection:this}),i=await s.fetch(t);if(i.success){if(t.addToCollection===!0){const r=this.get(s.id);r?t.merge!==!1&&r.set(s.attributes):this.add(s,{silent:t.silent})}return s}else return console.warn("Collection: fetchOne failed -",i.error||"Unknown error"),null}catch(s){return console.error("Collection: fetchOne error -",s.message),null}}async download(e="json",t={}){if(!this.restEnabled)return console.warn("Collection: REST is not enabled, cannot download from remote."),{success:!1,message:"Remote downloads are not enabled for this collection."};const s=this.buildUrl(),i={...this.params};delete i.start,delete i.size,i.download_format=e;const r=`export-${this.getModelName().toLowerCase()}`,n=this._buildDateRangeSuffix(i),a=`${r}${n}.${e}`,l={json:"application/json",csv:"text/csv"}[e]||"*/*";return i.filename=a,this.rest.download(s,i,{...t,filename:a,headers:{Accept:l}})}_buildDateRangeSuffix(e={}){const t=e.dr_start,s=e.dr_end;if(!t&&!s)return"";const i=a=>a?String(a).replace(/[^\dA-Za-z_-]/g,"-"):"",r=[],n=e.dr_field||"daterange";return r.push(i(n)),t&&r.push(`from-${i(e.dr_start)}`),s&&r.push(`to-${i(e.dr_end)}`),`-${r.filter(Boolean).join("-")}`}parse(e){return e.data&&Array.isArray(e.data.data)?(this.meta={size:e.data.size||10,start:e.data.start||0,count:e.data.count||0,status:e.data.status,graph:e.data.graph,...e.meta},e.data.data):Array.isArray(e.data)?e.data:Array.isArray(e)?e:[e]}add(e,t={}){const s=Array.isArray(e)?e:[e],i=[];for(const r of s){let n;r instanceof this.ModelClass?(n=r,n.collection||(n.collection=this)):n=new this.ModelClass(r,{endpoint:this.endpoint,collection:this});const a=this.models.findIndex(o=>o.id===n.id);a!==-1?t.merge!==!1&&this.models[a].set(n.attributes):(this.models.push(n),i.push(n))}return!t.silent&&i.length>0&&(this.emit("add",{models:i,collection:this}),this.emit("update",{collection:this})),i}remove(e,t={}){const s=Array.isArray(e)?e:[e],i=[];for(const r of s){let n=-1;if(typeof r=="string"||typeof r=="number"?n=this.models.findIndex(a=>a.id==r):n=this.models.indexOf(r),n!==-1){const a=this.models.splice(n,1)[0];a.collection===this&&(a.collection=null),i.push(a)}}return!t.silent&&i.length>0&&(this.emit("remove",{models:i,collection:this}),this.emit("update",{collection:this})),i}reset(e=null,t={}){const s=[...this.models];return this.models=[],e&&this.add(e,{silent:!0,...t}),t.silent||this.emit("reset",{collection:this,previousModels:s}),this}get(e){return this.models.find(t=>t.id==e)}at(e){return this.models[e]}length(){return this.models.length}isEmpty(){return this.models.length===0}where(e){return typeof e=="function"?this.models.filter(e):typeof e=="object"?this.models.filter(t=>Object.entries(e).every(([s,i])=>t.get(s)===i)):[]}findWhere(e){const t=this.where(e);return t.length>0?t[0]:void 0}forEach(e,t){if(typeof e!="function")throw new TypeError("Callback must be a function");return this.models.forEach((s,i)=>{e.call(t,s,i,this)}),this}sort(e,t={}){if(typeof e=="string"){const s=e;e=(i,r)=>{const n=i.get(s),a=r.get(s);return n<a?-1:n>a?1:0}}return this.models.sort(e),t.silent||this.emit("sort",{collection:this}),this}toJSON(){return this.models.map(e=>e.toJSON())}cancel(){return this.currentRequest&&this.abortController?(console.info("Collection: Manually cancelling active request"),this.abortController.abort(),!0):!1}isFetching(){return!!this.currentRequest}buildUrl(){return this.endpoint}*[Symbol.iterator](){for(const e of this.models)yield e}static fromArray(e,t=[],s={}){const i=new this({ModelClass:e,...s});return i.add(t,{silent:!0}),i}}Object.assign(le.prototype,Me);class Wt{constructor(e={}){this.options={containerId:"toast-container",position:"top-end",autohide:!0,defaultDelay:3e3,maxToasts:5,...e},this.toasts=new Map,this.toastCounter=0,this.init()}init(){this.createContainer()}createContainer(){let e=document.getElementById(this.options.containerId);e||(e=document.createElement("div"),e.id=this.options.containerId,e.className=`toast-container position-fixed ${this.getPositionClasses()}`,e.style.zIndex="1070",e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true"),document.body.appendChild(e)),this.container=e}getPositionClasses(){const e={"top-start":"top-0 start-0 p-3","top-center":"top-0 start-50 translate-middle-x p-3","top-end":"top-0 end-0 p-3","middle-start":"top-50 start-0 translate-middle-y p-3","middle-center":"top-50 start-50 translate-middle p-3","middle-end":"top-50 end-0 translate-middle-y p-3","bottom-start":"bottom-0 start-0 p-3","bottom-center":"bottom-0 start-50 translate-middle-x p-3","bottom-end":"bottom-0 end-0 p-3"};return e[this.options.position]||e["top-end"]}success(e,t={}){return this.show(e,"success",{icon:"bi-check-circle-fill",...t})}error(e,t={}){return this.show(e,"error",{icon:"bi-exclamation-triangle-fill",autohide:!0,...t})}info(e,t={}){return this.show(e,"info",{icon:"bi-info-circle-fill",...t})}warning(e,t={}){return this.show(e,"warning",{icon:"bi-exclamation-triangle-fill",...t})}plain(e,t={}){return this.show(e,"plain",{...t})}show(e,t="info",s={}){this.enforceMaxToasts();const i=`toast-${++this.toastCounter}`,r={title:this.getDefaultTitle(t),icon:this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,...s},n=this.createToastElement(i,e,t,r);if(this.container.appendChild(n),typeof bootstrap>"u")throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const a=new bootstrap.Toast(n,{autohide:r.autohide,delay:r.delay});return this.toasts.set(i,{element:n,bootstrap:a,type:t,message:e}),n.addEventListener("hidden.bs.toast",()=>{this.cleanup(i)}),a.show(),{id:i,hide:()=>{try{a.hide()}catch(o){console.warn("Error hiding toast:",o)}},dispose:()=>this.cleanup(i),updateProgress:s.updateProgress||null}}showView(e,t="info",s={}){this.enforceMaxToasts();const i=`toast-${++this.toastCounter}`,r={title:s.title||this.getDefaultTitle(t),icon:s.icon||this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,size:"md",...s},n=this.createViewToastElement(i,e,t,r);if(this.container.appendChild(n),typeof bootstrap>"u")throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const a=new bootstrap.Toast(n,{autohide:r.autohide,delay:r.delay});this.toasts.set(i,{element:n,bootstrap:a,type:t,view:e,message:"View toast"}),n.addEventListener("hidden.bs.toast",()=>{this.cleanupView(i)});const o=n.querySelector(".toast-view-body");return o&&e&&e.render(!0,o),a.show(),{id:i,view:e,hide:()=>{try{a.hide()}catch(l){console.warn("Error hiding view toast:",l)}},dispose:()=>this.cleanupView(i),updateProgress:l=>{e&&typeof e.updateProgress=="function"&&e.updateProgress(l)}}}createToastElement(e,t,s,i){const r=document.createElement("div");r.id=e,r.className=`toast toast-service-${s}${i.size?` toast-${i.size}`:""}`,r.setAttribute("role","alert"),r.setAttribute("aria-live","assertive"),r.setAttribute("aria-atomic","true");const n=i.title||i.icon?this.createToastHeader(i,s):"",a=this.createToastBody(t,i.icon&&!i.title);return r.innerHTML=`
142
+ `}async onAfterMount(){await super.onAfterMount(),this._writeIframe()}onActionRefresh(){this._writeIframe()}_writeIframe(){const e=this.element?.querySelector(".mojo-html-preview-frame");if(!e)return;const t=e.contentDocument||e.contentWindow?.document;t&&(t.open(),t.write(this.html),t.close())}setHtml(e){this.html=e,this._writeIframe()}}class K{constructor(e={},t={}){this.endpoint=t.endpoint||this.constructor.endpoint||"",this.id=e.id||null,this.attributes={...e},this._=this.attributes,this.originalAttributes={...e},this.errors={},this.loading=!1,this.rest=ie,this.collection=t.collection||null,this.options={idAttribute:"id",timestamps:!0,...t}}getContextValue(e){return this.get(e)}get(e){return!e.includes(".")&&!e.includes("|")&&this[e]!==void 0?typeof this[e]=="function"?this[e]():this[e]:$.getContextData(this.attributes,e)}set(e,t,s={}){const i=JSON.parse(JSON.stringify(this.attributes));let r=!1;if(e!=null){if(typeof e=="object"){for(const[n,a]of Object.entries(e))r=this._setNestedAttribute(n,a)||r;e.id!==void 0&&(this.id=e.id)}else e==="id"?(this.id=t,r=!0):r=this._setNestedAttribute(e,t);if(r&&!s.silent)if(this.emit("change",this),typeof e=="string")this.emit(`change:${e}`,t,this);else for(const[n,a]of Object.entries(e)){const o=this._getNestedValue(n);JSON.stringify(this._getNestedValue(n,i))!==JSON.stringify(o)&&this.emit(`change:${n}`,o,this)}}}_setNestedAttribute(e,t){if(!e.includes(".")){const l=this.attributes[e];return this.attributes[e]=t,this[e]=t,l!==t}const s=e.split("."),i=s[0];(!this.attributes[i]||typeof this.attributes[i]!="object")&&(this.attributes[i]={}),(!this[i]||typeof this[i]!="object")&&(this[i]={});const r=this._getNestedValue(e);let n=this.attributes[i],a=this[i];for(let l=1;l<s.length-1;l++){const d=s[l];(!n[d]||typeof n[d]!="object")&&(n[d]={}),(!a[d]||typeof a[d]!="object")&&(a[d]={}),n=n[d],a=a[d]}const o=s[s.length-1];return n[o]=t,a[o]=t,JSON.stringify(r)!==JSON.stringify(t)}_getNestedValue(e,t=this.attributes){if(!e.includes("."))return t[e];const s=e.split(".");let i=t;for(const r of s){if(i==null||typeof i!="object")return;i=i[r]}return i}getData(){return this.attributes}getId(){return this.id}async fetch(e={}){let t=e.url;if(!t){const n=e.id||this.getId();if(!n&&this.options.requiresId!==!1)throw new Error("Model: ID is required for fetching");t=this.buildUrl(n)}const s=JSON.stringify({url:t,params:e.params});if(e.debounceMs&&e.debounceMs>0)return this._debouncedFetch(s,e);if(this.currentRequest&&this.currentRequestKey!==s&&(console.info("Model: Cancelling previous request for new parameters"),this.abortController?.abort(),this.currentRequest=null),this.currentRequest&&this.currentRequestKey===s)return console.info("Model: Duplicate request in progress, returning existing promise"),this.currentRequest;const i=Date.now();if(this.lastFetchTime&&i-this.lastFetchTime<100)return console.info("Model: Rate limited, skipping fetch"),this;this.loading=!0,this.errors={},this.lastFetchTime=i,this.currentRequestKey=s,this.abortController=new AbortController,this.currentRequest=this._performFetch(t,e,this.abortController);try{return await this.currentRequest}catch(n){if(n.name==="AbortError")return console.info("Model: Request was cancelled"),this;throw n}finally{this.currentRequest=null,this.currentRequestKey=null,this.abortController=null}}async _debouncedFetch(e,t){return this.debouncedFetchTimeout&&clearTimeout(this.debouncedFetchTimeout),this.cancel(),new Promise((s,i)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const r=await this.fetch({...t,debounceMs:0});s(r)}catch(r){i(r)}},t.debounceMs)})}async _performFetch(e,t,s){try{t.graph&&(!t.params||!t.params.graph)&&(t.params||(t.params={}),t.params.graph=t.graph);const i=await this.rest.GET(e,t.params,{signal:s.signal});return i.success?i.data.status?(this.originalAttributes={...this.attributes},i.data.data&&this.set(i.data.data),this.errors={}):this.errors=i.data:this.errors=i.errors||{},i}catch(i){if(i.name==="AbortError")throw console.info("Model: Fetch was cancelled"),i;return this.errors={fetch:i.message},{success:!1,error:i.message,status:i.status||500}}finally{this.loading=!1}}async save(e,t={}){const s=!this.id,i=s?"POST":"PUT",r=s?this.buildUrl():this.buildUrl(this.id);this.loading=!0,this.errors={};try{const n=await this.rest[i](r,e,t.params);return n.success?n.data.status?(this.originalAttributes={...this.attributes},this.set(n.data.data),this.errors={}):this.errors=n.data:this.errors=n.errors||{},n}catch(n){return{success:!1,error:n.message,status:n.status||500}}finally{this.loading=!1}}async destroy(e={}){if(!this.id)return this.errors={destroy:"Cannot destroy model without ID"},{success:!1,error:"Cannot destroy model without ID",status:400};const t=this.buildUrl(this.id);this.loading=!0,this.errors={};try{const s=await this.rest.DELETE(t,e.params);return s.success?(this.attributes={},this.originalAttributes={},this.id=null,this.errors={}):this.errors=s.errors||{},s}catch(s){return this.errors={destroy:s.message},{success:!1,error:s.message,status:s.status||500}}finally{this.loading=!1}}isDirty(){return JSON.stringify(this.attributes)!==JSON.stringify(this.originalAttributes)}getChangedAttributes(){const e={};for(const[t,s]of Object.entries(this.attributes))this.originalAttributes[t]!==s&&(e[t]=s);return e}reset(){for(const e of Object.keys(this.attributes))e in this.originalAttributes||delete this[e];for(const[e,t]of Object.entries(this.originalAttributes))this[e]=t;this.attributes={...this.originalAttributes},this._=this.attributes,this.errors={}}buildUrl(e=null){let t=this.endpoint;return e&&(t=t.endsWith("/")?`${t}${e}`:`${t}/${e}`),t}toJSON(){return{id:this.id,...this.attributes}}validate(){if(this.errors={},this.constructor.validations)for(const[e,t]of Object.entries(this.constructor.validations))this.validateField(e,t);return Object.keys(this.errors).length===0}validateField(e,t){const s=this.get(e),i=Array.isArray(t)?t:[t];for(const r of i)if(typeof r=="function"){const n=r(s,this);if(n!==!0){this.errors[e]=n||`${e} is invalid`;break}}else if(typeof r=="object"){if(r.required&&(s==null||s==="")){this.errors[e]=r.message||`${e} is required`;break}if(r.minLength&&s&&s.length<r.minLength){this.errors[e]=r.message||`${e} must be at least ${r.minLength} characters`;break}if(r.maxLength&&s&&s.length>r.maxLength){this.errors[e]=r.message||`${e} must be no more than ${r.maxLength} characters`;break}if(r.pattern&&s&&!r.pattern.test(s)){this.errors[e]=r.message||`${e} format is invalid`;break}}}static async find(e,t={}){const s=new this({},t);return await s.fetch({id:e,...t}),s}static create(e={},t={}){return new this(e,t)}cancel(){return this.currentRequest&&this.abortController?(console.info("Model: Manually cancelling active request"),this.abortController.abort(),!0):this.debouncedFetchTimeout?(clearTimeout(this.debouncedFetchTimeout),this.debouncedFetchTimeout=null,!0):!1}isFetching(){return!!this.currentRequest}async showError(e){await(await Promise.resolve().then(()=>N)).default.alert(e,"Error",{size:"md",class:"text-danger"})}}Object.assign(K.prototype,Ie);class le{constructor(e={},t=null){if(Array.isArray(e)?(t=e,e=t||{}):t=t||e.data||[],this.ModelClass=e.ModelClass||K,this.models=[],this.loading=!1,this.errors={},this.meta={},this.rest=ie,t&&this.add(t),this.params={start:0,size:e.size||10,...e.params},this.endpoint=e.endpoint||this.ModelClass.endpoint||"",!this.endpoint){let s=new this.ModelClass;this.endpoint=s.endpoint}this.restEnabled=!!this.endpoint,e.restEnabled!==void 0&&(this.restEnabled=e.restEnabled),this.options={parse:!0,reset:!0,preloaded:!1,...e}}getModelName(){return this.ModelClass.name}async fetch(e={}){const t=JSON.stringify({...this.params,...e});if(this.currentRequest&&this.currentRequestKey!==t&&(console.info("Collection: Cancelling previous request for new parameters"),this.abortController?.abort(),this.currentRequest=null),this.currentRequest&&this.currentRequestKey===t)return console.info("Collection: Duplicate request in progress, returning existing promise"),this.currentRequest;const s=Date.now();if(this.options.rateLimiting&&this.lastFetchTime&&s-this.lastFetchTime<100)return console.info("Collection: Rate limited, skipping fetch"),{success:!0,message:"Rate limited, skipping fetch",data:{data:this.toJSON()}};if(!this.restEnabled)return console.info("Collection: REST disabled, skipping fetch"),{success:!0,message:"REST disabled, skipping fetch",data:{data:this.toJSON()}};if(this.options.preloaded&&this.models.length>0)return console.info("Collection: Using preloaded data, skipping fetch"),{success:!0,message:"Using preloaded data, skipping fetch",data:{data:this.toJSON()}};const r=this.buildUrl();this.loading=!0,this.errors={},this.lastFetchTime=s,this.currentRequestKey=t,this.abortController=new AbortController,this.currentRequest=this._performFetch(r,e,this.abortController);try{return await this.currentRequest}catch(n){return n.name==="AbortError"?(console.info("Collection: Request was cancelled"),{success:!1,error:"Request cancelled",status:0}):{success:!1,error:n.message,status:n.status||500}}finally{this.currentRequest=null,this.currentRequestKey=null,this.abortController=null}}async _performFetch(e,t,s){const i={...this.params,...t};console.log("Fetching collection data from",e,i);try{this.emit("fetch:start");const r=await this.rest.GET(e,i,{signal:s.signal});if(r.success&&r.data.status){const n=this.options.parse?this.parse(r):r.data;t.reset!==!1&&this.options.reset&&this.reset(),this.add(n,{silent:t.silent}),this.errors={},this.emit("fetch:success")}else r.data&&r.data.error?(this.errors=r.data,this.emit("fetch:error",{message:r.data.error,error:r.data})):(this.errors=r.errors||{},this.emit("fetch:error",{error:r.errors}));return r}catch(r){return r.name==="AbortError"?(console.info("Collection: Fetch was cancelled"),{success:!1,error:"Request cancelled",status:0}):(this.errors={fetch:r.message},this.emit("fetch:error",{message:r.message,error:r}),{success:!1,error:r.message,status:r.status||500})}finally{this.loading=!1,this.emit("fetch:end")}}async updateParams(e,t=!1,s=0){return await this.setParams({...this.params,...e},t,s)}async setParams(e,t=!1,s=0){return this.params=e,t&&this.restEnabled?s>0?(this.debouncedFetchTimeout&&clearTimeout(this.debouncedFetchTimeout),this.cancel(),new Promise((i,r)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const n=await this.fetch();i(n)}catch(n){r(n)}},s)})):this.fetch():Promise.resolve(this)}async fetchMore({pageDelta:e=1}={}){if(!this.restEnabled)return{success:!1,message:"REST disabled, cannot fetchMore"};const t=this.params.size||10,s=this.params.start||0,i=s+e*t;return this.meta&&typeof this.meta.count=="number"&&i>=this.meta.count?{success:!0,message:"No more results",data:{data:[],status:"ok",count:this.meta.count,start:s,size:t}}:(this.params={...this.params,start:i},this.emit("fetch:more",{start:i,pageDelta:e,collection:this}),this.fetch({reset:!1}))}async fetchOne(e,t={}){if(!e)return console.warn("Collection: fetchOne requires an ID"),null;if(!this.restEnabled)return console.info("Collection: REST disabled, cannot fetch single item"),null;try{const s=new this.ModelClass({id:e},{endpoint:this.endpoint,collection:this}),i=await s.fetch(t);if(i.success){if(t.addToCollection===!0){const r=this.get(s.id);r?t.merge!==!1&&r.set(s.attributes):this.add(s,{silent:t.silent})}return s}else return console.warn("Collection: fetchOne failed -",i.error||"Unknown error"),null}catch(s){return console.error("Collection: fetchOne error -",s.message),null}}async download(e="json",t={}){if(!this.restEnabled)return console.warn("Collection: REST is not enabled, cannot download from remote."),{success:!1,message:"Remote downloads are not enabled for this collection."};const s=this.buildUrl(),i={...this.params};delete i.start,delete i.size,i.download_format=e;const r=`export-${this.getModelName().toLowerCase()}`,n=this._buildDateRangeSuffix(i),a=`${r}${n}.${e}`,l={json:"application/json",csv:"text/csv"}[e]||"*/*";return i.filename=a,this.rest.download(s,i,{...t,filename:a,headers:{Accept:l}})}_buildDateRangeSuffix(e={}){const t=e.dr_start,s=e.dr_end;if(!t&&!s)return"";const i=a=>a?String(a).replace(/[^\dA-Za-z_-]/g,"-"):"",r=[],n=e.dr_field||"daterange";return r.push(i(n)),t&&r.push(`from-${i(e.dr_start)}`),s&&r.push(`to-${i(e.dr_end)}`),`-${r.filter(Boolean).join("-")}`}parse(e){return e.data&&Array.isArray(e.data.data)?(this.meta={size:e.data.size||10,start:e.data.start||0,count:e.data.count||0,status:e.data.status,graph:e.data.graph,...e.meta},e.data.data):Array.isArray(e.data)?e.data:Array.isArray(e)?e:[e]}add(e,t={}){const s=Array.isArray(e)?e:[e],i=[];for(const r of s){let n;r instanceof this.ModelClass?(n=r,n.collection||(n.collection=this)):n=new this.ModelClass(r,{endpoint:this.endpoint,collection:this});const a=this.models.findIndex(o=>o.id===n.id);a!==-1?t.merge!==!1&&this.models[a].set(n.attributes):(this.models.push(n),i.push(n))}return!t.silent&&i.length>0&&(this.emit("add",{models:i,collection:this}),this.emit("update",{collection:this})),i}remove(e,t={}){const s=Array.isArray(e)?e:[e],i=[];for(const r of s){let n=-1;if(typeof r=="string"||typeof r=="number"?n=this.models.findIndex(a=>a.id==r):n=this.models.indexOf(r),n!==-1){const a=this.models.splice(n,1)[0];a.collection===this&&(a.collection=null),i.push(a)}}return!t.silent&&i.length>0&&(this.emit("remove",{models:i,collection:this}),this.emit("update",{collection:this})),i}reset(e=null,t={}){const s=[...this.models];return this.models=[],e&&this.add(e,{silent:!0,...t}),t.silent||this.emit("reset",{collection:this,previousModels:s}),this}get(e){return this.models.find(t=>t.id==e)}at(e){return this.models[e]}length(){return this.models.length}isEmpty(){return this.models.length===0}where(e){return typeof e=="function"?this.models.filter(e):typeof e=="object"?this.models.filter(t=>Object.entries(e).every(([s,i])=>t.get(s)===i)):[]}findWhere(e){const t=this.where(e);return t.length>0?t[0]:void 0}forEach(e,t){if(typeof e!="function")throw new TypeError("Callback must be a function");return this.models.forEach((s,i)=>{e.call(t,s,i,this)}),this}sort(e,t={}){if(typeof e=="string"){const s=e;e=(i,r)=>{const n=i.get(s),a=r.get(s);return n<a?-1:n>a?1:0}}return this.models.sort(e),t.silent||this.emit("sort",{collection:this}),this}toJSON(){return this.models.map(e=>e.toJSON())}cancel(){return this.currentRequest&&this.abortController?(console.info("Collection: Manually cancelling active request"),this.abortController.abort(),!0):!1}isFetching(){return!!this.currentRequest}buildUrl(){return this.endpoint}*[Symbol.iterator](){for(const e of this.models)yield e}static fromArray(e,t=[],s={}){const i=new this({ModelClass:e,...s});return i.add(t,{silent:!0}),i}}Object.assign(le.prototype,Ie);class Wt{constructor(e={}){this.options={containerId:"toast-container",position:"top-end",autohide:!0,defaultDelay:3e3,maxToasts:5,...e},this.toasts=new Map,this.toastCounter=0,this.init()}init(){this.createContainer()}createContainer(){let e=document.getElementById(this.options.containerId);e||(e=document.createElement("div"),e.id=this.options.containerId,e.className=`toast-container position-fixed ${this.getPositionClasses()}`,e.style.zIndex="1070",e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true"),document.body.appendChild(e)),this.container=e}getPositionClasses(){const e={"top-start":"top-0 start-0 p-3","top-center":"top-0 start-50 translate-middle-x p-3","top-end":"top-0 end-0 p-3","middle-start":"top-50 start-0 translate-middle-y p-3","middle-center":"top-50 start-50 translate-middle p-3","middle-end":"top-50 end-0 translate-middle-y p-3","bottom-start":"bottom-0 start-0 p-3","bottom-center":"bottom-0 start-50 translate-middle-x p-3","bottom-end":"bottom-0 end-0 p-3"};return e[this.options.position]||e["top-end"]}success(e,t={}){return this.show(e,"success",{icon:"bi-check-circle-fill",...t})}error(e,t={}){return this.show(e,"error",{icon:"bi-exclamation-triangle-fill",autohide:!0,...t})}info(e,t={}){return this.show(e,"info",{icon:"bi-info-circle-fill",...t})}warning(e,t={}){return this.show(e,"warning",{icon:"bi-exclamation-triangle-fill",...t})}plain(e,t={}){return this.show(e,"plain",{...t})}show(e,t="info",s={}){this.enforceMaxToasts();const i=`toast-${++this.toastCounter}`,r={title:this.getDefaultTitle(t),icon:this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,...s},n=this.createToastElement(i,e,t,r);if(this.container.appendChild(n),typeof bootstrap>"u")throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const a=new bootstrap.Toast(n,{autohide:r.autohide,delay:r.delay});return this.toasts.set(i,{element:n,bootstrap:a,type:t,message:e}),n.addEventListener("hidden.bs.toast",()=>{this.cleanup(i)}),a.show(),{id:i,hide:()=>{try{a.hide()}catch(o){console.warn("Error hiding toast:",o)}},dispose:()=>this.cleanup(i),updateProgress:s.updateProgress||null}}showView(e,t="info",s={}){this.enforceMaxToasts();const i=`toast-${++this.toastCounter}`,r={title:s.title||this.getDefaultTitle(t),icon:s.icon||this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,size:"md",...s},n=this.createViewToastElement(i,e,t,r);if(this.container.appendChild(n),typeof bootstrap>"u")throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const a=new bootstrap.Toast(n,{autohide:r.autohide,delay:r.delay});this.toasts.set(i,{element:n,bootstrap:a,type:t,view:e,message:"View toast"}),n.addEventListener("hidden.bs.toast",()=>{this.cleanupView(i)});const o=n.querySelector(".toast-view-body");return o&&e&&e.render(!0,o),a.show(),{id:i,view:e,hide:()=>{try{a.hide()}catch(l){console.warn("Error hiding view toast:",l)}},dispose:()=>this.cleanupView(i),updateProgress:l=>{e&&typeof e.updateProgress=="function"&&e.updateProgress(l)}}}createToastElement(e,t,s,i){const r=document.createElement("div");r.id=e,r.className=`toast toast-service-${s}${i.size?` toast-${i.size}`:""}`,r.setAttribute("role","alert"),r.setAttribute("aria-live","assertive"),r.setAttribute("aria-atomic","true");const n=i.title||i.icon?this.createToastHeader(i,s):"",a=this.createToastBody(t,i.icon&&!i.title);return r.innerHTML=`
143
143
  ${n}
144
144
  ${a}
145
145
  `,r}createViewToastElement(e,t,s,i){const r=document.createElement("div");r.id=e,r.className=`toast toast-service-${s}${i.size?` toast-${i.size}`:""}`,r.setAttribute("role","alert"),r.setAttribute("aria-live","assertive"),r.setAttribute("aria-atomic","true");const n=i.title||i.icon?this.createToastHeader(i,s):"",a=this.createViewToastBody();return r.innerHTML=`
@@ -660,14 +660,14 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
660
660
  </div>
661
661
  </div>
662
662
  </div>
663
- `}buildFieldHTML(e){const{type:t,columns:s,class:i=""}=e;let r="";const n=Q&&typeof Q.getRenderer=="function"?Q.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(([v,_])=>`${v}="${this.escapeHtml(_)}"`).join(" "),b=this.getFieldId(s),y={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:b,name:s,type:t,fieldValue: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 v={...y,showToggle:!!e.showToggle,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,v)}if(t==="password"){const v={...y,showToggle:e.showToggle!==!1,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,v)}return D.render(this.templates.input,y)}renderTextareaField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,rows:l=3,cols:d,class:h="",attributes:u={},help:m=e.helpText||e.help||""}=e,p=`${this.options.inputClass} ${h}`.trim(),f=this.errors[t],g=this.getFieldValue(t)??i,b=Object.entries(u).map(([_,A])=>`${_}="${this.escapeHtml(A)}"`).join(" "),y=this.getFieldId(t),v={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,v)}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(([v,_])=>`${v}="${this.escapeHtml(_)}"`).join(" "),b=this.getFieldId(t),y={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:b,name:t,fieldValue:f,label:s?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(([v,_])=>`${v}="${this.escapeHtml(_)}"`).join(" "),y={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,fieldValue:m,label:s?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,v=`form-select ${d}`.trim(),_=this.errors[t],E=this.getFieldValue(t)??r,j=Object.entries(h).map(([I,H])=>`${I}="${this.escapeHtml(H)}"`).join(" "),M=this.getFieldId(t);let R=[...i];if(m!==void 0&&p!==void 0){const I=f!==void 0?f:1,H=this.generateSelectOptions(m,p,I,{format:g,prefix:b,suffix:y});R=[...R,...H]}let ne="";Array.isArray(R)&&(ne=R.map(I=>{if(typeof I=="string"){const H=I===E?"selected":"";return`<option value="${this.escapeHtml(I)}" ${H}>${this.escapeHtml(I)}</option>`}else if(I&&typeof I=="object"){const H=I.value==E?"selected":"";return`<option value="${this.escapeHtml(I.value)}" ${H}>${this.escapeHtml(I.label||I.text||I.value)}</option>`}return""}).join(""));const be=l?`
663
+ `}buildFieldHTML(e){const{type:t,columns:s,class:i=""}=e;let r="";const n=Q&&typeof Q.getRenderer=="function"?Q.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(([v,_])=>`${v}="${this.escapeHtml(_)}"`).join(" "),b=this.getFieldId(s),y={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:b,name:s,type:t,fieldValue: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 v={...y,showToggle:!!e.showToggle,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,v)}if(t==="password"){const v={...y,showToggle:e.showToggle!==!1,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,v)}return D.render(this.templates.input,y)}renderTextareaField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,rows:l=3,cols:d,class:h="",attributes:u={},help:m=e.helpText||e.help||""}=e,p=`${this.options.inputClass} ${h}`.trim(),f=this.errors[t],g=this.getFieldValue(t)??i,b=Object.entries(u).map(([_,A])=>`${_}="${this.escapeHtml(A)}"`).join(" "),y=this.getFieldId(t),v={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,v)}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(([v,_])=>`${v}="${this.escapeHtml(_)}"`).join(" "),b=this.getFieldId(t),y={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:b,name:t,fieldValue:f,label:s?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(([v,_])=>`${v}="${this.escapeHtml(_)}"`).join(" "),y={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,fieldValue:m,label:s?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,v=`form-select ${d}`.trim(),_=this.errors[t],E=this.getFieldValue(t)??r,j=Object.entries(h).map(([M,H])=>`${M}="${this.escapeHtml(H)}"`).join(" "),I=this.getFieldId(t);let R=[...i];if(m!==void 0&&p!==void 0){const M=f!==void 0?f:1,H=this.generateSelectOptions(m,p,M,{format:g,prefix:b,suffix:y});R=[...R,...H]}let ne="";Array.isArray(R)&&(ne=R.map(M=>{if(typeof M=="string"){const H=M===E?"selected":"";return`<option value="${this.escapeHtml(M)}" ${H}>${this.escapeHtml(M)}</option>`}else if(M&&typeof M=="object"){const H=M.value==E?"selected":"";return`<option value="${this.escapeHtml(M.value)}" ${H}>${this.escapeHtml(M.label||M.text||M.value)}</option>`}return""}).join(""));const be=l?`
664
664
  <input type="text"
665
665
  class="form-control form-control-sm mb-2"
666
666
  placeholder="Search options..."
667
667
  data-filter="live-search"
668
668
  data-change-action="filter-select-options"
669
- data-target="${M}">
670
- `:"",ye={labelClass:this.options.labelClass,inputClass:v,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:M,name:t,label:s?this.escapeHtml(s):null,help:u?this.escapeHtml(u):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:_?this.escapeHtml(_):null,searchInput:l?be:null,optionsHTML:ne,required:n,disabled:a,multiple:o,attrs:j};return D.render(this.templates.select,ye)}renderMultiSelectField(e){const{name:t,label:s,options:i=[],value:r=[],required:n=!1,disabled:a=!1,maxHeight:o=300,help:l=e.helpText||e.help||""}=e,d=e.placeholder||e.placeHolder||"Select...";this.getFieldId(t);const h=this.errors[t],u=e.value??this.getFieldValue(t)??r;return`
669
+ data-target="${I}">
670
+ `:"",ye={labelClass:this.options.labelClass,inputClass:v,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:I,name:t,label:s?this.escapeHtml(s):null,help:u?this.escapeHtml(u):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:_?this.escapeHtml(_):null,searchInput:l?be:null,optionsHTML:ne,required:n,disabled:a,multiple:o,attrs:j};return D.render(this.templates.select,ye)}renderMultiSelectField(e){const{name:t,label:s,options:i=[],value:r=[],required:n=!1,disabled:a=!1,maxHeight:o=300,help:l=e.helpText||e.help||""}=e,d=e.placeholder||e.placeHolder||"Select...";this.getFieldId(t);const h=this.errors[t],u=e.value??this.getFieldValue(t)??r;return`
671
671
  <div class="multiselect-placeholder"
672
672
  data-field-name="${t}"
673
673
  data-field-type="multiselect"
@@ -709,7 +709,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
709
709
  ${d?`<div class="${this.options.helpClass}">${this.escapeHtml(d)}</div>`:""}
710
710
  ${h?`<div class="${this.options.errorClass}">${this.escapeHtml(h)}</div>`:""}
711
711
  </div>
712
- `}renderDateField(e){return this.renderInputField(e,"date")}renderDateTimeField(e){return this.renderInputField(e,"datetime-local")}renderTimeField(e){return this.renderInputField(e,"time")}renderFileField(e){const{name:t,label:s,required:i=!1,disabled:r=!1,multiple:n=!1,accept:a="*/*",class:o="",attributes:l={},help:d=e.helpText||e.help||""}=e,h=`${this.options.inputClass} ${o}`.trim(),u=this.errors[t],m=Object.entries(l).map(([g,b])=>`${g}="${this.escapeHtml(b)}"`).join(" "),p=this.getFieldId(t),f={labelClass:this.options.labelClass,inputClass:h,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:p,name:t,label:s?this.escapeHtml(s):null,help:d?this.escapeHtml(d):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:u?this.escapeHtml(u):null,accept:a,required:i,disabled:r,multiple:n,attrs:m};return D.render(this.templates.file,f)}renderImageField(e){const{name:t,label:s,required:i=!1,disabled:r=!1,accept:n="image/*",class:a="",attributes:o={},help:l=e.helpText||e.help||"",size:d="md",allowDrop:h=!0,placeholder:u="Drop image here or click to upload"}=e,m=`${this.options.inputClass} ${a}`.trim(),p=this.errors[t],f=this.getFieldId(t),g=`${f}_dropzone`,b=`${f}_preview`,y={xs:{width:48,height:48,containerClass:"image-field-xs"},sm:{width:96,height:96,containerClass:"image-field-sm"},md:{width:150,height:150,containerClass:"image-field-md"},lg:{width:200,height:200,containerClass:"image-field-lg"},xl:{width:300,height:300,containerClass:"image-field-xl"}},v=y[d]||y.md,_=Object.entries(o).map(([M,R])=>`${M}="${this.escapeHtml(R)}"`).join(" "),A=this.getFieldValue(t),E=this.extractImageUrl(A,d),j={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:f,name:t,label:s?this.escapeHtml(s):null,help:l?this.escapeHtml(l):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:p?this.escapeHtml(p):null,dropZoneId:g,previewId:b,containerClass:v.containerClass,width:v.width,height:v.height,accept:n,imageUrl:E,placeholderText:r?"No image":this.escapeHtml(u),cursor:r?"default":"pointer",allowDrop:h,showRemove:!r,required:i,disabled:r,attrs:_};return D.render(this.templates.image,j)}extractImageUrl(e,t="md"){if(!e)return null;if(typeof e=="string")return e;if(typeof e=="object"&&e.url){if(e.renditions){const s={xs:["thumbnail_sm","thumbnail","square_sm"],sm:["thumbnail","thumbnail_sm","square_sm"],md:["thumbnail_md","thumbnail","thumbnail_lg"],lg:["thumbnail_lg","thumbnail_md","thumbnail"],xl:["original","thumbnail_lg"]},i=s[t]||s.md;for(const r of i)if(e.renditions[r]&&e.renditions[r].url)return e.renditions[r].url}return e.url}return null}renderColorField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=`${this.options.inputClass} ${l}`.trim(),m=this.errors[t],p=this.getFieldValue(t)??i,f=Object.entries(d).map(([y,v])=>`${y}="${this.escapeHtml(v)}"`).join(" "),g=this.getFieldId(t),b={labelClass:this.options.labelClass,inputClass:u,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,fieldValue:this.escapeHtml(p),label:s?this.escapeHtml(s):null,placeholder:r?this.escapeHtml(r):null,help:h?this.escapeHtml(h):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:m?this.escapeHtml(m):null,required:n,disabled:a,readonly:o,attrs:f};return D.render(this.templates.color,b)}renderRangeField(e){const{name:t,label:s,min:i=0,max:r=100,step:n=1,value:a=i,disabled:o=!1,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=`${this.options.inputClass} ${l}`.trim(),m=this.errors[t],p=this.getFieldValue(t)??a,f=Object.entries(d).map(([y,v])=>`${y}="${this.escapeHtml(v)}"`).join(" "),g=this.getFieldId(t),b={labelClass:this.options.labelClass,inputClass:u,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,label:s?this.escapeHtml(s):null,help:h?this.escapeHtml(h):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:m?this.escapeHtml(m):null,min:i,max:r,step:n,fieldValue:p,disabled:o,attrs:f};return D.render(this.templates.range,b)}renderHiddenField(e){const{name:t,value:s=""}=e,i=this.getFieldValue(t)??s;return`<input type="hidden" name="${t}" value="${this.escapeHtml(i)}">`}renderButton(e){const{name:t="",label:s="Button",type:i="button",action:r="",class:n="btn-secondary",disabled:a=!1,attributes:o={}}=e;let l=r;l||(i==="submit"?l="submit-form":i==="reset"&&(l="reset-form"));const d=Object.entries(o).map(([h,u])=>`${h}="${this.escapeHtml(u)}"`).join(" ");return`
712
+ `}renderDateField(e){return this.renderInputField(e,"date")}renderDateTimeField(e){return this.renderInputField(e,"datetime-local")}renderTimeField(e){return this.renderInputField(e,"time")}renderFileField(e){const{name:t,label:s,required:i=!1,disabled:r=!1,multiple:n=!1,accept:a="*/*",class:o="",attributes:l={},help:d=e.helpText||e.help||""}=e,h=`${this.options.inputClass} ${o}`.trim(),u=this.errors[t],m=Object.entries(l).map(([g,b])=>`${g}="${this.escapeHtml(b)}"`).join(" "),p=this.getFieldId(t),f={labelClass:this.options.labelClass,inputClass:h,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:p,name:t,label:s?this.escapeHtml(s):null,help:d?this.escapeHtml(d):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:u?this.escapeHtml(u):null,accept:a,required:i,disabled:r,multiple:n,attrs:m};return D.render(this.templates.file,f)}renderImageField(e){const{name:t,label:s,required:i=!1,disabled:r=!1,accept:n="image/*",class:a="",attributes:o={},help:l=e.helpText||e.help||"",size:d="md",allowDrop:h=!0,placeholder:u="Drop image here or click to upload"}=e,m=`${this.options.inputClass} ${a}`.trim(),p=this.errors[t],f=this.getFieldId(t),g=`${f}_dropzone`,b=`${f}_preview`,y={xs:{width:48,height:48,containerClass:"image-field-xs"},sm:{width:96,height:96,containerClass:"image-field-sm"},md:{width:150,height:150,containerClass:"image-field-md"},lg:{width:200,height:200,containerClass:"image-field-lg"},xl:{width:300,height:300,containerClass:"image-field-xl"}},v=y[d]||y.md,_=Object.entries(o).map(([I,R])=>`${I}="${this.escapeHtml(R)}"`).join(" "),A=this.getFieldValue(t),E=this.extractImageUrl(A,d),j={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:f,name:t,label:s?this.escapeHtml(s):null,help:l?this.escapeHtml(l):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:p?this.escapeHtml(p):null,dropZoneId:g,previewId:b,containerClass:v.containerClass,width:v.width,height:v.height,accept:n,imageUrl:E,placeholderText:r?"No image":this.escapeHtml(u),cursor:r?"default":"pointer",allowDrop:h,showRemove:!r,required:i,disabled:r,attrs:_};return D.render(this.templates.image,j)}extractImageUrl(e,t="md"){if(!e)return null;if(typeof e=="string")return e;if(typeof e=="object"&&e.url){if(e.renditions){const s={xs:["thumbnail_sm","thumbnail","square_sm"],sm:["thumbnail","thumbnail_sm","square_sm"],md:["thumbnail_md","thumbnail","thumbnail_lg"],lg:["thumbnail_lg","thumbnail_md","thumbnail"],xl:["original","thumbnail_lg"]},i=s[t]||s.md;for(const r of i)if(e.renditions[r]&&e.renditions[r].url)return e.renditions[r].url}return e.url}return null}renderColorField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=`${this.options.inputClass} ${l}`.trim(),m=this.errors[t],p=this.getFieldValue(t)??i,f=Object.entries(d).map(([y,v])=>`${y}="${this.escapeHtml(v)}"`).join(" "),g=this.getFieldId(t),b={labelClass:this.options.labelClass,inputClass:u,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,fieldValue:this.escapeHtml(p),label:s?this.escapeHtml(s):null,placeholder:r?this.escapeHtml(r):null,help:h?this.escapeHtml(h):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:m?this.escapeHtml(m):null,required:n,disabled:a,readonly:o,attrs:f};return D.render(this.templates.color,b)}renderRangeField(e){const{name:t,label:s,min:i=0,max:r=100,step:n=1,value:a=i,disabled:o=!1,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=`${this.options.inputClass} ${l}`.trim(),m=this.errors[t],p=this.getFieldValue(t)??a,f=Object.entries(d).map(([y,v])=>`${y}="${this.escapeHtml(v)}"`).join(" "),g=this.getFieldId(t),b={labelClass:this.options.labelClass,inputClass:u,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,label:s?this.escapeHtml(s):null,help:h?this.escapeHtml(h):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:m?this.escapeHtml(m):null,min:i,max:r,step:n,fieldValue:p,disabled:o,attrs:f};return D.render(this.templates.range,b)}renderHiddenField(e){const{name:t,value:s=""}=e,i=this.getFieldValue(t)??s;return`<input type="hidden" name="${t}" value="${this.escapeHtml(i)}">`}renderButton(e){const{name:t="",label:s="Button",type:i="button",action:r="",class:n="btn-secondary",disabled:a=!1,attributes:o={}}=e;let l=r;l||(i==="submit"?l="submit-form":i==="reset"&&(l="reset-form"));const d=Object.entries(o).map(([h,u])=>`${h}="${this.escapeHtml(u)}"`).join(" ");return`
713
713
  <button
714
714
  type="button"
715
715
  ${t?`name="${t}"`:""}
@@ -798,14 +798,14 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
798
798
  ${v?`<div class="${this.options.helpClass}">${this.escapeHtml(v)}</div>`:""}
799
799
  ${A?`<div class="${this.options.errorClass}">${this.escapeHtml(A)}</div>`:""}
800
800
  </div>
801
- `}renderDateRangeField(e){const{name:t,startName:s,endName:i,fieldName:r,label:n,startDate:a="",endDate:o="",precision:l="day",placeholder:d,required:h=!1,disabled:u=!1,readonly:m=!1,min:p=null,max:f=null,format:g=null,displayFormat:b=null,outputFormat:y="date",separator:v=" – ",months:_=null,presets:A=null,autoApply:E=!0,inline:j=!1,help:M=e.helpText||e.help||""}=e,R=this.getFieldId(t||s||"daterange"),ne=this.errors[t],be=s||(t?t+"_start":""),ye=i||(t?t+"_end":""),I=this.getFieldValue(be)||a,H=this.getFieldValue(ye)||o;return`
801
+ `}renderDateRangeField(e){const{name:t,startName:s,endName:i,fieldName:r,label:n,startDate:a="",endDate:o="",precision:l="day",placeholder:d,required:h=!1,disabled:u=!1,readonly:m=!1,min:p=null,max:f=null,format:g=null,displayFormat:b=null,outputFormat:y="date",separator:v=" – ",months:_=null,presets:A=null,autoApply:E=!0,inline:j=!1,help:I=e.helpText||e.help||""}=e,R=this.getFieldId(t||s||"daterange"),ne=this.errors[t],be=s||(t?t+"_start":""),ye=i||(t?t+"_end":""),M=this.getFieldValue(be)||a,H=this.getFieldValue(ye)||o;return`
802
802
  <div class="mojo-form-control">
803
803
  ${n?`<label for="${R}" class="${this.options.labelClass}">${this.escapeHtml(n)}${h?'<span class="text-danger">*</span>':""}${this.renderTooltipIcon(e)}</label>`:""}
804
804
  <div class="date-range-picker-placeholder"
805
805
  data-field-name="${t||s||"daterange"}"
806
806
  data-field-type="daterange"
807
- data-field-config='${JSON.stringify({name:t,startName:s,endName:i,fieldName:r,startDate:I,endDate:H,precision:l,placeholder:d,min:p,max:f,format:g,displayFormat:b,outputFormat:y,separator:v,months:_,presets:A,autoApply:E,inline:j,disabled:u,readonly:m,required:h})}'></div>
808
- ${M?`<div class="${this.options.helpClass}">${this.escapeHtml(M)}</div>`:""}
807
+ data-field-config='${JSON.stringify({name:t,startName:s,endName:i,fieldName:r,startDate:M,endDate:H,precision:l,placeholder:d,min:p,max:f,format:g,displayFormat:b,outputFormat:y,separator:v,months:_,presets:A,autoApply:E,inline:j,disabled:u,readonly:m,required:h})}'></div>
808
+ ${I?`<div class="${this.options.helpClass}">${this.escapeHtml(I)}</div>`:""}
809
809
  ${ne?`<div class="${this.options.errorClass}">${this.escapeHtml(ne)}</div>`:""}
810
810
  </div>
811
811
  `}renderTimePickerField(e){const{name:t,label:s,value:i="",format:r="24h",step:n=1,min:a=null,max:o=null,placeholder:l,required:d=!1,disabled:h=!1,readonly:u=!1,timezone:m=!1,timezones:p=null,outputFormat:f="string",autoApply:g=!1,inline:b=!1,help:y=e.helpText||e.help||""}=e,v=this.getFieldId(t),_=this.errors[t],A=this.getFieldValue(t)??i;return`
@@ -818,7 +818,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
818
818
  ${y?`<div class="${this.options.helpClass}">${this.escapeHtml(y)}</div>`:""}
819
819
  ${_?`<div class="${this.options.errorClass}">${this.escapeHtml(_)}</div>`:""}
820
820
  </div>
821
- `}renderDateTimePickerField(e){const{name:t,label:s,value:i="",displayFormat:r=null,timeFormat:n="24h",timeStep:a=1,min:o=null,max:l=null,placeholder:d,required:h=!1,disabled:u=!1,readonly:m=!1,disabledDates:p=[],firstDay:f=1,lang:g="en-US",timezone:b=!1,timezones:y=null,outputFormat:v="string",autoApply:_=!1,inline:A=!1,help:E=e.helpText||e.help||""}=e,j=this.getFieldId(t),M=this.errors[t],R=this.getFieldValue(t)??i;return`
821
+ `}renderDateTimePickerField(e){const{name:t,label:s,value:i="",displayFormat:r=null,timeFormat:n="24h",timeStep:a=1,min:o=null,max:l=null,placeholder:d,required:h=!1,disabled:u=!1,readonly:m=!1,disabledDates:p=[],firstDay:f=1,lang:g="en-US",timezone:b=!1,timezones:y=null,outputFormat:v="string",autoApply:_=!1,inline:A=!1,help:E=e.helpText||e.help||""}=e,j=this.getFieldId(t),I=this.errors[t],R=this.getFieldValue(t)??i;return`
822
822
  <div class="mojo-form-control">
823
823
  ${s?`<label for="${j}" class="${this.options.labelClass}">${this.escapeHtml(s)}${h?'<span class="text-danger">*</span>':""}${this.renderTooltipIcon(e)}</label>`:""}
824
824
  <div class="datetime-picker-placeholder"
@@ -826,7 +826,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
826
826
  data-field-type="datetimepicker"
827
827
  data-field-config='${JSON.stringify({name:t,value:R,displayFormat:r,timeFormat:n,timeStep:a,min:o,max:l,placeholder:d,disabledDates:p,firstDay:f,lang:g,timezone:b,timezones:y,outputFormat:v,autoApply:_,inline:A,disabled:u,readonly:m,required:h})}'></div>
828
828
  ${E?`<div class="${this.options.helpClass}">${this.escapeHtml(E)}</div>`:""}
829
- ${M?`<div class="${this.options.errorClass}">${this.escapeHtml(M)}</div>`:""}
829
+ ${I?`<div class="${this.options.errorClass}">${this.escapeHtml(I)}</div>`:""}
830
830
  </div>
831
831
  `}renderChecklistDropdownField(e){const t=this.getFieldId(e.name),s=this.getFieldValue(e.name)??[],i={fieldId:t,fieldName:e.name,buttonText:e.buttonText||"Select Options",buttonIcon:e.buttonIcon||"bi-chevron-down",buttonClass:e.buttonClass||"btn btn-outline-secondary btn-sm dropdown-toggle",dropdownClass:e.dropdownClass||"dropdown-menu p-2",minWidth:e.minWidth||"200px",options:e.options.map(r=>({value:r.value,label:r.label,id:`${e.name}-${r.value}`,checked:s.includes(r.value)}))};return D.render(this.templates.checklistdropdown,i)}renderButtonGroupField(e){const t=this.getFieldId(e.name),s=this.getFieldValue(e.name)??e.value,i={fieldId:t,fieldName:e.name,size:e.size||"sm",variant:e.variant||"outline-primary",options:e.options.map(r=>({value:r.value,label:r.label,action:r.action,active:r.value===s,buttonClass:this.getButtonClass(r.value===s,e.variant)}))};return D.render(this.templates.buttongroup,i)}getButtonClass(e,t="outline-primary"){return e?`btn btn-${t.replace("outline-","")}`:`btn btn-${t}`}renderComboField(e){const{name:t,label:s,value:i="",required:r=!1,disabled:n=!1,maxHeight:a=300,help:o=e.helpText||e.help||""}=e,l=e.placeholder||e.placeHolder||"Type or select...",d=e.allowCustom!==!1;this.getFieldId(t);const h=this.errors[t],u=e.value??this.getFieldValue(t)??i;return`
832
832
  <div class="mojo-form-control">
@@ -1127,7 +1127,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1127
1127
  ${!this.required&&!this.disabled&&!this.readonly?'<button type="button" class="mojo-date-trigger-clear" data-clear aria-label="Clear" tabindex="-1">&#x2715;</button>':""}
1128
1128
  </button>
1129
1129
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(this.currentValue)}" data-hidden-value />
1130
- `}async onAfterRender(){this.inline?this._mountCalendarInline():this._wireTrigger()}_wireTrigger(){const e=this.element.querySelector("[data-trigger]"),t=this.element.querySelector("[data-clear]");e&&(e.addEventListener("click",s=>{s.target.closest("[data-clear]")||this._togglePopover(e)}),t&&t.addEventListener("click",s=>{s.stopPropagation(),this._setValue("")}))}_togglePopover(e){if(!(this.disabled||this.readonly)){if(this._popover?this._popover.setAnchor(e):this._popover=new _e({anchor:e}),this._popover.isOpen()){this._popover.close();return}this._calendar||(this._calendar=this._buildCalendar()),this._popover.setContent(this._calendar.element),this._popover.open(),this._calendar.render(!1)}}_mountCalendarInline(){const e=this.element.querySelector("[data-cal-host]");e&&(this._calendar||(this._calendar=this._buildCalendar()),e.appendChild(this._calendar.element),this._calendar.render(!1))}_buildCalendar(){const e=new Be({precision:this.precision,mode:"single",months:1,value:this.currentValue||null,min:this.min,max:this.max,disabledDates:this.disabledDates,firstDay:this.firstDay,locale:this.lang});return e.on("select",({value:t})=>{this._setValue(t),this.autoApply&&this._popover&&this._popover.isOpen()&&this._popover.close()}),e}_setValue(e){const t=this.currentValue;let s="";if(e){const a=V(e,this.precision);a&&(s=U(a,this.precision))}this.currentValue=s;const i=this._displayText(s),r=this.element.querySelector("[data-trigger-text]");r&&(r.textContent=i||this.placeholder,r.classList.toggle("is-empty",!s));const n=this.element.querySelector("[data-hidden-value]");n&&(n.value=s),this._calendar&&this._calendar.setValue(s),t!==s&&(this.emit("change",{value:s,formatted:i,oldValue:t}),this.emit("date:changed",{value:s,oldValue:t}))}_displayText(e){if(!e)return"";const t=V(e,this.precision);return t?de(t,this._stripIncompatibleTokens(this.displayFormat)):""}_stripIncompatibleTokens(e){return this.precision==="day"?e:this.precision==="month"?e.replace(/\bDD\b|\bD\b/g,"").replace(/[\s\-\/]+$/,"").trim():this.precision==="year"?e.replace(/MMMM|MMM|MM|M|DD|D/g,"").replace(/[\s\-\/]+$/,"").trim()||"YYYY":e}setValue(e){this._setValue(e)}getValue(){return this.currentValue}getFormattedValue(){return this._displayText(this.currentValue)}clear(){this._setValue("")}setMin(e){this.min=e,this._calendar&&this._calendar.setMin(e)}setMax(e){this.max=e,this._calendar&&this._calendar.setMax(e)}setEnabled(e){this.disabled=!e;const t=this.element.querySelector("[data-trigger]");t&&(t.disabled=!e),!e&&this._popover&&this._popover.isOpen()&&this._popover.close()}setReadonly(e){this.readonly=e,e&&this._popover&&this._popover.isOpen()&&this._popover.close()}focus(){const e=this.element.querySelector("[data-trigger]");e&&e.focus()}show(){const e=this.element.querySelector("[data-trigger]");e&&this._togglePopover(e)}hide(){this._popover&&this._popover.close()}getFormValue(){return this.getValue()}async setFormValue(e){this._setValue(e)}hasError(){return!1}_inputId(){return this.name?`mojo-date-${this.name}-${this.id}`:`mojo-date-${this.id}`}_attr(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}async onBeforeDestroy(){this._popover&&(this._popover.destroy(),this._popover=null),this._calendar=null,await super.onBeforeDestroy()}static create(e={}){return new Ue(e)}}function ds(){return[{label:"Today",range:()=>{const c=F();return{start:c,end:c}}},{label:"Yesterday",range:()=>{const c=F(),e=xe(c,-1);return{start:e,end:e}}},{label:"Last 7 days",range:()=>{const c=F();return{start:xe(c,-6),end:c}}},{label:"Last 30 days",range:()=>{const c=F();return{start:xe(c,-29),end:c}}},{label:"Last 90 days",range:()=>{const c=F();return{start:xe(c,-89),end:c}}},{divider:!0},{label:"This month",range:()=>{const c=F();return{start:{y:c.y,m:c.m,d:1},end:c}}},{label:"Last month",range:()=>{const c=F(),e=re({y:c.y,m:c.m,d:1},-1),t=re(e,1);t.d=0;const s=new Date(t.y,t.m,0).getDate();return{start:{...e,d:1},end:{...e,d:s}}}},{label:"This year",range:()=>{const c=F();return{start:{y:c.y,m:1,d:1},end:c}}}]}function hs(){return[{label:"This month",range:()=>{const c=F();return{start:{y:c.y,m:c.m},end:{y:c.y,m:c.m}}}},{label:"Last month",range:()=>{const c=F(),e=re({y:c.y,m:c.m},-1);return{start:e,end:e}}},{label:"Last 3 months",range:()=>{const c=F();return{start:re({y:c.y,m:c.m},-2),end:{y:c.y,m:c.m}}}},{label:"Last 6 months",range:()=>{const c=F();return{start:re({y:c.y,m:c.m},-5),end:{y:c.y,m:c.m}}}},{label:"YTD",range:()=>{const c=F();return{start:{y:c.y,m:1},end:{y:c.y,m:c.m}}}},{label:"Last 12 months",range:()=>{const c=F();return{start:re({y:c.y,m:c.m},-11),end:{y:c.y,m:c.m}}}}]}function us(){return[{label:"This year",range:()=>{const c=F();return{start:{y:c.y},end:{y:c.y}}}},{label:"Last year",range:()=>{const c=F();return{start:{y:c.y-1},end:{y:c.y-1}}}},{label:"Last 3 years",range:()=>{const c=F();return{start:{y:c.y-2},end:{y:c.y}}}},{label:"Last 5 years",range:()=>{const c=F();return{start:{y:c.y-4},end:{y:c.y}}}},{label:"Last 10 years",range:()=>{const c=F();return{start:{y:c.y-9},end:{y:c.y}}}}]}function xe(c,e){if(!c)return null;const t=new Date(c.y,c.m-1,c.d+e);return{y:t.getFullYear(),m:t.getMonth()+1,d:t.getDate()}}function _t(c){return c==="year"?us():c==="month"?hs():ds()}class ms extends C{constructor(e={}){const{precision:t="day",presets:s="default",eyebrow:i="Quick range",...r}=e;super({tagName:"div",className:"mojo-calendar-presets",...r}),this.precision=t,this.eyebrow=i,this.activeIndex=-1,this.presets=s===!0||s==="default"?_t(t):Array.isArray(s)?s:_t(t)}setActive(e){this.activeIndex=e,this._highlight()}async renderTemplate(){return""}async onAfterRender(){this._renderInto(this.element)}_renderInto(e){if(e.innerHTML="",this.eyebrow){const t=document.createElement("div");t.className="mojo-calendar-presets-eyebrow",t.textContent=this.eyebrow,e.appendChild(t)}this.presets.forEach((t,s)=>{if(t.divider){const r=document.createElement("div");r.className="mojo-calendar-presets-divider",e.appendChild(r);return}const i=document.createElement("button");i.type="button",i.className="mojo-calendar-preset"+(this.activeIndex===s?" is-active":""),i.dataset.presetIndex=String(s),i.textContent=t.label,e.appendChild(i)}),e.addEventListener("click",t=>{const s=t.target.closest(".mojo-calendar-preset");if(!s)return;const i=parseInt(s.dataset.presetIndex,10),r=this.presets[i];if(!r||typeof r.range!="function")return;const n=r.range();this.activeIndex=i,this._highlight();const a=this.precision==="year"?mt:this.precision==="month"?He:B;this.emit("preset:select",{index:i,label:r.label,start:a(n.start),end:a(n.end),parsed:n})})}_highlight(){this.element&&this.element.querySelectorAll(".mojo-calendar-preset").forEach(e=>{const t=parseInt(e.dataset.presetIndex,10);e.classList.toggle("is-active",t===this.activeIndex)})}}const xt={day:"MMM DD, YYYY",month:"MMM YYYY",year:"YYYY"};class We extends C{constructor(e={}){const{name:t,startName:s,endName:i,fieldName:r,startDate:n="",endDate:a="",precision:o="day",format:l=null,displayFormat:d=null,outputFormat:h="date",min:u=null,max:m=null,placeholder:p=null,disabled:f=!1,readonly:g=!1,required:b=!1,class:y="",inputClass:v="form-control",inline:_=!1,separator:A=" – ",autoApply:E=!0,months:j=null,presets:M=null,...R}=e;super({tagName:"div",className:`mojo-date-picker mojo-date-range-picker mojo-date-picker-${o} ${y}`.trim(),...R}),this.name=t,this.startName=s,this.endName=i,this.fieldName=r,this.precision=o,this.format=l,this.displayFormat=d||xt[o]||xt.day,this.outputFormat=h,this.min=u,this.max=m,this.placeholder=p??this._defaultPlaceholder(o),this.disabled=f,this.readonly=g,this.required=b,this.inputClass=v,this.inline=_,this.separator=A,this.autoApply=E,this.months=j??(o==="day"?2:1),this.presets=M,this.currentStartDate=n||"",this.currentEndDate=a||"",this._calendar=null,this._popover=null,this._presetSidebar=null}_defaultPlaceholder(e){return e==="year"?"Select year range...":e==="month"?"Select month range...":"Select date range..."}async renderTemplate(){const e=this._inputId(),t=this._displayText(),s=!this.currentStartDate,i=this.startName||(this.name?`${this.name}_start`:""),r=this.endName||(this.name?`${this.name}_end`:""),n=`
1130
+ `}async onAfterRender(){this.inline?this._mountCalendarInline():this._wireTrigger()}_wireTrigger(){const e=this.element.querySelector("[data-trigger]"),t=this.element.querySelector("[data-clear]");e&&(e.addEventListener("click",s=>{s.target.closest("[data-clear]")||this._togglePopover(e)}),t&&t.addEventListener("click",s=>{s.stopPropagation(),this._setValue("")}))}_togglePopover(e){if(!(this.disabled||this.readonly)){if(this._popover?this._popover.setAnchor(e):this._popover=new _e({anchor:e}),this._popover.isOpen()){this._popover.close();return}this._calendar||(this._calendar=this._buildCalendar()),this._popover.setContent(this._calendar.element),this._popover.open(),this._calendar.render(!1)}}_mountCalendarInline(){const e=this.element.querySelector("[data-cal-host]");e&&(this._calendar||(this._calendar=this._buildCalendar()),e.appendChild(this._calendar.element),this._calendar.render(!1))}_buildCalendar(){const e=new Be({precision:this.precision,mode:"single",months:1,value:this.currentValue||null,min:this.min,max:this.max,disabledDates:this.disabledDates,firstDay:this.firstDay,locale:this.lang});return e.on("select",({value:t})=>{this._setValue(t),this.autoApply&&this._popover&&this._popover.isOpen()&&this._popover.close()}),e}_setValue(e){const t=this.currentValue;let s="";if(e){const a=V(e,this.precision);a&&(s=U(a,this.precision))}this.currentValue=s;const i=this._displayText(s),r=this.element.querySelector("[data-trigger-text]");r&&(r.textContent=i||this.placeholder,r.classList.toggle("is-empty",!s));const n=this.element.querySelector("[data-hidden-value]");n&&(n.value=s),this._calendar&&this._calendar.setValue(s),t!==s&&(this.emit("change",{value:s,formatted:i,oldValue:t}),this.emit("date:changed",{value:s,oldValue:t}))}_displayText(e){if(!e)return"";const t=V(e,this.precision);return t?de(t,this._stripIncompatibleTokens(this.displayFormat)):""}_stripIncompatibleTokens(e){return this.precision==="day"?e:this.precision==="month"?e.replace(/\bDD\b|\bD\b/g,"").replace(/[\s\-\/]+$/,"").trim():this.precision==="year"?e.replace(/MMMM|MMM|MM|M|DD|D/g,"").replace(/[\s\-\/]+$/,"").trim()||"YYYY":e}setValue(e){this._setValue(e)}getValue(){return this.currentValue}getFormattedValue(){return this._displayText(this.currentValue)}clear(){this._setValue("")}setMin(e){this.min=e,this._calendar&&this._calendar.setMin(e)}setMax(e){this.max=e,this._calendar&&this._calendar.setMax(e)}setEnabled(e){this.disabled=!e;const t=this.element.querySelector("[data-trigger]");t&&(t.disabled=!e),!e&&this._popover&&this._popover.isOpen()&&this._popover.close()}setReadonly(e){this.readonly=e,e&&this._popover&&this._popover.isOpen()&&this._popover.close()}focus(){const e=this.element.querySelector("[data-trigger]");e&&e.focus()}show(){const e=this.element.querySelector("[data-trigger]");e&&this._togglePopover(e)}hide(){this._popover&&this._popover.close()}getFormValue(){return this.getValue()}async setFormValue(e){this._setValue(e)}hasError(){return!1}_inputId(){return this.name?`mojo-date-${this.name}-${this.id}`:`mojo-date-${this.id}`}_attr(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}async onBeforeDestroy(){this._popover&&(this._popover.destroy(),this._popover=null),this._calendar=null,await super.onBeforeDestroy()}static create(e={}){return new Ue(e)}}function ds(){return[{label:"Today",range:()=>{const c=F();return{start:c,end:c}}},{label:"Yesterday",range:()=>{const c=F(),e=xe(c,-1);return{start:e,end:e}}},{label:"Last 7 days",range:()=>{const c=F();return{start:xe(c,-6),end:c}}},{label:"Last 30 days",range:()=>{const c=F();return{start:xe(c,-29),end:c}}},{label:"Last 90 days",range:()=>{const c=F();return{start:xe(c,-89),end:c}}},{divider:!0},{label:"This month",range:()=>{const c=F();return{start:{y:c.y,m:c.m,d:1},end:c}}},{label:"Last month",range:()=>{const c=F(),e=re({y:c.y,m:c.m,d:1},-1),t=re(e,1);t.d=0;const s=new Date(t.y,t.m,0).getDate();return{start:{...e,d:1},end:{...e,d:s}}}},{label:"This year",range:()=>{const c=F();return{start:{y:c.y,m:1,d:1},end:c}}}]}function hs(){return[{label:"This month",range:()=>{const c=F();return{start:{y:c.y,m:c.m},end:{y:c.y,m:c.m}}}},{label:"Last month",range:()=>{const c=F(),e=re({y:c.y,m:c.m},-1);return{start:e,end:e}}},{label:"Last 3 months",range:()=>{const c=F();return{start:re({y:c.y,m:c.m},-2),end:{y:c.y,m:c.m}}}},{label:"Last 6 months",range:()=>{const c=F();return{start:re({y:c.y,m:c.m},-5),end:{y:c.y,m:c.m}}}},{label:"YTD",range:()=>{const c=F();return{start:{y:c.y,m:1},end:{y:c.y,m:c.m}}}},{label:"Last 12 months",range:()=>{const c=F();return{start:re({y:c.y,m:c.m},-11),end:{y:c.y,m:c.m}}}}]}function us(){return[{label:"This year",range:()=>{const c=F();return{start:{y:c.y},end:{y:c.y}}}},{label:"Last year",range:()=>{const c=F();return{start:{y:c.y-1},end:{y:c.y-1}}}},{label:"Last 3 years",range:()=>{const c=F();return{start:{y:c.y-2},end:{y:c.y}}}},{label:"Last 5 years",range:()=>{const c=F();return{start:{y:c.y-4},end:{y:c.y}}}},{label:"Last 10 years",range:()=>{const c=F();return{start:{y:c.y-9},end:{y:c.y}}}}]}function xe(c,e){if(!c)return null;const t=new Date(c.y,c.m-1,c.d+e);return{y:t.getFullYear(),m:t.getMonth()+1,d:t.getDate()}}function _t(c){return c==="year"?us():c==="month"?hs():ds()}class ms extends C{constructor(e={}){const{precision:t="day",presets:s="default",eyebrow:i="Quick range",...r}=e;super({tagName:"div",className:"mojo-calendar-presets",...r}),this.precision=t,this.eyebrow=i,this.activeIndex=-1,this.presets=s===!0||s==="default"?_t(t):Array.isArray(s)?s:_t(t)}setActive(e){this.activeIndex=e,this._highlight()}async renderTemplate(){return""}async onAfterRender(){this._renderInto(this.element)}_renderInto(e){if(e.innerHTML="",this.eyebrow){const t=document.createElement("div");t.className="mojo-calendar-presets-eyebrow",t.textContent=this.eyebrow,e.appendChild(t)}this.presets.forEach((t,s)=>{if(t.divider){const r=document.createElement("div");r.className="mojo-calendar-presets-divider",e.appendChild(r);return}const i=document.createElement("button");i.type="button",i.className="mojo-calendar-preset"+(this.activeIndex===s?" is-active":""),i.dataset.presetIndex=String(s),i.textContent=t.label,e.appendChild(i)}),e.addEventListener("click",t=>{const s=t.target.closest(".mojo-calendar-preset");if(!s)return;const i=parseInt(s.dataset.presetIndex,10),r=this.presets[i];if(!r||typeof r.range!="function")return;const n=r.range();this.activeIndex=i,this._highlight();const a=this.precision==="year"?mt:this.precision==="month"?He:B;this.emit("preset:select",{index:i,label:r.label,start:a(n.start),end:a(n.end),parsed:n})})}_highlight(){this.element&&this.element.querySelectorAll(".mojo-calendar-preset").forEach(e=>{const t=parseInt(e.dataset.presetIndex,10);e.classList.toggle("is-active",t===this.activeIndex)})}}const xt={day:"MMM DD, YYYY",month:"MMM YYYY",year:"YYYY"};class We extends C{constructor(e={}){const{name:t,startName:s,endName:i,fieldName:r,startDate:n="",endDate:a="",precision:o="day",format:l=null,displayFormat:d=null,outputFormat:h="date",min:u=null,max:m=null,placeholder:p=null,disabled:f=!1,readonly:g=!1,required:b=!1,class:y="",inputClass:v="form-control",inline:_=!1,separator:A=" – ",autoApply:E=!0,months:j=null,presets:I=null,...R}=e;super({tagName:"div",className:`mojo-date-picker mojo-date-range-picker mojo-date-picker-${o} ${y}`.trim(),...R}),this.name=t,this.startName=s,this.endName=i,this.fieldName=r,this.precision=o,this.format=l,this.displayFormat=d||xt[o]||xt.day,this.outputFormat=h,this.min=u,this.max=m,this.placeholder=p??this._defaultPlaceholder(o),this.disabled=f,this.readonly=g,this.required=b,this.inputClass=v,this.inline=_,this.separator=A,this.autoApply=E,this.months=j??(o==="day"?2:1),this.presets=I,this.currentStartDate=n||"",this.currentEndDate=a||"",this._calendar=null,this._popover=null,this._presetSidebar=null}_defaultPlaceholder(e){return e==="year"?"Select year range...":e==="month"?"Select month range...":"Select date range..."}async renderTemplate(){const e=this._inputId(),t=this._displayText(),s=!this.currentStartDate,i=this.startName||(this.name?`${this.name}_start`:""),r=this.endName||(this.name?`${this.name}_end`:""),n=`
1131
1131
  ${this.name?`<input type="hidden" name="${this._attr(this.name)}" value="${this._attr(this.getCombinedValue())}" data-combined-value />`:""}
1132
1132
  ${i?`<input type="hidden" name="${this._attr(i)}" value="${this._attr(this.currentStartDate)}" data-start-value />`:""}
1133
1133
  ${r?`<input type="hidden" name="${this._attr(r)}" value="${this._attr(this.currentEndDate)}" data-end-value />`:""}
@@ -1193,7 +1193,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1193
1193
  ${!this.required&&!this.disabled&&!this.readonly?'<button type="button" class="mojo-time-trigger-clear" data-clear aria-label="Clear" tabindex="-1">&#x2715;</button>':""}
1194
1194
  </button>
1195
1195
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(i)}" data-hidden-value />
1196
- `}async onAfterRender(){this.inline?this._mountInline():this._wireTrigger()}_wireTrigger(){const e=this.element.querySelector("[data-trigger]"),t=this.element.querySelector("[data-clear]");e&&(e.addEventListener("click",s=>{s.target.closest("[data-clear]")||this._togglePopover(e)}),t&&t.addEventListener("click",s=>{s.stopPropagation(),this.clear()}))}_togglePopover(e){if(this.disabled||this.readonly)return;if(this._popover?this._popover.setAnchor(e):this._popover=new _e({anchor:e,classNames:"mojo-time-popover"}),this._popover.isOpen()){this._popover.close();return}const t=this._buildSpinnerContent();this._popover.setContent(t),this._popover.open(),this.timezone&&this._mountTimezoneSelect()}_mountInline(){const e=this.element.querySelector("[data-time-host]");if(!e)return;const t=this._buildSpinnerContent();e.appendChild(t),this.timezone&&this._mountTimezoneSelect()}_buildSpinnerContent(){const e=document.createElement("div");e.className="mojo-time-popover-inner";const t=document.createElement("div");t.className="mojo-time-stepper-row";const s=this.currentTime||{hours:0,minutes:0},i=this._hourDisplay(s.hours);t.appendChild(this._buildStepper("hour",i,"Hour"));const r=document.createElement("div");if(r.className="mojo-time-stepper-sep",r.textContent=":",t.appendChild(r),t.appendChild(this._buildStepper("minute",Ye(s.minutes),"Minute")),this.format==="12h"&&t.appendChild(this._buildAmPmToggle(s.hours)),e.appendChild(t),this.timezone){const n=document.createElement("div");n.className="mojo-time-tz-host",n.setAttribute("data-tz-host",""),e.appendChild(n)}if(this.showFooter){const n=document.createElement("div");n.className="mojo-time-foot";const a=document.createElement("button");a.type="button",a.className="btn btn-link btn-sm mojo-time-now",a.textContent="Now",a.addEventListener("click",l=>{l.preventDefault();const d=new Date;this._commitTime({hours:d.getHours(),minutes:d.getMinutes()}),this._refreshSpinnerDisplay()}),n.appendChild(a);const o=document.createElement("button");o.type="button",o.className="btn btn-primary btn-sm mojo-time-apply",o.textContent="Set",o.addEventListener("click",l=>{l.preventDefault(),this.currentTime||this._commitTime({hours:0,minutes:0}),this._popover&&this._popover.isOpen()&&this._popover.close()}),n.appendChild(o),e.appendChild(n)}return this._spinner=e,e}_buildStepper(e,t,s){const i=document.createElement("div");i.className=`mojo-time-stepper mojo-time-stepper-${e}`;const r=document.createElement("button");r.type="button",r.className="mojo-time-stepper-btn",r.setAttribute("aria-label",`Increase ${s.toLowerCase()}`),r.innerHTML='<i class="bi bi-chevron-up" aria-hidden="true"></i>',r.addEventListener("click",l=>{l.preventDefault(),this._step(e,1)});const n=document.createElement("input");n.type="text",n.className="mojo-time-stepper-value",n.value=t,n.setAttribute("inputmode","numeric"),n.setAttribute("aria-label",s),n.maxLength=2,n.addEventListener("focus",()=>n.select()),n.addEventListener("keydown",l=>this._onValueKey(e,n,l)),n.addEventListener("blur",()=>this._onValueBlur(e,n));const a=document.createElement("button");a.type="button",a.className="mojo-time-stepper-btn",a.setAttribute("aria-label",`Decrease ${s.toLowerCase()}`),a.innerHTML='<i class="bi bi-chevron-down" aria-hidden="true"></i>',a.addEventListener("click",l=>{l.preventDefault(),this._step(e,-1)});const o=document.createElement("div");return o.className="mojo-time-stepper-label",o.textContent=s,i.appendChild(r),i.appendChild(n),i.appendChild(a),i.appendChild(o),i}_buildAmPmToggle(e){const t=document.createElement("div");t.className="mojo-time-ampm";const s=e>=12,i=document.createElement("button");i.type="button",i.className=`mojo-time-ampm-btn${s?"":" is-active"}`,i.textContent="AM",i.addEventListener("click",n=>{n.preventDefault(),this._setAmPm("am")});const r=document.createElement("button");return r.type="button",r.className=`mojo-time-ampm-btn${s?" is-active":""}`,r.textContent="PM",r.addEventListener("click",n=>{n.preventDefault(),this._setAmPm("pm")}),t.appendChild(i),t.appendChild(r),t}_mountTimezoneSelect(){if(!this.timezone)return;const e=this.inline?this.element.querySelector("[data-time-host] [data-tz-host]"):this._spinner&&this._spinner.querySelector("[data-tz-host]");if(e){if(this._tzSelect)try{this._tzSelect.destroy&&this._tzSelect.destroy()}catch{}e.innerHTML="",this._tzSelect=new Tt({name:"timezone",value:this.currentTimezone,timezones:this.timezoneList}),this._tzSelect.render(!0,e),this._tzSelect.on("change",({value:t})=>{const s=this.currentTimezone;this.currentTimezone=t||null,s!==this.currentTimezone&&this._syncOutputs()})}}_step(e,t){const s=this.currentTime||{hours:0,minutes:0};let{hours:i,minutes:r}=s;if(e==="hour")i=((i+t)%24+24)%24;else{const a=i*60+r,o=t*this.step,l=((a+o)%1440+1440)%1440;i=Math.floor(l/60),r=l%60}const n=this._clampToBounds({hours:i,minutes:r});this._commitTime(n),this._refreshSpinnerDisplay()}_setAmPm(e){if(!this.currentTime)this._commitTime({hours:e==="pm"?12:0,minutes:0});else{const{hours:t,minutes:s}=this.currentTime;let i=t;e==="am"&&i>=12?i-=12:e==="pm"&&i<12&&(i+=12),this._commitTime(this._clampToBounds({hours:i,minutes:s}))}this._refreshSpinnerDisplay()}_onValueKey(e,t,s){s.key==="ArrowUp"?(s.preventDefault(),this._step(e,1),t.focus(),t.select()):s.key==="ArrowDown"?(s.preventDefault(),this._step(e,-1),t.focus(),t.select()):s.key==="Enter"?(s.preventDefault(),t.blur()):s.key==="Tab"||!/^[0-9]$/.test(s.key)&&!["Backspace","Delete","ArrowLeft","ArrowRight","Home","End"].includes(s.key)&&s.preventDefault()}_onValueBlur(e,t){const s=(t.value||"").replace(/\D/g,"");if(s===""){this._refreshSpinnerDisplay();return}let i=parseInt(s,10);const r=this.currentTime||{hours:0,minutes:0};let{hours:n,minutes:a}=r;if(e==="hour")if(this.format==="12h"){i<1&&(i=1),i>12&&(i=12);const o=r.hours>=12;i===12?n=o?12:0:n=o?i+12:i}else i<0&&(i=0),i>23&&(i=23),n=i;else i<0&&(i=0),i>59&&(i=59),a=i;this._commitTime(this._clampToBounds({hours:n,minutes:a})),this._refreshSpinnerDisplay()}_hourDisplay(e){if(this.format==="12h"){let t=e%12;return t===0&&(t=12),String(t)}return Ye(e)}_refreshSpinnerDisplay(){if(!this._spinner)return;const e=this.currentTime||{hours:0,minutes:0},t=this._spinner.querySelector(".mojo-time-stepper-hour .mojo-time-stepper-value"),s=this._spinner.querySelector(".mojo-time-stepper-minute .mojo-time-stepper-value");if(t&&(t.value=this._hourDisplay(e.hours)),s&&(s.value=Ye(e.minutes)),this.format==="12h"){const i=e.hours>=12,r=this._spinner.querySelector(".mojo-time-ampm-btn:nth-child(1)"),n=this._spinner.querySelector(".mojo-time-ampm-btn:nth-child(2)");r&&r.classList.toggle("is-active",!i),n&&n.classList.toggle("is-active",i)}}_clampToBounds(e){const t=this.min?G(this.min):null,s=this.max?G(this.max):null;return t&&bt(e,t)<0?t:s&&bt(e,s)>0?s:e}_commitTime(e){const t=this._serialize();this.currentTime=e?{hours:e.hours,minutes:e.minutes}:null,this._syncOutputs(t)}_syncOutputs(e){const t=this._serialize(),s=this._displayText(),i=this.element&&this.element.querySelector("[data-trigger-text]");i&&(i.textContent=s||this.placeholder,i.classList.toggle("is-empty",!this.currentTime));const r=this.element&&this.element.querySelector("[data-hidden-value]");r&&(r.value=t),e!==void 0&&e!==t&&(this.emit("change",{value:this.getValue(),formatted:s,oldValue:e}),this.emit("time:changed",{value:this.getValue()}))}_serialize(){if(!this.currentTime)return"";const e=J(this.currentTime,"24h");if(!this.timezone||!this.currentTimezone)return e;if(this.outputFormat==="iana")return`${e} ${this.currentTimezone}`;const t=yt(this.currentTimezone,new Date);return t?`${e}${t}`:e}_displayText(){if(!this.currentTime)return"";const e=J(this.currentTime,this.format);return this.timezone&&this.currentTimezone?`${e} ${this.currentTimezone}`:e}getValue(){return this.currentTime?this.timezone&&this.outputFormat==="object"?{time:J(this.currentTime,"24h"),timezone:this.currentTimezone||null}:this._serialize():this.outputFormat==="object"?null:""}setValue(e){const t=this._serialize(),s=this._parseInitial(e);this.currentTime=s.time,s.timezone&&(this.currentTimezone=s.timezone),this._refreshSpinnerDisplay(),this._syncOutputs(t)}getFormattedValue(){return this._displayText()}clear(){if(!this.currentTime&&!this.element.querySelector("[data-hidden-value]")?.value)return;const e=this._serialize();this.currentTime=null,this._syncOutputs(e)}setMin(e){this.min=e}setMax(e){this.max=e}setEnabled(e){this.disabled=!e;const t=this.element.querySelector("[data-trigger]");t&&(t.disabled=!e),!e&&this._popover&&this._popover.isOpen()&&this._popover.close()}setReadonly(e){this.readonly=e,e&&this._popover&&this._popover.isOpen()&&this._popover.close()}focus(){const e=this.element.querySelector("[data-trigger]");e&&e.focus()}show(){const e=this.element.querySelector("[data-trigger]");e&&this._togglePopover(e)}hide(){this._popover&&this._popover.close()}getFormValue(){return this.getValue()}async setFormValue(e){this.setValue(e)}hasError(){return!1}_inputId(){return this.name?`mojo-time-${this.name}-${this.id}`:`mojo-time-${this.id}`}_attr(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}async onBeforeDestroy(){if(this._popover){try{this._popover.destroy()}catch{}this._popover=null}if(this._tzSelect){try{await this._tzSelect.destroy()}catch{}this._tzSelect=null}this._spinner=null,await super.onBeforeDestroy()}static addMinutes(e,t){return ls(e,t)}static create(e={}){return new $e(e)}}function Ye(c){return c<10?"0"+c:String(c)}function bs(){try{return new Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}catch{return"UTC"}}const ys="MMM DD, YYYY";class Ge extends C{constructor(e={}){const{name:t,value:s="",format:i=null,displayFormat:r=null,timeFormat:n="24h",timeStep:a=1,min:o=null,max:l=null,placeholder:d=null,disabled:h=!1,readonly:u=!1,required:m=!1,class:p="",inline:f=!1,disabledDates:g=[],firstDay:b=1,lang:y="en-US",autoApply:v=!1,timezone:_=!1,timezones:A=null,outputFormat:E="iso",...j}=e;super({tagName:"div",className:`mojo-datetime-picker ${p}`.trim(),...j}),this.name=t,this.format=i,this.displayFormat=r||ys,this.timeFormat=n==="12h"?"12h":"24h",this.timeStep=Math.max(1,parseInt(a,10)||1),this.min=o,this.max=l,this.placeholder=d??"Pick date & time...",this.disabled=h,this.readonly=u,this.required=m,this.inline=f,this.disabledDates=g,this.firstDay=b,this.lang=y,this.autoApply=v,this.timezone=_===!0||Array.isArray(_),this.timezoneList=Array.isArray(_)?_:A,this.outputFormat=["object","iana","iso"].includes(E)?E:"iso";const M=this._parseInitial(s);this.currentDate=M.date,this.currentTime=M.time,this.currentTimezone=M.timezone||(this.timezone?Ft():null),this._calendar=null,this._timePicker=null,this._tzSelect=null,this._popover=null,this._popoverContent=null}_parseInitial(e){return e==null||e===""?{date:null,time:null,timezone:null}:typeof e=="object"&&!Array.isArray(e)&&!(e instanceof Date)?wt(e)||{date:null,time:null,timezone:null}:wt(e)||{date:null,time:null,timezone:null}}async renderTemplate(){const e=this._inputId(),t=this._displayText(),s=!this.currentDate,i=this._serialize();return this.inline?`
1196
+ `}async onAfterRender(){this.inline?this._mountInline():this._wireTrigger()}_wireTrigger(){const e=this.element.querySelector("[data-trigger]"),t=this.element.querySelector("[data-clear]");e&&(e.addEventListener("click",s=>{s.target.closest("[data-clear]")||this._togglePopover(e)}),t&&t.addEventListener("click",s=>{s.stopPropagation(),this.clear()}))}_togglePopover(e){if(this.disabled||this.readonly)return;if(this._popover?this._popover.setAnchor(e):this._popover=new _e({anchor:e,classNames:"mojo-time-popover"}),this._popover.isOpen()){this._popover.close();return}const t=this._buildSpinnerContent();this._popover.setContent(t),this._popover.open(),this.timezone&&this._mountTimezoneSelect()}_mountInline(){const e=this.element.querySelector("[data-time-host]");if(!e)return;const t=this._buildSpinnerContent();e.appendChild(t),this.timezone&&this._mountTimezoneSelect()}_buildSpinnerContent(){const e=document.createElement("div");e.className="mojo-time-popover-inner";const t=document.createElement("div");t.className="mojo-time-stepper-row";const s=this.currentTime||{hours:0,minutes:0},i=this._hourDisplay(s.hours);t.appendChild(this._buildStepper("hour",i,"Hour"));const r=document.createElement("div");if(r.className="mojo-time-stepper-sep",r.textContent=":",t.appendChild(r),t.appendChild(this._buildStepper("minute",Ye(s.minutes),"Minute")),this.format==="12h"&&t.appendChild(this._buildAmPmToggle(s.hours)),e.appendChild(t),this.timezone){const n=document.createElement("div");n.className="mojo-time-tz-host",n.setAttribute("data-tz-host",""),e.appendChild(n)}if(this.showFooter){const n=document.createElement("div");n.className="mojo-time-foot";const a=document.createElement("button");a.type="button",a.className="btn btn-link btn-sm mojo-time-now",a.textContent="Now",a.addEventListener("click",l=>{l.preventDefault();const d=new Date;this._commitTime({hours:d.getHours(),minutes:d.getMinutes()}),this._refreshSpinnerDisplay()}),n.appendChild(a);const o=document.createElement("button");o.type="button",o.className="btn btn-primary btn-sm mojo-time-apply",o.textContent="Set",o.addEventListener("click",l=>{l.preventDefault(),this.currentTime||this._commitTime({hours:0,minutes:0}),this._popover&&this._popover.isOpen()&&this._popover.close()}),n.appendChild(o),e.appendChild(n)}return this._spinner=e,e}_buildStepper(e,t,s){const i=document.createElement("div");i.className=`mojo-time-stepper mojo-time-stepper-${e}`;const r=document.createElement("button");r.type="button",r.className="mojo-time-stepper-btn",r.setAttribute("aria-label",`Increase ${s.toLowerCase()}`),r.innerHTML='<i class="bi bi-chevron-up" aria-hidden="true"></i>',r.addEventListener("click",l=>{l.preventDefault(),this._step(e,1)});const n=document.createElement("input");n.type="text",n.className="mojo-time-stepper-value",n.value=t,n.setAttribute("inputmode","numeric"),n.setAttribute("aria-label",s),n.maxLength=2,n.addEventListener("focus",()=>n.select()),n.addEventListener("keydown",l=>this._onValueKey(e,n,l)),n.addEventListener("blur",()=>this._onValueBlur(e,n));const a=document.createElement("button");a.type="button",a.className="mojo-time-stepper-btn",a.setAttribute("aria-label",`Decrease ${s.toLowerCase()}`),a.innerHTML='<i class="bi bi-chevron-down" aria-hidden="true"></i>',a.addEventListener("click",l=>{l.preventDefault(),this._step(e,-1)});const o=document.createElement("div");return o.className="mojo-time-stepper-label",o.textContent=s,i.appendChild(r),i.appendChild(n),i.appendChild(a),i.appendChild(o),i}_buildAmPmToggle(e){const t=document.createElement("div");t.className="mojo-time-ampm";const s=e>=12,i=document.createElement("button");i.type="button",i.className=`mojo-time-ampm-btn${s?"":" is-active"}`,i.textContent="AM",i.addEventListener("click",n=>{n.preventDefault(),this._setAmPm("am")});const r=document.createElement("button");return r.type="button",r.className=`mojo-time-ampm-btn${s?" is-active":""}`,r.textContent="PM",r.addEventListener("click",n=>{n.preventDefault(),this._setAmPm("pm")}),t.appendChild(i),t.appendChild(r),t}_mountTimezoneSelect(){if(!this.timezone)return;const e=this.inline?this.element.querySelector("[data-time-host] [data-tz-host]"):this._spinner&&this._spinner.querySelector("[data-tz-host]");if(e){if(this._tzSelect)try{this._tzSelect.destroy&&this._tzSelect.destroy()}catch{}e.innerHTML="",this._tzSelect=new Tt({name:"timezone",value:this.currentTimezone,timezones:this.timezoneList}),this._tzSelect.render(!0,e),this._tzSelect.on("change",({value:t})=>{const s=this.currentTimezone;this.currentTimezone=t||null,s!==this.currentTimezone&&this._syncOutputs()})}}_step(e,t){const s=this.currentTime||{hours:0,minutes:0};let{hours:i,minutes:r}=s;if(e==="hour")i=((i+t)%24+24)%24;else{const a=i*60+r,o=t*this.step,l=((a+o)%1440+1440)%1440;i=Math.floor(l/60),r=l%60}const n=this._clampToBounds({hours:i,minutes:r});this._commitTime(n),this._refreshSpinnerDisplay()}_setAmPm(e){if(!this.currentTime)this._commitTime({hours:e==="pm"?12:0,minutes:0});else{const{hours:t,minutes:s}=this.currentTime;let i=t;e==="am"&&i>=12?i-=12:e==="pm"&&i<12&&(i+=12),this._commitTime(this._clampToBounds({hours:i,minutes:s}))}this._refreshSpinnerDisplay()}_onValueKey(e,t,s){s.key==="ArrowUp"?(s.preventDefault(),this._step(e,1),t.focus(),t.select()):s.key==="ArrowDown"?(s.preventDefault(),this._step(e,-1),t.focus(),t.select()):s.key==="Enter"?(s.preventDefault(),t.blur()):s.key==="Tab"||!/^[0-9]$/.test(s.key)&&!["Backspace","Delete","ArrowLeft","ArrowRight","Home","End"].includes(s.key)&&s.preventDefault()}_onValueBlur(e,t){const s=(t.value||"").replace(/\D/g,"");if(s===""){this._refreshSpinnerDisplay();return}let i=parseInt(s,10);const r=this.currentTime||{hours:0,minutes:0};let{hours:n,minutes:a}=r;if(e==="hour")if(this.format==="12h"){i<1&&(i=1),i>12&&(i=12);const o=r.hours>=12;i===12?n=o?12:0:n=o?i+12:i}else i<0&&(i=0),i>23&&(i=23),n=i;else i<0&&(i=0),i>59&&(i=59),a=i;this._commitTime(this._clampToBounds({hours:n,minutes:a})),this._refreshSpinnerDisplay()}_hourDisplay(e){if(this.format==="12h"){let t=e%12;return t===0&&(t=12),String(t)}return Ye(e)}_refreshSpinnerDisplay(){if(!this._spinner)return;const e=this.currentTime||{hours:0,minutes:0},t=this._spinner.querySelector(".mojo-time-stepper-hour .mojo-time-stepper-value"),s=this._spinner.querySelector(".mojo-time-stepper-minute .mojo-time-stepper-value");if(t&&(t.value=this._hourDisplay(e.hours)),s&&(s.value=Ye(e.minutes)),this.format==="12h"){const i=e.hours>=12,r=this._spinner.querySelector(".mojo-time-ampm-btn:nth-child(1)"),n=this._spinner.querySelector(".mojo-time-ampm-btn:nth-child(2)");r&&r.classList.toggle("is-active",!i),n&&n.classList.toggle("is-active",i)}}_clampToBounds(e){const t=this.min?G(this.min):null,s=this.max?G(this.max):null;return t&&bt(e,t)<0?t:s&&bt(e,s)>0?s:e}_commitTime(e){const t=this._serialize();this.currentTime=e?{hours:e.hours,minutes:e.minutes}:null,this._syncOutputs(t)}_syncOutputs(e){const t=this._serialize(),s=this._displayText(),i=this.element&&this.element.querySelector("[data-trigger-text]");i&&(i.textContent=s||this.placeholder,i.classList.toggle("is-empty",!this.currentTime));const r=this.element&&this.element.querySelector("[data-hidden-value]");r&&(r.value=t),e!==void 0&&e!==t&&(this.emit("change",{value:this.getValue(),formatted:s,oldValue:e}),this.emit("time:changed",{value:this.getValue()}))}_serialize(){if(!this.currentTime)return"";const e=J(this.currentTime,"24h");if(!this.timezone||!this.currentTimezone)return e;if(this.outputFormat==="iana")return`${e} ${this.currentTimezone}`;const t=yt(this.currentTimezone,new Date);return t?`${e}${t}`:e}_displayText(){if(!this.currentTime)return"";const e=J(this.currentTime,this.format);return this.timezone&&this.currentTimezone?`${e} ${this.currentTimezone}`:e}getValue(){return this.currentTime?this.timezone&&this.outputFormat==="object"?{time:J(this.currentTime,"24h"),timezone:this.currentTimezone||null}:this._serialize():this.outputFormat==="object"?null:""}setValue(e){const t=this._serialize(),s=this._parseInitial(e);this.currentTime=s.time,s.timezone&&(this.currentTimezone=s.timezone),this._refreshSpinnerDisplay(),this._syncOutputs(t)}getFormattedValue(){return this._displayText()}clear(){if(!this.currentTime&&!this.element.querySelector("[data-hidden-value]")?.value)return;const e=this._serialize();this.currentTime=null,this._syncOutputs(e)}setMin(e){this.min=e}setMax(e){this.max=e}setEnabled(e){this.disabled=!e;const t=this.element.querySelector("[data-trigger]");t&&(t.disabled=!e),!e&&this._popover&&this._popover.isOpen()&&this._popover.close()}setReadonly(e){this.readonly=e,e&&this._popover&&this._popover.isOpen()&&this._popover.close()}focus(){const e=this.element.querySelector("[data-trigger]");e&&e.focus()}show(){const e=this.element.querySelector("[data-trigger]");e&&this._togglePopover(e)}hide(){this._popover&&this._popover.close()}getFormValue(){return this.getValue()}async setFormValue(e){this.setValue(e)}hasError(){return!1}_inputId(){return this.name?`mojo-time-${this.name}-${this.id}`:`mojo-time-${this.id}`}_attr(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}async onBeforeDestroy(){if(this._popover){try{this._popover.destroy()}catch{}this._popover=null}if(this._tzSelect){try{await this._tzSelect.destroy()}catch{}this._tzSelect=null}this._spinner=null,await super.onBeforeDestroy()}static addMinutes(e,t){return ls(e,t)}static create(e={}){return new $e(e)}}function Ye(c){return c<10?"0"+c:String(c)}function bs(){try{return new Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}catch{return"UTC"}}const ys="MMM DD, YYYY";class Ge extends C{constructor(e={}){const{name:t,value:s="",format:i=null,displayFormat:r=null,timeFormat:n="24h",timeStep:a=1,min:o=null,max:l=null,placeholder:d=null,disabled:h=!1,readonly:u=!1,required:m=!1,class:p="",inline:f=!1,disabledDates:g=[],firstDay:b=1,lang:y="en-US",autoApply:v=!1,timezone:_=!1,timezones:A=null,outputFormat:E="iso",...j}=e;super({tagName:"div",className:`mojo-datetime-picker ${p}`.trim(),...j}),this.name=t,this.format=i,this.displayFormat=r||ys,this.timeFormat=n==="12h"?"12h":"24h",this.timeStep=Math.max(1,parseInt(a,10)||1),this.min=o,this.max=l,this.placeholder=d??"Pick date & time...",this.disabled=h,this.readonly=u,this.required=m,this.inline=f,this.disabledDates=g,this.firstDay=b,this.lang=y,this.autoApply=v,this.timezone=_===!0||Array.isArray(_),this.timezoneList=Array.isArray(_)?_:A,this.outputFormat=["object","iana","iso"].includes(E)?E:"iso";const I=this._parseInitial(s);this.currentDate=I.date,this.currentTime=I.time,this.currentTimezone=I.timezone||(this.timezone?Ft():null),this._calendar=null,this._timePicker=null,this._tzSelect=null,this._popover=null,this._popoverContent=null}_parseInitial(e){return e==null||e===""?{date:null,time:null,timezone:null}:typeof e=="object"&&!Array.isArray(e)&&!(e instanceof Date)?wt(e)||{date:null,time:null,timezone:null}:wt(e)||{date:null,time:null,timezone:null}}async renderTemplate(){const e=this._inputId(),t=this._displayText(),s=!this.currentDate,i=this._serialize();return this.inline?`
1197
1197
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(i)}" data-hidden-value />
1198
1198
  <div data-dt-host class="mojo-datetime-picker-inline${this.hasError()?" is-invalid":""}"></div>
1199
1199
  `:`
@@ -1581,7 +1581,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1581
1581
  </button>
1582
1582
  </div>
1583
1583
  {{/hasMore}}
1584
- `}_initCollection(e){if(!e){console.log("Collection not provided");return}if(e instanceof le)this.setCollection(e);else if(typeof e=="function"){const t=new e;this.setCollection(t)}else if(Array.isArray(e)){const t=new le(e);this.setCollection(t)}}_normalizeDayRangeFilter(e){if(!e)return null;const t={field:"created",value:"7d",options:[{value:"1d",label:"1d"},{value:"7d",label:"7d"},{value:"30d",label:"30d"},{value:"90d",label:"90d"}],ariaLabel:"Time range"};return e===!0?t:{...t,...e}}_dayRangeDays(e){const t=/^(\d+)d$/.exec(String(e||""));return t?parseInt(t[1],10):null}_seedDayRangeParams(){if(!this.dayRangeFilter||!this.collection)return;const e=this._dayRangeDays(this.dayRangeFilter.value);if(e==null)return;const t=Math.floor(Date.now()/1e3)-e*86400;this.collection.params[`${this.dayRangeFilter.field}__gte`]=t}async _onDayRangeChange({value:e,previous:t}){const s=this.dayRangeFilter?.field||"created",i=this._dayRangeDays(e);let r={};if(i!=null&&this.collection){const n=Math.floor(Date.now()/1e3)-i*86400;this.collection.params[`${s}__gte`]=n,this.collection.params.start=0,r={[`${s}__gte`]:n}}if(this.emit("range:change",{field:s,value:e,previous:t,params:r}),this.emit("params-changed"),this.collection?.restEnabled)try{await this.collection.fetch()}catch(n){console.error("Failed to fetch day-range data:",n),await this.render()}else await this.render()}getRange(){return this.dayRangeControl?.getValue()??null}setRange(e,{silent:t=!1}={}){if(!this.dayRangeControl)return!1;const s=this.dayRangeControl.getValue();return this.dayRangeControl.setValue(e,{silent:!0})?(t||this._onDayRangeChange({value:e,previous:s}),!0):!1}setCollection(e){return this.collection===e?this:(this.collection&&(this.collection.off("add",this._onModelsAdded,this),this.collection.off("remove",this._onModelsRemoved,this),this.collection.off("reset",this._onCollectionReset,this),this.collection.off("fetch:start",this._onFetchStart,this),this.collection.off("fetch:end",this._onFetchEnd,this)),this.collection=e,this.options.defaultQuery&&!this.options.collectionParams&&(this.collection.params={...this.collection.params,...this.options.defaultQuery}),this.options.collectionParams&&(this.collection.params={...this.collection.params,...this.options.collectionParams}),this.options.pageSize&&this.collection&&(this.collection.params={...this.collection.params,size:this.options.pageSize}),this.collection&&(this.collection.on("add",this._onModelsAdded,this),this.collection.on("remove",this._onModelsRemoved,this),this.collection.on("reset",this._onCollectionReset,this),this.collection.on("fetch:start",this._onFetchStart,this),this.collection.on("fetch:end",this._onFetchEnd,this),this.collection.restEnabled&&!this.collection.lastFetchTime&&!this.collection.options?.preloaded?this.loading=!0:this._buildItems()),this)}async _renderChildren(){await super._renderChildren();const e=this.getChildElement("items");if(!e)return;const t=[];if(this._renderOrder.length>0)for(const s of this._renderOrder)e.appendChild(s.view.element),t.push(Promise.resolve(s.view.render(!1)).catch(()=>{}));else this.forEachItem(s=>{e.appendChild(s.element),t.push(Promise.resolve(s.render(!1)).catch(()=>{}))});await Promise.all(t)}_buildItems(){if(this._clearItems(),!this.collection||this.collection.isEmpty()){this.isEmpty=!0,this.emit("list:empty");return}this.isEmpty=!1,this.collection.forEach((e,t)=>{this._createItemView(e,t)}),this._applyPersistedSelections(),this._buildGroupHeaders(),this.emit("list:loaded",{count:this.collection.length()}),this.isMounted()&&this.render()}_buildGroupHeaders(){if(this.groupHeaderViews.forEach(i=>this.removeChild(i.id)),this.groupHeaderViews.clear(),this._renderOrder.length=0,!this.groupBy||!this.collection||this.collection.isEmpty())return;const e=typeof this.groupBy=="function"?this.groupBy:i=>i.get(this.groupBy);let t,s=!1;this.collection.forEach((i,r)=>{const n=this.itemViews.get(i.id);if(!n)return;let a;try{a=e(i)}catch(o){console.warn("ListView: groupBy resolver threw — treating as ungrouped tail",o),a=null}if(a&&(!s||a!==t)){const o=this._createGroupHeaderView(i,a,r);this._renderOrder.push({type:"header",view:o}),t=a,s=!0}this._renderOrder.push({type:"item",view:n})})}_rebuildGroupHeaders(){this._buildGroupHeaders()}_createGroupHeaderView(e,t,s){const i=this.groupHeaderLabel?this.groupHeaderLabel(t):t,r=new this.groupHeaderClass({template:this.groupHeaderTemplate||this._defaultGroupHeaderTemplate(),model:e,key:i,index:s,...this._groupHeaderViewOptions(e,t,s)});return this.groupHeaderViews.set(r.id,r),r}_groupHeaderViewOptions(e,t,s){return{className:`list-group-header list-group-header--${this.groupHeaderStyle}`}}_defaultGroupHeaderTemplate(){return"{{key}}"}_createItemView(e,t){if(this.itemViews.has(e.id))return this.itemViews.get(e.id);const s=new this.itemClass({model:e,index:t,listView:this,template:this.itemTemplate,clickable:this.clickable});return this.itemViews.set(e.id,s),this._wireItemViewListeners(s),s}_wireItemViewListeners(e){e.on("item:select",this._onItemSelect.bind(this)),e.on("item:deselect",this._onItemDeselect.bind(this)),e.on("item:click",t=>{t.action==="row-click"&&(this.emit("row:click",t),this._dispatchRowClick(t))}),e.on("row:click",t=>{this._dispatchRowClick(t)}),e.on("row:view",this._onRowView.bind(this)),e.on("row:edit",this._onRowEdit.bind(this)),e.on("row:delete",this._onRowDelete.bind(this))}_dispatchRowClick(e){if(typeof this.options.onRowClick=="function")return this.options.onRowClick(e.model,e.event);if(typeof this.clickAction=="function")return this.clickAction(e.model,e.event);if(this.onItemClick)return this.onItemClick(e.model,e.event);if(this.clickAction==="view")return this._onRowView(e);if(this.clickAction==="edit")return this._onRowEdit(e);this.clickAction==="select"&&(this.selectedItems.has(e.model.id)?this.deselectItem(e.model.id):this.selectItem(e.model.id))}_applyPersistedSelections(){!this.persistSelection||this.selectedItems.size===0||this.itemViews.forEach((e,t)=>{this.selectedItems.has(t)&&!e.selected&&(e.selected=!0,e.element&&e.addClass("selected"))})}_clearItems(){this.forEachItem(e=>{this.removeChild(e.id)}),this.itemViews.clear(),this.groupHeaderViews.forEach(e=>this.removeChild(e.id)),this.groupHeaderViews.clear(),this._renderOrder.length=0,this.persistSelection||this.selectedItems.clear()}_onModelsAdded(e){const{models:t}=e;t.forEach(s=>{const i=this.collection.models.indexOf(s);this._createItemView(s,i)}),this._applyPersistedSelections(),this.groupBy&&this._rebuildGroupHeaders(),this.isEmpty=this.collection.isEmpty(),!this.loading&&this.isMounted()&&this.render()}_onModelsRemoved(e){const{models:t}=e;t.forEach(s=>{const i=this.itemViews.get(s.id);i&&(this.removeChild(i.id),this.itemViews.delete(s.id),this.selectedItems.delete(s.id))}),this.isEmpty=this.collection.isEmpty(),!this.loading&&this.isMounted()&&this.render(),this.isEmpty&&this.emit("list:empty")}_onCollectionReset(e){this._buildItems()}_onFetchStart(){this.loading=!0,this.isMounted()&&this.render()}_onFetchEnd(){this.loading=!1,this.isMounted()&&this.render()}_onItemSelect(e){const{model:t,item:s}=e;if(this.selectionMode==="none"){s.deselect();return}this.selectionMode==="single"&&(this.itemViews.forEach((i,r)=>{r!==t.id&&i.selected&&i.deselect()}),this.selectedItems.clear()),this.selectedItems.add(t.id),this.emit("selection:change",{selected:Array.from(this.selectedItems),item:s,model:t})}_onItemDeselect(e){const{model:t}=e;this.selectedItems.delete(t.id),this.emit("selection:change",{selected:Array.from(this.selectedItems),item:e.item,model:t})}getSelectedItems(){const e=[];return this.selectedItems.forEach(t=>{const s=this.itemViews.get(t);s&&e.push({view:s,model:s.model,data:s.model?.toJSON?s.model.toJSON():s.model})}),e}forEachItem(e,t){if(typeof e!="function")throw new TypeError("Callback must be a function");let s=0;return this.itemViews.forEach(i=>{e.call(t,i,i.model,s++)}),this}clearSelection(){this.forEachItem(e=>{e.selected&&e.deselect()}),this.selectedItems.clear(),this.emit("selection:change",{selected:[]})}selectItem(e){const t=this.itemViews.get(e);return t&&t.select(),this}deselectItem(e){const t=this.itemViews.get(e);return t&&t.deselect(),this}setItemTemplate(e,t=!1){return this.itemTemplate=e,t&&this.itemViews.size>0&&this.forEachItem(s=>{s.setTemplate(e),s.isMounted()&&s.render()}),this}async refresh(){if(this.collection&&this.collection.restEnabled)return await this.collection.fetch();this._buildItems()}_stripeClassFor(e){if(!this.rowStripe||!e)return null;let t;try{t=this.rowStripe(e)}catch(s){return console.warn("ListView: rowStripe callback threw — treating as no stripe",s),null}return t==null||t===""||typeof t!="string"?null:he.ROW_STRIPE_TOKENS.includes(t)?`list-row-stripe-${t}`:t}_applyRowStripe(e){if(!e||!e.element)return;const t=e.element.classList;for(const i of Array.from(t))i.startsWith("list-row-stripe")&&t.remove(i);const s=this._stripeClassFor(e.model);if(s)try{t.add(s)}catch(i){console.warn("ListView: rowStripe returned an invalid class name, skipping",s,i)}}refreshStripes(){return this.rowStripe?(this.forEachItem(e=>this._applyRowStripe(e)),this):this}async _onRowView(e){if(this.emit("row:view",e),this.options.onItemView){await this.options.onItemView(e.model,e.event);return}if(this.fetchOnView)try{w.loading(),await e.model.fetch()}catch(s){w.hideLoading(!0),w.showError(s?.data?.error||s?.message||"Failed to load item details");return}finally{w.hideLoading(!0)}const t=this.getItemViewClass(e.model);if(t){const s=new t({model:e.model,collection:this.collection});await w.dialog({header:!1,body:s,size:"lg",centered:!1,...this.getFormDialogConfig(this.getModelClass(e.model)),...this.viewDialogOptions})}else await w.data({title:`View ${this.getModelName(e.model)} #${e.model.id}`,model:e.model})}async _onRowEdit(e){if(this.emit("row:edit",e),this.options.onItemEdit){await this.options.onItemEdit(e.model,e.event);return}const t=this.getModelClass(e.model);let s=this.getEditFormConfig(t);if(s){s.fields||(s={title:`Edit ${this.getModelName(e.model)}`,fields:s});const i=await w.modelForm({model:e.model,...s,...this.getFormDialogConfig(t)});if(!i)return;if(!i.success||!i?.result?.data.status){w.showError(i?.result?.data?.error||i?.result?.message||"An error occurred");return}}else{const i=await w.dialog({title:`Edit ${this.getModelName(e.model)} #${e.model.id}`,body:new ee({model:e.model,fields:this.options.formFields||[]})});if(i){const r=await e.model.save(i);if(!r.data?.status){w.showError(r.data.error||"An error occurred");return}await this.refresh()}}}async _onRowDelete(e){if(this.emit("row:delete",e),this.options.onItemDelete){await this.options.onItemDelete(e.model,e.event);return}const t=this.getModelClass(e.model),s=this.deleteTemplate||t?.DELETE_TEMPLATE||'Are you sure you want to delete this {{name||"item"}}?',i=this.renderTemplateString(s,e.model);await w.confirm({message:i||"Are you sure you want to delete this item?",title:"Confirm Delete",confirmText:"Delete",confirmClass:"btn-danger"})&&(await e.model.destroy(),this.collection?.restEnabled?this.collection.fetch():this._buildItems())}async onActionAdd(e,t){if(this.options.onAdd){this.emit("list:add",{event:e}),await this.options.onAdd(e);return}this.emit("list:add",{event:e});const s=this.getModelClass();if(!s){console.warn("Cannot determine Model class for add operation");return}let i=this.getAddFormConfig(s);if(i){const r=new s;i.fields||(i={title:`Add ${this.getModelName()}`,fields:i});const n=await w.form({model:r,...i,...this.getFormDialogConfig(s)});if(n){this.options.addRequiresActiveGroup&&(n.group=this.getApp().activeGroup.id),this.options.addRequiresActiveUser&&(n.user=this.getApp().activeUser.id),this.options.addFormDefaults&&Object.assign(n,this.options.addFormDefaults);const a=await r.save(n);if(!a?.data.status){w.showError(a?.data.error||"An error occurred");return}this.collection&&this.collection.add(r),await this.refresh()}}else{const r=new s,n=await w.dialog({title:`Add ${this.getModelName()}`,body:new ee({model:r,fields:this.options.formFields||[]})});if(n){const a=await r.save(n);if(!a?.data.status){w.showError(a.data.error||"An error occurred");return}this.collection&&this.collection.add(r),await this.refresh()}}}async onActionExport(e,t){const s=t.getAttribute("data-format")||"json";this.emit("list:export",{format:s,source:this.exportSource,event:e}),this.exportSource==="remote"?this.collection?await this.collection.download(s):console.warn("ListView: Cannot export from remote without a collection."):this.options.onExport?await this.options.onExport(this.collection?.toJSON()||[],s):console.warn("ListView: onExport handler not implemented for local export.")}getModelClass(e){return this.collection?.ModelClass?this.collection.ModelClass:this.collection?.model?this.collection.model:e?.constructor?e.constructor:null}getModelName(e){const t=this.getModelClass(e);return t&&(t.MODEL_NAME||t.name.replace(/Model$/,""))||"Item"}getItemViewClass(e){if(this.itemView)return this.itemView;const t=this.getModelClass(e);return t?.VIEW_CLASS?t.VIEW_CLASS:null}getAddFormConfig(e){return this.addForm||e?.ADD_FORM||this.editForm||e?.EDIT_FORM}getEditFormConfig(e){return this.editForm||e?.EDIT_FORM||this.addForm||e?.ADD_FORM}getFormDialogConfig(e){return{...e?.FORM_DIALOG_CONFIG,...this.formDialogConfig}}renderTemplateString(e,t){return e?D.render(e,t):""}async onActionRefresh(e,t){await this.refresh()}async onActionApplySearch(e,t){const s=t.value.trim();this.collection&&(this.setFilter("search",s),this.collection.params.start=0,this.collection.restEnabled?await this.collection.fetch():await this.render()),this.updateFilterPills(),this.emit("list:search",{searchTerm:s}),this.emit("params-changed")}async onActionClearSearch(e,t){this.setFilter("search",null),this.collection&&(this.collection.params.start=0,this.collection.restEnabled&&await this.collection.fetch()),await this.render(),this.updateFilterPills(),this.emit("list:search",{searchTerm:""}),this.emit("params-changed")}setupSearchClearListener(){if(!this.element)return;this.element.querySelectorAll('input[type="search"][data-filter="search"]').forEach(t=>{t.addEventListener("input",s=>{s.target.value===""&&this.getActiveFilters().search&&this.onActionClearSearch(s,s.target)})})}updateFilterPills(){const e=this.element?.querySelector('[data-container="filter-pills"]');e&&(e.innerHTML=this.buildActivePills())}updateSearchInputs(e){const t=this.element?.querySelectorAll('[data-filter="search"]');t&&t.forEach(s=>{s.value=e||""})}renderPagination(){const e=this.element.querySelector('[data-container="pagination"]');if(!e||!this.collection)return;const t=this.collection.meta?.count||this.collection.length(),s=this.collection.params?.size||10,i=this.collection.params?.start||0,r=Math.floor(i/s)+1,n=Math.ceil(t/s);if(n<=1){e.innerHTML="";return}const a=r>1?r-1:n,o=r<n?r+1:1,l=[];l.push(`
1584
+ `}_initCollection(e){if(!e){console.log("Collection not provided");return}if(e instanceof le)this.setCollection(e);else if(typeof e=="function"){const t=new e;this.setCollection(t)}else if(Array.isArray(e)){const t=new le(e);this.setCollection(t)}}_normalizeDayRangeFilter(e){if(!e)return null;const t={field:"created",value:"7d",options:[{value:"1d",label:"1d"},{value:"7d",label:"7d"},{value:"30d",label:"30d"},{value:"90d",label:"90d"}],ariaLabel:"Time range"};return e===!0?t:{...t,...e}}_dayRangeDays(e){const t=/^(\d+)d$/.exec(String(e||""));return t?parseInt(t[1],10):null}_seedDayRangeParams(){if(!this.dayRangeFilter||!this.collection)return;const e=this._dayRangeDays(this.dayRangeFilter.value);if(e==null)return;const t=Math.floor(Date.now()/1e3)-e*86400;this.collection.params[`${this.dayRangeFilter.field}__gte`]=t}async _onDayRangeChange({value:e,previous:t}){const s=this.dayRangeFilter?.field||"created",i=this._dayRangeDays(e);let r={};if(i!=null&&this.collection){const n=Math.floor(Date.now()/1e3)-i*86400;this.collection.params[`${s}__gte`]=n,this.collection.params.start=0,r={[`${s}__gte`]:n}}if(this.emit("range:change",{field:s,value:e,previous:t,params:r}),this.emit("params-changed"),this.collection?.restEnabled)try{await this.collection.fetch()}catch(n){console.error("Failed to fetch day-range data:",n),await this.render()}else await this.render()}getRange(){return this.dayRangeControl?.getValue()??null}setRange(e,{silent:t=!1}={}){if(!this.dayRangeControl)return!1;const s=this.dayRangeControl.getValue();return this.dayRangeControl.setValue(e,{silent:!0})?(t||this._onDayRangeChange({value:e,previous:s}),!0):!1}setCollection(e){return this.collection===e?this:(this.collection&&(this.collection.off("add",this._onModelsAdded,this),this.collection.off("remove",this._onModelsRemoved,this),this.collection.off("reset",this._onCollectionReset,this),this.collection.off("fetch:start",this._onFetchStart,this),this.collection.off("fetch:end",this._onFetchEnd,this)),this.collection=e,this.options.defaultQuery&&!this.options.collectionParams&&(this.collection.params={...this.collection.params,...this.options.defaultQuery}),this.options.collectionParams&&(this.collection.params={...this.collection.params,...this.options.collectionParams}),this.options.pageSize&&this.collection&&(this.collection.params={...this.collection.params,size:this.options.pageSize}),this.collection&&(this.collection.on("add",this._onModelsAdded,this),this.collection.on("remove",this._onModelsRemoved,this),this.collection.on("reset",this._onCollectionReset,this),this.collection.on("fetch:start",this._onFetchStart,this),this.collection.on("fetch:end",this._onFetchEnd,this),this.collection.restEnabled&&!this.collection.lastFetchTime&&!this.collection.options?.preloaded?this.loading=!0:this._buildItems()),this)}async _renderChildren(){await super._renderChildren();const e=this.getChildElement("items");if(!e)return;const t=[];if(this._renderOrder.length>0)for(const s of this._renderOrder)e.appendChild(s.view.element),t.push(Promise.resolve(s.view.render(!1)).catch(()=>{}));else this.forEachItem(s=>{e.appendChild(s.element),t.push(Promise.resolve(s.render(!1)).catch(()=>{}))});await Promise.all(t)}_buildItems(){if(this._clearItems(),!this.collection||this.collection.isEmpty()){this.isEmpty=!0,this.emit("list:empty");return}this.isEmpty=!1,this.collection.forEach((e,t)=>{this._createItemView(e,t)}),this._applyPersistedSelections(),this._buildGroupHeaders(),this.emit("list:loaded",{count:this.collection.length()}),this.isMounted()&&this.render()}_buildGroupHeaders(){if(this.groupHeaderViews.forEach(i=>this.removeChild(i.id)),this.groupHeaderViews.clear(),this._renderOrder.length=0,!this.groupBy||!this.collection||this.collection.isEmpty())return;const e=typeof this.groupBy=="function"?this.groupBy:i=>i.get(this.groupBy);let t,s=!1;this.collection.forEach((i,r)=>{const n=this.itemViews.get(i.id);if(!n)return;let a;try{a=e(i)}catch(o){console.warn("ListView: groupBy resolver threw — treating as ungrouped tail",o),a=null}if(a&&(!s||a!==t)){const o=this._createGroupHeaderView(i,a,r);this._renderOrder.push({type:"header",view:o}),t=a,s=!0}this._renderOrder.push({type:"item",view:n})})}_rebuildGroupHeaders(){this._buildGroupHeaders()}_createGroupHeaderView(e,t,s){const i=this.groupHeaderLabel?this.groupHeaderLabel(t):t,r=new this.groupHeaderClass({template:this.groupHeaderTemplate||this._defaultGroupHeaderTemplate(),model:e,key:i,index:s,...this._groupHeaderViewOptions(e,t,s)});return this.groupHeaderViews.set(r.id,r),r}_groupHeaderViewOptions(e,t,s){return{className:`list-group-header list-group-header--${this.groupHeaderStyle}`}}_defaultGroupHeaderTemplate(){return"{{key}}"}_createItemView(e,t){if(this.itemViews.has(e.id))return this.itemViews.get(e.id);const s=new this.itemClass({model:e,index:t,listView:this,template:this.itemTemplate,clickable:this.clickable});return this.itemViews.set(e.id,s),this._wireItemViewListeners(s),s}_wireItemViewListeners(e){e.on("item:select",this._onItemSelect.bind(this)),e.on("item:deselect",this._onItemDeselect.bind(this)),e.on("item:click",t=>{t.action==="row-click"&&(this.emit("row:click",t),this._dispatchRowClick(t))}),e.on("row:click",t=>{this._dispatchRowClick(t)}),e.on("row:view",this._onRowView.bind(this)),e.on("row:edit",this._onRowEdit.bind(this)),e.on("row:delete",this._onRowDelete.bind(this))}_dispatchRowClick(e){if(typeof this.options.onRowClick=="function")return this.options.onRowClick(e.model,e.event);if(typeof this.clickAction=="function")return this.clickAction(e.model,e.event);if(this.onItemClick)return this.onItemClick(e.model,e.event);if(this.clickAction==="view")return this._onRowView(e);if(this.clickAction==="edit")return this._onRowEdit(e);this.clickAction==="select"&&(this.selectedItems.has(e.model.id)?this.deselectItem(e.model.id):this.selectItem(e.model.id))}_applyPersistedSelections(){!this.persistSelection||this.selectedItems.size===0||this.itemViews.forEach((e,t)=>{this.selectedItems.has(t)&&!e.selected&&(e.selected=!0,e.element&&e.addClass("selected"))})}_clearItems(){this.forEachItem(e=>{this.removeChild(e.id)}),this.itemViews.clear(),this.groupHeaderViews.forEach(e=>this.removeChild(e.id)),this.groupHeaderViews.clear(),this._renderOrder.length=0,this.persistSelection||this.selectedItems.clear()}_onModelsAdded(e){const{models:t}=e;t.forEach(s=>{const i=this.collection.models.indexOf(s);this._createItemView(s,i)}),this._applyPersistedSelections(),this.groupBy&&this._rebuildGroupHeaders(),this.isEmpty=this.collection.isEmpty(),!this.loading&&this.isMounted()&&this.render()}_onModelsRemoved(e){const{models:t}=e;t.forEach(s=>{const i=this.itemViews.get(s.id);i&&(this.removeChild(i.id),this.itemViews.delete(s.id),this.selectedItems.delete(s.id))}),this.isEmpty=this.collection.isEmpty(),!this.loading&&this.isMounted()&&this.render(),this.isEmpty&&this.emit("list:empty")}_onCollectionReset(e){this._buildItems()}_onFetchStart(){this.loading=!0,!this.loadingMore&&this.isMounted()&&this.render()}_onFetchEnd(){this.loading=!1,!this.loadingMore&&this.isMounted()&&this.render()}_onItemSelect(e){const{model:t,item:s}=e;if(this.selectionMode==="none"){s.deselect();return}this.selectionMode==="single"&&(this.itemViews.forEach((i,r)=>{r!==t.id&&i.selected&&i.deselect()}),this.selectedItems.clear()),this.selectedItems.add(t.id),this.emit("selection:change",{selected:Array.from(this.selectedItems),item:s,model:t})}_onItemDeselect(e){const{model:t}=e;this.selectedItems.delete(t.id),this.emit("selection:change",{selected:Array.from(this.selectedItems),item:e.item,model:t})}getSelectedItems(){const e=[];return this.selectedItems.forEach(t=>{const s=this.itemViews.get(t);s&&e.push({view:s,model:s.model,data:s.model?.toJSON?s.model.toJSON():s.model})}),e}forEachItem(e,t){if(typeof e!="function")throw new TypeError("Callback must be a function");let s=0;return this.itemViews.forEach(i=>{e.call(t,i,i.model,s++)}),this}clearSelection(){this.forEachItem(e=>{e.selected&&e.deselect()}),this.selectedItems.clear(),this.emit("selection:change",{selected:[]})}selectItem(e){const t=this.itemViews.get(e);return t&&t.select(),this}deselectItem(e){const t=this.itemViews.get(e);return t&&t.deselect(),this}setItemTemplate(e,t=!1){return this.itemTemplate=e,t&&this.itemViews.size>0&&this.forEachItem(s=>{s.setTemplate(e),s.isMounted()&&s.render()}),this}async refresh(){if(this.collection&&this.collection.restEnabled)return await this.collection.fetch();this._buildItems()}_stripeClassFor(e){if(!this.rowStripe||!e)return null;let t;try{t=this.rowStripe(e)}catch(s){return console.warn("ListView: rowStripe callback threw — treating as no stripe",s),null}return t==null||t===""||typeof t!="string"?null:he.ROW_STRIPE_TOKENS.includes(t)?`list-row-stripe-${t}`:t}_applyRowStripe(e){if(!e||!e.element)return;const t=e.element.classList;for(const i of Array.from(t))i.startsWith("list-row-stripe")&&t.remove(i);const s=this._stripeClassFor(e.model);if(s)try{t.add(s)}catch(i){console.warn("ListView: rowStripe returned an invalid class name, skipping",s,i)}}refreshStripes(){return this.rowStripe?(this.forEachItem(e=>this._applyRowStripe(e)),this):this}async _onRowView(e){if(this.emit("row:view",e),this.options.onItemView){await this.options.onItemView(e.model,e.event);return}if(this.fetchOnView)try{w.loading(),await e.model.fetch()}catch(s){w.hideLoading(!0),w.showError(s?.data?.error||s?.message||"Failed to load item details");return}finally{w.hideLoading(!0)}const t=this.getItemViewClass(e.model);if(t){const s=new t({model:e.model,collection:this.collection});await w.dialog({header:!1,body:s,size:"lg",centered:!1,...this.getFormDialogConfig(this.getModelClass(e.model)),...this.viewDialogOptions})}else await w.data({title:`View ${this.getModelName(e.model)} #${e.model.id}`,model:e.model})}async _onRowEdit(e){if(this.emit("row:edit",e),this.options.onItemEdit){await this.options.onItemEdit(e.model,e.event);return}const t=this.getModelClass(e.model);let s=this.getEditFormConfig(t);if(s){s.fields||(s={title:`Edit ${this.getModelName(e.model)}`,fields:s});const i=await w.modelForm({model:e.model,...s,...this.getFormDialogConfig(t)});if(!i)return;if(!i.success||!i?.result?.data.status){w.showError(i?.result?.data?.error||i?.result?.message||"An error occurred");return}}else{const i=await w.dialog({title:`Edit ${this.getModelName(e.model)} #${e.model.id}`,body:new ee({model:e.model,fields:this.options.formFields||[]})});if(i){const r=await e.model.save(i);if(!r.data?.status){w.showError(r.data.error||"An error occurred");return}await this.refresh()}}}async _onRowDelete(e){if(this.emit("row:delete",e),this.options.onItemDelete){await this.options.onItemDelete(e.model,e.event);return}const t=this.getModelClass(e.model),s=this.deleteTemplate||t?.DELETE_TEMPLATE||'Are you sure you want to delete this {{name||"item"}}?',i=this.renderTemplateString(s,e.model);await w.confirm({message:i||"Are you sure you want to delete this item?",title:"Confirm Delete",confirmText:"Delete",confirmClass:"btn-danger"})&&(await e.model.destroy(),this.collection?.restEnabled?this.collection.fetch():this._buildItems())}async onActionAdd(e,t){if(this.options.onAdd){this.emit("list:add",{event:e}),await this.options.onAdd(e);return}this.emit("list:add",{event:e});const s=this.getModelClass();if(!s){console.warn("Cannot determine Model class for add operation");return}let i=this.getAddFormConfig(s);if(i){const r=new s;i.fields||(i={title:`Add ${this.getModelName()}`,fields:i});const n=await w.form({model:r,...i,...this.getFormDialogConfig(s)});if(n){this.options.addRequiresActiveGroup&&(n.group=this.getApp().activeGroup.id),this.options.addRequiresActiveUser&&(n.user=this.getApp().activeUser.id),this.options.addFormDefaults&&Object.assign(n,this.options.addFormDefaults);const a=await r.save(n);if(!a?.data.status){w.showError(a?.data.error||"An error occurred");return}this.collection&&this.collection.add(r),await this.refresh()}}else{const r=new s,n=await w.dialog({title:`Add ${this.getModelName()}`,body:new ee({model:r,fields:this.options.formFields||[]})});if(n){const a=await r.save(n);if(!a?.data.status){w.showError(a.data.error||"An error occurred");return}this.collection&&this.collection.add(r),await this.refresh()}}}async onActionExport(e,t){const s=t.getAttribute("data-format")||"json";this.emit("list:export",{format:s,source:this.exportSource,event:e}),this.exportSource==="remote"?this.collection?await this.collection.download(s):console.warn("ListView: Cannot export from remote without a collection."):this.options.onExport?await this.options.onExport(this.collection?.toJSON()||[],s):console.warn("ListView: onExport handler not implemented for local export.")}getModelClass(e){return this.collection?.ModelClass?this.collection.ModelClass:this.collection?.model?this.collection.model:e?.constructor?e.constructor:null}getModelName(e){const t=this.getModelClass(e);return t&&(t.MODEL_NAME||t.name.replace(/Model$/,""))||"Item"}getItemViewClass(e){if(this.itemView)return this.itemView;const t=this.getModelClass(e);return t?.VIEW_CLASS?t.VIEW_CLASS:null}getAddFormConfig(e){return this.addForm||e?.ADD_FORM||this.editForm||e?.EDIT_FORM}getEditFormConfig(e){return this.editForm||e?.EDIT_FORM||this.addForm||e?.ADD_FORM}getFormDialogConfig(e){return{...e?.FORM_DIALOG_CONFIG,...this.formDialogConfig}}renderTemplateString(e,t){return e?D.render(e,t):""}async onActionRefresh(e,t){await this.refresh()}async onActionApplySearch(e,t){const s=t.value.trim();this.collection&&(this.setFilter("search",s),this.collection.params.start=0,this.collection.restEnabled?await this.collection.fetch():await this.render()),this.updateFilterPills(),this.emit("list:search",{searchTerm:s}),this.emit("params-changed")}async onActionClearSearch(e,t){this.setFilter("search",null),this.collection&&(this.collection.params.start=0,this.collection.restEnabled&&await this.collection.fetch()),await this.render(),this.updateFilterPills(),this.emit("list:search",{searchTerm:""}),this.emit("params-changed")}setupSearchClearListener(){if(!this.element)return;this.element.querySelectorAll('input[type="search"][data-filter="search"]').forEach(t=>{t.addEventListener("input",s=>{s.target.value===""&&this.getActiveFilters().search&&this.onActionClearSearch(s,s.target)})})}updateFilterPills(){const e=this.element?.querySelector('[data-container="filter-pills"]');e&&(e.innerHTML=this.buildActivePills())}updateSearchInputs(e){const t=this.element?.querySelectorAll('[data-filter="search"]');t&&t.forEach(s=>{s.value=e||""})}renderPagination(){const e=this.element.querySelector('[data-container="pagination"]');if(!e||!this.collection)return;const t=this.collection.meta?.count||this.collection.length(),s=this.collection.params?.size||10,i=this.collection.params?.start||0,r=Math.floor(i/s)+1,n=Math.ceil(t/s);if(n<=1){e.innerHTML="";return}const a=r>1?r-1:n,o=r<n?r+1:1,l=[];l.push(`
1585
1585
  <li class="page-item">
1586
1586
  <a class="page-link" href="#" data-action="page" data-page="${a}">
1587
1587
  <i class="bi bi-chevron-left"></i>
@@ -1710,7 +1710,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1710
1710
  </button>
1711
1711
  </div>
1712
1712
  </div>
1713
- `}setupEditorEvents(e,t,s){const i=e.querySelector(".cell-input"),r=e.querySelector(".cell-save"),n=e.querySelector(".cell-cancel");i&&(i.type==="text"||i.type==="email"||i.type==="number")&&i.addEventListener("keydown",a=>{a.key==="Enter"?(a.preventDefault(),this.saveCellEdit(e,t,s)):a.key==="Escape"&&(a.preventDefault(),this.cancelCellEdit(e,t))}),i&&(i.type==="checkbox"||i.tagName==="SELECT")&&s.autoSave!==!1&&i.addEventListener("change",()=>{this.saveCellEdit(e,t,s)}),r?.addEventListener("click",()=>{this.saveCellEdit(e,t,s)}),n?.addEventListener("click",()=>{this.cancelCellEdit(e,t)})}async saveCellEdit(e,t,s){const i=e.querySelector(".cell-input");if(!i)return;let r;i.type==="checkbox"?r=i.checked:(i.tagName,r=i.value);const n=this.model.get?this.model.get(t):this.model[t];try{this.model.save?await this.model.save({[t]:r}):this.model[t]=r,this.exitEditMode(e,t,r),this.emit("cell:save",{row:this,model:this.model,column:t,oldValue:n,newValue:r})}catch(a){console.error("Failed to save cell edit:",a),this.emit("cell:save:error",{row:this,model:this.model,column:t,oldValue:n,newValue:r,error:a}),e.classList.add("saving-error"),setTimeout(()=>e.classList.remove("saving-error"),3e3)}}cancelCellEdit(e,t){const s=e.dataset.originalContent;this.exitEditMode(e,t,null,s),this.emit("cell:cancel",{row:this,model:this.model,column:t})}exitEditMode(e,t,s=null,i=null){const n=e.closest("td").querySelector(".cell-content");if(n){if(s!==null){const a=this.columns.find(l=>l.key===t);let o=s;a&&a.formatter&&typeof a.formatter=="string"&&(o=P.pipe(s,a.formatter)),n.innerHTML=this.escapeHtml(o)}else i&&(n.innerHTML=i);n.style.display=""}e.remove(),this.editingCells.delete(t)}escapeHtml(e){if(e==null)return"";const t=document.createElement("div");return t.textContent=e,t.innerHTML}select(){super.select(),this.addClass("selected");const e=this.element?.querySelector(".mojo-select-cell");e&&e.classList.add("selected")}deselect(){super.deselect(),this.removeClass("selected");const e=this.element?.querySelector(".mojo-select-cell");e&&e.classList.remove("selected")}}class It extends he{constructor(e={}){const t={className:"table-view-component",itemClass:e.itemClass||Ze,selectionMode:e.selectable?"multiple":"none",emptyMessage:e.emptyMessage||"No data available",addButtonIcon:e.addButtonIcon||"bi bi-plus-circle",...e};super(t),this.isFullscreen=!1,this.columns=e.columns||[],this.actions=e.actions||null,this.contextMenu=e.contextMenu||null,this.batchActions=e.batchActions||null,this.searchable=e.searchable!==!1,this.sortable=e.sortable!==!1,this.filterable=e.filterable!==!1,this.paginated=e.paginated!==!1,this.paginationMode=e.paginationMode||"pages",this.persistSelection=e.persistSelection===!0,this.clickAction=e.clickAction||"view",this.fetchOnView=e.fetchOnView!==!1,this.itemView=e.itemView,this.addForm=e.addForm,this.editForm=e.editForm,this.deleteTemplate=e.deleteTemplate,this.formDialogConfig=e.formDialogConfig||{},this.viewDialogOptions=e.viewDialogOptions||{},this.exportOptions=e.exportOptions||null,this.options.showExport&&!this.exportOptions&&(this.exportOptions=[{format:"csv",label:"Export as CSV",icon:"bi bi-file-earmark-spreadsheet"},{format:"json",label:"Export as JSON",icon:"bi bi-file-earmark-code"}]),this.exportSource=e.exportSource||"remote",this.filters={},this.additionalFilters=e.filters||[],this.hideActivePills=e.hideActivePills===!0,this.hideActivePillNames=e.hideActivePillNames||[],this.rowAction=e.rowAction||"row-click",this.batchBarLocation=e.batchBarLocation||"bottom",this.options.addButtonLabel=e.addButtonLabel||"Add",this.toolbarButtons=e.toolbarButtons||[],this.toolbarRight=e.toolbarRight||null,this.title=e.title||null,this.eyebrow=e.eyebrow||null,this.showRefresh=e.showRefresh!==!1,this.showFullscreen=e.showFullscreen!==!1,this.tableOptions={striped:!0,bordered:!1,hover:!0,responsive:!1,size:null,...e.tableOptions},this.searchPlacement=e.searchPlacement||"toolbar",this.searchPlaceholder=e.searchPlaceholder||"Search...",this.initializeColumns(),this.extractColumnFilters(),this.footerTotalColumns=this.columns.filter(s=>s.footer_total===!0),this.hasFooterTotals=this.footerTotalColumns.length>0,this.template=this.buildTableTemplate(),this.setupCollectionListeners()}setupCollectionListeners(){this.hasFooterTotals&&this.collection&&this.collection.on("reset add remove change",()=>{this.updateFooterTotals()})}initializeColumns(){this.columns.forEach(e=>{!e.key&&e.name&&(e.key=e.name),!e.label&&!e.title&&(e.label=e.key.charAt(0).toUpperCase()+e.key.slice(1))})}getResponsiveClasses(e){if(!e)return"";const t=["sm","md","lg","xl","xxl"];if(typeof e=="string")return t.includes(e)?`d-none d-${e}-table-cell`:(console.warn(`Invalid visibility breakpoint: ${e}. Valid options are: ${t.join(", ")}`),"");if(typeof e=="object"){const s=[];if(e.hide){if(!t.includes(e.hide))return console.warn(`Invalid hide breakpoint: ${e.hide}. Valid options are: ${t.join(", ")}`),"";s.push(`d-table-cell d-${e.hide}-none`)}if(e.show){if(!t.includes(e.show))return console.warn(`Invalid show breakpoint: ${e.show}. Valid options are: ${t.join(", ")}`),"";e.hide?s.push(`d-${e.show}-table-cell`):s.push(`d-none d-${e.show}-table-cell`)}return s.join(" ")}return""}getAlignClass(e){if(!e)return"";const s={left:"text-start",start:"text-start",center:"text-center",right:"text-end",end:"text-end"}[String(e).toLowerCase()];return s||(console.warn(`Invalid column align: ${e}. Valid options are: left, center, right`),"")}parseColumnKey(e){const t=e.split("|");return{fieldKey:t[0],formatter:t[1]||null}}updateFooterTotals(){if(!this.hasFooterTotals||!this.element)return;const e=this.calculateFooterTotals();let t=0;this.columns.forEach(s=>{if(s.footer_total){const i=`col_${t}`,r=this.element.querySelector(`[data-total-column="${i}"]`);if(r&&e[i]){const n=this.parseColumnKey(s.key).formatter||s.formatter;let a;n&&typeof n=="string"?a=this.formatValue(e[i].value,n):a=e[i].value,r.textContent=a}t++}})}formatValue(e,t){try{return P.pipe(e,t)}catch(s){return console.warn("Error formatting value:",s),e}}calculateFooterTotals(){if(!this.hasFooterTotals||!this.collection||this.collection.length===0)return{};const e={};return this.footerTotalColumns.forEach((t,s)=>{const{fieldKey:i,formatter:r}=this.parseColumnKey(t.key);let n=0;this.collection.forEach(o=>{const l=o.get?o.get(i):o[i],d=parseFloat(l)||0;n+=d});const a=`col_${s}`;e[a]={value:n,formatter:r||t.formatter,fieldKey:i,originalKey:t.key}}),e}extractColumnFilters(){this.filters={},this.columns.forEach(e=>{if(e.filter){const{fieldKey:t}=this.parseColumnKey(e.key);this.filters[t]={...e.filter,label:e.filter.label||e.label||t}}})}isSelectable(){return this.batchActions&&this.batchActions.length>0&&this.selectionMode==="multiple"}buildTableTemplate(){const e=this.batchBarLocation==="top"?this.buildBatchActionsPanel():"",t=this.batchBarLocation==="bottom"?this.buildBatchActionsPanel():"",s=(()=>{const i=this.tableOptions&&this.tableOptions.fontSize!=null?this.tableOptions.fontSize:this.options&&this.options.fontSize,r=i==="sm"?"0.9rem":i==="xs"?"0.8rem":i?String(i):null;return r?` style="font-size: ${r};"`:""})();return`
1713
+ `}setupEditorEvents(e,t,s){const i=e.querySelector(".cell-input"),r=e.querySelector(".cell-save"),n=e.querySelector(".cell-cancel");i&&(i.type==="text"||i.type==="email"||i.type==="number")&&i.addEventListener("keydown",a=>{a.key==="Enter"?(a.preventDefault(),this.saveCellEdit(e,t,s)):a.key==="Escape"&&(a.preventDefault(),this.cancelCellEdit(e,t))}),i&&(i.type==="checkbox"||i.tagName==="SELECT")&&s.autoSave!==!1&&i.addEventListener("change",()=>{this.saveCellEdit(e,t,s)}),r?.addEventListener("click",()=>{this.saveCellEdit(e,t,s)}),n?.addEventListener("click",()=>{this.cancelCellEdit(e,t)})}async saveCellEdit(e,t,s){const i=e.querySelector(".cell-input");if(!i)return;let r;i.type==="checkbox"?r=i.checked:(i.tagName,r=i.value);const n=this.model.get?this.model.get(t):this.model[t];try{this.model.save?await this.model.save({[t]:r}):this.model[t]=r,this.exitEditMode(e,t,r),this.emit("cell:save",{row:this,model:this.model,column:t,oldValue:n,newValue:r})}catch(a){console.error("Failed to save cell edit:",a),this.emit("cell:save:error",{row:this,model:this.model,column:t,oldValue:n,newValue:r,error:a}),e.classList.add("saving-error"),setTimeout(()=>e.classList.remove("saving-error"),3e3)}}cancelCellEdit(e,t){const s=e.dataset.originalContent;this.exitEditMode(e,t,null,s),this.emit("cell:cancel",{row:this,model:this.model,column:t})}exitEditMode(e,t,s=null,i=null){const n=e.closest("td").querySelector(".cell-content");if(n){if(s!==null){const a=this.columns.find(l=>l.key===t);let o=s;a&&a.formatter&&typeof a.formatter=="string"&&(o=P.pipe(s,a.formatter)),n.innerHTML=this.escapeHtml(o)}else i&&(n.innerHTML=i);n.style.display=""}e.remove(),this.editingCells.delete(t)}escapeHtml(e){if(e==null)return"";const t=document.createElement("div");return t.textContent=e,t.innerHTML}select(){super.select(),this.addClass("selected");const e=this.element?.querySelector(".mojo-select-cell");e&&e.classList.add("selected")}deselect(){super.deselect(),this.removeClass("selected");const e=this.element?.querySelector(".mojo-select-cell");e&&e.classList.remove("selected")}}class Mt extends he{constructor(e={}){const t={className:"table-view-component",itemClass:e.itemClass||Ze,selectionMode:e.selectable?"multiple":"none",emptyMessage:e.emptyMessage||"No data available",addButtonIcon:e.addButtonIcon||"bi bi-plus-circle",...e};super(t),this.isFullscreen=!1,this.columns=e.columns||[],this.actions=e.actions||null,this.contextMenu=e.contextMenu||null,this.batchActions=e.batchActions||null,this.searchable=e.searchable!==!1,this.sortable=e.sortable!==!1,this.filterable=e.filterable!==!1,this.paginated=e.paginated!==!1,this.paginationMode=e.paginationMode||"pages",this.persistSelection=e.persistSelection===!0,this.clickAction=e.clickAction||"view",this.fetchOnView=e.fetchOnView!==!1,this.itemView=e.itemView,this.addForm=e.addForm,this.editForm=e.editForm,this.deleteTemplate=e.deleteTemplate,this.formDialogConfig=e.formDialogConfig||{},this.viewDialogOptions=e.viewDialogOptions||{},this.exportOptions=e.exportOptions||null,this.options.showExport&&!this.exportOptions&&(this.exportOptions=[{format:"csv",label:"Export as CSV",icon:"bi bi-file-earmark-spreadsheet"},{format:"json",label:"Export as JSON",icon:"bi bi-file-earmark-code"}]),this.exportSource=e.exportSource||"remote",this.filters={},this.additionalFilters=e.filters||[],this.hideActivePills=e.hideActivePills===!0,this.hideActivePillNames=e.hideActivePillNames||[],this.rowAction=e.rowAction||"row-click",this.batchBarLocation=e.batchBarLocation||"bottom",this.options.addButtonLabel=e.addButtonLabel||"Add",this.toolbarButtons=e.toolbarButtons||[],this.toolbarRight=e.toolbarRight||null,this.title=e.title||null,this.eyebrow=e.eyebrow||null,this.showRefresh=e.showRefresh!==!1,this.showFullscreen=e.showFullscreen!==!1,this.tableOptions={striped:!0,bordered:!1,hover:!0,responsive:!1,size:null,...e.tableOptions},this.searchPlacement=e.searchPlacement||"toolbar",this.searchPlaceholder=e.searchPlaceholder||"Search...",this.initializeColumns(),this.extractColumnFilters(),this.footerTotalColumns=this.columns.filter(s=>s.footer_total===!0),this.hasFooterTotals=this.footerTotalColumns.length>0,this.template=this.buildTableTemplate(),this.setupCollectionListeners()}setupCollectionListeners(){this.hasFooterTotals&&this.collection&&this.collection.on("reset add remove change",()=>{this.updateFooterTotals()})}initializeColumns(){this.columns.forEach(e=>{!e.key&&e.name&&(e.key=e.name),!e.label&&!e.title&&(e.label=e.key.charAt(0).toUpperCase()+e.key.slice(1))})}getResponsiveClasses(e){if(!e)return"";const t=["sm","md","lg","xl","xxl"];if(typeof e=="string")return t.includes(e)?`d-none d-${e}-table-cell`:(console.warn(`Invalid visibility breakpoint: ${e}. Valid options are: ${t.join(", ")}`),"");if(typeof e=="object"){const s=[];if(e.hide){if(!t.includes(e.hide))return console.warn(`Invalid hide breakpoint: ${e.hide}. Valid options are: ${t.join(", ")}`),"";s.push(`d-table-cell d-${e.hide}-none`)}if(e.show){if(!t.includes(e.show))return console.warn(`Invalid show breakpoint: ${e.show}. Valid options are: ${t.join(", ")}`),"";e.hide?s.push(`d-${e.show}-table-cell`):s.push(`d-none d-${e.show}-table-cell`)}return s.join(" ")}return""}getAlignClass(e){if(!e)return"";const s={left:"text-start",start:"text-start",center:"text-center",right:"text-end",end:"text-end"}[String(e).toLowerCase()];return s||(console.warn(`Invalid column align: ${e}. Valid options are: left, center, right`),"")}parseColumnKey(e){const t=e.split("|");return{fieldKey:t[0],formatter:t[1]||null}}updateFooterTotals(){if(!this.hasFooterTotals||!this.element)return;const e=this.calculateFooterTotals();let t=0;this.columns.forEach(s=>{if(s.footer_total){const i=`col_${t}`,r=this.element.querySelector(`[data-total-column="${i}"]`);if(r&&e[i]){const n=this.parseColumnKey(s.key).formatter||s.formatter;let a;n&&typeof n=="string"?a=this.formatValue(e[i].value,n):a=e[i].value,r.textContent=a}t++}})}formatValue(e,t){try{return P.pipe(e,t)}catch(s){return console.warn("Error formatting value:",s),e}}calculateFooterTotals(){if(!this.hasFooterTotals||!this.collection||this.collection.length===0)return{};const e={};return this.footerTotalColumns.forEach((t,s)=>{const{fieldKey:i,formatter:r}=this.parseColumnKey(t.key);let n=0;this.collection.forEach(o=>{const l=o.get?o.get(i):o[i],d=parseFloat(l)||0;n+=d});const a=`col_${s}`;e[a]={value:n,formatter:r||t.formatter,fieldKey:i,originalKey:t.key}}),e}extractColumnFilters(){this.filters={},this.columns.forEach(e=>{if(e.filter){const{fieldKey:t}=this.parseColumnKey(e.key);this.filters[t]={...e.filter,label:e.filter.label||e.label||t}}})}isSelectable(){return this.batchActions&&this.batchActions.length>0&&this.selectionMode==="multiple"}buildTableTemplate(){const e=this.batchBarLocation==="top"?this.buildBatchActionsPanel():"",t=this.batchBarLocation==="bottom"?this.buildBatchActionsPanel():"",s=(()=>{const i=this.tableOptions&&this.tableOptions.fontSize!=null?this.tableOptions.fontSize:this.options&&this.options.fontSize,r=i==="sm"?"0.9rem":i==="xs"?"0.8rem":i?String(i):null;return r?` style="font-size: ${r};"`:""})();return`
1714
1714
  <div class="mojo-table-wrapper">
1715
1715
  ${this.buildToolbarTemplate()}
1716
1716
  ${e}
@@ -1846,7 +1846,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1846
1846
  </div>
1847
1847
  </div>
1848
1848
  </div>
1849
- `}}_createItemView(e,t){if(this.itemViews.has(e.id))return this.itemViews.get(e.id);const s=new this.itemClass({model:e,index:t,listView:this,tableView:this,template:this.itemTemplate,columns:this.columns,actions:this.actions,contextMenu:this.contextMenu,batchActions:this.batchActions,containerId:"items"});return this.itemViews.set(e.id,s),this._wireItemViewListeners(s),s.on("item:select",()=>this.updateBatchActionsPanel()),s.on("item:deselect",()=>this.updateBatchActionsPanel()),s.on("cell:edit",this._onCellEdit.bind(this)),s.on("cell:save",this._onCellSave.bind(this)),s.on("cell:cancel",this._onCellCancel.bind(this)),s}async onBeforeRender(){await super.onBeforeRender(),this.footerTotals=this.calculateFooterTotals()}async onAfterRender(){await super.onAfterRender(),this.hasFooterTotals&&this.updateFooterTotals(),this.updateSortIcons()}_onCellEdit(e){this.emit("cell:edit",e)}async _onCellSave(e){this.emit("cell:save",e)}_onCellCancel(e){this.emit("cell:cancel",e)}_defaultGroupHeaderTemplate(){return'<th colspan="{{colspan}}" class="list-group-header-cell">{{key}}</th>'}_groupHeaderViewOptions(e,t,s){const i=this.columns?.length||0,r=this.isSelectable()?1:0,n=this.actions||this.contextMenu?1:0;return{tagName:"tr",className:`list-group-header-row list-group-header-row--${this.groupHeaderStyle}`,colspan:Math.max(1,i+r+n)}}isFullscreenSupported(){return!!(document.fullscreenEnabled||document.mozFullScreenEnabled||document.webkitFullscreenEnabled||document.msFullscreenEnabled)}async onActionToggleFullscreen(e,t){this.isFullscreen?await this.exitFullscreen():await this.enterFullscreen()}async enterFullscreen(){try{this.element.requestFullscreen?await this.element.requestFullscreen():this.element.mozRequestFullScreen?await this.element.mozRequestFullScreen():this.element.webkitRequestFullscreen?await this.element.webkitRequestFullscreen():this.element.msRequestFullscreen&&await this.element.msRequestFullscreen(),this.isFullscreen=!0,this.element.classList.add("table-fullscreen"),this.updateFullscreenButton(),this.setupFullscreenListeners(),this.emit("table:fullscreen:enter")}catch(e){console.warn("Could not enter fullscreen:",e)}}async exitFullscreen(){try{document.exitFullscreen?await document.exitFullscreen():document.mozCancelFullScreen?await document.mozCancelFullScreen():document.webkitExitFullscreen?await document.webkitExitFullscreen():document.msExitFullscreen&&await document.msExitFullscreen(),this.isFullscreen=!1,this.element.classList.remove("table-fullscreen"),this.updateFullscreenButton(),this.emit("table:fullscreen:exit")}catch(e){console.warn("Could not exit fullscreen:",e)}}updateFullscreenButton(){const e=this.element?.querySelector(".btn-fullscreen"),t=e?.querySelector("i");e&&t&&(this.isFullscreen?(t.className="bi bi-fullscreen-exit",e.title="Exit Fullscreen"):(t.className="bi bi-fullscreen",e.title="Enter Fullscreen"))}setupFullscreenListeners(){if(this._fullscreenHandler)return;const e=()=>{!(document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement||document.msFullscreenElement)&&this.isFullscreen&&(this.isFullscreen=!1,this.element.classList.remove("table-fullscreen"),this.updateFullscreenButton(),this.emit("table:fullscreen:exit"))};document.addEventListener("fullscreenchange",e),document.addEventListener("mozfullscreenchange",e),document.addEventListener("webkitfullscreenchange",e),document.addEventListener("msfullscreenchange",e),this._fullscreenHandler=e}cleanupFullscreenListeners(){this._fullscreenHandler&&(document.removeEventListener("fullscreenchange",this._fullscreenHandler),document.removeEventListener("mozfullscreenchange",this._fullscreenHandler),document.removeEventListener("webkitfullscreenchange",this._fullscreenHandler),document.removeEventListener("msfullscreenchange",this._fullscreenHandler),this._fullscreenHandler=null)}destroy(){this.cleanupFullscreenListeners(),super.destroy()}async onActionAdd(e,t){return this.emit("table:add",{event:e}),super.onActionAdd(e,t)}async onActionExport(e,t){const s=t.getAttribute("data-format")||"json";return this.emit("table:export",{format:s,source:this.exportSource,event:e}),super.onActionExport(e,t)}getSortBy(){const e=this.collection?.params?.sort;return e?e.startsWith("-")?e.slice(1):e:null}getSortDirection(){const e=this.collection?.params?.sort;return e&&e.startsWith("-")?"desc":"asc"}getSortIcon(e){return e==="asc"?'<i class="bi bi-sort-alpha-down text-primary"></i>':e==="desc"?'<i class="bi bi-sort-alpha-down-alt text-primary"></i>':'<i class="bi bi-three-dots-vertical text-muted"></i>'}async onActionSort(e,t){e.preventDefault();const s=t.getAttribute("data-field"),i=t.getAttribute("data-direction");if(this.collection){let r;if(i==="none"?r=void 0:i==="desc"?r=`-${s}`:r=s,this.collection.setParams({...this.collection.params,sort:r,start:0}),this.collection.restEnabled)await this.collection.fetch();else{if(r){const n=r.startsWith("-"),a=n?r.slice(1):r;this.collection.sort((o,l)=>{const d=o.get(a),h=l.get(a);return d<h?n?1:-1:d>h?n?-1:1:0})}this.render()}}this.updateSortIcons(),this.emit("table:sort",{field:s,event:e}),this.emit("params-changed")}updateSortIcons(){if(!this.element)return;const e=this.getSortBy(),t=this.getSortDirection();this.columns.forEach(s=>{if(this.sortable&&s.sortable!==!1){const{fieldKey:i}=this.parseColumnKey(s.key),r=this.element.querySelector(`[data-bs-toggle="dropdown"][data-column="${i}"]`);if(r){const n=e===i,a=this.getSortIcon(n?t:null);r.innerHTML=a;const o=r.nextElementSibling;if(o){const l=o.querySelector(`[data-field="${i}"][data-direction="asc"]`),d=o.querySelector(`[data-field="${i}"][data-direction="desc"]`),h=o.querySelector(`[data-field="${i}"][data-direction="none"]`);l&&l.classList.toggle("active",n&&t==="asc"),d&&d.classList.toggle("active",n&&t==="desc"),h&&h.classList.toggle("active",!n||e!==i)}}}})}async onActionSelectAll(e,t){e.stopPropagation();const s=this.itemViews.size>0&&Array.from(this.itemViews.values()).every(r=>r.selected);s?this.clearSelection():this.forEachItem(r=>{r.selected||r.select()});const i=this.element?.querySelector(".mojo-select-all-cell");i&&i.classList.toggle("selected",!s),this.updateBatchActionsPanel()}updateBatchActionsPanel(){if(!this.batchActions||this.batchActions.length===0)return;const e=this.getSelectedItems().length;if(this.batchBarLocation==="top"){const s=this.element?.querySelector(".batch-actions-panel-top"),i=this.element?.querySelector(".batch-select-count");s&&i&&(i.textContent=e,e>0?s.classList.remove("d-none"):s.classList.add("d-none"))}else{const s=this.element?.querySelector(".batch-actions-panel"),i=this.element?.querySelector(".batch-select-count");s&&i&&(i.textContent=e,s.style.display=e>0?"block":"none")}const t=this.element?.querySelector(".mojo-select-all-cell");if(t){const s=this.itemViews.size>0&&Array.from(this.itemViews.values()).every(n=>n.selected),i=Array.from(this.itemViews.values()).some(n=>n.selected);t.classList.toggle("selected",s),t.classList.toggle("indeterminate",!s&&i);const r=t.querySelector("i");r&&(r.className=!s&&i?"bi bi-dash":"bi bi-check")}}async onActionBatch(e,t){const s=t.getAttribute("data-action").replace("batch-",""),i=this.getSelectedItems();this.emit("batch:action",{action:s,items:i,event:e})}async onActionClearSelection(e,t){this.clearSelection(),this.updateBatchActionsPanel()}getFilterDisplayValue(e,t){if(e==="search")return`"${t}"`;const s=this.filters[e]||this.additionalFilters.find(i=>(i.name||i.key)===e);if(s&&s.type==="daterange"&&typeof t=="object"){const i=t.start||"",r=t.end||"";return`${i} to ${r}`}if(s&&s.type==="select"&&s.options){if(typeof s.options[0]=="object"){const i=s.options.find(r=>r.value===t);return i?i.label:t}return t}return t}}function xs(){return typeof window>"u"?null:((!window.MOJO||typeof window.MOJO!="object")&&(window.MOJO={}),window.MOJO)}function $s(c){return c.__lite&&c.__lite.version||(c.WebApp=ve,c.View=C,c.Page=pe,c.Router=Te,c.Model=K,c.Collection=le,c.Rest=ie,c.FormBuilder=fe,c.FormView=ee,c.Dialog=x,c.ModalView=x,c.ProgressView=Le,c.ListView=he,c.ListViewItem=Ae,c.TableView=It,c.TableRow=Ze,c.DataFormatter=P,c.MOJOUtils=$,c.__lite={version:"dev",build:"web-mojo.lite"},c.mount=async function(t,s){if(!t)throw new Error("MOJO.mount(view, container) requires a view");const i=typeof s=="string"?document.querySelector(s):s;if(!i)throw new Error("MOJO.mount(view, container) container not found");if(typeof t.render!="function"||typeof t.mount!="function")throw new Error("MOJO.mount expects a View instance with render() and mount() methods");return await t.render(),await t.mount(i),t}),c}const Ke=xs();Ke&&$s(Ke);class Qe extends C{constructor(e={}){const{data:t,model:s,fields:i,columns:r,responsive:n,showEmptyValues:a,emptyValueText:o,...l}=e;super({tagName:"div",className:"data-view",...l}),this.data=t||{},this.fields=i||[],this.model=s||null,this.model&&(this.data=this.model),this.dataViewOptions={columns:r||2,responsive:n!==!1,showEmptyValues:a||!1,emptyValueText:o||"—",rowClass:"row g-3",itemClass:"data-view-item",labelClass:"data-view-label fw-semibold text-muted small text-uppercase",valueClass:"data-view-value"}}async onBeforeRender(){this.fields.length===0&&this.getData()&&this.generateFieldsFromData()}async renderTemplate(){const e=this.buildItemsHTML();return`
1849
+ `}}_createItemView(e,t){if(this.itemViews.has(e.id))return this.itemViews.get(e.id);const s=new this.itemClass({model:e,index:t,listView:this,tableView:this,template:this.itemTemplate,columns:this.columns,actions:this.actions,contextMenu:this.contextMenu,batchActions:this.batchActions,containerId:"items"});return this.itemViews.set(e.id,s),this._wireItemViewListeners(s),s.on("item:select",()=>this.updateBatchActionsPanel()),s.on("item:deselect",()=>this.updateBatchActionsPanel()),s.on("cell:edit",this._onCellEdit.bind(this)),s.on("cell:save",this._onCellSave.bind(this)),s.on("cell:cancel",this._onCellCancel.bind(this)),s}async onBeforeRender(){await super.onBeforeRender(),this.footerTotals=this.calculateFooterTotals()}async onAfterRender(){await super.onAfterRender(),this.hasFooterTotals&&this.updateFooterTotals(),this.updateSortIcons()}_onCellEdit(e){this.emit("cell:edit",e)}async _onCellSave(e){this.emit("cell:save",e)}_onCellCancel(e){this.emit("cell:cancel",e)}_defaultGroupHeaderTemplate(){return'<th colspan="{{colspan}}" class="list-group-header-cell">{{key}}</th>'}_groupHeaderViewOptions(e,t,s){const i=this.columns?.length||0,r=this.isSelectable()?1:0,n=this.actions||this.contextMenu?1:0;return{tagName:"tr",className:`list-group-header-row list-group-header-row--${this.groupHeaderStyle}`,colspan:Math.max(1,i+r+n)}}isFullscreenSupported(){return!!(document.fullscreenEnabled||document.mozFullScreenEnabled||document.webkitFullscreenEnabled||document.msFullscreenEnabled)}async onActionToggleFullscreen(e,t){this.isFullscreen?await this.exitFullscreen():await this.enterFullscreen()}async enterFullscreen(){try{this.element.requestFullscreen?await this.element.requestFullscreen():this.element.mozRequestFullScreen?await this.element.mozRequestFullScreen():this.element.webkitRequestFullscreen?await this.element.webkitRequestFullscreen():this.element.msRequestFullscreen&&await this.element.msRequestFullscreen(),this.isFullscreen=!0,this.element.classList.add("table-fullscreen"),this.updateFullscreenButton(),this.setupFullscreenListeners(),this.emit("table:fullscreen:enter")}catch(e){console.warn("Could not enter fullscreen:",e)}}async exitFullscreen(){try{document.exitFullscreen?await document.exitFullscreen():document.mozCancelFullScreen?await document.mozCancelFullScreen():document.webkitExitFullscreen?await document.webkitExitFullscreen():document.msExitFullscreen&&await document.msExitFullscreen(),this.isFullscreen=!1,this.element.classList.remove("table-fullscreen"),this.updateFullscreenButton(),this.emit("table:fullscreen:exit")}catch(e){console.warn("Could not exit fullscreen:",e)}}updateFullscreenButton(){const e=this.element?.querySelector(".btn-fullscreen"),t=e?.querySelector("i");e&&t&&(this.isFullscreen?(t.className="bi bi-fullscreen-exit",e.title="Exit Fullscreen"):(t.className="bi bi-fullscreen",e.title="Enter Fullscreen"))}setupFullscreenListeners(){if(this._fullscreenHandler)return;const e=()=>{!(document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement||document.msFullscreenElement)&&this.isFullscreen&&(this.isFullscreen=!1,this.element.classList.remove("table-fullscreen"),this.updateFullscreenButton(),this.emit("table:fullscreen:exit"))};document.addEventListener("fullscreenchange",e),document.addEventListener("mozfullscreenchange",e),document.addEventListener("webkitfullscreenchange",e),document.addEventListener("msfullscreenchange",e),this._fullscreenHandler=e}cleanupFullscreenListeners(){this._fullscreenHandler&&(document.removeEventListener("fullscreenchange",this._fullscreenHandler),document.removeEventListener("mozfullscreenchange",this._fullscreenHandler),document.removeEventListener("webkitfullscreenchange",this._fullscreenHandler),document.removeEventListener("msfullscreenchange",this._fullscreenHandler),this._fullscreenHandler=null)}destroy(){this.cleanupFullscreenListeners(),super.destroy()}async onActionAdd(e,t){return this.emit("table:add",{event:e}),super.onActionAdd(e,t)}async onActionExport(e,t){const s=t.getAttribute("data-format")||"json";return this.emit("table:export",{format:s,source:this.exportSource,event:e}),super.onActionExport(e,t)}getSortBy(){const e=this.collection?.params?.sort;return e?e.startsWith("-")?e.slice(1):e:null}getSortDirection(){const e=this.collection?.params?.sort;return e&&e.startsWith("-")?"desc":"asc"}getSortIcon(e){return e==="asc"?'<i class="bi bi-sort-alpha-down text-primary"></i>':e==="desc"?'<i class="bi bi-sort-alpha-down-alt text-primary"></i>':'<i class="bi bi-three-dots-vertical text-muted"></i>'}async onActionSort(e,t){e.preventDefault();const s=t.getAttribute("data-field"),i=t.getAttribute("data-direction");if(this.collection){let r;if(i==="none"?r=void 0:i==="desc"?r=`-${s}`:r=s,this.collection.setParams({...this.collection.params,sort:r,start:0}),this.collection.restEnabled)await this.collection.fetch();else{if(r){const n=r.startsWith("-"),a=n?r.slice(1):r;this.collection.sort((o,l)=>{const d=o.get(a),h=l.get(a);return d<h?n?1:-1:d>h?n?-1:1:0})}this.render()}}this.updateSortIcons(),this.emit("table:sort",{field:s,event:e}),this.emit("params-changed")}updateSortIcons(){if(!this.element)return;const e=this.getSortBy(),t=this.getSortDirection();this.columns.forEach(s=>{if(this.sortable&&s.sortable!==!1){const{fieldKey:i}=this.parseColumnKey(s.key),r=this.element.querySelector(`[data-bs-toggle="dropdown"][data-column="${i}"]`);if(r){const n=e===i,a=this.getSortIcon(n?t:null);r.innerHTML=a;const o=r.nextElementSibling;if(o){const l=o.querySelector(`[data-field="${i}"][data-direction="asc"]`),d=o.querySelector(`[data-field="${i}"][data-direction="desc"]`),h=o.querySelector(`[data-field="${i}"][data-direction="none"]`);l&&l.classList.toggle("active",n&&t==="asc"),d&&d.classList.toggle("active",n&&t==="desc"),h&&h.classList.toggle("active",!n||e!==i)}}}})}async onActionSelectAll(e,t){e.stopPropagation();const s=this.itemViews.size>0&&Array.from(this.itemViews.values()).every(r=>r.selected);s?this.clearSelection():this.forEachItem(r=>{r.selected||r.select()});const i=this.element?.querySelector(".mojo-select-all-cell");i&&i.classList.toggle("selected",!s),this.updateBatchActionsPanel()}updateBatchActionsPanel(){if(!this.batchActions||this.batchActions.length===0)return;const e=this.getSelectedItems().length;if(this.batchBarLocation==="top"){const s=this.element?.querySelector(".batch-actions-panel-top"),i=this.element?.querySelector(".batch-select-count");s&&i&&(i.textContent=e,e>0?s.classList.remove("d-none"):s.classList.add("d-none"))}else{const s=this.element?.querySelector(".batch-actions-panel"),i=this.element?.querySelector(".batch-select-count");s&&i&&(i.textContent=e,s.style.display=e>0?"block":"none")}const t=this.element?.querySelector(".mojo-select-all-cell");if(t){const s=this.itemViews.size>0&&Array.from(this.itemViews.values()).every(n=>n.selected),i=Array.from(this.itemViews.values()).some(n=>n.selected);t.classList.toggle("selected",s),t.classList.toggle("indeterminate",!s&&i);const r=t.querySelector("i");r&&(r.className=!s&&i?"bi bi-dash":"bi bi-check")}}async onActionBatch(e,t){const s=t.getAttribute("data-action").replace("batch-",""),i=this.getSelectedItems();this.emit("batch:action",{action:s,items:i,event:e})}async onActionClearSelection(e,t){this.clearSelection(),this.updateBatchActionsPanel()}getFilterDisplayValue(e,t){if(e==="search")return`"${t}"`;const s=this.filters[e]||this.additionalFilters.find(i=>(i.name||i.key)===e);if(s&&s.type==="daterange"&&typeof t=="object"){const i=t.start||"",r=t.end||"";return`${i} to ${r}`}if(s&&s.type==="select"&&s.options){if(typeof s.options[0]=="object"){const i=s.options.find(r=>r.value===t);return i?i.label:t}return t}return t}}function xs(){return typeof window>"u"?null:((!window.MOJO||typeof window.MOJO!="object")&&(window.MOJO={}),window.MOJO)}function $s(c){return c.__lite&&c.__lite.version||(c.WebApp=ve,c.View=C,c.Page=pe,c.Router=Te,c.Model=K,c.Collection=le,c.Rest=ie,c.FormBuilder=fe,c.FormView=ee,c.Dialog=x,c.ModalView=x,c.ProgressView=Le,c.ListView=he,c.ListViewItem=Ae,c.TableView=Mt,c.TableRow=Ze,c.DataFormatter=P,c.MOJOUtils=$,c.__lite={version:"dev",build:"web-mojo.lite"},c.mount=async function(t,s){if(!t)throw new Error("MOJO.mount(view, container) requires a view");const i=typeof s=="string"?document.querySelector(s):s;if(!i)throw new Error("MOJO.mount(view, container) container not found");if(typeof t.render!="function"||typeof t.mount!="function")throw new Error("MOJO.mount expects a View instance with render() and mount() methods");return await t.render(),await t.mount(i),t}),c}const Ke=xs();Ke&&$s(Ke);class Qe extends C{constructor(e={}){const{data:t,model:s,fields:i,columns:r,responsive:n,showEmptyValues:a,emptyValueText:o,...l}=e;super({tagName:"div",className:"data-view",...l}),this.data=t||{},this.fields=i||[],this.model=s||null,this.model&&(this.data=this.model),this.dataViewOptions={columns:r||2,responsive:n!==!1,showEmptyValues:a||!1,emptyValueText:o||"—",rowClass:"row g-3",itemClass:"data-view-item",labelClass:"data-view-label fw-semibold text-muted small text-uppercase",valueClass:"data-view-value"}}async onBeforeRender(){this.fields.length===0&&this.getData()&&this.generateFieldsFromData()}async renderTemplate(){const e=this.buildItemsHTML();return`
1850
1850
  <div class="${this.dataViewOptions.rowClass}">
1851
1851
  ${e}
1852
1852
  </div>
@@ -1894,5 +1894,5 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1894
1894
  ${i}
1895
1895
  </div>
1896
1896
  </div>
1897
- `}catch(s){return console.error("Error creating nested DataView:",s),'<span class="text-danger">Error displaying nested data</span>'}}async updateData(e){return this.data=e,this.model&&typeof this.model.set=="function"&&this.model.set(e),this.fields.length>0&&!this.options.fields&&(this.fields=[]),await this.render(),this.emit("data:updated",{data:e}),this}async updateFields(e){return this.fields=e,await this.render(),this.emit("fields:updated",{fields:e}),this}async updateConfig(e){return this.dataViewOptions={...this.dataViewOptions,...e},await this.render(),this.emit("config:updated",{options:this.dataViewOptions}),this}async refresh(){if(this.model&&typeof this.model.fetch=="function")try{await this.model.fetch(),this.emit("data:refreshed",{model:this.model})}catch(e){throw this.emit("error",{error:e,message:"Failed to refresh data"}),e}return this}getCurrentData(){return this.getData()}getField(e){return this.fields.find(t=>t.name===e)||null}setFieldFormat(e,t){const s=this.getField(e);return s?(s.format=t,s.formatter=t):this.fields.push({name:e,label:this.formatLabel(e),type:this.inferFieldType(this.getData()[e],e),format:t,formatter:t}),this}addFormatPipe(e,t){const s=this.getField(e);return s&&(s.format?(s.format+=`|${t}`,s.formatter=s.format):(s.format=t,s.formatter=t)),this}clearFieldFormat(e){const t=this.getField(e);if(t){const s=this.getData(),i=this.inferFormatter(s[e],e,t.type);t.format=i,t.formatter=i}return this}getFormattedValue(e,t=null){const s=this.getField(e);if(!s)return null;const i=t!==null?t:this.getData()[e],r=s.format||s.formatter;return r&&i!=null?P.pipe(i,r):i}setFieldFormats(e){return Object.entries(e).forEach(([t,s])=>{this.setFieldFormat(t,s)}),this}getFieldFormats(){const e={};return this.fields.forEach(t=>{const s=t.format||t.formatter;s&&(e[t.name]=s)}),e}onInit(){super.onInit(),this.model&&typeof this.model.on=="function"&&this.model.on("change",()=>{this.isMounted()&&this.render()})}static create(e={}){return new Qe(e)}}const As=Object.freeze(Object.defineProperty({__proto__:null,default:Qe},Symbol.toStringTag,{value:"Module"}));return T.Collection=le,T.DataFormatter=P,T.Dialog=x,T.FormBuilder=fe,T.FormPage=vs,T.FormView=ee,T.ListView=he,T.ListViewItem=Ae,T.MOJOUtils=$,T.ModalView=x,T.Model=K,T.Page=pe,T.ProgressView=Le,T.Rest=ie,T.Router=Te,T.TableRow=Ze,T.TableView=It,T.View=C,T.WebApp=ve,T.default=Ke,Object.defineProperties(T,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}}),T})({});
1897
+ `}catch(s){return console.error("Error creating nested DataView:",s),'<span class="text-danger">Error displaying nested data</span>'}}async updateData(e){return this.data=e,this.model&&typeof this.model.set=="function"&&this.model.set(e),this.fields.length>0&&!this.options.fields&&(this.fields=[]),await this.render(),this.emit("data:updated",{data:e}),this}async updateFields(e){return this.fields=e,await this.render(),this.emit("fields:updated",{fields:e}),this}async updateConfig(e){return this.dataViewOptions={...this.dataViewOptions,...e},await this.render(),this.emit("config:updated",{options:this.dataViewOptions}),this}async refresh(){if(this.model&&typeof this.model.fetch=="function")try{await this.model.fetch(),this.emit("data:refreshed",{model:this.model})}catch(e){throw this.emit("error",{error:e,message:"Failed to refresh data"}),e}return this}getCurrentData(){return this.getData()}getField(e){return this.fields.find(t=>t.name===e)||null}setFieldFormat(e,t){const s=this.getField(e);return s?(s.format=t,s.formatter=t):this.fields.push({name:e,label:this.formatLabel(e),type:this.inferFieldType(this.getData()[e],e),format:t,formatter:t}),this}addFormatPipe(e,t){const s=this.getField(e);return s&&(s.format?(s.format+=`|${t}`,s.formatter=s.format):(s.format=t,s.formatter=t)),this}clearFieldFormat(e){const t=this.getField(e);if(t){const s=this.getData(),i=this.inferFormatter(s[e],e,t.type);t.format=i,t.formatter=i}return this}getFormattedValue(e,t=null){const s=this.getField(e);if(!s)return null;const i=t!==null?t:this.getData()[e],r=s.format||s.formatter;return r&&i!=null?P.pipe(i,r):i}setFieldFormats(e){return Object.entries(e).forEach(([t,s])=>{this.setFieldFormat(t,s)}),this}getFieldFormats(){const e={};return this.fields.forEach(t=>{const s=t.format||t.formatter;s&&(e[t.name]=s)}),e}onInit(){super.onInit(),this.model&&typeof this.model.on=="function"&&this.model.on("change",()=>{this.isMounted()&&this.render()})}static create(e={}){return new Qe(e)}}const As=Object.freeze(Object.defineProperty({__proto__:null,default:Qe},Symbol.toStringTag,{value:"Module"}));return T.Collection=le,T.DataFormatter=P,T.Dialog=x,T.FormBuilder=fe,T.FormPage=vs,T.FormView=ee,T.ListView=he,T.ListViewItem=Ae,T.MOJOUtils=$,T.ModalView=x,T.Model=K,T.Page=pe,T.ProgressView=Le,T.Rest=ie,T.Router=Te,T.TableRow=Ze,T.TableView=Mt,T.View=C,T.WebApp=ve,T.default=Ke,Object.defineProperties(T,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}}),T})({});
1898
1898
  //# sourceMappingURL=web-mojo.lite.iife.min.js.map