@mui/x-data-grid 6.3.1 → 6.4.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.
Files changed (134) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/DataGrid/DataGrid.js +20 -1
  3. package/DataGrid/useDataGridComponent.js +2 -2
  4. package/DataGrid/useDataGridProps.js +3 -1
  5. package/colDef/gridBooleanColDef.js +19 -1
  6. package/colDef/gridDateColDef.js +6 -2
  7. package/colDef/gridSingleSelectColDef.js +21 -1
  8. package/components/base/GridBody.js +2 -1
  9. package/components/containers/GridRootStyles.js +1 -0
  10. package/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +1 -2
  11. package/components/panel/filterPanel/GridFilterInputMultipleValue.js +1 -2
  12. package/hooks/core/pipeProcessing/gridPipeProcessingApi.d.ts +12 -1
  13. package/hooks/features/clipboard/useGridClipboard.d.ts +2 -1
  14. package/hooks/features/clipboard/useGridClipboard.js +43 -26
  15. package/hooks/features/dimensions/useGridDimensions.js +2 -4
  16. package/hooks/features/editing/useGridCellEditing.js +7 -3
  17. package/hooks/features/editing/useGridRowEditing.js +7 -3
  18. package/hooks/features/export/serializers/csvSerializer.d.ts +5 -0
  19. package/hooks/features/export/serializers/csvSerializer.js +46 -6
  20. package/hooks/features/export/useGridCsvExport.d.ts +2 -1
  21. package/hooks/features/export/useGridCsvExport.js +7 -5
  22. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +11 -0
  23. package/index.js +1 -1
  24. package/internals/index.d.ts +3 -2
  25. package/internals/index.js +3 -2
  26. package/joy/icons.d.ts +33 -0
  27. package/joy/icons.js +433 -0
  28. package/joy/joySlots.js +114 -4
  29. package/legacy/DataGrid/DataGrid.js +20 -1
  30. package/legacy/DataGrid/useDataGridComponent.js +2 -2
  31. package/legacy/DataGrid/useDataGridProps.js +3 -1
  32. package/legacy/colDef/gridBooleanColDef.js +21 -1
  33. package/legacy/colDef/gridDateColDef.js +10 -2
  34. package/legacy/colDef/gridSingleSelectColDef.js +21 -1
  35. package/legacy/components/base/GridBody.js +2 -1
  36. package/legacy/components/containers/GridRootStyles.js +1 -0
  37. package/legacy/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +1 -2
  38. package/legacy/components/panel/filterPanel/GridFilterInputMultipleValue.js +1 -2
  39. package/legacy/hooks/features/clipboard/useGridClipboard.js +44 -26
  40. package/legacy/hooks/features/dimensions/useGridDimensions.js +2 -4
  41. package/legacy/hooks/features/editing/useGridCellEditing.js +7 -3
  42. package/legacy/hooks/features/editing/useGridRowEditing.js +7 -3
  43. package/legacy/hooks/features/export/serializers/csvSerializer.js +43 -6
  44. package/legacy/hooks/features/export/useGridCsvExport.js +8 -5
  45. package/legacy/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +10 -0
  46. package/legacy/index.js +1 -1
  47. package/legacy/internals/index.js +3 -2
  48. package/legacy/joy/icons.js +432 -0
  49. package/legacy/joy/joySlots.js +118 -4
  50. package/legacy/locales/deDE.js +2 -2
  51. package/legacy/locales/frFR.js +6 -6
  52. package/legacy/locales/ptBR.js +1 -1
  53. package/legacy/locales/ukUA.js +8 -9
  54. package/legacy/material/index.js +3 -1
  55. package/legacy/models/api/index.js +0 -1
  56. package/legacy/utils/domUtils.js +14 -1
  57. package/locales/deDE.js +2 -2
  58. package/locales/frFR.js +6 -6
  59. package/locales/ptBR.js +1 -1
  60. package/locales/ukUA.js +8 -9
  61. package/material/index.d.ts +1 -0
  62. package/material/index.js +3 -1
  63. package/models/api/gridApiCommon.d.ts +1 -2
  64. package/models/api/gridCoreApi.d.ts +4 -0
  65. package/models/api/index.d.ts +0 -1
  66. package/models/api/index.js +0 -1
  67. package/models/events/gridEventLookup.d.ts +6 -0
  68. package/models/gridSlotsComponent.d.ts +5 -0
  69. package/models/gridSlotsComponentsProps.d.ts +4 -0
  70. package/models/props/DataGridProps.d.ts +19 -0
  71. package/modern/DataGrid/DataGrid.js +20 -1
  72. package/modern/DataGrid/useDataGridComponent.js +2 -2
  73. package/modern/DataGrid/useDataGridProps.js +3 -1
  74. package/modern/colDef/gridBooleanColDef.js +19 -1
  75. package/modern/colDef/gridDateColDef.js +6 -2
  76. package/modern/colDef/gridSingleSelectColDef.js +21 -1
  77. package/modern/components/base/GridBody.js +2 -1
  78. package/modern/components/containers/GridRootStyles.js +1 -0
  79. package/modern/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +1 -2
  80. package/modern/components/panel/filterPanel/GridFilterInputMultipleValue.js +1 -2
  81. package/modern/hooks/features/clipboard/useGridClipboard.js +43 -26
  82. package/modern/hooks/features/dimensions/useGridDimensions.js +1 -3
  83. package/modern/hooks/features/editing/useGridCellEditing.js +7 -3
  84. package/modern/hooks/features/editing/useGridRowEditing.js +7 -3
  85. package/modern/hooks/features/export/serializers/csvSerializer.js +44 -6
  86. package/modern/hooks/features/export/useGridCsvExport.js +7 -5
  87. package/modern/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +11 -0
  88. package/modern/index.js +1 -1
  89. package/modern/internals/index.js +3 -2
  90. package/modern/joy/icons.js +433 -0
  91. package/modern/joy/joySlots.js +110 -4
  92. package/modern/locales/deDE.js +2 -2
  93. package/modern/locales/frFR.js +6 -6
  94. package/modern/locales/ptBR.js +1 -1
  95. package/modern/locales/ukUA.js +8 -9
  96. package/modern/material/index.js +3 -1
  97. package/modern/models/api/index.js +0 -1
  98. package/modern/utils/domUtils.js +13 -1
  99. package/node/DataGrid/DataGrid.js +20 -1
  100. package/node/DataGrid/useDataGridComponent.js +2 -2
  101. package/node/DataGrid/useDataGridProps.js +3 -1
  102. package/node/colDef/gridBooleanColDef.js +19 -1
  103. package/node/colDef/gridDateColDef.js +6 -2
  104. package/node/colDef/gridSingleSelectColDef.js +21 -1
  105. package/node/components/base/GridBody.js +2 -1
  106. package/node/components/containers/GridRootStyles.js +1 -0
  107. package/node/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +1 -2
  108. package/node/components/panel/filterPanel/GridFilterInputMultipleValue.js +1 -2
  109. package/node/hooks/features/clipboard/useGridClipboard.js +42 -25
  110. package/node/hooks/features/dimensions/useGridDimensions.js +1 -3
  111. package/node/hooks/features/editing/useGridCellEditing.js +7 -3
  112. package/node/hooks/features/editing/useGridRowEditing.js +7 -3
  113. package/node/hooks/features/export/serializers/csvSerializer.js +46 -6
  114. package/node/hooks/features/export/useGridCsvExport.js +6 -3
  115. package/node/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +11 -0
  116. package/node/index.js +1 -1
  117. package/node/internals/index.js +23 -1
  118. package/node/joy/icons.js +471 -0
  119. package/node/joy/joySlots.js +110 -3
  120. package/node/locales/deDE.js +2 -2
  121. package/node/locales/frFR.js +6 -6
  122. package/node/locales/ptBR.js +1 -1
  123. package/node/locales/ukUA.js +8 -9
  124. package/node/material/index.js +3 -1
  125. package/node/models/api/index.js +0 -11
  126. package/node/utils/domUtils.js +15 -1
  127. package/package.json +1 -1
  128. package/utils/domUtils.d.ts +1 -0
  129. package/utils/domUtils.js +13 -1
  130. package/legacy/models/api/gridClipboardApi.js +0 -1
  131. package/models/api/gridClipboardApi.d.ts +0 -11
  132. package/models/api/gridClipboardApi.js +0 -1
  133. package/modern/models/api/gridClipboardApi.js +0 -1
  134. package/node/models/api/gridClipboardApi.js +0 -5
package/CHANGELOG.md CHANGED
@@ -3,6 +3,63 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## v6.4.0
7
+
8
+ _May 12, 2023_
9
+
10
+ We'd like to offer a big thanks to the 12 contributors who made this release possible. Here are some highlights ✨:
11
+
12
+ - 🎁 Introduce clipboard paste support for `DataGridPremium`:
13
+
14
+ https://github.com/mui/mui-x/assets/13808724/abfcb5c6-9db6-4677-9ba7-ae97de441080
15
+
16
+ See [the documentation](https://mui.com/x/react-data-grid/clipboard/#clipboard-paste) for more information
17
+
18
+ - 🌍 Improve French (fr-FR), German (de-DE), Portuguese (pt-BR) and Ukrainian (uk-UA) locales on the data grid
19
+ - 🌍 Add Slovak (sk-SK) locale on the pickers
20
+ - 🐞 Bugfixes
21
+ - 📚 Documentation improvements
22
+
23
+ ### `@mui/x-data-grid@v6.4.0` / `@mui/x-data-grid-pro@v6.4.0` / `@mui/x-data-grid-premium@v6.4.0`
24
+
25
+ #### Changes
26
+
27
+ - [DataGrid] Fix DataGrid rendering in JSDOM (#8968) @cherniavskii
28
+ - [DataGrid] Fix layout when rendered inside a parent with `display: grid` (#8577) @cherniavskii
29
+ - [DataGrid] Add Joy UI icon slots (#8940) @siriwatknp
30
+ - [DataGrid] Add Joy UI pagination slot (#8871) @cherniavskii
31
+ - [DataGrid] Extract `baseChip` slot (#8748) @cherniavskii
32
+ - [DataGridPremium] Implement Clipboard import (#7389) @cherniavskii
33
+ - [l10n] Improve French (fr-FR) locale (#8825) @vallereaugabriel
34
+ - [l10n] Improve German (de-DE) locale (#8898) @marcauberer
35
+ - [l10n] Improve Portuguese (pt-BR) locale (#8960) @Sorriso337
36
+ - [l10n] Improve Ukrainian (uk-UA) locale (#8863) @Neonin
37
+
38
+ ### `@mui/x-date-pickers@v6.4.0` / `@mui/x-date-pickers-pro@v6.4.0`
39
+
40
+ #### Changes
41
+
42
+ - [pickers] Fix trailing zeros inconsistency in `LuxonAdapter` (#8955) @alexfauquette
43
+ - [pickers] Stop using deprecated adapter methods (#8735) @flaviendelangle
44
+ - [pickers] Strictly type the `adapterLocale` prop of `LocalizationProvider` (#8780) @flaviendelangle
45
+ - [l10n] Add Slovak (sk-SK) locale (#8875) @MatejFacko
46
+
47
+ ### Docs
48
+
49
+ - [docs] Fix date pickers typo in the docs (#8939) @richbustos
50
+ - [docs] Fix master detail demo (#8894) @m4theushw
51
+ - [docs] Fix typo in clipboard docs (#8971) @MBilalShafi
52
+ - [docs] Reduce list of dependencies in Codesandbox/Stackblitz demos (#8535) @cherniavskii
53
+
54
+ ### Core
55
+
56
+ - [core] Improve testing of the adapters (#8789) @flaviendelangle
57
+ - [core] Update license key for tests (#8917) @LukasTy
58
+ - [charts] Make introduction docs pages for each chart (#8869) @alexfauquette
59
+ - [charts] Document Tooltip and Highlighs (#8867) @alexfauquette
60
+ - [test] Cover row grouping regression with a unit test (#8870) @cherniavskii
61
+ - [test] Fix flaky regression tests (#8954) @cherniavskii
62
+
6
63
  ## 6.3.1
7
64
 
8
65
  _May 5, 2023_
@@ -68,6 +68,11 @@ DataGridRaw.propTypes = {
68
68
  * Override or extend the styles applied to the component.
69
69
  */
70
70
  classes: PropTypes.object,
71
+ /**
72
+ * The character used to separate cell values when copying to the clipboard.
73
+ * @default '\t'
74
+ */
75
+ clipboardCopyCellDelimiter: PropTypes.string,
71
76
  /**
72
77
  * Number of extra columns to be rendered before/after the visible slice.
73
78
  * @default 3
@@ -326,6 +331,11 @@ DataGridRaw.propTypes = {
326
331
  * @param {GridCallbackDetails} details Additional details for this callback.
327
332
  */
328
333
  onCellModesModelChange: PropTypes.func,
334
+ /**
335
+ * Callback called when the data is copied to the clipboard.
336
+ * @param {string} data The data copied to the clipboard.
337
+ */
338
+ onClipboardCopy: PropTypes.func,
329
339
  /**
330
340
  * Callback fired when a click event comes from a column header element.
331
341
  * @param {GridColumnHeaderParams} params With all properties from [[GridColumnHeaderParams]].
@@ -611,5 +621,14 @@ DataGridRaw.propTypes = {
611
621
  /**
612
622
  * The system prop that allows defining system overrides as well as additional CSS styles.
613
623
  */
614
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
624
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
625
+ /**
626
+ * If `true`, the grid will not use `valueFormatter` when exporting to CSV or copying to clipboard.
627
+ * If an object is provided, you can choose to ignore the `valueFormatter` for CSV export or clipboard export.
628
+ * @default: false
629
+ */
630
+ unstable_ignoreValueFormatterDuringExport: PropTypes.oneOfType([PropTypes.shape({
631
+ clipboardExport: PropTypes.bool,
632
+ csvExport: PropTypes.bool
633
+ }), PropTypes.bool])
615
634
  };
@@ -67,9 +67,9 @@ export const useDataGridComponent = (inputApiRef, props) => {
67
67
  useGridRowsMeta(privateApiRef, props);
68
68
  useGridScroll(privateApiRef, props);
69
69
  useGridColumnMenu(privateApiRef);
70
- useGridCsvExport(privateApiRef);
70
+ useGridCsvExport(privateApiRef, props);
71
71
  useGridPrintExport(privateApiRef, props);
72
- useGridClipboard(privateApiRef);
72
+ useGridClipboard(privateApiRef, props);
73
73
  useGridDimensions(privateApiRef, props);
74
74
  useGridEvents(privateApiRef, props);
75
75
  useGridStatePersistence(privateApiRef);
@@ -66,7 +66,9 @@ export const DATA_GRID_PROPS_DEFAULT_VALUES = {
66
66
  disableColumnReorder: false,
67
67
  disableColumnResize: false,
68
68
  keepNonExistentRowsSelected: false,
69
- keepColumnPositionIfDraggedOutside: false
69
+ keepColumnPositionIfDraggedOutside: false,
70
+ unstable_ignoreValueFormatterDuringExport: false,
71
+ clipboardCopyCellDelimiter: '\t'
70
72
  };
71
73
  const defaultSlots = uncapitalizeObjectKeys(DATA_GRID_DEFAULT_SLOTS_COMPONENTS);
72
74
  export const useDataGridProps = inProps => {
@@ -10,6 +10,22 @@ function gridBooleanFormatter({
10
10
  }) {
11
11
  return value ? api.getLocaleText('booleanCellTrueLabel') : api.getLocaleText('booleanCellFalseLabel');
12
12
  }
13
+ const stringToBoolean = value => {
14
+ switch (value.toLowerCase().trim()) {
15
+ case 'true':
16
+ case 'yes':
17
+ case '1':
18
+ return true;
19
+ case 'false':
20
+ case 'no':
21
+ case '0':
22
+ case 'null':
23
+ case 'undefined':
24
+ return false;
25
+ default:
26
+ return undefined;
27
+ }
28
+ };
13
29
  export const GRID_BOOLEAN_COL_DEF = _extends({}, GRID_STRING_COL_DEF, {
14
30
  type: 'boolean',
15
31
  align: 'center',
@@ -21,5 +37,7 @@ export const GRID_BOOLEAN_COL_DEF = _extends({}, GRID_STRING_COL_DEF, {
21
37
  filterOperators: getGridBooleanOperators(),
22
38
  getApplyQuickFilterFn: undefined,
23
39
  // @ts-ignore
24
- aggregable: false
40
+ aggregable: false,
41
+ // @ts-ignore
42
+ pastedValueParser: value => stringToBoolean(value)
25
43
  });
@@ -51,7 +51,9 @@ export const GRID_DATE_COL_DEF = _extends({}, GRID_STRING_COL_DEF, {
51
51
  valueFormatter: gridDateFormatter,
52
52
  filterOperators: getGridDateOperators(),
53
53
  renderEditCell: renderEditDateCell,
54
- getApplyQuickFilterFn: undefined
54
+ getApplyQuickFilterFn: undefined,
55
+ // @ts-ignore
56
+ pastedValueParser: value => new Date(value)
55
57
  });
56
58
  export const GRID_DATETIME_COL_DEF = _extends({}, GRID_STRING_COL_DEF, {
57
59
  type: 'dateTime',
@@ -59,5 +61,7 @@ export const GRID_DATETIME_COL_DEF = _extends({}, GRID_STRING_COL_DEF, {
59
61
  valueFormatter: gridDateTimeFormatter,
60
62
  filterOperators: getGridDateOperators(true),
61
63
  renderEditCell: renderEditDateCell,
62
- getApplyQuickFilterFn: undefined
64
+ getApplyQuickFilterFn: undefined,
65
+ // @ts-ignore
66
+ pastedValueParser: value => new Date(value)
63
67
  });
@@ -51,5 +51,25 @@ export const GRID_SINGLE_SELECT_COL_DEF = _extends({}, GRID_STRING_COL_DEF, {
51
51
  return valueOption ? colDef.getOptionLabel(valueOption) : '';
52
52
  },
53
53
  renderEditCell: renderEditSingleSelectCell,
54
- filterOperators: getGridSingleSelectOperators()
54
+ filterOperators: getGridSingleSelectOperators(),
55
+ // @ts-ignore
56
+ pastedValueParser: (value, params) => {
57
+ const colDef = params.colDef;
58
+ const colDefValueOptions = colDef.valueOptions;
59
+ const valueOptions = typeof colDefValueOptions === 'function' ? colDefValueOptions({
60
+ field: colDef.field
61
+ }) : colDefValueOptions || [];
62
+ const getOptionValue = colDef.getOptionValue;
63
+ const valueOption = valueOptions.find(option => {
64
+ if (getOptionValue(option) === value) {
65
+ return true;
66
+ }
67
+ return false;
68
+ });
69
+ if (valueOption) {
70
+ return value;
71
+ }
72
+ // do not paste the value if it is not in the valueOptions
73
+ return undefined;
74
+ }
55
75
  });
@@ -89,7 +89,8 @@ function GridBody(props) {
89
89
  apiRef.current.register('private', {
90
90
  columnHeadersContainerElementRef: columnsContainerRef,
91
91
  columnHeadersElementRef: columnHeadersRef,
92
- virtualScrollerRef
92
+ virtualScrollerRef,
93
+ mainElementRef: rootRef
93
94
  });
94
95
  const hasDimensions = !!apiRef.current.getRootDimensions();
95
96
  return /*#__PURE__*/_jsxs(GridMainContainer, {
@@ -149,6 +149,7 @@ export const GridRootStyles = styled('div', {
149
149
  outline: 'none',
150
150
  height: '100%',
151
151
  display: 'flex',
152
+ overflow: 'hidden',
152
153
  flexDirection: 'column',
153
154
  overflowAnchor: 'none',
154
155
  // Keep the same scrolling position
@@ -4,7 +4,6 @@ const _excluded = ["item", "applyValue", "type", "apiRef", "focusElementRef", "c
4
4
  import * as React from 'react';
5
5
  import PropTypes from 'prop-types';
6
6
  import Autocomplete, { createFilterOptions } from '@mui/material/Autocomplete';
7
- import Chip from '@mui/material/Chip';
8
7
  import { unstable_useId as useId } from '@mui/utils';
9
8
  import { isSingleSelectColDef } from './filterPanelUtils';
10
9
  import { useGridRootProps } from '../../../hooks/utils/useGridRootProps';
@@ -98,7 +97,7 @@ function GridFilterInputMultipleSingleSelect(props) {
98
97
  value: filteredValues,
99
98
  onChange: handleChange,
100
99
  getOptionLabel: getOptionLabel,
101
- renderTags: (value, getTagProps) => value.map((option, index) => /*#__PURE__*/_jsx(Chip, _extends({
100
+ renderTags: (value, getTagProps) => value.map((option, index) => /*#__PURE__*/_jsx(rootProps.slots.baseChip, _extends({
102
101
  variant: "outlined",
103
102
  size: "small",
104
103
  label: getOptionLabel(option)
@@ -4,7 +4,6 @@ const _excluded = ["item", "applyValue", "type", "apiRef", "focusElementRef", "c
4
4
  import * as React from 'react';
5
5
  import PropTypes from 'prop-types';
6
6
  import Autocomplete from '@mui/material/Autocomplete';
7
- import Chip from '@mui/material/Chip';
8
7
  import { unstable_useId as useId } from '@mui/utils';
9
8
  import { useGridRootProps } from '../../../hooks/utils/useGridRootProps';
10
9
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -56,7 +55,7 @@ function GridFilterInputMultipleValue(props) {
56
55
  id: id,
57
56
  value: filterValueState,
58
57
  onChange: handleChange,
59
- renderTags: (value, getTagProps) => value.map((option, index) => /*#__PURE__*/_jsx(Chip, _extends({
58
+ renderTags: (value, getTagProps) => value.map((option, index) => /*#__PURE__*/_jsx(rootProps.slots.baseChip, _extends({
60
59
  variant: "outlined",
61
60
  size: "small",
62
61
  label: option
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { GridCellIndexCoordinates, GridScrollParams, GridColDef, GridCellCoordinates, GridCellParams } from '../../../models';
2
+ import { GridCellIndexCoordinates, GridScrollParams, GridColDef, GridCellCoordinates, GridCellParams, GridEditMode } from '../../../models';
3
3
  import { GridInitialStateCommunity } from '../../../models/gridStateCommunity';
4
4
  import { GridExportStateParams, GridRestoreStatePreProcessingContext, GridRestoreStatePreProcessingValue } from '../../features/statePersistence/gridStatePersistenceInterface';
5
5
  import { GridHydrateColumnsValue } from '../../features/columns/gridColumnsInterfaces';
@@ -64,6 +64,17 @@ export interface GridPipeProcessingLookup {
64
64
  cell: GridCellParams | null;
65
65
  };
66
66
  };
67
+ clipboardCopy: {
68
+ value: string;
69
+ };
70
+ canStartEditing: {
71
+ value: boolean;
72
+ context: {
73
+ event: React.KeyboardEvent;
74
+ cellParams: GridCellParams;
75
+ editMode: GridEditMode;
76
+ };
77
+ };
67
78
  }
68
79
  export type GridPipeProcessor<P extends GridPipeProcessorGroup> = (value: GridPipeProcessingLookup[P]['value'], context: GridPipeProcessingLookup[P] extends {
69
80
  context: any;
@@ -1,7 +1,8 @@
1
1
  import * as React from 'react';
2
2
  import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity';
3
+ import type { DataGridProcessedProps } from '../../../models/props/DataGridProps';
3
4
  /**
4
5
  * @requires useGridCsvExport (method)
5
6
  * @requires useGridSelection (method)
6
7
  */
7
- export declare const useGridClipboard: (apiRef: React.MutableRefObject<GridPrivateApiCommunity>) => void;
8
+ export declare const useGridClipboard: (apiRef: React.MutableRefObject<GridPrivateApiCommunity>, props: Pick<DataGridProcessedProps, 'unstable_ignoreValueFormatterDuringExport' | 'onClipboardCopy' | 'clipboardCopyCellDelimiter'>) => void;
@@ -1,5 +1,7 @@
1
1
  import * as React from 'react';
2
- import { useGridApiMethod, useGridNativeEventListener } from '../../utils';
2
+ import { useGridApiOptionHandler, useGridNativeEventListener } from '../../utils';
3
+ import { gridFocusCellSelector } from '../focus/gridFocusStateSelector';
4
+ import { serializeCellValue } from '../export/serializers/csvSerializer';
3
5
  function writeToClipboardPolyfill(data) {
4
6
  const span = document.createElement('span');
5
7
  span.style.whiteSpace = 'pre';
@@ -18,6 +20,15 @@ function writeToClipboardPolyfill(data) {
18
20
  document.body.removeChild(span);
19
21
  }
20
22
  }
23
+ function copyToClipboard(data) {
24
+ if (navigator.clipboard) {
25
+ navigator.clipboard.writeText(data).catch(() => {
26
+ writeToClipboardPolyfill(data);
27
+ });
28
+ } else {
29
+ writeToClipboardPolyfill(data);
30
+ }
31
+ }
21
32
  function hasNativeSelection(element) {
22
33
  var _window$getSelection;
23
34
  // When getSelection is called on an <iframe> that is not displayed Firefox will return null.
@@ -38,24 +49,11 @@ function hasNativeSelection(element) {
38
49
  * @requires useGridCsvExport (method)
39
50
  * @requires useGridSelection (method)
40
51
  */
41
- export const useGridClipboard = apiRef => {
42
- const copySelectedRowsToClipboard = React.useCallback(() => {
43
- if (apiRef.current.getSelectedRows().size === 0) {
44
- return;
45
- }
46
- const data = apiRef.current.getDataAsCsv({
47
- includeHeaders: false,
48
- delimiter: '\t'
49
- });
50
- if (navigator.clipboard) {
51
- navigator.clipboard.writeText(data).catch(() => {
52
- writeToClipboardPolyfill(data);
53
- });
54
- } else {
55
- writeToClipboardPolyfill(data);
56
- }
57
- }, [apiRef]);
58
- const handleKeydown = React.useCallback(event => {
52
+ export const useGridClipboard = (apiRef, props) => {
53
+ const ignoreValueFormatterProp = props.unstable_ignoreValueFormatterDuringExport;
54
+ const ignoreValueFormatter = (typeof ignoreValueFormatterProp === 'object' ? ignoreValueFormatterProp == null ? void 0 : ignoreValueFormatterProp.clipboardExport : ignoreValueFormatterProp) || false;
55
+ const clipboardCopyCellDelimiter = props.clipboardCopyCellDelimiter;
56
+ const handleCopy = React.useCallback(event => {
59
57
  const isModifierKeyPressed = event.ctrlKey || event.metaKey;
60
58
  // event.code === 'KeyC' is not enough as event.code assume a QWERTY keyboard layout which would
61
59
  // be wrong with a Dvorak keyboard (as if pressing J).
@@ -67,11 +65,30 @@ export const useGridClipboard = apiRef => {
67
65
  if (hasNativeSelection(event.target)) {
68
66
  return;
69
67
  }
70
- apiRef.current.unstable_copySelectedRowsToClipboard();
71
- }, [apiRef]);
72
- useGridNativeEventListener(apiRef, apiRef.current.rootElementRef, 'keydown', handleKeydown);
73
- const clipboardApi = {
74
- unstable_copySelectedRowsToClipboard: copySelectedRowsToClipboard
75
- };
76
- useGridApiMethod(apiRef, clipboardApi, 'public');
68
+ let textToCopy = '';
69
+ const selectedRows = apiRef.current.getSelectedRows();
70
+ if (selectedRows.size > 0) {
71
+ textToCopy = apiRef.current.getDataAsCsv({
72
+ includeHeaders: false,
73
+ // TODO: make it configurable
74
+ delimiter: clipboardCopyCellDelimiter
75
+ });
76
+ } else {
77
+ const focusedCell = gridFocusCellSelector(apiRef);
78
+ if (focusedCell) {
79
+ const cellParams = apiRef.current.getCellParams(focusedCell.id, focusedCell.field);
80
+ textToCopy = serializeCellValue(cellParams, {
81
+ delimiterCharacter: clipboardCopyCellDelimiter,
82
+ ignoreValueFormatter
83
+ });
84
+ }
85
+ }
86
+ textToCopy = apiRef.current.unstable_applyPipeProcessors('clipboardCopy', textToCopy);
87
+ if (textToCopy) {
88
+ copyToClipboard(textToCopy);
89
+ apiRef.current.publishEvent('clipboardCopy', textToCopy);
90
+ }
91
+ }, [apiRef, ignoreValueFormatter, clipboardCopyCellDelimiter]);
92
+ useGridNativeEventListener(apiRef, apiRef.current.rootElementRef, 'keydown', handleCopy);
93
+ useGridApiOptionHandler(apiRef, 'clipboardCopy', props.onClipboardCopy);
77
94
  };
@@ -10,7 +10,6 @@ import { getVisibleRows } from '../../utils/useGridVisibleRows';
10
10
  import { gridRowsMetaSelector } from '../rows/gridRowsMetaSelector';
11
11
  import { calculatePinnedRowsHeight } from '../rows/gridRowsUtils';
12
12
  import { getTotalHeaderHeight } from '../columns/gridColumnsUtils';
13
- import { gridClasses } from '../../../constants/gridClasses';
14
13
  const isTestEnvironment = process.env.NODE_ENV === 'test';
15
14
  const hasScroll = ({
16
15
  content,
@@ -151,9 +150,8 @@ export function useGridDimensions(apiRef, props) {
151
150
  return Math.min(maximumPageSizeWithoutScrollBar, currentPage.rows.length);
152
151
  }, [apiRef, props.pagination, props.paginationMode, props.getRowHeight, rowHeight]);
153
152
  const computeSizeAndPublishResizeEvent = React.useCallback(() => {
154
- var _apiRef$current$rootE2, _previousSize$current, _previousSize$current2;
155
- const rootEl = (_apiRef$current$rootE2 = apiRef.current.rootElementRef) == null ? void 0 : _apiRef$current$rootE2.current;
156
- const mainEl = rootEl == null ? void 0 : rootEl.querySelector(`.${gridClasses.main}`);
153
+ var _apiRef$current$mainE, _previousSize$current, _previousSize$current2;
154
+ const mainEl = (_apiRef$current$mainE = apiRef.current.mainElementRef) == null ? void 0 : _apiRef$current$mainE.current;
157
155
  if (!mainEl) {
158
156
  return;
159
157
  }
@@ -90,10 +90,14 @@ export const useGridCellEditing = (apiRef, props) => {
90
90
  }
91
91
  } else if (params.isEditable) {
92
92
  let reason;
93
- if (event.key === ' ') {
94
- return; // Space scrolls to the last row
93
+ const canStartEditing = apiRef.current.unstable_applyPipeProcessors('canStartEditing', true, {
94
+ event,
95
+ cellParams: params,
96
+ editMode: 'cell'
97
+ });
98
+ if (!canStartEditing) {
99
+ return;
95
100
  }
96
-
97
101
  if (isPrintableKey(event)) {
98
102
  reason = GridCellEditStartReasons.printableKeyDown;
99
103
  } else if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
@@ -144,10 +144,14 @@ export const useGridRowEditing = (apiRef, props) => {
144
144
  }
145
145
  } else if (params.isEditable) {
146
146
  let reason;
147
- if (event.key === ' ') {
148
- return; // Space scrolls to the last row
147
+ const canStartEditing = apiRef.current.unstable_applyPipeProcessors('canStartEditing', true, {
148
+ event,
149
+ cellParams: params,
150
+ editMode: 'row'
151
+ });
152
+ if (!canStartEditing) {
153
+ return;
149
154
  }
150
-
151
155
  if (isPrintableKey(event)) {
152
156
  reason = GridRowEditStartReasons.printableKeyDown;
153
157
  } else if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
@@ -1,12 +1,17 @@
1
1
  import { GridRowId } from '../../../../models';
2
2
  import { GridCellParams } from '../../../../models/params/gridCellParams';
3
3
  import { GridStateColDef } from '../../../../models/colDef/gridColDef';
4
+ export declare const serializeCellValue: (cellParams: GridCellParams, options: {
5
+ delimiterCharacter: string;
6
+ ignoreValueFormatter: boolean;
7
+ }) => any;
4
8
  interface BuildCSVOptions {
5
9
  columns: GridStateColDef[];
6
10
  rowIds: GridRowId[];
7
11
  getCellParams: (id: GridRowId, field: string) => GridCellParams;
8
12
  delimiterCharacter: string;
9
13
  includeHeaders: boolean;
14
+ ignoreValueFormatter: boolean;
10
15
  }
11
16
  export declare function buildCSV(options: BuildCSVOptions): string;
12
17
  export {};
@@ -1,6 +1,6 @@
1
1
  import { GRID_CHECKBOX_SELECTION_COL_DEF } from '../../../../colDef';
2
2
  import { buildWarning } from '../../../../utils/warning';
3
- const serializeCellValue = (value, delimiterCharacter) => {
3
+ function sanitizeCellValue(value, delimiterCharacter) {
4
4
  if (typeof value === 'string') {
5
5
  const formattedValue = value.replace(/"/g, '""');
6
6
 
@@ -11,16 +11,49 @@ const serializeCellValue = (value, delimiterCharacter) => {
11
11
  return formattedValue;
12
12
  }
13
13
  return value;
14
+ }
15
+ export const serializeCellValue = (cellParams, options) => {
16
+ const {
17
+ delimiterCharacter,
18
+ ignoreValueFormatter
19
+ } = options;
20
+ let value;
21
+ if (ignoreValueFormatter) {
22
+ var _cellParams$value2;
23
+ const columnType = cellParams.colDef.type;
24
+ if (columnType === 'number') {
25
+ value = String(cellParams.value);
26
+ } else if (columnType === 'date' || columnType === 'dateTime') {
27
+ var _cellParams$value;
28
+ value = (_cellParams$value = cellParams.value) == null ? void 0 : _cellParams$value.toISOString();
29
+ } else if (typeof ((_cellParams$value2 = cellParams.value) == null ? void 0 : _cellParams$value2.toString) === 'function') {
30
+ value = cellParams.value.toString();
31
+ } else {
32
+ value = cellParams.value;
33
+ }
34
+ } else {
35
+ value = cellParams.formattedValue;
36
+ }
37
+ return sanitizeCellValue(value, delimiterCharacter);
14
38
  };
15
39
  const objectFormattedValueWarning = buildWarning(['MUI: When the value of a field is an object or a `renderCell` is provided, the CSV export might not display the value correctly.', 'You can provide a `valueFormatter` with a string representation to be used.']);
16
- const serializeRow = (id, columns, getCellParams, delimiterCharacter) => columns.map(column => {
40
+ const serializeRow = ({
41
+ id,
42
+ columns,
43
+ getCellParams,
44
+ delimiterCharacter,
45
+ ignoreValueFormatter
46
+ }) => columns.map(column => {
17
47
  const cellParams = getCellParams(id, column.field);
18
48
  if (process.env.NODE_ENV !== 'production') {
19
49
  if (String(cellParams.formattedValue) === '[object Object]') {
20
50
  objectFormattedValueWarning();
21
51
  }
22
52
  }
23
- return serializeCellValue(cellParams.formattedValue, delimiterCharacter);
53
+ return serializeCellValue(cellParams, {
54
+ delimiterCharacter,
55
+ ignoreValueFormatter
56
+ });
24
57
  });
25
58
  export function buildCSV(options) {
26
59
  const {
@@ -28,12 +61,19 @@ export function buildCSV(options) {
28
61
  rowIds,
29
62
  getCellParams,
30
63
  delimiterCharacter,
31
- includeHeaders
64
+ includeHeaders,
65
+ ignoreValueFormatter
32
66
  } = options;
33
- const CSVBody = rowIds.reduce((acc, id) => `${acc}${serializeRow(id, columns, getCellParams, delimiterCharacter).join(delimiterCharacter)}\r\n`, '').trim();
67
+ const CSVBody = rowIds.reduce((acc, id) => `${acc}${serializeRow({
68
+ id,
69
+ columns,
70
+ getCellParams,
71
+ delimiterCharacter,
72
+ ignoreValueFormatter
73
+ }).join(delimiterCharacter)}\r\n`, '').trim();
34
74
  if (!includeHeaders) {
35
75
  return CSVBody;
36
76
  }
37
- const CSVHead = `${columns.filter(column => column.field !== GRID_CHECKBOX_SELECTION_COL_DEF.field).map(column => serializeCellValue(column.headerName || column.field, delimiterCharacter)).join(delimiterCharacter)}\r\n`;
77
+ const CSVHead = `${columns.filter(column => column.field !== GRID_CHECKBOX_SELECTION_COL_DEF.field).map(column => sanitizeCellValue(column.headerName || column.field, delimiterCharacter)).join(delimiterCharacter)}\r\n`;
38
78
  return `${CSVHead}${CSVBody}`.trim();
39
79
  }
@@ -1,5 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity';
3
+ import type { DataGridProcessedProps } from '../../../models/props/DataGridProps';
3
4
  /**
4
5
  * @requires useGridColumns (state)
5
6
  * @requires useGridFilter (state)
@@ -7,4 +8,4 @@ import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity';
7
8
  * @requires useGridSelection (state)
8
9
  * @requires useGridParamsApi (method)
9
10
  */
10
- export declare const useGridCsvExport: (apiRef: React.MutableRefObject<GridPrivateApiCommunity>) => void;
11
+ export declare const useGridCsvExport: (apiRef: React.MutableRefObject<GridPrivateApiCommunity>, props: Pick<DataGridProcessedProps, 'unstable_ignoreValueFormatterDuringExport'>) => void;
@@ -6,7 +6,7 @@ import { buildCSV } from './serializers/csvSerializer';
6
6
  import { getColumnsToExport, defaultGetRowsToExport } from './utils';
7
7
  import { useGridRegisterPipeProcessor } from '../../core/pipeProcessing';
8
8
  import { GridCsvExportMenuItem } from '../../../components/toolbar/GridToolbarExport';
9
-
9
+ import { jsx as _jsx } from "react/jsx-runtime";
10
10
  /**
11
11
  * @requires useGridColumns (state)
12
12
  * @requires useGridFilter (state)
@@ -14,9 +14,10 @@ import { GridCsvExportMenuItem } from '../../../components/toolbar/GridToolbarEx
14
14
  * @requires useGridSelection (state)
15
15
  * @requires useGridParamsApi (method)
16
16
  */
17
- import { jsx as _jsx } from "react/jsx-runtime";
18
- export const useGridCsvExport = apiRef => {
17
+ export const useGridCsvExport = (apiRef, props) => {
19
18
  const logger = useGridLogger(apiRef, 'useGridCsvExport');
19
+ const ignoreValueFormatterProp = props.unstable_ignoreValueFormatterDuringExport;
20
+ const ignoreValueFormatter = (typeof ignoreValueFormatterProp === 'object' ? ignoreValueFormatterProp == null ? void 0 : ignoreValueFormatterProp.csvExport : ignoreValueFormatterProp) || false;
20
21
  const getDataAsCsv = React.useCallback((options = {}) => {
21
22
  var _options$getRowsToExp, _options$includeHeade;
22
23
  logger.debug(`Get data as CSV`);
@@ -33,9 +34,10 @@ export const useGridCsvExport = apiRef => {
33
34
  rowIds: exportedRowIds,
34
35
  getCellParams: apiRef.current.getCellParams,
35
36
  delimiterCharacter: options.delimiter || ',',
36
- includeHeaders: (_options$includeHeade = options.includeHeaders) != null ? _options$includeHeade : true
37
+ includeHeaders: (_options$includeHeade = options.includeHeaders) != null ? _options$includeHeade : true,
38
+ ignoreValueFormatter
37
39
  });
38
- }, [logger, apiRef]);
40
+ }, [logger, apiRef, ignoreValueFormatter]);
39
41
  const exportDataAsCsv = React.useCallback(options => {
40
42
  logger.debug(`Export data as CSV`);
41
43
  const csv = getDataAsCsv(options);
@@ -14,6 +14,7 @@ import { gridPinnedRowsSelector } from '../rows/gridRowsSelector';
14
14
  import { unstable_gridFocusColumnGroupHeaderSelector } from '../focus';
15
15
  import { gridColumnGroupsHeaderMaxDepthSelector } from '../columnGrouping/gridColumnGroupsSelector';
16
16
  import { useGridSelector } from '../../utils/useGridSelector';
17
+ import { useGridRegisterPipeProcessor } from '../../core/pipeProcessing';
17
18
  function enrichPageRowsWithPinnedRows(apiRef, rows) {
18
19
  const pinnedRows = gridPinnedRowsSelector(apiRef) || {};
19
20
  return [...(pinnedRows.top || []), ...rows, ...(pinnedRows.bottom || [])];
@@ -450,6 +451,16 @@ export const useGridKeyboardNavigation = (apiRef, props) => {
450
451
  event.preventDefault();
451
452
  }
452
453
  }, [apiRef, currentPageRows, theme.direction, getRowIdFromIndex, goToCell, goToHeader]);
454
+ const checkIfCanStartEditing = React.useCallback((initialValue, {
455
+ event
456
+ }) => {
457
+ if (event.key === ' ') {
458
+ // Space scrolls to the last row
459
+ return false;
460
+ }
461
+ return initialValue;
462
+ }, []);
463
+ useGridRegisterPipeProcessor(apiRef, 'canStartEditing', checkIfCanStartEditing);
453
464
  useGridApiEventHandler(apiRef, 'columnHeaderKeyDown', handleColumnHeaderKeyDown);
454
465
  useGridApiEventHandler(apiRef, 'columnGroupHeaderKeyDown', handleColumnGroupHeaderKeyDown);
455
466
  useGridApiEventHandler(apiRef, 'cellKeyDown', handleCellKeyDown);
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v6.3.1
2
+ * @mui/x-data-grid v6.4.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the