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

form-validity

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

form-validity - npm Package Compare versions

Comparing version 0.0.2 to 0.0.3

156

index.d.ts

@@ -1,65 +0,14 @@

interface Required {
required: (message?: string) => this;
}
interface Min<Value> {
min(value: Value | string, message?: string): this;
}
interface Max<Value> {
max(value: Value | string, message?: string): this;
}
interface MinLength {
minLength(number: number, message?: string): this;
}
interface MaxLength {
maxLength(number: number, message?: string): this;
}
interface Pattern {
pattern(regexp: RegExp, message?: string): this;
}
interface Step {
step(number: number | string, message?: string): this;
}
interface Multiple<Count = void> {
multiple(count: Count): this;
}
interface NoConstraint {
}
export interface FieldAttributes {
type?: Exclude<keyof FieldOption, 'select' | 'textarea' | 'fieldset'>;
required?: boolean;
minLength?: number;
maxLength?: number;
min?: string | number;
max?: string | number;
step?: string | number;
pattern?: string;
multiple?: boolean;
}
export interface FieldOption {
checkbox: Required;
color: NoConstraint;
date: Required & Min<Date> & Max<Date> & Step;
datetime: Required & Min<Date> & Max<Date> & Step;
'datetime-local': Required & Min<Date> & Max<Date> & Step;
email: Required & MinLength & MaxLength & Pattern;
fieldset: Multiple<Number>;
file: Required;
hidden: NoConstraint;
month: Required & Min<Date> & Max<Date> & Step;
number: Required & Min<number> & Max<number> & Step;
password: Required & MinLength & MaxLength & Pattern;
radio: Required;
range: Min<number> & Max<number> & Step;
search: Required & MinLength & MaxLength & Pattern;
select: Required;
tel: Required & MinLength & MaxLength & Pattern;
text: Required & MinLength & MaxLength & Pattern;
textarea: Required & MinLength & MaxLength;
time: Required & Min<Date> & Max<Date> & Step;
url: Required & MinLength & MaxLength & Pattern;
week: Required & Min<Date> & Max<Date> & Step;
}
export interface Constraint {
type: {
value: keyof FieldOption;
/**
*
*/
declare const symbol: unique symbol;
export declare type FieldTag = 'input' | 'textarea' | 'select' | 'fieldset';
export declare type InputType = 'checkbox' | 'color' | 'date' | 'date' | 'datetime-local' | 'email' | 'fieldset' | 'file' | 'hidden' | 'month' | 'number' | 'password' | 'radio' | 'range' | 'search' | 'select' | 'tel' | 'text' | 'textarea' | 'time' | 'url' | 'week';
export declare type Field<Tag extends FieldTag = FieldTag, Type extends InputType | undefined = undefined> = (Tag extends 'input' ? Type extends 'checkbox' | 'file' | 'radio' ? Required : Type extends 'date' | 'datetime-local' | 'month' | 'time' | 'week' ? Required & Min<Date> & Max<Date> & Step : Type extends 'email' | 'password' | 'search' | 'tel' | 'text' | 'url' ? Required & MinLength & MaxLength & Pattern : Type extends 'number' ? Required & Min<number> & Max<number> & Step : Type extends 'range' ? Min<number> & Max<number> & Step : {} : Tag extends 'select' ? Required : Tag extends 'textarea' ? Required & MinLength & MaxLength : Tag extends 'fieldset' ? Multiple<number> : unknown) & {
[symbol]: Constraint<Tag>;
};
export declare type Constraint<Tag extends FieldTag = FieldTag> = {
tag: Tag;
type?: {
value: InputType;
message: string | undefined;

@@ -98,47 +47,62 @@ };

};
}
declare const symbol: unique symbol;
export declare type Field<Type extends keyof FieldOption = keyof FieldOption> = FieldOption[Type] & {
[symbol]: () => Constraint;
};
/**
* Helpers for constructing the field constraints
* Helpers for constructing the field constraint based on the type
* @see https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Constraint_validation#validation-related_attributes
*/
export declare const f: {
checkbox: () => Field<"checkbox">;
color: () => Field<"color">;
date: () => Field<"date">;
datetime: () => Field<"datetime-local">;
email: (message?: string | undefined) => Field<"email">;
fieldset: () => Field<"fieldset">;
file: () => Field<"file">;
hidden: () => Field<"hidden">;
month: () => Field<"month">;
number: (message?: string | undefined) => Field<"number">;
password: () => Field<"password">;
radio: () => Field<"radio">;
range: () => Field<"range">;
search: () => Field<"search">;
select: () => Field<"select">;
tel: () => Field<"tel">;
text: () => Field<"text">;
textarea: () => Field<"textarea">;
time: () => Field<"time">;
url: (message?: string | undefined) => Field<"url">;
week: () => Field<"week">;
input: {
<T extends "number" | "email" | "url">(type: T, message?: string | undefined): Field<"input", T>;
<T_1 extends "textarea" | "select" | "fieldset" | "checkbox" | "color" | "date" | "datetime-local" | "file" | "hidden" | "month" | "password" | "radio" | "range" | "search" | "tel" | "text" | "time" | "week">(type: T_1): Field<"input", T_1>;
};
select: () => Field<'select'>;
textarea: () => Field<'textarea'>;
fieldset: () => Field<'fieldset'>;
};
export declare function getConstraint<Type extends keyof FieldOption>(field: Field<Type>): Constraint;
export declare function getConstraint<Tag extends FieldTag>(field: Field<Tag>): Constraint<Tag>;
export declare function isElement<T extends HTMLElement>(element: any, tag: string): element is T;
export declare function isInputElement(element: unknown): element is HTMLInputElement;
export declare function isSelectElement(element: unknown): element is HTMLSelectElement;
export declare function isTextareaElement(element: unknown): element is HTMLTextAreaElement;
export declare function isButtonElement(element: unknown): element is HTMLButtonElement;
export declare function isDirtyField(element: HTMLSelectElement | HTMLInputElement | HTMLTextAreaElement): boolean;
export declare function isDirty(element: unknown): boolean;
export declare function isValidationConstraintSupported(element: unknown): element is HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
export declare function shouldSkipValidate(element: unknown): boolean;
export declare function draftUpdate(name: string, index?: number): {
name: string;
value: string;
};
export declare function getDraft(payload: URLSearchParams | FormData): {
name: string;
index: number | null;
} | null;
export declare function parse<T>(payload: FormData | URLSearchParams | string, fieldsetCreator: ((value?: Record<string, any>) => Record<string, T>) | Record<string, T>): {
value: Record<string, any>;
error: Record<string, string> | null;
isDraft: boolean;
};
/**
* Helpers
*/
interface Required {
required(message?: string): this;
}
interface Min<Value> {
min(value: Value | string, message?: string): this;
}
interface Max<Value> {
max(value: Value | string, message?: string): this;
}
interface MinLength {
minLength(number: number, message?: string): this;
}
interface MaxLength {
maxLength(number: number, message?: string): this;
}
interface Pattern {
pattern(regexp: RegExp, message?: string): this;
}
interface Step {
step(number: number | string, message?: string): this;
}
interface Multiple<Count = void> {
multiple(count: Count): this;
}
export declare function checkCustomValidity(value: FormDataEntryValue, validity: ValidityState, constraint: Constraint): string | null;
export {};

@@ -5,111 +5,113 @@ 'use strict';

var attributesByType = {
// 'button': [],
checkbox: ['required'],
color: [],
date: ['required', 'minLength', 'maxLength', 'pattern'],
datetime: ['required', 'minLength', 'maxLength', 'pattern'],
'datetime-local': ['required', 'minLength', 'maxLength', 'pattern'],
email: ['required', 'minLength', 'maxLength', 'pattern'],
fieldset: ['multiple'],
file: ['required'],
hidden: [],
// 'image': [],
month: ['required', 'minLength', 'maxLength', 'pattern'],
number: ['required', 'minLength', 'maxLength', 'pattern'],
password: ['required', 'minLength', 'maxLength', 'pattern'],
radio: ['required'],
range: ['min', 'max', 'step'],
// 'reset': [],
search: ['required', 'minLength', 'maxLength', 'pattern'],
select: ['required'],
// 'submit': [],
tel: ['required', 'minLength', 'maxLength', 'pattern'],
text: ['required', 'minLength', 'maxLength', 'pattern'],
textarea: ['required', 'minLength', 'maxLength'],
time: ['required', 'minLength', 'maxLength', 'pattern'],
url: ['required', 'minLength', 'maxLength', 'pattern'],
week: ['required', 'minLength', 'maxLength', 'pattern']
};
var symbol = Symbol('constraints');
/**
*
*/
var symbol = Symbol('constraint');
function createField(type, message) {
var supportedAttributes = attributesByType[type];
var constraint = {
type: {
value: type,
message: message
}
};
var field = {
required(message) {
constraint.required = {
message
};
return field;
},
function configureF() {
function createField(tag, type, message) {
var constraint = {
tag
};
min(value, message) {
constraint.min = {
value,
if (type) {
constraint.type = {
value: type,
message
};
return field;
},
}
max(value, message) {
constraint.max = {
value,
message
};
return field;
},
return {
required(message) {
constraint.required = {
message
};
return this;
},
minLength(value, message) {
constraint.minLength = {
value,
message
};
return field;
},
min(value, message) {
constraint.min = {
value,
message
};
return this;
},
maxLength(value, message) {
constraint.maxLength = {
value,
message
};
return field;
},
max(value, message) {
constraint.max = {
value,
message
};
return this;
},
pattern(value, message) {
if (value.global || value.ignoreCase || value.multiline) {
console.warn("global, ignoreCase, and multiline flags are not supported on the pattern attribute");
} else {
var _constraint$pattern;
minLength(value, message) {
constraint.minLength = {
value,
message
};
return this;
},
constraint.pattern = ((_constraint$pattern = constraint.pattern) !== null && _constraint$pattern !== void 0 ? _constraint$pattern : []).concat({
maxLength(value, message) {
constraint.maxLength = {
value,
message
});
}
};
return this;
},
return field;
},
pattern(value, message) {
if (value.global || value.ignoreCase || value.multiline) {
console.warn("global, ignoreCase, and multiline flags are not supported on the pattern attribute");
} else {
var _constraint$pattern;
multiple(value) {
constraint.multiple = {
value,
message
};
return field;
},
constraint.pattern = ((_constraint$pattern = constraint.pattern) !== null && _constraint$pattern !== void 0 ? _constraint$pattern : []).concat({
value,
message
});
}
[symbol]: () => constraint
}; // @ts-ignore
return this;
},
return Object.fromEntries( // @ts-ignore
[symbol, ...supportedAttributes].map(key => [key, field[key]]));
multiple(value) {
constraint.multiple = {
value,
message
};
return this;
},
[symbol]: constraint
};
}
function input(type, message) {
// @ts-expect-error
return createField('input', type, message);
}
function select() {
return createField('select');
}
function textarea() {
return createField('textarea');
}
function fieldset() {
return createField('fieldset');
}
return {
input,
select,
textarea,
fieldset
};
}
/**
* Helpers for constructing the field constraints
* Helpers for constructing the field constraint based on the type
* @see https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Constraint_validation#validation-related_attributes

@@ -119,63 +121,38 @@ */

var f = {
// button: () => createField('button'),
checkbox: () => createField('checkbox'),
color: () => createField('color'),
date: () => createField('date'),
// datetime: () => createField('datetime'),
datetime: () => createField('datetime-local'),
// `datetime` is deprecated
email: message => createField('email', message),
fieldset: () => createField('fieldset'),
file: () => createField('file'),
hidden: () => createField('hidden'),
// image: () => createField('image'),
month: () => createField('month'),
number: message => createField('number', message),
password: () => createField('password'),
radio: () => createField('radio'),
range: () => createField('range'),
// reset: () => createField('reset'),
search: () => createField('search'),
select: () => createField('select'),
// submit: () => createField('submit'),
tel: () => createField('tel'),
text: () => createField('text'),
textarea: () => createField('textarea'),
time: () => createField('time'),
url: message => createField('url', message),
week: () => createField('week')
};
var f = configureF();
function getConstraint(field) {
return field[symbol]();
} // eslint-disable-next-line @typescript-eslint/no-explicit-any
if (typeof field[symbol] === 'undefined') {
throw new Error('Provided config is not a field; Please ensure only field object is used');
}
return field[symbol];
}
function isElement(element, tag) {
return !!element && element.tagName.toLowerCase() === tag;
}
function isInputElement(element) {
return isElement(element, 'input');
}
function isSelectElement(element) {
return isElement(element, 'select');
}
function isTextareaElement(element) {
return isElement(element, 'textarea');
}
function isButtonElement(element) {
return isElement(element, 'button');
}
function isDirtyField(element) {
function isDirty(element) {
if (isElement(element, 'form')) {
for (var el of element.elements) {
if (isDirty(el)) {
return true;
}
}
return false;
}
if (isElement(element, 'input') || isElement(element, 'textarea')) {
return element.value !== element.defaultValue;
} else if (isElement(element, 'select')) {
}
if (isElement(element, 'select')) {
var _Array$from$find;
return element.value !== ((_Array$from$find = Array.from(element.options).find(option => option.defaultSelected)) === null || _Array$from$find === void 0 ? void 0 : _Array$from$find.value);
} else {
return false;
}
return false;
}
function isValidationConstraintSupported(element) {
if (!isInputElement(element) && !isSelectElement(element) && !isTextareaElement(element)) {
if (!isElement(element, 'input') && !isElement(element, 'select') && !isElement(element, 'textarea')) {
return false;

@@ -187,5 +164,106 @@ }

function shouldSkipValidate(element) {
return isButtonElement(element) || isInputElement(element) ? element.formNoValidate : false;
return isElement(element, 'button') || isElement(element, 'input') ? element.formNoValidate : false;
}
function draftUpdate(name, index) {
return {
name: '__form-validity__',
value: [name].concat(typeof index === 'undefined' ? [] : ["".concat(index)]).join('|')
};
}
function getDraft(payload) {
var update = payload.get('__form-validity__');
if (!update) {
return null;
} // We are mutating the payload here
payload.delete('__form-validity__');
if (update instanceof File) {
throw new Error('What?');
}
var [name, indexString] = update.split('|');
var index = typeof indexString !== 'undefined' ? Number(indexString) : null;
return {
name,
index
};
}
function parse(payload, fieldsetCreator) {
var valueEntries = payload instanceof URLSearchParams || payload instanceof FormData ? payload : new URLSearchParams(payload);
var update = getDraft(valueEntries);
var value = unflatten(valueEntries);
if (update) {
var list = getItem(value, update.name);
if (!Array.isArray(list) || update.index !== null && isNaN(update.index)) {
throw new Error('Oops');
}
if (update.index !== null) {
list.splice(update.index, 1);
} else {
list.push({});
}
}
var fieldset = typeof fieldsetCreator === 'function' ? fieldsetCreator(value) : fieldsetCreator;
var valueByName = Object.fromEntries(valueEntries);
var errorEntries = [];
if (!update) {
for (var [name, field] of flatten(fieldset, f => typeof f[symbol] !== 'undefined')) {
var constraint = getConstraint(field);
var _value = valueByName[name];
var validity = validate(_value, constraint);
var _message = checkCustomValidity(_value, validity, constraint);
if (_message) {
errorEntries.push([name, _message]);
}
}
}
return {
value,
error: errorEntries.length > 0 ? unflatten(errorEntries) : null,
isDraft: update !== null
};
}
/**
* Helpers
*/
var pattern = /(\w+)\[(\d+)\]/;
function getPaths(key) {
return key.split('.').flatMap(key => {
var matches = pattern.exec(key);
if (!matches) {
return key;
}
return [matches[1], Number(matches[2])];
});
}
function getItem(obj, key, defaultValue) {
var target = obj;
for (var path of getPaths(key)) {
if (typeof target[path] === 'undefined') {
return defaultValue;
}
target = target[path];
}
return target;
}
function flatten(item, isLeaf) {

@@ -202,4 +280,4 @@ var prefix = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';

} else {
for (var [key, _value] of Object.entries(item)) {
entries.push(...flatten(_value, isLeaf, prefix ? "".concat(prefix, ".").concat(key) : key));
for (var [key, _value2] of Object.entries(item)) {
entries.push(...flatten(_value2, isLeaf, prefix ? "".concat(prefix, ".").concat(key) : key));
}

@@ -212,15 +290,6 @@ }

function unflatten(entries) {
var pattern = /(\w+)\[(\d+)\]/;
var result = {};
for (var [key, _value2] of entries) {
var paths = key.split('.').flatMap(key => {
var matches = pattern.exec(key);
if (!matches) {
return key;
}
return [matches[1], Number(matches[2])];
});
for (var [key, _value3] of entries) {
var paths = getPaths(key);
var length = paths.length;

@@ -234,3 +303,3 @@ var lastIndex = length - 1;

var next = paths[index + 1];
var newValue = _value2;
var newValue = _value3;

@@ -252,139 +321,111 @@ if (index != lastIndex) {

function validate(value, constraint) {
var _constraint$pattern2;
var badInput = false;
var customError = false;
var patternMismatch = false;
var rangeOverflow = false;
var rangeUnderflow = false;
var stepMismatch = false;
var tooLong = false;
var tooShort = false;
var typeMismatch = false;
var valueMissing = false;
if (value instanceof File) {
return 'File is not supported yet';
}
var _constraint$type;
if (constraint.required) {
if (typeof value === 'undefined' || value === '') {
var _constraint$required$;
typeMismatch = ((_constraint$type = constraint.type) === null || _constraint$type === void 0 ? void 0 : _constraint$type.value) !== 'file';
} else {
var _constraint$pattern$s, _constraint$pattern2, _constraint$type2, _constraint$type3;
return (_constraint$required$ = constraint.required.message) !== null && _constraint$required$ !== void 0 ? _constraint$required$ : 'This field is required';
}
}
var isURL = value => {
try {
new URL(value);
return true;
} catch (_unused) {
return false;
}
};
if (constraint.minLength) {
if (typeof value === 'undefined' || value.length < constraint.minLength.value) {
var _constraint$minLength;
return (_constraint$minLength = constraint.minLength.message) !== null && _constraint$minLength !== void 0 ? _constraint$minLength : "This field must be at least ".concat(constraint.minLength.value, " characters");
}
patternMismatch = (_constraint$pattern$s = (_constraint$pattern2 = constraint.pattern) === null || _constraint$pattern2 === void 0 ? void 0 : _constraint$pattern2.some(pattern => {
var match = value === null || value === void 0 ? void 0 : value.match(pattern.value);
return !match || value !== match[0];
})) !== null && _constraint$pattern$s !== void 0 ? _constraint$pattern$s : false;
rangeOverflow = constraint.max ? typeof value !== 'undefined' && constraint.max.value instanceof Date && new Date(value) > constraint.max.value || typeof value !== 'undefined' && typeof constraint.max.value === 'number' && Number(value) > constraint.max.value : false;
rangeUnderflow = constraint.min ? constraint.min.value instanceof Date && new Date(value !== null && value !== void 0 ? value : '') < constraint.min.value || typeof constraint.min.value === 'number' && Number(value !== null && value !== void 0 ? value : '') < constraint.min.value : false;
tooLong = constraint.maxLength ? typeof value !== 'undefined' && value.length > constraint.maxLength.value : false;
tooShort = constraint.minLength ? typeof value === 'undefined' || value.length < constraint.minLength.value : false;
typeMismatch = ((_constraint$type2 = constraint.type) === null || _constraint$type2 === void 0 ? void 0 : _constraint$type2.value) === 'email' && !/^\S+@\S+$/.test(value !== null && value !== void 0 ? value : '') || ((_constraint$type3 = constraint.type) === null || _constraint$type3 === void 0 ? void 0 : _constraint$type3.value) === 'url' && !isURL(value !== null && value !== void 0 ? value : '');
valueMissing = typeof value === 'undefined' || value === '';
}
if (constraint.maxLength) {
if (typeof value !== 'undefined' && value.length > constraint.maxLength.value) {
var _constraint$maxLength;
return {
badInput,
customError,
patternMismatch,
rangeOverflow,
rangeUnderflow,
stepMismatch,
tooLong,
tooShort,
typeMismatch,
valid: !patternMismatch && !rangeOverflow && !rangeUnderflow && !stepMismatch && !tooLong && !tooShort && !typeMismatch && !valueMissing,
valueMissing
};
}
return (_constraint$maxLength = constraint.maxLength.message) !== null && _constraint$maxLength !== void 0 ? _constraint$maxLength : "This field must be at most ".concat(constraint.maxLength.value, " characters");
}
}
function checkCustomValidity(value, validity, constraint) {
if (validity.valueMissing) {
var _constraint$required$, _constraint$required;
if (constraint.min) {
if (constraint.min.value instanceof Date && new Date(value !== null && value !== void 0 ? value : '') < constraint.min.value) {
var _constraint$min$messa;
return (_constraint$required$ = (_constraint$required = constraint.required) === null || _constraint$required === void 0 ? void 0 : _constraint$required.message) !== null && _constraint$required$ !== void 0 ? _constraint$required$ : null;
} else if (validity.tooShort) {
var _constraint$minLength, _constraint$minLength2;
return (_constraint$min$messa = constraint.min.message) !== null && _constraint$min$messa !== void 0 ? _constraint$min$messa : "This field must be later than ".concat(constraint.min.value.toISOString());
} else if (typeof constraint.min.value === 'number' && Number(value !== null && value !== void 0 ? value : '') < constraint.min.value) {
var _constraint$min$messa2;
return (_constraint$minLength = (_constraint$minLength2 = constraint.minLength) === null || _constraint$minLength2 === void 0 ? void 0 : _constraint$minLength2.message) !== null && _constraint$minLength !== void 0 ? _constraint$minLength : null;
} else if (validity.tooLong) {
var _constraint$maxLength, _constraint$maxLength2;
return (_constraint$min$messa2 = constraint.min.message) !== null && _constraint$min$messa2 !== void 0 ? _constraint$min$messa2 : "This field must be greater than or equal to ".concat(constraint.min.value);
}
}
return (_constraint$maxLength = (_constraint$maxLength2 = constraint.maxLength) === null || _constraint$maxLength2 === void 0 ? void 0 : _constraint$maxLength2.message) !== null && _constraint$maxLength !== void 0 ? _constraint$maxLength : null;
} else if (validity.stepMismatch) {
var _constraint$step$mess, _constraint$step;
if (constraint.max) {
if (typeof value !== 'undefined' && constraint.max.value instanceof Date && new Date(value) > constraint.max.value) {
var _constraint$max$messa;
return (_constraint$step$mess = (_constraint$step = constraint.step) === null || _constraint$step === void 0 ? void 0 : _constraint$step.message) !== null && _constraint$step$mess !== void 0 ? _constraint$step$mess : null;
} else if (validity.rangeUnderflow) {
var _constraint$min$messa, _constraint$min;
return (_constraint$max$messa = constraint.max.message) !== null && _constraint$max$messa !== void 0 ? _constraint$max$messa : "This field must be at earlier than ".concat(constraint.max.value.toISOString());
} else if (typeof value !== 'undefined' && typeof constraint.max.value === 'number' && Number(value) > constraint.max.value) {
var _constraint$max$messa2;
return (_constraint$min$messa = (_constraint$min = constraint.min) === null || _constraint$min === void 0 ? void 0 : _constraint$min.message) !== null && _constraint$min$messa !== void 0 ? _constraint$min$messa : null;
} else if (validity.rangeOverflow) {
var _constraint$max$messa, _constraint$max;
return (_constraint$max$messa2 = constraint.max.message) !== null && _constraint$max$messa2 !== void 0 ? _constraint$max$messa2 : "This field must be less than or equal to ".concat(constraint.max.value);
}
}
return (_constraint$max$messa = (_constraint$max = constraint.max) === null || _constraint$max === void 0 ? void 0 : _constraint$max.message) !== null && _constraint$max$messa !== void 0 ? _constraint$max$messa : null;
} else if (validity.typeMismatch || validity.badInput) {
var _constraint$type$mess, _constraint$type4;
if (constraint.step) ;
return (_constraint$type$mess = (_constraint$type4 = constraint.type) === null || _constraint$type4 === void 0 ? void 0 : _constraint$type4.message) !== null && _constraint$type$mess !== void 0 ? _constraint$type$mess : null;
} else if (validity.patternMismatch) {
if (!constraint.pattern) {
return null;
} else if (constraint.pattern.length === 1) {
var _constraint$pattern$;
if (constraint.type) {
switch (constraint.type.value) {
case 'email':
if (!/^\S+\@\S+$/.test(value !== null && value !== void 0 ? value : '')) {
var _constraint$type$mess;
return (_constraint$pattern$ = constraint.pattern[0].message) !== null && _constraint$pattern$ !== void 0 ? _constraint$pattern$ : null;
} else {
var _constraint$pattern$f, _constraint$pattern$f2;
return (_constraint$type$mess = constraint.type.message) !== null && _constraint$type$mess !== void 0 ? _constraint$type$mess : "This field must be a valid email";
}
break;
case 'url':
var isURL = value => {
try {
new URL(value);
return true;
} catch (_unused) {
return false;
}
};
if (!isURL(value !== null && value !== void 0 ? value : '')) {
var _constraint$type$mess2;
return (_constraint$type$mess2 = constraint.type.message) !== null && _constraint$type$mess2 !== void 0 ? _constraint$type$mess2 : "This field must be a valid URL";
}
break;
return (_constraint$pattern$f = (_constraint$pattern$f2 = constraint.pattern.find(pattern => pattern.value.test(value))) === null || _constraint$pattern$f2 === void 0 ? void 0 : _constraint$pattern$f2.message) !== null && _constraint$pattern$f !== void 0 ? _constraint$pattern$f : null;
}
} else {
return '';
}
if ((_constraint$pattern2 = constraint.pattern) !== null && _constraint$pattern2 !== void 0 && _constraint$pattern2.length) {
var _pattern = constraint.pattern.find(pattern => {
var match = value === null || value === void 0 ? void 0 : value.match(pattern.value);
return !match || value !== match[0];
});
if (_pattern) {
var _pattern$message;
return (_pattern$message = _pattern.message) !== null && _pattern$message !== void 0 ? _pattern$message : "This field must be a valid format";
}
}
return null;
}
function parse(payload, fieldsetCreator) {
var valueEntries = payload instanceof URLSearchParams || payload instanceof FormData ? payload : new URLSearchParams(payload);
var value = unflatten(valueEntries);
var fieldset = typeof fieldsetCreator === 'function' ? fieldsetCreator(value) : fieldsetCreator;
var values = Object.fromEntries(valueEntries);
var errorEntries = [];
for (var [name, field] of flatten(fieldset, f => typeof f[symbol] === 'function')) {
var constraint = getConstraint(field);
var _value3 = values[name];
var _message = validate(_value3, constraint);
if (_message) {
errorEntries.push([name, _message]);
}
}
return {
value,
error: errorEntries.length > 0 ? unflatten(errorEntries) : null
};
}
exports.checkCustomValidity = checkCustomValidity;
exports.draftUpdate = draftUpdate;
exports.f = f;
exports.getConstraint = getConstraint;
exports.isButtonElement = isButtonElement;
exports.isDirtyField = isDirtyField;
exports.getDraft = getDraft;
exports.isDirty = isDirty;
exports.isElement = isElement;
exports.isInputElement = isInputElement;
exports.isSelectElement = isSelectElement;
exports.isTextareaElement = isTextareaElement;
exports.isValidationConstraintSupported = isValidationConstraintSupported;
exports.parse = parse;
exports.shouldSkipValidate = shouldSkipValidate;

@@ -1,110 +0,112 @@

var attributesByType = {
// 'button': [],
checkbox: ['required'],
color: [],
date: ['required', 'minLength', 'maxLength', 'pattern'],
datetime: ['required', 'minLength', 'maxLength', 'pattern'],
'datetime-local': ['required', 'minLength', 'maxLength', 'pattern'],
email: ['required', 'minLength', 'maxLength', 'pattern'],
fieldset: ['multiple'],
file: ['required'],
hidden: [],
// 'image': [],
month: ['required', 'minLength', 'maxLength', 'pattern'],
number: ['required', 'minLength', 'maxLength', 'pattern'],
password: ['required', 'minLength', 'maxLength', 'pattern'],
radio: ['required'],
range: ['min', 'max', 'step'],
// 'reset': [],
search: ['required', 'minLength', 'maxLength', 'pattern'],
select: ['required'],
// 'submit': [],
tel: ['required', 'minLength', 'maxLength', 'pattern'],
text: ['required', 'minLength', 'maxLength', 'pattern'],
textarea: ['required', 'minLength', 'maxLength'],
time: ['required', 'minLength', 'maxLength', 'pattern'],
url: ['required', 'minLength', 'maxLength', 'pattern'],
week: ['required', 'minLength', 'maxLength', 'pattern']
};
var symbol = Symbol('constraints');
/**
*
*/
var symbol = Symbol('constraint');
function createField(type, message) {
var supportedAttributes = attributesByType[type];
var constraint = {
type: {
value: type,
message: message
}
};
var field = {
required(message) {
constraint.required = {
message
};
return field;
},
function configureF() {
function createField(tag, type, message) {
var constraint = {
tag
};
min(value, message) {
constraint.min = {
value,
if (type) {
constraint.type = {
value: type,
message
};
return field;
},
}
max(value, message) {
constraint.max = {
value,
message
};
return field;
},
return {
required(message) {
constraint.required = {
message
};
return this;
},
minLength(value, message) {
constraint.minLength = {
value,
message
};
return field;
},
min(value, message) {
constraint.min = {
value,
message
};
return this;
},
maxLength(value, message) {
constraint.maxLength = {
value,
message
};
return field;
},
max(value, message) {
constraint.max = {
value,
message
};
return this;
},
pattern(value, message) {
if (value.global || value.ignoreCase || value.multiline) {
console.warn("global, ignoreCase, and multiline flags are not supported on the pattern attribute");
} else {
var _constraint$pattern;
minLength(value, message) {
constraint.minLength = {
value,
message
};
return this;
},
constraint.pattern = ((_constraint$pattern = constraint.pattern) !== null && _constraint$pattern !== void 0 ? _constraint$pattern : []).concat({
maxLength(value, message) {
constraint.maxLength = {
value,
message
});
}
};
return this;
},
return field;
},
pattern(value, message) {
if (value.global || value.ignoreCase || value.multiline) {
console.warn("global, ignoreCase, and multiline flags are not supported on the pattern attribute");
} else {
var _constraint$pattern;
multiple(value) {
constraint.multiple = {
value,
message
};
return field;
},
constraint.pattern = ((_constraint$pattern = constraint.pattern) !== null && _constraint$pattern !== void 0 ? _constraint$pattern : []).concat({
value,
message
});
}
[symbol]: () => constraint
}; // @ts-ignore
return this;
},
return Object.fromEntries( // @ts-ignore
[symbol, ...supportedAttributes].map(key => [key, field[key]]));
multiple(value) {
constraint.multiple = {
value,
message
};
return this;
},
[symbol]: constraint
};
}
function input(type, message) {
// @ts-expect-error
return createField('input', type, message);
}
function select() {
return createField('select');
}
function textarea() {
return createField('textarea');
}
function fieldset() {
return createField('fieldset');
}
return {
input,
select,
textarea,
fieldset
};
}
/**
* Helpers for constructing the field constraints
* Helpers for constructing the field constraint based on the type
* @see https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Constraint_validation#validation-related_attributes

@@ -114,63 +116,38 @@ */

var f = {
// button: () => createField('button'),
checkbox: () => createField('checkbox'),
color: () => createField('color'),
date: () => createField('date'),
// datetime: () => createField('datetime'),
datetime: () => createField('datetime-local'),
// `datetime` is deprecated
email: message => createField('email', message),
fieldset: () => createField('fieldset'),
file: () => createField('file'),
hidden: () => createField('hidden'),
// image: () => createField('image'),
month: () => createField('month'),
number: message => createField('number', message),
password: () => createField('password'),
radio: () => createField('radio'),
range: () => createField('range'),
// reset: () => createField('reset'),
search: () => createField('search'),
select: () => createField('select'),
// submit: () => createField('submit'),
tel: () => createField('tel'),
text: () => createField('text'),
textarea: () => createField('textarea'),
time: () => createField('time'),
url: message => createField('url', message),
week: () => createField('week')
};
var f = configureF();
function getConstraint(field) {
return field[symbol]();
} // eslint-disable-next-line @typescript-eslint/no-explicit-any
if (typeof field[symbol] === 'undefined') {
throw new Error('Provided config is not a field; Please ensure only field object is used');
}
return field[symbol];
}
function isElement(element, tag) {
return !!element && element.tagName.toLowerCase() === tag;
}
function isInputElement(element) {
return isElement(element, 'input');
}
function isSelectElement(element) {
return isElement(element, 'select');
}
function isTextareaElement(element) {
return isElement(element, 'textarea');
}
function isButtonElement(element) {
return isElement(element, 'button');
}
function isDirtyField(element) {
function isDirty(element) {
if (isElement(element, 'form')) {
for (var el of element.elements) {
if (isDirty(el)) {
return true;
}
}
return false;
}
if (isElement(element, 'input') || isElement(element, 'textarea')) {
return element.value !== element.defaultValue;
} else if (isElement(element, 'select')) {
}
if (isElement(element, 'select')) {
var _Array$from$find;
return element.value !== ((_Array$from$find = Array.from(element.options).find(option => option.defaultSelected)) === null || _Array$from$find === void 0 ? void 0 : _Array$from$find.value);
} else {
return false;
}
return false;
}
function isValidationConstraintSupported(element) {
if (!isInputElement(element) && !isSelectElement(element) && !isTextareaElement(element)) {
if (!isElement(element, 'input') && !isElement(element, 'select') && !isElement(element, 'textarea')) {
return false;

@@ -182,5 +159,106 @@ }

function shouldSkipValidate(element) {
return isButtonElement(element) || isInputElement(element) ? element.formNoValidate : false;
return isElement(element, 'button') || isElement(element, 'input') ? element.formNoValidate : false;
}
function draftUpdate(name, index) {
return {
name: '__form-validity__',
value: [name].concat(typeof index === 'undefined' ? [] : ["".concat(index)]).join('|')
};
}
function getDraft(payload) {
var update = payload.get('__form-validity__');
if (!update) {
return null;
} // We are mutating the payload here
payload.delete('__form-validity__');
if (update instanceof File) {
throw new Error('What?');
}
var [name, indexString] = update.split('|');
var index = typeof indexString !== 'undefined' ? Number(indexString) : null;
return {
name,
index
};
}
function parse(payload, fieldsetCreator) {
var valueEntries = payload instanceof URLSearchParams || payload instanceof FormData ? payload : new URLSearchParams(payload);
var update = getDraft(valueEntries);
var value = unflatten(valueEntries);
if (update) {
var list = getItem(value, update.name);
if (!Array.isArray(list) || update.index !== null && isNaN(update.index)) {
throw new Error('Oops');
}
if (update.index !== null) {
list.splice(update.index, 1);
} else {
list.push({});
}
}
var fieldset = typeof fieldsetCreator === 'function' ? fieldsetCreator(value) : fieldsetCreator;
var valueByName = Object.fromEntries(valueEntries);
var errorEntries = [];
if (!update) {
for (var [name, field] of flatten(fieldset, f => typeof f[symbol] !== 'undefined')) {
var constraint = getConstraint(field);
var _value = valueByName[name];
var validity = validate(_value, constraint);
var _message = checkCustomValidity(_value, validity, constraint);
if (_message) {
errorEntries.push([name, _message]);
}
}
}
return {
value,
error: errorEntries.length > 0 ? unflatten(errorEntries) : null,
isDraft: update !== null
};
}
/**
* Helpers
*/
var pattern = /(\w+)\[(\d+)\]/;
function getPaths(key) {
return key.split('.').flatMap(key => {
var matches = pattern.exec(key);
if (!matches) {
return key;
}
return [matches[1], Number(matches[2])];
});
}
function getItem(obj, key, defaultValue) {
var target = obj;
for (var path of getPaths(key)) {
if (typeof target[path] === 'undefined') {
return defaultValue;
}
target = target[path];
}
return target;
}
function flatten(item, isLeaf) {

@@ -197,4 +275,4 @@ var prefix = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';

} else {
for (var [key, _value] of Object.entries(item)) {
entries.push(...flatten(_value, isLeaf, prefix ? "".concat(prefix, ".").concat(key) : key));
for (var [key, _value2] of Object.entries(item)) {
entries.push(...flatten(_value2, isLeaf, prefix ? "".concat(prefix, ".").concat(key) : key));
}

@@ -207,15 +285,6 @@ }

function unflatten(entries) {
var pattern = /(\w+)\[(\d+)\]/;
var result = {};
for (var [key, _value2] of entries) {
var paths = key.split('.').flatMap(key => {
var matches = pattern.exec(key);
if (!matches) {
return key;
}
return [matches[1], Number(matches[2])];
});
for (var [key, _value3] of entries) {
var paths = getPaths(key);
var length = paths.length;

@@ -229,3 +298,3 @@ var lastIndex = length - 1;

var next = paths[index + 1];
var newValue = _value2;
var newValue = _value3;

@@ -247,129 +316,102 @@ if (index != lastIndex) {

function validate(value, constraint) {
var _constraint$pattern2;
var badInput = false;
var customError = false;
var patternMismatch = false;
var rangeOverflow = false;
var rangeUnderflow = false;
var stepMismatch = false;
var tooLong = false;
var tooShort = false;
var typeMismatch = false;
var valueMissing = false;
if (value instanceof File) {
return 'File is not supported yet';
}
var _constraint$type;
if (constraint.required) {
if (typeof value === 'undefined' || value === '') {
var _constraint$required$;
typeMismatch = ((_constraint$type = constraint.type) === null || _constraint$type === void 0 ? void 0 : _constraint$type.value) !== 'file';
} else {
var _constraint$pattern$s, _constraint$pattern2, _constraint$type2, _constraint$type3;
return (_constraint$required$ = constraint.required.message) !== null && _constraint$required$ !== void 0 ? _constraint$required$ : 'This field is required';
}
}
var isURL = value => {
try {
new URL(value);
return true;
} catch (_unused) {
return false;
}
};
if (constraint.minLength) {
if (typeof value === 'undefined' || value.length < constraint.minLength.value) {
var _constraint$minLength;
return (_constraint$minLength = constraint.minLength.message) !== null && _constraint$minLength !== void 0 ? _constraint$minLength : "This field must be at least ".concat(constraint.minLength.value, " characters");
}
patternMismatch = (_constraint$pattern$s = (_constraint$pattern2 = constraint.pattern) === null || _constraint$pattern2 === void 0 ? void 0 : _constraint$pattern2.some(pattern => {
var match = value === null || value === void 0 ? void 0 : value.match(pattern.value);
return !match || value !== match[0];
})) !== null && _constraint$pattern$s !== void 0 ? _constraint$pattern$s : false;
rangeOverflow = constraint.max ? typeof value !== 'undefined' && constraint.max.value instanceof Date && new Date(value) > constraint.max.value || typeof value !== 'undefined' && typeof constraint.max.value === 'number' && Number(value) > constraint.max.value : false;
rangeUnderflow = constraint.min ? constraint.min.value instanceof Date && new Date(value !== null && value !== void 0 ? value : '') < constraint.min.value || typeof constraint.min.value === 'number' && Number(value !== null && value !== void 0 ? value : '') < constraint.min.value : false;
tooLong = constraint.maxLength ? typeof value !== 'undefined' && value.length > constraint.maxLength.value : false;
tooShort = constraint.minLength ? typeof value === 'undefined' || value.length < constraint.minLength.value : false;
typeMismatch = ((_constraint$type2 = constraint.type) === null || _constraint$type2 === void 0 ? void 0 : _constraint$type2.value) === 'email' && !/^\S+@\S+$/.test(value !== null && value !== void 0 ? value : '') || ((_constraint$type3 = constraint.type) === null || _constraint$type3 === void 0 ? void 0 : _constraint$type3.value) === 'url' && !isURL(value !== null && value !== void 0 ? value : '');
valueMissing = typeof value === 'undefined' || value === '';
}
if (constraint.maxLength) {
if (typeof value !== 'undefined' && value.length > constraint.maxLength.value) {
var _constraint$maxLength;
return {
badInput,
customError,
patternMismatch,
rangeOverflow,
rangeUnderflow,
stepMismatch,
tooLong,
tooShort,
typeMismatch,
valid: !patternMismatch && !rangeOverflow && !rangeUnderflow && !stepMismatch && !tooLong && !tooShort && !typeMismatch && !valueMissing,
valueMissing
};
}
return (_constraint$maxLength = constraint.maxLength.message) !== null && _constraint$maxLength !== void 0 ? _constraint$maxLength : "This field must be at most ".concat(constraint.maxLength.value, " characters");
}
}
function checkCustomValidity(value, validity, constraint) {
if (validity.valueMissing) {
var _constraint$required$, _constraint$required;
if (constraint.min) {
if (constraint.min.value instanceof Date && new Date(value !== null && value !== void 0 ? value : '') < constraint.min.value) {
var _constraint$min$messa;
return (_constraint$required$ = (_constraint$required = constraint.required) === null || _constraint$required === void 0 ? void 0 : _constraint$required.message) !== null && _constraint$required$ !== void 0 ? _constraint$required$ : null;
} else if (validity.tooShort) {
var _constraint$minLength, _constraint$minLength2;
return (_constraint$min$messa = constraint.min.message) !== null && _constraint$min$messa !== void 0 ? _constraint$min$messa : "This field must be later than ".concat(constraint.min.value.toISOString());
} else if (typeof constraint.min.value === 'number' && Number(value !== null && value !== void 0 ? value : '') < constraint.min.value) {
var _constraint$min$messa2;
return (_constraint$minLength = (_constraint$minLength2 = constraint.minLength) === null || _constraint$minLength2 === void 0 ? void 0 : _constraint$minLength2.message) !== null && _constraint$minLength !== void 0 ? _constraint$minLength : null;
} else if (validity.tooLong) {
var _constraint$maxLength, _constraint$maxLength2;
return (_constraint$min$messa2 = constraint.min.message) !== null && _constraint$min$messa2 !== void 0 ? _constraint$min$messa2 : "This field must be greater than or equal to ".concat(constraint.min.value);
}
}
return (_constraint$maxLength = (_constraint$maxLength2 = constraint.maxLength) === null || _constraint$maxLength2 === void 0 ? void 0 : _constraint$maxLength2.message) !== null && _constraint$maxLength !== void 0 ? _constraint$maxLength : null;
} else if (validity.stepMismatch) {
var _constraint$step$mess, _constraint$step;
if (constraint.max) {
if (typeof value !== 'undefined' && constraint.max.value instanceof Date && new Date(value) > constraint.max.value) {
var _constraint$max$messa;
return (_constraint$step$mess = (_constraint$step = constraint.step) === null || _constraint$step === void 0 ? void 0 : _constraint$step.message) !== null && _constraint$step$mess !== void 0 ? _constraint$step$mess : null;
} else if (validity.rangeUnderflow) {
var _constraint$min$messa, _constraint$min;
return (_constraint$max$messa = constraint.max.message) !== null && _constraint$max$messa !== void 0 ? _constraint$max$messa : "This field must be at earlier than ".concat(constraint.max.value.toISOString());
} else if (typeof value !== 'undefined' && typeof constraint.max.value === 'number' && Number(value) > constraint.max.value) {
var _constraint$max$messa2;
return (_constraint$min$messa = (_constraint$min = constraint.min) === null || _constraint$min === void 0 ? void 0 : _constraint$min.message) !== null && _constraint$min$messa !== void 0 ? _constraint$min$messa : null;
} else if (validity.rangeOverflow) {
var _constraint$max$messa, _constraint$max;
return (_constraint$max$messa2 = constraint.max.message) !== null && _constraint$max$messa2 !== void 0 ? _constraint$max$messa2 : "This field must be less than or equal to ".concat(constraint.max.value);
}
}
return (_constraint$max$messa = (_constraint$max = constraint.max) === null || _constraint$max === void 0 ? void 0 : _constraint$max.message) !== null && _constraint$max$messa !== void 0 ? _constraint$max$messa : null;
} else if (validity.typeMismatch || validity.badInput) {
var _constraint$type$mess, _constraint$type4;
if (constraint.step) ;
return (_constraint$type$mess = (_constraint$type4 = constraint.type) === null || _constraint$type4 === void 0 ? void 0 : _constraint$type4.message) !== null && _constraint$type$mess !== void 0 ? _constraint$type$mess : null;
} else if (validity.patternMismatch) {
if (!constraint.pattern) {
return null;
} else if (constraint.pattern.length === 1) {
var _constraint$pattern$;
if (constraint.type) {
switch (constraint.type.value) {
case 'email':
if (!/^\S+\@\S+$/.test(value !== null && value !== void 0 ? value : '')) {
var _constraint$type$mess;
return (_constraint$pattern$ = constraint.pattern[0].message) !== null && _constraint$pattern$ !== void 0 ? _constraint$pattern$ : null;
} else {
var _constraint$pattern$f, _constraint$pattern$f2;
return (_constraint$type$mess = constraint.type.message) !== null && _constraint$type$mess !== void 0 ? _constraint$type$mess : "This field must be a valid email";
}
break;
case 'url':
var isURL = value => {
try {
new URL(value);
return true;
} catch (_unused) {
return false;
}
};
if (!isURL(value !== null && value !== void 0 ? value : '')) {
var _constraint$type$mess2;
return (_constraint$type$mess2 = constraint.type.message) !== null && _constraint$type$mess2 !== void 0 ? _constraint$type$mess2 : "This field must be a valid URL";
}
break;
return (_constraint$pattern$f = (_constraint$pattern$f2 = constraint.pattern.find(pattern => pattern.value.test(value))) === null || _constraint$pattern$f2 === void 0 ? void 0 : _constraint$pattern$f2.message) !== null && _constraint$pattern$f !== void 0 ? _constraint$pattern$f : null;
}
} else {
return '';
}
if ((_constraint$pattern2 = constraint.pattern) !== null && _constraint$pattern2 !== void 0 && _constraint$pattern2.length) {
var _pattern = constraint.pattern.find(pattern => {
var match = value === null || value === void 0 ? void 0 : value.match(pattern.value);
return !match || value !== match[0];
});
if (_pattern) {
var _pattern$message;
return (_pattern$message = _pattern.message) !== null && _pattern$message !== void 0 ? _pattern$message : "This field must be a valid format";
}
}
return null;
}
function parse(payload, fieldsetCreator) {
var valueEntries = payload instanceof URLSearchParams || payload instanceof FormData ? payload : new URLSearchParams(payload);
var value = unflatten(valueEntries);
var fieldset = typeof fieldsetCreator === 'function' ? fieldsetCreator(value) : fieldsetCreator;
var values = Object.fromEntries(valueEntries);
var errorEntries = [];
for (var [name, field] of flatten(fieldset, f => typeof f[symbol] === 'function')) {
var constraint = getConstraint(field);
var _value3 = values[name];
var _message = validate(_value3, constraint);
if (_message) {
errorEntries.push([name, _message]);
}
}
return {
value,
error: errorEntries.length > 0 ? unflatten(errorEntries) : null
};
}
export { f, getConstraint, isButtonElement, isDirtyField, isElement, isInputElement, isSelectElement, isTextareaElement, isValidationConstraintSupported, parse, shouldSkipValidate };
export { checkCustomValidity, draftUpdate, f, getConstraint, getDraft, isDirty, isElement, isValidationConstraintSupported, parse, shouldSkipValidate };

@@ -5,3 +5,3 @@ {

"license": "MIT",
"version": "0.0.2",
"version": "0.0.3",
"main": "index.js",

@@ -8,0 +8,0 @@ "module": "module/index.js",

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc