UNPKG

34.1 kBJavaScriptView Raw
1import { Component, Vue } from 'vue-property-decorator';
2import dayjs from 'dayjs-ext';
3
4/*! *****************************************************************************
5Copyright (c) Microsoft Corporation. All rights reserved.
6Licensed under the Apache License, Version 2.0 (the "License"); you may not use
7this file except in compliance with the License. You may obtain a copy of the
8License at http://www.apache.org/licenses/LICENSE-2.0
9
10THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
12WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
13MERCHANTABLITY OR NON-INFRINGEMENT.
14
15See the Apache Version 2.0 License for specific language governing permissions
16and limitations under the License.
17***************************************************************************** */
18/* global Reflect, Promise */
19
20var extendStatics = function(d, b) {
21 extendStatics = Object.setPrototypeOf ||
22 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
23 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
24 return extendStatics(d, b);
25};
26
27function __extends(d, b) {
28 extendStatics(d, b);
29 function __() { this.constructor = d; }
30 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
31}
32
33var __assign = function() {
34 __assign = Object.assign || function __assign(t) {
35 for (var s, i = 1, n = arguments.length; i < n; i++) {
36 s = arguments[i];
37 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
38 }
39 return t;
40 };
41 return __assign.apply(this, arguments);
42};
43
44function __decorate(decorators, target, key, desc) {
45 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
46 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
47 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
48 return c > 3 && r && Object.defineProperty(target, key, r), r;
49}
50
51var FieldBag = /** @class */ (function () {
52 function FieldBag(items) {
53 this._items = items || [];
54 }
55 Object.defineProperty(FieldBag.prototype, "items", {
56 set: function (items) {
57 this.push(items);
58 },
59 enumerable: true,
60 configurable: true
61 });
62 /**
63 * Returns the corresping Field instance, or undefined if not found.
64 *
65 * @param {String} field - The name of the field.
66 * @param {String} scope? - Optional scope of the field.
67 * @returns {Field | undefined} - The Field instance, or undefined if not found.
68 */
69 FieldBag.prototype.get = function (field, scope) {
70 return this._items.find(function (item) { return scope
71 ? item.name === field && item.scope === scope
72 : item.name === field; });
73 };
74 /**
75 * Returns all fields registered in the FieldBag
76 *
77 * @param {String} scope? - If present, returns all the fields from that scope
78 * @returns {Array<Field>} - Array of field items
79 */
80 FieldBag.prototype.all = function (scope) {
81 return scope
82 ? this._items.filter(function (f) { return f.scope === scope; })
83 : this._items;
84 };
85 /**
86 * Check to see if a Field is preseint in the FieldBag, or if a Field
87 * exists in a given scope.
88 *
89 * @param {String} field - The name of the field
90 * @param {String} scope? - Optional scope of the field
91 * @returns {Boolean}
92 */
93 FieldBag.prototype.has = function (field, scope) {
94 return !!this._items.find(function (item) { return scope
95 ? item.name === field && item.scope === scope
96 : item.name === field; });
97 };
98 /**
99 * Add a new Field or an array of Field instances to the existing _items
100 * arrays.
101 *
102 * @param {Field | Array<Field>} scope? - If present, returns all the fields
103 * from that scope.
104 * @returns {void}
105 */
106 FieldBag.prototype.push = function (item) {
107 // Check if item is already present in the FieldBag instance
108 this._items.push.apply(this._items, Array.isArray(item) ? item : [item]);
109 };
110 /**
111 * Removes an existing field from the FieldBag instance.
112 *
113 * @param {String} field - The name of the field
114 * @param {String} scope? - Optional scope of the field
115 * @returns {void}
116 */
117 FieldBag.prototype.remove = function (field, scope) {
118 this._items = this._items.filter(function (item) { return scope && item.scope === scope
119 ? item.name !== field
120 : item.name !== field; });
121 };
122 return FieldBag;
123}());
124
125var RULES = {};
126var RuleContainer = /** @class */ (function () {
127 function RuleContainer() {
128 }
129 Object.defineProperty(RuleContainer, "rules", {
130 get: function () {
131 return RULES;
132 },
133 enumerable: true,
134 configurable: true
135 });
136 /**
137 * Get a specific rule from the container.
138 *
139 * @param {String} ruleName - The name of the rule.
140 * @returns {ValidationRule} - the respective ValidationRule object.
141 */
142 RuleContainer.getRule = function (ruleName) {
143 return RULES[ruleName];
144 };
145 /**
146 * Adds a new rule to the container.
147 *
148 * @param ruleName - The name of the rule to be added.
149 * @param rule - The ValidationRule object.
150 * @returns {Void}
151 */
152 RuleContainer.add = function (ruleName, rule) {
153 RULES[ruleName] = rule;
154 };
155 /**
156 * Removes a rule from the container.
157 *
158 * @param ruleName - The name of the rule to be removed.
159 * @returns {Void}
160 */
161 RuleContainer.remove = function (ruleName) {
162 delete RULES[ruleName];
163 };
164 /**
165 * Checks if a rule exists in the container
166 *
167 * @param ruleName - The name of the rule.
168 * @returns {Boolean}
169 */
170 RuleContainer.has = function (ruleName) {
171 return !!RULES[ruleName];
172 };
173 return RuleContainer;
174}());
175
176/**
177 * Check value's constructor name.
178 * @param {*} value
179 * @param {String} constructor
180 * @returns {Boolean}
181 *
182 * @author Vitor Luiz Cavalcanti (https://github.com/VitorLuizC)
183 */
184var is = function (value, constructor) {
185 return Object.prototype.toString.call(value) === "[object " + constructor + "]";
186};
187
188/**
189 * Test to see if an entity of the form `validations` object is an scope
190 * and not a FormValidation object.
191 *
192 * @param {Any} formEntity - The entity to be tested.
193 *
194 * @author Erik Isidore
195 * @version 0.1
196 */
197var isFormScope = function (formEntity) {
198 if (!is(formEntity, 'Object'))
199 return false;
200 return Object.keys(formEntity)
201 .every(function (name) { return !RuleContainer.has(name); });
202};
203
204var Field = /** @class */ (function () {
205 function Field(options) {
206 this._flags = {
207 pristine: false,
208 dirty: false,
209 changed: false,
210 touched: false,
211 valid: false,
212 errors: []
213 };
214 this.el = options.el;
215 this._vm = options.vm;
216 this.name = options.name;
217 this.value = options.value;
218 this.scope = options.scope;
219 this.rules = this.mapRules(options.rules);
220 this.initialValue = options.value;
221 this.init(options);
222 }
223 Object.defineProperty(Field.prototype, "validate", {
224 get: function () {
225 if (!this._vm || !this._vm.$validator)
226 return function () { return []; };
227 var validate = this._vm.$validator.validate;
228 return validate.bind(this._vm.$validator, this.name, this.scope);
229 },
230 enumerable: true,
231 configurable: true
232 });
233 Object.defineProperty(Field.prototype, "watch", {
234 get: function () {
235 if (!this._vm || !this._vm.$validator)
236 return;
237 return this._vm.$watch.bind(this._vm);
238 },
239 enumerable: true,
240 configurable: true
241 });
242 Object.defineProperty(Field.prototype, "options", {
243 get: function () {
244 if (!this._vm || !this._vm.$validator)
245 return;
246 return this._vm.$validator.options;
247 },
248 enumerable: true,
249 configurable: true
250 });
251 Object.defineProperty(Field.prototype, "flags", {
252 get: function () { return this._flags; },
253 enumerable: true,
254 configurable: true
255 });
256 Object.defineProperty(Field.prototype, "errors", {
257 get: function () { return this._flags.errors; },
258 enumerable: true,
259 configurable: true
260 });
261 Object.defineProperty(Field.prototype, "error", {
262 get: function () { return this._flags.errors[0] || ''; },
263 enumerable: true,
264 configurable: true
265 });
266 /**
267 * Sets a new value to one of the instance's FieldFlags.
268 *
269 * @param {Keyof FieldFlags} flag - The flag name
270 * @param {Boolean | Array<String>} value - the new value to assigned to the flag
271 * @returns {void}
272 * @author Erik Isidore
273 */
274 Field.prototype.setFlag = function (flag, value) {
275 if (!Object.keys(this._flags).includes(flag))
276 return;
277 this._flags[flag] = value;
278 };
279 /**
280 * Initializes the Field instance.
281 *
282 * @param {FieldItem} options
283 * @returns {void}
284 * @author Erik Isidore
285 */
286 Field.prototype.init = function (options) {
287 if (process.env.NODE_ENV !== 'production' && !this.name)
288 console.warn('CeeValidate: A field declaration is missing a "name" attribute');
289 this.initFlags();
290 this.addValueListeners();
291 };
292 /**
293 * Initializes or resets the Field flags to their default values.
294 *
295 * @returns {void}
296 * @author Erik Isidore
297 */
298 Field.prototype.initFlags = function () {
299 var _this = this;
300 var flagNames = Object.keys(this._flags);
301 var defaultFlags = {
302 pristine: !this.value,
303 dirty: !!this.value,
304 touched: false,
305 changed: false,
306 valid: false,
307 errors: []
308 };
309 flagNames.forEach(function (flag) {
310 _this._flags[flag] = defaultFlags[flag];
311 });
312 };
313 /**
314 * Adds event listener for the blur event on the input, so that we can
315 * tell when the input has been `touched` by the user, and attaches a
316 * watcher to the input value, validating it's value whenever it changes.
317 *
318 * @returns {void}
319 * @author Erik Isidore
320 */
321 Field.prototype.addValueListeners = function () {
322 var _this = this;
323 if (!this.watch || !this.el)
324 return;
325 var onBlur = function () {
326 if (!_this._flags.touched)
327 _this._flags.touched = true;
328 if (!_this.options.noListeners)
329 _this.validate();
330 };
331 var onInput = function (value) {
332 _this.value = value;
333 _this._flags.changed = _this.value !== _this.initialValue;
334 if (!_this.options.noListeners)
335 _this.validate();
336 if (!_this._flags.dirty) {
337 _this._flags.dirty = true;
338 _this._flags.pristine = false;
339 }
340 };
341 this.el.addEventListener('focusout', onBlur.bind(this));
342 this.watch(this.scope ? this.scope + "." + this.name : this.name, onInput.bind(this));
343 };
344 /**
345 * Receives a FieldValidation entity, which can be
346 * A string: 'required|dateFormat:DD/MM/YYYY'
347 * An array of strings: ['required', 'dateFormat:DD/MM/YYYY']
348 * Or an object: { required: true, dateFormat: 'DD/MM/YYYY' }
349 *
350 * And turns this entity into a array of NormalizedRules, this
351 * array will contain an NormalizedRule object for every rule
352 * found in FieldValidation. A NormalizedRule is simply an
353 * object with the format: { ruleName: <name>, args: [<...>] }
354 *
355 * @param {FieldValidation} rules - The validation rules defined for the field.
356 * @returns {Array<NormalizedRule>} - A array containing a NormalizedRule for
357 * every validation rule defined for the field.
358 *
359 * @author Erik Isidore
360 */
361 Field.prototype.mapRules = function (rules) {
362 var stringToRules = function (ruleDef) { return ({
363 ruleName: ruleDef.split(':')[0],
364 args: ruleDef.split(':')[1] && ruleDef.split(':')[1].split(',')
365 }); };
366 var objToRules = function (rulesObj) {
367 return Object.keys(rulesObj).map(function (ruleName) { return ({
368 ruleName: ruleName,
369 args: !Array.isArray(rulesObj[ruleName])
370 ? [rulesObj[ruleName]]
371 : rulesObj[ruleName]
372 }); });
373 };
374 return typeof rules === 'string' && rules.length
375 ? rules.split('|').map(stringToRules)
376 : Array.isArray(rules) ? rules.map(stringToRules)
377 : rules && is(rules, 'Object') ? objToRules(rules)
378 : [];
379 };
380 /**
381 * Resets the field flags and it's value.
382 *
383 * @returns {void}
384 * @author Erik Isidore
385 */
386 Field.prototype.reset = function () {
387 this.value = this.initialValue;
388 this.initFlags();
389 };
390 /**
391 * Dynamically updates the field's rules and remaps them.
392 *
393 * @param {FieldValidation} rule - The new rules to be applied
394 * @returns {void}
395 *
396 * @author Erik Isidore
397 */
398 Field.prototype.setRule = function (rule) {
399 this.rules = this.mapRules(rule);
400 };
401 return Field;
402}());
403
404/**
405 * Checks if all characters in a given value are alphanumeric (letters
406 * and numbers), ignores whitespace.
407 *
408 * @param {String} value - the input value to be tested.
409 * @returns {boolean}
410 *
411 * @author Viniazvd, Erik Isidore
412 * @version 0.1
413 */
414var rule = {
415 validate: function (value) {
416 if (!value)
417 return true;
418 return !!value.trim() && /^([0-9a-zA-Z\s]*)?$/.test(value.trim());
419 },
420 message: 'Deve conter apenas letras e números'
421};
422RuleContainer.add('alphanumeric', rule);
423
424/**
425 * Executes a callback or an array of callbacks with `value` as an argument
426 * and returns true if every callback passes
427 *
428 * @param {Any} value - the input value to be validated.
429 * @param {Function | Array<Function>} - The callback or array of callbacks
430 * to be called on the value.
431 * @returns {boolean} - Returns true if every callback passes, false otherwise.
432 *
433 * @author Viniazvd, Erik Isidore
434 * @version 0.1
435 */
436var rule$1 = {
437 validate: function (value) {
438 var callbacks = [];
439 for (var _i = 1; _i < arguments.length; _i++) {
440 callbacks[_i - 1] = arguments[_i];
441 }
442 return callbacks.every(function (f) { return f(value); });
443 },
444 message: 'Campo inválido'
445};
446RuleContainer.add('custom', rule$1);
447
448var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
449
450function createCommonjsModule(fn, module) {
451 return module = { exports: {} }, fn(module, module.exports), module.exports;
452}
453
454var customParseFormat = createCommonjsModule(function (module, exports) {
455!function(n,t){module.exports=t();}(commonjsGlobal,function(){var i=/(\[[^[]*\])|([-:/.()\s]+)|(A|a|YYYY|YY?|MM?|DD?|hh?|HH?|mm?|ss?|S{1,3}|z|ZZ?)/g,n=/\d\d/,t=/\d\d?/,r=/[+-]\d\d:?\d\d/,a={},f={},y={},m=[31,0,31,30,31,30,31,31,30,31,30,31];function w(n){var c=n.match(i);if(!c)throw new Error('Invalid format: "'+n+'".');for(var d=c.length,t=0;t<d;t+=1){var r=c[t],e=a[r],o=f[r];c[t]=o?{regex:e,parser:o}:r.replace(/^\[|\]$/g,"");}return function(n){for(var t={},r=0,e=0;r<d;r+=1){var o=c[r];if("string"==typeof o){if(n.indexOf(o,e)!==e){var i=n.substr(e,o.length);throw new Error('Expected "'+o+'" at character '+e+', found "'+i+'".')}e+=o.length;}else{var a=o.regex,f=o.parser,s=n.substr(e),u=a.exec(s);if(!u||0!==u.index)throw new Error('Matching "'+a+'" at character '+e+' failed with "'+s+'".');var h=u[0];f.call(t,h),e+=h.length;}}return function(n){var t,r,e=n.day,o=n.month;if(t=2===o?(r=n.year)%4==0&&r%100!=0||r%400==0?29:28:m[o-1],!(1<=e&&e<=t))throw new Error('Invalid day: "'+e+'".')}(t),function(n){var t=n.afternoon;if(void 0!==t){var r=n.hours;t?r<12&&(n.hours+=12):12===r&&(n.hours=0),delete n.afternoon;}}(t),t}}function e(n,t){a[n]=t;}function o(n,r,e){var t;"string"==typeof n&&(n=[n]),t="string"==typeof r?e?function(n){var t=+n;if(!e(t))throw new Error("Invalid "+r+': "'+n+'".');this[r]=t;}:function(n){this[r]=+n;}:r;for(var o=0,i=n.length;o<i;o+=1)f[n[o]]=t;}e("A",/[AP]M/),o(["A"],function(n){this.afternoon="PM"===n;}),e("a",/[ap]m/),o(["a"],function(n){this.afternoon="pm"===n;}),e("S",/\d/),e("SS",n),e("SSS",/\d{3}/);for(var s=function(n,t){o(n,function(n){this.milliseconds=+n*t;});},u="S",h=100;1<=h;u+="S",h/=10)s(u,h);e("s",t),e("ss",n),o(["s","ss"],"seconds",function(n){return n<=59}),e("m",t),e("mm",n),o(["m","mm"],"minutes",function(n){return n<=59}),e("H",t),e("h",t),e("HH",n),e("hh",n),o(["H","HH"],"hours",function(n){return n<=23}),o(["h","hh"],"hours",function(n){return 1<=n&&n<=12}),e("D",t),e("DD",n),o(["D","DD"],"day"),e("M",t),e("MM",n),o(["M","MM"],"month",function(n){return 1<=n&&n<=12}),e("Y",/[+-]?\d+/),e("YY",n),e("YYYY",/\d{4}/),o(["Y","YYYY"],"year"),o("YY",function(n){n=+n,this.year=n+(68<n?1900:2e3);}),e("z",/[A-Z]{3,4}/),o("z",function(n){(this.zone||(this.zone={})).abbreviation=n;}),e("Z",r),e("ZZ",r),o(["Z","ZZ"],function(n){(this.zone||(this.zone={})).offset=function(n){var t=n.match(/([+-]|\d\d)/g),r=60*t[1]+ +t[2],e=0===r?0:"+"===t[0]?-r:r;if(!(e%15==0&&Math.abs(e)<=765))throw new Error('Invalid time zone offset: "'+n+'".');return e}(n);});return function(n,t){var r=t.prototype,p=r.parse;r.parse=function(n){var t,r,e,o=n.date,i=n.format;if(i){try{var a,f=(t=o,(e=y[r=i])||(e=w(r),y[r]=e),e(t)),s=f.year,u=f.month,h=f.day,c=f.hours,d=f.minutes,m=f.seconds,v=f.milliseconds,l=f.zone;if(l){var Y=Date.UTC(s,u-1,h,c||0,d||0,m||0,v||0)+60*l.offset*1e3;a=new Date(Y);}else a=new Date(s,u-1,h,c||0,d||0,m||0,v||0);this.$d=a;}catch(n){this.$d=new Date(Number.NaN);}this.init(n);}else p.call(this,n);};}});
456
457});
458
459dayjs.extend(customParseFormat);
460/**
461 * Validate if the input value produces a valid date and optionally if
462 * it follows a given date format.
463 *
464 * @param {String | Number} value - The value of the input to be validated,
465 * if `value` is a String, the validator may also receive a format param to
466 * check if the string has the correct format.
467 * @param {String} format? - Optional parameter to validate whether the the
468 * given input value has the correct format. If given, the value must be a
469 * string, otherwise this parameter is completely ignored.
470 * @returns {boolean} True if the given value is valid or empty, false otherwise.
471 * If you want to check for empty value, use the 'required' rule.
472 *
473 * @author Erik Isidore
474 * @version 0.1
475 */
476var rule$2 = {
477 validate: function (value, format) {
478 if (format === void 0) { format = 'DD/MM/YYYY'; }
479 if (!value)
480 return true;
481 var options = is(value, 'String') ? { format: format } : {};
482 var date = dayjs(value, options);
483 return date.isValid();
484 },
485 message: 'Data inválida.'
486};
487RuleContainer.add('dateFormat', rule$2);
488
489/**
490 * Checks if all characters in a given value are numeric, ignores whitespace.
491 *
492 * @param {String} value - The input value to be validated.
493 * @returns {Boolean}
494 *
495 * @author Viniazvd, Erik Isidore
496 * @version 0.1
497 */
498var rule$3 = {
499 validate: function (value) {
500 if (!value)
501 return true;
502 return !!value.trim() && /^(\d+(\.\d+)?$)/.test(value.trim());
503 },
504 message: 'Deve conter apenas números.'
505};
506RuleContainer.add('numeric', rule$3);
507
508/**
509 * Receives a value and a regular expression and returns the result of
510 * executing the regex on the value.
511 *
512 * @param {String} value - Input value.
513 * @param {Regex} regex - Regular expression object.
514 * @returns {boolean}
515 *
516 * @author Erik Isidore
517 * @version 0.1
518 */
519var rule$4 = {
520 validate: function (value, regex) {
521 if (!value)
522 return true;
523 if (!is(value, 'String') || !is(regex, 'RegExp'))
524 return false;
525 return !!value && regex.test(value);
526 },
527 message: 'Formato inválido.'
528};
529RuleContainer.add('regex', rule$4);
530
531/**
532 * Validate if the given value is not empty
533 *
534 * @param {Any} value - The value of the input to be validated.
535 * @returns {boolean} - True if the given value is not empty, false otherwise.
536 *
537 * @author Viniazvd, Erik Isidore
538 * @version 0.1
539 */
540var rule$5 = {
541 validate: function (value) {
542 if (Array.isArray(value))
543 return !!value.length;
544 if (typeof value === 'object')
545 return !!Object.keys(value).length;
546 if (typeof value === 'string')
547 return !!value.trim().length;
548 if (typeof value === 'number')
549 return !!value;
550 if (typeof value === 'boolean')
551 return true;
552 return !!value;
553 },
554 message: 'Campo obrigatório.'
555};
556RuleContainer.add('required', rule$5);
557
558/**
559 * Checks to see if a given value is bigger than max length, if value
560 * is string/array, checks the string length, if it is a number,
561 * checks the value itself.
562 *
563 * @param {Array<any> | String | Number} value - Then given value
564 * @param {Number | String} maxLength - the max length.
565 * @returns {Boolean} - False if value exceeds max length.
566 *
567 * @author Erik Isidore
568 * @version 0.1
569 */
570var rule$6 = {
571 validate: function (value, maxLength) {
572 if (!value)
573 return true;
574 if (Array.isArray(value) || typeof value === 'string')
575 return (value || []).length <= maxLength;
576 return maxLength >= value;
577 },
578 message: 'Valor acima do limite.'
579};
580RuleContainer.add('maxLength', rule$6);
581
582/**
583 * Checks to see if a given value is bigger than min length, if value
584 * is string/array, checks the string length, if it is a number,
585 * checks the value itself.
586 *
587 * @param {Array<any> | String | Number} value - Then given value
588 * @param {Number | String} minLength - the min length.
589 * @returns {Boolean} - False if value is smaller than min length.
590 *
591 * @author Erik Isidore
592 * @version 0.1
593 */
594var rule$7 = {
595 validate: function (value, minLength) {
596 if (!value)
597 return true;
598 if (Array.isArray(value) || typeof value === 'string')
599 return (value || []).length >= minLength;
600 return value >= minLength;
601 },
602 message: 'Valor abaixo do limite.'
603};
604RuleContainer.add('minLength', rule$7);
605
606var rule$8 = {
607 validate: function (value) {
608 if (!value)
609 return true;
610 var FTAP = '3298765432';
611 var numPis = (value + '').replace(/[^\d]+/g, '');
612 var total = FTAP
613 .split('')
614 .reduce(function (total, digit, index) { return total + (+numPis[index] * +digit); }, 0);
615 var rest = (total % 11);
616 if (rest !== 0)
617 rest = 11 - rest;
618 if (rest === 10 || rest === 11)
619 rest = (rest + '').slice(1, 2);
620 if (+rest !== +(numPis.slice(10, 11)))
621 return false;
622 return true;
623 },
624 message: 'Número de PIS inválido'
625};
626RuleContainer.add('pis', rule$8);
627
628var ScopedValidator = /** @class */ (function () {
629 function ScopedValidator(vm) {
630 var _this = this;
631 this.scopes = [];
632 this._options = {};
633 this.validations = {};
634 this._vm = vm;
635 this.fields = new FieldBag();
636 vm.$nextTick(function () {
637 if (_this._vm.$options.validatorOptions)
638 _this.options = _this._vm.$options.validatorOptions;
639 if (_this._vm.$options.validations)
640 _this.init(_this._vm.$options.validations);
641 });
642 }
643 Object.defineProperty(ScopedValidator.prototype, "options", {
644 get: function () {
645 return this._options;
646 },
647 set: function (options) {
648 this._options = is(options, 'Function')
649 ? options(this._vm)
650 : __assign({}, options);
651 },
652 enumerable: true,
653 configurable: true
654 });
655 /**
656 * This two following functions are responsible for bootstraping
657 * the ScopedValidation class with the given validation options.
658 * The public init function exists to ensure that whenever we're
659 * bootstraping the ScopedValidator class, the DOM will be accessible
660 * through the _vm.
661 *
662 * @param template - The form validations template object.
663 * @returns {void}
664 *
665 * @author Erik Isidore
666 */
667 ScopedValidator.prototype.init = function (template) {
668 this._vm.$nextTick(this.__init.bind(this, template));
669 };
670 ScopedValidator.prototype.__init = function (template) {
671 this.scopes = Object.keys(template).filter(function (key) { return isFormScope(template[key]); });
672 this.fields.items = this.initFields(template);
673 this.validations = this.mapValidations();
674 };
675 /**
676 * Receives a FormTemplate object and maps the fields validation rules
677 * in it to populate the `fields` instance property with Field instances.
678 *
679 * @param {FormTemplate} template - The form or forms validation object.
680 * @returns {void}
681 *
682 * @author Erik Isidore
683 */
684 ScopedValidator.prototype.initFields = function (template) {
685 var _this = this;
686 var _a;
687 var mapField = function (name, rules, scope) {
688 var fieldOptions = {
689 name: name,
690 rules: rules,
691 scope: scope,
692 vm: _this._vm,
693 el: _this.getFieldEl(name, scope),
694 value: scope ? _this._vm[scope][name] : _this._vm[name],
695 };
696 return new Field(fieldOptions);
697 };
698 // This will map each form scope name to an array of Field instances,
699 // producing an Array of Field arrays, crazy rite? Each field will
700 // have its respective scope assigned to it.
701 var scopes = this.scopes.map(function (scope) {
702 var formScope = template[scope];
703 return Object.keys(formScope)
704 .map(function (fieldName) { return mapField(fieldName, formScope[fieldName], scope); });
705 });
706 var fields = Object.keys(template)
707 .filter(function (key) { return !isFormScope(template[key]); })
708 .map(function (key) { return mapField(key, template[key]); });
709 return (_a = Array.prototype).concat.apply(_a, [fields].concat(scopes));
710 };
711 /**
712 * Generetes the validation flags object based on the form scopes.
713 *
714 * @returns {FormValidationFlags}
715 *
716 * @author Erik Isidore
717 */
718 ScopedValidator.prototype.mapValidations = function () {
719 var _this = this;
720 var mapFlags = function (scope) { return _this.fields.all(scope)
721 .reduce(function (acc, field) {
722 var _a;
723 return (__assign({}, acc, (_a = {}, _a[field.name] = field.flags, _a)));
724 }, {}); };
725 var mapFormScopes = function (acc, scope) {
726 var _a;
727 return (__assign({}, acc, (_a = {}, _a[scope] = mapFlags(scope), _a)));
728 };
729 return this.scopes.length > 1
730 ? this.scopes.reduce(mapFormScopes, {})
731 : mapFlags();
732 };
733 /**
734 * Receives a fieldName and optionally it's scope and returns the HTML
735 * Element corresponding to that field in the DOM.
736 *
737 * @param {String} fieldName - The name of the field
738 * @param {String} scope? - Optional form scope.
739 * @returns {Element} - The first matching element found in the component DOM.
740 *
741 * @author Erik Isidore
742 */
743 ScopedValidator.prototype.getFieldEl = function (fieldName, scope) {
744 var fieldQuery = scope
745 ? "form[name=\"" + scope + "\"] [name=\"" + fieldName + "\"]"
746 : "[name=\"" + fieldName + "\"]";
747 var fields = this._vm.$el.querySelectorAll(fieldQuery);
748 if (process.env.NODE_ENV !== 'production' && !fields.length)
749 console.warn("CeeValidate: Field \"" + fieldName + "\" could not be found in the DOM");
750 return fields[0];
751 };
752 /**
753 * @param {String} fieldName -
754 * @param {String} scope? -
755 * @returns {void}
756 *
757 * @author Erik Isidore
758 */
759 ScopedValidator.prototype.validate = function (fieldName, scope) {
760 var field = this.fields.get(fieldName, scope);
761 // Field doesn't exist, return false (invalid field)
762 if (!field)
763 return false;
764 var mapErrors = function (_a) {
765 var ruleName = _a.ruleName, args = _a.args;
766 var rule = RuleContainer.getRule(ruleName);
767 var hasError = !rule.validate.apply(null, [field.value].concat((args || [])));
768 var errorMessage = rule.message;
769 return hasError ? errorMessage : '';
770 };
771 var fieldErrors = field.rules
772 .map(mapErrors)
773 .filter(function (message) { return !!message; });
774 field.setFlag('errors', fieldErrors);
775 field.setFlag('valid', !fieldErrors.length);
776 return !fieldErrors.length;
777 };
778 /**
779 * Executes the validate() method on all Field instances.
780 *
781 * @param {String} scope? -
782 * @returns {void}
783 *
784 * @author Erik Isidore
785 */
786 ScopedValidator.prototype.validateAll = function (scope) {
787 var fieldFlags = this.fields.all(scope)
788 .map(function (field) { return field.validate(); });
789 var isValid = fieldFlags.every(function (isValid) { return !!isValid; });
790 this.options = __assign({}, (this.options || {}), { noListeners: false });
791 return isValid;
792 };
793 /**
794 * Resets all of the fields validation flags.
795 *
796 * @param {String} scope? -
797 * @returns {void}
798 *
799 * @author Erik Isidore
800 */
801 ScopedValidator.prototype.reset = function (scope) {
802 this.fields.all(scope).forEach(function (field) { return field.reset(); });
803 };
804 /**
805 * Attaches a new field to the validator.
806 *
807 * @param {}
808 * @returns {void}
809 *
810 * @author Erik Isidore
811 */
812 ScopedValidator.prototype.attach = function (field) {
813 var newField = new Field({
814 vm: this._vm,
815 name: field.name,
816 rules: field.rules,
817 scope: field.scope,
818 el: this.getFieldEl(field.name, field.scope),
819 value: field.scope ? this._vm[field.scope][field.name] : this._vm[field.name]
820 });
821 this.fields.push(newField);
822 this.validations = this.mapValidations();
823 };
824 /**
825 * Detaches an existing field from the validator.
826 *
827 * @param {String} field - The name of the field
828 * @param {String} scope? - Optional scope of the field
829 * @returns {void}
830 *
831 * @author Erik Isidore
832 */
833 ScopedValidator.prototype.detach = function (field, scope) {
834 this.fields.remove(field, scope);
835 this.validations = this.mapValidations();
836 };
837 /**
838 * Sets the rule of a field and validate it if it has changed.
839 *
840 * @param {Object<name: string, scope: string>} field - Object with name
841 * and scope of the field.
842 * @param {FieldValidation} rules - The rules to be set in the field
843 * @returns {void}
844 */
845 ScopedValidator.prototype.setFieldRule = function (field, rules) {
846 var fieldInstance = this.fields.get(field.name, field.scope);
847 if (!fieldInstance)
848 return;
849 fieldInstance.setRule(rules);
850 if (fieldInstance.flags.changed)
851 fieldInstance.validate();
852 };
853 return ScopedValidator;
854}());
855
856// eslint-disable
857var FormValidator = /** @class */ (function (_super) {
858 __extends(FormValidator, _super);
859 function FormValidator() {
860 return _super !== null && _super.apply(this, arguments) || this;
861 }
862 // In the future we'll use this function to pass mixin options
863 // and make some checkings before instantiating the ScopedValidator
864 FormValidator.prototype.beforeCreate = function () {
865 var _this = this;
866 // Get Vue constructor
867 var Vue$$1 = this.$options._base;
868 this.$validator = new ScopedValidator(this);
869 // Setup computed properties on the component
870 if (!this.$options.computed)
871 this.$options.computed = {};
872 Vue$$1.util.defineReactive(this.$validator, 'validations', this.$validator.validations);
873 this.$options.computed['$validations'] = function () { return _this.$validator.validations; };
874 };
875 FormValidator = __decorate([
876 Component
877 ], FormValidator);
878 return FormValidator;
879}(Vue));
880
881export default FormValidator;
882//# sourceMappingURL=cee-validate.es5.js.map