@redsift/ds-mcp-server 12.5.2-muiv7 → 12.5.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.
- package/data/demos/patterns/_shared/StateDebugPanel.tsx +2 -2
- package/data/demos/patterns/_shared/columns.tsx +3 -3
- package/data/demos/patterns/_shared/defaults.ts +1 -1
- package/data/demos/patterns/_shared/filter-helpers.ts +1 -1
- package/data/demos/patterns/_shared/helpers.tsx +1 -1
- package/data/demos/patterns/_shared/server-logic.ts +1 -1
- package/data/demos/patterns/_shared/story-helpers.ts +106 -36
- package/data/demos/patterns/crossfiltered-datagrid-client-side/CrossfilteredDatagridClientSide.interaction.stories.tsx +4 -19
- package/data/demos/patterns/crossfiltered-datagrid-client-side/example.tsx +2 -2
- package/data/demos/patterns/crossfiltered-datagrid-server-side/CrossfilteredDatagridServerSide.interaction.stories.tsx +3 -3
- package/data/demos/patterns/crossfiltered-datagrid-server-side/example.tsx +5 -5
- package/data/demos/patterns/drilldowned-datagrid-client-side/DrilldownedDatagridClientSide.interaction.stories.tsx +2 -2
- package/data/demos/patterns/drilldowned-datagrid-client-side/example.tsx +1 -1
- package/data/demos/patterns/drilldowned-datagrid-server-side/DrilldownedDatagridServerSide.interaction.stories.tsx +2 -2
- package/data/demos/patterns/drilldowned-datagrid-server-side/example.tsx +5 -19
- package/data/demos/patterns/single-datagrid-client-side/SingleDatagridClientSide.interaction.stories.tsx +3 -3
- package/data/demos/patterns/single-datagrid-client-side/example.tsx +5 -5
- package/data/demos/patterns/single-datagrid-server-side/SingleDatagridServerSide.interaction.stories.tsx +3 -3
- package/data/demos/patterns/single-datagrid-server-side/example.tsx +5 -6
- package/data/demos/patterns/stateful-single-datagrid-client-side/StatefulSingleDatagridClientSide.interaction.stories.tsx +130 -3
- package/data/demos/patterns/stateful-single-datagrid-client-side/example.tsx +6 -6
- package/data/demos/patterns/stateful-single-datagrid-server-side/StatefulSingleDatagridServerSide.interaction.stories.tsx +136 -6
- package/data/demos/patterns/stateful-single-datagrid-server-side/example.tsx +6 -9
- package/data/demos/patterns/summary-dashboard/SummaryDashboard.interaction.stories.tsx +2 -2
- package/data/demos/patterns/tabbed-datagrid-client-side/TabbedDatagridClientSide.interaction.stories.tsx +2 -2
- package/data/demos/patterns/tabbed-datagrid-server-side/TabbedDatagridServerSide.interaction.stories.tsx +2 -2
- package/data/demos/patterns/tabbed-datagrid-server-side/example.tsx +1 -1
- package/data/docs/components/dashboard/Dashboard.json +2 -2
- package/data/docs/components/table/DataGrid.json +3 -30
- package/data/docs/components/table/StatefulDataGrid.json +3 -30
- package/data/docs/components-index.json +2 -2
- package/data/docs/components.json +10 -58
- package/data/docs/llms-full.txt +40 -46
- package/data/docs/llms.txt +6 -6
- package/data/docs/patterns-catalog.md +24 -25
- package/data/docs/patterns.json +4 -4
- package/data/metadata.json +2 -2
- package/data/patterns/crossfiltered-datagrid-server-side.mdx +1 -1
- package/data/patterns/drilldowned-datagrid-client-side.mdx +1 -1
- package/data/patterns/drilldowned-datagrid-server-side.mdx +1 -1
- package/data/patterns/single-datagrid-client-side.mdx +9 -9
- package/data/patterns/single-datagrid-server-side.mdx +4 -4
- package/data/patterns/stateful-single-datagrid-client-side.mdx +36 -20
- package/data/patterns/stateful-single-datagrid-server-side.mdx +46 -18
- package/data/patterns/tabbed-datagrid-server-side.mdx +1 -1
- package/package.json +2 -2
|
@@ -2,8 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
3
|
import { within, userEvent, waitFor } from '@storybook/testing-library';
|
|
4
4
|
import { expect } from '@storybook/jest';
|
|
5
|
-
import { GridFilterModel, useGridApiRef } from '@mui/x-data-grid-
|
|
6
|
-
import type { GridApiPro } from '@mui/x-data-grid-pro';
|
|
5
|
+
import { GridFilterModel, useGridApiRef } from '@mui/x-data-grid-premium';
|
|
7
6
|
|
|
8
7
|
import Example from './example';
|
|
9
8
|
import WithLoadingExample from './with-loading';
|
|
@@ -627,12 +626,94 @@ export const SortingInteraction: Story = {
|
|
|
627
626
|
},
|
|
628
627
|
};
|
|
629
628
|
|
|
629
|
+
// ---------------------------------------------------------------------------
|
|
630
|
+
// Row Grouping — set via apiRef, assert URL
|
|
631
|
+
// ---------------------------------------------------------------------------
|
|
632
|
+
|
|
633
|
+
let _rowGroupingRouter: ReturnType<typeof createMockRouter>;
|
|
634
|
+
let _rowGroupingApiRef: ReturnType<typeof useGridApiRef>;
|
|
635
|
+
|
|
636
|
+
export const RowGroupingInteraction: Story = {
|
|
637
|
+
render: () => {
|
|
638
|
+
_rowGroupingRouter = usePersistentMockRouter();
|
|
639
|
+
_rowGroupingApiRef = useGridApiRef();
|
|
640
|
+
return <Example useRouter={_rowGroupingRouter.useRouter} apiRef={_rowGroupingApiRef} />;
|
|
641
|
+
},
|
|
642
|
+
play: async ({ canvasElement, step }) => {
|
|
643
|
+
const canvas = within(canvasElement);
|
|
644
|
+
const { getSearch } = _rowGroupingRouter;
|
|
645
|
+
|
|
646
|
+
await step('Wait for grid to load', async () => {
|
|
647
|
+
await waitForGridToLoad(canvas);
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
await step('Set row grouping to Category', async () => {
|
|
651
|
+
_rowGroupingApiRef.current!.setRowGroupingModel(['Category']);
|
|
652
|
+
await waitFor(() => {
|
|
653
|
+
expect(getSearch()).toContain('_rowGrouping=Category');
|
|
654
|
+
});
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
await step('Assert sync', async () => {
|
|
658
|
+
await assertAllStatesInSync({ getSearch, checkRowGrouping: true });
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
await step('Clear row grouping', async () => {
|
|
662
|
+
_rowGroupingApiRef.current!.setRowGroupingModel([]);
|
|
663
|
+
await waitFor(() => {
|
|
664
|
+
expect(getSearch()).not.toContain('_rowGrouping');
|
|
665
|
+
});
|
|
666
|
+
});
|
|
667
|
+
},
|
|
668
|
+
};
|
|
669
|
+
|
|
670
|
+
// ---------------------------------------------------------------------------
|
|
671
|
+
// Aggregation — set via apiRef, assert URL
|
|
672
|
+
// ---------------------------------------------------------------------------
|
|
673
|
+
|
|
674
|
+
let _aggregationRouter: ReturnType<typeof createMockRouter>;
|
|
675
|
+
let _aggregationApiRef: ReturnType<typeof useGridApiRef>;
|
|
676
|
+
|
|
677
|
+
export const AggregationInteraction: Story = {
|
|
678
|
+
render: () => {
|
|
679
|
+
_aggregationRouter = usePersistentMockRouter();
|
|
680
|
+
_aggregationApiRef = useGridApiRef();
|
|
681
|
+
return <Example useRouter={_aggregationRouter.useRouter} apiRef={_aggregationApiRef} />;
|
|
682
|
+
},
|
|
683
|
+
play: async ({ canvasElement, step }) => {
|
|
684
|
+
const canvas = within(canvasElement);
|
|
685
|
+
const { getSearch } = _aggregationRouter;
|
|
686
|
+
|
|
687
|
+
await step('Wait for grid to load', async () => {
|
|
688
|
+
await waitForGridToLoad(canvas);
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
await step('Set aggregation Paid=sum', async () => {
|
|
692
|
+
_aggregationApiRef.current!.setAggregationModel({ Paid: 'sum' });
|
|
693
|
+
await waitFor(() => {
|
|
694
|
+
expect(getSearch()).toContain('_aggregation=Paid.sum');
|
|
695
|
+
});
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
await step('Assert sync', async () => {
|
|
699
|
+
await assertAllStatesInSync({ getSearch, checkAggregation: true });
|
|
700
|
+
});
|
|
701
|
+
|
|
702
|
+
await step('Clear aggregation', async () => {
|
|
703
|
+
_aggregationApiRef.current!.setAggregationModel({});
|
|
704
|
+
await waitFor(() => {
|
|
705
|
+
expect(getSearch()).not.toContain('_aggregation');
|
|
706
|
+
});
|
|
707
|
+
});
|
|
708
|
+
},
|
|
709
|
+
};
|
|
710
|
+
|
|
630
711
|
// ---------------------------------------------------------------------------
|
|
631
712
|
// Column Order — reorder via apiRef, assert URL
|
|
632
713
|
// ---------------------------------------------------------------------------
|
|
633
714
|
|
|
634
715
|
let _columnOrderRouter: ReturnType<typeof createMockRouter>;
|
|
635
|
-
let _columnOrderApiRef:
|
|
716
|
+
let _columnOrderApiRef: ReturnType<typeof useGridApiRef>;
|
|
636
717
|
|
|
637
718
|
export const ColumnOrderInteraction: Story = {
|
|
638
719
|
render: () => {
|
|
@@ -669,6 +750,52 @@ export const ColumnOrderInteraction: Story = {
|
|
|
669
750
|
},
|
|
670
751
|
};
|
|
671
752
|
|
|
753
|
+
// ---------------------------------------------------------------------------
|
|
754
|
+
// Pivot — activate via apiRef, assert URL
|
|
755
|
+
// ---------------------------------------------------------------------------
|
|
756
|
+
|
|
757
|
+
let _pivotRouter: ReturnType<typeof createMockRouter>;
|
|
758
|
+
let _pivotApiRef: ReturnType<typeof useGridApiRef>;
|
|
759
|
+
|
|
760
|
+
export const PivotInteraction: Story = {
|
|
761
|
+
render: () => {
|
|
762
|
+
_pivotRouter = usePersistentMockRouter();
|
|
763
|
+
_pivotApiRef = useGridApiRef();
|
|
764
|
+
return <Example useRouter={_pivotRouter.useRouter} apiRef={_pivotApiRef} />;
|
|
765
|
+
},
|
|
766
|
+
play: async ({ canvasElement, step }) => {
|
|
767
|
+
const canvas = within(canvasElement);
|
|
768
|
+
const { getSearch } = _pivotRouter;
|
|
769
|
+
|
|
770
|
+
await step('Wait for grid to load', async () => {
|
|
771
|
+
await waitForGridToLoad(canvas);
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
await step('Activate pivot with Category columns, Items rows, Paid sum values', async () => {
|
|
775
|
+
_pivotApiRef.current!.setPivotModel({
|
|
776
|
+
columns: [{ field: 'Category' }],
|
|
777
|
+
rows: [{ field: 'Items' }],
|
|
778
|
+
values: [{ field: 'Paid', aggFunc: 'sum' }],
|
|
779
|
+
});
|
|
780
|
+
_pivotApiRef.current!.setPivotActive(true);
|
|
781
|
+
await waitFor(() => {
|
|
782
|
+
expect(getSearch()).toContain('_pivot=');
|
|
783
|
+
});
|
|
784
|
+
});
|
|
785
|
+
|
|
786
|
+
await step('Assert pivot params in URL', async () => {
|
|
787
|
+
const search = getSearch();
|
|
788
|
+
expect(search).toContain('cols:Category');
|
|
789
|
+
expect(search).toContain('rows:Items');
|
|
790
|
+
expect(search).toContain('vals:Paid.sum');
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
await step('Assert sync', async () => {
|
|
794
|
+
await assertAllStatesInSync({ getSearch, checkPivot: true });
|
|
795
|
+
});
|
|
796
|
+
},
|
|
797
|
+
};
|
|
798
|
+
|
|
672
799
|
// ---------------------------------------------------------------------------
|
|
673
800
|
// State variants — with interaction assertions
|
|
674
801
|
// ---------------------------------------------------------------------------
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
|
-
import { StatefulDataGrid } from '@redsift/table';
|
|
2
|
+
import { StatefulDataGrid, EMPTY_ROW_SELECTION_MODEL, getSelectionCount } from '@redsift/table';
|
|
3
3
|
import { Flexbox } from '@redsift/design-system';
|
|
4
|
-
import { GridFilterModel, GridRowSelectionModel, useGridApiRef } from '@mui/x-data-grid-
|
|
5
|
-
import type {
|
|
4
|
+
import { GridFilterModel, GridRowSelectionModel, useGridApiRef } from '@mui/x-data-grid-premium';
|
|
5
|
+
import type { GridApiPremium } from '@mui/x-data-grid-premium';
|
|
6
6
|
import { rows } from '../_shared/data';
|
|
7
7
|
import { columns } from '../_shared/columns';
|
|
8
8
|
import { CustomToolbar, BulkActionBar } from '../_shared/helpers';
|
|
@@ -13,20 +13,20 @@ import { StateDebugPanel } from '../_shared/StateDebugPanel';
|
|
|
13
13
|
interface Props {
|
|
14
14
|
initialFilterModel?: GridFilterModel;
|
|
15
15
|
useRouter?: () => { pathname: string; search: string; historyReplace: (newSearch: string) => void };
|
|
16
|
-
apiRef?: React.MutableRefObject<
|
|
16
|
+
apiRef?: React.MutableRefObject<GridApiPremium | null>;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export default ({ initialFilterModel, useRouter = useRouterAdapter, apiRef: propsApiRef }: Props) => {
|
|
20
20
|
const internalApiRef = useGridApiRef();
|
|
21
21
|
const apiRef = propsApiRef ?? internalApiRef;
|
|
22
|
-
const [selectionModel, setSelectionModel] = useState<GridRowSelectionModel>(
|
|
22
|
+
const [selectionModel, setSelectionModel] = useState<GridRowSelectionModel>(EMPTY_ROW_SELECTION_MODEL);
|
|
23
23
|
|
|
24
24
|
return (
|
|
25
25
|
<div style={{ width: '100%' }}>
|
|
26
26
|
<StateDebugPanel apiRef={apiRef} useRouter={useRouter} localStorageVersion={1} />
|
|
27
27
|
<Flexbox flexDirection="column" gap="0px">
|
|
28
28
|
<BulkActionBar
|
|
29
|
-
count={selectionModel
|
|
29
|
+
count={getSelectionCount(selectionModel)}
|
|
30
30
|
onLog={() => console.log('Selected:', selectionModel)}
|
|
31
31
|
onDelete={() => console.log('Delete:', selectionModel)}
|
|
32
32
|
/>
|
|
@@ -2,8 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
3
|
import { within, userEvent, waitFor } from '@storybook/testing-library';
|
|
4
4
|
import { expect } from '@storybook/jest';
|
|
5
|
-
import { GridFilterModel, useGridApiRef } from '@mui/x-data-grid-
|
|
6
|
-
import type { GridApiPro } from '@mui/x-data-grid-pro';
|
|
5
|
+
import { GridFilterModel, useGridApiRef } from '@mui/x-data-grid-premium';
|
|
7
6
|
|
|
8
7
|
import Example from './example';
|
|
9
8
|
import WithLoadingExample from './with-loading';
|
|
@@ -387,9 +386,7 @@ export const SelectionPersistsAcrossPages: Story = {
|
|
|
387
386
|
await waitForServerResponse(canvas);
|
|
388
387
|
await assertDisplayedRowsText(canvasElement, '11–20 of 14,075');
|
|
389
388
|
await assertBulkActionBarVisible(canvasElement, 2);
|
|
390
|
-
|
|
391
|
-
// No page-2 rows are selected, so the header is unchecked (not indeterminate).
|
|
392
|
-
await assertHeaderCheckboxState(canvasElement, 'unchecked');
|
|
389
|
+
await assertHeaderCheckboxState(canvasElement, 'indeterminate');
|
|
393
390
|
await assertRowCheckboxChecked(canvasElement, 0, false);
|
|
394
391
|
await assertAllStatesInSync({ getSearch });
|
|
395
392
|
});
|
|
@@ -648,12 +645,98 @@ export const SortingInteraction: Story = {
|
|
|
648
645
|
},
|
|
649
646
|
};
|
|
650
647
|
|
|
648
|
+
// ---------------------------------------------------------------------------
|
|
649
|
+
// Row Grouping — set via apiRef, assert URL
|
|
650
|
+
// ---------------------------------------------------------------------------
|
|
651
|
+
|
|
652
|
+
let _rowGroupingRouter: ReturnType<typeof createMockRouter>;
|
|
653
|
+
let _rowGroupingApiRef: ReturnType<typeof useGridApiRef>;
|
|
654
|
+
|
|
655
|
+
export const RowGroupingInteraction: Story = {
|
|
656
|
+
render: () => {
|
|
657
|
+
_rowGroupingRouter = usePersistentMockRouter();
|
|
658
|
+
_rowGroupingApiRef = useGridApiRef();
|
|
659
|
+
return <Example useRouter={_rowGroupingRouter.useRouter} apiRef={_rowGroupingApiRef} />;
|
|
660
|
+
},
|
|
661
|
+
play: async ({ canvasElement, step }) => {
|
|
662
|
+
const canvas = within(canvasElement);
|
|
663
|
+
const { getSearch } = _rowGroupingRouter;
|
|
664
|
+
|
|
665
|
+
await step('Wait for grid to load', async () => {
|
|
666
|
+
await waitForGridToLoad(canvas);
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
await step('Set row grouping to Category', async () => {
|
|
670
|
+
_rowGroupingApiRef.current!.setRowGroupingModel(['Category']);
|
|
671
|
+
await waitForServerResponse(canvas);
|
|
672
|
+
await waitFor(() => {
|
|
673
|
+
expect(getSearch()).toContain('_rowGrouping=Category');
|
|
674
|
+
});
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
await step('Assert sync', async () => {
|
|
678
|
+
await assertAllStatesInSync({ getSearch, checkRowGrouping: true });
|
|
679
|
+
});
|
|
680
|
+
|
|
681
|
+
await step('Clear row grouping', async () => {
|
|
682
|
+
_rowGroupingApiRef.current!.setRowGroupingModel([]);
|
|
683
|
+
await waitForServerResponse(canvas);
|
|
684
|
+
await waitFor(() => {
|
|
685
|
+
expect(getSearch()).not.toContain('_rowGrouping');
|
|
686
|
+
});
|
|
687
|
+
});
|
|
688
|
+
},
|
|
689
|
+
};
|
|
690
|
+
|
|
691
|
+
// ---------------------------------------------------------------------------
|
|
692
|
+
// Aggregation — set via apiRef, assert URL
|
|
693
|
+
// ---------------------------------------------------------------------------
|
|
694
|
+
|
|
695
|
+
let _aggregationRouter: ReturnType<typeof createMockRouter>;
|
|
696
|
+
let _aggregationApiRef: ReturnType<typeof useGridApiRef>;
|
|
697
|
+
|
|
698
|
+
export const AggregationInteraction: Story = {
|
|
699
|
+
render: () => {
|
|
700
|
+
_aggregationRouter = usePersistentMockRouter();
|
|
701
|
+
_aggregationApiRef = useGridApiRef();
|
|
702
|
+
return <Example useRouter={_aggregationRouter.useRouter} apiRef={_aggregationApiRef} />;
|
|
703
|
+
},
|
|
704
|
+
play: async ({ canvasElement, step }) => {
|
|
705
|
+
const canvas = within(canvasElement);
|
|
706
|
+
const { getSearch } = _aggregationRouter;
|
|
707
|
+
|
|
708
|
+
await step('Wait for grid to load', async () => {
|
|
709
|
+
await waitForGridToLoad(canvas);
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
await step('Set aggregation Paid=sum', async () => {
|
|
713
|
+
_aggregationApiRef.current!.setAggregationModel({ Paid: 'sum' });
|
|
714
|
+
await waitForServerResponse(canvas);
|
|
715
|
+
await waitFor(() => {
|
|
716
|
+
expect(getSearch()).toContain('_aggregation=Paid.sum');
|
|
717
|
+
});
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
await step('Assert sync', async () => {
|
|
721
|
+
await assertAllStatesInSync({ getSearch, checkAggregation: true });
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
await step('Clear aggregation', async () => {
|
|
725
|
+
_aggregationApiRef.current!.setAggregationModel({});
|
|
726
|
+
await waitForServerResponse(canvas);
|
|
727
|
+
await waitFor(() => {
|
|
728
|
+
expect(getSearch()).not.toContain('_aggregation');
|
|
729
|
+
});
|
|
730
|
+
});
|
|
731
|
+
},
|
|
732
|
+
};
|
|
733
|
+
|
|
651
734
|
// ---------------------------------------------------------------------------
|
|
652
735
|
// Column Order — reorder via apiRef, assert URL
|
|
653
736
|
// ---------------------------------------------------------------------------
|
|
654
737
|
|
|
655
738
|
let _columnOrderRouter: ReturnType<typeof createMockRouter>;
|
|
656
|
-
let _columnOrderApiRef:
|
|
739
|
+
let _columnOrderApiRef: ReturnType<typeof useGridApiRef>;
|
|
657
740
|
|
|
658
741
|
export const ColumnOrderInteraction: Story = {
|
|
659
742
|
render: () => {
|
|
@@ -690,6 +773,53 @@ export const ColumnOrderInteraction: Story = {
|
|
|
690
773
|
},
|
|
691
774
|
};
|
|
692
775
|
|
|
776
|
+
// ---------------------------------------------------------------------------
|
|
777
|
+
// Pivot — activate via apiRef, assert URL
|
|
778
|
+
// ---------------------------------------------------------------------------
|
|
779
|
+
|
|
780
|
+
let _pivotRouter: ReturnType<typeof createMockRouter>;
|
|
781
|
+
let _pivotApiRef: ReturnType<typeof useGridApiRef>;
|
|
782
|
+
|
|
783
|
+
export const PivotInteraction: Story = {
|
|
784
|
+
render: () => {
|
|
785
|
+
_pivotRouter = usePersistentMockRouter();
|
|
786
|
+
_pivotApiRef = useGridApiRef();
|
|
787
|
+
return <Example useRouter={_pivotRouter.useRouter} apiRef={_pivotApiRef} />;
|
|
788
|
+
},
|
|
789
|
+
play: async ({ canvasElement, step }) => {
|
|
790
|
+
const canvas = within(canvasElement);
|
|
791
|
+
const { getSearch } = _pivotRouter;
|
|
792
|
+
|
|
793
|
+
await step('Wait for grid to load', async () => {
|
|
794
|
+
await waitForGridToLoad(canvas);
|
|
795
|
+
});
|
|
796
|
+
|
|
797
|
+
await step('Activate pivot with Category columns, Items rows, Paid sum values', async () => {
|
|
798
|
+
_pivotApiRef.current!.setPivotModel({
|
|
799
|
+
columns: [{ field: 'Category' }],
|
|
800
|
+
rows: [{ field: 'Items' }],
|
|
801
|
+
values: [{ field: 'Paid', aggFunc: 'sum' }],
|
|
802
|
+
});
|
|
803
|
+
_pivotApiRef.current!.setPivotActive(true);
|
|
804
|
+
await waitForServerResponse(canvas);
|
|
805
|
+
await waitFor(() => {
|
|
806
|
+
expect(getSearch()).toContain('_pivot=');
|
|
807
|
+
});
|
|
808
|
+
});
|
|
809
|
+
|
|
810
|
+
await step('Assert pivot params in URL', async () => {
|
|
811
|
+
const search = getSearch();
|
|
812
|
+
expect(search).toContain('cols:Category');
|
|
813
|
+
expect(search).toContain('rows:Items');
|
|
814
|
+
expect(search).toContain('vals:Paid.sum');
|
|
815
|
+
});
|
|
816
|
+
|
|
817
|
+
await step('Assert sync', async () => {
|
|
818
|
+
await assertAllStatesInSync({ getSearch, checkPivot: true });
|
|
819
|
+
});
|
|
820
|
+
},
|
|
821
|
+
};
|
|
822
|
+
|
|
693
823
|
// ---------------------------------------------------------------------------
|
|
694
824
|
// State variants — with interaction assertions
|
|
695
825
|
// ---------------------------------------------------------------------------
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { StatefulDataGrid } from '@redsift/table';
|
|
2
|
+
import { StatefulDataGrid, EMPTY_ROW_SELECTION_MODEL, getSelectionCount } from '@redsift/table';
|
|
3
3
|
import { Flexbox } from '@redsift/design-system';
|
|
4
|
-
import { GridFilterModel, GridRowSelectionModel, GridSortModel, useGridApiRef } from '@mui/x-data-grid-
|
|
5
|
-
import type {
|
|
4
|
+
import { GridFilterModel, GridRowSelectionModel, GridSortModel, useGridApiRef } from '@mui/x-data-grid-premium';
|
|
5
|
+
import type { GridApiPremium } from '@mui/x-data-grid-premium';
|
|
6
6
|
import { Row } from '../_shared/data';
|
|
7
7
|
import { columns } from '../_shared/columns';
|
|
8
8
|
import { fetchBakeryData } from '../_shared/api-client';
|
|
@@ -14,7 +14,7 @@ import { StateDebugPanel } from '../_shared/StateDebugPanel';
|
|
|
14
14
|
interface Props {
|
|
15
15
|
initialFilterModel?: GridFilterModel;
|
|
16
16
|
useRouter?: () => { pathname: string; search: string; historyReplace: (newSearch: string) => void };
|
|
17
|
-
apiRef?: React.MutableRefObject<
|
|
17
|
+
apiRef?: React.MutableRefObject<GridApiPremium | null>;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export default ({ initialFilterModel, useRouter = useRouterAdapter, apiRef: propsApiRef }: Props) => {
|
|
@@ -23,7 +23,7 @@ export default ({ initialFilterModel, useRouter = useRouterAdapter, apiRef: prop
|
|
|
23
23
|
const [rows, setRows] = useState<Row[]>([]);
|
|
24
24
|
const [totalRows, setTotalRows] = useState(0);
|
|
25
25
|
const [loading, setLoading] = useState(true);
|
|
26
|
-
const [selectionModel, setSelectionModel] = useState<GridRowSelectionModel>(
|
|
26
|
+
const [selectionModel, setSelectionModel] = useState<GridRowSelectionModel>(EMPTY_ROW_SELECTION_MODEL);
|
|
27
27
|
|
|
28
28
|
// Refs track the latest model values so fetchData() always reads current state.
|
|
29
29
|
// StatefulDataGrid manages filter/sort/pagination internally — we use callbacks
|
|
@@ -58,7 +58,7 @@ export default ({ initialFilterModel, useRouter = useRouterAdapter, apiRef: prop
|
|
|
58
58
|
<StateDebugPanel apiRef={apiRef} useRouter={useRouter} localStorageVersion={1} />
|
|
59
59
|
<Flexbox flexDirection="column" gap="0px">
|
|
60
60
|
<BulkActionBar
|
|
61
|
-
count={selectionModel
|
|
61
|
+
count={getSelectionCount(selectionModel)}
|
|
62
62
|
onLog={() => console.log('Selected:', selectionModel)}
|
|
63
63
|
onDelete={() => console.log('Delete:', selectionModel)}
|
|
64
64
|
/>
|
|
@@ -94,9 +94,6 @@ export default ({ initialFilterModel, useRouter = useRouterAdapter, apiRef: prop
|
|
|
94
94
|
fetchData();
|
|
95
95
|
}}
|
|
96
96
|
onPaginationModelChange={(model) => {
|
|
97
|
-
if (model.pageSize !== pageSizeRef.current) {
|
|
98
|
-
setRows([]);
|
|
99
|
-
}
|
|
100
97
|
pageRef.current = model.page;
|
|
101
98
|
pageSizeRef.current = model.pageSize;
|
|
102
99
|
fetchData();
|
|
@@ -24,9 +24,9 @@ import {
|
|
|
24
24
|
} from '../_shared/story-helpers';
|
|
25
25
|
import { AGG_CATEGORY, AGG_ALLERGENS, AGG_INSTOCK } from '../_shared/expected-values';
|
|
26
26
|
|
|
27
|
-
const meta: Meta
|
|
27
|
+
const meta: Meta = {
|
|
28
28
|
title: 'Patterns/Summary Dashboard',
|
|
29
|
-
component: Example,
|
|
29
|
+
component: Example as any,
|
|
30
30
|
};
|
|
31
31
|
export default meta;
|
|
32
32
|
type Story = StoryObj;
|
|
@@ -17,9 +17,9 @@ import {
|
|
|
17
17
|
} from '../_shared/story-helpers';
|
|
18
18
|
import { TOTAL, CATEGORY_BAKERY, CATEGORY_BEVERAGE, CATEGORY_PASTRY, CATEGORY_OTHER } from '../_shared/expected-values';
|
|
19
19
|
|
|
20
|
-
const meta: Meta
|
|
20
|
+
const meta: Meta = {
|
|
21
21
|
title: 'Patterns/Tabbed Datagrid (Client)',
|
|
22
|
-
component: Example,
|
|
22
|
+
component: Example as any,
|
|
23
23
|
};
|
|
24
24
|
export default meta;
|
|
25
25
|
type Story = StoryObj;
|
|
@@ -19,9 +19,9 @@ import {
|
|
|
19
19
|
} from '../_shared/story-helpers';
|
|
20
20
|
import { TOTAL, CATEGORY_BAKERY, CATEGORY_BEVERAGE, CATEGORY_PASTRY, CATEGORY_OTHER } from '../_shared/expected-values';
|
|
21
21
|
|
|
22
|
-
const meta: Meta
|
|
22
|
+
const meta: Meta = {
|
|
23
23
|
title: 'Patterns/Tabbed Datagrid (Server)',
|
|
24
|
-
component: Example,
|
|
24
|
+
component: Example as any,
|
|
25
25
|
parameters: {
|
|
26
26
|
msw: { handlers: bakeryHandlers },
|
|
27
27
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { DataGrid } from '@redsift/table';
|
|
3
3
|
import { Flexbox, Pill, Number, Text, Tabs, Tab } from '@redsift/design-system';
|
|
4
|
-
import { GridFilterModel, GridSortModel } from '@mui/x-data-grid-
|
|
4
|
+
import { GridFilterModel, GridSortModel } from '@mui/x-data-grid-premium';
|
|
5
5
|
import { Row } from '../_shared/data';
|
|
6
6
|
import { columns, CATEGORY_OPTIONS } from '../_shared/columns';
|
|
7
7
|
import { fetchBakeryData } from '../_shared/api-client';
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"name": "dataGridApiRef",
|
|
17
|
-
"description": "Datagrid API Ref.",
|
|
18
|
-
"type": "MutableRefObject<
|
|
17
|
+
"description": "Datagrid API Ref. MUI v8: can be null initially.",
|
|
18
|
+
"type": "MutableRefObject<GridApiPremium | null>",
|
|
19
19
|
"required": false,
|
|
20
20
|
"defaultValue": null,
|
|
21
21
|
"category": "props"
|
|
@@ -71,22 +71,6 @@
|
|
|
71
71
|
"defaultValue": null,
|
|
72
72
|
"category": "props"
|
|
73
73
|
},
|
|
74
|
-
{
|
|
75
|
-
"name": "className",
|
|
76
|
-
"description": "",
|
|
77
|
-
"type": "string",
|
|
78
|
-
"required": false,
|
|
79
|
-
"defaultValue": null,
|
|
80
|
-
"category": "props"
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
"name": "style",
|
|
84
|
-
"description": "",
|
|
85
|
-
"type": "CSSProperties",
|
|
86
|
-
"required": false,
|
|
87
|
-
"defaultValue": null,
|
|
88
|
-
"category": "props"
|
|
89
|
-
},
|
|
90
74
|
{
|
|
91
75
|
"name": "getTreeDataPath",
|
|
92
76
|
"description": "Determines the path of a row in the tree data.\nFor instance, a row with the path [\"A\", \"B\"] is the child of the row with the path [\"A\"].\nNote that all paths must contain at least one element.\n@template R\n@param row The row from which we want the path.\n@returns The path to the row.",
|
|
@@ -96,20 +80,9 @@
|
|
|
96
80
|
"category": "props"
|
|
97
81
|
},
|
|
98
82
|
{
|
|
99
|
-
"name": "
|
|
100
|
-
"description": "",
|
|
101
|
-
"type": [
|
|
102
|
-
"null",
|
|
103
|
-
"GridDataSourceCache"
|
|
104
|
-
],
|
|
105
|
-
"required": false,
|
|
106
|
-
"defaultValue": null,
|
|
107
|
-
"category": "props"
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
"name": "unstable_onDataSourceError",
|
|
111
|
-
"description": "",
|
|
112
|
-
"type": "(error: Error, params: GridGetRowsParams) => void",
|
|
83
|
+
"name": "setTreeDataPath",
|
|
84
|
+
"description": "Updates the tree path in a row model.\nUsed when reordering rows across different parents in tree data.\n@template R\n@param path The new path for the row.\n@param row The row model to update.\n@returns The updated row model with the new path.",
|
|
85
|
+
"type": "(path: string[], row: any) => any",
|
|
113
86
|
"required": false,
|
|
114
87
|
"defaultValue": null,
|
|
115
88
|
"category": "props"
|
|
@@ -95,22 +95,6 @@
|
|
|
95
95
|
"defaultValue": null,
|
|
96
96
|
"category": "props"
|
|
97
97
|
},
|
|
98
|
-
{
|
|
99
|
-
"name": "className",
|
|
100
|
-
"description": "",
|
|
101
|
-
"type": "string",
|
|
102
|
-
"required": false,
|
|
103
|
-
"defaultValue": null,
|
|
104
|
-
"category": "props"
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
"name": "style",
|
|
108
|
-
"description": "",
|
|
109
|
-
"type": "CSSProperties",
|
|
110
|
-
"required": false,
|
|
111
|
-
"defaultValue": null,
|
|
112
|
-
"category": "props"
|
|
113
|
-
},
|
|
114
98
|
{
|
|
115
99
|
"name": "getTreeDataPath",
|
|
116
100
|
"description": "Determines the path of a row in the tree data.\nFor instance, a row with the path [\"A\", \"B\"] is the child of the row with the path [\"A\"].\nNote that all paths must contain at least one element.\n@template R\n@param row The row from which we want the path.\n@returns The path to the row.",
|
|
@@ -120,20 +104,9 @@
|
|
|
120
104
|
"category": "props"
|
|
121
105
|
},
|
|
122
106
|
{
|
|
123
|
-
"name": "
|
|
124
|
-
"description": "",
|
|
125
|
-
"type": [
|
|
126
|
-
"null",
|
|
127
|
-
"GridDataSourceCache"
|
|
128
|
-
],
|
|
129
|
-
"required": false,
|
|
130
|
-
"defaultValue": null,
|
|
131
|
-
"category": "props"
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
"name": "unstable_onDataSourceError",
|
|
135
|
-
"description": "",
|
|
136
|
-
"type": "(error: Error, params: GridGetRowsParams) => void",
|
|
107
|
+
"name": "setTreeDataPath",
|
|
108
|
+
"description": "Updates the tree path in a row model.\nUsed when reordering rows across different parents in tree data.\n@template R\n@param path The new path for the row.\n@param row The row model to update.\n@returns The updated row model with the new path.",
|
|
109
|
+
"type": "(path: string[], row: any) => any",
|
|
137
110
|
"required": false,
|
|
138
111
|
"defaultValue": null,
|
|
139
112
|
"category": "props"
|
|
@@ -1011,7 +1011,7 @@
|
|
|
1011
1011
|
"name": "DataGrid",
|
|
1012
1012
|
"package": "@redsift/table",
|
|
1013
1013
|
"description": "DataGrid displays tabular data with sorting, filtering, pagination, and row selection.",
|
|
1014
|
-
"propsCount":
|
|
1014
|
+
"propsCount": 9,
|
|
1015
1015
|
"hasExamples": false
|
|
1016
1016
|
},
|
|
1017
1017
|
{
|
|
@@ -1039,7 +1039,7 @@
|
|
|
1039
1039
|
"name": "StatefulDataGrid",
|
|
1040
1040
|
"package": "@redsift/table",
|
|
1041
1041
|
"description": "StatefulDataGrid extends DataGrid with automatic state persistence to localStorage.",
|
|
1042
|
-
"propsCount":
|
|
1042
|
+
"propsCount": 12,
|
|
1043
1043
|
"hasExamples": false
|
|
1044
1044
|
},
|
|
1045
1045
|
{
|