@aws-amplify/ui
Version:
`@aws-amplify/ui` contains low-level logic & styles for stand-alone usage or re-use in framework-specific implementations.
258 lines (256 loc) • 8.27 kB
JavaScript
/**
* @deprecated - will be removed in a future major version
*
* Some libraries may not follow Node ES module spec and could be loaded as CommonJS modules,
* To ensure the interoperability between ESM and CJS, modules from those libraries have to be loaded via namespace import
* And sanitized by the function below because unlike ESM namespace, CJS namespace set `module.exports` object on the `default` key
* https://nodejs.org/api/esm.html#interoperability-with-commonjs
*/
const sanitizeNamespaceImport = (namespaceModule) => {
const sanitizedNamespaceModule = { default: undefined, ...namespaceModule };
return sanitizedNamespaceModule.default ?? sanitizedNamespaceModule;
};
/**
* Checks if `value` is an Object (non-primitive, non-array, non-function)
* Will return false for Arrays and functions
*
*
* @param {unknown} value The value to check
* @returns {boolean} Returns `true` if `value` is an object, `false` otherwise
*/
function isObject(value) {
return value != null && !Array.isArray(value) && typeof value === 'object';
}
/**
* Checks if `value` is a string primitive or object
*
* @param {unknown} value The value to check
* @returns {boolean} Returns `true` if `value` is a string, `false` otherwise
*/
function isString(value) {
return (typeof value === 'string' ||
(typeof value === 'object' &&
Object.prototype.toString.call(value) === '[object String]'));
}
/**
* Checks if `value` is a Map
*
* @param {unknown} value The value to check
* @returns {boolean} Returns `true` if `value` is a Map, `false` otherwise
*/
function isMap(value) {
return (isObject(value) && Object.prototype.toString.call(value) === '[object Map]');
}
/**
* Checks if `value` is a Set
*
* @param {unknown} value The value to check
* @returns {boolean} Returns `true` if `value` is a Set, `false` otherwise
*/
function isSet(value) {
return (isObject(value) && Object.prototype.toString.call(value) === '[object Set]');
}
/**
* Checks if `value` is undefined
*
* @param {unknown} value The value to check
* @returns {boolean} Returns `true` if `value` is undefined, `false` otherwise
*/
function isUndefined(value) {
return value === undefined;
}
/**
* Checks if `value` is nullish
*
* @param {unknown} value The value to check
* @returns {boolean} Returns `true` if `value` is nullish, `false` otherwise
*/
function isNil(value) {
return value == null;
}
/**
* Checks if `value` is empty
*
* @param {unknown} value The value to check
* @returns {boolean} Returns `true` if `value` is empty, `false` otherwise
*/
function isEmpty(value) {
if (value === null || value === undefined)
return true;
if (isObject(value) && (isMap(value) || isSet(value))) {
return !value.size;
}
if (isObject(value) && (isString(value) || Array.isArray(value))) {
return !value.length;
}
for (const key in value) {
if (has(value, key)) {
return false;
}
}
return true;
}
/**
* Checks if `value` is an empty array
*
* @param {unknown} value The value to check
* @returns {boolean} Returns `true` if `value` is a empty, `false` otherwise
*/
function isEmptyArray(value) {
return Array.isArray(value) && isEmpty(value);
}
/**
* Checks if all members of the `values` param are empty arrays
*
* @param {unknown} value The values to check
* @returns {boolean} Returns `true` if all members of `values` are empty, `false` otherwise
*/
function areEmptyArrays(...values) {
return values.every(isEmptyArray);
}
/**
* Checks if `value` is an empty object
*
* @param {unknown} value The value to check
* @returns {boolean} Returns `true` if `value` is empty, `false` otherwise
*/
function isEmptyObject(value) {
return isObject(value) && isEmpty(value);
}
/**
* Checks if all members of the `values` param are empty objects
*
* @param {unknown} values The values to check
* @returns {boolean} Returns `true` if all members of the `values` param are empty, `false` otherwise
*/
function areEmptyObjects(...values) {
return values.every(isEmptyObject);
}
/**
* Capitalizes `value` and its return type
*
* @param {string} value string to capitalize
* @returns {string} capitalized string
*/
function capitalize(value) {
return (isString(value) ? value.charAt(0).toUpperCase() + value.slice(1) : '');
}
/**
* Checks if `key` is a direct property of `value`
*
* @param {unknown} value `object` potentially containing property
* @param {string} key property key
* @returns whether `key` param is a property of the `obj` param
*/
function has(value, key) {
return value != null && Object.prototype.hasOwnProperty.call(value, key);
}
/**
* Checks if `value` is a function
*
* @param {unknown} value param to check
* @returns {boolean} whether `value` is a function
*/
function isFunction(value) {
return typeof value === 'function';
}
/**
* This helper function creates modifier class names that are used for our flat BEM styling
* it takes in a base and modifier and returns the modified class if a modifier was passed in and null otherwise
* @param base The base class of the output
* @param modifier The modifier to add onto the base
* @returns the modified class name or empty string
*/
const classNameModifier = (base, modifier) => {
return modifier ? `${base}--${modifier}` : '';
};
/**
* This helper function creates modified class names that are used for our flat BEM styling
* it takes in a base, modifier, and flag and returns the modified class name if the flag is true and null if the flag is false
* @param base
* @param modifier
* @param flag
* @returns the modified class name or empty string
*/
const classNameModifierByFlag = (base, modifier, flag) => {
return flag ? `${base}--${modifier}` : '';
};
/**
* Similar to `Array.join`, with an optional callback/template param
* for formatting returned string values
*
* @param {string[]} values string array
* @param {(value: string) => string} template callback format param
* @returns formatted string array
*/
function templateJoin(values, template) {
return values.reduce((acc, curr, index) => `${acc}${isString(curr) ? template(curr, index, values) : ''}`, '');
}
/**
* A function that does nothing
*
* @param {any[]} _ accepts any parameters
* @returns nothing
*/
function noop(..._) {
return;
}
/**
* @param {string} groupName name of group
* @param events string values related to group
*/
function groupLog(groupName, ...events) {
const hasEvents = !!events?.length;
if (hasEvents) {
// eslint-disable-next-line no-console
console.groupCollapsed(groupName);
events?.forEach((event) => {
// eslint-disable-next-line no-console
console.log(event);
});
// eslint-disable-next-line no-console
console.groupEnd();
}
else {
// eslint-disable-next-line no-console
console.log(groupName);
}
}
/**
* Splits an object into 2 objects based on a predicate
*
* @param {object} obj an object to split into two
* @param {function} predicate function to determin where an element should go
* @returns
*/
function splitObject(obj, predicate) {
const left = {};
const right = {};
Object.entries(obj).forEach(([key, value]) => {
if (predicate(key)) {
left[key] = value;
}
else {
right[key] = value;
}
});
return [left, right];
}
const cloneDeep = (obj) => {
if (obj === null || obj === undefined || typeof obj !== 'object') {
return obj;
}
if (obj instanceof Array) {
return obj.reduce((arr, item, i) => {
arr[i] = cloneDeep(item);
return arr;
}, []);
}
if (obj instanceof Object) {
return Object.keys(obj || {}).reduce((cpObj, key) => {
cpObj[key] = cloneDeep(obj[key]);
return cpObj;
}, {});
}
};
export { areEmptyArrays, areEmptyObjects, capitalize, classNameModifier, classNameModifierByFlag, cloneDeep, groupLog, has, isEmpty, isEmptyObject, isFunction, isMap, isNil, isObject, isSet, isString, isUndefined, noop, sanitizeNamespaceImport, splitObject, templateJoin };