@homebound/beam 2.280.0 → 2.281.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,19 +1,27 @@
1
- import { Dispatch, SetStateAction } from "react";
2
- export type PageSettings = {
3
- page: number;
4
- perPage: number;
1
+ import { Dispatch } from "react";
2
+ /**
3
+ * Page settings, either a pageNumber+pageSize or offset+limit.
4
+ *
5
+ * This component is implemented in terms of "page number + page size",
6
+ * but our backend wants offset+limit, so we accept both and translate.
7
+ */
8
+ export type PageSettings = PageNumberAndSize | OffsetAndLimit;
9
+ export type PageNumberAndSize = {
10
+ pageNumber: number;
11
+ pageSize: number;
5
12
  };
13
+ export type OffsetAndLimit = {
14
+ offset: number;
15
+ limit: number;
16
+ };
17
+ export declare const defaultPage: OffsetAndLimit;
6
18
  interface PaginationProps {
7
- label: string;
19
+ page: readonly [PageNumberAndSize, Dispatch<PageNumberAndSize>] | readonly [OffsetAndLimit, Dispatch<OffsetAndLimit>];
8
20
  totalCount: number;
9
- settings: PageSettings;
10
- setSettings: Dispatch<SetStateAction<PageSettings>>;
11
21
  }
12
22
  export declare function Pagination(props: PaginationProps): import("@emotion/react/jsx-runtime").JSX.Element;
13
- export declare function toFirstAndOffset(page: number, perPage: number): {
14
- first: number;
15
- offset: number;
16
- };
23
+ export declare function toLimitAndOffset(page: PageSettings): OffsetAndLimit;
24
+ export declare function toPageNumberSize(page: PageSettings): PageNumberAndSize;
17
25
  export declare const pageOptions: {
18
26
  id: number;
19
27
  name: string;
@@ -1,31 +1,55 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.pageOptions = exports.toFirstAndOffset = exports.Pagination = void 0;
3
+ exports.pageOptions = exports.toPageNumberSize = exports.toLimitAndOffset = exports.Pagination = exports.defaultPage = void 0;
4
4
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
- const react_1 = require("react");
6
5
  const components_1 = require("./");
7
6
  const Css_1 = require("../Css");
8
7
  const inputs_1 = require("../inputs");
9
8
  const utils_1 = require("../utils");
9
+ // Use OffsetAndLimit as our default b/c that's what backend filters expect
10
+ exports.defaultPage = { offset: 0, limit: 100 };
10
11
  function Pagination(props) {
11
- const { label, settings, totalCount, setSettings } = props;
12
- const { perPage, page } = settings;
13
- const hasNextPage = (0, react_1.useMemo)(() => page < totalCount / perPage, [page, perPage, totalCount]);
12
+ const { totalCount } = props;
13
+ const [page, setPage] = props.page;
14
+ const { pageSize, pageNumber } = toPageNumberSize(page);
15
+ const hasPrevPage = pageNumber > 1;
16
+ const hasNextPage = pageNumber < totalCount / pageSize;
17
+ // Create the `1 - 100 of 1000` or `0 of 0`
18
+ const first = pageSize * (pageNumber - 1) + (totalCount ? 1 : 0);
19
+ const last = Math.min(pageSize * pageNumber, totalCount);
20
+ // When no rows, show '0 of 0' instead of '0 - 0 of 0'
21
+ const showLast = totalCount > 0;
22
+ // Convert the new page back to whatever format the caller wants
23
+ function set(newPage) {
24
+ if ("pageNumber" in props.page[0]) {
25
+ setPage(newPage);
26
+ }
27
+ else {
28
+ setPage(toLimitAndOffset(newPage));
29
+ }
30
+ }
14
31
  const tid = (0, utils_1.useTestIds)(props, "pagination");
15
- return ((0, jsx_runtime_1.jsxs)("div", { css: Css_1.Css.df.bGray300.bt.xs.gray500.px1.ml2.pt2.$, ...tid, children: [(0, jsx_runtime_1.jsxs)("div", { css: Css_1.Css.df.mya.mr2.$, ...tid.perPageLabel, children: [label, " per page:"] }), (0, jsx_runtime_1.jsx)("div", { css: Css_1.Css.wPx(78).$, children: (0, jsx_runtime_1.jsx)(inputs_1.SelectField, { compact: true, ...tid.perPage, labelStyle: "hidden", label: `${label} per page`, options: exports.pageOptions, value: perPage, onSelect: (val) => {
16
- setSettings({ page: 1, perPage: val });
17
- } }) }), (0, jsx_runtime_1.jsxs)("div", { css: Css_1.Css.mla.mya.df.$, children: [(0, jsx_runtime_1.jsxs)("div", { css: Css_1.Css.df.mya.mr2.$, ...tid.pageInfoLabel, children: [perPage * (page - 1) + 1, " ", hasNextPage ? `- ${perPage * page}` : "", " of ", totalCount, " ", label] }), (0, jsx_runtime_1.jsx)(components_1.IconButton, { ...tid.previousIcon, icon: "chevronLeft", color: Css_1.Palette.LightBlue700, onClick: () => setSettings({ page: settings.page - 1, perPage }), disabled: settings.page === 1 }), (0, jsx_runtime_1.jsx)(components_1.IconButton, { ...tid.nextIcon, icon: "chevronRight", color: Css_1.Palette.LightBlue700, onClick: () => setSettings({ page: settings.page + 1, perPage }), disabled: !hasNextPage })] })] }));
32
+ return ((0, jsx_runtime_1.jsxs)("div", { css: Css_1.Css.df.bGray300.bt.xs.gray500.px1.ml2.pt2.$, ...tid, children: [(0, jsx_runtime_1.jsx)("div", { css: Css_1.Css.df.mya.mr2.$, ...tid.pageSizeLabel, children: "Page size:" }), (0, jsx_runtime_1.jsx)("div", { css: Css_1.Css.wPx(78).$, children: (0, jsx_runtime_1.jsx)(inputs_1.SelectField, { compact: true, label: "Page Size", labelStyle: "hidden", options: exports.pageOptions, value: pageSize, onSelect: (val) => set({ pageNumber: 1, pageSize: val }), ...tid.pageSize }) }), (0, jsx_runtime_1.jsxs)("div", { css: Css_1.Css.mla.mya.df.$, children: [(0, jsx_runtime_1.jsxs)("div", { css: Css_1.Css.df.mya.mr2.$, ...tid.pageInfoLabel, children: [first, " ", showLast ? `- ${last}` : "", " of ", totalCount] }), (0, jsx_runtime_1.jsx)(components_1.IconButton, { icon: "chevronLeft", color: hasPrevPage ? Css_1.Palette.LightBlue700 : Css_1.Palette.Gray200, onClick: () => set({ pageNumber: pageNumber - 1, pageSize }), disabled: !hasPrevPage, ...tid.previousIcon }), (0, jsx_runtime_1.jsx)(components_1.IconButton, { icon: "chevronRight", color: hasNextPage ? Css_1.Palette.LightBlue700 : Css_1.Palette.Gray200, onClick: () => set({ pageNumber: pageNumber + 1, pageSize }), disabled: !hasNextPage, ...tid.nextIcon })] })] }));
18
33
  }
19
34
  exports.Pagination = Pagination;
20
- function toFirstAndOffset(page, perPage) {
21
- return {
22
- first: perPage,
23
- // E.g. on first page the offset is 0, second page the offset is 100, then 200, etc.
24
- offset: (page - 1) * perPage,
25
- };
35
+ function toLimitAndOffset(page) {
36
+ return "limit" in page
37
+ ? page
38
+ : {
39
+ // E.g. on first page the offset is 0, second page the offset is 100, then 200, etc.
40
+ offset: (page.pageNumber - 1) * page.pageSize,
41
+ limit: page.pageSize,
42
+ };
26
43
  }
27
- exports.toFirstAndOffset = toFirstAndOffset;
28
- // Make a list of 50/100/150/etc page sizes for the user to chose
29
- exports.pageOptions = Array(5)
30
- .fill(0)
31
- .map((_, i) => ({ id: (i + 1) * 50, name: ((i + 1) * 50).toString() }));
44
+ exports.toLimitAndOffset = toLimitAndOffset;
45
+ function toPageNumberSize(page) {
46
+ return "pageNumber" in page
47
+ ? page
48
+ : {
49
+ pageNumber: Math.floor(page.offset / page.limit) + 1,
50
+ pageSize: page.limit,
51
+ };
52
+ }
53
+ exports.toPageNumberSize = toPageNumberSize;
54
+ // Make a list of 100/500/1000 for the user to choose
55
+ exports.pageOptions = [100, 500, 1000].map((num) => ({ id: num, name: String(num) }));
@@ -40,7 +40,8 @@ function TabContent(props) {
40
40
  const uniqueValue = uniqueTabValue(selectedTab);
41
41
  return (
42
42
  // Using FullBleed to allow the tab's bgColor to extend to the edges of the <ScrollableContent /> element.
43
- (0, jsx_runtime_1.jsx)(components_1.FullBleed, { children: (0, jsx_runtime_1.jsx)("div", { "aria-labelledby": `${uniqueValue}-tab`, id: `${uniqueValue}-tabPanel`, role: "tabpanel", tabIndex: 0, ...tid.panel, css: contentXss, children: isRouteTab(selectedTab) ? (0, jsx_runtime_1.jsx)(react_router_1.Route, { path: selectedTab.path, render: selectedTab.render }) : selectedTab.render() }) }));
43
+ // Omit the padding from `FullBleed` if the caller passes in the `paddingLeft/Right` styles.
44
+ (0, jsx_runtime_1.jsx)(components_1.FullBleed, { omitPadding: "paddingLeft" in contentXss || "paddingRight" in contentXss, children: (0, jsx_runtime_1.jsx)("div", { "aria-labelledby": `${uniqueValue}-tab`, id: `${uniqueValue}-tabPanel`, role: "tabpanel", tabIndex: 0, ...tid.panel, css: contentXss, children: isRouteTab(selectedTab) ? (0, jsx_runtime_1.jsx)(react_router_1.Route, { path: selectedTab.path, render: selectedTab.render }) : selectedTab.render() }) }));
44
45
  }
45
46
  exports.TabContent = TabContent;
46
47
  /** The top list of tabs. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.280.0",
3
+ "version": "2.281.0",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",