@conform-to/dom
Version:
A set of opinionated helpers built on top of the Constraint Validation API
116 lines (107 loc) • 3.35 kB
JavaScript
function invariant(expectedCondition, message) {
if (!expectedCondition) {
throw new Error(message);
}
}
function generateId() {
return (Date.now() * Math.random()).toString(36);
}
function clone(data) {
return JSON.parse(JSON.stringify(data));
}
/**
* Check if the value is a plain object
*/
function isPlainObject(obj) {
return !!obj && obj.constructor === Object && Object.getPrototypeOf(obj) === Object.prototype;
}
/**
* A utility function that performs a deep equality check between two values.
* It handles plain objects, arrays, and primitive values only.
*/
function deepEqual(left, right) {
if (Object.is(left, right)) {
return true;
}
if (left == null || right == null) {
return false;
}
// Compare plain objects
if (isPlainObject(left) && isPlainObject(right)) {
var prevKeys = Object.keys(left);
var nextKeys = Object.keys(right);
if (prevKeys.length !== nextKeys.length) {
return false;
}
for (var key of prevKeys) {
if (!Object.prototype.hasOwnProperty.call(right, key) || !deepEqual(left[key], right[key])) {
return false;
}
}
return true;
}
// Compare arrays
if (Array.isArray(left) && Array.isArray(right)) {
if (left.length !== right.length) {
return false;
}
for (var i = 0; i < left.length; i++) {
if (!deepEqual(left[i], right[i])) {
return false;
}
}
return true;
}
return false;
}
/*
* Removes File object from the FormValue.
* Used to avoid serialzing/sending File object back to the client.
*/
function stripFiles(value) {
var json = JSON.stringify(value, (_, value) => {
// If the current value is a File, return undefined to omit it
if (typeof File !== 'undefined' && value instanceof File) {
return undefined;
}
return value;
});
return JSON.parse(json);
}
/**
* Helper to get readable type name for error messages
*/
function getTypeName(value) {
if (value === null) return 'null';
if (Array.isArray(value)) return 'Array';
if (typeof value === 'object') {
var _value$constructor$na, _value$constructor;
return (_value$constructor$na = (_value$constructor = value.constructor) === null || _value$constructor === void 0 ? void 0 : _value$constructor.name) !== null && _value$constructor$na !== void 0 ? _value$constructor$na : 'Object';
}
return typeof value;
}
/**
* Combines multiple regex patterns into a single HTML pattern attribute.
*
* This is done by putting each input pattern into a lookahead assertion
* and stripping all flags.
*
* Returns undefined if any pattern is case-insensitive, since transforming
* it to a case-sensitive pattern is a non-trivial operation.
*
* Example: [/[A-Z]/, /[0-9]/] -> '^(?=.*(?:[A-Z]))(?=.*(?:[0-9])).*$'
*/
function serializeHtmlPattern(pattern) {
var patterns = Array.isArray(pattern) ? pattern : [pattern];
if (patterns.length === 0 || patterns.some(p => p.flags.includes('i'))) {
return undefined;
}
var serializedPattern = "^".concat(patterns.map(p => "(?=.*(?:".concat(p.source, "))")).join(''), ".*$");
try {
new RegExp(serializedPattern, 'v');
} catch (_unused) {
return undefined;
}
return serializedPattern;
}
export { clone, deepEqual, generateId, getTypeName, invariant, isPlainObject, serializeHtmlPattern, stripFiles };