@shopify/react-form
Version:
Manage React forms tersely and safely-typed with no magic using React hooks
170 lines (159 loc) • 5.55 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var get = require('get-value');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var get__default = /*#__PURE__*/_interopDefaultLegacy(get);
function isField(input) {
return Boolean(input) && Object.prototype.hasOwnProperty.call(input, 'value') && Object.prototype.hasOwnProperty.call(input, 'onChange') && Object.prototype.hasOwnProperty.call(input, 'onBlur') && Object.prototype.hasOwnProperty.call(input, 'defaultValue');
}
function mapObject(input, mapper) {
return Object.keys(input).reduce((accumulator, key) => {
const value = input[key];
accumulator[key] = mapper(value, key);
return accumulator;
}, {});
}
// Eg: set({a: 1}, ['b', 'c'], 2) // => {a: 1, b: {c: 2}}
function setObject(obj, path, value) {
const [key, ...restPath] = path;
if (key == null || obj === null || typeof obj !== 'object') {
return obj;
}
if (!restPath.length) {
obj[key] = value;
return obj;
}
// creates prop if it doesn't exist
if (typeof obj[key] === 'undefined') {
// look ahead to the next key. If it is a number, this prop is an array
obj[key] = typeof restPath[0] === 'number' ? [] : {};
}
obj[key] = setObject(obj[key], restPath, value);
return obj;
}
function normalizeValidation(input) {
return Array.isArray(input) ? input : [input];
}
function isChangeEvent(value) {
return typeof value === 'object' && value !== null && Reflect.has(value, 'target') && Reflect.has(value.target, 'value');
}
function propagateErrors(fieldBag, errors) {
errors.forEach(error => {
if (error.field == null) {
return;
}
const got = get__default["default"](fieldBag, error.field);
if (got && isField(got)) {
if (got.error !== error.message) {
got.setError(error.message);
}
}
});
}
// Reduce function similar to Array.reduce() for a tree-like FieldBag
function reduceFields(fieldBag, reduceFn, initialValue, reduceEmptyFn = value => value) {
return function reduceField(accumulator, item, path) {
if (isField(item)) {
return reduceFn(accumulator, item, path, fieldBag);
}
if (Array.isArray(item) && item.length) {
return item.reduce((_accumulator, value, index) => reduceField(_accumulator, value, path.concat(index)), accumulator);
}
if (typeof item === 'object' && item !== null) {
const entries = Object.entries(item);
if (entries.length) {
return entries.reduce((_accumulator, [key, value]) => reduceField(_accumulator, value, path.concat(key)), accumulator);
}
}
// item is empty array, empty object, or primitive
return reduceEmptyFn(accumulator, item, path, fieldBag);
}(initialValue, fieldBag, []);
}
function fieldsToArray(fieldBag) {
return reduceFields(fieldBag, (fields, field) => fields.concat(field), []);
}
function validateAll(fieldBag) {
return reduceFields(fieldBag, (errors, field) => {
const message = field.runValidation();
return message ? errors.concat({
message
}) : errors;
}, []);
}
function getValues(fieldBag) {
return reduceFields(fieldBag, (formValue, field, path) => setObject(formValue, path, field.value), {}, (formValue, value, path) => setObject(formValue, path, value));
}
function getDirtyValues(fieldBag) {
const reduceFn = (acc, [fieldName, field]) => {
if (Array.isArray(field)) {
const dirtyArray = field.map(dirtyField => Object.entries(dirtyField).reduce(reduceFn, {})).filter(dirtyField => Object.keys(dirtyField).length);
return {
...acc,
...(dirtyArray.length ? {
[fieldName]: dirtyArray
} : {})
};
}
if (!isField(field)) {
const dirtyField = Object.entries(field).reduce(reduceFn, {});
return {
...acc,
...(Object.keys(dirtyField).length ? {
[fieldName]: dirtyField
} : {})
};
}
return {
...acc,
...(field.dirty ? {
[fieldName]: field.value
} : {})
};
};
return Object.entries(fieldBag).reduce(reduceFn, {});
}
function shallowArrayComparison(arrA, arrB) {
if (arrA === arrB) {
return true;
}
if (!arrA || !arrB) {
return false;
}
const len = arrA.length;
if (arrB.length !== len) {
return false;
}
for (let i = 0; i < len; i++) {
if (arrA[i] !== arrB[i]) {
return false;
}
}
return true;
}
function defaultDirtyComparator(defaultValue, newValue) {
return Array.isArray(defaultValue) ? !shallowArrayComparison(defaultValue, newValue) : defaultValue !== newValue;
}
function makeCleanFields(fieldBag) {
reduceFields(fieldBag, (_, field) => field.newDefaultValue(field.value));
}
function makeCleanDynamicLists(dynamicLists) {
if (dynamicLists) {
Object.values(dynamicLists).forEach(dynamicList => {
dynamicList.newDefaultValue(dynamicList.value);
});
}
}
exports.defaultDirtyComparator = defaultDirtyComparator;
exports.fieldsToArray = fieldsToArray;
exports.getDirtyValues = getDirtyValues;
exports.getValues = getValues;
exports.isChangeEvent = isChangeEvent;
exports.isField = isField;
exports.makeCleanDynamicLists = makeCleanDynamicLists;
exports.makeCleanFields = makeCleanFields;
exports.mapObject = mapObject;
exports.normalizeValidation = normalizeValidation;
exports.propagateErrors = propagateErrors;
exports.reduceFields = reduceFields;
exports.shallowArrayComparison = shallowArrayComparison;
exports.validateAll = validateAll;