@coveord/plasma-mantine 59.7.0 → 59.7.1

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 (32) hide show
  1. package/.turbo/turbo-build.log +3 -3
  2. package/.turbo/turbo-test.log +99 -95
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/cjs/components/Table/Table.d.ts +46 -0
  5. package/dist/cjs/components/Table/Table.d.ts.map +1 -1
  6. package/dist/cjs/components/Table/Table.js +48 -17
  7. package/dist/cjs/components/Table/Table.js.map +1 -1
  8. package/dist/cjs/theme/Plasmantine.d.ts.map +1 -1
  9. package/dist/cjs/theme/Plasmantine.js +24 -4
  10. package/dist/cjs/theme/Plasmantine.js.map +1 -1
  11. package/dist/cjs/theme/Theme.d.ts.map +1 -1
  12. package/dist/cjs/theme/Theme.js +1 -9
  13. package/dist/cjs/theme/Theme.js.map +1 -1
  14. package/dist/esm/components/Table/Table.d.ts +46 -0
  15. package/dist/esm/components/Table/Table.d.ts.map +1 -1
  16. package/dist/esm/components/Table/Table.js +48 -17
  17. package/dist/esm/components/Table/Table.js.map +1 -1
  18. package/dist/esm/theme/Plasmantine.d.ts.map +1 -1
  19. package/dist/esm/theme/Plasmantine.js +22 -3
  20. package/dist/esm/theme/Plasmantine.js.map +1 -1
  21. package/dist/esm/theme/Theme.d.ts.map +1 -1
  22. package/dist/esm/theme/Theme.js +1 -9
  23. package/dist/esm/theme/Theme.js.map +1 -1
  24. package/package.json +3 -3
  25. package/src/__tests__/Utils.tsx +1 -17
  26. package/src/components/DateRangePicker/__tests__/DateRangePicker.spec.tsx +2 -2
  27. package/src/components/DateRangePicker/__tests__/DateRangePickerPopoverCalendar.spec.tsx +2 -2
  28. package/src/components/Table/Table.tsx +54 -6
  29. package/src/components/Table/__tests__/Table.spec.tsx +36 -0
  30. package/src/theme/Plasmantine.tsx +21 -3
  31. package/src/theme/Theme.tsx +0 -4
  32. package/src/theme/__tests__/Plasmantine.spec.tsx +48 -0
@@ -2,27 +2,11 @@ import {render, RenderOptions, RenderResult} from '@testing-library/react';
2
2
  import userEvent from '@testing-library/user-event';
3
3
  import {FunctionComponent, PropsWithChildren, ReactElement} from 'react';
4
4
 
5
- import {Combobox, createTheme, Popover} from '@mantine/core';
6
5
  import {Plasmantine} from '../theme/Plasmantine.js';
7
6
 
8
- const testTheme = createTheme({
9
- components: {
10
- Popover: Popover.extend({
11
- defaultProps: {
12
- middlewares: {inline: true},
13
- },
14
- }),
15
- Combobox: Combobox.extend({
16
- defaultProps: {
17
- middlewares: {inline: true},
18
- },
19
- }),
20
- },
21
- });
22
-
23
7
  const customRender = (ui: ReactElement, options?: Omit<RenderOptions, 'queries'>): RenderResult => {
24
8
  const TestWrapper: FunctionComponent<PropsWithChildren> = ({children}) => (
25
- <Plasmantine withCssVariables={false} theme={testTheme}>
9
+ <Plasmantine withCssVariables={false} env="test">
26
10
  {children}
27
11
  </Plasmantine>
28
12
  );
@@ -70,7 +70,7 @@ describe('DateRangePicker', () => {
70
70
 
71
71
  expect(onChange).toHaveBeenCalledTimes(1);
72
72
  expect(onChange).toHaveBeenCalledWith(['2022-01-02T00:00:00.000Z', '2022-01-08T23:59:59.999Z']);
73
- expect(screen.queryByRole('dialog')).not.toBeVisible();
73
+ expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
74
74
  });
75
75
 
76
76
  it('closes popover when Cancel is clicked', async () => {
@@ -81,7 +81,7 @@ describe('DateRangePicker', () => {
81
81
  await screen.findByRole('dialog');
82
82
  await user.click(screen.getByRole('button', {name: 'Cancel'}));
83
83
 
84
- await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeVisible());
84
+ await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument());
85
85
  });
86
86
 
87
87
  it('calls onCancel when Cancel button is clicked', async () => {
@@ -55,8 +55,8 @@ describe('DateRangePickerPopoverCalendar', () => {
55
55
  await user.click(screen.getByRole('button', {name: '14 February 2022'}));
56
56
 
57
57
  // hides the calendar when the second date is clicked
58
- await waitFor(() => expect(screen.queryByRole('button', {name: '8 January 2022'})).not.toBeVisible());
59
- expect(screen.queryByRole('button', {name: '8 February 2022'})).not.toBeVisible();
58
+ await waitFor(() => expect(screen.queryByRole('button', {name: '8 January 2022'})).not.toBeInTheDocument());
59
+ expect(screen.queryByRole('button', {name: '8 February 2022'})).not.toBeInTheDocument();
60
60
 
61
61
  expect(screen.getByTestId('json')).toHaveTextContent('["2022-01-08T00:00:00.000Z","2022-02-14T00:00:00.000Z"]');
62
62
 
@@ -252,12 +252,14 @@ export const Table = <T,>(props: TableProps<T> & {ref?: ForwardedRef<HTMLDivElem
252
252
  </th>
253
253
  </tr>
254
254
  ) : null}
255
- <Layout.Header
256
- getRowExpandedContent={getRowExpandedContent}
257
- getRowAttributes={getRowAttributes}
258
- loading={loading}
259
- {...layoutProps}
260
- />
255
+ {hasRows || loading ? (
256
+ <Layout.Header
257
+ getRowExpandedContent={getRowExpandedContent}
258
+ getRowAttributes={getRowAttributes}
259
+ loading={loading}
260
+ {...layoutProps}
261
+ />
262
+ ) : null}
261
263
  </thead>
262
264
  <tbody {...getStyles('body')}>
263
265
  {hasRows ? (
@@ -297,20 +299,66 @@ export const TableComponentsOrder = {
297
299
  LayoutControl: 1,
298
300
  };
299
301
 
302
+ /**
303
+ * Generic column to use when your table needs an accordion (collapsible rows, but only one open at a time).
304
+ */
300
305
  Table.AccordionColumn = TableAccordionColumn;
306
+ /**
307
+ * Generic column to use when your table needs actions on rows
308
+ */
301
309
  Table.ActionsColumn = TableActionsColumn;
310
+ /**
311
+ * An action to display when a row is selected in the table. Can be displayed as a primary action or menu item.
312
+ */
302
313
  Table.ActionItem = TableActionItem;
314
+ /**
315
+ * Generic column to use when your table needs collapsible rows
316
+ */
303
317
  Table.CollapsibleColumn = TableCollapsibleColumn;
318
+ /**
319
+ * A date range picker integrated with the table store that resets pagination on change.
320
+ */
304
321
  Table.DateRangePicker = TableDateRangePicker;
322
+ /**
323
+ * A search input that filters table rows by matching against any field.
324
+ * The filter value is debounced and resets pagination to the first page on change.
325
+ */
305
326
  Table.Filter = TableFilter;
327
+ /**
328
+ * Container for elements displayed below the table body, typically pagination and per-page controls.
329
+ */
306
330
  Table.Footer = TableFooter;
331
+ /**
332
+ * Container for elements displayed above the table body such as filters, predicates, and actions.
333
+ */
307
334
  Table.Header = TableHeader;
335
+ /**
336
+ * Displays the time of the last data update, automatically refreshing when table data changes.
337
+ */
308
338
  Table.LastUpdated = TableLastUpdated;
339
+ /**
340
+ * Available table layout configurations (e.g., Rows, Cards).
341
+ */
309
342
  Table.Layouts = TableLayouts;
343
+ /**
344
+ * Skeleton overlay displayed while the table data is loading.
345
+ */
310
346
  Table.Loading = TableLoading;
347
+ /**
348
+ * Container displayed when the table has no data to show.
349
+ */
311
350
  Table.NoData = TableNoData;
351
+ /**
352
+ * Page navigation control that syncs with the table store and scrolls to the table on page change.
353
+ */
312
354
  Table.Pagination = TablePagination;
355
+ /**
356
+ * Control allowing users to choose how many results are displayed per page.
357
+ */
313
358
  Table.PerPage = TablePerPage;
359
+ /**
360
+ * A dropdown that filters table data by a predefined set of values and resets pagination on change.
361
+ */
314
362
  Table.Predicate = TablePredicate;
315
363
 
316
364
  Table.extend = identity as CustomComponentThemeExtend<PlasmaTableFactory>;
@@ -39,6 +39,25 @@ describe('Table', () => {
39
39
  expect(screen.getByTestId('empty-state')).toBeVisible();
40
40
  });
41
41
 
42
+ it('hides column headers when filtered, not loading, and showing no data', () => {
43
+ const Fixture = () => {
44
+ const store = useTable<RowData>({initialState: {globalFilter: 'something'}});
45
+ return (
46
+ <Table store={store} data={[]} columns={columns}>
47
+ <Table.Header data-testid="table-header">header</Table.Header>
48
+ <Table.NoData>
49
+ <EmptyState isFiltered={store.isFiltered} />
50
+ </Table.NoData>
51
+ </Table>
52
+ );
53
+ };
54
+ render(<Fixture />);
55
+
56
+ expect(screen.queryByRole('columnheader', {name: /firstName/i})).not.toBeInTheDocument();
57
+ expect(screen.queryByRole('columnheader', {name: /lastName/i})).not.toBeInTheDocument();
58
+ expect(screen.getByTestId('filtered-empty-state')).toBeVisible();
59
+ });
60
+
42
61
  it('does not hide the footer and header if the table is filtered', () => {
43
62
  const Fixture = () => {
44
63
  const store = useTable<RowData>({initialState: {globalFilter: 'something'}});
@@ -73,6 +92,23 @@ describe('Table', () => {
73
92
  expect(screen.getByRole('table')).not.toHaveAttribute('data-loading');
74
93
  });
75
94
 
95
+ it('keeps column headers visible when loading with no rows', () => {
96
+ const Fixture = () => {
97
+ const store = useTable<RowData>({initialState: {globalFilter: 'something'}});
98
+ return (
99
+ <Table store={store} loading data={[]} columns={columns}>
100
+ <Table.NoData>
101
+ <EmptyState isFiltered={store.isFiltered} />
102
+ </Table.NoData>
103
+ </Table>
104
+ );
105
+ };
106
+ render(<Fixture />);
107
+
108
+ expect(screen.getByRole('columnheader', {name: /firstName/i})).toBeVisible();
109
+ expect(screen.getByRole('columnheader', {name: /lastName/i})).toBeVisible();
110
+ });
111
+
76
112
  it('shows a loading animation over the no data children (filtered)', () => {
77
113
  const Fixture = () => {
78
114
  const store = useTable<RowData>({initialState: {globalFilter: 'something'}});
@@ -1,22 +1,40 @@
1
1
  import '../styles/global.css';
2
2
 
3
- import {MantineProvider, MantineProviderProps, mergeThemeOverrides} from '@mantine/core';
3
+ import {
4
+ Combobox,
5
+ createTheme,
6
+ MantineProvider,
7
+ MantineProviderProps,
8
+ mergeThemeOverrides,
9
+ Popover,
10
+ } from '@mantine/core';
4
11
  import {FunctionComponent} from 'react';
5
12
  import {mergeCSSVariablesResolvers} from './mergeCSSVariablesResolvers.js';
6
13
  import {plasmaCSSVariablesResolver} from './plasmaCSSVariablesResolver.js';
7
14
  import {plasmaTheme} from './Theme.js';
8
15
 
16
+ const testThemeOverride = createTheme({
17
+ components: {
18
+ Combobox: Combobox.extend({defaultProps: {middlewares: {inline: true}}}),
19
+ Popover: Popover.extend({defaultProps: {middlewares: {inline: true}}}),
20
+ },
21
+ });
22
+
9
23
  export const Plasmantine: FunctionComponent<MantineProviderProps> = ({
10
24
  children,
11
25
  theme: externalTheme,
12
26
  cssVariablesResolver: externalCSSVariablesResolver,
27
+ env,
13
28
  ...others
14
29
  }) => {
15
- const theme = mergeThemeOverrides(plasmaTheme, externalTheme);
30
+ const theme =
31
+ env === 'test'
32
+ ? mergeThemeOverrides(plasmaTheme, testThemeOverride, externalTheme)
33
+ : mergeThemeOverrides(plasmaTheme, externalTheme);
16
34
  const cssVariablesResolver = mergeCSSVariablesResolvers(plasmaCSSVariablesResolver, externalCSSVariablesResolver);
17
35
 
18
36
  return (
19
- <MantineProvider theme={theme} cssVariablesResolver={cssVariablesResolver} {...others}>
37
+ <MantineProvider theme={theme} cssVariablesResolver={cssVariablesResolver} env={env} {...others}>
20
38
  {children}
21
39
  </MantineProvider>
22
40
  );
@@ -284,9 +284,6 @@ export const plasmaTheme: MantineThemeOverride = createTheme({
284
284
  }),
285
285
  Combobox: Combobox.extend({
286
286
  classNames: ComboboxClasses,
287
- defaultProps: {
288
- middlewares: {inline: true},
289
- },
290
287
  }),
291
288
  ComboboxChevron: ComboboxChevron.extend({
292
289
  defaultProps: {
@@ -443,7 +440,6 @@ export const plasmaTheme: MantineThemeOverride = createTheme({
443
440
  Popover: Popover.extend({
444
441
  classNames: PopoverClasses,
445
442
  defaultProps: {
446
- middlewares: {inline: true},
447
443
  position: 'bottom-start',
448
444
  },
449
445
  }),
@@ -0,0 +1,48 @@
1
+ import {MantineThemeOverride, useMantineTheme} from '@mantine/core';
2
+ import {render} from '@testing-library/react';
3
+ import {describe, expect, it} from 'vitest';
4
+
5
+ import {plasmaTheme} from '../Theme.js';
6
+ import {Plasmantine} from '../Plasmantine.js';
7
+
8
+ describe('Plasmantine', () => {
9
+ it('does not include inline middlewares in the base theme', () => {
10
+ const components = (plasmaTheme as MantineThemeOverride).components;
11
+ expect(components?.Combobox?.defaultProps?.middlewares).toBeUndefined();
12
+ expect(components?.Popover?.defaultProps?.middlewares).toBeUndefined();
13
+ });
14
+
15
+ it('injects inline middlewares when env="test"', () => {
16
+ let theme: ReturnType<typeof useMantineTheme> | undefined;
17
+ const Spy = () => {
18
+ theme = useMantineTheme();
19
+ return null;
20
+ };
21
+
22
+ render(
23
+ <Plasmantine withCssVariables={false} env="test">
24
+ <Spy />
25
+ </Plasmantine>,
26
+ );
27
+
28
+ expect(theme!.components?.Combobox?.defaultProps?.middlewares).toEqual({inline: true});
29
+ expect(theme!.components?.Popover?.defaultProps?.middlewares).toEqual({inline: true});
30
+ });
31
+
32
+ it('does not inject inline middlewares without env="test"', () => {
33
+ let theme: ReturnType<typeof useMantineTheme> | undefined;
34
+ const Spy = () => {
35
+ theme = useMantineTheme();
36
+ return null;
37
+ };
38
+
39
+ render(
40
+ <Plasmantine withCssVariables={false}>
41
+ <Spy />
42
+ </Plasmantine>,
43
+ );
44
+
45
+ expect(theme!.components?.Combobox?.defaultProps?.middlewares).toBeUndefined();
46
+ expect(theme!.components?.Popover?.defaultProps?.middlewares).toBeUndefined();
47
+ });
48
+ });