UNPKG

@popperjs/core

Version:

Tooltip and Popover Positioning Engine

135 lines (112 loc) 5.02 kB
import { top, left, right, bottom } from "../enums.js"; import getOffsetParent from "../dom-utils/getOffsetParent.js"; import getWindow from "../dom-utils/getWindow.js"; import getDocumentElement from "../dom-utils/getDocumentElement.js"; import getComputedStyle from "../dom-utils/getComputedStyle.js"; import getBasePlacement from "../utils/getBasePlacement.js"; var unsetSides = { top: 'auto', right: 'auto', bottom: 'auto', left: 'auto' }; // Round the offsets to the nearest suitable subpixel based on the DPR. // Zooming can change the DPR, but it seems to report a value that will // cleanly divide the values into the appropriate subpixels. function roundOffsets(_ref) { var x = _ref.x, y = _ref.y; var win = window; var dpr = win.devicePixelRatio || 1; return { x: Math.round(x * dpr) / dpr || 0, y: Math.round(y * dpr) / dpr || 0 }; } export function mapToStyles(_ref2) { var _Object$assign2; var popper = _ref2.popper, popperRect = _ref2.popperRect, placement = _ref2.placement, offsets = _ref2.offsets, position = _ref2.position, gpuAcceleration = _ref2.gpuAcceleration, adaptive = _ref2.adaptive; var _roundOffsets = roundOffsets(offsets), x = _roundOffsets.x, y = _roundOffsets.y; var hasX = offsets.hasOwnProperty('x'); var hasY = offsets.hasOwnProperty('y'); var sideX = left; var sideY = top; var win = window; if (adaptive) { var offsetParent = getOffsetParent(popper); if (offsetParent === getWindow(popper)) { offsetParent = getDocumentElement(popper); } // $FlowFixMe: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it /*:: offsetParent = (offsetParent: Element); */ if (placement === top) { sideY = bottom; y -= offsetParent.clientHeight - popperRect.height; y *= gpuAcceleration ? 1 : -1; } if (placement === left) { sideX = right; x -= offsetParent.clientWidth - popperRect.width; x *= gpuAcceleration ? 1 : -1; } } var commonStyles = Object.assign({ position: position }, adaptive && unsetSides); if (gpuAcceleration) { var _Object$assign; return Object.assign({}, commonStyles, (_Object$assign = {}, _Object$assign[sideY] = hasY ? '0' : '', _Object$assign[sideX] = hasX ? '0' : '', _Object$assign.transform = (win.devicePixelRatio || 1) < 2 ? "translate(" + x + "px, " + y + "px)" : "translate3d(" + x + "px, " + y + "px, 0)", _Object$assign)); } return Object.assign({}, commonStyles, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + "px" : '', _Object$assign2[sideX] = hasX ? x + "px" : '', _Object$assign2.transform = '', _Object$assign2)); } function computeStyles(_ref3) { var state = _ref3.state, options = _ref3.options; var _options$gpuAccelerat = options.gpuAcceleration, gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat, _options$adaptive = options.adaptive, adaptive = _options$adaptive === void 0 ? true : _options$adaptive; if (process.env.NODE_ENV !== "production") { var _getComputedStyle = getComputedStyle(state.elements.popper), transitionProperty = _getComputedStyle.transitionProperty; if (adaptive && ['transform', 'top', 'right', 'bottom', 'left'].some(function (property) { return transitionProperty.indexOf(property) >= 0; })) { console.warn(['Popper: Detected CSS transitions on at least one of the following', 'CSS properties: "transform", "top", "right", "bottom", "left".', '\n\n', 'Disable the "computeStyles" modifier\'s `adaptive` option to allow', 'for smooth transitions, or remove these properties from the CSS', 'transition declaration on the popper element if only transitioning', 'opacity or background-color for example.', '\n\n', 'We recommend using the popper element as a wrapper around an inner', 'element that can have any CSS property transitioned for animations.'].join(' ')); } } var commonStyles = { placement: getBasePlacement(state.placement), popper: state.elements.popper, popperRect: state.rects.popper, gpuAcceleration: gpuAcceleration }; // popper offsets are always available state.styles.popper = Object.assign({}, state.styles.popper, {}, mapToStyles(Object.assign({}, commonStyles, { offsets: state.modifiersData.popperOffsets, position: state.options.strategy, adaptive: adaptive }))); // arrow offsets may not be available if (state.modifiersData.arrow != null) { state.styles.arrow = Object.assign({}, state.styles.arrow, {}, mapToStyles(Object.assign({}, commonStyles, { offsets: state.modifiersData.arrow, position: 'absolute', adaptive: false }))); } state.attributes.popper = Object.assign({}, state.attributes.popper, { 'data-popper-placement': state.placement }); } export default { name: 'computeStyles', enabled: true, phase: 'beforeWrite', fn: computeStyles, data: {} };