@arbor-education/design-system.components 0.1.2 → 0.1.4
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.
- package/.github/workflows/chromatic.yml +2 -1
- package/.github/workflows/release.yml +135 -0
- package/CHANGELOG.md +9 -1
- package/bin/createComponent.sh +39 -9
- package/dist/components/dropdown/Dropdown.d.ts +1 -0
- package/dist/components/dropdown/Dropdown.d.ts.map +1 -1
- package/dist/components/dropdown/DropdownContent.d.ts +1 -0
- package/dist/components/dropdown/DropdownContent.d.ts.map +1 -1
- package/dist/components/dropdown/DropdownContent.js +3 -2
- package/dist/components/dropdown/DropdownContent.js.map +1 -1
- package/dist/components/formField/FormField.d.ts +8 -0
- package/dist/components/formField/FormField.d.ts.map +1 -1
- package/dist/components/formField/FormField.js +3 -1
- package/dist/components/formField/FormField.js.map +1 -1
- package/dist/components/formField/FormField.stories.d.ts.map +1 -1
- package/dist/components/formField/FormField.stories.js +5 -0
- package/dist/components/formField/FormField.stories.js.map +1 -1
- package/dist/components/formField/FormField.test.js +11 -1
- package/dist/components/formField/FormField.test.js.map +1 -1
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.d.ts +12 -0
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.d.ts.map +1 -0
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.js +17 -0
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.js.map +1 -0
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.d.ts +10 -0
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.d.ts.map +1 -0
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.js +24 -0
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.js.map +1 -0
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.test.d.ts +2 -0
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.test.d.ts.map +1 -0
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.test.js +88 -0
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.test.js.map +1 -0
- package/dist/components/formField/inputs/selectDropdown/SelectDropdown.d.ts +10 -6
- package/dist/components/formField/inputs/selectDropdown/SelectDropdown.d.ts.map +1 -1
- package/dist/components/formField/inputs/selectDropdown/SelectDropdown.js +10 -6
- package/dist/components/formField/inputs/selectDropdown/SelectDropdown.js.map +1 -1
- package/dist/components/formField/inputs/selectDropdown/SelectDropdown.test.js +1 -1
- package/dist/components/formField/inputs/selectDropdown/SelectDropdown.test.js.map +1 -1
- package/dist/components/icon/Icon.d.ts +0 -1
- package/dist/components/icon/Icon.d.ts.map +1 -1
- package/dist/components/icon/Icon.js +1 -1
- package/dist/components/icon/Icon.js.map +1 -1
- package/dist/components/searchBar/SearchBar.d.ts +8 -0
- package/dist/components/searchBar/SearchBar.d.ts.map +1 -0
- package/dist/components/searchBar/SearchBar.js +38 -0
- package/dist/components/searchBar/SearchBar.js.map +1 -0
- package/dist/components/searchBar/SearchBar.test.d.ts +2 -0
- package/dist/components/searchBar/SearchBar.test.d.ts.map +1 -0
- package/dist/components/searchBar/SearchBar.test.js +36 -0
- package/dist/components/searchBar/SearchBar.test.js.map +1 -0
- package/dist/components/slideover/Slideover.d.ts +1 -0
- package/dist/components/slideover/Slideover.d.ts.map +1 -1
- package/dist/components/slideover/Slideover.js +2 -2
- package/dist/components/slideover/Slideover.js.map +1 -1
- package/dist/components/table/HideColumnsDropdown.d.ts +9 -0
- package/dist/components/table/HideColumnsDropdown.d.ts.map +1 -0
- package/dist/components/table/HideColumnsDropdown.js +33 -0
- package/dist/components/table/HideColumnsDropdown.js.map +1 -0
- package/dist/components/table/Table.d.ts +14 -0
- package/dist/components/table/Table.d.ts.map +1 -1
- package/dist/components/table/Table.js +8 -3
- package/dist/components/table/Table.js.map +1 -1
- package/dist/components/table/Table.stories.d.ts +3 -0
- package/dist/components/table/Table.stories.d.ts.map +1 -1
- package/dist/components/table/Table.stories.js +53 -1
- package/dist/components/table/Table.stories.js.map +1 -1
- package/dist/components/table/Table.test.js +132 -0
- package/dist/components/table/Table.test.js.map +1 -1
- package/dist/components/table/TableHeader.d.ts +3 -0
- package/dist/components/table/TableHeader.d.ts.map +1 -1
- package/dist/components/table/TableHeader.js +4 -3
- package/dist/components/table/TableHeader.js.map +1 -1
- package/dist/index.css +93 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/components/dropdown/DropdownContent.tsx +4 -2
- package/src/components/formField/FormField.stories.tsx +17 -0
- package/src/components/formField/FormField.test.tsx +13 -1
- package/src/components/formField/FormField.tsx +10 -0
- package/src/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.tsx +29 -0
- package/src/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.test.tsx +121 -0
- package/src/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.tsx +53 -0
- package/src/components/formField/inputs/colourPickerDropdown/colourPickerDropdown.scss +12 -0
- package/src/components/formField/inputs/selectDropdown/SelectDropdown.test.tsx +1 -1
- package/src/components/formField/inputs/selectDropdown/SelectDropdown.tsx +55 -41
- package/src/components/heading/heading.scss +1 -0
- package/src/components/icon/Icon.tsx +1 -2
- package/src/components/searchBar/SearchBar.test.tsx +40 -0
- package/src/components/searchBar/SearchBar.tsx +97 -0
- package/src/components/searchBar/searchBar.scss +69 -0
- package/src/components/slideover/Slideover.tsx +10 -5
- package/src/components/table/HideColumnsDropdown.tsx +57 -0
- package/src/components/table/Table.stories.tsx +96 -2
- package/src/components/table/Table.test.tsx +240 -0
- package/src/components/table/Table.tsx +10 -1
- package/src/components/table/TableHeader.tsx +8 -0
- package/src/components/table/table.scss +22 -0
- package/src/index.scss +24 -22
- package/src/index.ts +1 -0
- package/.github/workflows/changeset-version.yml +0 -39
- package/.github/workflows/merge-version-packages-pr.yml +0 -31
- package/.github/workflows/production-build.yml +0 -130
- package/release/design-system.components.tgz +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import type
|
|
2
|
+
import { type Column, type ColDef, type ColGroupDef } from 'ag-grid-enterprise';
|
|
3
3
|
import { Table } from './Table';
|
|
4
4
|
import { Button } from 'Components/button/Button';
|
|
5
5
|
import { Icon } from 'Components/icon/Icon';
|
|
@@ -8,6 +8,7 @@ import { BulkActionsDropdown } from './BulkActionsDropdown';
|
|
|
8
8
|
import { useState, type ComponentProps } from 'react';
|
|
9
9
|
import { RowCountInfo } from './pagination/RowCountInfo';
|
|
10
10
|
import { PaginationPanel } from './pagination/PaginationPanel';
|
|
11
|
+
import { HideColumnsDropdown } from './HideColumnsDropdown';
|
|
11
12
|
|
|
12
13
|
type TableProps = ComponentProps<typeof Table>;
|
|
13
14
|
|
|
@@ -62,7 +63,6 @@ const HeaderContent = [
|
|
|
62
63
|
<Button key={1} variant="secondary" size="S">Button 2</Button>
|
|
63
64
|
</div>,
|
|
64
65
|
<div key={1} style={{ display: 'flex', gap: '1rem' }}>
|
|
65
|
-
<Icon name="search" />
|
|
66
66
|
<Icon name="download" />
|
|
67
67
|
<Icon name="settings" />
|
|
68
68
|
<Icon name="circle-help" />
|
|
@@ -105,6 +105,17 @@ export const WithHeader: Story = {
|
|
|
105
105
|
},
|
|
106
106
|
};
|
|
107
107
|
|
|
108
|
+
export const WithHeaderAndNoSearch: Story = {
|
|
109
|
+
args: {
|
|
110
|
+
rowData: sampleData,
|
|
111
|
+
columnDefs: sampleColumnDefs,
|
|
112
|
+
defaultColDef: defaultColDef,
|
|
113
|
+
domLayout: 'autoHeight',
|
|
114
|
+
headerContent: HeaderContent,
|
|
115
|
+
hasSearch: false,
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
|
|
108
119
|
export const WithHeaderAndFooter: Story = {
|
|
109
120
|
args: {
|
|
110
121
|
rowData: sampleData,
|
|
@@ -142,6 +153,89 @@ export const WithBulkActions: Story = {
|
|
|
142
153
|
},
|
|
143
154
|
};
|
|
144
155
|
|
|
156
|
+
export const WithHideColumnsDropdown: Story = {
|
|
157
|
+
args: {
|
|
158
|
+
rowData: sampleData,
|
|
159
|
+
columnDefs: sampleColumnDefs,
|
|
160
|
+
defaultColDef: defaultColDef,
|
|
161
|
+
domLayout: 'autoHeight',
|
|
162
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
163
|
+
// @ts-ignore
|
|
164
|
+
overrideColumnHiding: false,
|
|
165
|
+
},
|
|
166
|
+
render: (args) => {
|
|
167
|
+
const {
|
|
168
|
+
rowData,
|
|
169
|
+
columnDefs,
|
|
170
|
+
defaultColDef,
|
|
171
|
+
domLayout,
|
|
172
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
173
|
+
// @ts-ignore
|
|
174
|
+
overrideColumnHiding,
|
|
175
|
+
} = args;
|
|
176
|
+
|
|
177
|
+
return (
|
|
178
|
+
<Table
|
|
179
|
+
rowData={rowData}
|
|
180
|
+
columnDefs={columnDefs}
|
|
181
|
+
defaultColDef={defaultColDef}
|
|
182
|
+
domLayout={domLayout}
|
|
183
|
+
headerContent={(
|
|
184
|
+
<HideColumnsDropdown
|
|
185
|
+
overrideColumnHiding={overrideColumnHiding}
|
|
186
|
+
onSelectionChanged={console.log}
|
|
187
|
+
/>
|
|
188
|
+
)}
|
|
189
|
+
/>
|
|
190
|
+
);
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export const WithRestrictedHideColumnsDropdown: Story = {
|
|
195
|
+
args: {
|
|
196
|
+
rowData: sampleData,
|
|
197
|
+
columnDefs: sampleColumnDefs,
|
|
198
|
+
defaultColDef: defaultColDef,
|
|
199
|
+
domLayout: 'autoHeight',
|
|
200
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
201
|
+
// @ts-ignore
|
|
202
|
+
overrideColumnHiding: false,
|
|
203
|
+
},
|
|
204
|
+
render: (args) => {
|
|
205
|
+
const {
|
|
206
|
+
rowData,
|
|
207
|
+
columnDefs,
|
|
208
|
+
defaultColDef,
|
|
209
|
+
domLayout,
|
|
210
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
211
|
+
// @ts-ignore
|
|
212
|
+
overrideColumnHiding,
|
|
213
|
+
} = args;
|
|
214
|
+
|
|
215
|
+
const [columns, setColumns] = useState<Column[]>([]);
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<Table
|
|
219
|
+
rowData={rowData}
|
|
220
|
+
columnDefs={columnDefs}
|
|
221
|
+
defaultColDef={defaultColDef}
|
|
222
|
+
domLayout={domLayout}
|
|
223
|
+
onGridReady={(params) => {
|
|
224
|
+
const { api } = params;
|
|
225
|
+
setColumns(api.getColumns()?.slice(1) || []);
|
|
226
|
+
}}
|
|
227
|
+
headerContent={(
|
|
228
|
+
<HideColumnsDropdown
|
|
229
|
+
overrideColumnHiding={overrideColumnHiding}
|
|
230
|
+
onSelectionChanged={console.log}
|
|
231
|
+
columns={columns}
|
|
232
|
+
/>
|
|
233
|
+
)}
|
|
234
|
+
/>
|
|
235
|
+
);
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
|
|
145
239
|
export const WithClientSidePagination: StoryObj<TableProps> = {
|
|
146
240
|
args: {
|
|
147
241
|
rowData: sampleData,
|
|
@@ -3,6 +3,7 @@ import { render, screen, waitFor } from '@testing-library/react';
|
|
|
3
3
|
import { Table } from './Table';
|
|
4
4
|
import '@testing-library/jest-dom/vitest';
|
|
5
5
|
import { BulkActionsDropdown } from 'Components/table/BulkActionsDropdown';
|
|
6
|
+
import { HideColumnsDropdown } from 'Components/table/HideColumnsDropdown';
|
|
6
7
|
import userEvent from '@testing-library/user-event';
|
|
7
8
|
import type { GridApi } from 'ag-grid-enterprise';
|
|
8
9
|
|
|
@@ -169,4 +170,243 @@ describe('Table', () => {
|
|
|
169
170
|
expect(callbackMock).not.toHaveBeenCalled();
|
|
170
171
|
});
|
|
171
172
|
});
|
|
173
|
+
|
|
174
|
+
describe('HideColumnsDropdown', () => {
|
|
175
|
+
const columnDefs = [
|
|
176
|
+
{ field: 'name', headerName: 'Name' },
|
|
177
|
+
{ field: 'age', headerName: 'Age' },
|
|
178
|
+
{ field: 'email', headerName: 'Email' },
|
|
179
|
+
];
|
|
180
|
+
|
|
181
|
+
const rowData = [
|
|
182
|
+
{ name: 'John Doe', age: 30, email: 'john@example.com' },
|
|
183
|
+
{ name: 'Jane Smith', age: 25, email: 'jane@example.com' },
|
|
184
|
+
];
|
|
185
|
+
|
|
186
|
+
test('renders HideColumnsDropdown in header', async () => {
|
|
187
|
+
render(
|
|
188
|
+
<Table
|
|
189
|
+
columnDefs={columnDefs}
|
|
190
|
+
rowData={rowData}
|
|
191
|
+
headerContent={<HideColumnsDropdown />}
|
|
192
|
+
/>,
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
await waitFor(() => expect(screen.getByText('Hide Columns')).toBeInTheDocument());
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test('shows all column options when dropdown is opened', async () => {
|
|
199
|
+
render(
|
|
200
|
+
<Table
|
|
201
|
+
columnDefs={columnDefs}
|
|
202
|
+
rowData={rowData}
|
|
203
|
+
headerContent={<HideColumnsDropdown />}
|
|
204
|
+
/>,
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
await waitFor(() => expect(screen.getByText('Hide Columns')).toBeInTheDocument());
|
|
208
|
+
await userEvent.click(screen.getByText('Hide Columns'));
|
|
209
|
+
|
|
210
|
+
await waitFor(() => {
|
|
211
|
+
const dropdownItems = screen.getAllByRole('menuitemcheckbox');
|
|
212
|
+
expect(dropdownItems).toHaveLength(3);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
test('calls onSelectionChanged callback when columns are selected', async () => {
|
|
217
|
+
const onSelectionChanged = vi.fn();
|
|
218
|
+
|
|
219
|
+
render(
|
|
220
|
+
<Table
|
|
221
|
+
columnDefs={columnDefs}
|
|
222
|
+
rowData={rowData}
|
|
223
|
+
headerContent={(
|
|
224
|
+
<HideColumnsDropdown
|
|
225
|
+
onSelectionChanged={onSelectionChanged}
|
|
226
|
+
overrideColumnHiding
|
|
227
|
+
/>
|
|
228
|
+
)}
|
|
229
|
+
/>,
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
await waitFor(() => expect(screen.getByText('Hide Columns')).toBeInTheDocument());
|
|
233
|
+
await userEvent.click(screen.getByText('Hide Columns'));
|
|
234
|
+
|
|
235
|
+
const menuItems = await screen.findAllByRole('menuitemcheckbox');
|
|
236
|
+
const nameItem = menuItems.find(item => item.textContent === 'Name');
|
|
237
|
+
|
|
238
|
+
await userEvent.click(nameItem!);
|
|
239
|
+
|
|
240
|
+
await waitFor(() => {
|
|
241
|
+
expect(onSelectionChanged).toHaveBeenCalled();
|
|
242
|
+
expect(onSelectionChanged).toHaveBeenCalledWith(expect.arrayContaining(['name']));
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
test('hides selected columns when overrideColumnHiding is false', async () => {
|
|
247
|
+
const { container } = render(
|
|
248
|
+
<Table
|
|
249
|
+
columnDefs={columnDefs}
|
|
250
|
+
rowData={rowData}
|
|
251
|
+
headerContent={<HideColumnsDropdown />}
|
|
252
|
+
/>,
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
// Wait for grid to be ready
|
|
256
|
+
await waitFor(() => expect(screen.getByRole('grid')).toBeInTheDocument());
|
|
257
|
+
|
|
258
|
+
await waitFor(() => expect(screen.getByText('Hide Columns')).toBeInTheDocument());
|
|
259
|
+
const dropdownButton = screen.getByText('Hide Columns');
|
|
260
|
+
await userEvent.click(dropdownButton);
|
|
261
|
+
|
|
262
|
+
const menuItems = await screen.findAllByRole('menuitemcheckbox');
|
|
263
|
+
const nameItem = menuItems.find(item => item.textContent === 'Name');
|
|
264
|
+
|
|
265
|
+
await userEvent.click(nameItem!);
|
|
266
|
+
|
|
267
|
+
// The column should be hidden in the grid
|
|
268
|
+
await waitFor(() => {
|
|
269
|
+
const headers = container.querySelectorAll('.ag-header-cell-text');
|
|
270
|
+
const headerTexts = Array.from(headers).map(h => h.textContent);
|
|
271
|
+
expect(headerTexts).not.toContain('Name');
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
test('does not hide columns when overrideColumnHiding is true', async () => {
|
|
276
|
+
const onSelectionChanged = vi.fn();
|
|
277
|
+
const { container } = render(
|
|
278
|
+
<Table
|
|
279
|
+
columnDefs={columnDefs}
|
|
280
|
+
rowData={rowData}
|
|
281
|
+
headerContent={(
|
|
282
|
+
<HideColumnsDropdown
|
|
283
|
+
onSelectionChanged={onSelectionChanged}
|
|
284
|
+
overrideColumnHiding
|
|
285
|
+
/>
|
|
286
|
+
)}
|
|
287
|
+
/>,
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
await waitFor(() => expect(screen.getByRole('grid')).toBeInTheDocument());
|
|
291
|
+
|
|
292
|
+
await waitFor(() => expect(screen.getByText('Hide Columns')).toBeInTheDocument());
|
|
293
|
+
await userEvent.click(screen.getByText('Hide Columns'));
|
|
294
|
+
|
|
295
|
+
const menuItems = await screen.findAllByRole('menuitemcheckbox');
|
|
296
|
+
const nameItem = menuItems.find(item => item.textContent === 'Name');
|
|
297
|
+
|
|
298
|
+
await userEvent.click(nameItem!);
|
|
299
|
+
|
|
300
|
+
// The column should still be visible when overrideColumnHiding is true
|
|
301
|
+
await waitFor(() => {
|
|
302
|
+
const headers = container.querySelectorAll('.ag-header-cell-text');
|
|
303
|
+
const headerTexts = Array.from(headers).map(h => h.textContent);
|
|
304
|
+
expect(headerTexts).toContain('Name');
|
|
305
|
+
expect(onSelectionChanged).toHaveBeenCalled();
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
test('can hide multiple columns', async () => {
|
|
310
|
+
const { container } = render(
|
|
311
|
+
<Table
|
|
312
|
+
columnDefs={columnDefs}
|
|
313
|
+
rowData={rowData}
|
|
314
|
+
headerContent={<HideColumnsDropdown />}
|
|
315
|
+
/>,
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
await waitFor(() => expect(screen.getByRole('grid')).toBeInTheDocument());
|
|
319
|
+
|
|
320
|
+
// Open dropdown and select Name column
|
|
321
|
+
await waitFor(() => expect(screen.getByRole('button', { name: /Hide Columns/ })).toBeInTheDocument());
|
|
322
|
+
await userEvent.click(screen.getByRole('button', { name: /Hide Columns/ }));
|
|
323
|
+
|
|
324
|
+
let menuItems = await screen.findAllByRole('menuitemcheckbox');
|
|
325
|
+
const nameItem = menuItems.find(item => item.textContent === 'Name');
|
|
326
|
+
await userEvent.click(nameItem!);
|
|
327
|
+
|
|
328
|
+
await userEvent.keyboard('{Escape}');
|
|
329
|
+
|
|
330
|
+
await waitFor(() => {
|
|
331
|
+
expect(screen.getByText('Hide (1)')).toBeInTheDocument();
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
await userEvent.click(screen.getByText('Hide (1)'));
|
|
335
|
+
|
|
336
|
+
menuItems = await screen.findAllByRole('menuitemcheckbox');
|
|
337
|
+
const ageItem = menuItems.find(item => item.textContent === 'Age');
|
|
338
|
+
await userEvent.click(ageItem!);
|
|
339
|
+
|
|
340
|
+
// Both columns should be hidden
|
|
341
|
+
await waitFor(() => {
|
|
342
|
+
const headers = container.querySelectorAll('.ag-header-cell-text');
|
|
343
|
+
const headerTexts = Array.from(headers).map(h => h.textContent);
|
|
344
|
+
expect(headerTexts).not.toContain('Name');
|
|
345
|
+
expect(headerTexts).not.toContain('Age');
|
|
346
|
+
expect(headerTexts).toContain('Email');
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
test('updates dropdown text to reflect number of hidden columns', async () => {
|
|
351
|
+
render(
|
|
352
|
+
<Table
|
|
353
|
+
columnDefs={columnDefs}
|
|
354
|
+
rowData={rowData}
|
|
355
|
+
headerContent={<HideColumnsDropdown />}
|
|
356
|
+
/>,
|
|
357
|
+
);
|
|
358
|
+
|
|
359
|
+
await waitFor(() => expect(screen.getByText('Hide Columns')).toBeInTheDocument());
|
|
360
|
+
await userEvent.click(screen.getByText('Hide Columns'));
|
|
361
|
+
|
|
362
|
+
const menuItems = await screen.findAllByRole('menuitemcheckbox');
|
|
363
|
+
const nameItem = menuItems.find(item => item.textContent === 'Name');
|
|
364
|
+
|
|
365
|
+
await userEvent.click(nameItem!);
|
|
366
|
+
|
|
367
|
+
await waitFor(() => {
|
|
368
|
+
expect(screen.getByText('Hide (1)')).toBeInTheDocument();
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
test('works with custom columns prop', async () => {
|
|
373
|
+
const mockColumn = {
|
|
374
|
+
getColDef: () => ({ headerName: 'Custom Column' }),
|
|
375
|
+
isVisible: () => true,
|
|
376
|
+
getColId: () => 'custom',
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
const onSelectionChanged = vi.fn();
|
|
380
|
+
|
|
381
|
+
render(
|
|
382
|
+
<Table
|
|
383
|
+
columnDefs={columnDefs}
|
|
384
|
+
rowData={rowData}
|
|
385
|
+
headerContent={(
|
|
386
|
+
<HideColumnsDropdown
|
|
387
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
388
|
+
// @ts-expect-error
|
|
389
|
+
columns={[mockColumn]}
|
|
390
|
+
onSelectionChanged={onSelectionChanged}
|
|
391
|
+
overrideColumnHiding
|
|
392
|
+
/>
|
|
393
|
+
)}
|
|
394
|
+
/>,
|
|
395
|
+
);
|
|
396
|
+
|
|
397
|
+
await userEvent.click(screen.getByText('Hide Columns'));
|
|
398
|
+
|
|
399
|
+
const menuItems = await screen.findAllByRole('menuitemcheckbox');
|
|
400
|
+
expect(menuItems).toHaveLength(1);
|
|
401
|
+
expect(menuItems[0]).toHaveTextContent('Custom Column');
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
test('returns null when no columns are available', () => {
|
|
405
|
+
const { container } = render(
|
|
406
|
+
<div><HideColumnsDropdown columns={[]} /></div>,
|
|
407
|
+
);
|
|
408
|
+
|
|
409
|
+
expect(container.querySelector('button')).toBeNull();
|
|
410
|
+
});
|
|
411
|
+
});
|
|
172
412
|
});
|
|
@@ -10,11 +10,14 @@ import { PaginationPanel } from './pagination/PaginationPanel';
|
|
|
10
10
|
import { PageSizeSelector } from './pagination/PageSizeSelector';
|
|
11
11
|
import { PaginationControls } from './pagination/PaginationControls';
|
|
12
12
|
import { RowCountInfo } from './pagination/RowCountInfo';
|
|
13
|
+
import { BulkActionsDropdown } from './BulkActionsDropdown';
|
|
14
|
+
import { HideColumnsDropdown } from './HideColumnsDropdown';
|
|
13
15
|
|
|
14
16
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
17
|
type TableProps<TData = any> = {
|
|
16
18
|
'wrapperClassName'?: string;
|
|
17
19
|
'data-testid'?: string;
|
|
20
|
+
'hasSearch'?: boolean;
|
|
18
21
|
'footerContent'?: ReactNode;
|
|
19
22
|
'footerTestId'?: string;
|
|
20
23
|
'headerContent'?: ReactNode;
|
|
@@ -29,6 +32,7 @@ export const Table = (props: TableProps) => {
|
|
|
29
32
|
wrapperClassName,
|
|
30
33
|
headerContent,
|
|
31
34
|
headerTestId,
|
|
35
|
+
hasSearch = true,
|
|
32
36
|
footerContent,
|
|
33
37
|
footerTestId,
|
|
34
38
|
onGridReady,
|
|
@@ -37,11 +41,13 @@ export const Table = (props: TableProps) => {
|
|
|
37
41
|
|
|
38
42
|
const [gridApi, setGridApi] = useState<GridApi | null>(null);
|
|
39
43
|
|
|
44
|
+
const [searchValue, setSearchValue] = useState('');
|
|
45
|
+
|
|
40
46
|
return (
|
|
41
47
|
<GridApiContext.Provider value={gridApi}>
|
|
42
48
|
<section data-testid={testId} className={classNames('ds-table__container', wrapperClassName)}>
|
|
43
49
|
{headerContent && (
|
|
44
|
-
<TableHeader data-testid={headerTestId}>
|
|
50
|
+
<TableHeader data-testid={headerTestId} hasSearch={hasSearch} searchValue={searchValue} setSearchValue={setSearchValue}>
|
|
45
51
|
{headerContent}
|
|
46
52
|
</TableHeader>
|
|
47
53
|
)}
|
|
@@ -54,6 +60,7 @@ export const Table = (props: TableProps) => {
|
|
|
54
60
|
}}
|
|
55
61
|
suppressPaginationPanel
|
|
56
62
|
{...rest}
|
|
63
|
+
{...(hasSearch && { quickFilterText: searchValue })}
|
|
57
64
|
/>
|
|
58
65
|
{footerContent && (
|
|
59
66
|
<TableFooter data-testid={footerTestId}>
|
|
@@ -69,3 +76,5 @@ Table.PaginationPanel = PaginationPanel;
|
|
|
69
76
|
Table.PageSizeSelector = PageSizeSelector;
|
|
70
77
|
Table.PaginationControls = PaginationControls;
|
|
71
78
|
Table.RowCountInfo = RowCountInfo;
|
|
79
|
+
Table.BulkActionsDropdown = BulkActionsDropdown;
|
|
80
|
+
Table.HideColumnsDropdown = HideColumnsDropdown;
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import classNames from 'classnames';
|
|
2
2
|
import type { ReactNode } from 'react';
|
|
3
|
+
import { SearchBar } from 'Components/searchBar/SearchBar';
|
|
3
4
|
|
|
4
5
|
type TableHeaderProps = {
|
|
5
6
|
'className'?: string;
|
|
7
|
+
'hasSearch'?: boolean;
|
|
8
|
+
'searchValue'?: string;
|
|
9
|
+
'setSearchValue'?: (searchValue: string) => void;
|
|
6
10
|
'children'?: ReactNode;
|
|
7
11
|
'data-testid'?: string;
|
|
8
12
|
};
|
|
@@ -10,6 +14,9 @@ type TableHeaderProps = {
|
|
|
10
14
|
export const TableHeader = (props: TableHeaderProps) => {
|
|
11
15
|
const {
|
|
12
16
|
className,
|
|
17
|
+
hasSearch,
|
|
18
|
+
searchValue,
|
|
19
|
+
setSearchValue,
|
|
13
20
|
children,
|
|
14
21
|
'data-testid': dataTestId,
|
|
15
22
|
} = props;
|
|
@@ -20,6 +27,7 @@ export const TableHeader = (props: TableHeaderProps) => {
|
|
|
20
27
|
className={classNames('ds-table__header', className)}
|
|
21
28
|
>
|
|
22
29
|
{children}
|
|
30
|
+
{hasSearch && <SearchBar searchValue={searchValue} setSearchValue={setSearchValue} />}
|
|
23
31
|
</header>
|
|
24
32
|
);
|
|
25
33
|
};
|
|
@@ -17,5 +17,27 @@
|
|
|
17
17
|
color: var(--tables-header-color-text);
|
|
18
18
|
background-color: var(--tables-header-color-background);
|
|
19
19
|
padding: var(--tables-header-spacing-top) var(--tables-header-spacing-horizontal) var(--tables-header-spacing-bottom);
|
|
20
|
+
gap: var(--tables-controls-spacing-gap);
|
|
21
|
+
|
|
22
|
+
.ds-search-bar--inactive {
|
|
23
|
+
margin-left: auto;
|
|
24
|
+
border-radius: var(--search-in-table-radius);
|
|
25
|
+
background: var(--search-in-table-default-color-background);
|
|
26
|
+
|
|
27
|
+
&:hover {
|
|
28
|
+
background: var(--search-in-table-hover-color-background);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.ds-search-bar {
|
|
33
|
+
margin-left: auto;
|
|
34
|
+
border-radius: var(--search-in-table-radius);
|
|
35
|
+
background: var(--search-in-table-default-color-background);
|
|
36
|
+
|
|
37
|
+
&__input {
|
|
38
|
+
color: var(--search-in-table-default-color-text);
|
|
39
|
+
background-color: var(--search-in-table-default-color-background);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
20
42
|
}
|
|
21
43
|
}
|
package/src/index.scss
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
@use
|
|
2
|
-
@use
|
|
3
|
-
@use
|
|
4
|
-
@use
|
|
5
|
-
@use
|
|
6
|
-
@use
|
|
7
|
-
@use
|
|
8
|
-
@use
|
|
9
|
-
@use
|
|
10
|
-
@use
|
|
11
|
-
@use
|
|
12
|
-
@use
|
|
13
|
-
@use
|
|
1
|
+
@use "./tokens.scss";
|
|
2
|
+
@use "./global.scss";
|
|
3
|
+
@use "components/button/button.scss";
|
|
4
|
+
@use "components/icon/icon.scss";
|
|
5
|
+
@use "components/heading/heading.scss";
|
|
6
|
+
@use "components/card/card.scss";
|
|
7
|
+
@use "components/dropdown/dropdown.scss";
|
|
8
|
+
@use "components/formField/formField.scss";
|
|
9
|
+
@use "components/formField/inputs/input.scss";
|
|
10
|
+
@use "components/formField/label/label.scss";
|
|
11
|
+
@use "components/formField/inputs/number/numberInput.scss";
|
|
12
|
+
@use "components/formField/inputs/radio/radioButtonInput.scss";
|
|
13
|
+
@use "components/formField/inputs/checkbox/checkboxInput.scss";
|
|
14
14
|
@use "components/formField/inputs/selectDropdown/selectDropdown";
|
|
15
|
-
@use
|
|
16
|
-
@use
|
|
17
|
-
@use
|
|
18
|
-
@use "
|
|
19
|
-
@use "
|
|
20
|
-
@use "
|
|
21
|
-
@use "
|
|
22
|
-
@use "
|
|
23
|
-
@
|
|
15
|
+
@use "components/formField/inputs/colourPickerDropdown/colourPickerDropdown.scss";
|
|
16
|
+
@use "components/pill/pill.scss";
|
|
17
|
+
@use "components/section/section.scss";
|
|
18
|
+
@use "components/tabs/tabs.scss";
|
|
19
|
+
@use "components/slideoverManager/slideoverManager.scss";
|
|
20
|
+
@use "components/slideover/slideover.scss";
|
|
21
|
+
@use "components/table/table.scss";
|
|
22
|
+
@use "components/searchBar/searchBar.scss";
|
|
23
|
+
@use "components/table/pagination/pagination.scss";
|
|
24
|
+
@use "components/tooltip/tooltip.scss";
|
|
25
|
+
@import "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap";
|
package/src/index.ts
CHANGED
|
@@ -9,6 +9,7 @@ export { Tabs } from 'Components/tabs/Tabs';
|
|
|
9
9
|
export { TextInput } from 'Components/formField/inputs/text/TextInput';
|
|
10
10
|
export { TextArea } from 'Components/formField/inputs/textArea/TextArea';
|
|
11
11
|
export { NumberInput } from 'Components/formField/inputs/number/NumberInput';
|
|
12
|
+
export { ColourPickerDropdown } from 'Components/formField/inputs/colourPickerDropdown/ColourPickerDropdown';
|
|
12
13
|
export { SelectDropdown } from 'Components/formField/inputs/selectDropdown/SelectDropdown';
|
|
13
14
|
export { SlideoverManager } from 'Components/slideoverManager/SlideoverManager';
|
|
14
15
|
export { Slideover, type SlideoverProps } from 'Components/slideover/Slideover';
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
name: Release
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- main
|
|
7
|
-
|
|
8
|
-
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
|
9
|
-
|
|
10
|
-
jobs:
|
|
11
|
-
release:
|
|
12
|
-
name: Release
|
|
13
|
-
runs-on: ubuntu-latest
|
|
14
|
-
steps:
|
|
15
|
-
- name: Checkout Repo
|
|
16
|
-
uses: actions/checkout@v4
|
|
17
|
-
with:
|
|
18
|
-
fetch-depth: 0
|
|
19
|
-
token: ${{ secrets.ARBOR_AUTOMATION_ORG_GHA_TOKEN }}
|
|
20
|
-
|
|
21
|
-
- name: Setup Node.js
|
|
22
|
-
uses: actions/setup-node@v4
|
|
23
|
-
with:
|
|
24
|
-
node-version-file: ".nvmrc"
|
|
25
|
-
cache: "yarn"
|
|
26
|
-
|
|
27
|
-
- name: Install yarn
|
|
28
|
-
run: npm install yarn -g
|
|
29
|
-
|
|
30
|
-
- name: Install Dependencies
|
|
31
|
-
run: yarn
|
|
32
|
-
|
|
33
|
-
- name: Create Release Pull Request
|
|
34
|
-
id: changesets
|
|
35
|
-
uses: changesets/action@v1
|
|
36
|
-
with:
|
|
37
|
-
title: package-update/Version Packages
|
|
38
|
-
env:
|
|
39
|
-
GITHUB_TOKEN: ${{ secrets.ARBOR_AUTOMATION_ORG_GHA_TOKEN }}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
name: 'Auto-Merge Version Packages'
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
schedule:
|
|
5
|
-
# At 07:00 on every day-of-week from Monday through Friday. https://crontab.guru/#0_6_*_*_1-5
|
|
6
|
-
- cron: '0 7 * * 1-5'
|
|
7
|
-
jobs:
|
|
8
|
-
find-approve-merge-version-packages:
|
|
9
|
-
runs-on: ubuntu-latest
|
|
10
|
-
steps:
|
|
11
|
-
- name: Find Pull Request
|
|
12
|
-
uses: juliangruber/find-pull-request-action@v1
|
|
13
|
-
id: find-pull-request
|
|
14
|
-
with:
|
|
15
|
-
branch: changeset-release/main
|
|
16
|
-
repo: arbor-education/design-system.components
|
|
17
|
-
|
|
18
|
-
- name: Approve Pull Request
|
|
19
|
-
uses: juliangruber/approve-pull-request-action@v2
|
|
20
|
-
with:
|
|
21
|
-
github-token: ${{ secrets.ARBOR_AUTOMATION_SIS_GHA_TIMED_MERGE }}
|
|
22
|
-
number: ${{ steps.find-pull-request.outputs.number }}
|
|
23
|
-
repo: arbor-education/design-system.components
|
|
24
|
-
|
|
25
|
-
- name: Merge Pull Request
|
|
26
|
-
uses: juliangruber/merge-pull-request-action@v1
|
|
27
|
-
with:
|
|
28
|
-
github-token: ${{ secrets.ARBOR_AUTOMATION_SIS_GHA_TIMED_MERGE }}
|
|
29
|
-
number: ${{ steps.find-pull-request.outputs.number }}
|
|
30
|
-
method: squash # merge rebase
|
|
31
|
-
repo: arbor-education/design-system.components
|