@iobroker/json-config 6.17.6 → 6.17.12
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/LICENSE +21 -21
- package/build/JsonConfig.d.ts +1 -1
- package/build/JsonConfig.js +18 -19
- package/build/JsonConfig.js.map +1 -1
- package/build/JsonConfigComponent/ChipInput.d.ts +89 -11
- package/build/JsonConfigComponent/ChipInput.js +48 -137
- package/build/JsonConfigComponent/ChipInput.js.map +1 -1
- package/build/JsonConfigComponent/ConfigAccordion.d.ts +7 -14
- package/build/JsonConfigComponent/ConfigAccordion.js +10 -21
- package/build/JsonConfigComponent/ConfigAccordion.js.map +1 -1
- package/build/JsonConfigComponent/ConfigAlive.d.ts +5 -1
- package/build/JsonConfigComponent/ConfigAlive.js +0 -1
- package/build/JsonConfigComponent/ConfigAlive.js.map +1 -1
- package/build/JsonConfigComponent/ConfigAutocomplete.d.ts +5 -29
- package/build/JsonConfigComponent/ConfigAutocomplete.js +7 -5
- package/build/JsonConfigComponent/ConfigAutocomplete.js.map +1 -1
- package/build/JsonConfigComponent/ConfigAutocompleteSendTo.d.ts +5 -14
- package/build/JsonConfigComponent/ConfigAutocompleteSendTo.js +3 -3
- package/build/JsonConfigComponent/ConfigAutocompleteSendTo.js.map +1 -1
- package/build/JsonConfigComponent/ConfigCRON.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigCertCollection.d.ts +7 -13
- package/build/JsonConfigComponent/ConfigCertCollection.js +8 -18
- package/build/JsonConfigComponent/ConfigCertCollection.js.map +1 -1
- package/build/JsonConfigComponent/ConfigCertificateSelect.d.ts +7 -13
- package/build/JsonConfigComponent/ConfigCertificateSelect.js +5 -18
- package/build/JsonConfigComponent/ConfigCertificateSelect.js.map +1 -1
- package/build/JsonConfigComponent/ConfigCertificates.d.ts +7 -13
- package/build/JsonConfigComponent/ConfigCertificates.js +7 -18
- package/build/JsonConfigComponent/ConfigCertificates.js.map +1 -1
- package/build/JsonConfigComponent/ConfigCheckbox.d.ts +3 -11
- package/build/JsonConfigComponent/ConfigCheckbox.js +2 -2
- package/build/JsonConfigComponent/ConfigCheckbox.js.map +1 -1
- package/build/JsonConfigComponent/ConfigChip.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigColor.d.ts +13 -20
- package/build/JsonConfigComponent/ConfigColor.js +9 -23
- package/build/JsonConfigComponent/ConfigColor.js.map +1 -1
- package/build/JsonConfigComponent/ConfigCoordinates.d.ts +8 -13
- package/build/JsonConfigComponent/ConfigCoordinates.js +29 -39
- package/build/JsonConfigComponent/ConfigCoordinates.js.map +1 -1
- package/build/JsonConfigComponent/ConfigCustom.d.ts +4 -50
- package/build/JsonConfigComponent/ConfigCustom.js +0 -1
- package/build/JsonConfigComponent/ConfigCustom.js.map +1 -1
- package/build/JsonConfigComponent/ConfigDatePicker.d.ts +8 -3
- package/build/JsonConfigComponent/ConfigDatePicker.js +21 -13
- package/build/JsonConfigComponent/ConfigDatePicker.js.map +1 -1
- package/build/JsonConfigComponent/ConfigDeviceManager.d.ts +5 -1
- package/build/JsonConfigComponent/ConfigDeviceManager.js +1 -1
- package/build/JsonConfigComponent/ConfigDeviceManager.js.map +1 -1
- package/build/JsonConfigComponent/ConfigFile.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigFunc.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigGeneric.d.ts +46 -32
- package/build/JsonConfigComponent/ConfigGeneric.js +23 -12
- package/build/JsonConfigComponent/ConfigGeneric.js.map +1 -1
- package/build/JsonConfigComponent/ConfigIP.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigImageSendTo.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigInstanceSelect.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigInterface.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigJsonEditor.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigLanguage.d.ts +3 -2
- package/build/JsonConfigComponent/ConfigLanguage.js +2 -2
- package/build/JsonConfigComponent/ConfigLanguage.js.map +1 -1
- package/build/JsonConfigComponent/ConfigNumber.d.ts +3 -13
- package/build/JsonConfigComponent/ConfigNumber.js +2 -2
- package/build/JsonConfigComponent/ConfigNumber.js.map +1 -1
- package/build/JsonConfigComponent/ConfigObjectId.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigPanel.d.ts +7 -2
- package/build/JsonConfigComponent/ConfigPanel.js +5 -40
- package/build/JsonConfigComponent/ConfigPanel.js.map +1 -1
- package/build/JsonConfigComponent/ConfigPassword.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigPort.d.ts +6 -1
- package/build/JsonConfigComponent/ConfigPort.js +2 -3
- package/build/JsonConfigComponent/ConfigPort.js.map +1 -1
- package/build/JsonConfigComponent/ConfigRoom.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigSelect.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigSelectSendTo.d.ts +7 -16
- package/build/JsonConfigComponent/ConfigSelectSendTo.js +15 -61
- package/build/JsonConfigComponent/ConfigSelectSendTo.js.map +1 -1
- package/build/JsonConfigComponent/ConfigSendto.d.ts +3 -20
- package/build/JsonConfigComponent/ConfigSendto.js +8 -8
- package/build/JsonConfigComponent/ConfigSendto.js.map +1 -1
- package/build/JsonConfigComponent/ConfigSetState.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigSlider.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigStaticDivider.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigStaticHeader.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigStaticImage.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigStaticText.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigTable.d.ts +4 -25
- package/build/JsonConfigComponent/ConfigTable.js +5 -4
- package/build/JsonConfigComponent/ConfigTable.js.map +1 -1
- package/build/JsonConfigComponent/ConfigTabs.d.ts +8 -33
- package/build/JsonConfigComponent/ConfigTabs.js +10 -43
- package/build/JsonConfigComponent/ConfigTabs.js.map +1 -1
- package/build/JsonConfigComponent/ConfigText.d.ts +7 -13
- package/build/JsonConfigComponent/ConfigText.js +13 -18
- package/build/JsonConfigComponent/ConfigText.js.map +1 -1
- package/build/JsonConfigComponent/ConfigTextSendTo.d.ts +7 -9
- package/build/JsonConfigComponent/ConfigTextSendTo.js +11 -21
- package/build/JsonConfigComponent/ConfigTextSendTo.js.map +1 -1
- package/build/JsonConfigComponent/ConfigTimePicker.d.ts +9 -3
- package/build/JsonConfigComponent/ConfigTimePicker.js +28 -18
- package/build/JsonConfigComponent/ConfigTimePicker.js.map +1 -1
- package/build/JsonConfigComponent/ConfigTopic.d.ts +1 -1
- package/build/JsonConfigComponent/ConfigUUID.d.ts +12 -13
- package/build/JsonConfigComponent/ConfigUUID.js +1 -6
- package/build/JsonConfigComponent/ConfigUUID.js.map +1 -1
- package/build/JsonConfigComponent/ConfigUser.d.ts +1 -1
- package/build/JsonConfigComponent/index.d.ts +66 -25
- package/build/JsonConfigComponent/index.js +48 -61
- package/build/JsonConfigComponent/index.js.map +1 -1
- package/build/index.d.ts +2 -2
- package/build/index.js +2 -2
- package/build/index.js.map +1 -1
- package/package.json +27 -26
- package/src/JsonConfig.tsx +710 -0
- package/src/JsonConfigComponent/ChipInput.tsx +752 -0
- package/src/JsonConfigComponent/ConfigAccordion.tsx +278 -0
- package/src/JsonConfigComponent/ConfigAlive.tsx +74 -0
- package/src/JsonConfigComponent/ConfigAutocomplete.tsx +108 -0
- package/src/JsonConfigComponent/ConfigAutocompleteSendTo.tsx +183 -0
- package/src/JsonConfigComponent/ConfigCRON.jsx +101 -0
- package/src/JsonConfigComponent/ConfigCertCollection.tsx +102 -0
- package/src/JsonConfigComponent/ConfigCertificateSelect.tsx +92 -0
- package/src/JsonConfigComponent/ConfigCertificates.tsx +202 -0
- package/src/JsonConfigComponent/ConfigCheckLicense.jsx +662 -0
- package/src/JsonConfigComponent/ConfigCheckbox.tsx +67 -0
- package/src/JsonConfigComponent/ConfigChip.jsx +81 -0
- package/src/JsonConfigComponent/ConfigColor.tsx +86 -0
- package/src/JsonConfigComponent/ConfigCoordinates.tsx +234 -0
- package/src/JsonConfigComponent/ConfigCustom.tsx +246 -0
- package/src/JsonConfigComponent/ConfigDatePicker.tsx +48 -0
- package/src/JsonConfigComponent/ConfigDeviceManager.tsx +33 -0
- package/src/JsonConfigComponent/ConfigFile.jsx +181 -0
- package/src/JsonConfigComponent/ConfigFileSelector.jsx +520 -0
- package/src/JsonConfigComponent/ConfigFunc.jsx +90 -0
- package/src/JsonConfigComponent/ConfigGeneric.tsx +1027 -0
- package/src/JsonConfigComponent/ConfigIP.jsx +96 -0
- package/src/JsonConfigComponent/ConfigImageSendTo.jsx +79 -0
- package/src/JsonConfigComponent/ConfigImageUpload.jsx +114 -0
- package/src/JsonConfigComponent/ConfigInstanceSelect.jsx +172 -0
- package/src/JsonConfigComponent/ConfigInterface.jsx +112 -0
- package/src/JsonConfigComponent/ConfigJsonEditor.jsx +103 -0
- package/src/JsonConfigComponent/ConfigLanguage.tsx +153 -0
- package/src/JsonConfigComponent/ConfigLicense.jsx +148 -0
- package/src/JsonConfigComponent/ConfigNumber.tsx +207 -0
- package/src/JsonConfigComponent/ConfigObjectId.jsx +113 -0
- package/src/JsonConfigComponent/ConfigPanel.tsx +360 -0
- package/src/JsonConfigComponent/ConfigPassword.jsx +160 -0
- package/src/JsonConfigComponent/ConfigPattern.jsx +50 -0
- package/src/JsonConfigComponent/ConfigPort.tsx +232 -0
- package/src/JsonConfigComponent/ConfigRoom.jsx +90 -0
- package/src/JsonConfigComponent/ConfigSelect.jsx +124 -0
- package/src/JsonConfigComponent/ConfigSelectSendTo.tsx +251 -0
- package/src/JsonConfigComponent/ConfigSendto.tsx +340 -0
- package/src/JsonConfigComponent/ConfigSetState.jsx +116 -0
- package/src/JsonConfigComponent/ConfigSlider.jsx +97 -0
- package/src/JsonConfigComponent/ConfigStaticDivider.jsx +51 -0
- package/src/JsonConfigComponent/ConfigStaticHeader.jsx +63 -0
- package/src/JsonConfigComponent/ConfigStaticImage.jsx +48 -0
- package/src/JsonConfigComponent/ConfigStaticText.jsx +72 -0
- package/src/JsonConfigComponent/ConfigTable.tsx +1040 -0
- package/src/JsonConfigComponent/ConfigTabs.tsx +150 -0
- package/src/JsonConfigComponent/ConfigText.tsx +188 -0
- package/src/JsonConfigComponent/ConfigTextSendTo.tsx +102 -0
- package/src/JsonConfigComponent/ConfigTimePicker.tsx +63 -0
- package/src/JsonConfigComponent/ConfigTopic.jsx +78 -0
- package/src/JsonConfigComponent/ConfigUUID.tsx +55 -0
- package/src/JsonConfigComponent/ConfigUser.jsx +104 -0
- package/src/JsonConfigComponent/index.tsx +435 -0
- package/src/JsonConfigComponent/wrapper/Components/CustomModal.jsx +145 -0
- package/src/JsonConfigComponent/wrapper/Components/Editor.jsx +65 -0
- package/src/Utils.jsx +1683 -0
- package/src/index.tsx +14 -0
- package/src/types.d.ts +372 -0
|
@@ -0,0 +1,752 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notice: Some code was adapted from Material-UI's text field.
|
|
3
|
+
* Copyright (c) 2014 Call-Em-All (https://github.com/callemall/material-ui)
|
|
4
|
+
*/
|
|
5
|
+
import React, { type RefObject } from 'react';
|
|
6
|
+
import ReactDOM from 'react-dom';
|
|
7
|
+
import { withStyles } from '@mui/styles';
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
Input,
|
|
11
|
+
OutlinedInput,
|
|
12
|
+
InputLabel,
|
|
13
|
+
Chip,
|
|
14
|
+
FormControl,
|
|
15
|
+
FormHelperText, type Theme,
|
|
16
|
+
} from '@mui/material';
|
|
17
|
+
import FilledInput from '@mui/material/FilledInput/FilledInput';
|
|
18
|
+
import blue from '@mui/material/colors/blue';
|
|
19
|
+
|
|
20
|
+
import Utils from '../Utils';
|
|
21
|
+
|
|
22
|
+
const variantComponent = {
|
|
23
|
+
standard: Input,
|
|
24
|
+
filled: FilledInput,
|
|
25
|
+
outlined: OutlinedInput,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const styles: Record<string, any> = (theme: Theme) => {
|
|
29
|
+
// @ts-expect-error The type does exist
|
|
30
|
+
const light = theme.palette.type === 'light';
|
|
31
|
+
const bottomLineColor = light ? 'rgba(0, 0, 0, 0.42)' : 'rgba(255, 255, 255, 0.7)';
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
root: {},
|
|
35
|
+
inputRoot: {
|
|
36
|
+
display: 'inline-flex',
|
|
37
|
+
flexWrap: 'wrap',
|
|
38
|
+
flex: 1,
|
|
39
|
+
marginTop: 0,
|
|
40
|
+
minWidth: 70,
|
|
41
|
+
'&$outlined,&$filled': {
|
|
42
|
+
boxSizing: 'border-box',
|
|
43
|
+
},
|
|
44
|
+
'&$outlined': {
|
|
45
|
+
paddingTop: 14,
|
|
46
|
+
},
|
|
47
|
+
'&$filled': {
|
|
48
|
+
paddingTop: 28,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
input: {
|
|
52
|
+
display: 'inline-block',
|
|
53
|
+
textOverflow: 'ellipsis',
|
|
54
|
+
overflow: 'hidden',
|
|
55
|
+
whiteSpace: 'nowrap',
|
|
56
|
+
appearance: 'none', // Remove border in Safari, doesn't seem to break anything in other browsers
|
|
57
|
+
WebkitTapHighlightColor: 'rgba(0,0,0,0)', // Remove mobile color flashing (deprecated style).
|
|
58
|
+
float: 'left',
|
|
59
|
+
flex: 1,
|
|
60
|
+
},
|
|
61
|
+
chipContainer: {
|
|
62
|
+
display: 'flex',
|
|
63
|
+
flexFlow: 'row wrap',
|
|
64
|
+
cursor: 'text',
|
|
65
|
+
marginBottom: -2,
|
|
66
|
+
minHeight: 40,
|
|
67
|
+
'&$labeled&$standard': {
|
|
68
|
+
marginTop: 18,
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
outlined: {
|
|
72
|
+
'& input': {
|
|
73
|
+
height: 16,
|
|
74
|
+
paddingTop: 4,
|
|
75
|
+
paddingBottom: 12,
|
|
76
|
+
marginTop: 4,
|
|
77
|
+
marginBottom: 4,
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
standard: {},
|
|
81
|
+
filled: {
|
|
82
|
+
'& input': {
|
|
83
|
+
height: 22,
|
|
84
|
+
marginBottom: 4,
|
|
85
|
+
marginTop: 4,
|
|
86
|
+
paddingTop: 0,
|
|
87
|
+
},
|
|
88
|
+
'$marginDense & input': {
|
|
89
|
+
height: 26,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
labeled: {},
|
|
93
|
+
label: {
|
|
94
|
+
top: 4,
|
|
95
|
+
'&$outlined&:not($labelShrink)': {
|
|
96
|
+
top: 2,
|
|
97
|
+
'$marginDense &': {
|
|
98
|
+
top: 5,
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
'&$filled&:not($labelShrink)': {
|
|
102
|
+
top: 15,
|
|
103
|
+
'$marginDense &': {
|
|
104
|
+
top: 20,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
labelShrink: {
|
|
109
|
+
top: 0,
|
|
110
|
+
},
|
|
111
|
+
helperText: {
|
|
112
|
+
marginBottom: -20,
|
|
113
|
+
},
|
|
114
|
+
focused: {},
|
|
115
|
+
disabled: {},
|
|
116
|
+
underline: {
|
|
117
|
+
'&:after': {
|
|
118
|
+
borderBottom: `2px solid ${theme.palette.primary[light ? 'dark' : 'light']}`,
|
|
119
|
+
left: 0,
|
|
120
|
+
bottom: 0,
|
|
121
|
+
// Doing the other way around a crash on IE 11 "''" https://github.com/cssinjs/jss/issues/242
|
|
122
|
+
content: '""',
|
|
123
|
+
position: 'absolute',
|
|
124
|
+
right: 0,
|
|
125
|
+
transform: 'scaleX(0)',
|
|
126
|
+
transition: theme.transitions.create('transform', {
|
|
127
|
+
duration: theme.transitions.duration.shorter,
|
|
128
|
+
easing: theme.transitions.easing.easeOut,
|
|
129
|
+
}),
|
|
130
|
+
pointerEvents: 'none', // Transparent to the hover style.
|
|
131
|
+
},
|
|
132
|
+
'&$focused:after': {
|
|
133
|
+
transform: 'scaleX(1)',
|
|
134
|
+
},
|
|
135
|
+
'&$error:after': {
|
|
136
|
+
borderBottomColor: theme.palette.error.main,
|
|
137
|
+
transform: 'scaleX(1)', // error is always underlined in red
|
|
138
|
+
},
|
|
139
|
+
'&:before': {
|
|
140
|
+
borderBottom: `1px solid ${bottomLineColor}`,
|
|
141
|
+
left: 0,
|
|
142
|
+
bottom: 0,
|
|
143
|
+
// Doing the other way around a crash on IE 11 "''" https://github.com/cssinjs/jss/issues/242
|
|
144
|
+
content: '"\\00a0"',
|
|
145
|
+
position: 'absolute',
|
|
146
|
+
right: 0,
|
|
147
|
+
transition: theme.transitions.create('border-bottom-color', {
|
|
148
|
+
duration: theme.transitions.duration.shorter,
|
|
149
|
+
}),
|
|
150
|
+
pointerEvents: 'none', // Transparent to the hover style.
|
|
151
|
+
},
|
|
152
|
+
'&:hover:not($disabled):not($focused):not($error):before': {
|
|
153
|
+
borderBottom: `2px solid ${theme.palette.text.primary}`,
|
|
154
|
+
// Reset on touch devices, it doesn't add specificity
|
|
155
|
+
'@media (hover: none)': {
|
|
156
|
+
borderBottom: `1px solid ${bottomLineColor}`,
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
'&$disabled:before': {
|
|
160
|
+
borderBottomStyle: 'dotted',
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
error: {
|
|
164
|
+
'&:after': {
|
|
165
|
+
backgroundColor: theme.palette.error.main,
|
|
166
|
+
transform: 'scaleX(1)', // error is always underlined in red
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
chip: {
|
|
170
|
+
margin: '0 8px 8px 0',
|
|
171
|
+
float: 'left',
|
|
172
|
+
},
|
|
173
|
+
marginDense: {},
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const keyCodes = {
|
|
178
|
+
BACKSPACE: 8,
|
|
179
|
+
DELETE: 46,
|
|
180
|
+
LEFT_ARROW: 37,
|
|
181
|
+
RIGHT_ARROW: 39,
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
interface ChipRendererProps {
|
|
185
|
+
value: string;
|
|
186
|
+
isFocused: boolean;
|
|
187
|
+
isDisabled: boolean;
|
|
188
|
+
isReadOnly: boolean;
|
|
189
|
+
handleClick: () => void;
|
|
190
|
+
handleDelete: () => void;
|
|
191
|
+
className: string;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export const defaultChipRenderer = ({
|
|
195
|
+
value,
|
|
196
|
+
isFocused,
|
|
197
|
+
isDisabled,
|
|
198
|
+
isReadOnly,
|
|
199
|
+
handleClick,
|
|
200
|
+
handleDelete,
|
|
201
|
+
className,
|
|
202
|
+
}: ChipRendererProps, key: string) =>
|
|
203
|
+
<Chip
|
|
204
|
+
key={key}
|
|
205
|
+
className={className}
|
|
206
|
+
style={{
|
|
207
|
+
pointerEvents: isDisabled || isReadOnly ? 'none' : undefined,
|
|
208
|
+
backgroundColor: isFocused ? blue[300] : undefined,
|
|
209
|
+
}}
|
|
210
|
+
onClick={handleClick}
|
|
211
|
+
onDelete={handleDelete}
|
|
212
|
+
label={value}
|
|
213
|
+
/>;
|
|
214
|
+
|
|
215
|
+
interface ChipInputProps {
|
|
216
|
+
/** Allows duplicate chips if set to true. */
|
|
217
|
+
allowDuplicates?: boolean;
|
|
218
|
+
/** If true, the placeholder will always be visible. */
|
|
219
|
+
alwaysShowPlaceholder?: boolean;
|
|
220
|
+
/** Behavior when the chip input is blurred: `'clear'` clears the input, `'add'` creates a chip and `'ignore'` keeps the input. */
|
|
221
|
+
blurBehavior: 'clear' | 'add' | 'add-or-clear' | 'ignore';
|
|
222
|
+
/** A function of the type `({ value, text, chip, isFocused, isDisabled, isReadOnly, handleClick, handleDelete, className }, key) => node` that returns a chip based on the given properties. This can be used to customize chip styles. Each item in the `dataSource` array will be passed to `chipRenderer` as arguments `chip`, `value` and `text`. If `dataSource` is an array of objects and `dataSourceConfig` is present, then `value` and `text` will instead correspond to the object values defined in `dataSourceConfig`. If `dataSourceConfig` is not set and `dataSource` is an array of objects, then a custom `chipRenderer` must be set. `chip` is always the raw value from `dataSource`, either an object or a string. */
|
|
223
|
+
chipRenderer: (props: ChipRendererProps) => React.JSX.Element;
|
|
224
|
+
/** Whether the input value should be cleared if the `value` prop is changed. */
|
|
225
|
+
clearInputValueOnChange?: boolean;
|
|
226
|
+
/** Data source for auto complete. This should be an array of strings or objects. */
|
|
227
|
+
dataSource?: string[];
|
|
228
|
+
/** The chips to display by default (for uncontrolled mode). */
|
|
229
|
+
defaultValue?: string[];
|
|
230
|
+
/** Whether to use `setTimeout` to delay adding chips in case other input events like `onSelection` need to fire first */
|
|
231
|
+
delayBeforeAdd?: boolean;
|
|
232
|
+
/** Disables the chip input if set to true. */
|
|
233
|
+
disabled?: boolean;
|
|
234
|
+
/** Disable the input underline. Only valid for 'standard' variant */
|
|
235
|
+
disableUnderline?: boolean;
|
|
236
|
+
/** Props to pass through to the `FormHelperText` component. */
|
|
237
|
+
FormHelperTextProps: Record<string, any>;
|
|
238
|
+
/** If true, the chip input will fill the available width. */
|
|
239
|
+
fullWidth?: boolean;
|
|
240
|
+
/** If true, the input field will always be below the chips and fill the available space. By default, it will try to be beside the chips. */
|
|
241
|
+
fullWidthInput?: boolean;
|
|
242
|
+
/** Helper text that is displayed below the input. */
|
|
243
|
+
helperText?: string | React.JSX.Element;
|
|
244
|
+
/** Props to pass through to the `InputLabel`. */
|
|
245
|
+
InputLabelProps?: Record<string, any>;
|
|
246
|
+
/** Props to pass through to the `Input`. */
|
|
247
|
+
InputProps?: Record<string, any>;
|
|
248
|
+
/** Use this property to pass a ref callback to the native input component. */
|
|
249
|
+
inputRef: (el: HTMLInputElement) => void;
|
|
250
|
+
/** The input value (enables controlled mode for the text input if set). */
|
|
251
|
+
inputValue?: string;
|
|
252
|
+
/* The content of the floating label. */
|
|
253
|
+
label?: string | React.JSX.Element;
|
|
254
|
+
/** The key codes (`KeyboardEvent.keyCode`) used to determine when to create a new chip. */
|
|
255
|
+
newChipKeyCodes?: number[];
|
|
256
|
+
/** The keys (`KeyboardEvent.key`) used to determine when to create a new chip. */
|
|
257
|
+
newChipKeys?: string[];
|
|
258
|
+
/** Callback function that is called when a new chip was added (in controlled mode). */
|
|
259
|
+
onAdd?: (chip: string) => void;
|
|
260
|
+
/** Callback function that is called with the chip to be added and should return true to add the chip or false to prevent the chip from being added without clearing the text input. */
|
|
261
|
+
onBeforeAdd: (chip: string) => boolean;
|
|
262
|
+
onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
|
|
263
|
+
onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
|
|
264
|
+
onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
265
|
+
onKeyUp?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
266
|
+
onKeyPress?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
267
|
+
/** Callback function that is called when the chips change (in uncontrolled mode). */
|
|
268
|
+
onChange: (chips: string[]) => void;
|
|
269
|
+
/** Callback function that is called when a new chip was removed (in controlled mode). */
|
|
270
|
+
onDelete: (chip: string, i: number) => void;
|
|
271
|
+
/** Callback function that is called when the input changes. */
|
|
272
|
+
onUpdateInput: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
273
|
+
/** A placeholder that is displayed if the input has no values. */
|
|
274
|
+
placeholder?: string;
|
|
275
|
+
/** Makes the chip input read-only if set to true. */
|
|
276
|
+
readOnly?: boolean;
|
|
277
|
+
/** The chips to display (enables controlled mode if set). */
|
|
278
|
+
value?: string[];
|
|
279
|
+
/** The variant of the Input component */
|
|
280
|
+
variant?: 'outlined' | 'standard' | 'filled';
|
|
281
|
+
classes?: Record<string, string>;
|
|
282
|
+
className?: string;
|
|
283
|
+
error?: boolean;
|
|
284
|
+
id?: string;
|
|
285
|
+
required?: boolean;
|
|
286
|
+
rootRef?: RefObject<HTMLDivElement>;
|
|
287
|
+
margin?: 'dense' | 'normal' | 'none';
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
interface ChipInputState {
|
|
291
|
+
chips: string[];
|
|
292
|
+
focusedChip: number | null;
|
|
293
|
+
inputValue: string;
|
|
294
|
+
isFocused: boolean;
|
|
295
|
+
chipsUpdated: boolean;
|
|
296
|
+
prevPropsValue: string[];
|
|
297
|
+
variant: 'outlined' | 'standard' | 'filled';
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
class ChipInput extends React.Component<ChipInputProps, ChipInputState> {
|
|
301
|
+
private readonly labelRef: React.RefObject<HTMLLabelElement>;
|
|
302
|
+
|
|
303
|
+
private labelNode: HTMLLabelElement | null = null;
|
|
304
|
+
|
|
305
|
+
private readonly input: React.RefObject<HTMLInputElement>;
|
|
306
|
+
|
|
307
|
+
private readonly newChipKeyCodes: number[];
|
|
308
|
+
|
|
309
|
+
private readonly newChipKeys: string[];
|
|
310
|
+
|
|
311
|
+
private actualInput: HTMLInputElement | null = null;
|
|
312
|
+
|
|
313
|
+
private inputBlurTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
314
|
+
|
|
315
|
+
private _keyPressed: boolean;
|
|
316
|
+
|
|
317
|
+
private _preventChipCreation: boolean;
|
|
318
|
+
|
|
319
|
+
constructor(props: ChipInputProps) {
|
|
320
|
+
super(props);
|
|
321
|
+
this.state = {
|
|
322
|
+
chips: props.defaultValue || [],
|
|
323
|
+
focusedChip: null,
|
|
324
|
+
inputValue: '',
|
|
325
|
+
isFocused: false,
|
|
326
|
+
chipsUpdated: false,
|
|
327
|
+
prevPropsValue: [],
|
|
328
|
+
variant: this.props.variant || 'standard',
|
|
329
|
+
};
|
|
330
|
+
this.newChipKeyCodes = props.newChipKeyCodes || [13];
|
|
331
|
+
this.newChipKeys = props.newChipKeys || ['Enter'];
|
|
332
|
+
|
|
333
|
+
this.labelRef = React.createRef();
|
|
334
|
+
this.input = React.createRef();
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
componentDidMount() {
|
|
338
|
+
if (this.state.variant === 'outlined') {
|
|
339
|
+
// eslint-disable-next-line react/no-find-dom-node
|
|
340
|
+
this.labelNode = ReactDOM.findDOMNode(this.labelRef.current) as HTMLLabelElement;
|
|
341
|
+
this.forceUpdate();
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
componentWillUnmount() {
|
|
346
|
+
this.inputBlurTimeout && clearTimeout(this.inputBlurTimeout);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
static getDerivedStateFromProps(props: ChipInputProps, state: ChipInputState) {
|
|
350
|
+
let newState: Partial<ChipInputState> | null = null;
|
|
351
|
+
|
|
352
|
+
if (props.value && props.value.length !== state.prevPropsValue.length) {
|
|
353
|
+
newState = { prevPropsValue: props.value };
|
|
354
|
+
if (props.clearInputValueOnChange) {
|
|
355
|
+
newState.inputValue = '';
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// if change detection is only needed for clearInputValueOnChange
|
|
360
|
+
if (props.clearInputValueOnChange && props.value && props.value.length !== state.prevPropsValue.length) {
|
|
361
|
+
newState = { prevPropsValue: props.value, inputValue: '' };
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (props.disabled) {
|
|
365
|
+
newState = { ...newState, focusedChip: null };
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (!state.chipsUpdated && props.defaultValue) {
|
|
369
|
+
newState = { ...newState, chips: props.defaultValue };
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return newState;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Blurs this component.
|
|
377
|
+
* @public
|
|
378
|
+
*/
|
|
379
|
+
// blur() {
|
|
380
|
+
// if (this.input) {
|
|
381
|
+
// this.actualInput.blur();
|
|
382
|
+
// }
|
|
383
|
+
// }
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Focuses this component.
|
|
387
|
+
* @public
|
|
388
|
+
*/
|
|
389
|
+
focus = () => {
|
|
390
|
+
this.actualInput?.focus();
|
|
391
|
+
if (this.state.focusedChip) {
|
|
392
|
+
this.setState({ focusedChip: null });
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
handleInputBlur = (event: React.FocusEvent<HTMLInputElement>) => {
|
|
397
|
+
if (this.props.onBlur) {
|
|
398
|
+
this.props.onBlur(event);
|
|
399
|
+
}
|
|
400
|
+
this.setState({ isFocused: false });
|
|
401
|
+
if (this.state.focusedChip) {
|
|
402
|
+
this.setState({ focusedChip: null });
|
|
403
|
+
}
|
|
404
|
+
const value = event.target.value;
|
|
405
|
+
let addChipOptions: { clearInputOnFail: boolean };
|
|
406
|
+
switch (this.props.blurBehavior || 'clear') {
|
|
407
|
+
case 'add-or-clear':
|
|
408
|
+
addChipOptions = { clearInputOnFail: true };
|
|
409
|
+
// falls through
|
|
410
|
+
case 'add':
|
|
411
|
+
if (this.props.delayBeforeAdd) {
|
|
412
|
+
// Let's assume that we only want to add the existing content as chip, when
|
|
413
|
+
// another event has not added a chip within 200ms.
|
|
414
|
+
// e.g., onSelection Callback in Autocomplete case
|
|
415
|
+
const numChipsBefore = (this.props.value || this.state.chips).length;
|
|
416
|
+
this.inputBlurTimeout = setTimeout(() => {
|
|
417
|
+
const numChipsAfter = (this.props.value || this.state.chips).length;
|
|
418
|
+
if (numChipsBefore === numChipsAfter) {
|
|
419
|
+
this.handleAddChip(value, addChipOptions);
|
|
420
|
+
} else {
|
|
421
|
+
this.clearInput();
|
|
422
|
+
}
|
|
423
|
+
}, 150);
|
|
424
|
+
} else {
|
|
425
|
+
this.handleAddChip(value, addChipOptions);
|
|
426
|
+
}
|
|
427
|
+
break;
|
|
428
|
+
|
|
429
|
+
case 'clear':
|
|
430
|
+
this.clearInput();
|
|
431
|
+
break;
|
|
432
|
+
|
|
433
|
+
default:
|
|
434
|
+
break;
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
handleInputFocus = (event: React.FocusEvent<HTMLInputElement>) => {
|
|
439
|
+
this.setState({ isFocused: true });
|
|
440
|
+
if (this.props.onFocus) {
|
|
441
|
+
this.props.onFocus(event);
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
446
|
+
const { focusedChip } = this.state;
|
|
447
|
+
this._keyPressed = false;
|
|
448
|
+
this._preventChipCreation = false;
|
|
449
|
+
|
|
450
|
+
if (this.props.onKeyDown) {
|
|
451
|
+
// Needed for arrow controls on a menu in autocomplete scenario
|
|
452
|
+
this.props.onKeyDown(event);
|
|
453
|
+
// Check if the callback marked the event as isDefaultPrevented() and skip further actions
|
|
454
|
+
// enter key, for example, should not always add the current value of the inputField
|
|
455
|
+
if (event.isDefaultPrevented()) {
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
const chips = this.props.value || this.state.chips;
|
|
460
|
+
if (this.newChipKeyCodes.includes(event.keyCode) || this.newChipKeys.includes(event.key)) {
|
|
461
|
+
const result = this.handleAddChip((event.target as HTMLInputElement).value);
|
|
462
|
+
if (result !== false) {
|
|
463
|
+
event.preventDefault();
|
|
464
|
+
}
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
switch (event.keyCode) {
|
|
469
|
+
case keyCodes.BACKSPACE:
|
|
470
|
+
if ((event.target as HTMLInputElement).value === '') {
|
|
471
|
+
if (focusedChip) {
|
|
472
|
+
this.handleDeleteChip(chips[focusedChip], focusedChip);
|
|
473
|
+
if (focusedChip) {
|
|
474
|
+
this.setState({ focusedChip: focusedChip - 1 });
|
|
475
|
+
}
|
|
476
|
+
} else {
|
|
477
|
+
this.setState({ focusedChip: chips.length - 1 });
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
break;
|
|
481
|
+
case keyCodes.DELETE:
|
|
482
|
+
if ((event.target as HTMLInputElement).value === '' && focusedChip) {
|
|
483
|
+
this.handleDeleteChip(chips[focusedChip], focusedChip);
|
|
484
|
+
if (focusedChip <= chips.length - 1) {
|
|
485
|
+
this.setState({ focusedChip });
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
break;
|
|
489
|
+
case keyCodes.LEFT_ARROW:
|
|
490
|
+
if (focusedChip === null && (event.target as HTMLInputElement).value === '' && chips.length) {
|
|
491
|
+
this.setState({ focusedChip: chips.length - 1 });
|
|
492
|
+
} else if (focusedChip !== null && focusedChip > 0) {
|
|
493
|
+
this.setState({ focusedChip: focusedChip - 1 });
|
|
494
|
+
}
|
|
495
|
+
break;
|
|
496
|
+
case keyCodes.RIGHT_ARROW:
|
|
497
|
+
if (focusedChip !== null && focusedChip < chips.length - 1) {
|
|
498
|
+
this.setState({ focusedChip: focusedChip + 1 });
|
|
499
|
+
} else {
|
|
500
|
+
this.setState({ focusedChip: null });
|
|
501
|
+
}
|
|
502
|
+
break;
|
|
503
|
+
default:
|
|
504
|
+
this.setState({ focusedChip: null });
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
handleKeyUp = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
510
|
+
if (!this._preventChipCreation && (this.newChipKeyCodes.includes(event.keyCode) || this.newChipKeys.includes(event.key)) && this._keyPressed) {
|
|
511
|
+
this.clearInput();
|
|
512
|
+
} else {
|
|
513
|
+
this.updateInput((event.target as HTMLInputElement).value);
|
|
514
|
+
}
|
|
515
|
+
if (this.props.onKeyUp) {
|
|
516
|
+
this.props.onKeyUp(event);
|
|
517
|
+
}
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
handleKeyPress = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
521
|
+
this._keyPressed = true;
|
|
522
|
+
if (this.props.onKeyPress) {
|
|
523
|
+
this.props.onKeyPress(event);
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
handleUpdateInput = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
528
|
+
if (this.props.inputValue === null || this.props.inputValue === undefined) {
|
|
529
|
+
this.updateInput(e.target.value);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (this.props.onUpdateInput) {
|
|
533
|
+
this.props.onUpdateInput(e);
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Handles adding a chip.
|
|
539
|
+
* @param {string|object} chip Value of the chip, either a string or an object (if dataSourceConfig is set)
|
|
540
|
+
* @param {object=} options Additional options
|
|
541
|
+
* @param {boolean=} options.clearInputOnFail If `true`, and `onBeforeAdd` returns `false`, clear the input
|
|
542
|
+
* @returns True if the chip was added (or at least `onAdd` was called), false if adding the chip was prevented
|
|
543
|
+
*/
|
|
544
|
+
handleAddChip(chip: string, options?: { clearInputOnFail: boolean }): boolean {
|
|
545
|
+
if (this.props.onBeforeAdd && !this.props.onBeforeAdd(chip)) {
|
|
546
|
+
this._preventChipCreation = true;
|
|
547
|
+
if (options && options.clearInputOnFail) {
|
|
548
|
+
this.clearInput();
|
|
549
|
+
}
|
|
550
|
+
return false;
|
|
551
|
+
}
|
|
552
|
+
this.clearInput();
|
|
553
|
+
const chips = this.props.value || this.state.chips;
|
|
554
|
+
|
|
555
|
+
if ((chip as string).trim().length) {
|
|
556
|
+
if (this.props.allowDuplicates || !chips.includes(chip as string)) {
|
|
557
|
+
if (this.props.value && this.props.onAdd) {
|
|
558
|
+
this.props.onAdd(chip);
|
|
559
|
+
} else {
|
|
560
|
+
this.updateChips([...this.state.chips, chip]);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
return true;
|
|
564
|
+
}
|
|
565
|
+
return false;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
handleDeleteChip(chip: string, i: number) {
|
|
569
|
+
if (!this.props.value) {
|
|
570
|
+
const chips = this.state.chips.slice();
|
|
571
|
+
const changed = chips.splice(i, 1); // remove the chip at index i
|
|
572
|
+
if (changed) {
|
|
573
|
+
let focusedChip = this.state.focusedChip;
|
|
574
|
+
if (this.state.focusedChip === i) {
|
|
575
|
+
focusedChip = null;
|
|
576
|
+
} else if (this.state.focusedChip > i) {
|
|
577
|
+
focusedChip = this.state.focusedChip - 1;
|
|
578
|
+
}
|
|
579
|
+
this.updateChips(chips, { focusedChip });
|
|
580
|
+
}
|
|
581
|
+
} else if (this.props.onDelete) {
|
|
582
|
+
this.props.onDelete(chip, i);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
updateChips(chips: string[], additionalUpdates = {}) {
|
|
587
|
+
this.setState({ chips, chipsUpdated: true, ...additionalUpdates });
|
|
588
|
+
if (this.props.onChange) {
|
|
589
|
+
this.props.onChange(chips);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* Clears the text field for adding new chips.
|
|
595
|
+
* This only works in uncontrolled input mode, i.e., if the inputValue prop is not used.
|
|
596
|
+
* @public
|
|
597
|
+
*/
|
|
598
|
+
clearInput() {
|
|
599
|
+
this.updateInput('');
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
updateInput(value: string) {
|
|
603
|
+
this.setState({ inputValue: value });
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Set the reference to the actual input, that is the input of the Input.
|
|
608
|
+
* @param {object} ref - The reference
|
|
609
|
+
*/
|
|
610
|
+
setActualInputRef = (ref: HTMLInputElement) => {
|
|
611
|
+
this.actualInput = ref;
|
|
612
|
+
this.props.inputRef && this.props.inputRef(ref);
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
render() {
|
|
616
|
+
const {
|
|
617
|
+
alwaysShowPlaceholder,
|
|
618
|
+
chipRenderer = defaultChipRenderer,
|
|
619
|
+
classes,
|
|
620
|
+
className,
|
|
621
|
+
disabled,
|
|
622
|
+
disableUnderline,
|
|
623
|
+
error,
|
|
624
|
+
FormHelperTextProps,
|
|
625
|
+
fullWidth,
|
|
626
|
+
fullWidthInput,
|
|
627
|
+
helperText,
|
|
628
|
+
id,
|
|
629
|
+
InputProps = {},
|
|
630
|
+
InputLabelProps = {},
|
|
631
|
+
inputValue,
|
|
632
|
+
label,
|
|
633
|
+
placeholder,
|
|
634
|
+
readOnly,
|
|
635
|
+
required,
|
|
636
|
+
rootRef,
|
|
637
|
+
value,
|
|
638
|
+
margin,
|
|
639
|
+
} = this.props;
|
|
640
|
+
const variant = this.state.variant;
|
|
641
|
+
|
|
642
|
+
let chips = value || this.state.chips || [];
|
|
643
|
+
if (!Array.isArray(chips)) {
|
|
644
|
+
chips = (chips as string || '').toString().split(/[,\s]+/).map((c: string) => c.trim());
|
|
645
|
+
}
|
|
646
|
+
const actualInputValue = inputValue ?? this.state.inputValue;
|
|
647
|
+
|
|
648
|
+
const hasInput = (this.props.value || actualInputValue).length || actualInputValue.length;
|
|
649
|
+
const shrinkFloatingLabel = typeof InputLabelProps.shrink === 'boolean'
|
|
650
|
+
? InputLabelProps.shrink
|
|
651
|
+
: (label !== null && (hasInput || this.state.isFocused || chips.length));
|
|
652
|
+
|
|
653
|
+
const chipComponents = chips.map((chip, i) => chipRenderer(
|
|
654
|
+
{
|
|
655
|
+
value: chip,
|
|
656
|
+
isDisabled: !!disabled,
|
|
657
|
+
isReadOnly: readOnly,
|
|
658
|
+
isFocused: this.state.focusedChip === i,
|
|
659
|
+
handleClick: () => this.setState({ focusedChip: i }),
|
|
660
|
+
handleDelete: () => this.handleDeleteChip(chip, i),
|
|
661
|
+
className: classes.chip,
|
|
662
|
+
},
|
|
663
|
+
i.toString(),
|
|
664
|
+
));
|
|
665
|
+
|
|
666
|
+
const InputMore: { notched?: boolean; labelWidth?: number; startAdornment?: React.JSX.Element[] } = {};
|
|
667
|
+
if (variant === 'outlined') {
|
|
668
|
+
InputMore.notched = !!shrinkFloatingLabel;
|
|
669
|
+
InputMore.labelWidth =
|
|
670
|
+
(shrinkFloatingLabel && this.labelNode && this.labelNode.offsetWidth) ||
|
|
671
|
+
0;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
if (variant !== 'standard') {
|
|
675
|
+
InputMore.startAdornment = chipComponents;
|
|
676
|
+
} else {
|
|
677
|
+
InputProps.disableUnderline = true;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
const InputComponent = variantComponent[variant];
|
|
681
|
+
|
|
682
|
+
return <FormControl
|
|
683
|
+
ref={rootRef}
|
|
684
|
+
fullWidth={fullWidth}
|
|
685
|
+
className={Utils.clsx(className, classes.root, margin === 'dense' && classes.marginDense)}
|
|
686
|
+
error={error}
|
|
687
|
+
required={chips.length > 0 ? undefined : required}
|
|
688
|
+
onClick={this.focus}
|
|
689
|
+
disabled={disabled}
|
|
690
|
+
variant={variant}
|
|
691
|
+
component="div"
|
|
692
|
+
margin={margin}
|
|
693
|
+
>
|
|
694
|
+
{label && <InputLabel
|
|
695
|
+
htmlFor={id}
|
|
696
|
+
classes={{ root: Utils.clsx(classes[variant], classes.label), shrink: classes.labelShrink }}
|
|
697
|
+
shrink={!!shrinkFloatingLabel}
|
|
698
|
+
focused={this.state.isFocused}
|
|
699
|
+
variant={variant}
|
|
700
|
+
ref={this.labelRef}
|
|
701
|
+
required={required}
|
|
702
|
+
component="label"
|
|
703
|
+
{...InputLabelProps}
|
|
704
|
+
>
|
|
705
|
+
{label}
|
|
706
|
+
</InputLabel>}
|
|
707
|
+
<div
|
|
708
|
+
className={Utils.clsx(
|
|
709
|
+
classes[variant],
|
|
710
|
+
classes.chipContainer,
|
|
711
|
+
this.state.isFocused && classes.focused,
|
|
712
|
+
!disableUnderline && variant === 'standard' && classes.underline,
|
|
713
|
+
disabled && classes.disabled,
|
|
714
|
+
label && classes.labeled,
|
|
715
|
+
error && classes.error,
|
|
716
|
+
)}
|
|
717
|
+
>
|
|
718
|
+
{variant === 'standard' && chipComponents}
|
|
719
|
+
<InputComponent
|
|
720
|
+
ref={this.input}
|
|
721
|
+
classes={{
|
|
722
|
+
input: Utils.clsx(classes.input, classes[variant]),
|
|
723
|
+
root: Utils.clsx(classes.inputRoot, classes[variant]),
|
|
724
|
+
}}
|
|
725
|
+
id={id}
|
|
726
|
+
value={actualInputValue}
|
|
727
|
+
onChange={this.handleUpdateInput}
|
|
728
|
+
onKeyDown={this.handleKeyDown}
|
|
729
|
+
onKeyPress={this.handleKeyPress}
|
|
730
|
+
onKeyUp={this.handleKeyUp}
|
|
731
|
+
onFocus={this.handleInputFocus}
|
|
732
|
+
onBlur={this.handleInputBlur}
|
|
733
|
+
inputRef={this.setActualInputRef}
|
|
734
|
+
disabled={disabled}
|
|
735
|
+
fullWidth={fullWidthInput}
|
|
736
|
+
placeholder={(!hasInput && (shrinkFloatingLabel || label === null || label === undefined)) || alwaysShowPlaceholder ? placeholder : null}
|
|
737
|
+
readOnly={readOnly}
|
|
738
|
+
{...InputProps}
|
|
739
|
+
{...InputMore}
|
|
740
|
+
/>
|
|
741
|
+
</div>
|
|
742
|
+
{helperText && <FormHelperText
|
|
743
|
+
{...FormHelperTextProps}
|
|
744
|
+
className={FormHelperTextProps ? Utils.clsx(FormHelperTextProps.className, classes.helperText) : classes.helperText}
|
|
745
|
+
>
|
|
746
|
+
{helperText}
|
|
747
|
+
</FormHelperText>}
|
|
748
|
+
</FormControl>;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
export default withStyles(styles, { name: 'WAMuiChipInput' })(ChipInput);
|