@eccenca/gui-elements
Version:
GUI elements based on other libraries, usable in React application, written in Typescript.
126 lines • 7.35 kB
JavaScript
;
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.StickyTarget = void 0;
const react_1 = __importDefault(require("react"));
const common_1 = require("../../common/");
const constants_1 = require("../../configuration/constants");
/**
* Element wraps the content that need to be displayed sticky.
* The content then offset relative to its nearest scrolling ancestor and containing block (nearest block-level ancestor).
*/
const StickyTarget = (_a) => {
var { className, to = "top", local = false, offset, background = "transparent", fillMainGap, fillSecondaryGap, style, getConnectedElement } = _a, otherDivProps = __rest(_a, ["className", "to", "local", "offset", "background", "fillMainGap", "fillSecondaryGap", "style", "getConnectedElement"]);
const stickyTargetRef = react_1.default.useRef(null);
let offsetStyle = {};
if (typeof offset !== "undefined") {
offsetStyle = Object.assign(Object.assign({}, style), { "--eccgui-sticky-target-localoffset": offset });
}
react_1.default.useEffect(() => {
let removeEventForConnectedOffset = () => {
/* no event need to be removed */
};
let removeEventForStickynessCheck = () => {
/* no event need to be removed */
};
/**
* If the target should be sticky to a defined element then:
* * check for the element and its scroll parent
* * listen to scroll events and use the elements position as offset
*/
if (getConnectedElement && stickyTargetRef) {
const stickyConnection = getConnectedElement(stickyTargetRef);
if (stickyConnection) {
const scrollParent = common_1.utils.getScrollParent(stickyConnection);
const scrollParentFallback = !scrollParent ? document.documentElement : false;
if (scrollParent || scrollParentFallback) {
const updateTargetOffset = () => {
var _a;
let connectedOffset = 0;
const scrollParentPosition = (scrollParent || scrollParentFallback).getBoundingClientRect();
const stickyConnectionPosition = stickyConnection.getBoundingClientRect();
if (to === "top") {
connectedOffset =
stickyConnectionPosition.top -
Math.max(0, scrollParentPosition.top) +
stickyConnectionPosition.height;
}
if (to === "bottom") {
connectedOffset =
Math.max(scrollParentPosition.height, scrollParentPosition.bottom) -
stickyConnectionPosition.bottom +
stickyConnectionPosition.height;
}
(_a = stickyTargetRef.current) === null || _a === void 0 ? void 0 : _a.style.setProperty("--eccgui-sticky-target-applicationoffset", `${connectedOffset}px`);
};
updateTargetOffset();
const eventListeningTarget = scrollParent || window;
const eventListeningMethod = (_event) => {
updateTargetOffset();
};
eventListeningTarget.addEventListener("scroll", eventListeningMethod);
removeEventForConnectedOffset = () => {
eventListeningTarget.removeEventListener("scroll", eventListeningMethod);
};
}
}
}
/**
* Check if sticky target element is currently in sticky mode.
* sticky mode = current position === defined sticky position
*/
if (stickyTargetRef && (fillMainGap || fillSecondaryGap)) {
const stickyTarget = stickyTargetRef.current;
const scrollParent = common_1.utils.getScrollParent(stickyTarget);
const checkStickyness = () => {
const definedPosition = parseInt(window.getComputedStyle(stickyTarget)[to], 10);
const scrollParentPosition = scrollParent ? scrollParent.getBoundingClientRect()[to] : 0;
const currentPosition = (to === "top" ? 1 : -1) * (stickyTarget.getBoundingClientRect()[to] - scrollParentPosition);
// check stickyness in a small position range (not exact value) because of float values
const isSticky = currentPosition <= definedPosition + 1 && currentPosition >= definedPosition - 1;
if (isSticky && !stickyTarget.classList.contains(`${constants_1.CLASSPREFIX}-sticky__target--issticky`)) {
stickyTarget.classList.add(`${constants_1.CLASSPREFIX}-sticky__target--issticky`);
}
if (!isSticky && stickyTarget.classList.contains(`${constants_1.CLASSPREFIX}-sticky__target--issticky`)) {
stickyTarget.classList.remove(`${constants_1.CLASSPREFIX}-sticky__target--issticky`);
}
};
checkStickyness();
const eventListeningTarget = scrollParent || window;
const eventListeningMethod = (_event) => {
checkStickyness();
};
eventListeningTarget.addEventListener("scroll", eventListeningMethod);
removeEventForStickynessCheck = () => {
eventListeningTarget.removeEventListener("scroll", eventListeningMethod);
};
}
return () => {
removeEventForConnectedOffset();
removeEventForStickynessCheck();
};
}, [getConnectedElement, stickyTargetRef, to, fillMainGap, fillSecondaryGap]);
return (react_1.default.createElement("div", Object.assign({ ref: stickyTargetRef, className: `${constants_1.CLASSPREFIX}-sticky__target` +
(to ? ` ${constants_1.CLASSPREFIX}-sticky__target--${to}` : "") +
(local ? ` ${constants_1.CLASSPREFIX}-sticky__target--localscrollarea` : "") +
(background ? ` ${constants_1.CLASSPREFIX}-sticky__target--bg-${background}` : "") +
(fillMainGap ? ` ${constants_1.CLASSPREFIX}-sticky__target--maingapfill-${fillMainGap}` : "") +
(fillSecondaryGap ? ` ${constants_1.CLASSPREFIX}-sticky__target--secondarygapfill-${fillSecondaryGap}` : "") +
(className ? ` ${className}` : ""), style: offset ? offsetStyle : style }, otherDivProps)));
};
exports.StickyTarget = StickyTarget;
exports.default = exports.StickyTarget;
//# sourceMappingURL=StickyTarget.js.map