web-mojo 2.4.0 → 2.4.1

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 (47) hide show
  1. package/dist/admin.cjs.js +1 -1
  2. package/dist/admin.es.js +1 -1
  3. package/dist/auth.cjs.js +1 -1
  4. package/dist/auth.es.js +1 -1
  5. package/dist/charts.cjs.js +1 -1
  6. package/dist/charts.es.js +1 -1
  7. package/dist/chunks/{AssistantPanelView-CJypCC34.js → AssistantPanelView-C2UrR8N7.js} +2 -2
  8. package/dist/chunks/{AssistantPanelView-CJypCC34.js.map → AssistantPanelView-C2UrR8N7.js.map} +1 -1
  9. package/dist/chunks/{AssistantPanelView-8sMO_xgC.js → AssistantPanelView-DVeXmhzx.js} +2 -2
  10. package/dist/chunks/{AssistantPanelView-8sMO_xgC.js.map → AssistantPanelView-DVeXmhzx.js.map} +1 -1
  11. package/dist/chunks/{ChatView-D7cll_OP.js → ChatView-B0xHv7Nq.js} +2 -2
  12. package/dist/chunks/{ChatView-D7cll_OP.js.map → ChatView-B0xHv7Nq.js.map} +1 -1
  13. package/dist/chunks/{ChatView-BLl2pOeL.js → ChatView-CUmRTKna.js} +2 -2
  14. package/dist/chunks/{ChatView-BLl2pOeL.js.map → ChatView-CUmRTKna.js.map} +1 -1
  15. package/dist/chunks/{Passkeys-Dpzvoi97.js → Passkeys-CMh9iSax.js} +2 -2
  16. package/dist/chunks/{Passkeys-DZC4MMYY.js.map → Passkeys-CMh9iSax.js.map} +1 -1
  17. package/dist/chunks/{Passkeys-DZC4MMYY.js → Passkeys-DF7mRGYj.js} +2 -2
  18. package/dist/chunks/{Passkeys-Dpzvoi97.js.map → Passkeys-DF7mRGYj.js.map} +1 -1
  19. package/dist/chunks/{UserProfileView-zJ3DkZZI.js → UserProfileView-B56WeGL1.js} +2 -2
  20. package/dist/chunks/{UserProfileView-zJ3DkZZI.js.map → UserProfileView-B56WeGL1.js.map} +1 -1
  21. package/dist/chunks/{UserProfileView-CcZHcQzP.js → UserProfileView-CrmACQjJ.js} +2 -2
  22. package/dist/chunks/{UserProfileView-CcZHcQzP.js.map → UserProfileView-CrmACQjJ.js.map} +1 -1
  23. package/dist/chunks/{admin-D1JFG-EB.js → admin-D3DtCOgt.js} +2 -2
  24. package/dist/chunks/{admin-D1JFG-EB.js.map → admin-D3DtCOgt.js.map} +1 -1
  25. package/dist/chunks/{admin-eo5ktjR2.js → admin-oYYbqLlb.js} +2 -2
  26. package/dist/chunks/{admin-eo5ktjR2.js.map → admin-oYYbqLlb.js.map} +1 -1
  27. package/dist/chunks/{index-Cdxr98ac.js → index-DTXotoXw.js} +2 -2
  28. package/dist/chunks/{index-Cdxr98ac.js.map → index-DTXotoXw.js.map} +1 -1
  29. package/dist/chunks/{index-_1JBT2F1.js → index-NXnA6T-5.js} +2 -2
  30. package/dist/chunks/{index-_1JBT2F1.js.map → index-NXnA6T-5.js.map} +1 -1
  31. package/dist/chunks/{version-VTxMn6hv.js → version-Bpfg5FM3.js} +2 -2
  32. package/dist/chunks/{version-VTxMn6hv.js.map → version-Bpfg5FM3.js.map} +1 -1
  33. package/dist/chunks/{version-BUOTqQj6.js → version-CopJeO_u.js} +2 -2
  34. package/dist/chunks/{version-BUOTqQj6.js.map → version-CopJeO_u.js.map} +1 -1
  35. package/dist/docit.cjs.js +1 -1
  36. package/dist/docit.es.js +1 -1
  37. package/dist/index.cjs.js +1 -1
  38. package/dist/index.es.js +1 -1
  39. package/dist/lightbox.cjs.js +1 -1
  40. package/dist/lightbox.es.js +1 -1
  41. package/dist/user-profile.cjs.js +1 -1
  42. package/dist/user-profile.es.js +1 -1
  43. package/dist/web-mojo.lite.iife.js +23 -6
  44. package/dist/web-mojo.lite.iife.js.map +1 -1
  45. package/dist/web-mojo.lite.iife.min.js +17 -17
  46. package/dist/web-mojo.lite.iife.min.js.map +1 -1
  47. package/package.json +1 -1
@@ -11,7 +11,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
11
11
  ${r?`<span class="font-monospace">${i}</span>`:""}
12
12
  ${n}
13
13
  </span>
14
- `}nl2br(e){return e==null?"":this.escapeHtml(String(e)).replace(/\r\n|\r|\n/g,"<br>")}code(e,t=""){if(e==null)return"";const s=t?`language-${this.escapeHtml(String(t))}`:"",i=this.escapeHtml(String(e));return`<pre class="bg-light p-2 rounded border"><code class="${s}">${i}</code></pre>`}register(e,t){if(typeof t!="function")throw new Error(`Formatter must be a function, got ${typeof t}`);return this.formatters.set(e.toLowerCase(),t),this}apply(e,t,...s){try{const i=this.formatters.get(e.toLowerCase());return i?i(t,...s):(console.warn(`Formatter '${e}' not found`),t)}catch(i){return console.error(`Error in formatter '${e}':`,i),t}}pipe(e,t,s=null){return t?this.parsePipeString(t,s).reduce((r,n)=>this.apply(n.name,r,...n.args),e):e}parsePipeString(e,t=null){const s=[],i=e.split("|").map(r=>r.trim());for(const r of i){const n=this.parseFormatter(r,t);n&&s.push(n)}return s}parseFormatter(e,t=null){const s=e.match(/^([a-zA-Z_]\w*)\s*\((.*)\)$/);if(s){const[,r,n]=s,a=n?this.parseArguments(n,t):[];return{name:r,args:a}}const i=e.match(/^([a-zA-Z_]\w*)(?::(.+))?$/);if(i){const[,r,n]=i,a=n?this.parseColonArguments(n,t):[];return{name:r,args:a}}return null}parseArguments(e,t=null){const s=[];let i="",r=!1,n=null,a=0;for(let o=0;o<e.length;o++){const l=e[o];!r&&(l==='"'||l==="'")?(r=!0,n=l,i+=l):r&&l===n&&e[o-1]!=="\\"?(r=!1,n=null,i+=l):!r&&l==="{"?(a++,i+=l):!r&&l==="}"?(a--,i+=l):!r&&a===0&&l===","?(s.push(this.parseValue(i.trim(),t)),i=""):i+=l}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseColonArguments(e,t=null){const s=[];let i="",r=!1,n=null;for(let a=0;a<e.length;a++){const o=e[a];!r&&(o==='"'||o==="'")?(r=!0,n=o,i+=o):r&&o===n&&e[a-1]!=="\\"?(r=!1,n=null,i+=o):!r&&o===":"?(s.push(this.parseValue(i.trim(),t)),i=""):i+=o}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseValue(e,t=null){if(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);if(e==="true")return!0;if(e==="false")return!1;if(e==="null")return null;if(e!=="undefined"){if(!isNaN(e)&&e!=="")return Number(e);if(e.startsWith("{")&&e.endsWith("}"))try{return JSON.parse(e)}catch{}if(t&&this.isIdentifier(e)){if(!e.includes(".")&&Object.prototype.hasOwnProperty.call(t,e))return t[e];if(t.get&&typeof t.get=="function"){const s=t.get(e);if(s!==void 0)return s}if(t.getContextValue&&typeof t.getContextValue=="function"){const s=t.getContextValue(e);if(s!==void 0)return s}if(e.includes(".")){const s=window.MOJOUtils||(typeof require<"u"?require("./MOJOUtils.js").default:null);if(s){const i=s.getNestedValue(t,e);if(i!==void 0)return i}}}return e}}isIdentifier(e){return/^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/.test(e)}date(e,t="MM/DD/YYYY"){if(!e)return"";e=this.normalizeEpoch(e);let s;if(e instanceof Date)s=e;else if(typeof e=="string")if(/^\d{4}-\d{2}-\d{2}$/.test(e)){const[a,o,l]=e.split("-").map(Number);s=new Date(a,o-1,l)}else s=new Date(e);else s=new Date(e);if(isNaN(s.getTime()))return String(e);const i={YYYY:s.getFullYear(),YY:String(s.getFullYear()).slice(-2),MMMM:s.toLocaleDateString("en-US",{month:"long"}),MMM:s.toLocaleDateString("en-US",{month:"short"}),MM:String(s.getMonth()+1).padStart(2,"0"),M:s.getMonth()+1,dddd:s.toLocaleDateString("en-US",{weekday:"long"}),ddd:s.toLocaleDateString("en-US",{weekday:"short"}),DD:String(s.getDate()).padStart(2,"0"),D:s.getDate()};let r=t;const n=new RegExp(`(${Object.keys(i).join("|")})`,"g");return r=r.replace(n,a=>i[a]||a),r}time(e,t="HH:mm:ss"){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const i=s.getHours(),r={HH:String(i).padStart(2,"0"),H:i,hh:String(i%12||12).padStart(2,"0"),h:i%12||12,mm:String(s.getMinutes()).padStart(2,"0"),m:s.getMinutes(),ss:String(s.getSeconds()).padStart(2,"0"),s:s.getSeconds(),A:i>=12?"PM":"AM",a:i>=12?"pm":"am"};let n=t;const a=Object.keys(r).sort((o,l)=>l.length-o.length);for(const o of a)n=n.replace(new RegExp(o,"g"),r[o]);return n}datetime(e,t="MM/DD/YYYY",s="HH:mm:ss"){e=this.normalizeEpoch(e);const i=this.date(e,t),r=this.time(e,s);return i&&r?`${i} ${r}`:""}datetime_tz(e,t="MM/DD/YYYY",s="HH:mm:ss",i={}){if(!e)return"";e=this.normalizeEpoch(e);const r=e instanceof Date?e:new Date(e);if(isNaN(r.getTime()))return String(e);const n=i&&i.locale||"en-US",a=i&&i.timeZone?i.timeZone:void 0,o=()=>{let k="";try{const X=new Intl.DateTimeFormat(n,{hour:"2-digit",minute:"2-digit",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(R=>R.type==="timeZoneName");if(k=X?X.value:"",k&&/^GMT[+-]/i.test(k))try{const ee=new Intl.DateTimeFormat(n,{timeStyle:"short",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(ws=>ws.type==="timeZoneName");ee&&ee.value&&!/^GMT[+-]/i.test(ee.value)&&(k=ee.value)}catch{}if(k&&/\s/.test(k)){const R=k.split(/\s+/).map(ee=>ee[0]).join("").toUpperCase();R.length>=2&&R.length<=4&&(k=R)}}catch{k=""}return k};if(!a){const k=this.date(r,t),Y=this.time(r,s),X=o();return k&&Y?`${k} ${Y} ${X}`.trim():""}const l=new Intl.DateTimeFormat(n,{timeZone:a,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hourCycle:"h23"}).formatToParts(r),d=k=>{const Y=l.find(X=>X.type===k);return Y?Y.value:""},h=d("year"),u=d("month"),m=d("day"),p=d("hour"),f=d("minute"),g=d("second"),b=u?String(parseInt(u,10)):"",y=m?String(parseInt(m,10)):"",w=p?String(parseInt(p,10)):"",x=p?parseInt(p,10)%12||12:"",A=p?parseInt(p,10)>=12?"PM":"AM":"",E=A?A.toLowerCase():"",j=new Intl.DateTimeFormat(n,{timeZone:a,month:"long"}).format(r),M=new Intl.DateTimeFormat(n,{timeZone:a,month:"short"}).format(r),O=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"long"}).format(r),re=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"short"}).format(r),fe={YYYY:h,YY:h?h.slice(-2):"",MMMM:j,MMM:M,MM:u,M:b,dddd:O,ddd:re,DD:m,D:y},ge={HH:p,H:w,hh:x!==""?String(x).padStart(2,"0"):"",h:x!==""?String(x):"",mm:f,m:f?String(parseInt(f,10)):"",ss:g,s:g?String(parseInt(g,10)):"",A,a:E},I=(k,Y)=>{if(!k)return"";const X=new RegExp(`(${Object.keys(Y).sort((R,ee)=>ee.length-R.length).join("|")})`,"g");return k.replace(X,R=>Y[R]??R)},q=I(t,fe),At=I(s,ge),ys=o();return q&&At?`${q} ${At} ${ys}`.trim():""}normalizeEpoch(e){if(e instanceof Date)return e;if(typeof e=="string"){const t=Number(e);if(Number.isFinite(t))e=t;else{const s=Date.parse(e);return Number.isFinite(s)?s:""}}else typeof e!="number"&&(e=Number(e));if(isNaN(e))return"";if(e<1e11)return e*1e3;if(e>1e12&&e<1e13)return e;throw new Error("Value doesn't look like epoch seconds or ms")}date_range(e,t=null,s="MM/DD/YYYY"){if(!e)return"";const i=t||new Date,r=this.date(e,s),n=this.date(i,s);return!r||!n?"":`${r} - ${n}`}datetime_range(e,t=null,s="MM/DD/YYYY",i="HH:mm"){if(!e)return"";const r=t||new Date,n=this.datetime(e,s,i),a=this.datetime(r,s,i);return!n||!a?"":`${n} - ${a}`}relative(e,t=!1){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const r=s-new Date,n=Math.abs(r),a=Math.floor(n/1e3),o=Math.floor(a/60),l=Math.floor(o/60),d=Math.floor(l/24),h=r>0;if(t)return d>365?Math.floor(d/365)+"y":d>30?Math.floor(d/30)+"mo":d>7?Math.floor(d/7)+"w":d>0?d+"d":l>0?l+"h":o>0?o+"m":"now";if(d>365){const u=Math.floor(d/365),m=h?"in ":"",p=h?"":" ago";return m+u+" year"+(u>1?"s":"")+p}if(d>30){const u=Math.floor(d/30),m=h?"in ":"",p=h?"":" ago";return m+u+" month"+(u>1?"s":"")+p}if(d>7){const u=Math.floor(d/7),m=h?"in ":"",p=h?"":" ago";return m+u+" week"+(u>1?"s":"")+p}if(d===1)return h?"tomorrow":"yesterday";if(d>0){const u=h?"in ":"",m=h?"":" ago";return u+d+" days"+m}if(l>0){const u=h?"in ":"",m=h?"":" ago";return u+l+" hour"+(l>1?"s":"")+m}if(o>0){const u=h?"in ":"",m=h?"":" ago";return u+o+" minute"+(o>1?"s":"")+m}if(a>30){const u=h?"in ":"",m=h?"":" ago";return u+a+" seconds"+m}return"just now"}iso(e,t=!1){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);return isNaN(s.getTime())?String(e):t?s.toISOString().split("T")[0]:s.toISOString()}number(e,t=2,s="en-US"){const i=parseFloat(e);return isNaN(i)?String(e):i.toLocaleString(s,{minimumFractionDigits:t,maximumFractionDigits:t})}currency(e,t="$",s=2){const i=parseInt(e);if(isNaN(i))return String(e);const r=Math.abs(i).toString(),n=i<0?"-":"";let a,o;r.length<=2?(a="0",o=r.padStart(2,"0")):(a=r.slice(0,-2),o=r.slice(-2)),a=a.replace(/\B(?=(\d{3})+(?!\d))/g,",");let l;if(s===0)parseInt(o)>=50&&(a=(parseInt(a.replace(/,/g,""))+1).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")),l=a;else if(s===2)l=`${a}.${o}`;else{const d=o.slice(0,s).padEnd(s,"0");l=`${a}.${d}`}return n+t+l}percent(e,t=0,s=!0){const i=parseFloat(e);if(isNaN(i))return String(e);const r=s?i*100:i;return this.number(r,t)+"%"}filesize(e,t=!1,s=1){const i=parseInt(e);if(isNaN(i))return String(e);const r=t?["B","KiB","MiB","GiB","TiB"]:["B","KB","MB","GB","TB"],n=t?1024:1e3;let a=i,o=0;for(;a>=n&&o<r.length-1;)a/=n,o++;const l=o===0?0:s;return`${a.toFixed(l)} ${r[o]}`}ordinal(e,t=!1){const s=parseInt(e);if(isNaN(s))return String(e);const i=s%10,r=s%100;let n="th";return i===1&&r!==11?n="st":i===2&&r!==12?n="nd":i===3&&r!==13&&(n="rd"),t?n:s+n}compact(e,t=1){const s=parseFloat(e);if(isNaN(s))return String(e);const i=Math.abs(s),r=s<0?"-":"";return i>=1e9?r+(i/1e9).toFixed(t)+"B":i>=1e6?r+(i/1e6).toFixed(t)+"M":i>=1e3?r+(i/1e3).toFixed(t)+"K":String(s)}add(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s+i}subtract(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s-i}multiply(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s*i}divide(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)||i===0?e:s/i}capitalize(e,t=!0){const s=String(e);return s?t?s.replace(/\b\w/g,i=>i.toUpperCase()):s.charAt(0).toUpperCase()+s.slice(1):""}replace(e,t,s="",i="g"){if(e==null)return"";const r=String(e);if(t==null||t==="")return r;if(t instanceof RegExp)return r.replace(t,String(s));const n=String(t),a=n.match(/^\/(.+)\/([a-z]*)$/i);if(a){const[,o,l]=a;try{return r.replace(new RegExp(o,l),String(s))}catch{}}return String(i).includes("g")?r.split(n).join(String(s)):r.replace(n,String(s))}truncate(e,t=50,s="..."){const i=String(e);return i.length<=t?i:i.substring(0,t)+s}truncate_front(e,t=8,s="..."){const i=String(e);return i.length<=t?i:`${s}${i.slice(-t)}`}truncate_middle(e,t=8,s="***"){const i=String(e);if(i.length<=t)return i;const r=Math.floor(t/2),n=i.substring(0,r),a=i.substring(i.length-r);return`${n}${s}${a}`}slug(e,t="-"){return String(e).toLowerCase().replace(/[^\w\s-]/g,"").replace(/\s+/g,t).replace(new RegExp(`${t}+`,"g"),t).replace(new RegExp(`^${t}|${t}$`,"g"),"")}initials(e,t=2){return String(e).split(/\s+/).filter(r=>r.length>0).slice(0,t).map(r=>r.charAt(0).toUpperCase()).join("")}mask(e,t="*",s=4){const i=String(e);if(i.length<=s)return i;const r=t.repeat(Math.max(0,i.length-s)),n=i.slice(-s);return r+n}email(e,t={}){const s=String(e).trim();if(!s)return"";if(t.link===!1)return s;const i=t.subject?`?subject=${encodeURIComponent(t.subject)}`:"",r=t.body?`&body=${encodeURIComponent(t.body)}`:"",n=t.class?` class="${t.class}"`:"";return`<a href="mailto:${s}${i}${r}"${n}>${s}</a>`}phone(e,t="US",s=!0){let i=String(e).replace(/\D/g,""),r=i;return t==="US"&&(i.length===10?r=`(${i.slice(0,3)}) ${i.slice(3,6)}-${i.slice(6)}`:i.length===11&&i[0]==="1"&&(r=`+1 (${i.slice(1,4)}) ${i.slice(4,7)}-${i.slice(7)}`)),s?`<a href="tel:${i}">${r}</a>`:r}url(e,t=null,s=!0){let i=String(e).trim();return i?(/^https?:\/\//.test(i)||(i="https://"+i),`<a href="${i}"${s?' target="_blank"':""}${s?' rel="noopener noreferrer"':""}>${t||i}</a>`):""}badge(e,t="auto"){if(Array.isArray(e))return e.map(n=>this.badge(n,t)).join(" ");const s=String(e);if(typeof t=="string"&&t.includes("=")){const n=Object.fromEntries(t.split(",").map(l=>l.split("=").map(d=>d.trim()))),a=n[s]||n[s.toLowerCase()]||this.inferBadgeType(s);return`<span class="badge ${a?`bg-${a}`:"bg-secondary"}">${s}</span>`}const i=t==="auto"?this.inferBadgeType(s):t;return`<span class="badge ${i?`bg-${i}`:"bg-secondary"}">${s}</span>`}badgeClass(e,t="auto"){const s=String(e),i=t==="auto"?this.inferBadgeType(s):t;return i?`bg-${i}`:"bg-secondary"}inferBadgeType(e){const t=e.toLowerCase();return["active","pass","success","complete","completed","approved","done","true","on","yes"].includes(t)?"success":["error","failed","fail","rejected","deleted","cancelled","false","off","no","declined"].includes(t)?"danger":["warning","pending","review","processing","uploading"].includes(t)?"warning":["info","new","draft"].includes(t)?"info":(["inactive","disabled","archived","suspended"].includes(t),"secondary")}status(e){return this._status(e)}status_icon(e){return this._status(e,{},{},!1,!0)}status_text(e){return this._status(e,{},{},!0,!1)}_status(e,t={},s={},i=!1,r=!1){const n=String(e).toLowerCase(),a={active:"bi bi-check-circle-fill",approved:"bi bi-check-circle-fill",declined:"bi bi-x-circle-fill",inactive:"bi bi-pause-circle-fill",pending:"bi bi-clock-fill",success:"bi bi-check-circle-fill",error:"bi bi-exclamation-triangle-fill",warning:"bi bi-exclamation-triangle-fill"},o={active:"success",approved:"success",declined:"danger",inactive:"secondary",pending:"warning",success:"success",error:"danger",warning:"warning"},l=t[n]||a[n]||"",d=s[n]||o[n]||"secondary";let h="";!i&&l&&(h=`<i class="${l}"></i>`);let u="";return r||(u=e),`<span class="text-${d}">${h}${h?" ":""}${u}</span>`}boolean(e,t="True",s="False",i=!1){const r=e?t:s;return i?`<span class="text-${e?"success":"danger"}">${r}</span>`:r}bool(e){return e==null||e===0||e===""||e===!1||e==="false"?!1:e===!0||e==="true"?!0:!(Array.isArray(e)&&e.length===0||e&&typeof e=="object"&&e.constructor===Object&&Object.keys(e).length===0)}icon(e,t={}){const s=String(e).toLowerCase(),i=t[s]||"";return i?`<i class="${i}"></i>`:""}yesnoicon(e,t="bi bi-check-circle-fill text-success",s="bi bi-x-circle-fill text-danger"){return e?`<i class="${t}"></i>`:`<i class="${s}"></i>`}image(e,t="thumbnail",s="img-fluid",i=""){const r=this._extractImageUrl(e,t);return r?`<img src="${r}" class="${s}" alt="${i}" />`:""}avatar(e,t="md",s="rounded-circle",i=""){const r=this._extractImageUrl(e,"square_sm")||Dt,n={xs:"width: 1.5rem; height: 1.5rem;",sm:"width: 2rem; height: 2rem;",md:"width: 3rem; height: 3rem;",lg:"width: 4rem; height: 4rem;",xl:"width: 5rem; height: 5rem;"},a=n[t]||n.md,l=`object-fit-cover ${s}`.trim();return`<img src="${r}" class="${l}" style="${a}" alt="${i}" />`}tooltip(e,t="",s="top",i=""){if(e==null)return"";const r=String(e),n=i==="html"?t:this.escapeHtml(t);return`<span data-bs-toggle="tooltip" data-bs-placement="${s}" ${i==="html"?'data-bs-html="true"':""} data-bs-title="${n}">${r}</span>`}_extractImageUrl(e,t="thumbnail"){if(!e)return null;if(typeof e=="string")return e;if(typeof e=="object"){if(e.attributes&&(e=e.attributes),t==="thumbnail"&&e.thumbnail&&typeof e.thumbnail=="string")return e.thumbnail;if(e.renditions&&typeof e.renditions=="object"){const s=e.renditions[t];if(s&&s.url)return s.url;const i=Object.values(e.renditions);if(i.length>0&&i[0].url)return i[0].url}if(e.url)return e.url}return null}default(e,t=""){return e==null||e===""?t:e}equals(e,t,s,i=""){return e==t?s:i}plural(e,t,s=null,i=!0){if(e==null||t===null||t===void 0)return i?`${e} ${t}`:t||"";const r=parseInt(e);if(isNaN(r))return i?`${e} ${t}`:t||"";const n=Math.abs(r)===1?t:s||t+"s";return i?`${r} ${n}`:n}formatList(e,t={}){if(!Array.isArray(e))return String(e);const{conjunction:s="and",limit:i=null,moreText:r="others"}=t;if(e.length===0)return"";if(e.length===1)return String(e[0]);let n=e.slice(),a=!1;if(i&&e.length>i&&(n=e.slice(0,i),a=!0),a){const o=e.length-i;return`${n.join(", ")}, ${s} ${o} ${r}`}return n.length===2?`${n[0]} ${s} ${n[1]}`:`${n.slice(0,-1).join(", ")}, ${s} ${n[n.length-1]}`}duration(e,t="ms",s=!1,i=2){if(e==null)return"";const r=parseFloat(e);if(isNaN(r))return String(e);let n;switch(t){case"s":case"sec":case"seconds":n=r*1e3;break;case"m":case"min":case"minutes":n=r*6e4;break;case"h":case"hr":case"hours":n=r*36e5;break;case"d":case"day":case"days":n=r*864e5;break;default:n=r}const a=[{name:"day",short:"d",value:864e5},{name:"hour",short:"h",value:36e5},{name:"minute",short:"m",value:6e4},{name:"second",short:"s",value:1e3}];if(n===0)return s?"0s":"0 seconds";const o=Math.abs(n),l=n<0?"-":"",d=[];let h=o;for(const u of a)if(h>=u.value){const m=Math.floor(h/u.value);h=h%u.value;const p=s?u.short:m===1?u.name:u.name+"s";if(d.push(s?`${m}${p}`:`${m} ${p}`),d.length>=i)break}return d.length===0?s?`${Math.round(o)}ms`:`${Math.round(o)} milliseconds`:l+(s?d.join(""):d.join(" "))}hash(e,t=8,s="",i="..."){if(e==null)return"";const r=String(e);return r.length<=t?s+r:s+r.substring(0,t)+i}stripHtml(e){return e==null?"":String(e).replace(/<[^>]*>/g,"")}highlight(e,t,s="highlight"){if(e==null||!t)return String(e||"");const i=String(t).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(`(${i})`,"gi");return String(e).replace(r,`<mark class="${s}">$1</mark>`)}hex(e,t=!1,s=!1){if(e==null)return"";let i="";const r=n=>Array.from(n).map(a=>a.toString(16).padStart(2,"0")).join("");if(typeof e=="number"){let n=Math.abs(Math.trunc(e)).toString(16);n.length%2&&(n="0"+n),i=n}else if(e instanceof Uint8Array)i=r(e);else if(e instanceof ArrayBuffer)i=r(new Uint8Array(e));else if(Array.isArray(e)&&e.every(n=>typeof n=="number"))i=r(Uint8Array.from(e.map(n=>n&255)));else{const a=new TextEncoder().encode(String(e));i=r(a)}return t&&(i=i.toUpperCase()),(s?"0x":"")+i}unhex(e){if(e==null)return"";let t=String(e).trim();if((t.startsWith("0x")||t.startsWith("0X"))&&(t=t.slice(2)),t=t.replace(/\s+/g,""),t.length===0)return"";t.length%2!==0&&(t="0"+t);const s=new Uint8Array(t.length/2);for(let i=0;i<t.length;i+=2){const r=parseInt(t.slice(i,i+2),16);if(Number.isNaN(r))return String(e);s[i/2]=r}try{return new TextDecoder().decode(s)}catch{let r="";for(const n of s)r+=String.fromCharCode(n);return r}}json(e,t=2){try{return JSON.stringify(e,null,t)}catch{return String(e)}}has(e){return this.formatters.has(e.toLowerCase())}unregister(e){return this.formatters.delete(e.toLowerCase())}listFormatters(){return Array.from(this.formatters.keys()).sort()}iter(e){return e==null?[]:Array.isArray(e)?e:typeof e=="object"?Object.entries(e).map(([t,s])=>({key:t,value:s})):[{key:"0",value:e}]}}const 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===`
14
+ `}nl2br(e){return e==null?"":this.escapeHtml(String(e)).replace(/\r\n|\r|\n/g,"<br>")}code(e,t=""){if(e==null)return"";const s=t?`language-${this.escapeHtml(String(t))}`:"",i=this.escapeHtml(String(e));return`<pre class="bg-light p-2 rounded border"><code class="${s}">${i}</code></pre>`}register(e,t){if(typeof t!="function")throw new Error(`Formatter must be a function, got ${typeof t}`);return this.formatters.set(e.toLowerCase(),t),this}apply(e,t,...s){try{const i=this.formatters.get(e.toLowerCase());return i?i(t,...s):(console.warn(`Formatter '${e}' not found`),t)}catch(i){return console.error(`Error in formatter '${e}':`,i),t}}pipe(e,t,s=null){return t?this.parsePipeString(t,s).reduce((r,n)=>this.apply(n.name,r,...n.args),e):e}parsePipeString(e,t=null){const s=[],i=e.split("|").map(r=>r.trim());for(const r of i){const n=this.parseFormatter(r,t);n&&s.push(n)}return s}parseFormatter(e,t=null){const s=e.match(/^([a-zA-Z_]\w*)\s*\((.*)\)$/);if(s){const[,r,n]=s,a=n?this.parseArguments(n,t):[];return{name:r,args:a}}const i=e.match(/^([a-zA-Z_]\w*)(?::(.+))?$/);if(i){const[,r,n]=i,a=n?this.parseColonArguments(n,t):[];return{name:r,args:a}}return null}parseArguments(e,t=null){const s=[];let i="",r=!1,n=null,a=0;for(let o=0;o<e.length;o++){const l=e[o];!r&&(l==='"'||l==="'")?(r=!0,n=l,i+=l):r&&l===n&&e[o-1]!=="\\"?(r=!1,n=null,i+=l):!r&&l==="{"?(a++,i+=l):!r&&l==="}"?(a--,i+=l):!r&&a===0&&l===","?(s.push(this.parseValue(i.trim(),t)),i=""):i+=l}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseColonArguments(e,t=null){const s=[];let i="",r=!1,n=null;for(let a=0;a<e.length;a++){const o=e[a];!r&&(o==='"'||o==="'")?(r=!0,n=o,i+=o):r&&o===n&&e[a-1]!=="\\"?(r=!1,n=null,i+=o):!r&&o===":"?(s.push(this.parseValue(i.trim(),t)),i=""):i+=o}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseValue(e,t=null){if(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);if(e==="true")return!0;if(e==="false")return!1;if(e==="null")return null;if(e!=="undefined"){if(!isNaN(e)&&e!=="")return Number(e);if(e.startsWith("{")&&e.endsWith("}"))try{return JSON.parse(e)}catch{}if(t&&this.isIdentifier(e)){if(!e.includes(".")&&Object.prototype.hasOwnProperty.call(t,e))return t[e];if(t.get&&typeof t.get=="function"){const s=t.get(e);if(s!==void 0)return s}if(t.getContextValue&&typeof t.getContextValue=="function"){const s=t.getContextValue(e);if(s!==void 0)return s}if(e.includes(".")){const s=window.MOJOUtils||(typeof require<"u"?require("./MOJOUtils.js").default:null);if(s){const i=s.getNestedValue(t,e);if(i!==void 0)return i}}}return e}}isIdentifier(e){return/^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/.test(e)}date(e,t="MM/DD/YYYY"){if(!e)return"";e=this.normalizeEpoch(e);let s;if(e instanceof Date)s=e;else if(typeof e=="string")if(/^\d{4}-\d{2}-\d{2}$/.test(e)){const[a,o,l]=e.split("-").map(Number);s=new Date(a,o-1,l)}else s=new Date(e);else s=new Date(e);if(isNaN(s.getTime()))return String(e);const i={YYYY:s.getFullYear(),YY:String(s.getFullYear()).slice(-2),MMMM:s.toLocaleDateString("en-US",{month:"long"}),MMM:s.toLocaleDateString("en-US",{month:"short"}),MM:String(s.getMonth()+1).padStart(2,"0"),M:s.getMonth()+1,dddd:s.toLocaleDateString("en-US",{weekday:"long"}),ddd:s.toLocaleDateString("en-US",{weekday:"short"}),DD:String(s.getDate()).padStart(2,"0"),D:s.getDate()};let r=t;const n=new RegExp(`(${Object.keys(i).join("|")})`,"g");return r=r.replace(n,a=>i[a]||a),r}time(e,t="HH:mm:ss"){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const i=s.getHours(),r={HH:String(i).padStart(2,"0"),H:i,hh:String(i%12||12).padStart(2,"0"),h:i%12||12,mm:String(s.getMinutes()).padStart(2,"0"),m:s.getMinutes(),ss:String(s.getSeconds()).padStart(2,"0"),s:s.getSeconds(),A:i>=12?"PM":"AM",a:i>=12?"pm":"am"};let n=t;const a=Object.keys(r).sort((o,l)=>l.length-o.length);for(const o of a)n=n.replace(new RegExp(o,"g"),r[o]);return n}datetime(e,t="MM/DD/YYYY",s="HH:mm:ss"){e=this.normalizeEpoch(e);const i=this.date(e,t),r=this.time(e,s);return i&&r?`${i} ${r}`:""}datetime_tz(e,t="MM/DD/YYYY",s="HH:mm:ss",i={}){if(!e)return"";e=this.normalizeEpoch(e);const r=e instanceof Date?e:new Date(e);if(isNaN(r.getTime()))return String(e);const n=i&&i.locale||"en-US",a=i&&i.timeZone?i.timeZone:void 0,o=()=>{let k="";try{const X=new Intl.DateTimeFormat(n,{hour:"2-digit",minute:"2-digit",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(R=>R.type==="timeZoneName");if(k=X?X.value:"",k&&/^GMT[+-]/i.test(k))try{const ee=new Intl.DateTimeFormat(n,{timeStyle:"short",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(ws=>ws.type==="timeZoneName");ee&&ee.value&&!/^GMT[+-]/i.test(ee.value)&&(k=ee.value)}catch{}if(k&&/\s/.test(k)){const R=k.split(/\s+/).map(ee=>ee[0]).join("").toUpperCase();R.length>=2&&R.length<=4&&(k=R)}}catch{k=""}return k};if(!a){const k=this.date(r,t),Y=this.time(r,s),X=o();return k&&Y?`${k} ${Y} ${X}`.trim():""}const l=new Intl.DateTimeFormat(n,{timeZone:a,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hourCycle:"h23"}).formatToParts(r),d=k=>{const Y=l.find(X=>X.type===k);return Y?Y.value:""},h=d("year"),u=d("month"),m=d("day"),p=d("hour"),f=d("minute"),g=d("second"),b=u?String(parseInt(u,10)):"",y=m?String(parseInt(m,10)):"",w=p?String(parseInt(p,10)):"",x=p?parseInt(p,10)%12||12:"",A=p?parseInt(p,10)>=12?"PM":"AM":"",E=A?A.toLowerCase():"",j=new Intl.DateTimeFormat(n,{timeZone:a,month:"long"}).format(r),M=new Intl.DateTimeFormat(n,{timeZone:a,month:"short"}).format(r),O=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"long"}).format(r),re=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"short"}).format(r),fe={YYYY:h,YY:h?h.slice(-2):"",MMMM:j,MMM:M,MM:u,M:b,dddd:O,ddd:re,DD:m,D:y},ge={HH:p,H:w,hh:x!==""?String(x).padStart(2,"0"):"",h:x!==""?String(x):"",mm:f,m:f?String(parseInt(f,10)):"",ss:g,s:g?String(parseInt(g,10)):"",A,a:E},I=(k,Y)=>{if(!k)return"";const X=new RegExp(`(${Object.keys(Y).sort((R,ee)=>ee.length-R.length).join("|")})`,"g");return k.replace(X,R=>Y[R]??R)},q=I(t,fe),At=I(s,ge),ys=o();return q&&At?`${q} ${At} ${ys}`.trim():""}normalizeEpoch(e){if(e instanceof Date)return e;if(typeof e=="string"){const t=Number(e);if(Number.isFinite(t))e=t;else{const s=Date.parse(e);return Number.isFinite(s)?s:""}}else typeof e!="number"&&(e=Number(e));if(isNaN(e))return"";if(e<1e11)return e*1e3;if(e>1e12&&e<1e13)return e;throw new Error("Value doesn't look like epoch seconds or ms")}date_range(e,t=null,s="MM/DD/YYYY"){if(!e)return"";const i=t||new Date,r=this.date(e,s),n=this.date(i,s);return!r||!n?"":`${r} - ${n}`}datetime_range(e,t=null,s="MM/DD/YYYY",i="HH:mm"){if(!e)return"";const r=t||new Date,n=this.datetime(e,s,i),a=this.datetime(r,s,i);return!n||!a?"":`${n} - ${a}`}relative(e,t=!1){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const r=s-new Date,n=Math.abs(r),a=Math.floor(n/1e3),o=Math.floor(a/60),l=Math.floor(o/60),d=Math.floor(l/24),h=r>0;if(t)return d>365?Math.floor(d/365)+"y":d>30?Math.floor(d/30)+"mo":d>7?Math.floor(d/7)+"w":d>0?d+"d":l>0?l+"h":o>0?o+"m":"now";if(d>365){const u=Math.floor(d/365),m=h?"in ":"",p=h?"":" ago";return m+u+" year"+(u>1?"s":"")+p}if(d>30){const u=Math.floor(d/30),m=h?"in ":"",p=h?"":" ago";return m+u+" month"+(u>1?"s":"")+p}if(d>7){const u=Math.floor(d/7),m=h?"in ":"",p=h?"":" ago";return m+u+" week"+(u>1?"s":"")+p}if(d===1)return h?"tomorrow":"yesterday";if(d>0){const u=h?"in ":"",m=h?"":" ago";return u+d+" days"+m}if(l>0){const u=h?"in ":"",m=h?"":" ago";return u+l+" hour"+(l>1?"s":"")+m}if(o>0){const u=h?"in ":"",m=h?"":" ago";return u+o+" minute"+(o>1?"s":"")+m}if(a>30){const u=h?"in ":"",m=h?"":" ago";return u+a+" seconds"+m}return"just now"}iso(e,t=!1){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);return isNaN(s.getTime())?String(e):t?s.toISOString().split("T")[0]:s.toISOString()}number(e,t=2,s="en-US"){const i=parseFloat(e);return isNaN(i)?String(e):i.toLocaleString(s,{minimumFractionDigits:t,maximumFractionDigits:t})}currency(e,t="$",s=2){const i=parseInt(e);if(isNaN(i))return String(e);const r=Math.abs(i).toString(),n=i<0?"-":"";let a,o;r.length<=2?(a="0",o=r.padStart(2,"0")):(a=r.slice(0,-2),o=r.slice(-2)),a=a.replace(/\B(?=(\d{3})+(?!\d))/g,",");let l;if(s===0)parseInt(o)>=50&&(a=(parseInt(a.replace(/,/g,""))+1).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")),l=a;else if(s===2)l=`${a}.${o}`;else{const d=o.slice(0,s).padEnd(s,"0");l=`${a}.${d}`}return n+t+l}percent(e,t=0,s=!0){const i=parseFloat(e);if(isNaN(i))return String(e);const r=s?i*100:i;return this.number(r,t)+"%"}filesize(e,t=!1,s=1){const i=parseInt(e);if(isNaN(i))return String(e);const r=t?["B","KiB","MiB","GiB","TiB"]:["B","KB","MB","GB","TB"],n=t?1024:1e3;let a=i,o=0;for(;a>=n&&o<r.length-1;)a/=n,o++;const l=o===0?0:s;return`${a.toFixed(l)} ${r[o]}`}ordinal(e,t=!1){const s=parseInt(e);if(isNaN(s))return String(e);const i=s%10,r=s%100;let n="th";return i===1&&r!==11?n="st":i===2&&r!==12?n="nd":i===3&&r!==13&&(n="rd"),t?n:s+n}compact(e,t=1){const s=parseFloat(e);if(isNaN(s))return String(e);const i=Math.abs(s),r=s<0?"-":"";return i>=1e9?r+(i/1e9).toFixed(t)+"B":i>=1e6?r+(i/1e6).toFixed(t)+"M":i>=1e3?r+(i/1e3).toFixed(t)+"K":String(s)}add(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s+i}subtract(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s-i}multiply(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s*i}divide(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)||i===0?e:s/i}capitalize(e,t=!0){const s=String(e);return s?t?s.replace(/\b\w/g,i=>i.toUpperCase()):s.charAt(0).toUpperCase()+s.slice(1):""}replace(e,t,s="",i="g"){if(e==null)return"";const r=String(e);if(t==null||t==="")return r;if(t instanceof RegExp)return r.replace(t,String(s));const n=String(t),a=n.match(/^\/(.+)\/([a-z]*)$/i);if(a){const[,o,l]=a;try{return r.replace(new RegExp(o,l),String(s))}catch{}}return String(i).includes("g")?r.split(n).join(String(s)):r.replace(n,String(s))}truncate(e,t=50,s="..."){const i=String(e);return i.length<=t?i:i.substring(0,t)+s}truncate_front(e,t=8,s="..."){const i=String(e);return i.length<=t?i:`${s}${i.slice(-t)}`}truncate_middle(e,t=8,s="***"){const i=String(e);if(i.length<=t)return i;const r=Math.floor(t/2),n=i.substring(0,r),a=i.substring(i.length-r);return`${n}${s}${a}`}slug(e,t="-"){return String(e).toLowerCase().replace(/[^\w\s-]/g,"").replace(/\s+/g,t).replace(new RegExp(`${t}+`,"g"),t).replace(new RegExp(`^${t}|${t}$`,"g"),"")}initials(e,t=2){return String(e).split(/\s+/).filter(r=>r.length>0).slice(0,t).map(r=>r.charAt(0).toUpperCase()).join("")}mask(e,t="*",s=4){const i=String(e);if(i.length<=s)return i;const r=t.repeat(Math.max(0,i.length-s)),n=i.slice(-s);return r+n}email(e,t={}){const s=String(e).trim();if(!s)return"";if(t.link===!1)return s;const i=t.subject?`?subject=${encodeURIComponent(t.subject)}`:"",r=t.body?`&body=${encodeURIComponent(t.body)}`:"",n=t.class?` class="${t.class}"`:"";return`<a href="mailto:${s}${i}${r}"${n}>${s}</a>`}phone(e,t="US",s=!0){let i=String(e).replace(/\D/g,""),r=i;return t==="US"&&(i.length===10?r=`(${i.slice(0,3)}) ${i.slice(3,6)}-${i.slice(6)}`:i.length===11&&i[0]==="1"&&(r=`+1 (${i.slice(1,4)}) ${i.slice(4,7)}-${i.slice(7)}`)),s?`<a href="tel:${i}">${r}</a>`:r}url(e,t=null,s=!0){let i=String(e).trim();return i?(/^https?:\/\//.test(i)||(i="https://"+i),`<a href="${i}"${s?' target="_blank"':""}${s?' rel="noopener noreferrer"':""}>${t||i}</a>`):""}badge(e,t="auto"){if(Array.isArray(e))return e.map(n=>this.badge(n,t)).join(" ");const s=String(e);if(typeof t=="string"&&t.includes("=")){const n=Object.fromEntries(t.split(",").map(l=>l.split("=").map(d=>d.trim()))),a=n[s]||n[s.toLowerCase()]||this.inferBadgeType(s);return`<span class="badge ${a?`bg-${a}`:"bg-secondary"}">${s}</span>`}const i=t==="auto"?this.inferBadgeType(s):t;return`<span class="badge ${i?`bg-${i}`:"bg-secondary"}">${s}</span>`}badgeClass(e,t="auto"){const s=String(e),i=t==="auto"?this.inferBadgeType(s):t;return i?`bg-${i}`:"bg-secondary"}inferBadgeType(e){const t=e.toLowerCase();return["active","pass","success","complete","completed","approved","done","true","on","yes"].includes(t)?"success":["error","failed","fail","rejected","deleted","cancelled","false","off","no","declined"].includes(t)?"danger":["warning","pending","review","processing","uploading"].includes(t)?"warning":["info","new","draft"].includes(t)?"info":(["inactive","disabled","archived","suspended"].includes(t),"secondary")}status(e){return this._status(e)}status_icon(e){return this._status(e,{},{},!1,!0)}status_text(e){return this._status(e,{},{},!0,!1)}_status(e,t={},s={},i=!1,r=!1){const n=String(e).toLowerCase(),a={active:"bi bi-check-circle-fill",approved:"bi bi-check-circle-fill",declined:"bi bi-x-circle-fill",inactive:"bi bi-pause-circle-fill",pending:"bi bi-clock-fill",success:"bi bi-check-circle-fill",error:"bi bi-exclamation-triangle-fill",warning:"bi bi-exclamation-triangle-fill"},o={active:"success",approved:"success",declined:"danger",inactive:"secondary",pending:"warning",success:"success",error:"danger",warning:"warning"},l=t[n]||a[n]||"",d=s[n]||o[n]||"secondary";let h="";!i&&l&&(h=`<i class="${l}"></i>`);let u="";return r||(u=e),`<span class="text-${d}">${h}${h?" ":""}${u}</span>`}boolean(e,t="True",s="False",i=!1){const r=e?t:s;return i?`<span class="text-${e?"success":"danger"}">${r}</span>`:r}bool(e){return e==null||e===0||e===""||e===!1||e==="false"?!1:e===!0||e==="true"?!0:!(Array.isArray(e)&&e.length===0||e&&typeof e=="object"&&e.constructor===Object&&Object.keys(e).length===0)}icon(e,t={}){const s=String(e).toLowerCase(),i=t[s]||"";return i?`<i class="${i}"></i>`:""}yesnoicon(e,t="bi bi-check-circle-fill text-success",s="bi bi-x-circle-fill text-danger"){return e?`<i class="${t}"></i>`:`<i class="${s}"></i>`}image(e,t="thumbnail",s="img-fluid",i=""){const r=this._extractImageUrl(e,t);return r?`<img src="${r}" class="${s}" alt="${i}" />`:""}avatar(e,t="md",s="rounded-circle",i=""){const r=this._extractImageUrl(e,"square_sm")||Dt,n={xs:"width: 1.5rem; height: 1.5rem;",sm:"width: 2rem; height: 2rem;",md:"width: 3rem; height: 3rem;",lg:"width: 4rem; height: 4rem;",xl:"width: 5rem; height: 5rem;"},a=n[t]||n.md,l=`object-fit-cover ${s}`.trim();return`<img src="${r}" class="${l}" style="${a}" alt="${i}" />`}tooltip(e,t="",s="top",i=""){if(e==null)return"";const r=String(e),n=i==="html"?t:this.escapeHtml(t);return`<span data-bs-toggle="tooltip" data-bs-placement="${s}" ${i==="html"?'data-bs-html="true"':""} data-bs-title="${n}">${r}</span>`}_extractImageUrl(e,t="thumbnail"){if(!e)return null;if(typeof e=="string")return e;if(typeof e=="object"){if(e.attributes&&(e=e.attributes),t==="thumbnail"&&e.thumbnail&&typeof e.thumbnail=="string")return e.thumbnail;if(e.renditions&&typeof e.renditions=="object"){const s=e.renditions[t];if(s&&s.url)return s.url;const i=Object.values(e.renditions);if(i.length>0&&i[0].url)return i[0].url}if(e.url)return e.url}return null}default(e,t=""){return e==null||e===""?t:e}equals(e,t,s,i=""){return e==t?s:i}plural(e,t,s=null,i=!0){if(e==null||t===null||t===void 0)return i?`${e} ${t}`:t||"";const r=parseInt(e);if(isNaN(r))return i?`${e} ${t}`:t||"";const n=Math.abs(r)===1?t:s||t+"s";return i?`${r} ${n}`:n}formatList(e,t={}){if(!Array.isArray(e))return String(e);const{conjunction:s="and",limit:i=null,moreText:r="others"}=t;if(e.length===0)return"";if(e.length===1)return String(e[0]);let n=e.slice(),a=!1;if(i&&e.length>i&&(n=e.slice(0,i),a=!0),a){const o=e.length-i;return`${n.join(", ")}, ${s} ${o} ${r}`}return n.length===2?`${n[0]} ${s} ${n[1]}`:`${n.slice(0,-1).join(", ")}, ${s} ${n[n.length-1]}`}duration(e,t="ms",s=!1,i=2){if(e==null)return"";const r=parseFloat(e);if(isNaN(r))return String(e);let n;switch(t){case"s":case"sec":case"seconds":n=r*1e3;break;case"m":case"min":case"minutes":n=r*6e4;break;case"h":case"hr":case"hours":n=r*36e5;break;case"d":case"day":case"days":n=r*864e5;break;default:n=r}const a=[{name:"day",short:"d",value:864e5},{name:"hour",short:"h",value:36e5},{name:"minute",short:"m",value:6e4},{name:"second",short:"s",value:1e3}];if(n===0)return s?"0s":"0 seconds";const o=Math.abs(n),l=n<0?"-":"",d=[];let h=o;for(const u of a)if(h>=u.value){const m=Math.floor(h/u.value);h=h%u.value;const p=s?u.short:m===1?u.name:u.name+"s";if(d.push(s?`${m}${p}`:`${m} ${p}`),d.length>=i)break}return d.length===0?s?`${Math.round(o)}ms`:`${Math.round(o)} milliseconds`:l+(s?d.join(""):d.join(" "))}hash(e,t=8,s="",i="..."){if(e==null)return"";const r=String(e);return r.length<=t?s+r:s+r.substring(0,t)+i}stripHtml(e){return e==null?"":String(e).replace(/<[^>]*>/g,"")}highlight(e,t,s="highlight"){if(e==null||!t)return String(e||"");const i=String(t).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(`(${i})`,"gi");return String(e).replace(r,`<mark class="${s}">$1</mark>`)}hex(e,t=!1,s=!1){if(e==null)return"";let i="";const r=n=>Array.from(n).map(a=>a.toString(16).padStart(2,"0")).join("");if(typeof e=="number"){let n=Math.abs(Math.trunc(e)).toString(16);n.length%2&&(n="0"+n),i=n}else if(e instanceof Uint8Array)i=r(e);else if(e instanceof ArrayBuffer)i=r(new Uint8Array(e));else if(Array.isArray(e)&&e.every(n=>typeof n=="number"))i=r(Uint8Array.from(e.map(n=>n&255)));else{const a=new TextEncoder().encode(String(e));i=r(a)}return t&&(i=i.toUpperCase()),(s?"0x":"")+i}unhex(e){if(e==null)return"";let t=String(e).trim();if((t.startsWith("0x")||t.startsWith("0X"))&&(t=t.slice(2)),t=t.replace(/\s+/g,""),t.length===0)return"";t.length%2!==0&&(t="0"+t);const s=new Uint8Array(t.length/2);for(let i=0;i<t.length;i+=2){const r=parseInt(t.slice(i,i+2),16);if(Number.isNaN(r))return String(e);s[i/2]=r}try{return new TextDecoder().decode(s)}catch{let r="";for(const n of s)r+=String.fromCharCode(n);return r}}json(e,t=2){try{return JSON.stringify(e,null,t)}catch{return String(e)}}has(e){return this.formatters.has(e.toLowerCase())}unregister(e){return this.formatters.delete(e.toLowerCase())}listFormatters(){return Array.from(this.formatters.keys()).sort()}iter(e){return e==null?[]:Array.isArray(e)?e:typeof e=="object"?Object.entries(e).map(([t,s])=>({key:t,value:s})):[{key:"0",value:e}]}}const V=new It;window.dataFormatter=V;class ${static getContextData(e,t){if(!t||e==null)return;let s=t,i="",r=0,n=-1;for(let o=0;o<t.length;o++){const l=t[o];if(l==="(")r++;else if(l===")")r--;else if(l==="|"&&r===0){n=o;break}}n>-1&&(s=t.substring(0,n).trim(),i=t.substring(n+1).trim());const a=this.getNestedValue(e,s);return i?V.pipe(a,i,e):a}static getNestedValue(e,t){if(!t||e==null)return;if(!t.includes(".")){if(t in e){const r=e[t];return typeof r=="function"?r.call(e):r}return}const s=t.split(".");let i=e;for(let r=0;r<s.length;r++){const n=s[r];if(i==null)return;if(r===0)if(i.hasOwnProperty(n)){const a=i[n];typeof a=="function"?i=a.call(e):i=a}else return;else{if(i&&typeof i.getContextValue=="function"){const a=s.slice(r).join(".");return i.getContextValue(a)}if(Array.isArray(i)&&!isNaN(n))i=i[parseInt(n)];else if(i.hasOwnProperty(n))i=i[n];else if(typeof i[n]=="function")i=i[n].call(i);else return}}return i}static isNullOrUndefined(e){return e==null}static deepClone(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(e instanceof Array)return e.map(t=>this.deepClone(t));if(e instanceof Object){const t={};for(const s in e)e.hasOwnProperty(s)&&(t[s]=this.deepClone(e[s]));return t}}static deepMerge(e,...t){if(!t.length)return e;const s=t.shift();if(this.isObject(e)&&this.isObject(s))for(const i in s)this.isObject(s[i])?(e[i]||Object.assign(e,{[i]:{}}),this.deepMerge(e[i],s[i])):Object.assign(e,{[i]:s[i]});return this.deepMerge(e,...t)}static isObject(e){return e&&typeof e=="object"&&!Array.isArray(e)}static debounce(e,t){let s;return function(...r){const n=()=>{clearTimeout(s),e(...r)};clearTimeout(s),s=setTimeout(n,t)}}static throttle(e,t){let s;return function(...i){s||(e.apply(this,i),s=!0,setTimeout(()=>s=!1,t))}}static generateId(e=""){const t=Date.now().toString(36),s=Math.random().toString(36).substr(2,9);return e?`${e}_${t}_${s}`:`${t}_${s}`}static escapeHtml(e){const t={"&":"&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===`
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 Vt=`
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=`
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>${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=`
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=`
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="${Pt}">
124
+ <pre class="${i} dialog-code-block" style="${Vt}">
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=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`
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`
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,7 +199,7 @@ var MOJO=(function(F){"use strict";class $e{constructor(e={}){this.defaultRoute=
199
199
  </small>
200
200
  </div>
201
201
  </div>
202
- `}updateProgress(e){this.cancelled||this.completed||(this.progress=e.progress,this.percentage=e.percentage,this.loaded=e.loaded,this.total=e.total||this.filesize,this.loadedFormatted=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 qt{constructor(e,t={}){if(this.fileModel=e,this.options={file:null,name:null,group:null,description:null,onProgress:null,onComplete:null,onError:null,showToast:!0,...t},!this.options.file||!(this.options.file instanceof File))throw new Error("FileUpload requires a valid File object");this.cancelled=!1,this.uploadRequest=null,this.progressToast=null,this.progressView=null,this.toastService=null,this.options.showToast&&(this.toastService=new jt),this.promise=this._startUpload()}async _startUpload(){try{this.options.showToast&&this._showProgressToast();let e;try{e=await this._initiateUpload()}catch(i){throw new Error(`Failed to initiate upload: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");if(!e||!e.upload_url)throw new Error("Invalid upload response: missing upload URL");let t;if(typeof e.upload_url=="string")t={url:e.upload_url,method:"PUT",fields:null,headers:{}};else if(e.upload_url&&typeof e.upload_url=="object"&&e.upload_url.upload_url)t={url:e.upload_url.upload_url,method:e.upload_url.method||"POST",fields:e.upload_url.fields||null,headers:e.upload_url.headers||{}};else throw new Error(`Invalid upload response: unrecognised upload_url format. Server returned: ${JSON.stringify(e.upload_url)}`);let s;try{s=await this._performUpload(t)}catch(i){throw new Error(`File upload failed: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");try{await this._completeUpload()}catch(i){console.warn("Failed to mark upload as completed:",i)}return this._onComplete(this.fileModel),this.fileModel}catch(e){throw e.message!=="Upload cancelled"&&this._onError(e),e}}async _initiateUpload(){try{const e={filename:this.options.name||this.options.file.name,file_size:this.options.file.size,content_type:this.options.file.type};this.options.group&&(e.group=this.options.group),this.options.description&&(e.description=this.options.description);const t=await this.fileModel.rest.POST("/api/fileman/upload/initiate",e);if(!t)throw new Error("No response from upload initiation API");if(!t.data)throw new Error("Upload initiation response missing data");if(!t.data.status){const s=t.data.error||"Upload initiation failed";throw new Error(s)}if(!t.data.data)throw new Error("Upload initiation response missing data payload");return t.data.data.id&&this.fileModel.set("id",t.data.data.id),t.data.data}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload initiation. Please check your connection."):e}}async _performUpload(e){return new Promise((t,s)=>{if(!(this.options.file instanceof File)){s(new Error("Only single File objects are supported"));return}const{url:i,method:r,fields:n,headers:a}=e,o=r==="POST"&&n!==null,l=new XMLHttpRequest;this.uploadRequest=l,l.upload.onprogress=u=>{this.cancelled||this._onProgress({progress:u.loaded/u.total,loaded:u.loaded,total:u.total,percentage:Math.round(u.loaded/u.total*100)})},l.onload=()=>{l.status>=200&&l.status<300?t({data:l.response,status:l.status,statusText:l.statusText,xhr:l}):s(new Error(`Upload failed: ${l.status} ${l.statusText}`))},l.onerror=()=>s(new Error("Upload failed: Network error")),l.ontimeout=()=>s(new Error("Upload timed out — file may be too large or connection too slow")),l.onabort=()=>s(new Error("Upload cancelled"));let d=i;i.startsWith("/")&&!i.startsWith("/api/")&&(d="/api"+i);const h=this.fileModel.rest.buildUrl(d);if(l.open(r,h),l.timeout=3e4,o){for(const[m,p]of Object.entries(a||{}))m.toLowerCase()!=="content-type"&&l.setRequestHeader(m,p);const u=new FormData;for(const[m,p]of Object.entries(n))u.append(m,p);u.append("file",this.options.file),l.send(u)}else{l.setRequestHeader("Content-Type",this.options.file.type);for(const[u,m]of Object.entries(a||{}))u.toLowerCase()!=="content-type"&&l.setRequestHeader(u,m);l.send(this.options.file)}})}async _completeUpload(){try{const e=await this.fileModel.save({action:"mark_as_completed"});if(!e)throw new Error("No response from upload completion API");if(e.data&&!e.data.status){const t=e.data.error||"Failed to mark upload as completed";throw new Error(t)}return e}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload completion. The file may have uploaded successfully."):e}}_onProgress(e){this.progressToast&&this.progressToast.updateProgress&&this.progressToast.updateProgress(e),typeof this.options.onProgress=="function"&&this.options.onProgress(e)}_onComplete(e){this.progressView&&this.progressView.markCompleted("Upload completed successfully!"),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast:",t)}},2e3),typeof this.options.onComplete=="function"&&this.options.onComplete(e)}_onError(e){if(this.progressToast)try{this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast on error:",t)}this.toastService&&this.toastService.error(`Upload failed: ${e.message}`),typeof this.options.onError=="function"&&this.options.onError(e)}_showProgressToast(){this.progressView=new Me({filename:this.options.name||this.options.file.name,filesize:this.options.file.size,showCancel:!0,onCancel:()=>this.cancel()}),this.progressToast=this.toastService.showView(this.progressView,"info",{title:"File Upload",autohide:!1,dismissible:!1})}cancel(){return this.cancelled?!1:(this.cancelled=!0,this.uploadRequest&&typeof this.uploadRequest.abort=="function"&&this.uploadRequest.abort(),this.progressView&&this.progressView.markCancelled(),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(e){console.warn("Error hiding progress toast on cancel:",e)}},1500),!0)}isCancelled(){return this.cancelled}then(e,t){return this.promise.then(e,t)}catch(e){return this.promise.catch(e)}finally(e){return this.promise.finally(e)}getStats(){return{filename:this.options.file.name,size:this.options.file.size,type:this.options.file.type,cancelled:this.cancelled,group:this.options.group,description:this.options.description}}}class le extends se{constructor(e={}){super(e,{endpoint:"/api/group"})}}class ke extends oe{constructor(e={}){super({ModelClass:le,endpoint:"/api/group",size:10,...e})}}const rt={org:"Organization",division:"Division",department:"Department",team:"Team",merchant:"Merchant",partner:"Partner",client:"Client",iso:"ISO",sales:"Sales",reseller:"Reseller",location:"Location",region:"Region",route:"Route",project:"Project",inventory:"Inventory",test:"Testing",misc:"Miscellaneous",qa:"Quality Assurance"},Le=Object.entries(rt).map(([c,e])=>({value:c,label:e})),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, assistant, and system tools"},{name:"security",label:"Security",tooltip:"Incidents, events, rules, tickets, firewall, bouncer, GeoIP, system logs"},{name:"users",label:"Users",tooltip:"User records, passkeys, TOTP, API keys, OAuth, devices, locations"},{name:"groups",label:"Groups",tooltip:"Groups, members, group API keys, settings"},{name:"comms",label:"Communications",tooltip:"Email, phone, SMS, push notifications, chat, notifications"},{name:"jobs",label:"Jobs",tooltip:"Jobs, job events, job logs, runners, queue control, system stats"},{name:"metrics",label:"Metrics",tooltip:"Metrics recording, fetching, categories, values, permissions"},{name:"files",label:"Files",tooltip:"File managers, files, renditions, vault files, vault data, S3 buckets"},{name:"assistant",label:"AI Assistant",tooltip:"Access to the AI Assistant"},{name:"comms",label:"Communication",tooltip:"Ability to notify users"}],S.GRANULAR_PERMISSION_TABS=[{label:"Account",permissions:[{name:"view_users",label:"View Users"},{name:"manage_users",label:"Manage Users"},{name:"view_groups",label:"View Groups"},{name:"manage_groups",label:"Manage Groups"},{name:"manage_group",label:"Manage Own Group"},{name:"view_members",label:"View Members"},{name:"manage_settings",label:"Manage Settings"}]},{label:"Communication",permissions:[{name:"manage_chat",label:"Manage Chat"},{name:"manage_aws",label:"Manage Email (AWS)"},{name:"view_notifications",label:"View Notifications"},{name:"manage_notifications",label:"Manage Notifications"},{name:"send_notifications",label:"Send Notifications"},{name:"view_devices",label:"View Push Devices"},{name:"manage_devices",label:"Manage Push Devices"},{name:"manage_push_config",label:"Push Config"},{name:"view_phone_numbers",label:"View Phone Numbers"},{name:"manage_phone_numbers",label:"Manage Phone Numbers"},{name:"manage_phone_config",label:"Phone Config"},{name:"view_sms",label:"View SMS"},{name:"manage_sms",label:"Manage SMS"},{name:"send_sms",label:"Send SMS"}]},{label:"Platform",permissions:[{name:"view_security",label:"View Security"},{name:"manage_security",label:"Manage Security"},{name:"admin",label:"Log Admin"},{name:"view_logs",label:"View Logs"},{name:"manage_logs",label:"Manage Logs"},{name:"view_jobs",label:"View Jobs"},{name:"manage_jobs",label:"Manage Jobs"},{name:"view_metrics",label:"View Metrics"},{name:"manage_metrics",label:"Manage Metrics"},{name:"write_metrics",label:"Write Metrics"},{name:"view_fileman",label:"View File Managers"},{name:"manage_files",label:"Manage Files"},{name:"view_vault",label:"View Vault"},{name:"manage_vault",label:"Manage Vault"},{name:"manage_docit",label:"Manage Docs"},{name:"manage_shortlinks",label:"Manage Shortlinks"}]}],S.CATEGORY_GRANULAR_MAP={security:["view_security","manage_security"],users:["view_users","manage_users","view_members"],groups:["view_groups","manage_groups","manage_group"],comms:["manage_chat","manage_aws","view_notifications","manage_notifications","send_notifications","view_devices","manage_devices","manage_push_config","view_phone_numbers","manage_phone_numbers","manage_phone_config","view_sms","manage_sms","send_sms"],jobs:["view_jobs","manage_jobs"],metrics:["view_metrics","manage_metrics","write_metrics"],files:["view_fileman","manage_files","view_vault","manage_vault"]},S.APP_CATEGORY_PERMISSIONS=[],S.APP_GRANULAR_PERMISSIONS=[],S._permSwitch=function(c){return{name:`permissions.${c.name}`,type:"switch",label:c.label,columns:6,...c.tooltip?{tooltip:c.tooltip}:{}}},S.PERMISSIONS=[],S.PERMISSION_FIELDS=[],S.CATEGORY_PERMISSION_FIELDS=[],S.GRANULAR_PERMISSION_FIELDS=[],S.GRANULAR_TO_CATEGORY={},S.rebuildPermissions=function(){const c=S._permSwitch;S.PERMISSIONS.length=0,S.PERMISSIONS.push(...S.CATEGORY_PERMISSIONS,...S.GRANULAR_PERMISSION_TABS.flatMap(s=>s.permissions),...S.APP_CATEGORY_PERMISSIONS,...S.APP_GRANULAR_PERMISSIONS),S.PERMISSION_FIELDS.length=0,S.PERMISSION_FIELDS.push(...S.PERMISSIONS.map(c));const e=[{label:"System",fields:S.CATEGORY_PERMISSIONS.map(c)}];S.APP_CATEGORY_PERMISSIONS.length>0&&e.push({label:"App",fields:S.APP_CATEGORY_PERMISSIONS.map(c)}),S.CATEGORY_PERMISSION_FIELDS.length=0,S.CATEGORY_PERMISSION_FIELDS.push({type:"tabset",tabs:e});const t=S.GRANULAR_PERMISSION_TABS.map(s=>({label:s.label,fields:s.permissions.map(c)}));S.APP_GRANULAR_PERMISSIONS.length>0&&t.push({label:"App",fields:S.APP_GRANULAR_PERMISSIONS.map(c)}),S.GRANULAR_PERMISSION_FIELDS.length=0,S.GRANULAR_PERMISSION_FIELDS.push({type:"tabset",tabs:t});for(const s of Object.keys(S.GRANULAR_TO_CATEGORY))delete S.GRANULAR_TO_CATEGORY[s];for(const[s,i]of Object.entries(S.CATEGORY_GRANULAR_MAP))for(const r of i)S.GRANULAR_TO_CATEGORY[r]=s},S.registerCategoryMap=function(c){if(!c)return;let e=!1;for(const[t,s]of Object.entries(c)){if(!Array.isArray(s))continue;const i=S.CATEGORY_GRANULAR_MAP[t]||[];S.CATEGORY_GRANULAR_MAP[t]=Array.from(new Set([...i,...s])),e=!0}e&&S.rebuildPermissions()},S.registerPermissions=function(c){if(c){if(Array.isArray(c.categories)&&S.APP_CATEGORY_PERMISSIONS.push(...c.categories),Array.isArray(c.granularPermissions)&&S.APP_GRANULAR_PERMISSIONS.push(...c.granularPermissions),Array.isArray(c.granularTabs)&&S.GRANULAR_PERMISSION_TABS.push(...c.granularTabs),c.categoryGranularMap)for(const[e,t]of Object.entries(c.categoryGranularMap)){if(!Array.isArray(t))continue;const s=S.CATEGORY_GRANULAR_MAP[e]||[];S.CATEGORY_GRANULAR_MAP[e]=Array.from(new Set([...s,...t]))}S.rebuildPermissions()}},S.rebuildPermissions();const nt={create:{title:"Create User",fields:[{name:"email",type:"text",label:"Email",required:!0},{name:"phone_number",type:"text",label:"Phone number",columns:12},{name:"display_name",type:"text",label:"Display Name"}]},edit:{title:"Edit User",fields:[{name:"email",type:"email",label:"Email",columns:12},{name:"display_name",type:"text",label:"Display Name",columns:12},{name:"phone_number",type:"text",label:"Phone number",columns:12},{type:"collection",name:"org",label:"Organization",Collection:ke,labelField:"name",valueField:"id",columns:12}]},permissions:{fields:S.PERMISSION_FIELDS}},Rt={detailed:{title:"Detailed User Information",columns:2,showEmptyValues:!0,emptyValueText:"Not set",fields:[{name:"id",label:"User ID",type:"number",colSize:3},{name:"display_name",label:"Display Name",type:"text",format:'capitalize|default("Unnamed User")',colSize:9},{name:"username",label:"Username",type:"text",format:"lowercase",colSize:6},{name:"email",label:"Email Address",type:"email",colSize:6},{name:"phone_number",label:"Phone Number",type:"phone",format:'phone|default("Not provided")',colSize:6},{name:"is_active",label:"Account Status",type:"boolean",colSize:6},{name:"last_login",label:"Last Login",type:"datetime",format:"relative",colSize:6},{name:"last_activity",label:"Last Activity",type:"datetime",format:"relative",colSize:6},{name:"avatar.url",label:"Avatar",type:"url",colSize:12},{name:"permissions",label:"User Permissions",type:"dataview",dataViewColumns:2,showEmptyValues:!1},{name:"metadata",label:"User Metadata",type:"dataview",dataViewColumns:1},{name:"avatar",label:"Avatar Details",type:"dataview",dataViewColumns:1}]}};S.DATA_VIEW=Rt.detailed,S.EDIT_FORM=nt.edit,S.ADD_FORM=nt.create;let zt=class extends se{constructor(e={}){super(e,{endpoint:"/api/fileman/file"})}isImage(){return this.get("category")==="image"}getCategory(){return this.get("category")||this._inferCategoryFromContentType()}_inferCategoryFromContentType(){const e=(this.get("content_type")||"").toLowerCase();return e?e.startsWith("image/")?"image":e.startsWith("video/")?"video":e.startsWith("audio/")?"audio":e==="application/pdf"?"pdf":e.startsWith("text/")||e==="application/msword"||e.startsWith("application/vnd.openxmlformats-officedocument.wordprocessingml")||e==="application/vnd.oasis.opendocument.text"?"document":e==="application/vnd.ms-excel"||e.startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml")||e==="application/vnd.oasis.opendocument.spreadsheet"?"spreadsheet":e==="application/vnd.ms-powerpoint"||e.startsWith("application/vnd.openxmlformats-officedocument.presentationml")||e==="application/vnd.oasis.opendocument.presentation"?"presentation":e==="application/zip"||e==="application/x-rar-compressed"||e==="application/x-7z-compressed"||e==="application/x-tar"||e==="application/gzip"?"archive":"other":"other"}hasRenditions(){const e=this.get("renditions");return!!(e&&Object.keys(e).length)}isUploadPending(){const e=this.get("upload_status");return!!(e&&e!=="completed"&&e!=="failed")}regenerateRenditions(e){const t=this.id||this.get("id");if(!t)return Promise.reject(new Error("Cannot regenerate renditions on an unsaved file"));const s=Array.isArray(e)&&e.length?{regenerate_renditions:e}:{regenerate_renditions:!0};return this.rest.POST(`${this.endpoint}/${t}`,s)}share(e=!0){const t=this.id||this.get("id");return t?this.rest.POST(`${this.endpoint}/${t}`,{share:e}):Promise.reject(new Error("Cannot share an unsaved file"))}getRenditions(){const e=this.get("renditions");return e?Object.values(e):[]}getBestImageRendition(){const e=this.getRenditions().filter(t=>t&&typeof t.content_type=="string"&&t.content_type.startsWith("image/"));return e.length?e.reduce((t,s)=>{const i=(parseInt(t.width)||0)*(parseInt(t.height)||0);return(parseInt(s.width)||0)*(parseInt(s.height)||0)>i?s:t}):null}getThumbnailUrl(){const e=this.get("renditions")||{};if(e.thumbnail&&e.thumbnail.url)return e.thumbnail.url;const t=this.getBestImageRendition();return t?t.url:null}upload(e={}){return new qt(this,e)}};class v{static _renderAndAwait(e,{buttons:t=null,rejectOnDismiss:s=!1,onAction:i=null,cleanup:r=null}={}){const n=_.getMountTarget();return new Promise((a,o)=>{let l=!1;const d=u=>{l||(l=!0,a(u))},h=u=>{l||(l=!0,o(u))};(async()=>{try{await e.render(!0,n)}catch(u){h(u);return}t&&t.length>0&&e.element&&e.element.querySelectorAll(".modal-footer button").forEach((m,p)=>{const f=t[p];f&&m.addEventListener("click",async g=>{if(l)return;const b=f.value!==void 0?f.value:f.action??p;if(typeof f.handler=="function"){try{const y=await f.handler({dialog:e,button:f,index:p,event:g});if(y===null||y===!1)return;const w=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(w)}catch(y){console.error("Modal button handler error:",y)}return}if(typeof i=="function"&&f.action){try{const y=await i(f.action,{dialog:e,button:f,index:p,event:g});if(y===null||y===!1)return;const w=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(w)}catch(y){console.error("Modal onAction error:",y)}return}f.dismiss||e.hide(),d(b)})}),e.on("hidden",()=>{l||(s?h(new Error("Dialog dismissed")):d(null)),setTimeout(async()=>{try{typeof r=="function"&&await r(e)}catch(u){console.error("Modal cleanup error:",u)}try{await e.destroy()}catch(u){console.error("Modal destroy error:",u)}e.element?.parentNode&&e.element.parentNode.removeChild(e.element)},100)}),e.show()})()})}static async dialog(e={}){if(typeof e=="string"){const p=arguments[0],f=arguments[1]||"Alert";e={...arguments[2]||{},body:p,title:f}}const{title:t="Dialog",content:s,body:i,view:r,message:n,size:a="md",centered:o=!0,buttons:l=[{text:"OK",class:"btn-primary",value:!0}],rejectOnDismiss:d=!1,...h}=e,u=i??r??n??s??"",m=new _({title:t,body:u,size:a,centered:o,buttons:l,...h});return v._renderAndAwait(m,{buttons:l,rejectOnDismiss:d})}static async drawer(e={}){const{eyebrow:t,title:s,meta:i=[],view:r,body:n,size:a="lg",...o}=e,l=i.length?`
202
+ `}updateProgress(e){this.cancelled||this.completed||(this.progress=e.progress,this.percentage=e.percentage,this.loaded=e.loaded,this.total=e.total||this.filesize,this.loadedFormatted=V.pipe(this.loaded,"filesize"),this.totalFormatted=V.pipe(this.total,"filesize"),this.percentage<100?this.status=`Uploading... ${this.percentage}%`:this.status="Finalizing upload...",this.render())}markCompleted(e="Upload completed!"){this.completed=!0,this.progress=1,this.percentage=100,this.status=e,this.render()}markFailed(e="Upload failed"){this.status=e,this.render()}markCancelled(){this.cancelled=!0,this.status="Upload cancelled",this.render()}async onActionCancel(e,t,s){if(!(this.cancelled||this.completed)&&(s.disabled=!0,this.markCancelled(),this.emit("cancel"),typeof this.onCancel=="function"))try{await this.onCancel()}catch(i){console.error("Error in cancel callback:",i)}}setFilename(e){this.filename=e,this.render()}setFilesize(e){this.filesize=e,this.filesizeFormatted=V.pipe(e,"filesize"),this.total=e,this.totalFormatted=this.filesizeFormatted,this.render()}getPercentage(){return this.percentage}isCompleted(){return this.completed}isCancelled(){return this.cancelled}getStats(){return{filename:this.filename,filesize:this.filesize,progress:this.progress,percentage:this.percentage,loaded:this.loaded,total:this.total,cancelled:this.cancelled,completed:this.completed,status:this.status}}}class qt{constructor(e,t={}){if(this.fileModel=e,this.options={file:null,name:null,group:null,description:null,onProgress:null,onComplete:null,onError:null,showToast:!0,...t},!this.options.file||!(this.options.file instanceof File))throw new Error("FileUpload requires a valid File object");this.cancelled=!1,this.uploadRequest=null,this.progressToast=null,this.progressView=null,this.toastService=null,this.options.showToast&&(this.toastService=new jt),this.promise=this._startUpload()}async _startUpload(){try{this.options.showToast&&this._showProgressToast();let e;try{e=await this._initiateUpload()}catch(i){throw new Error(`Failed to initiate upload: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");if(!e||!e.upload_url)throw new Error("Invalid upload response: missing upload URL");let t;if(typeof e.upload_url=="string")t={url:e.upload_url,method:"PUT",fields:null,headers:{}};else if(e.upload_url&&typeof e.upload_url=="object"&&e.upload_url.upload_url)t={url:e.upload_url.upload_url,method:e.upload_url.method||"POST",fields:e.upload_url.fields||null,headers:e.upload_url.headers||{}};else throw new Error(`Invalid upload response: unrecognised upload_url format. Server returned: ${JSON.stringify(e.upload_url)}`);let s;try{s=await this._performUpload(t)}catch(i){throw new Error(`File upload failed: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");try{await this._completeUpload()}catch(i){console.warn("Failed to mark upload as completed:",i)}return this._onComplete(this.fileModel),this.fileModel}catch(e){throw e.message!=="Upload cancelled"&&this._onError(e),e}}async _initiateUpload(){try{const e={filename:this.options.name||this.options.file.name,file_size:this.options.file.size,content_type:this.options.file.type};this.options.group&&(e.group=this.options.group),this.options.description&&(e.description=this.options.description);const t=await this.fileModel.rest.POST("/api/fileman/upload/initiate",e);if(!t)throw new Error("No response from upload initiation API");if(!t.data)throw new Error("Upload initiation response missing data");if(!t.data.status){const s=t.data.error||"Upload initiation failed";throw new Error(s)}if(!t.data.data)throw new Error("Upload initiation response missing data payload");return t.data.data.id&&this.fileModel.set("id",t.data.data.id),t.data.data}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload initiation. Please check your connection."):e}}async _performUpload(e){return new Promise((t,s)=>{if(!(this.options.file instanceof File)){s(new Error("Only single File objects are supported"));return}const{url:i,method:r,fields:n,headers:a}=e,o=r==="POST"&&n!==null,l=new XMLHttpRequest;this.uploadRequest=l,l.upload.onprogress=u=>{this.cancelled||this._onProgress({progress:u.loaded/u.total,loaded:u.loaded,total:u.total,percentage:Math.round(u.loaded/u.total*100)})},l.onload=()=>{l.status>=200&&l.status<300?t({data:l.response,status:l.status,statusText:l.statusText,xhr:l}):s(new Error(`Upload failed: ${l.status} ${l.statusText}`))},l.onerror=()=>s(new Error("Upload failed: Network error")),l.ontimeout=()=>s(new Error("Upload timed out — file may be too large or connection too slow")),l.onabort=()=>s(new Error("Upload cancelled"));let d=i;i.startsWith("/")&&!i.startsWith("/api/")&&(d="/api"+i);const h=this.fileModel.rest.buildUrl(d);if(l.open(r,h),l.timeout=3e4,o){for(const[m,p]of Object.entries(a||{}))m.toLowerCase()!=="content-type"&&l.setRequestHeader(m,p);const u=new FormData;for(const[m,p]of Object.entries(n))u.append(m,p);u.append("file",this.options.file),l.send(u)}else{l.setRequestHeader("Content-Type",this.options.file.type);for(const[u,m]of Object.entries(a||{}))u.toLowerCase()!=="content-type"&&l.setRequestHeader(u,m);l.send(this.options.file)}})}async _completeUpload(){try{const e=await this.fileModel.save({action:"mark_as_completed"});if(!e)throw new Error("No response from upload completion API");if(e.data&&!e.data.status){const t=e.data.error||"Failed to mark upload as completed";throw new Error(t)}return e}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload completion. The file may have uploaded successfully."):e}}_onProgress(e){this.progressToast&&this.progressToast.updateProgress&&this.progressToast.updateProgress(e),typeof this.options.onProgress=="function"&&this.options.onProgress(e)}_onComplete(e){this.progressView&&this.progressView.markCompleted("Upload completed successfully!"),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast:",t)}},2e3),typeof this.options.onComplete=="function"&&this.options.onComplete(e)}_onError(e){if(this.progressToast)try{this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast on error:",t)}this.toastService&&this.toastService.error(`Upload failed: ${e.message}`),typeof this.options.onError=="function"&&this.options.onError(e)}_showProgressToast(){this.progressView=new Me({filename:this.options.name||this.options.file.name,filesize:this.options.file.size,showCancel:!0,onCancel:()=>this.cancel()}),this.progressToast=this.toastService.showView(this.progressView,"info",{title:"File Upload",autohide:!1,dismissible:!1})}cancel(){return this.cancelled?!1:(this.cancelled=!0,this.uploadRequest&&typeof this.uploadRequest.abort=="function"&&this.uploadRequest.abort(),this.progressView&&this.progressView.markCancelled(),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(e){console.warn("Error hiding progress toast on cancel:",e)}},1500),!0)}isCancelled(){return this.cancelled}then(e,t){return this.promise.then(e,t)}catch(e){return this.promise.catch(e)}finally(e){return this.promise.finally(e)}getStats(){return{filename:this.options.file.name,size:this.options.file.size,type:this.options.file.type,cancelled:this.cancelled,group:this.options.group,description:this.options.description}}}class le extends se{constructor(e={}){super(e,{endpoint:"/api/group"})}}class ke extends oe{constructor(e={}){super({ModelClass:le,endpoint:"/api/group",size:10,...e})}}const rt={org:"Organization",division:"Division",department:"Department",team:"Team",merchant:"Merchant",partner:"Partner",client:"Client",iso:"ISO",sales:"Sales",reseller:"Reseller",location:"Location",region:"Region",route:"Route",project:"Project",inventory:"Inventory",test:"Testing",misc:"Miscellaneous",qa:"Quality Assurance"},Le=Object.entries(rt).map(([c,e])=>({value:c,label:e})),Pe={create:{title:"Create Group",fields:[{name:"name",type:"text",label:"Group Name",required:!0,placeholder:"Enter group name"},{name:"kind",type:"select",label:"Group Kind",required:!0,options:Le},{type:"collection",name:"parent",label:"Parent Group",Collection:ke,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300}]},edit:{title:"Edit Group",fields:[{name:"name",type:"text",label:"Group Name",required:!0,placeholder:"Enter group name"},{name:"kind",type:"select",label:"Group Kind",required:!0,options:Le},{type:"collection",name:"parent",label:"Parent Group",Collection:ke,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300},{name:"metadata.domain",type:"text",label:"Default Domain",placeholder:"Enter Domain"},{name:"metadata.portal",type:"text",label:"Default Portal",placeholder:"Enter Portal URL"},{name:"is_active",type:"switch",label:"Is Active",cols:4}]}};le.EDIT_FORM=Pe.edit,le.ADD_FORM=Pe.create,le.CREATE_FORM=Pe.create,le.GroupKindOptions=Le,le.GroupKinds=rt;class S extends se{constructor(e={}){super(e,{endpoint:"/api/user"})}hasPermission(e){if(this.get("is_superuser"))return!0;if(Array.isArray(e))return e.some(i=>this.hasPermission(i));const t=e.startsWith("sys."),s=t?e.substring(4):e;return!!(this._hasPermission(s)||!t&&this.member&&this.member.hasPermission(e))}_hasPermission(e){const t=this.get("permissions");if(!t)return!1;if(t[e]==!0)return!0;const s=S.GRANULAR_TO_CATEGORY[e];return!!(s&&t[s]==!0)}hasPerm(e){return this.hasPermission(e)}}S.CATEGORY_PERMISSIONS=[{name:"view_admin",label:"Admin Panel",tooltip:"Access the admin panel, assistant, and system tools"},{name:"security",label:"Security",tooltip:"Incidents, events, rules, tickets, firewall, bouncer, GeoIP, system logs"},{name:"users",label:"Users",tooltip:"User records, passkeys, TOTP, API keys, OAuth, devices, locations"},{name:"groups",label:"Groups",tooltip:"Groups, members, group API keys, settings"},{name:"comms",label:"Communications",tooltip:"Email, phone, SMS, push notifications, chat, notifications"},{name:"jobs",label:"Jobs",tooltip:"Jobs, job events, job logs, runners, queue control, system stats"},{name:"metrics",label:"Metrics",tooltip:"Metrics recording, fetching, categories, values, permissions"},{name:"files",label:"Files",tooltip:"File managers, files, renditions, vault files, vault data, S3 buckets"},{name:"assistant",label:"AI Assistant",tooltip:"Access to the AI Assistant"},{name:"comms",label:"Communication",tooltip:"Ability to notify users"}],S.GRANULAR_PERMISSION_TABS=[{label:"Account",permissions:[{name:"view_users",label:"View Users"},{name:"manage_users",label:"Manage Users"},{name:"view_groups",label:"View Groups"},{name:"manage_groups",label:"Manage Groups"},{name:"manage_group",label:"Manage Own Group"},{name:"view_members",label:"View Members"},{name:"manage_settings",label:"Manage Settings"}]},{label:"Communication",permissions:[{name:"manage_chat",label:"Manage Chat"},{name:"manage_aws",label:"Manage Email (AWS)"},{name:"view_notifications",label:"View Notifications"},{name:"manage_notifications",label:"Manage Notifications"},{name:"send_notifications",label:"Send Notifications"},{name:"view_devices",label:"View Push Devices"},{name:"manage_devices",label:"Manage Push Devices"},{name:"manage_push_config",label:"Push Config"},{name:"view_phone_numbers",label:"View Phone Numbers"},{name:"manage_phone_numbers",label:"Manage Phone Numbers"},{name:"manage_phone_config",label:"Phone Config"},{name:"view_sms",label:"View SMS"},{name:"manage_sms",label:"Manage SMS"},{name:"send_sms",label:"Send SMS"}]},{label:"Platform",permissions:[{name:"view_security",label:"View Security"},{name:"manage_security",label:"Manage Security"},{name:"admin",label:"Log Admin"},{name:"view_logs",label:"View Logs"},{name:"manage_logs",label:"Manage Logs"},{name:"view_jobs",label:"View Jobs"},{name:"manage_jobs",label:"Manage Jobs"},{name:"view_metrics",label:"View Metrics"},{name:"manage_metrics",label:"Manage Metrics"},{name:"write_metrics",label:"Write Metrics"},{name:"view_fileman",label:"View File Managers"},{name:"manage_files",label:"Manage Files"},{name:"view_vault",label:"View Vault"},{name:"manage_vault",label:"Manage Vault"},{name:"manage_docit",label:"Manage Docs"},{name:"manage_shortlinks",label:"Manage Shortlinks"}]}],S.CATEGORY_GRANULAR_MAP={security:["view_security","manage_security"],users:["view_users","manage_users","view_members"],groups:["view_groups","manage_groups","manage_group"],comms:["manage_chat","manage_aws","view_notifications","manage_notifications","send_notifications","view_devices","manage_devices","manage_push_config","view_phone_numbers","manage_phone_numbers","manage_phone_config","view_sms","manage_sms","send_sms"],jobs:["view_jobs","manage_jobs"],metrics:["view_metrics","manage_metrics","write_metrics"],files:["view_fileman","manage_files","view_vault","manage_vault"]},S.APP_CATEGORY_PERMISSIONS=[],S.APP_GRANULAR_PERMISSIONS=[],S._permSwitch=function(c){return{name:`permissions.${c.name}`,type:"switch",label:c.label,columns:6,...c.tooltip?{tooltip:c.tooltip}:{}}},S.PERMISSIONS=[],S.PERMISSION_FIELDS=[],S.CATEGORY_PERMISSION_FIELDS=[],S.GRANULAR_PERMISSION_FIELDS=[],S.GRANULAR_TO_CATEGORY={},S.rebuildPermissions=function(){const c=S._permSwitch;S.PERMISSIONS.length=0,S.PERMISSIONS.push(...S.CATEGORY_PERMISSIONS,...S.GRANULAR_PERMISSION_TABS.flatMap(s=>s.permissions),...S.APP_CATEGORY_PERMISSIONS,...S.APP_GRANULAR_PERMISSIONS),S.PERMISSION_FIELDS.length=0,S.PERMISSION_FIELDS.push(...S.PERMISSIONS.map(c));const e=[{label:"System",fields:S.CATEGORY_PERMISSIONS.map(c)}];S.APP_CATEGORY_PERMISSIONS.length>0&&e.push({label:"App",fields:S.APP_CATEGORY_PERMISSIONS.map(c)}),S.CATEGORY_PERMISSION_FIELDS.length=0,S.CATEGORY_PERMISSION_FIELDS.push({type:"tabset",tabs:e});const t=S.GRANULAR_PERMISSION_TABS.map(s=>({label:s.label,fields:s.permissions.map(c)}));S.APP_GRANULAR_PERMISSIONS.length>0&&t.push({label:"App",fields:S.APP_GRANULAR_PERMISSIONS.map(c)}),S.GRANULAR_PERMISSION_FIELDS.length=0,S.GRANULAR_PERMISSION_FIELDS.push({type:"tabset",tabs:t});for(const s of Object.keys(S.GRANULAR_TO_CATEGORY))delete S.GRANULAR_TO_CATEGORY[s];for(const[s,i]of Object.entries(S.CATEGORY_GRANULAR_MAP))for(const r of i)S.GRANULAR_TO_CATEGORY[r]=s},S.registerCategoryMap=function(c){if(!c)return;let e=!1;for(const[t,s]of Object.entries(c)){if(!Array.isArray(s))continue;const i=S.CATEGORY_GRANULAR_MAP[t]||[];S.CATEGORY_GRANULAR_MAP[t]=Array.from(new Set([...i,...s])),e=!0}e&&S.rebuildPermissions()},S.registerPermissions=function(c){if(c){if(Array.isArray(c.categories)&&S.APP_CATEGORY_PERMISSIONS.push(...c.categories),Array.isArray(c.granularPermissions)&&S.APP_GRANULAR_PERMISSIONS.push(...c.granularPermissions),Array.isArray(c.granularTabs)&&S.GRANULAR_PERMISSION_TABS.push(...c.granularTabs),c.categoryGranularMap)for(const[e,t]of Object.entries(c.categoryGranularMap)){if(!Array.isArray(t))continue;const s=S.CATEGORY_GRANULAR_MAP[e]||[];S.CATEGORY_GRANULAR_MAP[e]=Array.from(new Set([...s,...t]))}S.rebuildPermissions()}},S.rebuildPermissions();const nt={create:{title:"Create User",fields:[{name:"email",type:"text",label:"Email",required:!0},{name:"phone_number",type:"text",label:"Phone number",columns:12},{name:"display_name",type:"text",label:"Display Name"}]},edit:{title:"Edit User",fields:[{name:"email",type:"email",label:"Email",columns:12},{name:"display_name",type:"text",label:"Display Name",columns:12},{name:"phone_number",type:"text",label:"Phone number",columns:12},{type:"collection",name:"org",label:"Organization",Collection:ke,labelField:"name",valueField:"id",columns:12}]},permissions:{fields:S.PERMISSION_FIELDS}},Rt={detailed:{title:"Detailed User Information",columns:2,showEmptyValues:!0,emptyValueText:"Not set",fields:[{name:"id",label:"User ID",type:"number",colSize:3},{name:"display_name",label:"Display Name",type:"text",format:'capitalize|default("Unnamed User")',colSize:9},{name:"username",label:"Username",type:"text",format:"lowercase",colSize:6},{name:"email",label:"Email Address",type:"email",colSize:6},{name:"phone_number",label:"Phone Number",type:"phone",format:'phone|default("Not provided")',colSize:6},{name:"is_active",label:"Account Status",type:"boolean",colSize:6},{name:"last_login",label:"Last Login",type:"datetime",format:"relative",colSize:6},{name:"last_activity",label:"Last Activity",type:"datetime",format:"relative",colSize:6},{name:"avatar.url",label:"Avatar",type:"url",colSize:12},{name:"permissions",label:"User Permissions",type:"dataview",dataViewColumns:2,showEmptyValues:!1},{name:"metadata",label:"User Metadata",type:"dataview",dataViewColumns:1},{name:"avatar",label:"Avatar Details",type:"dataview",dataViewColumns:1}]}};S.DATA_VIEW=Rt.detailed,S.EDIT_FORM=nt.edit,S.ADD_FORM=nt.create;let zt=class extends se{constructor(e={}){super(e,{endpoint:"/api/fileman/file"})}isImage(){return this.get("category")==="image"}getCategory(){return this.get("category")||this._inferCategoryFromContentType()}_inferCategoryFromContentType(){const e=(this.get("content_type")||"").toLowerCase();return e?e.startsWith("image/")?"image":e.startsWith("video/")?"video":e.startsWith("audio/")?"audio":e==="application/pdf"?"pdf":e.startsWith("text/")||e==="application/msword"||e.startsWith("application/vnd.openxmlformats-officedocument.wordprocessingml")||e==="application/vnd.oasis.opendocument.text"?"document":e==="application/vnd.ms-excel"||e.startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml")||e==="application/vnd.oasis.opendocument.spreadsheet"?"spreadsheet":e==="application/vnd.ms-powerpoint"||e.startsWith("application/vnd.openxmlformats-officedocument.presentationml")||e==="application/vnd.oasis.opendocument.presentation"?"presentation":e==="application/zip"||e==="application/x-rar-compressed"||e==="application/x-7z-compressed"||e==="application/x-tar"||e==="application/gzip"?"archive":"other":"other"}hasRenditions(){const e=this.get("renditions");return!!(e&&Object.keys(e).length)}isUploadPending(){const e=this.get("upload_status");return!!(e&&e!=="completed"&&e!=="failed")}regenerateRenditions(e){const t=this.id||this.get("id");if(!t)return Promise.reject(new Error("Cannot regenerate renditions on an unsaved file"));const s=Array.isArray(e)&&e.length?{regenerate_renditions:e}:{regenerate_renditions:!0};return this.rest.POST(`${this.endpoint}/${t}`,s)}share(e=!0){const t=this.id||this.get("id");return t?this.rest.POST(`${this.endpoint}/${t}`,{share:e}):Promise.reject(new Error("Cannot share an unsaved file"))}getRenditions(){const e=this.get("renditions");return e?Object.values(e):[]}getBestImageRendition(){const e=this.getRenditions().filter(t=>t&&typeof t.content_type=="string"&&t.content_type.startsWith("image/"));return e.length?e.reduce((t,s)=>{const i=(parseInt(t.width)||0)*(parseInt(t.height)||0);return(parseInt(s.width)||0)*(parseInt(s.height)||0)>i?s:t}):null}getThumbnailUrl(){const e=this.get("renditions")||{};if(e.thumbnail&&e.thumbnail.url)return e.thumbnail.url;const t=this.getBestImageRendition();return t?t.url:null}upload(e={}){return new qt(this,e)}};class v{static _renderAndAwait(e,{buttons:t=null,rejectOnDismiss:s=!1,onAction:i=null,cleanup:r=null}={}){const n=_.getMountTarget();return new Promise((a,o)=>{let l=!1;const d=u=>{l||(l=!0,a(u))},h=u=>{l||(l=!0,o(u))};(async()=>{try{await e.render(!0,n)}catch(u){h(u);return}t&&t.length>0&&e.element&&e.element.querySelectorAll(".modal-footer button").forEach((m,p)=>{const f=t[p];f&&m.addEventListener("click",async g=>{if(l)return;const b=f.value!==void 0?f.value:f.action??p;if(typeof f.handler=="function"){try{const y=await f.handler({dialog:e,button:f,index:p,event:g});if(y===null||y===!1)return;const w=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(w)}catch(y){console.error("Modal button handler error:",y)}return}if(typeof i=="function"&&f.action){try{const y=await i(f.action,{dialog:e,button:f,index:p,event:g});if(y===null||y===!1)return;const w=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(w)}catch(y){console.error("Modal onAction error:",y)}return}f.dismiss||e.hide(),d(b)})}),e.on("hidden",()=>{l||(s?h(new Error("Dialog dismissed")):d(null)),setTimeout(async()=>{try{typeof r=="function"&&await r(e)}catch(u){console.error("Modal cleanup error:",u)}try{await e.destroy()}catch(u){console.error("Modal destroy error:",u)}e.element?.parentNode&&e.element.parentNode.removeChild(e.element)},100)}),e.show()})()})}static async dialog(e={}){if(typeof e=="string"){const p=arguments[0],f=arguments[1]||"Alert";e={...arguments[2]||{},body:p,title:f}}const{title:t="Dialog",content:s,body:i,view:r,message:n,size:a="md",centered:o=!0,buttons:l=[{text:"OK",class:"btn-primary",value:!0}],rejectOnDismiss:d=!1,...h}=e,u=i??r??n??s??"",m=new _({title:t,body:u,size:a,centered:o,buttons:l,...h});return v._renderAndAwait(m,{buttons:l,rejectOnDismiss:d})}static async drawer(e={}){const{eyebrow:t,title:s,meta:i=[],view:r,body:n,size:a="lg",...o}=e,l=i.length?`
203
203
  <div class="modal-drawer-meta">
204
204
  ${i.map(u=>typeof u=="string"?`<span>${v._esc(u)}</span>`:`<span>${u.icon?`<i class="${v._esc(u.icon)} me-1"></i>`:""}${v._esc(u.text||"")}</span>`).join("")}
205
205
  </div>`:"",d=`
@@ -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 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`
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`
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 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:`
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:`
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 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,qe=null,Re=null;function pt(c="en-US",e="short"){if((!c||c==="en-US"||c==="en")&&e==="short")return Oe.slice();if((!c||c==="en-US"||c==="en")&&e==="long")return Ne.slice();if(typeof Intl>"u"||!Intl.DateTimeFormat)return e==="long"?Ne.slice():Oe.slice();if(ve===c+"/"+e&&qe)return qe.slice();const t=new Intl.DateTimeFormat(c,{month:e}),s=[];for(let i=0;i<12;i++)s.push(t.format(new Date(2024,i,15)));return ve=c+"/"+e,qe=s,s.slice()}function ss(c="en-US",e=1,t="short"){if(typeof Intl>"u"||!Intl.DateTimeFormat)return ft(["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],e);const s=c+"/"+e+"/"+t;if(ve===s&&Re)return Re.slice();const i=new Intl.DateTimeFormat(c,{weekday:t}),r=[];for(let a=0;a<7;a++)r.push(i.format(new Date(2024,0,7+a)));const n=ft(r,e);return ve=s,Re=n,n.slice()}function K(c){return c<10?"0"+c:String(c)}function ft(c,e){const t=(e%c.length+c.length)%c.length;return c.slice(t).concat(c.slice(0,t))}class ze extends C{constructor(e={}){const{precision:t="day",mode:s="single",months:i=1,value:r=null,startValue:n=null,endValue:a=null,min:o=null,max:l=null,disabledDates:d=[],firstDay:h=1,locale:u="en-US",excludeDisabledFromRange:m=!1,year:p=null,month:f=null,class:g="",...b}=e;super({tagName:"div",className:`mojo-calendar mojo-calendar-${t} ${g}`.trim(),...b}),this.precision=t,this.mode=s,this.months=Math.max(1,Math.min(2,i|0)),this.firstDay=h,this.locale=u,this.excludeDisabledFromRange=m,this.min=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(),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=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:w=!0,...x}=e;super({tagName:"div",className:`mojo-date-picker mojo-date-picker-${i} ${m}`.trim(),...x}),this.name=t,this.precision=i,this.format=r,this.displayFormat=n||gt[i]||gt.day,this.min=a,this.max=o,this.placeholder=l??this._defaultPlaceholder(i),this.disabled=d,this.readonly=h,this.required=u,this.inputClass=p,this.inline=f,this.disabledDates=g,this.firstDay=b,this.lang=y,this.autoApply=w,this.currentValue=s||"",this._calendar=null,this._popover=null}_defaultPlaceholder(e){return e==="year"?"Select year...":e==="month"?"Select month...":"Select date..."}async renderTemplate(){const e=this._inputId(),t=this._displayText(this.currentValue),s=!this.currentValue;return this.inline?`
1027
+ `,...e}),this.name=e.name||"multiselect",this.label=e.label||"",this.help=e.help||"",this.error=e.error||"",this.required=e.required||!1,this.disabled=e.disabled||!1,this.placeholder=e.placeholder||e.placeHolder||"Select...",this.maxHeight=e.maxHeight||300,this.showSelectedLabels=e.showSelectedLabels!==!1,this.maxLabelsToShow=e.maxLabelsToShow||3,this.options=e.options||[],this.selectedValues=Array.isArray(e.value)?e.value:[],this.buttonText=this.computeButtonText(),this.listView=null}computeButtonText(){const e=this.selectedValues.length;return e===0?this.placeholder||"Select...":this.showSelectedLabels&&e<=this.maxLabelsToShow?this.selectedValues.map(s=>{const i=this.options.find(r=>(typeof r=="string"?r:r.value)===s);return typeof i=="string"?i:i?.label||i?.value||s}).join(", "):`${e} selected`}async onAfterRender(){await super.onAfterRender(),this.createListView()}createListView(){const e=this.element?.querySelector('[data-container="items"]');if(!e)return;const t=this.options.map((s,i)=>{const r=typeof s=="string"?s:s.value,n=typeof s=="string"?s:s.label||s.text||s.value,a=typeof s=="object"?s.disabled:!1;return{id:`${this.name}_${i}`,value:r,label:n,index:i,selected:this.selectedValues.includes(r),disabled:a}});this.listView=new Zt({items:t,maxHeight:this.maxHeight}),this.listView.on("toggle",s=>{this.handleToggle(s)}),this.listView.on("close-dropdown",()=>{this.closeDropdown()}),this.listView.render(!0,e)}closeDropdown(){const e=this.element?.querySelector(".dropdown-toggle");if(e&&window.bootstrap?.Dropdown){const t=window.bootstrap.Dropdown.getInstance(e);t&&t.hide()}}handleToggle(e){const{value:t,selected:s}=e;s?this.selectedValues.includes(t)||this.selectedValues.push(t):this.selectedValues=this.selectedValues.filter(i=>i!==t),this.updateButtonText(),this.emit("change",{value:this.selectedValues,name:this.name})}updateButtonText(){const e=this.element?.querySelector(".multiselect-button-text");if(!e)return;const t=this.selectedValues.length;this.buttonText=this.computeButtonText(),e.textContent=this.buttonText,t===0?e.classList.add("text-muted"):e.classList.remove("text-muted")}getValue(){return this.selectedValues}setValue(e){this.selectedValues=Array.isArray(e)?e:e?[e]:[],this.listView&&this.listView.setValue(this.selectedValues),this.updateButtonText()}setOptions(e){if(this.options=e,this.listView){const t=this.options.map((s,i)=>{const r=typeof s=="string"?s:s.value,n=typeof s=="string"?s:s.label||s.text||s.value,a=typeof s=="object"?s.disabled:!1;return{id:`${this.name}_${i}`,value:r,label:n,index:i,selected:this.selectedValues.includes(r),disabled:a}});this.listView.updateItems(t)}}clear(){this.setValue([])}getFormValue(){return this.getValue()}setFormValue(e){this.setValue(e)}async onBeforeDestroy(){await super.onBeforeDestroy(),this.listView&&this.listView.destroy()}}const Ne=["January","February","March","April","May","June","July","August","September","October","November","December"],Oe=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function at(c){if(c==null||c==="")return null;const e=parseInt(String(c).slice(0,4),10);return Number.isFinite(e)?{y:e}:null}function we(c){if(c==null||c==="")return null;const e=String(c).split("-"),t=parseInt(e[0],10),s=parseInt(e[1],10);return!Number.isFinite(t)||!Number.isFinite(s)||s<1||s>12?null:{y:t,m:s}}function z(c){if(c==null||c==="")return null;if(c instanceof Date&&!isNaN(c.getTime()))return{y:c.getFullYear(),m:c.getMonth()+1,d:c.getDate()};const e=String(c).split("-"),t=parseInt(e[0],10),s=parseInt(e[1],10),i=parseInt(e[2],10);return!Number.isFinite(t)||!Number.isFinite(s)||!Number.isFinite(i)||s<1||s>12||i<1||i>31?null:{y:t,m:s,d:i}}function ot(c){const e=typeof c=="object"?c:at(c);return e?String(e.y):""}function je(c){const e=typeof c=="object"?c:we(c);return e?`${e.y}-${K(e.m)}`:""}function H(c){const e=typeof c=="object"?c:z(c);return e?`${e.y}-${K(e.m)}-${K(e.d)}`:""}function B(c,e){return e==="year"?ot(c):e==="month"?je(c):H(c)}function P(c,e){return e==="year"?at(c):e==="month"?we(c):z(c)}const Qt=/YYYY|YY|MMMM|MMM|MM|M|DD|D/g;function ce(c,e){if(!c)return"";const t=c.y,s=c.m,i=c.d;return String(e).replace(Qt,r=>{switch(r){case"YYYY":return String(t);case"YY":return String(t).slice(-2);case"MMMM":return s?Ne[s-1]:"";case"MMM":return s?Oe[s-1]:"";case"MM":return s?K(s):"";case"M":return s?String(s):"";case"DD":return i?K(i):"";case"D":return i?String(i):"";default:return r}})}function lt(c,e){return new Date(c,e,0).getDate()}function Xt(c,e,t,s=1){return((new Date(c,e-1,t).getDay()-s)%7+7)%7}function ie(c,e){if(!c)return null;let t=c.y,s=c.m+e;for(;s>12;)s-=12,t+=1;for(;s<1;)s+=12,t-=1;if(c.d==null)return{y:t,m:s};const i=lt(t,s);return{y:t,m:s,d:Math.min(c.d,i)}}function ct(c,e){return!c||!e?0:c.y!==e.y?c.y<e.y?-1:1:(c.m||0)!==(e.m||0)?(c.m||0)<(e.m||0)?-1:1:(c.d||0)!==(e.d||0)?(c.d||0)<(e.d||0)?-1:1:0}function dt(c,e){return!c||!e?0:c.y!==e.y?c.y<e.y?-1:1:(c.m||0)!==(e.m||0)?(c.m||0)<(e.m||0)?-1:1:0}function es(c,e){return!c||!e||c.y===e.y?0:c.y<e.y?-1:1}function U(c,e,t){return t==="year"?es(c,e):t==="month"?dt(c,e):ct(c,e)}function W(c){if(c==null||c==="")return null;if(typeof c=="object"&&c!==null){const d=parseInt(c.hours??c.h,10),h=parseInt(c.minutes??c.m,10);return!Number.isFinite(d)||!Number.isFinite(h)||d<0||d>23||h<0||h>59?null:{hours:d,minutes:h}}const e=String(c).trim(),t=e.indexOf(" "),s=t>-1?e.slice(0,t):e,r=(t>-1?e.slice(t+1).trim():"").match(/^(am|pm)$/i)||s.match(/(am|pm)$/i),a=s.replace(/(am|pm)$/i,"").trim().split(":");if(a.length<2)return null;let o=parseInt(a[0],10);const l=parseInt(a[1],10);if(!Number.isFinite(o)||!Number.isFinite(l)||l<0||l>59)return null;if(r){const d=r[1].toLowerCase()==="pm";if(o<1||o>12)return null;o===12?o=d?12:0:d&&(o+=12)}return o<0||o>23?null:{hours:o,minutes:l}}function G(c,e="24h"){if(!c)return"";const t=c.hours,s=c.minutes;if(!Number.isFinite(t)||!Number.isFinite(s))return"";if(e==="12h"){const i=t>=12?"PM":"AM";let r=t%12;return r===0&&(r=12),`${r}:${K(s)} ${i}`}return`${K(t)}:${K(s)}`}function ht(c,e){return!c||!e?0:c.hours!==e.hours?c.hours<e.hours?-1:1:c.minutes!==e.minutes?c.minutes<e.minutes?-1:1:0}function ts(c,e){if(!c)return null;let t=c.hours*60+c.minutes+e;return t=(t%1440+1440)%1440,{hours:Math.floor(t/60),minutes:t%60}}function ut(c,e){if(!c)return null;try{const t=e instanceof Date?e:new Date,r=new Intl.DateTimeFormat("en-US",{timeZone:c,timeZoneName:"shortOffset"}).formatToParts(t).find(h=>h.type==="timeZoneName");if(!r)return null;let n=r.value;if(n==="GMT"||n==="UTC")return"+00:00";n=n.replace(/^(GMT|UTC)/,"");const a=n.match(/^([+-])(\d{1,2})(?::(\d{2}))?$/);if(!a)return null;const o=a[1],l=a[2].padStart(2,"0"),d=a[3]||"00";return`${o}${l}:${d}`}catch{return null}}function mt(c){if(c==null||c==="")return null;if(typeof c=="object"&&!Array.isArray(c)&&!(c instanceof Date)){const h=c.date?z(c.date):null,u=c.time?W(c.time):null;return h?{date:h,time:u||{hours:0,minutes:0},timezone:c.timezone||null}:null}let e=String(c).trim();const t=e.match(/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})(?::\d{2}(?:\.\d+)?)?(Z|[+-]\d{2}:?\d{2})?$/);if(t){const[,h,u,m,p,f,g]=t;let b=null;return g&&(g==="Z"?b="+00:00":/^[+-]\d{4}$/.test(g)?b=`${g.slice(0,3)}:${g.slice(3)}`:b=g),{date:{y:+h,m:+u,d:+m},time:{hours:+p,minutes:+f},timezone:b}}let s,i;if(e.length>=11&&e.charAt(10)==="T")s=e.slice(0,10),i=e.slice(11);else{const h=e.indexOf(" ");if(h===-1){const u=z(e);return u?{date:u,time:{hours:0,minutes:0},timezone:null}:null}s=e.slice(0,h),i=e.slice(h+1)}const r=z(s);if(!r)return null;const n=i.trim();let a=null,o=n;const l=n.match(/\s+([A-Za-z][A-Za-z_+\-]*\/[A-Za-z][A-Za-z_+\-]*|UTC|GMT)$/);l&&(a=l[1],o=n.slice(0,l.index).trim());const d=W(o);return d?{date:r,time:d,timezone:a}:null}function T(){const c=new Date;return{y:c.getFullYear(),m:c.getMonth()+1,d:c.getDate()}}let ve=null,qe=null,Re=null;function pt(c="en-US",e="short"){if((!c||c==="en-US"||c==="en")&&e==="short")return Oe.slice();if((!c||c==="en-US"||c==="en")&&e==="long")return Ne.slice();if(typeof Intl>"u"||!Intl.DateTimeFormat)return e==="long"?Ne.slice():Oe.slice();if(ve===c+"/"+e&&qe)return qe.slice();const t=new Intl.DateTimeFormat(c,{month:e}),s=[];for(let i=0;i<12;i++)s.push(t.format(new Date(2024,i,15)));return ve=c+"/"+e,qe=s,s.slice()}function ss(c="en-US",e=1,t="short"){if(typeof Intl>"u"||!Intl.DateTimeFormat)return ft(["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],e);const s=c+"/"+e+"/"+t;if(ve===s&&Re)return Re.slice();const i=new Intl.DateTimeFormat(c,{weekday:t}),r=[];for(let a=0;a<7;a++)r.push(i.format(new Date(2024,0,7+a)));const n=ft(r,e);return ve=s,Re=n,n.slice()}function K(c){return c<10?"0"+c:String(c)}function ft(c,e){const t=(e%c.length+c.length)%c.length;return c.slice(t).concat(c.slice(0,t))}class ze extends C{constructor(e={}){const{precision:t="day",mode:s="single",months:i=1,value:r=null,startValue:n=null,endValue:a=null,min:o=null,max:l=null,disabledDates:d=[],firstDay:h=1,locale:u="en-US",excludeDisabledFromRange:m=!1,year:p=null,month:f=null,class:g="",...b}=e;super({tagName:"div",className:`mojo-calendar mojo-calendar-${t} ${g}`.trim(),...b}),this.precision=t,this.mode=s,this.months=Math.max(1,Math.min(2,i|0)),this.firstDay=h,this.locale=u,this.excludeDisabledFromRange=m,this.min=P(o,t)||(o?z(o):null),this.max=P(l,t)||(l?z(l):null),this.disabledDates=(d||[]).map(x=>H(z(x)||null)).filter(Boolean),s==="single"?this.selected=P(r,t):(this.start=P(n,t),this.end=P(a,t),this._anchor=null),this._hover=null,this.view=t;const y=T(),w=(s==="single"?this.selected:this.start||this.end)||y;this.pageY=p!=null?Number(p):w.y??y.y,this.pageM=f!=null?Number(f):w.m??y.m,this._onCellMouseEnter=this._onCellMouseEnter.bind(this),this._onCellMouseLeave=this._onCellMouseLeave.bind(this)}setMin(e){this.min=P(e,this.precision),this._rerender()}setMax(e){this.max=P(e,this.precision),this._rerender()}setValue(e){this.selected=P(e,this.precision),this.selected&&(this.pageY=this.selected.y,this.pageM=this.selected.m||this.pageM),this._rerender()}setRange(e,t){this.start=P(e,this.precision),this.end=P(t,this.precision),this._anchor=null,this._rerender()}getValue(){return this.selected?B(this.selected,this.precision):""}getRange(){return{start:this.start?B(this.start,this.precision):"",end:this.end?B(this.end,this.precision):""}}async renderTemplate(){return""}async onAfterRender(){this._eventsWired||(this._wireEvents(this.element),this._eventsWired=!0),this._renderInto(this.element)}_rerender(){this.element&&this._renderInto(this.element)}_renderInto(e){e.innerHTML="";const t=document.createElement("div");if(t.className=this.months>1&&this.view==="day"?"mojo-calendar-multi":"mojo-calendar-single",this.view==="day"){const s=this.months;for(let i=0;i<s;i++){let r=this.pageY,n=this.pageM+i;for(;n>12;)n-=12,r+=1;t.appendChild(this._buildDayPane(r,n,i===0,i===s-1))}}else this.view==="month"?t.appendChild(this._buildMonthPane(this.pageY)):this.view==="year"&&t.appendChild(this._buildYearPane(this._decadeStart(this.pageY)));e.appendChild(t)}_decadeStart(e){return Math.floor(e/10)*10}_buildDayPane(e,t,s,i){const r=document.createElement("div");return r.className="mojo-calendar-pane",r.appendChild(this._buildHead(this._dayHeadLabel(e,t),"day",s,i,e,t)),r.appendChild(this._buildWeekdayHeader()),r.appendChild(this._buildDayGrid(e,t)),r}_dayHeadLabel(e,t){return{kind:"day",year:e,month:t}}_buildWeekdayHeader(){const e=document.createElement("div");return e.className="mojo-calendar-grid mojo-calendar-grid-day",ss(this.locale,this.firstDay,"short").forEach(t=>{const s=document.createElement("div");s.className="mojo-calendar-weekday",s.textContent=t,e.appendChild(s)}),e}_buildDayGrid(e,t){const s=document.createElement("div");s.className="mojo-calendar-grid mojo-calendar-grid-day";const i=Xt(e,t,1,this.firstDay),r=lt(e,t),n=T();for(let a=0;a<i;a++){const o=document.createElement("div");o.className="mojo-calendar-cell mojo-calendar-cell-blank",s.appendChild(o)}for(let a=1;a<=r;a++){const o={y:e,m:t,d:a},l=document.createElement("button");l.type="button",l.className="mojo-calendar-cell",l.dataset.ymd=H(o),o.y===n.y&&o.m===n.m&&o.d===n.d&&l.classList.add("mojo-calendar-cell-today"),this._isDisabledAt(o,"day")&&(l.classList.add("mojo-calendar-cell-disabled"),l.disabled=!0),this.mode==="range"?this._applyRangeClasses(l,o,"day"):this.selected&&ct(o,this.selected)===0&&l.classList.add("mojo-calendar-cell-selected");const d=document.createElement("span");d.className="mojo-calendar-cell-inner",d.textContent=String(a),l.appendChild(d),s.appendChild(l)}return s}_buildMonthPane(e){const t=document.createElement("div");return t.className="mojo-calendar-pane",t.appendChild(this._buildHead(String(e),"month",!0,!0,e,1)),t.appendChild(this._buildMonthGrid(e)),t}_buildMonthGrid(e){const t=document.createElement("div");t.className="mojo-calendar-grid mojo-calendar-grid-month";const s=pt(this.locale,"short");for(let i=1;i<=12;i++){const r={y:e,m:i},n=document.createElement("button");n.type="button",n.className="mojo-calendar-cell",n.dataset.ym=je(r),this._isDisabledAt(r,"month")&&(n.classList.add("mojo-calendar-cell-disabled"),n.disabled=!0),this.precision==="month"&&this.mode==="range"?this._applyRangeClasses(n,r,"month"):this.precision==="month"&&this.mode==="single"&&this.selected&&dt(r,this.selected)===0&&n.classList.add("mojo-calendar-cell-selected");const a=document.createElement("span");a.className="mojo-calendar-cell-inner",a.textContent=s[i-1],n.appendChild(a),t.appendChild(n)}return t}_buildYearPane(e){const t=document.createElement("div");return t.className="mojo-calendar-pane",t.appendChild(this._buildHead(`${e} – ${e+11}`,"year",!0,!0,e,1)),t.appendChild(this._buildYearGrid(e)),t}_buildYearGrid(e){const t=document.createElement("div");t.className="mojo-calendar-grid mojo-calendar-grid-year";for(let s=0;s<12;s++){const i=e+s,r={y:i},n=document.createElement("button");n.type="button",n.className="mojo-calendar-cell",n.dataset.year=String(i),this._isDisabledAt(r,"year")&&(n.classList.add("mojo-calendar-cell-disabled"),n.disabled=!0),this.precision==="year"&&this.mode==="range"?this._applyRangeClasses(n,r,"year"):this.precision==="year"&&this.mode==="single"&&this.selected&&this.selected.y===i&&n.classList.add("mojo-calendar-cell-selected");const a=document.createElement("span");a.className="mojo-calendar-cell-inner",a.textContent=String(i),n.appendChild(a),t.appendChild(n)}return t}_applyRangeClasses(e,t,s){let i=this.start,r=this.end;if(this._anchor){const o=this._hover||this._anchor,l=U(this._anchor,o,s);i=l<=0?this._anchor:o,r=l<=0?o:this._anchor}if(!i||!r){this._anchor&&U(t,this._anchor,s)===0&&e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-solo");return}const n=U(t,i,s),a=U(t,r,s);n>0&&a<0&&e.classList.add(this._anchor?"mojo-calendar-cell-in-preview":"mojo-calendar-cell-in-range"),n===0&&(e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-start"),U(i,r,s)===0?e.classList.add("mojo-calendar-cell-anchor-solo"):e.classList.add(this._anchor?"mojo-calendar-cell-in-preview":"mojo-calendar-cell-in-range")),a===0&&U(i,r,s)!==0&&(e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-end"),e.classList.add(this._anchor?"mojo-calendar-cell-in-preview":"mojo-calendar-cell-in-range"))}_buildHead(e,t,s,i){const r=document.createElement("div");r.className="mojo-calendar-head";const n=document.createElement("button");if(n.type="button",n.className="mojo-calendar-head-label",n.dataset.level=t,n.dataset.action="zoom-out",typeof e=="string")n.textContent=e;else if(e&&e.kind==="day"){const o=pt(this.locale,"long");n.appendChild(document.createTextNode(`${o[e.month-1]} `));const l=document.createElement("span");l.className="mojo-calendar-year",l.textContent=String(e.year),n.appendChild(l)}r.appendChild(n);const a=document.createElement("div");return a.className="mojo-calendar-nav",s&&a.appendChild(this._navBtn("prev")),i&&a.appendChild(this._navBtn("next")),r.appendChild(a),r}_navBtn(e){const t=document.createElement("button");return t.type="button",t.className="mojo-calendar-nav-btn",t.dataset.action=`nav-${e}`,t.setAttribute("aria-label",e==="prev"?"Previous":"Next"),t.innerHTML=e==="prev"?"&#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?`
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=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: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=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=`
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=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=`
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=`
1056
1056
  <div class="combobox-container">
1057
1057
  <div class="input-group">
1058
1058
  <input type="text"
@@ -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 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=`
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=`
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=`
@@ -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=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.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`
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`
1375
1375
  <div class="mojo-table-wrapper">
1376
1376
  ${this.buildToolbarTemplate()}
1377
1377
  ${e}
@@ -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 i={name:"filter_value",label:e.label,value:t,...e,placeholder:e.placeholder||e.placeHolder};if(e.type==="daterange"){if(i.startName=i.startName||"dr_start",i.endName=i.endName||"dr_end",i.fieldName=i.fieldName||"dr_field",i.format=i.format||"YYYY-MM-DD",i.displayFormat=i.displayFormat||"MMM DD, YYYY",i.separator=i.separator||" to ",i.label=i.label||"Date Range",t&&typeof t=="object"){const r=n=>{if(!n&&n!==0)return"";if(n instanceof Date&&!isNaN(n))return n.toISOString().slice(0,10);const a=String(n).trim();if(!a)return"";if(/^-?\d+$/.test(a)){const l=Number(a),d=a.length<=10?l*1e3:l,h=new Date(d);if(!isNaN(h))return h.toISOString().slice(0,10)}const o=new Date(a);return isNaN(o)?a:o.toISOString().slice(0,10)};i.startDate=r(t.start||t.from||t.begin||""),i.endDate=r(t.end||t.to||t.finish||"")}}else if(e.type==="multiselect"){let r=[];t&&(Array.isArray(t)?r=t:typeof t=="string"&&(r=t.split(",").map(n=>n.trim()).filter(n=>n))),i.value=r,!i.placeholder&&!i.placeHolder&&(e.placeholder||e.placeHolder?i.placeholder=e.placeholder||e.placeHolder:e.label&&(i.placeholder=`Select ${e.label}...`))}return i}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;this.collection.params={start:s,size:i},r&&(this.collection.params.sort=r),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`
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`
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=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`
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`
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?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})({});
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})({});
1739
1739
  //# sourceMappingURL=web-mojo.lite.iife.min.js.map