@indico-data/design-system 2.47.3 → 2.48.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.
Files changed (39) hide show
  1. package/lib/components/index.d.ts +1 -0
  2. package/lib/components/pagination/Pagination.d.ts +2 -0
  3. package/lib/components/pagination/Pagination.stories.d.ts +6 -0
  4. package/lib/components/pagination/__tests__/Pagination.test.d.ts +1 -0
  5. package/lib/components/pagination/index.d.ts +1 -0
  6. package/lib/components/pagination/types.d.ts +6 -0
  7. package/lib/components/table/__tests__/Table.test.d.ts +1 -0
  8. package/lib/components/table/components/TablePagination.d.ts +9 -0
  9. package/lib/components/table/components/__tests__/TablePagination.test.d.ts +1 -0
  10. package/lib/components/table/sampleData.d.ts +2 -0
  11. package/lib/components/table/types.d.ts +5 -4
  12. package/lib/index.css +50 -8
  13. package/lib/index.d.ts +5 -5
  14. package/lib/index.esm.css +50 -8
  15. package/lib/index.esm.js +69 -14
  16. package/lib/index.esm.js.map +1 -1
  17. package/lib/index.js +68 -13
  18. package/lib/index.js.map +1 -1
  19. package/package.json +1 -1
  20. package/src/components/index.ts +1 -0
  21. package/src/components/pagination/Pagination.mdx +31 -0
  22. package/src/components/pagination/Pagination.stories.tsx +80 -0
  23. package/src/components/pagination/Pagination.tsx +117 -0
  24. package/src/components/pagination/__tests__/Pagination.test.tsx +91 -0
  25. package/src/components/pagination/index.ts +1 -0
  26. package/src/components/pagination/styles/Pagination.scss +22 -0
  27. package/src/components/pagination/types.ts +6 -0
  28. package/src/components/table/Table.mdx +2 -0
  29. package/src/components/table/Table.stories.tsx +20 -28
  30. package/src/components/table/Table.tsx +9 -1
  31. package/src/components/table/__tests__/Table.test.tsx +10 -0
  32. package/src/components/table/components/TablePagination.tsx +44 -0
  33. package/src/components/table/components/__tests__/TablePagination.test.tsx +17 -0
  34. package/src/components/table/sampleData.ts +110 -0
  35. package/src/components/table/styles/Table.scss +40 -9
  36. package/src/components/table/styles/_variables.scss +1 -0
  37. package/src/components/table/types.ts +6 -6
  38. package/src/setup/setupIcons.ts +4 -0
  39. package/src/styles/index.scss +1 -0
package/lib/index.js CHANGED
@@ -230,7 +230,7 @@ const registerFontAwesomeIcons = (...icons) => {
230
230
  fontawesomeSvgCore.library.add(...icons);
231
231
  };
232
232
  // Register the icons used directly in design system components
233
- registerFontAwesomeIcons(freeSolidSvgIcons.faArrowDown, freeSolidSvgIcons.faArrowRight, freeSolidSvgIcons.faArrowLeft, freeSolidSvgIcons.faCalculator, freeSolidSvgIcons.faCheck, freeSolidSvgIcons.faCircleNotch, freeSolidSvgIcons.faMountainSun, freeSolidSvgIcons.faRocket, freeSolidSvgIcons.faWind, freeSolidSvgIcons.faEyeSlash, freeSolidSvgIcons.faEye, freeSolidSvgIcons.faCaretUp, freeSolidSvgIcons.faCaretDown, freeSolidSvgIcons.faTag, freeSolidSvgIcons.faPencilAlt, freeSolidSvgIcons.faSearch, freeSolidSvgIcons.faCog, freeSolidSvgIcons.faFileDownload, freeSolidSvgIcons.faQuestionCircle, freeSolidSvgIcons.faCopy, freeSolidSvgIcons.faXmark,
233
+ registerFontAwesomeIcons(freeSolidSvgIcons.faArrowDown, freeSolidSvgIcons.faArrowRight, freeSolidSvgIcons.faArrowLeft, freeSolidSvgIcons.faCalculator, freeSolidSvgIcons.faCheck, freeSolidSvgIcons.faCircleNotch, freeSolidSvgIcons.faMountainSun, freeSolidSvgIcons.faRocket, freeSolidSvgIcons.faWind, freeSolidSvgIcons.faEyeSlash, freeSolidSvgIcons.faEye, freeSolidSvgIcons.faCaretUp, freeSolidSvgIcons.faCaretDown, freeSolidSvgIcons.faTag, freeSolidSvgIcons.faPencilAlt, freeSolidSvgIcons.faSearch, freeSolidSvgIcons.faCog, freeSolidSvgIcons.faFileDownload, freeSolidSvgIcons.faQuestionCircle, freeSolidSvgIcons.faCopy, freeSolidSvgIcons.faXmark, freeSolidSvgIcons.faChevronLeft, freeSolidSvgIcons.faChevronRight,
234
234
  // backwards compat, don't require registration of custom indicons
235
235
  // might want to consider doing so in the future
236
236
  ...indiconDefinitions);
@@ -7193,18 +7193,6 @@ const LoadingComponent = () => {
7193
7193
  return jsxRuntime.jsx("div", { className: "table-loading", children: "Loading..." });
7194
7194
  };
7195
7195
 
7196
- const Table = (props) => {
7197
- const { responsive = true, direction = 'auto', keyField = 'id', striped = false, noDataComponent = 'built-in', isDisabled, isLoading, isFullHeight = false, subHeaderAlign = 'left', className } = props, rest = __rest(props, ["responsive", "direction", "keyField", "striped", "noDataComponent", "isDisabled", "isLoading", "isFullHeight", "subHeaderAlign", "className"]);
7198
- const combinedClassName = classNames(className, {
7199
- 'table--striped': striped,
7200
- 'table-body': true,
7201
- });
7202
- const tableWrapperClassName = classNames('table', {
7203
- 'table--full-height': isFullHeight,
7204
- });
7205
- return (jsxRuntime.jsx("div", { className: tableWrapperClassName, children: jsxRuntime.jsx(Xe, Object.assign({ responsive: responsive, direction: direction, subHeaderAlign: subHeaderAlign, keyField: keyField, striped: striped, className: combinedClassName, disabled: isDisabled, noDataComponent: noDataComponent, progressPending: isLoading, progressComponent: jsxRuntime.jsx(LoadingComponent, {}) }, rest)) }));
7206
- };
7207
-
7208
7196
  const Label = ({ label, name, isRequired }) => {
7209
7197
  return (jsxRuntime.jsx("div", { "data-testid": `${name}-testId`, className: `form-label`, children: jsxRuntime.jsxs("label", { htmlFor: `${name}`, children: [label, isRequired ? jsxRuntime.jsx("span", { className: "text-error", children: " *" }) : ''] }) }));
7210
7198
  };
@@ -7238,6 +7226,73 @@ const Input = React__namespace.default.forwardRef((_a, ref) => {
7238
7226
  });
7239
7227
  const LabeledInput = withLabel(Input);
7240
7228
 
7229
+ const Pagination = (_a) => {
7230
+ var { totalPages, currentPage = 1, onChange, className } = _a, rest = __rest(_a, ["totalPages", "currentPage", "onChange", "className"]);
7231
+ const [inputValue, setInputValue] = React.useState(currentPage.toString());
7232
+ const totalPagesText = `of ${totalPages}`;
7233
+ const classes = classNames('pagination', className);
7234
+ React.useEffect(() => {
7235
+ setInputValue(currentPage.toString());
7236
+ }, [currentPage]);
7237
+ const handleNextPage = () => {
7238
+ if (currentPage < totalPages) {
7239
+ onChange === null || onChange === void 0 ? void 0 : onChange(currentPage + 1);
7240
+ }
7241
+ };
7242
+ const handlePreviousPage = () => {
7243
+ if (currentPage > 1) {
7244
+ onChange === null || onChange === void 0 ? void 0 : onChange(currentPage - 1);
7245
+ }
7246
+ };
7247
+ const validateAndUpdatePage = (value) => {
7248
+ // If empty or invalid, reset to current page
7249
+ if (!value) {
7250
+ setInputValue(currentPage.toString());
7251
+ return;
7252
+ }
7253
+ const page = Number(value);
7254
+ if (!isNaN(page) && page > 0 && page <= totalPages) {
7255
+ onChange === null || onChange === void 0 ? void 0 : onChange(page);
7256
+ }
7257
+ else {
7258
+ setInputValue(currentPage.toString());
7259
+ }
7260
+ };
7261
+ const isNextButtonDisabled = currentPage === totalPages;
7262
+ const isPreviousButtonDisabled = currentPage === 1;
7263
+ const hasError = Number(inputValue) > totalPages || Number(inputValue) < 1;
7264
+ return (jsxRuntime.jsx("div", Object.assign({ className: classes }, rest, { children: jsxRuntime.jsx(Container, { children: jsxRuntime.jsxs(Row, { gutterWidth: 12, align: "center", children: [jsxRuntime.jsx(Col, { xs: "content", children: jsxRuntime.jsx("div", { className: "pagination__previous", children: jsxRuntime.jsx(Button$1, { "data-testid": "pagination-previous-button", ariaLabel: "Previous Page", variant: "link", onClick: handlePreviousPage, iconLeft: "chevron-left", isDisabled: isPreviousButtonDisabled }) }) }), jsxRuntime.jsx(Col, { xs: "content", children: jsxRuntime.jsx("div", { className: "pagination__current-page", children: jsxRuntime.jsx(LabeledInput, { "data-testid": "pagination-current-page-input", className: classNames('pagination__current-page-input', {
7265
+ 'has-error': hasError,
7266
+ }), value: inputValue, name: "currentPage", label: "Current Page", hasHiddenLabel: true, onKeyDown: (e) => {
7267
+ if (e.key === 'Enter') {
7268
+ validateAndUpdatePage(e.currentTarget.value);
7269
+ }
7270
+ }, onChange: (e) => {
7271
+ const value = e.currentTarget.value;
7272
+ // Allow empty value or numbers
7273
+ if (value === '' || /^\d*$/.test(value)) {
7274
+ setInputValue(value);
7275
+ }
7276
+ }, onBlur: (e) => validateAndUpdatePage(e.currentTarget.value) }) }) }), jsxRuntime.jsx(Col, { xs: "content", children: jsxRuntime.jsx("p", { className: "pagination__page-total", children: totalPagesText }) }), jsxRuntime.jsx(Col, { xs: "content", children: jsxRuntime.jsx("div", { className: "pagination__next", children: jsxRuntime.jsx(Button$1, { "data-testid": "pagination-next-button", ariaLabel: "Next Page", variant: "link", onClick: handleNextPage, iconLeft: "chevron-right", isDisabled: isNextButtonDisabled }) }) })] }) }) })));
7277
+ };
7278
+
7279
+ const TablePagination = ({ rowsPerPage, rowCount, onChangePage, currentPage, totalEntriesText, }) => {
7280
+ const totalPages = Math.ceil(rowCount / rowsPerPage);
7281
+ return (jsxRuntime.jsx("div", { className: "table__pagination", children: jsxRuntime.jsxs(Row, { align: "center", justify: "between", children: [jsxRuntime.jsx(Col, { xs: "content", children: totalEntriesText && (jsxRuntime.jsx("span", { "data-testid": "table-pagination-total-entries", className: "table__pagination-total-entries", children: totalEntriesText })) }), jsxRuntime.jsx(Col, { xs: "content", children: jsxRuntime.jsx(Pagination, { "data-testid": "table-pagination-component", totalPages: totalPages, currentPage: currentPage, onChange: (page) => onChangePage(page, rowsPerPage) }) })] }) }));
7282
+ };
7283
+
7284
+ const Table = (props) => {
7285
+ const { responsive = true, direction = 'auto', keyField = 'id', striped = false, noDataComponent = 'built-in', isDisabled, isLoading, isFullHeight = false, subHeaderAlign = 'left', className, paginationTotalRows, totalEntriesText } = props, rest = __rest(props, ["responsive", "direction", "keyField", "striped", "noDataComponent", "isDisabled", "isLoading", "isFullHeight", "subHeaderAlign", "className", "paginationTotalRows", "totalEntriesText"]);
7286
+ const combinedClassName = classNames(className, {
7287
+ 'table--striped': striped,
7288
+ 'table-body': true,
7289
+ });
7290
+ const tableWrapperClassName = classNames('table', {
7291
+ 'table--full-height': isFullHeight,
7292
+ });
7293
+ return (jsxRuntime.jsx("div", { className: tableWrapperClassName, "data-testid": "table", children: jsxRuntime.jsx(Xe, Object.assign({ responsive: responsive, direction: direction, subHeaderAlign: subHeaderAlign, keyField: keyField, striped: striped, className: combinedClassName, disabled: isDisabled, noDataComponent: noDataComponent, progressPending: isLoading, progressComponent: jsxRuntime.jsx(LoadingComponent, {}), pagination: true, paginationComponent: (props) => (jsxRuntime.jsx(TablePagination, Object.assign({}, props, { totalEntriesText: totalEntriesText }))), paginationTotalRows: paginationTotalRows }, rest)) }));
7294
+ };
7295
+
7241
7296
  const Radio = React__namespace.default.forwardRef((_a, ref) => {
7242
7297
  var { id, label, name, value, onChange, isDisabled } = _a, rest = __rest(_a, ["id", "label", "name", "value", "onChange", "isDisabled"]);
7243
7298
  return (jsxRuntime.jsx("div", { className: "form-control", children: jsxRuntime.jsxs("div", { className: "radio-wrapper", children: [jsxRuntime.jsx("input", Object.assign({ "data-testid": `form-radio-input-${name}`, className: "radio-input", type: "radio", id: id, name: name, value: value, disabled: isDisabled, ref: ref, onChange: onChange, tabIndex: 0, "aria-describedby": id, "aria-label": label }, rest)), jsxRuntime.jsx("label", { htmlFor: id, className: "radio-input-label", "data-testid": `label-radio-input-${name}`, children: label })] }) }));