Comparing version 0.2.5 to 0.3.0-beta.0
@@ -1,214 +0,83 @@ | ||
import { State, Stateless, map, withDefault, distinctUntilChanged, asStateless, skipSynchronous, take, combine, just, switchMap } from 'derive-state'; | ||
import { useEffect, useState, useMemo, useRef } from 'react'; | ||
// src/internal/path.ts | ||
import { State } from "derive-state"; | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
// src/internal/subfield.ts | ||
var IS_SUBFIELD = Symbol("is subfield"); | ||
var setSubfield = (obj) => { | ||
obj[IS_SUBFIELD] = true; | ||
return obj; | ||
}; | ||
var subfield = (obj) => Array.isArray(obj) ? setSubfield([...obj]) : setSubfield({ ...obj }); | ||
var isSubfield = (obj) => IS_SUBFIELD in obj; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
// src/internal/path.ts | ||
var internal = Symbol("internal"); | ||
function createKeyFn() { | ||
return (path) => path; | ||
} | ||
var PATH_RESULT = Symbol("path"); | ||
var getProxyHandler = () => { | ||
const handler = { | ||
get: (target, prop, receiver) => { | ||
if (prop === PATH_RESULT) { | ||
return target.path; | ||
} | ||
if (typeof prop === "symbol") { | ||
throw new Error(`Can't serialize symbols to keys`); | ||
} | ||
const newPath = typeof prop === "number" || !isNaN(prop) ? `${target.path}[${prop}]` : target.path.length ? `${target.path}.${prop}` : prop; | ||
if (target.path.length === 0) | ||
return new Proxy({ | ||
path: newPath | ||
}, handler); | ||
target.path = newPath; | ||
return receiver; | ||
} | ||
return target; | ||
}; | ||
return _extends.apply(this, arguments); | ||
} | ||
function _inheritsLoose(subClass, superClass) { | ||
subClass.prototype = Object.create(superClass.prototype); | ||
subClass.prototype.constructor = subClass; | ||
subClass.__proto__ = superClass; | ||
} | ||
function _getPrototypeOf(o) { | ||
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { | ||
return o.__proto__ || Object.getPrototypeOf(o); | ||
}; | ||
return _getPrototypeOf(o); | ||
} | ||
function _setPrototypeOf(o, p) { | ||
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { | ||
o.__proto__ = p; | ||
return o; | ||
}; | ||
return _setPrototypeOf(o, p); | ||
} | ||
function _isNativeReflectConstruct() { | ||
if (typeof Reflect === "undefined" || !Reflect.construct) return false; | ||
if (Reflect.construct.sham) return false; | ||
if (typeof Proxy === "function") return true; | ||
try { | ||
Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); | ||
return true; | ||
} catch (e) { | ||
return false; | ||
return handler; | ||
}; | ||
var getKey = (keySelector) => { | ||
if (typeof keySelector === "string") | ||
return keySelector; | ||
const proxy = new Proxy({ path: "" }, getProxyHandler()); | ||
const result = keySelector(proxy); | ||
if (!(PATH_RESULT in result)) { | ||
throw new Error(`You must return a value from the argument in the selector function`); | ||
} | ||
} | ||
function _construct(Parent, args, Class) { | ||
if (_isNativeReflectConstruct()) { | ||
_construct = Reflect.construct; | ||
} else { | ||
_construct = function _construct(Parent, args, Class) { | ||
var a = [null]; | ||
a.push.apply(a, args); | ||
var Constructor = Function.bind.apply(Parent, a); | ||
var instance = new Constructor(); | ||
if (Class) _setPrototypeOf(instance, Class.prototype); | ||
return instance; | ||
}; | ||
return result[PATH_RESULT]; | ||
}; | ||
var getKeys = (keysSelector) => { | ||
if (Array.isArray(keysSelector) && keysSelector.length === 1 && typeof keysSelector[0] === "function") { | ||
keysSelector = keysSelector[0]; | ||
} | ||
return _construct.apply(null, arguments); | ||
} | ||
function _isNativeFunction(fn) { | ||
return Function.toString.call(fn).indexOf("[native code]") !== -1; | ||
} | ||
function _wrapNativeSuper(Class) { | ||
var _cache = typeof Map === "function" ? new Map() : undefined; | ||
_wrapNativeSuper = function _wrapNativeSuper(Class) { | ||
if (Class === null || !_isNativeFunction(Class)) return Class; | ||
if (typeof Class !== "function") { | ||
throw new TypeError("Super expression must either be null or a function"); | ||
} | ||
if (typeof _cache !== "undefined") { | ||
if (_cache.has(Class)) return _cache.get(Class); | ||
_cache.set(Class, Wrapper); | ||
} | ||
function Wrapper() { | ||
return _construct(Class, arguments, _getPrototypeOf(this).constructor); | ||
} | ||
Wrapper.prototype = Object.create(Class.prototype, { | ||
constructor: { | ||
value: Wrapper, | ||
enumerable: false, | ||
writable: true, | ||
configurable: true | ||
} | ||
}); | ||
return _setPrototypeOf(Wrapper, Class); | ||
}; | ||
return _wrapNativeSuper(Class); | ||
} | ||
function _objectWithoutPropertiesLoose(source, excluded) { | ||
if (source == null) return {}; | ||
var target = {}; | ||
var sourceKeys = Object.keys(source); | ||
var key, i; | ||
for (i = 0; i < sourceKeys.length; i++) { | ||
key = sourceKeys[i]; | ||
if (excluded.indexOf(key) >= 0) continue; | ||
target[key] = source[key]; | ||
if (typeof keysSelector === "object") | ||
return keysSelector; | ||
const proxy = new Proxy({ path: "" }, getProxyHandler()); | ||
const result = keysSelector(proxy); | ||
if (result.some((r) => !(PATH_RESULT in r))) { | ||
throw new Error(`You must return a value from the argument in the selector function`); | ||
} | ||
return target; | ||
} | ||
function _assertThisInitialized(self) { | ||
if (self === void 0) { | ||
throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); | ||
} | ||
return self; | ||
} | ||
var IS_SUBFIELD = /*#__PURE__*/Symbol('is subfield'); | ||
var setSubfield = function setSubfield(obj) { | ||
obj[IS_SUBFIELD] = true; | ||
return obj; | ||
return result.map((r) => r[PATH_RESULT]); | ||
}; | ||
var subfield = function subfield(obj) { | ||
return Array.isArray(obj) ? setSubfield([].concat(obj)) : setSubfield(_extends({}, obj)); | ||
}; | ||
var isSubfield = function isSubfield(obj) { | ||
return IS_SUBFIELD in obj; | ||
}; | ||
var path = /*#__PURE__*/Symbol('path'); | ||
var getKey = function getKey(keySelector) { | ||
if (typeof keySelector === 'string') return keySelector; | ||
var proxy = new Proxy({ | ||
path: '' | ||
}, getProxyHandler(false)); | ||
var result = keySelector(proxy); | ||
if (result !== proxy) { | ||
throw new Error("You must return a value from the argument in the selector function"); | ||
var getMapValue = (key, map6) => { | ||
if (!map6.has(key)) { | ||
map6.set(key, new State()); | ||
} | ||
return result[path]; | ||
return map6.get(key); | ||
}; | ||
var getMapValue = function getMapValue(keySelector, map) { | ||
var key = getKey(keySelector); | ||
if (!map.has(key)) { | ||
map.set(key, new State()); | ||
} | ||
return map.get(key); | ||
}; | ||
var getKeys = function getKeys(keysSelector) { | ||
if (typeof keysSelector === 'object') return keysSelector; | ||
var proxy = new Proxy({ | ||
path: '' | ||
}, getProxyHandler(true)); | ||
var result = keysSelector(proxy); // if (result.some(r => !(r instanceof Proxy))) { | ||
// throw new Error( | ||
// `You must return a value from the argument in the selector function` | ||
// ); | ||
// } | ||
return result.map(function (r) { | ||
return r[path]; | ||
}); | ||
}; | ||
var getKeyValues = function getKeyValues(input) { | ||
var result = {}; | ||
var getKeyValues = (input) => { | ||
const result = {}; | ||
if (!input) { | ||
return result; | ||
} | ||
if (typeof input !== 'object') { | ||
throw new Error('Model must be an object'); | ||
if (typeof input !== "object") { | ||
throw new Error("Model must be an object"); | ||
} | ||
var prefix = Array.isArray(input) ? function (k) { | ||
return "[" + k + "]"; | ||
} : function (k) { | ||
return k; | ||
}; | ||
Object.entries(input).forEach(function (_ref) { | ||
var key = _ref[0], | ||
value = _ref[1]; | ||
var prefixValue = prefix(key); | ||
const prefix = Array.isArray(input) ? (k) => `[${k}]` : (k) => k; | ||
Object.entries(input).forEach(([key, value]) => { | ||
const prefixValue = prefix(key); | ||
if ((isPlainObject(value) || Array.isArray(value)) && isSubfield(value)) { | ||
var inner = getKeyValues(value); | ||
Object.entries(inner).forEach(function (_ref2) { | ||
var innerKey = _ref2[0], | ||
innerValue = _ref2[1]; | ||
var chain = innerKey.startsWith('[') ? '' : '.'; | ||
const inner = getKeyValues(value); | ||
Object.entries(inner).forEach(([innerKey, innerValue]) => { | ||
const chain = innerKey.startsWith("[") ? "" : "."; | ||
result[prefixValue + chain + innerKey] = innerValue; | ||
@@ -222,390 +91,271 @@ }); | ||
}; | ||
var buildObject = function buildObject(propValues) { | ||
var ret = {}; | ||
for (var key in propValues) { | ||
var buildObject = (propValues) => { | ||
const ret = {}; | ||
for (const key in propValues) { | ||
setProp(ret, key, propValues[key]); | ||
} | ||
return ret; | ||
}; | ||
var setProp = function setProp(obj, key, value) { | ||
if (key.startsWith('[')) { | ||
var end = key.indexOf(']'); | ||
var num = Number(key.substring(1, end)); | ||
var remaining = key.substring(end + 1); | ||
var setProp = (obj, key, value) => { | ||
if (key.startsWith("[")) { | ||
const end = key.indexOf("]"); | ||
const num = Number(key.substring(1, end)); | ||
const remaining = key.substring(end + 1); | ||
if (remaining.length) { | ||
if (remaining.startsWith('.')) { | ||
if (remaining.startsWith(".")) { | ||
obj[num] = obj[num] || {}; | ||
return setProp(obj[num], remaining.slice(1), value); | ||
} | ||
obj[num] = obj[num] || []; | ||
return setProp(obj[num], remaining, value); | ||
} | ||
obj[num] = value; | ||
return; | ||
} | ||
var propType = getPropType(key); | ||
const propType = getPropType(key); | ||
switch (propType) { | ||
case 'array': | ||
{ | ||
var firstBracket = key.indexOf('['); | ||
var prop = key.substring(0, firstBracket); | ||
var _remaining = key.substring(firstBracket); | ||
obj[prop] = obj[prop] || []; | ||
return setProp(obj[prop], _remaining, value); | ||
} | ||
case 'object': | ||
{ | ||
var firstDot = key.indexOf('.'); | ||
var _prop = key.substring(0, firstDot); | ||
var _remaining2 = key.substring(firstDot + 1); | ||
obj[_prop] = obj[_prop] || {}; | ||
return setProp(obj[_prop], _remaining2, value); | ||
} | ||
case 'terminal': | ||
{ | ||
obj[key] = value; | ||
return; | ||
} | ||
case "array": { | ||
const firstBracket = key.indexOf("["); | ||
const prop = key.substring(0, firstBracket); | ||
const remaining = key.substring(firstBracket); | ||
obj[prop] = obj[prop] || []; | ||
return setProp(obj[prop], remaining, value); | ||
} | ||
case "object": { | ||
const firstDot = key.indexOf("."); | ||
const prop = key.substring(0, firstDot); | ||
const remaining = key.substring(firstDot + 1); | ||
obj[prop] = obj[prop] || {}; | ||
return setProp(obj[prop], remaining, value); | ||
} | ||
case "terminal": { | ||
obj[key] = value; | ||
return; | ||
} | ||
} | ||
}; | ||
var getPropType = function getPropType(key) { | ||
var firstDot = key.indexOf('.'); | ||
var firstBracket = key.indexOf('['); | ||
var getPropType = (key) => { | ||
const firstDot = key.indexOf("."); | ||
const firstBracket = key.indexOf("["); | ||
if (firstDot < 0 && firstBracket < 0) { | ||
return 'terminal'; | ||
return "terminal"; | ||
} | ||
if (firstDot < 0) { | ||
return 'array'; | ||
return "array"; | ||
} | ||
if (firstBracket < 0) { | ||
return 'object'; | ||
return "object"; | ||
} | ||
if (firstDot < firstBracket) { | ||
return 'object'; | ||
return "object"; | ||
} | ||
return 'array'; | ||
return "array"; | ||
}; | ||
var isPlainObject = (value) => value !== null && typeof value === "object" && value.__proto__ === Object.prototype; | ||
var getProxyHandler = function getProxyHandler(preserveRoot) { | ||
var handler = { | ||
get: function get(target, prop, receiver) { | ||
if (prop === path) { | ||
return target.path; | ||
} | ||
if (typeof prop === 'symbol') { | ||
throw new Error("Can't serialize symbols to keys"); | ||
} | ||
var newPath = typeof prop === 'number' || !isNaN(prop) ? target.path + "[" + prop + "]" : target.path.length ? target.path + "." + prop : prop; | ||
if (preserveRoot && target.path.length === 0) return new Proxy({ | ||
path: newPath | ||
}, handler); | ||
target.path = newPath; | ||
return receiver; | ||
} | ||
}; | ||
return handler; | ||
}; | ||
var isPlainObject = function isPlainObject(value) { | ||
return value !== null && typeof value === 'object' && value.__proto__ === Object.prototype; | ||
}; | ||
// src/commands/getFieldChanges.ts | ||
function getFieldChanges(formRef) { | ||
var keys = formRef.registeredKeys.getValue(); | ||
return Array.from(keys).map(function (key) { | ||
var initialValue$ = getMapValue(key, formRef.initialValues); | ||
var value$ = getMapValue(key, formRef.values); | ||
const keys = formRef.registeredKeys.getValue(); | ||
return Array.from(keys).map((key) => { | ||
const initialValue$ = getMapValue(key, formRef.initialValues); | ||
const value$ = getMapValue(key, formRef.values); | ||
if (!initialValue$.hasValue() || !value$.hasValue()) { | ||
return null; | ||
} | ||
var initial = initialValue$.getValue(); | ||
var value = value$.getValue(); | ||
return { | ||
key: key, | ||
initial: initial, | ||
value: value | ||
}; | ||
}).filter(function (change) { | ||
return change && change.initial !== change.value; | ||
}); | ||
const initial = initialValue$.getValue(); | ||
const value = value$.getValue(); | ||
return { key, initial, value }; | ||
}).filter((change) => change && change.initial !== change.value); | ||
} | ||
var readField = function readField(formRef, key) { | ||
// src/commands/getFieldValue.ts | ||
function getFieldValue(formRef, key) { | ||
try { | ||
return getMapValue(key, formRef.values).getValue(); | ||
return getMapValue(getKey(key), formRef.values).getValue(); | ||
} catch (ex) { | ||
return undefined; | ||
return void 0; | ||
} | ||
}; | ||
} | ||
var readForm = function readForm(formRef) { | ||
return buildObject(Object.fromEntries(Array.from(formRef.values.entries()).map(function (_ref) { | ||
var key = _ref[0], | ||
value = _ref[1]; | ||
return [key, value.hasValue() ? value.getValue() : undefined]; | ||
}))); | ||
// src/commands/getFormValue.ts | ||
var getFormValue = (formRef) => buildObject(Object.fromEntries(Array.from(formRef.values.entries()).map(([key, value]) => [ | ||
key, | ||
value.hasValue() ? value.getValue() : void 0 | ||
]))); | ||
// src/internal/formRef.ts | ||
import { | ||
asStateless, | ||
combine, | ||
distinctUntilChanged, | ||
map, | ||
skipSynchronous, | ||
State as State2, | ||
Stateless, | ||
take, | ||
withDefault | ||
} from "derive-state"; | ||
// src/validators.ts | ||
var validatorMessages = { | ||
isNumber: () => "Expected a number", | ||
isInteger: () => "Expected an integer", | ||
isRequired: () => "Required", | ||
isAtLeast: (threshold) => "Expected a value of at least " + threshold, | ||
isGreaterThan: (threshold) => "Expected a value greater than " + threshold, | ||
isAtMost: (threshold) => "Expected a value of at most " + threshold, | ||
isLessThan: (threshold) => "Expected a value less than " + threshold, | ||
matches: (regex) => "Invalid Value" | ||
}; | ||
var isNumber = function isNumber(value) { | ||
var setValidatorMessages = (messages) => { | ||
Object.entries(messages).forEach(([key, value]) => validatorMessages[key] = value); | ||
}; | ||
var isNumber = (message) => (value) => { | ||
if (isNil(value)) | ||
return true; | ||
if (isNaN(value)) { | ||
return ['Expected a number']; | ||
return [message != null ? message : validatorMessages.isNumber()]; | ||
} | ||
return true; | ||
}; | ||
var isInteger = function isInteger(value) { | ||
var isInteger = (message) => (value) => { | ||
if (isNil(value)) | ||
return true; | ||
if (parseInt(value) !== parseFloat(value)) { | ||
return ['Expected an integer']; | ||
return [message != null ? message : validatorMessages.isInteger()]; | ||
} | ||
return true; | ||
}; | ||
var isRequired = function isRequired(value) { | ||
return value != null && value !== '' ? true : ['required']; | ||
var isRequired = (message) => (value) => isNil(value) || value === "" ? [message != null ? message : validatorMessages.isRequired()] : true; | ||
var parseNumericParam = (value, getValue) => typeof value === "function" ? value(getValue) : typeof value === "string" ? Number(getValue(value)) : value; | ||
var isAtLeast = (threshold, message) => (value, getValue) => { | ||
if (isNil(value)) | ||
return true; | ||
const thresholdValue = parseNumericParam(threshold, getValue); | ||
if (Number(value) < thresholdValue) { | ||
return [message != null ? message : validatorMessages.isAtLeast(thresholdValue)]; | ||
} | ||
return true; | ||
}; | ||
var parseNumericParam = function parseNumericParam(value, getValue) { | ||
return typeof value === 'function' ? value(getValue) : typeof value === 'string' ? Number(getValue(value)) : value; | ||
var isGreaterThan = (threshold, message) => (value, getValue) => { | ||
if (isNil(value)) | ||
return true; | ||
const thresholdValue = parseNumericParam(threshold, getValue); | ||
if (Number(value) <= thresholdValue) { | ||
return [message != null ? message : validatorMessages.isGreaterThan(thresholdValue)]; | ||
} | ||
return true; | ||
}; | ||
var isAtLeast = function isAtLeast(threshold) { | ||
return function (value, getValue) { | ||
var thresholdValue = parseNumericParam(threshold, getValue); | ||
if (Number(value) < thresholdValue) { | ||
return ['Expected a value of at least ' + thresholdValue]; | ||
} | ||
var isAtMost = (threshold, message) => (value, getValue) => { | ||
if (isNil(value)) | ||
return true; | ||
}; | ||
const thresholdValue = parseNumericParam(threshold, getValue); | ||
if (Number(value) > thresholdValue) { | ||
return [message != null ? message : validatorMessages.isAtMost(thresholdValue)]; | ||
} | ||
return true; | ||
}; | ||
var isGreaterThan = function isGreaterThan(threshold) { | ||
return function (value, getValue) { | ||
var thresholdValue = parseNumericParam(threshold, getValue); | ||
if (Number(value) <= thresholdValue) { | ||
return ['Expected a value greater than ' + thresholdValue]; | ||
} | ||
var isLessThan = (threshold, message) => (value, getValue) => { | ||
if (isNil(value)) | ||
return true; | ||
}; | ||
const thresholdValue = parseNumericParam(threshold, getValue); | ||
if (Number(value) >= thresholdValue) { | ||
return [message != null ? message : validatorMessages.isLessThan(thresholdValue)]; | ||
} | ||
return true; | ||
}; | ||
var isAtMost = function isAtMost(threshold) { | ||
return function (value, getValue) { | ||
var thresholdValue = parseNumericParam(threshold, getValue); | ||
if (Number(value) > thresholdValue) { | ||
return ['Expected a value of at most ' + thresholdValue]; | ||
} | ||
var matches = (regex, message) => (value) => { | ||
if (isNil(value)) | ||
return true; | ||
}; | ||
if (regex.test(value)) { | ||
return true; | ||
} | ||
return [message != null ? message : validatorMessages.matches(regex)]; | ||
}; | ||
var isLessThan = function isLessThan(threshold) { | ||
return function (value, getValue) { | ||
var thresholdValue = parseNumericParam(threshold, getValue); | ||
if (Number(value) >= thresholdValue) { | ||
return ['Expected a value less than ' + thresholdValue]; | ||
} | ||
var recPipeValidators = (validators, i) => (...args) => { | ||
if (i >= validators.length) { | ||
return true; | ||
}; | ||
}; | ||
var matches = function matches(regex, message) { | ||
return function (value) { | ||
if (regex.test(value)) { | ||
return true; | ||
} | ||
const syncResult = validators[i](...args); | ||
const processResult = (result) => { | ||
if (result !== true) { | ||
return result; | ||
} | ||
return [message != null ? message : 'Invalid value']; | ||
return recPipeValidators(validators, i + 1)(...args); | ||
}; | ||
if (validationResultIsAsync(syncResult)) { | ||
return syncResult.then(processResult); | ||
} | ||
return processResult(syncResult); | ||
}; | ||
var recPipeValidators = function recPipeValidators(validators, i) { | ||
return function () { | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
if (i >= validators.length) { | ||
return true; | ||
} | ||
var syncResult = validators[i].apply(validators, args); | ||
var processResult = function processResult(result) { | ||
if (result !== true) { | ||
return result; | ||
} | ||
return recPipeValidators(validators, i + 1).apply(void 0, args); | ||
}; | ||
if (validationResultIsAsync(syncResult)) { | ||
return syncResult.then(processResult); | ||
} | ||
return processResult(syncResult); | ||
var pipeValidators = (...validators) => recPipeValidators(validators, 0); | ||
var mergeValidators = (...validators) => (...args) => { | ||
const syncResults = validators.map((validate) => validate(...args)); | ||
const processResult = (results) => { | ||
const flattenedResults = results.flatMap((result) => result === true ? [] : result); | ||
return flattenedResults; | ||
}; | ||
}; | ||
var pipeValidators = function pipeValidators() { | ||
for (var _len2 = arguments.length, validators = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
validators[_key2] = arguments[_key2]; | ||
if (syncResults.some(validationResultIsAsync)) { | ||
return Promise.all(syncResults).then(processResult); | ||
} | ||
return recPipeValidators(validators, 0); | ||
return processResult(syncResults); | ||
}; | ||
var mergeValidators = function mergeValidators() { | ||
for (var _len3 = arguments.length, validators = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { | ||
validators[_key3] = arguments[_key3]; | ||
} | ||
return function () { | ||
for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { | ||
args[_key4] = arguments[_key4]; | ||
} | ||
var syncResults = validators.map(function (validate) { | ||
return validate.apply(void 0, args); | ||
}); | ||
var processResult = function processResult(results) { | ||
var flattenedResults = results.flatMap(function (result) { | ||
return typeof result === 'boolean' ? [] : result; | ||
}); | ||
if (flattenedResults.length === 0) { | ||
return !results.some(function (result) { | ||
return result === false; | ||
}); | ||
} | ||
return flattenedResults; | ||
}; | ||
if (syncResults.some(validationResultIsAsync)) { | ||
return Promise.all(syncResults).then(processResult); | ||
} | ||
return processResult(syncResults); | ||
}; | ||
}; | ||
function conditionalValidator(condition, validator) { | ||
return function (value, getValue) { | ||
return (value, getValue) => { | ||
if (condition(value, getValue)) { | ||
return validator(value, getValue); | ||
} | ||
return true; | ||
}; | ||
} | ||
var noopValidator = function noopValidator() { | ||
return true; | ||
}; | ||
var noopValidator = () => true; | ||
var validationResultIsAsync = (result) => typeof result === "object" && !Array.isArray(result); | ||
var isNil = (v) => v == null; | ||
var validationResultIsAsync = function validationResultIsAsync(result) { | ||
return typeof result === 'object' && !Array.isArray(result); | ||
}; | ||
var createFormRef = function createFormRef(options) { | ||
if (options === void 0) { | ||
options = {}; | ||
} | ||
var initialValues = new Map(); | ||
Object.entries(getKeyValues(options.initialValue || {})).forEach(function (_ref) { | ||
var key = _ref[0], | ||
value = _ref[1]; | ||
initialValues.set(key, new State(value)); | ||
// src/internal/formRef.ts | ||
var createFormRef = (options = {}) => { | ||
const initialValues = new Map(); | ||
Object.entries(getKeyValues(options.initialValue || {})).forEach(([key, value]) => { | ||
initialValues.set(key, new State2(value)); | ||
}); | ||
var values = new Map(Array.from(initialValues.entries()).map(function (_ref2) { | ||
var key = _ref2[0], | ||
subject = _ref2[1]; | ||
return [key, new State(subject.getValue())]; | ||
})); | ||
var registeredKeys = new State(new Set(values.keys())); | ||
/** | ||
* Same structure as TValues, but every value is a ControlState | ||
*/ | ||
var controlStates = new Map(); | ||
var getControlValue$ = function getControlValue$(key) { | ||
return getMapValue(key, values); | ||
}; | ||
var registerControl = function registerControl(_ref3) { | ||
var initialValue = _ref3.initialValue, | ||
keySelector = _ref3.key, | ||
_ref3$validator = _ref3.validator, | ||
validator = _ref3$validator === void 0 ? noopValidator : _ref3$validator; | ||
var key = getKey(keySelector); | ||
var value$ = getControlValue$(key); | ||
var control$ = getMapValue(key, controlStates); | ||
const values = new Map(Array.from(initialValues.entries()).map(([key, subject]) => [key, new State2(subject.getValue())])); | ||
const registeredKeys = new State2(new Set(values.keys())); | ||
const controlStates = new Map(); | ||
const getControlValue$ = (key) => getMapValue(key, values); | ||
const registerControl = ({ | ||
initialValue, | ||
key, | ||
validator = noopValidator | ||
}) => { | ||
const value$ = getControlValue$(key); | ||
const control$ = getMapValue(key, controlStates); | ||
if (!control$.hasValue()) { | ||
var keys = registeredKeys.getValue(); | ||
const keys = registeredKeys.getValue(); | ||
keys.add(key); | ||
registeredKeys.setValue(keys); | ||
var manualError = new Stateless(); | ||
const manualError = new Stateless(); | ||
control$.setValue({ | ||
touched: false, | ||
validator: validator, | ||
manualError: manualError, | ||
validator, | ||
manualError, | ||
error$: createError$({ | ||
key: key, | ||
validator$: control$.pipe(map(function (control) { | ||
return control.validator; | ||
}), withDefault(validator), distinctUntilChanged()), | ||
value$: value$, | ||
key, | ||
validator$: control$.pipe(map((control) => control.validator), withDefault(validator), distinctUntilChanged()), | ||
value$, | ||
manualError$: manualError, | ||
getControlValue$: getControlValue$ | ||
getControlValue$ | ||
}).capture() | ||
}); | ||
} // Update validator | ||
} | ||
if (validator !== control$.getValue().validator) { | ||
control$.setValue(_extends({}, control$.getValue(), { | ||
validator: validator | ||
})); | ||
} // Update initial value | ||
var initialValue$ = getMapValue(key, initialValues); | ||
control$.setValue({ | ||
...control$.getValue(), | ||
validator | ||
}); | ||
} | ||
const initialValue$ = getMapValue(key, initialValues); | ||
if (!initialValue$.hasValue()) { | ||
initialValue$.setValue(initialValue); | ||
} // If it doesn't have value, set it to initial value | ||
var valueSource$ = getMapValue(key, values); | ||
} | ||
const valueSource$ = getMapValue(key, values); | ||
if (!valueSource$.hasValue()) { | ||
@@ -615,21 +365,15 @@ valueSource$.setValue(initialValue$.getValue()); | ||
}; | ||
return { | ||
registeredKeys: registeredKeys, | ||
registerControl: registerControl, | ||
initialValues: initialValues, | ||
controlStates: controlStates, | ||
values: values, | ||
dispose: function dispose() { | ||
Array.from(initialValues.values()).forEach(function (state) { | ||
return state.close(); | ||
}); | ||
Array.from(values.values()).forEach(function (state) { | ||
return state.close(); | ||
}); | ||
Array.from(controlStates.values()).forEach(function (state) { | ||
registeredKeys, | ||
registerControl, | ||
initialValues, | ||
controlStates, | ||
values, | ||
dispose: () => { | ||
Array.from(initialValues.values()).forEach((state) => state.close()); | ||
Array.from(values.values()).forEach((state) => state.close()); | ||
Array.from(controlStates.values()).forEach((state) => { | ||
if (state.hasValue()) { | ||
state.getValue().error$.close(); | ||
} | ||
state.close(); | ||
@@ -644,37 +388,27 @@ }); | ||
}; | ||
var getControlState = function getControlState(formRef, key) { | ||
return getMapValue(key, formRef.controlStates); | ||
}; | ||
var createError$ = function createError$(params) { | ||
var key = params.key, | ||
validator$ = params.validator$, | ||
value$ = params.value$, | ||
getControlValue$ = params.getControlValue$; | ||
var validationError$ = new Stateless(function (obs) { | ||
var dependenciesObserved = new Set(); | ||
var latestValidator = EMPTY; | ||
validator$.subscribe(function (v) { | ||
return latestValidator = v; | ||
}); | ||
var latestValue = EMPTY; | ||
value$.subscribe(function (v) { | ||
function isFormRef(value) { | ||
return !!(typeof value === "object" && value && "registeredKeys" in value && "registerControl" in value); | ||
} | ||
var getControlState = (formRef, key) => getMapValue(key, formRef.controlStates); | ||
var createError$ = (params) => { | ||
const { key, validator$, value$, getControlValue$ } = params; | ||
const validationError$ = new Stateless((obs) => { | ||
const dependenciesObserved = new Set(); | ||
let latestValidator = EMPTY; | ||
validator$.subscribe((v) => latestValidator = v); | ||
let latestValue = EMPTY; | ||
value$.subscribe((v) => { | ||
latestValue = v; | ||
runValidator(); | ||
}); | ||
function runValidator() { | ||
if (latestValidator === EMPTY) { | ||
throw new Error('No validator defined'); // TODO shouldn't ever happen | ||
throw new Error("No validator defined"); | ||
} | ||
if (latestValue === EMPTY) { | ||
throw new Error('No validator defined'); // TODO shouldn't ever happen | ||
throw new Error("No validator defined"); | ||
} | ||
try { | ||
var result = latestValidator(latestValue, function (keySelector) { | ||
var key = getKey(keySelector); | ||
var targetControlValue$ = getControlValue$(key); | ||
const result = latestValidator(latestValue, (key2) => { | ||
const targetControlValue$ = getControlValue$(key2); | ||
if (!dependenciesObserved.has(targetControlValue$)) { | ||
@@ -684,48 +418,34 @@ dependenciesObserved.add(targetControlValue$); | ||
} | ||
if (!targetControlValue$.hasValue()) { | ||
throw new ValueNotThereYetError(key); | ||
throw new ValueNotThereYetError(key2); | ||
} | ||
return targetControlValue$.getValue(); | ||
}); | ||
if (typeof result === 'boolean') { | ||
if (typeof result === "boolean") { | ||
return obs.next(result === true ? false : []); | ||
} | ||
if (Array.isArray(result)) { | ||
return obs.next(result); | ||
} | ||
obs.next('pending'); | ||
result.then(function (result) { | ||
return obs.next(result === true ? false : result === false ? [] : result); | ||
}); | ||
obs.next("pending"); | ||
result.then((result2) => obs.next(result2 === true ? false : result2)); | ||
} catch (ex) { | ||
if (ex instanceof ValueNotThereYetError) { | ||
console.warn("Setting control " + key + " error to pending, as the validation depends on a field that hasn't been registered yet", ex); | ||
console.warn(`Setting control ${key} error to pending, as the validation depends on a field that hasn't been registered yet`, ex); | ||
} else { | ||
console.error(ex); // TODO how to propagate into an error boundary? :| | ||
console.error(ex); | ||
} | ||
return obs.next('pending'); | ||
return obs.next("pending"); | ||
} | ||
} | ||
}); | ||
var manualError$ = new Stateless(function (obs) { | ||
const manualError$ = new Stateless((obs) => { | ||
obs.next(false); | ||
var innerUnsub = function innerUnsub() { | ||
return void 0; | ||
}; | ||
var outerUnsub = params.manualError$.subscribe(function (error) { | ||
let innerUnsub = () => void 0; | ||
const outerUnsub = params.manualError$.subscribe((error) => { | ||
obs.next(error); | ||
innerUnsub(); | ||
innerUnsub = value$.pipe(skipSynchronous(), take(1), map(function () { | ||
return false; | ||
})).subscribe(obs.next); | ||
innerUnsub = value$.pipe(skipSynchronous(), take(1), map(() => false)).subscribe(obs.next); | ||
}); | ||
return function () { | ||
return () => { | ||
innerUnsub(); | ||
@@ -735,49 +455,39 @@ outerUnsub(); | ||
}); | ||
var errors = combine({ | ||
const errors = combine({ | ||
validatorResult: validationError$, | ||
manualResult: manualError$ | ||
}); | ||
return errors.pipe(map(function (_ref4) { | ||
var validatorResult = _ref4.validatorResult, | ||
manualResult = _ref4.manualResult; | ||
if (manualResult === false || manualResult === 'pending') return validatorResult; | ||
if (validatorResult === false || validatorResult === 'pending') return manualResult; | ||
return [].concat(manualResult, validatorResult); | ||
return errors.pipe(map(({ validatorResult, manualResult }) => { | ||
if (manualResult === false || manualResult === "pending") | ||
return validatorResult; | ||
if (validatorResult === false || validatorResult === "pending") | ||
return manualResult; | ||
return [...manualResult, ...validatorResult]; | ||
})); | ||
}; | ||
var ValueNotThereYetError = /*#__PURE__*/function (_Error) { | ||
_inheritsLoose(ValueNotThereYetError, _Error); | ||
function ValueNotThereYetError(key) { | ||
var _this; | ||
_this = _Error.call(this, "Control " + key + " doesn't have any value yet") || this; | ||
_this.name = 'ValueNotThereYetError'; | ||
Object.setPrototypeOf(_assertThisInitialized(_this), ValueNotThereYetError.prototype); | ||
return _this; | ||
var ValueNotThereYetError = class extends Error { | ||
constructor(key) { | ||
super(`Control ${key} doesn't have any value yet`); | ||
this.name = "ValueNotThereYetError"; | ||
Object.setPrototypeOf(this, ValueNotThereYetError.prototype); | ||
} | ||
}; | ||
var EMPTY = Symbol("empty"); | ||
return ValueNotThereYetError; | ||
}( /*#__PURE__*/_wrapNativeSuper(Error)); | ||
var EMPTY = /*#__PURE__*/Symbol('empty'); | ||
var resetForm = function resetForm(formRef, keysSelector) { | ||
var values = formRef.values, | ||
initialValues = formRef.initialValues; | ||
var keys = keysSelector ? getKeys(keysSelector) : Array.from(values.keys()); | ||
keys.forEach(function (key) { | ||
// src/commands/resetForm.ts | ||
var resetForm = (formRef, keys) => { | ||
const { values, initialValues } = formRef; | ||
const allKeys = keys != null ? keys : Array.from(values.keys()); | ||
allKeys.forEach((key) => { | ||
if (!values.has(key) || !initialValues.has(key)) { | ||
return; | ||
} | ||
values.get(key).setValue(initialValues.get(key).getValue()); | ||
var control = getControlState(formRef, key); | ||
var controlValue = control.getValue(); | ||
const control = getControlState(formRef, key); | ||
const controlValue = control.getValue(); | ||
if (controlValue.touched) { | ||
control.setValue(_extends({}, controlValue, { | ||
control.setValue({ | ||
...controlValue, | ||
touched: false | ||
})); | ||
}); | ||
} | ||
@@ -787,38 +497,31 @@ }); | ||
var setFieldValue = function setFieldValue(formRef, keySelector, value) { | ||
getMapValue(keySelector, formRef.values).setValue(value); | ||
// src/commands/setFieldValue.ts | ||
var setFieldValue = (formRef, key, value) => { | ||
getMapValue(key, formRef.values).setValue(value); | ||
}; | ||
var setFormValue = function setFormValue(formRef, value) { | ||
Object.entries(getKeyValues(value)).forEach(function (_ref) { | ||
var key = _ref[0], | ||
value = _ref[1]; | ||
getMapValue(key, formRef.values).setValue(value); | ||
var setFormValue = (formRef, value) => { | ||
Object.entries(getKeyValues(value)).forEach(([key, value2]) => { | ||
getMapValue(key, formRef.values).setValue(value2); | ||
}); | ||
}; | ||
var setInitialValue = function setInitialValue(formRef, keySelector, value) { | ||
return getMapValue(keySelector, formRef.initialValues).setValue(value); | ||
}; | ||
var setFormInitialValue = function setFormInitialValue(formRef, value) { | ||
Object.entries(getKeyValues(value)).forEach(function (_ref) { | ||
var key = _ref[0], | ||
value = _ref[1]; | ||
getMapValue(key, formRef.initialValues).setValue(value); | ||
// src/commands/setInitialValue.ts | ||
var setInitialValue = (formRef, key, value) => getMapValue(key, formRef.initialValues).setValue(value); | ||
var setFormInitialValue = (formRef, value) => { | ||
Object.entries(getKeyValues(value)).forEach(([key, value2]) => { | ||
getMapValue(key, formRef.initialValues).setValue(value2); | ||
}); | ||
}; | ||
var touchFields = function touchFields(formRef, keysSelector, touch) { | ||
if (touch === void 0) { | ||
touch = true; | ||
} | ||
var keys = keysSelector ? getKeys(keysSelector) : formRef.registeredKeys.getValue(); | ||
keys.forEach(function (key) { | ||
var control$ = getControlState(formRef, key); | ||
var controlValue = control$.getValue(); | ||
// src/commands/touchFields.ts | ||
var touchFields = (formRef, keys, touch = true) => { | ||
const allKeys = keys != null ? keys : formRef.registeredKeys.getValue(); | ||
allKeys.forEach((key) => { | ||
const control$ = getControlState(formRef, key); | ||
const controlValue = control$.getValue(); | ||
if (controlValue.touched !== touch) { | ||
control$.setValue(_extends({}, controlValue, { | ||
control$.setValue({ | ||
...controlValue, | ||
touched: touch | ||
})); | ||
}); | ||
} | ||
@@ -828,5 +531,6 @@ }); | ||
var setFieldError = function setFieldError(formRef, keySelector, error) { | ||
// src/commands/setFieldError.ts | ||
var setFieldError = (formRef, key, error) => { | ||
try { | ||
getControlState(formRef, keySelector).getValue().manualError.emit(error); | ||
getControlState(formRef, key).getValue().manualError.emit(error); | ||
} catch (ex) { | ||
@@ -837,105 +541,154 @@ console.warn("Can't set error: Field not registered", ex); | ||
var useControlSubscription = function useControlSubscription(formRef, options) { | ||
var key = getKey(options.key); | ||
useEffect(function () { | ||
formRef.registerControl(options); | ||
// src/hooks/useControl.ts | ||
import { useEffect as useEffect2, useState } from "react"; | ||
// src/context.ts | ||
import { createContext, useContext } from "react"; | ||
var FormicaryContext = createContext(null); | ||
var useFormRef = () => { | ||
const formRef = useContext(FormicaryContext); | ||
if (!formRef) { | ||
throw new Error("Form Provider not found in component tree"); | ||
} | ||
return formRef; | ||
}; | ||
// src/internal/useHookParams.ts | ||
function useHookParams(args) { | ||
if (isFormRef(args[0])) { | ||
return args; | ||
} | ||
return [useFormRef(), ...args]; | ||
} | ||
// src/hooks/useControlStateless.ts | ||
import { useEffect } from "react"; | ||
function useControlStateless(...args) { | ||
const [formRef, options] = useHookParams(args); | ||
const key = getKey(options.key); | ||
useEffect(() => { | ||
var _a; | ||
formRef.registerControl({ | ||
key, | ||
initialValue: (_a = options.initialValue) != null ? _a : void 0, | ||
validator: options.validator | ||
}); | ||
}, [formRef, options]); | ||
return { | ||
getValue: function getValue() { | ||
var state = getMapValue(key, formRef.values); | ||
getValue: () => { | ||
const state = getMapValue(key, formRef.values); | ||
return state.hasValue() ? state.getValue() : options.initialValue; | ||
}, | ||
setValue: function setValue(value) { | ||
return getMapValue(key, formRef.values).setValue(value); | ||
}, | ||
subscribe: function subscribe(cb) { | ||
return getMapValue(key, formRef.values).subscribe(cb); | ||
}, | ||
touch: function touch() { | ||
var state$ = getControlState(formRef, key); | ||
state$.value.then(function (value) { | ||
if (value.touched || state$.closed) return; | ||
state$.setValue(_extends({}, value, { | ||
setValue: (value) => getMapValue(key, formRef.values).setValue(value), | ||
subscribe: (cb) => getMapValue(key, formRef.values).subscribe(cb), | ||
touch: () => { | ||
const state$ = getControlState(formRef, key); | ||
state$.value.then((value) => { | ||
if (value.touched || state$.closed) | ||
return; | ||
state$.setValue({ | ||
...value, | ||
touched: true | ||
})); | ||
}, function () {}); | ||
}); | ||
}, () => { | ||
}); | ||
} | ||
}; | ||
}; | ||
} | ||
var useControl = function useControl(formRef, options) { | ||
var _useControlSubscripti = useControlSubscription(formRef, options), | ||
subscribe = _useControlSubscripti.subscribe, | ||
control = _objectWithoutPropertiesLoose(_useControlSubscripti, ["subscribe"]); | ||
var _useState = useState(control.getValue), | ||
state = _useState[0], | ||
setState = _useState[1]; | ||
useEffect(function () { | ||
return subscribe(setState); | ||
}, []); | ||
return _extends({}, control, { | ||
// src/hooks/useControl.ts | ||
function useControl(...args) { | ||
const [formRef, options] = useHookParams(args); | ||
const { subscribe, ...control } = useControlStateless(formRef, options); | ||
const [state, setState] = useState(control.getValue); | ||
useEffect2(() => subscribe(setState), []); | ||
return { | ||
...control, | ||
value: state | ||
}); | ||
}; | ||
}; | ||
} | ||
var ALL_KEYS = {}; | ||
var useErrors = function useErrors(formRef, keysSelector) { | ||
var keys = keysSelector ? getKeys(keysSelector) : [ALL_KEYS]; | ||
var error$ = useMemo(function () { | ||
var keys$ = keys[0] === ALL_KEYS ? formRef.registeredKeys.pipe(map(function (set) { | ||
return Array.from(set); | ||
})) : just(keys); | ||
return keys$.pipe(switchMap(function (keys) { | ||
return combine(Object.fromEntries(keys.map(function (key) { | ||
return [key, getControlState(formRef, key).pipe(map(function (v) { | ||
return v.touched ? v.error$ : FALSE; | ||
}), withDefault(FALSE), distinctUntilChanged(), switchMap(function (v) { | ||
return v; | ||
}))]; | ||
}))); | ||
}), map(function (results) { | ||
return Object.fromEntries(Object.entries(results).filter(function (_ref) { | ||
var value = _ref[1]; | ||
return value !== false; | ||
})); | ||
})).capture(); | ||
}, [formRef].concat(keys)); | ||
var _useState = useState(function () { | ||
// src/hooks/useErrors.ts | ||
import { | ||
combine as combine2, | ||
distinctUntilChanged as distinctUntilChanged2, | ||
just, | ||
map as map2, | ||
switchMap, | ||
withDefault as withDefault2 | ||
} from "derive-state"; | ||
import { useEffect as useEffect3, useMemo, useState as useState2 } from "react"; | ||
function useErrors(...args) { | ||
const [formRef, ...keys] = useHookParams(args); | ||
const error$ = useMemo(() => { | ||
const keys$ = keys.length === 0 ? formRef.registeredKeys.pipe(map2((set) => Array.from(set))) : just(getKeys(keys)); | ||
return keys$.pipe(switchMap((keys2) => combine2(Object.fromEntries(keys2.map((key) => [ | ||
key, | ||
getControlState(formRef, key).pipe(map2((v) => v.touched ? v.error$ : FALSE), withDefault2(FALSE), distinctUntilChanged2(), switchMap((v) => v)) | ||
])))), map2((results) => Object.fromEntries(Object.entries(results).filter(([, value]) => value !== false)))).capture(); | ||
}, [formRef, ...keys]); | ||
const [errors, setErrors] = useState2(() => { | ||
if (error$.hasValue()) { | ||
return error$.getValue(); | ||
} | ||
return {}; | ||
}); | ||
useEffect3(() => { | ||
error$.subscribe((x) => setErrors(() => x)); | ||
return () => error$.close(); | ||
}, [error$]); | ||
return errors; | ||
} | ||
var FALSE = just(false); | ||
return {}; // TODO does this ever happen? - It did: that's why I need to pass in a default value above | ||
}), | ||
errors = _useState[0], | ||
setErrors = _useState[1]; | ||
// src/hooks/useFieldChanges.ts | ||
import { useEffect as useEffect4 } from "react"; | ||
useEffect(function () { | ||
error$.subscribe(function (x) { | ||
return setErrors(function () { | ||
return x; | ||
}); | ||
// src/internal/useLatestRef.ts | ||
import { useRef } from "react"; | ||
function useLatestRef(value) { | ||
const ref = useRef(value); | ||
ref.current = value; | ||
return ref; | ||
} | ||
// src/hooks/useFieldChanges.ts | ||
function useFieldChanges(...args) { | ||
const [formRef, keySelector, onChange] = useHookParams(args); | ||
const onChangeRef = useLatestRef(onChange); | ||
const value$ = getMapValue(getKey(keySelector), formRef.values); | ||
useEffect4(() => { | ||
let isInitial = true; | ||
return value$.subscribe((value) => { | ||
onChangeRef.current(value, isInitial); | ||
isInitial = false; | ||
}); | ||
return function () { | ||
return error$.close(); | ||
}; | ||
}, [error$]); | ||
return errors; | ||
}; | ||
var FALSE = /*#__PURE__*/just(false); | ||
}, [value$]); | ||
} | ||
var useForm = function useForm(options) { | ||
var ref = useRef(null); | ||
// src/hooks/useFieldValue.ts | ||
import { useEffect as useEffect5, useState as useState3 } from "react"; | ||
function useFieldValue(...args) { | ||
const [formRef, key] = useHookParams(args); | ||
const value$ = getMapValue(getKey(key), formRef.values); | ||
const [value, setValue] = useState3(() => { | ||
if (value$.hasValue()) { | ||
return value$.getValue(); | ||
} | ||
return void 0; | ||
}); | ||
useEffect5(() => value$.subscribe(setValue), [value$]); | ||
return value; | ||
} | ||
// src/hooks/useForm.ts | ||
import { useEffect as useEffect6, useRef as useRef2 } from "react"; | ||
var useForm = (options) => { | ||
const ref = useRef2(null); | ||
if (!ref.current) { | ||
ref.current = createFormRef(options); | ||
} | ||
useEffect(function () { | ||
return function () { | ||
return ref.current.dispose(); | ||
}; | ||
useEffect6(() => () => { | ||
var _a; | ||
return (_a = ref.current) == null ? void 0 : _a.dispose(); | ||
}, []); | ||
@@ -945,68 +698,43 @@ return ref.current; | ||
var useFormChanges = function useFormChanges(formRef, mapFn, eqFn) { | ||
var valueStream = useMemo(function () { | ||
return formRef.registeredKeys.pipe(map(function (set) { | ||
return Array.from(set); | ||
}), switchMap(function (keys) { | ||
return combine(Object.fromEntries(keys.map(function (key) { | ||
return [key, formRef.values.get(key).pipe(withDefault(undefined), distinctUntilChanged())]; | ||
}))); | ||
}), map(function (formValues) { | ||
return mapFn(buildObject(formValues)); | ||
}), distinctUntilChanged(eqFn)).capture(); | ||
}, [formRef]); | ||
var _useState = useState(function () { | ||
return valueStream.hasValue() ? valueStream.getValue() : {}; | ||
}), | ||
state = _useState[0], | ||
setState = _useState[1]; | ||
useEffect(function () { | ||
// src/hooks/useFormValue.ts | ||
import { | ||
combine as combine3, | ||
distinctUntilChanged as distinctUntilChanged3, | ||
map as map3, | ||
switchMap as switchMap2, | ||
withDefault as withDefault3 | ||
} from "derive-state"; | ||
import { useEffect as useEffect7, useMemo as useMemo2, useState as useState4 } from "react"; | ||
function useFormValue(...args) { | ||
const [formRef, mapFn, eqFn] = useHookParams(args); | ||
const valueStream = useMemo2(() => formRef.registeredKeys.pipe(map3((set) => Array.from(set)), switchMap2((keys) => combine3(Object.fromEntries(keys.map((key) => [ | ||
key, | ||
formRef.values.get(key).pipe(withDefault3(void 0), distinctUntilChanged3()) | ||
])))), map3((formValues) => mapFn(buildObject(formValues))), distinctUntilChanged3(eqFn)).capture(), [formRef]); | ||
const [state, setState] = useState4(() => valueStream.hasValue() ? valueStream.getValue() : {}); | ||
useEffect7(() => { | ||
valueStream.subscribe(setState); | ||
return function () { | ||
return valueStream.close(); | ||
}; | ||
return () => valueStream.close(); | ||
}, [valueStream]); | ||
return state; | ||
}; | ||
} | ||
var useInput = function useInput(formRef, options) { | ||
if (options === void 0) { | ||
options = {}; | ||
} | ||
var _options = options, | ||
_options$eventType = _options.eventType, | ||
eventType = _options$eventType === void 0 ? 'input' : _options$eventType, | ||
_options$elementProp = _options.elementProp, | ||
elementProp = _options$elementProp === void 0 ? 'value' : _options$elementProp; | ||
var ref = useRef(null); | ||
useEffect(function () { | ||
var element = ref.current; | ||
// src/hooks/useInput.ts | ||
import { useEffect as useEffect8, useRef as useRef3 } from "react"; | ||
function useInput(...args) { | ||
var _a; | ||
const [formRef, keySelector, options = {}] = useHookParams(args); | ||
const { eventType = "input", elementProp = "value" } = options; | ||
const ref = useRef3(null); | ||
const control = useControlStateless(formRef, { | ||
key: keySelector, | ||
initialValue: (_a = options.initialValue) != null ? _a : "", | ||
validator: options.validator | ||
}); | ||
useEffect8(() => { | ||
const element = ref.current; | ||
if (!element) { | ||
return; | ||
} | ||
var _options2 = options, | ||
_options2$initialValu = _options2.initialValue, | ||
initialValue = _options2$initialValu === void 0 ? '' : _options2$initialValu, | ||
validator = _options2.validator; | ||
var key = options.key ? getKey(options.key) : element.name; | ||
if (!key) { | ||
console.error("An input is missing its key. Either supply it through useInput `key` option or through the input's name", element, { | ||
options: options | ||
}); | ||
return; | ||
} | ||
formRef.registerControl({ | ||
initialValue: initialValue, | ||
key: key, | ||
validator: validator | ||
}); | ||
var value$ = getMapValue(key, formRef.values); | ||
var valueUnsub = value$.subscribe(function (value) { | ||
const valueUnsub = control.subscribe((value) => { | ||
if (element[elementProp] !== value) { | ||
@@ -1016,64 +744,39 @@ element[elementProp] = value; | ||
}); | ||
var blurListener = function blurListener() { | ||
var control$ = getControlState(formRef, key); | ||
if (control$.getValue().touched) return; | ||
control$.setValue(_extends({}, control$.getValue(), { | ||
touched: true | ||
})); | ||
const blurListener = () => { | ||
control.touch(); | ||
}; | ||
element.addEventListener('blur', blurListener); | ||
var valueListener = function valueListener(event) { | ||
return value$.setValue(event.target[elementProp]); | ||
}; | ||
element.addEventListener("blur", blurListener); | ||
const valueListener = (event) => control.setValue(event.target[elementProp]); | ||
element.addEventListener(eventType, valueListener); | ||
return function () { | ||
return () => { | ||
valueUnsub(); | ||
element.removeEventListener('blur', blurListener); | ||
element.removeEventListener("blur", blurListener); | ||
element.removeEventListener(eventType, valueListener); | ||
}; | ||
}); | ||
}, [ref.current]); | ||
return ref; | ||
}; | ||
} | ||
// src/hooks/useIsPristine.ts | ||
import { useEffect as useEffect9, useMemo as useMemo3, useState as useState5 } from "react"; | ||
import { combine as combine4, distinctUntilChanged as distinctUntilChanged4, map as map4, switchMap as switchMap3 } from "derive-state"; | ||
function useIsPristine(formRef) { | ||
var isPristine$ = useMemo(function () { | ||
return formRef.registeredKeys.pipe(switchMap(function (keys) { | ||
return combine(Array.from(keys).map(function (key) { | ||
var initialValue$ = getMapValue(key, formRef.initialValues); | ||
var value$ = getMapValue(key, formRef.values); | ||
return combine({ | ||
initialValue: initialValue$, | ||
value: value$ | ||
}).pipe(map(function (_ref) { | ||
var initialValue = _ref.initialValue, | ||
value = _ref.value; | ||
return initialValue === value; | ||
})); | ||
})).pipe(map(function (results) { | ||
return results.every(function (pristine) { | ||
return pristine; | ||
}); | ||
})); | ||
}), distinctUntilChanged()).capture(); | ||
}, [formRef]); | ||
var _useState = useState(function () { | ||
const [_formRef] = useHookParams([formRef]); | ||
const isPristine$ = useMemo3(() => _formRef.registeredKeys.pipe(switchMap3((keys) => combine4(Array.from(keys).map((key) => { | ||
const initialValue$ = getMapValue(key, _formRef.initialValues); | ||
const value$ = getMapValue(key, _formRef.values); | ||
return combine4({ | ||
initialValue: initialValue$, | ||
value: value$ | ||
}).pipe(map4(({ initialValue, value }) => initialValue === value)); | ||
})).pipe(map4((results) => results.every((pristine) => pristine)))), distinctUntilChanged4()).capture(), [_formRef]); | ||
const [isPristine, setIsPristine] = useState5(() => { | ||
if (isPristine$.hasValue()) { | ||
return isPristine$.getValue(); | ||
} | ||
return true; | ||
}), | ||
isPristine = _useState[0], | ||
setIsPristine = _useState[1]; | ||
useEffect(function () { | ||
}); | ||
useEffect9(() => { | ||
isPristine$.subscribe(setIsPristine); | ||
return function () { | ||
return isPristine$.close(); | ||
}; | ||
return () => isPristine$.close(); | ||
}, [isPristine$]); | ||
@@ -1083,81 +786,76 @@ return isPristine; | ||
var ALL_KEYS$1 = {}; | ||
var useIsValid = function useIsValid(formRef, defaultValue, keysSelector) { | ||
if (defaultValue === void 0) { | ||
defaultValue = false; | ||
} | ||
var keys = keysSelector ? getKeys(keysSelector) : [ALL_KEYS$1]; | ||
var error$ = useMemo(function () { | ||
var keys$ = keys[0] === ALL_KEYS$1 ? formRef.registeredKeys.pipe(map(function (set) { | ||
return Array.from(set); | ||
})) : just(keys); | ||
return keys$.pipe(switchMap(function (keys) { | ||
return combine(Object.fromEntries(keys.map(function (key) { | ||
return [key, getControlState(formRef, key).pipe(take(1), switchMap(function (v) { | ||
return v.error$; | ||
}), withDefault(false))]; | ||
}))); | ||
}), map(function (results) { | ||
return Object.fromEntries(Object.entries(results).filter(function (_ref) { | ||
var value = _ref[1]; | ||
return value !== false; | ||
})); | ||
})); | ||
}, [formRef].concat(keys)); | ||
var isValid$ = useMemo(function () { | ||
return error$.pipe(map(function (errors) { | ||
var errorValues = Object.values(errors); | ||
var hasPending = false; | ||
var hasError = errorValues.some(function (error) { | ||
if (error === 'pending') { | ||
hasPending = true; | ||
return false; | ||
} | ||
return true; | ||
}); | ||
return hasError ? false : hasPending ? 'pending' : true; | ||
})).capture(); | ||
}, [error$]); | ||
var _useState = useState(function () { | ||
// src/hooks/useIsValid.ts | ||
import { combine as combine5, just as just2, map as map5, switchMap as switchMap4, take as take2, withDefault as withDefault4 } from "derive-state"; | ||
import { useEffect as useEffect10, useMemo as useMemo4, useState as useState6 } from "react"; | ||
function useIsValid(...args) { | ||
const [formRef, defaultValue = false, ...keys] = useHookParams(args); | ||
const error$ = useMemo4(() => { | ||
const keys$ = keys.length === 0 ? formRef.registeredKeys.pipe(map5((set) => Array.from(set))) : just2(getKeys(keys)); | ||
return keys$.pipe(switchMap4((keys2) => combine5(Object.fromEntries(keys2.map((key) => [ | ||
key, | ||
getControlState(formRef, key).pipe(take2(1), switchMap4((v) => v.error$), withDefault4(false)) | ||
])))), map5((results) => Object.fromEntries(Object.entries(results).filter(([, value]) => value !== false)))); | ||
}, [formRef, ...keys]); | ||
const isValid$ = useMemo4(() => error$.pipe(map5((errors) => { | ||
const errorValues = Object.values(errors); | ||
let hasPending = false; | ||
const hasError = errorValues.some((error) => { | ||
if (error === "pending") { | ||
hasPending = true; | ||
return false; | ||
} | ||
return true; | ||
}); | ||
return hasError ? false : hasPending ? "pending" : true; | ||
})).capture(), [error$]); | ||
const [isValid, setIsValid] = useState6(() => { | ||
if (isValid$.hasValue()) { | ||
return isValid$.getValue(); | ||
} | ||
return defaultValue; // TODO does it ever happen? - It did: that's why I need to pass in a default value above | ||
}), | ||
isValid = _useState[0], | ||
setIsValid = _useState[1]; | ||
useEffect(function () { | ||
return defaultValue; | ||
}); | ||
useEffect10(() => { | ||
isValid$.subscribe(setIsValid); | ||
return function () { | ||
return isValid$.close(); | ||
}; | ||
return () => isValid$.close(); | ||
}, [isValid$]); | ||
return isValid; | ||
} | ||
export { | ||
FormicaryContext, | ||
conditionalValidator, | ||
createKeyFn, | ||
getFieldChanges, | ||
getFieldValue, | ||
getFormValue, | ||
isAtLeast, | ||
isAtMost, | ||
isGreaterThan, | ||
isInteger, | ||
isLessThan, | ||
isNumber, | ||
isRequired, | ||
matches, | ||
mergeValidators, | ||
noopValidator, | ||
pipeValidators, | ||
resetForm, | ||
setFieldError, | ||
setFieldValue, | ||
setFormInitialValue, | ||
setFormValue, | ||
setInitialValue, | ||
setValidatorMessages, | ||
subfield, | ||
touchFields, | ||
useControl, | ||
useControlStateless, | ||
useErrors, | ||
useFieldChanges, | ||
useFieldValue, | ||
useForm, | ||
useFormRef, | ||
useFormValue, | ||
useInput, | ||
useIsPristine, | ||
useIsValid | ||
}; | ||
function useWatch(formRef, keySelector) { | ||
var value$ = getMapValue(keySelector, formRef.values); | ||
var _useState = useState(function () { | ||
if (value$.hasValue()) { | ||
return value$.getValue(); | ||
} | ||
return undefined; | ||
}), | ||
value = _useState[0], | ||
setValue = _useState[1]; | ||
useEffect(function () { | ||
return value$.subscribe(setValue); | ||
}, [value$]); | ||
return value; | ||
} | ||
export { conditionalValidator, getFieldChanges, isAtLeast, isAtMost, isGreaterThan, isInteger, isLessThan, isNumber, isRequired, matches, mergeValidators, pipeValidators, readField, readForm, resetForm, setFieldError, setFieldValue, setFormInitialValue, setFormValue, setInitialValue, subfield, touchFields, useControl, useControlSubscription, useErrors, useForm, useFormChanges, useInput, useIsPristine, useIsValid, useWatch }; | ||
//# sourceMappingURL=formicary.esm.js.map |
@@ -0,8 +1,853 @@ | ||
var __create = Object.create; | ||
var __defProp = Object.defineProperty; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __getProtoOf = Object.getPrototypeOf; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); | ||
var __export = (target, all) => { | ||
__markAsModule(target); | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __reExport = (target, module2, desc) => { | ||
if (module2 && typeof module2 === "object" || typeof module2 === "function") { | ||
for (let key of __getOwnPropNames(module2)) | ||
if (!__hasOwnProp.call(target, key) && key !== "default") | ||
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable }); | ||
} | ||
return target; | ||
}; | ||
var __toModule = (module2) => { | ||
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2); | ||
}; | ||
'use strict' | ||
// src/index.ts | ||
__export(exports, { | ||
FormicaryContext: () => FormicaryContext, | ||
conditionalValidator: () => conditionalValidator, | ||
createKeyFn: () => createKeyFn, | ||
getFieldChanges: () => getFieldChanges, | ||
getFieldValue: () => getFieldValue, | ||
getFormValue: () => getFormValue, | ||
isAtLeast: () => isAtLeast, | ||
isAtMost: () => isAtMost, | ||
isGreaterThan: () => isGreaterThan, | ||
isInteger: () => isInteger, | ||
isLessThan: () => isLessThan, | ||
isNumber: () => isNumber, | ||
isRequired: () => isRequired, | ||
matches: () => matches, | ||
mergeValidators: () => mergeValidators, | ||
noopValidator: () => noopValidator, | ||
pipeValidators: () => pipeValidators, | ||
resetForm: () => resetForm, | ||
setFieldError: () => setFieldError, | ||
setFieldValue: () => setFieldValue, | ||
setFormInitialValue: () => setFormInitialValue, | ||
setFormValue: () => setFormValue, | ||
setInitialValue: () => setInitialValue, | ||
setValidatorMessages: () => setValidatorMessages, | ||
subfield: () => subfield, | ||
touchFields: () => touchFields, | ||
useControl: () => useControl, | ||
useControlStateless: () => useControlStateless, | ||
useErrors: () => useErrors, | ||
useFieldChanges: () => useFieldChanges, | ||
useFieldValue: () => useFieldValue, | ||
useForm: () => useForm, | ||
useFormRef: () => useFormRef, | ||
useFormValue: () => useFormValue, | ||
useInput: () => useInput, | ||
useIsPristine: () => useIsPristine, | ||
useIsValid: () => useIsValid | ||
}); | ||
if (process.env.NODE_ENV === 'production') { | ||
module.exports = require('./formicary.cjs.production.min.js') | ||
} else { | ||
module.exports = require('./formicary.cjs.development.js') | ||
// src/internal/path.ts | ||
var import_derive_state = __toModule(require("derive-state")); | ||
// src/internal/subfield.ts | ||
var IS_SUBFIELD = Symbol("is subfield"); | ||
var setSubfield = (obj) => { | ||
obj[IS_SUBFIELD] = true; | ||
return obj; | ||
}; | ||
var subfield = (obj) => Array.isArray(obj) ? setSubfield([...obj]) : setSubfield({ ...obj }); | ||
var isSubfield = (obj) => IS_SUBFIELD in obj; | ||
// src/internal/path.ts | ||
var internal = Symbol("internal"); | ||
function createKeyFn() { | ||
return (path) => path; | ||
} | ||
var PATH_RESULT = Symbol("path"); | ||
var getProxyHandler = () => { | ||
const handler = { | ||
get: (target, prop, receiver) => { | ||
if (prop === PATH_RESULT) { | ||
return target.path; | ||
} | ||
if (typeof prop === "symbol") { | ||
throw new Error(`Can't serialize symbols to keys`); | ||
} | ||
const newPath = typeof prop === "number" || !isNaN(prop) ? `${target.path}[${prop}]` : target.path.length ? `${target.path}.${prop}` : prop; | ||
if (target.path.length === 0) | ||
return new Proxy({ | ||
path: newPath | ||
}, handler); | ||
target.path = newPath; | ||
return receiver; | ||
} | ||
}; | ||
return handler; | ||
}; | ||
var getKey = (keySelector) => { | ||
if (typeof keySelector === "string") | ||
return keySelector; | ||
const proxy = new Proxy({ path: "" }, getProxyHandler()); | ||
const result = keySelector(proxy); | ||
if (!(PATH_RESULT in result)) { | ||
throw new Error(`You must return a value from the argument in the selector function`); | ||
} | ||
return result[PATH_RESULT]; | ||
}; | ||
var getKeys = (keysSelector) => { | ||
if (Array.isArray(keysSelector) && keysSelector.length === 1 && typeof keysSelector[0] === "function") { | ||
keysSelector = keysSelector[0]; | ||
} | ||
if (typeof keysSelector === "object") | ||
return keysSelector; | ||
const proxy = new Proxy({ path: "" }, getProxyHandler()); | ||
const result = keysSelector(proxy); | ||
if (result.some((r) => !(PATH_RESULT in r))) { | ||
throw new Error(`You must return a value from the argument in the selector function`); | ||
} | ||
return result.map((r) => r[PATH_RESULT]); | ||
}; | ||
var getMapValue = (key, map6) => { | ||
if (!map6.has(key)) { | ||
map6.set(key, new import_derive_state.State()); | ||
} | ||
return map6.get(key); | ||
}; | ||
var getKeyValues = (input) => { | ||
const result = {}; | ||
if (!input) { | ||
return result; | ||
} | ||
if (typeof input !== "object") { | ||
throw new Error("Model must be an object"); | ||
} | ||
const prefix = Array.isArray(input) ? (k) => `[${k}]` : (k) => k; | ||
Object.entries(input).forEach(([key, value]) => { | ||
const prefixValue = prefix(key); | ||
if ((isPlainObject(value) || Array.isArray(value)) && isSubfield(value)) { | ||
const inner = getKeyValues(value); | ||
Object.entries(inner).forEach(([innerKey, innerValue]) => { | ||
const chain = innerKey.startsWith("[") ? "" : "."; | ||
result[prefixValue + chain + innerKey] = innerValue; | ||
}); | ||
} else { | ||
result[prefixValue] = value; | ||
} | ||
}); | ||
return result; | ||
}; | ||
var buildObject = (propValues) => { | ||
const ret = {}; | ||
for (const key in propValues) { | ||
setProp(ret, key, propValues[key]); | ||
} | ||
return ret; | ||
}; | ||
var setProp = (obj, key, value) => { | ||
if (key.startsWith("[")) { | ||
const end = key.indexOf("]"); | ||
const num = Number(key.substring(1, end)); | ||
const remaining = key.substring(end + 1); | ||
if (remaining.length) { | ||
if (remaining.startsWith(".")) { | ||
obj[num] = obj[num] || {}; | ||
return setProp(obj[num], remaining.slice(1), value); | ||
} | ||
obj[num] = obj[num] || []; | ||
return setProp(obj[num], remaining, value); | ||
} | ||
obj[num] = value; | ||
return; | ||
} | ||
const propType = getPropType(key); | ||
switch (propType) { | ||
case "array": { | ||
const firstBracket = key.indexOf("["); | ||
const prop = key.substring(0, firstBracket); | ||
const remaining = key.substring(firstBracket); | ||
obj[prop] = obj[prop] || []; | ||
return setProp(obj[prop], remaining, value); | ||
} | ||
case "object": { | ||
const firstDot = key.indexOf("."); | ||
const prop = key.substring(0, firstDot); | ||
const remaining = key.substring(firstDot + 1); | ||
obj[prop] = obj[prop] || {}; | ||
return setProp(obj[prop], remaining, value); | ||
} | ||
case "terminal": { | ||
obj[key] = value; | ||
return; | ||
} | ||
} | ||
}; | ||
var getPropType = (key) => { | ||
const firstDot = key.indexOf("."); | ||
const firstBracket = key.indexOf("["); | ||
if (firstDot < 0 && firstBracket < 0) { | ||
return "terminal"; | ||
} | ||
if (firstDot < 0) { | ||
return "array"; | ||
} | ||
if (firstBracket < 0) { | ||
return "object"; | ||
} | ||
if (firstDot < firstBracket) { | ||
return "object"; | ||
} | ||
return "array"; | ||
}; | ||
var isPlainObject = (value) => value !== null && typeof value === "object" && value.__proto__ === Object.prototype; | ||
// src/commands/getFieldChanges.ts | ||
function getFieldChanges(formRef) { | ||
const keys = formRef.registeredKeys.getValue(); | ||
return Array.from(keys).map((key) => { | ||
const initialValue$ = getMapValue(key, formRef.initialValues); | ||
const value$ = getMapValue(key, formRef.values); | ||
if (!initialValue$.hasValue() || !value$.hasValue()) { | ||
return null; | ||
} | ||
const initial = initialValue$.getValue(); | ||
const value = value$.getValue(); | ||
return { key, initial, value }; | ||
}).filter((change) => change && change.initial !== change.value); | ||
} | ||
// src/commands/getFieldValue.ts | ||
function getFieldValue(formRef, key) { | ||
try { | ||
return getMapValue(getKey(key), formRef.values).getValue(); | ||
} catch (ex) { | ||
return void 0; | ||
} | ||
} | ||
// src/commands/getFormValue.ts | ||
var getFormValue = (formRef) => buildObject(Object.fromEntries(Array.from(formRef.values.entries()).map(([key, value]) => [ | ||
key, | ||
value.hasValue() ? value.getValue() : void 0 | ||
]))); | ||
// src/internal/formRef.ts | ||
var import_derive_state2 = __toModule(require("derive-state")); | ||
// src/validators.ts | ||
var validatorMessages = { | ||
isNumber: () => "Expected a number", | ||
isInteger: () => "Expected an integer", | ||
isRequired: () => "Required", | ||
isAtLeast: (threshold) => "Expected a value of at least " + threshold, | ||
isGreaterThan: (threshold) => "Expected a value greater than " + threshold, | ||
isAtMost: (threshold) => "Expected a value of at most " + threshold, | ||
isLessThan: (threshold) => "Expected a value less than " + threshold, | ||
matches: (regex) => "Invalid Value" | ||
}; | ||
var setValidatorMessages = (messages) => { | ||
Object.entries(messages).forEach(([key, value]) => validatorMessages[key] = value); | ||
}; | ||
var isNumber = (message) => (value) => { | ||
if (isNil(value)) | ||
return true; | ||
if (isNaN(value)) { | ||
return [message != null ? message : validatorMessages.isNumber()]; | ||
} | ||
return true; | ||
}; | ||
var isInteger = (message) => (value) => { | ||
if (isNil(value)) | ||
return true; | ||
if (parseInt(value) !== parseFloat(value)) { | ||
return [message != null ? message : validatorMessages.isInteger()]; | ||
} | ||
return true; | ||
}; | ||
var isRequired = (message) => (value) => isNil(value) || value === "" ? [message != null ? message : validatorMessages.isRequired()] : true; | ||
var parseNumericParam = (value, getValue) => typeof value === "function" ? value(getValue) : typeof value === "string" ? Number(getValue(value)) : value; | ||
var isAtLeast = (threshold, message) => (value, getValue) => { | ||
if (isNil(value)) | ||
return true; | ||
const thresholdValue = parseNumericParam(threshold, getValue); | ||
if (Number(value) < thresholdValue) { | ||
return [message != null ? message : validatorMessages.isAtLeast(thresholdValue)]; | ||
} | ||
return true; | ||
}; | ||
var isGreaterThan = (threshold, message) => (value, getValue) => { | ||
if (isNil(value)) | ||
return true; | ||
const thresholdValue = parseNumericParam(threshold, getValue); | ||
if (Number(value) <= thresholdValue) { | ||
return [message != null ? message : validatorMessages.isGreaterThan(thresholdValue)]; | ||
} | ||
return true; | ||
}; | ||
var isAtMost = (threshold, message) => (value, getValue) => { | ||
if (isNil(value)) | ||
return true; | ||
const thresholdValue = parseNumericParam(threshold, getValue); | ||
if (Number(value) > thresholdValue) { | ||
return [message != null ? message : validatorMessages.isAtMost(thresholdValue)]; | ||
} | ||
return true; | ||
}; | ||
var isLessThan = (threshold, message) => (value, getValue) => { | ||
if (isNil(value)) | ||
return true; | ||
const thresholdValue = parseNumericParam(threshold, getValue); | ||
if (Number(value) >= thresholdValue) { | ||
return [message != null ? message : validatorMessages.isLessThan(thresholdValue)]; | ||
} | ||
return true; | ||
}; | ||
var matches = (regex, message) => (value) => { | ||
if (isNil(value)) | ||
return true; | ||
if (regex.test(value)) { | ||
return true; | ||
} | ||
return [message != null ? message : validatorMessages.matches(regex)]; | ||
}; | ||
var recPipeValidators = (validators, i) => (...args) => { | ||
if (i >= validators.length) { | ||
return true; | ||
} | ||
const syncResult = validators[i](...args); | ||
const processResult = (result) => { | ||
if (result !== true) { | ||
return result; | ||
} | ||
return recPipeValidators(validators, i + 1)(...args); | ||
}; | ||
if (validationResultIsAsync(syncResult)) { | ||
return syncResult.then(processResult); | ||
} | ||
return processResult(syncResult); | ||
}; | ||
var pipeValidators = (...validators) => recPipeValidators(validators, 0); | ||
var mergeValidators = (...validators) => (...args) => { | ||
const syncResults = validators.map((validate) => validate(...args)); | ||
const processResult = (results) => { | ||
const flattenedResults = results.flatMap((result) => result === true ? [] : result); | ||
return flattenedResults; | ||
}; | ||
if (syncResults.some(validationResultIsAsync)) { | ||
return Promise.all(syncResults).then(processResult); | ||
} | ||
return processResult(syncResults); | ||
}; | ||
function conditionalValidator(condition, validator) { | ||
return (value, getValue) => { | ||
if (condition(value, getValue)) { | ||
return validator(value, getValue); | ||
} | ||
return true; | ||
}; | ||
} | ||
var noopValidator = () => true; | ||
var validationResultIsAsync = (result) => typeof result === "object" && !Array.isArray(result); | ||
var isNil = (v) => v == null; | ||
// src/internal/formRef.ts | ||
var createFormRef = (options = {}) => { | ||
const initialValues = new Map(); | ||
Object.entries(getKeyValues(options.initialValue || {})).forEach(([key, value]) => { | ||
initialValues.set(key, new import_derive_state2.State(value)); | ||
}); | ||
const values = new Map(Array.from(initialValues.entries()).map(([key, subject]) => [key, new import_derive_state2.State(subject.getValue())])); | ||
const registeredKeys = new import_derive_state2.State(new Set(values.keys())); | ||
const controlStates = new Map(); | ||
const getControlValue$ = (key) => getMapValue(key, values); | ||
const registerControl = ({ | ||
initialValue, | ||
key, | ||
validator = noopValidator | ||
}) => { | ||
const value$ = getControlValue$(key); | ||
const control$ = getMapValue(key, controlStates); | ||
if (!control$.hasValue()) { | ||
const keys = registeredKeys.getValue(); | ||
keys.add(key); | ||
registeredKeys.setValue(keys); | ||
const manualError = new import_derive_state2.Stateless(); | ||
control$.setValue({ | ||
touched: false, | ||
validator, | ||
manualError, | ||
error$: createError$({ | ||
key, | ||
validator$: control$.pipe((0, import_derive_state2.map)((control) => control.validator), (0, import_derive_state2.withDefault)(validator), (0, import_derive_state2.distinctUntilChanged)()), | ||
value$, | ||
manualError$: manualError, | ||
getControlValue$ | ||
}).capture() | ||
}); | ||
} | ||
if (validator !== control$.getValue().validator) { | ||
control$.setValue({ | ||
...control$.getValue(), | ||
validator | ||
}); | ||
} | ||
const initialValue$ = getMapValue(key, initialValues); | ||
if (!initialValue$.hasValue()) { | ||
initialValue$.setValue(initialValue); | ||
} | ||
const valueSource$ = getMapValue(key, values); | ||
if (!valueSource$.hasValue()) { | ||
valueSource$.setValue(initialValue$.getValue()); | ||
} | ||
}; | ||
return { | ||
registeredKeys, | ||
registerControl, | ||
initialValues, | ||
controlStates, | ||
values, | ||
dispose: () => { | ||
Array.from(initialValues.values()).forEach((state) => state.close()); | ||
Array.from(values.values()).forEach((state) => state.close()); | ||
Array.from(controlStates.values()).forEach((state) => { | ||
if (state.hasValue()) { | ||
state.getValue().error$.close(); | ||
} | ||
state.close(); | ||
}); | ||
registeredKeys.close(); | ||
initialValues.clear(); | ||
values.clear(); | ||
controlStates.clear(); | ||
} | ||
}; | ||
}; | ||
function isFormRef(value) { | ||
return !!(typeof value === "object" && value && "registeredKeys" in value && "registerControl" in value); | ||
} | ||
var getControlState = (formRef, key) => getMapValue(key, formRef.controlStates); | ||
var createError$ = (params) => { | ||
const { key, validator$, value$, getControlValue$ } = params; | ||
const validationError$ = new import_derive_state2.Stateless((obs) => { | ||
const dependenciesObserved = new Set(); | ||
let latestValidator = EMPTY; | ||
validator$.subscribe((v) => latestValidator = v); | ||
let latestValue = EMPTY; | ||
value$.subscribe((v) => { | ||
latestValue = v; | ||
runValidator(); | ||
}); | ||
function runValidator() { | ||
if (latestValidator === EMPTY) { | ||
throw new Error("No validator defined"); | ||
} | ||
if (latestValue === EMPTY) { | ||
throw new Error("No validator defined"); | ||
} | ||
try { | ||
const result = latestValidator(latestValue, (key2) => { | ||
const targetControlValue$ = getControlValue$(key2); | ||
if (!dependenciesObserved.has(targetControlValue$)) { | ||
dependenciesObserved.add(targetControlValue$); | ||
(0, import_derive_state2.asStateless)(targetControlValue$).subscribe(runValidator); | ||
} | ||
if (!targetControlValue$.hasValue()) { | ||
throw new ValueNotThereYetError(key2); | ||
} | ||
return targetControlValue$.getValue(); | ||
}); | ||
if (typeof result === "boolean") { | ||
return obs.next(result === true ? false : []); | ||
} | ||
if (Array.isArray(result)) { | ||
return obs.next(result); | ||
} | ||
obs.next("pending"); | ||
result.then((result2) => obs.next(result2 === true ? false : result2)); | ||
} catch (ex) { | ||
if (ex instanceof ValueNotThereYetError) { | ||
console.warn(`Setting control ${key} error to pending, as the validation depends on a field that hasn't been registered yet`, ex); | ||
} else { | ||
console.error(ex); | ||
} | ||
return obs.next("pending"); | ||
} | ||
} | ||
}); | ||
const manualError$ = new import_derive_state2.Stateless((obs) => { | ||
obs.next(false); | ||
let innerUnsub = () => void 0; | ||
const outerUnsub = params.manualError$.subscribe((error) => { | ||
obs.next(error); | ||
innerUnsub(); | ||
innerUnsub = value$.pipe((0, import_derive_state2.skipSynchronous)(), (0, import_derive_state2.take)(1), (0, import_derive_state2.map)(() => false)).subscribe(obs.next); | ||
}); | ||
return () => { | ||
innerUnsub(); | ||
outerUnsub(); | ||
}; | ||
}); | ||
const errors = (0, import_derive_state2.combine)({ | ||
validatorResult: validationError$, | ||
manualResult: manualError$ | ||
}); | ||
return errors.pipe((0, import_derive_state2.map)(({ validatorResult, manualResult }) => { | ||
if (manualResult === false || manualResult === "pending") | ||
return validatorResult; | ||
if (validatorResult === false || validatorResult === "pending") | ||
return manualResult; | ||
return [...manualResult, ...validatorResult]; | ||
})); | ||
}; | ||
var ValueNotThereYetError = class extends Error { | ||
constructor(key) { | ||
super(`Control ${key} doesn't have any value yet`); | ||
this.name = "ValueNotThereYetError"; | ||
Object.setPrototypeOf(this, ValueNotThereYetError.prototype); | ||
} | ||
}; | ||
var EMPTY = Symbol("empty"); | ||
// src/commands/resetForm.ts | ||
var resetForm = (formRef, keys) => { | ||
const { values, initialValues } = formRef; | ||
const allKeys = keys != null ? keys : Array.from(values.keys()); | ||
allKeys.forEach((key) => { | ||
if (!values.has(key) || !initialValues.has(key)) { | ||
return; | ||
} | ||
values.get(key).setValue(initialValues.get(key).getValue()); | ||
const control = getControlState(formRef, key); | ||
const controlValue = control.getValue(); | ||
if (controlValue.touched) { | ||
control.setValue({ | ||
...controlValue, | ||
touched: false | ||
}); | ||
} | ||
}); | ||
}; | ||
// src/commands/setFieldValue.ts | ||
var setFieldValue = (formRef, key, value) => { | ||
getMapValue(key, formRef.values).setValue(value); | ||
}; | ||
var setFormValue = (formRef, value) => { | ||
Object.entries(getKeyValues(value)).forEach(([key, value2]) => { | ||
getMapValue(key, formRef.values).setValue(value2); | ||
}); | ||
}; | ||
// src/commands/setInitialValue.ts | ||
var setInitialValue = (formRef, key, value) => getMapValue(key, formRef.initialValues).setValue(value); | ||
var setFormInitialValue = (formRef, value) => { | ||
Object.entries(getKeyValues(value)).forEach(([key, value2]) => { | ||
getMapValue(key, formRef.initialValues).setValue(value2); | ||
}); | ||
}; | ||
// src/commands/touchFields.ts | ||
var touchFields = (formRef, keys, touch = true) => { | ||
const allKeys = keys != null ? keys : formRef.registeredKeys.getValue(); | ||
allKeys.forEach((key) => { | ||
const control$ = getControlState(formRef, key); | ||
const controlValue = control$.getValue(); | ||
if (controlValue.touched !== touch) { | ||
control$.setValue({ | ||
...controlValue, | ||
touched: touch | ||
}); | ||
} | ||
}); | ||
}; | ||
// src/commands/setFieldError.ts | ||
var setFieldError = (formRef, key, error) => { | ||
try { | ||
getControlState(formRef, key).getValue().manualError.emit(error); | ||
} catch (ex) { | ||
console.warn("Can't set error: Field not registered", ex); | ||
} | ||
}; | ||
// src/hooks/useControl.ts | ||
var import_react3 = __toModule(require("react")); | ||
// src/context.ts | ||
var import_react = __toModule(require("react")); | ||
var FormicaryContext = (0, import_react.createContext)(null); | ||
var useFormRef = () => { | ||
const formRef = (0, import_react.useContext)(FormicaryContext); | ||
if (!formRef) { | ||
throw new Error("Form Provider not found in component tree"); | ||
} | ||
return formRef; | ||
}; | ||
// src/internal/useHookParams.ts | ||
function useHookParams(args) { | ||
if (isFormRef(args[0])) { | ||
return args; | ||
} | ||
return [useFormRef(), ...args]; | ||
} | ||
// src/hooks/useControlStateless.ts | ||
var import_react2 = __toModule(require("react")); | ||
function useControlStateless(...args) { | ||
const [formRef, options] = useHookParams(args); | ||
const key = getKey(options.key); | ||
(0, import_react2.useEffect)(() => { | ||
var _a; | ||
formRef.registerControl({ | ||
key, | ||
initialValue: (_a = options.initialValue) != null ? _a : void 0, | ||
validator: options.validator | ||
}); | ||
}, [formRef, options]); | ||
return { | ||
getValue: () => { | ||
const state = getMapValue(key, formRef.values); | ||
return state.hasValue() ? state.getValue() : options.initialValue; | ||
}, | ||
setValue: (value) => getMapValue(key, formRef.values).setValue(value), | ||
subscribe: (cb) => getMapValue(key, formRef.values).subscribe(cb), | ||
touch: () => { | ||
const state$ = getControlState(formRef, key); | ||
state$.value.then((value) => { | ||
if (value.touched || state$.closed) | ||
return; | ||
state$.setValue({ | ||
...value, | ||
touched: true | ||
}); | ||
}, () => { | ||
}); | ||
} | ||
}; | ||
} | ||
// src/hooks/useControl.ts | ||
function useControl(...args) { | ||
const [formRef, options] = useHookParams(args); | ||
const { subscribe, ...control } = useControlStateless(formRef, options); | ||
const [state, setState] = (0, import_react3.useState)(control.getValue); | ||
(0, import_react3.useEffect)(() => subscribe(setState), []); | ||
return { | ||
...control, | ||
value: state | ||
}; | ||
} | ||
// src/hooks/useErrors.ts | ||
var import_derive_state3 = __toModule(require("derive-state")); | ||
var import_react4 = __toModule(require("react")); | ||
function useErrors(...args) { | ||
const [formRef, ...keys] = useHookParams(args); | ||
const error$ = (0, import_react4.useMemo)(() => { | ||
const keys$ = keys.length === 0 ? formRef.registeredKeys.pipe((0, import_derive_state3.map)((set) => Array.from(set))) : (0, import_derive_state3.just)(getKeys(keys)); | ||
return keys$.pipe((0, import_derive_state3.switchMap)((keys2) => (0, import_derive_state3.combine)(Object.fromEntries(keys2.map((key) => [ | ||
key, | ||
getControlState(formRef, key).pipe((0, import_derive_state3.map)((v) => v.touched ? v.error$ : FALSE), (0, import_derive_state3.withDefault)(FALSE), (0, import_derive_state3.distinctUntilChanged)(), (0, import_derive_state3.switchMap)((v) => v)) | ||
])))), (0, import_derive_state3.map)((results) => Object.fromEntries(Object.entries(results).filter(([, value]) => value !== false)))).capture(); | ||
}, [formRef, ...keys]); | ||
const [errors, setErrors] = (0, import_react4.useState)(() => { | ||
if (error$.hasValue()) { | ||
return error$.getValue(); | ||
} | ||
return {}; | ||
}); | ||
(0, import_react4.useEffect)(() => { | ||
error$.subscribe((x) => setErrors(() => x)); | ||
return () => error$.close(); | ||
}, [error$]); | ||
return errors; | ||
} | ||
var FALSE = (0, import_derive_state3.just)(false); | ||
// src/hooks/useFieldChanges.ts | ||
var import_react6 = __toModule(require("react")); | ||
// src/internal/useLatestRef.ts | ||
var import_react5 = __toModule(require("react")); | ||
function useLatestRef(value) { | ||
const ref = (0, import_react5.useRef)(value); | ||
ref.current = value; | ||
return ref; | ||
} | ||
// src/hooks/useFieldChanges.ts | ||
function useFieldChanges(...args) { | ||
const [formRef, keySelector, onChange] = useHookParams(args); | ||
const onChangeRef = useLatestRef(onChange); | ||
const value$ = getMapValue(getKey(keySelector), formRef.values); | ||
(0, import_react6.useEffect)(() => { | ||
let isInitial = true; | ||
return value$.subscribe((value) => { | ||
onChangeRef.current(value, isInitial); | ||
isInitial = false; | ||
}); | ||
}, [value$]); | ||
} | ||
// src/hooks/useFieldValue.ts | ||
var import_react7 = __toModule(require("react")); | ||
function useFieldValue(...args) { | ||
const [formRef, key] = useHookParams(args); | ||
const value$ = getMapValue(getKey(key), formRef.values); | ||
const [value, setValue] = (0, import_react7.useState)(() => { | ||
if (value$.hasValue()) { | ||
return value$.getValue(); | ||
} | ||
return void 0; | ||
}); | ||
(0, import_react7.useEffect)(() => value$.subscribe(setValue), [value$]); | ||
return value; | ||
} | ||
// src/hooks/useForm.ts | ||
var import_react8 = __toModule(require("react")); | ||
var useForm = (options) => { | ||
const ref = (0, import_react8.useRef)(null); | ||
if (!ref.current) { | ||
ref.current = createFormRef(options); | ||
} | ||
(0, import_react8.useEffect)(() => () => { | ||
var _a; | ||
return (_a = ref.current) == null ? void 0 : _a.dispose(); | ||
}, []); | ||
return ref.current; | ||
}; | ||
// src/hooks/useFormValue.ts | ||
var import_derive_state4 = __toModule(require("derive-state")); | ||
var import_react9 = __toModule(require("react")); | ||
function useFormValue(...args) { | ||
const [formRef, mapFn, eqFn] = useHookParams(args); | ||
const valueStream = (0, import_react9.useMemo)(() => formRef.registeredKeys.pipe((0, import_derive_state4.map)((set) => Array.from(set)), (0, import_derive_state4.switchMap)((keys) => (0, import_derive_state4.combine)(Object.fromEntries(keys.map((key) => [ | ||
key, | ||
formRef.values.get(key).pipe((0, import_derive_state4.withDefault)(void 0), (0, import_derive_state4.distinctUntilChanged)()) | ||
])))), (0, import_derive_state4.map)((formValues) => mapFn(buildObject(formValues))), (0, import_derive_state4.distinctUntilChanged)(eqFn)).capture(), [formRef]); | ||
const [state, setState] = (0, import_react9.useState)(() => valueStream.hasValue() ? valueStream.getValue() : {}); | ||
(0, import_react9.useEffect)(() => { | ||
valueStream.subscribe(setState); | ||
return () => valueStream.close(); | ||
}, [valueStream]); | ||
return state; | ||
} | ||
// src/hooks/useInput.ts | ||
var import_react10 = __toModule(require("react")); | ||
function useInput(...args) { | ||
var _a; | ||
const [formRef, keySelector, options = {}] = useHookParams(args); | ||
const { eventType = "input", elementProp = "value" } = options; | ||
const ref = (0, import_react10.useRef)(null); | ||
const control = useControlStateless(formRef, { | ||
key: keySelector, | ||
initialValue: (_a = options.initialValue) != null ? _a : "", | ||
validator: options.validator | ||
}); | ||
(0, import_react10.useEffect)(() => { | ||
const element = ref.current; | ||
if (!element) { | ||
return; | ||
} | ||
const valueUnsub = control.subscribe((value) => { | ||
if (element[elementProp] !== value) { | ||
element[elementProp] = value; | ||
} | ||
}); | ||
const blurListener = () => { | ||
control.touch(); | ||
}; | ||
element.addEventListener("blur", blurListener); | ||
const valueListener = (event) => control.setValue(event.target[elementProp]); | ||
element.addEventListener(eventType, valueListener); | ||
return () => { | ||
valueUnsub(); | ||
element.removeEventListener("blur", blurListener); | ||
element.removeEventListener(eventType, valueListener); | ||
}; | ||
}, [ref.current]); | ||
return ref; | ||
} | ||
// src/hooks/useIsPristine.ts | ||
var import_react11 = __toModule(require("react")); | ||
var import_derive_state5 = __toModule(require("derive-state")); | ||
function useIsPristine(formRef) { | ||
const [_formRef] = useHookParams([formRef]); | ||
const isPristine$ = (0, import_react11.useMemo)(() => _formRef.registeredKeys.pipe((0, import_derive_state5.switchMap)((keys) => (0, import_derive_state5.combine)(Array.from(keys).map((key) => { | ||
const initialValue$ = getMapValue(key, _formRef.initialValues); | ||
const value$ = getMapValue(key, _formRef.values); | ||
return (0, import_derive_state5.combine)({ | ||
initialValue: initialValue$, | ||
value: value$ | ||
}).pipe((0, import_derive_state5.map)(({ initialValue, value }) => initialValue === value)); | ||
})).pipe((0, import_derive_state5.map)((results) => results.every((pristine) => pristine)))), (0, import_derive_state5.distinctUntilChanged)()).capture(), [_formRef]); | ||
const [isPristine, setIsPristine] = (0, import_react11.useState)(() => { | ||
if (isPristine$.hasValue()) { | ||
return isPristine$.getValue(); | ||
} | ||
return true; | ||
}); | ||
(0, import_react11.useEffect)(() => { | ||
isPristine$.subscribe(setIsPristine); | ||
return () => isPristine$.close(); | ||
}, [isPristine$]); | ||
return isPristine; | ||
} | ||
// src/hooks/useIsValid.ts | ||
var import_derive_state6 = __toModule(require("derive-state")); | ||
var import_react12 = __toModule(require("react")); | ||
function useIsValid(...args) { | ||
const [formRef, defaultValue = false, ...keys] = useHookParams(args); | ||
const error$ = (0, import_react12.useMemo)(() => { | ||
const keys$ = keys.length === 0 ? formRef.registeredKeys.pipe((0, import_derive_state6.map)((set) => Array.from(set))) : (0, import_derive_state6.just)(getKeys(keys)); | ||
return keys$.pipe((0, import_derive_state6.switchMap)((keys2) => (0, import_derive_state6.combine)(Object.fromEntries(keys2.map((key) => [ | ||
key, | ||
getControlState(formRef, key).pipe((0, import_derive_state6.take)(1), (0, import_derive_state6.switchMap)((v) => v.error$), (0, import_derive_state6.withDefault)(false)) | ||
])))), (0, import_derive_state6.map)((results) => Object.fromEntries(Object.entries(results).filter(([, value]) => value !== false)))); | ||
}, [formRef, ...keys]); | ||
const isValid$ = (0, import_react12.useMemo)(() => error$.pipe((0, import_derive_state6.map)((errors) => { | ||
const errorValues = Object.values(errors); | ||
let hasPending = false; | ||
const hasError = errorValues.some((error) => { | ||
if (error === "pending") { | ||
hasPending = true; | ||
return false; | ||
} | ||
return true; | ||
}); | ||
return hasError ? false : hasPending ? "pending" : true; | ||
})).capture(), [error$]); | ||
const [isValid, setIsValid] = (0, import_react12.useState)(() => { | ||
if (isValid$.hasValue()) { | ||
return isValid$.getValue(); | ||
} | ||
return defaultValue; | ||
}); | ||
(0, import_react12.useEffect)(() => { | ||
isValid$.subscribe(setIsValid); | ||
return () => isValid$.close(); | ||
}, [isValid$]); | ||
return isValid; | ||
} |
{ | ||
"version": "0.2.5", | ||
"version": "0.3.0-beta.0", | ||
"license": "MIT", | ||
"main": "dist/index.js", | ||
"typings": "dist/index.d.ts", | ||
"typings": "dist/types/index.d.ts", | ||
"files": [ | ||
"dist", | ||
"src" | ||
"dist" | ||
], | ||
@@ -14,19 +13,10 @@ "engines": { | ||
"scripts": { | ||
"start": "tsdx watch", | ||
"build": "tsdx build", | ||
"test": "tsdx test --passWithNoTests", | ||
"lint": "tsdx lint", | ||
"prepare": "tsdx build", | ||
"size": "size-limit", | ||
"analyze": "size-limit --why" | ||
"build": "node build.js", | ||
"test": "jest", | ||
"lint": "eslint src/**/*", | ||
"prepare": "node build.js" | ||
}, | ||
"peerDependencies": { | ||
"react": ">=16" | ||
"react": ">=17" | ||
}, | ||
"prettier": { | ||
"printWidth": 80, | ||
"semi": true, | ||
"singleQuote": true, | ||
"trailingComma": "es5" | ||
}, | ||
"name": "formicary", | ||
@@ -40,32 +30,35 @@ "author": "Víctor Oliva", | ||
"sideEffects": false, | ||
"size-limit": [ | ||
{ | ||
"path": "dist/formicary.cjs.production.min.js", | ||
"limit": "10 KB" | ||
}, | ||
{ | ||
"path": "dist/formicary.esm.js", | ||
"limit": "10 KB" | ||
} | ||
], | ||
"devDependencies": { | ||
"@size-limit/preset-small-lib": "^4.6.0", | ||
"@testing-library/jest-dom": "^5.11.4", | ||
"@testing-library/react": "^11.1.0", | ||
"@testing-library/react-hooks": "^3.4.2", | ||
"@testing-library/user-event": "^12.1.8", | ||
"@types/react": "^16.9.53", | ||
"@types/react-dom": "^16.9.8", | ||
"husky": "^4.3.0", | ||
"react": "^16.14.0", | ||
"react-dom": "^16.14.0", | ||
"react-test-renderer": "^17.0.1", | ||
"size-limit": "^4.6.0", | ||
"tsdx": "^0.14.1", | ||
"tslib": "^2.0.3", | ||
"typescript": "^4.0.3" | ||
"@babel/core": "^7.16.0", | ||
"@babel/preset-env": "^7.16.0", | ||
"@babel/preset-react": "^7.16.0", | ||
"@babel/preset-typescript": "^7.16.0", | ||
"@testing-library/jest-dom": "^5.15.0", | ||
"@testing-library/react": "^12.1.2", | ||
"@testing-library/react-hooks": "^7.0.2", | ||
"@testing-library/user-event": "^13.5.0", | ||
"@types/babel__core": "^7.1.16", | ||
"@types/jest": "^27.0.2", | ||
"@types/react": "^17.0.34", | ||
"@types/react-dom": "^17.0.11", | ||
"@typescript-eslint/eslint-plugin": "^5.3.0", | ||
"@typescript-eslint/parser": "^5.3.0", | ||
"babel-jest": "^27.3.1", | ||
"esbuild": "^0.13.12", | ||
"eslint": "^8.2.0", | ||
"eslint-plugin-react": "^7.26.1", | ||
"jest": "^27.3.1", | ||
"prettier": "^2.4.1", | ||
"react": "^17.0.2", | ||
"react-dom": "^17.0.2", | ||
"react-test-renderer": "^17.0.2", | ||
"tslib": "^2.3.1", | ||
"typescript": "^4.4.4" | ||
}, | ||
"dependencies": { | ||
"derive-state": "0.1.0-alpha.8" | ||
}, | ||
"jest": { | ||
"testEnvironment": "jsdom" | ||
} | ||
} | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
2
0
92378
25
35
1915
1