form-father 0.1.6 → 0.1.7
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.
- package/FormFather.min.js +1 -1
- package/index.d.ts +7 -0
- package/index.js +146 -28
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/types/index.d.ts +7 -0
package/FormFather.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var FormFather=function(t){"use strict";function e(t,e,r,o){return new(r||(r=Promise))((function(n,i){function s(t){try{a(o.next(t))}catch(t){i(t)}}function l(t){try{a(o.throw(t))}catch(t){i(t)}}function a(t){var e;t.done?n(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(s,l)}a((o=o.apply(t,e||[])).next())}))}function r(t){const e="FORM"===t.tagName?Array.from(t.elements):Array.from(t.querySelectorAll("input, select, textarea, button")),r=new FormData;return e.forEach((t=>{if(!(t instanceof HTMLInputElement||t instanceof HTMLSelectElement||t instanceof HTMLTextAreaElement||t instanceof HTMLButtonElement))return;if(!t.name||t.hasAttribute("data-no-serialize"))return;const{name:e,type:o}=t;if("file"===o)if("true"===t.getAttribute("multiple")){const o=t.files;if(o)for(let t=0;t<o.length;t++)r.append(`${e}[${t}]`,o[t])}else{const o=t.files;o&&o[0]&&r.append(e,o[0])}else{let n;if("select-one"===o||"select-multiple"===o){const i=t;if("select-multiple"===o){Array.from(i.selectedOptions).map((t=>t.value)).forEach(((t,o)=>{r.append(`${e}[${o}]`,t)}))}else n=i.value,n&&r.append(e,n)}else if("tel"===o)n=t.value.split(/[\s()-]/).join("").replace(/^8/,"+7");else if("checkbox"===o||"radio"===o){if(!t.checked)return;n=t.value}else if("date"===o){const e=t.getAttribute("data-date-format");n=e?function(t,e){const r=new Date(t),o=t=>t.toString().padStart(2,"0"),n=o(r.getDate()),i=o(r.getMonth()+1),s=r.getFullYear().toString();return e.replace("dd",n).replace("mm",i).replace("yyyy",s)}(t.value,e):t.value}else n=t.value;n&&"select-one"!==o&&"select-multiple"!==o&&r.append(e,n)}})),r}var o;"function"==typeof SuppressedError&&SuppressedError;const n=Symbol.for("FormFather.validators"),i=null!==(o=globalThis[n])&&void 0!==o?o:globalThis[n]=new Map;function s(t,e,r,{override:o=!1}={}){!i.has(t)||o?i.set(t,{fn:e,defaultMessage:r}):console.warn(`[FormFather] Validator "${t}" already exists; pass { override: true } to replace`)}const l=t=>i.get(t);s("required",((t,e,r)=>{if(e&&e.type){if("checkbox"===e.type)return e.checked;if("radio"===e.type){const t=r.querySelectorAll(`input[type="radio"][name="${e.name}"]`);return Array.from(t).some((t=>t.checked))}}return t.trim().length>0}),"Пустое значение"),s("email",(t=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)),"Неверный формат"),s("tel",(t=>/^\+7\d{10}$/.test(t)),"Неверный формат"),s("url",(t=>/^(https?:\/\/).+\..+/.test(t)),"Неверный формат"),s("not-numbers",(t=>!/[0-9]/.test(t)),"Неверный формат");class a{constructor(t,e){this.$submit=null,this.waitResponse=!1,this.inputs=null,this.$licensesCheckbox=null,this.$el=t,this.options=e;this.config=Object.assign({},{onSubmit:()=>{},onResponse:()=>{},onResponseSuccess:()=>{},onResponseUnsuccess:()=>{},customTypeError:null,loaderColor:"#fff",showLoaderButton:!0,scrollToFirstErroredInput:!0,logging:!1,inputSelector:".input",inputWrapperSelector:".input-primary"},a.defaultParams,e),this.$el?(this.$submit=this.$el.querySelector('input[type="submit"], button[type="submit"]'),this.isCorrectArguments()&&this.initialization()):console.warn("Empty $el")}getOptions(){return this.options}static setDefaultParams(t){this.defaultParams=Object.assign(Object.assign({},this.defaultParams),t)}initialization(){this.inputs=this.$el.querySelectorAll(this.config.inputSelector);const t=()=>e(this,void 0,void 0,(function*(){var t;const e=this.$el.getAttribute("action")||"",o=(null===(t=this.$el.getAttribute("method"))||void 0===t?void 0:t.toUpperCase())||"POST",n=this.$el.getAttribute("enctype")||"application/x-www-form-urlencoded";let i=null,s={};const l=r(this.$el);let a={};if(l.forEach(((t,e)=>{a[e]=t})),this.config.logging)for(const t of l.keys())console.log(l.get(t));switch("function"==typeof this.config.wrapData&&(a=this.config.wrapData(a)),n){case"application/x-www-form-urlencoded":i=new URLSearchParams(r(this.$el)).toString(),s["Content-Type"]="application/x-www-form-urlencoded";break;case"multipart/form-data":i=r(this.$el);break;case"text/plain":i=Array.from(r(this.$el)).map((([t,e])=>`${encodeURIComponent(t)}=${encodeURIComponent(e)}`)).join("\n"),s["Content-Type"]="text/plain";break;case"application/json":i=JSON.stringify(a),s["Content-Type"]="application/json";break;default:console.warn(`Неизвестный enctype: ${n}. Используется application/x-www-form-urlencoded.`),i=new URLSearchParams(r(this.$el)).toString(),s["Content-Type"]="application/x-www-form-urlencoded"}return fetch(e,{method:o,body:i,headers:s})})),o=()=>e(this,void 0,void 0,(function*(){var e,r,o,n,i,s,l,a;if(!this.waitResponse){!0===this.config.showLoaderButton&&this.showLoader(),null===(r=(e=this.config).onSubmit)||void 0===r||r.call(e,this),this.waitResponse=!0;const c=yield t(),u=yield c.json();if(this.waitResponse=!1,!0===this.config.showLoaderButton&&this.hideLoader(),null===(n=(o=this.config).onResponse)||void 0===n||n.call(o,u,this),200===c.status)if(function(t){if(Object.prototype.hasOwnProperty.call(t,"redirect-url")&&(window.location.href=t["redirect-url"]),Object.prototype.hasOwnProperty.call(t,"reload")&&!0===t.reload&&window.location.reload(),Object.prototype.hasOwnProperty.call(t,"error-toast")){const e=document.querySelector('[data-toast-name="formErrorToast"]');if(e){const r=e.querySelector(".toast__text");r&&(r.textContent=t["error-toast"],window.Toast.showToast("formErrorToast",{removeAfterClose:!1}))}}}(u),!0===u.success)null===(s=(i=this.config).onResponseSuccess)||void 0===s||s.call(i,u,this);else if(null===(a=(l=this.config).onResponseUnsuccess)||void 0===a||a.call(l,u,this),!0===u.error&&(u["error-msg"]&&this.showErrorForm(u["error-msg"]),u.errors)){const t=[];u.errors.forEach((e=>{const r=this.$el.querySelector(`input[name="${e.name}"]`);r?(t.push(r),this.showError(r,e["error-msg"])):console.warn(`Не найдено поле с именем: ${e.name}, для вывода ошибки: ${e["error-msg"]}`)})),!0===this.config.scrollToFirstErroredInput&&this.scrollToFirstErroredInput(t)}}}));this.$el.addEventListener("submit",(t=>e(this,void 0,void 0,(function*(){var e,r,n,i;t.preventDefault(),null===(r=(e=this.config).onBeforeValidate)||void 0===r||r.call(e,this);const s=yield this.validate();null===(i=(n=this.config).onAfterValidate)||void 0===i||i.call(n,s,this),s&&o()}))))}showError(t,e){(function(t,e){if(null==t)return null;let r=t;for(;r;){if(r.matches(e))return r;r=r.parentElement}return null})(t,this.config.inputWrapperSelector).showError(e)}showLoader(){var t;const e=`\n\t\t\t<svg height="38" viewBox="0 0 38 38" width="38" xmlns="http://www.w3.org/2000/svg">\n\t\t\t\t<defs>\n\t\t\t\t<linearGradient id="form-father-loader" x1="8.042%" x2="65.682%" y1="0%" y2="23.865%">\n\t\t\t\t\t<stop offset="0%" stop-color="${this.config.loaderColor}" stop-opacity="0"/>\n\t\t\t\t\t<stop offset="63.146%" stop-color="${this.config.loaderColor}" stop-opacity=".631"/>\n\t\t\t\t\t<stop offset="100%" stop-color="${this.config.loaderColor}"/>\n\t\t\t\t</linearGradient>\n\t\t\t\t</defs>\n\t\t\t\t<g fill-rule="evenodd" fill="none">\n\t\t\t\t<g transform="translate(1 1)">\n\t\t\t\t\t<path d="M36 18c0-9.94-8.06-18-18-18" id="Oval-2" stroke-width="5" stroke="url(#form-father-loader)"></path>\n\t\t\t\t\t<circle cx="36" cy="18" fill="${this.config.loaderColor}" r="1"></circle>\n\t\t\t\t</g>\n\t\t\t\t</g>\n\t\t\t</svg>\n\t\t`,r=document.createElement("span");r.innerHTML=e,r.className="button__loader",null===(t=this.$submit)||void 0===t||t.insertAdjacentElement("afterbegin",r),requestAnimationFrame((()=>{r.setAttribute("data-showed","")}))}hideLoader(){var t,e;null===(t=this.$submit)||void 0===t||t.classList.remove("button--loading");const r=null===(e=this.$submit)||void 0===e?void 0:e.querySelector(".button__loader");r&&(r.classList.remove("active"),r.removeAttribute("data-showed"),setTimeout((()=>{r.remove()}),250))}hideError(t){const e=t.parentElement;e&&e.classList.contains("input__wrapper")&&(e.getAttribute("data-type-error"),e.classList.remove("input__wrapper--error"))}scrollToFirstErroredInput(t){if(t.length>0){const e=Array.from(this.$el.querySelectorAll("input"));let r=null,o=1/0;if(t.forEach((t=>{const n=e.findIndex((e=>e===t));n<o&&(o=n,r=t)})),r){const t=r.getBoundingClientRect(),e=window.pageYOffset||document.documentElement.scrollTop,o=t.top+e-window.innerHeight/2;document.documentElement.setAttribute("data-now-scrolling",""),window.scrollTo({top:o,behavior:"smooth"}),setTimeout((()=>{document.documentElement.removeAttribute("data-now-scrolling")}),800)}}}validate(){return e(this,void 0,void 0,(function*(){const t=Object.assign(Object.assign({},a.defaultValidationSchema||{}),this.config.validationSchema||{}),r=t=>console.warn(`[FormFather] Unknown validation rule "${t}"`),o=[],n=new WeakSet;let i=!0;const s=(t,e=[])=>{var o;const n=[];t.hasAttribute("required")&&n.push("required"),n.push(...e);const i=(null!==(o=t.getAttribute("data-custom-validate"))&&void 0!==o?o:"").split(",").map((t=>t.trim())).filter(Boolean);n.push(...i);const s=[];for(const t of n){const e="string"==typeof t?t:t.rule;l(e)?s.push(t):r(e)}return s},c=(t,r,...n)=>e(this,[t,r,...n],void 0,(function*(t,e,r={}){var n;if(!("checkbox"===t.type||"radio"===t.type?!t.checked:0===t.value.trim().length)||e.includes("required")){for(const s of e){const{rule:e,params:a}="string"==typeof s?{rule:s,params:void 0}:s,c=l(e);if(!(yield c.fn(t.value,t,this.$el,a))){i=!1;const s=null!==(n=r[e])&&void 0!==n?n:c.defaultMessage;return this.showError(t,s),void o.push(t)}}this.hideError(t)}else this.hideError(t)}));for(const[e,r]of Object.entries(t)){const{selector:t,rules:o=[],messages:i={}}=r,l=t?this.$el.querySelectorAll(t):this.$el.querySelectorAll(`[data-validate="${e}"]`);for(const t of Array.from(l))n.has(t)||(n.add(t),yield c(t,s(t,o),i))}const u=Array.from(this.$el.querySelectorAll("[data-custom-validate]")).filter((t=>!n.has(t)));for(const t of u)n.add(t),yield c(t,s(t,[]));return!i&&this.config.scrollToFirstErroredInput&&this.scrollToFirstErroredInput(o),i}))}disableSubmit(){var t;null===(t=this.$submit)||void 0===t||t.setAttribute("disabled","")}enableSubmit(){var t;null===(t=this.$submit)||void 0===t||t.removeAttribute("disabled")}clearInputs(){var t;null===(t=this.inputs)||void 0===t||t.forEach((t=>{var e;const r=t;"radio"===r.type||"checkbox"===r.type?r.checked=!1:(r.value="",null===(e=r.parentElement)||void 0===e||e.classList.remove("filled"),r.dispatchEvent(new Event("input")))}))}showErrorForm(t){var e;const r=this.$el.querySelectorAll(this.config.inputWrapperSelector),o=r[r.length-1];let n=this.$el.querySelector(".error-block-under-input__wrapper");n&&o.nextElementSibling===n?(n.classList.add("error-block-under-input--warning"),n.querySelector(".error-block-under-input__icon").innerHTML="\x3c!-- SVG content --\x3e",n.querySelector(".error-block-under-input__main-text").textContent=t):(n=document.createElement("div"),n.className="error-block-under-input__wrapper",n.innerHTML=`\n <div class="error-block-under-input error-block-under-input--warning">\n <div class="error-block-under-input__icon-wrapper">\n <span class="error-block-under-input__icon">\n \x3c!-- SVG content --\x3e\n </span>\n <span class="error-block-under-input__icon error-block-under-input__icon--animated" style="display:none;"></span>\n </div>\n <p class="error-block-under-input__text">\n <span class="error-block-under-input__main-text">${t}</span>\n <span class="error-block-under-input__secondary-text"></span>\n </p>\n </div>`,o.insertAdjacentElement("afterend",n)),this.$el.addEventListener("input",(()=>{this.hideErrorForm()}),{passive:!0,once:!0}),null===(e=n.querySelector(".error-block-under-input"))||void 0===e||e.classList.remove("error-block-under-input--success");const i=n.querySelector(".error-block-under-input__secondary-text");i&&(i.textContent="");const s=parseFloat(n.style.height)||0,l=parseFloat(window.getComputedStyle(n).paddingTop)||0;s!==n.querySelector(".error-block-under-input").scrollHeight+16&&(n.style.height=`${s}px`,n.style.opacity="0",n.style.paddingTop=`${l}px`)}hideErrorForm(){const t=this.$el.querySelectorAll(this.config.inputWrapperSelector),e=t[t.length-1].nextElementSibling;e&&e.classList.contains("error-block-under-input__wrapper")}isCorrectArguments(){return"FORM"!==this.$el.tagName?(console.warn("$el не является тегом form"),!1):!!this.$submit||(console.warn("В форме нет кнопки с типом submit"),!1)}}return a.defaultParams={},a.defaultValidationSchema={tel:{selector:'input[type="tel"]',rules:["tel"]},email:{selector:'input[type="email"]',rules:["email"]},required:{selector:"[required]",rules:["required"]},url:{selector:'input[type="url"]',rules:["url"]},"not-numbers":{selector:'input[data-validate="not-numbers"]',rules:["not-numbers"]}},t.default=a,t.getAllValidators=function(){return new Map(i)},t.getValidator=l,t.registerValidator=s,Object.defineProperty(t,"__esModule",{value:!0}),t}({});
|
|
1
|
+
var FormFather=function(t){"use strict";function e(t,e,o,r){return new(o||(o=Promise))((function(n,i){function s(t){try{l(r.next(t))}catch(t){i(t)}}function a(t){try{l(r.throw(t))}catch(t){i(t)}}function l(t){var e;t.done?n(t.value):(e=t.value,e instanceof o?e:new o((function(t){t(e)}))).then(s,a)}l((r=r.apply(t,e||[])).next())}))}function o(t){const e="FORM"===t.tagName?Array.from(t.elements):Array.from(t.querySelectorAll("input, select, textarea, button")),o=new FormData;return e.forEach((t=>{if(!(t instanceof HTMLInputElement||t instanceof HTMLSelectElement||t instanceof HTMLTextAreaElement||t instanceof HTMLButtonElement))return;if(!t.name||t.hasAttribute("data-no-serialize"))return;const{name:e,type:r}=t;if("file"===r)if("true"===t.getAttribute("multiple")){const r=t.files;if(r)for(let t=0;t<r.length;t++)o.append(`${e}[${t}]`,r[t])}else{const r=t.files;r&&r[0]&&o.append(e,r[0])}else{let n;if("select-one"===r||"select-multiple"===r){const i=t;if("select-multiple"===r){Array.from(i.selectedOptions).map((t=>t.value)).forEach(((t,r)=>{o.append(`${e}[${r}]`,t)}))}else n=i.value,n&&o.append(e,n)}else if("tel"===r)n=t.value.split(/[\s()-]/).join("").replace(/^8/,"+7");else if("checkbox"===r||"radio"===r){if(!t.checked)return;n=t.value}else if("date"===r){const e=t.getAttribute("data-date-format");n=e?function(t,e){const o=new Date(t),r=t=>t.toString().padStart(2,"0"),n=r(o.getDate()),i=r(o.getMonth()+1),s=o.getFullYear().toString();return e.replace("dd",n).replace("mm",i).replace("yyyy",s)}(t.value,e):t.value}else n=t.value;n&&"select-one"!==r&&"select-multiple"!==r&&o.append(e,n)}})),o}var r;"function"==typeof SuppressedError&&SuppressedError;const n=Symbol.for("FormFather.validators"),i=null!==(r=globalThis[n])&&void 0!==r?r:globalThis[n]=new Map;function s(t,e,o,{override:r=!1}={}){!i.has(t)||r?i.set(t,{fn:e,defaultMessage:o}):console.warn(`[FormFather] Validator "${t}" already exists; pass { override: true } to replace`)}const a=t=>i.get(t);s("required",((t,e,o)=>{if(e&&e.type){if("checkbox"===e.type)return e.checked;if("radio"===e.type){const t=o.querySelectorAll(`input[type="radio"][name="${e.name}"]`);return Array.from(t).some((t=>t.checked))}}return t.trim().length>0}),"Пустое значение"),s("email",(t=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)),"Неверный формат"),s("tel",(t=>/^\+7\d{10}$/.test(t)),"Неверный формат"),s("url",(t=>/^(https?:\/\/).+\..+/.test(t)),"Неверный формат"),s("not-numbers",(t=>!/[0-9]/.test(t)),"Неверный формат");class l{constructor(t,e){this.$submit=null,this.waitResponse=!1,this.inputs=null,this.$licensesCheckbox=null,this._anim={duration:220,easing:"ease",paddingTopOpened:16,iconDuration:700},this.$el=t,this.options=e;this.config=Object.assign({},{onSubmit:()=>{},onResponse:()=>{},onResponseSuccess:()=>{},onResponseUnsuccess:()=>{},customTypeError:null,loaderColor:"#fff",showLoaderButton:!0,scrollToFirstErroredInput:!0,logging:!1,inputSelector:".input",inputWrapperSelector:".input-primary"},l.defaultParams,e),this.$el?(this.$submit=this.$el.querySelector('input[type="submit"], button[type="submit"]'),this.isCorrectArguments()&&this.initialization()):console.warn("Empty $el")}getOptions(){return this.options}static setDefaultParams(t){this.defaultParams=Object.assign(Object.assign({},this.defaultParams),t)}initialization(){this.inputs=this.$el.querySelectorAll(this.config.inputSelector);const t=()=>e(this,void 0,void 0,(function*(){var t;const e=this.$el.getAttribute("action")||"",r=(null===(t=this.$el.getAttribute("method"))||void 0===t?void 0:t.toUpperCase())||"POST",n=this.$el.getAttribute("enctype")||"application/x-www-form-urlencoded";let i=null,s={};const a=o(this.$el);let l={};if(a.forEach(((t,e)=>{l[e]=t})),this.config.logging)for(const t of a.keys())console.log(a.get(t));switch("function"==typeof this.config.wrapData&&(l=this.config.wrapData(l)),n){case"application/x-www-form-urlencoded":i=new URLSearchParams(o(this.$el)).toString(),s["Content-Type"]="application/x-www-form-urlencoded";break;case"multipart/form-data":i=o(this.$el);break;case"text/plain":i=Array.from(o(this.$el)).map((([t,e])=>`${encodeURIComponent(t)}=${encodeURIComponent(e)}`)).join("\n"),s["Content-Type"]="text/plain";break;case"application/json":i=JSON.stringify(l),s["Content-Type"]="application/json";break;default:console.warn(`Неизвестный enctype: ${n}. Используется application/x-www-form-urlencoded.`),i=new URLSearchParams(o(this.$el)).toString(),s["Content-Type"]="application/x-www-form-urlencoded"}return fetch(e,{method:r,body:i,headers:s})})),r=()=>e(this,void 0,void 0,(function*(){var e,o,r,n,i,s,a,l;if(!this.waitResponse){!0===this.config.showLoaderButton&&this.showLoader(),null===(o=(e=this.config).onSubmit)||void 0===o||o.call(e,this),this.waitResponse=!0;const c=yield t(),d=yield c.json();if(this.waitResponse=!1,!0===this.config.showLoaderButton&&this.hideLoader(),null===(n=(r=this.config).onResponse)||void 0===n||n.call(r,d,this),200===c.status)if(function(t){if(Object.prototype.hasOwnProperty.call(t,"redirect-url")&&(window.location.href=t["redirect-url"]),Object.prototype.hasOwnProperty.call(t,"reload")&&!0===t.reload&&window.location.reload(),Object.prototype.hasOwnProperty.call(t,"error-toast")){const e=document.querySelector('[data-toast-name="formErrorToast"]');if(e){const o=e.querySelector(".toast__text");o&&(o.textContent=t["error-toast"],window.Toast.showToast("formErrorToast",{removeAfterClose:!1}))}}}(d),!0===d.success)null===(s=(i=this.config).onResponseSuccess)||void 0===s||s.call(i,d,this);else if(null===(l=(a=this.config).onResponseUnsuccess)||void 0===l||l.call(a,d,this),!0===d.error&&(d["error-msg"]&&this.showErrorForm(d["error-msg"]),d.errors)){const t=[];d.errors.forEach((e=>{const o=this.$el.querySelector(`input[name="${e.name}"]`);o?(t.push(o),this.showError(o,e["error-msg"])):console.warn(`Не найдено поле с именем: ${e.name}, для вывода ошибки: ${e["error-msg"]}`)})),!0===this.config.scrollToFirstErroredInput&&this.scrollToFirstErroredInput(t)}}}));this.$el.addEventListener("submit",(t=>e(this,void 0,void 0,(function*(){var e,o,n,i;t.preventDefault(),null===(o=(e=this.config).onBeforeValidate)||void 0===o||o.call(e,this);const s=yield this.validate();null===(i=(n=this.config).onAfterValidate)||void 0===i||i.call(n,s,this),s&&r()}))))}showError(t,e){(function(t,e){if(null==t)return null;let o=t;for(;o;){if(o.matches(e))return o;o=o.parentElement}return null})(t,this.config.inputWrapperSelector).showError(e)}showLoader(){var t;const e=`\n\t\t\t<svg height="38" viewBox="0 0 38 38" width="38" xmlns="http://www.w3.org/2000/svg">\n\t\t\t\t<defs>\n\t\t\t\t<linearGradient id="form-father-loader" x1="8.042%" x2="65.682%" y1="0%" y2="23.865%">\n\t\t\t\t\t<stop offset="0%" stop-color="${this.config.loaderColor}" stop-opacity="0"/>\n\t\t\t\t\t<stop offset="63.146%" stop-color="${this.config.loaderColor}" stop-opacity=".631"/>\n\t\t\t\t\t<stop offset="100%" stop-color="${this.config.loaderColor}"/>\n\t\t\t\t</linearGradient>\n\t\t\t\t</defs>\n\t\t\t\t<g fill-rule="evenodd" fill="none">\n\t\t\t\t<g transform="translate(1 1)">\n\t\t\t\t\t<path d="M36 18c0-9.94-8.06-18-18-18" id="Oval-2" stroke-width="5" stroke="url(#form-father-loader)"></path>\n\t\t\t\t\t<circle cx="36" cy="18" fill="${this.config.loaderColor}" r="1"></circle>\n\t\t\t\t</g>\n\t\t\t\t</g>\n\t\t\t</svg>\n\t\t`,o=document.createElement("span");o.innerHTML=e,o.className="button__loader",null===(t=this.$submit)||void 0===t||t.insertAdjacentElement("afterbegin",o),requestAnimationFrame((()=>{o.setAttribute("data-showed","")}))}hideLoader(){var t,e;null===(t=this.$submit)||void 0===t||t.classList.remove("button--loading");const o=null===(e=this.$submit)||void 0===e?void 0:e.querySelector(".button__loader");o&&(o.classList.remove("active"),o.removeAttribute("data-showed"),setTimeout((()=>{o.remove()}),250))}hideError(t){const e=t.parentElement;e&&e.classList.contains("input__wrapper")&&(e.getAttribute("data-type-error"),e.classList.remove("input__wrapper--error"))}scrollToFirstErroredInput(t){if(t.length>0){const e=Array.from(this.$el.querySelectorAll("input"));let o=null,r=1/0;if(t.forEach((t=>{const n=e.findIndex((e=>e===t));n<r&&(r=n,o=t)})),o){const t=o.getBoundingClientRect(),e=window.pageYOffset||document.documentElement.scrollTop,r=t.top+e-window.innerHeight/2;document.documentElement.setAttribute("data-now-scrolling",""),window.scrollTo({top:r,behavior:"smooth"}),setTimeout((()=>{document.documentElement.removeAttribute("data-now-scrolling")}),800)}}}validate(){return e(this,void 0,void 0,(function*(){const t=Object.assign(Object.assign({},l.defaultValidationSchema||{}),this.config.validationSchema||{}),o=t=>console.warn(`[FormFather] Unknown validation rule "${t}"`),r=[],n=new WeakSet;let i=!0;const s=(t,e=[])=>{var r;const n=[];t.hasAttribute("required")&&n.push("required"),n.push(...e);const i=(null!==(r=t.getAttribute("data-custom-validate"))&&void 0!==r?r:"").split(",").map((t=>t.trim())).filter(Boolean);n.push(...i);const s=[];for(const t of n){const e="string"==typeof t?t:t.rule;a(e)?s.push(t):o(e)}return s},c=(t,o,...n)=>e(this,[t,o,...n],void 0,(function*(t,e,o={}){var n;if(!("checkbox"===t.type||"radio"===t.type?!t.checked:0===t.value.trim().length)||e.includes("required")){for(const s of e){const{rule:e,params:l}="string"==typeof s?{rule:s,params:void 0}:s,c=a(e);if(!(yield c.fn(t.value,t,this.$el,l))){i=!1;const s=null!==(n=o[e])&&void 0!==n?n:c.defaultMessage;return this.showError(t,s),void r.push(t)}}this.hideError(t)}else this.hideError(t)}));for(const[e,o]of Object.entries(t)){const{selector:t,rules:r=[],messages:i={}}=o,a=t?this.$el.querySelectorAll(t):this.$el.querySelectorAll(`[data-validate="${e}"]`);for(const t of Array.from(a))n.has(t)||(n.add(t),yield c(t,s(t,r),i))}const d=Array.from(this.$el.querySelectorAll("[data-custom-validate]")).filter((t=>!n.has(t)));for(const t of d)n.add(t),yield c(t,s(t,[]));return!i&&this.config.scrollToFirstErroredInput&&this.scrollToFirstErroredInput(r),i}))}disableSubmit(){var t;null===(t=this.$submit)||void 0===t||t.setAttribute("disabled","")}enableSubmit(){var t;null===(t=this.$submit)||void 0===t||t.removeAttribute("disabled")}clearInputs(){var t;null===(t=this.inputs)||void 0===t||t.forEach((t=>{var e;const o=t;"radio"===o.type||"checkbox"===o.type?o.checked=!1:(o.value="",null===(e=o.parentElement)||void 0===e||e.classList.remove("filled"),o.dispatchEvent(new Event("input")))}))}_prefersReducedMotion(){var t;return"undefined"!=typeof window&&(null===(t=window.matchMedia)||void 0===t?void 0:t.call(window,"(prefers-reduced-motion: reduce)").matches)}_canAnimate(t){return!(!t||!("animate"in t)||this._prefersReducedMotion())}_cancelAnimations(t){var e;null===(e=null==t?void 0:t.getAnimations)||void 0===e||e.call(t).forEach((t=>t.cancel()))}showErrorForm(t){var e;const o=this.$el.querySelectorAll(this.config.inputWrapperSelector),r=o[o.length-1];let n=this.$el.querySelector(".error-block-under-input__wrapper");n&&r.nextElementSibling===n?(n.style.boxSizing="border-box",n.style.overflow="hidden"):(n=document.createElement("div"),n.className="error-block-under-input__wrapper",n.innerHTML='\n <div class="error-block-under-input error-block-under-input--warning" style="display:grid;grid-template-columns:auto 1fr;gap:8px;align-items:start;">\n <div class="error-block-under-input__icon-wrapper" style="position:relative;width:20px;height:20px;">\n <span class="error-block-under-input__icon" style="display:block;width:20px;height:20px;"></span>\n <span class="error-block-under-input__icon error-block-under-input__icon--animated" style="display:block;position:absolute;inset:0;"></span>\n </div>\n <p class="error-block-under-input__text" style="margin:0;">\n <span class="error-block-under-input__main-text"></span>\n <span class="error-block-under-input__secondary-text"></span>\n </p>\n </div>\n ',Object.assign(n.style,{boxSizing:"border-box",overflow:"hidden",height:"0px",paddingTop:"0px",opacity:"0"}),r.insertAdjacentElement("afterend",n)),n.querySelector(".error-block-under-input__main-text").textContent=t;const i=n.querySelector(".error-block-under-input__secondary-text");i&&(i.textContent=""),null===(e=n.querySelector(".error-block-under-input"))||void 0===e||e.classList.remove("error-block-under-input--success"),n.querySelector(".error-block-under-input");const s=n.style.height,a=n.style.paddingTop;n.style.height="auto",n.style.paddingTop=`${this._anim.paddingTopOpened}px`;const l=n.clientHeight;if(n.style.height=s||"0px",n.style.paddingTop=a||"0px",parseFloat(n.style.height)===l&&1===parseFloat(n.style.opacity||"1"))this._ringIcon(n);else{if(this._cancelAnimations(n),this._canAnimate(n)){n.animate([{height:`${parseFloat(n.style.height)||0}px`,paddingTop:`${parseFloat(n.style.paddingTop)||0}px`,opacity:parseFloat(n.style.opacity||"0")},{height:`${l}px`,paddingTop:`${this._anim.paddingTopOpened}px`,opacity:1}],{duration:this._anim.duration,easing:this._anim.easing,fill:"forwards"}).addEventListener("finish",(()=>{n.style.height="auto",n.style.paddingTop=`${this._anim.paddingTopOpened}px`,n.style.opacity="1"}))}else n.style.height="auto",n.style.paddingTop=`${this._anim.paddingTopOpened}px`,n.style.opacity="1";this._ringIcon(n)}this.$el.addEventListener("input",(()=>this.hideErrorForm()),{passive:!0,once:!0})}hideErrorForm(){const t=this.$el.querySelectorAll(this.config.inputWrapperSelector),e=t[t.length-1].nextElementSibling;if(!e||!e.classList.contains("error-block-under-input__wrapper"))return;if((""===e.style.height||"auto"===e.style.height)&&(e.style.height=`${e.clientHeight}px`),e.style.paddingTop=e.style.paddingTop||`${this._anim.paddingTopOpened}px`,e.style.opacity=e.style.opacity||"1",this._cancelAnimations(e),this._canAnimate(e)){e.animate([{height:`${parseFloat(e.style.height)||e.clientHeight}px`,paddingTop:`${parseFloat(e.style.paddingTop)||this._anim.paddingTopOpened}px`,opacity:parseFloat(e.style.opacity||"1")},{height:"0px",paddingTop:"0px",opacity:0}],{duration:this._anim.duration,easing:this._anim.easing,fill:"forwards"}).addEventListener("finish",(()=>{e.remove()}))}else e.remove()}_ringIcon(t){const e=t.querySelector(".error-block-under-input__icon--animated");e&&(this._cancelAnimations(e),this._canAnimate(e)&&e.animate([{transform:"rotate(0deg) scale(1)",opacity:0},{transform:"rotate(-8deg) scale(1.05)",opacity:1,offset:.15},{transform:"rotate(8deg) scale(1.05)",opacity:1,offset:.3},{transform:"rotate(-6deg) scale(1.03)",opacity:1,offset:.45},{transform:"rotate(6deg) scale(1.03)",opacity:1,offset:.6},{transform:"rotate(0deg) scale(1)",opacity:0}],{duration:this._anim.iconDuration,easing:"ease"}))}isCorrectArguments(){return"FORM"!==this.$el.tagName?(console.warn("$el не является тегом form"),!1):!!this.$submit||(console.warn("В форме нет кнопки с типом submit"),!1)}}return l.defaultParams={},l.defaultValidationSchema={tel:{selector:'input[type="tel"]',rules:["tel"]},email:{selector:'input[type="email"]',rules:["email"]},required:{selector:"[required]",rules:["required"]},url:{selector:'input[type="url"]',rules:["url"]},"not-numbers":{selector:'input[data-validate="not-numbers"]',rules:["not-numbers"]}},t.default=l,t.getAllValidators=function(){return new Map(i)},t.getValidator=a,t.registerValidator=s,Object.defineProperty(t,"__esModule",{value:!0}),t}({});
|
|
2
2
|
//# sourceMappingURL=FormFather.min.js.map
|
package/index.d.ts
CHANGED
|
@@ -155,6 +155,11 @@ declare class Form {
|
|
|
155
155
|
private enableSubmit;
|
|
156
156
|
/** Очищает поля ввода формы. */
|
|
157
157
|
clearInputs(): void;
|
|
158
|
+
/** Общие настройки анимаций (можно подправить под вкус) */
|
|
159
|
+
private readonly _anim;
|
|
160
|
+
private _prefersReducedMotion;
|
|
161
|
+
private _canAnimate;
|
|
162
|
+
private _cancelAnimations;
|
|
158
163
|
/**
|
|
159
164
|
* Показывает ошибку под полями ввода - ошибку, относящуюся ко всей форме.
|
|
160
165
|
*
|
|
@@ -163,6 +168,8 @@ declare class Form {
|
|
|
163
168
|
private showErrorForm;
|
|
164
169
|
/** Скрывает ошибку под полями ввода - ошибку, относящуюся ко всей форме. */
|
|
165
170
|
private hideErrorForm;
|
|
171
|
+
/** Короткая анимация иконки без CSS */
|
|
172
|
+
private _ringIcon;
|
|
166
173
|
/**
|
|
167
174
|
* Проверяет входные данные на их корректность.
|
|
168
175
|
*
|
package/index.js
CHANGED
|
@@ -233,6 +233,13 @@ class Form {
|
|
|
233
233
|
this.waitResponse = false;
|
|
234
234
|
this.inputs = null;
|
|
235
235
|
this.$licensesCheckbox = null;
|
|
236
|
+
/** Общие настройки анимаций (можно подправить под вкус) */
|
|
237
|
+
this._anim = {
|
|
238
|
+
duration: 220,
|
|
239
|
+
easing: 'ease',
|
|
240
|
+
paddingTopOpened: 16,
|
|
241
|
+
iconDuration: 700,
|
|
242
|
+
};
|
|
236
243
|
this.$el = $el;
|
|
237
244
|
this.options = options;
|
|
238
245
|
const defaultConfig = {
|
|
@@ -602,6 +609,19 @@ class Form {
|
|
|
602
609
|
}
|
|
603
610
|
});
|
|
604
611
|
}
|
|
612
|
+
_prefersReducedMotion() {
|
|
613
|
+
var _a;
|
|
614
|
+
return typeof window !== 'undefined' && ((_a = window.matchMedia) === null || _a === void 0 ? void 0 : _a.call(window, '(prefers-reduced-motion: reduce)').matches);
|
|
615
|
+
}
|
|
616
|
+
_canAnimate(el) {
|
|
617
|
+
return !!(el && 'animate' in el && !this._prefersReducedMotion());
|
|
618
|
+
}
|
|
619
|
+
_cancelAnimations(el) {
|
|
620
|
+
var _a;
|
|
621
|
+
// Отменяем все активные WAAPI-анимации у элемента
|
|
622
|
+
// @ts-ignore
|
|
623
|
+
(_a = el === null || el === void 0 ? void 0 : el.getAnimations) === null || _a === void 0 ? void 0 : _a.call(el).forEach((a) => a.cancel());
|
|
624
|
+
}
|
|
605
625
|
/**
|
|
606
626
|
* Показывает ошибку под полями ввода - ошибку, относящуюся ко всей форме.
|
|
607
627
|
*
|
|
@@ -616,47 +636,145 @@ class Form {
|
|
|
616
636
|
$errorWrapper = document.createElement('div');
|
|
617
637
|
$errorWrapper.className = 'error-block-under-input__wrapper';
|
|
618
638
|
$errorWrapper.innerHTML = `
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
<
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
639
|
+
<div class="error-block-under-input error-block-under-input--warning" style="display:grid;grid-template-columns:auto 1fr;gap:8px;align-items:start;">
|
|
640
|
+
<div class="error-block-under-input__icon-wrapper" style="position:relative;width:20px;height:20px;">
|
|
641
|
+
<span class="error-block-under-input__icon" style="display:block;width:20px;height:20px;"></span>
|
|
642
|
+
<span class="error-block-under-input__icon error-block-under-input__icon--animated" style="display:block;position:absolute;inset:0;"></span>
|
|
643
|
+
</div>
|
|
644
|
+
<p class="error-block-under-input__text" style="margin:0;">
|
|
645
|
+
<span class="error-block-under-input__main-text"></span>
|
|
646
|
+
<span class="error-block-under-input__secondary-text"></span>
|
|
647
|
+
</p>
|
|
648
|
+
</div>
|
|
649
|
+
`;
|
|
650
|
+
// Стартовые inline-стили для анимаций
|
|
651
|
+
Object.assign($errorWrapper.style, {
|
|
652
|
+
boxSizing: 'border-box',
|
|
653
|
+
overflow: 'hidden',
|
|
654
|
+
height: '0px',
|
|
655
|
+
paddingTop: '0px',
|
|
656
|
+
opacity: '0',
|
|
657
|
+
});
|
|
631
658
|
$lastInputWrapper.insertAdjacentElement('afterend', $errorWrapper);
|
|
632
659
|
}
|
|
633
660
|
else {
|
|
634
|
-
|
|
635
|
-
$errorWrapper.
|
|
636
|
-
$errorWrapper.
|
|
661
|
+
// убедимся, что нужные стартовые inline-стили есть
|
|
662
|
+
$errorWrapper.style.boxSizing = 'border-box';
|
|
663
|
+
$errorWrapper.style.overflow = 'hidden';
|
|
637
664
|
}
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
}, { passive: true, once: true });
|
|
641
|
-
(_a = $errorWrapper.querySelector('.error-block-under-input')) === null || _a === void 0 ? void 0 : _a.classList.remove('error-block-under-input--success');
|
|
665
|
+
// Текст
|
|
666
|
+
$errorWrapper.querySelector('.error-block-under-input__main-text').textContent = text;
|
|
642
667
|
const $secondaryText = $errorWrapper.querySelector('.error-block-under-input__secondary-text');
|
|
643
668
|
if ($secondaryText)
|
|
644
669
|
$secondaryText.textContent = '';
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
670
|
+
// Сброс success-класса, если он устанавливался где-то в другом коде
|
|
671
|
+
(_a = $errorWrapper.querySelector('.error-block-under-input')) === null || _a === void 0 ? void 0 : _a.classList.remove('error-block-under-input--success');
|
|
672
|
+
// Посчитать целевую высоту
|
|
673
|
+
$errorWrapper.querySelector('.error-block-under-input');
|
|
674
|
+
// Чтобы корректно мерить, временно выставим auto
|
|
675
|
+
const prevHeight = $errorWrapper.style.height;
|
|
676
|
+
const prevPadding = $errorWrapper.style.paddingTop;
|
|
677
|
+
$errorWrapper.style.height = 'auto';
|
|
678
|
+
$errorWrapper.style.paddingTop = `${this._anim.paddingTopOpened}px`;
|
|
679
|
+
const targetHeight = $errorWrapper.clientHeight; // фактическая высота открытого состояния
|
|
680
|
+
// Вернуть стартовое состояние (схлопнуто)
|
|
681
|
+
$errorWrapper.style.height = prevHeight || '0px';
|
|
682
|
+
$errorWrapper.style.paddingTop = prevPadding || '0px';
|
|
683
|
+
// Если уже раскрыт на нужную высоту — просто «дзынь» иконке и выходим
|
|
684
|
+
if (parseFloat($errorWrapper.style.height) === targetHeight &&
|
|
685
|
+
parseFloat($errorWrapper.style.opacity || '1') === 1) {
|
|
686
|
+
this._ringIcon($errorWrapper);
|
|
687
|
+
}
|
|
688
|
+
else {
|
|
689
|
+
// Анимация раскрытия
|
|
690
|
+
this._cancelAnimations($errorWrapper);
|
|
691
|
+
if (this._canAnimate($errorWrapper)) {
|
|
692
|
+
const anim = $errorWrapper.animate([
|
|
693
|
+
{
|
|
694
|
+
height: `${parseFloat($errorWrapper.style.height) || 0}px`,
|
|
695
|
+
paddingTop: `${parseFloat($errorWrapper.style.paddingTop) || 0}px`,
|
|
696
|
+
opacity: parseFloat($errorWrapper.style.opacity || '0'),
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
height: `${targetHeight}px`,
|
|
700
|
+
paddingTop: `${this._anim.paddingTopOpened}px`,
|
|
701
|
+
opacity: 1,
|
|
702
|
+
},
|
|
703
|
+
], { duration: this._anim.duration, easing: this._anim.easing, fill: 'forwards' });
|
|
704
|
+
anim.addEventListener('finish', () => {
|
|
705
|
+
// После анимации: фиксируем авто-высоту, чтобы текст мог меняться
|
|
706
|
+
$errorWrapper.style.height = 'auto';
|
|
707
|
+
$errorWrapper.style.paddingTop = `${this._anim.paddingTopOpened}px`;
|
|
708
|
+
$errorWrapper.style.opacity = '1';
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
else {
|
|
712
|
+
// Фолбэк без анимации
|
|
713
|
+
$errorWrapper.style.height = 'auto';
|
|
714
|
+
$errorWrapper.style.paddingTop = `${this._anim.paddingTopOpened}px`;
|
|
715
|
+
$errorWrapper.style.opacity = '1';
|
|
716
|
+
}
|
|
717
|
+
this._ringIcon($errorWrapper);
|
|
652
718
|
}
|
|
719
|
+
// Скрыть при первом вводе после показа
|
|
720
|
+
this.$el.addEventListener('input', () => this.hideErrorForm(), { passive: true, once: true });
|
|
653
721
|
}
|
|
654
722
|
/** Скрывает ошибку под полями ввода - ошибку, относящуюся ко всей форме. */
|
|
655
723
|
hideErrorForm() {
|
|
656
724
|
const inputWrappersList = this.$el.querySelectorAll(this.config.inputWrapperSelector);
|
|
657
725
|
const $lastInputWrapper = inputWrappersList[inputWrappersList.length - 1];
|
|
658
|
-
const
|
|
659
|
-
if (
|
|
726
|
+
const $errorWrapper = $lastInputWrapper.nextElementSibling;
|
|
727
|
+
if (!$errorWrapper || !$errorWrapper.classList.contains('error-block-under-input__wrapper'))
|
|
728
|
+
return;
|
|
729
|
+
// Текущая высота (если была auto) — измерим и зафиксируем
|
|
730
|
+
const wasAuto = $errorWrapper.style.height === '' || $errorWrapper.style.height === 'auto';
|
|
731
|
+
if (wasAuto) {
|
|
732
|
+
$errorWrapper.style.height = `${$errorWrapper.clientHeight}px`;
|
|
733
|
+
}
|
|
734
|
+
$errorWrapper.style.paddingTop = $errorWrapper.style.paddingTop || `${this._anim.paddingTopOpened}px`;
|
|
735
|
+
$errorWrapper.style.opacity = $errorWrapper.style.opacity || '1';
|
|
736
|
+
// Анимация схлопывания
|
|
737
|
+
this._cancelAnimations($errorWrapper);
|
|
738
|
+
if (this._canAnimate($errorWrapper)) {
|
|
739
|
+
const anim = $errorWrapper.animate([
|
|
740
|
+
{
|
|
741
|
+
height: `${parseFloat($errorWrapper.style.height) || $errorWrapper.clientHeight}px`,
|
|
742
|
+
paddingTop: `${parseFloat($errorWrapper.style.paddingTop) || this._anim.paddingTopOpened}px`,
|
|
743
|
+
opacity: parseFloat($errorWrapper.style.opacity || '1'),
|
|
744
|
+
},
|
|
745
|
+
{ height: '0px', paddingTop: '0px', opacity: 0 },
|
|
746
|
+
], { duration: this._anim.duration, easing: this._anim.easing, fill: 'forwards' });
|
|
747
|
+
anim.addEventListener('finish', () => {
|
|
748
|
+
// После закрытия можно удалить узел или оставить схлопнутым
|
|
749
|
+
$errorWrapper.remove();
|
|
750
|
+
// Если хотите оставлять в DOM:
|
|
751
|
+
// $errorWrapper.style.height = '0px';
|
|
752
|
+
// $errorWrapper.style.paddingTop = '0px';
|
|
753
|
+
// $errorWrapper.style.opacity = '0';
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
else {
|
|
757
|
+
// Фолбэк без анимации
|
|
758
|
+
$errorWrapper.remove();
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
/** Короткая анимация иконки без CSS */
|
|
762
|
+
_ringIcon($wrapper) {
|
|
763
|
+
const $icon = $wrapper.querySelector('.error-block-under-input__icon--animated');
|
|
764
|
+
if (!$icon)
|
|
765
|
+
return;
|
|
766
|
+
this._cancelAnimations($icon);
|
|
767
|
+
if (!this._canAnimate($icon))
|
|
768
|
+
return;
|
|
769
|
+
// Небольшое «качание» и вспышка прозрачности
|
|
770
|
+
$icon.animate([
|
|
771
|
+
{ transform: 'rotate(0deg) scale(1)', opacity: 0 },
|
|
772
|
+
{ transform: 'rotate(-8deg) scale(1.05)', opacity: 1, offset: 0.15 },
|
|
773
|
+
{ transform: 'rotate(8deg) scale(1.05)', opacity: 1, offset: 0.3 },
|
|
774
|
+
{ transform: 'rotate(-6deg) scale(1.03)', opacity: 1, offset: 0.45 },
|
|
775
|
+
{ transform: 'rotate(6deg) scale(1.03)', opacity: 1, offset: 0.6 },
|
|
776
|
+
{ transform: 'rotate(0deg) scale(1)', opacity: 0 },
|
|
777
|
+
], { duration: this._anim.iconDuration, easing: 'ease' });
|
|
660
778
|
}
|
|
661
779
|
/**
|
|
662
780
|
* Проверяет входные данные на их корректность.
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -145,6 +145,11 @@ export default class Form {
|
|
|
145
145
|
private enableSubmit;
|
|
146
146
|
/** Очищает поля ввода формы. */
|
|
147
147
|
clearInputs(): void;
|
|
148
|
+
/** Общие настройки анимаций (можно подправить под вкус) */
|
|
149
|
+
private readonly _anim;
|
|
150
|
+
private _prefersReducedMotion;
|
|
151
|
+
private _canAnimate;
|
|
152
|
+
private _cancelAnimations;
|
|
148
153
|
/**
|
|
149
154
|
* Показывает ошибку под полями ввода - ошибку, относящуюся ко всей форме.
|
|
150
155
|
*
|
|
@@ -153,6 +158,8 @@ export default class Form {
|
|
|
153
158
|
private showErrorForm;
|
|
154
159
|
/** Скрывает ошибку под полями ввода - ошибку, относящуюся ко всей форме. */
|
|
155
160
|
private hideErrorForm;
|
|
161
|
+
/** Короткая анимация иконки без CSS */
|
|
162
|
+
private _ringIcon;
|
|
156
163
|
/**
|
|
157
164
|
* Проверяет входные данные на их корректность.
|
|
158
165
|
*
|