@smart-react-components/ui
Version:
SRC UI includes React and Styled components.
159 lines (158 loc) • 7.58 kB
JavaScript
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;
;