react-validatables
Advanced tools
Comparing version 1.0.0-alpha.4 to 1.0.0-alpha.5
import { InferBindingValueTypes } from 'react-bindings'; | ||
import type { Waitable } from 'react-waitables'; | ||
import { InferOptionalWaitableAndBindingValueTypes, TypeOrPromisedType, WaitableDependencies } from 'react-waitables'; | ||
import { MutableBindingDependencies } from '../types/mutable-binding-dependencies'; | ||
import type { ValidationError } from '../validator/types/validation-error'; | ||
import type { ValidationResult } from '../validator/types/validation-result'; | ||
import { Validator } from '../validator/types/validator'; | ||
export interface FinalizeValidationOptions<FieldBindingsT extends MutableBindingDependencies = Record<string, never>, AdditionalDependenciesT extends WaitableDependencies = Record<string, never>> { | ||
/** Bindings that, when unmodfied, cause validators to be disabled. Usually individual field bindings. */ | ||
fieldBindings?: FieldBindingsT; | ||
/** Additional dependencies, which must not overlap `markBindingsAsModified` */ | ||
additionalDependencies?: AdditionalDependenciesT; | ||
/** Called if the validator results in "invalidity" */ | ||
onInvalid?: (fieldBindingValues: InferBindingValueTypes<FieldBindingsT>, additionalDependencyValues: InferOptionalWaitableAndBindingValueTypes<AdditionalDependenciesT>, fieldBindings: FieldBindingsT, additionalDependencies: AdditionalDependenciesT, validationError: ValidationError) => void; | ||
/** Called if the validator results in "validity" */ | ||
onValid?: (fieldBindingValues: InferBindingValueTypes<FieldBindingsT>, additionalDependencyValues: InferOptionalWaitableAndBindingValueTypes<AdditionalDependenciesT>, fieldBindings: FieldBindingsT, additionalDependencies: AdditionalDependenciesT) => void; | ||
} | ||
export interface FinalizeValidationResult { | ||
/** Call to cancel the validation request */ | ||
cancel: () => void; | ||
/** The promised result, which may be undefined if canceled or if an error occurred */ | ||
validationResult: TypeOrPromisedType<ValidationResult | undefined>; | ||
} | ||
/** | ||
* Marks all specified bindings as "modified", locks them, and then waits for the specified checker to finish. | ||
* Generally used for final "form" validation before submitting data to a server, this: | ||
* | ||
* This is generally used for form-level validation before, for example, submitting to a server. | ||
* - marks field bindings as modified | ||
* - for any previously-unmodified bindings, artificially triggers a change listener callback | ||
* - locks the field bindings | ||
* - waits for the validators to complete | ||
* | ||
* The appropriate callback will be made once the validator is finished. | ||
* | ||
* @returns A function that can be used to cancel the requested validation. | ||
* @returns A function that can be used to cancel the requested validation and a promised validation result. | ||
*/ | ||
export declare const finalizeValidation: <DependenciesT extends MutableBindingDependencies = Record<string, never>>(validator: Waitable<ValidationResult>, { bindings, onInvalid, onValid }: { | ||
bindings?: DependenciesT | undefined; | ||
onInvalid?: ((bindingValues: InferBindingValueTypes<DependenciesT>, bindings: DependenciesT, validationError: ValidationError) => void) | undefined; | ||
onValid?: ((bindingValues: InferBindingValueTypes<DependenciesT>, bindings: DependenciesT) => void) | undefined; | ||
}) => () => void; | ||
export declare const finalizeValidation: <FieldBindingsT extends MutableBindingDependencies = Record<string, never>, AdditionalDependenciesT extends WaitableDependencies = Record<string, never>>(formValidator: Validator, { fieldBindings, additionalDependencies, onInvalid, onValid }?: FinalizeValidationOptions<FieldBindingsT, AdditionalDependenciesT>) => FinalizeValidationResult; | ||
//# sourceMappingURL=finalize-validation.d.ts.map |
@@ -14,23 +14,32 @@ "use strict"; | ||
const react_bindings_1 = require("react-bindings"); | ||
const react_waitables_1 = require("react-waitables"); | ||
const array_like_1 = require("../internal-utils/array-like"); | ||
const extract_binding_dependency_values_1 = require("../internal-utils/extract-binding-dependency-values"); | ||
const extract_waitable_dependency_values_1 = require("../internal-utils/extract-waitable-dependency-values"); | ||
const get_typed_keys_1 = require("../internal-utils/get-typed-keys"); | ||
const emptyDependencies = Object.freeze({}); | ||
/** | ||
* Marks all specified bindings as "modified", locks them, and then waits for the specified checker to finish. | ||
* Generally used for final "form" validation before submitting data to a server, this: | ||
* | ||
* This is generally used for form-level validation before, for example, submitting to a server. | ||
* - marks field bindings as modified | ||
* - for any previously-unmodified bindings, artificially triggers a change listener callback | ||
* - locks the field bindings | ||
* - waits for the validators to complete | ||
* | ||
* The appropriate callback will be made once the validator is finished. | ||
* | ||
* @returns A function that can be used to cancel the requested validation. | ||
* @returns A function that can be used to cancel the requested validation and a promised validation result. | ||
*/ | ||
const finalizeValidation = (validator, { bindings, onInvalid, onValid }) => { | ||
const isNonNamedBindings = Array.isArray(bindings) || (0, react_bindings_1.isBinding)(bindings); | ||
const nonNamedBindings = isNonNamedBindings ? bindings : undefined; | ||
const namedBindings = isNonNamedBindings ? undefined : bindings; | ||
const namedBindingsKeys = namedBindings !== undefined ? Object.keys(namedBindings) : undefined; | ||
const allBindings = isNonNamedBindings ? (0, array_like_1.normalizeAsArray)(nonNamedBindings) : Object.values(namedBindings !== null && namedBindings !== void 0 ? namedBindings : emptyDependencies); | ||
const finalizeValidation = (formValidator, { fieldBindings, additionalDependencies, onInvalid, onValid } = {}) => { | ||
const isNonNamedFieldBindings = Array.isArray(fieldBindings) || (0, react_bindings_1.isBinding)(fieldBindings); | ||
const nonNamedFieldBindings = isNonNamedFieldBindings ? fieldBindings : undefined; | ||
const namedFieldBindings = isNonNamedFieldBindings ? undefined : fieldBindings; | ||
const namedFieldBindingsKeys = namedFieldBindings !== undefined ? (0, get_typed_keys_1.getTypedKeys)(namedFieldBindings) : undefined; | ||
const allFieldBindings = isNonNamedFieldBindings | ||
? (0, array_like_1.normalizeAsArray)(nonNamedFieldBindings) | ||
: Object.values(namedFieldBindings !== null && namedFieldBindings !== void 0 ? namedFieldBindings : emptyDependencies); | ||
const isNonNamedDependencies = Array.isArray(additionalDependencies) || (0, react_waitables_1.isWaitable)(additionalDependencies) || (0, react_bindings_1.isBinding)(additionalDependencies); | ||
const namedDependencies = isNonNamedDependencies ? undefined : additionalDependencies; | ||
const namedAdditionalDependencyKeys = namedDependencies !== undefined ? (0, get_typed_keys_1.getTypedKeys)(namedDependencies) : undefined; | ||
// Marking any bindings that aren't already marked as modified as modified, so their validators will run if they're associated validators | ||
// are setup disabledWhileUnmodifiedBindings | ||
for (const binding of allBindings) { | ||
for (const binding of allFieldBindings) { | ||
if (binding !== undefined && !binding.isModified()) { | ||
@@ -46,45 +55,46 @@ binding.setIsModified(true); | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return | ||
const getDependencyValues = () => (0, extract_binding_dependency_values_1.extractBindingDependencyValues)({ bindings, namedBindingsKeys }); | ||
setTimeout(() => __awaiter(void 0, void 0, void 0, function* () { | ||
if (wasCanceled) { | ||
return; | ||
} | ||
const dependencies = bindings !== null && bindings !== void 0 ? bindings : emptyDependencies; | ||
const result = yield (0, react_bindings_1.lockBindingsAndDo)(allBindings, () => __awaiter(void 0, void 0, void 0, function* () { | ||
// If the validator is already ready, trigger the callbacks right away | ||
let validationResult = validator.value.get(); | ||
if (validationResult !== undefined) { | ||
return { | ||
bindingValues: getDependencyValues(), | ||
validationResult | ||
}; | ||
} | ||
// Otherwise wait for the result. Because we call triggerChangeListeners on the unmodified bindings above, one or more resets may occur | ||
// on the validator, which we want to ignore | ||
let waitResult = yield validator.wait(); | ||
while (!wasCanceled && waitResult === 'reset') { | ||
waitResult = yield validator.wait(); | ||
} | ||
if (waitResult === 'failure') { | ||
return undefined; | ||
} | ||
validationResult = validator.value.get(); | ||
if (validationResult !== undefined) { | ||
return { bindingValues: getDependencyValues(), validationResult }; | ||
} | ||
return undefined; | ||
})); | ||
if (result !== undefined) { | ||
const { bindingValues, validationResult } = result; | ||
const getAdditionalDependencyValues = () => (0, extract_waitable_dependency_values_1.extractOptionalWaitableDependencyValues)({ dependencies: additionalDependencies, namedDependencyKeys: namedAdditionalDependencyKeys }); | ||
const getFieldBindingValues = () => | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return | ||
(0, extract_binding_dependency_values_1.extractBindingDependencyValues)({ bindings: fieldBindings, namedBindingsKeys: namedFieldBindingsKeys }); | ||
const triggerCallbacks = (validationResult) => { | ||
const fieldBindingValues = getFieldBindingValues(); | ||
const additionalDependencyValues = getAdditionalDependencyValues().values; | ||
setTimeout(() => { | ||
if (validationResult.isValid) { | ||
onValid === null || onValid === void 0 ? void 0 : onValid(bindingValues, dependencies); | ||
onValid === null || onValid === void 0 ? void 0 : onValid(fieldBindingValues, additionalDependencyValues, fieldBindings !== null && fieldBindings !== void 0 ? fieldBindings : emptyDependencies, additionalDependencies !== null && additionalDependencies !== void 0 ? additionalDependencies : emptyDependencies); | ||
} | ||
else { | ||
onInvalid === null || onInvalid === void 0 ? void 0 : onInvalid(bindingValues, dependencies, validationResult.validationError); | ||
onInvalid === null || onInvalid === void 0 ? void 0 : onInvalid(fieldBindingValues, additionalDependencyValues, fieldBindings !== null && fieldBindings !== void 0 ? fieldBindings : emptyDependencies, additionalDependencies !== null && additionalDependencies !== void 0 ? additionalDependencies : emptyDependencies, validationResult.validationError); | ||
} | ||
}, 0); | ||
return validationResult; | ||
}; | ||
const validationResult = (0, react_bindings_1.lockBindingsAndDo)(allFieldBindings, () => __awaiter(void 0, void 0, void 0, function* () { | ||
if (wasCanceled) { | ||
return; | ||
} | ||
}), 0); | ||
return cancel; | ||
// If the validator is already ready, trigger the callbacks right away | ||
let validationResult = formValidator.value.get(); | ||
if (validationResult !== undefined) { | ||
return triggerCallbacks(validationResult); | ||
} | ||
// Otherwise wait for the result. Because we call triggerChangeListeners on the unmodified bindings above, one or more resets may occur | ||
// on the validator, which we want to ignore | ||
let waitResult = yield formValidator.wait(); | ||
while (!wasCanceled && waitResult === 'reset') { | ||
waitResult = yield formValidator.wait(); | ||
} | ||
if (waitResult === 'failure') { | ||
return undefined; | ||
} | ||
validationResult = formValidator.value.get(); | ||
if (validationResult !== undefined) { | ||
return triggerCallbacks(validationResult); | ||
} | ||
return undefined; | ||
})); | ||
return { cancel, validationResult }; | ||
}; | ||
exports.finalizeValidation = finalizeValidation; | ||
//# sourceMappingURL=finalize-validation.js.map |
{ | ||
"name": "react-validatables", | ||
"version": "1.0.0-alpha.4", | ||
"version": "1.0.0-alpha.5", | ||
"description": "Validation tools for React built on react-waitables", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
149052
208
1508