@dmitryvim/form-builder 0.2.0 → 0.2.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.
@@ -0,0 +1,184 @@
1
+ var FormBuilder=(function(F){"use strict";function se(e,t){(e.minLength!==null||e.maxLength!==null)&&(e.minLength!==null&&e.maxLength!==null?t.push(`length=${e.minLength}-${e.maxLength} characters`):e.maxLength!==null?t.push(`max=${e.maxLength} characters`):e.minLength!==null&&t.push(`min=${e.minLength} characters`))}function ce(e,t){(e.min!==null||e.max!==null)&&(e.min!==null&&e.max!==null?t.push(`range=${e.min}-${e.max}`):e.max!==null?t.push(`max=${e.max}`):e.min!==null&&t.push(`min=${e.min}`))}function de(e,t){e.maxSizeMB&&t.push(`max_size=${e.maxSizeMB}MB`)}function ue(e,t){var n;(n=e.accept)!=null&&n.extensions&&t.push(`formats=${e.accept.extensions.map(r=>r.toUpperCase()).join(",")}`)}function me(e,t){var n;e.pattern&&!e.pattern.includes("\u0410-\u042F")?t.push("plain text only"):(n=e.pattern)!=null&&n.includes("\u0410-\u042F")&&t.push("text with punctuation")}function k(e){const t=[];return t.push(e.required?"required":"optional"),se(e,t),ce(e,t),de(e,t),ue(e,t),me(e,t),t.join(" \u2022 ")}function M(e){const t=[];if(!e||typeof e!="object")return t.push("Schema must be an object"),t;if(e.version||t.push("Schema missing version"),!Array.isArray(e.elements))return t.push("Schema missing elements array"),t;function n(r,c){r.forEach((l,o)=>{const a=`${c}[${o}]`;if(l.type||t.push(`${a}: missing type`),l.key||t.push(`${a}: missing key`),l.type==="group"&&"elements"in l&&l.elements&&n(l.elements,`${a}.elements`),l.type==="container"&&l.elements&&n(l.elements,`${a}.elements`),l.type==="select"&&l.options){const i=l.default;i!=null&&i!==""&&(l.options.some(s=>s.value===i)||t.push(`${a}: default "${i}" not in options`))}})}return Array.isArray(e.elements)&&n(e.elements,"elements"),t}function A(e){return e&&typeof e=="object"&&e.constructor===Object}function L(e,t){return e?`${e}.${t}`:t}function N(e){for(;e.firstChild;)e.removeChild(e.firstChild)}function pe(e,t,n,r){const c=t.state,l=document.createElement("input");if(l.type="text",l.className="w-full rounded-lg",l.style.cssText=`
2
+ padding: var(--fb-input-padding-y) var(--fb-input-padding-x);
3
+ border: var(--fb-border-width) solid var(--fb-border-color);
4
+ border-radius: var(--fb-border-radius);
5
+ background-color: ${c.config.readonly?"var(--fb-background-readonly-color)":"var(--fb-background-color)"};
6
+ color: var(--fb-text-color);
7
+ font-size: var(--fb-font-size);
8
+ font-family: var(--fb-font-family);
9
+ transition: all var(--fb-transition-duration) ease-in-out;
10
+ `,l.name=r,l.placeholder=e.placeholder||"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442",l.value=t.prefill[e.key]||e.default||"",l.readOnly=c.config.readonly,c.config.readonly||(l.addEventListener("focus",()=>{l.style.borderColor="var(--fb-border-focus-color)",l.style.outline="var(--fb-focus-ring-width) solid var(--fb-focus-ring-color)",l.style.outlineOffset="0"}),l.addEventListener("blur",()=>{l.style.borderColor="var(--fb-border-color)",l.style.outline="none"}),l.addEventListener("mouseenter",()=>{document.activeElement!==l&&(l.style.borderColor="var(--fb-border-hover-color)")}),l.addEventListener("mouseleave",()=>{document.activeElement!==l&&(l.style.borderColor="var(--fb-border-color)")})),!c.config.readonly&&t.instance){const a=()=>{t.instance.triggerOnChange(r,l.value)};l.addEventListener("blur",a),l.addEventListener("input",a)}n.appendChild(l);const o=document.createElement("p");o.className="mt-1",o.style.cssText=`
11
+ font-size: var(--fb-font-size-small);
12
+ color: var(--fb-text-secondary-color);
13
+ `,o.textContent=k(e),n.appendChild(o)}function fe(e,t,n,r){var c,l;const o=t.state,a=t.prefill[e.key]||[],i=Array.isArray(a)?[...a]:[],s=(c=e.minCount)!=null?c:1,u=(l=e.maxCount)!=null?l:1/0;for(;i.length<s;)i.push(e.default||"");const d=document.createElement("div");d.className="space-y-2",n.appendChild(d);function h(){d.querySelectorAll(".multiple-text-item").forEach((x,g)=>{const y=x.querySelector("input");y&&(y.name=`${r}[${g}]`)})}function p(x="",g=-1){const y=document.createElement("div");y.className="multiple-text-item flex items-center gap-2";const f=document.createElement("input");if(f.type="text",f.className="flex-1",f.style.cssText=`
14
+ padding: var(--fb-input-padding-y) var(--fb-input-padding-x);
15
+ border: var(--fb-border-width) solid var(--fb-border-color);
16
+ border-radius: var(--fb-border-radius);
17
+ background-color: ${o.config.readonly?"var(--fb-background-readonly-color)":"var(--fb-background-color)"};
18
+ color: var(--fb-text-color);
19
+ font-size: var(--fb-font-size);
20
+ font-family: var(--fb-font-family);
21
+ transition: all var(--fb-transition-duration) ease-in-out;
22
+ `,f.placeholder=e.placeholder||"Enter text",f.value=x,f.readOnly=o.config.readonly,o.config.readonly||(f.addEventListener("focus",()=>{f.style.borderColor="var(--fb-border-focus-color)",f.style.outline="var(--fb-focus-ring-width) solid var(--fb-focus-ring-color)",f.style.outlineOffset="0"}),f.addEventListener("blur",()=>{f.style.borderColor="var(--fb-border-color)",f.style.outline="none"}),f.addEventListener("mouseenter",()=>{document.activeElement!==f&&(f.style.borderColor="var(--fb-border-hover-color)")}),f.addEventListener("mouseleave",()=>{document.activeElement!==f&&(f.style.borderColor="var(--fb-border-color)")})),!o.config.readonly&&t.instance){const C=()=>{t.instance.triggerOnChange(f.name,f.value)};f.addEventListener("blur",C),f.addEventListener("input",C)}return y.appendChild(f),g===-1?d.appendChild(y):d.insertBefore(y,d.children[g]),h(),y}function m(){if(o.config.readonly)return;const x=d.querySelectorAll(".multiple-text-item"),g=x.length;x.forEach(y=>{let f=y.querySelector(".remove-item-btn");f||(f=document.createElement("button"),f.type="button",f.className="remove-item-btn px-2 py-1 rounded",f.style.cssText=`
23
+ color: var(--fb-error-color);
24
+ background-color: transparent;
25
+ transition: background-color var(--fb-transition-duration);
26
+ `,f.innerHTML="\u2715",f.addEventListener("mouseenter",()=>{f.style.backgroundColor="var(--fb-background-hover-color)"}),f.addEventListener("mouseleave",()=>{f.style.backgroundColor="transparent"}),f.onclick=()=>{const E=Array.from(d.children).indexOf(y);d.children.length>s&&(i.splice(E,1),y.remove(),h(),v(),m())},y.appendChild(f));const C=g<=s;f.disabled=C,f.style.opacity=C?"0.5":"1",f.style.pointerEvents=C?"none":"auto"})}function v(){const x=n.querySelector(".add-text-btn");if(x&&x.remove(),!o.config.readonly&&i.length<u){const g=document.createElement("button");g.type="button",g.className="add-text-btn mt-2 px-3 py-1 rounded",g.style.cssText=`
27
+ color: var(--fb-primary-color);
28
+ border: var(--fb-border-width) solid var(--fb-primary-color);
29
+ background-color: transparent;
30
+ font-size: var(--fb-font-size);
31
+ transition: all var(--fb-transition-duration);
32
+ `,g.textContent=`+ Add ${e.label||"Text"}`,g.addEventListener("mouseenter",()=>{g.style.backgroundColor="var(--fb-background-hover-color)"}),g.addEventListener("mouseleave",()=>{g.style.backgroundColor="transparent"}),g.onclick=()=>{i.push(e.default||""),p(e.default||""),v(),m()},n.appendChild(g)}}i.forEach(x=>p(x)),v(),m();const b=document.createElement("p");b.className="mt-1",b.style.cssText=`
33
+ font-size: var(--fb-font-size-small);
34
+ color: var(--fb-text-secondary-color);
35
+ `,b.textContent=k(e),n.appendChild(b)}function I(e,t,n){var r,c,l;const o=[],{scopeRoot:a,skipValidation:i}=n,s=(d,h)=>{var p,m;if(!d)return;const v=`error-${d.getAttribute("name")||Math.random().toString(36).substring(7)}`;let b=document.getElementById(v);h?(d.classList.add("invalid"),d.title=h,b||(b=document.createElement("div"),b.id=v,b.className="error-message",b.style.cssText=`
36
+ color: var(--fb-error-color);
37
+ font-size: var(--fb-font-size-small);
38
+ margin-top: 0.25rem;
39
+ `,d.nextSibling?(p=d.parentNode)==null||p.insertBefore(b,d.nextSibling):(m=d.parentNode)==null||m.appendChild(b)),b.textContent=h,b.style.display="block"):(d.classList.remove("invalid"),d.title="",b&&b.remove())},u=(d,h,p)=>{let m=!1;if(!i&&h){if(e.minLength!==void 0&&e.minLength!==null&&h.length<e.minLength)o.push(`${p}: minLength=${e.minLength}`),s(d,`minLength=${e.minLength}`),m=!0;else if(e.maxLength!==void 0&&e.maxLength!==null&&h.length>e.maxLength)o.push(`${p}: maxLength=${e.maxLength}`),s(d,`maxLength=${e.maxLength}`),m=!0;else if(e.pattern)try{new RegExp(e.pattern).test(h)||(o.push(`${p}: pattern mismatch`),s(d,"pattern mismatch"),m=!0)}catch(v){o.push(`${p}: invalid pattern`),s(d,"invalid pattern"),m=!0}}m||s(d,null)};if(e.multiple){const d=a.querySelectorAll(`[name^="${t}["]`),h=[];if(d.forEach((p,m)=>{var v;const b=(v=p==null?void 0:p.value)!=null?v:"";h.push(b),u(p,b,`${t}[${m}]`)}),!i){const p=(r=e.minCount)!=null?r:1,m=(c=e.maxCount)!=null?c:1/0,v=h.filter(b=>b.trim()!=="");e.required&&v.length===0&&o.push(`${t}: required`),v.length<p&&o.push(`${t}: minimum ${p} items required`),v.length>m&&o.push(`${t}: maximum ${m} items allowed`)}return{value:h,errors:o}}else{const d=a.querySelector(`[name$="${t}"]`),h=(l=d==null?void 0:d.value)!=null?l:"";return!i&&e.required&&h===""?(o.push(`${t}: required`),s(d,"required"),{value:"",errors:o}):(u(d,h,t),{value:h,errors:o})}}function U(e,t,n,r){const{scopeRoot:c}=r;if(e.multiple){if(!Array.isArray(n)){console.warn(`updateTextField: Expected array for multiple field "${t}", got ${typeof n}`);return}const l=c.querySelectorAll(`[name^="${t}["]`);l.forEach((o,a)=>{a<n.length&&(o.value=n[a]!=null?String(n[a]):"",o.classList.remove("invalid"),o.title="")}),n.length!==l.length&&console.warn(`updateTextField: Multiple field "${t}" has ${l.length} inputs but received ${n.length} values. Consider re-rendering for add/remove.`)}else{const l=c.querySelector(`[name="${t}"]`);l&&(l.value=n!=null?String(n):"",l.classList.remove("invalid"),l.title="")}}function he(e,t,n,r){const c=t.state,l=document.createElement("textarea");if(l.className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 resize-none",l.name=r,l.placeholder=e.placeholder||"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442",l.rows=e.rows||4,l.value=t.prefill[e.key]||e.default||"",l.readOnly=c.config.readonly,!c.config.readonly&&t.instance){const a=()=>{t.instance.triggerOnChange(r,l.value)};l.addEventListener("blur",a),l.addEventListener("input",a)}n.appendChild(l);const o=document.createElement("p");o.className="text-xs text-gray-500 mt-1",o.textContent=k(e),n.appendChild(o)}function ve(e,t,n,r){var c,l;const o=t.state,a=t.prefill[e.key]||[],i=Array.isArray(a)?[...a]:[],s=(c=e.minCount)!=null?c:1,u=(l=e.maxCount)!=null?l:1/0;for(;i.length<s;)i.push(e.default||"");const d=document.createElement("div");d.className="space-y-2",n.appendChild(d);function h(){d.querySelectorAll(".multiple-textarea-item").forEach((x,g)=>{const y=x.querySelector("textarea");y&&(y.name=`${r}[${g}]`)})}function p(x="",g=-1){const y=document.createElement("div");y.className="multiple-textarea-item";const f=document.createElement("textarea");if(f.className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 resize-none",f.placeholder=e.placeholder||"Enter text",f.rows=e.rows||4,f.value=x,f.readOnly=o.config.readonly,!o.config.readonly&&t.instance){const C=()=>{t.instance.triggerOnChange(f.name,f.value)};f.addEventListener("blur",C),f.addEventListener("input",C)}return y.appendChild(f),g===-1?d.appendChild(y):d.insertBefore(y,d.children[g]),h(),y}function m(){if(o.config.readonly)return;const x=d.querySelectorAll(".multiple-textarea-item"),g=x.length;x.forEach(y=>{let f=y.querySelector(".remove-item-btn");f||(f=document.createElement("button"),f.type="button",f.className="remove-item-btn mt-1 px-2 py-1 text-red-600 hover:bg-red-50 rounded text-sm",f.innerHTML="\u2715 Remove",f.onclick=()=>{const E=Array.from(d.children).indexOf(y);d.children.length>s&&(i.splice(E,1),y.remove(),h(),v(),m())},y.appendChild(f));const C=g<=s;f.disabled=C,f.style.opacity=C?"0.5":"1",f.style.pointerEvents=C?"none":"auto"})}function v(){const x=n.querySelector(".add-textarea-btn");if(x&&x.remove(),!o.config.readonly&&i.length<u){const g=document.createElement("button");g.type="button",g.className="add-textarea-btn mt-2 px-3 py-1 text-blue-600 border border-blue-300 rounded hover:bg-blue-50 text-sm",g.textContent=`+ Add ${e.label||"Textarea"}`,g.onclick=()=>{i.push(e.default||""),p(e.default||""),v(),m()},n.appendChild(g)}}i.forEach(x=>p(x)),v(),m();const b=document.createElement("p");b.className="text-xs text-gray-500 mt-1",b.textContent=k(e),n.appendChild(b)}function ge(e,t,n){return I(e,t,n)}function ye(e,t,n,r){U(e,t,n,r)}function be(e,t,n,r){const c=t.state,l=document.createElement("input");if(l.type="number",l.className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500",l.name=r,l.placeholder=e.placeholder||"0",e.min!==void 0&&(l.min=e.min.toString()),e.max!==void 0&&(l.max=e.max.toString()),e.step!==void 0&&(l.step=e.step.toString()),l.value=t.prefill[e.key]||e.default||"",l.readOnly=c.config.readonly,!c.config.readonly&&t.instance){const a=()=>{const i=l.value?parseFloat(l.value):null;t.instance.triggerOnChange(r,i)};l.addEventListener("blur",a),l.addEventListener("input",a)}n.appendChild(l);const o=document.createElement("p");o.className="text-xs text-gray-500 mt-1",o.textContent=k(e),n.appendChild(o)}function xe(e,t,n,r){var c,l;const o=t.state,a=t.prefill[e.key]||[],i=Array.isArray(a)?[...a]:[],s=(c=e.minCount)!=null?c:1,u=(l=e.maxCount)!=null?l:1/0;for(;i.length<s;)i.push(e.default||"");const d=document.createElement("div");d.className="space-y-2",n.appendChild(d);function h(){d.querySelectorAll(".multiple-number-item").forEach((x,g)=>{const y=x.querySelector("input");y&&(y.name=`${r}[${g}]`)})}function p(x="",g=-1){const y=document.createElement("div");y.className="multiple-number-item flex items-center gap-2";const f=document.createElement("input");if(f.type="number",f.className="flex-1 px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500",f.placeholder=e.placeholder||"0",e.min!==void 0&&(f.min=e.min.toString()),e.max!==void 0&&(f.max=e.max.toString()),e.step!==void 0&&(f.step=e.step.toString()),f.value=x.toString(),f.readOnly=o.config.readonly,!o.config.readonly&&t.instance){const C=()=>{const E=f.value?parseFloat(f.value):null;t.instance.triggerOnChange(f.name,E)};f.addEventListener("blur",C),f.addEventListener("input",C)}return y.appendChild(f),g===-1?d.appendChild(y):d.insertBefore(y,d.children[g]),h(),y}function m(){if(o.config.readonly)return;const x=d.querySelectorAll(".multiple-number-item"),g=x.length;x.forEach(y=>{let f=y.querySelector(".remove-item-btn");f||(f=document.createElement("button"),f.type="button",f.className="remove-item-btn px-2 py-1 text-red-600 hover:bg-red-50 rounded",f.innerHTML="\u2715",f.onclick=()=>{const E=Array.from(d.children).indexOf(y);d.children.length>s&&(i.splice(E,1),y.remove(),h(),v(),m())},y.appendChild(f));const C=g<=s;f.disabled=C,f.style.opacity=C?"0.5":"1",f.style.pointerEvents=C?"none":"auto"})}function v(){const x=n.querySelector(".add-number-btn");if(x&&x.remove(),!o.config.readonly&&i.length<u){const g=document.createElement("button");g.type="button",g.className="add-number-btn mt-2 px-3 py-1 text-blue-600 border border-blue-300 rounded hover:bg-blue-50 text-sm",g.textContent=`+ Add ${e.label||"Number"}`,g.onclick=()=>{i.push(e.default||""),p(e.default||""),v(),m()},n.appendChild(g)}}i.forEach(x=>p(x)),v(),m();const b=document.createElement("p");b.className="text-xs text-gray-500 mt-1",b.textContent=k(e),n.appendChild(b)}function Ce(e,t,n){var r,c,l,o,a;const i=[],{scopeRoot:s,skipValidation:u}=n,d=(p,m)=>{var v,b;if(!p)return;const x=`error-${p.getAttribute("name")||Math.random().toString(36).substring(7)}`;let g=document.getElementById(x);m?(p.classList.add("invalid"),p.title=m,g||(g=document.createElement("div"),g.id=x,g.className="error-message",g.style.cssText=`
40
+ color: var(--fb-error-color);
41
+ font-size: var(--fb-font-size-small);
42
+ margin-top: 0.25rem;
43
+ `,p.nextSibling?(v=p.parentNode)==null||v.insertBefore(g,p.nextSibling):(b=p.parentNode)==null||b.appendChild(g)),g.textContent=m,g.style.display="block"):(p.classList.remove("invalid"),p.title="",g&&g.remove())},h=(p,m,v)=>{let b=!1;!u&&e.min!==void 0&&e.min!==null&&m<e.min?(i.push(`${v}: < min=${e.min}`),d(p,`< min=${e.min}`),b=!0):!u&&e.max!==void 0&&e.max!==null&&m>e.max&&(i.push(`${v}: > max=${e.max}`),d(p,`> max=${e.max}`),b=!0),b||d(p,null)};if(e.multiple){const p=s.querySelectorAll(`[name^="${t}["]`),m=[];if(p.forEach((v,b)=>{var x,g,y;const f=(x=v==null?void 0:v.value)!=null?x:"";if(f===""){m.push(null),d(v,null);return}const C=parseFloat(f);if(!u&&!Number.isFinite(C)){i.push(`${t}[${b}]: not a number`),d(v,"not a number"),m.push(null);return}h(v,C,`${t}[${b}]`);const E=Number.isInteger((g=e.decimals)!=null?g:0)&&(y=e.decimals)!=null?y:0;m.push(Number(C.toFixed(E)))}),!u){const v=(r=e.minCount)!=null?r:1,b=(c=e.maxCount)!=null?c:1/0,x=m.filter(g=>g!==null);e.required&&x.length===0&&i.push(`${t}: required`),x.length<v&&i.push(`${t}: minimum ${v} items required`),x.length>b&&i.push(`${t}: maximum ${b} items allowed`)}return{value:m,errors:i}}else{const p=s.querySelector(`[name$="${t}"]`),m=(l=p==null?void 0:p.value)!=null?l:"";if(!u&&e.required&&m==="")return i.push(`${t}: required`),d(p,"required"),{value:null,errors:i};if(m==="")return d(p,null),{value:null,errors:i};const v=parseFloat(m);if(!u&&!Number.isFinite(v))return i.push(`${t}: not a number`),d(p,"not a number"),{value:null,errors:i};h(p,v,t);const b=Number.isInteger((o=e.decimals)!=null?o:0)&&(a=e.decimals)!=null?a:0;return{value:Number(v.toFixed(b)),errors:i}}}function Ee(e,t,n,r){const{scopeRoot:c}=r;if(e.multiple){if(!Array.isArray(n)){console.warn(`updateNumberField: Expected array for multiple field "${t}", got ${typeof n}`);return}const l=c.querySelectorAll(`[name^="${t}["]`);l.forEach((o,a)=>{a<n.length&&(o.value=n[a]!=null?String(n[a]):"",o.classList.remove("invalid"),o.title="")}),n.length!==l.length&&console.warn(`updateNumberField: Multiple field "${t}" has ${l.length} inputs but received ${n.length} values. Consider re-rendering for add/remove.`)}else{const l=c.querySelector(`[name="${t}"]`);l&&(l.value=n!=null?String(n):"",l.classList.remove("invalid"),l.title="")}}function we(e,t,n,r){const c=t.state,l=document.createElement("select");if(l.className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500",l.name=r,l.disabled=c.config.readonly,(e.options||[]).forEach(a=>{const i=document.createElement("option");i.value=a.value,i.textContent=a.label,(t.prefill[e.key]||e.default)===a.value&&(i.selected=!0),l.appendChild(i)}),!c.config.readonly&&t.instance){const a=()=>{t.instance.triggerOnChange(r,l.value)};l.addEventListener("change",a)}n.appendChild(l);const o=document.createElement("p");o.className="text-xs text-gray-500 mt-1",o.textContent=k(e),n.appendChild(o)}function $e(e,t,n,r){var c,l,o,a;const i=t.state,s=t.prefill[e.key]||[],u=Array.isArray(s)?[...s]:[],d=(c=e.minCount)!=null?c:1,h=(l=e.maxCount)!=null?l:1/0;for(;u.length<d;)u.push(e.default||((a=(o=e.options)==null?void 0:o[0])==null?void 0:a.value)||"");const p=document.createElement("div");p.className="space-y-2",n.appendChild(p);function m(){p.querySelectorAll(".multiple-select-item").forEach((y,f)=>{const C=y.querySelector("select");C&&(C.name=`${r}[${f}]`)})}function v(y="",f=-1){const C=document.createElement("div");C.className="multiple-select-item flex items-center gap-2";const E=document.createElement("select");if(E.className="flex-1 px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500",E.disabled=i.config.readonly,(e.options||[]).forEach(w=>{const S=document.createElement("option");S.value=w.value,S.textContent=w.label,y===w.value&&(S.selected=!0),E.appendChild(S)}),!i.config.readonly&&t.instance){const w=()=>{t.instance.triggerOnChange(E.name,E.value)};E.addEventListener("change",w)}return C.appendChild(E),f===-1?p.appendChild(C):p.insertBefore(C,p.children[f]),m(),C}function b(){if(i.config.readonly)return;const y=p.querySelectorAll(".multiple-select-item"),f=y.length;y.forEach(C=>{let E=C.querySelector(".remove-item-btn");E||(E=document.createElement("button"),E.type="button",E.className="remove-item-btn px-2 py-1 text-red-600 hover:bg-red-50 rounded",E.innerHTML="\u2715",E.onclick=()=>{const S=Array.from(p.children).indexOf(C);p.children.length>d&&(u.splice(S,1),C.remove(),m(),x(),b())},C.appendChild(E));const w=f<=d;E.disabled=w,E.style.opacity=w?"0.5":"1",E.style.pointerEvents=w?"none":"auto"})}function x(){const y=n.querySelector(".add-select-btn");if(y&&y.remove(),!i.config.readonly&&u.length<h){const f=document.createElement("button");f.type="button",f.className="add-select-btn mt-2 px-3 py-1 text-blue-600 border border-blue-300 rounded hover:bg-blue-50 text-sm",f.textContent=`+ Add ${e.label||"Selection"}`,f.onclick=()=>{var C,E;const w=e.default||((E=(C=e.options)==null?void 0:C[0])==null?void 0:E.value)||"";u.push(w),v(w),x(),b()},n.appendChild(f)}}u.forEach(y=>v(y)),x(),b();const g=document.createElement("p");g.className="text-xs text-gray-500 mt-1",g.textContent=k(e),n.appendChild(g)}function ke(e,t,n){var r;const c=[],{scopeRoot:l,skipValidation:o}=n,a=(s,u)=>{var d,h;if(!s)return;const p=`error-${s.getAttribute("name")||Math.random().toString(36).substring(7)}`;let m=document.getElementById(p);u?(s.classList.add("invalid"),s.title=u,m||(m=document.createElement("div"),m.id=p,m.className="error-message",m.style.cssText=`
44
+ color: var(--fb-error-color);
45
+ font-size: var(--fb-font-size-small);
46
+ margin-top: 0.25rem;
47
+ `,s.nextSibling?(d=s.parentNode)==null||d.insertBefore(m,s.nextSibling):(h=s.parentNode)==null||h.appendChild(m)),m.textContent=u,m.style.display="block"):(s.classList.remove("invalid"),s.title="",m&&m.remove())},i=(s,u,d,h)=>{var p,m;if(o)return;const v=u.filter(h),b="minCount"in d&&(p=d.minCount)!=null?p:1,x="maxCount"in d&&(m=d.maxCount)!=null?m:1/0;d.required&&v.length===0&&c.push(`${s}: required`),v.length<b&&c.push(`${s}: minimum ${b} items required`),v.length>x&&c.push(`${s}: maximum ${x} items allowed`)};if("multiple"in e&&e.multiple){const s=l.querySelectorAll(`[name^="${t}["]`),u=[];return s.forEach(d=>{var h;const p=(h=d==null?void 0:d.value)!=null?h:"";u.push(p),a(d,null)}),i(t,u,e,d=>d!==""),{value:u,errors:c}}else{const s=l.querySelector(`[name$="${t}"]`),u=(r=s==null?void 0:s.value)!=null?r:"";return!o&&e.required&&u===""?(c.push(`${t}: required`),a(s,"required"),{value:null,errors:c}):(a(s,null),{value:u===""?null:u,errors:c})}}function Fe(e,t,n,r){const{scopeRoot:c}=r;if("multiple"in e&&e.multiple){if(!Array.isArray(n)){console.warn(`updateSelectField: Expected array for multiple field "${t}", got ${typeof n}`);return}const l=c.querySelectorAll(`[name^="${t}["]`);l.forEach((o,a)=>{a<n.length&&(o.value=n[a]!=null?String(n[a]):"",o.querySelectorAll("option").forEach(i=>{i.selected=i.value===String(n[a])}),o.classList.remove("invalid"),o.title="")}),n.length!==l.length&&console.warn(`updateSelectField: Multiple field "${t}" has ${l.length} selects but received ${n.length} values. Consider re-rendering for add/remove.`)}else{const l=c.querySelector(`[name="${t}"]`);l&&(l.value=n!=null?String(n):"",l.querySelectorAll("option").forEach(o=>{o.selected=o.value===String(n)}),l.classList.remove("invalid"),l.title="")}}function $(e,t){const n=t.config.locale||"en";return(t.config.translations[n]||t.config.translations.en)[e]||e}async function O(e,t,n,r={}){const{fileName:c="",isReadonly:l=!1,deps:o=null}=r;if(!l&&o&&(!o.picker||!o.fileUploadHandler||!o.dragHandler))throw new Error("renderFilePreview: missing deps {picker, fileUploadHandler, dragHandler}");N(e),l&&e.classList.add("cursor-pointer");const a=document.createElement("img");a.className="w-full h-full object-contain",a.alt=c||"Preview";const i=n.resourceIndex.get(t);if(i&&i.file&&i.file instanceof File){if(i.type&&i.type.startsWith("image/")){const s=new FileReader;s.onload=u=>{var d;a.src=((d=u.target)==null?void 0:d.result)||""},s.readAsDataURL(i.file),e.appendChild(a)}else if(i.type&&i.type.startsWith("video/")){const s=URL.createObjectURL(i.file);e.onclick=null;const u=e.cloneNode(!1);e.parentNode&&e.parentNode.replaceChild(u,e),e=u,e.innerHTML=`
48
+ <div class="relative group h-full">
49
+ <video class="w-full h-full object-contain" controls preload="auto" muted>
50
+ <source src="${s}" type="${i.type}">
51
+ Your browser does not support the video tag.
52
+ </video>
53
+ <div class="absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity z-10 flex gap-1">
54
+ <button class="bg-red-600 bg-opacity-75 hover:bg-opacity-90 text-white p-1 rounded text-xs delete-file-btn">
55
+ ${$("removeElement",n)}
56
+ </button>
57
+ <button class="bg-gray-800 bg-opacity-75 hover:bg-opacity-90 text-white p-1 rounded text-xs change-file-btn">
58
+ Change
59
+ </button>
60
+ </div>
61
+ </div>
62
+ `;const d=e.querySelector(".change-file-btn");d&&(d.onclick=p=>{p.stopPropagation(),o!=null&&o.picker&&o.picker.click()});const h=e.querySelector(".delete-file-btn");h&&(h.onclick=p=>{var m;p.stopPropagation(),n.resourceIndex.delete(t);const v=(m=e.parentElement)==null?void 0:m.querySelector('input[type="hidden"]');v&&(v.value=""),o!=null&&o.fileUploadHandler&&(e.onclick=o.fileUploadHandler),o!=null&&o.dragHandler&&z(e,o.dragHandler),e.innerHTML=`
63
+ <div class="flex flex-col items-center justify-center h-full text-gray-400">
64
+ <svg class="w-6 h-6 mb-2" fill="currentColor" viewBox="0 0 24 24">
65
+ <path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/>
66
+ </svg>
67
+ <div class="text-sm text-center">${$("clickDragText",n)}</div>
68
+ </div>
69
+ `})}else e.innerHTML=`<div class="flex flex-col items-center justify-center h-full text-gray-400"><div class="text-2xl mb-2">\u{1F4C1}</div><div class="text-sm">${c}</div></div>`;!l&&!(i&&i.type&&i.type.startsWith("video/"))&&Se(e,n,()=>{var s;n.resourceIndex.delete(t);const u=(s=e.parentElement)==null?void 0:s.querySelector('input[type="hidden"]');u&&(u.value=""),e.innerHTML=`
70
+ <div class="flex flex-col items-center justify-center h-full text-gray-400">
71
+ <svg class="w-6 h-6 mb-2" fill="currentColor" viewBox="0 0 24 24">
72
+ <path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/>
73
+ </svg>
74
+ <div class="text-sm text-center">${$("clickDragText",n)}</div>
75
+ </div>
76
+ `})}else if(n.config.getThumbnail)try{const s=await n.config.getThumbnail(t);s?(N(e),a.src=s,e.appendChild(a)):j(e,n)}catch(s){console.error("Failed to get thumbnail:",s),e.innerHTML=`
77
+ <div class="flex flex-col items-center justify-center h-full text-gray-400">
78
+ <svg class="w-6 h-6 mb-2" fill="currentColor" viewBox="0 0 24 24">
79
+ <path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/>
80
+ </svg>
81
+ <div class="text-sm text-center">${c||"Preview unavailable"}</div>
82
+ </div>
83
+ `}else j(e,n)}async function B(e,t,n){var r,c;const l=t.resourceIndex.get(e),o=(l==null?void 0:l.name)||e.split("/").pop()||"file",a=o.toLowerCase().match(/\.psd$/),i=document.createElement("div");i.className=a?"space-y-2":"space-y-3";const s=document.createElement("div");a?s.className="bg-gray-100 rounded-lg overflow-hidden cursor-pointer hover:opacity-90 transition-opacity flex items-center p-3 max-w-sm":s.className="bg-gray-100 rounded-lg overflow-hidden cursor-pointer hover:opacity-90 transition-opacity";const u=!a&&(((r=l==null?void 0:l.type)==null?void 0:r.startsWith("image/"))||o.toLowerCase().match(/\.(jpg|jpeg|png|gif|webp)$/)),d=((c=l==null?void 0:l.type)==null?void 0:c.startsWith("video/"))||o.toLowerCase().match(/\.(mp4|webm|avi|mov)$/);if(u)if(t.config.getThumbnail)try{const m=await t.config.getThumbnail(e);m?s.innerHTML=`<img src="${m}" alt="${o}" class="w-full h-auto">`:s.innerHTML=`<div class="aspect-video flex items-center justify-center text-gray-400"><div class="text-center"><div class="text-4xl mb-2">\u{1F5BC}\uFE0F</div><div class="text-sm">${o}</div></div></div>`}catch(m){console.warn("getThumbnail failed for",e,m),s.innerHTML=`<div class="aspect-video flex items-center justify-center text-gray-400"><div class="text-center"><div class="text-4xl mb-2">\u{1F5BC}\uFE0F</div><div class="text-sm">${o}</div></div></div>`}else s.innerHTML=`<div class="aspect-video flex items-center justify-center text-gray-400"><div class="text-center"><div class="text-4xl mb-2">\u{1F5BC}\uFE0F</div><div class="text-sm">${o}</div></div></div>`;else if(d)if(t.config.getThumbnail)try{const m=await t.config.getThumbnail(e);m?s.innerHTML=`
84
+ <div class="relative group">
85
+ <video class="w-full h-auto" controls preload="auto" muted>
86
+ <source src="${m}" type="${(l==null?void 0:l.type)||"video/mp4"}">
87
+ \u0412\u0430\u0448 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u0438\u0434\u0435\u043E.
88
+ </video>
89
+ <div class="absolute inset-0 bg-black bg-opacity-20 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center pointer-events-none">
90
+ <div class="bg-white bg-opacity-90 rounded-full p-3">
91
+ <svg class="w-8 h-8 text-gray-800" fill="currentColor" viewBox="0 0 24 24">
92
+ <path d="M8 5v14l11-7z"/>
93
+ </svg>
94
+ </div>
95
+ </div>
96
+ </div>
97
+ `:s.innerHTML=`<div class="aspect-video flex items-center justify-center text-gray-400"><div class="text-center"><div class="text-4xl mb-2">\u{1F3A5}</div><div class="text-sm">${o}</div></div></div>`}catch(m){console.warn("getThumbnail failed for video",e,m),s.innerHTML=`<div class="aspect-video flex items-center justify-center text-gray-400"><div class="text-center"><div class="text-4xl mb-2">\u{1F3A5}</div><div class="text-sm">${o}</div></div></div>`}else s.innerHTML=`<div class="aspect-video flex items-center justify-center text-gray-400"><div class="text-center"><div class="text-4xl mb-2">\u{1F3A5}</div><div class="text-sm">${o}</div></div></div>`;else{const m=a?"\u{1F3A8}":"\u{1F4C1}",v=a?"PSD File":"Document";a?s.innerHTML=`
98
+ <div class="flex items-center space-x-3">
99
+ <div class="text-3xl text-gray-400">${m}</div>
100
+ <div class="flex-1 min-w-0">
101
+ <div class="text-sm font-medium text-gray-900 truncate">${o}</div>
102
+ <div class="text-xs text-gray-500">${v}</div>
103
+ </div>
104
+ </div>
105
+ `:s.innerHTML=`<div class="aspect-video flex items-center justify-center text-gray-400"><div class="text-center"><div class="text-4xl mb-2">${m}</div><div class="text-sm">${o}</div><div class="text-xs text-gray-500 mt-1">${v}</div></div></div>`}const h=document.createElement("p");h.className=a?"hidden":"text-sm font-medium text-gray-900 text-center",h.textContent=o;const p=document.createElement("button");return p.className="w-full px-3 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors",p.textContent=$("downloadButton",t),p.onclick=m=>{m.preventDefault(),m.stopPropagation(),t.config.downloadFile?t.config.downloadFile(e,o):Ne(e,o,t)},i.appendChild(s),i.appendChild(h),i.appendChild(p),i}function P(e,t,n,r){N(e);const c=!e.classList.contains("grid");if((!t||t.length===0)&&c){const a=document.createElement("div");a.className="grid grid-cols-4 gap-3 mb-3";for(let u=0;u<4;u++){const d=document.createElement("div");d.className="aspect-square bg-gray-100 border-2 border-dashed border-gray-300 rounded flex items-center justify-center cursor-pointer hover:border-gray-400 transition-colors";const h=document.createElementNS("http://www.w3.org/2000/svg","svg");h.setAttribute("class","w-12 h-12 text-gray-400"),h.setAttribute("fill","currentColor"),h.setAttribute("viewBox","0 0 24 24");const p=document.createElementNS("http://www.w3.org/2000/svg","path");p.setAttribute("d","M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"),h.appendChild(p),d.appendChild(h),d.onclick=()=>{let m=e.parentElement;for(;m&&!m.classList.contains("space-y-2");)m=m.parentElement;!m&&e.classList.contains("space-y-2")&&(m=e);const v=m==null?void 0:m.querySelector('input[type="file"]');v&&v.click()},a.appendChild(d)}const i=document.createElement("div");i.className="text-center text-xs text-gray-600";const s=document.createElement("span");s.className="underline cursor-pointer",s.textContent=$("uploadText",n),s.onclick=u=>{u.stopPropagation();let d=e.parentElement;for(;d&&!d.classList.contains("space-y-2");)d=d.parentElement;!d&&e.classList.contains("space-y-2")&&(d=e);const h=d==null?void 0:d.querySelector('input[type="file"]');h&&h.click()},i.appendChild(s),i.appendChild(document.createTextNode(` ${$("dragDropText",n)}`)),e.appendChild(a),e.appendChild(i);return}e.className="files-list grid grid-cols-4 gap-3 mt-2";const l=t?t.length:0,o=(Math.floor(l/4)+1)*4;for(let a=0;a<o;a++){const i=document.createElement("div");if(t&&a<t.length){const s=t[a],u=n.resourceIndex.get(s);if(i.className="resource-pill aspect-square bg-gray-100 rounded-lg overflow-hidden relative group border border-gray-300",i.dataset.resourceId=s,Le(i,s,u,n).catch(d=>{console.error("Failed to render thumbnail:",d),i.innerHTML=`<div class="flex flex-col items-center justify-center h-full text-gray-400">
106
+ <div class="text-2xl mb-1">\u{1F4C1}</div>
107
+ <div class="text-xs">Preview error</div>
108
+ </div>`}),r){const d=document.createElement("div");d.className="absolute inset-0 bg-black bg-opacity-50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center";const h=document.createElement("button");h.className="bg-red-600 text-white px-2 py-1 rounded text-xs",h.textContent=$("removeElement",n),h.onclick=p=>{p.stopPropagation(),r(s)},d.appendChild(h),i.appendChild(d)}}else i.className="aspect-square bg-gray-100 border-2 border-dashed border-gray-300 rounded-lg flex items-center justify-center cursor-pointer hover:border-gray-400 transition-colors",i.innerHTML='<svg class="w-12 h-12 text-gray-400" fill="currentColor" viewBox="0 0 24 24"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></svg>',i.onclick=()=>{let s=e.parentElement;for(;s&&!s.classList.contains("space-y-2");)s=s.parentElement;!s&&e.classList.contains("space-y-2")&&(s=e);const u=s==null?void 0:s.querySelector('input[type="file"]');u&&u.click()};e.appendChild(i)}}function V(e,t="w-12 h-12"){e.innerHTML=`<div class="flex flex-col items-center justify-center h-full text-gray-400">
109
+ <svg class="${t} text-red-400" fill="currentColor" viewBox="0 0 24 24">
110
+ <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
111
+ </svg>
112
+ <div class="text-xs mt-1 text-red-600">Preview error</div>
113
+ </div>`}async function Le(e,t,n,r){var c,l;if(n&&(c=n.type)!=null&&c.startsWith("image/"))if(n.file&&n.file instanceof File){const o=document.createElement("img");o.className="w-full h-full object-contain",o.alt=n.name;const a=new FileReader;a.onload=i=>{var s;o.src=((s=i.target)==null?void 0:s.result)||""},a.readAsDataURL(n.file),e.appendChild(o)}else if(r.config.getThumbnail)try{const o=await r.config.getThumbnail(t);if(o){const a=document.createElement("img");a.className="w-full h-full object-contain",a.alt=n.name,a.src=o,e.appendChild(a)}else e.innerHTML=`<div class="flex flex-col items-center justify-center h-full text-gray-400">
114
+ <svg class="w-12 h-12" fill="currentColor" viewBox="0 0 24 24">
115
+ <path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/>
116
+ </svg>
117
+ </div>`}catch(o){const a=o instanceof Error?o:new Error(String(o));r.config.onThumbnailError&&r.config.onThumbnailError(a,t),V(e)}else e.innerHTML=`<div class="flex flex-col items-center justify-center h-full text-gray-400">
118
+ <svg class="w-12 h-12" fill="currentColor" viewBox="0 0 24 24">
119
+ <path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/>
120
+ </svg>
121
+ </div>`;else if(n&&(l=n.type)!=null&&l.startsWith("video/"))if(n.file&&n.file instanceof File){const o=URL.createObjectURL(n.file);e.innerHTML=`
122
+ <div class="relative group h-full w-full">
123
+ <video class="w-full h-full object-contain" preload="metadata" muted>
124
+ <source src="${o}" type="${n.type}">
125
+ </video>
126
+ <div class="absolute inset-0 bg-black bg-opacity-30 flex items-center justify-center">
127
+ <div class="bg-white bg-opacity-90 rounded-full p-1">
128
+ <svg class="w-4 h-4 text-gray-800" fill="currentColor" viewBox="0 0 24 24">
129
+ <path d="M8 5v14l11-7z"/>
130
+ </svg>
131
+ </div>
132
+ </div>
133
+ </div>
134
+ `}else if(r.config.getThumbnail)try{const o=await r.config.getThumbnail(t);o?e.innerHTML=`
135
+ <div class="relative group h-full w-full">
136
+ <video class="w-full h-full object-contain" preload="metadata" muted>
137
+ <source src="${o}" type="${n.type}">
138
+ </video>
139
+ <div class="absolute inset-0 bg-black bg-opacity-30 flex items-center justify-center">
140
+ <div class="bg-white bg-opacity-90 rounded-full p-1">
141
+ <svg class="w-4 h-4 text-gray-800" fill="currentColor" viewBox="0 0 24 24">
142
+ <path d="M8 5v14l11-7z"/>
143
+ </svg>
144
+ </div>
145
+ </div>
146
+ </div>
147
+ `:e.innerHTML=`<div class="flex flex-col items-center justify-center h-full text-gray-400">
148
+ <svg class="w-8 h-8" fill="currentColor" viewBox="0 0 24 24">
149
+ <path d="M8 5v14l11-7z"/>
150
+ </svg>
151
+ <div class="text-xs mt-1">${(n==null?void 0:n.name)||"Video"}</div>
152
+ </div>`}catch(o){const a=o instanceof Error?o:new Error(String(o));r.config.onThumbnailError&&r.config.onThumbnailError(a,t),V(e,"w-8 h-8")}else e.innerHTML=`<div class="flex flex-col items-center justify-center h-full text-gray-400">
153
+ <svg class="w-8 h-8" fill="currentColor" viewBox="0 0 24 24">
154
+ <path d="M8 5v14l11-7z"/>
155
+ </svg>
156
+ <div class="text-xs mt-1">${(n==null?void 0:n.name)||"Video"}</div>
157
+ </div>`;else e.innerHTML=`<div class="flex flex-col items-center justify-center h-full text-gray-400">
158
+ <div class="text-2xl mb-1">\u{1F4C1}</div>
159
+ <div class="text-xs">${(n==null?void 0:n.name)||"File"}</div>
160
+ </div>`}function j(e,t){e.innerHTML=`
161
+ <div class="flex flex-col items-center justify-center h-full text-gray-400">
162
+ <svg class="w-6 h-6 mb-2" fill="currentColor" viewBox="0 0 24 24">
163
+ <path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/>
164
+ </svg>
165
+ <div class="text-sm text-center">${$("clickDragText",t)}</div>
166
+ </div>
167
+ `}async function W(e,t,n,r,c=null,l){var o,a;let i;if(r.config.uploadFile)try{if(i=await r.config.uploadFile(e),typeof i!="string")throw new Error("Upload handler must return a string resource ID")}catch(u){const d=u instanceof Error?u:new Error(String(u));throw r.config.onUploadError&&r.config.onUploadError(d,e),new Error(`File upload failed: ${d.message}`)}else throw new Error("No upload handler configured. Set uploadHandler via FormBuilder.setUploadHandler()");r.resourceIndex.set(i,{name:e.name,type:e.type,size:e.size,uploadedAt:new Date,file:e});let s=(o=t.parentElement)==null?void 0:o.querySelector('input[type="hidden"]');s||(s=document.createElement("input"),s.type="hidden",s.name=n,(a=t.parentElement)==null||a.appendChild(s)),s.value=i,O(t,i,r,{fileName:e.name,isReadonly:!1,deps:c}).catch(console.error),l&&!r.config.readonly&&l.triggerOnChange(n,i)}function z(e,t){e.addEventListener("dragover",n=>{n.preventDefault(),e.classList.add("border-blue-500","bg-blue-50")}),e.addEventListener("dragleave",n=>{n.preventDefault(),e.classList.remove("border-blue-500","bg-blue-50")}),e.addEventListener("drop",n=>{var r;n.preventDefault(),e.classList.remove("border-blue-500","bg-blue-50"),(r=n.dataTransfer)!=null&&r.files&&t(n.dataTransfer.files)})}function Se(e,t,n){const r=e.querySelector(".delete-overlay");r&&r.remove();const c=document.createElement("div");c.className="delete-overlay absolute inset-0 bg-black bg-opacity-50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center";const l=document.createElement("button");l.className="bg-red-600 text-white px-3 py-1 rounded text-sm hover:bg-red-700 transition-colors",l.textContent=$("removeElement",t),l.onclick=o=>{o.stopPropagation(),n()},c.appendChild(l),e.appendChild(c)}async function _(e,t){if(t.config.uploadFile)try{const n=await t.config.uploadFile(e);if(typeof n!="string")throw new Error("Upload handler must return a string resource ID");return n}catch(n){const r=n instanceof Error?n:new Error(String(n));throw t.config.onUploadError&&t.config.onUploadError(r,e),new Error(`File upload failed: ${r.message}`)}else throw new Error("No upload handler configured. Set uploadHandler via FormBuilder.setUploadHandler()")}async function Ne(e,t,n){try{let r=null;if(n.config.getDownloadUrl?r=n.config.getDownloadUrl(e):n.config.getThumbnail&&(r=await n.config.getThumbnail(e)),r){const c=r.startsWith("http")?r:new URL(r,window.location.href).href,l=await fetch(c);if(!l.ok)throw new Error(`HTTP error! status: ${l.status}`);const o=await l.blob();Te(o,t)}else throw new Error("No download URL available for resource")}catch(r){const c=r instanceof Error?r:new Error(String(r));throw n.config.onDownloadError&&n.config.onDownloadError(c,e,t),console.error(`File download failed for ${t}:`,c),c}}function Te(e,t){try{const n=URL.createObjectURL(e),r=document.createElement("a");r.href=n,r.download=t,r.style.display="none",document.body.appendChild(r),r.click(),document.body.removeChild(r),setTimeout(()=>{URL.revokeObjectURL(n)},100)}catch(n){throw new Error(`Blob download failed: ${n.message}`)}}function G(e,t){e.length>0&&e.forEach(n=>{var r;if(!t.resourceIndex.has(n)){const c=n.split("/").pop()||"file",l=(r=c.split(".").pop())==null?void 0:r.toLowerCase();let o="application/octet-stream";l&&(["jpg","jpeg","png","gif","webp"].includes(l)?o=`image/${l==="jpg"?"jpeg":l}`:["mp4","webm","mov","avi"].includes(l)&&(o=`video/${l==="mov"?"quicktime":l}`)),t.resourceIndex.set(n,{name:c,type:o,size:0,uploadedAt:new Date,file:void 0})}})}function Ae(e,t,n,r,c,l){var o;if(!c.resourceIndex.has(e)){const i=e.split("/").pop()||"file",s=(o=i.split(".").pop())==null?void 0:o.toLowerCase();let u="application/octet-stream";s&&(["jpg","jpeg","png","gif","webp"].includes(s)?u=`image/${s==="jpg"?"jpeg":s}`:["mp4","webm","mov","avi"].includes(s)&&(u=`video/${s==="mov"?"quicktime":s}`)),c.resourceIndex.set(e,{name:i,type:u,size:0,uploadedAt:new Date,file:void 0})}O(t,e,c,{fileName:e,isReadonly:!1,deps:l}).catch(console.error);const a=document.createElement("input");a.type="hidden",a.name=n,a.value=e,r.appendChild(a)}function Y(e,t,n,r,c,l){z(e,async o=>{const a=Array.from(o);for(const i of a){const s=await _(i,n);n.resourceIndex.set(s,{name:i.name,type:i.type,size:i.size,uploadedAt:new Date,file:void 0}),t.push(s)}r(),l&&c&&!n.config.readonly&&l.triggerOnChange(c,t)})}function J(e,t,n,r,c,l){e.onchange=async()=>{if(e.files)for(const o of Array.from(e.files)){const a=await _(o,n);n.resourceIndex.set(a,{name:o.name,type:o.type,size:o.size,uploadedAt:new Date,file:void 0}),t.push(a)}r(),e.value="",l&&c&&!n.config.readonly&&l.triggerOnChange(c,t)}}function qe(e,t,n,r){var c;const l=t.state;if(l.config.readonly){const o=t.prefill[e.key];if(o)B(o,l).then(a=>{n.appendChild(a)}).catch(a=>{console.error("Failed to render file preview:",a);const i=document.createElement("div");i.className="aspect-video bg-gray-100 rounded-lg flex items-center justify-center text-gray-500",i.innerHTML='<div class="text-center">Preview unavailable</div>',n.appendChild(i)});else{const a=document.createElement("div");a.className="aspect-video bg-gray-100 rounded-lg flex items-center justify-center text-gray-500",a.innerHTML=`<div class="text-center">${$("noFileSelected",l)}</div>`,n.appendChild(a)}}else{const o=document.createElement("div");o.className="space-y-2";const a=document.createElement("input");a.type="file",a.name=r,a.style.display="none",e.accept&&(a.accept=typeof e.accept=="string"?e.accept:((c=e.accept.extensions)==null?void 0:c.map(v=>`.${v}`).join(","))||"");const i=document.createElement("div");i.className="file-preview-container w-full aspect-square max-w-xs bg-gray-100 rounded-lg overflow-hidden relative group cursor-pointer";const s=t.prefill[e.key],u=()=>a.click(),d=v=>{if(v.length>0){const b={picker:a,fileUploadHandler:u,dragHandler:d};W(v[0],i,r,l,b,t.instance)}};s?Ae(s,i,r,o,l,{picker:a,fileUploadHandler:u,dragHandler:d}):j(i,l),i.onclick=u,z(i,d),a.onchange=()=>{if(a.files&&a.files.length>0){const v={picker:a,fileUploadHandler:u,dragHandler:d};W(a.files[0],i,r,l,v,t.instance)}},o.appendChild(i),o.appendChild(a);const h=document.createElement("p");h.className="text-xs text-gray-600 mt-2 text-center",h.innerHTML=`<span class="underline cursor-pointer">${$("uploadText",l)}</span> ${$("dragDropTextSingle",l)}`;const p=h.querySelector("span");p&&(p.onclick=()=>a.click()),o.appendChild(h);const m=document.createElement("p");m.className="text-xs text-gray-500 mt-1 text-center",m.textContent=k(e),o.appendChild(m),n.appendChild(o)}}function He(e,t,n,r){var c;const l=t.state;if(l.config.readonly){const o=document.createElement("div");o.className="space-y-4";const a=t.prefill[e.key]||[];a.length>0?a.forEach(i=>{B(i,l).then(s=>{o.appendChild(s)}).catch(s=>{console.error("Failed to render file preview:",s)})}):o.innerHTML=`<div class="aspect-video bg-gray-100 rounded-lg flex items-center justify-center text-gray-500"><div class="text-center">${$("noFilesSelected",l)}</div></div>`,n.appendChild(o)}else{let o=function(){P(u,d,l,p=>{const m=d.indexOf(p);m>-1&&d.splice(m,1),o()})};const a=document.createElement("div");a.className="space-y-2";const i=document.createElement("input");i.type="file",i.name=r,i.multiple=!0,i.style.display="none",e.accept&&(i.accept=typeof e.accept=="string"?e.accept:((c=e.accept.extensions)==null?void 0:c.map(p=>`.${p}`).join(","))||"");const s=document.createElement("div");s.className="border-2 border-dashed border-gray-300 rounded-lg p-3 hover:border-gray-400 transition-colors";const u=document.createElement("div");u.className="files-list";const d=t.prefill[e.key]||[];G(d,l),o(),Y(s,d,l,o,r,t.instance),J(i,d,l,o,r,t.instance),s.appendChild(u),a.appendChild(s),a.appendChild(i);const h=document.createElement("p");h.className="text-xs text-gray-500 mt-1 text-center",h.textContent=k(e),a.appendChild(h),n.appendChild(a)}}function Me(e,t,n,r){var c,l,o;const a=t.state,i=(c=e.minCount)!=null?c:0,s=(l=e.maxCount)!=null?l:1/0;if(a.config.readonly){const u=document.createElement("div");u.className="space-y-4";const d=t.prefill[e.key]||[];d.length>0?d.forEach(h=>{B(h,a).then(p=>{u.appendChild(p)}).catch(p=>{console.error("Failed to render file preview:",p)})}):u.innerHTML=`<div class="aspect-video bg-gray-100 rounded-lg flex items-center justify-center text-gray-500"><div class="text-center">${$("noFilesSelected",a)}</div></div>`,n.appendChild(u)}else{const u=document.createElement("div");u.className="space-y-2";const d=document.createElement("input");d.type="file",d.name=r,d.multiple=!0,d.style.display="none",e.accept&&(d.accept=typeof e.accept=="string"?e.accept:((o=e.accept.extensions)==null?void 0:o.map(v=>`.${v}`).join(","))||"");const h=document.createElement("div");h.className="files-list space-y-2",u.appendChild(d),u.appendChild(h);const p=Array.isArray(t.prefill[e.key])?[...t.prefill[e.key]]:[];G(p,a);const m=()=>{P(h,p,a,y=>{p.splice(p.indexOf(y),1),m()});const v=document.createElement("div");v.className="text-xs text-gray-500 mt-2 file-count-info";const b=`${p.length} file${p.length!==1?"s":""}`,x=i>0||s<1/0?` (${i}-${s} allowed)`:"";v.textContent=b+x;const g=u.querySelector(".file-count-info");g&&g.remove(),u.appendChild(v)};Y(h,p,a,m,r,t.instance),J(d,p,a,m,r,t.instance),m(),n.appendChild(u)}}function X(e,t,n){var r;const c=[],{scopeRoot:l,skipValidation:o,path:a}=n,i=(s,u,d)=>{var h,p;if(o)return;const m="minCount"in d&&(h=d.minCount)!=null?h:0,v="maxCount"in d&&(p=d.maxCount)!=null?p:1/0;d.required&&u.length===0&&c.push(`${s}: required`),u.length<m&&c.push(`${s}: minimum ${m} files required`),u.length>v&&c.push(`${s}: maximum ${v} files allowed`)};if("multiple"in e&&e.multiple){const s=L(a,t),u=l.querySelector(`input[type="file"][name="${s}"]`),d=u==null?void 0:u.closest(".space-y-2"),h=(d==null?void 0:d.querySelector(".files-list"))||null,p=[];return h&&h.querySelectorAll(".resource-pill").forEach(m=>{const v=m.dataset.resourceId;v&&p.push(v)}),i(t,p,e),{value:p,errors:c}}else{const s=l.querySelector(`input[name$="${t}"][type="hidden"]`),u=(r=s==null?void 0:s.value)!=null?r:"";return!o&&e.required&&u===""?(c.push(`${t}: required`),{value:null,errors:c}):{value:u||null,errors:c}}}function Z(e,t,n,r){var c;const{scopeRoot:l,state:o}=r;if("multiple"in e&&e.multiple){if(!Array.isArray(n)){console.warn(`updateFileField: Expected array for multiple file field "${t}", got ${typeof n}`);return}n.forEach(a=>{var i;if(a&&typeof a=="string"&&!o.resourceIndex.has(a)){const s=a.split("/").pop()||"file",u=(i=s.split(".").pop())==null?void 0:i.toLowerCase();let d="application/octet-stream";u&&(["jpg","jpeg","png","gif","webp"].includes(u)?d=`image/${u==="jpg"?"jpeg":u}`:["mp4","webm","mov","avi"].includes(u)&&(d=`video/${u==="mov"?"quicktime":u}`)),o.resourceIndex.set(a,{name:s,type:d,size:0,uploadedAt:new Date,file:void 0})}}),console.info(`updateFileField: Multiple file field "${t}" updated. Preview update requires re-render.`)}else{const a=l.querySelector(`input[name="${t}"][type="hidden"]`);if(!a){console.warn(`updateFileField: Hidden input not found for file field "${t}"`);return}if(a.value=n!=null?String(n):"",n&&typeof n=="string"){if(!o.resourceIndex.has(n)){const i=n.split("/").pop()||"file",s=(c=i.split(".").pop())==null?void 0:c.toLowerCase();let u="application/octet-stream";s&&(["jpg","jpeg","png","gif","webp"].includes(s)?u=`image/${s==="jpg"?"jpeg":s}`:["mp4","webm","mov","avi"].includes(s)&&(u=`video/${s==="mov"?"quicktime":s}`)),o.resourceIndex.set(n,{name:i,type:u,size:0,uploadedAt:new Date,file:void 0})}console.info(`updateFileField: File field "${t}" updated. Preview update requires re-render.`)}}}let R=null;function Be(e){R=e}function q(e,t){if(!R)throw new Error("renderElement not initialized. Import from components/index.ts");return R(e,t)}function K(e,t,n,r){var c;const l=document.createElement("div");l.className="border border-gray-200 rounded-lg p-4 bg-gray-50",l.setAttribute("data-container",r);const o=document.createElement("div");o.className="flex justify-between items-center mb-4";const a=document.createElement("div");a.className="flex-1";const i=document.createElement("div");i.className="space-y-4",l.appendChild(o),o.appendChild(a);const s={path:L(t.path,e.key),prefill:((c=t.prefill)==null?void 0:c[e.key])||{},state:t.state};e.elements.forEach(u=>{u.hidden||i.appendChild(q(u,s))}),l.appendChild(i),a.innerHTML=`<span>${e.label||e.key}</span>`,n.appendChild(l)}function Q(e,t,n,r){var c,l,o;const a=t.state,i=document.createElement("div");i.className="border border-gray-200 rounded-lg p-4 bg-gray-50";const s=document.createElement("div");s.className="flex justify-between items-center mb-4";const u=document.createElement("div");u.className="flex-1";const d=document.createElement("div");d.className="flex gap-2";const h=document.createElement("div");h.className="space-y-4",i.appendChild(s),s.appendChild(u),a.config.readonly||s.appendChild(d);const p=(c=e.minCount)!=null?c:0,m=(l=e.maxCount)!=null?l:1/0,v=Array.isArray((o=t.prefill)==null?void 0:o[e.key])?t.prefill[e.key]:null,b=()=>h.querySelectorAll(":scope > .containerItem").length,x=()=>{const y=document.createElement("button");return y.type="button",y.className="px-3 py-1.5 bg-blue-600 text-white text-sm rounded-lg hover:bg-blue-700 transition-colors",y.textContent=$("addElement",a),y.onclick=()=>{if(b()<m){const f=b(),C={state:t.state,path:L(t.path,`${e.key}[${f}]`),prefill:{}},E=document.createElement("div");if(E.className="containerItem border border-gray-300 rounded-lg p-4 bg-white",E.setAttribute("data-container-item",`${e.key}[${f}]`),e.elements.forEach(w=>{w.hidden||E.appendChild(q(w,C))}),!a.config.readonly){const w=document.createElement("button");w.type="button",w.className="absolute top-2 right-2 w-6 h-6 bg-red-500 text-white rounded-full text-xs hover:bg-red-600 transition-colors",w.textContent="\xD7",w.onclick=()=>{E.remove(),g()},E.style.position="relative",E.appendChild(w)}h.appendChild(E),g()}},y},g=()=>{const y=b(),f=d.querySelector("button");f&&(f.disabled=y>=m,f.style.opacity=y>=m?"0.5":"1"),u.innerHTML=`<span>${e.label||e.key}</span> <span class="text-sm text-gray-500">(${y}/${m===1/0?"\u221E":m})</span>`};if(a.config.readonly||d.appendChild(x()),v&&Array.isArray(v)&&v.forEach((y,f)=>{const C={state:t.state,path:L(t.path,`${e.key}[${f}]`),prefill:y||{}},E=document.createElement("div");if(E.className="containerItem border border-gray-300 rounded-lg p-4 bg-white",E.setAttribute("data-container-item",`${e.key}[${f}]`),e.elements.forEach(w=>{w.hidden||E.appendChild(q(w,C))}),!a.config.readonly){const w=document.createElement("button");w.type="button",w.className="absolute top-2 right-2 w-6 h-6 bg-red-500 text-white rounded-full text-xs hover:bg-red-600 transition-colors",w.textContent="\xD7",w.onclick=()=>{E.remove(),g()},E.style.position="relative",E.appendChild(w)}h.appendChild(E)}),!a.config.readonly)for(;b()<p;){const y=b(),f={state:t.state,path:L(t.path,`${e.key}[${y}]`),prefill:{}},C=document.createElement("div");C.className="containerItem border border-gray-300 rounded-lg p-4 bg-white",C.setAttribute("data-container-item",`${e.key}[${y}]`),e.elements.forEach(w=>{w.hidden||C.appendChild(q(w,f))});const E=document.createElement("button");E.type="button",E.className="absolute top-2 right-2 w-6 h-6 bg-red-500 text-white rounded-full text-xs hover:bg-red-600 transition-colors",E.textContent="\xD7",E.onclick=()=>{b()>p&&(C.remove(),g())},C.style.position="relative",C.appendChild(E),h.appendChild(C)}i.appendChild(h),g(),n.appendChild(i)}let D=null;function je(e){D=e}function ee(e,t,n){if(!D)throw new Error("validateElement not initialized. Should be set from FormBuilderInstance");return D(e,t,n)}function te(e,t,n){const r=[],{scopeRoot:c,skipValidation:l,path:o}=n;if(!("elements"in e))return{value:null,errors:r};const a=(i,s,u)=>{var d,h;if(l)return;const p="minCount"in u&&(d=u.minCount)!=null?d:0,m="maxCount"in u&&(h=u.maxCount)!=null?h:1/0;u.required&&s.length===0&&r.push(`${i}: required`),s.length<p&&r.push(`${i}: minimum ${p} items required`),s.length>m&&r.push(`${i}: maximum ${m} items allowed`)};if("multiple"in e&&e.multiple){const i=[],s=c.querySelectorAll("[data-container-item]"),u=Array.from(s).filter(d=>{const h=d.getAttribute("data-container-item");return h==null?void 0:h.startsWith(`${t}[`)}).length;for(let d=0;d<u;d++){const h={},p=c.querySelector(`[data-container-item="${t}[${d}]"]`)||c;e.elements.forEach(m=>{if(m.hidden||m.type==="hidden")h[m.key]=m.default!==void 0?m.default:null;else{const v=`${t}[${d}].${m.key}`;h[m.key]=ee({...m,key:v},{path:o},p)}}),i.push(h)}return a(t,i,e),{value:i,errors:r}}else{const i={},s=c.querySelector(`[data-container="${t}"]`)||c;return e.elements.forEach(u=>{if(u.hidden||u.type==="hidden")i[u.key]=u.default!==void 0?u.default:null;else{const d=`${t}.${u.key}`;i[u.key]=ee({...u,key:d},{path:o},s)}}),{value:i,errors:r}}}function ne(e,t,n,r){const{instance:c,scopeRoot:l}=r;if("elements"in e)if("multiple"in e&&e.multiple){if(!Array.isArray(n)){console.warn(`updateContainerField: Expected array for multiple container field "${t}", got ${typeof n}`);return}n.forEach((a,i)=>{A(a)&&e.elements.forEach(s=>{const u=s.key,d=`${t}[${i}].${u}`,h=a[u];h!==void 0&&c.updateField(d,h)})});const o=l.querySelectorAll(`[data-container-item^="${t}["]`);n.length!==o.length&&console.warn(`updateContainerField: Multiple container field "${t}" item count mismatch. Consider re-rendering for add/remove.`)}else{if(!A(n)){console.warn(`updateContainerField: Expected object for container field "${t}", got ${typeof n}`);return}e.elements.forEach(o=>{const a=o.key,i=`${t}.${a}`,s=n[a];s!==void 0&&c.updateField(i,s)})}}function ze(e,t,n,r){var c,l;typeof console!="undefined"&&console.warn&&console.warn(`[Form Builder] The "group" field type is deprecated and will be removed in a future version. Please use type: "container" with multiple: true instead. Field key: "${e.key}"`);const o={key:e.key,label:e.label,description:e.description,hint:e.hint,required:e.required,hidden:e.hidden,default:e.default,actions:e.actions,elements:e.elements,multiple:!!(e.repeat&&A(e.repeat)),minCount:(c=e.repeat)==null?void 0:c.min,maxCount:(l=e.repeat)==null?void 0:l.max};o.multiple?Q(o,t,n):K(o,t,n,r)}function le(e){var t,n;const r=e;return{type:"container",key:r.key,label:r.label,description:r.description,hint:r.hint,required:r.required,hidden:r.hidden,default:r.default,actions:r.actions,elements:r.elements,multiple:!!(r.repeat&&A(r.repeat)),minCount:(t=r.repeat)==null?void 0:t.min,maxCount:(n=r.repeat)==null?void 0:n.max}}function Re(e,t,n){typeof console!="undefined"&&console.warn&&console.warn(`[Form Builder] The "group" field type is deprecated. Please use type: "container" instead. Field key: "${t}"`);const r=le(e);return te(r,t,n)}function De(e,t,n,r){typeof console!="undefined"&&console.warn&&console.warn(`[Form Builder] The "group" field type is deprecated. Please use type: "container" instead. Field path: "${t}"`);const c=le(e);return ne(c,t,n,r)}function Ie(e,t){const n=document.getElementById(e);if(!n)return;const r=!n.classList.contains("hidden");if(document.querySelectorAll('[id^="tooltip-"]').forEach(u=>{u.classList.add("hidden")}),r)return;const c=t.getBoundingClientRect(),l=window.innerWidth,o=window.innerHeight;n&&n.parentElement!==document.body&&document.body.appendChild(n),n.style.visibility="hidden",n.style.position="fixed",n.classList.remove("hidden");const a=n.getBoundingClientRect();n.classList.add("hidden"),n.style.visibility="visible";let i=c.left,s=c.bottom+5;i+a.width>l&&(i=c.right-a.width),s+a.height>o&&(s=c.top-a.height-5),i<10&&(i=10),s<10&&(s=c.bottom+5),n.style.left=`${i}px`,n.style.top=`${s}px`,n.classList.remove("hidden"),setTimeout(()=>{n.classList.add("hidden")},25e3)}typeof document!="undefined"&&document.addEventListener("click",e=>{const t=e.target,n=t.closest("button")&&t.closest("button").onclick,r=t.closest('[id^="tooltip-"]');!n&&!r&&document.querySelectorAll('[id^="tooltip-"]').forEach(c=>{c.classList.add("hidden")})});function oe(e,t){const n=document.createElement("div");n.className="mb-6 fb-field-wrapper";const r=document.createElement("div");r.className="flex items-center mb-2";const c=document.createElement("label");if(c.className="text-sm font-medium text-gray-900",c.textContent=e.label||e.key,e.required){const o=document.createElement("span");o.className="text-red-500 ml-1",o.textContent="*",c.appendChild(o)}if(r.appendChild(c),e.description||e.hint){const o=document.createElement("button");o.type="button",o.className="ml-2 text-gray-400 hover:text-gray-600",o.innerHTML='<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/></svg>';const a=`tooltip-${e.key}-${Math.random().toString(36).substr(2,9)}`,i=document.createElement("div");i.id=a,i.className="hidden absolute z-50 bg-gray-200 text-gray-900 text-sm rounded-lg p-3 max-w-sm border border-gray-300 shadow-lg",i.style.position="fixed",i.textContent=e.description||e.hint||"Field information",document.body.appendChild(i),o.onclick=s=>{s.preventDefault(),s.stopPropagation(),Ie(a,o)},r.appendChild(o)}n.appendChild(r);const l=L(t.path,e.key);switch(e.type){case"text":"multiple"in e&&e.multiple?fe(e,t,n,l):pe(e,t,n,l);break;case"textarea":"multiple"in e&&e.multiple?ve(e,t,n,l):he(e,t,n,l);break;case"number":"multiple"in e&&e.multiple?xe(e,t,n,l):be(e,t,n,l);break;case"select":"multiple"in e&&e.multiple?$e(e,t,n,l):we(e,t,n,l);break;case"file":"multiple"in e&&e.multiple?Me(e,t,n,l):qe(e,t,n,l);break;case"files":He(e,t,n,l);break;case"group":ze(e,t,n,l);break;case"container":"multiple"in e&&e.multiple?Q(e,t,n):K(e,t,n,l);break;default:{const o=document.createElement("div");o.className="text-red-500 text-sm",o.textContent=`Unsupported field type: ${e.type}`,n.appendChild(o)}}return n}Be(oe);const Ue={uploadFile:null,downloadFile:null,getThumbnail:null,getDownloadUrl:null,actionHandler:null,onChange:null,onFieldChange:null,onThumbnailError:null,onUploadError:null,onDownloadError:null,debounceMs:300,enableFilePreview:!0,maxPreviewSize:"200px",readonly:!1,locale:"en",translations:{en:{addElement:"Add Element",removeElement:"Remove",uploadText:"Upload",dragDropText:"or drag and drop files",dragDropTextSingle:"or drag and drop file",clickDragText:"Click or drag file",noFileSelected:"No file selected",noFilesSelected:"No files selected",downloadButton:"Download"},ru:{addElement:"\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u044D\u043B\u0435\u043C\u0435\u043D\u0442",removeElement:"\u0423\u0434\u0430\u043B\u0438\u0442\u044C",uploadText:"\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0435",dragDropText:"\u0438\u043B\u0438 \u043F\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0442\u0435 \u0444\u0430\u0439\u043B\u044B",dragDropTextSingle:"\u0438\u043B\u0438 \u043F\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0442\u0435 \u0444\u0430\u0439\u043B",clickDragText:"\u041D\u0430\u0436\u043C\u0438\u0442\u0435 \u0438\u043B\u0438 \u043F\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0442\u0435 \u0444\u0430\u0439\u043B",noFileSelected:"\u0424\u0430\u0439\u043B \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D",noFilesSelected:"\u041D\u0435\u0442 \u0444\u0430\u0439\u043B\u043E\u0432",downloadButton:"\u0421\u043A\u0430\u0447\u0430\u0442\u044C"}},theme:{}};function Oe(e){return{schema:null,formRoot:null,resourceIndex:new Map,externalActions:null,version:"1.0.0",config:{...Ue,...e},debounceTimer:null}}function Pe(){const e=Date.now().toString(36),t=Math.random().toString(36).substring(2,9);return`inst-${e}-${t}`}const T={primaryColor:"#3b82f6",primaryHoverColor:"#2563eb",errorColor:"#ef4444",errorHoverColor:"#dc2626",successColor:"#10b981",borderColor:"#d1d5db",borderHoverColor:"#9ca3af",borderFocusColor:"#3b82f6",backgroundColor:"#ffffff",backgroundHoverColor:"#f9fafb",backgroundReadonlyColor:"#f3f4f6",textColor:"#1f2937",textSecondaryColor:"#6b7280",textPlaceholderColor:"#9ca3af",textDisabledColor:"#d1d5db",buttonBgColor:"#3b82f6",buttonTextColor:"#ffffff",buttonBorderColor:"#2563eb",buttonHoverBgColor:"#2563eb",buttonHoverBorderColor:"#1d4ed8",actionBgColor:"#ffffff",actionTextColor:"#374151",actionBorderColor:"#e5e7eb",actionHoverBgColor:"#f9fafb",actionHoverBorderColor:"#d1d5db",fileUploadBgColor:"#f3f4f6",fileUploadBorderColor:"#d1d5db",fileUploadTextColor:"#9ca3af",fileUploadHoverBorderColor:"#3b82f6",inputPaddingX:"0.75rem",inputPaddingY:"0.5rem",borderRadius:"0.5rem",borderWidth:"1px",fontSize:"0.875rem",fontSizeSmall:"0.75rem",fontSizeExtraSmall:"0.625rem",fontFamily:'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',fontWeightNormal:"400",fontWeightMedium:"500",focusRingWidth:"2px",focusRingColor:"#3b82f6",focusRingOpacity:"0.5",transitionDuration:"200ms"};function Ve(e){const t={...T,...e},n=[];return Object.entries(t).forEach(([r,c])=>{const l=r.replace(/([A-Z])/g,"-$1").toLowerCase();n.push(` --fb-${l}: ${c};`)}),n.join(`
168
+ `)}function We(e,t){const n=Ve(t);let r=e.querySelector("style[data-fb-theme]");r||(r=document.createElement("style"),r.setAttribute("data-fb-theme","true"),e.appendChild(r)),r.textContent=`
169
+ [data-fb-root="true"] {
170
+ ${n}
171
+ }
172
+ `}const _e={default:T,dark:{...T,primaryColor:"#60a5fa",primaryHoverColor:"#3b82f6",borderColor:"#4b5563",borderHoverColor:"#6b7280",borderFocusColor:"#60a5fa",backgroundColor:"#1f2937",backgroundHoverColor:"#374151",backgroundReadonlyColor:"#111827",textColor:"#f9fafb",textSecondaryColor:"#9ca3af",textPlaceholderColor:"#6b7280",fileUploadBgColor:"#374151",fileUploadBorderColor:"#4b5563",fileUploadTextColor:"#9ca3af"},klein:{...T,primaryColor:"#0066cc",primaryHoverColor:"#0052a3",errorColor:"#d32f2f",errorHoverColor:"#c62828",successColor:"#388e3c",borderColor:"#e0e0e0",borderHoverColor:"#bdbdbd",borderFocusColor:"#0066cc",borderRadius:"4px",fontSize:"16px",fontSizeSmall:"14px",fontFamily:'"Roboto", "Helvetica", "Arial", sans-serif'}};function re(e,t=!1){e.style.cssText=`
173
+ background-color: var(--fb-action-bg-color);
174
+ color: var(--fb-action-text-color);
175
+ border: var(--fb-border-width) solid var(--fb-action-border-color);
176
+ padding: ${t?"0.5rem 1rem":"0.5rem 0.75rem"};
177
+ font-size: var(--fb-font-size);
178
+ font-weight: var(--fb-font-weight-medium);
179
+ border-radius: var(--fb-border-radius);
180
+ transition: all var(--fb-transition-duration);
181
+ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
182
+ `,e.addEventListener("mouseenter",()=>{e.style.backgroundColor="var(--fb-action-hover-bg-color)",e.style.borderColor="var(--fb-action-hover-border-color)"}),e.addEventListener("mouseleave",()=>{e.style.backgroundColor="var(--fb-action-bg-color)",e.style.borderColor="var(--fb-action-border-color)"})}const Ge={text:{validate:I,update:U},textarea:{validate:ge,update:ye},number:{validate:Ce,update:Ee},select:{validate:ke,update:Fe},file:{validate:X,update:Z},files:{validate:X,update:Z},container:{validate:te,update:ne},group:{validate:Re,update:De}};function ae(e){return Ge[e]||null}function Ye(e,t,n){const r=ae(e.type);return r&&r.validate?r.validate(e,t,n):null}function Je(e,t,n,r){const c=ae(e.type);return c&&c.update?(c.update(e,t,n,r),!0):!1}class H{constructor(t){this.instanceId=Pe(),this.state=Oe(t)}getInstanceId(){return this.instanceId}getState(){return this.state}setFormRoot(t){this.state.formRoot=t}configure(t){Object.assign(this.state.config,t)}setUploadHandler(t){this.state.config.uploadFile=t}setDownloadHandler(t){this.state.config.downloadFile=t}setThumbnailHandler(t){this.state.config.getThumbnail=t}setActionHandler(t){this.state.config.actionHandler=t}setMode(t){this.state.config.readonly=t==="readonly"}setLocale(t){this.state.config.translations[t]&&(this.state.config.locale=t)}triggerOnChange(t,n){this.state.config.readonly||(this.state.debounceTimer!==null&&clearTimeout(this.state.debounceTimer),this.state.debounceTimer=setTimeout(()=>{const r=this.validateForm(!0);this.state.config.onChange&&this.state.config.onChange(r),this.state.config.onFieldChange&&t!==void 0&&n!==void 0&&this.state.config.onFieldChange(t,n,r),this.state.debounceTimer=null},this.state.config.debounceMs))}registerAction(t){if(!t||!t.value)throw new Error("Action must have a value property");this.state.externalActions||(this.state.externalActions=[]);const n=this.state.externalActions.findIndex(r=>r.value===t.value&&r.related_field===t.related_field);n>=0?this.state.externalActions[n]=t:this.state.externalActions.push(t)}findFormElementByFieldPath(t){if(!this.state.formRoot)return null;if(!this.state.config.readonly){let c=this.state.formRoot.querySelector(`[name="${t}"]`);if(c)return c;const l=[t,t.replace(/\[(\d+)\]/g,"[$1]"),t.replace(/\./g,"[")+"]".repeat((t.match(/\./g)||[]).length)];for(const o of l)if(c=this.state.formRoot.querySelector(`[name="${o}"]`),c)return c}const n=this.findSchemaElement(t);if(!n)return null;const r=this.state.formRoot.querySelectorAll(".fb-field-wrapper");for(const c of r){const l=n.label||n.key,o=c.querySelector("label");if(o&&(o.textContent===l||o.textContent===`${l}*`)){let a=c.querySelector(".field-placeholder");return a||(a=document.createElement("div"),a.className="field-placeholder",a.style.display="none",c.appendChild(a)),a}}return null}findSchemaElement(t){if(!this.state.schema||!this.state.schema.elements)return null;let n=this.state.schema.elements,r=null;const c=t.replace(/\[\d+\]/g,"").split(".").filter(Boolean);for(const l of c){if(r=n.find(o=>o.key===l)||null,!r)return null;"elements"in r&&r.elements&&(n=r.elements)}return r}resolveActionLabel(t,n,r,c=!1){if(r&&"actions"in r&&r.actions){const l=r.actions.find(o=>o.key===t);if(l&&l.label)return l.label}if(c&&this.state.schema&&"actions"in this.state.schema&&this.state.schema.actions){const l=this.state.schema.actions.find(o=>o.key===t);if(l&&l.label)return l.label}return n||t}renderFormLevelActions(t,n=[]){if(!this.state.formRoot)return;const r=this.state.formRoot.querySelector(".form-level-actions-container");r&&r.remove();const c=document.createElement("div");c.className="form-level-actions-container mt-6 pt-4 flex flex-wrap gap-3 justify-center",c.style.cssText=`
183
+ border-top: var(--fb-border-width) solid var(--fb-border-color);
184
+ `,t.forEach(l=>{const o=document.createElement("button");o.type="button",re(o,!0);const a=n.includes(l),i=this.resolveActionLabel(l.key,l.label,null,a);o.textContent=i,o.addEventListener("click",s=>{s.preventDefault(),s.stopPropagation(),this.state.config.actionHandler&&typeof this.state.config.actionHandler=="function"&&this.state.config.actionHandler(l.value,l.key,null)}),c.appendChild(o)}),this.state.formRoot.appendChild(c)}renderExternalActions(){if(!this.state.externalActions||!Array.isArray(this.state.externalActions))return;const t=new Map,n=[],r=[];this.state.externalActions.forEach(l=>{!l.key||!l.value||(l.related_field?(t.has(l.related_field)||t.set(l.related_field,[]),t.get(l.related_field).push(l)):n.push(l))}),t.forEach((l,o)=>{const a=this.findFormElementByFieldPath(o);if(!a){console.warn(`External action: Could not find form element for field "${o}", treating as form-level actions`),r.push(...l);return}let i=a.closest(".fb-field-wrapper");if(i||(i=a.parentElement),!i){console.warn(`External action: Could not find wrapper for field "${o}"`);return}const s=i.querySelector(".external-actions-container");s&&s.remove();const u=document.createElement("div");u.className="external-actions-container mt-3 flex flex-wrap gap-2";const d=this.findSchemaElement(o);l.forEach(h=>{const p=document.createElement("button");p.type="button",re(p,!1);const m=this.resolveActionLabel(h.key,h.label,d);p.textContent=m,p.addEventListener("click",v=>{v.preventDefault(),v.stopPropagation(),this.state.config.actionHandler&&typeof this.state.config.actionHandler=="function"&&this.state.config.actionHandler(h.value,h.key,h.related_field)}),u.appendChild(p)}),i.appendChild(u)});const c=[...n,...r];c.length>0&&this.renderFormLevelActions(c,n)}renderForm(t,n,r,c){const l=M(n);if(l.length>0){console.error("Schema validation errors:",l);return}this.state.formRoot=t,this.state.schema=n,this.state.externalActions=c||null,N(t),t.setAttribute("data-fb-root","true"),We(t,this.state.config.theme);const o=document.createElement("div");o.className="space-y-6",n.elements.forEach(a=>{if(a.hidden)return;const i=oe(a,{path:"",prefill:r||{},state:this.state,instance:this});o.appendChild(i)}),t.appendChild(o),this.state.config.readonly&&this.state.externalActions&&Array.isArray(this.state.externalActions)&&this.renderExternalActions()}validateForm(t=!1){if(!this.state.schema||!this.state.formRoot)return{valid:!0,errors:[],data:{}};const n=[],r={},c=(l,o,a=null)=>{const i=l.key,s={scopeRoot:a||this.state.formRoot,state:this.state,instance:this,path:o.path,skipValidation:t},u=Ye(l,i,s);return u!==null?(n.push(...u.errors),u.value):(console.warn(`Unknown field type "${l.type}" for key "${i}"`),null)};return je(c),this.state.schema.elements.forEach(l=>{l.hidden?r[l.key]=l.default!==void 0?l.default:null:r[l.key]=c(l,{path:""})}),{valid:n.length===0,errors:n,data:r}}getFormData(){return this.validateForm(!1)}submitForm(){const t=this.validateForm(!1);return t.valid&&typeof window!="undefined"&&window.parent&&window.parent.postMessage({type:"formSubmit",data:t.data,schema:this.state.schema},"*"),t}saveDraft(){const t=this.validateForm(!0);return typeof window!="undefined"&&window.parent&&window.parent.postMessage({type:"formDraft",data:t.data,schema:this.state.schema},"*"),t}clearForm(){if(!this.state.schema||!this.state.formRoot){console.warn("clearForm: Form not initialized. Call renderForm() first.");return}const t=this.state.schema,n=this.state.formRoot,r=this.buildHiddenFieldsData(t.elements);this.renderForm(n,t,r)}buildHiddenFieldsData(t,n=""){const r={};for(const c of t){const l=c.key,o=n?`${n}.${l}`:l;if(c.hidden&&c.default!==void 0&&(r[o]=c.default),c.type==="container"||c.type==="group"){const a=c,i=this.buildHiddenFieldsData(a.elements,o);Object.assign(r,i)}}return r}setFormData(t){if(!this.state.schema||!this.state.formRoot){console.warn("setFormData: Form not initialized. Call renderForm() first.");return}for(const n in t)this.updateField(n,t[n])}updateField(t,n){if(!this.state.schema||!this.state.formRoot){console.warn("updateField: Form not initialized. Call renderForm() first.");return}const r=this.findSchemaElement(t);if(!r){console.warn(`updateField: Schema element not found for path "${t}"`);return}const c=this.findFormElementByFieldPath(t);if(!c){console.warn(`updateField: DOM element not found for path "${t}"`);return}this.updateFieldValue(c,r,t,n),(this.state.config.onChange||this.state.config.onFieldChange)&&this.triggerOnChange(t,n)}updateFieldValue(t,n,r,c){const l={scopeRoot:this.state.formRoot,state:this.state,instance:this,path:""};Je(n,r,c,l)||console.warn(`updateField: No updater found for field type "${n.type}" at path "${r}"`)}destroy(){this.state.debounceTimer!==null&&(clearTimeout(this.state.debounceTimer),this.state.debounceTimer=null),this.state.resourceIndex.clear(),this.state.formRoot&&N(this.state.formRoot),this.state.formRoot=null,this.state.schema=null,this.state.externalActions=null}}function ie(e){return new H(e)}return typeof window!="undefined"&&(window.FormBuilder=H,window.createFormBuilder=ie,window.validateSchema=M),F.FormBuilderInstance=H,F.createFormBuilder=ie,F.default=H,F.defaultTheme=T,F.exampleThemes=_e,F.validateSchema=M,Object.defineProperty(F,"__esModule",{value:!0}),F})({});
@@ -1521,6 +1521,14 @@ function renderResourcePills(container, rids, state, onRemove) {
1521
1521
  container.appendChild(slot);
1522
1522
  }
1523
1523
  }
1524
+ function renderThumbnailError(slot, iconSize = "w-12 h-12") {
1525
+ slot.innerHTML = `<div class="flex flex-col items-center justify-center h-full text-gray-400">
1526
+ <svg class="${iconSize} text-red-400" fill="currentColor" viewBox="0 0 24 24">
1527
+ <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
1528
+ </svg>
1529
+ <div class="text-xs mt-1 text-red-600">Preview error</div>
1530
+ </div>`;
1531
+ }
1524
1532
  async function renderThumbnailForResource(slot, rid, meta, state) {
1525
1533
  var _a, _b;
1526
1534
  if (meta && ((_a = meta.type) == null ? void 0 : _a.startsWith("image/"))) {
@@ -1536,19 +1544,27 @@ async function renderThumbnailForResource(slot, rid, meta, state) {
1536
1544
  reader.readAsDataURL(meta.file);
1537
1545
  slot.appendChild(img);
1538
1546
  } else if (state.config.getThumbnail) {
1539
- const url = await state.config.getThumbnail(rid);
1540
- if (url) {
1541
- const img = document.createElement("img");
1542
- img.className = "w-full h-full object-contain";
1543
- img.alt = meta.name;
1544
- img.src = url;
1545
- slot.appendChild(img);
1546
- } else {
1547
- slot.innerHTML = `<div class="flex flex-col items-center justify-center h-full text-gray-400">
1548
- <svg class="w-12 h-12" fill="currentColor" viewBox="0 0 24 24">
1549
- <path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/>
1550
- </svg>
1551
- </div>`;
1547
+ try {
1548
+ const url = await state.config.getThumbnail(rid);
1549
+ if (url) {
1550
+ const img = document.createElement("img");
1551
+ img.className = "w-full h-full object-contain";
1552
+ img.alt = meta.name;
1553
+ img.src = url;
1554
+ slot.appendChild(img);
1555
+ } else {
1556
+ slot.innerHTML = `<div class="flex flex-col items-center justify-center h-full text-gray-400">
1557
+ <svg class="w-12 h-12" fill="currentColor" viewBox="0 0 24 24">
1558
+ <path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/>
1559
+ </svg>
1560
+ </div>`;
1561
+ }
1562
+ } catch (error) {
1563
+ const err = error instanceof Error ? error : new Error(String(error));
1564
+ if (state.config.onThumbnailError) {
1565
+ state.config.onThumbnailError(err, rid);
1566
+ }
1567
+ renderThumbnailError(slot);
1552
1568
  }
1553
1569
  } else {
1554
1570
  slot.innerHTML = `<div class="flex flex-col items-center justify-center h-full text-gray-400">
@@ -1575,29 +1591,37 @@ async function renderThumbnailForResource(slot, rid, meta, state) {
1575
1591
  </div>
1576
1592
  `;
1577
1593
  } else if (state.config.getThumbnail) {
1578
- const videoUrl = await state.config.getThumbnail(rid);
1579
- if (videoUrl) {
1580
- slot.innerHTML = `
1581
- <div class="relative group h-full w-full">
1582
- <video class="w-full h-full object-contain" preload="metadata" muted>
1583
- <source src="${videoUrl}" type="${meta.type}">
1584
- </video>
1585
- <div class="absolute inset-0 bg-black bg-opacity-30 flex items-center justify-center">
1586
- <div class="bg-white bg-opacity-90 rounded-full p-1">
1587
- <svg class="w-4 h-4 text-gray-800" fill="currentColor" viewBox="0 0 24 24">
1588
- <path d="M8 5v14l11-7z"/>
1589
- </svg>
1594
+ try {
1595
+ const videoUrl = await state.config.getThumbnail(rid);
1596
+ if (videoUrl) {
1597
+ slot.innerHTML = `
1598
+ <div class="relative group h-full w-full">
1599
+ <video class="w-full h-full object-contain" preload="metadata" muted>
1600
+ <source src="${videoUrl}" type="${meta.type}">
1601
+ </video>
1602
+ <div class="absolute inset-0 bg-black bg-opacity-30 flex items-center justify-center">
1603
+ <div class="bg-white bg-opacity-90 rounded-full p-1">
1604
+ <svg class="w-4 h-4 text-gray-800" fill="currentColor" viewBox="0 0 24 24">
1605
+ <path d="M8 5v14l11-7z"/>
1606
+ </svg>
1607
+ </div>
1590
1608
  </div>
1591
1609
  </div>
1592
- </div>
1593
- `;
1594
- } else {
1595
- slot.innerHTML = `<div class="flex flex-col items-center justify-center h-full text-gray-400">
1596
- <svg class="w-8 h-8" fill="currentColor" viewBox="0 0 24 24">
1597
- <path d="M8 5v14l11-7z"/>
1598
- </svg>
1599
- <div class="text-xs mt-1">${(meta == null ? void 0 : meta.name) || "Video"}</div>
1600
- </div>`;
1610
+ `;
1611
+ } else {
1612
+ slot.innerHTML = `<div class="flex flex-col items-center justify-center h-full text-gray-400">
1613
+ <svg class="w-8 h-8" fill="currentColor" viewBox="0 0 24 24">
1614
+ <path d="M8 5v14l11-7z"/>
1615
+ </svg>
1616
+ <div class="text-xs mt-1">${(meta == null ? void 0 : meta.name) || "Video"}</div>
1617
+ </div>`;
1618
+ }
1619
+ } catch (error) {
1620
+ const err = error instanceof Error ? error : new Error(String(error));
1621
+ if (state.config.onThumbnailError) {
1622
+ state.config.onThumbnailError(err, rid);
1623
+ }
1624
+ renderThumbnailError(slot, "w-8 h-8");
1601
1625
  }
1602
1626
  } else {
1603
1627
  slot.innerHTML = `<div class="flex flex-col items-center justify-center h-full text-gray-400">
@@ -1634,7 +1658,11 @@ async function handleFileSelect(file, container, fieldName, state, deps = null,
1634
1658
  throw new Error("Upload handler must return a string resource ID");
1635
1659
  }
1636
1660
  } catch (error) {
1637
- throw new Error(`File upload failed: ${error.message}`);
1661
+ const err = error instanceof Error ? error : new Error(String(error));
1662
+ if (state.config.onUploadError) {
1663
+ state.config.onUploadError(err, file);
1664
+ }
1665
+ throw new Error(`File upload failed: ${err.message}`);
1638
1666
  }
1639
1667
  } else {
1640
1668
  throw new Error(
@@ -1712,7 +1740,11 @@ async function uploadSingleFile(file, state) {
1712
1740
  }
1713
1741
  return rid;
1714
1742
  } catch (error) {
1715
- throw new Error(`File upload failed: ${error.message}`);
1743
+ const err = error instanceof Error ? error : new Error(String(error));
1744
+ if (state.config.onUploadError) {
1745
+ state.config.onUploadError(err, file);
1746
+ }
1747
+ throw new Error(`File upload failed: ${err.message}`);
1716
1748
  }
1717
1749
  } else {
1718
1750
  throw new Error(
@@ -1721,26 +1753,31 @@ async function uploadSingleFile(file, state) {
1721
1753
  }
1722
1754
  }
1723
1755
  async function forceDownload(resourceId, fileName, state) {
1724
- let fileUrl = null;
1725
- if (state.config.getDownloadUrl) {
1726
- fileUrl = state.config.getDownloadUrl(resourceId);
1727
- } else if (state.config.getThumbnail) {
1728
- fileUrl = await state.config.getThumbnail(resourceId);
1729
- }
1730
- if (fileUrl) {
1731
- const finalUrl = fileUrl.startsWith("http") ? fileUrl : new URL(fileUrl, window.location.href).href;
1732
- fetch(finalUrl).then((response) => {
1756
+ try {
1757
+ let fileUrl = null;
1758
+ if (state.config.getDownloadUrl) {
1759
+ fileUrl = state.config.getDownloadUrl(resourceId);
1760
+ } else if (state.config.getThumbnail) {
1761
+ fileUrl = await state.config.getThumbnail(resourceId);
1762
+ }
1763
+ if (fileUrl) {
1764
+ const finalUrl = fileUrl.startsWith("http") ? fileUrl : new URL(fileUrl, window.location.href).href;
1765
+ const response = await fetch(finalUrl);
1733
1766
  if (!response.ok) {
1734
1767
  throw new Error(`HTTP error! status: ${response.status}`);
1735
1768
  }
1736
- return response.blob();
1737
- }).then((blob) => {
1769
+ const blob = await response.blob();
1738
1770
  downloadBlob(blob, fileName);
1739
- }).catch((error) => {
1740
- throw new Error(`File download failed: ${error.message}`);
1741
- });
1742
- } else {
1743
- console.warn("No download URL available for resource:", resourceId);
1771
+ } else {
1772
+ throw new Error("No download URL available for resource");
1773
+ }
1774
+ } catch (error) {
1775
+ const err = error instanceof Error ? error : new Error(String(error));
1776
+ if (state.config.onDownloadError) {
1777
+ state.config.onDownloadError(err, resourceId, fileName);
1778
+ }
1779
+ console.error(`File download failed for ${fileName}:`, err);
1780
+ throw err;
1744
1781
  }
1745
1782
  }
1746
1783
  function downloadBlob(blob, fileName) {
@@ -1767,7 +1804,14 @@ function addPrefillFilesToIndex(initialFiles, state) {
1767
1804
  if (!state.resourceIndex.has(resourceId)) {
1768
1805
  const filename = resourceId.split("/").pop() || "file";
1769
1806
  const extension = (_a = filename.split(".").pop()) == null ? void 0 : _a.toLowerCase();
1770
- const fileType = extension && ["jpg", "jpeg", "png", "gif", "webp"].includes(extension) ? `image/${extension === "jpg" ? "jpeg" : extension}` : "application/octet-stream";
1807
+ let fileType = "application/octet-stream";
1808
+ if (extension) {
1809
+ if (["jpg", "jpeg", "png", "gif", "webp"].includes(extension)) {
1810
+ fileType = `image/${extension === "jpg" ? "jpeg" : extension}`;
1811
+ } else if (["mp4", "webm", "mov", "avi"].includes(extension)) {
1812
+ fileType = `video/${extension === "mov" ? "quicktime" : extension}`;
1813
+ }
1814
+ }
1771
1815
  state.resourceIndex.set(resourceId, {
1772
1816
  name: filename,
1773
1817
  type: fileType,
@@ -2713,6 +2757,9 @@ var defaultConfig = {
2713
2757
  actionHandler: null,
2714
2758
  onChange: null,
2715
2759
  onFieldChange: null,
2760
+ onThumbnailError: null,
2761
+ onUploadError: null,
2762
+ onDownloadError: null,
2716
2763
  debounceMs: 300,
2717
2764
  enableFilePreview: true,
2718
2765
  maxPreviewSize: "200px",
@@ -3013,6 +3060,25 @@ var FormBuilderInstance = class {
3013
3060
  constructor(config) {
3014
3061
  this.instanceId = generateInstanceId();
3015
3062
  this.state = createInstanceState(config);
3063
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "development") {
3064
+ if (config == null ? void 0 : config.getThumbnail) {
3065
+ const testResult = config.getThumbnail("test-id");
3066
+ if (!(testResult instanceof Promise)) {
3067
+ console.warn(
3068
+ "[form-builder] getThumbnail must be async (return Promise). Wrap your function: async (id) => { ... }"
3069
+ );
3070
+ }
3071
+ }
3072
+ if (!globalThis.__formBuilderInstances) {
3073
+ globalThis.__formBuilderInstances = /* @__PURE__ */ new Set();
3074
+ }
3075
+ globalThis.__formBuilderInstances.add(this.instanceId);
3076
+ if (globalThis.__formBuilderInstances.size > 10) {
3077
+ console.warn(
3078
+ `[form-builder] ${globalThis.__formBuilderInstances.size} instances active. Possible memory leak - ensure you call destroy() when done.`
3079
+ );
3080
+ }
3081
+ }
3016
3082
  }
3017
3083
  /**
3018
3084
  * Get instance ID (useful for debugging and resource prefixing)
@@ -3547,6 +3613,7 @@ var FormBuilderInstance = class {
3547
3613
  * Destroy instance and clean up resources
3548
3614
  */
3549
3615
  destroy() {
3616
+ var _a;
3550
3617
  if (this.state.debounceTimer !== null) {
3551
3618
  clearTimeout(this.state.debounceTimer);
3552
3619
  this.state.debounceTimer = null;
@@ -3558,6 +3625,9 @@ var FormBuilderInstance = class {
3558
3625
  this.state.formRoot = null;
3559
3626
  this.state.schema = null;
3560
3627
  this.state.externalActions = null;
3628
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "development") {
3629
+ (_a = globalThis.__formBuilderInstances) == null ? void 0 : _a.delete(this.instanceId);
3630
+ }
3561
3631
  }
3562
3632
  };
3563
3633