Skip to content

Commit

Permalink
Merge
Browse files Browse the repository at this point in the history
  • Loading branch information
flaviendelangle committed Oct 29, 2024
2 parents f49dc88 + 365da92 commit 31a152d
Show file tree
Hide file tree
Showing 63 changed files with 639 additions and 150 deletions.
3 changes: 2 additions & 1 deletion docs/data/data-grid/column-definition/AutogeneratedRows.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import * as React from 'react';
import {
DataGridPremium,
GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
isAutogeneratedRow,
useGridApiRef,
useKeepGroupedColumnsHidden,
} from '@mui/x-data-grid-premium';
import { useMovieData } from '@mui/x-data-grid-generator';

const columns = [
{ field: '__row_group_by_columns_group__', width: 200 },
{ field: GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, width: 200 },
{ field: 'company', width: 200 },
{
field: 'title',
Expand Down
3 changes: 2 additions & 1 deletion docs/data/data-grid/column-definition/AutogeneratedRows.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import {
DataGridPremium,
GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
GridColDef,
isAutogeneratedRow,
useGridApiRef,
Expand All @@ -9,7 +10,7 @@ import {
import { useMovieData } from '@mui/x-data-grid-generator';

const columns: GridColDef[] = [
{ field: '__row_group_by_columns_group__', width: 200 },
{ field: GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, width: 200 },
{ field: 'company', width: 200 },
{
field: 'title',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import {
GridToolbar,
useKeepGroupedColumnsHidden,
useGridApiRef,
GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
} from '@mui/x-data-grid-premium';
import { useDemoData } from '@mui/x-data-grid-generator';

const hiddenFields = ['id', '__row_group_by_columns_group__', 'status'];
const hiddenFields = ['id', GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, 'status'];

const getTogglableColumns = (columns) => {
return columns
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import {
GridColDef,
useKeepGroupedColumnsHidden,
useGridApiRef,
GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
} from '@mui/x-data-grid-premium';
import { useDemoData } from '@mui/x-data-grid-generator';

const hiddenFields = ['id', '__row_group_by_columns_group__', 'status'];
const hiddenFields = ['id', GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, 'status'];

const getTogglableColumns = (columns: GridColDef[]) => {
return columns
Expand Down
11 changes: 8 additions & 3 deletions docs/data/data-grid/column-visibility/column-visibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,21 @@ In the following demo, the columns panel is disabled, and access to columns `id`
To show or hide specific columns in the column visibility panel, use the `slotProps.columnsManagement.getTogglableColumns` prop. It should return an array of column field names.

```tsx
// stop `id`, `__row_group_by_columns_group__`, and `status` columns to be togglable
const hiddenFields = ['id', '__row_group_by_columns_group__', 'status'];
import {
DataGridPremium,
GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
} from '@mui/x-data-grid-premium';

// stop `id`, GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, and `status` columns to be togglable
const hiddenFields = ['id', GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, 'status'];

const getTogglableColumns = (columns: GridColDef[]) => {
return columns
.filter((column) => !hiddenFields.includes(column.field))
.map((column) => column.field);
};

<DataGrid
<DataGridPremium
slots={{
toolbar: GridToolbar,
}}
Expand Down
3 changes: 2 additions & 1 deletion docs/data/data-grid/overview/DataGridPremiumDemo.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import Box from '@mui/material/Box';
import {
DataGridPremium,
GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
GridToolbar,
useGridApiRef,
useKeepGroupedColumnsHidden,
Expand Down Expand Up @@ -40,7 +41,7 @@ export default function DataGridPremiumDemo() {
model: ['commodity'],
},
sorting: {
sortModel: [{ field: '__row_group_by_columns_group__', sort: 'asc' }],
sortModel: [{ field: GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, sort: 'asc' }],
},
aggregation: {
model: {
Expand Down
3 changes: 2 additions & 1 deletion docs/data/data-grid/overview/DataGridPremiumDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import Box from '@mui/material/Box';
import {
DataGridPremium,
GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
GridToolbar,
useGridApiRef,
useKeepGroupedColumnsHidden,
Expand Down Expand Up @@ -40,7 +41,7 @@ export default function DataGridPremiumDemo() {
model: ['commodity'],
},
sorting: {
sortModel: [{ field: '__row_group_by_columns_group__', sort: 'asc' }],
sortModel: [{ field: GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, sort: 'asc' }],
},
aggregation: {
model: {
Expand Down
3 changes: 2 additions & 1 deletion docs/data/data-grid/row-grouping/RowGroupingFullExample.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import {
DataGridPremium,
GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
useGridApiRef,
useKeepGroupedColumnsHidden,
} from '@mui/x-data-grid-premium';
Expand All @@ -23,7 +24,7 @@ export default function RowGroupingFullExample() {
model: ['commodity'],
},
sorting: {
sortModel: [{ field: '__row_group_by_columns_group__', sort: 'asc' }],
sortModel: [{ field: GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, sort: 'asc' }],
},
},
});
Expand Down
3 changes: 2 additions & 1 deletion docs/data/data-grid/row-grouping/RowGroupingFullExample.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import {
DataGridPremium,
GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
useGridApiRef,
useKeepGroupedColumnsHidden,
} from '@mui/x-data-grid-premium';
Expand All @@ -23,7 +24,7 @@ export default function RowGroupingFullExample() {
model: ['commodity'],
},
sorting: {
sortModel: [{ field: '__row_group_by_columns_group__', sort: 'asc' }],
sortModel: [{ field: GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, sort: 'asc' }],
},
},
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import * as React from 'react';
import dayjs from 'dayjs';
import { useRifm } from 'rifm';
import TextField from '@mui/material/TextField';
import useControlled from '@mui/utils/useControlled';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';

import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import { useSplitFieldProps, useParsedFormat } from '@mui/x-date-pickers/hooks';
import { useValidation, validateDate } from '@mui/x-date-pickers/validation';

const MASK_USER_INPUT_SYMBOL = '_';
const ACCEPT_REGEX = /[\d]/gi;

const staticDateWith2DigitTokens = dayjs('2019-11-21T11:30:00.000');
const staticDateWith1DigitTokens = dayjs('2019-01-01T09:00:00.000');

function getInputValueFromDate(date, format) {
const dateWithKnownAdapter = date;
if (dateWithKnownAdapter == null) {
return '';
}

return dateWithKnownAdapter.isValid() ? dateWithKnownAdapter.format(format) : '';
}

function MaskedField(props) {
const { slots, slotProps, ...other } = props;

const { forwardedProps, internalProps } = useSplitFieldProps(other, 'date');

const {
format,
value: valueProp,
defaultValue,
onChange,
timezone,
onError,
} = internalProps;

const [value, setValue] = useControlled({
controlled: valueProp,
default: defaultValue ?? null,
name: 'MaskedField',
state: 'value',
});

// Control the input text
const [inputValue, setInputValue] = React.useState(() =>
getInputValueFromDate(value, format),
);

React.useEffect(() => {
if (value && value.isValid()) {
const newDisplayDate = getInputValueFromDate(value, format);
setInputValue(newDisplayDate);
}
}, [format, value]);

const parsedFormat = useParsedFormat(internalProps);

const { hasValidationError, getValidationErrorForNewValue } = useValidation({
value,
timezone,
onError,
props: internalProps,
validator: validateDate,
});

const handleValueStrChange = (newValueStr) => {
setInputValue(newValueStr);

const newValue = dayjs(newValueStr, format);
setValue(newValue);

if (onChange) {
onChange(newValue, {
validationError: getValidationErrorForNewValue(newValue),
});
}
};

const rifmFormat = React.useMemo(() => {
const formattedDateWith1Digit = staticDateWith1DigitTokens.format(format);
const inferredFormatPatternWith1Digits = formattedDateWith1Digit.replace(
ACCEPT_REGEX,
MASK_USER_INPUT_SYMBOL,
);
const inferredFormatPatternWith2Digits = staticDateWith2DigitTokens
.format(format)
.replace(ACCEPT_REGEX, '_');

if (inferredFormatPatternWith1Digits !== inferredFormatPatternWith2Digits) {
throw new Error(
`Mask does not support numbers with variable length such as 'M'.`,
);
}

const maskToUse = inferredFormatPatternWith1Digits;

return function formatMaskedDate(valueToFormat) {
let outputCharIndex = 0;
return valueToFormat
.split('')
.map((character, characterIndex) => {
ACCEPT_REGEX.lastIndex = 0;

if (outputCharIndex > maskToUse.length - 1) {
return '';
}

const maskChar = maskToUse[outputCharIndex];
const nextMaskChar = maskToUse[outputCharIndex + 1];

const acceptedChar = ACCEPT_REGEX.test(character) ? character : '';
const formattedChar =
maskChar === MASK_USER_INPUT_SYMBOL
? acceptedChar
: maskChar + acceptedChar;

outputCharIndex += formattedChar.length;

const isLastCharacter = characterIndex === valueToFormat.length - 1;
if (
isLastCharacter &&
nextMaskChar &&
nextMaskChar !== MASK_USER_INPUT_SYMBOL
) {
// when cursor at the end of mask part (e.g. month) prerender next symbol "21" -> "21/"
return formattedChar ? formattedChar + nextMaskChar : '';
}

return formattedChar;
})
.join('');
};
}, [format]);

const rifmProps = useRifm({
value: inputValue,
onChange: handleValueStrChange,
format: rifmFormat,
});

return (
<TextField
placeholder={parsedFormat}
error={!!hasValidationError}
{...rifmProps}
{...forwardedProps}
/>
);
}

function MaskedFieldDatePicker(props) {
return <DatePicker slots={{ ...props.slots, field: MaskedField }} {...props} />;
}

export default function MaskedMaterialTextField() {
return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<MaskedFieldDatePicker />
</LocalizationProvider>
);
}
Loading

0 comments on commit 31a152d

Please sign in to comment.