@fluido/react-components
Version:
Fluido webapp components
138 lines (137 loc) • 6.52 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const md_1 = require("react-icons/md");
const utils_1 = require("../utils");
const navigation_dots_1 = __importDefault(require("./navigation-dots"));
const styled_1 = require("./styled");
const utils_2 = require("./utils");
const ScrollableList = ({ children, ordered = false, pagination = false, hasIndicator = false, shouldShowPartials = false, paginationStep = 1, snap = 'start', snapType = 'proximity', style, }) => {
const ListType = ordered ? 'ol' : 'ul';
const [hasPointer, setHasPointer] = react_1.useState(true);
const [position, setPosition] = react_1.useState(0);
const [length, setLength] = react_1.useState(0);
const [visibleChildren, setVisibleChildren] = react_1.useState([true]);
const [visibleChildrenPartial, setVisibleChildrenPartial] = react_1.useState([]);
const [parent, setParent] = react_1.useState(null);
const isSSR = utils_1.testIsSSR();
react_1.useEffect(() => {
if (!parent)
return;
const handleScroll = () => {
const visibleChildren = utils_2.getChildrenVisible(parent);
const visibleChildrenPartial = utils_2.getChildrenVisible(parent, true);
const currentPos = utils_2.getNearestChildIndex(parent, snap);
setPosition(currentPos);
setVisibleChildren(visibleChildren);
setVisibleChildrenPartial(visibleChildrenPartial);
setLength(parent.children.length);
};
const drag = {
click: false,
start: false,
position: 0,
scroll: 0,
};
const handleDragStart = (ev) => {
drag.position = ev.clientX;
drag.scroll = parent.scrollLeft;
drag.click = true;
};
const handleDrag = (ev) => {
if (!drag.click)
return;
const currentPosition = ev.clientX;
const distance = drag.position - currentPosition;
if (drag.start || Math.abs(distance)) {
parent.setAttribute('data-drag', distance.toString());
drag.start = true;
parent.scrollTo({
left: drag.scroll + distance,
top: 0,
});
}
};
const handleClick = (ev) => {
drag.click = false;
if (drag.start) {
drag.start = false;
parent.removeAttribute('data-drag');
ev.stopPropagation();
}
};
const mutation = new MutationObserver((ml) => {
for (const m of ml) {
if (m.type === 'childList') {
handleScroll();
}
}
});
mutation.observe(parent, {
childList: true,
});
const asyncHandleScroll = () => {
setTimeout(handleScroll, 0);
};
parent.addEventListener('scroll', asyncHandleScroll);
parent.addEventListener('mousedown', handleDragStart);
window.addEventListener('mousemove', handleDrag);
window.addEventListener('mouseup', handleClick);
window.addEventListener('click', handleClick);
handleScroll();
return () => {
parent.removeEventListener('scroll', asyncHandleScroll);
parent.removeEventListener('mousedown', handleDragStart);
window.removeEventListener('mousemove', handleDrag);
window.removeEventListener('mouseup', handleClick);
window.removeEventListener('click', handleClick);
mutation.disconnect();
};
}, [parent, snap]);
react_1.useEffect(() => {
!isSSR &&
window.matchMedia &&
window.matchMedia('(any-pointer:fine)').matches
? setHasPointer(true)
: setHasPointer(false);
}, [hasPointer, isSSR]);
const validatePosition = (pos) => {
if (pos < 0)
return 0;
if (pos >= parent.children.length)
return parent.children.length - 1;
return pos;
};
const scrollToPosition = (targetPosition) => {
const validPosition = validatePosition(targetPosition);
const child = parent.children[validPosition];
utils_2.animatedScrollTo(parent, child, snap);
};
const scrollToDirection = (direction) => {
if (!pagination || !parent)
return;
const visibleWidth = parent.parentElement.offsetWidth;
const scrollAmount = direction === 'backwards' ? -visibleWidth : visibleWidth;
if (paginationStep === 'full') {
utils_2.animatedScrollTo(parent, scrollAmount, snap);
return;
}
const targetPosition = direction === 'backwards'
? position - paginationStep
: position + paginationStep;
scrollToPosition(targetPosition);
};
const scrollForwards = () => scrollToDirection('forwards');
const scrollBackwards = () => scrollToDirection('backwards');
return (jsx_runtime_1.jsxs(styled_1.ScrollableWrapper, Object.assign({ style: style, snapType: snapType, snap: snap }, { children: [pagination && hasPointer && !visibleChildren[0] && (jsx_runtime_1.jsx(styled_1.ScrollButton, Object.assign({ onClick: scrollBackwards, position: 'left' }, { children: jsx_runtime_1.jsx(md_1.MdChevronLeft, {}, void 0) }), void 0)),
jsx_runtime_1.jsx(ListType, Object.assign({ ref: setParent }, { children: children }), void 0),
pagination &&
hasPointer &&
!visibleChildren[visibleChildren.length - 1] && (jsx_runtime_1.jsx(styled_1.ScrollButton, Object.assign({ onClick: scrollForwards, position: 'right' }, { children: jsx_runtime_1.jsx(md_1.MdChevronRight, {}, void 0) }), void 0)),
pagination && hasIndicator && (jsx_runtime_1.jsx(navigation_dots_1.default, { active: position, length: length, group: shouldShowPartials ? visibleChildrenPartial : visibleChildren, onClick: scrollToPosition }, void 0))] }), void 0));
};
exports.default = ScrollableList;