UNPKG

baseui

Version:

A React Component library implementing the Base design language

130 lines (118 loc) 3.75 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.capitalize = capitalize; exports.fromPopperPlacement = fromPopperPlacement; exports.getArrowPositionStyles = getArrowPositionStyles; exports.getEndPosition = getEndPosition; exports.getOppositePosition = getOppositePosition; exports.getPopoverMarginStyles = getPopoverMarginStyles; exports.getStartPosition = getStartPosition; exports.isVerticalPosition = isVerticalPosition; exports.splitPlacement = splitPlacement; var _constants = require("./constants"); /* Copyright (c) Uber Technologies, Inc. This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. */ /* eslint-disable import/prefer-default-export */ const OPPOSITE_POSITIONS = { top: 'bottom', bottom: 'top', right: 'left', left: 'right' }; /** * Returns the opposite of the specified position. Useful for tooltip * positioning logic. * Examples: * top -> bottom * left -> right */ function getOppositePosition(position) { // @ts-ignore return OPPOSITE_POSITIONS[position]; } /** * Determines whether or not the specified position is a vertical one (top or bottom) */ function isVerticalPosition(position) { return position === 'top' || position === 'bottom'; } /** * Simple utility function for capitalizing the first letter of a string */ function capitalize(str) { return str.charAt(0).toUpperCase() + str.slice(1); } /** * Opposite of function above, converts from Popper.js placement * to our placement prop */ function fromPopperPlacement(placement) { const popoverPlacement = placement.replace(/(top|bottom)-start$/, '$1Left').replace(/(top|bottom)-end$/, '$1Right').replace(/(left|right)-start$/, '$1Top').replace(/(left|right)-end$/, '$1Bottom'); // @ts-ignore return _constants.PLACEMENT[popoverPlacement] || null; } /** * Splits something like 'topLeft' to ['top', 'left'] for easier usage */ function splitPlacement(placement) { const matches = placement.match(/^([a-z]+)([A-Z][a-z]+)?/) || []; return matches.slice(1, 3).filter(Boolean).map(s => s.toLowerCase()); } /** * Returns margin styles to add spacing between the popover * and its anchor. */ function getPopoverMarginStyles(arrowSize, placement, popoverMargin) { const [position] = splitPlacement(placement); const opposite = getOppositePosition(position); if (!opposite) { return null; } const property = `margin${capitalize(opposite)}`; return { [property]: `${arrowSize + popoverMargin}px` }; } /** * Returns CSS rules for the popover animation start keyframe */ function getStartPosition(offset, placement, arrowSize, popoverMargin) { offset = { ...offset }; const [position] = splitPlacement(placement); const margin = (arrowSize > 0 ? arrowSize : popoverMargin) * 2; if (isVerticalPosition(position)) { offset.top += position === 'top' ? margin : -margin; } else { offset.left += position === 'left' ? margin : -margin; } return `translate3d(${offset.left}px, ${offset.top}px, 0)`; } /** * Returns CSS rules for the popover animation end keyframe */ function getEndPosition(offset) { return `translate3d(${offset.left}px, ${offset.top}px, 0)`; } /** * Returns top/left styles to position the popover arrow */ function getArrowPositionStyles(offsets, placement) { const [position] = splitPlacement(placement); const oppositePosition = getOppositePosition(position); if (!oppositePosition) { return null; } const alignmentProperty = isVerticalPosition(position) ? 'left' : 'top'; return { // @ts-ignore [alignmentProperty]: `${offsets[alignmentProperty]}px`, [oppositePosition]: `-${_constants.ARROW_SIZE - 2}px` }; }