UNPKG

@engie-group/fluid-design-system-react

Version:

Fluid Design System React

153 lines (134 loc) 4.57 kB
import React from 'react'; const isUndefinedOrNull = (value: unknown): value is null | undefined => { return typeof value === 'undefined' || value === null; }; /** * Generates a string from arguments that can be a string, number, array or objects with {key: value} where key is a class and value is a boolean */ const classNames = (...args: unknown[]): string => { const classes = []; for (const arg of args) { if (!arg) { continue; } const argType = typeof arg; if (argType === 'string' || argType === 'number') { classes.push(arg); } else if (Array.isArray(arg)) { if (arg.length) { const inner = Utils.classNames.apply(null, arg); if (inner) { classes.push(inner); } } } else if (argType === 'object') { if (arg.toString === Object.prototype.toString) { for (const key in arg) { // @ts-expect-error arg is of type unknown if (Object.prototype.hasOwnProperty.call(arg, key) && arg[key]) { classes.push(key); } } } else { classes.push(arg.toString()); } } } return classes.join(' '); }; const coerceFunction = (func: (...args: unknown[]) => unknown) => { if (!isUndefinedOrNull(func) && typeof func === 'function') { return func; } else { return null; } }; const mergeRefs = <T = unknown>( refs: Array<React.MutableRefObject<T> | React.LegacyRef<T>> ): React.RefCallback<T> => { return (value) => { refs.forEach((ref) => { if (typeof ref === 'function') { ref(value); } else if (ref != null) { (ref as React.MutableRefObject<T | null>).current = value; } }); }; }; const normalizeString = (text: string) => { return text.normalize('NFD').replace(/[\u0300-\u036f]/g, ''); }; const normalizeAndSearchInText = (text: string, search: string): boolean => { if (Utils.isUndefinedOrNull(text) || Utils.isUndefinedOrNull(search)) { return false; } const normalizedText = Utils.normalizeString(text); // removed in 2.13.0: `normalizedSearch` used to filter out (, ) and \ through `.replace(/\(|\)|\\/gi, '');` const normalizedSearch = Utils.normalizeString(search); const regExp = new RegExp(Utils.escapeRegExp(normalizedSearch), 'gi'); return normalizedText.search(regExp) !== -1; }; // Escape special characters in a string (so regex behave properly) const escapeRegExp = (string: string): string => { return string.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&'); }; const highlightTextAsHtml = ( content: string, textToHighlight: string, caseSensitive = false, escapeAccents = true, openingTag = '<mark class="nj-highlight">', closingTag = '</mark>' ): string => { const regexFlags = caseSensitive ? 'g' : 'gi'; // Escape the textToHighlight to handle special characters const escapedTextToHighlight = Utils.escapeRegExp(textToHighlight); let innerHtml: string; if (Utils.isUndefinedOrNull(textToHighlight)) { innerHtml = content; } else { if (escapeAccents) { const regExp = new RegExp(Utils.normalizeString(escapedTextToHighlight), regexFlags); const matches = Utils.normalizeString(content).matchAll(regExp); let finalText = content; let buffer = 0; if (!Utils.isUndefinedOrNull(matches)) { for (const match of matches) { const updatedIndex = buffer + match.index; const textBeforeOccurrence = finalText.slice(0, updatedIndex); const occurrence = finalText.slice(updatedIndex, updatedIndex + textToHighlight.length); const textAfterOccurrence = finalText.slice( updatedIndex + textToHighlight.length, finalText.length ); finalText = `${textBeforeOccurrence}${openingTag}${occurrence}${closingTag}${textAfterOccurrence}`; buffer = buffer + openingTag.length + closingTag.length; } } innerHtml = finalText; } else { const regExp = new RegExp(escapedTextToHighlight, regexFlags); innerHtml = content.replace(regExp, `${openingTag}$&${closingTag}`); } } return innerHtml; }; const omit = <T extends NonNullable<unknown>, K extends keyof T>(obj: T, ...keys: K[]) => { return Object.fromEntries( Object.entries(obj).filter(([key]) => { return !keys.includes(key as K); }) ) as Omit<T, K>; }; export const Utils = { isUndefinedOrNull, classNames, coerceFunction, mergeRefs, normalizeString, normalizeAndSearchInText, escapeRegExp, highlightTextAsHtml, omit };