one
Version:
One is a React framework for web, iOS, and Android apps.
208 lines (207 loc) • 7.16 kB
JavaScript
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);
})
});
});