@zesty-io/material 0.1.0 → 0.1.3
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/es/ConfirmDialog/ConfirmDialog.stories.d.ts +6 -0
- package/es/ConfirmDialog/ConfirmDialog.stories.js +24 -0
- package/es/ConfirmDialog/index.d.ts +18 -0
- package/es/ConfirmDialog/index.js +11 -0
- package/es/CopyButton/index.js +3 -3
- package/es/FieldTypeColor/index.d.ts +1 -1
- package/es/FieldTypeColor/index.js +12 -16
- package/es/FieldTypeDate/FieldTypeDate.stories.js +1 -4
- package/es/FieldTypeDate/index.d.ts +4 -6
- package/es/FieldTypeDate/index.js +4 -8
- package/es/FieldTypeDateTime/FieldTypeDateTime.stories.js +1 -4
- package/es/FieldTypeDateTime/index.d.ts +4 -6
- package/es/FieldTypeDateTime/index.js +4 -8
- package/es/FieldTypeDropdown/FieldTypeDropwdon.stories.js +2 -1
- package/es/FieldTypeDropdown/index.d.ts +1 -1
- package/es/FieldTypeDropdown/index.js +5 -10
- package/es/FieldTypeNumber/FieldTypeNumber.stories.js +1 -0
- package/es/FieldTypeNumber/index.d.ts +1 -1
- package/es/FieldTypeNumber/index.js +4 -7
- package/es/FieldTypeOneToMany/FieldTypeOneToMany.stories.d.ts +5 -0
- package/es/FieldTypeOneToMany/FieldTypeOneToMany.stories.js +28 -0
- package/es/FieldTypeOneToMany/index.d.ts +32 -0
- package/es/FieldTypeOneToMany/index.js +29 -0
- package/es/FieldTypeOneToOne/FieldTypeOneToOne.stories.d.ts +5 -0
- package/es/FieldTypeOneToOne/FieldTypeOneToOne.stories.js +28 -0
- package/es/FieldTypeOneToOne/index.d.ts +34 -0
- package/es/FieldTypeOneToOne/index.js +33 -0
- package/es/FieldTypeSort/FieldTypeSort.stories.js +1 -0
- package/es/FieldTypeSort/index.d.ts +1 -1
- package/es/FieldTypeSort/index.js +17 -27
- package/es/FieldTypeText/FieldTypeText.stories.js +4 -2
- package/es/FieldTypeText/index.d.ts +1 -1
- package/es/FieldTypeText/index.js +4 -12
- package/es/FieldTypeUrl/index.d.ts +1 -1
- package/es/FieldTypeUrl/index.js +8 -16
- package/es/index.d.ts +3 -1
- package/es/index.js +3 -1
- package/es/theme/index.js +10 -0
- package/es/utils/virtualization.d.ts +2 -0
- package/es/utils/virtualization.js +63 -0
- package/package.json +5 -3
- package/src/{ConfirmModal/ConfirmModal.stories.tsx → ConfirmDialog/ConfirmDialog.stories.tsx} +0 -0
- package/src/{ConfirmModal → ConfirmDialog}/index.tsx +0 -0
- package/src/CopyButton/index.tsx +6 -6
- package/src/FieldTypeColor/index.tsx +5 -7
- package/src/FieldTypeDate/FieldTypeDate.stories.tsx +1 -4
- package/src/FieldTypeDate/index.tsx +22 -25
- package/src/FieldTypeDateTime/FieldTypeDateTime.stories.tsx +1 -4
- package/src/FieldTypeDateTime/index.tsx +23 -25
- package/src/FieldTypeDropdown/FieldTypeDropwdon.stories.tsx +2 -1
- package/src/FieldTypeDropdown/index.tsx +5 -7
- package/src/FieldTypeNumber/FieldTypeNumber.stories.tsx +1 -0
- package/src/FieldTypeNumber/index.tsx +5 -6
- package/src/FieldTypeOneToMany/FieldTypeOneToMany.stories.tsx +47 -0
- package/src/FieldTypeOneToMany/index.tsx +90 -0
- package/src/FieldTypeOneToOne/FieldTypeOneToOne.stories.tsx +46 -0
- package/src/FieldTypeOneToOne/index.tsx +96 -0
- package/src/FieldTypeSort/FieldTypeSort.stories.tsx +1 -0
- package/src/FieldTypeSort/index.tsx +9 -18
- package/src/FieldTypeText/FieldTypeText.stories.tsx +9 -5
- package/src/FieldTypeText/index.tsx +11 -18
- package/src/FieldTypeUrl/index.tsx +11 -18
- package/src/index.ts +3 -1
- package/src/theme/index.ts +10 -0
- package/src/utils/virtualization.tsx +107 -0
|
@@ -1,15 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import MuiTextField from '@mui/material/TextField';
|
|
3
|
-
import {
|
|
4
|
-
const FieldTypeText = ({ maxLength = 150, value, helperText,
|
|
5
|
-
return (_jsx(MuiTextField, { size: "small", variant: 'outlined', value: value,
|
|
6
|
-
endAdornment: (_jsx(InputAdornment, { position: "end", children: _jsxs(_Fragment, { children: [value.length, "/", maxLength] }) })),
|
|
7
|
-
// Spread props at the end to allow Input prop overrides
|
|
8
|
-
...InputProps,
|
|
9
|
-
}, InputLabelProps: {
|
|
10
|
-
shrink: true,
|
|
11
|
-
// Spread props at the end to allow InputLabel prop overrides
|
|
12
|
-
...InputLabelProps,
|
|
13
|
-
}, error: value.length > maxLength, helperText: value.length > maxLength ? 'Your input is over the specified limit' : helperText, ...props }));
|
|
3
|
+
import { FormControl, FormLabel, Box } from '@mui/material';
|
|
4
|
+
const FieldTypeText = ({ label, maxLength = 150, value, helperText, required, ...props }) => {
|
|
5
|
+
return (_jsxs(FormControl, { fullWidth: true, required: required, children: [_jsxs(FormLabel, { sx: { display: 'flex', justifyContent: 'space-between', '& .MuiFormLabel-asterisk': { order: 2 } }, children: [_jsx(Box, { sx: { order: 1 }, children: label }), _jsxs(Box, { sx: { order: 3, flex: 1, textAlign: 'right' }, children: [value?.length, "/", maxLength] })] }), _jsx(MuiTextField, { size: "small", variant: 'outlined', value: value, error: value?.length > maxLength, helperText: value?.length > maxLength ? 'Your input is over the specified limit' : helperText, ...props })] }));
|
|
14
6
|
};
|
|
15
7
|
export default FieldTypeText;
|
|
@@ -8,5 +8,5 @@ export interface FieldTypeUrlProps extends Omit<OutlinedTextFieldProps, 'variant
|
|
|
8
8
|
maxLength?: number;
|
|
9
9
|
value: string;
|
|
10
10
|
}
|
|
11
|
-
declare const FieldTypeUrl: ({ maxLength, value, helperText,
|
|
11
|
+
declare const FieldTypeUrl: ({ label, maxLength, value, helperText, required, inputProps, ...props }: FieldTypeUrlProps) => JSX.Element;
|
|
12
12
|
export default FieldTypeUrl;
|
package/es/FieldTypeUrl/index.js
CHANGED
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useRef } from 'react';
|
|
3
3
|
import MuiTextField from '@mui/material/TextField';
|
|
4
|
-
import {
|
|
5
|
-
const FieldTypeUrl = ({ maxLength = 2000, value, helperText,
|
|
4
|
+
import { FormControl, FormLabel, Box } from '@mui/material';
|
|
5
|
+
const FieldTypeUrl = ({ label, maxLength = 2000, value, helperText, required, inputProps, ...props }) => {
|
|
6
6
|
const inputRef = useRef(null);
|
|
7
|
-
return (_jsx(MuiTextField, { size: "small", type: 'url', variant: 'outlined', value: value,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
shrink: true,
|
|
13
|
-
// Spread props at the end to allow InputLabel prop overrides
|
|
14
|
-
...InputLabelProps,
|
|
15
|
-
}, inputProps: {
|
|
16
|
-
ref: inputRef,
|
|
17
|
-
// Spread props at the end to allow inputProps prop overrides
|
|
18
|
-
...inputProps,
|
|
19
|
-
}, error: (value && !inputRef.current?.validity.valid) || value.length > maxLength, helperText: value.length > maxLength ? 'Your input is over the specified limit' : (value && !inputRef.current?.validity.valid) ? 'Your input is not a valid url' : helperText, ...props }));
|
|
7
|
+
return (_jsxs(FormControl, { fullWidth: true, required: required, children: [_jsxs(FormLabel, { sx: { display: 'flex', justifyContent: 'space-between', '& .MuiFormLabel-asterisk': { order: 2 } }, children: [_jsx(Box, { sx: { order: 1 }, children: label }), _jsxs(Box, { sx: { order: 3, flex: 1, textAlign: 'right' }, children: [value?.length, "/", maxLength] })] }), _jsx(MuiTextField, { size: "small", type: 'url', variant: 'outlined', value: value, inputProps: {
|
|
8
|
+
ref: inputRef,
|
|
9
|
+
// Spread props at the end to allow inputProps prop overrides
|
|
10
|
+
...inputProps,
|
|
11
|
+
}, error: (value && !inputRef.current?.validity.valid) || value?.length > maxLength, helperText: value?.length > maxLength ? 'Your input is over the specified limit' : (value && !inputRef.current?.validity.valid) ? 'Your input is not a valid url' : helperText, ...props })] }));
|
|
20
12
|
};
|
|
21
13
|
export default FieldTypeUrl;
|
package/es/index.d.ts
CHANGED
|
@@ -7,5 +7,7 @@ export { default as FieldTypeDateTime } from './FieldTypeDateTime';
|
|
|
7
7
|
export { default as FieldTypeColor } from './FieldTypeColor';
|
|
8
8
|
export { default as FieldTypeNumber } from './FieldTypeNumber';
|
|
9
9
|
export { default as FieldTypeDropdown } from './FieldTypeDropdown';
|
|
10
|
+
export { default as FieldTypeOneToOne } from './FieldTypeOneToOne';
|
|
11
|
+
export { default as FieldTypeOneToMany } from './FieldTypeOneToMany';
|
|
10
12
|
export { default as CopyButton } from './CopyButton';
|
|
11
|
-
export { default as
|
|
13
|
+
export { default as ConfirmDialog } from './ConfirmDialog';
|
package/es/index.js
CHANGED
|
@@ -7,5 +7,7 @@ export { default as FieldTypeDateTime } from './FieldTypeDateTime';
|
|
|
7
7
|
export { default as FieldTypeColor } from './FieldTypeColor';
|
|
8
8
|
export { default as FieldTypeNumber } from './FieldTypeNumber';
|
|
9
9
|
export { default as FieldTypeDropdown } from './FieldTypeDropdown';
|
|
10
|
+
export { default as FieldTypeOneToOne } from './FieldTypeOneToOne';
|
|
11
|
+
export { default as FieldTypeOneToMany } from './FieldTypeOneToMany';
|
|
10
12
|
export { default as CopyButton } from './CopyButton';
|
|
11
|
-
export { default as
|
|
13
|
+
export { default as ConfirmDialog } from './ConfirmDialog';
|
package/es/theme/index.js
CHANGED
|
@@ -39,6 +39,16 @@ theme = createTheme(theme, {
|
|
|
39
39
|
root: {
|
|
40
40
|
color: theme.palette.primary.dark,
|
|
41
41
|
},
|
|
42
|
+
asterisk: {
|
|
43
|
+
color: theme.palette.error.main,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
MuiCardHeader: {
|
|
48
|
+
styleOverrides: {
|
|
49
|
+
root: {
|
|
50
|
+
backgroundColor: '#e4e9f1',
|
|
51
|
+
},
|
|
42
52
|
},
|
|
43
53
|
},
|
|
44
54
|
MuiToggleButton: {
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import useMediaQuery from '@mui/material/useMediaQuery';
|
|
4
|
+
import ListSubheader from '@mui/material/ListSubheader';
|
|
5
|
+
import { useTheme } from '@mui/material/styles';
|
|
6
|
+
import { VariableSizeList } from 'react-window';
|
|
7
|
+
import Typography from '@mui/material/Typography';
|
|
8
|
+
const LISTBOX_PADDING = 8; // px
|
|
9
|
+
function renderRow(props) {
|
|
10
|
+
const { data, index, style } = props;
|
|
11
|
+
const dataSet = data[index];
|
|
12
|
+
const inlineStyle = {
|
|
13
|
+
...style,
|
|
14
|
+
top: style.top + LISTBOX_PADDING,
|
|
15
|
+
};
|
|
16
|
+
if (dataSet.hasOwnProperty('group')) {
|
|
17
|
+
return (_jsx(ListSubheader, { component: "div", style: inlineStyle, children: dataSet.group }, dataSet.key));
|
|
18
|
+
}
|
|
19
|
+
return (_jsx(Typography, { component: "li", ...dataSet[0], noWrap: true, style: inlineStyle, children: dataSet[1] }));
|
|
20
|
+
}
|
|
21
|
+
const OuterElementContext = React.createContext({});
|
|
22
|
+
const OuterElementType = React.forwardRef((props, ref) => {
|
|
23
|
+
const outerProps = React.useContext(OuterElementContext);
|
|
24
|
+
return _jsx("div", { ref: ref, ...props, ...outerProps });
|
|
25
|
+
});
|
|
26
|
+
function useResetCache(data) {
|
|
27
|
+
const ref = React.useRef(null);
|
|
28
|
+
React.useEffect(() => {
|
|
29
|
+
if (ref.current != null) {
|
|
30
|
+
ref.current.resetAfterIndex(0, true);
|
|
31
|
+
}
|
|
32
|
+
}, [data]);
|
|
33
|
+
return ref;
|
|
34
|
+
}
|
|
35
|
+
// Adapter for react-window
|
|
36
|
+
export const ListboxComponent = React.forwardRef(function ListboxComponent(props, ref) {
|
|
37
|
+
const { children, ...other } = props;
|
|
38
|
+
const itemData = [];
|
|
39
|
+
children.forEach((item) => {
|
|
40
|
+
itemData.push(item);
|
|
41
|
+
itemData.push(...(item.children || []));
|
|
42
|
+
});
|
|
43
|
+
const theme = useTheme();
|
|
44
|
+
const smUp = useMediaQuery(theme.breakpoints.up('sm'), {
|
|
45
|
+
noSsr: true,
|
|
46
|
+
});
|
|
47
|
+
const itemCount = itemData.length;
|
|
48
|
+
const itemSize = smUp ? 36 : 48;
|
|
49
|
+
const getChildSize = (child) => {
|
|
50
|
+
if (child.hasOwnProperty('group')) {
|
|
51
|
+
return 48;
|
|
52
|
+
}
|
|
53
|
+
return itemSize;
|
|
54
|
+
};
|
|
55
|
+
const getHeight = () => {
|
|
56
|
+
if (itemCount > 8) {
|
|
57
|
+
return 8 * itemSize;
|
|
58
|
+
}
|
|
59
|
+
return itemData.map(getChildSize).reduce((a, b) => a + b, 0);
|
|
60
|
+
};
|
|
61
|
+
const gridRef = useResetCache(itemCount);
|
|
62
|
+
return (_jsx("div", { ref: ref, children: _jsx(OuterElementContext.Provider, { value: other, children: _jsx(VariableSizeList, { itemData: itemData, height: getHeight() + 2 * LISTBOX_PADDING, width: "100%", ref: gridRef, outerElementType: OuterElementType, innerElementType: "ul", itemSize: (index) => getChildSize(itemData[index]), overscanCount: 5, itemCount: itemCount, children: renderRow }) }) }));
|
|
63
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zesty-io/material",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Contains custom components which are in addition to the @mui design-system",
|
|
5
5
|
"author": "Zesty.io",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"module": "es/index.js",
|
|
17
17
|
"types": "es/index.d.ts",
|
|
18
18
|
"scripts": {
|
|
19
|
-
"build": "tsc",
|
|
19
|
+
"build": "npm ci && tsc",
|
|
20
20
|
"prerelease": "npm test",
|
|
21
21
|
"release": "npm run build && npm publish --access public",
|
|
22
22
|
"release:alpha": "npm run build && npm publish --access public --tag alpha",
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"@mui/icons-material": "^5.6.2",
|
|
33
33
|
"@mui/material": "^5.6.4",
|
|
34
34
|
"@mui/x-date-pickers": "^5.0.0-alpha.5",
|
|
35
|
-
"date-fns": "^2.28.0"
|
|
35
|
+
"date-fns": "^2.28.0",
|
|
36
|
+
"react-window": "^1.8.7"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
39
|
"@babel/core": "^7.17.10",
|
|
@@ -42,6 +43,7 @@
|
|
|
42
43
|
"@storybook/addon-links": "^6.4.22",
|
|
43
44
|
"@storybook/react": "^6.4.22",
|
|
44
45
|
"@storybook/testing-library": "0.0.11",
|
|
46
|
+
"@types/react-window": "^1.8.5",
|
|
45
47
|
"babel-loader": "^8.2.5",
|
|
46
48
|
"gh-pages": "^3.2.3",
|
|
47
49
|
"react": "^18.1.0",
|
package/src/{ConfirmModal/ConfirmModal.stories.tsx → ConfirmDialog/ConfirmDialog.stories.tsx}
RENAMED
|
File without changes
|
|
File without changes
|
package/src/CopyButton/index.tsx
CHANGED
|
@@ -39,15 +39,15 @@ const CopyButton = ({value, sx, ...props }: CopyButtonProps) => {
|
|
|
39
39
|
// Spread sx prop at the end to allow sx prop overrides
|
|
40
40
|
...sx,
|
|
41
41
|
}}
|
|
42
|
+
startIcon={copied ? (
|
|
43
|
+
<CheckIcon color='success' fontSize='small' />
|
|
44
|
+
) : (
|
|
45
|
+
<ContentCopyIcon fontSize='small' />
|
|
46
|
+
)}
|
|
42
47
|
// Spread props at the end to allow prop overrides
|
|
43
48
|
{...props}
|
|
44
49
|
>
|
|
45
|
-
{
|
|
46
|
-
<CheckIcon color='success' fontSize='small' />
|
|
47
|
-
) : (
|
|
48
|
-
<ContentCopyIcon fontSize='small' />
|
|
49
|
-
)}
|
|
50
|
-
{props.children ? props.children : value}
|
|
50
|
+
{props.children ? props.children : value}
|
|
51
51
|
</Button>
|
|
52
52
|
);
|
|
53
53
|
};
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { useRef } from 'react';
|
|
2
2
|
import MuiTextField, { OutlinedTextFieldProps } from '@mui/material/TextField';
|
|
3
|
-
import { Button, InputAdornment } from '@mui/material';
|
|
3
|
+
import { Button, FormControl, FormHelperText, FormLabel, InputAdornment } from '@mui/material';
|
|
4
4
|
import BrushIcon from '@mui/icons-material/Brush';
|
|
5
5
|
|
|
6
6
|
export interface FieldTypeColorProps extends Omit<OutlinedTextFieldProps, 'variant'> {}
|
|
7
7
|
|
|
8
|
-
const FieldTypeColor = ({InputProps,
|
|
8
|
+
const FieldTypeColor = ({InputProps, label, required, ...props }: FieldTypeColorProps) => {
|
|
9
9
|
|
|
10
10
|
return (
|
|
11
|
+
<FormControl fullWidth required={required}>
|
|
12
|
+
<FormLabel>{label}</FormLabel>
|
|
11
13
|
<MuiTextField
|
|
12
14
|
size="small"
|
|
13
15
|
variant='outlined'
|
|
@@ -31,14 +33,10 @@ const FieldTypeColor = ({InputProps, InputLabelProps, ...props }: FieldTypeColor
|
|
|
31
33
|
// Spread props at the end to allow Input prop overrides
|
|
32
34
|
...InputProps,
|
|
33
35
|
}}
|
|
34
|
-
InputLabelProps={{
|
|
35
|
-
shrink: true,
|
|
36
|
-
// Spread props at the end to allow InputLabel prop overrides
|
|
37
|
-
...InputLabelProps,
|
|
38
|
-
}}
|
|
39
36
|
// Spread props at the end to allow prop overrides
|
|
40
37
|
{...props}
|
|
41
38
|
/>
|
|
39
|
+
</FormControl>
|
|
42
40
|
);
|
|
43
41
|
};
|
|
44
42
|
|
|
@@ -19,8 +19,5 @@ const Template: Story<FieldTypeDateProps> = (args) => {
|
|
|
19
19
|
export const Default = Template.bind({});
|
|
20
20
|
Default.args = {
|
|
21
21
|
label: 'Date label',
|
|
22
|
-
|
|
23
|
-
helperText: 'Date helper text',
|
|
24
|
-
error: false,
|
|
25
|
-
}
|
|
22
|
+
helperText: 'Date helper text',
|
|
26
23
|
};
|
|
@@ -1,36 +1,33 @@
|
|
|
1
1
|
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
|
|
2
2
|
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
|
|
3
3
|
import { DatePicker, DatePickerProps} from '@mui/x-date-pickers/DatePicker';
|
|
4
|
-
import {
|
|
4
|
+
import { FormControl, FormLabel, TextField } from '@mui/material';
|
|
5
5
|
|
|
6
6
|
export interface FieldTypeDateProps extends Omit<DatePickerProps<Date, Date>, 'renderInput'> {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
textFieldProps?: TextFieldProps;
|
|
7
|
+
helperText?: string;
|
|
8
|
+
error?: boolean;
|
|
9
|
+
required?: boolean;
|
|
11
10
|
};
|
|
12
11
|
|
|
13
|
-
const FieldTypeDate = ({
|
|
12
|
+
const FieldTypeDate = ({label, helperText, error, required, ...props}: FieldTypeDateProps) => {
|
|
14
13
|
return (
|
|
15
|
-
<
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
/>
|
|
33
|
-
</LocalizationProvider>
|
|
14
|
+
<FormControl fullWidth required={required}>
|
|
15
|
+
<FormLabel>{label}</FormLabel>
|
|
16
|
+
<LocalizationProvider dateAdapter={AdapterDateFns}>
|
|
17
|
+
<DatePicker
|
|
18
|
+
data-testid="zds-date-picker"
|
|
19
|
+
renderInput={(params) =>
|
|
20
|
+
<TextField
|
|
21
|
+
{...params}
|
|
22
|
+
helperText={helperText}
|
|
23
|
+
error={error}
|
|
24
|
+
/>
|
|
25
|
+
}
|
|
26
|
+
// Spread props at the end to allow prop overrides
|
|
27
|
+
{...props}
|
|
28
|
+
/>
|
|
29
|
+
</LocalizationProvider>
|
|
30
|
+
</FormControl>
|
|
34
31
|
);
|
|
35
32
|
}
|
|
36
33
|
|
|
@@ -19,8 +19,5 @@ const Template: Story<FieldTypeDateTimeProps> = (args) => {
|
|
|
19
19
|
export const Default = Template.bind({});
|
|
20
20
|
Default.args = {
|
|
21
21
|
label: 'Date label',
|
|
22
|
-
|
|
23
|
-
helperText: 'Date helper text',
|
|
24
|
-
error: false,
|
|
25
|
-
}
|
|
22
|
+
helperText: 'Date helper text',
|
|
26
23
|
};
|
|
@@ -1,36 +1,34 @@
|
|
|
1
1
|
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
|
|
2
2
|
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
|
|
3
3
|
import { DateTimePicker, DateTimePickerProps} from '@mui/x-date-pickers/DateTimePicker';
|
|
4
|
-
import { TextField,
|
|
4
|
+
import { TextField, FormControl, FormLabel } from '@mui/material';
|
|
5
5
|
|
|
6
6
|
export interface FieldTypeDateTimeProps extends Omit<DateTimePickerProps<Date, Date>, 'renderInput'> {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
textFieldProps?: TextFieldProps;
|
|
7
|
+
helperText?: string;
|
|
8
|
+
error?: boolean;
|
|
9
|
+
required?: boolean;
|
|
11
10
|
};
|
|
12
11
|
|
|
13
|
-
const FieldTypeDateTime = ({
|
|
12
|
+
const FieldTypeDateTime = ({label, helperText, error, required, ...props}: FieldTypeDateTimeProps) => {
|
|
14
13
|
return (
|
|
15
|
-
<
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
...
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
</LocalizationProvider>
|
|
14
|
+
<FormControl fullWidth required={required}>
|
|
15
|
+
<FormLabel>{label}</FormLabel>
|
|
16
|
+
<LocalizationProvider dateAdapter={AdapterDateFns}>
|
|
17
|
+
<DateTimePicker
|
|
18
|
+
data-testid="zds-date-picker"
|
|
19
|
+
renderInput={(params) =>
|
|
20
|
+
<TextField
|
|
21
|
+
|
|
22
|
+
{...params}
|
|
23
|
+
helperText={helperText}
|
|
24
|
+
error={error}
|
|
25
|
+
/>
|
|
26
|
+
}
|
|
27
|
+
// Spread props at the end to allow prop overrides
|
|
28
|
+
{...props}
|
|
29
|
+
/>
|
|
30
|
+
</LocalizationProvider>
|
|
31
|
+
</FormControl>
|
|
34
32
|
);
|
|
35
33
|
}
|
|
36
34
|
|
|
@@ -44,7 +44,8 @@ const Template: Story<FieldTypeDropdownProps> = (args) => {
|
|
|
44
44
|
export const Default = Template.bind({});
|
|
45
45
|
Default.args = {
|
|
46
46
|
placeholder: 'Placeholder Text...',
|
|
47
|
-
label: '
|
|
47
|
+
label: 'Dropdown label',
|
|
48
|
+
helperText: 'Dropdown helper text',
|
|
48
49
|
};
|
|
49
50
|
|
|
50
51
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { MenuItem } from '@mui/material';
|
|
2
2
|
import MuiTextField, { OutlinedTextFieldProps } from '@mui/material/TextField';
|
|
3
|
+
import { FormControl, FormLabel } from '@mui/material';
|
|
3
4
|
|
|
4
5
|
interface Option {
|
|
5
6
|
label: string;
|
|
@@ -10,19 +11,15 @@ export interface FieldTypeDropdownProps extends Omit<OutlinedTextFieldProps, 'va
|
|
|
10
11
|
options: Option[];
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
const FieldTypeDropdown = ({
|
|
14
|
+
const FieldTypeDropdown = ({label, options, required, ...props }: FieldTypeDropdownProps) => {
|
|
14
15
|
|
|
15
16
|
return (
|
|
17
|
+
<FormControl fullWidth required={required}>
|
|
18
|
+
<FormLabel>{label}</FormLabel>
|
|
16
19
|
<MuiTextField
|
|
17
20
|
size="small"
|
|
18
21
|
variant='outlined'
|
|
19
22
|
select
|
|
20
|
-
InputLabelProps={{
|
|
21
|
-
shrink: true,
|
|
22
|
-
// Spread props at the end to allow InputLabel prop overrides
|
|
23
|
-
...InputLabelProps,
|
|
24
|
-
}}
|
|
25
|
-
// Spread props at the end to allow prop overrides
|
|
26
23
|
SelectProps={{
|
|
27
24
|
displayEmpty: true,
|
|
28
25
|
}}
|
|
@@ -37,6 +34,7 @@ const FieldTypeDropdown = ({InputLabelProps, options, ...props }: FieldTypeDropd
|
|
|
37
34
|
</MenuItem>
|
|
38
35
|
))}
|
|
39
36
|
</MuiTextField>
|
|
37
|
+
</FormControl>
|
|
40
38
|
);
|
|
41
39
|
};
|
|
42
40
|
|
|
@@ -1,22 +1,21 @@
|
|
|
1
|
+
import { FormControl, FormLabel } from '@mui/material';
|
|
1
2
|
import MuiTextField, { OutlinedTextFieldProps } from '@mui/material/TextField';
|
|
2
3
|
|
|
3
4
|
export interface FieldTypeNumberProps extends Omit<OutlinedTextFieldProps, 'variant'> {}
|
|
4
5
|
|
|
5
|
-
const FieldTypeText = ({
|
|
6
|
+
const FieldTypeText = ({label, required, ...props }: FieldTypeNumberProps) => {
|
|
6
7
|
|
|
7
8
|
return (
|
|
9
|
+
<FormControl fullWidth required={required}>
|
|
10
|
+
<FormLabel>{label}</FormLabel>
|
|
8
11
|
<MuiTextField
|
|
9
12
|
size="small"
|
|
10
13
|
variant='outlined'
|
|
11
14
|
type='number'
|
|
12
|
-
InputLabelProps={{
|
|
13
|
-
shrink: true,
|
|
14
|
-
// Spread props at the end to allow InputLabel prop overrides
|
|
15
|
-
...InputLabelProps,
|
|
16
|
-
}}
|
|
17
15
|
// Spread props at the end to allow prop overrides
|
|
18
16
|
{...props}
|
|
19
17
|
/>
|
|
18
|
+
</FormControl>
|
|
20
19
|
);
|
|
21
20
|
};
|
|
22
21
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ReactNode, SyntheticEvent, useState } from 'react';
|
|
2
|
+
import { Story, Meta } from '@storybook/react/types-6-0';
|
|
3
|
+
import FieldTypeOneToMany, { FieldTypeOneToManyProps } from '.';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: 'FieldTypeOneToMany',
|
|
7
|
+
component: FieldTypeOneToMany,
|
|
8
|
+
argType: {},
|
|
9
|
+
} as Meta;
|
|
10
|
+
|
|
11
|
+
const Template: Story<FieldTypeOneToManyProps> = (args) => {
|
|
12
|
+
const [value, setValue] = useState<{component: string | ReactNode, value: string, inputLabel: string}[]>([]);
|
|
13
|
+
|
|
14
|
+
const [options, setOptions] = useState<{component: string | ReactNode, value: string, inputLabel: string}[]>([]);
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
const handleOnOpen = async () => {
|
|
18
|
+
const largeArr = new Array(1000).fill(null);
|
|
19
|
+
await new Promise((resolve) => setTimeout(resolve, 3000))
|
|
20
|
+
const data = largeArr.map((_, idx) => ({component: <div>{`Test ${idx}`}</div>, value: String(Math.random()), inputLabel: `Test ${idx}`}));
|
|
21
|
+
setOptions(data);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const handleOnChange = (e: SyntheticEvent<Element, Event>, values: {component: string | ReactNode, value: string, inputLabel: string}[]) => {
|
|
25
|
+
setValue(values);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<FieldTypeOneToMany
|
|
30
|
+
{...args}
|
|
31
|
+
value={value}
|
|
32
|
+
onChange={handleOnChange}
|
|
33
|
+
options={options}
|
|
34
|
+
onOpen={handleOnOpen}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const Default = Template.bind({});
|
|
40
|
+
Default.args = {
|
|
41
|
+
placeholder: 'Placeholder Text...',
|
|
42
|
+
label: 'OneToMany label',
|
|
43
|
+
helperText: 'OneToMany helperText',
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { ReactNode, useState } from 'react';
|
|
2
|
+
import { AutocompleteProps, FormControl, FormLabel, Popper, styled, TextField, TextFieldProps } from '@mui/material';
|
|
3
|
+
import Autocomplete, { autocompleteClasses } from '@mui/material/Autocomplete';
|
|
4
|
+
import { ListboxComponent } from '../utils/virtualization';
|
|
5
|
+
|
|
6
|
+
export interface FieldTypeOneToManyProps extends Omit<AutocompleteProps<any, false, false, false>, 'onOpen' | 'renderInput'> {
|
|
7
|
+
label?: string;
|
|
8
|
+
helperText?: string;
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
error?: boolean;
|
|
11
|
+
required?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Callback to be fired upon opening the dropdown
|
|
14
|
+
*/
|
|
15
|
+
onOpen: () => Promise<any>;
|
|
16
|
+
/**
|
|
17
|
+
* Structure for option
|
|
18
|
+
*/
|
|
19
|
+
options: {
|
|
20
|
+
/**
|
|
21
|
+
* Component to be rendered in the dropdown
|
|
22
|
+
*/
|
|
23
|
+
component: ReactNode | string;
|
|
24
|
+
/**
|
|
25
|
+
* Value of option
|
|
26
|
+
*/
|
|
27
|
+
value: string;
|
|
28
|
+
/**
|
|
29
|
+
* Label that should display in the input when selected
|
|
30
|
+
*/
|
|
31
|
+
inputLabel: string;
|
|
32
|
+
}[]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const FieldTypeOneToMany = ({label, helperText, placeholder, error, onOpen, options, required, ...props }: FieldTypeOneToManyProps) => {
|
|
36
|
+
const [loaded, setLoaded] = useState(false);
|
|
37
|
+
const [loading, setLoading] = useState(false);
|
|
38
|
+
|
|
39
|
+
const handleOpen = () => {
|
|
40
|
+
if (!loaded && onOpen) {
|
|
41
|
+
onOpen().then(() => {
|
|
42
|
+
setLoading(false);
|
|
43
|
+
});
|
|
44
|
+
setLoading(true);
|
|
45
|
+
setLoaded(true);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<FormControl fullWidth required={required}>
|
|
51
|
+
<FormLabel>{label}</FormLabel>
|
|
52
|
+
<Autocomplete
|
|
53
|
+
onOpen={handleOpen}
|
|
54
|
+
loading={loading}
|
|
55
|
+
fullWidth
|
|
56
|
+
multiple
|
|
57
|
+
disableListWrap
|
|
58
|
+
disableClearable
|
|
59
|
+
disablePortal
|
|
60
|
+
size='small'
|
|
61
|
+
PopperComponent={StyledPopper}
|
|
62
|
+
ListboxComponent={ListboxComponent}
|
|
63
|
+
renderInput={(params) => (
|
|
64
|
+
<TextField
|
|
65
|
+
{...params}
|
|
66
|
+
helperText={helperText}
|
|
67
|
+
error={error}
|
|
68
|
+
placeholder={placeholder}
|
|
69
|
+
/>
|
|
70
|
+
)}
|
|
71
|
+
options={loading ? [] : options}
|
|
72
|
+
getOptionLabel={(option) => option.inputLabel}
|
|
73
|
+
renderOption={(props, option) => [props, option.component]}
|
|
74
|
+
{...props}
|
|
75
|
+
/>
|
|
76
|
+
</FormControl>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export default FieldTypeOneToMany;
|
|
81
|
+
|
|
82
|
+
const StyledPopper = styled(Popper)({
|
|
83
|
+
[`& .${autocompleteClasses.listbox}`]: {
|
|
84
|
+
boxSizing: 'border-box',
|
|
85
|
+
'& ul': {
|
|
86
|
+
padding: 0,
|
|
87
|
+
margin: 0,
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
});
|