UNPKG

@doyosi/laravel

Version:

Complete JavaScript plugins collection for Laravel applications - AJAX, forms, UI components, and more

9 lines (8 loc) • 40 kB
/*! * @doyosi/laravel-js v1.0.5 * JavaScript plugins for Laravel applications * (c) 2025 Karyazilim * Released under MIT License */ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).DoyosiJS={})}(this,function(t){"use strict";class e{constructor({url:t,container:e,templateId:s="box-template",metaKey:i="meta",dataKey:n="data",fetcher:o=(window.axios?"axios":"fetch"),onBox:r=null,pagination:a=null,filterSelector:l=null,loadingIndicator:c=".loading-list",nothingFoundBlock:d=".nothing-found-list",errorBlock:h=".list-render-error",additionalParams:u=null}){this.url=t,this.config={templateId:s,metaKey:i,dataKey:n,fetcher:o,onBox:r,additionalParams:u},this.filters={},this._handlers={},this.debounceTimer=null;const m=t=>t instanceof HTMLElement?t:"string"==typeof t?document.querySelector(t):null;if(this.elements={container:m(e),pagination:m(a),filters:m(l),loader:m(c),nothingFound:m(d),error:m(h)},!this.elements.container)throw new Error("AjaxDivBox: The main container element is required and was not found.");this._bindFilterEvents(),!1!==this.config.autoInit&&this.init()}on(t,e){return this._handlers[t]||(this._handlers[t]=[]),this._handlers[t].push(e),this}_emit(t,e){(this._handlers[t]||[]).forEach(t=>t(e))}init(){return this.elements.filters&&this._updateFilters(),this.fetchData(1)}refresh(){const t=this.lastMeta?.current_page||1;return this.fetchData(t)}_bindFilterEvents(){this.elements.filters&&this.elements.filters.addEventListener("input",t=>{t.target.matches("input, select")&&(clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout(()=>{this._updateFilters(),this.fetchData(1)},300))})}_updateFilters(){if(this.filters={},!this.elements.filters)return;const t=new FormData("FORM"===this.elements.filters.tagName?this.elements.filters:void 0);"FORM"!==this.elements.filters.tagName&&this.elements.filters.querySelectorAll("input, select").forEach(e=>{e.name&&t.append(e.name,e.value)});for(const[e,s]of t.entries())s&&(this.filters[e]=s)}_buildQueryString(t=1){let e={...this.filters,page:t};return"function"==typeof this.config.additionalParams&&(e={...e,...this.config.additionalParams()}),new URLSearchParams(Object.entries(e).filter(([,t])=>""!==t&&null!=t)).toString()}_setState(t,e="An error occurred."){const{container:s,loader:i,nothingFound:n,error:o}=this.elements;if([s,i,n,o].forEach(t=>t?.classList.add("hidden")),"loading"===t&&i)i.classList.remove("hidden");else if("content"===t&&s)s.classList.remove("hidden");else if("empty"===t&&n)n.classList.remove("hidden");else if("error"===t&&o){o.classList.remove("hidden");(o.querySelector(".list-render-error-text")||o).textContent=e}}async fetchData(t=1){this._setState("loading"),this._emit("start",{page:t});const e=`${this.url.split("?")[0]}?${this._buildQueryString(t)}`;try{const s="axios"===this.config.fetcher?(await window.axios.get(e)).data:await(await fetch(e,{headers:{Accept:"application/json"}})).json();if(!1===s.ok)throw s;const i=s[this.config.metaKey]||{};if(this.lastMeta=i,void 0!==s.html&&null!==s.html){this.elements.container.innerHTML=s.html,this._renderPagination(i);const e=s.html.trim().length>0;this._setState(e?"content":"empty"),this._emit("rendered",{html:s.html,meta:i,page:t})}else{const e=s[this.config.dataKey]||[];this._renderBoxes(e),this._renderPagination(i),this._setState(e.length>0?"content":"empty"),this._emit("rendered",{data:e,meta:i,page:t})}}catch(t){console.error("AjaxDivBox fetch error:",t);const e=t?.message||"Failed to load data.";this._setState("error",e),this._emit("error",{error:t,message:e})}}_renderBoxes(t){if(!this.elements.container)return;this.elements.container.innerHTML="";const e=document.createDocumentFragment();t.forEach(t=>{const s=this._renderTemplate(t),i=document.createElement("div");for(i.innerHTML=s;i.firstChild;)e.appendChild(i.firstChild)}),this.elements.container.appendChild(e)}_renderTemplate(t){if(void 0!==t.html&&null!==t.html)return t.html;if("function"==typeof this.config.onBox)return this.config.onBox(t);const e=document.getElementById(this.config.templateId);if(!e)return console.error(`Template with id "${this.config.templateId}" not found.`),"";let s=e.innerHTML;return s=s.replace(/data\.([a-zA-Z0-9_]+\.[a-zA-Z0-9_]+)/g,(e,s)=>{const i=s.split(".");let n=t;for(const t of i)if(n=n?.[t],void 0===n)break;return n??""}),s=s.replace(/data\.([a-zA-Z0-9_]+)/g,(e,s)=>t[s]??""),s}_renderPagination(t){const e=this.elements.pagination;if(!e)return;if(e.innerHTML="",!t?.links||t.last_page<=1)return void e.classList.add("hidden");e.classList.remove("hidden");const s=document.createDocumentFragment();t.links.forEach(t=>{const e=new URL(t.url||"",window.location.origin).searchParams.get("page");if(t.label.includes("...")){const t=document.createElement("span");return t.className="btn btn-disabled join-item",t.textContent="...",void s.appendChild(t)}const i=document.createElement("button");i.className="join-item btn "+(t.active?"btn-active":""),i.disabled=!t.url||t.active,i.innerHTML=t.label.replace(/&laquo;|&raquo;/g,""),t.url&&(i.onclick=s=>{s.preventDefault(),this._emit("pageChange",{page:parseInt(e),label:t.label}),this.fetchData(e)}),s.appendChild(i)});const i=document.createElement("div");i.className="join",i.appendChild(s),e.appendChild(i)}}class s{constructor({url:t,container:e,templateId:s="row-template",metaKey:i="meta",dataKey:n="data",fetcher:o=(window.axios?"axios":"fetch"),onRow:r=null,pagination:a=null,filterSelector:l=null,loadingIndicator:c=".loading-table",nothingFoundBlock:d=".nothing-found-table",errorBlock:h=".table-render-error",additionalParams:u=null,autoInit:m=!0,debounceTime:p=300}){this.url=t,this.config={templateId:s,metaKey:i,dataKey:n,fetcher:o,onRow:r,additionalParams:u,debounceTime:p},this.filters={},this._handlers={},this.debounceTimer=null;const f=t=>"string"==typeof t?document.querySelector(t):t;if(this.elements={container:f(e),table:f(e)?.querySelector("table"),tbody:f(e)?.querySelector("tbody"),pagination:f(a),filters:f(l),loader:f(c),nothingFound:f(d),error:f(h)},!this.elements.table||!this.elements.tbody)throw new Error("AjaxTable: Table or tbody element not found.");this._bindFilterEvents(),m&&this.init()}on(t,e){return this._handlers[t]||(this._handlers[t]=[]),this._handlers[t].push(e),this}_emit(t,e){(this._handlers[t]||[]).forEach(t=>t(e))}init(){return this.elements.filters&&this._updateFilters(),this.fetchData(1)}refresh(){const t=this.lastMeta?.current_page||1;return this.fetchData(t)}_bindFilterEvents(){if(!this.elements.filters)return;const t=()=>{clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout(()=>{this._updateFilters(),this.fetchData(1)},this.config.debounceTime)};this.elements.filters.querySelectorAll("input, select").forEach(e=>{"input"===e.tagName.toLowerCase()?e.addEventListener("input",t):e.addEventListener("change",t)})}_updateFilters(){this.filters={};const t=new FormData("FORM"===this.elements.filters.tagName?this.elements.filters:void 0);"FORM"!==this.elements.filters.tagName&&this.elements.filters.querySelectorAll("input, select").forEach(e=>{e.name&&t.append(e.name,e.value)});for(const[e,s]of t.entries())s&&(this.filters[e]=s)}_buildQueryString(t=1){let e={...this.filters,page:t};return"function"==typeof this.config.additionalParams&&(e={...e,...this.config.additionalParams()}),new URLSearchParams(Object.entries(e).filter(([,t])=>null!=t&&""!==t)).toString()}_setState(t,e="An error occurred."){const{container:s,loader:i,nothingFound:n,error:o}=this.elements;if([s,i,n,o].forEach(t=>t?.classList.add("hidden")),"loading"===t&&i)i.classList.remove("hidden");else if("content"===t&&s)s.classList.remove("hidden");else if("empty"===t&&n)n.classList.remove("hidden");else if("error"===t&&o){o.classList.remove("hidden");(o.querySelector(".table-render-error-text")||o).textContent=e}}async fetchData(t=1){this._setState("loading"),this._emit("start",{page:t});const e=this.elements.pagination;e&&(e.innerHTML="",e.classList.add("hidden"));const s=`${this.url.split("?")[0]}?${this._buildQueryString(t)}`;try{const e="axios"===this.config.fetcher?(await window.axios.get(s)).data:await(await fetch(s)).json(),i=e[this.config.metaKey]||{};this.lastMeta=i;const n=e[this.config.dataKey]||[];this._renderRows(n),this._renderPagination(i),this._setState(n.length>0?"content":"empty"),this._emit("rendered",{data:n,meta:i,page:t})}catch(t){console.error("AjaxTable fetch error:",t);const e=t?.message||"Failed to load data.";this._setState("error",e),this._emit("error",{error:t,message:e})}}_renderRows(t){if(!this.elements.tbody)return;this.elements.tbody.innerHTML="";const e=document.createDocumentFragment();t.forEach(t=>{const s=document.createElement("tr");s.innerHTML=this._renderTemplate(t),e.appendChild(1===s.children.length&&"TR"===s.children[0].tagName?s.children[0]:s)}),this.elements.tbody.appendChild(e)}_renderTemplate(t){if("function"==typeof this.config.onRow)return this.config.onRow(t);if(t.html)return t.html;const e=document.getElementById(this.config.templateId);if(!e)return"";let s=e.innerHTML;return s=s.replace(/data\.([a-zA-Z0-9_]+\.[a-zA-Z0-9_]+)/g,(e,s)=>{const i=s.split(".");let n=t;for(const t of i)if(n=n?.[t],void 0===n)break;return n??""}),s=s.replace(/data\.([a-zA-Z0-9_]+)/g,(e,s)=>t[s]??""),s}_renderPagination(t){const e=this.elements.pagination;if(!e||!t?.links||t.last_page<=1)return void e?.classList.add("hidden");e.classList.remove("hidden"),e.innerHTML="";const s=document.createDocumentFragment();t.links.forEach(t=>{const e=new URL(t.url||"",window.location.origin).searchParams.get("page"),i=document.createElement("button");i.className="join-item btn "+(t.active?"btn-active":""),i.disabled=!t.url||t.active,i.innerHTML=t.label.replace(/&laquo;|&raquo;/g,""),t.url&&(i.onclick=s=>{s.preventDefault(),this._emit("pageChange",{page:parseInt(e),label:t.label}),this.fetchData(e)}),s.appendChild(t.label.includes("...")?Object.assign(document.createElement("span"),{className:"btn btn-disabled join-item",textContent:"..."}):i)});const i=document.createElement("div");i.className="join",i.appendChild(s),e.appendChild(i)}}class i{constructor(t,e){this.inputs=Array.from(document.querySelectorAll(`${t}[data-id="${e}"]`)),this.hidden=document.querySelector(`input[type=hidden][name="${e}"]`),this._bindEvents(),this._updateHidden()}_bindEvents(){this.inputs.forEach((t,e)=>{t.setAttribute("maxlength",1),t.addEventListener("input",t=>this._onInput(t,e)),t.addEventListener("keydown",t=>this._onKeyDown(t,e)),t.addEventListener("paste",t=>this._onPaste(t,e))})}_onInput(t,e){const s=t.target.value.replace(/[^0-9]/g,"").charAt(0);t.target.value=s,this._updateHidden(),s&&this.inputs[e+1]&&this.inputs[e+1].focus()}_onKeyDown(t,e){"Backspace"===t.key&&!t.target.value&&this.inputs[e-1]&&this.inputs[e-1].focus()}_onPaste(t,e){t.preventDefault();const s=t.clipboardData.getData("text").trim().replace(/\s+/g,"").split("").slice(0,this.inputs.length-e);s.forEach((t,s)=>{this.inputs[e+s].value=t}),this.inputs[Math.min(this.inputs.length-1,e+s.length-1)].focus(),this._updateHidden()}_updateHidden(){const t=this.inputs.map(t=>t.value||"").join("");this.hidden&&(this.hidden.value=t)}}class n{constructor(t,e={}){this.options=Object.assign({confirmText:"Are you sure?",message:"This action cannot be undone!",successText:"Deleted!",successMessage:"Your item has been successfully deleted.",errorText:"Error!",errorMessage:"Delete failed.",successTimeout:null,errorTimeout:null},e),this.buttons="string"==typeof t?document.querySelectorAll(t):t,this._initModals(),this._bindEvents()}_initModals(){document.getElementById("delete_modal")||document.body.insertAdjacentHTML("beforeend",`\n <dialog id="delete_modal" class="modal">\n <div class="modal-box bg-red-800/90 text-white">\n <h3 class="font-bold text-lg text-white flex items-center gap-2 justify-center">\n <svg class="size-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>\n <span id="delete_modal_title">${this.options.confirmText}</span>\n </h3>\n <p class="py-1 text-sm text-center" id="delete_modal_message">${this.options.message}</p>\n <div class="modal-action flex gap-2 justify-center">\n <button class="btn btn-sm shadow-none" type="button" id="cancelDeleteBtn">Cancel</button>\n <button class="btn btn-sm btn-error shadow-none" type="button" id="confirmDeleteBtn">Delete</button>\n </div>\n </div>\n </dialog>`),document.getElementById("success_modal")||document.body.insertAdjacentHTML("beforeend",`\n <dialog id="success_modal" class="modal">\n <div class="modal-box bg-green-800/90 text-white">\n <div class="flex items-center justify-between gap-1 border-b border-gray-200 py-2">\n <h3 class="text-lg font-bold">\n <span id="success_modal_title">${this.options.successText}</span>\n </h3>\n <form method="dialog">\n <button class="btn btn-xs btn-ghost rounded-full btn-circle" type="submit"> <svg class="size-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg></button>\n </form>\n </div>\n <p class="py-4" id="success_modal_message">${this.options.successMessage}</p>\n </div>\n </dialog>`),document.getElementById("error_modal")||document.body.insertAdjacentHTML("beforeend",`\n <dialog id="error_modal" class="modal">\n <div class="modal-box bg-red-800/90 text-white">\n <div class="flex items-center justify-between gap-1 border-b border-gray-200 py-2">\n <h3 class="text-lg font-bold">\n <span id="error_modal_title">${this.options.errorText}</span>\n </h3>\n <form method="dialog">\n <button class="btn btn-xs btn-ghost rounded-full btn-circle" type="submit"> <svg class="size-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg></button>\n </form>\n </div>\n <p class="py-4" id="error_modal_message">${this.options.errorMessage}</p>\n </div>\n </dialog>`),this.deleteModal=document.getElementById("delete_modal"),this.successModal=document.getElementById("success_modal"),this.errorModal=document.getElementById("error_modal"),this.confirmBtn=document.getElementById("confirmDeleteBtn"),this.cancelBtn=document.getElementById("cancelDeleteBtn")}_bindEvents(){this.currentBtn=null,this.buttons.forEach(t=>{t.addEventListener("click",e=>{e.preventDefault(),this.currentBtn=t,document.getElementById("delete_modal_title").textContent=this.options.confirmText,document.getElementById("delete_modal_message").textContent=this.options.message,this.confirmBtn.disabled=!1,this.cancelBtn.disabled=!1,this.deleteModal.showModal()})}),this.cancelBtn.addEventListener("click",()=>{this.deleteModal.close(),this.currentBtn=null}),this.confirmBtn.addEventListener("click",async()=>{if(!this.currentBtn)return;const t=this.currentBtn.dataset.href;this.confirmBtn.disabled=!0,this.cancelBtn.disabled=!0;try{let e;if(window.axios){if(e=await axios.delete(t,{headers:{"X-Requested-With":"XMLHttpRequest",Accept:"application/json"}}),200!==e.status&&204!==e.status)throw e;this._showSuccess(),this._afterDelete(!0,e.data)}else{const e=await fetch(t,{method:"DELETE",headers:{"X-Requested-With":"XMLHttpRequest",Accept:"application/json"}});if(!e.ok)throw e;{this._showSuccess();let t=await e.json().catch(()=>({}));this._afterDelete(!0,t)}}}catch(t){this._showError(t),this._afterDelete(!1,t)}finally{this.deleteModal.close(),this.currentBtn=null,setTimeout(()=>{this.confirmBtn.disabled=!1,this.cancelBtn.disabled=!1},300)}})}_showSuccess(){document.getElementById("success_modal_title").textContent=this.options.successText,document.getElementById("success_modal_message").textContent=this.options.successMessage,this.successModal.showModal(),this.options.successTimeout&&this.options.successTimeout>0&&setTimeout(()=>{this.successModal.close()},this.options.successTimeout)}_showError(t){document.getElementById("error_modal_title").textContent=this.options.errorText;let e=this.options.errorMessage;t&&t.response&&t.response.data&&t.response.data.message&&(e=t.response.data.message),document.getElementById("error_modal_message").textContent=e,this.errorModal.showModal(),this.options.errorTimeout&&this.options.errorTimeout>0&&setTimeout(()=>{this.errorModal.close()},this.options.errorTimeout)}_afterDelete(t,e){"function"==typeof this.options.onDelete&&this.options.onDelete(t,e,this.currentBtn)}}class o{constructor(t={}){this.form="string"==typeof t.form?document.querySelector(t.form):t.form,this.editButtonSelector=t.editButtonSelector,this.cancelButton=document.querySelector(t.cancelButtonSelector),this.submitButton=t.submitButtonSelector?document.querySelector(t.submitButtonSelector):this.form.querySelector('[type="submit"]'),this.buttonText=this.submitButton?.querySelector(".button-text")||this.submitButton,this.header=this.form.closest(".pcard")?.querySelector(".pcard-title"),this.addTitle=t.addTitle||this.header?.dataset.addTitle||this.header?.textContent||"Add",this.editTitle=t.editTitle||this.header?.dataset.editTitle||"Edit",this.addButtonText=t.addButtonText||this.buttonText?.dataset.addTitle||this.buttonText?.textContent||"Save",this.editButtonText=t.editButtonText||this.buttonText?.dataset.editTitle||"Edit",this.onEditStart=t.onEditStart,this.onEditEnd=t.onEditEnd,this.editMode=!1,this._bindEditButtons(),this._bindCancelButton()}_bindEditButtons(){document.body.addEventListener("click",async t=>{const e=t.target.closest(this.editButtonSelector);if(!e)return;t.preventDefault();const s=e.dataset.href;if(s)try{let t,e;window.axios?(t=await axios.get(s,{headers:{Accept:"application/json"}}),e=t.data.data||t.data):(t=await fetch(s,{headers:{Accept:"application/json"}}),e=(await t.json()).data||{}),this._fillForm(e,{action:s,method:"POST",title:this.editTitle,buttonText:this.editButtonText}),this.cancelButton&&this.cancelButton.classList.remove("hidden"),this.editMode=!0,"function"==typeof this.onEditStart&&this.onEditStart(e)}catch(t){console.error(t),window.Toast?new Toast({message:"Cannot fetch item.",type:"error"}):alert("Fetch error")}})}_bindCancelButton(){this.cancelButton&&this.cancelButton.addEventListener("click",()=>this.resetToAddMode())}_fillForm(t={},e={}){["input","textarea","select"].forEach(e=>{this.form.querySelectorAll(e).forEach(e=>{if(!e.name)return;if("file"===e.type)return;let s=e.name.match(/^(\w+)\[(\w+)\]$/);if(s){let[i,n,o]=s,r=n+"s";t[r]&&void 0!==t[r][o]?e.value=t[r][o]:t[n]&&"object"==typeof t[n]&&void 0!==t[n][o]&&(e.value=t[n][o])}else void 0!==t[e.name]&&(console.log(e.name,t[e.name]),e.value=t[e.name])})}),e.action&&(this.form.action=e.action),e.method&&this.form.setAttribute("data-method",e.method),this.header&&e.title&&(this.header.textContent=e.title),this.buttonText&&e.buttonText&&(this.buttonText.textContent=e.buttonText),this.form.setAttribute("data-edit-mode",this.editMode?"true":"false")}resetToAddMode(t={}){this.form.reset(),this._fillForm(t,{action:this.form.dataset.action,method:"POST",title:this.addTitle,buttonText:this.addButtonText}),this.cancelButton&&this.cancelButton.classList.add("hidden"),this.editMode=!1,"function"==typeof this.onEditEnd&&this.onEditEnd()}}class r{constructor(t={}){if(this.config=Object.assign({method:"axios",httpMethod:"POST",formSelector:null,submitButtonSelector:null,action:null,successMessage:"Operation completed successfully!",errorMessage:"An error occurred.",useToast:"undefined"!=typeof Toast,disableOnSuccess:!1,redirectUrl:null,beforeSubmit:null,afterSubmit:null,getUrl:null,buttonOnly:!1},t),this.handlers={success:[],error:[],beforeSubmit:[],afterSubmit:[]},this.form=this._getFormElement(this.config.formSelector),this.submitButton=this._getSubmitButton(),this.isButtonOnly=!this.form||this.config.buttonOnly,!this.isButtonOnly&&!this.form)throw new Error("Form element not found.");if(!this.submitButton)throw new Error("Submit button not found.");this.originalButtonText=this.submitButton.querySelector(".button-text")?.textContent||this.submitButton.textContent,this._setupEventListeners()}on(t,e){return this.handlers[t]&&this.handlers[t].push(e),this}_emit(t,e){(this.handlers[t]||[]).forEach(t=>t(e))}_getFormElement(t){return t?"string"==typeof t?document.querySelector(t):t instanceof HTMLFormElement?t:null:null}_getSubmitButton(){const t=this.config.submitButtonSelector;return!t&&this.form?this.form.querySelector('[type="submit"]'):t instanceof HTMLElement?t:"string"==typeof t?document.querySelector(t):null}_setupEventListeners(){this.submitButton.addEventListener("click",t=>{t.preventDefault(),this._clearErrors(),this.isButtonOnly?this._handleSubmit():this.form.dispatchEvent(new Event("submit",{cancelable:!0}))}),this.form&&!this.isButtonOnly&&this.form.addEventListener("submit",t=>{t.preventDefault(),this._handleSubmit()})}async _handleSubmit(){let t=new FormData(this.isButtonOnly?void 0:this.form);if(this.isButtonOnly&&this.submitButton.dataset.data)try{const e=JSON.parse(this.submitButton.dataset.data);Object.entries(e).forEach(([e,s])=>t.append(e,s))}catch(t){console.warn("Invalid JSON in button data attribute:",t)}const e=this.config.httpMethod.toUpperCase();"POST"===e||t.has("_method")||t.append("_method",e);const s="function"==typeof this.config.getUrl?this.config.getUrl(this.submitButton):this.config.action||this.form?.action||window.location.href;try{if("function"==typeof this.config.beforeSubmit){const e=await this.config.beforeSubmit(t,this.form,this.submitButton);if(e instanceof FormData)t=e;else if(!1===e)return}this._emit("beforeSubmit",{formData:t,form:this.form,button:this.submitButton})}catch(t){return void console.error("Error in beforeSubmit hook:",t)}this._setLoading(!0);let i,n=!1;try{if("axios"===this.config.method&&window.axios){const n=await axios({url:s,method:e.toLowerCase(),data:t});i=n.data??n}else i="xhr"===this.config.method?await this._sendWithXHR(s,t,e):await this._sendWithFetch(s,t,e);n=!0,await this._handleSuccess(i),this.config.disableOnSuccess||this._setLoading(!1)}catch(t){i=t,await this._handleError(t),this._setLoading(!1)}try{"function"==typeof this.config.afterSubmit&&await this.config.afterSubmit(i,n,this.form,this.submitButton),this._emit("afterSubmit",{response:i,success:n,form:this.form,button:this.submitButton})}catch(t){console.error("Error in afterSubmit hook:",t)}}async _sendWithFetch(t,e,s){const i=await fetch(t,{method:s,body:e,headers:{Accept:"application/json"}}),n=await i.json().catch(()=>({}));if(!i.ok)throw{response:{data:n,status:i.status}};return n}_sendWithXHR(t,e,s){return new Promise((i,n)=>{const o=new XMLHttpRequest;o.open(s,t),o.setRequestHeader("Accept","application/json"),o.onload=()=>{try{const t=JSON.parse(o.responseText);o.status>=200&&o.status<300?i(t):n({response:{data:t,status:o.status}})}catch(t){n({message:"Invalid JSON",error:t})}},o.onerror=()=>n(new Error("Network error")),o.send(e)})}_setLoading(t){if(!this.submitButton)return;const e=this.submitButton.querySelector(".button-text");this.submitButton.disabled=t;const s=this.submitButton.dataset.loadingText||"Loading…";if(t)e?e.textContent=s:this.submitButton.textContent=s;else{const t=e?.dataset.default||this.originalButtonText;e?e.textContent=t:this.submitButton.textContent=this.originalButtonText}}async _handleSuccess(t){const e=t?.message||t?.data?.message||this.config.successMessage,s=t?.redirect||t?.data?.redirect||this.config.redirectUrl;this._showMessage(e,"success"),this._emit("success",t),s&&setTimeout(()=>window.location.href=s,1e3)}async _handleError(t){console.error(t);const e=t.response?.data||t,s=e?.message||this.config.errorMessage;e?.errors&&this.form&&Object.entries(e.errors).forEach(([t,e])=>{const s=t.includes(".")?t.replace(".","[")+"]":t,i=this.form.querySelector(`.form-error[data-input="${s}"]`);i&&(i.textContent=Array.isArray(e)?e.join(" "):e,i.classList.remove("hidden"))}),this._showMessage(s,"error"),this._emit("error",t)}_clearErrors(){this.form&&this.form.querySelectorAll(".form-error[data-input]").forEach(t=>{t.classList.add("hidden"),t.textContent=""})}_showMessage(t,e){this.config.useToast&&window.Toast?new Toast({message:t,type:e,duration:4e3,position:"top-center-full"}):alert(t)}reset(){this.form?(this.form.reset(),this._clearErrors(),this._setLoading(!1)):console.warn("FormSubmit: Cannot reset without form.")}submit(){this._handleSubmit()}getFormData(){return this.form?new FormData(this.form):(console.warn("FormSubmit: No form available."),new FormData)}setFieldValue(t,e){const s=this.form?.querySelector(`[name="${t}"]`);s&&(s.value=e)}getFieldValue(t){const e=this.form?.querySelector(`[name="${t}"]`);return e?e.value:null}}class a{constructor(t){if("string"==typeof t)this.inputs=document.querySelectorAll(t);else if(t instanceof HTMLElement)this.inputs=[t];else{if(!(t instanceof NodeList))throw new Error("ImageInput: Invalid input selector/element.");this.inputs=Array.from(t)}this.inputs.forEach(t=>this.init(t))}init(t){const e=t.closest(".form-group")?.querySelector("[data-img-preview]")||t.dataset.imgPreview&&document.querySelector(t.dataset.imgPreview);if(!e)return;const s=e,i=s.getAttribute("data-src")||s.src;t.addEventListener("change",e=>{if(t.files&&t.files[0]){const e=new FileReader;e.onload=t=>s.src=t.target.result,e.readAsDataURL(t.files[0])}}),t.addEventListener("keydown",e=>{"Escape"===e.key&&this.reset(t,s,i)}),s.addEventListener("dblclick",()=>this.reset(t,s,i))}reset(t,e,s){e.src=s,t.value=""}}class l{constructor({root:t=document,localeDropdownSelector:e=".dropdown",buttonSelector:s=".btn-locale",defaultLocale:i=null}={}){this.root=t,this.dropdown=this.root.querySelector(e),this.buttonSelector=s,this.defaultLocale=i||(this.dropdown?.querySelector("summary[data-default-locale]")?.dataset.defaultLocale??"en"),this.currentLocale=this.defaultLocale,this.init()}init(){this.dropdown?.querySelectorAll(this.buttonSelector).forEach(t=>{t.addEventListener("click",e=>{e.preventDefault();const s=t.dataset.locale;s&&this.switchLocale(s)})}),this.switchLocale(this.currentLocale)}switchLocale(t){this.currentLocale=t;const e=this.dropdown?.querySelector("summary");if(e){const s=this.dropdown.querySelector(`${this.buttonSelector}[data-locale="${t}"]`);s&&(e.innerHTML=s.innerHTML,e.setAttribute("data-default-locale",t),this.dropdown.removeAttribute("open"))}document.querySelectorAll("[data-locale-form]").forEach(e=>{e.classList.toggle("hidden",e.dataset.localeForm!==t),e.style.display=e.classList.contains("hidden")?"none":""})}}class c{constructor(t,e={}){this.config=Object.assign({closeOnSelect:!0},e),this.root="string"==typeof t?document.querySelector(t):t;const s=this.root.id.replace(/_dropdown$/,"");this.summary=this.root.querySelector("summary"),this.optionsBox=this.root.querySelector(".options"),this.searchInput=this.root.querySelector(".search-input"),this.hiddenInput=document.querySelector(`input#${s}`),this.options=Array.from(this.optionsBox.querySelectorAll(".option")),this.selectedIndex=-1;const i=this.hiddenInput?.value;if(i){const t=this.options.find(t=>t.dataset.value==i);t&&(t.setAttribute("data-selected","true"),t.classList.add("bg-base-300"),this.summary.textContent=t.dataset.label||t.textContent.trim())}this.resetBtn=this.root.closest(".form-control").querySelector(".select-reset"),this.resetBtn&&(i?this.resetBtn.classList.remove("hidden"):this.resetBtn.classList.add("hidden")),this.resetBtn&&this.resetBtn.addEventListener("click",t=>{t.preventDefault(),this._reset()}),this._bindEvents()}_bindEvents(){this.summary.addEventListener("click",t=>{setTimeout(()=>this._focusSearch(),120)}),this.optionsBox.addEventListener("click",t=>{const e=t.target.closest(".option");e&&this._select(e)}),this.options.forEach((t,e)=>{t.addEventListener("mouseenter",()=>this._highlight(e))}),this.root.addEventListener("keydown",t=>{this.root.hasAttribute("open")&&("ArrowDown"===t.key?(this._moveHighlight(1),t.preventDefault()):"ArrowUp"===t.key?(this._moveHighlight(-1),t.preventDefault()):"Enter"===t.key?(this.selectedIndex>=0&&this._select(this.options[this.selectedIndex]),t.preventDefault()):"Escape"===t.key&&(this.root.removeAttribute("open"),this.selectedIndex=-1,t.preventDefault()))}),this.searchInput.addEventListener("input",()=>this._filterOptions()),document.addEventListener("mousedown",t=>{this.root.contains(t.target)||this.root.removeAttribute("open")})}_focusSearch(){this.searchInput&&this.searchInput.focus()}_highlight(t){this.options.forEach((e,s)=>e.classList.toggle("bg-base-200",s===t)),this.selectedIndex=t}_moveHighlight(t){let e=this.options.filter(t=>!t.classList.contains("hidden"));if(!e.length)return;let s=e.findIndex(t=>t.classList.contains("bg-base-200"));s=-1===s?0:s+t,s<0&&(s=e.length-1),s>=e.length&&(s=0),e.forEach(t=>t.classList.remove("bg-base-200")),e[s].classList.add("bg-base-200"),this.selectedIndex=this.options.indexOf(e[s]),e[s].scrollIntoView({block:"nearest"})}_filterOptions(){const t=this.searchInput.value.trim().toLowerCase();this.options.forEach(e=>{const s=e.dataset.label.toLowerCase();e.classList.toggle("hidden",!s.includes(t))}),this.selectedIndex=-1}_select(t){const e=t.dataset.value,s=t.dataset.label||t.textContent.trim();this.summary.textContent=s,this.hiddenInput&&(this.hiddenInput.value=e),this.options.forEach(t=>{t.setAttribute("data-selected",""),t.classList.remove("bg-base-300")}),t.setAttribute("data-selected","true"),t.classList.add("bg-base-300"),this.config.closeOnSelect&&this.root.removeAttribute("open"),"function"==typeof this.config.onSelect&&this.config.onSelect({label:s,value:e},t),this.resetBtn&&this.resetBtn.classList.remove("hidden")}_reset(){this.hiddenInput&&(this.hiddenInput.value=""),this.summary.textContent=this.summary.dataset.label||this.summary.textContent.trim(),this.options.forEach(t=>{t.setAttribute("data-selected",""),t.classList.remove("bg-base-300")}),this.searchInput&&(this.searchInput.value=""),this.options.forEach(t=>t.classList.remove("hidden")),"function"==typeof this.config.onSelect&&this.config.onSelect({label:null,value:null},null),this.resetBtn&&this.resetBtn.classList.add("hidden")}selectValue(t){const e=this.options.find(e=>e.dataset.value==t);e&&this._select(e)}}class d{constructor(t,e={}){this.config=Object.assign({closeOnSelect:!1,maxSelections:null},e),this.root="string"==typeof t?document.querySelector(t):t,this.root.id.replace(/_dropdown$/,""),this.summary=this.root.querySelector("summary"),this.optionsBox=this.root.querySelector(".options"),this.searchInput=this.root.querySelector(".search-input"),this.hiddenInputsContainer=this.root.closest(".form-control").querySelector(".hidden-inputs"),this.selectedDisplay=this.root.querySelector(".selected-display"),this.placeholderText=this.root.querySelector(".placeholder-text"),this.selectionCountSpan=this.root.querySelector(".selection-count"),this.options=Array.from(this.optionsBox.querySelectorAll(".option")),this.checkboxes=Array.from(this.optionsBox.querySelectorAll(".option-checkbox")),this.resetBtn=this.root.closest(".form-control").querySelector(".select-reset"),this.selections=new Set,this.disabledOptions=new Set,this._initializeSelections(),this._updateDisplay(),this._updateResetButton(),this._bindEvents()}_initializeSelections(){this.checkboxes.forEach(t=>{t.checked&&this.selections.add(t.value)})}_bindEvents(){this.summary.addEventListener("click",t=>{if(t.target.closest(".remove-selection"))return t.preventDefault(),void t.stopPropagation();setTimeout(()=>this._focusSearch(),120)}),this.optionsBox.addEventListener("change",t=>{t.target.classList.contains("option-checkbox")&&this._toggleSelection(t.target)}),this.selectedDisplay.addEventListener("click",t=>{const e=t.target.closest(".remove-selection");if(e){t.preventDefault(),t.stopPropagation();const s=e.dataset.value;this._removeSelection(s)}}),this.resetBtn&&this.resetBtn.addEventListener("click",t=>{t.preventDefault(),this._reset()}),this.searchInput&&this.searchInput.addEventListener("input",()=>this._filterOptions()),this.root.addEventListener("keydown",t=>{this.root.hasAttribute("open")&&"Escape"===t.key&&(this.root.removeAttribute("open"),t.preventDefault())}),document.addEventListener("mousedown",t=>{this.root.contains(t.target)||this.root.removeAttribute("open")})}_focusSearch(){this.searchInput&&this.searchInput.focus()}_toggleSelection(t){const e=t.value,s=t.checked;if(this.disabledOptions.has(e))t.checked=!1;else if(s){if(this.config.maxSelections&&this.selections.size>=this.config.maxSelections)return t.checked=!1,void this._showMaxSelectionWarning();this._addSelection(e)}else this._removeSelection(e)}_addSelection(t){this.selections.add(t);const e=this.checkboxes.find(e=>e.value===t),s=e?.closest(".option");e&&(e.checked=!0),s&&s.classList.add("bg-base-300"),this._updateDisplay(),this._updateHiddenInputs(),this._updateResetButton(),this._updateSelectionCount(),"function"==typeof this.config.onSelect&&this.config.onSelect({selections:Array.from(this.selections),added:t},s)}_removeSelection(t){this.selections.delete(t);const e=this.checkboxes.find(e=>e.value===t),s=e?.closest(".option");e&&(e.checked=!1),s&&s.classList.remove("bg-base-300"),this._updateDisplay(),this._updateHiddenInputs(),this._updateResetButton(),this._updateSelectionCount(),"function"==typeof this.config.onRemove&&this.config.onRemove({selections:Array.from(this.selections),removed:t},s)}_updateDisplay(){if(0===this.selections.size)this.selectedDisplay.innerHTML=`<span class="placeholder-text text-gray-500">${this.summary.dataset.label||"Select items"}</span>`;else{const t=Array.from(this.selections).map(t=>{const e=this.options.find(e=>e.dataset.value===t);return`<span class="badge badge-primary badge-sm">\n ${e?.dataset.label||t}\n <button type="button" class="ml-1 remove-selection" data-value="${t}">\n <svg class="size-3" viewBox="0 0 24 24"><path fill="currentColor" d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"/></svg>\n </button>\n </span>`}).join("");this.selectedDisplay.innerHTML=`<div class="flex flex-wrap gap-1">${t}</div>`}}_updateHiddenInputs(){this.hiddenInputsContainer.innerHTML="",this.selections.forEach(t=>{const e=document.createElement("input");e.type="hidden",e.name=`${this.root.id.replace(/_dropdown$/,"")}[]`,e.value=t,this.hiddenInputsContainer.appendChild(e)})}_updateResetButton(){this.resetBtn&&this.resetBtn.classList.toggle("hidden",0===this.selections.size)}_updateSelectionCount(){this.selectionCountSpan&&(this.selectionCountSpan.textContent=this.selections.size)}_filterOptions(){const t=this.searchInput.value.trim().toLowerCase();this.options.forEach(e=>{const s=e.dataset.label.toLowerCase(),i=this.disabledOptions.has(e.dataset.value);e.classList.toggle("hidden",!s.includes(t)||i)})}_updateOptionVisualState(t){const e=this.checkboxes.find(e=>e.value===t),s=e?.closest(".option");if(e&&s){const i=this.disabledOptions.has(t);e.disabled=i,i?(s.classList.add("opacity-50","cursor-not-allowed"),s.classList.remove("hover:bg-base-200","cursor-pointer"),this.selections.has(t)&&this._removeSelection(t)):(s.classList.remove("opacity-50","cursor-not-allowed"),s.classList.add("hover:bg-base-200","cursor-pointer"))}}_reset(){this.selections.clear(),this.checkboxes.forEach(t=>{t.checked=!1,t.closest(".option").classList.remove("bg-base-300")}),this._updateDisplay(),this._updateHiddenInputs(),this._updateResetButton(),this._updateSelectionCount(),this.searchInput&&(this.searchInput.value=""),this.options.forEach(t=>t.classList.remove("hidden")),"function"==typeof this.config.onSelect&&this.config.onSelect({selections:[],cleared:!0},null)}_showMaxSelectionWarning(){console.warn(`Maximum ${this.config.maxSelections} selections allowed`)}selectValues(t){t.forEach(t=>{this.selections.has(t)||this.disabledOptions.has(t)||this._addSelection(t)})}getSelections(){return Array.from(this.selections)}clearSelections(){this._reset()}disableOption(t){(Array.isArray(t)?t:[t]).forEach(t=>{this.disabledOptions.add(t),this._updateOptionVisualState(t)}),this.searchInput&&this.searchInput.value.trim()&&this._filterOptions()}enableOption(t){(Array.isArray(t)?t:[t]).forEach(t=>{this.disabledOptions.delete(t),this._updateOptionVisualState(t)}),this.searchInput&&this.searchInput.value.trim()&&this._filterOptions()}isOptionDisabled(t){return this.disabledOptions.has(t)}getDisabledOptions(){return Array.from(this.disabledOptions)}clearDisabledOptions(){const t=Array.from(this.disabledOptions);this.disabledOptions.clear(),t.forEach(t=>{this._updateOptionVisualState(t)}),this.searchInput&&this.searchInput.value.trim()&&this._filterOptions()}}let h=class{constructor({message:t="",title:e="",type:s="info",duration:i=4e3,position:n="top-center",icon:o=null}={}){Object.assign(this,{message:t,title:e,type:s,duration:i,position:n,icon:o}),this._show()}_show(){const t=document.createElement("div");t.className=["fixed","z-50","transform","-translate-y-full","pointer-events-none",...this._posClass().split(" "),"w-full","mx-auto"].filter(Boolean).join(" ");const e={success:"bg-green-600",error:"bg-red-600",warning:"bg-yellow-500",info:"bg-blue-600"}[this.type];t.innerHTML=`\n<div class="flex flex-col items-center justify-center w-full ${e} bg-opacity-80 ">\n <div class="text-white p-4 flex items-center space-x-2 pointer-events-auto justify-center">\n ${this.icon?`<img src="${this.icon}" class="size-[30px] flex-shrink-0"/>`:""}\n <div class="flex-1 text-left">\n ${this.title?`<h4 class="font-semibold">${this.title}</h4>`:""}\n <p class="text-sm">${this.message}</p>\n </div>\n </div>\n <div class="${e} h-1 overflow-hidden w-full">\n <div class="toast-bar h-full bg-white w-full"></div>\n </div>\n </div>\n `,document.body.appendChild(t),requestAnimationFrame(()=>{t.classList.add("animate-toast-in"),t.classList.remove("-translate-y-full")});const s=t.querySelector(".toast-bar"),i=performance.now(),n=e=>{const o=e-i,r=Math.max(0,1-o/this.duration);s.style.width=100*r+"%",o<this.duration?requestAnimationFrame(n):(t.classList.replace("animate-toast-in","animate-toast-out"),t.addEventListener("animationend",()=>t.remove()))};requestAnimationFrame(n)}_posClass(){const t={"top-left":"top-4 left-4","top-center":"top-4 left-1/2 transform -translate-x-1/2","top-center-full":"top-0 left-1/2 transform -translate-x-1/2","bottom-center-full":"bottom-0 left-1/2 transform -translate-x-1/2","top-right":"top-4 right-4","bottom-left":"bottom-4 left-4","bottom-center":"bottom-4 left-1/2 transform -translate-x-1/2","bottom-right":"bottom-4 right-4"};return t[this.position]||t["top-center"]}};var u={AjaxDivBox:e,AjaxTable:s,CodeInput:i,DeleteContent:n,EditContent:o,FormSubmit:r,ImageInput:a,LanguageSwitch:l,SelectDropdown:c,SelectMultipleDropdown:d,Toast:h};t.AjaxDivBox=e,t.AjaxTable=s,t.CodeInput=i,t.DeleteContent=n,t.EditContent=o,t.FormSubmit=r,t.ImageInput=a,t.LanguageSwitch=l,t.SelectDropdown=c,t.SelectMultipleDropdown=d,t.Toast=h,t.default=u,t.version="1.0.0",Object.defineProperty(t,"__esModule",{value:!0})}); //# sourceMappingURL=index.umd.js.map