(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('is-url'), require('nanoid'), require('is-plain-object')) : typeof define === 'function' && define.amd ? define(['exports', 'is-url', 'nanoid', 'is-plain-object'], factory) : (global = global || self, factory(global.Formulate = {}, global.isUrl, global.nanoid, global.isPlainObject)); }(this, (function (exports, isUrl, nanoid, isPlainObject) { 'use strict'; isUrl = isUrl && isUrl.hasOwnProperty('default') ? isUrl['default'] : isUrl; nanoid = nanoid && nanoid.hasOwnProperty('default') ? nanoid['default'] : nanoid; isPlainObject = isPlainObject && isPlainObject.hasOwnProperty('default') ? isPlainObject['default'] : isPlainObject; var library = { // === SINGLE LINE TEXT STYLE INPUTS text: { classification: 'text', component: 'FormulateInputText' }, email: { classification: 'text', component: 'FormulateInputText' }, number: { classification: 'text', component: 'FormulateInputText' }, color: { classification: 'text', component: 'FormulateInputText' }, date: { classification: 'text', component: 'FormulateInputText' }, hidden: { classification: 'text', component: 'FormulateInputText' }, month: { classification: 'text', component: 'FormulateInputText' }, password: { classification: 'text', component: 'FormulateInputText' }, search: { classification: 'text', component: 'FormulateInputText' }, tel: { classification: 'text', component: 'FormulateInputText' }, time: { classification: 'text', component: 'FormulateInputText' }, url: { classification: 'text', component: 'FormulateInputText' }, week: { classification: 'text', component: 'FormulateInputText' }, 'datetime-local': { classification: 'text', component: 'FormulateInputText' }, // === SLIDER INPUTS range: { classification: 'slider', component: 'FormulateInputSlider' }, // === MULTI LINE TEXT INPUTS textarea: { classification: 'textarea', component: 'FormulateInputTextArea' }, // === BOX STYLE INPUTS checkbox: { classification: 'box', component: 'FormulateInputBox' }, radio: { classification: 'box', component: 'FormulateInputBox' }, // === BUTTON STYLE INPUTS submit: { classification: 'button', component: 'FormulateInputButton' }, button: { classification: 'button', component: 'FormulateInputButton' }, // === SELECT STYLE INPUTS select: { classification: 'select', component: 'FormulateInputSelect' }, // === FILE TYPE file: { classification: 'file', component: 'FormulateInputFile' }, image: { classification: 'file', component: 'FormulateInputFile' } }; /** * The file upload class holds and represents a file’s upload state durring * the upload flow. */ var FileUpload = function FileUpload (input, context, options) { this.input = input; this.fileList = input.files; this.files = []; this.options = options; this.addFileList(this.fileList); this.context = context; }; /** * Produce an array of files and alert the callback. * @param {FileList} */ FileUpload.prototype.addFileList = function addFileList (fileList) { var this$1 = this; var loop = function ( i ) { var file = fileList[i]; var uuid = nanoid(); var removeFile = function () { this.removeFile(uuid); }; this$1.files.push({ progress: false, error: false, complete: false, justFinished: false, name: file.name || 'file-upload', file: file, uuid: uuid, path: false, removeFile: removeFile.bind(this$1), previewData: false }); }; for (var i = 0; i < fileList.length; i++) loop( i ); }; /** * Check if the file has an. */ FileUpload.prototype.hasUploader = function hasUploader () { return !!this.context.uploader }; /** * Check if the given uploader is axios instance. */ FileUpload.prototype.uploaderIsAxios = function uploaderIsAxios () { if ( this.hasUploader && typeof this.hasUploader.request === 'function' && typeof this.hasUploader.get === 'function' && typeof this.hasUploader.delete === 'function' && typeof this.hasUploader.post === 'function' ) { return true } return false }; /** * Get a new uploader function. */ FileUpload.prototype.getUploader = function getUploader () { var ref; var args = [], len = arguments.length; while ( len-- ) args[ len ] = arguments[ len ]; if (this.uploaderIsAxios()) { var formData = new FormData(); formData.append(this.context.name || 'file', args[0]); return this.uploader.post(this.context.uploadUrl, formData, { headers: { 'Content-Type': 'multipart/form-data' }, onUploadProgress: function (progressEvent) { args[1](Math.round((progressEvent.loaded * 100) / progressEvent.total)); } }) .catch(function (err) { return args[2](err); }) } return (ref = this.context).uploader.apply(ref, args) }; /** * Perform the file upload. */ FileUpload.prototype.upload = function upload () { var this$1 = this; return new Promise(function (resolve, reject) { if (!this$1.hasUploader) { return reject(new Error('No uploader has been defined')) } Promise.all(this$1.files.map(function (file) { return file.path ? Promise.resolve(file.path) : this$1.getUploader( file.file, function (progress) { file.progress = progress; if (progress >= 100) { if (!file.complete) { file.justFinished = true; setTimeout(function () { file.justFinished = false; }, this$1.options.uploadJustCompleteDuration); } file.complete = true; } }, function (error) { file.progress = 0; file.error = error; file.complete = true; }, this$1.options ) })) .then(function (results) { return resolve(results); }) .catch(function (err) { throw new Error(err) }); }) }; /** * Remove a file from the uploader (and the file list) * @param {string} uuid */ FileUpload.prototype.removeFile = function removeFile (uuid) { this.files = this.files.filter(function (file) { return file.uuid !== uuid; }); if (window) { var transfer = new DataTransfer(); this.files.map(function (file) { return transfer.items.add(file.file); }); this.fileList = transfer.files; this.input.files = this.fileList; } }; /** * load image previews for all uploads. */ FileUpload.prototype.loadPreviews = function loadPreviews () { this.files.map(function (file) { if (!file.previewData && window && window.FileReader && /^image\//.test(file.file.type)) { var reader = new FileReader(); reader.onload = function (e) { return Object.assign(file, { previewData: e.target.result }); }; reader.readAsDataURL(file.file); } }); }; /** * Get the files. */ FileUpload.prototype.getFileList = function getFileList () { return this.fileList }; /** * Get the files. */ FileUpload.prototype.getFiles = function getFiles () { return this.files }; FileUpload.prototype.toString = function toString () { var descriptor = this.files.length ? this.files.length + ' files' : 'empty'; return ("FileUpload(" + descriptor + ")") }; /** * Function to map over an object. * @param {Object} obj An object to map over * @param {Function} callback */ function map (original, callback) { var obj = {}; for (var key in original) { obj[key] = callback(key, original[key]); } return obj } /** * Shallow equal. * @param {} objA * @param {*} objB */ function shallowEqualObjects (objA, objB) { if (objA === objB) { return true } if (!objA || !objB) { return false } var aKeys = Object.keys(objA); var bKeys = Object.keys(objB); var len = aKeys.length; if (bKeys.length !== len) { return false } for (var i = 0; i < len; i++) { var key = aKeys[i]; if (objA[key] !== objB[key]) { return false } } return true } /** * Given a string, object, falsey, or array - return an array. * @param {mixed} item */ function arrayify (item) { if (!item) { return [] } if (typeof item === 'string') { return [item] } if (Array.isArray(item)) { return item } if (typeof item === 'object') { return Object.values(item) } return [] } /** * How to add an item. * @param {string} item */ function sentence (item) { if (typeof item === 'string') { return item[0].toUpperCase() + item.substr(1) } return item } /** * Given an array or string return an array of callables. * @param {array|string} validation * @param {array} rules and array of functions * @return {array} an array of functions */ function parseRules (validation, rules) { if (typeof validation === 'string') { return parseRules(validation.split('|'), rules) } if (!Array.isArray(validation)) { return [] } return validation.map(function (rule) { return parseRule(rule, rules); }).filter(function (f) { return !!f; }) } /** * Given a string or function, parse it and return the an array in the format * [fn, [...arguments]] * @param {string|function} rule */ function parseRule (rule, rules) { if (typeof rule === 'function') { return [rule, []] } if (Array.isArray(rule) && rule.length) { rule = rule.map(function (r) { return r; }); // light clone if (typeof rule[0] === 'string' && rules.hasOwnProperty(rule[0])) { return [rules[rule.shift()], rule] } if (typeof rule[0] === 'function') { return [rule.shift(), rule] } } if (typeof rule === 'string') { var segments = rule.split(':'); var functionName = segments.shift(); if (rules.hasOwnProperty(functionName)) { return [rules[functionName], segments.length ? segments.join(':').split(',') : []] } else { throw new Error(("Unknown validation rule " + rule)) } } return false } /** * Escape a string for use in regular expressions. * @param {string} string */ function escapeRegExp (string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') // $& means the whole matched string } /** * Given a string format (date) return a regex to match against. * @param {string} format */ function regexForFormat (format) { var escaped = "^" + (escapeRegExp(format)) + "$"; var 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(function (regex, format) { return regex.replace(format, formats[format]) }, escaped)) } /** * Check if * @param {mixed} data */ function isValueType (data) { switch (typeof data) { case 'symbol': case 'number': case 'string': case 'boolean': case 'undefined': return true default: if (data === null) { return true } return false } } /** * A simple (somewhat non-comprehensive) cloneDeep function, valid for our use * case of needing to unbind reactive watchers. */ function cloneDeep (obj) { var newObj = {}; for (var key in obj) { if (obj[key] instanceof FileUpload || isValueType(obj[key])) { newObj[key] = obj; } else { newObj[key] = cloneDeep(obj[key]); } } return newObj } /** * Library of rules */ var rules = { /** * Rule: the value must be "yes", "on", "1", or true */ accepted: function (ref) { var value = ref.value; return Promise.resolve(['yes', 'on', '1', 1, true, 'true'].includes(value)) }, /** * Rule: checks if a value is after a given date. Defaults to current time */ after: function (ref, compare) { var value = ref.value; if ( compare === void 0 ) compare = false; var timestamp = Date.parse(compare || new Date()); var fieldValue = Date.parse(value); return Promise.resolve(isNaN(fieldValue) ? false : (fieldValue > timestamp)) }, /** * Rule: checks if the value is only alpha */ alpha: function (ref, set) { var value = ref.value; if ( set === void 0 ) set = 'default'; var sets = { default: /^[a-zA-ZÀ-ÖØ-öø-ÿ]+$/, latin: /^[a-zA-Z]+$/ }; var selectedSet = sets.hasOwnProperty(set) ? set : 'default'; return Promise.resolve(sets[selectedSet].test(value)) }, /** * Rule: checks if the value is alpha numeric */ alphanumeric: function (ref, set) { var value = ref.value; if ( set === void 0 ) set = 'default'; var sets = { default: /^[a-zA-Z0-9À-ÖØ-öø-ÿ]+$/, latin: /^[a-zA-Z0-9]+$/ }; var selectedSet = sets.hasOwnProperty(set) ? set : 'default'; return Promise.resolve(sets[selectedSet].test(value)) }, /** * Rule: checks if a value is after a given date. Defaults to current time */ before: function (ref, compare) { var value = ref.value; if ( compare === void 0 ) compare = false; var timestamp = Date.parse(compare || new Date()); var fieldValue = Date.parse(value); return Promise.resolve(isNaN(fieldValue) ? false : (fieldValue < timestamp)) }, /** * Rule: checks if the value is between two other values */ between: function (ref, from, to) { var value = ref.value; if ( from === void 0 ) from = 0; if ( to === void 0 ) to = 10; return Promise.resolve((function () { if (from === null || to === null || isNaN(from) || isNaN(to)) { return false } from = Number(from); to = Number(to); if (!isNaN(value)) { value = Number(value); return (value > from && value < to) } if (typeof value === 'string') { 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: function (ref, field) { var value = ref.value; var getFormValues = ref.getFormValues; var name = ref.name; return Promise.resolve((function () { var formValues = getFormValues(); var 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: function (ref, format) { var value = ref.value; if ( format === void 0 ) format = false; return Promise.resolve((function () { if (format && typeof format === 'string') { return regexForFormat(format).test(value) } return !isNaN(Date.parse(value)) })()) }, /** * Rule: tests */ email: function (ref) { var value = ref.value; // eslint-disable-next-line var isEmail = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; return Promise.resolve(isEmail.test(value)) }, /** * Rule: Value is in an array (stack). */ in: function (ref) { var value = ref.value; var stack = [], len = arguments.length - 1; while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ]; return Promise.resolve(stack.find(function (item) { if (typeof item === 'object') { return shallowEqualObjects(item, value) } return item === value }) !== undefined) }, /** * Rule: Match the value against a (stack) of patterns or strings */ matches: function (ref) { var value = ref.value; var stack = [], len = arguments.length - 1; while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ]; return Promise.resolve(!!stack.find(function (pattern) { if (pattern instanceof RegExp) { return pattern.test(value) } return pattern === value })) }, /** * Check the maximum value of a particular. */ max: function (ref, minimum, force) { var value = ref.value; if ( minimum === void 0 ) minimum = 10; return Promise.resolve((function () { 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 })()) }, /** * Check the file type is correct. */ mime: function (ref) { var value = ref.value; var types = [], len = arguments.length - 1; while ( len-- > 0 ) types[ len ] = arguments[ len + 1 ]; return Promise.resolve((function () { if (value instanceof FileUpload) { var fileList = value.getFileList(); for (var i = 0; i < fileList.length; i++) { var file = fileList[i]; if (!types.includes(file.type)) { return false } } } return true })()) }, /** * Check the minimum value of a particular. */ min: function (ref, minimum, force) { var value = ref.value; if ( minimum === void 0 ) minimum = 1; return Promise.resolve((function () { 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: function (ref) { var value = ref.value; var stack = [], len = arguments.length - 1; while ( len-- > 0 ) stack[ len ] = arguments[ len + 1 ]; return Promise.resolve(stack.find(function (item) { if (typeof item === 'object') { return shallowEqualObjects(item, value) } return item === value }) === undefined) }, /** * Rule: checks if the value is only alpha numeric */ number: function (ref) { var value = ref.value; return Promise.resolve(!isNaN(value)) }, /** * Rule: must be a value */ required: function (ref, isRequired) { var value = ref.value; if ( isRequired === void 0 ) isRequired = true; return Promise.resolve((function () { 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: checks if a string is a valid url */ url: function (ref) { var value = ref.value; return Promise.resolve(isUrl(value)) } }; /** * Validation error message generators. */ var en = { /** * Valid accepted value. */ accepted: function (ref) { var name = ref.name; return ("Please accept the " + name + ".") }, /** * The date is not after. */ after: function (ref) { var name = ref.name; var args = ref.args; if (Array.isArray(args) && args.length) { return ((sentence(name)) + " must be after " + (args[0]) + ".") } return ((sentence(name)) + " must be a later date.") }, /** * The value is not a letter. */ alpha: function (ref) { var name = ref.name; return ((sentence(name)) + " can only contain alphabetical characters.") }, /** * Rule: checks if the value is alpha numeric */ alphanumeric: function (ref) { var name = ref.name; return ((sentence(name)) + " can only contain letters and numbers.") }, /** * The date is not before. */ before: function (ref) { var name = ref.name; var args = ref.args; if (Array.isArray(args) && args.length) { return ((sentence(name)) + " must be before " + (args[0]) + ".") } return ((sentence(name)) + " must be an earlier date.") }, /** * The value is not between two numbers or lengths */ between: function (ref) { var name = ref.name; var value = ref.value; var args = ref.args; if (!isNaN(value)) { return ((sentence(name)) + " must be between " + (args[0]) + " and " + (args[1]) + ".") } return ((sentence(name)) + " must be between " + (args[0]) + " and " + (args[1]) + " characters long.") }, /** * The confirmation field does not match */ confirm: function (ref) { var name = ref.name; var args = ref.args; return ((sentence(name)) + " does not match.") }, /** * Is not a valid date. */ date: function (ref) { var name = ref.name; var args = ref.args; if (Array.isArray(args) && args.length) { return ((sentence(name)) + " is not a valid, please use the format " + (args[0])) } return ((sentence(name)) + " is not a valid date.") }, /** * The default render method for error messages. */ default: function (ref) { var name = ref.name; return "This field isn’t valid." }, /** * Is not a valid email address. */ email: function (ref) { var name = ref.name; var value = ref.value; if (!value) { return 'Please enter a valid email address.' } return ("“" + value + "” is not a valid email address.") }, /** * Value is an allowed value. */ in: function (ref) { var name = ref.name; var value = ref.value; if (typeof value === 'string' && value) { return ("“" + (sentence(value)) + "” is not an allowed " + name + ".") } return ("This is not an allowed " + name + ".") }, /** * Value is not a match. */ matches: function (ref) { var name = ref.name; return ((sentence(name)) + " is not an allowed value.") }, /** * The maximum value allowed. */ max: function (ref) { var name = ref.name; var value = ref.value; var args = ref.args; if (Array.isArray(value)) { return ("You may only select " + (args[0]) + " " + name + ".") } var force = Array.isArray(args) && args[1] ? args[1] : false; if ((!isNaN(value) && force !== 'length') || force === 'value') { return ((sentence(name)) + " must be less than " + (args[0]) + ".") } return ((sentence(name)) + " must be less than " + (args[0]) + " characters long.") }, /** * The (field-level) error message for mime errors. */ mime: function (ref) { var name = ref.name; var args = ref.args; return ((sentence(name)) + " must be of the the type: " + (args[0] || 'No file formats allowed.')) }, /** * The maximum value allowed. */ min: function (ref) { var name = ref.name; var value = ref.value; var args = ref.args; if (Array.isArray(value)) { return ("You must select at least " + (args[0]) + " " + name + ".") } var force = Array.isArray(args) && args[1] ? args[1] : false; if ((!isNaN(value) && force !== 'length') || force === 'value') { return ((sentence(name)) + " must be more than " + (args[0]) + ".") } return ((sentence(name)) + " must be more than " + (args[0]) + " characters long.") }, /** * The field is not an allowed value */ not: function (ref) { var name = ref.name; var value = ref.value; return ("“" + value + "” is not an allowed " + name + ".") }, /** * The field is not a number */ number: function (ref) { var name = ref.name; return ((sentence(name)) + " must be a number.") }, /** * Required field. */ required: function (ref) { var name = ref.name; return ((sentence(name)) + " is required.") }, /** * Value is not a url. */ url: function (ref) { var name = ref.name; return "Please include a valid url." } }; /** * A fake uploader used by default. * * @param {File} file * @param {function} progress * @param {function} error * @param {object} options */ function fauxUploader (file, progress, error, options) { return new Promise(function (resolve, reject) { var totalTime = (options.fauxUploaderDuration || 2000) * (0.5 + Math.random()); var start = performance.now(); /** * Create a recursive timeout that advances the progress. */ var advance = function () { return setTimeout(function () { var elapsed = performance.now() - start; var currentProgress = Math.min(100, Math.round(elapsed / totalTime * 100)); progress(currentProgress); if (currentProgress >= 100) { return resolve({ url: 'http://via.placeholder.com/350x150.png', name: file.name }) } else { advance(); } }, 20); }; advance(); }) } /** * For a single instance of an input, export all of the context needed to fully * render that element. * @return {object} */ var context = { context: function context () { return defineModel.call(this, Object.assign({}, {type: this.type, value: this.value, name: this.nameOrFallback, classification: this.classification, component: this.component, id: this.id || this.defaultId, hasLabel: (this.label && this.classification !== 'button'), label: this.label, labelPosition: this.logicalLabelPosition, attributes: this.elementAttributes, blurHandler: blurHandler.bind(this), imageBehavior: this.imageBehavior, uploadUrl: this.uploadUrl, uploader: this.uploader || this.$formulate.getUploader(), uploadBehavior: this.uploadBehavior, preventWindowDrops: this.preventWindowDrops, hasValidationErrors: this.hasValidationErrors}, this.typeContext)) }, nameOrFallback: nameOrFallback, typeContext: typeContext, elementAttributes: elementAttributes, logicalLabelPosition: logicalLabelPosition, isVmodeled: isVmodeled, mergedErrors: mergedErrors, hasErrors: hasErrors, showFieldErrors: showFieldErrors, mergedValidationName: mergedValidationName }; /** * Given (this.type), return an object to merge with the context * @return {object} * @return {object} */ function typeContext () { var this$1 = this; switch (this.classification) { case 'select': return { options: createOptionList.call(this, this.options), optionGroups: this.optionGroups ? map(this.optionGroups, function (k, v) { return createOptionList.call(this$1, v); }) : false, placeholder: this.$attrs.placeholder || false } case 'group': if (this.options) { return { options: createOptionList.call(this, this.options) } } break default: return {} } } /** * Reducer for attributes that will be applied to each core input element. * @return {object} */ function elementAttributes () { var attrs = Object.assign({}, this.localAttributes); if (this.id) { attrs.id = this.id; } else { attrs.id = this.defaultId; } return attrs } /** * Determine the a best-guess location for the label (before or after). * @return {string} before|after */ function logicalLabelPosition () { if (this.labelPosition) { return this.labelPosition } switch (this.classification) { case 'box': return 'after' default: return 'before' } } /** * The validation label to use. */ function mergedValidationName () { if (this.validationName) { return this.validationName } if (typeof this.name === 'string') { return this.name } if (this.label) { return this.label } return this.type } /** * Determines if the field should show it's error (if it has one) * @return {boolean} */ function showFieldErrors () { if (this.showErrors || this.formShouldShowErrors) { return true } return this.behavioralErrorVisibility } /** * Return the element’s name, or select a fallback. */ function nameOrFallback () { if (this.name === true && this.classification !== 'button') { return ((this.type) + "_" + (this.elementAttributes.id)) } if (this.name === false || (this.classification === 'button' && this.name === true)) { return false } return this.name } /** * Determines if this formulate element is v-modeled or not. */ function isVmodeled () { return !!(this.$options.propsData.hasOwnProperty('formulateValue') && this._events && Array.isArray(this._events.input) && this._events.input.length) } /** * Given an object or array of options, create an array of objects with label, * value, and id. * @param {array|object} * @return {array} */ function createOptionList (options) { if (!Array.isArray(options) && options && typeof options === 'object') { var optionList = []; var that = this; for (var value in options) { optionList.push({ value: value, label: options[value], id: ((that.elementAttributes.id) + "_" + value) }); } return optionList } else if (Array.isArray(options) && !options.length) { return [{ value: this.value, label: (this.label || this.name), id: this.context.id || nanoid(9) }] } return options } /** * The merged errors computed property. */ function mergedErrors () { return arrayify(this.errors) .concat(arrayify(this.error)) .concat(arrayify(this.validationErrors)) .reduce(function (errors, err) { return !errors.includes(err) ? errors.concat(err) : errors; }, []) } /** * Does this computed property have errors. */ function hasErrors () { return !!this.mergedErrors.length } /** * Bound into the context object. */ function blurHandler () { if (this.errorBehavior === 'blur') { this.behavioralErrorVisibility = true; } } /** * Defines the model used throughout the existing context. * @param {object} context */ function defineModel (context) { return Object.defineProperty(context, 'model', { get: modelGetter.bind(this), set: modelSetter.bind(this) }) } /** * Get the value from a model. **/ function modelGetter () { var model = this.isVmodeled ? 'formulateValue' : 'internalModelProxy'; if (this.type === 'checkbox' && !Array.isArray(this[model]) && this.options) { return [] } if (!this[model]) { return '' } return this[model] } /** * Set the value from a model. **/ function modelSetter (value) { this.internalModelProxy = value; this.$emit('input', value); if (this.context.name && typeof this.formulateFormSetter === 'function') { this.formulateFormSetter(this.context.name, value); } } // var script = { name: 'FormulateInput', inheritAttrs: false, inject: { formulateFormSetter: { default: undefined }, formulateFormRegister: { default: undefined }, getFormValues: { default: function () { return function () { return ({}); }; } } }, model: { prop: 'formulateValue', event: 'input' }, props: { type: { type: String, default: 'text' }, name: { type: [String, Boolean], default: true }, /* eslint-disable */ formulateValue: { default: '' }, value: { default: false }, /* eslint-enable */ options: { type: [Object, Array, Boolean], default: false }, optionGroups: { type: [Object, Boolean], default: false }, id: { type: [String, Boolean, Number], default: false }, label: { type: [String, Boolean], default: false }, labelPosition: { type: [String, Boolean], default: false }, help: { type: [String, Boolean], default: false }, debug: { type: Boolean, default: false }, errors: { type: [String, Array, Boolean], default: false }, validation: { type: [String, Boolean, Array], default: false }, validationName: { type: [String, Boolean], default: false }, error: { type: [String, Boolean], default: false }, errorBehavior: { type: String, default: 'blur', validator: function (value) { return ['blur', 'live'].includes(value) } }, showErrors: { type: Boolean, default: false }, imageBehavior: { type: String, default: 'preview' }, uploadUrl: { type: [String, Boolean], default: false }, uploader: { type: [Function, Object, Boolean], default: false }, uploadBehavior: { type: String, default: 'live' }, preventWindowDrops: { type: Boolean, default: true } }, data: function data () { return { /** * @todo consider swapping out nanoid for this._uid */ defaultId: nanoid(9), localAttributes: {}, internalModelProxy: this.formulateValue || this.value, behavioralErrorVisibility: (this.errorBehavior === 'live'), formShouldShowErrors: false, validationErrors: [], pendingValidation: Promise.resolve() } }, computed: Object.assign({}, context, {classification: function classification () { var classification = this.$formulate.classify(this.type); return (classification === 'box' && this.options) ? 'group' : classification }, component: function component () { return (this.classification === 'group') ? 'FormulateInputGroup' : this.$formulate.component(this.type) }}), watch: { '$attrs': { handler: function handler (value) { this.updateLocalAttributes(value); }, deep: true }, internalModelProxy: function internalModelProxy (newValue, oldValue) { this.performValidation(); if (!this.isVmodeled && !shallowEqualObjects(newValue, oldValue)) { this.context.model = newValue; } }, formulateValue: function formulateValue (newValue, oldValue) { if (this.isVmodeled && !shallowEqualObjects(newValue, oldValue)) { this.context.model = newValue; } } }, created: function created () { if (this.formulateFormRegister && typeof this.formulateFormRegister === 'function') { this.formulateFormRegister(this.nameOrFallback, this); } this.updateLocalAttributes(this.$attrs); this.performValidation(); }, methods: { updateLocalAttributes: function updateLocalAttributes (value) { if (!shallowEqualObjects(value, this.localAttributes)) { this.localAttributes = value; } }, performValidation: function performValidation () { var this$1 = this; var rules = parseRules(this.validation, this.$formulate.rules()); this.pendingValidation = Promise.all( rules.map(function (ref) { var rule = ref[0]; var args = ref[1]; return rule.apply(void 0, [ { value: this$1.context.model, getFormValues: this$1.getFormValues.bind(this$1), name: this$1.context.name } ].concat( args )) .then(function (res) { return res ? false : this$1.$formulate.validationMessage(rule.name, { args: args, name: this$1.mergedValidationName, value: this$1.context.model, vm: this$1, formValues: this$1.getFormValues() }); }) }) ) .then(function (result) { return result.filter(function (result) { return result; }); }) .then(function (errorMessages) { this$1.validationErrors = errorMessages; }); return this.pendingValidation }, hasValidationErrors: function hasValidationErrors () { var this$1 = this; return new Promise(function (resolve) { this$1.$nextTick(function () { this$1.pendingValidation.then(function () { return resolve(!!this$1.validationErrors.length); }); }); }) } } }; 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. var 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; } var 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 var originalRender = options.render; options.render = function renderWithStyleInjection(h, context) { hook.call(context); return originalRender(h, context); }; } else { // inject component registration as beforeCreate hook var existing = options.beforeCreate; options.beforeCreate = existing ? [].concat(existing, hook) : [hook]; } } return script; } /* script */ var __vue_script__ = script; /* template */ var __vue_render__ = function() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c( "div", { staticClass: "formulate-input", attrs: { "data-classification": _vm.classification, "data-has-errors": _vm.hasErrors, "data-is-showing-errors": _vm.hasErrors && _vm.showFieldErrors, "data-type": _vm.type } }, [ _c( "div", { staticClass: "formulate-input-wrapper" }, [ _vm.context.hasLabel && _vm.context.labelPosition === "before" ? _vm._t( "label", [ _c("label", { staticClass: "formulate-input-label formulate-input-label--before", attrs: { for: _vm.context.attributes.id }, domProps: { textContent: _vm._s(_vm.context.label) } }) ], null, _vm.context ) : _vm._e(), _vm._v(" "), _vm._t( "element", [ _c( _vm.context.component, { tag: "component", attrs: { context: _vm.context } }, [_vm._t("default", null, null, _vm.context)], 2 ) ], null, _vm.context ), _vm._v(" "), _vm.context.hasLabel && _vm.context.labelPosition === "after" ? _vm._t( "label", [ _c("label", { staticClass: "formulate-input-label formulate-input-label--after", attrs: { for: _vm.context.attributes.id }, domProps: { textContent: _vm._s(_vm.context.label) } }) ], null, _vm.context.label ) : _vm._e() ], 2 ), _vm._v(" "), _vm.help ? _c("div", { staticClass: "formulate-input-help", domProps: { textContent: _vm._s(_vm.help) } }) : _vm._e(), _vm._v(" "), _vm.showFieldErrors ? _c("FormulateInputErrors", { attrs: { errors: _vm.mergedErrors } }) : _vm._e() ], 1 ) }; var __vue_staticRenderFns__ = []; __vue_render__._withStripped = true; /* style */ var __vue_inject_styles__ = undefined; /* scoped */ var __vue_scope_id__ = undefined; /* module identifier */ var __vue_module_identifier__ = undefined; /* functional template */ var __vue_is_functional_template__ = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__ = 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 ); var FormSubmission = function FormSubmission (form) { this.form = form; }; /** * Determine if the form has any validation errors. * * @return {Promise} resolves a boolean */ FormSubmission.prototype.hasValidationErrors = function hasValidationErrors () { return this.form.hasValidationErrors() }; /** * Asynchronously generate the values payload of this form. * @return {Promise} resolves to json */ FormSubmission.prototype.values = function values () { var this$1 = this; return new Promise(function (resolve, reject) { var pending = []; var values = cloneDeep(this$1.form.internalModelProxy); for (var key in values) { if (typeof this$1.form.internalModelProxy[key] === 'object' && this$1.form.internalModelProxy[key] instanceof FileUpload) { pending.push(this$1.form.internalModelProxy[key].upload()); } } /** * @todo - how do we get these uploaded path values back into our data? */ Promise.all(pending) // .then(file => file.path) .then(function () { return resolve(values); }) .catch(function (err) { return reject(err); }); }) }; // var script$1 = { provide: function provide () { return { formulateFormSetter: this.setFieldValue, formulateFormRegister: this.register, getFormValues: this.getFormValues } }, name: 'FormulateForm', model: { prop: 'formulateValue', event: 'input' }, props: { name: { type: [String, Boolean], default: false }, formulateValue: { type: Object, default: function () { return ({}); } } }, data: function data () { return { registry: {}, internalFormModelProxy: {}, formShouldShowErrors: false } }, computed: { hasFormulateValue: function hasFormulateValue () { return this.formulateValue && typeof this.formulateValue === 'object' }, isVmodeled: function isVmodeled () { return !!(this.$options.propsData.hasOwnProperty('formulateValue') && this._events && Array.isArray(this._events.input) && this._events.input.length) } }, watch: { formulateValue: { handler: function handler (newValue, oldValue) { if (this.isVmodeled && newValue && typeof newValue === 'object' ) { for (var field in newValue) { if (this.registry.hasOwnProperty(field) && !shallowEqualObjects(newValue[field], this.internalFormModelProxy[field]) && !shallowEqualObjects(newValue[field], this.registry[field].internalModelProxy[field]) ) { this.setFieldValue(field, newValue[field]); this.registry[field].context.model = newValue[field]; } } } }, deep: true, immediate: false } }, created: function created () { if (this.$options.propsData.hasOwnProperty('formulateValue')) { this.internalFormModelProxy = Object.assign({}, this.formulateValue); } }, methods: { setFieldValue: function setFieldValue (field, value) { var obj; Object.assign(this.internalFormModelProxy, ( obj = {}, obj[field] = value, obj )); this.$emit('input', Object.assign({}, this.internalFormModelProxy)); }, register: function register (field, component) { this.registry[field] = component; if (!component.$options.propsData.hasOwnProperty('formulateValue') && this.hasFormulateValue && this.formulateValue[field]) { // In the case that the form is carrying an initial value and the // element is not, set it directly. component.context.model = this.formulateValue[field]; } else if (component.$options.propsData.hasOwnProperty('formulateValue') && !shallowEqualObjects(component.internalModelProxy, this.formulateValue[field])) { this.setFieldValue(field, component.internalModelProxy); } }, formSubmitted: function formSubmitted () { var this$1 = this; // perform validation here this.showErrors(); var submission = new FormSubmission(this); this.$emit('submit-raw', submission); submission.hasValidationErrors() .then(function (hasErrors) { return hasErrors ? false : submission.values(); }) .then(function (json) { return this$1.$emit('submit', json); }); }, showErrors: function showErrors () { for (var fieldName in this.registry) { this.registry[fieldName].formShouldShowErrors = true; } }, getFormValues: function getFormValues () { return this.internalFormModelProxy }, hasValidationErrors: function hasValidationErrors () { var resolvers = []; for (var fieldName in this.registry) { if (typeof this.registry[fieldName].hasValidationErrors === 'function') { resolvers.push(this.registry[fieldName].hasValidationErrors()); } } return Promise.all(resolvers).then(function (fields) { return !!fields.find(function (hasErrors) { return hasErrors; }); }) } } }; /* script */ var __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( "form", { on: { submit: function($event) { $event.preventDefault(); return _vm.formSubmitted($event) } } }, [_vm._t("default")], 2 ) }; var __vue_staticRenderFns__$1 = []; __vue_render__$1._withStripped = true; /* style */ var __vue_inject_styles__$1 = undefined; /* scoped */ var __vue_scope_id__$1 = undefined; /* module identifier */ var __vue_module_identifier__$1 = undefined; /* functional template */ var __vue_is_functional_template__$1 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$1 = 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 ); // // // // // // // // // // // // // // // // var script$2 = { props: { errors: { type: [Boolean, Array], required: true } } }; /* script */ var __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 _vm.errors.length ? _c( "ul", { staticClass: "formulate-input-errors" }, _vm._l(_vm.errors, function(error) { return _c("li", { key: error, staticClass: "formulate-input-error", domProps: { innerHTML: _vm._s(error) } }) }), 0 ) : _vm._e() }; var __vue_staticRenderFns__$2 = []; __vue_render__$2._withStripped = true; /* style */ var __vue_inject_styles__$2 = undefined; /* scoped */ var __vue_scope_id__$2 = undefined; /* module identifier */ var __vue_module_identifier__$2 = undefined; /* functional template */ var __vue_is_functional_template__$2 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$2 = 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 ); // // // // // // // // // // // // // function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; } var script$3 = { name: 'FormulateInputGroup', props: { context: { type: Object, required: true } }, computed: { options: function options () { return this.context.options || [] }, optionsWithContext: function optionsWithContext () { var this$1 = this; var ref = this.context; var options = ref.options; var labelPosition = ref.labelPosition; var attributes = ref.attributes; var classification = ref.classification; var rest = objectWithoutProperties( ref, ["options", "labelPosition", "attributes", "classification"] ); var context = rest; return this.options.map(function (option) { return this$1.groupItemContext(context, option); }) } }, methods: { groupItemContext: function groupItemContext () { var args = [], len = arguments.length; while ( len-- ) args[ len ] = arguments[ len ]; return Object.assign.apply(Object, [ {} ].concat( args, [{ component: 'FormulateInput' }] )) } } }; /* script */ var __vue_script__$3 = script$3; /* template */ var __vue_render__$3 = function() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c( "div", { staticClass: "formulate-input-group" }, _vm._l(_vm.optionsWithContext, function(optionContext) { return _c( optionContext.component, _vm._b( { key: optionContext.id, tag: "component", staticClass: "formulate-input-group-item", model: { value: _vm.context.model, callback: function($$v) { _vm.$set(_vm.context, "model", $$v); }, expression: "context.model" } }, "component", optionContext, false ) ) }), 1 ) }; var __vue_staticRenderFns__$3 = []; __vue_render__$3._withStripped = true; /* style */ var __vue_inject_styles__$3 = undefined; /* scoped */ var __vue_scope_id__$3 = undefined; /* module identifier */ var __vue_module_identifier__$3 = undefined; /* functional template */ var __vue_is_functional_template__$3 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$3 = normalizeComponent( { render: __vue_render__$3, staticRenderFns: __vue_staticRenderFns__$3 }, __vue_inject_styles__$3, __vue_script__$3, __vue_scope_id__$3, __vue_is_functional_template__$3, __vue_module_identifier__$3, false, undefined, undefined, undefined ); /** * Default base for input components. */ var FormulateInputMixin = { props: { context: { type: Object, required: true } }, computed: { type: function type () { return this.context.type }, id: function id () { return this.context.id }, attributes: function attributes () { return this.context.attributes || {} }, hasValue: function hasValue () { return !!this.context.model } } }; // var script$4 = { name: 'FormulateInputBox', mixins: [FormulateInputMixin] }; /* script */ var __vue_script__$4 = script$4; /* template */ var __vue_render__$4 = function() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c( "div", { class: "formulate-input-element formulate-input-element--" + _vm.context.type, attrs: { "data-type": _vm.context.type } }, [ _vm.type === "checkbox" ? _c( "input", _vm._b( { directives: [ { name: "model", rawName: "v-model", value: _vm.context.model, expression: "context.model" } ], attrs: { type: "checkbox" }, domProps: { value: _vm.context.value, checked: Array.isArray(_vm.context.model) ? _vm._i(_vm.context.model, _vm.context.value) > -1 : _vm.context.model }, on: { blur: _vm.context.blurHandler, change: function($event) { var $$a = _vm.context.model, $$el = $event.target, $$c = $$el.checked ? true : false; if (Array.isArray($$a)) { var $$v = _vm.context.value, $$i = _vm._i($$a, $$v); if ($$el.checked) { $$i < 0 && _vm.$set(_vm.context, "model", $$a.concat([$$v])); } else { $$i > -1 && _vm.$set( _vm.context, "model", $$a.slice(0, $$i).concat($$a.slice($$i + 1)) ); } } else { _vm.$set(_vm.context, "model", $$c); } } } }, "input", _vm.attributes, false ) ) : _vm.type === "radio" ? _c( "input", _vm._b( { directives: [ { name: "model", rawName: "v-model", value: _vm.context.model, expression: "context.model" } ], attrs: { type: "radio" }, domProps: { value: _vm.context.value, checked: _vm._q(_vm.context.model, _vm.context.value) }, on: { blur: _vm.context.blurHandler, change: function($event) { return _vm.$set(_vm.context, "model", _vm.context.value) } } }, "input", _vm.attributes, false ) ) : _c( "input", _vm._b( { directives: [ { name: "model", rawName: "v-model", value: _vm.context.model, expression: "context.model" } ], attrs: { type: _vm.type }, domProps: { value: _vm.context.value, value: _vm.context.model }, on: { blur: _vm.context.blurHandler, input: function($event) { if ($event.target.composing) { return } _vm.$set(_vm.context, "model", $event.target.value); } } }, "input", _vm.attributes, false ) ), _vm._v(" "), _c("label", { staticClass: "formulate-input-element-decorator", attrs: { for: _vm.id } }) ] ) }; var __vue_staticRenderFns__$4 = []; __vue_render__$4._withStripped = true; /* style */ var __vue_inject_styles__$4 = undefined; /* scoped */ var __vue_scope_id__$4 = undefined; /* module identifier */ var __vue_module_identifier__$4 = undefined; /* functional template */ var __vue_is_functional_template__$4 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$4 = normalizeComponent( { render: __vue_render__$4, staticRenderFns: __vue_staticRenderFns__$4 }, __vue_inject_styles__$4, __vue_script__$4, __vue_scope_id__$4, __vue_is_functional_template__$4, __vue_module_identifier__$4, false, undefined, undefined, undefined ); // var script$5 = { name: 'FormulateInputText', mixins: [FormulateInputMixin] }; /* script */ var __vue_script__$5 = script$5; /* template */ var __vue_render__$5 = function() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c( "div", { class: "formulate-input-element formulate-input-element--" + _vm.context.type, attrs: { "data-type": _vm.context.type } }, [ _vm.type === "checkbox" ? _c( "input", _vm._b( { directives: [ { name: "model", rawName: "v-model", value: _vm.context.model, expression: "context.model" } ], attrs: { type: "checkbox" }, domProps: { checked: Array.isArray(_vm.context.model) ? _vm._i(_vm.context.model, null) > -1 : _vm.context.model }, on: { blur: _vm.context.blurHandler, change: function($event) { var $$a = _vm.context.model, $$el = $event.target, $$c = $$el.checked ? true : false; if (Array.isArray($$a)) { var $$v = null, $$i = _vm._i($$a, $$v); if ($$el.checked) { $$i < 0 && _vm.$set(_vm.context, "model", $$a.concat([$$v])); } else { $$i > -1 && _vm.$set( _vm.context, "model", $$a.slice(0, $$i).concat($$a.slice($$i + 1)) ); } } else { _vm.$set(_vm.context, "model", $$c); } } } }, "input", _vm.attributes, false ) ) : _vm.type === "radio" ? _c( "input", _vm._b( { directives: [ { name: "model", rawName: "v-model", value: _vm.context.model, expression: "context.model" } ], attrs: { type: "radio" }, domProps: { checked: _vm._q(_vm.context.model, null) }, on: { blur: _vm.context.blurHandler, change: function($event) { return _vm.$set(_vm.context, "model", null) } } }, "input", _vm.attributes, false ) ) : _c( "input", _vm._b( { directives: [ { name: "model", rawName: "v-model", value: _vm.context.model, expression: "context.model" } ], attrs: { type: _vm.type }, domProps: { value: _vm.context.model }, on: { blur: _vm.context.blurHandler, input: function($event) { if ($event.target.composing) { return } _vm.$set(_vm.context, "model", $event.target.value); } } }, "input", _vm.attributes, false ) ) ] ) }; var __vue_staticRenderFns__$5 = []; __vue_render__$5._withStripped = true; /* style */ var __vue_inject_styles__$5 = undefined; /* scoped */ var __vue_scope_id__$5 = undefined; /* module identifier */ var __vue_module_identifier__$5 = undefined; /* functional template */ var __vue_is_functional_template__$5 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$5 = normalizeComponent( { render: __vue_render__$5, staticRenderFns: __vue_staticRenderFns__$5 }, __vue_inject_styles__$5, __vue_script__$5, __vue_scope_id__$5, __vue_is_functional_template__$5, __vue_module_identifier__$5, false, undefined, undefined, undefined ); // var script$6 = { name: 'FormulateFiles', props: { files: { type: FileUpload, required: true }, imagePreview: { type: Boolean, default: false } }, computed: { fileUploads: function fileUploads () { return this.files.files || [] } }, watch: { files: function files () { if (this.imagePreview) { this.files.loadPreviews(); } } }, mounted: function mounted () { if (this.imagePreview) { this.files.loadPreviews(); } } }; /* script */ var __vue_script__$6 = script$6; /* template */ var __vue_render__$6 = function() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _vm.fileUploads.length ? _c( "ul", { staticClass: "formulate-files" }, _vm._l(_vm.fileUploads, function(file) { return _c( "li", { key: file.uuid, attrs: { "data-has-error": !!file.error, "data-has-preview": _vm.imagePreview && file.previewData } }, [ _c("div", { staticClass: "formulate-file" }, [ _vm.imagePreview && file.previewData ? _c("div", { staticClass: "formulate-file-image-preview" }, [ _c("img", { attrs: { src: file.previewData } }) ]) : _vm._e(), _vm._v(" "), _c("div", { staticClass: "formualte-file-name", domProps: { textContent: _vm._s(file.name) } }), _vm._v(" "), file.progress !== false ? _c( "div", { staticClass: "formulate-file-progress", attrs: { "data-just-finished": file.justFinished, "data-is-finished": !file.justFinished && file.complete } }, [ _c("div", { staticClass: "formulate-file-progress-inner", style: { width: file.progress + "%" } }) ] ) : _vm._e(), _vm._v(" "), (file.complete && !file.justFinished) || file.progress === false ? _c("div", { staticClass: "formulate-file-remove", on: { click: file.removeFile } }) : _vm._e() ]), _vm._v(" "), file.error ? _c("div", { staticClass: "formulate-file-upload-error", domProps: { textContent: _vm._s(file.error) } }) : _vm._e() ] ) }), 0 ) : _vm._e() }; var __vue_staticRenderFns__$6 = []; __vue_render__$6._withStripped = true; /* style */ var __vue_inject_styles__$6 = undefined; /* scoped */ var __vue_scope_id__$6 = undefined; /* module identifier */ var __vue_module_identifier__$6 = undefined; /* functional template */ var __vue_is_functional_template__$6 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$6 = normalizeComponent( { render: __vue_render__$6, staticRenderFns: __vue_staticRenderFns__$6 }, __vue_inject_styles__$6, __vue_script__$6, __vue_scope_id__$6, __vue_is_functional_template__$6, __vue_module_identifier__$6, false, undefined, undefined, undefined ); // var script$7 = { name: 'FormulateInputFile', components: { FormulateFiles: __vue_component__$6 }, mixins: [FormulateInputMixin], data: function data () { return { isOver: false } }, computed: { hasFiles: function hasFiles () { return !!(this.context.model instanceof FileUpload && this.context.model.files.length) } }, mounted: function mounted () { // Add a listener to the window to prevent drag/drops that miss the dropzone // from opening the file and navigating the user away from the page. if (window && this.context.preventWindowDrops) { window.addEventListener('dragover', this.preventDefault); window.addEventListener('drop', this.preventDefault); } }, destroyed: function destroyed () { if (window && this.context.preventWindowDrops) { window.removeEventListener('dragover', this.preventDefault); window.removeEventListener('drop', this.preventDefault); } }, methods: { preventDefault: function preventDefault (e) { if (e.target.tagName !== 'INPUT' && e.target.getAttribute('type') !== 'file') { e = e || event; e.preventDefault(); } }, handleFile: function handleFile () { this.isOver = false; var input = this.$refs.file; if (input.files.length) { this.context.model = this.$formulate.createUpload(input, this.context); } this.attemptImmediateUpload(); }, attemptImmediateUpload: function attemptImmediateUpload () { var this$1 = this; if (this.context.uploadBehavior === 'live' && this.context.model instanceof FileUpload) { this.context.hasValidationErrors().then(function (errors) { if (!errors) { this$1.context.model.upload(); } }); } }, handleDragOver: function handleDragOver (e) { e.preventDefault(); this.isOver = true; }, handleDragLeave: function handleDragLeave (e) { e.preventDefault(); this.isOver = false; } } }; /* script */ var __vue_script__$7 = script$7; /* template */ var __vue_render__$7 = function() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c( "div", { class: "formulate-input-element formulate-input-element--" + _vm.context.type, attrs: { "data-type": _vm.context.type, "data-has-files": _vm.hasFiles } }, [ _c( "div", { staticClass: "formulate-input-upload-area", attrs: { "data-has-files": _vm.hasFiles } }, [ _c( "input", _vm._b( { ref: "file", attrs: { "data-is-drag-hover": _vm.isOver, type: "file" }, on: { blur: _vm.context.blurHandler, change: _vm.handleFile, dragover: _vm.handleDragOver, dragleave: _vm.handleDragLeave } }, "input", _vm.attributes, false ) ), _vm._v(" "), _c("div", { directives: [ { name: "show", rawName: "v-show", value: !_vm.hasFiles, expression: "!hasFiles" } ], staticClass: "formulate-input-upload-area-mask" }), _vm._v(" "), _vm.hasFiles ? _c("FormulateFiles", { attrs: { files: _vm.context.model, "image-preview": _vm.context.type === "image" && _vm.context.imageBehavior === "preview" } }) : _vm._e() ], 1 ) ] ) }; var __vue_staticRenderFns__$7 = []; __vue_render__$7._withStripped = true; /* style */ var __vue_inject_styles__$7 = undefined; /* scoped */ var __vue_scope_id__$7 = undefined; /* module identifier */ var __vue_module_identifier__$7 = undefined; /* functional template */ var __vue_is_functional_template__$7 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$7 = normalizeComponent( { render: __vue_render__$7, staticRenderFns: __vue_staticRenderFns__$7 }, __vue_inject_styles__$7, __vue_script__$7, __vue_scope_id__$7, __vue_is_functional_template__$7, __vue_module_identifier__$7, false, undefined, undefined, undefined ); // var script$8 = { name: 'FormulateInputButton', mixins: [FormulateInputMixin] }; /* script */ var __vue_script__$8 = script$8; /* template */ var __vue_render__$8 = function() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c( "div", { class: "formulate-input-element formulate-input-element--" + _vm.context.type, attrs: { "data-type": _vm.context.type } }, [ _c( "button", _vm._b({ attrs: { type: _vm.type } }, "button", _vm.attributes, false), [ _vm._t("default", [ _c("span", { class: "formulate-input-element--" + _vm.context.type + "--label", domProps: { textContent: _vm._s( _vm.context.value || _vm.context.label || _vm.context.name || "Submit" ) } }) ]) ], 2 ) ] ) }; var __vue_staticRenderFns__$8 = []; __vue_render__$8._withStripped = true; /* style */ var __vue_inject_styles__$8 = undefined; /* scoped */ var __vue_scope_id__$8 = undefined; /* module identifier */ var __vue_module_identifier__$8 = undefined; /* functional template */ var __vue_is_functional_template__$8 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$8 = normalizeComponent( { render: __vue_render__$8, staticRenderFns: __vue_staticRenderFns__$8 }, __vue_inject_styles__$8, __vue_script__$8, __vue_scope_id__$8, __vue_is_functional_template__$8, __vue_module_identifier__$8, false, undefined, undefined, undefined ); // var script$9 = { name: 'FormulateInputSelect', mixins: [FormulateInputMixin], computed: { options: function options () { return this.context.options || {} }, optionGroups: function optionGroups () { return this.context.optionGroups || false }, placeholderSelected: function placeholderSelected () { return !!(!this.hasValue && this.context.attributes && this.context.attributes.placeholder) } } }; /* script */ var __vue_script__$9 = script$9; /* template */ var __vue_render__$9 = function() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c( "div", { class: "formulate-input-element formulate-input-element--" + _vm.context.type, attrs: { "data-type": _vm.context.type } }, [ _c( "select", _vm._b( { directives: [ { name: "model", rawName: "v-model", value: _vm.context.model, expression: "context.model" } ], attrs: { "data-placeholder-selected": _vm.placeholderSelected }, on: { blur: _vm.context.blurHandler, change: function($event) { var $$selectedVal = Array.prototype.filter .call($event.target.options, function(o) { return o.selected }) .map(function(o) { var val = "_value" in o ? o._value : o.value; return val }); _vm.$set( _vm.context, "model", $event.target.multiple ? $$selectedVal : $$selectedVal[0] ); } } }, "select", _vm.attributes, false ), [ _vm.context.placeholder ? _c( "option", { attrs: { value: "", disabled: "" }, domProps: { selected: !_vm.hasValue } }, [ _vm._v( "\n " + _vm._s(_vm.context.placeholder) + "\n " ) ] ) : _vm._e(), _vm._v(" "), !_vm.optionGroups ? _vm._l(_vm.options, function(option) { return _c( "option", _vm._b( { key: option.id, domProps: { value: option.value, textContent: _vm._s(option.label) } }, "option", option.attributes || {}, false ) ) }) : _vm._l(_vm.optionGroups, function(subOptions, label) { return _c( "optgroup", { key: label, attrs: { label: label } }, _vm._l(subOptions, function(option) { return _c( "option", _vm._b( { key: option.id, domProps: { value: option.value, textContent: _vm._s(option.label) } }, "option", option.attributes || {}, false ) ) }), 0 ) }) ], 2 ) ] ) }; var __vue_staticRenderFns__$9 = []; __vue_render__$9._withStripped = true; /* style */ var __vue_inject_styles__$9 = undefined; /* scoped */ var __vue_scope_id__$9 = undefined; /* module identifier */ var __vue_module_identifier__$9 = undefined; /* functional template */ var __vue_is_functional_template__$9 = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$9 = normalizeComponent( { render: __vue_render__$9, staticRenderFns: __vue_staticRenderFns__$9 }, __vue_inject_styles__$9, __vue_script__$9, __vue_scope_id__$9, __vue_is_functional_template__$9, __vue_module_identifier__$9, false, undefined, undefined, undefined ); // var script$a = { name: 'FormulateInputSlider', mixins: [FormulateInputMixin] }; /* script */ var __vue_script__$a = script$a; /* template */ var __vue_render__$a = function() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c( "div", { class: "formulate-input-element formulate-input-element--" + _vm.context.type, attrs: { "data-type": _vm.context.type } }, [ _vm.type === "checkbox" ? _c( "input", _vm._b( { directives: [ { name: "model", rawName: "v-model", value: _vm.context.model, expression: "context.model" } ], attrs: { type: "checkbox" }, domProps: { checked: Array.isArray(_vm.context.model) ? _vm._i(_vm.context.model, null) > -1 : _vm.context.model }, on: { blur: _vm.context.blurHandler, change: function($event) { var $$a = _vm.context.model, $$el = $event.target, $$c = $$el.checked ? true : false; if (Array.isArray($$a)) { var $$v = null, $$i = _vm._i($$a, $$v); if ($$el.checked) { $$i < 0 && _vm.$set(_vm.context, "model", $$a.concat([$$v])); } else { $$i > -1 && _vm.$set( _vm.context, "model", $$a.slice(0, $$i).concat($$a.slice($$i + 1)) ); } } else { _vm.$set(_vm.context, "model", $$c); } } } }, "input", _vm.attributes, false ) ) : _vm.type === "radio" ? _c( "input", _vm._b( { directives: [ { name: "model", rawName: "v-model", value: _vm.context.model, expression: "context.model" } ], attrs: { type: "radio" }, domProps: { checked: _vm._q(_vm.context.model, null) }, on: { blur: _vm.context.blurHandler, change: function($event) { return _vm.$set(_vm.context, "model", null) } } }, "input", _vm.attributes, false ) ) : _c( "input", _vm._b( { directives: [ { name: "model", rawName: "v-model", value: _vm.context.model, expression: "context.model" } ], attrs: { type: _vm.type }, domProps: { value: _vm.context.model }, on: { blur: _vm.context.blurHandler, input: function($event) { if ($event.target.composing) { return } _vm.$set(_vm.context, "model", $event.target.value); } } }, "input", _vm.attributes, false ) ) ] ) }; var __vue_staticRenderFns__$a = []; __vue_render__$a._withStripped = true; /* style */ var __vue_inject_styles__$a = undefined; /* scoped */ var __vue_scope_id__$a = undefined; /* module identifier */ var __vue_module_identifier__$a = undefined; /* functional template */ var __vue_is_functional_template__$a = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$a = normalizeComponent( { render: __vue_render__$a, staticRenderFns: __vue_staticRenderFns__$a }, __vue_inject_styles__$a, __vue_script__$a, __vue_scope_id__$a, __vue_is_functional_template__$a, __vue_module_identifier__$a, false, undefined, undefined, undefined ); // var script$b = { name: 'FormulateInputTextArea', mixins: [FormulateInputMixin] }; /* script */ var __vue_script__$b = script$b; /* template */ var __vue_render__$b = function() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c( "div", { staticClass: "formulate-input-element formulate-input-element--textarea", attrs: { "data-type": "textarea" } }, [ _c( "textarea", _vm._b( { directives: [ { name: "model", rawName: "v-model", value: _vm.context.model, expression: "context.model" } ], domProps: { value: _vm.context.model }, on: { blur: _vm.context.blurHandler, input: function($event) { if ($event.target.composing) { return } _vm.$set(_vm.context, "model", $event.target.value); } } }, "textarea", _vm.attributes, false ) ) ] ) }; var __vue_staticRenderFns__$b = []; __vue_render__$b._withStripped = true; /* style */ var __vue_inject_styles__$b = undefined; /* scoped */ var __vue_scope_id__$b = undefined; /* module identifier */ var __vue_module_identifier__$b = undefined; /* functional template */ var __vue_is_functional_template__$b = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ var __vue_component__$b = normalizeComponent( { render: __vue_render__$b, staticRenderFns: __vue_staticRenderFns__$b }, __vue_inject_styles__$b, __vue_script__$b, __vue_scope_id__$b, __vue_is_functional_template__$b, __vue_module_identifier__$b, false, undefined, undefined, undefined ); /** * The base formulate library. */ var Formulate = function Formulate () { this.defaults = { components: { FormulateForm: __vue_component__$1, FormulateInput: __vue_component__, FormulateInputErrors: __vue_component__$2, FormulateInputBox: __vue_component__$4, FormulateInputText: __vue_component__$5, FormulateInputFile: __vue_component__$7, FormulateInputGroup: __vue_component__$3, FormulateInputButton: __vue_component__$8, FormulateInputSelect: __vue_component__$9, FormulateInputSlider: __vue_component__$a, FormulateInputTextArea: __vue_component__$b }, library: library, rules: rules, locale: 'en', uploader: fauxUploader, uploadJustCompleteDuration: 1000, locales: { en: en } }; }; /** * Install vue formulate, and register it’s components. */ Formulate.prototype.install = function install (Vue, options) { Vue.prototype.$formulate = this; this.options = this.extend(this.defaults, options || {}); for (var componentName in this.options.components) { Vue.component(componentName, this.options.components[componentName]); } Object.freeze(this); }; /** * Create a new object by copying properties of base and extendWith. * @param {Object} base * @param {Object} extendWith */ Formulate.prototype.extend = function extend (base, extendWith) { var merged = {}; for (var key in base) { if (extendWith.hasOwnProperty(key)) { merged[key] = isPlainObject(extendWith[key]) && isPlainObject(base[key]) ? this.extend(base[key], extendWith[key]) : extendWith[key]; } else { merged[key] = base[key]; } } for (var prop in extendWith) { if (!merged.hasOwnProperty(prop)) { merged[prop] = extendWith[prop]; } } return merged }; /** * Determine what "class" of input this element is given the "type". * @param {string} type */ Formulate.prototype.classify = function classify (type) { if (this.options.library.hasOwnProperty(type)) { return this.options.library[type].classification } return 'unknown' }; /** * Determine what type of component to render given the "type". * @param {string} type */ Formulate.prototype.component = function component (type) { if (this.options.library.hasOwnProperty(type)) { return this.options.library[type].component } return false }; /** * Get validation rules. * @return {object} object of validation functions */ Formulate.prototype.rules = function rules () { return this.options.rules }; /** * Get the validation message for a particular error. */ Formulate.prototype.validationMessage = function validationMessage (rule, validationContext) { var generators = this.options.locales[this.options.locale]; if (generators.hasOwnProperty(rule)) { return generators[rule](validationContext) } else if (rule[0] === '_' && generators.hasOwnProperty(rule.substr(1))) { return generators[rule.substr(1)](validationContext) } if (generators.hasOwnProperty('default')) { return generators.default(validationContext) } return 'This field does not have a valid value' }; /** * Get the file uploader. */ Formulate.prototype.getUploader = function getUploader () { return this.options.uploader || false }; /** * Create a new instance of an upload. */ Formulate.prototype.createUpload = function createUpload (fileList, context) { return new FileUpload(fileList, context, this.options) }; var Formulate$1 = new Formulate(); exports.FileUpload = FileUpload; exports.default = Formulate$1; Object.defineProperty(exports, '__esModule', { value: true }); })));