2020-11-11 11:56:00 +03:00
import isPlainObject from 'is-plain-object' ;
import isUrl from 'is-url' ;
import Vue from 'vue' ;
2021-08-03 14:48:41 +03:00
import { Inject , Model , Prop , Watch , Component , Provide } from 'vue-property-decorator' ;
2020-11-11 11:56:00 +03:00
/ * *
* Shorthand for Object . prototype . hasOwnProperty . call ( space saving )
* /
function has ( ctx , prop ) {
return Object . prototype . hasOwnProperty . call ( ctx , prop ) ;
}
/ * *
* Create a new object by copying properties of base and mergeWith .
* Note : arrays don ' t overwrite - they push
*
* @ param { Object } a
* @ param { Object } b
* @ param { boolean } concatArrays
* /
function merge ( a , b , concatArrays = true ) {
const merged = { } ;
for ( const key in a ) {
if ( has ( b , key ) ) {
if ( isPlainObject ( b [ key ] ) && isPlainObject ( a [ key ] ) ) {
merged [ key ] = merge ( a [ key ] , b [ key ] , concatArrays ) ;
}
else if ( concatArrays && Array . isArray ( a [ key ] ) && Array . isArray ( b [ key ] ) ) {
merged [ key ] = a [ key ] . concat ( b [ key ] ) ;
}
else {
merged [ key ] = b [ key ] ;
}
}
else {
merged [ key ] = a [ key ] ;
}
}
for ( const prop in b ) {
if ( ! has ( merged , prop ) ) {
merged [ prop ] = b [ prop ] ;
}
}
return merged ;
}
2021-08-03 14:48:41 +03:00
const registry = new Map ( ) ;
var id = ( prefix ) => {
const current = registry . get ( prefix ) || 0 ;
const next = current + 1 ;
registry . set ( prefix , next ) ;
return ` ${ prefix } - ${ next } ` ;
} ;
2020-11-11 11:56:00 +03:00
2021-08-03 14:48:41 +03:00
var TYPE ;
( function ( TYPE ) {
TYPE [ "ARRAY" ] = "ARRAY" ;
TYPE [ "BIGINT" ] = "BIGINT" ;
TYPE [ "BOOLEAN" ] = "BOOLEAN" ;
TYPE [ "DATE" ] = "DATE" ;
TYPE [ "FUNCTION" ] = "FUNCTION" ;
TYPE [ "NUMBER" ] = "NUMBER" ;
TYPE [ "RECORD" ] = "RECORD" ;
TYPE [ "STRING" ] = "STRING" ;
TYPE [ "SYMBOL" ] = "SYMBOL" ;
TYPE [ "UNDEFINED" ] = "UNDEFINED" ;
TYPE [ "NULL" ] = "NULL" ;
} ) ( TYPE || ( TYPE = { } ) ) ;
2021-09-21 10:32:18 +03:00
const constructorOf = ( value ) => {
return Object . getPrototypeOf ( value ) . constructor ;
} ;
function isRecord ( value ) {
return constructorOf ( value ) === Object && Object . keys ( Object . getPrototypeOf ( value ) ) . length === 0 ;
}
function isRecordLike ( value ) {
return typeof value === 'object' && value !== null && ( isRecord ( value ) || Array . isArray ( value ) ) ;
}
2021-08-03 14:48:41 +03:00
function typeOf ( value ) {
switch ( typeof value ) {
case 'bigint' :
return TYPE . BIGINT ;
case 'boolean' :
return TYPE . BOOLEAN ;
case 'function' :
return TYPE . FUNCTION ;
2020-11-11 11:56:00 +03:00
case 'number' :
2021-08-03 14:48:41 +03:00
return TYPE . NUMBER ;
2020-11-11 11:56:00 +03:00
case 'string' :
2021-08-03 14:48:41 +03:00
return TYPE . STRING ;
case 'symbol' :
return TYPE . SYMBOL ;
case 'undefined' :
return TYPE . UNDEFINED ;
case 'object' :
if ( value === null ) {
return TYPE . NULL ;
}
if ( value instanceof Date ) {
return TYPE . DATE ;
}
if ( Array . isArray ( value ) ) {
return TYPE . ARRAY ;
}
2021-09-21 10:32:18 +03:00
if ( isRecord ( value ) ) {
2021-08-03 14:48:41 +03:00
return TYPE . RECORD ;
}
2021-09-21 10:32:18 +03:00
return 'InstanceOf<' + constructorOf ( value ) . name + '>' ;
2021-08-03 14:48:41 +03:00
}
throw new Error ( ) ;
}
function isScalar ( value ) {
switch ( typeof value ) {
case 'bigint' :
2020-11-11 11:56:00 +03:00
case 'boolean' :
2021-08-03 14:48:41 +03:00
case 'number' :
case 'string' :
case 'symbol' :
2020-11-11 11:56:00 +03:00
case 'undefined' :
return true ;
default :
2021-08-03 14:48:41 +03:00
return value === null ;
2020-11-11 11:56:00 +03:00
}
}
2021-08-03 14:48:41 +03:00
const cloneInstance = ( original ) => {
return Object . assign ( Object . create ( Object . getPrototypeOf ( original ) ) , original ) ;
} ;
2020-11-11 11:56:00 +03:00
/ * *
* A simple ( somewhat non - comprehensive ) clone function , valid for our use
* case of needing to unbind reactive watchers .
* /
function clone ( value ) {
2021-08-03 14:48:41 +03:00
if ( isScalar ( value ) ) {
2020-11-11 11:56:00 +03:00
return value ;
}
2021-08-03 14:48:41 +03:00
if ( value instanceof Date ) {
return new Date ( value ) ;
}
if ( ! isRecordLike ( value ) ) {
return cloneInstance ( value ) ;
}
if ( Array . isArray ( value ) ) {
return value . slice ( ) . map ( clone ) ;
}
const source = value ;
return Object . keys ( source ) . reduce ( ( copy , key ) => ( Object . assign ( Object . assign ( { } , copy ) , { [ key ] : clone ( source [ key ] ) } ) ) , { } ) ;
}
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Copyright ( c ) Microsoft Corporation .
Permission to use , copy , modify , and / or distribute this software for any
purpose with or without fee is hereby granted .
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS . IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL , DIRECT ,
INDIRECT , OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE , DATA OR PROFITS , WHETHER IN AN ACTION OF CONTRACT , NEGLIGENCE OR
OTHER TORTIOUS ACTION , ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
function _ _rest ( s , e ) {
var t = { } ;
for ( var p in s ) if ( Object . prototype . hasOwnProperty . call ( s , p ) && e . indexOf ( p ) < 0 )
t [ p ] = s [ p ] ;
if ( s != null && typeof Object . getOwnPropertySymbols === "function" )
for ( var i = 0 , p = Object . getOwnPropertySymbols ( s ) ; i < p . length ; i ++ ) {
if ( e . indexOf ( p [ i ] ) < 0 && Object . prototype . propertyIsEnumerable . call ( s , p [ i ] ) )
t [ p [ i ] ] = s [ p [ i ] ] ;
}
return t ;
}
function _ _decorate ( decorators , target , key , desc ) {
var c = arguments . length , r = c < 3 ? target : desc === null ? desc = Object . getOwnPropertyDescriptor ( target , key ) : desc , d ;
if ( typeof Reflect === "object" && typeof Reflect . decorate === "function" ) r = Reflect . decorate ( decorators , target , key , desc ) ;
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 ;
return c > 3 && r && Object . defineProperty ( target , key , r ) , r ;
}
const extractIntOrNaN = ( value ) => {
const numeric = parseInt ( value ) ;
return numeric . toString ( ) === value ? numeric : NaN ;
} ;
const extractPath = ( raw ) => {
const path = [ ] ;
raw . split ( '.' ) . forEach ( key => {
if ( /(.*)\[(\d+)]$/ . test ( key ) ) {
path . push ( ... key . substr ( 0 , key . length - 1 ) . split ( '[' ) . filter ( k => k . length ) ) ;
}
else {
path . push ( key ) ;
}
} ) ;
return path ;
} ;
function get ( state , rawOrPath , fallback = undefined ) {
const path = typeof rawOrPath === 'string' ? extractPath ( rawOrPath ) : rawOrPath ;
if ( isScalar ( state ) || path . length === 0 ) {
return fallback ;
}
const key = path . shift ( ) ;
const index = extractIntOrNaN ( key ) ;
if ( ! isNaN ( index ) ) {
if ( Array . isArray ( state ) && index >= 0 && index < state . length ) {
return path . length === 0 ? state [ index ] : get ( state [ index ] , path , fallback ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
return undefined ;
}
if ( has ( state , key ) ) {
const values = state ;
return path . length === 0 ? values [ key ] : get ( values [ key ] , path , fallback ) ;
}
return undefined ;
}
function set ( state , rawOrPath , value ) {
const path = typeof rawOrPath === 'string' ? extractPath ( rawOrPath ) : rawOrPath ;
if ( path . length === 0 ) {
return value ;
}
const key = path . shift ( ) ;
const index = extractIntOrNaN ( key ) ;
if ( ! isRecordLike ( state ) ) {
return set ( ! isNaN ( index ) ? [ ] : { } , [ key , ... path ] , value ) ;
}
if ( ! isNaN ( index ) && Array . isArray ( state ) ) {
const slice = [ ... state ] ;
slice [ index ] = path . length === 0 ? value : set ( slice [ index ] , path , value ) ;
return slice ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
const slice = Object . assign ( { } , state ) ;
slice [ key ] = path . length === 0 ? value : set ( slice [ key ] , path , value ) ;
return slice ;
}
const unsetInRecord = ( record , prop ) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const _a = record , _b = prop , _ = _a [ _b ] , copy = _ _rest ( _a , [ typeof _b === "symbol" ? _b : _b + "" ] ) ;
2020-11-11 11:56:00 +03:00
return copy ;
2021-08-03 14:48:41 +03:00
} ;
function unset ( state , rawOrPath ) {
if ( ! isRecordLike ( state ) ) {
return state ;
}
const path = typeof rawOrPath === 'string' ? extractPath ( rawOrPath ) : rawOrPath ;
if ( path . length === 0 ) {
return state ;
}
const key = path . shift ( ) ;
const index = extractIntOrNaN ( key ) ;
if ( ! isNaN ( index ) && Array . isArray ( state ) && index >= 0 && index < state . length ) {
const slice = [ ... state ] ;
if ( path . length === 0 ) {
slice . splice ( index , 1 ) ;
}
else {
slice [ index ] = unset ( slice [ index ] , path ) ;
}
return slice ;
}
if ( has ( state , key ) ) {
const slice = Object . assign ( { } , state ) ;
return path . length === 0
? unsetInRecord ( slice , key )
: Object . assign ( Object . assign ( { } , slice ) , { [ key ] : unset ( slice [ key ] , path ) } ) ;
}
return state ;
2020-11-11 11:56:00 +03:00
}
/ * *
* Escape a string for use in regular expressions .
* /
function escapeRegExp ( string ) {
return string . replace ( /[.*+?^${}()|[\]\\]/g , '\\$&' ) ; // $& means the whole matched string
}
/ * *
* Given a string format ( date ) return a regex to match against .
* /
function regexForFormat ( format ) {
const escaped = ` ^ ${ escapeRegExp ( format ) } $ ` ;
const formats = {
MM : '(0[1-9]|1[012])' ,
M : '([1-9]|1[012])' ,
DD : '([012][1-9]|3[01])' ,
D : '([012]?[1-9]|3[01])' ,
YYYY : '\\d{4}' ,
YY : '\\d{2}'
} ;
return new RegExp ( Object . keys ( formats ) . reduce ( ( regex , format ) => {
return regex . replace ( format , formats [ format ] ) ;
} , escaped ) ) ;
}
2021-08-03 14:48:41 +03:00
function datesEquals ( a , b ) {
return a . getTime ( ) === b . getTime ( ) ;
}
function arraysEquals ( a , b , predicate ) {
if ( a . length !== b . length ) {
2020-11-11 11:56:00 +03:00
return false ;
}
2021-08-03 14:48:41 +03:00
for ( let i = 0 ; i < a . length ; i ++ ) {
if ( ! predicate ( a [ i ] , b [ i ] ) ) {
return false ;
}
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
return true ;
}
function recordsEquals ( a , b , predicate ) {
if ( Object . keys ( a ) . length !== Object . keys ( b ) . length ) {
return false ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
for ( const prop in a ) {
if ( ! has ( b , prop ) || ! predicate ( a [ prop ] , b [ prop ] ) ) {
2020-11-11 11:56:00 +03:00
return false ;
}
}
return true ;
2021-08-03 14:48:41 +03:00
}
function strictEquals ( a , b ) {
return a === b ;
}
function equals ( a , b , predicate ) {
const typeOfA = typeOf ( a ) ;
const typeOfB = typeOf ( b ) ;
return typeOfA === typeOfB && ( ( typeOfA === TYPE . ARRAY && arraysEquals ( a , b , predicate ) ) ||
( typeOfA === TYPE . DATE && datesEquals ( a , b ) ) ||
( typeOfA === TYPE . RECORD && recordsEquals ( a , b , predicate ) ) ||
( typeOfA . includes ( 'InstanceOf' ) && equals ( Object . entries ( a ) , Object . entries ( b ) , predicate ) ) ) ;
}
function deepEquals ( a , b ) {
return a === b || equals ( a , b , deepEquals ) ;
}
function shallowEquals ( a , b ) {
return a === b || equals ( a , b , strictEquals ) ;
2020-11-11 11:56:00 +03:00
}
/ * *
* Given a string , convert snake _case to camelCase
* /
function snakeToCamel ( string ) {
return string . replace ( /([_][a-z0-9])/ig , ( $1 ) => {
if ( string . indexOf ( $1 ) !== 0 && string [ string . indexOf ( $1 ) - 1 ] !== '_' ) {
return $1 . toUpperCase ( ) . replace ( '_' , '' ) ;
}
return $1 ;
} ) ;
}
const rules = {
/ * *
* Rule : the value must be "yes" , "on" , "1" , or true
* /
accepted ( { value } ) {
return [ 'yes' , 'on' , '1' , 1 , true , 'true' ] . includes ( value ) ;
} ,
/ * *
* Rule : checks if a value is after a given date . Defaults to current time
* /
after ( { value } , compare = false ) {
const compareTimestamp = compare !== false ? Date . parse ( compare ) : Date . now ( ) ;
const valueTimestamp = value instanceof Date ? value . getTime ( ) : Date . parse ( value ) ;
return isNaN ( valueTimestamp ) ? false : ( valueTimestamp > compareTimestamp ) ;
} ,
/ * *
* Rule : checks if the value is only alpha
* /
alpha ( { value } , set = 'default' ) {
const sets = {
default : /^[a-zA-ZÀ-ÖØ-öø-ÿ]+$/ ,
latin : /^[a-zA-Z]+$/ ,
} ;
return typeof value === 'string' && sets [ has ( sets , set ) ? set : 'default' ] . test ( value ) ;
} ,
/ * *
* Rule : checks if the value is alpha numeric
* /
alphanumeric ( { value } , set = 'default' ) {
const sets = {
default : /^[a-zA-Z0-9À-ÖØ-öø-ÿ]+$/ ,
latin : /^[a-zA-Z0-9]+$/
} ;
return typeof value === 'string' && sets [ has ( sets , set ) ? set : 'default' ] . test ( value ) ;
} ,
/ * *
* Rule : checks if a value is after a given date . Defaults to current time
* /
before ( { value } , compare = false ) {
const compareTimestamp = compare !== false ? Date . parse ( compare ) : Date . now ( ) ;
const valueTimestamp = value instanceof Date ? value . getTime ( ) : Date . parse ( value ) ;
return isNaN ( valueTimestamp ) ? false : ( valueTimestamp < compareTimestamp ) ;
} ,
/ * *
* Rule : checks if the value is between two other values
* /
between ( { value } , from = 0 , to = 10 , force ) {
if ( from === null || to === null || isNaN ( from ) || isNaN ( to ) ) {
return false ;
}
if ( ( ! isNaN ( Number ( value ) ) && force !== 'length' ) || force === 'value' ) {
value = Number ( value ) ;
return ( value > Number ( from ) && value < Number ( to ) ) ;
}
if ( typeof value === 'string' || force === 'length' ) {
value = ( ! isNaN ( Number ( value ) ) ? value . toString ( ) : value ) ;
return value . length > from && value . length < to ;
}
return false ;
} ,
/ * *
* Confirm that the value of one field is the same as another , mostly used
* for password confirmations .
* /
confirm ( { value , formValues , name } , field ) {
let confirmationFieldName = field ;
if ( ! confirmationFieldName ) {
confirmationFieldName = /_confirm$/ . test ( name ) ? name . substr ( 0 , name . length - 8 ) : ` ${ name } _confirm ` ;
}
return formValues [ confirmationFieldName ] === value ;
} ,
/ * *
* Rule : ensures the value is a date according to Date . parse ( ) , or a format
* regex .
* /
date ( { value } , format = false ) {
return format ? regexForFormat ( format ) . test ( value ) : ! isNaN ( Date . parse ( value ) ) ;
} ,
/ * *
* Rule : tests
* /
email ( { value } ) {
if ( ! value ) {
return true ;
}
// eslint-disable-next-line
const isEmail = /^(([^<>()\[\].,;:\s@"]+(\.[^<>()\[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i ;
return isEmail . test ( value ) ;
} ,
/ * *
* Rule : Value ends with one of the given Strings
* /
endsWith ( { value } , ... stack ) {
if ( ! value ) {
return true ;
}
if ( typeof value === 'string' ) {
return stack . length === 0 || stack . some ( str => value . endsWith ( str ) ) ;
}
return false ;
} ,
/ * *
* Rule : Value is in an array ( stack ) .
* /
in ( { value } , ... stack ) {
2021-08-03 14:48:41 +03:00
return stack . some ( item => shallowEquals ( item , value ) ) ;
2020-11-11 11:56:00 +03:00
} ,
/ * *
* Rule : Match the value against a ( stack ) of patterns or strings
* /
matches ( { value } , ... stack ) {
return ! ! stack . find ( pattern => {
if ( typeof pattern === 'string' && pattern . substr ( 0 , 1 ) === '/' && pattern . substr ( - 1 ) === '/' ) {
pattern = new RegExp ( pattern . substr ( 1 , pattern . length - 2 ) ) ;
}
if ( pattern instanceof RegExp ) {
return pattern . test ( value ) ;
}
return pattern === value ;
} ) ;
} ,
/ * *
* Check the maximum value of a particular .
* /
max ( { value } , maximum = 10 , force ) {
if ( Array . isArray ( value ) ) {
maximum = ! isNaN ( Number ( maximum ) ) ? Number ( maximum ) : maximum ;
return value . length <= maximum ;
}
if ( ( ! isNaN ( value ) && force !== 'length' ) || force === 'value' ) {
value = ! isNaN ( value ) ? Number ( value ) : value ;
return value <= maximum ;
}
if ( typeof value === 'string' || ( force === 'length' ) ) {
value = ! isNaN ( value ) ? value . toString ( ) : value ;
return value . length <= maximum ;
}
return false ;
} ,
/ * *
* Check the minimum value of a particular .
* /
min ( { value } , minimum = 1 , force ) {
if ( Array . isArray ( value ) ) {
minimum = ! isNaN ( minimum ) ? Number ( minimum ) : minimum ;
return value . length >= minimum ;
}
if ( ( ! isNaN ( value ) && force !== 'length' ) || force === 'value' ) {
value = ! isNaN ( value ) ? Number ( value ) : value ;
return value >= minimum ;
}
if ( typeof value === 'string' || ( force === 'length' ) ) {
value = ! isNaN ( value ) ? value . toString ( ) : value ;
return value . length >= minimum ;
}
return false ;
} ,
/ * *
* Rule : Value is not in stack .
* /
not ( { value } , ... stack ) {
2021-08-03 14:48:41 +03:00
return ! stack . some ( item => shallowEquals ( item , value ) ) ;
2020-11-11 11:56:00 +03:00
} ,
/ * *
* Rule : checks if the value is only alpha numeric
* /
number ( { value } ) {
return String ( value ) . length > 0 && ! isNaN ( Number ( value ) ) ;
} ,
/ * *
* Rule : must be a value
* /
required ( { value } , isRequired = true ) {
if ( ! isRequired || [ 'no' , 'false' ] . includes ( isRequired ) ) {
return true ;
}
if ( Array . isArray ( value ) ) {
return ! ! value . length ;
}
if ( typeof value === 'string' ) {
return ! ! value ;
}
if ( typeof value === 'object' ) {
return ( ! value ) ? false : ! ! Object . keys ( value ) . length ;
}
return true ;
} ,
/ * *
* Rule : Value starts with one of the given Strings
* /
startsWith ( { value } , ... stack ) {
if ( ! value ) {
return true ;
}
if ( typeof value === 'string' ) {
return stack . length === 0 || stack . some ( str => value . startsWith ( str ) ) ;
}
return false ;
} ,
/ * *
* Rule : checks if a string is a valid url
* /
url ( { value } ) {
2021-08-03 14:48:41 +03:00
if ( ! value ) {
return true ;
}
2020-11-11 11:56:00 +03:00
return isUrl ( value ) ;
} ,
/ * *
* Rule : not a true rule — more like a compiler flag .
* /
bail ( ) {
return true ;
} ,
} ;
/ * *
* Message builders , names match rules names , see @ / validation / rules
* /
const messages = {
/ * *
* Fallback for rules without message builder
* @ param vm
* @ param context
* /
default ( vm , context ) {
return vm . $t ( 'validation.default' , context ) ;
} ,
accepted ( vm , context ) {
return vm . $t ( 'validation.accepted' , context ) ;
} ,
after ( vm , context , compare = false ) {
if ( typeof compare === 'string' && compare . length ) {
return vm . $t ( 'validation.after.compare' , context ) ;
}
return vm . $t ( 'validation.after.default' , context ) ;
} ,
alpha ( vm , context ) {
return vm . $t ( 'validation.alpha' , context ) ;
} ,
alphanumeric ( vm , context ) {
return vm . $t ( 'validation.alphanumeric' , context ) ;
} ,
before ( vm , context , compare = false ) {
if ( typeof compare === 'string' && compare . length ) {
return vm . $t ( 'validation.before.compare' , context ) ;
}
return vm . $t ( 'validation.before.default' , context ) ;
} ,
between ( vm , context , from = 0 , to = 10 , force ) {
const data = Object . assign ( Object . assign ( { } , context ) , { from , to } ) ;
if ( ( ! isNaN ( context . value ) && force !== 'length' ) || force === 'value' ) {
return vm . $t ( 'validation.between.force' , data ) ;
}
return vm . $t ( 'validation.between.default' , data ) ;
} ,
confirm ( vm , context ) {
return vm . $t ( 'validation.confirm' , context ) ;
} ,
date ( vm , context , format = false ) {
if ( typeof format === 'string' && format . length ) {
return vm . $t ( 'validation.date.format' , context ) ;
}
return vm . $t ( 'validation.date.default' , context ) ;
} ,
email ( vm , context ) {
return vm . $t ( 'validation.email.default' , context ) ;
} ,
endsWith ( vm , context ) {
return vm . $t ( 'validation.endsWith.default' , context ) ;
} ,
in ( vm , context ) {
if ( typeof context . value === 'string' && context . value ) {
return vm . $t ( 'validation.in.string' , context ) ;
}
return vm . $t ( 'validation.in.default' , context ) ;
} ,
matches ( vm , context ) {
return vm . $t ( 'validation.matches.default' , context ) ;
} ,
max ( vm , context , maximum = 10 , force ) {
if ( Array . isArray ( context . value ) ) {
return vm . $tc ( 'validation.max.array' , maximum , context ) ;
}
if ( ( ! isNaN ( context . value ) && force !== 'length' ) || force === 'value' ) {
return vm . $tc ( 'validation.max.force' , maximum , context ) ;
}
return vm . $tc ( 'validation.max.default' , maximum , context ) ;
} ,
min ( vm , context , minimum = 1 , force ) {
if ( Array . isArray ( context . value ) ) {
return vm . $tc ( 'validation.min.array' , minimum , context ) ;
}
if ( ( ! isNaN ( context . value ) && force !== 'length' ) || force === 'value' ) {
return vm . $tc ( 'validation.min.force' , minimum , context ) ;
}
return vm . $tc ( 'validation.min.default' , minimum , context ) ;
} ,
not ( vm , context ) {
return vm . $t ( 'validation.not.default' , context ) ;
} ,
number ( vm , context ) {
return vm . $t ( 'validation.number.default' , context ) ;
} ,
required ( vm , context ) {
return vm . $t ( 'validation.required.default' , context ) ;
} ,
startsWith ( vm , context ) {
return vm . $t ( 'validation.startsWith.default' , context ) ;
} ,
url ( vm , context ) {
return vm . $t ( 'validation.url.default' , context ) ;
}
} ;
/ * *
* The base formulario library .
* /
class Formulario {
constructor ( options ) {
this . validationRules = { } ;
this . validationMessages = { } ;
2021-08-03 14:48:41 +03:00
this . registry = new Map ( ) ;
2020-11-11 11:56:00 +03:00
this . validationRules = rules ;
this . validationMessages = messages ;
this . extend ( options || { } ) ;
}
/ * *
* Given a set of options , apply them to the pre - existing options .
* /
extend ( extendWith ) {
if ( typeof extendWith === 'object' ) {
this . validationRules = merge ( this . validationRules , extendWith . validationRules || { } ) ;
this . validationMessages = merge ( this . validationMessages , extendWith . validationMessages || { } ) ;
return this ;
}
2021-08-03 14:48:41 +03:00
throw new Error ( ` [Formulario]: Formulario.extend(): should be passed an object (was ${ typeof extendWith } ) ` ) ;
}
runValidation ( id ) {
if ( ! this . registry . has ( id ) ) {
throw new Error ( ` [Formulario]: Formulario.runValidation(): no forms with id " ${ id } " ` ) ;
}
const form = this . registry . get ( id ) ;
return form . runValidation ( ) ;
}
resetValidation ( id ) {
if ( ! this . registry . has ( id ) ) {
return ;
}
const form = this . registry . get ( id ) ;
form . resetValidation ( ) ;
}
/ * *
* Used by forms instances to add themselves into a registry
* @ internal
* /
register ( id , form ) {
if ( this . registry . has ( id ) ) {
throw new Error ( ` [Formulario]: Formulario.register(): id " ${ id } " is already in use ` ) ;
}
this . registry . set ( id , form ) ;
}
/ * *
* Used by forms instances to remove themselves from a registry
* @ internal
* /
unregister ( id ) {
if ( this . registry . has ( id ) ) {
this . registry . delete ( id ) ;
}
2020-11-11 11:56:00 +03:00
}
/ * *
* Get validation rules by merging any passed in with global rules .
2021-08-03 14:48:41 +03:00
* @ internal
2020-11-11 11:56:00 +03:00
* /
getRules ( extendWith = { } ) {
return merge ( this . validationRules , extendWith ) ;
}
/ * *
* Get validation messages by merging any passed in with global messages .
2021-08-03 14:48:41 +03:00
* @ internal
2020-11-11 11:56:00 +03:00
* /
getMessages ( vm , extendWith ) {
const raw = merge ( this . validationMessages || { } , extendWith ) ;
const messages = { } ;
for ( const name in raw ) {
messages [ name ] = ( context , ... args ) => {
return typeof raw [ name ] === 'string' ? raw [ name ] : raw [ name ] ( vm , context , ... args ) ;
} ;
}
return messages ;
}
}
2021-08-03 14:48:41 +03:00
function createValidator ( ruleFn , ruleName , ruleArgs , messageFn ) {
return ( context ) => {
return Promise . resolve ( ruleFn ( context , ... ruleArgs ) ) . then ( valid => {
return ! valid ? {
rule : ruleName ,
args : ruleArgs ,
context ,
message : messageFn ( context , ... ruleArgs ) ,
} : null ;
} ) ;
} ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
function parseModifier ( ruleName ) {
if ( /^[\^]/ . test ( ruleName . charAt ( 0 ) ) ) {
return [ snakeToCamel ( ruleName . substr ( 1 ) ) , ruleName . charAt ( 0 ) ] ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
return [ snakeToCamel ( ruleName ) , null ] ;
}
function processSingleArrayConstraint ( constraint , rules , messages ) {
const args = constraint . slice ( ) ;
const first = args . shift ( ) ;
if ( typeof first === 'function' ) {
return [ first , null , null ] ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
if ( typeof first !== 'string' ) {
throw new Error ( '[Formulario]: For array constraint first element must be rule name or Validator function' ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
const [ name , modifier ] = parseModifier ( first ) ;
if ( has ( rules , name ) ) {
return [
createValidator ( rules [ name ] , name , args , messages [ name ] || messages . default ) ,
name ,
modifier ,
] ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
throw new Error ( ` [Formulario] Can't create validator for constraint: ${ JSON . stringify ( constraint ) } ` ) ;
}
function processSingleStringConstraint ( constraint , rules , messages ) {
const args = constraint . split ( ':' ) ;
const [ name , modifier ] = parseModifier ( args . shift ( ) || '' ) ;
if ( has ( rules , name ) ) {
return [
createValidator ( rules [ name ] , name , args . length ? args . join ( ':' ) . split ( ',' ) : [ ] , messages [ name ] || messages . default ) ,
name ,
modifier ,
] ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
throw new Error ( ` [Formulario] Can't create validator for constraint: ${ constraint } ` ) ;
}
function processSingleConstraint ( constraint , rules , messages ) {
if ( typeof constraint === 'function' ) {
return [ constraint , null , null ] ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
if ( Array . isArray ( constraint ) && constraint . length ) {
return processSingleArrayConstraint ( constraint , rules , messages ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
if ( typeof constraint === 'string' ) {
return processSingleStringConstraint ( constraint , rules , messages ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
return [ ( ) => Promise . resolve ( null ) , null , null ] ;
}
function processConstraints ( constraints , rules , messages ) {
if ( typeof constraints === 'string' ) {
return processConstraints ( constraints . split ( '|' ) . filter ( f => f . length ) , rules , messages ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
if ( ! Array . isArray ( constraints ) ) {
return [ ] ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
return constraints . map ( constraint => processSingleConstraint ( constraint , rules , messages ) ) ;
}
function enlarge ( groups ) {
const enlarged = [ ] ;
if ( groups . length ) {
let current = groups . shift ( ) ;
enlarged . push ( current ) ;
groups . forEach ( ( group ) => {
if ( ! group . bail && group . bail === current . bail ) {
current . validators . push ( ... group . validators ) ;
}
else {
current = Object . assign ( { } , group ) ;
enlarged . push ( current ) ;
}
} ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
return enlarged ;
}
/ * *
* Given an array of rules , group them by bail signals . For example for this :
* bail | required | min : 10 | max : 20
* we would expect :
* [ [ required ] , [ min ] , [ max ] ]
* because any sub - array failure would cause a shutdown . While
* ^ required | min : 10 | max : 10
* would return :
* [ [ required ] , [ min , max ] ]
* and no bailing would produce :
* [ [ required , min , max ] ]
* @ param { array } rules
* /
function createValidatorGroups ( rules ) {
const mapper = ( [ validator , /** name */ , modifier ] ) => ( {
validators : [ validator ] ,
bail : modifier === '^' ,
} ) ;
const groups = [ ] ;
const bailIndex = rules . findIndex ( ( [ , name ] ) => name && name . toLowerCase ( ) === 'bail' ) ;
if ( bailIndex >= 0 ) {
groups . push ( ... enlarge ( rules . splice ( 0 , bailIndex + 1 ) . slice ( 0 , - 1 ) . map ( mapper ) ) ) ;
groups . push ( ... rules . map ( ( [ validator ] ) => ( {
validators : [ validator ] ,
bail : true ,
} ) ) ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
else {
groups . push ( ... enlarge ( rules . map ( mapper ) ) ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
return groups ;
}
function validateByGroup ( group , context ) {
return Promise . all ( group . validators . map ( validate => validate ( context ) ) )
. then ( violations => violations . filter ( v => v !== null ) ) ;
}
function validate ( validators , context ) {
return new Promise ( resolve => {
const resolveGroups = ( groups , all = [ ] ) => {
if ( groups . length ) {
const current = groups . shift ( ) ;
validateByGroup ( current , context ) . then ( violations => {
// The rule passed or its a non-bailing group, and there are additional groups to check, continue
if ( ( violations . length === 0 || ! current . bail ) && groups . length ) {
return resolveGroups ( groups , all . concat ( violations ) ) ;
}
return resolve ( all . concat ( violations ) ) ;
} ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
else {
resolve ( [ ] ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
} ;
resolveGroups ( createValidatorGroups ( validators ) ) ;
} ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
const VALIDATION _BEHAVIOR = {
DEMAND : 'demand' ,
LIVE : 'live' ,
SUBMIT : 'submit' ,
} ;
let FormularioField = class FormularioField extends Vue {
2020-11-11 11:56:00 +03:00
constructor ( ) {
super ( ... arguments ) ;
2021-08-03 14:48:41 +03:00
this . proxy = this . hasModel ? this . value : '' ;
this . localErrors = [ ] ;
this . violations = [ ] ;
this . validationRun = Promise . resolve ( [ ] ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
get fullPath ( ) {
return this . _ _Formulario _path !== '' ? ` ${ this . _ _Formulario _path } . ${ this . name } ` : this . name ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
/ * *
* Determines if this formulario element is v - modeled or not .
* /
2020-11-11 11:56:00 +03:00
get hasModel ( ) {
2021-08-03 14:48:41 +03:00
return has ( this . $options . propsData || { } , 'value' ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
get context ( ) {
return Object . defineProperty ( {
name : this . fullPath ,
path : this . fullPath ,
runValidation : this . runValidation . bind ( this ) ,
violations : this . violations ,
errors : this . localErrors ,
allErrors : [ ... this . localErrors , ... this . violations . map ( v => v . message ) ] ,
} , 'model' , {
get : ( ) => this . modelGetConverter ( this . proxy ) ,
set : ( value ) => {
this . syncProxy ( this . modelSetConverter ( value , this . proxy ) ) ;
} ,
} ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
get normalizedValidationRules ( ) {
const rules = { } ;
Object . keys ( this . validationRules ) . forEach ( key => {
rules [ snakeToCamel ( key ) ] = this . validationRules [ key ] ;
} ) ;
return rules ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
get normalizedValidationMessages ( ) {
const messages = { } ;
Object . keys ( this . validationMessages ) . forEach ( key => {
messages [ snakeToCamel ( key ) ] = this . validationMessages [ key ] ;
2020-11-11 11:56:00 +03:00
} ) ;
2021-08-03 14:48:41 +03:00
return messages ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
onValueChange ( ) {
this . syncProxy ( this . value ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
onProxyChange ( ) {
if ( this . validationBehavior === VALIDATION _BEHAVIOR . LIVE ) {
this . runValidation ( ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
else {
this . resetValidation ( ) ;
2020-11-11 11:56:00 +03:00
}
}
2021-08-03 14:48:41 +03:00
/ * *
* @ internal
* /
created ( ) {
if ( typeof this . _ _FormularioForm _register === 'function' ) {
this . _ _FormularioForm _register ( this . fullPath , this ) ;
}
if ( this . validationBehavior === VALIDATION _BEHAVIOR . LIVE ) {
this . runValidation ( ) ;
}
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
/ * *
* @ internal
* /
beforeDestroy ( ) {
if ( typeof this . _ _FormularioForm _unregister === 'function' ) {
this . _ _FormularioForm _unregister ( this . fullPath ) ;
2020-11-11 11:56:00 +03:00
}
}
2021-08-03 14:48:41 +03:00
syncProxy ( value ) {
if ( ! deepEquals ( value , this . proxy ) ) {
this . proxy = value ;
this . $emit ( 'input' , value ) ;
if ( typeof this . _ _FormularioForm _set === 'function' ) {
this . _ _FormularioForm _set ( this . fullPath , value ) ;
this . _ _FormularioForm _emitInput ( ) ;
2020-11-11 11:56:00 +03:00
}
}
}
2021-08-03 14:48:41 +03:00
runValidation ( ) {
this . validationRun = this . validate ( ) . then ( violations => {
this . violations = violations ;
this . emitValidation ( this . fullPath , violations ) ;
return this . violations ;
} ) ;
return this . validationRun ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
validate ( ) {
return validate ( processConstraints ( this . validation , this . $formulario . getRules ( this . normalizedValidationRules ) , this . $formulario . getMessages ( this , this . normalizedValidationMessages ) ) , {
value : this . proxy ,
name : this . fullPath ,
formValues : this . _ _FormularioForm _getState ( ) ,
} ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
emitValidation ( path , violations ) {
this . $emit ( 'validation' , { path , violations } ) ;
if ( typeof this . _ _FormularioForm _emitValidation === 'function' ) {
this . _ _FormularioForm _emitValidation ( path , violations ) ;
}
2020-11-11 11:56:00 +03:00
}
hasValidationErrors ( ) {
2021-08-03 14:48:41 +03:00
return new Promise ( resolve => {
this . $nextTick ( ( ) => {
this . validationRun . then ( ( ) => resolve ( this . violations . length > 0 ) ) ;
} ) ;
} ) ;
}
/ * *
* @ internal
* /
setErrors ( errors ) {
if ( ! this . errorsDisabled ) {
this . localErrors = errors ;
}
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
/ * *
* @ internal
* /
2020-11-11 11:56:00 +03:00
resetValidation ( ) {
2021-08-03 14:48:41 +03:00
this . localErrors = [ ] ;
this . violations = [ ] ;
2020-11-11 11:56:00 +03:00
}
} ;
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Inject ( { default : '' } )
] , FormularioField . prototype , "__Formulario_path" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Inject ( { default : undefined } )
] , FormularioField . prototype , "__FormularioForm_set" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Inject ( { default : ( ) => ( ) => { } } )
] , FormularioField . prototype , "__FormularioForm_emitInput" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Inject ( { default : ( ) => ( ) => { } } )
] , FormularioField . prototype , "__FormularioForm_emitValidation" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Inject ( { default : undefined } )
] , FormularioField . prototype , "__FormularioForm_register" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Inject ( { default : undefined } )
] , FormularioField . prototype , "__FormularioForm_unregister" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Inject ( { default : ( ) => ( ) => ( { } ) } )
] , FormularioField . prototype , "__FormularioForm_getState" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Model ( 'input' , { default : '' } )
] , FormularioField . prototype , "value" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Prop ( {
required : true ,
validator : ( name ) => typeof name === 'string' && name . length > 0 ,
} )
] , FormularioField . prototype , "name" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Prop ( { default : '' } )
] , FormularioField . prototype , "validation" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Prop ( { default : ( ) => ( { } ) } )
] , FormularioField . prototype , "validationRules" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Prop ( { default : ( ) => ( { } ) } )
] , FormularioField . prototype , "validationMessages" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Prop ( {
default : VALIDATION _BEHAVIOR . DEMAND ,
validator : behavior => Object . values ( VALIDATION _BEHAVIOR ) . includes ( behavior )
} )
] , FormularioField . prototype , "validationBehavior" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Prop ( { default : false } )
] , FormularioField . prototype , "errorsDisabled" , void 0 ) ;
_ _decorate ( [
Prop ( { default : ( ) => ( value ) => value } )
] , FormularioField . prototype , "modelGetConverter" , void 0 ) ;
_ _decorate ( [
Prop ( { default : ( ) => ( value ) => value } )
] , FormularioField . prototype , "modelSetConverter" , void 0 ) ;
_ _decorate ( [
Watch ( 'value' )
] , FormularioField . prototype , "onValueChange" , null ) ;
_ _decorate ( [
Watch ( 'proxy' )
] , FormularioField . prototype , "onProxyChange" , null ) ;
FormularioField = _ _decorate ( [
Component ( { name : 'FormularioField' , inheritAttrs : false } )
] , FormularioField ) ;
var script = FormularioField ;
2020-11-11 11:56:00 +03:00
function normalizeComponent ( template , style , script , scopeId , isFunctionalTemplate , moduleIdentifier /* server only */ , shadowMode , createInjector , createInjectorSSR , createInjectorShadow ) {
if ( typeof shadowMode !== 'boolean' ) {
createInjectorSSR = createInjector ;
createInjector = shadowMode ;
shadowMode = false ;
}
// Vue.extend constructor export interop.
const options = typeof script === 'function' ? script . options : script ;
// render functions
if ( template && template . render ) {
options . render = template . render ;
options . staticRenderFns = template . staticRenderFns ;
options . _compiled = true ;
// functional template
if ( isFunctionalTemplate ) {
options . functional = true ;
}
}
// scopedId
if ( scopeId ) {
options . _scopeId = scopeId ;
}
let hook ;
if ( moduleIdentifier ) {
// server build
hook = function ( context ) {
// 2.3 injection
context =
context || // cached call
( this . $vnode && this . $vnode . ssrContext ) || // stateful
( this . parent && this . parent . $vnode && this . parent . $vnode . ssrContext ) ; // functional
// 2.2 with runInNewContext: true
if ( ! context && typeof _ _VUE _SSR _CONTEXT _ _ !== 'undefined' ) {
context = _ _VUE _SSR _CONTEXT _ _ ;
}
// inject component styles
if ( style ) {
style . call ( this , createInjectorSSR ( context ) ) ;
}
// register component module identifier for async chunk inference
if ( context && context . _registeredComponents ) {
context . _registeredComponents . add ( moduleIdentifier ) ;
}
} ;
// used by ssr in case component is cached and beforeCreate
// never gets called
options . _ssrRegister = hook ;
}
else if ( style ) {
hook = shadowMode
? function ( context ) {
style . call ( this , createInjectorShadow ( context , this . $root . $options . shadowRoot ) ) ;
}
: function ( context ) {
style . call ( this , createInjector ( context ) ) ;
} ;
}
if ( hook ) {
if ( options . functional ) {
// register for functional component in vue file
const originalRender = options . render ;
options . render = function renderWithStyleInjection ( h , context ) {
hook . call ( context ) ;
return originalRender ( h , context ) ;
} ;
}
else {
// inject component registration as beforeCreate hook
const existing = options . beforeCreate ;
options . beforeCreate = existing ? [ ] . concat ( existing , hook ) : [ hook ] ;
}
}
return script ;
}
/* script */
const _ _vue _script _ _ = script ;
/* template */
var _ _vue _render _ _ = function ( ) {
var _vm = this ;
var _h = _vm . $createElement ;
var _c = _vm . _self . _c || _h ;
return _c (
2021-08-03 14:48:41 +03:00
"div" ,
_vm . _b ( { } , "div" , _vm . $attrs , false ) ,
[ _vm . _t ( "default" , null , { context : _vm . context } ) ] ,
2020-11-11 11:56:00 +03:00
2
)
} ;
var _ _vue _staticRenderFns _ _ = [ ] ;
_ _vue _render _ _ . _withStripped = true ;
/* style */
const _ _vue _inject _styles _ _ = undefined ;
/* scoped */
const _ _vue _scope _id _ _ = undefined ;
/* module identifier */
const _ _vue _module _identifier _ _ = undefined ;
/* functional template */
const _ _vue _is _functional _template _ _ = false ;
/* style inject */
/* style inject SSR */
/* style inject shadow dom */
const _ _vue _component _ _ = /*#__PURE__*/ normalizeComponent (
{ render : _ _vue _render _ _ , staticRenderFns : _ _vue _staticRenderFns _ _ } ,
_ _vue _inject _styles _ _ ,
_ _vue _script _ _ ,
_ _vue _scope _id _ _ ,
_ _vue _is _functional _template _ _ ,
_ _vue _module _identifier _ _ ,
false ,
undefined ,
undefined ,
undefined
) ;
2021-08-03 14:48:41 +03:00
let FormularioFieldGroup = class FormularioFieldGroup extends Vue {
get fullPath ( ) {
const path = ` ${ this . name } ` ;
if ( parseInt ( path ) . toString ( ) === path ) {
return ` ${ this . _ _Formulario _path } [ ${ path } ] ` ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
if ( this . _ _Formulario _path === '' ) {
return path ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
return ` ${ this . _ _Formulario _path } . ${ path } ` ;
2020-11-11 11:56:00 +03:00
}
} ;
_ _decorate ( [
Inject ( { default : '' } )
2021-08-03 14:48:41 +03:00
] , FormularioFieldGroup . prototype , "__Formulario_path" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
Prop ( { required : true } )
2021-08-03 14:48:41 +03:00
] , FormularioFieldGroup . prototype , "name" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Provide ( '__Formulario_path' )
] , FormularioFieldGroup . prototype , "fullPath" , null ) ;
FormularioFieldGroup = _ _decorate ( [
Component ( { name : 'FormularioFieldGroup' } )
] , FormularioFieldGroup ) ;
var script$1 = FormularioFieldGroup ;
2020-11-11 11:56:00 +03:00
/* script */
const _ _vue _script _ _$1 = script$1 ;
/* template */
var _ _vue _render _ _$1 = function ( ) {
var _vm = this ;
var _h = _vm . $createElement ;
var _c = _vm . _self . _c || _h ;
return _c ( "div" , [ _vm . _t ( "default" ) ] , 2 )
} ;
var _ _vue _staticRenderFns _ _$1 = [ ] ;
_ _vue _render _ _$1 . _withStripped = true ;
/* style */
const _ _vue _inject _styles _ _$1 = undefined ;
/* scoped */
const _ _vue _scope _id _ _$1 = undefined ;
/* module identifier */
const _ _vue _module _identifier _ _$1 = undefined ;
/* functional template */
const _ _vue _is _functional _template _ _$1 = false ;
/* style inject */
/* style inject SSR */
/* style inject shadow dom */
const _ _vue _component _ _$1 = /*#__PURE__*/ normalizeComponent (
{ render : _ _vue _render _ _$1 , staticRenderFns : _ _vue _staticRenderFns _ _$1 } ,
_ _vue _inject _styles _ _$1 ,
_ _vue _script _ _$1 ,
_ _vue _scope _id _ _$1 ,
_ _vue _is _functional _template _ _$1 ,
_ _vue _module _identifier _ _$1 ,
false ,
undefined ,
undefined ,
undefined
) ;
2021-08-03 14:48:41 +03:00
const update = ( state , path , value ) => {
if ( value === undefined ) {
return unset ( state , path ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
return set ( state , path , value ) ;
2020-11-11 11:56:00 +03:00
} ;
2021-08-03 14:48:41 +03:00
let FormularioForm = class FormularioForm extends Vue {
2020-11-11 11:56:00 +03:00
constructor ( ) {
super ( ... arguments ) ;
2021-08-03 14:48:41 +03:00
this . proxy = { } ;
this . registry = new Map ( ) ;
// Local error messages are temporal, they wiped each resetValidation call
this . localFieldsErrors = { } ;
this . localFormErrors = [ ] ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
get fieldsErrorsComputed ( ) {
return merge ( this . fieldsErrors || { } , this . localFieldsErrors ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
get formErrorsComputed ( ) {
return [ ... this . formErrors , ... this . localFormErrors ] ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
register ( path , field ) {
if ( ! this . registry . has ( path ) ) {
this . registry . set ( path , field ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
const value = get ( this . proxy , path ) ;
if ( ! field . hasModel ) {
if ( value !== undefined ) {
field . proxy = value ;
}
else {
this . setFieldValue ( path , null ) ;
this . emitInput ( ) ;
}
}
else if ( ! deepEquals ( field . proxy , value ) ) {
this . setFieldValue ( path , field . proxy ) ;
this . emitInput ( ) ;
}
if ( has ( this . fieldsErrorsComputed , path ) ) {
field . setErrors ( this . fieldsErrorsComputed [ path ] ) ;
2020-11-11 11:56:00 +03:00
}
}
2021-08-03 14:48:41 +03:00
unregister ( path ) {
if ( this . registry . has ( path ) ) {
this . registry . delete ( path ) ;
this . proxy = unset ( this . proxy , path ) ;
this . emitInput ( ) ;
}
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
getState ( ) {
return this . proxy ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
setFieldValue ( path , value ) {
this . proxy = update ( this . proxy , path , value ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
emitInput ( ) {
this . $emit ( 'input' , clone ( this . proxy ) ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
emitValidation ( path , violations ) {
this . $emit ( 'validation' , { path , violations } ) ;
2020-11-11 11:56:00 +03:00
}
2021-08-03 14:48:41 +03:00
onStateChange ( newState ) {
const newProxy = clone ( newState ) ;
const oldProxy = this . proxy ;
let proxyHasChanges = false ;
this . registry . forEach ( ( field , path ) => {
const newValue = get ( newState , path , null ) ;
const oldValue = get ( oldProxy , path , null ) ;
field . proxy = newValue ;
if ( ! deepEquals ( newValue , oldValue ) ) {
field . $emit ( 'input' , newValue ) ;
update ( newProxy , path , newValue ) ;
proxyHasChanges = true ;
}
} ) ;
this . proxy = newProxy ;
if ( proxyHasChanges ) {
this . emitInput ( ) ;
2020-11-11 11:56:00 +03:00
}
}
2021-08-03 14:48:41 +03:00
onFieldsErrorsChange ( fieldsErrors ) {
this . registry . forEach ( ( field , path ) => {
field . setErrors ( fieldsErrors [ path ] || [ ] ) ;
} ) ;
}
2020-11-11 11:56:00 +03:00
created ( ) {
2021-08-03 14:48:41 +03:00
this . $formulario . register ( this . id , this ) ;
if ( typeof this . state === 'object' ) {
this . proxy = clone ( this . state ) ;
2020-11-11 11:56:00 +03:00
}
}
beforeDestroy ( ) {
2021-08-03 14:48:41 +03:00
this . $formulario . unregister ( this . id ) ;
2020-11-11 11:56:00 +03:00
}
runValidation ( ) {
2021-08-03 14:48:41 +03:00
const runs = [ ] ;
const violations = { } ;
this . registry . forEach ( ( field , path ) => {
runs . push ( field . runValidation ( ) . then ( v => { violations [ path ] = v ; } ) ) ;
2020-11-11 11:56:00 +03:00
} ) ;
2021-08-03 14:48:41 +03:00
return Promise . all ( runs ) . then ( ( ) => violations ) ;
2020-11-11 11:56:00 +03:00
}
hasValidationErrors ( ) {
2021-08-03 14:48:41 +03:00
return this . runValidation ( ) . then ( violations => {
return Object . keys ( violations ) . some ( path => violations [ path ] . length > 0 ) ;
2020-11-11 11:56:00 +03:00
} ) ;
}
2021-08-03 14:48:41 +03:00
setErrors ( { fieldsErrors , formErrors } ) {
this . localFieldsErrors = fieldsErrors || { } ;
this . localFormErrors = formErrors || [ ] ;
2020-11-11 11:56:00 +03:00
}
resetValidation ( ) {
2021-08-03 14:48:41 +03:00
this . localFieldsErrors = { } ;
this . localFormErrors = [ ] ;
this . registry . forEach ( ( field ) => {
field . resetValidation ( ) ;
} ) ;
}
onSubmit ( ) {
return this . runValidation ( ) . then ( violations => {
const hasErrors = Object . keys ( violations ) . some ( path => violations [ path ] . length > 0 ) ;
if ( ! hasErrors ) {
this . $emit ( 'submit' , clone ( this . proxy ) ) ;
}
else {
this . $emit ( 'error' , violations ) ;
}
} ) ;
2020-11-11 11:56:00 +03:00
}
} ;
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Model ( 'input' , { default : ( ) => ( { } ) } )
] , FormularioForm . prototype , "state" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Prop ( { default : ( ) => id ( 'formulario-form' ) } )
] , FormularioForm . prototype , "id" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Prop ( { default : ( ) => ( { } ) } )
] , FormularioForm . prototype , "fieldsErrors" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Prop ( { default : ( ) => ( [ ] ) } )
] , FormularioForm . prototype , "formErrors" , void 0 ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Provide ( '__FormularioForm_register' )
] , FormularioForm . prototype , "register" , null ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Provide ( '__FormularioForm_unregister' )
] , FormularioForm . prototype , "unregister" , null ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Provide ( '__FormularioForm_getState' )
] , FormularioForm . prototype , "getState" , null ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Provide ( '__FormularioForm_set' )
] , FormularioForm . prototype , "setFieldValue" , null ) ;
2020-11-13 12:28:12 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Provide ( '__FormularioForm_emitInput' )
] , FormularioForm . prototype , "emitInput" , null ) ;
2020-11-13 12:28:12 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Provide ( '__FormularioForm_emitValidation' )
] , FormularioForm . prototype , "emitValidation" , null ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Watch ( 'state' , { deep : true } )
] , FormularioForm . prototype , "onStateChange" , null ) ;
2020-11-11 11:56:00 +03:00
_ _decorate ( [
2021-08-03 14:48:41 +03:00
Watch ( 'fieldsErrorsComputed' , { deep : true , immediate : true } )
] , FormularioForm . prototype , "onFieldsErrorsChange" , null ) ;
FormularioForm = _ _decorate ( [
Component ( { name : 'FormularioForm' } )
] , FormularioForm ) ;
var script$2 = FormularioForm ;
2020-11-11 11:56:00 +03:00
/* script */
const _ _vue _script _ _$2 = script$2 ;
/* template */
var _ _vue _render _ _$2 = function ( ) {
var _vm = this ;
var _h = _vm . $createElement ;
var _c = _vm . _self . _c || _h ;
return _c (
2021-08-03 14:48:41 +03:00
"form" ,
{
on : {
submit : function ( $event ) {
$event . preventDefault ( ) ;
return _vm . onSubmit ( $event )
}
}
} ,
[ _vm . _t ( "default" , null , { errors : _vm . formErrorsComputed } ) ] ,
2020-11-11 11:56:00 +03:00
2
)
} ;
var _ _vue _staticRenderFns _ _$2 = [ ] ;
_ _vue _render _ _$2 . _withStripped = true ;
/* style */
const _ _vue _inject _styles _ _$2 = undefined ;
/* scoped */
const _ _vue _scope _id _ _$2 = undefined ;
/* module identifier */
const _ _vue _module _identifier _ _$2 = undefined ;
/* functional template */
const _ _vue _is _functional _template _ _$2 = false ;
/* style inject */
/* style inject SSR */
/* style inject shadow dom */
const _ _vue _component _ _$2 = /*#__PURE__*/ normalizeComponent (
{ render : _ _vue _render _ _$2 , staticRenderFns : _ _vue _staticRenderFns _ _$2 } ,
_ _vue _inject _styles _ _$2 ,
_ _vue _script _ _$2 ,
_ _vue _scope _id _ _$2 ,
_ _vue _is _functional _template _ _$2 ,
_ _vue _module _identifier _ _$2 ,
false ,
undefined ,
undefined ,
undefined
) ;
var index = {
2021-08-03 14:48:41 +03:00
Formulario ,
2020-11-11 11:56:00 +03:00
install ( Vue , options ) {
2021-08-03 14:48:41 +03:00
Vue . component ( 'FormularioField' , _ _vue _component _ _ ) ;
Vue . component ( 'FormularioFieldGroup' , _ _vue _component _ _$1 ) ;
Vue . component ( 'FormularioForm' , _ _vue _component _ _$2 ) ;
// @deprecated Use FormularioField instead
Vue . component ( 'FormularioInput' , _ _vue _component _ _ ) ;
// @deprecated Use FormularioFieldGroup instead
2020-11-11 11:56:00 +03:00
Vue . component ( 'FormularioGrouping' , _ _vue _component _ _$1 ) ;
Vue . mixin ( {
beforeCreate ( ) {
const o = this . $options ;
if ( typeof o . formulario === 'function' ) {
this . $formulario = o . formulario ( ) ;
}
else if ( o . parent && o . parent . $formulario ) {
this . $formulario = o . parent . $formulario ;
}
else {
this . $formulario = new Formulario ( options ) ;
}
}
} ) ;
} ,
} ;
export default index ;