@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) • 10.1 kB
JavaScript
;var e=require("react/jsx-runtime"),t=require("react-hook-form");function r(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var n=r(require("yup"));const a=(e,r,n)=>{if(e&&"reportValidity"in e){const a=t.get(n,r);e.setCustomValidity(a&&a.message||""),e.reportValidity()}},i=(e,t)=>{for(const r in t.fields){const n=t.fields[r];n&&n.ref&&"reportValidity"in n.ref?a(n.ref,r,e):n.refs&&n.refs.forEach((t=>a(t,r,e)))}},s=(e,r)=>{r.shouldUseNativeValidation&&i(e,r);const n={};for(const a in e){const i=t.get(r.fields,a),s=Object.assign(e[a]||{},{ref:i&&i.ref});if(o(r.names||Object.keys(e),a)){const e=Object.assign({},t.get(n,a));t.set(e,"root",s),t.set(n,a,e)}else t.set(n,a,s)}return n},o=(e,t)=>e.some((e=>e.startsWith(t+".")));function l(e,r,n){return void 0===r&&(r={}),void 0===n&&(n={}),function(a,o,l){try{return Promise.resolve(function(t,s){try{var u=(r.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"===n.mode?"validateSync":"validate"](a,Object.assign({abortEarly:!1},r,{context:o}))).then((function(e){return l.shouldUseNativeValidation&&i({},l),{values:n.raw?a:e,errors:{}}})))}catch(e){return s(e)}return u&&u.then?u.then(void 0,s):u}(0,(function(e){if(!e.inner)throw e;return{values:{},errors:s((r=e,n=!l.shouldUseNativeValidation&&"all"===l.criteriaMode,(r.inner||[]).reduce((function(e,r){if(e[r.path]||(e[r.path]={message:r.message,type:r.type}),n){var a=e[r.path].types,i=a&&a[r.type];e[r.path]=t.appendErrors(r.path,n,e,r.type,i?[].concat(i,r.message):r.message)}return e}),{})),l)};var r,n})))}catch(e){return Promise.reject(e)}}}function u(e,t){var r;let a;switch(e.type){case"text":case"email":case"password":case"url":case"tel":case"textarea":a=n.string();break;case"number":a=n.number();break;case"checkbox":a=n.boolean();break;case"date":case"datetime-local":case"time":a=n.date();break;case"select":case"radio":case"file":default:a=n.mixed();break;case"array":a=n.array();break;case"object":a=n.object()}if(e.validation&&(a=function(e,t,r){let a=e;if(a instanceof n.StringSchema){if(void 0!==t.minLength){const e=d("minLength",r);a=a.min(t.minLength,e)}if(void 0!==t.maxLength){const e=d("maxLength",r);a=a.max(t.maxLength,e)}if(t.pattern){const e=d("pattern",r);a=a.matches(new RegExp(t.pattern),e)}if("email"in t&&t.email){const e=d("email",r);a=a.email(e)}}if(a instanceof n.NumberSchema){if(void 0!==t.min){const e=d("min",r);a=a.min(t.min,e)}if(void 0!==t.max){const e=d("max",r);a=a.max(t.max,e)}}if(a instanceof n.ArraySchema){if("minItems"in t&&void 0!==t.minItems){const e=d("minItems",r);a=a.min(t.minItems,e)}if("maxItems"in t&&void 0!==t.maxItems){const e=d("maxItems",r);a=a.max(t.maxItems,e)}}if(t.custom){const e=d("custom",r);a=a.test("custom",e,(async function(e){const r=await t.custom(e);return"boolean"==typeof r&&r}))}return a}(a,e.validation,e.validationMessages||t)),e.required||(null===(r=e.validation)||void 0===r?void 0:r.required)){const r=d("required",e.validationMessages,t);a=a.required(r)}return a}function c(e,t){const r={};return function e(a){a.forEach((a=>{if("type"in a)if("group"===a.type)e(a.fields);else if("array"===a.type){const e=c(a.itemSchema,t);r[a.name]=n.array().of(e)}else if("object"===a.type){const e={};a.fields.forEach((r=>{e[r.name]=u(r,t)})),r[a.name]=n.object().shape(e)}else r[a.name]=u(a,t)}))}(e.fields),n.object().shape(r)}function d(e,t,r){return(null==t?void 0:t[e])||(null==r?void 0:r[e])||m[e]||`Validation failed for ${e}`}const m={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"};"function"==typeof SuppressedError&&SuppressedError;function f(e,t){const r=y(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 p(e,t){return e.and?e.and.every((e=>f(e,t))):e.or?e.or.some((e=>f(e,t))):!!e.not&&!f(e.not,t)}function b(e,t){return"field"in e?f(e,t):p(e,t)}function h(e,t){return Object.entries(e).every((([e,r])=>{const n=y(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 y(e,t){return t.split(".").reduce(((e,t)=>e&&void 0!==e[t]?e[t]:void 0),e)}exports.DEFAULT_VALIDATION_MESSAGES=m,exports.FormRenderer=({schema:r,onSubmit:n,initialValues:a={},customComponents:i={},loading:s=!1,disabled:o=!1,className:u="",style:d,onFormChange:m,onFieldChange:f,renderSubmitButton:p,renderResetButton:b,renderFieldWrapper:h,renderErrorSummary:y})=>{const g=c(r),v=t.useForm({defaultValues:a,resolver:l(g),mode:"onChange"});return e.jsx(t.FormProvider,Object.assign({},v,{children:e.jsxs("form",{onSubmit:v.handleSubmit((async e=>{await n(e)})),className:`conform-form ${u}`,style:d,children:[r.title&&e.jsx("h2",{className:"text-xl font-semibold text-gray-900 mb-4",children:r.title}),r.description&&e.jsx("p",{className:"text-sm text-gray-600 mb-6",children:r.description}),e.jsx("div",{className:"space-y-4",children:r.fields.map(((t,r)=>e.jsx("div",{children:"name"in t?`Field: ${t.name} (Type: ${t.type})`:`Group: ${t.title||"Untitled"}`},("name"in t?t.name:`group-${r}`)||r)))}),e.jsx("button",{type:"submit",disabled:s||o,className:"px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:bg-gray-400",children:s?"Submitting...":r.submitButtonText||"Submit"})]})}))},exports.TextField=t=>{var{name:r,label:n,type:a="text",placeholder:i,value:s,defaultValue:o,disabled:l=!1,readonly:u=!1,required:c=!1,autoComplete:d,maxLength:m,className:f="",style:p,error:b,description:h,onChange:y,onBlur:g,onFocus:v,"data-testid":x}=t,j=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}(t,["name","label","type","placeholder","value","defaultValue","disabled","readonly","required","autoComplete","maxLength","className","style","error","description","onChange","onBlur","onFocus","data-testid"]);const N=`field-${r}`,$=`${N}-error`,E=`${N}-description`,O=`\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 ${b?"border-red-500 focus:ring-red-500 focus:border-red-500":"border-gray-300"}\n ${f}\n `.trim().replace(/\s+/g," ");return e.jsxs("div",{className:"form-field",style:p,children:[e.jsxs("label",{htmlFor:N,className:"block text-sm font-medium text-gray-700 mb-1 "+(c?"required":""),children:[n,c&&e.jsx("span",{className:"text-red-500 ml-1","aria-label":"required",children:"*"})]}),h&&e.jsx("p",{id:E,className:"text-sm text-gray-600 mb-2",children:h}),e.jsx("input",Object.assign({id:N,name:r,type:a,placeholder:i,value:s,defaultValue:o,disabled:l,readOnly:u,required:c,autoComplete:d,maxLength:m,className:O,onChange:y,onBlur:g,onFocus:v,"aria-invalid":b?"true":"false","aria-describedby":[b?$:null,h?E:null].filter(Boolean).join(" ")||void 0,"data-testid":x},j)),b&&e.jsx("p",{id:$,className:"mt-1 text-sm text-red-600",role:"alert",children:b})]})},exports.createFieldValidationSchema=u,exports.createFormValidationSchema=c,exports.evaluateComplexCondition=p,exports.evaluateCondition=f,exports.evaluateConditionalLogic=b,exports.evaluateSimpleCondition=h,exports.getNestedValue=y,exports.isEmpty=function(e){return null==e||("string"==typeof e?""===e.trim():Array.isArray(e)?0===e.length:"object"==typeof e&&0===Object.keys(e).length)},exports.shouldFieldBeDisabled=function(e,t){return!!e.disabled||!!e.disabledWhen&&h(e.disabledWhen,t)},exports.shouldFieldBeVisible=function(e,t){return e.conditional?b(e.conditional,t):!e.visibleWhen||h(e.visibleWhen,t)},exports.transformValidationErrors=function(e){const t={};return e.inner.forEach((e=>{e.path&&(t[e.path]||(t[e.path]=[]),t[e.path].push(e.message))})),t},exports.validateFieldValue=async function(e,t,r,a){try{const e=u(r,a);return await e.validate(t),null}catch(e){return e instanceof n.ValidationError?e.message:"Validation error"}},exports.validateFormData=async function(e,t,r){const a={};try{const n=c(t,r);await n.validate(e,{abortEarly:!1})}catch(e){e instanceof n.ValidationError&&e.inner.forEach((e=>{e.path&&(a[e.path]=e.message)}))}return a};
//# sourceMappingURL=index.js.map