@vicaniddouglas/js_aide 1.13.0 → 1.13.2

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.
package/README.md CHANGED
@@ -1,73 +1,51 @@
1
1
  # @vicaniddouglas/js_aide
2
2
 
3
- A versatile collection of modular JavaScript utility helpers designed to streamline single-page application (SPA) development and general web programming tasks. This library provides a set of independent modules for common functionalities such as routing, input handling, validation, and more.
3
+ [![Documentation & Demo](https://img.shields.io/badge/Live-Documentation%20%26%20Demo-blue?style=for-the-badge&logo=gitlab)](https://vicaniddouglas.gitlab.io/js_aide)
4
4
 
5
- ## Description
5
+ **JS Aide** is a high-performance, modular utility collection designed for modern web applications. Whether you're building a native SPA or an enterprise-grade MPA, JS Aide provides the orchestrated power you need.
6
6
 
7
- `@vicaniddouglas/js_aide` bundles frequently needed JavaScript functionalities into a cohesive, easy-to-use package. Each module is designed to be independent, allowing you to import only what you need, reducing bundle size and improving application performance. From dynamic client-side routing to robust input validation and DOM manipulation, this library aims to accelerate your development workflow.
8
-
9
- ## Features
10
-
11
- ### 🎮 Live Playground
12
- Explore all library features—including the new Asynchronous Handshaking system—directly in our interactive sandbox.
13
-
14
- **Access via Repository:**
15
- 1. Clone the repository: `git clone https://gitlab.com/vicaniddouglas/js_aide.git`
16
- 2. Open `demo/index.html` in any modern browser.
17
-
18
- **Access via NPM:**
19
- If you have the package installed locally, you can run the playground using:
20
- ```bash
21
- npm explore @vicaniddouglas/js_aide -- npm run serve:demo
22
- ```
7
+ ## 🕹️ Live Playground
8
+ Explore all library features—including the new Asynchronous Handshaking system—directly in our **[Interactive Sandbox](https://vicaniddouglas.gitlab.io/js_aide)**.
23
9
 
24
10
  ### `Router`
25
11
 
26
- A modern, feature-rich client-side router for Single-Page Applications (SPAs).
12
+ A modern, feature-rich client-side router for Single-Page Applications (SPAs). Features include History API navigation, dynamic route segments (`/users/:id`), and view lifecycle hooks (`beforeEnter`, `beforeLeave`).
27
13
 
28
- - History API-based navigation.
29
- - Supports dynamic route segments (e.g., `/users/:id`).
30
- - Automatic interception of internal `<a>` tags for seamless SPA navigation.
31
- - Configurable route guards (`beforeNavigate`) with support for redirects.
32
- - View lifecycle hooks (`beforeEnter`, `beforeLeave`) directly on DOM elements for managing view transitions and data loading.
33
- - Parses and exposes URL query parameters and hash fragments.
34
- - Efficient view toggling, only hiding the previously active view.
14
+ ### `Validator`
35
15
 
36
- ### `validator`
16
+ A collection of high-precision validation utilities. Handles complex email logic, phone number formatting, and mandatory field checks out of the box.
37
17
 
38
- A module offering various input validation utilities (e.g., email, number, custom regex).
18
+ ### `Input Handlers`
39
19
 
40
- ### `inputHandlers`
20
+ Utilities for enhanced DOM interaction, such as restricting input to specific characters, real-time number formatting, and custom select behaviors.
41
21
 
42
- Utilities for enhanced DOM element interaction, such as restricting input to numbers, formatting number inputs, or providing custom select options.
22
+ ### `HTTP Engine`
43
23
 
44
- ### `requests`
24
+ A "Zero-Touch" HTTP client built on `sendRequest`. Features automatic retries with exponential backoff, request queuing, and standardized response objects.
45
25
 
46
- Helper functions for making HTTP requests (e.g., `fetch` wrappers for common patterns).
26
+ ### `Dates & Timing`
47
27
 
48
- ### `dates`
28
+ Convenience functions for complex date manipulation, including relative timing (`timeAgo`), `humanizeDate`, and range calculations.
49
29
 
50
- Convenience functions for common date and time manipulation tasks.
30
+ ### `File Manager`
51
31
 
52
- ### `fileManager`
32
+ Robust utilities for browser-side file handling, including dynamic `DataExporter` for Excel/PDF and secure file upload orchestration.
53
33
 
54
- Utilities for browser-side file handling (e.g., file uploads, local storage, file type checks).
34
+ ### `Camera`
55
35
 
56
- ### `camera`
36
+ Advanced module for interacting with device cameras, allowing image capture and video stream management with a single promise-based API.
57
37
 
58
- Functions for interacting with device cameras, capturing images or video streams (requires browser API support).
38
+ ### `Figures & Formatting`
59
39
 
60
- ### `figures`
40
+ Specialized formatting for financial data. Includes native support for **UGX** (Ugandan Shilling) currency defaults and abbreviated large numbers.
61
41
 
62
- Utilities for number formatting, currency (including UGX defaults), and percentages.
42
+ ### `Dependency Manager`
63
43
 
64
- ### `dependencyManager`
44
+ A smart loader for external libraries (like SheetJS or jsPDF). Manages CDN fallbacks, retry logic, and ensures libraries are only loaded when needed.
65
45
 
66
- A robust manager for dynamically loading CDN-based libraries (like SheetJS or jsPDF) with retry logic and dependency tracking.
46
+ ### `WebSocket Client`
67
47
 
68
- ### `WebSocketClient`
69
-
70
- A professional-grade WebSocket client featuring automatic reconnection, heartbeat/health monitoring, and a built-in instance registry to prevent duplicate connections. Supports namespaces, rooms, and message acknowledgements.
48
+ A professional-grade WebSocket implementation with automatic reconnection, heartbeat monitoring, and a registry to prevent duplicate connections.
71
49
 
72
50
  ## Installation
73
51
 
@@ -92,11 +70,13 @@ Ensure your project is configured to use ES Modules (e.g., by adding `"type": "m
92
70
  You can import specific modules or all of them:
93
71
 
94
72
  ```javascript
95
- // Import specific modules
96
- import { Router, validator } from "@vicaniddouglas/js_aide";
97
-
98
- // Or import all, though generally not recommended for tree-shaking
99
- // import * => JSAide from '@vicaniddouglas/js_aide';
73
+ // Import specific modules for best tree-shaking
74
+ import {
75
+ Router,
76
+ sendRequest,
77
+ validatePhoneNumber,
78
+ humanizeDate
79
+ } from "@vicaniddouglas/js_aide";
100
80
  ```
101
81
 
102
82
  ### Example: Using the Router
@@ -1071,7 +1071,7 @@ var PA=Object.defineProperty;var Y2=Object.getOwnPropertyDescriptor;var S2=Objec
1071
1071
  color: #ef4444;
1072
1072
  font-weight: 600;
1073
1073
  }
1074
- `}static injectStyles(){if(document.querySelector("style[data-smart-input]"))return;let A=document.createElement("style");A.setAttribute("data-smart-input","");let I=document.head.firstChild;I?document.head.insertBefore(A,I):document.head.appendChild(A),A.textContent=N.defaultCSS}_createInputWrapper(A,I,O=[]){let U=document.createElement("div");U.className=["smart-input-wrapper",...O].join(" ");let E=document.createElement("label");return E.htmlFor=A,E.textContent=I,E.className="smart-input-label",U.appendChild(E),U}_mount(A,I){I.appendChild(A)}_makeHandle(A,I,O={}){return{element:A,getValue:O.getValue||(()=>A.value),setValue:O.setValue||(U=>{A.value=U}),clear:O.clear||(()=>{A.value=""}),destroy:O.destroy||(()=>{I.remove()})}}getInput(A){return this.inputs[A]||null}createNumberInput({id:A,labelText:I,container:O,placeholder:U="Enter numbers only",wrapperClasses:E=[],inputClasses:B=[]}){if(!O)return console.error("SmartInput: container element is required"),null;let R=this._createInputWrapper(A,I,E),K=document.createElement("input");K.type="text",K.id=A,K.className=["smart-input","smart-input-number",...B].join(" "),K.placeholder=U,K.addEventListener("input",L=>{let G="";for(let T of L.target.value)"0123456789".includes(T)&&(G+=T);L.target.value=G}),R.appendChild(K),this._mount(R,O);let M=this._makeHandle(K,R);return this.inputs[A]=M,M}createFormattedNumberInput({id:A,labelText:I,container:O,placeholder:U="Enter amount (e.g., 1,234.56)",wrapperClasses:E=[],inputClasses:B=[]}){if(!O)return console.error("SmartInput: container element is required"),null;let R=this._createInputWrapper(A,I,E),K=document.createElement("input");K.type="text",K.id=A,K.className=["smart-input","smart-input-formatted-number",...B].join(" "),K.placeholder=U;let M=G=>{let T="",W=!1;for(let r of G)"0123456789".includes(r)?T+=r:r==="."&&!W&&(T+=r,W=!0);let S=T.indexOf("."),Y=S>=0?T.substring(0,S):T,i=S>=0?T.substring(S):"",t="";if(Y.length>0){let r=Y.split("").reverse().join(""),P="";for(let H=0;H<r.length;H++)P+=r[H],(H+1)%3===0&&H+1!==r.length&&(P+=",");t=P.split("").reverse().join("")}return t+i};K.addEventListener("input",G=>{G.target.value=M(G.target.value)}),R.appendChild(K),this._mount(R,O);let L=this._makeHandle(K,R,{setValue:G=>{K.value=M(String(G))}});return this.inputs[A]=L,L}createSearchableInput({id:A,labelText:I,container:O,data:U=[],placeholder:E="Search...",wrapperClasses:B=[],inputClasses:R=[],dropdownClasses:K=[]}){if(!O)return console.error("SmartInput: container element is required"),null;let M=this._createInputWrapper(A,I,["smart-input-searchable-wrapper",...B]),L=document.createElement("input");L.type="text",L.id=A,L.className=["smart-input","smart-input-searchable",...R].join(" "),L.placeholder=E;let G=document.createElement("ul");G.className=["smart-input-dropdown",...K].join(" ");let T=null,W=U,S=()=>G.classList.add("smart-input-dropdown-visible"),Y=()=>{G.classList.remove("smart-input-dropdown-visible"),L.setAttribute("data-value",T!=null?T:"")},i=P=>{let H=document.createDocumentFragment(),EA=P.toLowerCase(),V=W.filter(Q=>Q.key.toLowerCase().includes(EA));if(V.length>0){for(let Q of V){let UA=document.createElement("li");UA.textContent=Q.key,UA.dataset.value=Q.value,UA.className="smart-input-dropdown-item",UA.addEventListener("mousedown",W2=>{W2.preventDefault(),L.value=Q.key,T=Q.value,Y(),L.focus()}),H.appendChild(UA)}G.replaceChildren(H),S()}else G.replaceChildren(),Y()};L.addEventListener("focus",()=>i(L.value)),L.addEventListener("input",()=>{T=null,i(L.value)}),L.addEventListener("blur",()=>{setTimeout(()=>{M.contains(document.activeElement)||Y()},150)});let t=new AbortController;document.addEventListener("click",P=>{M.contains(P.target)||Y()},{signal:t.signal}),M.appendChild(L),M.appendChild(G),this._mount(M,O);let r=this._makeHandle(L,M,{getValue:()=>T,setValue:({key:P,value:H})=>{L.value=P,T=H,L.setAttribute("data-value",H!=null?H:"")},clear:()=>{L.value="",T=null,L.removeAttribute("data-value"),Y()},destroy:()=>{t.abort(),M.remove()}});return r.setData=P=>{W=P,i(L.value)},this.inputs[A]=r,r}createLimitedTextInput({id:A,labelText:I,container:O,maxLength:U,allowedCharactersString:E="",placeholder:B="",wrapperClasses:R=[],inputClasses:K=[]}){if(!O)return console.error("SmartInput: container element is required"),null;if(!U)return console.error("SmartInput: maxLength is required for createLimitedTextInput"),null;let M=Math.max(1,Math.round(U*.1)),L=this._createInputWrapper(A,I,R),G=document.createElement("input");G.type="text",G.id=A,G.className=["smart-input","smart-input-limited",...K].join(" "),G.maxLength=U,G.placeholder=B||`Max ${U} characters`;let T=document.createElement("span");T.className="smart-input-char-count";let W=()=>{let Y=G.value.length,i=U-Y;T.textContent=`${Y} / ${U}`,T.classList.remove("smart-input-char-warn","smart-input-char-over"),i<0?T.classList.add("smart-input-char-over"):i<=M&&T.classList.add("smart-input-char-warn")};G.addEventListener("input",Y=>{if(E){let i="";for(let t of Y.target.value)E.includes(t)&&(i+=t);Y.target.value=i}W()}),W(),L.appendChild(G),L.appendChild(T),this._mount(L,O);let S=this._makeHandle(G,L,{setValue:Y=>{G.value=Y,W()},clear:()=>{G.value="",W()}});return this.inputs[A]=S,S}createAutoExpandingTextArea({id:A,labelText:I,container:O,placeholder:U="",minHeight:E=150,maxHeight:B=300,wrapperClasses:R=[],inputClasses:K=[]}){if(!O)return console.error("SmartInput: container element is required"),null;let M=this._createInputWrapper(A,I,R),L=document.createElement("textarea");L.id=A,L.className=["smart-input","smart-input-textarea",...K].join(" "),L.placeholder=U,L.style.resize="none",L.style.overflowY="hidden",L.style.minHeight=`${E}px`;let G=()=>{L.style.height="auto";let W=L.scrollHeight,S=Math.min(Math.max(W,E),B);L.style.height=`${S}px`,W>B?L.style.overflowY="auto":L.style.overflowY="hidden"};L.addEventListener("input",G),M.appendChild(L),this._mount(M,O);let T=this._makeHandle(L,M,{setValue:W=>{L.value=W,G()},clear:()=>{L.value="",G()}});return setTimeout(G,0),this.inputs[A]=T,T}createSelectInput({id:A,labelText:I,container:O,optionsData:U=[],wrapperClasses:E=[],inputClasses:B=[]}){if(!O)return console.error("SmartInput: container element is required"),null;let R=this._createInputWrapper(A,I,E),K=document.createElement("select");K.id=A,K.className=["smart-input","smart-input-select",...B].join(" ");for(let L of U){let G=document.createElement("option");G.value=L.value,G.textContent=L.key,K.appendChild(G)}R.appendChild(K),this._mount(R,O);let M=this._makeHandle(K,R,{getValue:()=>K.value,setValue:L=>{K.value=L},clear:()=>{K.selectedIndex=0}});return this.inputs[A]=M,M}};var d=(function(){let N={apiUrl:null,timeout:6e5,maxRetries:3,retryStrategy:"exponential",csrfToken:null,authToken:null,environment:"development",keys:{globalConfig:"APP_CONFIG",authToken:"auth_token",csrfToken:"csrf-token",csrfCookie:"XSRF-TOKEN"}};return{init(A={}){A.keys&&(N.keys={...N.keys,...A.keys}),window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1"?N.environment="development":N.environment="production";let I=N.keys.globalConfig;window[I]&&window[I].apiUrl&&(N.apiUrl=window[I].apiUrl,window[I].environment&&(N.environment=window[I].environment));let O=document.querySelector('meta[name="api-url"]');O&&(N.apiUrl=O.getAttribute("content")),Object.assign(N,A),this.validate()},validate(){!N.apiUrl&&N.environment==="production"&&console.warn("RequestHandler: API URL is missing in production environment.")},get:()=>N}})(),vA={getCsrfToken(){let N=d.get().keys;if(d.get().csrfToken)return d.get().csrfToken;let A=document.querySelector(`meta[name="${N.csrfToken}"]`);if(A)return A.getAttribute("content");let I=N.csrfCookie+"=",U=decodeURIComponent(document.cookie).split(";");for(let E=0;E<U.length;E++){let B=U[E].trim();if(B.indexOf(I)===0)return B.substring(I.length,B.length)}return null},getAuthToken(){let N=d.get().keys;return d.get().authToken?d.get().authToken:sessionStorage.getItem(N.authToken)||localStorage.getItem(N.authToken)},sanitizePayload(N){if(!N||typeof N!="object"||N instanceof FormData)return N;let A=JSON.parse(JSON.stringify(N)),I=O=>{for(let U in O)typeof O[U]=="string"?O[U]=O[U].replace(/<script\b[^>]*>([\s\S]*?)<\/script>/gim,"").replace(/javascript:/gim,""):typeof O[U]=="object"&&O[U]!==null&&I(O[U])};return I(A),A}},_={request:[],response:[],error:[],addRequest(N,A){let I=Date.now()+Math.random();return this.request.push({id:I,onFulfilled:N,onRejected:A}),I},addResponse(N,A){let I=Date.now()+Math.random();return this.response.push({id:I,onFulfilled:N,onRejected:A}),I},addError(N){this.error.push(N)},clear(){this.request=[],this.response=[],this.error=[]}},c1=(function(){let N=[],A=0,I=3,O=()=>{if(A>=I||N.length===0)return;N.sort((E,B)=>B.priority-E.priority);let U=N.shift();A++,U.execute().finally(()=>{A--,O()})};return{add(U,E=0){return new Promise((B,R)=>{N.push({priority:E,execute:()=>U().then(B).catch(R)}),O()})},getStatus:()=>({active:A,pending:N.length}),clear:()=>{N.length=0}}})(),hA=async function(N={}){let I={...{method:"POST",endpoint:"",payload:null,headers:{},timeout:d.get().timeout,maxRetries:d.get().maxRetries,retryStrategy:d.get().retryStrategy,useQueue:!1,priority:0,responseType:"json",showLoading:null,onSuccess:null,onError:null,onProgress:null,silent:!1},...N};for(let R of _.request)try{R.onFulfilled&&(I=await R.onFulfilled(I))}catch(K){if(R.onRejected)return R.onRejected(K);throw K}let O=(R,K)=>{let M=K>=200&&K<300;if(R&&typeof R=="object"&&"status"in R){let L=R.status===!0;return{status:L&&M,log:L&&M?"":R.log||"Error",data:R.data!==void 0?R.data:R,httpCode:K}}return{status:M,log:M?"":(R==null?void 0:R.message)||(R==null?void 0:R.error)||`Request failed with status ${K}`,data:M?R:null,httpCode:K}},U=async(R=0)=>{I.showLoading&&await I.showLoading(!0);try{let K=new XMLHttpRequest,M=I.endpoint.startsWith("http")?I.endpoint:`${d.get().apiUrl}/${I.endpoint.replace(/^\//,"")}`;return await new Promise(L=>{K.open(I.method,M,!0),K.timeout=I.timeout;let G=vA.getCsrfToken();G&&K.setRequestHeader("X-CSRF-Token",G);let T=vA.getAuthToken();T&&K.setRequestHeader("Authorization",`Bearer ${T}`),K.setRequestHeader("X-Requested-With","XMLHttpRequest");let W=I.headers||{};!Object.keys(W).some(t=>t.toLowerCase()==="content-type")&&!(I.payload instanceof FormData)&&K.setRequestHeader("Content-Type","application/json"),Object.keys(W).forEach(t=>{K.setRequestHeader(t,W[t])}),I.onProgress&&K.upload&&(K.upload.onprogress=t=>{if(t.lengthComputable){let r=Math.round(t.loaded/t.total*100);I.onProgress(r)}}),K.onload=async()=>{I.showLoading&&await I.showLoading(!1);let t;try{t=I.responseType==="json"?JSON.parse(K.responseText):K.response}catch{t=K.responseText}let r={},P=K.getAllResponseHeaders();P&&P.trim().split(/[\r\n]+/).forEach(EA=>{let V=EA.split(": "),Q=V.shift(),UA=V.join(": ");r[Q.toLowerCase()]=UA});let H=O(t,K.status);if(K.status>=200&&K.status<300){if(H.status===!1){I.onError&&await I.onError(H.log),I.silent||await o.error(H.log);for(let V of _.response)V.onFulfilled&&await V.onFulfilled({...H,url:M});L(H);return}let EA={data:t.data||t,status:K.status,url:M,headers:r};for(let V of _.response)V.onFulfilled&&(EA=await V.onFulfilled(EA));I.onSuccess&&await I.onSuccess(H.data),L(H)}else await E(K,R,U,r,t,L)},K.onerror=()=>E(K,R,U,{},null,L),K.ontimeout=()=>E({status:408},R,U,{},null,L);let Y=vA.sanitizePayload(I.payload),i=Y;!(Y instanceof FormData)&&typeof Y=="object"&&Y!==null&&(i=JSON.stringify(Y)),K.send(i)})}catch(K){I.showLoading&&await I.showLoading(!1);let M=K.message||"Critical Runtime Error";return I.onError&&await I.onError(M),I.silent||await o.error(M),{status:!1,log:M,data:null}}},E=async(R,K,M,L,G,T)=>{let W=I.endpoint.startsWith("http")?I.endpoint:`${d.get().apiUrl}/${I.endpoint.replace(/^\//,"")}`;if(K<I.maxRetries&&(R.status>=500||R.status===408||R.status===0)){let S=B(K,I.retryStrategy);setTimeout(()=>M(K+1).then(T),S)}else{I.showLoading&&await I.showLoading(!1);let S=O(G,R.status);I.onError&&await I.onError(S.log),I.silent||await o.error(S.log),_.error.forEach(Y=>Y(R));for(let Y of _.response)Y.onFulfilled&&await Y.onFulfilled({...S,url:W});T(S)}},B=(R,K)=>{switch(K){case"linear":return(R+1)*1e3;case"fibonacci":return([1,1,2,3,5,8][R]||13)*1e3;case"exponential":return Math.pow(2,R)*1e3;default:return 1e3}};return I.useQueue?c1.add(()=>U(),I.priority):U()},l1=N=>d.init(N),h1={request:(N,A)=>_.addRequest(N,A),response:(N,A)=>_.addResponse(N,A),error:N=>_.addError(N),clear:()=>_.clear()},J1=()=>c1.getStatus();document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>d.init()):d.init();function AA(N,A={}){let{showAlert:I=!1}=A;if(typeof N!="string")return I&&console.error("Invalid input: Date must be a string."),!1;let O=N.trim().split("-");if(O.length!==3||O[0].length!==4||O[1].length!==2||O[2].length!==2)return I&&o.error("Invalid date format. Use YYYY-MM-DD."),!1;if(O.some(K=>isNaN(K)))return I&&o.error("Date must contain only numbers."),!1;let[U,E,B]=O.map(Number);if(E<1||E>12||B<1||B>31)return I&&o.error("Invalid month or day range."),!1;let R=new Date(U,E-1,B);return R.getFullYear()!==U||R.getMonth()!==E-1||R.getDate()!==B?(I&&o.error("Invalid date. Please enter a real date."),!1):!0}function d1(N,A={}){let{format:I="weekday",locale:O="en-US",includeYear:U=!0}=A;if(!AA(N,{showAlert:!1}))throw new Error("Invalid date format. Use YYYY-MM-DD.");let E=N.split("-"),B=new Date(E[0],E[1]-1,E[2]),R={short:{year:"numeric",month:"numeric",day:"numeric"},medium:{year:"numeric",month:"short",day:"numeric"},long:{year:"numeric",month:"long",day:"numeric"},full:{weekday:"long",year:"numeric",month:"long",day:"numeric"},weekday:{weekday:"short",year:"numeric",month:"short",day:"numeric"}},K=R[I]||R.weekday;return U||(K={...K},delete K.year),B.toLocaleString(O,K)}function u1(N,A={}){let{locale:I="en-US"}=A;if(!AA(N,{showAlert:!1}))throw new Error("Invalid date format. Use YYYY-MM-DD.");let O=N.split("-"),B=new Date(O[0],O[1]-1,O[2])-new Date,R=Math.round(B/(1e3*60*60*24)),K=new Intl.RelativeTimeFormat(I,{numeric:"auto"});if(Math.abs(R)<1){let M=Math.round(B/36e5);return K.format(M,"hour")}else{if(Math.abs(R)<7)return K.format(R,"day");if(Math.abs(R)<30){let M=Math.round(R/7);return K.format(M,"week")}else if(Math.abs(R)<365){let M=Math.round(R/30);return K.format(M,"month")}else{let M=Math.round(R/365);return K.format(M,"year")}}}function Z1(){let N=new Date,A=N.getFullYear(),I=String(N.getMonth()+1).padStart(2,"0"),O=String(N.getDate()).padStart(2,"0");return`${A}-${I}-${O}`}function p1(){let N=new Date;N.setDate(N.getDate()-1);let A=N.getFullYear(),I=String(N.getMonth()+1).padStart(2,"0"),O=String(N.getDate()).padStart(2,"0");return`${A}-${I}-${O}`}function m1(N,A={}){let{showSeconds:I=!0}=A,O=new Date,U=new Date(N);if(isNaN(U.getTime()))return"Invalid timestamp";let E=O-U,B=Math.floor(E/1e3),R=Math.floor(B/60),K=Math.floor(R/60),M=Math.floor(K/24),L=Math.floor(M/7),G=Math.floor(M/30),T=Math.floor(M/365);return B<60?I?`${B} second${B!==1?"s":""} ago`:"now":R<60?`${R} minute${R!==1?"s":""} ago`:K<24?`${K} hour${K!==1?"s":""} ago`:M<7?`${M} day${M!==1?"s":""} ago`:L<4?`${L} week${L!==1?"s":""} ago`:G<12?`${G} month${G!==1?"s":""} ago`:`${T} year${T!==1?"s":""} ago`}function g1(N,A,I){if(!AA(N,{showAlert:!1}))throw new Error("Invalid date format. Use YYYY-MM-DD.");let O=new Date(N),E={days:()=>O.setDate(O.getDate()+A),weeks:()=>O.setDate(O.getDate()+A*7),months:()=>O.setMonth(O.getMonth()+A),years:()=>O.setFullYear(O.getFullYear()+A)}[I.toLowerCase()];if(!E)throw new Error(`Invalid unit: ${I}. Use: days, weeks, months, years`);return E(),O.toISOString().split("T")[0]}function f1(N){let A=new Date,I=K=>{let M=K.getFullYear(),L=String(K.getMonth()+1).padStart(2,"0"),G=String(K.getDate()).padStart(2,"0");return`${M}-${L}-${G}`},O=K=>{let M=K.getDay(),L=K.getDate()-M+(M===0?-6:1),G=new Date(K);return G.setDate(L),G},U=K=>new Date(K.getFullYear(),K.getMonth(),1),E=K=>new Date(K.getFullYear(),K.getMonth()+1,0),B,R;switch(N.toLowerCase()){case"today":{B=I(A),R=I(A);break}case"yesterday":{let K=new Date(A);K.setDate(A.getDate()-1),B=I(K),R=I(K);break}case"thisweek":{let K=O(A);B=I(K),R=I(A);break}case"lastweek":{let K=new Date(A);K.setDate(A.getDate()-7);let M=O(K),L=new Date(M);L.setDate(M.getDate()+6),B=I(M),R=I(L);break}case"thismonth":{let K=U(A);B=I(K),R=I(A);break}case"lastmonth":{let K=new Date(A.getFullYear(),A.getMonth()-1,1),M=U(K),L=E(K);B=I(M),R=I(L);break}default:throw new Error(`Unknown keyword: ${N}. Use: today, yesterday, thisWeek, lastWeek, thisMonth, lastMonth`)}return[B,R]}function w1(N,A){let I=new Date,U={days:()=>I.setDate(I.getDate()-N),weeks:()=>I.setDate(I.getDate()-N*7),months:()=>I.setMonth(I.getMonth()-N),years:()=>I.setFullYear(I.getFullYear()-N)}[A.toLowerCase()];if(!U)throw new Error(`Invalid unit: ${A}. Use: days, weeks, months, years`);U();let E=I.getFullYear(),B=String(I.getMonth()+1).padStart(2,"0"),R=String(I.getDate()).padStart(2,"0");return`${E}-${B}-${R}`}function v1(){let N=new Date;N.setDate(N.getDate()+1);let A=N.getFullYear(),I=String(N.getMonth()+1).padStart(2,"0"),O=String(N.getDate()).padStart(2,"0");return`${A}-${I}-${O}`}function V1(N){let A=new Date,I=M=>{let L=M.getFullYear(),G=String(M.getMonth()+1).padStart(2,"0"),T=String(M.getDate()).padStart(2,"0");return`${L}-${G}-${T}`},O=M=>{let L=M.getDay(),G=M.getDate()-L+(L===0?-6:1),T=new Date(M);return T.setDate(G),T},U=M=>{let L=O(M),G=new Date(L);return G.setDate(L.getDate()+6),G},E=M=>new Date(M.getFullYear(),M.getMonth(),1),B=M=>new Date(M.getFullYear(),M.getMonth()+1,0),R,K;switch(N.toLowerCase()){case"tomorrow":{let M=new Date(A);M.setDate(A.getDate()+1),R=I(M),K=I(M);break}case"nextweek":{let M=new Date(A);M.setDate(A.getDate()+7);let L=O(M),G=U(M);R=I(L),K=I(G);break}case"nextmonth":{let M=new Date(A.getFullYear(),A.getMonth()+1,1),L=E(M),G=B(M);R=I(L),K=I(G);break}case"nextyear":{let M=new Date(A.getFullYear()+1,0,1),L=new Date(A.getFullYear()+1,11,31);R=I(M),K=I(L);break}default:throw new Error(`Unknown keyword: ${N}. Use: tomorrow, nextWeek, nextMonth, nextYear`)}return[R,K]}function y1(N,A,I={}){let{inclusiveEndDate:O=!1}=I;if(!AA(N,{showAlert:!1})||!AA(A,{showAlert:!1}))throw new Error("Invalid date format. Use YYYY-MM-DD.");let U=new Date(N),E=new Date(A);if(U>E)throw new Error("Start date cannot be after end date.");let B=E-U,R=Math.floor(B/(1e3*60*60*24));return O&&(R+=1),R}function x1(N,A,I={}){let{startDate:O}=I,U;if(O){if(!AA(O,{showAlert:!1}))throw new Error("Invalid start date format. Use YYYY-MM-DD.");U=new Date(O)}else U=new Date;if(typeof N!="number"||N<0)throw new Error("Amount must be a positive number.");let B={days:()=>U.setDate(U.getDate()+N),weeks:()=>U.setDate(U.getDate()+N*7),months:()=>U.setMonth(U.getMonth()+N),years:()=>U.setFullYear(U.getFullYear()+N)}[A.toLowerCase()];if(!B)throw new Error(`Invalid unit: ${A}. Use: days, weeks, months, years`);B();let R=U.getFullYear(),K=String(U.getMonth()+1).padStart(2,"0"),M=String(U.getDate()).padStart(2,"0");return`${R}-${K}-${M}`}function F1(N){let A=new Date;return A.setHours(0,0,0,0),new Date(N)>A}function b1(N){let A=new Date;return A.setHours(0,0,0,0),new Date(N)<A}var VA=class{constructor(){this.dependencies={sheetjs:{name:"SheetJS",cdn:"https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js",check:()=>typeof XLSX<"u"&&!!XLSX.utils},jspdf:{name:"jsPDF",cdn:"https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js",check:()=>typeof(window.jsPDF||window.jspdf&&window.jspdf.jsPDF)<"u"},jspdfAutotable:{name:"jsPDF AutoTable",cdn:"https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.5.28/jspdf.plugin.autotable.min.js",check:()=>{let A=window.jsPDF||window.jspdf&&window.jspdf.jsPDF;return typeof A<"u"&&(typeof A.autoTable<"u"||A.API&&typeof A.API.autoTable<"u")},requires:["jspdf"]}},this.loadingPromises=new Map}register(A,I){this.dependencies[A]&&console.warn(`Dependency "${A}" is already registered. Overwriting.`),this.dependencies[A]=I}hasDependency(A){let I=this.dependencies[A];if(!I)return!1;if(I.requires){for(let O of I.requires)if(!this.hasDependency(O))return!1}return I.check()}async loadDependency(A,I=0){if(this.loadingPromises.has(A))return this.loadingPromises.get(A);let O=this.dependencies[A];if(!O)throw new Error(`Unknown dependency: ${A}`);if(this.hasDependency(A))return!0;if(O.requires)for(let R of O.requires)await this.loadDependency(R);let U=O.maxRetries||2,E=[O.cdn,...O.fallbacks||[]],B=(async()=>{let R;for(let K of E)try{return await this._injectScript(O,K),this.loadingPromises.delete(A),!0}catch(M){R=M,console.warn(`Failed to load ${O.name} from ${K}:`,M.message)}if(I<U)return this.loadingPromises.delete(A),this.loadDependency(A,I+1);throw this.loadingPromises.delete(A),R||new Error(`Failed to load ${O.name} after all attempts.`)})();return this.loadingPromises.set(A,B),B}_injectScript(A,I){return new Promise((O,U)=>{let E=document.createElement("script");E.src=I,E.async=!0,A.integrity&&(E.integrity=A.integrity,E.crossOrigin=A.crossorigin||"anonymous"),E.onload=()=>{let B=0,R=setInterval(()=>{A.check()?(clearInterval(R),O(!0)):B>20&&(clearInterval(R),U(new Error(`Library ${A.name} loaded but failed verification.`))),B++},50)},E.onerror=()=>U(new Error("Network error or CSP violation")),document.head.appendChild(E),setTimeout(()=>{E.parentNode&&(E.remove(),U(new Error(`Timeout (10s) reached for ${I}`)))},1e4)})}async ensureDependency(A,I=null){try{return this.hasDependency(A)||await this.loadDependency(A),!0}catch(O){if(console.error(`Dependency Manager error [${A}]:`,O.message),I)return I();throw O}}},BA=new VA;async function SA(N,A,I="download",O={}){let{maxSize:U=50*1024*1024,onProgress:E=null,fallbackFormats:B=!0,csvDelimiter:R=",",pdfOptions:K={}}=O;try{if(!N)throw new Error("No data provided for download");if(!I||typeof I!="string")throw new Error("Invalid file name");let M,L=I,G=A.toLowerCase();E==null||E(10);try{G==="excel"?await BA.ensureDependency("sheetjs"):G==="pdf"&&await Promise.all([BA.ensureDependency("jspdf"),BA.ensureDependency("jspdfAutotable")])}catch(W){if(B){if(console.warn(`Dependency missing for ${G}, falling back to print/csv...`),G==="excel")G="csv";else if(G==="pdf")return await s3(N,I,K)}else throw W}switch(E==null||E(30),G){case"csv":M=await Y3(N,R,{onProgress:E}),L.toLowerCase().endsWith(".csv")||(L+=".csv");break;case"json":M=await S3(N,{onProgress:E}),L.toLowerCase().endsWith(".json")||(L+=".json");break;case"txt":M=await t3(N,{onProgress:E}),L.toLowerCase().endsWith(".txt")||(L+=".txt");break;case"excel":M=await e3(N,{onProgress:E}),L.toLowerCase().endsWith(".xlsx")||(L+=".xlsx");break;case"pdf":M=await D3(N,K,{onProgress:E}),L.toLowerCase().endsWith(".pdf")||(L+=".pdf");break;default:throw new Error(`Unsupported file type: ${A}`)}if(E==null||E(80),M.size>U)throw new Error(`File size ${(M.size/1024/1024).toFixed(2)}MB exceeds limit.`);if(G==="pdf"){r3(M,L),E==null||E(100);return}let T=URL.createObjectURL(M);try{let W=document.createElement("a");W.href=T,W.download=L,W.style.display="none",document.body.appendChild(W),W.click(),document.body.removeChild(W)}finally{setTimeout(()=>URL.revokeObjectURL(T),1e3)}E==null||E(100)}catch(M){throw console.error("Download failed:",M),M}}var JA=class{constructor(A="export"){this.defaultFilename=A}async exportToExcel(A,I={}){let O=this.extractTableData(A,I),U=[...O.headers,...O.rows,...O.footers];await SA(U,"excel",I.filename||this.defaultFilename,I)}async exportToCSV(A,I={}){let O=this.extractTableData(A,I),U=this.generateCsvContent(O,I.delimiter||",",`
1074
+ `}static injectStyles(){if(document.querySelector("style[data-smart-input]"))return;let A=document.createElement("style");A.setAttribute("data-smart-input","");let I=document.head.firstChild;I?document.head.insertBefore(A,I):document.head.appendChild(A),A.textContent=N.defaultCSS}_createInputWrapper(A,I,O=[]){let U=document.createElement("div");U.className=["smart-input-wrapper",...O].join(" ");let E=document.createElement("label");return E.htmlFor=A,E.textContent=I,E.className="smart-input-label",U.appendChild(E),U}_mount(A,I){I.appendChild(A)}_makeHandle(A,I,O={}){return{element:A,getValue:O.getValue||(()=>A.value),setValue:O.setValue||(U=>{A.value=U}),clear:O.clear||(()=>{A.value=""}),destroy:O.destroy||(()=>{I.remove()})}}getInput(A){return this.inputs[A]||null}createNumberInput({id:A,labelText:I,container:O,placeholder:U="Enter numbers only",wrapperClasses:E=[],inputClasses:B=[]}){if(!O)return console.error("SmartInput: container element is required"),null;let R=this._createInputWrapper(A,I,E),K=document.createElement("input");K.type="text",K.id=A,K.className=["smart-input","smart-input-number",...B].join(" "),K.placeholder=U,K.addEventListener("input",L=>{let G="";for(let T of L.target.value)"0123456789".includes(T)&&(G+=T);L.target.value=G}),R.appendChild(K),this._mount(R,O);let M=this._makeHandle(K,R);return this.inputs[A]=M,M}createFormattedNumberInput({id:A,labelText:I,container:O,placeholder:U="Enter amount (e.g., 1,234.56)",wrapperClasses:E=[],inputClasses:B=[]}){if(!O)return console.error("SmartInput: container element is required"),null;let R=this._createInputWrapper(A,I,E),K=document.createElement("input");K.type="text",K.id=A,K.className=["smart-input","smart-input-formatted-number",...B].join(" "),K.placeholder=U;let M=G=>{let T="",W=!1;for(let r of G)"0123456789".includes(r)?T+=r:r==="."&&!W&&(T+=r,W=!0);let S=T.indexOf("."),Y=S>=0?T.substring(0,S):T,i=S>=0?T.substring(S):"",t="";if(Y.length>0){let r=Y.split("").reverse().join(""),P="";for(let H=0;H<r.length;H++)P+=r[H],(H+1)%3===0&&H+1!==r.length&&(P+=",");t=P.split("").reverse().join("")}return t+i};K.addEventListener("input",G=>{G.target.value=M(G.target.value)}),R.appendChild(K),this._mount(R,O);let L=this._makeHandle(K,R,{setValue:G=>{K.value=M(String(G))}});return this.inputs[A]=L,L}createSearchableInput({id:A,labelText:I,container:O,data:U=[],placeholder:E="Search...",wrapperClasses:B=[],inputClasses:R=[],dropdownClasses:K=[]}){if(!O)return console.error("SmartInput: container element is required"),null;let M=this._createInputWrapper(A,I,["smart-input-searchable-wrapper",...B]),L=document.createElement("input");L.type="text",L.id=A,L.className=["smart-input","smart-input-searchable",...R].join(" "),L.placeholder=E;let G=document.createElement("ul");G.className=["smart-input-dropdown",...K].join(" ");let T=null,W=U,S=()=>G.classList.add("smart-input-dropdown-visible"),Y=()=>{G.classList.remove("smart-input-dropdown-visible"),L.setAttribute("data-value",T!=null?T:"")},i=P=>{let H=document.createDocumentFragment(),EA=P.toLowerCase(),V=W.filter(Q=>Q.key.toLowerCase().includes(EA));if(V.length>0){for(let Q of V){let UA=document.createElement("li");UA.textContent=Q.key,UA.dataset.value=Q.value,UA.className="smart-input-dropdown-item",UA.addEventListener("mousedown",W2=>{W2.preventDefault(),L.value=Q.key,T=Q.value,Y(),L.focus()}),H.appendChild(UA)}G.replaceChildren(H),S()}else G.replaceChildren(),Y()};L.addEventListener("focus",()=>i(L.value)),L.addEventListener("input",()=>{T=null,i(L.value)}),L.addEventListener("blur",()=>{setTimeout(()=>{M.contains(document.activeElement)||Y()},150)});let t=new AbortController;document.addEventListener("click",P=>{M.contains(P.target)||Y()},{signal:t.signal}),M.appendChild(L),M.appendChild(G),this._mount(M,O);let r=this._makeHandle(L,M,{getValue:()=>T,setValue:({key:P,value:H})=>{L.value=P,T=H,L.setAttribute("data-value",H!=null?H:"")},clear:()=>{L.value="",T=null,L.removeAttribute("data-value"),Y()},destroy:()=>{t.abort(),M.remove()}});return r.setData=P=>{W=P,i(L.value)},this.inputs[A]=r,r}createLimitedTextInput({id:A,labelText:I,container:O,maxLength:U,allowedCharactersString:E="",placeholder:B="",wrapperClasses:R=[],inputClasses:K=[]}){if(!O)return console.error("SmartInput: container element is required"),null;if(!U)return console.error("SmartInput: maxLength is required for createLimitedTextInput"),null;let M=Math.max(1,Math.round(U*.1)),L=this._createInputWrapper(A,I,R),G=document.createElement("input");G.type="text",G.id=A,G.className=["smart-input","smart-input-limited",...K].join(" "),G.maxLength=U,G.placeholder=B||`Max ${U} characters`;let T=document.createElement("span");T.className="smart-input-char-count";let W=()=>{let Y=G.value.length,i=U-Y;T.textContent=`${Y} / ${U}`,T.classList.remove("smart-input-char-warn","smart-input-char-over"),i<0?T.classList.add("smart-input-char-over"):i<=M&&T.classList.add("smart-input-char-warn")};G.addEventListener("input",Y=>{if(E){let i="";for(let t of Y.target.value)E.includes(t)&&(i+=t);Y.target.value=i}W()}),W(),L.appendChild(G),L.appendChild(T),this._mount(L,O);let S=this._makeHandle(G,L,{setValue:Y=>{G.value=Y,W()},clear:()=>{G.value="",W()}});return this.inputs[A]=S,S}createAutoExpandingTextArea({id:A,labelText:I,container:O,placeholder:U="",minHeight:E=150,maxHeight:B=300,wrapperClasses:R=[],inputClasses:K=[]}){if(!O)return console.error("SmartInput: container element is required"),null;let M=this._createInputWrapper(A,I,R),L=document.createElement("textarea");L.id=A,L.className=["smart-input","smart-input-textarea",...K].join(" "),L.placeholder=U,L.style.resize="none",L.style.overflowY="hidden",L.style.minHeight=`${E}px`;let G=()=>{L.style.height="auto";let W=L.scrollHeight,S=Math.min(Math.max(W,E),B);L.style.height=`${S}px`,W>B?L.style.overflowY="auto":L.style.overflowY="hidden"};L.addEventListener("input",G),M.appendChild(L),this._mount(M,O);let T=this._makeHandle(L,M,{setValue:W=>{L.value=W,G()},clear:()=>{L.value="",G()}});return setTimeout(G,0),this.inputs[A]=T,T}createSelectInput({id:A,labelText:I,container:O,optionsData:U=[],wrapperClasses:E=[],inputClasses:B=[]}){if(!O)return console.error("SmartInput: container element is required"),null;let R=this._createInputWrapper(A,I,E),K=document.createElement("select");K.id=A,K.className=["smart-input","smart-input-select",...B].join(" ");for(let L of U){let G=document.createElement("option");G.value=L.value,G.textContent=L.key,K.appendChild(G)}R.appendChild(K),this._mount(R,O);let M=this._makeHandle(K,R,{getValue:()=>K.value,setValue:L=>{K.value=L},clear:()=>{K.selectedIndex=0}});return this.inputs[A]=M,M}};var d=(function(){let N={apiUrl:null,timeout:6e5,maxRetries:3,retryStrategy:"exponential",csrfToken:null,authToken:null,environment:"development",keys:{globalConfig:"APP_CONFIG",authToken:"auth_token",csrfToken:"csrf-token",csrfCookie:"XSRF-TOKEN"}};return{init(A={}){A.keys&&(N.keys={...N.keys,...A.keys}),window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1"?N.environment="development":N.environment="production";let I=N.keys.globalConfig;window[I]&&window[I].apiUrl&&(N.apiUrl=window[I].apiUrl,window[I].environment&&(N.environment=window[I].environment));let O=document.querySelector('meta[name="api-url"]');O&&(N.apiUrl=O.getAttribute("content")),Object.assign(N,A),this.validate()},validate(){!N.apiUrl&&N.environment==="production"&&console.warn("RequestHandler: API URL is missing in production environment.")},get:()=>N}})(),vA={getCsrfToken(){let N=d.get().keys;if(d.get().csrfToken)return d.get().csrfToken;let A=document.querySelector(`meta[name="${N.csrfToken}"]`);if(A)return A.getAttribute("content");let I=N.csrfCookie+"=",U=decodeURIComponent(document.cookie).split(";");for(let E=0;E<U.length;E++){let B=U[E].trim();if(B.indexOf(I)===0)return B.substring(I.length,B.length)}return null},getAuthToken(){let N=d.get().keys;return d.get().authToken?d.get().authToken:sessionStorage.getItem(N.authToken)||localStorage.getItem(N.authToken)},sanitizePayload(N){if(!N||typeof N!="object"||N instanceof FormData)return N;let A=JSON.parse(JSON.stringify(N)),I=O=>{for(let U in O)typeof O[U]=="string"?O[U]=O[U].replace(/<script\b[^>]*>([\s\S]*?)<\/script>/gim,"").replace(/javascript:/gim,""):typeof O[U]=="object"&&O[U]!==null&&I(O[U])};return I(A),A}},_={request:[],response:[],error:[],addRequest(N,A){let I=Date.now()+Math.random();return this.request.push({id:I,onFulfilled:N,onRejected:A}),I},addResponse(N,A){let I=Date.now()+Math.random();return this.response.push({id:I,onFulfilled:N,onRejected:A}),I},addError(N){this.error.push(N)},clear(){this.request=[],this.response=[],this.error=[]}},c1=(function(){let N=[],A=0,I=3,O=()=>{if(A>=I||N.length===0)return;N.sort((E,B)=>B.priority-E.priority);let U=N.shift();A++,U.execute().finally(()=>{A--,O()})};return{add(U,E=0){return new Promise((B,R)=>{N.push({priority:E,execute:()=>U().then(B).catch(R)}),O()})},getStatus:()=>({active:A,pending:N.length}),clear:()=>{N.length=0}}})(),hA=async function(N={}){let I={...{method:"POST",endpoint:"",payload:null,headers:{},timeout:d.get().timeout,maxRetries:d.get().maxRetries,retryStrategy:d.get().retryStrategy,useQueue:!1,priority:0,responseType:"json",showLoading:null,onSuccess:null,onError:null,onProgress:null,silent:!1},...N};for(let R of _.request)try{R.onFulfilled&&(I=await R.onFulfilled(I))}catch(K){if(R.onRejected)return R.onRejected(K);throw K}let O=(R,K)=>{let M=K>=200&&K<300;if(R&&typeof R=="object"&&"status"in R){let L=R.status===!0;return{status:L&&M,log:L&&M?"":R.log||"Error",data:R.data!==void 0?R.data:R,httpCode:K}}return{status:M,log:M?"":(R==null?void 0:R.message)||(R==null?void 0:R.error)||`Request failed with status ${K}`,data:M?R:null,httpCode:K}},U=async(R=0)=>{I.showLoading&&await I.showLoading(!0);try{let K=new XMLHttpRequest,M=I.endpoint.startsWith("http")?I.endpoint:`${d.get().apiUrl}/${I.endpoint.replace(/^\//,"")}`;return await new Promise(L=>{K.open(I.method,M,!0),K.timeout=I.timeout;let G=vA.getCsrfToken();G&&K.setRequestHeader("X-CSRF-Token",G);let T=vA.getAuthToken();T&&K.setRequestHeader("Authorization",`Bearer ${T}`),K.setRequestHeader("X-Requested-With","XMLHttpRequest");let W=I.headers||{};!Object.keys(W).some(t=>t.toLowerCase()==="content-type")&&!(I.payload instanceof FormData)&&K.setRequestHeader("Content-Type","application/json"),Object.keys(W).forEach(t=>{K.setRequestHeader(t,W[t])}),I.onProgress&&K.upload&&(K.upload.onprogress=t=>{if(t.lengthComputable){let r=Math.round(t.loaded/t.total*100);I.onProgress(r)}}),K.onload=async()=>{I.showLoading&&await I.showLoading(!1);let t;try{t=I.responseType==="json"?JSON.parse(K.responseText):K.response}catch{t=K.responseText}let r={},P=K.getAllResponseHeaders();P&&P.trim().split(/[\r\n]+/).forEach(EA=>{let V=EA.split(": "),Q=V.shift(),UA=V.join(": ");r[Q.toLowerCase()]=UA});let H=O(t,K.status);if(K.status>=200&&K.status<300){if(H.status===!1){I.onError&&await I.onError(H.log),I.silent||await o.error(H.log);for(let V of _.response)V.onFulfilled&&await V.onFulfilled({...H,url:M});L(H);return}let EA={data:t.data||t,status:K.status,url:M,headers:r};for(let V of _.response)V.onFulfilled&&(EA=await V.onFulfilled(EA));I.onSuccess&&await I.onSuccess(H.data),L(H)}else await E(K,R,U,r,t,L)},K.onerror=()=>E(K,R,U,{},null,L),K.ontimeout=()=>E({status:408},R,U,{},null,L);let Y=vA.sanitizePayload(I.payload),i=Y;!(Y instanceof FormData)&&typeof Y=="object"&&Y!==null&&(i=JSON.stringify(Y)),K.send(i)})}catch(K){I.showLoading&&await I.showLoading(!1);let M=K.message||"Critical Runtime Error";return I.onError&&await I.onError(M),I.silent||await o.error(M),{status:!1,log:M,data:null}}},E=async(R,K,M,L,G,T)=>{let W=I.endpoint.startsWith("http")?I.endpoint:`${d.get().apiUrl}/${I.endpoint.replace(/^\//,"")}`;if(K<I.maxRetries&&(R.status>=500||R.status===408||R.status===0)){let S=B(K,I.retryStrategy);setTimeout(()=>M(K+1).then(T),S)}else{I.showLoading&&await I.showLoading(!1);let S=O(G,R.status);I.onError&&await I.onError(S.log),I.silent||await o.error(S.log),_.error.forEach(Y=>Y(R));for(let Y of _.response)Y.onFulfilled&&await Y.onFulfilled({...S,url:W});T(S)}},B=(R,K)=>{switch(K){case"linear":return(R+1)*1e3;case"fibonacci":return([1,1,2,3,5,8][R]||13)*1e3;case"exponential":return Math.pow(2,R)*1e3;default:return 1e3}};return I.useQueue?c1.add(()=>U(),I.priority):U()},l1=N=>d.init(N),h1={request:(N,A)=>_.addRequest(N,A),response:(N,A)=>_.addResponse(N,A),error:N=>_.addError(N),clear:()=>_.clear()},J1=()=>c1.getStatus();document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>d.init()):d.init();function AA(N,A={}){let{showAlert:I=!1}=A;if(typeof N!="string")return I&&console.error("Invalid input: Date must be a string."),!1;let O=N.trim().split("-");if(O.length!==3||O[0].length!==4||O[1].length!==2||O[2].length!==2)return I&&o.error("Invalid date format. Use YYYY-MM-DD."),!1;if(O.some(K=>isNaN(K)))return I&&o.error("Date must contain only numbers."),!1;let[U,E,B]=O.map(Number);if(E<1||E>12||B<1||B>31)return I&&o.error("Invalid month or day range."),!1;let R=new Date(U,E-1,B);return R.getFullYear()!==U||R.getMonth()!==E-1||R.getDate()!==B?(I&&o.error("Invalid date. Please enter a real date."),!1):!0}function d1(N,A={}){let{format:I="weekday",locale:O="en-US",includeYear:U=!0}=A;if(!AA(N,{showAlert:!1}))throw new Error("Invalid date format. Use YYYY-MM-DD.");let E=N.split("-"),B=new Date(E[0],E[1]-1,E[2]),R={short:{year:"numeric",month:"numeric",day:"numeric"},medium:{year:"numeric",month:"short",day:"numeric"},long:{year:"numeric",month:"long",day:"numeric"},full:{weekday:"long",year:"numeric",month:"long",day:"numeric"},weekday:{weekday:"short",year:"numeric",month:"short",day:"numeric"}},K=R[I]||R.weekday;return U||(K={...K},delete K.year),B.toLocaleString(O,K)}function u1(N,A={}){let{locale:I="en-US"}=A;if(!AA(N,{showAlert:!1}))throw new Error("Invalid date format. Use YYYY-MM-DD.");let O=N.split("-"),B=new Date(O[0],O[1]-1,O[2])-new Date,R=Math.round(B/(1e3*60*60*24)),K=new Intl.RelativeTimeFormat(I,{numeric:"auto"});if(Math.abs(R)<1){let M=Math.round(B/36e5);return K.format(M,"hour")}else{if(Math.abs(R)<7)return K.format(R,"day");if(Math.abs(R)<30){let M=Math.round(R/7);return K.format(M,"week")}else if(Math.abs(R)<365){let M=Math.round(R/30);return K.format(M,"month")}else{let M=Math.round(R/365);return K.format(M,"year")}}}function Z1(){let N=new Date,A=N.getFullYear(),I=String(N.getMonth()+1).padStart(2,"0"),O=String(N.getDate()).padStart(2,"0");return`${A}-${I}-${O}`}function p1(){let N=new Date;N.setDate(N.getDate()-1);let A=N.getFullYear(),I=String(N.getMonth()+1).padStart(2,"0"),O=String(N.getDate()).padStart(2,"0");return`${A}-${I}-${O}`}function m1(N,A={}){let{showSeconds:I=!0}=A,O=new Date,U=new Date(N);if(isNaN(U.getTime()))return"Invalid timestamp";let E=O-U,B=Math.floor(E/1e3),R=Math.floor(B/60),K=Math.floor(R/60),M=Math.floor(K/24),L=Math.floor(M/7),G=Math.floor(M/30),T=Math.floor(M/365);return B<60?I?`${B} second${B!==1?"s":""} ago`:"now":R<60?`${R} minute${R!==1?"s":""} ago`:K<24?`${K} hour${K!==1?"s":""} ago`:M<7?`${M} day${M!==1?"s":""} ago`:L<4?`${L} week${L!==1?"s":""} ago`:G<12?`${G} month${G!==1?"s":""} ago`:`${T} year${T!==1?"s":""} ago`}function g1(N,A,I){if(!AA(N,{showAlert:!1}))throw new Error("Invalid date format. Use YYYY-MM-DD.");let O=new Date(N),E={days:()=>O.setDate(O.getDate()+A),weeks:()=>O.setDate(O.getDate()+A*7),months:()=>O.setMonth(O.getMonth()+A),years:()=>O.setFullYear(O.getFullYear()+A)}[I.toLowerCase()];if(!E)throw new Error(`Invalid unit: ${I}. Use: days, weeks, months, years`);return E(),O.toISOString().split("T")[0]}function f1(N){let A=new Date,I=K=>{let M=K.getFullYear(),L=String(K.getMonth()+1).padStart(2,"0"),G=String(K.getDate()).padStart(2,"0");return`${M}-${L}-${G}`},O=K=>{let M=K.getDay(),L=K.getDate()-M+(M===0?-6:1),G=new Date(K);return G.setDate(L),G},U=K=>new Date(K.getFullYear(),K.getMonth(),1),E=K=>new Date(K.getFullYear(),K.getMonth()+1,0),B,R;switch(N.toLowerCase()){case"today":{B=I(A),R=I(A);break}case"yesterday":{let K=new Date(A);K.setDate(A.getDate()-1),B=I(K),R=I(K);break}case"thisweek":{let K=O(A);B=I(K),R=I(A);break}case"lastweek":{let K=new Date(A);K.setDate(A.getDate()-7);let M=O(K),L=new Date(M);L.setDate(M.getDate()+6),B=I(M),R=I(L);break}case"thismonth":{let K=U(A);B=I(K),R=I(A);break}case"lastmonth":{let K=new Date(A.getFullYear(),A.getMonth()-1,1),M=U(K),L=E(K);B=I(M),R=I(L);break}default:throw new Error(`Unknown keyword: ${N}. Use: today, yesterday, thisWeek, lastWeek, thisMonth, lastMonth`)}return[B,R]}function w1(N,A){let I=new Date,U={days:()=>I.setDate(I.getDate()-N),weeks:()=>I.setDate(I.getDate()-N*7),months:()=>I.setMonth(I.getMonth()-N),years:()=>I.setFullYear(I.getFullYear()-N)}[A.toLowerCase()];if(!U)throw new Error(`Invalid unit: ${A}. Use: days, weeks, months, years`);U();let E=I.getFullYear(),B=String(I.getMonth()+1).padStart(2,"0"),R=String(I.getDate()).padStart(2,"0");return`${E}-${B}-${R}`}function v1(){let N=new Date;N.setDate(N.getDate()+1);let A=N.getFullYear(),I=String(N.getMonth()+1).padStart(2,"0"),O=String(N.getDate()).padStart(2,"0");return`${A}-${I}-${O}`}function V1(N){let A=new Date,I=M=>{let L=M.getFullYear(),G=String(M.getMonth()+1).padStart(2,"0"),T=String(M.getDate()).padStart(2,"0");return`${L}-${G}-${T}`},O=M=>{let L=M.getDay(),G=M.getDate()-L+(L===0?-6:1),T=new Date(M);return T.setDate(G),T},U=M=>{let L=O(M),G=new Date(L);return G.setDate(L.getDate()+6),G},E=M=>new Date(M.getFullYear(),M.getMonth(),1),B=M=>new Date(M.getFullYear(),M.getMonth()+1,0),R,K;switch(N.toLowerCase()){case"tomorrow":{let M=new Date(A);M.setDate(A.getDate()+1),R=I(M),K=I(M);break}case"nextweek":{let M=new Date(A);M.setDate(A.getDate()+7);let L=O(M),G=U(M);R=I(L),K=I(G);break}case"nextmonth":{let M=new Date(A.getFullYear(),A.getMonth()+1,1),L=E(M),G=B(M);R=I(L),K=I(G);break}case"nextyear":{let M=new Date(A.getFullYear()+1,0,1),L=new Date(A.getFullYear()+1,11,31);R=I(M),K=I(L);break}default:throw new Error(`Unknown keyword: ${N}. Use: tomorrow, nextWeek, nextMonth, nextYear`)}return[R,K]}function y1(N,A,I={}){let{inclusiveEndDate:O=!1}=I;if(!AA(N,{showAlert:!1})||!AA(A,{showAlert:!1}))throw new Error("Invalid date format. Use YYYY-MM-DD.");let U=new Date(N),E=new Date(A);if(U>E)throw new Error("Start date cannot be after end date.");let B=E-U,R=Math.floor(B/(1e3*60*60*24));return O&&(R+=1),R}function x1(N,A,I={}){let{startDate:O}=I,U;if(O){if(!AA(O,{showAlert:!1}))throw new Error("Invalid start date format. Use YYYY-MM-DD.");U=new Date(O)}else U=new Date;if(typeof N!="number"||N<0)throw new Error("Amount must be a positive number.");let B={days:()=>U.setDate(U.getDate()+N),weeks:()=>U.setDate(U.getDate()+N*7),months:()=>U.setMonth(U.getMonth()+N),years:()=>U.setFullYear(U.getFullYear()+N)}[A.toLowerCase()];if(!B)throw new Error(`Invalid unit: ${A}. Use: days, weeks, months, years`);B();let R=U.getFullYear(),K=String(U.getMonth()+1).padStart(2,"0"),M=String(U.getDate()).padStart(2,"0");return`${R}-${K}-${M}`}function F1(N){let A=new Date;return A.setHours(0,0,0,0),new Date(N)>A}function b1(N){let A=new Date;return A.setHours(0,0,0,0),new Date(N)<A}var VA=class{constructor(){this.dependencies={sheetjs:{name:"SheetJS",cdn:"https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js",check:()=>typeof XLSX<"u"&&!!XLSX.utils,timeout:45e3},jspdf:{name:"jsPDF",cdn:"https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js",fallbacks:["https://cdn.jsdelivr.net/npm/jspdf@2.5.1/dist/jspdf.umd.min.js","https://unpkg.com/jspdf@2.5.1/dist/jspdf.umd.min.js"],check:()=>typeof(window.jsPDF||window.jspdf&&window.jspdf.jsPDF)<"u",timeout:3e4},jspdfAutotable:{name:"jsPDF AutoTable",cdn:"https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.5.28/jspdf.plugin.autotable.min.js",fallbacks:["https://cdn.jsdelivr.net/npm/jspdf-autotable@3.5.28/dist/jspdf.plugin.autotable.min.js"],check:()=>{let A=window.jsPDF||window.jspdf&&window.jspdf.jsPDF;return typeof A<"u"&&(typeof A.autoTable<"u"||A.API&&typeof A.API.autoTable<"u")},requires:["jspdf"],timeout:2e4}},this.loadingPromises=new Map}register(A,I){this.dependencies[A]&&console.warn(`Dependency "${A}" is already registered. Overwriting.`),this.dependencies[A]=I}hasDependency(A){let I=this.dependencies[A];if(!I)return!1;if(I.requires){for(let O of I.requires)if(!this.hasDependency(O))return!1}return I.check()}async loadDependency(A,I=0){if(this.loadingPromises.has(A))return this.loadingPromises.get(A);let O=this.dependencies[A];if(!O)throw new Error(`Unknown dependency: ${A}`);if(this.hasDependency(A))return!0;if(O.requires)for(let R of O.requires)await this.loadDependency(R);let U=O.maxRetries||2,E=[O.cdn,...O.fallbacks||[]],B=(async()=>{let R;for(let K of E)try{return await this._injectScript(O,K),this.loadingPromises.delete(A),!0}catch(M){R=M,console.warn(`Failed to load ${O.name} from ${K}:`,M.message)}if(I<U)return this.loadingPromises.delete(A),this.loadDependency(A,I+1);throw this.loadingPromises.delete(A),R||new Error(`Failed to load ${O.name} after all attempts.`)})();return this.loadingPromises.set(A,B),B}_injectScript(A,I){return new Promise((O,U)=>{let E=document.createElement("script");E.src=I,E.async=!0,A.integrity&&(E.integrity=A.integrity,E.crossOrigin=A.crossorigin||"anonymous"),E.onload=()=>{let R=0,K=setInterval(()=>{A.check()?(clearInterval(K),O(!0)):R>20&&(clearInterval(K),U(new Error(`Library ${A.name} loaded but failed verification.`))),R++},50)},E.onerror=()=>U(new Error("Network error or CSP violation")),document.head.appendChild(E);let B=(A.timeout||3e4)/1e3;setTimeout(()=>{E.parentNode&&(E.remove(),U(new Error(`Timeout (${B}s) reached for ${I}`)))},A.timeout||3e4)})}async ensureDependency(A,I=null){try{return this.hasDependency(A)||await this.loadDependency(A),!0}catch(O){if(console.error(`Dependency Manager error [${A}]:`,O.message),I)return I();throw O}}},BA=new VA;async function SA(N,A,I="download",O={}){let{maxSize:U=50*1024*1024,onProgress:E=null,fallbackFormats:B=!0,csvDelimiter:R=",",pdfOptions:K={}}=O;try{if(!N)throw new Error("No data provided for download");if(!I||typeof I!="string")throw new Error("Invalid file name");let M,L=I,G=A.toLowerCase();E==null||E(10);try{G==="excel"?await BA.ensureDependency("sheetjs"):G==="pdf"&&await Promise.all([BA.ensureDependency("jspdf"),BA.ensureDependency("jspdfAutotable")])}catch(W){if(B){if(console.warn(`Dependency missing for ${G}, falling back to print/csv...`),G==="excel")G="csv";else if(G==="pdf")return await s3(N,I,K)}else throw W}switch(E==null||E(30),G){case"csv":M=await Y3(N,R,{onProgress:E}),L.toLowerCase().endsWith(".csv")||(L+=".csv");break;case"json":M=await S3(N,{onProgress:E}),L.toLowerCase().endsWith(".json")||(L+=".json");break;case"txt":M=await t3(N,{onProgress:E}),L.toLowerCase().endsWith(".txt")||(L+=".txt");break;case"excel":M=await e3(N,{onProgress:E}),L.toLowerCase().endsWith(".xlsx")||(L+=".xlsx");break;case"pdf":M=await D3(N,K,{onProgress:E}),L.toLowerCase().endsWith(".pdf")||(L+=".pdf");break;default:throw new Error(`Unsupported file type: ${A}`)}if(E==null||E(80),M.size>U)throw new Error(`File size ${(M.size/1024/1024).toFixed(2)}MB exceeds limit.`);if(G==="pdf"){r3(M,L),E==null||E(100);return}let T=URL.createObjectURL(M);try{let W=document.createElement("a");W.href=T,W.download=L,W.style.display="none",document.body.appendChild(W),W.click(),document.body.removeChild(W)}finally{setTimeout(()=>URL.revokeObjectURL(T),1e3)}E==null||E(100)}catch(M){throw console.error("Download failed:",M),M}}var JA=class{constructor(A="export"){this.defaultFilename=A}async exportToExcel(A,I={}){let O=this.extractTableData(A,I),U=[...O.headers,...O.rows,...O.footers];await SA(U,"excel",I.filename||this.defaultFilename,I)}async exportToCSV(A,I={}){let O=this.extractTableData(A,I),U=this.generateCsvContent(O,I.delimiter||",",`
1075
1075
  `,!0);await SA(U,"csv",I.filename||this.defaultFilename,I)}async exportToPDF(A,I={}){let O=this.extractTableData(A,I);await SA(O,"pdf",I.filename||this.defaultFilename,I)}extractTableData(A,I={}){let{rowClass:O,cellClass:U,headerRowClass:E,footerRowClass:B,includeFooter:R=!0}=I,K={headers:[],rows:[],footers:[]},M=L=>Array.from(A.querySelectorAll(L)).map(T=>Array.from(T.querySelectorAll(U||"th, td")).map(W=>(W.textContent||"").trim().replace(/\s+/g," ")));if(E?K.headers=M(`.${E}`):(K.headers=M("thead tr"),K.headers.length===0&&(K.headers=M("tr:has(th)"))),O)K.rows=M(`.${O}`);else{let L=M("tbody tr");L.length>0?K.rows=L:K.rows=M("tr:not(thead tr):not(tfoot tr)")}return R&&(B?K.footers=M(`.${B}`):K.footers=M("tfoot tr")),K}generateCsvContent(A,I,O,U){let B=[...A.headers,...A.rows,...A.footers].map(R=>R.map(K=>this.escapeCsvValue(K,I)).join(I)).join(O);return U?"\uFEFF"+B:B}escapeCsvValue(A,I){let O=String(A||"");return O.includes('"')||O.includes(I)||O.includes(`
1076
1076
  `)?`"${O.replace(/"/g,'""')}"`:O}};async function Y3(N,A){let I;return Array.isArray(N)?I=N.map(O=>Array.isArray(O)?O.map(U=>String(U)).join(A):JSON.stringify(O)).join(`
1077
1077
  `):I=String(N),new Blob(["\uFEFF"+I],{type:"text/csv;charset=utf-8"})}async function S3(N){return new Blob([JSON.stringify(N,null,2)],{type:"application/json"})}async function t3(N){return new Blob([String(N)],{type:"text/plain"})}async function e3(N){if(typeof XLSX>"u")throw new Error("SheetJS not loaded");let A=XLSX.utils.book_new(),I=XLSX.utils.aoa_to_sheet(N);XLSX.utils.book_append_sheet(A,I,"Sheet1");let O=XLSX.write(A,{bookType:"xlsx",type:"array"});return new Blob([O],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"})}async function D3(N,A){let I=window.jspdf?window.jspdf.jsPDF:window.jsPDF;if(!I)throw new Error("jsPDF library not found");let O=new I({orientation:A.orientation||"portrait",unit:"mm",format:A.format||"a4"}),U=A.title||"";if(U&&(O.setFontSize(16),O.text(U,14,15)),typeof N=="string"||Array.isArray(N)&&typeof N[0]=="string"&&!Array.isArray(N[0])){O.setFontSize(11);let B=Array.isArray(N)?N.join(`