Skip to content

Commit

Permalink
Move renderers to separate files to enable easier copy of the relevan…
Browse files Browse the repository at this point in the history
…t code
  • Loading branch information
arminmeh committed Jul 8, 2024
1 parent 6f338a2 commit a4d4b83
Show file tree
Hide file tree
Showing 10 changed files with 797 additions and 1,424 deletions.
705 changes: 9 additions & 696 deletions docs/data/data-grid/custom-columns/CustomColumnFullExample.js

Large diffs are not rendered by default.

736 changes: 8 additions & 728 deletions docs/data/data-grid/custom-columns/CustomColumnFullExample.tsx

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions docs/data/data-grid/custom-columns/renderers/avatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Avatar from '@mui/material/Avatar';
import { GridRenderCellParams } from '@mui/x-data-grid';

export function renderAvatar(
params: GridRenderCellParams<{ name: string; color: string }, any, any>,
) {
if (params.value == null) {
return '';
}

return (
<Avatar style={{ backgroundColor: params.value.color }}>
{params.value.name.toUpperCase().substring(0, 1)}
</Avatar>
);
}
144 changes: 144 additions & 0 deletions docs/data/data-grid/custom-columns/renderers/country.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import * as React from 'react';
import {
GridRenderCellParams,
GridRenderEditCellParams,
useGridApiContext,
} from '@mui/x-data-grid';
import {
COUNTRY_ISO_OPTIONS,
CountryIsoOption,
} from '@mui/x-data-grid-generator/services/static-data';
import {
Autocomplete,
autocompleteClasses,
AutocompleteProps,
Box,
InputBase,
styled,
} from '@mui/material';

interface CountryProps {
value: CountryIsoOption;
}

const Country = React.memo(function Country(props: CountryProps) {
const { value } = props;

return (
<Box
sx={{
width: '100%',
display: 'flex',
alignItems: 'center',
'& > img': {
mr: 0.5,
flexShrink: 0,
width: '20px',
},
}}
>
<img
loading="lazy"
width="20"
src={`https://flagcdn.com/w20/${value.code.toLowerCase()}.png`}
srcSet={`https://flagcdn.com/w40/${value.code.toLowerCase()}.png 2x`}
alt=""
/>
<Box component="span" sx={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>
{value.label}
</Box>
</Box>
);
});

const StyledAutocomplete = styled(Autocomplete)(({ theme }) => ({
height: '100%',
[`& .${autocompleteClasses.inputRoot}`]: {
...theme.typography.body2,
padding: '1px 0',
height: '100%',
'& input': {
padding: '0 16px',
height: '100%',
},
},
})) as typeof Autocomplete;

function EditCountry(props: GridRenderEditCellParams<CountryIsoOption>) {
const { id, value, field } = props;

const apiRef = useGridApiContext();

const handleChange = React.useCallback<
NonNullable<AutocompleteProps<CountryIsoOption, false, true, false>['onChange']>
>(
async (event, newValue) => {
await apiRef.current.setEditCellValue({ id, field, value: newValue }, event);
apiRef.current.stopCellEditMode({ id, field });
},
[apiRef, field, id],
);

return (
<StyledAutocomplete<CountryIsoOption, false, true, false>
value={value}
onChange={handleChange}
options={COUNTRY_ISO_OPTIONS}
getOptionLabel={(option: any) => option.label}
autoHighlight
fullWidth
open
disableClearable
renderOption={(optionProps, option: any) => (
<Box
component="li"
sx={{
'& > img': {
mr: 1.5,
flexShrink: 0,
},
}}
{...optionProps}
key={option.code}
>
<img
loading="lazy"
width="20"
src={`https://flagcdn.com/w20/${option.code.toLowerCase()}.png`}
srcSet={`https://flagcdn.com/w40/${option.code.toLowerCase()}.png 2x`}
alt=""
/>
{option.label}
</Box>
)}
renderInput={(params) => (
<InputBase
autoFocus
fullWidth
id={params.id}
inputProps={{
...params.inputProps,
autoComplete: 'new-password', // disable autocomplete and autofill
}}
{...params.InputProps}
/>
)}
/>
);
}

export function renderCountry(
params: GridRenderCellParams<CountryIsoOption, any, any>,
) {
if (params.value == null) {
return '';
}

return <Country value={params.value} />;
}

export function renderEditCountry(
params: GridRenderEditCellParams<CountryIsoOption>,
) {
return <EditCountry {...params} />;
}
39 changes: 39 additions & 0 deletions docs/data/data-grid/custom-columns/renderers/email.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import * as React from 'react';
import { styled } from '@mui/material';
import { GridRenderCellParams } from '@mui/x-data-grid';

interface DemoLinkProps {
href: string;
children: string;
tabIndex: number;
}

const Link = styled('a')({
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
overflow: 'hidden',
color: 'inherit',
});

const DemoLink = React.memo(function DemoLink(props: DemoLinkProps) {
const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();
event.stopPropagation();
};

return (
<Link tabIndex={props.tabIndex} onClick={handleClick} href={props.href}>
{props.children}
</Link>
);
});

export function renderEmail(params: GridRenderCellParams<any, string, any>) {
const email = params.value ?? '';

return (
<DemoLink href={`mailto:${email}`} tabIndex={params.tabIndex}>
{email}
</DemoLink>
);
}
110 changes: 110 additions & 0 deletions docs/data/data-grid/custom-columns/renderers/incoterm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import * as React from 'react';
import {
Box,
ListItemIcon,
ListItemText,
MenuItem,
MenuProps,
Select,
SelectProps,
Tooltip,
} from '@mui/material';
import InfoIcon from '@mui/icons-material/Info';
import {
GridRenderCellParams,
GridRenderEditCellParams,
useGridApiContext,
} from '@mui/x-data-grid';
import { INCOTERM_OPTIONS } from '@mui/x-data-grid-generator/services/static-data';

interface IncotermProps {
value: string | null | undefined;
}

const Incoterm = React.memo(function Incoterm(props: IncotermProps) {
const { value } = props;

if (!value) {
return null;
}

const valueStr = value.toString();
const tooltip = valueStr.slice(valueStr.indexOf('(') + 1, valueStr.indexOf(')'));
const code = valueStr.slice(0, valueStr.indexOf('(')).trim();

return (
<Box
sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}
>
<span>{code}</span>
<Tooltip title={tooltip}>
<InfoIcon sx={{ color: '#2196f3', alignSelf: 'center', ml: '8px' }} />
</Tooltip>
</Box>
);
});

function EditIncoterm(props: GridRenderEditCellParams<any, string | null>) {
const { id, value, field } = props;

const apiRef = useGridApiContext();

const handleChange: SelectProps['onChange'] = async (event) => {
await apiRef.current.setEditCellValue(
{ id, field, value: event.target.value as any },
event,
);
apiRef.current.stopCellEditMode({ id, field });
};

const handleClose: MenuProps['onClose'] = (event, reason) => {
if (reason === 'backdropClick') {
apiRef.current.stopCellEditMode({ id, field });
}
};

return (
<Select
value={value}
onChange={handleChange}
MenuProps={{
onClose: handleClose,
}}
sx={{
height: '100%',
'& .MuiSelect-select': {
display: 'flex',
alignItems: 'center',
pl: 1,
},
}}
autoFocus
fullWidth
open
>
{INCOTERM_OPTIONS.map((option) => {
const tooltip = option.slice(option.indexOf('(') + 1, option.indexOf(')'));
const code = option.slice(0, option.indexOf('(')).trim();

return (
<MenuItem key={option} value={option}>
<ListItemIcon sx={{ minWidth: 36 }}>{code}</ListItemIcon>
<ListItemText primary={tooltip} sx={{ overflow: 'hidden' }} />
</MenuItem>
);
})}
</Select>
);
}

export function renderIncoterm(
params: GridRenderCellParams<any, string | null, any>,
) {
return <Incoterm value={params.value} />;
}

export function renderEditIncoterm(
params: GridRenderEditCellParams<any, string | null>,
) {
return <EditIncoterm {...params} />;
}
Loading

0 comments on commit a4d4b83

Please sign in to comment.