@zesty-io/material 0.1.4 → 0.2.2

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.
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
- import { DatePickerProps } from '@mui/x-date-pickers/DatePicker';
3
- export interface FieldTypeDateProps extends Omit<DatePickerProps<Date, Date>, 'renderInput'> {
2
+ import { DesktopDatePickerProps } from '@mui/x-date-pickers';
3
+ export interface FieldTypeDateProps extends Omit<DesktopDatePickerProps<Date, Date>, 'renderInput'> {
4
4
  helperText?: string;
5
5
  error?: boolean;
6
6
  required?: boolean;
@@ -1,10 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
3
3
  import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
4
- import { DatePicker } from '@mui/x-date-pickers/DatePicker';
4
+ import { DesktopDatePicker } from '@mui/x-date-pickers';
5
5
  import { FormControl, FormLabel, TextField } from '@mui/material';
6
6
  ;
7
7
  const FieldTypeDate = ({ label, helperText, error, required, ...props }) => {
8
- return (_jsxs(FormControl, { fullWidth: true, required: required, children: [_jsx(FormLabel, { children: label }), _jsx(LocalizationProvider, { dateAdapter: AdapterDateFns, children: _jsx(DatePicker, { "data-testid": "zds-date-picker", renderInput: (params) => _jsx(TextField, { ...params, helperText: helperText, error: error }), ...props }) })] }));
8
+ return (_jsxs(FormControl, { fullWidth: true, required: required, children: [_jsx(FormLabel, { children: label }), _jsx(LocalizationProvider, { dateAdapter: AdapterDateFns, children: _jsx(DesktopDatePicker, { "data-testid": "zds-date-picker", renderInput: (params) => _jsx(TextField, { ...params, helperText: helperText, error: error, size: "small" }), ...props }) })] }));
9
9
  };
10
10
  export default FieldTypeDate;
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
- import { DateTimePickerProps } from '@mui/x-date-pickers/DateTimePicker';
3
- export interface FieldTypeDateTimeProps extends Omit<DateTimePickerProps<Date, Date>, 'renderInput'> {
2
+ import { DesktopDateTimePickerProps } from '@mui/x-date-pickers';
3
+ export interface FieldTypeDateTimeProps extends Omit<DesktopDateTimePickerProps<Date, Date>, 'renderInput'> {
4
4
  helperText?: string;
5
5
  error?: boolean;
6
6
  required?: boolean;
@@ -1,10 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
3
3
  import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
4
- import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker';
4
+ import { DesktopDateTimePicker } from '@mui/x-date-pickers';
5
5
  import { TextField, FormControl, FormLabel } from '@mui/material';
6
6
  ;
7
7
  const FieldTypeDateTime = ({ label, helperText, error, required, ...props }) => {
8
- return (_jsxs(FormControl, { fullWidth: true, required: required, children: [_jsx(FormLabel, { children: label }), _jsx(LocalizationProvider, { dateAdapter: AdapterDateFns, children: _jsx(DateTimePicker, { "data-testid": "zds-date-picker", renderInput: (params) => _jsx(TextField, { ...params, helperText: helperText, error: error }), ...props }) })] }));
8
+ return (_jsxs(FormControl, { fullWidth: true, required: required, children: [_jsx(FormLabel, { children: label }), _jsx(LocalizationProvider, { dateAdapter: AdapterDateFns, children: _jsx(DesktopDateTimePicker, { "data-testid": "zds-date-time-picker", renderInput: (params) => _jsx(TextField, { ...params, helperText: helperText, error: error, size: "small" }), ...props }) })] }));
9
9
  };
10
10
  export default FieldTypeDateTime;
@@ -3,5 +3,5 @@ import { OutlinedTextFieldProps } from '@mui/material/TextField';
3
3
  export interface FieldTypeSortProps extends Omit<OutlinedTextFieldProps, 'variant'> {
4
4
  value: string;
5
5
  }
6
- declare const FieldTypeSort: ({ label, value, InputProps, required, ...props }: FieldTypeSortProps) => JSX.Element;
6
+ declare const FieldTypeSort: ({ label, value, InputProps, required, onChange, ...props }: FieldTypeSortProps) => JSX.Element;
7
7
  export default FieldTypeSort;
@@ -3,17 +3,29 @@ import MuiTextField from '@mui/material/TextField';
3
3
  import { Button, FormControl, FormLabel, InputAdornment } from '@mui/material';
4
4
  import AddIcon from '@mui/icons-material/Add';
5
5
  import RemoveIcon from '@mui/icons-material/Remove';
6
- const FieldTypeSort = ({ label, value, InputProps, required, ...props }) => {
7
- return (_jsxs(FormControl, { fullWidth: true, required: required, children: [_jsx(FormLabel, { children: label }), _jsx(MuiTextField, { size: "small", variant: 'outlined', type: 'number', value: value, InputProps: {
6
+ const FieldTypeSort = ({ label, value, InputProps, required, onChange, ...props }) => {
7
+ return (_jsxs(FormControl, { fullWidth: true, required: required, children: [_jsx(FormLabel, { children: label }), _jsx(MuiTextField, { size: "small", variant: 'outlined', type: 'number', value: value, onChange: onChange, InputProps: {
8
8
  startAdornment: (_jsx(InputAdornment, { position: "start", children: _jsx(Button, { size: "small", variant: "contained", onClick: (e) => {
9
- // References input via event in order to modify its value
9
+ e.stopPropagation();
10
+ // References input via click event in order to obtain its value
10
11
  const input = e.currentTarget?.parentElement?.parentElement?.childNodes?.[1];
11
- input.value = String(+input.value - 1);
12
+ const newValue = String(+input.value - 1);
13
+ // Updates internal input value in case component is not controlled
14
+ input.value = newValue;
15
+ // Mocks an event change
16
+ const event = { target: { value: newValue } };
17
+ onChange && onChange(event);
12
18
  }, children: _jsx(RemoveIcon, { fontSize: 'small' }) }) })),
13
19
  endAdornment: (_jsx(InputAdornment, { position: "end", children: _jsx(Button, { size: "small", variant: "contained", onClick: (e) => {
14
- // References input via event in order to modify its value
20
+ e.stopPropagation();
21
+ // References input via click event in order to obtain its value
15
22
  const input = e.currentTarget?.parentElement?.parentElement?.childNodes?.[1];
16
- input.value = String(+input.value + 1);
23
+ const newValue = String(+input.value + 1);
24
+ // Updates internal input value in case component is not controlled
25
+ input.value = newValue;
26
+ // Mocks an event change
27
+ const event = { target: { value: newValue } };
28
+ onChange && onChange(event);
17
29
  }, children: _jsx(AddIcon, { fontSize: 'small' }) }) })),
18
30
  // Spread props at the end to allow Input prop overrides
19
31
  ...InputProps,
@@ -1,13 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useRef } from 'react';
2
+ import { useState } from 'react';
3
3
  import MuiTextField from '@mui/material/TextField';
4
4
  import { FormControl, FormLabel, Box } from '@mui/material';
5
5
  const FieldTypeUrl = ({ label, maxLength = 2000, value, helperText, required, inputProps, ...props }) => {
6
- const inputRef = useRef(null);
6
+ // Use state to hold input reference to re-render once ref changes in case error needs to be shown on mount
7
+ const [inputRef, setInputRef] = useState();
7
8
  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
+ ref: (inputRef) => setInputRef(inputRef),
9
10
  // Spread props at the end to allow inputProps prop overrides
10
11
  ...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 })] }));
12
+ }, error: (value && !inputRef?.validity.valid) || value?.length > maxLength, helperText: value?.length > maxLength ? 'Your input is over the specified limit' : (value && !inputRef?.validity.valid) ? 'Your input is not a valid url' : helperText, ...props })] }));
12
13
  };
13
14
  export default FieldTypeUrl;
@@ -0,0 +1,5 @@
1
+ import { Story, Meta } from '@storybook/react/types-6-0';
2
+ import { VirtualizedAutocompleteProps } from './';
3
+ declare const _default: Meta<import("@storybook/react/types-6-0").Args>;
4
+ export default _default;
5
+ export declare const Default: Story<VirtualizedAutocompleteProps>;
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import VirtualizedAutocomplete from './';
4
+ export default {
5
+ title: 'VirtualizedAutocomplete',
6
+ component: VirtualizedAutocomplete,
7
+ argType: {},
8
+ };
9
+ const Template = (args) => {
10
+ const [value, setValue] = useState({ component: '- None -', value: '0', inputLabel: '- None -' });
11
+ const [options, setOptions] = useState([]);
12
+ const handleOnOpen = async () => {
13
+ const largeArr = new Array(1000).fill(null);
14
+ await new Promise((resolve) => setTimeout(resolve, 3000));
15
+ const data = largeArr.map((_, idx) => ({ component: _jsx("div", { children: `Test ${idx}` }), value: String(Math.random()), inputLabel: `Test ${idx}` }));
16
+ setOptions(data);
17
+ };
18
+ const handleOnChange = (e, option) => {
19
+ setValue(option);
20
+ };
21
+ return (_jsx(VirtualizedAutocomplete, { ...args, value: value, onChange: handleOnChange, options: options, onOpen: handleOnOpen }));
22
+ };
23
+ export const Default = Template.bind({});
24
+ Default.args = {
25
+ helperText: 'OneToOne helperText',
26
+ placeholder: 'OneToOne placeholder'
27
+ };
@@ -0,0 +1,28 @@
1
+ import { ReactNode } from 'react';
2
+ import { AutocompleteProps } from '@mui/material';
3
+ export interface VirtualizedAutocompleteProps extends Omit<AutocompleteProps<any, false, false, false>, 'renderInput'> {
4
+ helperText?: string;
5
+ placeholder?: string;
6
+ error?: boolean;
7
+ startAdornment?: ReactNode;
8
+ endAdornment?: ReactNode;
9
+ /**
10
+ * Structure for option
11
+ */
12
+ options: {
13
+ /**
14
+ * Component to be rendered in the dropdown
15
+ */
16
+ component: ReactNode | string;
17
+ /**
18
+ * Value of option
19
+ */
20
+ value: string;
21
+ /**
22
+ * Label that should display in the input when selected
23
+ */
24
+ inputLabel: string;
25
+ }[];
26
+ }
27
+ declare const VirtualizedAutocomplete: ({ helperText, placeholder, error, startAdornment, endAdornment, ...props }: VirtualizedAutocompleteProps) => JSX.Element;
28
+ export default VirtualizedAutocomplete;
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Popper, styled, TextField, InputAdornment } from '@mui/material';
3
+ import Autocomplete, { autocompleteClasses } from '@mui/material/Autocomplete';
4
+ import { ListboxComponent } from '../utils/virtualization';
5
+ const VirtualizedAutocomplete = ({ helperText, placeholder, error, startAdornment, endAdornment, ...props }) => {
6
+ return (_jsx(Autocomplete, { fullWidth: true, disableListWrap: true, size: 'small', PopperComponent: StyledPopper, ListboxComponent: ListboxComponent, renderInput: (params) => (_jsx(TextField, { ...params, helperText: helperText, error: error, placeholder: placeholder, InputProps: {
7
+ ...params.InputProps,
8
+ startAdornment: _jsx(InputAdornment, { position: 'end', children: startAdornment }),
9
+ endAdornment: _jsxs(_Fragment, { children: [params.InputProps.endAdornment, _jsx(InputAdornment, { sx: { position: 'relative', right: '40px' }, position: 'end', children: endAdornment })] })
10
+ } })), getOptionLabel: (option) => option.inputLabel, renderOption: (props, option) => [props, option.component], ...props }));
11
+ };
12
+ export default VirtualizedAutocomplete;
13
+ const StyledPopper = styled(Popper)({
14
+ [`& .${autocompleteClasses.listbox}`]: {
15
+ boxSizing: 'border-box',
16
+ '& ul': {
17
+ padding: 0,
18
+ margin: 0,
19
+ },
20
+ },
21
+ });
package/es/index.d.ts CHANGED
@@ -6,8 +6,8 @@ export { default as FieldTypeDate } from './FieldTypeDate';
6
6
  export { default as FieldTypeDateTime } from './FieldTypeDateTime';
7
7
  export { default as FieldTypeColor } from './FieldTypeColor';
8
8
  export { default as FieldTypeNumber } from './FieldTypeNumber';
9
- export { default as FieldTypeDropdown } from './FieldTypeDropdown';
10
9
  export { default as FieldTypeOneToOne } from './FieldTypeOneToOne';
11
10
  export { default as FieldTypeOneToMany } from './FieldTypeOneToMany';
12
11
  export { default as CopyButton } from './CopyButton';
13
12
  export { default as ConfirmDialog } from './ConfirmDialog';
13
+ export { default as VirtualizedAutocomplete } from './VitualizedAutocomplete';
package/es/index.js CHANGED
@@ -6,8 +6,8 @@ export { default as FieldTypeDate } from './FieldTypeDate';
6
6
  export { default as FieldTypeDateTime } from './FieldTypeDateTime';
7
7
  export { default as FieldTypeColor } from './FieldTypeColor';
8
8
  export { default as FieldTypeNumber } from './FieldTypeNumber';
9
- export { default as FieldTypeDropdown } from './FieldTypeDropdown';
10
9
  export { default as FieldTypeOneToOne } from './FieldTypeOneToOne';
11
10
  export { default as FieldTypeOneToMany } from './FieldTypeOneToMany';
12
11
  export { default as CopyButton } from './CopyButton';
13
12
  export { default as ConfirmDialog } from './ConfirmDialog';
13
+ export { default as VirtualizedAutocomplete } from './VitualizedAutocomplete';
package/es/theme/index.js CHANGED
@@ -7,6 +7,13 @@ let theme = createTheme({
7
7
  });
8
8
  theme = createTheme(theme, {
9
9
  components: {
10
+ MuiAccordionSummary: {
11
+ styleOverrides: {
12
+ root: {
13
+ backgroundColor: '#e4e9f1',
14
+ },
15
+ },
16
+ },
10
17
  MuiButton: {
11
18
  styleOverrides: {
12
19
  root: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zesty-io/material",
3
- "version": "0.1.4",
3
+ "version": "0.2.2",
4
4
  "description": "Contains custom components which are in addition to the @mui design-system",
5
5
  "author": "Zesty.io",
6
6
  "license": "MIT",
@@ -1,9 +1,9 @@
1
1
  import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
2
2
  import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
3
- import { DatePicker, DatePickerProps} from '@mui/x-date-pickers/DatePicker';
3
+ import { DesktopDatePicker, DesktopDatePickerProps } from '@mui/x-date-pickers';
4
4
  import { FormControl, FormLabel, TextField } from '@mui/material';
5
5
 
6
- export interface FieldTypeDateProps extends Omit<DatePickerProps<Date, Date>, 'renderInput'> {
6
+ export interface FieldTypeDateProps extends Omit<DesktopDatePickerProps<Date, Date>, 'renderInput'> {
7
7
  helperText?: string;
8
8
  error?: boolean;
9
9
  required?: boolean;
@@ -14,13 +14,14 @@ const FieldTypeDate = ({label, helperText, error, required, ...props}: FieldType
14
14
  <FormControl fullWidth required={required}>
15
15
  <FormLabel>{label}</FormLabel>
16
16
  <LocalizationProvider dateAdapter={AdapterDateFns}>
17
- <DatePicker
17
+ <DesktopDatePicker
18
18
  data-testid="zds-date-picker"
19
19
  renderInput={(params) =>
20
20
  <TextField
21
21
  {...params}
22
22
  helperText={helperText}
23
23
  error={error}
24
+ size="small"
24
25
  />
25
26
  }
26
27
  // Spread props at the end to allow prop overrides
@@ -1,9 +1,9 @@
1
1
  import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
2
2
  import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
3
- import { DateTimePicker, DateTimePickerProps} from '@mui/x-date-pickers/DateTimePicker';
3
+ import { DesktopDateTimePicker, DesktopDateTimePickerProps } from '@mui/x-date-pickers';
4
4
  import { TextField, FormControl, FormLabel } from '@mui/material';
5
5
 
6
- export interface FieldTypeDateTimeProps extends Omit<DateTimePickerProps<Date, Date>, 'renderInput'> {
6
+ export interface FieldTypeDateTimeProps extends Omit<DesktopDateTimePickerProps<Date, Date>, 'renderInput'> {
7
7
  helperText?: string;
8
8
  error?: boolean;
9
9
  required?: boolean;
@@ -14,14 +14,15 @@ const FieldTypeDateTime = ({label, helperText, error, required, ...props}: Field
14
14
  <FormControl fullWidth required={required}>
15
15
  <FormLabel>{label}</FormLabel>
16
16
  <LocalizationProvider dateAdapter={AdapterDateFns}>
17
- <DateTimePicker
18
- data-testid="zds-date-picker"
17
+ <DesktopDateTimePicker
18
+ data-testid="zds-date-time-picker"
19
19
  renderInput={(params) =>
20
20
  <TextField
21
21
 
22
22
  {...params}
23
23
  helperText={helperText}
24
24
  error={error}
25
+ size="small"
25
26
  />
26
27
  }
27
28
  // Spread props at the end to allow prop overrides
@@ -1,3 +1,4 @@
1
+ import { ChangeEvent } from 'react';
1
2
  import MuiTextField, { OutlinedTextFieldProps } from '@mui/material/TextField';
2
3
  import { Button, FormControl, FormLabel, InputAdornment } from '@mui/material';
3
4
  import AddIcon from '@mui/icons-material/Add';
@@ -7,7 +8,7 @@ export interface FieldTypeSortProps extends Omit<OutlinedTextFieldProps, 'varian
7
8
  value: string;
8
9
  }
9
10
 
10
- const FieldTypeSort = ({label, value, InputProps, required, ...props }: FieldTypeSortProps) => {
11
+ const FieldTypeSort = ({label, value, InputProps, required, onChange, ...props }: FieldTypeSortProps) => {
11
12
  return (
12
13
  <FormControl fullWidth required={required}>
13
14
  <FormLabel>{label}</FormLabel>
@@ -16,6 +17,7 @@ const FieldTypeSort = ({label, value, InputProps, required, ...props }: FieldTyp
16
17
  variant='outlined'
17
18
  type='number'
18
19
  value={value}
20
+ onChange={onChange}
19
21
  InputProps={{
20
22
  startAdornment: (
21
23
  <InputAdornment position="start">
@@ -23,9 +25,15 @@ const FieldTypeSort = ({label, value, InputProps, required, ...props }: FieldTyp
23
25
  size="small"
24
26
  variant="contained"
25
27
  onClick={(e) => {
26
- // References input via event in order to modify its value
28
+ e.stopPropagation();
29
+ // References input via click event in order to obtain its value
27
30
  const input = e.currentTarget?.parentElement?.parentElement?.childNodes?.[1] as HTMLInputElement;
28
- input.value = String(+input.value - 1)
31
+ const newValue = String(+input.value - 1)
32
+ // Updates internal input value in case component is not controlled
33
+ input.value = newValue
34
+ // Mocks an event change
35
+ const event = {target: {value: newValue}}
36
+ onChange && onChange(event as ChangeEvent<HTMLTextAreaElement | HTMLInputElement>);
29
37
  }}><RemoveIcon fontSize='small' />
30
38
  </Button>
31
39
  </InputAdornment>
@@ -36,9 +44,15 @@ const FieldTypeSort = ({label, value, InputProps, required, ...props }: FieldTyp
36
44
  size="small"
37
45
  variant="contained"
38
46
  onClick={(e) => {
39
- // References input via event in order to modify its value
47
+ e.stopPropagation();
48
+ // References input via click event in order to obtain its value
40
49
  const input = e.currentTarget?.parentElement?.parentElement?.childNodes?.[1] as HTMLInputElement;
41
- input.value = String(+input.value + 1)
50
+ const newValue = String(+input.value + 1)
51
+ // Updates internal input value in case component is not controlled
52
+ input.value = newValue
53
+ // Mocks an event change
54
+ const event = {target: {value: newValue}}
55
+ onChange && onChange(event as ChangeEvent<HTMLTextAreaElement | HTMLInputElement>);
42
56
  }}><AddIcon fontSize='small' />
43
57
  </Button>
44
58
  </InputAdornment>
@@ -1,4 +1,4 @@
1
- import { useRef } from 'react';
1
+ import { useState } from 'react';
2
2
  import MuiTextField, { OutlinedTextFieldProps } from '@mui/material/TextField';
3
3
  import { FormControl, FormLabel, Box } from '@mui/material';
4
4
 
@@ -12,7 +12,8 @@ export interface FieldTypeUrlProps extends Omit<OutlinedTextFieldProps, 'variant
12
12
  }
13
13
 
14
14
  const FieldTypeUrl = ({label, maxLength = 2000, value, helperText, required, inputProps, ...props }: FieldTypeUrlProps) => {
15
- const inputRef = useRef<HTMLInputElement>(null);
15
+ // Use state to hold input reference to re-render once ref changes in case error needs to be shown on mount
16
+ const [inputRef, setInputRef] = useState<HTMLInputElement>();
16
17
 
17
18
  return (
18
19
  <FormControl fullWidth required={required}>
@@ -27,12 +28,12 @@ const FieldTypeUrl = ({label, maxLength = 2000, value, helperText, required, inp
27
28
  variant='outlined'
28
29
  value={value}
29
30
  inputProps={{
30
- ref: inputRef,
31
+ ref: (inputRef: HTMLInputElement) => setInputRef(inputRef),
31
32
  // Spread props at the end to allow inputProps prop overrides
32
33
  ...inputProps,
33
34
  }}
34
- error={(value && !inputRef.current?.validity.valid) || value?.length > maxLength}
35
- helperText={value?.length > maxLength ? 'Your input is over the specified limit' : (value && !inputRef.current?.validity.valid) ? 'Your input is not a valid url' : helperText}
35
+ error={(value && !inputRef?.validity.valid) || value?.length > maxLength}
36
+ helperText={value?.length > maxLength ? 'Your input is over the specified limit' : (value && !inputRef?.validity.valid) ? 'Your input is not a valid url' : helperText}
36
37
  // Spread props at the end to allow prop overrides
37
38
  {...props}
38
39
  />
@@ -0,0 +1,45 @@
1
+ import { ReactNode, SyntheticEvent, useState } from 'react';
2
+ import { Story, Meta } from '@storybook/react/types-6-0';
3
+ import VirtualizedAutocomplete, { VirtualizedAutocompleteProps } from './';
4
+
5
+ export default {
6
+ title: 'VirtualizedAutocomplete',
7
+ component: VirtualizedAutocomplete,
8
+ argType: {},
9
+ } as Meta;
10
+
11
+ const Template: Story<VirtualizedAutocompleteProps> = (args) => {
12
+ const [value, setValue] = useState<{component: string | ReactNode, value: string, inputLabel: string}>({component: '- None -', value: '0', inputLabel: '- None -'});
13
+
14
+ const [options, setOptions] = useState<{component: string | ReactNode, value: string, inputLabel: string}[]>([]);
15
+
16
+ const handleOnOpen = async () => {
17
+ const largeArr = new Array(1000).fill(null);
18
+ await new Promise((resolve) => setTimeout(resolve, 3000))
19
+ const data = largeArr.map((_, idx) => ({component: <div>{`Test ${idx}`}</div>, value: String(Math.random()), inputLabel: `Test ${idx}`}));
20
+ setOptions(data);
21
+ }
22
+
23
+ const handleOnChange = (e: SyntheticEvent<Element, Event>, option: {component: string | ReactNode, value: string, inputLabel: string}) => {
24
+ setValue(option);
25
+ }
26
+
27
+ return (
28
+ <VirtualizedAutocomplete
29
+ {...args}
30
+ value={value}
31
+ onChange={handleOnChange}
32
+ options={options}
33
+ onOpen={handleOnOpen}
34
+ />
35
+ );
36
+ };
37
+
38
+ export const Default = Template.bind({});
39
+ Default.args = {
40
+ helperText: 'OneToOne helperText',
41
+ placeholder: 'OneToOne placeholder'
42
+ };
43
+
44
+
45
+
@@ -0,0 +1,69 @@
1
+ import { ReactNode, useState } from 'react';
2
+ import { AutocompleteProps, Popper, styled, TextField, FormLabel, FormControl, InputAdornment } from '@mui/material';
3
+ import Autocomplete, { autocompleteClasses } from '@mui/material/Autocomplete';
4
+ import { ListboxComponent } from '../utils/virtualization';
5
+
6
+ export interface VirtualizedAutocompleteProps extends Omit<AutocompleteProps<any, false, false, false>, 'renderInput'> {
7
+ helperText?: string;
8
+ placeholder?: string;
9
+ error?: boolean;
10
+ startAdornment?: ReactNode;
11
+ endAdornment?: ReactNode;
12
+ /**
13
+ * Structure for option
14
+ */
15
+ options: {
16
+ /**
17
+ * Component to be rendered in the dropdown
18
+ */
19
+ component: ReactNode | string;
20
+ /**
21
+ * Value of option
22
+ */
23
+ value: string;
24
+ /**
25
+ * Label that should display in the input when selected
26
+ */
27
+ inputLabel: string;
28
+ }[]
29
+ }
30
+
31
+ const VirtualizedAutocomplete = ({helperText, placeholder, error, startAdornment, endAdornment, ...props }: VirtualizedAutocompleteProps) => {
32
+ return (
33
+ <Autocomplete
34
+ fullWidth
35
+ disableListWrap
36
+ size='small'
37
+ PopperComponent={StyledPopper}
38
+ ListboxComponent={ListboxComponent}
39
+ renderInput={(params) => (
40
+ <TextField
41
+ {...params}
42
+ helperText={helperText}
43
+ error={error}
44
+ placeholder={placeholder}
45
+ InputProps={{
46
+ ...params.InputProps,
47
+ startAdornment: <InputAdornment position='end'>{startAdornment}</InputAdornment>,
48
+ endAdornment: <>{params.InputProps.endAdornment}<InputAdornment sx={{ position: 'relative', right: '40px'}} position='end'>{endAdornment}</InputAdornment></>
49
+ }}
50
+ />
51
+ )}
52
+ getOptionLabel={(option) => option.inputLabel}
53
+ renderOption={(props, option) => [props, option.component]}
54
+ {...props}
55
+ />
56
+ );
57
+ };
58
+
59
+ export default VirtualizedAutocomplete;
60
+
61
+ const StyledPopper = styled(Popper)({
62
+ [`& .${autocompleteClasses.listbox}`]: {
63
+ boxSizing: 'border-box',
64
+ '& ul': {
65
+ padding: 0,
66
+ margin: 0,
67
+ },
68
+ },
69
+ });
package/src/index.ts CHANGED
@@ -6,8 +6,8 @@ export { default as FieldTypeDate } from './FieldTypeDate';
6
6
  export { default as FieldTypeDateTime } from './FieldTypeDateTime';
7
7
  export { default as FieldTypeColor } from './FieldTypeColor';
8
8
  export { default as FieldTypeNumber } from './FieldTypeNumber';
9
- export { default as FieldTypeDropdown } from './FieldTypeDropdown';
10
9
  export { default as FieldTypeOneToOne} from './FieldTypeOneToOne';
11
10
  export { default as FieldTypeOneToMany} from './FieldTypeOneToMany';
12
11
  export { default as CopyButton } from './CopyButton';
13
- export { default as ConfirmDialog } from './ConfirmDialog';
12
+ export { default as ConfirmDialog } from './ConfirmDialog';
13
+ export { default as VirtualizedAutocomplete } from './VitualizedAutocomplete';
@@ -9,6 +9,13 @@ let theme: Theme = createTheme({
9
9
 
10
10
  theme = createTheme(theme, {
11
11
  components: {
12
+ MuiAccordionSummary: {
13
+ styleOverrides: {
14
+ root: {
15
+ backgroundColor: '#e4e9f1',
16
+ },
17
+ },
18
+ },
12
19
  MuiButton: {
13
20
  styleOverrides: {
14
21
  root: {
Binary file
@@ -1,52 +0,0 @@
1
- import { ChangeEvent, useState } from 'react';
2
- import { Story, Meta } from '@storybook/react/types-6-0';
3
- import FieldTypeDropdown, { FieldTypeDropdownProps } from './';
4
- import { MenuItem } from '@mui/material';
5
-
6
- export default {
7
- title: 'FieldTypeDropdown',
8
- component: FieldTypeDropdown,
9
- argType: {},
10
- } as Meta;
11
-
12
- const options = [
13
- {
14
- value: 'option1',
15
- label: 'Option 1',
16
- },
17
- {
18
- value: 'option2',
19
- label: 'Option 2',
20
- },
21
- {
22
- value: 'option3',
23
- label: 'Option 3',
24
- },
25
- ];
26
-
27
- const Template: Story<FieldTypeDropdownProps> = (args) => {
28
- const [value, setValue] = useState('');
29
-
30
- const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
31
- setValue(e.target.value);
32
- }
33
-
34
- return (
35
- <FieldTypeDropdown
36
- {...args}
37
- value={value}
38
- onChange={handleOnChange}
39
- options={options}
40
- />
41
- );
42
- };
43
-
44
- export const Default = Template.bind({});
45
- Default.args = {
46
- placeholder: 'Placeholder Text...',
47
- label: 'Dropdown label',
48
- helperText: 'Dropdown helper text',
49
- };
50
-
51
-
52
-
@@ -1,41 +0,0 @@
1
- import { MenuItem } from '@mui/material';
2
- import MuiTextField, { OutlinedTextFieldProps } from '@mui/material/TextField';
3
- import { FormControl, FormLabel } from '@mui/material';
4
-
5
- interface Option {
6
- label: string;
7
- value: any;
8
- }
9
-
10
- export interface FieldTypeDropdownProps extends Omit<OutlinedTextFieldProps, 'variant'> {
11
- options: Option[];
12
- }
13
-
14
- const FieldTypeDropdown = ({label, options, required, ...props }: FieldTypeDropdownProps) => {
15
-
16
- return (
17
- <FormControl fullWidth required={required}>
18
- <FormLabel>{label}</FormLabel>
19
- <MuiTextField
20
- size="small"
21
- variant='outlined'
22
- select
23
- SelectProps={{
24
- displayEmpty: true,
25
- }}
26
- {...props}
27
- >
28
- <MenuItem key={''} value={''}>
29
- - None -
30
- </MenuItem>
31
- {options.map((option) => (
32
- <MenuItem key={option.value} value={option.value}>
33
- {option.label}
34
- </MenuItem>
35
- ))}
36
- </MuiTextField>
37
- </FormControl>
38
- );
39
- };
40
-
41
- export default FieldTypeDropdown;