UNPKG

devongovett-react-overlays

Version:

Utilities for creating robust overlay components

147 lines (110 loc) 4.55 kB
'use strict'; exports.__esModule = true; exports.default = calculatePosition; var _offset = require('dom-helpers/query/offset'); var _offset2 = _interopRequireDefault(_offset); var _position = require('dom-helpers/query/position'); var _position2 = _interopRequireDefault(_position); var _scrollTop = require('dom-helpers/query/scrollTop'); var _scrollTop2 = _interopRequireDefault(_scrollTop); var _scrollLeft = require('dom-helpers/query/scrollLeft'); var _scrollLeft2 = _interopRequireDefault(_scrollLeft); var _ownerDocument = require('./ownerDocument'); var _ownerDocument2 = _interopRequireDefault(_ownerDocument); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var AXIS = { top: 'top', bottom: 'top', left: 'left', right: 'left' }; var CROSS_AXIS = { top: 'left', left: 'top' }; var AXIS_SIZE = { top: 'height', left: 'width' }; function getContainerDimensions(containerNode) { var width = void 0, height = void 0; var scroll = {}; if (containerNode.tagName === 'BODY') { width = window.innerWidth; height = window.innerHeight; scroll.top = (0, _scrollTop2.default)((0, _ownerDocument2.default)(containerNode).documentElement) || (0, _scrollTop2.default)(containerNode); scroll.left = (0, _scrollLeft2.default)((0, _ownerDocument2.default)(containerNode).documentElement) || (0, _scrollLeft2.default)(containerNode); } else { var _getOffset = (0, _offset2.default)(containerNode); width = _getOffset.width; height = _getOffset.height; scroll.top = (0, _scrollTop2.default)(containerNode); scroll.left = (0, _scrollLeft2.default)(containerNode); } return { width: width, height: height, scroll: scroll }; } function getDelta(axis, offset, size, container, padding) { var containerDimensions = getContainerDimensions(container); var containerScroll = containerDimensions.scroll[axis]; var containerHeight = containerDimensions[AXIS_SIZE[axis]]; var startEdgeOffset = offset - padding - containerScroll; var endEdgeOffset = offset + padding - containerScroll + size; if (startEdgeOffset < 0) { return -startEdgeOffset; } else if (endEdgeOffset > containerHeight) { return containerHeight - endEdgeOffset; } else { return 0; } } function parsePlacement(input) { var _input$split = input.split(' '), placement = _input$split[0], crossPlacement = _input$split[1]; var axis = AXIS[placement] || 'right'; var crossAxis = CROSS_AXIS[axis]; if (!AXIS[crossPlacement]) { crossPlacement = 'center'; } var size = AXIS_SIZE[axis]; var crossSize = AXIS_SIZE[crossAxis]; return { placement: placement, crossPlacement: crossPlacement, axis: axis, crossAxis: crossAxis, size: size, crossSize: crossSize }; } function calculatePosition(placementInput, overlayNode, target, container, padding) { var childOffset = container.tagName === 'BODY' ? (0, _offset2.default)(target) : (0, _position2.default)(target, container); var overlaySize = (0, _offset2.default)(overlayNode); var style = window.getComputedStyle(overlayNode); overlaySize.width += parseInt(style.marginLeft, 10) + parseInt(style.marginRight, 10) || 0; overlaySize.height += parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10) || 0; var _parsePlacement = parsePlacement(placementInput), placement = _parsePlacement.placement, crossPlacement = _parsePlacement.crossPlacement, axis = _parsePlacement.axis, crossAxis = _parsePlacement.crossAxis, size = _parsePlacement.size, crossSize = _parsePlacement.crossSize; var position = {}; var arrowPosition = {}; position[crossAxis] = childOffset[crossAxis]; if (crossPlacement === 'center') { position[crossAxis] += (childOffset[crossSize] - overlaySize[crossSize]) / 2; } else if (crossPlacement !== crossAxis) { position[crossAxis] += childOffset[crossSize] - overlaySize[crossSize]; } if (placement === axis) { position[axis] = childOffset[axis] - overlaySize[size]; } else { position[axis] = childOffset[axis] + childOffset[size]; } var delta = getDelta(crossAxis, position[crossAxis], overlaySize[crossSize], container, padding); position[crossAxis] += delta; arrowPosition[crossAxis] = 50 * (1 - 2 * delta / overlaySize[crossSize]) + '%'; return { positionLeft: position.left, positionTop: position.top, arrowOffsetLeft: arrowPosition.left, arrowOffsetTop: arrowPosition.top }; } module.exports = exports['default'];