@stephahart/react-native-pager
Version:
simple pager component for react-native
790 lines (673 loc) • 28.8 kB
JavaScript
'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var React = require('react');
var React__default = _interopDefault(React);
var reactNative = require('react-native');
var Animated = _interopDefault(require('react-native-reanimated'));
var reactNativeGestureHandler = require('react-native-gesture-handler');
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
(function (Extrapolate) {
Extrapolate["EXTEND"] = "extend";
Extrapolate["CLAMP"] = "clamp";
Extrapolate["IDENTITY"] = "identity";
})(exports.Extrapolate || (exports.Extrapolate = {}));
var VERTICAL = 1;
var HORIZONTAL = 2;
var UNSET = -1;
var TRUE = 1;
var FALSE = 0;
var event = Animated.event,
defined = Animated.defined,
block = Animated.block,
Value = Animated.Value,
divide = Animated.divide,
cond = Animated.cond,
eq = Animated.eq,
add = Animated.add,
stopClock = Animated.stopClock,
Clock = Animated.Clock,
set = Animated.set,
clockRunning = Animated.clockRunning,
multiply = Animated.multiply,
sub = Animated.sub,
call = Animated.call,
max = Animated.max,
min = Animated.min,
modulo = Animated.modulo,
not = Animated.not,
greaterThan = Animated.greaterThan,
abs = Animated.abs,
ceil = Animated.ceil,
interpolate = Animated.interpolate,
concat = Animated.concat,
neq = Animated.neq,
and = Animated.and,
proc = Animated.proc,
startClock = Animated.startClock,
spring = Animated.spring,
timing = Animated.timing,
greaterOrEq = Animated.greaterOrEq,
debug = Animated.debug;
var REALLY_BIG_NUMBER = 1000000000; // at its core, this component converts an activeIndex integer value to an Animated.Value
// this animated value represents all intermediate values of a pager, e.g when a user is dragging, the index
// value might be anything between 1 -> 2 as they are moving. when a gesture is completed, it figures out
// the next activeIndex, snaps to it and passes it back. it also handles snapping to different indices when the activeIndex
// prop changes.
// all styles and positioning of child screens can be computed from this one value, based on a childs index and
// any style config props passed to the Pager.
// pretty much all other props passed to the Pager are configurations for different behaviours of what is described above
function Pager(_ref) {
var _ref4, _style2;
var onChange = _ref.onChange,
children = _ref.children,
springConfig = _ref.springConfig,
_ref$panProps = _ref.panProps,
panProps = _ref$panProps === void 0 ? {} : _ref$panProps,
_ref$pageSize = _ref.pageSize,
pageSize = _ref$pageSize === void 0 ? 1 : _ref$pageSize,
_ref$threshold = _ref.threshold,
threshold = _ref$threshold === void 0 ? 0.1 : _ref$threshold,
minIndex = _ref.minIndex,
parentMax = _ref.maxIndex,
_ref$adjacentChildOff = _ref.adjacentChildOffset,
adjacentChildOffset = _ref$adjacentChildOff === void 0 ? 5 : _ref$adjacentChildOff,
style = _ref.style,
containerStyle = _ref.containerStyle,
_ref$type = _ref.type,
type = _ref$type === void 0 ? 'horizontal' : _ref$type,
pageInterpolation = _ref.pageInterpolation,
_ref$clamp = _ref.clamp,
clamp = _ref$clamp === void 0 ? {} : _ref$clamp,
_ref$clampDrag = _ref.clampDrag,
clampDrag = _ref$clampDrag === void 0 ? {} : _ref$clampDrag,
_ref$loop = _ref.loop,
loop = _ref$loop === void 0 ? true : _ref$loop;
var _useContext = React.useContext(PagerContext),
animatedValue = _useContext.animatedValue,
animatedIndex = _useContext.animatedIndex,
nextIndex = _useContext.nextIndex,
activeIndex = _useContext.activeIndex,
setActiveIndex = _useContext.setActiveIndex,
content = _useContext.content;
var numberOfScreens = content ? content.length : 0;
var animatedNumberOfScreens = memoize(new Value(numberOfScreens));
animatedNumberOfScreens.setValue(numberOfScreens);
var initialIndex = memoize(activeIndex);
var animatedLoop = memoize(new Value(loop ? 1 : 0));
animatedLoop.setValue(loop ? 1 : 0);
var dragX = memoize(new Value(0));
var dragY = memoize(new Value(0));
var gestureState = memoize(new Value(0));
var activeIndexSyncRequested = React.useRef(false);
var activeIndexRef = React.useRef(-1);
var handleGesture = memoize(event([{
nativeEvent: {
translationX: dragX,
translationY: dragY
}
}], {
useNativeDriver: true
}));
var handleStateChange = memoize(event([{
nativeEvent: {
state: gestureState
}
}], {
useNativeDriver: true
}));
var initialWidth = UNSET;
if (style && style.width) {
if (typeof style.width === 'number') {
initialWidth = style.width;
}
}
var initialHeight = UNSET;
if (style && style.height) {
if (typeof style.height === 'number') {
initialHeight = style.height;
}
}
var _useState = React.useState(initialWidth),
width = _useState[0],
setWidth = _useState[1];
var _useState2 = React.useState(initialHeight),
height = _useState2[0],
setHeight = _useState2[1]; // assign references based on vertical / horizontal configurations
var dimension = memoize(new Value(0));
var targetDimension = type === 'vertical' ? 'height' : 'width';
var targetTransform = type === 'vertical' ? 'translateY' : 'translateX';
var delta = type === 'vertical' ? dragY : dragX;
var layoutDimension = type === 'vertical' ? height : width; // `totalDimension` on the container view is required for android layouts to work properly
// otherwise translations move the panHandler off of the screen
// set the total width of the container view to the sum width of all the screens
var totalDimension = multiply(dimension, animatedNumberOfScreens);
function handleLayout(_ref2) {
var layout = _ref2.nativeEvent.layout;
layout.width !== width && setWidth(layout.width);
layout.height !== height && setHeight(layout.height);
}
var TYPE = type === 'vertical' ? VERTICAL : HORIZONTAL; // props that might change over time should be reactive:
var animatedThreshold = useAnimatedValue(threshold);
var clampDragPrev = useAnimatedValue(clampDrag.prev, REALLY_BIG_NUMBER);
var clampDragNext = useAnimatedValue(clampDrag.next, REALLY_BIG_NUMBER);
var animatedMaxIndex = parentMax === undefined ? new Value() : new Value(parentMax);
var animatedMinIndex = minIndex === undefined ? new Value() : new Value(minIndex); // pan event values to track
var dragStart = memoize(new Value(0));
var swiping = memoize(new Value(FALSE));
var _animatedActiveIndex = memoize(new Value(initialIndex));
var change = memoize(cond(and(eq(_animatedActiveIndex, 0), greaterThan(animatedValue, sub(animatedNumberOfScreens, 1))), sub(animatedNumberOfScreens, animatedValue), sub(_animatedActiveIndex, animatedValue)));
var absChange = memoize(abs(change));
var shouldTransition = memoize(greaterThan(absChange, animatedThreshold));
var withinRange = memoize(proc(function (n) {
return min(max(n, animatedMinIndex), animatedMaxIndex);
}));
var indexChange = memoize(new Value(0)); // clamp drag values between the configured clamp props
// e.g prev => 0.5, next => 0.5 means change can only be between [-0.5, 0.5]
// minMax order is reversed because next is negative in translation values
var clampedDelta = memoize(min(max(divide(delta, dimension), multiply(clampDragNext, -1)), clampDragPrev));
var clock = memoize(new Clock()); // animatedIndex represents pager position with an animated value
// this value is used to compute the transformations of the container screen
// its also used to compute the offsets of child screens, and any other consumers
var prevIdx = memoize(new Value(initialIndex));
var syncActiveIndex = memoize(function () {
return call([modulo(nextIndex, animatedNumberOfScreens)], function (_ref3) {
var idx = _ref3[0];
activeIndexRef.current = idx;
if (!activeIndexSyncRequested.current) {
activeIndexSyncRequested.current = true;
reactNative.InteractionManager.runAfterInteractions(function () {
activeIndexSyncRequested.current = false;
setActiveIndex(activeIndexRef.current);
onChange == null ? void 0 : onChange(activeIndexRef.current);
});
}
});
});
var _animatedValue = memoize(block([cond(eq(gestureState, reactNativeGestureHandler.State.ACTIVE), [cond(clockRunning(clock), stopClock(clock)), // captures the initial drag value on first drag event
cond(swiping, 0, [set(dragStart, animatedValue), set(swiping, TRUE)]), set(animatedValue, sub(dragStart, clampedDelta))], [// on release -- figure out if the index needs to change, and what index it should change to
cond(swiping, [set(swiping, FALSE), cond(shouldTransition, [// rounds index change if pan gesture greater than just one screen
set(indexChange, ceil(absChange)), // nextIndex set to the next snap point
set(nextIndex, cond(greaterThan(change, 0), [cond(defined(animatedMaxIndex), [withinRange(sub(_animatedActiveIndex, indexChange))], [cond(eq(_animatedActiveIndex, 0), sub(animatedNumberOfScreens, 1), sub(_animatedActiveIndex, indexChange))])], [cond(defined(animatedMaxIndex), [withinRange(add(_animatedActiveIndex, indexChange))], [add(_animatedActiveIndex, indexChange)])]))])]), // set animatedActiveIndex for next swipe event
set(_animatedActiveIndex, modulo(nextIndex, animatedNumberOfScreens)), set(animatedIndex, modulo(nextIndex, animatedNumberOfScreens)), set(animatedValue, runSpring(clock, animatedValue, nextIndex, animatedNumberOfScreens, springConfig, syncActiveIndex))]), cond(not(eq(prevIdx, nextIndex)), [set(prevIdx, nextIndex)]), set(animatedValue, modulo(animatedValue, animatedNumberOfScreens)), animatedValue]));
var clampPrevValue = useAnimatedValue(clamp.prev, add(animatedNumberOfScreens, 1));
var clampNextValue = useAnimatedValue(clamp.next, add(animatedNumberOfScreens, 1)); // stop child screens from translating beyond the bounds set by clamp props:
var minimum = memoize(multiply(sub(_animatedValue, clampPrevValue), dimension));
var maximum = memoize(multiply(add(_animatedValue, clampNextValue), dimension));
var animatedPageSize = useAnimatedValue(pageSize); // container offset -- this is the window of focus for active screens
// it shifts around based on the animatedIndex value
var containerTranslation = memoize(cond(eq(animatedNumberOfScreens, 1), 0, multiply(_animatedValue, dimension, animatedPageSize, -1))); // grabbing the height property from the style prop if there is no container style, this reduces
// the chances of messing up the layout with containerStyle configurations
// can be overridden by the prop itself, but its likely that this is what is intended most of the time
// also has the benefit of covering 100% width of container, meaning better pan coverage on android
var defaultContainerStyle = style && style.height ? {
height: style.height
} : undefined;
var pages = function pages() {
// waiting for initial layout - except when testing
if (width === UNSET) {
return null;
} // slice the children that are rendered by the <Pager />
// this enables very large child lists to render efficiently
// the downside is that children are unmounted after they pass this threshold
// it's an optional prop, however a default value of ~20 is set here to prevent
// possible performance bottlenecks to those not aware of the prop or what it does
// this will slice adjacentChildOffset number of children previous and after
// the current active child index into a smaller child array
// TODO: render end of list if index = 0
// inclusive
var startIndex = 2 * adjacentChildOffset + 1 >= numberOfScreens ? 0 : moduloJs(activeIndex - adjacentChildOffset, numberOfScreens); // exclusive
var endIndex = 2 * adjacentChildOffset + 1 >= numberOfScreens ? numberOfScreens : moduloJs(activeIndex + adjacentChildOffset + 1, numberOfScreens);
var adjacentChildren;
if (startIndex >= endIndex) {
adjacentChildren = [].concat(children.slice(startIndex, numberOfScreens), children.slice(0, endIndex));
} else {
adjacentChildren = children.slice(startIndex, endIndex);
}
return adjacentChildren.map(function (child, i) {
// use map instead of React.Children because we want to track
// the keys of these children by their index
// React.Children shifts these key values intelligently, but it
// causes issues with the memoized values in <Page /> components
var index = moduloJs(i + startIndex, numberOfScreens);
return React__default.createElement(Page, {
key: index + "-" + child.props.content.content_id,
index: index,
animatedIndex: _animatedValue,
minimum: minimum,
maximum: maximum,
dimension: dimension,
targetTransform: targetTransform,
targetDimension: targetDimension,
pageInterpolation: pageInterpolation,
animatedNumberOfScreens: animatedNumberOfScreens,
loop: loop
}, child);
});
}; // extra Animated.Views below may seem redundant but they preserve applied styles e.g padding and margin
// of the page views
return React__default.createElement(Animated.View, {
style: containerStyle || defaultContainerStyle || {
flex: 1
}
}, React__default.createElement(Animated.Code, {
key: layoutDimension,
exec: cond( // dimension already set to last layout
and(eq(dimension, width), eq(dimension, height)), [], [cond(eq(TYPE, VERTICAL), set(dimension, height), set(dimension, width))])
}), React__default.createElement(reactNativeGestureHandler.PanGestureHandler, Object.assign({}, panProps, {
onGestureEvent: handleGesture,
onHandlerStateChange: handleStateChange
}), React__default.createElement(Animated.View, {
style: {
flex: 1
}
}, React__default.createElement(Animated.View, {
style: style || {
flex: 1
}
}, React__default.createElement(Animated.View, {
style: {
flex: 1
},
onLayout: handleLayout
}, React__default.createElement(Animated.View, {
style: (_style2 = {
flex: 1
}, _style2[targetDimension] = totalDimension, _style2.transform = [(_ref4 = {}, _ref4[targetTransform] = containerTranslation, _ref4)], _style2)
}, pages()))))));
}
var Page =
/*#__PURE__*/
React__default.memo(function (_ref5) {
var _ref6, _memoize;
var children = _ref5.children,
index = _ref5.index,
minimum = _ref5.minimum,
maximum = _ref5.maximum,
dimension = _ref5.dimension,
targetTransform = _ref5.targetTransform,
targetDimension = _ref5.targetDimension,
pageInterpolation = _ref5.pageInterpolation,
animatedIndex = _ref5.animatedIndex,
animatedNumberOfScreens = _ref5.animatedNumberOfScreens,
loop = _ref5.loop;
// compute the absolute position of the page based on index and dimension
// this means that it's not relative to any other child, which is good because
// it doesn't rely on a mechanism like flex, which requires all children to be present
// to properly position pages
var position = memoize(cond(eq(animatedNumberOfScreens, 1), 0, cond(and(eq(index, 0), greaterThan(animatedIndex, sub(animatedNumberOfScreens, 1))), // if we're in the last position of the loop, and we're calulcating the position for the first page
[multiply(animatedNumberOfScreens, dimension)], // position the first item
multiply(index, dimension) // normal position
)));
var defaultStyle = memoize((_memoize = {}, _memoize[targetDimension] = dimension, _memoize.transform = [(_ref6 = {}, _ref6[targetTransform] = position, _ref6)], _memoize));
var styleOffset = memoize(cond(eq(animatedNumberOfScreens, 1), 0, cond(eq(index, 0), cond(greaterOrEq(animatedIndex, sub(animatedNumberOfScreens, 1)), sub(animatedNumberOfScreens, animatedIndex), sub(index, animatedIndex)), sub(index, animatedIndex)))); // apply interpolation configs to <Page />
var interpolatedStyles = memoize(interpolateWithConfig(styleOffset, animatedNumberOfScreens, pageInterpolation)); // take out zIndex here as it needs to be applied to siblings
var zIndex = interpolatedStyles.zIndex,
otherStyles = _objectWithoutPropertiesLoose(interpolatedStyles, ["zIndex"]); // zIndex is not a requirement of interpolation
// it will be clear when someone needs it as views will overlap with some configurations
if (!zIndex) {
zIndex = 0;
}
return React__default.createElement(Animated.View, {
style: _extends({}, reactNative.StyleSheet.absoluteFillObject, {}, defaultStyle, {
zIndex: zIndex
})
}, React__default.createElement(Animated.View, {
style: [reactNative.StyleSheet.absoluteFillObject, otherStyles]
}, children));
}); // utility to update animated values without changing their reference
// this is key for using memoized Animated.Values and prevents costly rerenders
function useAnimatedValue(value, defaultValue) {
if (defaultValue === void 0) {
defaultValue = 0;
}
var initialValue = value !== undefined ? value : defaultValue;
var animatedValue = memoize(typeof defaultValue === 'number' ? new Value(initialValue) : defaultValue);
React.useEffect(function () {
if (value !== undefined) {
animatedValue.setValue(value);
}
}, [value, defaultValue]);
return animatedValue;
}
var PagerContext =
/*#__PURE__*/
React.createContext({
animatedValue:
/*#__PURE__*/
new Value(0),
animatedIndex:
/*#__PURE__*/
new Value(0),
nextIndex:
/*#__PURE__*/
new Value(0),
activeIndex: 0,
setActiveIndex: function setActiveIndex(_) {
return null;
},
content: [],
setContent: function setContent(_) {
return null;
},
setState: function setState(_) {
return null;
}
});
var PagerProvider = function PagerProvider(_ref7) {
var children = _ref7.children,
_ref7$initialIndex = _ref7.initialIndex,
initialIndex = _ref7$initialIndex === void 0 ? 0 : _ref7$initialIndex;
var _useState3 = React.useState({
activeIndex: initialIndex,
content: null
}),
state = _useState3[0],
setState = _useState3[1];
var animatedValue = memoize(new Value(initialIndex));
var animatedIndex = memoize(new Value(initialIndex));
var nextIndex = memoize(new Value(initialIndex));
var setActiveIndex = function setActiveIndex(idx) {
return setState(function (s) {
return _extends({}, s, {
activeIndex: idx
});
});
};
var setContent = function setContent(content) {
return setState(function (s) {
return _extends({}, s, {
content: content
});
});
};
return React__default.createElement(PagerContext.Provider, {
value: {
animatedValue: animatedValue,
animatedIndex: animatedIndex,
nextIndex: nextIndex,
activeIndex: state.activeIndex,
content: state.content,
setActiveIndex: setActiveIndex,
setContent: setContent,
setState: setState
}
}, typeof children === 'function' ? children({
animatedValue: animatedValue,
animatedIndex: animatedIndex,
nextIndex: nextIndex,
activeIndex: state.activeIndex,
setActiveIndex: setActiveIndex,
content: state.content,
setContent: setContent,
setState: setState
}) : children);
};
function usePager() {
var context = React.useContext(PagerContext);
if (context === undefined) {
throw new Error("usePager() must be used within a <PagerProvider />");
}
return context;
}
var IndexContext =
/*#__PURE__*/
React__default.createContext(undefined);
function useIndex() {
var index = React.useContext(IndexContext);
if (index === undefined) {
throw new Error("useIndex() must be used within an <IndexProvider />");
}
return index;
}
function useAnimatedIndex() {
var pager = usePager();
return pager[2];
}
function useOffset(index, animatedNumberOfScreens) {
var animatedIndex = useAnimatedIndex();
var offset = memoize(cond(eq(animatedNumberOfScreens, 1), 0, cond(eq(index, 0), cond(greaterOrEq(animatedIndex, sub(animatedNumberOfScreens, 1)), sub(animatedNumberOfScreens, animatedIndex), sub(index, animatedIndex)), sub(index, animatedIndex))));
return offset;
}
function useInterpolation(pageInterpolation, animatedNumberOfScreens, index) {
var _index = index !== undefined ? index : useIndex();
var offset = useOffset(_index, animatedNumberOfScreens);
var styles = memoize(interpolateWithConfig(offset, animatedNumberOfScreens, pageInterpolation));
return styles;
}
function interpolateWithConfig(offset, animatedNumberOfScreens, pageInterpolation) {
if (!pageInterpolation) {
return {};
}
return Object.keys(pageInterpolation).reduce(function (styles, key) {
var currentStyle = pageInterpolation[key];
if (Array.isArray(currentStyle)) {
var _style = currentStyle.map(function (interpolationConfig) {
return interpolateWithConfig(offset, animatedNumberOfScreens, interpolationConfig);
});
styles[key] = _style;
return styles;
}
if (typeof currentStyle === 'object') {
var _style3;
var unit = currentStyle.unit,
rest = _objectWithoutPropertiesLoose(currentStyle, ["unit"]);
if (currentStyle.unit) {
_style3 = concat(interpolate(offset, rest), currentStyle.unit);
} else {
_style3 = interpolate(offset, currentStyle);
}
styles[key] = _style3;
return styles;
}
if (typeof currentStyle === 'function') {
var _style4 = currentStyle(offset);
styles[key] = _style4;
return styles;
}
return styles;
}, {});
}
function memoize(value) {
var ref = React__default.useRef(value);
return ref.current;
}
var DEFAULT_SPRING_CONFIG = {
stiffness: 1000,
damping: 500,
mass: 3,
overshootClamping: false,
restDisplacementThreshold: 0.01,
restSpeedThreshold: 0.01
};
function runSpring(clock, position, toValue, numPages, springConfig, onEnd) {
var state = {
finished: new Value(0),
velocity: new Value(0),
position: position,
time: new Value(0)
};
var config = _extends({}, DEFAULT_SPRING_CONFIG, {}, springConfig, {
toValue: new Value(0)
});
var calcToValue = proc(function (position, toValue, numPages) {
return block([cond(and(eq(toValue, 0), greaterOrEq(position, sub(numPages, 1))), numPages, toValue)]);
});
var adjToValue = new Value(0);
var prev = new Value(-1);
var updateActiveValue = function updateActiveValue() {
return cond(neq(prev, config.toValue), [set(prev, toValue), onEnd == null ? void 0 : onEnd()]);
};
return block([set(adjToValue, calcToValue(position, toValue, numPages)), cond(clockRunning(clock), 0, // this never happens because we stop the clock when the user starts swiping
[set(state.finished, 0), set(state.time, 0), set(state.velocity, 0), updateActiveValue(), set(config.toValue, adjToValue), startClock(clock)]), spring(clock, state, config), cond(state.finished, [stopClock(clock), set(toValue, modulo(toValue, numPages)), set(state.position, toValue), updateActiveValue()]), state.position]);
} // a % b but handles negatives
var moduloJs = function moduloJs(a, b) {
return (a % b + b) % b;
};
var interpolate$1 = Animated.interpolate,
concat$1 = Animated.concat,
Value$1 = Animated.Value,
clockRunning$1 = Animated.clockRunning,
cond$1 = Animated.cond,
neq$1 = Animated.neq,
set$1 = Animated.set,
startClock$1 = Animated.startClock,
spring$1 = Animated.spring,
stopClock$1 = Animated.stopClock,
block$1 = Animated.block;
function interpolateWithConfig$1(offset, pageInterpolation) {
if (!pageInterpolation) {
return {};
}
return Object.keys(pageInterpolation).reduce(function (styles, key) {
var currentStyle = pageInterpolation[key];
if (Array.isArray(currentStyle)) {
var _style = currentStyle.map(function (interpolationConfig) {
return interpolateWithConfig$1(offset, interpolationConfig);
});
styles[key] = _style;
return styles;
}
if (typeof currentStyle === 'object') {
var _style2;
var unit = currentStyle.unit,
rest = _objectWithoutPropertiesLoose(currentStyle, ["unit"]);
if (currentStyle.unit) {
_style2 = concat$1(interpolate$1(offset, rest), currentStyle.unit);
} else {
_style2 = interpolate$1(offset, currentStyle);
}
styles[key] = _style2;
return styles;
}
if (typeof currentStyle === 'function') {
var _style3 = currentStyle(offset);
styles[key] = _style3;
return styles;
}
return styles;
}, {});
}
function memoize$1(value) {
var ref = React.useRef(value);
return ref.current;
}
var Value$2 = Animated.Value,
divide$1 = Animated.divide,
multiply$1 = Animated.multiply,
add$1 = Animated.add;
var DEFAULT_PAGINATION_STYLE = {
height: 50,
width: '100%',
flexDirection: 'row'
};
function Pagination(_ref) {
var children = _ref.children,
pageInterpolation = _ref.pageInterpolation,
style = _ref.style;
return React__default.createElement(Animated.View, {
style: _extends({}, DEFAULT_PAGINATION_STYLE, {}, style)
}, React.Children.map(children, function (child, index) {
return React__default.createElement(PaginationItem, {
index: index,
pageInterpolation: pageInterpolation,
style: child.props.style
}, child);
}));
}
function PaginationItem(_ref2) {
var children = _ref2.children,
pageInterpolation = _ref2.pageInterpolation,
index = _ref2.index,
style = _ref2.style;
var offset = useOffset(index);
var configStyles = memoize$1(interpolateWithConfig$1(offset, pageInterpolation));
return React__default.createElement(Animated.View, {
style: [style || {
flex: 1
}, configStyles]
}, children);
}
var DEFAULT_SLIDER_STYLE = {
height: 2,
backgroundColor: 'aquamarine'
};
function Slider(_ref3) {
var numberOfScreens = _ref3.numberOfScreens,
style = _ref3.style;
var animatedIndex = useAnimatedIndex();
var width = memoize$1(new Value$2(0));
function handleLayout(_ref4) {
var layout = _ref4.nativeEvent.layout;
width.setValue(layout.width);
}
var sliderWidth = divide$1(width, numberOfScreens);
var translation = memoize$1(multiply$1(animatedIndex, sliderWidth));
return React__default.createElement(Animated.View, {
onLayout: handleLayout
}, React__default.createElement(Animated.View, {
style: _extends({
width: sliderWidth,
transform: [{
translateX: translation
}]
}, DEFAULT_SLIDER_STYLE, {}, style)
}));
}
function Progress(_ref5) {
var numberOfScreens = _ref5.numberOfScreens,
style = _ref5.style;
var animatedIndex = useAnimatedIndex();
var width = memoize$1(new Value$2(0));
function handleLayout(_ref6) {
var layout = _ref6.nativeEvent.layout;
width.setValue(layout.width);
}
var sliderWidth = memoize$1(divide$1(width, numberOfScreens, divide$1(1, add$1(animatedIndex, 1))));
return React__default.createElement(Animated.View, {
onLayout: handleLayout
}, React__default.createElement(Animated.View, {
style: _extends({
width: sliderWidth,
height: 2,
backgroundColor: 'rebeccapurple'
}, DEFAULT_SLIDER_STYLE, {}, style)
}));
}
exports.Pager = Pager;
exports.PagerContext = PagerContext;
exports.PagerProvider = PagerProvider;
exports.Pagination = Pagination;
exports.Progress = Progress;
exports.Slider = Slider;
exports.interpolateWithConfig = interpolateWithConfig$1;
exports.useAnimatedIndex = useAnimatedIndex;
exports.useIndex = useIndex;
exports.useInterpolation = useInterpolation;
exports.useOffset = useOffset;
exports.usePager = usePager;
//# sourceMappingURL=react-native-pager.cjs.development.js.map