@fivexlabs/conform-react
Version:
🚀 A powerful React library for building dynamic, conditional forms using JSON schemas with React Hook Form integration. Create complex forms declaratively with built-in validation, accessibility, and customizable components. Made with ❤️ by Fivex Labs.
3 lines (2 loc) • 9.75 kB
JavaScript
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{get as r,set as n,appendErrors as a,useForm as i,FormProvider as s}from"react-hook-form";import*as o from"yup";const l=(e,t,n)=>{if(e&&"reportValidity"in e){const a=r(n,t);e.setCustomValidity(a&&a.message||""),e.reportValidity()}},u=(e,t)=>{for(const r in t.fields){const n=t.fields[r];n&&n.ref&&"reportValidity"in n.ref?l(n.ref,r,e):n.refs&&n.refs.forEach((t=>l(t,r,e)))}},c=(e,t)=>{t.shouldUseNativeValidation&&u(e,t);const a={};for(const i in e){const s=r(t.fields,i),o=Object.assign(e[i]||{},{ref:s&&s.ref});if(d(t.names||Object.keys(e),i)){const e=Object.assign({},r(a,i));n(e,"root",o),n(a,i,e)}else n(a,i,o)}return a},d=(e,t)=>e.some((e=>e.startsWith(t+".")));function m(e,t,r){return void 0===t&&(t={}),void 0===r&&(r={}),function(n,i,s){try{return Promise.resolve(function(a,o){try{var l=(t.context&&"development"===process.env.NODE_ENV&&console.warn("You should not used the yup options context. Please, use the 'useForm' context object instead"),Promise.resolve(e["sync"===r.mode?"validateSync":"validate"](n,Object.assign({abortEarly:!1},t,{context:i}))).then((function(e){return s.shouldUseNativeValidation&&u({},s),{values:r.raw?n:e,errors:{}}})))}catch(e){return o(e)}return l&&l.then?l.then(void 0,o):l}(0,(function(e){if(!e.inner)throw e;return{values:{},errors:c((t=e,r=!s.shouldUseNativeValidation&&"all"===s.criteriaMode,(t.inner||[]).reduce((function(e,t){if(e[t.path]||(e[t.path]={message:t.message,type:t.type}),r){var n=e[t.path].types,i=n&&n[t.type];e[t.path]=a(t.path,r,e,t.type,i?[].concat(i,t.message):t.message)}return e}),{})),s)};var t,r})))}catch(e){return Promise.reject(e)}}}function f(e,t){var r;let n;switch(e.type){case"text":case"email":case"password":case"url":case"tel":case"textarea":n=o.string();break;case"number":n=o.number();break;case"checkbox":n=o.boolean();break;case"date":case"datetime-local":case"time":n=o.date();break;case"select":case"radio":case"file":default:n=o.mixed();break;case"array":n=o.array();break;case"object":n=o.object()}if(e.validation&&(n=function(e,t,r){let n=e;if(n instanceof o.StringSchema){if(void 0!==t.minLength){const e=h("minLength",r);n=n.min(t.minLength,e)}if(void 0!==t.maxLength){const e=h("maxLength",r);n=n.max(t.maxLength,e)}if(t.pattern){const e=h("pattern",r);n=n.matches(new RegExp(t.pattern),e)}if("email"in t&&t.email){const e=h("email",r);n=n.email(e)}}if(n instanceof o.NumberSchema){if(void 0!==t.min){const e=h("min",r);n=n.min(t.min,e)}if(void 0!==t.max){const e=h("max",r);n=n.max(t.max,e)}}if(n instanceof o.ArraySchema){if("minItems"in t&&void 0!==t.minItems){const e=h("minItems",r);n=n.min(t.minItems,e)}if("maxItems"in t&&void 0!==t.maxItems){const e=h("maxItems",r);n=n.max(t.maxItems,e)}}if(t.custom){const e=h("custom",r);n=n.test("custom",e,(async function(e){const r=await t.custom(e);return"boolean"==typeof r&&r}))}return n}(n,e.validation,e.validationMessages||t)),e.required||(null===(r=e.validation)||void 0===r?void 0:r.required)){const r=h("required",e.validationMessages,t);n=n.required(r)}return n}function b(e,t){const r={};return function e(n){n.forEach((n=>{if("type"in n)if("group"===n.type)e(n.fields);else if("array"===n.type){const e=b(n.itemSchema,t);r[n.name]=o.array().of(e)}else if("object"===n.type){const e={};n.fields.forEach((r=>{e[r.name]=f(r,t)})),r[n.name]=o.object().shape(e)}else r[n.name]=f(n,t)}))}(e.fields),o.object().shape(r)}function h(e,t,r){return(null==t?void 0:t[e])||(null==r?void 0:r[e])||p[e]||`Validation failed for ${e}`}const p={required:"This field is required",minLength:"Must be at least ${min} characters",maxLength:"Must be no more than ${max} characters",min:"Must be at least ${min}",max:"Must be no more than ${max}",pattern:"Invalid format",email:"Must be a valid email address",custom:"Invalid value",minItems:"Must have at least ${min} items",maxItems:"Must have no more than ${max} items"};async function y(e,t,r,n){try{const e=f(r,n);return await e.validate(t),null}catch(e){return e instanceof o.ValidationError?e.message:"Validation error"}}async function g(e,t,r){const n={};try{const n=b(t,r);await n.validate(e,{abortEarly:!1})}catch(e){e instanceof o.ValidationError&&e.inner.forEach((e=>{e.path&&(n[e.path]=e.message)}))}return n}function v(e){const t={};return e.inner.forEach((e=>{e.path&&(t[e.path]||(t[e.path]=[]),t[e.path].push(e.message))})),t}function x(e){return null==e||("string"==typeof e?""===e.trim():Array.isArray(e)?0===e.length:"object"==typeof e&&0===Object.keys(e).length)}const N=({schema:r,onSubmit:n,initialValues:a={},customComponents:o={},loading:l=!1,disabled:u=!1,className:c="",style:d,onFormChange:f,onFieldChange:h,renderSubmitButton:p,renderResetButton:y,renderFieldWrapper:g,renderErrorSummary:v})=>{const x=b(r),N=i({defaultValues:a,resolver:m(x),mode:"onChange"});return e(s,Object.assign({},N,{children:t("form",{onSubmit:N.handleSubmit((async e=>{await n(e)})),className:`conform-form ${c}`,style:d,children:[r.title&&e("h2",{className:"text-xl font-semibold text-gray-900 mb-4",children:r.title}),r.description&&e("p",{className:"text-sm text-gray-600 mb-6",children:r.description}),e("div",{className:"space-y-4",children:r.fields.map(((t,r)=>e("div",{children:"name"in t?`Field: ${t.name} (Type: ${t.type})`:`Group: ${t.title||"Untitled"}`},("name"in t?t.name:`group-${r}`)||r)))}),e("button",{type:"submit",disabled:l||u,className:"px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:bg-gray-400",children:l?"Submitting...":r.submitButtonText||"Submit"})]})}))};"function"==typeof SuppressedError&&SuppressedError;const $=r=>{var{name:n,label:a,type:i="text",placeholder:s,value:o,defaultValue:l,disabled:u=!1,readonly:c=!1,required:d=!1,autoComplete:m,maxLength:f,className:b="",style:h,error:p,description:y,onChange:g,onBlur:v,onFocus:x,"data-testid":N}=r,$=function(e,t){var r={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var a=0;for(n=Object.getOwnPropertySymbols(e);a<n.length;a++)t.indexOf(n[a])<0&&Object.prototype.propertyIsEnumerable.call(e,n[a])&&(r[n[a]]=e[n[a]])}return r}(r,["name","label","type","placeholder","value","defaultValue","disabled","readonly","required","autoComplete","maxLength","className","style","error","description","onChange","onBlur","onFocus","data-testid"]);const j=`field-${n}`,E=`${j}-error`,O=`${j}-description`,S=`\n w-full px-3 py-2 border rounded-md text-sm\n focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500\n disabled:bg-gray-100 disabled:text-gray-500 disabled:cursor-not-allowed\n readonly:bg-gray-50 readonly:cursor-default\n ${p?"border-red-500 focus:ring-red-500 focus:border-red-500":"border-gray-300"}\n ${b}\n `.trim().replace(/\s+/g," ");return t("div",{className:"form-field",style:h,children:[t("label",{htmlFor:j,className:"block text-sm font-medium text-gray-700 mb-1 "+(d?"required":""),children:[a,d&&e("span",{className:"text-red-500 ml-1","aria-label":"required",children:"*"})]}),y&&e("p",{id:O,className:"text-sm text-gray-600 mb-2",children:y}),e("input",Object.assign({id:j,name:n,type:i,placeholder:s,value:o,defaultValue:l,disabled:u,readOnly:c,required:d,autoComplete:m,maxLength:f,className:S,onChange:g,onBlur:v,onFocus:x,"aria-invalid":p?"true":"false","aria-describedby":[p?E:null,y?O:null].filter(Boolean).join(" ")||void 0,"data-testid":N},$)),p&&e("p",{id:E,className:"mt-1 text-sm text-red-600",role:"alert",children:p})]})};function j(e,t){const r=w(t,e.field);switch(e.operator){case"equals":return r===e.value;case"notEquals":return r!==e.value;case"greaterThan":return Number(r)>Number(e.value);case"lessThan":return Number(r)<Number(e.value);case"greaterThanOrEqual":return Number(r)>=Number(e.value);case"lessThanOrEqual":return Number(r)<=Number(e.value);case"contains":return"string"==typeof r?r.includes(String(e.value)):!!Array.isArray(r)&&r.includes(e.value);case"notContains":return"string"==typeof r?!r.includes(String(e.value)):!Array.isArray(r)||!r.includes(e.value);case"in":return!!e.values&&e.values.includes(r);case"notIn":return!e.values||!e.values.includes(r);case"isEmpty":return null==r||""===r||Array.isArray(r)&&0===r.length;case"isNotEmpty":return null!=r&&""!==r&&(!Array.isArray(r)||r.length>0);default:return!1}}function E(e,t){return e.and?e.and.every((e=>j(e,t))):e.or?e.or.some((e=>j(e,t))):!!e.not&&!j(e.not,t)}function O(e,t){return"field"in e?j(e,t):E(e,t)}function S(e,t){return Object.entries(e).every((([e,r])=>{const n=w(t,e);if("object"==typeof r&&null!==r){if("$in"in r)return r.$in.includes(n);if("$notIn"in r)return!r.$notIn.includes(n);if("$gt"in r)return Number(n)>Number(r.$gt);if("$lt"in r)return Number(n)<Number(r.$lt);if("$gte"in r)return Number(n)>=Number(r.$gte);if("$lte"in r)return Number(n)<=Number(r.$lte);if("$contains"in r)return String(n).includes(String(r.$contains));if("$isEmpty"in r){const e=null==n||""===n||Array.isArray(n)&&0===n.length;return r.$isEmpty?e:!e}}return n===r}))}function w(e,t){return t.split(".").reduce(((e,t)=>e&&void 0!==e[t]?e[t]:void 0),e)}function V(e,t){return e.conditional?O(e.conditional,t):!e.visibleWhen||S(e.visibleWhen,t)}function I(e,t){return!!e.disabled||!!e.disabledWhen&&S(e.disabledWhen,t)}export{p as DEFAULT_VALIDATION_MESSAGES,N as FormRenderer,$ as TextField,f as createFieldValidationSchema,b as createFormValidationSchema,E as evaluateComplexCondition,j as evaluateCondition,O as evaluateConditionalLogic,S as evaluateSimpleCondition,w as getNestedValue,x as isEmpty,I as shouldFieldBeDisabled,V as shouldFieldBeVisible,v as transformValidationErrors,y as validateFieldValue,g as validateFormData};
//# sourceMappingURL=index.js.map