UNPKG

@vimeo/iris

Version:
106 lines (103 loc) 5.47 kB
import { a as __makeTemplateObject, b as __rest, _ as __read, c as __assign } from '../../../tslib.es6-7f0e734f.js'; import React__default, { useState, useCallback, useLayoutEffect } from 'react'; import styled, { css } from 'styled-components'; import { rem } from 'polished'; function Anchor(_a) { var anchor = _a.anchor, anchorToWindow = _a.anchorToWindow, attach = _a.attach, childRef = _a.childRef, children = _a.children, margin = _a.margin, style = _a.style, props = __rest(_a, ["anchor", "anchorToWindow", "attach", "childRef", "children", "margin", "style"]); var _b = __read(useState({}), 2), state = _b[0], setState = _b[1]; var onResize = useCallback(function () { var childElement = childRef === null || childRef === void 0 ? void 0 : childRef.current; if (!childElement) return; var viewport = anchorToWindow && windowRect(); var childRect = calcRect(childRef); var rect = viewport || calcRect(anchor, window); var _a = remPos({ attach: attach, margin: margin, rect: rect, childRect: childRect, }), top = _a.top, left = _a.left; setState(function (state) { return (__assign(__assign({}, state), { top: top, left: left, rect: rect, childRect: childRect })); }); }, [anchor, anchorToWindow, attach, childRef, margin]); // eslint-disable-next-line react-hooks/exhaustive-deps useLayoutEffect(function () { return onResize(); }, []); useLayoutEffect(function () { var childElement = childRef === null || childRef === void 0 ? void 0 : childRef.current; window.addEventListener('resize', onResize); window.addEventListener('scroll', onResize); childElement === null || childElement === void 0 ? void 0 : childElement.addEventListener('transitionend', onResize); return function () { window.removeEventListener('resize', onResize); window.removeEventListener('scroll', onResize); childElement === null || childElement === void 0 ? void 0 : childElement.removeEventListener('transitionend', onResize); }; }, [childRef, onResize]); useLayoutEffect(function () { if (!top && !left) onResize(); }); var top = state.top, left = state.left; var zIndex = useChildZIndex(children); return (React__default.createElement(AnchorStyled, __assign({ anchorToWindow: anchorToWindow, attach: attach, childRect: state.childRect, children: children, margin: margin, rect: state.rect, style: __assign(__assign({}, style), { top: top, left: left, zIndex: zIndex }) }, props))); } function useChildZIndex(children) { var _a; if ((_a = children === null || children === void 0 ? void 0 : children.ref) === null || _a === void 0 ? void 0 : _a.current) { var style = getComputedStyle(children.ref.current); var zIndex = parseInt(style.zIndex); if (zIndex > 0) return zIndex; } return 5000; } function calcRect(ref, _a) { var _b = _a === void 0 ? {} : _a, _c = _b.scrollX, scrollX = _c === void 0 ? 0 : _c, _d = _b.scrollY, scrollY = _d === void 0 ? 0 : _d; if (ref && ref.current) { var _e = ref.current, offsetHeight = _e.offsetHeight, offsetWidth = _e.offsetWidth; var _f = ref.current.getBoundingClientRect(), x = _f.x, y = _f.y; var height = offsetHeight; var left = x + scrollX; var top_1 = y + scrollY; var width = offsetWidth; return { bottom: top_1 + height, height: height, left: left, right: left + width, top: top_1, width: width, }; } return null; } function windowRect() { return { bottom: 0, height: window.innerHeight, left: 0, right: 0, top: 0, width: window.innerWidth, }; } function remPos(_a) { var _b = __read(_a.attach, 2), a = _b[0], b = _b[1], margin = _a.margin, rect = _a.rect, childRect = _a.childRect; if (!rect || !childRect) return { top: null, left: null }; var top = rect.top + rect.height * (a[0] / 100) - (childRect.height + margin * 2) * (b[0] / 100); var left = rect.left + rect.width * (a[1] / 100) - (childRect.width + margin * 2) * (b[1] / 100); return { top: rem(top <= 0 ? rect.bottom : top), left: rem(left <= 0 ? rect.right : left), }; } var AnchorStyled = styled.div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n position: fixed;\n margin: ", ";\n overflow: visible;\n max-width: calc(100vw - 1.5rem) !important;\n\n ", "\n"], ["\n position: fixed;\n margin: ", ";\n overflow: visible;\n max-width: calc(100vw - 1.5rem) !important;\n\n ", "\n"])), function (p) { return rem(p.margin); }, function (p) { return !p.anchorToWindow && css(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n position: absolute;\n\n > div {\n max-width: 100%;\n\n > div {\n max-width: 100%;\n\n > * {\n max-width: 100%;\n }\n }\n }\n "], ["\n position: absolute;\n\n > div {\n max-width: 100%;\n\n > div {\n max-width: 100%;\n\n > * {\n max-width: 100%;\n }\n }\n }\n "]))); }); var templateObject_1, templateObject_2; export { Anchor };