web-mojo 2.5.11 → 2.5.12

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 (49) 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/{ChatView-D2JKsn70.js → ChatView-Boy13xn0.js} +2 -2
  8. package/dist/chunks/{ChatView-D2JKsn70.js.map → ChatView-Boy13xn0.js.map} +1 -1
  9. package/dist/chunks/{ChatView-bXNwCBea.js → ChatView-_J50Mw9K.js} +2 -2
  10. package/dist/chunks/{ChatView-bXNwCBea.js.map → ChatView-_J50Mw9K.js.map} +1 -1
  11. package/dist/chunks/ListView-BlG1DvdZ.js +2 -0
  12. package/dist/chunks/ListView-BlG1DvdZ.js.map +1 -0
  13. package/dist/chunks/ListView-S5pMrBXs.js +2 -0
  14. package/dist/chunks/ListView-S5pMrBXs.js.map +1 -0
  15. package/dist/chunks/{Passkeys-Dq8v7Hve.js → Passkeys-CvMXixC8.js} +2 -2
  16. package/dist/chunks/{Passkeys-Dq8v7Hve.js.map → Passkeys-CvMXixC8.js.map} +1 -1
  17. package/dist/chunks/{Passkeys-BqQPlxQ-.js → Passkeys-DpH18HEu.js} +2 -2
  18. package/dist/chunks/{Passkeys-BqQPlxQ-.js.map → Passkeys-DpH18HEu.js.map} +1 -1
  19. package/dist/chunks/{UserProfileView-CgOPa29h.js → UserProfileView-BFRqUqIE.js} +2 -2
  20. package/dist/chunks/{UserProfileView-CgOPa29h.js.map → UserProfileView-BFRqUqIE.js.map} +1 -1
  21. package/dist/chunks/{UserProfileView-CY5rbwOV.js → UserProfileView-BUCgJnCx.js} +2 -2
  22. package/dist/chunks/{UserProfileView-CY5rbwOV.js.map → UserProfileView-BUCgJnCx.js.map} +1 -1
  23. package/dist/chunks/{index-Bo1mHdoL.js → index-CWN_9fmw.js} +2 -2
  24. package/dist/chunks/{index-Bo1mHdoL.js.map → index-CWN_9fmw.js.map} +1 -1
  25. package/dist/chunks/{index-DlWzTa2P.js → index-DU5qrlJm.js} +2 -2
  26. package/dist/chunks/{index-DlWzTa2P.js.map → index-DU5qrlJm.js.map} +1 -1
  27. package/dist/chunks/{version-BMN-tbP5.js → version-BJ_dJxnZ.js} +2 -2
  28. package/dist/chunks/{version-BMN-tbP5.js.map → version-BJ_dJxnZ.js.map} +1 -1
  29. package/dist/chunks/{version-rtP1hR6u.js → version-CRy8tr3T.js} +2 -2
  30. package/dist/chunks/{version-rtP1hR6u.js.map → version-CRy8tr3T.js.map} +1 -1
  31. package/dist/docit.cjs.js +1 -1
  32. package/dist/docit.es.js +1 -1
  33. package/dist/index.cjs.js +1 -1
  34. package/dist/index.es.js +1 -1
  35. package/dist/lightbox.cjs.js +1 -1
  36. package/dist/lightbox.es.js +1 -1
  37. package/dist/timeline.cjs.js +1 -1
  38. package/dist/timeline.es.js +1 -1
  39. package/dist/user-profile.cjs.js +1 -1
  40. package/dist/user-profile.es.js +1 -1
  41. package/dist/web-mojo.lite.iife.js +16 -1
  42. package/dist/web-mojo.lite.iife.js.map +1 -1
  43. package/dist/web-mojo.lite.iife.min.js +29 -29
  44. package/dist/web-mojo.lite.iife.min.js.map +1 -1
  45. package/package.json +1 -1
  46. package/dist/chunks/ListView-BR5f9Nzl.js +0 -2
  47. package/dist/chunks/ListView-BR5f9Nzl.js.map +0 -1
  48. package/dist/chunks/ListView-BWAUUg-a.js +0 -2
  49. package/dist/chunks/ListView-BWAUUg-a.js.map +0 -1
@@ -1,4 +1,4 @@
1
- var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=e.defaultRoute||"home",this.routes=[],this.currentRoute=null,this.eventEmitter=e.eventEmitter||null,this.boundHandlePopState=this.handlePopState.bind(this)}start(){window.addEventListener("popstate",this.boundHandlePopState),this.handleCurrentLocation()}stop(){window.removeEventListener("popstate",this.boundHandlePopState)}addRoute(e,t){this.routes.push({pattern:this.normalizePattern(e),regex:this.patternToRegex(e),pageName:t,paramNames:this.extractParamNames(e)})}async navigate(e,t={}){const{replace:s=!1,state:i=null,trigger:r=!0}=t,{pageName:n,queryParams:a}=this.parseInput(e);r&&await this.handleRouteChange(n,a)}back(){window.history.back()}forward(){window.history.forward()}getCurrentRoute(){return this.currentRoute}getCurrentPath(){const{pageName:e,queryParams:t}=this.parseCurrentUrl();return this.buildPublicUrl(e,t)}handlePopState(e){this.allowPopState?this.handleCurrentLocation():console.warn("PopStateEvent is not allowed")}async handleCurrentLocation(){const{pageName:e,queryParams:t}=this.parseCurrentUrl();await this.handleRouteChange(e,t)}async handleRouteChange(e,t){const s="/"+e,i=this.matchRoute(s),r=this.buildPublicUrl(e,t);return i?(this.currentRoute=i,this.eventEmitter&&this.eventEmitter.emit("route:changed",{path:r,pageName:i.pageName,params:i.params,query:t,route:i}),i):(console.log("No route matched for page:",e),this.eventEmitter&&this.eventEmitter.emit("route:notfound",{path:r}),null)}matchRoute(e){for(const t of this.routes){const s=e.match(t.regex);if(s){const i={};return t.paramNames.forEach((r,n)=>{i[r]=s[n+1]}),{...t,params:i,path:e}}}return null}parseInput(e){let t=this.defaultRoute,s={};if(!e)return{pageName:t,queryParams:s};try{if(e.includes("?")){const[i,r]=e.split("?",2),n=new URLSearchParams(r);if(n.has("page")){t=n.get("page")||this.defaultRoute;for(const[a,o]of n)a!=="page"&&(s[a]=o)}else{i.startsWith("/")?t=i.substring(1)||this.defaultRoute:t=i||this.defaultRoute;for(const[a,o]of n)s[a]=o}}else e.startsWith("/")?t=e.substring(1)||this.defaultRoute:t=e}catch(i){console.warn("Failed to parse input:",e,i),t=this.defaultRoute,s={}}return{pageName:t,queryParams:s}}parseCurrentUrl(){const e=new URLSearchParams(window.location.search),t=e.get("page")||this.defaultRoute,s={};for(const[i,r]of e)i!=="page"&&(s[i]=r);return{pageName:t,queryParams:s}}buildPublicUrl(e,t={}){const s=new URLSearchParams;return s.set("page",e),Object.entries(t).forEach(([i,r])=>{r!=null&&r!==""&&s.set(i,String(r))}),"?"+s.toString()}updateBrowserUrl(e,t,s,i){const r=new URL(window.location.origin+window.location.pathname);r.searchParams.set("page",e),Object.entries(t).forEach(([a,o])=>{o!=null&&o!==""&&r.searchParams.set(a,String(o))});const n=r.toString();s?window.history.replaceState(i,"",n):window.history.pushState(i,"",n)}patternToRegex(e){let t=e.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&").replace(/\/:([^/?]+)\?/g,"(?:/([^/]+))?").replace(/:([^/]+)/g,"([^/]+)");return new RegExp(`^${t}$`)}extractParamNames(e){return(e.match(/:([^/?]+)\??/g)||[]).map(s=>s.replace(/[:?]/g,""))}normalizePattern(e){return e.startsWith("/")?e:`/${e}`}updateUrl(e={},t={}){const{replace:s=!1}=t,{pageName:i}=this.parseCurrentUrl();this.updateBrowserUrl(i,e,s)}buildUrl(e,t={}){return this.buildPublicUrl(e,t)}doRoutesMatch(e,t){if(!e||!t)return!1;const{pageName:s}=this.parseInput(e),{pageName:i}=this.parseInput(t);return s===i}}class kt{constructor(){this.listeners={},this.onceListeners={},this.maxListeners=100,this.debugMode=!1,this.eventStats={}}on(e,t){if(typeof t!="function")throw new Error("Callback must be a function");return Array.isArray(e)?(e.forEach(s=>this.on(s,t)),this):(this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].length>=this.maxListeners&&console.warn(`Max listeners (${this.maxListeners}) exceeded for event: ${e}`),this.listeners[e].push(t),this)}once(e,t){if(typeof t!="function")throw new Error("Callback must be a function");return Array.isArray(e)?(e.forEach(s=>this.once(s,t)),this):(this.onceListeners[e]||(this.onceListeners[e]=[]),this.onceListeners[e].push(t),this)}off(e,t){if(Array.isArray(e))return e.forEach(s=>this.off(s,t)),this;if(!t)return delete this.listeners[e],delete this.onceListeners[e],this;if(this.listeners[e]){const s=this.listeners[e].indexOf(t);s!==-1&&(this.listeners[e].splice(s,1),this.listeners[e].length===0&&delete this.listeners[e])}if(this.onceListeners[e]){const s=this.onceListeners[e].indexOf(t);s!==-1&&(this.onceListeners[e].splice(s,1),this.onceListeners[e].length===0&&delete this.onceListeners[e])}return this}emit(e,t){this.updateEventStats(e),this.debugMode&&console.log(`[EventBus] Emitting: ${e}`,t);const s=[];return this.listeners[e]&&s.push(...this.listeners[e]),this.listeners["*"]&&s.push(...this.listeners["*"]),this.onceListeners[e]&&(s.push(...this.onceListeners[e]),delete this.onceListeners[e]),this.onceListeners["*"]&&(s.push(...this.onceListeners["*"]),delete this.onceListeners["*"]),this.debugMode&&s.length>0&&console.log(`[EventBus] ${s.length} listener(s) for '${e}'`),s.forEach(i=>{try{i(t,e)&&(e.stopPropagation&&e.stopPropagation(),e.preventDefault&&e.preventDefault())}catch(r){console.error(`Error in event listener for '${e}':`,r),this.emitError(r,e,i)}}),this}async emitAsync(e,t){const s=[];this.listeners[e]&&s.push(...this.listeners[e]),this.listeners["*"]&&s.push(...this.listeners["*"]),this.onceListeners[e]&&(s.push(...this.onceListeners[e]),delete this.onceListeners[e]),this.onceListeners["*"]&&(s.push(...this.onceListeners["*"]),delete this.onceListeners["*"]);const i=s.map(r=>new Promise(n=>{try{const a=r(t,e);n(a)}catch(a){console.error(`Error in async event listener for '${e}':`,a),this.emitError(a,e,r),n()}}));return await Promise.all(i),this}removeAllListeners(){return this.listeners={},this.onceListeners={},this}listenerCount(e){const t=this.listeners[e]?this.listeners[e].length:0,s=this.onceListeners[e]?this.onceListeners[e].length:0;return t+s}eventNames(){const e=Object.keys(this.listeners),t=Object.keys(this.onceListeners);return[...new Set([...e,...t])]}setMaxListeners(e){if(typeof e!="number"||e<0)throw new Error("Max listeners must be a non-negative number");return this.maxListeners=e,this}namespace(e){const t=s=>`${e}:${s}`;return{on:(s,i)=>this.on(t(s),i),once:(s,i)=>this.once(t(s),i),off:(s,i)=>this.off(t(s),i),emit:(s,i)=>this.emit(t(s),i),emitAsync:(s,i)=>this.emitAsync(t(s),i)}}use(e){if(typeof e!="function")throw new Error("Middleware must be a function");const t=this.emit;return this.emit=(s,i)=>{try{const r=e(s,i);if(r===!1)return this;const n=r!==void 0?r:i;return t.call(this,s,n)}catch(r){return console.error("Error in event middleware:",r),t.call(this,s,i)}},this}emitError(e,t,s){t!=="error"&&setTimeout(()=>{this.emit("error",{error:e,originalEvent:t,callback:s.toString()})},0)}waitFor(e,t=null){return new Promise((s,i)=>{let r=null;const n=()=>{r&&clearTimeout(r)},a=o=>{n(),s(o)};this.once(e,a),t&&(r=setTimeout(()=>{this.off(e,a),i(new Error(`Timeout waiting for event: ${e}`))},t))})}debug(e=!0){return this.debugMode=e,console.log(e?"[EventBus] Debug mode enabled":"[EventBus] Debug mode disabled"),this}getStats(){const e=this.eventNames(),t={totalEvents:e.length,totalListeners:0,events:{},emissions:{...this.eventStats}};return e.forEach(s=>{const i=this.listenerCount(s);t.events[s]=i,t.totalListeners+=i}),t}updateEventStats(e){this.eventStats[e]||(this.eventStats[e]={count:0,firstEmission:Date.now(),lastEmission:null}),this.eventStats[e].count++,this.eventStats[e].lastEmission=Date.now()}getEventStats(e){const t=this.eventStats[e];return t?{...t,listenerCount:this.listenerCount(e),avgEmissionsPerMinute:this.calculateEmissionRate(t)}:null}calculateEmissionRate(e){if(!e.firstEmission||!e.lastEmission)return 0;const t=e.lastEmission-e.firstEmission;if(t===0)return 0;const s=t/(1e3*60);return Math.round(e.count/s*100)/100}resetStats(){return this.eventStats={},this}getTopEvents(e=10){return Object.entries(this.eventStats).map(([t,s])=>({event:t,count:s.count,rate:this.calculateEmissionRate(s),listeners:this.listenerCount(t)})).sort((t,s)=>s.count-t.count).slice(0,e)}debugInfo(){console.group("[EventBus] Debug Information"),console.log("Debug Mode:",this.debugMode),console.log("Max Listeners:",this.maxListeners);const e=this.getStats();return console.log("Total Events:",e.totalEvents),console.log("Total Listeners:",e.totalListeners),Object.keys(this.eventStats).length>0&&console.log("Top Events:",this.getTopEvents(5)),console.groupEnd(),this}}const Xe=["light","dark","system"];class Lt{constructor({storageKey:e,eventBus:t}={}){this.storageKey=e||"mojo:theme",this.eventBus=t||null,this.preference="system",this.resolved="light",this._mediaQuery=null,this._mediaListener=null}init(){const e=this._readStored();return this.preference=Xe.includes(e)?e:"system",this._apply(!1),this.preference==="system"&&this._attachSystemListener(),this}getPreference(){return this.preference}getResolved(){return this.resolved}set(e){if(!Xe.includes(e))return console.warn(`ThemeManager: invalid preference "${e}" — expected 'light' | 'dark' | 'system'`),this;const t=this.preference==="system";return this.preference=e,this._writeStored(e),e==="system"?t||this._attachSystemListener():t&&this._detachSystemListener(),this._apply(!0),this}destroy(){this._detachSystemListener(),this.eventBus=null}_resolve(){return this.preference==="light"||this.preference==="dark"?this.preference:this._systemPrefersDark()?"dark":"light"}_apply(e){const t=this._resolve(),s=t!==this.resolved;this.resolved=t,typeof document<"u"&&document.documentElement&&document.documentElement.setAttribute("data-bs-theme",t),e&&s&&this.eventBus&&typeof this.eventBus.emit=="function"?this.eventBus.emit("theme:changed",{theme:this.preference,resolved:t}):e&&this.eventBus&&typeof this.eventBus.emit=="function"&&this.eventBus.emit("theme:changed",{theme:this.preference,resolved:t})}_systemPrefersDark(){if(typeof window>"u"||typeof window.matchMedia!="function")return!1;try{return window.matchMedia("(prefers-color-scheme: dark)").matches}catch{return!1}}_attachSystemListener(){if(!(this._mediaQuery||typeof window>"u"||typeof window.matchMedia!="function")){try{this._mediaQuery=window.matchMedia("(prefers-color-scheme: dark)")}catch{this._mediaQuery=null;return}this._mediaListener=()=>{this.preference==="system"&&this._apply(!0)},typeof this._mediaQuery.addEventListener=="function"?this._mediaQuery.addEventListener("change",this._mediaListener):typeof this._mediaQuery.addListener=="function"&&this._mediaQuery.addListener(this._mediaListener)}}_detachSystemListener(){if(!this._mediaQuery||!this._mediaListener){this._mediaQuery=null,this._mediaListener=null;return}typeof this._mediaQuery.removeEventListener=="function"?this._mediaQuery.removeEventListener("change",this._mediaListener):typeof this._mediaQuery.removeListener=="function"&&this._mediaQuery.removeListener(this._mediaListener),this._mediaQuery=null,this._mediaListener=null}_readStored(){try{return typeof localStorage>"u"?null:localStorage.getItem(this.storageKey)}catch(e){return console.warn("ThemeManager: failed to read stored theme:",e),null}}_writeStored(e){try{if(typeof localStorage>"u")return;localStorage.setItem(this.storageKey,e)}catch(t){console.warn("ThemeManager: failed to persist theme:",t)}}}class Vt{constructor(){this.config={baseURL:"",timeout:3e4,headers:{"Content-Type":"application/json",Accept:"application/json"},trackDevice:!0,duidHeader:"X-Mojo-UID",duidTransport:"header"},this.interceptors={request:[],response:[]},this.duid=null,this.config.trackDevice&&this._initializeDuid()}_initializeDuid(){const e="mojo_device_uid";try{let t=localStorage.getItem(e);t?this.duid=t:(this.duid=this._generateDuid(),localStorage.setItem(e,this.duid))}catch(t){console.error("Could not access localStorage to get/set DUID.",t),this.duid=this._generateDuid()}}_generateDuid(){return crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){const t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}configure(e){e.baseUrl&&(e.baseURL=e.baseUrl);const t=this.config.trackDevice;this.config={...this.config,...e,headers:{...this.config.headers,...e.headers}},this.config.trackDevice&&!t&&this._initializeDuid()}addInterceptor(e,t){this.interceptors[e]&&this.interceptors[e].push(t)}buildUrl(e){if(e.startsWith("http://")||e.startsWith("https://"))return e;const t=this.config.baseURL.endsWith("/")?this.config.baseURL.slice(0,-1):this.config.baseURL,s=e.startsWith("/")?e:`/${e}`;return`${t}${s}`}categorizeError(e,t=0){if(e.name==="TypeError"&&e.message.includes("fetch"))return{reason:"not_reachable",message:"Service is not reachable - please check your connection"};if(e.name==="AbortError")return{reason:"cancelled",message:"Request was cancelled"};if(e.name==="TimeoutError"||e.message.includes("timeout"))return{reason:"timed_out",message:"Request timed out - please try again"};if(t>=400){if(t===400)return{reason:"bad_request",message:"Invalid request data"};if(t===401)return{reason:"unauthorized",message:"Authentication required"};if(t===403)return{reason:"forbidden",message:"Access denied"};if(t===404)return{reason:"not_found",message:"Resource not found"};if(t===409)return{reason:"conflict",message:"Resource conflict"};if(t===422)return{reason:"validation_error",message:"Validation failed"};if(t===429)return{reason:"rate_limited",message:"Too many requests - please wait"};if(t>=500)return{reason:"server_error",message:"Server error - please try again later"};if(t>=400)return{reason:"client_error",message:"Request error"}}return e.message.includes("CORS")?{reason:"cors_error",message:"Cross-origin request blocked"}:e.message.includes("DNS")||e.message.includes("ENOTFOUND")?{reason:"dns_error",message:"Unable to resolve server address"}:{reason:"unknown_error",message:`Network error: ${e.message}`}}buildQueryString(e={}){const t=new URLSearchParams;Object.entries(e).forEach(([i,r])=>{r!=null&&(Array.isArray(r)?r.forEach(n=>t.append(`${i}[]`,n)):t.append(i,r))});const s=t.toString();return s?`?${s}`:""}async processRequestInterceptors(e){let t={...e};for(const s of this.interceptors.request)try{t=await s(t)}catch(i){throw console.error("Request interceptor error:",i),i}return t}async processResponseInterceptors(e,t){let s={success:e.ok,status:e.status,statusText:e.statusText,headers:Object.fromEntries(e.headers.entries()),data:null,errors:null,message:null,reason:null};try{const i=e.headers.get("content-type");if(i&&i.includes("application/json")){const r=await e.json();if(s.data=r,!e.ok){const n=this.categorizeError(new Error("HTTP Error"),e.status);s.errors=r.errors||{},s.message=r.message||n.message,s.reason=n.reason}}else if(s.data=await e.text(),!e.ok){const r=this.categorizeError(new Error("HTTP Error"),e.status);s.message=r.message,s.reason=r.reason}}catch{s.errors={parse:"Failed to parse response"},s.message="Invalid response format"}for(const i of this.interceptors.response)try{s=await i(s,t)}catch(r){console.error("Response interceptor error:",r)}return s}async request(e,t,s=null,i={},r={}){let n={method:e.toUpperCase(),url:this.buildUrl(t)+this.buildQueryString(i),headers:{...this.config.headers,...r.headers},data:s,options:{timeout:this.config.timeout,...r}};try{n=await this.processRequestInterceptors(n)}catch(l){if(l.name==="AuthRequiredError")return{success:!1,status:401,statusText:"Unauthorized",headers:{},data:null,errors:{auth:l.message},message:"Authentication required",reason:"unauthorized"};throw l}if(this.config.trackDevice&&this.duid)if(this.config.duidTransport==="header")n.headers[this.config.duidHeader]=this.duid;else if(n.method==="GET"){const l=new URL(n.url);l.searchParams.append("duid",this.duid),n.url=l.toString()}else n.data&&typeof n.data=="object"&&!(n.data instanceof FormData)&&(n.data.duid=this.duid);const a={method:n.method,headers:n.headers},o=[];n.options.timeout&&o.push(AbortSignal.timeout(n.options.timeout)),n.options.signal&&o.push(n.options.signal),o.length>1?a.signal=AbortSignal.any?AbortSignal.any(o):o[0]:o.length===1&&(a.signal=o[0]),n.data&&["POST","PUT","PATCH"].includes(n.method)&&(n.data instanceof FormData?(a.body=n.data,delete a.headers["Content-Type"]):typeof n.data=="object"?a.body=JSON.stringify(n.data):a.body=n.data);try{const l=await fetch(n.url,a),d=await this.processResponseInterceptors(l,n);return r.dataOnly&&d.data&&typeof d.data=="object"&&"data"in d.data&&(d.message=d.message||d.data.message,d.data=d.data.data),d}catch(l){if(l.name==="AbortError")throw l;const d=this.categorizeError(l),h={success:!1,status:0,statusText:"Network Error",headers:{},data:null,errors:{network:l.message},message:d.message,reason:d.reason},u={ok:!1,status:0,statusText:"Network Error",headers:new Headers,json:async()=>({}),text:async()=>""};return await this.processResponseInterceptors(u,n),h}}async GET(e,t={},s={}){return this.request("GET",e,null,t,s)}async POST(e,t={},s={},i={}){return this.request("POST",e,t,s,i)}async PUT(e,t={},s={},i={}){return this.request("PUT",e,t,s,i)}async PATCH(e,t={},s={},i={}){return this.request("PATCH",e,t,s,i)}async DELETE(e,t={},s={}){return this.request("DELETE",e,null,t,s)}get(...e){return this.GET(...e)}post(...e){return this.POST(...e)}put(...e){return this.PUT(...e)}patch(...e){return this.PATCH(...e)}delete(...e){return this.DELETE(...e)}async download(e,t={},s={}){const r={method:"GET",url:this.buildUrl(e)+this.buildQueryString(t),headers:{...this.config.headers,Accept:"*/*",...s.headers},options:{...s}};delete r.headers["Content-Type"];try{const n=await fetch(r.url,{method:r.method,headers:r.headers,signal:r.options.signal});if(!n.ok)throw new Error(`Download failed: ${n.status} ${n.statusText}`);const a=n.headers.get("content-disposition");let o=s.filename||"download";if(a){const p=a.match(/filename="?(.+)"?/);p&&p.length>1&&(o=p[1])}const l=n.body.getReader(),d=new ReadableStream({start(p){function f(){return l.read().then(({done:g,value:b})=>{if(g){p.close();return}return p.enqueue(b),f()})}return f()}}),h=await new Response(d).blob(),u=window.URL.createObjectURL(h),m=document.createElement("a");return m.style.display="none",m.href=u,m.download=o,document.body.appendChild(m),m.click(),window.URL.revokeObjectURL(u),m.remove(),{success:!0,message:"Download initiated"}}catch(n){return console.error("Download error:",n),{success:!1,message:n.message}}}async downloadBlob(e,t={},s={}){const r={method:"GET",url:this.buildUrl(e)+this.buildQueryString(t),headers:{...this.config.headers,Accept:"*/*",...s.headers},options:{...s}};delete r.headers["Content-Type"];try{const n=await fetch(r.url,{method:r.method,headers:r.headers,signal:r.options.signal});if(!n.ok)throw new Error(`Download failed: ${n.status} ${n.statusText}`);const a=await n.blob(),o=n.headers.get("content-disposition");let l=s.filename||"download";if(o){const u=o.match(/filename="?(.+)"?/);u&&u.length>1&&(l=u[1])}const d=window.URL.createObjectURL(a),h=document.createElement("a");return h.style.display="none",h.href=d,h.download=l,document.body.appendChild(h),h.click(),window.URL.revokeObjectURL(d),h.remove(),{success:!0,message:"Download initiated"}}catch(n){return console.error("Download error:",n),{success:!1,message:n.message}}}async upload(e,t,s={}){return new Promise((i,r)=>{if(!(t instanceof File)){r(new Error("Only single File objects are supported for legacy backend compatibility"));return}const n=new XMLHttpRequest;s.onProgress&&typeof s.onProgress=="function"&&(n.upload.onprogress=s.onProgress),n.onload=function(){n.status>=200&&n.status<300?i({data:n.response,status:n.status,statusText:n.statusText,xhr:n}):r(new Error(`Upload failed: ${n.status} ${n.statusText}`))},n.onerror=function(){r(new Error("Upload failed: Network error"))},n.ontimeout=function(){r(new Error("Upload failed: Timeout"))},n.open("PUT",e),n.setRequestHeader("Content-Type",t.type),s.timeout&&(n.timeout=s.timeout),n.send(t)})}async uploadMultipart(e,t,s={},i={}){const r=new FormData;if(t instanceof FileList)Array.from(t).forEach((n,a)=>{r.append(`file_${a}`,n)});else if(t instanceof File)r.append("file",t);else if(t instanceof FormData)return this.POST(e,t,{},i);return Object.entries(s).forEach(([n,a])=>{r.append(n,a)}),this.POST(e,r,{},i)}setAuthToken(e,t="Bearer"){e?this.config.headers.Authorization=`${t} ${e}`:delete this.config.headers.Authorization}clearAuth(){delete this.config.headers.Authorization}isRetryableError(e){return["not_reachable","timed_out","server_error","dns_error"].includes(e.reason)}requiresAuth(e){return e.reason==="unauthorized"}isNetworkError(e){return["not_reachable","timed_out","cancelled","cors_error","dns_error"].includes(e.reason)}getUserMessage(e){return e.message?e.message:{not_reachable:"Unable to connect to the server. Please check your internet connection.",timed_out:"The request took too long. Please try again.",cancelled:"The request was cancelled.",unauthorized:"Please log in to continue.",forbidden:"You don't have permission to perform this action.",not_found:"The requested resource was not found.",validation_error:"Please check your input and try again.",rate_limited:"Too many requests. Please wait a moment before trying again.",server_error:"Server error. Please try again later.",cors_error:"Access blocked by security policy.",dns_error:"Unable to reach the server.",unknown_error:"An unexpected error occurred."}[e.reason]||"An error occurred. Please try again."}}const ie=new Vt,Pt="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI2NlZDRkYSI+PHBhdGggZD0iTTEyIDEyYzIuMjEgMCA0LTEuNzkgNC00cy0xLjc5LTQtNC00LTQgMS43OS00IDQgMS43OSA0IDQgNHptMCAyYy0yLjY3IDAtOCAxLjM0LTggNHYyaDE2di0yYzAtMi42Ni01LjMzLTQtOC00eiIvPjwvc3ZnPg==";class Nt{constructor(){this.formatters=new Map,this.registerBuiltInFormatters()}escapeHtml(e){if(e==null)return"";const t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;"};return String(e).replace(/[&<>"']/g,s=>t[s])}registerBuiltInFormatters(){this.register("date",this.date.bind(this)),this.register("time",this.time.bind(this)),this.register("datetime",this.datetime.bind(this)),this.register("datetime_tz",this.datetime_tz.bind(this)),this.register("datatime_tz",this.datetime_tz.bind(this)),this.register("date_range",this.date_range.bind(this)),this.register("datetime_range",this.datetime_range.bind(this)),this.register("relative",this.relative.bind(this)),this.register("fromNow",this.relative.bind(this)),this.register("timeago",this.relative.bind(this)),this.register("relative_short",this.relative_short.bind(this)),this.register("iso",this.iso.bind(this)),this.register("epoch",e=>{if(e==null||e==="")return e;const t=parseFloat(e);return isNaN(t)?e:t*1e3}),this.register("number",this.number.bind(this)),this.register("currency",this.currency.bind(this)),this.register("percent",this.percent.bind(this)),this.register("filesize",this.filesize.bind(this)),this.register("ordinal",this.ordinal.bind(this)),this.register("compact",this.compact.bind(this)),this.register("add",this.add.bind(this)),this.register("subtract",this.subtract.bind(this)),this.register("multiply",this.multiply.bind(this)),this.register("divide",this.divide.bind(this)),this.register("sub",this.subtract.bind(this)),this.register("mult",this.multiply.bind(this)),this.register("div",this.divide.bind(this)),this.register("uppercase",e=>String(e).toUpperCase()),this.register("lowercase",e=>String(e).toLowerCase()),this.register("upper",e=>String(e).toUpperCase()),this.register("lower",e=>String(e).toLowerCase()),this.register("capitalize",this.capitalize.bind(this)),this.register("caps",this.capitalize.bind(this)),this.register("replace",this.replace.bind(this)),this.register("truncate",this.truncate.bind(this)),this.register("truncate_middle",this.truncate_middle.bind(this)),this.register("truncate_front",this.truncate_front.bind(this)),this.register("slug",this.slug.bind(this)),this.register("initials",this.initials.bind(this)),this.register("mask",this.mask.bind(this)),this.register("hex",this.hex.bind(this)),this.register("tohex",this.hex.bind(this)),this.register("unhex",this.unhex.bind(this)),this.register("fromhex",this.unhex.bind(this)),this.register("email",this.email.bind(this)),this.register("phone",this.phone.bind(this)),this.register("url",this.url.bind(this)),this.register("badge",this.badge.bind(this)),this.register("badgeClass",this.badgeClass.bind(this)),this.register("status",this.status.bind(this)),this.register("status_text",this.status_text.bind(this)),this.register("status_icon",this.status_icon.bind(this)),this.register("boolean",this.boolean.bind(this)),this.register("bool",this.bool.bind(this)),this.register("yesno",e=>this.boolean(e,"Yes","No")),this.register("yesnoicon",this.yesnoicon.bind(this)),this.register("icon",this.icon.bind(this)),this.register("avatar",this.avatar.bind(this)),this.register("image",this.image.bind(this)),this.register("tooltip",this.tooltip.bind(this)),this.register("linkify",this.linkify.bind(this)),this.register("clipboard",this.clipboard.bind(this)),this.register("default",this.default.bind(this)),this.register("equals",this.equals.bind(this)),this.register("json",this.json.bind(this)),this.register("raw",e=>e),this.register("custom",(e,t)=>typeof t=="function"?t(e):e),this.register("iter",this.iter.bind(this)),this.register("keys",e=>e&&typeof e=="object"&&!Array.isArray(e)?Object.keys(e):null),this.register("values",e=>e&&typeof e=="object"&&!Array.isArray(e)?Object.values(e):null),this.register("plural",this.plural.bind(this)),this.register("list",this.formatList.bind(this)),this.register("duration",this.duration.bind(this)),this.register("hash",this.hash.bind(this)),this.register("stripHtml",this.stripHtml.bind(this)),this.register("highlight",this.highlight.bind(this)),this.register("nl2br",this.nl2br.bind(this)),this.register("code",this.code.bind(this)),this.register("pre",e=>`<pre class="bg-light p-2 rounded border">${this.escapeHtml(String(e))}</pre>`)}relative_short(e){return this.relative(e,!0)}linkify(e,t={}){if(e==null)return"";const s=String(e),i=this.escapeHtml(s),r={urls:!0,emails:!0,target:"_blank",rel:"noopener noreferrer"},n=t&&typeof t=="object"?{...r,...t}:r;let a=i;if(n.urls!==!1){const o=/(^|\s)((?:https?:\/\/|www\.)[^\s<]+)/gi;a=a.replace(o,(l,d,h)=>{const u=h.startsWith("www.")?`https://${h}`:h;return`${d}<a href="${u}" target="${n.target}" rel="${n.rel}">${h}</a>`})}if(n.emails!==!1){const o=/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;a=a.replace(o,l=>`<a href="mailto:${l}">${l}</a>`)}return a}clipboard(e,t="text"){if(e==null)return"";const s=String(e),i=this.escapeHtml(s),r=t!=="icon-only",n=`
1
+ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=e.defaultRoute||"home",this.routes=[],this.currentRoute=null,this.eventEmitter=e.eventEmitter||null,this.boundHandlePopState=this.handlePopState.bind(this)}start(){window.addEventListener("popstate",this.boundHandlePopState),this.handleCurrentLocation()}stop(){window.removeEventListener("popstate",this.boundHandlePopState)}addRoute(e,t){this.routes.push({pattern:this.normalizePattern(e),regex:this.patternToRegex(e),pageName:t,paramNames:this.extractParamNames(e)})}async navigate(e,t={}){const{replace:s=!1,state:i=null,trigger:r=!0}=t,{pageName:n,queryParams:a}=this.parseInput(e);r&&await this.handleRouteChange(n,a)}back(){window.history.back()}forward(){window.history.forward()}getCurrentRoute(){return this.currentRoute}getCurrentPath(){const{pageName:e,queryParams:t}=this.parseCurrentUrl();return this.buildPublicUrl(e,t)}handlePopState(e){this.allowPopState?this.handleCurrentLocation():console.warn("PopStateEvent is not allowed")}async handleCurrentLocation(){const{pageName:e,queryParams:t}=this.parseCurrentUrl();await this.handleRouteChange(e,t)}async handleRouteChange(e,t){const s="/"+e,i=this.matchRoute(s),r=this.buildPublicUrl(e,t);return i?(this.currentRoute=i,this.eventEmitter&&this.eventEmitter.emit("route:changed",{path:r,pageName:i.pageName,params:i.params,query:t,route:i}),i):(console.log("No route matched for page:",e),this.eventEmitter&&this.eventEmitter.emit("route:notfound",{path:r}),null)}matchRoute(e){for(const t of this.routes){const s=e.match(t.regex);if(s){const i={};return t.paramNames.forEach((r,n)=>{i[r]=s[n+1]}),{...t,params:i,path:e}}}return null}parseInput(e){let t=this.defaultRoute,s={};if(!e)return{pageName:t,queryParams:s};try{if(e.includes("?")){const[i,r]=e.split("?",2),n=new URLSearchParams(r);if(n.has("page")){t=n.get("page")||this.defaultRoute;for(const[a,o]of n)a!=="page"&&(s[a]=o)}else{i.startsWith("/")?t=i.substring(1)||this.defaultRoute:t=i||this.defaultRoute;for(const[a,o]of n)s[a]=o}}else e.startsWith("/")?t=e.substring(1)||this.defaultRoute:t=e}catch(i){console.warn("Failed to parse input:",e,i),t=this.defaultRoute,s={}}return{pageName:t,queryParams:s}}parseCurrentUrl(){const e=new URLSearchParams(window.location.search),t=e.get("page")||this.defaultRoute,s={};for(const[i,r]of e)i!=="page"&&(s[i]=r);return{pageName:t,queryParams:s}}buildPublicUrl(e,t={}){const s=new URLSearchParams;return s.set("page",e),Object.entries(t).forEach(([i,r])=>{r!=null&&r!==""&&s.set(i,String(r))}),"?"+s.toString()}updateBrowserUrl(e,t,s,i){const r=new URL(window.location.origin+window.location.pathname);r.searchParams.set("page",e),Object.entries(t).forEach(([a,o])=>{o!=null&&o!==""&&r.searchParams.set(a,String(o))});const n=r.toString();s?window.history.replaceState(i,"",n):window.history.pushState(i,"",n)}patternToRegex(e){let t=e.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&").replace(/\/:([^/?]+)\?/g,"(?:/([^/]+))?").replace(/:([^/]+)/g,"([^/]+)");return new RegExp(`^${t}$`)}extractParamNames(e){return(e.match(/:([^/?]+)\??/g)||[]).map(s=>s.replace(/[:?]/g,""))}normalizePattern(e){return e.startsWith("/")?e:`/${e}`}updateUrl(e={},t={}){const{replace:s=!1}=t,{pageName:i}=this.parseCurrentUrl();this.updateBrowserUrl(i,e,s)}buildUrl(e,t={}){return this.buildPublicUrl(e,t)}doRoutesMatch(e,t){if(!e||!t)return!1;const{pageName:s}=this.parseInput(e),{pageName:i}=this.parseInput(t);return s===i}}class kt{constructor(){this.listeners={},this.onceListeners={},this.maxListeners=100,this.debugMode=!1,this.eventStats={}}on(e,t){if(typeof t!="function")throw new Error("Callback must be a function");return Array.isArray(e)?(e.forEach(s=>this.on(s,t)),this):(this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].length>=this.maxListeners&&console.warn(`Max listeners (${this.maxListeners}) exceeded for event: ${e}`),this.listeners[e].push(t),this)}once(e,t){if(typeof t!="function")throw new Error("Callback must be a function");return Array.isArray(e)?(e.forEach(s=>this.once(s,t)),this):(this.onceListeners[e]||(this.onceListeners[e]=[]),this.onceListeners[e].push(t),this)}off(e,t){if(Array.isArray(e))return e.forEach(s=>this.off(s,t)),this;if(!t)return delete this.listeners[e],delete this.onceListeners[e],this;if(this.listeners[e]){const s=this.listeners[e].indexOf(t);s!==-1&&(this.listeners[e].splice(s,1),this.listeners[e].length===0&&delete this.listeners[e])}if(this.onceListeners[e]){const s=this.onceListeners[e].indexOf(t);s!==-1&&(this.onceListeners[e].splice(s,1),this.onceListeners[e].length===0&&delete this.onceListeners[e])}return this}emit(e,t){this.updateEventStats(e),this.debugMode&&console.log(`[EventBus] Emitting: ${e}`,t);const s=[];return this.listeners[e]&&s.push(...this.listeners[e]),this.listeners["*"]&&s.push(...this.listeners["*"]),this.onceListeners[e]&&(s.push(...this.onceListeners[e]),delete this.onceListeners[e]),this.onceListeners["*"]&&(s.push(...this.onceListeners["*"]),delete this.onceListeners["*"]),this.debugMode&&s.length>0&&console.log(`[EventBus] ${s.length} listener(s) for '${e}'`),s.forEach(i=>{try{i(t,e)&&(e.stopPropagation&&e.stopPropagation(),e.preventDefault&&e.preventDefault())}catch(r){console.error(`Error in event listener for '${e}':`,r),this.emitError(r,e,i)}}),this}async emitAsync(e,t){const s=[];this.listeners[e]&&s.push(...this.listeners[e]),this.listeners["*"]&&s.push(...this.listeners["*"]),this.onceListeners[e]&&(s.push(...this.onceListeners[e]),delete this.onceListeners[e]),this.onceListeners["*"]&&(s.push(...this.onceListeners["*"]),delete this.onceListeners["*"]);const i=s.map(r=>new Promise(n=>{try{const a=r(t,e);n(a)}catch(a){console.error(`Error in async event listener for '${e}':`,a),this.emitError(a,e,r),n()}}));return await Promise.all(i),this}removeAllListeners(){return this.listeners={},this.onceListeners={},this}listenerCount(e){const t=this.listeners[e]?this.listeners[e].length:0,s=this.onceListeners[e]?this.onceListeners[e].length:0;return t+s}eventNames(){const e=Object.keys(this.listeners),t=Object.keys(this.onceListeners);return[...new Set([...e,...t])]}setMaxListeners(e){if(typeof e!="number"||e<0)throw new Error("Max listeners must be a non-negative number");return this.maxListeners=e,this}namespace(e){const t=s=>`${e}:${s}`;return{on:(s,i)=>this.on(t(s),i),once:(s,i)=>this.once(t(s),i),off:(s,i)=>this.off(t(s),i),emit:(s,i)=>this.emit(t(s),i),emitAsync:(s,i)=>this.emitAsync(t(s),i)}}use(e){if(typeof e!="function")throw new Error("Middleware must be a function");const t=this.emit;return this.emit=(s,i)=>{try{const r=e(s,i);if(r===!1)return this;const n=r!==void 0?r:i;return t.call(this,s,n)}catch(r){return console.error("Error in event middleware:",r),t.call(this,s,i)}},this}emitError(e,t,s){t!=="error"&&setTimeout(()=>{this.emit("error",{error:e,originalEvent:t,callback:s.toString()})},0)}waitFor(e,t=null){return new Promise((s,i)=>{let r=null;const n=()=>{r&&clearTimeout(r)},a=o=>{n(),s(o)};this.once(e,a),t&&(r=setTimeout(()=>{this.off(e,a),i(new Error(`Timeout waiting for event: ${e}`))},t))})}debug(e=!0){return this.debugMode=e,console.log(e?"[EventBus] Debug mode enabled":"[EventBus] Debug mode disabled"),this}getStats(){const e=this.eventNames(),t={totalEvents:e.length,totalListeners:0,events:{},emissions:{...this.eventStats}};return e.forEach(s=>{const i=this.listenerCount(s);t.events[s]=i,t.totalListeners+=i}),t}updateEventStats(e){this.eventStats[e]||(this.eventStats[e]={count:0,firstEmission:Date.now(),lastEmission:null}),this.eventStats[e].count++,this.eventStats[e].lastEmission=Date.now()}getEventStats(e){const t=this.eventStats[e];return t?{...t,listenerCount:this.listenerCount(e),avgEmissionsPerMinute:this.calculateEmissionRate(t)}:null}calculateEmissionRate(e){if(!e.firstEmission||!e.lastEmission)return 0;const t=e.lastEmission-e.firstEmission;if(t===0)return 0;const s=t/(1e3*60);return Math.round(e.count/s*100)/100}resetStats(){return this.eventStats={},this}getTopEvents(e=10){return Object.entries(this.eventStats).map(([t,s])=>({event:t,count:s.count,rate:this.calculateEmissionRate(s),listeners:this.listenerCount(t)})).sort((t,s)=>s.count-t.count).slice(0,e)}debugInfo(){console.group("[EventBus] Debug Information"),console.log("Debug Mode:",this.debugMode),console.log("Max Listeners:",this.maxListeners);const e=this.getStats();return console.log("Total Events:",e.totalEvents),console.log("Total Listeners:",e.totalListeners),Object.keys(this.eventStats).length>0&&console.log("Top Events:",this.getTopEvents(5)),console.groupEnd(),this}}const Xe=["light","dark","system"];class Lt{constructor({storageKey:e,eventBus:t}={}){this.storageKey=e||"mojo:theme",this.eventBus=t||null,this.preference="system",this.resolved="light",this._mediaQuery=null,this._mediaListener=null}init(){const e=this._readStored();return this.preference=Xe.includes(e)?e:"system",this._apply(!1),this.preference==="system"&&this._attachSystemListener(),this}getPreference(){return this.preference}getResolved(){return this.resolved}set(e){if(!Xe.includes(e))return console.warn(`ThemeManager: invalid preference "${e}" — expected 'light' | 'dark' | 'system'`),this;const t=this.preference==="system";return this.preference=e,this._writeStored(e),e==="system"?t||this._attachSystemListener():t&&this._detachSystemListener(),this._apply(!0),this}destroy(){this._detachSystemListener(),this.eventBus=null}_resolve(){return this.preference==="light"||this.preference==="dark"?this.preference:this._systemPrefersDark()?"dark":"light"}_apply(e){const t=this._resolve(),s=t!==this.resolved;this.resolved=t,typeof document<"u"&&document.documentElement&&document.documentElement.setAttribute("data-bs-theme",t),e&&s&&this.eventBus&&typeof this.eventBus.emit=="function"?this.eventBus.emit("theme:changed",{theme:this.preference,resolved:t}):e&&this.eventBus&&typeof this.eventBus.emit=="function"&&this.eventBus.emit("theme:changed",{theme:this.preference,resolved:t})}_systemPrefersDark(){if(typeof window>"u"||typeof window.matchMedia!="function")return!1;try{return window.matchMedia("(prefers-color-scheme: dark)").matches}catch{return!1}}_attachSystemListener(){if(!(this._mediaQuery||typeof window>"u"||typeof window.matchMedia!="function")){try{this._mediaQuery=window.matchMedia("(prefers-color-scheme: dark)")}catch{this._mediaQuery=null;return}this._mediaListener=()=>{this.preference==="system"&&this._apply(!0)},typeof this._mediaQuery.addEventListener=="function"?this._mediaQuery.addEventListener("change",this._mediaListener):typeof this._mediaQuery.addListener=="function"&&this._mediaQuery.addListener(this._mediaListener)}}_detachSystemListener(){if(!this._mediaQuery||!this._mediaListener){this._mediaQuery=null,this._mediaListener=null;return}typeof this._mediaQuery.removeEventListener=="function"?this._mediaQuery.removeEventListener("change",this._mediaListener):typeof this._mediaQuery.removeListener=="function"&&this._mediaQuery.removeListener(this._mediaListener),this._mediaQuery=null,this._mediaListener=null}_readStored(){try{return typeof localStorage>"u"?null:localStorage.getItem(this.storageKey)}catch(e){return console.warn("ThemeManager: failed to read stored theme:",e),null}}_writeStored(e){try{if(typeof localStorage>"u")return;localStorage.setItem(this.storageKey,e)}catch(t){console.warn("ThemeManager: failed to persist theme:",t)}}}class Vt{constructor(){this.config={baseURL:"",timeout:3e4,headers:{"Content-Type":"application/json",Accept:"application/json"},trackDevice:!0,duidHeader:"X-Mojo-UID",duidTransport:"header"},this.interceptors={request:[],response:[]},this.duid=null,this.config.trackDevice&&this._initializeDuid()}_initializeDuid(){const e="mojo_device_uid";try{let t=localStorage.getItem(e);t?this.duid=t:(this.duid=this._generateDuid(),localStorage.setItem(e,this.duid))}catch(t){console.error("Could not access localStorage to get/set DUID.",t),this.duid=this._generateDuid()}}_generateDuid(){return crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){const t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}configure(e){e.baseUrl&&(e.baseURL=e.baseUrl);const t=this.config.trackDevice;this.config={...this.config,...e,headers:{...this.config.headers,...e.headers}},this.config.trackDevice&&!t&&this._initializeDuid()}addInterceptor(e,t){this.interceptors[e]&&this.interceptors[e].push(t)}buildUrl(e){if(e.startsWith("http://")||e.startsWith("https://"))return e;const t=this.config.baseURL.endsWith("/")?this.config.baseURL.slice(0,-1):this.config.baseURL,s=e.startsWith("/")?e:`/${e}`;return`${t}${s}`}categorizeError(e,t=0){if(e.name==="TypeError"&&e.message.includes("fetch"))return{reason:"not_reachable",message:"Service is not reachable - please check your connection"};if(e.name==="AbortError")return{reason:"cancelled",message:"Request was cancelled"};if(e.name==="TimeoutError"||e.message.includes("timeout"))return{reason:"timed_out",message:"Request timed out - please try again"};if(t>=400){if(t===400)return{reason:"bad_request",message:"Invalid request data"};if(t===401)return{reason:"unauthorized",message:"Authentication required"};if(t===403)return{reason:"forbidden",message:"Access denied"};if(t===404)return{reason:"not_found",message:"Resource not found"};if(t===409)return{reason:"conflict",message:"Resource conflict"};if(t===422)return{reason:"validation_error",message:"Validation failed"};if(t===429)return{reason:"rate_limited",message:"Too many requests - please wait"};if(t>=500)return{reason:"server_error",message:"Server error - please try again later"};if(t>=400)return{reason:"client_error",message:"Request error"}}return e.message.includes("CORS")?{reason:"cors_error",message:"Cross-origin request blocked"}:e.message.includes("DNS")||e.message.includes("ENOTFOUND")?{reason:"dns_error",message:"Unable to resolve server address"}:{reason:"unknown_error",message:`Network error: ${e.message}`}}buildQueryString(e={}){const t=new URLSearchParams;Object.entries(e).forEach(([i,r])=>{r!=null&&(Array.isArray(r)?r.forEach(n=>t.append(`${i}[]`,n)):t.append(i,r))});const s=t.toString();return s?`?${s}`:""}async processRequestInterceptors(e){let t={...e};for(const s of this.interceptors.request)try{t=await s(t)}catch(i){throw console.error("Request interceptor error:",i),i}return t}async processResponseInterceptors(e,t){let s={success:e.ok,status:e.status,statusText:e.statusText,headers:Object.fromEntries(e.headers.entries()),data:null,errors:null,message:null,reason:null};try{const i=e.headers.get("content-type");if(i&&i.includes("application/json")){const r=await e.json();if(s.data=r,!e.ok){const n=this.categorizeError(new Error("HTTP Error"),e.status);s.errors=r.errors||{},s.message=r.message||n.message,s.reason=n.reason}}else if(s.data=await e.text(),!e.ok){const r=this.categorizeError(new Error("HTTP Error"),e.status);s.message=r.message,s.reason=r.reason}}catch{s.errors={parse:"Failed to parse response"},s.message="Invalid response format"}for(const i of this.interceptors.response)try{s=await i(s,t)}catch(r){console.error("Response interceptor error:",r)}return s}async request(e,t,s=null,i={},r={}){let n={method:e.toUpperCase(),url:this.buildUrl(t)+this.buildQueryString(i),headers:{...this.config.headers,...r.headers},data:s,options:{timeout:this.config.timeout,...r}};try{n=await this.processRequestInterceptors(n)}catch(l){if(l.name==="AuthRequiredError")return{success:!1,status:401,statusText:"Unauthorized",headers:{},data:null,errors:{auth:l.message},message:"Authentication required",reason:"unauthorized"};throw l}if(this.config.trackDevice&&this.duid)if(this.config.duidTransport==="header")n.headers[this.config.duidHeader]=this.duid;else if(n.method==="GET"){const l=new URL(n.url);l.searchParams.append("duid",this.duid),n.url=l.toString()}else n.data&&typeof n.data=="object"&&!(n.data instanceof FormData)&&(n.data.duid=this.duid);const a={method:n.method,headers:n.headers},o=[];n.options.timeout&&o.push(AbortSignal.timeout(n.options.timeout)),n.options.signal&&o.push(n.options.signal),o.length>1?a.signal=AbortSignal.any?AbortSignal.any(o):o[0]:o.length===1&&(a.signal=o[0]),n.data&&["POST","PUT","PATCH"].includes(n.method)&&(n.data instanceof FormData?(a.body=n.data,delete a.headers["Content-Type"]):typeof n.data=="object"?a.body=JSON.stringify(n.data):a.body=n.data);try{const l=await fetch(n.url,a),d=await this.processResponseInterceptors(l,n);return r.dataOnly&&d.data&&typeof d.data=="object"&&"data"in d.data&&(d.message=d.message||d.data.message,d.data=d.data.data),d}catch(l){if(l.name==="AbortError")throw l;const d=this.categorizeError(l),h={success:!1,status:0,statusText:"Network Error",headers:{},data:null,errors:{network:l.message},message:d.message,reason:d.reason},u={ok:!1,status:0,statusText:"Network Error",headers:new Headers,json:async()=>({}),text:async()=>""};return await this.processResponseInterceptors(u,n),h}}async GET(e,t={},s={}){return this.request("GET",e,null,t,s)}async POST(e,t={},s={},i={}){return this.request("POST",e,t,s,i)}async PUT(e,t={},s={},i={}){return this.request("PUT",e,t,s,i)}async PATCH(e,t={},s={},i={}){return this.request("PATCH",e,t,s,i)}async DELETE(e,t={},s={}){return this.request("DELETE",e,null,t,s)}get(...e){return this.GET(...e)}post(...e){return this.POST(...e)}put(...e){return this.PUT(...e)}patch(...e){return this.PATCH(...e)}delete(...e){return this.DELETE(...e)}async download(e,t={},s={}){const r={method:"GET",url:this.buildUrl(e)+this.buildQueryString(t),headers:{...this.config.headers,Accept:"*/*",...s.headers},options:{...s}};delete r.headers["Content-Type"];try{const n=await fetch(r.url,{method:r.method,headers:r.headers,signal:r.options.signal});if(!n.ok)throw new Error(`Download failed: ${n.status} ${n.statusText}`);const a=n.headers.get("content-disposition");let o=s.filename||"download";if(a){const p=a.match(/filename="?(.+)"?/);p&&p.length>1&&(o=p[1])}const l=n.body.getReader(),d=new ReadableStream({start(p){function f(){return l.read().then(({done:g,value:b})=>{if(g){p.close();return}return p.enqueue(b),f()})}return f()}}),h=await new Response(d).blob(),u=window.URL.createObjectURL(h),m=document.createElement("a");return m.style.display="none",m.href=u,m.download=o,document.body.appendChild(m),m.click(),window.URL.revokeObjectURL(u),m.remove(),{success:!0,message:"Download initiated"}}catch(n){return console.error("Download error:",n),{success:!1,message:n.message}}}async downloadBlob(e,t={},s={}){const r={method:"GET",url:this.buildUrl(e)+this.buildQueryString(t),headers:{...this.config.headers,Accept:"*/*",...s.headers},options:{...s}};delete r.headers["Content-Type"];try{const n=await fetch(r.url,{method:r.method,headers:r.headers,signal:r.options.signal});if(!n.ok)throw new Error(`Download failed: ${n.status} ${n.statusText}`);const a=await n.blob(),o=n.headers.get("content-disposition");let l=s.filename||"download";if(o){const u=o.match(/filename="?(.+)"?/);u&&u.length>1&&(l=u[1])}const d=window.URL.createObjectURL(a),h=document.createElement("a");return h.style.display="none",h.href=d,h.download=l,document.body.appendChild(h),h.click(),window.URL.revokeObjectURL(d),h.remove(),{success:!0,message:"Download initiated"}}catch(n){return console.error("Download error:",n),{success:!1,message:n.message}}}async upload(e,t,s={}){return new Promise((i,r)=>{if(!(t instanceof File)){r(new Error("Only single File objects are supported for legacy backend compatibility"));return}const n=new XMLHttpRequest;s.onProgress&&typeof s.onProgress=="function"&&(n.upload.onprogress=s.onProgress),n.onload=function(){n.status>=200&&n.status<300?i({data:n.response,status:n.status,statusText:n.statusText,xhr:n}):r(new Error(`Upload failed: ${n.status} ${n.statusText}`))},n.onerror=function(){r(new Error("Upload failed: Network error"))},n.ontimeout=function(){r(new Error("Upload failed: Timeout"))},n.open("PUT",e),n.setRequestHeader("Content-Type",t.type),s.timeout&&(n.timeout=s.timeout),n.send(t)})}async uploadMultipart(e,t,s={},i={}){const r=new FormData;if(t instanceof FileList)Array.from(t).forEach((n,a)=>{r.append(`file_${a}`,n)});else if(t instanceof File)r.append("file",t);else if(t instanceof FormData)return this.POST(e,t,{},i);return Object.entries(s).forEach(([n,a])=>{r.append(n,a)}),this.POST(e,r,{},i)}setAuthToken(e,t="Bearer"){e?this.config.headers.Authorization=`${t} ${e}`:delete this.config.headers.Authorization}clearAuth(){delete this.config.headers.Authorization}isRetryableError(e){return["not_reachable","timed_out","server_error","dns_error"].includes(e.reason)}requiresAuth(e){return e.reason==="unauthorized"}isNetworkError(e){return["not_reachable","timed_out","cancelled","cors_error","dns_error"].includes(e.reason)}getUserMessage(e){return e.message?e.message:{not_reachable:"Unable to connect to the server. Please check your internet connection.",timed_out:"The request took too long. Please try again.",cancelled:"The request was cancelled.",unauthorized:"Please log in to continue.",forbidden:"You don't have permission to perform this action.",not_found:"The requested resource was not found.",validation_error:"Please check your input and try again.",rate_limited:"Too many requests. Please wait a moment before trying again.",server_error:"Server error. Please try again later.",cors_error:"Access blocked by security policy.",dns_error:"Unable to reach the server.",unknown_error:"An unexpected error occurred."}[e.reason]||"An error occurred. Please try again."}}const re=new Vt,Pt="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI2NlZDRkYSI+PHBhdGggZD0iTTEyIDEyYzIuMjEgMCA0LTEuNzkgNC00cy0xLjc5LTQtNC00LTQgMS43OS00IDQgMS43OSA0IDQgNHptMCAyYy0yLjY3IDAtOCAxLjM0LTggNHYyaDE2di0yYzAtMi42Ni01LjMzLTQtOC00eiIvPjwvc3ZnPg==";class Nt{constructor(){this.formatters=new Map,this.registerBuiltInFormatters()}escapeHtml(e){if(e==null)return"";const t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;"};return String(e).replace(/[&<>"']/g,s=>t[s])}registerBuiltInFormatters(){this.register("date",this.date.bind(this)),this.register("time",this.time.bind(this)),this.register("datetime",this.datetime.bind(this)),this.register("datetime_tz",this.datetime_tz.bind(this)),this.register("datatime_tz",this.datetime_tz.bind(this)),this.register("date_range",this.date_range.bind(this)),this.register("datetime_range",this.datetime_range.bind(this)),this.register("relative",this.relative.bind(this)),this.register("fromNow",this.relative.bind(this)),this.register("timeago",this.relative.bind(this)),this.register("relative_short",this.relative_short.bind(this)),this.register("iso",this.iso.bind(this)),this.register("epoch",e=>{if(e==null||e==="")return e;const t=parseFloat(e);return isNaN(t)?e:t*1e3}),this.register("number",this.number.bind(this)),this.register("currency",this.currency.bind(this)),this.register("percent",this.percent.bind(this)),this.register("filesize",this.filesize.bind(this)),this.register("ordinal",this.ordinal.bind(this)),this.register("compact",this.compact.bind(this)),this.register("add",this.add.bind(this)),this.register("subtract",this.subtract.bind(this)),this.register("multiply",this.multiply.bind(this)),this.register("divide",this.divide.bind(this)),this.register("sub",this.subtract.bind(this)),this.register("mult",this.multiply.bind(this)),this.register("div",this.divide.bind(this)),this.register("uppercase",e=>String(e).toUpperCase()),this.register("lowercase",e=>String(e).toLowerCase()),this.register("upper",e=>String(e).toUpperCase()),this.register("lower",e=>String(e).toLowerCase()),this.register("capitalize",this.capitalize.bind(this)),this.register("caps",this.capitalize.bind(this)),this.register("replace",this.replace.bind(this)),this.register("truncate",this.truncate.bind(this)),this.register("truncate_middle",this.truncate_middle.bind(this)),this.register("truncate_front",this.truncate_front.bind(this)),this.register("slug",this.slug.bind(this)),this.register("initials",this.initials.bind(this)),this.register("mask",this.mask.bind(this)),this.register("hex",this.hex.bind(this)),this.register("tohex",this.hex.bind(this)),this.register("unhex",this.unhex.bind(this)),this.register("fromhex",this.unhex.bind(this)),this.register("email",this.email.bind(this)),this.register("phone",this.phone.bind(this)),this.register("url",this.url.bind(this)),this.register("badge",this.badge.bind(this)),this.register("badgeClass",this.badgeClass.bind(this)),this.register("status",this.status.bind(this)),this.register("status_text",this.status_text.bind(this)),this.register("status_icon",this.status_icon.bind(this)),this.register("boolean",this.boolean.bind(this)),this.register("bool",this.bool.bind(this)),this.register("yesno",e=>this.boolean(e,"Yes","No")),this.register("yesnoicon",this.yesnoicon.bind(this)),this.register("icon",this.icon.bind(this)),this.register("avatar",this.avatar.bind(this)),this.register("image",this.image.bind(this)),this.register("tooltip",this.tooltip.bind(this)),this.register("linkify",this.linkify.bind(this)),this.register("clipboard",this.clipboard.bind(this)),this.register("default",this.default.bind(this)),this.register("equals",this.equals.bind(this)),this.register("json",this.json.bind(this)),this.register("raw",e=>e),this.register("custom",(e,t)=>typeof t=="function"?t(e):e),this.register("iter",this.iter.bind(this)),this.register("keys",e=>e&&typeof e=="object"&&!Array.isArray(e)?Object.keys(e):null),this.register("values",e=>e&&typeof e=="object"&&!Array.isArray(e)?Object.values(e):null),this.register("plural",this.plural.bind(this)),this.register("list",this.formatList.bind(this)),this.register("duration",this.duration.bind(this)),this.register("hash",this.hash.bind(this)),this.register("stripHtml",this.stripHtml.bind(this)),this.register("highlight",this.highlight.bind(this)),this.register("nl2br",this.nl2br.bind(this)),this.register("code",this.code.bind(this)),this.register("pre",e=>`<pre class="bg-light p-2 rounded border">${this.escapeHtml(String(e))}</pre>`)}relative_short(e){return this.relative(e,!0)}linkify(e,t={}){if(e==null)return"";const s=String(e),i=this.escapeHtml(s),r={urls:!0,emails:!0,target:"_blank",rel:"noopener noreferrer"},n=t&&typeof t=="object"?{...r,...t}:r;let a=i;if(n.urls!==!1){const o=/(^|\s)((?:https?:\/\/|www\.)[^\s<]+)/gi;a=a.replace(o,(l,d,h)=>{const u=h.startsWith("www.")?`https://${h}`:h;return`${d}<a href="${u}" target="${n.target}" rel="${n.rel}">${h}</a>`})}if(n.emails!==!1){const o=/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;a=a.replace(o,l=>`<a href="mailto:${l}">${l}</a>`)}return a}clipboard(e,t="text"){if(e==null)return"";const s=String(e),i=this.escapeHtml(s),r=t!=="icon-only",n=`
2
2
  <button type="button"
3
3
  class="btn btn-sm btn-outline-secondary ms-1 p-0 border-0 bg-transparent"
4
4
  title="Copy"
@@ -11,8 +11,8 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
11
11
  ${r?`<span class="font-monospace">${i}</span>`:""}
12
12
  ${n}
13
13
  </span>
14
- `}nl2br(e){return e==null?"":this.escapeHtml(String(e)).replace(/\r\n|\r|\n/g,"<br>")}code(e,t=""){if(e==null)return"";const s=t?`language-${this.escapeHtml(String(t))}`:"",i=this.escapeHtml(String(e));return`<pre class="bg-light p-2 rounded border"><code class="${s}">${i}</code></pre>`}register(e,t){if(typeof t!="function")throw new Error(`Formatter must be a function, got ${typeof t}`);return this.formatters.set(e.toLowerCase(),t),this}apply(e,t,...s){if(Array.isArray(t)&&t.every(i=>typeof i=="string"))return t.reduce((i,r)=>this.apply(r,i,...s),e);try{const i=this.formatters.get(e.toLowerCase());return i?i(t,...s):(console.warn(`Formatter '${e}' not found`),t)}catch(i){return console.error(`Error in formatter '${e}':`,i),t}}pipe(e,t,s=null){return t?this.parsePipeString(t,s).reduce((r,n)=>this.apply(n.name,r,...n.args),e):e}parsePipeString(e,t=null){const s=[],i=e.split("|").map(r=>r.trim());for(const r of i){const n=this.parseFormatter(r,t);n&&s.push(n)}return s}parseFormatter(e,t=null){const s=e.match(/^([a-zA-Z_]\w*)\s*\((.*)\)$/);if(s){const[,r,n]=s,a=n?this.parseArguments(n,t):[];return{name:r,args:a}}const i=e.match(/^([a-zA-Z_]\w*)(?::(.+))?$/);if(i){const[,r,n]=i,a=n?this.parseColonArguments(n,t):[];return{name:r,args:a}}return null}parseArguments(e,t=null){const s=[];let i="",r=!1,n=null,a=0;for(let o=0;o<e.length;o++){const l=e[o];!r&&(l==='"'||l==="'")?(r=!0,n=l,i+=l):r&&l===n&&e[o-1]!=="\\"?(r=!1,n=null,i+=l):!r&&l==="{"?(a++,i+=l):!r&&l==="}"?(a--,i+=l):!r&&a===0&&l===","?(s.push(this.parseValue(i.trim(),t)),i=""):i+=l}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseColonArguments(e,t=null){const s=[];let i="",r=!1,n=null;for(let a=0;a<e.length;a++){const o=e[a];!r&&(o==='"'||o==="'")?(r=!0,n=o,i+=o):r&&o===n&&e[a-1]!=="\\"?(r=!1,n=null,i+=o):!r&&o===":"?(s.push(this.parseValue(i.trim(),t)),i=""):i+=o}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseValue(e,t=null){if(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);if(e==="true")return!0;if(e==="false")return!1;if(e==="null")return null;if(e!=="undefined"){if(!isNaN(e)&&e!=="")return Number(e);if(e.startsWith("{")&&e.endsWith("}"))try{return JSON.parse(e)}catch{}if(t&&this.isIdentifier(e)){if(!e.includes(".")&&Object.prototype.hasOwnProperty.call(t,e))return t[e];if(t.get&&typeof t.get=="function"){const s=t.get(e);if(s!==void 0)return s}if(t.getContextValue&&typeof t.getContextValue=="function"){const s=t.getContextValue(e);if(s!==void 0)return s}if(e.includes(".")){const s=window.MOJOUtils||(typeof require<"u"?require("./MOJOUtils.js").default:null);if(s){const i=s.getNestedValue(t,e);if(i!==void 0)return i}}}return e}}isIdentifier(e){return/^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/.test(e)}date(e,t="MM/DD/YYYY"){if(!e)return"";e=this.normalizeEpoch(e);let s;if(e instanceof Date)s=e;else if(typeof e=="string")if(/^\d{4}-\d{2}-\d{2}$/.test(e)){const[a,o,l]=e.split("-").map(Number);s=new Date(a,o-1,l)}else s=new Date(e);else s=new Date(e);if(isNaN(s.getTime()))return String(e);const i={YYYY:s.getFullYear(),YY:String(s.getFullYear()).slice(-2),MMMM:s.toLocaleDateString("en-US",{month:"long"}),MMM:s.toLocaleDateString("en-US",{month:"short"}),MM:String(s.getMonth()+1).padStart(2,"0"),M:s.getMonth()+1,dddd:s.toLocaleDateString("en-US",{weekday:"long"}),ddd:s.toLocaleDateString("en-US",{weekday:"short"}),DD:String(s.getDate()).padStart(2,"0"),D:s.getDate()};let r=t;const n=new RegExp(`(${Object.keys(i).join("|")})`,"g");return r=r.replace(n,a=>i[a]||a),r}time(e,t="HH:mm:ss"){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const i=s.getHours(),r={HH:String(i).padStart(2,"0"),H:i,hh:String(i%12||12).padStart(2,"0"),h:i%12||12,mm:String(s.getMinutes()).padStart(2,"0"),m:s.getMinutes(),ss:String(s.getSeconds()).padStart(2,"0"),s:s.getSeconds(),A:i>=12?"PM":"AM",a:i>=12?"pm":"am"};let n=t;const a=Object.keys(r).sort((o,l)=>l.length-o.length);for(const o of a)n=n.replace(new RegExp(o,"g"),r[o]);return n}datetime(e,t="MM/DD/YYYY",s="HH:mm:ss"){e=this.normalizeEpoch(e);const i=this.date(e,t),r=this.time(e,s);return i&&r?`${i} ${r}`:""}datetime_tz(e,t="MM/DD/YYYY",s="HH:mm:ss",i={}){if(!e)return"";e=this.normalizeEpoch(e);const r=e instanceof Date?e:new Date(e);if(isNaN(r.getTime()))return String(e);const n=i&&i.locale||"en-US",a=i&&i.timeZone?i.timeZone:void 0,o=()=>{let k="";try{const te=new Intl.DateTimeFormat(n,{hour:"2-digit",minute:"2-digit",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(z=>z.type==="timeZoneName");if(k=te?te.value:"",k&&/^GMT[+-]/i.test(k))try{const se=new Intl.DateTimeFormat(n,{timeStyle:"short",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(Fs=>Fs.type==="timeZoneName");se&&se.value&&!/^GMT[+-]/i.test(se.value)&&(k=se.value)}catch{}if(k&&/\s/.test(k)){const z=k.split(/\s+/).map(se=>se[0]).join("").toUpperCase();z.length>=2&&z.length<=4&&(k=z)}}catch{k=""}return k};if(!a){const k=this.date(r,t),Y=this.time(r,s),te=o();return k&&Y?`${k} ${Y} ${te}`.trim():""}const l=new Intl.DateTimeFormat(n,{timeZone:a,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hourCycle:"h23"}).formatToParts(r),d=k=>{const Y=l.find(te=>te.type===k);return Y?Y.value:""},h=d("year"),u=d("month"),m=d("day"),p=d("hour"),f=d("minute"),g=d("second"),b=u?String(parseInt(u,10)):"",y=m?String(parseInt(m,10)):"",v=p?String(parseInt(p,10)):"",_=p?parseInt(p,10)%12||12:"",A=p?parseInt(p,10)>=12?"PM":"AM":"",E=A?A.toLowerCase():"",j=new Intl.DateTimeFormat(n,{timeZone:a,month:"long"}).format(r),M=new Intl.DateTimeFormat(n,{timeZone:a,month:"short"}).format(r),R=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"long"}).format(r),ne=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"short"}).format(r),be={YYYY:h,YY:h?h.slice(-2):"",MMMM:j,MMM:M,MM:u,M:b,dddd:R,ddd:ne,DD:m,D:y},ye={HH:p,H:v,hh:_!==""?String(_).padStart(2,"0"):"",h:_!==""?String(_):"",mm:f,m:f?String(parseInt(f,10)):"",ss:g,s:g?String(parseInt(g,10)):"",A,a:E},I=(k,Y)=>{if(!k)return"";const te=new RegExp(`(${Object.keys(Y).sort((z,se)=>se.length-z.length).join("|")})`,"g");return k.replace(te,z=>Y[z]??z)},H=I(t,be),Mt=I(s,ye),Ts=o();return H&&Mt?`${H} ${Mt} ${Ts}`.trim():""}normalizeEpoch(e){if(e instanceof Date)return e;if(typeof e=="string"){const t=Number(e);if(Number.isFinite(t))e=t;else{const s=Date.parse(e);return Number.isFinite(s)?s:""}}else typeof e!="number"&&(e=Number(e));if(isNaN(e))return"";if(e<1e11)return e*1e3;if(e>1e12&&e<1e13)return e;throw new Error("Value doesn't look like epoch seconds or ms")}date_range(e,t=null,s="MM/DD/YYYY"){if(!e)return"";const i=t||new Date,r=this.date(e,s),n=this.date(i,s);return!r||!n?"":`${r} - ${n}`}datetime_range(e,t=null,s="MM/DD/YYYY",i="HH:mm"){if(!e)return"";const r=t||new Date,n=this.datetime(e,s,i),a=this.datetime(r,s,i);return!n||!a?"":`${n} - ${a}`}relative(e,t=!1){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const r=s-new Date,n=Math.abs(r),a=Math.floor(n/1e3),o=Math.floor(a/60),l=Math.floor(o/60),d=Math.floor(l/24),h=r>0;if(t)return d>365?Math.floor(d/365)+"y":d>30?Math.floor(d/30)+"mo":d>7?Math.floor(d/7)+"w":d>0?d+"d":l>0?l+"h":o>0?o+"m":"now";if(d>365){const u=Math.floor(d/365),m=h?"in ":"",p=h?"":" ago";return m+u+" year"+(u>1?"s":"")+p}if(d>30){const u=Math.floor(d/30),m=h?"in ":"",p=h?"":" ago";return m+u+" month"+(u>1?"s":"")+p}if(d>7){const u=Math.floor(d/7),m=h?"in ":"",p=h?"":" ago";return m+u+" week"+(u>1?"s":"")+p}if(d===1)return h?"tomorrow":"yesterday";if(d>0){const u=h?"in ":"",m=h?"":" ago";return u+d+" days"+m}if(l>0){const u=h?"in ":"",m=h?"":" ago";return u+l+" hour"+(l>1?"s":"")+m}if(o>0){const u=h?"in ":"",m=h?"":" ago";return u+o+" minute"+(o>1?"s":"")+m}if(a>30){const u=h?"in ":"",m=h?"":" ago";return u+a+" seconds"+m}return"just now"}iso(e,t=!1){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);return isNaN(s.getTime())?String(e):t?s.toISOString().split("T")[0]:s.toISOString()}number(e,t=2,s="en-US"){const i=parseFloat(e);return isNaN(i)?String(e):i.toLocaleString(s,{minimumFractionDigits:t,maximumFractionDigits:t})}currency(e,t="$",s=2){const i=parseInt(e);if(isNaN(i))return String(e);const r=Math.abs(i).toString(),n=i<0?"-":"";let a,o;r.length<=2?(a="0",o=r.padStart(2,"0")):(a=r.slice(0,-2),o=r.slice(-2)),a=a.replace(/\B(?=(\d{3})+(?!\d))/g,",");let l;if(s===0)parseInt(o)>=50&&(a=(parseInt(a.replace(/,/g,""))+1).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")),l=a;else if(s===2)l=`${a}.${o}`;else{const d=o.slice(0,s).padEnd(s,"0");l=`${a}.${d}`}return n+t+l}percent(e,t=0,s=!0){const i=parseFloat(e);if(isNaN(i))return String(e);const r=s?i*100:i;return this.number(r,t)+"%"}filesize(e,t=!1,s=1){const i=parseInt(e);if(isNaN(i))return String(e);const r=t?["B","KiB","MiB","GiB","TiB"]:["B","KB","MB","GB","TB"],n=t?1024:1e3;let a=i,o=0;for(;a>=n&&o<r.length-1;)a/=n,o++;const l=o===0?0:s;return`${a.toFixed(l)} ${r[o]}`}ordinal(e,t=!1){const s=parseInt(e);if(isNaN(s))return String(e);const i=s%10,r=s%100;let n="th";return i===1&&r!==11?n="st":i===2&&r!==12?n="nd":i===3&&r!==13&&(n="rd"),t?n:s+n}compact(e,t=1){const s=parseFloat(e);if(isNaN(s))return String(e);const i=Math.abs(s),r=s<0?"-":"";return i>=1e9?r+(i/1e9).toFixed(t)+"B":i>=1e6?r+(i/1e6).toFixed(t)+"M":i>=1e3?r+(i/1e3).toFixed(t)+"K":String(s)}add(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s+i}subtract(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s-i}multiply(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s*i}divide(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)||i===0?e:s/i}capitalize(e,t=!0){const s=String(e);return s?t?s.replace(/\b\w/g,i=>i.toUpperCase()):s.charAt(0).toUpperCase()+s.slice(1):""}replace(e,t,s="",i="g"){if(e==null)return"";const r=String(e);if(t==null||t==="")return r;if(t instanceof RegExp)return r.replace(t,String(s));const n=String(t),a=n.match(/^\/(.+)\/([a-z]*)$/i);if(a){const[,o,l]=a;try{return r.replace(new RegExp(o,l),String(s))}catch{}}return String(i).includes("g")?r.split(n).join(String(s)):r.replace(n,String(s))}truncate(e,t=50,s="..."){const i=String(e);return i.length<=t?i:i.substring(0,t)+s}truncate_front(e,t=8,s="..."){const i=String(e);return i.length<=t?i:`${s}${i.slice(-t)}`}truncate_middle(e,t=8,s="***"){const i=String(e);if(i.length<=t)return i;const r=Math.floor(t/2),n=i.substring(0,r),a=i.substring(i.length-r);return`${n}${s}${a}`}slug(e,t="-"){return String(e).toLowerCase().replace(/[^\w\s-]/g,"").replace(/\s+/g,t).replace(new RegExp(`${t}+`,"g"),t).replace(new RegExp(`^${t}|${t}$`,"g"),"")}initials(e,t=2){return String(e).split(/\s+/).filter(r=>r.length>0).slice(0,t).map(r=>r.charAt(0).toUpperCase()).join("")}mask(e,t="*",s=4){const i=String(e);if(i.length<=s)return i;const r=t.repeat(Math.max(0,i.length-s)),n=i.slice(-s);return r+n}email(e,t={}){const s=String(e).trim();if(!s)return"";if(t.link===!1)return s;const i=t.subject?`?subject=${encodeURIComponent(t.subject)}`:"",r=t.body?`&body=${encodeURIComponent(t.body)}`:"",n=t.class?` class="${t.class}"`:"";return`<a href="mailto:${s}${i}${r}"${n}>${s}</a>`}phone(e,t="US",s=!0){let i=String(e).replace(/\D/g,""),r=i;return t==="US"&&(i.length===10?r=`(${i.slice(0,3)}) ${i.slice(3,6)}-${i.slice(6)}`:i.length===11&&i[0]==="1"&&(r=`+1 (${i.slice(1,4)}) ${i.slice(4,7)}-${i.slice(7)}`)),s?`<a href="tel:${i}">${r}</a>`:r}url(e,t=null,s=!0){let i=String(e).trim();return i?(/^https?:\/\//.test(i)||(i="https://"+i),`<a href="${i}"${s?' target="_blank"':""}${s?' rel="noopener noreferrer"':""}>${t||i}</a>`):""}badge(e,t="auto"){if(Array.isArray(e))return e.map(n=>this.badge(n,t)).join(" ");const s=String(e);if(typeof t=="string"&&t.includes("=")){const n=Object.fromEntries(t.split(",").map(l=>l.split("=").map(d=>d.trim()))),a=n[s]||n[s.toLowerCase()]||this.inferBadgeType(s);return`<span class="badge ${a?`bg-${a}`:"bg-secondary"}">${s}</span>`}const i=t==="auto"?this.inferBadgeType(s):t;return`<span class="badge ${i?`bg-${i}`:"bg-secondary"}">${s}</span>`}badgeClass(e,t="auto"){const s=String(e),i=t==="auto"?this.inferBadgeType(s):t;return i?`bg-${i}`:"bg-secondary"}inferBadgeType(e){const t=e.toLowerCase();return["active","pass","success","complete","completed","approved","done","true","on","yes"].includes(t)?"success":["error","failed","fail","rejected","deleted","cancelled","false","off","no","declined"].includes(t)?"danger":["warning","pending","review","processing","uploading"].includes(t)?"warning":["info","new","draft"].includes(t)?"info":(["inactive","disabled","archived","suspended"].includes(t),"secondary")}status(e){return this._status(e)}status_icon(e){return this._status(e,{},{},!1,!0)}status_text(e){return this._status(e,{},{},!0,!1)}_status(e,t={},s={},i=!1,r=!1){const n=String(e).toLowerCase(),a={active:"bi bi-check-circle-fill",approved:"bi bi-check-circle-fill",declined:"bi bi-x-circle-fill",inactive:"bi bi-pause-circle-fill",pending:"bi bi-clock-fill",success:"bi bi-check-circle-fill",error:"bi bi-exclamation-triangle-fill",warning:"bi bi-exclamation-triangle-fill"},o={active:"success",approved:"success",declined:"danger",inactive:"secondary",pending:"warning",success:"success",error:"danger",warning:"warning"},l=t[n]||a[n]||"",d=s[n]||o[n]||"secondary";let h="";!i&&l&&(h=`<i class="${l}"></i>`);let u="";return r||(u=e),`<span class="text-${d}">${h}${h?" ":""}${u}</span>`}boolean(e,t="True",s="False",i=!1){const r=e?t:s;return i?`<span class="text-${e?"success":"danger"}">${r}</span>`:r}bool(e){return e==null||e===0||e===""||e===!1||e==="false"?!1:e===!0||e==="true"?!0:!(Array.isArray(e)&&e.length===0||e&&typeof e=="object"&&e.constructor===Object&&Object.keys(e).length===0)}icon(e,t={}){const s=String(e).toLowerCase(),i=t[s]||"";return i?`<i class="${i}"></i>`:""}yesnoicon(e,t="bi bi-check-circle-fill text-success",s="bi bi-x-circle-fill text-danger"){return e?`<i class="${t}"></i>`:`<i class="${s}"></i>`}image(e,t="thumbnail",s="img-fluid",i=""){const r=this._extractImageUrl(e,t);return r?`<img src="${r}" class="${s}" alt="${i}" />`:""}avatar(e,t="md",s="rounded-circle",i=""){const r=this._extractImageUrl(e,"square_sm")||Pt,n={xs:"width: 1.5rem; height: 1.5rem;",sm:"width: 2rem; height: 2rem;",md:"width: 3rem; height: 3rem;",lg:"width: 4rem; height: 4rem;",xl:"width: 5rem; height: 5rem;"},a=n[t]||n.md,l=`object-fit-cover ${s}`.trim();return`<img src="${r}" class="${l}" style="${a}" alt="${i}" />`}tooltip(e,t="",s="top",i=""){if(e==null)return"";const r=String(e),n=i==="html"?t:this.escapeHtml(t);return`<span data-bs-toggle="tooltip" data-bs-placement="${s}" ${i==="html"?'data-bs-html="true"':""} data-bs-title="${n}">${r}</span>`}_extractImageUrl(e,t="thumbnail"){if(!e)return null;if(typeof e=="string")return e;if(typeof e=="object"){if(e.attributes&&(e=e.attributes),t==="thumbnail"&&e.thumbnail&&typeof e.thumbnail=="string")return e.thumbnail;if(e.renditions&&typeof e.renditions=="object"){const s=e.renditions[t];if(s&&s.url)return s.url;const i=Object.values(e.renditions);if(i.length>0&&i[0].url)return i[0].url}if(e.url)return e.url}return null}default(e,t=""){return e==null||e===""?t:e}equals(e,t,s,i=""){return e==t?s:i}plural(e,t,s=null,i=!0){if(e==null||t===null||t===void 0)return i?`${e} ${t}`:t||"";const r=parseInt(e);if(isNaN(r))return i?`${e} ${t}`:t||"";const n=Math.abs(r)===1?t:s||t+"s";return i?`${r} ${n}`:n}formatList(e,t={}){if(!Array.isArray(e))return String(e);const{conjunction:s="and",limit:i=null,moreText:r="others"}=t;if(e.length===0)return"";if(e.length===1)return String(e[0]);let n=e.slice(),a=!1;if(i&&e.length>i&&(n=e.slice(0,i),a=!0),a){const o=e.length-i;return`${n.join(", ")}, ${s} ${o} ${r}`}return n.length===2?`${n[0]} ${s} ${n[1]}`:`${n.slice(0,-1).join(", ")}, ${s} ${n[n.length-1]}`}duration(e,t="ms",s=!1,i=2){if(e==null)return"";const r=parseFloat(e);if(isNaN(r))return String(e);let n;switch(t){case"s":case"sec":case"seconds":n=r*1e3;break;case"m":case"min":case"minutes":n=r*6e4;break;case"h":case"hr":case"hours":n=r*36e5;break;case"d":case"day":case"days":n=r*864e5;break;default:n=r}const a=[{name:"day",short:"d",value:864e5},{name:"hour",short:"h",value:36e5},{name:"minute",short:"m",value:6e4},{name:"second",short:"s",value:1e3}];if(n===0)return s?"0s":"0 seconds";const o=Math.abs(n),l=n<0?"-":"",d=[];let h=o;for(const u of a)if(h>=u.value){const m=Math.floor(h/u.value);h=h%u.value;const p=s?u.short:m===1?u.name:u.name+"s";if(d.push(s?`${m}${p}`:`${m} ${p}`),d.length>=i)break}return d.length===0?s?`${Math.round(o)}ms`:`${Math.round(o)} milliseconds`:l+(s?d.join(""):d.join(" "))}hash(e,t=8,s="",i="..."){if(e==null)return"";const r=String(e);return r.length<=t?s+r:s+r.substring(0,t)+i}stripHtml(e){return e==null?"":String(e).replace(/<[^>]*>/g,"")}highlight(e,t,s="highlight"){if(e==null||!t)return String(e||"");const i=String(t).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(`(${i})`,"gi");return String(e).replace(r,`<mark class="${s}">$1</mark>`)}hex(e,t=!1,s=!1){if(e==null)return"";let i="";const r=n=>Array.from(n).map(a=>a.toString(16).padStart(2,"0")).join("");if(typeof e=="number"){let n=Math.abs(Math.trunc(e)).toString(16);n.length%2&&(n="0"+n),i=n}else if(e instanceof Uint8Array)i=r(e);else if(e instanceof ArrayBuffer)i=r(new Uint8Array(e));else if(Array.isArray(e)&&e.every(n=>typeof n=="number"))i=r(Uint8Array.from(e.map(n=>n&255)));else{const a=new TextEncoder().encode(String(e));i=r(a)}return t&&(i=i.toUpperCase()),(s?"0x":"")+i}unhex(e){if(e==null)return"";let t=String(e).trim();if((t.startsWith("0x")||t.startsWith("0X"))&&(t=t.slice(2)),t=t.replace(/\s+/g,""),t.length===0)return"";t.length%2!==0&&(t="0"+t);const s=new Uint8Array(t.length/2);for(let i=0;i<t.length;i+=2){const r=parseInt(t.slice(i,i+2),16);if(Number.isNaN(r))return String(e);s[i/2]=r}try{return new TextDecoder().decode(s)}catch{let r="";for(const n of s)r+=String.fromCharCode(n);return r}}json(e,t=2){try{return JSON.stringify(e,null,t)}catch{return String(e)}}has(e){return this.formatters.has(e.toLowerCase())}unregister(e){return this.formatters.delete(e.toLowerCase())}listFormatters(){return Array.from(this.formatters.keys()).sort()}iter(e){return e==null?[]:Array.isArray(e)?e:typeof e=="object"?Object.entries(e).map(([t,s])=>({key:t,value:s})):[{key:"0",value:e}]}}const P=new Nt;window.dataFormatter=P;const et=new Set(["__proto__","constructor","prototype"]),tt=(c,e)=>c!=null&&Object.prototype.hasOwnProperty.call(c,e);class ${static getContextData(e,t){if(!t||e==null)return;let s=t,i="",r=0,n=-1;for(let o=0;o<t.length;o++){const l=t[o];if(l==="(")r++;else if(l===")")r--;else if(l==="|"&&r===0){n=o;break}}n>-1&&(s=t.substring(0,n).trim(),i=t.substring(n+1).trim());const a=this.getNestedValue(e,s);return i?P.pipe(a,i,e):a}static getNestedValue(e,t){if(!t||e==null||t.split(".").some(r=>et.has(r)))return;if(!t.includes(".")){if(t in e){const r=e[t];return typeof r=="function"?r===Object.prototype[t]?void 0:r.call(e):r}return}const s=t.split(".");let i=e;for(let r=0;r<s.length;r++){const n=s[r];if(i==null)return;if(r===0)if(tt(i,n)){const a=i[n];typeof a=="function"?i=a.call(e):i=a}else return;else{if(i&&typeof i.getContextValue=="function"){const a=s.slice(r).join(".");return i.getContextValue(a)}if(Array.isArray(i)&&!isNaN(n))i=i[parseInt(n)];else if(tt(i,n))i=i[n];else return}}return i}static isNullOrUndefined(e){return e==null}static deepClone(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(e instanceof Array)return e.map(t=>this.deepClone(t));if(e instanceof Object){const t={};for(const s in e)e.hasOwnProperty(s)&&(t[s]=this.deepClone(e[s]));return t}}static deepMerge(e,...t){if(!t.length)return e;const s=t.shift();if(this.isObject(e)&&this.isObject(s))for(const i in s)this.isObject(s[i])?(e[i]||Object.assign(e,{[i]:{}}),this.deepMerge(e[i],s[i])):Object.assign(e,{[i]:s[i]});return this.deepMerge(e,...t)}static isObject(e){return e&&typeof e=="object"&&!Array.isArray(e)}static debounce(e,t){let s;return function(...r){const n=()=>{clearTimeout(s),e(...r)};clearTimeout(s),s=setTimeout(n,t)}}static throttle(e,t){let s;return function(...i){s||(e.apply(this,i),s=!0,setTimeout(()=>s=!1,t))}}static generateId(e=""){const t=Date.now().toString(36),s=Math.random().toString(36).substr(2,9);return e?`${e}_${t}_${s}`:`${t}_${s}`}static escapeHtml(e){const t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(e).replace(/[&<>"'`=\/]/g,s=>t[s])}static checkPasswordStrength(e){if(!e||typeof e!="string")return{score:0,strength:"invalid",feedback:["Password must be a non-empty string"],details:{length:0,hasLowercase:!1,hasUppercase:!1,hasNumbers:!1,hasSpecialChars:!1,hasCommonPatterns:!1,isCommonPassword:!1}};const t=[],s={length:e.length,hasLowercase:/[a-z]/.test(e),hasUppercase:/[A-Z]/.test(e),hasNumbers:/[0-9]/.test(e),hasSpecialChars:/[^a-zA-Z0-9]/.test(e),hasCommonPatterns:!1,isCommonPassword:!1};let i=0;e.length<6?t.push("Password should be at least 6 characters long"):e.length<8?(i+=1,t.push("Consider using at least 8 characters for better security")):e.length<12?i+=3:i+=4,s.hasLowercase?i+=1:t.push("Include lowercase letters"),s.hasUppercase?i+=1:t.push("Include uppercase letters"),s.hasNumbers?i+=1:t.push("Include numbers"),s.hasSpecialChars?i+=2:t.push("Include special characters (!@#$%^&* etc.)");const r=[/123/,/abc/i,/qwerty/i,/asdf/i,/(.)\1{2,}/,/password/i,/admin/i,/user/i,/login/i];for(const o of r)if(o.test(e)){s.hasCommonPatterns=!0,i-=1,t.push("Avoid common patterns and dictionary words");break}["123456","password","123456789","12345678","12345","1234567","1234567890","qwerty","abc123","111111","123123","admin","letmein","welcome","monkey","password123","123qwe","qwerty123","000000","dragon","sunshine","princess","azerty","1234","iloveyou","trustno1","superman","shadow","master","jennifer"].includes(e.toLowerCase())&&(s.isCommonPassword=!0,i=Math.max(0,i-3),t.push("This password is too common and easily guessed"));let a;return i<2?a="very-weak":i<4?a="weak":i<6?a="fair":i<8?a="good":a="strong",i>=7&&t.length===0?t.push("Strong password! Consider using a password manager."):i>=5&&t.length<=1&&t.push("Good password strength. Consider adding more variety."),{score:Math.max(0,i),strength:a,feedback:t,details:s}}static generatePassword(e={}){const s={...{length:12,includeLowercase:!0,includeUppercase:!0,includeNumbers:!0,includeSpecialChars:!0,customChars:"",excludeAmbiguous:!1},...e};if(s.length<4)throw new Error("Password length must be at least 4 characters");let i="abcdefghijklmnopqrstuvwxyz",r="ABCDEFGHIJKLMNOPQRSTUVWXYZ",n="0123456789",a="!@#$%^&*()_+-=[]{}|;:,.<>?";s.excludeAmbiguous&&(i=i.replace(/[il]/g,""),r=r.replace(/[IOL]/g,""),n=n.replace(/[01]/g,""),a=a.replace(/[|]/g,""));let o="";const l=[];if(s.customChars?o=s.customChars:(s.includeLowercase&&(o+=i,l.push(i[Math.floor(Math.random()*i.length)])),s.includeUppercase&&(o+=r,l.push(r[Math.floor(Math.random()*r.length)])),s.includeNumbers&&(o+=n,l.push(n[Math.floor(Math.random()*n.length)])),s.includeSpecialChars&&(o+=a,l.push(a[Math.floor(Math.random()*a.length)]))),!o)throw new Error("No character types selected for password generation");let d="";for(const h of l)d+=h;for(let h=d.length;h<s.length;h++)d+=o[Math.floor(Math.random()*o.length)];return d.split("").sort(()=>Math.random()-.5).join("")}static parseQueryString(e){const t={},s=new URLSearchParams(e);for(const[i,r]of s.entries())t[i]=r;return t}static toQueryString(e){return new URLSearchParams(e).toString()}static wrapData(e,t=null,s=3){return!e||typeof e!="object"||e instanceof Date||e instanceof RegExp||e instanceof Error||s<=0||typeof e.getContextValue=="function"?e:Array.isArray(e)?e.map(i=>i&&typeof i=="object"&&!i.getContextValue?new Fe(i,t):i):new Fe(e,t)}}class Fe{constructor(e,t=null){if(Object.defineProperty(this,"_data",{value:e,writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(this,"_rootContext",{value:t,writable:!1,enumerable:!1,configurable:!1}),e&&typeof e=="object"){for(const s in e)if(e.hasOwnProperty(s)){const i=e[s];this[s]=$.wrapData(i,t)}}}getContextValue(e){let t=e,s="",i=0,r=-1;for(let a=0;a<e.length;a++){const o=e[a];if(o==="(")i++;else if(o===")")i--;else if(o==="|"&&i===0){r=a;break}}r>-1&&(t=e.substring(0,r).trim(),s=e.substring(r+1).trim());let n;return t in this&&!et.has(t)&&t!=="_data"&&t!=="_rootContext"?n=this[t]:n=$.getNestedValue(this._data,t),s&&n!==void 0?P.pipe(n,s,this._rootContext||this._data):n}has(e){return this._data&&this._data.hasOwnProperty(e)}toJSON(){return this._data}}$.DataWrapper=Fe,typeof window<"u"&&(window.utils=$);const Ot=new Set(["__proto__","constructor","prototype"]),Rt=Object.prototype.toString,ae=Array.isArray||function(c){return Rt.call(c)==="[object Array]"},ue=function(c){return typeof c=="function"},st=function(c){return c!==null&&typeof c=="object"};function jt(){return typeof window>"u"?null:window.MOJO?.dataFormatter?window.MOJO.dataFormatter:window.dataFormatter?window.dataFormatter:null}const it=function(c){const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(c).replace(/[&<>"'`=\/]/g,function(t){return e[t]})};class rt{constructor(e){this.string=e,this.tail=e,this.pos=0}eos(){return this.tail===""}scan(e){const t=this.tail.match(e);if(!t||t.index!==0)return"";const s=t[0];return this.tail=this.tail.substring(s.length),this.pos+=s.length,s}scanUntil(e){const t=this.tail.search(e);let s;switch(t){case-1:s=this.tail,this.tail="";break;case 0:s="";break;default:s=this.tail.substring(0,t),this.tail=this.tail.substring(t)}return this.pos+=s.length,s}}class we{constructor(e,t){this.view=e,this.cache={".":this.view},this.parent=t,this.view?._cacheId||this.view&&typeof this.view=="object"&&(this.view._cacheId=Math.random().toString(36).substring(2))}push(e){return new we(e,this)}lookup(e){if(this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;if(this.renderCache.has(i))return this.renderCache.get(i)}if(e===".")return this.view;if(e&&(e.startsWith(".")?e.slice(1):e).split("|")[0].split(".").some(r=>Ot.has(r)))return;if(e&&e.startsWith(".")){let i=e.substring(1),r=!1,n=null;const a=i.indexOf("|");if(a!==-1&&(n=i.substring(a+1).trim(),i=i.substring(0,a).trim()),i.endsWith("|iter")&&(i=i.substring(0,i.length-5),r=!0),this.view&&typeof this.view=="object"){let o;if(typeof this.view.getContextValue=="function")try{o=this.view.getContextValue(i),o!==void 0&&ue(o)&&(o=o.call(this.view))}catch{o=void 0}if(o===void 0&&(i.indexOf(".")>0?o=$.getNestedValue(this.view,i):i in this.view&&(o=this.view[i],ue(o)&&(o===Object.prototype[i]?o=void 0:o=o.call(this.view)))),n&&o!==void 0)try{const l=jt();l&&typeof l.pipe=="function"&&(o=l.pipe(o,n,this))}catch{}return ae(o)?r?o:o.length>0:st(o)?r?Object.entries(o).map(([l,d])=>({key:l,value:d})):Object.keys(o).length>0:o}return}const t=this.cache;let s;if(t.hasOwnProperty(e))s=t[e];else{let i=this,r,n,a,o=!1;for(;i;){if(i.view&&typeof i.view.getContextValue=="function")try{r=i.view.getContextValue(e),r!==void 0&&(o=!0)}catch{o=!1}if(!o)if(e.indexOf(".")>0)for(r=i.view,n=e.split("."),a=0;r!=null&&a<n.length;)if(r&&typeof r.getContextValue=="function"&&a<n.length)try{const l=n.slice(a).join(".");r=r.getContextValue(l),a=n.length,r!==void 0&&(o=!0)}catch{a===n.length-1&&(o=Ee(r,n[a])||nt(r,n[a])),r=r[n[a++]]}else a===n.length-1&&(o=Ee(r,n[a])||nt(r,n[a])),r=r[n[a++]];else r=i.view[e],o=Ee(i.view,e);if(o){s=r;break}i=i.parent}t[e]=s}if(ue(s)){const i=e.split("|")[0].split(".").pop();if(s===Object.prototype[i])s=void 0;else try{s=s.call(this.view)}catch(r){if(r instanceof TypeError&&/^Class constructor /.test(r.message))s=void 0;else throw r}}if(this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;this.renderCache.set(i,s)}return s}}function Ee(c,e){return c!=null&&typeof c=="object"&&e in c}function nt(c,e){return c!=null&&typeof c!="object"&&c.hasOwnProperty&&c.hasOwnProperty(e)}class at{constructor(){this.templateCache=new Map}clearCache(){this.templateCache.clear()}parse(e,t){t=t||["{{","}}"];const s=e+":"+t.join(":");let i=this.templateCache.get(s);return i==null&&(i=this.parseTemplate(e,t),this.templateCache.set(s,i)),i}parseTemplate(e,t){if(!e)return[];const s=t[0],i=t[1],r=new rt(e),n=[];let a,o,l,d,h;const u=new RegExp(De(s)+"\\s*"),m=new RegExp("\\s*"+De(i)),p=new RegExp("\\s*"+De("}"+i));for(;!r.eos();){if(a=r.pos,l=r.scanUntil(u),l)for(let f=0;f<l.length;++f)d=l.charAt(f),d===`
15
- `?n.push(["text",d]):n.push(["text",d]);if(!r.scan(u))break;if(o=r.scan(/[#^\/>{&=!]/),o||(o="name"),r.scan(/\s*/),o==="="?(l=r.scanUntil(/\s*=/),r.scan(/\s*=/),r.scanUntil(m)):o==="{"?(l=r.scanUntil(p),r.scan(p),o="&"):l=r.scanUntil(m),r.scan(m),o==="#"||o==="^")h=[o,l,a,r.pos],n.push(h);else if(o==="/"){let f;for(let g=n.length-1;g>=0;--g)if((n[g][0]==="#"||n[g][0]==="^")&&n[g][1]===l){f=n[g];break}f&&f.length===4&&f.push(r.pos),n.push([o,l,a,r.pos])}else n.push([o,l,a,r.pos])}return this.nestSections(this.squashTokens(n))}squashTokens(e){const t=[];let s,i;for(let r=0;r<e.length;++r)s=e[r],s&&(s[0]==="text"&&i&&i[0]==="text"?(i[1]+=s[1],i[3]=s[3]):(t.push(s),i=s));return t}nestSections(e){const t=[];let s=t;const i=[];for(let r=0;r<e.length;++r){const n=e[r];switch(n[0]){case"#":case"^":const a=[n[0],n[1],n[2],n[3],[],n[4]||null];s.push(a),i.push(a),s=a[4];break;case"/":const o=i.pop();o&&(o[5]=n[2],s=i.length>0?i[i.length-1][4]:t);break;default:s.push(n)}}return t}render(e,t,s,i){const r=this.getConfigTags(i)||["{{","}}"],n=this.parse(e,r),a=new Map;return this.renderTokens(n,new we(t),s,e,i,a)}renderTokens(e,t,s,i,r,n){n&&!t.renderCache&&(t.renderCache=n);let a="";for(let o=0;o<e.length;++o){const l=e[o];let d;switch(l[0]){case"#":if(d=t.lookup(l[1]),!d)continue;const h=l[4];if(!h||!ae(h)){console.warn(`MUSTACHE WARNING - Section ${l[1]} has no child tokens:`,l);continue}if(ae(d))for(let u=0;u<d.length;++u){const m=t.push(d[u]);t.renderCache&&(m.renderCache=t.renderCache);const p=this.renderTokens(h,m,s,i,r,n);a+=p}else if(typeof d=="object"||typeof d=="string"||typeof d=="number"){const u=t.push(d);t.renderCache&&(u.renderCache=t.renderCache),a+=this.renderTokens(h,u,s,i,r,n)}else if(ue(d)){const u=i==null?null:i.slice(l[3],l[5]);d=d.call(t.view,u,m=>this.render(m,t.view,s,r)),d!=null&&(a+=d)}else d&&(a+=this.renderTokens(h,t,s,i,r,n));break;case"^":if(d=t.lookup(l[1]),!d||ae(d)&&d.length===0){const u=l[4];u&&ae(u)&&(a+=this.renderTokens(u,t,s,i,r,n))}break;case">":if(!s)continue;d=ue(s)?s(l[1]):s[l[1]],d!=null&&(a+=this.render(d,t.view,s,r));break;case"&":d=t.lookup(l[1]),d!=null&&(a+=d);break;case"name":d=t.lookup(l[1]),d!=null&&(a+=it(d));break;case"text":a+=l[1];break}}return a}getConfigTags(e){return st(e)&&ae(e.tags)?e.tags:null}}function De(c){return c.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}const Ie=new at,D={name:"MOJO Mustache",version:"1.0.0",tags:["{{","}}"],Scanner:rt,Context:we,Writer:at,escape:it,clearCache(){return Ie.clearCache()},parse(c,e){return Ie.parse(c,e)},render(c,e,t,s){if(typeof c!="string")throw new TypeError('Invalid template! Template should be a "string"');return e&&typeof e=="object"&&!e.getContextValue&&typeof e.toJSON!="function"&&(e=$.wrapData(e)),Ie.render(c,e,t,s)}};class Ht{constructor(e){this.view=e,this.domListeners=[],this.debounceTimers=new Map}_enterDispatchChain(e){const t=e._mojoDispatch;let s;return e._mojoDispatch=new Promise(i=>{s=i}),{prior:t,done:s}}bind(e){if(this.unbind(),!e)return;const t=async a=>{const{prior:o,done:l}=this._enterDispatchChain(a);try{o&&await o;const d=a.target.closest("[data-action]");if(d&&this.shouldHandle(d,a)){const u=d.getAttribute("data-action");if(d.tagName==="A"&&a.preventDefault(),this.hideTooltip(d),await this.dispatch(u,a,d)){a.preventDefault(),a.stopPropagation(),a.handledByChild=!0;return}}const h=a.target.closest("a[href], [data-page]");if(h&&!h.hasAttribute("data-action")&&this.shouldHandle(h,a)){if(a.ctrlKey||a.metaKey||a.shiftKey||a.button===1)return;if(h.tagName==="A"){const u=h.getAttribute("href");if(u&&u!=="#"&&!u.startsWith("#")&&(this.view.isExternalLink(u)||h.hasAttribute("data-external")))return}this.hideTooltip(h),a.preventDefault(),a.stopPropagation(),a.handledByChild=!0,h.hasAttribute("data-page")?await this.view.handlePageNavigation(h):await this.view.handleHrefNavigation(h)}}finally{l()}},s=async a=>{const{prior:o,done:l}=this._enterDispatchChain(a);try{o&&await o;const d=a.target.closest("[data-change-action]");if(d&&this.shouldHandle(d,a)){const u=d.getAttribute("data-change-action");await this.dispatchChange(u,a,d)&&(a.stopPropagation(),a.handledByChild=!0);return}const h=a.target.closest("[data-action]");if(h&&this.isFormControl(h)&&this.shouldHandle(h,a)){const u=h.getAttribute("data-action");await this.dispatch(u,a,h)&&(a.stopPropagation(),a.handledByChild=!0)}}finally{l()}},i=a=>{const o=a.target.closest("[data-change-action]");if(o&&this.shouldHandle(o,a)&&a.target.matches('[data-filter="live-search"]')){const m=o.getAttribute("data-change-action"),p=parseInt(o.getAttribute("data-filter-debounce"))||300,f=`change-${m}-${o.getAttribute("data-container")||"default"}`;this.debounceTimers.has(f)&&clearTimeout(this.debounceTimers.get(f));const g=setTimeout(()=>{this.debounceTimers.delete(f),this.dispatchChange(m,a,o).then(b=>{b&&(a.stopPropagation(),a.handledByChild=!0)})},p);this.debounceTimers.set(f,g);return}const l=a.target.closest("[data-action]");if(!l||!this.isFormControl(l)||l.hasAttribute("data-change-action")||!this.shouldHandle(l,a))return;const d=l.getAttribute("data-action"),h=l.getAttribute("data-action-debounce"),u=h!=null&&parseInt(h)||0;if(u>0){const m=`action-${d}-${l.getAttribute("data-container")||"default"}`;this.debounceTimers.has(m)&&clearTimeout(this.debounceTimers.get(m));const p=setTimeout(()=>{this.debounceTimers.delete(m),this.dispatch(d,a,l).then(f=>{f&&(a.stopPropagation(),a.handledByChild=!0)})},u);this.debounceTimers.set(m,p);return}this.dispatch(d,a,l).then(m=>{m&&(a.stopPropagation(),a.handledByChild=!0)})},r=async a=>{if(a.target.matches('[data-filter="search"]'))return;const o=a.target.closest("[data-keydown-action]")||a.target.closest("[data-change-action]");if(!o)return;const{prior:l,done:d}=this._enterDispatchChain(a);try{if(l&&await l,!this.shouldHandle(o,a))return;let h=["Enter"];if(o.getAttribute("data-change-keys")&&(h=o.getAttribute("data-change-keys").split(",").map(u=>u.trim())),h.includes("*")||h.includes(a.key)){const u=o.getAttribute("data-keydown-action")||o.getAttribute("data-change-action");await this.dispatch(u,a,o)&&(a.preventDefault(),a.stopPropagation(),a.handledByChild=!0)}}finally{d()}},n=a=>{const o=a.target.closest("form[data-action]");if(!o||!this.shouldHandle(o,a))return;a.preventDefault();const l=o.getAttribute("data-action");this.dispatch(l,a,o)};e.addEventListener("click",t),e.addEventListener("change",s),e.addEventListener("input",i),e.addEventListener("keydown",r),e.addEventListener("submit",n),this.domListeners.push({el:e,type:"click",fn:t},{el:e,type:"change",fn:s},{el:e,type:"input",fn:i},{el:e,type:"keydown",fn:r},{el:e,type:"submit",fn:n})}unbind(){for(const{el:e,type:t,fn:s}of this.domListeners)e.removeEventListener(t,s);this.domListeners=[];for(const e of this.debounceTimers.values())clearTimeout(e);this.debounceTimers.clear()}hideDropdown(e){const s=e.closest(".dropdown-menu").closest(".dropdown");if(!s)return;const i=s.querySelector('[data-bs-toggle="dropdown"]');i&&window.bootstrap?.Dropdown&&window.bootstrap.Dropdown.getInstance(i)?.hide()}hideTooltip(e){if(e&&window.bootstrap?.Tooltip){const t=window.bootstrap.Tooltip.getInstance(e);t&&t.dispose()}}hideAllTooltips(){window.bootstrap?.Tooltip&&document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.hide()})}async dispatch(e,t,s){const i=this.view,r=l=>l.includes("-")?l.split("-").map(d=>d[0].toUpperCase()+d.slice(1)).join(""):l[0].toUpperCase()+l.slice(1),n=`handleAction${r(e)}`;if(typeof i[n]=="function")try{return t.preventDefault(),await i[n](t,s),!0}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const a=`onAction${r(e)}`;if(typeof i[a]=="function")try{return await i[a](t,s)?(s.closest(".dropdown-menu")&&this.hideDropdown(s),t.preventDefault(),t.stopPropagation(),!0):!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const o=`onPassThruAction${r(e)}`;if(typeof i[o]=="function")try{return await i[o](t,s),!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}if(typeof i.onActionDefault=="function")try{return await i.onActionDefault(e,t,s)}catch(l){return console.error(`Error in default action handler for ${e}:`,l),i.handleActionError(e,l,t,s),!0}return i.emit?.(`action:${e}`,{action:e,event:t,element:s}),!1}async dispatchChange(e,t,s){const i=this.view,n=`onChange${(a=>a.includes("-")?a.split("-").map(o=>o[0].toUpperCase()+o.slice(1)).join(""):a[0].toUpperCase()+a.slice(1))(e)}`;if(typeof i[n]=="function")try{return await i[n](t,s),!0}catch(a){return console.error(`Error in onChange ${e}:`,a),i.handleActionError?.(e,a,t,s),!0}return await this.dispatch(e,t,s)}isFormControl(e){if(!e||!e.tagName)return!1;const t=e.tagName;return t==="INPUT"||t==="TEXTAREA"||t==="SELECT"}shouldHandle(e,t){return!!(this.owns(e)||this.contains(e)&&!t.handledByChild)}owns(e){const t=this.view.element;if(!t||!t.contains(e))return!1;for(const s of Object.values(this.view.children))if(s.element&&s.element.contains(e))return!1;return!0}contains(e){return!!this.view.element&&this.view.element.contains(e)}}const Me={on(c,e,t){this._listeners||(this._listeners={}),this._listeners[c]||(this._listeners[c]=[]);const s={callback:e,context:t,fn:t?e.bind(t):e};return this._listeners[c].push(s),this},off(c,e,t){return!this._listeners||!this._listeners[c]?this:(e?(this._listeners[c]=this._listeners[c].filter(s=>s.callback!==e||arguments.length===3&&s.context!==t),this._listeners[c].length===0&&delete this._listeners[c]):delete this._listeners[c],this)},once(c,e,t){const s=(...i)=>{this.off(c,s),(t?e.bind(t):e).apply(t||this,i)};return this.on(c,s),this},emit(c,...e){if(!this._listeners||!this._listeners[c])return this;const t=this._listeners[c].slice();for(const s of t)try{s.fn.apply(s.context||this,e)}catch(i){console&&console.error&&console.error(`Error in ${c} event handler:`,i)}return this}};typeof window<"u"&&(window.Mustache=D);class C{constructor(e={}){this.tagName=e.tagName??"div",this.className=e.className??"mojo-view",this.style=e.style??null,this.id=e.id??C._genId(),this.containerId=e.containerId??null,this.container=e.container??null,typeof this.container=="string"&&(this.containerId=this.container,this.container=null),this.parent=e.parent??null,this.children=e.children??{},this.template=e.template||e.templateUrl||"",this.data=e.data??{},this.isRendering=!1,this.lastRenderTime=0,this.mounted=!1,this.debug=e.debug??!1,this.app=e.app??null,this.cacheTemplate=e.cacheTemplate??!0,this.enableTooltips=e.enableTooltips??!1,this.options={...e},this.element=this._ensureElement(),this.events=new Ht(this),e.model&&this.setModel(e.model)}async onInit(){}async onInitView(){this.initialized||(this.initialized=!0,await this.onInit())}async onBeforeRender(){}async onAfterRender(){}async onBeforeMount(){}async onAfterMount(){}async onBeforeUnmount(){}async onAfterUnmount(){}async onBeforeDestroy(){}async onAfterDestroy(){}setModel(e={}){let t=e!==this.model;if(!t)return this;this.model&&this.model.off&&this.model.off("change",this._onModelChange,this),this.model=e,this.model&&this.model.on&&this.model.on("change",this._onModelChange,this);for(const s in this.children){const i=this.children[s];i&&typeof i.setModel=="function"&&i.setModel(e)}return t&&this._onModelChange(),this}_onModelChange(){this.isMounted()&&this.render()}setTemplate(e){return this.template=e??"",this}addChild(e,t){try{if(!e||typeof e!="object")return this;t&&((t.containerId||t.container)&&(e.containerId=t.containerId||t.container),t.id&&(e.id=t.id),t.lazyMount===!0&&(e._lazyMount=!0)),e.parent=this,this.getApp()&&(e.app=this.app),this.children[e.id]=e}catch(s){C._warn("addChild error",s)}return e}removeChild(e){try{const t=typeof e=="string"?e:e&&e.id;if(!t)return this;const s=this.children[t];s&&(Promise.resolve(s.destroy()).catch(i=>C._warn("removeChild destroy error",i)),delete this.children[t])}catch(t){C._warn("removeChild error",t)}return this}getChild(e){return this.children[e]}async updateData(e,t=!1){return Object.assign(this.data,e),t&&this.isMounted()&&await this.render(),this}toggleClass(e,t){return t===void 0&&(t=!this.element.classList.contains(e)),this.element.classList.toggle(e,t),this}addClass(e){return this.element.classList.add(e),this}setClass(e){return this.element.className=e,this}removeClass(e){return this.element.classList.remove(e),this}canRender(){if(this.isRendering)return!1;const e=Date.now();if(this.options.renderCooldown>0&&e-this.lastRenderTime<this.options.renderCooldown)return C._warn(`View ${this.id}: Render called too quickly, cooldown active`),!1;if(this.options.noAppend&&this.parent)if(this.parent.contains(this.containerId||this.container)){if(this.containerId&&!document.getElementById(this.containerId))return!1;if(this.container&&!document.contains(this.container))return!1}else return!1;return!0}async render(e=!0,t=null){const s=Date.now();if(!this.canRender())return this;this.isRendering=!0,this.lastRenderTime=s;try{this.initialized||await this.onInitView(),this.unbindEvents(),await this.onBeforeRender(),this.getViewData&&(this.data=await this.getViewData());const i=await this.renderTemplate();this.element.innerHTML=i,e&&!this.isMounted()&&await this.mount(t),await this._renderChildren(),await this.onAfterRender(),this.bindEvents()}catch(i){C._warn(`Render error in ${this.id}`,i)}finally{this.isRendering=!1}return this}async _renderChildren(){const e=[];for(const t in this.children){const s=this.children[t];if(s){if(s.parent=this,s._lazyMount&&!s._lazyTriggered){e.push(s);continue}await Promise.resolve(s.render()).catch(i=>C._warn(`Child render error (${t})`,i))}}e.length&&this._setupLazyMountObserver(e)}_setupLazyMountObserver(e){if(typeof IntersectionObserver>"u"){e.forEach(t=>{t._lazyTriggered=!0,Promise.resolve(t.render()).catch(s=>C._warn(`Lazy child render error (${t.id})`,s))});return}this._lazyObserver||(this._lazyObserver=new IntersectionObserver((t,s)=>{for(const i of t){if(!i.isIntersecting)continue;const r=i.target.__mojoLazyChild;s.unobserve(i.target),!(!r||r._lazyTriggered)&&(r._lazyTriggered=!0,Promise.resolve(r.render()).catch(n=>C._warn(`Lazy child render error (${r.id})`,n)))}},{rootMargin:"120px 0px",threshold:.01}));for(const t of e){const s=this.getChildElement(t.containerId);s&&(s.__mojoLazyChild=t,s.style.minHeight||(s.classList.add("mojo-lazy-placeholder"),s.style.minHeight="1px"),this._lazyObserver.observe(s),requestAnimationFrame(()=>{if(t._lazyTriggered)return;const i=s.getBoundingClientRect(),r=typeof window<"u"?window.innerHeight:0,n=typeof window<"u"?window.innerWidth:0;i.top<r+120&&i.bottom>-120&&i.left<n&&i.right>0&&(t._lazyTriggered=!0,this._lazyObserver?.unobserve(s),Promise.resolve(t.render()).catch(o=>C._warn(`Lazy child render error (${t.id})`,o)))}))}}async _unmountChildren(){for(const e in this.children){const t=this.children[e];t&&t.unbindEvents()}}isMounted(){return this.element?.isConnected}getChildElementById(e,t=null){const s=e.startsWith("#")?e.substring(1):e;return t?t.querySelector(`#${s}`):this.element.querySelector(`#${s}`)}getChildElement(e){if(e.startsWith("#"))return this.getChildElementById(e);let t=this.element?.querySelector(`[data-container="${e}"]`);return t||this.getChildElementById(e)}getContainer(){return this.replaceById?this.parent?this.parent.getChildElementById(this.id):null:this.containerId?this.parent?this.parent.getChildElement(this.containerId):this.getChildElementById(this.containerId,document.body):null}async mount(e=null){if(await this.onBeforeMount(),e||(e=this.getContainer()),this.containerId&&!e){console.error(`Container not found for ${this.containerId}`);return}e&&this.replaceById?e.replaceWith(this.element):e?e.replaceChildren(this.element):!this.containerId&&this.parent?this.parent.element.appendChild(this.element):!this.containerId&&!this.parent&&this.options.allowAppendToBody?(console.log("APPENDING TO BODY!!!!"),document.body.appendChild(this.element)):console.error(`Container not found for ${this.containerId}`),await this.onAfterMount(),this.mounted=!0}async unmount(){!this.element||!this.element.parentNode||(await this.onBeforeUnmount(),await this._unmountChildren(),this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.events.unbind(),await this.onAfterUnmount(),this.mounted=!1)}async destroy(){try{this.events.unbind(),this._lazyObserver&&(this._lazyObserver.disconnect(),this._lazyObserver=null);for(const e in this.children){const t=this.children[e];t&&await Promise.resolve(t.destroy()).catch(s=>C._warn(`Child destroy error (${e})`,s))}this.mounted=!1,this.element&&this.element.parentNode&&(await this.onBeforeDestroy(),this.element.parentNode&&this.element.parentNode.removeChild(this.element),await this.onAfterDestroy())}catch(e){C._warn(`Destroy error in ${this.id}`,e)}}_ensureElement(){try{if(this.element&&this.element.tagName?.toLowerCase()===this.tagName)return this._syncAttrs(),this.element;const e=document.createElement(this.tagName);return this.element=e,this.el=e,this._syncAttrs(),e}catch(e){C._warn("ensureElement error",e);const t=document.createElement("div");return t.id=this.id||C._genId(),t}}_syncAttrs(){try{if(!this.element)return;this.id&&(this.element.id=this.id),this.element.className=this.className||"",this.style==null?this.element.removeAttribute("style"):this.element.style.cssText=String(this.style)}catch(e){C._warn("_syncAttrs error",e)}}bindEvents(){this.events.bind(this.element),this.enableTooltips&&this.initializeTooltips()}unbindEvents(){this.events.unbind(),this.enableTooltips&&this.disposeTooltips()}async renderTemplate(){const e=await this.getTemplate();if(!e)return"";const t=this.getPartials();return D.render(e,this,t)}renderTemplateString(e,t,s){return D.render(e,t,s)}getPartials(){return{}}async getTemplate(){if(this._templateCache&&this.cacheTemplate)return this._templateCache;const e=this.template||this.templateUrl;if(!e)throw new Error("Template not found");let t="";if(typeof e=="string")if(e.includes("<")||e.includes("{"))t=e;else try{let s=e;this.app||(this.app=this.getApp()),this.app&&this.app.basePath&&!s.startsWith("/")&&!s.startsWith("http://")&&!s.startsWith("https://")&&(s=`${this.app.basePath.endsWith("/")?this.app.basePath.slice(0,-1):this.app.basePath}/${s}`);const i=await fetch(s);if(!i.ok)throw new Error(`HTTP ${i.status}: ${i.statusText}`);t=await i.text()}catch(s){C._warn(`Failed to load template from ${e}: ${s}`),this.showError?.(`Failed to load template from ${e}: ${s.message}`)}else typeof e=="function"&&(t=await this.template(this.data,this.state));return this.cacheTemplate&&t&&typeof e!="function"&&(this._templateCache=t),t}getContextValue(e){const t=$.getContextData(this,e);return e&&e.startsWith("data.")&&t&&typeof t=="object"?$.wrapData(t,this):e&&e.startsWith("model.")&&e!=="model"&&t&&typeof t=="object"&&typeof t.getContextValue!="function"?$.wrapData(t,null):t}async handlePageNavigation(e){const t=e.getAttribute("data-page"),s=e.getAttribute("data-params");let i={};if(s)try{i=JSON.parse(s)}catch{console.warn("Invalid JSON in data-params:",s)}const r=this.getApp();if(r){r.showPage(t,i);return}const n=this.findRouter();n&&typeof n.navigateToPage=="function"?await n.navigateToPage(t,i):console.error(`No router found for page navigation to '${t}'`)}async handleHrefNavigation(e){const t=e.getAttribute("href");if(this.isExternalLink(t)||e.hasAttribute("data-external"))return;const s=this.findRouter();if(s){if(s.options&&s.options.mode==="param"&&t.startsWith("?")){const r="/"+t;await s.navigate(r);return}if(s.options&&s.options.mode==="hash"&&t.startsWith("#")){await s.navigate(t);return}const i=this.hrefToRoutePath(t);await s.navigate(i)}else console.warn("No router found for navigation, using default behavior"),window.location.href=t}isExternalLink(e){return e?e.startsWith("/")&&this.getApp()?!e.startsWith(this.findRouter().basePath):e.startsWith("#")||e.startsWith("mailto:")||e.startsWith("tel:")||e.startsWith("http://")||e.startsWith("https://")||e.startsWith("//"):!0}hrefToRoutePath(e){if(e.startsWith("/")){const t=this.findRouter();if(t&&t.options&&t.options.base){const s=t.options.base;if(e.startsWith(s))return e.substring(s.length)||"/"}return e}return e.startsWith("./")?e.substring(2):e}findRouter(){return this.getApp(),this.app?.router||null}getApp(){if(this.app)return this.app;const e=[window.__app__,window.MOJO?.app,window.APP,window.app,window.WebApp,window.matchUUID?window[window.matchUUID]():window[window.matchUUID]];return this.app=e.find(t=>t&&typeof t.showPage=="function")||null,this.app}handleActionError(e,t,s,i){this.showError(`Action '${e}' failed: ${t}`,s,i)}escapeHtml(e){if(typeof e!="string")return e;const t=document.createElement("div");return t.textContent=e,t.innerHTML}contains(e){if(typeof e=="string"){if(!this.element)return!1;e=document.getElementById(e)}return e?this.element.contains(e):!1}initializeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.disposeTooltips(),[...this.element.querySelectorAll('[data-bs-toggle="tooltip"]')].map(t=>{const s=t.getAttribute("data-tooltip-theme"),i=t.getAttribute("data-tooltip-size");let r="";s&&(r+=`tooltip-${s} `),i&&(r+=`tooltip-${i}`);const n={},a=r.trim();return a&&(n.customClass=a),new window.bootstrap.Tooltip(t,n)})}disposeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.element.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.dispose()})}async showError(e){console.error(`View ${this.id} error:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showError=="function"){await t.showError(e);return}alert(`Error: ${e}`)}async showSuccess(e){this.debug&&console.log(`View ${this.id} success:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showSuccess=="function"){await t.showSuccess(e);return}alert(`Success: ${e}`)}async showInfo(e){console.info(`View ${this.id} info:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showInfo=="function"){await t.showInfo(e);return}alert(`Info: ${e}`)}async showWarning(e){console.warn(`View ${this.id} warning:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showWarning=="function"){await t.showWarning(e);return}alert(`Warning: ${e}`)}async onActionCopyToClipboard(e,t){try{const i=(t?.closest("[data-clipboard]")||t)?.getAttribute("data-clipboard")||"";if(!i)return!0;if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(i);else{const a=document.createElement("textarea");a.value=i,document.body.appendChild(a),a.select(),document.execCommand("copy"),document.body.removeChild(a)}const r=t.querySelector("i"),n=r&&r.className;return r&&(r.className="bi bi-check",setTimeout(()=>{r.className=n},1e3)),!0}catch(s){return console.warn("Copy to clipboard failed:",s),!0}}static _genId(){return`view_${Math.random().toString(36).substr(2,9)}`}static _warn(e,t){try{t?console.warn(`[View] ${e}:`,t):console.warn(`[View] ${e}`)}catch{}}}Object.assign(C.prototype,Me);class x extends C{static _openDialogs=[];static _baseZIndex={backdrop:1050,modal:1055};static getFullscreenAwareZIndex(){return document.querySelector(".table-fullscreen")?{backdrop:10040,modal:10050}:x._baseZIndex}static fixAllBackdropStacking(){const e=document.querySelectorAll(".modal-backdrop"),t=x._openDialogs;if(e.length===0||t.length===0)return;const s=[...t].sort((n,a)=>(n._dialogZIndex||0)-(a._dialogZIndex||0)),r=document.querySelector(".table-fullscreen")||document.body;e.forEach((n,a)=>{if(a>=s.length)return;const o=s[a];n.style.zIndex=o._dialogZIndex-5,n.parentNode!==r&&r.appendChild(n)})}static updateAllBackdropStacking(){x.fixAllBackdropStacking()}static getMountTarget(){return document.querySelector(".table-fullscreen")||document.body}constructor(e={}){const t=e.id||`modal-${Date.now()}-${Math.random().toString(36).slice(2,7)}`;super({...e,id:t,tagName:"div",className:`modal ${e.fade!==!1?"fade":""} ${e.className||""}`.trim().replace(/\s+/g," "),attributes:{tabindex:"-1","aria-hidden":"true","aria-labelledby":e.labelledBy||`${t}-label`,"aria-describedby":e.describedBy||null,...e.attributes}}),this.modalId=t,this.title=e.title||"",this.titleId=`${this.modalId}-label`,this.size=e.size||"",this.centered=e.centered!==void 0?e.centered:!1,this.scrollable=e.scrollable!==void 0?e.scrollable:!1,this.autoSize=e.autoSize||e.size==="auto",this.backdrop=e.backdrop!==void 0?e.backdrop:!0,this.keyboard=e.keyboard!==void 0?e.keyboard:!0,this.focus=e.focus!==void 0?e.focus:!0,this.header=e.header!==void 0?e.header:!0,this.headerContent=e.headerContent||null,this.headerView=null,this.closeButton=e.closeButton!==void 0?e.closeButton:!0,this.contextMenu=e.contextMenu||null,this._processHeaderContent(this.headerContent),this.body=e.body??e.view??e.message??e.content??"",this.bodyView=null,this.bodyClass=e.bodyClass||"",this.noBodyPadding=e.noBodyPadding||!1,this.minWidth=e.minWidth||300,this.minHeight=e.minHeight||200,e.maxHeight&&(this.maxHeight=e.maxHeight),this.maxWidthPercent=e.maxWidthPercent||.9,this.maxHeightPercent=e.maxHeightPercent||.8,this._processBodyContent(this.body),this.footer=e.footer||null,this.footerView=null,this.footerClass=e.footerClass||"",this._processFooterContent(this.footer),this.buttons=e.buttons||null,this.onShow=e.onShow||null,this.onShown=e.onShown||null,this.onHide=e.onHide||null,this.onHidden=e.onHidden||null,this.onHidePrevented=e.onHidePrevented||null,this.autoShow=e.autoShow!==void 0?e.autoShow:!1,this.modal=null,this.relatedTarget=e.relatedTarget||null}_processBodyContent(e){if(e instanceof C||e&&typeof e=="object"&&typeof e.render=="function")this.bodyView=e,this.body="",this.addChild(this.bodyView);else if(typeof e=="function")try{const t=e();t instanceof C?(this.bodyView=t,this.body="",this.addChild(this.bodyView)):t instanceof Promise?(this.bodyPromise=t,this.body='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.body=t}catch(t){console.error("ModalView: error processing body function:",t),this.body=e}else this.body=e}_processHeaderContent(e){if(e instanceof C)this.headerView=e,this.headerContent=null,this.addChild(this.headerView);else if(typeof e=="function")try{const t=e();t instanceof C?(this.headerView=t,this.headerContent=null,this.addChild(this.headerView)):t instanceof Promise?(this.headerPromise=t,this.headerContent='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.headerContent=t}catch(t){console.error("ModalView: error processing headerContent function:",t),this.headerContent=e}else this.headerContent=e}_processFooterContent(e){if(e instanceof C)this.footerView=e,this.footer=null,this.addChild(this.footerView);else if(typeof e=="function")try{const t=e();t instanceof C?(this.footerView=t,this.footer=null,this.addChild(this.footerView)):t instanceof Promise?(this.footerPromise=t,this.footer='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.footer=t}catch(t){console.error("ModalView: error processing footer function:",t),this.footer=e}else this.footer=e}async getTemplate(){const e=["modal-dialog"];return this.size&&this.size!=="auto"&&(this.size.startsWith("fullscreen")?e.push(`modal-${this.size}`):["sm","lg","xl","xxl"].includes(this.size)&&(e.push(`modal-${this.size}`),["lg","xl","xxl"].includes(this.size)&&e.push("modal-fullscreen-sm-down"))),this.centered&&e.push("modal-dialog-centered"),this.scrollable&&(this.maxHeight?e.push("overflow-hidden"):e.push("modal-dialog-scrollable")),`
14
+ `}nl2br(e){return e==null?"":this.escapeHtml(String(e)).replace(/\r\n|\r|\n/g,"<br>")}code(e,t=""){if(e==null)return"";const s=t?`language-${this.escapeHtml(String(t))}`:"",i=this.escapeHtml(String(e));return`<pre class="bg-light p-2 rounded border"><code class="${s}">${i}</code></pre>`}register(e,t){if(typeof t!="function")throw new Error(`Formatter must be a function, got ${typeof t}`);return this.formatters.set(e.toLowerCase(),t),this}apply(e,t,...s){if(Array.isArray(t)&&t.every(i=>typeof i=="string"))return t.reduce((i,r)=>this.apply(r,i,...s),e);try{const i=this.formatters.get(e.toLowerCase());return i?i(t,...s):(console.warn(`Formatter '${e}' not found`),t)}catch(i){return console.error(`Error in formatter '${e}':`,i),t}}pipe(e,t,s=null){return t?this.parsePipeString(t,s).reduce((r,n)=>this.apply(n.name,r,...n.args),e):e}parsePipeString(e,t=null){const s=[],i=e.split("|").map(r=>r.trim());for(const r of i){const n=this.parseFormatter(r,t);n&&s.push(n)}return s}parseFormatter(e,t=null){const s=e.match(/^([a-zA-Z_]\w*)\s*\((.*)\)$/);if(s){const[,r,n]=s,a=n?this.parseArguments(n,t):[];return{name:r,args:a}}const i=e.match(/^([a-zA-Z_]\w*)(?::(.+))?$/);if(i){const[,r,n]=i,a=n?this.parseColonArguments(n,t):[];return{name:r,args:a}}return null}parseArguments(e,t=null){const s=[];let i="",r=!1,n=null,a=0;for(let o=0;o<e.length;o++){const l=e[o];!r&&(l==='"'||l==="'")?(r=!0,n=l,i+=l):r&&l===n&&e[o-1]!=="\\"?(r=!1,n=null,i+=l):!r&&l==="{"?(a++,i+=l):!r&&l==="}"?(a--,i+=l):!r&&a===0&&l===","?(s.push(this.parseValue(i.trim(),t)),i=""):i+=l}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseColonArguments(e,t=null){const s=[];let i="",r=!1,n=null;for(let a=0;a<e.length;a++){const o=e[a];!r&&(o==='"'||o==="'")?(r=!0,n=o,i+=o):r&&o===n&&e[a-1]!=="\\"?(r=!1,n=null,i+=o):!r&&o===":"?(s.push(this.parseValue(i.trim(),t)),i=""):i+=o}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseValue(e,t=null){if(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);if(e==="true")return!0;if(e==="false")return!1;if(e==="null")return null;if(e!=="undefined"){if(!isNaN(e)&&e!=="")return Number(e);if(e.startsWith("{")&&e.endsWith("}"))try{return JSON.parse(e)}catch{}if(t&&this.isIdentifier(e)){if(!e.includes(".")&&Object.prototype.hasOwnProperty.call(t,e))return t[e];if(t.get&&typeof t.get=="function"){const s=t.get(e);if(s!==void 0)return s}if(t.getContextValue&&typeof t.getContextValue=="function"){const s=t.getContextValue(e);if(s!==void 0)return s}if(e.includes(".")){const s=window.MOJOUtils||(typeof require<"u"?require("./MOJOUtils.js").default:null);if(s){const i=s.getNestedValue(t,e);if(i!==void 0)return i}}}return e}}isIdentifier(e){return/^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/.test(e)}date(e,t="MM/DD/YYYY"){if(!e)return"";e=this.normalizeEpoch(e);let s;if(e instanceof Date)s=e;else if(typeof e=="string")if(/^\d{4}-\d{2}-\d{2}$/.test(e)){const[a,o,l]=e.split("-").map(Number);s=new Date(a,o-1,l)}else s=new Date(e);else s=new Date(e);if(isNaN(s.getTime()))return String(e);const i={YYYY:s.getFullYear(),YY:String(s.getFullYear()).slice(-2),MMMM:s.toLocaleDateString("en-US",{month:"long"}),MMM:s.toLocaleDateString("en-US",{month:"short"}),MM:String(s.getMonth()+1).padStart(2,"0"),M:s.getMonth()+1,dddd:s.toLocaleDateString("en-US",{weekday:"long"}),ddd:s.toLocaleDateString("en-US",{weekday:"short"}),DD:String(s.getDate()).padStart(2,"0"),D:s.getDate()};let r=t;const n=new RegExp(`(${Object.keys(i).join("|")})`,"g");return r=r.replace(n,a=>i[a]||a),r}time(e,t="HH:mm:ss"){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const i=s.getHours(),r={HH:String(i).padStart(2,"0"),H:i,hh:String(i%12||12).padStart(2,"0"),h:i%12||12,mm:String(s.getMinutes()).padStart(2,"0"),m:s.getMinutes(),ss:String(s.getSeconds()).padStart(2,"0"),s:s.getSeconds(),A:i>=12?"PM":"AM",a:i>=12?"pm":"am"};let n=t;const a=Object.keys(r).sort((o,l)=>l.length-o.length);for(const o of a)n=n.replace(new RegExp(o,"g"),r[o]);return n}datetime(e,t="MM/DD/YYYY",s="HH:mm:ss"){e=this.normalizeEpoch(e);const i=this.date(e,t),r=this.time(e,s);return i&&r?`${i} ${r}`:""}datetime_tz(e,t="MM/DD/YYYY",s="HH:mm:ss",i={}){if(!e)return"";e=this.normalizeEpoch(e);const r=e instanceof Date?e:new Date(e);if(isNaN(r.getTime()))return String(e);const n=i&&i.locale||"en-US",a=i&&i.timeZone?i.timeZone:void 0,o=()=>{let k="";try{const se=new Intl.DateTimeFormat(n,{hour:"2-digit",minute:"2-digit",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(z=>z.type==="timeZoneName");if(k=se?se.value:"",k&&/^GMT[+-]/i.test(k))try{const ie=new Intl.DateTimeFormat(n,{timeStyle:"short",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(r).find(Fs=>Fs.type==="timeZoneName");ie&&ie.value&&!/^GMT[+-]/i.test(ie.value)&&(k=ie.value)}catch{}if(k&&/\s/.test(k)){const z=k.split(/\s+/).map(ie=>ie[0]).join("").toUpperCase();z.length>=2&&z.length<=4&&(k=z)}}catch{k=""}return k};if(!a){const k=this.date(r,t),Y=this.time(r,s),se=o();return k&&Y?`${k} ${Y} ${se}`.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(se=>se.type===k);return Y?Y.value:""},h=d("year"),u=d("month"),m=d("day"),p=d("hour"),f=d("minute"),g=d("second"),b=u?String(parseInt(u,10)):"",y=m?String(parseInt(m,10)):"",v=p?String(parseInt(p,10)):"",_=p?parseInt(p,10)%12||12:"",A=p?parseInt(p,10)>=12?"PM":"AM":"",E=A?A.toLowerCase():"",j=new Intl.DateTimeFormat(n,{timeZone:a,month:"long"}).format(r),I=new Intl.DateTimeFormat(n,{timeZone:a,month:"short"}).format(r),R=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"long"}).format(r),ae=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"short"}).format(r),be={YYYY:h,YY:h?h.slice(-2):"",MMMM:j,MMM:I,MM:u,M:b,dddd:R,ddd:ae,DD:m,D:y},ye={HH:p,H:v,hh:_!==""?String(_).padStart(2,"0"):"",h:_!==""?String(_):"",mm:f,m:f?String(parseInt(f,10)):"",ss:g,s:g?String(parseInt(g,10)):"",A,a:E},M=(k,Y)=>{if(!k)return"";const se=new RegExp(`(${Object.keys(Y).sort((z,ie)=>ie.length-z.length).join("|")})`,"g");return k.replace(se,z=>Y[z]??z)},H=M(t,be),It=M(s,ye),Ts=o();return H&&It?`${H} ${It} ${Ts}`.trim():""}normalizeEpoch(e){if(e instanceof Date)return e;if(typeof e=="string"){const t=Number(e);if(Number.isFinite(t))e=t;else{const s=Date.parse(e);return Number.isFinite(s)?s:""}}else typeof e!="number"&&(e=Number(e));if(isNaN(e))return"";if(e<1e11)return e*1e3;if(e>1e12&&e<1e13)return e;throw new Error("Value doesn't look like epoch seconds or ms")}date_range(e,t=null,s="MM/DD/YYYY"){if(!e)return"";const i=t||new Date,r=this.date(e,s),n=this.date(i,s);return!r||!n?"":`${r} - ${n}`}datetime_range(e,t=null,s="MM/DD/YYYY",i="HH:mm"){if(!e)return"";const r=t||new Date,n=this.datetime(e,s,i),a=this.datetime(r,s,i);return!n||!a?"":`${n} - ${a}`}relative(e,t=!1){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const r=s-new Date,n=Math.abs(r),a=Math.floor(n/1e3),o=Math.floor(a/60),l=Math.floor(o/60),d=Math.floor(l/24),h=r>0;if(t)return d>365?Math.floor(d/365)+"y":d>30?Math.floor(d/30)+"mo":d>7?Math.floor(d/7)+"w":d>0?d+"d":l>0?l+"h":o>0?o+"m":"now";if(d>365){const u=Math.floor(d/365),m=h?"in ":"",p=h?"":" ago";return m+u+" year"+(u>1?"s":"")+p}if(d>30){const u=Math.floor(d/30),m=h?"in ":"",p=h?"":" ago";return m+u+" month"+(u>1?"s":"")+p}if(d>7){const u=Math.floor(d/7),m=h?"in ":"",p=h?"":" ago";return m+u+" week"+(u>1?"s":"")+p}if(d===1)return h?"tomorrow":"yesterday";if(d>0){const u=h?"in ":"",m=h?"":" ago";return u+d+" days"+m}if(l>0){const u=h?"in ":"",m=h?"":" ago";return u+l+" hour"+(l>1?"s":"")+m}if(o>0){const u=h?"in ":"",m=h?"":" ago";return u+o+" minute"+(o>1?"s":"")+m}if(a>30){const u=h?"in ":"",m=h?"":" ago";return u+a+" seconds"+m}return"just now"}iso(e,t=!1){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);return isNaN(s.getTime())?String(e):t?s.toISOString().split("T")[0]:s.toISOString()}number(e,t=2,s="en-US"){const i=parseFloat(e);return isNaN(i)?String(e):i.toLocaleString(s,{minimumFractionDigits:t,maximumFractionDigits:t})}currency(e,t="$",s=2){const i=parseInt(e);if(isNaN(i))return String(e);const r=Math.abs(i).toString(),n=i<0?"-":"";let a,o;r.length<=2?(a="0",o=r.padStart(2,"0")):(a=r.slice(0,-2),o=r.slice(-2)),a=a.replace(/\B(?=(\d{3})+(?!\d))/g,",");let l;if(s===0)parseInt(o)>=50&&(a=(parseInt(a.replace(/,/g,""))+1).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")),l=a;else if(s===2)l=`${a}.${o}`;else{const d=o.slice(0,s).padEnd(s,"0");l=`${a}.${d}`}return n+t+l}percent(e,t=0,s=!0){const i=parseFloat(e);if(isNaN(i))return String(e);const r=s?i*100:i;return this.number(r,t)+"%"}filesize(e,t=!1,s=1){const i=parseInt(e);if(isNaN(i))return String(e);const r=t?["B","KiB","MiB","GiB","TiB"]:["B","KB","MB","GB","TB"],n=t?1024:1e3;let a=i,o=0;for(;a>=n&&o<r.length-1;)a/=n,o++;const l=o===0?0:s;return`${a.toFixed(l)} ${r[o]}`}ordinal(e,t=!1){const s=parseInt(e);if(isNaN(s))return String(e);const i=s%10,r=s%100;let n="th";return i===1&&r!==11?n="st":i===2&&r!==12?n="nd":i===3&&r!==13&&(n="rd"),t?n:s+n}compact(e,t=1){const s=parseFloat(e);if(isNaN(s))return String(e);const i=Math.abs(s),r=s<0?"-":"";return i>=1e9?r+(i/1e9).toFixed(t)+"B":i>=1e6?r+(i/1e6).toFixed(t)+"M":i>=1e3?r+(i/1e3).toFixed(t)+"K":String(s)}add(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s+i}subtract(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s-i}multiply(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s*i}divide(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)||i===0?e:s/i}capitalize(e,t=!0){const s=String(e);return s?t?s.replace(/\b\w/g,i=>i.toUpperCase()):s.charAt(0).toUpperCase()+s.slice(1):""}replace(e,t,s="",i="g"){if(e==null)return"";const r=String(e);if(t==null||t==="")return r;if(t instanceof RegExp)return r.replace(t,String(s));const n=String(t),a=n.match(/^\/(.+)\/([a-z]*)$/i);if(a){const[,o,l]=a;try{return r.replace(new RegExp(o,l),String(s))}catch{}}return String(i).includes("g")?r.split(n).join(String(s)):r.replace(n,String(s))}truncate(e,t=50,s="..."){const i=String(e);return i.length<=t?i:i.substring(0,t)+s}truncate_front(e,t=8,s="..."){const i=String(e);return i.length<=t?i:`${s}${i.slice(-t)}`}truncate_middle(e,t=8,s="***"){const i=String(e);if(i.length<=t)return i;const r=Math.floor(t/2),n=i.substring(0,r),a=i.substring(i.length-r);return`${n}${s}${a}`}slug(e,t="-"){return String(e).toLowerCase().replace(/[^\w\s-]/g,"").replace(/\s+/g,t).replace(new RegExp(`${t}+`,"g"),t).replace(new RegExp(`^${t}|${t}$`,"g"),"")}initials(e,t=2){return String(e).split(/\s+/).filter(r=>r.length>0).slice(0,t).map(r=>r.charAt(0).toUpperCase()).join("")}mask(e,t="*",s=4){const i=String(e);if(i.length<=s)return i;const r=t.repeat(Math.max(0,i.length-s)),n=i.slice(-s);return r+n}email(e,t={}){const s=String(e).trim();if(!s)return"";if(t.link===!1)return s;const i=t.subject?`?subject=${encodeURIComponent(t.subject)}`:"",r=t.body?`&body=${encodeURIComponent(t.body)}`:"",n=t.class?` class="${t.class}"`:"";return`<a href="mailto:${s}${i}${r}"${n}>${s}</a>`}phone(e,t="US",s=!0){let i=String(e).replace(/\D/g,""),r=i;return t==="US"&&(i.length===10?r=`(${i.slice(0,3)}) ${i.slice(3,6)}-${i.slice(6)}`:i.length===11&&i[0]==="1"&&(r=`+1 (${i.slice(1,4)}) ${i.slice(4,7)}-${i.slice(7)}`)),s?`<a href="tel:${i}">${r}</a>`:r}url(e,t=null,s=!0){let i=String(e).trim();return i?(/^https?:\/\//.test(i)||(i="https://"+i),`<a href="${i}"${s?' target="_blank"':""}${s?' rel="noopener noreferrer"':""}>${t||i}</a>`):""}badge(e,t="auto"){if(Array.isArray(e))return e.map(n=>this.badge(n,t)).join(" ");const s=String(e);if(typeof t=="string"&&t.includes("=")){const n=Object.fromEntries(t.split(",").map(l=>l.split("=").map(d=>d.trim()))),a=n[s]||n[s.toLowerCase()]||this.inferBadgeType(s);return`<span class="badge ${a?`bg-${a}`:"bg-secondary"}">${s}</span>`}const i=t==="auto"?this.inferBadgeType(s):t;return`<span class="badge ${i?`bg-${i}`:"bg-secondary"}">${s}</span>`}badgeClass(e,t="auto"){const s=String(e),i=t==="auto"?this.inferBadgeType(s):t;return i?`bg-${i}`:"bg-secondary"}inferBadgeType(e){const t=e.toLowerCase();return["active","pass","success","complete","completed","approved","done","true","on","yes"].includes(t)?"success":["error","failed","fail","rejected","deleted","cancelled","false","off","no","declined"].includes(t)?"danger":["warning","pending","review","processing","uploading"].includes(t)?"warning":["info","new","draft"].includes(t)?"info":(["inactive","disabled","archived","suspended"].includes(t),"secondary")}status(e){return this._status(e)}status_icon(e){return this._status(e,{},{},!1,!0)}status_text(e){return this._status(e,{},{},!0,!1)}_status(e,t={},s={},i=!1,r=!1){const n=String(e).toLowerCase(),a={active:"bi bi-check-circle-fill",approved:"bi bi-check-circle-fill",declined:"bi bi-x-circle-fill",inactive:"bi bi-pause-circle-fill",pending:"bi bi-clock-fill",success:"bi bi-check-circle-fill",error:"bi bi-exclamation-triangle-fill",warning:"bi bi-exclamation-triangle-fill"},o={active:"success",approved:"success",declined:"danger",inactive:"secondary",pending:"warning",success:"success",error:"danger",warning:"warning"},l=t[n]||a[n]||"",d=s[n]||o[n]||"secondary";let h="";!i&&l&&(h=`<i class="${l}"></i>`);let u="";return r||(u=e),`<span class="text-${d}">${h}${h?" ":""}${u}</span>`}boolean(e,t="True",s="False",i=!1){const r=e?t:s;return i?`<span class="text-${e?"success":"danger"}">${r}</span>`:r}bool(e){return e==null||e===0||e===""||e===!1||e==="false"?!1:e===!0||e==="true"?!0:!(Array.isArray(e)&&e.length===0||e&&typeof e=="object"&&e.constructor===Object&&Object.keys(e).length===0)}icon(e,t={}){const s=String(e).toLowerCase(),i=t[s]||"";return i?`<i class="${i}"></i>`:""}yesnoicon(e,t="bi bi-check-circle-fill text-success",s="bi bi-x-circle-fill text-danger"){return e?`<i class="${t}"></i>`:`<i class="${s}"></i>`}image(e,t="thumbnail",s="img-fluid",i=""){const r=this._extractImageUrl(e,t);return r?`<img src="${r}" class="${s}" alt="${i}" />`:""}avatar(e,t="md",s="rounded-circle",i=""){const r=this._extractImageUrl(e,"square_sm")||Pt,n={xs:"width: 1.5rem; height: 1.5rem;",sm:"width: 2rem; height: 2rem;",md:"width: 3rem; height: 3rem;",lg:"width: 4rem; height: 4rem;",xl:"width: 5rem; height: 5rem;"},a=n[t]||n.md,l=`object-fit-cover ${s}`.trim();return`<img src="${r}" class="${l}" style="${a}" alt="${i}" />`}tooltip(e,t="",s="top",i=""){if(e==null)return"";const r=String(e),n=i==="html"?t:this.escapeHtml(t);return`<span data-bs-toggle="tooltip" data-bs-placement="${s}" ${i==="html"?'data-bs-html="true"':""} data-bs-title="${n}">${r}</span>`}_extractImageUrl(e,t="thumbnail"){if(!e)return null;if(typeof e=="string")return e;if(typeof e=="object"){if(e.attributes&&(e=e.attributes),t==="thumbnail"&&e.thumbnail&&typeof e.thumbnail=="string")return e.thumbnail;if(e.renditions&&typeof e.renditions=="object"){const s=e.renditions[t];if(s&&s.url)return s.url;const i=Object.values(e.renditions);if(i.length>0&&i[0].url)return i[0].url}if(e.url)return e.url}return null}default(e,t=""){return e==null||e===""?t:e}equals(e,t,s,i=""){return e==t?s:i}plural(e,t,s=null,i=!0){if(e==null||t===null||t===void 0)return i?`${e} ${t}`:t||"";const r=parseInt(e);if(isNaN(r))return i?`${e} ${t}`:t||"";const n=Math.abs(r)===1?t:s||t+"s";return i?`${r} ${n}`:n}formatList(e,t={}){if(!Array.isArray(e))return String(e);const{conjunction:s="and",limit:i=null,moreText:r="others"}=t;if(e.length===0)return"";if(e.length===1)return String(e[0]);let n=e.slice(),a=!1;if(i&&e.length>i&&(n=e.slice(0,i),a=!0),a){const o=e.length-i;return`${n.join(", ")}, ${s} ${o} ${r}`}return n.length===2?`${n[0]} ${s} ${n[1]}`:`${n.slice(0,-1).join(", ")}, ${s} ${n[n.length-1]}`}duration(e,t="ms",s=!1,i=2){if(e==null)return"";const r=parseFloat(e);if(isNaN(r))return String(e);let n;switch(t){case"s":case"sec":case"seconds":n=r*1e3;break;case"m":case"min":case"minutes":n=r*6e4;break;case"h":case"hr":case"hours":n=r*36e5;break;case"d":case"day":case"days":n=r*864e5;break;default:n=r}const a=[{name:"day",short:"d",value:864e5},{name:"hour",short:"h",value:36e5},{name:"minute",short:"m",value:6e4},{name:"second",short:"s",value:1e3}];if(n===0)return s?"0s":"0 seconds";const o=Math.abs(n),l=n<0?"-":"",d=[];let h=o;for(const u of a)if(h>=u.value){const m=Math.floor(h/u.value);h=h%u.value;const p=s?u.short:m===1?u.name:u.name+"s";if(d.push(s?`${m}${p}`:`${m} ${p}`),d.length>=i)break}return d.length===0?s?`${Math.round(o)}ms`:`${Math.round(o)} milliseconds`:l+(s?d.join(""):d.join(" "))}hash(e,t=8,s="",i="..."){if(e==null)return"";const r=String(e);return r.length<=t?s+r:s+r.substring(0,t)+i}stripHtml(e){return e==null?"":String(e).replace(/<[^>]*>/g,"")}highlight(e,t,s="highlight"){if(e==null||!t)return String(e||"");const i=String(t).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(`(${i})`,"gi");return String(e).replace(r,`<mark class="${s}">$1</mark>`)}hex(e,t=!1,s=!1){if(e==null)return"";let i="";const r=n=>Array.from(n).map(a=>a.toString(16).padStart(2,"0")).join("");if(typeof e=="number"){let n=Math.abs(Math.trunc(e)).toString(16);n.length%2&&(n="0"+n),i=n}else if(e instanceof Uint8Array)i=r(e);else if(e instanceof ArrayBuffer)i=r(new Uint8Array(e));else if(Array.isArray(e)&&e.every(n=>typeof n=="number"))i=r(Uint8Array.from(e.map(n=>n&255)));else{const a=new TextEncoder().encode(String(e));i=r(a)}return t&&(i=i.toUpperCase()),(s?"0x":"")+i}unhex(e){if(e==null)return"";let t=String(e).trim();if((t.startsWith("0x")||t.startsWith("0X"))&&(t=t.slice(2)),t=t.replace(/\s+/g,""),t.length===0)return"";t.length%2!==0&&(t="0"+t);const s=new Uint8Array(t.length/2);for(let i=0;i<t.length;i+=2){const r=parseInt(t.slice(i,i+2),16);if(Number.isNaN(r))return String(e);s[i/2]=r}try{return new TextDecoder().decode(s)}catch{let r="";for(const n of s)r+=String.fromCharCode(n);return r}}json(e,t=2){try{return JSON.stringify(e,null,t)}catch{return String(e)}}has(e){return this.formatters.has(e.toLowerCase())}unregister(e){return this.formatters.delete(e.toLowerCase())}listFormatters(){return Array.from(this.formatters.keys()).sort()}iter(e){return e==null?[]:Array.isArray(e)?e:typeof e=="object"?Object.entries(e).map(([t,s])=>({key:t,value:s})):[{key:"0",value:e}]}}const P=new Nt;window.dataFormatter=P;const et=new Set(["__proto__","constructor","prototype"]),tt=(c,e)=>c!=null&&Object.prototype.hasOwnProperty.call(c,e);class ${static getContextData(e,t){if(!t||e==null)return;let s=t,i="",r=0,n=-1;for(let o=0;o<t.length;o++){const l=t[o];if(l==="(")r++;else if(l===")")r--;else if(l==="|"&&r===0){n=o;break}}n>-1&&(s=t.substring(0,n).trim(),i=t.substring(n+1).trim());const a=this.getNestedValue(e,s);return i?P.pipe(a,i,e):a}static getNestedValue(e,t){if(!t||e==null||t.split(".").some(r=>et.has(r)))return;if(!t.includes(".")){if(t in e){const r=e[t];return typeof r=="function"?r===Object.prototype[t]?void 0:r.call(e):r}return}const s=t.split(".");let i=e;for(let r=0;r<s.length;r++){const n=s[r];if(i==null)return;if(r===0)if(tt(i,n)){const a=i[n];typeof a=="function"?i=a.call(e):i=a}else return;else{if(i&&typeof i.getContextValue=="function"){const a=s.slice(r).join(".");return i.getContextValue(a)}if(Array.isArray(i)&&!isNaN(n))i=i[parseInt(n)];else if(tt(i,n))i=i[n];else return}}return i}static isNullOrUndefined(e){return e==null}static deepClone(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(e instanceof Array)return e.map(t=>this.deepClone(t));if(e instanceof Object){const t={};for(const s in e)e.hasOwnProperty(s)&&(t[s]=this.deepClone(e[s]));return t}}static deepMerge(e,...t){if(!t.length)return e;const s=t.shift();if(this.isObject(e)&&this.isObject(s))for(const i in s)this.isObject(s[i])?(e[i]||Object.assign(e,{[i]:{}}),this.deepMerge(e[i],s[i])):Object.assign(e,{[i]:s[i]});return this.deepMerge(e,...t)}static isObject(e){return e&&typeof e=="object"&&!Array.isArray(e)}static debounce(e,t){let s;return function(...r){const n=()=>{clearTimeout(s),e(...r)};clearTimeout(s),s=setTimeout(n,t)}}static throttle(e,t){let s;return function(...i){s||(e.apply(this,i),s=!0,setTimeout(()=>s=!1,t))}}static generateId(e=""){const t=Date.now().toString(36),s=Math.random().toString(36).substr(2,9);return e?`${e}_${t}_${s}`:`${t}_${s}`}static escapeHtml(e){const t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(e).replace(/[&<>"'`=\/]/g,s=>t[s])}static checkPasswordStrength(e){if(!e||typeof e!="string")return{score:0,strength:"invalid",feedback:["Password must be a non-empty string"],details:{length:0,hasLowercase:!1,hasUppercase:!1,hasNumbers:!1,hasSpecialChars:!1,hasCommonPatterns:!1,isCommonPassword:!1}};const t=[],s={length:e.length,hasLowercase:/[a-z]/.test(e),hasUppercase:/[A-Z]/.test(e),hasNumbers:/[0-9]/.test(e),hasSpecialChars:/[^a-zA-Z0-9]/.test(e),hasCommonPatterns:!1,isCommonPassword:!1};let i=0;e.length<6?t.push("Password should be at least 6 characters long"):e.length<8?(i+=1,t.push("Consider using at least 8 characters for better security")):e.length<12?i+=3:i+=4,s.hasLowercase?i+=1:t.push("Include lowercase letters"),s.hasUppercase?i+=1:t.push("Include uppercase letters"),s.hasNumbers?i+=1:t.push("Include numbers"),s.hasSpecialChars?i+=2:t.push("Include special characters (!@#$%^&* etc.)");const r=[/123/,/abc/i,/qwerty/i,/asdf/i,/(.)\1{2,}/,/password/i,/admin/i,/user/i,/login/i];for(const o of r)if(o.test(e)){s.hasCommonPatterns=!0,i-=1,t.push("Avoid common patterns and dictionary words");break}["123456","password","123456789","12345678","12345","1234567","1234567890","qwerty","abc123","111111","123123","admin","letmein","welcome","monkey","password123","123qwe","qwerty123","000000","dragon","sunshine","princess","azerty","1234","iloveyou","trustno1","superman","shadow","master","jennifer"].includes(e.toLowerCase())&&(s.isCommonPassword=!0,i=Math.max(0,i-3),t.push("This password is too common and easily guessed"));let a;return i<2?a="very-weak":i<4?a="weak":i<6?a="fair":i<8?a="good":a="strong",i>=7&&t.length===0?t.push("Strong password! Consider using a password manager."):i>=5&&t.length<=1&&t.push("Good password strength. Consider adding more variety."),{score:Math.max(0,i),strength:a,feedback:t,details:s}}static generatePassword(e={}){const s={...{length:12,includeLowercase:!0,includeUppercase:!0,includeNumbers:!0,includeSpecialChars:!0,customChars:"",excludeAmbiguous:!1},...e};if(s.length<4)throw new Error("Password length must be at least 4 characters");let i="abcdefghijklmnopqrstuvwxyz",r="ABCDEFGHIJKLMNOPQRSTUVWXYZ",n="0123456789",a="!@#$%^&*()_+-=[]{}|;:,.<>?";s.excludeAmbiguous&&(i=i.replace(/[il]/g,""),r=r.replace(/[IOL]/g,""),n=n.replace(/[01]/g,""),a=a.replace(/[|]/g,""));let o="";const l=[];if(s.customChars?o=s.customChars:(s.includeLowercase&&(o+=i,l.push(i[Math.floor(Math.random()*i.length)])),s.includeUppercase&&(o+=r,l.push(r[Math.floor(Math.random()*r.length)])),s.includeNumbers&&(o+=n,l.push(n[Math.floor(Math.random()*n.length)])),s.includeSpecialChars&&(o+=a,l.push(a[Math.floor(Math.random()*a.length)]))),!o)throw new Error("No character types selected for password generation");let d="";for(const h of l)d+=h;for(let h=d.length;h<s.length;h++)d+=o[Math.floor(Math.random()*o.length)];return d.split("").sort(()=>Math.random()-.5).join("")}static parseQueryString(e){const t={},s=new URLSearchParams(e);for(const[i,r]of s.entries())t[i]=r;return t}static toQueryString(e){return new URLSearchParams(e).toString()}static wrapData(e,t=null,s=3){return!e||typeof e!="object"||e instanceof Date||e instanceof RegExp||e instanceof Error||s<=0||typeof e.getContextValue=="function"?e:Array.isArray(e)?e.map(i=>i&&typeof i=="object"&&!i.getContextValue?new Fe(i,t):i):new Fe(e,t)}}class Fe{constructor(e,t=null){if(Object.defineProperty(this,"_data",{value:e,writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(this,"_rootContext",{value:t,writable:!1,enumerable:!1,configurable:!1}),e&&typeof e=="object"){for(const s in e)if(e.hasOwnProperty(s)){const i=e[s];this[s]=$.wrapData(i,t)}}}getContextValue(e){let t=e,s="",i=0,r=-1;for(let a=0;a<e.length;a++){const o=e[a];if(o==="(")i++;else if(o===")")i--;else if(o==="|"&&i===0){r=a;break}}r>-1&&(t=e.substring(0,r).trim(),s=e.substring(r+1).trim());let n;return t in this&&!et.has(t)&&t!=="_data"&&t!=="_rootContext"?n=this[t]:n=$.getNestedValue(this._data,t),s&&n!==void 0?P.pipe(n,s,this._rootContext||this._data):n}has(e){return this._data&&this._data.hasOwnProperty(e)}toJSON(){return this._data}}$.DataWrapper=Fe,typeof window<"u"&&(window.utils=$);const Ot=new Set(["__proto__","constructor","prototype"]),Rt=Object.prototype.toString,oe=Array.isArray||function(c){return Rt.call(c)==="[object Array]"},ue=function(c){return typeof c=="function"},st=function(c){return c!==null&&typeof c=="object"};function jt(){return typeof window>"u"?null:window.MOJO?.dataFormatter?window.MOJO.dataFormatter:window.dataFormatter?window.dataFormatter:null}const it=function(c){const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(c).replace(/[&<>"'`=\/]/g,function(t){return e[t]})};class rt{constructor(e){this.string=e,this.tail=e,this.pos=0}eos(){return this.tail===""}scan(e){const t=this.tail.match(e);if(!t||t.index!==0)return"";const s=t[0];return this.tail=this.tail.substring(s.length),this.pos+=s.length,s}scanUntil(e){const t=this.tail.search(e);let s;switch(t){case-1:s=this.tail,this.tail="";break;case 0:s="";break;default:s=this.tail.substring(0,t),this.tail=this.tail.substring(t)}return this.pos+=s.length,s}}class we{constructor(e,t){this.view=e,this.cache={".":this.view},this.parent=t,this.view?._cacheId||this.view&&typeof this.view=="object"&&(this.view._cacheId=Math.random().toString(36).substring(2))}push(e){return new we(e,this)}lookup(e){if(this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;if(this.renderCache.has(i))return this.renderCache.get(i)}if(e===".")return this.view;if(e&&(e.startsWith(".")?e.slice(1):e).split("|")[0].split(".").some(r=>Ot.has(r)))return;if(e&&e.startsWith(".")){let i=e.substring(1),r=!1,n=null;const a=i.indexOf("|");if(a!==-1&&(n=i.substring(a+1).trim(),i=i.substring(0,a).trim()),i.endsWith("|iter")&&(i=i.substring(0,i.length-5),r=!0),this.view&&typeof this.view=="object"){let o;if(typeof this.view.getContextValue=="function")try{o=this.view.getContextValue(i),o!==void 0&&ue(o)&&(o=o.call(this.view))}catch{o=void 0}if(o===void 0&&(i.indexOf(".")>0?o=$.getNestedValue(this.view,i):i in this.view&&(o=this.view[i],ue(o)&&(o===Object.prototype[i]?o=void 0:o=o.call(this.view)))),n&&o!==void 0)try{const l=jt();l&&typeof l.pipe=="function"&&(o=l.pipe(o,n,this))}catch{}return oe(o)?r?o:o.length>0:st(o)?r?Object.entries(o).map(([l,d])=>({key:l,value:d})):Object.keys(o).length>0:o}return}const t=this.cache;let s;if(t.hasOwnProperty(e))s=t[e];else{let i=this,r,n,a,o=!1;for(;i;){if(i.view&&typeof i.view.getContextValue=="function")try{r=i.view.getContextValue(e),r!==void 0&&(o=!0)}catch{o=!1}if(!o)if(e.indexOf(".")>0)for(r=i.view,n=e.split("."),a=0;r!=null&&a<n.length;)if(r&&typeof r.getContextValue=="function"&&a<n.length)try{const l=n.slice(a).join(".");r=r.getContextValue(l),a=n.length,r!==void 0&&(o=!0)}catch{a===n.length-1&&(o=Ee(r,n[a])||nt(r,n[a])),r=r[n[a++]]}else a===n.length-1&&(o=Ee(r,n[a])||nt(r,n[a])),r=r[n[a++]];else r=i.view[e],o=Ee(i.view,e);if(o){s=r;break}i=i.parent}t[e]=s}if(ue(s)){const i=e.split("|")[0].split(".").pop();if(s===Object.prototype[i])s=void 0;else try{s=s.call(this.view)}catch(r){if(r instanceof TypeError&&/^Class constructor /.test(r.message))s=void 0;else throw r}}if(this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;this.renderCache.set(i,s)}return s}}function Ee(c,e){return c!=null&&typeof c=="object"&&e in c}function nt(c,e){return c!=null&&typeof c!="object"&&c.hasOwnProperty&&c.hasOwnProperty(e)}class at{constructor(){this.templateCache=new Map}clearCache(){this.templateCache.clear()}parse(e,t){t=t||["{{","}}"];const s=e+":"+t.join(":");let i=this.templateCache.get(s);return i==null&&(i=this.parseTemplate(e,t),this.templateCache.set(s,i)),i}parseTemplate(e,t){if(!e)return[];const s=t[0],i=t[1],r=new rt(e),n=[];let a,o,l,d,h;const u=new RegExp(De(s)+"\\s*"),m=new RegExp("\\s*"+De(i)),p=new RegExp("\\s*"+De("}"+i));for(;!r.eos();){if(a=r.pos,l=r.scanUntil(u),l)for(let f=0;f<l.length;++f)d=l.charAt(f),d===`
15
+ `?n.push(["text",d]):n.push(["text",d]);if(!r.scan(u))break;if(o=r.scan(/[#^\/>{&=!]/),o||(o="name"),r.scan(/\s*/),o==="="?(l=r.scanUntil(/\s*=/),r.scan(/\s*=/),r.scanUntil(m)):o==="{"?(l=r.scanUntil(p),r.scan(p),o="&"):l=r.scanUntil(m),r.scan(m),o==="#"||o==="^")h=[o,l,a,r.pos],n.push(h);else if(o==="/"){let f;for(let g=n.length-1;g>=0;--g)if((n[g][0]==="#"||n[g][0]==="^")&&n[g][1]===l){f=n[g];break}f&&f.length===4&&f.push(r.pos),n.push([o,l,a,r.pos])}else n.push([o,l,a,r.pos])}return this.nestSections(this.squashTokens(n))}squashTokens(e){const t=[];let s,i;for(let r=0;r<e.length;++r)s=e[r],s&&(s[0]==="text"&&i&&i[0]==="text"?(i[1]+=s[1],i[3]=s[3]):(t.push(s),i=s));return t}nestSections(e){const t=[];let s=t;const i=[];for(let r=0;r<e.length;++r){const n=e[r];switch(n[0]){case"#":case"^":const a=[n[0],n[1],n[2],n[3],[],n[4]||null];s.push(a),i.push(a),s=a[4];break;case"/":const o=i.pop();o&&(o[5]=n[2],s=i.length>0?i[i.length-1][4]:t);break;default:s.push(n)}}return t}render(e,t,s,i){const r=this.getConfigTags(i)||["{{","}}"],n=this.parse(e,r),a=new Map;return this.renderTokens(n,new we(t),s,e,i,a)}renderTokens(e,t,s,i,r,n){n&&!t.renderCache&&(t.renderCache=n);let a="";for(let o=0;o<e.length;++o){const l=e[o];let d;switch(l[0]){case"#":if(d=t.lookup(l[1]),!d)continue;const h=l[4];if(!h||!oe(h)){console.warn(`MUSTACHE WARNING - Section ${l[1]} has no child tokens:`,l);continue}if(oe(d))for(let u=0;u<d.length;++u){const m=t.push(d[u]);t.renderCache&&(m.renderCache=t.renderCache);const p=this.renderTokens(h,m,s,i,r,n);a+=p}else if(typeof d=="object"||typeof d=="string"||typeof d=="number"){const u=t.push(d);t.renderCache&&(u.renderCache=t.renderCache),a+=this.renderTokens(h,u,s,i,r,n)}else if(ue(d)){const u=i==null?null:i.slice(l[3],l[5]);d=d.call(t.view,u,m=>this.render(m,t.view,s,r)),d!=null&&(a+=d)}else d&&(a+=this.renderTokens(h,t,s,i,r,n));break;case"^":if(d=t.lookup(l[1]),!d||oe(d)&&d.length===0){const u=l[4];u&&oe(u)&&(a+=this.renderTokens(u,t,s,i,r,n))}break;case">":if(!s)continue;d=ue(s)?s(l[1]):s[l[1]],d!=null&&(a+=this.render(d,t.view,s,r));break;case"&":d=t.lookup(l[1]),d!=null&&(a+=d);break;case"name":d=t.lookup(l[1]),d!=null&&(a+=it(d));break;case"text":a+=l[1];break}}return a}getConfigTags(e){return st(e)&&oe(e.tags)?e.tags:null}}function De(c){return c.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}const Me=new at,D={name:"MOJO Mustache",version:"1.0.0",tags:["{{","}}"],Scanner:rt,Context:we,Writer:at,escape:it,clearCache(){return Me.clearCache()},parse(c,e){return Me.parse(c,e)},render(c,e,t,s){if(typeof c!="string")throw new TypeError('Invalid template! Template should be a "string"');return e&&typeof e=="object"&&!e.getContextValue&&typeof e.toJSON!="function"&&(e=$.wrapData(e)),Me.render(c,e,t,s)}};class Ht{constructor(e){this.view=e,this.domListeners=[],this.debounceTimers=new Map}_enterDispatchChain(e){const t=e._mojoDispatch;let s;return e._mojoDispatch=new Promise(i=>{s=i}),{prior:t,done:s}}bind(e){if(this.unbind(),!e)return;const t=async a=>{const{prior:o,done:l}=this._enterDispatchChain(a);try{o&&await o;const d=a.target.closest("[data-action]");if(d&&this.shouldHandle(d,a)){const u=d.getAttribute("data-action");if(d.tagName==="A"&&a.preventDefault(),this.hideTooltip(d),await this.dispatch(u,a,d)){a.preventDefault(),a.stopPropagation(),a.handledByChild=!0;return}}const h=a.target.closest("a[href], [data-page]");if(h&&!h.hasAttribute("data-action")&&this.shouldHandle(h,a)){if(a.ctrlKey||a.metaKey||a.shiftKey||a.button===1)return;if(h.tagName==="A"){const u=h.getAttribute("href");if(u&&u!=="#"&&!u.startsWith("#")&&(this.view.isExternalLink(u)||h.hasAttribute("data-external")))return}this.hideTooltip(h),a.preventDefault(),a.stopPropagation(),a.handledByChild=!0,h.hasAttribute("data-page")?await this.view.handlePageNavigation(h):await this.view.handleHrefNavigation(h)}}finally{l()}},s=async a=>{const{prior:o,done:l}=this._enterDispatchChain(a);try{o&&await o;const d=a.target.closest("[data-change-action]");if(d&&this.shouldHandle(d,a)){const u=d.getAttribute("data-change-action");await this.dispatchChange(u,a,d)&&(a.stopPropagation(),a.handledByChild=!0);return}const h=a.target.closest("[data-action]");if(h&&this.isFormControl(h)&&this.shouldHandle(h,a)){const u=h.getAttribute("data-action");await this.dispatch(u,a,h)&&(a.stopPropagation(),a.handledByChild=!0)}}finally{l()}},i=a=>{const o=a.target.closest("[data-change-action]");if(o&&this.shouldHandle(o,a)&&a.target.matches('[data-filter="live-search"]')){const m=o.getAttribute("data-change-action"),p=parseInt(o.getAttribute("data-filter-debounce"))||300,f=`change-${m}-${o.getAttribute("data-container")||"default"}`;this.debounceTimers.has(f)&&clearTimeout(this.debounceTimers.get(f));const g=setTimeout(()=>{this.debounceTimers.delete(f),this.dispatchChange(m,a,o).then(b=>{b&&(a.stopPropagation(),a.handledByChild=!0)})},p);this.debounceTimers.set(f,g);return}const l=a.target.closest("[data-action]");if(!l||!this.isFormControl(l)||l.hasAttribute("data-change-action")||!this.shouldHandle(l,a))return;const d=l.getAttribute("data-action"),h=l.getAttribute("data-action-debounce"),u=h!=null&&parseInt(h)||0;if(u>0){const m=`action-${d}-${l.getAttribute("data-container")||"default"}`;this.debounceTimers.has(m)&&clearTimeout(this.debounceTimers.get(m));const p=setTimeout(()=>{this.debounceTimers.delete(m),this.dispatch(d,a,l).then(f=>{f&&(a.stopPropagation(),a.handledByChild=!0)})},u);this.debounceTimers.set(m,p);return}this.dispatch(d,a,l).then(m=>{m&&(a.stopPropagation(),a.handledByChild=!0)})},r=async a=>{if(a.target.matches('[data-filter="search"]'))return;const o=a.target.closest("[data-keydown-action]")||a.target.closest("[data-change-action]");if(!o)return;const{prior:l,done:d}=this._enterDispatchChain(a);try{if(l&&await l,!this.shouldHandle(o,a))return;let h=["Enter"];if(o.getAttribute("data-change-keys")&&(h=o.getAttribute("data-change-keys").split(",").map(u=>u.trim())),h.includes("*")||h.includes(a.key)){const u=o.getAttribute("data-keydown-action")||o.getAttribute("data-change-action");await this.dispatch(u,a,o)&&(a.preventDefault(),a.stopPropagation(),a.handledByChild=!0)}}finally{d()}},n=a=>{const o=a.target.closest("form[data-action]");if(!o||!this.shouldHandle(o,a))return;a.preventDefault();const l=o.getAttribute("data-action");this.dispatch(l,a,o)};e.addEventListener("click",t),e.addEventListener("change",s),e.addEventListener("input",i),e.addEventListener("keydown",r),e.addEventListener("submit",n),this.domListeners.push({el:e,type:"click",fn:t},{el:e,type:"change",fn:s},{el:e,type:"input",fn:i},{el:e,type:"keydown",fn:r},{el:e,type:"submit",fn:n})}unbind(){for(const{el:e,type:t,fn:s}of this.domListeners)e.removeEventListener(t,s);this.domListeners=[];for(const e of this.debounceTimers.values())clearTimeout(e);this.debounceTimers.clear()}hideDropdown(e){const s=e.closest(".dropdown-menu").closest(".dropdown");if(!s)return;const i=s.querySelector('[data-bs-toggle="dropdown"]');i&&window.bootstrap?.Dropdown&&window.bootstrap.Dropdown.getInstance(i)?.hide()}hideTooltip(e){if(e&&window.bootstrap?.Tooltip){const t=window.bootstrap.Tooltip.getInstance(e);t&&t.dispose()}}hideAllTooltips(){window.bootstrap?.Tooltip&&document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.hide()})}async dispatch(e,t,s){const i=this.view,r=l=>l.includes("-")?l.split("-").map(d=>d[0].toUpperCase()+d.slice(1)).join(""):l[0].toUpperCase()+l.slice(1),n=`handleAction${r(e)}`;if(typeof i[n]=="function")try{return t.preventDefault(),await i[n](t,s),!0}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const a=`onAction${r(e)}`;if(typeof i[a]=="function")try{return await i[a](t,s)?(s.closest(".dropdown-menu")&&this.hideDropdown(s),t.preventDefault(),t.stopPropagation(),!0):!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const o=`onPassThruAction${r(e)}`;if(typeof i[o]=="function")try{return await i[o](t,s),!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}if(typeof i.onActionDefault=="function")try{return await i.onActionDefault(e,t,s)}catch(l){return console.error(`Error in default action handler for ${e}:`,l),i.handleActionError(e,l,t,s),!0}return i.emit?.(`action:${e}`,{action:e,event:t,element:s}),!1}async dispatchChange(e,t,s){const i=this.view,n=`onChange${(a=>a.includes("-")?a.split("-").map(o=>o[0].toUpperCase()+o.slice(1)).join(""):a[0].toUpperCase()+a.slice(1))(e)}`;if(typeof i[n]=="function")try{return await i[n](t,s),!0}catch(a){return console.error(`Error in onChange ${e}:`,a),i.handleActionError?.(e,a,t,s),!0}return await this.dispatch(e,t,s)}isFormControl(e){if(!e||!e.tagName)return!1;const t=e.tagName;return t==="INPUT"||t==="TEXTAREA"||t==="SELECT"}shouldHandle(e,t){return!!(this.owns(e)||this.contains(e)&&!t.handledByChild)}owns(e){const t=this.view.element;if(!t||!t.contains(e))return!1;for(const s of Object.values(this.view.children))if(s.element&&s.element.contains(e))return!1;return!0}contains(e){return!!this.view.element&&this.view.element.contains(e)}}const Ie={on(c,e,t){this._listeners||(this._listeners={}),this._listeners[c]||(this._listeners[c]=[]);const s={callback:e,context:t,fn:t?e.bind(t):e};return this._listeners[c].push(s),this},off(c,e,t){return!this._listeners||!this._listeners[c]?this:(e?(this._listeners[c]=this._listeners[c].filter(s=>s.callback!==e||arguments.length===3&&s.context!==t),this._listeners[c].length===0&&delete this._listeners[c]):delete this._listeners[c],this)},once(c,e,t){const s=(...i)=>{this.off(c,s),(t?e.bind(t):e).apply(t||this,i)};return this.on(c,s),this},emit(c,...e){if(!this._listeners||!this._listeners[c])return this;const t=this._listeners[c].slice();for(const s of t)try{s.fn.apply(s.context||this,e)}catch(i){console&&console.error&&console.error(`Error in ${c} event handler:`,i)}return this}};typeof window<"u"&&(window.Mustache=D);class C{constructor(e={}){this.tagName=e.tagName??"div",this.className=e.className??"mojo-view",this.style=e.style??null,this.id=e.id??C._genId(),this.containerId=e.containerId??null,this.container=e.container??null,typeof this.container=="string"&&(this.containerId=this.container,this.container=null),this.parent=e.parent??null,this.children=e.children??{},this.template=e.template||e.templateUrl||"",this.data=e.data??{},this.isRendering=!1,this.lastRenderTime=0,this.mounted=!1,this.debug=e.debug??!1,this.app=e.app??null,this.cacheTemplate=e.cacheTemplate??!0,this.enableTooltips=e.enableTooltips??!1,this.options={...e},this.element=this._ensureElement(),this.events=new Ht(this),e.model&&this.setModel(e.model)}async onInit(){}async onInitView(){this.initialized||(this.initialized=!0,await this.onInit())}async onBeforeRender(){}async onAfterRender(){}async onBeforeMount(){}async onAfterMount(){}async onBeforeUnmount(){}async onAfterUnmount(){}async onBeforeDestroy(){}async onAfterDestroy(){}setModel(e={}){let t=e!==this.model;if(!t)return this;this.model&&this.model.off&&this.model.off("change",this._onModelChange,this),this.model=e,this.model&&this.model.on&&this.model.on("change",this._onModelChange,this);for(const s in this.children){const i=this.children[s];i&&typeof i.setModel=="function"&&i.setModel(e)}return t&&this._onModelChange(),this}_onModelChange(){this.isMounted()&&this.render()}setTemplate(e){return this.template=e??"",this}addChild(e,t){try{if(!e||typeof e!="object")return this;t&&((t.containerId||t.container)&&(e.containerId=t.containerId||t.container),t.id&&(e.id=t.id),t.lazyMount===!0&&(e._lazyMount=!0)),e.parent=this,this.getApp()&&(e.app=this.app),this.children[e.id]=e}catch(s){C._warn("addChild error",s)}return e}removeChild(e){try{const t=typeof e=="string"?e:e&&e.id;if(!t)return this;const s=this.children[t];s&&(Promise.resolve(s.destroy()).catch(i=>C._warn("removeChild destroy error",i)),delete this.children[t])}catch(t){C._warn("removeChild error",t)}return this}getChild(e){return this.children[e]}async updateData(e,t=!1){return Object.assign(this.data,e),t&&this.isMounted()&&await this.render(),this}toggleClass(e,t){return t===void 0&&(t=!this.element.classList.contains(e)),this.element.classList.toggle(e,t),this}addClass(e){return this.element.classList.add(e),this}setClass(e){return this.element.className=e,this}removeClass(e){return this.element.classList.remove(e),this}canRender(){if(this.isRendering)return!1;const e=Date.now();if(this.options.renderCooldown>0&&e-this.lastRenderTime<this.options.renderCooldown)return C._warn(`View ${this.id}: Render called too quickly, cooldown active`),!1;if(this.options.noAppend&&this.parent)if(this.parent.contains(this.containerId||this.container)){if(this.containerId&&!document.getElementById(this.containerId))return!1;if(this.container&&!document.contains(this.container))return!1}else return!1;return!0}async render(e=!0,t=null){const s=Date.now();if(!this.canRender())return this;this.isRendering=!0,this.lastRenderTime=s;try{this.initialized||await this.onInitView(),this.unbindEvents(),await this.onBeforeRender(),this.getViewData&&(this.data=await this.getViewData());const i=await this.renderTemplate();this.element.innerHTML=i,e&&!this.isMounted()&&await this.mount(t),await this._renderChildren(),await this.onAfterRender(),this.bindEvents()}catch(i){C._warn(`Render error in ${this.id}`,i)}finally{this.isRendering=!1}return this}async _renderChildren(){const e=[];for(const t in this.children){const s=this.children[t];if(s){if(s.parent=this,s._lazyMount&&!s._lazyTriggered){e.push(s);continue}await Promise.resolve(s.render()).catch(i=>C._warn(`Child render error (${t})`,i))}}e.length&&this._setupLazyMountObserver(e)}_setupLazyMountObserver(e){if(typeof IntersectionObserver>"u"){e.forEach(t=>{t._lazyTriggered=!0,Promise.resolve(t.render()).catch(s=>C._warn(`Lazy child render error (${t.id})`,s))});return}this._lazyObserver||(this._lazyObserver=new IntersectionObserver((t,s)=>{for(const i of t){if(!i.isIntersecting)continue;const r=i.target.__mojoLazyChild;s.unobserve(i.target),!(!r||r._lazyTriggered)&&(r._lazyTriggered=!0,Promise.resolve(r.render()).catch(n=>C._warn(`Lazy child render error (${r.id})`,n)))}},{rootMargin:"120px 0px",threshold:.01}));for(const t of e){const s=this.getChildElement(t.containerId);s&&(s.__mojoLazyChild=t,s.style.minHeight||(s.classList.add("mojo-lazy-placeholder"),s.style.minHeight="1px"),this._lazyObserver.observe(s),requestAnimationFrame(()=>{if(t._lazyTriggered)return;const i=s.getBoundingClientRect(),r=typeof window<"u"?window.innerHeight:0,n=typeof window<"u"?window.innerWidth:0;i.top<r+120&&i.bottom>-120&&i.left<n&&i.right>0&&(t._lazyTriggered=!0,this._lazyObserver?.unobserve(s),Promise.resolve(t.render()).catch(o=>C._warn(`Lazy child render error (${t.id})`,o)))}))}}async _unmountChildren(){for(const e in this.children){const t=this.children[e];t&&t.unbindEvents()}}isMounted(){return this.element?.isConnected}getChildElementById(e,t=null){const s=e.startsWith("#")?e.substring(1):e;return t?t.querySelector(`#${s}`):this.element.querySelector(`#${s}`)}getChildElement(e){if(e.startsWith("#"))return this.getChildElementById(e);let t=this.element?.querySelector(`[data-container="${e}"]`);return t||this.getChildElementById(e)}getContainer(){return this.replaceById?this.parent?this.parent.getChildElementById(this.id):null:this.containerId?this.parent?this.parent.getChildElement(this.containerId):this.getChildElementById(this.containerId,document.body):null}async mount(e=null){if(await this.onBeforeMount(),e||(e=this.getContainer()),this.containerId&&!e){console.error(`Container not found for ${this.containerId}`);return}e&&this.replaceById?e.replaceWith(this.element):e?e.replaceChildren(this.element):!this.containerId&&this.parent?this.parent.element.appendChild(this.element):!this.containerId&&!this.parent&&this.options.allowAppendToBody?(console.log("APPENDING TO BODY!!!!"),document.body.appendChild(this.element)):console.error(`Container not found for ${this.containerId}`),await this.onAfterMount(),this.mounted=!0}async unmount(){!this.element||!this.element.parentNode||(await this.onBeforeUnmount(),await this._unmountChildren(),this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.events.unbind(),await this.onAfterUnmount(),this.mounted=!1)}async destroy(){try{this.events.unbind(),this._lazyObserver&&(this._lazyObserver.disconnect(),this._lazyObserver=null);for(const e in this.children){const t=this.children[e];t&&await Promise.resolve(t.destroy()).catch(s=>C._warn(`Child destroy error (${e})`,s))}this.mounted=!1,this.element&&this.element.parentNode&&(await this.onBeforeDestroy(),this.element.parentNode&&this.element.parentNode.removeChild(this.element),await this.onAfterDestroy())}catch(e){C._warn(`Destroy error in ${this.id}`,e)}}_ensureElement(){try{if(this.element&&this.element.tagName?.toLowerCase()===this.tagName)return this._syncAttrs(),this.element;const e=document.createElement(this.tagName);return this.element=e,this.el=e,this._syncAttrs(),e}catch(e){C._warn("ensureElement error",e);const t=document.createElement("div");return t.id=this.id||C._genId(),t}}_syncAttrs(){try{if(!this.element)return;this.id&&(this.element.id=this.id),this.element.className=this.className||"",this.style==null?this.element.removeAttribute("style"):this.element.style.cssText=String(this.style)}catch(e){C._warn("_syncAttrs error",e)}}bindEvents(){this.events.bind(this.element),this.enableTooltips&&this.initializeTooltips()}unbindEvents(){this.events.unbind(),this.enableTooltips&&this.disposeTooltips()}async renderTemplate(){const e=await this.getTemplate();if(!e)return"";const t=this.getPartials();return D.render(e,this,t)}renderTemplateString(e,t,s){return D.render(e,t,s)}getPartials(){return{}}async getTemplate(){if(this._templateCache&&this.cacheTemplate)return this._templateCache;const e=this.template||this.templateUrl;if(!e)throw new Error("Template not found");let t="";if(typeof e=="string")if(e.includes("<")||e.includes("{"))t=e;else try{let s=e;this.app||(this.app=this.getApp()),this.app&&this.app.basePath&&!s.startsWith("/")&&!s.startsWith("http://")&&!s.startsWith("https://")&&(s=`${this.app.basePath.endsWith("/")?this.app.basePath.slice(0,-1):this.app.basePath}/${s}`);const i=await fetch(s);if(!i.ok)throw new Error(`HTTP ${i.status}: ${i.statusText}`);t=await i.text()}catch(s){C._warn(`Failed to load template from ${e}: ${s}`),this.showError?.(`Failed to load template from ${e}: ${s.message}`)}else typeof e=="function"&&(t=await this.template(this.data,this.state));return this.cacheTemplate&&t&&typeof e!="function"&&(this._templateCache=t),t}getContextValue(e){const t=$.getContextData(this,e);return e&&e.startsWith("data.")&&t&&typeof t=="object"?$.wrapData(t,this):e&&e.startsWith("model.")&&e!=="model"&&t&&typeof t=="object"&&typeof t.getContextValue!="function"?$.wrapData(t,null):t}async handlePageNavigation(e){const t=e.getAttribute("data-page"),s=e.getAttribute("data-params");let i={};if(s)try{i=JSON.parse(s)}catch{console.warn("Invalid JSON in data-params:",s)}const r=this.getApp();if(r){r.showPage(t,i);return}const n=this.findRouter();n&&typeof n.navigateToPage=="function"?await n.navigateToPage(t,i):console.error(`No router found for page navigation to '${t}'`)}async handleHrefNavigation(e){const t=e.getAttribute("href");if(this.isExternalLink(t)||e.hasAttribute("data-external"))return;const s=this.findRouter();if(s){if(s.options&&s.options.mode==="param"&&t.startsWith("?")){const r="/"+t;await s.navigate(r);return}if(s.options&&s.options.mode==="hash"&&t.startsWith("#")){await s.navigate(t);return}const i=this.hrefToRoutePath(t);await s.navigate(i)}else console.warn("No router found for navigation, using default behavior"),window.location.href=t}isExternalLink(e){return e?e.startsWith("/")&&this.getApp()?!e.startsWith(this.findRouter().basePath):e.startsWith("#")||e.startsWith("mailto:")||e.startsWith("tel:")||e.startsWith("http://")||e.startsWith("https://")||e.startsWith("//"):!0}hrefToRoutePath(e){if(e.startsWith("/")){const t=this.findRouter();if(t&&t.options&&t.options.base){const s=t.options.base;if(e.startsWith(s))return e.substring(s.length)||"/"}return e}return e.startsWith("./")?e.substring(2):e}findRouter(){return this.getApp(),this.app?.router||null}getApp(){if(this.app)return this.app;const e=[window.__app__,window.MOJO?.app,window.APP,window.app,window.WebApp,window.matchUUID?window[window.matchUUID]():window[window.matchUUID]];return this.app=e.find(t=>t&&typeof t.showPage=="function")||null,this.app}handleActionError(e,t,s,i){this.showError(`Action '${e}' failed: ${t}`,s,i)}escapeHtml(e){if(typeof e!="string")return e;const t=document.createElement("div");return t.textContent=e,t.innerHTML}contains(e){if(typeof e=="string"){if(!this.element)return!1;e=document.getElementById(e)}return e?this.element.contains(e):!1}initializeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.disposeTooltips(),[...this.element.querySelectorAll('[data-bs-toggle="tooltip"]')].map(t=>{const s=t.getAttribute("data-tooltip-theme"),i=t.getAttribute("data-tooltip-size");let r="";s&&(r+=`tooltip-${s} `),i&&(r+=`tooltip-${i}`);const n={},a=r.trim();return a&&(n.customClass=a),new window.bootstrap.Tooltip(t,n)})}disposeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.element.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.dispose()})}async showError(e){console.error(`View ${this.id} error:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showError=="function"){await t.showError(e);return}alert(`Error: ${e}`)}async showSuccess(e){this.debug&&console.log(`View ${this.id} success:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showSuccess=="function"){await t.showSuccess(e);return}alert(`Success: ${e}`)}async showInfo(e){console.info(`View ${this.id} info:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showInfo=="function"){await t.showInfo(e);return}alert(`Info: ${e}`)}async showWarning(e){console.warn(`View ${this.id} warning:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showWarning=="function"){await t.showWarning(e);return}alert(`Warning: ${e}`)}async onActionCopyToClipboard(e,t){try{const i=(t?.closest("[data-clipboard]")||t)?.getAttribute("data-clipboard")||"";if(!i)return!0;if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(i);else{const a=document.createElement("textarea");a.value=i,document.body.appendChild(a),a.select(),document.execCommand("copy"),document.body.removeChild(a)}const r=t.querySelector("i"),n=r&&r.className;return r&&(r.className="bi bi-check",setTimeout(()=>{r.className=n},1e3)),!0}catch(s){return console.warn("Copy to clipboard failed:",s),!0}}static _genId(){return`view_${Math.random().toString(36).substr(2,9)}`}static _warn(e,t){try{t?console.warn(`[View] ${e}:`,t):console.warn(`[View] ${e}`)}catch{}}}Object.assign(C.prototype,Ie);class x extends C{static _openDialogs=[];static _baseZIndex={backdrop:1050,modal:1055};static getFullscreenAwareZIndex(){return document.querySelector(".table-fullscreen")?{backdrop:10040,modal:10050}:x._baseZIndex}static fixAllBackdropStacking(){const e=document.querySelectorAll(".modal-backdrop"),t=x._openDialogs;if(e.length===0||t.length===0)return;const s=[...t].sort((n,a)=>(n._dialogZIndex||0)-(a._dialogZIndex||0)),r=document.querySelector(".table-fullscreen")||document.body;e.forEach((n,a)=>{if(a>=s.length)return;const o=s[a];n.style.zIndex=o._dialogZIndex-5,n.parentNode!==r&&r.appendChild(n)})}static updateAllBackdropStacking(){x.fixAllBackdropStacking()}static getMountTarget(){return document.querySelector(".table-fullscreen")||document.body}constructor(e={}){const t=e.id||`modal-${Date.now()}-${Math.random().toString(36).slice(2,7)}`;super({...e,id:t,tagName:"div",className:`modal ${e.fade!==!1?"fade":""} ${e.className||""}`.trim().replace(/\s+/g," "),attributes:{tabindex:"-1","aria-hidden":"true","aria-labelledby":e.labelledBy||`${t}-label`,"aria-describedby":e.describedBy||null,...e.attributes}}),this.modalId=t,this.title=e.title||"",this.titleId=`${this.modalId}-label`,this.size=e.size||"",this.centered=e.centered!==void 0?e.centered:!1,this.scrollable=e.scrollable!==void 0?e.scrollable:!1,this.autoSize=e.autoSize||e.size==="auto",this.backdrop=e.backdrop!==void 0?e.backdrop:!0,this.keyboard=e.keyboard!==void 0?e.keyboard:!0,this.focus=e.focus!==void 0?e.focus:!0,this.header=e.header!==void 0?e.header:!0,this.headerContent=e.headerContent||null,this.headerView=null,this.closeButton=e.closeButton!==void 0?e.closeButton:!0,this.contextMenu=e.contextMenu||null,this._processHeaderContent(this.headerContent),this.body=e.body??e.view??e.message??e.content??"",this.bodyView=null,this.bodyClass=e.bodyClass||"",this.noBodyPadding=e.noBodyPadding||!1,this.minWidth=e.minWidth||300,this.minHeight=e.minHeight||200,e.maxHeight&&(this.maxHeight=e.maxHeight),this.maxWidthPercent=e.maxWidthPercent||.9,this.maxHeightPercent=e.maxHeightPercent||.8,this._processBodyContent(this.body),this.footer=e.footer||null,this.footerView=null,this.footerClass=e.footerClass||"",this._processFooterContent(this.footer),this.buttons=e.buttons||null,this.onShow=e.onShow||null,this.onShown=e.onShown||null,this.onHide=e.onHide||null,this.onHidden=e.onHidden||null,this.onHidePrevented=e.onHidePrevented||null,this.autoShow=e.autoShow!==void 0?e.autoShow:!1,this.modal=null,this.relatedTarget=e.relatedTarget||null}_processBodyContent(e){if(e instanceof C||e&&typeof e=="object"&&typeof e.render=="function")this.bodyView=e,this.body="",this.addChild(this.bodyView);else if(typeof e=="function")try{const t=e();t instanceof C?(this.bodyView=t,this.body="",this.addChild(this.bodyView)):t instanceof Promise?(this.bodyPromise=t,this.body='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.body=t}catch(t){console.error("ModalView: error processing body function:",t),this.body=e}else this.body=e}_processHeaderContent(e){if(e instanceof C)this.headerView=e,this.headerContent=null,this.addChild(this.headerView);else if(typeof e=="function")try{const t=e();t instanceof C?(this.headerView=t,this.headerContent=null,this.addChild(this.headerView)):t instanceof Promise?(this.headerPromise=t,this.headerContent='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.headerContent=t}catch(t){console.error("ModalView: error processing headerContent function:",t),this.headerContent=e}else this.headerContent=e}_processFooterContent(e){if(e instanceof C)this.footerView=e,this.footer=null,this.addChild(this.footerView);else if(typeof e=="function")try{const t=e();t instanceof C?(this.footerView=t,this.footer=null,this.addChild(this.footerView)):t instanceof Promise?(this.footerPromise=t,this.footer='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.footer=t}catch(t){console.error("ModalView: error processing footer function:",t),this.footer=e}else this.footer=e}async getTemplate(){const e=["modal-dialog"];return this.size&&this.size!=="auto"&&(this.size.startsWith("fullscreen")?e.push(`modal-${this.size}`):["sm","lg","xl","xxl"].includes(this.size)&&(e.push(`modal-${this.size}`),["lg","xl","xxl"].includes(this.size)&&e.push("modal-fullscreen-sm-down"))),this.centered&&e.push("modal-dialog-centered"),this.scrollable&&(this.maxHeight?e.push("overflow-hidden"):e.push("modal-dialog-scrollable")),`
16
16
  <div class="${e.join(" ")}">
17
17
  <div class="modal-content">
18
18
  ${await this.buildHeader()}
@@ -52,7 +52,7 @@ var MOJO=(function(T){"use strict";class Te{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,Z=0,oe=null;const zt=`
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,Z=0,le=null;const zt=`
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);
@@ -85,13 +85,13 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
85
85
  white-space: nowrap;
86
86
  }
87
87
  @keyframes mojo-spin { to { transform: rotate(360deg); } }
88
- `,ke={show(c){typeof c=="string"&&(c={message:c});const{message:e="Loading...",timeout:t=3e4}=c||{};if(Z++,Z===1){oe&&clearTimeout(oe);const i=x.getFullscreenAwareZIndex().modal+1e3;L||(L=document.createElement("div"),L.className="mojo-loading-overlay",L.innerHTML=`
88
+ `,ke={show(c){typeof c=="string"&&(c={message:c});const{message:e="Loading...",timeout:t=3e4}=c||{};if(Z++,Z===1){le&&clearTimeout(le);const i=x.getFullscreenAwareZIndex().modal+1e3;L||(L=document.createElement("div"),L.className="mojo-loading-overlay",L.innerHTML=`
89
89
  <div class="mojo-loading-card">
90
90
  <div class="mojo-loading-spinner"></div>
91
91
  <div class="mojo-loading-message">${e}</div>
92
92
  </div>
93
93
  <style>${zt}</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&&(oe=setTimeout(()=>{console.error("BusyIndicator timed out."),ke.hide(!0)},t))}else if(L){const s=L.querySelector(".mojo-loading-message");s&&(s.textContent=e)}},hide(c=!1){c?Z=0:Z--,!(Z>0)&&(Z=0,oe&&(clearTimeout(oe),oe=null),L&&(L.classList.remove("show"),setTimeout(()=>{L&&Z===0&&(L.remove(),L=null)},200)))},isShown(){return L!==null&&Z>0}},qt=`
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&&(le=setTimeout(()=>{console.error("BusyIndicator timed out."),ke.hide(!0)},t))}else if(L){const s=L.querySelector(".mojo-loading-message");s&&(s.textContent=e)}},hide(c=!1){c?Z=0:Z--,!(Z>0)&&(Z=0,le&&(clearTimeout(le),le=null),L&&(L.classList.remove("show"),setTimeout(()=>{L&&Z===0&&(L.remove(),L=null)},200)))},isShown(){return L!==null&&Z>0}},qt=`
95
95
  max-height: 60vh;
96
96
  overflow-y: auto;
97
97
  background: #1e1e1e;
@@ -139,7 +139,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
139
139
  frameborder="0"
140
140
  ></iframe>
141
141
  </div>
142
- `}async onAfterMount(){await super.onAfterMount(),this._writeIframe()}onActionRefresh(){this._writeIframe()}_writeIframe(){const e=this.element?.querySelector(".mojo-html-preview-frame");if(!e)return;const t=e.contentDocument||e.contentWindow?.document;t&&(t.open(),t.write(this.html),t.close())}setHtml(e){this.html=e,this._writeIframe()}}class K{constructor(e={},t={}){this.endpoint=t.endpoint||this.constructor.endpoint||"",this.id=e.id||null,this.attributes={...e},this._=this.attributes,this.originalAttributes={...e},this.errors={},this.loading=!1,this.rest=ie,this.collection=t.collection||null,this.options={idAttribute:"id",timestamps:!0,...t}}getContextValue(e){return this.get(e)}get(e){return!e.includes(".")&&!e.includes("|")&&this[e]!==void 0?typeof this[e]=="function"?this[e]():this[e]:$.getContextData(this.attributes,e)}set(e,t,s={}){const i=JSON.parse(JSON.stringify(this.attributes));let r=!1;if(e!=null){if(typeof e=="object"){for(const[n,a]of Object.entries(e))r=this._setNestedAttribute(n,a)||r;e.id!==void 0&&(this.id=e.id)}else e==="id"?(this.id=t,r=!0):r=this._setNestedAttribute(e,t);if(r&&!s.silent)if(this.emit("change",this),typeof e=="string")this.emit(`change:${e}`,t,this);else for(const[n,a]of Object.entries(e)){const o=this._getNestedValue(n);JSON.stringify(this._getNestedValue(n,i))!==JSON.stringify(o)&&this.emit(`change:${n}`,o,this)}}}_setNestedAttribute(e,t){if(!e.includes(".")){const l=this.attributes[e];return this.attributes[e]=t,this[e]=t,l!==t}const s=e.split("."),i=s[0];(!this.attributes[i]||typeof this.attributes[i]!="object")&&(this.attributes[i]={}),(!this[i]||typeof this[i]!="object")&&(this[i]={});const r=this._getNestedValue(e);let n=this.attributes[i],a=this[i];for(let l=1;l<s.length-1;l++){const d=s[l];(!n[d]||typeof n[d]!="object")&&(n[d]={}),(!a[d]||typeof a[d]!="object")&&(a[d]={}),n=n[d],a=a[d]}const o=s[s.length-1];return n[o]=t,a[o]=t,JSON.stringify(r)!==JSON.stringify(t)}_getNestedValue(e,t=this.attributes){if(!e.includes("."))return t[e];const s=e.split(".");let i=t;for(const r of s){if(i==null||typeof i!="object")return;i=i[r]}return i}getData(){return this.attributes}getId(){return this.id}async fetch(e={}){let t=e.url;if(!t){const n=e.id||this.getId();if(!n&&this.options.requiresId!==!1)throw new Error("Model: ID is required for fetching");t=this.buildUrl(n)}const s=JSON.stringify({url:t,params:e.params});if(e.debounceMs&&e.debounceMs>0)return this._debouncedFetch(s,e);if(this.currentRequest&&this.currentRequestKey!==s&&(console.info("Model: Cancelling previous request for new parameters"),this.abortController?.abort(),this.currentRequest=null),this.currentRequest&&this.currentRequestKey===s)return console.info("Model: Duplicate request in progress, returning existing promise"),this.currentRequest;const i=Date.now();if(this.lastFetchTime&&i-this.lastFetchTime<100)return console.info("Model: Rate limited, skipping fetch"),this;this.loading=!0,this.errors={},this.lastFetchTime=i,this.currentRequestKey=s,this.abortController=new AbortController,this.currentRequest=this._performFetch(t,e,this.abortController);try{return await this.currentRequest}catch(n){if(n.name==="AbortError")return console.info("Model: Request was cancelled"),this;throw n}finally{this.currentRequest=null,this.currentRequestKey=null,this.abortController=null}}async _debouncedFetch(e,t){return this.debouncedFetchTimeout&&clearTimeout(this.debouncedFetchTimeout),this.cancel(),new Promise((s,i)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const r=await this.fetch({...t,debounceMs:0});s(r)}catch(r){i(r)}},t.debounceMs)})}async _performFetch(e,t,s){try{t.graph&&(!t.params||!t.params.graph)&&(t.params||(t.params={}),t.params.graph=t.graph);const i=await this.rest.GET(e,t.params,{signal:s.signal});return i.success?i.data.status?(this.originalAttributes={...this.attributes},i.data.data&&this.set(i.data.data),this.errors={}):this.errors=i.data:this.errors=i.errors||{},i}catch(i){if(i.name==="AbortError")throw console.info("Model: Fetch was cancelled"),i;return this.errors={fetch:i.message},{success:!1,error:i.message,status:i.status||500}}finally{this.loading=!1}}async save(e,t={}){const s=!this.id,i=s?"POST":"PUT",r=s?this.buildUrl():this.buildUrl(this.id);this.loading=!0,this.errors={};try{const n=await this.rest[i](r,e,t.params);return n.success?n.data.status?(this.originalAttributes={...this.attributes},this.set(n.data.data),this.errors={}):this.errors=n.data:this.errors=n.errors||{},n}catch(n){return{success:!1,error:n.message,status:n.status||500}}finally{this.loading=!1}}async destroy(e={}){if(!this.id)return this.errors={destroy:"Cannot destroy model without ID"},{success:!1,error:"Cannot destroy model without ID",status:400};const t=this.buildUrl(this.id);this.loading=!0,this.errors={};try{const s=await this.rest.DELETE(t,e.params);return s.success?(this.attributes={},this.originalAttributes={},this.id=null,this.errors={}):this.errors=s.errors||{},s}catch(s){return this.errors={destroy:s.message},{success:!1,error:s.message,status:s.status||500}}finally{this.loading=!1}}isDirty(){return JSON.stringify(this.attributes)!==JSON.stringify(this.originalAttributes)}getChangedAttributes(){const e={};for(const[t,s]of Object.entries(this.attributes))this.originalAttributes[t]!==s&&(e[t]=s);return e}reset(){for(const e of Object.keys(this.attributes))e in this.originalAttributes||delete this[e];for(const[e,t]of Object.entries(this.originalAttributes))this[e]=t;this.attributes={...this.originalAttributes},this._=this.attributes,this.errors={}}buildUrl(e=null){let t=this.endpoint;return e&&(t=t.endsWith("/")?`${t}${e}`:`${t}/${e}`),t}toJSON(){return{id:this.id,...this.attributes}}validate(){if(this.errors={},this.constructor.validations)for(const[e,t]of Object.entries(this.constructor.validations))this.validateField(e,t);return Object.keys(this.errors).length===0}validateField(e,t){const s=this.get(e),i=Array.isArray(t)?t:[t];for(const r of i)if(typeof r=="function"){const n=r(s,this);if(n!==!0){this.errors[e]=n||`${e} is invalid`;break}}else if(typeof r=="object"){if(r.required&&(s==null||s==="")){this.errors[e]=r.message||`${e} is required`;break}if(r.minLength&&s&&s.length<r.minLength){this.errors[e]=r.message||`${e} must be at least ${r.minLength} characters`;break}if(r.maxLength&&s&&s.length>r.maxLength){this.errors[e]=r.message||`${e} must be no more than ${r.maxLength} characters`;break}if(r.pattern&&s&&!r.pattern.test(s)){this.errors[e]=r.message||`${e} format is invalid`;break}}}static async find(e,t={}){const s=new this({},t);return await s.fetch({id:e,...t}),s}static create(e={},t={}){return new this(e,t)}cancel(){return this.currentRequest&&this.abortController?(console.info("Model: Manually cancelling active request"),this.abortController.abort(),!0):this.debouncedFetchTimeout?(clearTimeout(this.debouncedFetchTimeout),this.debouncedFetchTimeout=null,!0):!1}isFetching(){return!!this.currentRequest}async showError(e){await(await Promise.resolve().then(()=>N)).default.alert(e,"Error",{size:"md",class:"text-danger"})}}Object.assign(K.prototype,Me);class le{constructor(e={},t=null){if(Array.isArray(e)?(t=e,e=t||{}):t=t||e.data||[],this.ModelClass=e.ModelClass||K,this.models=[],this.loading=!1,this.errors={},this.meta={},this.rest=ie,t&&this.add(t),this.params={start:0,size:e.size||10,...e.params},this.endpoint=e.endpoint||this.ModelClass.endpoint||"",!this.endpoint){let s=new this.ModelClass;this.endpoint=s.endpoint}this.restEnabled=!!this.endpoint,e.restEnabled!==void 0&&(this.restEnabled=e.restEnabled),this.options={parse:!0,reset:!0,preloaded:!1,...e}}getModelName(){return this.ModelClass.name}async fetch(e={}){const t=JSON.stringify({...this.params,...e});if(this.currentRequest&&this.currentRequestKey!==t&&(console.info("Collection: Cancelling previous request for new parameters"),this.abortController?.abort(),this.currentRequest=null),this.currentRequest&&this.currentRequestKey===t)return console.info("Collection: Duplicate request in progress, returning existing promise"),this.currentRequest;const s=Date.now();if(this.options.rateLimiting&&this.lastFetchTime&&s-this.lastFetchTime<100)return console.info("Collection: Rate limited, skipping fetch"),{success:!0,message:"Rate limited, skipping fetch",data:{data:this.toJSON()}};if(!this.restEnabled)return console.info("Collection: REST disabled, skipping fetch"),{success:!0,message:"REST disabled, skipping fetch",data:{data:this.toJSON()}};if(this.options.preloaded&&this.models.length>0)return console.info("Collection: Using preloaded data, skipping fetch"),{success:!0,message:"Using preloaded data, skipping fetch",data:{data:this.toJSON()}};const r=this.buildUrl();this.loading=!0,this.errors={},this.lastFetchTime=s,this.currentRequestKey=t,this.abortController=new AbortController,this.currentRequest=this._performFetch(r,e,this.abortController);try{return await this.currentRequest}catch(n){return n.name==="AbortError"?(console.info("Collection: Request was cancelled"),{success:!1,error:"Request cancelled",status:0}):{success:!1,error:n.message,status:n.status||500}}finally{this.currentRequest=null,this.currentRequestKey=null,this.abortController=null}}async _performFetch(e,t,s){const i={...this.params,...t};console.log("Fetching collection data from",e,i);try{this.emit("fetch:start");const r=await this.rest.GET(e,i,{signal:s.signal});if(r.success&&r.data.status){const n=this.options.parse?this.parse(r):r.data;t.reset!==!1&&this.options.reset&&this.reset(),this.add(n,{silent:t.silent}),this.errors={},this.emit("fetch:success")}else r.data&&r.data.error?(this.errors=r.data,this.emit("fetch:error",{message:r.data.error,error:r.data})):(this.errors=r.errors||{},this.emit("fetch:error",{error:r.errors}));return r}catch(r){return r.name==="AbortError"?(console.info("Collection: Fetch was cancelled"),{success:!1,error:"Request cancelled",status:0}):(this.errors={fetch:r.message},this.emit("fetch:error",{message:r.message,error:r}),{success:!1,error:r.message,status:r.status||500})}finally{this.loading=!1,this.emit("fetch:end")}}async updateParams(e,t=!1,s=0){return await this.setParams({...this.params,...e},t,s)}async setParams(e,t=!1,s=0){return this.params=e,t&&this.restEnabled?s>0?(this.debouncedFetchTimeout&&clearTimeout(this.debouncedFetchTimeout),this.cancel(),new Promise((i,r)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const n=await this.fetch();i(n)}catch(n){r(n)}},s)})):this.fetch():Promise.resolve(this)}async fetchMore({pageDelta:e=1}={}){if(!this.restEnabled)return{success:!1,message:"REST disabled, cannot fetchMore"};const t=this.params.size||10,s=this.params.start||0,i=s+e*t;return this.meta&&typeof this.meta.count=="number"&&i>=this.meta.count?{success:!0,message:"No more results",data:{data:[],status:"ok",count:this.meta.count,start:s,size:t}}:(this.params={...this.params,start:i},this.emit("fetch:more",{start:i,pageDelta:e,collection:this}),this.fetch({reset:!1}))}async fetchOne(e,t={}){if(!e)return console.warn("Collection: fetchOne requires an ID"),null;if(!this.restEnabled)return console.info("Collection: REST disabled, cannot fetch single item"),null;try{const s=new this.ModelClass({id:e},{endpoint:this.endpoint,collection:this}),i=await s.fetch(t);if(i.success){if(t.addToCollection===!0){const r=this.get(s.id);r?t.merge!==!1&&r.set(s.attributes):this.add(s,{silent:t.silent})}return s}else return console.warn("Collection: fetchOne failed -",i.error||"Unknown error"),null}catch(s){return console.error("Collection: fetchOne error -",s.message),null}}async download(e="json",t={}){if(!this.restEnabled)return console.warn("Collection: REST is not enabled, cannot download from remote."),{success:!1,message:"Remote downloads are not enabled for this collection."};const s=this.buildUrl(),i={...this.params};delete i.start,delete i.size,i.download_format=e;const r=`export-${this.getModelName().toLowerCase()}`,n=this._buildDateRangeSuffix(i),a=`${r}${n}.${e}`,l={json:"application/json",csv:"text/csv"}[e]||"*/*";return i.filename=a,this.rest.download(s,i,{...t,filename:a,headers:{Accept:l}})}_buildDateRangeSuffix(e={}){const t=e.dr_start,s=e.dr_end;if(!t&&!s)return"";const i=a=>a?String(a).replace(/[^\dA-Za-z_-]/g,"-"):"",r=[],n=e.dr_field||"daterange";return r.push(i(n)),t&&r.push(`from-${i(e.dr_start)}`),s&&r.push(`to-${i(e.dr_end)}`),`-${r.filter(Boolean).join("-")}`}parse(e){return e.data&&Array.isArray(e.data.data)?(this.meta={size:e.data.size||10,start:e.data.start||0,count:e.data.count||0,status:e.data.status,graph:e.data.graph,...e.meta},e.data.data):Array.isArray(e.data)?e.data:Array.isArray(e)?e:[e]}add(e,t={}){const s=Array.isArray(e)?e:[e],i=[];for(const r of s){let n;r instanceof this.ModelClass?(n=r,n.collection||(n.collection=this)):n=new this.ModelClass(r,{endpoint:this.endpoint,collection:this});const a=this.models.findIndex(o=>o.id===n.id);a!==-1?t.merge!==!1&&this.models[a].set(n.attributes):(this.models.push(n),i.push(n))}return!t.silent&&i.length>0&&(this.emit("add",{models:i,collection:this}),this.emit("update",{collection:this})),i}remove(e,t={}){const s=Array.isArray(e)?e:[e],i=[];for(const r of s){let n=-1;if(typeof r=="string"||typeof r=="number"?n=this.models.findIndex(a=>a.id==r):n=this.models.indexOf(r),n!==-1){const a=this.models.splice(n,1)[0];a.collection===this&&(a.collection=null),i.push(a)}}return!t.silent&&i.length>0&&(this.emit("remove",{models:i,collection:this}),this.emit("update",{collection:this})),i}reset(e=null,t={}){const s=[...this.models];return this.models=[],e&&this.add(e,{silent:!0,...t}),t.silent||this.emit("reset",{collection:this,previousModels:s}),this}get(e){return this.models.find(t=>t.id==e)}at(e){return this.models[e]}length(){return this.models.length}isEmpty(){return this.models.length===0}where(e){return typeof e=="function"?this.models.filter(e):typeof e=="object"?this.models.filter(t=>Object.entries(e).every(([s,i])=>t.get(s)===i)):[]}findWhere(e){const t=this.where(e);return t.length>0?t[0]:void 0}forEach(e,t){if(typeof e!="function")throw new TypeError("Callback must be a function");return this.models.forEach((s,i)=>{e.call(t,s,i,this)}),this}sort(e,t={}){if(typeof e=="string"){const s=e;e=(i,r)=>{const n=i.get(s),a=r.get(s);return n<a?-1:n>a?1:0}}return this.models.sort(e),t.silent||this.emit("sort",{collection:this}),this}toJSON(){return this.models.map(e=>e.toJSON())}cancel(){return this.currentRequest&&this.abortController?(console.info("Collection: Manually cancelling active request"),this.abortController.abort(),!0):!1}isFetching(){return!!this.currentRequest}buildUrl(){return this.endpoint}*[Symbol.iterator](){for(const e of this.models)yield e}static fromArray(e,t=[],s={}){const i=new this({ModelClass:e,...s});return i.add(t,{silent:!0}),i}}Object.assign(le.prototype,Me);class Wt{constructor(e={}){this.options={containerId:"toast-container",position:"top-end",autohide:!0,defaultDelay:3e3,maxToasts:5,...e},this.toasts=new Map,this.toastCounter=0,this.init()}init(){this.createContainer()}createContainer(){let e=document.getElementById(this.options.containerId);e||(e=document.createElement("div"),e.id=this.options.containerId,e.className=`toast-container position-fixed ${this.getPositionClasses()}`,e.style.zIndex="1070",e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true"),document.body.appendChild(e)),this.container=e}getPositionClasses(){const e={"top-start":"top-0 start-0 p-3","top-center":"top-0 start-50 translate-middle-x p-3","top-end":"top-0 end-0 p-3","middle-start":"top-50 start-0 translate-middle-y p-3","middle-center":"top-50 start-50 translate-middle p-3","middle-end":"top-50 end-0 translate-middle-y p-3","bottom-start":"bottom-0 start-0 p-3","bottom-center":"bottom-0 start-50 translate-middle-x p-3","bottom-end":"bottom-0 end-0 p-3"};return e[this.options.position]||e["top-end"]}success(e,t={}){return this.show(e,"success",{icon:"bi-check-circle-fill",...t})}error(e,t={}){return this.show(e,"error",{icon:"bi-exclamation-triangle-fill",autohide:!0,...t})}info(e,t={}){return this.show(e,"info",{icon:"bi-info-circle-fill",...t})}warning(e,t={}){return this.show(e,"warning",{icon:"bi-exclamation-triangle-fill",...t})}plain(e,t={}){return this.show(e,"plain",{...t})}show(e,t="info",s={}){this.enforceMaxToasts();const i=`toast-${++this.toastCounter}`,r={title:this.getDefaultTitle(t),icon:this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,...s},n=this.createToastElement(i,e,t,r);if(this.container.appendChild(n),typeof bootstrap>"u")throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const a=new bootstrap.Toast(n,{autohide:r.autohide,delay:r.delay});return this.toasts.set(i,{element:n,bootstrap:a,type:t,message:e}),n.addEventListener("hidden.bs.toast",()=>{this.cleanup(i)}),a.show(),{id:i,hide:()=>{try{a.hide()}catch(o){console.warn("Error hiding toast:",o)}},dispose:()=>this.cleanup(i),updateProgress:s.updateProgress||null}}showView(e,t="info",s={}){this.enforceMaxToasts();const i=`toast-${++this.toastCounter}`,r={title:s.title||this.getDefaultTitle(t),icon:s.icon||this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,size:"md",...s},n=this.createViewToastElement(i,e,t,r);if(this.container.appendChild(n),typeof bootstrap>"u")throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const a=new bootstrap.Toast(n,{autohide:r.autohide,delay:r.delay});this.toasts.set(i,{element:n,bootstrap:a,type:t,view:e,message:"View toast"}),n.addEventListener("hidden.bs.toast",()=>{this.cleanupView(i)});const o=n.querySelector(".toast-view-body");return o&&e&&e.render(!0,o),a.show(),{id:i,view:e,hide:()=>{try{a.hide()}catch(l){console.warn("Error hiding view toast:",l)}},dispose:()=>this.cleanupView(i),updateProgress:l=>{e&&typeof e.updateProgress=="function"&&e.updateProgress(l)}}}createToastElement(e,t,s,i){const r=document.createElement("div");r.id=e,r.className=`toast toast-service-${s}${i.size?` toast-${i.size}`:""}`,r.setAttribute("role","alert"),r.setAttribute("aria-live","assertive"),r.setAttribute("aria-atomic","true");const n=i.title||i.icon?this.createToastHeader(i,s):"",a=this.createToastBody(t,i.icon&&!i.title);return r.innerHTML=`
142
+ `}async onAfterMount(){await super.onAfterMount(),this._writeIframe()}onActionRefresh(){this._writeIframe()}_writeIframe(){const e=this.element?.querySelector(".mojo-html-preview-frame");if(!e)return;const t=e.contentDocument||e.contentWindow?.document;t&&(t.open(),t.write(this.html),t.close())}setHtml(e){this.html=e,this._writeIframe()}}class K{constructor(e={},t={}){this.endpoint=t.endpoint||this.constructor.endpoint||"",this.id=e.id||null,this.attributes={...e},this._=this.attributes,this.originalAttributes={...e},this.errors={},this.loading=!1,this.rest=re,this.collection=t.collection||null,this.options={idAttribute:"id",timestamps:!0,...t}}getContextValue(e){return this.get(e)}get(e){return!e.includes(".")&&!e.includes("|")&&this[e]!==void 0?typeof this[e]=="function"?this[e]():this[e]:$.getContextData(this.attributes,e)}set(e,t,s={}){const i=JSON.parse(JSON.stringify(this.attributes));let r=!1;if(e!=null){if(typeof e=="object"){for(const[n,a]of Object.entries(e))r=this._setNestedAttribute(n,a)||r;e.id!==void 0&&(this.id=e.id)}else e==="id"?(this.id=t,r=!0):r=this._setNestedAttribute(e,t);if(r&&!s.silent)if(this.emit("change",this),typeof e=="string")this.emit(`change:${e}`,t,this);else for(const[n,a]of Object.entries(e)){const o=this._getNestedValue(n);JSON.stringify(this._getNestedValue(n,i))!==JSON.stringify(o)&&this.emit(`change:${n}`,o,this)}}}_setNestedAttribute(e,t){if(!e.includes(".")){const l=this.attributes[e];return this.attributes[e]=t,this[e]=t,l!==t}const s=e.split("."),i=s[0];(!this.attributes[i]||typeof this.attributes[i]!="object")&&(this.attributes[i]={}),(!this[i]||typeof this[i]!="object")&&(this[i]={});const r=this._getNestedValue(e);let n=this.attributes[i],a=this[i];for(let l=1;l<s.length-1;l++){const d=s[l];(!n[d]||typeof n[d]!="object")&&(n[d]={}),(!a[d]||typeof a[d]!="object")&&(a[d]={}),n=n[d],a=a[d]}const o=s[s.length-1];return n[o]=t,a[o]=t,JSON.stringify(r)!==JSON.stringify(t)}_getNestedValue(e,t=this.attributes){if(!e.includes("."))return t[e];const s=e.split(".");let i=t;for(const r of s){if(i==null||typeof i!="object")return;i=i[r]}return i}getData(){return this.attributes}getId(){return this.id}async fetch(e={}){let t=e.url;if(!t){const n=e.id||this.getId();if(!n&&this.options.requiresId!==!1)throw new Error("Model: ID is required for fetching");t=this.buildUrl(n)}const s=JSON.stringify({url:t,params:e.params});if(e.debounceMs&&e.debounceMs>0)return this._debouncedFetch(s,e);if(this.currentRequest&&this.currentRequestKey!==s&&(console.info("Model: Cancelling previous request for new parameters"),this.abortController?.abort(),this.currentRequest=null),this.currentRequest&&this.currentRequestKey===s)return console.info("Model: Duplicate request in progress, returning existing promise"),this.currentRequest;const i=Date.now();if(this.lastFetchTime&&i-this.lastFetchTime<100)return console.info("Model: Rate limited, skipping fetch"),this;this.loading=!0,this.errors={},this.lastFetchTime=i,this.currentRequestKey=s,this.abortController=new AbortController,this.currentRequest=this._performFetch(t,e,this.abortController);try{return await this.currentRequest}catch(n){if(n.name==="AbortError")return console.info("Model: Request was cancelled"),this;throw n}finally{this.currentRequest=null,this.currentRequestKey=null,this.abortController=null}}async _debouncedFetch(e,t){return this.debouncedFetchTimeout&&clearTimeout(this.debouncedFetchTimeout),this.cancel(),new Promise((s,i)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const r=await this.fetch({...t,debounceMs:0});s(r)}catch(r){i(r)}},t.debounceMs)})}async _performFetch(e,t,s){try{t.graph&&(!t.params||!t.params.graph)&&(t.params||(t.params={}),t.params.graph=t.graph);const i=await this.rest.GET(e,t.params,{signal:s.signal});return i.success?i.data.status?(this.originalAttributes={...this.attributes},i.data.data&&this.set(i.data.data),this.errors={}):this.errors=i.data:this.errors=i.errors||{},i}catch(i){if(i.name==="AbortError")throw console.info("Model: Fetch was cancelled"),i;return this.errors={fetch:i.message},{success:!1,error:i.message,status:i.status||500}}finally{this.loading=!1}}async save(e,t={}){const s=!this.id,i=s?"POST":"PUT",r=s?this.buildUrl():this.buildUrl(this.id);this.loading=!0,this.errors={};try{const n=await this.rest[i](r,e,t.params);return n.success?n.data.status?(this.originalAttributes={...this.attributes},this.set(n.data.data),this.errors={}):this.errors=n.data:this.errors=n.errors||{},n}catch(n){return{success:!1,error:n.message,status:n.status||500}}finally{this.loading=!1}}async destroy(e={}){if(!this.id)return this.errors={destroy:"Cannot destroy model without ID"},{success:!1,error:"Cannot destroy model without ID",status:400};const t=this.buildUrl(this.id);this.loading=!0,this.errors={};try{const s=await this.rest.DELETE(t,e.params);return s.success?(this.attributes={},this.originalAttributes={},this.id=null,this.errors={}):this.errors=s.errors||{},s}catch(s){return this.errors={destroy:s.message},{success:!1,error:s.message,status:s.status||500}}finally{this.loading=!1}}isDirty(){return JSON.stringify(this.attributes)!==JSON.stringify(this.originalAttributes)}getChangedAttributes(){const e={};for(const[t,s]of Object.entries(this.attributes))this.originalAttributes[t]!==s&&(e[t]=s);return e}reset(){for(const e of Object.keys(this.attributes))e in this.originalAttributes||delete this[e];for(const[e,t]of Object.entries(this.originalAttributes))this[e]=t;this.attributes={...this.originalAttributes},this._=this.attributes,this.errors={}}buildUrl(e=null){let t=this.endpoint;return e&&(t=t.endsWith("/")?`${t}${e}`:`${t}/${e}`),t}toJSON(){return{id:this.id,...this.attributes}}validate(){if(this.errors={},this.constructor.validations)for(const[e,t]of Object.entries(this.constructor.validations))this.validateField(e,t);return Object.keys(this.errors).length===0}validateField(e,t){const s=this.get(e),i=Array.isArray(t)?t:[t];for(const r of i)if(typeof r=="function"){const n=r(s,this);if(n!==!0){this.errors[e]=n||`${e} is invalid`;break}}else if(typeof r=="object"){if(r.required&&(s==null||s==="")){this.errors[e]=r.message||`${e} is required`;break}if(r.minLength&&s&&s.length<r.minLength){this.errors[e]=r.message||`${e} must be at least ${r.minLength} characters`;break}if(r.maxLength&&s&&s.length>r.maxLength){this.errors[e]=r.message||`${e} must be no more than ${r.maxLength} characters`;break}if(r.pattern&&s&&!r.pattern.test(s)){this.errors[e]=r.message||`${e} format is invalid`;break}}}static async find(e,t={}){const s=new this({},t);return await s.fetch({id:e,...t}),s}static create(e={},t={}){return new this(e,t)}cancel(){return this.currentRequest&&this.abortController?(console.info("Model: Manually cancelling active request"),this.abortController.abort(),!0):this.debouncedFetchTimeout?(clearTimeout(this.debouncedFetchTimeout),this.debouncedFetchTimeout=null,!0):!1}isFetching(){return!!this.currentRequest}async showError(e){await(await Promise.resolve().then(()=>N)).default.alert(e,"Error",{size:"md",class:"text-danger"})}}Object.assign(K.prototype,Ie);class ce{constructor(e={},t=null){if(Array.isArray(e)?(t=e,e=t||{}):t=t||e.data||[],this.ModelClass=e.ModelClass||K,this.models=[],this.loading=!1,this.errors={},this.meta={},this.rest=re,t&&this.add(t),this.params={start:0,size:e.size||10,...e.params},this.endpoint=e.endpoint||this.ModelClass.endpoint||"",!this.endpoint){let s=new this.ModelClass;this.endpoint=s.endpoint}this.restEnabled=!!this.endpoint,e.restEnabled!==void 0&&(this.restEnabled=e.restEnabled),this.options={parse:!0,reset:!0,preloaded:!1,...e}}getModelName(){return this.ModelClass.name}async fetch(e={}){const t=JSON.stringify({...this.params,...e});if(this.currentRequest&&this.currentRequestKey!==t&&(console.info("Collection: Cancelling previous request for new parameters"),this.abortController?.abort(),this.currentRequest=null),this.currentRequest&&this.currentRequestKey===t)return console.info("Collection: Duplicate request in progress, returning existing promise"),this.currentRequest;const s=Date.now();if(this.options.rateLimiting&&this.lastFetchTime&&s-this.lastFetchTime<100)return console.info("Collection: Rate limited, skipping fetch"),{success:!0,message:"Rate limited, skipping fetch",data:{data:this.toJSON()}};if(!this.restEnabled)return console.info("Collection: REST disabled, skipping fetch"),{success:!0,message:"REST disabled, skipping fetch",data:{data:this.toJSON()}};if(this.options.preloaded&&this.models.length>0)return console.info("Collection: Using preloaded data, skipping fetch"),{success:!0,message:"Using preloaded data, skipping fetch",data:{data:this.toJSON()}};const r=this.buildUrl();this.loading=!0,this.errors={},this.lastFetchTime=s,this.currentRequestKey=t,this.abortController=new AbortController,this.currentRequest=this._performFetch(r,e,this.abortController);try{return await this.currentRequest}catch(n){return n.name==="AbortError"?(console.info("Collection: Request was cancelled"),{success:!1,error:"Request cancelled",status:0}):{success:!1,error:n.message,status:n.status||500}}finally{this.currentRequest=null,this.currentRequestKey=null,this.abortController=null}}async _performFetch(e,t,s){const i={...this.params,...t};console.log("Fetching collection data from",e,i);try{this.emit("fetch:start");const r=await this.rest.GET(e,i,{signal:s.signal});if(r.success&&r.data.status){const n=this.options.parse?this.parse(r):r.data;t.reset!==!1&&this.options.reset&&this.reset(),this.add(n,{silent:t.silent}),this.errors={},this.emit("fetch:success")}else r.data&&r.data.error?(this.errors=r.data,this.emit("fetch:error",{message:r.data.error,error:r.data})):(this.errors=r.errors||{},this.emit("fetch:error",{error:r.errors}));return r}catch(r){return r.name==="AbortError"?(console.info("Collection: Fetch was cancelled"),{success:!1,error:"Request cancelled",status:0}):(this.errors={fetch:r.message},this.emit("fetch:error",{message:r.message,error:r}),{success:!1,error:r.message,status:r.status||500})}finally{this.loading=!1,this.emit("fetch:end")}}async updateParams(e,t=!1,s=0){return await this.setParams({...this.params,...e},t,s)}async setParams(e,t=!1,s=0){return this.params=e,t&&this.restEnabled?s>0?(this.debouncedFetchTimeout&&clearTimeout(this.debouncedFetchTimeout),this.cancel(),new Promise((i,r)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const n=await this.fetch();i(n)}catch(n){r(n)}},s)})):this.fetch():Promise.resolve(this)}async fetchMore({pageDelta:e=1}={}){if(!this.restEnabled)return{success:!1,message:"REST disabled, cannot fetchMore"};const t=this.params.size||10,s=this.params.start||0,i=s+e*t;return this.meta&&typeof this.meta.count=="number"&&i>=this.meta.count?{success:!0,message:"No more results",data:{data:[],status:"ok",count:this.meta.count,start:s,size:t}}:(this.params={...this.params,start:i},this.emit("fetch:more",{start:i,pageDelta:e,collection:this}),this.fetch({reset:!1}))}async fetchOne(e,t={}){if(!e)return console.warn("Collection: fetchOne requires an ID"),null;if(!this.restEnabled)return console.info("Collection: REST disabled, cannot fetch single item"),null;try{const s=new this.ModelClass({id:e},{endpoint:this.endpoint,collection:this}),i=await s.fetch(t);if(i.success){if(t.addToCollection===!0){const r=this.get(s.id);r?t.merge!==!1&&r.set(s.attributes):this.add(s,{silent:t.silent})}return s}else return console.warn("Collection: fetchOne failed -",i.error||"Unknown error"),null}catch(s){return console.error("Collection: fetchOne error -",s.message),null}}async download(e="json",t={}){if(!this.restEnabled)return console.warn("Collection: REST is not enabled, cannot download from remote."),{success:!1,message:"Remote downloads are not enabled for this collection."};const s=this.buildUrl(),i={...this.params};delete i.start,delete i.size,i.download_format=e;const r=`export-${this.getModelName().toLowerCase()}`,n=this._buildDateRangeSuffix(i),a=`${r}${n}.${e}`,l={json:"application/json",csv:"text/csv"}[e]||"*/*";return i.filename=a,this.rest.download(s,i,{...t,filename:a,headers:{Accept:l}})}_buildDateRangeSuffix(e={}){const t=e.dr_start,s=e.dr_end;if(!t&&!s)return"";const i=a=>a?String(a).replace(/[^\dA-Za-z_-]/g,"-"):"",r=[],n=e.dr_field||"daterange";return r.push(i(n)),t&&r.push(`from-${i(e.dr_start)}`),s&&r.push(`to-${i(e.dr_end)}`),`-${r.filter(Boolean).join("-")}`}parse(e){return e.data&&Array.isArray(e.data.data)?(this.meta={size:e.data.size||10,start:e.data.start||0,count:e.data.count||0,status:e.data.status,graph:e.data.graph,...e.meta},e.data.data):Array.isArray(e.data)?e.data:Array.isArray(e)?e:[e]}add(e,t={}){const s=Array.isArray(e)?e:[e],i=[];for(const r of s){let n;r instanceof this.ModelClass?(n=r,n.collection||(n.collection=this)):n=new this.ModelClass(r,{endpoint:this.endpoint,collection:this});const a=this.models.findIndex(o=>o.id===n.id);a!==-1?t.merge!==!1&&this.models[a].set(n.attributes):(this.models.push(n),i.push(n))}return!t.silent&&i.length>0&&(this.emit("add",{models:i,collection:this}),this.emit("update",{collection:this})),i}remove(e,t={}){const s=Array.isArray(e)?e:[e],i=[];for(const r of s){let n=-1;if(typeof r=="string"||typeof r=="number"?n=this.models.findIndex(a=>a.id==r):n=this.models.indexOf(r),n!==-1){const a=this.models.splice(n,1)[0];a.collection===this&&(a.collection=null),i.push(a)}}return!t.silent&&i.length>0&&(this.emit("remove",{models:i,collection:this}),this.emit("update",{collection:this})),i}reset(e=null,t={}){const s=[...this.models];return this.models=[],e&&this.add(e,{silent:!0,...t}),t.silent||this.emit("reset",{collection:this,previousModels:s}),this}get(e){return this.models.find(t=>t.id==e)}at(e){return this.models[e]}length(){return this.models.length}isEmpty(){return this.models.length===0}where(e){return typeof e=="function"?this.models.filter(e):typeof e=="object"?this.models.filter(t=>Object.entries(e).every(([s,i])=>t.get(s)===i)):[]}findWhere(e){const t=this.where(e);return t.length>0?t[0]:void 0}forEach(e,t){if(typeof e!="function")throw new TypeError("Callback must be a function");return this.models.forEach((s,i)=>{e.call(t,s,i,this)}),this}sort(e,t={}){if(typeof e=="string"){const s=e;e=(i,r)=>{const n=i.get(s),a=r.get(s);return n<a?-1:n>a?1:0}}return this.models.sort(e),t.silent||this.emit("sort",{collection:this}),this}toJSON(){return this.models.map(e=>e.toJSON())}cancel(){return this.currentRequest&&this.abortController?(console.info("Collection: Manually cancelling active request"),this.abortController.abort(),!0):!1}isFetching(){return!!this.currentRequest}buildUrl(){return this.endpoint}*[Symbol.iterator](){for(const e of this.models)yield e}static fromArray(e,t=[],s={}){const i=new this({ModelClass:e,...s});return i.add(t,{silent:!0}),i}}Object.assign(ce.prototype,Ie);class Wt{constructor(e={}){this.options={containerId:"toast-container",position:"top-end",autohide:!0,defaultDelay:3e3,maxToasts:5,...e},this.toasts=new Map,this.toastCounter=0,this.init()}init(){this.createContainer()}createContainer(){let e=document.getElementById(this.options.containerId);e||(e=document.createElement("div"),e.id=this.options.containerId,e.className=`toast-container position-fixed ${this.getPositionClasses()}`,e.style.zIndex="1070",e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true"),document.body.appendChild(e)),this.container=e}getPositionClasses(){const e={"top-start":"top-0 start-0 p-3","top-center":"top-0 start-50 translate-middle-x p-3","top-end":"top-0 end-0 p-3","middle-start":"top-50 start-0 translate-middle-y p-3","middle-center":"top-50 start-50 translate-middle p-3","middle-end":"top-50 end-0 translate-middle-y p-3","bottom-start":"bottom-0 start-0 p-3","bottom-center":"bottom-0 start-50 translate-middle-x p-3","bottom-end":"bottom-0 end-0 p-3"};return e[this.options.position]||e["top-end"]}success(e,t={}){return this.show(e,"success",{icon:"bi-check-circle-fill",...t})}error(e,t={}){return this.show(e,"error",{icon:"bi-exclamation-triangle-fill",autohide:!0,...t})}info(e,t={}){return this.show(e,"info",{icon:"bi-info-circle-fill",...t})}warning(e,t={}){return this.show(e,"warning",{icon:"bi-exclamation-triangle-fill",...t})}plain(e,t={}){return this.show(e,"plain",{...t})}show(e,t="info",s={}){this.enforceMaxToasts();const i=`toast-${++this.toastCounter}`,r={title:this.getDefaultTitle(t),icon:this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,...s},n=this.createToastElement(i,e,t,r);if(this.container.appendChild(n),typeof bootstrap>"u")throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const a=new bootstrap.Toast(n,{autohide:r.autohide,delay:r.delay});return this.toasts.set(i,{element:n,bootstrap:a,type:t,message:e}),n.addEventListener("hidden.bs.toast",()=>{this.cleanup(i)}),a.show(),{id:i,hide:()=>{try{a.hide()}catch(o){console.warn("Error hiding toast:",o)}},dispose:()=>this.cleanup(i),updateProgress:s.updateProgress||null}}showView(e,t="info",s={}){this.enforceMaxToasts();const i=`toast-${++this.toastCounter}`,r={title:s.title||this.getDefaultTitle(t),icon:s.icon||this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,size:"md",...s},n=this.createViewToastElement(i,e,t,r);if(this.container.appendChild(n),typeof bootstrap>"u")throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const a=new bootstrap.Toast(n,{autohide:r.autohide,delay:r.delay});this.toasts.set(i,{element:n,bootstrap:a,type:t,view:e,message:"View toast"}),n.addEventListener("hidden.bs.toast",()=>{this.cleanupView(i)});const o=n.querySelector(".toast-view-body");return o&&e&&e.render(!0,o),a.show(),{id:i,view:e,hide:()=>{try{a.hide()}catch(l){console.warn("Error hiding view toast:",l)}},dispose:()=>this.cleanupView(i),updateProgress:l=>{e&&typeof e.updateProgress=="function"&&e.updateProgress(l)}}}createToastElement(e,t,s,i){const r=document.createElement("div");r.id=e,r.className=`toast toast-service-${s}${i.size?` toast-${i.size}`:""}`,r.setAttribute("role","alert"),r.setAttribute("aria-live","assertive"),r.setAttribute("aria-atomic","true");const n=i.title||i.icon?this.createToastHeader(i,s):"",a=this.createToastBody(t,i.icon&&!i.title);return r.innerHTML=`
143
143
  ${n}
144
144
  ${a}
145
145
  `,r}createViewToastElement(e,t,s,i){const r=document.createElement("div");r.id=e,r.className=`toast toast-service-${s}${i.size?` toast-${i.size}`:""}`,r.setAttribute("role","alert"),r.setAttribute("aria-live","assertive"),r.setAttribute("aria-atomic","true");const n=i.title||i.icon?this.createToastHeader(i,s):"",a=this.createViewToastBody();return r.innerHTML=`
@@ -199,7 +199,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
199
199
  </small>
200
200
  </div>
201
201
  </div>
202
- `}updateProgress(e){this.cancelled||this.completed||(this.progress=e.progress,this.percentage=e.percentage,this.loaded=e.loaded,this.total=e.total||this.filesize,this.loadedFormatted=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 Yt{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 Wt),this.promise=this._startUpload()}async _startUpload(){try{this.options.showToast&&this._showProgressToast();let e;try{e=await this._initiateUpload()}catch(i){throw new Error(`Failed to initiate upload: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");if(!e||!e.upload_url)throw new Error("Invalid upload response: missing upload URL");let t;if(typeof e.upload_url=="string")t={url:e.upload_url,method:"PUT",fields:null,headers:{}};else if(e.upload_url&&typeof e.upload_url=="object"&&e.upload_url.upload_url)t={url:e.upload_url.upload_url,method:e.upload_url.method||"POST",fields:e.upload_url.fields||null,headers:e.upload_url.headers||{}};else throw new Error(`Invalid upload response: unrecognised upload_url format. Server returned: ${JSON.stringify(e.upload_url)}`);let s;try{s=await this._performUpload(t)}catch(i){throw new Error(`File upload failed: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");try{await this._completeUpload()}catch(i){console.warn("Failed to mark upload as completed:",i)}return this._onComplete(this.fileModel),this.fileModel}catch(e){throw e.message!=="Upload cancelled"&&this._onError(e),e}}async _initiateUpload(){try{const e={filename:this.options.name||this.options.file.name,file_size:this.options.file.size,content_type:this.options.file.type};this.options.group&&(e.group=this.options.group),this.options.description&&(e.description=this.options.description);const t=await this.fileModel.rest.POST("/api/fileman/upload/initiate",e);if(!t)throw new Error("No response from upload initiation API");if(!t.data)throw new Error("Upload initiation response missing data");if(!t.data.status){const s=t.data.error||"Upload initiation failed";throw new Error(s)}if(!t.data.data)throw new Error("Upload initiation response missing data payload");return t.data.data.id&&this.fileModel.set("id",t.data.data.id),t.data.data}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload initiation. Please check your connection."):e}}async _performUpload(e){return new Promise((t,s)=>{if(!(this.options.file instanceof File)){s(new Error("Only single File objects are supported"));return}const{url:i,method:r,fields:n,headers:a}=e,o=r==="POST"&&n!==null,l=new XMLHttpRequest;this.uploadRequest=l,l.upload.onprogress=u=>{this.cancelled||this._onProgress({progress:u.loaded/u.total,loaded:u.loaded,total:u.total,percentage:Math.round(u.loaded/u.total*100)})},l.onload=()=>{l.status>=200&&l.status<300?t({data:l.response,status:l.status,statusText:l.statusText,xhr:l}):s(new Error(`Upload failed: ${l.status} ${l.statusText}`))},l.onerror=()=>s(new Error("Upload failed: Network error")),l.ontimeout=()=>s(new Error("Upload timed out — file may be too large or connection too slow")),l.onabort=()=>s(new Error("Upload cancelled"));let d=i;i.startsWith("/")&&!i.startsWith("/api/")&&(d="/api"+i);const h=this.fileModel.rest.buildUrl(d);if(l.open(r,h),l.timeout=3e4,o){for(const[m,p]of Object.entries(a||{}))m.toLowerCase()!=="content-type"&&l.setRequestHeader(m,p);const u=new FormData;for(const[m,p]of Object.entries(n))u.append(m,p);u.append("file",this.options.file),l.send(u)}else{l.setRequestHeader("Content-Type",this.options.file.type);for(const[u,m]of Object.entries(a||{}))u.toLowerCase()!=="content-type"&&l.setRequestHeader(u,m);l.send(this.options.file)}})}async _completeUpload(){try{const e=await this.fileModel.save({action:"mark_as_completed"});if(!e)throw new Error("No response from upload completion API");if(e.data&&!e.data.status){const t=e.data.error||"Failed to mark upload as completed";throw new Error(t)}return e}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload completion. The file may have uploaded successfully."):e}}_onProgress(e){this.progressToast&&this.progressToast.updateProgress&&this.progressToast.updateProgress(e),typeof this.options.onProgress=="function"&&this.options.onProgress(e)}_onComplete(e){this.progressView&&this.progressView.markCompleted("Upload completed successfully!"),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast:",t)}},2e3),typeof this.options.onComplete=="function"&&this.options.onComplete(e)}_onError(e){if(this.progressToast)try{this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast on error:",t)}this.toastService&&this.toastService.error(`Upload failed: ${e.message}`),typeof this.options.onError=="function"&&this.options.onError(e)}_showProgressToast(){this.progressView=new Le({filename:this.options.name||this.options.file.name,filesize:this.options.file.size,showCancel:!0,onCancel:()=>this.cancel()}),this.progressToast=this.toastService.showView(this.progressView,"info",{title:"File Upload",autohide:!1,dismissible:!1})}cancel(){return this.cancelled?!1:(this.cancelled=!0,this.uploadRequest&&typeof this.uploadRequest.abort=="function"&&this.uploadRequest.abort(),this.progressView&&this.progressView.markCancelled(),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(e){console.warn("Error hiding progress toast on cancel:",e)}},1500),!0)}isCancelled(){return this.cancelled}then(e,t){return this.promise.then(e,t)}catch(e){return this.promise.catch(e)}finally(e){return this.promise.finally(e)}getStats(){return{filename:this.options.file.name,size:this.options.file.size,type:this.options.file.type,cancelled:this.cancelled,group:this.options.group,description:this.options.description}}}class ce extends K{constructor(e={}){super(e,{endpoint:"/api/group"})}}class Ve extends le{constructor(e={}){super({ModelClass:ce,endpoint:"/api/group",size:10,...e})}}const ot={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"},Pe=Object.entries(ot).map(([c,e])=>({value:c,label:e})),Ne={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:Pe},{type:"collection",name:"parent",label:"Parent Group",Collection:Ve,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:"uuid",type:"text",label:"UUID",placeholder:"32-character hex string"},{name:"kind",type:"select",label:"Group Kind",required:!0,options:Pe},{type:"collection",name:"parent",label:"Parent Group",Collection:Ve,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}]}};ce.EDIT_FORM=Ne.edit,ce.ADD_FORM=Ne.create,ce.CREATE_FORM=Ne.create,ce.GroupKindOptions=Pe,ce.GroupKinds=ot;class S extends K{constructor(e={}){super(e,{endpoint:"/api/user"})}hasPermission(e){if(this.get("is_superuser"))return!0;if(Array.isArray(e))return e.some(i=>this.hasPermission(i));const t=e.startsWith("sys."),s=t?e.substring(4):e;return!!(this._hasPermission(s)||!t&&this.member&&this.member.hasPermission(e))}_hasPermission(e){const t=this.get("permissions");if(!t)return!1;if(t[e]==!0)return!0;const s=S.GRANULAR_TO_CATEGORY[e];return!!(s&&t[s]==!0)}hasPerm(e){return this.hasPermission(e)}}S.CATEGORY_PERMISSIONS=[{name:"view_admin",label:"Admin Panel",tooltip:"Access the admin panel, Mojo, and system tools"},{name:"security",label:"Security",tooltip:"Incidents, events, rules, tickets, firewall, bouncer, GeoIP, system logs"},{name:"users",label:"Users",tooltip:"User records, passkeys, TOTP, API keys, OAuth, devices, locations"},{name:"groups",label:"Groups",tooltip:"Groups, members, group API keys, settings"},{name:"comms",label:"Communications",tooltip:"Email, phone, SMS, push notifications, chat, notifications"},{name:"jobs",label:"Jobs",tooltip:"Jobs, job events, job logs, runners, queue control, system stats"},{name:"metrics",label:"Metrics",tooltip:"Metrics recording, fetching, categories, values, permissions"},{name:"files",label:"Files",tooltip:"File managers, files, renditions, vault files, vault data, S3 buckets"},{name:"assistant",label:"Mojo",tooltip:"Access to Mojo"}],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 lt={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:Ve,labelField:"name",valueField:"id",columns:12}]},permissions:{fields:S.PERMISSION_FIELDS}},Gt={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=Gt.detailed,S.EDIT_FORM=lt.edit,S.ADD_FORM=lt.create;class ct extends K{constructor(e={}){super(e,{endpoint:"/api/fileman/manager"})}}const dt={create:{title:"Add Storage Backend",fields:[{name:"name",type:"text",label:"Display Name",placeholder:"Enter Display Name",cols:12},{name:"use",type:"text",label:"Use",placeholder:"Enter User or Leave Blank",cols:12},{name:"backend_url",type:"text",label:"Backend URL",required:!0,value:"s3://BUCKET_NAME/OPTION_FOLDER",placeholder:"s3://bucket_name/optional folder",help:"Format: service://path. Valid services: s3",cols:12},{name:"aws_region",type:"select",label:"AWS Region (optional)",value:"us-east-1",options:[{value:"",text:"System Default"},{value:"us-east-1",text:"US East (N. Virginia)"},{value:"us-east-2",text:"US East (Ohio)"},{value:"us-west-1",text:"US West (N. California)"},{value:"us-west-2",text:"US West (Oregon)"},{value:"ca-central-1",text:"Canada (Central)"},{value:"eu-west-1",text:"Europe (Ireland)"},{value:"eu-west-2",text:"Europe (London)"},{value:"eu-west-3",text:"Europe (Paris)"},{value:"eu-central-1",text:"Europe (Frankfurt)"},{value:"eu-north-1",text:"Europe (Stockholm)"},{value:"eu-south-1",text:"Europe (Milan)"},{value:"ap-southeast-2",text:"Asia Pacific (Sydney)"}],columns:12,help:"Optional. Defaults to project AWS_REGION if omitted."},{name:"aws_key",type:"text",label:"AWS Key (optional)",placeholder:"enter your AWS Key with S3 permissions",columns:12,help:"Optional, AWS Key with S3 permissions"},{name:"aws_secret",type:"text",label:"AWS Secret (optional)",placeholder:"enter your AWS Secret with S3 permissions",columns:12,help:"Optional, AWS Secret with S3 permissions"},{name:"is_default",type:"switch",label:"Is Default",cols:6},{name:"is_active",type:"switch",label:"Is Active",default:!0,cols:6}]},edit:{title:"Edit Storage Backend",fields:[{name:"name",type:"text",label:"Display Name",placeholder:"Enter Display Name",cols:12},{name:"use",type:"text",label:"Use",placeholder:"Enter User or Leave Blank",cols:12},{name:"backend_url",type:"text",label:"Backend URL",required:!0,placeholder:"s3://bucket_name/optional folder",help:"Format: service://path. Valid services: s3",cols:12},{name:"allowed_origins",type:"text",label:"Domains Who Can Upload",cols:12},{name:"is_default",type:"switch",label:"Is Default",cols:6},{name:"is_active",type:"switch",label:"Is Active",default:!0,cols:6},{name:"is_public",type:"switch",label:"Is Public",default:!0,cols:6}]}};let ht=class extends K{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 Yt(this,e)}};const Jt={edit:{title:"Edit File Backend",fields:[]}};ct.ADD_FORM=dt.create,ct.EDIT_FORM=dt.edit,ht.EDIT_FORM=Jt.edit;class w{static _renderAndAwait(e,{buttons:t=null,rejectOnDismiss:s=!1,onAction:i=null,cleanup:r=null}={}){const n=x.getMountTarget();return new Promise((a,o)=>{let l=!1;const d=u=>{l||(l=!0,a(u))},h=u=>{l||(l=!0,o(u))};(async()=>{try{await e.render(!0,n)}catch(u){h(u);return}t&&t.length>0&&e.element&&e.element.querySelectorAll(".modal-footer button").forEach((m,p)=>{const f=t[p];f&&m.addEventListener("click",async g=>{if(l)return;const b=f.value!==void 0?f.value:f.action??p;if(typeof f.handler=="function"){try{const y=await f.handler({dialog:e,button:f,index:p,event:g});if(y===null||y===!1)return;const v=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(v)}catch(y){console.error("Modal button handler error:",y)}return}if(typeof i=="function"&&f.action){try{const y=await i(f.action,{dialog:e,button:f,index:p,event:g});if(y===null||y===!1)return;const v=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(v)}catch(y){console.error("Modal onAction error:",y)}return}f.dismiss||e.hide(),d(b)})}),e.on("hidden",()=>{l||(s?h(new Error("Dialog dismissed")):d(null)),setTimeout(async()=>{try{typeof r=="function"&&await r(e)}catch(u){console.error("Modal cleanup error:",u)}try{await e.destroy()}catch(u){console.error("Modal destroy error:",u)}e.element?.parentNode&&e.element.parentNode.removeChild(e.element)},100)}),e.show()})()})}static async dialog(e={}){if(typeof e=="string"){const p=arguments[0],f=arguments[1]||"Alert";e={...arguments[2]||{},body:p,title:f}}const{title:t="Dialog",content:s,body:i,view:r,message:n,size:a="md",centered:o=!0,buttons:l=[{text:"OK",class:"btn-primary",value:!0}],rejectOnDismiss:d=!1,...h}=e,u=i??r??n??s??"",m=new x({title:t,body:u,size:a,centered:o,buttons:l,...h});return w._renderAndAwait(m,{buttons:l,rejectOnDismiss:d})}static async drawer(e={}){const{eyebrow:t,title:s,meta:i=[],view:r,body:n,size:a="lg",...o}=e,l=i.length?`
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 Yt{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 Wt),this.promise=this._startUpload()}async _startUpload(){try{this.options.showToast&&this._showProgressToast();let e;try{e=await this._initiateUpload()}catch(i){throw new Error(`Failed to initiate upload: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");if(!e||!e.upload_url)throw new Error("Invalid upload response: missing upload URL");let t;if(typeof e.upload_url=="string")t={url:e.upload_url,method:"PUT",fields:null,headers:{}};else if(e.upload_url&&typeof e.upload_url=="object"&&e.upload_url.upload_url)t={url:e.upload_url.upload_url,method:e.upload_url.method||"POST",fields:e.upload_url.fields||null,headers:e.upload_url.headers||{}};else throw new Error(`Invalid upload response: unrecognised upload_url format. Server returned: ${JSON.stringify(e.upload_url)}`);let s;try{s=await this._performUpload(t)}catch(i){throw new Error(`File upload failed: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");try{await this._completeUpload()}catch(i){console.warn("Failed to mark upload as completed:",i)}return this._onComplete(this.fileModel),this.fileModel}catch(e){throw e.message!=="Upload cancelled"&&this._onError(e),e}}async _initiateUpload(){try{const e={filename:this.options.name||this.options.file.name,file_size:this.options.file.size,content_type:this.options.file.type};this.options.group&&(e.group=this.options.group),this.options.description&&(e.description=this.options.description);const t=await this.fileModel.rest.POST("/api/fileman/upload/initiate",e);if(!t)throw new Error("No response from upload initiation API");if(!t.data)throw new Error("Upload initiation response missing data");if(!t.data.status){const s=t.data.error||"Upload initiation failed";throw new Error(s)}if(!t.data.data)throw new Error("Upload initiation response missing data payload");return t.data.data.id&&this.fileModel.set("id",t.data.data.id),t.data.data}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload initiation. Please check your connection."):e}}async _performUpload(e){return new Promise((t,s)=>{if(!(this.options.file instanceof File)){s(new Error("Only single File objects are supported"));return}const{url:i,method:r,fields:n,headers:a}=e,o=r==="POST"&&n!==null,l=new XMLHttpRequest;this.uploadRequest=l,l.upload.onprogress=u=>{this.cancelled||this._onProgress({progress:u.loaded/u.total,loaded:u.loaded,total:u.total,percentage:Math.round(u.loaded/u.total*100)})},l.onload=()=>{l.status>=200&&l.status<300?t({data:l.response,status:l.status,statusText:l.statusText,xhr:l}):s(new Error(`Upload failed: ${l.status} ${l.statusText}`))},l.onerror=()=>s(new Error("Upload failed: Network error")),l.ontimeout=()=>s(new Error("Upload timed out — file may be too large or connection too slow")),l.onabort=()=>s(new Error("Upload cancelled"));let d=i;i.startsWith("/")&&!i.startsWith("/api/")&&(d="/api"+i);const h=this.fileModel.rest.buildUrl(d);if(l.open(r,h),l.timeout=3e4,o){for(const[m,p]of Object.entries(a||{}))m.toLowerCase()!=="content-type"&&l.setRequestHeader(m,p);const u=new FormData;for(const[m,p]of Object.entries(n))u.append(m,p);u.append("file",this.options.file),l.send(u)}else{l.setRequestHeader("Content-Type",this.options.file.type);for(const[u,m]of Object.entries(a||{}))u.toLowerCase()!=="content-type"&&l.setRequestHeader(u,m);l.send(this.options.file)}})}async _completeUpload(){try{const e=await this.fileModel.save({action:"mark_as_completed"});if(!e)throw new Error("No response from upload completion API");if(e.data&&!e.data.status){const t=e.data.error||"Failed to mark upload as completed";throw new Error(t)}return e}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload completion. The file may have uploaded successfully."):e}}_onProgress(e){this.progressToast&&this.progressToast.updateProgress&&this.progressToast.updateProgress(e),typeof this.options.onProgress=="function"&&this.options.onProgress(e)}_onComplete(e){this.progressView&&this.progressView.markCompleted("Upload completed successfully!"),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast:",t)}},2e3),typeof this.options.onComplete=="function"&&this.options.onComplete(e)}_onError(e){if(this.progressToast)try{this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast on error:",t)}this.toastService&&this.toastService.error(`Upload failed: ${e.message}`),typeof this.options.onError=="function"&&this.options.onError(e)}_showProgressToast(){this.progressView=new Le({filename:this.options.name||this.options.file.name,filesize:this.options.file.size,showCancel:!0,onCancel:()=>this.cancel()}),this.progressToast=this.toastService.showView(this.progressView,"info",{title:"File Upload",autohide:!1,dismissible:!1})}cancel(){return this.cancelled?!1:(this.cancelled=!0,this.uploadRequest&&typeof this.uploadRequest.abort=="function"&&this.uploadRequest.abort(),this.progressView&&this.progressView.markCancelled(),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(e){console.warn("Error hiding progress toast on cancel:",e)}},1500),!0)}isCancelled(){return this.cancelled}then(e,t){return this.promise.then(e,t)}catch(e){return this.promise.catch(e)}finally(e){return this.promise.finally(e)}getStats(){return{filename:this.options.file.name,size:this.options.file.size,type:this.options.file.type,cancelled:this.cancelled,group:this.options.group,description:this.options.description}}}class de extends K{constructor(e={}){super(e,{endpoint:"/api/group"})}}class Ve extends ce{constructor(e={}){super({ModelClass:de,endpoint:"/api/group",size:10,...e})}}const ot={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"},Pe=Object.entries(ot).map(([c,e])=>({value:c,label:e})),Ne={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:Pe},{type:"collection",name:"parent",label:"Parent Group",Collection:Ve,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:"uuid",type:"text",label:"UUID",placeholder:"32-character hex string"},{name:"kind",type:"select",label:"Group Kind",required:!0,options:Pe},{type:"collection",name:"parent",label:"Parent Group",Collection:Ve,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}]}};de.EDIT_FORM=Ne.edit,de.ADD_FORM=Ne.create,de.CREATE_FORM=Ne.create,de.GroupKindOptions=Pe,de.GroupKinds=ot;class S extends K{constructor(e={}){super(e,{endpoint:"/api/user"})}hasPermission(e){if(this.get("is_superuser"))return!0;if(Array.isArray(e))return e.some(i=>this.hasPermission(i));const t=e.startsWith("sys."),s=t?e.substring(4):e;return!!(this._hasPermission(s)||!t&&this.member&&this.member.hasPermission(e))}_hasPermission(e){const t=this.get("permissions");if(!t)return!1;if(t[e]==!0)return!0;const s=S.GRANULAR_TO_CATEGORY[e];return!!(s&&t[s]==!0)}hasPerm(e){return this.hasPermission(e)}}S.CATEGORY_PERMISSIONS=[{name:"view_admin",label:"Admin Panel",tooltip:"Access the admin panel, Mojo, and system tools"},{name:"security",label:"Security",tooltip:"Incidents, events, rules, tickets, firewall, bouncer, GeoIP, system logs"},{name:"users",label:"Users",tooltip:"User records, passkeys, TOTP, API keys, OAuth, devices, locations"},{name:"groups",label:"Groups",tooltip:"Groups, members, group API keys, settings"},{name:"comms",label:"Communications",tooltip:"Email, phone, SMS, push notifications, chat, notifications"},{name:"jobs",label:"Jobs",tooltip:"Jobs, job events, job logs, runners, queue control, system stats"},{name:"metrics",label:"Metrics",tooltip:"Metrics recording, fetching, categories, values, permissions"},{name:"files",label:"Files",tooltip:"File managers, files, renditions, vault files, vault data, S3 buckets"},{name:"assistant",label:"Mojo",tooltip:"Access to Mojo"}],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 lt={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:Ve,labelField:"name",valueField:"id",columns:12}]},permissions:{fields:S.PERMISSION_FIELDS}},Gt={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=Gt.detailed,S.EDIT_FORM=lt.edit,S.ADD_FORM=lt.create;class ct extends K{constructor(e={}){super(e,{endpoint:"/api/fileman/manager"})}}const dt={create:{title:"Add Storage Backend",fields:[{name:"name",type:"text",label:"Display Name",placeholder:"Enter Display Name",cols:12},{name:"use",type:"text",label:"Use",placeholder:"Enter User or Leave Blank",cols:12},{name:"backend_url",type:"text",label:"Backend URL",required:!0,value:"s3://BUCKET_NAME/OPTION_FOLDER",placeholder:"s3://bucket_name/optional folder",help:"Format: service://path. Valid services: s3",cols:12},{name:"aws_region",type:"select",label:"AWS Region (optional)",value:"us-east-1",options:[{value:"",text:"System Default"},{value:"us-east-1",text:"US East (N. Virginia)"},{value:"us-east-2",text:"US East (Ohio)"},{value:"us-west-1",text:"US West (N. California)"},{value:"us-west-2",text:"US West (Oregon)"},{value:"ca-central-1",text:"Canada (Central)"},{value:"eu-west-1",text:"Europe (Ireland)"},{value:"eu-west-2",text:"Europe (London)"},{value:"eu-west-3",text:"Europe (Paris)"},{value:"eu-central-1",text:"Europe (Frankfurt)"},{value:"eu-north-1",text:"Europe (Stockholm)"},{value:"eu-south-1",text:"Europe (Milan)"},{value:"ap-southeast-2",text:"Asia Pacific (Sydney)"}],columns:12,help:"Optional. Defaults to project AWS_REGION if omitted."},{name:"aws_key",type:"text",label:"AWS Key (optional)",placeholder:"enter your AWS Key with S3 permissions",columns:12,help:"Optional, AWS Key with S3 permissions"},{name:"aws_secret",type:"text",label:"AWS Secret (optional)",placeholder:"enter your AWS Secret with S3 permissions",columns:12,help:"Optional, AWS Secret with S3 permissions"},{name:"is_default",type:"switch",label:"Is Default",cols:6},{name:"is_active",type:"switch",label:"Is Active",default:!0,cols:6}]},edit:{title:"Edit Storage Backend",fields:[{name:"name",type:"text",label:"Display Name",placeholder:"Enter Display Name",cols:12},{name:"use",type:"text",label:"Use",placeholder:"Enter User or Leave Blank",cols:12},{name:"backend_url",type:"text",label:"Backend URL",required:!0,placeholder:"s3://bucket_name/optional folder",help:"Format: service://path. Valid services: s3",cols:12},{name:"allowed_origins",type:"text",label:"Domains Who Can Upload",cols:12},{name:"is_default",type:"switch",label:"Is Default",cols:6},{name:"is_active",type:"switch",label:"Is Active",default:!0,cols:6},{name:"is_public",type:"switch",label:"Is Public",default:!0,cols:6}]}};let ht=class extends K{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 Yt(this,e)}};const Jt={edit:{title:"Edit File Backend",fields:[]}};ct.ADD_FORM=dt.create,ct.EDIT_FORM=dt.edit,ht.EDIT_FORM=Jt.edit;class w{static _renderAndAwait(e,{buttons:t=null,rejectOnDismiss:s=!1,onAction:i=null,cleanup:r=null}={}){const n=x.getMountTarget();return new Promise((a,o)=>{let l=!1;const d=u=>{l||(l=!0,a(u))},h=u=>{l||(l=!0,o(u))};(async()=>{try{await e.render(!0,n)}catch(u){h(u);return}t&&t.length>0&&e.element&&e.element.querySelectorAll(".modal-footer button").forEach((m,p)=>{const f=t[p];f&&m.addEventListener("click",async g=>{if(l)return;const b=f.value!==void 0?f.value:f.action??p;if(typeof f.handler=="function"){try{const y=await f.handler({dialog:e,button:f,index:p,event:g});if(y===null||y===!1)return;const v=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(v)}catch(y){console.error("Modal button handler error:",y)}return}if(typeof i=="function"&&f.action){try{const y=await i(f.action,{dialog:e,button:f,index:p,event:g});if(y===null||y===!1)return;const v=y===!0||y===void 0?b:y;f.dismiss||e.hide(),d(v)}catch(y){console.error("Modal onAction error:",y)}return}f.dismiss||e.hide(),d(b)})}),e.on("hidden",()=>{l||(s?h(new Error("Dialog dismissed")):d(null)),setTimeout(async()=>{try{typeof r=="function"&&await r(e)}catch(u){console.error("Modal cleanup error:",u)}try{await e.destroy()}catch(u){console.error("Modal destroy error:",u)}e.element?.parentNode&&e.element.parentNode.removeChild(e.element)},100)}),e.show()})()})}static async dialog(e={}){if(typeof e=="string"){const p=arguments[0],f=arguments[1]||"Alert";e={...arguments[2]||{},body:p,title:f}}const{title:t="Dialog",content:s,body:i,view:r,message:n,size:a="md",centered:o=!0,buttons:l=[{text:"OK",class:"btn-primary",value:!0}],rejectOnDismiss:d=!1,...h}=e,u=i??r??n??s??"",m=new x({title:t,body:u,size:a,centered:o,buttons:l,...h});return w._renderAndAwait(m,{buttons:l,rejectOnDismiss:d})}static async drawer(e={}){const{eyebrow:t,title:s,meta:i=[],view:r,body:n,size:a="lg",...o}=e,l=i.length?`
203
203
  <div class="modal-drawer-meta">
204
204
  ${i.map(u=>typeof u=="string"?`<span>${w._esc(u)}</span>`:`<span>${u.icon?`<i class="${w._esc(u.icon)} me-1"></i>`:""}${w._esc(u.text||"")}</span>`).join("")}
205
205
  </div>`:"",d=`
@@ -215,7 +215,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
215
215
  id="${i}"
216
216
  value="${r}"
217
217
  placeholder="${a}">
218
- `,size:s.size||"sm",centered:!0,backdrop:"static",buttons:o,...s});return l.on("shown",()=>{const d=l.element.querySelector(`#${i}`);d&&(d.focus(),d.select())}),w._renderAndAwait(l,{buttons:o,onAction:async d=>{if(d!=="ok")return null;const h=l.element.querySelector(`#${i}`);return h?h.value:null}})}static showError(e){return w.alert(e,"Error",{type:"error"})}static async form(e={}){const{title:t="Form",formConfig:s={},size:i="md",centered:r=!0,submitText:n="Submit",cancelText:a="Cancel",...o}=e,l=(await Promise.resolve().then(()=>Et)).default,d=new l({fileHandling:e.fileHandling||"base64",data:e.data,defaults:e.defaults,model:e.model,formConfig:{fields:s.fields||e.fields,...s,submitButton:!1,resetButton:!1}}),h=[{text:a,class:"btn-secondary",action:"cancel"},{text:n,class:"btn-primary",action:"submit"}],u=new x({title:t,body:d,size:i,centered:r,buttons:h,...o});return w._renderAndAwait(u,{buttons:h,onAction:async m=>{if(m==="cancel")return u.hide(),null;if(m!=="submit")return null;if(!d.validate())return d.focusFirstError(),!1;if(e.autoSave&&e.model){u.setLoading(!0);const p=await d.saveModel();return p.success?p:(u.setLoading(!1),await u.render(),u.getApp()?.toast?.error(p.message),!1)}try{return await d.getFormData()}catch(p){return console.error("Modal.form: error collecting form data:",p),d.showError("Error collecting form data"),!1}},cleanup:async()=>{try{await d.destroy()}catch{}}})}static async modelForm(e={}){const{title:t="Edit",formConfig:s={},size:i="md",centered:r=!0,submitText:n="Save",cancelText:a="Cancel",model:o,fields:l,...d}=e;if(!o)throw new Error("Modal.modelForm requires a model");const h=(await Promise.resolve().then(()=>Et)).default,u=new h({fileHandling:e.fileHandling||"base64",model:o,data:e.data,defaults:e.defaults,formConfig:{fields:l||s.fields||[],...s,submitButton:!1,resetButton:!1}}),m=[{text:a,class:"btn-secondary",action:"cancel"},{text:n,class:"btn-primary",action:"submit"}],p=new x({title:t,body:u,size:i,centered:r,buttons:m,...d});return w._renderAndAwait(p,{buttons:m,onAction:async f=>{if(f==="cancel")return p.hide(),null;if(f!=="submit")return null;p.setLoading(!0,"Saving...");try{const g=await u.handleSubmit();if(g.success)return g;p.setLoading(!1);let b=g.error;return g.data?.error&&(b=g.data.error),p.getApp()?.toast?.error(b),!1}catch(g){return console.error("Modal.modelForm: error saving:",g),await p.setContent(u),u.showError(g.message||"An error occurred while saving"),!1}},cleanup:async()=>{try{await u.destroy()}catch{}}})}static async data(e={}){const{title:t="Data View",data:s={},model:i=null,fields:r=[],columns:n=2,responsive:a=!0,showEmptyValues:o=!1,emptyValueText:l="—",size:d="lg",centered:h=!0,closeText:u="Close",...m}=e,p=(await Promise.resolve().then(()=>As)).default,f=new p({data:s,model:i,fields:r,columns:n,responsive:a,showEmptyValues:o,emptyValueText:l}),g=[{text:u,class:"btn-secondary",value:"close"}],b=new x({title:t,body:f,size:d,centered:h,buttons:g,...m});return f.on("field:click",y=>b.emit("dataview:field:click",y)),f.on("error",y=>b.emit("dataview:error",y)),w._renderAndAwait(b,{buttons:g,cleanup:async()=>{try{await f.destroy()}catch{}}})}static async code(e={}){const{code:t="",language:s="javascript",title:i="Source Code",size:r="lg",...n}=e,a=new me({code:t,language:s}),o=[{text:"Copy to Clipboard",class:"btn-primary",icon:"bi-clipboard",action:"copy"},{text:"Close",class:"btn-secondary",dismiss:!0}],l=new x({title:i,body:a,size:r,scrollable:!0,buttons:o,...n});return w._renderAndAwait(l,{buttons:o,onAction:async d=>{if(d!=="copy")return null;if(!navigator.clipboard)return!1;try{await navigator.clipboard.writeText(t),w._showCopySuccess(l)}catch(h){console.error("Modal.code: clipboard write failed:",h)}return!1}})}static _showCopySuccess(e){const t=e.element?.querySelector('[data-action="copy"]');if(!t)return;const s=t.innerHTML;t.innerHTML='<i class="bi bi-check me-1"></i>Copied!',t.classList.remove("btn-primary"),t.classList.add("btn-success"),t.disabled=!0,setTimeout(()=>{t.innerHTML=s,t.classList.remove("btn-success"),t.classList.add("btn-primary"),t.disabled=!1},2e3)}static async htmlPreview(e={}){const{html:t=e.content||"",title:s="HTML Preview",size:i="lg",height:r=500,...n}=e,a=new Ut({html:t,height:r}),o=[{text:"Close",class:"btn-secondary",dismiss:!0}],l=new x({title:s,body:a,size:i,scrollable:!1,buttons:o,...n});return w._renderAndAwait(l,{buttons:o})}static async updateModelImage(e={},t={}){const s=e.upload||!1,i=t.name||e.field||"image",r={title:"Upload Your Avatar",model:null,autoSave:!s,size:"sm",fields:[{type:"image",name:i,size:"lg",imageSize:{width:200,height:200},placeholder:"Upload your image",...t}],...e},n=await w.form(r);if(!s||!n||!e.model)return n;const a=n[i];if(!a||!a.startsWith("data:"))return n;const o=a.split(","),d=o[0]?.match(/:(.*?);/)?.[1]||"image/png",h=atob(o[1]);let u=h.length;const m=new Uint8Array(u);for(;u--;)m[u]=h.charCodeAt(u);const p=d.split("/")[1]||"png",f=typeof window<"u"&&window.File||globalThis.File;if(!f)throw new Error("File API is not available in this environment");const g=new f([m],`${i}.${p}`,{type:d}),b=new ht;return await b.upload({file:g,name:`${i}.${p}`,description:e.uploadDescription||`${i} upload`,showToast:!0}),e.model.save({[i]:b.id})}static loading(e){ke.show(e)}static hideLoading(e){ke.hide(e)}static showBusy(e){return w.loading(e)}static hideBusy(e){return w.hideLoading(e)}}const N=Object.freeze(Object.defineProperty({__proto__:null,default:w},Symbol.toStringTag,{value:"Module"}));class ve{constructor(e={}){this.config=e,this.initPluginRegistry(),this.name=e.name||"MOJO App",this.version=e.version||"1.0.0",this.debug=e.debug||!1,this.container=e.container||"#app",this.layoutType=e.layout||"portal",this.layoutConfig=e.layoutConfig||{},e.sidebar&&(this.layoutConfig.sidebarConfig=e.sidebar),e.topbar&&(this.layoutConfig.topbarConfig=e.topbar),this.layout=null,this.layoutConfig.containerId=this.container||this.containerId||"#app",this.pageContainer=e.pageContainer||"#page-container",this.basePath=e.basePath||"",this.routerMode=e.routerMode||e.router?.mode||"param",this.basePath=e.basePath||e.router?.base||"",this.defaultRoute=e.defaultRoute||"home",this.session=e.session||{},this.router=null,this.navigation=e.navigation||{},this.state={currentPage:null,previousPage:null,loading:!1},this.events=new kt,this.rest=ie,this.modal=w,e.api&&this.rest.configure(e.api);const t=(this.name||"mojo").replace(/\s+/g,"_").toLowerCase();this.theme=new Lt({storageKey:`${t}:theme`,eventBus:this.events}),this.theme.init(),this.router=new Te({mode:this.routerMode==="param"?"params":this.routerMode,basePath:this.basePath,defaultRoute:this.defaultRoute,eventEmitter:this.events}),this.events.on("route:changed",async s=>{const{pageName:i,params:r,query:n}=s;await this.showPage(i,n,r,{fromRouter:!0})}),typeof window<"u"&&(window.MOJO=window.MOJO||{},window.MOJO.router=this.router),this.setupFocusTracking(),this.pageCache=new Map,this.pageClasses=new Map,this.componentClasses=new Map,this.modelClasses=new Map,this.modelRefClasses=new Map,this.currentPage=null,this.isStarted=!1,window.matchUUID?window[window.matchUUID]=this:window.MOJO?window.MOJO.app=this:window.__app__=this}async start(){if(this.isStarted){console.warn("WebApp already started");return}try{this.setupPageContainer(),this.validateDefaultRoute(),await this.setupRouter(),this.isStarted=!0,this.router.allowPopState=!1,this.events.emit("app:ready",{app:this})}catch(e){throw console.error(`Failed to start ${this.name}:`,e),this.showError("Failed to start application"),e}}async setupRouter(){if(!this.router){console.error("Router not initialized");return}this.events.on("route:notfound",async e=>{console.warn(`Route not found: ${e.path}`),this._show404(e.path)}),this.router.start(),console.log(`Router started in ${this.routerMode} mode`)}setupPageContainer(){const e=typeof this.container=="string"?document.querySelector(this.container):this.container;e&&!e.querySelector("#page-container")&&(e.innerHTML='<div id="page-container"></div>'),this.pageContainer="#page-container"}registerPage(e,t,s={}){if(typeof e!="string"||!e)return console.error("registerPage: pageName must be a non-empty string"),this;if(typeof t!="function")return console.error("registerPage: PageClass must be a constructor function"),this;if(s.containerId||(s.containerId=this.pageContainer),this.pageClasses.set(e,{PageClass:t,constructorOptions:s}),this.router){let i=s.route||`/${e}`;i.startsWith("/")||(i=`/${i}`),s.route=i,this.router.addRoute(i,e)}return this}getPage(e){return this.pageCache.get(e)}getPagePermissions(e){if(this.pageCache.has(e))return this.pageCache.get(e).permissions;const t=this.pageClasses.get(e);if(!t)return null;const{PageClass:s,constructorOptions:i}=t;return i?i.permissions:null}getOrCreatePage(e){if(this.pageCache.has(e))return this.pageCache.get(e);const t=this.pageClasses.get(e);if(!t)return console.error(`Page not registered: ${e}`),null;const{PageClass:s,constructorOptions:i}=t;try{const r={pageName:e,...i,app:this},n=new s(r);return i.route&&(n.route=i.route),this.pageCache.set(e,n),console.log(`Created page: ${e} with route: ${n.route}`),n}catch(r){return console.error(`Failed to create page ${e}:`,r),null}}async showPage(e,t={},s={},i={}){const{fromRouter:r=!1,replace:n=!1,force:a=!1}=i;try{let o,l;typeof e=="string"?(l=e,o=this.getOrCreatePage(e)):e&&typeof e=="object"&&(o=e,l=e.pageName);const d=this.currentPage;if(!o){this._show404(l,s,t,r);return}if(this.events.emit("page:showing",{page:o,pageName:o.pageName,params:s,query:t,fromRouter:r}),!o.canEnter()){this._showDeniedPage(o,s,t,r);return}d&&d!==o&&await this._exitOldPage(d),await o.onParams(s,t),d!==o&&await o.onEnter(),o.syncUrl(),this.events.emit("page:show",{page:o,pageName:o.pageName,params:s,query:t,fromRouter:r}),await o.render(),this.currentPage=o,console.log(`✅ Showing page: ${o.pageName}`,{query:t,params:s})}catch(o){console.error("Error in showPage:",o),this.showError(`Failed to load page: ${o.message}`),e!=="error"&&await this.showPage("error",{},{error:o,originalPage:e},{fromRouter:r})}}async _show404(e,t,s,i){const r=this.getOrCreatePage("404");r&&(r.setInfo&&r.setInfo(e),await this._exitOldPage(this.currentPage),await r.render(),this.currentPage=r,this.events.emit("page:404",{page:null,pageName:e,params:t,query:s,fromRouter:i}))}async _showDeniedPage(e,t,s,i){const r=this.getOrCreatePage("denied");r.setDeniedPage&&r.setDeniedPage(e),await this._exitOldPage(this.currentPage),await r.render(),this.currentPage=r,this.events.emit("page:denied",{page:e,pageName:e.pageName,params:t,query:s,fromRouter:i})}async _exitOldPage(e){if(e)try{await e.onExit(),await e.unmount(),this.events.emit("page:hide",{page:e})}catch(t){console.error(`Error exiting page ${e.pageName}:`,t)}}async navigate(e,t={},s={}){if(!this.router){console.error("Router not initialized");return}let i=e;if(Object.keys(t).length>0){const r=new URLSearchParams(t).toString();i+=(e.includes("?")?"&":"?")+r}return await this.router.navigate(i,s)}async navigateToDefault(e={}){return await this.showPage(this.defaultRoute,{},{},e)}back(){this.router?this.router.back():console.warn("Router not initialized")}forward(){this.router?this.router.forward():console.warn("Router not initialized")}getCurrentPage(){return this.currentPage}getPageContainer(){return this.layout&&this.layout.getPageContainer?this.layout.getPageContainer():typeof this.pageContainer=="string"?document.querySelector(this.pageContainer):this.pageContainer}async showError(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Error",{size:"md",type:"error"})}catch(t){this.events.emit("notification",{message:e,type:"error"}),typeof window<"u"&&window?.console&&console.error("[WebApp] showError fallback:",t),typeof window<"u"&&alert(`Error: ${e}`)}}async showSuccess(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Success",{size:"md",type:"success"})}catch(t){this.events.emit("notification",{message:e,type:"success"}),typeof window<"u"&&window?.console&&console.warn("[WebApp] showSuccess fallback:",t),typeof window<"u"&&alert(`Success: ${e}`)}}async showInfo(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Information",{size:"md",type:"info"})}catch(t){this.events.emit("notification",{message:e,type:"info"}),typeof window<"u"&&window?.console&&console.info("[WebApp] showInfo fallback:",t),typeof window<"u"&&alert(`Info: ${e}`)}}async showWarning(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Warning",{size:"md",type:"warning"})}catch(t){this.events.emit("notification",{message:e,type:"warning"}),typeof window<"u"&&window?.console&&console.warn("[WebApp] showWarning fallback:",t),typeof window<"u"&&alert(`Warning: ${e}`)}}showNotification(e,t="info"){this.events.emit("notification",{message:e,type:t})}async showLoading(e={}){typeof e=="string"&&(e={message:e});try{(await Promise.resolve().then(()=>N)).default.showBusy(e)}catch(t){typeof window<"u"&&window?.console&&console.warn("[WebApp] showLoading fallback:",t,e),this.events.emit("notification",{message:e.message||"Loading...",type:"info"})}}async hideLoading(){try{(await Promise.resolve().then(()=>N)).default.hideBusy()}catch(e){typeof window<"u"&&window?.console&&console.warn("[WebApp] hideLoading fallback:",e)}}async showModelView(e,t={}){try{return await(await Promise.resolve().then(()=>N)).default.showModelView(e,t)}catch(s){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showModelForm failed:",s),s}}async showModelForm(e={}){try{return await(await Promise.resolve().then(()=>N)).default.modelForm(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showModelForm failed:",t),t}}async showForm(e={}){try{return await(await Promise.resolve().then(()=>N)).default.form(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showForm failed:",t),t}}async showDialog(e={}){try{return await(await Promise.resolve().then(()=>N)).default.dialog(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showDialog failed:",t),t}}async showAlert(e={}){try{return await(await Promise.resolve().then(()=>N)).default.dialog(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showDialog failed:",t),t}}async confirm(e,t="Confirm",s={}){return await(await Promise.resolve().then(()=>N)).default.confirm(e,t,s)}setTheme(e){return this.theme.set(e),this}getTheme(){return this.theme.getPreference()}getResolvedTheme(){return this.theme.getResolved()}setupFocusTracking(){if(typeof window>"u")return;this.isFocused=!document.hidden;const e=()=>{const i=this.isFocused;this.isFocused=!document.hidden,i!==this.isFocused&&(this.isFocused?this.events.emit("browser:focus"):this.events.emit("browser:blur"))},t=()=>{this.isFocused||(this.isFocused=!0,this.events.emit("browser:focus"))},s=()=>{this.isFocused&&(this.isFocused=!1,this.events.emit("browser:blur"))};document.addEventListener("visibilitychange",e),window.addEventListener("focus",t),window.addEventListener("blur",s),this._focusHandlers={visibilitychange:e,focus:t,blur:s}}setupErrorHandling(){window.addEventListener("error",e=>{console.error("Global error:",e.error),this.debug&&this.showError(`Error: ${e.error?.message||"Unknown error"}`)}),window.addEventListener("unhandledrejection",e=>{console.error("Unhandled promise rejection:",e.reason),this.debug&&this.showError(`Promise rejected: ${e.reason?.message||"Unknown error"}`)})}escapeHtml(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}getState(e){return e?this.state[e]:this.state}setState(e){const t={...this.state};Object.assign(this.state,e),this.events.emit("state:changed",{oldState:t,newState:this.state,updates:e})}registerComponent(e,t){this.componentClasses.set(e,t)}getComponent(e){return this.componentClasses.get(e)}registerModel(e,t){this.modelClasses.set(e,t)}getModel(e){return this.modelClasses.get(e)}registerModelRef(e,t){this.modelRefClasses.set(e,t)}getModelByRef(e){return this.modelRefClasses.get(e)}setupRest(){this.rest=ie,ie.configure(this.api)}async destroy(){console.log("Destroying WebApp..."),this.router&&this.router.stop(),this._focusHandlers&&typeof window<"u"&&(document.removeEventListener("visibilitychange",this._focusHandlers.visibilitychange),window.removeEventListener("focus",this._focusHandlers.focus),window.removeEventListener("blur",this._focusHandlers.blur));const e=Array.from(this.pageCache.values());if(await Promise.allSettled(e.map(async t=>{try{t.destroy&&await t.destroy()}catch(s){console.error("Error destroying page:",s)}})),this.layout&&this.layout.destroy)try{await this.layout.destroy()}catch(t){console.error("Error destroying layout:",t)}this.pageCache.clear(),this.pageClasses.clear(),this.componentClasses.clear(),this.modelClasses.clear(),typeof window<"u"&&window.MOJO&&delete window.MOJO.router,this.isStarted=!1,console.log(`✨ ${this.name} destroyed`)}buildPagePath(e,t,s){let i=e.route||`/${e.pageName.toLowerCase()}`;if(Object.keys(t).forEach(r=>{(typeof t[r]=="string"||typeof t[r]=="number")&&(i=i.replace(`:${r}`,t[r]))}),s&&Object.keys(s).length>0){const r=new URLSearchParams(s).toString();i+=(i.includes("?")?"&":"?")+r}return i}validateDefaultRoute(){this.pageClasses.has(this.defaultRoute)?console.log(`✅ Default route '${this.defaultRoute}' is registered`):(console.warn(`⚠️ Default route '${this.defaultRoute}' is not registered!`),console.warn(` Please register a page: app.registerPage('${this.defaultRoute}', YourPageClass);`),console.warn(" Or change default route: new WebApp({ defaultRoute: 'your-page' });"))}findFallbackPage(){const e=["404","error","denied"];for(const[t]of this.pageClasses.entries())if(!e.includes(t))return t;return null}static create(e={}){return new ve(e)}initPluginRegistry(){typeof window<"u"&&(window.MOJO||(window.MOJO={}),window.MOJO.plugins||(window.MOJO.plugins={}),window.MOJO.app=this)}static registerPlugin(e,t){typeof window<"u"&&(window.MOJO||(window.MOJO={}),window.MOJO.plugins||(window.MOJO.plugins={}),window.MOJO.plugins[e]=t,console.debug(`MOJO Plugin registered: ${e}`))}}class pe extends C{constructor(e={}){e.tagName=e.tagName||"main",e.className=e.className||"mojo-page";const t=e.pageName||"";t&&!e.id&&(e.id="page_"+t.toLowerCase().replace(/\s+/g,"_")),super(e),this.pageName=e.pageName||this.constructor.pageName||"",this.route=e.route||this.constructor.route||"",this.title=e.title||this.pageName||"",!this.id&&this.constructor.pageName&&!e.pageName&&(this.id="page_"+this.constructor.pageName.toLowerCase().replace(/\s+/g,"_")),this.pageIcon=e.icon||e.pageIcon||this.constructor.pageIcon||"bi bi-file-text",this.displayName=e.displayName||this.constructor.displayName||this.pageName||"",this.pageDescription=e.pageDescription||this.constructor.pageDescription||"",this.params={},this.query={},this.matched=!1,this.isActive=!1,this.pageOptions={title:e.title||this.pageName||"Untitled Page",description:e.description||"",requiresAuth:e.requiresAuth||!1,...e.pageOptions},this.savedState=null,console.log(`Page ${this.pageName} constructed with route: ${this.route}`)}async onParams(e={},t={}){this.params=e,this.query=t}canEnter(){if(this.options.permissions){const e=this.getApp().activeUser;if(!e||!e.hasPermission(this.options.permissions))return!1}return!(this.options.requiresGroup&&!this.getApp().activeGroup)}async onEnter(){this.isActive=!0,this._wasExited=!1,await this.onInitView(),this.savedState&&(this.restoreState(this.savedState),this.savedState=null),this.pageOptions&&this.pageOptions.title&&typeof document<"u"&&(document.title=this.pageOptions.title),this.emit("activated",{page:this.getMetadata()}),console.log(`Page ${this.pageName} entered`)}async onExit(){this.savedState=this.captureState(),this.isActive=!1,this._wasExited=!0,this._clearScheduledRefreshes(),this.emit("deactivated",{page:this.getMetadata()}),console.log(`Page ${this.pageName} exiting`)}scheduleRefresh(e,t,s={}){if(this._scheduledRefreshes||(this._scheduledRefreshes=[]),typeof e!="function"||!(t>0))return null;const i=async()=>{try{await e()}catch(a){console.warn(`[Page ${this.pageName}] scheduleRefresh handler error:`,a)}};s.immediate&&i();const r=setInterval(i,t),n={id:r,tier:s.tier||null,handler:i,intervalMs:t};return this._scheduledRefreshes.push(n),{cancel:()=>{clearInterval(r),this._scheduledRefreshes=(this._scheduledRefreshes||[]).filter(a=>a!==n)}}}async runScheduledRefreshes(e=null){const t=this._scheduledRefreshes||[],s=e?t.filter(i=>i.tier===e):t;await Promise.allSettled(s.map(i=>i.handler()))}_clearScheduledRefreshes(){if(this._scheduledRefreshes){for(const e of this._scheduledRefreshes)clearInterval(e.id);this._scheduledRefreshes=[]}}async render(e=!0,t=null){return this._wasExited&&!this.isActive?this:super.render(e,t)}async onGroupChange(e){}getMetadata(){return{name:this.pageName,displayName:this.displayName||this.pageName,icon:this.pageIcon,description:this.pageDescription,route:this.route,isActive:this.isActive}}async onActionDefault(e){console.log(`Default action '${e}' triggered on page: ${this.pageName}`)}async makeActive(){this.getApp().showPage(this)}async onActionNavigate(e,t){e.preventDefault();const s=t.dataset.page;this.getApp().showPage(s)}captureState(){return this.element?{scrollTop:this.element.scrollTop,formData:this.captureFormData(),custom:this.captureCustomState()}:null}restoreState(e){!e||!this.element||(this.element.scrollTop=e.scrollTop||0,this.restoreFormData(e.formData),e.custom&&this.restoreCustomState(e.custom))}captureFormData(){const e={};return this.element&&this.element.querySelectorAll("input, select, textarea").forEach(t=>{t.name&&(t.type==="checkbox"?e[t.name]=t.checked:t.type==="radio"?t.checked&&(e[t.name]=t.value):e[t.name]=t.value)}),e}restoreFormData(e){!e||!this.element||Object.entries(e).forEach(([t,s])=>{const i=this.element.querySelector(`[name="${t}"]`);if(i)if(i.type==="checkbox")i.checked=s;else if(i.type==="radio"){const r=this.element.querySelector(`[name="${t}"][value="${s}"]`);r&&(r.checked=!0)}else i.value=s})}captureCustomState(){return{}}restoreCustomState(e){}setMeta(e={}){if(!(typeof document>"u")){if(e.title&&(document.title=e.title,this.pageOptions.title=e.title),e.description){let t=document.querySelector('meta[name="description"]');t||(t=document.createElement("meta"),t.name="description",document.head.appendChild(t)),t.content=e.description,this.pageOptions.description=e.description}Object.entries(e).forEach(([t,s])=>{if(t!=="title"&&t!=="description"){let i=document.querySelector(`meta[name="${t}"]`);i||(i=document.createElement("meta"),i.name=t,document.head.appendChild(i)),i.content=s}})}}showError(e){if(super.showError(e),this.element){const t=document.createElement("div");t.className="alert alert-danger alert-dismissible fade show",t.innerHTML=`
218
+ `,size:s.size||"sm",centered:!0,backdrop:"static",buttons:o,...s});return l.on("shown",()=>{const d=l.element.querySelector(`#${i}`);d&&(d.focus(),d.select())}),w._renderAndAwait(l,{buttons:o,onAction:async d=>{if(d!=="ok")return null;const h=l.element.querySelector(`#${i}`);return h?h.value:null}})}static showError(e){return w.alert(e,"Error",{type:"error"})}static async form(e={}){const{title:t="Form",formConfig:s={},size:i="md",centered:r=!0,submitText:n="Submit",cancelText:a="Cancel",...o}=e,l=(await Promise.resolve().then(()=>Et)).default,d=new l({fileHandling:e.fileHandling||"base64",data:e.data,defaults:e.defaults,model:e.model,formConfig:{fields:s.fields||e.fields,...s,submitButton:!1,resetButton:!1}}),h=[{text:a,class:"btn-secondary",action:"cancel"},{text:n,class:"btn-primary",action:"submit"}],u=new x({title:t,body:d,size:i,centered:r,buttons:h,...o});return w._renderAndAwait(u,{buttons:h,onAction:async m=>{if(m==="cancel")return u.hide(),null;if(m!=="submit")return null;if(!d.validate())return d.focusFirstError(),!1;if(e.autoSave&&e.model){u.setLoading(!0);const p=await d.saveModel();return p.success?p:(u.setLoading(!1),await u.render(),u.getApp()?.toast?.error(p.message),!1)}try{return await d.getFormData()}catch(p){return console.error("Modal.form: error collecting form data:",p),d.showError("Error collecting form data"),!1}},cleanup:async()=>{try{await d.destroy()}catch{}}})}static async modelForm(e={}){const{title:t="Edit",formConfig:s={},size:i="md",centered:r=!0,submitText:n="Save",cancelText:a="Cancel",model:o,fields:l,...d}=e;if(!o)throw new Error("Modal.modelForm requires a model");const h=(await Promise.resolve().then(()=>Et)).default,u=new h({fileHandling:e.fileHandling||"base64",model:o,data:e.data,defaults:e.defaults,formConfig:{fields:l||s.fields||[],...s,submitButton:!1,resetButton:!1}}),m=[{text:a,class:"btn-secondary",action:"cancel"},{text:n,class:"btn-primary",action:"submit"}],p=new x({title:t,body:u,size:i,centered:r,buttons:m,...d});return w._renderAndAwait(p,{buttons:m,onAction:async f=>{if(f==="cancel")return p.hide(),null;if(f!=="submit")return null;p.setLoading(!0,"Saving...");try{const g=await u.handleSubmit();if(g.success)return g;p.setLoading(!1);let b=g.error;return g.data?.error&&(b=g.data.error),p.getApp()?.toast?.error(b),!1}catch(g){return console.error("Modal.modelForm: error saving:",g),await p.setContent(u),u.showError(g.message||"An error occurred while saving"),!1}},cleanup:async()=>{try{await u.destroy()}catch{}}})}static async data(e={}){const{title:t="Data View",data:s={},model:i=null,fields:r=[],columns:n=2,responsive:a=!0,showEmptyValues:o=!1,emptyValueText:l="—",size:d="lg",centered:h=!0,closeText:u="Close",...m}=e,p=(await Promise.resolve().then(()=>As)).default,f=new p({data:s,model:i,fields:r,columns:n,responsive:a,showEmptyValues:o,emptyValueText:l}),g=[{text:u,class:"btn-secondary",value:"close"}],b=new x({title:t,body:f,size:d,centered:h,buttons:g,...m});return f.on("field:click",y=>b.emit("dataview:field:click",y)),f.on("error",y=>b.emit("dataview:error",y)),w._renderAndAwait(b,{buttons:g,cleanup:async()=>{try{await f.destroy()}catch{}}})}static async code(e={}){const{code:t="",language:s="javascript",title:i="Source Code",size:r="lg",...n}=e,a=new me({code:t,language:s}),o=[{text:"Copy to Clipboard",class:"btn-primary",icon:"bi-clipboard",action:"copy"},{text:"Close",class:"btn-secondary",dismiss:!0}],l=new x({title:i,body:a,size:r,scrollable:!0,buttons:o,...n});return w._renderAndAwait(l,{buttons:o,onAction:async d=>{if(d!=="copy")return null;if(!navigator.clipboard)return!1;try{await navigator.clipboard.writeText(t),w._showCopySuccess(l)}catch(h){console.error("Modal.code: clipboard write failed:",h)}return!1}})}static _showCopySuccess(e){const t=e.element?.querySelector('[data-action="copy"]');if(!t)return;const s=t.innerHTML;t.innerHTML='<i class="bi bi-check me-1"></i>Copied!',t.classList.remove("btn-primary"),t.classList.add("btn-success"),t.disabled=!0,setTimeout(()=>{t.innerHTML=s,t.classList.remove("btn-success"),t.classList.add("btn-primary"),t.disabled=!1},2e3)}static async htmlPreview(e={}){const{html:t=e.content||"",title:s="HTML Preview",size:i="lg",height:r=500,...n}=e,a=new Ut({html:t,height:r}),o=[{text:"Close",class:"btn-secondary",dismiss:!0}],l=new x({title:s,body:a,size:i,scrollable:!1,buttons:o,...n});return w._renderAndAwait(l,{buttons:o})}static async updateModelImage(e={},t={}){const s=e.upload||!1,i=t.name||e.field||"image",r={title:"Upload Your Avatar",model:null,autoSave:!s,size:"sm",fields:[{type:"image",name:i,size:"lg",imageSize:{width:200,height:200},placeholder:"Upload your image",...t}],...e},n=await w.form(r);if(!s||!n||!e.model)return n;const a=n[i];if(!a||!a.startsWith("data:"))return n;const o=a.split(","),d=o[0]?.match(/:(.*?);/)?.[1]||"image/png",h=atob(o[1]);let u=h.length;const m=new Uint8Array(u);for(;u--;)m[u]=h.charCodeAt(u);const p=d.split("/")[1]||"png",f=typeof window<"u"&&window.File||globalThis.File;if(!f)throw new Error("File API is not available in this environment");const g=new f([m],`${i}.${p}`,{type:d}),b=new ht;return await b.upload({file:g,name:`${i}.${p}`,description:e.uploadDescription||`${i} upload`,showToast:!0}),e.model.save({[i]:b.id})}static loading(e){ke.show(e)}static hideLoading(e){ke.hide(e)}static showBusy(e){return w.loading(e)}static hideBusy(e){return w.hideLoading(e)}}const N=Object.freeze(Object.defineProperty({__proto__:null,default:w},Symbol.toStringTag,{value:"Module"}));class ve{constructor(e={}){this.config=e,this.initPluginRegistry(),this.name=e.name||"MOJO App",this.version=e.version||"1.0.0",this.debug=e.debug||!1,this.container=e.container||"#app",this.layoutType=e.layout||"portal",this.layoutConfig=e.layoutConfig||{},e.sidebar&&(this.layoutConfig.sidebarConfig=e.sidebar),e.topbar&&(this.layoutConfig.topbarConfig=e.topbar),this.layout=null,this.layoutConfig.containerId=this.container||this.containerId||"#app",this.pageContainer=e.pageContainer||"#page-container",this.basePath=e.basePath||"",this.routerMode=e.routerMode||e.router?.mode||"param",this.basePath=e.basePath||e.router?.base||"",this.defaultRoute=e.defaultRoute||"home",this.session=e.session||{},this.router=null,this.navigation=e.navigation||{},this.state={currentPage:null,previousPage:null,loading:!1},this.events=new kt,this.rest=re,this.modal=w,e.api&&this.rest.configure(e.api);const t=(this.name||"mojo").replace(/\s+/g,"_").toLowerCase();this.theme=new Lt({storageKey:`${t}:theme`,eventBus:this.events}),this.theme.init(),this.router=new Te({mode:this.routerMode==="param"?"params":this.routerMode,basePath:this.basePath,defaultRoute:this.defaultRoute,eventEmitter:this.events}),this.events.on("route:changed",async s=>{const{pageName:i,params:r,query:n}=s;await this.showPage(i,n,r,{fromRouter:!0})}),typeof window<"u"&&(window.MOJO=window.MOJO||{},window.MOJO.router=this.router),this.setupFocusTracking(),this.pageCache=new Map,this.pageClasses=new Map,this.componentClasses=new Map,this.modelClasses=new Map,this.modelRefClasses=new Map,this.currentPage=null,this.isStarted=!1,window.matchUUID?window[window.matchUUID]=this:window.MOJO?window.MOJO.app=this:window.__app__=this}async start(){if(this.isStarted){console.warn("WebApp already started");return}try{this.setupPageContainer(),this.validateDefaultRoute(),await this.setupRouter(),this.isStarted=!0,this.router.allowPopState=!1,this.events.emit("app:ready",{app:this})}catch(e){throw console.error(`Failed to start ${this.name}:`,e),this.showError("Failed to start application"),e}}async setupRouter(){if(!this.router){console.error("Router not initialized");return}this.events.on("route:notfound",async e=>{console.warn(`Route not found: ${e.path}`),this._show404(e.path)}),this.router.start(),console.log(`Router started in ${this.routerMode} mode`)}setupPageContainer(){const e=typeof this.container=="string"?document.querySelector(this.container):this.container;e&&!e.querySelector("#page-container")&&(e.innerHTML='<div id="page-container"></div>'),this.pageContainer="#page-container"}registerPage(e,t,s={}){if(typeof e!="string"||!e)return console.error("registerPage: pageName must be a non-empty string"),this;if(typeof t!="function")return console.error("registerPage: PageClass must be a constructor function"),this;if(s.containerId||(s.containerId=this.pageContainer),this.pageClasses.set(e,{PageClass:t,constructorOptions:s}),this.router){let i=s.route||`/${e}`;i.startsWith("/")||(i=`/${i}`),s.route=i,this.router.addRoute(i,e)}return this}getPage(e){return this.pageCache.get(e)}getPagePermissions(e){if(this.pageCache.has(e))return this.pageCache.get(e).permissions;const t=this.pageClasses.get(e);if(!t)return null;const{PageClass:s,constructorOptions:i}=t;return i?i.permissions:null}getOrCreatePage(e){if(this.pageCache.has(e))return this.pageCache.get(e);const t=this.pageClasses.get(e);if(!t)return console.error(`Page not registered: ${e}`),null;const{PageClass:s,constructorOptions:i}=t;try{const r={pageName:e,...i,app:this},n=new s(r);return i.route&&(n.route=i.route),this.pageCache.set(e,n),console.log(`Created page: ${e} with route: ${n.route}`),n}catch(r){return console.error(`Failed to create page ${e}:`,r),null}}async showPage(e,t={},s={},i={}){const{fromRouter:r=!1,replace:n=!1,force:a=!1}=i;try{let o,l;typeof e=="string"?(l=e,o=this.getOrCreatePage(e)):e&&typeof e=="object"&&(o=e,l=e.pageName);const d=this.currentPage;if(!o){this._show404(l,s,t,r);return}if(this.events.emit("page:showing",{page:o,pageName:o.pageName,params:s,query:t,fromRouter:r}),!o.canEnter()){this._showDeniedPage(o,s,t,r);return}d&&d!==o&&await this._exitOldPage(d),await o.onParams(s,t),d!==o&&await o.onEnter(),o.syncUrl(),this.events.emit("page:show",{page:o,pageName:o.pageName,params:s,query:t,fromRouter:r}),await o.render(),this.currentPage=o,console.log(`✅ Showing page: ${o.pageName}`,{query:t,params:s})}catch(o){console.error("Error in showPage:",o),this.showError(`Failed to load page: ${o.message}`),e!=="error"&&await this.showPage("error",{},{error:o,originalPage:e},{fromRouter:r})}}async _show404(e,t,s,i){const r=this.getOrCreatePage("404");r&&(r.setInfo&&r.setInfo(e),await this._exitOldPage(this.currentPage),await r.render(),this.currentPage=r,this.events.emit("page:404",{page:null,pageName:e,params:t,query:s,fromRouter:i}))}async _showDeniedPage(e,t,s,i){const r=this.getOrCreatePage("denied");r.setDeniedPage&&r.setDeniedPage(e),await this._exitOldPage(this.currentPage),await r.render(),this.currentPage=r,this.events.emit("page:denied",{page:e,pageName:e.pageName,params:t,query:s,fromRouter:i})}async _exitOldPage(e){if(e)try{await e.onExit(),await e.unmount(),this.events.emit("page:hide",{page:e})}catch(t){console.error(`Error exiting page ${e.pageName}:`,t)}}async navigate(e,t={},s={}){if(!this.router){console.error("Router not initialized");return}let i=e;if(Object.keys(t).length>0){const r=new URLSearchParams(t).toString();i+=(e.includes("?")?"&":"?")+r}return await this.router.navigate(i,s)}async navigateToDefault(e={}){return await this.showPage(this.defaultRoute,{},{},e)}back(){this.router?this.router.back():console.warn("Router not initialized")}forward(){this.router?this.router.forward():console.warn("Router not initialized")}getCurrentPage(){return this.currentPage}getPageContainer(){return this.layout&&this.layout.getPageContainer?this.layout.getPageContainer():typeof this.pageContainer=="string"?document.querySelector(this.pageContainer):this.pageContainer}async showError(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Error",{size:"md",type:"error"})}catch(t){this.events.emit("notification",{message:e,type:"error"}),typeof window<"u"&&window?.console&&console.error("[WebApp] showError fallback:",t),typeof window<"u"&&alert(`Error: ${e}`)}}async showSuccess(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Success",{size:"md",type:"success"})}catch(t){this.events.emit("notification",{message:e,type:"success"}),typeof window<"u"&&window?.console&&console.warn("[WebApp] showSuccess fallback:",t),typeof window<"u"&&alert(`Success: ${e}`)}}async showInfo(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Information",{size:"md",type:"info"})}catch(t){this.events.emit("notification",{message:e,type:"info"}),typeof window<"u"&&window?.console&&console.info("[WebApp] showInfo fallback:",t),typeof window<"u"&&alert(`Info: ${e}`)}}async showWarning(e){try{await(await Promise.resolve().then(()=>N)).default.alert(e,"Warning",{size:"md",type:"warning"})}catch(t){this.events.emit("notification",{message:e,type:"warning"}),typeof window<"u"&&window?.console&&console.warn("[WebApp] showWarning fallback:",t),typeof window<"u"&&alert(`Warning: ${e}`)}}showNotification(e,t="info"){this.events.emit("notification",{message:e,type:t})}async showLoading(e={}){typeof e=="string"&&(e={message:e});try{(await Promise.resolve().then(()=>N)).default.showBusy(e)}catch(t){typeof window<"u"&&window?.console&&console.warn("[WebApp] showLoading fallback:",t,e),this.events.emit("notification",{message:e.message||"Loading...",type:"info"})}}async hideLoading(){try{(await Promise.resolve().then(()=>N)).default.hideBusy()}catch(e){typeof window<"u"&&window?.console&&console.warn("[WebApp] hideLoading fallback:",e)}}async showModelView(e,t={}){try{return await(await Promise.resolve().then(()=>N)).default.showModelView(e,t)}catch(s){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showModelForm failed:",s),s}}async showModelForm(e={}){try{return await(await Promise.resolve().then(()=>N)).default.modelForm(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showModelForm failed:",t),t}}async showForm(e={}){try{return await(await Promise.resolve().then(()=>N)).default.form(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showForm failed:",t),t}}async showDialog(e={}){try{return await(await Promise.resolve().then(()=>N)).default.dialog(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showDialog failed:",t),t}}async showAlert(e={}){try{return await(await Promise.resolve().then(()=>N)).default.dialog(e)}catch(t){throw typeof window<"u"&&window?.console&&console.error("[WebApp] showDialog failed:",t),t}}async confirm(e,t="Confirm",s={}){return await(await Promise.resolve().then(()=>N)).default.confirm(e,t,s)}setTheme(e){return this.theme.set(e),this}getTheme(){return this.theme.getPreference()}getResolvedTheme(){return this.theme.getResolved()}setupFocusTracking(){if(typeof window>"u")return;this.isFocused=!document.hidden;const e=()=>{const i=this.isFocused;this.isFocused=!document.hidden,i!==this.isFocused&&(this.isFocused?this.events.emit("browser:focus"):this.events.emit("browser:blur"))},t=()=>{this.isFocused||(this.isFocused=!0,this.events.emit("browser:focus"))},s=()=>{this.isFocused&&(this.isFocused=!1,this.events.emit("browser:blur"))};document.addEventListener("visibilitychange",e),window.addEventListener("focus",t),window.addEventListener("blur",s),this._focusHandlers={visibilitychange:e,focus:t,blur:s}}setupErrorHandling(){window.addEventListener("error",e=>{console.error("Global error:",e.error),this.debug&&this.showError(`Error: ${e.error?.message||"Unknown error"}`)}),window.addEventListener("unhandledrejection",e=>{console.error("Unhandled promise rejection:",e.reason),this.debug&&this.showError(`Promise rejected: ${e.reason?.message||"Unknown error"}`)})}escapeHtml(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}getState(e){return e?this.state[e]:this.state}setState(e){const t={...this.state};Object.assign(this.state,e),this.events.emit("state:changed",{oldState:t,newState:this.state,updates:e})}registerComponent(e,t){this.componentClasses.set(e,t)}getComponent(e){return this.componentClasses.get(e)}registerModel(e,t){this.modelClasses.set(e,t)}getModel(e){return this.modelClasses.get(e)}registerModelRef(e,t){this.modelRefClasses.set(e,t)}getModelByRef(e){return this.modelRefClasses.get(e)}setupRest(){this.rest=re,re.configure(this.api)}async destroy(){console.log("Destroying WebApp..."),this.router&&this.router.stop(),this._focusHandlers&&typeof window<"u"&&(document.removeEventListener("visibilitychange",this._focusHandlers.visibilitychange),window.removeEventListener("focus",this._focusHandlers.focus),window.removeEventListener("blur",this._focusHandlers.blur));const e=Array.from(this.pageCache.values());if(await Promise.allSettled(e.map(async t=>{try{t.destroy&&await t.destroy()}catch(s){console.error("Error destroying page:",s)}})),this.layout&&this.layout.destroy)try{await this.layout.destroy()}catch(t){console.error("Error destroying layout:",t)}this.pageCache.clear(),this.pageClasses.clear(),this.componentClasses.clear(),this.modelClasses.clear(),typeof window<"u"&&window.MOJO&&delete window.MOJO.router,this.isStarted=!1,console.log(`✨ ${this.name} destroyed`)}buildPagePath(e,t,s){let i=e.route||`/${e.pageName.toLowerCase()}`;if(Object.keys(t).forEach(r=>{(typeof t[r]=="string"||typeof t[r]=="number")&&(i=i.replace(`:${r}`,t[r]))}),s&&Object.keys(s).length>0){const r=new URLSearchParams(s).toString();i+=(i.includes("?")?"&":"?")+r}return i}validateDefaultRoute(){this.pageClasses.has(this.defaultRoute)?console.log(`✅ Default route '${this.defaultRoute}' is registered`):(console.warn(`⚠️ Default route '${this.defaultRoute}' is not registered!`),console.warn(` Please register a page: app.registerPage('${this.defaultRoute}', YourPageClass);`),console.warn(" Or change default route: new WebApp({ defaultRoute: 'your-page' });"))}findFallbackPage(){const e=["404","error","denied"];for(const[t]of this.pageClasses.entries())if(!e.includes(t))return t;return null}static create(e={}){return new ve(e)}initPluginRegistry(){typeof window<"u"&&(window.MOJO||(window.MOJO={}),window.MOJO.plugins||(window.MOJO.plugins={}),window.MOJO.app=this)}static registerPlugin(e,t){typeof window<"u"&&(window.MOJO||(window.MOJO={}),window.MOJO.plugins||(window.MOJO.plugins={}),window.MOJO.plugins[e]=t,console.debug(`MOJO Plugin registered: ${e}`))}}class pe extends C{constructor(e={}){e.tagName=e.tagName||"main",e.className=e.className||"mojo-page";const t=e.pageName||"";t&&!e.id&&(e.id="page_"+t.toLowerCase().replace(/\s+/g,"_")),super(e),this.pageName=e.pageName||this.constructor.pageName||"",this.route=e.route||this.constructor.route||"",this.title=e.title||this.pageName||"",!this.id&&this.constructor.pageName&&!e.pageName&&(this.id="page_"+this.constructor.pageName.toLowerCase().replace(/\s+/g,"_")),this.pageIcon=e.icon||e.pageIcon||this.constructor.pageIcon||"bi bi-file-text",this.displayName=e.displayName||this.constructor.displayName||this.pageName||"",this.pageDescription=e.pageDescription||this.constructor.pageDescription||"",this.params={},this.query={},this.matched=!1,this.isActive=!1,this.pageOptions={title:e.title||this.pageName||"Untitled Page",description:e.description||"",requiresAuth:e.requiresAuth||!1,...e.pageOptions},this.savedState=null,console.log(`Page ${this.pageName} constructed with route: ${this.route}`)}async onParams(e={},t={}){this.params=e,this.query=t}canEnter(){if(this.options.permissions){const e=this.getApp().activeUser;if(!e||!e.hasPermission(this.options.permissions))return!1}return!(this.options.requiresGroup&&!this.getApp().activeGroup)}async onEnter(){this.isActive=!0,this._wasExited=!1,await this.onInitView(),this.savedState&&(this.restoreState(this.savedState),this.savedState=null),this.pageOptions&&this.pageOptions.title&&typeof document<"u"&&(document.title=this.pageOptions.title),this.emit("activated",{page:this.getMetadata()}),console.log(`Page ${this.pageName} entered`)}async onExit(){this.savedState=this.captureState(),this.isActive=!1,this._wasExited=!0,this._clearScheduledRefreshes(),this.emit("deactivated",{page:this.getMetadata()}),console.log(`Page ${this.pageName} exiting`)}scheduleRefresh(e,t,s={}){if(this._scheduledRefreshes||(this._scheduledRefreshes=[]),typeof e!="function"||!(t>0))return null;const i=async()=>{try{await e()}catch(a){console.warn(`[Page ${this.pageName}] scheduleRefresh handler error:`,a)}};s.immediate&&i();const r=setInterval(i,t),n={id:r,tier:s.tier||null,handler:i,intervalMs:t};return this._scheduledRefreshes.push(n),{cancel:()=>{clearInterval(r),this._scheduledRefreshes=(this._scheduledRefreshes||[]).filter(a=>a!==n)}}}async runScheduledRefreshes(e=null){const t=this._scheduledRefreshes||[],s=e?t.filter(i=>i.tier===e):t;await Promise.allSettled(s.map(i=>i.handler()))}_clearScheduledRefreshes(){if(this._scheduledRefreshes){for(const e of this._scheduledRefreshes)clearInterval(e.id);this._scheduledRefreshes=[]}}async render(e=!0,t=null){return this._wasExited&&!this.isActive?this:super.render(e,t)}async onGroupChange(e){}getMetadata(){return{name:this.pageName,displayName:this.displayName||this.pageName,icon:this.pageIcon,description:this.pageDescription,route:this.route,isActive:this.isActive}}async onActionDefault(e){console.log(`Default action '${e}' triggered on page: ${this.pageName}`)}async makeActive(){this.getApp().showPage(this)}async onActionNavigate(e,t){e.preventDefault();const s=t.dataset.page;this.getApp().showPage(s)}captureState(){return this.element?{scrollTop:this.element.scrollTop,formData:this.captureFormData(),custom:this.captureCustomState()}:null}restoreState(e){!e||!this.element||(this.element.scrollTop=e.scrollTop||0,this.restoreFormData(e.formData),e.custom&&this.restoreCustomState(e.custom))}captureFormData(){const e={};return this.element&&this.element.querySelectorAll("input, select, textarea").forEach(t=>{t.name&&(t.type==="checkbox"?e[t.name]=t.checked:t.type==="radio"?t.checked&&(e[t.name]=t.value):e[t.name]=t.value)}),e}restoreFormData(e){!e||!this.element||Object.entries(e).forEach(([t,s])=>{const i=this.element.querySelector(`[name="${t}"]`);if(i)if(i.type==="checkbox")i.checked=s;else if(i.type==="radio"){const r=this.element.querySelector(`[name="${t}"][value="${s}"]`);r&&(r.checked=!0)}else i.value=s})}captureCustomState(){return{}}restoreCustomState(e){}setMeta(e={}){if(!(typeof document>"u")){if(e.title&&(document.title=e.title,this.pageOptions.title=e.title),e.description){let t=document.querySelector('meta[name="description"]');t||(t=document.createElement("meta"),t.name="description",document.head.appendChild(t)),t.content=e.description,this.pageOptions.description=e.description}Object.entries(e).forEach(([t,s])=>{if(t!=="title"&&t!=="description"){let i=document.querySelector(`meta[name="${t}"]`);i||(i=document.createElement("meta"),i.name=t,document.head.appendChild(i)),i.content=s}})}}showError(e){if(super.showError(e),this.element){const t=document.createElement("div");t.className="alert alert-danger alert-dismissible fade show",t.innerHTML=`
219
219
  ${e}
220
220
  <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
221
221
  `,this.element.insertBefore(t,this.element.firstChild),setTimeout(()=>{t.parentNode&&t.parentNode.removeChild(t)},5e3)}}showSuccess(e){if(super.showSuccess(e),this.element){const t=document.createElement("div");t.className="alert alert-success alert-dismissible fade show",t.innerHTML=`
@@ -660,14 +660,14 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
660
660
  </div>
661
661
  </div>
662
662
  </div>
663
- `}buildFieldHTML(e){const{type:t,columns:s,class:i=""}=e;let r="";const n=Q&&typeof Q.getRenderer=="function"?Q.getRenderer(t):null;if(typeof n=="function")try{const d=n(this,e);d!=null&&(r=String(d))}catch(d){console.error("FormPlugins custom renderer error:",d)}if(!r)switch(t){case"text":r=this.renderTextField(e);break;case"email":r=this.renderEmailField(e);break;case"password":r=this.renderPasswordField(e);break;case"number":r=this.renderNumberField(e);break;case"tel":r=this.renderTelField(e);break;case"url":r=this.renderUrlField(e);break;case"search":r=this.renderSearchField(e);break;case"hex":r=this.renderHexField(e);break;case"textarea":r=this.renderTextareaField(e);break;case"htmlpreview":r=this.renderHtmlPreviewField(e);break;case"json":r=this.renderJsonField(e);break;case"select":r=this.renderSelectField(e);break;case"multiselect":r=this.renderMultiSelectField(e);break;case"checkbox":r=this.renderCheckboxField(e);break;case"toggle":case"switch":r=this.renderSwitchField(e);break;case"radio":r=this.renderRadioField(e);break;case"date":r=this.renderDateField(e);break;case"datetime":r=this.renderDateTimeField(e);break;case"time":r=this.renderTimeField(e);break;case"file":r=this.renderFileField(e);break;case"image":r=this.renderImageField(e);break;case"color":r=this.renderColorField(e);break;case"range":r=this.renderRangeField(e);break;case"hidden":r=this.renderHiddenField(e);break;case"button":r=this.renderButton(e);break;case"divider":r=this.renderDivider(e);break;case"html":r=this.renderHtmlField(e);break;case"heading":case"header":r=this.renderHeaderField(e);break;case"tag":case"tags":r=this.renderTagField(e);break;case"collection":r=this.renderCollectionField(e);break;case"collectionmultiselect":case"collection-multiselect":r=this.renderCollectionMultiSelectField(e);break;case"datepicker":r=this.renderDatePickerField(e);break;case"monthpicker":r=this.renderDatePickerField({...e,precision:"month"});break;case"yearpicker":r=this.renderDatePickerField({...e,precision:"year"});break;case"daterange":r=this.renderDateRangeField(e);break;case"monthrange":r=this.renderDateRangeField({...e,precision:"month"});break;case"yearrange":r=this.renderDateRangeField({...e,precision:"year"});break;case"timepicker":r=this.renderTimePickerField(e);break;case"datetimepicker":r=this.renderDateTimePickerField(e);break;case"checklistdropdown":r=this.renderChecklistDropdownField(e);break;case"buttongroup":r=this.renderButtonGroupField(e);break;case"combo":case"combobox":case"autocomplete":r=this.renderComboField(e);break;case"tabset":r=this.renderTabsetField(e);break;default:console.warn(`Unknown field type: ${t}`),r=this.renderTextField(e)}let a;if(this.isAutoSizingField(e))a=`col ${i}`.trim();else if(typeof s=="object"&&s!==null){const d=[];s.xs&&d.push(`col-${s.xs}`),s.sm&&d.push(`col-sm-${s.sm}`),s.md&&d.push(`col-md-${s.md}`),s.lg&&d.push(`col-lg-${s.lg}`),s.xl&&d.push(`col-xl-${s.xl}`),s.xxl&&d.push(`col-xxl-${s.xxl}`),d.length===0&&d.push("col-12"),i&&d.push(i),a=d.join(" ")}else a=`col-${s} ${i}`.trim();let o="",l="";if(e.showWhen){const d=e.showWhen,h=Array.isArray(d.value)?d.value:[d.value];o=` data-show-when-field="${d.field}" data-show-when-value="${h.join(",")}"`,d.negate&&(o+=' data-show-when-negate="true"');let u=this.data[d.field];if(u==null){const g=this._findField(d.field,this.fields);g&&(u=g.value)}const m=String(u??""),p=h.map(String).includes(m);(d.negate?!p:p)||(l=' style="display:none"')}return`<div class="${a}"${o}${l}>${r}</div>`}_findField(e,t){for(const s of t){if(s.name===e)return s;if(s.fields){const i=this._findField(e,s.fields);if(i)return i}if(s.tabs){for(const i of s.tabs)if(i.fields){const r=this._findField(e,i.fields);if(r)return r}}}return null}getFieldId(e){return e?`field_${e.replace(/[.\s\[\]]/g,"_")}`:`field_${Math.random().toString(36).substr(2,9)}`}renderTextField(e){return this.renderInputField(e,"text")}renderEmailField(e){return this.renderInputField(e,"email")}renderPasswordField(e){const t=e.passwordUsage||"current",s=t==="new"||t==="new-password"?"new-password":"current-password",i={...e.attributes||{},autocomplete:e.attributes&&e.attributes.autocomplete||s};return this.renderInputField({...e,showToggle:e.showToggle!==!1,attributes:i},"password")}renderNumberField(e){const{min:t,max:s,step:i=1,...r}=e,n=[];return t!==void 0&&n.push(`min="${t}"`),s!==void 0&&n.push(`max="${s}"`),i!==void 0&&n.push(`step="${i}"`),this.renderInputField({...r,attributes:{...r.attributes,...n.reduce((a,o)=>{const[l,d]=o.split("=");return a[l]=d.replace(/"/g,""),a},{})}},"number")}renderTelField(e){return this.renderInputField(e,"tel")}renderUrlField(e){return this.renderInputField(e,"url")}renderSearchField(e){const t={...e,attributes:{"data-filter":"live-search","data-change-action":"filter-search","data-filter-debounce":e.debounce||"300",...e.attributes}};return this.renderInputField(t,"search")}renderHexField(e){const{hexType:t="color",allowPrefix:s=!0,minLength:i,maxLength:r,...n}=e;let a,o,l,d,h;switch(t){case"color":a=s?"^#?[0-9A-Fa-f]{6}$":"^[0-9A-Fa-f]{6}$",o=6,l=s?7:6,d=s?"#FF0000":"FF0000",h=h||"Enter a valid hex color (e.g., "+d+")";break;case"color-short":a=s?"^#?[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$":"^[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$",o=s?4:3,l=s?7:6,d=s?"#F00 or #FF0000":"F00 or FF0000",h=h||"Enter a valid hex color (3 or 6 digits)";break;case"string":a="^[0-9A-Fa-f]+$",o=i||1,l=r||64,d="ABCDEF123456",h=h||"Only hexadecimal characters (0-9, A-F) allowed";break;default:a=s?"^#?[0-9A-Fa-f]+$":"^[0-9A-Fa-f]+$",o=i||1,l=r||64,d=s?"#ABCDEF or ABCDEF":"ABCDEF",h=h||"Enter hexadecimal characters only"}const u={...n,pattern:a,minLength:o,maxLength:l,placeholder:n.placeholder||d,help:n.help||h,attributes:{"data-hex-type":t,"data-allow-prefix":s,style:"text-transform: uppercase;",...n.attributes}};return this.renderInputField(u,"text")}renderInputField(e,t="text"){const{name:s,label:i,value:r="",placeholder:n="",required:a=!1,disabled:o=!1,readonly:l=!1,class:d="",attributes:h={},help:u=e.helpText||e.help||""}=e,m=`${this.options.inputClass} ${d}`.trim(),p=this.errors[s],f=this.getFieldValue(s)??r,g=Object.entries(h).map(([v,_])=>`${v}="${this.escapeHtml(_)}"`).join(" "),b=this.getFieldId(s),y={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:b,name:s,type:t,fieldValue:this.escapeHtml(f),label:i?this.escapeHtml(i):null,placeholder:n?this.escapeHtml(n):null,help:u?this.escapeHtml(u):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:p?this.escapeHtml(p):null,required:a,disabled:o,readonly:l,attrs:g,showCopy:!!e.showCopy};if(t==="password"&&(e.showToggle||e.strengthMeter||e.capsLockWarning)){const v={...y,showToggle:!!e.showToggle,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,v)}if(t==="password"){const v={...y,showToggle:e.showToggle!==!1,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,v)}return D.render(this.templates.input,y)}renderTextareaField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,rows:l=3,cols:d,class:h="",attributes:u={},help:m=e.helpText||e.help||""}=e,p=`${this.options.inputClass} ${h}`.trim(),f=this.errors[t],g=this.getFieldValue(t)??i,b=Object.entries(u).map(([_,A])=>`${_}="${this.escapeHtml(A)}"`).join(" "),y=this.getFieldId(t),v={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:y,name:t,fieldValue:g,label:s?this.escapeHtml(s):null,placeholder:r?this.escapeHtml(r):null,help:m?this.escapeHtml(m):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:f?this.escapeHtml(f):null,rows:l||3,required:n,disabled:a,readonly:o,showCopy:!!e.showCopy,attrs:b};return D.render(this.templates.textarea,v)}renderHtmlPreviewField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,rows:l=5,class:d="",attributes:h={},help:u=e.helpText||e.help||""}=e,m=`${this.options.inputClass} ${d}`.trim(),p=this.errors[t],f=this.getFieldValue(t)??i,g=Object.entries(h).map(([v,_])=>`${v}="${this.escapeHtml(_)}"`).join(" "),b=this.getFieldId(t),y={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:b,name:t,fieldValue:f,label:s?this.escapeHtml(s):null,placeholder:r?this.escapeHtml(r):null,help:u?this.escapeHtml(u):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:p?this.escapeHtml(p):null,rows:l||5,required:n,disabled:a,readonly:o,attrs:g,showCopy:!!e.showCopy};return D.render(this.templates.htmlpreview,y)}renderJsonField(e){const{name:t,label:s,placeholder:i="",required:r=!1,disabled:n=!1,readonly:a=!1,rows:o=3,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=this.getFieldValue(e.name)??e.value??{};let m=u;if(typeof u=="object"&&u!==null)try{m=JSON.stringify(u,null,2)}catch{m="{}"}else typeof u!="string"&&(m=String(u));const p=`${this.options.inputClass} ${l}`.trim(),f=this.errors[t],g=this.getFieldId(t),b=Object.entries({...d,"data-field-type":"json"}).map(([v,_])=>`${v}="${this.escapeHtml(_)}"`).join(" "),y={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,fieldValue:m,label:s?this.escapeHtml(s):null,placeholder:i?this.escapeHtml(i):null,help:h?this.escapeHtml(h):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:f?this.escapeHtml(f):null,rows:o||3,required:r,disabled:n,readonly:a,attrs:b};return D.render(this.templates.textarea,y)}renderSelectField(e){const{name:t,label:s,options:i=[],value:r="",required:n=!1,disabled:a=!1,multiple:o=!1,searchable:l=!1,class:d="",attributes:h={},help:u=e.helpText||e.help||"",start:m=e.start,end:p=e.end,step:f=e.step,format:g=e.format,prefix:b=e.prefix,suffix:y=e.suffix}=e,v=`form-select ${d}`.trim(),_=this.errors[t],E=this.getFieldValue(t)??r,j=Object.entries(h).map(([I,H])=>`${I}="${this.escapeHtml(H)}"`).join(" "),M=this.getFieldId(t);let R=[...i];if(m!==void 0&&p!==void 0){const I=f!==void 0?f:1,H=this.generateSelectOptions(m,p,I,{format:g,prefix:b,suffix:y});R=[...R,...H]}let ne="";Array.isArray(R)&&(ne=R.map(I=>{if(typeof I=="string"){const H=I===E?"selected":"";return`<option value="${this.escapeHtml(I)}" ${H}>${this.escapeHtml(I)}</option>`}else if(I&&typeof I=="object"){const H=I.value==E?"selected":"";return`<option value="${this.escapeHtml(I.value)}" ${H}>${this.escapeHtml(I.label||I.text||I.value)}</option>`}return""}).join(""));const be=l?`
663
+ `}buildFieldHTML(e){const{type:t,columns:s,class:i=""}=e;let r="";const n=Q&&typeof Q.getRenderer=="function"?Q.getRenderer(t):null;if(typeof n=="function")try{const d=n(this,e);d!=null&&(r=String(d))}catch(d){console.error("FormPlugins custom renderer error:",d)}if(!r)switch(t){case"text":r=this.renderTextField(e);break;case"email":r=this.renderEmailField(e);break;case"password":r=this.renderPasswordField(e);break;case"number":r=this.renderNumberField(e);break;case"tel":r=this.renderTelField(e);break;case"url":r=this.renderUrlField(e);break;case"search":r=this.renderSearchField(e);break;case"hex":r=this.renderHexField(e);break;case"textarea":r=this.renderTextareaField(e);break;case"htmlpreview":r=this.renderHtmlPreviewField(e);break;case"json":r=this.renderJsonField(e);break;case"select":r=this.renderSelectField(e);break;case"multiselect":r=this.renderMultiSelectField(e);break;case"checkbox":r=this.renderCheckboxField(e);break;case"toggle":case"switch":r=this.renderSwitchField(e);break;case"radio":r=this.renderRadioField(e);break;case"date":r=this.renderDateField(e);break;case"datetime":r=this.renderDateTimeField(e);break;case"time":r=this.renderTimeField(e);break;case"file":r=this.renderFileField(e);break;case"image":r=this.renderImageField(e);break;case"color":r=this.renderColorField(e);break;case"range":r=this.renderRangeField(e);break;case"hidden":r=this.renderHiddenField(e);break;case"button":r=this.renderButton(e);break;case"divider":r=this.renderDivider(e);break;case"html":r=this.renderHtmlField(e);break;case"heading":case"header":r=this.renderHeaderField(e);break;case"tag":case"tags":r=this.renderTagField(e);break;case"collection":r=this.renderCollectionField(e);break;case"collectionmultiselect":case"collection-multiselect":r=this.renderCollectionMultiSelectField(e);break;case"datepicker":r=this.renderDatePickerField(e);break;case"monthpicker":r=this.renderDatePickerField({...e,precision:"month"});break;case"yearpicker":r=this.renderDatePickerField({...e,precision:"year"});break;case"daterange":r=this.renderDateRangeField(e);break;case"monthrange":r=this.renderDateRangeField({...e,precision:"month"});break;case"yearrange":r=this.renderDateRangeField({...e,precision:"year"});break;case"timepicker":r=this.renderTimePickerField(e);break;case"datetimepicker":r=this.renderDateTimePickerField(e);break;case"checklistdropdown":r=this.renderChecklistDropdownField(e);break;case"buttongroup":r=this.renderButtonGroupField(e);break;case"combo":case"combobox":case"autocomplete":r=this.renderComboField(e);break;case"tabset":r=this.renderTabsetField(e);break;default:console.warn(`Unknown field type: ${t}`),r=this.renderTextField(e)}let a;if(this.isAutoSizingField(e))a=`col ${i}`.trim();else if(typeof s=="object"&&s!==null){const d=[];s.xs&&d.push(`col-${s.xs}`),s.sm&&d.push(`col-sm-${s.sm}`),s.md&&d.push(`col-md-${s.md}`),s.lg&&d.push(`col-lg-${s.lg}`),s.xl&&d.push(`col-xl-${s.xl}`),s.xxl&&d.push(`col-xxl-${s.xxl}`),d.length===0&&d.push("col-12"),i&&d.push(i),a=d.join(" ")}else a=`col-${s} ${i}`.trim();let o="",l="";if(e.showWhen){const d=e.showWhen,h=Array.isArray(d.value)?d.value:[d.value];o=` data-show-when-field="${d.field}" data-show-when-value="${h.join(",")}"`,d.negate&&(o+=' data-show-when-negate="true"');let u=this.data[d.field];if(u==null){const g=this._findField(d.field,this.fields);g&&(u=g.value)}const m=String(u??""),p=h.map(String).includes(m);(d.negate?!p:p)||(l=' style="display:none"')}return`<div class="${a}"${o}${l}>${r}</div>`}_findField(e,t){for(const s of t){if(s.name===e)return s;if(s.fields){const i=this._findField(e,s.fields);if(i)return i}if(s.tabs){for(const i of s.tabs)if(i.fields){const r=this._findField(e,i.fields);if(r)return r}}}return null}getFieldId(e){return e?`field_${e.replace(/[.\s\[\]]/g,"_")}`:`field_${Math.random().toString(36).substr(2,9)}`}renderTextField(e){return this.renderInputField(e,"text")}renderEmailField(e){return this.renderInputField(e,"email")}renderPasswordField(e){const t=e.passwordUsage||"current",s=t==="new"||t==="new-password"?"new-password":"current-password",i={...e.attributes||{},autocomplete:e.attributes&&e.attributes.autocomplete||s};return this.renderInputField({...e,showToggle:e.showToggle!==!1,attributes:i},"password")}renderNumberField(e){const{min:t,max:s,step:i=1,...r}=e,n=[];return t!==void 0&&n.push(`min="${t}"`),s!==void 0&&n.push(`max="${s}"`),i!==void 0&&n.push(`step="${i}"`),this.renderInputField({...r,attributes:{...r.attributes,...n.reduce((a,o)=>{const[l,d]=o.split("=");return a[l]=d.replace(/"/g,""),a},{})}},"number")}renderTelField(e){return this.renderInputField(e,"tel")}renderUrlField(e){return this.renderInputField(e,"url")}renderSearchField(e){const t={...e,attributes:{"data-filter":"live-search","data-change-action":"filter-search","data-filter-debounce":e.debounce||"300",...e.attributes}};return this.renderInputField(t,"search")}renderHexField(e){const{hexType:t="color",allowPrefix:s=!0,minLength:i,maxLength:r,...n}=e;let a,o,l,d,h;switch(t){case"color":a=s?"^#?[0-9A-Fa-f]{6}$":"^[0-9A-Fa-f]{6}$",o=6,l=s?7:6,d=s?"#FF0000":"FF0000",h=h||"Enter a valid hex color (e.g., "+d+")";break;case"color-short":a=s?"^#?[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$":"^[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$",o=s?4:3,l=s?7:6,d=s?"#F00 or #FF0000":"F00 or FF0000",h=h||"Enter a valid hex color (3 or 6 digits)";break;case"string":a="^[0-9A-Fa-f]+$",o=i||1,l=r||64,d="ABCDEF123456",h=h||"Only hexadecimal characters (0-9, A-F) allowed";break;default:a=s?"^#?[0-9A-Fa-f]+$":"^[0-9A-Fa-f]+$",o=i||1,l=r||64,d=s?"#ABCDEF or ABCDEF":"ABCDEF",h=h||"Enter hexadecimal characters only"}const u={...n,pattern:a,minLength:o,maxLength:l,placeholder:n.placeholder||d,help:n.help||h,attributes:{"data-hex-type":t,"data-allow-prefix":s,style:"text-transform: uppercase;",...n.attributes}};return this.renderInputField(u,"text")}renderInputField(e,t="text"){const{name:s,label:i,value:r="",placeholder:n="",required:a=!1,disabled:o=!1,readonly:l=!1,class:d="",attributes:h={},help:u=e.helpText||e.help||""}=e,m=`${this.options.inputClass} ${d}`.trim(),p=this.errors[s],f=this.getFieldValue(s)??r,g=Object.entries(h).map(([v,_])=>`${v}="${this.escapeHtml(_)}"`).join(" "),b=this.getFieldId(s),y={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:b,name:s,type:t,fieldValue:this.escapeHtml(f),label:i?this.escapeHtml(i):null,placeholder:n?this.escapeHtml(n):null,help:u?this.escapeHtml(u):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:p?this.escapeHtml(p):null,required:a,disabled:o,readonly:l,attrs:g,showCopy:!!e.showCopy};if(t==="password"&&(e.showToggle||e.strengthMeter||e.capsLockWarning)){const v={...y,showToggle:!!e.showToggle,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,v)}if(t==="password"){const v={...y,showToggle:e.showToggle!==!1,strengthMeter:!!e.strengthMeter,capsLockWarning:!!e.capsLockWarning};return D.render(this.templates.password,v)}return D.render(this.templates.input,y)}renderTextareaField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,rows:l=3,cols:d,class:h="",attributes:u={},help:m=e.helpText||e.help||""}=e,p=`${this.options.inputClass} ${h}`.trim(),f=this.errors[t],g=this.getFieldValue(t)??i,b=Object.entries(u).map(([_,A])=>`${_}="${this.escapeHtml(A)}"`).join(" "),y=this.getFieldId(t),v={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:y,name:t,fieldValue:g,label:s?this.escapeHtml(s):null,placeholder:r?this.escapeHtml(r):null,help:m?this.escapeHtml(m):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:f?this.escapeHtml(f):null,rows:l||3,required:n,disabled:a,readonly:o,showCopy:!!e.showCopy,attrs:b};return D.render(this.templates.textarea,v)}renderHtmlPreviewField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,rows:l=5,class:d="",attributes:h={},help:u=e.helpText||e.help||""}=e,m=`${this.options.inputClass} ${d}`.trim(),p=this.errors[t],f=this.getFieldValue(t)??i,g=Object.entries(h).map(([v,_])=>`${v}="${this.escapeHtml(_)}"`).join(" "),b=this.getFieldId(t),y={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:b,name:t,fieldValue:f,label:s?this.escapeHtml(s):null,placeholder:r?this.escapeHtml(r):null,help:u?this.escapeHtml(u):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:p?this.escapeHtml(p):null,rows:l||5,required:n,disabled:a,readonly:o,attrs:g,showCopy:!!e.showCopy};return D.render(this.templates.htmlpreview,y)}renderJsonField(e){const{name:t,label:s,placeholder:i="",required:r=!1,disabled:n=!1,readonly:a=!1,rows:o=3,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=this.getFieldValue(e.name)??e.value??{};let m=u;if(typeof u=="object"&&u!==null)try{m=JSON.stringify(u,null,2)}catch{m="{}"}else typeof u!="string"&&(m=String(u));const p=`${this.options.inputClass} ${l}`.trim(),f=this.errors[t],g=this.getFieldId(t),b=Object.entries({...d,"data-field-type":"json"}).map(([v,_])=>`${v}="${this.escapeHtml(_)}"`).join(" "),y={labelClass:this.options.labelClass,inputClass:p,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,fieldValue:m,label:s?this.escapeHtml(s):null,placeholder:i?this.escapeHtml(i):null,help:h?this.escapeHtml(h):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:f?this.escapeHtml(f):null,rows:o||3,required:r,disabled:n,readonly:a,attrs:b};return D.render(this.templates.textarea,y)}renderSelectField(e){const{name:t,label:s,options:i=[],value:r="",required:n=!1,disabled:a=!1,multiple:o=!1,searchable:l=!1,class:d="",attributes:h={},help:u=e.helpText||e.help||"",start:m=e.start,end:p=e.end,step:f=e.step,format:g=e.format,prefix:b=e.prefix,suffix:y=e.suffix}=e,v=`form-select ${d}`.trim(),_=this.errors[t],E=this.getFieldValue(t)??r,j=Object.entries(h).map(([M,H])=>`${M}="${this.escapeHtml(H)}"`).join(" "),I=this.getFieldId(t);let R=[...i];if(m!==void 0&&p!==void 0){const M=f!==void 0?f:1,H=this.generateSelectOptions(m,p,M,{format:g,prefix:b,suffix:y});R=[...R,...H]}let ae="";Array.isArray(R)&&(ae=R.map(M=>{if(typeof M=="string"){const H=M===E?"selected":"";return`<option value="${this.escapeHtml(M)}" ${H}>${this.escapeHtml(M)}</option>`}else if(M&&typeof M=="object"){const H=M.value==E?"selected":"";return`<option value="${this.escapeHtml(M.value)}" ${H}>${this.escapeHtml(M.label||M.text||M.value)}</option>`}return""}).join(""));const be=l?`
664
664
  <input type="text"
665
665
  class="form-control form-control-sm mb-2"
666
666
  placeholder="Search options..."
667
667
  data-filter="live-search"
668
668
  data-change-action="filter-select-options"
669
- data-target="${M}">
670
- `:"",ye={labelClass:this.options.labelClass,inputClass:v,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:M,name:t,label:s?this.escapeHtml(s):null,help:u?this.escapeHtml(u):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:_?this.escapeHtml(_):null,searchInput:l?be:null,optionsHTML:ne,required:n,disabled:a,multiple:o,attrs:j};return D.render(this.templates.select,ye)}renderMultiSelectField(e){const{name:t,label:s,options:i=[],value:r=[],required:n=!1,disabled:a=!1,maxHeight:o=300,help:l=e.helpText||e.help||""}=e,d=e.placeholder||e.placeHolder||"Select...";this.getFieldId(t);const h=this.errors[t],u=e.value??this.getFieldValue(t)??r;return`
669
+ data-target="${I}">
670
+ `:"",ye={labelClass:this.options.labelClass,inputClass:v,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:I,name:t,label:s?this.escapeHtml(s):null,help:u?this.escapeHtml(u):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:_?this.escapeHtml(_):null,searchInput:l?be:null,optionsHTML:ae,required:n,disabled:a,multiple:o,attrs:j};return D.render(this.templates.select,ye)}renderMultiSelectField(e){const{name:t,label:s,options:i=[],value:r=[],required:n=!1,disabled:a=!1,maxHeight:o=300,help:l=e.helpText||e.help||""}=e,d=e.placeholder||e.placeHolder||"Select...";this.getFieldId(t);const h=this.errors[t],u=e.value??this.getFieldValue(t)??r;return`
671
671
  <div class="multiselect-placeholder"
672
672
  data-field-name="${t}"
673
673
  data-field-type="multiselect"
@@ -709,7 +709,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
709
709
  ${d?`<div class="${this.options.helpClass}">${this.escapeHtml(d)}</div>`:""}
710
710
  ${h?`<div class="${this.options.errorClass}">${this.escapeHtml(h)}</div>`:""}
711
711
  </div>
712
- `}renderDateField(e){return this.renderInputField(e,"date")}renderDateTimeField(e){return this.renderInputField(e,"datetime-local")}renderTimeField(e){return this.renderInputField(e,"time")}renderFileField(e){const{name:t,label:s,required:i=!1,disabled:r=!1,multiple:n=!1,accept:a="*/*",class:o="",attributes:l={},help:d=e.helpText||e.help||""}=e,h=`${this.options.inputClass} ${o}`.trim(),u=this.errors[t],m=Object.entries(l).map(([g,b])=>`${g}="${this.escapeHtml(b)}"`).join(" "),p=this.getFieldId(t),f={labelClass:this.options.labelClass,inputClass:h,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:p,name:t,label:s?this.escapeHtml(s):null,help:d?this.escapeHtml(d):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:u?this.escapeHtml(u):null,accept:a,required:i,disabled:r,multiple:n,attrs:m};return D.render(this.templates.file,f)}renderImageField(e){const{name:t,label:s,required:i=!1,disabled:r=!1,accept:n="image/*",class:a="",attributes:o={},help:l=e.helpText||e.help||"",size:d="md",allowDrop:h=!0,placeholder:u="Drop image here or click to upload"}=e,m=`${this.options.inputClass} ${a}`.trim(),p=this.errors[t],f=this.getFieldId(t),g=`${f}_dropzone`,b=`${f}_preview`,y={xs:{width:48,height:48,containerClass:"image-field-xs"},sm:{width:96,height:96,containerClass:"image-field-sm"},md:{width:150,height:150,containerClass:"image-field-md"},lg:{width:200,height:200,containerClass:"image-field-lg"},xl:{width:300,height:300,containerClass:"image-field-xl"}},v=y[d]||y.md,_=Object.entries(o).map(([M,R])=>`${M}="${this.escapeHtml(R)}"`).join(" "),A=this.getFieldValue(t),E=this.extractImageUrl(A,d),j={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:f,name:t,label:s?this.escapeHtml(s):null,help:l?this.escapeHtml(l):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:p?this.escapeHtml(p):null,dropZoneId:g,previewId:b,containerClass:v.containerClass,width:v.width,height:v.height,accept:n,imageUrl:E,placeholderText:r?"No image":this.escapeHtml(u),cursor:r?"default":"pointer",allowDrop:h,showRemove:!r,required:i,disabled:r,attrs:_};return D.render(this.templates.image,j)}extractImageUrl(e,t="md"){if(!e)return null;if(typeof e=="string")return e;if(typeof e=="object"&&e.url){if(e.renditions){const s={xs:["thumbnail_sm","thumbnail","square_sm"],sm:["thumbnail","thumbnail_sm","square_sm"],md:["thumbnail_md","thumbnail","thumbnail_lg"],lg:["thumbnail_lg","thumbnail_md","thumbnail"],xl:["original","thumbnail_lg"]},i=s[t]||s.md;for(const r of i)if(e.renditions[r]&&e.renditions[r].url)return e.renditions[r].url}return e.url}return null}renderColorField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=`${this.options.inputClass} ${l}`.trim(),m=this.errors[t],p=this.getFieldValue(t)??i,f=Object.entries(d).map(([y,v])=>`${y}="${this.escapeHtml(v)}"`).join(" "),g=this.getFieldId(t),b={labelClass:this.options.labelClass,inputClass:u,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,fieldValue:this.escapeHtml(p),label:s?this.escapeHtml(s):null,placeholder:r?this.escapeHtml(r):null,help:h?this.escapeHtml(h):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:m?this.escapeHtml(m):null,required:n,disabled:a,readonly:o,attrs:f};return D.render(this.templates.color,b)}renderRangeField(e){const{name:t,label:s,min:i=0,max:r=100,step:n=1,value:a=i,disabled:o=!1,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=`${this.options.inputClass} ${l}`.trim(),m=this.errors[t],p=this.getFieldValue(t)??a,f=Object.entries(d).map(([y,v])=>`${y}="${this.escapeHtml(v)}"`).join(" "),g=this.getFieldId(t),b={labelClass:this.options.labelClass,inputClass:u,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,label:s?this.escapeHtml(s):null,help:h?this.escapeHtml(h):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:m?this.escapeHtml(m):null,min:i,max:r,step:n,fieldValue:p,disabled:o,attrs:f};return D.render(this.templates.range,b)}renderHiddenField(e){const{name:t,value:s=""}=e,i=this.getFieldValue(t)??s;return`<input type="hidden" name="${t}" value="${this.escapeHtml(i)}">`}renderButton(e){const{name:t="",label:s="Button",type:i="button",action:r="",class:n="btn-secondary",disabled:a=!1,attributes:o={}}=e;let l=r;l||(i==="submit"?l="submit-form":i==="reset"&&(l="reset-form"));const d=Object.entries(o).map(([h,u])=>`${h}="${this.escapeHtml(u)}"`).join(" ");return`
712
+ `}renderDateField(e){return this.renderInputField(e,"date")}renderDateTimeField(e){return this.renderInputField(e,"datetime-local")}renderTimeField(e){return this.renderInputField(e,"time")}renderFileField(e){const{name:t,label:s,required:i=!1,disabled:r=!1,multiple:n=!1,accept:a="*/*",class:o="",attributes:l={},help:d=e.helpText||e.help||""}=e,h=`${this.options.inputClass} ${o}`.trim(),u=this.errors[t],m=Object.entries(l).map(([g,b])=>`${g}="${this.escapeHtml(b)}"`).join(" "),p=this.getFieldId(t),f={labelClass:this.options.labelClass,inputClass:h,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:p,name:t,label:s?this.escapeHtml(s):null,help:d?this.escapeHtml(d):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:u?this.escapeHtml(u):null,accept:a,required:i,disabled:r,multiple:n,attrs:m};return D.render(this.templates.file,f)}renderImageField(e){const{name:t,label:s,required:i=!1,disabled:r=!1,accept:n="image/*",class:a="",attributes:o={},help:l=e.helpText||e.help||"",size:d="md",allowDrop:h=!0,placeholder:u="Drop image here or click to upload"}=e,m=`${this.options.inputClass} ${a}`.trim(),p=this.errors[t],f=this.getFieldId(t),g=`${f}_dropzone`,b=`${f}_preview`,y={xs:{width:48,height:48,containerClass:"image-field-xs"},sm:{width:96,height:96,containerClass:"image-field-sm"},md:{width:150,height:150,containerClass:"image-field-md"},lg:{width:200,height:200,containerClass:"image-field-lg"},xl:{width:300,height:300,containerClass:"image-field-xl"}},v=y[d]||y.md,_=Object.entries(o).map(([I,R])=>`${I}="${this.escapeHtml(R)}"`).join(" "),A=this.getFieldValue(t),E=this.extractImageUrl(A,d),j={labelClass:this.options.labelClass,inputClass:m,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:f,name:t,label:s?this.escapeHtml(s):null,help:l?this.escapeHtml(l):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:p?this.escapeHtml(p):null,dropZoneId:g,previewId:b,containerClass:v.containerClass,width:v.width,height:v.height,accept:n,imageUrl:E,placeholderText:r?"No image":this.escapeHtml(u),cursor:r?"default":"pointer",allowDrop:h,showRemove:!r,required:i,disabled:r,attrs:_};return D.render(this.templates.image,j)}extractImageUrl(e,t="md"){if(!e)return null;if(typeof e=="string")return e;if(typeof e=="object"&&e.url){if(e.renditions){const s={xs:["thumbnail_sm","thumbnail","square_sm"],sm:["thumbnail","thumbnail_sm","square_sm"],md:["thumbnail_md","thumbnail","thumbnail_lg"],lg:["thumbnail_lg","thumbnail_md","thumbnail"],xl:["original","thumbnail_lg"]},i=s[t]||s.md;for(const r of i)if(e.renditions[r]&&e.renditions[r].url)return e.renditions[r].url}return e.url}return null}renderColorField(e){const{name:t,label:s,value:i="",placeholder:r="",required:n=!1,disabled:a=!1,readonly:o=!1,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=`${this.options.inputClass} ${l}`.trim(),m=this.errors[t],p=this.getFieldValue(t)??i,f=Object.entries(d).map(([y,v])=>`${y}="${this.escapeHtml(v)}"`).join(" "),g=this.getFieldId(t),b={labelClass:this.options.labelClass,inputClass:u,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,fieldValue:this.escapeHtml(p),label:s?this.escapeHtml(s):null,placeholder:r?this.escapeHtml(r):null,help:h?this.escapeHtml(h):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:m?this.escapeHtml(m):null,required:n,disabled:a,readonly:o,attrs:f};return D.render(this.templates.color,b)}renderRangeField(e){const{name:t,label:s,min:i=0,max:r=100,step:n=1,value:a=i,disabled:o=!1,class:l="",attributes:d={},help:h=e.helpText||e.help||""}=e,u=`${this.options.inputClass} ${l}`.trim(),m=this.errors[t],p=this.getFieldValue(t)??a,f=Object.entries(d).map(([y,v])=>`${y}="${this.escapeHtml(v)}"`).join(" "),g=this.getFieldId(t),b={labelClass:this.options.labelClass,inputClass:u,helpClass:this.options.helpClass,errorClass:this.options.errorClass,fieldId:g,name:t,label:s?this.escapeHtml(s):null,help:h?this.escapeHtml(h):null,tooltip:e.tooltip?this.escapeHtml(e.tooltip):null,error:m?this.escapeHtml(m):null,min:i,max:r,step:n,fieldValue:p,disabled:o,attrs:f};return D.render(this.templates.range,b)}renderHiddenField(e){const{name:t,value:s=""}=e,i=this.getFieldValue(t)??s;return`<input type="hidden" name="${t}" value="${this.escapeHtml(i)}">`}renderButton(e){const{name:t="",label:s="Button",type:i="button",action:r="",class:n="btn-secondary",disabled:a=!1,attributes:o={}}=e;let l=r;l||(i==="submit"?l="submit-form":i==="reset"&&(l="reset-form"));const d=Object.entries(o).map(([h,u])=>`${h}="${this.escapeHtml(u)}"`).join(" ");return`
713
713
  <button
714
714
  type="button"
715
715
  ${t?`name="${t}"`:""}
@@ -798,15 +798,15 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
798
798
  ${v?`<div class="${this.options.helpClass}">${this.escapeHtml(v)}</div>`:""}
799
799
  ${A?`<div class="${this.options.errorClass}">${this.escapeHtml(A)}</div>`:""}
800
800
  </div>
801
- `}renderDateRangeField(e){const{name:t,startName:s,endName:i,fieldName:r,label:n,startDate:a="",endDate:o="",precision:l="day",placeholder:d,required:h=!1,disabled:u=!1,readonly:m=!1,min:p=null,max:f=null,format:g=null,displayFormat:b=null,outputFormat:y="date",separator:v=" – ",months:_=null,presets:A=null,autoApply:E=!0,inline:j=!1,help:M=e.helpText||e.help||""}=e,R=this.getFieldId(t||s||"daterange"),ne=this.errors[t],be=s||(t?t+"_start":""),ye=i||(t?t+"_end":""),I=this.getFieldValue(be)||a,H=this.getFieldValue(ye)||o;return`
801
+ `}renderDateRangeField(e){const{name:t,startName:s,endName:i,fieldName:r,label:n,startDate:a="",endDate:o="",precision:l="day",placeholder:d,required:h=!1,disabled:u=!1,readonly:m=!1,min:p=null,max:f=null,format:g=null,displayFormat:b=null,outputFormat:y="date",separator:v=" – ",months:_=null,presets:A=null,autoApply:E=!0,inline:j=!1,help:I=e.helpText||e.help||""}=e,R=this.getFieldId(t||s||"daterange"),ae=this.errors[t],be=s||(t?t+"_start":""),ye=i||(t?t+"_end":""),M=this.getFieldValue(be)||a,H=this.getFieldValue(ye)||o;return`
802
802
  <div class="mojo-form-control">
803
803
  ${n?`<label for="${R}" class="${this.options.labelClass}">${this.escapeHtml(n)}${h?'<span class="text-danger">*</span>':""}${this.renderTooltipIcon(e)}</label>`:""}
804
804
  <div class="date-range-picker-placeholder"
805
805
  data-field-name="${t||s||"daterange"}"
806
806
  data-field-type="daterange"
807
- data-field-config='${JSON.stringify({name:t,startName:s,endName:i,fieldName:r,startDate:I,endDate:H,precision:l,placeholder:d,min:p,max:f,format:g,displayFormat:b,outputFormat:y,separator:v,months:_,presets:A,autoApply:E,inline:j,disabled:u,readonly:m,required:h})}'></div>
808
- ${M?`<div class="${this.options.helpClass}">${this.escapeHtml(M)}</div>`:""}
809
- ${ne?`<div class="${this.options.errorClass}">${this.escapeHtml(ne)}</div>`:""}
807
+ data-field-config='${JSON.stringify({name:t,startName:s,endName:i,fieldName:r,startDate:M,endDate:H,precision:l,placeholder:d,min:p,max:f,format:g,displayFormat:b,outputFormat:y,separator:v,months:_,presets:A,autoApply:E,inline:j,disabled:u,readonly:m,required:h})}'></div>
808
+ ${I?`<div class="${this.options.helpClass}">${this.escapeHtml(I)}</div>`:""}
809
+ ${ae?`<div class="${this.options.errorClass}">${this.escapeHtml(ae)}</div>`:""}
810
810
  </div>
811
811
  `}renderTimePickerField(e){const{name:t,label:s,value:i="",format:r="24h",step:n=1,min:a=null,max:o=null,placeholder:l,required:d=!1,disabled:h=!1,readonly:u=!1,timezone:m=!1,timezones:p=null,outputFormat:f="string",autoApply:g=!1,inline:b=!1,help:y=e.helpText||e.help||""}=e,v=this.getFieldId(t),_=this.errors[t],A=this.getFieldValue(t)??i;return`
812
812
  <div class="mojo-form-control">
@@ -818,7 +818,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
818
818
  ${y?`<div class="${this.options.helpClass}">${this.escapeHtml(y)}</div>`:""}
819
819
  ${_?`<div class="${this.options.errorClass}">${this.escapeHtml(_)}</div>`:""}
820
820
  </div>
821
- `}renderDateTimePickerField(e){const{name:t,label:s,value:i="",displayFormat:r=null,timeFormat:n="24h",timeStep:a=1,min:o=null,max:l=null,placeholder:d,required:h=!1,disabled:u=!1,readonly:m=!1,disabledDates:p=[],firstDay:f=1,lang:g="en-US",timezone:b=!1,timezones:y=null,outputFormat:v="string",autoApply:_=!1,inline:A=!1,help:E=e.helpText||e.help||""}=e,j=this.getFieldId(t),M=this.errors[t],R=this.getFieldValue(t)??i;return`
821
+ `}renderDateTimePickerField(e){const{name:t,label:s,value:i="",displayFormat:r=null,timeFormat:n="24h",timeStep:a=1,min:o=null,max:l=null,placeholder:d,required:h=!1,disabled:u=!1,readonly:m=!1,disabledDates:p=[],firstDay:f=1,lang:g="en-US",timezone:b=!1,timezones:y=null,outputFormat:v="string",autoApply:_=!1,inline:A=!1,help:E=e.helpText||e.help||""}=e,j=this.getFieldId(t),I=this.errors[t],R=this.getFieldValue(t)??i;return`
822
822
  <div class="mojo-form-control">
823
823
  ${s?`<label for="${j}" class="${this.options.labelClass}">${this.escapeHtml(s)}${h?'<span class="text-danger">*</span>':""}${this.renderTooltipIcon(e)}</label>`:""}
824
824
  <div class="datetime-picker-placeholder"
@@ -826,7 +826,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
826
826
  data-field-type="datetimepicker"
827
827
  data-field-config='${JSON.stringify({name:t,value:R,displayFormat:r,timeFormat:n,timeStep:a,min:o,max:l,placeholder:d,disabledDates:p,firstDay:f,lang:g,timezone:b,timezones:y,outputFormat:v,autoApply:_,inline:A,disabled:u,readonly:m,required:h})}'></div>
828
828
  ${E?`<div class="${this.options.helpClass}">${this.escapeHtml(E)}</div>`:""}
829
- ${M?`<div class="${this.options.errorClass}">${this.escapeHtml(M)}</div>`:""}
829
+ ${I?`<div class="${this.options.errorClass}">${this.escapeHtml(I)}</div>`:""}
830
830
  </div>
831
831
  `}renderChecklistDropdownField(e){const t=this.getFieldId(e.name),s=this.getFieldValue(e.name)??[],i={fieldId:t,fieldName:e.name,buttonText:e.buttonText||"Select Options",buttonIcon:e.buttonIcon||"bi-chevron-down",buttonClass:e.buttonClass||"btn btn-outline-secondary btn-sm dropdown-toggle",dropdownClass:e.dropdownClass||"dropdown-menu p-2",minWidth:e.minWidth||"200px",options:e.options.map(r=>({value:r.value,label:r.label,id:`${e.name}-${r.value}`,checked:s.includes(r.value)}))};return D.render(this.templates.checklistdropdown,i)}renderButtonGroupField(e){const t=this.getFieldId(e.name),s=this.getFieldValue(e.name)??e.value,i={fieldId:t,fieldName:e.name,size:e.size||"sm",variant:e.variant||"outline-primary",options:e.options.map(r=>({value:r.value,label:r.label,action:r.action,active:r.value===s,buttonClass:this.getButtonClass(r.value===s,e.variant)}))};return D.render(this.templates.buttongroup,i)}getButtonClass(e,t="outline-primary"){return e?`btn btn-${t.replace("outline-","")}`:`btn btn-${t}`}renderComboField(e){const{name:t,label:s,value:i="",required:r=!1,disabled:n=!1,maxHeight:a=300,help:o=e.helpText||e.help||""}=e,l=e.placeholder||e.placeHolder||"Type or select...",d=e.allowCustom!==!1;this.getFieldId(t);const h=this.errors[t],u=e.value??this.getFieldValue(t)??i;return`
832
832
  <div class="mojo-form-control">
@@ -1115,7 +1115,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1115
1115
  <div class="invalid-feedback d-block">{{error}}</div>
1116
1116
  {{/error}}
1117
1117
  </div>
1118
- `,...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 is({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 Re=["January","February","March","April","May","June","July","August","September","October","November","December"],je=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function ut(c){if(c==null||c==="")return null;const e=parseInt(String(c).slice(0,4),10);return Number.isFinite(e)?{y:e}:null}function Ce(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 q(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 mt(c){const e=typeof c=="object"?c:ut(c);return e?String(e.y):""}function He(c){const e=typeof c=="object"?c:Ce(c);return e?`${e.y}-${X(e.m)}`:""}function B(c){const e=typeof c=="object"?c:q(c);return e?`${e.y}-${X(e.m)}-${X(e.d)}`:""}function U(c,e){return e==="year"?mt(c):e==="month"?He(c):B(c)}function V(c,e){return e==="year"?ut(c):e==="month"?Ce(c):q(c)}const ns=/YYYY|YY|MMMM|MMM|MM|M|DD|D/g;function de(c,e){if(!c)return"";const t=c.y,s=c.m,i=c.d;return String(e).replace(ns,r=>{switch(r){case"YYYY":return String(t);case"YY":return String(t).slice(-2);case"MMMM":return s?Re[s-1]:"";case"MMM":return s?je[s-1]:"";case"MM":return s?X(s):"";case"M":return s?String(s):"";case"DD":return i?X(i):"";case"D":return i?String(i):"";default:return r}})}function pt(c,e){return new Date(c,e,0).getDate()}function as(c,e,t,s=1){return((new Date(c,e-1,t).getDay()-s)%7+7)%7}function re(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=pt(t,s);return{y:t,m:s,d:Math.min(c.d,i)}}function ft(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 gt(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 os(c,e){return!c||!e||c.y===e.y?0:c.y<e.y?-1:1}function W(c,e,t){return t==="year"?os(c,e):t==="month"?gt(c,e):ft(c,e)}function G(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 J(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}:${X(s)} ${i}`}return`${X(t)}:${X(s)}`}function bt(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 ls(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 yt(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 wt(c){if(c==null||c==="")return null;if(typeof c=="object"&&!Array.isArray(c)&&!(c instanceof Date)){const h=c.date?q(c.date):null,u=c.time?G(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=q(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=q(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=G(o);return d?{date:r,time:d,timezone:a}:null}function F(){const c=new Date;return{y:c.getFullYear(),m:c.getMonth()+1,d:c.getDate()}}let Se=null,ze=null,qe=null;function vt(c="en-US",e="short"){if((!c||c==="en-US"||c==="en")&&e==="short")return je.slice();if((!c||c==="en-US"||c==="en")&&e==="long")return Re.slice();if(typeof Intl>"u"||!Intl.DateTimeFormat)return e==="long"?Re.slice():je.slice();if(Se===c+"/"+e&&ze)return ze.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 Se=c+"/"+e,ze=s,s.slice()}function cs(c="en-US",e=1,t="short"){if(typeof Intl>"u"||!Intl.DateTimeFormat)return Ct(["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],e);const s=c+"/"+e+"/"+t;if(Se===s&&qe)return qe.slice();const i=new Intl.DateTimeFormat(c,{weekday:t}),r=[];for(let a=0;a<7;a++)r.push(i.format(new Date(2024,0,7+a)));const n=Ct(r,e);return Se=s,qe=n,n.slice()}function X(c){return c<10?"0"+c:String(c)}function Ct(c,e){const t=(e%c.length+c.length)%c.length;return c.slice(t).concat(c.slice(0,t))}class Be 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?q(o):null),this.max=V(l,t)||(l?q(l):null),this.disabledDates=(d||[]).map(_=>B(q(_)||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=F(),v=(s==="single"?this.selected:this.start||this.end)||y;this.pageY=p!=null?Number(p):v.y??y.y,this.pageM=f!=null?Number(f):v.m??y.m,this._onCellMouseEnter=this._onCellMouseEnter.bind(this),this._onCellMouseLeave=this._onCellMouseLeave.bind(this)}setMin(e){this.min=V(e,this.precision),this._rerender()}setMax(e){this.max=V(e,this.precision),this._rerender()}setValue(e){this.selected=V(e,this.precision),this.selected&&(this.pageY=this.selected.y,this.pageM=this.selected.m||this.pageM),this._rerender()}setRange(e,t){this.start=V(e,this.precision),this.end=V(t,this.precision),this._anchor=null,this._rerender()}getValue(){return this.selected?U(this.selected,this.precision):""}getRange(){return{start:this.start?U(this.start,this.precision):"",end:this.end?U(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",cs(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=as(e,t,1,this.firstDay),r=pt(e,t),n=F();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=B(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&&ft(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=vt(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=He(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&&gt(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=W(this._anchor,o,s);i=l<=0?this._anchor:o,r=l<=0?o:this._anchor}if(!i||!r){this._anchor&&W(t,this._anchor,s)===0&&e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-solo");return}const n=W(t,i,s),a=W(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"),W(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&&W(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=vt(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=Ce(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=q(e.dataset.ymd);if(!t)return;this._commitValue(t)}}_commitValue(e){if(this.mode==="single"){this.selected=e,this.emit("select",{value:U(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:U(e,this.precision)}),this._rerender();return}const t=this._anchor,s=e,i=W(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:U(this.start,this.precision),end:U(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=q(t.dataset.ymd):this.view==="month"&&t.dataset.ym?s=Ce(t.dataset.ym):this.view==="year"&&t.dataset.year&&(s={y:parseInt(t.dataset.year,10)}),s&&(this._hover&&W(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=re({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&&W(e,this.min,t)<0||this.max&&W(e,this.max,t)>0)return!0;if(t==="day"&&this.disabledDates.length){const s=B(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 _e{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 St={day:"MMM DD, YYYY",month:"MMM YYYY",year:"YYYY"};class Ue extends C{constructor(e={}){const{name:t,value:s="",precision:i="day",format:r=null,displayFormat:n=null,min:a=null,max:o=null,placeholder:l=null,disabled:d=!1,readonly:h=!1,required:u=!1,class:m="",inputClass:p="form-control",inline:f=!1,disabledDates:g=[],firstDay:b=1,lang:y="en-US",autoApply:v=!0,..._}=e;super({tagName:"div",className:`mojo-date-picker mojo-date-picker-${i} ${m}`.trim(),..._}),this.name=t,this.precision=i,this.format=r,this.displayFormat=n||St[i]||St.day,this.min=a,this.max=o,this.placeholder=l??this._defaultPlaceholder(i),this.disabled=d,this.readonly=h,this.required=u,this.inputClass=p,this.inline=f,this.disabledDates=g,this.firstDay=b,this.lang=y,this.autoApply=v,this.currentValue=s||"",this._calendar=null,this._popover=null}_defaultPlaceholder(e){return e==="year"?"Select year...":e==="month"?"Select month...":"Select date..."}async renderTemplate(){const e=this._inputId(),t=this._displayText(this.currentValue),s=!this.currentValue;return this.inline?`
1118
+ `,...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 is({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 Re=["January","February","March","April","May","June","July","August","September","October","November","December"],je=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function ut(c){if(c==null||c==="")return null;const e=parseInt(String(c).slice(0,4),10);return Number.isFinite(e)?{y:e}:null}function Ce(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 q(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 mt(c){const e=typeof c=="object"?c:ut(c);return e?String(e.y):""}function He(c){const e=typeof c=="object"?c:Ce(c);return e?`${e.y}-${X(e.m)}`:""}function B(c){const e=typeof c=="object"?c:q(c);return e?`${e.y}-${X(e.m)}-${X(e.d)}`:""}function U(c,e){return e==="year"?mt(c):e==="month"?He(c):B(c)}function V(c,e){return e==="year"?ut(c):e==="month"?Ce(c):q(c)}const ns=/YYYY|YY|MMMM|MMM|MM|M|DD|D/g;function he(c,e){if(!c)return"";const t=c.y,s=c.m,i=c.d;return String(e).replace(ns,r=>{switch(r){case"YYYY":return String(t);case"YY":return String(t).slice(-2);case"MMMM":return s?Re[s-1]:"";case"MMM":return s?je[s-1]:"";case"MM":return s?X(s):"";case"M":return s?String(s):"";case"DD":return i?X(i):"";case"D":return i?String(i):"";default:return r}})}function pt(c,e){return new Date(c,e,0).getDate()}function as(c,e,t,s=1){return((new Date(c,e-1,t).getDay()-s)%7+7)%7}function ne(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=pt(t,s);return{y:t,m:s,d:Math.min(c.d,i)}}function ft(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 gt(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 os(c,e){return!c||!e||c.y===e.y?0:c.y<e.y?-1:1}function W(c,e,t){return t==="year"?os(c,e):t==="month"?gt(c,e):ft(c,e)}function G(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 J(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}:${X(s)} ${i}`}return`${X(t)}:${X(s)}`}function bt(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 ls(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 yt(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 wt(c){if(c==null||c==="")return null;if(typeof c=="object"&&!Array.isArray(c)&&!(c instanceof Date)){const h=c.date?q(c.date):null,u=c.time?G(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=q(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=q(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=G(o);return d?{date:r,time:d,timezone:a}:null}function F(){const c=new Date;return{y:c.getFullYear(),m:c.getMonth()+1,d:c.getDate()}}let Se=null,ze=null,qe=null;function vt(c="en-US",e="short"){if((!c||c==="en-US"||c==="en")&&e==="short")return je.slice();if((!c||c==="en-US"||c==="en")&&e==="long")return Re.slice();if(typeof Intl>"u"||!Intl.DateTimeFormat)return e==="long"?Re.slice():je.slice();if(Se===c+"/"+e&&ze)return ze.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 Se=c+"/"+e,ze=s,s.slice()}function cs(c="en-US",e=1,t="short"){if(typeof Intl>"u"||!Intl.DateTimeFormat)return Ct(["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],e);const s=c+"/"+e+"/"+t;if(Se===s&&qe)return qe.slice();const i=new Intl.DateTimeFormat(c,{weekday:t}),r=[];for(let a=0;a<7;a++)r.push(i.format(new Date(2024,0,7+a)));const n=Ct(r,e);return Se=s,qe=n,n.slice()}function X(c){return c<10?"0"+c:String(c)}function Ct(c,e){const t=(e%c.length+c.length)%c.length;return c.slice(t).concat(c.slice(0,t))}class Be 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?q(o):null),this.max=V(l,t)||(l?q(l):null),this.disabledDates=(d||[]).map(_=>B(q(_)||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=F(),v=(s==="single"?this.selected:this.start||this.end)||y;this.pageY=p!=null?Number(p):v.y??y.y,this.pageM=f!=null?Number(f):v.m??y.m,this._onCellMouseEnter=this._onCellMouseEnter.bind(this),this._onCellMouseLeave=this._onCellMouseLeave.bind(this)}setMin(e){this.min=V(e,this.precision),this._rerender()}setMax(e){this.max=V(e,this.precision),this._rerender()}setValue(e){this.selected=V(e,this.precision),this.selected&&(this.pageY=this.selected.y,this.pageM=this.selected.m||this.pageM),this._rerender()}setRange(e,t){this.start=V(e,this.precision),this.end=V(t,this.precision),this._anchor=null,this._rerender()}getValue(){return this.selected?U(this.selected,this.precision):""}getRange(){return{start:this.start?U(this.start,this.precision):"",end:this.end?U(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",cs(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=as(e,t,1,this.firstDay),r=pt(e,t),n=F();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=B(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&&ft(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=vt(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=He(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&&gt(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=W(this._anchor,o,s);i=l<=0?this._anchor:o,r=l<=0?o:this._anchor}if(!i||!r){this._anchor&&W(t,this._anchor,s)===0&&e.classList.add("mojo-calendar-cell-anchor","mojo-calendar-cell-anchor-solo");return}const n=W(t,i,s),a=W(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"),W(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&&W(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=vt(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=Ce(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=q(e.dataset.ymd);if(!t)return;this._commitValue(t)}}_commitValue(e){if(this.mode==="single"){this.selected=e,this.emit("select",{value:U(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:U(e,this.precision)}),this._rerender();return}const t=this._anchor,s=e,i=W(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:U(this.start,this.precision),end:U(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=q(t.dataset.ymd):this.view==="month"&&t.dataset.ym?s=Ce(t.dataset.ym):this.view==="year"&&t.dataset.year&&(s={y:parseInt(t.dataset.year,10)}),s&&(this._hover&&W(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=ne({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&&W(e,this.min,t)<0||this.max&&W(e,this.max,t)>0)return!0;if(t==="day"&&this.disabledDates.length){const s=B(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 _e{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 St={day:"MMM DD, YYYY",month:"MMM YYYY",year:"YYYY"};class Ue extends C{constructor(e={}){const{name:t,value:s="",precision:i="day",format:r=null,displayFormat:n=null,min:a=null,max:o=null,placeholder:l=null,disabled:d=!1,readonly:h=!1,required:u=!1,class:m="",inputClass:p="form-control",inline:f=!1,disabledDates:g=[],firstDay:b=1,lang:y="en-US",autoApply:v=!0,..._}=e;super({tagName:"div",className:`mojo-date-picker mojo-date-picker-${i} ${m}`.trim(),..._}),this.name=t,this.precision=i,this.format=r,this.displayFormat=n||St[i]||St.day,this.min=a,this.max=o,this.placeholder=l??this._defaultPlaceholder(i),this.disabled=d,this.readonly=h,this.required=u,this.inputClass=p,this.inline=f,this.disabledDates=g,this.firstDay=b,this.lang=y,this.autoApply=v,this.currentValue=s||"",this._calendar=null,this._popover=null}_defaultPlaceholder(e){return e==="year"?"Select year...":e==="month"?"Select month...":"Select date..."}async renderTemplate(){const e=this._inputId(),t=this._displayText(this.currentValue),s=!this.currentValue;return this.inline?`
1119
1119
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(this.currentValue)}" data-hidden-value />
1120
1120
  <div data-cal-host class="mojo-date-picker-inline${this.hasError()?" is-invalid":""}"></div>
1121
1121
  `:`
@@ -1127,7 +1127,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1127
1127
  ${!this.required&&!this.disabled&&!this.readonly?'<button type="button" class="mojo-date-trigger-clear" data-clear aria-label="Clear" tabindex="-1">&#x2715;</button>':""}
1128
1128
  </button>
1129
1129
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(this.currentValue)}" data-hidden-value />
1130
- `}async onAfterRender(){this.inline?this._mountCalendarInline():this._wireTrigger()}_wireTrigger(){const e=this.element.querySelector("[data-trigger]"),t=this.element.querySelector("[data-clear]");e&&(e.addEventListener("click",s=>{s.target.closest("[data-clear]")||this._togglePopover(e)}),t&&t.addEventListener("click",s=>{s.stopPropagation(),this._setValue("")}))}_togglePopover(e){if(!(this.disabled||this.readonly)){if(this._popover?this._popover.setAnchor(e):this._popover=new _e({anchor:e}),this._popover.isOpen()){this._popover.close();return}this._calendar||(this._calendar=this._buildCalendar()),this._popover.setContent(this._calendar.element),this._popover.open(),this._calendar.render(!1)}}_mountCalendarInline(){const e=this.element.querySelector("[data-cal-host]");e&&(this._calendar||(this._calendar=this._buildCalendar()),e.appendChild(this._calendar.element),this._calendar.render(!1))}_buildCalendar(){const e=new Be({precision:this.precision,mode:"single",months:1,value:this.currentValue||null,min:this.min,max:this.max,disabledDates:this.disabledDates,firstDay:this.firstDay,locale:this.lang});return e.on("select",({value:t})=>{this._setValue(t),this.autoApply&&this._popover&&this._popover.isOpen()&&this._popover.close()}),e}_setValue(e){const t=this.currentValue;let s="";if(e){const a=V(e,this.precision);a&&(s=U(a,this.precision))}this.currentValue=s;const i=this._displayText(s),r=this.element.querySelector("[data-trigger-text]");r&&(r.textContent=i||this.placeholder,r.classList.toggle("is-empty",!s));const n=this.element.querySelector("[data-hidden-value]");n&&(n.value=s),this._calendar&&this._calendar.setValue(s),t!==s&&(this.emit("change",{value:s,formatted:i,oldValue:t}),this.emit("date:changed",{value:s,oldValue:t}))}_displayText(e){if(!e)return"";const t=V(e,this.precision);return t?de(t,this._stripIncompatibleTokens(this.displayFormat)):""}_stripIncompatibleTokens(e){return this.precision==="day"?e:this.precision==="month"?e.replace(/\bDD\b|\bD\b/g,"").replace(/[\s\-\/]+$/,"").trim():this.precision==="year"?e.replace(/MMMM|MMM|MM|M|DD|D/g,"").replace(/[\s\-\/]+$/,"").trim()||"YYYY":e}setValue(e){this._setValue(e)}getValue(){return this.currentValue}getFormattedValue(){return this._displayText(this.currentValue)}clear(){this._setValue("")}setMin(e){this.min=e,this._calendar&&this._calendar.setMin(e)}setMax(e){this.max=e,this._calendar&&this._calendar.setMax(e)}setEnabled(e){this.disabled=!e;const t=this.element.querySelector("[data-trigger]");t&&(t.disabled=!e),!e&&this._popover&&this._popover.isOpen()&&this._popover.close()}setReadonly(e){this.readonly=e,e&&this._popover&&this._popover.isOpen()&&this._popover.close()}focus(){const e=this.element.querySelector("[data-trigger]");e&&e.focus()}show(){const e=this.element.querySelector("[data-trigger]");e&&this._togglePopover(e)}hide(){this._popover&&this._popover.close()}getFormValue(){return this.getValue()}async setFormValue(e){this._setValue(e)}hasError(){return!1}_inputId(){return this.name?`mojo-date-${this.name}-${this.id}`:`mojo-date-${this.id}`}_attr(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}async onBeforeDestroy(){this._popover&&(this._popover.destroy(),this._popover=null),this._calendar=null,await super.onBeforeDestroy()}static create(e={}){return new Ue(e)}}function ds(){return[{label:"Today",range:()=>{const c=F();return{start:c,end:c}}},{label:"Yesterday",range:()=>{const c=F(),e=xe(c,-1);return{start:e,end:e}}},{label:"Last 7 days",range:()=>{const c=F();return{start:xe(c,-6),end:c}}},{label:"Last 30 days",range:()=>{const c=F();return{start:xe(c,-29),end:c}}},{label:"Last 90 days",range:()=>{const c=F();return{start:xe(c,-89),end:c}}},{divider:!0},{label:"This month",range:()=>{const c=F();return{start:{y:c.y,m:c.m,d:1},end:c}}},{label:"Last month",range:()=>{const c=F(),e=re({y:c.y,m:c.m,d:1},-1),t=re(e,1);t.d=0;const s=new Date(t.y,t.m,0).getDate();return{start:{...e,d:1},end:{...e,d:s}}}},{label:"This year",range:()=>{const c=F();return{start:{y:c.y,m:1,d:1},end:c}}}]}function hs(){return[{label:"This month",range:()=>{const c=F();return{start:{y:c.y,m:c.m},end:{y:c.y,m:c.m}}}},{label:"Last month",range:()=>{const c=F(),e=re({y:c.y,m:c.m},-1);return{start:e,end:e}}},{label:"Last 3 months",range:()=>{const c=F();return{start:re({y:c.y,m:c.m},-2),end:{y:c.y,m:c.m}}}},{label:"Last 6 months",range:()=>{const c=F();return{start:re({y:c.y,m:c.m},-5),end:{y:c.y,m:c.m}}}},{label:"YTD",range:()=>{const c=F();return{start:{y:c.y,m:1},end:{y:c.y,m:c.m}}}},{label:"Last 12 months",range:()=>{const c=F();return{start:re({y:c.y,m:c.m},-11),end:{y:c.y,m:c.m}}}}]}function us(){return[{label:"This year",range:()=>{const c=F();return{start:{y:c.y},end:{y:c.y}}}},{label:"Last year",range:()=>{const c=F();return{start:{y:c.y-1},end:{y:c.y-1}}}},{label:"Last 3 years",range:()=>{const c=F();return{start:{y:c.y-2},end:{y:c.y}}}},{label:"Last 5 years",range:()=>{const c=F();return{start:{y:c.y-4},end:{y:c.y}}}},{label:"Last 10 years",range:()=>{const c=F();return{start:{y:c.y-9},end:{y:c.y}}}}]}function xe(c,e){if(!c)return null;const t=new Date(c.y,c.m-1,c.d+e);return{y:t.getFullYear(),m:t.getMonth()+1,d:t.getDate()}}function _t(c){return c==="year"?us():c==="month"?hs():ds()}class ms extends C{constructor(e={}){const{precision:t="day",presets:s="default",eyebrow:i="Quick range",...r}=e;super({tagName:"div",className:"mojo-calendar-presets",...r}),this.precision=t,this.eyebrow=i,this.activeIndex=-1,this.presets=s===!0||s==="default"?_t(t):Array.isArray(s)?s:_t(t)}setActive(e){this.activeIndex=e,this._highlight()}async renderTemplate(){return""}async onAfterRender(){this._renderInto(this.element)}_renderInto(e){if(e.innerHTML="",this.eyebrow){const t=document.createElement("div");t.className="mojo-calendar-presets-eyebrow",t.textContent=this.eyebrow,e.appendChild(t)}this.presets.forEach((t,s)=>{if(t.divider){const r=document.createElement("div");r.className="mojo-calendar-presets-divider",e.appendChild(r);return}const i=document.createElement("button");i.type="button",i.className="mojo-calendar-preset"+(this.activeIndex===s?" is-active":""),i.dataset.presetIndex=String(s),i.textContent=t.label,e.appendChild(i)}),e.addEventListener("click",t=>{const s=t.target.closest(".mojo-calendar-preset");if(!s)return;const i=parseInt(s.dataset.presetIndex,10),r=this.presets[i];if(!r||typeof r.range!="function")return;const n=r.range();this.activeIndex=i,this._highlight();const a=this.precision==="year"?mt:this.precision==="month"?He:B;this.emit("preset:select",{index:i,label:r.label,start:a(n.start),end:a(n.end),parsed:n})})}_highlight(){this.element&&this.element.querySelectorAll(".mojo-calendar-preset").forEach(e=>{const t=parseInt(e.dataset.presetIndex,10);e.classList.toggle("is-active",t===this.activeIndex)})}}const xt={day:"MMM DD, YYYY",month:"MMM YYYY",year:"YYYY"};class We extends C{constructor(e={}){const{name:t,startName:s,endName:i,fieldName:r,startDate:n="",endDate:a="",precision:o="day",format:l=null,displayFormat:d=null,outputFormat:h="date",min:u=null,max:m=null,placeholder:p=null,disabled:f=!1,readonly:g=!1,required:b=!1,class:y="",inputClass:v="form-control",inline:_=!1,separator:A=" – ",autoApply:E=!0,months:j=null,presets:M=null,...R}=e;super({tagName:"div",className:`mojo-date-picker mojo-date-range-picker mojo-date-picker-${o} ${y}`.trim(),...R}),this.name=t,this.startName=s,this.endName=i,this.fieldName=r,this.precision=o,this.format=l,this.displayFormat=d||xt[o]||xt.day,this.outputFormat=h,this.min=u,this.max=m,this.placeholder=p??this._defaultPlaceholder(o),this.disabled=f,this.readonly=g,this.required=b,this.inputClass=v,this.inline=_,this.separator=A,this.autoApply=E,this.months=j??(o==="day"?2:1),this.presets=M,this.currentStartDate=n||"",this.currentEndDate=a||"",this._calendar=null,this._popover=null,this._presetSidebar=null}_defaultPlaceholder(e){return e==="year"?"Select year range...":e==="month"?"Select month range...":"Select date range..."}async renderTemplate(){const e=this._inputId(),t=this._displayText(),s=!this.currentStartDate,i=this.startName||(this.name?`${this.name}_start`:""),r=this.endName||(this.name?`${this.name}_end`:""),n=`
1130
+ `}async onAfterRender(){this.inline?this._mountCalendarInline():this._wireTrigger()}_wireTrigger(){const e=this.element.querySelector("[data-trigger]"),t=this.element.querySelector("[data-clear]");e&&(e.addEventListener("click",s=>{s.target.closest("[data-clear]")||this._togglePopover(e)}),t&&t.addEventListener("click",s=>{s.stopPropagation(),this._setValue("")}))}_togglePopover(e){if(!(this.disabled||this.readonly)){if(this._popover?this._popover.setAnchor(e):this._popover=new _e({anchor:e}),this._popover.isOpen()){this._popover.close();return}this._calendar||(this._calendar=this._buildCalendar()),this._popover.setContent(this._calendar.element),this._popover.open(),this._calendar.render(!1)}}_mountCalendarInline(){const e=this.element.querySelector("[data-cal-host]");e&&(this._calendar||(this._calendar=this._buildCalendar()),e.appendChild(this._calendar.element),this._calendar.render(!1))}_buildCalendar(){const e=new Be({precision:this.precision,mode:"single",months:1,value:this.currentValue||null,min:this.min,max:this.max,disabledDates:this.disabledDates,firstDay:this.firstDay,locale:this.lang});return e.on("select",({value:t})=>{this._setValue(t),this.autoApply&&this._popover&&this._popover.isOpen()&&this._popover.close()}),e}_setValue(e){const t=this.currentValue;let s="";if(e){const a=V(e,this.precision);a&&(s=U(a,this.precision))}this.currentValue=s;const i=this._displayText(s),r=this.element.querySelector("[data-trigger-text]");r&&(r.textContent=i||this.placeholder,r.classList.toggle("is-empty",!s));const n=this.element.querySelector("[data-hidden-value]");n&&(n.value=s),this._calendar&&this._calendar.setValue(s),t!==s&&(this.emit("change",{value:s,formatted:i,oldValue:t}),this.emit("date:changed",{value:s,oldValue:t}))}_displayText(e){if(!e)return"";const t=V(e,this.precision);return t?he(t,this._stripIncompatibleTokens(this.displayFormat)):""}_stripIncompatibleTokens(e){return this.precision==="day"?e:this.precision==="month"?e.replace(/\bDD\b|\bD\b/g,"").replace(/[\s\-\/]+$/,"").trim():this.precision==="year"?e.replace(/MMMM|MMM|MM|M|DD|D/g,"").replace(/[\s\-\/]+$/,"").trim()||"YYYY":e}setValue(e){this._setValue(e)}getValue(){return this.currentValue}getFormattedValue(){return this._displayText(this.currentValue)}clear(){this._setValue("")}setMin(e){this.min=e,this._calendar&&this._calendar.setMin(e)}setMax(e){this.max=e,this._calendar&&this._calendar.setMax(e)}setEnabled(e){this.disabled=!e;const t=this.element.querySelector("[data-trigger]");t&&(t.disabled=!e),!e&&this._popover&&this._popover.isOpen()&&this._popover.close()}setReadonly(e){this.readonly=e,e&&this._popover&&this._popover.isOpen()&&this._popover.close()}focus(){const e=this.element.querySelector("[data-trigger]");e&&e.focus()}show(){const e=this.element.querySelector("[data-trigger]");e&&this._togglePopover(e)}hide(){this._popover&&this._popover.close()}getFormValue(){return this.getValue()}async setFormValue(e){this._setValue(e)}hasError(){return!1}_inputId(){return this.name?`mojo-date-${this.name}-${this.id}`:`mojo-date-${this.id}`}_attr(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}async onBeforeDestroy(){this._popover&&(this._popover.destroy(),this._popover=null),this._calendar=null,await super.onBeforeDestroy()}static create(e={}){return new Ue(e)}}function ds(){return[{label:"Today",range:()=>{const c=F();return{start:c,end:c}}},{label:"Yesterday",range:()=>{const c=F(),e=xe(c,-1);return{start:e,end:e}}},{label:"Last 7 days",range:()=>{const c=F();return{start:xe(c,-6),end:c}}},{label:"Last 30 days",range:()=>{const c=F();return{start:xe(c,-29),end:c}}},{label:"Last 90 days",range:()=>{const c=F();return{start:xe(c,-89),end:c}}},{divider:!0},{label:"This month",range:()=>{const c=F();return{start:{y:c.y,m:c.m,d:1},end:c}}},{label:"Last month",range:()=>{const c=F(),e=ne({y:c.y,m:c.m,d:1},-1),t=ne(e,1);t.d=0;const s=new Date(t.y,t.m,0).getDate();return{start:{...e,d:1},end:{...e,d:s}}}},{label:"This year",range:()=>{const c=F();return{start:{y:c.y,m:1,d:1},end:c}}}]}function hs(){return[{label:"This month",range:()=>{const c=F();return{start:{y:c.y,m:c.m},end:{y:c.y,m:c.m}}}},{label:"Last month",range:()=>{const c=F(),e=ne({y:c.y,m:c.m},-1);return{start:e,end:e}}},{label:"Last 3 months",range:()=>{const c=F();return{start:ne({y:c.y,m:c.m},-2),end:{y:c.y,m:c.m}}}},{label:"Last 6 months",range:()=>{const c=F();return{start:ne({y:c.y,m:c.m},-5),end:{y:c.y,m:c.m}}}},{label:"YTD",range:()=>{const c=F();return{start:{y:c.y,m:1},end:{y:c.y,m:c.m}}}},{label:"Last 12 months",range:()=>{const c=F();return{start:ne({y:c.y,m:c.m},-11),end:{y:c.y,m:c.m}}}}]}function us(){return[{label:"This year",range:()=>{const c=F();return{start:{y:c.y},end:{y:c.y}}}},{label:"Last year",range:()=>{const c=F();return{start:{y:c.y-1},end:{y:c.y-1}}}},{label:"Last 3 years",range:()=>{const c=F();return{start:{y:c.y-2},end:{y:c.y}}}},{label:"Last 5 years",range:()=>{const c=F();return{start:{y:c.y-4},end:{y:c.y}}}},{label:"Last 10 years",range:()=>{const c=F();return{start:{y:c.y-9},end:{y:c.y}}}}]}function xe(c,e){if(!c)return null;const t=new Date(c.y,c.m-1,c.d+e);return{y:t.getFullYear(),m:t.getMonth()+1,d:t.getDate()}}function _t(c){return c==="year"?us():c==="month"?hs():ds()}class ms extends C{constructor(e={}){const{precision:t="day",presets:s="default",eyebrow:i="Quick range",...r}=e;super({tagName:"div",className:"mojo-calendar-presets",...r}),this.precision=t,this.eyebrow=i,this.activeIndex=-1,this.presets=s===!0||s==="default"?_t(t):Array.isArray(s)?s:_t(t)}setActive(e){this.activeIndex=e,this._highlight()}async renderTemplate(){return""}async onAfterRender(){this._renderInto(this.element)}_renderInto(e){if(e.innerHTML="",this.eyebrow){const t=document.createElement("div");t.className="mojo-calendar-presets-eyebrow",t.textContent=this.eyebrow,e.appendChild(t)}this.presets.forEach((t,s)=>{if(t.divider){const r=document.createElement("div");r.className="mojo-calendar-presets-divider",e.appendChild(r);return}const i=document.createElement("button");i.type="button",i.className="mojo-calendar-preset"+(this.activeIndex===s?" is-active":""),i.dataset.presetIndex=String(s),i.textContent=t.label,e.appendChild(i)}),e.addEventListener("click",t=>{const s=t.target.closest(".mojo-calendar-preset");if(!s)return;const i=parseInt(s.dataset.presetIndex,10),r=this.presets[i];if(!r||typeof r.range!="function")return;const n=r.range();this.activeIndex=i,this._highlight();const a=this.precision==="year"?mt:this.precision==="month"?He:B;this.emit("preset:select",{index:i,label:r.label,start:a(n.start),end:a(n.end),parsed:n})})}_highlight(){this.element&&this.element.querySelectorAll(".mojo-calendar-preset").forEach(e=>{const t=parseInt(e.dataset.presetIndex,10);e.classList.toggle("is-active",t===this.activeIndex)})}}const xt={day:"MMM DD, YYYY",month:"MMM YYYY",year:"YYYY"};class We extends C{constructor(e={}){const{name:t,startName:s,endName:i,fieldName:r,startDate:n="",endDate:a="",precision:o="day",format:l=null,displayFormat:d=null,outputFormat:h="date",min:u=null,max:m=null,placeholder:p=null,disabled:f=!1,readonly:g=!1,required:b=!1,class:y="",inputClass:v="form-control",inline:_=!1,separator:A=" – ",autoApply:E=!0,months:j=null,presets:I=null,...R}=e;super({tagName:"div",className:`mojo-date-picker mojo-date-range-picker mojo-date-picker-${o} ${y}`.trim(),...R}),this.name=t,this.startName=s,this.endName=i,this.fieldName=r,this.precision=o,this.format=l,this.displayFormat=d||xt[o]||xt.day,this.outputFormat=h,this.min=u,this.max=m,this.placeholder=p??this._defaultPlaceholder(o),this.disabled=f,this.readonly=g,this.required=b,this.inputClass=v,this.inline=_,this.separator=A,this.autoApply=E,this.months=j??(o==="day"?2:1),this.presets=I,this.currentStartDate=n||"",this.currentEndDate=a||"",this._calendar=null,this._popover=null,this._presetSidebar=null}_defaultPlaceholder(e){return e==="year"?"Select year range...":e==="month"?"Select month range...":"Select date range..."}async renderTemplate(){const e=this._inputId(),t=this._displayText(),s=!this.currentStartDate,i=this.startName||(this.name?`${this.name}_start`:""),r=this.endName||(this.name?`${this.name}_end`:""),n=`
1131
1131
  ${this.name?`<input type="hidden" name="${this._attr(this.name)}" value="${this._attr(this.getCombinedValue())}" data-combined-value />`:""}
1132
1132
  ${i?`<input type="hidden" name="${this._attr(i)}" value="${this._attr(this.currentStartDate)}" data-start-value />`:""}
1133
1133
  ${r?`<input type="hidden" name="${this._attr(r)}" value="${this._attr(this.currentEndDate)}" data-end-value />`:""}
@@ -1143,7 +1143,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1143
1143
  ${!this.required&&!this.disabled&&!this.readonly?'<button type="button" class="mojo-date-trigger-clear" data-clear aria-label="Clear" tabindex="-1">&#x2715;</button>':""}
1144
1144
  </button>
1145
1145
  ${n}
1146
- `}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 _e({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 Be({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 ms({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=U(o,this.precision))}if(t){const o=V(t,this.precision);o&&(n=U(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?`${de(e,s)}${this.separator}${de(t,s)}`:de(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 We(e)}}class $t 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=`
1146
+ `}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 _e({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 Be({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 ms({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=U(o,this.precision))}if(t){const o=V(t,this.precision);o&&(n=U(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?`${he(e,s)}${this.separator}${he(t,s)}`:he(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 We(e)}}class $t 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=`
1147
1147
  <div class="combobox-container">
1148
1148
  <div class="input-group">
1149
1149
  <input type="text"
@@ -1193,7 +1193,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1193
1193
  ${!this.required&&!this.disabled&&!this.readonly?'<button type="button" class="mojo-time-trigger-clear" data-clear aria-label="Clear" tabindex="-1">&#x2715;</button>':""}
1194
1194
  </button>
1195
1195
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(i)}" data-hidden-value />
1196
- `}async onAfterRender(){this.inline?this._mountInline():this._wireTrigger()}_wireTrigger(){const e=this.element.querySelector("[data-trigger]"),t=this.element.querySelector("[data-clear]");e&&(e.addEventListener("click",s=>{s.target.closest("[data-clear]")||this._togglePopover(e)}),t&&t.addEventListener("click",s=>{s.stopPropagation(),this.clear()}))}_togglePopover(e){if(this.disabled||this.readonly)return;if(this._popover?this._popover.setAnchor(e):this._popover=new _e({anchor:e,classNames:"mojo-time-popover"}),this._popover.isOpen()){this._popover.close();return}const t=this._buildSpinnerContent();this._popover.setContent(t),this._popover.open(),this.timezone&&this._mountTimezoneSelect()}_mountInline(){const e=this.element.querySelector("[data-time-host]");if(!e)return;const t=this._buildSpinnerContent();e.appendChild(t),this.timezone&&this._mountTimezoneSelect()}_buildSpinnerContent(){const e=document.createElement("div");e.className="mojo-time-popover-inner";const t=document.createElement("div");t.className="mojo-time-stepper-row";const s=this.currentTime||{hours:0,minutes:0},i=this._hourDisplay(s.hours);t.appendChild(this._buildStepper("hour",i,"Hour"));const r=document.createElement("div");if(r.className="mojo-time-stepper-sep",r.textContent=":",t.appendChild(r),t.appendChild(this._buildStepper("minute",Ye(s.minutes),"Minute")),this.format==="12h"&&t.appendChild(this._buildAmPmToggle(s.hours)),e.appendChild(t),this.timezone){const n=document.createElement("div");n.className="mojo-time-tz-host",n.setAttribute("data-tz-host",""),e.appendChild(n)}if(this.showFooter){const n=document.createElement("div");n.className="mojo-time-foot";const a=document.createElement("button");a.type="button",a.className="btn btn-link btn-sm mojo-time-now",a.textContent="Now",a.addEventListener("click",l=>{l.preventDefault();const d=new Date;this._commitTime({hours:d.getHours(),minutes:d.getMinutes()}),this._refreshSpinnerDisplay()}),n.appendChild(a);const o=document.createElement("button");o.type="button",o.className="btn btn-primary btn-sm mojo-time-apply",o.textContent="Set",o.addEventListener("click",l=>{l.preventDefault(),this.currentTime||this._commitTime({hours:0,minutes:0}),this._popover&&this._popover.isOpen()&&this._popover.close()}),n.appendChild(o),e.appendChild(n)}return this._spinner=e,e}_buildStepper(e,t,s){const i=document.createElement("div");i.className=`mojo-time-stepper mojo-time-stepper-${e}`;const r=document.createElement("button");r.type="button",r.className="mojo-time-stepper-btn",r.setAttribute("aria-label",`Increase ${s.toLowerCase()}`),r.innerHTML='<i class="bi bi-chevron-up" aria-hidden="true"></i>',r.addEventListener("click",l=>{l.preventDefault(),this._step(e,1)});const n=document.createElement("input");n.type="text",n.className="mojo-time-stepper-value",n.value=t,n.setAttribute("inputmode","numeric"),n.setAttribute("aria-label",s),n.maxLength=2,n.addEventListener("focus",()=>n.select()),n.addEventListener("keydown",l=>this._onValueKey(e,n,l)),n.addEventListener("blur",()=>this._onValueBlur(e,n));const a=document.createElement("button");a.type="button",a.className="mojo-time-stepper-btn",a.setAttribute("aria-label",`Decrease ${s.toLowerCase()}`),a.innerHTML='<i class="bi bi-chevron-down" aria-hidden="true"></i>',a.addEventListener("click",l=>{l.preventDefault(),this._step(e,-1)});const o=document.createElement("div");return o.className="mojo-time-stepper-label",o.textContent=s,i.appendChild(r),i.appendChild(n),i.appendChild(a),i.appendChild(o),i}_buildAmPmToggle(e){const t=document.createElement("div");t.className="mojo-time-ampm";const s=e>=12,i=document.createElement("button");i.type="button",i.className=`mojo-time-ampm-btn${s?"":" is-active"}`,i.textContent="AM",i.addEventListener("click",n=>{n.preventDefault(),this._setAmPm("am")});const r=document.createElement("button");return r.type="button",r.className=`mojo-time-ampm-btn${s?" is-active":""}`,r.textContent="PM",r.addEventListener("click",n=>{n.preventDefault(),this._setAmPm("pm")}),t.appendChild(i),t.appendChild(r),t}_mountTimezoneSelect(){if(!this.timezone)return;const e=this.inline?this.element.querySelector("[data-time-host] [data-tz-host]"):this._spinner&&this._spinner.querySelector("[data-tz-host]");if(e){if(this._tzSelect)try{this._tzSelect.destroy&&this._tzSelect.destroy()}catch{}e.innerHTML="",this._tzSelect=new Tt({name:"timezone",value:this.currentTimezone,timezones:this.timezoneList}),this._tzSelect.render(!0,e),this._tzSelect.on("change",({value:t})=>{const s=this.currentTimezone;this.currentTimezone=t||null,s!==this.currentTimezone&&this._syncOutputs()})}}_step(e,t){const s=this.currentTime||{hours:0,minutes:0};let{hours:i,minutes:r}=s;if(e==="hour")i=((i+t)%24+24)%24;else{const a=i*60+r,o=t*this.step,l=((a+o)%1440+1440)%1440;i=Math.floor(l/60),r=l%60}const n=this._clampToBounds({hours:i,minutes:r});this._commitTime(n),this._refreshSpinnerDisplay()}_setAmPm(e){if(!this.currentTime)this._commitTime({hours:e==="pm"?12:0,minutes:0});else{const{hours:t,minutes:s}=this.currentTime;let i=t;e==="am"&&i>=12?i-=12:e==="pm"&&i<12&&(i+=12),this._commitTime(this._clampToBounds({hours:i,minutes:s}))}this._refreshSpinnerDisplay()}_onValueKey(e,t,s){s.key==="ArrowUp"?(s.preventDefault(),this._step(e,1),t.focus(),t.select()):s.key==="ArrowDown"?(s.preventDefault(),this._step(e,-1),t.focus(),t.select()):s.key==="Enter"?(s.preventDefault(),t.blur()):s.key==="Tab"||!/^[0-9]$/.test(s.key)&&!["Backspace","Delete","ArrowLeft","ArrowRight","Home","End"].includes(s.key)&&s.preventDefault()}_onValueBlur(e,t){const s=(t.value||"").replace(/\D/g,"");if(s===""){this._refreshSpinnerDisplay();return}let i=parseInt(s,10);const r=this.currentTime||{hours:0,minutes:0};let{hours:n,minutes:a}=r;if(e==="hour")if(this.format==="12h"){i<1&&(i=1),i>12&&(i=12);const o=r.hours>=12;i===12?n=o?12:0:n=o?i+12:i}else i<0&&(i=0),i>23&&(i=23),n=i;else i<0&&(i=0),i>59&&(i=59),a=i;this._commitTime(this._clampToBounds({hours:n,minutes:a})),this._refreshSpinnerDisplay()}_hourDisplay(e){if(this.format==="12h"){let t=e%12;return t===0&&(t=12),String(t)}return Ye(e)}_refreshSpinnerDisplay(){if(!this._spinner)return;const e=this.currentTime||{hours:0,minutes:0},t=this._spinner.querySelector(".mojo-time-stepper-hour .mojo-time-stepper-value"),s=this._spinner.querySelector(".mojo-time-stepper-minute .mojo-time-stepper-value");if(t&&(t.value=this._hourDisplay(e.hours)),s&&(s.value=Ye(e.minutes)),this.format==="12h"){const i=e.hours>=12,r=this._spinner.querySelector(".mojo-time-ampm-btn:nth-child(1)"),n=this._spinner.querySelector(".mojo-time-ampm-btn:nth-child(2)");r&&r.classList.toggle("is-active",!i),n&&n.classList.toggle("is-active",i)}}_clampToBounds(e){const t=this.min?G(this.min):null,s=this.max?G(this.max):null;return t&&bt(e,t)<0?t:s&&bt(e,s)>0?s:e}_commitTime(e){const t=this._serialize();this.currentTime=e?{hours:e.hours,minutes:e.minutes}:null,this._syncOutputs(t)}_syncOutputs(e){const t=this._serialize(),s=this._displayText(),i=this.element&&this.element.querySelector("[data-trigger-text]");i&&(i.textContent=s||this.placeholder,i.classList.toggle("is-empty",!this.currentTime));const r=this.element&&this.element.querySelector("[data-hidden-value]");r&&(r.value=t),e!==void 0&&e!==t&&(this.emit("change",{value:this.getValue(),formatted:s,oldValue:e}),this.emit("time:changed",{value:this.getValue()}))}_serialize(){if(!this.currentTime)return"";const e=J(this.currentTime,"24h");if(!this.timezone||!this.currentTimezone)return e;if(this.outputFormat==="iana")return`${e} ${this.currentTimezone}`;const t=yt(this.currentTimezone,new Date);return t?`${e}${t}`:e}_displayText(){if(!this.currentTime)return"";const e=J(this.currentTime,this.format);return this.timezone&&this.currentTimezone?`${e} ${this.currentTimezone}`:e}getValue(){return this.currentTime?this.timezone&&this.outputFormat==="object"?{time:J(this.currentTime,"24h"),timezone:this.currentTimezone||null}:this._serialize():this.outputFormat==="object"?null:""}setValue(e){const t=this._serialize(),s=this._parseInitial(e);this.currentTime=s.time,s.timezone&&(this.currentTimezone=s.timezone),this._refreshSpinnerDisplay(),this._syncOutputs(t)}getFormattedValue(){return this._displayText()}clear(){if(!this.currentTime&&!this.element.querySelector("[data-hidden-value]")?.value)return;const e=this._serialize();this.currentTime=null,this._syncOutputs(e)}setMin(e){this.min=e}setMax(e){this.max=e}setEnabled(e){this.disabled=!e;const t=this.element.querySelector("[data-trigger]");t&&(t.disabled=!e),!e&&this._popover&&this._popover.isOpen()&&this._popover.close()}setReadonly(e){this.readonly=e,e&&this._popover&&this._popover.isOpen()&&this._popover.close()}focus(){const e=this.element.querySelector("[data-trigger]");e&&e.focus()}show(){const e=this.element.querySelector("[data-trigger]");e&&this._togglePopover(e)}hide(){this._popover&&this._popover.close()}getFormValue(){return this.getValue()}async setFormValue(e){this.setValue(e)}hasError(){return!1}_inputId(){return this.name?`mojo-time-${this.name}-${this.id}`:`mojo-time-${this.id}`}_attr(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}async onBeforeDestroy(){if(this._popover){try{this._popover.destroy()}catch{}this._popover=null}if(this._tzSelect){try{await this._tzSelect.destroy()}catch{}this._tzSelect=null}this._spinner=null,await super.onBeforeDestroy()}static addMinutes(e,t){return ls(e,t)}static create(e={}){return new $e(e)}}function Ye(c){return c<10?"0"+c:String(c)}function bs(){try{return new Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}catch{return"UTC"}}const ys="MMM DD, YYYY";class Ge extends C{constructor(e={}){const{name:t,value:s="",format:i=null,displayFormat:r=null,timeFormat:n="24h",timeStep:a=1,min:o=null,max:l=null,placeholder:d=null,disabled:h=!1,readonly:u=!1,required:m=!1,class:p="",inline:f=!1,disabledDates:g=[],firstDay:b=1,lang:y="en-US",autoApply:v=!1,timezone:_=!1,timezones:A=null,outputFormat:E="iso",...j}=e;super({tagName:"div",className:`mojo-datetime-picker ${p}`.trim(),...j}),this.name=t,this.format=i,this.displayFormat=r||ys,this.timeFormat=n==="12h"?"12h":"24h",this.timeStep=Math.max(1,parseInt(a,10)||1),this.min=o,this.max=l,this.placeholder=d??"Pick date & time...",this.disabled=h,this.readonly=u,this.required=m,this.inline=f,this.disabledDates=g,this.firstDay=b,this.lang=y,this.autoApply=v,this.timezone=_===!0||Array.isArray(_),this.timezoneList=Array.isArray(_)?_:A,this.outputFormat=["object","iana","iso"].includes(E)?E:"iso";const M=this._parseInitial(s);this.currentDate=M.date,this.currentTime=M.time,this.currentTimezone=M.timezone||(this.timezone?Ft():null),this._calendar=null,this._timePicker=null,this._tzSelect=null,this._popover=null,this._popoverContent=null}_parseInitial(e){return e==null||e===""?{date:null,time:null,timezone:null}:typeof e=="object"&&!Array.isArray(e)&&!(e instanceof Date)?wt(e)||{date:null,time:null,timezone:null}:wt(e)||{date:null,time:null,timezone:null}}async renderTemplate(){const e=this._inputId(),t=this._displayText(),s=!this.currentDate,i=this._serialize();return this.inline?`
1196
+ `}async onAfterRender(){this.inline?this._mountInline():this._wireTrigger()}_wireTrigger(){const e=this.element.querySelector("[data-trigger]"),t=this.element.querySelector("[data-clear]");e&&(e.addEventListener("click",s=>{s.target.closest("[data-clear]")||this._togglePopover(e)}),t&&t.addEventListener("click",s=>{s.stopPropagation(),this.clear()}))}_togglePopover(e){if(this.disabled||this.readonly)return;if(this._popover?this._popover.setAnchor(e):this._popover=new _e({anchor:e,classNames:"mojo-time-popover"}),this._popover.isOpen()){this._popover.close();return}const t=this._buildSpinnerContent();this._popover.setContent(t),this._popover.open(),this.timezone&&this._mountTimezoneSelect()}_mountInline(){const e=this.element.querySelector("[data-time-host]");if(!e)return;const t=this._buildSpinnerContent();e.appendChild(t),this.timezone&&this._mountTimezoneSelect()}_buildSpinnerContent(){const e=document.createElement("div");e.className="mojo-time-popover-inner";const t=document.createElement("div");t.className="mojo-time-stepper-row";const s=this.currentTime||{hours:0,minutes:0},i=this._hourDisplay(s.hours);t.appendChild(this._buildStepper("hour",i,"Hour"));const r=document.createElement("div");if(r.className="mojo-time-stepper-sep",r.textContent=":",t.appendChild(r),t.appendChild(this._buildStepper("minute",Ye(s.minutes),"Minute")),this.format==="12h"&&t.appendChild(this._buildAmPmToggle(s.hours)),e.appendChild(t),this.timezone){const n=document.createElement("div");n.className="mojo-time-tz-host",n.setAttribute("data-tz-host",""),e.appendChild(n)}if(this.showFooter){const n=document.createElement("div");n.className="mojo-time-foot";const a=document.createElement("button");a.type="button",a.className="btn btn-link btn-sm mojo-time-now",a.textContent="Now",a.addEventListener("click",l=>{l.preventDefault();const d=new Date;this._commitTime({hours:d.getHours(),minutes:d.getMinutes()}),this._refreshSpinnerDisplay()}),n.appendChild(a);const o=document.createElement("button");o.type="button",o.className="btn btn-primary btn-sm mojo-time-apply",o.textContent="Set",o.addEventListener("click",l=>{l.preventDefault(),this.currentTime||this._commitTime({hours:0,minutes:0}),this._popover&&this._popover.isOpen()&&this._popover.close()}),n.appendChild(o),e.appendChild(n)}return this._spinner=e,e}_buildStepper(e,t,s){const i=document.createElement("div");i.className=`mojo-time-stepper mojo-time-stepper-${e}`;const r=document.createElement("button");r.type="button",r.className="mojo-time-stepper-btn",r.setAttribute("aria-label",`Increase ${s.toLowerCase()}`),r.innerHTML='<i class="bi bi-chevron-up" aria-hidden="true"></i>',r.addEventListener("click",l=>{l.preventDefault(),this._step(e,1)});const n=document.createElement("input");n.type="text",n.className="mojo-time-stepper-value",n.value=t,n.setAttribute("inputmode","numeric"),n.setAttribute("aria-label",s),n.maxLength=2,n.addEventListener("focus",()=>n.select()),n.addEventListener("keydown",l=>this._onValueKey(e,n,l)),n.addEventListener("blur",()=>this._onValueBlur(e,n));const a=document.createElement("button");a.type="button",a.className="mojo-time-stepper-btn",a.setAttribute("aria-label",`Decrease ${s.toLowerCase()}`),a.innerHTML='<i class="bi bi-chevron-down" aria-hidden="true"></i>',a.addEventListener("click",l=>{l.preventDefault(),this._step(e,-1)});const o=document.createElement("div");return o.className="mojo-time-stepper-label",o.textContent=s,i.appendChild(r),i.appendChild(n),i.appendChild(a),i.appendChild(o),i}_buildAmPmToggle(e){const t=document.createElement("div");t.className="mojo-time-ampm";const s=e>=12,i=document.createElement("button");i.type="button",i.className=`mojo-time-ampm-btn${s?"":" is-active"}`,i.textContent="AM",i.addEventListener("click",n=>{n.preventDefault(),this._setAmPm("am")});const r=document.createElement("button");return r.type="button",r.className=`mojo-time-ampm-btn${s?" is-active":""}`,r.textContent="PM",r.addEventListener("click",n=>{n.preventDefault(),this._setAmPm("pm")}),t.appendChild(i),t.appendChild(r),t}_mountTimezoneSelect(){if(!this.timezone)return;const e=this.inline?this.element.querySelector("[data-time-host] [data-tz-host]"):this._spinner&&this._spinner.querySelector("[data-tz-host]");if(e){if(this._tzSelect)try{this._tzSelect.destroy&&this._tzSelect.destroy()}catch{}e.innerHTML="",this._tzSelect=new Tt({name:"timezone",value:this.currentTimezone,timezones:this.timezoneList}),this._tzSelect.render(!0,e),this._tzSelect.on("change",({value:t})=>{const s=this.currentTimezone;this.currentTimezone=t||null,s!==this.currentTimezone&&this._syncOutputs()})}}_step(e,t){const s=this.currentTime||{hours:0,minutes:0};let{hours:i,minutes:r}=s;if(e==="hour")i=((i+t)%24+24)%24;else{const a=i*60+r,o=t*this.step,l=((a+o)%1440+1440)%1440;i=Math.floor(l/60),r=l%60}const n=this._clampToBounds({hours:i,minutes:r});this._commitTime(n),this._refreshSpinnerDisplay()}_setAmPm(e){if(!this.currentTime)this._commitTime({hours:e==="pm"?12:0,minutes:0});else{const{hours:t,minutes:s}=this.currentTime;let i=t;e==="am"&&i>=12?i-=12:e==="pm"&&i<12&&(i+=12),this._commitTime(this._clampToBounds({hours:i,minutes:s}))}this._refreshSpinnerDisplay()}_onValueKey(e,t,s){s.key==="ArrowUp"?(s.preventDefault(),this._step(e,1),t.focus(),t.select()):s.key==="ArrowDown"?(s.preventDefault(),this._step(e,-1),t.focus(),t.select()):s.key==="Enter"?(s.preventDefault(),t.blur()):s.key==="Tab"||!/^[0-9]$/.test(s.key)&&!["Backspace","Delete","ArrowLeft","ArrowRight","Home","End"].includes(s.key)&&s.preventDefault()}_onValueBlur(e,t){const s=(t.value||"").replace(/\D/g,"");if(s===""){this._refreshSpinnerDisplay();return}let i=parseInt(s,10);const r=this.currentTime||{hours:0,minutes:0};let{hours:n,minutes:a}=r;if(e==="hour")if(this.format==="12h"){i<1&&(i=1),i>12&&(i=12);const o=r.hours>=12;i===12?n=o?12:0:n=o?i+12:i}else i<0&&(i=0),i>23&&(i=23),n=i;else i<0&&(i=0),i>59&&(i=59),a=i;this._commitTime(this._clampToBounds({hours:n,minutes:a})),this._refreshSpinnerDisplay()}_hourDisplay(e){if(this.format==="12h"){let t=e%12;return t===0&&(t=12),String(t)}return Ye(e)}_refreshSpinnerDisplay(){if(!this._spinner)return;const e=this.currentTime||{hours:0,minutes:0},t=this._spinner.querySelector(".mojo-time-stepper-hour .mojo-time-stepper-value"),s=this._spinner.querySelector(".mojo-time-stepper-minute .mojo-time-stepper-value");if(t&&(t.value=this._hourDisplay(e.hours)),s&&(s.value=Ye(e.minutes)),this.format==="12h"){const i=e.hours>=12,r=this._spinner.querySelector(".mojo-time-ampm-btn:nth-child(1)"),n=this._spinner.querySelector(".mojo-time-ampm-btn:nth-child(2)");r&&r.classList.toggle("is-active",!i),n&&n.classList.toggle("is-active",i)}}_clampToBounds(e){const t=this.min?G(this.min):null,s=this.max?G(this.max):null;return t&&bt(e,t)<0?t:s&&bt(e,s)>0?s:e}_commitTime(e){const t=this._serialize();this.currentTime=e?{hours:e.hours,minutes:e.minutes}:null,this._syncOutputs(t)}_syncOutputs(e){const t=this._serialize(),s=this._displayText(),i=this.element&&this.element.querySelector("[data-trigger-text]");i&&(i.textContent=s||this.placeholder,i.classList.toggle("is-empty",!this.currentTime));const r=this.element&&this.element.querySelector("[data-hidden-value]");r&&(r.value=t),e!==void 0&&e!==t&&(this.emit("change",{value:this.getValue(),formatted:s,oldValue:e}),this.emit("time:changed",{value:this.getValue()}))}_serialize(){if(!this.currentTime)return"";const e=J(this.currentTime,"24h");if(!this.timezone||!this.currentTimezone)return e;if(this.outputFormat==="iana")return`${e} ${this.currentTimezone}`;const t=yt(this.currentTimezone,new Date);return t?`${e}${t}`:e}_displayText(){if(!this.currentTime)return"";const e=J(this.currentTime,this.format);return this.timezone&&this.currentTimezone?`${e} ${this.currentTimezone}`:e}getValue(){return this.currentTime?this.timezone&&this.outputFormat==="object"?{time:J(this.currentTime,"24h"),timezone:this.currentTimezone||null}:this._serialize():this.outputFormat==="object"?null:""}setValue(e){const t=this._serialize(),s=this._parseInitial(e);this.currentTime=s.time,s.timezone&&(this.currentTimezone=s.timezone),this._refreshSpinnerDisplay(),this._syncOutputs(t)}getFormattedValue(){return this._displayText()}clear(){if(!this.currentTime&&!this.element.querySelector("[data-hidden-value]")?.value)return;const e=this._serialize();this.currentTime=null,this._syncOutputs(e)}setMin(e){this.min=e}setMax(e){this.max=e}setEnabled(e){this.disabled=!e;const t=this.element.querySelector("[data-trigger]");t&&(t.disabled=!e),!e&&this._popover&&this._popover.isOpen()&&this._popover.close()}setReadonly(e){this.readonly=e,e&&this._popover&&this._popover.isOpen()&&this._popover.close()}focus(){const e=this.element.querySelector("[data-trigger]");e&&e.focus()}show(){const e=this.element.querySelector("[data-trigger]");e&&this._togglePopover(e)}hide(){this._popover&&this._popover.close()}getFormValue(){return this.getValue()}async setFormValue(e){this.setValue(e)}hasError(){return!1}_inputId(){return this.name?`mojo-time-${this.name}-${this.id}`:`mojo-time-${this.id}`}_attr(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}async onBeforeDestroy(){if(this._popover){try{this._popover.destroy()}catch{}this._popover=null}if(this._tzSelect){try{await this._tzSelect.destroy()}catch{}this._tzSelect=null}this._spinner=null,await super.onBeforeDestroy()}static addMinutes(e,t){return ls(e,t)}static create(e={}){return new $e(e)}}function Ye(c){return c<10?"0"+c:String(c)}function bs(){try{return new Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}catch{return"UTC"}}const ys="MMM DD, YYYY";class Ge extends C{constructor(e={}){const{name:t,value:s="",format:i=null,displayFormat:r=null,timeFormat:n="24h",timeStep:a=1,min:o=null,max:l=null,placeholder:d=null,disabled:h=!1,readonly:u=!1,required:m=!1,class:p="",inline:f=!1,disabledDates:g=[],firstDay:b=1,lang:y="en-US",autoApply:v=!1,timezone:_=!1,timezones:A=null,outputFormat:E="iso",...j}=e;super({tagName:"div",className:`mojo-datetime-picker ${p}`.trim(),...j}),this.name=t,this.format=i,this.displayFormat=r||ys,this.timeFormat=n==="12h"?"12h":"24h",this.timeStep=Math.max(1,parseInt(a,10)||1),this.min=o,this.max=l,this.placeholder=d??"Pick date & time...",this.disabled=h,this.readonly=u,this.required=m,this.inline=f,this.disabledDates=g,this.firstDay=b,this.lang=y,this.autoApply=v,this.timezone=_===!0||Array.isArray(_),this.timezoneList=Array.isArray(_)?_:A,this.outputFormat=["object","iana","iso"].includes(E)?E:"iso";const I=this._parseInitial(s);this.currentDate=I.date,this.currentTime=I.time,this.currentTimezone=I.timezone||(this.timezone?Ft():null),this._calendar=null,this._timePicker=null,this._tzSelect=null,this._popover=null,this._popoverContent=null}_parseInitial(e){return e==null||e===""?{date:null,time:null,timezone:null}:typeof e=="object"&&!Array.isArray(e)&&!(e instanceof Date)?wt(e)||{date:null,time:null,timezone:null}:wt(e)||{date:null,time:null,timezone:null}}async renderTemplate(){const e=this._inputId(),t=this._displayText(),s=!this.currentDate,i=this._serialize();return this.inline?`
1197
1197
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(i)}" data-hidden-value />
1198
1198
  <div data-dt-host class="mojo-datetime-picker-inline${this.hasError()?" is-invalid":""}"></div>
1199
1199
  `:`
@@ -1205,7 +1205,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1205
1205
  ${!this.required&&!this.disabled&&!this.readonly?'<button type="button" class="mojo-datetime-trigger-clear" data-clear aria-label="Clear" tabindex="-1">&#x2715;</button>':""}
1206
1206
  </button>
1207
1207
  <input type="hidden" name="${this._attr(this.name||"")}" value="${this._attr(i)}" data-hidden-value />
1208
- `}async onAfterRender(){this.inline?this._mountInline():this._wireTrigger()}_wireTrigger(){const e=this.element.querySelector("[data-trigger]"),t=this.element.querySelector("[data-clear]");e&&(e.addEventListener("click",s=>{s.target.closest("[data-clear]")||this._togglePopover(e)}),t&&t.addEventListener("click",s=>{s.stopPropagation(),this.clear()}))}_togglePopover(e){if(!(this.disabled||this.readonly)){if(this._popover?this._popover.setAnchor(e):this._popover=new _e({anchor:e,classNames:"mojo-datetime-popover"}),this._popover.isOpen()){this._popover.close();return}this._popoverContent||(this._popoverContent=this._buildContent()),this._popover.setContent(this._popoverContent),this._popover.open(),this._calendar&&this._calendar.render(!1)}}_mountInline(){const e=this.element.querySelector("[data-dt-host]");e&&(this._popoverContent||(this._popoverContent=this._buildContent()),e.appendChild(this._popoverContent),this._calendar&&this._calendar.render(!1))}_buildContent(){const e=document.createElement("div");e.className="mojo-datetime-popover-inner";const t=document.createElement("div");t.className="mojo-datetime-row";const s=document.createElement("div");s.className="mojo-datetime-cal-col",t.appendChild(s);const i=document.createElement("div");i.className="mojo-datetime-time-col",t.appendChild(i),e.appendChild(t),this._calendar=new Be({precision:"day",mode:"single",months:1,value:this.currentDate?B(this.currentDate):null,min:this._dateBound(this.min),max:this._dateBound(this.max),disabledDates:this.disabledDates,firstDay:this.firstDay,locale:this.lang}),s.appendChild(this._calendar.element),this._calendar.on("select",({value:l})=>{const d=q(l);this.currentDate=d,this.currentTime||(this.currentTime={hours:0,minutes:0}),this._refreshTimezoneDefault(),this._syncOutputs()}),this._timePicker=new $e({name:null,value:this.currentTime?J(this.currentTime,"24h"):"",format:this.timeFormat,step:this.timeStep,timezone:!1,inline:!0,autoApply:!1,showFooter:!1});const r=document.createElement("div");if(r.className="mojo-datetime-time-head",r.textContent="Time",i.appendChild(r),i.appendChild(this._timePicker.element),this._timePicker.on("change",()=>{const l=this._timePicker.currentTime;if(this.currentTime=l?{...l}:null,this.currentTime&&!this.currentDate){const d=new Date;this.currentDate={y:d.getFullYear(),m:d.getMonth()+1,d:d.getDate()},this._calendar&&this._calendar.setValue(B(this.currentDate))}this._syncOutputs()}),this._timePicker.render(!1),this.timezone){const l=document.createElement("div");l.className="mojo-datetime-tz-row";const d=document.createElement("div");d.className="mojo-datetime-tz-label",d.textContent="Timezone",l.appendChild(d);const h=document.createElement("div");h.className="mojo-datetime-tz-host",l.appendChild(h),e.appendChild(l),this._tzSelect=new Tt({name:"timezone",value:this.currentTimezone,timezones:Array.isArray(this.timezoneList)?this.timezoneList:null}),this._tzSelect.render(!0,h),this._tzSelect.on("change",({value:u})=>{const m=this.currentTimezone;this.currentTimezone=u||null,m!==this.currentTimezone&&this._syncOutputs()})}const n=document.createElement("div");n.className="mojo-datetime-foot";const a=document.createElement("button");a.type="button",a.className="btn btn-link btn-sm",a.textContent="Now",a.addEventListener("click",l=>{l.preventDefault();const d=new Date;this.currentDate={y:d.getFullYear(),m:d.getMonth()+1,d:d.getDate()},this.currentTime={hours:d.getHours(),minutes:d.getMinutes()},this._calendar&&this._calendar.setValue(B(this.currentDate)),this._timePicker&&this._timePicker.setValue(J(this.currentTime,"24h")),this._syncOutputs()}),n.appendChild(a);const o=document.createElement("button");return o.type="button",o.className="btn btn-primary btn-sm",o.textContent="Done",o.addEventListener("click",l=>{l.preventDefault(),this._popover&&this._popover.isOpen()&&this._popover.close()}),n.appendChild(o),e.appendChild(n),e}_refreshTimezoneDefault(){this.timezone&&!this.currentTimezone&&this._timePicker&&(this.currentTimezone=this._timePicker.currentTimezone||Ft())}_timePickerValue(){if(!this.currentTime&&!this.currentTimezone)return"";const e=this.currentTime?J(this.currentTime,"24h"):"00:00";return this.timezone&&this.currentTimezone?`${e} ${this.currentTimezone}`:e}_dateBound(e){return e?String(e).trim().split(/[ T]/)[0]:null}_syncOutputs(e){const t=this._serialize(),s=this._displayText(),i=this.element&&this.element.querySelector("[data-trigger-text]");i&&(i.textContent=s||this.placeholder,i.classList.toggle("is-empty",!this.currentDate));const r=this.element&&this.element.querySelector("[data-hidden-value]");r&&(r.value=t),e!==void 0&&e!==t?(this.emit("change",{value:this.getValue(),formatted:s,oldValue:e}),this.emit("datetime:changed",{value:this.getValue()})):e===void 0&&this.emit("change",{value:this.getValue(),formatted:s,oldValue:null})}_serialize(){if(!this.currentDate)return"";const e=B(this.currentDate),t=this.currentTime?J(this.currentTime,"24h"):"00:00";if(this.outputFormat==="iana"){let i=`${e} ${t}`;return this.timezone&&this.currentTimezone&&(i+=` ${this.currentTimezone}`),i}let s=`${e}T${t}:00`;if(this.timezone&&this.currentTimezone){const i=new Date(this.currentDate.y,this.currentDate.m-1,this.currentDate.d,this.currentTime?.hours||0,this.currentTime?.minutes||0),r=yt(this.currentTimezone,i);r&&(s+=r)}return s}_displayText(){if(!this.currentDate)return"";const e=de(this.currentDate,this.displayFormat),t=this.currentTime?J(this.currentTime,this.timeFormat):this.timeFormat==="12h"?"12:00 AM":"00:00";let s=`${e} ${t}`;return this.timezone&&this.currentTimezone&&(s+=` ${this.currentTimezone}`),s}getValue(){if(!this.currentDate)return this.outputFormat==="object"?null:"";if(this.outputFormat==="object"){const e={date:B(this.currentDate),time:this.currentTime?J(this.currentTime,"24h"):"00:00"};return this.timezone&&(e.timezone=this.currentTimezone||null),e}return this._serialize()}setValue(e){const t=this._parseInitial(e);this.currentDate=t.date,this.currentTime=t.time,t.timezone&&(this.currentTimezone=t.timezone),this._calendar&&this.currentDate&&this._calendar.setValue(B(this.currentDate)),this._timePicker&&this._timePicker.setValue(this._timePickerValue()),this._syncOutputs()}getFormattedValue(){return this._displayText()}clear(){const e=this._serialize();this.currentDate=null,this.currentTime=null,this._calendar&&this._calendar.setValue(null),this._timePicker&&this._timePicker.clear(),this._syncOutputs(e)}setMin(e){this.min=e,this._calendar&&this._calendar.setMin(this._dateBound(e))}setMax(e){this.max=e,this._calendar&&this._calendar.setMax(this._dateBound(e))}setEnabled(e){this.disabled=!e;const t=this.element.querySelector("[data-trigger]");t&&(t.disabled=!e),!e&&this._popover&&this._popover.isOpen()&&this._popover.close()}setReadonly(e){this.readonly=e,e&&this._popover&&this._popover.isOpen()&&this._popover.close()}focus(){const e=this.element.querySelector("[data-trigger]");e&&e.focus()}show(){const e=this.element.querySelector("[data-trigger]");e&&this._togglePopover(e)}hide(){this._popover&&this._popover.close()}getFormValue(){return this.getValue()}async setFormValue(e){this.setValue(e)}hasError(){return!1}_inputId(){return this.name?`mojo-datetime-${this.name}-${this.id}`:`mojo-datetime-${this.id}`}_attr(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}async onBeforeDestroy(){if(this._popover){try{this._popover.destroy()}catch{}this._popover=null}if(this._timePicker){try{await this._timePicker.destroy()}catch{}this._timePicker=null}if(this._tzSelect){try{await this._tzSelect.destroy()}catch{}this._tzSelect=null}this._calendar=null,this._popoverContent=null,await super.onBeforeDestroy()}static create(e={}){return new Ge(e)}}function Ft(){try{return new Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}catch{return"UTC"}}class Je extends C{constructor(e={}){const{name:t,value:s="",placeholder:i="Select or type...",options:r=[],allowCustom:n=!0,showDescription:a=!0,minChars:o=0,maxSuggestions:l=10,disabled:d=!1,readonly:h=!1,required:u=!1,class:m="",inputClass:p="form-control",onSelect:f=null,onChange:g=null,...b}=e;super({tagName:"div",className:`combo-input ${m}`,...b}),this.name=t,this.placeholder=i,this.options=this.normalizeOptions(r),this.allowCustom=n,this.showDescription=a,this.minChars=o,this.maxSuggestions=l,this.disabled=d,this.readonly=h,this.required=u,this.inputClass=p,this.onSelectCallback=f,this.onChangeCallback=g,this.currentValue=s,this.inputValue=this.getDisplayValue(s),this.filteredOptions=[],this.highlightedIndex=-1,this.isOpen=!1,this.selectedOption=this.findOptionByValue(s)}normalizeOptions(e){return Array.isArray(e)?e.map(t=>typeof t=="string"?{value:t,label:t}:typeof t=="object"&&t.value!==void 0?{value:t.value,label:t.label||String(t.value),description:t.description||t.label||"",meta:t.meta||{}}:null).filter(t=>t!==null):[]}findOptionByValue(e){return this.options.find(t=>t.value===e)||null}getDisplayValue(e){const t=this.findOptionByValue(e);return t?t.label:e}async renderTemplate(){return`
1208
+ `}async onAfterRender(){this.inline?this._mountInline():this._wireTrigger()}_wireTrigger(){const e=this.element.querySelector("[data-trigger]"),t=this.element.querySelector("[data-clear]");e&&(e.addEventListener("click",s=>{s.target.closest("[data-clear]")||this._togglePopover(e)}),t&&t.addEventListener("click",s=>{s.stopPropagation(),this.clear()}))}_togglePopover(e){if(!(this.disabled||this.readonly)){if(this._popover?this._popover.setAnchor(e):this._popover=new _e({anchor:e,classNames:"mojo-datetime-popover"}),this._popover.isOpen()){this._popover.close();return}this._popoverContent||(this._popoverContent=this._buildContent()),this._popover.setContent(this._popoverContent),this._popover.open(),this._calendar&&this._calendar.render(!1)}}_mountInline(){const e=this.element.querySelector("[data-dt-host]");e&&(this._popoverContent||(this._popoverContent=this._buildContent()),e.appendChild(this._popoverContent),this._calendar&&this._calendar.render(!1))}_buildContent(){const e=document.createElement("div");e.className="mojo-datetime-popover-inner";const t=document.createElement("div");t.className="mojo-datetime-row";const s=document.createElement("div");s.className="mojo-datetime-cal-col",t.appendChild(s);const i=document.createElement("div");i.className="mojo-datetime-time-col",t.appendChild(i),e.appendChild(t),this._calendar=new Be({precision:"day",mode:"single",months:1,value:this.currentDate?B(this.currentDate):null,min:this._dateBound(this.min),max:this._dateBound(this.max),disabledDates:this.disabledDates,firstDay:this.firstDay,locale:this.lang}),s.appendChild(this._calendar.element),this._calendar.on("select",({value:l})=>{const d=q(l);this.currentDate=d,this.currentTime||(this.currentTime={hours:0,minutes:0}),this._refreshTimezoneDefault(),this._syncOutputs()}),this._timePicker=new $e({name:null,value:this.currentTime?J(this.currentTime,"24h"):"",format:this.timeFormat,step:this.timeStep,timezone:!1,inline:!0,autoApply:!1,showFooter:!1});const r=document.createElement("div");if(r.className="mojo-datetime-time-head",r.textContent="Time",i.appendChild(r),i.appendChild(this._timePicker.element),this._timePicker.on("change",()=>{const l=this._timePicker.currentTime;if(this.currentTime=l?{...l}:null,this.currentTime&&!this.currentDate){const d=new Date;this.currentDate={y:d.getFullYear(),m:d.getMonth()+1,d:d.getDate()},this._calendar&&this._calendar.setValue(B(this.currentDate))}this._syncOutputs()}),this._timePicker.render(!1),this.timezone){const l=document.createElement("div");l.className="mojo-datetime-tz-row";const d=document.createElement("div");d.className="mojo-datetime-tz-label",d.textContent="Timezone",l.appendChild(d);const h=document.createElement("div");h.className="mojo-datetime-tz-host",l.appendChild(h),e.appendChild(l),this._tzSelect=new Tt({name:"timezone",value:this.currentTimezone,timezones:Array.isArray(this.timezoneList)?this.timezoneList:null}),this._tzSelect.render(!0,h),this._tzSelect.on("change",({value:u})=>{const m=this.currentTimezone;this.currentTimezone=u||null,m!==this.currentTimezone&&this._syncOutputs()})}const n=document.createElement("div");n.className="mojo-datetime-foot";const a=document.createElement("button");a.type="button",a.className="btn btn-link btn-sm",a.textContent="Now",a.addEventListener("click",l=>{l.preventDefault();const d=new Date;this.currentDate={y:d.getFullYear(),m:d.getMonth()+1,d:d.getDate()},this.currentTime={hours:d.getHours(),minutes:d.getMinutes()},this._calendar&&this._calendar.setValue(B(this.currentDate)),this._timePicker&&this._timePicker.setValue(J(this.currentTime,"24h")),this._syncOutputs()}),n.appendChild(a);const o=document.createElement("button");return o.type="button",o.className="btn btn-primary btn-sm",o.textContent="Done",o.addEventListener("click",l=>{l.preventDefault(),this._popover&&this._popover.isOpen()&&this._popover.close()}),n.appendChild(o),e.appendChild(n),e}_refreshTimezoneDefault(){this.timezone&&!this.currentTimezone&&this._timePicker&&(this.currentTimezone=this._timePicker.currentTimezone||Ft())}_timePickerValue(){if(!this.currentTime&&!this.currentTimezone)return"";const e=this.currentTime?J(this.currentTime,"24h"):"00:00";return this.timezone&&this.currentTimezone?`${e} ${this.currentTimezone}`:e}_dateBound(e){return e?String(e).trim().split(/[ T]/)[0]:null}_syncOutputs(e){const t=this._serialize(),s=this._displayText(),i=this.element&&this.element.querySelector("[data-trigger-text]");i&&(i.textContent=s||this.placeholder,i.classList.toggle("is-empty",!this.currentDate));const r=this.element&&this.element.querySelector("[data-hidden-value]");r&&(r.value=t),e!==void 0&&e!==t?(this.emit("change",{value:this.getValue(),formatted:s,oldValue:e}),this.emit("datetime:changed",{value:this.getValue()})):e===void 0&&this.emit("change",{value:this.getValue(),formatted:s,oldValue:null})}_serialize(){if(!this.currentDate)return"";const e=B(this.currentDate),t=this.currentTime?J(this.currentTime,"24h"):"00:00";if(this.outputFormat==="iana"){let i=`${e} ${t}`;return this.timezone&&this.currentTimezone&&(i+=` ${this.currentTimezone}`),i}let s=`${e}T${t}:00`;if(this.timezone&&this.currentTimezone){const i=new Date(this.currentDate.y,this.currentDate.m-1,this.currentDate.d,this.currentTime?.hours||0,this.currentTime?.minutes||0),r=yt(this.currentTimezone,i);r&&(s+=r)}return s}_displayText(){if(!this.currentDate)return"";const e=he(this.currentDate,this.displayFormat),t=this.currentTime?J(this.currentTime,this.timeFormat):this.timeFormat==="12h"?"12:00 AM":"00:00";let s=`${e} ${t}`;return this.timezone&&this.currentTimezone&&(s+=` ${this.currentTimezone}`),s}getValue(){if(!this.currentDate)return this.outputFormat==="object"?null:"";if(this.outputFormat==="object"){const e={date:B(this.currentDate),time:this.currentTime?J(this.currentTime,"24h"):"00:00"};return this.timezone&&(e.timezone=this.currentTimezone||null),e}return this._serialize()}setValue(e){const t=this._parseInitial(e);this.currentDate=t.date,this.currentTime=t.time,t.timezone&&(this.currentTimezone=t.timezone),this._calendar&&this.currentDate&&this._calendar.setValue(B(this.currentDate)),this._timePicker&&this._timePicker.setValue(this._timePickerValue()),this._syncOutputs()}getFormattedValue(){return this._displayText()}clear(){const e=this._serialize();this.currentDate=null,this.currentTime=null,this._calendar&&this._calendar.setValue(null),this._timePicker&&this._timePicker.clear(),this._syncOutputs(e)}setMin(e){this.min=e,this._calendar&&this._calendar.setMin(this._dateBound(e))}setMax(e){this.max=e,this._calendar&&this._calendar.setMax(this._dateBound(e))}setEnabled(e){this.disabled=!e;const t=this.element.querySelector("[data-trigger]");t&&(t.disabled=!e),!e&&this._popover&&this._popover.isOpen()&&this._popover.close()}setReadonly(e){this.readonly=e,e&&this._popover&&this._popover.isOpen()&&this._popover.close()}focus(){const e=this.element.querySelector("[data-trigger]");e&&e.focus()}show(){const e=this.element.querySelector("[data-trigger]");e&&this._togglePopover(e)}hide(){this._popover&&this._popover.close()}getFormValue(){return this.getValue()}async setFormValue(e){this.setValue(e)}hasError(){return!1}_inputId(){return this.name?`mojo-datetime-${this.name}-${this.id}`:`mojo-datetime-${this.id}`}_attr(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}async onBeforeDestroy(){if(this._popover){try{this._popover.destroy()}catch{}this._popover=null}if(this._timePicker){try{await this._timePicker.destroy()}catch{}this._timePicker=null}if(this._tzSelect){try{await this._tzSelect.destroy()}catch{}this._tzSelect=null}this._calendar=null,this._popoverContent=null,await super.onBeforeDestroy()}static create(e={}){return new Ge(e)}}function Ft(){try{return new Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}catch{return"UTC"}}class Je extends C{constructor(e={}){const{name:t,value:s="",placeholder:i="Select or type...",options:r=[],allowCustom:n=!0,showDescription:a=!0,minChars:o=0,maxSuggestions:l=10,disabled:d=!1,readonly:h=!1,required:u=!1,class:m="",inputClass:p="form-control",onSelect:f=null,onChange:g=null,...b}=e;super({tagName:"div",className:`combo-input ${m}`,...b}),this.name=t,this.placeholder=i,this.options=this.normalizeOptions(r),this.allowCustom=n,this.showDescription=a,this.minChars=o,this.maxSuggestions=l,this.disabled=d,this.readonly=h,this.required=u,this.inputClass=p,this.onSelectCallback=f,this.onChangeCallback=g,this.currentValue=s,this.inputValue=this.getDisplayValue(s),this.filteredOptions=[],this.highlightedIndex=-1,this.isOpen=!1,this.selectedOption=this.findOptionByValue(s)}normalizeOptions(e){return Array.isArray(e)?e.map(t=>typeof t=="string"?{value:t,label:t}:typeof t=="object"&&t.value!==void 0?{value:t.value,label:t.label||String(t.value),description:t.description||t.label||"",meta:t.meta||{}}:null).filter(t=>t!==null):[]}findOptionByValue(e){return this.options.find(t=>t.value===e)||null}getDisplayValue(e){const t=this.findOptionByValue(e);return t?t.label:e}async renderTemplate(){return`
1209
1209
  <div class="combo-input-container position-relative">
1210
1210
  <div class="input-wrapper position-relative">
1211
1211
  ${this.renderInput()}
@@ -1332,7 +1332,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1332
1332
  <span class="item-empty">No data</span>
1333
1333
  {{/model}}
1334
1334
  </div>
1335
- `)}async onActionSelect(e,t){e.stopPropagation(),this.selected?this.deselect():this.select()}async onActionView(e,t){e.stopPropagation(),this._emitRowEvent("row:view",e)}async onActionEdit(e,t){e.stopPropagation(),this._emitRowEvent("row:edit",e)}async onActionDelete(e,t){e.stopPropagation(),this._emitRowEvent("row:delete",e)}_emitRowEvent(e,t){const s={item:this,model:this.model,index:this.index,event:t,data:this.model?.toJSON?this.model.toJSON():this.model};this.emit(e,s),this.listView&&this.listView.emit(e,s)}select(){this.selected||(this.selected=!0,this.addClass("selected"),this.emit("item:select",{item:this,model:this.model,index:this.index,data:this.model?.toJSON?this.model.toJSON():this.model}),this.listView&&this.listView.emit("item:select",{item:this,model:this.model,index:this.index,data:this.model?.toJSON?this.model.toJSON():this.model}))}deselect(){this.selected&&(this.selected=!1,this.removeClass("selected"),this.emit("item:deselect",{item:this,model:this.model,index:this.index,data:this.model?.toJSON?this.model.toJSON():this.model}),this.listView&&this.listView.emit("item:deselect",{item:this,model:this.model,index:this.index,data:this.model?.toJSON?this.model.toJSON():this.model}))}async onAfterRender(){await super.onAfterRender(),this.clickable&&this.element&&(this.addClass("clickable"),this._wireClickableHandler()),this.listView?.rowStripe&&typeof this.listView._applyRowStripe=="function"&&this.listView._applyRowStripe(this)}_wireClickableHandler(){this._clickableHandler||!this.element||(this._clickableHandler=e=>{if(e.target?.closest?.("[data-action]"))return;const t=e.target?.tagName;t==="INPUT"||t==="TEXTAREA"||t==="SELECT"||(this.emit("item:click",{item:this,model:this.model,index:this.index,action:"row-click",event:e,data:this.model?.toJSON?this.model.toJSON():this.model}),this.listView&&this.listView.emit("item:click",{item:this,model:this.model,index:this.index,action:"row-click",event:e,data:this.model?.toJSON?this.model.toJSON():this.model}))},this.element.addEventListener("click",this._clickableHandler))}async onActionDefault(e,t,s){this.emit("item:click",{item:this,model:this.model,index:this.index,action:e,data:this.model?.toJSON?this.model.toJSON():this.model}),this.listView&&this.listView.emit("item:click",{item:this,model:this.model,index:this.index,action:e,data:this.model?.toJSON?this.model.toJSON():this.model})}setIndex(e){return this.index=e,this.element.setAttribute("data-index",e),this}setSelected(e){return e?this.select():this.deselect(),this}async destroy(){this._clickableHandler&&this.element&&(this.element.removeEventListener("click",this._clickableHandler),this._clickableHandler=null),this.listView=null,await super.destroy()}}class _s extends C{constructor(e={}){super({tagName:e.tagName||"div",className:e.className||"list-group-header",...e}),this.key=e.key??"",this.index=e.index??0,this.colspan=e.colspan??1,this.template||(this.template="{{key}}")}}class he extends C{static GROUP_HEADER_STYLES=["banner","mark","band","rule"];static ROW_STRIPE_TOKENS=["danger","warning","success","info","primary","secondary"];constructor(e={}){super({className:e.className||"list-view",...e}),this.collection=null,this.itemViews=new Map,this.selectedItems=new Set,this.itemTemplate=e.itemTemplate||null,this.itemClass=e.itemClass||Ae,this.selectionMode=e.selectionMode||"none",this.emptyMessage=e.emptyMessage||"No items to display",this.loading=!1,this.isEmpty=!0,this.searchable=e.searchable===!0,this.filterable=e.filterable===!0,this.paginated=e.paginated===!0;let t=e.paginationMode;t||(t=this.paginated?"more":"none"),this.paginationMode=t,this.searchPlacement=e.searchPlacement||"toolbar",this.searchPlaceholder=e.searchPlaceholder||"Search...",this.sortOptions=Array.isArray(e.sortOptions)?e.sortOptions:[],this.filters={},this.additionalFilters=e.filters||[],this.hideActivePills=e.hideActivePills===!0,this.hideActivePillNames=e.hideActivePillNames||[],this.title=e.title||null,this.eyebrow=e.eyebrow||null,this.showRefresh=e.showRefresh!==!1,this.toolbarButtons=e.toolbarButtons||[],this.toolbarRight=e.toolbarRight||null,this._toolbarRightMounted=!1,this.dayRangeFilter=this._normalizeDayRangeFilter(e.dayRangeFilter),this.dayRangeControl=null,this.exportOptions=e.exportOptions||null,this.exportSource=e.exportSource||"remote",this.persistSelection=e.persistSelection===void 0?this.paginationMode==="more":e.persistSelection===!0,this.onItemClick=typeof e.onItemClick=="function"?e.onItemClick:null,this.clickAction=e.clickAction||"none",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.fetchOnView=e.fetchOnView!==!1,this.clickable=e.clickable===!0||!!this.onItemClick||this.clickAction&&this.clickAction!=="none",this.rowStripe=typeof e.rowStripe=="function"?e.rowStripe:null,this.groupBy=typeof e.groupBy=="function"||typeof e.groupBy=="string"?e.groupBy:null,this.groupHeaderTemplate=e.groupHeaderTemplate||null,this.groupHeaderLabel=typeof e.groupHeaderLabel=="function"?e.groupHeaderLabel:null,this.groupHeaderClass=e.groupHeaderClass||_s,this.groupHeaderStyle=he.GROUP_HEADER_STYLES.includes(e.groupHeaderStyle)?e.groupHeaderStyle:"banner",this.groupHeaderViews=new Map,this._renderOrder=[],this.loadingMore=!1,this._isToolbarEnabled()||this.paginationMode!=="none"?this.template=this.buildListTemplate():this.template||(this.template=this._defaultBareTemplate())}async onInit(){this._initCollection(this.options.collection||this.options.Collection),this.dayRangeFilter&&(this._seedDayRangeParams(),this.dayRangeControl=new Cs({containerId:"toolbar-day-range",options:this.dayRangeFilter.options,value:this.dayRangeFilter.value,ariaLabel:this.dayRangeFilter.ariaLabel}),this.dayRangeControl.on("change",this._onDayRangeChange,this),this.addChild(this.dayRangeControl))}async onAfterMount(){await super.onAfterMount(),this.collection&&(this.options.fetchOnMount||!this.collection.lastFetchTime)&&this.collection.fetch()}async onBeforeRender(){this.searchValue=this.getActiveFilters().search||"",this.hasMore=this._computeHasMore()}async onAfterRender(){if(await super.onAfterRender(),this.toolbarRight&&!this._toolbarRightMounted&&(this.toolbarRight.containerId="toolbar-right",this.addChild(this.toolbarRight),await this.toolbarRight.render(),this._toolbarRightMounted=!0),this._toolbarRightMounted&&this.toolbarRight&&!this.element?.contains(this.toolbarRight.element)&&(this._toolbarRightMounted=!1),this.paginated&&this.paginationMode==="pages"&&this.collection){const e=this.collection.meta?.count||this.collection.length(),t=this.collection.params?.start||0,s=this.collection.params?.size||10,i=Math.min(t+s,e),r=this.element.querySelector('[data-value="start"]'),n=this.element.querySelector('[data-value="end"]'),a=this.element.querySelector('[data-value="total"]');r&&(r.textContent=e===0?0:t+1),n&&(n.textContent=i),a&&(a.textContent=e);const o=this.element.querySelector('[data-change-action="page-size"]');o&&(o.value=s),this.renderPagination()}this._isToolbarEnabled()&&(this.updateFilterPills(),this.setupSearchClearListener())}_defaultBareTemplate(){return`
1335
+ `)}async onActionSelect(e,t){e.stopPropagation(),this.selected?this.deselect():this.select()}async onActionView(e,t){e.stopPropagation(),this._emitRowEvent("row:view",e)}async onActionEdit(e,t){e.stopPropagation(),this._emitRowEvent("row:edit",e)}async onActionDelete(e,t){e.stopPropagation(),this._emitRowEvent("row:delete",e)}_emitRowEvent(e,t){const s={item:this,model:this.model,index:this.index,event:t,data:this.model?.toJSON?this.model.toJSON():this.model};this.emit(e,s),this.listView&&this.listView.emit(e,s)}select(){this.selected||(this.selected=!0,this.addClass("selected"),this.emit("item:select",{item:this,model:this.model,index:this.index,data:this.model?.toJSON?this.model.toJSON():this.model}),this.listView&&this.listView.emit("item:select",{item:this,model:this.model,index:this.index,data:this.model?.toJSON?this.model.toJSON():this.model}))}deselect(){this.selected&&(this.selected=!1,this.removeClass("selected"),this.emit("item:deselect",{item:this,model:this.model,index:this.index,data:this.model?.toJSON?this.model.toJSON():this.model}),this.listView&&this.listView.emit("item:deselect",{item:this,model:this.model,index:this.index,data:this.model?.toJSON?this.model.toJSON():this.model}))}async onAfterRender(){await super.onAfterRender(),this.clickable&&this.element&&(this.addClass("clickable"),this._wireClickableHandler()),this.listView?.rowStripe&&typeof this.listView._applyRowStripe=="function"&&this.listView._applyRowStripe(this)}_wireClickableHandler(){this._clickableHandler||!this.element||(this._clickableHandler=e=>{if(e.target?.closest?.("[data-action]"))return;const t=e.target?.tagName;t==="INPUT"||t==="TEXTAREA"||t==="SELECT"||(this.emit("item:click",{item:this,model:this.model,index:this.index,action:"row-click",event:e,data:this.model?.toJSON?this.model.toJSON():this.model}),this.listView&&this.listView.emit("item:click",{item:this,model:this.model,index:this.index,action:"row-click",event:e,data:this.model?.toJSON?this.model.toJSON():this.model}))},this.element.addEventListener("click",this._clickableHandler))}async onActionDefault(e,t,s){this.emit("item:click",{item:this,model:this.model,index:this.index,action:e,data:this.model?.toJSON?this.model.toJSON():this.model}),this.listView&&this.listView.emit("item:click",{item:this,model:this.model,index:this.index,action:e,data:this.model?.toJSON?this.model.toJSON():this.model})}setIndex(e){return this.index=e,this.element.setAttribute("data-index",e),this}setSelected(e){return e?this.select():this.deselect(),this}async destroy(){this._clickableHandler&&this.element&&(this.element.removeEventListener("click",this._clickableHandler),this._clickableHandler=null),this.listView=null,await super.destroy()}}class _s extends C{constructor(e={}){super({tagName:e.tagName||"div",className:e.className||"list-group-header",...e}),this.key=e.key??"",this.index=e.index??0,this.colspan=e.colspan??1,this.template||(this.template="{{key}}")}}class te extends C{static GROUP_HEADER_STYLES=["banner","mark","band","rule"];static ROW_STRIPE_TOKENS=["danger","warning","success","info","primary","secondary"];static _warnedMinifiedClasses=new WeakSet;constructor(e={}){super({className:e.className||"list-view",...e}),this.collection=null,this.itemViews=new Map,this.selectedItems=new Set,this.itemTemplate=e.itemTemplate||null,this.itemClass=e.itemClass||Ae,this.selectionMode=e.selectionMode||"none",this.emptyMessage=e.emptyMessage||"No items to display",this.loading=!1,this.isEmpty=!0,this.searchable=e.searchable===!0,this.filterable=e.filterable===!0,this.paginated=e.paginated===!0;let t=e.paginationMode;t||(t=this.paginated?"more":"none"),this.paginationMode=t,this.searchPlacement=e.searchPlacement||"toolbar",this.searchPlaceholder=e.searchPlaceholder||"Search...",this.sortOptions=Array.isArray(e.sortOptions)?e.sortOptions:[],this.filters={},this.additionalFilters=e.filters||[],this.hideActivePills=e.hideActivePills===!0,this.hideActivePillNames=e.hideActivePillNames||[],this.title=e.title||null,this.eyebrow=e.eyebrow||null,this.showRefresh=e.showRefresh!==!1,this.toolbarButtons=e.toolbarButtons||[],this.toolbarRight=e.toolbarRight||null,this._toolbarRightMounted=!1,this.dayRangeFilter=this._normalizeDayRangeFilter(e.dayRangeFilter),this.dayRangeControl=null,this.exportOptions=e.exportOptions||null,this.exportSource=e.exportSource||"remote",this.persistSelection=e.persistSelection===void 0?this.paginationMode==="more":e.persistSelection===!0,this.onItemClick=typeof e.onItemClick=="function"?e.onItemClick:null,this.clickAction=e.clickAction||"none",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.fetchOnView=e.fetchOnView!==!1,this.clickable=e.clickable===!0||!!this.onItemClick||this.clickAction&&this.clickAction!=="none",this.rowStripe=typeof e.rowStripe=="function"?e.rowStripe:null,this.groupBy=typeof e.groupBy=="function"||typeof e.groupBy=="string"?e.groupBy:null,this.groupHeaderTemplate=e.groupHeaderTemplate||null,this.groupHeaderLabel=typeof e.groupHeaderLabel=="function"?e.groupHeaderLabel:null,this.groupHeaderClass=e.groupHeaderClass||_s,this.groupHeaderStyle=te.GROUP_HEADER_STYLES.includes(e.groupHeaderStyle)?e.groupHeaderStyle:"banner",this.groupHeaderViews=new Map,this._renderOrder=[],this.loadingMore=!1,this._isToolbarEnabled()||this.paginationMode!=="none"?this.template=this.buildListTemplate():this.template||(this.template=this._defaultBareTemplate())}async onInit(){this._initCollection(this.options.collection||this.options.Collection),this.dayRangeFilter&&(this._seedDayRangeParams(),this.dayRangeControl=new Cs({containerId:"toolbar-day-range",options:this.dayRangeFilter.options,value:this.dayRangeFilter.value,ariaLabel:this.dayRangeFilter.ariaLabel}),this.dayRangeControl.on("change",this._onDayRangeChange,this),this.addChild(this.dayRangeControl))}async onAfterMount(){await super.onAfterMount(),this.collection&&(this.options.fetchOnMount||!this.collection.lastFetchTime)&&this.collection.fetch()}async onBeforeRender(){this.searchValue=this.getActiveFilters().search||"",this.hasMore=this._computeHasMore()}async onAfterRender(){if(await super.onAfterRender(),this.toolbarRight&&!this._toolbarRightMounted&&(this.toolbarRight.containerId="toolbar-right",this.addChild(this.toolbarRight),await this.toolbarRight.render(),this._toolbarRightMounted=!0),this._toolbarRightMounted&&this.toolbarRight&&!this.element?.contains(this.toolbarRight.element)&&(this._toolbarRightMounted=!1),this.paginated&&this.paginationMode==="pages"&&this.collection){const e=this.collection.meta?.count||this.collection.length(),t=this.collection.params?.start||0,s=this.collection.params?.size||10,i=Math.min(t+s,e),r=this.element.querySelector('[data-value="start"]'),n=this.element.querySelector('[data-value="end"]'),a=this.element.querySelector('[data-value="total"]');r&&(r.textContent=e===0?0:t+1),n&&(n.textContent=i),a&&(a.textContent=e);const o=this.element.querySelector('[data-change-action="page-size"]');o&&(o.value=s),this.renderPagination()}this._isToolbarEnabled()&&(this.updateFilterPills(),this.setupSearchClearListener())}_defaultBareTemplate(){return`
1336
1336
  <div class="list-view-container">
1337
1337
  {{#loading}}
1338
1338
  <div class="list-loading">
@@ -1581,7 +1581,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1581
1581
  </button>
1582
1582
  </div>
1583
1583
  {{/hasMore}}
1584
- `}_initCollection(e){if(!e){console.log("Collection not provided");return}if(e instanceof le)this.setCollection(e);else if(typeof e=="function"){const t=new e;this.setCollection(t)}else if(Array.isArray(e)){const t=new le(e);this.setCollection(t)}}_normalizeDayRangeFilter(e){if(!e)return null;const t={field:"created",value:"7d",options:[{value:"1d",label:"1d"},{value:"7d",label:"7d"},{value:"30d",label:"30d"},{value:"90d",label:"90d"}],ariaLabel:"Time range"};return e===!0?t:{...t,...e}}_dayRangeDays(e){const t=/^(\d+)d$/.exec(String(e||""));return t?parseInt(t[1],10):null}_seedDayRangeParams(){if(!this.dayRangeFilter||!this.collection)return;const e=this._dayRangeDays(this.dayRangeFilter.value);if(e==null)return;const t=Math.floor(Date.now()/1e3)-e*86400;this.collection.params[`${this.dayRangeFilter.field}__gte`]=t}async _onDayRangeChange({value:e,previous:t}){const s=this.dayRangeFilter?.field||"created",i=this._dayRangeDays(e);let r={};if(i!=null&&this.collection){const n=Math.floor(Date.now()/1e3)-i*86400;this.collection.params[`${s}__gte`]=n,this.collection.params.start=0,r={[`${s}__gte`]:n}}if(this.emit("range:change",{field:s,value:e,previous:t,params:r}),this.emit("params-changed"),this.collection?.restEnabled)try{await this.collection.fetch()}catch(n){console.error("Failed to fetch day-range data:",n),await this.render()}else await this.render()}getRange(){return this.dayRangeControl?.getValue()??null}setRange(e,{silent:t=!1}={}){if(!this.dayRangeControl)return!1;const s=this.dayRangeControl.getValue();return this.dayRangeControl.setValue(e,{silent:!0})?(t||this._onDayRangeChange({value:e,previous:s}),!0):!1}setCollection(e){return this.collection===e?this:(this.collection&&(this.collection.off("add",this._onModelsAdded,this),this.collection.off("remove",this._onModelsRemoved,this),this.collection.off("reset",this._onCollectionReset,this),this.collection.off("fetch:start",this._onFetchStart,this),this.collection.off("fetch:end",this._onFetchEnd,this)),this.collection=e,this.options.defaultQuery&&!this.options.collectionParams&&(this.collection.params={...this.collection.params,...this.options.defaultQuery}),this.options.collectionParams&&(this.collection.params={...this.collection.params,...this.options.collectionParams}),this.options.pageSize&&this.collection&&(this.collection.params={...this.collection.params,size:this.options.pageSize}),this.collection&&(this.collection.on("add",this._onModelsAdded,this),this.collection.on("remove",this._onModelsRemoved,this),this.collection.on("reset",this._onCollectionReset,this),this.collection.on("fetch:start",this._onFetchStart,this),this.collection.on("fetch:end",this._onFetchEnd,this),this.collection.restEnabled&&!this.collection.lastFetchTime&&!this.collection.options?.preloaded?this.loading=!0:this._buildItems()),this)}async _renderChildren(){await super._renderChildren();const e=this.getChildElement("items");if(!e)return;const t=[];if(this._renderOrder.length>0)for(const s of this._renderOrder)e.appendChild(s.view.element),t.push(Promise.resolve(s.view.render(!1)).catch(()=>{}));else this.forEachItem(s=>{e.appendChild(s.element),t.push(Promise.resolve(s.render(!1)).catch(()=>{}))});await Promise.all(t)}_buildItems(){if(this._clearItems(),!this.collection||this.collection.isEmpty()){this.isEmpty=!0,this.emit("list:empty");return}this.isEmpty=!1,this.collection.forEach((e,t)=>{this._createItemView(e,t)}),this._applyPersistedSelections(),this._buildGroupHeaders(),this.emit("list:loaded",{count:this.collection.length()}),this.isMounted()&&this.render()}_buildGroupHeaders(){if(this.groupHeaderViews.forEach(i=>this.removeChild(i.id)),this.groupHeaderViews.clear(),this._renderOrder.length=0,!this.groupBy||!this.collection||this.collection.isEmpty())return;const e=typeof this.groupBy=="function"?this.groupBy:i=>i.get(this.groupBy);let t,s=!1;this.collection.forEach((i,r)=>{const n=this.itemViews.get(i.id);if(!n)return;let a;try{a=e(i)}catch(o){console.warn("ListView: groupBy resolver threw — treating as ungrouped tail",o),a=null}if(a&&(!s||a!==t)){const o=this._createGroupHeaderView(i,a,r);this._renderOrder.push({type:"header",view:o}),t=a,s=!0}this._renderOrder.push({type:"item",view:n})})}_rebuildGroupHeaders(){this._buildGroupHeaders()}_createGroupHeaderView(e,t,s){const i=this.groupHeaderLabel?this.groupHeaderLabel(t):t,r=new this.groupHeaderClass({template:this.groupHeaderTemplate||this._defaultGroupHeaderTemplate(),model:e,key:i,index:s,...this._groupHeaderViewOptions(e,t,s)});return this.groupHeaderViews.set(r.id,r),r}_groupHeaderViewOptions(e,t,s){return{className:`list-group-header list-group-header--${this.groupHeaderStyle}`}}_defaultGroupHeaderTemplate(){return"{{key}}"}_createItemView(e,t){if(this.itemViews.has(e.id))return this.itemViews.get(e.id);const s=new this.itemClass({model:e,index:t,listView:this,template:this.itemTemplate,clickable:this.clickable});return this.itemViews.set(e.id,s),this._wireItemViewListeners(s),s}_wireItemViewListeners(e){e.on("item:select",this._onItemSelect.bind(this)),e.on("item:deselect",this._onItemDeselect.bind(this)),e.on("item:click",t=>{t.action==="row-click"&&(this.emit("row:click",t),this._dispatchRowClick(t))}),e.on("row:click",t=>{this._dispatchRowClick(t)}),e.on("row:view",this._onRowView.bind(this)),e.on("row:edit",this._onRowEdit.bind(this)),e.on("row:delete",this._onRowDelete.bind(this))}_dispatchRowClick(e){if(typeof this.options.onRowClick=="function")return this.options.onRowClick(e.model,e.event);if(typeof this.clickAction=="function")return this.clickAction(e.model,e.event);if(this.onItemClick)return this.onItemClick(e.model,e.event);if(this.clickAction==="view")return this._onRowView(e);if(this.clickAction==="edit")return this._onRowEdit(e);this.clickAction==="select"&&(this.selectedItems.has(e.model.id)?this.deselectItem(e.model.id):this.selectItem(e.model.id))}_applyPersistedSelections(){!this.persistSelection||this.selectedItems.size===0||this.itemViews.forEach((e,t)=>{this.selectedItems.has(t)&&!e.selected&&(e.selected=!0,e.element&&e.addClass("selected"))})}_clearItems(){this.forEachItem(e=>{this.removeChild(e.id)}),this.itemViews.clear(),this.groupHeaderViews.forEach(e=>this.removeChild(e.id)),this.groupHeaderViews.clear(),this._renderOrder.length=0,this.persistSelection||this.selectedItems.clear()}_onModelsAdded(e){const{models:t}=e;t.forEach(s=>{const i=this.collection.models.indexOf(s);this._createItemView(s,i)}),this._applyPersistedSelections(),this.groupBy&&this._rebuildGroupHeaders(),this.isEmpty=this.collection.isEmpty(),!this.loading&&this.isMounted()&&this.render()}_onModelsRemoved(e){const{models:t}=e;t.forEach(s=>{const i=this.itemViews.get(s.id);i&&(this.removeChild(i.id),this.itemViews.delete(s.id),this.selectedItems.delete(s.id))}),this.isEmpty=this.collection.isEmpty(),!this.loading&&this.isMounted()&&this.render(),this.isEmpty&&this.emit("list:empty")}_onCollectionReset(e){this._buildItems()}_onFetchStart(){this.loading=!0,!this.loadingMore&&this.isMounted()&&this.render()}_onFetchEnd(){this.loading=!1,!this.loadingMore&&this.isMounted()&&this.render()}_onItemSelect(e){const{model:t,item:s}=e;if(this.selectionMode==="none"){s.deselect();return}this.selectionMode==="single"&&(this.itemViews.forEach((i,r)=>{r!==t.id&&i.selected&&i.deselect()}),this.selectedItems.clear()),this.selectedItems.add(t.id),this.emit("selection:change",{selected:Array.from(this.selectedItems),item:s,model:t})}_onItemDeselect(e){const{model:t}=e;this.selectedItems.delete(t.id),this.emit("selection:change",{selected:Array.from(this.selectedItems),item:e.item,model:t})}getSelectedItems(){const e=[];return this.selectedItems.forEach(t=>{const s=this.itemViews.get(t);s&&e.push({view:s,model:s.model,data:s.model?.toJSON?s.model.toJSON():s.model})}),e}forEachItem(e,t){if(typeof e!="function")throw new TypeError("Callback must be a function");let s=0;return this.itemViews.forEach(i=>{e.call(t,i,i.model,s++)}),this}clearSelection(){this.forEachItem(e=>{e.selected&&e.deselect()}),this.selectedItems.clear(),this.emit("selection:change",{selected:[]})}selectItem(e){const t=this.itemViews.get(e);return t&&t.select(),this}deselectItem(e){const t=this.itemViews.get(e);return t&&t.deselect(),this}setItemTemplate(e,t=!1){return this.itemTemplate=e,t&&this.itemViews.size>0&&this.forEachItem(s=>{s.setTemplate(e),s.isMounted()&&s.render()}),this}async refresh(){if(this.collection&&this.collection.restEnabled)return await this.collection.fetch();this._buildItems()}_stripeClassFor(e){if(!this.rowStripe||!e)return null;let t;try{t=this.rowStripe(e)}catch(s){return console.warn("ListView: rowStripe callback threw — treating as no stripe",s),null}return t==null||t===""||typeof t!="string"?null:he.ROW_STRIPE_TOKENS.includes(t)?`list-row-stripe-${t}`:t}_applyRowStripe(e){if(!e||!e.element)return;const t=e.element.classList;for(const i of Array.from(t))i.startsWith("list-row-stripe")&&t.remove(i);const s=this._stripeClassFor(e.model);if(s)try{t.add(s)}catch(i){console.warn("ListView: rowStripe returned an invalid class name, skipping",s,i)}}refreshStripes(){return this.rowStripe?(this.forEachItem(e=>this._applyRowStripe(e)),this):this}async _onRowView(e){if(this.emit("row:view",e),this.options.onItemView){await this.options.onItemView(e.model,e.event);return}if(this.fetchOnView)try{w.loading(),await e.model.fetch()}catch(s){w.hideLoading(!0),w.showError(s?.data?.error||s?.message||"Failed to load item details");return}finally{w.hideLoading(!0)}const t=this.getItemViewClass(e.model);if(t){const s=new t({model:e.model,collection:this.collection});await w.dialog({header:!1,body:s,size:"lg",centered:!1,...this.getFormDialogConfig(this.getModelClass(e.model)),...t.DIALOG_OPTIONS,...this.viewDialogOptions})}else await w.data({title:`View ${this.getModelName(e.model)} #${e.model.id}`,model:e.model})}async _onRowEdit(e){if(this.emit("row:edit",e),this.options.onItemEdit){await this.options.onItemEdit(e.model,e.event);return}const t=this.getModelClass(e.model);let s=this.getEditFormConfig(t);if(s){s.fields||(s={title:`Edit ${this.getModelName(e.model)}`,fields:s});const i=await w.modelForm({model:e.model,...s,...this.getFormDialogConfig(t)});if(!i)return;if(!i.success||!i?.result?.data.status){w.showError(i?.result?.data?.error||i?.result?.message||"An error occurred");return}}else{const i=await w.dialog({title:`Edit ${this.getModelName(e.model)} #${e.model.id}`,body:new ee({model:e.model,fields:this.options.formFields||[]})});if(i){const r=await e.model.save(i);if(!r.data?.status){w.showError(r.data.error||"An error occurred");return}await this.refresh()}}}async _onRowDelete(e){if(this.emit("row:delete",e),this.options.onItemDelete){await this.options.onItemDelete(e.model,e.event);return}const t=this.getModelClass(e.model),s=this.deleteTemplate||t?.DELETE_TEMPLATE||'Are you sure you want to delete this {{name||"item"}}?',i=this.renderTemplateString(s,e.model);await w.confirm({message:i||"Are you sure you want to delete this item?",title:"Confirm Delete",confirmText:"Delete",confirmClass:"btn-danger"})&&(await e.model.destroy(),this.collection?.restEnabled?this.collection.fetch():this._buildItems())}async onActionAdd(e,t){if(this.options.onAdd){this.emit("list:add",{event:e}),await this.options.onAdd(e);return}this.emit("list:add",{event:e});const s=this.getModelClass();if(!s){console.warn("Cannot determine Model class for add operation");return}let i=this.getAddFormConfig(s);if(i){const r=new s;i.fields||(i={title:`Add ${this.getModelName()}`,fields:i});const n=await w.form({model:r,...i,...this.getFormDialogConfig(s)});if(n){this.options.addRequiresActiveGroup&&(n.group=this.getApp().activeGroup.id),this.options.addRequiresActiveUser&&(n.user=this.getApp().activeUser.id),this.options.addFormDefaults&&Object.assign(n,this.options.addFormDefaults);const a=await r.save(n);if(!a?.data.status){w.showError(a?.data.error||"An error occurred");return}this.collection&&this.collection.add(r),await this.refresh()}}else{const r=new s,n=await w.dialog({title:`Add ${this.getModelName()}`,body:new ee({model:r,fields:this.options.formFields||[]})});if(n){const a=await r.save(n);if(!a?.data.status){w.showError(a.data.error||"An error occurred");return}this.collection&&this.collection.add(r),await this.refresh()}}}async onActionExport(e,t){const s=t.getAttribute("data-format")||"json";this.emit("list:export",{format:s,source:this.exportSource,event:e}),this.exportSource==="remote"?this.collection?await this.collection.download(s):console.warn("ListView: Cannot export from remote without a collection."):this.options.onExport?await this.options.onExport(this.collection?.toJSON()||[],s):console.warn("ListView: onExport handler not implemented for local export.")}getModelClass(e){return this.collection?.ModelClass?this.collection.ModelClass:this.collection?.model?this.collection.model:e?.constructor?e.constructor:null}getModelName(e){const t=this.getModelClass(e);return t&&(t.MODEL_NAME||t.name.replace(/Model$/,""))||"Item"}getItemViewClass(e){if(this.itemView)return this.itemView;const t=this.getModelClass(e);return t?.VIEW_CLASS?t.VIEW_CLASS:null}getAddFormConfig(e){return this.addForm||e?.ADD_FORM||this.editForm||e?.EDIT_FORM}getEditFormConfig(e){return this.editForm||e?.EDIT_FORM||this.addForm||e?.ADD_FORM}getFormDialogConfig(e){return{...e?.FORM_DIALOG_CONFIG,...this.formDialogConfig}}renderTemplateString(e,t){return e?D.render(e,t):""}async onActionRefresh(e,t){await this.refresh()}async onActionApplySearch(e,t){const s=t.value.trim();this.collection&&(this.setFilter("search",s),this.collection.params.start=0,this.collection.restEnabled?await this.collection.fetch():await this.render()),this.updateFilterPills(),this.emit("list:search",{searchTerm:s}),this.emit("params-changed")}async onActionClearSearch(e,t){this.setFilter("search",null),this.collection&&(this.collection.params.start=0,this.collection.restEnabled&&await this.collection.fetch()),await this.render(),this.updateFilterPills(),this.emit("list:search",{searchTerm:""}),this.emit("params-changed")}setupSearchClearListener(){if(!this.element)return;this.element.querySelectorAll('input[type="search"][data-filter="search"]').forEach(t=>{t.addEventListener("input",s=>{s.target.value===""&&this.getActiveFilters().search&&this.onActionClearSearch(s,s.target)})})}updateFilterPills(){const e=this.element?.querySelector('[data-container="filter-pills"]');e&&(e.innerHTML=this.buildActivePills())}updateSearchInputs(e){const t=this.element?.querySelectorAll('[data-filter="search"]');t&&t.forEach(s=>{s.value=e||""})}renderPagination(){const e=this.element.querySelector('[data-container="pagination"]');if(!e||!this.collection)return;const t=this.collection.meta?.count||this.collection.length(),s=this.collection.params?.size||10,i=this.collection.params?.start||0,r=Math.floor(i/s)+1,n=Math.ceil(t/s);if(n<=1){e.innerHTML="";return}const a=r>1?r-1:n,o=r<n?r+1:1,l=[];l.push(`
1584
+ `}_initCollection(e){if(!e){console.log("Collection not provided");return}if(e instanceof ce)this.setCollection(e);else if(typeof e=="function"){const t=new e;this.setCollection(t)}else if(Array.isArray(e)){const t=new ce(e);this.setCollection(t)}}_normalizeDayRangeFilter(e){if(!e)return null;const t={field:"created",value:"7d",options:[{value:"1d",label:"1d"},{value:"7d",label:"7d"},{value:"30d",label:"30d"},{value:"90d",label:"90d"}],ariaLabel:"Time range"};return e===!0?t:{...t,...e}}_dayRangeDays(e){const t=/^(\d+)d$/.exec(String(e||""));return t?parseInt(t[1],10):null}_seedDayRangeParams(){if(!this.dayRangeFilter||!this.collection)return;const e=this._dayRangeDays(this.dayRangeFilter.value);if(e==null)return;const t=Math.floor(Date.now()/1e3)-e*86400;this.collection.params[`${this.dayRangeFilter.field}__gte`]=t}async _onDayRangeChange({value:e,previous:t}){const s=this.dayRangeFilter?.field||"created",i=this._dayRangeDays(e);let r={};if(i!=null&&this.collection){const n=Math.floor(Date.now()/1e3)-i*86400;this.collection.params[`${s}__gte`]=n,this.collection.params.start=0,r={[`${s}__gte`]:n}}if(this.emit("range:change",{field:s,value:e,previous:t,params:r}),this.emit("params-changed"),this.collection?.restEnabled)try{await this.collection.fetch()}catch(n){console.error("Failed to fetch day-range data:",n),await this.render()}else await this.render()}getRange(){return this.dayRangeControl?.getValue()??null}setRange(e,{silent:t=!1}={}){if(!this.dayRangeControl)return!1;const s=this.dayRangeControl.getValue();return this.dayRangeControl.setValue(e,{silent:!0})?(t||this._onDayRangeChange({value:e,previous:s}),!0):!1}setCollection(e){return this.collection===e?this:(this.collection&&(this.collection.off("add",this._onModelsAdded,this),this.collection.off("remove",this._onModelsRemoved,this),this.collection.off("reset",this._onCollectionReset,this),this.collection.off("fetch:start",this._onFetchStart,this),this.collection.off("fetch:end",this._onFetchEnd,this)),this.collection=e,this.options.defaultQuery&&!this.options.collectionParams&&(this.collection.params={...this.collection.params,...this.options.defaultQuery}),this.options.collectionParams&&(this.collection.params={...this.collection.params,...this.options.collectionParams}),this.options.pageSize&&this.collection&&(this.collection.params={...this.collection.params,size:this.options.pageSize}),this.collection&&(this.collection.on("add",this._onModelsAdded,this),this.collection.on("remove",this._onModelsRemoved,this),this.collection.on("reset",this._onCollectionReset,this),this.collection.on("fetch:start",this._onFetchStart,this),this.collection.on("fetch:end",this._onFetchEnd,this),this.collection.restEnabled&&!this.collection.lastFetchTime&&!this.collection.options?.preloaded?this.loading=!0:this._buildItems()),this)}async _renderChildren(){await super._renderChildren();const e=this.getChildElement("items");if(!e)return;const t=[];if(this._renderOrder.length>0)for(const s of this._renderOrder)e.appendChild(s.view.element),t.push(Promise.resolve(s.view.render(!1)).catch(()=>{}));else this.forEachItem(s=>{e.appendChild(s.element),t.push(Promise.resolve(s.render(!1)).catch(()=>{}))});await Promise.all(t)}_buildItems(){if(this._clearItems(),!this.collection||this.collection.isEmpty()){this.isEmpty=!0,this.emit("list:empty");return}this.isEmpty=!1,this.collection.forEach((e,t)=>{this._createItemView(e,t)}),this._applyPersistedSelections(),this._buildGroupHeaders(),this.emit("list:loaded",{count:this.collection.length()}),this.isMounted()&&this.render()}_buildGroupHeaders(){if(this.groupHeaderViews.forEach(i=>this.removeChild(i.id)),this.groupHeaderViews.clear(),this._renderOrder.length=0,!this.groupBy||!this.collection||this.collection.isEmpty())return;const e=typeof this.groupBy=="function"?this.groupBy:i=>i.get(this.groupBy);let t,s=!1;this.collection.forEach((i,r)=>{const n=this.itemViews.get(i.id);if(!n)return;let a;try{a=e(i)}catch(o){console.warn("ListView: groupBy resolver threw — treating as ungrouped tail",o),a=null}if(a&&(!s||a!==t)){const o=this._createGroupHeaderView(i,a,r);this._renderOrder.push({type:"header",view:o}),t=a,s=!0}this._renderOrder.push({type:"item",view:n})})}_rebuildGroupHeaders(){this._buildGroupHeaders()}_createGroupHeaderView(e,t,s){const i=this.groupHeaderLabel?this.groupHeaderLabel(t):t,r=new this.groupHeaderClass({template:this.groupHeaderTemplate||this._defaultGroupHeaderTemplate(),model:e,key:i,index:s,...this._groupHeaderViewOptions(e,t,s)});return this.groupHeaderViews.set(r.id,r),r}_groupHeaderViewOptions(e,t,s){return{className:`list-group-header list-group-header--${this.groupHeaderStyle}`}}_defaultGroupHeaderTemplate(){return"{{key}}"}_createItemView(e,t){if(this.itemViews.has(e.id))return this.itemViews.get(e.id);const s=new this.itemClass({model:e,index:t,listView:this,template:this.itemTemplate,clickable:this.clickable});return this.itemViews.set(e.id,s),this._wireItemViewListeners(s),s}_wireItemViewListeners(e){e.on("item:select",this._onItemSelect.bind(this)),e.on("item:deselect",this._onItemDeselect.bind(this)),e.on("item:click",t=>{t.action==="row-click"&&(this.emit("row:click",t),this._dispatchRowClick(t))}),e.on("row:click",t=>{this._dispatchRowClick(t)}),e.on("row:view",this._onRowView.bind(this)),e.on("row:edit",this._onRowEdit.bind(this)),e.on("row:delete",this._onRowDelete.bind(this))}_dispatchRowClick(e){if(typeof this.options.onRowClick=="function")return this.options.onRowClick(e.model,e.event);if(typeof this.clickAction=="function")return this.clickAction(e.model,e.event);if(this.onItemClick)return this.onItemClick(e.model,e.event);if(this.clickAction==="view")return this._onRowView(e);if(this.clickAction==="edit")return this._onRowEdit(e);this.clickAction==="select"&&(this.selectedItems.has(e.model.id)?this.deselectItem(e.model.id):this.selectItem(e.model.id))}_applyPersistedSelections(){!this.persistSelection||this.selectedItems.size===0||this.itemViews.forEach((e,t)=>{this.selectedItems.has(t)&&!e.selected&&(e.selected=!0,e.element&&e.addClass("selected"))})}_clearItems(){this.forEachItem(e=>{this.removeChild(e.id)}),this.itemViews.clear(),this.groupHeaderViews.forEach(e=>this.removeChild(e.id)),this.groupHeaderViews.clear(),this._renderOrder.length=0,this.persistSelection||this.selectedItems.clear()}_onModelsAdded(e){const{models:t}=e;t.forEach(s=>{const i=this.collection.models.indexOf(s);this._createItemView(s,i)}),this._applyPersistedSelections(),this.groupBy&&this._rebuildGroupHeaders(),this.isEmpty=this.collection.isEmpty(),!this.loading&&this.isMounted()&&this.render()}_onModelsRemoved(e){const{models:t}=e;t.forEach(s=>{const i=this.itemViews.get(s.id);i&&(this.removeChild(i.id),this.itemViews.delete(s.id),this.selectedItems.delete(s.id))}),this.isEmpty=this.collection.isEmpty(),!this.loading&&this.isMounted()&&this.render(),this.isEmpty&&this.emit("list:empty")}_onCollectionReset(e){this._buildItems()}_onFetchStart(){this.loading=!0,!this.loadingMore&&this.isMounted()&&this.render()}_onFetchEnd(){this.loading=!1,!this.loadingMore&&this.isMounted()&&this.render()}_onItemSelect(e){const{model:t,item:s}=e;if(this.selectionMode==="none"){s.deselect();return}this.selectionMode==="single"&&(this.itemViews.forEach((i,r)=>{r!==t.id&&i.selected&&i.deselect()}),this.selectedItems.clear()),this.selectedItems.add(t.id),this.emit("selection:change",{selected:Array.from(this.selectedItems),item:s,model:t})}_onItemDeselect(e){const{model:t}=e;this.selectedItems.delete(t.id),this.emit("selection:change",{selected:Array.from(this.selectedItems),item:e.item,model:t})}getSelectedItems(){const e=[];return this.selectedItems.forEach(t=>{const s=this.itemViews.get(t);s&&e.push({view:s,model:s.model,data:s.model?.toJSON?s.model.toJSON():s.model})}),e}forEachItem(e,t){if(typeof e!="function")throw new TypeError("Callback must be a function");let s=0;return this.itemViews.forEach(i=>{e.call(t,i,i.model,s++)}),this}clearSelection(){this.forEachItem(e=>{e.selected&&e.deselect()}),this.selectedItems.clear(),this.emit("selection:change",{selected:[]})}selectItem(e){const t=this.itemViews.get(e);return t&&t.select(),this}deselectItem(e){const t=this.itemViews.get(e);return t&&t.deselect(),this}setItemTemplate(e,t=!1){return this.itemTemplate=e,t&&this.itemViews.size>0&&this.forEachItem(s=>{s.setTemplate(e),s.isMounted()&&s.render()}),this}async refresh(){if(this.collection&&this.collection.restEnabled)return await this.collection.fetch();this._buildItems()}_stripeClassFor(e){if(!this.rowStripe||!e)return null;let t;try{t=this.rowStripe(e)}catch(s){return console.warn("ListView: rowStripe callback threw — treating as no stripe",s),null}return t==null||t===""||typeof t!="string"?null:te.ROW_STRIPE_TOKENS.includes(t)?`list-row-stripe-${t}`:t}_applyRowStripe(e){if(!e||!e.element)return;const t=e.element.classList;for(const i of Array.from(t))i.startsWith("list-row-stripe")&&t.remove(i);const s=this._stripeClassFor(e.model);if(s)try{t.add(s)}catch(i){console.warn("ListView: rowStripe returned an invalid class name, skipping",s,i)}}refreshStripes(){return this.rowStripe?(this.forEachItem(e=>this._applyRowStripe(e)),this):this}async _onRowView(e){if(this.emit("row:view",e),this.options.onItemView){await this.options.onItemView(e.model,e.event);return}if(this.fetchOnView)try{w.loading(),await e.model.fetch()}catch(s){w.hideLoading(!0),w.showError(s?.data?.error||s?.message||"Failed to load item details");return}finally{w.hideLoading(!0)}const t=this.getItemViewClass(e.model);if(t){const s=new t({model:e.model,collection:this.collection});await w.dialog({header:!1,body:s,size:"lg",centered:!1,...this.getFormDialogConfig(this.getModelClass(e.model)),...t.DIALOG_OPTIONS,...this.viewDialogOptions})}else await w.data({title:`View ${this.getModelName(e.model)} #${e.model.id}`,model:e.model})}async _onRowEdit(e){if(this.emit("row:edit",e),this.options.onItemEdit){await this.options.onItemEdit(e.model,e.event);return}const t=this.getModelClass(e.model);let s=this.getEditFormConfig(t);if(s){s.fields||(s={title:`Edit ${this.getModelName(e.model)}`,fields:s});const i=await w.modelForm({model:e.model,...s,...this.getFormDialogConfig(t)});if(!i)return;if(!i.success||!i?.result?.data.status){w.showError(i?.result?.data?.error||i?.result?.message||"An error occurred");return}}else{const i=await w.dialog({title:`Edit ${this.getModelName(e.model)} #${e.model.id}`,body:new ee({model:e.model,fields:this.options.formFields||[]})});if(i){const r=await e.model.save(i);if(!r.data?.status){w.showError(r.data.error||"An error occurred");return}await this.refresh()}}}async _onRowDelete(e){if(this.emit("row:delete",e),this.options.onItemDelete){await this.options.onItemDelete(e.model,e.event);return}const t=this.getModelClass(e.model),s=this.deleteTemplate||t?.DELETE_TEMPLATE||'Are you sure you want to delete this {{name||"item"}}?',i=this.renderTemplateString(s,e.model);await w.confirm({message:i||"Are you sure you want to delete this item?",title:"Confirm Delete",confirmText:"Delete",confirmClass:"btn-danger"})&&(await e.model.destroy(),this.collection?.restEnabled?this.collection.fetch():this._buildItems())}async onActionAdd(e,t){if(this.options.onAdd){this.emit("list:add",{event:e}),await this.options.onAdd(e);return}this.emit("list:add",{event:e});const s=this.getModelClass();if(!s){console.warn("Cannot determine Model class for add operation");return}let i=this.getAddFormConfig(s);if(i){const r=new s;i.fields||(i={title:`Add ${this.getModelName()}`,fields:i});const n=await w.form({model:r,...i,...this.getFormDialogConfig(s)});if(n){this.options.addRequiresActiveGroup&&(n.group=this.getApp().activeGroup.id),this.options.addRequiresActiveUser&&(n.user=this.getApp().activeUser.id),this.options.addFormDefaults&&Object.assign(n,this.options.addFormDefaults);const a=await r.save(n);if(!a?.data.status){w.showError(a?.data.error||"An error occurred");return}this.collection&&this.collection.add(r),await this.refresh()}}else{const r=new s,n=await w.dialog({title:`Add ${this.getModelName()}`,body:new ee({model:r,fields:this.options.formFields||[]})});if(n){const a=await r.save(n);if(!a?.data.status){w.showError(a.data.error||"An error occurred");return}this.collection&&this.collection.add(r),await this.refresh()}}}async onActionExport(e,t){const s=t.getAttribute("data-format")||"json";this.emit("list:export",{format:s,source:this.exportSource,event:e}),this.exportSource==="remote"?this.collection?await this.collection.download(s):console.warn("ListView: Cannot export from remote without a collection."):this.options.onExport?await this.options.onExport(this.collection?.toJSON()||[],s):console.warn("ListView: onExport handler not implemented for local export.")}getModelClass(e){return this.collection?.ModelClass?this.collection.ModelClass:this.collection?.model?this.collection.model:e?.constructor?e.constructor:null}getModelName(e){const t=this.getModelClass(e);if(!t)return"Item";if(t.MODEL_NAME)return t.MODEL_NAME;const s=(t.name||"").replace(/Model$/,"");return/^[A-Z][A-Za-z0-9]{2,}$/.test(s)?s:(te._warnedMinifiedClasses.has(t)||(te._warnedMinifiedClasses.add(t),console.warn(`ListView.getModelName: class name '${s}' looks minified — set a static MODEL_NAME on the model class for user-facing dialog titles. Falling back to 'Item'.`)),"Item")}getItemViewClass(e){if(this.itemView)return this.itemView;const t=this.getModelClass(e);return t?.VIEW_CLASS?t.VIEW_CLASS:null}getAddFormConfig(e){return this.addForm||e?.ADD_FORM||this.editForm||e?.EDIT_FORM}getEditFormConfig(e){return this.editForm||e?.EDIT_FORM||this.addForm||e?.ADD_FORM}getFormDialogConfig(e){return{...e?.FORM_DIALOG_CONFIG,...this.formDialogConfig}}renderTemplateString(e,t){return e?D.render(e,t):""}async onActionRefresh(e,t){await this.refresh()}async onActionApplySearch(e,t){const s=t.value.trim();this.collection&&(this.setFilter("search",s),this.collection.params.start=0,this.collection.restEnabled?await this.collection.fetch():await this.render()),this.updateFilterPills(),this.emit("list:search",{searchTerm:s}),this.emit("params-changed")}async onActionClearSearch(e,t){this.setFilter("search",null),this.collection&&(this.collection.params.start=0,this.collection.restEnabled&&await this.collection.fetch()),await this.render(),this.updateFilterPills(),this.emit("list:search",{searchTerm:""}),this.emit("params-changed")}setupSearchClearListener(){if(!this.element)return;this.element.querySelectorAll('input[type="search"][data-filter="search"]').forEach(t=>{t.addEventListener("input",s=>{s.target.value===""&&this.getActiveFilters().search&&this.onActionClearSearch(s,s.target)})})}updateFilterPills(){const e=this.element?.querySelector('[data-container="filter-pills"]');e&&(e.innerHTML=this.buildActivePills())}updateSearchInputs(e){const t=this.element?.querySelectorAll('[data-filter="search"]');t&&t.forEach(s=>{s.value=e||""})}renderPagination(){const e=this.element.querySelector('[data-container="pagination"]');if(!e||!this.collection)return;const t=this.collection.meta?.count||this.collection.length(),s=this.collection.params?.size||10,i=this.collection.params?.start||0,r=Math.floor(i/s)+1,n=Math.ceil(t/s);if(n<=1){e.innerHTML="";return}const a=r>1?r-1:n,o=r<n?r+1:1,l=[];l.push(`
1585
1585
  <li class="page-item">
1586
1586
  <a class="page-link" href="#" data-action="page" data-page="${a}">
1587
1587
  <i class="bi bi-chevron-left"></i>
@@ -1710,7 +1710,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1710
1710
  </button>
1711
1711
  </div>
1712
1712
  </div>
1713
- `}setupEditorEvents(e,t,s){const i=e.querySelector(".cell-input"),r=e.querySelector(".cell-save"),n=e.querySelector(".cell-cancel");i&&(i.type==="text"||i.type==="email"||i.type==="number")&&i.addEventListener("keydown",a=>{a.key==="Enter"?(a.preventDefault(),this.saveCellEdit(e,t,s)):a.key==="Escape"&&(a.preventDefault(),this.cancelCellEdit(e,t))}),i&&(i.type==="checkbox"||i.tagName==="SELECT")&&s.autoSave!==!1&&i.addEventListener("change",()=>{this.saveCellEdit(e,t,s)}),r?.addEventListener("click",()=>{this.saveCellEdit(e,t,s)}),n?.addEventListener("click",()=>{this.cancelCellEdit(e,t)})}async saveCellEdit(e,t,s){const i=e.querySelector(".cell-input");if(!i)return;let r;i.type==="checkbox"?r=i.checked:(i.tagName,r=i.value);const n=this.model.get?this.model.get(t):this.model[t];try{this.model.save?await this.model.save({[t]:r}):this.model[t]=r,this.exitEditMode(e,t,r),this.emit("cell:save",{row:this,model:this.model,column:t,oldValue:n,newValue:r})}catch(a){console.error("Failed to save cell edit:",a),this.emit("cell:save:error",{row:this,model:this.model,column:t,oldValue:n,newValue:r,error:a}),e.classList.add("saving-error"),setTimeout(()=>e.classList.remove("saving-error"),3e3)}}cancelCellEdit(e,t){const s=e.dataset.originalContent;this.exitEditMode(e,t,null,s),this.emit("cell:cancel",{row:this,model:this.model,column:t})}exitEditMode(e,t,s=null,i=null){const n=e.closest("td").querySelector(".cell-content");if(n){if(s!==null){const a=this.columns.find(l=>l.key===t);let o=s;a&&a.formatter&&typeof a.formatter=="string"&&(o=P.pipe(s,a.formatter)),n.innerHTML=this.escapeHtml(o)}else i&&(n.innerHTML=i);n.style.display=""}e.remove(),this.editingCells.delete(t)}escapeHtml(e){if(e==null)return"";const t=document.createElement("div");return t.textContent=e,t.innerHTML}select(){super.select(),this.addClass("selected");const e=this.element?.querySelector(".mojo-select-cell");e&&e.classList.add("selected")}deselect(){super.deselect(),this.removeClass("selected");const e=this.element?.querySelector(".mojo-select-cell");e&&e.classList.remove("selected")}}class It extends he{constructor(e={}){const t={className:"table-view-component",itemClass:e.itemClass||Ze,selectionMode:e.selectable?"multiple":"none",emptyMessage:e.emptyMessage||"No data available",addButtonIcon:e.addButtonIcon||"bi bi-plus-circle",...e};super(t),this.isFullscreen=!1,this.columns=e.columns||[],this.actions=e.actions||null,this.contextMenu=e.contextMenu||null,this.batchActions=e.batchActions||null,this.searchable=e.searchable!==!1,this.sortable=e.sortable!==!1,this.filterable=e.filterable!==!1,this.paginated=e.paginated!==!1,this.paginationMode=e.paginationMode||"pages",this.persistSelection=e.persistSelection===!0,this.clickAction=e.clickAction||"view",this.fetchOnView=e.fetchOnView!==!1,this.itemView=e.itemView,this.addForm=e.addForm,this.editForm=e.editForm,this.deleteTemplate=e.deleteTemplate,this.formDialogConfig=e.formDialogConfig||{},this.viewDialogOptions=e.viewDialogOptions||{},this.exportOptions=e.exportOptions||null,this.options.showExport&&!this.exportOptions&&(this.exportOptions=[{format:"csv",label:"Export as CSV",icon:"bi bi-file-earmark-spreadsheet"},{format:"json",label:"Export as JSON",icon:"bi bi-file-earmark-code"}]),this.exportSource=e.exportSource||"remote",this.filters={},this.additionalFilters=e.filters||[],this.hideActivePills=e.hideActivePills===!0,this.hideActivePillNames=e.hideActivePillNames||[],this.rowAction=e.rowAction||"row-click",this.batchBarLocation=e.batchBarLocation||"bottom",this.options.addButtonLabel=e.addButtonLabel||"Add",this.toolbarButtons=e.toolbarButtons||[],this.toolbarRight=e.toolbarRight||null,this.title=e.title||null,this.eyebrow=e.eyebrow||null,this.showRefresh=e.showRefresh!==!1,this.showFullscreen=e.showFullscreen!==!1,this.tableOptions={striped:!0,bordered:!1,hover:!0,responsive:!1,size:null,...e.tableOptions},this.searchPlacement=e.searchPlacement||"toolbar",this.searchPlaceholder=e.searchPlaceholder||"Search...",this.initializeColumns(),this.extractColumnFilters(),this.footerTotalColumns=this.columns.filter(s=>s.footer_total===!0),this.hasFooterTotals=this.footerTotalColumns.length>0,this.template=this.buildTableTemplate(),this.setupCollectionListeners()}setupCollectionListeners(){this.hasFooterTotals&&this.collection&&this.collection.on("reset add remove change",()=>{this.updateFooterTotals()})}initializeColumns(){this.columns.forEach(e=>{!e.key&&e.name&&(e.key=e.name),!e.label&&!e.title&&(e.label=e.key.charAt(0).toUpperCase()+e.key.slice(1))})}getResponsiveClasses(e){if(!e)return"";const t=["sm","md","lg","xl","xxl"];if(typeof e=="string")return t.includes(e)?`d-none d-${e}-table-cell`:(console.warn(`Invalid visibility breakpoint: ${e}. Valid options are: ${t.join(", ")}`),"");if(typeof e=="object"){const s=[];if(e.hide){if(!t.includes(e.hide))return console.warn(`Invalid hide breakpoint: ${e.hide}. Valid options are: ${t.join(", ")}`),"";s.push(`d-table-cell d-${e.hide}-none`)}if(e.show){if(!t.includes(e.show))return console.warn(`Invalid show breakpoint: ${e.show}. Valid options are: ${t.join(", ")}`),"";e.hide?s.push(`d-${e.show}-table-cell`):s.push(`d-none d-${e.show}-table-cell`)}return s.join(" ")}return""}getAlignClass(e){if(!e)return"";const s={left:"text-start",start:"text-start",center:"text-center",right:"text-end",end:"text-end"}[String(e).toLowerCase()];return s||(console.warn(`Invalid column align: ${e}. Valid options are: left, center, right`),"")}parseColumnKey(e){const t=e.split("|");return{fieldKey:t[0],formatter:t[1]||null}}updateFooterTotals(){if(!this.hasFooterTotals||!this.element)return;const e=this.calculateFooterTotals();let t=0;this.columns.forEach(s=>{if(s.footer_total){const i=`col_${t}`,r=this.element.querySelector(`[data-total-column="${i}"]`);if(r&&e[i]){const n=this.parseColumnKey(s.key).formatter||s.formatter;let a;n&&typeof n=="string"?a=this.formatValue(e[i].value,n):a=e[i].value,r.textContent=a}t++}})}formatValue(e,t){try{return P.pipe(e,t)}catch(s){return console.warn("Error formatting value:",s),e}}calculateFooterTotals(){if(!this.hasFooterTotals||!this.collection||this.collection.length===0)return{};const e={};return this.footerTotalColumns.forEach((t,s)=>{const{fieldKey:i,formatter:r}=this.parseColumnKey(t.key);let n=0;this.collection.forEach(o=>{const l=o.get?o.get(i):o[i],d=parseFloat(l)||0;n+=d});const a=`col_${s}`;e[a]={value:n,formatter:r||t.formatter,fieldKey:i,originalKey:t.key}}),e}extractColumnFilters(){this.filters={},this.columns.forEach(e=>{if(e.filter){const{fieldKey:t}=this.parseColumnKey(e.key);this.filters[t]={...e.filter,label:e.filter.label||e.label||t}}})}isSelectable(){return this.batchActions&&this.batchActions.length>0&&this.selectionMode==="multiple"}buildTableTemplate(){const e=this.batchBarLocation==="top"?this.buildBatchActionsPanel():"",t=this.batchBarLocation==="bottom"?this.buildBatchActionsPanel():"",s=(()=>{const i=this.tableOptions&&this.tableOptions.fontSize!=null?this.tableOptions.fontSize:this.options&&this.options.fontSize,r=i==="sm"?"0.9rem":i==="xs"?"0.8rem":i?String(i):null;return r?` style="font-size: ${r};"`:""})();return`
1713
+ `}setupEditorEvents(e,t,s){const i=e.querySelector(".cell-input"),r=e.querySelector(".cell-save"),n=e.querySelector(".cell-cancel");i&&(i.type==="text"||i.type==="email"||i.type==="number")&&i.addEventListener("keydown",a=>{a.key==="Enter"?(a.preventDefault(),this.saveCellEdit(e,t,s)):a.key==="Escape"&&(a.preventDefault(),this.cancelCellEdit(e,t))}),i&&(i.type==="checkbox"||i.tagName==="SELECT")&&s.autoSave!==!1&&i.addEventListener("change",()=>{this.saveCellEdit(e,t,s)}),r?.addEventListener("click",()=>{this.saveCellEdit(e,t,s)}),n?.addEventListener("click",()=>{this.cancelCellEdit(e,t)})}async saveCellEdit(e,t,s){const i=e.querySelector(".cell-input");if(!i)return;let r;i.type==="checkbox"?r=i.checked:(i.tagName,r=i.value);const n=this.model.get?this.model.get(t):this.model[t];try{this.model.save?await this.model.save({[t]:r}):this.model[t]=r,this.exitEditMode(e,t,r),this.emit("cell:save",{row:this,model:this.model,column:t,oldValue:n,newValue:r})}catch(a){console.error("Failed to save cell edit:",a),this.emit("cell:save:error",{row:this,model:this.model,column:t,oldValue:n,newValue:r,error:a}),e.classList.add("saving-error"),setTimeout(()=>e.classList.remove("saving-error"),3e3)}}cancelCellEdit(e,t){const s=e.dataset.originalContent;this.exitEditMode(e,t,null,s),this.emit("cell:cancel",{row:this,model:this.model,column:t})}exitEditMode(e,t,s=null,i=null){const n=e.closest("td").querySelector(".cell-content");if(n){if(s!==null){const a=this.columns.find(l=>l.key===t);let o=s;a&&a.formatter&&typeof a.formatter=="string"&&(o=P.pipe(s,a.formatter)),n.innerHTML=this.escapeHtml(o)}else i&&(n.innerHTML=i);n.style.display=""}e.remove(),this.editingCells.delete(t)}escapeHtml(e){if(e==null)return"";const t=document.createElement("div");return t.textContent=e,t.innerHTML}select(){super.select(),this.addClass("selected");const e=this.element?.querySelector(".mojo-select-cell");e&&e.classList.add("selected")}deselect(){super.deselect(),this.removeClass("selected");const e=this.element?.querySelector(".mojo-select-cell");e&&e.classList.remove("selected")}}class Mt extends te{constructor(e={}){const t={className:"table-view-component",itemClass:e.itemClass||Ze,selectionMode:e.selectable?"multiple":"none",emptyMessage:e.emptyMessage||"No data available",addButtonIcon:e.addButtonIcon||"bi bi-plus-circle",...e};super(t),this.isFullscreen=!1,this.columns=e.columns||[],this.actions=e.actions||null,this.contextMenu=e.contextMenu||null,this.batchActions=e.batchActions||null,this.searchable=e.searchable!==!1,this.sortable=e.sortable!==!1,this.filterable=e.filterable!==!1,this.paginated=e.paginated!==!1,this.paginationMode=e.paginationMode||"pages",this.persistSelection=e.persistSelection===!0,this.clickAction=e.clickAction||"view",this.fetchOnView=e.fetchOnView!==!1,this.itemView=e.itemView,this.addForm=e.addForm,this.editForm=e.editForm,this.deleteTemplate=e.deleteTemplate,this.formDialogConfig=e.formDialogConfig||{},this.viewDialogOptions=e.viewDialogOptions||{},this.exportOptions=e.exportOptions||null,this.options.showExport&&!this.exportOptions&&(this.exportOptions=[{format:"csv",label:"Export as CSV",icon:"bi bi-file-earmark-spreadsheet"},{format:"json",label:"Export as JSON",icon:"bi bi-file-earmark-code"}]),this.exportSource=e.exportSource||"remote",this.filters={},this.additionalFilters=e.filters||[],this.hideActivePills=e.hideActivePills===!0,this.hideActivePillNames=e.hideActivePillNames||[],this.rowAction=e.rowAction||"row-click",this.batchBarLocation=e.batchBarLocation||"bottom",this.options.addButtonLabel=e.addButtonLabel||"Add",this.toolbarButtons=e.toolbarButtons||[],this.toolbarRight=e.toolbarRight||null,this.title=e.title||null,this.eyebrow=e.eyebrow||null,this.showRefresh=e.showRefresh!==!1,this.showFullscreen=e.showFullscreen!==!1,this.tableOptions={striped:!0,bordered:!1,hover:!0,responsive:!1,size:null,...e.tableOptions},this.searchPlacement=e.searchPlacement||"toolbar",this.searchPlaceholder=e.searchPlaceholder||"Search...",this.initializeColumns(),this.extractColumnFilters(),this.footerTotalColumns=this.columns.filter(s=>s.footer_total===!0),this.hasFooterTotals=this.footerTotalColumns.length>0,this.template=this.buildTableTemplate(),this.setupCollectionListeners()}setupCollectionListeners(){this.hasFooterTotals&&this.collection&&this.collection.on("reset add remove change",()=>{this.updateFooterTotals()})}initializeColumns(){this.columns.forEach(e=>{!e.key&&e.name&&(e.key=e.name),!e.label&&!e.title&&(e.label=e.key.charAt(0).toUpperCase()+e.key.slice(1))})}getResponsiveClasses(e){if(!e)return"";const t=["sm","md","lg","xl","xxl"];if(typeof e=="string")return t.includes(e)?`d-none d-${e}-table-cell`:(console.warn(`Invalid visibility breakpoint: ${e}. Valid options are: ${t.join(", ")}`),"");if(typeof e=="object"){const s=[];if(e.hide){if(!t.includes(e.hide))return console.warn(`Invalid hide breakpoint: ${e.hide}. Valid options are: ${t.join(", ")}`),"";s.push(`d-table-cell d-${e.hide}-none`)}if(e.show){if(!t.includes(e.show))return console.warn(`Invalid show breakpoint: ${e.show}. Valid options are: ${t.join(", ")}`),"";e.hide?s.push(`d-${e.show}-table-cell`):s.push(`d-none d-${e.show}-table-cell`)}return s.join(" ")}return""}getAlignClass(e){if(!e)return"";const s={left:"text-start",start:"text-start",center:"text-center",right:"text-end",end:"text-end"}[String(e).toLowerCase()];return s||(console.warn(`Invalid column align: ${e}. Valid options are: left, center, right`),"")}parseColumnKey(e){const t=e.split("|");return{fieldKey:t[0],formatter:t[1]||null}}updateFooterTotals(){if(!this.hasFooterTotals||!this.element)return;const e=this.calculateFooterTotals();let t=0;this.columns.forEach(s=>{if(s.footer_total){const i=`col_${t}`,r=this.element.querySelector(`[data-total-column="${i}"]`);if(r&&e[i]){const n=this.parseColumnKey(s.key).formatter||s.formatter;let a;n&&typeof n=="string"?a=this.formatValue(e[i].value,n):a=e[i].value,r.textContent=a}t++}})}formatValue(e,t){try{return P.pipe(e,t)}catch(s){return console.warn("Error formatting value:",s),e}}calculateFooterTotals(){if(!this.hasFooterTotals||!this.collection||this.collection.length===0)return{};const e={};return this.footerTotalColumns.forEach((t,s)=>{const{fieldKey:i,formatter:r}=this.parseColumnKey(t.key);let n=0;this.collection.forEach(o=>{const l=o.get?o.get(i):o[i],d=parseFloat(l)||0;n+=d});const a=`col_${s}`;e[a]={value:n,formatter:r||t.formatter,fieldKey:i,originalKey:t.key}}),e}extractColumnFilters(){this.filters={},this.columns.forEach(e=>{if(e.filter){const{fieldKey:t}=this.parseColumnKey(e.key);this.filters[t]={...e.filter,label:e.filter.label||e.label||t}}})}isSelectable(){return this.batchActions&&this.batchActions.length>0&&this.selectionMode==="multiple"}buildTableTemplate(){const e=this.batchBarLocation==="top"?this.buildBatchActionsPanel():"",t=this.batchBarLocation==="bottom"?this.buildBatchActionsPanel():"",s=(()=>{const i=this.tableOptions&&this.tableOptions.fontSize!=null?this.tableOptions.fontSize:this.options&&this.options.fontSize,r=i==="sm"?"0.9rem":i==="xs"?"0.8rem":i?String(i):null;return r?` style="font-size: ${r};"`:""})();return`
1714
1714
  <div class="mojo-table-wrapper">
1715
1715
  ${this.buildToolbarTemplate()}
1716
1716
  ${e}
@@ -1846,7 +1846,7 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1846
1846
  </div>
1847
1847
  </div>
1848
1848
  </div>
1849
- `}}_createItemView(e,t){if(this.itemViews.has(e.id))return this.itemViews.get(e.id);const s=new this.itemClass({model:e,index:t,listView:this,tableView:this,template:this.itemTemplate,columns:this.columns,actions:this.actions,contextMenu:this.contextMenu,batchActions:this.batchActions,containerId:"items"});return this.itemViews.set(e.id,s),this._wireItemViewListeners(s),s.on("item:select",()=>this.updateBatchActionsPanel()),s.on("item:deselect",()=>this.updateBatchActionsPanel()),s.on("cell:edit",this._onCellEdit.bind(this)),s.on("cell:save",this._onCellSave.bind(this)),s.on("cell:cancel",this._onCellCancel.bind(this)),s}async onBeforeRender(){await super.onBeforeRender(),this.footerTotals=this.calculateFooterTotals()}async onAfterRender(){await super.onAfterRender(),this.hasFooterTotals&&this.updateFooterTotals(),this.updateSortIcons()}_onCellEdit(e){this.emit("cell:edit",e)}async _onCellSave(e){this.emit("cell:save",e)}_onCellCancel(e){this.emit("cell:cancel",e)}_defaultGroupHeaderTemplate(){return'<th colspan="{{colspan}}" class="list-group-header-cell">{{key}}</th>'}_groupHeaderViewOptions(e,t,s){const i=this.columns?.length||0,r=this.isSelectable()?1:0,n=this.actions||this.contextMenu?1:0;return{tagName:"tr",className:`list-group-header-row list-group-header-row--${this.groupHeaderStyle}`,colspan:Math.max(1,i+r+n)}}isFullscreenSupported(){return!!(document.fullscreenEnabled||document.mozFullScreenEnabled||document.webkitFullscreenEnabled||document.msFullscreenEnabled)}async onActionToggleFullscreen(e,t){this.isFullscreen?await this.exitFullscreen():await this.enterFullscreen()}async enterFullscreen(){try{this.element.requestFullscreen?await this.element.requestFullscreen():this.element.mozRequestFullScreen?await this.element.mozRequestFullScreen():this.element.webkitRequestFullscreen?await this.element.webkitRequestFullscreen():this.element.msRequestFullscreen&&await this.element.msRequestFullscreen(),this.isFullscreen=!0,this.element.classList.add("table-fullscreen"),this.updateFullscreenButton(),this.setupFullscreenListeners(),this.emit("table:fullscreen:enter")}catch(e){console.warn("Could not enter fullscreen:",e)}}async exitFullscreen(){try{document.exitFullscreen?await document.exitFullscreen():document.mozCancelFullScreen?await document.mozCancelFullScreen():document.webkitExitFullscreen?await document.webkitExitFullscreen():document.msExitFullscreen&&await document.msExitFullscreen(),this.isFullscreen=!1,this.element.classList.remove("table-fullscreen"),this.updateFullscreenButton(),this.emit("table:fullscreen:exit")}catch(e){console.warn("Could not exit fullscreen:",e)}}updateFullscreenButton(){const e=this.element?.querySelector(".btn-fullscreen"),t=e?.querySelector("i");e&&t&&(this.isFullscreen?(t.className="bi bi-fullscreen-exit",e.title="Exit Fullscreen"):(t.className="bi bi-fullscreen",e.title="Enter Fullscreen"))}setupFullscreenListeners(){if(this._fullscreenHandler)return;const e=()=>{!(document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement||document.msFullscreenElement)&&this.isFullscreen&&(this.isFullscreen=!1,this.element.classList.remove("table-fullscreen"),this.updateFullscreenButton(),this.emit("table:fullscreen:exit"))};document.addEventListener("fullscreenchange",e),document.addEventListener("mozfullscreenchange",e),document.addEventListener("webkitfullscreenchange",e),document.addEventListener("msfullscreenchange",e),this._fullscreenHandler=e}cleanupFullscreenListeners(){this._fullscreenHandler&&(document.removeEventListener("fullscreenchange",this._fullscreenHandler),document.removeEventListener("mozfullscreenchange",this._fullscreenHandler),document.removeEventListener("webkitfullscreenchange",this._fullscreenHandler),document.removeEventListener("msfullscreenchange",this._fullscreenHandler),this._fullscreenHandler=null)}destroy(){this.cleanupFullscreenListeners(),super.destroy()}async onActionAdd(e,t){return this.emit("table:add",{event:e}),super.onActionAdd(e,t)}async onActionExport(e,t){const s=t.getAttribute("data-format")||"json";return this.emit("table:export",{format:s,source:this.exportSource,event:e}),super.onActionExport(e,t)}getSortBy(){const e=this.collection?.params?.sort;return e?e.startsWith("-")?e.slice(1):e:null}getSortDirection(){const e=this.collection?.params?.sort;return e&&e.startsWith("-")?"desc":"asc"}getSortIcon(e){return e==="asc"?'<i class="bi bi-sort-alpha-down text-primary"></i>':e==="desc"?'<i class="bi bi-sort-alpha-down-alt text-primary"></i>':'<i class="bi bi-three-dots-vertical text-muted"></i>'}async onActionSort(e,t){e.preventDefault();const s=t.getAttribute("data-field"),i=t.getAttribute("data-direction");if(this.collection){let r;if(i==="none"?r=void 0:i==="desc"?r=`-${s}`:r=s,this.collection.setParams({...this.collection.params,sort:r,start:0}),this.collection.restEnabled)await this.collection.fetch();else{if(r){const n=r.startsWith("-"),a=n?r.slice(1):r;this.collection.sort((o,l)=>{const d=o.get(a),h=l.get(a);return d<h?n?1:-1:d>h?n?-1:1:0})}this.render()}}this.updateSortIcons(),this.emit("table:sort",{field:s,event:e}),this.emit("params-changed")}updateSortIcons(){if(!this.element)return;const e=this.getSortBy(),t=this.getSortDirection();this.columns.forEach(s=>{if(this.sortable&&s.sortable!==!1){const{fieldKey:i}=this.parseColumnKey(s.key),r=this.element.querySelector(`[data-bs-toggle="dropdown"][data-column="${i}"]`);if(r){const n=e===i,a=this.getSortIcon(n?t:null);r.innerHTML=a;const o=r.nextElementSibling;if(o){const l=o.querySelector(`[data-field="${i}"][data-direction="asc"]`),d=o.querySelector(`[data-field="${i}"][data-direction="desc"]`),h=o.querySelector(`[data-field="${i}"][data-direction="none"]`);l&&l.classList.toggle("active",n&&t==="asc"),d&&d.classList.toggle("active",n&&t==="desc"),h&&h.classList.toggle("active",!n||e!==i)}}}})}async onActionSelectAll(e,t){e.stopPropagation();const s=this.itemViews.size>0&&Array.from(this.itemViews.values()).every(r=>r.selected);s?this.clearSelection():this.forEachItem(r=>{r.selected||r.select()});const i=this.element?.querySelector(".mojo-select-all-cell");i&&i.classList.toggle("selected",!s),this.updateBatchActionsPanel()}updateBatchActionsPanel(){if(!this.batchActions||this.batchActions.length===0)return;const e=this.getSelectedItems().length;if(this.batchBarLocation==="top"){const s=this.element?.querySelector(".batch-actions-panel-top"),i=this.element?.querySelector(".batch-select-count");s&&i&&(i.textContent=e,e>0?s.classList.remove("d-none"):s.classList.add("d-none"))}else{const s=this.element?.querySelector(".batch-actions-panel"),i=this.element?.querySelector(".batch-select-count");s&&i&&(i.textContent=e,s.style.display=e>0?"block":"none")}const t=this.element?.querySelector(".mojo-select-all-cell");if(t){const s=this.itemViews.size>0&&Array.from(this.itemViews.values()).every(n=>n.selected),i=Array.from(this.itemViews.values()).some(n=>n.selected);t.classList.toggle("selected",s),t.classList.toggle("indeterminate",!s&&i);const r=t.querySelector("i");r&&(r.className=!s&&i?"bi bi-dash":"bi bi-check")}}async onActionBatch(e,t){const s=t.getAttribute("data-action").replace("batch-",""),i=this.getSelectedItems();this.emit("batch:action",{action:s,items:i,event:e})}async onActionClearSelection(e,t){this.clearSelection(),this.updateBatchActionsPanel()}getFilterDisplayValue(e,t){if(e==="search")return`"${t}"`;const s=this.filters[e]||this.additionalFilters.find(i=>(i.name||i.key)===e);if(s&&s.type==="daterange"&&typeof t=="object"){const i=t.start||"",r=t.end||"";return`${i} to ${r}`}if(s&&s.type==="select"&&s.options){if(typeof s.options[0]=="object"){const i=s.options.find(r=>r.value===t);return i?i.label:t}return t}return t}}function xs(){return typeof window>"u"?null:((!window.MOJO||typeof window.MOJO!="object")&&(window.MOJO={}),window.MOJO)}function $s(c){return c.__lite&&c.__lite.version||(c.WebApp=ve,c.View=C,c.Page=pe,c.Router=Te,c.Model=K,c.Collection=le,c.Rest=ie,c.FormBuilder=fe,c.FormView=ee,c.Dialog=x,c.ModalView=x,c.ProgressView=Le,c.ListView=he,c.ListViewItem=Ae,c.TableView=It,c.TableRow=Ze,c.DataFormatter=P,c.MOJOUtils=$,c.__lite={version:"dev",build:"web-mojo.lite"},c.mount=async function(t,s){if(!t)throw new Error("MOJO.mount(view, container) requires a view");const i=typeof s=="string"?document.querySelector(s):s;if(!i)throw new Error("MOJO.mount(view, container) container not found");if(typeof t.render!="function"||typeof t.mount!="function")throw new Error("MOJO.mount expects a View instance with render() and mount() methods");return await t.render(),await t.mount(i),t}),c}const Ke=xs();Ke&&$s(Ke);class Qe extends C{constructor(e={}){const{data:t,model:s,fields:i,columns:r,responsive:n,showEmptyValues:a,emptyValueText:o,...l}=e;super({tagName:"div",className:"data-view",...l}),this.data=t||{},this.fields=i||[],this.model=s||null,this.model&&(this.data=this.model),this.dataViewOptions={columns:r||2,responsive:n!==!1,showEmptyValues:a||!1,emptyValueText:o||"—",rowClass:"row g-3",itemClass:"data-view-item",labelClass:"data-view-label fw-semibold text-muted small text-uppercase",valueClass:"data-view-value"}}async onBeforeRender(){this.fields.length===0&&this.getData()&&this.generateFieldsFromData()}async renderTemplate(){const e=this.buildItemsHTML();return`
1849
+ `}}_createItemView(e,t){if(this.itemViews.has(e.id))return this.itemViews.get(e.id);const s=new this.itemClass({model:e,index:t,listView:this,tableView:this,template:this.itemTemplate,columns:this.columns,actions:this.actions,contextMenu:this.contextMenu,batchActions:this.batchActions,containerId:"items"});return this.itemViews.set(e.id,s),this._wireItemViewListeners(s),s.on("item:select",()=>this.updateBatchActionsPanel()),s.on("item:deselect",()=>this.updateBatchActionsPanel()),s.on("cell:edit",this._onCellEdit.bind(this)),s.on("cell:save",this._onCellSave.bind(this)),s.on("cell:cancel",this._onCellCancel.bind(this)),s}async onBeforeRender(){await super.onBeforeRender(),this.footerTotals=this.calculateFooterTotals()}async onAfterRender(){await super.onAfterRender(),this.hasFooterTotals&&this.updateFooterTotals(),this.updateSortIcons()}_onCellEdit(e){this.emit("cell:edit",e)}async _onCellSave(e){this.emit("cell:save",e)}_onCellCancel(e){this.emit("cell:cancel",e)}_defaultGroupHeaderTemplate(){return'<th colspan="{{colspan}}" class="list-group-header-cell">{{key}}</th>'}_groupHeaderViewOptions(e,t,s){const i=this.columns?.length||0,r=this.isSelectable()?1:0,n=this.actions||this.contextMenu?1:0;return{tagName:"tr",className:`list-group-header-row list-group-header-row--${this.groupHeaderStyle}`,colspan:Math.max(1,i+r+n)}}isFullscreenSupported(){return!!(document.fullscreenEnabled||document.mozFullScreenEnabled||document.webkitFullscreenEnabled||document.msFullscreenEnabled)}async onActionToggleFullscreen(e,t){this.isFullscreen?await this.exitFullscreen():await this.enterFullscreen()}async enterFullscreen(){try{this.element.requestFullscreen?await this.element.requestFullscreen():this.element.mozRequestFullScreen?await this.element.mozRequestFullScreen():this.element.webkitRequestFullscreen?await this.element.webkitRequestFullscreen():this.element.msRequestFullscreen&&await this.element.msRequestFullscreen(),this.isFullscreen=!0,this.element.classList.add("table-fullscreen"),this.updateFullscreenButton(),this.setupFullscreenListeners(),this.emit("table:fullscreen:enter")}catch(e){console.warn("Could not enter fullscreen:",e)}}async exitFullscreen(){try{document.exitFullscreen?await document.exitFullscreen():document.mozCancelFullScreen?await document.mozCancelFullScreen():document.webkitExitFullscreen?await document.webkitExitFullscreen():document.msExitFullscreen&&await document.msExitFullscreen(),this.isFullscreen=!1,this.element.classList.remove("table-fullscreen"),this.updateFullscreenButton(),this.emit("table:fullscreen:exit")}catch(e){console.warn("Could not exit fullscreen:",e)}}updateFullscreenButton(){const e=this.element?.querySelector(".btn-fullscreen"),t=e?.querySelector("i");e&&t&&(this.isFullscreen?(t.className="bi bi-fullscreen-exit",e.title="Exit Fullscreen"):(t.className="bi bi-fullscreen",e.title="Enter Fullscreen"))}setupFullscreenListeners(){if(this._fullscreenHandler)return;const e=()=>{!(document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement||document.msFullscreenElement)&&this.isFullscreen&&(this.isFullscreen=!1,this.element.classList.remove("table-fullscreen"),this.updateFullscreenButton(),this.emit("table:fullscreen:exit"))};document.addEventListener("fullscreenchange",e),document.addEventListener("mozfullscreenchange",e),document.addEventListener("webkitfullscreenchange",e),document.addEventListener("msfullscreenchange",e),this._fullscreenHandler=e}cleanupFullscreenListeners(){this._fullscreenHandler&&(document.removeEventListener("fullscreenchange",this._fullscreenHandler),document.removeEventListener("mozfullscreenchange",this._fullscreenHandler),document.removeEventListener("webkitfullscreenchange",this._fullscreenHandler),document.removeEventListener("msfullscreenchange",this._fullscreenHandler),this._fullscreenHandler=null)}destroy(){this.cleanupFullscreenListeners(),super.destroy()}async onActionAdd(e,t){return this.emit("table:add",{event:e}),super.onActionAdd(e,t)}async onActionExport(e,t){const s=t.getAttribute("data-format")||"json";return this.emit("table:export",{format:s,source:this.exportSource,event:e}),super.onActionExport(e,t)}getSortBy(){const e=this.collection?.params?.sort;return e?e.startsWith("-")?e.slice(1):e:null}getSortDirection(){const e=this.collection?.params?.sort;return e&&e.startsWith("-")?"desc":"asc"}getSortIcon(e){return e==="asc"?'<i class="bi bi-sort-alpha-down text-primary"></i>':e==="desc"?'<i class="bi bi-sort-alpha-down-alt text-primary"></i>':'<i class="bi bi-three-dots-vertical text-muted"></i>'}async onActionSort(e,t){e.preventDefault();const s=t.getAttribute("data-field"),i=t.getAttribute("data-direction");if(this.collection){let r;if(i==="none"?r=void 0:i==="desc"?r=`-${s}`:r=s,this.collection.setParams({...this.collection.params,sort:r,start:0}),this.collection.restEnabled)await this.collection.fetch();else{if(r){const n=r.startsWith("-"),a=n?r.slice(1):r;this.collection.sort((o,l)=>{const d=o.get(a),h=l.get(a);return d<h?n?1:-1:d>h?n?-1:1:0})}this.render()}}this.updateSortIcons(),this.emit("table:sort",{field:s,event:e}),this.emit("params-changed")}updateSortIcons(){if(!this.element)return;const e=this.getSortBy(),t=this.getSortDirection();this.columns.forEach(s=>{if(this.sortable&&s.sortable!==!1){const{fieldKey:i}=this.parseColumnKey(s.key),r=this.element.querySelector(`[data-bs-toggle="dropdown"][data-column="${i}"]`);if(r){const n=e===i,a=this.getSortIcon(n?t:null);r.innerHTML=a;const o=r.nextElementSibling;if(o){const l=o.querySelector(`[data-field="${i}"][data-direction="asc"]`),d=o.querySelector(`[data-field="${i}"][data-direction="desc"]`),h=o.querySelector(`[data-field="${i}"][data-direction="none"]`);l&&l.classList.toggle("active",n&&t==="asc"),d&&d.classList.toggle("active",n&&t==="desc"),h&&h.classList.toggle("active",!n||e!==i)}}}})}async onActionSelectAll(e,t){e.stopPropagation();const s=this.itemViews.size>0&&Array.from(this.itemViews.values()).every(r=>r.selected);s?this.clearSelection():this.forEachItem(r=>{r.selected||r.select()});const i=this.element?.querySelector(".mojo-select-all-cell");i&&i.classList.toggle("selected",!s),this.updateBatchActionsPanel()}updateBatchActionsPanel(){if(!this.batchActions||this.batchActions.length===0)return;const e=this.getSelectedItems().length;if(this.batchBarLocation==="top"){const s=this.element?.querySelector(".batch-actions-panel-top"),i=this.element?.querySelector(".batch-select-count");s&&i&&(i.textContent=e,e>0?s.classList.remove("d-none"):s.classList.add("d-none"))}else{const s=this.element?.querySelector(".batch-actions-panel"),i=this.element?.querySelector(".batch-select-count");s&&i&&(i.textContent=e,s.style.display=e>0?"block":"none")}const t=this.element?.querySelector(".mojo-select-all-cell");if(t){const s=this.itemViews.size>0&&Array.from(this.itemViews.values()).every(n=>n.selected),i=Array.from(this.itemViews.values()).some(n=>n.selected);t.classList.toggle("selected",s),t.classList.toggle("indeterminate",!s&&i);const r=t.querySelector("i");r&&(r.className=!s&&i?"bi bi-dash":"bi bi-check")}}async onActionBatch(e,t){const s=t.getAttribute("data-action").replace("batch-",""),i=this.getSelectedItems();this.emit("batch:action",{action:s,items:i,event:e})}async onActionClearSelection(e,t){this.clearSelection(),this.updateBatchActionsPanel()}getFilterDisplayValue(e,t){if(e==="search")return`"${t}"`;const s=this.filters[e]||this.additionalFilters.find(i=>(i.name||i.key)===e);if(s&&s.type==="daterange"&&typeof t=="object"){const i=t.start||"",r=t.end||"";return`${i} to ${r}`}if(s&&s.type==="select"&&s.options){if(typeof s.options[0]=="object"){const i=s.options.find(r=>r.value===t);return i?i.label:t}return t}return t}}function xs(){return typeof window>"u"?null:((!window.MOJO||typeof window.MOJO!="object")&&(window.MOJO={}),window.MOJO)}function $s(c){return c.__lite&&c.__lite.version||(c.WebApp=ve,c.View=C,c.Page=pe,c.Router=Te,c.Model=K,c.Collection=ce,c.Rest=re,c.FormBuilder=fe,c.FormView=ee,c.Dialog=x,c.ModalView=x,c.ProgressView=Le,c.ListView=te,c.ListViewItem=Ae,c.TableView=Mt,c.TableRow=Ze,c.DataFormatter=P,c.MOJOUtils=$,c.__lite={version:"dev",build:"web-mojo.lite"},c.mount=async function(t,s){if(!t)throw new Error("MOJO.mount(view, container) requires a view");const i=typeof s=="string"?document.querySelector(s):s;if(!i)throw new Error("MOJO.mount(view, container) container not found");if(typeof t.render!="function"||typeof t.mount!="function")throw new Error("MOJO.mount expects a View instance with render() and mount() methods");return await t.render(),await t.mount(i),t}),c}const Ke=xs();Ke&&$s(Ke);class Qe extends C{constructor(e={}){const{data:t,model:s,fields:i,columns:r,responsive:n,showEmptyValues:a,emptyValueText:o,...l}=e;super({tagName:"div",className:"data-view",...l}),this.data=t||{},this.fields=i||[],this.model=s||null,this.model&&(this.data=this.model),this.dataViewOptions={columns:r||2,responsive:n!==!1,showEmptyValues:a||!1,emptyValueText:o||"—",rowClass:"row g-3",itemClass:"data-view-item",labelClass:"data-view-label fw-semibold text-muted small text-uppercase",valueClass:"data-view-value"}}async onBeforeRender(){this.fields.length===0&&this.getData()&&this.generateFieldsFromData()}async renderTemplate(){const e=this.buildItemsHTML();return`
1850
1850
  <div class="${this.dataViewOptions.rowClass}">
1851
1851
  ${e}
1852
1852
  </div>
@@ -1894,5 +1894,5 @@ var MOJO=(function(T){"use strict";class Te{constructor(e={}){this.defaultRoute=
1894
1894
  ${i}
1895
1895
  </div>
1896
1896
  </div>
1897
- `}catch(s){return console.error("Error creating nested DataView:",s),'<span class="text-danger">Error displaying nested data</span>'}}async updateData(e){return this.data=e,this.model&&typeof this.model.set=="function"&&this.model.set(e),this.fields.length>0&&!this.options.fields&&(this.fields=[]),await this.render(),this.emit("data:updated",{data:e}),this}async updateFields(e){return this.fields=e,await this.render(),this.emit("fields:updated",{fields:e}),this}async updateConfig(e){return this.dataViewOptions={...this.dataViewOptions,...e},await this.render(),this.emit("config:updated",{options:this.dataViewOptions}),this}async refresh(){if(this.model&&typeof this.model.fetch=="function")try{await this.model.fetch(),this.emit("data:refreshed",{model:this.model})}catch(e){throw this.emit("error",{error:e,message:"Failed to refresh data"}),e}return this}getCurrentData(){return this.getData()}getField(e){return this.fields.find(t=>t.name===e)||null}setFieldFormat(e,t){const s=this.getField(e);return s?(s.format=t,s.formatter=t):this.fields.push({name:e,label:this.formatLabel(e),type:this.inferFieldType(this.getData()[e],e),format:t,formatter:t}),this}addFormatPipe(e,t){const s=this.getField(e);return s&&(s.format?(s.format+=`|${t}`,s.formatter=s.format):(s.format=t,s.formatter=t)),this}clearFieldFormat(e){const t=this.getField(e);if(t){const s=this.getData(),i=this.inferFormatter(s[e],e,t.type);t.format=i,t.formatter=i}return this}getFormattedValue(e,t=null){const s=this.getField(e);if(!s)return null;const i=t!==null?t:this.getData()[e],r=s.format||s.formatter;return r&&i!=null?P.pipe(i,r):i}setFieldFormats(e){return Object.entries(e).forEach(([t,s])=>{this.setFieldFormat(t,s)}),this}getFieldFormats(){const e={};return this.fields.forEach(t=>{const s=t.format||t.formatter;s&&(e[t.name]=s)}),e}onInit(){super.onInit(),this.model&&typeof this.model.on=="function"&&this.model.on("change",()=>{this.isMounted()&&this.render()})}static create(e={}){return new Qe(e)}}const As=Object.freeze(Object.defineProperty({__proto__:null,default:Qe},Symbol.toStringTag,{value:"Module"}));return T.Collection=le,T.DataFormatter=P,T.Dialog=x,T.FormBuilder=fe,T.FormPage=vs,T.FormView=ee,T.ListView=he,T.ListViewItem=Ae,T.MOJOUtils=$,T.ModalView=x,T.Model=K,T.Page=pe,T.ProgressView=Le,T.Rest=ie,T.Router=Te,T.TableRow=Ze,T.TableView=It,T.View=C,T.WebApp=ve,T.default=Ke,Object.defineProperties(T,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}}),T})({});
1897
+ `}catch(s){return console.error("Error creating nested DataView:",s),'<span class="text-danger">Error displaying nested data</span>'}}async updateData(e){return this.data=e,this.model&&typeof this.model.set=="function"&&this.model.set(e),this.fields.length>0&&!this.options.fields&&(this.fields=[]),await this.render(),this.emit("data:updated",{data:e}),this}async updateFields(e){return this.fields=e,await this.render(),this.emit("fields:updated",{fields:e}),this}async updateConfig(e){return this.dataViewOptions={...this.dataViewOptions,...e},await this.render(),this.emit("config:updated",{options:this.dataViewOptions}),this}async refresh(){if(this.model&&typeof this.model.fetch=="function")try{await this.model.fetch(),this.emit("data:refreshed",{model:this.model})}catch(e){throw this.emit("error",{error:e,message:"Failed to refresh data"}),e}return this}getCurrentData(){return this.getData()}getField(e){return this.fields.find(t=>t.name===e)||null}setFieldFormat(e,t){const s=this.getField(e);return s?(s.format=t,s.formatter=t):this.fields.push({name:e,label:this.formatLabel(e),type:this.inferFieldType(this.getData()[e],e),format:t,formatter:t}),this}addFormatPipe(e,t){const s=this.getField(e);return s&&(s.format?(s.format+=`|${t}`,s.formatter=s.format):(s.format=t,s.formatter=t)),this}clearFieldFormat(e){const t=this.getField(e);if(t){const s=this.getData(),i=this.inferFormatter(s[e],e,t.type);t.format=i,t.formatter=i}return this}getFormattedValue(e,t=null){const s=this.getField(e);if(!s)return null;const i=t!==null?t:this.getData()[e],r=s.format||s.formatter;return r&&i!=null?P.pipe(i,r):i}setFieldFormats(e){return Object.entries(e).forEach(([t,s])=>{this.setFieldFormat(t,s)}),this}getFieldFormats(){const e={};return this.fields.forEach(t=>{const s=t.format||t.formatter;s&&(e[t.name]=s)}),e}onInit(){super.onInit(),this.model&&typeof this.model.on=="function"&&this.model.on("change",()=>{this.isMounted()&&this.render()})}static create(e={}){return new Qe(e)}}const As=Object.freeze(Object.defineProperty({__proto__:null,default:Qe},Symbol.toStringTag,{value:"Module"}));return T.Collection=ce,T.DataFormatter=P,T.Dialog=x,T.FormBuilder=fe,T.FormPage=vs,T.FormView=ee,T.ListView=te,T.ListViewItem=Ae,T.MOJOUtils=$,T.ModalView=x,T.Model=K,T.Page=pe,T.ProgressView=Le,T.Rest=re,T.Router=Te,T.TableRow=Ze,T.TableView=Mt,T.View=C,T.WebApp=ve,T.default=Ke,Object.defineProperties(T,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}}),T})({});
1898
1898
  //# sourceMappingURL=web-mojo.lite.iife.min.js.map