@vimeo/iris
Version:
Vimeo Design System
115 lines (108 loc) • 5.88 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var tslib_es6 = require('../../../tslib.es6-3ec409b7.js');
var React = require('react');
var styled = require('styled-components');
var polished = require('polished');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
var styled__default = /*#__PURE__*/_interopDefaultLegacy(styled);
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 = tslib_es6.__rest(_a, ["anchor", "anchorToWindow", "attach", "childRef", "children", "margin", "style"]);
var _b = tslib_es6.__read(React.useState({}), 2), state = _b[0], setState = _b[1];
var onResize = React.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 (tslib_es6.__assign(tslib_es6.__assign({}, state), { top: top, left: left, rect: rect, childRect: childRect })); });
}, [anchor, anchorToWindow, attach, childRef, margin]);
// eslint-disable-next-line react-hooks/exhaustive-deps
React.useLayoutEffect(function () { return onResize(); }, []);
React.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]);
React.useLayoutEffect(function () {
if (!top && !left)
onResize();
});
var top = state.top, left = state.left;
var zIndex = useChildZIndex(children);
return (React__default["default"].createElement(AnchorStyled, tslib_es6.__assign({ anchorToWindow: anchorToWindow, attach: attach, childRect: state.childRect, children: children, margin: margin, rect: state.rect, style: tslib_es6.__assign(tslib_es6.__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 = tslib_es6.__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: polished.rem(top <= 0 ? rect.bottom : top),
left: polished.rem(left <= 0 ? rect.right : left),
};
}
var AnchorStyled = styled__default["default"].div(templateObject_2 || (templateObject_2 = tslib_es6.__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 polished.rem(p.margin); }, function (p) {
return !p.anchorToWindow && styled.css(templateObject_1 || (templateObject_1 = tslib_es6.__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;
exports.Anchor = Anchor;