web-mojo 2.3.0 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/CHANGELOG.md +124 -0
  2. package/dist/admin-models.cjs.js +1 -1
  3. package/dist/admin-models.es.js +1 -1
  4. package/dist/admin.cjs.js +1 -1
  5. package/dist/admin.es.js +1 -1
  6. package/dist/auth.cjs.js +1 -1
  7. package/dist/auth.es.js +1 -1
  8. package/dist/charts.cjs.js +1 -1
  9. package/dist/charts.es.js +1 -1
  10. package/dist/chunks/{AssistantPanelView-BG34Qbfj.js → AssistantPanelView-CE6me7sJ.js} +2 -2
  11. package/dist/chunks/{AssistantPanelView-BG34Qbfj.js.map → AssistantPanelView-CE6me7sJ.js.map} +1 -1
  12. package/dist/chunks/{AssistantPanelView-DCEV6VeI.js → AssistantPanelView-DvsLAAIF.js} +2 -2
  13. package/dist/chunks/{AssistantPanelView-DCEV6VeI.js.map → AssistantPanelView-DvsLAAIF.js.map} +1 -1
  14. package/dist/chunks/{ChatView-B73uox2v.js → ChatView-CXykdAV1.js} +2 -2
  15. package/dist/chunks/{ChatView-B73uox2v.js.map → ChatView-CXykdAV1.js.map} +1 -1
  16. package/dist/chunks/{ChatView-W8daOwIo.js → ChatView-ys5MIiBf.js} +2 -2
  17. package/dist/chunks/{ChatView-W8daOwIo.js.map → ChatView-ys5MIiBf.js.map} +1 -1
  18. package/dist/chunks/{Collection-BZlmtcuL.js → Collection-BpUmNuDZ.js} +2 -2
  19. package/dist/chunks/{Collection-BZlmtcuL.js.map → Collection-BpUmNuDZ.js.map} +1 -1
  20. package/dist/chunks/{Collection-Bwoq6muu.js → Collection-CY6BblFn.js} +2 -2
  21. package/dist/chunks/{Collection-Bwoq6muu.js.map → Collection-CY6BblFn.js.map} +1 -1
  22. package/dist/chunks/{ContextMenu-q76hjQb6.js → ContextMenu-PtN50qH2.js} +2 -2
  23. package/dist/chunks/{ContextMenu-q76hjQb6.js.map → ContextMenu-PtN50qH2.js.map} +1 -1
  24. package/dist/chunks/{ContextMenu-BPPtuqKk.js → ContextMenu-XQVFU0mL.js} +2 -2
  25. package/dist/chunks/{ContextMenu-BPPtuqKk.js.map → ContextMenu-XQVFU0mL.js.map} +1 -1
  26. package/dist/chunks/{DataView-k-7wmk5_.js → DataView-BTi_BZHx.js} +2 -2
  27. package/dist/chunks/{DataView-k-7wmk5_.js.map → DataView-BTi_BZHx.js.map} +1 -1
  28. package/dist/chunks/{DataView-BbrwHMV4.js → DataView-WHRh1o6E.js} +2 -2
  29. package/dist/chunks/{DataView-BbrwHMV4.js.map → DataView-WHRh1o6E.js.map} +1 -1
  30. package/dist/chunks/{FormView-Dcy7XOtC.js → FormView-BzaGMf5_.js} +3 -3
  31. package/dist/chunks/{FormView-Dcy7XOtC.js.map → FormView-BzaGMf5_.js.map} +1 -1
  32. package/dist/chunks/{FormView-DPSuwWMq.js → FormView-DTD-Zy22.js} +3 -3
  33. package/dist/chunks/{FormView-DPSuwWMq.js.map → FormView-DTD-Zy22.js.map} +1 -1
  34. package/dist/chunks/{ListView-iGBsD4a7.js → ListView-BsnnTcmC.js} +2 -2
  35. package/dist/chunks/{ListView-iGBsD4a7.js.map → ListView-BsnnTcmC.js.map} +1 -1
  36. package/dist/chunks/{ListView-DHC-yBIw.js → ListView-Xf7kO6Me.js} +2 -2
  37. package/dist/chunks/{ListView-DHC-yBIw.js.map → ListView-Xf7kO6Me.js.map} +1 -1
  38. package/dist/chunks/{MetricsCountryMapView-CAD9wR_T.js → MetricsCountryMapView-BzGOi1d2.js} +2 -2
  39. package/dist/chunks/{MetricsCountryMapView-CAD9wR_T.js.map → MetricsCountryMapView-BzGOi1d2.js.map} +1 -1
  40. package/dist/chunks/{MetricsCountryMapView-Dzk3Yrzx.js → MetricsCountryMapView-C-S00Wiw.js} +2 -2
  41. package/dist/chunks/{MetricsCountryMapView-Dzk3Yrzx.js.map → MetricsCountryMapView-C-S00Wiw.js.map} +1 -1
  42. package/dist/chunks/{Modal-DuULCMFZ.js → Modal-GWjyfcz5.js} +3 -3
  43. package/dist/chunks/Modal-GWjyfcz5.js.map +1 -0
  44. package/dist/chunks/{Modal-DBJU16cc.js → Modal-wrfWfQhv.js} +3 -3
  45. package/dist/chunks/Modal-wrfWfQhv.js.map +1 -0
  46. package/dist/chunks/{Passkeys-CGRZ8ZMv.js → Passkeys-BviQX3_5.js} +2 -2
  47. package/dist/chunks/{Passkeys-CGRZ8ZMv.js.map → Passkeys-BviQX3_5.js.map} +1 -1
  48. package/dist/chunks/{Passkeys-Dr8-oSm9.js → Passkeys-gXR1Rc6C.js} +2 -2
  49. package/dist/chunks/{Passkeys-Dr8-oSm9.js.map → Passkeys-gXR1Rc6C.js.map} +1 -1
  50. package/dist/chunks/TokenManager-C6aXkRaI.js +2 -0
  51. package/dist/chunks/TokenManager-C6aXkRaI.js.map +1 -0
  52. package/dist/chunks/TokenManager-DgvhhTqN.js +2 -0
  53. package/dist/chunks/TokenManager-DgvhhTqN.js.map +1 -0
  54. package/dist/chunks/{User-Dg7xpYEI.js → User-B_Urf7U7.js} +2 -2
  55. package/dist/chunks/{User-Dg7xpYEI.js.map → User-B_Urf7U7.js.map} +1 -1
  56. package/dist/chunks/{User-DNQhdBtI.js → User-KTBU_5cr.js} +2 -2
  57. package/dist/chunks/{User-DNQhdBtI.js.map → User-KTBU_5cr.js.map} +1 -1
  58. package/dist/chunks/{UserProfileView-Bpz3VZmP.js → UserProfileView-BmduMJ86.js} +2 -2
  59. package/dist/chunks/{UserProfileView-Bpz3VZmP.js.map → UserProfileView-BmduMJ86.js.map} +1 -1
  60. package/dist/chunks/{UserProfileView-B5nczdfw.js → UserProfileView-COxSyPB0.js} +2 -2
  61. package/dist/chunks/{UserProfileView-B5nczdfw.js.map → UserProfileView-COxSyPB0.js.map} +1 -1
  62. package/dist/chunks/{View-Yazho7OL.js → View-C8UWvaSM.js} +2 -2
  63. package/dist/chunks/{View-Yazho7OL.js.map → View-C8UWvaSM.js.map} +1 -1
  64. package/dist/chunks/{View-C5n3sIFi.js → View-Cvs2TY7b.js} +2 -2
  65. package/dist/chunks/{View-C5n3sIFi.js.map → View-Cvs2TY7b.js.map} +1 -1
  66. package/dist/chunks/{WebApp-CeiDNV6L.js → WebApp-DuwanN2O.js} +2 -2
  67. package/dist/chunks/{WebApp-CeiDNV6L.js.map → WebApp-DuwanN2O.js.map} +1 -1
  68. package/dist/chunks/{WebApp-irKlhuFX.js → WebApp-kbRq7dM_.js} +2 -2
  69. package/dist/chunks/{WebApp-irKlhuFX.js.map → WebApp-kbRq7dM_.js.map} +1 -1
  70. package/dist/chunks/{admin-B5tf0zOO.js → admin-CszsTA0T.js} +2 -2
  71. package/dist/chunks/{admin-B5tf0zOO.js.map → admin-CszsTA0T.js.map} +1 -1
  72. package/dist/chunks/{admin-CGoTpXfs.js → admin-vsKDrnpV.js} +2 -2
  73. package/dist/chunks/{admin-CGoTpXfs.js.map → admin-vsKDrnpV.js.map} +1 -1
  74. package/dist/chunks/{exportChart-kQ-we4Cp.js → exportChart-Bkxr7mCe.js} +2 -2
  75. package/dist/chunks/{exportChart-kQ-we4Cp.js.map → exportChart-Bkxr7mCe.js.map} +1 -1
  76. package/dist/chunks/{exportChart-BTJBYkOz.js → exportChart-Dn2pioNl.js} +2 -2
  77. package/dist/chunks/{exportChart-BTJBYkOz.js.map → exportChart-Dn2pioNl.js.map} +1 -1
  78. package/dist/chunks/{index-BNjCQA7q.js → index-BCWkcyOy.js} +2 -2
  79. package/dist/chunks/{index-BNjCQA7q.js.map → index-BCWkcyOy.js.map} +1 -1
  80. package/dist/chunks/{index-DBsIDOAa.js → index-CJeTVskY.js} +2 -2
  81. package/dist/chunks/{index-DBsIDOAa.js.map → index-CJeTVskY.js.map} +1 -1
  82. package/dist/chunks/{version-BURwX10Q.js → version-CRFysUYb.js} +2 -2
  83. package/dist/chunks/{version-BURwX10Q.js.map → version-CRFysUYb.js.map} +1 -1
  84. package/dist/chunks/{version-CYGIXntv.js → version-uUvnEzFR.js} +2 -2
  85. package/dist/chunks/{version-CYGIXntv.js.map → version-uUvnEzFR.js.map} +1 -1
  86. package/dist/core.css +134 -109
  87. package/dist/css/web-mojo.css +1 -1
  88. package/dist/docit.cjs.js +1 -1
  89. package/dist/docit.es.js +1 -1
  90. package/dist/index.cjs.js +1 -1
  91. package/dist/index.cjs.js.map +1 -1
  92. package/dist/index.es.js +1 -1
  93. package/dist/index.es.js.map +1 -1
  94. package/dist/lightbox.cjs.js +1 -1
  95. package/dist/lightbox.es.js +1 -1
  96. package/dist/map.cjs.js +1 -1
  97. package/dist/map.es.js +1 -1
  98. package/dist/portal.css +32 -0
  99. package/dist/timeline.cjs.js +1 -1
  100. package/dist/timeline.es.js +1 -1
  101. package/dist/user-profile.cjs.js +1 -1
  102. package/dist/user-profile.es.js +1 -1
  103. package/dist/web-mojo.lite.iife.js +33 -9
  104. package/dist/web-mojo.lite.iife.js.map +1 -1
  105. package/dist/web-mojo.lite.iife.min.js +5 -5
  106. package/dist/web-mojo.lite.iife.min.js.map +1 -1
  107. package/package.json +1 -1
  108. package/dist/chunks/Modal-DBJU16cc.js.map +0 -1
  109. package/dist/chunks/Modal-DuULCMFZ.js.map +0 -1
  110. package/dist/chunks/TokenManager-CcQFvaFD.js +0 -2
  111. package/dist/chunks/TokenManager-CcQFvaFD.js.map +0 -1
  112. package/dist/chunks/TokenManager-DEWZqbuo.js +0 -2
  113. package/dist/chunks/TokenManager-DEWZqbuo.js.map +0 -1
@@ -1,2 +1,2 @@
1
- "use strict";const t=new class{constructor(){this.formatters=/* @__PURE__ */new Map,this.registerBuiltInFormatters()}escapeHtml(t){if(null==t)return"";const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;"};return String(t).replace(/[&<>"']/g,t=>e[t])}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",t=>{if(null==t||""===t)return t;const e=parseFloat(t);return isNaN(e)?t:1e3*e}),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",t=>String(t).toUpperCase()),this.register("lowercase",t=>String(t).toLowerCase()),this.register("upper",t=>String(t).toUpperCase()),this.register("lower",t=>String(t).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",t=>this.boolean(t,"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",t=>t),this.register("custom",(t,e)=>"function"==typeof e?e(t):t),this.register("iter",this.iter.bind(this)),this.register("keys",t=>t&&"object"==typeof t&&!Array.isArray(t)?Object.keys(t):null),this.register("values",t=>t&&"object"==typeof t&&!Array.isArray(t)?Object.values(t):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",t=>`<pre class="bg-light p-2 rounded border">${this.escapeHtml(String(t))}</pre>`)}relative_short(t){return this.relative(t,!0)}linkify(t,e={}){if(null==t)return"";const r=String(t),s=this.escapeHtml(r),i={urls:!0,emails:!0,target:"_blank",rel:"noopener noreferrer"},n=e&&"object"==typeof e?{...i,...e}:i;let a=s;if(!1!==n.urls){const t=/(^|\s)((?:https?:\/\/|www\.)[^\s<]+)/gi;a=a.replace(t,(t,e,r)=>`${e}<a href="${r.startsWith("www.")?`https://${r}`:r}" target="${n.target}" rel="${n.rel}">${r}</a>`)}if(!1!==n.emails){const t=/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;a=a.replace(t,t=>`<a href="mailto:${t}">${t}</a>`)}return a}clipboard(t,e="text"){if(null==t)return"";const r=String(t),s=this.escapeHtml(r);return`\n <span class="mojo-clipboard d-inline-flex align-items-center">\n ${"icon-only"!==e?`<span class="font-monospace">${s}</span>`:""}\n ${`\n <button type="button"\n class="btn btn-sm btn-outline-secondary ms-1 p-0 border-0 bg-transparent"\n title="Copy"\n data-bs-toggle="tooltip"\n data-action="copy-to-clipboard"\n data-clipboard="${s}">\n <i class="bi bi-clipboard"></i>\n </button>`.trim()}\n </span>\n `}nl2br(t){return null==t?"":this.escapeHtml(String(t)).replace(/\r\n|\r|\n/g,"<br>")}code(t,e=""){return null==t?"":`<pre class="bg-light p-2 rounded border"><code class="${e?`language-${this.escapeHtml(String(e))}`:""}">${this.escapeHtml(String(t))}</code></pre>`}register(t,e){if("function"!=typeof e)throw new Error("Formatter must be a function, got "+typeof e);return this.formatters.set(t.toLowerCase(),e),this}apply(t,e,...r){try{const s=this.formatters.get(t.toLowerCase());return s?s(e,...r):(console.warn(`Formatter '${t}' not found`),e)}catch(s){return console.error(`Error in formatter '${t}':`,s),e}}pipe(t,e,r=null){return e?this.parsePipeString(e,r).reduce((t,e)=>this.apply(e.name,t,...e.args),t):t}parsePipeString(t,e=null){const r=[],s=t.split("|").map(t=>t.trim());for(const i of s){const t=this.parseFormatter(i,e);t&&r.push(t)}return r}parseFormatter(t,e=null){const r=t.match(/^([a-zA-Z_]\w*)\s*\((.*)\)$/);if(r){const[,t,s]=r;return{name:t,args:s?this.parseArguments(s,e):[]}}const s=t.match(/^([a-zA-Z_]\w*)(?::(.+))?$/);if(s){const[,t,r]=s;return{name:t,args:r?this.parseColonArguments(r,e):[]}}return null}parseArguments(t,e=null){const r=[];let s="",i=!1,n=null,a=0;for(let o=0;o<t.length;o++){const l=t[o];i||'"'!==l&&"'"!==l?i&&l===n&&"\\"!==t[o-1]?(i=!1,n=null,s+=l):i||"{"!==l?i||"}"!==l?i||0!==a||","!==l?s+=l:(r.push(this.parseValue(s.trim(),e)),s=""):(a--,s+=l):(a++,s+=l):(i=!0,n=l,s+=l)}return s.trim()&&r.push(this.parseValue(s.trim(),e)),r}parseColonArguments(t,e=null){const r=[];let s="",i=!1,n=null;for(let a=0;a<t.length;a++){const o=t[a];i||'"'!==o&&"'"!==o?i&&o===n&&"\\"!==t[a-1]?(i=!1,n=null,s+=o):i||":"!==o?s+=o:(r.push(this.parseValue(s.trim(),e)),s=""):(i=!0,n=o,s+=o)}return s.trim()&&r.push(this.parseValue(s.trim(),e)),r}parseValue(t,e=null){if(t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'"))return t.slice(1,-1);if("true"===t)return!0;if("false"===t)return!1;if("null"===t)return null;if("undefined"!==t){if(!isNaN(t)&&""!==t)return Number(t);if(t.startsWith("{")&&t.endsWith("}"))try{return JSON.parse(t)}catch(r){}if(e&&this.isIdentifier(t)){if(!t.includes(".")&&Object.prototype.hasOwnProperty.call(e,t))return e[t];if(e.get&&"function"==typeof e.get){const r=e.get(t);if(void 0!==r)return r}if(e.getContextValue&&"function"==typeof e.getContextValue){const r=e.getContextValue(t);if(void 0!==r)return r}if(t.includes(".")){const r=window.MOJOUtils||("undefined"!=typeof require?require("./MOJOUtils.js").default:null);if(r){const s=r.getNestedValue(e,t);if(void 0!==s)return s}}}return t}}isIdentifier(t){return/^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/.test(t)}date(t,e="MM/DD/YYYY"){if(!t)return"";let r;if((t=this.normalizeEpoch(t))instanceof Date)r=t;else if("string"==typeof t)if(/^\d{4}-\d{2}-\d{2}$/.test(t)){const[e,s,i]=t.split("-").map(Number);r=new Date(e,s-1,i)}else r=new Date(t);else r=new Date(t);if(isNaN(r.getTime()))return String(t);const s={YYYY:r.getFullYear(),YY:String(r.getFullYear()).slice(-2),MMMM:r.toLocaleDateString("en-US",{month:"long"}),MMM:r.toLocaleDateString("en-US",{month:"short"}),MM:String(r.getMonth()+1).padStart(2,"0"),M:r.getMonth()+1,dddd:r.toLocaleDateString("en-US",{weekday:"long"}),ddd:r.toLocaleDateString("en-US",{weekday:"short"}),DD:String(r.getDate()).padStart(2,"0"),D:r.getDate()};let i=e;const n=new RegExp(`(${Object.keys(s).join("|")})`,"g");return i=i.replace(n,t=>s[t]||t),i}time(t,e="HH:mm:ss"){if(!t)return"";const r=(t=this.normalizeEpoch(t))instanceof Date?t:new Date(t);if(isNaN(r.getTime()))return String(t);const s=r.getHours(),i={HH:String(s).padStart(2,"0"),H:s,hh:String(s%12||12).padStart(2,"0"),h:s%12||12,mm:String(r.getMinutes()).padStart(2,"0"),m:r.getMinutes(),ss:String(r.getSeconds()).padStart(2,"0"),s:r.getSeconds(),A:s>=12?"PM":"AM",a:s>=12?"pm":"am"};let n=e;const a=Object.keys(i).sort((t,e)=>e.length-t.length);for(const o of a)n=n.replace(new RegExp(o,"g"),i[o]);return n}datetime(t,e="MM/DD/YYYY",r="HH:mm:ss"){t=this.normalizeEpoch(t);const s=this.date(t,e),i=this.time(t,r);return s&&i?`${s} ${i}`:""}datetime_tz(t,e="MM/DD/YYYY",r="HH:mm:ss",s={}){if(!t)return"";const i=(t=this.normalizeEpoch(t))instanceof Date?t:new Date(t);if(isNaN(i.getTime()))return String(t);const n=s&&s.locale||"en-US",a=s&&s.timeZone?s.timeZone:void 0,o=()=>{let t="";try{const r=new Intl.DateTimeFormat(n,{hour:"2-digit",minute:"2-digit",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(i).find(t=>"timeZoneName"===t.type);if(t=r?r.value:"",t&&/^GMT[+-]/i.test(t))try{const e=new Intl.DateTimeFormat(n,{timeStyle:"short",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(i).find(t=>"timeZoneName"===t.type);e&&e.value&&!/^GMT[+-]/i.test(e.value)&&(t=e.value)}catch(e){}if(t&&/\s/.test(t)){const e=t.split(/\s+/).map(t=>t[0]).join("").toUpperCase();e.length>=2&&e.length<=4&&(t=e)}}catch(e){t=""}return t};if(!a){const t=this.date(i,e),s=this.time(i,r),n=o();return t&&s?`${t} ${s} ${n}`.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(i),c=t=>{const e=l.find(e=>e.type===t);return e?e.value:""},h=c("year"),u=c("month"),d=c("day"),g=c("hour"),m=c("minute"),p=c("second"),f=u?String(parseInt(u,10)):"",b=d?String(parseInt(d,10)):"",y=g?String(parseInt(g,10)):"",w=g?parseInt(g,10)%12||12:"",S=g?parseInt(g,10)>=12?"PM":"AM":"",$=S?S.toLowerCase():"",x=new Intl.DateTimeFormat(n,{timeZone:a,month:"long"}).format(i),M=new Intl.DateTimeFormat(n,{timeZone:a,month:"short"}).format(i),_=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"long"}).format(i),C=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"short"}).format(i),A={YYYY:h,YY:h?h.slice(-2):"",MMMM:x,MMM:M,MM:u,M:f,dddd:_,ddd:C,DD:d,D:b},T={HH:g,H:y,hh:""!==w?String(w).padStart(2,"0"):"",h:""!==w?String(w):"",mm:m,m:m?String(parseInt(m,10)):"",ss:p,s:p?String(parseInt(p,10)):"",A:S,a:$},N=(t,e)=>{if(!t)return"";const r=new RegExp(`(${Object.keys(e).sort((t,e)=>e.length-t.length).join("|")})`,"g");return t.replace(r,t=>e[t]??t)},D=N(e,A),v=N(r,T),O=o();return D&&v?`${D} ${v} ${O}`.trim():""}normalizeEpoch(t){if(t instanceof Date)return t;if("string"==typeof t){const e=Number(t);if(!Number.isFinite(e)){const e=Date.parse(t);return Number.isFinite(e)?e:""}t=e}else"number"!=typeof t&&(t=Number(t));if(isNaN(t))return"";if(t<1e11)return 1e3*t;if(t>1e12&&t<1e13)return t;throw new Error("Value doesn't look like epoch seconds or ms")}date_range(t,e=null,r="MM/DD/YYYY"){if(!t)return"";const s=e||/* @__PURE__ */new Date,i=this.date(t,r),n=this.date(s,r);return i&&n?`${i} - ${n}`:""}datetime_range(t,e=null,r="MM/DD/YYYY",s="HH:mm"){if(!t)return"";const i=e||/* @__PURE__ */new Date,n=this.datetime(t,r,s),a=this.datetime(i,r,s);return n&&a?`${n} - ${a}`:""}relative(t,e=!1){if(!t)return"";const r=(t=this.normalizeEpoch(t))instanceof Date?t:new Date(t);if(isNaN(r.getTime()))return String(t);const s=r-/* @__PURE__ */new Date,i=Math.abs(s),n=Math.floor(i/1e3),a=Math.floor(n/60),o=Math.floor(a/60),l=Math.floor(o/24),c=s>0;if(e)return l>365?Math.floor(l/365)+"y":l>30?Math.floor(l/30)+"mo":l>7?Math.floor(l/7)+"w":l>0?l+"d":o>0?o+"h":a>0?a+"m":"now";if(l>365){const t=Math.floor(l/365);return(c?"in ":"")+t+" year"+(t>1?"s":"")+(c?"":" ago")}if(l>30){const t=Math.floor(l/30);return(c?"in ":"")+t+" month"+(t>1?"s":"")+(c?"":" ago")}if(l>7){const t=Math.floor(l/7);return(c?"in ":"")+t+" week"+(t>1?"s":"")+(c?"":" ago")}return 1===l?c?"tomorrow":"yesterday":l>0?(c?"in ":"")+l+" days"+(c?"":" ago"):o>0?(c?"in ":"")+o+" hour"+(o>1?"s":"")+(c?"":" ago"):a>0?(c?"in ":"")+a+" minute"+(a>1?"s":"")+(c?"":" ago"):n>30?(c?"in ":"")+n+" seconds"+(c?"":" ago"):"just now"}iso(t,e=!1){if(!t)return"";const r=(t=this.normalizeEpoch(t))instanceof Date?t:new Date(t);return isNaN(r.getTime())?String(t):e?r.toISOString().split("T")[0]:r.toISOString()}number(t,e=2,r="en-US"){const s=parseFloat(t);return isNaN(s)?String(t):s.toLocaleString(r,{minimumFractionDigits:e,maximumFractionDigits:e})}currency(t,e="$",r=2){const s=parseInt(t);if(isNaN(s))return String(t);const i=Math.abs(s).toString(),n=s<0?"-":"";let a,o,l;return i.length<=2?(a="0",o=i.padStart(2,"0")):(a=i.slice(0,-2),o=i.slice(-2)),a=a.replace(/\B(?=(\d{3})+(?!\d))/g,","),0===r?(parseInt(o)>=50&&(a=(parseInt(a.replace(/,/g,""))+1).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")),l=a):l=2===r?`${a}.${o}`:`${a}.${o.slice(0,r).padEnd(r,"0")}`,n+e+l}percent(t,e=0,r=!0){const s=parseFloat(t);if(isNaN(s))return String(t);const i=r?100*s:s;return this.number(i,e)+"%"}filesize(t,e=!1,r=1){const s=parseInt(t);if(isNaN(s))return String(t);const i=e?["B","KiB","MiB","GiB","TiB"]:["B","KB","MB","GB","TB"],n=e?1024:1e3;let a=s,o=0;for(;a>=n&&o<i.length-1;)a/=n,o++;const l=0===o?0:r;return`${a.toFixed(l)} ${i[o]}`}ordinal(t,e=!1){const r=parseInt(t);if(isNaN(r))return String(t);const s=r%10,i=r%100;let n="th";return 1===s&&11!==i?n="st":2===s&&12!==i?n="nd":3===s&&13!==i&&(n="rd"),e?n:r+n}compact(t,e=1){const r=parseFloat(t);if(isNaN(r))return String(t);const s=Math.abs(r),i=r<0?"-":"";return s>=1e9?i+(s/1e9).toFixed(e)+"B":s>=1e6?i+(s/1e6).toFixed(e)+"M":s>=1e3?i+(s/1e3).toFixed(e)+"K":String(r)}add(t,e){const r=parseFloat(t),s=parseFloat(e);return isNaN(r)||isNaN(s)?t:r+s}subtract(t,e){const r=parseFloat(t),s=parseFloat(e);return isNaN(r)||isNaN(s)?t:r-s}multiply(t,e){const r=parseFloat(t),s=parseFloat(e);return isNaN(r)||isNaN(s)?t:r*s}divide(t,e){const r=parseFloat(t),s=parseFloat(e);return isNaN(r)||isNaN(s)||0===s?t:r/s}capitalize(t,e=!0){const r=String(t);return r?e?r.replace(/\b\w/g,t=>t.toUpperCase()):r.charAt(0).toUpperCase()+r.slice(1):""}replace(t,e,r="",s="g"){if(null==t)return"";const i=String(t);if(null==e||""===e)return i;if(e instanceof RegExp)return i.replace(e,String(r));const n=String(e),a=n.match(/^\/(.+)\/([a-z]*)$/i);if(a){const[,t,e]=a;try{return i.replace(new RegExp(t,e),String(r))}catch(o){}}return String(s).includes("g")?i.split(n).join(String(r)):i.replace(n,String(r))}truncate(t,e=50,r="..."){const s=String(t);return s.length<=e?s:s.substring(0,e)+r}truncate_front(t,e=8,r="..."){const s=String(t);return s.length<=e?s:`${r}${s.slice(-e)}`}truncate_middle(t,e=8,r="***"){const s=String(t);if(s.length<=e)return s;const i=Math.floor(e/2);return`${s.substring(0,i)}${r}${s.substring(s.length-i)}`}slug(t,e="-"){return String(t).toLowerCase().replace(/[^\w\s-]/g,"").replace(/\s+/g,e).replace(new RegExp(`${e}+`,"g"),e).replace(new RegExp(`^${e}|${e}$`,"g"),"")}initials(t,e=2){return String(t).split(/\s+/).filter(t=>t.length>0).slice(0,e).map(t=>t.charAt(0).toUpperCase()).join("")}mask(t,e="*",r=4){const s=String(t);return s.length<=r?s:e.repeat(Math.max(0,s.length-r))+s.slice(-r)}email(t,e={}){const r=String(t).trim();return r?!1===e.link?r:`<a href="mailto:${r}${e.subject?`?subject=${encodeURIComponent(e.subject)}`:""}${e.body?`&body=${encodeURIComponent(e.body)}`:""}"${e.class?` class="${e.class}"`:""}>${r}</a>`:""}phone(t,e="US",r=!0){let s=String(t).replace(/\D/g,""),i=s;return"US"===e&&(10===s.length?i=`(${s.slice(0,3)}) ${s.slice(3,6)}-${s.slice(6)}`:11===s.length&&"1"===s[0]&&(i=`+1 (${s.slice(1,4)}) ${s.slice(4,7)}-${s.slice(7)}`)),r?`<a href="tel:${s}">${i}</a>`:i}url(t,e=null,r=!0){let s=String(t).trim();return s?(/^https?:\/\//.test(s)||(s="https://"+s),`<a href="${s}"${r?' target="_blank"':""}${r?' rel="noopener noreferrer"':""}>${e||s}</a>`):""}badge(t,e="auto"){if(Array.isArray(t))return t.map(t=>this.badge(t,e)).join(" ");const r=String(t);if("string"==typeof e&&e.includes("=")){const t=Object.fromEntries(e.split(",").map(t=>t.split("=").map(t=>t.trim()))),s=t[r]||t[r.toLowerCase()]||this.inferBadgeType(r);return`<span class="badge ${s?`bg-${s}`:"bg-secondary"}">${r}</span>`}const s="auto"===e?this.inferBadgeType(r):e;return`<span class="badge ${s?`bg-${s}`:"bg-secondary"}">${r}</span>`}badgeClass(t,e="auto"){const r=String(t),s="auto"===e?this.inferBadgeType(r):e;return s?`bg-${s}`:"bg-secondary"}inferBadgeType(t){const e=t.toLowerCase();return["active","pass","success","complete","completed","approved","done","true","on","yes"].includes(e)?"success":["error","failed","fail","rejected","deleted","cancelled","false","off","no","declined"].includes(e)?"danger":["warning","pending","review","processing","uploading"].includes(e)?"warning":["info","new","draft"].includes(e)?"info":(["inactive","disabled","archived","suspended"].includes(e),"secondary")}status(t){return this._status(t)}status_icon(t){return this._status(t,{},{},!1,!0)}status_text(t){return this._status(t,{},{},!0,!1)}_status(t,e={},r={},s=!1,i=!1){const n=String(t).toLowerCase(),a=e[n]||{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"}[n]||"";let o="";!s&&a&&(o=`<i class="${a}"></i>`);let l="";return i||(l=t),`<span class="text-${r[n]||{active:"success",approved:"success",declined:"danger",inactive:"secondary",pending:"warning",success:"success",error:"danger",warning:"warning"}[n]||"secondary"}">${o}${o?" ":""}${l}</span>`}boolean(t,e="True",r="False",s=!1){const i=t?e:r;return s?`<span class="text-${t?"success":"danger"}">${i}</span>`:i}bool(t){return!(null==t||0===t||""===t||!1===t||"false"===t||!0!==t&&"true"!==t&&(Array.isArray(t)&&0===t.length||t&&"object"==typeof t&&t.constructor===Object&&0===Object.keys(t).length))}icon(t,e={}){const r=e[String(t).toLowerCase()]||"";return r?`<i class="${r}"></i>`:""}yesnoicon(t,e="bi bi-check-circle-fill text-success",r="bi bi-x-circle-fill text-danger"){return t?`<i class="${e}"></i>`:`<i class="${r}"></i>`}image(t,e="thumbnail",r="img-fluid",s=""){const i=this._extractImageUrl(t,e);return i?`<img src="${i}" class="${r}" alt="${s}" />`:""}avatar(t,e="md",r="rounded-circle",s=""){const i=this._extractImageUrl(t,"square_sm")||"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI2NlZDRkYSI+PHBhdGggZD0iTTEyIDEyYzIuMjEgMCA0LTEuNzkgNC00cy0xLjc5LTQtNC00LTQgMS43OS00IDQgMS43OSA0IDQgNHptMCAyYy0yLjY3IDAtOCAxLjM0LTggNHYyaDE2di0yYzAtMi42Ni01LjMzLTQtOC00eiIvPjwvc3ZnPg==",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[e]||n.md;return`<img src="${i}" class="${`object-fit-cover ${r}`.trim()}" style="${a}" alt="${s}" />`}tooltip(t,e="",r="top",s=""){if(null==t)return"";const i=String(t);return`<span data-bs-toggle="tooltip" data-bs-placement="${r}" ${"html"===s?'data-bs-html="true"':""} data-bs-title="${"html"===s?e:this.escapeHtml(e)}">${i}</span>`}_extractImageUrl(t,e="thumbnail"){if(!t)return null;if("string"==typeof t)return t;if("object"==typeof t){if(t.attributes&&(t=t.attributes),"thumbnail"===e&&t.thumbnail&&"string"==typeof t.thumbnail)return t.thumbnail;if(t.renditions&&"object"==typeof t.renditions){const r=t.renditions[e];if(r&&r.url)return r.url;const s=Object.values(t.renditions);if(s.length>0&&s[0].url)return s[0].url}if(t.url)return t.url}return null}default(t,e=""){return null==t||""===t?e:t}equals(t,e,r,s=""){return t==e?r:s}plural(t,e,r=null,s=!0){if(null==t||null==e)return s?`${t} ${e}`:e||"";const i=parseInt(t);if(isNaN(i))return s?`${t} ${e}`:e||"";const n=1===Math.abs(i)?e:r||e+"s";return s?`${i} ${n}`:n}formatList(t,e={}){if(!Array.isArray(t))return String(t);const{conjunction:r="and",limit:s=null,moreText:i="others"}=e;if(0===t.length)return"";if(1===t.length)return String(t[0]);let n=t.slice(),a=!1;if(s&&t.length>s&&(n=t.slice(0,s),a=!0),a){const e=t.length-s;return`${n.join(", ")}, ${r} ${e} ${i}`}return 2===n.length?`${n[0]} ${r} ${n[1]}`:`${n.slice(0,-1).join(", ")}, ${r} ${n[n.length-1]}`}duration(t,e="ms",r=!1,s=2){if(null==t)return"";const i=parseFloat(t);if(isNaN(i))return String(t);let n;switch(e){case"s":case"sec":case"seconds":n=1e3*i;break;case"m":case"min":case"minutes":n=6e4*i;break;case"h":case"hr":case"hours":n=36e5*i;break;case"d":case"day":case"days":n=864e5*i;break;default:n=i}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(0===n)return r?"0s":"0 seconds";const o=Math.abs(n),l=n<0?"-":"",c=[];let h=o;for(const u of a)if(h>=u.value){const t=Math.floor(h/u.value);h%=u.value;const e=r?u.short:1===t?u.name:u.name+"s";if(c.push(r?`${t}${e}`:`${t} ${e}`),c.length>=s)break}return 0===c.length?r?`${Math.round(o)}ms`:`${Math.round(o)} milliseconds`:l+(r?c.join(""):c.join(" "))}hash(t,e=8,r="",s="..."){if(null==t)return"";const i=String(t);return i.length<=e?r+i:r+i.substring(0,e)+s}stripHtml(t){return null==t?"":String(t).replace(/<[^>]*>/g,"")}highlight(t,e,r="highlight"){if(null==t||!e)return String(t||"");const s=String(e).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),i=new RegExp(`(${s})`,"gi");return String(t).replace(i,`<mark class="${r}">$1</mark>`)}hex(t,e=!1,r=!1){if(null==t)return"";let s="";const i=t=>Array.from(t).map(t=>t.toString(16).padStart(2,"0")).join("");if("number"==typeof t){let e=Math.abs(Math.trunc(t)).toString(16);e.length%2&&(e="0"+e),s=e}else s=t instanceof Uint8Array?i(t):t instanceof ArrayBuffer?i(new Uint8Array(t)):Array.isArray(t)&&t.every(t=>"number"==typeof t)?i(Uint8Array.from(t.map(t=>255&t))):i((new TextEncoder).encode(String(t)));return e&&(s=s.toUpperCase()),(r?"0x":"")+s}unhex(t){if(null==t)return"";let e=String(t).trim();if((e.startsWith("0x")||e.startsWith("0X"))&&(e=e.slice(2)),e=e.replace(/\s+/g,""),0===e.length)return"";e.length%2!=0&&(e="0"+e);const r=new Uint8Array(e.length/2);for(let i=0;i<e.length;i+=2){const s=parseInt(e.slice(i,i+2),16);if(Number.isNaN(s))return String(t);r[i/2]=s}try{return(new TextDecoder).decode(r)}catch(s){let t="";for(const e of r)t+=String.fromCharCode(e);return t}}json(t,e=2){try{return JSON.stringify(t,null,e)}catch(r){return String(t)}}has(t){return this.formatters.has(t.toLowerCase())}unregister(t){return this.formatters.delete(t.toLowerCase())}listFormatters(){return Array.from(this.formatters.keys()).sort()}iter(t){return null==t?[]:Array.isArray(t)?t:"object"==typeof t?Object.entries(t).map(([t,e])=>({key:t,value:e})):[{key:"0",value:t}]}};window.dataFormatter=t;class MOJOUtils{static getContextData(e,r){if(!r||null==e)return;let s=r,i="",n=0,a=-1;for(let t=0;t<r.length;t++){const e=r[t];if("("===e)n++;else if(")"===e)n--;else if("|"===e&&0===n){a=t;break}}a>-1&&(s=r.substring(0,a).trim(),i=r.substring(a+1).trim());const o=this.getNestedValue(e,s);return i?t.pipe(o,i,e):o}static getNestedValue(t,e){if(!e||null==t)return;if(!e.includes(".")){if(e in t){const r=t[e];return"function"==typeof r?r.call(t):r}return}const r=e.split(".");let s=t;for(let i=0;i<r.length;i++){const e=r[i];if(null==s)return;if(0===i){if(!s.hasOwnProperty(e))return;{const r=s[e];s="function"==typeof r?r.call(t):r}}else{if(s&&"function"==typeof s.getContextValue){const t=r.slice(i).join(".");return s.getContextValue(t)}if(Array.isArray(s)&&!isNaN(e))s=s[parseInt(e)];else if(s.hasOwnProperty(e))s=s[e];else{if("function"!=typeof s[e])return;s=s[e].call(s)}}}return s}static isNullOrUndefined(t){return null==t}static deepClone(t){if(null===t||"object"!=typeof t)return t;if(t instanceof Date)return new Date(t.getTime());if(t instanceof Array)return t.map(t=>this.deepClone(t));if(t instanceof Object){const e={};for(const r in t)t.hasOwnProperty(r)&&(e[r]=this.deepClone(t[r]));return e}}static deepMerge(t,...e){if(!e.length)return t;const r=e.shift();if(this.isObject(t)&&this.isObject(r))for(const s in r)this.isObject(r[s])?(t[s]||Object.assign(t,{[s]:{}}),this.deepMerge(t[s],r[s])):Object.assign(t,{[s]:r[s]});return this.deepMerge(t,...e)}static isObject(t){return t&&"object"==typeof t&&!Array.isArray(t)}static debounce(t,e){let r;return function(...s){clearTimeout(r),r=setTimeout(()=>{clearTimeout(r),t(...s)},e)}}static throttle(t,e){let r;return function(...s){r||(t.apply(this,s),r=!0,setTimeout(()=>r=!1,e))}}static generateId(t=""){const e=Date.now().toString(36),r=Math.random().toString(36).substr(2,9);return t?`${t}_${e}_${r}`:`${e}_${r}`}static escapeHtml(t){const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(t).replace(/[&<>"'`=\/]/g,t=>e[t])}static checkPasswordStrength(t){if(!t||"string"!=typeof t)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 e=[],r={length:t.length,hasLowercase:/[a-z]/.test(t),hasUppercase:/[A-Z]/.test(t),hasNumbers:/[0-9]/.test(t),hasSpecialChars:/[^a-zA-Z0-9]/.test(t),hasCommonPatterns:!1,isCommonPassword:!1};let s=0;t.length<6?e.push("Password should be at least 6 characters long"):t.length<8?(s+=1,e.push("Consider using at least 8 characters for better security")):t.length<12?s+=3:s+=4,r.hasLowercase?s+=1:e.push("Include lowercase letters"),r.hasUppercase?s+=1:e.push("Include uppercase letters"),r.hasNumbers?s+=1:e.push("Include numbers"),r.hasSpecialChars?s+=2:e.push("Include special characters (!@#$%^&* etc.)");const i=[/123/,/abc/i,/qwerty/i,/asdf/i,/(.)\1{2,}/,/password/i,/admin/i,/user/i,/login/i];for(const a of i)if(a.test(t)){r.hasCommonPatterns=!0,s-=1,e.push("Avoid common patterns and dictionary words");break}let n;return["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(t.toLowerCase())&&(r.isCommonPassword=!0,s=Math.max(0,s-3),e.push("This password is too common and easily guessed")),n=s<2?"very-weak":s<4?"weak":s<6?"fair":s<8?"good":"strong",s>=7&&0===e.length?e.push("Strong password! Consider using a password manager."):s>=5&&e.length<=1&&e.push("Good password strength. Consider adding more variety."),{score:Math.max(0,s),strength:n,feedback:e,details:r}}static generatePassword(t={}){const e={length:12,includeLowercase:!0,includeUppercase:!0,includeNumbers:!0,includeSpecialChars:!0,customChars:"",excludeAmbiguous:!1,...t};if(e.length<4)throw new Error("Password length must be at least 4 characters");let r="abcdefghijklmnopqrstuvwxyz",s="ABCDEFGHIJKLMNOPQRSTUVWXYZ",i="0123456789",n="!@#$%^&*()_+-=[]{}|;:,.<>?";e.excludeAmbiguous&&(r=r.replace(/[il]/g,""),s=s.replace(/[IOL]/g,""),i=i.replace(/[01]/g,""),n=n.replace(/[|]/g,""));let a="";const o=[];if(e.customChars?a=e.customChars:(e.includeLowercase&&(a+=r,o.push(r[Math.floor(Math.random()*r.length)])),e.includeUppercase&&(a+=s,o.push(s[Math.floor(Math.random()*s.length)])),e.includeNumbers&&(a+=i,o.push(i[Math.floor(Math.random()*i.length)])),e.includeSpecialChars&&(a+=n,o.push(n[Math.floor(Math.random()*n.length)]))),!a)throw new Error("No character types selected for password generation");let l="";for(const c of o)l+=c;for(let c=l.length;c<e.length;c++)l+=a[Math.floor(Math.random()*a.length)];return l.split("").sort(()=>Math.random()-.5).join("")}static parseQueryString(t){const e={},r=new URLSearchParams(t);for(const[s,i]of r.entries())e[s]=i;return e}static toQueryString(t){return new URLSearchParams(t).toString()}static wrapData(t,e=null,r=3){return t&&"object"==typeof t?t instanceof Date||t instanceof RegExp||t instanceof Error||r<=0||"function"==typeof t.getContextValue?t:Array.isArray(t)?t.map(t=>t&&"object"==typeof t&&!t.getContextValue?new DataWrapper(t,e):t):new DataWrapper(t,e):t}}class DataWrapper{constructor(t,e=null){if(Object.defineProperty(this,"_data",{value:t,writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(this,"_rootContext",{value:e,writable:!1,enumerable:!1,configurable:!1}),t&&"object"==typeof t)for(const r in t)if(t.hasOwnProperty(r)){const s=t[r];this[r]=MOJOUtils.wrapData(s,e)}}getContextValue(e){let r,s=e,i="",n=0,a=-1;for(let t=0;t<e.length;t++){const r=e[t];if("("===r)n++;else if(")"===r)n--;else if("|"===r&&0===n){a=t;break}}return a>-1&&(s=e.substring(0,a).trim(),i=e.substring(a+1).trim()),r=s in this&&"_data"!==s&&"_rootContext"!==s?this[s]:MOJOUtils.getNestedValue(this._data,s),i&&void 0!==r?t.pipe(r,i,this._rootContext||this._data):r}has(t){return this._data&&this._data.hasOwnProperty(t)}toJSON(){return this._data}}MOJOUtils.DataWrapper=DataWrapper,"undefined"!=typeof window&&(window.utils=MOJOUtils);const e={on(t,e,r){this._listeners||(this._listeners={}),this._listeners[t]||(this._listeners[t]=[]);const s={callback:e,context:r,fn:r?e.bind(r):e};return this._listeners[t].push(s),this},off(t,e,r){return this._listeners&&this._listeners[t]?(e?(this._listeners[t]=this._listeners[t].filter(t=>t.callback!==e||3===arguments.length&&t.context!==r),0===this._listeners[t].length&&delete this._listeners[t]):delete this._listeners[t],this):this},once(t,e,r){const s=(...i)=>{this.off(t,s),(r?e.bind(r):e).apply(r||this,i)};return this.on(t,s),this},emit(t,...e){if(!this._listeners||!this._listeners[t])return this;const r=this._listeners[t].slice();for(const i of r)try{i.fn.apply(i.context||this,e)}catch(s){console&&console.error&&console.error(`Error in ${t} event handler:`,s)}return this}},r=new class{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 t="mojo_device_uid";try{let e=localStorage.getItem(t);e?this.duid=e:(this.duid=this._generateDuid(),localStorage.setItem(t,this.duid))}catch(e){console.error("Could not access localStorage to get/set DUID.",e),this.duid=this._generateDuid()}}_generateDuid(){return crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){const e=16*Math.random()|0;return("x"===t?e:3&e|8).toString(16)})}configure(t){t.baseUrl&&(t.baseURL=t.baseUrl);const e=this.config.trackDevice;this.config={...this.config,...t,headers:{...this.config.headers,...t.headers}},this.config.trackDevice&&!e&&this._initializeDuid()}addInterceptor(t,e){this.interceptors[t]&&this.interceptors[t].push(e)}buildUrl(t){return t.startsWith("http://")||t.startsWith("https://")?t:`${this.config.baseURL.endsWith("/")?this.config.baseURL.slice(0,-1):this.config.baseURL}${t.startsWith("/")?t:`/${t}`}`}categorizeError(t,e=0){if("TypeError"===t.name&&t.message.includes("fetch"))return{reason:"not_reachable",message:"Service is not reachable - please check your connection"};if("AbortError"===t.name)return{reason:"cancelled",message:"Request was cancelled"};if("TimeoutError"===t.name||t.message.includes("timeout"))return{reason:"timed_out",message:"Request timed out - please try again"};if(e>=400){if(400===e)return{reason:"bad_request",message:"Invalid request data"};if(401===e)return{reason:"unauthorized",message:"Authentication required"};if(403===e)return{reason:"forbidden",message:"Access denied"};if(404===e)return{reason:"not_found",message:"Resource not found"};if(409===e)return{reason:"conflict",message:"Resource conflict"};if(422===e)return{reason:"validation_error",message:"Validation failed"};if(429===e)return{reason:"rate_limited",message:"Too many requests - please wait"};if(e>=500)return{reason:"server_error",message:"Server error - please try again later"};if(e>=400)return{reason:"client_error",message:"Request error"}}return t.message.includes("CORS")?{reason:"cors_error",message:"Cross-origin request blocked"}:t.message.includes("DNS")||t.message.includes("ENOTFOUND")?{reason:"dns_error",message:"Unable to resolve server address"}:{reason:"unknown_error",message:`Network error: ${t.message}`}}buildQueryString(t={}){const e=new URLSearchParams;Object.entries(t).forEach(([t,r])=>{null!=r&&(Array.isArray(r)?r.forEach(r=>e.append(`${t}[]`,r)):e.append(t,r))});const r=e.toString();return r?`?${r}`:""}async processRequestInterceptors(t){let e={...t};for(const s of this.interceptors.request)try{e=await s(e)}catch(r){throw console.error("Request interceptor error:",r),r}return e}async processResponseInterceptors(t,e){let r={success:t.ok,status:t.status,statusText:t.statusText,headers:Object.fromEntries(t.headers.entries()),data:null,errors:null,message:null,reason:null};try{const e=t.headers.get("content-type");if(e&&e.includes("application/json")){const e=await t.json();if(r.data=e,!t.ok){const s=this.categorizeError(new Error("HTTP Error"),t.status);r.errors=e.errors||{},r.message=e.message||s.message,r.reason=s.reason}}else if(r.data=await t.text(),!t.ok){const e=this.categorizeError(new Error("HTTP Error"),t.status);r.message=e.message,r.reason=e.reason}}catch(s){r.errors={parse:"Failed to parse response"},r.message="Invalid response format"}for(const i of this.interceptors.response)try{r=await i(r,e)}catch(s){console.error("Response interceptor error:",s)}return r}async request(t,e,r=null,s={},i={}){let n={method:t.toUpperCase(),url:this.buildUrl(e)+this.buildQueryString(s),headers:{...this.config.headers,...i.headers},data:r,options:{timeout:this.config.timeout,...i}};try{n=await this.processRequestInterceptors(n)}catch(l){if("AuthRequiredError"===l.name)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("header"===this.config.duidTransport)n.headers[this.config.duidHeader]=this.duid;else if("GET"===n.method){const t=new URL(n.url);t.searchParams.append("duid",this.duid),n.url=t.toString()}else!n.data||"object"!=typeof n.data||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]:1===o.length&&(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"]):"object"==typeof n.data?a.body=JSON.stringify(n.data):a.body=n.data);try{const t=await fetch(n.url,a),e=await this.processResponseInterceptors(t,n);return i.dataOnly&&e.data&&"object"==typeof e.data&&"data"in e.data&&(e.message=e.message||e.data.message,e.data=e.data.data),e}catch(l){if("AbortError"===l.name)throw l;const t=this.categorizeError(l),e={success:!1,status:0,statusText:"Network Error",headers:{},data:null,errors:{network:l.message},message:t.message,reason:t.reason},r={ok:!1,status:0,statusText:"Network Error",headers:new Headers,json:async()=>({}),text:async()=>""};return await this.processResponseInterceptors(r,n),e}}async GET(t,e={},r={}){return this.request("GET",t,null,e,r)}async POST(t,e={},r={},s={}){return this.request("POST",t,e,r,s)}async PUT(t,e={},r={},s={}){return this.request("PUT",t,e,r,s)}async PATCH(t,e={},r={},s={}){return this.request("PATCH",t,e,r,s)}async DELETE(t,e={},r={}){return this.request("DELETE",t,null,e,r)}get(...t){return this.GET(...t)}post(...t){return this.POST(...t)}put(...t){return this.PUT(...t)}patch(...t){return this.PATCH(...t)}delete(...t){return this.DELETE(...t)}async download(t,e={},r={}){const s={method:"GET",url:this.buildUrl(t)+this.buildQueryString(e),headers:{...this.config.headers,Accept:"*/*",...r.headers},options:{...r}};delete s.headers["Content-Type"];try{const t=await fetch(s.url,{method:s.method,headers:s.headers,signal:s.options.signal});if(!t.ok)throw new Error(`Download failed: ${t.status} ${t.statusText}`);const e=t.headers.get("content-disposition");let i=r.filename||"download";if(e){const t=e.match(/filename="?(.+)"?/);t&&t.length>1&&(i=t[1])}const n=t.body.getReader(),a=new ReadableStream({start:t=>function e(){return n.read().then(({done:r,value:s})=>{if(!r)return t.enqueue(s),e();t.close()})}()}),o=await new Response(a).blob(),l=window.URL.createObjectURL(o),c=document.createElement("a");return c.style.display="none",c.href=l,c.download=i,document.body.appendChild(c),c.click(),window.URL.revokeObjectURL(l),c.remove(),{success:!0,message:"Download initiated"}}catch(i){return console.error("Download error:",i),{success:!1,message:i.message}}}async downloadBlob(t,e={},r={}){const s={method:"GET",url:this.buildUrl(t)+this.buildQueryString(e),headers:{...this.config.headers,Accept:"*/*",...r.headers},options:{...r}};delete s.headers["Content-Type"];try{const t=await fetch(s.url,{method:s.method,headers:s.headers,signal:s.options.signal});if(!t.ok)throw new Error(`Download failed: ${t.status} ${t.statusText}`);const e=await t.blob(),i=t.headers.get("content-disposition");let n=r.filename||"download";if(i){const t=i.match(/filename="?(.+)"?/);t&&t.length>1&&(n=t[1])}const a=window.URL.createObjectURL(e),o=document.createElement("a");return o.style.display="none",o.href=a,o.download=n,document.body.appendChild(o),o.click(),window.URL.revokeObjectURL(a),o.remove(),{success:!0,message:"Download initiated"}}catch(i){return console.error("Download error:",i),{success:!1,message:i.message}}}async upload(t,e,r={}){return new Promise((s,i)=>{if(!(e instanceof File))return void i(new Error("Only single File objects are supported for legacy backend compatibility"));const n=new XMLHttpRequest;r.onProgress&&"function"==typeof r.onProgress&&(n.upload.onprogress=r.onProgress),n.onload=function(){n.status>=200&&n.status<300?s({data:n.response,status:n.status,statusText:n.statusText,xhr:n}):i(new Error(`Upload failed: ${n.status} ${n.statusText}`))},n.onerror=function(){i(new Error("Upload failed: Network error"))},n.ontimeout=function(){i(new Error("Upload failed: Timeout"))},n.open("PUT",t),n.setRequestHeader("Content-Type",e.type),r.timeout&&(n.timeout=r.timeout),n.send(e)})}async uploadMultipart(t,e,r={},s={}){const i=new FormData;if(e instanceof FileList)Array.from(e).forEach((t,e)=>{i.append(`file_${e}`,t)});else if(e instanceof File)i.append("file",e);else if(e instanceof FormData)return this.POST(t,e,{},s);return Object.entries(r).forEach(([t,e])=>{i.append(t,e)}),this.POST(t,i,{},s)}setAuthToken(t,e="Bearer"){t?this.config.headers.Authorization=`${e} ${t}`:delete this.config.headers.Authorization}clearAuth(){delete this.config.headers.Authorization}isRetryableError(t){return["not_reachable","timed_out","server_error","dns_error"].includes(t.reason)}requiresAuth(t){return"unauthorized"===t.reason}isNetworkError(t){return["not_reachable","timed_out","cancelled","cors_error","dns_error"].includes(t.reason)}getUserMessage(t){return t.message?t.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."}[t.reason]||"An error occurred. Please try again."}};class Model{constructor(t={},e={}){this.endpoint=e.endpoint||this.constructor.endpoint||"",this.id=t.id||null,this.attributes={...t},this._=this.attributes,this.originalAttributes={...t},this.errors={},this.loading=!1,this.rest=r,this.options={idAttribute:"id",timestamps:!0,...e}}getContextValue(t){return this.get(t)}get(t){return t.includes(".")||t.includes("|")||void 0===this[t]?MOJOUtils.getContextData(this.attributes,t):"function"==typeof this[t]?this[t]():this[t]}set(t,e,r={}){const s=JSON.parse(JSON.stringify(this.attributes));let i=!1;if(null!=t){if("object"==typeof t){for(const[e,r]of Object.entries(t))i=this._setNestedAttribute(e,r)||i;void 0!==t.id&&(this.id=t.id)}else"id"===t?(this.id=e,i=!0):i=this._setNestedAttribute(t,e);if(i&&!r.silent)if(this.emit("change",this),"string"==typeof t)this.emit(`change:${t}`,e,this);else for(const[e,r]of Object.entries(t)){const t=this._getNestedValue(e);JSON.stringify(this._getNestedValue(e,s))!==JSON.stringify(t)&&this.emit(`change:${e}`,t,this)}}}_setNestedAttribute(t,e){if(!t.includes(".")){const r=this.attributes[t];return this.attributes[t]=e,this[t]=e,r!==e}const r=t.split("."),s=r[0];this.attributes[s]&&"object"==typeof this.attributes[s]||(this.attributes[s]={}),this[s]&&"object"==typeof this[s]||(this[s]={});const i=this._getNestedValue(t);let n=this.attributes[s],a=this[s];for(let l=1;l<r.length-1;l++){const t=r[l];n[t]&&"object"==typeof n[t]||(n[t]={}),a[t]&&"object"==typeof a[t]||(a[t]={}),n=n[t],a=a[t]}const o=r[r.length-1];return n[o]=e,a[o]=e,JSON.stringify(i)!==JSON.stringify(e)}_getNestedValue(t,e=this.attributes){if(!t.includes("."))return e[t];const r=t.split(".");let s=e;for(const i of r){if(null==s||"object"!=typeof s)return;s=s[i]}return s}getData(){return this.attributes}getId(){return this.id}async fetch(t={}){let e=t.url;if(!e){const r=t.id||this.getId();if(!r&&!1!==this.options.requiresId)throw new Error("Model: ID is required for fetching");e=this.buildUrl(r)}const r=JSON.stringify({url:e,params:t.params});if(t.debounceMs&&t.debounceMs>0)return this._debouncedFetch(r,t);if(this.currentRequest&&this.currentRequestKey!==r&&(this.abortController?.abort(),this.currentRequest=null),this.currentRequest&&this.currentRequestKey===r)return this.currentRequest;const s=Date.now();if(this.lastFetchTime&&s-this.lastFetchTime<100)return this;this.loading=!0,this.errors={},this.lastFetchTime=s,this.currentRequestKey=r,this.abortController=new AbortController,this.currentRequest=this._performFetch(e,t,this.abortController);try{return await this.currentRequest}catch(i){if("AbortError"===i.name)return this;throw i}finally{this.currentRequest=null,this.currentRequestKey=null,this.abortController=null}}async _debouncedFetch(t,e){return this.debouncedFetchTimeout&&clearTimeout(this.debouncedFetchTimeout),this.cancel(),new Promise((t,r)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const r=await this.fetch({...e,debounceMs:0});t(r)}catch(s){r(s)}},e.debounceMs)})}async _performFetch(t,e,r){try{!e.graph||e.params&&e.params.graph||(e.params||(e.params={}),e.params.graph=e.graph);const s=await this.rest.GET(t,e.params,{signal:r.signal});return s.success?s.data.status?(this.originalAttributes={...this.attributes},s.data.data&&this.set(s.data.data),this.errors={}):this.errors=s.data:this.errors=s.errors||{},s}catch(s){if("AbortError"===s.name)throw s;return this.errors={fetch:s.message},{success:!1,error:s.message,status:s.status||500}}finally{this.loading=!1}}async save(t,e={}){const r=!this.id,s=r?"POST":"PUT",i=r?this.buildUrl():this.buildUrl(this.id);this.loading=!0,this.errors={};try{const r=await this.rest[s](i,t,e.params);return r.success?r.data.status?(this.originalAttributes={...this.attributes},this.set(r.data.data),this.errors={}):this.errors=r.data:this.errors=r.errors||{},r}catch(n){return{success:!1,error:n.message,status:n.status||500}}finally{this.loading=!1}}async destroy(t={}){if(!this.id)return this.errors={destroy:"Cannot destroy model without ID"},{success:!1,error:"Cannot destroy model without ID",status:400};const e=this.buildUrl(this.id);this.loading=!0,this.errors={};try{const r=await this.rest.DELETE(e,t.params);return r.success?(this.attributes={},this.originalAttributes={},this.id=null,this.errors={}):this.errors=r.errors||{},r}catch(r){return this.errors={destroy:r.message},{success:!1,error:r.message,status:r.status||500}}finally{this.loading=!1}}isDirty(){return JSON.stringify(this.attributes)!==JSON.stringify(this.originalAttributes)}getChangedAttributes(){const t={};for(const[e,r]of Object.entries(this.attributes))this.originalAttributes[e]!==r&&(t[e]=r);return t}reset(){for(const t of Object.keys(this.attributes))t in this.originalAttributes||delete this[t];for(const[t,e]of Object.entries(this.originalAttributes))this[t]=e;this.attributes={...this.originalAttributes},this._=this.attributes,this.errors={}}buildUrl(t=null){let e=this.endpoint;return t&&(e=e.endsWith("/")?`${e}${t}`:`${e}/${t}`),e}toJSON(){return{id:this.id,...this.attributes}}validate(){if(this.errors={},this.constructor.validations)for(const[t,e]of Object.entries(this.constructor.validations))this.validateField(t,e);return 0===Object.keys(this.errors).length}validateField(t,e){const r=this.get(t),s=Array.isArray(e)?e:[e];for(const i of s)if("function"==typeof i){const e=i(r,this);if(!0!==e){this.errors[t]=e||`${t} is invalid`;break}}else if("object"==typeof i){if(i.required&&(null==r||""===r)){this.errors[t]=i.message||`${t} is required`;break}if(i.minLength&&r&&r.length<i.minLength){this.errors[t]=i.message||`${t} must be at least ${i.minLength} characters`;break}if(i.maxLength&&r&&r.length>i.maxLength){this.errors[t]=i.message||`${t} must be no more than ${i.maxLength} characters`;break}if(i.pattern&&r&&!i.pattern.test(r)){this.errors[t]=i.message||`${t} format is invalid`;break}}}static async find(t,e={}){const r=new this({},e);return await r.fetch({id:t,...e}),r}static create(t={},e={}){return new this(t,e)}cancel(){return this.currentRequest&&this.abortController?(this.abortController.abort(),!0):!!this.debouncedFetchTimeout&&(clearTimeout(this.debouncedFetchTimeout),this.debouncedFetchTimeout=null,!0)}isFetching(){return!!this.currentRequest}async showError(t){const e=(await Promise.resolve().then(()=>require("./Modal-DBJU16cc.js")).then(t=>t.Modal$1)).default;await e.alert(t,"Error",{size:"md",class:"text-danger"})}}Object.assign(Model.prototype,e);class Collection{constructor(t={},e=null){if(Array.isArray(t)?t=(e=t)||{}:e=e||t.data||[],this.ModelClass=t.ModelClass||Model,this.models=[],this.loading=!1,this.errors={},this.meta={},this.rest=r,e&&this.add(e),this.params={start:0,size:t.size||10,...t.params},this.endpoint=t.endpoint||this.ModelClass.endpoint||"",!this.endpoint){let t=new this.ModelClass;this.endpoint=t.endpoint}this.restEnabled=!!this.endpoint,void 0!==t.restEnabled&&(this.restEnabled=t.restEnabled),this.options={parse:!0,reset:!0,preloaded:!1,...t}}getModelName(){return this.ModelClass.name}async fetch(t={}){const e=JSON.stringify({...this.params,...t});if(this.currentRequest&&this.currentRequestKey!==e&&(this.abortController?.abort(),this.currentRequest=null),this.currentRequest&&this.currentRequestKey===e)return this.currentRequest;const r=Date.now();if(this.options.rateLimiting&&this.lastFetchTime&&r-this.lastFetchTime<100)return{success:!0,message:"Rate limited, skipping fetch",data:{data:this.toJSON()}};if(!this.restEnabled)return{success:!0,message:"REST disabled, skipping fetch",data:{data:this.toJSON()}};if(this.options.preloaded&&this.models.length>0)return{success:!0,message:"Using preloaded data, skipping fetch",data:{data:this.toJSON()}};const s=this.buildUrl();this.loading=!0,this.errors={},this.lastFetchTime=r,this.currentRequestKey=e,this.abortController=new AbortController,this.currentRequest=this._performFetch(s,t,this.abortController);try{return await this.currentRequest}catch(i){return"AbortError"===i.name?{success:!1,error:"Request cancelled",status:0}:{success:!1,error:i.message,status:i.status||500}}finally{this.currentRequest=null,this.currentRequestKey=null,this.abortController=null}}async _performFetch(t,e,r){const s={...this.params,...e};try{this.emit("fetch:start");const i=await this.rest.GET(t,s,{signal:r.signal});if(i.success&&i.data.status){const t=this.options.parse?this.parse(i):i.data;(this.options.reset||!1!==e.reset)&&this.reset(),this.add(t,{silent:e.silent}),this.errors={},this.emit("fetch:success")}else i.data&&i.data.error?(this.errors=i.data,this.emit("fetch:error",{message:i.data.error,error:i.data})):(this.errors=i.errors||{},this.emit("fetch:error",{error:i.errors}));return i}catch(i){return"AbortError"===i.name?{success:!1,error:"Request cancelled",status:0}:(this.errors={fetch:i.message},this.emit("fetch:error",{message:i.message,error:i}),{success:!1,error:i.message,status:i.status||500})}finally{this.loading=!1,this.emit("fetch:end")}}async updateParams(t,e=!1,r=0){return await this.setParams({...this.params,...t},e,r)}async setParams(t,e=!1,r=0){return this.params=t,e&&this.restEnabled?r>0?(this.debouncedFetchTimeout&&clearTimeout(this.debouncedFetchTimeout),this.cancel(),new Promise((t,e)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const e=await this.fetch();t(e)}catch(r){e(r)}},r)})):this.fetch():Promise.resolve(this)}async fetchOne(t,e={}){if(!t)return console.warn("Collection: fetchOne requires an ID"),null;if(!this.restEnabled)return null;try{const r=new this.ModelClass({id:t},{endpoint:this.endpoint,collection:this}),s=await r.fetch(e);if(s.success){if(!0===e.addToCollection){const t=this.get(r.id);t?!1!==e.merge&&t.set(r.attributes):this.add(r,{silent:e.silent})}return r}return console.warn("Collection: fetchOne failed -",s.error||"Unknown error"),null}catch(r){return console.error("Collection: fetchOne error -",r.message),null}}async download(t="json",e={}){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 r=this.buildUrl(),s={...this.params};delete s.start,delete s.size,s.download_format=t;const i=`export-${this.getModelName().toLowerCase()}${this._buildDateRangeSuffix(s)}.${t}`,n={json:"application/json",csv:"text/csv"}[t]||"*/*";return s.filename=i,this.rest.download(r,s,{...e,filename:i,headers:{Accept:n}})}_buildDateRangeSuffix(t={}){const e=t.dr_start,r=t.dr_end;if(!e&&!r)return"";const s=t=>t?String(t).replace(/[^\dA-Za-z_-]/g,"-"):"",i=[],n=t.dr_field||"daterange";return i.push(s(n)),e&&i.push(`from-${s(t.dr_start)}`),r&&i.push(`to-${s(t.dr_end)}`),`-${i.filter(Boolean).join("-")}`}parse(t){return t.data&&Array.isArray(t.data.data)?(this.meta={size:t.data.size||10,start:t.data.start||0,count:t.data.count||0,status:t.data.status,graph:t.data.graph,...t.meta},t.data.data):Array.isArray(t.data)?t.data:Array.isArray(t)?t:[t]}add(t,e={}){const r=Array.isArray(t)?t:[t],s=[];for(const i of r){let t;t=i instanceof this.ModelClass?i:new this.ModelClass(i,{endpoint:this.endpoint,collection:this});const r=this.models.findIndex(e=>e.id===t.id);-1!==r?!1!==e.merge&&this.models[r].set(t.attributes):(this.models.push(t),s.push(t))}return!e.silent&&s.length>0&&(this.emit("add",{models:s,collection:this}),this.emit("update",{collection:this})),s}remove(t,e={}){const r=Array.isArray(t)?t:[t],s=[];for(const i of r){let t=-1;if(t="string"==typeof i||"number"==typeof i?this.models.findIndex(t=>t.id==i):this.models.indexOf(i),-1!==t){const e=this.models.splice(t,1)[0];s.push(e)}}return!e.silent&&s.length>0&&(this.emit("remove",{models:s,collection:this}),this.emit("update",{collection:this})),s}reset(t=null,e={}){const r=[...this.models];return this.models=[],t&&this.add(t,{silent:!0,...e}),e.silent||this.emit("reset",{collection:this,previousModels:r}),this}get(t){return this.models.find(e=>e.id==t)}at(t){return this.models[t]}length(){return this.models.length}isEmpty(){return 0===this.models.length}where(t){return"function"==typeof t?this.models.filter(t):"object"==typeof t?this.models.filter(e=>Object.entries(t).every(([t,r])=>e.get(t)===r)):[]}findWhere(t){const e=this.where(t);return e.length>0?e[0]:void 0}forEach(t,e){if("function"!=typeof t)throw new TypeError("Callback must be a function");return this.models.forEach((r,s)=>{t.call(e,r,s,this)}),this}sort(t,e={}){if("string"==typeof t){const e=t;t=(t,r)=>{const s=t.get(e),i=r.get(e);return s<i?-1:s>i?1:0}}return this.models.sort(t),e.silent||this.emit("sort",{collection:this}),this}toJSON(){return this.models.map(t=>t.toJSON())}cancel(){return!(!this.currentRequest||!this.abortController||(this.abortController.abort(),0))}isFetching(){return!!this.currentRequest}buildUrl(){return this.endpoint}*[Symbol.iterator](){for(const t of this.models)yield t}static fromArray(t,e=[],r={}){const s=new this({ModelClass:t,...r});return s.add(e,{silent:!0}),s}}Object.assign(Collection.prototype,e),exports.Collection=Collection,exports.EventEmitter=e,exports.MOJOUtils=MOJOUtils,exports.Model=Model,exports.dataFormatter=t,exports.rest=r;
2
- //# sourceMappingURL=Collection-BZlmtcuL.js.map
1
+ "use strict";const t=new class{constructor(){this.formatters=/* @__PURE__ */new Map,this.registerBuiltInFormatters()}escapeHtml(t){if(null==t)return"";const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;"};return String(t).replace(/[&<>"']/g,t=>e[t])}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",t=>{if(null==t||""===t)return t;const e=parseFloat(t);return isNaN(e)?t:1e3*e}),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",t=>String(t).toUpperCase()),this.register("lowercase",t=>String(t).toLowerCase()),this.register("upper",t=>String(t).toUpperCase()),this.register("lower",t=>String(t).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",t=>this.boolean(t,"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",t=>t),this.register("custom",(t,e)=>"function"==typeof e?e(t):t),this.register("iter",this.iter.bind(this)),this.register("keys",t=>t&&"object"==typeof t&&!Array.isArray(t)?Object.keys(t):null),this.register("values",t=>t&&"object"==typeof t&&!Array.isArray(t)?Object.values(t):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",t=>`<pre class="bg-light p-2 rounded border">${this.escapeHtml(String(t))}</pre>`)}relative_short(t){return this.relative(t,!0)}linkify(t,e={}){if(null==t)return"";const r=String(t),s=this.escapeHtml(r),i={urls:!0,emails:!0,target:"_blank",rel:"noopener noreferrer"},n=e&&"object"==typeof e?{...i,...e}:i;let a=s;if(!1!==n.urls){const t=/(^|\s)((?:https?:\/\/|www\.)[^\s<]+)/gi;a=a.replace(t,(t,e,r)=>`${e}<a href="${r.startsWith("www.")?`https://${r}`:r}" target="${n.target}" rel="${n.rel}">${r}</a>`)}if(!1!==n.emails){const t=/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;a=a.replace(t,t=>`<a href="mailto:${t}">${t}</a>`)}return a}clipboard(t,e="text"){if(null==t)return"";const r=String(t),s=this.escapeHtml(r);return`\n <span class="mojo-clipboard d-inline-flex align-items-center">\n ${"icon-only"!==e?`<span class="font-monospace">${s}</span>`:""}\n ${`\n <button type="button"\n class="btn btn-sm btn-outline-secondary ms-1 p-0 border-0 bg-transparent"\n title="Copy"\n data-bs-toggle="tooltip"\n data-action="copy-to-clipboard"\n data-clipboard="${s}">\n <i class="bi bi-clipboard"></i>\n </button>`.trim()}\n </span>\n `}nl2br(t){return null==t?"":this.escapeHtml(String(t)).replace(/\r\n|\r|\n/g,"<br>")}code(t,e=""){return null==t?"":`<pre class="bg-light p-2 rounded border"><code class="${e?`language-${this.escapeHtml(String(e))}`:""}">${this.escapeHtml(String(t))}</code></pre>`}register(t,e){if("function"!=typeof e)throw new Error("Formatter must be a function, got "+typeof e);return this.formatters.set(t.toLowerCase(),e),this}apply(t,e,...r){try{const s=this.formatters.get(t.toLowerCase());return s?s(e,...r):(console.warn(`Formatter '${t}' not found`),e)}catch(s){return console.error(`Error in formatter '${t}':`,s),e}}pipe(t,e,r=null){return e?this.parsePipeString(e,r).reduce((t,e)=>this.apply(e.name,t,...e.args),t):t}parsePipeString(t,e=null){const r=[],s=t.split("|").map(t=>t.trim());for(const i of s){const t=this.parseFormatter(i,e);t&&r.push(t)}return r}parseFormatter(t,e=null){const r=t.match(/^([a-zA-Z_]\w*)\s*\((.*)\)$/);if(r){const[,t,s]=r;return{name:t,args:s?this.parseArguments(s,e):[]}}const s=t.match(/^([a-zA-Z_]\w*)(?::(.+))?$/);if(s){const[,t,r]=s;return{name:t,args:r?this.parseColonArguments(r,e):[]}}return null}parseArguments(t,e=null){const r=[];let s="",i=!1,n=null,a=0;for(let o=0;o<t.length;o++){const l=t[o];i||'"'!==l&&"'"!==l?i&&l===n&&"\\"!==t[o-1]?(i=!1,n=null,s+=l):i||"{"!==l?i||"}"!==l?i||0!==a||","!==l?s+=l:(r.push(this.parseValue(s.trim(),e)),s=""):(a--,s+=l):(a++,s+=l):(i=!0,n=l,s+=l)}return s.trim()&&r.push(this.parseValue(s.trim(),e)),r}parseColonArguments(t,e=null){const r=[];let s="",i=!1,n=null;for(let a=0;a<t.length;a++){const o=t[a];i||'"'!==o&&"'"!==o?i&&o===n&&"\\"!==t[a-1]?(i=!1,n=null,s+=o):i||":"!==o?s+=o:(r.push(this.parseValue(s.trim(),e)),s=""):(i=!0,n=o,s+=o)}return s.trim()&&r.push(this.parseValue(s.trim(),e)),r}parseValue(t,e=null){if(t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'"))return t.slice(1,-1);if("true"===t)return!0;if("false"===t)return!1;if("null"===t)return null;if("undefined"!==t){if(!isNaN(t)&&""!==t)return Number(t);if(t.startsWith("{")&&t.endsWith("}"))try{return JSON.parse(t)}catch(r){}if(e&&this.isIdentifier(t)){if(!t.includes(".")&&Object.prototype.hasOwnProperty.call(e,t))return e[t];if(e.get&&"function"==typeof e.get){const r=e.get(t);if(void 0!==r)return r}if(e.getContextValue&&"function"==typeof e.getContextValue){const r=e.getContextValue(t);if(void 0!==r)return r}if(t.includes(".")){const r=window.MOJOUtils||("undefined"!=typeof require?require("./MOJOUtils.js").default:null);if(r){const s=r.getNestedValue(e,t);if(void 0!==s)return s}}}return t}}isIdentifier(t){return/^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/.test(t)}date(t,e="MM/DD/YYYY"){if(!t)return"";let r;if((t=this.normalizeEpoch(t))instanceof Date)r=t;else if("string"==typeof t)if(/^\d{4}-\d{2}-\d{2}$/.test(t)){const[e,s,i]=t.split("-").map(Number);r=new Date(e,s-1,i)}else r=new Date(t);else r=new Date(t);if(isNaN(r.getTime()))return String(t);const s={YYYY:r.getFullYear(),YY:String(r.getFullYear()).slice(-2),MMMM:r.toLocaleDateString("en-US",{month:"long"}),MMM:r.toLocaleDateString("en-US",{month:"short"}),MM:String(r.getMonth()+1).padStart(2,"0"),M:r.getMonth()+1,dddd:r.toLocaleDateString("en-US",{weekday:"long"}),ddd:r.toLocaleDateString("en-US",{weekday:"short"}),DD:String(r.getDate()).padStart(2,"0"),D:r.getDate()};let i=e;const n=new RegExp(`(${Object.keys(s).join("|")})`,"g");return i=i.replace(n,t=>s[t]||t),i}time(t,e="HH:mm:ss"){if(!t)return"";const r=(t=this.normalizeEpoch(t))instanceof Date?t:new Date(t);if(isNaN(r.getTime()))return String(t);const s=r.getHours(),i={HH:String(s).padStart(2,"0"),H:s,hh:String(s%12||12).padStart(2,"0"),h:s%12||12,mm:String(r.getMinutes()).padStart(2,"0"),m:r.getMinutes(),ss:String(r.getSeconds()).padStart(2,"0"),s:r.getSeconds(),A:s>=12?"PM":"AM",a:s>=12?"pm":"am"};let n=e;const a=Object.keys(i).sort((t,e)=>e.length-t.length);for(const o of a)n=n.replace(new RegExp(o,"g"),i[o]);return n}datetime(t,e="MM/DD/YYYY",r="HH:mm:ss"){t=this.normalizeEpoch(t);const s=this.date(t,e),i=this.time(t,r);return s&&i?`${s} ${i}`:""}datetime_tz(t,e="MM/DD/YYYY",r="HH:mm:ss",s={}){if(!t)return"";const i=(t=this.normalizeEpoch(t))instanceof Date?t:new Date(t);if(isNaN(i.getTime()))return String(t);const n=s&&s.locale||"en-US",a=s&&s.timeZone?s.timeZone:void 0,o=()=>{let t="";try{const r=new Intl.DateTimeFormat(n,{hour:"2-digit",minute:"2-digit",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(i).find(t=>"timeZoneName"===t.type);if(t=r?r.value:"",t&&/^GMT[+-]/i.test(t))try{const e=new Intl.DateTimeFormat(n,{timeStyle:"short",timeZoneName:"short",...a?{timeZone:a}:{}}).formatToParts(i).find(t=>"timeZoneName"===t.type);e&&e.value&&!/^GMT[+-]/i.test(e.value)&&(t=e.value)}catch(e){}if(t&&/\s/.test(t)){const e=t.split(/\s+/).map(t=>t[0]).join("").toUpperCase();e.length>=2&&e.length<=4&&(t=e)}}catch(e){t=""}return t};if(!a){const t=this.date(i,e),s=this.time(i,r),n=o();return t&&s?`${t} ${s} ${n}`.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(i),c=t=>{const e=l.find(e=>e.type===t);return e?e.value:""},h=c("year"),u=c("month"),d=c("day"),g=c("hour"),m=c("minute"),p=c("second"),f=u?String(parseInt(u,10)):"",b=d?String(parseInt(d,10)):"",y=g?String(parseInt(g,10)):"",w=g?parseInt(g,10)%12||12:"",S=g?parseInt(g,10)>=12?"PM":"AM":"",$=S?S.toLowerCase():"",x=new Intl.DateTimeFormat(n,{timeZone:a,month:"long"}).format(i),M=new Intl.DateTimeFormat(n,{timeZone:a,month:"short"}).format(i),_=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"long"}).format(i),C=new Intl.DateTimeFormat(n,{timeZone:a,weekday:"short"}).format(i),A={YYYY:h,YY:h?h.slice(-2):"",MMMM:x,MMM:M,MM:u,M:f,dddd:_,ddd:C,DD:d,D:b},T={HH:g,H:y,hh:""!==w?String(w).padStart(2,"0"):"",h:""!==w?String(w):"",mm:m,m:m?String(parseInt(m,10)):"",ss:p,s:p?String(parseInt(p,10)):"",A:S,a:$},N=(t,e)=>{if(!t)return"";const r=new RegExp(`(${Object.keys(e).sort((t,e)=>e.length-t.length).join("|")})`,"g");return t.replace(r,t=>e[t]??t)},D=N(e,A),v=N(r,T),O=o();return D&&v?`${D} ${v} ${O}`.trim():""}normalizeEpoch(t){if(t instanceof Date)return t;if("string"==typeof t){const e=Number(t);if(!Number.isFinite(e)){const e=Date.parse(t);return Number.isFinite(e)?e:""}t=e}else"number"!=typeof t&&(t=Number(t));if(isNaN(t))return"";if(t<1e11)return 1e3*t;if(t>1e12&&t<1e13)return t;throw new Error("Value doesn't look like epoch seconds or ms")}date_range(t,e=null,r="MM/DD/YYYY"){if(!t)return"";const s=e||/* @__PURE__ */new Date,i=this.date(t,r),n=this.date(s,r);return i&&n?`${i} - ${n}`:""}datetime_range(t,e=null,r="MM/DD/YYYY",s="HH:mm"){if(!t)return"";const i=e||/* @__PURE__ */new Date,n=this.datetime(t,r,s),a=this.datetime(i,r,s);return n&&a?`${n} - ${a}`:""}relative(t,e=!1){if(!t)return"";const r=(t=this.normalizeEpoch(t))instanceof Date?t:new Date(t);if(isNaN(r.getTime()))return String(t);const s=r-/* @__PURE__ */new Date,i=Math.abs(s),n=Math.floor(i/1e3),a=Math.floor(n/60),o=Math.floor(a/60),l=Math.floor(o/24),c=s>0;if(e)return l>365?Math.floor(l/365)+"y":l>30?Math.floor(l/30)+"mo":l>7?Math.floor(l/7)+"w":l>0?l+"d":o>0?o+"h":a>0?a+"m":"now";if(l>365){const t=Math.floor(l/365);return(c?"in ":"")+t+" year"+(t>1?"s":"")+(c?"":" ago")}if(l>30){const t=Math.floor(l/30);return(c?"in ":"")+t+" month"+(t>1?"s":"")+(c?"":" ago")}if(l>7){const t=Math.floor(l/7);return(c?"in ":"")+t+" week"+(t>1?"s":"")+(c?"":" ago")}return 1===l?c?"tomorrow":"yesterday":l>0?(c?"in ":"")+l+" days"+(c?"":" ago"):o>0?(c?"in ":"")+o+" hour"+(o>1?"s":"")+(c?"":" ago"):a>0?(c?"in ":"")+a+" minute"+(a>1?"s":"")+(c?"":" ago"):n>30?(c?"in ":"")+n+" seconds"+(c?"":" ago"):"just now"}iso(t,e=!1){if(!t)return"";const r=(t=this.normalizeEpoch(t))instanceof Date?t:new Date(t);return isNaN(r.getTime())?String(t):e?r.toISOString().split("T")[0]:r.toISOString()}number(t,e=2,r="en-US"){const s=parseFloat(t);return isNaN(s)?String(t):s.toLocaleString(r,{minimumFractionDigits:e,maximumFractionDigits:e})}currency(t,e="$",r=2){const s=parseInt(t);if(isNaN(s))return String(t);const i=Math.abs(s).toString(),n=s<0?"-":"";let a,o,l;return i.length<=2?(a="0",o=i.padStart(2,"0")):(a=i.slice(0,-2),o=i.slice(-2)),a=a.replace(/\B(?=(\d{3})+(?!\d))/g,","),0===r?(parseInt(o)>=50&&(a=(parseInt(a.replace(/,/g,""))+1).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")),l=a):l=2===r?`${a}.${o}`:`${a}.${o.slice(0,r).padEnd(r,"0")}`,n+e+l}percent(t,e=0,r=!0){const s=parseFloat(t);if(isNaN(s))return String(t);const i=r?100*s:s;return this.number(i,e)+"%"}filesize(t,e=!1,r=1){const s=parseInt(t);if(isNaN(s))return String(t);const i=e?["B","KiB","MiB","GiB","TiB"]:["B","KB","MB","GB","TB"],n=e?1024:1e3;let a=s,o=0;for(;a>=n&&o<i.length-1;)a/=n,o++;const l=0===o?0:r;return`${a.toFixed(l)} ${i[o]}`}ordinal(t,e=!1){const r=parseInt(t);if(isNaN(r))return String(t);const s=r%10,i=r%100;let n="th";return 1===s&&11!==i?n="st":2===s&&12!==i?n="nd":3===s&&13!==i&&(n="rd"),e?n:r+n}compact(t,e=1){const r=parseFloat(t);if(isNaN(r))return String(t);const s=Math.abs(r),i=r<0?"-":"";return s>=1e9?i+(s/1e9).toFixed(e)+"B":s>=1e6?i+(s/1e6).toFixed(e)+"M":s>=1e3?i+(s/1e3).toFixed(e)+"K":String(r)}add(t,e){const r=parseFloat(t),s=parseFloat(e);return isNaN(r)||isNaN(s)?t:r+s}subtract(t,e){const r=parseFloat(t),s=parseFloat(e);return isNaN(r)||isNaN(s)?t:r-s}multiply(t,e){const r=parseFloat(t),s=parseFloat(e);return isNaN(r)||isNaN(s)?t:r*s}divide(t,e){const r=parseFloat(t),s=parseFloat(e);return isNaN(r)||isNaN(s)||0===s?t:r/s}capitalize(t,e=!0){const r=String(t);return r?e?r.replace(/\b\w/g,t=>t.toUpperCase()):r.charAt(0).toUpperCase()+r.slice(1):""}replace(t,e,r="",s="g"){if(null==t)return"";const i=String(t);if(null==e||""===e)return i;if(e instanceof RegExp)return i.replace(e,String(r));const n=String(e),a=n.match(/^\/(.+)\/([a-z]*)$/i);if(a){const[,t,e]=a;try{return i.replace(new RegExp(t,e),String(r))}catch(o){}}return String(s).includes("g")?i.split(n).join(String(r)):i.replace(n,String(r))}truncate(t,e=50,r="..."){const s=String(t);return s.length<=e?s:s.substring(0,e)+r}truncate_front(t,e=8,r="..."){const s=String(t);return s.length<=e?s:`${r}${s.slice(-e)}`}truncate_middle(t,e=8,r="***"){const s=String(t);if(s.length<=e)return s;const i=Math.floor(e/2);return`${s.substring(0,i)}${r}${s.substring(s.length-i)}`}slug(t,e="-"){return String(t).toLowerCase().replace(/[^\w\s-]/g,"").replace(/\s+/g,e).replace(new RegExp(`${e}+`,"g"),e).replace(new RegExp(`^${e}|${e}$`,"g"),"")}initials(t,e=2){return String(t).split(/\s+/).filter(t=>t.length>0).slice(0,e).map(t=>t.charAt(0).toUpperCase()).join("")}mask(t,e="*",r=4){const s=String(t);return s.length<=r?s:e.repeat(Math.max(0,s.length-r))+s.slice(-r)}email(t,e={}){const r=String(t).trim();return r?!1===e.link?r:`<a href="mailto:${r}${e.subject?`?subject=${encodeURIComponent(e.subject)}`:""}${e.body?`&body=${encodeURIComponent(e.body)}`:""}"${e.class?` class="${e.class}"`:""}>${r}</a>`:""}phone(t,e="US",r=!0){let s=String(t).replace(/\D/g,""),i=s;return"US"===e&&(10===s.length?i=`(${s.slice(0,3)}) ${s.slice(3,6)}-${s.slice(6)}`:11===s.length&&"1"===s[0]&&(i=`+1 (${s.slice(1,4)}) ${s.slice(4,7)}-${s.slice(7)}`)),r?`<a href="tel:${s}">${i}</a>`:i}url(t,e=null,r=!0){let s=String(t).trim();return s?(/^https?:\/\//.test(s)||(s="https://"+s),`<a href="${s}"${r?' target="_blank"':""}${r?' rel="noopener noreferrer"':""}>${e||s}</a>`):""}badge(t,e="auto"){if(Array.isArray(t))return t.map(t=>this.badge(t,e)).join(" ");const r=String(t);if("string"==typeof e&&e.includes("=")){const t=Object.fromEntries(e.split(",").map(t=>t.split("=").map(t=>t.trim()))),s=t[r]||t[r.toLowerCase()]||this.inferBadgeType(r);return`<span class="badge ${s?`bg-${s}`:"bg-secondary"}">${r}</span>`}const s="auto"===e?this.inferBadgeType(r):e;return`<span class="badge ${s?`bg-${s}`:"bg-secondary"}">${r}</span>`}badgeClass(t,e="auto"){const r=String(t),s="auto"===e?this.inferBadgeType(r):e;return s?`bg-${s}`:"bg-secondary"}inferBadgeType(t){const e=t.toLowerCase();return["active","pass","success","complete","completed","approved","done","true","on","yes"].includes(e)?"success":["error","failed","fail","rejected","deleted","cancelled","false","off","no","declined"].includes(e)?"danger":["warning","pending","review","processing","uploading"].includes(e)?"warning":["info","new","draft"].includes(e)?"info":(["inactive","disabled","archived","suspended"].includes(e),"secondary")}status(t){return this._status(t)}status_icon(t){return this._status(t,{},{},!1,!0)}status_text(t){return this._status(t,{},{},!0,!1)}_status(t,e={},r={},s=!1,i=!1){const n=String(t).toLowerCase(),a=e[n]||{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"}[n]||"";let o="";!s&&a&&(o=`<i class="${a}"></i>`);let l="";return i||(l=t),`<span class="text-${r[n]||{active:"success",approved:"success",declined:"danger",inactive:"secondary",pending:"warning",success:"success",error:"danger",warning:"warning"}[n]||"secondary"}">${o}${o?" ":""}${l}</span>`}boolean(t,e="True",r="False",s=!1){const i=t?e:r;return s?`<span class="text-${t?"success":"danger"}">${i}</span>`:i}bool(t){return!(null==t||0===t||""===t||!1===t||"false"===t||!0!==t&&"true"!==t&&(Array.isArray(t)&&0===t.length||t&&"object"==typeof t&&t.constructor===Object&&0===Object.keys(t).length))}icon(t,e={}){const r=e[String(t).toLowerCase()]||"";return r?`<i class="${r}"></i>`:""}yesnoicon(t,e="bi bi-check-circle-fill text-success",r="bi bi-x-circle-fill text-danger"){return t?`<i class="${e}"></i>`:`<i class="${r}"></i>`}image(t,e="thumbnail",r="img-fluid",s=""){const i=this._extractImageUrl(t,e);return i?`<img src="${i}" class="${r}" alt="${s}" />`:""}avatar(t,e="md",r="rounded-circle",s=""){const i=this._extractImageUrl(t,"square_sm")||"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI2NlZDRkYSI+PHBhdGggZD0iTTEyIDEyYzIuMjEgMCA0LTEuNzkgNC00cy0xLjc5LTQtNC00LTQgMS43OS00IDQgMS43OSA0IDQgNHptMCAyYy0yLjY3IDAtOCAxLjM0LTggNHYyaDE2di0yYzAtMi42Ni01LjMzLTQtOC00eiIvPjwvc3ZnPg==",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[e]||n.md;return`<img src="${i}" class="${`object-fit-cover ${r}`.trim()}" style="${a}" alt="${s}" />`}tooltip(t,e="",r="top",s=""){if(null==t)return"";const i=String(t);return`<span data-bs-toggle="tooltip" data-bs-placement="${r}" ${"html"===s?'data-bs-html="true"':""} data-bs-title="${"html"===s?e:this.escapeHtml(e)}">${i}</span>`}_extractImageUrl(t,e="thumbnail"){if(!t)return null;if("string"==typeof t)return t;if("object"==typeof t){if(t.attributes&&(t=t.attributes),"thumbnail"===e&&t.thumbnail&&"string"==typeof t.thumbnail)return t.thumbnail;if(t.renditions&&"object"==typeof t.renditions){const r=t.renditions[e];if(r&&r.url)return r.url;const s=Object.values(t.renditions);if(s.length>0&&s[0].url)return s[0].url}if(t.url)return t.url}return null}default(t,e=""){return null==t||""===t?e:t}equals(t,e,r,s=""){return t==e?r:s}plural(t,e,r=null,s=!0){if(null==t||null==e)return s?`${t} ${e}`:e||"";const i=parseInt(t);if(isNaN(i))return s?`${t} ${e}`:e||"";const n=1===Math.abs(i)?e:r||e+"s";return s?`${i} ${n}`:n}formatList(t,e={}){if(!Array.isArray(t))return String(t);const{conjunction:r="and",limit:s=null,moreText:i="others"}=e;if(0===t.length)return"";if(1===t.length)return String(t[0]);let n=t.slice(),a=!1;if(s&&t.length>s&&(n=t.slice(0,s),a=!0),a){const e=t.length-s;return`${n.join(", ")}, ${r} ${e} ${i}`}return 2===n.length?`${n[0]} ${r} ${n[1]}`:`${n.slice(0,-1).join(", ")}, ${r} ${n[n.length-1]}`}duration(t,e="ms",r=!1,s=2){if(null==t)return"";const i=parseFloat(t);if(isNaN(i))return String(t);let n;switch(e){case"s":case"sec":case"seconds":n=1e3*i;break;case"m":case"min":case"minutes":n=6e4*i;break;case"h":case"hr":case"hours":n=36e5*i;break;case"d":case"day":case"days":n=864e5*i;break;default:n=i}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(0===n)return r?"0s":"0 seconds";const o=Math.abs(n),l=n<0?"-":"",c=[];let h=o;for(const u of a)if(h>=u.value){const t=Math.floor(h/u.value);h%=u.value;const e=r?u.short:1===t?u.name:u.name+"s";if(c.push(r?`${t}${e}`:`${t} ${e}`),c.length>=s)break}return 0===c.length?r?`${Math.round(o)}ms`:`${Math.round(o)} milliseconds`:l+(r?c.join(""):c.join(" "))}hash(t,e=8,r="",s="..."){if(null==t)return"";const i=String(t);return i.length<=e?r+i:r+i.substring(0,e)+s}stripHtml(t){return null==t?"":String(t).replace(/<[^>]*>/g,"")}highlight(t,e,r="highlight"){if(null==t||!e)return String(t||"");const s=String(e).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),i=new RegExp(`(${s})`,"gi");return String(t).replace(i,`<mark class="${r}">$1</mark>`)}hex(t,e=!1,r=!1){if(null==t)return"";let s="";const i=t=>Array.from(t).map(t=>t.toString(16).padStart(2,"0")).join("");if("number"==typeof t){let e=Math.abs(Math.trunc(t)).toString(16);e.length%2&&(e="0"+e),s=e}else s=t instanceof Uint8Array?i(t):t instanceof ArrayBuffer?i(new Uint8Array(t)):Array.isArray(t)&&t.every(t=>"number"==typeof t)?i(Uint8Array.from(t.map(t=>255&t))):i((new TextEncoder).encode(String(t)));return e&&(s=s.toUpperCase()),(r?"0x":"")+s}unhex(t){if(null==t)return"";let e=String(t).trim();if((e.startsWith("0x")||e.startsWith("0X"))&&(e=e.slice(2)),e=e.replace(/\s+/g,""),0===e.length)return"";e.length%2!=0&&(e="0"+e);const r=new Uint8Array(e.length/2);for(let i=0;i<e.length;i+=2){const s=parseInt(e.slice(i,i+2),16);if(Number.isNaN(s))return String(t);r[i/2]=s}try{return(new TextDecoder).decode(r)}catch(s){let t="";for(const e of r)t+=String.fromCharCode(e);return t}}json(t,e=2){try{return JSON.stringify(t,null,e)}catch(r){return String(t)}}has(t){return this.formatters.has(t.toLowerCase())}unregister(t){return this.formatters.delete(t.toLowerCase())}listFormatters(){return Array.from(this.formatters.keys()).sort()}iter(t){return null==t?[]:Array.isArray(t)?t:"object"==typeof t?Object.entries(t).map(([t,e])=>({key:t,value:e})):[{key:"0",value:t}]}};window.dataFormatter=t;class MOJOUtils{static getContextData(e,r){if(!r||null==e)return;let s=r,i="",n=0,a=-1;for(let t=0;t<r.length;t++){const e=r[t];if("("===e)n++;else if(")"===e)n--;else if("|"===e&&0===n){a=t;break}}a>-1&&(s=r.substring(0,a).trim(),i=r.substring(a+1).trim());const o=this.getNestedValue(e,s);return i?t.pipe(o,i,e):o}static getNestedValue(t,e){if(!e||null==t)return;if(!e.includes(".")){if(e in t){const r=t[e];return"function"==typeof r?r.call(t):r}return}const r=e.split(".");let s=t;for(let i=0;i<r.length;i++){const e=r[i];if(null==s)return;if(0===i){if(!s.hasOwnProperty(e))return;{const r=s[e];s="function"==typeof r?r.call(t):r}}else{if(s&&"function"==typeof s.getContextValue){const t=r.slice(i).join(".");return s.getContextValue(t)}if(Array.isArray(s)&&!isNaN(e))s=s[parseInt(e)];else if(s.hasOwnProperty(e))s=s[e];else{if("function"!=typeof s[e])return;s=s[e].call(s)}}}return s}static isNullOrUndefined(t){return null==t}static deepClone(t){if(null===t||"object"!=typeof t)return t;if(t instanceof Date)return new Date(t.getTime());if(t instanceof Array)return t.map(t=>this.deepClone(t));if(t instanceof Object){const e={};for(const r in t)t.hasOwnProperty(r)&&(e[r]=this.deepClone(t[r]));return e}}static deepMerge(t,...e){if(!e.length)return t;const r=e.shift();if(this.isObject(t)&&this.isObject(r))for(const s in r)this.isObject(r[s])?(t[s]||Object.assign(t,{[s]:{}}),this.deepMerge(t[s],r[s])):Object.assign(t,{[s]:r[s]});return this.deepMerge(t,...e)}static isObject(t){return t&&"object"==typeof t&&!Array.isArray(t)}static debounce(t,e){let r;return function(...s){clearTimeout(r),r=setTimeout(()=>{clearTimeout(r),t(...s)},e)}}static throttle(t,e){let r;return function(...s){r||(t.apply(this,s),r=!0,setTimeout(()=>r=!1,e))}}static generateId(t=""){const e=Date.now().toString(36),r=Math.random().toString(36).substr(2,9);return t?`${t}_${e}_${r}`:`${e}_${r}`}static escapeHtml(t){const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(t).replace(/[&<>"'`=\/]/g,t=>e[t])}static checkPasswordStrength(t){if(!t||"string"!=typeof t)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 e=[],r={length:t.length,hasLowercase:/[a-z]/.test(t),hasUppercase:/[A-Z]/.test(t),hasNumbers:/[0-9]/.test(t),hasSpecialChars:/[^a-zA-Z0-9]/.test(t),hasCommonPatterns:!1,isCommonPassword:!1};let s=0;t.length<6?e.push("Password should be at least 6 characters long"):t.length<8?(s+=1,e.push("Consider using at least 8 characters for better security")):t.length<12?s+=3:s+=4,r.hasLowercase?s+=1:e.push("Include lowercase letters"),r.hasUppercase?s+=1:e.push("Include uppercase letters"),r.hasNumbers?s+=1:e.push("Include numbers"),r.hasSpecialChars?s+=2:e.push("Include special characters (!@#$%^&* etc.)");const i=[/123/,/abc/i,/qwerty/i,/asdf/i,/(.)\1{2,}/,/password/i,/admin/i,/user/i,/login/i];for(const a of i)if(a.test(t)){r.hasCommonPatterns=!0,s-=1,e.push("Avoid common patterns and dictionary words");break}let n;return["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(t.toLowerCase())&&(r.isCommonPassword=!0,s=Math.max(0,s-3),e.push("This password is too common and easily guessed")),n=s<2?"very-weak":s<4?"weak":s<6?"fair":s<8?"good":"strong",s>=7&&0===e.length?e.push("Strong password! Consider using a password manager."):s>=5&&e.length<=1&&e.push("Good password strength. Consider adding more variety."),{score:Math.max(0,s),strength:n,feedback:e,details:r}}static generatePassword(t={}){const e={length:12,includeLowercase:!0,includeUppercase:!0,includeNumbers:!0,includeSpecialChars:!0,customChars:"",excludeAmbiguous:!1,...t};if(e.length<4)throw new Error("Password length must be at least 4 characters");let r="abcdefghijklmnopqrstuvwxyz",s="ABCDEFGHIJKLMNOPQRSTUVWXYZ",i="0123456789",n="!@#$%^&*()_+-=[]{}|;:,.<>?";e.excludeAmbiguous&&(r=r.replace(/[il]/g,""),s=s.replace(/[IOL]/g,""),i=i.replace(/[01]/g,""),n=n.replace(/[|]/g,""));let a="";const o=[];if(e.customChars?a=e.customChars:(e.includeLowercase&&(a+=r,o.push(r[Math.floor(Math.random()*r.length)])),e.includeUppercase&&(a+=s,o.push(s[Math.floor(Math.random()*s.length)])),e.includeNumbers&&(a+=i,o.push(i[Math.floor(Math.random()*i.length)])),e.includeSpecialChars&&(a+=n,o.push(n[Math.floor(Math.random()*n.length)]))),!a)throw new Error("No character types selected for password generation");let l="";for(const c of o)l+=c;for(let c=l.length;c<e.length;c++)l+=a[Math.floor(Math.random()*a.length)];return l.split("").sort(()=>Math.random()-.5).join("")}static parseQueryString(t){const e={},r=new URLSearchParams(t);for(const[s,i]of r.entries())e[s]=i;return e}static toQueryString(t){return new URLSearchParams(t).toString()}static wrapData(t,e=null,r=3){return t&&"object"==typeof t?t instanceof Date||t instanceof RegExp||t instanceof Error||r<=0||"function"==typeof t.getContextValue?t:Array.isArray(t)?t.map(t=>t&&"object"==typeof t&&!t.getContextValue?new DataWrapper(t,e):t):new DataWrapper(t,e):t}}class DataWrapper{constructor(t,e=null){if(Object.defineProperty(this,"_data",{value:t,writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(this,"_rootContext",{value:e,writable:!1,enumerable:!1,configurable:!1}),t&&"object"==typeof t)for(const r in t)if(t.hasOwnProperty(r)){const s=t[r];this[r]=MOJOUtils.wrapData(s,e)}}getContextValue(e){let r,s=e,i="",n=0,a=-1;for(let t=0;t<e.length;t++){const r=e[t];if("("===r)n++;else if(")"===r)n--;else if("|"===r&&0===n){a=t;break}}return a>-1&&(s=e.substring(0,a).trim(),i=e.substring(a+1).trim()),r=s in this&&"_data"!==s&&"_rootContext"!==s?this[s]:MOJOUtils.getNestedValue(this._data,s),i&&void 0!==r?t.pipe(r,i,this._rootContext||this._data):r}has(t){return this._data&&this._data.hasOwnProperty(t)}toJSON(){return this._data}}MOJOUtils.DataWrapper=DataWrapper,"undefined"!=typeof window&&(window.utils=MOJOUtils);const e={on(t,e,r){this._listeners||(this._listeners={}),this._listeners[t]||(this._listeners[t]=[]);const s={callback:e,context:r,fn:r?e.bind(r):e};return this._listeners[t].push(s),this},off(t,e,r){return this._listeners&&this._listeners[t]?(e?(this._listeners[t]=this._listeners[t].filter(t=>t.callback!==e||3===arguments.length&&t.context!==r),0===this._listeners[t].length&&delete this._listeners[t]):delete this._listeners[t],this):this},once(t,e,r){const s=(...i)=>{this.off(t,s),(r?e.bind(r):e).apply(r||this,i)};return this.on(t,s),this},emit(t,...e){if(!this._listeners||!this._listeners[t])return this;const r=this._listeners[t].slice();for(const i of r)try{i.fn.apply(i.context||this,e)}catch(s){console&&console.error&&console.error(`Error in ${t} event handler:`,s)}return this}},r=new class{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 t="mojo_device_uid";try{let e=localStorage.getItem(t);e?this.duid=e:(this.duid=this._generateDuid(),localStorage.setItem(t,this.duid))}catch(e){console.error("Could not access localStorage to get/set DUID.",e),this.duid=this._generateDuid()}}_generateDuid(){return crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){const e=16*Math.random()|0;return("x"===t?e:3&e|8).toString(16)})}configure(t){t.baseUrl&&(t.baseURL=t.baseUrl);const e=this.config.trackDevice;this.config={...this.config,...t,headers:{...this.config.headers,...t.headers}},this.config.trackDevice&&!e&&this._initializeDuid()}addInterceptor(t,e){this.interceptors[t]&&this.interceptors[t].push(e)}buildUrl(t){return t.startsWith("http://")||t.startsWith("https://")?t:`${this.config.baseURL.endsWith("/")?this.config.baseURL.slice(0,-1):this.config.baseURL}${t.startsWith("/")?t:`/${t}`}`}categorizeError(t,e=0){if("TypeError"===t.name&&t.message.includes("fetch"))return{reason:"not_reachable",message:"Service is not reachable - please check your connection"};if("AbortError"===t.name)return{reason:"cancelled",message:"Request was cancelled"};if("TimeoutError"===t.name||t.message.includes("timeout"))return{reason:"timed_out",message:"Request timed out - please try again"};if(e>=400){if(400===e)return{reason:"bad_request",message:"Invalid request data"};if(401===e)return{reason:"unauthorized",message:"Authentication required"};if(403===e)return{reason:"forbidden",message:"Access denied"};if(404===e)return{reason:"not_found",message:"Resource not found"};if(409===e)return{reason:"conflict",message:"Resource conflict"};if(422===e)return{reason:"validation_error",message:"Validation failed"};if(429===e)return{reason:"rate_limited",message:"Too many requests - please wait"};if(e>=500)return{reason:"server_error",message:"Server error - please try again later"};if(e>=400)return{reason:"client_error",message:"Request error"}}return t.message.includes("CORS")?{reason:"cors_error",message:"Cross-origin request blocked"}:t.message.includes("DNS")||t.message.includes("ENOTFOUND")?{reason:"dns_error",message:"Unable to resolve server address"}:{reason:"unknown_error",message:`Network error: ${t.message}`}}buildQueryString(t={}){const e=new URLSearchParams;Object.entries(t).forEach(([t,r])=>{null!=r&&(Array.isArray(r)?r.forEach(r=>e.append(`${t}[]`,r)):e.append(t,r))});const r=e.toString();return r?`?${r}`:""}async processRequestInterceptors(t){let e={...t};for(const s of this.interceptors.request)try{e=await s(e)}catch(r){throw console.error("Request interceptor error:",r),r}return e}async processResponseInterceptors(t,e){let r={success:t.ok,status:t.status,statusText:t.statusText,headers:Object.fromEntries(t.headers.entries()),data:null,errors:null,message:null,reason:null};try{const e=t.headers.get("content-type");if(e&&e.includes("application/json")){const e=await t.json();if(r.data=e,!t.ok){const s=this.categorizeError(new Error("HTTP Error"),t.status);r.errors=e.errors||{},r.message=e.message||s.message,r.reason=s.reason}}else if(r.data=await t.text(),!t.ok){const e=this.categorizeError(new Error("HTTP Error"),t.status);r.message=e.message,r.reason=e.reason}}catch(s){r.errors={parse:"Failed to parse response"},r.message="Invalid response format"}for(const i of this.interceptors.response)try{r=await i(r,e)}catch(s){console.error("Response interceptor error:",s)}return r}async request(t,e,r=null,s={},i={}){let n={method:t.toUpperCase(),url:this.buildUrl(e)+this.buildQueryString(s),headers:{...this.config.headers,...i.headers},data:r,options:{timeout:this.config.timeout,...i}};try{n=await this.processRequestInterceptors(n)}catch(l){if("AuthRequiredError"===l.name)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("header"===this.config.duidTransport)n.headers[this.config.duidHeader]=this.duid;else if("GET"===n.method){const t=new URL(n.url);t.searchParams.append("duid",this.duid),n.url=t.toString()}else!n.data||"object"!=typeof n.data||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]:1===o.length&&(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"]):"object"==typeof n.data?a.body=JSON.stringify(n.data):a.body=n.data);try{const t=await fetch(n.url,a),e=await this.processResponseInterceptors(t,n);return i.dataOnly&&e.data&&"object"==typeof e.data&&"data"in e.data&&(e.message=e.message||e.data.message,e.data=e.data.data),e}catch(l){if("AbortError"===l.name)throw l;const t=this.categorizeError(l),e={success:!1,status:0,statusText:"Network Error",headers:{},data:null,errors:{network:l.message},message:t.message,reason:t.reason},r={ok:!1,status:0,statusText:"Network Error",headers:new Headers,json:async()=>({}),text:async()=>""};return await this.processResponseInterceptors(r,n),e}}async GET(t,e={},r={}){return this.request("GET",t,null,e,r)}async POST(t,e={},r={},s={}){return this.request("POST",t,e,r,s)}async PUT(t,e={},r={},s={}){return this.request("PUT",t,e,r,s)}async PATCH(t,e={},r={},s={}){return this.request("PATCH",t,e,r,s)}async DELETE(t,e={},r={}){return this.request("DELETE",t,null,e,r)}get(...t){return this.GET(...t)}post(...t){return this.POST(...t)}put(...t){return this.PUT(...t)}patch(...t){return this.PATCH(...t)}delete(...t){return this.DELETE(...t)}async download(t,e={},r={}){const s={method:"GET",url:this.buildUrl(t)+this.buildQueryString(e),headers:{...this.config.headers,Accept:"*/*",...r.headers},options:{...r}};delete s.headers["Content-Type"];try{const t=await fetch(s.url,{method:s.method,headers:s.headers,signal:s.options.signal});if(!t.ok)throw new Error(`Download failed: ${t.status} ${t.statusText}`);const e=t.headers.get("content-disposition");let i=r.filename||"download";if(e){const t=e.match(/filename="?(.+)"?/);t&&t.length>1&&(i=t[1])}const n=t.body.getReader(),a=new ReadableStream({start:t=>function e(){return n.read().then(({done:r,value:s})=>{if(!r)return t.enqueue(s),e();t.close()})}()}),o=await new Response(a).blob(),l=window.URL.createObjectURL(o),c=document.createElement("a");return c.style.display="none",c.href=l,c.download=i,document.body.appendChild(c),c.click(),window.URL.revokeObjectURL(l),c.remove(),{success:!0,message:"Download initiated"}}catch(i){return console.error("Download error:",i),{success:!1,message:i.message}}}async downloadBlob(t,e={},r={}){const s={method:"GET",url:this.buildUrl(t)+this.buildQueryString(e),headers:{...this.config.headers,Accept:"*/*",...r.headers},options:{...r}};delete s.headers["Content-Type"];try{const t=await fetch(s.url,{method:s.method,headers:s.headers,signal:s.options.signal});if(!t.ok)throw new Error(`Download failed: ${t.status} ${t.statusText}`);const e=await t.blob(),i=t.headers.get("content-disposition");let n=r.filename||"download";if(i){const t=i.match(/filename="?(.+)"?/);t&&t.length>1&&(n=t[1])}const a=window.URL.createObjectURL(e),o=document.createElement("a");return o.style.display="none",o.href=a,o.download=n,document.body.appendChild(o),o.click(),window.URL.revokeObjectURL(a),o.remove(),{success:!0,message:"Download initiated"}}catch(i){return console.error("Download error:",i),{success:!1,message:i.message}}}async upload(t,e,r={}){return new Promise((s,i)=>{if(!(e instanceof File))return void i(new Error("Only single File objects are supported for legacy backend compatibility"));const n=new XMLHttpRequest;r.onProgress&&"function"==typeof r.onProgress&&(n.upload.onprogress=r.onProgress),n.onload=function(){n.status>=200&&n.status<300?s({data:n.response,status:n.status,statusText:n.statusText,xhr:n}):i(new Error(`Upload failed: ${n.status} ${n.statusText}`))},n.onerror=function(){i(new Error("Upload failed: Network error"))},n.ontimeout=function(){i(new Error("Upload failed: Timeout"))},n.open("PUT",t),n.setRequestHeader("Content-Type",e.type),r.timeout&&(n.timeout=r.timeout),n.send(e)})}async uploadMultipart(t,e,r={},s={}){const i=new FormData;if(e instanceof FileList)Array.from(e).forEach((t,e)=>{i.append(`file_${e}`,t)});else if(e instanceof File)i.append("file",e);else if(e instanceof FormData)return this.POST(t,e,{},s);return Object.entries(r).forEach(([t,e])=>{i.append(t,e)}),this.POST(t,i,{},s)}setAuthToken(t,e="Bearer"){t?this.config.headers.Authorization=`${e} ${t}`:delete this.config.headers.Authorization}clearAuth(){delete this.config.headers.Authorization}isRetryableError(t){return["not_reachable","timed_out","server_error","dns_error"].includes(t.reason)}requiresAuth(t){return"unauthorized"===t.reason}isNetworkError(t){return["not_reachable","timed_out","cancelled","cors_error","dns_error"].includes(t.reason)}getUserMessage(t){return t.message?t.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."}[t.reason]||"An error occurred. Please try again."}};class Model{constructor(t={},e={}){this.endpoint=e.endpoint||this.constructor.endpoint||"",this.id=t.id||null,this.attributes={...t},this._=this.attributes,this.originalAttributes={...t},this.errors={},this.loading=!1,this.rest=r,this.options={idAttribute:"id",timestamps:!0,...e}}getContextValue(t){return this.get(t)}get(t){return t.includes(".")||t.includes("|")||void 0===this[t]?MOJOUtils.getContextData(this.attributes,t):"function"==typeof this[t]?this[t]():this[t]}set(t,e,r={}){const s=JSON.parse(JSON.stringify(this.attributes));let i=!1;if(null!=t){if("object"==typeof t){for(const[e,r]of Object.entries(t))i=this._setNestedAttribute(e,r)||i;void 0!==t.id&&(this.id=t.id)}else"id"===t?(this.id=e,i=!0):i=this._setNestedAttribute(t,e);if(i&&!r.silent)if(this.emit("change",this),"string"==typeof t)this.emit(`change:${t}`,e,this);else for(const[e,r]of Object.entries(t)){const t=this._getNestedValue(e);JSON.stringify(this._getNestedValue(e,s))!==JSON.stringify(t)&&this.emit(`change:${e}`,t,this)}}}_setNestedAttribute(t,e){if(!t.includes(".")){const r=this.attributes[t];return this.attributes[t]=e,this[t]=e,r!==e}const r=t.split("."),s=r[0];this.attributes[s]&&"object"==typeof this.attributes[s]||(this.attributes[s]={}),this[s]&&"object"==typeof this[s]||(this[s]={});const i=this._getNestedValue(t);let n=this.attributes[s],a=this[s];for(let l=1;l<r.length-1;l++){const t=r[l];n[t]&&"object"==typeof n[t]||(n[t]={}),a[t]&&"object"==typeof a[t]||(a[t]={}),n=n[t],a=a[t]}const o=r[r.length-1];return n[o]=e,a[o]=e,JSON.stringify(i)!==JSON.stringify(e)}_getNestedValue(t,e=this.attributes){if(!t.includes("."))return e[t];const r=t.split(".");let s=e;for(const i of r){if(null==s||"object"!=typeof s)return;s=s[i]}return s}getData(){return this.attributes}getId(){return this.id}async fetch(t={}){let e=t.url;if(!e){const r=t.id||this.getId();if(!r&&!1!==this.options.requiresId)throw new Error("Model: ID is required for fetching");e=this.buildUrl(r)}const r=JSON.stringify({url:e,params:t.params});if(t.debounceMs&&t.debounceMs>0)return this._debouncedFetch(r,t);if(this.currentRequest&&this.currentRequestKey!==r&&(this.abortController?.abort(),this.currentRequest=null),this.currentRequest&&this.currentRequestKey===r)return this.currentRequest;const s=Date.now();if(this.lastFetchTime&&s-this.lastFetchTime<100)return this;this.loading=!0,this.errors={},this.lastFetchTime=s,this.currentRequestKey=r,this.abortController=new AbortController,this.currentRequest=this._performFetch(e,t,this.abortController);try{return await this.currentRequest}catch(i){if("AbortError"===i.name)return this;throw i}finally{this.currentRequest=null,this.currentRequestKey=null,this.abortController=null}}async _debouncedFetch(t,e){return this.debouncedFetchTimeout&&clearTimeout(this.debouncedFetchTimeout),this.cancel(),new Promise((t,r)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const r=await this.fetch({...e,debounceMs:0});t(r)}catch(s){r(s)}},e.debounceMs)})}async _performFetch(t,e,r){try{!e.graph||e.params&&e.params.graph||(e.params||(e.params={}),e.params.graph=e.graph);const s=await this.rest.GET(t,e.params,{signal:r.signal});return s.success?s.data.status?(this.originalAttributes={...this.attributes},s.data.data&&this.set(s.data.data),this.errors={}):this.errors=s.data:this.errors=s.errors||{},s}catch(s){if("AbortError"===s.name)throw s;return this.errors={fetch:s.message},{success:!1,error:s.message,status:s.status||500}}finally{this.loading=!1}}async save(t,e={}){const r=!this.id,s=r?"POST":"PUT",i=r?this.buildUrl():this.buildUrl(this.id);this.loading=!0,this.errors={};try{const r=await this.rest[s](i,t,e.params);return r.success?r.data.status?(this.originalAttributes={...this.attributes},this.set(r.data.data),this.errors={}):this.errors=r.data:this.errors=r.errors||{},r}catch(n){return{success:!1,error:n.message,status:n.status||500}}finally{this.loading=!1}}async destroy(t={}){if(!this.id)return this.errors={destroy:"Cannot destroy model without ID"},{success:!1,error:"Cannot destroy model without ID",status:400};const e=this.buildUrl(this.id);this.loading=!0,this.errors={};try{const r=await this.rest.DELETE(e,t.params);return r.success?(this.attributes={},this.originalAttributes={},this.id=null,this.errors={}):this.errors=r.errors||{},r}catch(r){return this.errors={destroy:r.message},{success:!1,error:r.message,status:r.status||500}}finally{this.loading=!1}}isDirty(){return JSON.stringify(this.attributes)!==JSON.stringify(this.originalAttributes)}getChangedAttributes(){const t={};for(const[e,r]of Object.entries(this.attributes))this.originalAttributes[e]!==r&&(t[e]=r);return t}reset(){for(const t of Object.keys(this.attributes))t in this.originalAttributes||delete this[t];for(const[t,e]of Object.entries(this.originalAttributes))this[t]=e;this.attributes={...this.originalAttributes},this._=this.attributes,this.errors={}}buildUrl(t=null){let e=this.endpoint;return t&&(e=e.endsWith("/")?`${e}${t}`:`${e}/${t}`),e}toJSON(){return{id:this.id,...this.attributes}}validate(){if(this.errors={},this.constructor.validations)for(const[t,e]of Object.entries(this.constructor.validations))this.validateField(t,e);return 0===Object.keys(this.errors).length}validateField(t,e){const r=this.get(t),s=Array.isArray(e)?e:[e];for(const i of s)if("function"==typeof i){const e=i(r,this);if(!0!==e){this.errors[t]=e||`${t} is invalid`;break}}else if("object"==typeof i){if(i.required&&(null==r||""===r)){this.errors[t]=i.message||`${t} is required`;break}if(i.minLength&&r&&r.length<i.minLength){this.errors[t]=i.message||`${t} must be at least ${i.minLength} characters`;break}if(i.maxLength&&r&&r.length>i.maxLength){this.errors[t]=i.message||`${t} must be no more than ${i.maxLength} characters`;break}if(i.pattern&&r&&!i.pattern.test(r)){this.errors[t]=i.message||`${t} format is invalid`;break}}}static async find(t,e={}){const r=new this({},e);return await r.fetch({id:t,...e}),r}static create(t={},e={}){return new this(t,e)}cancel(){return this.currentRequest&&this.abortController?(this.abortController.abort(),!0):!!this.debouncedFetchTimeout&&(clearTimeout(this.debouncedFetchTimeout),this.debouncedFetchTimeout=null,!0)}isFetching(){return!!this.currentRequest}async showError(t){const e=(await Promise.resolve().then(()=>require("./Modal-wrfWfQhv.js")).then(t=>t.Modal$1)).default;await e.alert(t,"Error",{size:"md",class:"text-danger"})}}Object.assign(Model.prototype,e);class Collection{constructor(t={},e=null){if(Array.isArray(t)?t=(e=t)||{}:e=e||t.data||[],this.ModelClass=t.ModelClass||Model,this.models=[],this.loading=!1,this.errors={},this.meta={},this.rest=r,e&&this.add(e),this.params={start:0,size:t.size||10,...t.params},this.endpoint=t.endpoint||this.ModelClass.endpoint||"",!this.endpoint){let t=new this.ModelClass;this.endpoint=t.endpoint}this.restEnabled=!!this.endpoint,void 0!==t.restEnabled&&(this.restEnabled=t.restEnabled),this.options={parse:!0,reset:!0,preloaded:!1,...t}}getModelName(){return this.ModelClass.name}async fetch(t={}){const e=JSON.stringify({...this.params,...t});if(this.currentRequest&&this.currentRequestKey!==e&&(this.abortController?.abort(),this.currentRequest=null),this.currentRequest&&this.currentRequestKey===e)return this.currentRequest;const r=Date.now();if(this.options.rateLimiting&&this.lastFetchTime&&r-this.lastFetchTime<100)return{success:!0,message:"Rate limited, skipping fetch",data:{data:this.toJSON()}};if(!this.restEnabled)return{success:!0,message:"REST disabled, skipping fetch",data:{data:this.toJSON()}};if(this.options.preloaded&&this.models.length>0)return{success:!0,message:"Using preloaded data, skipping fetch",data:{data:this.toJSON()}};const s=this.buildUrl();this.loading=!0,this.errors={},this.lastFetchTime=r,this.currentRequestKey=e,this.abortController=new AbortController,this.currentRequest=this._performFetch(s,t,this.abortController);try{return await this.currentRequest}catch(i){return"AbortError"===i.name?{success:!1,error:"Request cancelled",status:0}:{success:!1,error:i.message,status:i.status||500}}finally{this.currentRequest=null,this.currentRequestKey=null,this.abortController=null}}async _performFetch(t,e,r){const s={...this.params,...e};try{this.emit("fetch:start");const i=await this.rest.GET(t,s,{signal:r.signal});if(i.success&&i.data.status){const t=this.options.parse?this.parse(i):i.data;(this.options.reset||!1!==e.reset)&&this.reset(),this.add(t,{silent:e.silent}),this.errors={},this.emit("fetch:success")}else i.data&&i.data.error?(this.errors=i.data,this.emit("fetch:error",{message:i.data.error,error:i.data})):(this.errors=i.errors||{},this.emit("fetch:error",{error:i.errors}));return i}catch(i){return"AbortError"===i.name?{success:!1,error:"Request cancelled",status:0}:(this.errors={fetch:i.message},this.emit("fetch:error",{message:i.message,error:i}),{success:!1,error:i.message,status:i.status||500})}finally{this.loading=!1,this.emit("fetch:end")}}async updateParams(t,e=!1,r=0){return await this.setParams({...this.params,...t},e,r)}async setParams(t,e=!1,r=0){return this.params=t,e&&this.restEnabled?r>0?(this.debouncedFetchTimeout&&clearTimeout(this.debouncedFetchTimeout),this.cancel(),new Promise((t,e)=>{this.debouncedFetchTimeout=setTimeout(async()=>{try{const e=await this.fetch();t(e)}catch(r){e(r)}},r)})):this.fetch():Promise.resolve(this)}async fetchOne(t,e={}){if(!t)return console.warn("Collection: fetchOne requires an ID"),null;if(!this.restEnabled)return null;try{const r=new this.ModelClass({id:t},{endpoint:this.endpoint,collection:this}),s=await r.fetch(e);if(s.success){if(!0===e.addToCollection){const t=this.get(r.id);t?!1!==e.merge&&t.set(r.attributes):this.add(r,{silent:e.silent})}return r}return console.warn("Collection: fetchOne failed -",s.error||"Unknown error"),null}catch(r){return console.error("Collection: fetchOne error -",r.message),null}}async download(t="json",e={}){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 r=this.buildUrl(),s={...this.params};delete s.start,delete s.size,s.download_format=t;const i=`export-${this.getModelName().toLowerCase()}${this._buildDateRangeSuffix(s)}.${t}`,n={json:"application/json",csv:"text/csv"}[t]||"*/*";return s.filename=i,this.rest.download(r,s,{...e,filename:i,headers:{Accept:n}})}_buildDateRangeSuffix(t={}){const e=t.dr_start,r=t.dr_end;if(!e&&!r)return"";const s=t=>t?String(t).replace(/[^\dA-Za-z_-]/g,"-"):"",i=[],n=t.dr_field||"daterange";return i.push(s(n)),e&&i.push(`from-${s(t.dr_start)}`),r&&i.push(`to-${s(t.dr_end)}`),`-${i.filter(Boolean).join("-")}`}parse(t){return t.data&&Array.isArray(t.data.data)?(this.meta={size:t.data.size||10,start:t.data.start||0,count:t.data.count||0,status:t.data.status,graph:t.data.graph,...t.meta},t.data.data):Array.isArray(t.data)?t.data:Array.isArray(t)?t:[t]}add(t,e={}){const r=Array.isArray(t)?t:[t],s=[];for(const i of r){let t;t=i instanceof this.ModelClass?i:new this.ModelClass(i,{endpoint:this.endpoint,collection:this});const r=this.models.findIndex(e=>e.id===t.id);-1!==r?!1!==e.merge&&this.models[r].set(t.attributes):(this.models.push(t),s.push(t))}return!e.silent&&s.length>0&&(this.emit("add",{models:s,collection:this}),this.emit("update",{collection:this})),s}remove(t,e={}){const r=Array.isArray(t)?t:[t],s=[];for(const i of r){let t=-1;if(t="string"==typeof i||"number"==typeof i?this.models.findIndex(t=>t.id==i):this.models.indexOf(i),-1!==t){const e=this.models.splice(t,1)[0];s.push(e)}}return!e.silent&&s.length>0&&(this.emit("remove",{models:s,collection:this}),this.emit("update",{collection:this})),s}reset(t=null,e={}){const r=[...this.models];return this.models=[],t&&this.add(t,{silent:!0,...e}),e.silent||this.emit("reset",{collection:this,previousModels:r}),this}get(t){return this.models.find(e=>e.id==t)}at(t){return this.models[t]}length(){return this.models.length}isEmpty(){return 0===this.models.length}where(t){return"function"==typeof t?this.models.filter(t):"object"==typeof t?this.models.filter(e=>Object.entries(t).every(([t,r])=>e.get(t)===r)):[]}findWhere(t){const e=this.where(t);return e.length>0?e[0]:void 0}forEach(t,e){if("function"!=typeof t)throw new TypeError("Callback must be a function");return this.models.forEach((r,s)=>{t.call(e,r,s,this)}),this}sort(t,e={}){if("string"==typeof t){const e=t;t=(t,r)=>{const s=t.get(e),i=r.get(e);return s<i?-1:s>i?1:0}}return this.models.sort(t),e.silent||this.emit("sort",{collection:this}),this}toJSON(){return this.models.map(t=>t.toJSON())}cancel(){return!(!this.currentRequest||!this.abortController||(this.abortController.abort(),0))}isFetching(){return!!this.currentRequest}buildUrl(){return this.endpoint}*[Symbol.iterator](){for(const t of this.models)yield t}static fromArray(t,e=[],r={}){const s=new this({ModelClass:t,...r});return s.add(e,{silent:!0}),s}}Object.assign(Collection.prototype,e),exports.Collection=Collection,exports.EventEmitter=e,exports.MOJOUtils=MOJOUtils,exports.Model=Model,exports.dataFormatter=t,exports.rest=r;
2
+ //# sourceMappingURL=Collection-BpUmNuDZ.js.map