UNPKG

@spaceavocado/svelte-form

Version:

Simple Svelte form model handler and input validations.

504 lines (422 loc) 11.2 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var tc = _interopDefault(require('@spaceavocado/type-check')); var store = require('svelte/store'); function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } /** * Svelte Form validation rules module. * @module svelte-form/rule/required */ /** * Required rule * @param {string} msg error message. * @return {boolean|string} true when valid, error message otherwise. */ var required = (function (msg) { return function (value) { if (tc.isNullOrUndefined(value) || tc.isObject(value) || tc.isFunction(value)) { return msg; } if (tc.isString(value)) { value = value.trim(); if (value.length == 0) { return msg; } } return true; }; }); /** * Svelte Form validation rules module. * @module svelte-form/rule/ignore */ var BREAK_FLAG = Symbol('Break Validation'); /** * Ignore empty rule * This rule causes to break the validation chain for empty values. * @return {boolean|string} true when valid, error message otherwise. */ var ignoreEmpty = (function () { var req = required(''); return function (value) { if (req(value) !== true) { return BREAK_FLAG; } return true; }; }); /** * Svelte Form validation rules module. * @module svelte-form/rule/email */ /** * Email rule * @param {string} msg error message. * @return {boolean|string} true when valid, error message otherwise. */ var email = (function (msg) { return function (value) { if (tc.isNullOrUndefined(value) || tc.not.isString(value)) { return msg; } var rule = /^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/; if (value.match(rule) == null) { return msg; } return true; }; }); /** * Svelte Form validation rules module. * @module svelte-form/rule/url */ /** * URL rule * @param {string} msg error message. * @return {boolean|string} true when valid, error message otherwise. */ var url = (function (msg) { return function (value) { if (tc.isNullOrUndefined(value) || tc.not.isString(value)) { return msg; } if (value.match(/^https?:\/\/[^\s]*/i) == null) { return msg; } return true; }; }); /** * Svelte Form validation rules module. * @module svelte-form/rule/equal */ /** * Equal rule. * @param {string} msg error message. * @param {mixed|function} arg a matcher object or * matcher function = fn(val) returning true|false. * @return {boolean|string} true when valid, error message otherwise. */ var equal = (function (msg, arg) { var customMatcher = tc.isFunction(arg); return function (value) { if (customMatcher === false && tc.isNullOrUndefined(value)) { return msg; } if (customMatcher) { if (arg(value) === false) { return msg; } } else if (value !== arg) { return msg; } return true; }; }); /** * Svelte Form validation rules module. * @module svelte-form/rule/min */ /** * Min rule * @param {string} msg error message. * @param {number} arg min number. * @return {boolean|string} true when valid, error message otherwise. */ var min = (function (msg, arg) { return function (value) { if (tc.isNullOrUndefined(value) || tc.not.isNumber(value) || tc.isNullOrUndefined(arg)) { return msg; } if (value < arg) { return msg; } return true; }; }); /** * Svelte Form validation rules module. * @module svelte-form/rule/max */ /** * Max rule * @param {string} msg error message. * @param {number} arg max number. * @return {boolean|string} true when valid, error message otherwise. */ var max = (function (msg, arg) { return function (value) { if (tc.isNullOrUndefined(value) || tc.not.isNumber(value) || tc.isNullOrUndefined(arg)) { return msg; } if (value > arg) { return msg; } return true; }; }); /** * Svelte Form validation rules module. * @module svelte-form/rule/between */ /** * Between numbers rule * @param {string} msg error message. * @param {number} arg1 min number. * @param {number} arg2 max number. * @return {boolean|string} true when valid, error message otherwise. */ var between = (function (msg, arg1, arg2) { return function (value) { if (min('', arg1)(value) !== true || max('', arg2)(value) !== true) { return msg; } return true; }; }); /** * Svelte Form validation rules module. * @module svelte-form/rule/rx */ /** * Custom regex rule. * @param {string} msg error message. * @param {number} arg Regular expression. * @return {boolean|string} true when valid, error message otherwise. */ var rx = (function (msg, arg) { return function (value) { if (tc.isNullOrUndefined(value) || tc.not.isString(value)) { return msg; } if (value.match(arg) == null) { return msg; } return true; }; }); /** * Svelte Form validation rules module. * @module svelte-form/rule/exclude */ /** * Max rule * @param {string} msg error message. * @param {number[]|string[]} arg exclusion list. * @return {boolean|string} true when valid, error message otherwise. */ var exclude = (function (msg, arg) { return function (value) { if (tc.isNullOrUndefined(value) || tc.not.isString(value) && tc.not.isNumber(value) || tc.isNullOrUndefined(arg)) { return msg; } if (arg.indexOf(value) > -1) { return msg; } return true; }; }); /** * Svelte Form validation rules module. * @module svelte-form/rule/include */ /** * Include rule * @param {string} msg error message. * @param {number[]|string[]} arg inclusion list. * @return {boolean|string} true when valid, error message otherwise. */ var include = (function (msg, arg) { return function (value) { if (tc.isNullOrUndefined(value) || tc.not.isString(value) && tc.not.isNumber(value) || tc.isNullOrUndefined(arg)) { return msg; } if (arg.indexOf(value) == -1) { return msg; } return true; }; }); /** * Get input validation rules * @private * @param {string} key input key. * @param {object} validation rules. * @return {function[]} validation rules. */ function validationRules(key, validation) { validation = validation || {}; if (tc.isNullOrUndefined(validation[key])) { return []; } if (tc.isArray(validation[key])) { return validation[key]; } return [validation[key]]; } /** * Validate field * @private * @param {mixed} value field value. * @param {function[]} rules filed validation rules. * @return {boolean|string} true = no error, string = error message. */ function validate(value, rules) { for (var i = 0; i < rules.length; i++) { var err = rules[i](value); if (err === BREAK_FLAG) { return true; } else if (err !== true) { return err; } } return true; } /** * Form object * @typedef Form * @property {function} subscribe Svelte store, context {valid: boolean}. * @property {function} field Get form field observable value and state. * Signature fn(key), returns {module:svelte-form~FormField}. * @property {function} validate Trigger all fields validation. * @property {function} data Get all form fields data. Signature fn(). */ /** * FormField object * @typedef FormField * @property {function} value Writeable Svelte store, context: mixed value. * @property {function} state Readonly Svelte store, * context: {valid: boolean, error: string}. */ /** * Create a new form store * @param {object} fields Form fields. * @param {object} validation Validation rules mapping. * Where each key is a fn(val)->boolean validation function or * an array of fn(val)->boolean validation functions. * @param {object} opts Form options. * @param {boolean} opts.onCreateValidation Validate form fields * when the form is created. Defaults to false. * @return {module:svelte-form~Form} */ function index (fields, validation, opts) { opts = opts || {}; opts.onCreateValidation = opts.onCreateValidation || false; var _fields = {}; var form = store.writable(Date.now()); // Field wrapper structure var field = function field(key, rules) { var firstPass = true; var value = store.writable(fields[key]); var state = store.derived([value, form], function (_ref) { var _ref2 = _slicedToArray(_ref, 1), $value = _ref2[0]; if (firstPass) { firstPass = false; if (opts.onCreateValidation === false) { return { valid: true, error: '' }; } } var res = validate($value, rules); return { valid: res === true, error: res === true ? '' : res }; }); return { value: value, state: state }; }; // Convert all inputs into field wrappers var key; for (key in fields) { if (fields.hasOwnProperty(key)) { _fields[key] = field(key, validationRules(key, validation)); } } // Overall valid state var _derived = store.derived(Object.values(_fields).map(function (f) { return f.state; }), function ($states) { return { valid: $states.every(function (s) { return s.valid === true; }) }; }), subscribe = _derived.subscribe; return { subscribe: subscribe, field: function field(key) { if (tc.isNullOrUndefined(_fields[key])) { return undefined; } return { value: _fields[key].value, state: _fields[key].state }; }, validate: function validate() { form.set(Date.now()); }, data: function data() { var data = {}; var key; for (key in _fields) { if (_fields.hasOwnProperty(key)) { data[key] = store.get(_fields[key].value); } } return data; } }; } exports.between = between; exports.default = index; exports.email = email; exports.equal = equal; exports.exclude = exclude; exports.ignoreEmpty = ignoreEmpty; exports.include = include; exports.max = max; exports.min = min; exports.required = required; exports.rx = rx; exports.url = url; exports.validate = validate; exports.validationRules = validationRules;