UNPKG

one

Version:

One is a React framework for web, iOS, and Android apps.

208 lines (207 loc) • 7.16 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var Pager_exports = {}; __export(Pager_exports, { Pager: () => Pager }); module.exports = __toCommonJS(Pager_exports); var import_react = require("react"); var import_pagerTypes = require("./pagerTypes.cjs"); var import_DomView = require("../web/DomView.cjs"); var import_jsx_runtime = require("react/jsx-runtime"); function event(nativeEvent) { return { nativeEvent }; } const Pager = (0, import_react.forwardRef)(function Pager2({ children, initialPage = 0, scrollEnabled = true, orientation = "horizontal", layoutDirection = "ltr", pageMargin = 0, onPageScroll, onPageSelected, onPageScrollStateChanged, keyboardDismissMode = "none", style, testID, ...props }, ref) { (0, import_pagerTypes.validatePager)({ ...props, initialPage, orientation, layoutDirection, pageMargin, keyboardDismissMode }); const container = (0, import_react.useRef)(null); const callbacks = (0, import_react.useRef)({ onPageScroll, onPageSelected, onPageScrollStateChanged }); callbacks.current = { onPageScroll, onPageSelected, onPageScrollStateChanged }; const pointer = (0, import_react.useRef)(null); const selected = (0, import_react.useRef)(initialPage); const initialized = (0, import_react.useRef)(false); const state = (0, import_react.useRef)("idle"); const [enabled, setEnabled] = (0, import_react.useState)(scrollEnabled); const vertical = orientation === "vertical"; const count = import_react.Children.count(children); const dimensions = (0, import_react.useRef)({ vertical, rtl: layoutDirection === "rtl", pageMargin, count }); dimensions.current = { vertical, rtl: layoutDirection === "rtl", pageMargin, count }; function setState(next) { if (state.current === next) return; state.current = next; callbacks.current.onPageScrollStateChanged?.(event({ pageScrollState: next })); } function scroll() { const node = container.current; if (!node || !count) return; const stride = (vertical ? node.clientHeight : node.clientWidth) + pageMargin; if (!stride) return; const value = Math.max(0, Math.min(count - 1, (vertical ? node.scrollTop : Math.abs(node.scrollLeft)) / stride)); callbacks.current.onPageScroll?.(event({ position: Math.floor(value), offset: value - Math.floor(value) })); } function settle() { const node = container.current; if (!node || !count) return; const stride = (vertical ? node.clientHeight : node.clientWidth) + pageMargin; if (!stride) return; const page = Math.max(0, Math.min(count - 1, Math.round((vertical ? node.scrollTop : Math.abs(node.scrollLeft)) / stride))); if (page !== selected.current || !initialized.current) { selected.current = page; callbacks.current.onPageSelected?.(event({ position: page })); } initialized.current = true; callbacks.current.onPageScroll?.(event({ position: page, offset: 0 })); setState("idle"); } function goTo(index, animated) { (0, import_pagerTypes.validatePage)(index); const node = container.current; const d = dimensions.current; if (!node || index >= d.count) return; const offset = index * ((d.vertical ? node.clientHeight : node.clientWidth) + d.pageMargin); if (animated && index !== selected.current) setState("settling"); node.scrollTo({ left: d.vertical ? 0 : offset * (d.rtl ? -1 : 1), top: d.vertical ? offset : 0, behavior: animated ? "smooth" : "instant" }); if (!animated) settle(); } (0, import_react.useImperativeHandle)(ref, () => ({ setPage: (index) => goTo(index, true), setPageWithoutAnimation: (index) => goTo(index, false), setScrollEnabled: setEnabled })); (0, import_react.useEffect)(() => setEnabled(scrollEnabled), [scrollEnabled]); (0, import_react.useLayoutEffect)(() => { const node = container.current; if (!node) return; const resize = new ResizeObserver(() => goTo(Math.min(selected.current, Math.max(0, count - 1)), false)); resize.observe(node); goTo(Math.min(selected.current, Math.max(0, count - 1)), false); node.addEventListener("scrollend", settle); return () => { resize.disconnect(); node.removeEventListener("scrollend", settle); }; }, [ count, orientation, layoutDirection, pageMargin ]); const css = { ...(0, import_DomView.domStyle)(style), display: "flex", position: "relative", flexDirection: vertical ? "column" : "row", direction: layoutDirection, overflowX: enabled && !vertical ? "auto" : "hidden", overflowY: enabled && vertical ? "auto" : "hidden", scrollSnapType: `${vertical ? "y" : "x"} mandatory`, gap: pageMargin, scrollbarWidth: "none", overscrollBehavior: "contain" }; return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: container, style: css, "data-testid": testID, onScroll: scroll, onPointerDown: (e) => { const node = container.current; if (!enabled || !node) return; pointer.current = { x: e.clientX, y: e.clientY, offset: vertical ? node.scrollTop : node.scrollLeft }; }, onPointerMove: (e) => { const start = pointer.current; if (!start || !enabled || state.current === "dragging") return; const distance = vertical ? Math.abs(e.clientY - start.y) : Math.abs(e.clientX - start.x); if (distance < 8) return; setState("dragging"); if (keyboardDismissMode === "on-drag" && document.activeElement instanceof HTMLElement) document.activeElement.blur(); }, onPointerUp: () => { const start = pointer.current; const node = container.current; pointer.current = null; if (state.current !== "dragging" || !node) return; if ((vertical ? node.scrollTop : node.scrollLeft) === start?.offset) settle(); else setState("settling"); }, onPointerCancel: () => { pointer.current = null; if (state.current === "dragging") setState("settling"); }, onWheel: () => { if (enabled) setState("dragging"); }, children: import_react.Children.map(children, (child, index) => { if (!(0, import_react.isValidElement)(child)) throw new Error("Pager children must be React Native views"); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: "0 0 100%", display: "flex", flexDirection: "column", width: vertical ? "100%" : void 0, height: vertical ? void 0 : "100%", scrollSnapAlign: "start", position: "relative", overflow: "hidden" }, children: child }, index); }) }); });