@junyiacademy/ui-test 0.0.7 → 0.0.8

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.
Files changed (38) hide show
  1. package/package.json +1 -1
  2. package/src/index.ts +4 -1
  3. package/src/lib/TopicFilter.spec.tsx +10 -0
  4. package/src/lib/TopicFilter.stories.tsx +80 -0
  5. package/src/lib/TopicFilter.tsx +204 -0
  6. package/src/lib/menu-item/SelectMenuItem.spec.tsx +10 -0
  7. package/src/lib/menu-item/SelectMenuItem.stories.tsx +44 -0
  8. package/src/lib/menu-item/SelectMenuItem.tsx +45 -0
  9. package/src/lib/radio/Radio.stories.tsx +3 -2
  10. package/src/lib/radio/Radio.tsx +1 -1
  11. package/src/lib/select/OutlinedSelect.spec.tsx +10 -0
  12. package/src/lib/select/OutlinedSelect.stories.tsx +245 -0
  13. package/src/lib/select/OutlinedSelect.tsx +223 -0
  14. package/src/lib/select/StandardSelect.stories.tsx +221 -0
  15. package/src/lib/select/StandardSelect.tsx +188 -0
  16. package/src/lib/text-field/TextField.stories.tsx +35 -1
  17. package/src/utils/topicTree.ts +91 -1
  18. package/declarations/libs/ui/src/index.d.ts +0 -5
  19. package/declarations/libs/ui/src/interfaces/index.d.ts +0 -8
  20. package/declarations/libs/ui/src/lib/TopicFilter.d.ts +0 -13
  21. package/declarations/libs/ui/src/lib/button/Button.d.ts +0 -6
  22. package/declarations/libs/ui/src/lib/button-group/ButtonGroup.d.ts +0 -3
  23. package/declarations/libs/ui/src/lib/menu-item/SelectMenuItem.d.ts +0 -9
  24. package/declarations/libs/ui/src/lib/radio/Radio.d.ts +0 -10
  25. package/declarations/libs/ui/src/lib/select/OutlinedSelect.d.ts +0 -15
  26. package/declarations/libs/ui/src/lib/select/StandardSelect.d.ts +0 -20
  27. package/declarations/libs/ui/src/lib/text-field/TextField.d.ts +0 -3
  28. package/dist/libs/ui/src/index.js +0 -16
  29. package/dist/libs/ui/src/interfaces/index.js +0 -2
  30. package/dist/libs/ui/src/lib/TopicFilter.js +0 -122
  31. package/dist/libs/ui/src/lib/button/Button.js +0 -71
  32. package/dist/libs/ui/src/lib/button-group/ButtonGroup.js +0 -33
  33. package/dist/libs/ui/src/lib/menu-item/SelectMenuItem.js +0 -24
  34. package/dist/libs/ui/src/lib/radio/Radio.js +0 -43
  35. package/dist/libs/ui/src/lib/select/OutlinedSelect.js +0 -65
  36. package/dist/libs/ui/src/lib/select/StandardSelect.js +0 -97
  37. package/dist/libs/ui/src/lib/text-field/TextField.js +0 -75
  38. package/src/lib/selection-item/SelectionItem.tsx +0 -33
@@ -0,0 +1,223 @@
1
+ import React, { ChangeEvent } from 'react'
2
+ import { Theme, styled } from '@material-ui/core/styles'
3
+ import {
4
+ InputLabel,
5
+ FormControl,
6
+ Select,
7
+ OutlinedInput,
8
+ SelectProps,
9
+ OutlinedInputProps,
10
+ FormHelperText,
11
+ } from '@material-ui/core'
12
+
13
+ // self-defined-components
14
+ const PREFIX = 'JuiOutlinedSelect'
15
+
16
+ const classes = {
17
+ inputLabelFocused: `${PREFIX}-inputLabelFocused`,
18
+ inputLabelOutlined: `${PREFIX}-inputLabelOutlined`,
19
+ inputLabelMarginDense: `${PREFIX}-inputLabelMarginDense`,
20
+ inputLabelShrink: `${PREFIX}-inputLabelShrink`,
21
+ inputLabelError: `${PREFIX}-inputLabelError`,
22
+ inputLabelDisabled: `${PREFIX}-inputLabelDisabled`,
23
+ outlineInputInput: `${PREFIX}-input`,
24
+ outlineInputInputMarginDense: `${PREFIX}-inputMarginDense`,
25
+ outlineInputNotchedOutline: `${PREFIX}-notchedOutline`,
26
+ outlineInputDisabled: `${PREFIX}-inputDisabled`,
27
+ outlineInputError: `${PREFIX}-outlinedInputError`,
28
+ selectPaper: `${PREFIX}-menuPaper`,
29
+ }
30
+
31
+ interface StyledFormControlProps {
32
+ color: 'primary' | 'secondary'
33
+ width: number | 'auto'
34
+ theme?: Theme
35
+ }
36
+
37
+ const StyledFormControl = styled(
38
+ ({ color: _color, width: _width, ...props }) => <FormControl {...props} />
39
+ )(({ color, width, theme }: StyledFormControlProps) => ({
40
+ margin: theme.spacing(1),
41
+ width: width,
42
+ backgroundColor: 'white',
43
+ '&:hover': {
44
+ [`& :not(.${classes.outlineInputDisabled}):not(.${classes.outlineInputError}) .${classes.outlineInputNotchedOutline}`]: {
45
+ borderColor: theme.palette[color].main,
46
+ },
47
+ },
48
+ }))
49
+
50
+ interface StyledInputLabelProps {
51
+ color: 'primary' | 'secondary'
52
+ theme?: Theme
53
+ }
54
+
55
+ const StyledInputLabel = styled(({ color: _color, ...props }) => (
56
+ <InputLabel
57
+ classes={{
58
+ outlined: classes.inputLabelOutlined,
59
+ marginDense: classes.inputLabelMarginDense,
60
+ shrink: classes.inputLabelShrink,
61
+ focused: classes.inputLabelFocused,
62
+ disabled: classes.inputLabelDisabled,
63
+ error: classes.inputLabelError,
64
+ }}
65
+ {...props}
66
+ />
67
+ ))(({ color, theme }: StyledInputLabelProps) => ({
68
+ color: theme.palette.text.secondary,
69
+ [`&.${classes.inputLabelOutlined}`]: {
70
+ [`&:not(.${classes.inputLabelDisabled}) .${classes.inputLabelFocused}`]: {
71
+ color: theme.palette.action.active,
72
+ },
73
+ [`&.${classes.inputLabelMarginDense}:not(.${classes.inputLabelShrink})`]: {
74
+ transform: 'translate(12px, 16px) scale(1)',
75
+ },
76
+ },
77
+ [`&.${classes.inputLabelShrink}:not(.${classes.inputLabelError}):not(.${classes.inputLabelDisabled}).${classes.inputLabelFocused}`]: {
78
+ color: theme.palette[color].main,
79
+ },
80
+ [`&.${classes.inputLabelShrink}`]: {
81
+ backgroundColor: '#ffffff',
82
+ padding: '0 2px',
83
+ },
84
+ }))
85
+
86
+ interface StyledOutlinedInputProps {
87
+ theme?: Theme
88
+ }
89
+
90
+ const StyledOutlinedInput = styled((props) => (
91
+ <OutlinedInput
92
+ classes={{
93
+ input: classes.outlineInputInput,
94
+ inputMarginDense: classes.outlineInputInputMarginDense,
95
+ notchedOutline: classes.outlineInputNotchedOutline,
96
+ disabled: classes.outlineInputDisabled,
97
+ error: classes.outlineInputError,
98
+ }}
99
+ {...props}
100
+ />
101
+ ))(({ theme }: StyledOutlinedInputProps) => ({
102
+ [`& .${classes.outlineInputInput}`]: {
103
+ color: theme.palette.text.primary,
104
+ },
105
+ [`& .${classes.outlineInputInputMarginDense}`]: {
106
+ padding: '14.5px 15px 14.5px 12px',
107
+ },
108
+ }))
109
+
110
+ interface StyledSelectProps {
111
+ paperMaxHeight: number | 'auto'
112
+ hasAdornment: boolean
113
+ }
114
+
115
+ const StyledSelect = styled(
116
+ ({
117
+ paperMaxHeight: _paperMaxHeight,
118
+ hasAdornment: _hasAdornment,
119
+ className,
120
+ ...props
121
+ }) => (
122
+ <Select
123
+ MenuProps={{
124
+ disableAutoFocusItem: true,
125
+ anchorOrigin: {
126
+ vertical: 2,
127
+ horizontal: 'left',
128
+ },
129
+ transformOrigin: {
130
+ vertical: 'top',
131
+ horizontal: 'left',
132
+ },
133
+ getContentAnchorEl: null,
134
+ classes: { paper: className },
135
+ }}
136
+ {...props}
137
+ />
138
+ )
139
+ )(({ hasAdornment, paperMaxHeight }: StyledSelectProps) => ({
140
+ '&&': {
141
+ maxHeight: paperMaxHeight,
142
+ left: hasAdornment ? '24px !important' : '70px',
143
+ },
144
+ }))
145
+
146
+ export interface OutlinedSelectProps {
147
+ color?: 'primary' | 'secondary'
148
+ size?: 'medium' | 'small'
149
+ width?: number | 'auto'
150
+ paperMaxHeight?: number | 'auto'
151
+ error?: boolean
152
+ hasLabel?: boolean
153
+ hasShrink?: boolean
154
+ placeholder: string
155
+ helperText?: string
156
+ value?: unknown
157
+ disabled?: boolean
158
+ SelectProps?: object | Partial<SelectProps>
159
+ OutlinedInputProps?: Partial<OutlinedInputProps> & {
160
+ onChange: (e: ChangeEvent<HTMLInputElement>) => void
161
+ }
162
+ children?: React.ReactNode
163
+ }
164
+
165
+ const OutlinedSelect = ({
166
+ color = 'primary',
167
+ size = 'medium',
168
+ width = 'auto',
169
+ paperMaxHeight = 'auto',
170
+ error = false,
171
+ hasLabel = true,
172
+ hasShrink = false,
173
+ placeholder,
174
+ helperText = '',
175
+ value = '',
176
+ disabled = false,
177
+ SelectProps,
178
+ OutlinedInputProps,
179
+ children,
180
+ }: OutlinedSelectProps) => {
181
+ const hasAdornment = !!OutlinedInputProps?.startAdornment
182
+ const hasHelperText = !!helperText
183
+ return (
184
+ <StyledFormControl
185
+ size={size}
186
+ width={width}
187
+ disabled={disabled}
188
+ error={error}
189
+ color={color}
190
+ >
191
+ {hasLabel ? (
192
+ hasShrink ? (
193
+ <StyledInputLabel color={color} variant='outlined' shrink>
194
+ {placeholder}
195
+ </StyledInputLabel>
196
+ ) : (
197
+ <StyledInputLabel color={color} variant='outlined'>
198
+ {placeholder}
199
+ </StyledInputLabel>
200
+ )
201
+ ) : null}
202
+ <StyledSelect
203
+ value={value}
204
+ paperMaxHeight={paperMaxHeight}
205
+ hasAdornment={hasAdornment}
206
+ input={
207
+ <StyledOutlinedInput
208
+ color={color}
209
+ label={hasLabel ? placeholder : undefined}
210
+ disabled={disabled}
211
+ {...OutlinedInputProps}
212
+ />
213
+ }
214
+ {...SelectProps}
215
+ >
216
+ {children}
217
+ </StyledSelect>
218
+ {hasHelperText && <FormHelperText>{helperText}</FormHelperText>}
219
+ </StyledFormControl>
220
+ )
221
+ }
222
+
223
+ export default OutlinedSelect
@@ -0,0 +1,221 @@
1
+ import React, { useState } from 'react'
2
+ import { Story, Meta } from '@storybook/react'
3
+ import { Theme, styled } from '@material-ui/core/styles'
4
+ import { InputAdornment } from '@material-ui/core'
5
+ import { Visibility } from '@material-ui/icons'
6
+ import { StandardSelect, StandardSelectProps } from './StandardSelect'
7
+ import SelectMenuItem from '../menu-item/SelectMenuItem'
8
+
9
+ const PLACEHOLDER = '請選擇'
10
+
11
+ export default {
12
+ component: StandardSelect,
13
+ title: 'StandardSelect',
14
+ argTypes: {
15
+ color: {
16
+ type: { name: 'string', required: false },
17
+ description:
18
+ 'The color of the component. It supports those theme colors that make sense for this component.',
19
+ table: {
20
+ type: { summary: 'primary | secondary' },
21
+ defaultValue: { summary: 'primary' },
22
+ },
23
+ options: ['primary', 'secondary'],
24
+ control: { type: 'radio' },
25
+ },
26
+ size: {
27
+ type: { name: 'string', required: false },
28
+ description: `Adjust size`,
29
+ table: {
30
+ type: { summary: 'medium | small' },
31
+ defaultValue: { summary: 'medium' },
32
+ },
33
+ options: ['small', 'medium'],
34
+ control: { type: 'radio' },
35
+ },
36
+ width: {
37
+ type: { name: 'number', required: false },
38
+ description: `Adjust width`,
39
+ table: {
40
+ type: { summary: 'number' },
41
+ defaultValue: { summary: 'auto' },
42
+ },
43
+ control: { type: 'number' },
44
+ },
45
+ paperMaxHeight: {
46
+ type: { name: 'number', required: false },
47
+ description: `Adjust select menu paper max height.`,
48
+ table: {
49
+ type: { summary: 'number' },
50
+ defaultValue: { summary: 'auto' },
51
+ },
52
+ control: { type: 'number' },
53
+ },
54
+ hasShrink: {
55
+ type: { name: 'boolean', required: false },
56
+ description: 'If true, the label is displayed and shrunk.',
57
+ table: {
58
+ type: { summary: 'boolean' },
59
+ defaultValue: { summary: true },
60
+ },
61
+ control: { type: 'boolean' },
62
+ },
63
+ placeholder: {
64
+ type: { name: 'string', required: true },
65
+ description: `The label title`,
66
+ table: {
67
+ type: { summary: 'string' },
68
+ defaultValue: { summary: '請選擇' },
69
+ },
70
+ control: { type: 'text' },
71
+ },
72
+ value: {
73
+ type: { name: 'any', required: false },
74
+ description: `The input value. Providing an empty string will select no options. This prop is required when the native prop is false (default). Set to an empty string '' if you don't want any of the available options to be selected.
75
+ If the value is an object it must have reference equality with the option in order to be selected. If the value is not an object, the string representation must match with the string representation of the option in order to be selected.`,
76
+ table: {
77
+ type: { summary: 'any' },
78
+ defaultValue: { summary: '' },
79
+ },
80
+ },
81
+ disabled: {
82
+ type: { name: 'boolean', required: false },
83
+ description: 'If true, the input element will be disabled.',
84
+ table: {
85
+ type: { summary: 'boolean' },
86
+ defaultValue: { summary: false },
87
+ },
88
+ control: { type: 'boolean' },
89
+ },
90
+ error: {
91
+ type: { name: 'boolean', required: false },
92
+ description: 'If true, the label will be displayed in an error state.',
93
+ table: {
94
+ type: { summary: 'boolean' },
95
+ defaultValue: { summary: false },
96
+ },
97
+ control: { type: 'boolean' },
98
+ },
99
+ helperText: {
100
+ type: { name: 'string', required: true },
101
+ description: `Display the helper text.`,
102
+ table: {
103
+ type: { summary: 'string' },
104
+ defaultValue: { summary: '' },
105
+ },
106
+ control: { type: 'text' },
107
+ },
108
+ InputProps: {
109
+ type: { name: 'any', required: false },
110
+ description: 'Attributes applied to inner Input element.',
111
+ table: {
112
+ type: { summary: 'any' },
113
+ },
114
+ },
115
+ SelectProps: {
116
+ type: { name: 'any', required: false },
117
+ description: 'Attributes applied to inner Select element.',
118
+ table: {
119
+ type: { summary: 'any' },
120
+ },
121
+ },
122
+ },
123
+ } as Meta
124
+
125
+ const PREFIX = 'JuiStandardSelect'
126
+
127
+ const classes = {
128
+ inputAdornmentRoot: `${PREFIX}-inputAdornmentRoot`,
129
+ }
130
+ interface StyledInputAdornmentProps {
131
+ theme: Theme
132
+ disabled: boolean
133
+ }
134
+
135
+ const StyledInputAdornment = styled(({ disabled: _disabled, ...props }) => (
136
+ <InputAdornment
137
+ classes={{
138
+ root: classes.inputAdornmentRoot,
139
+ }}
140
+ {...props}
141
+ />
142
+ ))(({ disabled, theme }: StyledInputAdornmentProps) => ({
143
+ [`&.${classes.inputAdornmentRoot}`]: {
144
+ color: disabled
145
+ ? theme.palette.action.disabled
146
+ : theme.palette.action.active,
147
+ },
148
+ }))
149
+
150
+ const StandardSelectWithMenu = (props: StandardSelectProps) => {
151
+ const [item, setItem] = useState<string>('')
152
+
153
+ const handleChange = (event) => {
154
+ setItem(event.target.value)
155
+ }
156
+
157
+ return (
158
+ <StandardSelect
159
+ value={item}
160
+ SelectProps={{
161
+ onChange: (e) => {
162
+ handleChange(e)
163
+ },
164
+ }}
165
+ {...props}
166
+ >
167
+ <SelectMenuItem width={300} value='' disabled>
168
+ {PLACEHOLDER}
169
+ </SelectMenuItem>
170
+ <SelectMenuItem width={300} value={'Test'}>
171
+ This is a select menu item, This is a select menu item
172
+ </SelectMenuItem>
173
+ <SelectMenuItem width={300} value={'Example'}>
174
+ Example
175
+ </SelectMenuItem>
176
+ </StandardSelect>
177
+ )
178
+ }
179
+
180
+ const ValueOnlyStory: Story<StandardSelectProps> = (args) => (
181
+ <StandardSelectWithMenu {...args} />
182
+ )
183
+
184
+ export const ValueOnly = ValueOnlyStory.bind({})
185
+
186
+ ValueOnly.args = {
187
+ color: 'primary',
188
+ size: 'medium',
189
+ width: 220,
190
+ paperMaxHeight: 300,
191
+ hasShrink: false,
192
+ placeholder: PLACEHOLDER,
193
+ helperText: 'test',
194
+ disabled: false,
195
+ }
196
+
197
+ const WithPrefixStory: Story<StandardSelectProps> = (args) => (
198
+ <StandardSelectWithMenu
199
+ InputProps={{
200
+ startAdornment: (
201
+ <StyledInputAdornment position='start' disabled={args.disabled}>
202
+ <Visibility />
203
+ </StyledInputAdornment>
204
+ ),
205
+ }}
206
+ {...args}
207
+ />
208
+ )
209
+
210
+ export const WithPrefix = WithPrefixStory.bind({})
211
+
212
+ WithPrefix.args = {
213
+ color: 'primary',
214
+ size: 'medium',
215
+ width: 300,
216
+ paperMaxHeight: 300,
217
+ hasShrink: false,
218
+ placeholder: PLACEHOLDER,
219
+ helperText: 'test',
220
+ disabled: false,
221
+ }
@@ -0,0 +1,188 @@
1
+ import React from 'react'
2
+ import { Theme, styled } from '@material-ui/core/styles'
3
+ import {
4
+ InputLabel,
5
+ FormControl,
6
+ Select,
7
+ SelectProps,
8
+ Input,
9
+ InputProps,
10
+ FormHelperText,
11
+ InputAdornment,
12
+ } from '@material-ui/core'
13
+
14
+ // self-defined-components
15
+ const PREFIX = 'JuiStandardSelect'
16
+
17
+ const classes = {
18
+ inputLabelFocused: `${PREFIX}-inputLabelFocused`,
19
+ inputLabelMarginDense: `${PREFIX}-inputLabelMarginDense`,
20
+ inputLabelError: `${PREFIX}-inputLabelError`,
21
+ inputUnderline: `${PREFIX}-inputUnderline`,
22
+ inputError: `${PREFIX}-inputError`,
23
+ inputDisabled: `${PREFIX}-inputDisabled`,
24
+ inputAdornmentRoot: `${PREFIX}-inputAdornmentRoot`,
25
+ selectPaper: `${PREFIX}-menuPaper`,
26
+ selectDisabled: `${PREFIX}-selectDisabled`,
27
+ }
28
+
29
+ interface StyledFormControlProps {
30
+ color: 'primary' | 'secondary'
31
+ width: number | 'auto'
32
+ theme?: Theme
33
+ }
34
+
35
+ const StyledFormControl = styled(({ width: _width, ...props }) => (
36
+ <FormControl {...props} />
37
+ ))(({ width, theme }: StyledFormControlProps) => ({
38
+ width,
39
+ margin: theme.spacing(0, 4, 4, 4),
40
+ }))
41
+
42
+ interface StyledInputLabelProps {
43
+ color: 'primary' | 'secondary'
44
+ theme?: Theme
45
+ }
46
+
47
+ const StyledInputLabel = styled(({ color: _color, ...props }) => (
48
+ <InputLabel
49
+ classes={{
50
+ focused: classes.inputLabelFocused,
51
+ error: classes.inputLabelError,
52
+ }}
53
+ {...props}
54
+ />
55
+ ))(({ color, theme }: StyledInputLabelProps) => ({
56
+ color: theme.palette.text.disabled,
57
+ margin: theme.spacing(0, 10, 1.5, 0),
58
+ [`&.${classes.inputLabelFocused}`]: {
59
+ color: theme.palette[color].main,
60
+ },
61
+ [`&.${classes.inputLabelError}`]: {
62
+ color: theme.palette.error.main,
63
+ },
64
+ }))
65
+
66
+ interface StyledSelectProps {
67
+ paperMaxHeight: number | 'auto'
68
+ hasAdornment: boolean
69
+ }
70
+
71
+ const StyledSelect = styled(
72
+ ({
73
+ paperMaxHeight: _selectPaperHeight,
74
+ hasAdornment: _hasAdornment,
75
+ className,
76
+ ...props
77
+ }) => (
78
+ <Select
79
+ MenuProps={{
80
+ classes: { paper: className },
81
+ transformOrigin: {
82
+ vertical: 'top',
83
+ horizontal: 'left',
84
+ },
85
+ getContentAnchorEl: null,
86
+ }}
87
+ {...props}
88
+ />
89
+ )
90
+ )(({ hasAdornment, paperMaxHeight }: StyledSelectProps) => ({
91
+ '&&': {
92
+ maxHeight: paperMaxHeight,
93
+ left: hasAdornment ? '48px !important' : '70px',
94
+ },
95
+ [`&.${classes.selectDisabled}`]: {},
96
+ }))
97
+
98
+ interface StyledInputProps {
99
+ color: 'primary' | 'secondary'
100
+ theme: Theme
101
+ }
102
+
103
+ const StyledInput = styled(({ color: _color, ...props }) => (
104
+ <Input
105
+ classes={{
106
+ disabled: classes.inputDisabled,
107
+ underline: classes.inputUnderline,
108
+ error: classes.inputError,
109
+ }}
110
+ {...props}
111
+ />
112
+ ))(({ color, theme }: StyledInputProps) => ({
113
+ color: theme.palette.text.primary,
114
+ [`&.${classes.inputUnderline}:not(.${classes.inputDisabled}):not(.${classes.inputError})`]: {
115
+ [`&:after,&:hover:before`]: {
116
+ borderBottomColor: theme.palette[color].main,
117
+ },
118
+ },
119
+ [`&.${classes.inputUnderline}.${classes.inputError}:not(.${classes.inputDisabled})`]: {
120
+ [`&:after,&:hover:before`]: {
121
+ borderBottomColor: theme.palette.error.main,
122
+ },
123
+ },
124
+ }))
125
+
126
+ export interface StandardSelectProps {
127
+ color?: 'primary' | 'secondary'
128
+ size?: 'medium' | 'small'
129
+ width?: number | 'auto'
130
+ paperMaxHeight?: number | 'auto'
131
+ error?: boolean
132
+ hasShrink?: boolean
133
+ placeholder: string
134
+ helperText?: string
135
+ InputProps?: object & Partial<InputProps>
136
+ value?: unknown
137
+ disabled?: boolean
138
+ SelectProps?: object | Partial<SelectProps>
139
+ children?: React.ReactNode
140
+ }
141
+
142
+ export function StandardSelect({
143
+ color = 'primary',
144
+ size = 'medium',
145
+ width = 'auto',
146
+ paperMaxHeight = 'auto',
147
+ error = false,
148
+ hasShrink = false,
149
+ placeholder,
150
+ helperText,
151
+ InputProps,
152
+ value = '',
153
+ SelectProps,
154
+ disabled = false,
155
+ children,
156
+ }: StandardSelectProps) {
157
+ const hasAdornment = !!InputProps?.startAdornment
158
+ const hasHelperText = !!helperText
159
+ return (
160
+ <StyledFormControl
161
+ color={color}
162
+ size={size}
163
+ width={width}
164
+ disabled={disabled}
165
+ error={error}
166
+ >
167
+ {hasShrink ? (
168
+ <StyledInputLabel color={color} shrink>
169
+ {placeholder}
170
+ </StyledInputLabel>
171
+ ) : (
172
+ <StyledInputLabel color={color}>{placeholder}</StyledInputLabel>
173
+ )}
174
+ <StyledSelect
175
+ value={value}
176
+ paperMaxHeight={paperMaxHeight}
177
+ hasAdornment={hasAdornment}
178
+ input={<StyledInput color={color} {...InputProps} />}
179
+ {...SelectProps}
180
+ >
181
+ {children}
182
+ </StyledSelect>
183
+ {hasHelperText && <FormHelperText>{helperText}</FormHelperText>}
184
+ </StyledFormControl>
185
+ )
186
+ }
187
+
188
+ export default StandardSelect
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import React, { useEffect } from 'react'
2
2
  import { Story, Meta } from '@storybook/react'
3
3
  import { InputAdornment, TextFieldProps } from '@material-ui/core'
4
4
  import { Visibility } from '@material-ui/icons'
@@ -77,6 +77,40 @@ ValueOnly.args = {
77
77
  label: 'Which UI?',
78
78
  }
79
79
 
80
+ const TextFieldWithError = (props: TextFieldProps) => {
81
+ const [value, setValue] = React.useState('')
82
+ const [isError, setIsError] = React.useState(false)
83
+
84
+ const handleChange = (event) => {
85
+ setValue(event.target.value)
86
+ }
87
+
88
+ useEffect(() => {
89
+ if (value.length > 3) {
90
+ setIsError(true)
91
+ return
92
+ }
93
+ setIsError(false)
94
+ return
95
+ }, [value])
96
+
97
+ return <TextField error={isError} onChange={handleChange} {...props} />
98
+ }
99
+
100
+ const WithErrorStory: Story<TextFieldProps> = (args) => (
101
+ <TextFieldWithError {...args} />
102
+ )
103
+
104
+ export const WithError = WithErrorStory.bind({})
105
+
106
+ WithError.args = {
107
+ variant: 'standard',
108
+ color: 'primary',
109
+ disabled: false,
110
+ size: 'small',
111
+ label: 'No more than 3 words',
112
+ }
113
+
80
114
  const WithSuffixStory: Story<TextFieldProps> = (args) => (
81
115
  <TextField
82
116
  {...args}