@junyiacademy/ui-test 0.0.4 → 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.
- package/declarations/libs/ui/src/lib/selection-item/SelectionItem.d.ts +10 -0
- package/dist/libs/ui/src/lib/selection-item/SelectionItem.js +16 -0
- package/package.json +1 -1
- package/src/lib/TopicFilter.tsx +5 -14
- package/src/lib/menu-item/SelectMenuItem.tsx +5 -11
- package/src/lib/radio/Radio.stories.tsx +3 -2
- package/src/lib/select/OutlinedSelect.stories.tsx +79 -58
- package/src/lib/select/OutlinedSelect.tsx +34 -79
- package/src/lib/select/StandardSelect.stories.tsx +45 -29
- package/src/lib/select/StandardSelect.tsx +14 -50
- package/src/lib/text-field/TextField.stories.tsx +35 -1
- package/declarations/libs/ui/src/index.d.ts +0 -8
- package/declarations/libs/ui/src/interfaces/index.d.ts +0 -8
- package/declarations/libs/ui/src/lib/TopicFilter.d.ts +0 -13
- package/declarations/libs/ui/src/lib/button/Button.d.ts +0 -6
- package/declarations/libs/ui/src/lib/button-group/ButtonGroup.d.ts +0 -3
- package/declarations/libs/ui/src/lib/menu-item/SelectMenuItem.d.ts +0 -9
- package/declarations/libs/ui/src/lib/radio/Radio.d.ts +0 -10
- package/declarations/libs/ui/src/lib/select/OutlinedSelect.d.ts +0 -24
- package/declarations/libs/ui/src/lib/select/StandardSelect.d.ts +0 -20
- package/declarations/libs/ui/src/lib/text-field/TextField.d.ts +0 -3
- package/dist/libs/ui/src/index.js +0 -22
- package/dist/libs/ui/src/interfaces/index.js +0 -2
- package/dist/libs/ui/src/lib/TopicFilter.js +0 -123
- package/dist/libs/ui/src/lib/button/Button.js +0 -71
- package/dist/libs/ui/src/lib/button-group/ButtonGroup.js +0 -33
- package/dist/libs/ui/src/lib/menu-item/SelectMenuItem.js +0 -30
- package/dist/libs/ui/src/lib/radio/Radio.js +0 -43
- package/dist/libs/ui/src/lib/select/OutlinedSelect.js +0 -132
- package/dist/libs/ui/src/lib/select/StandardSelect.js +0 -105
- package/dist/libs/ui/src/lib/text-field/TextField.js +0 -75
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
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'
|
|
3
6
|
import { StandardSelect, StandardSelectProps } from './StandardSelect'
|
|
4
7
|
import SelectMenuItem from '../menu-item/SelectMenuItem'
|
|
5
8
|
|
|
@@ -29,7 +32,6 @@ export default {
|
|
|
29
32
|
},
|
|
30
33
|
options: ['small', 'medium'],
|
|
31
34
|
control: { type: 'radio' },
|
|
32
|
-
defaultValue: 'medium',
|
|
33
35
|
},
|
|
34
36
|
width: {
|
|
35
37
|
type: { name: 'number', required: false },
|
|
@@ -39,7 +41,6 @@ export default {
|
|
|
39
41
|
defaultValue: { summary: 'auto' },
|
|
40
42
|
},
|
|
41
43
|
control: { type: 'number' },
|
|
42
|
-
defaultValue: '220',
|
|
43
44
|
},
|
|
44
45
|
paperMaxHeight: {
|
|
45
46
|
type: { name: 'number', required: false },
|
|
@@ -49,17 +50,15 @@ export default {
|
|
|
49
50
|
defaultValue: { summary: 'auto' },
|
|
50
51
|
},
|
|
51
52
|
control: { type: 'number' },
|
|
52
|
-
defaultValue: '412',
|
|
53
53
|
},
|
|
54
54
|
hasShrink: {
|
|
55
55
|
type: { name: 'boolean', required: false },
|
|
56
|
-
description: '
|
|
56
|
+
description: 'If true, the label is displayed and shrunk.',
|
|
57
57
|
table: {
|
|
58
58
|
type: { summary: 'boolean' },
|
|
59
59
|
defaultValue: { summary: true },
|
|
60
60
|
},
|
|
61
61
|
control: { type: 'boolean' },
|
|
62
|
-
defaultValue: true,
|
|
63
62
|
},
|
|
64
63
|
placeholder: {
|
|
65
64
|
type: { name: 'string', required: true },
|
|
@@ -69,7 +68,6 @@ export default {
|
|
|
69
68
|
defaultValue: { summary: '請選擇' },
|
|
70
69
|
},
|
|
71
70
|
control: { type: 'text' },
|
|
72
|
-
defaultValue: '請選擇',
|
|
73
71
|
},
|
|
74
72
|
value: {
|
|
75
73
|
type: { name: 'any', required: false },
|
|
@@ -98,33 +96,21 @@ export default {
|
|
|
98
96
|
},
|
|
99
97
|
control: { type: 'boolean' },
|
|
100
98
|
},
|
|
101
|
-
hasHelperText: {
|
|
102
|
-
type: { name: 'boolean', required: false },
|
|
103
|
-
description: 'If true, the helper text will be displayed.',
|
|
104
|
-
table: {
|
|
105
|
-
type: { summary: 'boolean' },
|
|
106
|
-
defaultValue: { summary: false },
|
|
107
|
-
},
|
|
108
|
-
control: { type: 'boolean' },
|
|
109
|
-
},
|
|
110
99
|
helperText: {
|
|
111
100
|
type: { name: 'string', required: true },
|
|
112
|
-
description: `
|
|
101
|
+
description: `Display the helper text.`,
|
|
113
102
|
table: {
|
|
114
103
|
type: { summary: 'string' },
|
|
115
|
-
defaultValue: { summary: '
|
|
104
|
+
defaultValue: { summary: '' },
|
|
116
105
|
},
|
|
117
106
|
control: { type: 'text' },
|
|
118
|
-
defaultValue: 'Helper text.',
|
|
119
107
|
},
|
|
120
|
-
|
|
121
|
-
type: { name: '
|
|
122
|
-
description: '
|
|
108
|
+
InputProps: {
|
|
109
|
+
type: { name: 'any', required: false },
|
|
110
|
+
description: 'Attributes applied to inner Input element.',
|
|
123
111
|
table: {
|
|
124
|
-
type: { summary: '
|
|
125
|
-
defaultValue: { summary: false },
|
|
112
|
+
type: { summary: 'any' },
|
|
126
113
|
},
|
|
127
|
-
control: { type: 'boolean' },
|
|
128
114
|
},
|
|
129
115
|
SelectProps: {
|
|
130
116
|
type: { name: 'any', required: false },
|
|
@@ -136,6 +122,31 @@ export default {
|
|
|
136
122
|
},
|
|
137
123
|
} as Meta
|
|
138
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
|
+
|
|
139
150
|
const StandardSelectWithMenu = (props: StandardSelectProps) => {
|
|
140
151
|
const [item, setItem] = useState<string>('')
|
|
141
152
|
|
|
@@ -179,14 +190,21 @@ ValueOnly.args = {
|
|
|
179
190
|
paperMaxHeight: 300,
|
|
180
191
|
hasShrink: false,
|
|
181
192
|
placeholder: PLACEHOLDER,
|
|
182
|
-
hasHelperText: false,
|
|
183
193
|
helperText: 'test',
|
|
184
|
-
hasAdornment: false,
|
|
185
194
|
disabled: false,
|
|
186
195
|
}
|
|
187
196
|
|
|
188
197
|
const WithPrefixStory: Story<StandardSelectProps> = (args) => (
|
|
189
|
-
<StandardSelectWithMenu
|
|
198
|
+
<StandardSelectWithMenu
|
|
199
|
+
InputProps={{
|
|
200
|
+
startAdornment: (
|
|
201
|
+
<StyledInputAdornment position='start' disabled={args.disabled}>
|
|
202
|
+
<Visibility />
|
|
203
|
+
</StyledInputAdornment>
|
|
204
|
+
),
|
|
205
|
+
}}
|
|
206
|
+
{...args}
|
|
207
|
+
/>
|
|
190
208
|
)
|
|
191
209
|
|
|
192
210
|
export const WithPrefix = WithPrefixStory.bind({})
|
|
@@ -198,8 +216,6 @@ WithPrefix.args = {
|
|
|
198
216
|
paperMaxHeight: 300,
|
|
199
217
|
hasShrink: false,
|
|
200
218
|
placeholder: PLACEHOLDER,
|
|
201
|
-
hasHelperText: false,
|
|
202
219
|
helperText: 'test',
|
|
203
|
-
hasAdornment: true,
|
|
204
220
|
disabled: false,
|
|
205
221
|
}
|
|
@@ -6,20 +6,18 @@ import {
|
|
|
6
6
|
Select,
|
|
7
7
|
SelectProps,
|
|
8
8
|
Input,
|
|
9
|
+
InputProps,
|
|
9
10
|
FormHelperText,
|
|
10
11
|
InputAdornment,
|
|
11
12
|
} from '@material-ui/core'
|
|
12
|
-
import VisibilityIcon from '@material-ui/icons/Visibility'
|
|
13
13
|
|
|
14
14
|
// self-defined-components
|
|
15
15
|
const PREFIX = 'JuiStandardSelect'
|
|
16
16
|
|
|
17
17
|
const classes = {
|
|
18
|
-
inputLabelRoot: `${PREFIX}-inputLabel`,
|
|
19
18
|
inputLabelFocused: `${PREFIX}-inputLabelFocused`,
|
|
20
19
|
inputLabelMarginDense: `${PREFIX}-inputLabelMarginDense`,
|
|
21
20
|
inputLabelError: `${PREFIX}-inputLabelError`,
|
|
22
|
-
inputRoot: `${PREFIX}-inputRoot`,
|
|
23
21
|
inputUnderline: `${PREFIX}-inputUnderline`,
|
|
24
22
|
inputError: `${PREFIX}-inputError`,
|
|
25
23
|
inputDisabled: `${PREFIX}-inputDisabled`,
|
|
@@ -49,22 +47,19 @@ interface StyledInputLabelProps {
|
|
|
49
47
|
const StyledInputLabel = styled(({ color: _color, ...props }) => (
|
|
50
48
|
<InputLabel
|
|
51
49
|
classes={{
|
|
52
|
-
root: classes.inputLabelRoot,
|
|
53
50
|
focused: classes.inputLabelFocused,
|
|
54
51
|
error: classes.inputLabelError,
|
|
55
52
|
}}
|
|
56
53
|
{...props}
|
|
57
54
|
/>
|
|
58
55
|
))(({ color, theme }: StyledInputLabelProps) => ({
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
[
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
color: theme.palette.error.main,
|
|
67
|
-
},
|
|
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,
|
|
68
63
|
},
|
|
69
64
|
}))
|
|
70
65
|
|
|
@@ -109,16 +104,13 @@ const StyledInput = styled(({ color: _color, ...props }) => (
|
|
|
109
104
|
<Input
|
|
110
105
|
classes={{
|
|
111
106
|
disabled: classes.inputDisabled,
|
|
112
|
-
root: classes.inputRoot,
|
|
113
107
|
underline: classes.inputUnderline,
|
|
114
108
|
error: classes.inputError,
|
|
115
109
|
}}
|
|
116
110
|
{...props}
|
|
117
111
|
/>
|
|
118
112
|
))(({ color, theme }: StyledInputProps) => ({
|
|
119
|
-
|
|
120
|
-
color: theme.palette.text.primary,
|
|
121
|
-
},
|
|
113
|
+
color: theme.palette.text.primary,
|
|
122
114
|
[`&.${classes.inputUnderline}:not(.${classes.inputDisabled}):not(.${classes.inputError})`]: {
|
|
123
115
|
[`&:after,&:hover:before`]: {
|
|
124
116
|
borderBottomColor: theme.palette[color].main,
|
|
@@ -131,23 +123,6 @@ const StyledInput = styled(({ color: _color, ...props }) => (
|
|
|
131
123
|
},
|
|
132
124
|
}))
|
|
133
125
|
|
|
134
|
-
interface StyledInputAdornmentProps {
|
|
135
|
-
theme: Theme
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const StyledInputAdornment = styled((props) => (
|
|
139
|
-
<InputAdornment
|
|
140
|
-
classes={{
|
|
141
|
-
root: classes.inputAdornmentRoot,
|
|
142
|
-
}}
|
|
143
|
-
{...props}
|
|
144
|
-
/>
|
|
145
|
-
))(({ theme }: StyledInputAdornmentProps) => ({
|
|
146
|
-
[`&.${classes.inputAdornmentRoot}`]: {
|
|
147
|
-
color: theme.palette.action.active,
|
|
148
|
-
},
|
|
149
|
-
}))
|
|
150
|
-
|
|
151
126
|
export interface StandardSelectProps {
|
|
152
127
|
color?: 'primary' | 'secondary'
|
|
153
128
|
size?: 'medium' | 'small'
|
|
@@ -156,9 +131,8 @@ export interface StandardSelectProps {
|
|
|
156
131
|
error?: boolean
|
|
157
132
|
hasShrink?: boolean
|
|
158
133
|
placeholder: string
|
|
159
|
-
hasHelperText?: boolean
|
|
160
134
|
helperText?: string
|
|
161
|
-
|
|
135
|
+
InputProps?: object & Partial<InputProps>
|
|
162
136
|
value?: unknown
|
|
163
137
|
disabled?: boolean
|
|
164
138
|
SelectProps?: object | Partial<SelectProps>
|
|
@@ -173,14 +147,15 @@ export function StandardSelect({
|
|
|
173
147
|
error = false,
|
|
174
148
|
hasShrink = false,
|
|
175
149
|
placeholder,
|
|
176
|
-
hasHelperText = false,
|
|
177
150
|
helperText,
|
|
178
|
-
|
|
151
|
+
InputProps,
|
|
179
152
|
value = '',
|
|
180
153
|
SelectProps,
|
|
181
154
|
disabled = false,
|
|
182
155
|
children,
|
|
183
156
|
}: StandardSelectProps) {
|
|
157
|
+
const hasAdornment = !!InputProps?.startAdornment
|
|
158
|
+
const hasHelperText = !!helperText
|
|
184
159
|
return (
|
|
185
160
|
<StyledFormControl
|
|
186
161
|
color={color}
|
|
@@ -200,18 +175,7 @@ export function StandardSelect({
|
|
|
200
175
|
value={value}
|
|
201
176
|
paperMaxHeight={paperMaxHeight}
|
|
202
177
|
hasAdornment={hasAdornment}
|
|
203
|
-
input={
|
|
204
|
-
<StyledInput
|
|
205
|
-
color={color}
|
|
206
|
-
startAdornment={
|
|
207
|
-
hasAdornment && (
|
|
208
|
-
<StyledInputAdornment position='start'>
|
|
209
|
-
<VisibilityIcon />
|
|
210
|
-
</StyledInputAdornment>
|
|
211
|
-
)
|
|
212
|
-
}
|
|
213
|
-
/>
|
|
214
|
-
}
|
|
178
|
+
input={<StyledInput color={color} {...InputProps} />}
|
|
215
179
|
{...SelectProps}
|
|
216
180
|
>
|
|
217
181
|
{children}
|
|
@@ -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}
|
|
@@ -1,8 +0,0 @@
|
|
|
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';
|
|
4
|
-
export { default as Button } from './lib/button/Button';
|
|
5
|
-
export { default as ButtonGroup } from './lib/button-group/ButtonGroup';
|
|
6
|
-
export { default as Radio } from './lib/radio/Radio';
|
|
7
|
-
export { default as TextField } from './lib/text-field/TextField';
|
|
8
|
-
export { default as StandardSelect } from './lib/select/StandardSelect';
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { ITopicTreeNode } from '../interfaces';
|
|
2
|
-
export interface TopicFilterProps {
|
|
3
|
-
topicTree: ITopicTreeNode;
|
|
4
|
-
onTopicSelected: (topic: ITopicTreeNode, selectedInfo: {
|
|
5
|
-
layerNumber: number;
|
|
6
|
-
selectedTopicIds: string[];
|
|
7
|
-
}) => void;
|
|
8
|
-
isLastLayer: (topic: ITopicTreeNode) => boolean;
|
|
9
|
-
hasArrow: boolean;
|
|
10
|
-
initSelectedTopicIds: string[];
|
|
11
|
-
}
|
|
12
|
-
declare const TopicFilter: ({ topicTree, onTopicSelected, isLastLayer, hasArrow, initSelectedTopicIds, }: TopicFilterProps) => JSX.Element;
|
|
13
|
-
export default TopicFilter;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { MenuItemProps } from '@material-ui/core';
|
|
3
|
-
export interface SelectMenuItemProps extends MenuItemProps {
|
|
4
|
-
width: number | 'auto';
|
|
5
|
-
value?: any;
|
|
6
|
-
disabled?: boolean;
|
|
7
|
-
}
|
|
8
|
-
declare const SelectMenuItem: React.ForwardRefExoticComponent<Pick<React.PropsWithChildren<SelectMenuItemProps>, "button" | "slot" | "style" | "title" | "color" | "width" | "alignItems" | "translate" | "hidden" | "dense" | "disabled" | "classes" | "className" | "children" | "placeholder" | "value" | "innerRef" | "key" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "id" | "lang" | "spellCheck" | "tabIndex" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "autoFocus" | "selected" | "ContainerComponent" | "ContainerProps" | "disableGutters" | "divider" | "focusVisibleClassName"> & React.RefAttributes<HTMLLIElement>>;
|
|
9
|
-
export default SelectMenuItem;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { RadioProps as MuiRadioProps, FormControlLabelProps } from '@material-ui/core';
|
|
2
|
-
export interface RadioProps extends FormControlLabelProps {
|
|
3
|
-
color?: 'primary' | 'secondary' | 'default';
|
|
4
|
-
size?: 'medium' | 'small';
|
|
5
|
-
caption?: string;
|
|
6
|
-
formControlLabelProps?: Partial<FormControlLabelProps>;
|
|
7
|
-
radioProps?: Partial<MuiRadioProps>;
|
|
8
|
-
}
|
|
9
|
-
export declare const Radio: ({ checked, disabled, label, labelPlacement, value, formControlLabelProps, radioProps, color, size, caption, }: RadioProps) => JSX.Element;
|
|
10
|
-
export default Radio;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import React, { ChangeEvent } from 'react';
|
|
2
|
-
import { SelectProps, OutlinedInputProps } from '@material-ui/core';
|
|
3
|
-
export interface OutlinedSelectProps {
|
|
4
|
-
color?: 'primary' | 'secondary';
|
|
5
|
-
size?: 'medium' | 'small';
|
|
6
|
-
width?: number | 'auto';
|
|
7
|
-
selectPaperMaxHeight?: number | 'auto';
|
|
8
|
-
error?: boolean;
|
|
9
|
-
hasLabel?: boolean;
|
|
10
|
-
hasShrink?: boolean;
|
|
11
|
-
placeholder: string;
|
|
12
|
-
hasHelperText?: boolean;
|
|
13
|
-
helperText?: string;
|
|
14
|
-
hasAdornment?: boolean;
|
|
15
|
-
value?: unknown;
|
|
16
|
-
disabled?: boolean;
|
|
17
|
-
SelectProps?: object | Partial<SelectProps>;
|
|
18
|
-
OutlinedInputProps?: Partial<OutlinedInputProps> & {
|
|
19
|
-
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
|
|
20
|
-
};
|
|
21
|
-
children?: React.ReactNode;
|
|
22
|
-
}
|
|
23
|
-
declare const OutlinedSelect: ({ color, size, width, selectPaperMaxHeight, error, hasLabel, hasShrink, placeholder, hasHelperText, helperText, hasAdornment, value, disabled, SelectProps, OutlinedInputProps, children, }: OutlinedSelectProps) => JSX.Element;
|
|
24
|
-
export default OutlinedSelect;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { SelectProps } from '@material-ui/core';
|
|
3
|
-
export interface StandardSelectProps {
|
|
4
|
-
color?: 'primary' | 'secondary';
|
|
5
|
-
size?: 'medium' | 'small';
|
|
6
|
-
width?: number | 'auto';
|
|
7
|
-
paperMaxHeight?: number | 'auto';
|
|
8
|
-
error?: boolean;
|
|
9
|
-
hasShrink?: boolean;
|
|
10
|
-
placeholder: string;
|
|
11
|
-
hasHelperText?: boolean;
|
|
12
|
-
helperText?: string;
|
|
13
|
-
hasAdornment?: boolean;
|
|
14
|
-
value?: unknown;
|
|
15
|
-
disabled?: boolean;
|
|
16
|
-
SelectProps?: object | Partial<SelectProps>;
|
|
17
|
-
children?: React.ReactNode;
|
|
18
|
-
}
|
|
19
|
-
export declare function StandardSelect({ color, size, width, paperMaxHeight, error, hasShrink, placeholder, hasHelperText, helperText, hasAdornment, value, SelectProps, disabled, children, }: StandardSelectProps): JSX.Element;
|
|
20
|
-
export default StandardSelect;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.StandardSelect = exports.TextField = exports.Radio = exports.ButtonGroup = exports.Button = exports.OutlinedSelect = exports.SelectMenuItem = exports.TopicFilter = void 0;
|
|
7
|
-
var TopicFilter_1 = require("./lib/TopicFilter");
|
|
8
|
-
Object.defineProperty(exports, "TopicFilter", { enumerable: true, get: function () { return __importDefault(TopicFilter_1).default; } });
|
|
9
|
-
var SelectMenuItem_1 = require("./lib/menu-item/SelectMenuItem");
|
|
10
|
-
Object.defineProperty(exports, "SelectMenuItem", { enumerable: true, get: function () { return __importDefault(SelectMenuItem_1).default; } });
|
|
11
|
-
var OutlinedSelect_1 = require("./lib/select/OutlinedSelect");
|
|
12
|
-
Object.defineProperty(exports, "OutlinedSelect", { enumerable: true, get: function () { return __importDefault(OutlinedSelect_1).default; } });
|
|
13
|
-
var Button_1 = require("./lib/button/Button");
|
|
14
|
-
Object.defineProperty(exports, "Button", { enumerable: true, get: function () { return __importDefault(Button_1).default; } });
|
|
15
|
-
var ButtonGroup_1 = require("./lib/button-group/ButtonGroup");
|
|
16
|
-
Object.defineProperty(exports, "ButtonGroup", { enumerable: true, get: function () { return __importDefault(ButtonGroup_1).default; } });
|
|
17
|
-
var Radio_1 = require("./lib/radio/Radio");
|
|
18
|
-
Object.defineProperty(exports, "Radio", { enumerable: true, get: function () { return __importDefault(Radio_1).default; } });
|
|
19
|
-
var TextField_1 = require("./lib/text-field/TextField");
|
|
20
|
-
Object.defineProperty(exports, "TextField", { enumerable: true, get: function () { return __importDefault(TextField_1).default; } });
|
|
21
|
-
var StandardSelect_1 = require("./lib/select/StandardSelect");
|
|
22
|
-
Object.defineProperty(exports, "StandardSelect", { enumerable: true, get: function () { return __importDefault(StandardSelect_1).default; } });
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const tslib_1 = require("tslib");
|
|
4
|
-
const react_1 = tslib_1.__importStar(require("react"));
|
|
5
|
-
const styles_1 = require("@material-ui/core/styles");
|
|
6
|
-
const ArrowRightRounded_1 = tslib_1.__importDefault(require("@material-ui/icons/ArrowRightRounded"));
|
|
7
|
-
const OutlinedSelect_1 = tslib_1.__importDefault(require("./select/OutlinedSelect"));
|
|
8
|
-
const SelectMenuItem_1 = tslib_1.__importDefault(require("./menu-item/SelectMenuItem"));
|
|
9
|
-
// self-defined-configs
|
|
10
|
-
const PLACEHOLDER = '請選擇';
|
|
11
|
-
// self-defined-components
|
|
12
|
-
const PREFIX = 'JuiTopicFilter';
|
|
13
|
-
const classes = {
|
|
14
|
-
root: `${PREFIX}-arrowIcon`,
|
|
15
|
-
};
|
|
16
|
-
const FiltersWrapper = styles_1.styled('div')({
|
|
17
|
-
display: 'flex',
|
|
18
|
-
alignItems: 'center',
|
|
19
|
-
flexWrap: 'wrap',
|
|
20
|
-
});
|
|
21
|
-
const SelectWrapper = styles_1.styled('div')({
|
|
22
|
-
display: 'flex',
|
|
23
|
-
alignItems: 'center',
|
|
24
|
-
});
|
|
25
|
-
const StyledArrowRightRoundedIcon = styles_1.styled((props) => (react_1.default.createElement(ArrowRightRounded_1.default, Object.assign({ classes: classes }, props))))(({ theme }) => ({
|
|
26
|
-
[`&.${classes.root}`]: {
|
|
27
|
-
margin: theme.spacing(-1, -1.5),
|
|
28
|
-
fontSize: theme.spacing(7),
|
|
29
|
-
color: '#444',
|
|
30
|
-
},
|
|
31
|
-
}));
|
|
32
|
-
const TopicFilter = ({ topicTree, onTopicSelected, isLastLayer, hasArrow, initSelectedTopicIds, }) => {
|
|
33
|
-
const [selectedTopicIds, setSelectedTopicIds] = react_1.useState([]);
|
|
34
|
-
const [layeredTopicList, setLayeredTopicList] = react_1.useState([]);
|
|
35
|
-
const [isFocusedList, setIsFocusedList] = react_1.useState([]);
|
|
36
|
-
const initSelectedLayers = () => {
|
|
37
|
-
const newLayeredTopicList = initSelectedTopicIds.reduce((topicListAccumulator, topicId, index) => {
|
|
38
|
-
var _a, _b;
|
|
39
|
-
const selectedTopic = (_b = (_a = topicListAccumulator[index]) === null || _a === void 0 ? void 0 : _a.childTopics) === null || _b === void 0 ? void 0 : _b.find((childTopic) => childTopic.id === topicId);
|
|
40
|
-
if (!selectedTopic) {
|
|
41
|
-
return topicListAccumulator;
|
|
42
|
-
}
|
|
43
|
-
if (isLastLayer(selectedTopic)) {
|
|
44
|
-
return topicListAccumulator;
|
|
45
|
-
}
|
|
46
|
-
return [...topicListAccumulator, selectedTopic];
|
|
47
|
-
}, [topicTree]);
|
|
48
|
-
setLayeredTopicList(newLayeredTopicList);
|
|
49
|
-
setSelectedTopicIds(initSelectedTopicIds.slice(0, newLayeredTopicList.length));
|
|
50
|
-
setIsFocusedList(Array(newLayeredTopicList.length).fill(false));
|
|
51
|
-
};
|
|
52
|
-
const handleChange = (e, layerNumber, layeredTopic) => {
|
|
53
|
-
const selectedTopic = layeredTopic.childTopics.find((childTopic) => childTopic.id === e.target.value);
|
|
54
|
-
const newSelectedTopicIds = [
|
|
55
|
-
...selectedTopicIds.slice(0, layerNumber),
|
|
56
|
-
selectedTopic.id,
|
|
57
|
-
];
|
|
58
|
-
setSelectedTopicIds(newSelectedTopicIds);
|
|
59
|
-
onTopicSelected(selectedTopic, {
|
|
60
|
-
layerNumber,
|
|
61
|
-
selectedTopicIds: newSelectedTopicIds,
|
|
62
|
-
});
|
|
63
|
-
if (isLastLayer(selectedTopic)) {
|
|
64
|
-
setLayeredTopicList((prevTopicList) => prevTopicList.slice(0, layerNumber + 1));
|
|
65
|
-
setIsFocusedList((prevList) => prevList.slice(0, layerNumber + 1));
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
setLayeredTopicList((prevTopicList) => [
|
|
69
|
-
...prevTopicList.slice(0, layerNumber + 1),
|
|
70
|
-
selectedTopic,
|
|
71
|
-
]);
|
|
72
|
-
setIsFocusedList((prevList) => [
|
|
73
|
-
...prevList.slice(0, layerNumber + 1),
|
|
74
|
-
false,
|
|
75
|
-
]);
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
react_1.useEffect(() => {
|
|
79
|
-
if (!topicTree || Object.keys(topicTree).length === 0) {
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
if (initSelectedTopicIds.length !== 0) {
|
|
83
|
-
initSelectedLayers();
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
setLayeredTopicList([topicTree]);
|
|
87
|
-
}, [topicTree]);
|
|
88
|
-
if (layeredTopicList.length === 0) {
|
|
89
|
-
return (react_1.default.createElement(OutlinedSelect_1.default, { size: 'small', width: 220, placeholder: '\u8F09\u5165\u8CC7\u6599\u4E2D...', disabled: true }));
|
|
90
|
-
}
|
|
91
|
-
return (react_1.default.createElement(FiltersWrapper, null, layeredTopicList.map((layeredTopic, layerNumber) => {
|
|
92
|
-
const hasLabel = isFocusedList[layerNumber] || !selectedTopicIds[layerNumber];
|
|
93
|
-
return (react_1.default.createElement(SelectWrapper, { key: layeredTopic.id },
|
|
94
|
-
react_1.default.createElement(OutlinedSelect_1.default, { size: 'small', width: 220, selectPaperMaxHeight: 412, error: false, hasLabel: hasLabel, hasShrink: false, placeholder: PLACEHOLDER, hasAdornment: false, value: (selectedTopicIds === null || selectedTopicIds === void 0 ? void 0 : selectedTopicIds[layerNumber]) || '', SelectProps: {
|
|
95
|
-
'data-testid': `layered-topic-${layerNumber}`,
|
|
96
|
-
}, OutlinedInputProps: {
|
|
97
|
-
inputProps: {
|
|
98
|
-
'aria-label': `layered-topic-${layerNumber}`,
|
|
99
|
-
},
|
|
100
|
-
onChange: (e) => {
|
|
101
|
-
handleChange(e, layerNumber, layeredTopic);
|
|
102
|
-
},
|
|
103
|
-
onFocus: () => {
|
|
104
|
-
setIsFocusedList((prevList) => {
|
|
105
|
-
const newList = [...prevList];
|
|
106
|
-
newList[layerNumber] = true;
|
|
107
|
-
return newList;
|
|
108
|
-
});
|
|
109
|
-
},
|
|
110
|
-
onBlur: () => {
|
|
111
|
-
setIsFocusedList((prevList) => {
|
|
112
|
-
const newList = [...prevList];
|
|
113
|
-
newList[layerNumber] = false;
|
|
114
|
-
return newList;
|
|
115
|
-
});
|
|
116
|
-
},
|
|
117
|
-
} },
|
|
118
|
-
react_1.default.createElement(SelectMenuItem_1.default, { width: 220, disabled: true }, PLACEHOLDER),
|
|
119
|
-
layeredTopic.childTopics.map((childTopic) => (react_1.default.createElement(SelectMenuItem_1.default, { width: 220, key: childTopic.id, value: childTopic.id, "data-testid": `layered-menuitem-${layerNumber}`, "data-is-content-topic": childTopic.isContentTopic }, childTopic.title)))),
|
|
120
|
-
hasArrow && layerNumber !== layeredTopicList.length - 1 && (react_1.default.createElement(StyledArrowRightRoundedIcon, { fontSize: 'large', "data-testid": 'topic-filter-arrow' }))));
|
|
121
|
-
})));
|
|
122
|
-
};
|
|
123
|
-
exports.default = TopicFilter;
|