@vulform/react
Version:
React components for VulForm contact form management
9 lines (7 loc) • 15.2 kB
JavaScript
import{useCallback as E}from"react";import{useState as k,useEffect as V,useCallback as B}from"react";import{VulFormApiClient as mo,VulFormError as z,FormValidator as no}from"@vulform/core";function G(o){let{templateId:e,apiKey:t,apiUrl:l,prefill:u={},onSuccess:p,onError:F,onValidationError:v,enableAnalytics:g=!0,spamProtection:N=!0}=o,[r,d]=k(null),[x,y]=k(!0),[Y,w]=k(null),[j,n]=k(!1),[Z,q]=k(!1),[R,S]=k(u),[M,L]=k({}),[f,C]=k(null);V(()=>{let i=t||process.env.NEXT_PUBLIC_VULFORM_API_KEY||process.env.REACT_APP_VULFORM_API_KEY||process.env.VULFORM_API_KEY;if(!i){w(new z("MISSING_API_KEY","API key is required. Set NEXT_PUBLIC_VULFORM_API_KEY, REACT_APP_VULFORM_API_KEY, or pass apiKey prop.")),y(!1);return}try{let m=new mo({apiKey:i,baseUrl:l,debug:!0});C(m)}catch(m){w(m instanceof z?m:new z("CLIENT_INIT_ERROR","Failed to initialize API client")),y(!1)}},[t,l]),V(()=>{if(!f||!e)return;(async()=>{try{y(!0),w(null);let m=await f.getTemplate(e);d(m);let s={};if(m.fields.forEach((h)=>{if(h.defaultValue!==void 0)s[h.name]=h.defaultValue}),S((h)=>({...s,...h})),g)f.trackEvent({type:"form_view",templateId:e,timestamp:Date.now()})}catch(m){let s=m instanceof z?m:new z("LOAD_FAILED","Failed to load form template");w(s),F?.(s)}finally{y(!1)}})()},[f,e,g,F]);let W=B((i,m)=>{if(S((s)=>({...s,[i]:m})),M[i])L((s)=>{let h={...s};return delete h[i],h})},[M]),_=B(async()=>{if(!r)return!1;let i=no.validateForm(R,r);L(i);let m=Object.keys(i).length===0;if(!m){if(v?.(i),g&&f)f.trackEvent({type:"validation_error",templateId:e,timestamp:Date.now(),metadata:{errorFields:Object.keys(i)}})}return m},[r,R,v,g,f,e]),O=B(async(i)=>{if(!f||!r)return;let m=i||R;n(!0),w(null);try{if(!await _())return;if(g)f.trackEvent({type:"form_submit",templateId:e,timestamp:Date.now(),metadata:{fieldCount:Object.keys(m).length}});let h=await f.submitForm({templateId:e,data:m});q(!0),p?.(h)}catch(s){let h=s instanceof z?s:new z("SUBMIT_FAILED","Form submission failed");w(h),F?.(h)}finally{n(!1)}},[f,r,R,_,p,F,g,e]),T=B(()=>{S(u),L({}),q(!1),w(null)},[u]),U=B(()=>{L({}),w(null)},[]);return{template:r,loading:x,error:Y,submitting:j,submitted:Z,formData:R,validationErrors:M,setFormData:S,updateField:W,validateForm:_,submitForm:O,resetForm:T,clearErrors:U}}import{memo as to}from"react";import{jsxDEV as P}from"react/jsx-dev-runtime";var D=to(({field:o,value:e,error:t,disabled:l=!1,onChange:u,onBlur:p,className:F=""})=>{let v=`vulform-${o.name}`,g=o.validation?.required,N=["vulform-input","w-full px-4 py-3 border rounded-lg transition-all duration-200","focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500","disabled:opacity-50 disabled:cursor-not-allowed",t?"border-red-500":"border-gray-300",o.className||""].filter(Boolean).join(" "),r=()=>{switch(o.type){case"textarea":return P("textarea",{id:v,name:o.name,value:e||"",onChange:(d)=>u(d.target.value),onBlur:p,placeholder:o.placeholder,disabled:l,required:g,rows:o.rows||3,className:N},void 0,!1,void 0,this);case"select":return P("select",{id:v,name:o.name,value:e||"",onChange:(d)=>u(d.target.value),onBlur:p,disabled:l,required:g,className:N,children:[o.placeholder&&P("option",{value:"",disabled:!0,children:o.placeholder},void 0,!1,void 0,this),o.options?.map((d)=>P("option",{value:d.value,children:d.label},d.value,!1,void 0,this))]},void 0,!0,void 0,this);default:return P("input",{type:o.type,id:v,name:o.name,value:e||"",onChange:(d)=>u(d.target.value),onBlur:p,placeholder:o.placeholder,disabled:l,required:g,className:N,step:o.step,min:o.validation?.min,max:o.validation?.max,minLength:o.validation?.minLength,maxLength:o.validation?.maxLength},void 0,!1,void 0,this)}};return P("div",{className:`vulform-field-wrapper ${F}`.trim(),children:[P("label",{htmlFor:v,className:"vulform-label block text-sm font-medium text-gray-700 mb-2",children:[o.label,g&&P("span",{className:"text-red-500",children:" *"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),o.description&&P("p",{className:"vulform-description text-sm text-gray-600 mb-2",children:o.description},void 0,!1,void 0,this),r(),t&&P("p",{className:"vulform-error text-sm text-red-600 mt-1",children:t},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});D.displayName="FormField";var J=D;import so from"react";import{jsxDEV as b}from"react/jsx-dev-runtime";var ro=({loadingState:o="default",className:e="",style:t})=>{if(typeof o==="object"&&so.isValidElement(o))return b("div",{className:e,style:t,children:o},void 0,!1,void 0,this);if(o==="custom")return b("div",{className:`vulform-loading ${e}`,style:t,children:b("div",{className:"animate-pulse space-y-4",children:[b("div",{className:"h-4 bg-gray-300 rounded w-3/4"},void 0,!1,void 0,this),b("div",{className:"h-10 bg-gray-300 rounded"},void 0,!1,void 0,this),b("div",{className:"h-4 bg-gray-300 rounded w-1/2"},void 0,!1,void 0,this),b("div",{className:"h-10 bg-gray-300 rounded"},void 0,!1,void 0,this),b("div",{className:"h-10 bg-gray-300 rounded w-1/3"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this);return b("div",{className:`vulform-loading ${e}`,style:t,children:b("div",{className:"flex items-center justify-center p-4 sm:p-6",children:b("div",{className:"flex items-center space-x-2 sm:space-x-3",children:[b("div",{className:"animate-spin rounded-full h-5 w-5 sm:h-6 sm:w-6 border-b-2 border-blue-600"},void 0,!1,void 0,this),b("span",{className:"text-gray-600 font-medium text-sm sm:text-base",children:"Loading form..."},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)},Q=ro;import{jsxDEV as $}from"react/jsx-dev-runtime";var co=({message:o="Thank you! Your message has been sent successfully.",onReset:e,className:t="",style:l})=>{return $("div",{className:`vulform-success ${t}`,style:l,children:$("div",{className:"text-center p-4 sm:p-6 border-2 border-green-200 bg-green-50 rounded-lg max-w-full",children:[$("div",{className:"mx-auto flex items-center justify-center h-10 w-10 sm:h-12 sm:w-12 rounded-full bg-green-100 mb-3 sm:mb-4",children:$("svg",{className:"h-5 w-5 sm:h-6 sm:w-6 text-green-600",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:$("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M5 13l4 4L19 7"},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),$("h3",{className:"text-base sm:text-lg font-semibold text-green-900 mb-2",children:"Success!"},void 0,!1,void 0,this),$("p",{className:"text-sm sm:text-base text-green-800 mb-4 sm:mb-6 leading-relaxed",children:o},void 0,!1,void 0,this),e&&$("button",{onClick:e,className:"inline-flex items-center px-3 py-2 sm:px-4 sm:py-2 border border-transparent text-xs sm:text-sm font-medium rounded-md text-green-700 bg-green-100 hover:bg-green-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 transition-colors",children:"Send Another Message"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},X=co;import{jsxDEV as c}from"react/jsx-dev-runtime";var uo=({error:o,onRetry:e,className:t="",style:l})=>{let u=()=>{switch(o.code){case"MISSING_API_KEY":return"Configuration error: API key is missing.";case"INVALID_API_KEY":return"Configuration error: Invalid API key format.";case"TEMPLATE_NOT_FOUND":return"Form template not found. Please check the template ID.";case"NETWORK_ERROR":return"Network error. Please check your internet connection and try again.";case"RATE_LIMIT_EXCEEDED":return"Too many requests. Please wait a moment before trying again.";case"TIMEOUT":return"Request timeout. Please try again.";default:return o.message||"An unexpected error occurred."}},p=()=>{switch(o.code){case"MISSING_API_KEY":case"INVALID_API_KEY":return"Configuration Error";case"TEMPLATE_NOT_FOUND":return"Form Not Found";case"NETWORK_ERROR":case"TIMEOUT":return"Connection Error";case"RATE_LIMIT_EXCEEDED":return"Rate Limit Exceeded";default:return"Error"}},F=()=>{return!["MISSING_API_KEY","INVALID_API_KEY","TEMPLATE_NOT_FOUND"].includes(o.code)};return c("div",{className:`vulform-error ${t}`,style:l,children:c("div",{className:"text-center p-4 sm:p-6 border-2 border-red-200 bg-red-50 rounded-lg max-w-full",children:[c("div",{className:"mx-auto flex items-center justify-center h-10 w-10 sm:h-12 sm:w-12 rounded-full bg-red-100 mb-3 sm:mb-4",children:c("svg",{className:"h-5 w-5 sm:h-6 sm:w-6 text-red-600",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:c("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),c("h3",{className:"text-base sm:text-lg font-semibold text-red-900 mb-2",children:p()},void 0,!1,void 0,this),c("p",{className:"text-sm sm:text-base text-red-800 mb-4 sm:mb-6 leading-relaxed",children:u()},void 0,!1,void 0,this),c("details",{className:"mb-4 sm:mb-6 text-left",children:[c("summary",{className:"cursor-pointer text-xs sm:text-sm text-red-700 hover:text-red-900 font-medium",children:"Technical Details"},void 0,!1,void 0,this),c("div",{className:"mt-2 p-2 sm:p-3 bg-red-100 rounded text-xs text-red-800 font-mono overflow-x-auto",children:[c("div",{className:"whitespace-nowrap",children:[c("strong",{children:"Code:"},void 0,!1,void 0,this)," ",o.code]},void 0,!0,void 0,this),c("div",{className:"whitespace-nowrap",children:[c("strong",{children:"Message:"},void 0,!1,void 0,this)," ",o.message]},void 0,!0,void 0,this),o.statusCode&&c("div",{className:"whitespace-nowrap",children:[c("strong",{children:"Status:"},void 0,!1,void 0,this)," ",o.statusCode]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),F()&&e&&c("button",{onClick:e,className:"inline-flex items-center px-3 py-2 sm:px-4 sm:py-2 border border-transparent text-xs sm:text-sm font-medium rounded-md text-red-700 bg-red-100 hover:bg-red-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 transition-colors",children:[c("svg",{className:"h-3 w-3 sm:h-4 sm:w-4 mr-1 sm:mr-2",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:c("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"},void 0,!1,void 0,this)},void 0,!1,void 0,this),"Try Again"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},H=uo;import{jsxDEV as a}from"react/jsx-dev-runtime";var K=({templateId:o,apiKey:e,apiUrl:t,theme:l="auto",className:u="",style:p,prefill:F={},onSuccess:v,onError:g,onValidationError:N,onFieldChange:r,enableAnalytics:d=!0,spamProtection:x=!0,loadingState:y="default",resetOnSuccess:Y=!0,showSuccessMessage:w=!0,autoRedirect:j=!1})=>{let{template:n,loading:Z,error:q,submitting:R,submitted:S,formData:M,validationErrors:L,updateField:f,submitForm:C,resetForm:W}=G({templateId:o,apiKey:e,apiUrl:t,prefill:F,onSuccess:v,onError:g,onValidationError:N,enableAnalytics:d,spamProtection:x}),_=E((m,s)=>{f(m,s),r?.(m,s)},[f,r]),O=E(async(m)=>{if(m.preventDefault(),await C(),Y&&!Object.keys(L).length)W()},[C,Y,L,W]),T=()=>{if(l==="auto"&&n?.theme)return{"--vulform-primary":n.theme.primaryColor,"--vulform-secondary":n.theme.secondaryColor,"--vulform-background":n.theme.backgroundColor,"--vulform-text":n.theme.textColor,"--vulform-border":n.theme.borderColor,"--vulform-border-radius":n.theme.borderRadius,"--vulform-font-family":n.theme.fontFamily,"--vulform-font-size":n.theme.fontSize,"--vulform-spacing":n.theme.spacing,fontFamily:n.theme.fontFamily,fontSize:n.theme.fontSize,color:n.theme.textColor,backgroundColor:n.theme.backgroundColor,...p};return p||{}},U=()=>{if(!n)return"space-y-6";let m=n.fields.some((s)=>s.width&&s.width!=="full");switch(n.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 m?"grid grid-cols-12 gap-6":"space-y-6"}},i=(m)=>{switch(m){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"}};if(Z)return a(Q,{loadingState:y,className:u,style:T()},void 0,!1,void 0,this);if(q)return a(H,{error:q,onRetry:()=>window.location.reload(),className:u,style:T()},void 0,!1,void 0,this);if(S&&w)return a(X,{message:n?.settings?.successMessage,onReset:W,className:u,style:T()},void 0,!1,void 0,this);if(!n)return a(H,{error:{code:"NO_TEMPLATE",message:"Form template not found"},className:u,style:T()},void 0,!1,void 0,this);return a("div",{className:`vulform-container ${u}`,style:T(),children:[n.theme?.customCss&&a("style",{dangerouslySetInnerHTML:{__html:n.theme.customCss}},void 0,!1,void 0,this),a("form",{onSubmit:O,className:"vulform-form",children:[n.name&&a("div",{className:"vulform-header mb-6",children:[a("h2",{className:"text-2xl font-semibold text-gray-900 mb-2",children:n.name},void 0,!1,void 0,this),n.description&&a("p",{className:"text-gray-600",children:n.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),a("div",{className:U(),children:n.fields.map((m)=>a("div",{className:i(m.width),children:a(J,{field:m,value:M[m.name],error:L[m.name],onChange:(s)=>_(m.name,s),disabled:R},void 0,!1,void 0,this)},m.id,!1,void 0,this))},void 0,!1,void 0,this),a("div",{className:"vulform-submit-section mt-8 pt-6 border-t border-gray-200",children:a("button",{type:"submit",disabled:R,className:`
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
${R?"bg-gray-400 cursor-not-allowed":"bg-blue-600 hover:bg-blue-700 focus:ring-blue-500"}
`,style:{backgroundColor:n.theme?.primaryColor||void 0},children:R?"Sending...":n.settings?.submitText||"Submit"},void 0,!1,void 0,this)},void 0,!1,void 0,this),q&&a("div",{className:"vulform-error-message mt-4 p-4 bg-red-50 border border-red-200 rounded-lg",children:a("p",{className:"text-red-800 text-sm",children:q?.message||"An error occurred"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{useState as I,useEffect as A,useCallback as oo}from"react";import{RealtimeValidator as ao}from"@vulform/core";function eo(o){let{field:e,value:t,apiClient:l,debounceMs:u=300,validateOnChange:p=!0}=o,[F,v]=I(null),[g,N]=I(!1),[r]=I(()=>new ao);A(()=>{if(!l||!e.validation)return;return r.registerField(e.name,async(y)=>{return l.validateField(e.name,y,e.validation)}),()=>{r.destroy()}},[e,l,r]);let d=oo(async()=>{if(!e.validation)return;N(!0);try{await r.validateField(e.name,t,(y)=>{v(y),N(!1)},u)}catch(y){N(!1)}},[e,t,r,u]);A(()=>{if(p&&t!==void 0)d()},[t,d,p]);let x=oo(()=>{v(null)},[]);return A(()=>{return()=>{r.destroy()}},[r]),{error:F,isValidating:g,validate:d,clearError:x}}export{G as useVulForm,eo as useFieldValidation,K as default,K as VulForm,X as FormSuccess,Q as FormLoader,J as FormField,H as FormErrorComponent};
//# debugId=DB25766F40CCFBDF64756E2164756E21
//# sourceMappingURL=index.js.map