UNPKG

@hakuna-matata-ui/utils

Version:
1,802 lines (1,524 loc) 50.4 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var cssBoxModel = require('css-box-model'); var lodash_mergewith = require('lodash.mergewith'); var sync = require('framesync'); function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; } var lodash_mergewith__default = /*#__PURE__*/_interopDefault(lodash_mergewith); var sync__default = /*#__PURE__*/_interopDefault(sync); function getFirstItem(array) { return array != null && array.length ? array[0] : undefined; } function getLastItem(array) { var length = array == null ? 0 : array.length; return length ? array[length - 1] : undefined; } function getPrevItem(index, array, loop) { if (loop === void 0) { loop = true; } var prevIndex = getPrevIndex(index, array.length, loop); return array[prevIndex]; } function getNextItem(index, array, loop) { if (loop === void 0) { loop = true; } var nextIndex = getNextIndex(index, array.length, 1, loop); return array[nextIndex]; } function removeIndex(array, index) { return array.filter(function (_, idx) { return idx !== index; }); } function addItem(array, item) { return [].concat(array, [item]); } function removeItem(array, item) { return array.filter(function (eachItem) { return eachItem !== item; }); } /** * Get the next index based on the current index and step. * * @param currentIndex the current index * @param length the total length or count of items * @param step the number of steps * @param loop whether to circle back once `currentIndex` is at the start/end */ function getNextIndex(currentIndex, length, step, loop) { if (step === void 0) { step = 1; } if (loop === void 0) { loop = true; } var lastIndex = length - 1; if (currentIndex === -1) { return step > 0 ? 0 : lastIndex; } var nextIndex = currentIndex + step; if (nextIndex < 0) { return loop ? lastIndex : 0; } if (nextIndex >= length) { if (loop) return 0; return currentIndex > length ? length : currentIndex; } return nextIndex; } /** * Get's the previous index based on the current index. * Mostly used for keyboard navigation. * * @param index - the current index * @param count - the length or total count of items in the array * @param loop - whether we should circle back to the * first/last once `currentIndex` is at the start/end */ function getPrevIndex(index, count, loop) { if (loop === void 0) { loop = true; } return getNextIndex(index, count, -1, loop); } /** * Converts an array into smaller chunks or groups. * * @param array the array to chunk into group * @param size the length of each chunk */ function chunk(array, size) { return array.reduce(function (rows, currentValue, index) { if (index % size === 0) { rows.push([currentValue]); } else { rows[rows.length - 1].push(currentValue); } return rows; }, []); } /** * Gets the next item based on a search string * * @param items array of items * @param searchString the search string * @param itemToString resolves an item to string * @param currentItem the current selected item */ function getNextItemFromSearch(items, searchString, itemToString, currentItem) { if (searchString == null) { return currentItem; } // If current item doesn't exist, find the item that matches the search string if (!currentItem) { var foundItem = items.find(function (item) { return itemToString(item).toLowerCase().startsWith(searchString.toLowerCase()); }); return foundItem; } // Filter items for ones that match the search string (case insensitive) var matchingItems = items.filter(function (item) { return itemToString(item).toLowerCase().startsWith(searchString.toLowerCase()); }); // If there's a match, let's get the next item to select if (matchingItems.length > 0) { var nextIndex; // If the currentItem is in the available items, we move to the next available option if (matchingItems.includes(currentItem)) { var currentIndex = matchingItems.indexOf(currentItem); nextIndex = currentIndex + 1; if (nextIndex === matchingItems.length) { nextIndex = 0; } return matchingItems[nextIndex]; } // Else, we pick the first item in the available items nextIndex = items.indexOf(matchingItems[0]); return items[nextIndex]; } // a decent fallback to the currentItem return currentItem; } // Number assertions function isNumber(value) { return typeof value === "number"; } function isNotNumber(value) { return typeof value !== "number" || Number.isNaN(value) || !Number.isFinite(value); } function isNumeric(value) { return value != null && value - parseFloat(value) + 1 >= 0; } // Array assertions function isArray(value) { return Array.isArray(value); } function isEmptyArray(value) { return isArray(value) && value.length === 0; } // Function assertions function isFunction(value) { return typeof value === "function"; } // Generic assertions function isDefined(value) { return typeof value !== "undefined" && value !== undefined; } function isUndefined(value) { return typeof value === "undefined" || value === undefined; } // Object assertions function isObject(value) { var type = typeof value; return value != null && (type === "object" || type === "function") && !isArray(value); } function isEmptyObject(value) { return isObject(value) && Object.keys(value).length === 0; } function isNotEmptyObject(value) { return value && !isEmptyObject(value); } function isNull(value) { return value == null; } // String assertions function isString(value) { return Object.prototype.toString.call(value) === "[object String]"; } function isCssVar(value) { return /^var\(--.+\)$/.test(value); } // Empty assertions function isEmpty(value) { if (isArray(value)) return isEmptyArray(value); if (isObject(value)) return isEmptyObject(value); if (value == null || value === "") return true; return false; } var __DEV__ = process.env.NODE_ENV !== "production"; var __TEST__ = process.env.NODE_ENV === "test"; function isRefObject(val) { return "current" in val; } function isInputEvent(value) { return value && isObject(value) && isObject(value.target); } function omit(object, keys) { var result = {}; Object.keys(object).forEach(function (key) { if (keys.includes(key)) return; result[key] = object[key]; }); return result; } function pick(object, keys) { var result = {}; keys.forEach(function (key) { if (key in object) { result[key] = object[key]; } }); return result; } function split(object, keys) { var picked = {}; var omitted = {}; Object.keys(object).forEach(function (key) { if (keys.includes(key)) { picked[key] = object[key]; } else { omitted[key] = object[key]; } }); return [picked, omitted]; } /** * Get value from a deeply nested object using a string path. * Memoizes the value. * @param obj - the object * @param path - the string path * @param def - the fallback value */ function get(obj, path, fallback, index) { var key = typeof path === "string" ? path.split(".") : [path]; for (index = 0; index < key.length; index += 1) { if (!obj) break; obj = obj[key[index]]; } return obj === undefined ? fallback : obj; } var memoize = function memoize(fn) { var cache = new WeakMap(); var memoizedFn = function memoizedFn(obj, path, fallback, index) { if (typeof obj === "undefined") { return fn(obj, path, fallback); } if (!cache.has(obj)) { cache.set(obj, new Map()); } var map = cache.get(obj); if (map.has(path)) { return map.get(path); } var value = fn(obj, path, fallback, index); map.set(path, value); return value; }; return memoizedFn; }; var memoizedGet = memoize(get); /** * Get value from deeply nested object, based on path * It returns the path value if not found in object * * @param path - the string path or value * @param scale - the string path or value */ function getWithDefault(path, scale) { return memoizedGet(scale, path, path); } /** * Returns the items of an object that meet the condition specified in a callback function. * * @param object the object to loop through * @param fn The filter function */ function objectFilter(object, fn) { var result = {}; Object.keys(object).forEach(function (key) { var value = object[key]; var shouldPass = fn(value, key, object); if (shouldPass) { result[key] = value; } }); return result; } var filterUndefined = function filterUndefined(object) { return objectFilter(object, function (val) { return val !== null && val !== undefined; }); }; var objectKeys = function objectKeys(obj) { return Object.keys(obj); }; /** * Object.entries polyfill for Nodev10 compatibility */ var fromEntries = function fromEntries(entries) { return entries.reduce(function (carry, _ref) { var key = _ref[0], value = _ref[1]; carry[key] = value; return carry; }, {}); }; /** * Get the CSS variable ref stored in the theme */ var getCSSVar = function getCSSVar(theme, scale, value) { var _theme$__cssMap$$varR, _theme$__cssMap$; return (_theme$__cssMap$$varR = (_theme$__cssMap$ = theme.__cssMap[scale + "." + value]) == null ? void 0 : _theme$__cssMap$.varRef) != null ? _theme$__cssMap$$varR : value; }; function analyzeCSSValue(value) { var num = parseFloat(value.toString()); var unit = value.toString().replace(String(num), ""); return { unitless: !unit, value: num, unit: unit }; } function px(value) { if (value == null) return value; var _analyzeCSSValue = analyzeCSSValue(value), unitless = _analyzeCSSValue.unitless; return unitless || isNumber(value) ? value + "px" : value; } var sortByBreakpointValue = function sortByBreakpointValue(a, b) { return parseInt(a[1], 10) > parseInt(b[1], 10) ? 1 : -1; }; var sortBps = function sortBps(breakpoints) { return fromEntries(Object.entries(breakpoints).sort(sortByBreakpointValue)); }; function normalize(breakpoints) { var sorted = sortBps(breakpoints); return Object.assign(Object.values(sorted), sorted); } function keys(breakpoints) { var value = Object.keys(sortBps(breakpoints)); return new Set(value); } function subtract(value) { var _px; if (!value) return value; value = (_px = px(value)) != null ? _px : value; var factor = value.endsWith("px") ? -1 : // the equivalent of 1px in em using a 16px base -0.0635; return isNumber(value) ? "" + (value + factor) : value.replace(/([0-9]+\.?[0-9]*)/, function (m) { return "" + (parseFloat(m) + factor); }); } function queryString(min, max) { var query = []; if (min) query.push("@media screen and (min-width: " + px(min) + ")"); if (query.length > 0 && max) query.push("and"); if (max) query.push("@media screen and (max-width: " + px(max) + ")"); return query.join(" "); } function analyzeBreakpoints(breakpoints) { var _breakpoints$base; if (!breakpoints) return null; breakpoints.base = (_breakpoints$base = breakpoints.base) != null ? _breakpoints$base : "0px"; var normalized = normalize(breakpoints); var queries = Object.entries(breakpoints).sort(sortByBreakpointValue).map(function (_ref, index, entry) { var _entry; var breakpoint = _ref[0], minW = _ref[1]; var _ref2 = (_entry = entry[index + 1]) != null ? _entry : [], maxW = _ref2[1]; maxW = parseFloat(maxW) > 0 ? subtract(maxW) : undefined; return { breakpoint: breakpoint, minW: minW, maxW: maxW, maxWQuery: queryString(null, maxW), minWQuery: queryString(minW), minMaxQuery: queryString(minW, maxW) }; }); var _keys = keys(breakpoints); var _keysArr = Array.from(_keys.values()); return { keys: _keys, normalized: normalized, isResponsive: function isResponsive(test) { var keys = Object.keys(test); return keys.length > 0 && keys.every(function (key) { return _keys.has(key); }); }, asObject: sortBps(breakpoints), asArray: normalize(breakpoints), details: queries, media: [null].concat(normalized.map(function (minW) { return queryString(minW); }).slice(1)), toArrayValue: function toArrayValue(test) { if (!isObject(test)) { throw new Error("toArrayValue: value must be an object"); } var result = _keysArr.map(function (bp) { var _test$bp; return (_test$bp = test[bp]) != null ? _test$bp : null; }); while (getLastItem(result) === null) { result.pop(); } return result; }, toObjectValue: function toObjectValue(test) { if (!Array.isArray(test)) { throw new Error("toObjectValue: value must be an array"); } return test.reduce(function (acc, value, index) { var key = _keysArr[index]; if (key != null && value != null) acc[key] = value; return acc; }, {}); } }; } function isElement(el) { return el != null && typeof el == "object" && "nodeType" in el && el.nodeType === Node.ELEMENT_NODE; } function isHTMLElement(el) { var _el$ownerDocument$def; if (!isElement(el)) { return false; } var win = (_el$ownerDocument$def = el.ownerDocument.defaultView) != null ? _el$ownerDocument$def : window; return el instanceof win.HTMLElement; } function getOwnerWindow(node) { var _getOwnerDocument$def, _getOwnerDocument; return isElement(node) ? (_getOwnerDocument$def = (_getOwnerDocument = getOwnerDocument(node)) == null ? void 0 : _getOwnerDocument.defaultView) != null ? _getOwnerDocument$def : window : window; } function getOwnerDocument(node) { var _node$ownerDocument; return isElement(node) ? (_node$ownerDocument = node.ownerDocument) != null ? _node$ownerDocument : document : document; } function getEventWindow(event) { var _view; return (_view = event.view) != null ? _view : window; } function canUseDOM() { return !!(typeof window !== "undefined" && window.document && window.document.createElement); } var isBrowser = canUseDOM(); var dataAttr = function dataAttr(condition) { return condition ? "" : undefined; }; var ariaAttr = function ariaAttr(condition) { return condition ? true : undefined; }; var cx = function cx() { for (var _len = arguments.length, classNames = new Array(_len), _key = 0; _key < _len; _key++) { classNames[_key] = arguments[_key]; } return classNames.filter(Boolean).join(" "); }; function getActiveElement(node) { var doc = getOwnerDocument(node); return doc == null ? void 0 : doc.activeElement; } function contains(parent, child) { if (!parent) return false; return parent === child || parent.contains(child); } function addDomEvent(target, eventName, handler, options) { target.addEventListener(eventName, handler, options); return function () { target.removeEventListener(eventName, handler, options); }; } /** * Get the normalized event key across all browsers * @param event keyboard event */ function normalizeEventKey(event) { var key = event.key, keyCode = event.keyCode; var isArrowKey = keyCode >= 37 && keyCode <= 40 && key.indexOf("Arrow") !== 0; var eventKey = isArrowKey ? "Arrow" + key : key; return eventKey; } function getRelatedTarget(event) { var _event$target, _event$relatedTarget; var target = (_event$target = event.target) != null ? _event$target : event.currentTarget; var activeElement = getActiveElement(target); return (_event$relatedTarget = event.relatedTarget) != null ? _event$relatedTarget : activeElement; } function isRightClick(event) { return event.button !== 0; } // Really great work done by Diego Haz on this one var hasDisplayNone = function hasDisplayNone(element) { return window.getComputedStyle(element).display === "none"; }; var hasTabIndex = function hasTabIndex(element) { return element.hasAttribute("tabindex"); }; var hasNegativeTabIndex = function hasNegativeTabIndex(element) { return hasTabIndex(element) && element.tabIndex === -1; }; function isDisabled(element) { return Boolean(element.getAttribute("disabled")) === true || Boolean(element.getAttribute("aria-disabled")) === true; } function isInputElement(element) { return isHTMLElement(element) && element.tagName.toLowerCase() === "input" && "select" in element; } function isActiveElement(element) { var doc = isHTMLElement(element) ? getOwnerDocument(element) : document; return doc.activeElement === element; } function hasFocusWithin(element) { if (!document.activeElement) return false; return element.contains(document.activeElement); } function isHidden(element) { if (element.parentElement && isHidden(element.parentElement)) return true; return element.hidden; } function isContentEditable(element) { var value = element.getAttribute("contenteditable"); return value !== "false" && value != null; } function isFocusable(element) { if (!isHTMLElement(element) || isHidden(element) || isDisabled(element)) { return false; } var localName = element.localName; var focusableTags = ["input", "select", "textarea", "button"]; if (focusableTags.indexOf(localName) >= 0) return true; var others = { a: function a() { return element.hasAttribute("href"); }, audio: function audio() { return element.hasAttribute("controls"); }, video: function video() { return element.hasAttribute("controls"); } }; if (localName in others) { return others[localName](); } if (isContentEditable(element)) return true; return hasTabIndex(element); } function isTabbable(element) { if (!element) return false; return isHTMLElement(element) && isFocusable(element) && !hasNegativeTabIndex(element); } var focusableElList = ["input:not([disabled])", "select:not([disabled])", "textarea:not([disabled])", "embed", "iframe", "object", "a[href]", "area[href]", "button:not([disabled])", "[tabindex]", "audio[controls]", "video[controls]", "*[tabindex]:not([aria-disabled])", "*[contenteditable]"]; var focusableElSelector = focusableElList.join(); function getAllFocusable(container) { var focusableEls = Array.from(container.querySelectorAll(focusableElSelector)); focusableEls.unshift(container); return focusableEls.filter(isFocusable).filter(function (el) { return window.getComputedStyle(el).display !== "none"; }); } function getFirstFocusable(container) { var allFocusable = getAllFocusable(container); return allFocusable.length ? allFocusable[0] : null; } function getAllTabbable(container, fallbackToFocusable) { var allFocusable = Array.from(container.querySelectorAll(focusableElSelector)); var allTabbable = allFocusable.filter(isTabbable); if (isTabbable(container)) { allTabbable.unshift(container); } if (!allTabbable.length && fallbackToFocusable) { return allFocusable; } return allTabbable; } function getFirstTabbableIn(container, fallbackToFocusable) { var _getAllTabbable = getAllTabbable(container, fallbackToFocusable), first = _getAllTabbable[0]; return first || null; } function getLastTabbableIn(container, fallbackToFocusable) { var allTabbable = getAllTabbable(container, fallbackToFocusable); return allTabbable[allTabbable.length - 1] || null; } function getNextTabbable(container, fallbackToFocusable) { var allFocusable = getAllFocusable(container); var index = allFocusable.indexOf(document.activeElement); var slice = allFocusable.slice(index + 1); return slice.find(isTabbable) || allFocusable.find(isTabbable) || (fallbackToFocusable ? slice[0] : null); } function getPreviousTabbable(container, fallbackToFocusable) { var allFocusable = getAllFocusable(container).reverse(); var index = allFocusable.indexOf(document.activeElement); var slice = allFocusable.slice(index + 1); return slice.find(isTabbable) || allFocusable.find(isTabbable) || (fallbackToFocusable ? slice[0] : null); } function focusNextTabbable(container, fallbackToFocusable) { var nextTabbable = getNextTabbable(container, fallbackToFocusable); if (nextTabbable && isHTMLElement(nextTabbable)) { nextTabbable.focus(); } } function focusPreviousTabbable(container, fallbackToFocusable) { var previousTabbable = getPreviousTabbable(container, fallbackToFocusable); if (previousTabbable && isHTMLElement(previousTabbable)) { previousTabbable.focus(); } } function matches(element, selectors) { if ("matches" in element) return element.matches(selectors); if ("msMatchesSelector" in element) return element.msMatchesSelector(selectors); return element.webkitMatchesSelector(selectors); } function closest(element, selectors) { if ("closest" in element) return element.closest(selectors); do { if (matches(element, selectors)) return element; element = element.parentElement || element.parentNode; } while (element !== null && element.nodeType === 1); return null; } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } /* eslint-disable no-nested-ternary */ function runIfFn(valueOrFn) { for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } return isFunction(valueOrFn) ? valueOrFn.apply(void 0, args) : valueOrFn; } function callAllHandlers() { for (var _len2 = arguments.length, fns = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { fns[_key2] = arguments[_key2]; } return function func(event) { fns.some(function (fn) { fn == null ? void 0 : fn(event); return event == null ? void 0 : event.defaultPrevented; }); }; } function callAll() { for (var _len3 = arguments.length, fns = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { fns[_key3] = arguments[_key3]; } return function mergedFn(arg) { fns.forEach(function (fn) { fn == null ? void 0 : fn(arg); }); }; } var compose = function compose(fn1) { for (var _len4 = arguments.length, fns = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { fns[_key4 - 1] = arguments[_key4]; } return fns.reduce(function (f1, f2) { return function () { return f1(f2.apply(void 0, arguments)); }; }, fn1); }; function once(fn) { var result; return function func() { if (fn) { for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { args[_key5] = arguments[_key5]; } result = fn.apply(this, args); fn = null; } return result; }; } var noop = function noop() {}; var warn = once(function (options) { return function () { var condition = options.condition, message = options.message; if (condition && __DEV__) { console.warn(message); } }; }); var error = once(function (options) { return function () { var condition = options.condition, message = options.message; if (condition && __DEV__) { console.error(message); } }; }); var pipe = function pipe() { for (var _len6 = arguments.length, fns = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) { fns[_key6] = arguments[_key6]; } return function (v) { return fns.reduce(function (a, b) { return b(a); }, v); }; }; var distance1D = function distance1D(a, b) { return Math.abs(a - b); }; var isPoint = function isPoint(point) { return "x" in point && "y" in point; }; function distance(a, b) { if (isNumber(a) && isNumber(b)) { return distance1D(a, b); } if (isPoint(a) && isPoint(b)) { var xDelta = distance1D(a.x, b.x); var yDelta = distance1D(a.y, b.y); return Math.sqrt(Math.pow(xDelta, 2) + Math.pow(yDelta, 2)); } return 0; } function focus(element, options) { if (options === void 0) { options = {}; } var _options = options, _options$isActive = _options.isActive, isActive = _options$isActive === void 0 ? isActiveElement : _options$isActive, nextTick = _options.nextTick, _options$preventScrol = _options.preventScroll, preventScroll = _options$preventScrol === void 0 ? true : _options$preventScrol, _options$selectTextIf = _options.selectTextIfInput, selectTextIfInput = _options$selectTextIf === void 0 ? true : _options$selectTextIf; if (!element || isActive(element)) return -1; function triggerFocus() { if (!element) { warn({ condition: true, message: "[chakra-ui]: can't call focus() on `null` or `undefined` element" }); return; } if (supportsPreventScroll()) { element.focus({ preventScroll: preventScroll }); } else { element.focus(); if (preventScroll) { var scrollableElements = getScrollableElements(element); restoreScrollPosition(scrollableElements); } } if (isInputElement(element) && selectTextIfInput) { element.select(); } } if (nextTick) { return requestAnimationFrame(triggerFocus); } triggerFocus(); return -1; } var supportsPreventScrollCached = null; function supportsPreventScroll() { if (supportsPreventScrollCached == null) { supportsPreventScrollCached = false; try { var div = document.createElement("div"); div.focus({ get preventScroll() { supportsPreventScrollCached = true; return true; } }); } catch (e) {// Ignore } } return supportsPreventScrollCached; } function getScrollableElements(element) { var _doc$defaultView; var doc = getOwnerDocument(element); var win = (_doc$defaultView = doc.defaultView) != null ? _doc$defaultView : window; var parent = element.parentNode; var scrollableElements = []; var rootScrollingElement = doc.scrollingElement || doc.documentElement; while (parent instanceof win.HTMLElement && parent !== rootScrollingElement) { if (parent.offsetHeight < parent.scrollHeight || parent.offsetWidth < parent.scrollWidth) { scrollableElements.push({ element: parent, scrollTop: parent.scrollTop, scrollLeft: parent.scrollLeft }); } parent = parent.parentNode; } if (rootScrollingElement instanceof win.HTMLElement) { scrollableElements.push({ element: rootScrollingElement, scrollTop: rootScrollingElement.scrollTop, scrollLeft: rootScrollingElement.scrollLeft }); } return scrollableElements; } function restoreScrollPosition(scrollableElements) { for (var _iterator = _createForOfIteratorHelperLoose(scrollableElements), _step; !(_step = _iterator()).done;) { var _step$value = _step.value, element = _step$value.element, scrollTop = _step$value.scrollTop, scrollLeft = _step$value.scrollLeft; element.scrollTop = scrollTop; element.scrollLeft = scrollLeft; } } /** * Determines whether the children of a disclosure widget * should be rendered or not, depending on the lazy behavior. * * Used in accordion, tabs, popover, menu and other disclosure * widgets. */ function determineLazyBehavior(options) { var hasBeenSelected = options.hasBeenSelected, isLazy = options.isLazy, isSelected = options.isSelected, _options$lazyBehavior = options.lazyBehavior, lazyBehavior = _options$lazyBehavior === void 0 ? "unmount" : _options$lazyBehavior; // if not lazy, always render the disclosure's content if (!isLazy) return true; // if the diclosure is selected, render the disclosure's content if (isSelected) return true; // if the disclosure was selected but not active, keep its content active if (lazyBehavior === "keepMounted" && hasBeenSelected) return true; return false; } var minSafeInteger = Number.MIN_SAFE_INTEGER || -9007199254740991; var maxSafeInteger = Number.MAX_SAFE_INTEGER || 9007199254740991; function toNumber(value) { var num = parseFloat(value); return isNotNumber(num) ? 0 : num; } /** * Converts a value to a specific precision (or decimal points). * * Returns a string representing a number in fixed-point notation. * * @param value the value to convert * @param precision the precision or decimal points */ function toPrecision(value, precision) { var nextValue = toNumber(value); var scaleFactor = Math.pow(10, precision != null ? precision : 10); nextValue = Math.round(nextValue * scaleFactor) / scaleFactor; return precision ? nextValue.toFixed(precision) : nextValue.toString(); } /** * Counts the number of decimal places a number has * * @param value the decimal value to count */ function countDecimalPlaces(value) { if (!Number.isFinite(value)) return 0; var e = 1; var p = 0; while (Math.round(value * e) / e !== value) { e *= 10; p += 1; } return p; } /** * Convert a value to percentage based on lower and upper bound values * * @param value the value in number * @param min the minimum value * @param max the maximum value */ function valueToPercent(value, min, max) { return (value - min) * 100 / (max - min); } /** * Calculate the value based on percentage, lower and upper bound values * * @param percent the percent value in decimals (e.g 0.6, 0.3) * @param min the minimum value * @param max the maximum value */ function percentToValue(percent, min, max) { return (max - min) * percent + min; } /** * Rounds a specific value to the next or previous step * * @param value the value to round * @param from the number that stepping started from * @param step the specified step */ function roundValueToStep(value, from, step) { var nextValue = Math.round((value - from) / step) * step + from; var precision = countDecimalPlaces(step); return toPrecision(nextValue, precision); } /** * Clamps a value to ensure it stays within the min and max range. * * @param value the value to clamp * @param min the minimum value * @param max the maximum value */ function clampValue(value, min, max) { if (value == null) return value; warn({ condition: max < min, message: "clamp: max cannot be less than min" }); return Math.min(Math.max(value, min), max); } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } /** * Credit goes to `framer-motion` of this useful utilities. * License can be found here: https://github.com/framer/motion */ function isMouseEvent(event) { var win = getEventWindow(event); // PointerEvent inherits from MouseEvent so we can't use a straight instanceof check. if (typeof win.PointerEvent !== "undefined" && event instanceof win.PointerEvent) { return !!(event.pointerType === "mouse"); } return event instanceof win.MouseEvent; } function isTouchEvent(event) { var hasTouches = !!event.touches; return hasTouches; } /** * Filters out events not attached to the primary pointer (currently left mouse button) * @param eventHandler */ function filterPrimaryPointer(eventHandler) { return function (event) { var win = getEventWindow(event); var isMouseEvent = event instanceof win.MouseEvent; var isPrimaryPointer = !isMouseEvent || isMouseEvent && event.button === 0; if (isPrimaryPointer) { eventHandler(event); } }; } var defaultPagePoint = { pageX: 0, pageY: 0 }; function pointFromTouch(e, pointType) { if (pointType === void 0) { pointType = "page"; } var primaryTouch = e.touches[0] || e.changedTouches[0]; var point = primaryTouch || defaultPagePoint; return { x: point[pointType + "X"], y: point[pointType + "Y"] }; } function pointFromMouse(point, pointType) { if (pointType === void 0) { pointType = "page"; } return { x: point[pointType + "X"], y: point[pointType + "Y"] }; } function extractEventInfo(event, pointType) { if (pointType === void 0) { pointType = "page"; } return { point: isTouchEvent(event) ? pointFromTouch(event, pointType) : pointFromMouse(event, pointType) }; } function getViewportPointFromEvent(event) { return extractEventInfo(event, "client"); } var wrapPointerEventHandler = function wrapPointerEventHandler(handler, shouldFilterPrimaryPointer) { if (shouldFilterPrimaryPointer === void 0) { shouldFilterPrimaryPointer = false; } var listener = function listener(event) { return handler(event, extractEventInfo(event)); }; return shouldFilterPrimaryPointer ? filterPrimaryPointer(listener) : listener; }; // We check for event support via functions in case they've been mocked by a testing suite. var supportsPointerEvents = function supportsPointerEvents() { return isBrowser && window.onpointerdown === null; }; var supportsTouchEvents = function supportsTouchEvents() { return isBrowser && window.ontouchstart === null; }; var supportsMouseEvents = function supportsMouseEvents() { return isBrowser && window.onmousedown === null; }; var mouseEventNames = { pointerdown: "mousedown", pointermove: "mousemove", pointerup: "mouseup", pointercancel: "mousecancel", pointerover: "mouseover", pointerout: "mouseout", pointerenter: "mouseenter", pointerleave: "mouseleave" }; var touchEventNames = { pointerdown: "touchstart", pointermove: "touchmove", pointerup: "touchend", pointercancel: "touchcancel" }; function getPointerEventName(name) { if (supportsPointerEvents()) { return name; } if (supportsTouchEvents()) { return touchEventNames[name]; } if (supportsMouseEvents()) { return mouseEventNames[name]; } return name; } function addPointerEvent(target, eventName, handler, options) { return addDomEvent(target, getPointerEventName(eventName), wrapPointerEventHandler(handler, eventName === "pointerdown"), options); } function isMultiTouchEvent(event) { return isTouchEvent(event) && event.touches.length > 1; } /** * The event information passed to pan event handlers like `onPan`, `onPanStart`. * * It contains information about the current state of the tap gesture such as its * `point`, `delta`, and `offset` */ /** * @internal * * A Pan Session is recognized when the pointer is down * and moved in the allowed direction. */ var PanSession = /*#__PURE__*/function () { /** * We use this to keep track of the `x` and `y` pan session history * as the pan event happens. It helps to calculate the `offset` and `delta` */ // The pointer event that started the pan session // The current pointer event for the pan session // The current pointer event info for the pan session /** * Minimal pan distance required before recognizing the pan. * @default "3px" */ function PanSession(_event, handlers, threshold) { var _this = this; this.history = []; this.startEvent = null; this.lastEvent = null; this.lastEventInfo = null; this.handlers = {}; this.removeListeners = noop; this.threshold = 3; this.win = void 0; this.updatePoint = function () { if (!(_this.lastEvent && _this.lastEventInfo)) return; var info = getPanInfo(_this.lastEventInfo, _this.history); var isPanStarted = _this.startEvent !== null; var isDistancePastThreshold = distance(info.offset, { x: 0, y: 0 }) >= _this.threshold; if (!isPanStarted && !isDistancePastThreshold) return; var _getFrameData = sync.getFrameData(), timestamp = _getFrameData.timestamp; _this.history.push(_extends({}, info.point, { timestamp: timestamp })); var _this$handlers = _this.handlers, onStart = _this$handlers.onStart, onMove = _this$handlers.onMove; if (!isPanStarted) { onStart == null ? void 0 : onStart(_this.lastEvent, info); _this.startEvent = _this.lastEvent; } onMove == null ? void 0 : onMove(_this.lastEvent, info); }; this.onPointerMove = function (event, info) { _this.lastEvent = event; _this.lastEventInfo = info; // Because Safari doesn't trigger mouseup events when it's above a `<select>` if (isMouseEvent(event) && event.buttons === 0) { _this.onPointerUp(event, info); return; } // Throttle mouse move event to once per frame sync__default["default"].update(_this.updatePoint, true); }; this.onPointerUp = function (event, info) { // notify pan session ended var panInfo = getPanInfo(info, _this.history); var _this$handlers2 = _this.handlers, onEnd = _this$handlers2.onEnd, onSessionEnd = _this$handlers2.onSessionEnd; onSessionEnd == null ? void 0 : onSessionEnd(event, panInfo); _this.end(); // if panning never started, no need to call `onEnd` // panning requires a pointermove of at least 3px if (!onEnd || !_this.startEvent) return; onEnd == null ? void 0 : onEnd(event, panInfo); }; this.win = getEventWindow(_event); // If we have more than one touch, don't start detecting this gesture if (isMultiTouchEvent(_event)) return; this.handlers = handlers; if (threshold) { this.threshold = threshold; } // stop default browser behavior _event.stopPropagation(); _event.preventDefault(); // get and save the `pointerdown` event info in history // we'll use it to compute the `offset` var _info = extractEventInfo(_event); var _getFrameData2 = sync.getFrameData(), _timestamp = _getFrameData2.timestamp; this.history = [_extends({}, _info.point, { timestamp: _timestamp })]; // notify pan session start var onSessionStart = handlers.onSessionStart; onSessionStart == null ? void 0 : onSessionStart(_event, getPanInfo(_info, this.history)); // attach event listeners and return a single function to remove them all this.removeListeners = pipe(addPointerEvent(this.win, "pointermove", this.onPointerMove), addPointerEvent(this.win, "pointerup", this.onPointerUp), addPointerEvent(this.win, "pointercancel", this.onPointerUp)); } var _proto = PanSession.prototype; _proto.updateHandlers = function updateHandlers(handlers) { this.handlers = handlers; }; _proto.end = function end() { var _this$removeListeners; (_this$removeListeners = this.removeListeners) == null ? void 0 : _this$removeListeners.call(this); sync.cancelSync.update(this.updatePoint); }; return PanSession; }(); function subtractPoint(a, b) { return { x: a.x - b.x, y: a.y - b.y }; } function startPanPoint(history) { return history[0]; } function lastPanPoint(history) { return history[history.length - 1]; } function getPanInfo(info, history) { return { point: info.point, delta: subtractPoint(info.point, lastPanPoint(history)), offset: subtractPoint(info.point, startPanPoint(history)), velocity: getVelocity(history, 0.1) }; } function lastDevicePoint(history) { return history[history.length - 1]; } var toMilliseconds = function toMilliseconds(seconds) { return seconds * 1000; }; function getVelocity(history, timeDelta) { if (history.length < 2) { return { x: 0, y: 0 }; } var i = history.length - 1; var timestampedPoint = null; var lastPoint = lastDevicePoint(history); while (i >= 0) { timestampedPoint = history[i]; if (lastPoint.timestamp - timestampedPoint.timestamp > toMilliseconds(timeDelta)) { break; } i--; } if (!timestampedPoint) { return { x: 0, y: 0 }; } var time = (lastPoint.timestamp - timestampedPoint.timestamp) / 1000; if (time === 0) { return { x: 0, y: 0 }; } var currentVelocity = { x: (lastPoint.x - timestampedPoint.x) / time, y: (lastPoint.y - timestampedPoint.y) / time }; if (currentVelocity.x === Infinity) { currentVelocity.x = 0; } if (currentVelocity.y === Infinity) { currentVelocity.y = 0; } return currentVelocity; } var breakpoints = Object.freeze(["base", "sm", "md", "lg", "xl", "2xl"]); function mapResponsive(prop, mapper) { if (isArray(prop)) { return prop.map(function (item) { if (item === null) { return null; } return mapper(item); }); } if (isObject(prop)) { return objectKeys(prop).reduce(function (result, key) { result[key] = mapper(prop[key]); return result; }, {}); } if (prop != null) { return mapper(prop); } return null; } function objectToArrayNotation(obj, bps) { if (bps === void 0) { bps = breakpoints; } var result = bps.map(function (br) { var _obj$br; return (_obj$br = obj[br]) != null ? _obj$br : null; }); while (getLastItem(result) === null) { result.pop(); } return result; } function arrayToObjectNotation(values, bps) { if (bps === void 0) { bps = breakpoints; } var result = {}; values.forEach(function (value, index) { var key = bps[index]; if (value == null) return; result[key] = value; }); return result; } function isResponsiveObjectLike(obj, bps) { if (bps === void 0) { bps = breakpoints; } var keys = Object.keys(obj); return keys.length > 0 && keys.every(function (key) { return bps.includes(key); }); } /** * since breakpoints are defined as custom properties on an array, you may * `Object.keys(theme.breakpoints)` to retrieve both regular numeric indices * and custom breakpoints as string. * * This function returns true given a custom array property. */ var isCustomBreakpoint = function isCustomBreakpoint(maybeBreakpoint) { return Number.isNaN(Number(maybeBreakpoint)); }; function getUserAgentBrowser(navigator) { var ua = navigator.userAgent, vendor = navigator.vendor; var android = /(android)/i.test(ua); switch (true) { case /CriOS/.test(ua): return "Chrome for iOS"; case /Edg\//.test(ua): return "Edge"; case android && /Silk\//.test(ua): return "Silk"; case /Chrome/.test(ua) && /Google Inc/.test(vendor): return "Chrome"; case /Firefox\/\d+\.\d+$/.test(ua): return "Firefox"; case android: return "AOSP"; case /MSIE|Trident/.test(ua): return "IE"; case /Safari/.test(navigator.userAgent) && /Apple Computer/.test(ua): return "Safari"; case /AppleWebKit/.test(ua): return "WebKit"; default: return null; } } function getUserAgentOS(navigator) { var ua = navigator.userAgent, platform = navigator.platform; switch (true) { case /Android/.test(ua): return "Android"; case /iPhone|iPad|iPod/.test(platform): return "iOS"; case /Win/.test(platform): return "Windows"; case /Mac/.test(platform): return "Mac"; case /CrOS/.test(ua): return "Chrome OS"; case /Firefox/.test(ua): return "Firefox OS"; default: return null; } } function detectDeviceType(navigator) { var ua = navigator.userAgent; if (/(tablet)|(iPad)|(Nexus 9)/i.test(ua)) return "tablet"; if (/(mobi)/i.test(ua)) return "phone"; return "desktop"; } function detectOS(os) { if (!isBrowser) return false; return getUserAgentOS(window.navigator) === os; } function detectBrowser(browser) { if (!isBrowser) return false; return getUserAgentBrowser(window.navigator) === browser; } function detectTouch() { if (!isBrowser) return false; return window.ontouchstart === null && window.ontouchmove === null && window.ontouchend === null; } function walkObject(target, predicate) { function inner(value, path) { if (path === void 0) { path = []; } if (isArray(value)) { return value.map(function (item, index) { return inner(item, [].concat(path, [String(index)])); }); } if (isObject(value)) { return fromEntries(Object.entries(value).map(function (_ref) { var key = _ref[0], child = _ref[1]; return [key, inner(child, [].concat(path, [key]))]; })); } return predicate(value, path); } return inner(target); } Object.defineProperty(exports, 'mergeWith', { enumerable: true, get: function () { return lodash_mergewith__default["default"]; } }); exports.PanSession = PanSession; exports.__DEV__ = __DEV__; exports.__TEST__ = __TEST__; exports.addDomEvent = addDomEvent; exports.addItem = addItem; exports.addPointerEvent = addPointerEvent; exports.analyzeBreakpoints = analyzeBreakpoints; exports.ariaAttr = ariaAttr; exports.arrayToObjectNotation = arrayToObjectNotation; exports.breakpoints = breakpoints; exports.callAll = callAll; exports.callAllHandlers = callAllHandlers; exports.canUseDOM = canUseDOM; exports.chunk = chunk; exports.clampValue = clampValue; exports.closest = closest; exports.compose = compose; exports.contains = contains; exports.countDecimalPlaces = countDecimalPlaces; exports.cx = cx; exports.dataAttr = dataAttr; exports.detectBrowser = detectBrowser; exports.detectDeviceType = detectDeviceType; exports.detectOS = detectOS; exports.detectTouch = detectTouch; exports.determineLazyBehavior = determineLazyBehavior; exports.distance = distance; exports.error = error; exports.extractEventInfo = extractEventInfo; exports.filterUndefined = filterUndefined; exports.focus = focus; exports.focusNextTabbable = focusNextTabbable; exports.focusPreviousTabbable = focusPreviousTabbable; exports.fromEntries = fromEntries; exports.get = get; exports.getActiveElement = getActiveElement; exports.getAllFocusable = getAllFocusable; exports.getAllTabbable = getAllTabbable; exports.getCSSVar = getCSSVar; exports.getEventWindow = getEventWindow; exports.getFirstFocusable = getFirstFocusable; exports.getFirstItem = getFirstItem; exports.getFirstTabbableIn = getFirstTabbableIn; exports.getLastItem = getLastItem; exports.getLastTabbableIn = getLastTabbableIn; exports.getNextIndex = getNextIndex; exports.getNextItem = getNextItem; exports.getNextItemFromSearch = getNextItemFromSearch; exports.getNextTabbable = getNextTabbable; exports.getOwnerDocument = getOwnerDocument; exports.getOwnerWindow = getOwnerWindow; exports.getPointerEventName = getPointerEventName; exports.getPrevIndex = getPrevIndex; exports.getPrevItem = getPrevItem; exports.getPreviousTabbable = getPreviousTabbable; exports.getRelatedTarget = getRelatedTarget; exports.getViewportPointFromEvent = getViewportPointFromEvent; exports.getWithDefault = getWithDefault; exports.hasDisplayNone = hasDisplayNone; exports.hasFocusWithin = hasFocusWithin; exports.hasNegativeTabIndex = hasNegativeTabIndex; exports.hasTabIndex = hasTabIndex; exports.isActiveElement = isActiveElement; exports.isArray = isArray; exports.isBrowser = isBrowser; exports.isContentEditable = isContentEditable; exports.isCssVar = isCssVar; exports.isCustomBreakpoint = isCustomBreakpoint; exports.isDefined = isDefined; exports.isDisabled = isDisabled; exports.isElement = isElement; exports.isEmpty = isEmpty; exports.isEmptyArray = isEmptyArray; exports.isEmptyObject = isEmptyObject; exports.isFocusable = isFocusable; exports.isFunction = isFunction; exports.isHTMLElement = isHTMLElement; exports.isHidden = isHidden; exports.isInputElement = isInputElement; exports.isInputEvent = isInputEvent; exports.isMouseEvent = isMouseEvent; exports.isMultiTouchEvent = isMultiTouchEvent; exports.isNotEmptyObject = isNotEmptyObject; exports.isNotNumber = isNotNumber; exports.isNull = isNull; exports.isNumber = isNumber; exports.isNumeric = isNumeric; exports.isObject = isObject; exports.isRefObject = isRefObject; exports.isResponsiveObjectLike = isResponsiveObjectLike; exports.isRightClick = isRightClick; exports.isString = isString; exports.isTabbable = isTabbable; exports.isTouchEvent = isTouchEvent; exports.isUndefined = isUndefined; exports.mapResponsive = mapResponsive; exports.maxSafeInteger = maxSafeInteger; exports.memoize = memoize; exports.memoizedGet = memoizedGet; exports.minSafeInteger = minSafeInteger; exports.noop = noop; exports.normalizeEventKey = normalizeEventKey; exports.objectFilter = objectFilter; exports.objectKeys = objectKeys; exports.objectToArrayNotation = objectToArrayNotation; exports.omit = omit; exports.once = once; exports.percentToValue = percentToValue; exports.pick = pick; exports.pipe = pipe; exports.px = px; exports.removeIndex = removeIndex; exports.removeItem = removeItem; exports.roundValueToStep = roundValueToStep; exports.runIfF