@retailmenot/anchor
Version:
A React UI Library by RetailMeNot
414 lines (372 loc) • 13 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var __chunk_1 = require('./anchor-chunk-24f232e7.js');
var __chunk_2 = require('./anchor-chunk-9d9a5df6.js');
var __chunk_7 = require('./anchor-chunk-eb382a51.js');
var form = require('./form.js');
var React = require('react');
var classNames = _interopDefault(require('classnames'));
var styled = require('@xstyled/styled-components');
var styled__default = _interopDefault(styled);
var system = require('@xstyled/system');
require('./addevent.js');
require('./anchor-chunk-31a3b978.js');
require('./arrowback.js');
require('./arrowforward.js');
require('./avataricon.js');
require('./avataroutline.js');
require('./barcode.js');
require('./bulletlist.js');
require('./calendar.js');
require('./camera.js');
require('./cart.js');
require('./cashback.js');
require('./cells.js');
require('./chat.js');
require('./check.js');
require('./checksmall.js');
require('./chevrondown.js');
require('./chevrondownsmall.js');
var chevronleft = require('./chevronleft.js');
require('./chevronleftsmall.js');
var chevronright = require('./chevronright.js');
require('./chevronrightsmall.js');
require('./chevronup.js');
require('./chevronupsmall.js');
require('./clock.js');
require('./close.js');
require('./closesmall.js');
require('./commentmore.js');
require('./creditcard.js');
require('./crosshairs.js');
require('./cut.js');
require('./disabled.js');
require('./dislike.js');
require('./download.js');
var ellipses = require('./ellipses.js');
require('./ellipsesvertical.js');
require('./envelope.js');
require('./envelopeopen.js');
require('./error.js');
require('./expand.js');
require('./gear.js');
require('./giftcard.js');
require('./hamburger.js');
require('./heart.js');
require('./heartoutline.js');
require('./home.js');
require('./info.js');
require('./infooutline.js');
require('./laptop.js');
require('./lightning.js');
require('./like.js');
require('./listicon.js');
require('./lock.js');
require('./map.js');
require('./marker.js');
require('./markeroutline.js');
require('./mobile.js');
require('./news.js');
require('./pencil.js');
require('./play.js');
require('./plus.js');
require('./plussmall.js');
require('./print.js');
require('./question.js');
require('./questionoutline.js');
require('./refresh.js');
require('./retailmenotlogo.js');
require('./sadface.js');
require('./search.js');
require('./share.js');
require('./sliders.js');
require('./star.js');
require('./starhalf.js');
require('./staroutline.js');
require('./success.js');
require('./successoutline.js');
require('./tag.js');
require('./upload.js');
require('./tagadd.js');
var __chunk_6 = require('./anchor-chunk-cd6fece5.js');
require('./anchor-chunk-1efd6395.js');
require('./anchor-chunk-598e53e1.js');
require('polished');
require('./anchor-chunk-f296150d.js');
require('./anchor-chunk-925bd1f9.js');
function _templateObject() {
var data = __chunk_1._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__default('div')(_templateObject());
var Goto = function Goto(_a) {
var onSubmit = _a.onSubmit,
className = _a.className,
props = __chunk_2.__rest(_a, ["onSubmit", "className"]);
var _React$useState = React.useState(null),
_React$useState2 = __chunk_1._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 React.createElement(StyledGoto, Object.assign({
className: classNames('anchor-pagination-goto', className)
}, props), "Goto", React.createElement(form.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 = React.useRef(false);
React.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 = React.useRef(true);
React.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 = __chunk_1._taggedTemplateLiteral(["\n display: inline;\n margin: 0 1rem;\n"]);
_templateObject2 = function _templateObject2() {
return data;
};
return data;
}
function _templateObject$1() {
var data = __chunk_1._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 = function Button(_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 = __chunk_2.__rest(_a, ["variant", "size"]);
return React.createElement(__chunk_7.Button, Object.assign({
variant: variant,
size: size
}, props));
};
var StyledPagination = styled__default('div')(_templateObject$1(), system.space);
var AffixWrapper = styled__default('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 = __chunk_2.__rest(_a, ["className", "prefix", "suffix", "children", "totalPages", "totalResults", "pageSize", "current", "showGoto", "showArrows", "size", "onChange", "variant"]);
var _React$useReducer = React.useReducer(reducer, {
current: controlledCurrent || 1
}),
_React$useReducer2 = __chunk_1._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 React.createElement(Button, {
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: React.createElement(React.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 React.createElement(React.Fragment, null, React.createElement(StyledPagination, Object.assign({
className: classNames('anchor-pagination', className)
}, props), prefix && React.createElement(AffixWrapper, null, prefix(renderProps)), showArrows && React.createElement(Button, {
size: size,
disabled: current <= 1,
prefix: React.createElement(chevronleft.ChevronLeft, {
scale: iconSize
}),
onClick: function onClick() {
return dispatch({
type: 'decrement',
total: total
});
}
}), variant === 'minimal' && React.createElement(__chunk_6.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
});
}) : React.createElement(React.Fragment, null, pageButton({
page: 1,
slot: 1
}), constrain(2, current - 2, total - 5) === 2 ? pageButton({
page: 2,
slot: 2
}) : React.createElement(Button, {
size: size,
prefix: React.createElement(ellipses.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
}) : React.createElement(Button, {
size: size,
prefix: React.createElement(ellipses.Ellipses, null)
}), pageButton({
page: total,
slot: 7
}))), showArrows && React.createElement(Button, {
size: size,
disabled: current === total,
prefix: React.createElement(chevronright.ChevronRight, {
scale: iconSize
}),
onClick: function onClick() {
return dispatch({
type: 'increment',
total: total
});
}
}), suffix && React.createElement(AffixWrapper, null, suffix(renderProps)), showGoto && React.createElement(Goto, {
onSubmit: function onSubmit(page) {
return dispatch({
type: 'setCurrent',
payload: page,
total: total
});
}
})), children && children(renderProps));
};
exports.Pagination = Pagination;
//# sourceMappingURL=pagination.js.map