Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

svelte-formula

Package Overview
Dependencies
Maintainers
1
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

svelte-formula - npm Package Compare versions

Comparing version 0.6.0 to 0.7.0

lib/stores.d.ts

31

CHANGELOG.md

@@ -8,2 +8,33 @@ # Changelog

## [0.7.0] 2021-02-19
### Added
- `defaultValues` option that allows default values to be set on fields - supports single and multi-value properties -
these values are only applied if there is no value already bound to the field.
```sveltehtml
<script>
import {formula} from 'svelte-formula';
const { form } = formula({
defaultValues: {
textField: 'Initial Value',
numberField: 42,
checkBox: true,
multiValue: ['option1', 'option3']
}
})
</script>
```
- Added `isFormReady` store - Formula stores are created immediately when using the `formula` method, previously they
were always empty objects filled with keys from parsing the form. This meant early binding would cause an error and
forced the use of `?.` operators in the templates. This store can now be used as `{#if $isFormReady}`, reducing the
need for the number of conditionals in templates
- `initialValues` store that contains the values at form initialisation, this is generated from merging any initial
element values merged with any potential default values
- `formReset` function that when called will reset the form to the pristine state at setup time
## [0.6.0] 2021-02-18

@@ -10,0 +41,0 @@

29

lib/extract.d.ts
import { FormEl, FormulaField } from '../types/forms';
import { FormulaOptions } from '../types/options';
import { FormulaStores } from 'svelte-formula';
/**

@@ -8,28 +9,4 @@ * Create a data handler for any type of input field

* @param options
* @param stores
*/
export declare function createFieldExtract(name: string, elementGroup: FormEl[], options: FormulaOptions): (element: HTMLInputElement) => FormulaField;
/**
* Create a data handler for checkbox fields
* @param name
* @param elementGroup
* @param options
*/
export declare function createCheckboxExtract(name: string, elementGroup: FormEl[], options: FormulaOptions): (element: HTMLInputElement) => FormulaField;
/**
* Create a data handler for radio groups
* @param name
* @param options
*/
export declare function createRadioExtract(name: string, options: FormulaOptions): (element: HTMLInputElement) => FormulaField;
/**
* Create a data handler for select fields
* @param name
* @param options
*/
export declare function createSelectExtract(name: string, options: FormulaOptions): (element: HTMLSelectElement) => FormulaField;
/**
* Create a data handler for form fields
* @param name
* @param options
*/
export declare function createFileExtract(name: string, options: FormulaOptions): (element: HTMLInputElement) => FormulaField;
export declare function createFieldExtract(name: string, elementGroup: FormEl[], options: FormulaOptions, stores: FormulaStores): (element: FormEl, isInit?: boolean, isReset?: boolean) => FormulaField;

@@ -15,2 +15,3 @@ import { FormulaOptions } from '../types/options';

destroy: () => void;
reset: () => void;
};

@@ -1,15 +0,15 @@

import { FormEl, FormulaField } from '../types/forms';
import { FormEl } from '../types/forms';
import { FormulaStores } from '../types/formula';
import { FormulaOptions } from '../types/options';
/**
* Get the initial value from the passed elements
* @param name
* @param elements
* Initialise the stores with data from the form, it will also use any default values provided
* @param allGroups
* @param stores
* @param options
*/
export declare function getInitialValue(name: string, elements: FormEl[], options: FormulaOptions): FormulaField;
export declare function initialValues(allGroups: [string, FormEl[]][], stores: FormulaStores, options: FormulaOptions): void;
export declare function getInitialFormValues(allGroups: [string, FormEl[]][], stores: FormulaStores, options: FormulaOptions): void;
/**
* Create the stores for the instance
* Create the form reset method
*/
export declare function createStores(): FormulaStores;
export declare function createReset(allGroups: [string, FormEl[]][], stores: FormulaStores, options: FormulaOptions): () => void;
{
"name": "svelte-formula",
"description": "Reactive Forms for Svelte",
"version": "0.6.0",
"version": "0.7.0",
"keywords": [

@@ -9,3 +9,5 @@ "svelte",

"forms",
"reactive"
"reactive",
"data",
"validation"
],

@@ -12,0 +14,0 @@ "license": "MIT",

@@ -1,2 +0,2 @@

import { writable } from 'svelte/store';
import { get, writable } from 'svelte/store';

@@ -255,115 +255,167 @@ /*! *****************************************************************************

/**
* Create a data handler for any type of input field
* @param name
* @param elementGroup
* @param options
* As the `HTMLCollectionOf` is not iterable, we have to loop over it with
* a for loop instead
* @private
* @internal
* @param collection
*/
function createFieldExtract(name, elementGroup, options) {
var validator = createValidationChecker(name, options);
return function (element) {
var validValue = typeof element.value !== 'number' && !element.value ? '' : element.value;
var value = elementGroup.length > 1 ? elementGroup.map(function (v) {
return v.id === element.id ? validValue : v.value;
}).filter(function (v) {
return v !== '';
}) : validValue; // Parse number values
function getMultiSelectOptionValues(collection) {
var value = [];
if (['number', 'range'].includes(element.getAttribute('type'))) {
if (Array.isArray(value)) {
value = value.length > 0 ? value.map(function (v) {
return parseFloat(v);
}) : [];
} else {
value = value !== '' ? parseFloat(value) : null;
}
for (var i = 0; i < collection.length; i++) {
if (collection[i].selected) {
value.push(collection[i].value);
}
}
return __assign({
name: name,
value: value
}, validator(element, value));
};
return value;
}
/**
* Create a data handler for checkbox fields
* @param name
* Sets the element value
* @param element
* @param value
* @param isMultiValue
* @param elementGroup
* @param options
*/
function createCheckboxExtract(name, elementGroup, options) {
var validator = createValidationChecker(name, options);
return function (element) {
var value = elementGroup.length > 1 ? elementGroup.map(function (e) {
return e.id === element.id ? element.checked && element.value || null : e.checked && e.value || null;
}).filter(function (v) {
return v !== null;
}) : element.checked;
return __assign({
name: name,
value: value
}, validator(element, value));
};
function setElementValue(element, value, isMultiValue, elementGroup) {
if (isMultiValue) {
elementGroup.forEach(function (el, i) {
if (el.type === 'checkbox') {
el.checked = value.includes(el.value);
} else {
el.value = value[i];
}
});
} else {
if (element instanceof HTMLSelectElement) {
for (var i = 0; i < element.options.length; i++) {
var el = element.options[i];
el.selected = value.includes(el.value);
}
} else if (element.type === 'radio') {
elementGroup.forEach(function (el) {
el.checked = value === el.value;
});
} else if (element.type === 'file') {
element.files = value instanceof FileList ? value : null;
console.log(value);
} else {
element.value = value;
}
}
}
/**
* Create a data handler for radio groups
* @param name
* @param options
* Get the value or values from an element
* @param element
* @param isMultiValue
* @param elementGroup
*/
function createRadioExtract(name, options) {
var validator = createValidationChecker(name, options);
return function (element) {
var value = element.checked ? element.value : '';
return __assign({
name: name,
value: value
}, validator(element, value));
};
function getElementValues(element, isMultiValue, elementGroup) {
var elValue;
if (element instanceof HTMLSelectElement) {
elValue = element.multiple ? getMultiSelectOptionValues(element.options) : element.value || null;
} else {
switch (element.type) {
case 'number':
case 'range':
{
elValue = isMultiValue ? elementGroup.map(function (v) {
return v.id === element.id ? parseFloat(element.value) : parseFloat(v.value);
}).filter(function (v) {
return !isNaN(v);
}) : function () {
var val = parseFloat(element.value);
return !isNaN(val) ? val : null;
}();
break;
}
case 'checkbox':
{
elValue = isMultiValue ? elementGroup.map(function (e) {
return e.id === element.id ? element.checked && element.value : e.checked && e.value;
}).filter(Boolean) : element.checked;
break;
}
case 'radio':
{
elValue = element.checked ? element.value : null;
break;
}
case 'file':
{
elValue = element.files;
break;
}
default:
{
elValue = isMultiValue ? elementGroup.map(function (v) {
return v.id === element.id ? element.value : v.value;
}) : element.value || null;
}
}
}
return elValue;
}
/**
* Create a data handler for select fields
* Create a data handler for any type of input field
* @param name
* @param elementGroup
* @param options
* @param stores
*/
function createSelectExtract(name, options) {
function createFieldExtract(name, elementGroup, options, stores) {
var validator = createValidationChecker(name, options);
var isMultiValue = function () {
if (elementGroup[0].type === 'radio') {
return false;
}
return !elementGroup[0].multiple;
}() && elementGroup.length > 1;
/**
* As the `HTMLCollectionOf` is not iterable, we have to loop over it with
* a for loop instead
* @private
* @internal
* @param collection
* Function called on every element update, can also be called at initial value
* Welcome to edge-case hell
*/
function getMultiValue(collection) {
var value = [];
for (var i = 0; i < collection.length; i++) {
value.push(collection[i].value);
return function (element, isInit, isReset) {
var _a, _b, _c, _d;
var value;
if (isInit && ((_a = options === null || options === void 0 ? void 0 : options.defaultValues) === null || _a === void 0 ? void 0 : _a[name])) {
value = isMultiValue ? ((_b = options === null || options === void 0 ? void 0 : options.defaultValues) === null || _b === void 0 ? void 0 : _b[name]) || [] : ((_c = options === null || options === void 0 ? void 0 : options.defaultValues) === null || _c === void 0 ? void 0 : _c[name]) || '';
} else {
var storeValue = (_d = get(stores.formValues)) === null || _d === void 0 ? void 0 : _d[name];
value = storeValue ? storeValue : isMultiValue ? [] : '';
}
return value;
}
if (!isReset) {
var elValue = getElementValues(element, isMultiValue, elementGroup);
return function (element) {
var value = element.multiple ? getMultiValue(element.selectedOptions) : element.value;
return __assign({
name: name,
value: value
}, validator(element, value));
};
}
/**
* Create a data handler for form fields
* @param name
* @param options
*/
if (isInit && (isMultiValue || element.type === 'select-multiple')) {
value = elValue.length === 0 ? value : elValue;
} else if (!isReset && elValue !== null) {
value = elValue;
}
}
function createFileExtract(name, options) {
var validator = createValidationChecker(name, options);
return function (element) {
var value = element.files;
if (isInit || isReset) {
setElementValue(element, value, isMultiValue, elementGroup);
}
return __assign({

@@ -473,25 +525,3 @@ name: name,

var extract;
if (element instanceof HTMLSelectElement) {
extract = createSelectExtract(name, options);
} else {
switch (element.type) {
case 'checkbox':
extract = createCheckboxExtract(name, groupElements, options);
break;
case 'radio':
extract = createRadioExtract(name, options);
break;
case 'file':
extract = createFileExtract(name, options);
break;
default:
extract = createFieldExtract(name, groupElements, options);
}
}
var extract = createFieldExtract(name, groupElements, options, stores);
var enrich;

@@ -523,45 +553,13 @@

var initialValues = {};
var initialValidity = {};
var initialEnrichment = {};
/**
* Get the initial value from the passed elements
* @param name
* @param elements
* Initialise the stores with data from the form, it will also use any default values provided
* @param allGroups
* @param stores
* @param options
*/
function getInitialValue(name, elements, options) {
var el = elements[0];
var handler;
if (el instanceof HTMLSelectElement) {
handler = createSelectExtract(name, options);
} else {
switch (el.type) {
case 'checkbox':
{
handler = createCheckboxExtract(name, elements, options);
break;
}
case 'file':
{
handler = createFileExtract(name, options);
break;
}
case 'radio':
{
handler = createRadioExtract(name, options);
break;
}
default:
{
handler = createFieldExtract(name, elements, options);
}
}
}
return handler(el);
}
function initialValues(allGroups, stores, options) {
function getInitialFormValues(allGroups, stores, options) {
var e_1, _a;

@@ -571,6 +569,2 @@

var finalResult = {};
var finalValidity = {};
var finalEnrichment = {};
try {

@@ -582,14 +576,15 @@ for (var allGroups_1 = __values(allGroups), allGroups_1_1 = allGroups_1.next(); !allGroups_1_1.done; allGroups_1_1 = allGroups_1.next()) {

var details = getInitialValue(key, elements, options);
finalResult[key] = details.value;
finalValidity[key] = {
invalid: details.invalid,
valid: details.valid,
message: details.message,
errors: details.errors
};
var extract = createFieldExtract(key, elements, options, stores);
var _d = extract(elements[0], true),
name_1 = _d.name,
value = _d.value,
validity = __rest(_d, ["name", "value"]);
initialValues[key] = value;
initialValidity[key] = validity;
if ((_b = options === null || options === void 0 ? void 0 : options.enrich) === null || _b === void 0 ? void 0 : _b[key]) {
var enrich = createEnrichField(key, options);
finalEnrichment[key] = enrich(details.value);
initialEnrichment[key] = enrich(value);
}

@@ -609,23 +604,61 @@ }

stores.formValues.set(finalResult);
stores.validity.set(finalValidity);
stores.isFormValid.set(Object.values(finalValidity).every(function (v) {
stores.formValues.set(initialValues);
stores.initialValues.set(initialValues);
stores.validity.set(initialValidity);
stores.isFormValid.set(Object.values(initialValidity).every(function (v) {
return v.valid;
}));
stores.enrichment.set(finalEnrichment);
stores.enrichment.set(initialEnrichment);
}
/**
* Create the stores for the instance
* Create the form reset method
*/
function createStores() {
return {
formValues: writable({}),
submitValues: writable({}),
touched: writable({}),
dirty: writable({}),
validity: writable({}),
formValidity: writable({}),
isFormValid: writable(false),
enrichment: writable({})
function createReset(allGroups, stores, options) {
/**
* Resets the form to the initial values
*/
return function () {
var e_2, _a;
stores.formValues.set(initialValues);
stores.validity.set(initialValidity);
stores.isFormValid.set(Object.values(initialValidity).every(function (v) {
return v.valid;
}));
stores.enrichment.set(initialEnrichment); // Also override touched and dirty
stores.touched.set(Object.keys(initialValues).reduce(function (val, key) {
var _a;
return __assign(__assign({}, val), (_a = {}, _a[key] = false, _a));
}, {}));
stores.dirty.set(Object.keys(initialValues).reduce(function (val, key) {
var _a;
return __assign(__assign({}, val), (_a = {}, _a[key] = false, _a));
}, {}));
try {
// Update the elements
for (var allGroups_2 = __values(allGroups), allGroups_2_1 = allGroups_2.next(); !allGroups_2_1.done; allGroups_2_1 = allGroups_2.next()) {
var _b = __read(allGroups_2_1.value, 2),
key = _b[0],
elements = _b[1];
var extract = createFieldExtract(key, elements, options, stores);
extract(elements[0], false, true);
}
} catch (e_2_1) {
e_2 = {
error: e_2_1
};
} finally {
try {
if (allGroups_2_1 && !allGroups_2_1.done && (_a = allGroups_2["return"])) _a.call(allGroups_2);
} finally {
if (e_2) throw e_2.error;
}
}
};

@@ -729,2 +762,13 @@ }

/**
* Check if two arrays match
* @param array1
* @param array2
*/
function matchingArrays(array1, array2) {
return array1.every(function (e) {
return array2.includes(e);
});
}
/**
* Creates the handler for a group of elements for the dirty event on the group name, once an

@@ -742,2 +786,3 @@ * element in the group has been changed, all element blur handlers will be removed

function createDirtyHandler(name, elements, stores) {

@@ -799,10 +844,3 @@ var e_1, _a;

if (Array.isArray(v[groupName])) {
var newVal = new Set(v[groupName]);
var existing_1 = new Set(startValue);
var same = __spread(newVal).every(function (e) {
return __spread(existing_1).includes(e);
});
if (!same) {
if (!matchingArrays(v[groupName], startValue)) {
stores.dirty.update(function (state) {

@@ -865,5 +903,5 @@ var _a;

var submitHandler = undefined;
var unsub; // eslint-disable-line
var unsub = function unsub() {}; // eslint-disable-line
var innerReset;
/**

@@ -875,3 +913,2 @@ * Internal method to do binding of te action element

function bindElements(node, innerOpt) {

@@ -885,3 +922,4 @@ var formElements = getAllFieldsWithValidity(node); // Group elements by name

initialValues(groupedMap, stores, innerOpt); // Loop over each group and setup up their initial touch and dirty handlers,
getInitialFormValues(groupedMap, stores, innerOpt);
innerReset = createReset(groupedMap, stores, innerOpt); // Loop over each group and setup up their initial touch and dirty handlers,
// also get initial values

@@ -936,2 +974,4 @@

}
stores.isFormReady.set(true);
} // Keep a instance of the passed node around

@@ -986,2 +1026,3 @@

update: function update(updatedOpts) {
stores.isFormReady.set(false);
cleanupSubscriptions();

@@ -991,2 +1032,3 @@ bindElements(currentNode, updatedOpts);

destroy: function destroy() {
stores.isFormReady.set(false);
cleanupSubscriptions();

@@ -997,2 +1039,5 @@

}
},
reset: function reset() {
return innerReset();
}

@@ -1003,2 +1048,65 @@ };

/**
* Create the stores for the the form instance, these can be set using the `defaultValue` property
* of FormulaOptions
* @param options
*
* @returns An object containing the stores for the form instance
*/
function createStores(options) {
var initialKeys = Object.keys((options === null || options === void 0 ? void 0 : options.defaultValues) || {});
var initialStates = initialKeys.reduce(function (val, key) {
var _a;
return __assign(__assign({}, val), (_a = {}, _a[key] = false, _a));
}, {});
var initialValidity = initialKeys.reduce(function (val, key) {
var _a;
return __assign(__assign({}, val), (_a = {}, _a[key] = {
valid: true,
invalid: false,
message: '',
errors: {}
}, _a));
}, {});
var initialFormValidity = Object.keys((options === null || options === void 0 ? void 0 : options.formValidators) || {}).reduce(function (val, key) {
var _a;
return __assign(__assign({}, val), (_a = {}, _a[key] = '', _a));
}, {});
var initialEnrichment = Object.entries((options === null || options === void 0 ? void 0 : options.enrich) || {}).reduce(function (value, _a) {
var _b;
var _c = __read(_a, 2),
key = _c[0],
fns = _c[1];
return __assign(__assign({}, value), (_b = {}, _b[key] = Object.entries(fns).reduce(function (v, _a) {
var _b;
var _c, _d;
var _e = __read(_a, 2),
k = _e[0],
fn = _e[1];
return __assign(__assign({}, v), (_b = {}, _b[k] = ((_c = options === null || options === void 0 ? void 0 : options.defaultValues) === null || _c === void 0 ? void 0 : _c[key]) ? fn((_d = options === null || options === void 0 ? void 0 : options.defaultValues) === null || _d === void 0 ? void 0 : _d[key]) : undefined, _b));
}, {}), _b));
}, {});
return {
formValues: writable((options === null || options === void 0 ? void 0 : options.defaultValues) || {}),
submitValues: writable({}),
initialValues: writable((options === null || options === void 0 ? void 0 : options.defaultValues) || {}),
touched: writable(initialStates),
dirty: writable(initialStates),
validity: writable(initialValidity),
formValidity: writable(initialFormValidity),
isFormValid: writable(false),
isFormReady: writable(false),
enrichment: writable(initialEnrichment)
};
}
/**
* A global map of stores for elements with an `id` property and the `use` directive,

@@ -1023,3 +1131,3 @@ * if no ID is used the store is not added

// Create a store object for this instance, if there is an `id` on the element the stores will be added to formulaStores
var stores = createStores();
var stores = createStores(options);

@@ -1029,3 +1137,4 @@ var _a = createForm(stores, options, formulaStores),

update = _a.update,
destroy = _a.destroy;
destroy = _a.destroy,
reset = _a.reset;

@@ -1035,3 +1144,4 @@ return __assign({

updateForm: update,
destroyForm: destroy
destroyForm: destroy,
resetForm: reset
}, stores);

@@ -1038,0 +1148,0 @@ }

@@ -259,115 +259,167 @@ (function (global, factory) {

/**
* Create a data handler for any type of input field
* @param name
* @param elementGroup
* @param options
* As the `HTMLCollectionOf` is not iterable, we have to loop over it with
* a for loop instead
* @private
* @internal
* @param collection
*/
function createFieldExtract(name, elementGroup, options) {
var validator = createValidationChecker(name, options);
return function (element) {
var validValue = typeof element.value !== 'number' && !element.value ? '' : element.value;
var value = elementGroup.length > 1 ? elementGroup.map(function (v) {
return v.id === element.id ? validValue : v.value;
}).filter(function (v) {
return v !== '';
}) : validValue; // Parse number values
function getMultiSelectOptionValues(collection) {
var value = [];
if (['number', 'range'].includes(element.getAttribute('type'))) {
if (Array.isArray(value)) {
value = value.length > 0 ? value.map(function (v) {
return parseFloat(v);
}) : [];
} else {
value = value !== '' ? parseFloat(value) : null;
}
for (var i = 0; i < collection.length; i++) {
if (collection[i].selected) {
value.push(collection[i].value);
}
}
return __assign({
name: name,
value: value
}, validator(element, value));
};
return value;
}
/**
* Create a data handler for checkbox fields
* @param name
* Sets the element value
* @param element
* @param value
* @param isMultiValue
* @param elementGroup
* @param options
*/
function createCheckboxExtract(name, elementGroup, options) {
var validator = createValidationChecker(name, options);
return function (element) {
var value = elementGroup.length > 1 ? elementGroup.map(function (e) {
return e.id === element.id ? element.checked && element.value || null : e.checked && e.value || null;
}).filter(function (v) {
return v !== null;
}) : element.checked;
return __assign({
name: name,
value: value
}, validator(element, value));
};
function setElementValue(element, value, isMultiValue, elementGroup) {
if (isMultiValue) {
elementGroup.forEach(function (el, i) {
if (el.type === 'checkbox') {
el.checked = value.includes(el.value);
} else {
el.value = value[i];
}
});
} else {
if (element instanceof HTMLSelectElement) {
for (var i = 0; i < element.options.length; i++) {
var el = element.options[i];
el.selected = value.includes(el.value);
}
} else if (element.type === 'radio') {
elementGroup.forEach(function (el) {
el.checked = value === el.value;
});
} else if (element.type === 'file') {
element.files = value instanceof FileList ? value : null;
console.log(value);
} else {
element.value = value;
}
}
}
/**
* Create a data handler for radio groups
* @param name
* @param options
* Get the value or values from an element
* @param element
* @param isMultiValue
* @param elementGroup
*/
function createRadioExtract(name, options) {
var validator = createValidationChecker(name, options);
return function (element) {
var value = element.checked ? element.value : '';
return __assign({
name: name,
value: value
}, validator(element, value));
};
function getElementValues(element, isMultiValue, elementGroup) {
var elValue;
if (element instanceof HTMLSelectElement) {
elValue = element.multiple ? getMultiSelectOptionValues(element.options) : element.value || null;
} else {
switch (element.type) {
case 'number':
case 'range':
{
elValue = isMultiValue ? elementGroup.map(function (v) {
return v.id === element.id ? parseFloat(element.value) : parseFloat(v.value);
}).filter(function (v) {
return !isNaN(v);
}) : function () {
var val = parseFloat(element.value);
return !isNaN(val) ? val : null;
}();
break;
}
case 'checkbox':
{
elValue = isMultiValue ? elementGroup.map(function (e) {
return e.id === element.id ? element.checked && element.value : e.checked && e.value;
}).filter(Boolean) : element.checked;
break;
}
case 'radio':
{
elValue = element.checked ? element.value : null;
break;
}
case 'file':
{
elValue = element.files;
break;
}
default:
{
elValue = isMultiValue ? elementGroup.map(function (v) {
return v.id === element.id ? element.value : v.value;
}) : element.value || null;
}
}
}
return elValue;
}
/**
* Create a data handler for select fields
* Create a data handler for any type of input field
* @param name
* @param elementGroup
* @param options
* @param stores
*/
function createSelectExtract(name, options) {
function createFieldExtract(name, elementGroup, options, stores) {
var validator = createValidationChecker(name, options);
var isMultiValue = function () {
if (elementGroup[0].type === 'radio') {
return false;
}
return !elementGroup[0].multiple;
}() && elementGroup.length > 1;
/**
* As the `HTMLCollectionOf` is not iterable, we have to loop over it with
* a for loop instead
* @private
* @internal
* @param collection
* Function called on every element update, can also be called at initial value
* Welcome to edge-case hell
*/
function getMultiValue(collection) {
var value = [];
for (var i = 0; i < collection.length; i++) {
value.push(collection[i].value);
return function (element, isInit, isReset) {
var _a, _b, _c, _d;
var value;
if (isInit && ((_a = options === null || options === void 0 ? void 0 : options.defaultValues) === null || _a === void 0 ? void 0 : _a[name])) {
value = isMultiValue ? ((_b = options === null || options === void 0 ? void 0 : options.defaultValues) === null || _b === void 0 ? void 0 : _b[name]) || [] : ((_c = options === null || options === void 0 ? void 0 : options.defaultValues) === null || _c === void 0 ? void 0 : _c[name]) || '';
} else {
var storeValue = (_d = store.get(stores.formValues)) === null || _d === void 0 ? void 0 : _d[name];
value = storeValue ? storeValue : isMultiValue ? [] : '';
}
return value;
}
if (!isReset) {
var elValue = getElementValues(element, isMultiValue, elementGroup);
return function (element) {
var value = element.multiple ? getMultiValue(element.selectedOptions) : element.value;
return __assign({
name: name,
value: value
}, validator(element, value));
};
}
/**
* Create a data handler for form fields
* @param name
* @param options
*/
if (isInit && (isMultiValue || element.type === 'select-multiple')) {
value = elValue.length === 0 ? value : elValue;
} else if (!isReset && elValue !== null) {
value = elValue;
}
}
function createFileExtract(name, options) {
var validator = createValidationChecker(name, options);
return function (element) {
var value = element.files;
if (isInit || isReset) {
setElementValue(element, value, isMultiValue, elementGroup);
}
return __assign({

@@ -477,25 +529,3 @@ name: name,

var extract;
if (element instanceof HTMLSelectElement) {
extract = createSelectExtract(name, options);
} else {
switch (element.type) {
case 'checkbox':
extract = createCheckboxExtract(name, groupElements, options);
break;
case 'radio':
extract = createRadioExtract(name, options);
break;
case 'file':
extract = createFileExtract(name, options);
break;
default:
extract = createFieldExtract(name, groupElements, options);
}
}
var extract = createFieldExtract(name, groupElements, options, stores);
var enrich;

@@ -527,45 +557,13 @@

var initialValues = {};
var initialValidity = {};
var initialEnrichment = {};
/**
* Get the initial value from the passed elements
* @param name
* @param elements
* Initialise the stores with data from the form, it will also use any default values provided
* @param allGroups
* @param stores
* @param options
*/
function getInitialValue(name, elements, options) {
var el = elements[0];
var handler;
if (el instanceof HTMLSelectElement) {
handler = createSelectExtract(name, options);
} else {
switch (el.type) {
case 'checkbox':
{
handler = createCheckboxExtract(name, elements, options);
break;
}
case 'file':
{
handler = createFileExtract(name, options);
break;
}
case 'radio':
{
handler = createRadioExtract(name, options);
break;
}
default:
{
handler = createFieldExtract(name, elements, options);
}
}
}
return handler(el);
}
function initialValues(allGroups, stores, options) {
function getInitialFormValues(allGroups, stores, options) {
var e_1, _a;

@@ -575,6 +573,2 @@

var finalResult = {};
var finalValidity = {};
var finalEnrichment = {};
try {

@@ -586,14 +580,15 @@ for (var allGroups_1 = __values(allGroups), allGroups_1_1 = allGroups_1.next(); !allGroups_1_1.done; allGroups_1_1 = allGroups_1.next()) {

var details = getInitialValue(key, elements, options);
finalResult[key] = details.value;
finalValidity[key] = {
invalid: details.invalid,
valid: details.valid,
message: details.message,
errors: details.errors
};
var extract = createFieldExtract(key, elements, options, stores);
var _d = extract(elements[0], true),
name_1 = _d.name,
value = _d.value,
validity = __rest(_d, ["name", "value"]);
initialValues[key] = value;
initialValidity[key] = validity;
if ((_b = options === null || options === void 0 ? void 0 : options.enrich) === null || _b === void 0 ? void 0 : _b[key]) {
var enrich = createEnrichField(key, options);
finalEnrichment[key] = enrich(details.value);
initialEnrichment[key] = enrich(value);
}

@@ -613,23 +608,61 @@ }

stores.formValues.set(finalResult);
stores.validity.set(finalValidity);
stores.isFormValid.set(Object.values(finalValidity).every(function (v) {
stores.formValues.set(initialValues);
stores.initialValues.set(initialValues);
stores.validity.set(initialValidity);
stores.isFormValid.set(Object.values(initialValidity).every(function (v) {
return v.valid;
}));
stores.enrichment.set(finalEnrichment);
stores.enrichment.set(initialEnrichment);
}
/**
* Create the stores for the instance
* Create the form reset method
*/
function createStores() {
return {
formValues: store.writable({}),
submitValues: store.writable({}),
touched: store.writable({}),
dirty: store.writable({}),
validity: store.writable({}),
formValidity: store.writable({}),
isFormValid: store.writable(false),
enrichment: store.writable({})
function createReset(allGroups, stores, options) {
/**
* Resets the form to the initial values
*/
return function () {
var e_2, _a;
stores.formValues.set(initialValues);
stores.validity.set(initialValidity);
stores.isFormValid.set(Object.values(initialValidity).every(function (v) {
return v.valid;
}));
stores.enrichment.set(initialEnrichment); // Also override touched and dirty
stores.touched.set(Object.keys(initialValues).reduce(function (val, key) {
var _a;
return __assign(__assign({}, val), (_a = {}, _a[key] = false, _a));
}, {}));
stores.dirty.set(Object.keys(initialValues).reduce(function (val, key) {
var _a;
return __assign(__assign({}, val), (_a = {}, _a[key] = false, _a));
}, {}));
try {
// Update the elements
for (var allGroups_2 = __values(allGroups), allGroups_2_1 = allGroups_2.next(); !allGroups_2_1.done; allGroups_2_1 = allGroups_2.next()) {
var _b = __read(allGroups_2_1.value, 2),
key = _b[0],
elements = _b[1];
var extract = createFieldExtract(key, elements, options, stores);
extract(elements[0], false, true);
}
} catch (e_2_1) {
e_2 = {
error: e_2_1
};
} finally {
try {
if (allGroups_2_1 && !allGroups_2_1.done && (_a = allGroups_2["return"])) _a.call(allGroups_2);
} finally {
if (e_2) throw e_2.error;
}
}
};

@@ -733,2 +766,13 @@ }

/**
* Check if two arrays match
* @param array1
* @param array2
*/
function matchingArrays(array1, array2) {
return array1.every(function (e) {
return array2.includes(e);
});
}
/**
* Creates the handler for a group of elements for the dirty event on the group name, once an

@@ -746,2 +790,3 @@ * element in the group has been changed, all element blur handlers will be removed

function createDirtyHandler(name, elements, stores) {

@@ -803,10 +848,3 @@ var e_1, _a;

if (Array.isArray(v[groupName])) {
var newVal = new Set(v[groupName]);
var existing_1 = new Set(startValue);
var same = __spread(newVal).every(function (e) {
return __spread(existing_1).includes(e);
});
if (!same) {
if (!matchingArrays(v[groupName], startValue)) {
stores.dirty.update(function (state) {

@@ -869,5 +907,5 @@ var _a;

var submitHandler = undefined;
var unsub; // eslint-disable-line
var unsub = function unsub() {}; // eslint-disable-line
var innerReset;
/**

@@ -879,3 +917,2 @@ * Internal method to do binding of te action element

function bindElements(node, innerOpt) {

@@ -889,3 +926,4 @@ var formElements = getAllFieldsWithValidity(node); // Group elements by name

initialValues(groupedMap, stores, innerOpt); // Loop over each group and setup up their initial touch and dirty handlers,
getInitialFormValues(groupedMap, stores, innerOpt);
innerReset = createReset(groupedMap, stores, innerOpt); // Loop over each group and setup up their initial touch and dirty handlers,
// also get initial values

@@ -940,2 +978,4 @@

}
stores.isFormReady.set(true);
} // Keep a instance of the passed node around

@@ -990,2 +1030,3 @@

update: function update(updatedOpts) {
stores.isFormReady.set(false);
cleanupSubscriptions();

@@ -995,2 +1036,3 @@ bindElements(currentNode, updatedOpts);

destroy: function destroy() {
stores.isFormReady.set(false);
cleanupSubscriptions();

@@ -1001,2 +1043,5 @@

}
},
reset: function reset() {
return innerReset();
}

@@ -1007,2 +1052,65 @@ };

/**
* Create the stores for the the form instance, these can be set using the `defaultValue` property
* of FormulaOptions
* @param options
*
* @returns An object containing the stores for the form instance
*/
function createStores(options) {
var initialKeys = Object.keys((options === null || options === void 0 ? void 0 : options.defaultValues) || {});
var initialStates = initialKeys.reduce(function (val, key) {
var _a;
return __assign(__assign({}, val), (_a = {}, _a[key] = false, _a));
}, {});
var initialValidity = initialKeys.reduce(function (val, key) {
var _a;
return __assign(__assign({}, val), (_a = {}, _a[key] = {
valid: true,
invalid: false,
message: '',
errors: {}
}, _a));
}, {});
var initialFormValidity = Object.keys((options === null || options === void 0 ? void 0 : options.formValidators) || {}).reduce(function (val, key) {
var _a;
return __assign(__assign({}, val), (_a = {}, _a[key] = '', _a));
}, {});
var initialEnrichment = Object.entries((options === null || options === void 0 ? void 0 : options.enrich) || {}).reduce(function (value, _a) {
var _b;
var _c = __read(_a, 2),
key = _c[0],
fns = _c[1];
return __assign(__assign({}, value), (_b = {}, _b[key] = Object.entries(fns).reduce(function (v, _a) {
var _b;
var _c, _d;
var _e = __read(_a, 2),
k = _e[0],
fn = _e[1];
return __assign(__assign({}, v), (_b = {}, _b[k] = ((_c = options === null || options === void 0 ? void 0 : options.defaultValues) === null || _c === void 0 ? void 0 : _c[key]) ? fn((_d = options === null || options === void 0 ? void 0 : options.defaultValues) === null || _d === void 0 ? void 0 : _d[key]) : undefined, _b));
}, {}), _b));
}, {});
return {
formValues: store.writable((options === null || options === void 0 ? void 0 : options.defaultValues) || {}),
submitValues: store.writable({}),
initialValues: store.writable((options === null || options === void 0 ? void 0 : options.defaultValues) || {}),
touched: store.writable(initialStates),
dirty: store.writable(initialStates),
validity: store.writable(initialValidity),
formValidity: store.writable(initialFormValidity),
isFormValid: store.writable(false),
isFormReady: store.writable(false),
enrichment: store.writable(initialEnrichment)
};
}
/**
* A global map of stores for elements with an `id` property and the `use` directive,

@@ -1027,3 +1135,3 @@ * if no ID is used the store is not added

// Create a store object for this instance, if there is an `id` on the element the stores will be added to formulaStores
var stores = createStores();
var stores = createStores(options);

@@ -1033,3 +1141,4 @@ var _a = createForm(stores, options, formulaStores),

update = _a.update,
destroy = _a.destroy;
destroy = _a.destroy,
reset = _a.reset;

@@ -1039,3 +1148,4 @@ return __assign({

updateForm: update,
destroyForm: destroy
destroyForm: destroy,
resetForm: reset
}, stores);

@@ -1042,0 +1152,0 @@ }

import { Writable } from 'svelte/store';
import { FormulaError, FormValues } from './forms';
import { FormulaOptions } from 'packages/svelte/formula/src/types/options';
import { FormulaOptions } from './options';
/**

@@ -17,2 +17,6 @@ * The stores available in Formula

/**
* A store containing the initial values
*/
initialValues: Writable<FormValues>;
/**
* A store containing the touched status of each named field

@@ -38,2 +42,6 @@ */

/**
* Observable value if the form state is ready to be used
*/
isFormReady: Writable<boolean>;
/**
* A store containing additional field enrichment

@@ -62,2 +70,6 @@ */

destroyForm: () => void;
/**
* Resets the form to the initial value
*/
resetForm: () => void;
}
import { CustomValidationMessages, ValidationRule, ValidationRules } from './validation';
import { EnrichFields } from './enrich';
import { FormValues } from 'svelte-formula';
/**

@@ -31,2 +32,6 @@ * Optional settings for Formula

enrich?: EnrichFields;
/**
* Default values are used as initial values for the form fields if there is no value already set on the form
*/
defaultValues?: FormValues;
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc