@arbor-education/design-system.components 0.1.1 → 0.1.2

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 (74) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/components/button/Button.d.ts +1 -0
  3. package/dist/components/button/Button.d.ts.map +1 -1
  4. package/dist/components/button/Button.js +2 -1
  5. package/dist/components/button/Button.js.map +1 -1
  6. package/dist/components/formField/inputs/number/NumberInput.d.ts +2 -0
  7. package/dist/components/formField/inputs/number/NumberInput.d.ts.map +1 -1
  8. package/dist/components/formField/inputs/number/NumberInput.js +9 -4
  9. package/dist/components/formField/inputs/number/NumberInput.js.map +1 -1
  10. package/dist/components/table/BulkActionsDropdown.js +2 -2
  11. package/dist/components/table/BulkActionsDropdown.js.map +1 -1
  12. package/dist/components/table/GridApiContext.d.ts +1 -2
  13. package/dist/components/table/GridApiContext.d.ts.map +1 -1
  14. package/dist/components/table/GridApiContext.js +1 -1
  15. package/dist/components/table/GridApiContext.js.map +1 -1
  16. package/dist/components/table/Table.d.ts +9 -1
  17. package/dist/components/table/Table.d.ts.map +1 -1
  18. package/dist/components/table/Table.js +13 -5
  19. package/dist/components/table/Table.js.map +1 -1
  20. package/dist/components/table/Table.stories.d.ts +5 -1
  21. package/dist/components/table/Table.stories.d.ts.map +1 -1
  22. package/dist/components/table/Table.stories.js +36 -1
  23. package/dist/components/table/Table.stories.js.map +1 -1
  24. package/dist/components/table/Table.test.js +2 -0
  25. package/dist/components/table/Table.test.js.map +1 -1
  26. package/dist/components/table/pagination/PageSizeSelector.d.ts +7 -0
  27. package/dist/components/table/pagination/PageSizeSelector.d.ts.map +1 -0
  28. package/dist/components/table/pagination/PageSizeSelector.js +46 -0
  29. package/dist/components/table/pagination/PageSizeSelector.js.map +1 -0
  30. package/dist/components/table/pagination/Pagination.test.d.ts +2 -0
  31. package/dist/components/table/pagination/Pagination.test.d.ts.map +1 -0
  32. package/dist/components/table/pagination/Pagination.test.js +616 -0
  33. package/dist/components/table/pagination/Pagination.test.js.map +1 -0
  34. package/dist/components/table/pagination/PaginationControls.d.ts +6 -0
  35. package/dist/components/table/pagination/PaginationControls.d.ts.map +1 -0
  36. package/dist/components/table/pagination/PaginationControls.js +47 -0
  37. package/dist/components/table/pagination/PaginationControls.js.map +1 -0
  38. package/dist/components/table/pagination/PaginationPanel.d.ts +9 -0
  39. package/dist/components/table/pagination/PaginationPanel.d.ts.map +1 -0
  40. package/dist/components/table/pagination/PaginationPanel.js +11 -0
  41. package/dist/components/table/pagination/PaginationPanel.js.map +1 -0
  42. package/dist/components/table/pagination/RowCountInfo.d.ts +5 -0
  43. package/dist/components/table/pagination/RowCountInfo.d.ts.map +1 -0
  44. package/dist/components/table/pagination/RowCountInfo.js +53 -0
  45. package/dist/components/table/pagination/RowCountInfo.js.map +1 -0
  46. package/dist/index.css +28 -0
  47. package/dist/index.css.map +1 -1
  48. package/dist/utils/hooks/useGridApi.d.ts +5 -0
  49. package/dist/utils/hooks/useGridApi.d.ts.map +1 -0
  50. package/dist/utils/hooks/useGridApi.js +13 -0
  51. package/dist/utils/hooks/useGridApi.js.map +1 -0
  52. package/dist/utils/hooks/useIsMounted.d.ts +2 -0
  53. package/dist/utils/hooks/useIsMounted.d.ts.map +1 -0
  54. package/dist/utils/hooks/useIsMounted.js +12 -0
  55. package/dist/utils/hooks/useIsMounted.js.map +1 -0
  56. package/package.json +1 -1
  57. package/release/design-system.components.tgz +0 -0
  58. package/src/components/button/Button.tsx +3 -0
  59. package/src/components/button/button.scss +4 -0
  60. package/src/components/formField/inputs/number/NumberInput.tsx +39 -24
  61. package/src/components/table/BulkActionsDropdown.tsx +2 -2
  62. package/src/components/table/GridApiContext.ts +2 -2
  63. package/src/components/table/Table.stories.tsx +64 -2
  64. package/src/components/table/Table.test.tsx +2 -0
  65. package/src/components/table/Table.tsx +14 -4
  66. package/src/components/table/pagination/PageSizeSelector.tsx +73 -0
  67. package/src/components/table/pagination/Pagination.test.tsx +846 -0
  68. package/src/components/table/pagination/PaginationControls.tsx +116 -0
  69. package/src/components/table/pagination/PaginationPanel.tsx +30 -0
  70. package/src/components/table/pagination/RowCountInfo.tsx +67 -0
  71. package/src/components/table/pagination/pagination.scss +26 -0
  72. package/src/index.scss +1 -0
  73. package/src/utils/hooks/useGridApi.ts +15 -0
  74. package/src/utils/hooks/useIsMounted.ts +12 -0
@@ -5,7 +5,13 @@ import { Button } from 'Components/button/Button';
5
5
  import { Icon } from 'Components/icon/Icon';
6
6
  import { BulkActionsDropdown } from './BulkActionsDropdown';
7
7
 
8
- const meta: Meta<typeof Table> = {
8
+ import { useState, type ComponentProps } from 'react';
9
+ import { RowCountInfo } from './pagination/RowCountInfo';
10
+ import { PaginationPanel } from './pagination/PaginationPanel';
11
+
12
+ type TableProps = ComponentProps<typeof Table>;
13
+
14
+ const meta: Meta<TableProps> = {
9
15
  title: 'Components/Table',
10
16
  component: Table,
11
17
  };
@@ -46,7 +52,7 @@ const sampleColumnDefs: (ColDef | ColGroupDef)[] = [
46
52
 
47
53
  const FooterContent = [
48
54
  <Button key={0} variant="primary">Button 1</Button>,
49
- <span key={1}>Pagination placeholder</span>,
55
+ <RowCountInfo key={3} />,
50
56
  <Button key={2} variant="secondary">Button 2</Button>,
51
57
  ];
52
58
 
@@ -85,6 +91,7 @@ export const WithFooter: Story = {
85
91
  defaultColDef: defaultColDef,
86
92
  domLayout: 'autoHeight',
87
93
  footerContent: FooterContent,
94
+ pagination: true,
88
95
  },
89
96
  };
90
97
 
@@ -135,4 +142,59 @@ export const WithBulkActions: Story = {
135
142
  },
136
143
  };
137
144
 
145
+ export const WithClientSidePagination: StoryObj<TableProps> = {
146
+ args: {
147
+ rowData: sampleData,
148
+ columnDefs: sampleColumnDefs,
149
+ defaultColDef: defaultColDef,
150
+ domLayout: 'autoHeight',
151
+ pagination: true,
152
+ footerContent: <PaginationPanel availableSizes={[1, 2, 3, 4, 'All']} initialPageSize={2} />,
153
+ },
154
+ };
155
+
156
+ export const WithServerSidePagination: StoryObj<TableProps> = {
157
+ args: {
158
+ rowData: sampleData,
159
+ columnDefs: sampleColumnDefs,
160
+ defaultColDef: defaultColDef,
161
+ domLayout: 'autoHeight',
162
+ pagination: false,
163
+ },
164
+ render: () => {
165
+ const availableSizes = [1, 2, 3, 4, 'All'];
166
+ const initialPageSize = availableSizes[1] as number;
167
+ const [currentPage, setCurrentPage] = useState(0);
168
+ const [currentPageSize, setCurrentPageSize] = useState(initialPageSize);
169
+
170
+ const splitRowDataBasedOnPageSize = (arr: RowData[]): RowData[][] =>
171
+ arr.length > currentPageSize
172
+ ? [arr.slice(0, currentPageSize), ...splitRowDataBasedOnPageSize(arr.slice(currentPageSize))]
173
+ : [arr];
174
+
175
+ const pageData = splitRowDataBasedOnPageSize(sampleData);
176
+
177
+ const data = pageData[currentPage];
178
+
179
+ return (
180
+ <Table
181
+ rowData={data}
182
+ columnDefs={sampleColumnDefs}
183
+ defaultColDef={defaultColDef}
184
+ domLayout="autoHeight"
185
+ footerContent={(
186
+ <PaginationPanel
187
+ totalRows={5}
188
+ totalPages={pageData.length}
189
+ onPageChange={page => setCurrentPage(page)}
190
+ availableSizes={[1, 2, 3, 4, 'All']}
191
+ initialPageSize={currentPageSize}
192
+ onPageSizeChange={size => setCurrentPageSize(size as number)}
193
+ />
194
+ )}
195
+ />
196
+ );
197
+ },
198
+ };
199
+
138
200
  export default meta;
@@ -94,7 +94,9 @@ describe('Table', () => {
94
94
  expect(screen.getByText('Page 1 of 10')).toBeInTheDocument();
95
95
  expect(screen.getByText('Next')).toBeInTheDocument();
96
96
  });
97
+ });
97
98
 
99
+ describe('BulkActionsDropdown', () => {
98
100
  test('renders all bulk actions in dropdown', async () => {
99
101
  render(
100
102
  <Table
@@ -2,10 +2,14 @@ import { AllEnterpriseModule, ModuleRegistry, type GridApi } from 'ag-grid-enter
2
2
  import { AgGridReact, type AgGridReactProps } from 'ag-grid-react';
3
3
  import { tableTheme } from './tableTheme';
4
4
  import classNames from 'classnames';
5
- import { useRef, type ReactNode } from 'react';
5
+ import { useState, type ReactNode } from 'react';
6
6
  import { TableFooter } from './TableFooter';
7
7
  import { TableHeader } from './TableHeader';
8
8
  import { GridApiContext } from './GridApiContext';
9
+ import { PaginationPanel } from './pagination/PaginationPanel';
10
+ import { PageSizeSelector } from './pagination/PageSizeSelector';
11
+ import { PaginationControls } from './pagination/PaginationControls';
12
+ import { RowCountInfo } from './pagination/RowCountInfo';
9
13
 
10
14
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
15
  type TableProps<TData = any> = {
@@ -31,10 +35,10 @@ export const Table = (props: TableProps) => {
31
35
  ...rest
32
36
  } = props;
33
37
 
34
- const gridApiRef = useRef<GridApi>(null);
38
+ const [gridApi, setGridApi] = useState<GridApi | null>(null);
35
39
 
36
40
  return (
37
- <GridApiContext.Provider value={gridApiRef}>
41
+ <GridApiContext.Provider value={gridApi}>
38
42
  <section data-testid={testId} className={classNames('ds-table__container', wrapperClassName)}>
39
43
  {headerContent && (
40
44
  <TableHeader data-testid={headerTestId}>
@@ -45,9 +49,10 @@ export const Table = (props: TableProps) => {
45
49
  theme={tableTheme}
46
50
  onGridReady={(event) => {
47
51
  const { api } = event;
48
- gridApiRef.current = api;
52
+ setGridApi(api);
49
53
  onGridReady?.(event);
50
54
  }}
55
+ suppressPaginationPanel
51
56
  {...rest}
52
57
  />
53
58
  {footerContent && (
@@ -59,3 +64,8 @@ export const Table = (props: TableProps) => {
59
64
  </GridApiContext.Provider>
60
65
  );
61
66
  };
67
+
68
+ Table.PaginationPanel = PaginationPanel;
69
+ Table.PageSizeSelector = PageSizeSelector;
70
+ Table.PaginationControls = PaginationControls;
71
+ Table.RowCountInfo = RowCountInfo;
@@ -0,0 +1,73 @@
1
+ import { Button } from 'Components/button/Button';
2
+ import { Dropdown } from 'Components/dropdown/Dropdown';
3
+ import { useEffect, useState } from 'react';
4
+ import { useGridApi } from 'Utils/hooks/useGridApi';
5
+
6
+ const DEFAULT_PAGE_SIZES = [
7
+ 10,
8
+ 20,
9
+ 30,
10
+ 50,
11
+ 100,
12
+ 200,
13
+ 300,
14
+ 500,
15
+ 1000,
16
+ 'All',
17
+ ] as const;
18
+
19
+ export type PageSizeSelectorProps = {
20
+ availableSizes?: (number | 'All')[];
21
+ initialPageSize?: number | 'All';
22
+ onPageSizeChange?: (newPageSize: number | 'All') => void;
23
+ };
24
+
25
+ export const PageSizeSelector = (props: PageSizeSelectorProps) => {
26
+ const {
27
+ availableSizes = DEFAULT_PAGE_SIZES,
28
+ initialPageSize,
29
+ onPageSizeChange: passedOnPageSizeChange,
30
+ } = props;
31
+
32
+ const { gridApi, isGridApiReady } = useGridApi();
33
+
34
+ const [selectedPageSize, setSelectedPageSize] = useState(initialPageSize || '100');
35
+
36
+ const updatePageSize = (newPageSize: string | number) => {
37
+ const normalizedValue = !isNaN(Number(newPageSize)) ? Number(newPageSize) : 'All';
38
+ setSelectedPageSize(normalizedValue);
39
+ if (passedOnPageSizeChange) {
40
+ passedOnPageSizeChange(normalizedValue);
41
+ return;
42
+ }
43
+ if (typeof normalizedValue === 'number') {
44
+ gridApi?.setGridOption('pagination', true);
45
+ gridApi?.setGridOption('paginationPageSize', normalizedValue);
46
+ }
47
+ else {
48
+ gridApi?.setGridOption('pagination', false);
49
+ }
50
+ };
51
+
52
+ useEffect(() => {
53
+ if (isGridApiReady && initialPageSize) {
54
+ updatePageSize(initialPageSize);
55
+ }
56
+ }, [isGridApiReady]);
57
+
58
+ return (
59
+ <Dropdown>
60
+ <Dropdown.Trigger>
61
+ <Button variant="dropdown" iconRightName="chevron-down" aria-label="Select page size">
62
+ {selectedPageSize}
63
+ </Button>
64
+ </Dropdown.Trigger>
65
+ <Dropdown.Content>
66
+ {availableSizes.map((size) => {
67
+ return <Dropdown.Item key={size} onSelect={() => updatePageSize(size)}>{size}</Dropdown.Item>;
68
+ })}
69
+ </Dropdown.Content>
70
+ </Dropdown>
71
+
72
+ );
73
+ };