web-mojo 2.4.5 → 2.4.6

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 (60) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/admin.cjs.js +1 -1
  3. package/dist/admin.es.js +1 -1
  4. package/dist/auth.cjs.js +1 -1
  5. package/dist/auth.es.js +1 -1
  6. package/dist/charts.cjs.js +1 -1
  7. package/dist/charts.es.js +1 -1
  8. package/dist/chunks/{AssistantPanelView-C4ZyIQoH.js → AssistantPanelView-CkQEcaFk.js} +2 -2
  9. package/dist/chunks/{AssistantPanelView-C4ZyIQoH.js.map → AssistantPanelView-CkQEcaFk.js.map} +1 -1
  10. package/dist/chunks/{AssistantPanelView-DlBgWeM_.js → AssistantPanelView-D1wEbgtM.js} +2 -2
  11. package/dist/chunks/{AssistantPanelView-DlBgWeM_.js.map → AssistantPanelView-D1wEbgtM.js.map} +1 -1
  12. package/dist/chunks/ChatView-D2WOSxPu.js +2 -0
  13. package/dist/chunks/ChatView-D2WOSxPu.js.map +1 -0
  14. package/dist/chunks/ChatView-kWguc444.js +2 -0
  15. package/dist/chunks/ChatView-kWguc444.js.map +1 -0
  16. package/dist/chunks/Passkeys-B1-Z4-16.js +2 -0
  17. package/dist/chunks/Passkeys-B1-Z4-16.js.map +1 -0
  18. package/dist/chunks/Passkeys-BlHx11-5.js +2 -0
  19. package/dist/chunks/Passkeys-BlHx11-5.js.map +1 -0
  20. package/dist/chunks/{TicketPanelView-DeeANyKv.js → TicketPanelView-DVePzWyJ.js} +2 -2
  21. package/dist/chunks/{TicketPanelView-DeeANyKv.js.map → TicketPanelView-DVePzWyJ.js.map} +1 -1
  22. package/dist/chunks/{TicketPanelView-if4ogL_D.js → TicketPanelView-TYh5iZiR.js} +2 -2
  23. package/dist/chunks/{TicketPanelView-if4ogL_D.js.map → TicketPanelView-TYh5iZiR.js.map} +1 -1
  24. package/dist/chunks/{UserProfileView-BPjz7uIp.js → UserProfileView-DDflzpTa.js} +2 -2
  25. package/dist/chunks/{UserProfileView-BPjz7uIp.js.map → UserProfileView-DDflzpTa.js.map} +1 -1
  26. package/dist/chunks/{UserProfileView-udbSWe1S.js → UserProfileView-cUF8ED9n.js} +2 -2
  27. package/dist/chunks/{UserProfileView-udbSWe1S.js.map → UserProfileView-cUF8ED9n.js.map} +1 -1
  28. package/dist/chunks/{admin-C3-HqQvC.js → admin-CHPo4iDn.js} +2 -2
  29. package/dist/chunks/{admin-C3-HqQvC.js.map → admin-CHPo4iDn.js.map} +1 -1
  30. package/dist/chunks/{admin-DrFBTXnB.js → admin-CucHFXfD.js} +2 -2
  31. package/dist/chunks/{admin-DrFBTXnB.js.map → admin-CucHFXfD.js.map} +1 -1
  32. package/dist/chunks/{index-dFX91Gwz.js → index-Cxffar1o.js} +2 -2
  33. package/dist/chunks/{index-dFX91Gwz.js.map → index-Cxffar1o.js.map} +1 -1
  34. package/dist/chunks/{index-Byf1pa3Z.js → index-DsID1QpB.js} +2 -2
  35. package/dist/chunks/{index-Byf1pa3Z.js.map → index-DsID1QpB.js.map} +1 -1
  36. package/dist/chunks/{version-C9vC8_Oy.js → version-BYy2UAT0.js} +2 -2
  37. package/dist/chunks/{version-C9vC8_Oy.js.map → version-BYy2UAT0.js.map} +1 -1
  38. package/dist/chunks/{version-CjNfmLdK.js → version-BxLEknar.js} +2 -2
  39. package/dist/chunks/{version-CjNfmLdK.js.map → version-BxLEknar.js.map} +1 -1
  40. package/dist/docit.cjs.js +1 -1
  41. package/dist/docit.es.js +1 -1
  42. package/dist/index.cjs.js +1 -1
  43. package/dist/index.es.js +1 -1
  44. package/dist/lightbox.cjs.js +1 -1
  45. package/dist/lightbox.es.js +1 -1
  46. package/dist/user-profile.cjs.js +1 -1
  47. package/dist/user-profile.es.js +1 -1
  48. package/dist/web-mojo.lite.iife.js +13 -0
  49. package/dist/web-mojo.lite.iife.js.map +1 -1
  50. package/dist/web-mojo.lite.iife.min.js +44 -44
  51. package/dist/web-mojo.lite.iife.min.js.map +1 -1
  52. package/package.json +1 -1
  53. package/dist/chunks/ChatView-CcR1GR30.js +0 -2
  54. package/dist/chunks/ChatView-CcR1GR30.js.map +0 -1
  55. package/dist/chunks/ChatView-ChyTcmrd.js +0 -2
  56. package/dist/chunks/ChatView-ChyTcmrd.js.map +0 -1
  57. package/dist/chunks/Passkeys-DJn9yy-0.js +0 -2
  58. package/dist/chunks/Passkeys-DJn9yy-0.js.map +0 -1
  59. package/dist/chunks/Passkeys-WWAg5tKf.js +0 -2
  60. package/dist/chunks/Passkeys-WWAg5tKf.js.map +0 -1
@@ -11,7 +11,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
11
11
  ${r?`<span class="font-monospace">${i}</span>`:""}
12
12
  ${n}
13
13
  </span>
14
- `}nl2br(e){return e==null?"":this.escapeHtml(String(e)).replace(/\r\n|\r|\n/g,"<br>")}code(e,t=""){if(e==null)return"";const s=t?`language-${this.escapeHtml(String(t))}`:"",i=this.escapeHtml(String(e));return`<pre class="bg-light p-2 rounded border"><code class="${s}">${i}</code></pre>`}register(e,t){if(typeof t!="function")throw new Error(`Formatter must be a function, got ${typeof t}`);return this.formatters.set(e.toLowerCase(),t),this}apply(e,t,...s){try{const i=this.formatters.get(e.toLowerCase());return i?i(t,...s):(console.warn(`Formatter '${e}' not found`),t)}catch(i){return console.error(`Error in formatter '${e}':`,i),t}}pipe(e,t,s=null){return t?this.parsePipeString(t,s).reduce((r,n)=>this.apply(n.name,r,...n.args),e):e}parsePipeString(e,t=null){const s=[],i=e.split("|").map(r=>r.trim());for(const r of i){const n=this.parseFormatter(r,t);n&&s.push(n)}return s}parseFormatter(e,t=null){const s=e.match(/^([a-zA-Z_]\w*)\s*\((.*)\)$/);if(s){const[,r,n]=s,a=n?this.parseArguments(n,t):[];return{name:r,args:a}}const i=e.match(/^([a-zA-Z_]\w*)(?::(.+))?$/);if(i){const[,r,n]=i,a=n?this.parseColonArguments(n,t):[];return{name:r,args:a}}return null}parseArguments(e,t=null){const s=[];let i="",r=!1,n=null,a=0;for(let o=0;o<e.length;o++){const l=e[o];!r&&(l==='"'||l==="'")?(r=!0,n=l,i+=l):r&&l===n&&e[o-1]!=="\\"?(r=!1,n=null,i+=l):!r&&l==="{"?(a++,i+=l):!r&&l==="}"?(a--,i+=l):!r&&a===0&&l===","?(s.push(this.parseValue(i.trim(),t)),i=""):i+=l}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseColonArguments(e,t=null){const s=[];let i="",r=!1,n=null;for(let a=0;a<e.length;a++){const o=e[a];!r&&(o==='"'||o==="'")?(r=!0,n=o,i+=o):r&&o===n&&e[a-1]!=="\\"?(r=!1,n=null,i+=o):!r&&o===":"?(s.push(this.parseValue(i.trim(),t)),i=""):i+=o}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseValue(e,t=null){if(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);if(e==="true")return!0;if(e==="false")return!1;if(e==="null")return null;if(e!=="undefined"){if(!isNaN(e)&&e!=="")return Number(e);if(e.startsWith("{")&&e.endsWith("}"))try{return JSON.parse(e)}catch{}if(t&&this.isIdentifier(e)){if(!e.includes(".")&&Object.prototype.hasOwnProperty.call(t,e))return t[e];if(t.get&&typeof t.get=="function"){const s=t.get(e);if(s!==void 0)return s}if(t.getContextValue&&typeof t.getContextValue=="function"){const s=t.getContextValue(e);if(s!==void 0)return s}if(e.includes(".")){const s=window.MOJOUtils||(typeof require<"u"?require("./MOJOUtils.js").default:null);if(s){const i=s.getNestedValue(t,e);if(i!==void 0)return i}}}return e}}isIdentifier(e){return/^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/.test(e)}date(e,t="MM/DD/YYYY"){if(!e)return"";e=this.normalizeEpoch(e);let s;if(e instanceof Date)s=e;else if(typeof e=="string")if(/^\d{4}-\d{2}-\d{2}$/.test(e)){const[a,o,l]=e.split("-").map(Number);s=new Date(a,o-1,l)}else s=new Date(e);else s=new Date(e);if(isNaN(s.getTime()))return String(e);const i={YYYY:s.getFullYear(),YY:String(s.getFullYear()).slice(-2),MMMM:s.toLocaleDateString("en-US",{month:"long"}),MMM:s.toLocaleDateString("en-US",{month:"short"}),MM:String(s.getMonth()+1).padStart(2,"0"),M:s.getMonth()+1,dddd:s.toLocaleDateString("en-US",{weekday:"long"}),ddd:s.toLocaleDateString("en-US",{weekday:"short"}),DD:String(s.getDate()).padStart(2,"0"),D:s.getDate()};let r=t;const n=new RegExp(`(${Object.keys(i).join("|")})`,"g");return r=r.replace(n,a=>i[a]||a),r}time(e,t="HH:mm:ss"){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const i=s.getHours(),r={HH:String(i).padStart(2,"0"),H:i,hh:String(i%12||12).padStart(2,"0"),h:i%12||12,mm:String(s.getMinutes()).padStart(2,"0"),m:s.getMinutes(),ss:String(s.getSeconds()).padStart(2,"0"),s:s.getSeconds(),A:i>=12?"PM":"AM",a:i>=12?"pm":"am"};let n=t;const a=Object.keys(r).sort((o,l)=>l.length-o.length);for(const o of a)n=n.replace(new RegExp(o,"g"),r[o]);return n}datetime(e,t="MM/DD/YYYY",s="HH:mm:ss"){e=this.normalizeEpoch(e);const i=this.date(e,t),r=this.time(e,s);return i&&r?`${i} ${r}`:""}datetime_tz(e,t="MM/DD/YYYY",s="HH:mm:ss",i={}){if(!e)return"";e=this.normalizeEpoch(e);const r=e instanceof Date?e:new Date(e);if(isNaN(r.getTime()))return String(e);const n=i&&i.locale||"en-US",a=i&&i.timeZone?i.timeZone:void 0,o=()=>{let k="";try{const X=new Intl.DateTimeFormat(n,{hour:"2-digit",minute:"2-digit",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(q=>q.type==="timeZoneName");if(k=X?X.value:"",k&&/^GMT[+-]/i.test(k))try{const ee=new Intl.DateTimeFormat(n,{timeStyle:"short",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(ws=>ws.type==="timeZoneName");ee&&ee.value&&!/^GMT[+-]/i.test(ee.value)&&(k=ee.value)}catch{}if(k&&/\s/.test(k)){const q=k.split(/\s+/).map(ee=>ee[0]).join("").toUpperCase();q.length>=2&&q.length<=4&&(k=q)}}catch{k=""}return k};if(!a){const k=this.date(r,t),Y=this.time(r,s),X=o();return k&&Y?`${k} ${Y} ${X}`.trim():""}const l=new Intl.DateTimeFormat(n,{timeZone:a,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hourCycle:"h23"}).formatToParts(r),d=k=>{const Y=l.find(X=>X.type===k);return Y?Y.value:""},h=d("year"),u=d("month"),m=d("day"),p=d("hour"),f=d("minute"),g=d("second"),b=u?String(parseInt(u,10)):"",y=m?String(parseInt(m,10)):"",w=p?String(parseInt(p,10)):"",x=p?parseInt(p,10)%12||12:"",A=p?parseInt(p,10)>=12?"PM":"AM":"",E=A?A.toLowerCase():"",j=new Intl.DateTimeFormat(n,{timeZone:a,month:"long"}).format(r),M=new Intl.DateTimeFormat(n,{timeZone:a,month:"short"}).format(r),O=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"long"}).format(r),re=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"short"}).format(r),fe={YYYY:h,YY:h?h.slice(-2):"",MMMM:j,MMM:M,MM:u,M:b,dddd:O,ddd:re,DD:m,D:y},ge={HH:p,H:w,hh:x!==""?String(x).padStart(2,"0"):"",h:x!==""?String(x):"",mm:f,m:f?String(parseInt(f,10)):"",ss:g,s:g?String(parseInt(g,10)):"",A,a:E},I=(k,Y)=>{if(!k)return"";const X=new RegExp(`(${Object.keys(Y).sort((q,ee)=>ee.length-q.length).join("|")})`,"g");return k.replace(X,q=>Y[q]??q)},R=I(t,fe),At=I(s,ge),ys=o();return R&&At?`${R} ${At} ${ys}`.trim():""}normalizeEpoch(e){if(e instanceof Date)return e;if(typeof e=="string"){const t=Number(e);if(Number.isFinite(t))e=t;else{const s=Date.parse(e);return Number.isFinite(s)?s:""}}else typeof e!="number"&&(e=Number(e));if(isNaN(e))return"";if(e<1e11)return e*1e3;if(e>1e12&&e<1e13)return e;throw new Error("Value doesn't look like epoch seconds or ms")}date_range(e,t=null,s="MM/DD/YYYY"){if(!e)return"";const i=t||new Date,r=this.date(e,s),n=this.date(i,s);return!r||!n?"":`${r} - ${n}`}datetime_range(e,t=null,s="MM/DD/YYYY",i="HH:mm"){if(!e)return"";const r=t||new Date,n=this.datetime(e,s,i),a=this.datetime(r,s,i);return!n||!a?"":`${n} - ${a}`}relative(e,t=!1){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const r=s-new Date,n=Math.abs(r),a=Math.floor(n/1e3),o=Math.floor(a/60),l=Math.floor(o/60),d=Math.floor(l/24),h=r>0;if(t)return d>365?Math.floor(d/365)+"y":d>30?Math.floor(d/30)+"mo":d>7?Math.floor(d/7)+"w":d>0?d+"d":l>0?l+"h":o>0?o+"m":"now";if(d>365){const u=Math.floor(d/365),m=h?"in ":"",p=h?"":" ago";return m+u+" year"+(u>1?"s":"")+p}if(d>30){const u=Math.floor(d/30),m=h?"in ":"",p=h?"":" ago";return m+u+" month"+(u>1?"s":"")+p}if(d>7){const u=Math.floor(d/7),m=h?"in ":"",p=h?"":" ago";return m+u+" week"+(u>1?"s":"")+p}if(d===1)return h?"tomorrow":"yesterday";if(d>0){const u=h?"in ":"",m=h?"":" ago";return u+d+" days"+m}if(l>0){const u=h?"in ":"",m=h?"":" ago";return u+l+" hour"+(l>1?"s":"")+m}if(o>0){const u=h?"in ":"",m=h?"":" ago";return u+o+" minute"+(o>1?"s":"")+m}if(a>30){const u=h?"in ":"",m=h?"":" ago";return u+a+" seconds"+m}return"just now"}iso(e,t=!1){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);return isNaN(s.getTime())?String(e):t?s.toISOString().split("T")[0]:s.toISOString()}number(e,t=2,s="en-US"){const i=parseFloat(e);return isNaN(i)?String(e):i.toLocaleString(s,{minimumFractionDigits:t,maximumFractionDigits:t})}currency(e,t="$",s=2){const i=parseInt(e);if(isNaN(i))return String(e);const r=Math.abs(i).toString(),n=i<0?"-":"";let a,o;r.length<=2?(a="0",o=r.padStart(2,"0")):(a=r.slice(0,-2),o=r.slice(-2)),a=a.replace(/\B(?=(\d{3})+(?!\d))/g,",");let l;if(s===0)parseInt(o)>=50&&(a=(parseInt(a.replace(/,/g,""))+1).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")),l=a;else if(s===2)l=`${a}.${o}`;else{const d=o.slice(0,s).padEnd(s,"0");l=`${a}.${d}`}return n+t+l}percent(e,t=0,s=!0){const i=parseFloat(e);if(isNaN(i))return String(e);const r=s?i*100:i;return this.number(r,t)+"%"}filesize(e,t=!1,s=1){const i=parseInt(e);if(isNaN(i))return String(e);const r=t?["B","KiB","MiB","GiB","TiB"]:["B","KB","MB","GB","TB"],n=t?1024:1e3;let a=i,o=0;for(;a>=n&&o<r.length-1;)a/=n,o++;const l=o===0?0:s;return`${a.toFixed(l)} ${r[o]}`}ordinal(e,t=!1){const s=parseInt(e);if(isNaN(s))return String(e);const i=s%10,r=s%100;let n="th";return i===1&&r!==11?n="st":i===2&&r!==12?n="nd":i===3&&r!==13&&(n="rd"),t?n:s+n}compact(e,t=1){const s=parseFloat(e);if(isNaN(s))return String(e);const i=Math.abs(s),r=s<0?"-":"";return i>=1e9?r+(i/1e9).toFixed(t)+"B":i>=1e6?r+(i/1e6).toFixed(t)+"M":i>=1e3?r+(i/1e3).toFixed(t)+"K":String(s)}add(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s+i}subtract(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s-i}multiply(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s*i}divide(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)||i===0?e:s/i}capitalize(e,t=!0){const s=String(e);return s?t?s.replace(/\b\w/g,i=>i.toUpperCase()):s.charAt(0).toUpperCase()+s.slice(1):""}replace(e,t,s="",i="g"){if(e==null)return"";const r=String(e);if(t==null||t==="")return r;if(t instanceof RegExp)return r.replace(t,String(s));const n=String(t),a=n.match(/^\/(.+)\/([a-z]*)$/i);if(a){const[,o,l]=a;try{return r.replace(new RegExp(o,l),String(s))}catch{}}return String(i).includes("g")?r.split(n).join(String(s)):r.replace(n,String(s))}truncate(e,t=50,s="..."){const i=String(e);return i.length<=t?i:i.substring(0,t)+s}truncate_front(e,t=8,s="..."){const i=String(e);return i.length<=t?i:`${s}${i.slice(-t)}`}truncate_middle(e,t=8,s="***"){const i=String(e);if(i.length<=t)return i;const r=Math.floor(t/2),n=i.substring(0,r),a=i.substring(i.length-r);return`${n}${s}${a}`}slug(e,t="-"){return String(e).toLowerCase().replace(/[^\w\s-]/g,"").replace(/\s+/g,t).replace(new RegExp(`${t}+`,"g"),t).replace(new RegExp(`^${t}|${t}$`,"g"),"")}initials(e,t=2){return String(e).split(/\s+/).filter(r=>r.length>0).slice(0,t).map(r=>r.charAt(0).toUpperCase()).join("")}mask(e,t="*",s=4){const i=String(e);if(i.length<=s)return i;const r=t.repeat(Math.max(0,i.length-s)),n=i.slice(-s);return r+n}email(e,t={}){const s=String(e).trim();if(!s)return"";if(t.link===!1)return s;const i=t.subject?`?subject=${encodeURIComponent(t.subject)}`:"",r=t.body?`&body=${encodeURIComponent(t.body)}`:"",n=t.class?` class="${t.class}"`:"";return`<a href="mailto:${s}${i}${r}"${n}>${s}</a>`}phone(e,t="US",s=!0){let i=String(e).replace(/\D/g,""),r=i;return t==="US"&&(i.length===10?r=`(${i.slice(0,3)}) ${i.slice(3,6)}-${i.slice(6)}`:i.length===11&&i[0]==="1"&&(r=`+1 (${i.slice(1,4)}) ${i.slice(4,7)}-${i.slice(7)}`)),s?`<a href="tel:${i}">${r}</a>`:r}url(e,t=null,s=!0){let i=String(e).trim();return i?(/^https?:\/\//.test(i)||(i="https://"+i),`<a href="${i}"${s?' target="_blank"':""}${s?' rel="noopener noreferrer"':""}>${t||i}</a>`):""}badge(e,t="auto"){if(Array.isArray(e))return e.map(n=>this.badge(n,t)).join(" ");const s=String(e);if(typeof t=="string"&&t.includes("=")){const n=Object.fromEntries(t.split(",").map(l=>l.split("=").map(d=>d.trim()))),a=n[s]||n[s.toLowerCase()]||this.inferBadgeType(s);return`<span class="badge ${a?`bg-${a}`:"bg-secondary"}">${s}</span>`}const i=t==="auto"?this.inferBadgeType(s):t;return`<span class="badge ${i?`bg-${i}`:"bg-secondary"}">${s}</span>`}badgeClass(e,t="auto"){const s=String(e),i=t==="auto"?this.inferBadgeType(s):t;return i?`bg-${i}`:"bg-secondary"}inferBadgeType(e){const t=e.toLowerCase();return["active","pass","success","complete","completed","approved","done","true","on","yes"].includes(t)?"success":["error","failed","fail","rejected","deleted","cancelled","false","off","no","declined"].includes(t)?"danger":["warning","pending","review","processing","uploading"].includes(t)?"warning":["info","new","draft"].includes(t)?"info":(["inactive","disabled","archived","suspended"].includes(t),"secondary")}status(e){return this._status(e)}status_icon(e){return this._status(e,{},{},!1,!0)}status_text(e){return this._status(e,{},{},!0,!1)}_status(e,t={},s={},i=!1,r=!1){const n=String(e).toLowerCase(),a={active:"bi bi-check-circle-fill",approved:"bi bi-check-circle-fill",declined:"bi bi-x-circle-fill",inactive:"bi bi-pause-circle-fill",pending:"bi bi-clock-fill",success:"bi bi-check-circle-fill",error:"bi bi-exclamation-triangle-fill",warning:"bi bi-exclamation-triangle-fill"},o={active:"success",approved:"success",declined:"danger",inactive:"secondary",pending:"warning",success:"success",error:"danger",warning:"warning"},l=t[n]||a[n]||"",d=s[n]||o[n]||"secondary";let h="";!i&&l&&(h=`<i class="${l}"></i>`);let u="";return r||(u=e),`<span class="text-${d}">${h}${h?" ":""}${u}</span>`}boolean(e,t="True",s="False",i=!1){const r=e?t:s;return i?`<span class="text-${e?"success":"danger"}">${r}</span>`:r}bool(e){return e==null||e===0||e===""||e===!1||e==="false"?!1:e===!0||e==="true"?!0:!(Array.isArray(e)&&e.length===0||e&&typeof e=="object"&&e.constructor===Object&&Object.keys(e).length===0)}icon(e,t={}){const s=String(e).toLowerCase(),i=t[s]||"";return i?`<i class="${i}"></i>`:""}yesnoicon(e,t="bi bi-check-circle-fill text-success",s="bi bi-x-circle-fill text-danger"){return e?`<i class="${t}"></i>`:`<i class="${s}"></i>`}image(e,t="thumbnail",s="img-fluid",i=""){const r=this._extractImageUrl(e,t);return r?`<img src="${r}" class="${s}" alt="${i}" />`:""}avatar(e,t="md",s="rounded-circle",i=""){const r=this._extractImageUrl(e,"square_sm")||Dt,n={xs:"width: 1.5rem; height: 1.5rem;",sm:"width: 2rem; height: 2rem;",md:"width: 3rem; height: 3rem;",lg:"width: 4rem; height: 4rem;",xl:"width: 5rem; height: 5rem;"},a=n[t]||n.md,l=`object-fit-cover ${s}`.trim();return`<img src="${r}" class="${l}" style="${a}" alt="${i}" />`}tooltip(e,t="",s="top",i=""){if(e==null)return"";const r=String(e),n=i==="html"?t:this.escapeHtml(t);return`<span data-bs-toggle="tooltip" data-bs-placement="${s}" ${i==="html"?'data-bs-html="true"':""} data-bs-title="${n}">${r}</span>`}_extractImageUrl(e,t="thumbnail"){if(!e)return null;if(typeof e=="string")return e;if(typeof e=="object"){if(e.attributes&&(e=e.attributes),t==="thumbnail"&&e.thumbnail&&typeof e.thumbnail=="string")return e.thumbnail;if(e.renditions&&typeof e.renditions=="object"){const s=e.renditions[t];if(s&&s.url)return s.url;const i=Object.values(e.renditions);if(i.length>0&&i[0].url)return i[0].url}if(e.url)return e.url}return null}default(e,t=""){return e==null||e===""?t:e}equals(e,t,s,i=""){return e==t?s:i}plural(e,t,s=null,i=!0){if(e==null||t===null||t===void 0)return i?`${e} ${t}`:t||"";const r=parseInt(e);if(isNaN(r))return i?`${e} ${t}`:t||"";const n=Math.abs(r)===1?t:s||t+"s";return i?`${r} ${n}`:n}formatList(e,t={}){if(!Array.isArray(e))return String(e);const{conjunction:s="and",limit:i=null,moreText:r="others"}=t;if(e.length===0)return"";if(e.length===1)return String(e[0]);let n=e.slice(),a=!1;if(i&&e.length>i&&(n=e.slice(0,i),a=!0),a){const o=e.length-i;return`${n.join(", ")}, ${s} ${o} ${r}`}return n.length===2?`${n[0]} ${s} ${n[1]}`:`${n.slice(0,-1).join(", ")}, ${s} ${n[n.length-1]}`}duration(e,t="ms",s=!1,i=2){if(e==null)return"";const r=parseFloat(e);if(isNaN(r))return String(e);let n;switch(t){case"s":case"sec":case"seconds":n=r*1e3;break;case"m":case"min":case"minutes":n=r*6e4;break;case"h":case"hr":case"hours":n=r*36e5;break;case"d":case"day":case"days":n=r*864e5;break;default:n=r}const a=[{name:"day",short:"d",value:864e5},{name:"hour",short:"h",value:36e5},{name:"minute",short:"m",value:6e4},{name:"second",short:"s",value:1e3}];if(n===0)return s?"0s":"0 seconds";const o=Math.abs(n),l=n<0?"-":"",d=[];let h=o;for(const u of a)if(h>=u.value){const m=Math.floor(h/u.value);h=h%u.value;const p=s?u.short:m===1?u.name:u.name+"s";if(d.push(s?`${m}${p}`:`${m} ${p}`),d.length>=i)break}return d.length===0?s?`${Math.round(o)}ms`:`${Math.round(o)} milliseconds`:l+(s?d.join(""):d.join(" "))}hash(e,t=8,s="",i="..."){if(e==null)return"";const r=String(e);return r.length<=t?s+r:s+r.substring(0,t)+i}stripHtml(e){return e==null?"":String(e).replace(/<[^>]*>/g,"")}highlight(e,t,s="highlight"){if(e==null||!t)return String(e||"");const i=String(t).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(`(${i})`,"gi");return String(e).replace(r,`<mark class="${s}">$1</mark>`)}hex(e,t=!1,s=!1){if(e==null)return"";let i="";const r=n=>Array.from(n).map(a=>a.toString(16).padStart(2,"0")).join("");if(typeof e=="number"){let n=Math.abs(Math.trunc(e)).toString(16);n.length%2&&(n="0"+n),i=n}else if(e instanceof Uint8Array)i=r(e);else if(e instanceof ArrayBuffer)i=r(new Uint8Array(e));else if(Array.isArray(e)&&e.every(n=>typeof n=="number"))i=r(Uint8Array.from(e.map(n=>n&255)));else{const a=new TextEncoder().encode(String(e));i=r(a)}return t&&(i=i.toUpperCase()),(s?"0x":"")+i}unhex(e){if(e==null)return"";let t=String(e).trim();if((t.startsWith("0x")||t.startsWith("0X"))&&(t=t.slice(2)),t=t.replace(/\s+/g,""),t.length===0)return"";t.length%2!==0&&(t="0"+t);const s=new Uint8Array(t.length/2);for(let i=0;i<t.length;i+=2){const r=parseInt(t.slice(i,i+2),16);if(Number.isNaN(r))return String(e);s[i/2]=r}try{return new TextDecoder().decode(s)}catch{let r="";for(const n of s)r+=String.fromCharCode(n);return r}}json(e,t=2){try{return JSON.stringify(e,null,t)}catch{return String(e)}}has(e){return this.formatters.has(e.toLowerCase())}unregister(e){return this.formatters.delete(e.toLowerCase())}listFormatters(){return Array.from(this.formatters.keys()).sort()}iter(e){return e==null?[]:Array.isArray(e)?e:typeof e=="object"?Object.entries(e).map(([t,s])=>({key:t,value:s})):[{key:"0",value:e}]}}const V=new It;window.dataFormatter=V;class ${static getContextData(e,t){if(!t||e==null)return;let s=t,i="",r=0,n=-1;for(let o=0;o<t.length;o++){const l=t[o];if(l==="(")r++;else if(l===")")r--;else if(l==="|"&&r===0){n=o;break}}n>-1&&(s=t.substring(0,n).trim(),i=t.substring(n+1).trim());const a=this.getNestedValue(e,s);return i?V.pipe(a,i,e):a}static getNestedValue(e,t){if(!t||e==null)return;if(!t.includes(".")){if(t in e){const r=e[t];return typeof r=="function"?r.call(e):r}return}const s=t.split(".");let i=e;for(let r=0;r<s.length;r++){const n=s[r];if(i==null)return;if(r===0)if(i.hasOwnProperty(n)){const a=i[n];typeof a=="function"?i=a.call(e):i=a}else return;else{if(i&&typeof i.getContextValue=="function"){const a=s.slice(r).join(".");return i.getContextValue(a)}if(Array.isArray(i)&&!isNaN(n))i=i[parseInt(n)];else if(i.hasOwnProperty(n))i=i[n];else if(typeof i[n]=="function")i=i[n].call(i);else return}}return i}static isNullOrUndefined(e){return e==null}static deepClone(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(e instanceof Array)return e.map(t=>this.deepClone(t));if(e instanceof Object){const t={};for(const s in e)e.hasOwnProperty(s)&&(t[s]=this.deepClone(e[s]));return t}}static deepMerge(e,...t){if(!t.length)return e;const s=t.shift();if(this.isObject(e)&&this.isObject(s))for(const i in s)this.isObject(s[i])?(e[i]||Object.assign(e,{[i]:{}}),this.deepMerge(e[i],s[i])):Object.assign(e,{[i]:s[i]});return this.deepMerge(e,...t)}static isObject(e){return e&&typeof e=="object"&&!Array.isArray(e)}static debounce(e,t){let s;return function(...r){const n=()=>{clearTimeout(s),e(...r)};clearTimeout(s),s=setTimeout(n,t)}}static throttle(e,t){let s;return function(...i){s||(e.apply(this,i),s=!0,setTimeout(()=>s=!1,t))}}static generateId(e=""){const t=Date.now().toString(36),s=Math.random().toString(36).substr(2,9);return e?`${e}_${t}_${s}`:`${t}_${s}`}static escapeHtml(e){const t={"&":"&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 Ae(i,t):i):new Ae(e,t)}}class Ae{constructor(e,t=null){if(Object.defineProperty(this,"_data",{value:e,writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(this,"_rootContext",{value:t,writable:!1,enumerable:!1,configurable:!1}),e&&typeof e=="object"){for(const s in e)if(e.hasOwnProperty(s)){const i=e[s];this[s]=$.wrapData(i,t)}}}getContextValue(e){let t=e,s="",i=0,r=-1;for(let a=0;a<e.length;a++){const o=e[a];if(o==="(")i++;else if(o===")")i--;else if(o==="|"&&i===0){r=a;break}}r>-1&&(t=e.substring(0,r).trim(),s=e.substring(r+1).trim());let n;return t in this&&t!=="_data"&&t!=="_rootContext"?n=this[t]:n=$.getNestedValue(this._data,t),s&&n!==void 0?V.pipe(n,s,this._rootContext||this._data):n}has(e){return this._data&&this._data.hasOwnProperty(e)}toJSON(){return this._data}}$.DataWrapper=Ae,typeof window<"u"&&(window.utils=$);const Mt=Object.prototype.toString,ne=Array.isArray||function(c){return Mt.call(c)==="[object Array]"},de=function(c){return typeof c=="function"},Xe=function(c){return c!==null&&typeof c=="object"};function kt(){return typeof window>"u"?null:window.MOJO?.dataFormatter?window.MOJO.dataFormatter:window.dataFormatter?window.dataFormatter:null}const et=function(c){const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(c).replace(/[&<>"'`=\/]/g,function(t){return e[t]})};class tt{constructor(e){this.string=e,this.tail=e,this.pos=0}eos(){return this.tail===""}scan(e){const t=this.tail.match(e);if(!t||t.index!==0)return"";const s=t[0];return this.tail=this.tail.substring(s.length),this.pos+=s.length,s}scanUntil(e){const t=this.tail.search(e);let s;switch(t){case-1:s=this.tail,this.tail="";break;case 0:s="";break;default:s=this.tail.substring(0,t),this.tail=this.tail.substring(t)}return this.pos+=s.length,s}}class be{constructor(e,t){this.view=e,this.cache={".":this.view},this.parent=t,this.view?._cacheId||this.view&&typeof this.view=="object"&&(this.view._cacheId=Math.random().toString(36).substring(2))}push(e){return new be(e,this)}lookup(e){if(this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;if(this.renderCache.has(i))return this.renderCache.get(i)}if(e===".")return this.view;if(e&&e.startsWith(".")){let i=e.substring(1),r=!1,n=null;const a=i.indexOf("|");if(a!==-1&&(n=i.substring(a+1).trim(),i=i.substring(0,a).trim()),i.endsWith("|iter")&&(i=i.substring(0,i.length-5),r=!0),this.view&&typeof this.view=="object"){let o;if(typeof this.view.getContextValue=="function")try{o=this.view.getContextValue(i),o!==void 0&&de(o)&&(o=o.call(this.view))}catch{o=void 0}if(o===void 0&&i in this.view&&(o=this.view[i],de(o)&&(o=o.call(this.view))),n&&o!==void 0)try{const l=kt();l&&typeof l.pipe=="function"&&(o=l.pipe(o,n,this))}catch{}return ne(o)?r?o:o.length>0:Xe(o)?r?Object.entries(o).map(([l,d])=>({key:l,value:d})):Object.keys(o).length>0:o}return}const t=this.cache;let s;if(t.hasOwnProperty(e))s=t[e];else{let i=this,r,n,a,o=!1;for(;i;){if(i.view&&typeof i.view.getContextValue=="function")try{r=i.view.getContextValue(e),r!==void 0&&(o=!0)}catch{o=!1}if(!o)if(e.indexOf(".")>0)for(r=i.view,n=e.split("."),a=0;r!=null&&a<n.length;)if(r&&typeof r.getContextValue=="function"&&a<n.length)try{const l=n.slice(a).join(".");r=r.getContextValue(l),a=n.length,r!==void 0&&(o=!0)}catch{a===n.length-1&&(o=Fe(r,n[a])||st(r,n[a])),r=r[n[a++]]}else a===n.length-1&&(o=Fe(r,n[a])||st(r,n[a])),r=r[n[a++]];else r=i.view[e],o=Fe(i.view,e);if(o){s=r;break}i=i.parent}t[e]=s}if(de(s)&&(s=s.call(this.view)),this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;this.renderCache.set(i,s)}return s}}function Fe(c,e){return c!=null&&typeof c=="object"&&e in c}function st(c,e){return c!=null&&typeof c!="object"&&c.hasOwnProperty&&c.hasOwnProperty(e)}class it{constructor(){this.templateCache=new Map}clearCache(){this.templateCache.clear()}parse(e,t){t=t||["{{","}}"];const s=e+":"+t.join(":");let i=this.templateCache.get(s);return i==null&&(i=this.parseTemplate(e,t),this.templateCache.set(s,i)),i}parseTemplate(e,t){if(!e)return[];const s=t[0],i=t[1],r=new tt(e),n=[];let a,o,l,d,h;const u=new RegExp(Te(s)+"\\s*"),m=new RegExp("\\s*"+Te(i)),p=new RegExp("\\s*"+Te("}"+i));for(;!r.eos();){if(a=r.pos,l=r.scanUntil(u),l)for(let f=0;f<l.length;++f)d=l.charAt(f),d===`
14
+ `}nl2br(e){return e==null?"":this.escapeHtml(String(e)).replace(/\r\n|\r|\n/g,"<br>")}code(e,t=""){if(e==null)return"";const s=t?`language-${this.escapeHtml(String(t))}`:"",i=this.escapeHtml(String(e));return`<pre class="bg-light p-2 rounded border"><code class="${s}">${i}</code></pre>`}register(e,t){if(typeof t!="function")throw new Error(`Formatter must be a function, got ${typeof t}`);return this.formatters.set(e.toLowerCase(),t),this}apply(e,t,...s){try{const i=this.formatters.get(e.toLowerCase());return i?i(t,...s):(console.warn(`Formatter '${e}' not found`),t)}catch(i){return console.error(`Error in formatter '${e}':`,i),t}}pipe(e,t,s=null){return t?this.parsePipeString(t,s).reduce((r,n)=>this.apply(n.name,r,...n.args),e):e}parsePipeString(e,t=null){const s=[],i=e.split("|").map(r=>r.trim());for(const r of i){const n=this.parseFormatter(r,t);n&&s.push(n)}return s}parseFormatter(e,t=null){const s=e.match(/^([a-zA-Z_]\w*)\s*\((.*)\)$/);if(s){const[,r,n]=s,a=n?this.parseArguments(n,t):[];return{name:r,args:a}}const i=e.match(/^([a-zA-Z_]\w*)(?::(.+))?$/);if(i){const[,r,n]=i,a=n?this.parseColonArguments(n,t):[];return{name:r,args:a}}return null}parseArguments(e,t=null){const s=[];let i="",r=!1,n=null,a=0;for(let o=0;o<e.length;o++){const l=e[o];!r&&(l==='"'||l==="'")?(r=!0,n=l,i+=l):r&&l===n&&e[o-1]!=="\\"?(r=!1,n=null,i+=l):!r&&l==="{"?(a++,i+=l):!r&&l==="}"?(a--,i+=l):!r&&a===0&&l===","?(s.push(this.parseValue(i.trim(),t)),i=""):i+=l}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseColonArguments(e,t=null){const s=[];let i="",r=!1,n=null;for(let a=0;a<e.length;a++){const o=e[a];!r&&(o==='"'||o==="'")?(r=!0,n=o,i+=o):r&&o===n&&e[a-1]!=="\\"?(r=!1,n=null,i+=o):!r&&o===":"?(s.push(this.parseValue(i.trim(),t)),i=""):i+=o}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseValue(e,t=null){if(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);if(e==="true")return!0;if(e==="false")return!1;if(e==="null")return null;if(e!=="undefined"){if(!isNaN(e)&&e!=="")return Number(e);if(e.startsWith("{")&&e.endsWith("}"))try{return JSON.parse(e)}catch{}if(t&&this.isIdentifier(e)){if(!e.includes(".")&&Object.prototype.hasOwnProperty.call(t,e))return t[e];if(t.get&&typeof t.get=="function"){const s=t.get(e);if(s!==void 0)return s}if(t.getContextValue&&typeof t.getContextValue=="function"){const s=t.getContextValue(e);if(s!==void 0)return s}if(e.includes(".")){const s=window.MOJOUtils||(typeof require<"u"?require("./MOJOUtils.js").default:null);if(s){const i=s.getNestedValue(t,e);if(i!==void 0)return i}}}return e}}isIdentifier(e){return/^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/.test(e)}date(e,t="MM/DD/YYYY"){if(!e)return"";e=this.normalizeEpoch(e);let s;if(e instanceof Date)s=e;else if(typeof e=="string")if(/^\d{4}-\d{2}-\d{2}$/.test(e)){const[a,o,l]=e.split("-").map(Number);s=new Date(a,o-1,l)}else s=new Date(e);else s=new Date(e);if(isNaN(s.getTime()))return String(e);const i={YYYY:s.getFullYear(),YY:String(s.getFullYear()).slice(-2),MMMM:s.toLocaleDateString("en-US",{month:"long"}),MMM:s.toLocaleDateString("en-US",{month:"short"}),MM:String(s.getMonth()+1).padStart(2,"0"),M:s.getMonth()+1,dddd:s.toLocaleDateString("en-US",{weekday:"long"}),ddd:s.toLocaleDateString("en-US",{weekday:"short"}),DD:String(s.getDate()).padStart(2,"0"),D:s.getDate()};let r=t;const n=new RegExp(`(${Object.keys(i).join("|")})`,"g");return r=r.replace(n,a=>i[a]||a),r}time(e,t="HH:mm:ss"){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const i=s.getHours(),r={HH:String(i).padStart(2,"0"),H:i,hh:String(i%12||12).padStart(2,"0"),h:i%12||12,mm:String(s.getMinutes()).padStart(2,"0"),m:s.getMinutes(),ss:String(s.getSeconds()).padStart(2,"0"),s:s.getSeconds(),A:i>=12?"PM":"AM",a:i>=12?"pm":"am"};let n=t;const a=Object.keys(r).sort((o,l)=>l.length-o.length);for(const o of a)n=n.replace(new RegExp(o,"g"),r[o]);return n}datetime(e,t="MM/DD/YYYY",s="HH:mm:ss"){e=this.normalizeEpoch(e);const i=this.date(e,t),r=this.time(e,s);return i&&r?`${i} ${r}`:""}datetime_tz(e,t="MM/DD/YYYY",s="HH:mm:ss",i={}){if(!e)return"";e=this.normalizeEpoch(e);const r=e instanceof Date?e:new Date(e);if(isNaN(r.getTime()))return String(e);const n=i&&i.locale||"en-US",a=i&&i.timeZone?i.timeZone:void 0,o=()=>{let k="";try{const X=new Intl.DateTimeFormat(n,{hour:"2-digit",minute:"2-digit",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(q=>q.type==="timeZoneName");if(k=X?X.value:"",k&&/^GMT[+-]/i.test(k))try{const ee=new Intl.DateTimeFormat(n,{timeStyle:"short",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(ws=>ws.type==="timeZoneName");ee&&ee.value&&!/^GMT[+-]/i.test(ee.value)&&(k=ee.value)}catch{}if(k&&/\s/.test(k)){const q=k.split(/\s+/).map(ee=>ee[0]).join("").toUpperCase();q.length>=2&&q.length<=4&&(k=q)}}catch{k=""}return k};if(!a){const k=this.date(r,t),Y=this.time(r,s),X=o();return k&&Y?`${k} ${Y} ${X}`.trim():""}const l=new Intl.DateTimeFormat(n,{timeZone:a,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hourCycle:"h23"}).formatToParts(r),d=k=>{const Y=l.find(X=>X.type===k);return Y?Y.value:""},h=d("year"),u=d("month"),m=d("day"),p=d("hour"),f=d("minute"),g=d("second"),b=u?String(parseInt(u,10)):"",y=m?String(parseInt(m,10)):"",v=p?String(parseInt(p,10)):"",x=p?parseInt(p,10)%12||12:"",A=p?parseInt(p,10)>=12?"PM":"AM":"",E=A?A.toLowerCase():"",j=new Intl.DateTimeFormat(n,{timeZone:a,month:"long"}).format(r),M=new Intl.DateTimeFormat(n,{timeZone:a,month:"short"}).format(r),O=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"long"}).format(r),re=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"short"}).format(r),fe={YYYY:h,YY:h?h.slice(-2):"",MMMM:j,MMM:M,MM:u,M:b,dddd:O,ddd:re,DD:m,D:y},ge={HH:p,H:v,hh:x!==""?String(x).padStart(2,"0"):"",h:x!==""?String(x):"",mm:f,m:f?String(parseInt(f,10)):"",ss:g,s:g?String(parseInt(g,10)):"",A,a:E},I=(k,Y)=>{if(!k)return"";const X=new RegExp(`(${Object.keys(Y).sort((q,ee)=>ee.length-q.length).join("|")})`,"g");return k.replace(X,q=>Y[q]??q)},R=I(t,fe),At=I(s,ge),ys=o();return R&&At?`${R} ${At} ${ys}`.trim():""}normalizeEpoch(e){if(e instanceof Date)return e;if(typeof e=="string"){const t=Number(e);if(Number.isFinite(t))e=t;else{const s=Date.parse(e);return Number.isFinite(s)?s:""}}else typeof e!="number"&&(e=Number(e));if(isNaN(e))return"";if(e<1e11)return e*1e3;if(e>1e12&&e<1e13)return e;throw new Error("Value doesn't look like epoch seconds or ms")}date_range(e,t=null,s="MM/DD/YYYY"){if(!e)return"";const i=t||new Date,r=this.date(e,s),n=this.date(i,s);return!r||!n?"":`${r} - ${n}`}datetime_range(e,t=null,s="MM/DD/YYYY",i="HH:mm"){if(!e)return"";const r=t||new Date,n=this.datetime(e,s,i),a=this.datetime(r,s,i);return!n||!a?"":`${n} - ${a}`}relative(e,t=!1){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const r=s-new Date,n=Math.abs(r),a=Math.floor(n/1e3),o=Math.floor(a/60),l=Math.floor(o/60),d=Math.floor(l/24),h=r>0;if(t)return d>365?Math.floor(d/365)+"y":d>30?Math.floor(d/30)+"mo":d>7?Math.floor(d/7)+"w":d>0?d+"d":l>0?l+"h":o>0?o+"m":"now";if(d>365){const u=Math.floor(d/365),m=h?"in ":"",p=h?"":" ago";return m+u+" year"+(u>1?"s":"")+p}if(d>30){const u=Math.floor(d/30),m=h?"in ":"",p=h?"":" ago";return m+u+" month"+(u>1?"s":"")+p}if(d>7){const u=Math.floor(d/7),m=h?"in ":"",p=h?"":" ago";return m+u+" week"+(u>1?"s":"")+p}if(d===1)return h?"tomorrow":"yesterday";if(d>0){const u=h?"in ":"",m=h?"":" ago";return u+d+" days"+m}if(l>0){const u=h?"in ":"",m=h?"":" ago";return u+l+" hour"+(l>1?"s":"")+m}if(o>0){const u=h?"in ":"",m=h?"":" ago";return u+o+" minute"+(o>1?"s":"")+m}if(a>30){const u=h?"in ":"",m=h?"":" ago";return u+a+" seconds"+m}return"just now"}iso(e,t=!1){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);return isNaN(s.getTime())?String(e):t?s.toISOString().split("T")[0]:s.toISOString()}number(e,t=2,s="en-US"){const i=parseFloat(e);return isNaN(i)?String(e):i.toLocaleString(s,{minimumFractionDigits:t,maximumFractionDigits:t})}currency(e,t="$",s=2){const i=parseInt(e);if(isNaN(i))return String(e);const r=Math.abs(i).toString(),n=i<0?"-":"";let a,o;r.length<=2?(a="0",o=r.padStart(2,"0")):(a=r.slice(0,-2),o=r.slice(-2)),a=a.replace(/\B(?=(\d{3})+(?!\d))/g,",");let l;if(s===0)parseInt(o)>=50&&(a=(parseInt(a.replace(/,/g,""))+1).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")),l=a;else if(s===2)l=`${a}.${o}`;else{const d=o.slice(0,s).padEnd(s,"0");l=`${a}.${d}`}return n+t+l}percent(e,t=0,s=!0){const i=parseFloat(e);if(isNaN(i))return String(e);const r=s?i*100:i;return this.number(r,t)+"%"}filesize(e,t=!1,s=1){const i=parseInt(e);if(isNaN(i))return String(e);const r=t?["B","KiB","MiB","GiB","TiB"]:["B","KB","MB","GB","TB"],n=t?1024:1e3;let a=i,o=0;for(;a>=n&&o<r.length-1;)a/=n,o++;const l=o===0?0:s;return`${a.toFixed(l)} ${r[o]}`}ordinal(e,t=!1){const s=parseInt(e);if(isNaN(s))return String(e);const i=s%10,r=s%100;let n="th";return i===1&&r!==11?n="st":i===2&&r!==12?n="nd":i===3&&r!==13&&(n="rd"),t?n:s+n}compact(e,t=1){const s=parseFloat(e);if(isNaN(s))return String(e);const i=Math.abs(s),r=s<0?"-":"";return i>=1e9?r+(i/1e9).toFixed(t)+"B":i>=1e6?r+(i/1e6).toFixed(t)+"M":i>=1e3?r+(i/1e3).toFixed(t)+"K":String(s)}add(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s+i}subtract(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s-i}multiply(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s*i}divide(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)||i===0?e:s/i}capitalize(e,t=!0){const s=String(e);return s?t?s.replace(/\b\w/g,i=>i.toUpperCase()):s.charAt(0).toUpperCase()+s.slice(1):""}replace(e,t,s="",i="g"){if(e==null)return"";const r=String(e);if(t==null||t==="")return r;if(t instanceof RegExp)return r.replace(t,String(s));const n=String(t),a=n.match(/^\/(.+)\/([a-z]*)$/i);if(a){const[,o,l]=a;try{return r.replace(new RegExp(o,l),String(s))}catch{}}return String(i).includes("g")?r.split(n).join(String(s)):r.replace(n,String(s))}truncate(e,t=50,s="..."){const i=String(e);return i.length<=t?i:i.substring(0,t)+s}truncate_front(e,t=8,s="..."){const i=String(e);return i.length<=t?i:`${s}${i.slice(-t)}`}truncate_middle(e,t=8,s="***"){const i=String(e);if(i.length<=t)return i;const r=Math.floor(t/2),n=i.substring(0,r),a=i.substring(i.length-r);return`${n}${s}${a}`}slug(e,t="-"){return String(e).toLowerCase().replace(/[^\w\s-]/g,"").replace(/\s+/g,t).replace(new RegExp(`${t}+`,"g"),t).replace(new RegExp(`^${t}|${t}$`,"g"),"")}initials(e,t=2){return String(e).split(/\s+/).filter(r=>r.length>0).slice(0,t).map(r=>r.charAt(0).toUpperCase()).join("")}mask(e,t="*",s=4){const i=String(e);if(i.length<=s)return i;const r=t.repeat(Math.max(0,i.length-s)),n=i.slice(-s);return r+n}email(e,t={}){const s=String(e).trim();if(!s)return"";if(t.link===!1)return s;const i=t.subject?`?subject=${encodeURIComponent(t.subject)}`:"",r=t.body?`&body=${encodeURIComponent(t.body)}`:"",n=t.class?` class="${t.class}"`:"";return`<a href="mailto:${s}${i}${r}"${n}>${s}</a>`}phone(e,t="US",s=!0){let i=String(e).replace(/\D/g,""),r=i;return t==="US"&&(i.length===10?r=`(${i.slice(0,3)}) ${i.slice(3,6)}-${i.slice(6)}`:i.length===11&&i[0]==="1"&&(r=`+1 (${i.slice(1,4)}) ${i.slice(4,7)}-${i.slice(7)}`)),s?`<a href="tel:${i}">${r}</a>`:r}url(e,t=null,s=!0){let i=String(e).trim();return i?(/^https?:\/\//.test(i)||(i="https://"+i),`<a href="${i}"${s?' target="_blank"':""}${s?' rel="noopener noreferrer"':""}>${t||i}</a>`):""}badge(e,t="auto"){if(Array.isArray(e))return e.map(n=>this.badge(n,t)).join(" ");const s=String(e);if(typeof t=="string"&&t.includes("=")){const n=Object.fromEntries(t.split(",").map(l=>l.split("=").map(d=>d.trim()))),a=n[s]||n[s.toLowerCase()]||this.inferBadgeType(s);return`<span class="badge ${a?`bg-${a}`:"bg-secondary"}">${s}</span>`}const i=t==="auto"?this.inferBadgeType(s):t;return`<span class="badge ${i?`bg-${i}`:"bg-secondary"}">${s}</span>`}badgeClass(e,t="auto"){const s=String(e),i=t==="auto"?this.inferBadgeType(s):t;return i?`bg-${i}`:"bg-secondary"}inferBadgeType(e){const t=e.toLowerCase();return["active","pass","success","complete","completed","approved","done","true","on","yes"].includes(t)?"success":["error","failed","fail","rejected","deleted","cancelled","false","off","no","declined"].includes(t)?"danger":["warning","pending","review","processing","uploading"].includes(t)?"warning":["info","new","draft"].includes(t)?"info":(["inactive","disabled","archived","suspended"].includes(t),"secondary")}status(e){return this._status(e)}status_icon(e){return this._status(e,{},{},!1,!0)}status_text(e){return this._status(e,{},{},!0,!1)}_status(e,t={},s={},i=!1,r=!1){const n=String(e).toLowerCase(),a={active:"bi bi-check-circle-fill",approved:"bi bi-check-circle-fill",declined:"bi bi-x-circle-fill",inactive:"bi bi-pause-circle-fill",pending:"bi bi-clock-fill",success:"bi bi-check-circle-fill",error:"bi bi-exclamation-triangle-fill",warning:"bi bi-exclamation-triangle-fill"},o={active:"success",approved:"success",declined:"danger",inactive:"secondary",pending:"warning",success:"success",error:"danger",warning:"warning"},l=t[n]||a[n]||"",d=s[n]||o[n]||"secondary";let h="";!i&&l&&(h=`<i class="${l}"></i>`);let u="";return r||(u=e),`<span class="text-${d}">${h}${h?" ":""}${u}</span>`}boolean(e,t="True",s="False",i=!1){const r=e?t:s;return i?`<span class="text-${e?"success":"danger"}">${r}</span>`:r}bool(e){return e==null||e===0||e===""||e===!1||e==="false"?!1:e===!0||e==="true"?!0:!(Array.isArray(e)&&e.length===0||e&&typeof e=="object"&&e.constructor===Object&&Object.keys(e).length===0)}icon(e,t={}){const s=String(e).toLowerCase(),i=t[s]||"";return i?`<i class="${i}"></i>`:""}yesnoicon(e,t="bi bi-check-circle-fill text-success",s="bi bi-x-circle-fill text-danger"){return e?`<i class="${t}"></i>`:`<i class="${s}"></i>`}image(e,t="thumbnail",s="img-fluid",i=""){const r=this._extractImageUrl(e,t);return r?`<img src="${r}" class="${s}" alt="${i}" />`:""}avatar(e,t="md",s="rounded-circle",i=""){const r=this._extractImageUrl(e,"square_sm")||Dt,n={xs:"width: 1.5rem; height: 1.5rem;",sm:"width: 2rem; height: 2rem;",md:"width: 3rem; height: 3rem;",lg:"width: 4rem; height: 4rem;",xl:"width: 5rem; height: 5rem;"},a=n[t]||n.md,l=`object-fit-cover ${s}`.trim();return`<img src="${r}" class="${l}" style="${a}" alt="${i}" />`}tooltip(e,t="",s="top",i=""){if(e==null)return"";const r=String(e),n=i==="html"?t:this.escapeHtml(t);return`<span data-bs-toggle="tooltip" data-bs-placement="${s}" ${i==="html"?'data-bs-html="true"':""} data-bs-title="${n}">${r}</span>`}_extractImageUrl(e,t="thumbnail"){if(!e)return null;if(typeof e=="string")return e;if(typeof e=="object"){if(e.attributes&&(e=e.attributes),t==="thumbnail"&&e.thumbnail&&typeof e.thumbnail=="string")return e.thumbnail;if(e.renditions&&typeof e.renditions=="object"){const s=e.renditions[t];if(s&&s.url)return s.url;const i=Object.values(e.renditions);if(i.length>0&&i[0].url)return i[0].url}if(e.url)return e.url}return null}default(e,t=""){return e==null||e===""?t:e}equals(e,t,s,i=""){return e==t?s:i}plural(e,t,s=null,i=!0){if(e==null||t===null||t===void 0)return i?`${e} ${t}`:t||"";const r=parseInt(e);if(isNaN(r))return i?`${e} ${t}`:t||"";const n=Math.abs(r)===1?t:s||t+"s";return i?`${r} ${n}`:n}formatList(e,t={}){if(!Array.isArray(e))return String(e);const{conjunction:s="and",limit:i=null,moreText:r="others"}=t;if(e.length===0)return"";if(e.length===1)return String(e[0]);let n=e.slice(),a=!1;if(i&&e.length>i&&(n=e.slice(0,i),a=!0),a){const o=e.length-i;return`${n.join(", ")}, ${s} ${o} ${r}`}return n.length===2?`${n[0]} ${s} ${n[1]}`:`${n.slice(0,-1).join(", ")}, ${s} ${n[n.length-1]}`}duration(e,t="ms",s=!1,i=2){if(e==null)return"";const r=parseFloat(e);if(isNaN(r))return String(e);let n;switch(t){case"s":case"sec":case"seconds":n=r*1e3;break;case"m":case"min":case"minutes":n=r*6e4;break;case"h":case"hr":case"hours":n=r*36e5;break;case"d":case"day":case"days":n=r*864e5;break;default:n=r}const a=[{name:"day",short:"d",value:864e5},{name:"hour",short:"h",value:36e5},{name:"minute",short:"m",value:6e4},{name:"second",short:"s",value:1e3}];if(n===0)return s?"0s":"0 seconds";const o=Math.abs(n),l=n<0?"-":"",d=[];let h=o;for(const u of a)if(h>=u.value){const m=Math.floor(h/u.value);h=h%u.value;const p=s?u.short:m===1?u.name:u.name+"s";if(d.push(s?`${m}${p}`:`${m} ${p}`),d.length>=i)break}return d.length===0?s?`${Math.round(o)}ms`:`${Math.round(o)} milliseconds`:l+(s?d.join(""):d.join(" "))}hash(e,t=8,s="",i="..."){if(e==null)return"";const r=String(e);return r.length<=t?s+r:s+r.substring(0,t)+i}stripHtml(e){return e==null?"":String(e).replace(/<[^>]*>/g,"")}highlight(e,t,s="highlight"){if(e==null||!t)return String(e||"");const i=String(t).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(`(${i})`,"gi");return String(e).replace(r,`<mark class="${s}">$1</mark>`)}hex(e,t=!1,s=!1){if(e==null)return"";let i="";const r=n=>Array.from(n).map(a=>a.toString(16).padStart(2,"0")).join("");if(typeof e=="number"){let n=Math.abs(Math.trunc(e)).toString(16);n.length%2&&(n="0"+n),i=n}else if(e instanceof Uint8Array)i=r(e);else if(e instanceof ArrayBuffer)i=r(new Uint8Array(e));else if(Array.isArray(e)&&e.every(n=>typeof n=="number"))i=r(Uint8Array.from(e.map(n=>n&255)));else{const a=new TextEncoder().encode(String(e));i=r(a)}return t&&(i=i.toUpperCase()),(s?"0x":"")+i}unhex(e){if(e==null)return"";let t=String(e).trim();if((t.startsWith("0x")||t.startsWith("0X"))&&(t=t.slice(2)),t=t.replace(/\s+/g,""),t.length===0)return"";t.length%2!==0&&(t="0"+t);const s=new Uint8Array(t.length/2);for(let i=0;i<t.length;i+=2){const r=parseInt(t.slice(i,i+2),16);if(Number.isNaN(r))return String(e);s[i/2]=r}try{return new TextDecoder().decode(s)}catch{let r="";for(const n of s)r+=String.fromCharCode(n);return r}}json(e,t=2){try{return JSON.stringify(e,null,t)}catch{return String(e)}}has(e){return this.formatters.has(e.toLowerCase())}unregister(e){return this.formatters.delete(e.toLowerCase())}listFormatters(){return Array.from(this.formatters.keys()).sort()}iter(e){return e==null?[]:Array.isArray(e)?e:typeof e=="object"?Object.entries(e).map(([t,s])=>({key:t,value:s})):[{key:"0",value:e}]}}const P=new It;window.dataFormatter=P;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)return;if(!t.includes(".")){if(t in e){const r=e[t];return typeof r=="function"?r.call(e):r}return}const s=t.split(".");let i=e;for(let r=0;r<s.length;r++){const n=s[r];if(i==null)return;if(r===0)if(i.hasOwnProperty(n)){const a=i[n];typeof a=="function"?i=a.call(e):i=a}else return;else{if(i&&typeof i.getContextValue=="function"){const a=s.slice(r).join(".");return i.getContextValue(a)}if(Array.isArray(i)&&!isNaN(n))i=i[parseInt(n)];else if(i.hasOwnProperty(n))i=i[n];else if(typeof i[n]=="function")i=i[n].call(i);else return}}return i}static isNullOrUndefined(e){return e==null}static deepClone(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(e instanceof Array)return e.map(t=>this.deepClone(t));if(e instanceof Object){const t={};for(const s in e)e.hasOwnProperty(s)&&(t[s]=this.deepClone(e[s]));return t}}static deepMerge(e,...t){if(!t.length)return e;const s=t.shift();if(this.isObject(e)&&this.isObject(s))for(const i in s)this.isObject(s[i])?(e[i]||Object.assign(e,{[i]:{}}),this.deepMerge(e[i],s[i])):Object.assign(e,{[i]:s[i]});return this.deepMerge(e,...t)}static isObject(e){return e&&typeof e=="object"&&!Array.isArray(e)}static debounce(e,t){let s;return function(...r){const n=()=>{clearTimeout(s),e(...r)};clearTimeout(s),s=setTimeout(n,t)}}static throttle(e,t){let s;return function(...i){s||(e.apply(this,i),s=!0,setTimeout(()=>s=!1,t))}}static generateId(e=""){const t=Date.now().toString(36),s=Math.random().toString(36).substr(2,9);return e?`${e}_${t}_${s}`:`${t}_${s}`}static escapeHtml(e){const t={"&":"&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 Ae(i,t):i):new Ae(e,t)}}class Ae{constructor(e,t=null){if(Object.defineProperty(this,"_data",{value:e,writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(this,"_rootContext",{value:t,writable:!1,enumerable:!1,configurable:!1}),e&&typeof e=="object"){for(const s in e)if(e.hasOwnProperty(s)){const i=e[s];this[s]=$.wrapData(i,t)}}}getContextValue(e){let t=e,s="",i=0,r=-1;for(let a=0;a<e.length;a++){const o=e[a];if(o==="(")i++;else if(o===")")i--;else if(o==="|"&&i===0){r=a;break}}r>-1&&(t=e.substring(0,r).trim(),s=e.substring(r+1).trim());let n;return t in this&&t!=="_data"&&t!=="_rootContext"?n=this[t]:n=$.getNestedValue(this._data,t),s&&n!==void 0?P.pipe(n,s,this._rootContext||this._data):n}has(e){return this._data&&this._data.hasOwnProperty(e)}toJSON(){return this._data}}$.DataWrapper=Ae,typeof window<"u"&&(window.utils=$);const Mt=Object.prototype.toString,ne=Array.isArray||function(c){return Mt.call(c)==="[object Array]"},de=function(c){return typeof c=="function"},Xe=function(c){return c!==null&&typeof c=="object"};function kt(){return typeof window>"u"?null:window.MOJO?.dataFormatter?window.MOJO.dataFormatter:window.dataFormatter?window.dataFormatter:null}const et=function(c){const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(c).replace(/[&<>"'`=\/]/g,function(t){return e[t]})};class tt{constructor(e){this.string=e,this.tail=e,this.pos=0}eos(){return this.tail===""}scan(e){const t=this.tail.match(e);if(!t||t.index!==0)return"";const s=t[0];return this.tail=this.tail.substring(s.length),this.pos+=s.length,s}scanUntil(e){const t=this.tail.search(e);let s;switch(t){case-1:s=this.tail,this.tail="";break;case 0:s="";break;default:s=this.tail.substring(0,t),this.tail=this.tail.substring(t)}return this.pos+=s.length,s}}class be{constructor(e,t){this.view=e,this.cache={".":this.view},this.parent=t,this.view?._cacheId||this.view&&typeof this.view=="object"&&(this.view._cacheId=Math.random().toString(36).substring(2))}push(e){return new be(e,this)}lookup(e){if(this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;if(this.renderCache.has(i))return this.renderCache.get(i)}if(e===".")return this.view;if(e&&e.startsWith(".")){let i=e.substring(1),r=!1,n=null;const a=i.indexOf("|");if(a!==-1&&(n=i.substring(a+1).trim(),i=i.substring(0,a).trim()),i.endsWith("|iter")&&(i=i.substring(0,i.length-5),r=!0),this.view&&typeof this.view=="object"){let o;if(typeof this.view.getContextValue=="function")try{o=this.view.getContextValue(i),o!==void 0&&de(o)&&(o=o.call(this.view))}catch{o=void 0}if(o===void 0&&i in this.view&&(o=this.view[i],de(o)&&(o=o.call(this.view))),n&&o!==void 0)try{const l=kt();l&&typeof l.pipe=="function"&&(o=l.pipe(o,n,this))}catch{}return ne(o)?r?o:o.length>0:Xe(o)?r?Object.entries(o).map(([l,d])=>({key:l,value:d})):Object.keys(o).length>0:o}return}const t=this.cache;let s;if(t.hasOwnProperty(e))s=t[e];else{let i=this,r,n,a,o=!1;for(;i;){if(i.view&&typeof i.view.getContextValue=="function")try{r=i.view.getContextValue(e),r!==void 0&&(o=!0)}catch{o=!1}if(!o)if(e.indexOf(".")>0)for(r=i.view,n=e.split("."),a=0;r!=null&&a<n.length;)if(r&&typeof r.getContextValue=="function"&&a<n.length)try{const l=n.slice(a).join(".");r=r.getContextValue(l),a=n.length,r!==void 0&&(o=!0)}catch{a===n.length-1&&(o=Fe(r,n[a])||st(r,n[a])),r=r[n[a++]]}else a===n.length-1&&(o=Fe(r,n[a])||st(r,n[a])),r=r[n[a++]];else r=i.view[e],o=Fe(i.view,e);if(o){s=r;break}i=i.parent}t[e]=s}if(de(s)&&(s=s.call(this.view)),this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;this.renderCache.set(i,s)}return s}}function Fe(c,e){return c!=null&&typeof c=="object"&&e in c}function st(c,e){return c!=null&&typeof c!="object"&&c.hasOwnProperty&&c.hasOwnProperty(e)}class it{constructor(){this.templateCache=new Map}clearCache(){this.templateCache.clear()}parse(e,t){t=t||["{{","}}"];const s=e+":"+t.join(":");let i=this.templateCache.get(s);return i==null&&(i=this.parseTemplate(e,t),this.templateCache.set(s,i)),i}parseTemplate(e,t){if(!e)return[];const s=t[0],i=t[1],r=new tt(e),n=[];let a,o,l,d,h;const u=new RegExp(Te(s)+"\\s*"),m=new RegExp("\\s*"+Te(i)),p=new RegExp("\\s*"+Te("}"+i));for(;!r.eos();){if(a=r.pos,l=r.scanUntil(u),l)for(let f=0;f<l.length;++f)d=l.charAt(f),d===`
15
15
  `?n.push(["text",d]):n.push(["text",d]);if(!r.scan(u))break;if(o=r.scan(/[#^\/>{&=!]/),o||(o="name"),r.scan(/\s*/),o==="="?(l=r.scanUntil(/\s*=/),r.scan(/\s*=/),r.scanUntil(m)):o==="{"?(l=r.scanUntil(p),r.scan(p),o="&"):l=r.scanUntil(m),r.scan(m),o==="#"||o==="^")h=[o,l,a,r.pos],n.push(h);else if(o==="/"){let f;for(let g=n.length-1;g>=0;--g)if((n[g][0]==="#"||n[g][0]==="^")&&n[g][1]===l){f=n[g];break}f&&f.length===4&&f.push(r.pos),n.push([o,l,a,r.pos])}else n.push([o,l,a,r.pos])}return this.nestSections(this.squashTokens(n))}squashTokens(e){const t=[];let s,i;for(let r=0;r<e.length;++r)s=e[r],s&&(s[0]==="text"&&i&&i[0]==="text"?(i[1]+=s[1],i[3]=s[3]):(t.push(s),i=s));return t}nestSections(e){const t=[];let s=t;const i=[];for(let r=0;r<e.length;++r){const n=e[r];switch(n[0]){case"#":case"^":const a=[n[0],n[1],n[2],n[3],[],n[4]||null];s.push(a),i.push(a),s=a[4];break;case"/":const o=i.pop();o&&(o[5]=n[2],s=i.length>0?i[i.length-1][4]:t);break;default:s.push(n)}}return t}render(e,t,s,i){const r=this.getConfigTags(i)||["{{","}}"],n=this.parse(e,r),a=new Map;return this.renderTokens(n,new be(t),s,e,i,a)}renderTokens(e,t,s,i,r,n){n&&!t.renderCache&&(t.renderCache=n);let a="";for(let o=0;o<e.length;++o){const l=e[o];let d;switch(l[0]){case"#":if(d=t.lookup(l[1]),!d)continue;const h=l[4];if(!h||!ne(h)){console.warn(`MUSTACHE WARNING - Section ${l[1]} has no child tokens:`,l);continue}if(ne(d))for(let u=0;u<d.length;++u){const m=t.push(d[u]);t.renderCache&&(m.renderCache=t.renderCache);const p=this.renderTokens(h,m,s,i,r,n);a+=p}else if(typeof d=="object"||typeof d=="string"||typeof d=="number"){const u=t.push(d);t.renderCache&&(u.renderCache=t.renderCache),a+=this.renderTokens(h,u,s,i,r,n)}else if(de(d)){const u=i==null?null:i.slice(l[3],l[5]);d=d.call(t.view,u,m=>this.render(m,t.view,s,r)),d!=null&&(a+=d)}else d&&(a+=this.renderTokens(h,t,s,i,r,n));break;case"^":if(d=t.lookup(l[1]),!d||ne(d)&&d.length===0){const u=l[4];u&&ne(u)&&(a+=this.renderTokens(u,t,s,i,r,n))}break;case">":if(!s)continue;d=de(s)?s(l[1]):s[l[1]],d!=null&&(a+=this.render(d,t.view,s,r));break;case"&":d=t.lookup(l[1]),d!=null&&(a+=d);break;case"name":d=t.lookup(l[1]),d!=null&&(a+=et(d));break;case"text":a+=l[1];break}}return a}getConfigTags(e){return Xe(e)&&ne(e.tags)?e.tags:null}}function Te(c){return c.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}const Ee=new it,D={name:"MOJO Mustache",version:"1.0.0",tags:["{{","}}"],Scanner:tt,Context:be,Writer:it,escape:et,clearCache(){return Ee.clearCache()},parse(c,e){return Ee.parse(c,e)},render(c,e,t,s){if(typeof c!="string")throw new TypeError('Invalid template! Template should be a "string"');return e&&typeof e=="object"&&!e.getContextValue&&typeof e.toJSON!="function"&&(e=$.wrapData(e)),Ee.render(c,e,t,s)}};class Lt{constructor(e){this.view=e,this.domListeners=[],this.debounceTimers=new Map}bind(e){if(this.unbind(),!e)return;const t=async a=>{const o=a.target.closest("[data-action]");if(o&&this.shouldHandle(o,a)){const d=o.getAttribute("data-action");if(o.tagName==="A"&&a.preventDefault(),this.hideTooltip(o),await this.dispatch(d,a,o)){a.preventDefault(),a.stopPropagation(),a.handledByChild=!0;return}}const l=a.target.closest("a[href], [data-page]");if(l&&!l.hasAttribute("data-action")&&this.shouldHandle(l,a)){if(a.ctrlKey||a.metaKey||a.shiftKey||a.button===1)return;if(l.tagName==="A"){const d=l.getAttribute("href");if(d&&d!=="#"&&!d.startsWith("#")&&(this.view.isExternalLink(d)||l.hasAttribute("data-external")))return}this.hideTooltip(l),a.preventDefault(),a.stopPropagation(),a.handledByChild=!0,l.hasAttribute("data-page")?await this.view.handlePageNavigation(l):await this.view.handleHrefNavigation(l)}},s=a=>{const o=a.target.closest("[data-change-action]");if(o&&this.shouldHandle(o,a)){const d=o.getAttribute("data-change-action");this.dispatchChange(d,a,o).then(h=>{h&&(a.stopPropagation(),a.handledByChild=!0)});return}const l=a.target.closest("[data-action]");if(l&&this.isFormControl(l)&&this.shouldHandle(l,a)){const d=l.getAttribute("data-action");this.dispatch(d,a,l).then(h=>{h&&(a.stopPropagation(),a.handledByChild=!0)})}},i=a=>{const o=a.target.closest("[data-change-action]");if(o&&this.shouldHandle(o,a)&&a.target.matches('[data-filter="live-search"]')){const m=o.getAttribute("data-change-action"),p=parseInt(o.getAttribute("data-filter-debounce"))||300,f=`change-${m}-${o.getAttribute("data-container")||"default"}`;this.debounceTimers.has(f)&&clearTimeout(this.debounceTimers.get(f));const g=setTimeout(()=>{this.debounceTimers.delete(f),this.dispatchChange(m,a,o).then(b=>{b&&(a.stopPropagation(),a.handledByChild=!0)})},p);this.debounceTimers.set(f,g);return}const l=a.target.closest("[data-action]");if(!l||!this.isFormControl(l)||l.hasAttribute("data-change-action")||!this.shouldHandle(l,a))return;const d=l.getAttribute("data-action"),h=l.getAttribute("data-action-debounce"),u=h!=null&&parseInt(h)||0;if(u>0){const m=`action-${d}-${l.getAttribute("data-container")||"default"}`;this.debounceTimers.has(m)&&clearTimeout(this.debounceTimers.get(m));const p=setTimeout(()=>{this.debounceTimers.delete(m),this.dispatch(d,a,l).then(f=>{f&&(a.stopPropagation(),a.handledByChild=!0)})},u);this.debounceTimers.set(m,p);return}this.dispatch(d,a,l).then(m=>{m&&(a.stopPropagation(),a.handledByChild=!0)})},r=a=>{if(a.target.matches('[data-filter="search"]'))return;const o=a.target.closest("[data-keydown-action]")||a.target.closest("[data-change-action]");if(!o||!this.shouldHandle(o,a))return;let l=["Enter"];if(o.getAttribute("data-change-keys")&&(l=o.getAttribute("data-change-keys").split(",").map(d=>d.trim())),l.includes("*")||l.includes(a.key)){const d=o.getAttribute("data-keydown-action")||o.getAttribute("data-change-action");this.dispatch(d,a,o).then(h=>{h&&(a.preventDefault(),a.stopPropagation(),a.handledByChild=!0)})}},n=a=>{const o=a.target.closest("form[data-action]");if(!o||!this.shouldHandle(o,a))return;a.preventDefault();const l=o.getAttribute("data-action");this.dispatch(l,a,o)};e.addEventListener("click",t),e.addEventListener("change",s),e.addEventListener("input",i),e.addEventListener("keydown",r),e.addEventListener("submit",n),this.domListeners.push({el:e,type:"click",fn:t},{el:e,type:"change",fn:s},{el:e,type:"input",fn:i},{el:e,type:"keydown",fn:r},{el:e,type:"submit",fn:n})}unbind(){for(const{el:e,type:t,fn:s}of this.domListeners)e.removeEventListener(t,s);this.domListeners=[];for(const e of this.debounceTimers.values())clearTimeout(e);this.debounceTimers.clear()}hideDropdown(e){const s=e.closest(".dropdown-menu").closest(".dropdown");if(!s)return;const i=s.querySelector('[data-bs-toggle="dropdown"]');i&&window.bootstrap?.Dropdown&&window.bootstrap.Dropdown.getInstance(i)?.hide()}hideTooltip(e){if(e&&window.bootstrap?.Tooltip){const t=window.bootstrap.Tooltip.getInstance(e);t&&t.dispose()}}hideAllTooltips(){window.bootstrap?.Tooltip&&document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.hide()})}async dispatch(e,t,s){const i=this.view,r=l=>l.includes("-")?l.split("-").map(d=>d[0].toUpperCase()+d.slice(1)).join(""):l[0].toUpperCase()+l.slice(1),n=`handleAction${r(e)}`;if(typeof i[n]=="function")try{return t.preventDefault(),await i[n](t,s),!0}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const a=`onAction${r(e)}`;if(typeof i[a]=="function")try{return await i[a](t,s)?(s.closest(".dropdown-menu")&&this.hideDropdown(s),t.preventDefault(),t.stopPropagation(),!0):!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const o=`onPassThruAction${r(e)}`;if(typeof i[o]=="function")try{return await i[o](t,s),!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}if(typeof i.onActionDefault=="function")try{return await i.onActionDefault(e,t,s)}catch(l){return console.error(`Error in default action handler for ${e}:`,l),i.handleActionError(e,l,t,s),!0}return i.emit?.(`action:${e}`,{action:e,event:t,element:s}),!1}async dispatchChange(e,t,s){const i=this.view,n=`onChange${(a=>a.includes("-")?a.split("-").map(o=>o[0].toUpperCase()+o.slice(1)).join(""):a[0].toUpperCase()+a.slice(1))(e)}`;if(typeof i[n]=="function")try{return await i[n](t,s),!0}catch(a){return console.error(`Error in onChange ${e}:`,a),i.handleActionError?.(e,a,t,s),!0}return await this.dispatch(e,t,s)}isFormControl(e){if(!e||!e.tagName)return!1;const t=e.tagName;return t==="INPUT"||t==="TEXTAREA"||t==="SELECT"}shouldHandle(e,t){return!!(this.owns(e)||this.contains(e)&&!t.handledByChild)}owns(e){const t=this.view.element;if(!t||!t.contains(e))return!1;for(const s of Object.values(this.view.children))if(s.element&&s.element.contains(e))return!1;return!0}contains(e){return!!this.view.element&&this.view.element.contains(e)}}const De={on(c,e,t){this._listeners||(this._listeners={}),this._listeners[c]||(this._listeners[c]=[]);const s={callback:e,context:t,fn:t?e.bind(t):e};return this._listeners[c].push(s),this},off(c,e,t){return!this._listeners||!this._listeners[c]?this:(e?(this._listeners[c]=this._listeners[c].filter(s=>s.callback!==e||arguments.length===3&&s.context!==t),this._listeners[c].length===0&&delete this._listeners[c]):delete this._listeners[c],this)},once(c,e,t){const s=(...i)=>{this.off(c,s),(t?e.bind(t):e).apply(t||this,i)};return this.on(c,s),this},emit(c,...e){if(!this._listeners||!this._listeners[c])return this;const t=this._listeners[c].slice();for(const s of t)try{s.fn.apply(s.context||this,e)}catch(i){console&&console.error&&console.error(`Error in ${c} event handler:`,i)}return this}};typeof window<"u"&&(window.Mustache=D);class C{constructor(e={}){this.tagName=e.tagName??"div",this.className=e.className??"mojo-view",this.style=e.style??null,this.id=e.id??C._genId(),this.containerId=e.containerId??null,this.container=e.container??null,typeof this.container=="string"&&(this.containerId=this.container,this.container=null),this.parent=e.parent??null,this.children=e.children??{},this.template=e.template||e.templateUrl||"",this.data=e.data??{},this.isRendering=!1,this.lastRenderTime=0,this.mounted=!1,this.debug=e.debug??!1,this.app=e.app??null,this.cacheTemplate=e.cacheTemplate??!0,this.enableTooltips=e.enableTooltips??!1,this.options={...e},this.element=this._ensureElement(),this.events=new Lt(this),e.model&&this.setModel(e.model)}async onInit(){}async onInitView(){this.initialized||(this.initialized=!0,await this.onInit())}async onBeforeRender(){}async onAfterRender(){}async onBeforeMount(){}async onAfterMount(){}async onBeforeUnmount(){}async onAfterUnmount(){}async onBeforeDestroy(){}async onAfterDestroy(){}setModel(e={}){let t=e!==this.model;if(!t)return this;this.model&&this.model.off&&this.model.off("change",this._onModelChange,this),this.model=e,this.model&&this.model.on&&this.model.on("change",this._onModelChange,this);for(const s in this.children){const i=this.children[s];i&&typeof i.setModel=="function"&&i.setModel(e)}return t&&this._onModelChange(),this}_onModelChange(){this.isMounted()&&this.render()}setTemplate(e){return this.template=e??"",this}addChild(e,t){try{if(!e||typeof e!="object")return this;t&&((t.containerId||t.container)&&(e.containerId=t.containerId||t.container),t.id&&(e.id=t.id),t.lazyMount===!0&&(e._lazyMount=!0)),e.parent=this,this.getApp()&&(e.app=this.app),this.children[e.id]=e}catch(s){C._warn("addChild error",s)}return e}removeChild(e){try{const t=typeof e=="string"?e:e&&e.id;if(!t)return this;const s=this.children[t];s&&(Promise.resolve(s.destroy()).catch(i=>C._warn("removeChild destroy error",i)),delete this.children[t])}catch(t){C._warn("removeChild error",t)}return this}getChild(e){return this.children[e]}async updateData(e,t=!1){return Object.assign(this.data,e),t&&this.isMounted()&&await this.render(),this}toggleClass(e,t){return t===void 0&&(t=!this.element.classList.contains(e)),this.element.classList.toggle(e,t),this}addClass(e){return this.element.classList.add(e),this}setClass(e){return this.element.className=e,this}removeClass(e){return this.element.classList.remove(e),this}canRender(){if(this.isRendering)return!1;const e=Date.now();if(this.options.renderCooldown>0&&e-this.lastRenderTime<this.options.renderCooldown)return C._warn(`View ${this.id}: Render called too quickly, cooldown active`),!1;if(this.options.noAppend&&this.parent)if(this.parent.contains(this.containerId||this.container)){if(this.containerId&&!document.getElementById(this.containerId))return!1;if(this.container&&!document.contains(this.container))return!1}else return!1;return!0}async render(e=!0,t=null){const s=Date.now();if(!this.canRender())return this;this.isRendering=!0,this.lastRenderTime=s;try{this.initialized||await this.onInitView(),this.unbindEvents(),await this.onBeforeRender(),this.getViewData&&(this.data=await this.getViewData());const i=await this.renderTemplate();this.element.innerHTML=i,e&&!this.isMounted()&&await this.mount(t),await this._renderChildren(),await this.onAfterRender(),this.bindEvents()}catch(i){C._warn(`Render error in ${this.id}`,i)}finally{this.isRendering=!1}return this}async _renderChildren(){const e=[];for(const t in this.children){const s=this.children[t];if(s){if(s.parent=this,s._lazyMount&&!s._lazyTriggered){e.push(s);continue}await Promise.resolve(s.render()).catch(i=>C._warn(`Child render error (${t})`,i))}}e.length&&this._setupLazyMountObserver(e)}_setupLazyMountObserver(e){if(typeof IntersectionObserver>"u"){e.forEach(t=>{t._lazyTriggered=!0,Promise.resolve(t.render()).catch(s=>C._warn(`Lazy child render error (${t.id})`,s))});return}this._lazyObserver||(this._lazyObserver=new IntersectionObserver((t,s)=>{for(const i of t){if(!i.isIntersecting)continue;const r=i.target.__mojoLazyChild;s.unobserve(i.target),!(!r||r._lazyTriggered)&&(r._lazyTriggered=!0,Promise.resolve(r.render()).catch(n=>C._warn(`Lazy child render error (${r.id})`,n)))}},{rootMargin:"120px 0px",threshold:.01}));for(const t of e){const s=this.getChildElement(t.containerId);s&&(s.__mojoLazyChild=t,s.style.minHeight||(s.classList.add("mojo-lazy-placeholder"),s.style.minHeight="1px"),this._lazyObserver.observe(s),requestAnimationFrame(()=>{if(t._lazyTriggered)return;const i=s.getBoundingClientRect(),r=typeof window<"u"?window.innerHeight:0,n=typeof window<"u"?window.innerWidth:0;i.top<r+120&&i.bottom>-120&&i.left<n&&i.right>0&&(t._lazyTriggered=!0,this._lazyObserver?.unobserve(s),Promise.resolve(t.render()).catch(o=>C._warn(`Lazy child render error (${t.id})`,o)))}))}}async _unmountChildren(){for(const e in this.children){const t=this.children[e];t&&t.unbindEvents()}}isMounted(){return this.element?.isConnected}getChildElementById(e,t=null){const s=e.startsWith("#")?e.substring(1):e;return t?t.querySelector(`#${s}`):this.element.querySelector(`#${s}`)}getChildElement(e){if(e.startsWith("#"))return this.getChildElementById(e);let t=this.element?.querySelector(`[data-container="${e}"]`);return t||this.getChildElementById(e)}getContainer(){return this.replaceById?this.parent?this.parent.getChildElementById(this.id):null:this.containerId?this.parent?this.parent.getChildElement(this.containerId):this.getChildElementById(this.containerId,document.body):null}async mount(e=null){if(await this.onBeforeMount(),e||(e=this.getContainer()),this.containerId&&!e){console.error(`Container not found for ${this.containerId}`);return}e&&this.replaceById?e.replaceWith(this.element):e?e.replaceChildren(this.element):!this.containerId&&this.parent?this.parent.element.appendChild(this.element):!this.containerId&&!this.parent&&this.options.allowAppendToBody?(console.log("APPENDING TO BODY!!!!"),document.body.appendChild(this.element)):console.error(`Container not found for ${this.containerId}`),await this.onAfterMount(),this.mounted=!0}async unmount(){!this.element||!this.element.parentNode||(await this.onBeforeUnmount(),await this._unmountChildren(),this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.events.unbind(),await this.onAfterUnmount(),this.mounted=!1)}async destroy(){try{this.events.unbind(),this._lazyObserver&&(this._lazyObserver.disconnect(),this._lazyObserver=null);for(const e in this.children){const t=this.children[e];t&&await Promise.resolve(t.destroy()).catch(s=>C._warn(`Child destroy error (${e})`,s))}this.mounted=!1,this.element&&this.element.parentNode&&(await this.onBeforeDestroy(),this.element.parentNode&&this.element.parentNode.removeChild(this.element),await this.onAfterDestroy())}catch(e){C._warn(`Destroy error in ${this.id}`,e)}}_ensureElement(){try{if(this.element&&this.element.tagName?.toLowerCase()===this.tagName)return this._syncAttrs(),this.element;const e=document.createElement(this.tagName);return this.element=e,this.el=e,this._syncAttrs(),e}catch(e){C._warn("ensureElement error",e);const t=document.createElement("div");return t.id=this.id||C._genId(),t}}_syncAttrs(){try{if(!this.element)return;this.id&&(this.element.id=this.id),this.element.className=this.className||"",this.style==null?this.element.removeAttribute("style"):this.element.style.cssText=String(this.style)}catch(e){C._warn("_syncAttrs error",e)}}bindEvents(){this.events.bind(this.element),this.enableTooltips&&this.initializeTooltips()}unbindEvents(){this.events.unbind(),this.enableTooltips&&this.disposeTooltips()}async renderTemplate(){const e=await this.getTemplate();if(!e)return"";const t=this.getPartials();return D.render(e,this,t)}renderTemplateString(e,t,s){return D.render(e,t,s)}getPartials(){return{}}async getTemplate(){if(this._templateCache&&this.cacheTemplate)return this._templateCache;const e=this.template||this.templateUrl;if(!e)throw new Error("Template not found");let t="";if(typeof e=="string")if(e.includes("<")||e.includes("{"))t=e;else try{let s=e;this.app||(this.app=this.getApp()),this.app&&this.app.basePath&&!s.startsWith("/")&&!s.startsWith("http://")&&!s.startsWith("https://")&&(s=`${this.app.basePath.endsWith("/")?this.app.basePath.slice(0,-1):this.app.basePath}/${s}`);const i=await fetch(s);if(!i.ok)throw new Error(`HTTP ${i.status}: ${i.statusText}`);t=await i.text()}catch(s){C._warn(`Failed to load template from ${e}: ${s}`),this.showError?.(`Failed to load template from ${e}: ${s.message}`)}else typeof e=="function"&&(t=await this.template(this.data,this.state));return this.cacheTemplate&&t&&(this._templateCache=t),t}getContextValue(e){const t=$.getContextData(this,e);return e&&e.startsWith("data.")&&t&&typeof t=="object"?$.wrapData(t,this):e&&e.startsWith("model.")&&e!=="model"&&t&&typeof t=="object"&&typeof t.getContextValue!="function"?$.wrapData(t,null):t}async handlePageNavigation(e){const t=e.getAttribute("data-page"),s=e.getAttribute("data-params");let i={};if(s)try{i=JSON.parse(s)}catch{console.warn("Invalid JSON in data-params:",s)}const r=this.getApp();if(r){r.showPage(t,i);return}const n=this.findRouter();n&&typeof n.navigateToPage=="function"?await n.navigateToPage(t,i):console.error(`No router found for page navigation to '${t}'`)}async handleHrefNavigation(e){const t=e.getAttribute("href");if(this.isExternalLink(t)||e.hasAttribute("data-external"))return;const s=this.findRouter();if(s){if(s.options&&s.options.mode==="param"&&t.startsWith("?")){const r="/"+t;await s.navigate(r);return}if(s.options&&s.options.mode==="hash"&&t.startsWith("#")){await s.navigate(t);return}const i=this.hrefToRoutePath(t);await s.navigate(i)}else console.warn("No router found for navigation, using default behavior"),window.location.href=t}isExternalLink(e){return e?e.startsWith("/")&&this.getApp()?!e.startsWith(this.findRouter().basePath):e.startsWith("#")||e.startsWith("mailto:")||e.startsWith("tel:")||e.startsWith("http://")||e.startsWith("https://")||e.startsWith("//"):!0}hrefToRoutePath(e){if(e.startsWith("/")){const t=this.findRouter();if(t&&t.options&&t.options.base){const s=t.options.base;if(e.startsWith(s))return e.substring(s.length)||"/"}return e}return e.startsWith("./")?e.substring(2):e}findRouter(){return this.getApp(),this.app?.router||null}getApp(){if(this.app)return this.app;const e=[window.__app__,window.MOJO?.app,window.APP,window.app,window.WebApp,window.matchUUID?window[window.matchUUID]():window[window.matchUUID]];return this.app=e.find(t=>t&&typeof t.showPage=="function")||null,this.app}handleActionError(e,t,s,i){this.showError(`Action '${e}' failed: ${t}`,s,i)}escapeHtml(e){if(typeof e!="string")return e;const t=document.createElement("div");return t.textContent=e,t.innerHTML}contains(e){if(typeof e=="string"){if(!this.element)return!1;e=document.getElementById(e)}return e?this.element.contains(e):!1}initializeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.disposeTooltips(),[...this.element.querySelectorAll('[data-bs-toggle="tooltip"]')].map(t=>{const s=t.getAttribute("data-tooltip-theme"),i=t.getAttribute("data-tooltip-size");let r="";s&&(r+=`tooltip-${s} `),i&&(r+=`tooltip-${i}`);const n={},a=r.trim();return a&&(n.customClass=a),new window.bootstrap.Tooltip(t,n)})}disposeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.element.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.dispose()})}async showError(e){console.error(`View ${this.id} error:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showError=="function"){await t.showError(e);return}alert(`Error: ${e}`)}async showSuccess(e){this.debug&&console.log(`View ${this.id} success:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showSuccess=="function"){await t.showSuccess(e);return}alert(`Success: ${e}`)}async showInfo(e){console.info(`View ${this.id} info:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showInfo=="function"){await t.showInfo(e);return}alert(`Info: ${e}`)}async showWarning(e){console.warn(`View ${this.id} warning:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showWarning=="function"){await t.showWarning(e);return}alert(`Warning: ${e}`)}async onActionCopyToClipboard(e,t){try{const i=(t?.closest("[data-clipboard]")||t)?.getAttribute("data-clipboard")||"";if(!i)return!0;if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(i);else{const a=document.createElement("textarea");a.value=i,document.body.appendChild(a),a.select(),document.execCommand("copy"),document.body.removeChild(a)}const r=t.querySelector("i"),n=r&&r.className;return r&&(r.className="bi bi-check",setTimeout(()=>{r.className=n},1e3)),!0}catch(s){return console.warn("Copy to clipboard failed:",s),!0}}static _genId(){return`view_${Math.random().toString(36).substr(2,9)}`}static _warn(e,t){try{t?console.warn(`[View] ${e}:`,t):console.warn(`[View] ${e}`)}catch{}}}Object.assign(C.prototype,De);class _ extends C{static _openDialogs=[];static _baseZIndex={backdrop:1050,modal:1055};static getFullscreenAwareZIndex(){return document.querySelector(".table-fullscreen")?{backdrop:10040,modal:10050}:_._baseZIndex}static fixAllBackdropStacking(){const e=document.querySelectorAll(".modal-backdrop"),t=_._openDialogs;if(e.length===0||t.length===0)return;const s=[...t].sort((n,a)=>(n._dialogZIndex||0)-(a._dialogZIndex||0)),r=document.querySelector(".table-fullscreen")||document.body;e.forEach((n,a)=>{if(a>=s.length)return;const o=s[a];n.style.zIndex=o._dialogZIndex-5,n.parentNode!==r&&r.appendChild(n)})}static updateAllBackdropStacking(){_.fixAllBackdropStacking()}static getMountTarget(){return document.querySelector(".table-fullscreen")||document.body}constructor(e={}){const t=e.id||`modal-${Date.now()}-${Math.random().toString(36).slice(2,7)}`;super({...e,id:t,tagName:"div",className:`modal ${e.fade!==!1?"fade":""} ${e.className||""}`.trim().replace(/\s+/g," "),attributes:{tabindex:"-1","aria-hidden":"true","aria-labelledby":e.labelledBy||`${t}-label`,"aria-describedby":e.describedBy||null,...e.attributes}}),this.modalId=t,this.title=e.title||"",this.titleId=`${this.modalId}-label`,this.size=e.size||"",this.centered=e.centered!==void 0?e.centered:!1,this.scrollable=e.scrollable!==void 0?e.scrollable:!1,this.autoSize=e.autoSize||e.size==="auto",this.backdrop=e.backdrop!==void 0?e.backdrop:!0,this.keyboard=e.keyboard!==void 0?e.keyboard:!0,this.focus=e.focus!==void 0?e.focus:!0,this.header=e.header!==void 0?e.header:!0,this.headerContent=e.headerContent||null,this.headerView=null,this.closeButton=e.closeButton!==void 0?e.closeButton:!0,this.contextMenu=e.contextMenu||null,this._processHeaderContent(this.headerContent),this.body=e.body??e.view??e.message??e.content??"",this.bodyView=null,this.bodyClass=e.bodyClass||"",this.noBodyPadding=e.noBodyPadding||!1,this.minWidth=e.minWidth||300,this.minHeight=e.minHeight||200,e.maxHeight&&(this.maxHeight=e.maxHeight),this.maxWidthPercent=e.maxWidthPercent||.9,this.maxHeightPercent=e.maxHeightPercent||.8,this._processBodyContent(this.body),this.footer=e.footer||null,this.footerView=null,this.footerClass=e.footerClass||"",this._processFooterContent(this.footer),this.buttons=e.buttons||null,this.onShow=e.onShow||null,this.onShown=e.onShown||null,this.onHide=e.onHide||null,this.onHidden=e.onHidden||null,this.onHidePrevented=e.onHidePrevented||null,this.autoShow=e.autoShow!==void 0?e.autoShow:!1,this.modal=null,this.relatedTarget=e.relatedTarget||null}_processBodyContent(e){if(e instanceof C||e&&typeof e=="object"&&typeof e.render=="function")this.bodyView=e,this.body="",this.addChild(this.bodyView);else if(typeof e=="function")try{const t=e();t instanceof C?(this.bodyView=t,this.body="",this.addChild(this.bodyView)):t instanceof Promise?(this.bodyPromise=t,this.body='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.body=t}catch(t){console.error("ModalView: error processing body function:",t),this.body=e}else this.body=e}_processHeaderContent(e){if(e instanceof C)this.headerView=e,this.headerContent=null,this.addChild(this.headerView);else if(typeof e=="function")try{const t=e();t instanceof C?(this.headerView=t,this.headerContent=null,this.addChild(this.headerView)):t instanceof Promise?(this.headerPromise=t,this.headerContent='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.headerContent=t}catch(t){console.error("ModalView: error processing headerContent function:",t),this.headerContent=e}else this.headerContent=e}_processFooterContent(e){if(e instanceof C)this.footerView=e,this.footer=null,this.addChild(this.footerView);else if(typeof e=="function")try{const t=e();t instanceof C?(this.footerView=t,this.footer=null,this.addChild(this.footerView)):t instanceof Promise?(this.footerPromise=t,this.footer='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.footer=t}catch(t){console.error("ModalView: error processing footer function:",t),this.footer=e}else this.footer=e}async getTemplate(){const e=["modal-dialog"];return this.size&&this.size!=="auto"&&(this.size.startsWith("fullscreen")?e.push(`modal-${this.size}`):["sm","lg","xl","xxl"].includes(this.size)&&(e.push(`modal-${this.size}`),["lg","xl","xxl"].includes(this.size)&&e.push("modal-fullscreen-sm-down"))),this.centered&&e.push("modal-dialog-centered"),this.scrollable&&(this.maxHeight?e.push("overflow-hidden"):e.push("modal-dialog-scrollable")),`
16
16
  <div class="${e.join(" ")}">
17
17
  <div class="modal-content">
@@ -52,7 +52,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
52
52
  </div>
53
53
  <p>${t}</p>
54
54
  </div>
55
- `:this.bodyView&&s.replaceChildren(this.bodyView.element))}async destroy(){if(this.modal){const e=this.element?.querySelector(":focus");e&&e.blur(),this.modal.dispose(),this.modal=null}this.previousFocus&&document.body.contains(this.previousFocus)&&(this.previousFocus.focus(),this.previousFocus=null),this.autoSize&&this.resetAutoSizing(),await super.destroy()}async onBeforeDestroy(){this.headerView&&await this.headerView.destroy(),this.bodyView&&await this.bodyView.destroy(),this.footerView&&await this.footerView.destroy(),await super.onBeforeDestroy(),this.modal&&(this.modal.dispose(),this.modal=null)}}let L=null,J=0,ae=null;const Pt=`
55
+ `:this.bodyView&&s.replaceChildren(this.bodyView.element))}async destroy(){if(this.modal){const e=this.element?.querySelector(":focus");e&&e.blur(),this.modal.dispose(),this.modal=null}this.previousFocus&&document.body.contains(this.previousFocus)&&(this.previousFocus.focus(),this.previousFocus=null),this.autoSize&&this.resetAutoSizing(),await super.destroy()}async onBeforeDestroy(){this.headerView&&await this.headerView.destroy(),this.bodyView&&await this.bodyView.destroy(),this.footerView&&await this.footerView.destroy(),await super.onBeforeDestroy(),this.modal&&(this.modal.dispose(),this.modal=null)}}let L=null,J=0,ae=null;const Vt=`
56
56
  .mojo-loading-overlay {
57
57
  position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;
58
58
  background: rgba(255, 255, 255, 0.4);
@@ -90,8 +90,8 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
90
90
  <div class="mojo-loading-spinner"></div>
91
91
  <div class="mojo-loading-message">${e}</div>
92
92
  </div>
93
- <style>${Pt}</style>
94
- `,document.body.appendChild(L)),L.style.zIndex=String(i);const r=L.querySelector(".mojo-loading-message");r&&(r.textContent=e),requestAnimationFrame(()=>{L&&L.classList.add("show")}),t>0&&(ae=setTimeout(()=>{console.error("BusyIndicator timed out."),Ie.hide(!0)},t))}else if(L){const s=L.querySelector(".mojo-loading-message");s&&(s.textContent=e)}},hide(c=!1){c?J=0:J--,!(J>0)&&(J=0,ae&&(clearTimeout(ae),ae=null),L&&(L.classList.remove("show"),setTimeout(()=>{L&&J===0&&(L.remove(),L=null)},200)))},isShown(){return L!==null&&J>0}},Vt=`
93
+ <style>${Vt}</style>
94
+ `,document.body.appendChild(L)),L.style.zIndex=String(i);const r=L.querySelector(".mojo-loading-message");r&&(r.textContent=e),requestAnimationFrame(()=>{L&&L.classList.add("show")}),t>0&&(ae=setTimeout(()=>{console.error("BusyIndicator timed out."),Ie.hide(!0)},t))}else if(L){const s=L.querySelector(".mojo-loading-message");s&&(s.textContent=e)}},hide(c=!1){c?J=0:J--,!(J>0)&&(J=0,ae&&(clearTimeout(ae),ae=null),L&&(L.classList.remove("show"),setTimeout(()=>{L&&J===0&&(L.remove(),L=null)},200)))},isShown(){return L!==null&&J>0}},Pt=`
95
95
  max-height: 60vh;
96
96
  overflow-y: auto;
97
97
  background: #1e1e1e;
@@ -121,7 +121,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
121
121
  .dialog-code-block ::selection { background: #264f78; }
122
122
  `;class he extends C{constructor(e={}){super({tagName:"div",className:"mojo-code-viewer",...e}),this.code=e.code||"",this.language=e.language||"javascript"}async getTemplate(){return he.formatCode(this.code,this.language)}static formatCode(e,t="javascript"){let s;window.Prism&&window.Prism.languages[t]?s=window.Prism.highlight(e,window.Prism.languages[t],t):s=String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;");const i=window.Prism?`language-${t}`:"";return`
123
123
  <style>${Nt}</style>
124
- <pre class="${i} dialog-code-block" style="${Vt}">
124
+ <pre class="${i} dialog-code-block" style="${Pt}">
125
125
  <code class="${i}" style="color: inherit; background: transparent; text-shadow: none;">${s}</code>
126
126
  </pre>
127
127
  `}static highlightCodeBlocks(e=document){window.Prism&&window.Prism.highlightAllUnder&&window.Prism.highlightAllUnder(e)}}class Ot extends C{constructor(e={}){super({tagName:"div",className:"mojo-html-preview",...e}),this.html=e.html||e.content||"",this.height=e.height||500}async getTemplate(){return`
@@ -160,7 +160,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
160
160
  ${t?`<i class="${this.getDefaultIcon("info")} toast-service-icon me-2"></i>`:""}
161
161
  <span>${this.escapeHtml(e)}</span>
162
162
  </div>
163
- `}getDefaultTitle(e){return{success:"Success",error:"Error",warning:"Warning",info:"Information",plain:""}[e]||"Notification"}getDefaultIcon(e){return{success:"bi-check-circle-fill",error:"bi-exclamation-triangle-fill",warning:"bi-exclamation-triangle-fill",info:"bi-info-circle-fill",plain:""}[e]||"bi-info-circle-fill"}enforceMaxToasts(){if(Array.from(this.toasts.values()).length>=this.options.maxToasts){const t=this.toasts.keys().next().value,s=this.toasts.get(t);s&&s.bootstrap.hide()}}cleanup(e){const t=this.toasts.get(e);if(t){try{t.bootstrap.dispose()}catch(s){console.warn("Error disposing toast:",s)}t.element&&t.element.parentNode&&t.element.parentNode.removeChild(t.element),this.toasts.delete(e)}}cleanupView(e){const t=this.toasts.get(e);if(t){if(t.view&&typeof t.view.dispose=="function")try{t.view.dispose()}catch(s){console.warn("Error disposing view in toast:",s)}try{t.bootstrap.dispose()}catch(s){console.warn("Error disposing toast:",s)}t.element&&t.element.parentNode&&t.element.parentNode.removeChild(t.element),this.toasts.delete(e)}}hideAll(){this.toasts.forEach((e,t)=>{e.bootstrap.hide()})}clearAll(){this.toasts.forEach((e,t)=>{this.cleanup(t)})}getTimeString(){return new Date().toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}escapeHtml(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}dispose(){this.clearAll(),this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container)}getStats(){const e={total:this.toasts.size,byType:{}};return this.toasts.forEach(t=>{e.byType[t.type]=(e.byType[t.type]||0)+1}),e}setOptions(e){this.options={...this.options,...e},e.position&&this.container&&(this.container.className=`toast-container position-fixed ${this.getPositionClasses()}`)}}class Me extends C{constructor(e={}){super({template:"progress-view-template",...e}),this.filename=e.filename||"Unknown file",this.filesize=e.filesize||0,this.filesizeFormatted=V.pipe(this.filesize,"filesize"),this.progress=0,this.percentage=0,this.loaded=0,this.total=this.filesize,this.loadedFormatted="0 B",this.totalFormatted=this.filesizeFormatted,this.status="Starting upload...",this.showCancel=e.showCancel!==!1,this.onCancel=e.onCancel||null,this.cancelled=!1,this.completed=!1}getTemplate(){return`
163
+ `}getDefaultTitle(e){return{success:"Success",error:"Error",warning:"Warning",info:"Information",plain:""}[e]||"Notification"}getDefaultIcon(e){return{success:"bi-check-circle-fill",error:"bi-exclamation-triangle-fill",warning:"bi-exclamation-triangle-fill",info:"bi-info-circle-fill",plain:""}[e]||"bi-info-circle-fill"}enforceMaxToasts(){if(Array.from(this.toasts.values()).length>=this.options.maxToasts){const t=this.toasts.keys().next().value,s=this.toasts.get(t);s&&s.bootstrap.hide()}}cleanup(e){const t=this.toasts.get(e);if(t){try{t.bootstrap.dispose()}catch(s){console.warn("Error disposing toast:",s)}t.element&&t.element.parentNode&&t.element.parentNode.removeChild(t.element),this.toasts.delete(e)}}cleanupView(e){const t=this.toasts.get(e);if(t){if(t.view&&typeof t.view.dispose=="function")try{t.view.dispose()}catch(s){console.warn("Error disposing view in toast:",s)}try{t.bootstrap.dispose()}catch(s){console.warn("Error disposing toast:",s)}t.element&&t.element.parentNode&&t.element.parentNode.removeChild(t.element),this.toasts.delete(e)}}hideAll(){this.toasts.forEach((e,t)=>{e.bootstrap.hide()})}clearAll(){this.toasts.forEach((e,t)=>{this.cleanup(t)})}getTimeString(){return new Date().toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}escapeHtml(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}dispose(){this.clearAll(),this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container)}getStats(){const e={total:this.toasts.size,byType:{}};return this.toasts.forEach(t=>{e.byType[t.type]=(e.byType[t.type]||0)+1}),e}setOptions(e){this.options={...this.options,...e},e.position&&this.container&&(this.container.className=`toast-container position-fixed ${this.getPositionClasses()}`)}}class Me extends C{constructor(e={}){super({template:"progress-view-template",...e}),this.filename=e.filename||"Unknown file",this.filesize=e.filesize||0,this.filesizeFormatted=P.pipe(this.filesize,"filesize"),this.progress=0,this.percentage=0,this.loaded=0,this.total=this.filesize,this.loadedFormatted="0 B",this.totalFormatted=this.filesizeFormatted,this.status="Starting upload...",this.showCancel=e.showCancel!==!1,this.onCancel=e.onCancel||null,this.cancelled=!1,this.completed=!1}getTemplate(){return`
164
164
  <div class="progress-view">
165
165
  <div class="d-flex justify-content-between align-items-start mb-2">
166
166
  <div class="flex-grow-1 min-width-0">
@@ -199,23 +199,23 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
199
199
  </small>
200
200
  </div>
201
201
  </div>
202
- `}updateProgress(e){this.cancelled||this.completed||(this.progress=e.progress,this.percentage=e.percentage,this.loaded=e.loaded,this.total=e.total||this.filesize,this.loadedFormatted=V.pipe(this.loaded,"filesize"),this.totalFormatted=V.pipe(this.total,"filesize"),this.percentage<100?this.status=`Uploading... ${this.percentage}%`:this.status="Finalizing upload...",this.render())}markCompleted(e="Upload completed!"){this.completed=!0,this.progress=1,this.percentage=100,this.status=e,this.render()}markFailed(e="Upload failed"){this.status=e,this.render()}markCancelled(){this.cancelled=!0,this.status="Upload cancelled",this.render()}async onActionCancel(e,t,s){if(!(this.cancelled||this.completed)&&(s.disabled=!0,this.markCancelled(),this.emit("cancel"),typeof this.onCancel=="function"))try{await this.onCancel()}catch(i){console.error("Error in cancel callback:",i)}}setFilename(e){this.filename=e,this.render()}setFilesize(e){this.filesize=e,this.filesizeFormatted=V.pipe(e,"filesize"),this.total=e,this.totalFormatted=this.filesizeFormatted,this.render()}getPercentage(){return this.percentage}isCompleted(){return this.completed}isCancelled(){return this.cancelled}getStats(){return{filename:this.filename,filesize:this.filesize,progress:this.progress,percentage:this.percentage,loaded:this.loaded,total:this.total,cancelled:this.cancelled,completed:this.completed,status:this.status}}}class Rt{constructor(e,t={}){if(this.fileModel=e,this.options={file:null,name:null,group:null,description:null,onProgress:null,onComplete:null,onError:null,showToast:!0,...t},!this.options.file||!(this.options.file instanceof File))throw new Error("FileUpload requires a valid File object");this.cancelled=!1,this.uploadRequest=null,this.progressToast=null,this.progressView=null,this.toastService=null,this.options.showToast&&(this.toastService=new jt),this.promise=this._startUpload()}async _startUpload(){try{this.options.showToast&&this._showProgressToast();let e;try{e=await this._initiateUpload()}catch(i){throw new Error(`Failed to initiate upload: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");if(!e||!e.upload_url)throw new Error("Invalid upload response: missing upload URL");let t;if(typeof e.upload_url=="string")t={url:e.upload_url,method:"PUT",fields:null,headers:{}};else if(e.upload_url&&typeof e.upload_url=="object"&&e.upload_url.upload_url)t={url:e.upload_url.upload_url,method:e.upload_url.method||"POST",fields:e.upload_url.fields||null,headers:e.upload_url.headers||{}};else throw new Error(`Invalid upload response: unrecognised upload_url format. Server returned: ${JSON.stringify(e.upload_url)}`);let s;try{s=await this._performUpload(t)}catch(i){throw new Error(`File upload failed: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");try{await this._completeUpload()}catch(i){console.warn("Failed to mark upload as completed:",i)}return this._onComplete(this.fileModel),this.fileModel}catch(e){throw e.message!=="Upload cancelled"&&this._onError(e),e}}async _initiateUpload(){try{const e={filename:this.options.name||this.options.file.name,file_size:this.options.file.size,content_type:this.options.file.type};this.options.group&&(e.group=this.options.group),this.options.description&&(e.description=this.options.description);const t=await this.fileModel.rest.POST("/api/fileman/upload/initiate",e);if(!t)throw new Error("No response from upload initiation API");if(!t.data)throw new Error("Upload initiation response missing data");if(!t.data.status){const s=t.data.error||"Upload initiation failed";throw new Error(s)}if(!t.data.data)throw new Error("Upload initiation response missing data payload");return t.data.data.id&&this.fileModel.set("id",t.data.data.id),t.data.data}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload initiation. Please check your connection."):e}}async _performUpload(e){return new Promise((t,s)=>{if(!(this.options.file instanceof File)){s(new Error("Only single File objects are supported"));return}const{url:i,method:r,fields:n,headers:a}=e,o=r==="POST"&&n!==null,l=new XMLHttpRequest;this.uploadRequest=l,l.upload.onprogress=u=>{this.cancelled||this._onProgress({progress:u.loaded/u.total,loaded:u.loaded,total:u.total,percentage:Math.round(u.loaded/u.total*100)})},l.onload=()=>{l.status>=200&&l.status<300?t({data:l.response,status:l.status,statusText:l.statusText,xhr:l}):s(new Error(`Upload failed: ${l.status} ${l.statusText}`))},l.onerror=()=>s(new Error("Upload failed: Network error")),l.ontimeout=()=>s(new Error("Upload timed out — file may be too large or connection too slow")),l.onabort=()=>s(new Error("Upload cancelled"));let d=i;i.startsWith("/")&&!i.startsWith("/api/")&&(d="/api"+i);const h=this.fileModel.rest.buildUrl(d);if(l.open(r,h),l.timeout=3e4,o){for(const[m,p]of Object.entries(a||{}))m.toLowerCase()!=="content-type"&&l.setRequestHeader(m,p);const u=new FormData;for(const[m,p]of Object.entries(n))u.append(m,p);u.append("file",this.options.file),l.send(u)}else{l.setRequestHeader("Content-Type",this.options.file.type);for(const[u,m]of Object.entries(a||{}))u.toLowerCase()!=="content-type"&&l.setRequestHeader(u,m);l.send(this.options.file)}})}async _completeUpload(){try{const e=await this.fileModel.save({action:"mark_as_completed"});if(!e)throw new Error("No response from upload completion API");if(e.data&&!e.data.status){const t=e.data.error||"Failed to mark upload as completed";throw new Error(t)}return e}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload completion. The file may have uploaded successfully."):e}}_onProgress(e){this.progressToast&&this.progressToast.updateProgress&&this.progressToast.updateProgress(e),typeof this.options.onProgress=="function"&&this.options.onProgress(e)}_onComplete(e){this.progressView&&this.progressView.markCompleted("Upload completed successfully!"),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast:",t)}},2e3),typeof this.options.onComplete=="function"&&this.options.onComplete(e)}_onError(e){if(this.progressToast)try{this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast on error:",t)}this.toastService&&this.toastService.error(`Upload failed: ${e.message}`),typeof this.options.onError=="function"&&this.options.onError(e)}_showProgressToast(){this.progressView=new Me({filename:this.options.name||this.options.file.name,filesize:this.options.file.size,showCancel:!0,onCancel:()=>this.cancel()}),this.progressToast=this.toastService.showView(this.progressView,"info",{title:"File Upload",autohide:!1,dismissible:!1})}cancel(){return this.cancelled?!1:(this.cancelled=!0,this.uploadRequest&&typeof this.uploadRequest.abort=="function"&&this.uploadRequest.abort(),this.progressView&&this.progressView.markCancelled(),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(e){console.warn("Error hiding progress toast on cancel:",e)}},1500),!0)}isCancelled(){return this.cancelled}then(e,t){return this.promise.then(e,t)}catch(e){return this.promise.catch(e)}finally(e){return this.promise.finally(e)}getStats(){return{filename:this.options.file.name,size:this.options.file.size,type:this.options.file.type,cancelled:this.cancelled,group:this.options.group,description:this.options.description}}}class le extends se{constructor(e={}){super(e,{endpoint:"/api/group"})}}class ke extends oe{constructor(e={}){super({ModelClass:le,endpoint:"/api/group",size:10,...e})}}const rt={org:"Organization",division:"Division",department:"Department",team:"Team",merchant:"Merchant",partner:"Partner",client:"Client",iso:"ISO",sales:"Sales",reseller:"Reseller",location:"Location",region:"Region",route:"Route",project:"Project",inventory:"Inventory",test:"Testing",misc:"Miscellaneous",qa:"Quality Assurance"},Le=Object.entries(rt).map(([c,e])=>({value:c,label:e})),Pe={create:{title:"Create Group",fields:[{name:"name",type:"text",label:"Group Name",required:!0,placeholder:"Enter group name"},{name:"kind",type:"select",label:"Group Kind",required:!0,options:Le},{type:"collection",name:"parent",label:"Parent Group",Collection:ke,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300}]},edit:{title:"Edit Group",fields:[{name:"name",type:"text",label:"Group Name",required:!0,placeholder:"Enter group name"},{name:"kind",type:"select",label:"Group Kind",required:!0,options:Le},{type:"collection",name:"parent",label:"Parent Group",Collection:ke,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300},{name:"metadata.domain",type:"text",label:"Default Domain",placeholder:"Enter Domain"},{name:"metadata.portal",type:"text",label:"Default Portal",placeholder:"Enter Portal URL"},{name:"is_active",type:"switch",label:"Is Active",cols:4}]}};le.EDIT_FORM=Pe.edit,le.ADD_FORM=Pe.create,le.CREATE_FORM=Pe.create,le.GroupKindOptions=Le,le.GroupKinds=rt;class S extends se{constructor(e={}){super(e,{endpoint:"/api/user"})}hasPermission(e){if(this.get("is_superuser"))return!0;if(Array.isArray(e))return e.some(i=>this.hasPermission(i));const t=e.startsWith("sys."),s=t?e.substring(4):e;return!!(this._hasPermission(s)||!t&&this.member&&this.member.hasPermission(e))}_hasPermission(e){const t=this.get("permissions");if(!t)return!1;if(t[e]==!0)return!0;const s=S.GRANULAR_TO_CATEGORY[e];return!!(s&&t[s]==!0)}hasPerm(e){return this.hasPermission(e)}}S.CATEGORY_PERMISSIONS=[{name:"view_admin",label:"Admin Panel",tooltip:"Access the admin panel, Mojo, and system tools"},{name:"security",label:"Security",tooltip:"Incidents, events, rules, tickets, firewall, bouncer, GeoIP, system logs"},{name:"users",label:"Users",tooltip:"User records, passkeys, TOTP, API keys, OAuth, devices, locations"},{name:"groups",label:"Groups",tooltip:"Groups, members, group API keys, settings"},{name:"comms",label:"Communications",tooltip:"Email, phone, SMS, push notifications, chat, notifications"},{name:"jobs",label:"Jobs",tooltip:"Jobs, job events, job logs, runners, queue control, system stats"},{name:"metrics",label:"Metrics",tooltip:"Metrics recording, fetching, categories, values, permissions"},{name:"files",label:"Files",tooltip:"File managers, files, renditions, vault files, vault data, S3 buckets"},{name:"assistant",label:"Mojo",tooltip:"Access to Mojo"},{name:"comms",label:"Communication",tooltip:"Ability to notify users"}],S.GRANULAR_PERMISSION_TABS=[{label:"Account",permissions:[{name:"view_users",label:"View Users"},{name:"manage_users",label:"Manage Users"},{name:"view_groups",label:"View Groups"},{name:"manage_groups",label:"Manage Groups"},{name:"manage_group",label:"Manage Own Group"},{name:"view_members",label:"View Members"},{name:"manage_settings",label:"Manage Settings"}]},{label:"Communication",permissions:[{name:"manage_chat",label:"Manage Chat"},{name:"manage_aws",label:"Manage Email (AWS)"},{name:"view_notifications",label:"View Notifications"},{name:"manage_notifications",label:"Manage Notifications"},{name:"send_notifications",label:"Send Notifications"},{name:"view_devices",label:"View Push Devices"},{name:"manage_devices",label:"Manage Push Devices"},{name:"manage_push_config",label:"Push Config"},{name:"view_phone_numbers",label:"View Phone Numbers"},{name:"manage_phone_numbers",label:"Manage Phone Numbers"},{name:"manage_phone_config",label:"Phone Config"},{name:"view_sms",label:"View SMS"},{name:"manage_sms",label:"Manage SMS"},{name:"send_sms",label:"Send SMS"}]},{label:"Platform",permissions:[{name:"view_security",label:"View Security"},{name:"manage_security",label:"Manage Security"},{name:"admin",label:"Log Admin"},{name:"view_logs",label:"View Logs"},{name:"manage_logs",label:"Manage Logs"},{name:"view_jobs",label:"View Jobs"},{name:"manage_jobs",label:"Manage Jobs"},{name:"view_metrics",label:"View Metrics"},{name:"manage_metrics",label:"Manage Metrics"},{name:"write_metrics",label:"Write Metrics"},{name:"view_fileman",label:"View File Managers"},{name:"manage_files",label:"Manage Files"},{name:"view_vault",label:"View Vault"},{name:"manage_vault",label:"Manage Vault"},{name:"manage_docit",label:"Manage Docs"},{name:"manage_shortlinks",label:"Manage Shortlinks"}]}],S.CATEGORY_GRANULAR_MAP={security:["view_security","manage_security"],users:["view_users","manage_users","view_members"],groups:["view_groups","manage_groups","manage_group"],comms:["manage_chat","manage_aws","view_notifications","manage_notifications","send_notifications","view_devices","manage_devices","manage_push_config","view_phone_numbers","manage_phone_numbers","manage_phone_config","view_sms","manage_sms","send_sms"],jobs:["view_jobs","manage_jobs"],metrics:["view_metrics","manage_metrics","write_metrics"],files:["view_fileman","manage_files","view_vault","manage_vault"]},S.APP_CATEGORY_PERMISSIONS=[],S.APP_GRANULAR_PERMISSIONS=[],S._permSwitch=function(c){return{name:`permissions.${c.name}`,type:"switch",label:c.label,columns:6,...c.tooltip?{tooltip:c.tooltip}:{}}},S.PERMISSIONS=[],S.PERMISSION_FIELDS=[],S.CATEGORY_PERMISSION_FIELDS=[],S.GRANULAR_PERMISSION_FIELDS=[],S.GRANULAR_TO_CATEGORY={},S.rebuildPermissions=function(){const c=S._permSwitch;S.PERMISSIONS.length=0,S.PERMISSIONS.push(...S.CATEGORY_PERMISSIONS,...S.GRANULAR_PERMISSION_TABS.flatMap(s=>s.permissions),...S.APP_CATEGORY_PERMISSIONS,...S.APP_GRANULAR_PERMISSIONS),S.PERMISSION_FIELDS.length=0,S.PERMISSION_FIELDS.push(...S.PERMISSIONS.map(c));const e=[{label:"System",fields:S.CATEGORY_PERMISSIONS.map(c)}];S.APP_CATEGORY_PERMISSIONS.length>0&&e.push({label:"App",fields:S.APP_CATEGORY_PERMISSIONS.map(c)}),S.CATEGORY_PERMISSION_FIELDS.length=0,S.CATEGORY_PERMISSION_FIELDS.push({type:"tabset",tabs:e});const t=S.GRANULAR_PERMISSION_TABS.map(s=>({label:s.label,fields:s.permissions.map(c)}));S.APP_GRANULAR_PERMISSIONS.length>0&&t.push({label:"App",fields:S.APP_GRANULAR_PERMISSIONS.map(c)}),S.GRANULAR_PERMISSION_FIELDS.length=0,S.GRANULAR_PERMISSION_FIELDS.push({type:"tabset",tabs:t});for(const s of Object.keys(S.GRANULAR_TO_CATEGORY))delete S.GRANULAR_TO_CATEGORY[s];for(const[s,i]of Object.entries(S.CATEGORY_GRANULAR_MAP))for(const r of i)S.GRANULAR_TO_CATEGORY[r]=s},S.registerCategoryMap=function(c){if(!c)return;let e=!1;for(const[t,s]of Object.entries(c)){if(!Array.isArray(s))continue;const i=S.CATEGORY_GRANULAR_MAP[t]||[];S.CATEGORY_GRANULAR_MAP[t]=Array.from(new Set([...i,...s])),e=!0}e&&S.rebuildPermissions()},S.registerPermissions=function(c){if(c){if(Array.isArray(c.categories)&&S.APP_CATEGORY_PERMISSIONS.push(...c.categories),Array.isArray(c.granularPermissions)&&S.APP_GRANULAR_PERMISSIONS.push(...c.granularPermissions),Array.isArray(c.granularTabs)&&S.GRANULAR_PERMISSION_TABS.push(...c.granularTabs),c.categoryGranularMap)for(const[e,t]of Object.entries(c.categoryGranularMap)){if(!Array.isArray(t))continue;const s=S.CATEGORY_GRANULAR_MAP[e]||[];S.CATEGORY_GRANULAR_MAP[e]=Array.from(new Set([...s,...t]))}S.rebuildPermissions()}},S.rebuildPermissions();const nt={create:{title:"Create User",fields:[{name:"email",type:"text",label:"Email",required:!0},{name:"phone_number",type:"text",label:"Phone number",columns:12},{name:"display_name",type:"text",label:"Display Name"}]},edit:{title:"Edit User",fields:[{name:"email",type:"email",label:"Email",columns:12},{name:"display_name",type:"text",label:"Display Name",columns:12},{name:"phone_number",type:"text",label:"Phone number",columns:12},{type:"collection",name:"org",label:"Organization",Collection:ke,labelField:"name",valueField:"id",columns:12}]},permissions:{fields:S.PERMISSION_FIELDS}},qt={detailed:{title:"Detailed User Information",columns:2,showEmptyValues:!0,emptyValueText:"Not set",fields:[{name:"id",label:"User ID",type:"number",colSize:3},{name:"display_name",label:"Display Name",type:"text",format:'capitalize|default("Unnamed User")',colSize:9},{name:"username",label:"Username",type:"text",format:"lowercase",colSize:6},{name:"email",label:"Email Address",type:"email",colSize:6},{name:"phone_number",label:"Phone Number",type:"phone",format:'phone|default("Not provided")',colSize:6},{name:"is_active",label:"Account Status",type:"boolean",colSize:6},{name:"last_login",label:"Last Login",type:"datetime",format:"relative",colSize:6},{name:"last_activity",label:"Last Activity",type:"datetime",format:"relative",colSize:6},{name:"avatar.url",label:"Avatar",type:"url",colSize:12},{name:"permissions",label:"User Permissions",type:"dataview",dataViewColumns:2,showEmptyValues:!1},{name:"metadata",label:"User Metadata",type:"dataview",dataViewColumns:1},{name:"avatar",label:"Avatar Details",type:"dataview",dataViewColumns:1}]}};S.DATA_VIEW=qt.detailed,S.EDIT_FORM=nt.edit,S.ADD_FORM=nt.create;let zt=class extends se{constructor(e={}){super(e,{endpoint:"/api/fileman/file"})}isImage(){return this.get("category")==="image"}getCategory(){return this.get("category")||this._inferCategoryFromContentType()}_inferCategoryFromContentType(){const e=(this.get("content_type")||"").toLowerCase();return e?e.startsWith("image/")?"image":e.startsWith("video/")?"video":e.startsWith("audio/")?"audio":e==="application/pdf"?"pdf":e.startsWith("text/")||e==="application/msword"||e.startsWith("application/vnd.openxmlformats-officedocument.wordprocessingml")||e==="application/vnd.oasis.opendocument.text"?"document":e==="application/vnd.ms-excel"||e.startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml")||e==="application/vnd.oasis.opendocument.spreadsheet"?"spreadsheet":e==="application/vnd.ms-powerpoint"||e.startsWith("application/vnd.openxmlformats-officedocument.presentationml")||e==="application/vnd.oasis.opendocument.presentation"?"presentation":e==="application/zip"||e==="application/x-rar-compressed"||e==="application/x-7z-compressed"||e==="application/x-tar"||e==="application/gzip"?"archive":"other":"other"}hasRenditions(){const e=this.get("renditions");return!!(e&&Object.keys(e).length)}isUploadPending(){const e=this.get("upload_status");return!!(e&&e!=="completed"&&e!=="failed")}regenerateRenditions(e){const t=this.id||this.get("id");if(!t)return Promise.reject(new Error("Cannot regenerate renditions on an unsaved file"));const s=Array.isArray(e)&&e.length?{regenerate_renditions:e}:{regenerate_renditions:!0};return this.rest.POST(`${this.endpoint}/${t}`,s)}share(e=!0){const t=this.id||this.get("id");return t?this.rest.POST(`${this.endpoint}/${t}`,{share:e}):Promise.reject(new Error("Cannot share an unsaved file"))}getRenditions(){const e=this.get("renditions");return e?Object.values(e):[]}getBestImageRendition(){const e=this.getRenditions().filter(t=>t&&typeof t.content_type=="string"&&t.content_type.startsWith("image/"));return e.length?e.reduce((t,s)=>{const i=(parseInt(t.width)||0)*(parseInt(t.height)||0);return(parseInt(s.width)||0)*(parseInt(s.height)||0)>i?s:t}):null}getThumbnailUrl(){const e=this.get("renditions")||{};if(e.thumbnail&&e.thumbnail.url)return e.thumbnail.url;const t=this.getBestImageRendition();return t?t.url:null}upload(e={}){return new Rt(this,e)}};class v{static _renderAndAwait(e,{buttons:t=null,rejectOnDismiss:s=!1,onAction:i=null,cleanup:r=null}={}){const n=_.getMountTarget();return new Promise((a,o)=>{let l=!1;const d=u=>{l||(l=!0,a(u))},h=u=>{l||(l=!0,o(u))};(async()=>{try{await e.render(!0,n)}catch(u){h(u);return}t&&t.length>0&&e.element&&e.element.querySelectorAll(".modal-footer button").forEach((m,p)=>{const f=t[p];f&&m.addEventListener("click",async g=>{if(l)return;const b=f.value!==void 0?f.value:f.action??p;if(typeof f.handler=="function"){try{const y=await f.handler({dialog:e,button:f,index:p,event:g});if(y===null||y===!1)return;const w=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(w)}catch(y){console.error("Modal button handler error:",y)}return}if(typeof i=="function"&&f.action){try{const y=await i(f.action,{dialog:e,button:f,index:p,event:g});if(y===null||y===!1)return;const w=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(w)}catch(y){console.error("Modal onAction error:",y)}return}f.dismiss||e.hide(),d(b)})}),e.on("hidden",()=>{l||(s?h(new Error("Dialog dismissed")):d(null)),setTimeout(async()=>{try{typeof r=="function"&&await r(e)}catch(u){console.error("Modal cleanup error:",u)}try{await e.destroy()}catch(u){console.error("Modal destroy error:",u)}e.element?.parentNode&&e.element.parentNode.removeChild(e.element)},100)}),e.show()})()})}static async dialog(e={}){if(typeof e=="string"){const p=arguments[0],f=arguments[1]||"Alert";e={...arguments[2]||{},body:p,title:f}}const{title:t="Dialog",content:s,body:i,view:r,message:n,size:a="md",centered:o=!0,buttons:l=[{text:"OK",class:"btn-primary",value:!0}],rejectOnDismiss:d=!1,...h}=e,u=i??r??n??s??"",m=new _({title:t,body:u,size:a,centered:o,buttons:l,...h});return v._renderAndAwait(m,{buttons:l,rejectOnDismiss:d})}static async drawer(e={}){const{eyebrow:t,title:s,meta:i=[],view:r,body:n,size:a="lg",...o}=e,l=i.length?`
202
+ `}updateProgress(e){this.cancelled||this.completed||(this.progress=e.progress,this.percentage=e.percentage,this.loaded=e.loaded,this.total=e.total||this.filesize,this.loadedFormatted=P.pipe(this.loaded,"filesize"),this.totalFormatted=P.pipe(this.total,"filesize"),this.percentage<100?this.status=`Uploading... ${this.percentage}%`:this.status="Finalizing upload...",this.render())}markCompleted(e="Upload completed!"){this.completed=!0,this.progress=1,this.percentage=100,this.status=e,this.render()}markFailed(e="Upload failed"){this.status=e,this.render()}markCancelled(){this.cancelled=!0,this.status="Upload cancelled",this.render()}async onActionCancel(e,t,s){if(!(this.cancelled||this.completed)&&(s.disabled=!0,this.markCancelled(),this.emit("cancel"),typeof this.onCancel=="function"))try{await this.onCancel()}catch(i){console.error("Error in cancel callback:",i)}}setFilename(e){this.filename=e,this.render()}setFilesize(e){this.filesize=e,this.filesizeFormatted=P.pipe(e,"filesize"),this.total=e,this.totalFormatted=this.filesizeFormatted,this.render()}getPercentage(){return this.percentage}isCompleted(){return this.completed}isCancelled(){return this.cancelled}getStats(){return{filename:this.filename,filesize:this.filesize,progress:this.progress,percentage:this.percentage,loaded:this.loaded,total:this.total,cancelled:this.cancelled,completed:this.completed,status:this.status}}}class Rt{constructor(e,t={}){if(this.fileModel=e,this.options={file:null,name:null,group:null,description:null,onProgress:null,onComplete:null,onError:null,showToast:!0,...t},!this.options.file||!(this.options.file instanceof File))throw new Error("FileUpload requires a valid File object");this.cancelled=!1,this.uploadRequest=null,this.progressToast=null,this.progressView=null,this.toastService=null,this.options.showToast&&(this.toastService=new jt),this.promise=this._startUpload()}async _startUpload(){try{this.options.showToast&&this._showProgressToast();let e;try{e=await this._initiateUpload()}catch(i){throw new Error(`Failed to initiate upload: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");if(!e||!e.upload_url)throw new Error("Invalid upload response: missing upload URL");let t;if(typeof e.upload_url=="string")t={url:e.upload_url,method:"PUT",fields:null,headers:{}};else if(e.upload_url&&typeof e.upload_url=="object"&&e.upload_url.upload_url)t={url:e.upload_url.upload_url,method:e.upload_url.method||"POST",fields:e.upload_url.fields||null,headers:e.upload_url.headers||{}};else throw new Error(`Invalid upload response: unrecognised upload_url format. Server returned: ${JSON.stringify(e.upload_url)}`);let s;try{s=await this._performUpload(t)}catch(i){throw new Error(`File upload failed: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");try{await this._completeUpload()}catch(i){console.warn("Failed to mark upload as completed:",i)}return this._onComplete(this.fileModel),this.fileModel}catch(e){throw e.message!=="Upload cancelled"&&this._onError(e),e}}async _initiateUpload(){try{const e={filename:this.options.name||this.options.file.name,file_size:this.options.file.size,content_type:this.options.file.type};this.options.group&&(e.group=this.options.group),this.options.description&&(e.description=this.options.description);const t=await this.fileModel.rest.POST("/api/fileman/upload/initiate",e);if(!t)throw new Error("No response from upload initiation API");if(!t.data)throw new Error("Upload initiation response missing data");if(!t.data.status){const s=t.data.error||"Upload initiation failed";throw new Error(s)}if(!t.data.data)throw new Error("Upload initiation response missing data payload");return t.data.data.id&&this.fileModel.set("id",t.data.data.id),t.data.data}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload initiation. Please check your connection."):e}}async _performUpload(e){return new Promise((t,s)=>{if(!(this.options.file instanceof File)){s(new Error("Only single File objects are supported"));return}const{url:i,method:r,fields:n,headers:a}=e,o=r==="POST"&&n!==null,l=new XMLHttpRequest;this.uploadRequest=l,l.upload.onprogress=u=>{this.cancelled||this._onProgress({progress:u.loaded/u.total,loaded:u.loaded,total:u.total,percentage:Math.round(u.loaded/u.total*100)})},l.onload=()=>{l.status>=200&&l.status<300?t({data:l.response,status:l.status,statusText:l.statusText,xhr:l}):s(new Error(`Upload failed: ${l.status} ${l.statusText}`))},l.onerror=()=>s(new Error("Upload failed: Network error")),l.ontimeout=()=>s(new Error("Upload timed out — file may be too large or connection too slow")),l.onabort=()=>s(new Error("Upload cancelled"));let d=i;i.startsWith("/")&&!i.startsWith("/api/")&&(d="/api"+i);const h=this.fileModel.rest.buildUrl(d);if(l.open(r,h),l.timeout=3e4,o){for(const[m,p]of Object.entries(a||{}))m.toLowerCase()!=="content-type"&&l.setRequestHeader(m,p);const u=new FormData;for(const[m,p]of Object.entries(n))u.append(m,p);u.append("file",this.options.file),l.send(u)}else{l.setRequestHeader("Content-Type",this.options.file.type);for(const[u,m]of Object.entries(a||{}))u.toLowerCase()!=="content-type"&&l.setRequestHeader(u,m);l.send(this.options.file)}})}async _completeUpload(){try{const e=await this.fileModel.save({action:"mark_as_completed"});if(!e)throw new Error("No response from upload completion API");if(e.data&&!e.data.status){const t=e.data.error||"Failed to mark upload as completed";throw new Error(t)}return e}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload completion. The file may have uploaded successfully."):e}}_onProgress(e){this.progressToast&&this.progressToast.updateProgress&&this.progressToast.updateProgress(e),typeof this.options.onProgress=="function"&&this.options.onProgress(e)}_onComplete(e){this.progressView&&this.progressView.markCompleted("Upload completed successfully!"),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast:",t)}},2e3),typeof this.options.onComplete=="function"&&this.options.onComplete(e)}_onError(e){if(this.progressToast)try{this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast on error:",t)}this.toastService&&this.toastService.error(`Upload failed: ${e.message}`),typeof this.options.onError=="function"&&this.options.onError(e)}_showProgressToast(){this.progressView=new Me({filename:this.options.name||this.options.file.name,filesize:this.options.file.size,showCancel:!0,onCancel:()=>this.cancel()}),this.progressToast=this.toastService.showView(this.progressView,"info",{title:"File Upload",autohide:!1,dismissible:!1})}cancel(){return this.cancelled?!1:(this.cancelled=!0,this.uploadRequest&&typeof this.uploadRequest.abort=="function"&&this.uploadRequest.abort(),this.progressView&&this.progressView.markCancelled(),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(e){console.warn("Error hiding progress toast on cancel:",e)}},1500),!0)}isCancelled(){return this.cancelled}then(e,t){return this.promise.then(e,t)}catch(e){return this.promise.catch(e)}finally(e){return this.promise.finally(e)}getStats(){return{filename:this.options.file.name,size:this.options.file.size,type:this.options.file.type,cancelled:this.cancelled,group:this.options.group,description:this.options.description}}}class le extends se{constructor(e={}){super(e,{endpoint:"/api/group"})}}class ke extends oe{constructor(e={}){super({ModelClass:le,endpoint:"/api/group",size:10,...e})}}const rt={org:"Organization",division:"Division",department:"Department",team:"Team",merchant:"Merchant",partner:"Partner",client:"Client",iso:"ISO",sales:"Sales",reseller:"Reseller",location:"Location",region:"Region",route:"Route",project:"Project",inventory:"Inventory",test:"Testing",misc:"Miscellaneous",qa:"Quality Assurance"},Le=Object.entries(rt).map(([c,e])=>({value:c,label:e})),Ve={create:{title:"Create Group",fields:[{name:"name",type:"text",label:"Group Name",required:!0,placeholder:"Enter group name"},{name:"kind",type:"select",label:"Group Kind",required:!0,options:Le},{type:"collection",name:"parent",label:"Parent Group",Collection:ke,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300}]},edit:{title:"Edit Group",fields:[{name:"name",type:"text",label:"Group Name",required:!0,placeholder:"Enter group name"},{name:"kind",type:"select",label:"Group Kind",required:!0,options:Le},{type:"collection",name:"parent",label:"Parent Group",Collection:ke,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300},{name:"metadata.domain",type:"text",label:"Default Domain",placeholder:"Enter Domain"},{name:"metadata.portal",type:"text",label:"Default Portal",placeholder:"Enter Portal URL"},{name:"is_active",type:"switch",label:"Is Active",cols:4}]}};le.EDIT_FORM=Ve.edit,le.ADD_FORM=Ve.create,le.CREATE_FORM=Ve.create,le.GroupKindOptions=Le,le.GroupKinds=rt;class S extends se{constructor(e={}){super(e,{endpoint:"/api/user"})}hasPermission(e){if(this.get("is_superuser"))return!0;if(Array.isArray(e))return e.some(i=>this.hasPermission(i));const t=e.startsWith("sys."),s=t?e.substring(4):e;return!!(this._hasPermission(s)||!t&&this.member&&this.member.hasPermission(e))}_hasPermission(e){const t=this.get("permissions");if(!t)return!1;if(t[e]==!0)return!0;const s=S.GRANULAR_TO_CATEGORY[e];return!!(s&&t[s]==!0)}hasPerm(e){return this.hasPermission(e)}}S.CATEGORY_PERMISSIONS=[{name:"view_admin",label:"Admin Panel",tooltip:"Access the admin panel, Mojo, and system tools"},{name:"security",label:"Security",tooltip:"Incidents, events, rules, tickets, firewall, bouncer, GeoIP, system logs"},{name:"users",label:"Users",tooltip:"User records, passkeys, TOTP, API keys, OAuth, devices, locations"},{name:"groups",label:"Groups",tooltip:"Groups, members, group API keys, settings"},{name:"comms",label:"Communications",tooltip:"Email, phone, SMS, push notifications, chat, notifications"},{name:"jobs",label:"Jobs",tooltip:"Jobs, job events, job logs, runners, queue control, system stats"},{name:"metrics",label:"Metrics",tooltip:"Metrics recording, fetching, categories, values, permissions"},{name:"files",label:"Files",tooltip:"File managers, files, renditions, vault files, vault data, S3 buckets"},{name:"assistant",label:"Mojo",tooltip:"Access to Mojo"},{name:"comms",label:"Communication",tooltip:"Ability to notify users"}],S.GRANULAR_PERMISSION_TABS=[{label:"Account",permissions:[{name:"view_users",label:"View Users"},{name:"manage_users",label:"Manage Users"},{name:"view_groups",label:"View Groups"},{name:"manage_groups",label:"Manage Groups"},{name:"manage_group",label:"Manage Own Group"},{name:"view_members",label:"View Members"},{name:"manage_settings",label:"Manage Settings"}]},{label:"Communication",permissions:[{name:"manage_chat",label:"Manage Chat"},{name:"manage_aws",label:"Manage Email (AWS)"},{name:"view_notifications",label:"View Notifications"},{name:"manage_notifications",label:"Manage Notifications"},{name:"send_notifications",label:"Send Notifications"},{name:"view_devices",label:"View Push Devices"},{name:"manage_devices",label:"Manage Push Devices"},{name:"manage_push_config",label:"Push Config"},{name:"view_phone_numbers",label:"View Phone Numbers"},{name:"manage_phone_numbers",label:"Manage Phone Numbers"},{name:"manage_phone_config",label:"Phone Config"},{name:"view_sms",label:"View SMS"},{name:"manage_sms",label:"Manage SMS"},{name:"send_sms",label:"Send SMS"}]},{label:"Platform",permissions:[{name:"view_security",label:"View Security"},{name:"manage_security",label:"Manage Security"},{name:"admin",label:"Log Admin"},{name:"view_logs",label:"View Logs"},{name:"manage_logs",label:"Manage Logs"},{name:"view_jobs",label:"View Jobs"},{name:"manage_jobs",label:"Manage Jobs"},{name:"view_metrics",label:"View Metrics"},{name:"manage_metrics",label:"Manage Metrics"},{name:"write_metrics",label:"Write Metrics"},{name:"view_fileman",label:"View File Managers"},{name:"manage_files",label:"Manage Files"},{name:"view_vault",label:"View Vault"},{name:"manage_vault",label:"Manage Vault"},{name:"manage_docit",label:"Manage Docs"},{name:"manage_shortlinks",label:"Manage Shortlinks"}]}],S.CATEGORY_GRANULAR_MAP={security:["view_security","manage_security"],users:["view_users","manage_users","view_members"],groups:["view_groups","manage_groups","manage_group"],comms:["manage_chat","manage_aws","view_notifications","manage_notifications","send_notifications","view_devices","manage_devices","manage_push_config","view_phone_numbers","manage_phone_numbers","manage_phone_config","view_sms","manage_sms","send_sms"],jobs:["view_jobs","manage_jobs"],metrics:["view_metrics","manage_metrics","write_metrics"],files:["view_fileman","manage_files","view_vault","manage_vault"]},S.APP_CATEGORY_PERMISSIONS=[],S.APP_GRANULAR_PERMISSIONS=[],S._permSwitch=function(c){return{name:`permissions.${c.name}`,type:"switch",label:c.label,columns:6,...c.tooltip?{tooltip:c.tooltip}:{}}},S.PERMISSIONS=[],S.PERMISSION_FIELDS=[],S.CATEGORY_PERMISSION_FIELDS=[],S.GRANULAR_PERMISSION_FIELDS=[],S.GRANULAR_TO_CATEGORY={},S.rebuildPermissions=function(){const c=S._permSwitch;S.PERMISSIONS.length=0,S.PERMISSIONS.push(...S.CATEGORY_PERMISSIONS,...S.GRANULAR_PERMISSION_TABS.flatMap(s=>s.permissions),...S.APP_CATEGORY_PERMISSIONS,...S.APP_GRANULAR_PERMISSIONS),S.PERMISSION_FIELDS.length=0,S.PERMISSION_FIELDS.push(...S.PERMISSIONS.map(c));const e=[{label:"System",fields:S.CATEGORY_PERMISSIONS.map(c)}];S.APP_CATEGORY_PERMISSIONS.length>0&&e.push({label:"App",fields:S.APP_CATEGORY_PERMISSIONS.map(c)}),S.CATEGORY_PERMISSION_FIELDS.length=0,S.CATEGORY_PERMISSION_FIELDS.push({type:"tabset",tabs:e});const t=S.GRANULAR_PERMISSION_TABS.map(s=>({label:s.label,fields:s.permissions.map(c)}));S.APP_GRANULAR_PERMISSIONS.length>0&&t.push({label:"App",fields:S.APP_GRANULAR_PERMISSIONS.map(c)}),S.GRANULAR_PERMISSION_FIELDS.length=0,S.GRANULAR_PERMISSION_FIELDS.push({type:"tabset",tabs:t});for(const s of Object.keys(S.GRANULAR_TO_CATEGORY))delete S.GRANULAR_TO_CATEGORY[s];for(const[s,i]of Object.entries(S.CATEGORY_GRANULAR_MAP))for(const r of i)S.GRANULAR_TO_CATEGORY[r]=s},S.registerCategoryMap=function(c){if(!c)return;let e=!1;for(const[t,s]of Object.entries(c)){if(!Array.isArray(s))continue;const i=S.CATEGORY_GRANULAR_MAP[t]||[];S.CATEGORY_GRANULAR_MAP[t]=Array.from(new Set([...i,...s])),e=!0}e&&S.rebuildPermissions()},S.registerPermissions=function(c){if(c){if(Array.isArray(c.categories)&&S.APP_CATEGORY_PERMISSIONS.push(...c.categories),Array.isArray(c.granularPermissions)&&S.APP_GRANULAR_PERMISSIONS.push(...c.granularPermissions),Array.isArray(c.granularTabs)&&S.GRANULAR_PERMISSION_TABS.push(...c.granularTabs),c.categoryGranularMap)for(const[e,t]of Object.entries(c.categoryGranularMap)){if(!Array.isArray(t))continue;const s=S.CATEGORY_GRANULAR_MAP[e]||[];S.CATEGORY_GRANULAR_MAP[e]=Array.from(new Set([...s,...t]))}S.rebuildPermissions()}},S.rebuildPermissions();const nt={create:{title:"Create User",fields:[{name:"email",type:"text",label:"Email",required:!0},{name:"phone_number",type:"text",label:"Phone number",columns:12},{name:"display_name",type:"text",label:"Display Name"}]},edit:{title:"Edit User",fields:[{name:"email",type:"email",label:"Email",columns:12},{name:"display_name",type:"text",label:"Display Name",columns:12},{name:"phone_number",type:"text",label:"Phone number",columns:12},{type:"collection",name:"org",label:"Organization",Collection:ke,labelField:"name",valueField:"id",columns:12}]},permissions:{fields:S.PERMISSION_FIELDS}},qt={detailed:{title:"Detailed User Information",columns:2,showEmptyValues:!0,emptyValueText:"Not set",fields:[{name:"id",label:"User ID",type:"number",colSize:3},{name:"display_name",label:"Display Name",type:"text",format:'capitalize|default("Unnamed User")',colSize:9},{name:"username",label:"Username",type:"text",format:"lowercase",colSize:6},{name:"email",label:"Email Address",type:"email",colSize:6},{name:"phone_number",label:"Phone Number",type:"phone",format:'phone|default("Not provided")',colSize:6},{name:"is_active",label:"Account Status",type:"boolean",colSize:6},{name:"last_login",label:"Last Login",type:"datetime",format:"relative",colSize:6},{name:"last_activity",label:"Last Activity",type:"datetime",format:"relative",colSize:6},{name:"avatar.url",label:"Avatar",type:"url",colSize:12},{name:"permissions",label:"User Permissions",type:"dataview",dataViewColumns:2,showEmptyValues:!1},{name:"metadata",label:"User Metadata",type:"dataview",dataViewColumns:1},{name:"avatar",label:"Avatar Details",type:"dataview",dataViewColumns:1}]}};S.DATA_VIEW=qt.detailed,S.EDIT_FORM=nt.edit,S.ADD_FORM=nt.create;let zt=class extends se{constructor(e={}){super(e,{endpoint:"/api/fileman/file"})}isImage(){return this.get("category")==="image"}getCategory(){return this.get("category")||this._inferCategoryFromContentType()}_inferCategoryFromContentType(){const e=(this.get("content_type")||"").toLowerCase();return e?e.startsWith("image/")?"image":e.startsWith("video/")?"video":e.startsWith("audio/")?"audio":e==="application/pdf"?"pdf":e.startsWith("text/")||e==="application/msword"||e.startsWith("application/vnd.openxmlformats-officedocument.wordprocessingml")||e==="application/vnd.oasis.opendocument.text"?"document":e==="application/vnd.ms-excel"||e.startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml")||e==="application/vnd.oasis.opendocument.spreadsheet"?"spreadsheet":e==="application/vnd.ms-powerpoint"||e.startsWith("application/vnd.openxmlformats-officedocument.presentationml")||e==="application/vnd.oasis.opendocument.presentation"?"presentation":e==="application/zip"||e==="application/x-rar-compressed"||e==="application/x-7z-compressed"||e==="application/x-tar"||e==="application/gzip"?"archive":"other":"other"}hasRenditions(){const e=this.get("renditions");return!!(e&&Object.keys(e).length)}isUploadPending(){const e=this.get("upload_status");return!!(e&&e!=="completed"&&e!=="failed")}regenerateRenditions(e){const t=this.id||this.get("id");if(!t)return Promise.reject(new Error("Cannot regenerate renditions on an unsaved file"));const s=Array.isArray(e)&&e.length?{regenerate_renditions:e}:{regenerate_renditions:!0};return this.rest.POST(`${this.endpoint}/${t}`,s)}share(e=!0){const t=this.id||this.get("id");return t?this.rest.POST(`${this.endpoint}/${t}`,{share:e}):Promise.reject(new Error("Cannot share an unsaved file"))}getRenditions(){const e=this.get("renditions");return e?Object.values(e):[]}getBestImageRendition(){const e=this.getRenditions().filter(t=>t&&typeof t.content_type=="string"&&t.content_type.startsWith("image/"));return e.length?e.reduce((t,s)=>{const i=(parseInt(t.width)||0)*(parseInt(t.height)||0);return(parseInt(s.width)||0)*(parseInt(s.height)||0)>i?s:t}):null}getThumbnailUrl(){const e=this.get("renditions")||{};if(e.thumbnail&&e.thumbnail.url)return e.thumbnail.url;const t=this.getBestImageRendition();return t?t.url:null}upload(e={}){return new Rt(this,e)}};class w{static _renderAndAwait(e,{buttons:t=null,rejectOnDismiss:s=!1,onAction:i=null,cleanup:r=null}={}){const n=_.getMountTarget();return new Promise((a,o)=>{let l=!1;const d=u=>{l||(l=!0,a(u))},h=u=>{l||(l=!0,o(u))};(async()=>{try{await e.render(!0,n)}catch(u){h(u);return}t&&t.length>0&&e.element&&e.element.querySelectorAll(".modal-footer button").forEach((m,p)=>{const f=t[p];f&&m.addEventListener("click",async g=>{if(l)return;const b=f.value!==void 0?f.value:f.action??p;if(typeof f.handler=="function"){try{const y=await f.handler({dialog:e,button:f,index:p,event:g});if(y===null||y===!1)return;const v=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(v)}catch(y){console.error("Modal button handler error:",y)}return}if(typeof i=="function"&&f.action){try{const y=await i(f.action,{dialog:e,button:f,index:p,event:g});if(y===null||y===!1)return;const v=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(v)}catch(y){console.error("Modal onAction error:",y)}return}f.dismiss||e.hide(),d(b)})}),e.on("hidden",()=>{l||(s?h(new Error("Dialog dismissed")):d(null)),setTimeout(async()=>{try{typeof r=="function"&&await r(e)}catch(u){console.error("Modal cleanup error:",u)}try{await e.destroy()}catch(u){console.error("Modal destroy error:",u)}e.element?.parentNode&&e.element.parentNode.removeChild(e.element)},100)}),e.show()})()})}static async dialog(e={}){if(typeof e=="string"){const p=arguments[0],f=arguments[1]||"Alert";e={...arguments[2]||{},body:p,title:f}}const{title:t="Dialog",content:s,body:i,view:r,message:n,size:a="md",centered:o=!0,buttons:l=[{text:"OK",class:"btn-primary",value:!0}],rejectOnDismiss:d=!1,...h}=e,u=i??r??n??s??"",m=new _({title:t,body:u,size:a,centered:o,buttons:l,...h});return w._renderAndAwait(m,{buttons:l,rejectOnDismiss:d})}static async drawer(e={}){const{eyebrow:t,title:s,meta:i=[],view:r,body:n,size:a="lg",...o}=e,l=i.length?`
203
203
  <div class="modal-drawer-meta">
204
- ${i.map(u=>typeof u=="string"?`<span>${v._esc(u)}</span>`:`<span>${u.icon?`<i class="${v._esc(u.icon)} me-1"></i>`:""}${v._esc(u.text||"")}</span>`).join("")}
204
+ ${i.map(u=>typeof u=="string"?`<span>${w._esc(u)}</span>`:`<span>${u.icon?`<i class="${w._esc(u.icon)} me-1"></i>`:""}${w._esc(u.text||"")}</span>`).join("")}
205
205
  </div>`:"",d=`
206
206
  <div class="modal-drawer-head">
207
- ${t?`<span class="modal-drawer-eyebrow">${v._esc(t)}</span>`:""}
208
- <h2 class="modal-drawer-title">${v._esc(s||"")}</h2>
207
+ ${t?`<span class="modal-drawer-eyebrow">${w._esc(t)}</span>`:""}
208
+ <h2 class="modal-drawer-title">${w._esc(s||"")}</h2>
209
209
  ${l}
210
210
  </div>
211
- `;let h;if(r&&typeof r=="object"&&typeof r.render=="function"){const u=class extends C{async getTemplate(){return`${d}<div class="modal-drawer-body" data-container="drawer-body"></div>`}async onInit(){r.containerId="drawer-body",this.addChild(r)}};h=new u}else h=`${d}<div class="modal-drawer-body">${n||""}</div>`;return v.dialog({header:!1,body:h,size:a,centered:!1,buttons:[{text:"Close",class:"btn-secondary",dismiss:!0}],...o})}static _esc(e){const t=typeof document<"u"?document.createElement("div"):null;return t?(t.textContent=String(e??""),t.innerHTML):String(e??"")}static async show(e,t={}){return v.dialog({header:t.title!==void 0?!!t.title:!1,title:t.title||void 0,body:e,size:"lg",centered:!1,buttons:[{text:"Close",class:"btn-secondary",dismiss:!0}],...t})}static async showModel(e,t={}){const s=e.constructor,i=s?.VIEW_CLASS;if(!i)throw new Error(`Modal.showModel: No VIEW_CLASS defined on ${s?.name||"model"}. Set ${s?.name||"Model"}.VIEW_CLASS = YourView to use this method.`);const r=new i({model:e});return v.show(r,t)}static async showModelById(e,t,s={}){const i=new e({id:t});return await i.fetch(),i.id?v.showModel(i,s):(v.alert({message:`Could not find ${e.name||"record"} with ID: ${t}`,type:"warning"}),null)}static async showModelView(e,t={}){const s=e.constructor,i=s?.VIEW_CLASS;if(!i)throw new Error(`Modal.showModelView: No VIEW_CLASS defined on ${s?.name||"model"}.`);const r=new i({model:e});return v.dialog({header:!1,body:r,size:"lg",centered:!1,...t})}static async alert(e={},t,s){let i;typeof e=="string"?i={message:e,...t!==void 0?{title:t}:{},...s||{}}:i={...e};const{message:r="",title:n="Alert",type:a="info",icon:o,className:l,...d}=i,h=a==="danger"?"error":a,m=[`modal-alert modal-alert-${h}`,l].filter(Boolean).join(" "),f=o!==void 0?o:{info:"bi-info-circle",success:"bi-check-circle",warning:"bi-exclamation-triangle",error:"bi-x-circle"}[h],g=f?`<i class="bi ${f} modal-alert-icon"></i>`:"",b=`<span class="modal-alert-headline">${n}</span>`;return v.dialog({title:`${g}${b}`,body:`<p class="modal-alert-message">${r}</p>`,size:"sm",centered:!0,className:m,buttons:[{text:"OK",class:"btn-primary",value:!0}],...d})}static async confirm(e,t="Confirm",s={}){let i;typeof e=="object"&&e!==null?(s=e,i=s.message,t=s.title||t):i=e;const r=[{text:s.cancelText||"Cancel",class:"btn-secondary",dismiss:!0,action:"cancel"},{text:s.confirmText||"Confirm",class:s.confirmClass||"btn-primary",action:"confirm"}],n=new _({title:t,body:`<p>${i}</p>`,size:s.size||"sm",centered:!0,backdrop:"static",buttons:r,...s});return await v._renderAndAwait(n,{buttons:r})==="confirm"}static async prompt(e,t="Input",s={}){const i=`prompt-input-${Date.now()}`,r=s.defaultValue||"",n=s.inputType||"text",a=s.placeholder||"",o=[{text:"Cancel",class:"btn-secondary",dismiss:!0},{text:"OK",class:"btn-primary",action:"ok"}],l=new _({title:t,body:`
211
+ `;let h;if(r&&typeof r=="object"&&typeof r.render=="function"){const u=class extends C{async getTemplate(){return`${d}<div class="modal-drawer-body" data-container="drawer-body"></div>`}async onInit(){r.containerId="drawer-body",this.addChild(r)}};h=new u}else h=`${d}<div class="modal-drawer-body">${n||""}</div>`;return w.dialog({header:!1,body:h,size:a,centered:!1,buttons:[{text:"Close",class:"btn-secondary",dismiss:!0}],...o})}static _esc(e){const t=typeof document<"u"?document.createElement("div"):null;return t?(t.textContent=String(e??""),t.innerHTML):String(e??"")}static async show(e,t={}){return w.dialog({header:t.title!==void 0?!!t.title:!1,title:t.title||void 0,body:e,size:"lg",centered:!1,buttons:[{text:"Close",class:"btn-secondary",dismiss:!0}],...t})}static async showModel(e,t={}){const s=e.constructor,i=s?.VIEW_CLASS;if(!i)throw new Error(`Modal.showModel: No VIEW_CLASS defined on ${s?.name||"model"}. Set ${s?.name||"Model"}.VIEW_CLASS = YourView to use this method.`);const r=new i({model:e});return w.show(r,t)}static async showModelById(e,t,s={}){const i=new e({id:t});return await i.fetch(),i.id?w.showModel(i,s):(w.alert({message:`Could not find ${e.name||"record"} with ID: ${t}`,type:"warning"}),null)}static async showModelView(e,t={}){const s=e.constructor,i=s?.VIEW_CLASS;if(!i)throw new Error(`Modal.showModelView: No VIEW_CLASS defined on ${s?.name||"model"}.`);const r=new i({model:e});return w.dialog({header:!1,body:r,size:"lg",centered:!1,...t})}static async alert(e={},t,s){let i;typeof e=="string"?i={message:e,...t!==void 0?{title:t}:{},...s||{}}:i={...e};const{message:r="",title:n="Alert",type:a="info",icon:o,className:l,...d}=i,h=a==="danger"?"error":a,m=[`modal-alert modal-alert-${h}`,l].filter(Boolean).join(" "),f=o!==void 0?o:{info:"bi-info-circle",success:"bi-check-circle",warning:"bi-exclamation-triangle",error:"bi-x-circle"}[h],g=f?`<i class="bi ${f} modal-alert-icon"></i>`:"",b=`<span class="modal-alert-headline">${n}</span>`;return w.dialog({title:`${g}${b}`,body:`<p class="modal-alert-message">${r}</p>`,size:"sm",centered:!0,className:m,buttons:[{text:"OK",class:"btn-primary",value:!0}],...d})}static async confirm(e,t="Confirm",s={}){let i;typeof e=="object"&&e!==null?(s=e,i=s.message,t=s.title||t):i=e;const r=[{text:s.cancelText||"Cancel",class:"btn-secondary",dismiss:!0,action:"cancel"},{text:s.confirmText||"Confirm",class:s.confirmClass||"btn-primary",action:"confirm"}],n=new _({title:t,body:`<p>${i}</p>`,size:s.size||"sm",centered:!0,backdrop:"static",buttons:r,...s});return await w._renderAndAwait(n,{buttons:r})==="confirm"}static async prompt(e,t="Input",s={}){const i=`prompt-input-${Date.now()}`,r=s.defaultValue||"",n=s.inputType||"text",a=s.placeholder||"",o=[{text:"Cancel",class:"btn-secondary",dismiss:!0},{text:"OK",class:"btn-primary",action:"ok"}],l=new _({title:t,body:`
212
212
  <p>${e}</p>
213
213
  <input type="${n}"
214
214
  class="form-control"
215
215
  id="${i}"
216
216
  value="${r}"
217
217
  placeholder="${a}">
218
- `,size:s.size||"sm",centered:!0,backdrop:"static",buttons:o,...s});return l.on("shown",()=>{const d=l.element.querySelector(`#${i}`);d&&(d.focus(),d.select())}),v._renderAndAwait(l,{buttons:o,onAction:async d=>{if(d!=="ok")return null;const h=l.element.querySelector(`#${i}`);return h?h.value:null}})}static showError(e){return v.alert(e,"Error",{type:"error"})}static async form(e={}){const{title:t="Form",formConfig:s={},size:i="md",centered:r=!0,submitText:n="Submit",cancelText:a="Cancel",...o}=e,l=(await Promise.resolve().then(()=>_t)).default,d=new l({fileHandling:e.fileHandling||"base64",data:e.data,defaults:e.defaults,model:e.model,formConfig:{fields:s.fields||e.fields,...s,submitButton:!1,resetButton:!1}}),h=[{text:a,class:"btn-secondary",action:"cancel"},{text:n,class:"btn-primary",action:"submit"}],u=new _({title:t,body:d,size:i,centered:r,buttons:h,...o});return v._renderAndAwait(u,{buttons:h,onAction:async m=>{if(m==="cancel")return u.hide(),null;if(m!=="submit")return null;if(!d.validate())return d.focusFirstError(),!1;if(e.autoSave&&e.model){u.setLoading(!0);const p=await d.saveModel();return p.success?p:(u.setLoading(!1),await u.render(),u.getApp()?.toast?.error(p.message),!1)}try{return await d.getFormData()}catch(p){return console.error("Modal.form: error collecting form data:",p),d.showError("Error collecting form data"),!1}},cleanup:async()=>{try{await d.destroy()}catch{}}})}static async modelForm(e={}){const{title:t="Edit",formConfig:s={},size:i="md",centered:r=!0,submitText:n="Save",cancelText:a="Cancel",model:o,fields:l,...d}=e;if(!o)throw new Error("Modal.modelForm requires a model");const h=(await Promise.resolve().then(()=>_t)).default,u=new h({fileHandling:e.fileHandling||"base64",model:o,data:e.data,defaults:e.defaults,formConfig:{fields:l||s.fields||[],...s,submitButton:!1,resetButton:!1}}),m=[{text:a,class:"btn-secondary",action:"cancel"},{text:n,class:"btn-primary",action:"submit"}],p=new _({title:t,body:u,size:i,centered:r,buttons:m,...d});return v._renderAndAwait(p,{buttons:m,onAction:async f=>{if(f==="cancel")return p.hide(),null;if(f!=="submit")return null;p.setLoading(!0,"Saving...");try{const g=await u.handleSubmit();if(g.success)return g;p.setLoading(!1);let b=g.error;return g.data?.error&&(b=g.data.error),p.getApp()?.toast?.error(b),!1}catch(g){return console.error("Modal.modelForm: error saving:",g),await p.setContent(u),u.showError(g.message||"An error occurred while saving"),!1}},cleanup:async()=>{try{await u.destroy()}catch{}}})}static async data(e={}){const{title:t="Data View",data:s={},model:i=null,fields:r=[],columns:n=2,responsive:a=!0,showEmptyValues:o=!1,emptyValueText:l="—",size:d="lg",centered:h=!0,closeText:u="Close",...m}=e,p=(await Promise.resolve().then(()=>bs)).default,f=new p({data:s,model:i,fields:r,columns:n,responsive:a,showEmptyValues:o,emptyValueText:l}),g=[{text:u,class:"btn-secondary",value:"close"}],b=new _({title:t,body:f,size:d,centered:h,buttons:g,...m});return f.on("field:click",y=>b.emit("dataview:field:click",y)),f.on("error",y=>b.emit("dataview:error",y)),v._renderAndAwait(b,{buttons:g,cleanup:async()=>{try{await f.destroy()}catch{}}})}static async code(e={}){const{code:t="",language:s="javascript",title:i="Source Code",size:r="lg",...n}=e,a=new he({code:t,language:s}),o=[{text:"Copy to Clipboard",class:"btn-primary",icon:"bi-clipboard",action:"copy"},{text:"Close",class:"btn-secondary",dismiss:!0}],l=new _({title:i,body:a,size:r,scrollable:!0,buttons:o,...n});return v._renderAndAwait(l,{buttons:o,onAction:async d=>{if(d!=="copy")return null;if(!navigator.clipboard)return!1;try{await navigator.clipboard.writeText(t),v._showCopySuccess(l)}catch(h){console.error("Modal.code: clipboard write failed:",h)}return!1}})}static _showCopySuccess(e){const t=e.element?.querySelector('[data-action="copy"]');if(!t)return;const s=t.innerHTML;t.innerHTML='<i class="bi bi-check me-1"></i>Copied!',t.classList.remove("btn-primary"),t.classList.add("btn-success"),t.disabled=!0,setTimeout(()=>{t.innerHTML=s,t.classList.remove("btn-success"),t.classList.add("btn-primary"),t.disabled=!1},2e3)}static async htmlPreview(e={}){const{html:t=e.content||"",title:s="HTML Preview",size:i="lg",height:r=500,...n}=e,a=new Ot({html:t,height:r}),o=[{text:"Close",class:"btn-secondary",dismiss:!0}],l=new _({title:s,body:a,size:i,scrollable:!1,buttons:o,...n});return v._renderAndAwait(l,{buttons:o})}static async updateModelImage(e={},t={}){const s=e.upload||!1,i=t.name||e.field||"image",r={title:"Upload Your Avatar",model:null,autoSave:!s,size:"sm",fields:[{type:"image",name:i,size:"lg",imageSize:{width:200,height:200},placeholder:"Upload your image",...t}],...e},n=await v.form(r);if(!s||!n||!e.model)return n;const a=n[i];if(!a||!a.startsWith("data:"))return n;const o=a.split(","),d=o[0]?.match(/:(.*?);/)?.[1]||"image/png",h=atob(o[1]);let u=h.length;const m=new Uint8Array(u);for(;u--;)m[u]=h.charCodeAt(u);const p=d.split("/")[1]||"png",f=typeof window<"u"&&window.File||globalThis.File;if(!f)throw new Error("File API is not available in this environment");const g=new f([m],`${i}.${p}`,{type:d}),b=new zt;return await b.upload({file:g,name:`${i}.${p}`,description:e.uploadDescription||`${i} upload`,showToast:!0}),e.model.save({[i]:b.id})}static loading(e){Ie.show(e)}static hideLoading(e){Ie.hide(e)}static showBusy(e){return v.loading(e)}static hideBusy(e){return v.hideLoading(e)}}const N=Object.freeze(Object.defineProperty({__proto__:null,default:v},Symbol.toStringTag,{value:"Module"}));class ye{constructor(e={}){this.config=e,this.initPluginRegistry(),this.name=e.name||"MOJO App",this.version=e.version||"1.0.0",this.debug=e.debug||!1,this.container=e.container||"#app",this.layoutType=e.layout||"portal",this.layoutConfig=e.layoutConfig||{},e.sidebar&&(this.layoutConfig.sidebarConfig=e.sidebar),e.topbar&&(this.layoutConfig.topbarConfig=e.topbar),this.layout=null,this.layoutConfig.containerId=this.container||this.containerId||"#app",this.pageContainer=e.pageContainer||"#page-container",this.basePath=e.basePath||"",this.routerMode=e.routerMode||e.router?.mode||"param",this.basePath=e.basePath||e.router?.base||"",this.defaultRoute=e.defaultRoute||"home",this.session=e.session||{},this.router=null,this.navigation=e.navigation||{},this.state={currentPage:null,previousPage:null,loading:!1},this.events=new Ft,this.rest=te,this.modal=v,e.api&&this.rest.configure(e.api);const t=(this.name||"mojo").replace(/\s+/g,"_").toLowerCase();this.theme=new Tt({storageKey:`${t}:theme`,eventBus:this.events}),this.theme.init(),this.router=new $e({mode:this.routerMode==="param"?"params":this.routerMode,basePath:this.basePath,defaultRoute:this.defaultRoute,eventEmitter:this.events}),this.events.on("route:changed",async s=>{const{pageName:i,params:r,query:n}=s;await this.showPage(i,n,r,{fromRouter:!0})}),typeof window<"u"&&(window.MOJO=window.MOJO||{},window.MOJO.router=this.router),this.setupFocusTracking(),this.pageCache=new Map,this.pageClasses=new Map,this.componentClasses=new Map,this.modelClasses=new Map,this.modelRefClasses=new Map,this.currentPage=null,this.isStarted=!1,window.matchUUID?window[window.matchUUID]=this:window.MOJO?window.MOJO.app=this:window.__app__=this}async start(){if(this.isStarted){console.warn("WebApp already started");return}try{this.setupPageContainer(),this.validateDefaultRoute(),await this.setupRouter(),this.isStarted=!0,this.router.allowPopState=!1,this.events.emit("app:ready",{app:this})}catch(e){throw console.error(`Failed to start ${this.name}:`,e),this.showError("Failed to start application"),e}}async setupRouter(){if(!this.router){console.error("Router not initialized");return}this.events.on("route:notfound",async e=>{console.warn(`Route not found: ${e.path}`),this._show404(e.path)}),this.router.start(),console.log(`Router started in ${this.routerMode} mode`)}setupPageContainer(){const e=typeof this.container=="string"?document.querySelector(this.container):this.container;e&&!e.querySelector("#page-container")&&(e.innerHTML='<div id="page-container"></div>'),this.pageContainer="#page-container"}registerPage(e,t,s={}){if(typeof e!="string"||!e)return console.error("registerPage: pageName must be a non-empty string"),this;if(typeof t!="function")return console.error("registerPage: PageClass must be a constructor function"),this;if(s.containerId||(s.containerId=this.pageContainer),this.pageClasses.set(e,{PageClass:t,constructorOptions:s}),this.router){let i=s.route||`/${e}`;i.startsWith("/")||(i=`/${i}`),s.route=i,this.router.addRoute(i,e)}return this}getPage(e){return this.pageCache.get(e)}getPagePermissions(e){if(this.pageCache.has(e))return this.pageCache.get(e).permissions;const t=this.pageClasses.get(e);if(!t)return null;const{PageClass:s,constructorOptions:i}=t;return i?i.permissions:null}getOrCreatePage(e){if(this.pageCache.has(e))return this.pageCache.get(e);const t=this.pageClasses.get(e);if(!t)return console.error(`Page not registered: ${e}`),null;const{PageClass:s,constructorOptions:i}=t;try{const r={pageName:e,...i,app:this},n=new s(r);return i.route&&(n.route=i.route),this.pageCache.set(e,n),console.log(`Created page: ${e} with route: ${n.route}`),n}catch(r){return console.error(`Failed to create page ${e}:`,r),null}}async showPage(e,t={},s={},i={}){const{fromRouter:r=!1,replace:n=!1,force:a=!1}=i;try{let o,l;typeof e=="string"?(l=e,o=this.getOrCreatePage(e)):e&&typeof e=="object"&&(o=e,l=e.pageName);const d=this.currentPage;if(!o){this._show404(l,s,t,r);return}if(this.events.emit("page:showing",{page:o,pageName:o.pageName,params:s,query:t,fromRouter:r}),!o.canEnter()){this._showDeniedPage(o,s,t,r);return}d&&d!==o&&await this._exitOldPage(d),await o.onParams(s,t),d!==o&&await o.onEnter(),o.syncUrl(),this.events.emit("page:show",{page:o,pageName:o.pageName,params:s,query:t,fromRouter:r}),await o.render(),this.currentPage=o,console.log(`✅ Showing page: ${o.pageName}`,{query:t,params:s})}catch(o){console.error("Error in showPage:",o),this.showError(`Failed to load page: ${o.message}`),e!=="error"&&await this.showPage("error",{},{error:o,originalPage:e},{fromRouter:r})}}async _show404(e,t,s,i){const r=this.getOrCreatePage("404");r&&(r.setInfo&&r.setInfo(e),await this._exitOldPage(this.currentPage),await r.render(),this.currentPage=r,this.events.emit("page:404",{page:null,pageName:e,params:t,query:s,fromRouter:i}))}async _showDeniedPage(e,t,s,i){const r=this.getOrCreatePage("denied");r.setDeniedPage&&r.setDeniedPage(e),await this._exitOldPage(this.currentPage),await r.render(),this.currentPage=r,this.events.emit("page:denied",{page:e,pageName:e.pageName,params:t,query:s,fromRouter:i})}async _exitOldPage(e){if(e)try{await e.onExit(),await e.unmount(),this.events.emit("page:hide",{page:e})}catch(t){console.error(`Error exiting page ${e.pageName}:`,t)}}async navigate(e,t={},s={}){if(!this.router){console.error("Router not initialized");return}let i=e;if(Object.keys(t).length>0){const r=new URLSearchParams(t).toString();i+=(e.includes("?")?"&":"?")+r}return await this.router.navigate(i,s)}async navigateToDefault(e={}){return await this.showPage(this.defaultRoute,{},{},e)}back(){this.router?this.router.back():console.warn("Router not initialized")}forward(){this.router?this.router.forward():console.warn("Router not initialized")}getCurrentPage(){return this.currentPage}getPageContainer(){return this.layout&&this.layout.getPageContainer?this.layout.getPageContainer():typeof this.pageContainer=="string"?document.querySelector(this.pageContainer):this.pageContainer}async showError(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Error",{size:"md",type:"error"})}catch(t){this.events.emit("notification",{message:e,type:"error"}),typeof window<"u"&&window?.console&&console.error("[WebApp] showError fallback:",t),typeof window<"u"&&alert(`Error: ${e}`)}}async showSuccess(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Success",{size:"md",type:"success"})}catch(t){this.events.emit("notification",{message:e,type:"success"}),typeof window<"u"&&window?.console&&console.warn("[WebApp] showSuccess fallback:",t),typeof window<"u"&&alert(`Success: ${e}`)}}async showInfo(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Information",{size:"md",type:"info"})}catch(t){this.events.emit("notification",{message:e,type:"info"}),typeof window<"u"&&window?.console&&console.info("[WebApp] showInfo fallback:",t),typeof window<"u"&&alert(`Info: ${e}`)}}async showWarning(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Warning",{size:"md",type:"warning"})}catch(t){this.events.emit("notification",{message:e,type:"warning"}),typeof window<"u"&&window?.console&&console.warn("[WebApp] showWarning fallback:",t),typeof window<"u"&&alert(`Warning: ${e}`)}}showNotification(e,t="info"){this.events.emit("notification",{message:e,type:t})}async showLoading(e={}){typeof e=="string"&&(e={message:e});try{(await Promise.resolve().then(()=>N)).default.showBusy(e)}catch(t){typeof window<"u"&&window?.console&&console.warn("[WebApp] showLoading fallback:",t,e),this.events.emit("notification",{message:e.message||"Loading...",type:"info"})}}async hideLoading(){try{(await Promise.resolve().then(()=>N)).default.hideBusy()}catch(e){typeof window<"u"&&window?.console&&console.warn("[WebApp] hideLoading fallback:",e)}}async showModelView(e,t={}){try{return await(await Promise.resolve().then(()=>N)).default.showModelView(e,t)}catch(s){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showModelForm failed:",s),s}}async showModelForm(e={}){try{return await(await Promise.resolve().then(()=>N)).default.modelForm(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showModelForm failed:",t),t}}async showForm(e={}){try{return await(await Promise.resolve().then(()=>N)).default.form(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showForm failed:",t),t}}async showDialog(e={}){try{return await(await Promise.resolve().then(()=>N)).default.dialog(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showDialog failed:",t),t}}async showAlert(e={}){try{return await(await Promise.resolve().then(()=>N)).default.dialog(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showDialog failed:",t),t}}async confirm(e,t="Confirm",s={}){return await(await Promise.resolve().then(()=>N)).default.confirm(e,t,s)}setTheme(e){return this.theme.set(e),this}getTheme(){return this.theme.getPreference()}getResolvedTheme(){return this.theme.getResolved()}setupFocusTracking(){if(typeof window>"u")return;this.isFocused=!document.hidden;const e=()=>{const i=this.isFocused;this.isFocused=!document.hidden,i!==this.isFocused&&(this.isFocused?this.events.emit("browser:focus"):this.events.emit("browser:blur"))},t=()=>{this.isFocused||(this.isFocused=!0,this.events.emit("browser:focus"))},s=()=>{this.isFocused&&(this.isFocused=!1,this.events.emit("browser:blur"))};document.addEventListener("visibilitychange",e),window.addEventListener("focus",t),window.addEventListener("blur",s),this._focusHandlers={visibilitychange:e,focus:t,blur:s}}setupErrorHandling(){window.addEventListener("error",e=>{console.error("Global error:",e.error),this.debug&&this.showError(`Error: ${e.error?.message||"Unknown error"}`)}),window.addEventListener("unhandledrejection",e=>{console.error("Unhandled promise rejection:",e.reason),this.debug&&this.showError(`Promise rejected: ${e.reason?.message||"Unknown error"}`)})}escapeHtml(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}getState(e){return e?this.state[e]:this.state}setState(e){const t={...this.state};Object.assign(this.state,e),this.events.emit("state:changed",{oldState:t,newState:this.state,updates:e})}registerComponent(e,t){this.componentClasses.set(e,t)}getComponent(e){return this.componentClasses.get(e)}registerModel(e,t){this.modelClasses.set(e,t)}getModel(e){return this.modelClasses.get(e)}registerModelRef(e,t){this.modelRefClasses.set(e,t)}getModelByRef(e){return this.modelRefClasses.get(e)}setupRest(){this.rest=te,te.configure(this.api)}async destroy(){console.log("Destroying WebApp..."),this.router&&this.router.stop(),this._focusHandlers&&typeof window<"u"&&(document.removeEventListener("visibilitychange",this._focusHandlers.visibilitychange),window.removeEventListener("focus",this._focusHandlers.focus),window.removeEventListener("blur",this._focusHandlers.blur));const e=Array.from(this.pageCache.values());if(await Promise.allSettled(e.map(async t=>{try{t.destroy&&await t.destroy()}catch(s){console.error("Error destroying page:",s)}})),this.layout&&this.layout.destroy)try{await this.layout.destroy()}catch(t){console.error("Error destroying layout:",t)}this.pageCache.clear(),this.pageClasses.clear(),this.componentClasses.clear(),this.modelClasses.clear(),typeof window<"u"&&window.MOJO&&delete window.MOJO.router,this.isStarted=!1,console.log(`✨ ${this.name} destroyed`)}buildPagePath(e,t,s){let i=e.route||`/${e.pageName.toLowerCase()}`;if(Object.keys(t).forEach(r=>{(typeof t[r]=="string"||typeof t[r]=="number")&&(i=i.replace(`:${r}`,t[r]))}),s&&Object.keys(s).length>0){const r=new URLSearchParams(s).toString();i+=(i.includes("?")?"&":"?")+r}return i}validateDefaultRoute(){this.pageClasses.has(this.defaultRoute)?console.log(`✅ Default route '${this.defaultRoute}' is registered`):(console.warn(`⚠️ Default route '${this.defaultRoute}' is not registered!`),console.warn(` Please register a page: app.registerPage('${this.defaultRoute}', YourPageClass);`),console.warn(" Or change default route: new WebApp({ defaultRoute: 'your-page' });"))}findFallbackPage(){const e=["404","error","denied"];for(const[t]of this.pageClasses.entries())if(!e.includes(t))return t;return null}static create(e={}){return new ye(e)}initPluginRegistry(){typeof window<"u"&&(window.MOJO||(window.MOJO={}),window.MOJO.plugins||(window.MOJO.plugins={}),window.MOJO.app=this)}static registerPlugin(e,t){typeof window<"u"&&(window.MOJO||(window.MOJO={}),window.MOJO.plugins||(window.MOJO.plugins={}),window.MOJO.plugins[e]=t,console.debug(`MOJO Plugin registered: ${e}`))}}class ue extends C{constructor(e={}){e.tagName=e.tagName||"main",e.className=e.className||"mojo-page";const t=e.pageName||"";t&&!e.id&&(e.id="page_"+t.toLowerCase().replace(/\s+/g,"_")),super(e),this.pageName=e.pageName||this.constructor.pageName||"",this.route=e.route||this.constructor.route||"",this.title=e.title||this.pageName||"",!this.id&&this.constructor.pageName&&!e.pageName&&(this.id="page_"+this.constructor.pageName.toLowerCase().replace(/\s+/g,"_")),this.pageIcon=e.icon||e.pageIcon||this.constructor.pageIcon||"bi bi-file-text",this.displayName=e.displayName||this.constructor.displayName||this.pageName||"",this.pageDescription=e.pageDescription||this.constructor.pageDescription||"",this.params={},this.query={},this.matched=!1,this.isActive=!1,this.pageOptions={title:e.title||this.pageName||"Untitled Page",description:e.description||"",requiresAuth:e.requiresAuth||!1,...e.pageOptions},this.savedState=null,console.log(`Page ${this.pageName} constructed with route: ${this.route}`)}async onParams(e={},t={}){this.params=e,this.query=t}canEnter(){if(this.options.permissions){const e=this.getApp().activeUser;if(!e||!e.hasPermission(this.options.permissions))return!1}return!(this.options.requiresGroup&&!this.getApp().activeGroup)}async onEnter(){this.isActive=!0,this._wasExited=!1,await this.onInitView(),this.savedState&&(this.restoreState(this.savedState),this.savedState=null),this.pageOptions&&this.pageOptions.title&&typeof document<"u"&&(document.title=this.pageOptions.title),this.emit("activated",{page:this.getMetadata()}),console.log(`Page ${this.pageName} entered`)}async onExit(){this.savedState=this.captureState(),this.isActive=!1,this._wasExited=!0,this._clearScheduledRefreshes(),this.emit("deactivated",{page:this.getMetadata()}),console.log(`Page ${this.pageName} exiting`)}scheduleRefresh(e,t,s={}){if(this._scheduledRefreshes||(this._scheduledRefreshes=[]),typeof e!="function"||!(t>0))return null;const i=async()=>{try{await e()}catch(a){console.warn(`[Page ${this.pageName}] scheduleRefresh handler error:`,a)}};s.immediate&&i();const r=setInterval(i,t),n={id:r,tier:s.tier||null,handler:i,intervalMs:t};return this._scheduledRefreshes.push(n),{cancel:()=>{clearInterval(r),this._scheduledRefreshes=(this._scheduledRefreshes||[]).filter(a=>a!==n)}}}async runScheduledRefreshes(e=null){const t=this._scheduledRefreshes||[],s=e?t.filter(i=>i.tier===e):t;await Promise.allSettled(s.map(i=>i.handler()))}_clearScheduledRefreshes(){if(this._scheduledRefreshes){for(const e of this._scheduledRefreshes)clearInterval(e.id);this._scheduledRefreshes=[]}}async render(e=!0,t=null){return this._wasExited&&!this.isActive?this:super.render(e,t)}async onGroupChange(e){}getMetadata(){return{name:this.pageName,displayName:this.displayName||this.pageName,icon:this.pageIcon,description:this.pageDescription,route:this.route,isActive:this.isActive}}async onActionDefault(e){console.log(`Default action '${e}' triggered on page: ${this.pageName}`)}async makeActive(){this.getApp().showPage(this)}async onActionNavigate(e,t){e.preventDefault();const s=t.dataset.page;this.getApp().showPage(s)}captureState(){return this.element?{scrollTop:this.element.scrollTop,formData:this.captureFormData(),custom:this.captureCustomState()}:null}restoreState(e){!e||!this.element||(this.element.scrollTop=e.scrollTop||0,this.restoreFormData(e.formData),e.custom&&this.restoreCustomState(e.custom))}captureFormData(){const e={};return this.element&&this.element.querySelectorAll("input, select, textarea").forEach(t=>{t.name&&(t.type==="checkbox"?e[t.name]=t.checked:t.type==="radio"?t.checked&&(e[t.name]=t.value):e[t.name]=t.value)}),e}restoreFormData(e){!e||!this.element||Object.entries(e).forEach(([t,s])=>{const i=this.element.querySelector(`[name="${t}"]`);if(i)if(i.type==="checkbox")i.checked=s;else if(i.type==="radio"){const r=this.element.querySelector(`[name="${t}"][value="${s}"]`);r&&(r.checked=!0)}else i.value=s})}captureCustomState(){return{}}restoreCustomState(e){}setMeta(e={}){if(!(typeof document>"u")){if(e.title&&(document.title=e.title,this.pageOptions.title=e.title),e.description){let t=document.querySelector('meta[name="description"]');t||(t=document.createElement("meta"),t.name="description",document.head.appendChild(t)),t.content=e.description,this.pageOptions.description=e.description}Object.entries(e).forEach(([t,s])=>{if(t!=="title"&&t!=="description"){let i=document.querySelector(`meta[name="${t}"]`);i||(i=document.createElement("meta"),i.name=t,document.head.appendChild(i)),i.content=s}})}}showError(e){if(super.showError(e),this.element){const t=document.createElement("div");t.className="alert alert-danger alert-dismissible fade show",t.innerHTML=`
218
+ `,size:s.size||"sm",centered:!0,backdrop:"static",buttons:o,...s});return l.on("shown",()=>{const d=l.element.querySelector(`#${i}`);d&&(d.focus(),d.select())}),w._renderAndAwait(l,{buttons:o,onAction:async d=>{if(d!=="ok")return null;const h=l.element.querySelector(`#${i}`);return h?h.value:null}})}static showError(e){return w.alert(e,"Error",{type:"error"})}static async form(e={}){const{title:t="Form",formConfig:s={},size:i="md",centered:r=!0,submitText:n="Submit",cancelText:a="Cancel",...o}=e,l=(await Promise.resolve().then(()=>_t)).default,d=new l({fileHandling:e.fileHandling||"base64",data:e.data,defaults:e.defaults,model:e.model,formConfig:{fields:s.fields||e.fields,...s,submitButton:!1,resetButton:!1}}),h=[{text:a,class:"btn-secondary",action:"cancel"},{text:n,class:"btn-primary",action:"submit"}],u=new _({title:t,body:d,size:i,centered:r,buttons:h,...o});return w._renderAndAwait(u,{buttons:h,onAction:async m=>{if(m==="cancel")return u.hide(),null;if(m!=="submit")return null;if(!d.validate())return d.focusFirstError(),!1;if(e.autoSave&&e.model){u.setLoading(!0);const p=await d.saveModel();return p.success?p:(u.setLoading(!1),await u.render(),u.getApp()?.toast?.error(p.message),!1)}try{return await d.getFormData()}catch(p){return console.error("Modal.form: error collecting form data:",p),d.showError("Error collecting form data"),!1}},cleanup:async()=>{try{await d.destroy()}catch{}}})}static async modelForm(e={}){const{title:t="Edit",formConfig:s={},size:i="md",centered:r=!0,submitText:n="Save",cancelText:a="Cancel",model:o,fields:l,...d}=e;if(!o)throw new Error("Modal.modelForm requires a model");const h=(await Promise.resolve().then(()=>_t)).default,u=new h({fileHandling:e.fileHandling||"base64",model:o,data:e.data,defaults:e.defaults,formConfig:{fields:l||s.fields||[],...s,submitButton:!1,resetButton:!1}}),m=[{text:a,class:"btn-secondary",action:"cancel"},{text:n,class:"btn-primary",action:"submit"}],p=new _({title:t,body:u,size:i,centered:r,buttons:m,...d});return w._renderAndAwait(p,{buttons:m,onAction:async f=>{if(f==="cancel")return p.hide(),null;if(f!=="submit")return null;p.setLoading(!0,"Saving...");try{const g=await u.handleSubmit();if(g.success)return g;p.setLoading(!1);let b=g.error;return g.data?.error&&(b=g.data.error),p.getApp()?.toast?.error(b),!1}catch(g){return console.error("Modal.modelForm: error saving:",g),await p.setContent(u),u.showError(g.message||"An error occurred while saving"),!1}},cleanup:async()=>{try{await u.destroy()}catch{}}})}static async data(e={}){const{title:t="Data View",data:s={},model:i=null,fields:r=[],columns:n=2,responsive:a=!0,showEmptyValues:o=!1,emptyValueText:l="—",size:d="lg",centered:h=!0,closeText:u="Close",...m}=e,p=(await Promise.resolve().then(()=>bs)).default,f=new p({data:s,model:i,fields:r,columns:n,responsive:a,showEmptyValues:o,emptyValueText:l}),g=[{text:u,class:"btn-secondary",value:"close"}],b=new _({title:t,body:f,size:d,centered:h,buttons:g,...m});return f.on("field:click",y=>b.emit("dataview:field:click",y)),f.on("error",y=>b.emit("dataview:error",y)),w._renderAndAwait(b,{buttons:g,cleanup:async()=>{try{await f.destroy()}catch{}}})}static async code(e={}){const{code:t="",language:s="javascript",title:i="Source Code",size:r="lg",...n}=e,a=new he({code:t,language:s}),o=[{text:"Copy to Clipboard",class:"btn-primary",icon:"bi-clipboard",action:"copy"},{text:"Close",class:"btn-secondary",dismiss:!0}],l=new _({title:i,body:a,size:r,scrollable:!0,buttons:o,...n});return w._renderAndAwait(l,{buttons:o,onAction:async d=>{if(d!=="copy")return null;if(!navigator.clipboard)return!1;try{await navigator.clipboard.writeText(t),w._showCopySuccess(l)}catch(h){console.error("Modal.code: clipboard write failed:",h)}return!1}})}static _showCopySuccess(e){const t=e.element?.querySelector('[data-action="copy"]');if(!t)return;const s=t.innerHTML;t.innerHTML='<i class="bi bi-check me-1"></i>Copied!',t.classList.remove("btn-primary"),t.classList.add("btn-success"),t.disabled=!0,setTimeout(()=>{t.innerHTML=s,t.classList.remove("btn-success"),t.classList.add("btn-primary"),t.disabled=!1},2e3)}static async htmlPreview(e={}){const{html:t=e.content||"",title:s="HTML Preview",size:i="lg",height:r=500,...n}=e,a=new Ot({html:t,height:r}),o=[{text:"Close",class:"btn-secondary",dismiss:!0}],l=new _({title:s,body:a,size:i,scrollable:!1,buttons:o,...n});return w._renderAndAwait(l,{buttons:o})}static async updateModelImage(e={},t={}){const s=e.upload||!1,i=t.name||e.field||"image",r={title:"Upload Your Avatar",model:null,autoSave:!s,size:"sm",fields:[{type:"image",name:i,size:"lg",imageSize:{width:200,height:200},placeholder:"Upload your image",...t}],...e},n=await w.form(r);if(!s||!n||!e.model)return n;const a=n[i];if(!a||!a.startsWith("data:"))return n;const o=a.split(","),d=o[0]?.match(/:(.*?);/)?.[1]||"image/png",h=atob(o[1]);let u=h.length;const m=new Uint8Array(u);for(;u--;)m[u]=h.charCodeAt(u);const p=d.split("/")[1]||"png",f=typeof window<"u"&&window.File||globalThis.File;if(!f)throw new Error("File API is not available in this environment");const g=new f([m],`${i}.${p}`,{type:d}),b=new zt;return await b.upload({file:g,name:`${i}.${p}`,description:e.uploadDescription||`${i} upload`,showToast:!0}),e.model.save({[i]:b.id})}static loading(e){Ie.show(e)}static hideLoading(e){Ie.hide(e)}static showBusy(e){return w.loading(e)}static hideBusy(e){return w.hideLoading(e)}}const N=Object.freeze(Object.defineProperty({__proto__:null,default:w},Symbol.toStringTag,{value:"Module"}));class ye{constructor(e={}){this.config=e,this.initPluginRegistry(),this.name=e.name||"MOJO App",this.version=e.version||"1.0.0",this.debug=e.debug||!1,this.container=e.container||"#app",this.layoutType=e.layout||"portal",this.layoutConfig=e.layoutConfig||{},e.sidebar&&(this.layoutConfig.sidebarConfig=e.sidebar),e.topbar&&(this.layoutConfig.topbarConfig=e.topbar),this.layout=null,this.layoutConfig.containerId=this.container||this.containerId||"#app",this.pageContainer=e.pageContainer||"#page-container",this.basePath=e.basePath||"",this.routerMode=e.routerMode||e.router?.mode||"param",this.basePath=e.basePath||e.router?.base||"",this.defaultRoute=e.defaultRoute||"home",this.session=e.session||{},this.router=null,this.navigation=e.navigation||{},this.state={currentPage:null,previousPage:null,loading:!1},this.events=new Ft,this.rest=te,this.modal=w,e.api&&this.rest.configure(e.api);const t=(this.name||"mojo").replace(/\s+/g,"_").toLowerCase();this.theme=new Tt({storageKey:`${t}:theme`,eventBus:this.events}),this.theme.init(),this.router=new $e({mode:this.routerMode==="param"?"params":this.routerMode,basePath:this.basePath,defaultRoute:this.defaultRoute,eventEmitter:this.events}),this.events.on("route:changed",async s=>{const{pageName:i,params:r,query:n}=s;await this.showPage(i,n,r,{fromRouter:!0})}),typeof window<"u"&&(window.MOJO=window.MOJO||{},window.MOJO.router=this.router),this.setupFocusTracking(),this.pageCache=new Map,this.pageClasses=new Map,this.componentClasses=new Map,this.modelClasses=new Map,this.modelRefClasses=new Map,this.currentPage=null,this.isStarted=!1,window.matchUUID?window[window.matchUUID]=this:window.MOJO?window.MOJO.app=this:window.__app__=this}async start(){if(this.isStarted){console.warn("WebApp already started");return}try{this.setupPageContainer(),this.validateDefaultRoute(),await this.setupRouter(),this.isStarted=!0,this.router.allowPopState=!1,this.events.emit("app:ready",{app:this})}catch(e){throw console.error(`Failed to start ${this.name}:`,e),this.showError("Failed to start application"),e}}async setupRouter(){if(!this.router){console.error("Router not initialized");return}this.events.on("route:notfound",async e=>{console.warn(`Route not found: ${e.path}`),this._show404(e.path)}),this.router.start(),console.log(`Router started in ${this.routerMode} mode`)}setupPageContainer(){const e=typeof this.container=="string"?document.querySelector(this.container):this.container;e&&!e.querySelector("#page-container")&&(e.innerHTML='<div id="page-container"></div>'),this.pageContainer="#page-container"}registerPage(e,t,s={}){if(typeof e!="string"||!e)return console.error("registerPage: pageName must be a non-empty string"),this;if(typeof t!="function")return console.error("registerPage: PageClass must be a constructor function"),this;if(s.containerId||(s.containerId=this.pageContainer),this.pageClasses.set(e,{PageClass:t,constructorOptions:s}),this.router){let i=s.route||`/${e}`;i.startsWith("/")||(i=`/${i}`),s.route=i,this.router.addRoute(i,e)}return this}getPage(e){return this.pageCache.get(e)}getPagePermissions(e){if(this.pageCache.has(e))return this.pageCache.get(e).permissions;const t=this.pageClasses.get(e);if(!t)return null;const{PageClass:s,constructorOptions:i}=t;return i?i.permissions:null}getOrCreatePage(e){if(this.pageCache.has(e))return this.pageCache.get(e);const t=this.pageClasses.get(e);if(!t)return console.error(`Page not registered: ${e}`),null;const{PageClass:s,constructorOptions:i}=t;try{const r={pageName:e,...i,app:this},n=new s(r);return i.route&&(n.route=i.route),this.pageCache.set(e,n),console.log(`Created page: ${e} with route: ${n.route}`),n}catch(r){return console.error(`Failed to create page ${e}:`,r),null}}async showPage(e,t={},s={},i={}){const{fromRouter:r=!1,replace:n=!1,force:a=!1}=i;try{let o,l;typeof e=="string"?(l=e,o=this.getOrCreatePage(e)):e&&typeof e=="object"&&(o=e,l=e.pageName);const d=this.currentPage;if(!o){this._show404(l,s,t,r);return}if(this.events.emit("page:showing",{page:o,pageName:o.pageName,params:s,query:t,fromRouter:r}),!o.canEnter()){this._showDeniedPage(o,s,t,r);return}d&&d!==o&&await this._exitOldPage(d),await o.onParams(s,t),d!==o&&await o.onEnter(),o.syncUrl(),this.events.emit("page:show",{page:o,pageName:o.pageName,params:s,query:t,fromRouter:r}),await o.render(),this.currentPage=o,console.log(`✅ Showing page: ${o.pageName}`,{query:t,params:s})}catch(o){console.error("Error in showPage:",o),this.showError(`Failed to load page: ${o.message}`),e!=="error"&&await this.showPage("error",{},{error:o,originalPage:e},{fromRouter:r})}}async _show404(e,t,s,i){const r=this.getOrCreatePage("404");r&&(r.setInfo&&r.setInfo(e),await this._exitOldPage(this.currentPage),await r.render(),this.currentPage=r,this.events.emit("page:404",{page:null,pageName:e,params:t,query:s,fromRouter:i}))}async _showDeniedPage(e,t,s,i){const r=this.getOrCreatePage("denied");r.setDeniedPage&&r.setDeniedPage(e),await this._exitOldPage(this.currentPage),await r.render(),this.currentPage=r,this.events.emit("page:denied",{page:e,pageName:e.pageName,params:t,query:s,fromRouter:i})}async _exitOldPage(e){if(e)try{await e.onExit(),await e.unmount(),this.events.emit("page:hide",{page:e})}catch(t){console.error(`Error exiting page ${e.pageName}:`,t)}}async navigate(e,t={},s={}){if(!this.router){console.error("Router not initialized");return}let i=e;if(Object.keys(t).length>0){const r=new URLSearchParams(t).toString();i+=(e.includes("?")?"&":"?")+r}return await this.router.navigate(i,s)}async navigateToDefault(e={}){return await this.showPage(this.defaultRoute,{},{},e)}back(){this.router?this.router.back():console.warn("Router not initialized")}forward(){this.router?this.router.forward():console.warn("Router not initialized")}getCurrentPage(){return this.currentPage}getPageContainer(){return this.layout&&this.layout.getPageContainer?this.layout.getPageContainer():typeof this.pageContainer=="string"?document.querySelector(this.pageContainer):this.pageContainer}async showError(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Error",{size:"md",type:"error"})}catch(t){this.events.emit("notification",{message:e,type:"error"}),typeof window<"u"&&window?.console&&console.error("[WebApp] showError fallback:",t),typeof window<"u"&&alert(`Error: ${e}`)}}async showSuccess(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Success",{size:"md",type:"success"})}catch(t){this.events.emit("notification",{message:e,type:"success"}),typeof window<"u"&&window?.console&&console.warn("[WebApp] showSuccess fallback:",t),typeof window<"u"&&alert(`Success: ${e}`)}}async showInfo(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Information",{size:"md",type:"info"})}catch(t){this.events.emit("notification",{message:e,type:"info"}),typeof window<"u"&&window?.console&&console.info("[WebApp] showInfo fallback:",t),typeof window<"u"&&alert(`Info: ${e}`)}}async showWarning(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Warning",{size:"md",type:"warning"})}catch(t){this.events.emit("notification",{message:e,type:"warning"}),typeof window<"u"&&window?.console&&console.warn("[WebApp] showWarning fallback:",t),typeof window<"u"&&alert(`Warning: ${e}`)}}showNotification(e,t="info"){this.events.emit("notification",{message:e,type:t})}async showLoading(e={}){typeof e=="string"&&(e={message:e});try{(await Promise.resolve().then(()=>N)).default.showBusy(e)}catch(t){typeof window<"u"&&window?.console&&console.warn("[WebApp] showLoading fallback:",t,e),this.events.emit("notification",{message:e.message||"Loading...",type:"info"})}}async hideLoading(){try{(await Promise.resolve().then(()=>N)).default.hideBusy()}catch(e){typeof window<"u"&&window?.console&&console.warn("[WebApp] hideLoading fallback:",e)}}async showModelView(e,t={}){try{return await(await Promise.resolve().then(()=>N)).default.showModelView(e,t)}catch(s){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showModelForm failed:",s),s}}async showModelForm(e={}){try{return await(await Promise.resolve().then(()=>N)).default.modelForm(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showModelForm failed:",t),t}}async showForm(e={}){try{return await(await Promise.resolve().then(()=>N)).default.form(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showForm failed:",t),t}}async showDialog(e={}){try{return await(await Promise.resolve().then(()=>N)).default.dialog(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showDialog failed:",t),t}}async showAlert(e={}){try{return await(await Promise.resolve().then(()=>N)).default.dialog(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showDialog failed:",t),t}}async confirm(e,t="Confirm",s={}){return await(await Promise.resolve().then(()=>N)).default.confirm(e,t,s)}setTheme(e){return this.theme.set(e),this}getTheme(){return this.theme.getPreference()}getResolvedTheme(){return this.theme.getResolved()}setupFocusTracking(){if(typeof window>"u")return;this.isFocused=!document.hidden;const e=()=>{const i=this.isFocused;this.isFocused=!document.hidden,i!==this.isFocused&&(this.isFocused?this.events.emit("browser:focus"):this.events.emit("browser:blur"))},t=()=>{this.isFocused||(this.isFocused=!0,this.events.emit("browser:focus"))},s=()=>{this.isFocused&&(this.isFocused=!1,this.events.emit("browser:blur"))};document.addEventListener("visibilitychange",e),window.addEventListener("focus",t),window.addEventListener("blur",s),this._focusHandlers={visibilitychange:e,focus:t,blur:s}}setupErrorHandling(){window.addEventListener("error",e=>{console.error("Global error:",e.error),this.debug&&this.showError(`Error: ${e.error?.message||"Unknown error"}`)}),window.addEventListener("unhandledrejection",e=>{console.error("Unhandled promise rejection:",e.reason),this.debug&&this.showError(`Promise rejected: ${e.reason?.message||"Unknown error"}`)})}escapeHtml(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}getState(e){return e?this.state[e]:this.state}setState(e){const t={...this.state};Object.assign(this.state,e),this.events.emit("state:changed",{oldState:t,newState:this.state,updates:e})}registerComponent(e,t){this.componentClasses.set(e,t)}getComponent(e){return this.componentClasses.get(e)}registerModel(e,t){this.modelClasses.set(e,t)}getModel(e){return this.modelClasses.get(e)}registerModelRef(e,t){this.modelRefClasses.set(e,t)}getModelByRef(e){return this.modelRefClasses.get(e)}setupRest(){this.rest=te,te.configure(this.api)}async destroy(){console.log("Destroying WebApp..."),this.router&&this.router.stop(),this._focusHandlers&&typeof window<"u"&&(document.removeEventListener("visibilitychange",this._focusHandlers.visibilitychange),window.removeEventListener("focus",this._focusHandlers.focus),window.removeEventListener("blur",this._focusHandlers.blur));const e=Array.from(this.pageCache.values());if(await Promise.allSettled(e.map(async t=>{try{t.destroy&&await t.destroy()}catch(s){console.error("Error destroying page:",s)}})),this.layout&&this.layout.destroy)try{await this.layout.destroy()}catch(t){console.error("Error destroying layout:",t)}this.pageCache.clear(),this.pageClasses.clear(),this.componentClasses.clear(),this.modelClasses.clear(),typeof window<"u"&&window.MOJO&&delete window.MOJO.router,this.isStarted=!1,console.log(`✨ ${this.name} destroyed`)}buildPagePath(e,t,s){let i=e.route||`/${e.pageName.toLowerCase()}`;if(Object.keys(t).forEach(r=>{(typeof t[r]=="string"||typeof t[r]=="number")&&(i=i.replace(`:${r}`,t[r]))}),s&&Object.keys(s).length>0){const r=new URLSearchParams(s).toString();i+=(i.includes("?")?"&":"?")+r}return i}validateDefaultRoute(){this.pageClasses.has(this.defaultRoute)?console.log(`✅ Default route '${this.defaultRoute}' is registered`):(console.warn(`⚠️ Default route '${this.defaultRoute}' is not registered!`),console.warn(` Please register a page: app.registerPage('${this.defaultRoute}', YourPageClass);`),console.warn(" Or change default route: new WebApp({ defaultRoute: 'your-page' });"))}findFallbackPage(){const e=["404","error","denied"];for(const[t]of this.pageClasses.entries())if(!e.includes(t))return t;return null}static create(e={}){return new ye(e)}initPluginRegistry(){typeof window<"u"&&(window.MOJO||(window.MOJO={}),window.MOJO.plugins||(window.MOJO.plugins={}),window.MOJO.app=this)}static registerPlugin(e,t){typeof window<"u"&&(window.MOJO||(window.MOJO={}),window.MOJO.plugins||(window.MOJO.plugins={}),window.MOJO.plugins[e]=t,console.debug(`MOJO Plugin registered: ${e}`))}}class ue extends C{constructor(e={}){e.tagName=e.tagName||"main",e.className=e.className||"mojo-page";const t=e.pageName||"";t&&!e.id&&(e.id="page_"+t.toLowerCase().replace(/\s+/g,"_")),super(e),this.pageName=e.pageName||this.constructor.pageName||"",this.route=e.route||this.constructor.route||"",this.title=e.title||this.pageName||"",!this.id&&this.constructor.pageName&&!e.pageName&&(this.id="page_"+this.constructor.pageName.toLowerCase().replace(/\s+/g,"_")),this.pageIcon=e.icon||e.pageIcon||this.constructor.pageIcon||"bi bi-file-text",this.displayName=e.displayName||this.constructor.displayName||this.pageName||"",this.pageDescription=e.pageDescription||this.constructor.pageDescription||"",this.params={},this.query={},this.matched=!1,this.isActive=!1,this.pageOptions={title:e.title||this.pageName||"Untitled Page",description:e.description||"",requiresAuth:e.requiresAuth||!1,...e.pageOptions},this.savedState=null,console.log(`Page ${this.pageName} constructed with route: ${this.route}`)}async onParams(e={},t={}){this.params=e,this.query=t}canEnter(){if(this.options.permissions){const e=this.getApp().activeUser;if(!e||!e.hasPermission(this.options.permissions))return!1}return!(this.options.requiresGroup&&!this.getApp().activeGroup)}async onEnter(){this.isActive=!0,this._wasExited=!1,await this.onInitView(),this.savedState&&(this.restoreState(this.savedState),this.savedState=null),this.pageOptions&&this.pageOptions.title&&typeof document<"u"&&(document.title=this.pageOptions.title),this.emit("activated",{page:this.getMetadata()}),console.log(`Page ${this.pageName} entered`)}async onExit(){this.savedState=this.captureState(),this.isActive=!1,this._wasExited=!0,this._clearScheduledRefreshes(),this.emit("deactivated",{page:this.getMetadata()}),console.log(`Page ${this.pageName} exiting`)}scheduleRefresh(e,t,s={}){if(this._scheduledRefreshes||(this._scheduledRefreshes=[]),typeof e!="function"||!(t>0))return null;const i=async()=>{try{await e()}catch(a){console.warn(`[Page ${this.pageName}] scheduleRefresh handler error:`,a)}};s.immediate&&i();const r=setInterval(i,t),n={id:r,tier:s.tier||null,handler:i,intervalMs:t};return this._scheduledRefreshes.push(n),{cancel:()=>{clearInterval(r),this._scheduledRefreshes=(this._scheduledRefreshes||[]).filter(a=>a!==n)}}}async runScheduledRefreshes(e=null){const t=this._scheduledRefreshes||[],s=e?t.filter(i=>i.tier===e):t;await Promise.allSettled(s.map(i=>i.handler()))}_clearScheduledRefreshes(){if(this._scheduledRefreshes){for(const e of this._scheduledRefreshes)clearInterval(e.id);this._scheduledRefreshes=[]}}async render(e=!0,t=null){return this._wasExited&&!this.isActive?this:super.render(e,t)}async onGroupChange(e){}getMetadata(){return{name:this.pageName,displayName:this.displayName||this.pageName,icon:this.pageIcon,description:this.pageDescription,route:this.route,isActive:this.isActive}}async onActionDefault(e){console.log(`Default action '${e}' triggered on page: ${this.pageName}`)}async makeActive(){this.getApp().showPage(this)}async onActionNavigate(e,t){e.preventDefault();const s=t.dataset.page;this.getApp().showPage(s)}captureState(){return this.element?{scrollTop:this.element.scrollTop,formData:this.captureFormData(),custom:this.captureCustomState()}:null}restoreState(e){!e||!this.element||(this.element.scrollTop=e.scrollTop||0,this.restoreFormData(e.formData),e.custom&&this.restoreCustomState(e.custom))}captureFormData(){const e={};return this.element&&this.element.querySelectorAll("input, select, textarea").forEach(t=>{t.name&&(t.type==="checkbox"?e[t.name]=t.checked:t.type==="radio"?t.checked&&(e[t.name]=t.value):e[t.name]=t.value)}),e}restoreFormData(e){!e||!this.element||Object.entries(e).forEach(([t,s])=>{const i=this.element.querySelector(`[name="${t}"]`);if(i)if(i.type==="checkbox")i.checked=s;else if(i.type==="radio"){const r=this.element.querySelector(`[name="${t}"][value="${s}"]`);r&&(r.checked=!0)}else i.value=s})}captureCustomState(){return{}}restoreCustomState(e){}setMeta(e={}){if(!(typeof document>"u")){if(e.title&&(document.title=e.title,this.pageOptions.title=e.title),e.description){let t=document.querySelector('meta[name="description"]');t||(t=document.createElement("meta"),t.name="description",document.head.appendChild(t)),t.content=e.description,this.pageOptions.description=e.description}Object.entries(e).forEach(([t,s])=>{if(t!=="title"&&t!=="description"){let i=document.querySelector(`meta[name="${t}"]`);i||(i=document.createElement("meta"),i.name=t,document.head.appendChild(i)),i.content=s}})}}showError(e){if(super.showError(e),this.element){const t=document.createElement("div");t.className="alert alert-danger alert-dismissible fade show",t.innerHTML=`
219
219
  ${e}
220
220
  <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
221
221
  `,this.element.insertBefore(t,this.element.firstChild),setTimeout(()=>{t.parentNode&&t.parentNode.removeChild(t)},5e3)}}showSuccess(e){if(super.showSuccess(e),this.element){const t=document.createElement("div");t.className="alert alert-success alert-dismissible fade show",t.innerHTML=`
@@ -569,14 +569,14 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
569
569
  </div>
570
570
  </div>
571
571
  </div>
572
- `}buildFieldHTML(e){const{type:t,columns:s,class:i=""}=e;let r="";const n=Z&&typeof Z.getRenderer=="function"?Z.getRenderer(t):null;if(typeof n=="function")try{const d=n(this,e);d!=null&&(r=String(d))}catch(d){console.error("FormPlugins custom renderer error:",d)}if(!r)switch(t){case"text":r=this.renderTextField(e);break;case"email":r=this.renderEmailField(e);break;case"password":r=this.renderPasswordField(e);break;case"number":r=this.renderNumberField(e);break;case"tel":r=this.renderTelField(e);break;case"url":r=this.renderUrlField(e);break;case"search":r=this.renderSearchField(e);break;case"hex":r=this.renderHexField(e);break;case"textarea":r=this.renderTextareaField(e);break;case"htmlpreview":r=this.renderHtmlPreviewField(e);break;case"json":r=this.renderJsonField(e);break;case"select":r=this.renderSelectField(e);break;case"multiselect":r=this.renderMultiSelectField(e);break;case"checkbox":r=this.renderCheckboxField(e);break;case"toggle":case"switch":r=this.renderSwitchField(e);break;case"radio":r=this.renderRadioField(e);break;case"date":r=this.renderDateField(e);break;case"datetime":r=this.renderDateTimeField(e);break;case"time":r=this.renderTimeField(e);break;case"file":r=this.renderFileField(e);break;case"image":r=this.renderImageField(e);break;case"color":r=this.renderColorField(e);break;case"range":r=this.renderRangeField(e);break;case"hidden":r=this.renderHiddenField(e);break;case"button":r=this.renderButton(e);break;case"divider":r=this.renderDivider(e);break;case"html":r=this.renderHtmlField(e);break;case"heading":case"header":r=this.renderHeaderField(e);break;case"tag":case"tags":r=this.renderTagField(e);break;case"collection":r=this.renderCollectionField(e);break;case"collectionmultiselect":case"collection-multiselect":r=this.renderCollectionMultiSelectField(e);break;case"datepicker":r=this.renderDatePickerField(e);break;case"monthpicker":r=this.renderDatePickerField({...e,precision:"month"});break;case"yearpicker":r=this.renderDatePickerField({...e,precision:"year"});break;case"daterange":r=this.renderDateRangeField(e);break;case"monthrange":r=this.renderDateRangeField({...e,precision:"month"});break;case"yearrange":r=this.renderDateRangeField({...e,precision:"year"});break;case"timepicker":r=this.renderTimePickerField(e);break;case"datetimepicker":r=this.renderDateTimePickerField(e);break;case"checklistdropdown":r=this.renderChecklistDropdownField(e);break;case"buttongroup":r=this.renderButtonGroupField(e);break;case"combo":case"combobox":case"autocomplete":r=this.renderComboField(e);break;case"tabset":r=this.renderTabsetField(e);break;default:console.warn(`Unknown field type: ${t}`),r=this.renderTextField(e)}let a;this.isAutoSizingField(e)?a=`col ${i}`.trim():a=`col-${s} ${i}`.trim();let o="",l="";if(e.showWhen){const d=e.showWhen,h=Array.isArray(d.value)?d.value:[d.value];o=` data-show-when-field="${d.field}" data-show-when-value="${h.join(",")}"`,d.negate&&(o+=' data-show-when-negate="true"');let u=this.data[d.field];if(u==null){const g=this._findField(d.field,this.fields);g&&(u=g.value)}const m=String(u??""),p=h.map(String).includes(m);(d.negate?!p:p)||(l=' style="display:none"')}return`<div class="${a}"${o}${l}>${r}</div>`}_findField(e,t){for(const s of t){if(s.name===e)return s;if(s.fields){const i=this._findField(e,s.fields);if(i)return i}if(s.tabs){for(const i of s.tabs)if(i.fields){const r=this._findField(e,i.fields);if(r)return r}}}return null}getFieldId(e){return e?`field_${e.replace(/[.\s\[\]]/g,"_")}`:`field_${Math.random().toString(36).substr(2,9)}`}renderTextField(e){return this.renderInputField(e,"text")}renderEmailField(e){return this.renderInputField(e,"email")}renderPasswordField(e){const t=e.passwordUsage||"current",s=t==="new"||t==="new-password"?"new-password":"current-password",i={...e.attributes||{},autocomplete:e.attributes&&e.attributes.autocomplete||s};return this.renderInputField({...e,showToggle:e.showToggle!==!1,attributes:i},"password")}renderNumberField(e){const{min:t,max:s,step:i=1,...r}=e,n=[];return t!==void 0&&n.push(`min="${t}"`),s!==void 0&&n.push(`max="${s}"`),i!==void 0&&n.push(`step="${i}"`),this.renderInputField({...r,attributes:{...r.attributes,...n.reduce((a,o)=>{const[l,d]=o.split("=");return a[l]=d.replace(/"/g,""),a},{})}},"number")}renderTelField(e){return this.renderInputField(e,"tel")}renderUrlField(e){return this.renderInputField(e,"url")}renderSearchField(e){const t={...e,attributes:{"data-filter":"live-search","data-change-action":"filter-search","data-filter-debounce":e.debounce||"300",...e.attributes}};return this.renderInputField(t,"search")}renderHexField(e){const{hexType:t="color",allowPrefix:s=!0,minLength:i,maxLength:r,...n}=e;let a,o,l,d,h;switch(t){case"color":a=s?"^#?[0-9A-Fa-f]{6}$":"^[0-9A-Fa-f]{6}$",o=6,l=s?7:6,d=s?"#FF0000":"FF0000",h=h||"Enter a valid hex color (e.g., "+d+")";break;case"color-short":a=s?"^#?[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$":"^[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$",o=s?4:3,l=s?7:6,d=s?"#F00 or #FF0000":"F00 or FF0000",h=h||"Enter a valid hex color (3 or 6 digits)";break;case"string":a="^[0-9A-Fa-f]+$",o=i||1,l=r||64,d="ABCDEF123456",h=h||"Only hexadecimal characters (0-9, A-F) allowed";break;default:a=s?"^#?[0-9A-Fa-f]+$":"^[0-9A-Fa-f]+$",o=i||1,l=r||64,d=s?"#ABCDEF or ABCDEF":"ABCDEF",h=h||"Enter hexadecimal characters only"}const u={...n,pattern:a,minLength:o,maxLength:l,placeholder:n.placeholder||d,help:n.help||h,attributes:{"data-hex-type":t,"data-allow-prefix":s,style:"text-transform: uppercase;",...n.attributes}};return this.renderInputField(u,"text")}renderInputField(e,t="text"){const{name:s,label:i,value:r="",placeholder:n="",required:a=!1,disabled:o=!1,readonly:l=!1,class:d="",attributes:h={},help:u=e.helpText||e.help||""}=e,m=`${this.options.inputClass} ${d}`.trim(),p=this.errors[s],f=this.getFieldValue(s)??r,g=Object.entries(h).map(([w,x])=>`${w}="${this.escapeHtml(x)}"`).join(" "),b=this.getFieldId(s),y={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:b,name:s,type:t,fieldValue:this.escapeHtml(f),label:i?this.escapeHtml(i):null,placeholder:n?this.escapeHtml(n):null,help:u?this.escapeHtml(u):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:p?this.escapeHtml(p):null,required:a,disabled:o,readonly:l,attrs:g,showCopy:!!e.showCopy};if(t==="password"&&(e.showToggle||e.strengthMeter||e.capsLockWarning)){const w={...y,showToggle:!!e.showToggle,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,w)}if(t==="password"){const w={...y,showToggle:e.showToggle!==!1,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,w)}return D.render(this.templates.input,y)}renderTextareaField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,rows:l=3,cols:d,class:h="",attributes:u={},help:m=e.helpText||e.help||""}=e,p=`${this.options.inputClass} ${h}`.trim(),f=this.errors[t],g=this.getFieldValue(t)??i,b=Object.entries(u).map(([x,A])=>`${x}="${this.escapeHtml(A)}"`).join(" "),y=this.getFieldId(t),w={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:y,name:t,fieldValue:g,label:s?this.escapeHtml(s):null,placeholder:r?this.escapeHtml(r):null,help:m?this.escapeHtml(m):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:f?this.escapeHtml(f):null,rows:l||3,required:n,disabled:a,readonly:o,showCopy:!!e.showCopy,attrs:b};return D.render(this.templates.textarea,w)}renderHtmlPreviewField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,rows:l=5,class:d="",attributes:h={},help:u=e.helpText||e.help||""}=e,m=`${this.options.inputClass} ${d}`.trim(),p=this.errors[t],f=this.getFieldValue(t)??i,g=Object.entries(h).map(([w,x])=>`${w}="${this.escapeHtml(x)}"`).join(" "),b=this.getFieldId(t),y={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:b,name:t,fieldValue:f,label:s?this.escapeHtml(s):null,placeholder:r?this.escapeHtml(r):null,help:u?this.escapeHtml(u):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:p?this.escapeHtml(p):null,rows:l||5,required:n,disabled:a,readonly:o,attrs:g,showCopy:!!e.showCopy};return D.render(this.templates.htmlpreview,y)}renderJsonField(e){const{name:t,label:s,placeholder:i="",required:r=!1,disabled:n=!1,readonly:a=!1,rows:o=3,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=this.getFieldValue(e.name)??e.value??{};let m=u;if(typeof u=="object"&&u!==null)try{m=JSON.stringify(u,null,2)}catch{m="{}"}else typeof u!="string"&&(m=String(u));const p=`${this.options.inputClass} ${l}`.trim(),f=this.errors[t],g=this.getFieldId(t),b=Object.entries({...d,"data-field-type":"json"}).map(([w,x])=>`${w}="${this.escapeHtml(x)}"`).join(" "),y={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,fieldValue:m,label:s?this.escapeHtml(s):null,placeholder:i?this.escapeHtml(i):null,help:h?this.escapeHtml(h):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:f?this.escapeHtml(f):null,rows:o||3,required:r,disabled:n,readonly:a,attrs:b};return D.render(this.templates.textarea,y)}renderSelectField(e){const{name:t,label:s,options:i=[],value:r="",required:n=!1,disabled:a=!1,multiple:o=!1,searchable:l=!1,class:d="",attributes:h={},help:u=e.helpText||e.help||"",start:m=e.start,end:p=e.end,step:f=e.step,format:g=e.format,prefix:b=e.prefix,suffix:y=e.suffix}=e,w=`form-select ${d}`.trim(),x=this.errors[t],E=this.getFieldValue(t)??r,j=Object.entries(h).map(([I,R])=>`${I}="${this.escapeHtml(R)}"`).join(" "),M=this.getFieldId(t);let O=[...i];if(m!==void 0&&p!==void 0){const I=f!==void 0?f:1,R=this.generateSelectOptions(m,p,I,{format:g,prefix:b,suffix:y});O=[...O,...R]}let re="";Array.isArray(O)&&(re=O.map(I=>{if(typeof I=="string"){const R=I===E?"selected":"";return`<option value="${this.escapeHtml(I)}" ${R}>${this.escapeHtml(I)}</option>`}else if(I&&typeof I=="object"){const R=I.value==E?"selected":"";return`<option value="${this.escapeHtml(I.value)}" ${R}>${this.escapeHtml(I.label||I.text||I.value)}</option>`}return""}).join(""));const fe=l?`
572
+ `}buildFieldHTML(e){const{type:t,columns:s,class:i=""}=e;let r="";const n=Z&&typeof Z.getRenderer=="function"?Z.getRenderer(t):null;if(typeof n=="function")try{const d=n(this,e);d!=null&&(r=String(d))}catch(d){console.error("FormPlugins custom renderer error:",d)}if(!r)switch(t){case"text":r=this.renderTextField(e);break;case"email":r=this.renderEmailField(e);break;case"password":r=this.renderPasswordField(e);break;case"number":r=this.renderNumberField(e);break;case"tel":r=this.renderTelField(e);break;case"url":r=this.renderUrlField(e);break;case"search":r=this.renderSearchField(e);break;case"hex":r=this.renderHexField(e);break;case"textarea":r=this.renderTextareaField(e);break;case"htmlpreview":r=this.renderHtmlPreviewField(e);break;case"json":r=this.renderJsonField(e);break;case"select":r=this.renderSelectField(e);break;case"multiselect":r=this.renderMultiSelectField(e);break;case"checkbox":r=this.renderCheckboxField(e);break;case"toggle":case"switch":r=this.renderSwitchField(e);break;case"radio":r=this.renderRadioField(e);break;case"date":r=this.renderDateField(e);break;case"datetime":r=this.renderDateTimeField(e);break;case"time":r=this.renderTimeField(e);break;case"file":r=this.renderFileField(e);break;case"image":r=this.renderImageField(e);break;case"color":r=this.renderColorField(e);break;case"range":r=this.renderRangeField(e);break;case"hidden":r=this.renderHiddenField(e);break;case"button":r=this.renderButton(e);break;case"divider":r=this.renderDivider(e);break;case"html":r=this.renderHtmlField(e);break;case"heading":case"header":r=this.renderHeaderField(e);break;case"tag":case"tags":r=this.renderTagField(e);break;case"collection":r=this.renderCollectionField(e);break;case"collectionmultiselect":case"collection-multiselect":r=this.renderCollectionMultiSelectField(e);break;case"datepicker":r=this.renderDatePickerField(e);break;case"monthpicker":r=this.renderDatePickerField({...e,precision:"month"});break;case"yearpicker":r=this.renderDatePickerField({...e,precision:"year"});break;case"daterange":r=this.renderDateRangeField(e);break;case"monthrange":r=this.renderDateRangeField({...e,precision:"month"});break;case"yearrange":r=this.renderDateRangeField({...e,precision:"year"});break;case"timepicker":r=this.renderTimePickerField(e);break;case"datetimepicker":r=this.renderDateTimePickerField(e);break;case"checklistdropdown":r=this.renderChecklistDropdownField(e);break;case"buttongroup":r=this.renderButtonGroupField(e);break;case"combo":case"combobox":case"autocomplete":r=this.renderComboField(e);break;case"tabset":r=this.renderTabsetField(e);break;default:console.warn(`Unknown field type: ${t}`),r=this.renderTextField(e)}let a;this.isAutoSizingField(e)?a=`col ${i}`.trim():a=`col-${s} ${i}`.trim();let o="",l="";if(e.showWhen){const d=e.showWhen,h=Array.isArray(d.value)?d.value:[d.value];o=` data-show-when-field="${d.field}" data-show-when-value="${h.join(",")}"`,d.negate&&(o+=' data-show-when-negate="true"');let u=this.data[d.field];if(u==null){const g=this._findField(d.field,this.fields);g&&(u=g.value)}const m=String(u??""),p=h.map(String).includes(m);(d.negate?!p:p)||(l=' style="display:none"')}return`<div class="${a}"${o}${l}>${r}</div>`}_findField(e,t){for(const s of t){if(s.name===e)return s;if(s.fields){const i=this._findField(e,s.fields);if(i)return i}if(s.tabs){for(const i of s.tabs)if(i.fields){const r=this._findField(e,i.fields);if(r)return r}}}return null}getFieldId(e){return e?`field_${e.replace(/[.\s\[\]]/g,"_")}`:`field_${Math.random().toString(36).substr(2,9)}`}renderTextField(e){return this.renderInputField(e,"text")}renderEmailField(e){return this.renderInputField(e,"email")}renderPasswordField(e){const t=e.passwordUsage||"current",s=t==="new"||t==="new-password"?"new-password":"current-password",i={...e.attributes||{},autocomplete:e.attributes&&e.attributes.autocomplete||s};return this.renderInputField({...e,showToggle:e.showToggle!==!1,attributes:i},"password")}renderNumberField(e){const{min:t,max:s,step:i=1,...r}=e,n=[];return t!==void 0&&n.push(`min="${t}"`),s!==void 0&&n.push(`max="${s}"`),i!==void 0&&n.push(`step="${i}"`),this.renderInputField({...r,attributes:{...r.attributes,...n.reduce((a,o)=>{const[l,d]=o.split("=");return a[l]=d.replace(/"/g,""),a},{})}},"number")}renderTelField(e){return this.renderInputField(e,"tel")}renderUrlField(e){return this.renderInputField(e,"url")}renderSearchField(e){const t={...e,attributes:{"data-filter":"live-search","data-change-action":"filter-search","data-filter-debounce":e.debounce||"300",...e.attributes}};return this.renderInputField(t,"search")}renderHexField(e){const{hexType:t="color",allowPrefix:s=!0,minLength:i,maxLength:r,...n}=e;let a,o,l,d,h;switch(t){case"color":a=s?"^#?[0-9A-Fa-f]{6}$":"^[0-9A-Fa-f]{6}$",o=6,l=s?7:6,d=s?"#FF0000":"FF0000",h=h||"Enter a valid hex color (e.g., "+d+")";break;case"color-short":a=s?"^#?[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$":"^[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$",o=s?4:3,l=s?7:6,d=s?"#F00 or #FF0000":"F00 or FF0000",h=h||"Enter a valid hex color (3 or 6 digits)";break;case"string":a="^[0-9A-Fa-f]+$",o=i||1,l=r||64,d="ABCDEF123456",h=h||"Only hexadecimal characters (0-9, A-F) allowed";break;default:a=s?"^#?[0-9A-Fa-f]+$":"^[0-9A-Fa-f]+$",o=i||1,l=r||64,d=s?"#ABCDEF or ABCDEF":"ABCDEF",h=h||"Enter hexadecimal characters only"}const u={...n,pattern:a,minLength:o,maxLength:l,placeholder:n.placeholder||d,help:n.help||h,attributes:{"data-hex-type":t,"data-allow-prefix":s,style:"text-transform: uppercase;",...n.attributes}};return this.renderInputField(u,"text")}renderInputField(e,t="text"){const{name:s,label:i,value:r="",placeholder:n="",required:a=!1,disabled:o=!1,readonly:l=!1,class:d="",attributes:h={},help:u=e.helpText||e.help||""}=e,m=`${this.options.inputClass} ${d}`.trim(),p=this.errors[s],f=this.getFieldValue(s)??r,g=Object.entries(h).map(([v,x])=>`${v}="${this.escapeHtml(x)}"`).join(" "),b=this.getFieldId(s),y={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:b,name:s,type:t,fieldValue:this.escapeHtml(f),label:i?this.escapeHtml(i):null,placeholder:n?this.escapeHtml(n):null,help:u?this.escapeHtml(u):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:p?this.escapeHtml(p):null,required:a,disabled:o,readonly:l,attrs:g,showCopy:!!e.showCopy};if(t==="password"&&(e.showToggle||e.strengthMeter||e.capsLockWarning)){const 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(([x,A])=>`${x}="${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,x])=>`${v}="${this.escapeHtml(x)}"`).join(" "),b=this.getFieldId(t),y={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:b,name:t,fieldValue:f,label:s?this.escapeHtml(s):null,placeholder:r?this.escapeHtml(r):null,help:u?this.escapeHtml(u):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:p?this.escapeHtml(p):null,rows:l||5,required:n,disabled:a,readonly:o,attrs:g,showCopy:!!e.showCopy};return D.render(this.templates.htmlpreview,y)}renderJsonField(e){const{name:t,label:s,placeholder:i="",required:r=!1,disabled:n=!1,readonly:a=!1,rows:o=3,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=this.getFieldValue(e.name)??e.value??{};let m=u;if(typeof u=="object"&&u!==null)try{m=JSON.stringify(u,null,2)}catch{m="{}"}else typeof u!="string"&&(m=String(u));const p=`${this.options.inputClass} ${l}`.trim(),f=this.errors[t],g=this.getFieldId(t),b=Object.entries({...d,"data-field-type":"json"}).map(([v,x])=>`${v}="${this.escapeHtml(x)}"`).join(" "),y={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,fieldValue:m,label:s?this.escapeHtml(s):null,placeholder:i?this.escapeHtml(i):null,help:h?this.escapeHtml(h):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:f?this.escapeHtml(f):null,rows:o||3,required:r,disabled:n,readonly:a,attrs:b};return D.render(this.templates.textarea,y)}renderSelectField(e){const{name:t,label:s,options:i=[],value:r="",required:n=!1,disabled:a=!1,multiple:o=!1,searchable:l=!1,class:d="",attributes:h={},help:u=e.helpText||e.help||"",start:m=e.start,end:p=e.end,step:f=e.step,format:g=e.format,prefix:b=e.prefix,suffix:y=e.suffix}=e,v=`form-select ${d}`.trim(),x=this.errors[t],E=this.getFieldValue(t)??r,j=Object.entries(h).map(([I,R])=>`${I}="${this.escapeHtml(R)}"`).join(" "),M=this.getFieldId(t);let O=[...i];if(m!==void 0&&p!==void 0){const I=f!==void 0?f:1,R=this.generateSelectOptions(m,p,I,{format:g,prefix:b,suffix:y});O=[...O,...R]}let re="";Array.isArray(O)&&(re=O.map(I=>{if(typeof I=="string"){const R=I===E?"selected":"";return`<option value="${this.escapeHtml(I)}" ${R}>${this.escapeHtml(I)}</option>`}else if(I&&typeof I=="object"){const R=I.value==E?"selected":"";return`<option value="${this.escapeHtml(I.value)}" ${R}>${this.escapeHtml(I.label||I.text||I.value)}</option>`}return""}).join(""));const fe=l?`
573
573
  <input type="text"
574
574
  class="form-control form-control-sm mb-2"
575
575
  placeholder="Search options..."
576
576
  data-filter="live-search"
577
577
  data-change-action="filter-select-options"
578
578
  data-target="${M}">
579
- `:"",ge={labelClass:this.options.labelClass,inputClass:w,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:x?this.escapeHtml(x):null,searchInput:l?fe:null,optionsHTML:re,required:n,disabled:a,multiple:o,attrs:j};return D.render(this.templates.select,ge)}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`
579
+ `:"",ge={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:x?this.escapeHtml(x):null,searchInput:l?fe:null,optionsHTML:re,required:n,disabled:a,multiple:o,attrs:j};return D.render(this.templates.select,ge)}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`
580
580
  <div class="multiselect-placeholder"
581
581
  data-field-name="${t}"
582
582
  data-field-type="multiselect"
@@ -590,7 +590,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
590
590
  </select>
591
591
  <small class="form-text text-muted">This will be enhanced with MultiSelectDropdown component</small>
592
592
  </div>
593
- `}renderCheckboxField(e){const{name:t,label:s,value:i=!1,required:r=!1,disabled:n=!1,class:a="",attributes:o={},help:l=e.helpText||e.help||""}=e,d=this.errors[t],h=this.getFieldValue(t)??i,u=h===!0||h==="true"||h==="1",m=Object.entries(o).map(([g,b])=>`${g}="${this.escapeHtml(b)}"`).join(" "),p=this.getFieldId(t),f={helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:p,name:t,label:this.escapeHtml(s),help:l?this.escapeHtml(l):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:d?this.escapeHtml(d):null,value:this.escapeHtml(i),fieldClass:a,checked:u,required:r,disabled:n,attrs:m};return D.render(this.templates.checkbox,f)}renderSwitchField(e){const{name:t,label:s,value:i=!1,required:r=!1,disabled:n=!1,size:a="md",class:o="",attributes:l={},help:d=e.helpText||e.help||""}=e,h=this.errors[t],u=this.getFieldValue(t)??i,m=u===!0||u==="true"||u==="1",p=Object.entries(l).map(([y,w])=>`${y}="${this.escapeHtml(w)}"`).join(" "),f=this.getFieldId(t),g=a!=="md"?`form-switch-${a}`:"",b={helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:f,name:t,label:this.escapeHtml(s),help:d?this.escapeHtml(d):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:h?this.escapeHtml(h):null,value:this.escapeHtml(i),sizeClass:g,fieldClass:o,checked:m,required:r,disabled:n,attrs:p};return D.render(this.templates.switch,b)}renderRadioField(e){const{name:t,label:s,options:i=[],value:r="",disabled:n=!1,inline:a=!1,class:o="",attributes:l={},help:d=e.helpText||e.help||""}=e,h=this.errors[t],u=this.getFieldValue(t)??r,m=Object.entries(l).map(([f,g])=>`${f}="${this.escapeHtml(g)}"`).join(" ");let p="";return Array.isArray(i)&&(p=i.map((f,g)=>{const b=`${t}_${g}`,y=typeof f=="string"?f:f.value,w=typeof f=="string"?f:f.label||f.text||f.value,x=y===u?"checked":"";return`
593
+ `}renderCheckboxField(e){const{name:t,label:s,value:i=!1,required:r=!1,disabled:n=!1,class:a="",attributes:o={},help:l=e.helpText||e.help||""}=e,d=this.errors[t],h=this.getFieldValue(t)??i,u=h===!0||h==="true"||h==="1",m=Object.entries(o).map(([g,b])=>`${g}="${this.escapeHtml(b)}"`).join(" "),p=this.getFieldId(t),f={helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:p,name:t,label:this.escapeHtml(s),help:l?this.escapeHtml(l):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:d?this.escapeHtml(d):null,value:this.escapeHtml(i),fieldClass:a,checked:u,required:r,disabled:n,attrs:m};return D.render(this.templates.checkbox,f)}renderSwitchField(e){const{name:t,label:s,value:i=!1,required:r=!1,disabled:n=!1,size:a="md",class:o="",attributes:l={},help:d=e.helpText||e.help||""}=e,h=this.errors[t],u=this.getFieldValue(t)??i,m=u===!0||u==="true"||u==="1",p=Object.entries(l).map(([y,v])=>`${y}="${this.escapeHtml(v)}"`).join(" "),f=this.getFieldId(t),g=a!=="md"?`form-switch-${a}`:"",b={helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:f,name:t,label:this.escapeHtml(s),help:d?this.escapeHtml(d):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:h?this.escapeHtml(h):null,value:this.escapeHtml(i),sizeClass:g,fieldClass:o,checked:m,required:r,disabled:n,attrs:p};return D.render(this.templates.switch,b)}renderRadioField(e){const{name:t,label:s,options:i=[],value:r="",disabled:n=!1,inline:a=!1,class:o="",attributes:l={},help:d=e.helpText||e.help||""}=e,h=this.errors[t],u=this.getFieldValue(t)??r,m=Object.entries(l).map(([f,g])=>`${f}="${this.escapeHtml(g)}"`).join(" ");let p="";return Array.isArray(i)&&(p=i.map((f,g)=>{const b=`${t}_${g}`,y=typeof f=="string"?f:f.value,v=typeof f=="string"?f:f.label||f.text||f.value,x=y===u?"checked":"";return`
594
594
  <div class="form-check ${a?"form-check-inline":""}">
595
595
  <input
596
596
  type="radio"
@@ -604,7 +604,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
604
604
  ${m}
605
605
  >
606
606
  <label class="form-check-label" for="${b}">
607
- ${this.escapeHtml(w)}
607
+ ${this.escapeHtml(v)}
608
608
  </label>
609
609
  </div>
610
610
  `}).join("")),`
@@ -618,7 +618,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
618
618
  ${d?`<div class="${this.options.helpClass}">${this.escapeHtml(d)}</div>`:""}
619
619
  ${h?`<div class="${this.options.errorClass}">${this.escapeHtml(h)}</div>`:""}
620
620
  </div>
621
- `}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"}},w=y[d]||y.md,x=Object.entries(o).map(([M,O])=>`${M}="${this.escapeHtml(O)}"`).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:w.containerClass,width:w.width,height:w.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:x};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,w])=>`${y}="${this.escapeHtml(w)}"`).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,w])=>`${y}="${this.escapeHtml(w)}"`).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`
621
+ `}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,x=Object.entries(o).map(([M,O])=>`${M}="${this.escapeHtml(O)}"`).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:x};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`
622
622
  <button
623
623
  type="button"
624
624
  ${t?`name="${t}"`:""}
@@ -663,13 +663,13 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
663
663
  ${u?`<div class="${this.options.helpClass}">${this.escapeHtml(u)}</div>`:""}
664
664
  ${p?`<div class="${this.options.errorClass}">${this.escapeHtml(p)}</div>`:""}
665
665
  </div>
666
- `}renderCollectionField(e){const{name:t,label:s,value:i="",placeholder:r="Search...",required:n=!1,disabled:a=!1,readonly:o=!1,Collection:l,labelField:d="name",valueField:h="id",maxItems:u=10,emptyFetch:m=!1,debounceMs:p=300,requiresActiveGroup:f=!1,help:g=e.helpText||e.help||""}=e,b=this.getFieldId(t),y=this.errors[t],w=this.getFieldValue(t)??i;return`
666
+ `}renderCollectionField(e){const{name:t,label:s,value:i="",placeholder:r="Search...",required:n=!1,disabled:a=!1,readonly:o=!1,Collection:l,labelField:d="name",valueField:h="id",maxItems:u=10,emptyFetch:m=!1,debounceMs:p=300,requiresActiveGroup:f=!1,help:g=e.helpText||e.help||""}=e,b=this.getFieldId(t),y=this.errors[t],v=this.getFieldValue(t)??i;return`
667
667
  <div class="mojo-form-control">
668
668
  ${s?`<label for="${b}" class="${this.options.labelClass}">${this.escapeHtml(s)}${n?'<span class="text-danger">*</span>':""}${this.renderTooltipIcon(e)}</label>`:""}
669
669
  <div class="collection-select-placeholder"
670
670
  data-field-name="${t}"
671
671
  data-field-type="collection"
672
- data-field-config='${JSON.stringify({name:t,value:w,placeholder:r,labelField:d,valueField:h,maxItems:u,emptyFetch:m,debounceMs:p,disabled:a,readonly:o,required:n,requiresActiveGroup:f})}'>
672
+ data-field-config='${JSON.stringify({name:t,value:v,placeholder:r,labelField:d,valueField:h,maxItems:u,emptyFetch:m,debounceMs:p,disabled:a,readonly:o,required:n,requiresActiveGroup:f})}'>
673
673
  <input type="text"
674
674
  id="${b}"
675
675
  name="${t}_display"
@@ -678,48 +678,48 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
678
678
  ${a?"disabled":""}
679
679
  ${o?"readonly":""}
680
680
 
681
- <input type="hidden" name="${t}" value="${this.escapeHtml(w)}">
681
+ <input type="hidden" name="${t}" value="${this.escapeHtml(v)}">
682
682
  <small class="form-text text-muted">This will be enhanced with CollectionSelect component</small>
683
683
  </div>
684
684
  ${g?`<div class="${this.options.helpClass}">${this.escapeHtml(g)}</div>`:""}
685
685
  ${y?`<div class="${this.options.errorClass}">${this.escapeHtml(y)}</div>`:""}
686
686
  </div>
687
- `}renderCollectionMultiSelectField(e){const{name:t,label:s,value:i=[],required:r=!1,disabled:n=!1,Collection:a,collectionParams:o={},labelField:l="name",valueField:d="id",excludeIds:h=[],ignoreIds:u=[],size:m=8,maxHeight:p=null,showSelectAll:f=!0,enableSearch:g=!1,searchPlaceholder:b="Search...",searchDebounce:y=400,requiresActiveGroup:w=!1,help:x=e.helpText||e.help||""}=e;this.getFieldId(t);const A=this.errors[t],E=this.getFieldValue(t)??i;return`
687
+ `}renderCollectionMultiSelectField(e){const{name:t,label:s,value:i=[],required:r=!1,disabled:n=!1,Collection:a,collectionParams:o={},labelField:l="name",valueField:d="id",excludeIds:h=[],ignoreIds:u=[],size:m=8,maxHeight:p=null,showSelectAll:f=!0,enableSearch:g=!1,searchPlaceholder:b="Search...",searchDebounce:y=400,requiresActiveGroup:v=!1,help:x=e.helpText||e.help||""}=e;this.getFieldId(t);const A=this.errors[t],E=this.getFieldValue(t)??i;return`
688
688
  <div class="mojo-form-control">
689
689
  ${s?`<label class="${this.options.labelClass}">${this.escapeHtml(s)}${r?'<span class="text-danger">*</span>':""}${this.renderTooltipIcon(e)}</label>`:""}
690
690
  <div class="collection-multiselect-placeholder"
691
691
  data-field-name="${t}"
692
692
  data-field-type="collectionmultiselect"
693
- data-field-config='${JSON.stringify({name:t,value:E,labelField:l,valueField:d,excludeIds:h,ignoreIds:u,size:m,maxHeight:p,showSelectAll:f,enableSearch:g,searchPlaceholder:b,searchDebounce:y,disabled:n,required:r,requiresActiveGroup:w})}'>
693
+ data-field-config='${JSON.stringify({name:t,value:E,labelField:l,valueField:d,excludeIds:h,ignoreIds:u,size:m,maxHeight:p,showSelectAll:f,enableSearch:g,searchPlaceholder:b,searchDebounce:y,disabled:n,required:r,requiresActiveGroup:v})}'>
694
694
  <input type="hidden" name="${t}" value="${this.escapeHtml(JSON.stringify(E))}">
695
695
  <small class="form-text text-muted">This will be enhanced with CollectionMultiSelect component</small>
696
696
  </div>
697
697
  ${x?`<div class="${this.options.helpClass}">${this.escapeHtml(x)}</div>`:""}
698
698
  ${A?`<div class="${this.options.errorClass}">${this.escapeHtml(A)}</div>`:""}
699
699
  </div>
700
- `}renderDatePickerField(e){const{name:t,label:s,value:i="",precision:r="day",placeholder:n,required:a=!1,disabled:o=!1,readonly:l=!1,min:d=null,max:h=null,format:u=null,displayFormat:m=null,disabledDates:p=[],firstDay:f=1,lang:g="en-US",autoApply:b=!0,inline:y=!1,help:w=e.helpText||e.help||""}=e,x=this.getFieldId(t),A=this.errors[t],E=this.getFieldValue(t)??i;return`
700
+ `}renderDatePickerField(e){const{name:t,label:s,value:i="",precision:r="day",placeholder:n,required:a=!1,disabled:o=!1,readonly:l=!1,min:d=null,max:h=null,format:u=null,displayFormat:m=null,disabledDates:p=[],firstDay:f=1,lang:g="en-US",autoApply:b=!0,inline:y=!1,help:v=e.helpText||e.help||""}=e,x=this.getFieldId(t),A=this.errors[t],E=this.getFieldValue(t)??i;return`
701
701
  <div class="mojo-form-control">
702
702
  ${s?`<label for="${x}" class="${this.options.labelClass}">${this.escapeHtml(s)}${a?'<span class="text-danger">*</span>':""}${this.renderTooltipIcon(e)}</label>`:""}
703
703
  <div class="date-picker-placeholder"
704
704
  data-field-name="${t}"
705
705
  data-field-type="datepicker"
706
706
  data-field-config='${JSON.stringify({name:t,value:E,precision:r,placeholder:n,min:d,max:h,format:u,displayFormat:m,disabledDates:p,firstDay:f,lang:g,autoApply:b,inline:y,disabled:o,readonly:l,required:a})}'></div>
707
- ${w?`<div class="${this.options.helpClass}">${this.escapeHtml(w)}</div>`:""}
707
+ ${v?`<div class="${this.options.helpClass}">${this.escapeHtml(v)}</div>`:""}
708
708
  ${A?`<div class="${this.options.errorClass}">${this.escapeHtml(A)}</div>`:""}
709
709
  </div>
710
- `}renderDateRangeField(e){const{name:t,startName:s,endName:i,fieldName:r,label:n,startDate:a="",endDate:o="",precision:l="day",placeholder:d,required:h=!1,disabled:u=!1,readonly:m=!1,min:p=null,max:f=null,format:g=null,displayFormat:b=null,outputFormat:y="date",separator:w=" – ",months:x=null,presets:A=null,autoApply:E=!0,inline:j=!1,help:M=e.helpText||e.help||""}=e,O=this.getFieldId(t||s||"daterange"),re=this.errors[t],fe=s||(t?t+"_start":""),ge=i||(t?t+"_end":""),I=this.getFieldValue(fe)||a,R=this.getFieldValue(ge)||o;return`
710
+ `}renderDateRangeField(e){const{name:t,startName:s,endName:i,fieldName:r,label:n,startDate:a="",endDate:o="",precision:l="day",placeholder:d,required:h=!1,disabled:u=!1,readonly:m=!1,min:p=null,max:f=null,format:g=null,displayFormat:b=null,outputFormat:y="date",separator:v=" – ",months:x=null,presets:A=null,autoApply:E=!0,inline:j=!1,help:M=e.helpText||e.help||""}=e,O=this.getFieldId(t||s||"daterange"),re=this.errors[t],fe=s||(t?t+"_start":""),ge=i||(t?t+"_end":""),I=this.getFieldValue(fe)||a,R=this.getFieldValue(ge)||o;return`
711
711
  <div class="mojo-form-control">
712
712
  ${n?`<label for="${O}" class="${this.options.labelClass}">${this.escapeHtml(n)}${h?'<span class="text-danger">*</span>':""}${this.renderTooltipIcon(e)}</label>`:""}
713
713
  <div class="date-range-picker-placeholder"
714
714
  data-field-name="${t||s||"daterange"}"
715
715
  data-field-type="daterange"
716
- data-field-config='${JSON.stringify({name:t,startName:s,endName:i,fieldName:r,startDate:I,endDate:R,precision:l,placeholder:d,min:p,max:f,format:g,displayFormat:b,outputFormat:y,separator:w,months:x,presets:A,autoApply:E,inline:j,disabled:u,readonly:m,required:h})}'></div>
716
+ data-field-config='${JSON.stringify({name:t,startName:s,endName:i,fieldName:r,startDate:I,endDate:R,precision:l,placeholder:d,min:p,max:f,format:g,displayFormat:b,outputFormat:y,separator:v,months:x,presets:A,autoApply:E,inline:j,disabled:u,readonly:m,required:h})}'></div>
717
717
  ${M?`<div class="${this.options.helpClass}">${this.escapeHtml(M)}</div>`:""}
718
718
  ${re?`<div class="${this.options.errorClass}">${this.escapeHtml(re)}</div>`:""}
719
719
  </div>
720
- `}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,w=this.getFieldId(t),x=this.errors[t],A=this.getFieldValue(t)??i;return`
720
+ `}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),x=this.errors[t],A=this.getFieldValue(t)??i;return`
721
721
  <div class="mojo-form-control">
722
- ${s?`<label for="${w}" class="${this.options.labelClass}">${this.escapeHtml(s)}${d?'<span class="text-danger">*</span>':""}${this.renderTooltipIcon(e)}</label>`:""}
722
+ ${s?`<label for="${v}" class="${this.options.labelClass}">${this.escapeHtml(s)}${d?'<span class="text-danger">*</span>':""}${this.renderTooltipIcon(e)}</label>`:""}
723
723
  <div class="time-picker-placeholder"
724
724
  data-field-name="${t}"
725
725
  data-field-type="timepicker"
@@ -727,13 +727,13 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
727
727
  ${y?`<div class="${this.options.helpClass}">${this.escapeHtml(y)}</div>`:""}
728
728
  ${x?`<div class="${this.options.errorClass}">${this.escapeHtml(x)}</div>`:""}
729
729
  </div>
730
- `}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:w="string",autoApply:x=!1,inline:A=!1,help:E=e.helpText||e.help||""}=e,j=this.getFieldId(t),M=this.errors[t],O=this.getFieldValue(t)??i;return`
730
+ `}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:x=!1,inline:A=!1,help:E=e.helpText||e.help||""}=e,j=this.getFieldId(t),M=this.errors[t],O=this.getFieldValue(t)??i;return`
731
731
  <div class="mojo-form-control">
732
732
  ${s?`<label for="${j}" class="${this.options.labelClass}">${this.escapeHtml(s)}${h?'<span class="text-danger">*</span>':""}${this.renderTooltipIcon(e)}</label>`:""}
733
733
  <div class="datetime-picker-placeholder"
734
734
  data-field-name="${t}"
735
735
  data-field-type="datetimepicker"
736
- data-field-config='${JSON.stringify({name:t,value:O,displayFormat:r,timeFormat:n,timeStep:a,min:o,max:l,placeholder:d,disabledDates:p,firstDay:f,lang:g,timezone:b,timezones:y,outputFormat:w,autoApply:x,inline:A,disabled:u,readonly:m,required:h})}'></div>
736
+ data-field-config='${JSON.stringify({name:t,value:O,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:x,inline:A,disabled:u,readonly:m,required:h})}'></div>
737
737
  ${E?`<div class="${this.options.helpClass}">${this.escapeHtml(E)}</div>`:""}
738
738
  ${M?`<div class="${this.options.errorClass}">${this.escapeHtml(M)}</div>`:""}
739
739
  </div>
@@ -787,7 +787,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
787
787
  ${o}
788
788
  </div>
789
789
  </div>
790
- `}generateSelectOptions(e,t,s=1,i={}){const{format:r,prefix:n="",suffix:a=""}=i,o=[],l=e<=t?Math.abs(s):-Math.abs(s);for(let d=e;e<=t?d<=t:d>=t;d+=l){let h=String(d);if(typeof r=="function")h=r(d);else if(r==="padded"||r==="pad"){const u=String(Math.max(Math.abs(e),Math.abs(t))).length;h=String(d).padStart(u,"0")}else r==="ordinal"&&(h=this.formatOrdinal(d));h=`${n}${h}${a}`,o.push({value:d,label:h})}return o}formatOrdinal(e){const t=e%10,s=e%100;return t===1&&s!==11?e+"st":t===2&&s!==12?e+"nd":t===3&&s!==13?e+"rd":e+"th"}escapeHtml(e){if(e==null)return"";const t=document.createElement("div");return t.textContent=String(e),t.innerHTML}renderTooltipIcon(e){return!e||!e.tooltip?"":` <i class="bi bi-info-circle text-muted" data-bs-toggle="tooltip" title="${this.escapeHtml(e.tooltip)}" style="font-size: 0.75rem; cursor: help;"></i>`}}const Ht={enableFileDrop(c={}){if(this._fileDropConfig={acceptedTypes:c.acceptedTypes||["*/*"],maxFileSize:c.maxFileSize||10*1024*1024,dropZoneSelector:c.dropZoneSelector||null,visualFeedback:c.visualFeedback!==!1,multiple:c.multiple||!1,validateOnDrop:c.validateOnDrop!==!1,dragOverClass:c.dragOverClass||"drag-over",dragActiveClass:c.dragActiveClass||"drag-active"},this._fileDropState={isDragActive:!1,dragCounter:0},this._boundFileDropHandlers={dragEnter:this._onFileDropDragEnter.bind(this),dragOver:this._onFileDropDragOver.bind(this),dragLeave:this._onFileDropDragLeave.bind(this),drop:this._onFileDropDrop.bind(this),preventDefault:this._onFileDropPreventDefault.bind(this)},this.element)this._setupFileDropListeners();else{const t=this.onAfterRender.bind(this);this.onAfterRender=async()=>{await t(),this._setupFileDropListeners()}}const e=this.onBeforeDestroy.bind(this);this.onBeforeDestroy=async()=>{this._cleanupFileDropListeners(),await e()}},_setupFileDropListeners(){if(!this._fileDropConfig)return;const c=this._getFileDropZone();if(!c){console.warn("FileDropMixin: Drop zone not found");return}this._fileDropZone=c,c.addEventListener("dragenter",this._boundFileDropHandlers.dragEnter),c.addEventListener("dragover",this._boundFileDropHandlers.dragOver),c.addEventListener("dragleave",this._boundFileDropHandlers.dragLeave),c.addEventListener("drop",this._boundFileDropHandlers.drop),["dragenter","dragover","dragleave","drop"].forEach(e=>{document.addEventListener(e,this._boundFileDropHandlers.preventDefault)})},_cleanupFileDropListeners(){this._boundFileDropHandlers&&(this._fileDropZone&&(this._fileDropZone.removeEventListener("dragenter",this._boundFileDropHandlers.dragEnter),this._fileDropZone.removeEventListener("dragover",this._boundFileDropHandlers.dragOver),this._fileDropZone.removeEventListener("dragleave",this._boundFileDropHandlers.dragLeave),this._fileDropZone.removeEventListener("drop",this._boundFileDropHandlers.drop)),["dragenter","dragover","dragleave","drop"].forEach(c=>{document.removeEventListener(c,this._boundFileDropHandlers.preventDefault)}),this._fileDropZone=null,this._boundFileDropHandlers=null,this._fileDropConfig=null,this._fileDropState=null)},_getFileDropZone(){return this._fileDropConfig.dropZoneSelector?this.element.querySelector(this._fileDropConfig.dropZoneSelector):this.element},_onFileDropPreventDefault(c){c.preventDefault(),c.stopPropagation()},_onFileDropDragEnter(c){this._onFileDropPreventDefault(c),this._fileDropState.dragCounter++,this._fileDropState.isDragActive||(this._fileDropState.isDragActive=!0,this._applyFileDropVisualFeedback(!0))},_onFileDropDragOver(c){this._onFileDropPreventDefault(c),c.dataTransfer.dropEffect="copy"},_onFileDropDragLeave(c){this._onFileDropPreventDefault(c),this._fileDropState.dragCounter--,this._fileDropState.dragCounter<=0&&(this._fileDropState.isDragActive=!1,this._fileDropState.dragCounter=0,this._applyFileDropVisualFeedback(!1))},async _onFileDropDrop(c){this._onFileDropPreventDefault(c),this._fileDropState.isDragActive=!1,this._fileDropState.dragCounter=0,this._applyFileDropVisualFeedback(!1);const e=Array.from(c.dataTransfer.files);if(e.length===0)return;const t=this._fileDropConfig.multiple?e:[e[0]];let s={valid:!0,errors:[]};if(this._fileDropConfig.validateOnDrop&&(s=this._validateFileDropFiles(t),!s.valid)){typeof this.onFileDropError=="function"&&await this.onFileDropError(new Error(s.errors.join(", ")),c,t);return}if(typeof this.onFileDrop=="function")try{await this.onFileDrop(t,c,s)}catch(i){typeof this.onFileDropError=="function"?await this.onFileDropError(i,c,t):console.error("FileDropMixin: Error in onFileDrop callback:",i)}else console.warn("FileDropMixin: No onFileDrop method found on view")},_applyFileDropVisualFeedback(c){if(!this._fileDropConfig.visualFeedback||!this._fileDropZone)return;const{dragOverClass:e,dragActiveClass:t}=this._fileDropConfig;c?this._fileDropZone.classList.add(e,t):this._fileDropZone.classList.remove(e,t)},_validateFileDropFiles(c){const e=[],t=this._fileDropConfig;for(const s of c){if(!this._isFileDropTypeAccepted(s.type)){e.push(`File type "${s.type}" is not accepted for file "${s.name}"`);continue}s.size>t.maxFileSize&&e.push(`File "${s.name}" (${this._formatFileDropSize(s.size)}) exceeds maximum size (${this._formatFileDropSize(t.maxFileSize)})`)}return{valid:e.length===0,errors:e}},_isFileDropTypeAccepted(c){const{acceptedTypes:e}=this._fileDropConfig;return e.includes("*/*")?!0:e.some(t=>{if(t===c)return!0;if(t.endsWith("/*")){const s=t.split("/")[0];return c.startsWith(s+"/")}return!1})},_formatFileDropSize(c){if(c===0)return"0 Bytes";const e=1024,t=["Bytes","KB","MB","GB"],s=Math.floor(Math.log(c)/Math.log(e));return parseFloat((c/Math.pow(e,s)).toFixed(2))+" "+t[s]}};function Bt(c){Object.assign(c.prototype,Ht)}class Ve extends C{constructor(e={}){const{name:t,value:s="",placeholder:i="Add tags...",maxTags:r=50,allowDuplicates:n=!1,separator:a=",",trimTags:o=!0,minLength:l=1,maxLength:d=50,disabled:h=!1,readonly:u=!1,class:m="",tagClass:p="badge bg-primary",inputClass:f="form-control",...g}=e;super({tagName:"div",className:`tag-input-view ${m}`,...g}),this.name=t,this.placeholder=i,this.maxTags=r,this.allowDuplicates=n,this.separator=a,this.trimTags=o,this.minLength=l,this.maxLength=d,this.disabled=h,this.readonly=u,this.tagClass=p,this.inputClass=f,this.tags=[],this.focusedTagIndex=-1,s&&(this.tags=this.parseTagString(s))}async renderTemplate(){const e=this.renderTags(),t=this.renderHiddenInput(),s=this.renderInput();return`
790
+ `}generateSelectOptions(e,t,s=1,i={}){const{format:r,prefix:n="",suffix:a=""}=i,o=[],l=e<=t?Math.abs(s):-Math.abs(s);for(let d=e;e<=t?d<=t:d>=t;d+=l){let h=String(d);if(typeof r=="function")h=r(d);else if(r==="padded"||r==="pad"){const u=String(Math.max(Math.abs(e),Math.abs(t))).length;h=String(d).padStart(u,"0")}else r==="ordinal"&&(h=this.formatOrdinal(d));h=`${n}${h}${a}`,o.push({value:d,label:h})}return o}formatOrdinal(e){const t=e%10,s=e%100;return t===1&&s!==11?e+"st":t===2&&s!==12?e+"nd":t===3&&s!==13?e+"rd":e+"th"}escapeHtml(e){if(e==null)return"";const t=document.createElement("div");return t.textContent=String(e),t.innerHTML}renderTooltipIcon(e){return!e||!e.tooltip?"":` <i class="bi bi-info-circle text-muted" data-bs-toggle="tooltip" title="${this.escapeHtml(e.tooltip)}" style="font-size: 0.75rem; cursor: help;"></i>`}}const Ht={enableFileDrop(c={}){if(this._fileDropConfig={acceptedTypes:c.acceptedTypes||["*/*"],maxFileSize:c.maxFileSize||10*1024*1024,dropZoneSelector:c.dropZoneSelector||null,visualFeedback:c.visualFeedback!==!1,multiple:c.multiple||!1,validateOnDrop:c.validateOnDrop!==!1,dragOverClass:c.dragOverClass||"drag-over",dragActiveClass:c.dragActiveClass||"drag-active"},this._fileDropState={isDragActive:!1,dragCounter:0},this._boundFileDropHandlers={dragEnter:this._onFileDropDragEnter.bind(this),dragOver:this._onFileDropDragOver.bind(this),dragLeave:this._onFileDropDragLeave.bind(this),drop:this._onFileDropDrop.bind(this),preventDefault:this._onFileDropPreventDefault.bind(this)},this.element)this._setupFileDropListeners();else{const t=this.onAfterRender.bind(this);this.onAfterRender=async()=>{await t(),this._setupFileDropListeners()}}const e=this.onBeforeDestroy.bind(this);this.onBeforeDestroy=async()=>{this._cleanupFileDropListeners(),await e()}},_setupFileDropListeners(){if(!this._fileDropConfig)return;const c=this._getFileDropZone();if(!c){console.warn("FileDropMixin: Drop zone not found");return}this._fileDropZone=c,c.addEventListener("dragenter",this._boundFileDropHandlers.dragEnter),c.addEventListener("dragover",this._boundFileDropHandlers.dragOver),c.addEventListener("dragleave",this._boundFileDropHandlers.dragLeave),c.addEventListener("drop",this._boundFileDropHandlers.drop),["dragenter","dragover","dragleave","drop"].forEach(e=>{document.addEventListener(e,this._boundFileDropHandlers.preventDefault)})},_cleanupFileDropListeners(){this._boundFileDropHandlers&&(this._fileDropZone&&(this._fileDropZone.removeEventListener("dragenter",this._boundFileDropHandlers.dragEnter),this._fileDropZone.removeEventListener("dragover",this._boundFileDropHandlers.dragOver),this._fileDropZone.removeEventListener("dragleave",this._boundFileDropHandlers.dragLeave),this._fileDropZone.removeEventListener("drop",this._boundFileDropHandlers.drop)),["dragenter","dragover","dragleave","drop"].forEach(c=>{document.removeEventListener(c,this._boundFileDropHandlers.preventDefault)}),this._fileDropZone=null,this._boundFileDropHandlers=null,this._fileDropConfig=null,this._fileDropState=null)},_getFileDropZone(){return this._fileDropConfig.dropZoneSelector?this.element.querySelector(this._fileDropConfig.dropZoneSelector):this.element},_onFileDropPreventDefault(c){c.preventDefault(),c.stopPropagation()},_onFileDropDragEnter(c){this._onFileDropPreventDefault(c),this._fileDropState.dragCounter++,this._fileDropState.isDragActive||(this._fileDropState.isDragActive=!0,this._applyFileDropVisualFeedback(!0))},_onFileDropDragOver(c){this._onFileDropPreventDefault(c),c.dataTransfer.dropEffect="copy"},_onFileDropDragLeave(c){this._onFileDropPreventDefault(c),this._fileDropState.dragCounter--,this._fileDropState.dragCounter<=0&&(this._fileDropState.isDragActive=!1,this._fileDropState.dragCounter=0,this._applyFileDropVisualFeedback(!1))},async _onFileDropDrop(c){this._onFileDropPreventDefault(c),this._fileDropState.isDragActive=!1,this._fileDropState.dragCounter=0,this._applyFileDropVisualFeedback(!1);const e=Array.from(c.dataTransfer.files);if(e.length===0)return;const t=this._fileDropConfig.multiple?e:[e[0]];let s={valid:!0,errors:[]};if(this._fileDropConfig.validateOnDrop&&(s=this._validateFileDropFiles(t),!s.valid)){typeof this.onFileDropError=="function"&&await this.onFileDropError(new Error(s.errors.join(", ")),c,t);return}if(typeof this.onFileDrop=="function")try{await this.onFileDrop(t,c,s)}catch(i){typeof this.onFileDropError=="function"?await this.onFileDropError(i,c,t):console.error("FileDropMixin: Error in onFileDrop callback:",i)}else console.warn("FileDropMixin: No onFileDrop method found on view")},_applyFileDropVisualFeedback(c){if(!this._fileDropConfig.visualFeedback||!this._fileDropZone)return;const{dragOverClass:e,dragActiveClass:t}=this._fileDropConfig;c?this._fileDropZone.classList.add(e,t):this._fileDropZone.classList.remove(e,t)},_validateFileDropFiles(c){const e=[],t=this._fileDropConfig;for(const s of c){if(!this._isFileDropTypeAccepted(s.type)){e.push(`File type "${s.type}" is not accepted for file "${s.name}"`);continue}s.size>t.maxFileSize&&e.push(`File "${s.name}" (${this._formatFileDropSize(s.size)}) exceeds maximum size (${this._formatFileDropSize(t.maxFileSize)})`)}return{valid:e.length===0,errors:e}},_isFileDropTypeAccepted(c){const{acceptedTypes:e}=this._fileDropConfig;return e.includes("*/*")?!0:e.some(t=>{if(t===c)return!0;if(t.endsWith("/*")){const s=t.split("/")[0];return c.startsWith(s+"/")}return!1})},_formatFileDropSize(c){if(c===0)return"0 Bytes";const e=1024,t=["Bytes","KB","MB","GB"],s=Math.floor(Math.log(c)/Math.log(e));return parseFloat((c/Math.pow(e,s)).toFixed(2))+" "+t[s]}};function Bt(c){Object.assign(c.prototype,Ht)}class Pe extends C{constructor(e={}){const{name:t,value:s="",placeholder:i="Add tags...",maxTags:r=50,allowDuplicates:n=!1,separator:a=",",trimTags:o=!0,minLength:l=1,maxLength:d=50,disabled:h=!1,readonly:u=!1,class:m="",tagClass:p="badge bg-primary",inputClass:f="form-control",...g}=e;super({tagName:"div",className:`tag-input-view ${m}`,...g}),this.name=t,this.placeholder=i,this.maxTags=r,this.allowDuplicates=n,this.separator=a,this.trimTags=o,this.minLength=l,this.maxLength=d,this.disabled=h,this.readonly=u,this.tagClass=p,this.inputClass=f,this.tags=[],this.focusedTagIndex=-1,s&&(this.tags=this.parseTagString(s))}async renderTemplate(){const e=this.renderTags(),t=this.renderHiddenInput(),s=this.renderInput();return`
791
791
  <div class="tag-input-container">
792
792
  <div class="tag-input-wrapper border rounded p-2"
793
793
  data-action="focus-input"
@@ -833,7 +833,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
833
833
  value="${this.escapeHtml(this.getTagString())}"
834
834
  class="tag-input-hidden">
835
835
  `:""}async onAfterRender(){await super.onAfterRender(),this.updateTagCount()}async onActionFocusInput(e,t){this.focus()}focus(){const e=this.element.querySelector(".tag-input-field");e&&!this.disabled&&e.focus(),this.focusedTagIndex=-1}async onActionRemoveTag(e,t){e.stopPropagation();const s=parseInt(t.getAttribute("data-tag-index"));s>=0&&s<this.tags.length&&await this.removeTag(s)}async onChangeInputChange(e,t){const s=t.value,i=s.slice(-1);if(i===this.separator||i===`
836
- `){e.preventDefault();const r=s.slice(0,-1);r.trim()&&(await this.addTag(r),t.value="");return}}bindEvents(){this.__bnd_keydown||(this.__bnd_keydown=this.handleInputKeydown.bind(this)),this.element.addEventListener("keydown",this.__bnd_keydown),this.events.bind(this.element)}unbindEvents(){this.__bnd_keydown&&this.element.removeEventListener("keydown",this.__bnd_keydown),this.events.unbind()}handleInputKeydown(e){const t=e.target,s=t.value||"";switch(e.key){case"Enter":case"Tab":case",":s.trim()&&(e.preventDefault(),this.addTag(s),t.value="");break;case"Backspace":s===""&&this.tags.length>0&&(e.preventDefault(),this.focusedTagIndex>=0?(this.removeTag(this.focusedTagIndex),this.focusedTagIndex==0?this.focus():this.focusTag(this.focusedTagIndex-1)):this.removeTag(this.tags.length-1));break;case"ArrowLeft":if(s===""&&this.tags.length>0)if(e.preventDefault(),this.focusedTagIndex>=0){const i=this.focusedTagIndex-1;i>=0?this.focusTag(i):this.focus()}else this.focusTag(this.tags.length-1);break;case"ArrowRight":if(s===""&&this.tags.length>0)if(e.preventDefault(),this.focusedTagIndex>=0){const i=this.focusedTagIndex+1;i<this.tags.length?this.focusTag(i):this.focus()}else this.focusTag(0);break;case"Escape":t.value="",t.blur();break}}async addTag(e){if(this.readonly||this.disabled)return!1;const t=this.trimTags?e.trim():e;return this.isValidTag(t)?!this.allowDuplicates&&this.tags.includes(t)?(this.showTagError(`Tag "${t}" already exists`),!1):this.tags.length>=this.maxTags?(this.showTagError(`Maximum ${this.maxTags} tags allowed`),!1):(this.tags.push(t),await this.updateDisplay(),this.emit("tag:added",{tag:t,tags:this.tags}),this.emit("change",{value:this.getTagString(),tags:this.tags}),!0):!1}async removeTag(e){if(this.readonly||this.disabled)return!1;if(e>=0&&e<this.tags.length){const t=this.tags[e];return this.tags.splice(e,1),await this.updateDisplay(),this.emit("tag:removed",{tag:t,tags:this.tags}),this.emit("change",{value:this.getTagString(),tags:this.tags}),!0}return!1}async removeTagByValue(e){const t=this.tags.indexOf(e);return t>=0?await this.removeTag(t):!1}async clearTags(){if(this.readonly||this.disabled)return!1;const e=[...this.tags];return this.tags=[],await this.updateDisplay(),this.emit("tags:cleared",{oldTags:e}),this.emit("change",{value:"",tags:[]}),!0}async setTags(e){let t=[];Array.isArray(e)?t=e:typeof e=="string"&&(t=this.parseTagString(e)),t=t.filter(s=>this.isValidTag(s)).slice(0,this.maxTags),this.allowDuplicates||(t=[...new Set(t)]),this.tags=t,await this.updateDisplay(),this.emit("tags:set",{tags:this.tags}),this.emit("change",{value:this.getTagString(),tags:this.tags})}isValidTag(e){return!(typeof e!="string"||e.length<this.minLength||e.length>this.maxLength||e.trim()==="")}parseTagString(e){return e?e.split(this.separator).map(t=>this.trimTags?t.trim():t).filter(t=>t.length>0):[]}getTagString(){return this.tags.join(this.separator)}getTags(){return[...this.tags]}focusTag(e){const t=this.element.querySelectorAll(".tag-item");t[e]&&(this.focusedTagIndex=e,console.log(`Focused tag index: ${e}`),t[e].focus())}async updateDisplay(){const e=this.element.querySelector(".tags-container");e&&(e.innerHTML=this.renderTags());const t=this.element.querySelector(".tag-input-hidden");t&&(t.value=this.getTagString()),this.updateTagCount()}updateTagCount(){const e=this.element.querySelector(".tag-count");e&&(e.textContent=this.tags.length)}showTagError(e){let t=this.element.querySelector(".tag-error");if(!t){t=document.createElement("div"),t.className="tag-error small text-danger mt-1";const s=this.element.querySelector(".tag-input-feedback");s&&s.parentNode.insertBefore(t,s.nextSibling)}t.textContent=e,setTimeout(()=>{t.parentNode&&t.remove()},3e3)}setEnabled(e){this.disabled=!e;const t=this.element.querySelector(".tag-input-field");t&&(t.disabled=this.disabled);const s=this.element.querySelector(".tag-input-wrapper");s&&s.classList.toggle("disabled",this.disabled)}setReadonly(e){this.readonly=e;const t=this.element.querySelector(".tag-input-field");t&&(t.style.display=e?"none":""),this.element.querySelectorAll(".tag-remove").forEach(i=>{i.style.display=e?"none":""})}escapeHtml(e){if(e==null)return"";const t=document.createElement("div");return t.textContent=String(e),t.innerHTML}getFormValue(){return this.getTagString()}async setFormValue(e){await this.setTags(e)}static create(e={}){return new Ve(e)}}class Ut extends C{constructor(e={}){super({tagName:"div",className:"collection-dropdown-view dropdown-menu show w-100 position-absolute",style:"max-height: 250px; overflow-y: auto; z-index: 1000;",template:`
836
+ `){e.preventDefault();const r=s.slice(0,-1);r.trim()&&(await this.addTag(r),t.value="");return}}bindEvents(){this.__bnd_keydown||(this.__bnd_keydown=this.handleInputKeydown.bind(this)),this.element.addEventListener("keydown",this.__bnd_keydown),this.events.bind(this.element)}unbindEvents(){this.__bnd_keydown&&this.element.removeEventListener("keydown",this.__bnd_keydown),this.events.unbind()}handleInputKeydown(e){const t=e.target,s=t.value||"";switch(e.key){case"Enter":case"Tab":case",":s.trim()&&(e.preventDefault(),this.addTag(s),t.value="");break;case"Backspace":s===""&&this.tags.length>0&&(e.preventDefault(),this.focusedTagIndex>=0?(this.removeTag(this.focusedTagIndex),this.focusedTagIndex==0?this.focus():this.focusTag(this.focusedTagIndex-1)):this.removeTag(this.tags.length-1));break;case"ArrowLeft":if(s===""&&this.tags.length>0)if(e.preventDefault(),this.focusedTagIndex>=0){const i=this.focusedTagIndex-1;i>=0?this.focusTag(i):this.focus()}else this.focusTag(this.tags.length-1);break;case"ArrowRight":if(s===""&&this.tags.length>0)if(e.preventDefault(),this.focusedTagIndex>=0){const i=this.focusedTagIndex+1;i<this.tags.length?this.focusTag(i):this.focus()}else this.focusTag(0);break;case"Escape":t.value="",t.blur();break}}async addTag(e){if(this.readonly||this.disabled)return!1;const t=this.trimTags?e.trim():e;return this.isValidTag(t)?!this.allowDuplicates&&this.tags.includes(t)?(this.showTagError(`Tag "${t}" already exists`),!1):this.tags.length>=this.maxTags?(this.showTagError(`Maximum ${this.maxTags} tags allowed`),!1):(this.tags.push(t),await this.updateDisplay(),this.emit("tag:added",{tag:t,tags:this.tags}),this.emit("change",{value:this.getTagString(),tags:this.tags}),!0):!1}async removeTag(e){if(this.readonly||this.disabled)return!1;if(e>=0&&e<this.tags.length){const t=this.tags[e];return this.tags.splice(e,1),await this.updateDisplay(),this.emit("tag:removed",{tag:t,tags:this.tags}),this.emit("change",{value:this.getTagString(),tags:this.tags}),!0}return!1}async removeTagByValue(e){const t=this.tags.indexOf(e);return t>=0?await this.removeTag(t):!1}async clearTags(){if(this.readonly||this.disabled)return!1;const e=[...this.tags];return this.tags=[],await this.updateDisplay(),this.emit("tags:cleared",{oldTags:e}),this.emit("change",{value:"",tags:[]}),!0}async setTags(e){let t=[];Array.isArray(e)?t=e:typeof e=="string"&&(t=this.parseTagString(e)),t=t.filter(s=>this.isValidTag(s)).slice(0,this.maxTags),this.allowDuplicates||(t=[...new Set(t)]),this.tags=t,await this.updateDisplay(),this.emit("tags:set",{tags:this.tags}),this.emit("change",{value:this.getTagString(),tags:this.tags})}isValidTag(e){return!(typeof e!="string"||e.length<this.minLength||e.length>this.maxLength||e.trim()==="")}parseTagString(e){return e?e.split(this.separator).map(t=>this.trimTags?t.trim():t).filter(t=>t.length>0):[]}getTagString(){return this.tags.join(this.separator)}getTags(){return[...this.tags]}focusTag(e){const t=this.element.querySelectorAll(".tag-item");t[e]&&(this.focusedTagIndex=e,console.log(`Focused tag index: ${e}`),t[e].focus())}async updateDisplay(){const e=this.element.querySelector(".tags-container");e&&(e.innerHTML=this.renderTags());const t=this.element.querySelector(".tag-input-hidden");t&&(t.value=this.getTagString()),this.updateTagCount()}updateTagCount(){const e=this.element.querySelector(".tag-count");e&&(e.textContent=this.tags.length)}showTagError(e){let t=this.element.querySelector(".tag-error");if(!t){t=document.createElement("div"),t.className="tag-error small text-danger mt-1";const s=this.element.querySelector(".tag-input-feedback");s&&s.parentNode.insertBefore(t,s.nextSibling)}t.textContent=e,setTimeout(()=>{t.parentNode&&t.remove()},3e3)}setEnabled(e){this.disabled=!e;const t=this.element.querySelector(".tag-input-field");t&&(t.disabled=this.disabled);const s=this.element.querySelector(".tag-input-wrapper");s&&s.classList.toggle("disabled",this.disabled)}setReadonly(e){this.readonly=e;const t=this.element.querySelector(".tag-input-field");t&&(t.style.display=e?"none":""),this.element.querySelectorAll(".tag-remove").forEach(i=>{i.style.display=e?"none":""})}escapeHtml(e){if(e==null)return"";const t=document.createElement("div");return t.textContent=String(e),t.innerHTML}getFormValue(){return this.getTagString()}async setFormValue(e){await this.setTags(e)}static create(e={}){return new Pe(e)}}class Ut extends C{constructor(e={}){super({tagName:"div",className:"collection-dropdown-view dropdown-menu show w-100 position-absolute",style:"max-height: 250px; overflow-y: auto; z-index: 1000;",template:`
837
837
  {{#data.loading}}
838
838
  <div class="dropdown-item text-center">
839
839
  <div class="spinner-border spinner-border-sm" role="status">
@@ -1024,7 +1024,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
1024
1024
  <div class="invalid-feedback d-block">{{error}}</div>
1025
1025
  {{/error}}
1026
1026
  </div>
1027
- `,...e}),this.name=e.name||"multiselect",this.label=e.label||"",this.help=e.help||"",this.error=e.error||"",this.required=e.required||!1,this.disabled=e.disabled||!1,this.placeholder=e.placeholder||e.placeHolder||"Select...",this.maxHeight=e.maxHeight||300,this.showSelectedLabels=e.showSelectedLabels!==!1,this.maxLabelsToShow=e.maxLabelsToShow||3,this.options=e.options||[],this.selectedValues=Array.isArray(e.value)?e.value:[],this.buttonText=this.computeButtonText(),this.listView=null}computeButtonText(){const e=this.selectedValues.length;return e===0?this.placeholder||"Select...":this.showSelectedLabels&&e<=this.maxLabelsToShow?this.selectedValues.map(s=>{const i=this.options.find(r=>(typeof r=="string"?r:r.value)===s);return typeof i=="string"?i:i?.label||i?.value||s}).join(", "):`${e} selected`}async onAfterRender(){await super.onAfterRender(),this.createListView()}createListView(){const e=this.element?.querySelector('[data-container="items"]');if(!e)return;const t=this.options.map((s,i)=>{const r=typeof s=="string"?s:s.value,n=typeof s=="string"?s:s.label||s.text||s.value,a=typeof s=="object"?s.disabled:!1;return{id:`${this.name}_${i}`,value:r,label:n,index:i,selected:this.selectedValues.includes(r),disabled:a}});this.listView=new Zt({items:t,maxHeight:this.maxHeight}),this.listView.on("toggle",s=>{this.handleToggle(s)}),this.listView.on("close-dropdown",()=>{this.closeDropdown()}),this.listView.render(!0,e)}closeDropdown(){const e=this.element?.querySelector(".dropdown-toggle");if(e&&window.bootstrap?.Dropdown){const t=window.bootstrap.Dropdown.getInstance(e);t&&t.hide()}}handleToggle(e){const{value:t,selected:s}=e;s?this.selectedValues.includes(t)||this.selectedValues.push(t):this.selectedValues=this.selectedValues.filter(i=>i!==t),this.updateButtonText(),this.emit("change",{value:this.selectedValues,name:this.name})}updateButtonText(){const e=this.element?.querySelector(".multiselect-button-text");if(!e)return;const t=this.selectedValues.length;this.buttonText=this.computeButtonText(),e.textContent=this.buttonText,t===0?e.classList.add("text-muted"):e.classList.remove("text-muted")}getValue(){return this.selectedValues}setValue(e){this.selectedValues=Array.isArray(e)?e:e?[e]:[],this.listView&&this.listView.setValue(this.selectedValues),this.updateButtonText()}setOptions(e){if(this.options=e,this.listView){const t=this.options.map((s,i)=>{const r=typeof s=="string"?s:s.value,n=typeof s=="string"?s:s.label||s.text||s.value,a=typeof s=="object"?s.disabled:!1;return{id:`${this.name}_${i}`,value:r,label:n,index:i,selected:this.selectedValues.includes(r),disabled:a}});this.listView.updateItems(t)}}clear(){this.setValue([])}getFormValue(){return this.getValue()}setFormValue(e){this.setValue(e)}async onBeforeDestroy(){await super.onBeforeDestroy(),this.listView&&this.listView.destroy()}}const Ne=["January","February","March","April","May","June","July","August","September","October","November","December"],Oe=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function at(c){if(c==null||c==="")return null;const e=parseInt(String(c).slice(0,4),10);return Number.isFinite(e)?{y:e}:null}function we(c){if(c==null||c==="")return null;const e=String(c).split("-"),t=parseInt(e[0],10),s=parseInt(e[1],10);return!Number.isFinite(t)||!Number.isFinite(s)||s<1||s>12?null:{y:t,m:s}}function z(c){if(c==null||c==="")return null;if(c instanceof Date&&!isNaN(c.getTime()))return{y:c.getFullYear(),m:c.getMonth()+1,d:c.getDate()};const e=String(c).split("-"),t=parseInt(e[0],10),s=parseInt(e[1],10),i=parseInt(e[2],10);return!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(i)||s<1||s>12||i<1||i>31?null:{y:t,m:s,d:i}}function ot(c){const e=typeof c=="object"?c:at(c);return e?String(e.y):""}function je(c){const e=typeof c=="object"?c:we(c);return e?`${e.y}-${K(e.m)}`:""}function H(c){const e=typeof c=="object"?c:z(c);return e?`${e.y}-${K(e.m)}-${K(e.d)}`:""}function B(c,e){return e==="year"?ot(c):e==="month"?je(c):H(c)}function P(c,e){return e==="year"?at(c):e==="month"?we(c):z(c)}const Qt=/YYYY|YY|MMMM|MMM|MM|M|DD|D/g;function ce(c,e){if(!c)return"";const t=c.y,s=c.m,i=c.d;return String(e).replace(Qt,r=>{switch(r){case"YYYY":return String(t);case"YY":return String(t).slice(-2);case"MMMM":return s?Ne[s-1]:"";case"MMM":return s?Oe[s-1]:"";case"MM":return s?K(s):"";case"M":return s?String(s):"";case"DD":return i?K(i):"";case"D":return i?String(i):"";default:return r}})}function lt(c,e){return new Date(c,e,0).getDate()}function Xt(c,e,t,s=1){return((new Date(c,e-1,t).getDay()-s)%7+7)%7}function ie(c,e){if(!c)return null;let t=c.y,s=c.m+e;for(;s>12;)s-=12,t+=1;for(;s<1;)s+=12,t-=1;if(c.d==null)return{y:t,m:s};const i=lt(t,s);return{y:t,m:s,d:Math.min(c.d,i)}}function ct(c,e){return!c||!e?0:c.y!==e.y?c.y<e.y?-1:1:(c.m||0)!==(e.m||0)?(c.m||0)<(e.m||0)?-1:1:(c.d||0)!==(e.d||0)?(c.d||0)<(e.d||0)?-1:1:0}function dt(c,e){return!c||!e?0:c.y!==e.y?c.y<e.y?-1:1:(c.m||0)!==(e.m||0)?(c.m||0)<(e.m||0)?-1:1:0}function es(c,e){return!c||!e||c.y===e.y?0:c.y<e.y?-1:1}function U(c,e,t){return t==="year"?es(c,e):t==="month"?dt(c,e):ct(c,e)}function W(c){if(c==null||c==="")return null;if(typeof c=="object"&&c!==null){const d=parseInt(c.hours??c.h,10),h=parseInt(c.minutes??c.m,10);return!Number.isFinite(d)||!Number.isFinite(h)||d<0||d>23||h<0||h>59?null:{hours:d,minutes:h}}const e=String(c).trim(),t=e.indexOf(" "),s=t>-1?e.slice(0,t):e,r=(t>-1?e.slice(t+1).trim():"").match(/^(am|pm)$/i)||s.match(/(am|pm)$/i),a=s.replace(/(am|pm)$/i,"").trim().split(":");if(a.length<2)return null;let o=parseInt(a[0],10);const l=parseInt(a[1],10);if(!Number.isFinite(o)||!Number.isFinite(l)||l<0||l>59)return null;if(r){const d=r[1].toLowerCase()==="pm";if(o<1||o>12)return null;o===12?o=d?12:0:d&&(o+=12)}return o<0||o>23?null:{hours:o,minutes:l}}function G(c,e="24h"){if(!c)return"";const t=c.hours,s=c.minutes;if(!Number.isFinite(t)||!Number.isFinite(s))return"";if(e==="12h"){const i=t>=12?"PM":"AM";let r=t%12;return r===0&&(r=12),`${r}:${K(s)} ${i}`}return`${K(t)}:${K(s)}`}function ht(c,e){return!c||!e?0:c.hours!==e.hours?c.hours<e.hours?-1:1:c.minutes!==e.minutes?c.minutes<e.minutes?-1:1:0}function ts(c,e){if(!c)return null;let t=c.hours*60+c.minutes+e;return t=(t%1440+1440)%1440,{hours:Math.floor(t/60),minutes:t%60}}function ut(c,e){if(!c)return null;try{const t=e instanceof Date?e:new Date,r=new Intl.DateTimeFormat("en-US",{timeZone:c,timeZoneName:"shortOffset"}).formatToParts(t).find(h=>h.type==="timeZoneName");if(!r)return null;let n=r.value;if(n==="GMT"||n==="UTC")return"+00:00";n=n.replace(/^(GMT|UTC)/,"");const a=n.match(/^([+-])(\d{1,2})(?::(\d{2}))?$/);if(!a)return null;const o=a[1],l=a[2].padStart(2,"0"),d=a[3]||"00";return`${o}${l}:${d}`}catch{return null}}function mt(c){if(c==null||c==="")return null;if(typeof c=="object"&&!Array.isArray(c)&&!(c instanceof Date)){const h=c.date?z(c.date):null,u=c.time?W(c.time):null;return h?{date:h,time:u||{hours:0,minutes:0},timezone:c.timezone||null}:null}let e=String(c).trim();const t=e.match(/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})(?::\d{2}(?:\.\d+)?)?(Z|[+-]\d{2}:?\d{2})?$/);if(t){const[,h,u,m,p,f,g]=t;let b=null;return g&&(g==="Z"?b="+00:00":/^[+-]\d{4}$/.test(g)?b=`${g.slice(0,3)}:${g.slice(3)}`:b=g),{date:{y:+h,m:+u,d:+m},time:{hours:+p,minutes:+f},timezone:b}}let s,i;if(e.length>=11&&e.charAt(10)==="T")s=e.slice(0,10),i=e.slice(11);else{const h=e.indexOf(" ");if(h===-1){const u=z(e);return u?{date:u,time:{hours:0,minutes:0},timezone:null}:null}s=e.slice(0,h),i=e.slice(h+1)}const r=z(s);if(!r)return null;const n=i.trim();let a=null,o=n;const l=n.match(/\s+([A-Za-z][A-Za-z_+\-]*\/[A-Za-z][A-Za-z_+\-]*|UTC|GMT)$/);l&&(a=l[1],o=n.slice(0,l.index).trim());const d=W(o);return d?{date:r,time:d,timezone:a}:null}function T(){const c=new Date;return{y:c.getFullYear(),m:c.getMonth()+1,d:c.getDate()}}let ve=null,Re=null,qe=null;function pt(c="en-US",e="short"){if((!c||c==="en-US"||c==="en")&&e==="short")return Oe.slice();if((!c||c==="en-US"||c==="en")&&e==="long")return Ne.slice();if(typeof Intl>"u"||!Intl.DateTimeFormat)return e==="long"?Ne.slice():Oe.slice();if(ve===c+"/"+e&&Re)return Re.slice();const t=new Intl.DateTimeFormat(c,{month:e}),s=[];for(let i=0;i<12;i++)s.push(t.format(new Date(2024,i,15)));return ve=c+"/"+e,Re=s,s.slice()}function ss(c="en-US",e=1,t="short"){if(typeof Intl>"u"||!Intl.DateTimeFormat)return ft(["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],e);const s=c+"/"+e+"/"+t;if(ve===s&&qe)return qe.slice();const i=new Intl.DateTimeFormat(c,{weekday:t}),r=[];for(let a=0;a<7;a++)r.push(i.format(new Date(2024,0,7+a)));const n=ft(r,e);return ve=s,qe=n,n.slice()}function K(c){return c<10?"0"+c:String(c)}function ft(c,e){const t=(e%c.length+c.length)%c.length;return c.slice(t).concat(c.slice(0,t))}class ze extends C{constructor(e={}){const{precision:t="day",mode:s="single",months:i=1,value:r=null,startValue:n=null,endValue:a=null,min:o=null,max:l=null,disabledDates:d=[],firstDay:h=1,locale:u="en-US",excludeDisabledFromRange:m=!1,year:p=null,month:f=null,class:g="",...b}=e;super({tagName:"div",className:`mojo-calendar mojo-calendar-${t} ${g}`.trim(),...b}),this.precision=t,this.mode=s,this.months=Math.max(1,Math.min(2,i|0)),this.firstDay=h,this.locale=u,this.excludeDisabledFromRange=m,this.min=P(o,t)||(o?z(o):null),this.max=P(l,t)||(l?z(l):null),this.disabledDates=(d||[]).map(x=>H(z(x)||null)).filter(Boolean),s==="single"?this.selected=P(r,t):(this.start=P(n,t),this.end=P(a,t),this._anchor=null),this._hover=null,this.view=t;const y=T(),w=(s==="single"?this.selected:this.start||this.end)||y;this.pageY=p!=null?Number(p):w.y??y.y,this.pageM=f!=null?Number(f):w.m??y.m,this._onCellMouseEnter=this._onCellMouseEnter.bind(this),this._onCellMouseLeave=this._onCellMouseLeave.bind(this)}setMin(e){this.min=P(e,this.precision),this._rerender()}setMax(e){this.max=P(e,this.precision),this._rerender()}setValue(e){this.selected=P(e,this.precision),this.selected&&(this.pageY=this.selected.y,this.pageM=this.selected.m||this.pageM),this._rerender()}setRange(e,t){this.start=P(e,this.precision),this.end=P(t,this.precision),this._anchor=null,this._rerender()}getValue(){return this.selected?B(this.selected,this.precision):""}getRange(){return{start:this.start?B(this.start,this.precision):"",end:this.end?B(this.end,this.precision):""}}async renderTemplate(){return""}async onAfterRender(){this._eventsWired||(this._wireEvents(this.element),this._eventsWired=!0),this._renderInto(this.element)}_rerender(){this.element&&this._renderInto(this.element)}_renderInto(e){e.innerHTML="";const t=document.createElement("div");if(t.className=this.months>1&&this.view==="day"?"mojo-calendar-multi":"mojo-calendar-single",this.view==="day"){const s=this.months;for(let i=0;i<s;i++){let r=this.pageY,n=this.pageM+i;for(;n>12;)n-=12,r+=1;t.appendChild(this._buildDayPane(r,n,i===0,i===s-1))}}else this.view==="month"?t.appendChild(this._buildMonthPane(this.pageY)):this.view==="year"&&t.appendChild(this._buildYearPane(this._decadeStart(this.pageY)));e.appendChild(t)}_decadeStart(e){return Math.floor(e/10)*10}_buildDayPane(e,t,s,i){const r=document.createElement("div");return r.className="mojo-calendar-pane",r.appendChild(this._buildHead(this._dayHeadLabel(e,t),"day",s,i,e,t)),r.appendChild(this._buildWeekdayHeader()),r.appendChild(this._buildDayGrid(e,t)),r}_dayHeadLabel(e,t){return{kind:"day",year:e,month:t}}_buildWeekdayHeader(){const e=document.createElement("div");return e.className="mojo-calendar-grid mojo-calendar-grid-day",ss(this.locale,this.firstDay,"short").forEach(t=>{const s=document.createElement("div");s.className="mojo-calendar-weekday",s.textContent=t,e.appendChild(s)}),e}_buildDayGrid(e,t){const s=document.createElement("div");s.className="mojo-calendar-grid mojo-calendar-grid-day";const i=Xt(e,t,1,this.firstDay),r=lt(e,t),n=T();for(let a=0;a<i;a++){const o=document.createElement("div");o.className="mojo-calendar-cell mojo-calendar-cell-blank",s.appendChild(o)}for(let a=1;a<=r;a++){const o={y:e,m:t,d:a},l=document.createElement("button");l.type="button",l.className="mojo-calendar-cell",l.dataset.ymd=H(o),o.y===n.y&&o.m===n.m&&o.d===n.d&&l.classList.add("mojo-calendar-cell-today"),this._isDisabledAt(o,"day")&&(l.classList.add("mojo-calendar-cell-disabled"),l.disabled=!0),this.mode==="range"?this._applyRangeClasses(l,o,"day"):this.selected&&ct(o,this.selected)===0&&l.classList.add("mojo-calendar-cell-selected");const d=document.createElement("span");d.className="mojo-calendar-cell-inner",d.textContent=String(a),l.appendChild(d),s.appendChild(l)}return s}_buildMonthPane(e){const t=document.createElement("div");return t.className="mojo-calendar-pane",t.appendChild(this._buildHead(String(e),"month",!0,!0,e,1)),t.appendChild(this._buildMonthGrid(e)),t}_buildMonthGrid(e){const t=document.createElement("div");t.className="mojo-calendar-grid mojo-calendar-grid-month";const s=pt(this.locale,"short");for(let i=1;i<=12;i++){const r={y:e,m:i},n=document.createElement("button");n.type="button",n.className="mojo-calendar-cell",n.dataset.ym=je(r),this._isDisabledAt(r,"month")&&(n.classList.add("mojo-calendar-cell-disabled"),n.disabled=!0),this.precision==="month"&&this.mode==="range"?this._applyRangeClasses(n,r,"month"):this.precision==="month"&&this.mode==="single"&&this.selected&&dt(r,this.selected)===0&&n.classList.add("mojo-calendar-cell-selected");const a=document.createElement("span");a.className="mojo-calendar-cell-inner",a.textContent=s[i-1],n.appendChild(a),t.appendChild(n)}return t}_buildYearPane(e){const t=document.createElement("div");return t.className="mojo-calendar-pane",t.appendChild(this._buildHead(`${e} – ${e+11}`,"year",!0,!0,e,1)),t.appendChild(this._buildYearGrid(e)),t}_buildYearGrid(e){const t=document.createElement("div");t.className="mojo-calendar-grid mojo-calendar-grid-year";for(let s=0;s<12;s++){const i=e+s,r={y:i},n=document.createElement("button");n.type="button",n.className="mojo-calendar-cell",n.dataset.year=String(i),this._isDisabledAt(r,"year")&&(n.classList.add("mojo-calendar-cell-disabled"),n.disabled=!0),this.precision==="year"&&this.mode==="range"?this._applyRangeClasses(n,r,"year"):this.precision==="year"&&this.mode==="single"&&this.selected&&this.selected.y===i&&n.classList.add("mojo-calendar-cell-selected");const a=document.createElement("span");a.className="mojo-calendar-cell-inner",a.textContent=String(i),n.appendChild(a),t.appendChild(n)}return t}_applyRangeClasses(e,t,s){let i=this.start,r=this.end;if(this._anchor){const o=this._hover||this._anchor,l=U(this._anchor,o,s);i=l<=0?this._anchor:o,r=l<=0?o:this._anchor}if(!i||!r){this._anchor&&U(t,this._anchor,s)===0&&e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-solo");return}const n=U(t,i,s),a=U(t,r,s);n>0&&a<0&&e.classList.add(this._anchor?"mojo-calendar-cell-in-preview":"mojo-calendar-cell-in-range"),n===0&&(e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-start"),U(i,r,s)===0?e.classList.add("mojo-calendar-cell-anchor-solo"):e.classList.add(this._anchor?"mojo-calendar-cell-in-preview":"mojo-calendar-cell-in-range")),a===0&&U(i,r,s)!==0&&(e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-end"),e.classList.add(this._anchor?"mojo-calendar-cell-in-preview":"mojo-calendar-cell-in-range"))}_buildHead(e,t,s,i){const r=document.createElement("div");r.className="mojo-calendar-head";const n=document.createElement("button");if(n.type="button",n.className="mojo-calendar-head-label",n.dataset.level=t,n.dataset.action="zoom-out",typeof e=="string")n.textContent=e;else if(e&&e.kind==="day"){const o=pt(this.locale,"long");n.appendChild(document.createTextNode(`${o[e.month-1]} `));const l=document.createElement("span");l.className="mojo-calendar-year",l.textContent=String(e.year),n.appendChild(l)}r.appendChild(n);const a=document.createElement("div");return a.className="mojo-calendar-nav",s&&a.appendChild(this._navBtn("prev")),i&&a.appendChild(this._navBtn("next")),r.appendChild(a),r}_navBtn(e){const t=document.createElement("button");return t.type="button",t.className="mojo-calendar-nav-btn",t.dataset.action=`nav-${e}`,t.setAttribute("aria-label",e==="prev"?"Previous":"Next"),t.innerHTML=e==="prev"?"&#x2039;":"&#x203A;",t}_wireEvents(e){e.addEventListener("click",t=>this._onClick(t)),e.addEventListener("mouseover",this._onCellMouseEnter),e.addEventListener("mouseleave",this._onCellMouseLeave),e.addEventListener("keydown",t=>this._onKeyDown(t))}_onClick(e){const t=e.target.closest("[data-action], .mojo-calendar-cell");if(!t||t.classList.contains("mojo-calendar-cell-blank")||t.disabled)return;const s=t.dataset.action;if(s==="nav-prev")return this._navigate(-1);if(s==="nav-next")return this._navigate(1);if(s==="zoom-out")return this._zoomOut(t.dataset.level);t.classList.contains("mojo-calendar-cell")&&this._onCellClick(t)}_onCellClick(e){if(this.view==="year"){const t=parseInt(e.dataset.year,10);if(!Number.isFinite(t))return;if(this.precision==="year")return this._commitValue({y:t});this.pageY=t,this.view="month",this.emit("view:change",{view:this.view}),this._rerender();return}if(this.view==="month"){const t=we(e.dataset.ym);if(!t)return;if(this.precision==="month")return this._commitValue(t);this.pageY=t.y,this.pageM=t.m,this.view="day",this.emit("view:change",{view:this.view}),this._rerender();return}if(this.view==="day"){const t=z(e.dataset.ymd);if(!t)return;this._commitValue(t)}}_commitValue(e){if(this.mode==="single"){this.selected=e,this.emit("select",{value:B(e,this.precision),parsed:e}),this._rerender();return}if(!this._anchor){this._anchor=e,this.start=null,this.end=null,this._hover=null,this.emit("range:start",{anchor:B(e,this.precision)}),this._rerender();return}const t=this._anchor,s=e,i=U(t,s,this.precision);this.start=i<=0?t:s,this.end=i<=0?s:t,this._anchor=null,this._hover=null,this.emit("range:select",{start:B(this.start,this.precision),end:B(this.end,this.precision)}),this._rerender()}_onCellMouseEnter(e){if(this.mode!=="range"||!this._anchor)return;const t=e.target.closest(".mojo-calendar-cell");if(!t||t.classList.contains("mojo-calendar-cell-blank")||t.disabled)return;let s=null;this.view==="day"&&t.dataset.ymd?s=z(t.dataset.ymd):this.view==="month"&&t.dataset.ym?s=we(t.dataset.ym):this.view==="year"&&t.dataset.year&&(s={y:parseInt(t.dataset.year,10)}),s&&(this._hover&&U(this._hover,s,this.view)===0||(this._hover=s,this._rerender()))}_onCellMouseLeave(){this.mode!=="range"||!this._anchor||this._hover&&(this._hover=null,this._rerender())}_navigate(e){if(this.view==="day"){const t=ie({y:this.pageY,m:this.pageM},e);this.pageY=t.y,this.pageM=t.m}else this.view==="month"?this.pageY+=e:this.view==="year"&&(this.pageY=this._decadeStart(this.pageY)+e*10);this.emit("navigate",{delta:e}),this._rerender()}_zoomOut(e){if(e==="day"){this.view="month",this.emit("view:change",{view:this.view}),this._rerender();return}e==="month"&&(this.view="year",this.emit("view:change",{view:this.view}),this._rerender())}_onKeyDown(e){const t=e.key;if(t==="Escape"){this._anchor&&(this._anchor=null,this._hover=null,this.emit("range:cancel"),this._rerender(),e.preventDefault());return}if(t==="PageUp"){this._navigate(-1),e.preventDefault();return}if(t==="PageDown"){this._navigate(1),e.preventDefault();return}}_isDisabledAt(e,t){if(this.min&&U(e,this.min,t)<0||this.max&&U(e,this.max,t)>0)return!0;if(t==="day"&&this.disabledDates.length){const s=H(e);if(this.disabledDates.includes(s))return!0}return!1}async onBeforeDestroy(){this.element&&(this.element.removeEventListener("mouseover",this._onCellMouseEnter),this.element.removeEventListener("mouseleave",this._onCellMouseLeave)),await super.onBeforeDestroy()}}class Ce{constructor(e={}){const{anchor:t=null,placement:s="bottom-start",gap:i=6,portal:r=!0,onOutsideClick:n=null,classNames:a=""}=e;this.anchor=t,this.placement=s,this.gap=i,this.portal=r,this.onOutsideClick=n,this.element=document.createElement("div"),this.element.className=`mojo-calendar-popover ${a}`.trim(),this.element.style.position="absolute",this.element.style.zIndex="10000",this.element.setAttribute("role","dialog"),this._open=!1,this._onDocClick=this._onDocClick.bind(this),this._onScroll=this._onScroll.bind(this),this._onResize=this._onResize.bind(this),this._onKey=this._onKey.bind(this)}setAnchor(e){this.anchor=e,this._open&&this._reposition()}setContent(e){this.element.innerHTML="",e&&this.element.appendChild(e)}open(){this._open||(this._open=!0,this.portal&&this.element.parentNode!==document.body&&document.body.appendChild(this.element),this.element.classList.add("is-open"),this._reposition(),setTimeout(()=>{document.addEventListener("mousedown",this._onDocClick,!0),document.addEventListener("keydown",this._onKey,!0),window.addEventListener("scroll",this._onScroll,!0),window.addEventListener("resize",this._onResize)},0))}close(){this._open&&(this._open=!1,this.element.classList.remove("is-open"),document.removeEventListener("mousedown",this._onDocClick,!0),document.removeEventListener("keydown",this._onKey,!0),window.removeEventListener("scroll",this._onScroll,!0),window.removeEventListener("resize",this._onResize),this.portal&&this.element.parentNode===document.body&&document.body.removeChild(this.element))}isOpen(){return this._open}destroy(){this.close(),this.element=null}_onDocClick(e){this.element.contains(e.target)||this.anchor&&this.anchor.contains(e.target)||(typeof this.onOutsideClick=="function"?this.onOutsideClick(e):this.close())}_onKey(e){e.key==="Escape"&&this.close()}_onScroll(){this._open&&this._reposition()}_onResize(){this._open&&this._reposition()}_reposition(){if(!this.anchor)return;const e=this.anchor.getBoundingClientRect(),t=this.element.getBoundingClientRect(),s=window.scrollX||window.pageXOffset||0,i=window.scrollY||window.pageYOffset||0;let r=e.bottom+i+this.gap,n=e.left+s;this.placement==="bottom-end"?n=e.right+s-t.width:this.placement==="top-start"?r=e.top+i-t.height-this.gap:this.placement==="top-end"&&(r=e.top+i-t.height-this.gap,n=e.right+s-t.width);const a=document.documentElement.clientWidth||window.innerWidth;n+t.width>s+a-8&&(n=s+a-t.width-8),n<s+8&&(n=s+8);const o=document.documentElement.clientHeight||window.innerHeight;r-i+t.height>o-8&&e.top-t.height-this.gap>8&&(r=e.top+i-t.height-this.gap),this.element.style.top=`${r}px`,this.element.style.left=`${n}px`}}const gt={day:"MMM DD, YYYY",month:"MMM YYYY",year:"YYYY"};class He extends C{constructor(e={}){const{name:t,value:s="",precision:i="day",format:r=null,displayFormat:n=null,min:a=null,max:o=null,placeholder:l=null,disabled:d=!1,readonly:h=!1,required:u=!1,class:m="",inputClass:p="form-control",inline:f=!1,disabledDates:g=[],firstDay:b=1,lang:y="en-US",autoApply:w=!0,...x}=e;super({tagName:"div",className:`mojo-date-picker mojo-date-picker-${i} ${m}`.trim(),...x}),this.name=t,this.precision=i,this.format=r,this.displayFormat=n||gt[i]||gt.day,this.min=a,this.max=o,this.placeholder=l??this._defaultPlaceholder(i),this.disabled=d,this.readonly=h,this.required=u,this.inputClass=p,this.inline=f,this.disabledDates=g,this.firstDay=b,this.lang=y,this.autoApply=w,this.currentValue=s||"",this._calendar=null,this._popover=null}_defaultPlaceholder(e){return e==="year"?"Select year...":e==="month"?"Select month...":"Select date..."}async renderTemplate(){const e=this._inputId(),t=this._displayText(this.currentValue),s=!this.currentValue;return this.inline?`
1027
+ `,...e}),this.name=e.name||"multiselect",this.label=e.label||"",this.help=e.help||"",this.error=e.error||"",this.required=e.required||!1,this.disabled=e.disabled||!1,this.placeholder=e.placeholder||e.placeHolder||"Select...",this.maxHeight=e.maxHeight||300,this.showSelectedLabels=e.showSelectedLabels!==!1,this.maxLabelsToShow=e.maxLabelsToShow||3,this.options=e.options||[],this.selectedValues=Array.isArray(e.value)?e.value:[],this.buttonText=this.computeButtonText(),this.listView=null}computeButtonText(){const e=this.selectedValues.length;return e===0?this.placeholder||"Select...":this.showSelectedLabels&&e<=this.maxLabelsToShow?this.selectedValues.map(s=>{const i=this.options.find(r=>(typeof r=="string"?r:r.value)===s);return typeof i=="string"?i:i?.label||i?.value||s}).join(", "):`${e} selected`}async onAfterRender(){await super.onAfterRender(),this.createListView()}createListView(){const e=this.element?.querySelector('[data-container="items"]');if(!e)return;const t=this.options.map((s,i)=>{const r=typeof s=="string"?s:s.value,n=typeof s=="string"?s:s.label||s.text||s.value,a=typeof s=="object"?s.disabled:!1;return{id:`${this.name}_${i}`,value:r,label:n,index:i,selected:this.selectedValues.includes(r),disabled:a}});this.listView=new Zt({items:t,maxHeight:this.maxHeight}),this.listView.on("toggle",s=>{this.handleToggle(s)}),this.listView.on("close-dropdown",()=>{this.closeDropdown()}),this.listView.render(!0,e)}closeDropdown(){const e=this.element?.querySelector(".dropdown-toggle");if(e&&window.bootstrap?.Dropdown){const t=window.bootstrap.Dropdown.getInstance(e);t&&t.hide()}}handleToggle(e){const{value:t,selected:s}=e;s?this.selectedValues.includes(t)||this.selectedValues.push(t):this.selectedValues=this.selectedValues.filter(i=>i!==t),this.updateButtonText(),this.emit("change",{value:this.selectedValues,name:this.name})}updateButtonText(){const e=this.element?.querySelector(".multiselect-button-text");if(!e)return;const t=this.selectedValues.length;this.buttonText=this.computeButtonText(),e.textContent=this.buttonText,t===0?e.classList.add("text-muted"):e.classList.remove("text-muted")}getValue(){return this.selectedValues}setValue(e){this.selectedValues=Array.isArray(e)?e:e?[e]:[],this.listView&&this.listView.setValue(this.selectedValues),this.updateButtonText()}setOptions(e){if(this.options=e,this.listView){const t=this.options.map((s,i)=>{const r=typeof s=="string"?s:s.value,n=typeof s=="string"?s:s.label||s.text||s.value,a=typeof s=="object"?s.disabled:!1;return{id:`${this.name}_${i}`,value:r,label:n,index:i,selected:this.selectedValues.includes(r),disabled:a}});this.listView.updateItems(t)}}clear(){this.setValue([])}getFormValue(){return this.getValue()}setFormValue(e){this.setValue(e)}async onBeforeDestroy(){await super.onBeforeDestroy(),this.listView&&this.listView.destroy()}}const Ne=["January","February","March","April","May","June","July","August","September","October","November","December"],Oe=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function at(c){if(c==null||c==="")return null;const e=parseInt(String(c).slice(0,4),10);return Number.isFinite(e)?{y:e}:null}function we(c){if(c==null||c==="")return null;const e=String(c).split("-"),t=parseInt(e[0],10),s=parseInt(e[1],10);return!Number.isFinite(t)||!Number.isFinite(s)||s<1||s>12?null:{y:t,m:s}}function z(c){if(c==null||c==="")return null;if(c instanceof Date&&!isNaN(c.getTime()))return{y:c.getFullYear(),m:c.getMonth()+1,d:c.getDate()};const e=String(c).split("-"),t=parseInt(e[0],10),s=parseInt(e[1],10),i=parseInt(e[2],10);return!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(i)||s<1||s>12||i<1||i>31?null:{y:t,m:s,d:i}}function ot(c){const e=typeof c=="object"?c:at(c);return e?String(e.y):""}function je(c){const e=typeof c=="object"?c:we(c);return e?`${e.y}-${K(e.m)}`:""}function H(c){const e=typeof c=="object"?c:z(c);return e?`${e.y}-${K(e.m)}-${K(e.d)}`:""}function B(c,e){return e==="year"?ot(c):e==="month"?je(c):H(c)}function V(c,e){return e==="year"?at(c):e==="month"?we(c):z(c)}const Qt=/YYYY|YY|MMMM|MMM|MM|M|DD|D/g;function ce(c,e){if(!c)return"";const t=c.y,s=c.m,i=c.d;return String(e).replace(Qt,r=>{switch(r){case"YYYY":return String(t);case"YY":return String(t).slice(-2);case"MMMM":return s?Ne[s-1]:"";case"MMM":return s?Oe[s-1]:"";case"MM":return s?K(s):"";case"M":return s?String(s):"";case"DD":return i?K(i):"";case"D":return i?String(i):"";default:return r}})}function lt(c,e){return new Date(c,e,0).getDate()}function Xt(c,e,t,s=1){return((new Date(c,e-1,t).getDay()-s)%7+7)%7}function ie(c,e){if(!c)return null;let t=c.y,s=c.m+e;for(;s>12;)s-=12,t+=1;for(;s<1;)s+=12,t-=1;if(c.d==null)return{y:t,m:s};const i=lt(t,s);return{y:t,m:s,d:Math.min(c.d,i)}}function ct(c,e){return!c||!e?0:c.y!==e.y?c.y<e.y?-1:1:(c.m||0)!==(e.m||0)?(c.m||0)<(e.m||0)?-1:1:(c.d||0)!==(e.d||0)?(c.d||0)<(e.d||0)?-1:1:0}function dt(c,e){return!c||!e?0:c.y!==e.y?c.y<e.y?-1:1:(c.m||0)!==(e.m||0)?(c.m||0)<(e.m||0)?-1:1:0}function es(c,e){return!c||!e||c.y===e.y?0:c.y<e.y?-1:1}function U(c,e,t){return t==="year"?es(c,e):t==="month"?dt(c,e):ct(c,e)}function W(c){if(c==null||c==="")return null;if(typeof c=="object"&&c!==null){const d=parseInt(c.hours??c.h,10),h=parseInt(c.minutes??c.m,10);return!Number.isFinite(d)||!Number.isFinite(h)||d<0||d>23||h<0||h>59?null:{hours:d,minutes:h}}const e=String(c).trim(),t=e.indexOf(" "),s=t>-1?e.slice(0,t):e,r=(t>-1?e.slice(t+1).trim():"").match(/^(am|pm)$/i)||s.match(/(am|pm)$/i),a=s.replace(/(am|pm)$/i,"").trim().split(":");if(a.length<2)return null;let o=parseInt(a[0],10);const l=parseInt(a[1],10);if(!Number.isFinite(o)||!Number.isFinite(l)||l<0||l>59)return null;if(r){const d=r[1].toLowerCase()==="pm";if(o<1||o>12)return null;o===12?o=d?12:0:d&&(o+=12)}return o<0||o>23?null:{hours:o,minutes:l}}function G(c,e="24h"){if(!c)return"";const t=c.hours,s=c.minutes;if(!Number.isFinite(t)||!Number.isFinite(s))return"";if(e==="12h"){const i=t>=12?"PM":"AM";let r=t%12;return r===0&&(r=12),`${r}:${K(s)} ${i}`}return`${K(t)}:${K(s)}`}function ht(c,e){return!c||!e?0:c.hours!==e.hours?c.hours<e.hours?-1:1:c.minutes!==e.minutes?c.minutes<e.minutes?-1:1:0}function ts(c,e){if(!c)return null;let t=c.hours*60+c.minutes+e;return t=(t%1440+1440)%1440,{hours:Math.floor(t/60),minutes:t%60}}function ut(c,e){if(!c)return null;try{const t=e instanceof Date?e:new Date,r=new Intl.DateTimeFormat("en-US",{timeZone:c,timeZoneName:"shortOffset"}).formatToParts(t).find(h=>h.type==="timeZoneName");if(!r)return null;let n=r.value;if(n==="GMT"||n==="UTC")return"+00:00";n=n.replace(/^(GMT|UTC)/,"");const a=n.match(/^([+-])(\d{1,2})(?::(\d{2}))?$/);if(!a)return null;const o=a[1],l=a[2].padStart(2,"0"),d=a[3]||"00";return`${o}${l}:${d}`}catch{return null}}function mt(c){if(c==null||c==="")return null;if(typeof c=="object"&&!Array.isArray(c)&&!(c instanceof Date)){const h=c.date?z(c.date):null,u=c.time?W(c.time):null;return h?{date:h,time:u||{hours:0,minutes:0},timezone:c.timezone||null}:null}let e=String(c).trim();const t=e.match(/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})(?::\d{2}(?:\.\d+)?)?(Z|[+-]\d{2}:?\d{2})?$/);if(t){const[,h,u,m,p,f,g]=t;let b=null;return g&&(g==="Z"?b="+00:00":/^[+-]\d{4}$/.test(g)?b=`${g.slice(0,3)}:${g.slice(3)}`:b=g),{date:{y:+h,m:+u,d:+m},time:{hours:+p,minutes:+f},timezone:b}}let s,i;if(e.length>=11&&e.charAt(10)==="T")s=e.slice(0,10),i=e.slice(11);else{const h=e.indexOf(" ");if(h===-1){const u=z(e);return u?{date:u,time:{hours:0,minutes:0},timezone:null}:null}s=e.slice(0,h),i=e.slice(h+1)}const r=z(s);if(!r)return null;const n=i.trim();let a=null,o=n;const l=n.match(/\s+([A-Za-z][A-Za-z_+\-]*\/[A-Za-z][A-Za-z_+\-]*|UTC|GMT)$/);l&&(a=l[1],o=n.slice(0,l.index).trim());const d=W(o);return d?{date:r,time:d,timezone:a}:null}function T(){const c=new Date;return{y:c.getFullYear(),m:c.getMonth()+1,d:c.getDate()}}let ve=null,Re=null,qe=null;function pt(c="en-US",e="short"){if((!c||c==="en-US"||c==="en")&&e==="short")return Oe.slice();if((!c||c==="en-US"||c==="en")&&e==="long")return Ne.slice();if(typeof Intl>"u"||!Intl.DateTimeFormat)return e==="long"?Ne.slice():Oe.slice();if(ve===c+"/"+e&&Re)return Re.slice();const t=new Intl.DateTimeFormat(c,{month:e}),s=[];for(let i=0;i<12;i++)s.push(t.format(new Date(2024,i,15)));return ve=c+"/"+e,Re=s,s.slice()}function ss(c="en-US",e=1,t="short"){if(typeof Intl>"u"||!Intl.DateTimeFormat)return ft(["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],e);const s=c+"/"+e+"/"+t;if(ve===s&&qe)return qe.slice();const i=new Intl.DateTimeFormat(c,{weekday:t}),r=[];for(let a=0;a<7;a++)r.push(i.format(new Date(2024,0,7+a)));const n=ft(r,e);return ve=s,qe=n,n.slice()}function K(c){return c<10?"0"+c:String(c)}function ft(c,e){const t=(e%c.length+c.length)%c.length;return c.slice(t).concat(c.slice(0,t))}class ze extends C{constructor(e={}){const{precision:t="day",mode:s="single",months:i=1,value:r=null,startValue:n=null,endValue:a=null,min:o=null,max:l=null,disabledDates:d=[],firstDay:h=1,locale:u="en-US",excludeDisabledFromRange:m=!1,year:p=null,month:f=null,class:g="",...b}=e;super({tagName:"div",className:`mojo-calendar mojo-calendar-${t} ${g}`.trim(),...b}),this.precision=t,this.mode=s,this.months=Math.max(1,Math.min(2,i|0)),this.firstDay=h,this.locale=u,this.excludeDisabledFromRange=m,this.min=V(o,t)||(o?z(o):null),this.max=V(l,t)||(l?z(l):null),this.disabledDates=(d||[]).map(x=>H(z(x)||null)).filter(Boolean),s==="single"?this.selected=V(r,t):(this.start=V(n,t),this.end=V(a,t),this._anchor=null),this._hover=null,this.view=t;const y=T(),v=(s==="single"?this.selected:this.start||this.end)||y;this.pageY=p!=null?Number(p):v.y??y.y,this.pageM=f!=null?Number(f):v.m??y.m,this._onCellMouseEnter=this._onCellMouseEnter.bind(this),this._onCellMouseLeave=this._onCellMouseLeave.bind(this)}setMin(e){this.min=V(e,this.precision),this._rerender()}setMax(e){this.max=V(e,this.precision),this._rerender()}setValue(e){this.selected=V(e,this.precision),this.selected&&(this.pageY=this.selected.y,this.pageM=this.selected.m||this.pageM),this._rerender()}setRange(e,t){this.start=V(e,this.precision),this.end=V(t,this.precision),this._anchor=null,this._rerender()}getValue(){return this.selected?B(this.selected,this.precision):""}getRange(){return{start:this.start?B(this.start,this.precision):"",end:this.end?B(this.end,this.precision):""}}async renderTemplate(){return""}async onAfterRender(){this._eventsWired||(this._wireEvents(this.element),this._eventsWired=!0),this._renderInto(this.element)}_rerender(){this.element&&this._renderInto(this.element)}_renderInto(e){e.innerHTML="";const t=document.createElement("div");if(t.className=this.months>1&&this.view==="day"?"mojo-calendar-multi":"mojo-calendar-single",this.view==="day"){const s=this.months;for(let i=0;i<s;i++){let r=this.pageY,n=this.pageM+i;for(;n>12;)n-=12,r+=1;t.appendChild(this._buildDayPane(r,n,i===0,i===s-1))}}else this.view==="month"?t.appendChild(this._buildMonthPane(this.pageY)):this.view==="year"&&t.appendChild(this._buildYearPane(this._decadeStart(this.pageY)));e.appendChild(t)}_decadeStart(e){return Math.floor(e/10)*10}_buildDayPane(e,t,s,i){const r=document.createElement("div");return r.className="mojo-calendar-pane",r.appendChild(this._buildHead(this._dayHeadLabel(e,t),"day",s,i,e,t)),r.appendChild(this._buildWeekdayHeader()),r.appendChild(this._buildDayGrid(e,t)),r}_dayHeadLabel(e,t){return{kind:"day",year:e,month:t}}_buildWeekdayHeader(){const e=document.createElement("div");return e.className="mojo-calendar-grid mojo-calendar-grid-day",ss(this.locale,this.firstDay,"short").forEach(t=>{const s=document.createElement("div");s.className="mojo-calendar-weekday",s.textContent=t,e.appendChild(s)}),e}_buildDayGrid(e,t){const s=document.createElement("div");s.className="mojo-calendar-grid mojo-calendar-grid-day";const i=Xt(e,t,1,this.firstDay),r=lt(e,t),n=T();for(let a=0;a<i;a++){const o=document.createElement("div");o.className="mojo-calendar-cell mojo-calendar-cell-blank",s.appendChild(o)}for(let a=1;a<=r;a++){const o={y:e,m:t,d:a},l=document.createElement("button");l.type="button",l.className="mojo-calendar-cell",l.dataset.ymd=H(o),o.y===n.y&&o.m===n.m&&o.d===n.d&&l.classList.add("mojo-calendar-cell-today"),this._isDisabledAt(o,"day")&&(l.classList.add("mojo-calendar-cell-disabled"),l.disabled=!0),this.mode==="range"?this._applyRangeClasses(l,o,"day"):this.selected&&ct(o,this.selected)===0&&l.classList.add("mojo-calendar-cell-selected");const d=document.createElement("span");d.className="mojo-calendar-cell-inner",d.textContent=String(a),l.appendChild(d),s.appendChild(l)}return s}_buildMonthPane(e){const t=document.createElement("div");return t.className="mojo-calendar-pane",t.appendChild(this._buildHead(String(e),"month",!0,!0,e,1)),t.appendChild(this._buildMonthGrid(e)),t}_buildMonthGrid(e){const t=document.createElement("div");t.className="mojo-calendar-grid mojo-calendar-grid-month";const s=pt(this.locale,"short");for(let i=1;i<=12;i++){const r={y:e,m:i},n=document.createElement("button");n.type="button",n.className="mojo-calendar-cell",n.dataset.ym=je(r),this._isDisabledAt(r,"month")&&(n.classList.add("mojo-calendar-cell-disabled"),n.disabled=!0),this.precision==="month"&&this.mode==="range"?this._applyRangeClasses(n,r,"month"):this.precision==="month"&&this.mode==="single"&&this.selected&&dt(r,this.selected)===0&&n.classList.add("mojo-calendar-cell-selected");const a=document.createElement("span");a.className="mojo-calendar-cell-inner",a.textContent=s[i-1],n.appendChild(a),t.appendChild(n)}return t}_buildYearPane(e){const t=document.createElement("div");return t.className="mojo-calendar-pane",t.appendChild(this._buildHead(`${e} – ${e+11}`,"year",!0,!0,e,1)),t.appendChild(this._buildYearGrid(e)),t}_buildYearGrid(e){const t=document.createElement("div");t.className="mojo-calendar-grid mojo-calendar-grid-year";for(let s=0;s<12;s++){const i=e+s,r={y:i},n=document.createElement("button");n.type="button",n.className="mojo-calendar-cell",n.dataset.year=String(i),this._isDisabledAt(r,"year")&&(n.classList.add("mojo-calendar-cell-disabled"),n.disabled=!0),this.precision==="year"&&this.mode==="range"?this._applyRangeClasses(n,r,"year"):this.precision==="year"&&this.mode==="single"&&this.selected&&this.selected.y===i&&n.classList.add("mojo-calendar-cell-selected");const a=document.createElement("span");a.className="mojo-calendar-cell-inner",a.textContent=String(i),n.appendChild(a),t.appendChild(n)}return t}_applyRangeClasses(e,t,s){let i=this.start,r=this.end;if(this._anchor){const o=this._hover||this._anchor,l=U(this._anchor,o,s);i=l<=0?this._anchor:o,r=l<=0?o:this._anchor}if(!i||!r){this._anchor&&U(t,this._anchor,s)===0&&e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-solo");return}const n=U(t,i,s),a=U(t,r,s);n>0&&a<0&&e.classList.add(this._anchor?"mojo-calendar-cell-in-preview":"mojo-calendar-cell-in-range"),n===0&&(e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-start"),U(i,r,s)===0?e.classList.add("mojo-calendar-cell-anchor-solo"):e.classList.add(this._anchor?"mojo-calendar-cell-in-preview":"mojo-calendar-cell-in-range")),a===0&&U(i,r,s)!==0&&(e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-end"),e.classList.add(this._anchor?"mojo-calendar-cell-in-preview":"mojo-calendar-cell-in-range"))}_buildHead(e,t,s,i){const r=document.createElement("div");r.className="mojo-calendar-head";const n=document.createElement("button");if(n.type="button",n.className="mojo-calendar-head-label",n.dataset.level=t,n.dataset.action="zoom-out",typeof e=="string")n.textContent=e;else if(e&&e.kind==="day"){const o=pt(this.locale,"long");n.appendChild(document.createTextNode(`${o[e.month-1]} `));const l=document.createElement("span");l.className="mojo-calendar-year",l.textContent=String(e.year),n.appendChild(l)}r.appendChild(n);const a=document.createElement("div");return a.className="mojo-calendar-nav",s&&a.appendChild(this._navBtn("prev")),i&&a.appendChild(this._navBtn("next")),r.appendChild(a),r}_navBtn(e){const t=document.createElement("button");return t.type="button",t.className="mojo-calendar-nav-btn",t.dataset.action=`nav-${e}`,t.setAttribute("aria-label",e==="prev"?"Previous":"Next"),t.innerHTML=e==="prev"?"&#x2039;":"&#x203A;",t}_wireEvents(e){e.addEventListener("click",t=>this._onClick(t)),e.addEventListener("mouseover",this._onCellMouseEnter),e.addEventListener("mouseleave",this._onCellMouseLeave),e.addEventListener("keydown",t=>this._onKeyDown(t))}_onClick(e){const t=e.target.closest("[data-action], .mojo-calendar-cell");if(!t||t.classList.contains("mojo-calendar-cell-blank")||t.disabled)return;const s=t.dataset.action;if(s==="nav-prev")return this._navigate(-1);if(s==="nav-next")return this._navigate(1);if(s==="zoom-out")return this._zoomOut(t.dataset.level);t.classList.contains("mojo-calendar-cell")&&this._onCellClick(t)}_onCellClick(e){if(this.view==="year"){const t=parseInt(e.dataset.year,10);if(!Number.isFinite(t))return;if(this.precision==="year")return this._commitValue({y:t});this.pageY=t,this.view="month",this.emit("view:change",{view:this.view}),this._rerender();return}if(this.view==="month"){const t=we(e.dataset.ym);if(!t)return;if(this.precision==="month")return this._commitValue(t);this.pageY=t.y,this.pageM=t.m,this.view="day",this.emit("view:change",{view:this.view}),this._rerender();return}if(this.view==="day"){const t=z(e.dataset.ymd);if(!t)return;this._commitValue(t)}}_commitValue(e){if(this.mode==="single"){this.selected=e,this.emit("select",{value:B(e,this.precision),parsed:e}),this._rerender();return}if(!this._anchor){this._anchor=e,this.start=null,this.end=null,this._hover=null,this.emit("range:start",{anchor:B(e,this.precision)}),this._rerender();return}const t=this._anchor,s=e,i=U(t,s,this.precision);this.start=i<=0?t:s,this.end=i<=0?s:t,this._anchor=null,this._hover=null,this.emit("range:select",{start:B(this.start,this.precision),end:B(this.end,this.precision)}),this._rerender()}_onCellMouseEnter(e){if(this.mode!=="range"||!this._anchor)return;const t=e.target.closest(".mojo-calendar-cell");if(!t||t.classList.contains("mojo-calendar-cell-blank")||t.disabled)return;let s=null;this.view==="day"&&t.dataset.ymd?s=z(t.dataset.ymd):this.view==="month"&&t.dataset.ym?s=we(t.dataset.ym):this.view==="year"&&t.dataset.year&&(s={y:parseInt(t.dataset.year,10)}),s&&(this._hover&&U(this._hover,s,this.view)===0||(this._hover=s,this._rerender()))}_onCellMouseLeave(){this.mode!=="range"||!this._anchor||this._hover&&(this._hover=null,this._rerender())}_navigate(e){if(this.view==="day"){const t=ie({y:this.pageY,m:this.pageM},e);this.pageY=t.y,this.pageM=t.m}else this.view==="month"?this.pageY+=e:this.view==="year"&&(this.pageY=this._decadeStart(this.pageY)+e*10);this.emit("navigate",{delta:e}),this._rerender()}_zoomOut(e){if(e==="day"){this.view="month",this.emit("view:change",{view:this.view}),this._rerender();return}e==="month"&&(this.view="year",this.emit("view:change",{view:this.view}),this._rerender())}_onKeyDown(e){const t=e.key;if(t==="Escape"){this._anchor&&(this._anchor=null,this._hover=null,this.emit("range:cancel"),this._rerender(),e.preventDefault());return}if(t==="PageUp"){this._navigate(-1),e.preventDefault();return}if(t==="PageDown"){this._navigate(1),e.preventDefault();return}}_isDisabledAt(e,t){if(this.min&&U(e,this.min,t)<0||this.max&&U(e,this.max,t)>0)return!0;if(t==="day"&&this.disabledDates.length){const s=H(e);if(this.disabledDates.includes(s))return!0}return!1}async onBeforeDestroy(){this.element&&(this.element.removeEventListener("mouseover",this._onCellMouseEnter),this.element.removeEventListener("mouseleave",this._onCellMouseLeave)),await super.onBeforeDestroy()}}class Ce{constructor(e={}){const{anchor:t=null,placement:s="bottom-start",gap:i=6,portal:r=!0,onOutsideClick:n=null,classNames:a=""}=e;this.anchor=t,this.placement=s,this.gap=i,this.portal=r,this.onOutsideClick=n,this.element=document.createElement("div"),this.element.className=`mojo-calendar-popover ${a}`.trim(),this.element.style.position="absolute",this.element.style.zIndex="10000",this.element.setAttribute("role","dialog"),this._open=!1,this._onDocClick=this._onDocClick.bind(this),this._onScroll=this._onScroll.bind(this),this._onResize=this._onResize.bind(this),this._onKey=this._onKey.bind(this)}setAnchor(e){this.anchor=e,this._open&&this._reposition()}setContent(e){this.element.innerHTML="",e&&this.element.appendChild(e)}open(){this._open||(this._open=!0,this.portal&&this.element.parentNode!==document.body&&document.body.appendChild(this.element),this.element.classList.add("is-open"),this._reposition(),setTimeout(()=>{document.addEventListener("mousedown",this._onDocClick,!0),document.addEventListener("keydown",this._onKey,!0),window.addEventListener("scroll",this._onScroll,!0),window.addEventListener("resize",this._onResize)},0))}close(){this._open&&(this._open=!1,this.element.classList.remove("is-open"),document.removeEventListener("mousedown",this._onDocClick,!0),document.removeEventListener("keydown",this._onKey,!0),window.removeEventListener("scroll",this._onScroll,!0),window.removeEventListener("resize",this._onResize),this.portal&&this.element.parentNode===document.body&&document.body.removeChild(this.element))}isOpen(){return this._open}destroy(){this.close(),this.element=null}_onDocClick(e){this.element.contains(e.target)||this.anchor&&this.anchor.contains(e.target)||(typeof this.onOutsideClick=="function"?this.onOutsideClick(e):this.close())}_onKey(e){e.key==="Escape"&&this.close()}_onScroll(){this._open&&this._reposition()}_onResize(){this._open&&this._reposition()}_reposition(){if(!this.anchor)return;const e=this.anchor.getBoundingClientRect(),t=this.element.getBoundingClientRect(),s=window.scrollX||window.pageXOffset||0,i=window.scrollY||window.pageYOffset||0;let r=e.bottom+i+this.gap,n=e.left+s;this.placement==="bottom-end"?n=e.right+s-t.width:this.placement==="top-start"?r=e.top+i-t.height-this.gap:this.placement==="top-end"&&(r=e.top+i-t.height-this.gap,n=e.right+s-t.width);const a=document.documentElement.clientWidth||window.innerWidth;n+t.width>s+a-8&&(n=s+a-t.width-8),n<s+8&&(n=s+8);const o=document.documentElement.clientHeight||window.innerHeight;r-i+t.height>o-8&&e.top-t.height-this.gap>8&&(r=e.top+i-t.height-this.gap),this.element.style.top=`${r}px`,this.element.style.left=`${n}px`}}const gt={day:"MMM DD, YYYY",month:"MMM YYYY",year:"YYYY"};class He extends C{constructor(e={}){const{name:t,value:s="",precision:i="day",format:r=null,displayFormat:n=null,min:a=null,max:o=null,placeholder:l=null,disabled:d=!1,readonly:h=!1,required:u=!1,class:m="",inputClass:p="form-control",inline:f=!1,disabledDates:g=[],firstDay:b=1,lang:y="en-US",autoApply:v=!0,...x}=e;super({tagName:"div",className:`mojo-date-picker mojo-date-picker-${i} ${m}`.trim(),...x}),this.name=t,this.precision=i,this.format=r,this.displayFormat=n||gt[i]||gt.day,this.min=a,this.max=o,this.placeholder=l??this._defaultPlaceholder(i),this.disabled=d,this.readonly=h,this.required=u,this.inputClass=p,this.inline=f,this.disabledDates=g,this.firstDay=b,this.lang=y,this.autoApply=v,this.currentValue=s||"",this._calendar=null,this._popover=null}_defaultPlaceholder(e){return e==="year"?"Select year...":e==="month"?"Select month...":"Select date..."}async renderTemplate(){const e=this._inputId(),t=this._displayText(this.currentValue),s=!this.currentValue;return this.inline?`
1028
1028
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(this.currentValue)}" data-hidden-value />
1029
1029
  <div data-cal-host class="mojo-date-picker-inline${this.hasError()?" is-invalid":""}"></div>
1030
1030
  `:`
@@ -1036,7 +1036,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
1036
1036
  ${!this.required&&!this.disabled&&!this.readonly?'<button type="button" class="mojo-date-trigger-clear" data-clear aria-label="Clear" tabindex="-1">&#x2715;</button>':""}
1037
1037
  </button>
1038
1038
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(this.currentValue)}" data-hidden-value />
1039
- `}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 Ce({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 ze({precision:this.precision,mode:"single",months:1,value:this.currentValue||null,min:this.min,max:this.max,disabledDates:this.disabledDates,firstDay:this.firstDay,locale:this.lang});return e.on("select",({value:t})=>{this._setValue(t),this.autoApply&&this._popover&&this._popover.isOpen()&&this._popover.close()}),e}_setValue(e){const t=this.currentValue;let s="";if(e){const a=P(e,this.precision);a&&(s=B(a,this.precision))}this.currentValue=s;const i=this._displayText(s),r=this.element.querySelector("[data-trigger-text]");r&&(r.textContent=i||this.placeholder,r.classList.toggle("is-empty",!s));const n=this.element.querySelector("[data-hidden-value]");n&&(n.value=s),this._calendar&&this._calendar.setValue(s),t!==s&&(this.emit("change",{value:s,formatted:i,oldValue:t}),this.emit("date:changed",{value:s,oldValue:t}))}_displayText(e){if(!e)return"";const t=P(e,this.precision);return t?ce(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 He(e)}}function is(){return[{label:"Today",range:()=>{const c=T();return{start:c,end:c}}},{label:"Yesterday",range:()=>{const c=T(),e=Se(c,-1);return{start:e,end:e}}},{label:"Last 7 days",range:()=>{const c=T();return{start:Se(c,-6),end:c}}},{label:"Last 30 days",range:()=>{const c=T();return{start:Se(c,-29),end:c}}},{label:"Last 90 days",range:()=>{const c=T();return{start:Se(c,-89),end:c}}},{divider:!0},{label:"This month",range:()=>{const c=T();return{start:{y:c.y,m:c.m,d:1},end:c}}},{label:"Last month",range:()=>{const c=T(),e=ie({y:c.y,m:c.m,d:1},-1),t=ie(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=T();return{start:{y:c.y,m:1,d:1},end:c}}}]}function rs(){return[{label:"This month",range:()=>{const c=T();return{start:{y:c.y,m:c.m},end:{y:c.y,m:c.m}}}},{label:"Last month",range:()=>{const c=T(),e=ie({y:c.y,m:c.m},-1);return{start:e,end:e}}},{label:"Last 3 months",range:()=>{const c=T();return{start:ie({y:c.y,m:c.m},-2),end:{y:c.y,m:c.m}}}},{label:"Last 6 months",range:()=>{const c=T();return{start:ie({y:c.y,m:c.m},-5),end:{y:c.y,m:c.m}}}},{label:"YTD",range:()=>{const c=T();return{start:{y:c.y,m:1},end:{y:c.y,m:c.m}}}},{label:"Last 12 months",range:()=>{const c=T();return{start:ie({y:c.y,m:c.m},-11),end:{y:c.y,m:c.m}}}}]}function ns(){return[{label:"This year",range:()=>{const c=T();return{start:{y:c.y},end:{y:c.y}}}},{label:"Last year",range:()=>{const c=T();return{start:{y:c.y-1},end:{y:c.y-1}}}},{label:"Last 3 years",range:()=>{const c=T();return{start:{y:c.y-2},end:{y:c.y}}}},{label:"Last 5 years",range:()=>{const c=T();return{start:{y:c.y-4},end:{y:c.y}}}},{label:"Last 10 years",range:()=>{const c=T();return{start:{y:c.y-9},end:{y:c.y}}}}]}function Se(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 bt(c){return c==="year"?ns():c==="month"?rs():is()}class as 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"?bt(t):Array.isArray(s)?s:bt(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"?ot:this.precision==="month"?je:H;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 yt={day:"MMM DD, YYYY",month:"MMM YYYY",year:"YYYY"};class Be 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:w="form-control",inline:x=!1,separator:A=" – ",autoApply:E=!0,months:j=null,presets:M=null,...O}=e;super({tagName:"div",className:`mojo-date-picker mojo-date-range-picker mojo-date-picker-${o} ${y}`.trim(),...O}),this.name=t,this.startName=s,this.endName=i,this.fieldName=r,this.precision=o,this.format=l,this.displayFormat=d||yt[o]||yt.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=w,this.inline=x,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=`
1039
+ `}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 Ce({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 ze({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=B(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?ce(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 He(e)}}function is(){return[{label:"Today",range:()=>{const c=T();return{start:c,end:c}}},{label:"Yesterday",range:()=>{const c=T(),e=Se(c,-1);return{start:e,end:e}}},{label:"Last 7 days",range:()=>{const c=T();return{start:Se(c,-6),end:c}}},{label:"Last 30 days",range:()=>{const c=T();return{start:Se(c,-29),end:c}}},{label:"Last 90 days",range:()=>{const c=T();return{start:Se(c,-89),end:c}}},{divider:!0},{label:"This month",range:()=>{const c=T();return{start:{y:c.y,m:c.m,d:1},end:c}}},{label:"Last month",range:()=>{const c=T(),e=ie({y:c.y,m:c.m,d:1},-1),t=ie(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=T();return{start:{y:c.y,m:1,d:1},end:c}}}]}function rs(){return[{label:"This month",range:()=>{const c=T();return{start:{y:c.y,m:c.m},end:{y:c.y,m:c.m}}}},{label:"Last month",range:()=>{const c=T(),e=ie({y:c.y,m:c.m},-1);return{start:e,end:e}}},{label:"Last 3 months",range:()=>{const c=T();return{start:ie({y:c.y,m:c.m},-2),end:{y:c.y,m:c.m}}}},{label:"Last 6 months",range:()=>{const c=T();return{start:ie({y:c.y,m:c.m},-5),end:{y:c.y,m:c.m}}}},{label:"YTD",range:()=>{const c=T();return{start:{y:c.y,m:1},end:{y:c.y,m:c.m}}}},{label:"Last 12 months",range:()=>{const c=T();return{start:ie({y:c.y,m:c.m},-11),end:{y:c.y,m:c.m}}}}]}function ns(){return[{label:"This year",range:()=>{const c=T();return{start:{y:c.y},end:{y:c.y}}}},{label:"Last year",range:()=>{const c=T();return{start:{y:c.y-1},end:{y:c.y-1}}}},{label:"Last 3 years",range:()=>{const c=T();return{start:{y:c.y-2},end:{y:c.y}}}},{label:"Last 5 years",range:()=>{const c=T();return{start:{y:c.y-4},end:{y:c.y}}}},{label:"Last 10 years",range:()=>{const c=T();return{start:{y:c.y-9},end:{y:c.y}}}}]}function Se(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 bt(c){return c==="year"?ns():c==="month"?rs():is()}class as 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"?bt(t):Array.isArray(s)?s:bt(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"?ot:this.precision==="month"?je:H;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 yt={day:"MMM DD, YYYY",month:"MMM YYYY",year:"YYYY"};class Be 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:x=!1,separator:A=" – ",autoApply:E=!0,months:j=null,presets:M=null,...O}=e;super({tagName:"div",className:`mojo-date-picker mojo-date-range-picker mojo-date-picker-${o} ${y}`.trim(),...O}),this.name=t,this.startName=s,this.endName=i,this.fieldName=r,this.precision=o,this.format=l,this.displayFormat=d||yt[o]||yt.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=x,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=`
1040
1040
  ${this.name?`<input type="hidden" name="${this._attr(this.name)}" value="${this._attr(this.getCombinedValue())}" data-combined-value />`:""}
1041
1041
  ${i?`<input type="hidden" name="${this._attr(i)}" value="${this._attr(this.currentStartDate)}" data-start-value />`:""}
1042
1042
  ${r?`<input type="hidden" name="${this._attr(r)}" value="${this._attr(this.currentEndDate)}" data-end-value />`:""}
@@ -1052,7 +1052,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
1052
1052
  ${!this.required&&!this.disabled&&!this.readonly?'<button type="button" class="mojo-date-trigger-clear" data-clear aria-label="Clear" tabindex="-1">&#x2715;</button>':""}
1053
1053
  </button>
1054
1054
  ${n}
1055
- `}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._setRange("","")}))}_togglePopover(e){if(this.disabled||this.readonly)return;if(this._popover)this._popover.setAnchor(e);else{const s=this._hasPresets();this._popover=new Ce({anchor:e,classNames:s?"mojo-calendar-popover-with-presets":""})}if(this._popover.isOpen()){this._popover.close();return}this._calendar||(this._calendar=this._buildCalendar()),this._hasPresets()&&!this._presetSidebar&&(this._presetSidebar=this._buildPresetSidebar());const t=this._buildPopoverContent();this._popover.setContent(t),this._popover.open(),this._calendar.render(!1),this._presetSidebar&&this._presetSidebar.render(!1)}_mountInline(){const e=this.element.querySelector("[data-cal-host]");e&&(this._calendar||(this._calendar=this._buildCalendar()),this._hasPresets()&&!this._presetSidebar&&(this._presetSidebar=this._buildPresetSidebar()),e.appendChild(this._buildPopoverContent()),this._calendar.render(!1),this._presetSidebar&&this._presetSidebar.render(!1))}_buildPopoverContent(){const e=document.createElement("div");e.className="mojo-calendar-popover-inner",e.style.display="contents",this._presetSidebar&&e.appendChild(this._presetSidebar.element);const t=document.createElement("div");return t.className="mojo-calendar-cal-wrap",t.appendChild(this._calendar.element),e.appendChild(t),e}_buildCalendar(){const e=new ze({precision:this.precision,mode:"range",months:this.months,startValue:this.currentStartDate||null,endValue:this.currentEndDate||null,min:this.min,max:this.max,firstDay:1,locale:"en-US"});return e.on("range:select",({start:t,end:s})=>{this._setRange(t,s),this.autoApply&&this._popover&&this._popover.isOpen()&&this._popover.close()}),e.on("range:start",()=>{this._presetSidebar&&this._presetSidebar.setActive(-1)}),e}_hasPresets(){return this.presets===!0||this.presets==="default"||Array.isArray(this.presets)&&this.presets.length>0}_buildPresetSidebar(){const e=new as({precision:this.precision,presets:this.presets});return e.on("preset:select",({start:t,end:s})=>{this._setRange(t,s),this._calendar&&this._calendar.setRange(t,s),this.autoApply&&this._popover&&this._popover.isOpen()&&this._popover.close()}),e}_setRange(e,t){const s=this.currentStartDate,i=this.currentEndDate;let r="",n="";if(e){const o=P(e,this.precision);o&&(r=B(o,this.precision))}if(t){const o=P(t,this.precision);o&&(n=B(o,this.precision))}this.currentStartDate=r,this.currentEndDate=n;const a=this.element.querySelector("[data-trigger-text]");if(a){const o=this._displayText();a.textContent=o||this.placeholder,a.classList.toggle("is-empty",!r)}this._updateHidden(),(s!==r||i!==n)&&(this.emit("change",{startDate:r,endDate:n,combined:this.getCombinedValue(),formatted:this._displayText(),oldStartDate:s,oldEndDate:i}),this.emit("range:changed",{startDate:r,endDate:n,oldStartDate:s,oldEndDate:i}))}_updateHidden(){const e=this.element.querySelector("[data-start-value]"),t=this.element.querySelector("[data-end-value]"),s=this.element.querySelector("[data-combined-value]");e&&(e.value=this.currentStartDate),t&&(t.value=this.currentEndDate),s&&(s.value=this.getCombinedValue())}_displayText(){const e=this.currentStartDate?P(this.currentStartDate,this.precision):null,t=this.currentEndDate?P(this.currentEndDate,this.precision):null;if(!e&&!t)return"";const s=this._stripIncompatibleTokens(this.displayFormat);return e&&t?`${ce(e,s)}${this.separator}${ce(t,s)}`:ce(e||t,s)}_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}getCombinedValue(){return!this.currentStartDate&&!this.currentEndDate?"":this.outputFormat==="string"?`${this.currentStartDate}${this.separator}${this.currentEndDate}`:this.outputFormat==="object"?JSON.stringify({start:this.currentStartDate,end:this.currentEndDate}):`${this.currentStartDate}${this.separator}${this.currentEndDate}`}setRange(e,t){this._setRange(e,t),this._calendar&&this._calendar.setRange(e,t)}setStartDate(e){this._setRange(e,this.currentEndDate)}setEndDate(e){this._setRange(this.currentStartDate,e)}getStartDate(){return this.currentStartDate}getEndDate(){return this.currentEndDate}getRange(){return{start:this.currentStartDate,end:this.currentEndDate}}clear(){this._setRange("","")}setMin(e){this.min=e,this._calendar&&this._calendar.setMin(e)}setMax(e){this.max=e,this._calendar&&this._calendar.setMax(e)}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.getCombinedValue()}async setFormValue(e){if(!e){this._setRange("","");return}if(typeof e=="object"&&e.start)this._setRange(e.start,e.end);else if(typeof e=="string"&&e.includes(this.separator.trim())){const[t,s]=e.split(this.separator.trim()).map(i=>i.trim());this._setRange(t,s)}else this._setRange(e,this.currentEndDate)}hasError(){return!1}_inputId(){return this.name?`mojo-daterange-${this.name}-${this.id}`:`mojo-daterange-${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,this._presetSidebar=null,await super.onBeforeDestroy()}static create(e={}){return new Be(e)}}class wt extends C{constructor(e={}){super(e),this.name=e.name||"combo",this.placeholder=e.placeholder||e.placeHolder||"Type or select...",this.value=e.value||"",this.options=(e.options||[]).map(t=>typeof t=="string"?{label:t,value:t}:typeof t=="object"&&t!==null?t:{label:t,value:t}),this.allowCustom=e.allowCustom!==!1,this.disabled=e.disabled||!1,this.required=e.required||!1,this.maxHeight=e.maxHeight||300,this.filteredOptions=[...this.options],this.highlightedIndex=-1,this.isOpen=!1,this.template=`
1055
+ `}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._setRange("","")}))}_togglePopover(e){if(this.disabled||this.readonly)return;if(this._popover)this._popover.setAnchor(e);else{const s=this._hasPresets();this._popover=new Ce({anchor:e,classNames:s?"mojo-calendar-popover-with-presets":""})}if(this._popover.isOpen()){this._popover.close();return}this._calendar||(this._calendar=this._buildCalendar()),this._hasPresets()&&!this._presetSidebar&&(this._presetSidebar=this._buildPresetSidebar());const t=this._buildPopoverContent();this._popover.setContent(t),this._popover.open(),this._calendar.render(!1),this._presetSidebar&&this._presetSidebar.render(!1)}_mountInline(){const e=this.element.querySelector("[data-cal-host]");e&&(this._calendar||(this._calendar=this._buildCalendar()),this._hasPresets()&&!this._presetSidebar&&(this._presetSidebar=this._buildPresetSidebar()),e.appendChild(this._buildPopoverContent()),this._calendar.render(!1),this._presetSidebar&&this._presetSidebar.render(!1))}_buildPopoverContent(){const e=document.createElement("div");e.className="mojo-calendar-popover-inner",e.style.display="contents",this._presetSidebar&&e.appendChild(this._presetSidebar.element);const t=document.createElement("div");return t.className="mojo-calendar-cal-wrap",t.appendChild(this._calendar.element),e.appendChild(t),e}_buildCalendar(){const e=new ze({precision:this.precision,mode:"range",months:this.months,startValue:this.currentStartDate||null,endValue:this.currentEndDate||null,min:this.min,max:this.max,firstDay:1,locale:"en-US"});return e.on("range:select",({start:t,end:s})=>{this._setRange(t,s),this.autoApply&&this._popover&&this._popover.isOpen()&&this._popover.close()}),e.on("range:start",()=>{this._presetSidebar&&this._presetSidebar.setActive(-1)}),e}_hasPresets(){return this.presets===!0||this.presets==="default"||Array.isArray(this.presets)&&this.presets.length>0}_buildPresetSidebar(){const e=new as({precision:this.precision,presets:this.presets});return e.on("preset:select",({start:t,end:s})=>{this._setRange(t,s),this._calendar&&this._calendar.setRange(t,s),this.autoApply&&this._popover&&this._popover.isOpen()&&this._popover.close()}),e}_setRange(e,t){const s=this.currentStartDate,i=this.currentEndDate;let r="",n="";if(e){const o=V(e,this.precision);o&&(r=B(o,this.precision))}if(t){const o=V(t,this.precision);o&&(n=B(o,this.precision))}this.currentStartDate=r,this.currentEndDate=n;const a=this.element.querySelector("[data-trigger-text]");if(a){const o=this._displayText();a.textContent=o||this.placeholder,a.classList.toggle("is-empty",!r)}this._updateHidden(),(s!==r||i!==n)&&(this.emit("change",{startDate:r,endDate:n,combined:this.getCombinedValue(),formatted:this._displayText(),oldStartDate:s,oldEndDate:i}),this.emit("range:changed",{startDate:r,endDate:n,oldStartDate:s,oldEndDate:i}))}_updateHidden(){const e=this.element.querySelector("[data-start-value]"),t=this.element.querySelector("[data-end-value]"),s=this.element.querySelector("[data-combined-value]");e&&(e.value=this.currentStartDate),t&&(t.value=this.currentEndDate),s&&(s.value=this.getCombinedValue())}_displayText(){const e=this.currentStartDate?V(this.currentStartDate,this.precision):null,t=this.currentEndDate?V(this.currentEndDate,this.precision):null;if(!e&&!t)return"";const s=this._stripIncompatibleTokens(this.displayFormat);return e&&t?`${ce(e,s)}${this.separator}${ce(t,s)}`:ce(e||t,s)}_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}getCombinedValue(){return!this.currentStartDate&&!this.currentEndDate?"":this.outputFormat==="string"?`${this.currentStartDate}${this.separator}${this.currentEndDate}`:this.outputFormat==="object"?JSON.stringify({start:this.currentStartDate,end:this.currentEndDate}):`${this.currentStartDate}${this.separator}${this.currentEndDate}`}setRange(e,t){this._setRange(e,t),this._calendar&&this._calendar.setRange(e,t)}setStartDate(e){this._setRange(e,this.currentEndDate)}setEndDate(e){this._setRange(this.currentStartDate,e)}getStartDate(){return this.currentStartDate}getEndDate(){return this.currentEndDate}getRange(){return{start:this.currentStartDate,end:this.currentEndDate}}clear(){this._setRange("","")}setMin(e){this.min=e,this._calendar&&this._calendar.setMin(e)}setMax(e){this.max=e,this._calendar&&this._calendar.setMax(e)}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.getCombinedValue()}async setFormValue(e){if(!e){this._setRange("","");return}if(typeof e=="object"&&e.start)this._setRange(e.start,e.end);else if(typeof e=="string"&&e.includes(this.separator.trim())){const[t,s]=e.split(this.separator.trim()).map(i=>i.trim());this._setRange(t,s)}else this._setRange(e,this.currentEndDate)}hasError(){return!1}_inputId(){return this.name?`mojo-daterange-${this.name}-${this.id}`:`mojo-daterange-${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,this._presetSidebar=null,await super.onBeforeDestroy()}static create(e={}){return new Be(e)}}class wt extends C{constructor(e={}){super(e),this.name=e.name||"combo",this.placeholder=e.placeholder||e.placeHolder||"Type or select...",this.value=e.value||"",this.options=(e.options||[]).map(t=>typeof t=="string"?{label:t,value:t}:typeof t=="object"&&t!==null?t:{label:t,value:t}),this.allowCustom=e.allowCustom!==!1,this.disabled=e.disabled||!1,this.required=e.required||!1,this.maxHeight=e.maxHeight||300,this.filteredOptions=[...this.options],this.highlightedIndex=-1,this.isOpen=!1,this.template=`
1056
1056
  <div class="combobox-container">
1057
1057
  <div class="input-group">
1058
1058
  <input type="text"
@@ -1090,7 +1090,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
1090
1090
  {{label}}
1091
1091
  </button>
1092
1092
  {{/items}}
1093
- `}async onInit(){await super.onInit()}async onAfterRender(){if(await super.onAfterRender(),this.input=this.element.querySelector(".combobox-input"),this.dropdown=this.element.querySelector(".combobox-dropdown"),this.dropdownItems=this.element.querySelector('[data-region="dropdown-items"]'),this.noMatchDiv=this.element.querySelector(".combobox-no-match"),this.value&&this.input){const e=this.options.find(t=>t.value===this.value);e?this.input.value=e.label||e.value:this.allowCustom&&(this.input.value=this.value)}this.renderItems(),this.setupEventListeners()}setupEventListeners(){this.input.addEventListener("focus",()=>this.openDropdown()),this.input.addEventListener("input",e=>this.handleInput(e)),this.input.addEventListener("keydown",e=>this.handleKeydown(e)),document.addEventListener("click",e=>{this.element.contains(e.target)||this.closeDropdown()})}handleInput(e){const t=e.target.value.toLowerCase();this.filteredOptions=this.options.filter(s=>(s.label||s.value).toLowerCase().includes(t)),this.highlightedIndex=-1,this.renderItems(),this.openDropdown(),!this.allowCustom&&this.noMatchDiv&&(this.noMatchDiv.style.display=this.filteredOptions.length===0?"block":"none"),this.value=e.target.value,this.emit("change",{value:this.value})}handleKeydown(e){if(!this.isOpen&&(e.key==="ArrowDown"||e.key==="ArrowUp")){this.openDropdown(),e.preventDefault();return}if(this.isOpen)switch(e.key){case"ArrowDown":e.preventDefault(),this.highlightedIndex=Math.min(this.highlightedIndex+1,this.filteredOptions.length-1),this.renderItems(),this.scrollToHighlighted();break;case"ArrowUp":e.preventDefault(),this.highlightedIndex=Math.max(this.highlightedIndex-1,-1),this.renderItems(),this.scrollToHighlighted();break;case"Enter":e.preventDefault(),this.highlightedIndex>=0&&this.selectItem(this.filteredOptions[this.highlightedIndex]);break;case"Escape":e.preventDefault(),this.closeDropdown();break;case"Tab":this.closeDropdown();break}}scrollToHighlighted(){if(this.highlightedIndex<0)return;const t=this.dropdownItems.querySelectorAll(".combobox-item")[this.highlightedIndex];t&&t.scrollIntoView({block:"nearest"})}openDropdown(){this.disabled||this.isOpen||(this.isOpen=!0,this.dropdown.classList.add("show"),this.input.value===""&&(this.filteredOptions=[...this.options],this.renderItems()))}closeDropdown(){this.isOpen&&(this.isOpen=!1,this.dropdown.classList.remove("show"),this.highlightedIndex=-1,this.allowCustom||!this.options.find(t=>t.value===this.input.value||t.label===this.input.value)&&this.input.value!==""&&(this.input.value=this.value))}selectItem(e){const t=e.value,s=e.label||e.value;this.input.value=s,this.value=t,this.closeDropdown(),this.filteredOptions=[...this.options],this.highlightedIndex=-1,this.emit("change",{value:this.value,label:s})}renderItems(){const e=this.filteredOptions.map((s,i)=>({value:s.value,label:s.label||s.value,index:i,highlighted:i===this.highlightedIndex})),t=D.render(this.itemTemplate,{items:e});this.dropdownItems.innerHTML=t}async onActionComboboxInput(e,t){}async onActionComboboxToggle(e,t){this.isOpen?this.closeDropdown():(this.input.focus(),this.openDropdown())}async onActionSelectItem(e,t){const s=t.getAttribute("data-value"),i=this.options.find(r=>r.value===s);i&&this.selectItem(i)}getValue(){return this.value}setValue(e){if(this.value=e,!this.input)return;const t=this.options.find(s=>s.value===e);t?this.input.value=t.label||t.value:this.allowCustom&&(this.input.value=e)}setFormValue(e){this.setValue(e)}getTemplateData(){return{placeholder:this.placeholder,value:this.input?this.input.value:this.value,disabled:this.disabled,required:this.required,maxHeight:this.maxHeight,allowCustom:this.allowCustom}}}const os=["UTC","GMT","America/New_York","America/Chicago","America/Denver","America/Los_Angeles","America/Anchorage","America/Honolulu","America/Phoenix","America/Toronto","America/Vancouver","America/Mexico_City","America/Sao_Paulo","America/Buenos_Aires","America/Bogota","Europe/London","Europe/Dublin","Europe/Paris","Europe/Berlin","Europe/Madrid","Europe/Rome","Europe/Amsterdam","Europe/Stockholm","Europe/Athens","Europe/Moscow","Europe/Istanbul","Africa/Cairo","Africa/Johannesburg","Africa/Lagos","Africa/Nairobi","Asia/Dubai","Asia/Tehran","Asia/Karachi","Asia/Kolkata","Asia/Bangkok","Asia/Singapore","Asia/Hong_Kong","Asia/Shanghai","Asia/Tokyo","Asia/Seoul","Asia/Jakarta","Asia/Manila","Australia/Perth","Australia/Sydney","Australia/Melbourne","Pacific/Auckland","Pacific/Fiji","Pacific/Honolulu"];let vt=!1;class Ct extends C{constructor(e={}){const{name:t="timezone",value:s=null,timezones:i=null,disabled:r=!1,required:n=!1,placeholder:a="Search timezone...",...o}=e;super({tagName:"div",className:"mojo-timezone-select",...o}),this.name=t,this.disabled=r,this.required=n,this.placeholder=a,this.timezones=i,this.currentValue=s||ls(),this._combo=null,this.template='<div data-region="combo-host"></div>'}async onAfterRender(){const e=this.element.querySelector('[data-region="combo-host"]');if(!e)return;const s=this._buildZoneList().map(i=>({value:i,label:this._labelFor(i)}));this._combo=new wt({name:this.name,value:this.currentValue,placeholder:this.placeholder,options:s,allowCustom:!1,disabled:this.disabled,required:this.required,maxHeight:280}),await this._combo.render(!0,e),this._combo.on("change",i=>{const r=i&&i.value?i.value:"";if(r!==this.currentValue){const n=this.currentValue;this.currentValue=r,this.emit("change",{value:r,oldValue:n})}})}_buildZoneList(){if(Array.isArray(this.timezones)&&this.timezones.length)return this.timezones.slice();try{if(typeof Intl<"u"&&typeof Intl.supportedValuesOf=="function"){const e=Intl.supportedValuesOf("timeZone");if(Array.isArray(e)&&e.length)return e.slice()}}catch{}return vt||(vt=!0,console.warn('[TimezoneSelect] Intl.supportedValuesOf("timeZone") unavailable; falling back to curated list.')),os.slice()}_labelFor(e){const t=cs(e);return t?`${e} (UTC${t})`:e}getValue(){return this.currentValue}getFormValue(){return this.currentValue}setValue(e){if(e!==this.currentValue&&(this.currentValue=e||"",this._combo)){this._combo.value=this.currentValue;const t=this._combo.element&&this._combo.element.querySelector(".combobox-input");t&&(t.value=this.currentValue)}}setEnabled(e){this.disabled=!e;const t=this.element.querySelector(".combobox-input"),s=this.element.querySelector(".combobox-toggle");t&&(t.disabled=!e),s&&(s.disabled=!e)}async onBeforeDestroy(){if(this._combo&&typeof this._combo.destroy=="function")try{await this._combo.destroy()}catch{}this._combo=null,await super.onBeforeDestroy()}}function ls(){try{return new Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}catch{return"UTC"}}function cs(c){try{const e=new Date,i=new Intl.DateTimeFormat("en-US",{timeZone:c,timeZoneName:"shortOffset"}).formatToParts(e).find(d=>d.type==="timeZoneName");if(!i)return null;let r=i.value;if(r==="GMT")return"+00:00";r=r.replace(/^GMT/,"");const n=r.match(/^([+-])(\d{1,2})(?::(\d{2}))?$/);if(!n)return r||null;const a=n[1],o=n[2].padStart(2,"0"),l=n[3]||"00";return`${a==="-"?"−":"+"}${o}:${l}`}catch{return null}}class _e extends C{constructor(e={}){const{name:t,value:s="",format:i="24h",step:r=1,min:n=null,max:a=null,placeholder:o=null,disabled:l=!1,readonly:d=!1,required:h=!1,class:u="",inline:m=!1,autoApply:p=!1,timezone:f=!1,timezones:g=null,outputFormat:b="iso",showFooter:y=!0,...w}=e;super({tagName:"div",className:`mojo-time-picker ${u}`.trim(),...w}),this.name=t,this.format=i==="12h"?"12h":"24h",this.step=Math.max(1,parseInt(r,10)||1),this.min=n,this.max=a,this.placeholder=o??(this.format==="12h"?"h:mm AM/PM":"HH:MM"),this.disabled=l,this.readonly=d,this.required=h,this.inline=m,this.autoApply=p,this.showFooter=y!==!1,this.timezone=f===!0||Array.isArray(f),this.timezoneList=Array.isArray(f)?f:g,this.outputFormat=["object","iana","iso"].includes(b)?b:"iso";const x=this._parseInitial(s);this.currentTime=x.time,this.currentTimezone=x.timezone||(this.timezone?ds():null),this._popover=null,this._tzSelect=null,this._spinner=null}_parseInitial(e){if(e==null||e==="")return{time:null,timezone:null};if(typeof e=="object"&&!Array.isArray(e))return{time:e.time?W(e.time):null,timezone:e.timezone||null};const t=String(e).trim(),s=t.match(/^(\d{1,2}:\d{2})(Z|[+-]\d{2}:?\d{2})$/);if(s){const r=s[2];let n=null;return r==="Z"?n="+00:00":/^[+-]\d{4}$/.test(r)?n=`${r.slice(0,3)}:${r.slice(3)}`:n=r,{time:W(s[1]),timezone:n}}const i=t.indexOf(" ");if(i>-1){const r=t.slice(i+1).trim();return/^(am|pm)$/i.test(r)?{time:W(t),timezone:null}:{time:W(t.slice(0,i)),timezone:r||null}}return{time:W(t),timezone:null}}async renderTemplate(){const e=this._inputId(),t=this._displayText(),s=!this.currentTime,i=this._serialize();return this.inline?`
1093
+ `}async onInit(){await super.onInit()}async onAfterRender(){if(await super.onAfterRender(),this.input=this.element.querySelector(".combobox-input"),this.dropdown=this.element.querySelector(".combobox-dropdown"),this.dropdownItems=this.element.querySelector('[data-region="dropdown-items"]'),this.noMatchDiv=this.element.querySelector(".combobox-no-match"),this.value&&this.input){const e=this.options.find(t=>t.value===this.value);e?this.input.value=e.label||e.value:this.allowCustom&&(this.input.value=this.value)}this.renderItems(),this.setupEventListeners()}setupEventListeners(){this.input.addEventListener("focus",()=>this.openDropdown()),this.input.addEventListener("input",e=>this.handleInput(e)),this.input.addEventListener("keydown",e=>this.handleKeydown(e)),document.addEventListener("click",e=>{this.element.contains(e.target)||this.closeDropdown()})}handleInput(e){const t=e.target.value.toLowerCase();this.filteredOptions=this.options.filter(s=>(s.label||s.value).toLowerCase().includes(t)),this.highlightedIndex=-1,this.renderItems(),this.openDropdown(),!this.allowCustom&&this.noMatchDiv&&(this.noMatchDiv.style.display=this.filteredOptions.length===0?"block":"none"),this.value=e.target.value,this.emit("change",{value:this.value})}handleKeydown(e){if(!this.isOpen&&(e.key==="ArrowDown"||e.key==="ArrowUp")){this.openDropdown(),e.preventDefault();return}if(this.isOpen)switch(e.key){case"ArrowDown":e.preventDefault(),this.highlightedIndex=Math.min(this.highlightedIndex+1,this.filteredOptions.length-1),this.renderItems(),this.scrollToHighlighted();break;case"ArrowUp":e.preventDefault(),this.highlightedIndex=Math.max(this.highlightedIndex-1,-1),this.renderItems(),this.scrollToHighlighted();break;case"Enter":e.preventDefault(),this.highlightedIndex>=0&&this.selectItem(this.filteredOptions[this.highlightedIndex]);break;case"Escape":e.preventDefault(),this.closeDropdown();break;case"Tab":this.closeDropdown();break}}scrollToHighlighted(){if(this.highlightedIndex<0)return;const t=this.dropdownItems.querySelectorAll(".combobox-item")[this.highlightedIndex];t&&t.scrollIntoView({block:"nearest"})}openDropdown(){this.disabled||this.isOpen||(this.isOpen=!0,this.dropdown.classList.add("show"),this.input.value===""&&(this.filteredOptions=[...this.options],this.renderItems()))}closeDropdown(){this.isOpen&&(this.isOpen=!1,this.dropdown.classList.remove("show"),this.highlightedIndex=-1,this.allowCustom||!this.options.find(t=>t.value===this.input.value||t.label===this.input.value)&&this.input.value!==""&&(this.input.value=this.value))}selectItem(e){const t=e.value,s=e.label||e.value;this.input.value=s,this.value=t,this.closeDropdown(),this.filteredOptions=[...this.options],this.highlightedIndex=-1,this.emit("change",{value:this.value,label:s})}renderItems(){const e=this.filteredOptions.map((s,i)=>({value:s.value,label:s.label||s.value,index:i,highlighted:i===this.highlightedIndex})),t=D.render(this.itemTemplate,{items:e});this.dropdownItems.innerHTML=t}async onActionComboboxInput(e,t){}async onActionComboboxToggle(e,t){this.isOpen?this.closeDropdown():(this.input.focus(),this.openDropdown())}async onActionSelectItem(e,t){const s=t.getAttribute("data-value"),i=this.options.find(r=>r.value===s);i&&this.selectItem(i)}getValue(){return this.value}setValue(e){if(this.value=e,!this.input)return;const t=this.options.find(s=>s.value===e);t?this.input.value=t.label||t.value:this.allowCustom&&(this.input.value=e)}setFormValue(e){this.setValue(e)}getTemplateData(){return{placeholder:this.placeholder,value:this.input?this.input.value:this.value,disabled:this.disabled,required:this.required,maxHeight:this.maxHeight,allowCustom:this.allowCustom}}}const os=["UTC","GMT","America/New_York","America/Chicago","America/Denver","America/Los_Angeles","America/Anchorage","America/Honolulu","America/Phoenix","America/Toronto","America/Vancouver","America/Mexico_City","America/Sao_Paulo","America/Buenos_Aires","America/Bogota","Europe/London","Europe/Dublin","Europe/Paris","Europe/Berlin","Europe/Madrid","Europe/Rome","Europe/Amsterdam","Europe/Stockholm","Europe/Athens","Europe/Moscow","Europe/Istanbul","Africa/Cairo","Africa/Johannesburg","Africa/Lagos","Africa/Nairobi","Asia/Dubai","Asia/Tehran","Asia/Karachi","Asia/Kolkata","Asia/Bangkok","Asia/Singapore","Asia/Hong_Kong","Asia/Shanghai","Asia/Tokyo","Asia/Seoul","Asia/Jakarta","Asia/Manila","Australia/Perth","Australia/Sydney","Australia/Melbourne","Pacific/Auckland","Pacific/Fiji","Pacific/Honolulu"];let vt=!1;class Ct extends C{constructor(e={}){const{name:t="timezone",value:s=null,timezones:i=null,disabled:r=!1,required:n=!1,placeholder:a="Search timezone...",...o}=e;super({tagName:"div",className:"mojo-timezone-select",...o}),this.name=t,this.disabled=r,this.required=n,this.placeholder=a,this.timezones=i,this.currentValue=s||ls(),this._combo=null,this.template='<div data-region="combo-host"></div>'}async onAfterRender(){const e=this.element.querySelector('[data-region="combo-host"]');if(!e)return;const s=this._buildZoneList().map(i=>({value:i,label:this._labelFor(i)}));this._combo=new wt({name:this.name,value:this.currentValue,placeholder:this.placeholder,options:s,allowCustom:!1,disabled:this.disabled,required:this.required,maxHeight:280}),await this._combo.render(!0,e),this._combo.on("change",i=>{const r=i&&i.value?i.value:"";if(r!==this.currentValue){const n=this.currentValue;this.currentValue=r,this.emit("change",{value:r,oldValue:n})}})}_buildZoneList(){if(Array.isArray(this.timezones)&&this.timezones.length)return this.timezones.slice();try{if(typeof Intl<"u"&&typeof Intl.supportedValuesOf=="function"){const e=Intl.supportedValuesOf("timeZone");if(Array.isArray(e)&&e.length)return e.slice()}}catch{}return vt||(vt=!0,console.warn('[TimezoneSelect] Intl.supportedValuesOf("timeZone") unavailable; falling back to curated list.')),os.slice()}_labelFor(e){const t=cs(e);return t?`${e} (UTC${t})`:e}getValue(){return this.currentValue}getFormValue(){return this.currentValue}setValue(e){if(e!==this.currentValue&&(this.currentValue=e||"",this._combo)){this._combo.value=this.currentValue;const t=this._combo.element&&this._combo.element.querySelector(".combobox-input");t&&(t.value=this.currentValue)}}setEnabled(e){this.disabled=!e;const t=this.element.querySelector(".combobox-input"),s=this.element.querySelector(".combobox-toggle");t&&(t.disabled=!e),s&&(s.disabled=!e)}async onBeforeDestroy(){if(this._combo&&typeof this._combo.destroy=="function")try{await this._combo.destroy()}catch{}this._combo=null,await super.onBeforeDestroy()}}function ls(){try{return new Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}catch{return"UTC"}}function cs(c){try{const e=new Date,i=new Intl.DateTimeFormat("en-US",{timeZone:c,timeZoneName:"shortOffset"}).formatToParts(e).find(d=>d.type==="timeZoneName");if(!i)return null;let r=i.value;if(r==="GMT")return"+00:00";r=r.replace(/^GMT/,"");const n=r.match(/^([+-])(\d{1,2})(?::(\d{2}))?$/);if(!n)return r||null;const a=n[1],o=n[2].padStart(2,"0"),l=n[3]||"00";return`${a==="-"?"−":"+"}${o}:${l}`}catch{return null}}class _e extends C{constructor(e={}){const{name:t,value:s="",format:i="24h",step:r=1,min:n=null,max:a=null,placeholder:o=null,disabled:l=!1,readonly:d=!1,required:h=!1,class:u="",inline:m=!1,autoApply:p=!1,timezone:f=!1,timezones:g=null,outputFormat:b="iso",showFooter:y=!0,...v}=e;super({tagName:"div",className:`mojo-time-picker ${u}`.trim(),...v}),this.name=t,this.format=i==="12h"?"12h":"24h",this.step=Math.max(1,parseInt(r,10)||1),this.min=n,this.max=a,this.placeholder=o??(this.format==="12h"?"h:mm AM/PM":"HH:MM"),this.disabled=l,this.readonly=d,this.required=h,this.inline=m,this.autoApply=p,this.showFooter=y!==!1,this.timezone=f===!0||Array.isArray(f),this.timezoneList=Array.isArray(f)?f:g,this.outputFormat=["object","iana","iso"].includes(b)?b:"iso";const x=this._parseInitial(s);this.currentTime=x.time,this.currentTimezone=x.timezone||(this.timezone?ds():null),this._popover=null,this._tzSelect=null,this._spinner=null}_parseInitial(e){if(e==null||e==="")return{time:null,timezone:null};if(typeof e=="object"&&!Array.isArray(e))return{time:e.time?W(e.time):null,timezone:e.timezone||null};const t=String(e).trim(),s=t.match(/^(\d{1,2}:\d{2})(Z|[+-]\d{2}:?\d{2})$/);if(s){const r=s[2];let n=null;return r==="Z"?n="+00:00":/^[+-]\d{4}$/.test(r)?n=`${r.slice(0,3)}:${r.slice(3)}`:n=r,{time:W(s[1]),timezone:n}}const i=t.indexOf(" ");if(i>-1){const r=t.slice(i+1).trim();return/^(am|pm)$/i.test(r)?{time:W(t),timezone:null}:{time:W(t.slice(0,i)),timezone:r||null}}return{time:W(t),timezone:null}}async renderTemplate(){const e=this._inputId(),t=this._displayText(),s=!this.currentTime,i=this._serialize();return this.inline?`
1094
1094
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(i)}" data-hidden-value />
1095
1095
  <div data-time-host class="mojo-time-picker-inline${this.hasError()?" is-invalid":""}"></div>
1096
1096
  `:`
@@ -1102,7 +1102,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
1102
1102
  ${!this.required&&!this.disabled&&!this.readonly?'<button type="button" class="mojo-time-trigger-clear" data-clear aria-label="Clear" tabindex="-1">&#x2715;</button>':""}
1103
1103
  </button>
1104
1104
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(i)}" data-hidden-value />
1105
- `}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 Ce({anchor:e,classNames:"mojo-time-popover"}),this._popover.isOpen()){this._popover.close();return}const t=this._buildSpinnerContent();this._popover.setContent(t),this._popover.open(),this.timezone&&this._mountTimezoneSelect()}_mountInline(){const e=this.element.querySelector("[data-time-host]");if(!e)return;const t=this._buildSpinnerContent();e.appendChild(t),this.timezone&&this._mountTimezoneSelect()}_buildSpinnerContent(){const e=document.createElement("div");e.className="mojo-time-popover-inner";const t=document.createElement("div");t.className="mojo-time-stepper-row";const s=this.currentTime||{hours:0,minutes:0},i=this._hourDisplay(s.hours);t.appendChild(this._buildStepper("hour",i,"Hour"));const r=document.createElement("div");if(r.className="mojo-time-stepper-sep",r.textContent=":",t.appendChild(r),t.appendChild(this._buildStepper("minute",Ue(s.minutes),"Minute")),this.format==="12h"&&t.appendChild(this._buildAmPmToggle(s.hours)),e.appendChild(t),this.timezone){const n=document.createElement("div");n.className="mojo-time-tz-host",n.setAttribute("data-tz-host",""),e.appendChild(n)}if(this.showFooter){const n=document.createElement("div");n.className="mojo-time-foot";const a=document.createElement("button");a.type="button",a.className="btn btn-link btn-sm mojo-time-now",a.textContent="Now",a.addEventListener("click",l=>{l.preventDefault();const d=new Date;this._commitTime({hours:d.getHours(),minutes:d.getMinutes()}),this._refreshSpinnerDisplay()}),n.appendChild(a);const o=document.createElement("button");o.type="button",o.className="btn btn-primary btn-sm mojo-time-apply",o.textContent="Set",o.addEventListener("click",l=>{l.preventDefault(),this.currentTime||this._commitTime({hours:0,minutes:0}),this._popover&&this._popover.isOpen()&&this._popover.close()}),n.appendChild(o),e.appendChild(n)}return this._spinner=e,e}_buildStepper(e,t,s){const i=document.createElement("div");i.className=`mojo-time-stepper mojo-time-stepper-${e}`;const r=document.createElement("button");r.type="button",r.className="mojo-time-stepper-btn",r.setAttribute("aria-label",`Increase ${s.toLowerCase()}`),r.innerHTML='<i class="bi bi-chevron-up" aria-hidden="true"></i>',r.addEventListener("click",l=>{l.preventDefault(),this._step(e,1)});const n=document.createElement("input");n.type="text",n.className="mojo-time-stepper-value",n.value=t,n.setAttribute("inputmode","numeric"),n.setAttribute("aria-label",s),n.maxLength=2,n.addEventListener("focus",()=>n.select()),n.addEventListener("keydown",l=>this._onValueKey(e,n,l)),n.addEventListener("blur",()=>this._onValueBlur(e,n));const a=document.createElement("button");a.type="button",a.className="mojo-time-stepper-btn",a.setAttribute("aria-label",`Decrease ${s.toLowerCase()}`),a.innerHTML='<i class="bi bi-chevron-down" aria-hidden="true"></i>',a.addEventListener("click",l=>{l.preventDefault(),this._step(e,-1)});const o=document.createElement("div");return o.className="mojo-time-stepper-label",o.textContent=s,i.appendChild(r),i.appendChild(n),i.appendChild(a),i.appendChild(o),i}_buildAmPmToggle(e){const t=document.createElement("div");t.className="mojo-time-ampm";const s=e>=12,i=document.createElement("button");i.type="button",i.className=`mojo-time-ampm-btn${s?"":" is-active"}`,i.textContent="AM",i.addEventListener("click",n=>{n.preventDefault(),this._setAmPm("am")});const r=document.createElement("button");return r.type="button",r.className=`mojo-time-ampm-btn${s?" is-active":""}`,r.textContent="PM",r.addEventListener("click",n=>{n.preventDefault(),this._setAmPm("pm")}),t.appendChild(i),t.appendChild(r),t}_mountTimezoneSelect(){if(!this.timezone)return;const e=this.inline?this.element.querySelector("[data-time-host] [data-tz-host]"):this._spinner&&this._spinner.querySelector("[data-tz-host]");if(e){if(this._tzSelect)try{this._tzSelect.destroy&&this._tzSelect.destroy()}catch{}e.innerHTML="",this._tzSelect=new Ct({name:"timezone",value:this.currentTimezone,timezones:this.timezoneList}),this._tzSelect.render(!0,e),this._tzSelect.on("change",({value:t})=>{const s=this.currentTimezone;this.currentTimezone=t||null,s!==this.currentTimezone&&this._syncOutputs()})}}_step(e,t){const s=this.currentTime||{hours:0,minutes:0};let{hours:i,minutes:r}=s;if(e==="hour")i=((i+t)%24+24)%24;else{const a=i*60+r,o=t*this.step,l=((a+o)%1440+1440)%1440;i=Math.floor(l/60),r=l%60}const n=this._clampToBounds({hours:i,minutes:r});this._commitTime(n),this._refreshSpinnerDisplay()}_setAmPm(e){if(!this.currentTime)this._commitTime({hours:e==="pm"?12:0,minutes:0});else{const{hours:t,minutes:s}=this.currentTime;let i=t;e==="am"&&i>=12?i-=12:e==="pm"&&i<12&&(i+=12),this._commitTime(this._clampToBounds({hours:i,minutes:s}))}this._refreshSpinnerDisplay()}_onValueKey(e,t,s){s.key==="ArrowUp"?(s.preventDefault(),this._step(e,1),t.focus(),t.select()):s.key==="ArrowDown"?(s.preventDefault(),this._step(e,-1),t.focus(),t.select()):s.key==="Enter"?(s.preventDefault(),t.blur()):s.key==="Tab"||!/^[0-9]$/.test(s.key)&&!["Backspace","Delete","ArrowLeft","ArrowRight","Home","End"].includes(s.key)&&s.preventDefault()}_onValueBlur(e,t){const s=(t.value||"").replace(/\D/g,"");if(s===""){this._refreshSpinnerDisplay();return}let i=parseInt(s,10);const r=this.currentTime||{hours:0,minutes:0};let{hours:n,minutes:a}=r;if(e==="hour")if(this.format==="12h"){i<1&&(i=1),i>12&&(i=12);const o=r.hours>=12;i===12?n=o?12:0:n=o?i+12:i}else i<0&&(i=0),i>23&&(i=23),n=i;else i<0&&(i=0),i>59&&(i=59),a=i;this._commitTime(this._clampToBounds({hours:n,minutes:a})),this._refreshSpinnerDisplay()}_hourDisplay(e){if(this.format==="12h"){let t=e%12;return t===0&&(t=12),String(t)}return Ue(e)}_refreshSpinnerDisplay(){if(!this._spinner)return;const e=this.currentTime||{hours:0,minutes:0},t=this._spinner.querySelector(".mojo-time-stepper-hour .mojo-time-stepper-value"),s=this._spinner.querySelector(".mojo-time-stepper-minute .mojo-time-stepper-value");if(t&&(t.value=this._hourDisplay(e.hours)),s&&(s.value=Ue(e.minutes)),this.format==="12h"){const i=e.hours>=12,r=this._spinner.querySelector(".mojo-time-ampm-btn:nth-child(1)"),n=this._spinner.querySelector(".mojo-time-ampm-btn:nth-child(2)");r&&r.classList.toggle("is-active",!i),n&&n.classList.toggle("is-active",i)}}_clampToBounds(e){const t=this.min?W(this.min):null,s=this.max?W(this.max):null;return t&&ht(e,t)<0?t:s&&ht(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=G(this.currentTime,"24h");if(!this.timezone||!this.currentTimezone)return e;if(this.outputFormat==="iana")return`${e} ${this.currentTimezone}`;const t=ut(this.currentTimezone,new Date);return t?`${e}${t}`:e}_displayText(){if(!this.currentTime)return"";const e=G(this.currentTime,this.format);return this.timezone&&this.currentTimezone?`${e} ${this.currentTimezone}`:e}getValue(){return this.currentTime?this.timezone&&this.outputFormat==="object"?{time:G(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 ts(e,t)}static create(e={}){return new _e(e)}}function Ue(c){return c<10?"0"+c:String(c)}function ds(){try{return new Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}catch{return"UTC"}}const hs="MMM DD, YYYY";class Ye 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:w=!1,timezone:x=!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||hs,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=w,this.timezone=x===!0||Array.isArray(x),this.timezoneList=Array.isArray(x)?x: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?St():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)?mt(e)||{date:null,time:null,timezone:null}:mt(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?`
1105
+ `}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 Ce({anchor:e,classNames:"mojo-time-popover"}),this._popover.isOpen()){this._popover.close();return}const t=this._buildSpinnerContent();this._popover.setContent(t),this._popover.open(),this.timezone&&this._mountTimezoneSelect()}_mountInline(){const e=this.element.querySelector("[data-time-host]");if(!e)return;const t=this._buildSpinnerContent();e.appendChild(t),this.timezone&&this._mountTimezoneSelect()}_buildSpinnerContent(){const e=document.createElement("div");e.className="mojo-time-popover-inner";const t=document.createElement("div");t.className="mojo-time-stepper-row";const s=this.currentTime||{hours:0,minutes:0},i=this._hourDisplay(s.hours);t.appendChild(this._buildStepper("hour",i,"Hour"));const r=document.createElement("div");if(r.className="mojo-time-stepper-sep",r.textContent=":",t.appendChild(r),t.appendChild(this._buildStepper("minute",Ue(s.minutes),"Minute")),this.format==="12h"&&t.appendChild(this._buildAmPmToggle(s.hours)),e.appendChild(t),this.timezone){const n=document.createElement("div");n.className="mojo-time-tz-host",n.setAttribute("data-tz-host",""),e.appendChild(n)}if(this.showFooter){const n=document.createElement("div");n.className="mojo-time-foot";const a=document.createElement("button");a.type="button",a.className="btn btn-link btn-sm mojo-time-now",a.textContent="Now",a.addEventListener("click",l=>{l.preventDefault();const d=new Date;this._commitTime({hours:d.getHours(),minutes:d.getMinutes()}),this._refreshSpinnerDisplay()}),n.appendChild(a);const o=document.createElement("button");o.type="button",o.className="btn btn-primary btn-sm mojo-time-apply",o.textContent="Set",o.addEventListener("click",l=>{l.preventDefault(),this.currentTime||this._commitTime({hours:0,minutes:0}),this._popover&&this._popover.isOpen()&&this._popover.close()}),n.appendChild(o),e.appendChild(n)}return this._spinner=e,e}_buildStepper(e,t,s){const i=document.createElement("div");i.className=`mojo-time-stepper mojo-time-stepper-${e}`;const r=document.createElement("button");r.type="button",r.className="mojo-time-stepper-btn",r.setAttribute("aria-label",`Increase ${s.toLowerCase()}`),r.innerHTML='<i class="bi bi-chevron-up" aria-hidden="true"></i>',r.addEventListener("click",l=>{l.preventDefault(),this._step(e,1)});const n=document.createElement("input");n.type="text",n.className="mojo-time-stepper-value",n.value=t,n.setAttribute("inputmode","numeric"),n.setAttribute("aria-label",s),n.maxLength=2,n.addEventListener("focus",()=>n.select()),n.addEventListener("keydown",l=>this._onValueKey(e,n,l)),n.addEventListener("blur",()=>this._onValueBlur(e,n));const a=document.createElement("button");a.type="button",a.className="mojo-time-stepper-btn",a.setAttribute("aria-label",`Decrease ${s.toLowerCase()}`),a.innerHTML='<i class="bi bi-chevron-down" aria-hidden="true"></i>',a.addEventListener("click",l=>{l.preventDefault(),this._step(e,-1)});const o=document.createElement("div");return o.className="mojo-time-stepper-label",o.textContent=s,i.appendChild(r),i.appendChild(n),i.appendChild(a),i.appendChild(o),i}_buildAmPmToggle(e){const t=document.createElement("div");t.className="mojo-time-ampm";const s=e>=12,i=document.createElement("button");i.type="button",i.className=`mojo-time-ampm-btn${s?"":" is-active"}`,i.textContent="AM",i.addEventListener("click",n=>{n.preventDefault(),this._setAmPm("am")});const r=document.createElement("button");return r.type="button",r.className=`mojo-time-ampm-btn${s?" is-active":""}`,r.textContent="PM",r.addEventListener("click",n=>{n.preventDefault(),this._setAmPm("pm")}),t.appendChild(i),t.appendChild(r),t}_mountTimezoneSelect(){if(!this.timezone)return;const e=this.inline?this.element.querySelector("[data-time-host] [data-tz-host]"):this._spinner&&this._spinner.querySelector("[data-tz-host]");if(e){if(this._tzSelect)try{this._tzSelect.destroy&&this._tzSelect.destroy()}catch{}e.innerHTML="",this._tzSelect=new Ct({name:"timezone",value:this.currentTimezone,timezones:this.timezoneList}),this._tzSelect.render(!0,e),this._tzSelect.on("change",({value:t})=>{const s=this.currentTimezone;this.currentTimezone=t||null,s!==this.currentTimezone&&this._syncOutputs()})}}_step(e,t){const s=this.currentTime||{hours:0,minutes:0};let{hours:i,minutes:r}=s;if(e==="hour")i=((i+t)%24+24)%24;else{const a=i*60+r,o=t*this.step,l=((a+o)%1440+1440)%1440;i=Math.floor(l/60),r=l%60}const n=this._clampToBounds({hours:i,minutes:r});this._commitTime(n),this._refreshSpinnerDisplay()}_setAmPm(e){if(!this.currentTime)this._commitTime({hours:e==="pm"?12:0,minutes:0});else{const{hours:t,minutes:s}=this.currentTime;let i=t;e==="am"&&i>=12?i-=12:e==="pm"&&i<12&&(i+=12),this._commitTime(this._clampToBounds({hours:i,minutes:s}))}this._refreshSpinnerDisplay()}_onValueKey(e,t,s){s.key==="ArrowUp"?(s.preventDefault(),this._step(e,1),t.focus(),t.select()):s.key==="ArrowDown"?(s.preventDefault(),this._step(e,-1),t.focus(),t.select()):s.key==="Enter"?(s.preventDefault(),t.blur()):s.key==="Tab"||!/^[0-9]$/.test(s.key)&&!["Backspace","Delete","ArrowLeft","ArrowRight","Home","End"].includes(s.key)&&s.preventDefault()}_onValueBlur(e,t){const s=(t.value||"").replace(/\D/g,"");if(s===""){this._refreshSpinnerDisplay();return}let i=parseInt(s,10);const r=this.currentTime||{hours:0,minutes:0};let{hours:n,minutes:a}=r;if(e==="hour")if(this.format==="12h"){i<1&&(i=1),i>12&&(i=12);const o=r.hours>=12;i===12?n=o?12:0:n=o?i+12:i}else i<0&&(i=0),i>23&&(i=23),n=i;else i<0&&(i=0),i>59&&(i=59),a=i;this._commitTime(this._clampToBounds({hours:n,minutes:a})),this._refreshSpinnerDisplay()}_hourDisplay(e){if(this.format==="12h"){let t=e%12;return t===0&&(t=12),String(t)}return Ue(e)}_refreshSpinnerDisplay(){if(!this._spinner)return;const e=this.currentTime||{hours:0,minutes:0},t=this._spinner.querySelector(".mojo-time-stepper-hour .mojo-time-stepper-value"),s=this._spinner.querySelector(".mojo-time-stepper-minute .mojo-time-stepper-value");if(t&&(t.value=this._hourDisplay(e.hours)),s&&(s.value=Ue(e.minutes)),this.format==="12h"){const i=e.hours>=12,r=this._spinner.querySelector(".mojo-time-ampm-btn:nth-child(1)"),n=this._spinner.querySelector(".mojo-time-ampm-btn:nth-child(2)");r&&r.classList.toggle("is-active",!i),n&&n.classList.toggle("is-active",i)}}_clampToBounds(e){const t=this.min?W(this.min):null,s=this.max?W(this.max):null;return t&&ht(e,t)<0?t:s&&ht(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=G(this.currentTime,"24h");if(!this.timezone||!this.currentTimezone)return e;if(this.outputFormat==="iana")return`${e} ${this.currentTimezone}`;const t=ut(this.currentTimezone,new Date);return t?`${e}${t}`:e}_displayText(){if(!this.currentTime)return"";const e=G(this.currentTime,this.format);return this.timezone&&this.currentTimezone?`${e} ${this.currentTimezone}`:e}getValue(){return this.currentTime?this.timezone&&this.outputFormat==="object"?{time:G(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 ts(e,t)}static create(e={}){return new _e(e)}}function Ue(c){return c<10?"0"+c:String(c)}function ds(){try{return new Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}catch{return"UTC"}}const hs="MMM DD, YYYY";class Ye 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:x=!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||hs,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=x===!0||Array.isArray(x),this.timezoneList=Array.isArray(x)?x: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?St():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)?mt(e)||{date:null,time:null,timezone:null}:mt(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?`
1106
1106
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(i)}" data-hidden-value />
1107
1107
  <div data-dt-host class="mojo-datetime-picker-inline${this.hasError()?" is-invalid":""}"></div>
1108
1108
  `:`
@@ -1186,7 +1186,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
1186
1186
  <i class="bi bi-search me-1"></i>
1187
1187
  No matching options found.
1188
1188
  </div>
1189
- `}highlightMatch(e){if(!this.inputValue)return this.escapeHtml(e);const t=this.escapeHtml(e),s=new RegExp(`(${this.escapeRegex(this.inputValue)})`,"gi");return t.replace(s,'<mark class="bg-warning bg-opacity-25">$1</mark>')}async onAfterRender(){await super.onAfterRender(),this.updateFilteredOptions(),this.handleOutsideClick=e=>{this.element&&!this.element.contains(e.target)&&this.closeDropdown()},document.addEventListener("click",this.handleOutsideClick)}async onChangeInputChange(e,t){this.inputValue=t.value,this.updateFilteredOptions(),this.inputValue.length>=this.minChars?this.openDropdown():this.closeDropdown(),this.highlightedIndex=-1,await this.updateDropdownDisplay()}async onActionInputKeydown(e,t){switch(e.key){case"ArrowDown":e.preventDefault(),this.isOpen?this.highlightNext():this.openDropdown(),await this.updateDropdownDisplay();break;case"ArrowUp":e.preventDefault(),this.isOpen&&(this.highlightPrevious(),await this.updateDropdownDisplay());break;case"Enter":e.preventDefault(),this.isOpen&&this.highlightedIndex>=0?await this.selectHighlightedOption():this.allowCustom&&this.inputValue&&await this.selectCustomValue(this.inputValue);break;case"Escape":e.preventDefault(),this.closeDropdown();const s=this.element.querySelector(".combo-input-field");s&&(s.value=this.getDisplayValue(this.currentValue),this.inputValue=s.value);break;case"Tab":this.isOpen&&this.closeDropdown();break}}async onActionToggleDropdown(e,t){if(e.preventDefault(),e.stopPropagation(),this.isOpen)this.closeDropdown();else{this.inputValue="";const s=this.element.querySelector(".combo-input-field");s&&(s.value="",s.focus()),this.updateFilteredOptions(),this.openDropdown(),await this.updateDropdownDisplay()}}async onActionSelectOption(e,t){e.preventDefault(),e.stopPropagation();const s=parseInt(t.getAttribute("data-option-index"));s>=0&&s<this.filteredOptions.length&&await this.selectOption(this.filteredOptions[s])}openDropdown(){this.isOpen=!0;const e=this.element?.querySelector(".combo-dropdown");e&&e.classList.add("show");const t=this.element?.querySelector(".combo-input-field");t&&t.setAttribute("aria-expanded","true")}closeDropdown(){this.isOpen=!1,this.highlightedIndex=-1;const e=this.element?.querySelector(".combo-dropdown");e&&e.classList.remove("show");const t=this.element?.querySelector(".combo-input-field");t&&t.setAttribute("aria-expanded","false")}updateFilteredOptions(){const e=this.inputValue.toLowerCase().trim();if(!e){this.filteredOptions=[...this.options];return}this.filteredOptions=this.options.filter(t=>{const s=t.label.toLowerCase().includes(e),i=String(t.value).toLowerCase().includes(e),r=t.description?.toLowerCase().includes(e);return s||i||r}),this.filteredOptions.sort((t,s)=>{const i=t.label.toLowerCase()===e,r=s.label.toLowerCase()===e;if(i&&!r)return-1;if(!i&&r)return 1;const n=t.label.toLowerCase().startsWith(e),a=s.label.toLowerCase().startsWith(e);return n&&!a?-1:!n&&a?1:0})}async updateDropdownDisplay(){const e=this.element?.querySelector(".combo-dropdown");if(e&&(e.innerHTML=this.renderDropdownContent(),this.highlightedIndex>=0)){const t=e.querySelector(".combo-option.active");t&&t.scrollIntoView({block:"nearest"})}}highlightNext(){this.filteredOptions.length!==0&&(this.highlightedIndex=(this.highlightedIndex+1)%Math.min(this.filteredOptions.length,this.maxSuggestions))}highlightPrevious(){this.filteredOptions.length!==0&&(this.highlightedIndex=this.highlightedIndex<=0?Math.min(this.filteredOptions.length,this.maxSuggestions)-1:this.highlightedIndex-1)}async selectHighlightedOption(){this.highlightedIndex>=0&&this.highlightedIndex<this.filteredOptions.length&&await this.selectOption(this.filteredOptions[this.highlightedIndex])}async selectOption(e){this.currentValue=e.value,this.inputValue=e.label,this.selectedOption=e;const t=this.element?.querySelector(".combo-input-field");t&&(t.value=e.label);const s=this.element?.querySelector(".combo-input-hidden");s&&(s.value=e.value),this.closeDropdown(),this.emit("select",{option:e,value:e.value,meta:e.meta}),this.emit("change",{value:e.value,option:e,meta:e.meta}),typeof this.onSelectCallback=="function"&&this.onSelectCallback(e),typeof this.onChangeCallback=="function"&&this.onChangeCallback(e.value)}async selectCustomValue(e){if(!this.allowCustom)return;this.currentValue=e,this.inputValue=e,this.selectedOption=null;const t=this.element?.querySelector(".combo-input-hidden");t&&(t.value=e),this.closeDropdown(),this.emit("custom",{value:e}),this.emit("change",{value:e,custom:!0}),typeof this.onChangeCallback=="function"&&this.onChangeCallback(e)}getValue(){return this.currentValue}async setValue(e){this.currentValue=e,this.selectedOption=this.findOptionByValue(e),this.inputValue=this.getDisplayValue(e);const t=this.element?.querySelector(".combo-input-field");t&&(t.value=this.inputValue);const s=this.element?.querySelector(".combo-input-hidden");s&&(s.value=e),this.updateFilteredOptions()}getSelectedOption(){return this.selectedOption}async setOptions(e){this.options=this.normalizeOptions(e),this.updateFilteredOptions(),this.isOpen&&await this.updateDropdownDisplay()}setEnabled(e){this.disabled=!e;const t=this.element?.querySelector(".combo-input-field");t&&(t.disabled=this.disabled);const s=this.element?.querySelector(".combo-toggle");s&&(s.disabled=this.disabled)}setReadonly(e){this.readonly=e;const t=this.element?.querySelector(".combo-input-field");t&&(e?t.setAttribute("readonly",""):t.removeAttribute("readonly"))}focus(){const e=this.element?.querySelector(".combo-input-field");e&&e.focus()}async clear(){await this.setValue(""),this.inputValue="";const e=this.element?.querySelector(".combo-input-field");e&&(e.value=""),this.emit("clear")}getFormValue(){return this.allowCustom&&this.inputValue&&this.inputValue!==this.getDisplayValue(this.currentValue)?this.inputValue:this.currentValue}async setFormValue(e){await this.setValue(e)}escapeHtml(e){if(e==null)return"";const t=document.createElement("div");return t.textContent=String(e),t.innerHTML}escapeRegex(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}async onBeforeDestroy(){this.handleOutsideClick&&document.removeEventListener("click",this.handleOutsideClick),await super.onBeforeDestroy()}static create(e={}){return new We(e)}}class Q extends C{constructor(e={}){const{formConfig:t=e.config,fields:s,model:i=null,data:r={},defaults:n=null,errors:a={},fileHandling:o="base64",autosaveModelField:l=!1,...d}=e;super({tagName:"div",className:"form-view",enableTooltips:!0,...d}),Z.onFormViewInit?.(this),this.model=i,this.defaults=n||r,this._originalData=r,this.errors=a,this.loading=!1,this.fileHandling=o,this.autosaveModelField=l,this.customComponents=new Map,this.fieldStatusManagers=new Map,this.saveTimeouts=new Map,this.pendingSaveFields=new Map,this.batchSaveTimeout=null,this.isSaving=!1,this.data=this.prepareFormData(),this.formConfig=t||{fields:s||[]},this.formBuilder=new me({...this.getFormConfig(),data:this.data,errors:a})}prepareFormData(){const e={...this.defaults};if(this.model)if(this.model.attributes&&typeof this.model.attributes=="object")Object.assign(e,this.model.attributes);else if(typeof this.model.toJSON=="function"){const t=this.model.toJSON();Object.assign(e,t)}else typeof this.model=="object"&&this.model.constructor===Object&&Object.assign(e,this.model);return this._originalData&&Object.assign(e,this._originalData),e}getFormConfig(){const e={...this.formConfig},t=this.getApp();return this.formConfig.fields&&Array.isArray(this.formConfig.fields)?e.fields=this.formConfig.fields.filter(s=>s.permissions?t.activeUser?.hasPermission(s.permissions):!0):e.fields=[],e}async renderTemplate(){return this.formBuilder.buildFormHTML()}async onAfterRender(){await super.onAfterRender(),this.data=this.prepareFormData(),this.populateFormValues(),this.initializeFormComponents(),this.initializeChangeHandlers();const e=this.getFormElement();e&&e.addEventListener("submit",t=>(t.preventDefault(),!1)),this._initShowWhen(),Z.onFormViewAfterRender?.(this)}populateFormValues(){if(!(!this.element||!this.formConfig?.fields)){this._isPopulating=!0;try{this.formConfig.fields.forEach(e=>{this.populateFieldRecursive(e)})}finally{this._isPopulating=!1}}}populateFieldRecursive(e){e.type==="group"&&e.fields?e.fields.forEach(t=>{this.populateFieldRecursive(t)}):e.type==="tabset"&&e.tabs?e.tabs.forEach(t=>{t.fields&&Array.isArray(t.fields)&&t.fields.forEach(s=>{this.populateFieldRecursive(s)})}):this.populateFieldValue(e)}populateFieldValue(e){if(!e.name||!this.element)return;const t=this.element.querySelector(`[name="${e.name}"]`);if(!t)return;const s=$.getContextData(this.data,e.name);s!=null&&this.setFieldValue(t,e,s)}initializeFormComponents(){this.initializeImageFields(),this.initializeCustomComponents(),this.initializeTagInputs(),this.initializeMultiSelectDropdowns(),this.initializeComboBoxes(),this.initializeCollectionSelects(),this.initializeCollectionMultiSelects(),this.initializeDatePickers(),this.initializeDateRangePickers(),this.initializeTimePickers(),this.initializeDateTimePickers(),this.initializePasswordFields()}initializeImageFields(){this.element.querySelectorAll(".image-drop-zone.droppable").length>0&&this.enableFileDrop({acceptedTypes:["image/*"],maxFileSize:10485760,multiple:!1,dropZoneSelector:".image-drop-zone.droppable",visualFeedback:!0,dragOverClass:"drag-over",dragActiveClass:"drag-active"})}initializeCustomComponents(){this.initializeTagInputs(),this.initializeCollectionSelects(),this.initializeCollectionMultiSelects(),this.initializeDatePickers(),this.initializeDateRangePickers(),this.initializeTimePickers(),this.initializeDateTimePickers(),this.initializeComboInputs();try{const t=(s=[])=>{s.forEach(i=>{if(i&&i.type==="group"&&Array.isArray(i.fields))t(i.fields);else if(i&&i.name){const r=this.element.querySelector(`[name="${i.name}"], #${i.id||i.name}`);r&&Z.onFieldInit?.(this,r,i)}})};t(this.formConfig?.fields||[])}catch(t){console.warn("FormPlugins.onFieldInit error:",t)}this.element.querySelectorAll("[data-component]").forEach(t=>{t.getAttribute("data-component"),t.getAttribute("data-field")})}initializeChangeHandlers(){if(!this.element)return;const e=this.element.querySelectorAll("input:not([data-action]), select:not([data-action]), textarea:not([data-action])");console.log("FormView: initializeChangeHandlers - found",e.length,"inputs"),e.forEach(t=>{console.log("FormView: Processing input:",t.type,t.name,t.getAttribute("data-change-action")),!(t.hasAttribute("data-component")||t.hasAttribute("data-change-action")||t.classList.contains("form-check-input"))&&(t.addEventListener("change",s=>{if(this._isPopulating)return;const i=t.name;if(i){let r=t.value;if(t.type==="checkbox")r=t.checked;else if(t.type==="radio"){if(!t.checked)return}else if(t.multiple&&t.selectedOptions)r=Array.from(t.selectedOptions).map(n=>n.value);else if(t.type==="file"){const n=t.getAttribute("data-change-action");if(n==="image-selected"){this.onChangeImageSelected(s,t);return}else if(n==="file-selected"){this.onChangeFileSelected(s,t);return}}this.handleFieldChange(i,r)}}),(t.type==="text"||t.type==="email"||t.type==="url"||t.tagName==="TEXTAREA")&&t.addEventListener("input",s=>{if(this._isPopulating)return;const i=t.name;i&&this.handleFieldChange(i,t.value)}))})}initializeTagInputs(){this.element.querySelectorAll('[data-field-type="tag"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=new Ve({...r,containerId:null});n.render(!0,t),this.customComponents.set(s,n),n.on("change",a=>{this.handleFieldChange(s,a.value)})}catch{}})}initializeMultiSelectDropdowns(){this.element.querySelectorAll('[data-field-type="multiselect"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=this.getFormFieldConfig(s);if(!n)return;const a=new Kt({...r,options:n.options||[],placeholder:n.placeholder||r.placeholder||"Select...",label:n.label,containerId:null});let o=r.value??$.getContextData(this.data,s);o&&a.setFormValue(o),a.render(!0,t),this.customComponents.set(s,a),a.on("change",l=>{this.handleFieldChange(s,l.value)})}catch(s){console.error("MultiSelectDropdown initialization failed:",s)}})}initializeComboBoxes(){this.element.querySelectorAll('[data-field-type="combobox"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=this.getFormFieldConfig(s);if(!n)return;const a=new wt({...r,options:n.options||[],placeholder:n.placeholder||r.placeholder||"Type or select...",containerId:null});let o=r.value??$.getContextData(this.data,s);o&&a.setFormValue(o),a.render(!0,t),this.customComponents.set(s,a),a.on("change",l=>{this.handleFieldChange(s,l.value)})}catch(s){console.error("ComboBox initialization failed:",s)}})}initializeCollectionSelects(){this.element.querySelectorAll('[data-field-type="collection"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=this.getFormFieldConfig(s);if(!n||!n.Collection)return;const a=new n.Collection;n.collectionParams&&(a.params={...a.params,...n.collectionParams});const o=new Yt({...r,collection:a,defaultParams:n.defaultParams||null,containerId:null});let l=$.getContextData(this.data,s);l&&o.setFormValue(l),o.render(!0,t),this.customComponents.set(s,o),o.on("change",d=>{this.handleFieldChange(s,d.value)})}catch{}})}initializeCollectionMultiSelects(){this.element.querySelectorAll('[data-field-type="collectionmultiselect"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=this.getFormFieldConfig(s);if(!n||!n.Collection)return;const a=new n.Collection;n.collectionParams&&(a.params={...a.params,...n.collectionParams});const o=new Jt({...r,collection:a,defaultParams:n.defaultParams||null,itemTemplate:n.itemTemplate||null,containerId:null});let l=$.getContextData(this.data,s);l&&o.setFormValue(l),o.render(!0,t),this.customComponents.set(s,o),o.on("change",d=>{this.handleFieldChange(s,d.value)})}catch(s){console.error("CollectionMultiSelect initialization failed:",s)}})}initializeDatePickers(){this.element.querySelectorAll('[data-field-type="datepicker"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=new He({...r,containerId:null});n.render(!0,t),this.customComponents.set(s,n),n.on("change",a=>{this.handleFieldChange(s,a.value)})}catch{}})}initializeDateRangePickers(){this.element.querySelectorAll('[data-field-type="daterange"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=new Be({...r,containerId:null});n.render(!0,t),this.customComponents.set(s,n),n.on("change",a=>{this.handleFieldChange(s,a.combined)})}catch{}})}initializeTimePickers(){this.element.querySelectorAll('[data-field-type="timepicker"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=new _e({...r,containerId:null});n.render(!0,t),this.customComponents.set(s,n),n.on("change",a=>{this.handleFieldChange(s,a.value)})}catch{}})}initializeDateTimePickers(){this.element.querySelectorAll('[data-field-type="datetimepicker"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=new Ye({...r,containerId:null});n.render(!0,t),this.customComponents.set(s,n),n.on("change",a=>{this.handleFieldChange(s,a.value)})}catch{}})}initializeComboInputs(){this.element.querySelectorAll('[data-field-type="combo"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=new We({...r,containerId:null});let a=$.getContextData(this.data,s);a&&n.setValue(a),n.render(!0,t),this.customComponents.set(s,n),n.on("change",o=>{this.handleFieldChange(s,o.value)}),n.on("select",o=>{this.emit("field:select",{field:s,value:o.value,option:o.option,meta:o.meta})})}catch(s){console.error("ComboInput initialization failed:",s)}})}handleFieldChange(e,t){this._isPopulating||(this.data[e]=t,this.autosaveModelField&&this.model?this.handleFieldSave(e,t):this.model&&this.options.allowModelChange&&(this._isFormDrivenChange=!0,this.model.set(e,t)),this.emit("field:change",{field:e,value:t}),this._updateShowWhen(e,t),Z.onFieldChange?.(this,e,t))}_initShowWhen(){if(this._showWhenMap={},!this.element)return;this.element.querySelectorAll("[data-show-when-field]").forEach(t=>{const s=t.getAttribute("data-show-when-field");this._showWhenMap[s]||(this._showWhenMap[s]=[]),this._showWhenMap[s].push(t),t.style.display==="none"?t.querySelectorAll("input, select, textarea").forEach(r=>{r.required&&(r.dataset.wasRequired="true",r.required=!1)}):t.querySelectorAll("input, select, textarea").forEach(r=>{r.required&&(r.dataset.wasRequired="true")})})}_updateShowWhen(e,t){const s=this._showWhenMap?.[e];if(!s)return;const i=String(t??"");s.forEach(r=>{const n=r.getAttribute("data-show-when-value").split(","),a=r.getAttribute("data-show-when-negate")==="true",o=n.includes(i),l=a?!o:o;r.style.display=l?"":"none",r.querySelectorAll("input, select, textarea").forEach(h=>{l?h.dataset.wasRequired==="true"&&(h.required=!0):(h.required&&(h.dataset.wasRequired="true"),h.required=!1)})})}async handleFieldSave(e,t){if(!this.model)return;this.pendingSaveFields.set(e,t),this.getFieldStatusManager(e).showStatus("saving"),this.batchSaveTimeout&&clearTimeout(this.batchSaveTimeout),this.batchSaveTimeout=setTimeout(async()=>{await this.executeBatchSave()},300)}async executeBatchSave(){if(this.isSaving||this.pendingSaveFields.size===0)return;const e=Object.fromEntries(this.pendingSaveFields),t=Array.from(this.pendingSaveFields.keys());try{if(this.isSaving=!0,this.pendingSaveFields.clear(),this.batchSaveTimeout=null,this._isFormDrivenChange=!0,typeof this.model.save=="function"){const s=await this.model.save(e);if(!s||!s.success||s.data&&!s.data.status){const i=s?.data?.error||s?.error||s?.message||"Save failed";this.getApp()?.toast?.error(i),this.revertFields(t),t.forEach(r=>{this.getFieldStatusManager(r).showStatus("error",{message:i})});return}}else Object.entries(e).forEach(([s,i])=>{this.model.set(s,i)});t.forEach(s=>{this.getFieldStatusManager(s).showStatus("saved")})}catch(s){console.error("Batch save error:",s),this.getApp()?.toast?.error(s.message||"An error occurred while saving"),this.revertFields(t),t.forEach(i=>{this.getFieldStatusManager(i).showStatus("error",{message:s.message})})}finally{this.isSaving=!1}}revertFields(e){if(!this.model)return;const t=this._isPopulating;this._isPopulating=!0;try{e.forEach(s=>{const i=this.model.get(s);this.data[s]=i;const r=this.element?.querySelector(`[name="${s}"]`);if(r){const n=this.getFormFieldConfig(s);n?this.setFieldValue(r,n,i):r.type==="checkbox"?r.checked=!!i:r.value=i??""}})}finally{this._isPopulating=t}}getFieldStatusManager(e){if(!this.fieldStatusManagers.has(e)){const t=this.element.querySelector(`[name="${e}"]`);if(t){const s=new us(t);this.fieldStatusManagers.set(e,s)}}return this.fieldStatusManagers.get(e)}refreshForm(){this.data=this.prepareFormData(),this.element&&this.populateFormValues()}getChangeReason(e,t){if(e instanceof File)return e.size===0||e.name===""||e.name==="blob"?"empty file, no change":`file upload: ${e.name}, ${e.size} bytes`;if(typeof e=="string"&&e.startsWith("data:image/"))return"base64 image upload";if(typeof e=="boolean"||typeof t=="boolean"){const s=!!e;return`boolean: ${t==null?!1:!!t} → ${s}`}return e==null||String(e).trim(),t==null||String(t).trim(),t==null?"was null/undefined, now has value":e==null?"was value, now null/undefined":"text content changed"}setFormData(e){this._originalData={...this._originalData,...e},this.refreshForm()}async onActionSubmitForm(e,t){e.preventDefault();const s=await this.handleSubmit();s.success?(this.data=s.data,this.emit("submit",{data:s.data,result:s.result,form:this,event:e}),!this.model&&this.formConfig.onSubmit&&typeof this.formConfig.onSubmit=="function"&&await this.formConfig.onSubmit(s.data,this)):this.emit("error",{error:s.error,result:s,form:this})}async onActionResetForm(e,t){const s=this.getFormElement();s&&(s.reset(),this.data={},this.clearAllErrors(),this.emit("reset",{form:this,event:e}))}async onActionClickImageUpload(e,t){console.log("FormView: onActionClickImageUpload called"),console.log("FormView: element:",t);const s=t.getAttribute("data-field-id");if(console.log("FormView: fieldId:",s),!s){console.error("FormView: No fieldId attribute found");return}const i=this.element.querySelector(`#${s}`);console.log("FormView: fileInput:",i),i&&!i.disabled?(i.click(),console.log("FormView: fileInput.click() called")):i?console.log("FormView: fileInput is disabled"):console.error("FormView: fileInput not found for fieldId:",s)}async onActionRemoveImage(e,t){const s=t.getAttribute("data-field");if(!s)return;const i=this.element.querySelector(`input[name="${s}"]`);i&&(i.value="",i.dispatchEvent(new Event("change",{bubbles:!0}))),delete this.data[s],this.emit("change",{field:s,value:null,form:this}),await this.updateField(s)}async onActionClearColor(e,t){const s=t.getAttribute("data-field");if(!s)return;const i=this.element.querySelector(`input[name="${s}"]`);i&&(i.value="",this.handleFieldChange(s,""),await this.updateField(s))}async onActionPreviewHtml(e,t){e.preventDefault();const s=t.getAttribute("data-target");if(!s)return;const i=this.element.querySelector(`#${s}`);if(!i)return;const r=i.value||"";(await Promise.resolve().then(()=>N)).default.htmlPreview({html:r,title:"HTML Preview"})}async onActionSelectButtonOption(e,t){const s=t.getAttribute("data-field"),i=t.getAttribute("data-value");if(!s||!i)return;this.data[s]=i;const r=t.closest(".btn-group");r&&(r.querySelectorAll("button").forEach(a=>{a.classList.remove("active"),a.classList.add("btn-outline-primary"),a.classList.remove("btn-primary")}),t.classList.add("active"),t.classList.remove("btn-outline-primary"),t.classList.add("btn-primary")),this.emit("field:changed",{field:s,value:i,form:this}),this.emit("change",{field:s,value:i,form:this}),this.emit("form:changed",await this.getFormData())}async onActionApplyFilter(e,t){const s=t.closest(".dropdown"),i=s?.querySelectorAll('input[type="checkbox"]');if(!i||i.length===0)return;const r=i[0].getAttribute("data-field");if(!r)return;const n=[];i.forEach(o=>{o.checked&&n.push(o.value)}),this.data[r]=n;const a=s.querySelector('[data-bs-toggle="dropdown"]');a&&window.bootstrap?.Dropdown&&window.bootstrap.Dropdown.getInstance(a)?.hide(),this.emit("field:changed",{field:r,value:n,form:this}),this.emit("change",{field:r,value:n,form:this}),this.emit("form:changed",await this.getFormData())}async onChangeValidateField(e,t){const s=t.name;if(s){const i=t.value;this.handleFieldChange(s,i),this.validateField(s)}}async onChangeToggleSwitch(e,t){const s=t.getAttribute("data-field");if(s){const i=t.checked;this.handleFieldChange(s,i),this.emit("switch:toggle",{field:s,checked:i,form:this})}}async onChangeImageSelected(e,t){console.log("FormView: onChangeImageSelected called"),console.log("FormView: element:",t),console.log("FormView: element.files:",t.files);const s=t.getAttribute("data-field"),i=t.files[0];if(console.log("FormView: fieldName:",s),console.log("FormView: file:",i),s&&i){console.log("FormView: fieldName and file exist, processing...");const r=this.findFieldConfig(s);console.log("FormView: fieldConfig:",r);const n=URL.createObjectURL(i);if(console.log("FormView: previewUrl created:",n),r&&r.imageSize){console.log("FormView: Image cropping is required, imageSize:",r.imageSize);try{const a=window.MOJO?.plugins?.ImageCropView;if(console.log("FormView: ImageCropView available?",!!a),!a){console.log("FormView: ImageCropView not available, falling back to normal handling"),this.data[s]=i,await this.updateImagePreview(s,n),this.emit("image:selected",{field:s,file:i,form:this});return}const o=await a.showDialog(n,{title:`Crop ${r.label||s}`,cropAndScale:r.imageSize,size:"lg"});if(o.action==="crop"&&o.data){const d=await(await fetch(o.data)).blob(),h=new File([d],i.name,{type:i.type||"image/png"});this.data[s]=h,await this.updateImagePreview(s,o.data),this.emit("image:selected",{field:s,file:h,originalFile:i,cropped:!0,cropData:o.cropData,form:this}),this.emit("change",{field:s,value:h,form:this})}else t.value=""}catch(a){console.error("FormView: Error during image cropping:",a),console.log("FormView: Falling back to normal image handling after error"),this.data[s]=i,await this.updateImagePreview(s,n),this.emit("image:selected",{field:s,file:i,form:this}),this.emit("change",{field:s,value:i,form:this})}}else console.log("FormView: Normal image handling (no cropping)"),this.data[s]=i,console.log("FormView: File stored in this.data["+s+"]"),await this.updateImagePreview(s,n),console.log("FormView: updateImagePreview completed"),this.emit("image:selected",{field:s,file:i,form:this}),console.log("FormView: image:selected event emitted")}else console.log("FormView: Missing fieldName or file - not processing")}async onChangeFileSelected(e,t){const s=Array.from(t.files);t.multiple?this.data[t.name]=t.files:this.data[t.name]=s[0]||null,this.emit("file:selected",{field:t.name,files:s,form:this}),this.emit("change",{field:t.name,value:s,form:this})}async onChangeRangeChanged(e,t){const s=t.name,i=t.value,r=t.getAttribute("data-target");if(r){const n=this.element.querySelector(`#${r}`);n&&(n.textContent=i)}s&&this.handleFieldChange(s,i),this.emit("range:changed",{field:s,value:i,form:this})}async onChangeFilterSearch(e,t){const s=t.value;this.emit("search",{query:s,field:t.name,form:this})}async onChangeFilterSelectOptions(e,t){const s=t.value.toLowerCase(),i=t.getAttribute("data-target"),r=i?this.element.querySelector(`#${i}`):null;r&&r.querySelectorAll("option").forEach(a=>{const o=a.textContent.toLowerCase();a.style.display=o.includes(s)?"":"none"})}async onFileDrop(e,t,s){const i=t.target.closest(".image-drop-zone");if(!i)return;const r=i.getAttribute("data-field");if(!r)return;const n=e[0],a=this.element.querySelector(`input[name="${r}"]`);if(a){const l=new DataTransfer;l.items.add(n),a.files=l.files,a.dispatchEvent(new Event("change",{bubbles:!0}))}this.data[r]=n;const o=URL.createObjectURL(n);await this.updateImagePreview(r,o),this.emit("image:dropped",{field:r,file:n,form:this})}async onFileDropError(e,t,s){this.showError(`File upload error: ${e.message}`),this.emit("file:error",{error:e,files:s,form:this})}getFormElement(){return this.element?this.element.querySelector("form"):null}getFormFieldConfig(e){const t=s=>{for(const i of s){if(i.name===e)return i;if(i.fields&&Array.isArray(i.fields)){const r=t(i.fields);if(r)return r}}return null};return t(this.formConfig.fields||[])}async getFormData(){const e=this.getFormElement();if(!e)return this.fileHandling==="multipart"?new FormData:{};if(this.fileHandling==="multipart"){const t=new FormData(e);for(const[s,i]of Object.entries(this.data))if(i instanceof File)t.set(s,i);else if(i instanceof FileList)for(let r=0;r<i.length;r++)t.append(`${s}[${r}]`,i[r]);return t}else{const t=new FormData(e),s={};for(const[a,o]of t.entries())s[a]?(Array.isArray(s[a])||(s[a]=[s[a]]),s[a].push(o)):s[a]=o;e.querySelectorAll('input[type="checkbox"]').forEach(a=>{s[a.name]=a.checked}),e.querySelectorAll('input[type="number"]').forEach(a=>{if(a.name&&s[a.name]!==void 0&&s[a.name]!==""){const o=Number(s[a.name]);isNaN(o)||(s[a.name]=o)}}),this.formConfig.fields?.forEach(a=>{if(a.type==="select"&&a.name&&s[a.name]!==void 0){const o=this.getFormFieldConfig(a.name);if(o?.options&&Array.isArray(o.options)&&o.options.every(d=>{const h=typeof d=="object"?d.value:d;return h===""||!isNaN(Number(h))})&&s[a.name]!==""){const d=Number(s[a.name]);isNaN(d)||(s[a.name]=d)}}}),e.querySelectorAll('[data-field-type="json"]').forEach(a=>{try{s[a.name]=JSON.parse(a.value)}catch{s[a.name]=a.value}}),this.customComponents.forEach((a,o)=>{a.getFormValue?s[o]=a.getFormValue():a.getValue&&(s[o]=a.getValue())}),this.element&&this.element.querySelectorAll("[data-show-when-field]").forEach(o=>{o.style.display==="none"&&o.querySelectorAll("[name]").forEach(d=>{delete s[d.name]})});for(const[a,o]of Object.entries(this.data))if(o instanceof File)try{s[a]=await this.fileToBase64(o)}catch{s[a]=null}else if(o instanceof FileList){const l=[];for(let d=0;d<o.length;d++)try{l.push(await this.fileToBase64(o[d]))}catch{l.push(null)}s[a]=l}return s}}_onModelChange(){this.isSaving||(this.data=this.prepareFormData(),this.isMounted()&&(this._isFormDrivenChange||this.syncFormWithModel(),this._isFormDrivenChange=!1))}syncFormWithModel(){!this.model||!this.element||this.formDataMatchesModelData(this.data)||this.populateFormValues()}formDataMatchesModelData(e){if(!this.formConfig?.fields||!this.element)return!0;for(const t of this.formConfig.fields)if(t.type==="group"&&t.fields){for(const s of t.fields)if(!this.fieldValueMatchesModel(s,e))return!1}else if(!this.fieldValueMatchesModel(t,e))return!1;return!0}fieldValueMatchesModel(e,t){if(!e.name)return!0;const s=this.element.querySelector(`[name="${e.name}"]`);if(!s)return!0;const i=this.getFieldCurrentValue(s,e),r=$.getContextData(t,e.name);return this.valuesAreDifferent(i,r)===!1}getFieldCurrentValue(e,t){switch(t.type){case"checkbox":case"toggle":case"switch":return e.checked;case"radio":const s=this.element.querySelector(`[name="${t.name}"]:checked`);return s?s.value:"";case"select":return e.multiple?Array.from(e.selectedOptions).map(i=>i.value):e.value;case"file":case"image":return null;case"json":try{return e.value?JSON.parse(e.value):null}catch{return e.value}default:return e.value}}setFieldValue(e,t,s){switch(t.type){case"checkbox":case"toggle":case"switch":e.checked=!!s;break;case"radio":const i=this.element.querySelector(`[name="${t.name}"][value="${s}"]`);i&&(i.checked=!0);break;case"select":e.multiple&&Array.isArray(s)?Array.from(e.options).forEach(r=>{r.selected=s.includes(r.value)}):e.value=s??"";break;case"file":case"image":break;case"json":if(typeof s=="object"&&s!==null)try{e.value=JSON.stringify(s,null,2)}catch{e.value="{}"}else typeof s=="string"?e.value=s:e.value=String(s||"");break;default:e.value=s||"";break}e.dispatchEvent(new Event("change",{bubbles:!0}))}setDefaults(e){this.defaults={...this.defaults,...e},this.refreshForm()}async handleSubmit(){try{const e=await this.getFormData();if(this.formConfig.validateOnSubmit!==!1&&!this.validate())return this.focusFirstError(),{success:!1,data:e,error:"Form validation failed"};if(this.model&&typeof this.model.save=="function"){const t=await this.saveModel(e);if(t&&t.success!==!1)return{success:!0,data:e,result:t};{const s=t?.message||t?.error||"Save failed. Please try again.";return{success:!1,data:e,result:t,error:s}}}else return e}catch(e){return{success:!1,error:e.message||"An error occurred while submitting the form"}}}async saveModel(e=null){if(!this.model||typeof this.model.save!="function")throw new Error("No model available for saving");e||(e=await this.getFormData());const t=this.getChangedData(e);if(!t||Object.keys(t).length===0)return{success:!0,message:"No changes to save",data:e};try{return this._isFormDrivenChange=!0,await this.model.save(t)}catch(s){throw s}}getChangedData(e){if(!this.model)return e;const t=this.getOriginalModelData();let s;return e instanceof FormData?s=this.getChangedFormData(e,t):s=this.getChangedObjectData(e,t),s}getOriginalModelData(){return this.model.attributes?this.model.attributes:typeof this.model.toJSON=="function"?this.model.toJSON():{}}getChangedFormData(e,t){const s=new FormData;let i=!1;for(const[r,n]of e.entries())if(n instanceof File)n.size===0||n.name===""||n.name==="blob"||(s.set(r,n),i=!0);else{const a=t[r];n!==a&&n!==String(a)&&(s.set(r,n),i=!0)}return i?s:null}getChangedObjectData(e,t){const s={};let i=!1;const r=new Set([...Object.keys(t),...Object.keys(e)]),n=(a,o)=>o.split(".").reduce((l,d)=>l&&typeof l=="object"?l[d]:void 0,a);for(const a of r){const o=this.findFieldConfig(a);if(!o)continue;const l=e[a],d=n(t,a),h=o.type||"text";this.valuesAreDifferent(l,d,h,o)&&(s[a]=l,i=!0)}return i?s:null}valuesAreDifferent(e,t,s="text",i={}){if(e instanceof File)return e.size>0&&e.name!==""&&e.name!=="blob";if(typeof e=="string"&&e.startsWith("data:image/"))return!0;if(s==="collection"&&typeof t=="object"&&t!==null&&t!==void 0&&typeof e=="string"){if(e==="0")return t!==null;const a=i.valueField||"id";if(t[a]==e)return!1}if(s==="switch"||s==="checkbox"||s==="toggle")return!!e!==!!t;const r=e==null?"":String(e).trim(),n=t==null?"":String(t).trim();return r!==n}validate(){const e=this.getFormElement();if(!e)return!1;const t=e.checkValidity();return t||e.classList.add("was-validated"),t}validateField(e){const t=this.getFormElement();if(!t)return!1;const s=t.elements[e];if(!s)return!1;const i=s.checkValidity();return i?(s.classList.remove("is-invalid"),s.classList.add("is-valid"),delete this.errors[e]):(s.classList.remove("is-valid"),s.classList.add("is-invalid"),this.errors[e]=s.validationMessage),i}focusFirstError(){const e=this.getFormElement();if(!e)return;const t=e.querySelector(":invalid");if(!t)return;const s=t.closest(".tab-pane");if(s&&!s.classList.contains("active")){const i=s.id,r=e.querySelector(`[role="tab"][aria-controls="${i}"], [data-bs-target="#${i}"]`);if(r){const n=window.bootstrap?.Tab?.getOrCreateInstance?window.bootstrap.Tab.getOrCreateInstance(r):null;n&&typeof n.show=="function"?n.show():(e.querySelectorAll('[role="tab"].nav-link').forEach(l=>{const d=l===r;l.classList.toggle("active",d),l.setAttribute("aria-selected",d?"true":"false")}),e.querySelectorAll(".tab-pane").forEach(l=>l.classList.remove("show","active")),s.classList.add("show","active"))}}t.focus(),t.scrollIntoView({behavior:"smooth",block:"center"})}clearAllErrors(){const e=this.getFormElement();if(!e)return;this.errors={},e.classList.remove("was-validated"),e.querySelectorAll(".is-invalid").forEach(i=>i.classList.remove("is-invalid")),e.querySelectorAll(".is-valid").forEach(i=>i.classList.remove("is-valid"))}setLoading(e){this.loading=e;const t=this.getFormElement();if(!t)return;const s=t.querySelectorAll("input, select, textarea, button"),i=t.querySelector('button[type="submit"]');if(e)s.forEach(r=>r.disabled=!0),i&&(i.innerHTML='<span class="spinner-border spinner-border-sm me-2"></span>Loading...');else if(s.forEach(r=>r.disabled=!1),i){const r=this.formConfig.options?.submitButton||"Submit";i.innerHTML=typeof r=="string"?r:"Submit"}}showError(e){if(this.emit("error",{message:e,form:this}),this.element){this.element.querySelectorAll(".alert").forEach(i=>i.remove());const s=document.createElement("div");s.className="alert alert-danger alert-dismissible fade show",s.innerHTML=`
1189
+ `}highlightMatch(e){if(!this.inputValue)return this.escapeHtml(e);const t=this.escapeHtml(e),s=new RegExp(`(${this.escapeRegex(this.inputValue)})`,"gi");return t.replace(s,'<mark class="bg-warning bg-opacity-25">$1</mark>')}async onAfterRender(){await super.onAfterRender(),this.updateFilteredOptions(),this.handleOutsideClick=e=>{this.element&&!this.element.contains(e.target)&&this.closeDropdown()},document.addEventListener("click",this.handleOutsideClick)}async onChangeInputChange(e,t){this.inputValue=t.value,this.updateFilteredOptions(),this.inputValue.length>=this.minChars?this.openDropdown():this.closeDropdown(),this.highlightedIndex=-1,await this.updateDropdownDisplay()}async onActionInputKeydown(e,t){switch(e.key){case"ArrowDown":e.preventDefault(),this.isOpen?this.highlightNext():this.openDropdown(),await this.updateDropdownDisplay();break;case"ArrowUp":e.preventDefault(),this.isOpen&&(this.highlightPrevious(),await this.updateDropdownDisplay());break;case"Enter":e.preventDefault(),this.isOpen&&this.highlightedIndex>=0?await this.selectHighlightedOption():this.allowCustom&&this.inputValue&&await this.selectCustomValue(this.inputValue);break;case"Escape":e.preventDefault(),this.closeDropdown();const s=this.element.querySelector(".combo-input-field");s&&(s.value=this.getDisplayValue(this.currentValue),this.inputValue=s.value);break;case"Tab":this.isOpen&&this.closeDropdown();break}}async onActionToggleDropdown(e,t){if(e.preventDefault(),e.stopPropagation(),this.isOpen)this.closeDropdown();else{this.inputValue="";const s=this.element.querySelector(".combo-input-field");s&&(s.value="",s.focus()),this.updateFilteredOptions(),this.openDropdown(),await this.updateDropdownDisplay()}}async onActionSelectOption(e,t){e.preventDefault(),e.stopPropagation();const s=parseInt(t.getAttribute("data-option-index"));s>=0&&s<this.filteredOptions.length&&await this.selectOption(this.filteredOptions[s])}openDropdown(){this.isOpen=!0;const e=this.element?.querySelector(".combo-dropdown");e&&e.classList.add("show");const t=this.element?.querySelector(".combo-input-field");t&&t.setAttribute("aria-expanded","true")}closeDropdown(){this.isOpen=!1,this.highlightedIndex=-1;const e=this.element?.querySelector(".combo-dropdown");e&&e.classList.remove("show");const t=this.element?.querySelector(".combo-input-field");t&&t.setAttribute("aria-expanded","false")}updateFilteredOptions(){const e=this.inputValue.toLowerCase().trim();if(!e){this.filteredOptions=[...this.options];return}this.filteredOptions=this.options.filter(t=>{const s=t.label.toLowerCase().includes(e),i=String(t.value).toLowerCase().includes(e),r=t.description?.toLowerCase().includes(e);return s||i||r}),this.filteredOptions.sort((t,s)=>{const i=t.label.toLowerCase()===e,r=s.label.toLowerCase()===e;if(i&&!r)return-1;if(!i&&r)return 1;const n=t.label.toLowerCase().startsWith(e),a=s.label.toLowerCase().startsWith(e);return n&&!a?-1:!n&&a?1:0})}async updateDropdownDisplay(){const e=this.element?.querySelector(".combo-dropdown");if(e&&(e.innerHTML=this.renderDropdownContent(),this.highlightedIndex>=0)){const t=e.querySelector(".combo-option.active");t&&t.scrollIntoView({block:"nearest"})}}highlightNext(){this.filteredOptions.length!==0&&(this.highlightedIndex=(this.highlightedIndex+1)%Math.min(this.filteredOptions.length,this.maxSuggestions))}highlightPrevious(){this.filteredOptions.length!==0&&(this.highlightedIndex=this.highlightedIndex<=0?Math.min(this.filteredOptions.length,this.maxSuggestions)-1:this.highlightedIndex-1)}async selectHighlightedOption(){this.highlightedIndex>=0&&this.highlightedIndex<this.filteredOptions.length&&await this.selectOption(this.filteredOptions[this.highlightedIndex])}async selectOption(e){this.currentValue=e.value,this.inputValue=e.label,this.selectedOption=e;const t=this.element?.querySelector(".combo-input-field");t&&(t.value=e.label);const s=this.element?.querySelector(".combo-input-hidden");s&&(s.value=e.value),this.closeDropdown(),this.emit("select",{option:e,value:e.value,meta:e.meta}),this.emit("change",{value:e.value,option:e,meta:e.meta}),typeof this.onSelectCallback=="function"&&this.onSelectCallback(e),typeof this.onChangeCallback=="function"&&this.onChangeCallback(e.value)}async selectCustomValue(e){if(!this.allowCustom)return;this.currentValue=e,this.inputValue=e,this.selectedOption=null;const t=this.element?.querySelector(".combo-input-hidden");t&&(t.value=e),this.closeDropdown(),this.emit("custom",{value:e}),this.emit("change",{value:e,custom:!0}),typeof this.onChangeCallback=="function"&&this.onChangeCallback(e)}getValue(){return this.currentValue}async setValue(e){this.currentValue=e,this.selectedOption=this.findOptionByValue(e),this.inputValue=this.getDisplayValue(e);const t=this.element?.querySelector(".combo-input-field");t&&(t.value=this.inputValue);const s=this.element?.querySelector(".combo-input-hidden");s&&(s.value=e),this.updateFilteredOptions()}getSelectedOption(){return this.selectedOption}async setOptions(e){this.options=this.normalizeOptions(e),this.updateFilteredOptions(),this.isOpen&&await this.updateDropdownDisplay()}setEnabled(e){this.disabled=!e;const t=this.element?.querySelector(".combo-input-field");t&&(t.disabled=this.disabled);const s=this.element?.querySelector(".combo-toggle");s&&(s.disabled=this.disabled)}setReadonly(e){this.readonly=e;const t=this.element?.querySelector(".combo-input-field");t&&(e?t.setAttribute("readonly",""):t.removeAttribute("readonly"))}focus(){const e=this.element?.querySelector(".combo-input-field");e&&e.focus()}async clear(){await this.setValue(""),this.inputValue="";const e=this.element?.querySelector(".combo-input-field");e&&(e.value=""),this.emit("clear")}getFormValue(){return this.allowCustom&&this.inputValue&&this.inputValue!==this.getDisplayValue(this.currentValue)?this.inputValue:this.currentValue}async setFormValue(e){await this.setValue(e)}escapeHtml(e){if(e==null)return"";const t=document.createElement("div");return t.textContent=String(e),t.innerHTML}escapeRegex(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}async onBeforeDestroy(){this.handleOutsideClick&&document.removeEventListener("click",this.handleOutsideClick),await super.onBeforeDestroy()}static create(e={}){return new We(e)}}class Q extends C{constructor(e={}){const{formConfig:t=e.config,fields:s,model:i=null,data:r={},defaults:n=null,errors:a={},fileHandling:o="base64",autosaveModelField:l=!1,...d}=e;super({tagName:"div",className:"form-view",enableTooltips:!0,...d}),Z.onFormViewInit?.(this),this.model=i,this.defaults=n||r,this._originalData=r,this.errors=a,this.loading=!1,this.fileHandling=o,this.autosaveModelField=l,this.customComponents=new Map,this.fieldStatusManagers=new Map,this.saveTimeouts=new Map,this.pendingSaveFields=new Map,this.batchSaveTimeout=null,this.isSaving=!1,this.data=this.prepareFormData(),this.formConfig=t||{fields:s||[]},this.formBuilder=new me({...this.getFormConfig(),data:this.data,errors:a})}prepareFormData(){const e={...this.defaults};if(this.model)if(this.model.attributes&&typeof this.model.attributes=="object")Object.assign(e,this.model.attributes);else if(typeof this.model.toJSON=="function"){const t=this.model.toJSON();Object.assign(e,t)}else typeof this.model=="object"&&this.model.constructor===Object&&Object.assign(e,this.model);return this._originalData&&Object.assign(e,this._originalData),e}getFormConfig(){const e={...this.formConfig},t=this.getApp();return this.formConfig.fields&&Array.isArray(this.formConfig.fields)?e.fields=this.formConfig.fields.filter(s=>s.permissions?t.activeUser?.hasPermission(s.permissions):!0):e.fields=[],e}async renderTemplate(){return this.formBuilder.buildFormHTML()}async onAfterRender(){await super.onAfterRender(),this.data=this.prepareFormData(),this.populateFormValues(),this.initializeFormComponents(),this.initializeChangeHandlers();const e=this.getFormElement();e&&e.addEventListener("submit",t=>(t.preventDefault(),!1)),this._initShowWhen(),Z.onFormViewAfterRender?.(this)}populateFormValues(){if(!(!this.element||!this.formConfig?.fields)){this._isPopulating=!0;try{this.formConfig.fields.forEach(e=>{this.populateFieldRecursive(e)})}finally{this._isPopulating=!1}}}populateFieldRecursive(e){e.type==="group"&&e.fields?e.fields.forEach(t=>{this.populateFieldRecursive(t)}):e.type==="tabset"&&e.tabs?e.tabs.forEach(t=>{t.fields&&Array.isArray(t.fields)&&t.fields.forEach(s=>{this.populateFieldRecursive(s)})}):this.populateFieldValue(e)}populateFieldValue(e){if(!e.name||!this.element)return;const t=this.element.querySelector(`[name="${e.name}"]`);if(!t)return;const s=$.getContextData(this.data,e.name);s!=null&&this.setFieldValue(t,e,s)}initializeFormComponents(){this.initializeImageFields(),this.initializeCustomComponents(),this.initializeTagInputs(),this.initializeMultiSelectDropdowns(),this.initializeComboBoxes(),this.initializeCollectionSelects(),this.initializeCollectionMultiSelects(),this.initializeDatePickers(),this.initializeDateRangePickers(),this.initializeTimePickers(),this.initializeDateTimePickers(),this.initializePasswordFields()}initializeImageFields(){this.element.querySelectorAll(".image-drop-zone.droppable").length>0&&this.enableFileDrop({acceptedTypes:["image/*"],maxFileSize:10485760,multiple:!1,dropZoneSelector:".image-drop-zone.droppable",visualFeedback:!0,dragOverClass:"drag-over",dragActiveClass:"drag-active"})}initializeCustomComponents(){this.initializeTagInputs(),this.initializeCollectionSelects(),this.initializeCollectionMultiSelects(),this.initializeDatePickers(),this.initializeDateRangePickers(),this.initializeTimePickers(),this.initializeDateTimePickers(),this.initializeComboInputs();try{const t=(s=[])=>{s.forEach(i=>{if(i&&i.type==="group"&&Array.isArray(i.fields))t(i.fields);else if(i&&i.name){const r=this.element.querySelector(`[name="${i.name}"], #${i.id||i.name}`);r&&Z.onFieldInit?.(this,r,i)}})};t(this.formConfig?.fields||[])}catch(t){console.warn("FormPlugins.onFieldInit error:",t)}this.element.querySelectorAll("[data-component]").forEach(t=>{t.getAttribute("data-component"),t.getAttribute("data-field")})}initializeChangeHandlers(){if(!this.element)return;const e=this.element.querySelectorAll("input:not([data-action]), select:not([data-action]), textarea:not([data-action])");console.log("FormView: initializeChangeHandlers - found",e.length,"inputs"),e.forEach(t=>{console.log("FormView: Processing input:",t.type,t.name,t.getAttribute("data-change-action")),!(t.hasAttribute("data-component")||t.hasAttribute("data-change-action")||t.classList.contains("form-check-input"))&&(t.addEventListener("change",s=>{if(this._isPopulating)return;const i=t.name;if(i){let r=t.value;if(t.type==="checkbox")r=t.checked;else if(t.type==="radio"){if(!t.checked)return}else if(t.multiple&&t.selectedOptions)r=Array.from(t.selectedOptions).map(n=>n.value);else if(t.type==="file"){const n=t.getAttribute("data-change-action");if(n==="image-selected"){this.onChangeImageSelected(s,t);return}else if(n==="file-selected"){this.onChangeFileSelected(s,t);return}}this.handleFieldChange(i,r)}}),(t.type==="text"||t.type==="email"||t.type==="url"||t.tagName==="TEXTAREA")&&t.addEventListener("input",s=>{if(this._isPopulating)return;const i=t.name;i&&this.handleFieldChange(i,t.value)}))})}initializeTagInputs(){this.element.querySelectorAll('[data-field-type="tag"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=new Pe({...r,containerId:null});n.render(!0,t),this.customComponents.set(s,n),n.on("change",a=>{this.handleFieldChange(s,a.value)})}catch{}})}initializeMultiSelectDropdowns(){this.element.querySelectorAll('[data-field-type="multiselect"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=this.getFormFieldConfig(s);if(!n)return;const a=new Kt({...r,options:n.options||[],placeholder:n.placeholder||r.placeholder||"Select...",label:n.label,containerId:null});let o=r.value??$.getContextData(this.data,s);o&&a.setFormValue(o),a.render(!0,t),this.customComponents.set(s,a),a.on("change",l=>{this.handleFieldChange(s,l.value)})}catch(s){console.error("MultiSelectDropdown initialization failed:",s)}})}initializeComboBoxes(){this.element.querySelectorAll('[data-field-type="combobox"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=this.getFormFieldConfig(s);if(!n)return;const a=new wt({...r,options:n.options||[],placeholder:n.placeholder||r.placeholder||"Type or select...",containerId:null});let o=r.value??$.getContextData(this.data,s);o&&a.setFormValue(o),a.render(!0,t),this.customComponents.set(s,a),a.on("change",l=>{this.handleFieldChange(s,l.value)})}catch(s){console.error("ComboBox initialization failed:",s)}})}initializeCollectionSelects(){this.element.querySelectorAll('[data-field-type="collection"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=this.getFormFieldConfig(s);if(!n||!n.Collection)return;const a=new n.Collection;n.collectionParams&&(a.params={...a.params,...n.collectionParams});const o=new Yt({...r,collection:a,defaultParams:n.defaultParams||null,containerId:null});let l=$.getContextData(this.data,s);l&&o.setFormValue(l),o.render(!0,t),this.customComponents.set(s,o),o.on("change",d=>{this.handleFieldChange(s,d.value)})}catch{}})}initializeCollectionMultiSelects(){this.element.querySelectorAll('[data-field-type="collectionmultiselect"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=this.getFormFieldConfig(s);if(!n||!n.Collection)return;const a=new n.Collection;n.collectionParams&&(a.params={...a.params,...n.collectionParams});const o=new Jt({...r,collection:a,defaultParams:n.defaultParams||null,itemTemplate:n.itemTemplate||null,containerId:null});let l=$.getContextData(this.data,s);l&&o.setFormValue(l),o.render(!0,t),this.customComponents.set(s,o),o.on("change",d=>{this.handleFieldChange(s,d.value)})}catch(s){console.error("CollectionMultiSelect initialization failed:",s)}})}initializeDatePickers(){this.element.querySelectorAll('[data-field-type="datepicker"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=new He({...r,containerId:null});n.render(!0,t),this.customComponents.set(s,n),n.on("change",a=>{this.handleFieldChange(s,a.value)})}catch{}})}initializeDateRangePickers(){this.element.querySelectorAll('[data-field-type="daterange"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=new Be({...r,containerId:null});n.render(!0,t),this.customComponents.set(s,n),n.on("change",a=>{this.handleFieldChange(s,a.combined)})}catch{}})}initializeTimePickers(){this.element.querySelectorAll('[data-field-type="timepicker"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=new _e({...r,containerId:null});n.render(!0,t),this.customComponents.set(s,n),n.on("change",a=>{this.handleFieldChange(s,a.value)})}catch{}})}initializeDateTimePickers(){this.element.querySelectorAll('[data-field-type="datetimepicker"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=new Ye({...r,containerId:null});n.render(!0,t),this.customComponents.set(s,n),n.on("change",a=>{this.handleFieldChange(s,a.value)})}catch{}})}initializeComboInputs(){this.element.querySelectorAll('[data-field-type="combo"]').forEach(t=>{try{const s=t.getAttribute("data-field-name"),i=t.getAttribute("data-field-config"),r=JSON.parse(i),n=new We({...r,containerId:null});let a=$.getContextData(this.data,s);a&&n.setValue(a),n.render(!0,t),this.customComponents.set(s,n),n.on("change",o=>{this.handleFieldChange(s,o.value)}),n.on("select",o=>{this.emit("field:select",{field:s,value:o.value,option:o.option,meta:o.meta})})}catch(s){console.error("ComboInput initialization failed:",s)}})}handleFieldChange(e,t){this._isPopulating||(this.data[e]=t,this.autosaveModelField&&this.model?this.handleFieldSave(e,t):this.model&&this.options.allowModelChange&&(this._isFormDrivenChange=!0,this.model.set(e,t)),this.emit("field:change",{field:e,value:t}),this._updateShowWhen(e,t),Z.onFieldChange?.(this,e,t))}_initShowWhen(){if(this._showWhenMap={},!this.element)return;this.element.querySelectorAll("[data-show-when-field]").forEach(t=>{const s=t.getAttribute("data-show-when-field");this._showWhenMap[s]||(this._showWhenMap[s]=[]),this._showWhenMap[s].push(t),t.style.display==="none"?t.querySelectorAll("input, select, textarea").forEach(r=>{r.required&&(r.dataset.wasRequired="true",r.required=!1)}):t.querySelectorAll("input, select, textarea").forEach(r=>{r.required&&(r.dataset.wasRequired="true")})})}_updateShowWhen(e,t){const s=this._showWhenMap?.[e];if(!s)return;const i=String(t??"");s.forEach(r=>{const n=r.getAttribute("data-show-when-value").split(","),a=r.getAttribute("data-show-when-negate")==="true",o=n.includes(i),l=a?!o:o;r.style.display=l?"":"none",r.querySelectorAll("input, select, textarea").forEach(h=>{l?h.dataset.wasRequired==="true"&&(h.required=!0):(h.required&&(h.dataset.wasRequired="true"),h.required=!1)})})}async handleFieldSave(e,t){if(!this.model)return;this.pendingSaveFields.set(e,t),this.getFieldStatusManager(e).showStatus("saving"),this.batchSaveTimeout&&clearTimeout(this.batchSaveTimeout),this.batchSaveTimeout=setTimeout(async()=>{await this.executeBatchSave()},300)}async executeBatchSave(){if(this.isSaving||this.pendingSaveFields.size===0)return;const e=Object.fromEntries(this.pendingSaveFields),t=Array.from(this.pendingSaveFields.keys());try{if(this.isSaving=!0,this.pendingSaveFields.clear(),this.batchSaveTimeout=null,this._isFormDrivenChange=!0,typeof this.model.save=="function"){const s=await this.model.save(e);if(!s||!s.success||s.data&&!s.data.status){const i=s?.data?.error||s?.error||s?.message||"Save failed";this.getApp()?.toast?.error(i),this.revertFields(t),t.forEach(r=>{this.getFieldStatusManager(r).showStatus("error",{message:i})});return}}else Object.entries(e).forEach(([s,i])=>{this.model.set(s,i)});t.forEach(s=>{this.getFieldStatusManager(s).showStatus("saved")})}catch(s){console.error("Batch save error:",s),this.getApp()?.toast?.error(s.message||"An error occurred while saving"),this.revertFields(t),t.forEach(i=>{this.getFieldStatusManager(i).showStatus("error",{message:s.message})})}finally{this.isSaving=!1}}revertFields(e){if(!this.model)return;const t=this._isPopulating;this._isPopulating=!0;try{e.forEach(s=>{const i=this.model.get(s);this.data[s]=i;const r=this.element?.querySelector(`[name="${s}"]`);if(r){const n=this.getFormFieldConfig(s);n?this.setFieldValue(r,n,i):r.type==="checkbox"?r.checked=!!i:r.value=i??""}})}finally{this._isPopulating=t}}getFieldStatusManager(e){if(!this.fieldStatusManagers.has(e)){const t=this.element.querySelector(`[name="${e}"]`);if(t){const s=new us(t);this.fieldStatusManagers.set(e,s)}}return this.fieldStatusManagers.get(e)}refreshForm(){this.data=this.prepareFormData(),this.element&&this.populateFormValues()}getChangeReason(e,t){if(e instanceof File)return e.size===0||e.name===""||e.name==="blob"?"empty file, no change":`file upload: ${e.name}, ${e.size} bytes`;if(typeof e=="string"&&e.startsWith("data:image/"))return"base64 image upload";if(typeof e=="boolean"||typeof t=="boolean"){const s=!!e;return`boolean: ${t==null?!1:!!t} → ${s}`}return e==null||String(e).trim(),t==null||String(t).trim(),t==null?"was null/undefined, now has value":e==null?"was value, now null/undefined":"text content changed"}setFormData(e){this._originalData={...this._originalData,...e},this.refreshForm()}async onActionSubmitForm(e,t){e.preventDefault();const s=await this.handleSubmit();s.success?(this.data=s.data,this.emit("submit",{data:s.data,result:s.result,form:this,event:e}),!this.model&&this.formConfig.onSubmit&&typeof this.formConfig.onSubmit=="function"&&await this.formConfig.onSubmit(s.data,this)):this.emit("error",{error:s.error,result:s,form:this})}async onActionResetForm(e,t){const s=this.getFormElement();s&&(s.reset(),this.data={},this.clearAllErrors(),this.emit("reset",{form:this,event:e}))}async onActionClickImageUpload(e,t){console.log("FormView: onActionClickImageUpload called"),console.log("FormView: element:",t);const s=t.getAttribute("data-field-id");if(console.log("FormView: fieldId:",s),!s){console.error("FormView: No fieldId attribute found");return}const i=this.element.querySelector(`#${s}`);console.log("FormView: fileInput:",i),i&&!i.disabled?(i.click(),console.log("FormView: fileInput.click() called")):i?console.log("FormView: fileInput is disabled"):console.error("FormView: fileInput not found for fieldId:",s)}async onActionRemoveImage(e,t){const s=t.getAttribute("data-field");if(!s)return;const i=this.element.querySelector(`input[name="${s}"]`);i&&(i.value="",i.dispatchEvent(new Event("change",{bubbles:!0}))),delete this.data[s],this.emit("change",{field:s,value:null,form:this}),await this.updateField(s)}async onActionClearColor(e,t){const s=t.getAttribute("data-field");if(!s)return;const i=this.element.querySelector(`input[name="${s}"]`);i&&(i.value="",this.handleFieldChange(s,""),await this.updateField(s))}async onActionPreviewHtml(e,t){e.preventDefault();const s=t.getAttribute("data-target");if(!s)return;const i=this.element.querySelector(`#${s}`);if(!i)return;const r=i.value||"";(await Promise.resolve().then(()=>N)).default.htmlPreview({html:r,title:"HTML Preview"})}async onActionSelectButtonOption(e,t){const s=t.getAttribute("data-field"),i=t.getAttribute("data-value");if(!s||!i)return;this.data[s]=i;const r=t.closest(".btn-group");r&&(r.querySelectorAll("button").forEach(a=>{a.classList.remove("active"),a.classList.add("btn-outline-primary"),a.classList.remove("btn-primary")}),t.classList.add("active"),t.classList.remove("btn-outline-primary"),t.classList.add("btn-primary")),this.emit("field:changed",{field:s,value:i,form:this}),this.emit("change",{field:s,value:i,form:this}),this.emit("form:changed",await this.getFormData())}async onActionApplyFilter(e,t){const s=t.closest(".dropdown"),i=s?.querySelectorAll('input[type="checkbox"]');if(!i||i.length===0)return;const r=i[0].getAttribute("data-field");if(!r)return;const n=[];i.forEach(o=>{o.checked&&n.push(o.value)}),this.data[r]=n;const a=s.querySelector('[data-bs-toggle="dropdown"]');a&&window.bootstrap?.Dropdown&&window.bootstrap.Dropdown.getInstance(a)?.hide(),this.emit("field:changed",{field:r,value:n,form:this}),this.emit("change",{field:r,value:n,form:this}),this.emit("form:changed",await this.getFormData())}async onChangeValidateField(e,t){const s=t.name;if(s){const i=t.value;this.handleFieldChange(s,i),this.validateField(s)}}async onChangeToggleSwitch(e,t){const s=t.getAttribute("data-field");if(s){const i=t.checked;this.handleFieldChange(s,i),this.emit("switch:toggle",{field:s,checked:i,form:this})}}async onChangeImageSelected(e,t){console.log("FormView: onChangeImageSelected called"),console.log("FormView: element:",t),console.log("FormView: element.files:",t.files);const s=t.getAttribute("data-field"),i=t.files[0];if(console.log("FormView: fieldName:",s),console.log("FormView: file:",i),s&&i){console.log("FormView: fieldName and file exist, processing...");const r=this.findFieldConfig(s);console.log("FormView: fieldConfig:",r);const n=URL.createObjectURL(i);if(console.log("FormView: previewUrl created:",n),r&&r.imageSize){console.log("FormView: Image cropping is required, imageSize:",r.imageSize);try{const a=window.MOJO?.plugins?.ImageCropView;if(console.log("FormView: ImageCropView available?",!!a),!a){console.log("FormView: ImageCropView not available, falling back to normal handling"),this.data[s]=i,await this.updateImagePreview(s,n),this.emit("image:selected",{field:s,file:i,form:this});return}const o=await a.showDialog(n,{title:`Crop ${r.label||s}`,cropAndScale:r.imageSize,size:"lg"});if(o.action==="crop"&&o.data){const d=await(await fetch(o.data)).blob(),h=new File([d],i.name,{type:i.type||"image/png"});this.data[s]=h,await this.updateImagePreview(s,o.data),this.emit("image:selected",{field:s,file:h,originalFile:i,cropped:!0,cropData:o.cropData,form:this}),this.emit("change",{field:s,value:h,form:this})}else t.value=""}catch(a){console.error("FormView: Error during image cropping:",a),console.log("FormView: Falling back to normal image handling after error"),this.data[s]=i,await this.updateImagePreview(s,n),this.emit("image:selected",{field:s,file:i,form:this}),this.emit("change",{field:s,value:i,form:this})}}else console.log("FormView: Normal image handling (no cropping)"),this.data[s]=i,console.log("FormView: File stored in this.data["+s+"]"),await this.updateImagePreview(s,n),console.log("FormView: updateImagePreview completed"),this.emit("image:selected",{field:s,file:i,form:this}),console.log("FormView: image:selected event emitted")}else console.log("FormView: Missing fieldName or file - not processing")}async onChangeFileSelected(e,t){const s=Array.from(t.files);t.multiple?this.data[t.name]=t.files:this.data[t.name]=s[0]||null,this.emit("file:selected",{field:t.name,files:s,form:this}),this.emit("change",{field:t.name,value:s,form:this})}async onChangeRangeChanged(e,t){const s=t.name,i=t.value,r=t.getAttribute("data-target");if(r){const n=this.element.querySelector(`#${r}`);n&&(n.textContent=i)}s&&this.handleFieldChange(s,i),this.emit("range:changed",{field:s,value:i,form:this})}async onChangeFilterSearch(e,t){const s=t.value;this.emit("search",{query:s,field:t.name,form:this})}async onChangeFilterSelectOptions(e,t){const s=t.value.toLowerCase(),i=t.getAttribute("data-target"),r=i?this.element.querySelector(`#${i}`):null;r&&r.querySelectorAll("option").forEach(a=>{const o=a.textContent.toLowerCase();a.style.display=o.includes(s)?"":"none"})}async onFileDrop(e,t,s){const i=t.target.closest(".image-drop-zone");if(!i)return;const r=i.getAttribute("data-field");if(!r)return;const n=e[0],a=this.element.querySelector(`input[name="${r}"]`);if(a){const l=new DataTransfer;l.items.add(n),a.files=l.files,a.dispatchEvent(new Event("change",{bubbles:!0}))}this.data[r]=n;const o=URL.createObjectURL(n);await this.updateImagePreview(r,o),this.emit("image:dropped",{field:r,file:n,form:this})}async onFileDropError(e,t,s){this.showError(`File upload error: ${e.message}`),this.emit("file:error",{error:e,files:s,form:this})}getFormElement(){return this.element?this.element.querySelector("form"):null}getFormFieldConfig(e){const t=s=>{for(const i of s){if(i.name===e)return i;if(i.fields&&Array.isArray(i.fields)){const r=t(i.fields);if(r)return r}}return null};return t(this.formConfig.fields||[])}async getFormData(){const e=this.getFormElement();if(!e)return this.fileHandling==="multipart"?new FormData:{};if(this.fileHandling==="multipart"){const t=new FormData(e);for(const[s,i]of Object.entries(this.data))if(i instanceof File)t.set(s,i);else if(i instanceof FileList)for(let r=0;r<i.length;r++)t.append(`${s}[${r}]`,i[r]);return t}else{const t=new FormData(e),s={};for(const[a,o]of t.entries())s[a]?(Array.isArray(s[a])||(s[a]=[s[a]]),s[a].push(o)):s[a]=o;e.querySelectorAll('input[type="checkbox"]').forEach(a=>{s[a.name]=a.checked}),e.querySelectorAll('input[type="number"]').forEach(a=>{if(a.name&&s[a.name]!==void 0&&s[a.name]!==""){const o=Number(s[a.name]);isNaN(o)||(s[a.name]=o)}}),this.formConfig.fields?.forEach(a=>{if(a.type==="select"&&a.name&&s[a.name]!==void 0){const o=this.getFormFieldConfig(a.name);if(o?.options&&Array.isArray(o.options)&&o.options.every(d=>{const h=typeof d=="object"?d.value:d;return h===""||!isNaN(Number(h))})&&s[a.name]!==""){const d=Number(s[a.name]);isNaN(d)||(s[a.name]=d)}}}),e.querySelectorAll('[data-field-type="json"]').forEach(a=>{try{s[a.name]=JSON.parse(a.value)}catch{s[a.name]=a.value}}),this.customComponents.forEach((a,o)=>{a.getFormValue?s[o]=a.getFormValue():a.getValue&&(s[o]=a.getValue())}),this.element&&this.element.querySelectorAll("[data-show-when-field]").forEach(o=>{o.style.display==="none"&&o.querySelectorAll("[name]").forEach(d=>{delete s[d.name]})});for(const[a,o]of Object.entries(this.data))if(o instanceof File)try{s[a]=await this.fileToBase64(o)}catch{s[a]=null}else if(o instanceof FileList){const l=[];for(let d=0;d<o.length;d++)try{l.push(await this.fileToBase64(o[d]))}catch{l.push(null)}s[a]=l}return s}}_onModelChange(){this.isSaving||(this.data=this.prepareFormData(),this.isMounted()&&(this._isFormDrivenChange||this.syncFormWithModel(),this._isFormDrivenChange=!1))}syncFormWithModel(){!this.model||!this.element||this.formDataMatchesModelData(this.data)||this.populateFormValues()}formDataMatchesModelData(e){if(!this.formConfig?.fields||!this.element)return!0;for(const t of this.formConfig.fields)if(t.type==="group"&&t.fields){for(const s of t.fields)if(!this.fieldValueMatchesModel(s,e))return!1}else if(!this.fieldValueMatchesModel(t,e))return!1;return!0}fieldValueMatchesModel(e,t){if(!e.name)return!0;const s=this.element.querySelector(`[name="${e.name}"]`);if(!s)return!0;const i=this.getFieldCurrentValue(s,e),r=$.getContextData(t,e.name);return this.valuesAreDifferent(i,r)===!1}getFieldCurrentValue(e,t){switch(t.type){case"checkbox":case"toggle":case"switch":return e.checked;case"radio":const s=this.element.querySelector(`[name="${t.name}"]:checked`);return s?s.value:"";case"select":return e.multiple?Array.from(e.selectedOptions).map(i=>i.value):e.value;case"file":case"image":return null;case"json":try{return e.value?JSON.parse(e.value):null}catch{return e.value}default:return e.value}}setFieldValue(e,t,s){switch(t.type){case"checkbox":case"toggle":case"switch":e.checked=!!s;break;case"radio":const i=this.element.querySelector(`[name="${t.name}"][value="${s}"]`);i&&(i.checked=!0);break;case"select":e.multiple&&Array.isArray(s)?Array.from(e.options).forEach(r=>{r.selected=s.includes(r.value)}):e.value=s??"";break;case"file":case"image":break;case"json":if(typeof s=="object"&&s!==null)try{e.value=JSON.stringify(s,null,2)}catch{e.value="{}"}else typeof s=="string"?e.value=s:e.value=String(s||"");break;default:e.value=s||"";break}e.dispatchEvent(new Event("change",{bubbles:!0}))}setDefaults(e){this.defaults={...this.defaults,...e},this.refreshForm()}async handleSubmit(){try{const e=await this.getFormData();if(this.formConfig.validateOnSubmit!==!1&&!this.validate())return this.focusFirstError(),{success:!1,data:e,error:"Form validation failed"};if(this.model&&typeof this.model.save=="function"){const t=await this.saveModel(e);if(t&&t.success!==!1)return{success:!0,data:e,result:t};{const s=t?.message||t?.error||"Save failed. Please try again.";return{success:!1,data:e,result:t,error:s}}}else return e}catch(e){return{success:!1,error:e.message||"An error occurred while submitting the form"}}}async saveModel(e=null){if(!this.model||typeof this.model.save!="function")throw new Error("No model available for saving");e||(e=await this.getFormData());const t=this.getChangedData(e);if(!t||Object.keys(t).length===0)return{success:!0,message:"No changes to save",data:e};try{return this._isFormDrivenChange=!0,await this.model.save(t)}catch(s){throw s}}getChangedData(e){if(!this.model)return e;const t=this.getOriginalModelData();let s;return e instanceof FormData?s=this.getChangedFormData(e,t):s=this.getChangedObjectData(e,t),s}getOriginalModelData(){return this.model.attributes?this.model.attributes:typeof this.model.toJSON=="function"?this.model.toJSON():{}}getChangedFormData(e,t){const s=new FormData;let i=!1;for(const[r,n]of e.entries())if(n instanceof File)n.size===0||n.name===""||n.name==="blob"||(s.set(r,n),i=!0);else{const a=t[r];n!==a&&n!==String(a)&&(s.set(r,n),i=!0)}return i?s:null}getChangedObjectData(e,t){const s={};let i=!1;const r=new Set([...Object.keys(t),...Object.keys(e)]),n=(a,o)=>o.split(".").reduce((l,d)=>l&&typeof l=="object"?l[d]:void 0,a);for(const a of r){const o=this.findFieldConfig(a);if(!o)continue;const l=e[a],d=n(t,a),h=o.type||"text";this.valuesAreDifferent(l,d,h,o)&&(s[a]=l,i=!0)}return i?s:null}valuesAreDifferent(e,t,s="text",i={}){if(e instanceof File)return e.size>0&&e.name!==""&&e.name!=="blob";if(typeof e=="string"&&e.startsWith("data:image/"))return!0;if(s==="collection"&&typeof t=="object"&&t!==null&&t!==void 0&&typeof e=="string"){if(e==="0")return t!==null;const a=i.valueField||"id";if(t[a]==e)return!1}if(s==="switch"||s==="checkbox"||s==="toggle")return!!e!==!!t;const r=e==null?"":String(e).trim(),n=t==null?"":String(t).trim();return r!==n}validate(){const e=this.getFormElement();if(!e)return!1;const t=e.checkValidity();return t||e.classList.add("was-validated"),t}validateField(e){const t=this.getFormElement();if(!t)return!1;const s=t.elements[e];if(!s)return!1;const i=s.checkValidity();return i?(s.classList.remove("is-invalid"),s.classList.add("is-valid"),delete this.errors[e]):(s.classList.remove("is-valid"),s.classList.add("is-invalid"),this.errors[e]=s.validationMessage),i}focusFirstError(){const e=this.getFormElement();if(!e)return;const t=e.querySelector(":invalid");if(!t)return;const s=t.closest(".tab-pane");if(s&&!s.classList.contains("active")){const i=s.id,r=e.querySelector(`[role="tab"][aria-controls="${i}"], [data-bs-target="#${i}"]`);if(r){const n=window.bootstrap?.Tab?.getOrCreateInstance?window.bootstrap.Tab.getOrCreateInstance(r):null;n&&typeof n.show=="function"?n.show():(e.querySelectorAll('[role="tab"].nav-link').forEach(l=>{const d=l===r;l.classList.toggle("active",d),l.setAttribute("aria-selected",d?"true":"false")}),e.querySelectorAll(".tab-pane").forEach(l=>l.classList.remove("show","active")),s.classList.add("show","active"))}}t.focus(),t.scrollIntoView({behavior:"smooth",block:"center"})}clearAllErrors(){const e=this.getFormElement();if(!e)return;this.errors={},e.classList.remove("was-validated"),e.querySelectorAll(".is-invalid").forEach(i=>i.classList.remove("is-invalid")),e.querySelectorAll(".is-valid").forEach(i=>i.classList.remove("is-valid"))}setLoading(e){this.loading=e;const t=this.getFormElement();if(!t)return;const s=t.querySelectorAll("input, select, textarea, button"),i=t.querySelector('button[type="submit"]');if(e)s.forEach(r=>r.disabled=!0),i&&(i.innerHTML='<span class="spinner-border spinner-border-sm me-2"></span>Loading...');else if(s.forEach(r=>r.disabled=!1),i){const r=this.formConfig.options?.submitButton||"Submit";i.innerHTML=typeof r=="string"?r:"Submit"}}showError(e){if(this.emit("error",{message:e,form:this}),this.element){this.element.querySelectorAll(".alert").forEach(i=>i.remove());const s=document.createElement("div");s.className="alert alert-danger alert-dismissible fade show",s.innerHTML=`
1190
1190
  ${e}
1191
1191
  <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
1192
1192
  `,this.element.insertBefore(s,this.element.firstChild),setTimeout(()=>{s.parentNode&&s.remove()},5e3)}}async updateField(e){this.formBuilder=new me({...this.getFormConfig(),data:this.data,errors:this.errors}),await this.render()}async updateImagePreview(e,t){const s=this.element.querySelector(`[data-field="${e}"].image-drop-zone`);if(!s)return;let i=s.querySelector("img");const r=s.querySelector(".bi-image")?.parentElement,n=s.getAttribute("data-field-id");if(t){if(i)i.src=t;else{const a=`${n}_preview`;s.innerHTML=`
@@ -1224,7 +1224,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
1224
1224
  </div>
1225
1225
  <i class="bi bi-check-circle text-success d-none" data-status="saved"></i>
1226
1226
  <i class="bi bi-exclamation-circle text-danger d-none" data-status="error"></i>
1227
- `}showStatus(e,t={}){this.clearTimeout(e),this.showStandardStatus(e,t)}showStandardStatus(e,t={}){this.hideAllStatuses();const s=this.statusContainer.querySelector(`[data-status="${e}"]`);s&&(s.classList.remove("d-none"),s.classList.add("d-inline-block","show"),e==="saved"?this.setTimeout(e,()=>this.hideStatus(e),2500):e==="error"&&(t.message&&(s.title=t.message),this.setTimeout(e,()=>this.hideStatus(e),6e3)))}showFullOverlayStatus(e,t={}){this.statusContainer.querySelectorAll(".saving-indicator, .success-indicator, .error-indicator").forEach(r=>r.classList.add("d-none")),this.statusContainer.classList.remove("d-none");let i;switch(e){case"saving":i=".saving-indicator";break;case"saved":i=".success-indicator",this.setTimeout(e,()=>this.hideStatus(e),2500);break;case"error":if(i=".error-indicator",t.message){const r=this.statusContainer.querySelector(".error-indicator span");r&&(r.textContent=t.message)}this.setTimeout(e,()=>this.hideStatus(e),6e3);break}if(i){const r=this.statusContainer.querySelector(i);r&&r.classList.remove("d-none")}}hideStatus(e){const t=this.statusContainer.querySelector(`[data-status="${e}"]`);t&&(t.classList.remove("show"),t.classList.add("hide"),setTimeout(()=>{t.classList.add("d-none"),t.classList.remove("d-inline-block","hide"),t.title=""},300))}hideAllStatuses(){this.statusContainer.querySelectorAll("[data-status]").forEach(t=>{t.classList.add("d-none"),t.classList.remove("d-inline-block","show","hide"),t.title=""})}setTimeout(e,t,s){const i=setTimeout(t,s);this.timeouts.set(e,i)}clearTimeout(e){this.timeouts.has(e)&&(clearTimeout(this.timeouts.get(e)),this.timeouts.delete(e))}destroy(){this.timeouts.forEach(e=>clearTimeout(e)),this.timeouts.clear()}}Bt(Q);const _t=Object.freeze(Object.defineProperty({__proto__:null,FormView:Q,default:Q},Symbol.toStringTag,{value:"Module"}));class ms extends ue{constructor(e={}){super({title:"Form Page",description:"A page for submitting forms",icon:"form",fields:[],template:'<div data-container="form-view-container"></div>',className:"form-page container-sm",...e})}async onInit(){await super.onInit(),await this.recreateFormView()}async onEnter(){await super.onEnter(),this.formView&&await this.recreateFormView()}async onGroupChange(e){this.formView&&await this.recreateFormView()}async getModel(){return this.model?this.model:this.getApp().activeGroup?this.getApp().activeGroup:null}async recreateFormView(){this.formView&&(await this.formView.destroy(),this.removeChild(this.formView)),this.formView=new Q({containerId:"form-view-container",fields:this.options.fields,autosaveModelField:!0}),this.addChild(this.formView);const e=await this.getModel();e&&this.formView.setModel(e)}}_.showDialog=(...c)=>v.dialog(...c),_.alert=(...c)=>v.alert(...c),_.confirm=(...c)=>v.confirm(...c),_.prompt=(...c)=>v.prompt(...c),_.showError=(...c)=>v.showError(...c),_.showForm=(...c)=>v.form(...c),_.showModelForm=(...c)=>v.modelForm(...c),_.showData=(...c)=>v.data(...c),_.showModelView=(...c)=>v.showModelView(...c),_.updateModelImage=(...c)=>v.updateModelImage(...c),_.showCode=(...c)=>v.code(...c),_.showHtmlPreview=(...c)=>v.htmlPreview(...c),_.formatCode=(...c)=>he.formatCode(...c),_.highlightCodeBlocks=(...c)=>he.highlightCodeBlocks(...c),_.showBusy=(...c)=>v.showBusy(...c),_.hideBusy=(...c)=>v.hideBusy(...c),_.showConfirm=_.confirm;class xe extends C{constructor(e={}){super({className:"list-view-item",...e}),this.selected=!1,this.index=e.index??0,this.listView=e.listView??null,this.template||(this.template=`
1227
+ `}showStatus(e,t={}){this.clearTimeout(e),this.showStandardStatus(e,t)}showStandardStatus(e,t={}){this.hideAllStatuses();const s=this.statusContainer.querySelector(`[data-status="${e}"]`);s&&(s.classList.remove("d-none"),s.classList.add("d-inline-block","show"),e==="saved"?this.setTimeout(e,()=>this.hideStatus(e),2500):e==="error"&&(t.message&&(s.title=t.message),this.setTimeout(e,()=>this.hideStatus(e),6e3)))}showFullOverlayStatus(e,t={}){this.statusContainer.querySelectorAll(".saving-indicator, .success-indicator, .error-indicator").forEach(r=>r.classList.add("d-none")),this.statusContainer.classList.remove("d-none");let i;switch(e){case"saving":i=".saving-indicator";break;case"saved":i=".success-indicator",this.setTimeout(e,()=>this.hideStatus(e),2500);break;case"error":if(i=".error-indicator",t.message){const r=this.statusContainer.querySelector(".error-indicator span");r&&(r.textContent=t.message)}this.setTimeout(e,()=>this.hideStatus(e),6e3);break}if(i){const r=this.statusContainer.querySelector(i);r&&r.classList.remove("d-none")}}hideStatus(e){const t=this.statusContainer.querySelector(`[data-status="${e}"]`);t&&(t.classList.remove("show"),t.classList.add("hide"),setTimeout(()=>{t.classList.add("d-none"),t.classList.remove("d-inline-block","hide"),t.title=""},300))}hideAllStatuses(){this.statusContainer.querySelectorAll("[data-status]").forEach(t=>{t.classList.add("d-none"),t.classList.remove("d-inline-block","show","hide"),t.title=""})}setTimeout(e,t,s){const i=setTimeout(t,s);this.timeouts.set(e,i)}clearTimeout(e){this.timeouts.has(e)&&(clearTimeout(this.timeouts.get(e)),this.timeouts.delete(e))}destroy(){this.timeouts.forEach(e=>clearTimeout(e)),this.timeouts.clear()}}Bt(Q);const _t=Object.freeze(Object.defineProperty({__proto__:null,FormView:Q,default:Q},Symbol.toStringTag,{value:"Module"}));class ms extends ue{constructor(e={}){super({title:"Form Page",description:"A page for submitting forms",icon:"form",fields:[],template:'<div data-container="form-view-container"></div>',className:"form-page container-sm",...e})}async onInit(){await super.onInit(),await this.recreateFormView()}async onEnter(){await super.onEnter(),this.formView&&await this.recreateFormView()}async onGroupChange(e){this.formView&&await this.recreateFormView()}async getModel(){return this.model?this.model:this.getApp().activeGroup?this.getApp().activeGroup:null}async recreateFormView(){this.formView&&(await this.formView.destroy(),this.removeChild(this.formView)),this.formView=new Q({containerId:"form-view-container",fields:this.options.fields,autosaveModelField:!0}),this.addChild(this.formView);const e=await this.getModel();e&&this.formView.setModel(e)}}_.showDialog=(...c)=>w.dialog(...c),_.alert=(...c)=>w.alert(...c),_.confirm=(...c)=>w.confirm(...c),_.prompt=(...c)=>w.prompt(...c),_.showError=(...c)=>w.showError(...c),_.showForm=(...c)=>w.form(...c),_.showModelForm=(...c)=>w.modelForm(...c),_.showData=(...c)=>w.data(...c),_.showModelView=(...c)=>w.showModelView(...c),_.updateModelImage=(...c)=>w.updateModelImage(...c),_.showCode=(...c)=>w.code(...c),_.showHtmlPreview=(...c)=>w.htmlPreview(...c),_.formatCode=(...c)=>he.formatCode(...c),_.highlightCodeBlocks=(...c)=>he.highlightCodeBlocks(...c),_.showBusy=(...c)=>w.showBusy(...c),_.hideBusy=(...c)=>w.hideBusy(...c),_.showConfirm=_.confirm;class xe extends C{constructor(e={}){super({className:"list-view-item",...e}),this.selected=!1,this.index=e.index??0,this.listView=e.listView??null,this.template||(this.template=`
1228
1228
  <div class="list-item-content" data-action="select">
1229
1229
  {{#model}}
1230
1230
  {{#id}}<span class="item-id">{{id}}</span>{{/id}}
@@ -1371,7 +1371,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
1371
1371
  </button>
1372
1372
  </div>
1373
1373
  </div>
1374
- `}setupEditorEvents(e,t,s){const i=e.querySelector(".cell-input"),r=e.querySelector(".cell-save"),n=e.querySelector(".cell-cancel");i&&(i.type==="text"||i.type==="email"||i.type==="number")&&i.addEventListener("keydown",a=>{a.key==="Enter"?(a.preventDefault(),this.saveCellEdit(e,t,s)):a.key==="Escape"&&(a.preventDefault(),this.cancelCellEdit(e,t))}),i&&(i.type==="checkbox"||i.tagName==="SELECT")&&s.autoSave!==!1&&i.addEventListener("change",()=>{this.saveCellEdit(e,t,s)}),r?.addEventListener("click",()=>{this.saveCellEdit(e,t,s)}),n?.addEventListener("click",()=>{this.cancelCellEdit(e,t)})}async saveCellEdit(e,t,s){const i=e.querySelector(".cell-input");if(!i)return;let r;i.type==="checkbox"?r=i.checked:(i.tagName,r=i.value);const n=this.model.get?this.model.get(t):this.model[t];try{this.model.save?await this.model.save({[t]:r}):this.model[t]=r,this.exitEditMode(e,t,r),this.emit("cell:save",{row:this,model:this.model,column:t,oldValue:n,newValue:r})}catch(a){console.error("Failed to save cell edit:",a),this.emit("cell:save:error",{row:this,model:this.model,column:t,oldValue:n,newValue:r,error:a}),e.classList.add("saving-error"),setTimeout(()=>e.classList.remove("saving-error"),3e3)}}cancelCellEdit(e,t){const s=e.dataset.originalContent;this.exitEditMode(e,t,null,s),this.emit("cell:cancel",{row:this,model:this.model,column:t})}exitEditMode(e,t,s=null,i=null){const n=e.closest("td").querySelector(".cell-content");if(n){if(s!==null){const a=this.columns.find(l=>l.key===t);let o=s;a&&a.formatter&&typeof a.formatter=="string"&&(o=V.pipe(s,a.formatter)),n.innerHTML=this.escapeHtml(o)}else i&&(n.innerHTML=i);n.style.display=""}e.remove(),this.editingCells.delete(t)}escapeHtml(e){if(e==null)return"";const t=document.createElement("div");return t.textContent=e,t.innerHTML}select(){super.select(),this.addClass("selected");const e=this.element?.querySelector(".mojo-select-cell");e&&e.classList.add("selected")}deselect(){super.deselect(),this.removeClass("selected");const e=this.element?.querySelector(".mojo-select-cell");e&&e.classList.remove("selected")}}const xt={exact:{display:"is",description:"Exact match"},in:{display:"in",description:"Match any of the values (comma-separated)"},not:{display:"is not",description:"Does not match"},not_in:{display:"not in",description:"Does not match any of the values"},gt:{display:">",description:"Greater than"},gte:{display:">=",description:"Greater than or equal to"},lt:{display:"<",description:"Less than"},lte:{display:"<=",description:"Less than or equal to"},contains:{display:"contains",description:"Contains substring (case-sensitive)"},icontains:{display:"contains",description:"Contains substring (case-insensitive)"},startswith:{display:"starts with",description:"Starts with substring (case-sensitive)"},istartswith:{display:"starts with",description:"Starts with substring (case-insensitive)"},endswith:{display:"ends with",description:"Ends with substring (case-sensitive)"},iendswith:{display:"ends with",description:"Ends with substring (case-insensitive)"},isnull:{display:c=>c==="true"||c===!0?"is null":"is not null",description:"Check if value is null or not"},range:{display:"between",description:"Between two values (comma-separated)"}};function pe(c){if(!c||typeof c!="string")return{field:c,lookup:null};const e=c.split("__");if(e.length===1)return{field:c,lookup:null};const t=e[e.length-1];return xt[t]?{field:e.slice(0,-1).join("__"),lookup:t}:{field:c,lookup:null}}function ps(c,e,t){if(!c||e===null||e===void 0)return"";const{field:s,lookup:i}=pe(c),r=xt[i];if(e&&typeof e=="object"&&!Array.isArray(e)){const a=e.start!==void 0&&e.start!==null&&e.start!=="",o=e.end!==void 0&&e.end!==null&&e.end!=="";return a||o?a&&o?`${t} between '${e.start}' and '${e.end}'`:a?`${t} from '${e.start}'`:`${t} until '${e.end}'`:`${t} is '${JSON.stringify(e)}'`}const n=Array.isArray(e)?e.join(","):String(e);if(!i||i==="exact")return`${t} is '${n}'`;if(i==="in"||i==="not_in"){const a=n.split(",").map(l=>l.trim()).filter(l=>l);if(a.length===0)return`${t} ${r.display}`;const o=a.map(l=>`'${l}'`).join(", ");return`${t} ${r.display} ${o}`}if(i==="range"){const a=n.split(",").map(o=>o.trim()).filter(o=>o);return a.length===2?`${t} between '${a[0]}' and '${a[1]}'`:`${t} ${r.display} '${n}'`}if(i==="isnull"){const a=typeof r.display=="function"?r.display(n):r.display;return`${t} ${a}`}return r?`${t} ${r.display} '${n}'`:`${t} is '${n}'`}class $t extends Ge{constructor(e={}){const t={className:"table-view-component",itemClass:e.itemClass||Je,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.clickAction=e.clickAction||"view",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.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();console.log("Updating footer totals in DOM:",e);let t=0;this.columns.forEach(s=>{if(s.footer_total){const i=`col_${t}`,r=this.element.querySelector(`[data-total-column="${i}"]`);if(r&&e[i]){const n=this.parseColumnKey(s.key).formatter||s.formatter;let a;n&&typeof n=="string"?a=this.formatValue(e[i].value,n):a=e[i].value,r.textContent=a}t++}})}formatValue(e,t){try{return V.pipe(e,t)}catch(s){return console.warn("Error formatting value:",s),e}}calculateFooterTotals(){if(!this.hasFooterTotals||!this.collection||this.collection.length===0)return{};const e={};return this.footerTotalColumns.forEach((t,s)=>{const{fieldKey:i,formatter:r}=this.parseColumnKey(t.key);let n=0;this.collection.forEach(o=>{const l=o.get?o.get(i):o[i],d=parseFloat(l)||0;n+=d}),console.log(`Footer total for ${t.key}: ${n} (from ${this.collection.length} items)`);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}})}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():"";return`
1374
+ `}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")}}const xt={exact:{display:"is",description:"Exact match"},in:{display:"in",description:"Match any of the values (comma-separated)"},not:{display:"is not",description:"Does not match"},not_in:{display:"not in",description:"Does not match any of the values"},gt:{display:">",description:"Greater than"},gte:{display:">=",description:"Greater than or equal to"},lt:{display:"<",description:"Less than"},lte:{display:"<=",description:"Less than or equal to"},contains:{display:"contains",description:"Contains substring (case-sensitive)"},icontains:{display:"contains",description:"Contains substring (case-insensitive)"},startswith:{display:"starts with",description:"Starts with substring (case-sensitive)"},istartswith:{display:"starts with",description:"Starts with substring (case-insensitive)"},endswith:{display:"ends with",description:"Ends with substring (case-sensitive)"},iendswith:{display:"ends with",description:"Ends with substring (case-insensitive)"},isnull:{display:c=>c==="true"||c===!0?"is null":"is not null",description:"Check if value is null or not"},range:{display:"between",description:"Between two values (comma-separated)"}};function pe(c){if(!c||typeof c!="string")return{field:c,lookup:null};const e=c.split("__");if(e.length===1)return{field:c,lookup:null};const t=e[e.length-1];return xt[t]?{field:e.slice(0,-1).join("__"),lookup:t}:{field:c,lookup:null}}function ps(c,e,t){if(!c||e===null||e===void 0)return"";const{field:s,lookup:i}=pe(c),r=xt[i];if(e&&typeof e=="object"&&!Array.isArray(e)){const a=e.start!==void 0&&e.start!==null&&e.start!=="",o=e.end!==void 0&&e.end!==null&&e.end!=="";return a||o?a&&o?`${t} between '${e.start}' and '${e.end}'`:a?`${t} from '${e.start}'`:`${t} until '${e.end}'`:`${t} is '${JSON.stringify(e)}'`}const n=Array.isArray(e)?e.join(","):String(e);if(!i||i==="exact")return`${t} is '${n}'`;if(i==="in"||i==="not_in"){const a=n.split(",").map(l=>l.trim()).filter(l=>l);if(a.length===0)return`${t} ${r.display}`;const o=a.map(l=>`'${l}'`).join(", ");return`${t} ${r.display} ${o}`}if(i==="range"){const a=n.split(",").map(o=>o.trim()).filter(o=>o);return a.length===2?`${t} between '${a[0]}' and '${a[1]}'`:`${t} ${r.display} '${n}'`}if(i==="isnull"){const a=typeof r.display=="function"?r.display(n):r.display;return`${t} ${a}`}return r?`${t} ${r.display} '${n}'`:`${t} is '${n}'`}class $t extends Ge{constructor(e={}){const t={className:"table-view-component",itemClass:e.itemClass||Je,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.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.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();console.log("Updating footer totals in DOM:",e);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}),console.log(`Footer total for ${t.key}: ${n} (from ${this.collection.length} items)`);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}})}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():"";return`
1375
1375
  <div class="mojo-table-wrapper">
1376
1376
  ${this.buildToolbarTemplate()}
1377
1377
  ${e}
@@ -1669,7 +1669,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
1669
1669
  </nav>
1670
1670
  </div>
1671
1671
  </div>
1672
- `:""}_createItemView(e,t){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),s.on("item:select",i=>{this._onItemSelect(i),this.updateBatchActionsPanel()}),s.on("item:deselect",i=>{this._onItemDeselect(i),this.updateBatchActionsPanel()}),s.on("row:click",this._onRowClick.bind(this)),s.on("row:view",this._onRowView.bind(this)),s.on("row:edit",this._onRowEdit.bind(this)),s.on("row:delete",this._onRowDelete.bind(this)),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 onMounted(){await super.onMounted();const e=this.getActiveFilters();this.collection&&Object.keys(e).length>0&&this.updateFilterPills(),this.setupSearchClearListener()}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)})})}_onRowClick(e){if(this.emit("row:click",e),this.options.onRowClick)return this.options.onRowClick(e.model,e.event);this.clickAction==="view"?this._onRowView(e):this.clickAction==="edit"&&this._onRowEdit(e)}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 _onRowView(e){if(this.emit("row:view",e),this.options.onItemView){await this.options.onItemView(e.model,e.event);return}const t=this.getItemViewClass(e.model);if(t){const s=new t({model:e.model,collection:this.collection});await v.dialog({header:!1,body:s,size:"lg",centered:!1,...this.getFormDialogConfig(this.getModelClass(e.model)),...this.viewDialogOptions})}else await v.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 v.modelForm({model:e.model,...s,...this.getFormDialogConfig(t)});if(!i)return;if(!i.success||!i?.result?.data.status){v.showError(i?.result?.data?.error||i?.result?.message||"An error occurred");return}}else{const i=await v.dialog({title:`Edit ${this.getModelName(e.model)} #${e.model.id}`,body:new Q({model:e.model,fields:this.options.formFields||[]})});if(i){const r=await e.model.save(i);if(!r.data?.status){v.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 v.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.fetch())}_onCellEdit(e){this.emit("cell:edit",e)}async _onCellSave(e){this.emit("cell:save",e)}_onCellCancel(e){this.emit("cell:cancel",e)}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 onActionRefresh(e,t){await this.refresh()}async onActionAdd(e,t){if(this.options.onAdd){this.emit("table:add",{event:e}),await this.options.onAdd(e);return}this.emit("table: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 v.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){v.showError(a?.data.error||"An error occurred");return}this.collection&&this.collection.add(r),await this.refresh()}}else{const r=new s,n=await v.dialog({title:`Add ${this.getModelName()}`,body:new Q({model:r,fields:this.options.formFields||[]})});if(n){const a=await r.save(n);if(!a?.data.status){v.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("table:export",{format:s,source:this.exportSource,event:e}),this.exportSource==="remote"?this.collection?await this.collection.download(s):console.warn("TableView: Cannot export from remote without a collection."):this.options.onExport?await this.options.onExport(this.collection?.toJSON()||[],s):console.warn("TableView: onExport handler not implemented for local export.")}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("table:search",{searchTerm:s,event:e}),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("table:search",{searchTerm:"",event:e}),this.emit("params-changed")}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()}async onBeforeRender(){this.searchValue=this.getActiveFilters().search||"",this.footerTotals=this.calculateFooterTotals()}async onAfterRender(){if(await super.onAfterRender(),this.hasFooterTotals&&this.updateFooterTotals(),this.paginated&&this.collection){const e=this.collection.meta?.count||this.collection.length(),t=this.collection.params?.start||0,s=this.collection.params?.size||10,i=Math.min(t+s,e),r=this.element.querySelector('[data-value="start"]'),n=this.element.querySelector('[data-value="end"]'),a=this.element.querySelector('[data-value="total"]');r&&(r.textContent=t+1),n&&(n.textContent=i),a&&(a.textContent=e);const o=this.element.querySelector('[data-change-action="page-size"]');o&&(o.value=s),this.renderPagination()}this.updateSortIcons(),this.updateFilterPills(),this.setupSearchClearListener()}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(`
1672
+ `:""}_createItemView(e,t){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),s.on("item:select",i=>{this._onItemSelect(i),this.updateBatchActionsPanel()}),s.on("item:deselect",i=>{this._onItemDeselect(i),this.updateBatchActionsPanel()}),s.on("row:click",this._onRowClick.bind(this)),s.on("row:view",this._onRowView.bind(this)),s.on("row:edit",this._onRowEdit.bind(this)),s.on("row:delete",this._onRowDelete.bind(this)),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 onMounted(){await super.onMounted();const e=this.getActiveFilters();this.collection&&Object.keys(e).length>0&&this.updateFilterPills(),this.setupSearchClearListener()}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)})})}_onRowClick(e){if(this.emit("row:click",e),this.options.onRowClick)return this.options.onRowClick(e.model,e.event);this.clickAction==="view"?this._onRowView(e):this.clickAction==="edit"&&this._onRowEdit(e)}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 _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 Q({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.fetch())}_onCellEdit(e){this.emit("cell:edit",e)}async _onCellSave(e){this.emit("cell:save",e)}_onCellCancel(e){this.emit("cell:cancel",e)}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 onActionRefresh(e,t){await this.refresh()}async onActionAdd(e,t){if(this.options.onAdd){this.emit("table:add",{event:e}),await this.options.onAdd(e);return}this.emit("table: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 Q({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("table:export",{format:s,source:this.exportSource,event:e}),this.exportSource==="remote"?this.collection?await this.collection.download(s):console.warn("TableView: Cannot export from remote without a collection."):this.options.onExport?await this.options.onExport(this.collection?.toJSON()||[],s):console.warn("TableView: onExport handler not implemented for local export.")}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("table:search",{searchTerm:s,event:e}),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("table:search",{searchTerm:"",event:e}),this.emit("params-changed")}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()}async onBeforeRender(){this.searchValue=this.getActiveFilters().search||"",this.footerTotals=this.calculateFooterTotals()}async onAfterRender(){if(await super.onAfterRender(),this.hasFooterTotals&&this.updateFooterTotals(),this.paginated&&this.collection){const e=this.collection.meta?.count||this.collection.length(),t=this.collection.params?.start||0,s=this.collection.params?.size||10,i=Math.min(t+s,e),r=this.element.querySelector('[data-value="start"]'),n=this.element.querySelector('[data-value="end"]'),a=this.element.querySelector('[data-value="total"]');r&&(r.textContent=t+1),n&&(n.textContent=i),a&&(a.textContent=e);const o=this.element.querySelector('[data-change-action="page-size"]');o&&(o.value=s),this.renderPagination()}this.updateSortIcons(),this.updateFilterPills(),this.setupSearchClearListener()}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(`
1673
1673
  <li class="page-item">
1674
1674
  <a class="page-link" href="#" data-action="page" data-page="${a}">
1675
1675
  <i class="bi bi-chevron-left"></i>
@@ -1687,11 +1687,11 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
1687
1687
  <i class="bi bi-chevron-right"></i>
1688
1688
  </a>
1689
1689
  </li>
1690
- `),e.innerHTML=l.join("")}async onActionPage(e,t){e.preventDefault();const s=parseInt(t.getAttribute("data-page"),10),i=this.collection.params?.size||10,r=this.collection.meta?.count||this.collection.length(),n=Math.max(1,Math.ceil(r/i));let a=isNaN(s)?1:s;a<1&&(a=n),a>n&&(a=1),this.collection.setParams({...this.collection.params,start:(a-1)*i}),this.collection.restEnabled?await this.collection.fetch():this.render(),this.emit("table:page",{page:a,event:e}),this.emit("params-changed")}async onChangePageSize(e,t){const s=parseInt(t.value);this.collection&&(this.collection.setParams({...this.collection.params,start:0,size:s}),this.collection.restEnabled&&await this.collection.fetch(),this.render()),this.emit("table:pagesize",{size:s,event:e}),this.emit("params-changed")}getActiveFilters(){if(!this.collection?.params)return{};const{start:e,size:t,sort:s,...i}=this.collection.params,r={},n=new Set;return this.getAllAvailableFilters().forEach(o=>{if(o.config.type==="daterange"){const l=o.key,d=o.config.startName||"dr_start",h=o.config.endName||"dr_end",u=o.config.fieldName||"dr_field";i[u]===l&&(i[d]||i[h])&&(r[l]={start:i[d]||"",end:i[h]||""},n.add(d),n.add(h),n.add(u))}}),Object.keys(i).forEach(o=>{n.has(o)||(r[o]=i[o])}),Object.keys(r).forEach(o=>{if(r.hasOwnProperty(o)){const l=`${o}__in`;r.hasOwnProperty(l)&&(delete r[o],r[l]=r[l])}}),r}setFilter(e,t){if(!this.collection)return;const s=this.getFilterConfig(e);if(s&&s.type==="daterange"){const i=s.startName||"dr_start",r=s.endName||"dr_end",n=s.fieldName||"dr_field";delete this.collection.params[i],delete this.collection.params[r],delete this.collection.params[n],t&&typeof t=="object"&&(t.start||t.end)&&(t.start&&(this.collection.params[i]=t.start),t.end&&(this.collection.params[r]=t.end),this.collection.params[n]=e)}else{const{field:i,lookup:r}=pe(e);if(delete this.collection.params[e],delete this.collection.params[i],delete this.collection.params[`${i}__in`],!t||Array.isArray(t)&&t.length===0)return;Array.isArray(t)?t.length===1?this.collection.params[i]=t[0]:this.collection.params[`${i}__in`]=t.join(","):this.collection.params[e]=t}}getAllAvailableFilters(){const e=[];return this.columns.forEach(t=>{if(t.filter){const{fieldKey:s}=this.parseColumnKey(t.key);e.push({key:s,label:t.filter.label||t.label||s,type:t.filter.type,config:t.filter})}}),this.additionalFilters&&Array.isArray(this.additionalFilters)&&this.additionalFilters.forEach(t=>{e.push({key:t.name||t.key,label:t.label,type:t.type,config:t})}),e}getFilterConfig(e){const t=this.columns.find(s=>{const{fieldKey:i}=this.parseColumnKey(s.key);return i===e});if(t&&t.filter)return t.filter;if(this.additionalFilters&&Array.isArray(this.additionalFilters)){const s=this.additionalFilters.find(i=>(i.name||i.key)===e);if(s)return s}return null}getFilterLabel(e){if(e==="search")return"Search";const t=this.filters[e];if(t&&t.label)return t.label;const s=this.additionalFilters.find(i=>(i.name||i.key)===e);return s&&s.label?s.label:e.charAt(0).toUpperCase()+e.slice(1)}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}getFilterIcon(e){return{text:"search",select:"funnel",date:"calendar",daterange:"calendar-range",number:"123",boolean:"toggle-on"}[e]||"filter"}async onActionAddFilter(e,t){const s=t.getAttribute("data-filter-key"),i=this.getFilterConfig(s),r=this.getActiveFilters()[s];if(!i){console.warn("No filter config found for key:",s);return}const n=await v.form({title:`${r!==void 0&&r!==""?"Edit":"Add"} ${this.getFilterLabel(s)} Filter`,size:"md",fields:[this.buildFilterDialogField(i,r,s)]});if(n){const a=this.extractFilterValue(i,n);this.setFilter(s,a),await this.applyFilters()}}buildFilterDialogField(e,t,s){const{name:i,value:r,...n}=e,a={...n,name:"filter_value",label:n.label,value:t,placeholder:n.placeholder||n.placeHolder};if(e.type==="daterange"){if(a.startName=a.startName||"dr_start",a.endName=a.endName||"dr_end",a.fieldName=a.fieldName||"dr_field",a.format=a.format||"YYYY-MM-DD",a.displayFormat=a.displayFormat||"MMM DD, YYYY",a.separator=a.separator||" to ",a.label=a.label||"Date Range",t&&typeof t=="object"){const o=l=>{if(!l&&l!==0)return"";if(l instanceof Date&&!isNaN(l))return l.toISOString().slice(0,10);const d=String(l).trim();if(!d)return"";if(/^-?\d+$/.test(d)){const u=Number(d),m=d.length<=10?u*1e3:u,p=new Date(m);if(!isNaN(p))return p.toISOString().slice(0,10)}const h=new Date(d);return isNaN(h)?d:h.toISOString().slice(0,10)};a.startDate=o(t.start||t.from||t.begin||""),a.endDate=o(t.end||t.to||t.finish||"")}}else if(e.type==="multiselect"){let o=[];t&&(Array.isArray(t)?o=t:typeof t=="string"&&(o=t.split(",").map(l=>l.trim()).filter(l=>l))),a.value=o,!a.placeholder&&!a.placeHolder&&(e.placeholder||e.placeHolder?a.placeholder=e.placeholder||e.placeHolder:e.label&&(a.placeholder=`Select ${e.label}...`))}return a}extractFilterValue(e,t){if(e.type==="daterange"){const s=e.startName||"dr_start",i=e.endName||"dr_end";return{start:t[s],end:t[i]}}return e.type==="multiselect",t.filter_value}async applyFilters(){if(this.collection&&(this.collection.params.start=0),this.collection?.restEnabled)try{await this.collection.fetch(),await this.render()}catch(e){console.error("Failed to fetch filtered data:",e),await this.render()}else await this.render();this.updateFilterPills(),this.emit("params-changed")}async onActionEditFilter(e,t){const s=t.getAttribute("data-filter"),{field:i}=pe(s);let r=this.getFilterConfig(i)||this.getFilterConfig(s);const n=this.getActiveFilters(),a=n[s]||n[i];if(!r){console.warn("No filter config found for key:",s,"or field:",i);return}const o={filter_value:a};if(r.type==="daterange"&&a&&typeof a=="object"){const d=r.startName||"dr_start",h=r.endName||"dr_end";o[d]=a.start||"",o[h]=a.end||""}const l=await v.form({title:`Edit ${this.getFilterLabel(i)} Filter`,size:"md",data:o,fields:[this.buildFilterDialogField(r,a,i)]});if(l){const d=this.extractFilterValue(r,l);this.setFilter(s,d),await this.applyFilters()}}async onActionRemoveFilter(e,t){const s=t.getAttribute("data-filter"),{field:i}=pe(s);this.setFilter(s,null),s==="search"&&this.updateSearchInputs(""),this.collection.restEnabled&&await this.collection.fetch(),this.render(),this.updateFilterPills(),this.emit("filter:remove",{key:s,field:i}),this.emit("params-changed")}async onActionClearAllFilters(e,t){if(!this.collection)return;const{start:s,size:i,sort:r}=this.collection.params,n={start:s,size:i};r&&(n.sort=r),Array.isArray(this.hideActivePillNames)&&this.hideActivePillNames.length>0&&this.hideActivePillNames.forEach(a=>{this.collection.params[a]!==void 0&&(n[a]=this.collection.params[a]);const o=this.getFilterConfig(a);if(o&&o.type==="daterange"){const l=o.startName||"dr_start",d=o.endName||"dr_end",h=o.fieldName||"dr_field";this.collection.params[l]!==void 0&&(n[l]=this.collection.params[l]),this.collection.params[d]!==void 0&&(n[d]=this.collection.params[d]),this.collection.params[h]!==void 0&&(n[h]=this.collection.params[h])}}),this.collection.params=n,this.updateSearchInputs(""),this.collection.restEnabled&&await this.collection.fetch(),this.render(),this.updateFilterPills(),this.emit("filters:clear"),this.emit("params-changed")}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()}async onActionCustomToolbarButton(e,t){const s=parseInt(t.getAttribute("data-button-index"),10),i=this.toolbarButtons[s];i&&typeof i.handler=="function"&&await i.handler.call(this,e,t)}}function fs(){return typeof window>"u"?null:((!window.MOJO||typeof window.MOJO!="object")&&(window.MOJO={}),window.MOJO)}function gs(c){return c.__lite&&c.__lite.version||(c.WebApp=ye,c.View=C,c.Page=ue,c.Router=$e,c.Model=se,c.Collection=oe,c.Rest=te,c.FormBuilder=me,c.FormView=Q,c.Dialog=_,c.ModalView=_,c.ProgressView=Me,c.ListView=Ge,c.ListViewItem=xe,c.TableView=$t,c.TableRow=Je,c.DataFormatter=V,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 Ze=fs();Ze&&gs(Ze);class Ke 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`
1690
+ `),e.innerHTML=l.join("")}async onActionPage(e,t){e.preventDefault();const s=parseInt(t.getAttribute("data-page"),10),i=this.collection.params?.size||10,r=this.collection.meta?.count||this.collection.length(),n=Math.max(1,Math.ceil(r/i));let a=isNaN(s)?1:s;a<1&&(a=n),a>n&&(a=1),this.collection.setParams({...this.collection.params,start:(a-1)*i}),this.collection.restEnabled?await this.collection.fetch():this.render(),this.emit("table:page",{page:a,event:e}),this.emit("params-changed")}async onChangePageSize(e,t){const s=parseInt(t.value);this.collection&&(this.collection.setParams({...this.collection.params,start:0,size:s}),this.collection.restEnabled&&await this.collection.fetch(),this.render()),this.emit("table:pagesize",{size:s,event:e}),this.emit("params-changed")}getActiveFilters(){if(!this.collection?.params)return{};const{start:e,size:t,sort:s,...i}=this.collection.params,r={},n=new Set;return this.getAllAvailableFilters().forEach(o=>{if(o.config.type==="daterange"){const l=o.key,d=o.config.startName||"dr_start",h=o.config.endName||"dr_end",u=o.config.fieldName||"dr_field";i[u]===l&&(i[d]||i[h])&&(r[l]={start:i[d]||"",end:i[h]||""},n.add(d),n.add(h),n.add(u))}}),Object.keys(i).forEach(o=>{n.has(o)||(r[o]=i[o])}),Object.keys(r).forEach(o=>{if(r.hasOwnProperty(o)){const l=`${o}__in`;r.hasOwnProperty(l)&&(delete r[o],r[l]=r[l])}}),r}setFilter(e,t){if(!this.collection)return;const s=this.getFilterConfig(e);if(s&&s.type==="daterange"){const i=s.startName||"dr_start",r=s.endName||"dr_end",n=s.fieldName||"dr_field";delete this.collection.params[i],delete this.collection.params[r],delete this.collection.params[n],t&&typeof t=="object"&&(t.start||t.end)&&(t.start&&(this.collection.params[i]=t.start),t.end&&(this.collection.params[r]=t.end),this.collection.params[n]=e)}else{const{field:i,lookup:r}=pe(e);if(delete this.collection.params[e],delete this.collection.params[i],delete this.collection.params[`${i}__in`],!t||Array.isArray(t)&&t.length===0)return;Array.isArray(t)?t.length===1?this.collection.params[i]=t[0]:this.collection.params[`${i}__in`]=t.join(","):this.collection.params[e]=t}}getAllAvailableFilters(){const e=[];return this.columns.forEach(t=>{if(t.filter){const{fieldKey:s}=this.parseColumnKey(t.key);e.push({key:s,label:t.filter.label||t.label||s,type:t.filter.type,config:t.filter})}}),this.additionalFilters&&Array.isArray(this.additionalFilters)&&this.additionalFilters.forEach(t=>{e.push({key:t.name||t.key,label:t.label,type:t.type,config:t})}),e}getFilterConfig(e){const t=this.columns.find(s=>{const{fieldKey:i}=this.parseColumnKey(s.key);return i===e});if(t&&t.filter)return t.filter;if(this.additionalFilters&&Array.isArray(this.additionalFilters)){const s=this.additionalFilters.find(i=>(i.name||i.key)===e);if(s)return s}return null}getFilterLabel(e){if(e==="search")return"Search";const t=this.filters[e];if(t&&t.label)return t.label;const s=this.additionalFilters.find(i=>(i.name||i.key)===e);return s&&s.label?s.label:e.charAt(0).toUpperCase()+e.slice(1)}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}getFilterIcon(e){return{text:"search",select:"funnel",date:"calendar",daterange:"calendar-range",number:"123",boolean:"toggle-on"}[e]||"filter"}async onActionAddFilter(e,t){const s=t.getAttribute("data-filter-key"),i=this.getFilterConfig(s),r=this.getActiveFilters()[s];if(!i){console.warn("No filter config found for key:",s);return}const n=await w.form({title:`${r!==void 0&&r!==""?"Edit":"Add"} ${this.getFilterLabel(s)} Filter`,size:"md",fields:[this.buildFilterDialogField(i,r,s)]});if(n){const a=this.extractFilterValue(i,n);this.setFilter(s,a),await this.applyFilters()}}buildFilterDialogField(e,t,s){const{name:i,value:r,...n}=e,a={...n,name:"filter_value",label:n.label,value:t,placeholder:n.placeholder||n.placeHolder};if(e.type==="daterange"){if(a.startName=a.startName||"dr_start",a.endName=a.endName||"dr_end",a.fieldName=a.fieldName||"dr_field",a.format=a.format||"YYYY-MM-DD",a.displayFormat=a.displayFormat||"MMM DD, YYYY",a.separator=a.separator||" to ",a.label=a.label||"Date Range",t&&typeof t=="object"){const o=l=>{if(!l&&l!==0)return"";if(l instanceof Date&&!isNaN(l))return l.toISOString().slice(0,10);const d=String(l).trim();if(!d)return"";if(/^-?\d+$/.test(d)){const u=Number(d),m=d.length<=10?u*1e3:u,p=new Date(m);if(!isNaN(p))return p.toISOString().slice(0,10)}const h=new Date(d);return isNaN(h)?d:h.toISOString().slice(0,10)};a.startDate=o(t.start||t.from||t.begin||""),a.endDate=o(t.end||t.to||t.finish||"")}}else if(e.type==="multiselect"){let o=[];t&&(Array.isArray(t)?o=t:typeof t=="string"&&(o=t.split(",").map(l=>l.trim()).filter(l=>l))),a.value=o,!a.placeholder&&!a.placeHolder&&(e.placeholder||e.placeHolder?a.placeholder=e.placeholder||e.placeHolder:e.label&&(a.placeholder=`Select ${e.label}...`))}return a}extractFilterValue(e,t){if(e.type==="daterange"){const s=e.startName||"dr_start",i=e.endName||"dr_end";return{start:t[s],end:t[i]}}return e.type==="multiselect",t.filter_value}async applyFilters(){if(this.collection&&(this.collection.params.start=0),this.collection?.restEnabled)try{await this.collection.fetch(),await this.render()}catch(e){console.error("Failed to fetch filtered data:",e),await this.render()}else await this.render();this.updateFilterPills(),this.emit("params-changed")}async onActionEditFilter(e,t){const s=t.getAttribute("data-filter"),{field:i}=pe(s);let r=this.getFilterConfig(i)||this.getFilterConfig(s);const n=this.getActiveFilters(),a=n[s]||n[i];if(!r){console.warn("No filter config found for key:",s,"or field:",i);return}const o={filter_value:a};if(r.type==="daterange"&&a&&typeof a=="object"){const d=r.startName||"dr_start",h=r.endName||"dr_end";o[d]=a.start||"",o[h]=a.end||""}const l=await w.form({title:`Edit ${this.getFilterLabel(i)} Filter`,size:"md",data:o,fields:[this.buildFilterDialogField(r,a,i)]});if(l){const d=this.extractFilterValue(r,l);this.setFilter(s,d),await this.applyFilters()}}async onActionRemoveFilter(e,t){const s=t.getAttribute("data-filter"),{field:i}=pe(s);this.setFilter(s,null),s==="search"&&this.updateSearchInputs(""),this.collection.restEnabled&&await this.collection.fetch(),this.render(),this.updateFilterPills(),this.emit("filter:remove",{key:s,field:i}),this.emit("params-changed")}async onActionClearAllFilters(e,t){if(!this.collection)return;const{start:s,size:i,sort:r}=this.collection.params,n={start:s,size:i};r&&(n.sort=r),Array.isArray(this.hideActivePillNames)&&this.hideActivePillNames.length>0&&this.hideActivePillNames.forEach(a=>{this.collection.params[a]!==void 0&&(n[a]=this.collection.params[a]);const o=this.getFilterConfig(a);if(o&&o.type==="daterange"){const l=o.startName||"dr_start",d=o.endName||"dr_end",h=o.fieldName||"dr_field";this.collection.params[l]!==void 0&&(n[l]=this.collection.params[l]),this.collection.params[d]!==void 0&&(n[d]=this.collection.params[d]),this.collection.params[h]!==void 0&&(n[h]=this.collection.params[h])}}),this.collection.params=n,this.updateSearchInputs(""),this.collection.restEnabled&&await this.collection.fetch(),this.render(),this.updateFilterPills(),this.emit("filters:clear"),this.emit("params-changed")}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()}async onActionCustomToolbarButton(e,t){const s=parseInt(t.getAttribute("data-button-index"),10),i=this.toolbarButtons[s];i&&typeof i.handler=="function"&&await i.handler.call(this,e,t)}}function fs(){return typeof window>"u"?null:((!window.MOJO||typeof window.MOJO!="object")&&(window.MOJO={}),window.MOJO)}function gs(c){return c.__lite&&c.__lite.version||(c.WebApp=ye,c.View=C,c.Page=ue,c.Router=$e,c.Model=se,c.Collection=oe,c.Rest=te,c.FormBuilder=me,c.FormView=Q,c.Dialog=_,c.ModalView=_,c.ProgressView=Me,c.ListView=Ge,c.ListViewItem=xe,c.TableView=$t,c.TableRow=Je,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 Ze=fs();Ze&&gs(Ze);class Ke 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`
1691
1691
  <div class="${this.dataViewOptions.rowClass}">
1692
1692
  ${e}
1693
1693
  </div>
1694
- `}generateFieldsFromData(){const e=this.getData();e&&typeof e=="object"&&(this.fields=Object.keys(e).map(t=>{const s=e[t],i=this.inferFieldType(s,t),r=this.inferFormatter(s,t,i);return{name:t,label:this.formatLabel(t),type:i,format:r,formatter:r}}))}formatLabel(e){return e.replace(/([A-Z])/g," $1").replace(/[_-]/g," ").replace(/\b\w/g,t=>t.toUpperCase()).trim()}inferFieldType(e,t=""){if(e==null)return"text";const s=t.toLowerCase(),i=typeof e;if(s.includes("date")||s.includes("time")||s.includes("created")||s.includes("updated")||s.includes("modified")||s.includes("last_login")||s.includes("expires")||s.includes("last_activity"))return"datetime";if(s.includes("email")||s.includes("mail"))return"email";if(s.includes("url")||s.includes("link")||s.includes("website")||s.includes("homepage"))return"url";if(s.includes("phone")||s.includes("tel")||s.includes("mobile")||s.includes("cell"))return"phone";if(s.includes("price")||s.includes("cost")||s.includes("amount")||s.includes("fee")||s.includes("salary")||s.includes("revenue"))return"currency";if(s.includes("size")||s.includes("bytes"))return"filesize";if(s.includes("percent")||s.includes("rate")||s.includes("ratio")&&i==="number")return"percent";if(i==="boolean")return"boolean";if(i==="number")return"number";if(i==="object")return Array.isArray(e)?"array":e&&e.renditions?"file":this.shouldUseDataView(e,s)?"dataview":"object";if(i==="string"){if(e.includes("@")&&e.includes("."))return"email";if(e.match(/^\d{4}-\d{2}-\d{2}/))return"date";if(e.match(/^https?:\/\//))return"url";if(e.match(/^\+?[\d\s\-\(\)]+$/))return"phone"}return"text"}inferFormatter(e,t,s){const i=t.toLowerCase(),r=[];switch(s){case"datetime":i.includes("time")&&!i.includes("date")?r.push("time"):i.includes("relative")||i.includes("ago")||i.includes("last_")?r.push("relative"):i.includes("created")||i.includes("updated")||i.includes("modified")?r.push('date("MMM D, YYYY")'):r.push('date("MMMM D, YYYY")');break;case"date":i.includes("birth")||i.includes("dob")?r.push('date("MMMM D, YYYY")'):r.push('date("MMM D, YYYY")');break;case"email":break;case"url":break;case"phone":r.push("phone");break;case"currency":r.push("currency"),i.includes("eur")||i.includes("euro")?r[r.length-1]='currency("EUR")':(i.includes("gbp")||i.includes("pound"))&&(r[r.length-1]='currency("GBP")');break;case"filesize":r.push("filesize");break;case"percent":r.push("percent");break;case"number":if(typeof e=="number")if(i.includes("count")||i.includes("total")||i.includes("followers")||i.includes("views"))e>=1e3?r.push("compact"):r.push("number");else if(i.includes("score")||i.includes("rating"))r.push("number"),e%1!==0&&(r[r.length-1]="number(1)");else{if(i.includes("version")||i.includes("id"))return null;r.push("number")}break;case"boolean":break;case"text":typeof e=="string"&&(i.includes("description")||i.includes("content")||i.includes("body")?e.length>200?r.push("truncate(200)"):e.length>100&&r.push("truncate(100)"):i.includes("summary")||i.includes("excerpt")?e.length>150&&r.push("truncate(150)"):i.includes("name")||i.includes("title")||i.includes("label")?(r.push("capitalize"),e.length>50&&r.unshift("truncate(50)")):i.includes("slug")||i.includes("handle")||i.includes("username")?r.push("slug"):i.includes("code")||i.includes("token")||i.includes("key")?e.length>20&&r.push("mask"):e.length>100&&r.push("truncate(100)"));break;case"array":case"object":break;case"dataview":break;default:typeof e=="string"&&e.length>100&&r.push("truncate(100)");break}return r.length>0?r.join("|"):null}shouldUseDataView(e,t){if(!e||typeof e!="object"||Array.isArray(e))return!1;const s=["permissions","perms","access","rights","settings","config","configuration","options","profile","info","details","data","metadata","meta","attributes","props","preferences","prefs","user_data","contact","address","location","stats","statistics","metrics","counts"];if(window.utils&&window.utils.isObject(e)&&e.id)return!0;if(s.some(r=>t.includes(r))){const r=Object.keys(e);if(r.length>=2&&r.length<=20&&!r.some(a=>typeof e[a]=="object"&&e[a]!==null&&!Array.isArray(e[a])&&Object.keys(e[a]).length>3))return!0}return!1}getData(){return this.model&&this.model.attributes?{...this.model.attributes}:this.data||{}}getFieldValue(e){let t,s=e.name||e.key,i=e.format||e.formatter;if(!s)return null;if(s&&s.includes("|")){const r=s.split("|");s=r[0].trim(),i||(i=r.slice(1).join("|").trim())}if(this.model&&typeof this.model.get=="function"?t=this.model.get(s):t=this.getData()[s],i&&(t=V.pipe(t,i)),t==null||t==="")return this.dataViewOptions.showEmptyValues?this.dataViewOptions.emptyValueText:null;if(e.template){const r=this.model?this.model:this.data;return this.renderTemplateString(e.template,r)}return t}renderTemplateString(e,t){return!e||!t?"":e.replace(/\{\{([^}]+)\}\}/g,(s,i)=>{const r=i.trim();let n;const a=r.split("|"),o=a[0],l=a.slice(1).join("|");return this.model&&typeof this.model.get=="function"?n=this.model.get(o):n=o.split(".").reduce((d,h)=>d?d[h]:void 0,t),l&&(n=V.pipe(n,l)),n??""})}getColumnClasses(e){let t=this.getColumnSizeClasses(e);return e.justify=="right"?t+=" d-flex justify-content-end":e.justify=="center"&&(t+=" d-flex justify-content-center"),t}getColumnSizeClasses(e){if(e.type==="array"||e.type==="object"||e.type==="dataview")return"col-12";const t=e.columns||e.colSize||e.cols||Math.floor(12/this.dataViewOptions.columns);return this.dataViewOptions.responsive?`col-12 col-md-${t}`:`col-${t}`}buildItemsHTML(){return this.fields.map(e=>this.buildItemHTML(e)).filter(Boolean).join("")}buildItemHTML(e){const t=this.getFieldValue(e);if(t===null&&!this.dataViewOptions.showEmptyValues)return"";const s=e.label||this.formatLabel(e.name);return`
1694
+ `}generateFieldsFromData(){const e=this.getData();e&&typeof e=="object"&&(this.fields=Object.keys(e).map(t=>{const s=e[t],i=this.inferFieldType(s,t),r=this.inferFormatter(s,t,i);return{name:t,label:this.formatLabel(t),type:i,format:r,formatter:r}}))}formatLabel(e){return e.replace(/([A-Z])/g," $1").replace(/[_-]/g," ").replace(/\b\w/g,t=>t.toUpperCase()).trim()}inferFieldType(e,t=""){if(e==null)return"text";const s=t.toLowerCase(),i=typeof e;if(s.includes("date")||s.includes("time")||s.includes("created")||s.includes("updated")||s.includes("modified")||s.includes("last_login")||s.includes("expires")||s.includes("last_activity"))return"datetime";if(s.includes("email")||s.includes("mail"))return"email";if(s.includes("url")||s.includes("link")||s.includes("website")||s.includes("homepage"))return"url";if(s.includes("phone")||s.includes("tel")||s.includes("mobile")||s.includes("cell"))return"phone";if(s.includes("price")||s.includes("cost")||s.includes("amount")||s.includes("fee")||s.includes("salary")||s.includes("revenue"))return"currency";if(s.includes("size")||s.includes("bytes"))return"filesize";if(s.includes("percent")||s.includes("rate")||s.includes("ratio")&&i==="number")return"percent";if(i==="boolean")return"boolean";if(i==="number")return"number";if(i==="object")return Array.isArray(e)?"array":e&&e.renditions?"file":this.shouldUseDataView(e,s)?"dataview":"object";if(i==="string"){if(e.includes("@")&&e.includes("."))return"email";if(e.match(/^\d{4}-\d{2}-\d{2}/))return"date";if(e.match(/^https?:\/\//))return"url";if(e.match(/^\+?[\d\s\-\(\)]+$/))return"phone"}return"text"}inferFormatter(e,t,s){const i=t.toLowerCase(),r=[];switch(s){case"datetime":i.includes("time")&&!i.includes("date")?r.push("time"):i.includes("relative")||i.includes("ago")||i.includes("last_")?r.push("relative"):i.includes("created")||i.includes("updated")||i.includes("modified")?r.push('date("MMM D, YYYY")'):r.push('date("MMMM D, YYYY")');break;case"date":i.includes("birth")||i.includes("dob")?r.push('date("MMMM D, YYYY")'):r.push('date("MMM D, YYYY")');break;case"email":break;case"url":break;case"phone":r.push("phone");break;case"currency":r.push("currency"),i.includes("eur")||i.includes("euro")?r[r.length-1]='currency("EUR")':(i.includes("gbp")||i.includes("pound"))&&(r[r.length-1]='currency("GBP")');break;case"filesize":r.push("filesize");break;case"percent":r.push("percent");break;case"number":if(typeof e=="number")if(i.includes("count")||i.includes("total")||i.includes("followers")||i.includes("views"))e>=1e3?r.push("compact"):r.push("number");else if(i.includes("score")||i.includes("rating"))r.push("number"),e%1!==0&&(r[r.length-1]="number(1)");else{if(i.includes("version")||i.includes("id"))return null;r.push("number")}break;case"boolean":break;case"text":typeof e=="string"&&(i.includes("description")||i.includes("content")||i.includes("body")?e.length>200?r.push("truncate(200)"):e.length>100&&r.push("truncate(100)"):i.includes("summary")||i.includes("excerpt")?e.length>150&&r.push("truncate(150)"):i.includes("name")||i.includes("title")||i.includes("label")?(r.push("capitalize"),e.length>50&&r.unshift("truncate(50)")):i.includes("slug")||i.includes("handle")||i.includes("username")?r.push("slug"):i.includes("code")||i.includes("token")||i.includes("key")?e.length>20&&r.push("mask"):e.length>100&&r.push("truncate(100)"));break;case"array":case"object":break;case"dataview":break;default:typeof e=="string"&&e.length>100&&r.push("truncate(100)");break}return r.length>0?r.join("|"):null}shouldUseDataView(e,t){if(!e||typeof e!="object"||Array.isArray(e))return!1;const s=["permissions","perms","access","rights","settings","config","configuration","options","profile","info","details","data","metadata","meta","attributes","props","preferences","prefs","user_data","contact","address","location","stats","statistics","metrics","counts"];if(window.utils&&window.utils.isObject(e)&&e.id)return!0;if(s.some(r=>t.includes(r))){const r=Object.keys(e);if(r.length>=2&&r.length<=20&&!r.some(a=>typeof e[a]=="object"&&e[a]!==null&&!Array.isArray(e[a])&&Object.keys(e[a]).length>3))return!0}return!1}getData(){return this.model&&this.model.attributes?{...this.model.attributes}:this.data||{}}getFieldValue(e){let t,s=e.name||e.key,i=e.format||e.formatter;if(!s)return null;if(s&&s.includes("|")){const r=s.split("|");s=r[0].trim(),i||(i=r.slice(1).join("|").trim())}if(this.model&&typeof this.model.get=="function"?t=this.model.get(s):t=this.getData()[s],i&&(t=P.pipe(t,i)),t==null||t==="")return this.dataViewOptions.showEmptyValues?this.dataViewOptions.emptyValueText:null;if(e.template){const r=this.model?this.model:this.data;return this.renderTemplateString(e.template,r)}return t}renderTemplateString(e,t){return!e||!t?"":e.replace(/\{\{([^}]+)\}\}/g,(s,i)=>{const r=i.trim();let n;const a=r.split("|"),o=a[0],l=a.slice(1).join("|");return this.model&&typeof this.model.get=="function"?n=this.model.get(o):n=o.split(".").reduce((d,h)=>d?d[h]:void 0,t),l&&(n=P.pipe(n,l)),n??""})}getColumnClasses(e){let t=this.getColumnSizeClasses(e);return e.justify=="right"?t+=" d-flex justify-content-end":e.justify=="center"&&(t+=" d-flex justify-content-center"),t}getColumnSizeClasses(e){if(e.type==="array"||e.type==="object"||e.type==="dataview")return"col-12";const t=e.columns||e.colSize||e.cols||Math.floor(12/this.dataViewOptions.columns);return this.dataViewOptions.responsive?`col-12 col-md-${t}`:`col-${t}`}buildItemsHTML(){return this.fields.map(e=>this.buildItemHTML(e)).filter(Boolean).join("")}buildItemHTML(e){const t=this.getFieldValue(e);if(t===null&&!this.dataViewOptions.showEmptyValues)return"";const s=e.label||this.formatLabel(e.name);return`
1695
1695
  <div class="${this.getColumnClasses(e)}">
1696
1696
  <div class="${this.dataViewOptions.itemClass} ${e.className}" data-field="${e.name}">
1697
1697
  ${this.buildLabelHTML(s,e)}
@@ -1735,5 +1735,5 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
1735
1735
  ${i}
1736
1736
  </div>
1737
1737
  </div>
1738
- `}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?V.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 Ke(e)}}const bs=Object.freeze(Object.defineProperty({__proto__:null,default:Ke},Symbol.toStringTag,{value:"Module"}));return F.Collection=oe,F.DataFormatter=V,F.Dialog=_,F.FormBuilder=me,F.FormPage=ms,F.FormView=Q,F.ListView=Ge,F.ListViewItem=xe,F.MOJOUtils=$,F.ModalView=_,F.Model=se,F.Page=ue,F.ProgressView=Me,F.Rest=te,F.Router=$e,F.TableRow=Je,F.TableView=$t,F.View=C,F.WebApp=ye,F.default=Ze,Object.defineProperties(F,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}}),F})({});
1738
+ `}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 Ke(e)}}const bs=Object.freeze(Object.defineProperty({__proto__:null,default:Ke},Symbol.toStringTag,{value:"Module"}));return F.Collection=oe,F.DataFormatter=P,F.Dialog=_,F.FormBuilder=me,F.FormPage=ms,F.FormView=Q,F.ListView=Ge,F.ListViewItem=xe,F.MOJOUtils=$,F.ModalView=_,F.Model=se,F.Page=ue,F.ProgressView=Me,F.Rest=te,F.Router=$e,F.TableRow=Je,F.TableView=$t,F.View=C,F.WebApp=ye,F.default=Ze,Object.defineProperties(F,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}}),F})({});
1739
1739
  //# sourceMappingURL=web-mojo.lite.iife.min.js.map