@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@junyiacademy/ui-test",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "junyiacademy ui library",
5
5
  "main": "./dist/libs/ui/src/index.js",
6
6
  "typings": "./declarations/libs/ui/src/index.d.ts",
package/src/index.ts CHANGED
@@ -1,5 +1,8 @@
1
+ export { default as TopicFilter } from './lib/TopicFilter'
2
+ export { default as SelectMenuItem } from './lib/menu-item/SelectMenuItem'
3
+ export { default as OutlinedSelect } from './lib/select/OutlinedSelect'
1
4
  export { default as Button } from './lib/button/Button'
2
5
  export { default as ButtonGroup } from './lib/button-group/ButtonGroup'
3
6
  export { default as Radio } from './lib/radio/Radio'
4
7
  export { default as TextField } from './lib/text-field/TextField'
5
- export { default as SelectionItem } from './lib/selection-item/SelectionItem'
8
+ export { default as StandardSelect } from './lib/select/StandardSelect'
@@ -0,0 +1,10 @@
1
+ import { render } from '@testing-library/react'
2
+
3
+ import TopicFilter from './TopicFilter'
4
+
5
+ describe('TopicFilter', () => {
6
+ it('should render successfully', () => {
7
+ const { baseElement } = render(<TopicFilter />)
8
+ expect(baseElement).toBeTruthy()
9
+ })
10
+ })
@@ -0,0 +1,80 @@
1
+ import React from 'react'
2
+ import { Story, Meta } from '@storybook/react'
3
+ import TopicFilter, { TopicFilterProps } from './TopicFilter'
4
+ import { topicTree } from '../utils/topicTree'
5
+
6
+ export default {
7
+ component: TopicFilter,
8
+ title: 'TopicFilter',
9
+ argTypes: {
10
+ topicTree: {
11
+ type: { name: 'object', required: false },
12
+ description: 'Topic tree data list',
13
+ table: {
14
+ type: { summary: 'object' },
15
+ defaultValue: { summary: topicTree },
16
+ },
17
+ control: { type: 'object' },
18
+ },
19
+ onTopicSelected: {
20
+ type: { name: 'function', required: false },
21
+ description: 'Callback fired when the topic selected.',
22
+ table: {
23
+ type: {
24
+ summary: `(
25
+ topic: Topic,
26
+ selectedInfo: { layerNumber: number; selectedTopicIds: string[] }
27
+ ) => void`,
28
+ },
29
+ defaultValue: { summary: () => {} },
30
+ },
31
+ control: { type: 'function' },
32
+ },
33
+ isLastLayer: {
34
+ type: { name: 'function', required: false },
35
+ description: 'Callback for checking selected topic is last layer or not.',
36
+ table: {
37
+ type: {
38
+ summary: `(topic: Topic) => boolean`,
39
+ },
40
+ defaultValue: { summary: () => false },
41
+ },
42
+ control: { type: 'function' },
43
+ },
44
+ hasArrow: {
45
+ type: { name: 'boolean', required: false },
46
+ description: 'Control the arrow display state.',
47
+ table: {
48
+ type: { summary: 'boolean' },
49
+ defaultValue: { summary: true },
50
+ },
51
+ control: { type: 'boolean' },
52
+ defaultValue: true,
53
+ },
54
+ initSelectedTopicIds: {
55
+ type: { name: 'array', required: false },
56
+ description: ``,
57
+ table: {
58
+ type: { summary: 'array' },
59
+ defaultValue: { summary: [] },
60
+ },
61
+ control: { type: 'array' },
62
+ },
63
+ },
64
+ } as Meta
65
+
66
+ const OutlinedSelectStory: Story<TopicFilterProps> = (args) => (
67
+ <TopicFilter {...args} />
68
+ )
69
+
70
+ export const OutlinedSelect = OutlinedSelectStory.bind({})
71
+
72
+ OutlinedSelect.args = {
73
+ topicTree: topicTree,
74
+ onTopicSelected: () => {},
75
+ isLastLayer: (selectedTopic) => {
76
+ return selectedTopic.isContentTopic
77
+ },
78
+ hasArrow: true,
79
+ initSelectedTopicIds: [],
80
+ }
@@ -0,0 +1,204 @@
1
+ import React, { useState, useEffect } from 'react'
2
+ import { Theme, styled } from '@material-ui/core/styles'
3
+ import ArrowRightRoundedIcon from '@material-ui/icons/ArrowRightRounded'
4
+ import type { ITopicTreeNode } from '../interfaces'
5
+ import OutlinedSelect from './select/OutlinedSelect'
6
+ import SelectMenuItem from './menu-item/SelectMenuItem'
7
+
8
+ // self-defined-configs
9
+ const PLACEHOLDER = '請選擇'
10
+
11
+ // self-defined-components
12
+ const PREFIX = 'JuiTopicFilter'
13
+
14
+ const FiltersWrapper = styled('div')({
15
+ display: 'flex',
16
+ alignItems: 'center',
17
+ flexWrap: 'wrap',
18
+ })
19
+
20
+ const SelectWrapper = styled('div')({
21
+ display: 'flex',
22
+ alignItems: 'center',
23
+ })
24
+
25
+ interface StyledArrowRightRoundedIconProps {
26
+ theme?: Theme
27
+ }
28
+
29
+ const StyledArrowRightRoundedIcon = styled(ArrowRightRoundedIcon)(
30
+ ({ theme }: StyledArrowRightRoundedIconProps) => ({
31
+ margin: theme.spacing(-1, -1.5),
32
+ fontSize: theme.spacing(7),
33
+ color: '#444',
34
+ })
35
+ )
36
+
37
+ export interface TopicFilterProps {
38
+ topicTree: ITopicTreeNode
39
+ onTopicSelected: (
40
+ topic: ITopicTreeNode,
41
+ selectedInfo: { layerNumber: number; selectedTopicIds: string[] }
42
+ ) => void
43
+ isLastLayer: (topic: ITopicTreeNode) => boolean
44
+ hasArrow: boolean
45
+ initSelectedTopicIds: string[]
46
+ }
47
+
48
+ const TopicFilter = ({
49
+ topicTree,
50
+ onTopicSelected,
51
+ isLastLayer,
52
+ hasArrow,
53
+ initSelectedTopicIds,
54
+ }: TopicFilterProps) => {
55
+ const [selectedTopicIds, setSelectedTopicIds] = useState([])
56
+ const [layeredTopicList, setLayeredTopicList] = useState([])
57
+ const [isFocusedList, setIsFocusedList] = useState([])
58
+ const initSelectedLayers = () => {
59
+ const newLayeredTopicList = initSelectedTopicIds.reduce(
60
+ (topicListAccumulator, topicId, index) => {
61
+ const selectedTopic = topicListAccumulator[index]?.childTopics?.find(
62
+ (childTopic) => childTopic.id === topicId
63
+ )
64
+
65
+ if (!selectedTopic) {
66
+ return topicListAccumulator
67
+ }
68
+ if (isLastLayer(selectedTopic)) {
69
+ return topicListAccumulator
70
+ }
71
+ return [...topicListAccumulator, selectedTopic]
72
+ },
73
+ [topicTree]
74
+ )
75
+
76
+ setLayeredTopicList(newLayeredTopicList)
77
+ setSelectedTopicIds(
78
+ initSelectedTopicIds.slice(0, newLayeredTopicList.length)
79
+ )
80
+ setIsFocusedList(Array(newLayeredTopicList.length).fill(false))
81
+ }
82
+
83
+ const handleChange = (e, layerNumber, layeredTopic) => {
84
+ const selectedTopic = layeredTopic.childTopics.find(
85
+ (childTopic) => childTopic.id === e.target.value
86
+ )
87
+
88
+ const newSelectedTopicIds = [
89
+ ...selectedTopicIds.slice(0, layerNumber),
90
+ selectedTopic.id,
91
+ ]
92
+ setSelectedTopicIds(newSelectedTopicIds)
93
+ onTopicSelected(selectedTopic, {
94
+ layerNumber,
95
+ selectedTopicIds: newSelectedTopicIds,
96
+ })
97
+
98
+ if (isLastLayer(selectedTopic)) {
99
+ setLayeredTopicList((prevTopicList) =>
100
+ prevTopicList.slice(0, layerNumber + 1)
101
+ )
102
+ setIsFocusedList((prevList) => prevList.slice(0, layerNumber + 1))
103
+ } else {
104
+ setLayeredTopicList((prevTopicList) => [
105
+ ...prevTopicList.slice(0, layerNumber + 1),
106
+ selectedTopic,
107
+ ])
108
+ setIsFocusedList((prevList) => [
109
+ ...prevList.slice(0, layerNumber + 1),
110
+ false,
111
+ ])
112
+ }
113
+ }
114
+
115
+ useEffect(() => {
116
+ if (!topicTree || Object.keys(topicTree).length === 0) {
117
+ return
118
+ }
119
+ if (initSelectedTopicIds.length !== 0) {
120
+ initSelectedLayers()
121
+ return
122
+ }
123
+ setLayeredTopicList([topicTree])
124
+ }, [topicTree])
125
+
126
+ if (layeredTopicList.length === 0) {
127
+ return (
128
+ <OutlinedSelect
129
+ size='small'
130
+ width={220}
131
+ placeholder='載入資料中...'
132
+ disabled
133
+ ></OutlinedSelect>
134
+ )
135
+ }
136
+ return (
137
+ <FiltersWrapper>
138
+ {layeredTopicList.map((layeredTopic, layerNumber) => {
139
+ const hasLabel =
140
+ isFocusedList[layerNumber] || !selectedTopicIds[layerNumber]
141
+ return (
142
+ <SelectWrapper key={layeredTopic.id}>
143
+ <OutlinedSelect
144
+ size='small'
145
+ width={220}
146
+ paperMaxHeight={412}
147
+ hasLabel={hasLabel}
148
+ placeholder={PLACEHOLDER}
149
+ value={selectedTopicIds?.[layerNumber] || ''}
150
+ SelectProps={{
151
+ 'data-testid': `layered-topic-${layerNumber}`,
152
+ }}
153
+ OutlinedInputProps={{
154
+ inputProps: {
155
+ 'aria-label': `layered-topic-${layerNumber}`,
156
+ },
157
+ onChange: (e) => {
158
+ handleChange(e, layerNumber, layeredTopic)
159
+ },
160
+ onFocus: () => {
161
+ setIsFocusedList((prevList) => {
162
+ const newList = [...prevList]
163
+ newList[layerNumber] = true
164
+ return newList
165
+ })
166
+ },
167
+ onBlur: () => {
168
+ setIsFocusedList((prevList) => {
169
+ const newList = [...prevList]
170
+ newList[layerNumber] = false
171
+ return newList
172
+ })
173
+ },
174
+ }}
175
+ >
176
+ <SelectMenuItem width={220} disabled>
177
+ {PLACEHOLDER}
178
+ </SelectMenuItem>
179
+ {layeredTopic.childTopics.map((childTopic) => (
180
+ <SelectMenuItem
181
+ width={220}
182
+ key={childTopic.id}
183
+ value={childTopic.id}
184
+ data-testid={`layered-menuitem-${layerNumber}`}
185
+ data-is-content-topic={childTopic.isContentTopic}
186
+ >
187
+ {childTopic.title}
188
+ </SelectMenuItem>
189
+ ))}
190
+ </OutlinedSelect>
191
+ {hasArrow && layerNumber !== layeredTopicList.length - 1 && (
192
+ <StyledArrowRightRoundedIcon
193
+ fontSize='large'
194
+ data-testid='topic-filter-arrow'
195
+ ></StyledArrowRightRoundedIcon>
196
+ )}
197
+ </SelectWrapper>
198
+ )
199
+ })}
200
+ </FiltersWrapper>
201
+ )
202
+ }
203
+
204
+ export default TopicFilter
@@ -0,0 +1,10 @@
1
+ import { render } from '@testing-library/react'
2
+
3
+ import SelectMenuItem from './SelectMenuItem'
4
+
5
+ describe('SelectMenuItem', () => {
6
+ it('should render successfully', () => {
7
+ const { baseElement } = render(<SelectMenuItem />)
8
+ expect(baseElement).toBeTruthy()
9
+ })
10
+ })
@@ -0,0 +1,44 @@
1
+ import React from 'react'
2
+ import { Story, Meta } from '@storybook/react'
3
+ import { Menu } from '@material-ui/core'
4
+ import SelectMenuItem, { SelectMenuItemProps } from './SelectMenuItem'
5
+
6
+ export default {
7
+ component: SelectMenuItem,
8
+ title: 'SelectMenuItem',
9
+ argTypes: {
10
+ value: {
11
+ type: { name: 'any', required: false },
12
+ 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.
13
+ 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.`,
14
+ table: {
15
+ type: { summary: 'any' },
16
+ defaultValue: { summary: '' },
17
+ },
18
+ },
19
+ disabled: {
20
+ type: { name: 'boolean', required: false },
21
+ description: 'Control the disabled display state.',
22
+ table: {
23
+ type: { summary: 'boolean' },
24
+ defaultValue: { summary: true },
25
+ },
26
+ control: { type: 'boolean' },
27
+ defaultValue: true,
28
+ },
29
+ },
30
+ } as Meta
31
+
32
+ const Template: Story<SelectMenuItemProps> = (args) => (
33
+ <Menu open={true}>
34
+ <SelectMenuItem {...args}>Test</SelectMenuItem>
35
+ <SelectMenuItem {...args}>Example</SelectMenuItem>
36
+ </Menu>
37
+ )
38
+
39
+ export const Primary = Template.bind({})
40
+
41
+ Primary.args = {
42
+ value: '',
43
+ disabled: false,
44
+ }
@@ -0,0 +1,45 @@
1
+ import React, { PropsWithChildren } from 'react'
2
+ import { Theme, styled } from '@material-ui/core/styles'
3
+ import { MenuItem, MenuItemProps } from '@material-ui/core'
4
+
5
+ // self-defined-components
6
+ const PREFIX = 'JuiSelectMenuItem'
7
+
8
+ const classes = {
9
+ menuItemSelected: `${PREFIX}-menuItemSelected`,
10
+ }
11
+
12
+ interface StyledMenuItemProps {
13
+ width: number | 'auto'
14
+ theme?: Theme
15
+ }
16
+
17
+ const StyledMenuItem = styled(({ width: _width, ...props }) => (
18
+ <MenuItem classes={{ selected: classes.menuItemSelected }} {...props} />
19
+ ))(({ width, theme }: StyledMenuItemProps) => ({
20
+ width: width,
21
+ whiteSpace: 'unset',
22
+ color: theme.palette.text.primary,
23
+ [`& .${classes.menuItemSelected}`]: {
24
+ backgroundColor: theme.palette.grey[300],
25
+ },
26
+ }))
27
+
28
+ export interface SelectMenuItemProps extends MenuItemProps {
29
+ width: number | 'auto'
30
+ value?: any
31
+ disabled?: boolean
32
+ }
33
+
34
+ const SelectMenuItem = React.forwardRef<
35
+ HTMLLIElement,
36
+ PropsWithChildren<SelectMenuItemProps>
37
+ >(({ width, children, value = '', ...otherProps }, ref) => {
38
+ return (
39
+ <StyledMenuItem width={width} innerRef={ref} value={value} {...otherProps}>
40
+ {children}
41
+ </StyledMenuItem>
42
+ )
43
+ })
44
+
45
+ export default SelectMenuItem
@@ -25,10 +25,11 @@ export default {
25
25
  type: { name: 'string', required: false },
26
26
  description: 'The position of the label.',
27
27
  table: {
28
- type: { summary: 'bottom | end | start | top' },
28
+ type: { summary: 'end' },
29
29
  defaultValue: { summary: 'end' },
30
+ category: 'not comparable with caption',
30
31
  },
31
- options: ['bottom', 'end', 'start', 'top'],
32
+ options: ['end'],
32
33
  control: { type: 'radio' },
33
34
  },
34
35
  color: {
@@ -52,7 +52,7 @@ const StyledTypography = styled(Typography)(({ theme }) => ({
52
52
  margin: '0 0 0 30px',
53
53
  }))
54
54
 
55
- export interface RadioProps extends Omit<FormControlLabelProps, 'control'> {
55
+ export interface RadioProps extends FormControlLabelProps {
56
56
  color?: 'primary' | 'secondary' | 'default'
57
57
  size?: 'medium' | 'small'
58
58
  caption?: string
@@ -0,0 +1,10 @@
1
+ import { render } from '@testing-library/react'
2
+
3
+ import OutlinedSelect from './OutlinedSelect'
4
+
5
+ describe('OutlinedSelect', () => {
6
+ it('should render successfully', () => {
7
+ const { baseElement } = render(<OutlinedSelect />)
8
+ expect(baseElement).toBeTruthy()
9
+ })
10
+ })
@@ -0,0 +1,245 @@
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 OutlinedSelect, { OutlinedSelectProps } from './OutlinedSelect'
7
+ import SelectMenuItem from '../menu-item/SelectMenuItem'
8
+
9
+ const PLACEHOLDER = '請選擇'
10
+
11
+ export default {
12
+ component: OutlinedSelect,
13
+ title: 'OutlinedSelect',
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
+ hasInputLabel: {
55
+ type: { name: 'boolean', required: false },
56
+ description: 'If true, the label is displayed.',
57
+ table: {
58
+ type: { summary: 'boolean' },
59
+ defaultValue: { summary: true },
60
+ },
61
+ control: { type: 'boolean' },
62
+ },
63
+ hasShrink: {
64
+ type: { name: 'boolean', required: false },
65
+ description: 'If true, the label is displayed and shrunk.',
66
+ table: {
67
+ type: { summary: 'boolean' },
68
+ defaultValue: { summary: false },
69
+ },
70
+ control: { type: 'boolean' },
71
+ },
72
+ placeholder: {
73
+ type: { name: 'string', required: true },
74
+ description: `The label title`,
75
+ table: {
76
+ type: { summary: 'string' },
77
+ defaultValue: { summary: '請選擇' },
78
+ },
79
+ control: { type: 'text' },
80
+ },
81
+ value: {
82
+ type: { name: 'any', required: false },
83
+ 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.
84
+ 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.`,
85
+ table: {
86
+ type: { summary: 'any' },
87
+ defaultValue: { summary: '' },
88
+ },
89
+ },
90
+ disabled: {
91
+ type: { name: 'boolean', required: false },
92
+ description: 'If true, the input element will be disabled.',
93
+ table: {
94
+ type: { summary: 'boolean' },
95
+ defaultValue: { summary: false },
96
+ },
97
+ control: { type: 'boolean' },
98
+ },
99
+ error: {
100
+ type: { name: 'boolean', required: false },
101
+ description: 'If true, the label will be displayed in an error state.',
102
+ table: {
103
+ type: { summary: 'boolean' },
104
+ defaultValue: { summary: false },
105
+ },
106
+ control: { type: 'boolean' },
107
+ },
108
+ helperText: {
109
+ type: { name: 'string', required: true },
110
+ description: `Display the helper text.`,
111
+ table: {
112
+ type: { summary: 'string' },
113
+ defaultValue: { summary: '' },
114
+ },
115
+ control: { type: 'text' },
116
+ },
117
+ SelectProps: {
118
+ type: { name: 'any', required: false },
119
+ description: 'Attributes applied to inner Select element.',
120
+ table: {
121
+ type: { summary: 'any' },
122
+ },
123
+ },
124
+ OutlinedInputProps: {
125
+ type: { name: 'any', required: false },
126
+ description: 'Attributes applied to to inner OutlinedInput element.',
127
+ table: {
128
+ type: { summary: 'any' },
129
+ },
130
+ },
131
+ },
132
+ } as Meta
133
+
134
+ const PREFIX = 'JuiOutlinedSelect'
135
+
136
+ const classes = {
137
+ outlineInputAdornmentRoot: `${PREFIX}-outlineInputAdornmentRoot`,
138
+ }
139
+
140
+ interface StyledInputAdornmentProps {
141
+ disabled: boolean
142
+ theme?: Theme
143
+ }
144
+
145
+ const StyledInputAdornment = styled(({ disabled: _disabled, ...props }) => (
146
+ <InputAdornment
147
+ classes={{
148
+ root: classes.outlineInputAdornmentRoot,
149
+ }}
150
+ {...props}
151
+ />
152
+ ))(({ disabled, theme }: StyledInputAdornmentProps) => ({
153
+ [`&.${classes.outlineInputAdornmentRoot}`]: {
154
+ color: disabled
155
+ ? theme.palette.action.disabled
156
+ : theme.palette.action.active,
157
+ },
158
+ }))
159
+
160
+ const OutlinedSelectWithMenu = (props: OutlinedSelectProps) => {
161
+ return (
162
+ <OutlinedSelect {...props}>
163
+ <SelectMenuItem width={220} value='' disabled>
164
+ {PLACEHOLDER}
165
+ </SelectMenuItem>
166
+ <SelectMenuItem width={220} value='Test'>
167
+ This is a select menu item
168
+ </SelectMenuItem>
169
+ <SelectMenuItem width={220} value='Example'>
170
+ Example
171
+ </SelectMenuItem>
172
+ </OutlinedSelect>
173
+ )
174
+ }
175
+
176
+ const ValueOnlyStory: Story<OutlinedSelectProps> = (args) => {
177
+ const [item, setItem] = useState<string>('')
178
+
179
+ const handleChange = (event) => {
180
+ setItem(event.target.value)
181
+ }
182
+ return (
183
+ <OutlinedSelectWithMenu
184
+ OutlinedInputProps={{
185
+ onChange: (e) => {
186
+ handleChange(e)
187
+ },
188
+ }}
189
+ value={item}
190
+ {...args}
191
+ />
192
+ )
193
+ }
194
+
195
+ export const ValueOnly = ValueOnlyStory.bind({})
196
+
197
+ ValueOnly.args = {
198
+ color: 'primary',
199
+ size: 'medium',
200
+ width: 220,
201
+ paperMaxHeight: 412,
202
+ hasInputLabel: true,
203
+ placeholder: PLACEHOLDER,
204
+ helperText: 'test',
205
+ disabled: false,
206
+ SelectProps: {},
207
+ }
208
+
209
+ const WithPrefixStory: Story<OutlinedSelectProps> = (args) => {
210
+ const [item, setItem] = useState<string>('')
211
+
212
+ const handleChange = (event) => {
213
+ setItem(event.target.value)
214
+ }
215
+ return (
216
+ <OutlinedSelectWithMenu
217
+ OutlinedInputProps={{
218
+ onChange: (e) => {
219
+ handleChange(e)
220
+ },
221
+ startAdornment: (
222
+ <StyledInputAdornment position='start' disabled={args.disabled}>
223
+ <Visibility />
224
+ </StyledInputAdornment>
225
+ ),
226
+ }}
227
+ value={item}
228
+ {...args}
229
+ />
230
+ )
231
+ }
232
+
233
+ export const WithPrefix = WithPrefixStory.bind({})
234
+
235
+ WithPrefix.args = {
236
+ color: 'primary',
237
+ size: 'medium',
238
+ width: 220,
239
+ paperMaxHeight: 412,
240
+ hasInputLabel: true,
241
+ placeholder: PLACEHOLDER,
242
+ helperText: 'test',
243
+ disabled: false,
244
+ SelectProps: {},
245
+ }