@canonical/react-components 0.43.0 → 0.45.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.
@@ -44,6 +44,10 @@ export type Props<D extends Record<string, unknown>> = PropsWithSpread<{
44
44
  * The direction of the initial sort.
45
45
  */
46
46
  initialSortDirection?: "ascending" | "descending";
47
+ /**
48
+ * Whether the sort by needs to be reset after each data change.
49
+ */
50
+ autoResetSortBy?: boolean;
47
51
  }, HTMLProps<HTMLTableElement>>;
48
- declare function ModularTable<D extends Record<string, unknown>>({ data, columns, emptyMsg, footer, sortable, getHeaderProps, getRowProps, getCellProps, getRowId, initialSortColumn, initialSortDirection, ...props }: Props<D>): JSX.Element;
52
+ declare function ModularTable<D extends Record<string, unknown>>({ data, columns, emptyMsg, footer, sortable, getHeaderProps, getRowProps, getCellProps, getRowId, initialSortColumn, initialSortDirection, autoResetSortBy, ...props }: Props<D>): JSX.Element;
49
53
  export default ModularTable;
@@ -11,7 +11,7 @@ var _TableRow = _interopRequireDefault(require("../TableRow"));
11
11
  var _TableHeader = _interopRequireDefault(require("../TableHeader"));
12
12
  var _TableCell = _interopRequireDefault(require("../TableCell"));
13
13
  var _Icon = _interopRequireDefault(require("../Icon"));
14
- var _excluded = ["data", "columns", "emptyMsg", "footer", "sortable", "getHeaderProps", "getRowProps", "getCellProps", "getRowId", "initialSortColumn", "initialSortDirection"];
14
+ var _excluded = ["data", "columns", "emptyMsg", "footer", "sortable", "getHeaderProps", "getRowProps", "getCellProps", "getRowId", "initialSortColumn", "initialSortDirection", "autoResetSortBy"];
15
15
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
16
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
17
17
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -65,6 +65,8 @@ function ModularTable(_ref) {
65
65
  getRowId = _ref.getRowId,
66
66
  initialSortColumn = _ref.initialSortColumn,
67
67
  initialSortDirection = _ref.initialSortDirection,
68
+ _ref$autoResetSortBy = _ref.autoResetSortBy,
69
+ autoResetSortBy = _ref$autoResetSortBy === void 0 ? false : _ref$autoResetSortBy,
68
70
  props = _objectWithoutProperties(_ref, _excluded);
69
71
  var sortBy = (0, _react.useMemo)(function () {
70
72
  return initialSortColumn ? [{
@@ -78,7 +80,8 @@ function ModularTable(_ref) {
78
80
  getRowId: getRowId || undefined,
79
81
  initialState: {
80
82
  sortBy: sortBy
81
- }
83
+ },
84
+ autoResetSortBy: autoResetSortBy
82
85
  }, sortable ? _reactTable.useSortBy : undefined),
83
86
  getTableProps = _useTable.getTableProps,
84
87
  getTableBodyProps = _useTable.getTableBodyProps,
@@ -86,17 +89,33 @@ function ModularTable(_ref) {
86
89
  rows = _useTable.rows,
87
90
  prepareRow = _useTable.prepareRow;
88
91
  var showEmpty = !!emptyMsg && (!rows || rows.length === 0);
92
+
93
+ // Function returns whether table can be sorted by a specific column.
94
+ // Returns true if sorting is enabled for the column and there is text
95
+ // or JSX provided for the header, otherwise returns false.
96
+ var isColumnSortable = function isColumnSortable(column) {
97
+ return column.canSort && ( /*#__PURE__*/(0, _react.isValidElement)(column.Header) || (typeof column.Header === "string" || typeof column.Header === "number") && !!String(column.Header).trim());
98
+ };
99
+ var getColumnSortDirection = function getColumnSortDirection(column) {
100
+ if (!isColumnSortable(column)) {
101
+ return undefined;
102
+ }
103
+ if (!column.isSorted) {
104
+ return "none";
105
+ }
106
+ return column.isSortedDesc ? "descending" : "ascending";
107
+ };
89
108
  return /*#__PURE__*/_react.default.createElement(_Table.default, _extends({}, getTableProps(), props), /*#__PURE__*/_react.default.createElement("thead", null, headerGroups.map(function (headerGroup) {
90
109
  return /*#__PURE__*/_react.default.createElement(_TableRow.default, headerGroup.getHeaderGroupProps(), headerGroup.headers.map(function (column) {
91
110
  return /*#__PURE__*/_react.default.createElement(_TableHeader.default, _extends({
92
- sort: column.isSorted ? column.isSortedDesc ? "descending" : "ascending" : "none"
111
+ sort: getColumnSortDirection(column)
93
112
  }, column.getHeaderProps([{
94
113
  className: column.className
95
114
  }, {
96
115
  className: column.getCellIcon ? "p-table__cell--icon-placeholder" : ""
97
116
  }, _objectSpread({}, getHeaderProps === null || getHeaderProps === void 0 ? void 0 : getHeaderProps(column)),
98
117
  // Only call this if we want it to be sortable too.
99
- sortable ? column.getSortByToggleProps({
118
+ sortable && isColumnSortable(column) ? column.getSortByToggleProps({
100
119
  title: undefined
101
120
  }) : {}])), column.render("Header"));
102
121
  }));
@@ -1,34 +1,90 @@
1
1
  import type { HTMLProps } from "react";
2
2
  import type { PropsWithSpread } from "../../types";
3
- export type Props = PropsWithSpread<{
3
+ type BaseProps = {
4
4
  /**
5
- * The current page being viewed.
5
+ * Whether to scroll to the top of the list on page change.
6
+ */
7
+ scrollToTop?: boolean;
8
+ /**
9
+ * The number of pages at which to truncate the pagination items.
10
+ */
11
+ truncateThreshold?: number;
12
+ /**
13
+ * Whether the pagination is ceneterd on the page.
14
+ */
15
+ centered?: boolean;
16
+ /**
17
+ * Whether to show the labels for forward and back buttons.
18
+ */
19
+ showLabels?: boolean;
20
+ /**
21
+ * Whether forward button is disabled.
22
+ */
23
+ forwardDisabled?: boolean;
24
+ /**
25
+ * Whether back button is disabled.
26
+ */
27
+ backDisabled?: boolean;
28
+ /**
29
+ * Custom label for forward button.
30
+ */
31
+ forwardLabel?: string;
32
+ /**
33
+ * Custom label for back button.
34
+ */
35
+ backLabel?: string;
36
+ };
37
+ type NumberedPagination = BaseProps & {
38
+ /**
39
+ * The current page being viewed.<br>
40
+ * **Required for Numbered Pagination.**
6
41
  */
7
42
  currentPage: number;
8
43
  /**
9
- * The number of items to show per page.
44
+ * The number of items to show per page.<br>
45
+ * **Required for numbered pagination.**
10
46
  */
11
47
  itemsPerPage: number;
12
48
  /**
13
- * Function to handle paginating the items.
49
+ * Function to handle paginating the items.<br>
50
+ * **Required for numbered pagination.**
14
51
  */
15
52
  paginate: (page: number) => void;
16
53
  /**
17
- * The total number of items.
54
+ * The total number of items.<br>
55
+ * **Required for numbered pagination.**
18
56
  */
19
57
  totalItems: number;
20
58
  /**
21
- * Whether to scroll to the top of the list on page change.
59
+ * Whether to hide the pagination items.
22
60
  */
23
- scrollToTop?: boolean;
61
+ hideNumbers?: boolean;
24
62
  /**
25
- * The number of pages at which to truncate the pagination items.
63
+ * Function to handle page transition to a higher-numbered page for
64
+ * numbered pagination and to next page for buttons-only pagination.<br>
65
+ * _Called with page parameter for numbered pagination and_
66
+ * _with no parameter for buttons-only pagination._<br>
67
+ * **Required for buttons-only pagination.**
26
68
  */
27
- truncateThreshold?: number;
69
+ onForward?: (page: number) => void;
28
70
  /**
29
- * Whether or not the pagination is ceneterd on the page.
71
+ * Function to handle page transition to a lower-numbered page for
72
+ * numbered pagination and to next page for buttons-only pagination.<br>
73
+ * _Called with page parameter for numbered pagination and_
74
+ * _with no parameter for buttons-only pagination._<br>
75
+ * **Required for buttons-only pagination.**
30
76
  */
31
- centered?: boolean;
32
- }, HTMLProps<HTMLElement>>;
33
- declare const Pagination: ({ itemsPerPage, totalItems, paginate, currentPage, scrollToTop, truncateThreshold, centered, ...navProps }: Props) => JSX.Element;
77
+ onBack?: (page: number) => void;
78
+ };
79
+ type ButtonsOnlyPagination = BaseProps & {
80
+ itemsPerPage?: never;
81
+ totalItems?: never;
82
+ currentPage?: never;
83
+ paginate?: never;
84
+ hideNumbers?: never;
85
+ onForward: () => void;
86
+ onBack: () => void;
87
+ };
88
+ export type Props = PropsWithSpread<NumberedPagination | ButtonsOnlyPagination, HTMLProps<HTMLElement>>;
89
+ declare const Pagination: ({ itemsPerPage, totalItems, paginate, currentPage, scrollToTop, truncateThreshold, centered, showLabels, hideNumbers, onForward, onBack, forwardDisabled, backDisabled, forwardLabel, backLabel, ...navProps }: Props) => JSX.Element;
34
90
  export default Pagination;
@@ -8,7 +8,7 @@ var _classnames = _interopRequireDefault(require("classnames"));
8
8
  var _react = _interopRequireDefault(require("react"));
9
9
  var _PaginationButton = _interopRequireDefault(require("./PaginationButton"));
10
10
  var _PaginationItem = _interopRequireDefault(require("./PaginationItem"));
11
- var _excluded = ["itemsPerPage", "totalItems", "paginate", "currentPage", "scrollToTop", "truncateThreshold", "centered"];
11
+ var _excluded = ["itemsPerPage", "totalItems", "paginate", "currentPage", "scrollToTop", "truncateThreshold", "centered", "showLabels", "hideNumbers", "onForward", "onBack", "forwardDisabled", "backDisabled", "forwardLabel", "backLabel"];
12
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
13
  function _extends() { _extends = Object.assign ? Object.assign.bind() : 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); }
14
14
  function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
@@ -93,6 +93,16 @@ var PaginationItemSeparator = function PaginationItemSeparator() {
93
93
  className: "p-pagination__item p-pagination__item--truncation"
94
94
  }, "\u2026");
95
95
  };
96
+
97
+ // Props that are used in both types of paginations.
98
+
99
+ // Used when number of items per page, number of total items,
100
+ // current page and paginate function is defined. Pagination
101
+ // is handled by paginate function and optional onForward and
102
+ // onBack functions.
103
+ // Used when number of items per page, number of total items,
104
+ // current page and paginate function are undefined.
105
+ // Pagination is handled by onForward and onBack function.
96
106
  var Pagination = function Pagination(_ref) {
97
107
  var itemsPerPage = _ref.itemsPerPage,
98
108
  totalItems = _ref.totalItems,
@@ -102,17 +112,43 @@ var Pagination = function Pagination(_ref) {
102
112
  _ref$truncateThreshol = _ref.truncateThreshold,
103
113
  truncateThreshold = _ref$truncateThreshol === void 0 ? 10 : _ref$truncateThreshol,
104
114
  centered = _ref.centered,
115
+ showLabels = _ref.showLabels,
116
+ hideNumbers = _ref.hideNumbers,
117
+ onForward = _ref.onForward,
118
+ onBack = _ref.onBack,
119
+ forwardDisabled = _ref.forwardDisabled,
120
+ backDisabled = _ref.backDisabled,
121
+ forwardLabel = _ref.forwardLabel,
122
+ backLabel = _ref.backLabel,
105
123
  navProps = _objectWithoutProperties(_ref, _excluded);
106
- // return early if no pagination is required
107
- if (totalItems <= itemsPerPage) {
108
- return null;
109
- }
124
+ var isNumberedPagination = !!itemsPerPage && !!totalItems && !!currentPage && !!paginate;
110
125
  var pageNumbers = [];
111
- for (var i = 1; i <= Math.ceil(totalItems / itemsPerPage); i++) {
112
- pageNumbers.push(i);
126
+ if (isNumberedPagination) {
127
+ // return early if no pagination is required
128
+ if (totalItems <= itemsPerPage) {
129
+ return null;
130
+ }
131
+ for (var i = 1; i <= Math.ceil(totalItems / itemsPerPage); i++) {
132
+ pageNumbers.push(i);
133
+ }
113
134
  }
114
- var changePage = function changePage(page) {
135
+ var changeNumberedPage = function changeNumberedPage(page) {
115
136
  paginate(page);
137
+ if (page > currentPage) {
138
+ onForward === null || onForward === void 0 ? void 0 : onForward(page);
139
+ }
140
+ if (page < currentPage) {
141
+ onBack === null || onBack === void 0 ? void 0 : onBack(page);
142
+ }
143
+ scrollToTop && scrollTop();
144
+ };
145
+ var changeButtonsOnlyPage = function changeButtonsOnlyPage(direction) {
146
+ if (direction === "forward") {
147
+ onForward === null || onForward === void 0 ? void 0 : onForward(undefined);
148
+ }
149
+ if (direction === "back") {
150
+ onBack === null || onBack === void 0 ? void 0 : onBack(undefined);
151
+ }
116
152
  scrollToTop && scrollTop();
117
153
  };
118
154
  return /*#__PURE__*/_react.default.createElement("nav", _extends({
@@ -125,17 +161,21 @@ var Pagination = function Pagination(_ref) {
125
161
  }, /*#__PURE__*/_react.default.createElement(_PaginationButton.default, {
126
162
  key: "back",
127
163
  direction: "back",
128
- disabled: currentPage === 1,
164
+ disabled: backDisabled || currentPage === 1,
129
165
  onClick: function onClick() {
130
- return changePage(currentPage - 1);
131
- }
132
- }), generatePaginationItems(pageNumbers, currentPage, truncateThreshold, changePage), /*#__PURE__*/_react.default.createElement(_PaginationButton.default, {
166
+ return isNumberedPagination ? changeNumberedPage(currentPage - 1) : changeButtonsOnlyPage("back");
167
+ },
168
+ showLabel: showLabels,
169
+ label: backLabel
170
+ }), isNumberedPagination && !hideNumbers ? generatePaginationItems(pageNumbers, currentPage, truncateThreshold, changeNumberedPage) : null, /*#__PURE__*/_react.default.createElement(_PaginationButton.default, {
133
171
  key: "forward",
134
172
  direction: "forward",
135
- disabled: currentPage === pageNumbers.length,
173
+ disabled: forwardDisabled || currentPage === pageNumbers.length,
136
174
  onClick: function onClick() {
137
- return changePage(currentPage + 1);
138
- }
175
+ return isNumberedPagination ? changeNumberedPage(currentPage + 1) : changeButtonsOnlyPage("forward");
176
+ },
177
+ showLabel: showLabels,
178
+ label: forwardLabel
139
179
  })));
140
180
  };
141
181
  var _default = Pagination;
@@ -17,6 +17,14 @@ export type Props = {
17
17
  * Function to handle clicking the pagination button.
18
18
  */
19
19
  onClick: MouseEventHandler<HTMLButtonElement>;
20
+ /**
21
+ * Whether to show the label for button.
22
+ */
23
+ showLabel?: boolean;
24
+ /**
25
+ * Custom label for button.
26
+ */
27
+ label?: string;
20
28
  };
21
- declare const PaginationButton: ({ direction, onClick, disabled, }: Props) => JSX.Element;
29
+ declare const PaginationButton: ({ direction, onClick, disabled, showLabel, label, }: Props) => JSX.Element;
22
30
  export default PaginationButton;
@@ -17,8 +17,10 @@ var PaginationButton = function PaginationButton(_ref) {
17
17
  var direction = _ref.direction,
18
18
  onClick = _ref.onClick,
19
19
  _ref$disabled = _ref.disabled,
20
- disabled = _ref$disabled === void 0 ? false : _ref$disabled;
21
- var label = direction === "back" ? Label.Previous : Label.Next;
20
+ disabled = _ref$disabled === void 0 ? false : _ref$disabled,
21
+ showLabel = _ref.showLabel,
22
+ label = _ref.label;
23
+ var buttonLabel = label || (direction === "back" ? Label.Previous : Label.Next);
22
24
  return /*#__PURE__*/_react.default.createElement("li", {
23
25
  className: "p-pagination__item"
24
26
  }, /*#__PURE__*/_react.default.createElement("button", {
@@ -29,9 +31,9 @@ var PaginationButton = function PaginationButton(_ref) {
29
31
  disabled: disabled,
30
32
  onClick: onClick,
31
33
  type: "button"
32
- }, /*#__PURE__*/_react.default.createElement("i", {
34
+ }, direction === "forward" && showLabel && /*#__PURE__*/_react.default.createElement("span", null, buttonLabel), /*#__PURE__*/_react.default.createElement("i", {
33
35
  className: "p-icon--chevron-down"
34
- }, label)));
36
+ }, buttonLabel), direction === "back" && showLabel && /*#__PURE__*/_react.default.createElement("span", null, buttonLabel)));
35
37
  };
36
38
  var _default = PaginationButton;
37
39
  exports.default = _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonical/react-components",
3
- "version": "0.43.0",
3
+ "version": "0.45.0",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "author": "Huw Wilkins <huw.wilkins@canonical.com>",
@@ -79,7 +79,7 @@
79
79
  "ts-jest": "27.1.5",
80
80
  "tsc-alias": "1.8.6",
81
81
  "typescript": "4.9.5",
82
- "vanilla-framework": "3.15.1",
82
+ "vanilla-framework": "4.0.0",
83
83
  "wait-on": "5.3.0",
84
84
  "webpack": "5.88.0"
85
85
  },
@@ -106,7 +106,7 @@
106
106
  "@types/react-dom": "^17.0.2 || ^18.0.0",
107
107
  "react": "^17.0.2 || ^18.0.0",
108
108
  "react-dom": "^17.0.2 || ^18.0.0",
109
- "vanilla-framework": "3.15.1"
109
+ "vanilla-framework": "^3.15.1 || ^4.0.0"
110
110
  },
111
111
  "scripts": {
112
112
  "build": "rm -rf dist && yarn build-local; yarn build-declaration",