UNPKG

@smart-react-components/ui

Version:
159 lines (158 loc) 7.58 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const Div_1 = __importDefault(require("@smart-react-components/core/Element/Div")); const element_props_1 = __importDefault(require("@smart-react-components/core/element-props")); const click_events_1 = __importDefault(require("@smart-react-components/core/element-props/click-events")); const dom_1 = require("@smart-react-components/core/util/dom"); const react_1 = __importDefault(require("react")); const react_dom_1 = require("react-dom"); const styled_components_1 = require("styled-components"); const dom_2 = require("../util/dom"); const OverlayElement_1 = __importDefault(require("../components/Overlay/OverlayElement")); const Overlay = react_1.default.forwardRef((props, forwardRef) => { var _a; const theme = react_1.default.useContext(styled_components_1.ThemeContext); const ref = (_a = forwardRef) !== null && _a !== void 0 ? _a : react_1.default.useRef(null); const getInBody = () => (props.isInBody || props.hasBlurEffect) && (0, dom_2.canBeRenderedInPortal)(); const getActive = () => (props.hasBlurEffect && (0, dom_2.canBeRenderedInPortal)()) && ((props.breakpoint && window.innerWidth < theme.$.length.breakpoint[props.breakpoint]) || !props.breakpoint); const getFront = () => { if (!isActive) { return false; } const activeOverlayEls = document.querySelectorAll('body > *[data-src-overlay="visible"]'); return activeOverlayEls[activeOverlayEls.length - 1] === ref.current; }; const [isInBody, setInBody] = react_1.default.useState(() => getInBody()); const [isActive, setActive] = react_1.default.useState(() => getActive()); const [isFront, setFront] = react_1.default.useState(() => getFront()); const handleResize = () => setActive(getActive()); const handleMouseWheel = (e) => { const activeOverlayEls = document.querySelectorAll('body > *[data-src-overlay="visible"]'); if (activeOverlayEls[activeOverlayEls.length - 1] !== ref.current) { return; } const container = ref.current; const delta = ((e.deltaY || -e.wheelDelta || e.detail) >> 10) || 1; const up = delta < 0; const el = e.target; let scrollEl = (0, dom_2.isElementScrollable)(el) ? el : (0, dom_2.getScrollParent)(el); while (scrollEl && (scrollEl === container || container.contains(scrollEl))) { if ((up && scrollEl.scrollTop > 0) || (!up && scrollEl.scrollHeight > scrollEl.scrollTop)) { return; } else { scrollEl = (0, dom_2.getScrollParent)(scrollEl); } } e.preventDefault(); e.stopPropagation(); }; const handleSelectStart = (e) => { if (e.target === ref.current) { e.preventDefault(); } }; const applyBlurEffect = react_1.default.useCallback((el) => { el.classList.add('src-blur-effect'); let value = 1; el.style.filter = `blur(${value}px)`; const interval = setInterval(() => { value++; if (value > 5 || !el.classList.contains('src-blur-effect')) { clearInterval(interval); } else { el.style.filter = `blur(${value}px)`; } }, 100); }, []); const removeBlurEffect = react_1.default.useCallback((el) => { el.classList.remove('src-blur-effect'); let value = 4; el.style.filter = `blur(${value}px)`; const interval = setInterval(() => { if (el.classList.contains('src-blur-effect')) { value = 0; } else { value--; } el.style.filter = `blur(${value}px)`; if (value === 0) { clearInterval(interval); } }, 100); }, []); react_1.default.useEffect(() => { if (props.hasBlurEffect && !props.isInBody) { (0, dom_1.displayWarning)('The component is always rendered directly in body when it has blur effect.'); } setInBody(getInBody()); }, [props.hasBlurEffect, props.isInBody]); react_1.default.useEffect(() => { if (isInBody) { (0, dom_1.addEventListener)(window, ['resize'], handleResize); handleResize(); return () => { (0, dom_1.removeEventListener)(window, ['resize'], handleResize); }; } else { setActive(false); } }, [isInBody, props.breakpoint, isActive]); react_1.default.useEffect(() => setFront(getFront()), [isActive]); react_1.default.useEffect(() => { if (isFront) { (0, dom_1.addEventListener)(document, dom_2.mouseWheel, handleMouseWheel, { passive: false }); (0, dom_1.addEventListener)(window, ['selectstart'], handleSelectStart); return () => { (0, dom_1.removeEventListener)(document, dom_2.mouseWheel, handleMouseWheel, {}); (0, dom_1.removeEventListener)(window, ['selectstart'], handleSelectStart); }; } }, [isFront]); react_1.default.useEffect(() => { if (isFront) { const list = document.querySelectorAll('body > *'); list.forEach(item => { if (item.nodeName !== 'SCRIPT' && item !== ref.current && !item.classList.contains('src-blur-effect') && !item.classList.contains('src-replica')) { applyBlurEffect(item); } }); return () => { const activeOverlayEls = document.querySelectorAll('body > *[data-src-overlay="visible"]'); if (activeOverlayEls.length > 0) { const activeOverlayEl = activeOverlayEls[activeOverlayEls.length - 1]; if (activeOverlayEl.classList.contains('src-blur-effect')) { removeBlurEffect(activeOverlayEl); } } else { document.querySelectorAll('body > *').forEach(item => { if (item.classList.contains('src-blur-effect')) { removeBlurEffect(item); } }); } }; } }, [isFront]); const Element = react_1.default.cloneElement(props.template, Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ isDisplayedWhenBreakpointNull: true }, props.elementProps), { breakpoint: props.breakpoint, hasBackground: props.hasBackground, ref }), props.template.props), (isInBody && { 'data-src-overlay': isActive ? 'visible' : 'hidden' })), { children: (react_1.default.createElement(react_1.default.Fragment, null, react_1.default.createElement(Div_1.default, Object.assign({ height: "100%", left: 0, position: "absolute", top: 0, width: "100%" }, (0, element_props_1.default)(props, [click_events_1.default]))), props.children)) })); return isInBody ? (0, react_dom_1.createPortal)(Element, document.body) : Element; }); Overlay.defaultProps = { hasBackground: true, isInBody: true, template: react_1.default.createElement(OverlayElement_1.default, null), }; exports.default = Overlay;