@mui/x-data-grid-generator 8.26.0 → 8.27.0
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/CHANGELOG.md +100 -0
- package/columns/commodities.columns.d.ts +1 -1
- package/columns/commodities.columns.js +2 -0
- package/columns/employees.columns.d.ts +1 -1
- package/columns/employees.columns.js +1 -0
- package/constants/prompts.d.ts +1 -1
- package/esm/columns/commodities.columns.d.ts +1 -1
- package/esm/columns/commodities.columns.js +3 -1
- package/esm/columns/employees.columns.d.ts +1 -1
- package/esm/columns/employees.columns.js +2 -1
- package/esm/constants/prompts.d.ts +1 -1
- package/esm/hooks/serverUtils.d.ts +1 -1
- package/esm/hooks/useBasicDemoData.d.ts +1 -1
- package/esm/hooks/useDemoData.d.ts +4 -4
- package/esm/hooks/useEditDropdownState.d.ts +39 -0
- package/esm/hooks/useEditDropdownState.js +158 -0
- package/esm/hooks/useMockServer.d.ts +1 -1
- package/esm/hooks/useMovieData.d.ts +1 -1
- package/esm/hooks/useQuery.d.ts +2 -2
- package/esm/hooks/useRowEditHandlers.d.ts +25 -0
- package/esm/hooks/useRowEditHandlers.js +84 -0
- package/esm/index.js +1 -1
- package/esm/renderer/index.d.ts +2 -1
- package/esm/renderer/index.js +2 -1
- package/esm/renderer/renderAvatar.d.ts +1 -1
- package/esm/renderer/renderCountry.d.ts +2 -2
- package/esm/renderer/renderEditBoolean.d.ts +2 -0
- package/esm/renderer/renderEditBoolean.js +56 -0
- package/esm/renderer/renderEditCountry.d.ts +2 -2
- package/esm/renderer/renderEditCountry.js +68 -48
- package/esm/renderer/renderEditCurrency.d.ts +1 -1
- package/esm/renderer/renderEditCurrency.js +67 -47
- package/esm/renderer/renderEditIncoterm.d.ts +1 -1
- package/esm/renderer/renderEditIncoterm.js +30 -27
- package/esm/renderer/renderEditProgress.d.ts +1 -1
- package/esm/renderer/renderEditProgress.js +3 -2
- package/esm/renderer/renderEditRating.d.ts +1 -1
- package/esm/renderer/renderEditRating.js +3 -2
- package/esm/renderer/renderEditStatus.d.ts +1 -1
- package/esm/renderer/renderEditStatus.js +30 -28
- package/esm/renderer/renderEmail.d.ts +1 -1
- package/esm/renderer/renderIncoterm.d.ts +1 -1
- package/esm/renderer/renderLink.d.ts +1 -1
- package/esm/renderer/renderPnl.d.ts +1 -1
- package/esm/renderer/renderProgress.d.ts +1 -1
- package/esm/renderer/renderRating.d.ts +1 -1
- package/esm/renderer/renderStatus.d.ts +1 -1
- package/esm/renderer/renderTotalPrice.d.ts +1 -1
- package/esm/services/basic-data-service.d.ts +1 -1
- package/esm/services/gridColDefGenerator.d.ts +1 -1
- package/esm/services/prompt-resolver.d.ts +1 -1
- package/esm/services/random-generator.d.ts +1 -1
- package/esm/services/real-data-service.d.ts +2 -2
- package/esm/services/tree-data-generator.d.ts +2 -2
- package/hooks/serverUtils.d.ts +1 -1
- package/hooks/useBasicDemoData.d.ts +1 -1
- package/hooks/useDemoData.d.ts +4 -4
- package/hooks/useEditDropdownState.d.ts +39 -0
- package/hooks/useEditDropdownState.js +165 -0
- package/hooks/useMockServer.d.ts +1 -1
- package/hooks/useMovieData.d.ts +1 -1
- package/hooks/useQuery.d.ts +2 -2
- package/hooks/useRowEditHandlers.d.ts +25 -0
- package/hooks/useRowEditHandlers.js +90 -0
- package/index.js +1 -1
- package/package.json +5 -5
- package/renderer/index.d.ts +2 -1
- package/renderer/index.js +11 -0
- package/renderer/renderAvatar.d.ts +1 -1
- package/renderer/renderCountry.d.ts +2 -2
- package/renderer/renderEditBoolean.d.ts +2 -0
- package/renderer/renderEditBoolean.js +63 -0
- package/renderer/renderEditCountry.d.ts +2 -2
- package/renderer/renderEditCountry.js +67 -48
- package/renderer/renderEditCurrency.d.ts +1 -1
- package/renderer/renderEditCurrency.js +66 -47
- package/renderer/renderEditIncoterm.d.ts +1 -1
- package/renderer/renderEditIncoterm.js +30 -27
- package/renderer/renderEditProgress.d.ts +1 -1
- package/renderer/renderEditProgress.js +3 -2
- package/renderer/renderEditRating.d.ts +1 -1
- package/renderer/renderEditRating.js +3 -2
- package/renderer/renderEditStatus.d.ts +1 -1
- package/renderer/renderEditStatus.js +30 -28
- package/renderer/renderEmail.d.ts +1 -1
- package/renderer/renderIncoterm.d.ts +1 -1
- package/renderer/renderLink.d.ts +1 -1
- package/renderer/renderPnl.d.ts +1 -1
- package/renderer/renderProgress.d.ts +1 -1
- package/renderer/renderRating.d.ts +1 -1
- package/renderer/renderStatus.d.ts +1 -1
- package/renderer/renderTotalPrice.d.ts +1 -1
- package/services/basic-data-service.d.ts +1 -1
- package/services/gridColDefGenerator.d.ts +1 -1
- package/services/prompt-resolver.d.ts +1 -1
- package/services/random-generator.d.ts +1 -1
- package/services/real-data-service.d.ts +2 -2
- package/services/tree-data-generator.d.ts +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,106 @@
|
|
|
5
5
|
All notable changes to this project will be documented in this file.
|
|
6
6
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
7
7
|
|
|
8
|
+
## v8.27.0
|
|
9
|
+
|
|
10
|
+
_Feb 2, 2026_
|
|
11
|
+
|
|
12
|
+
We'd like to extend a big thank you to the 8 contributors who made this release possible. Here are some highlights ✨:
|
|
13
|
+
|
|
14
|
+
- 📝 Data Grid supports new `longText` [column type](https://mui.com/x/react-data-grid/column-definition/#column-types)
|
|
15
|
+
|
|
16
|
+
The following team members contributed to this release:
|
|
17
|
+
@alexfauquette, @arminmeh, @bernardobelchior, @cherniavskii, @flaviendelangle, @JCQuintas, @MBilalShafi, @siriwatknp
|
|
18
|
+
|
|
19
|
+
### Data Grid
|
|
20
|
+
|
|
21
|
+
#### `@mui/x-data-grid@8.27.0`
|
|
22
|
+
|
|
23
|
+
- [DataGrid] Fix virtualization crash by preventing out-of-bounds `focusedVirtualCell` indices (#21123) @cherniavskii
|
|
24
|
+
- [DataGrid] Fix focus steal issue with `<Dialog />` (#21106) @MBilalShafi
|
|
25
|
+
- [DataGrid] Add new `longText` column type (#21103) @siriwatknp
|
|
26
|
+
|
|
27
|
+
#### `@mui/x-data-grid-pro@8.27.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
28
|
+
|
|
29
|
+
Same changes as in `@mui/x-data-grid@8.27.0`.
|
|
30
|
+
|
|
31
|
+
#### `@mui/x-data-grid-premium@8.27.0` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
32
|
+
|
|
33
|
+
Same changes as in `@mui/x-data-grid-pro@8.27.0`, plus:
|
|
34
|
+
|
|
35
|
+
- [DataGridPremium] Fix focus retention when undo/redo operations are done on the same cell (#21110) @arminmeh
|
|
36
|
+
|
|
37
|
+
### Date and Time Pickers
|
|
38
|
+
|
|
39
|
+
#### `@mui/x-date-pickers@8.27.0`
|
|
40
|
+
|
|
41
|
+
Internal changes.
|
|
42
|
+
|
|
43
|
+
#### `@mui/x-date-pickers-pro@8.27.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
44
|
+
|
|
45
|
+
Same changes as in `@mui/x-date-pickers@8.27.0`.
|
|
46
|
+
|
|
47
|
+
### Charts
|
|
48
|
+
|
|
49
|
+
#### `@mui/x-charts@8.27.0`
|
|
50
|
+
|
|
51
|
+
- [charts] Deprecate `AxisId` class in favour of to `data-axis-id` attribute (#21048) @JCQuintas
|
|
52
|
+
|
|
53
|
+
#### `@mui/x-charts-pro@8.27.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
54
|
+
|
|
55
|
+
Same changes as in `@mui/x-charts@8.27.0`, plus:
|
|
56
|
+
|
|
57
|
+
- [charts-pro] Add `onItemClick` to the heatmap (#20817) (#21030) @alexfauquette
|
|
58
|
+
|
|
59
|
+
#### `@mui/x-charts-premium@8.27.0` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
60
|
+
|
|
61
|
+
Same changes as in `@mui/x-charts-pro@8.27.0`, plus:
|
|
62
|
+
|
|
63
|
+
- [charts-premium] Fix wrong `defaultSlots` in premium charts (#21052) @bernardobelchior
|
|
64
|
+
|
|
65
|
+
### Tree View
|
|
66
|
+
|
|
67
|
+
#### `@mui/x-tree-view@8.27.0`
|
|
68
|
+
|
|
69
|
+
Internal changes.
|
|
70
|
+
|
|
71
|
+
#### `@mui/x-tree-view-pro@8.27.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
72
|
+
|
|
73
|
+
Same changes as in `@mui/x-tree-view@8.27.0`, plus:
|
|
74
|
+
|
|
75
|
+
- [RichTreeViewPro] Do not export `useSimpleTreeViewApiRef()` and `useRichTreeViewApiRef()` from pro package (#21145) @flaviendelangle
|
|
76
|
+
|
|
77
|
+
### Codemod
|
|
78
|
+
|
|
79
|
+
#### `@mui/x-codemod@8.27.0`
|
|
80
|
+
|
|
81
|
+
Internal changes.
|
|
82
|
+
|
|
83
|
+
### Docs
|
|
84
|
+
|
|
85
|
+
- [docs] Fix DataGrid's cell edit renderers (@arminmeh) (#21041) @github-actions[bot]
|
|
86
|
+
|
|
87
|
+
### Core
|
|
88
|
+
|
|
89
|
+
- [code-infra] Add `consistent-type-imports` rule to the grid packages (#21119) @arminmeh
|
|
90
|
+
- [code-infra] Allow user to select target branch if it exists for current major (#21005) @JCQuintas
|
|
91
|
+
- [code-infra] Fix the target branch condition in the release script (#21051) @arminmeh
|
|
92
|
+
- [code-infra] Update docs deploy script to fetch from `v8.x` (#21013) @arminmeh
|
|
93
|
+
|
|
94
|
+
## 8.26.1
|
|
95
|
+
|
|
96
|
+
_Jan 23, 2026_
|
|
97
|
+
|
|
98
|
+
Release highlight ✨:
|
|
99
|
+
|
|
100
|
+
- 🐞 Hotfix for Data Grid Premium type imports
|
|
101
|
+
|
|
102
|
+
### Data Grid
|
|
103
|
+
|
|
104
|
+
#### `@mui/x-data-grid-premium@8.26.1` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
105
|
+
|
|
106
|
+
- [DataGridPremium] Fix type import (#21033) @arminmeh
|
|
107
|
+
|
|
8
108
|
## 8.26.0
|
|
9
109
|
|
|
10
110
|
_Jan 22, 2026_
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { GridColDefGenerator } from "../services/gridColDefGenerator.js";
|
|
1
|
+
import type { GridColDefGenerator } from "../services/gridColDefGenerator.js";
|
|
2
2
|
export declare const getCommodityColumns: (editable?: boolean) => GridColDefGenerator[];
|
|
@@ -61,6 +61,7 @@ const getCommodityColumns = (editable = false) => [{
|
|
|
61
61
|
generateData: _services.generateIsFilled,
|
|
62
62
|
type: 'boolean',
|
|
63
63
|
width: 80,
|
|
64
|
+
renderEditCell: _renderer.renderEditBoolean,
|
|
64
65
|
editable
|
|
65
66
|
}, {
|
|
66
67
|
field: 'status',
|
|
@@ -168,6 +169,7 @@ const getCommodityColumns = (editable = false) => [{
|
|
|
168
169
|
type: 'singleSelect',
|
|
169
170
|
generateData: _services.randomCountry,
|
|
170
171
|
renderCell: _renderer.renderCountry,
|
|
172
|
+
renderEditCell: _renderer.renderEditCountry,
|
|
171
173
|
valueOptions: _staticData.COUNTRY_ISO_OPTIONS_SORTED,
|
|
172
174
|
valueParser: value => {
|
|
173
175
|
if (typeof value === 'string') {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { GridColDefGenerator } from "../services/gridColDefGenerator.js";
|
|
1
|
+
import type { GridColDefGenerator } from "../services/gridColDefGenerator.js";
|
|
2
2
|
export declare const getEmployeeColumns: () => GridColDefGenerator[];
|
package/constants/prompts.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { PromptResponse } from '@mui/x-data-grid-premium';
|
|
1
|
+
import type { PromptResponse } from '@mui/x-data-grid-premium';
|
|
2
2
|
export declare const mockPrompts: Map<string, PromptResponse>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { GridColDefGenerator } from "../services/gridColDefGenerator.js";
|
|
1
|
+
import type { GridColDefGenerator } from "../services/gridColDefGenerator.js";
|
|
2
2
|
export declare const getCommodityColumns: (editable?: boolean) => GridColDefGenerator[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { gridStringOrNumberComparator } from '@mui/x-data-grid-premium';
|
|
2
2
|
import { randomCommodity, randomDesk, randomEmail, randomFeeRate, generateFilledQuantity, randomId, randomIncoterm, generateIsFilled, randomQuantity, randomTraderName, randomUnitPrice, randomUnitPriceCurrency, randomStatusOptions, randomPnL, randomTradeDate, randomMaturityDate, randomBrokerId, randomCompanyName, randomCountry, randomCurrency, randomAddress, randomCity, randomUpdatedDate, randomCreatedDate, randomRateType, randomContractType, randomTaxCode } from "../services/index.js";
|
|
3
|
-
import { renderCountry, renderEmail, renderIncoterm, renderPnl, renderProgress, renderStatus, renderTotalPrice, renderEditCurrency, renderEditProgress, renderEditStatus, renderEditIncoterm } from "../renderer/index.js";
|
|
3
|
+
import { renderCountry, renderEmail, renderIncoterm, renderPnl, renderProgress, renderStatus, renderTotalPrice, renderEditCurrency, renderEditProgress, renderEditStatus, renderEditIncoterm, renderEditBoolean, renderEditCountry } from "../renderer/index.js";
|
|
4
4
|
import { CONTRACT_TYPE_OPTIONS, COUNTRY_ISO_OPTIONS_SORTED, CURRENCY_OPTIONS, INCOTERM_OPTIONS, RATE_TYPE_OPTIONS, STATUS_OPTIONS, TAXCODE_OPTIONS } from "../services/static-data.js";
|
|
5
5
|
export const getCommodityColumns = (editable = false) => [{
|
|
6
6
|
field: 'id',
|
|
@@ -55,6 +55,7 @@ export const getCommodityColumns = (editable = false) => [{
|
|
|
55
55
|
generateData: generateIsFilled,
|
|
56
56
|
type: 'boolean',
|
|
57
57
|
width: 80,
|
|
58
|
+
renderEditCell: renderEditBoolean,
|
|
58
59
|
editable
|
|
59
60
|
}, {
|
|
60
61
|
field: 'status',
|
|
@@ -162,6 +163,7 @@ export const getCommodityColumns = (editable = false) => [{
|
|
|
162
163
|
type: 'singleSelect',
|
|
163
164
|
generateData: randomCountry,
|
|
164
165
|
renderCell: renderCountry,
|
|
166
|
+
renderEditCell: renderEditCountry,
|
|
165
167
|
valueOptions: COUNTRY_ISO_OPTIONS_SORTED,
|
|
166
168
|
valueParser: value => {
|
|
167
169
|
if (typeof value === 'string') {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { GridColDefGenerator } from "../services/gridColDefGenerator.js";
|
|
1
|
+
import type { GridColDefGenerator } from "../services/gridColDefGenerator.js";
|
|
2
2
|
export declare const getEmployeeColumns: () => GridColDefGenerator[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { gridStringOrNumberComparator } from '@mui/x-data-grid-premium';
|
|
2
2
|
import { randomCity, randomCompanyName, randomCountry, randomCreatedDate, randomEmail, randomId, randomJobTitle, randomPhoneNumber, randomRating, randomUpdatedDate, randomUrl, randomUserName, randomBoolean, randomName, randomColor, randomInt } from "../services/index.js";
|
|
3
|
-
import { renderAvatar, renderCountry, renderEmail, renderLink, renderRating, renderEditRating, renderEditCountry } from "../renderer/index.js";
|
|
3
|
+
import { renderAvatar, renderCountry, renderEmail, renderLink, renderRating, renderEditRating, renderEditCountry, renderEditBoolean } from "../renderer/index.js";
|
|
4
4
|
import { COUNTRY_ISO_OPTIONS_SORTED } from "../services/static-data.js";
|
|
5
5
|
export const getEmployeeColumns = () => [{
|
|
6
6
|
field: 'id',
|
|
@@ -121,6 +121,7 @@ export const getEmployeeColumns = () => [{
|
|
|
121
121
|
generateData: randomBoolean,
|
|
122
122
|
type: 'boolean',
|
|
123
123
|
width: 150,
|
|
124
|
+
renderEditCell: renderEditBoolean,
|
|
124
125
|
editable: true
|
|
125
126
|
}, {
|
|
126
127
|
field: 'salary',
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { PromptResponse } from '@mui/x-data-grid-premium';
|
|
1
|
+
import type { PromptResponse } from '@mui/x-data-grid-premium';
|
|
2
2
|
export declare const mockPrompts: Map<string, PromptResponse>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GridRowModel, GridFilterModel, GridSortModel, GridColDef, GridRowId, GridPaginationModel, GridValidRowModel, GridAggregationModel, GridPivotModel, GridGetRowsResponse } from '@mui/x-data-grid-premium';
|
|
1
|
+
import { type GridRowModel, type GridFilterModel, type GridSortModel, type GridColDef, type GridRowId, type GridPaginationModel, type GridValidRowModel, type GridAggregationModel, type GridPivotModel, type GridGetRowsResponse } from '@mui/x-data-grid-premium';
|
|
2
2
|
export interface FakeServerResponse {
|
|
3
3
|
returnedRows: GridRowModel[];
|
|
4
4
|
aggregateRow?: GridValidRowModel;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { GridBasicData } from "../services/index.js";
|
|
1
|
+
import { type GridBasicData } from "../services/index.js";
|
|
2
2
|
export declare const useBasicDemoData: (nbRows: number, nbCols: number) => GridBasicData;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { GridColumnVisibilityModel } from '@mui/x-data-grid-premium';
|
|
2
|
-
import { GridDemoData } from "../services/real-data-service.js";
|
|
3
|
-
import { GridColDefGenerator } from "../services/gridColDefGenerator.js";
|
|
4
|
-
import { AddPathToDemoDataOptions, DemoTreeDataValue } from "../services/tree-data-generator.js";
|
|
1
|
+
import type { GridColumnVisibilityModel } from '@mui/x-data-grid-premium';
|
|
2
|
+
import { type GridDemoData } from "../services/real-data-service.js";
|
|
3
|
+
import type { GridColDefGenerator } from "../services/gridColDefGenerator.js";
|
|
4
|
+
import { type AddPathToDemoDataOptions, type DemoTreeDataValue } from "../services/tree-data-generator.js";
|
|
5
5
|
export type DemoDataReturnType = {
|
|
6
6
|
data: DemoTreeDataValue;
|
|
7
7
|
loading: boolean;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type GridRowId } from '@mui/x-data-grid-premium';
|
|
3
|
+
interface UseEditDropdownStateParams {
|
|
4
|
+
id: GridRowId;
|
|
5
|
+
field: string;
|
|
6
|
+
hasFocus: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Hook that manages dropdown state and keyboard handling for custom edit cells
|
|
10
|
+
* with dropdowns (Select, Autocomplete).
|
|
11
|
+
*
|
|
12
|
+
* Provides:
|
|
13
|
+
* - Auto-open on mount if cell had focus when edit started
|
|
14
|
+
* - Focus management when tabbing into the cell
|
|
15
|
+
* - Keyboard handlers for Tab, Enter, Escape that work in both cell and row edit modes
|
|
16
|
+
* - Handlers for Select and Autocomplete components
|
|
17
|
+
*/
|
|
18
|
+
export declare function useEditDropdownState(params: UseEditDropdownStateParams): {
|
|
19
|
+
open: boolean;
|
|
20
|
+
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
|
21
|
+
inputRef: React.RefObject<HTMLInputElement | null>;
|
|
22
|
+
shouldAutoOpen: boolean;
|
|
23
|
+
handleSelectKeyDown: (event: React.KeyboardEvent) => void;
|
|
24
|
+
handleSelectMenuClose: (event: object, reason: "escapeKeyDown" | "backdropClick" | "tabKeyDown") => void;
|
|
25
|
+
handleSelectMenuListKeyDown: (event: React.KeyboardEvent) => void;
|
|
26
|
+
createSelectChangeHandler: (getValue: (event: {
|
|
27
|
+
target: {
|
|
28
|
+
value: unknown;
|
|
29
|
+
};
|
|
30
|
+
}) => unknown) => (event: {
|
|
31
|
+
target: {
|
|
32
|
+
value: unknown;
|
|
33
|
+
};
|
|
34
|
+
}) => Promise<void>;
|
|
35
|
+
handleAutocompleteInputKeyDown: (event: React.KeyboardEvent) => void;
|
|
36
|
+
handleAutocompleteWrapperKeyDown: (event: React.KeyboardEvent) => void;
|
|
37
|
+
createAutocompleteChangeHandler: <T>(transformValue?: (value: T) => unknown) => (event: React.SyntheticEvent, newValue: T) => Promise<void>;
|
|
38
|
+
};
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
|
|
6
|
+
import { GridCellEditStopReasons, GridEditModes, useGridApiContext, useGridRootProps } from '@mui/x-data-grid-premium';
|
|
7
|
+
import { useRowEditHandlers } from "./useRowEditHandlers.js";
|
|
8
|
+
/**
|
|
9
|
+
* Hook that manages dropdown state and keyboard handling for custom edit cells
|
|
10
|
+
* with dropdowns (Select, Autocomplete).
|
|
11
|
+
*
|
|
12
|
+
* Provides:
|
|
13
|
+
* - Auto-open on mount if cell had focus when edit started
|
|
14
|
+
* - Focus management when tabbing into the cell
|
|
15
|
+
* - Keyboard handlers for Tab, Enter, Escape that work in both cell and row edit modes
|
|
16
|
+
* - Handlers for Select and Autocomplete components
|
|
17
|
+
*/
|
|
18
|
+
export function useEditDropdownState(params) {
|
|
19
|
+
const {
|
|
20
|
+
id,
|
|
21
|
+
field,
|
|
22
|
+
hasFocus
|
|
23
|
+
} = params;
|
|
24
|
+
const apiRef = useGridApiContext();
|
|
25
|
+
const rootProps = useGridRootProps();
|
|
26
|
+
const inputRef = React.useRef(null);
|
|
27
|
+
|
|
28
|
+
// Only auto-open if this cell had focus when edit started
|
|
29
|
+
const shouldAutoOpen = React.useRef(hasFocus).current;
|
|
30
|
+
const [open, setOpen] = React.useState(shouldAutoOpen);
|
|
31
|
+
|
|
32
|
+
// Track open state in a ref for event handlers that need current value
|
|
33
|
+
const openRef = React.useRef(open);
|
|
34
|
+
openRef.current = open;
|
|
35
|
+
const isRowEditMode = rootProps.editMode === GridEditModes.Row;
|
|
36
|
+
const closeMenu = React.useCallback(() => setOpen(false), []);
|
|
37
|
+
const {
|
|
38
|
+
handleTabKeyDown,
|
|
39
|
+
handleMenuKeyDown
|
|
40
|
+
} = useRowEditHandlers({
|
|
41
|
+
id,
|
|
42
|
+
field,
|
|
43
|
+
onClose: closeMenu
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Focus input when hasFocus becomes true (e.g., when tabbing into this cell)
|
|
47
|
+
useEnhancedEffect(() => {
|
|
48
|
+
if (hasFocus) {
|
|
49
|
+
inputRef.current?.focus();
|
|
50
|
+
}
|
|
51
|
+
}, [hasFocus]);
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Handler for Select's onKeyDown - handles Tab when menu is closed
|
|
55
|
+
*/
|
|
56
|
+
const handleSelectKeyDown = React.useCallback(event => {
|
|
57
|
+
if (event.key === 'Tab') {
|
|
58
|
+
handleTabKeyDown(event);
|
|
59
|
+
}
|
|
60
|
+
}, [handleTabKeyDown]);
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Handler for Select's MenuProps.onClose - closes menu and exits cell edit on backdrop click
|
|
64
|
+
*/
|
|
65
|
+
const handleSelectMenuClose = React.useCallback((event, reason) => {
|
|
66
|
+
setOpen(false);
|
|
67
|
+
if (reason === 'backdropClick' && rootProps.editMode === GridEditModes.Cell && apiRef.current.getCellMode(id, field) === 'edit') {
|
|
68
|
+
const cellParams = apiRef.current.getCellParams(id, field);
|
|
69
|
+
apiRef.current.publishEvent('cellEditStop', _extends({}, cellParams, {
|
|
70
|
+
reason: GridCellEditStopReasons.cellFocusOut
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
}, [apiRef, id, field, rootProps.editMode]);
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Creates a change handler for Select that closes menu and optionally exits edit mode
|
|
77
|
+
*/
|
|
78
|
+
const createSelectChangeHandler = React.useCallback(getValue => {
|
|
79
|
+
return async event => {
|
|
80
|
+
// Close menu after selection
|
|
81
|
+
setOpen(false);
|
|
82
|
+
const newValue = getValue(event);
|
|
83
|
+
const isValid = await apiRef.current.setEditCellValue({
|
|
84
|
+
id,
|
|
85
|
+
field,
|
|
86
|
+
value: newValue
|
|
87
|
+
}, event);
|
|
88
|
+
|
|
89
|
+
// In cell edit mode, selecting closes the menu and exits edit mode
|
|
90
|
+
// In row edit mode, selecting only closes the menu (already done above)
|
|
91
|
+
// Check if still in edit mode to avoid double-exit when Enter key also triggers grid's handler
|
|
92
|
+
if (isValid && !isRowEditMode && apiRef.current.getCellMode(id, field) === 'edit') {
|
|
93
|
+
const cellParams = apiRef.current.getCellParams(id, field);
|
|
94
|
+
apiRef.current.publishEvent('cellEditStop', _extends({}, cellParams, {
|
|
95
|
+
reason: GridCellEditStopReasons.enterKeyDown
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}, [apiRef, id, field, isRowEditMode]);
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Handler for Autocomplete's InputBase onKeyDown - handles Tab
|
|
103
|
+
*/
|
|
104
|
+
const handleAutocompleteInputKeyDown = React.useCallback(event => {
|
|
105
|
+
if (event.key === 'Tab') {
|
|
106
|
+
handleTabKeyDown(event);
|
|
107
|
+
}
|
|
108
|
+
}, [handleTabKeyDown]);
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Handler for Autocomplete's wrapper div - stops Enter/Escape only when dropdown is open
|
|
112
|
+
*/
|
|
113
|
+
const handleAutocompleteWrapperKeyDown = React.useCallback(event => {
|
|
114
|
+
if (isRowEditMode && openRef.current && (event.key === 'Enter' || event.key === 'Escape')) {
|
|
115
|
+
event.stopPropagation();
|
|
116
|
+
}
|
|
117
|
+
}, [isRowEditMode]);
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Creates a change handler for Autocomplete that optionally exits edit mode
|
|
121
|
+
*/
|
|
122
|
+
const createAutocompleteChangeHandler = React.useCallback(transformValue => {
|
|
123
|
+
return async (event, newValue) => {
|
|
124
|
+
const valueToSet = transformValue ? transformValue(newValue) : newValue;
|
|
125
|
+
await apiRef.current.setEditCellValue({
|
|
126
|
+
id,
|
|
127
|
+
field,
|
|
128
|
+
value: valueToSet
|
|
129
|
+
}, event);
|
|
130
|
+
|
|
131
|
+
// In cell edit mode, selecting exits edit mode
|
|
132
|
+
// In row edit mode, selecting only closes the dropdown (Autocomplete handles this)
|
|
133
|
+
// Check if still in edit mode to avoid double-exit when Enter key also triggers grid's handler
|
|
134
|
+
if (!isRowEditMode && apiRef.current.getCellMode(id, field) === 'edit') {
|
|
135
|
+
apiRef.current.stopCellEditMode({
|
|
136
|
+
id,
|
|
137
|
+
field
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}, [apiRef, id, field, isRowEditMode]);
|
|
142
|
+
return {
|
|
143
|
+
// State
|
|
144
|
+
open,
|
|
145
|
+
setOpen,
|
|
146
|
+
inputRef,
|
|
147
|
+
shouldAutoOpen,
|
|
148
|
+
// Select handlers
|
|
149
|
+
handleSelectKeyDown,
|
|
150
|
+
handleSelectMenuClose,
|
|
151
|
+
handleSelectMenuListKeyDown: handleMenuKeyDown,
|
|
152
|
+
createSelectChangeHandler,
|
|
153
|
+
// Autocomplete handlers
|
|
154
|
+
handleAutocompleteInputKeyDown,
|
|
155
|
+
handleAutocompleteWrapperKeyDown,
|
|
156
|
+
createAutocompleteChangeHandler
|
|
157
|
+
};
|
|
158
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type GridGetRowsResponse, type GridRowId, type GridRowModel, type GridColDef, type GridInitialState } from '@mui/x-data-grid-premium';
|
|
2
|
-
import { AddPathToDemoDataOptions } from "../services/tree-data-generator.js";
|
|
2
|
+
import { type AddPathToDemoDataOptions } from "../services/tree-data-generator.js";
|
|
3
3
|
import type { ServerOptions } from "./serverUtils.js";
|
|
4
4
|
export declare const BASE_URL = "https://mui.com/x/api/data-grid";
|
|
5
5
|
type UseMockServerResponse<T> = {
|
package/esm/hooks/useQuery.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { GridRowModel } from '@mui/x-data-grid-pro';
|
|
3
|
-
import { UseDemoDataOptions } from "./useDemoData.js";
|
|
2
|
+
import { type GridRowModel } from '@mui/x-data-grid-pro';
|
|
3
|
+
import { type UseDemoDataOptions } from "./useDemoData.js";
|
|
4
4
|
import type { ServerOptions, QueryOptions, PageInfo } from "./serverUtils.js";
|
|
5
5
|
export declare const createFakeServer: (dataSetOptions?: Partial<UseDemoDataOptions>, serverOptions?: ServerOptions) => {
|
|
6
6
|
columns: import("../index.js").GridColDefGenerator[];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type GridRowId } from '@mui/x-data-grid-premium';
|
|
3
|
+
interface UseRowEditHandlersParams {
|
|
4
|
+
id: GridRowId;
|
|
5
|
+
field: string;
|
|
6
|
+
onClose?: () => void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Hook that provides keyboard event handlers for custom edit cells
|
|
10
|
+
* to work correctly in both cell and row edit modes.
|
|
11
|
+
*
|
|
12
|
+
* In row edit mode:
|
|
13
|
+
* - Tab moves focus to the next/previous editable cell
|
|
14
|
+
* - Enter/Escape are stopped from propagating to prevent exiting row edit
|
|
15
|
+
*
|
|
16
|
+
* In cell edit mode:
|
|
17
|
+
* - Default behavior is preserved
|
|
18
|
+
*/
|
|
19
|
+
export declare function useRowEditHandlers(params: UseRowEditHandlersParams): {
|
|
20
|
+
handleTabKeyDown: (event: React.KeyboardEvent) => void;
|
|
21
|
+
handleEnterEscapeKeyDown: (event: React.KeyboardEvent) => void;
|
|
22
|
+
handleMenuKeyDown: (event: React.KeyboardEvent) => void;
|
|
23
|
+
moveFocusToNextCell: (shiftKey: boolean) => void;
|
|
24
|
+
};
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { GridEditModes, useGridApiContext, useGridRootProps } from '@mui/x-data-grid-premium';
|
|
5
|
+
/**
|
|
6
|
+
* Hook that provides keyboard event handlers for custom edit cells
|
|
7
|
+
* to work correctly in both cell and row edit modes.
|
|
8
|
+
*
|
|
9
|
+
* In row edit mode:
|
|
10
|
+
* - Tab moves focus to the next/previous editable cell
|
|
11
|
+
* - Enter/Escape are stopped from propagating to prevent exiting row edit
|
|
12
|
+
*
|
|
13
|
+
* In cell edit mode:
|
|
14
|
+
* - Default behavior is preserved
|
|
15
|
+
*/
|
|
16
|
+
export function useRowEditHandlers(params) {
|
|
17
|
+
const {
|
|
18
|
+
id,
|
|
19
|
+
field,
|
|
20
|
+
onClose
|
|
21
|
+
} = params;
|
|
22
|
+
const apiRef = useGridApiContext();
|
|
23
|
+
const rootProps = useGridRootProps();
|
|
24
|
+
const isRowEditMode = rootProps.editMode === GridEditModes.Row;
|
|
25
|
+
const moveFocusToNextCell = React.useCallback(shiftKey => {
|
|
26
|
+
const editableFields = apiRef.current.getVisibleColumns().filter(column => column.type === 'actions' || apiRef.current.isCellEditable(apiRef.current.getCellParams(id, column.field))).map(column => column.field);
|
|
27
|
+
const currentIndex = editableFields.indexOf(field);
|
|
28
|
+
if (currentIndex === -1) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const nextIndex = shiftKey ? currentIndex - 1 : currentIndex + 1;
|
|
32
|
+
if (nextIndex < 0 || nextIndex >= editableFields.length) {
|
|
33
|
+
// At boundary - exit row edit mode
|
|
34
|
+
apiRef.current.stopRowEditMode({
|
|
35
|
+
id,
|
|
36
|
+
field,
|
|
37
|
+
cellToFocusAfter: shiftKey ? 'left' : 'right'
|
|
38
|
+
});
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
apiRef.current.setCellFocus(id, editableFields[nextIndex]);
|
|
42
|
+
}, [apiRef, id, field]);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Handle Tab key in row edit mode.
|
|
46
|
+
* Closes any open popup and moves focus to the next/previous editable cell.
|
|
47
|
+
*/
|
|
48
|
+
const handleTabKeyDown = React.useCallback(event => {
|
|
49
|
+
if (!isRowEditMode || event.key !== 'Tab') {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
event.stopPropagation();
|
|
54
|
+
onClose?.();
|
|
55
|
+
moveFocusToNextCell(event.shiftKey);
|
|
56
|
+
}, [isRowEditMode, onClose, moveFocusToNextCell]);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Prevent Enter/Escape from bubbling in row edit mode.
|
|
60
|
+
* This prevents the grid from exiting row edit when selecting from a dropdown.
|
|
61
|
+
*/
|
|
62
|
+
const handleEnterEscapeKeyDown = React.useCallback(event => {
|
|
63
|
+
if (!isRowEditMode) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (event.key === 'Enter' || event.key === 'Escape') {
|
|
67
|
+
event.stopPropagation();
|
|
68
|
+
}
|
|
69
|
+
}, [isRowEditMode]);
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Combined handler for menus/listboxes that need to handle both Tab and Enter/Escape.
|
|
73
|
+
*/
|
|
74
|
+
const handleMenuKeyDown = React.useCallback(event => {
|
|
75
|
+
handleEnterEscapeKeyDown(event);
|
|
76
|
+
handleTabKeyDown(event);
|
|
77
|
+
}, [handleEnterEscapeKeyDown, handleTabKeyDown]);
|
|
78
|
+
return {
|
|
79
|
+
handleTabKeyDown,
|
|
80
|
+
handleEnterEscapeKeyDown,
|
|
81
|
+
handleMenuKeyDown,
|
|
82
|
+
moveFocusToNextCell
|
|
83
|
+
};
|
|
84
|
+
}
|
package/esm/index.js
CHANGED
package/esm/renderer/index.d.ts
CHANGED
|
@@ -13,4 +13,5 @@ export * from "./renderEditProgress.js";
|
|
|
13
13
|
export * from "./renderEditStatus.js";
|
|
14
14
|
export * from "./renderEditIncoterm.js";
|
|
15
15
|
export * from "./renderEditRating.js";
|
|
16
|
-
export * from "./renderEditCountry.js";
|
|
16
|
+
export * from "./renderEditCountry.js";
|
|
17
|
+
export * from "./renderEditBoolean.js";
|
package/esm/renderer/index.js
CHANGED
|
@@ -13,4 +13,5 @@ export * from "./renderEditProgress.js";
|
|
|
13
13
|
export * from "./renderEditStatus.js";
|
|
14
14
|
export * from "./renderEditIncoterm.js";
|
|
15
15
|
export * from "./renderEditRating.js";
|
|
16
|
-
export * from "./renderEditCountry.js";
|
|
16
|
+
export * from "./renderEditCountry.js";
|
|
17
|
+
export * from "./renderEditBoolean.js";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { GridRenderCellParams } from '@mui/x-data-grid-premium';
|
|
2
|
-
import { CountryIsoOption } from "../services/static-data.js";
|
|
1
|
+
import { type GridRenderCellParams } from '@mui/x-data-grid-premium';
|
|
2
|
+
import type { CountryIsoOption } from "../services/static-data.js";
|
|
3
3
|
export declare function renderCountry(params: GridRenderCellParams<CountryIsoOption, any, any>): any;
|