@zesty-io/material 0.0.3 → 0.0.4
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/.storybook/main.js +15 -2
- package/.storybook/preview-head.html +1 -0
- package/.storybook/preview.js +14 -8
- package/es/CopyButton/CopyButton.stories.d.ts +5 -0
- package/es/CopyButton/CopyButton.stories.js +14 -0
- package/es/CopyButton/index.d.ts +10 -0
- package/es/CopyButton/index.js +26 -0
- package/es/FieldTypeSort/FieldTypeSort.stories.d.ts +5 -0
- package/es/FieldTypeSort/FieldTypeSort.stories.js +20 -0
- package/es/FieldTypeSort/index.d.ts +7 -0
- package/es/FieldTypeSort/index.js +34 -0
- package/es/FieldTypeText/FieldTypeText.stories.d.ts +6 -0
- package/es/FieldTypeText/FieldTypeText.stories.js +29 -0
- package/es/FieldTypeText/index.d.ts +12 -0
- package/es/FieldTypeText/index.js +15 -0
- package/es/FieldTypeUrl/FieldTypeUrl.stories.d.ts +5 -0
- package/es/FieldTypeUrl/FieldTypeUrl.stories.js +21 -0
- package/es/FieldTypeUrl/index.d.ts +12 -0
- package/es/FieldTypeUrl/index.js +21 -0
- package/es/index.d.ts +1 -0
- package/es/index.js +1 -0
- package/es/theme/Theme.stories.d.ts +4 -0
- package/es/theme/Theme.stories.js +10 -0
- package/es/theme/index.js +25 -8
- package/package.json +2 -1
- package/src/CopyButton/CopyButton.stories.tsx +20 -0
- package/src/CopyButton/index.tsx +55 -0
- package/src/FieldTypeSort/FieldTypeSort.stories.tsx +35 -0
- package/src/FieldTypeSort/index.tsx +109 -0
- package/src/FieldTypeText/FieldTypeText.stories.tsx +43 -0
- package/src/FieldTypeText/index.tsx +43 -0
- package/src/FieldTypeUrl/FieldTypeUrl.stories.tsx +33 -0
- package/src/FieldTypeUrl/index.tsx +50 -0
- package/src/index.ts +1 -0
- package/src/{stories → theme}/Theme.stories.tsx +1 -1
- package/src/theme/index.ts +28 -9
package/.storybook/main.js
CHANGED
|
@@ -6,7 +6,20 @@ module.exports = {
|
|
|
6
6
|
"addons": [
|
|
7
7
|
"@storybook/addon-links",
|
|
8
8
|
"@storybook/addon-essentials",
|
|
9
|
-
"@storybook/addon-interactions"
|
|
10
9
|
],
|
|
11
|
-
"framework": "@storybook/react"
|
|
10
|
+
"framework": "@storybook/react",
|
|
11
|
+
typescript: {
|
|
12
|
+
check: true,
|
|
13
|
+
reactDocgen: 'react-docgen-typescript',
|
|
14
|
+
reactDocgenTypescriptOptions: {
|
|
15
|
+
shouldExtractLiteralValuesFromEnum: true,
|
|
16
|
+
shouldRemoveUndefinedFromOptional: true,
|
|
17
|
+
propFilter: (prop) => {
|
|
18
|
+
return prop.parent
|
|
19
|
+
? /@mui/.test(prop.parent.fileName) ||
|
|
20
|
+
!/node_modules/.test(prop.parent.fileName)
|
|
21
|
+
: true;
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
12
25
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Mulish" />
|
package/.storybook/preview.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ThemeProvider } from 'emotion-theming';
|
|
3
|
+
import { theme } from '../src/index.ts';
|
|
4
|
+
|
|
1
5
|
export const parameters = {
|
|
2
|
-
actions: { argTypesRegex:
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
actions: { argTypesRegex: '^on[A-Z].*' },
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const decorators = [
|
|
10
|
+
(Story) => (
|
|
11
|
+
<ThemeProvider theme={theme}>
|
|
12
|
+
<Story />
|
|
13
|
+
</ThemeProvider>
|
|
14
|
+
),
|
|
15
|
+
];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import CopyButton from '.';
|
|
3
|
+
export default {
|
|
4
|
+
title: 'CopyButton',
|
|
5
|
+
component: CopyButton,
|
|
6
|
+
argType: {},
|
|
7
|
+
};
|
|
8
|
+
const Template = (args) => {
|
|
9
|
+
return (_jsx(CopyButton, { ...args }));
|
|
10
|
+
};
|
|
11
|
+
export const Default = Template.bind({});
|
|
12
|
+
Default.args = {
|
|
13
|
+
value: 'Copy Me!'
|
|
14
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { ButtonProps } from '@mui/material/Button';
|
|
3
|
+
export interface CopyButtonProps extends ButtonProps {
|
|
4
|
+
/**
|
|
5
|
+
* Value to be copied to clipboard
|
|
6
|
+
*/
|
|
7
|
+
value: string;
|
|
8
|
+
}
|
|
9
|
+
declare const CopyButton: ({ value, sx, ...props }: CopyButtonProps) => JSX.Element;
|
|
10
|
+
export default CopyButton;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useState, useEffect } from 'react';
|
|
3
|
+
import Button from '@mui/material/Button';
|
|
4
|
+
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
|
5
|
+
import CheckIcon from '@mui/icons-material/Check';
|
|
6
|
+
const CopyButton = ({ value, sx, ...props }) => {
|
|
7
|
+
const [copied, setCopied] = useState(false);
|
|
8
|
+
const copyValue = useCallback(() => {
|
|
9
|
+
navigator?.clipboard.writeText(value);
|
|
10
|
+
setCopied(true);
|
|
11
|
+
}, [value]);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const iconTimer = setTimeout(() => {
|
|
14
|
+
setCopied(false);
|
|
15
|
+
}, 500);
|
|
16
|
+
return () => {
|
|
17
|
+
clearTimeout(iconTimer);
|
|
18
|
+
};
|
|
19
|
+
}, [copied]);
|
|
20
|
+
return (_jsxs(Button, { variant: 'outlined', onClick: copyValue, size: "small", title: props.children ? `Copy ${props.children}` : `Copy ${value}`, sx: {
|
|
21
|
+
textTransform: 'unset',
|
|
22
|
+
// Spread sx prop at the end to allow sx prop overrides
|
|
23
|
+
...sx,
|
|
24
|
+
}, ...props, children: [copied ? (_jsx(CheckIcon, { color: 'success', fontSize: 'small' })) : (_jsx(ContentCopyIcon, { fontSize: 'small' })), props.children ? props.children : value] }));
|
|
25
|
+
};
|
|
26
|
+
export default CopyButton;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import FieldTypeSort from './';
|
|
4
|
+
export default {
|
|
5
|
+
title: 'FieldTypeSort',
|
|
6
|
+
component: FieldTypeSort,
|
|
7
|
+
argType: {},
|
|
8
|
+
};
|
|
9
|
+
const Template = (args) => {
|
|
10
|
+
const [value, setValue] = useState('3');
|
|
11
|
+
const handleOnChange = (e) => {
|
|
12
|
+
setValue(e.target.value);
|
|
13
|
+
};
|
|
14
|
+
return (_jsx(FieldTypeSort, { ...args, value: value, onChange: handleOnChange }));
|
|
15
|
+
};
|
|
16
|
+
export const Default = Template.bind({});
|
|
17
|
+
Default.args = {
|
|
18
|
+
placeholder: 'Placeholder Text...',
|
|
19
|
+
label: 'Some label',
|
|
20
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { OutlinedTextFieldProps } from '@mui/material/TextField';
|
|
3
|
+
export interface FieldTypeSortProps extends Omit<OutlinedTextFieldProps, 'variant'> {
|
|
4
|
+
value: string;
|
|
5
|
+
}
|
|
6
|
+
declare const FieldTypeSort: ({ value, InputProps, InputLabelProps, inputProps, sx, ...props }: FieldTypeSortProps) => JSX.Element;
|
|
7
|
+
export default FieldTypeSort;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
import MuiTextField from '@mui/material/TextField';
|
|
4
|
+
import { Button, InputAdornment } from '@mui/material';
|
|
5
|
+
import AddIcon from '@mui/icons-material/Add';
|
|
6
|
+
import RemoveIcon from '@mui/icons-material/Remove';
|
|
7
|
+
const FieldTypeSort = ({ value, InputProps, InputLabelProps, inputProps, sx, ...props }) => {
|
|
8
|
+
const inputRef = useRef(null);
|
|
9
|
+
return (_jsx(MuiTextField, { size: "small", variant: 'outlined', type: 'number', value: value, sx: {
|
|
10
|
+
width: 165,
|
|
11
|
+
// Spread props at the end to allow sx prop overrides
|
|
12
|
+
...sx
|
|
13
|
+
}, InputProps: {
|
|
14
|
+
startAdornment: (_jsx(InputAdornment, { position: "start", children: _jsx(Button, { size: "small", variant: "contained", onClick: () => {
|
|
15
|
+
if (inputRef.current)
|
|
16
|
+
inputRef.current.value = String(+inputRef.current.value + 1);
|
|
17
|
+
}, children: _jsx(AddIcon, { fontSize: 'small' }) }) })),
|
|
18
|
+
endAdornment: (_jsx(InputAdornment, { position: "end", children: _jsx(Button, { size: "small", variant: "contained", onClick: () => {
|
|
19
|
+
if (inputRef.current)
|
|
20
|
+
inputRef.current.value = String(+inputRef.current.value - 1);
|
|
21
|
+
}, children: _jsx(RemoveIcon, { fontSize: 'small' }) }) })),
|
|
22
|
+
// Spread props at the end to allow Input prop overrides
|
|
23
|
+
...InputProps,
|
|
24
|
+
}, InputLabelProps: {
|
|
25
|
+
shrink: true,
|
|
26
|
+
// Spread props at the end to allow InputLabel prop overrides
|
|
27
|
+
...InputLabelProps,
|
|
28
|
+
}, inputProps: {
|
|
29
|
+
ref: inputRef,
|
|
30
|
+
// Spread props at the end to allow inputProps prop overrides
|
|
31
|
+
...inputProps,
|
|
32
|
+
}, ...props }));
|
|
33
|
+
};
|
|
34
|
+
export default FieldTypeSort;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Story, Meta } from '@storybook/react/types-6-0';
|
|
2
|
+
import { FieldTypeTextProps } from './';
|
|
3
|
+
declare const _default: Meta<import("@storybook/react/types-6-0").Args>;
|
|
4
|
+
export default _default;
|
|
5
|
+
export declare const Default: Story<FieldTypeTextProps>;
|
|
6
|
+
export declare const TextArea: Story<FieldTypeTextProps>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import FieldTypeText from './';
|
|
4
|
+
export default {
|
|
5
|
+
title: 'FieldTypeText',
|
|
6
|
+
component: FieldTypeText,
|
|
7
|
+
argType: {},
|
|
8
|
+
};
|
|
9
|
+
const Template = (args) => {
|
|
10
|
+
const [value, setValue] = useState('');
|
|
11
|
+
const handleOnChange = (e) => {
|
|
12
|
+
setValue(e.target.value);
|
|
13
|
+
};
|
|
14
|
+
return (_jsx(FieldTypeText, { ...args, value: value, onChange: handleOnChange }));
|
|
15
|
+
};
|
|
16
|
+
export const Default = Template.bind({});
|
|
17
|
+
Default.args = {
|
|
18
|
+
placeholder: 'Placeholder Text...',
|
|
19
|
+
label: 'Some label',
|
|
20
|
+
fullWidth: true,
|
|
21
|
+
};
|
|
22
|
+
export const TextArea = Template.bind({});
|
|
23
|
+
TextArea.args = {
|
|
24
|
+
multiline: true,
|
|
25
|
+
rows: 4,
|
|
26
|
+
placeholder: 'Placeholder Text...',
|
|
27
|
+
label: 'Some Label',
|
|
28
|
+
fullWidth: true,
|
|
29
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { OutlinedTextFieldProps } from '@mui/material/TextField';
|
|
3
|
+
export interface FieldTypeTextProps extends Omit<OutlinedTextFieldProps, 'variant'> {
|
|
4
|
+
/**
|
|
5
|
+
* Max length of the field
|
|
6
|
+
* @default 150
|
|
7
|
+
*/
|
|
8
|
+
maxLength?: number;
|
|
9
|
+
value: string;
|
|
10
|
+
}
|
|
11
|
+
declare const FieldTypeText: ({ maxLength, value, helperText, InputProps, InputLabelProps, ...props }: FieldTypeTextProps) => JSX.Element;
|
|
12
|
+
export default FieldTypeText;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import MuiTextField from '@mui/material/TextField';
|
|
3
|
+
import { InputAdornment } from '@mui/material';
|
|
4
|
+
const FieldTypeText = ({ maxLength = 150, value, helperText, InputProps, InputLabelProps, ...props }) => {
|
|
5
|
+
return (_jsx(MuiTextField, { size: "small", variant: 'outlined', value: value, InputProps: {
|
|
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 }));
|
|
14
|
+
};
|
|
15
|
+
export default FieldTypeText;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import FieldTypeUrl from './';
|
|
4
|
+
export default {
|
|
5
|
+
title: 'FieldTypeUrl',
|
|
6
|
+
component: FieldTypeUrl,
|
|
7
|
+
argType: {},
|
|
8
|
+
};
|
|
9
|
+
const Template = (args) => {
|
|
10
|
+
const [value, setValue] = useState('');
|
|
11
|
+
const handleOnChange = (e) => {
|
|
12
|
+
setValue(e.target.value);
|
|
13
|
+
};
|
|
14
|
+
return (_jsx(FieldTypeUrl, { ...args, value: value, onChange: handleOnChange }));
|
|
15
|
+
};
|
|
16
|
+
export const Default = Template.bind({});
|
|
17
|
+
Default.args = {
|
|
18
|
+
placeholder: 'Placeholder Text...',
|
|
19
|
+
label: 'Some label',
|
|
20
|
+
fullWidth: true,
|
|
21
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { OutlinedTextFieldProps } from '@mui/material/TextField';
|
|
3
|
+
export interface FieldTypeUrlProps extends Omit<OutlinedTextFieldProps, 'variant'> {
|
|
4
|
+
/**
|
|
5
|
+
* Max length of the field
|
|
6
|
+
* @default 2000
|
|
7
|
+
*/
|
|
8
|
+
maxLength?: number;
|
|
9
|
+
value: string;
|
|
10
|
+
}
|
|
11
|
+
declare const FieldTypeUrl: ({ maxLength, value, helperText, InputProps, InputLabelProps, inputProps, ...props }: FieldTypeUrlProps) => JSX.Element;
|
|
12
|
+
export default FieldTypeUrl;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
import MuiTextField from '@mui/material/TextField';
|
|
4
|
+
import { InputAdornment } from '@mui/material';
|
|
5
|
+
const FieldTypeUrl = ({ maxLength = 2000, value, helperText, InputProps, InputLabelProps, inputProps, ...props }) => {
|
|
6
|
+
const inputRef = useRef(null);
|
|
7
|
+
return (_jsx(MuiTextField, { size: "small", type: 'url', variant: 'outlined', value: value, InputProps: {
|
|
8
|
+
endAdornment: (_jsx(InputAdornment, { position: "end", children: _jsxs(_Fragment, { children: [value.length, "/", maxLength] }) })),
|
|
9
|
+
// Spread props at the end to allow Input prop overrides
|
|
10
|
+
...InputProps,
|
|
11
|
+
}, InputLabelProps: {
|
|
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 }));
|
|
20
|
+
};
|
|
21
|
+
export default FieldTypeUrl;
|
package/es/index.d.ts
CHANGED
package/es/index.js
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import ReactJson from 'react-json-view';
|
|
3
|
+
import theme from '.';
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Theme',
|
|
6
|
+
};
|
|
7
|
+
const Template = (args) => {
|
|
8
|
+
return (_jsx(ReactJson, { src: theme }));
|
|
9
|
+
};
|
|
10
|
+
export const Default = Template.bind({});
|
package/es/theme/index.js
CHANGED
|
@@ -7,26 +7,43 @@ let theme = createTheme({
|
|
|
7
7
|
});
|
|
8
8
|
theme = createTheme(theme, {
|
|
9
9
|
components: {
|
|
10
|
+
MuiButton: {
|
|
11
|
+
styleOverrides: {
|
|
12
|
+
root: {
|
|
13
|
+
minWidth: 'auto',
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
},
|
|
10
17
|
MuiTooltip: {
|
|
11
18
|
styleOverrides: {
|
|
12
19
|
tooltip: {
|
|
13
20
|
color: theme.palette.primary.contrastText,
|
|
14
21
|
backgroundColor: theme.palette.primary.main,
|
|
15
|
-
fontSize:
|
|
16
|
-
lineHeight:
|
|
22
|
+
fontSize: '14px',
|
|
23
|
+
lineHeight: '20px',
|
|
17
24
|
},
|
|
18
25
|
arrow: {
|
|
19
26
|
color: theme.palette.primary.main,
|
|
20
|
-
}
|
|
21
|
-
}
|
|
27
|
+
},
|
|
28
|
+
},
|
|
22
29
|
},
|
|
23
30
|
MuiInputBase: {
|
|
24
31
|
styleOverrides: {
|
|
25
32
|
root: {
|
|
26
|
-
backgroundColor: theme.palette.primary.contrastText
|
|
33
|
+
backgroundColor: theme.palette.primary.contrastText,
|
|
27
34
|
},
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
MuiToggleButton: {
|
|
38
|
+
styleOverrides: {
|
|
39
|
+
root: ({ ownerState, theme }) => ({
|
|
40
|
+
...(ownerState.selected && {
|
|
41
|
+
color: `${theme.palette[ownerState.color].contrastText} !important`,
|
|
42
|
+
backgroundColor: `${theme.palette[ownerState.color].main} !important`,
|
|
43
|
+
}),
|
|
44
|
+
}),
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
31
48
|
});
|
|
32
49
|
export default theme;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zesty-io/material",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Contains custom components which are in addition to the @mui design-system",
|
|
5
5
|
"author": "Zesty.io",
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"babel-loader": "^8.2.5",
|
|
44
44
|
"gh-pages": "^3.2.3",
|
|
45
45
|
"react": "^18.1.0",
|
|
46
|
+
"react-docgen-typescript": "^2.2.2",
|
|
46
47
|
"react-dom": "^18.1.0",
|
|
47
48
|
"react-json-view": "^1.21.3",
|
|
48
49
|
"typescript": "^4.6.3"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Story, Meta } from '@storybook/react/types-6-0';
|
|
2
|
+
import CopyButton, { CopyButtonProps } from '.';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'CopyButton',
|
|
6
|
+
component: CopyButton,
|
|
7
|
+
argType: {},
|
|
8
|
+
} as Meta;
|
|
9
|
+
|
|
10
|
+
const Template: Story<CopyButtonProps> = (args) => {
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<CopyButton {...args} />
|
|
14
|
+
);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const Default = Template.bind({});
|
|
18
|
+
Default.args = {
|
|
19
|
+
value: 'Copy Me!'
|
|
20
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { useCallback, useState, useEffect } from 'react';
|
|
2
|
+
import Button, { ButtonProps } from '@mui/material/Button';
|
|
3
|
+
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
|
4
|
+
import CheckIcon from '@mui/icons-material/Check';
|
|
5
|
+
|
|
6
|
+
export interface CopyButtonProps extends ButtonProps {
|
|
7
|
+
/**
|
|
8
|
+
* Value to be copied to clipboard
|
|
9
|
+
*/
|
|
10
|
+
value: string ;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const CopyButton = ({value, sx, ...props }: CopyButtonProps) => {
|
|
14
|
+
const [copied, setCopied] = useState(false);
|
|
15
|
+
|
|
16
|
+
const copyValue = useCallback(() => {
|
|
17
|
+
navigator?.clipboard.writeText(value);
|
|
18
|
+
setCopied(true);
|
|
19
|
+
}, [value]);
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
const iconTimer = setTimeout(() => {
|
|
23
|
+
setCopied(false);
|
|
24
|
+
}, 500);
|
|
25
|
+
|
|
26
|
+
return () => {
|
|
27
|
+
clearTimeout(iconTimer);
|
|
28
|
+
};
|
|
29
|
+
}, [copied]);
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<Button
|
|
33
|
+
variant='outlined'
|
|
34
|
+
onClick={copyValue}
|
|
35
|
+
size="small"
|
|
36
|
+
title={props.children ? `Copy ${props.children}` : `Copy ${value}`}
|
|
37
|
+
sx={{
|
|
38
|
+
textTransform: 'unset',
|
|
39
|
+
// Spread sx prop at the end to allow sx prop overrides
|
|
40
|
+
...sx,
|
|
41
|
+
}}
|
|
42
|
+
// Spread props at the end to allow prop overrides
|
|
43
|
+
{...props}
|
|
44
|
+
>
|
|
45
|
+
{copied ? (
|
|
46
|
+
<CheckIcon color='success' fontSize='small' />
|
|
47
|
+
) : (
|
|
48
|
+
<ContentCopyIcon fontSize='small' />
|
|
49
|
+
)}
|
|
50
|
+
{props.children ? props.children : value}
|
|
51
|
+
</Button>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default CopyButton;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ChangeEvent, useState } from 'react';
|
|
2
|
+
import { Story, Meta } from '@storybook/react/types-6-0';
|
|
3
|
+
import { TextFieldProps } from '@mui/material';
|
|
4
|
+
import FieldTypeSort, { FieldTypeSortProps } from './';
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
title: 'FieldTypeSort',
|
|
8
|
+
component: FieldTypeSort,
|
|
9
|
+
argType: {},
|
|
10
|
+
} as Meta;
|
|
11
|
+
|
|
12
|
+
const Template: Story<FieldTypeSortProps> = (args) => {
|
|
13
|
+
const [value, setValue] = useState('3');
|
|
14
|
+
|
|
15
|
+
const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|
16
|
+
setValue(e.target.value);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<FieldTypeSort
|
|
21
|
+
{...args}
|
|
22
|
+
value={value}
|
|
23
|
+
onChange={handleOnChange}
|
|
24
|
+
/>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const Default = Template.bind({});
|
|
29
|
+
Default.args = {
|
|
30
|
+
placeholder: 'Placeholder Text...',
|
|
31
|
+
label: 'Some label',
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React, { ChangeEvent, ReactNode, useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import MuiTextField, { OutlinedTextFieldProps } from '@mui/material/TextField';
|
|
3
|
+
import { Button, InputAdornment } from '@mui/material';
|
|
4
|
+
import AddIcon from '@mui/icons-material/Add';
|
|
5
|
+
import RemoveIcon from '@mui/icons-material/Remove';
|
|
6
|
+
|
|
7
|
+
export interface FieldTypeSortProps extends Omit<OutlinedTextFieldProps, 'variant'> {
|
|
8
|
+
value: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const FieldTypeSort = ({value, InputProps, InputLabelProps, inputProps, sx, ...props }: FieldTypeSortProps) => {
|
|
12
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<MuiTextField
|
|
16
|
+
size="small"
|
|
17
|
+
variant='outlined'
|
|
18
|
+
type='number'
|
|
19
|
+
value={value}
|
|
20
|
+
sx={{
|
|
21
|
+
width: 165,
|
|
22
|
+
// Spread props at the end to allow sx prop overrides
|
|
23
|
+
...sx
|
|
24
|
+
}}
|
|
25
|
+
InputProps={{
|
|
26
|
+
startAdornment: (
|
|
27
|
+
<InputAdornment position="start">
|
|
28
|
+
<Button
|
|
29
|
+
size="small"
|
|
30
|
+
variant="contained"
|
|
31
|
+
onClick={() => {
|
|
32
|
+
if(inputRef.current) inputRef.current.value = String(+inputRef.current.value + 1)
|
|
33
|
+
}}><AddIcon fontSize='small' />
|
|
34
|
+
</Button>
|
|
35
|
+
</InputAdornment>
|
|
36
|
+
),
|
|
37
|
+
endAdornment: (
|
|
38
|
+
<InputAdornment position="end">
|
|
39
|
+
<Button
|
|
40
|
+
size="small"
|
|
41
|
+
variant="contained"
|
|
42
|
+
onClick={() => {
|
|
43
|
+
if(inputRef.current) inputRef.current.value = String(+inputRef.current.value - 1)
|
|
44
|
+
}}><RemoveIcon fontSize='small' />
|
|
45
|
+
</Button>
|
|
46
|
+
</InputAdornment>
|
|
47
|
+
),
|
|
48
|
+
// Spread props at the end to allow Input prop overrides
|
|
49
|
+
...InputProps,
|
|
50
|
+
}}
|
|
51
|
+
InputLabelProps={{
|
|
52
|
+
shrink: true,
|
|
53
|
+
// Spread props at the end to allow InputLabel prop overrides
|
|
54
|
+
...InputLabelProps,
|
|
55
|
+
}}
|
|
56
|
+
inputProps={{
|
|
57
|
+
ref: inputRef,
|
|
58
|
+
// Spread props at the end to allow inputProps prop overrides
|
|
59
|
+
...inputProps,
|
|
60
|
+
}}
|
|
61
|
+
// Spread props at the end to allow prop overrides
|
|
62
|
+
{...props}
|
|
63
|
+
/>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export default FieldTypeSort;
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
// const FieldTypeSort = ({InputProps, InputLabelProps, ...props }: FieldTypeSortProps) => {
|
|
71
|
+
|
|
72
|
+
// return (
|
|
73
|
+
// <MuiTextField
|
|
74
|
+
// variant='outlined'
|
|
75
|
+
// type='number'
|
|
76
|
+
// InputProps={{
|
|
77
|
+
// startAdornment: (
|
|
78
|
+
// <InputAdornment position="start">
|
|
79
|
+
// <Button
|
|
80
|
+
// variant="contained"
|
|
81
|
+
// onClick={() => {
|
|
82
|
+
// callback(props.value + 1)
|
|
83
|
+
// }}>+</Button>
|
|
84
|
+
// </InputAdornment>
|
|
85
|
+
// ),
|
|
86
|
+
// endAdornment: (
|
|
87
|
+
// <InputAdornment position="end">
|
|
88
|
+
// <Button
|
|
89
|
+
// variant="contained"
|
|
90
|
+
// onClick={() => {
|
|
91
|
+
// callback(props.value - 1)
|
|
92
|
+
// }}>-</Button>
|
|
93
|
+
// </InputAdornment>
|
|
94
|
+
// ),
|
|
95
|
+
// // Spread props at the end to allow Input prop overrides
|
|
96
|
+
// ...InputProps,
|
|
97
|
+
// }}
|
|
98
|
+
// InputLabelProps={{
|
|
99
|
+
// shrink: true,
|
|
100
|
+
// // Spread props at the end to allow InputLabel prop overrides
|
|
101
|
+
// ...InputLabelProps,
|
|
102
|
+
// }}
|
|
103
|
+
// // Spread props at the end to allow prop overrides
|
|
104
|
+
// {...props}
|
|
105
|
+
// />
|
|
106
|
+
// );
|
|
107
|
+
// };
|
|
108
|
+
|
|
109
|
+
// export default FieldTypeSort;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ChangeEvent, useState } from 'react';
|
|
2
|
+
import { Story, Meta } from '@storybook/react/types-6-0';
|
|
3
|
+
import FieldTypeText, { FieldTypeTextProps } from './';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: 'FieldTypeText',
|
|
7
|
+
component: FieldTypeText,
|
|
8
|
+
argType: {},
|
|
9
|
+
} as Meta;
|
|
10
|
+
|
|
11
|
+
const Template: Story<FieldTypeTextProps> = (args) => {
|
|
12
|
+
const [value, setValue] = useState('');
|
|
13
|
+
|
|
14
|
+
const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|
15
|
+
setValue(e.target.value);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<FieldTypeText
|
|
20
|
+
{...args}
|
|
21
|
+
value={value}
|
|
22
|
+
onChange={handleOnChange}
|
|
23
|
+
/>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const Default = Template.bind({});
|
|
28
|
+
Default.args = {
|
|
29
|
+
placeholder: 'Placeholder Text...',
|
|
30
|
+
label: 'Some label',
|
|
31
|
+
fullWidth: true,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const TextArea = Template.bind({});
|
|
35
|
+
TextArea.args = {
|
|
36
|
+
multiline: true,
|
|
37
|
+
rows: 4,
|
|
38
|
+
placeholder: 'Placeholder Text...',
|
|
39
|
+
label: 'Some Label',
|
|
40
|
+
fullWidth: true,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React, { ChangeEvent, ReactNode, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import MuiTextField, { OutlinedTextFieldProps } from '@mui/material/TextField';
|
|
3
|
+
import { Box, InputAdornment } from '@mui/material';
|
|
4
|
+
|
|
5
|
+
export interface FieldTypeTextProps extends Omit<OutlinedTextFieldProps, 'variant'> {
|
|
6
|
+
/**
|
|
7
|
+
* Max length of the field
|
|
8
|
+
* @default 150
|
|
9
|
+
*/
|
|
10
|
+
maxLength?: number;
|
|
11
|
+
value: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const FieldTypeText = ({maxLength = 150, value, helperText, InputProps, InputLabelProps, ...props }: FieldTypeTextProps) => {
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<MuiTextField
|
|
18
|
+
size="small"
|
|
19
|
+
variant='outlined'
|
|
20
|
+
value={value}
|
|
21
|
+
InputProps={{
|
|
22
|
+
endAdornment: (
|
|
23
|
+
<InputAdornment position="end">
|
|
24
|
+
<>{value.length}/{maxLength}</>
|
|
25
|
+
</InputAdornment>
|
|
26
|
+
),
|
|
27
|
+
// Spread props at the end to allow Input prop overrides
|
|
28
|
+
...InputProps,
|
|
29
|
+
}}
|
|
30
|
+
InputLabelProps={{
|
|
31
|
+
shrink: true,
|
|
32
|
+
// Spread props at the end to allow InputLabel prop overrides
|
|
33
|
+
...InputLabelProps,
|
|
34
|
+
}}
|
|
35
|
+
error={value.length > maxLength}
|
|
36
|
+
helperText={value.length > maxLength ? 'Your input is over the specified limit' : helperText}
|
|
37
|
+
// Spread props at the end to allow prop overrides
|
|
38
|
+
{...props}
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default FieldTypeText;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ChangeEvent, useState } from 'react';
|
|
2
|
+
import { Story, Meta } from '@storybook/react/types-6-0';
|
|
3
|
+
import FieldTypeUrl, { FieldTypeUrlProps } from './';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: 'FieldTypeUrl',
|
|
7
|
+
component: FieldTypeUrl,
|
|
8
|
+
argType: {},
|
|
9
|
+
} as Meta;
|
|
10
|
+
|
|
11
|
+
const Template: Story<FieldTypeUrlProps> = (args) => {
|
|
12
|
+
const [value, setValue] = useState('');
|
|
13
|
+
|
|
14
|
+
const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|
15
|
+
setValue(e.target.value);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<FieldTypeUrl
|
|
20
|
+
{...args}
|
|
21
|
+
value={value}
|
|
22
|
+
onChange={handleOnChange}
|
|
23
|
+
/>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const Default = Template.bind({});
|
|
28
|
+
Default.args = {
|
|
29
|
+
placeholder: 'Placeholder Text...',
|
|
30
|
+
label: 'Some label',
|
|
31
|
+
fullWidth: true,
|
|
32
|
+
};
|
|
33
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React, { ChangeEvent, ReactNode, useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import MuiTextField, { OutlinedTextFieldProps } from '@mui/material/TextField';
|
|
3
|
+
import { InputAdornment } from '@mui/material';
|
|
4
|
+
|
|
5
|
+
export interface FieldTypeUrlProps extends Omit<OutlinedTextFieldProps, 'variant'> {
|
|
6
|
+
/**
|
|
7
|
+
* Max length of the field
|
|
8
|
+
* @default 2000
|
|
9
|
+
*/
|
|
10
|
+
maxLength?: number;
|
|
11
|
+
value: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const FieldTypeUrl = ({maxLength = 2000, value, helperText, InputProps, InputLabelProps, inputProps, ...props }: FieldTypeUrlProps) => {
|
|
15
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<MuiTextField
|
|
19
|
+
size="small"
|
|
20
|
+
type='url'
|
|
21
|
+
variant='outlined'
|
|
22
|
+
value={value}
|
|
23
|
+
InputProps={{
|
|
24
|
+
endAdornment: (
|
|
25
|
+
<InputAdornment position="end">
|
|
26
|
+
<>{value.length}/{maxLength}</>
|
|
27
|
+
</InputAdornment>
|
|
28
|
+
),
|
|
29
|
+
// Spread props at the end to allow Input prop overrides
|
|
30
|
+
...InputProps,
|
|
31
|
+
}}
|
|
32
|
+
InputLabelProps={{
|
|
33
|
+
shrink: true,
|
|
34
|
+
// Spread props at the end to allow InputLabel prop overrides
|
|
35
|
+
...InputLabelProps,
|
|
36
|
+
}}
|
|
37
|
+
inputProps={{
|
|
38
|
+
ref: inputRef,
|
|
39
|
+
// Spread props at the end to allow inputProps prop overrides
|
|
40
|
+
...inputProps,
|
|
41
|
+
}}
|
|
42
|
+
error={(value && !inputRef.current?.validity.valid) || value.length > maxLength}
|
|
43
|
+
helperText={value.length > maxLength ? 'Your input is over the specified limit' : (value && !inputRef.current?.validity.valid) ? 'Your input is not a valid url' : helperText}
|
|
44
|
+
// Spread props at the end to allow prop overrides
|
|
45
|
+
{...props}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default FieldTypeUrl;
|
package/src/index.ts
CHANGED
package/src/theme/index.ts
CHANGED
|
@@ -9,27 +9,46 @@ let theme: Theme = createTheme({
|
|
|
9
9
|
|
|
10
10
|
theme = createTheme(theme, {
|
|
11
11
|
components: {
|
|
12
|
+
MuiButton: {
|
|
13
|
+
styleOverrides: {
|
|
14
|
+
root: {
|
|
15
|
+
minWidth: 'auto',
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
12
19
|
MuiTooltip: {
|
|
13
20
|
styleOverrides: {
|
|
14
21
|
tooltip: {
|
|
15
22
|
color: theme.palette.primary.contrastText,
|
|
16
23
|
backgroundColor: theme.palette.primary.main,
|
|
17
|
-
fontSize:
|
|
18
|
-
lineHeight:
|
|
24
|
+
fontSize: '14px',
|
|
25
|
+
lineHeight: '20px',
|
|
19
26
|
},
|
|
20
27
|
arrow: {
|
|
21
28
|
color: theme.palette.primary.main,
|
|
22
|
-
}
|
|
23
|
-
}
|
|
29
|
+
},
|
|
30
|
+
},
|
|
24
31
|
},
|
|
25
32
|
MuiInputBase: {
|
|
26
33
|
styleOverrides: {
|
|
27
34
|
root: {
|
|
28
|
-
backgroundColor: theme.palette.primary.contrastText
|
|
35
|
+
backgroundColor: theme.palette.primary.contrastText,
|
|
29
36
|
},
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
MuiToggleButton: {
|
|
40
|
+
styleOverrides: {
|
|
41
|
+
root: ({ ownerState, theme }: any) => ({
|
|
42
|
+
...(ownerState.selected && {
|
|
43
|
+
color: `${theme.palette[ownerState.color].contrastText} !important`,
|
|
44
|
+
backgroundColor: `${
|
|
45
|
+
theme.palette[ownerState.color].main
|
|
46
|
+
} !important`,
|
|
47
|
+
}),
|
|
48
|
+
}),
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
});
|
|
34
53
|
|
|
35
54
|
export default theme;
|