@retailmenot/anchor
Version:
A React UI Library by RetailMeNot
407 lines (368 loc) • 12.5 kB
JavaScript
import { c as _slicedToArray, a as _taggedTemplateLiteral } from './anchor-chunk-7b9d8557.js';
import { a as __rest } from './anchor-chunk-27f34e54.js';
import { a as Button } from './anchor-chunk-e1ca097b.js';
import { Input } from './form.js';
import { forwardRef, createElement, useContext, useState, Children, Fragment, useEffect, useRef, createRef, Component, cloneElement, useReducer, PureComponent, isValidElement, createContext, useImperativeHandle } from 'react';
import classNames from 'classnames';
import styled from '@xstyled/styled-components';
import { space } from '@xstyled/system';
import './addevent.js';
import './anchor-chunk-25c07228.js';
import './arrowback.js';
import './arrowforward.js';
import './avataricon.js';
import './avataroutline.js';
import './barcode.js';
import './bulletlist.js';
import './calendar.js';
import './camera.js';
import './cart.js';
import './cashback.js';
import './cells.js';
import './chat.js';
import './check.js';
import './checksmall.js';
import './chevrondown.js';
import './chevrondownsmall.js';
import { ChevronLeft } from './chevronleft.js';
import './chevronleftsmall.js';
import { ChevronRight } from './chevronright.js';
import './chevronrightsmall.js';
import './chevronup.js';
import './chevronupsmall.js';
import './clock.js';
import './close.js';
import './closesmall.js';
import './commentmore.js';
import './creditcard.js';
import './crosshairs.js';
import './cut.js';
import './disabled.js';
import './dislike.js';
import './download.js';
import { Ellipses } from './ellipses.js';
import './ellipsesvertical.js';
import './envelope.js';
import './envelopeopen.js';
import './error.js';
import './expand.js';
import './gear.js';
import './giftcard.js';
import './hamburger.js';
import './heart.js';
import './heartoutline.js';
import './home.js';
import './info.js';
import './infooutline.js';
import './laptop.js';
import './lightning.js';
import './like.js';
import './listicon.js';
import './lock.js';
import './map.js';
import './marker.js';
import './markeroutline.js';
import './mobile.js';
import './news.js';
import './pencil.js';
import './play.js';
import './plus.js';
import './plussmall.js';
import './print.js';
import './question.js';
import './questionoutline.js';
import './refresh.js';
import './retailmenotlogo.js';
import './sadface.js';
import './search.js';
import './share.js';
import './sliders.js';
import './star.js';
import './starhalf.js';
import './staroutline.js';
import './success.js';
import './successoutline.js';
import './tag.js';
import './upload.js';
import './tagadd.js';
import { a as Typography } from './anchor-chunk-5b0bbe0b.js';
import './anchor-chunk-cd7ef49a.js';
import './anchor-chunk-20e4020f.js';
import 'polished';
import './anchor-chunk-6ebffda8.js';
import './anchor-chunk-210b63ef.js';
function _templateObject() {
var data = _taggedTemplateLiteral(["\n width: 6rem;\n display: flex;\n flex-direction: row;\n align-items: center;\n padding: 0 0.5rem;\n\n .anchor-input {\n margin-left: 0.5rem;\n }\n"]);
_templateObject = function _templateObject() {
return data;
};
return data;
}
var EventKeyCodes = {
ENTER: 13
};
var StyledGoto = styled('div')(_templateObject());
var Goto = function Goto(_a) {
var onSubmit = _a.onSubmit,
className = _a.className,
props = __rest(_a, ["onSubmit", "className"]);
var _React$useState = useState(null),
_React$useState2 = _slicedToArray(_React$useState, 2),
value = _React$useState2[0],
setValue = _React$useState2[1];
var handleSubmit = function handleSubmit() {
if (onSubmit && value !== null) {
onSubmit(value);
setValue(null);
}
};
return createElement(StyledGoto, Object.assign({
className: classNames('anchor-pagination-goto', className)
}, props), "Goto", createElement(Input, {
type: "number",
onChange: function onChange(num) {
return setValue(num);
},
onKeyDown: function onKeyDown(event) {
if (event.keyCode === EventKeyCodes.ENTER) {
handleSubmit();
}
},
value: value === null ? '' : value
}));
};
/* eslint-disable prefer-arrow-callback */
// for detecting when values change
// https://stackoverflow.com/a/58217148
// Named functions are for stack traceability
var useIsMounted = function useIsMounted() {
var isMounted = useRef(false);
useEffect(function setIsMounted() {
isMounted.current = true;
return function cleanupSetIsMounted() {
isMounted.current = false;
};
}, []);
return isMounted;
};
var useUpdateEffect = function useUpdateEffect(effect, dependencies) {
var isMounted = useIsMounted();
var isInitialMount = useRef(true);
useEffect(function () {
// eslint-disable-next-line @typescript-eslint/no-empty-function
var effectCleanupFunc = function noop() {};
if (isInitialMount.current) {
isInitialMount.current = false;
} else {
effectCleanupFunc = effect() || effectCleanupFunc;
}
return function () {
effectCleanupFunc();
if (!isMounted.current) {
isInitialMount.current = true;
}
};
}, dependencies);
};
function _templateObject2() {
var data = _taggedTemplateLiteral(["\n display: inline;\n margin: 0 1rem;\n"]);
_templateObject2 = function _templateObject2() {
return data;
};
return data;
}
function _templateObject$1() {
var data = _taggedTemplateLiteral(["\n display: flex;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n\n ", "\n"]);
_templateObject$1 = function _templateObject() {
return data;
};
return data;
}
// Used primarily here to keep the current page
// value between the first page and last page
var constrain = function constrain(min, value, max) {
return Math.min(Math.max(value, min), max);
};
var Button$1 = function Button$$1(_a) {
var _a$variant = _a.variant,
variant = _a$variant === void 0 ? 'minimal' : _a$variant,
_a$size = _a.size,
size = _a$size === void 0 ? 'sm' : _a$size,
props = __rest(_a, ["variant", "size"]);
return createElement(Button, Object.assign({
variant: variant,
size: size
}, props));
};
var StyledPagination = styled('div')(_templateObject$1(), space);
var AffixWrapper = styled('div')(_templateObject2());
function reducer(state, action) {
switch (action.type) {
case 'increment':
return Object.assign(Object.assign({}, state), {
current: Math.min(state.current + 1, action.total)
});
case 'decrement':
return Object.assign(Object.assign({}, state), {
current: Math.max(state.current - 1, 1)
});
case 'setCurrent':
return Object.assign(Object.assign({}, state), {
current: constrain(1, action.payload, action.total)
});
case 'totalChanged':
// This will make it so that if the current page is now beyond the
// new page total then the current page changes to the new last page.
// It might be that we want to revert to the first page instead.
return Object.assign(Object.assign({}, state), {
current: constrain(1, state.current, action.total)
});
default:
throw new Error("Unrecognized reducer action type: ".concat(action && action.type));
}
} // We could improve this component by adding ways to show the total number of results,
// allowing "Next" and "Prev" text instead of arrows, and having the Ellipses buttons
// dropdown a Goto or decrement/increment the current page by 5, for instance.
var Pagination = function Pagination(_a) {
var className = _a.className,
prefix = _a.prefix,
suffix = _a.suffix,
children = _a.children,
totalPages = _a.totalPages,
totalResults = _a.totalResults,
_a$pageSize = _a.pageSize,
pageSize = _a$pageSize === void 0 ? 10 : _a$pageSize,
controlledCurrent = _a.current,
showGoto = _a.showGoto,
_a$showArrows = _a.showArrows,
showArrows = _a$showArrows === void 0 ? true : _a$showArrows,
_a$size2 = _a.size,
size = _a$size2 === void 0 ? 'sm' : _a$size2,
onChange = _a.onChange,
_a$variant2 = _a.variant,
variant = _a$variant2 === void 0 ? 'expanded' : _a$variant2,
props = __rest(_a, ["className", "prefix", "suffix", "children", "totalPages", "totalResults", "pageSize", "current", "showGoto", "showArrows", "size", "onChange", "variant"]);
var _React$useReducer = useReducer(reducer, {
current: controlledCurrent || 1
}),
_React$useReducer2 = _slicedToArray(_React$useReducer, 2),
state = _React$useReducer2[0],
dispatch = _React$useReducer2[1]; // If the current page is controlled we want to
// prefer that over internal state
var current = controlledCurrent || state.current; // Prefer the totalPages prop over calculating from
// the totalResults/pageSize
var total = totalPages || totalResults && Math.ceil(totalResults / pageSize) || 1;
useUpdateEffect(function () {
dispatch({
type: 'totalChanged',
total: total
});
}, [total]);
useUpdateEffect(function () {
if (onChange) {
onChange(state.current);
}
}, [state.current]);
var pageButton = function pageButton(_ref) {
var page = _ref.page,
slot = _ref.slot;
return createElement(Button$1, {
className: current === page ? 'active' : undefined,
size: size,
key: "page".concat(page, ":").concat(slot),
onClick: function onClick() {
return dispatch({
type: 'setCurrent',
payload: page,
total: total
});
},
variant: current === page ? 'filled' : undefined,
prefix: createElement(Fragment, null, page)
});
}; // Seven is enough to show the first and last page, the current page
// and pages on either side, and potential ellipses in between. If the
// page count is 7 or less, we can just display a button for each
// page.
var numButtonSlots = 7;
var iconSize = size === 'sm' ? 'lg' : undefined;
var renderProps = {
current: current,
totalPages: total,
totalResults: totalResults,
pageSize: pageSize,
range: [(current - 1) * pageSize + 1, Math.min(pageSize * current, totalResults || Infinity)]
};
return createElement(Fragment, null, createElement(StyledPagination, Object.assign({
className: classNames('anchor-pagination', className)
}, props), prefix && createElement(AffixWrapper, null, prefix(renderProps)), showArrows && createElement(Button$1, {
size: size,
disabled: current <= 1,
prefix: createElement(ChevronLeft, {
scale: iconSize
}),
onClick: function onClick() {
return dispatch({
type: 'decrement',
total: total
});
}
}), variant === 'minimal' && createElement(Typography, {
scale: 20,
margin: "0 0.5rem"
}, current, " / ", total), variant === 'expanded' && (total <= numButtonSlots ? Array.from(Array(total)).map(function (_, i) {
return pageButton({
page: i + 1,
slot: i
});
}) : createElement(Fragment, null, pageButton({
page: 1,
slot: 1
}), constrain(2, current - 2, total - 5) === 2 ? pageButton({
page: 2,
slot: 2
}) : createElement(Button$1, {
size: size,
prefix: createElement(Ellipses, null)
}), pageButton({
page: constrain(3, current - 1, total - 4),
slot: 3
}), pageButton({
page: constrain(4, current, total - 3),
slot: 4
}), pageButton({
page: constrain(5, current + 1, total - 2),
slot: 5
}), constrain(6, current + 2, total - 1) === total - 1 ? pageButton({
page: total - 1,
slot: 6
}) : createElement(Button$1, {
size: size,
prefix: createElement(Ellipses, null)
}), pageButton({
page: total,
slot: 7
}))), showArrows && createElement(Button$1, {
size: size,
disabled: current === total,
prefix: createElement(ChevronRight, {
scale: iconSize
}),
onClick: function onClick() {
return dispatch({
type: 'increment',
total: total
});
}
}), suffix && createElement(AffixWrapper, null, suffix(renderProps)), showGoto && createElement(Goto, {
onSubmit: function onSubmit(page) {
return dispatch({
type: 'setCurrent',
payload: page,
total: total
});
}
})), children && children(renderProps));
};
export { Pagination };
//# sourceMappingURL=pagination.js.map