UNPKG

@freshworks/crayons

Version:
254 lines (253 loc) 6.96 kB
export function format(first, middle, last) { return ((first || '') + (middle ? ` ${middle}` : '') + (last ? ` ${last}` : '')); } /* tslint:enable */ export const watchForOptions = (containerEl, tagName, onChange) => { const mutation = new MutationObserver((mutationList) => { onChange(getSelectedOption(mutationList, tagName)); }); mutation.observe(containerEl, { childList: true, subtree: true, }); return mutation; }; const getSelectedOption = (mutationList, tagName) => { let newOption; mutationList.forEach((mut) => { // tslint:disable-next-line: prefer-for-of for (let i = 0; i < mut.addedNodes.length; i++) { newOption = findCheckedOption(mut.addedNodes[i], tagName) || newOption; } }); return newOption; }; export const findCheckedOption = (el, tagName) => { if (el.nodeType !== 1) { return undefined; } const options = el.tagName === tagName.toUpperCase() ? [el] : Array.from(el.querySelectorAll(tagName)); return options.find((o) => o.checked === true); }; export const renderHiddenField = (container, name, value) => { let input = container.querySelector('input.hidden-input'); if (!input) { input = container.ownerDocument.createElement('input'); input.type = 'hidden'; input.classList.add('hidden-input'); container.appendChild(input); } input.name = name; input.value = value || ''; }; // handle jsx-a11y/click-events-have-key-events export const handleKeyDown = (handler, skipSpace = false) => (e) => { const event = e; const key = event.key || event.keyCode; if (key === 'Enter' || key === 13 || key === 32 || (!skipSpace && ['Spacebar', ' '].indexOf(key) >= 0)) { // In IE11 and lower, event.key will equal "Spacebar" instead of ' ' // Default behavior is prevented to prevent the page to scroll when "space" is pressed event.preventDefault(); handler(event); } }; export const throttle = (func, context, delay) => { let lastExecutedAt; return (...args) => { if (!lastExecutedAt || Date.now() - lastExecutedAt >= delay) { func.apply(context, args); lastExecutedAt = Date.now(); } }; }; export const getFocusableChildren = (node) => { let focusableElements = []; const getAllNodes = (element, root = true) => { root && (focusableElements = []); element = element.shadowRoot ? element.shadowRoot : element; Array.from(element.children).forEach((el) => { if (isFocusable(el)) { focusableElements.push(el); } else if (el.nodeName === 'SLOT') { el.assignedElements({ flatten: true }).forEach((assignedEl) => getAllNodes(assignedEl, false)); } else if (el.children.length > 0 || el.shadowRoot) { if (!(parseInt(el.getAttribute('tabindex')) < 0)) { getAllNodes(el, false); } } }); }; getAllNodes(node); return focusableElements; }; export const isFocusable = (element) => { if (parseInt(element.getAttribute('tabindex')) < 0) { return false; } if (element.disabled) { return false; } const boundingRect = element.getBoundingClientRect(); if (boundingRect.bottom === 0 && boundingRect.top === 0 && boundingRect.left === 0 && boundingRect.right === 0 && boundingRect.height === 0 && boundingRect.width === 0 && boundingRect.x === 0 && boundingRect.y === 0) { return false; } if (element.style.display === 'none' || element.style.visibility === 'hidden' || element.style.opacity === 0) { return false; } if (element.getAttribute('role') === 'button') { return true; } // All crayons input components have this function. if (element.setFocus) { return true; } // To identify other native focus elements. switch (element.nodeName) { case 'A': return !!element.href && element.rel !== 'ignore'; case 'INPUT': return element.type !== 'hidden'; case 'BUTTON': case 'SELECT': case 'TEXTAREA': return true; default: return false; } }; export const hasSlot = (el, name) => { // Look for a named slot if (name) { return el.querySelector(`:scope > [slot="${name}"]`) !== null; } // Look for a default slot const nodeList = Array.from(el.childNodes); return nodeList.some((node) => { if (node.nodeType === node.TEXT_NODE && node.textContent.trim() !== '') { return true; } if (node.nodeType === node.ELEMENT_NODE) { const el = node; if (!el.hasAttribute('slot')) { return true; } } return false; }); }; export const debounce = (fn, context, timeout) => { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => { fn.apply(context, args); }, timeout); }; }; // deep clone the node along with its attached events. export function cloneNodeWithEvents(oElm, shouldCopyDeep = false, shouldCopyEvents = false) { let aInputSubElements, aNodeCopySubElements, n1, n2; const allEvents = [ 'onabort', 'onbeforecopy', 'onbeforecut', 'onbeforepaste', 'onblur', 'onchange', 'onclick', 'oncontextmenu', 'oncopy', 'ondblclick', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onfocus', 'oninput', 'oninvalid', 'onkeydown', 'onkeypress', 'onkeyup', 'onload', 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onpaste', 'onreset', 'onresize', 'onscroll', 'onsearch', 'onselect', 'onselectstart', 'onsubmit', 'onunload', ]; // deep clone node const eNodeCopy = oElm.cloneNode(shouldCopyDeep); // copy events if (shouldCopyEvents) { aInputSubElements = oElm.getElementsByTagName('*'); aNodeCopySubElements = eNodeCopy.getElementsByTagName('*'); // The node root for (n2 = 0; n2 < allEvents.length; n2++) { if (oElm[allEvents[n2]]) { eNodeCopy[allEvents[n2]] = oElm[allEvents[n2]]; } } // Node descendants copy events for (n1 = 0; n1 < aInputSubElements.length; n1++) { for (n2 = 0; n2 < allEvents.length; n2++) { if (aInputSubElements[n1][allEvents[n2]]) { aNodeCopySubElements[n1][allEvents[n2]] = aInputSubElements[n1][allEvents[n2]]; } } } } return eNodeCopy; } export const cyclicIncrement = (value, maxValue) => { value++; return value > maxValue ? 0 : value; }; export const cyclicDecrement = (value, maxValue) => { value--; return value < 0 ? maxValue : value; }; export const isEqual = (a, b) => { if (Array.isArray(a)) { return isArrayEquals(a, b); } else { return a === b; } }; export const isArrayEquals = (a, b) => { return (Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((val, index) => val === b[index])); };