@redsift/ds-mcp-server 12.5.13-muiv6 → 12.5.13
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 +12 -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 -22
- package/data/demos/patterns/crossfiltered-datagrid-client-side/CrossfilteredDatagridClientSide.interaction.stories.tsx +1 -18
- package/data/demos/patterns/crossfiltered-datagrid-server-side/CrossfilteredDatagridServerSide.interaction.stories.tsx +1 -1
- package/data/demos/patterns/crossfiltered-datagrid-server-side/example.tsx +10 -10
- package/data/demos/patterns/drilldowned-datagrid-client-side/example.tsx +1 -1
- package/data/demos/patterns/drilldowned-datagrid-server-side/example.tsx +1 -1
- package/data/demos/patterns/single-datagrid-client-side/SingleDatagridClientSide.interaction.stories.tsx +1 -1
- package/data/demos/patterns/single-datagrid-client-side/example.tsx +4 -4
- package/data/demos/patterns/single-datagrid-server-side/SingleDatagridServerSide.interaction.stories.tsx +1 -1
- package/data/demos/patterns/single-datagrid-server-side/example.tsx +4 -4
- package/data/demos/patterns/stateful-single-datagrid-client-side/StatefulSingleDatagridClientSide.interaction.stories.tsx +129 -1
- package/data/demos/patterns/stateful-single-datagrid-client-side/example.tsx +6 -5
- package/data/demos/patterns/stateful-single-datagrid-server-side/StatefulSingleDatagridServerSide.interaction.stories.tsx +134 -1
- package/data/demos/patterns/stateful-single-datagrid-server-side/example.tsx +6 -5
- 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/products/DmarcSummaryBoxes.json +1 -1
- package/data/docs/components/table/DataGrid.json +6 -6
- package/data/docs/components/table/GridToolbarFilterSemanticField.json +1 -1
- package/data/docs/components/table/StatefulDataGrid.json +6 -6
- package/data/docs/components/table/Toolbar.json +8 -2
- package/data/docs/components/table-pro/ControlledPagination.json +9 -0
- package/data/docs/components/table-pro/DataGrid.json +114 -0
- package/data/docs/components/table-pro/GridToolbarFilterSemanticField.json +69 -0
- package/data/docs/components/table-pro/ServerSideControlledPagination.json +9 -0
- package/data/docs/components/table-pro/StatefulDataGrid.json +135 -0
- package/data/docs/components/table-pro/TextCell.json +118 -0
- package/data/docs/components/table-pro/Toolbar.json +151 -0
- package/data/docs/components/table-pro/ToolbarWrapper.json +9 -0
- package/data/docs/components-index.json +69 -0
- package/data/docs/components.json +626 -21
- package/data/docs/llms-full.txt +209 -45
- package/data/docs/llms.txt +17 -5
- 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 +7 -7
- package/data/patterns/single-datagrid-server-side.mdx +4 -4
- package/data/patterns/stateful-single-datagrid-client-side.mdx +36 -21
- 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,7 +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-
|
|
5
|
+
import { GridFilterModel, useGridApiRef } from '@mui/x-data-grid-premium';
|
|
6
6
|
|
|
7
7
|
import Example from './example';
|
|
8
8
|
import WithLoadingExample from './with-loading';
|
|
@@ -626,6 +626,88 @@ export const SortingInteraction: Story = {
|
|
|
626
626
|
},
|
|
627
627
|
};
|
|
628
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
|
+
|
|
629
711
|
// ---------------------------------------------------------------------------
|
|
630
712
|
// Column Order — reorder via apiRef, assert URL
|
|
631
713
|
// ---------------------------------------------------------------------------
|
|
@@ -668,6 +750,52 @@ export const ColumnOrderInteraction: Story = {
|
|
|
668
750
|
},
|
|
669
751
|
};
|
|
670
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
|
+
|
|
671
799
|
// ---------------------------------------------------------------------------
|
|
672
800
|
// State variants — with interaction assertions
|
|
673
801
|
// ---------------------------------------------------------------------------
|
|
@@ -1,7 +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,
|
|
4
|
+
import { GridFilterModel, GridRowSelectionModel, useGridApiRef } from '@mui/x-data-grid-premium';
|
|
5
|
+
import type { GridApiPremium } from '@mui/x-data-grid-premium';
|
|
5
6
|
import { rows } from '../_shared/data';
|
|
6
7
|
import { columns } from '../_shared/columns';
|
|
7
8
|
import { CustomToolbar, BulkActionBar } from '../_shared/helpers';
|
|
@@ -12,20 +13,20 @@ import { StateDebugPanel } from '../_shared/StateDebugPanel';
|
|
|
12
13
|
interface Props {
|
|
13
14
|
initialFilterModel?: GridFilterModel;
|
|
14
15
|
useRouter?: () => { pathname: string; search: string; historyReplace: (newSearch: string) => void };
|
|
15
|
-
apiRef?: React.MutableRefObject<
|
|
16
|
+
apiRef?: React.MutableRefObject<GridApiPremium | null>;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export default ({ initialFilterModel, useRouter = useRouterAdapter, apiRef: propsApiRef }: Props) => {
|
|
19
20
|
const internalApiRef = useGridApiRef();
|
|
20
21
|
const apiRef = propsApiRef ?? internalApiRef;
|
|
21
|
-
const [selectionModel, setSelectionModel] = useState<GridRowSelectionModel>(
|
|
22
|
+
const [selectionModel, setSelectionModel] = useState<GridRowSelectionModel>(EMPTY_ROW_SELECTION_MODEL);
|
|
22
23
|
|
|
23
24
|
return (
|
|
24
25
|
<div style={{ width: '100%' }}>
|
|
25
26
|
<StateDebugPanel apiRef={apiRef} useRouter={useRouter} localStorageVersion={1} />
|
|
26
27
|
<Flexbox flexDirection="column" gap="0px">
|
|
27
28
|
<BulkActionBar
|
|
28
|
-
count={selectionModel
|
|
29
|
+
count={getSelectionCount(selectionModel)}
|
|
29
30
|
onLog={() => console.log('Selected:', selectionModel)}
|
|
30
31
|
onDelete={() => console.log('Delete:', selectionModel)}
|
|
31
32
|
/>
|
|
@@ -2,7 +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-
|
|
5
|
+
import { GridFilterModel, useGridApiRef } from '@mui/x-data-grid-premium';
|
|
6
6
|
|
|
7
7
|
import Example from './example';
|
|
8
8
|
import WithLoadingExample from './with-loading';
|
|
@@ -645,6 +645,92 @@ export const SortingInteraction: Story = {
|
|
|
645
645
|
},
|
|
646
646
|
};
|
|
647
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
|
+
|
|
648
734
|
// ---------------------------------------------------------------------------
|
|
649
735
|
// Column Order — reorder via apiRef, assert URL
|
|
650
736
|
// ---------------------------------------------------------------------------
|
|
@@ -687,6 +773,53 @@ export const ColumnOrderInteraction: Story = {
|
|
|
687
773
|
},
|
|
688
774
|
};
|
|
689
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
|
+
|
|
690
823
|
// ---------------------------------------------------------------------------
|
|
691
824
|
// State variants — with interaction assertions
|
|
692
825
|
// ---------------------------------------------------------------------------
|
|
@@ -1,7 +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,
|
|
4
|
+
import { GridFilterModel, GridRowSelectionModel, GridSortModel, useGridApiRef } from '@mui/x-data-grid-premium';
|
|
5
|
+
import type { GridApiPremium } from '@mui/x-data-grid-premium';
|
|
5
6
|
import { Row } from '../_shared/data';
|
|
6
7
|
import { columns } from '../_shared/columns';
|
|
7
8
|
import { fetchBakeryData } from '../_shared/api-client';
|
|
@@ -13,7 +14,7 @@ import { StateDebugPanel } from '../_shared/StateDebugPanel';
|
|
|
13
14
|
interface Props {
|
|
14
15
|
initialFilterModel?: GridFilterModel;
|
|
15
16
|
useRouter?: () => { pathname: string; search: string; historyReplace: (newSearch: string) => void };
|
|
16
|
-
apiRef?: React.MutableRefObject<
|
|
17
|
+
apiRef?: React.MutableRefObject<GridApiPremium | null>;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export default ({ initialFilterModel, useRouter = useRouterAdapter, apiRef: propsApiRef }: Props) => {
|
|
@@ -22,7 +23,7 @@ export default ({ initialFilterModel, useRouter = useRouterAdapter, apiRef: prop
|
|
|
22
23
|
const [rows, setRows] = useState<Row[]>([]);
|
|
23
24
|
const [totalRows, setTotalRows] = useState(0);
|
|
24
25
|
const [loading, setLoading] = useState(true);
|
|
25
|
-
const [selectionModel, setSelectionModel] = useState<GridRowSelectionModel>(
|
|
26
|
+
const [selectionModel, setSelectionModel] = useState<GridRowSelectionModel>(EMPTY_ROW_SELECTION_MODEL);
|
|
26
27
|
|
|
27
28
|
// Refs track the latest model values so fetchData() always reads current state.
|
|
28
29
|
// StatefulDataGrid manages filter/sort/pagination internally — we use callbacks
|
|
@@ -57,7 +58,7 @@ export default ({ initialFilterModel, useRouter = useRouterAdapter, apiRef: prop
|
|
|
57
58
|
<StateDebugPanel apiRef={apiRef} useRouter={useRouter} localStorageVersion={1} />
|
|
58
59
|
<Flexbox flexDirection="column" gap="0px">
|
|
59
60
|
<BulkActionBar
|
|
60
|
-
count={selectionModel
|
|
61
|
+
count={getSelectionCount(selectionModel)}
|
|
61
62
|
onLog={() => console.log('Selected:', selectionModel)}
|
|
62
63
|
onDelete={() => console.log('Delete:', selectionModel)}
|
|
63
64
|
/>
|
|
@@ -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<GridApiPro>",
|
|
17
|
+
"description": "Datagrid API Ref. MUI v8: can be null initially.",
|
|
18
|
+
"type": "MutableRefObject<GridApiPro | null>",
|
|
19
19
|
"required": false,
|
|
20
20
|
"defaultValue": null,
|
|
21
21
|
"category": "props"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "DmarcSummaryBoxes",
|
|
3
|
-
"description": "
|
|
3
|
+
"description": "",
|
|
4
4
|
"package": "@redsift/products",
|
|
5
5
|
"filePath": "packages/products/src/components/signal-cards/cards/SignalCardDmarc/DmarcSummaryBoxes.tsx",
|
|
6
6
|
"props": [
|
|
@@ -85,17 +85,17 @@
|
|
|
85
85
|
"category": "props"
|
|
86
86
|
},
|
|
87
87
|
{
|
|
88
|
-
"name": "
|
|
89
|
-
"description": "",
|
|
90
|
-
"type": "string",
|
|
88
|
+
"name": "getTreeDataPath",
|
|
89
|
+
"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.",
|
|
90
|
+
"type": "(row: any) => readonly string[]",
|
|
91
91
|
"required": false,
|
|
92
92
|
"defaultValue": null,
|
|
93
93
|
"category": "props"
|
|
94
94
|
},
|
|
95
95
|
{
|
|
96
|
-
"name": "
|
|
97
|
-
"description": "",
|
|
98
|
-
"type": "
|
|
96
|
+
"name": "setTreeDataPath",
|
|
97
|
+
"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.",
|
|
98
|
+
"type": "(path: string[], row: any) => any",
|
|
99
99
|
"required": false,
|
|
100
100
|
"defaultValue": null,
|
|
101
101
|
"category": "props"
|
|
@@ -109,17 +109,17 @@
|
|
|
109
109
|
"category": "props"
|
|
110
110
|
},
|
|
111
111
|
{
|
|
112
|
-
"name": "
|
|
113
|
-
"description": "",
|
|
114
|
-
"type": "string",
|
|
112
|
+
"name": "getTreeDataPath",
|
|
113
|
+
"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.",
|
|
114
|
+
"type": "(row: any) => readonly string[]",
|
|
115
115
|
"required": false,
|
|
116
116
|
"defaultValue": null,
|
|
117
117
|
"category": "props"
|
|
118
118
|
},
|
|
119
119
|
{
|
|
120
|
-
"name": "
|
|
121
|
-
"description": "",
|
|
122
|
-
"type": "
|
|
120
|
+
"name": "setTreeDataPath",
|
|
121
|
+
"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.",
|
|
122
|
+
"type": "(path: string[], row: any) => any",
|
|
123
123
|
"required": false,
|
|
124
124
|
"defaultValue": null,
|
|
125
125
|
"category": "props"
|
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
{
|
|
8
8
|
"name": "columnsButtonProps",
|
|
9
9
|
"description": "Props to forward to the column button.",
|
|
10
|
-
"type":
|
|
10
|
+
"type": [
|
|
11
|
+
"GridToolbarColumnsButtonProps",
|
|
12
|
+
"GridToolbarColumnsButtonProps & RefAttributes<HTMLButtonElement>"
|
|
13
|
+
],
|
|
11
14
|
"required": false,
|
|
12
15
|
"defaultValue": null,
|
|
13
16
|
"category": "props"
|
|
@@ -23,7 +26,10 @@
|
|
|
23
26
|
{
|
|
24
27
|
"name": "densityButtonProps",
|
|
25
28
|
"description": "Props to forward to the density button.",
|
|
26
|
-
"type":
|
|
29
|
+
"type": [
|
|
30
|
+
"GridToolbarDensitySelectorProps",
|
|
31
|
+
"GridToolbarDensitySelectorProps & RefAttributes<HTMLButtonElement>"
|
|
32
|
+
],
|
|
27
33
|
"required": false,
|
|
28
34
|
"defaultValue": null,
|
|
29
35
|
"category": "props"
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "DataGrid",
|
|
3
|
+
"description": "DataGrid displays tabular data with sorting, filtering, pagination, and row selection.\nBuilt on MUI X DataGrid Pro with Red Sift styling and theming.\n\nRequires MUI X Pro license key (set via `MUI_LICENSE_KEY` env variable).\n\nUse `createColumn()` to get pre-configured column definitions with typed filter operators.\nSupported types: `string`, `number`, `date`, `dateTime`, `singleSelect`, `multiSelect`, `tags`.\nFor `boolean` columns, use `type: 'boolean'` directly (no createColumn wrapper needed).",
|
|
4
|
+
"package": "@redsift/table-pro",
|
|
5
|
+
"filePath": "packages/table-pro/src/components/DataGrid/DataGrid.tsx",
|
|
6
|
+
"props": [
|
|
7
|
+
{
|
|
8
|
+
"name": "license",
|
|
9
|
+
"description": "License key for MUI Datagrid Pro.",
|
|
10
|
+
"type": "string",
|
|
11
|
+
"required": false,
|
|
12
|
+
"defaultValue": null,
|
|
13
|
+
"category": "props"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"name": "height",
|
|
17
|
+
"description": "Height. A default one is set to prevent rendering all rows.",
|
|
18
|
+
"type": "string",
|
|
19
|
+
"required": false,
|
|
20
|
+
"defaultValue": "'500px'",
|
|
21
|
+
"category": "props"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "toolbar",
|
|
25
|
+
"description": "Toolbar. A default one is provided but every button from this default Toolbar can be customized and the entire Toolbar can be replaced.",
|
|
26
|
+
"type": "ReactNode",
|
|
27
|
+
"required": false,
|
|
28
|
+
"defaultValue": null,
|
|
29
|
+
"category": "props"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "hideToolbar",
|
|
33
|
+
"description": "Whether the Toolbar is displayed or not.",
|
|
34
|
+
"type": [
|
|
35
|
+
"false",
|
|
36
|
+
"true"
|
|
37
|
+
],
|
|
38
|
+
"required": false,
|
|
39
|
+
"defaultValue": null,
|
|
40
|
+
"category": "props"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "paginationPlacement",
|
|
44
|
+
"description": "Indicates where to render the pagination controls (the \"Rows per page\" + page\nnavigation bar). Independent of `selectionBannerPlacement`.\n\n- `'top'` / `'bottom'` / `'both'` — above / below / both sides of the grid body.\n- `'none'` — no pager controls.\n- `'belowToolbar'` — in a row directly below the toolbar (right-aligned). Pair\n with `selectionBannerPlacement=\"belowToolbar\"` to get the banner on the left\n and the pager on the right in the same row. Only applies when `pagination` is enabled.",
|
|
45
|
+
"type": [
|
|
46
|
+
"\"top\"",
|
|
47
|
+
"\"bottom\"",
|
|
48
|
+
"\"both\"",
|
|
49
|
+
"\"none\"",
|
|
50
|
+
"\"belowToolbar\""
|
|
51
|
+
],
|
|
52
|
+
"required": false,
|
|
53
|
+
"defaultValue": "'both'",
|
|
54
|
+
"category": "props"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"name": "selectionBannerPlacement",
|
|
58
|
+
"description": "Where to render the row-selection banner (the \"All N rows on this page are\nselected…\" line). Independent of `paginationPlacement` — the latter only\ncontrols the pager controls.\n\n- `'top'` — above the toolbar (default, current behaviour).\n- `'bottom'` — in the footer, alongside the bottom pager.\n- `'belowToolbar'` — between the toolbar and the grid body. Rendered via\n the toolbar slot, so the toolbar slot is forced to render even when\n `hideToolbar` is set (the toolbar itself stays hidden, only the banner shows).\n Combine with `paginationPlacement=\"belowToolbar\"` for a banner-left / pager-right\n row. Only applies when `pagination` is enabled.",
|
|
59
|
+
"type": [
|
|
60
|
+
"\"top\"",
|
|
61
|
+
"\"bottom\"",
|
|
62
|
+
"\"belowToolbar\""
|
|
63
|
+
],
|
|
64
|
+
"required": false,
|
|
65
|
+
"defaultValue": "'top'",
|
|
66
|
+
"category": "props"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "paginationProps",
|
|
70
|
+
"description": "Props to forward to the pagination component.",
|
|
71
|
+
"type": "Omit<TablePaginationProps, \"paginationMode\" | \"component\" | \"count\" | \"onPageChange\" | \"onRowsPerPageChange\" | \"page\" | \"rowsPerPage\" | \"rowsPerPageOptions\">",
|
|
72
|
+
"required": false,
|
|
73
|
+
"defaultValue": null,
|
|
74
|
+
"category": "props"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "theme",
|
|
78
|
+
"description": "Theme.",
|
|
79
|
+
"type": [
|
|
80
|
+
"\"light\"",
|
|
81
|
+
"\"dark\""
|
|
82
|
+
],
|
|
83
|
+
"required": false,
|
|
84
|
+
"defaultValue": null,
|
|
85
|
+
"category": "props"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"name": "getTreeDataPath",
|
|
89
|
+
"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.",
|
|
90
|
+
"type": "(row: any) => readonly string[]",
|
|
91
|
+
"required": false,
|
|
92
|
+
"defaultValue": null,
|
|
93
|
+
"category": "props"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"name": "setTreeDataPath",
|
|
97
|
+
"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.",
|
|
98
|
+
"type": "(path: string[], row: any) => any",
|
|
99
|
+
"required": false,
|
|
100
|
+
"defaultValue": null,
|
|
101
|
+
"category": "props"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
"examples": [],
|
|
105
|
+
"tags": {},
|
|
106
|
+
"keywords": [
|
|
107
|
+
"data grid",
|
|
108
|
+
"data table",
|
|
109
|
+
"table",
|
|
110
|
+
"grid view",
|
|
111
|
+
"list view",
|
|
112
|
+
"spreadsheet"
|
|
113
|
+
]
|
|
114
|
+
}
|