1 import tinycolor from 'tinycolor2';
9 (event?: Event, error?: string | Event): void;
12 const loadScriptHelper = ({ path, integrity }: ScriptInfo, cb: Callback) => {
13 const script = document.createElement('script');
17 script.integrity = integrity;
19 script.onload = (e) => {
23 script.onerror = (e) => cb(undefined, e);
25 document.head.appendChild(script);
28 export const loadScript = (path: string, integrity?: string) => {
29 return new Promise<Event>((resolve, reject) => {
30 loadScriptHelper({ path, integrity }, (event, error) => {
31 if (error || !event) {
34 return resolve(event);
40 * Returns whether the element is a node.
41 * See {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType}
43 export const isElement = (node: Node | null): node is Element => Boolean(node && node.nodeType === 1);
46 * Returns the node if it's an element or the parent element if not
48 export const getElement = (node: Node | null) => (isElement(node) ? (node as Element) : node?.parentElement || null);
51 * From https://stackoverflow.com/a/42543908
53 export const getScrollParent = (element: HTMLElement | null | undefined, includeHidden = false) => {
58 const style = getComputedStyle(element);
59 const excludeStaticParent = style.position === 'absolute';
60 const overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/;
62 if (style.position === 'fixed') {
66 for (let parent = element.parentElement; parent; parent = parent.parentElement) {
67 const style = getComputedStyle(parent);
68 if (excludeStaticParent && style.position === 'static') {
71 if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) {
80 * get computed root font size, to manage properly some elements in pixels
83 let rootFontSizeCache: number | undefined = undefined;
85 const getRootFontSize = () => {
86 return parseFloat(window.getComputedStyle(document.querySelector('html') as Element).getPropertyValue('font-size'));
89 export const rootFontSize = (reset?: boolean) => {
90 if (rootFontSizeCache === undefined || reset === true) {
91 rootFontSizeCache = getRootFontSize();
93 return rootFontSizeCache;
97 * Firefox <58 does not support block: 'nearest' and just throws
99 export const scrollIntoView = (element: HTMLElement | undefined | null, extra?: boolean | ScrollIntoViewOptions) => {
104 element.scrollIntoView(extra);
105 // eslint-disable-next-line no-empty
109 export const hasChildren = (node?: ChildNode) => {
110 return node && node.childNodes && node.childNodes.length > 0;
113 export const getMaxDepth = (node: ChildNode) => {
115 for (const child of node.childNodes) {
116 if (hasChildren(child)) {
117 const depth = getMaxDepth(child);
118 if (depth > maxDepth) {
126 export const checkContrast = (node: ChildNode, window: Window): boolean => {
127 if (node.nodeType === Node.ELEMENT_NODE) {
128 const style = window.getComputedStyle(node as Element);
129 const color = style.color ? tinycolor(style.color) : tinycolor('#fff');
130 const background = style.backgroundColor ? tinycolor(style.backgroundColor) : tinycolor('#000');
132 (color?.isDark() && (background?.isLight() || background?.getAlpha() === 0)) ||
133 (color?.isLight() && background?.isDark());
139 return [...node.childNodes].every((node) => checkContrast(node, window));
142 export const getIsEventModified = (event: MouseEvent) => {
143 return event.metaKey || event.altKey || event.ctrlKey || event.shiftKey;
146 export const isVisibleOnScreen = (element: HTMLElement | null) => {
151 var rect = element.getBoundingClientRect();
152 var viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight);
153 return !(rect.bottom < 0 || rect.top - viewHeight >= 0);
156 export const isVisible = (element: HTMLElement | null) => {
161 const style = getComputedStyle(element);
162 const { offsetWidth, offsetHeight } = element;
163 const { width, height } = element.getBoundingClientRect();
165 if (style.display === 'none') {
169 if (style.visibility !== 'visible') {
173 if ((style.opacity as any) === 0) {
177 if (offsetWidth + offsetHeight + height + width === 0) {
184 export const parseStringToDOM = (content: string, type: DOMParserSupportedType = 'text/html') => {
185 const parser = new DOMParser();
186 return parser.parseFromString(content, type);