@luscii-healthtech/web-ui 30.4.1 → 30.6.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.
@@ -49,6 +49,7 @@ export interface CheckboxProps {
49
49
  */
50
50
  value?: string;
51
51
  onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
52
+ onClick?: (event: React.MouseEvent<HTMLInputElement, MouseEvent>) => void;
52
53
  className?: string;
53
54
  classNameCheckboxLabel?: string;
54
55
  /**
@@ -1,6 +1,10 @@
1
1
  import React from "react";
2
2
  import { PaginationMenuProps } from "../PaginationMenu/PaginationMenu.types";
3
3
  import { TableFieldConfig } from "./Table.types";
4
+ type SelectableTableRow<Item> = {
5
+ index: number;
6
+ value: Item;
7
+ };
4
8
  export interface TableProps<Item> extends React.HTMLAttributes<HTMLTableElement> {
5
9
  items?: Item[];
6
10
  fieldConfigurations: TableFieldConfig<Item>[];
@@ -12,5 +16,37 @@ export interface TableProps<Item> extends React.HTMLAttributes<HTMLTableElement>
12
16
  onRowClick?: (item: Item) => void;
13
17
  className?: string;
14
18
  dataTestId?: string;
19
+ /**
20
+ * When `true`, will render checkboxes as the first column of each row,
21
+ * including the header. Allowing for multiple rows to be selected.
22
+ *
23
+ * Two callbacks can control this behavior:
24
+ * - The one for each row selected `onSelectedRow`,
25
+ * triggered by the checkbox in the table row.
26
+ * - The one for all rows selected `onSelectedAllRows`,
27
+ * triggered by the checkbox in the table header.
28
+ *
29
+ * Turning this configuration on also requires `selectedItems` to be passed as a prop,
30
+ * the shape of this prop is:
31
+ *
32
+ * `Array<{ index: number; value: Item }>` -> Where `Item` is the generic shape
33
+ * passed to the table, in the `props.items` list.
34
+ *
35
+ * Also gives access to the `onSelectedRowsChange` callback, if you need to use it.
36
+ *
37
+ */
38
+ isSelectable?: boolean;
39
+ /**
40
+ * Used to render components on the header for when one or all
41
+ * rows are selected.
42
+ *
43
+ * Ideally this will be one or more buttons for specific actions.
44
+ *
45
+ *
46
+ */
47
+ rowSelectionHeaderAccessories?: React.ReactNode;
48
+ selectedItems?: Array<SelectableTableRow<Item>>;
49
+ onSelectedRowsChange?: (params: Array<SelectableTableRow<Item>>) => void;
15
50
  }
16
- export declare function Table<Item>({ items, fieldConfigurations, emptyRowsText, emptyFieldContentText, isLoading, showHeader, paginationMenuProps, onRowClick, className, dataTestId, ...otherAttributes }: TableProps<Item>): JSX.Element;
51
+ export declare function Table<Item>({ items, fieldConfigurations, emptyRowsText, emptyFieldContentText, isLoading, showHeader, paginationMenuProps, onRowClick, className, dataTestId, isSelectable, selectedItems, onSelectedRowsChange, rowSelectionHeaderAccessories, ...otherAttributes }: TableProps<Item>): JSX.Element;
52
+ export {};
@@ -1,3 +1,56 @@
1
1
  import { TableFieldText, TableFieldAction, TableFieldContent } from "./Table.types";
2
2
  export declare function isTableFieldText<Item>(content: TableFieldContent<Item>): content is TableFieldText;
3
3
  export declare function isTableFieldAction<Item>(content: TableFieldContent<Item>): content is [TableFieldAction<Item>?, TableFieldAction<Item>?];
4
+ /**
5
+ * This function is to be used when the data we need can be completely on the client side.
6
+ * By doing so we have a centralized way to deal with pagination.
7
+ *
8
+ * For server side data (e.g.: pagination on the API), do not use this and rely on the API instead.
9
+ *
10
+ * @example
11
+ * const chunkSize = 17;
12
+ * const totalItems = 200;
13
+ *
14
+ * // Create an array with 200 items [0, 1, 2, ..., 199]
15
+ * const array = Array.from(Array(totalItems).keys());
16
+ *
17
+ * // Split array into chunks of 17, where the least one will have only 13 items.
18
+ * const chunks = chunkArray(array, chunkSize);
19
+ *
20
+ * console.log(chunks);
21
+ * // Output:
22
+ * // [
23
+ * // [0, 1, 2, ..., 16],
24
+ * // [17, 18, 19, ..., 33],
25
+ * // ...
26
+ * // [187, 188, 189, ..., 199]
27
+ * // ]
28
+ */
29
+ export declare function prepareClientSidePagination<Item>({
30
+ /**
31
+ * The array to be split into chunks.
32
+ */
33
+ items,
34
+ /**
35
+ * The size of each page.
36
+ */
37
+ pageSize, }: {
38
+ items: Array<Item>;
39
+ pageSize: number;
40
+ }): {
41
+ pageSlices: Array<Array<Item>>;
42
+ /**
43
+ * The size of the collection.
44
+ */
45
+ totalItems: number;
46
+ /**
47
+ * The amount of pages based on the number of items.
48
+ */
49
+ pages: number;
50
+ /**
51
+ * Utility function to help getting items from a specific page.
52
+ * @param pageNumber - the page being seeked
53
+ * @returns - the array containing the items of a specific page.
54
+ */
55
+ getItemsFromPage: (pageNumber: number) => Array<Item>;
56
+ };
@@ -1,13 +1,33 @@
1
1
  /// <reference types="react" />
2
2
  import { TableFieldConfig } from "./Table.types";
3
- export interface TableBody<Item> {
4
- items?: Item[];
5
- fieldConfigurations: TableFieldConfig<Item>[];
3
+ export interface TableBody<RowData> {
4
+ items?: RowData[];
5
+ selectedItems?: {
6
+ index: number;
7
+ }[];
8
+ fieldConfigurations: TableFieldConfig<RowData>[];
6
9
  emptyItemsText: string;
7
10
  emptyFieldContentText?: string;
8
11
  isLoading: boolean;
9
12
  showEmptyView: boolean;
10
- onRowClick?: (item: Item) => void;
13
+ onRowClick?: (item: RowData) => void;
11
14
  className?: string;
15
+ /**
16
+ * Property to use when the table does not have a footer,
17
+ * and we want to preserve the rounded layout.
18
+ */
19
+ lastRowRounded: boolean;
20
+ /**
21
+ * Property to use when the table does not have a header,
22
+ * and we want to preserve the rounded layout.
23
+ */
24
+ topRowRounded: boolean;
25
+ isSelectable?: boolean;
26
+ onSelectRow?: (params: {
27
+ checked: boolean;
28
+ rowIndex: number;
29
+ value: RowData;
30
+ }) => void;
31
+ colSpan: number;
12
32
  }
13
33
  export declare function TableBody<Item>(props: TableBody<Item>): JSX.Element;
@@ -1,7 +1,18 @@
1
- /// <reference types="react" />
1
+ import React from "react";
2
2
  import { TableFieldConfig } from "./Table.types";
3
- export interface TableHeaderProps<Item> {
3
+ export type TableHeaderProps<Item> = {
4
4
  fieldConfigurations: TableFieldConfig<Item>[];
5
5
  className?: string;
6
- }
6
+ /**
7
+ * The combination of checkbox and action button above the table,
8
+ * replaces the default header when there are one or more items selected.
9
+ *
10
+ */
11
+ selectAllComponent?: React.ReactNode;
12
+ /**
13
+ * The checkbox next to the other headers, can be used to select all items.
14
+ */
15
+ selectAllCheckbox?: React.ReactNode;
16
+ colSpan: number;
17
+ };
7
18
  export declare function TableHeader<Item>(props: TableHeaderProps<Item>): JSX.Element;
package/dist/index.d.ts CHANGED
@@ -38,6 +38,7 @@ export { FlyOutMenu } from "./components/FlyOutMenu/FlyOutMenu";
38
38
  export { StyledInput } from "./components/Input/StyledInput";
39
39
  export { default as Line } from "./components/Line/Line";
40
40
  export { Table, type TableProps } from "./components/Table/Table";
41
+ export { prepareClientSidePagination } from "./components/Table/Table.utils";
41
42
  export { type TableFieldConfig, type TableFieldContent, type TableFieldText, type TableFieldAction, } from "./components/Table/Table.types";
42
43
  export { LoadingIndicator, type LoadingIndicatorProps, } from "./components/LoadingIndicator/LoadingIndicator";
43
44
  export { default as Menu } from "./components/Menu/Menu";
@@ -2743,7 +2743,7 @@ var css_248z$b = "/**\n * --- DEPRECATED ---\n * DON'T USE ANYTHING FROM THIS FI
2743
2743
  styleInject(css_248z$b);
2744
2744
 
2745
2745
  const CheckboxInner = (props) => {
2746
- const { id, explanation, type = "regular", isChecked = false, isIndeterminate = false, isDisabled, name, value, onChange, className, classNameCheckboxLabel, error, innerRef } = props;
2746
+ const { id, explanation, type = "regular", isChecked = false, isIndeterminate = false, isDisabled, name, value, onChange, onClick, className, classNameCheckboxLabel, error, innerRef } = props;
2747
2747
  const [checked, setChecked] = React.useState(false);
2748
2748
  const [indeterminate, setIndeterminate] = React.useState(isIndeterminate);
2749
2749
  const [isFocused, setIsFocused] = React.useState(false);
@@ -2780,7 +2780,19 @@ const CheckboxInner = (props) => {
2780
2780
  const handleBlur = () => setIsFocused(false);
2781
2781
  return React__namespace.default.createElement(
2782
2782
  "div",
2783
- { className: containerClassName, "data-test-id": "checkbox" },
2783
+ {
2784
+ className: containerClassName,
2785
+ /**
2786
+ * This harms a11y since the div becomes an interactible element.
2787
+ * The main interaction in this component happens between a styled label (looking like a checkbox)
2788
+ * and the invisible input checkbox itself.
2789
+ *
2790
+ * This `onClick` event is a requirement from using this component in the table,
2791
+ * since the row is clickable and we need to stop propagation to not invoking the row click
2792
+ * upon marking the checkbox as checked/unchecked.
2793
+ */
2794
+ onClick
2795
+ },
2784
2796
  React__namespace.default.createElement(
2785
2797
  "label",
2786
2798
  { className: classNames__default.default(classNameCheckboxLabel, "cweb-checkbox-label ui-group ui-relative ui-overflow-hidden", "ui-flex ui-w-full ui-cursor-pointer", {
@@ -3678,18 +3690,46 @@ Line.propTypes = {
3678
3690
  className: PropTypes__default.default.string
3679
3691
  };
3680
3692
 
3693
+ const THead = (props) => {
3694
+ return React__namespace.default.createElement("thead", { className: classNames__default.default(
3695
+ // Styles for all <th>
3696
+ "[&>tr>th]:ui-border-neutral-interactive",
3697
+ "[&>tr>th]:ui-border-y",
3698
+ "[&>tr>th]:ui-px-xxs",
3699
+ // Styles for the first <th> in the header row
3700
+ "[&>tr>th:first-child]:ui-rounded-tl-2xl [&>tr>th:first-child]:ui-border-l [&>tr>th:first-child]:ui-pl-l",
3701
+ // Styles for the last <th> in the table row
3702
+ "[&>tr>th:last-child]:ui-rounded-tr-2xl [&>tr>th:last-child]:ui-border-r [&>tr>th:last-child]:ui-pr-l"
3703
+ ) }, props.children);
3704
+ };
3681
3705
  function TableHeader(props) {
3706
+ if (props.selectAllComponent) {
3707
+ return React__namespace.default.createElement(
3708
+ THead,
3709
+ null,
3710
+ React__namespace.default.createElement(
3711
+ "tr",
3712
+ { className: "ui-rounded-2xl" },
3713
+ React__namespace.default.createElement("th", { colSpan: props.colSpan }, props.selectAllComponent)
3714
+ )
3715
+ );
3716
+ }
3682
3717
  return React__namespace.default.createElement(
3683
- "thead",
3684
- { className: props.className },
3685
- React__namespace.default.createElement("tr", null, props.fieldConfigurations.map((fieldConfig) => {
3686
- var _a;
3687
- return React__namespace.default.createElement(
3688
- "th",
3689
- { className: "ui-px-2 first:ui-pl-6 last:ui-pr-6", key: fieldConfig.key },
3690
- React__namespace.default.createElement(Text, { text: (_a = fieldConfig.headerText) !== null && _a !== void 0 ? _a : "", type: "strong", className: "ui-truncate ui-py-4 ui-text-left ui-uppercase ui-leading-5" })
3691
- );
3692
- }))
3718
+ THead,
3719
+ null,
3720
+ React__namespace.default.createElement(
3721
+ "tr",
3722
+ { className: "ui-rounded-2xl" },
3723
+ props.selectAllCheckbox && React__namespace.default.createElement("th", null, props.selectAllCheckbox),
3724
+ props.fieldConfigurations.map((fieldConfig) => {
3725
+ var _a;
3726
+ return React__namespace.default.createElement(
3727
+ "th",
3728
+ { key: fieldConfig.key },
3729
+ React__namespace.default.createElement(Text, { variant: "strong", className: "ui-truncate ui-py-m ui-text-left ui-capitalize ui-leading-5" }, (_a = fieldConfig.headerText) !== null && _a !== void 0 ? _a : "")
3730
+ );
3731
+ })
3732
+ )
3693
3733
  );
3694
3734
  }
3695
3735
 
@@ -3699,6 +3739,36 @@ function isTableFieldText(content) {
3699
3739
  function isTableFieldAction(content) {
3700
3740
  return Array.isArray(content) && content.some((action) => action && "key" in action && "icon" in action && "handleClick" in action);
3701
3741
  }
3742
+ function prepareClientSidePagination({
3743
+ /**
3744
+ * The array to be split into chunks.
3745
+ */
3746
+ items,
3747
+ /**
3748
+ * The size of each page.
3749
+ */
3750
+ pageSize
3751
+ }) {
3752
+ const totalItems = items.length;
3753
+ let pages = Math.floor(totalItems / pageSize);
3754
+ const remainderFromChunk = totalItems % pageSize;
3755
+ if (remainderFromChunk > 0) {
3756
+ pages++;
3757
+ }
3758
+ const pageSlices = [];
3759
+ for (let i = 0; i < pages; i++) {
3760
+ const startOfSlice = i * pageSize;
3761
+ const endOfSlice = startOfSlice + pageSize;
3762
+ const chunkSlice = items.slice(startOfSlice, endOfSlice);
3763
+ pageSlices.push(chunkSlice);
3764
+ }
3765
+ return {
3766
+ pageSlices,
3767
+ totalItems,
3768
+ pages,
3769
+ getItemsFromPage: (pageNumber) => pageSlices[pageNumber]
3770
+ };
3771
+ }
3702
3772
 
3703
3773
  function TableBodyRowDataCell(props) {
3704
3774
  var _a;
@@ -3710,16 +3780,14 @@ function TableBodyRowDataCell(props) {
3710
3780
  const isTextCellEmpty = isTableFieldText(content) && !content.text && !content.tag;
3711
3781
  return React__namespace.default.createElement(
3712
3782
  "td",
3713
- { className: classNames__default.default("ui-px-2 first:ui-pl-6 last:ui-pr-6", {
3714
- "ui-align-top": !isTableFieldAction(content)
3715
- }) },
3783
+ { className: classNames__default.default("ui-px-2 ui-align-middle first:ui-pl-6 last:ui-pr-6") },
3716
3784
  isTableFieldText(content) && React__namespace.default.createElement(
3717
3785
  "div",
3718
- { className: "ui-flex ui-flex-row" },
3786
+ { className: "ui-flex ui-flex-row " },
3719
3787
  content.tag && React__namespace.default.createElement(
3720
3788
  "div",
3721
3789
  { className: "ui-mr-2 ui-mt-3" },
3722
- React__namespace.default.createElement(Tag, { text: content.tag.text, colorTheme: content.tag.color })
3790
+ React__namespace.default.createElement(Tag, { colorTheme: content.tag.color }, content.tag.text)
3723
3791
  ),
3724
3792
  React__namespace.default.createElement(
3725
3793
  "div",
@@ -3727,11 +3795,11 @@ function TableBodyRowDataCell(props) {
3727
3795
  React__namespace.default.createElement(Text, { className: classNames__default.default("ui-text-left ui-leading-5", {
3728
3796
  "ui-break-all": content.breakAllWord,
3729
3797
  "ui-break-words": !content.breakAllWord
3730
- }), text: isTextCellEmpty ? emptyFieldContentText : content.text, type: "base" }),
3798
+ }) }, isTextCellEmpty ? emptyFieldContentText : content.text),
3731
3799
  content.description && React__namespace.default.createElement(Text, { className: classNames__default.default({
3732
3800
  "ui-break-all": content.description.breakAllWord,
3733
3801
  "ui-break-words": !content.description.breakAllWord
3734
- }), text: content.description.content, type: "sm", color: "slate-500" })
3802
+ }), variant: "sm", color: "slate-500" }, content.description.content)
3735
3803
  )
3736
3804
  ),
3737
3805
  isTableFieldAction(content) && React__namespace.default.createElement("div", { className: classNames__default.default("ui-flex ui-flex-row ui-justify-end", "ui-transition-opacity ui-duration-300 ui-ease-in-out", {
@@ -3748,30 +3816,76 @@ function TableBodyRowDataCell(props) {
3748
3816
  );
3749
3817
  }
3750
3818
 
3751
- function TableBodyRow(props) {
3752
- const handleRowClick = (event) => {
3753
- var _a;
3754
- event.stopPropagation();
3755
- (_a = props.onClick) === null || _a === void 0 ? void 0 : _a.call(props, props.item);
3756
- };
3757
- return React__namespace.default.createElement("tr", { tabIndex: 0, className: classNames__default.default("ui-group", {
3758
- "ui-cursor-pointer ui-transition-colors ui-duration-300 ui-ease-in-out hover:ui-bg-blue-50 focus:ui-outline-primary": props.onClick,
3759
- "ui-cursor-default hover:ui-bg-white": !props.onClick
3760
- }, props.className), onClick: handleRowClick }, props.fieldConfigurations.map((fieldConfig) => React__namespace.default.createElement(TableBodyRowDataCell, { key: fieldConfig.key, item: props.item, fieldConfig, emptyFieldContentText: props.emptyFieldContentText })));
3761
- }
3762
-
3763
3819
  function TableBody(props) {
3764
3820
  var _a;
3821
+ const isItemChecked = (index) => {
3822
+ if (!props.selectedItems) {
3823
+ return false;
3824
+ }
3825
+ return Boolean(props.selectedItems.find((item) => item.index === index));
3826
+ };
3827
+ const generateRowClickHandler = (item) => {
3828
+ return (event) => {
3829
+ var _a2;
3830
+ event.stopPropagation();
3831
+ (_a2 = props.onRowClick) === null || _a2 === void 0 ? void 0 : _a2.call(props, item);
3832
+ };
3833
+ };
3765
3834
  return React__namespace.default.createElement(
3766
3835
  "tbody",
3767
- { className: props.className },
3768
- !props.isLoading && ((_a = props.items) === null || _a === void 0 ? void 0 : _a.map((item) => React__namespace.default.createElement(TableBodyRow, { className: classNames__default.default("ui-border-b ui-border-slate-100 last:ui-border-none"), key: JSON.stringify(item), item, fieldConfigurations: props.fieldConfigurations, emptyFieldContentText: props.emptyFieldContentText, onClick: props.onRowClick }))),
3836
+ { className: classNames__default.default(
3837
+ props.className,
3838
+ // setting border color across all cells
3839
+ "[&>tr>td]:ui-border-neutral-interactive",
3840
+ // left border for first cell and right border for last cell
3841
+ "[&>tr>td:first-child]:ui-border-l [&>tr>td:last-child]:ui-border-r",
3842
+ "[&>tr>td]:ui-border-b",
3843
+ /**
3844
+ * Configuration for the top row to have rounded edges, in case
3845
+ * there is no header.
3846
+ */
3847
+ {
3848
+ "[&>tr:first-child>td]:ui-border-t": props.topRowRounded,
3849
+ "[&>tr:first-child>td:first-child]:ui-rounded-tl-2xl": props.topRowRounded,
3850
+ "[&>tr:first-child>td:last-child]:ui-rounded-tr-2xl": props.topRowRounded
3851
+ },
3852
+ /**
3853
+ * Configuration for the last row to have rounded edges, in case
3854
+ * there is no footer.
3855
+ */
3856
+ {
3857
+ "[&>tr:last-child>td:first-child]:ui-rounded-bl-2xl": props.lastRowRounded,
3858
+ "[&>tr:last-child>td:last-child]:ui-rounded-br-2xl": props.lastRowRounded
3859
+ }
3860
+ ) },
3861
+ !props.isLoading && ((_a = props.items) === null || _a === void 0 ? void 0 : _a.map((item, index) => React__namespace.default.createElement(
3862
+ "tr",
3863
+ { tabIndex: 0, className: classNames__default.default("ui-group", {
3864
+ "ui-cursor-pointer ui-transition-colors ui-duration-300 ui-ease-in-out hover:ui-bg-blue-50 focus:ui-outline-primary": props.onRowClick,
3865
+ "ui-cursor-default hover:ui-bg-white": !props.onRowClick,
3866
+ "ui-bg-blue-100": isItemChecked(index)
3867
+ }, props.className), onClick: generateRowClickHandler(item) },
3868
+ props.isSelectable && React__namespace.default.createElement(
3869
+ "td",
3870
+ { className: "ui-px-2 first:ui-pl-6 last:ui-pr-6" },
3871
+ React__namespace.default.createElement(Checkbox, { isChecked: isItemChecked(index), onClick: (event) => event.stopPropagation(), onChange: (event) => {
3872
+ var _a2;
3873
+ event.stopPropagation();
3874
+ (_a2 = props.onSelectRow) === null || _a2 === void 0 ? void 0 : _a2.call(props, {
3875
+ rowIndex: index,
3876
+ checked: event.target.checked,
3877
+ value: item
3878
+ });
3879
+ } })
3880
+ ),
3881
+ props.fieldConfigurations.map((fieldConfig) => React__namespace.default.createElement(TableBodyRowDataCell, { key: fieldConfig.key, item, fieldConfig, emptyFieldContentText: props.emptyFieldContentText }))
3882
+ ))),
3769
3883
  props.isLoading && React__namespace.default.createElement(
3770
3884
  "tr",
3771
3885
  null,
3772
3886
  React__namespace.default.createElement(
3773
3887
  "td",
3774
- { colSpan: props.fieldConfigurations.length },
3888
+ { colSpan: props.colSpan },
3775
3889
  React__namespace.default.createElement(LoadingIndicator, { className: "ui-px-3 ui-py-0", asModal: false })
3776
3890
  )
3777
3891
  ),
@@ -3780,7 +3894,7 @@ function TableBody(props) {
3780
3894
  null,
3781
3895
  React__namespace.default.createElement(
3782
3896
  "td",
3783
- { colSpan: props.fieldConfigurations.length },
3897
+ { colSpan: props.colSpan },
3784
3898
  React__namespace.default.createElement(EmptyListMessage, { className: "ui-py-6", text: props.emptyItemsText, imageName: "search-not-found" })
3785
3899
  )
3786
3900
  )
@@ -3997,7 +4111,7 @@ const TableFooter = (props) => {
3997
4111
  null,
3998
4112
  React__namespace.default.createElement(
3999
4113
  "td",
4000
- { colSpan: props.colSpan },
4114
+ { className: "ui-rounded-b-2xl ui-border-x ui-border-b ui-border-neutral-interactive", colSpan: props.colSpan },
4001
4115
  React__namespace.default.createElement(PaginationMenu, Object.assign({ className: "ui-p-6" }, props.paginationMenuProps))
4002
4116
  )
4003
4117
  )
@@ -4005,20 +4119,83 @@ const TableFooter = (props) => {
4005
4119
  };
4006
4120
 
4007
4121
  function Table(_a) {
4008
- var { items, fieldConfigurations, emptyRowsText, emptyFieldContentText, isLoading = false, showHeader = true, paginationMenuProps, onRowClick, className, dataTestId } = _a, otherAttributes = __rest(_a, ["items", "fieldConfigurations", "emptyRowsText", "emptyFieldContentText", "isLoading", "showHeader", "paginationMenuProps", "onRowClick", "className", "dataTestId"]);
4122
+ var { items, fieldConfigurations, emptyRowsText, emptyFieldContentText, isLoading = false, showHeader = true, paginationMenuProps, onRowClick, className, dataTestId, isSelectable, selectedItems, onSelectedRowsChange, rowSelectionHeaderAccessories } = _a, otherAttributes = __rest(_a, ["items", "fieldConfigurations", "emptyRowsText", "emptyFieldContentText", "isLoading", "showHeader", "paginationMenuProps", "onRowClick", "className", "dataTestId", "isSelectable", "selectedItems", "onSelectedRowsChange", "rowSelectionHeaderAccessories"]);
4009
4123
  const [isPristine, setIsPristine] = React.useState(true);
4124
+ const getSelectAllCheckboxState = () => {
4125
+ if (!items || !selectedItems) {
4126
+ return "unchecked";
4127
+ }
4128
+ const totalItems = items.length;
4129
+ if (selectedItems.length === 0) {
4130
+ return "unchecked";
4131
+ }
4132
+ if (selectedItems.length === items.length) {
4133
+ return "checked";
4134
+ }
4135
+ if (selectedItems.length !== totalItems) {
4136
+ return "indeterminate";
4137
+ }
4138
+ return "unchecked";
4139
+ };
4010
4140
  React.useEffect(() => {
4011
4141
  setIsPristine(false);
4012
4142
  }, [items, isLoading]);
4013
4143
  const showEmptyView = !isPristine && !isLoading && !(items && items.length > 0);
4144
+ const showFooter = !isLoading && !showEmptyView && paginationMenuProps && paginationMenuProps.currentPageNumber > 0 && paginationMenuProps.pageCount > 0;
4145
+ const colSpan = isSelectable ? fieldConfigurations.length + 1 : fieldConfigurations.length;
4146
+ const handleOnToggleAll = () => {
4147
+ const newState = getSelectAllCheckboxState() === "checked" ? [] : (items !== null && items !== void 0 ? items : []).map((value, index) => ({
4148
+ index,
4149
+ value
4150
+ }));
4151
+ onSelectedRowsChange === null || onSelectedRowsChange === void 0 ? void 0 : onSelectedRowsChange(newState);
4152
+ };
4153
+ const handleOnSelectRow = (params) => {
4154
+ if (!selectedItems) {
4155
+ return;
4156
+ }
4157
+ const newState = params.checked ? [...selectedItems, { value: params.value, index: params.rowIndex }] : selectedItems.filter((item) => item.index !== params.rowIndex);
4158
+ onSelectedRowsChange === null || onSelectedRowsChange === void 0 ? void 0 : onSelectedRowsChange(newState);
4159
+ };
4160
+ const shouldDisplaySelectAllControls = isSelectable && rowSelectionHeaderAccessories && selectedItems && selectedItems.length > 0;
4161
+ const toggleAllCheckbox = React__namespace.default.createElement(
4162
+ "label",
4163
+ null,
4164
+ React__namespace.default.createElement("span", { className: "ui-sr-only" }, "Select all rows"),
4165
+ React__namespace.default.createElement(Checkbox, { isChecked: getSelectAllCheckboxState() === "checked", isIndeterminate: getSelectAllCheckboxState() === "indeterminate", onChange: handleOnToggleAll })
4166
+ );
4014
4167
  return React__namespace.default.createElement(
4015
4168
  "table",
4016
- Object.assign({ className: classNames__default.default("ui-w-full ui-table-auto ui-border-collapse ui-rounded-lg ui-bg-white", className), "data-test-id": dataTestId }, otherAttributes),
4017
- showHeader ? React__namespace.default.createElement(TableHeader, { className: "ui-border-b ui-border-slate-100", fieldConfigurations }) : null,
4018
- React__namespace.default.createElement(TableBody, { className: classNames__default.default({
4019
- "ui-border-b ui-border-slate-100": !isLoading && !showEmptyView && paginationMenuProps && paginationMenuProps.currentPageNumber > 0 && paginationMenuProps.pageCount > 0
4020
- }), items, fieldConfigurations, emptyItemsText: emptyRowsText, emptyFieldContentText, isLoading, showEmptyView, onRowClick }),
4021
- !isLoading && !showEmptyView && paginationMenuProps && paginationMenuProps.currentPageNumber > 0 && paginationMenuProps.pageCount > 0 ? React__namespace.default.createElement(TableFooter, { colSpan: fieldConfigurations.length, paginationMenuProps }) : null
4169
+ Object.assign({ className: classNames__default.default("ui-w-full ui-table-auto ui-bg-white", "ui-border-separate ui-border-spacing-0 ui-rounded-2xl", className), "data-test-id": dataTestId }, otherAttributes),
4170
+ showHeader ? React__namespace.default.createElement(TableHeader, { fieldConfigurations, colSpan, selectAllCheckbox: isSelectable ? toggleAllCheckbox : null, selectAllComponent: shouldDisplaySelectAllControls ? React__namespace.default.createElement(
4171
+ Stack,
4172
+ { axis: "x", align: "center", gap: "xs", my: "xxs" },
4173
+ toggleAllCheckbox,
4174
+ rowSelectionHeaderAccessories
4175
+ ) : null }) : null,
4176
+ React__namespace.default.createElement(
4177
+ TableBody,
4178
+ {
4179
+ // TODO: early return to remove all the boolean juggling.
4180
+ className: classNames__default.default({
4181
+ "ui-border-b ui-border-neutral-interactive": showFooter
4182
+ }),
4183
+ items,
4184
+ fieldConfigurations,
4185
+ emptyItemsText: emptyRowsText,
4186
+ emptyFieldContentText,
4187
+ isLoading,
4188
+ showEmptyView,
4189
+ onRowClick,
4190
+ lastRowRounded: !showFooter,
4191
+ topRowRounded: !showHeader,
4192
+ isSelectable,
4193
+ onSelectRow: handleOnSelectRow,
4194
+ selectedItems,
4195
+ colSpan
4196
+ }
4197
+ ),
4198
+ showFooter ? React__namespace.default.createElement(TableFooter, { colSpan, paginationMenuProps }) : null
4022
4199
  );
4023
4200
  }
4024
4201
 
@@ -6857,5 +7034,6 @@ exports.ViewItem = ViewItem;
6857
7034
  exports.WarningIcon = ExclamationMarkIcon;
6858
7035
  exports.WeekdaysPicker = WeekdaysPicker;
6859
7036
  exports.getDndListItemProps = getDndListItemProps;
7037
+ exports.prepareClientSidePagination = prepareClientSidePagination;
6860
7038
  exports.toast = toast;
6861
7039
  //# sourceMappingURL=index.development.js.map