@vulform/astro
Version:
Astro components for VulForm contact form management
177 lines (157 loc) • 24.6 kB
JavaScript
var N=Object.create;var{getPrototypeOf:Q,defineProperty:$,getOwnPropertyNames:C}=Object;var g=Object.prototype.hasOwnProperty;var w=(F,O,_)=>{_=F!=null?N(Q(F)):{};let q=O||!F||!F.__esModule?$(_,"default",{value:F,enumerable:!0}):_;for(let z of C(F))if(!g.call(q,z))$(q,z,{get:()=>F[z],enumerable:!0});return q};var u=(F,O)=>()=>(O||F((O={exports:{}}).exports,O),O.exports);var Z=u((l,K)=>{var{defineProperty:H,getOwnPropertyNames:A,getOwnPropertyDescriptor:h}=Object,m=Object.prototype.hasOwnProperty,V=new WeakMap,s=(F)=>{var O=V.get(F),_;if(O)return O;if(O=H({},"__esModule",{value:!0}),F&&typeof F==="object"||typeof F==="function")A(F).map((q)=>!m.call(O,q)&&H(O,q,{get:()=>F[q],enumerable:!(_=h(F,q))||_.enumerable}));return V.set(F,O),O},a=(F,O)=>{for(var _ in O)H(F,_,{get:O[_],enumerable:!0,configurable:!0,set:(q)=>O[_]=()=>q})},S={};a(S,{resolveApiUrl:()=>k,normalizeApiUrl:()=>E,isValidVulFormUrl:()=>p,isSelfHosted:()=>b,isProduction:()=>r,isDevelopment:()=>P,getDefaultConfig:()=>y,createSelfHostedConfig:()=>c,createSaaSConfig:()=>t,createCustomConfig:()=>o,VulFormError:()=>D,VulFormApiClient:()=>J,VULFORM_CONFIG:()=>L,RealtimeValidator:()=>I,FormValidator:()=>W,ConfigBuilder:()=>B});K.exports=s(S);var n=()=>{let F=typeof process!=="undefined"?process.env:{};return{baseUrl:F.VULFORM_BASE_URL||F.NEXT_PUBLIC_VULFORM_BASE_URL||F.REACT_APP_VULFORM_BASE_URL||F.VITE_VULFORM_BASE_URL,cdnUrl:F.VULFORM_CDN_URL||F.NEXT_PUBLIC_VULFORM_CDN_URL||F.REACT_APP_VULFORM_CDN_URL||F.VITE_VULFORM_CDN_URL,version:F.VULFORM_VERSION||"1.0.0",environment:F.NODE_ENV||"production"}},L={DEFAULT_BASE_URL:"https://api.vulform.dev",DEFAULT_CDN_URL:"https://cdn.vulform.dev",DEFAULT_TIMEOUT:1e4,DEFAULT_RETRIES:3,SELF_HOSTED_BASE_URL:"/api/v1",LOCAL_DEV_BASE_URL:"http://localhost:3000/api/v1",SDK_VERSION:"1.0.0",SDK_NAME:"vulform-sdk",AUTHOR:"Dogu Yilmaz",ORGANIZATION:"Dogu Yilmaz",HOMEPAGE:"https://vulform.dev",REPOSITORY:"https://github.com/doguyilmaz/vulform",...n()};class B{config;strategy="auto";constructor(F={},O="auto"){this.strategy=O,this.config={baseUrl:this.resolveBaseUrl(F.baseUrl),cdnUrl:this.resolveCdnUrl(F.cdnUrl),timeout:F.timeout||L.DEFAULT_TIMEOUT,retries:F.retries||L.DEFAULT_RETRIES,version:F.version||L.SDK_VERSION,environment:F.environment||L.environment||"production"}}resolveBaseUrl(F){if(F)return F;let O=L.baseUrl;if(O)return O;switch(this.strategy){case"saas":return L.DEFAULT_BASE_URL;case"self-hosted":return L.SELF_HOSTED_BASE_URL;case"custom":return L.DEFAULT_BASE_URL;case"auto":default:if(this.isLocalDevelopment())return L.LOCAL_DEV_BASE_URL;if(typeof window!=="undefined"){let _=window.location.origin;if(this.strategy==="auto")return L.SELF_HOSTED_BASE_URL}return L.DEFAULT_BASE_URL}}resolveCdnUrl(F){if(F)return F;let O=L.cdnUrl;if(O)return O;return L.DEFAULT_CDN_URL}isLocalDevelopment(){return this.config.environment==="development"||typeof window!=="undefined"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1"||window.location.hostname.endsWith(".local"))}setBaseUrl(F){return this.config.baseUrl=F,this}setCdnUrl(F){return this.config.cdnUrl=F,this}setEnvironment(F){return this.config.environment=F,this}setStrategy(F){return this.strategy=F,this.config.baseUrl=this.resolveBaseUrl(),this}build(){return{...this.config}}}var y=(F={},O="auto")=>{return new B(F,O).build()},k=(F,O="auto")=>{return new B({baseUrl:F},O).build().baseUrl},t=(F={})=>{return y(F,"saas")},c=(F={})=>{return y(F,"self-hosted")},o=(F,O={})=>{return y({...O,baseUrl:F},"custom")},P=()=>{return L.environment==="development"},r=()=>{return L.environment==="production"},b=()=>{let F=y();return F.baseUrl.startsWith("/")||F.baseUrl.includes(typeof window!=="undefined"?window.location.hostname:"localhost")},p=(F)=>{try{if(F.startsWith("/"))return!0;let O=new URL(F);return O.protocol==="http:"||O.protocol==="https:"}catch{return!1}},E=(F)=>{if(!F)return L.DEFAULT_BASE_URL;if(F=F.replace(/\/$/,""),!F.startsWith("http")&&!F.startsWith("/"))F="/"+F;return F};class J{config;constructor(F){if(!F.apiKey)throw new D("MISSING_API_KEY","API key is required");if(!F.apiKey.startsWith("vf_"))throw new D("INVALID_API_KEY",'Invalid API key format. API key must start with "vf_"');let O=this.resolveBaseUrl(F.baseUrl);if(this.config={baseUrl:O,timeout:F.timeout||1e4,retries:F.retries||3,debug:F.debug||!1,apiKey:F.apiKey},this.config.debug)console.log("[VulForm API] Client initialized:",{apiKey:F.apiKey.substring(0,8)+"...",baseUrl:this.config.baseUrl,resolvedFrom:F.baseUrl?"provided":"auto-detected"})}resolveBaseUrl(F){if(F&&p(F))return E(F);let O=k(F,"auto");if(this.config?.debug)console.log("[VulForm API] URL Resolution:",{provided:F,resolved:O,strategy:"auto"});return O}async getTemplate(F){let O=await this.makeRequest(`/templates/${F}`,{method:"GET"});if(!O.data?.template)throw new D("TEMPLATE_NOT_FOUND",`Template ${F} not found`);return O.data.template}async submitForm(F){let O={...F,api_key:this.config.apiKey,metadata:{...F.metadata,userAgent:typeof navigator!=="undefined"?navigator.userAgent:void 0,timestamp:new Date().toISOString()}},_=await this.makeRequest("/submit",{method:"POST",body:JSON.stringify(O),headers:{"Content-Type":"application/json"}});if(!_.success||!_.data)throw new D(_.error?.code||"SUBMISSION_FAILED",_.error?.message||"Form submission failed");return _.data}async validateField(F,O,_){let q=this.validateFieldClientSide(F,O,_);if(q)return q;if(_.pattern||F==="email")try{let z=await this.makeRequest("/validate",{method:"POST",body:JSON.stringify({field:F,value:O,rules:_}),headers:{"Content-Type":"application/json"}});if(z.data&&!z.data.valid)return z.data.error||"Validation failed"}catch(z){if(this.config.debug)console.warn("[VulForm API] Server validation failed, using client-side validation:",z)}return null}async trackEvent(F){try{await this.makeRequest("/analytics/events",{method:"POST",body:JSON.stringify({events:[F]}),headers:{"Content-Type":"application/json"}})}catch(O){if(this.config.debug)console.warn("[VulForm API] Failed to track analytics event:",O)}}async exportTemplate(F){let O=await this.makeRequest(`/templates/${F.templateId}/export`,{method:"POST",body:JSON.stringify({options:F.options}),headers:{"Content-Type":"application/json"}});if(!O.data)throw new D("EXPORT_FAILED","Failed to export template");return O.data}validateFieldClientSide(F,O,_){if(_.required&&(!O||typeof O==="string"&&O.trim().length===0))return _.customMessage||`${F} is required`;if(!O||O.length===0)return null;if(typeof O==="string"){if(_.minLength&&O.length<_.minLength)return _.customMessage||`Must be at least ${_.minLength} characters`;if(_.maxLength&&O.length>_.maxLength)return _.customMessage||`Must be no more than ${_.maxLength} characters`;if(F==="email"&&!this.isValidEmail(O))return _.customMessage||"Please enter a valid email address";if(_.pattern&&!new RegExp(_.pattern).test(O))return _.customMessage||"Invalid format"}if(typeof O==="number"||typeof O==="string"&&!isNaN(Number(O))){let q=Number(O);if(_.min!==void 0&&q<_.min)return _.customMessage||`Must be at least ${_.min}`;if(_.max!==void 0&&q>_.max)return _.customMessage||`Must be no more than ${_.max}`}return null}isValidEmail(F){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(F)}async makeRequest(F,O){let _=`${this.config.baseUrl}${F}`,q=null;for(let z=1;z<=this.config.retries;z++)try{let G=new AbortController,T=setTimeout(()=>G.abort(),this.config.timeout),U=await fetch(_,{...O,headers:{Authorization:`Bearer ${this.config.apiKey}`,"X-VulForm-SDK":"core/1.0.0",...O.headers},signal:G.signal});clearTimeout(T);let X,M=U.headers.get("content-type");if(M&&M.includes("application/json"))X=await U.json();else X={message:await U.text()};if(!U.ok){if(U.status===429){let Y=parseInt(U.headers.get("Retry-After")||"60");throw new D("RATE_LIMIT_EXCEEDED",`Rate limit exceeded. Try again in ${Y} seconds`,U.status,{retryAfter:Y})}throw new D(X.code||"API_ERROR",X.message||`HTTP ${U.status}: ${U.statusText}`,U.status,X)}return{success:!0,data:X}}catch(G){if(q=G instanceof Error?G:new Error(String(G)),G instanceof D){if(["INVALID_API_KEY","TEMPLATE_NOT_FOUND","VALIDATION_ERROR"].includes(G.code))throw G}if(z<this.config.retries){let T=Math.min(1000*Math.pow(2,z-1),1e4);await this.sleep(T);continue}if(G instanceof D)throw G;throw new D("NETWORK_ERROR",q.message||"Network request failed",0,q)}throw new D("UNKNOWN_ERROR","An unknown error occurred")}sleep(F){return new Promise((O)=>setTimeout(O,F))}}class D extends Error{code;statusCode;details;constructor(F,O,_,q){super(O);this.name="VulFormError",this.code=F,this.statusCode=_,this.details=q}}class W{static validateForm(F,O){let _={};for(let q of O.fields){if(["divider","heading","paragraph","hidden"].includes(q.type))continue;let z=F[q.name],G=this.validateField(q,z);if(G)_[q.name]=G}return _}static validateField(F,O){if(!F.validation)return null;return this.validateValue(F.name,O,F.validation,F.type)}static validateValue(F,O,_,q){if(_.required&&this.isEmpty(O))return _.customMessage||`${F} is required`;if(this.isEmpty(O))return null;if(typeof O==="string"){if(_.minLength&&O.length<_.minLength)return _.customMessage||`Must be at least ${_.minLength} characters`;if(_.maxLength&&O.length>_.maxLength)return _.customMessage||`Must be no more than ${_.maxLength} characters`;if(_.pattern&&!new RegExp(_.pattern).test(O))return _.customMessage||"Invalid format";if(q==="email"&&!this.isValidEmail(O))return _.customMessage||"Please enter a valid email address";if(q==="url"&&!this.isValidUrl(O))return _.customMessage||"Please enter a valid URL";if(q==="tel"&&!this.isValidPhone(O))return _.customMessage||"Please enter a valid phone number"}if(q==="number"&&O!==""){let z=parseFloat(O);if(isNaN(z))return _.customMessage||"Please enter a valid number";if(_.min!==void 0&&z<_.min)return _.customMessage||`Must be at least ${_.min}`;if(_.max!==void 0&&z>_.max)return _.customMessage||`Must be no more than ${_.max}`}if(["date","datetime-local","time"].includes(q||"")){if(!this.isValidDate(O))return _.customMessage||"Please enter a valid date"}if(q==="file"&&O instanceof FileList){let z=this.validateFiles(O,_);if(z)return _.customMessage||z}return null}static isEmpty(F){if(F===null||F===void 0)return!0;if(typeof F==="string")return F.trim().length===0;if(Array.isArray(F))return F.length===0;if(F instanceof FileList)return F.length===0;return!1}static isValidEmail(F){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(F)}static isValidUrl(F){try{return new URL(F),!0}catch{return!1}}static isValidPhone(F){let O=/^[\+]?[1-9][\d]{0,15}$/,_=F.replace(/[\s\-\(\)\.]/g,"");return O.test(_)}static isValidDate(F){if(!F)return!1;let O=new Date(F);return!isNaN(O.getTime())}static validateFiles(F,O){if(F.length===0)return null;if(O.max&&F.length>O.max)return`Too many files. Maximum ${O.max} files allowed`;for(let _=0;_<F.length;_++){let q=F[_];if(O.min&&q.size<O.min)return`File "${q.name}" is too small. Minimum size: ${this.formatFileSize(O.min)}`;if(O.max&&q.size>O.max)return`File "${q.name}" is too large. Maximum size: ${this.formatFileSize(O.max)}`}return null}static formatFileSize(F){let O=["Bytes","KB","MB","GB"];if(F===0)return"0 Bytes";let _=Math.floor(Math.log(F)/Math.log(1024));return Math.round(F/Math.pow(1024,_)*100)/100+" "+O[_]}}class I{validators=new Map;debounceTimers=new Map;registerField(F,O){this.validators.set(F,O)}async validateField(F,O,_,q=300){let z=this.debounceTimers.get(F);if(z)clearTimeout(z);let G=setTimeout(async()=>{let T=this.validators.get(F);if(T)try{let U=await T(O);_(U)}catch(U){console.warn(`Validation error for field ${F}:`,U),_(null)}this.debounceTimers.delete(F)},q);this.debounceTimers.set(F,G)}destroy(){this.debounceTimers.forEach((F)=>clearTimeout(F)),this.debounceTimers.clear(),this.validators.clear()}}});var R=w(Z(),1);class v{element;config;apiClient=null;template=null;formData={};validationErrors={};isSubmitting=!1;isSubmitted=!1;constructor(F,O){this.element=F,this.config=O,this.formData={...O.prefill},this.initialize()}async initialize(){try{await this.initializeApiClient(),await this.loadTemplate(),this.setupForm()}catch(F){this.showError(F instanceof R.VulFormError?F:new R.VulFormError("INIT_ERROR","Failed to initialize form"))}}async initializeApiClient(){let F=this.config.apiKey||this.getApiKeyFromEnv();if(!F)throw new R.VulFormError("MISSING_API_KEY","API key is required");this.apiClient=new R.VulFormApiClient({apiKey:F,baseUrl:this.config.apiUrl,debug:window.location.hostname==="localhost"})}getApiKeyFromEnv(){return window.__VULFORM_API_KEY__||window.VULFORM_API_KEY||void 0}async loadTemplate(){if(!this.apiClient)return;let F=await this.apiClient.getTemplate(this.config.templateId);this.template=F;let O={};if(F.fields.forEach((_)=>{if(_.defaultValue!==void 0)O[_.name]=_.defaultValue}),this.formData={...O,...this.formData},this.config.enableAnalytics&&this.apiClient)this.apiClient.trackEvent({type:"form_view",templateId:this.config.templateId,timestamp:Date.now()})}setupForm(){if(!this.template)return;this.hideLoading(),this.renderForm(),this.attachEventListeners()}hideLoading(){let F=this.element.querySelector('[data-loading="true"]');if(F)F.style.display="none"}renderForm(){if(!this.template)return;let F=this.element.querySelector('[data-form="true"]');if(!F)return;F.innerHTML=this.generateFormHTML(),F.style.display="block",F.classList.remove("hidden")}generateFormHTML(){if(!this.template)return"";let{fields:F,theme:O,settings:_}=this.template,q=this.getLayoutClasses();return`
<form class="vulform-form" data-vulform-form>
${this.template.name?`
<div class="vulform-header mb-6">
<h2 class="text-2xl font-semibold text-gray-900 mb-2">${this.template.name}</h2>
${this.template.description?`<p class="text-gray-600">${this.template.description}</p>`:""}
</div>
`:""}
<div class="${q}">
${F.map((z)=>this.generateFieldHTML(z)).join("")}
</div>
<div class="vulform-submit-section mt-8 pt-6 border-t border-gray-200">
<button
type="submit"
class="vulform-submit-button w-full px-6 py-3 text-white font-medium rounded-lg transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-600 hover:bg-blue-700 focus:ring-blue-500"
style="${O?.primaryColor?`background-color: ${O.primaryColor}`:""}"
>
${_?.submitText||"Submit"}
</button>
</div>
<div class="vulform-form-errors mt-4 hidden">
<div class="p-4 bg-red-50 border border-red-200 rounded-lg">
<p class="text-red-800 text-sm vulform-error-message"></p>
</div>
</div>
</form>
`}generateFieldHTML(F){let O=`field-${F.id}`,_=this.getFieldClasses(F);return`
<div class="${this.getFieldWidth(F.width)}">
<div class="vulform-field">
${F.label?`
<label for="${O}" class="vulform-label block text-sm font-medium text-gray-700 mb-2">
${F.label}
${F.required?'<span class="text-red-500 ml-1">*</span>':""}
</label>
`:""}
${F.description?`
<p class="text-sm text-gray-600 mb-2">${F.description}</p>
`:""}
${this.generateFieldInput(F,O,_)}
<div class="vulform-field-error mt-1 text-sm text-red-600 hidden" data-field-error="${F.name}"></div>
${F.helpText?`
<p class="mt-1 text-sm text-gray-500">${F.helpText}</p>
`:""}
</div>
</div>
`}generateFieldInput(F,O,_){let q=`
id="${O}"
name="${F.name}"
class="${_}"
${F.required?"required":""}
${F.placeholder?`placeholder="${F.placeholder}"`:""}
data-field-name="${F.name}"
`;switch(F.type){case"textarea":return`<textarea ${q} rows="${F.options?.rows||4}">${this.formData[F.name]||""}</textarea>`;case"select":return`
<select ${q}>
${!F.required?'<option value="">Select an option</option>':""}
${F.options?.choices?.map((G)=>`<option value="${G.value}" ${this.formData[F.name]===G.value?"selected":""}>${G.label}</option>`).join("")||""}
</select>
`;case"radio":return`
<div class="space-y-2">
${F.options?.choices?.map((G)=>`
<div class="flex items-center">
<input
type="radio"
id="${O}-${G.value}"
name="${F.name}"
value="${G.value}"
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300"
${this.formData[F.name]===G.value?"checked":""}
/>
<label for="${O}-${G.value}" class="ml-3 block text-sm font-medium text-gray-700">
${G.label}
</label>
</div>
`).join("")||""}
</div>
`;case"checkbox":return`
<div class="space-y-2">
${F.options?.choices?.map((G)=>{let T=Array.isArray(this.formData[F.name])?this.formData[F.name].includes(G.value):this.formData[F.name]===G.value;return`
<div class="flex items-center">
<input
type="checkbox"
id="${O}-${G.value}"
name="${F.name}"
value="${G.value}"
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
${T?"checked":""}
/>
<label for="${O}-${G.value}" class="ml-3 block text-sm font-medium text-gray-700">
${G.label}
</label>
</div>
`}).join("")||""}
</div>
`;default:let z=this.getInputType(F.type);return`<input ${q} type="${z}" value="${this.formData[F.name]||""}" />`}}getInputType(F){switch(F){case"email":return"email";case"phone":return"tel";case"number":return"number";case"url":return"url";case"date":return"date";case"time":return"time";case"datetime":return"datetime-local";default:return"text"}}getLayoutClasses(){if(!this.template)return"space-y-6";let F=this.template.fields.some((O)=>O.width&&O.width!=="full");switch(this.template.layout){case"horizontal":return"grid grid-cols-1 md:grid-cols-2 gap-6";case"grid":return"grid grid-cols-12 gap-6";default:return F?"grid grid-cols-12 gap-6":"space-y-6"}}getFieldWidth(F){switch(F){case"full":return"col-span-full";case"half":return"col-span-full md:col-span-6";case"third":return"col-span-full md:col-span-4";case"quarter":return"col-span-full md:col-span-3";default:return"col-span-full"}}getFieldClasses(F){return"block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"}attachEventListeners(){let F=this.element.querySelector("[data-vulform-form]");if(!F)return;F.addEventListener("submit",this.handleSubmit.bind(this)),F.querySelectorAll("input, textarea, select").forEach((_)=>{_.addEventListener("change",this.handleFieldChange.bind(this)),_.addEventListener("blur",this.handleFieldBlur.bind(this))})}handleFieldChange(F){let O=F.target,_=O.getAttribute("data-field-name");if(!_)return;if(O.type==="checkbox")this.handleCheckboxChange(O,_);else this.formData[_]=O.value;this.clearFieldError(_)}handleCheckboxChange(F,O){let _=this.formData[O],q=F.value;if(Array.isArray(_)){if(F.checked&&!_.includes(q))this.formData[O]=[..._,q];else if(!F.checked)this.formData[O]=_.filter((z)=>z!==q)}else this.formData[O]=F.checked?q:""}handleFieldBlur(F){let _=F.target.getAttribute("data-field-name");if(!_||!this.template)return;let q=this.template.fields.find((z)=>z.name===_);if(q){let z=R.FormValidator.validateField(this.formData[_],q);if(z&&z.length>0)this.showFieldError(_,z[0])}}async handleSubmit(F){if(F.preventDefault(),this.isSubmitting||!this.apiClient||!this.template)return;this.isSubmitting=!0,this.updateSubmitButton(!0),this.clearErrors();try{let O=R.FormValidator.validateForm(this.formData,this.template);if(Object.keys(O).length>0){this.showValidationErrors(O);return}let _=await this.apiClient.submitForm({templateId:this.config.templateId,data:this.formData});if(this.isSubmitted=!0,this.showSuccess(_),this.config.resetOnSuccess)this.resetForm()}catch(O){this.showError(O instanceof R.VulFormError?O:new R.VulFormError("SUBMIT_ERROR","Form submission failed"))}finally{this.isSubmitting=!1,this.updateSubmitButton(!1)}}showValidationErrors(F){Object.entries(F).forEach(([O,_])=>{this.showFieldError(O,_)})}showFieldError(F,O){let _=this.element.querySelector(`[data-field-error="${F}"]`);if(_)_.textContent=O,_.classList.remove("hidden")}clearFieldError(F){let O=this.element.querySelector(`[data-field-error="${F}"]`);if(O)O.classList.add("hidden")}clearErrors(){this.element.querySelectorAll("[data-field-error]").forEach((_)=>{_.classList.add("hidden")});let O=this.element.querySelector(".vulform-form-errors");if(O)O.classList.add("hidden")}showError(F){let O=this.element.querySelector(".vulform-error"),_=this.element.querySelector(".vulform-error-message");if(O&&_)_.textContent=F.message,O.style.display="block",O.classList.remove("hidden");this.hideLoading()}showSuccess(F){let O=this.element.querySelector(".vulform-success"),_=this.element.querySelector(".vulform-success-message"),q=this.element.querySelector('[data-form="true"]');if(O&&q){if(_&&this.template?.settings?.successMessage)_.textContent=this.template.settings.successMessage;q.style.display="none",O.style.display="block",O.classList.remove("hidden")}}updateSubmitButton(F){let O=this.element.querySelector(".vulform-submit-button");if(O)O.disabled=F,O.textContent=F?"Sending...":this.template?.settings?.submitText||"Submit"}resetForm(){this.formData={...this.config.prefill},this.isSubmitted=!1;let F=this.element.querySelector('[data-form="true"]'),O=this.element.querySelector(".vulform-success");if(F&&O){O.style.display="none",F.style.display="block";let _=F.querySelector("form");if(_)_.reset()}}}var j=w(Z(),1);function f(F={}){return{name:"vulform",hooks:{"astro:config:setup":({injectScript:O})=>{let _=j.resolveApiUrl(F.apiUrl,"auto");O("head-inline",`
window.__VULFORM_CONFIG__ = ${JSON.stringify({apiKey:F.apiKey,apiUrl:_,debug:F.debug||!1})};
if (typeof window !== 'undefined' && window.__VULFORM_CONFIG__.apiKey) {
window.__VULFORM_API_KEY__ = window.__VULFORM_CONFIG__.apiKey;
}
`),O("head-inline",`
<style>
.vulform-container {
max-width: 100%;
}
.vulform-label {
display: block;
font-size: 0.875rem;
font-weight: 500;
color: #374151;
margin-bottom: 0.5rem;
}
.vulform-input {
display: block;
width: 100%;
padding: 0.75rem;
border: 1px solid #D1D5DB;
border-radius: 0.375rem;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
font-size: 0.875rem;
line-height: 1.25rem;
transition: all 0.15s ease;
}
.vulform-input:focus {
outline: none;
border-color: #3B82F6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.vulform-input:disabled {
background-color: #F9FAFB;
cursor: not-allowed;
}
.vulform-error-text {
margin-top: 0.25rem;
font-size: 0.875rem;
color: #EF4444;
}
.vulform-submit-button:disabled {
background-color: #9CA3AF !important;
cursor: not-allowed;
}
.animate-pulse {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.animate-spin {
animation: spin 1s linear infinite;
}
pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
</style>
`)}}}}export{f as VulFormIntegration,v as VulFormClient};
//# debugId=F7FD7B6E799474C364756E2164756E21
//# sourceMappingURL=index.js.map