@redsift/ds-mcp-server 12.4.0 → 12.5.0-muiv6
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 +153 -0
- 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 +560 -10
- package/data/demos/patterns/_shared/use-router-adapter.ts +51 -0
- package/data/demos/patterns/crossfiltered-datagrid-server-side/example.tsx +11 -11
- 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 +380 -167
- package/data/demos/patterns/single-datagrid-client-side/example.tsx +5 -5
- package/data/demos/patterns/single-datagrid-client-side/with-empty-state.tsx +1 -1
- package/data/demos/patterns/single-datagrid-client-side/with-error.tsx +1 -1
- package/data/demos/patterns/single-datagrid-client-side/with-loading.tsx +1 -1
- package/data/demos/patterns/single-datagrid-server-side/SingleDatagridServerSide.interaction.stories.tsx +424 -52
- package/data/demos/patterns/single-datagrid-server-side/example.tsx +5 -4
- package/data/demos/patterns/stateful-single-datagrid-client-side/StatefulSingleDatagridClientSide.interaction.stories.tsx +671 -0
- package/data/demos/patterns/stateful-single-datagrid-client-side/example.tsx +55 -0
- package/data/demos/patterns/stateful-single-datagrid-client-side/with-empty-state.tsx +27 -0
- package/data/demos/patterns/stateful-single-datagrid-client-side/with-error.tsx +39 -0
- package/data/demos/patterns/stateful-single-datagrid-client-side/with-loading.tsx +25 -0
- package/data/demos/patterns/stateful-single-datagrid-server-side/StatefulSingleDatagridServerSide.interaction.stories.tsx +690 -0
- package/data/demos/patterns/stateful-single-datagrid-server-side/example.tsx +108 -0
- package/data/demos/patterns/stateful-single-datagrid-server-side/with-empty-state.tsx +31 -0
- package/data/demos/patterns/stateful-single-datagrid-server-side/with-error.tsx +43 -0
- package/data/demos/patterns/stateful-single-datagrid-server-side/with-loading.tsx +29 -0
- package/data/demos/patterns/summary-dashboard/SummaryDashboard.interaction.stories.tsx +42 -22
- package/data/demos/patterns/summary-dashboard/example.tsx +66 -28
- package/data/demos/patterns/summary-dashboard/with-loading.tsx +12 -3
- 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 +7 -7
- package/data/docs/components/table/GridToolbarFilterSemanticField.json +1 -1
- package/data/docs/components/table/StatefulDataGrid.json +7 -7
- package/data/docs/components/table/Toolbar.json +2 -8
- package/data/docs/components.json +21 -27
- package/data/docs/llms-full.txt +805 -56
- package/data/docs/llms.txt +18 -4
- package/data/docs/patterns-catalog.md +25 -24
- package/data/docs/patterns.json +82 -8
- 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 +6 -6
- package/data/patterns/stateful-single-datagrid-client-side.mdx +304 -0
- package/data/patterns/stateful-single-datagrid-server-side.mdx +347 -0
- package/data/patterns/summary-dashboard.mdx +47 -7
- package/data/patterns/tabbed-datagrid-client-side.mdx +72 -2
- package/data/patterns/tabbed-datagrid-server-side.mdx +105 -2
- package/package.json +2 -2
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
2
|
+
import type { GridApiPro } from '@mui/x-data-grid-pro/models/gridApiPro';
|
|
3
|
+
|
|
4
|
+
// localStorage key categories — must match @redsift/table internals
|
|
5
|
+
const LS_CATEGORIES = [
|
|
6
|
+
'paginationModel',
|
|
7
|
+
'searchModel',
|
|
8
|
+
'sortModel',
|
|
9
|
+
'visibilityModel',
|
|
10
|
+
'pinnedColumns',
|
|
11
|
+
'dimension',
|
|
12
|
+
'densityModel',
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
interface StateDebugPanelProps {
|
|
16
|
+
apiRef: React.MutableRefObject<GridApiPro>;
|
|
17
|
+
useRouter: () => { pathname: string; search: string; historyReplace: (newSearch: string) => void };
|
|
18
|
+
localStorageVersion?: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const sectionStyle: React.CSSProperties = {
|
|
22
|
+
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace',
|
|
23
|
+
fontSize: '11px',
|
|
24
|
+
lineHeight: '1.4',
|
|
25
|
+
padding: '8px 12px',
|
|
26
|
+
borderRadius: '4px',
|
|
27
|
+
overflow: 'auto',
|
|
28
|
+
maxHeight: '200px',
|
|
29
|
+
whiteSpace: 'pre-wrap',
|
|
30
|
+
wordBreak: 'break-all',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const labelStyle: React.CSSProperties = {
|
|
34
|
+
fontFamily: 'inherit',
|
|
35
|
+
fontSize: '11px',
|
|
36
|
+
fontWeight: 600,
|
|
37
|
+
cursor: 'pointer',
|
|
38
|
+
userSelect: 'none',
|
|
39
|
+
display: 'flex',
|
|
40
|
+
alignItems: 'center',
|
|
41
|
+
gap: '4px',
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Reads the real DataGrid state from apiRef, URL from useRouter, and localStorage keys.
|
|
46
|
+
* Renders three collapsible JSON panels for debugging.
|
|
47
|
+
*/
|
|
48
|
+
export const StateDebugPanel: React.FC<StateDebugPanelProps> = ({ apiRef, useRouter, localStorageVersion = 1 }) => {
|
|
49
|
+
const { pathname, search } = useRouter();
|
|
50
|
+
const [_tick, setTick] = useState(0);
|
|
51
|
+
const rerender = useCallback(() => setTick((t) => t + 1), []);
|
|
52
|
+
|
|
53
|
+
// Subscribe to grid events so we re-read state after every change
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
const api = apiRef.current;
|
|
56
|
+
if (!api?.subscribeEvent) return;
|
|
57
|
+
|
|
58
|
+
const unsubs = [
|
|
59
|
+
api.subscribeEvent('filterModelChange', rerender),
|
|
60
|
+
api.subscribeEvent('sortModelChange', rerender),
|
|
61
|
+
api.subscribeEvent('paginationModelChange', rerender),
|
|
62
|
+
api.subscribeEvent('columnVisibilityModelChange', rerender),
|
|
63
|
+
api.subscribeEvent('pinnedColumnsChange', rerender),
|
|
64
|
+
api.subscribeEvent('stateChange', rerender),
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
return () => unsubs.forEach((u) => u());
|
|
68
|
+
}, [apiRef, rerender]);
|
|
69
|
+
|
|
70
|
+
// Also update after URL changes (historyReplace doesn't trigger re-render)
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
rerender();
|
|
73
|
+
}, [search, rerender]);
|
|
74
|
+
|
|
75
|
+
// -- Read grid state from apiRef --
|
|
76
|
+
let gridState: Record<string, unknown> = {};
|
|
77
|
+
try {
|
|
78
|
+
const api = apiRef.current;
|
|
79
|
+
if (api?.state) {
|
|
80
|
+
gridState = {
|
|
81
|
+
filterModel: api.state.filter?.filterModel ?? null,
|
|
82
|
+
sortModel: api.state.sorting?.sortModel ?? null,
|
|
83
|
+
paginationModel: api.state.pagination?.paginationModel ?? null,
|
|
84
|
+
columnVisibilityModel: api.state.columns?.columnVisibilityModel ?? null,
|
|
85
|
+
pinnedColumns: api.state.pinnedColumns ?? null,
|
|
86
|
+
density: api.state.density ?? null,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
} catch {
|
|
90
|
+
gridState = { error: 'Grid not yet initialized' };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// -- Read URL query params --
|
|
94
|
+
const urlParams: Record<string, string> = {};
|
|
95
|
+
const sp = new URLSearchParams(search);
|
|
96
|
+
sp.forEach((v, k) => {
|
|
97
|
+
urlParams[k] = v;
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// -- Read localStorage --
|
|
101
|
+
const lsState: Record<string, string | null> = {};
|
|
102
|
+
for (const cat of LS_CATEGORIES) {
|
|
103
|
+
const key = `${pathname}:${localStorageVersion}:${cat}`;
|
|
104
|
+
try {
|
|
105
|
+
const raw = localStorage.getItem(key);
|
|
106
|
+
lsState[cat] = raw;
|
|
107
|
+
} catch {
|
|
108
|
+
lsState[cat] = null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<div
|
|
114
|
+
data-testid="state-debug-panel"
|
|
115
|
+
style={{
|
|
116
|
+
border: '1px solid #e0e0e0',
|
|
117
|
+
borderRadius: '6px',
|
|
118
|
+
padding: '8px 12px',
|
|
119
|
+
marginBottom: '8px',
|
|
120
|
+
background: '#fafafa',
|
|
121
|
+
fontSize: '11px',
|
|
122
|
+
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace',
|
|
123
|
+
}}
|
|
124
|
+
>
|
|
125
|
+
<div style={{ fontWeight: 700, marginBottom: '6px', fontSize: '12px' }}>State Inspector</div>
|
|
126
|
+
<div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
|
|
127
|
+
<Section title="DataGrid State" data={gridState} bg="#f0f4ff" />
|
|
128
|
+
<Section
|
|
129
|
+
title="URL Query Params"
|
|
130
|
+
data={Object.keys(urlParams).length > 0 ? urlParams : '(empty)'}
|
|
131
|
+
bg="#f0fff4"
|
|
132
|
+
/>
|
|
133
|
+
<Section title="localStorage" data={lsState} bg="#fff8f0" />
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const Section: React.FC<{ title: string; data: unknown; bg: string }> = ({ title, data, bg }) => {
|
|
140
|
+
const [open, setOpen] = useState(true);
|
|
141
|
+
return (
|
|
142
|
+
<div style={{ flex: '1 1 280px', minWidth: '280px' }}>
|
|
143
|
+
<div style={labelStyle} onClick={() => setOpen((o) => !o)}>
|
|
144
|
+
<span>{open ? '▾' : '▸'}</span> {title}
|
|
145
|
+
</div>
|
|
146
|
+
{open && (
|
|
147
|
+
<pre style={{ ...sectionStyle, background: bg, margin: '4px 0 0' }}>
|
|
148
|
+
{typeof data === 'string' ? data : JSON.stringify(data, null, 2)}
|
|
149
|
+
</pre>
|
|
150
|
+
)}
|
|
151
|
+
</div>
|
|
152
|
+
);
|
|
153
|
+
};
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { createColumn, TextCell } from '@redsift/table';
|
|
3
3
|
import { Flexbox, Icon, IconButtonLink, Pill } from '@redsift/design-system';
|
|
4
4
|
import { mdiArrowRight, mdiCheck, mdiClose } from '@redsift/icons';
|
|
5
|
-
import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid-
|
|
5
|
+
import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid-pro';
|
|
6
6
|
import { Row } from './data';
|
|
7
7
|
|
|
8
8
|
// -- Option constants -------------------------------------------------------
|
|
@@ -106,7 +106,7 @@ export const columns: GridColDef<Row>[] = [
|
|
|
106
106
|
headerName: 'Date',
|
|
107
107
|
width: 140,
|
|
108
108
|
...createColumn('date'),
|
|
109
|
-
valueGetter: (
|
|
109
|
+
valueGetter: (params: any) => parseDate(params.value),
|
|
110
110
|
renderCell: ({ value }: GridRenderCellParams) => <TextCell>{value ? formatDate(value as Date) : '—'}</TextCell>,
|
|
111
111
|
},
|
|
112
112
|
// DateTime
|
|
@@ -115,7 +115,7 @@ export const columns: GridColDef<Row>[] = [
|
|
|
115
115
|
headerName: 'Date & Time',
|
|
116
116
|
width: 180,
|
|
117
117
|
...createColumn('dateTime'),
|
|
118
|
-
valueGetter: (
|
|
118
|
+
valueGetter: (params: any) => parseDate(params.value),
|
|
119
119
|
renderCell: ({ value }: GridRenderCellParams) => <TextCell>{value ? formatDateTime(value as Date) : '—'}</TextCell>,
|
|
120
120
|
},
|
|
121
121
|
// Boolean — in stock
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GridFilterModel, GridSortModel } from '@mui/x-data-grid-
|
|
1
|
+
import { GridFilterModel, GridSortModel } from '@mui/x-data-grid-pro';
|
|
2
2
|
import { Row, allRows } from './data';
|
|
3
3
|
import { Aggregates, computeAggregates, applyFilters } from './filter-helpers';
|
|
4
4
|
|