UNPKG

@awsui/components-react

Version:

AWS UI is a collection of [React](https://reactjs.org/) components that help create intuitive, responsive, and accessible user experiences for web applications. It is developed by Amazon Web Services (AWS). This work is available under the terms of the [A

127 lines (126 loc) 6.18 kB
import { getOverflowParentDimensions, getOverflowParents } from '../../utils/scrollable-containers'; var AVAILABLE_SPACE_RESERVE = 50; var getClosestParentDimensions = function (element) { var parents = getOverflowParents(element).map(function (el) { var _a = el.getBoundingClientRect(), height = _a.height, width = _a.width, top = _a.top, left = _a.left; return { height: height, width: width, top: top, left: left }; }); return parents.shift(); }; export var focusPreservingScroll = function (element) { var savedScrollPositions = saveParentScrollPositions(element); element.focus(); restoreParentScrollPositions(savedScrollPositions); }; var saveParentScrollPositions = function (element) { return getOverflowParents(element).map(function (el) { return ({ scrollParent: el, prevScrollTop: el.scrollTop }); }); }; export var getAvailableSpace = function (trigger, dropdown) { var overflowParents = getOverflowParentDimensions(dropdown); var _a = trigger.getBoundingClientRect(), triggerBottom = _a.bottom, triggerLeft = _a.left, triggerRight = _a.right; return overflowParents.reduce(function (_a, overflowParent) { var above = _a.above, below = _a.below, left = _a.left, right = _a.right; var offsetTop = triggerBottom - overflowParent.top; var currentAbove = offsetTop - trigger.offsetHeight - AVAILABLE_SPACE_RESERVE; var currentBelow = overflowParent.height - offsetTop - AVAILABLE_SPACE_RESERVE; var currentLeft = triggerRight - overflowParent.left - AVAILABLE_SPACE_RESERVE; var currentRight = overflowParent.left + overflowParent.width - triggerLeft - AVAILABLE_SPACE_RESERVE; return { above: Math.min(above, currentAbove), below: Math.min(below, currentBelow), left: Math.min(left, currentLeft), right: Math.min(right, currentRight) }; }, { above: Number.MAX_VALUE, below: Number.MAX_VALUE, left: Number.MAX_VALUE, right: Number.MAX_VALUE }); }; export var getInteriorAvailableSpace = function (trigger, dropdown) { var overflowParents = getOverflowParentDimensions(dropdown, true); var _a = trigger.getBoundingClientRect(), triggerBottom = _a.bottom, triggerTop = _a.top, triggerLeft = _a.left, triggerRight = _a.right; return overflowParents.reduce(function (_a, overflowParent) { var above = _a.above, below = _a.below, left = _a.left, right = _a.right; var currentAbove = triggerBottom - overflowParent.top - trigger.offsetHeight - AVAILABLE_SPACE_RESERVE; var currentBelow = overflowParent.height - triggerTop + overflowParent.top - AVAILABLE_SPACE_RESERVE; var currentLeft = triggerLeft - overflowParent.left - AVAILABLE_SPACE_RESERVE; var currentRight = overflowParent.left + overflowParent.width - triggerRight - AVAILABLE_SPACE_RESERVE; return { above: Math.min(above, currentAbove), below: Math.min(below, currentBelow), left: Math.min(left, currentLeft), right: Math.min(right, currentRight) }; }, { above: Number.MAX_VALUE, below: Number.MAX_VALUE, left: Number.MAX_VALUE, right: Number.MAX_VALUE }); }; export var getDropdownPosition = function (trigger, dropdown, prefersDownDirection) { if (prefersDownDirection === void 0) { prefersDownDirection = false; } var availableSpace = getAvailableSpace(trigger, dropdown); var triggerWidth = trigger.getBoundingClientRect().width; var requiredWidth = dropdown.getBoundingClientRect().width; var idealWidth = Math.max(requiredWidth, triggerWidth); var dropLeft; var width = idealWidth; if (idealWidth <= availableSpace.right) { dropLeft = false; } else if (idealWidth <= availableSpace.left) { dropLeft = true; } else { dropLeft = availableSpace.left > availableSpace.right; width = Math.max(availableSpace.left, availableSpace.right, triggerWidth); } var dropUp = availableSpace.below < dropdown.offsetHeight && availableSpace.above > availableSpace.below; if (prefersDownDirection && dropUp && availableSpace.above < dropdown.offsetHeight) { dropUp = false; } return { dropUp: dropUp, dropLeft: dropLeft, height: dropUp ? availableSpace.above + "px" : availableSpace.below + "px", width: width + "px" }; }; export var getInteriorDropdownPosition = function (trigger, dropdown) { var availableSpace = getInteriorAvailableSpace(trigger, dropdown); var _a = trigger.getBoundingClientRect(), triggerBottom = _a.bottom, triggerTop = _a.top, triggerWidth = _a.width; var _b = getClosestParentDimensions(trigger), parentDropdownTop = _b.top, parentDropdownHeight = _b.height; var dropLeft; var width = dropdown.getBoundingClientRect().width; var top = triggerTop - parentDropdownTop; if (width <= availableSpace.right) { dropLeft = false; } else if (width <= availableSpace.left) { dropLeft = true; } else { dropLeft = availableSpace.left > availableSpace.right; width = Math.max(availableSpace.left, availableSpace.right); } var left = dropLeft ? 0 - width : triggerWidth; var dropUp = availableSpace.below < dropdown.offsetHeight && availableSpace.above > availableSpace.below; var bottom = dropUp ? parentDropdownTop + parentDropdownHeight - triggerBottom : 0; return { dropUp: dropUp, dropLeft: dropLeft, height: dropUp ? availableSpace.above + "px" : availableSpace.below + "px", width: width + "px", top: top + "px", bottom: bottom + "px", left: left + "px" }; }; var restoreParentScrollPositions = function (savedScrollPositions) { window.setTimeout(function () { savedScrollPositions.forEach(function (_a) { var scrollParent = _a.scrollParent, prevScrollTop = _a.prevScrollTop; if (scrollParent.scrollTop !== prevScrollTop) { scrollParent.scrollTop = prevScrollTop; } }); }, 0); };