@itcase/forms 1.0.37 → 1.0.38

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.
@@ -1 +1,2292 @@
1
- import{isPossiblePhoneNumber as e}from"libphonenumber-js";import t,{useMemo as r,useEffect as i,useCallback as o,useState as a}from"react";import{setIn as n,FORM_ERROR as s,getIn as l}from"final-form";import{useForm as m,Field as c,Form as u,FormSpy as d}from"react-final-form";export{Field,useForm,useFormState}from"react-final-form";import p from"prop-types";import f from"clsx";import{Checkbox as b}from"@itcase/ui/components/Checkbox";import{Divider as g}from"@itcase/ui/components/Divider";import{Text as h}from"@itcase/ui/components/Text";import{useDeviceTargetClass as _}from"@itcase/ui/hooks/useDeviceTargetClass";import{useStyles as x}from"@itcase/ui/hooks/useStyles";import{Choice as T}from"@itcase/ui/components/Choice";import{Code as y}from"@itcase/ui/components/Code";import{DatePickerInput as v}from"@itcase/ui/components/DatePicker";import S from"axios";import{useDropzone as E}from"react-dropzone";import{fromEvent as C}from"file-selector";import N from"lodash/castArray";import{createFileFromDataURL as z}from"@itcase/common";import{Loader as P}from"@itcase/ui/components/Loader";import{Title as F}from"@itcase/ui/components/Title";import{Input as j}from"@itcase/ui/components/Input";import{Icon as k}from"@itcase/ui/components/Icon";import{RadioButton as R}from"@itcase/ui/components/RadioButton";import{Segmented as B}from"@itcase/ui/components/Segmented";import{Select as W}from"@itcase/ui/components/Select";import{Switch as M}from"@itcase/ui/components/Switch";import{Textarea as w}from"@itcase/ui/components/Textarea";import{Button as L}from"@itcase/ui/components/Button";import{Group as q}from"@itcase/ui/components/Group";import{NotificationItem as O}from"@itcase/ui/components/Notification";import V from"final-form-focus";const D=(t,r)=>!t||e(t,"RU"),A=(e,t)=>{if(!e)return!0;return/^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]{2,}(?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/.test(String(e).toLowerCase())},I=e=>{const t=Object.entries(e.fields);return e.requiredFields=t.reduce(((e,[t,r])=>(r.exclusiveTests?.required&&e.push(t),e)),[]),e},$=(e,t)=>n(e,t.path,t.message),H=Object.create(null);function G(e,t){const i=r((()=>e&&(e=>async function(t){try{await e.validate(t,{abortEarly:!1})}catch(e){if(e.inner)return e.inner.reduce($,H);console.warn("itcase-forms schema.validate error: An error not related to the form occurred during validation. Validation ignored.")}})(e)),[e,t]);return i}function K(e){const{after:i,afterItem:o,before:a,beforeItem:n,children:s,className:l,desc:m,descTextSize:c,descTextColor:u,descTextWidth:d,divider:p,dividerDirection:b,dividerFill:T,dividerSize:y,dividerWidth:v,fieldClassName:S,id:E,inputName:C,inputValue:N,isRequired:z,label:P,labelTextSize:F,labelTextColor:j,labelTextWidth:k,errorMessageTextSize:R,errorMessageTextWeight:B,errorMessageTextColor:W,message:M,messageTextSize:w,messageTextColor:L,messageTextWeight:q,metaActive:O,metaError:V,metaModifiedSinceLastSubmit:D,metaSubmitError:A,metaSubmitFailed:I,metaTouched:$,metaValid:H,set:G,type:K,hideMessage:U,isHidden:J,tag:Q,dataTour:X,showErrorsOnSubmit:Y}=e,Z=V||!D&&A||!1,ee=r((()=>Y?I&&$&&Z:$&&Z),[Y,I,$,Z]),te=r((()=>(Array.isArray(N)?N.length:N)&&(H||!V&&A&&D)),[N,H,V,A,D]),re=r((()=>f(l,ee&&"form__item_state_error",te&&"form__item_state_success",z&&"form__item_state_required",O&&"form__item_state_focus",N&&"form__item_state_filled")),[l,ee,te,z,O,N]),ie=r((()=>f(S,ee&&`${S}_state_error`,te&&`${S}_state_success`,O&&`${S}_state_focus`,N&&`${S}_state_filled`)),[S,ee,te,O,N]),oe=_(e,{prefix:"form-field_size_",propsKey:"size"}),ae=_(e,{prefix:"fill_",propsKey:"fill"}),ne=_(e,{prefix:"fill_",propsKey:"inputFill"}),se=_(e,{prefix:"form-field_shape_",propsKey:"shape"}),le=_(e,{prefix:"form-field__item-value_shape_",propsKey:"inputShape"}),me=_(e,{prefix:"direction_",propsKey:"direction"}),ce=_(e,{prefix:"width_",propsKey:"width"}),{styles:ue}=x(e);return t.createElement(Q,{className:f(re,"form__item","form-field",K&&`form-field_type_${K}`,G&&`form-field_set_${G}`,oe,ae,se,J&&"form-field_state_hidden",me,ce),"data-tour":X,style:ue},a,P&&t.createElement("div",{htmlFor:E,className:"form-field__label"},t.createElement(h,{size:F,textWeight:k,textColor:j},P)),m&&t.createElement("div",{className:"form-field__desc"},t.createElement(h,{size:c,textWeight:d,textColor:u},m)),t.createElement("div",{className:f("form-field__content",ne,le)},t.createElement("div",{className:f("form-field__content-inner",ie)},n,s,o),p&&t.createElement(g,{className:"form-field__item-divider",width:v,direction:b,size:y,fill:T})),!U&&t.createElement("div",{className:"form-field__message"},Boolean(ee)&&t.createElement(h,{className:"form-field__message-item form-field__message-item_type-error",size:R,textWeight:B,textColor:W,id:`${C}-error`},Z),Boolean(M)&&!ee&&t.createElement(h,{className:"form-field__message-item form-field__message-item_type_message",size:w,textWeight:q,textColor:L},M),Boolean(!ee)&&Boolean(!M)&&t.createElement(h,{className:"form-field__message-item form-field__message-item_type_message",size:w}," ")),i)}function U(e){const{inputName:r}=e,{change:o}=m();return i((()=>()=>{o(r,void 0)}),[]),t.createElement(K,e)}K.defaultProps={tag:"div",type:"normal",errorMessageTextSize:"s",errorMessageTextColor:"errorTextSecondary"},K.propTypes={after:p.any,afterItem:p.any,autoComplete:p.string,before:p.any,beforeItem:p.any,children:p.any,className:p.string,desc:p.string,descTextSize:p.string,descTextColor:p.string,descTextWidth:p.string,dividerDirection:p.string,dividerFill:p.string,dividerSize:p.string,dividerWidth:p.string,fieldClassName:p.string,id:p.string,inputName:p.string,inputOnBlur:p.func,inputOnChange:p.func,inputOnFocus:p.func,inputValue:p.any,isRequired:p.bool,itemType:p.string,label:p.any,labelTextSize:p.string,labelTextColor:p.string,labelTextWidth:p.string,errorMessageTextSize:p.string,errorMessageTextWidth:p.string,errorMessageTextColor:p.string,message:p.string,messageSize:p.string,messageTextColor:p.string,messageTextWidth:p.string,metaActive:p.bool,metaError:p.string,metaModifiedSinceLastSubmit:p.bool,metaSubmitError:p.string,metaSubmitFailed:p.bool,metaTouched:p.bool,metaValid:p.bool,set:p.string,showErrorsOnSubmit:p.bool,type:p.string},U.propTypes={autoComplete:p.string,children:p.any,className:p.string,fieldClassName:p.string,hint:p.string,inputName:p.string,inputOnBlur:p.func,inputOnChange:p.func,inputOnFocus:p.func,inputValue:p.any,isRequired:p.bool,itemType:p.string,label:p.any,metaActive:p.bool,metaError:p.string,metaModifiedSinceLastSubmit:p.bool,metaSubmitError:p.string,metaSubmitFailed:p.bool,metaTouched:p.bool,metaValid:p.bool,showErrorsOnSubmit:p.bool};const J=t.memo((function(e){const{name:r,isRequired:i,onChange:a,fieldProps:n,inputProps:s,classNameGroupItem:l,hideMessage:m}=e;return t.createElement(c,{name:r,type:"checkbox"},(({input:e,meta:r})=>{const c=o((t=>{e.onChange(t),a&&a(t.target.checked,e.name)}),[a]);return t.createElement(U,Object.assign({className:f("form-field_type_checkbox","form__item_type_checkbox",l),fieldClassName:"form-checkbox",inputName:e.name,inputValue:e.checked,isRequired:i,metaActive:r.active,metaError:r.error,metaModifiedSinceLastSubmit:r.modifiedSinceLastSubmit,metaSubmitError:r.submitError,metaSubmitFailed:r.submitFailed,metaTouched:r.touched,metaValid:r.valid,tag:"label",hideMessage:m},n),t.createElement(b,Object.assign({autoComplete:"nope",checked:e.checked,name:e.name,type:"checkbox",onBlur:e.onBlur,onChange:c,onFocus:e.onFocus},s)))}))}));J.defaultProps={inputProps:{},fieldProps:{}},J.propTypes={fieldProps:p.object,inputProps:p.object,isRequired:p.bool,name:p.string,onChange:p.func};const Q=t.memo((function(e){const{options:i,classNameGroupItem:a,fieldProps:n,inputProps:s,isMultiple:l,isRequired:u,initialValue:d,label:p,name:b,messageType:g,hideMessage:h,placeholder:_}=e,{change:x}=m();return t.createElement(c,{name:b,initialValue:d},(({input:e,meta:m})=>{const c=r((()=>{const t={value:null,label:null};if(e.value){return i.find((t=>t.value===e.value))||t}return t}),[e.value]),d=o((e=>{x(b,e.value)}),[x]);return t.createElement(U,Object.assign({className:f("form-field_type_choice","form__item_type_choice",a),fieldClassName:"form-choice",inputName:e.name,inputValue:e.value||[],isRequired:u,label:p,messageType:g,metaActive:m.active,metaError:m.error,metaModifiedSinceLastSubmit:m.modifiedSinceLastSubmit,metaSubmitError:m.submitError,metaSubmitFailed:m.submitFailed,metaTouched:m.touched,metaValid:m.valid,hideMessage:h},n),t.createElement(T,Object.assign({className:f(m.active&&"form-choice_state_focus",m.error&&m.touched&&"form-choice_state_error"),options:i,inputName:e.name,inputValue:e.value||[],isMultiple:l,isRequired:u,placeholder:_,active:c,setActiveSegment:d},s)))}))}));Q.propTypes={options:p.array.isRequired,name:p.string.isRequired,className:p.string,inputClass:p.string,isMultiple:p.bool,isRequired:p.bool,label:p.string,placeholder:p.string};const X=t.memo((function(e){const{Component:r,isRequired:i,name:o,fieldProps:a,classNameGroupItem:n,hideMessage:s}=e;return t.createElement(c,{name:o},(({input:o,meta:l})=>t.createElement(U,Object.assign({className:f("form-field_type_custom","form__item_type_custom",n),fieldClassName:"form-custom",inputName:o.name,inputValue:o.value,isRequired:i,metaActive:l.active,metaError:l.error,metaModifiedSinceLastSubmit:l.modifiedSinceLastSubmit,metaSubmitError:l.submitError,metaSubmitFailed:l.submitFailed,metaTouched:l.touched,metaValid:l.valid,hideMessage:s},a),t.createElement(r,Object.assign({},e,{input:o,meta:l})))))}));X.defaultProps={inputProps:{},fieldProps:{}},X.propTypes={name:p.string.isRequired,isRequired:p.bool,fieldProps:p.object,inputProps:p.object};const Y=t.memo((function(e){const{isRequired:r,name:i,fieldProps:o,inputProps:a,classNameGroupItem:n,hideMessage:s}=e;return t.createElement(c,{name:i},(({input:e,meta:i})=>t.createElement(U,Object.assign({className:f("form-field_type_code","form__item_type_code",n),fieldClassName:"form-code",inputName:e.name,inputValue:e.value,isRequired:r,metaActive:i.active,metaError:i.error,metaModifiedSinceLastSubmit:i.modifiedSinceLastSubmit,metaSubmitError:i.submitError,metaSubmitFailed:i.submitFailed,metaTouched:i.touched,metaValid:i.valid,hideMessage:s},o),t.createElement(y,Object.assign({autoComplete:"nope",name:e.name,value:e.value,onBlur:e.onBlur,onChange:e.onChange,onFocus:e.onFocus},a)))))}));function Z(e){const{isRequired:r,fieldProps:i,inputProps:a,datePickerProps:n,name:s,iconSize:l,iconBorder:m,iconBorderHover:u,iconFill:d,iconFillHover:p,iconRevealableShow:b,iconRevealableHide:g,iconShape:h,hideMessage:_,onChange:x,classNameGroupItem:T}=e;return t.createElement(c,{name:s},(({input:e,meta:s})=>{const l=o((t=>{e.onChange(t),x&&x(t,e.name)}),[x]);return t.createElement(U,Object.assign({className:f("form-field_type_datepicker","form__item_type_datepicker",T),fieldClassName:"form-datepicker",inputName:e.name,inputValue:e.value||"",isRequired:r,metaActive:s.active,metaError:s.error,metaModifiedSinceLastSubmit:s.modifiedSinceLastSubmit,metaSubmitError:s.submitError,metaSubmitFailed:s.submitFailed,metaTouched:s.touched,metaValid:s.valid,hideMessage:_},i),t.createElement(v,{name:e.name,value:e.value||"",onBlur:e.onBlur,onChange:l,onFocus:e.onFocus,inputProps:a,datePickerProps:n}))}))}async function ee(e){try{const t=await S({url:`/api/${e}/`,responseType:"blob"}),r=t.data,i=t.headers["content-disposition"]?.split("filename=")[1];let o=i?.substring(1).slice(0,-1);if(!o){const e=r.type.split("/"),t=e[e.length-1];o=`${(new Date).getTime()}.${t}`}return new File([r],o,{type:r.type})}catch(e){return console.log("error: ",e),null}}function te(e,t){t=t||(()=>{});const r=new FileReader;r._readedFile=e,r.onabort=()=>t(),r.onerror=()=>t(),r.onload=e=>{e.target._readedFile.dataURL=r.result,t()},e instanceof File?r.readAsDataURL(e):t()}Y.defaultProps={inputProps:{},fieldProps:{}},Y.propTypes={name:p.string.isRequired,isRequired:p.bool,fieldProps:p.object,inputProps:p.object},Z.defaultProps={inputProps:{},fieldProps:{}},Z.propTypes={fieldProps:p.object,inputProps:p.object,isRequired:p.bool,name:p.string.isRequired,onChange:p.func};const re=t.memo((function(e){const{inputName:r,size:n,className:s,fileErrorText:l,hintTitleTextSize:c,removeThumbTextSize:u,removeThumbTextColor:d,removeThumbTextWeight:p,thumbNameTextSize:b,thumbNameTextColor:g,removeThumbTextHoverColor:x,thumbNameTextWrap:T,thumbNameTextWeight:y,hintTitleTextColor:v,hintTitleTextWrap:S,thumbColumn:F,hintTitleTextWeight:j,hintDescriptionTextSize:k,hintDescriptionTextColor:R,hintDescriptionTextWrap:B,hintDescriptionTextWeight:W,errorMessageTextSize:M,errorMessageTextWeight:w,errorMessageTextColor:L,inputValue:q,maxFiles:O,maxSize:V,removeThumbText:D,hintTitle:A,hintDescription:I,isShowFilename:$,isPreviews:H,loadingText:G,dropzoneProps:K={},onAddFiles:U,onDeleteFile:J}=e,[Q,X]=a(""),[Y,Z]=a(!1),[re,ie]=a(q?N(q):[]),{change:oe}=m(),ae=o((e=>{const t=1==K.maxFiles?e[0]:e;return oe(r,t),t}),[K,oe]),{getRootProps:ne,getInputProps:se}=E({maxSize:V||10485760,maxFiles:O||5,...K,getFilesFromEvent:async e=>{const t=(await C(e)).filter((e=>e instanceof File));return[...re,...t]},onDropAccepted:(e,t)=>{H&&e.forEach((e=>{e.error||(e.preview=URL.createObjectURL(e))})),ie(e),X("");const i=e.map((e=>new Promise((t=>te(e,t)))));Promise.all(i).then((()=>{const t=ae(e);U&&U(t,r)}))},onDropRejected:(e,t)=>{if(e.length){const t=e[0].errors[0]?.message;X(t||"Error on adding file")}else X("")}}),le=o(((e,t)=>{e.stopPropagation(),e.preventDefault();const i=[...re];i.splice(t,1),J&&J(re[t],r),ae(i)}),[re,ae,J]),me=o((async e=>{Z(!0);const t=await async function(e,t){const r=[];for await(const i of N(e)){let e=null;const o="string"==typeof i&&i.includes("/");(i.image||o)&&(e=await ee(i.image||i),e&&te(e)),i.dataURL&&(e=z(i.name||i.path,i.dataURL),e.dataURL=i.dataURL),e&&(e.id=i.id,t&&(e.preview=URL.createObjectURL(e)),r.push(e))}return r}(e,H);return Z(!1),ie(t),t}),[H]);i((()=>{me(q).then((e=>ae(e)))}),[]),i((()=>{q?me(q):ie([])}),[q]),i((()=>()=>re.forEach((e=>URL.revokeObjectURL(e?.preview)))),[]);const ce=_(e,{prefix:"fill_",propsKey:"fill"}),ue=_(e,{prefix:"fill_hover_",propsKey:"fillHover"}),de=_(e,{prefix:"border-width_",propsKey:"borderWidth"}),pe=_(e,{prefix:"border-color_",propsKey:"borderColor"}),fe=_(e,{prefix:"border-color_hover_",propsKey:"borderColorHover"}),be=_(e,{prefix:"border_type_",propsKey:"borderType"}),ge=_(e,{prefix:"form-dropzone_shape_",propsKey:"shape"}),he=_(e,{prefix:"border-width_",propsKey:"thumbBorderWidth"}),_e=_(e,{prefix:"form-dropzone__thumb_direction_",propsKey:"thumbDirection"}),xe=_(e,{prefix:"border-color_",propsKey:"thumbBorderColor"}),Te=_(e,{prefix:"border-color_hover_",propsKey:"thumbBorderColorHover"}),ye=_(e,{prefix:"border_type_",propsKey:"thumbBorderType"});return t.createElement(t.Fragment,null,t.createElement("div",ne({className:`form-dropzone__dropzone dropzone ${s} thumbColumn form-dropzone__dropzone_size_${n} ${ge}`}),t.createElement("input",Object.assign({},se(),{name:r})),t.createElement("div",{className:f("form-dropzone__dropzone-wrapper",F&&`form-dropzone__dropzone-wrapper_column_${F}`,ce,ue,de,pe,fe,be)},re.map(((e,r)=>t.createElement("aside",{className:f("form-dropzone__thumb",ce,_e,he,xe,Te,ye),key:`${e.id||`${e.name}_${r}`||"i"+r}`},H&&!e.error&&t.createElement("div",{className:"form-dropzone__thumb-image"},t.createElement("img",{className:"form-dropzone__thumb-image-inner",src:e.preview||e.image,onLoad:()=>{URL.revokeObjectURL(e.preview)}})),e.error&&t.createElement("div",null,t.createElement(h,{size:b,textColor:g,textWrap:T,textWeight:y},l||e.error)),$&&t.createElement("div",{className:"form-dropzone__thumb-name"},t.createElement(h,{size:b,textColor:g,textWrap:T,textWeight:y,className:"form-dropzone__thumb-name-inner"},e.name)),Y&&t.createElement("div",{className:"form-dropzone__thumb-loader"},t.createElement(P,{fill:"surfacePrimary",height:"fill",itemFill:"surfaceItemAccent",set:"simple",width:"fill"})),t.createElement("div",{className:"form-dropzone__thumb-remove",onClick:e=>le(e,r)},t.createElement(h,{size:u,textColor:d,textWeight:p,textColorHover:x,className:"form-dropzone__thumb-remove-text"},D||"Remove"))))),re.length?t.createElement("div",{className:"form-dropzone__hint form-dropzone__hint_type_add-more"},t.createElement(h,{size:c,textColor:v,textWrap:S,textWeight:j,className:"form-dropzone__hint-title"},A||"Select a file or drag in form"),t.createElement(h,{size:k,textColor:R,textWrap:B,textWeight:W,className:"form-dropzone__hint-text"},I)):t.createElement("div",{className:"form-dropzone__hint"},t.createElement(h,{size:c,textColor:v,textWrap:S,textWeight:j,className:"form-dropzone__hint-title"},A||"Select a file or drag in form"),t.createElement(h,{size:k,textColor:R,textWrap:B,textWeight:W,className:"form-dropzone__hint-text"},I)))),Q&&t.createElement("div",{className:"form-field__message"},t.createElement(h,{className:"form-field__message-item form-field__message-item_type_message",size:M,textWeight:w,textColor:L},Q)))}));re.propTypes={dropzoneProps:p.object,hintDescription:p.string,hintTitle:p.string,inputName:p.string,inputValue:p.any,isPreviews:p.bool,isShowFilename:p.bool,loadingText:p.string,metaError:p.string,metaTouched:p.bool,removeThumbText:p.string,onAddFiles:p.func,onDeleteFile:p.func};const ie=t.memo((function(e){const{name:r,shape:i,size:o,borderWidth:a,borderColor:n,borderColorHover:s,borderType:l,label:m,thumbBorderWidth:u,thumbBorderColor:d,thumbBorderColorHover:p,thumbBorderType:b,removeThumbTextHoverColor:g,labelTextColor:h,fill:_,fillHover:x,className:T,removeThumbText:y,thumbNameTextSize:v,thumbNameTextColor:S,thumbNameTextWrap:E,thumbNameTextWeight:C,removeThumbTextSize:N,removeThumbTextColor:z,removeThumbTextWeight:P,hintTitle:F,errorMessageTextSize:j,errorMessageTextWeight:k,errorMessageTextColor:R,fieldProps:B,hintTitleTextSize:W,hintTitleTextColor:M,hintTitleTextWrap:w,hintTitleTextWeight:L,hintDescriptionTextSize:q,hintDescriptionTextColor:O,hintDescriptionTextWrap:V,hintDescriptionTextWeight:D,hideMessage:A,thumbDirection:I,hintDescription:$,isShowFilename:H,fileErrorText:G,dropzoneProps:K,maxFiles:J,maxSize:Q,thumbColumn:X,isRequired:Y,isPreviews:Z,onAddFiles:ee,onDeleteFile:te,classNameGroupItem:ie}=e;return t.createElement(c,{name:r},(({input:e,meta:r})=>t.createElement(U,Object.assign({className:f("form-field_type_dropzone","form__item_type_dropzone",ie),fieldClassName:"form-dropzone",inputName:e.name,inputValue:e.value,isRequired:Y,label:m,labelTextColor:h,metaActive:r.active,metaError:r.error,metaModifiedSinceLastSubmit:r.modifiedSinceLastSubmit,metaSubmitError:r.submitError,metaSubmitFailed:r.submitFailed,metaTouched:r.touched,metaValid:r.valid,hideMessage:A},B),t.createElement(re,{dropzoneProps:K,hintDescription:$,hintTitle:F,borderWidth:a,borderColor:n,borderColorHover:s,borderType:l,thumbBorderWidth:u,thumbBorderColor:d,thumbBorderColorHover:p,thumbBorderType:b,fileErrorText:G,fill:_,size:o,maxFiles:J,maxSize:Q,removeThumbTextHoverColor:g,fillHover:x,className:T,thumbColumn:X,thumbDirection:I,inputName:e.name,inputValue:e.value,thumbNameTextSize:v,thumbNameTextColor:S,thumbNameTextWrap:E,thumbNameTextWeight:C,hintTitleTextSize:W,hintTitleTextColor:M,hintTitleTextWrap:w,hintTitleTextWeight:L,removeThumbTextSize:N,removeThumbTextColor:z,removeThumbTextWeight:P,hintDescriptionTextSize:q,hintDescriptionTextColor:O,hintDescriptionTextWrap:V,hintDescriptionTextWeight:D,errorMessageTextSize:j,errorMessageWeight:k,errorMessageTextColor:R,isPreviews:Z,shape:i,isShowFilename:H,metaError:r.error,metaTouched:r.touched,removeThumbText:y,onAddFiles:ee,onDeleteFile:te}))))}));ie.defaultProps={errorMessageTextSize:"s",errorMessageTextColor:"errorTextPrimary",thumbColumn:1,thumbDirection:"vertical"},ie.propTypes={name:p.string.isRequired,className:p.string,classNameGroupItem:p.string,classNameInput:p.string,classNameInputWrapper:p.string,dropzoneProps:p.object,hintDescription:p.string,hintTitle:p.string,inputClass:p.string,isPreviews:p.bool,isRequired:p.bool,isShowFilename:p.bool,label:p.any,removeThumbText:p.string,onAddFiles:p.func,onDeleteFile:p.func};const oe=t.memo((function(e){const{after:i,before:o,className:a,label:n,labelTextColor:s,labelTextSize:l,labelTextWeight:m,message:u,errorMessageTextSize:d,errorMessageTextWeight:p,errorMessageTextColor:b,messageTextSize:g,messageTextWeight:_,messageTextColor:x,children:T,dataTour:y,hideMessage:v,name:S,showErrorsOnSubmit:E}=e;return t.createElement(c,{name:S},(({input:e,meta:c})=>{const C=c.error||!c.modifiedSinceLastSubmit&&c.submitError||!1,N=r((()=>E?c.submitFailed&&c.touched&&C:c.touched&&C),[E,c.submitFailed,c.touched,C]);return t.createElement("div",{className:f("form__group",a),"data-tour":y},t.createElement("div",{className:"form__group-wrapper"},o,t.createElement("div",{className:"form__group-label"},t.createElement(F,{textColor:s,size:l,textWeight:m},n)),t.createElement("div",{className:"form__group-items"},T),i),!v&&t.createElement(t.Fragment,null,Boolean(N)&&t.createElement(h,{className:"form__group-message form__group-message_type-error",size:d,textWeight:p,textColor:b,id:`${S}-error`},C),Boolean(u)&&!N&&t.createElement(h,{className:"form__group-message",size:g,textWeight:_,textColor:x},u),Boolean(!N)&&Boolean(!u)&&t.createElement(h,{className:"form__group-message",size:g}," ")))}))}));oe.defaultProps={inputProps:{},fieldProps:{},type:"normal",errorMessageTextSize:"s",errorMessageTextColor:"errorTextPrimary",messageTextSize:"s",messageTextColor:"surfaceTextTertiary"},oe.propTypes={name:p.string.isRequired,isRequired:p.bool,fieldProps:p.object,inputProps:p.object};const ae=t.memo((function(e){const{isPassword:i,isRequired:n,fieldProps:s,inputProps:l,isRevealable:m,name:u,parse:d,iconSize:p,iconBorder:b,iconBorderHover:g,iconFill:h,iconFillHover:_,iconRevealableShow:x,iconRevealableHide:T,iconShape:y,hideMessage:v,onChange:S,classNameGroupItem:E}=e,[C,N]=a(!1),z=r((()=>i?C?"text":"password":"text"),[C,i]),P=o((e=>{e.preventDefault(),N((e=>!e))}),[N]);return t.createElement(c,{name:u,parse:d},(({input:e,meta:r})=>{const i=o((t=>{e.onChange(t),S&&S(t.target.value,e.name)}),[S]);return t.createElement(U,Object.assign({className:f("form-field_type_input","form__item_type_input",E),fieldClassName:m?"form-password":"form-input",inputName:e.name,inputValue:e.value||"",isRequired:n,metaActive:r.active,metaError:r.error,metaModifiedSinceLastSubmit:r.modifiedSinceLastSubmit,metaSubmitError:r.submitError,metaSubmitFailed:r.submitFailed,metaTouched:r.touched,metaValid:r.valid,hideMessage:v},s),t.createElement(j,Object.assign({className:f(r.active&&"input_state_focus",r.error&&r.touched&&"input_state_error"),autoComplete:"nope",name:e.name,type:z,value:e.value||"",onBlur:e.onBlur,onChange:i,onFocus:e.onFocus},l)),m&&t.createElement(k,{className:"form-field__icon",iconFill:h,iconFillHover:_,SvgImage:C?T:x,imageSrc:C?T:x,shape:y,size:p,onClick:P}))}))}));function ne(e){const{input:r,option:i,onChange:a,inputProps:n}=e,s=o((e=>{e.target.checked&&a(i.value)}),[]);return t.createElement(R,Object.assign({className:"form-radio__item",checked:i.value===r.value,name:r.name,type:"radio",value:i.value,onBlur:r.onBlur,onChange:s,onFocus:r.onFocus,label:i.label},n))}function se(e){const{input:r,value:i,onChange:a}=e,n=o((e=>a(e.target.value)),[a]);return t.createElement(j,Object.assign({autoComplete:"nope",name:r.name,onBlur:r.onBlur,onChange:n,onFocus:r.onFocus,value:i},e))}function le(e){const{input:r,options:n,editableProps:s,onChange:l,inputProps:m}=e,[c,u]=a((()=>n.find((e=>e.value===r.value))?"":r.value));i((()=>{if(r.value){const e=n.find((e=>e.value===r.value&&!e.editable));u(e?"":r.value)}else u("")}),[r.value]);const d=o((e=>{r.onChange(e),l&&l(e,r.name)}),[r,l]),p=o((e=>{u(""),d(e)}),[d]),f=o((e=>{u(e),d(e)}),[d]);return t.createElement(t.Fragment,null,n.map((e=>e.editable?t.createElement(se,{key:e.label,input:r,value:c,option:e,onChange:f,editableProps:s,inputProps:m}):t.createElement(ne,{key:e.value,input:r,option:e,onChange:p,inputProps:m}))))}ae.defaultProps={inputProps:{},fieldProps:{}},ae.propTypes={fieldProps:p.object,inputProps:p.object,isPassword:p.bool,isRequired:p.bool,isRevealable:p.bool,name:p.string.isRequired,onChange:p.func},ne.propTypes={inputProps:p.object,onChange:p.func,option:p.shape({label:p.string,value:p.string}),input:p.shape({name:p.string,value:p.string,onBlur:p.func,onFocus:p.func,onChange:p.func})},se.propTypes={input:p.string,value:p.string,editableProps:p.object,onChange:p.func},le.propTypes={editableProps:p.object,input:p.object,inputProps:p.object,onChange:p.object,options:p.object};const me=t.memo((function(e){const{isRequired:r,name:i,options:o,fieldProps:a,editableProps:n,inputProps:s,onChange:l,hideMessage:m}=e;return t.createElement(c,{name:i},(({input:e,meta:i})=>t.createElement(U,Object.assign({className:"form__item_type_radio",fieldClassName:"form-radio",inputName:e.name,inputValue:e.value||"",isRequired:r,metaActive:i.active,metaError:i.error,metaModifiedSinceLastSubmit:i.modifiedSinceLastSubmit,metaSubmitError:i.submitError,metaSubmitFailed:i.submitFailed,metaTouched:i.touched,metaValid:i.valid,hideMessage:m},a),t.createElement(le,{input:e,options:o,onChange:l,editableProps:n,inputProps:s}))))}));function ce(e){const{options:i,isRequired:a,name:n,fieldProps:s,inputProps:l,hideMessage:u}=e,{change:d}=m();return t.createElement(c,{name:n},(({input:e,meta:m})=>{const c=r((()=>{const t={value:null,label:null};if(e.value){return i.find((t=>t.value===e.value))||t}return t}),[e.value]),p=o((e=>{d(n,e.value)}),[d]);return t.createElement(U,Object.assign({className:f("form-field_type_segmented","form__item_type_segmented"),fieldClassName:"form-segmented",inputName:e.name,inputValue:e.value||[],isRequired:a,metaActive:m.active,metaError:m.error,metaModifiedSinceLastSubmit:m.modifiedSinceLastSubmit,metaSubmitError:m.submitError,metaSubmitFailed:m.submitFailed,metaTouched:m.touched,metaValid:m.valid,hideMessage:u},s),t.createElement(B,Object.assign({segments:i,setActiveSegment:p,activeSegment:c},l)))}))}function ue(e,t){const r=Array.isArray(t)?t:[t];let i=[];return e.forEach((e=>{const o=r.includes(e.value),a=r.includes(e.label);let n=[];e.options&&(n=ue(e.options,t)),o||a?i.push(e):n.length&&(i=i.concat(n))})),i}me.defaultProps={fieldProps:{},editableProps:{},inputProps:{},options:[]},me.propTypes={name:p.string.isRequired,fieldProps:p.object,inputProps:p.object,editableProps:p.object,isRequired:p.bool,options:p.array,onChange:p.func},ce.propTypes={options:p.array.isRequired,name:p.string.isRequired,className:p.string,inputClass:p.string,isRequired:p.bool,label:p.string,placeholder:p.string,fieldProps:p.object,inputProps:p.object};const de=t.memo((function(e){const{isRequired:n,key:s,name:l,options:m,fieldProps:u,selectProps:d,selectRef:p,onChange:b,classNameGroupItem:g,hideMessage:h}=e;return t.createElement(c,{name:l},(({input:e,meta:l})=>{const c=o((t=>{e.onChange(t),b&&b(t,e.name)}),[b]),[_,x]=a(null),T=r((()=>{const t=ue(m,e.value);return!t.length&&e.value?.length&&t.push({value:e.value,label:e.value}),t}),[e.value]);i((()=>x(T)),[T]);const y=o(((e,t)=>{const r=Array.isArray(e)?e.map((e=>e.value)):e?.value||null;x(e),c(r)}),[c]);return t.createElement(U,Object.assign({className:f("form-field_type_select","form__item_type_select",g),fieldClassName:"form-select",inputName:e.name,inputValue:e.value,isRequired:n,metaActive:l.active,metaError:l.error,metaModifiedSinceLastSubmit:l.modifiedSinceLastSubmit,metaSubmitError:l.submitError,metaSubmitFailed:l.submitFailed,metaTouched:l.touched,metaValid:l.valid,hideMessage:h},u),t.createElement(W,Object.assign({className:"form-select-item",instanceId:`id_${e.name}`,value:_,onChange:y,options:m,ref:p,key:s},d)))}))}));de.propTypes={name:p.string.isRequired,selectProps:p.object,isRequired:p.bool,label:p.any,messageType:p.string,options:p.array,onChange:p.func};const pe=t.memo((function(e){const{name:r,isRequired:i,onChange:a,fieldProps:n,inputProps:s,classNameGroupItem:l,hideMessage:m}=e;return t.createElement(c,{name:r,type:"checkbox"},(({input:e,meta:r})=>{const c=o((t=>{e.onChange(t),a&&a(t.target.checked,e.name)}),[a]);return t.createElement(U,Object.assign({className:f("form-field_type_switch","form__item_type_switch",l),fieldClassName:"form-switch",inputName:e.name,inputValue:e.checked,isRequired:i,metaActive:r.active,metaError:r.error,metaModifiedSinceLastSubmit:r.modifiedSinceLastSubmit,metaSubmitError:r.submitError,metaSubmitFailed:r.submitFailed,metaTouched:r.touched,metaValid:r.valid,hideMessage:m,tag:"label"},n),t.createElement(M,Object.assign({autoComplete:"nope",checked:e.checked,name:e.name,type:"checkbox",onBlur:e.onBlur,onChange:c,onFocus:e.onFocus},s)))}))}));pe.defaultProps={inputProps:{},fieldProps:{}},pe.propTypes={fieldProps:p.object,inputProps:p.object,isRequired:p.bool,name:p.string,onChange:p.func};const fe=t.memo((function(e){const{isRequired:r,name:i,fieldProps:o,inputProps:a,classNameGroupItem:n,hideMessage:s}=e;return t.createElement(c,{name:i},(({input:e,meta:i})=>t.createElement(U,Object.assign({className:f("form-field_type_textarea","form__item_type_textarea",n),fieldClassName:"form-textarea",inputName:e.name,inputValue:e.value,isRequired:r,metaActive:i.active,metaError:i.error,metaModifiedSinceLastSubmit:i.modifiedSinceLastSubmit,metaSubmitError:i.submitError,metaSubmitFailed:i.submitFailed,metaTouched:i.touched,metaValid:i.valid,hideMessage:s},o),t.createElement(w,Object.assign({autoComplete:"nope",name:e.name,value:e.value,onBlur:e.onBlur,onChange:e.onChange,onFocus:e.onFocus},a)))))}));fe.defaultProps={inputProps:{},fieldProps:{}},fe.propTypes={name:p.string.isRequired,isRequired:p.bool,fieldProps:p.object,inputProps:p.object};const be=(e,t)=>{const r=Object.keys(t).map((e=>e===s?"notification__item_status_error":`react-select-id_${e}-input`)),i=e.find((e=>e.name?l(t,e.name):r.includes(e.id))),o=Object.keys(t);if(!i&&o.length){let e;try{const t=o[0];t===s?e=document.querySelector("notification__item_status_error"):(e=document.querySelector(`#${t}-error`),e||(e=document.querySelector(`#id_${t}`)))}catch(e){console.warn(e)}e&&e.scrollIntoView({block:"center"})}return i&&i.scrollIntoView({block:"center"}),null},ge=V(null,be),he=(e,t)=>{const[r,i]=e,o=i.submitError,a=i.error;if("non_field_errors"===r)t.formState.error=a,t.formState.submitError=o;else if(r in t.fields){if(a){const e=Object.assign({},t.formState.errors,{[r]:a});t.fields[r].touched=!0,t.fields[r].error=a,t.formState.errors=e}if(o){const e=Object.assign({},t.formState.submitErrors,{[r]:o});t.fields[r].submitError=o,t.formState.submitErrors=e,t.formState.submitFailed=!0,t.formState.submitSucceeded=!1,t.formState.lastSubmittedValues=t.formState.values}}},_e=async(e,t)=>{try{return{success:!0,response:await S({url:e,method:"POST",data:t})}}catch(e){const t={};return"string"==typeof e.response?.data&&(t[s]="Something went wrong"),"object"==typeof e.response?.data&&Object.entries(e.response.data).forEach((([e,r])=>{t[e]=r[0]})),{success:!1,formErrors:t,error:e}}},xe={checkbox:"checkbox",custom:"custom",choice:"choice",code:"code",datePicker:"datePicker",dateRangePicker:"dateRangePicker",fileInput:"fileInput",group:"group",radioGroup:"radioGroup",segmented:"segmented",select:"select",switch:"switch",text:"text",textarea:"textarea"};function Te(e,r,i){switch(e.type){case xe.checkbox:return t.createElement(J,Object.assign({key:r.key},e,i));case xe.choice:return t.createElement(Q,Object.assign({key:r.key},e,i));case xe.code:return t.createElement(Y,Object.assign({key:r.key},e,i));case xe.switch:return t.createElement(pe,Object.assign({key:r.key},e,i));case xe.segmented:return t.createElement(ce,Object.assign({key:r.key},e,i));case xe.datePicker:return t.createElement(Z,Object.assign({key:r.key},e,i));case xe.fileInput:return t.createElement(ie,Object.assign({key:r.key},e,i));case xe.radioGroup:return t.createElement(me,Object.assign({key:r.key},e,i));case xe.select:return t.createElement(de,Object.assign({key:r.key},e,i));case xe.text:return t.createElement(ae,Object.assign({key:r.key},e,i));case xe.textarea:return t.createElement(fe,Object.assign({key:r.key},e,i));case xe.custom:return t.createElement(X,Object.assign({key:r.key},e,i));case xe.group:return t.createElement(oe,Object.assign({key:r.key},e,i),Object.entries(e.group).map((([t,r])=>Te({...r,hideMessage:e.hideMessage,classNameGroupItem:r.classNameGroupItem||"form__group-item"},{key:t+"_form_group"},i))))}}const ye=t.forwardRef((function(e,r){const{additionalProps:i,after:a,before:n,buttonDirection:s,buttonGap:l,buttonPadding:m,groupGap:c,className:p,config:b,description:g,descriptionSize:T,descriptionTextColor:y,descriptionTextWeight:v,disableFieldsAutoComplete:S,fieldsGap:E,formName:C,initialValues:N,initialValuesEqual:z,isLoading:j,loader:k,loaderSet:R,loaderFill:B,loaderItemFill:W,loaderText:M,language:w,mutators:V,onChangeFormValues:D,onClickSecondaryButton:A,onClickTertiaryButton:I,onSubmit:$,primaryButton:H,primaryButtonLabel:K,secondaryButton:U,secondaryButtonLabel:J,primaryButtonFill:Q,primaryButtonFillHover:X,secondaryButtonFill:Y,secondaryButtonFillHover:Z,primaryButtonSize:ee,primaryButtonLabelTextColor:te,primaryButtonLabelSize:re,primaryButtonLabelTextWeight:ie,secondaryButtonSize:oe,secondaryButtonLabelTextColor:ae,secondaryButtonLabelSize:ne,secondaryButtonLabelTextWeight:se,tertiaryButton:le,tertiaryButtonFill:me,tertiaryButtonFillHover:ce,tertiaryButtonSize:ue,tertiaryButtonLabelTextColor:de,tertiaryButtonLabelSize:pe,tertiaryButtonLabelTextWeight:fe,tertiaryButtonLabel:be,set:he,type:_e,buttonJustifyContent:xe,title:ye,notificationType:ve,buttonFill:Se,titleTextSize:Ee,titleTextColor:Ce,titleTextWeight:Ne,validationSchema:ze,dataTour:Pe,dataTourButtons:Fe,dataTourPrimaryButton:je,dataTourSecondaryButton:ke,dataTourTertiaryButton:Re}=e,Be=G(ze,w),We=o((e=>{r&&(r.current=e)}),[r]),Me=_(e,{prefix:"fill_",propsKey:"fill"}),we=_(e,{prefix:"direction_",propsKey:"direction"}),Le=_(e,{prefix:"shape_",propsKey:"shape"}),qe=_(e,{prefix:"elevation_",propsKey:"elevation"}),{styles:Oe}=x(e);return t.createElement(u,{decorators:[ge],initialValues:N,initialValuesEqual:z,mutators:V,render:({handleSubmit:e,submitError:r,modifiedSinceLastSubmit:o,form:u})=>t.createElement("form",{style:Oe,className:f(p,"form",he&&`form_set_${he}`,_e&&`form_type_${_e}`,we,Me,Le,qe),name:C,"data-tour":Pe,ref:()=>We(u),onSubmit:e,autoComplete:S?"off":void 0,autoCorrect:S?"off":void 0,autoCapitalize:S?"off":void 0,spellCheck:S?"false":void 0},n,ye&&t.createElement(F,{className:"form__title",size:Ee,textColor:Ce,textWeight:Ne},ye),g&&t.createElement(h,{className:"form__description",size:T,textColor:y,textWeight:v},g),r&&!o&&t.createElement("div",{className:f("notification","form-notification",ve?`form-notification_type_${ve}`:"form-notification_type_global")},t.createElement(O,{className:"form-notification__item",titleTextSize:"h6",title:u.getState().submitError,set:"form",status:"error"})),D&&t.createElement(d,{subscription:{values:!0},onChange:D}),Boolean(Object.keys(b).length)&&t.createElement(q,{direction:"vertical",gap:E||c,className:"form__wrapper"},Object.keys(b).map((e=>Te(b[e],{key:e},i[b[e].name]))),j&&(k||t.createElement(P,{className:"form__loader",set:R,fill:B,itemFill:W,text:M}))),(K||H||J||U||le||be)&&t.createElement(q,{fill:Se,justifyContent:xe,direction:s,padding:m,gap:l,className:"form__button",dataTour:Fe},K?t.createElement(L,{width:"fill",className:"form__button-item",fill:Q,fillHover:X,size:ee,labelTextColor:te,labelSize:re,labelTextWeight:ie,label:K,dataTour:je}):H,J?t.createElement(L,{width:"fill",className:"form__button-item",fill:Y,fillHover:Z,size:oe,labelTextColor:ae,labelSize:ne,labelTextWeight:se,label:J,onClick:A,dataTour:ke}):U,be?t.createElement(L,{width:"fill",className:"form__button-item",fill:me,fillHover:ce,size:ue,labelTextColor:de,labelSize:pe,labelTextWeight:fe,label:be,onClick:I,dataTour:Re}):le),a),subscription:{submitting:!0,pristine:!0,modifiedSinceLastSubmit:!0,submitError:!0},validate:Be,onSubmit:$})}));ye.propTypes={additionalProps:p.object,after:p.any,before:p.any,buttonGap:p.string,className:p.string,config:p.object,description:p.string,descriptionSize:p.string,descriptionTextColor:p.string,descriptionTextWeight:p.string,disableFieldsAutoComplete:p.string,fieldsGap:p.string,formName:p.string,initialValues:p.any,initialValuesEqual:p.any,language:p.string,isLoading:p.bool,loaderText:p.string,mutators:p.any,onChangeFormValues:p.func,onClickSecondaryButton:p.func,onSubmit:p.func,primaryButton:p.string,primaryButtonFill:p.string,primaryButtonLabel:p.string,secondaryButton:p.string,secondaryButtonFill:p.string,secondaryButtonLabel:p.string,set:p.string,title:p.string,titleSize:p.string,titleTextColor:p.string,titleTextWeight:p.string,validationSchema:p.object},ye.defaultProps={additionalProps:{},isLoading:!1,loaderSet:"simple",loaderFill:"surfacePrimary",loaderItemFill:"surfaceItemAccent",language:"en",titleSize:"h1",buttonDirection:"vertical",direction:"vertical",disableFieldsAutoComplete:!1};export{J as Checkbox,Q as ChoiceField,Y as CodeField,X as CustomField,Z as DatePickerField,U as FieldWrapper,K as FieldWrapperBase,ie as FileInput,ye as FinalForm,oe as Group,ae as InputField,me as RadioGroup,ce as SegmentedField,de as SelectField,pe as Switch,fe as Textarea,I as addRequiredFieldsParamToSchema,A as emailValidation,be as focusOnError,ge as focusOnErrorDecorator,xe as formTypes,Te as generateField,D as phoneValidation,_e as sendFormDataToServer,he as setErrorsMutator,G as useYupValidationSchema};
1
+ import { isPossiblePhoneNumber } from 'libphonenumber-js';
2
+ import React, { useMemo, useEffect, useCallback, useState } from 'react';
3
+ import { setIn, FORM_ERROR, getIn } from 'final-form';
4
+ import { useForm, Field, Form, FormSpy } from 'react-final-form';
5
+ export { Field, useForm, useFormState } from 'react-final-form';
6
+ import PropTypes from 'prop-types';
7
+ import clsx from 'clsx';
8
+ import { Checkbox } from '@itcase/ui/components/Checkbox';
9
+ import { Divider } from '@itcase/ui/components/Divider';
10
+ import { Text } from '@itcase/ui/components/Text';
11
+ import { useDeviceTargetClass } from '@itcase/ui/hooks/useDeviceTargetClass';
12
+ import { useStyles } from '@itcase/ui/hooks/useStyles';
13
+ import { Choice } from '@itcase/ui/components/Choice';
14
+ import { Code } from '@itcase/ui/components/Code';
15
+ import { DatePickerInput } from '@itcase/ui/components/DatePicker';
16
+ import axios from 'axios';
17
+ import { useDropzone } from 'react-dropzone';
18
+ import { fromEvent } from 'file-selector';
19
+ import castArray from 'lodash/castArray';
20
+ import { createFileFromDataURL } from '@itcase/common';
21
+ import { Loader } from '@itcase/ui/components/Loader';
22
+ import { Title } from '@itcase/ui/components/Title';
23
+ import { Input } from '@itcase/ui/components/Input';
24
+ import { Icon } from '@itcase/ui/components/Icon';
25
+ import { RadioButton } from '@itcase/ui/components/RadioButton';
26
+ import { Segmented } from '@itcase/ui/components/Segmented';
27
+ import { Select } from '@itcase/ui/components/Select';
28
+ import { Switch } from '@itcase/ui/components/Switch';
29
+ import { Textarea } from '@itcase/ui/components/Textarea';
30
+ import { Button } from '@itcase/ui/components/Button';
31
+ import { Group as Group$1 } from '@itcase/ui/components/Group';
32
+ import { NotificationItem } from '@itcase/ui/components/Notification';
33
+ import createDecorator from 'final-form-focus';
34
+
35
+ const phoneValidation = (value, context) => {
36
+ if (!value) {
37
+ return true;
38
+ }
39
+ return isPossiblePhoneNumber(value, 'RU');
40
+ };
41
+ const emailValidation = (value, context) => {
42
+ // from https://emailregex.com/
43
+ if (!value) {
44
+ return true;
45
+ }
46
+ // eslint-disable-next-line
47
+ const regexp = /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]{2,}(?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/;
48
+ return regexp.test(String(value).toLowerCase());
49
+ };
50
+ const addRequiredFieldsParamToSchema = schema => {
51
+ const fields = Object.entries(schema.fields);
52
+ schema.requiredFields = fields.reduce((list, [fieldName, validationProps]) => {
53
+ if (validationProps.exclusiveTests?.required) {
54
+ list.push(fieldName);
55
+ }
56
+ return list;
57
+ }, []);
58
+ return schema;
59
+ };
60
+
61
+ /**
62
+ * Sets the `innerError.message` in an `errors` object at the key
63
+ * defined by `innerError.path`.
64
+ * @param {Object} errors The object to set the error in.
65
+ * @param {{ path: string, message: string }} innerError A `yup` field error.
66
+ * @returns {Object} The result of setting the new error message onto `errors`.
67
+ */
68
+ const setInError = (errors, innerError) => {
69
+ return setIn(errors, innerError.path, innerError.message);
70
+ };
71
+
72
+ /**
73
+ * Empty object map with no prototype. Used as default
74
+ * value for reducing the `err.inner` array of errors
75
+ * from a `yup~ValidationError`.
76
+ */
77
+ const emptyObj = Object.create(null);
78
+
79
+ /**
80
+ * Takes a `yup` validation schema and returns a function that expects
81
+ * a map of values to validate. If the validation passes, the function resolves to `undefined`
82
+ * (signalling that the values are valid). If the validation doesn't pass, it resolves
83
+ * to a map of invalid field names to errors.
84
+ * @param {import('yup').ObjectSchema} schema `yup` schema definition.
85
+ * @returns {(values: Object) => Promise<?Object>} An async function that expects some `values`
86
+ * and resolves to either `undefined` or a map of field names to error messages.
87
+ */
88
+
89
+ const makeValidate = schema => {
90
+ return async function validate(values) {
91
+ try {
92
+ await schema.validate(values, {
93
+ abortEarly: false
94
+ });
95
+ } catch (error) {
96
+ if (error.inner) {
97
+ return error.inner.reduce(setInError, emptyObj);
98
+ } else {
99
+ console.warn('itcase-forms schema.validate error: An error not related to the form occurred during validation. Validation ignored.');
100
+ }
101
+ }
102
+ };
103
+ };
104
+ function useYupValidationSchema(schema, language) {
105
+ const validate = useMemo(() => schema && makeValidate(schema), [schema, language]);
106
+ return validate;
107
+ }
108
+
109
+ function FieldWrapperBase(props) {
110
+ const {
111
+ after,
112
+ afterItem,
113
+ before,
114
+ beforeItem,
115
+ children,
116
+ className,
117
+ desc,
118
+ descTextSize,
119
+ descTextColor,
120
+ descTextWidth,
121
+ divider,
122
+ dividerDirection,
123
+ dividerFill,
124
+ dividerSize,
125
+ dividerWidth,
126
+ fieldClassName,
127
+ id,
128
+ inputName,
129
+ inputValue,
130
+ isRequired,
131
+ label,
132
+ labelTextSize,
133
+ labelTextColor,
134
+ labelTextWidth,
135
+ errorMessageTextSize,
136
+ errorMessageTextWeight,
137
+ errorMessageTextColor,
138
+ message,
139
+ messageTextSize,
140
+ messageTextColor,
141
+ messageTextWeight,
142
+ metaActive,
143
+ metaError,
144
+ metaModifiedSinceLastSubmit,
145
+ metaSubmitError,
146
+ metaSubmitFailed,
147
+ metaTouched,
148
+ metaValid,
149
+ set,
150
+ type,
151
+ hideMessage,
152
+ isHidden,
153
+ tag: Tag,
154
+ dataTour,
155
+ showErrorsOnSubmit
156
+ } = props;
157
+ const error = metaError || !metaModifiedSinceLastSubmit && metaSubmitError || false;
158
+ const showError = useMemo(() => {
159
+ if (showErrorsOnSubmit) {
160
+ return metaSubmitFailed && metaTouched && error;
161
+ } else {
162
+ return metaTouched && error;
163
+ }
164
+ }, [showErrorsOnSubmit, metaSubmitFailed, metaTouched, error]);
165
+ const showValid = useMemo(() => {
166
+ const hasValue = Array.isArray(inputValue) ? inputValue.length : inputValue;
167
+ const isModifiedAfterSubmit = !metaError && metaSubmitError && metaModifiedSinceLastSubmit;
168
+ return hasValue && (metaValid || isModifiedAfterSubmit);
169
+ }, [inputValue, metaValid, metaError, metaSubmitError, metaModifiedSinceLastSubmit]);
170
+ const formFieldClass = useMemo(() => clsx(className, showError && 'form__item_state_error', showValid && 'form__item_state_success', isRequired && 'form__item_state_required', metaActive && 'form__item_state_focus', inputValue && 'form__item_state_filled'), [className, showError, showValid, isRequired, metaActive, inputValue]);
171
+ const fieldClass = useMemo(() => clsx(fieldClassName, showError && `${fieldClassName}_state_error`, showValid && `${fieldClassName}_state_success`, metaActive && `${fieldClassName}_state_focus`, inputValue && `${fieldClassName}_state_filled`), [fieldClassName, showError, showValid, metaActive, inputValue]);
172
+ const sizeClass = useDeviceTargetClass(props, {
173
+ prefix: 'form-field_size_',
174
+ propsKey: 'size'
175
+ });
176
+ const fillClass = useDeviceTargetClass(props, {
177
+ prefix: 'fill_',
178
+ propsKey: 'fill'
179
+ });
180
+ const inputFillClass = useDeviceTargetClass(props, {
181
+ prefix: 'fill_',
182
+ propsKey: 'inputFill'
183
+ });
184
+ const shapeClass = useDeviceTargetClass(props, {
185
+ prefix: 'form-field_shape_',
186
+ propsKey: 'shape'
187
+ });
188
+ const inputShapeClass = useDeviceTargetClass(props, {
189
+ prefix: 'form-field__item-value_shape_',
190
+ propsKey: 'inputShape'
191
+ });
192
+ const directionClass = useDeviceTargetClass(props, {
193
+ prefix: 'direction_',
194
+ propsKey: 'direction'
195
+ });
196
+ const widthClass = useDeviceTargetClass(props, {
197
+ prefix: 'width_',
198
+ propsKey: 'width'
199
+ });
200
+ const {
201
+ styles: formFieldStyles
202
+ } = useStyles(props);
203
+ return /*#__PURE__*/React.createElement(Tag, {
204
+ className: clsx(formFieldClass, 'form__item', 'form-field', type && `form-field_type_${type}`, set && `form-field_set_${set}`, sizeClass, fillClass, shapeClass, isHidden && `form-field_state_hidden`, directionClass, widthClass),
205
+ "data-tour": dataTour,
206
+ style: formFieldStyles
207
+ }, before, label && /*#__PURE__*/React.createElement("div", {
208
+ htmlFor: id,
209
+ className: "form-field__label"
210
+ }, /*#__PURE__*/React.createElement(Text, {
211
+ size: labelTextSize,
212
+ textWeight: labelTextWidth,
213
+ textColor: labelTextColor
214
+ }, label)), desc && /*#__PURE__*/React.createElement("div", {
215
+ className: "form-field__desc"
216
+ }, /*#__PURE__*/React.createElement(Text, {
217
+ size: descTextSize,
218
+ textWeight: descTextWidth,
219
+ textColor: descTextColor
220
+ }, desc)), /*#__PURE__*/React.createElement("div", {
221
+ className: clsx('form-field__content', inputFillClass, inputShapeClass)
222
+ }, /*#__PURE__*/React.createElement("div", {
223
+ className: clsx('form-field__content-inner', fieldClass)
224
+ }, beforeItem, children, afterItem), divider && /*#__PURE__*/React.createElement(Divider, {
225
+ className: "form-field__item-divider",
226
+ width: dividerWidth,
227
+ direction: dividerDirection,
228
+ size: dividerSize,
229
+ fill: dividerFill
230
+ })), !hideMessage && /*#__PURE__*/React.createElement("div", {
231
+ className: "form-field__message"
232
+ }, Boolean(showError) && /*#__PURE__*/React.createElement(Text, {
233
+ className: "form-field__message-item form-field__message-item_type-error",
234
+ size: errorMessageTextSize,
235
+ textWeight: errorMessageTextWeight,
236
+ textColor: errorMessageTextColor,
237
+ id: `${inputName}-error`
238
+ }, error), Boolean(message) && !showError && /*#__PURE__*/React.createElement(Text, {
239
+ className: "form-field__message-item form-field__message-item_type_message",
240
+ size: messageTextSize,
241
+ textWeight: messageTextWeight,
242
+ textColor: messageTextColor
243
+ }, message), Boolean(!showError) && Boolean(!message) && /*#__PURE__*/React.createElement(Text, {
244
+ className: "form-field__message-item form-field__message-item_type_message",
245
+ size: messageTextSize
246
+ }, '\u00A0')), after);
247
+ }
248
+ FieldWrapperBase.defaultProps = {
249
+ tag: 'div',
250
+ type: 'normal',
251
+ errorMessageTextSize: 's',
252
+ errorMessageTextColor: 'errorTextSecondary'
253
+ };
254
+ FieldWrapperBase.propTypes = {
255
+ after: PropTypes.any,
256
+ afterItem: PropTypes.any,
257
+ autoComplete: PropTypes.string,
258
+ before: PropTypes.any,
259
+ beforeItem: PropTypes.any,
260
+ children: PropTypes.any,
261
+ className: PropTypes.string,
262
+ desc: PropTypes.string,
263
+ descTextSize: PropTypes.string,
264
+ descTextColor: PropTypes.string,
265
+ descTextWidth: PropTypes.string,
266
+ dividerDirection: PropTypes.string,
267
+ dividerFill: PropTypes.string,
268
+ dividerSize: PropTypes.string,
269
+ dividerWidth: PropTypes.string,
270
+ fieldClassName: PropTypes.string,
271
+ id: PropTypes.string,
272
+ inputName: PropTypes.string,
273
+ inputOnBlur: PropTypes.func,
274
+ inputOnChange: PropTypes.func,
275
+ inputOnFocus: PropTypes.func,
276
+ inputValue: PropTypes.any,
277
+ isRequired: PropTypes.bool,
278
+ itemType: PropTypes.string,
279
+ label: PropTypes.any,
280
+ labelTextSize: PropTypes.string,
281
+ labelTextColor: PropTypes.string,
282
+ labelTextWidth: PropTypes.string,
283
+ errorMessageTextSize: PropTypes.string,
284
+ errorMessageTextWidth: PropTypes.string,
285
+ errorMessageTextColor: PropTypes.string,
286
+ message: PropTypes.string,
287
+ messageSize: PropTypes.string,
288
+ messageTextColor: PropTypes.string,
289
+ messageTextWidth: PropTypes.string,
290
+ metaActive: PropTypes.bool,
291
+ metaError: PropTypes.string,
292
+ metaModifiedSinceLastSubmit: PropTypes.bool,
293
+ metaSubmitError: PropTypes.string,
294
+ metaSubmitFailed: PropTypes.bool,
295
+ metaTouched: PropTypes.bool,
296
+ metaValid: PropTypes.bool,
297
+ set: PropTypes.string,
298
+ showErrorsOnSubmit: PropTypes.bool,
299
+ type: PropTypes.string
300
+ };
301
+ function FieldWrapper(props) {
302
+ const {
303
+ inputName
304
+ } = props;
305
+ const {
306
+ change
307
+ } = useForm(); // , mutators
308
+
309
+ useEffect(() => {
310
+ return () => {
311
+ change(inputName, undefined);
312
+ };
313
+ }, []);
314
+ return /*#__PURE__*/React.createElement(FieldWrapperBase, props);
315
+ }
316
+ FieldWrapper.propTypes = {
317
+ autoComplete: PropTypes.string,
318
+ children: PropTypes.any,
319
+ className: PropTypes.string,
320
+ fieldClassName: PropTypes.string,
321
+ hint: PropTypes.string,
322
+ inputName: PropTypes.string,
323
+ inputOnBlur: PropTypes.func,
324
+ inputOnChange: PropTypes.func,
325
+ inputOnFocus: PropTypes.func,
326
+ inputValue: PropTypes.any,
327
+ isRequired: PropTypes.bool,
328
+ itemType: PropTypes.string,
329
+ label: PropTypes.any,
330
+ metaActive: PropTypes.bool,
331
+ metaError: PropTypes.string,
332
+ metaModifiedSinceLastSubmit: PropTypes.bool,
333
+ metaSubmitError: PropTypes.string,
334
+ metaSubmitFailed: PropTypes.bool,
335
+ metaTouched: PropTypes.bool,
336
+ metaValid: PropTypes.bool,
337
+ showErrorsOnSubmit: PropTypes.bool
338
+ };
339
+
340
+ const CheckboxField = /*#__PURE__*/React.memo(function CheckboxField(props) {
341
+ const {
342
+ name,
343
+ isRequired,
344
+ onChange,
345
+ fieldProps,
346
+ inputProps,
347
+ classNameGroupItem,
348
+ hideMessage
349
+ } = props;
350
+ return /*#__PURE__*/React.createElement(Field, {
351
+ name: name,
352
+ type: "checkbox"
353
+ }, ({
354
+ input,
355
+ meta
356
+ }) => {
357
+ const onChangeField = useCallback(event => {
358
+ input.onChange(event);
359
+ if (onChange) {
360
+ onChange(event.target.checked, input.name);
361
+ }
362
+ }, [onChange]);
363
+ return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
364
+ className: clsx('form-field_type_checkbox', 'form__item_type_checkbox', classNameGroupItem),
365
+ fieldClassName: "form-checkbox",
366
+ inputName: input.name,
367
+ inputValue: input.checked,
368
+ isRequired: isRequired,
369
+ metaActive: meta.active,
370
+ metaError: meta.error,
371
+ metaModifiedSinceLastSubmit: meta.modifiedSinceLastSubmit,
372
+ metaSubmitError: meta.submitError,
373
+ metaSubmitFailed: meta.submitFailed,
374
+ metaTouched: meta.touched,
375
+ metaValid: meta.valid,
376
+ tag: "label",
377
+ hideMessage: hideMessage
378
+ }, fieldProps), /*#__PURE__*/React.createElement(Checkbox, Object.assign({
379
+ autoComplete: "nope",
380
+ checked: input.checked,
381
+ name: input.name,
382
+ type: "checkbox",
383
+ onBlur: input.onBlur,
384
+ onChange: onChangeField,
385
+ onFocus: input.onFocus
386
+ }, inputProps)));
387
+ });
388
+ });
389
+ CheckboxField.defaultProps = {
390
+ inputProps: {},
391
+ fieldProps: {}
392
+ };
393
+ CheckboxField.propTypes = {
394
+ fieldProps: PropTypes.object,
395
+ inputProps: PropTypes.object,
396
+ isRequired: PropTypes.bool,
397
+ name: PropTypes.string,
398
+ onChange: PropTypes.func
399
+ };
400
+
401
+ const ChoiceField = /*#__PURE__*/React.memo(function ChoiceField(props) {
402
+ const {
403
+ options,
404
+ classNameGroupItem,
405
+ fieldProps,
406
+ inputProps,
407
+ isMultiple,
408
+ isRequired,
409
+ initialValue,
410
+ label,
411
+ name,
412
+ messageType,
413
+ hideMessage,
414
+ placeholder
415
+ } = props;
416
+ const {
417
+ change
418
+ } = useForm();
419
+ return /*#__PURE__*/React.createElement(Field, {
420
+ name: name,
421
+ initialValue: initialValue
422
+ }, ({
423
+ input,
424
+ meta
425
+ }) => {
426
+ const activeOption = useMemo(() => {
427
+ const emptyOption = {
428
+ value: null,
429
+ label: null
430
+ };
431
+ if (input.value) {
432
+ const currentOption = options.find(option => option.value === input.value);
433
+ return currentOption || emptyOption;
434
+ }
435
+ return emptyOption;
436
+ }, [input.value]);
437
+ const setActiveSegment = useCallback(option => {
438
+ change(name, option.value);
439
+ }, [change]);
440
+ return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
441
+ className: clsx('form-field_type_choice', 'form__item_type_choice', classNameGroupItem),
442
+ fieldClassName: "form-choice",
443
+ inputName: input.name,
444
+ inputValue: input.value || [],
445
+ isRequired: isRequired,
446
+ label: label,
447
+ messageType: messageType,
448
+ metaActive: meta.active,
449
+ metaError: meta.error,
450
+ metaModifiedSinceLastSubmit: meta.modifiedSinceLastSubmit,
451
+ metaSubmitError: meta.submitError,
452
+ metaSubmitFailed: meta.submitFailed,
453
+ metaTouched: meta.touched,
454
+ metaValid: meta.valid,
455
+ hideMessage: hideMessage
456
+ }, fieldProps), /*#__PURE__*/React.createElement(Choice, Object.assign({
457
+ className: clsx(meta.active && 'form-choice_state_focus', meta.error && meta.touched && 'form-choice_state_error'),
458
+ options: options,
459
+ inputName: input.name,
460
+ inputValue: input.value || [],
461
+ isMultiple: isMultiple,
462
+ isRequired: isRequired,
463
+ placeholder: placeholder,
464
+ active: activeOption,
465
+ setActiveSegment: setActiveSegment
466
+ }, inputProps)));
467
+ });
468
+ });
469
+ ChoiceField.propTypes = {
470
+ options: PropTypes.array.isRequired,
471
+ name: PropTypes.string.isRequired,
472
+ className: PropTypes.string,
473
+ inputClass: PropTypes.string,
474
+ isMultiple: PropTypes.bool,
475
+ isRequired: PropTypes.bool,
476
+ label: PropTypes.string,
477
+ placeholder: PropTypes.string
478
+ };
479
+
480
+ const CustomField = /*#__PURE__*/React.memo(function CustomField(props) {
481
+ const {
482
+ Component,
483
+ isRequired,
484
+ name,
485
+ fieldProps,
486
+ classNameGroupItem,
487
+ hideMessage
488
+ } = props;
489
+ return /*#__PURE__*/React.createElement(Field, {
490
+ name: name
491
+ }, ({
492
+ input,
493
+ meta
494
+ }) => /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
495
+ className: clsx('form-field_type_custom', 'form__item_type_custom', classNameGroupItem),
496
+ fieldClassName: 'form-custom',
497
+ inputName: input.name,
498
+ inputValue: input.value,
499
+ isRequired: isRequired,
500
+ metaActive: meta.active,
501
+ metaError: meta.error,
502
+ metaModifiedSinceLastSubmit: meta.modifiedSinceLastSubmit,
503
+ metaSubmitError: meta.submitError,
504
+ metaSubmitFailed: meta.submitFailed,
505
+ metaTouched: meta.touched,
506
+ metaValid: meta.valid,
507
+ hideMessage: hideMessage
508
+ }, fieldProps), /*#__PURE__*/React.createElement(Component, Object.assign({}, props, {
509
+ input: input,
510
+ meta: meta
511
+ }))));
512
+ });
513
+ CustomField.defaultProps = {
514
+ inputProps: {},
515
+ fieldProps: {}
516
+ };
517
+ CustomField.propTypes = {
518
+ name: PropTypes.string.isRequired,
519
+ isRequired: PropTypes.bool,
520
+ fieldProps: PropTypes.object,
521
+ inputProps: PropTypes.object
522
+ };
523
+
524
+ const CodeField = /*#__PURE__*/React.memo(function CodeField(props) {
525
+ const {
526
+ isRequired,
527
+ name,
528
+ fieldProps,
529
+ inputProps,
530
+ classNameGroupItem,
531
+ hideMessage
532
+ } = props;
533
+ return /*#__PURE__*/React.createElement(Field, {
534
+ name: name
535
+ }, ({
536
+ input,
537
+ meta
538
+ }) => /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
539
+ className: clsx('form-field_type_code', 'form__item_type_code', classNameGroupItem),
540
+ fieldClassName: 'form-code',
541
+ inputName: input.name,
542
+ inputValue: input.value,
543
+ isRequired: isRequired,
544
+ metaActive: meta.active,
545
+ metaError: meta.error,
546
+ metaModifiedSinceLastSubmit: meta.modifiedSinceLastSubmit,
547
+ metaSubmitError: meta.submitError,
548
+ metaSubmitFailed: meta.submitFailed,
549
+ metaTouched: meta.touched,
550
+ metaValid: meta.valid,
551
+ hideMessage: hideMessage
552
+ }, fieldProps), /*#__PURE__*/React.createElement(Code, Object.assign({
553
+ autoComplete: "nope",
554
+ name: input.name,
555
+ value: input.value,
556
+ onBlur: input.onBlur,
557
+ onChange: input.onChange,
558
+ onFocus: input.onFocus
559
+ }, inputProps))));
560
+ });
561
+ CodeField.defaultProps = {
562
+ inputProps: {},
563
+ fieldProps: {}
564
+ };
565
+ CodeField.propTypes = {
566
+ name: PropTypes.string.isRequired,
567
+ isRequired: PropTypes.bool,
568
+ fieldProps: PropTypes.object,
569
+ inputProps: PropTypes.object
570
+ };
571
+
572
+ function DatePickerField(props) {
573
+ const {
574
+ isRequired,
575
+ fieldProps,
576
+ inputProps,
577
+ datePickerProps,
578
+ name,
579
+ iconSize,
580
+ iconBorder,
581
+ iconBorderHover,
582
+ iconFill,
583
+ iconFillHover,
584
+ iconRevealableShow,
585
+ iconRevealableHide,
586
+ iconShape,
587
+ hideMessage,
588
+ onChange,
589
+ classNameGroupItem
590
+ } = props;
591
+ return /*#__PURE__*/React.createElement(Field, {
592
+ name: name
593
+ }, ({
594
+ input,
595
+ meta
596
+ }) => {
597
+ const onChangeField = useCallback(value => {
598
+ input.onChange(value);
599
+ if (onChange) {
600
+ onChange(value, input.name);
601
+ }
602
+ }, [onChange]);
603
+ return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
604
+ className: clsx('form-field_type_datepicker', 'form__item_type_datepicker', classNameGroupItem),
605
+ fieldClassName: "form-datepicker",
606
+ inputName: input.name,
607
+ inputValue: input.value || '',
608
+ isRequired: isRequired,
609
+ metaActive: meta.active,
610
+ metaError: meta.error,
611
+ metaModifiedSinceLastSubmit: meta.modifiedSinceLastSubmit,
612
+ metaSubmitError: meta.submitError,
613
+ metaSubmitFailed: meta.submitFailed,
614
+ metaTouched: meta.touched,
615
+ metaValid: meta.valid,
616
+ hideMessage: hideMessage
617
+ }, fieldProps), /*#__PURE__*/React.createElement(DatePickerInput, {
618
+ name: input.name,
619
+ value: input.value || '',
620
+ onBlur: input.onBlur,
621
+ onChange: onChangeField,
622
+ onFocus: input.onFocus,
623
+ inputProps: inputProps,
624
+ datePickerProps: datePickerProps
625
+ }));
626
+ });
627
+ }
628
+ DatePickerField.defaultProps = {
629
+ inputProps: {},
630
+ fieldProps: {}
631
+ };
632
+ DatePickerField.propTypes = {
633
+ fieldProps: PropTypes.object,
634
+ inputProps: PropTypes.object,
635
+ isRequired: PropTypes.bool,
636
+ name: PropTypes.string.isRequired,
637
+ onChange: PropTypes.func
638
+ };
639
+
640
+ async function getFileByURL(url) {
641
+ try {
642
+ const response = await axios({
643
+ url: `/api/${url}/`,
644
+ responseType: 'blob'
645
+ });
646
+ const blobObject = response.data;
647
+ const dirtyFilename = response.headers['content-disposition']?.split('filename=')[1];
648
+ // Remove double quotes
649
+ let filename = dirtyFilename?.substring(1).slice(0, -1);
650
+ if (!filename) {
651
+ const typeParts = blobObject.type.split('/');
652
+ const fileType = typeParts[typeParts.length - 1];
653
+ filename = `${new Date().getTime()}.${fileType}`;
654
+ }
655
+ return new File([blobObject], filename, {
656
+ type: blobObject.type
657
+ });
658
+ } catch (error) {
659
+ console.log('error: ', error);
660
+ return null;
661
+ }
662
+ }
663
+ async function convertToFiles(inputValue, isPreviews) {
664
+ const newFiles = [];
665
+ for await (const value of castArray(inputValue)) {
666
+ let newFile = null;
667
+
668
+ // Download image by url and save as File instance
669
+ const isURL = typeof value === 'string' && value.includes('/');
670
+ if (value.image || isURL) {
671
+ newFile = await getFileByURL(value.image || value);
672
+ if (newFile) {
673
+ setFileDataURL(newFile);
674
+ }
675
+ }
676
+
677
+ // Convert dataURL to File instance
678
+ if (value.dataURL) {
679
+ newFile = createFileFromDataURL(value.name || value.path, value.dataURL);
680
+ newFile.dataURL = value.dataURL;
681
+ }
682
+
683
+ // Save new File to state
684
+ if (newFile) {
685
+ newFile.id = value.id;
686
+ if (isPreviews) {
687
+ newFile.preview = URL.createObjectURL(newFile);
688
+ }
689
+ newFiles.push(newFile);
690
+ }
691
+
692
+ // else if (value) {
693
+ // newFiles.push({
694
+ // name: value,
695
+ // error: 'File is unavailable',
696
+ // })
697
+ // }
698
+ }
699
+
700
+ return newFiles;
701
+ }
702
+ function setFileDataURL(file, resolve) {
703
+ resolve = resolve || (() => {});
704
+ // Init reader and save his file
705
+ const reader = new FileReader();
706
+ reader._readedFile = file;
707
+
708
+ // Set handlers
709
+ reader.onabort = () => resolve();
710
+ reader.onerror = () => resolve();
711
+ reader.onload = event => {
712
+ event.target._readedFile.dataURL = reader.result;
713
+ resolve();
714
+ };
715
+ // Run reader
716
+ if (file instanceof File) {
717
+ reader.readAsDataURL(file);
718
+ } else {
719
+ resolve();
720
+ }
721
+ }
722
+ const FileInputDropzone = /*#__PURE__*/React.memo(function FileInputDropzone(props) {
723
+ const {
724
+ inputName,
725
+ size,
726
+ className,
727
+ fileErrorText,
728
+ hintTitleTextSize,
729
+ removeThumbTextSize,
730
+ removeThumbTextColor,
731
+ removeThumbTextWeight,
732
+ thumbNameTextSize,
733
+ thumbNameTextColor,
734
+ removeThumbTextHoverColor,
735
+ thumbNameTextWrap,
736
+ thumbNameTextWeight,
737
+ hintTitleTextColor,
738
+ hintTitleTextWrap,
739
+ thumbColumn,
740
+ hintTitleTextWeight,
741
+ hintDescriptionTextSize,
742
+ hintDescriptionTextColor,
743
+ hintDescriptionTextWrap,
744
+ hintDescriptionTextWeight,
745
+ errorMessageTextSize,
746
+ errorMessageTextWeight,
747
+ errorMessageTextColor,
748
+ inputValue,
749
+ maxFiles,
750
+ maxSize,
751
+ removeThumbText,
752
+ hintTitle,
753
+ hintDescription,
754
+ isShowFilename,
755
+ isPreviews,
756
+ loadingText,
757
+ dropzoneProps = {},
758
+ onAddFiles,
759
+ onDeleteFile
760
+ } = props;
761
+ const [fileError, setFileError] = useState('');
762
+ const [fileIsLoading, setFileIsLoading] = useState(false);
763
+ // State with instances of "File" type
764
+ const [files, setFiles] = useState(inputValue ? castArray(inputValue) : []);
765
+
766
+ // Save to mobx state
767
+ const {
768
+ change
769
+ } = useForm();
770
+ const changeFormState = useCallback(newFiles => {
771
+ // If max files in dropzone is 1 - return file as it self, else as array of files
772
+ // ps: for old projects compatibility
773
+ const toSave = dropzoneProps.maxFiles == 1 ? newFiles[0] : newFiles;
774
+ change(inputName, toSave);
775
+ return toSave;
776
+ }, [dropzoneProps, change]);
777
+
778
+ // Create dropzone options
779
+ const {
780
+ getRootProps,
781
+ getInputProps
782
+ } = useDropzone({
783
+ maxSize: maxSize || 10485760,
784
+ // 10mb
785
+ maxFiles: maxFiles || 5,
786
+ // accept: { 'image/*': [] },
787
+ ...dropzoneProps,
788
+ getFilesFromEvent: async event => {
789
+ const result = await fromEvent(event);
790
+ const newFiles = result.filter(item => item instanceof File);
791
+ // Add exists and new files to accepted(or rejected)
792
+ return [...files, ...newFiles];
793
+ },
794
+ onDropAccepted: (acceptedFiles, event) => {
795
+ // If dropped files has accepted and we need a previews
796
+ if (isPreviews) {
797
+ // Add preview to every file
798
+ acceptedFiles.forEach(file => {
799
+ if (!file.error) {
800
+ file.preview = URL.createObjectURL(file);
801
+ }
802
+ });
803
+ }
804
+ // Save to form data (including empty when files are not valid)
805
+ setFiles(acceptedFiles);
806
+ setFileError('');
807
+
808
+ // Save DataURL for all files
809
+ const readerPromisesList = acceptedFiles.map(file => {
810
+ return new Promise(resolve => setFileDataURL(file, resolve));
811
+ });
812
+ // Save files to form values
813
+ Promise.all(readerPromisesList).then(() => {
814
+ const filesToSave = changeFormState(acceptedFiles);
815
+ if (onAddFiles) {
816
+ onAddFiles(filesToSave, inputName);
817
+ }
818
+ });
819
+ },
820
+ onDropRejected: (rejectedFiles, event) => {
821
+ // If dropped files has rejected
822
+ if (rejectedFiles.length) {
823
+ const firstFileError = rejectedFiles[0].errors[0]?.message;
824
+ // Show error
825
+ setFileError(firstFileError || 'Error on adding file');
826
+ } else {
827
+ // Else clean error
828
+ setFileError('');
829
+ }
830
+ }
831
+ });
832
+
833
+ // Delete file from dropzone
834
+ const removeFile = useCallback((event, index) => {
835
+ event.stopPropagation();
836
+ event.preventDefault();
837
+ const newFiles = [...files];
838
+ newFiles.splice(index, 1);
839
+ if (onDeleteFile) {
840
+ onDeleteFile(files[index], inputName);
841
+ }
842
+ changeFormState(newFiles);
843
+ }, [files, changeFormState, onDeleteFile]);
844
+
845
+ //
846
+ const convertFiledValueAndSaveAsFiles = useCallback(async newInputValue => {
847
+ setFileIsLoading(true);
848
+ const newFiles = await convertToFiles(newInputValue, isPreviews);
849
+ setFileIsLoading(false);
850
+ setFiles(newFiles);
851
+ return newFiles;
852
+ }, [isPreviews]);
853
+ useEffect(() => {
854
+ // First time convert value to Files and save to local and form state
855
+ convertFiledValueAndSaveAsFiles(inputValue).then(newFiles => changeFormState(newFiles));
856
+ }, []); // eslint-disable-line
857
+
858
+ useEffect(() => {
859
+ // Everytime convert value to Files and save to local state
860
+ if (!inputValue) {
861
+ setFiles([]);
862
+ } else {
863
+ convertFiledValueAndSaveAsFiles(inputValue);
864
+ }
865
+ // only "inputValue"
866
+ }, [inputValue]); // eslint-disable-line
867
+
868
+ useEffect(() => {
869
+ // Make sure to revoke the data uris to avoid memory leaks, will run on unmount
870
+ return () => files.forEach(file => URL.revokeObjectURL(file?.preview));
871
+ }, []); // eslint-disable-line
872
+
873
+ const fillClass = useDeviceTargetClass(props, {
874
+ prefix: 'fill_',
875
+ propsKey: 'fill'
876
+ });
877
+ const fillHoverClass = useDeviceTargetClass(props, {
878
+ prefix: 'fill_hover_',
879
+ propsKey: 'fillHover'
880
+ });
881
+ const borderWidthClass = useDeviceTargetClass(props, {
882
+ prefix: 'border-width_',
883
+ propsKey: 'borderWidth'
884
+ });
885
+ const borderColorClass = useDeviceTargetClass(props, {
886
+ prefix: 'border-color_',
887
+ propsKey: 'borderColor'
888
+ });
889
+ const borderColorHoverClass = useDeviceTargetClass(props, {
890
+ prefix: 'border-color_hover_',
891
+ propsKey: 'borderColorHover'
892
+ });
893
+ const borderTypeClass = useDeviceTargetClass(props, {
894
+ prefix: 'border_type_',
895
+ propsKey: 'borderType'
896
+ });
897
+ const shapeClass = useDeviceTargetClass(props, {
898
+ prefix: 'form-dropzone_shape_',
899
+ propsKey: 'shape'
900
+ });
901
+ const thumbBorderWidthClass = useDeviceTargetClass(props, {
902
+ prefix: 'border-width_',
903
+ propsKey: 'thumbBorderWidth'
904
+ });
905
+ const thumbDirectionClass = useDeviceTargetClass(props, {
906
+ prefix: 'form-dropzone__thumb_direction_',
907
+ propsKey: 'thumbDirection'
908
+ });
909
+ const thumbBorderColorClass = useDeviceTargetClass(props, {
910
+ prefix: 'border-color_',
911
+ propsKey: 'thumbBorderColor'
912
+ });
913
+ const thumbBorderColorHoverClass = useDeviceTargetClass(props, {
914
+ prefix: 'border-color_hover_',
915
+ propsKey: 'thumbBorderColorHover'
916
+ });
917
+ const thumbBorderTypeClass = useDeviceTargetClass(props, {
918
+ prefix: 'border_type_',
919
+ propsKey: 'thumbBorderType'
920
+ });
921
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", getRootProps({
922
+ className: `form-dropzone__dropzone dropzone ${className} thumbColumn form-dropzone__dropzone_size_${size} ${shapeClass}`
923
+ }), /*#__PURE__*/React.createElement("input", Object.assign({}, getInputProps(), {
924
+ name: inputName
925
+ })), /*#__PURE__*/React.createElement("div", {
926
+ className: clsx('form-dropzone__dropzone-wrapper', thumbColumn && `form-dropzone__dropzone-wrapper_column_${thumbColumn}`, fillClass, fillHoverClass, borderWidthClass, borderColorClass, borderColorHoverClass, borderTypeClass)
927
+ }, files.map((file, i) => /*#__PURE__*/React.createElement("aside", {
928
+ className: clsx('form-dropzone__thumb', fillClass, thumbDirectionClass, thumbBorderWidthClass, thumbBorderColorClass, thumbBorderColorHoverClass, thumbBorderTypeClass),
929
+ key: `${file.id || `${file.name}_${i}` || 'i' + i}`
930
+ }, isPreviews && !file.error && /*#__PURE__*/React.createElement("div", {
931
+ className: "form-dropzone__thumb-image"
932
+ }, /*#__PURE__*/React.createElement("img", {
933
+ className: "form-dropzone__thumb-image-inner",
934
+ src: file.preview || file.image,
935
+ onLoad: () => {
936
+ // Revoke data uri after image is loaded
937
+ URL.revokeObjectURL(file.preview);
938
+ }
939
+ })), file.error && /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Text, {
940
+ size: thumbNameTextSize,
941
+ textColor: thumbNameTextColor,
942
+ textWrap: thumbNameTextWrap,
943
+ textWeight: thumbNameTextWeight
944
+ }, fileErrorText || file.error)), isShowFilename && /*#__PURE__*/React.createElement("div", {
945
+ className: "form-dropzone__thumb-name"
946
+ }, /*#__PURE__*/React.createElement(Text, {
947
+ size: thumbNameTextSize,
948
+ textColor: thumbNameTextColor,
949
+ textWrap: thumbNameTextWrap,
950
+ textWeight: thumbNameTextWeight,
951
+ className: "form-dropzone__thumb-name-inner"
952
+ }, file.name)), fileIsLoading && /*#__PURE__*/React.createElement("div", {
953
+ className: "form-dropzone__thumb-loader"
954
+ }, /*#__PURE__*/React.createElement(Loader, {
955
+ fill: "surfacePrimary",
956
+ height: "fill",
957
+ itemFill: "surfaceItemAccent",
958
+ set: "simple",
959
+ width: "fill"
960
+ })), /*#__PURE__*/React.createElement("div", {
961
+ className: "form-dropzone__thumb-remove",
962
+ onClick: event => removeFile(event, i)
963
+ }, /*#__PURE__*/React.createElement(Text, {
964
+ size: removeThumbTextSize,
965
+ textColor: removeThumbTextColor,
966
+ textWeight: removeThumbTextWeight,
967
+ textColorHover: removeThumbTextHoverColor,
968
+ className: "form-dropzone__thumb-remove-text"
969
+ }, removeThumbText || 'Remove')))), !files.length ? /*#__PURE__*/React.createElement("div", {
970
+ className: "form-dropzone__hint"
971
+ }, /*#__PURE__*/React.createElement(Text, {
972
+ size: hintTitleTextSize,
973
+ textColor: hintTitleTextColor,
974
+ textWrap: hintTitleTextWrap,
975
+ textWeight: hintTitleTextWeight,
976
+ className: "form-dropzone__hint-title"
977
+ }, hintTitle || 'Select a file or drag in form'), /*#__PURE__*/React.createElement(Text, {
978
+ size: hintDescriptionTextSize,
979
+ textColor: hintDescriptionTextColor,
980
+ textWrap: hintDescriptionTextWrap,
981
+ textWeight: hintDescriptionTextWeight,
982
+ className: "form-dropzone__hint-text"
983
+ }, hintDescription)) : /*#__PURE__*/React.createElement("div", {
984
+ className: "form-dropzone__hint form-dropzone__hint_type_add-more"
985
+ }, /*#__PURE__*/React.createElement(Text, {
986
+ size: hintTitleTextSize,
987
+ textColor: hintTitleTextColor,
988
+ textWrap: hintTitleTextWrap,
989
+ textWeight: hintTitleTextWeight,
990
+ className: "form-dropzone__hint-title"
991
+ }, hintTitle || 'Select a file or drag in form'), /*#__PURE__*/React.createElement(Text, {
992
+ size: hintDescriptionTextSize,
993
+ textColor: hintDescriptionTextColor,
994
+ textWrap: hintDescriptionTextWrap,
995
+ textWeight: hintDescriptionTextWeight,
996
+ className: "form-dropzone__hint-text"
997
+ }, hintDescription)))), fileError && /*#__PURE__*/React.createElement("div", {
998
+ className: "form-field__message"
999
+ }, /*#__PURE__*/React.createElement(Text, {
1000
+ className: "form-field__message-item form-field__message-item_type_message",
1001
+ size: errorMessageTextSize,
1002
+ textWeight: errorMessageTextWeight,
1003
+ textColor: errorMessageTextColor
1004
+ }, fileError)));
1005
+ });
1006
+ FileInputDropzone.propTypes = {
1007
+ dropzoneProps: PropTypes.object,
1008
+ hintDescription: PropTypes.string,
1009
+ hintTitle: PropTypes.string,
1010
+ inputName: PropTypes.string,
1011
+ inputValue: PropTypes.any,
1012
+ isPreviews: PropTypes.bool,
1013
+ isShowFilename: PropTypes.bool,
1014
+ loadingText: PropTypes.string,
1015
+ metaError: PropTypes.string,
1016
+ metaTouched: PropTypes.bool,
1017
+ removeThumbText: PropTypes.string,
1018
+ onAddFiles: PropTypes.func,
1019
+ onDeleteFile: PropTypes.func
1020
+ };
1021
+
1022
+ const FileInput = /*#__PURE__*/React.memo(function FileInput(props) {
1023
+ const {
1024
+ name,
1025
+ shape,
1026
+ size,
1027
+ borderWidth,
1028
+ borderColor,
1029
+ borderColorHover,
1030
+ borderType,
1031
+ label,
1032
+ thumbBorderWidth,
1033
+ thumbBorderColor,
1034
+ thumbBorderColorHover,
1035
+ thumbBorderType,
1036
+ removeThumbTextHoverColor,
1037
+ labelTextColor,
1038
+ fill,
1039
+ fillHover,
1040
+ className,
1041
+ removeThumbText,
1042
+ thumbNameTextSize,
1043
+ thumbNameTextColor,
1044
+ thumbNameTextWrap,
1045
+ thumbNameTextWeight,
1046
+ removeThumbTextSize,
1047
+ removeThumbTextColor,
1048
+ removeThumbTextWeight,
1049
+ hintTitle,
1050
+ errorMessageTextSize,
1051
+ errorMessageTextWeight,
1052
+ errorMessageTextColor,
1053
+ fieldProps,
1054
+ hintTitleTextSize,
1055
+ hintTitleTextColor,
1056
+ hintTitleTextWrap,
1057
+ hintTitleTextWeight,
1058
+ hintDescriptionTextSize,
1059
+ hintDescriptionTextColor,
1060
+ hintDescriptionTextWrap,
1061
+ hintDescriptionTextWeight,
1062
+ hideMessage,
1063
+ thumbDirection,
1064
+ hintDescription,
1065
+ isShowFilename,
1066
+ fileErrorText,
1067
+ dropzoneProps,
1068
+ maxFiles,
1069
+ maxSize,
1070
+ thumbColumn,
1071
+ isRequired,
1072
+ isPreviews,
1073
+ onAddFiles,
1074
+ onDeleteFile,
1075
+ classNameGroupItem
1076
+ } = props;
1077
+ return /*#__PURE__*/React.createElement(Field, {
1078
+ name: name
1079
+ }, ({
1080
+ input,
1081
+ meta
1082
+ }) => /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1083
+ className: clsx('form-field_type_dropzone', 'form__item_type_dropzone', classNameGroupItem),
1084
+ fieldClassName: "form-dropzone",
1085
+ inputName: input.name,
1086
+ inputValue: input.value,
1087
+ isRequired: isRequired,
1088
+ label: label,
1089
+ labelTextColor: labelTextColor,
1090
+ metaActive: meta.active,
1091
+ metaError: meta.error,
1092
+ metaModifiedSinceLastSubmit: meta.modifiedSinceLastSubmit,
1093
+ metaSubmitError: meta.submitError,
1094
+ metaSubmitFailed: meta.submitFailed,
1095
+ metaTouched: meta.touched,
1096
+ metaValid: meta.valid,
1097
+ hideMessage: hideMessage
1098
+ }, fieldProps), /*#__PURE__*/React.createElement(FileInputDropzone, {
1099
+ dropzoneProps: dropzoneProps,
1100
+ hintDescription: hintDescription,
1101
+ hintTitle: hintTitle,
1102
+ borderWidth: borderWidth,
1103
+ borderColor: borderColor,
1104
+ borderColorHover: borderColorHover,
1105
+ borderType: borderType,
1106
+ thumbBorderWidth: thumbBorderWidth,
1107
+ thumbBorderColor: thumbBorderColor,
1108
+ thumbBorderColorHover: thumbBorderColorHover,
1109
+ thumbBorderType: thumbBorderType,
1110
+ fileErrorText: fileErrorText,
1111
+ fill: fill,
1112
+ size: size,
1113
+ maxFiles: maxFiles,
1114
+ maxSize: maxSize,
1115
+ removeThumbTextHoverColor: removeThumbTextHoverColor,
1116
+ fillHover: fillHover,
1117
+ className: className,
1118
+ thumbColumn: thumbColumn,
1119
+ thumbDirection: thumbDirection,
1120
+ inputName: input.name,
1121
+ inputValue: input.value,
1122
+ thumbNameTextSize: thumbNameTextSize,
1123
+ thumbNameTextColor: thumbNameTextColor,
1124
+ thumbNameTextWrap: thumbNameTextWrap,
1125
+ thumbNameTextWeight: thumbNameTextWeight,
1126
+ hintTitleTextSize: hintTitleTextSize,
1127
+ hintTitleTextColor: hintTitleTextColor,
1128
+ hintTitleTextWrap: hintTitleTextWrap,
1129
+ hintTitleTextWeight: hintTitleTextWeight,
1130
+ removeThumbTextSize: removeThumbTextSize,
1131
+ removeThumbTextColor: removeThumbTextColor,
1132
+ removeThumbTextWeight: removeThumbTextWeight,
1133
+ hintDescriptionTextSize: hintDescriptionTextSize,
1134
+ hintDescriptionTextColor: hintDescriptionTextColor,
1135
+ hintDescriptionTextWrap: hintDescriptionTextWrap,
1136
+ hintDescriptionTextWeight: hintDescriptionTextWeight,
1137
+ errorMessageTextSize: errorMessageTextSize,
1138
+ errorMessageWeight: errorMessageTextWeight,
1139
+ errorMessageTextColor: errorMessageTextColor,
1140
+ isPreviews: isPreviews,
1141
+ shape: shape,
1142
+ isShowFilename: isShowFilename,
1143
+ metaError: meta.error,
1144
+ metaTouched: meta.touched,
1145
+ removeThumbText: removeThumbText,
1146
+ onAddFiles: onAddFiles,
1147
+ onDeleteFile: onDeleteFile
1148
+ })));
1149
+ });
1150
+ FileInput.defaultProps = {
1151
+ errorMessageTextSize: 's',
1152
+ errorMessageTextColor: 'errorTextPrimary',
1153
+ thumbColumn: 1,
1154
+ thumbDirection: 'vertical'
1155
+ };
1156
+ FileInput.propTypes = {
1157
+ name: PropTypes.string.isRequired,
1158
+ className: PropTypes.string,
1159
+ classNameGroupItem: PropTypes.string,
1160
+ classNameInput: PropTypes.string,
1161
+ classNameInputWrapper: PropTypes.string,
1162
+ dropzoneProps: PropTypes.object,
1163
+ hintDescription: PropTypes.string,
1164
+ hintTitle: PropTypes.string,
1165
+ inputClass: PropTypes.string,
1166
+ isPreviews: PropTypes.bool,
1167
+ isRequired: PropTypes.bool,
1168
+ isShowFilename: PropTypes.bool,
1169
+ label: PropTypes.any,
1170
+ removeThumbText: PropTypes.string,
1171
+ onAddFiles: PropTypes.func,
1172
+ onDeleteFile: PropTypes.func
1173
+ };
1174
+
1175
+ const Group = /*#__PURE__*/React.memo(function Group(props) {
1176
+ const {
1177
+ after,
1178
+ before,
1179
+ className,
1180
+ label,
1181
+ labelTextColor,
1182
+ labelTextSize,
1183
+ labelTextWeight,
1184
+ message,
1185
+ errorMessageTextSize,
1186
+ errorMessageTextWeight,
1187
+ errorMessageTextColor,
1188
+ messageTextSize,
1189
+ messageTextWeight,
1190
+ messageTextColor,
1191
+ children,
1192
+ dataTour,
1193
+ hideMessage,
1194
+ name,
1195
+ showErrorsOnSubmit
1196
+ } = props;
1197
+ return /*#__PURE__*/React.createElement(Field, {
1198
+ name: name
1199
+ }, ({
1200
+ input,
1201
+ meta
1202
+ }) => {
1203
+ const error = meta.error || !meta.modifiedSinceLastSubmit && meta.submitError || false;
1204
+ const showError = useMemo(() => {
1205
+ if (showErrorsOnSubmit) {
1206
+ return meta.submitFailed && meta.touched && error;
1207
+ } else {
1208
+ return meta.touched && error;
1209
+ }
1210
+ }, [showErrorsOnSubmit, meta.submitFailed, meta.touched, error]);
1211
+ return /*#__PURE__*/React.createElement("div", {
1212
+ className: clsx('form__group', className),
1213
+ "data-tour": dataTour
1214
+ }, /*#__PURE__*/React.createElement("div", {
1215
+ className: "form__group-wrapper"
1216
+ }, before, /*#__PURE__*/React.createElement("div", {
1217
+ className: "form__group-label"
1218
+ }, /*#__PURE__*/React.createElement(Title, {
1219
+ textColor: labelTextColor,
1220
+ size: labelTextSize,
1221
+ textWeight: labelTextWeight
1222
+ }, label)), /*#__PURE__*/React.createElement("div", {
1223
+ className: "form__group-items"
1224
+ }, children), after), !hideMessage && /*#__PURE__*/React.createElement(React.Fragment, null, Boolean(showError) && /*#__PURE__*/React.createElement(Text, {
1225
+ className: "form__group-message form__group-message_type-error",
1226
+ size: errorMessageTextSize,
1227
+ textWeight: errorMessageTextWeight,
1228
+ textColor: errorMessageTextColor,
1229
+ id: `${name}-error`
1230
+ }, error), Boolean(message) && !showError && /*#__PURE__*/React.createElement(Text, {
1231
+ className: "form__group-message",
1232
+ size: messageTextSize,
1233
+ textWeight: messageTextWeight,
1234
+ textColor: messageTextColor
1235
+ }, message), Boolean(!showError) && Boolean(!message) && /*#__PURE__*/React.createElement(Text, {
1236
+ className: "form__group-message",
1237
+ size: messageTextSize
1238
+ }, '\u00A0')));
1239
+ });
1240
+ });
1241
+ Group.defaultProps = {
1242
+ inputProps: {},
1243
+ fieldProps: {},
1244
+ type: 'normal',
1245
+ errorMessageTextSize: 's',
1246
+ errorMessageTextColor: 'errorTextPrimary',
1247
+ messageTextSize: 's',
1248
+ messageTextColor: 'surfaceTextTertiary'
1249
+ };
1250
+ Group.propTypes = {
1251
+ name: PropTypes.string.isRequired,
1252
+ isRequired: PropTypes.bool,
1253
+ fieldProps: PropTypes.object,
1254
+ inputProps: PropTypes.object
1255
+ };
1256
+
1257
+ const InputField = /*#__PURE__*/React.memo(function InputField(props) {
1258
+ const {
1259
+ isPassword,
1260
+ isRequired,
1261
+ fieldProps,
1262
+ inputProps,
1263
+ isRevealable,
1264
+ name,
1265
+ parse,
1266
+ iconSize,
1267
+ iconBorder,
1268
+ iconBorderHover,
1269
+ iconFill,
1270
+ iconFillHover,
1271
+ iconRevealableShow,
1272
+ iconRevealableHide,
1273
+ iconShape,
1274
+ hideMessage,
1275
+ onChange,
1276
+ classNameGroupItem
1277
+ } = props;
1278
+ const [isRevealed, setIsRevealed] = useState(false);
1279
+ const inputType = useMemo(() => {
1280
+ if (isPassword) {
1281
+ return isRevealed ? 'text' : 'password';
1282
+ } else {
1283
+ return 'text';
1284
+ }
1285
+ }, [isRevealed, isPassword]);
1286
+ const revealeHandler = useCallback(e => {
1287
+ e.preventDefault();
1288
+ setIsRevealed(prev => !prev);
1289
+ }, [setIsRevealed]);
1290
+ return /*#__PURE__*/React.createElement(Field, {
1291
+ name: name,
1292
+ parse: parse
1293
+ }, ({
1294
+ input,
1295
+ meta
1296
+ }) => {
1297
+ const onChangeField = useCallback(event => {
1298
+ input.onChange(event);
1299
+ if (onChange) {
1300
+ onChange(event.target.value, input.name);
1301
+ }
1302
+ }, [onChange]);
1303
+ return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1304
+ className: clsx('form-field_type_input', 'form__item_type_input', classNameGroupItem),
1305
+ fieldClassName: isRevealable ? 'form-password' : 'form-input',
1306
+ inputName: input.name,
1307
+ inputValue: input.value || '',
1308
+ isRequired: isRequired,
1309
+ metaActive: meta.active,
1310
+ metaError: meta.error,
1311
+ metaModifiedSinceLastSubmit: meta.modifiedSinceLastSubmit,
1312
+ metaSubmitError: meta.submitError,
1313
+ metaSubmitFailed: meta.submitFailed,
1314
+ metaTouched: meta.touched,
1315
+ metaValid: meta.valid,
1316
+ hideMessage: hideMessage
1317
+ }, fieldProps), /*#__PURE__*/React.createElement(Input, Object.assign({
1318
+ className: clsx(meta.active && 'input_state_focus', meta.error && meta.touched && 'input_state_error'),
1319
+ autoComplete: "nope",
1320
+ name: input.name,
1321
+ type: inputType,
1322
+ value: input.value || '',
1323
+ onBlur: input.onBlur,
1324
+ onChange: onChangeField,
1325
+ onFocus: input.onFocus
1326
+ }, inputProps)), isRevealable && /*#__PURE__*/React.createElement(Icon, {
1327
+ className: "form-field__icon",
1328
+ iconFill: iconFill,
1329
+ iconFillHover: iconFillHover,
1330
+ SvgImage: isRevealed ? iconRevealableHide : iconRevealableShow,
1331
+ imageSrc: isRevealed ? iconRevealableHide : iconRevealableShow,
1332
+ shape: iconShape,
1333
+ size: iconSize,
1334
+ onClick: revealeHandler
1335
+ }));
1336
+ });
1337
+ });
1338
+ InputField.defaultProps = {
1339
+ inputProps: {},
1340
+ fieldProps: {}
1341
+ };
1342
+ InputField.propTypes = {
1343
+ fieldProps: PropTypes.object,
1344
+ inputProps: PropTypes.object,
1345
+ isPassword: PropTypes.bool,
1346
+ isRequired: PropTypes.bool,
1347
+ isRevealable: PropTypes.bool,
1348
+ name: PropTypes.string.isRequired,
1349
+ onChange: PropTypes.func
1350
+ };
1351
+
1352
+ function RadioGroupItem(props) {
1353
+ const {
1354
+ input,
1355
+ option,
1356
+ onChange,
1357
+ inputProps
1358
+ } = props;
1359
+ const onChangeField = useCallback(event => {
1360
+ if (event.target.checked) {
1361
+ onChange(option.value);
1362
+ }
1363
+ }, []);
1364
+ return /*#__PURE__*/React.createElement(RadioButton, Object.assign({
1365
+ className: "form-radio__item",
1366
+ checked: option.value === input.value,
1367
+ name: input.name,
1368
+ type: "radio",
1369
+ value: option.value,
1370
+ onBlur: input.onBlur,
1371
+ onChange: onChangeField,
1372
+ onFocus: input.onFocus,
1373
+ label: option.label
1374
+ }, inputProps));
1375
+ }
1376
+ RadioGroupItem.propTypes = {
1377
+ inputProps: PropTypes.object,
1378
+ onChange: PropTypes.func,
1379
+ option: PropTypes.shape({
1380
+ label: PropTypes.string,
1381
+ value: PropTypes.string
1382
+ }),
1383
+ input: PropTypes.shape({
1384
+ name: PropTypes.string,
1385
+ value: PropTypes.string,
1386
+ onBlur: PropTypes.func,
1387
+ onFocus: PropTypes.func,
1388
+ onChange: PropTypes.func
1389
+ })
1390
+ };
1391
+
1392
+ function RadioGroupInput(props) {
1393
+ const {
1394
+ input,
1395
+ value,
1396
+ onChange
1397
+ } = props;
1398
+ const onChangeField = useCallback(event => onChange(event.target.value), [onChange]);
1399
+ return /*#__PURE__*/React.createElement(Input, Object.assign({
1400
+ autoComplete: "nope",
1401
+ name: input.name,
1402
+ onBlur: input.onBlur,
1403
+ onChange: onChangeField,
1404
+ onFocus: input.onFocus,
1405
+ value: value
1406
+ }, props));
1407
+ }
1408
+ RadioGroupInput.propTypes = {
1409
+ input: PropTypes.string,
1410
+ value: PropTypes.string,
1411
+ editableProps: PropTypes.object,
1412
+ onChange: PropTypes.func
1413
+ };
1414
+
1415
+ function RadioGroupList(props) {
1416
+ const {
1417
+ input,
1418
+ options,
1419
+ editableProps,
1420
+ onChange,
1421
+ inputProps
1422
+ } = props;
1423
+ const [editableValue, setEditableValue] = useState(() => {
1424
+ const isRadioValue = options.find(option => option.value === input.value);
1425
+ if (!isRadioValue) {
1426
+ return input.value;
1427
+ }
1428
+ return '';
1429
+ });
1430
+ useEffect(() => {
1431
+ // When a new value from outside enters the form
1432
+ if (input.value) {
1433
+ // Check value for radio type
1434
+ const isRadioValue = options.find(option => option.value === input.value && !option.editable);
1435
+ // If new value not in radio list - set to editable input
1436
+ setEditableValue(isRadioValue ? '' : input.value);
1437
+ } else {
1438
+ // If new value is empty - clear editable input
1439
+ setEditableValue('');
1440
+ }
1441
+ }, [input.value]);
1442
+
1443
+ // Callback for value changes
1444
+ const onChangeSomeInput = useCallback(value => {
1445
+ // Save to form values
1446
+ input.onChange(value);
1447
+ if (onChange) {
1448
+ // Pass to custom event
1449
+ onChange(value, input.name);
1450
+ }
1451
+ }, [input, onChange]);
1452
+
1453
+ // Handle for radio inputs
1454
+ const onChangeRadio = useCallback(value => {
1455
+ setEditableValue('');
1456
+ onChangeSomeInput(value);
1457
+ }, [onChangeSomeInput]);
1458
+
1459
+ // Handle for text input
1460
+ const onChangeEditable = useCallback(value => {
1461
+ setEditableValue(value);
1462
+ onChangeSomeInput(value);
1463
+ }, [onChangeSomeInput]);
1464
+ return /*#__PURE__*/React.createElement(React.Fragment, null, options.map(option => option.editable ? /*#__PURE__*/React.createElement(RadioGroupInput, {
1465
+ key: option.label,
1466
+ input: input,
1467
+ value: editableValue,
1468
+ option: option,
1469
+ onChange: onChangeEditable,
1470
+ editableProps: editableProps,
1471
+ inputProps: inputProps
1472
+ }) : /*#__PURE__*/React.createElement(RadioGroupItem, {
1473
+ key: option.value,
1474
+ input: input,
1475
+ option: option,
1476
+ onChange: onChangeRadio,
1477
+ inputProps: inputProps
1478
+ })));
1479
+ }
1480
+ RadioGroupList.propTypes = {
1481
+ editableProps: PropTypes.object,
1482
+ input: PropTypes.object,
1483
+ inputProps: PropTypes.object,
1484
+ onChange: PropTypes.object,
1485
+ options: PropTypes.object
1486
+ };
1487
+
1488
+ const RadioGroup = /*#__PURE__*/React.memo(function RadioGroup(props) {
1489
+ const {
1490
+ isRequired,
1491
+ name,
1492
+ options,
1493
+ fieldProps,
1494
+ editableProps,
1495
+ inputProps,
1496
+ onChange,
1497
+ hideMessage
1498
+ } = props;
1499
+ return /*#__PURE__*/React.createElement(Field, {
1500
+ name: name
1501
+ }, ({
1502
+ input,
1503
+ meta
1504
+ }) => /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1505
+ className: "form__item_type_radio",
1506
+ fieldClassName: 'form-radio',
1507
+ inputName: input.name,
1508
+ inputValue: input.value || '',
1509
+ isRequired: isRequired,
1510
+ metaActive: meta.active,
1511
+ metaError: meta.error,
1512
+ metaModifiedSinceLastSubmit: meta.modifiedSinceLastSubmit,
1513
+ metaSubmitError: meta.submitError,
1514
+ metaSubmitFailed: meta.submitFailed,
1515
+ metaTouched: meta.touched,
1516
+ metaValid: meta.valid,
1517
+ hideMessage: hideMessage
1518
+ }, fieldProps), /*#__PURE__*/React.createElement(RadioGroupList, {
1519
+ input: input,
1520
+ options: options,
1521
+ onChange: onChange,
1522
+ editableProps: editableProps,
1523
+ inputProps: inputProps
1524
+ })));
1525
+ });
1526
+ RadioGroup.defaultProps = {
1527
+ fieldProps: {},
1528
+ editableProps: {},
1529
+ inputProps: {},
1530
+ options: []
1531
+ };
1532
+ RadioGroup.propTypes = {
1533
+ name: PropTypes.string.isRequired,
1534
+ fieldProps: PropTypes.object,
1535
+ inputProps: PropTypes.object,
1536
+ editableProps: PropTypes.object,
1537
+ isRequired: PropTypes.bool,
1538
+ options: PropTypes.array,
1539
+ onChange: PropTypes.func
1540
+ };
1541
+
1542
+ // const SegmentedField = React.memo(
1543
+ function SegmentedField(props) {
1544
+ const {
1545
+ options,
1546
+ isRequired,
1547
+ name,
1548
+ fieldProps,
1549
+ inputProps,
1550
+ hideMessage
1551
+ } = props;
1552
+ const {
1553
+ change
1554
+ } = useForm();
1555
+ return /*#__PURE__*/React.createElement(Field, {
1556
+ name: name
1557
+ }, ({
1558
+ input,
1559
+ meta
1560
+ }) => {
1561
+ const activeOption = useMemo(() => {
1562
+ const emptyOption = {
1563
+ value: null,
1564
+ label: null
1565
+ };
1566
+ if (input.value) {
1567
+ const currentOption = options.find(option => option.value === input.value);
1568
+ return currentOption || emptyOption;
1569
+ }
1570
+ return emptyOption;
1571
+ }, [input.value]);
1572
+ const setActiveSegment = useCallback(option => {
1573
+ change(name, option.value);
1574
+ }, [change]);
1575
+ return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1576
+ className: clsx('form-field_type_segmented', 'form__item_type_segmented'),
1577
+ fieldClassName: "form-segmented",
1578
+ inputName: input.name,
1579
+ inputValue: input.value || [],
1580
+ isRequired: isRequired,
1581
+ metaActive: meta.active,
1582
+ metaError: meta.error,
1583
+ metaModifiedSinceLastSubmit: meta.modifiedSinceLastSubmit,
1584
+ metaSubmitError: meta.submitError,
1585
+ metaSubmitFailed: meta.submitFailed,
1586
+ metaTouched: meta.touched,
1587
+ metaValid: meta.valid,
1588
+ hideMessage: hideMessage
1589
+ }, fieldProps), /*#__PURE__*/React.createElement(Segmented, Object.assign({
1590
+ segments: options,
1591
+ setActiveSegment: setActiveSegment,
1592
+ activeSegment: activeOption
1593
+ }, inputProps)));
1594
+ });
1595
+ }
1596
+ // )
1597
+
1598
+ SegmentedField.propTypes = {
1599
+ options: PropTypes.array.isRequired,
1600
+ name: PropTypes.string.isRequired,
1601
+ className: PropTypes.string,
1602
+ inputClass: PropTypes.string,
1603
+ isRequired: PropTypes.bool,
1604
+ label: PropTypes.string,
1605
+ placeholder: PropTypes.string,
1606
+ fieldProps: PropTypes.object,
1607
+ inputProps: PropTypes.object
1608
+ };
1609
+
1610
+ function getDefaultValue(options, selectValue) {
1611
+ const selectValues = Array.isArray(selectValue) ? selectValue : [selectValue];
1612
+ let result = [];
1613
+ options.forEach(item => {
1614
+ const isValue = selectValues.includes(item.value);
1615
+ const isLabel = selectValues.includes(item.label);
1616
+ let childOptions = [];
1617
+ if (item.options) {
1618
+ childOptions = getDefaultValue(item.options, selectValue);
1619
+ }
1620
+ if (isValue || isLabel) {
1621
+ result.push(item);
1622
+ } else if (childOptions.length) {
1623
+ result = result.concat(childOptions);
1624
+ }
1625
+ });
1626
+ return result;
1627
+ }
1628
+ const SelectField = /*#__PURE__*/React.memo(function SelectField(props) {
1629
+ const {
1630
+ isRequired,
1631
+ key,
1632
+ name,
1633
+ options,
1634
+ fieldProps,
1635
+ selectProps,
1636
+ selectRef,
1637
+ onChange,
1638
+ classNameGroupItem,
1639
+ hideMessage
1640
+ } = props;
1641
+ return /*#__PURE__*/React.createElement(Field, {
1642
+ name: name
1643
+ }, ({
1644
+ input,
1645
+ meta
1646
+ }) => {
1647
+ const onChangeField = useCallback(value => {
1648
+ input.onChange(value);
1649
+ if (onChange) {
1650
+ onChange(value, input.name);
1651
+ }
1652
+ }, [onChange]);
1653
+ const [selectedOptions, setSelectedOptions] = useState(null);
1654
+ const defaultValue = useMemo(() => {
1655
+ const optionsValues = getDefaultValue(options, input.value);
1656
+ if (!optionsValues.length && input.value?.length) {
1657
+ optionsValues.push({
1658
+ value: input.value,
1659
+ label: input.value
1660
+ });
1661
+ }
1662
+ return optionsValues;
1663
+ }, [input.value]);
1664
+ useEffect(() => setSelectedOptions(defaultValue), [defaultValue]);
1665
+ const onChangeValue = useCallback((option, actionMeta) => {
1666
+ const value = Array.isArray(option) ? option.map(o => o.value) : option?.value || null;
1667
+ setSelectedOptions(option);
1668
+ onChangeField(value);
1669
+ }, [onChangeField]);
1670
+ return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1671
+ className: clsx('form-field_type_select', 'form__item_type_select', classNameGroupItem),
1672
+ fieldClassName: 'form-select',
1673
+ inputName: input.name,
1674
+ inputValue: input.value,
1675
+ isRequired: isRequired,
1676
+ metaActive: meta.active,
1677
+ metaError: meta.error,
1678
+ metaModifiedSinceLastSubmit: meta.modifiedSinceLastSubmit,
1679
+ metaSubmitError: meta.submitError,
1680
+ metaSubmitFailed: meta.submitFailed,
1681
+ metaTouched: meta.touched,
1682
+ metaValid: meta.valid,
1683
+ hideMessage: hideMessage
1684
+ }, fieldProps), /*#__PURE__*/React.createElement(Select, Object.assign({
1685
+ className: "form-select-item",
1686
+ instanceId: `id_${input.name}`,
1687
+ value: selectedOptions,
1688
+ onChange: onChangeValue,
1689
+ options: options,
1690
+ ref: selectRef,
1691
+ key: key
1692
+ }, selectProps)));
1693
+ });
1694
+ });
1695
+ SelectField.propTypes = {
1696
+ name: PropTypes.string.isRequired,
1697
+ selectProps: PropTypes.object,
1698
+ isRequired: PropTypes.bool,
1699
+ label: PropTypes.any,
1700
+ messageType: PropTypes.string,
1701
+ options: PropTypes.array,
1702
+ onChange: PropTypes.func
1703
+ };
1704
+
1705
+ const SwitchField = /*#__PURE__*/React.memo(function SwitchField(props) {
1706
+ const {
1707
+ name,
1708
+ isRequired,
1709
+ onChange,
1710
+ fieldProps,
1711
+ inputProps,
1712
+ classNameGroupItem,
1713
+ hideMessage
1714
+ } = props;
1715
+ return /*#__PURE__*/React.createElement(Field, {
1716
+ name: name,
1717
+ type: "checkbox"
1718
+ }, ({
1719
+ input,
1720
+ meta
1721
+ }) => {
1722
+ const onChangeField = useCallback(event => {
1723
+ input.onChange(event);
1724
+ if (onChange) {
1725
+ onChange(event.target.checked, input.name);
1726
+ }
1727
+ }, [onChange]);
1728
+ return /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1729
+ className: clsx('form-field_type_switch', 'form__item_type_switch', classNameGroupItem),
1730
+ fieldClassName: "form-switch",
1731
+ inputName: input.name,
1732
+ inputValue: input.checked,
1733
+ isRequired: isRequired,
1734
+ metaActive: meta.active,
1735
+ metaError: meta.error,
1736
+ metaModifiedSinceLastSubmit: meta.modifiedSinceLastSubmit,
1737
+ metaSubmitError: meta.submitError,
1738
+ metaSubmitFailed: meta.submitFailed,
1739
+ metaTouched: meta.touched,
1740
+ metaValid: meta.valid,
1741
+ hideMessage: hideMessage,
1742
+ tag: "label"
1743
+ }, fieldProps), /*#__PURE__*/React.createElement(Switch, Object.assign({
1744
+ autoComplete: "nope",
1745
+ checked: input.checked,
1746
+ name: input.name,
1747
+ type: "checkbox",
1748
+ onBlur: input.onBlur,
1749
+ onChange: onChangeField,
1750
+ onFocus: input.onFocus
1751
+ }, inputProps)));
1752
+ });
1753
+ });
1754
+ SwitchField.defaultProps = {
1755
+ inputProps: {},
1756
+ fieldProps: {}
1757
+ };
1758
+ SwitchField.propTypes = {
1759
+ fieldProps: PropTypes.object,
1760
+ inputProps: PropTypes.object,
1761
+ isRequired: PropTypes.bool,
1762
+ name: PropTypes.string,
1763
+ onChange: PropTypes.func
1764
+ };
1765
+
1766
+ const TextareaField = /*#__PURE__*/React.memo(function TextareaField(props) {
1767
+ const {
1768
+ isRequired,
1769
+ name,
1770
+ fieldProps,
1771
+ inputProps,
1772
+ classNameGroupItem,
1773
+ hideMessage
1774
+ } = props;
1775
+ return /*#__PURE__*/React.createElement(Field, {
1776
+ name: name
1777
+ }, ({
1778
+ input,
1779
+ meta
1780
+ }) => /*#__PURE__*/React.createElement(FieldWrapper, Object.assign({
1781
+ className: clsx('form-field_type_textarea', 'form__item_type_textarea', classNameGroupItem),
1782
+ fieldClassName: 'form-textarea',
1783
+ inputName: input.name,
1784
+ inputValue: input.value,
1785
+ isRequired: isRequired,
1786
+ metaActive: meta.active,
1787
+ metaError: meta.error,
1788
+ metaModifiedSinceLastSubmit: meta.modifiedSinceLastSubmit,
1789
+ metaSubmitError: meta.submitError,
1790
+ metaSubmitFailed: meta.submitFailed,
1791
+ metaTouched: meta.touched,
1792
+ metaValid: meta.valid,
1793
+ hideMessage: hideMessage
1794
+ }, fieldProps), /*#__PURE__*/React.createElement(Textarea, Object.assign({
1795
+ autoComplete: "nope",
1796
+ name: input.name,
1797
+ value: input.value,
1798
+ onBlur: input.onBlur,
1799
+ onChange: input.onChange,
1800
+ onFocus: input.onFocus
1801
+ }, inputProps))));
1802
+ });
1803
+ TextareaField.defaultProps = {
1804
+ inputProps: {},
1805
+ fieldProps: {}
1806
+ };
1807
+ TextareaField.propTypes = {
1808
+ name: PropTypes.string.isRequired,
1809
+ isRequired: PropTypes.bool,
1810
+ fieldProps: PropTypes.object,
1811
+ inputProps: PropTypes.object
1812
+ };
1813
+
1814
+ const focusOnError = (formElementsList, errors) => {
1815
+ const selectsIds = Object.keys(errors).map(fieldName => {
1816
+ if (fieldName === FORM_ERROR) {
1817
+ // TODO: get from somewhere
1818
+ return 'notification__item_status_error';
1819
+ }
1820
+ return `react-select-id_${fieldName}-input`;
1821
+ });
1822
+ const errorFieldElement = formElementsList.find(element => {
1823
+ if (element.name) {
1824
+ return getIn(errors, element.name);
1825
+ } else {
1826
+ return selectsIds.includes(element.id);
1827
+ }
1828
+ });
1829
+ const errorsList = Object.keys(errors);
1830
+ if (!errorFieldElement && errorsList.length) {
1831
+ let errorElement;
1832
+ try {
1833
+ const fieldName = errorsList[0];
1834
+ if (fieldName === FORM_ERROR) {
1835
+ errorElement = document.querySelector('notification__item_status_error');
1836
+ } else {
1837
+ errorElement = document.querySelector(`#${fieldName}-error`);
1838
+ if (!errorElement) {
1839
+ errorElement = document.querySelector(`#id_${fieldName}`);
1840
+ }
1841
+ }
1842
+ } catch (err) {
1843
+ console.warn(err);
1844
+ }
1845
+ if (errorElement) {
1846
+ errorElement.scrollIntoView({
1847
+ block: 'center'
1848
+ }); // , behavior: 'smooth'
1849
+ }
1850
+ }
1851
+
1852
+ // the field is covered by the header because header is "sticky",
1853
+ // that's we scroll manually so that the field falls into the center of the visible area
1854
+ if (errorFieldElement) {
1855
+ errorFieldElement.scrollIntoView({
1856
+ block: 'center'
1857
+ });
1858
+ }
1859
+ return null;
1860
+ };
1861
+ const focusOnErrorDecorator = createDecorator(null, focusOnError);
1862
+ const setErrorsMutator = (args, state) => {
1863
+ const [fieldName, data] = args;
1864
+ const submitError = data.submitError;
1865
+ const fieldError = data.error;
1866
+ if (fieldName === 'non_field_errors') {
1867
+ // state.formState.invalid = true
1868
+ // state.formState.valid = false
1869
+ state.formState.error = fieldError;
1870
+ state.formState.submitError = submitError;
1871
+ } else if (fieldName in state.fields) {
1872
+ if (fieldError) {
1873
+ const errorsState = Object.assign({}, state.formState.errors, {
1874
+ [fieldName]: fieldError
1875
+ });
1876
+ state.fields[fieldName].touched = true;
1877
+ state.fields[fieldName].error = fieldError;
1878
+ state.formState.errors = errorsState;
1879
+ }
1880
+ if (submitError) {
1881
+ const submitErrorsState = Object.assign({}, state.formState.submitErrors, {
1882
+ [fieldName]: submitError
1883
+ });
1884
+
1885
+ // state.fields[fieldName].submitFailed = true
1886
+ // state.fields[fieldName].submitSucceeded = false
1887
+ state.fields[fieldName].submitError = submitError;
1888
+ state.formState.submitErrors = submitErrorsState;
1889
+ state.formState.submitFailed = true;
1890
+ state.formState.submitSucceeded = false;
1891
+ state.formState.lastSubmittedValues = state.formState.values;
1892
+ }
1893
+ }
1894
+ };
1895
+ const sendFormDataToServer = async (url, data) => {
1896
+ try {
1897
+ const response = await axios({
1898
+ url: url,
1899
+ method: 'POST',
1900
+ data: data
1901
+ });
1902
+ return {
1903
+ success: true,
1904
+ response
1905
+ };
1906
+ } catch (error) {
1907
+ const formErrors = {};
1908
+ if (typeof error.response?.data === 'string') {
1909
+ formErrors[FORM_ERROR] = 'Something went wrong';
1910
+ }
1911
+ if (typeof error.response?.data === 'object') {
1912
+ Object.entries(error.response.data).forEach(([fieldName, errorsList]) => {
1913
+ formErrors[fieldName] = errorsList[0];
1914
+ });
1915
+ }
1916
+ return {
1917
+ success: false,
1918
+ formErrors,
1919
+ error
1920
+ };
1921
+ }
1922
+ };
1923
+
1924
+ const formTypes = {
1925
+ checkbox: 'checkbox',
1926
+ custom: 'custom',
1927
+ choice: 'choice',
1928
+ code: 'code',
1929
+ datePicker: 'datePicker',
1930
+ dateRangePicker: 'dateRangePicker',
1931
+ fileInput: 'fileInput',
1932
+ group: 'group',
1933
+ radioGroup: 'radioGroup',
1934
+ segmented: 'segmented',
1935
+ select: 'select',
1936
+ switch: 'switch',
1937
+ text: 'text',
1938
+ textarea: 'textarea'
1939
+ };
1940
+ function generateField(field, config, props) {
1941
+ switch (field.type) {
1942
+ case formTypes.checkbox:
1943
+ {
1944
+ return /*#__PURE__*/React.createElement(CheckboxField, Object.assign({
1945
+ key: config.key
1946
+ }, field, props));
1947
+ }
1948
+ case formTypes.choice:
1949
+ {
1950
+ return /*#__PURE__*/React.createElement(ChoiceField, Object.assign({
1951
+ key: config.key
1952
+ }, field, props));
1953
+ }
1954
+ case formTypes.code:
1955
+ {
1956
+ return /*#__PURE__*/React.createElement(CodeField, Object.assign({
1957
+ key: config.key
1958
+ }, field, props));
1959
+ }
1960
+ case formTypes.switch:
1961
+ {
1962
+ return /*#__PURE__*/React.createElement(SwitchField, Object.assign({
1963
+ key: config.key
1964
+ }, field, props));
1965
+ }
1966
+ case formTypes.segmented:
1967
+ {
1968
+ return /*#__PURE__*/React.createElement(SegmentedField, Object.assign({
1969
+ key: config.key
1970
+ }, field, props));
1971
+ }
1972
+ case formTypes.datePicker:
1973
+ {
1974
+ return /*#__PURE__*/React.createElement(DatePickerField, Object.assign({
1975
+ key: config.key
1976
+ }, field, props));
1977
+ }
1978
+ case formTypes.fileInput:
1979
+ {
1980
+ return /*#__PURE__*/React.createElement(FileInput, Object.assign({
1981
+ key: config.key
1982
+ }, field, props));
1983
+ }
1984
+ case formTypes.radioGroup:
1985
+ {
1986
+ return /*#__PURE__*/React.createElement(RadioGroup, Object.assign({
1987
+ key: config.key
1988
+ }, field, props));
1989
+ }
1990
+ case formTypes.select:
1991
+ {
1992
+ return /*#__PURE__*/React.createElement(SelectField, Object.assign({
1993
+ key: config.key
1994
+ }, field, props));
1995
+ }
1996
+ case formTypes.text:
1997
+ {
1998
+ return /*#__PURE__*/React.createElement(InputField, Object.assign({
1999
+ key: config.key
2000
+ }, field, props));
2001
+ }
2002
+ case formTypes.textarea:
2003
+ {
2004
+ return /*#__PURE__*/React.createElement(TextareaField, Object.assign({
2005
+ key: config.key
2006
+ }, field, props));
2007
+ }
2008
+ case formTypes.custom:
2009
+ {
2010
+ return /*#__PURE__*/React.createElement(CustomField, Object.assign({
2011
+ key: config.key
2012
+ }, field, props));
2013
+ }
2014
+ case formTypes.group:
2015
+ {
2016
+ return /*#__PURE__*/React.createElement(Group, Object.assign({
2017
+ key: config.key
2018
+ }, field, props), Object.entries(field.group).map(([key, value]) => {
2019
+ const groupProps = {
2020
+ ...value,
2021
+ hideMessage: field.hideMessage,
2022
+ classNameGroupItem: value.classNameGroupItem || 'form__group-item'
2023
+ };
2024
+ return generateField(groupProps, {
2025
+ key: key + '_form_group'
2026
+ }, props);
2027
+ }));
2028
+ }
2029
+ }
2030
+ }
2031
+
2032
+ const FinalForm = /*#__PURE__*/React.forwardRef(function FinalForm(props, ref) {
2033
+ const {
2034
+ additionalProps,
2035
+ after,
2036
+ before,
2037
+ buttonDirection,
2038
+ buttonGap,
2039
+ buttonPadding,
2040
+ groupGap,
2041
+ className,
2042
+ config,
2043
+ description,
2044
+ descriptionSize,
2045
+ descriptionTextColor,
2046
+ descriptionTextWeight,
2047
+ disableFieldsAutoComplete,
2048
+ fieldsGap,
2049
+ formName,
2050
+ initialValues,
2051
+ initialValuesEqual,
2052
+ isLoading,
2053
+ loader,
2054
+ loaderSet,
2055
+ loaderFill,
2056
+ loaderItemFill,
2057
+ loaderText,
2058
+ language,
2059
+ mutators,
2060
+ onChangeFormValues,
2061
+ onClickSecondaryButton,
2062
+ onClickTertiaryButton,
2063
+ onSubmit,
2064
+ primaryButton,
2065
+ primaryButtonLabel,
2066
+ secondaryButton,
2067
+ secondaryButtonLabel,
2068
+ primaryButtonFill,
2069
+ primaryButtonFillHover,
2070
+ secondaryButtonFill,
2071
+ secondaryButtonFillHover,
2072
+ primaryButtonSize,
2073
+ primaryButtonLabelTextColor,
2074
+ primaryButtonLabelSize,
2075
+ primaryButtonLabelTextWeight,
2076
+ secondaryButtonSize,
2077
+ secondaryButtonLabelTextColor,
2078
+ secondaryButtonLabelSize,
2079
+ secondaryButtonLabelTextWeight,
2080
+ tertiaryButton,
2081
+ tertiaryButtonFill,
2082
+ tertiaryButtonFillHover,
2083
+ tertiaryButtonSize,
2084
+ tertiaryButtonLabelTextColor,
2085
+ tertiaryButtonLabelSize,
2086
+ tertiaryButtonLabelTextWeight,
2087
+ tertiaryButtonLabel,
2088
+ set,
2089
+ type,
2090
+ buttonJustifyContent,
2091
+ title,
2092
+ notificationType,
2093
+ notificationClose,
2094
+ buttonFill,
2095
+ titleTextSize,
2096
+ titleTextColor,
2097
+ titleTextWeight,
2098
+ validationSchema,
2099
+ dataTour,
2100
+ dataTourButtons,
2101
+ dataTourPrimaryButton,
2102
+ dataTourSecondaryButton,
2103
+ dataTourTertiaryButton
2104
+ } = props;
2105
+ const validate = useYupValidationSchema(validationSchema, language);
2106
+ const onRefFormInstance = useCallback(formInstance => {
2107
+ if (ref) {
2108
+ ref.current = formInstance;
2109
+ }
2110
+ }, [ref]);
2111
+ const fillClass = useDeviceTargetClass(props, {
2112
+ prefix: 'fill_',
2113
+ propsKey: 'fill'
2114
+ });
2115
+ const directionClass = useDeviceTargetClass(props, {
2116
+ prefix: 'direction_',
2117
+ propsKey: 'direction'
2118
+ });
2119
+ const shapeClass = useDeviceTargetClass(props, {
2120
+ prefix: 'shape_',
2121
+ propsKey: 'shape'
2122
+ });
2123
+ const elevationClass = useDeviceTargetClass(props, {
2124
+ prefix: 'elevation_',
2125
+ propsKey: 'elevation'
2126
+ });
2127
+ const {
2128
+ styles: formStyles
2129
+ } = useStyles(props);
2130
+ return /*#__PURE__*/React.createElement(Form, {
2131
+ decorators: [focusOnErrorDecorator],
2132
+ initialValues: initialValues,
2133
+ initialValuesEqual: initialValuesEqual,
2134
+ mutators: mutators,
2135
+ render: ({
2136
+ handleSubmit,
2137
+ submitError,
2138
+ modifiedSinceLastSubmit,
2139
+ form
2140
+ }) => {
2141
+ return /*#__PURE__*/React.createElement("form", {
2142
+ style: formStyles,
2143
+ className: clsx(className, 'form', set && `form_set_${set}`, type && `form_type_${type}`, directionClass, fillClass, shapeClass, elevationClass),
2144
+ name: formName,
2145
+ "data-tour": dataTour,
2146
+ ref: () => onRefFormInstance(form),
2147
+ onSubmit: handleSubmit,
2148
+ autoComplete: disableFieldsAutoComplete ? 'off' : undefined,
2149
+ autoCorrect: disableFieldsAutoComplete ? 'off' : undefined,
2150
+ autoCapitalize: disableFieldsAutoComplete ? 'off' : undefined,
2151
+ spellCheck: disableFieldsAutoComplete ? 'false' : undefined
2152
+ }, before, title && /*#__PURE__*/React.createElement(Title, {
2153
+ className: "form__title",
2154
+ size: titleTextSize,
2155
+ textColor: titleTextColor,
2156
+ textWeight: titleTextWeight
2157
+ }, title), description && /*#__PURE__*/React.createElement(Text, {
2158
+ className: "form__description",
2159
+ size: descriptionSize,
2160
+ textColor: descriptionTextColor,
2161
+ textWeight: descriptionTextWeight
2162
+ }, description), submitError && !modifiedSinceLastSubmit && /*#__PURE__*/React.createElement("div", {
2163
+ className: clsx('notification', 'form-notification', notificationType ? `form-notification_type_${notificationType}` : 'form-notification_type_global')
2164
+ }, /*#__PURE__*/React.createElement(NotificationItem, {
2165
+ className: "form-notification__item",
2166
+ titleTextSize: "h6",
2167
+ notificationClose: notificationClose,
2168
+ title: form.getState().submitError,
2169
+ set: "form",
2170
+ status: "error"
2171
+ })), onChangeFormValues && /*#__PURE__*/React.createElement(FormSpy, {
2172
+ subscription: {
2173
+ values: true
2174
+ },
2175
+ onChange: onChangeFormValues
2176
+ }), Boolean(Object.keys(config).length) && /*#__PURE__*/React.createElement(Group$1, {
2177
+ direction: "vertical",
2178
+ gap: fieldsGap || groupGap,
2179
+ className: "form__wrapper"
2180
+ }, Object.keys(config).map(key => generateField(config[key], {
2181
+ key
2182
+ }, additionalProps[config[key].name])), isLoading && (loader || /*#__PURE__*/React.createElement(Loader, {
2183
+ className: "form__loader",
2184
+ set: loaderSet,
2185
+ fill: loaderFill,
2186
+ itemFill: loaderItemFill,
2187
+ text: loaderText
2188
+ }))), (primaryButtonLabel || primaryButton || secondaryButtonLabel || secondaryButton || tertiaryButton || tertiaryButtonLabel) && /*#__PURE__*/React.createElement(Group$1, {
2189
+ fill: buttonFill,
2190
+ justifyContent: buttonJustifyContent,
2191
+ direction: buttonDirection,
2192
+ padding: buttonPadding,
2193
+ gap: buttonGap,
2194
+ className: "form__button",
2195
+ dataTour: dataTourButtons
2196
+ }, primaryButtonLabel ? /*#__PURE__*/React.createElement(Button, {
2197
+ width: "fill",
2198
+ className: "form__button-item",
2199
+ fill: primaryButtonFill,
2200
+ fillHover: primaryButtonFillHover,
2201
+ size: primaryButtonSize,
2202
+ labelTextColor: primaryButtonLabelTextColor,
2203
+ labelSize: primaryButtonLabelSize,
2204
+ labelTextWeight: primaryButtonLabelTextWeight,
2205
+ label: primaryButtonLabel,
2206
+ dataTour: dataTourPrimaryButton
2207
+ }) : primaryButton, secondaryButtonLabel ? /*#__PURE__*/React.createElement(Button, {
2208
+ width: "fill",
2209
+ className: "form__button-item",
2210
+ fill: secondaryButtonFill,
2211
+ fillHover: secondaryButtonFillHover,
2212
+ size: secondaryButtonSize,
2213
+ labelTextColor: secondaryButtonLabelTextColor,
2214
+ labelSize: secondaryButtonLabelSize,
2215
+ labelTextWeight: secondaryButtonLabelTextWeight,
2216
+ label: secondaryButtonLabel,
2217
+ onClick: onClickSecondaryButton,
2218
+ dataTour: dataTourSecondaryButton
2219
+ }) : secondaryButton, tertiaryButtonLabel ? /*#__PURE__*/React.createElement(Button, {
2220
+ width: "fill",
2221
+ className: "form__button-item",
2222
+ fill: tertiaryButtonFill,
2223
+ fillHover: tertiaryButtonFillHover,
2224
+ size: tertiaryButtonSize,
2225
+ labelTextColor: tertiaryButtonLabelTextColor,
2226
+ labelSize: tertiaryButtonLabelSize,
2227
+ labelTextWeight: tertiaryButtonLabelTextWeight,
2228
+ label: tertiaryButtonLabel,
2229
+ onClick: onClickTertiaryButton,
2230
+ dataTour: dataTourTertiaryButton
2231
+ }) : tertiaryButton), after);
2232
+ },
2233
+ subscription: {
2234
+ submitting: true,
2235
+ pristine: true,
2236
+ modifiedSinceLastSubmit: true,
2237
+ submitError: true
2238
+ },
2239
+ validate: validate,
2240
+ onSubmit: onSubmit
2241
+ });
2242
+ });
2243
+ FinalForm.propTypes = {
2244
+ additionalProps: PropTypes.object,
2245
+ after: PropTypes.any,
2246
+ before: PropTypes.any,
2247
+ buttonGap: PropTypes.string,
2248
+ className: PropTypes.string,
2249
+ config: PropTypes.object,
2250
+ description: PropTypes.string,
2251
+ descriptionSize: PropTypes.string,
2252
+ descriptionTextColor: PropTypes.string,
2253
+ descriptionTextWeight: PropTypes.string,
2254
+ disableFieldsAutoComplete: PropTypes.string,
2255
+ fieldsGap: PropTypes.string,
2256
+ formName: PropTypes.string,
2257
+ initialValues: PropTypes.any,
2258
+ initialValuesEqual: PropTypes.any,
2259
+ language: PropTypes.string,
2260
+ isLoading: PropTypes.bool,
2261
+ loaderText: PropTypes.string,
2262
+ mutators: PropTypes.any,
2263
+ onChangeFormValues: PropTypes.func,
2264
+ onClickSecondaryButton: PropTypes.func,
2265
+ onSubmit: PropTypes.func,
2266
+ primaryButton: PropTypes.string,
2267
+ primaryButtonFill: PropTypes.string,
2268
+ primaryButtonLabel: PropTypes.string,
2269
+ secondaryButton: PropTypes.string,
2270
+ secondaryButtonFill: PropTypes.string,
2271
+ secondaryButtonLabel: PropTypes.string,
2272
+ set: PropTypes.string,
2273
+ title: PropTypes.string,
2274
+ titleSize: PropTypes.string,
2275
+ titleTextColor: PropTypes.string,
2276
+ titleTextWeight: PropTypes.string,
2277
+ validationSchema: PropTypes.object
2278
+ };
2279
+ FinalForm.defaultProps = {
2280
+ additionalProps: {},
2281
+ isLoading: false,
2282
+ loaderSet: 'simple',
2283
+ loaderFill: 'surfacePrimary',
2284
+ loaderItemFill: 'surfaceItemAccent',
2285
+ language: 'en',
2286
+ titleSize: 'h1',
2287
+ buttonDirection: 'vertical',
2288
+ direction: 'vertical',
2289
+ disableFieldsAutoComplete: false
2290
+ };
2291
+
2292
+ export { CheckboxField as Checkbox, ChoiceField, CodeField, CustomField, DatePickerField, FieldWrapper, FieldWrapperBase, FileInput, FinalForm, Group, InputField, RadioGroup, SegmentedField, SelectField, SwitchField as Switch, TextareaField as Textarea, addRequiredFieldsParamToSchema, emailValidation, focusOnError, focusOnErrorDecorator, formTypes, generateField, phoneValidation, sendFormDataToServer, setErrorsMutator, useYupValidationSchema };