@mozaic-ds/vue-3
Version:
Vue.js implementation of Mozaic Design System
133 lines (119 loc) • 3.46 kB
JavaScript
/** create a sort function to pass into the sort function of the array.
* The objective is to be able to sort on several fields ordered according to the same order as the parameter.
* @example
* array.sort(orderedArraySorted([{
* fieldExpr: 'prop1'
* },{
* fieldExpr: 'prop2.propA',
* sortOrder: 'desc' }]
* ))
* // the array is order by 'prop1', then by 'prop2.propA'.
* */
export function orderedArraySorted(properties) {
const compareFn = function (left, right, sortOrder = 'asc') {
const direction = sortOrder === 'asc' ? 1 : -1;
return (left > right ? 1 : left < right ? -1 : 0) * direction;
};
return function (item1, item2) {
return properties
.map((property) => {
return compareFn(
getObjectValueByPath(item1, property.fieldExpr),
getObjectValueByPath(item2, property.fieldExpr),
property.sortOrder
);
})
.reduceRight((left, right) => {
return right || left;
});
};
}
/** Test if value is a Promise function. */
export function isPromise(value) {
return value.toString().includes('Promise');
}
/** Test if object a is equal to object b. */
export function deepEqual(a, b) {
if (a === b) {
return true;
}
if (a instanceof Date && b instanceof Date && a.getTime() !== b.getTime()) {
// If the values are Date, compare them as timestamps
return false;
}
if (a !== Object(a) || b !== Object(b)) {
// If the values aren't objects, they were already checked for equality
return false;
}
const props = Object.keys(a);
if (props.length !== Object.keys(b).length) {
// Different number of props, don't bother to check
return false;
}
return props.every((p) => deepEqual(a[p], b[p]));
}
/** Get value of an object by string path.
* @example
* let obj = {
* prop1: {
* propA: 'test'
* }
* }
* let result = getObjectValueByPath(obj, 'prop1.propA')
* // result is equal to 'test'.
*/
export function getObjectValueByPath(obj, path) {
// credit: http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key#comment55278413_6491621
if (obj == null || !path || typeof path !== 'string') {
return null;
}
if (obj[path] !== undefined) {
return obj[path];
}
path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
path = path.replace(/^\./, ''); // strip a leading dot
return getNestedValue(obj, path.split('.'));
}
function getNestedValue(obj, path) {
const last = path.length - 1;
if (last < 0) {
return obj;
}
for (let i = 0; i < last; i++) {
if (obj == null) {
return null;
}
obj = obj[path[i]];
}
return obj[path[last]];
}
/** Convert string value to unit (Default: px). */
export function convertToUnit(str, unit = 'px') {
if (str == null || str === '') {
return undefined;
} else if (isNaN(+str)) {
return String(str);
} else {
return `${Number(str)}${unit}`;
}
}
/** Parse value as object used by bindabled class property. */
export function parseClasses(value, obj) {
if (typeof value === 'function') {
return parseClasses(value(obj));
} else if (Array.isArray(value)) {
return value.reduce(
(acc, v) => ({
...acc,
[v]: true,
}),
{}
);
} else if (typeof value === 'object') {
return value;
} else if (value != null) {
return { [value]: true };
} else {
return null;
}
}