UNPKG

@fluido/react-components

Version:
138 lines (137 loc) 6.52 kB
"use strict"; 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;