diff options
Diffstat (limited to 'packages/forms/src/select')
-rw-r--r-- | packages/forms/src/select/index.tsx | 119 |
1 files changed, 67 insertions, 52 deletions
diff --git a/packages/forms/src/select/index.tsx b/packages/forms/src/select/index.tsx index e5b59cb19..4a5775579 100644 --- a/packages/forms/src/select/index.tsx +++ b/packages/forms/src/select/index.tsx | |||
@@ -1,4 +1,8 @@ | |||
1 | import { mdiArrowRightDropCircleOutline, mdiCloseCircle, mdiMagnify } from '@mdi/js'; | 1 | import { |
2 | mdiArrowRightDropCircleOutline, | ||
3 | mdiCloseCircle, | ||
4 | mdiMagnify, | ||
5 | } from '@mdi/js'; | ||
2 | import Icon from '@mdi/react'; | 6 | import Icon from '@mdi/react'; |
3 | import classnames from 'classnames'; | 7 | import classnames from 'classnames'; |
4 | import React, { Component, createRef } from 'react'; | 8 | import React, { Component, createRef } from 'react'; |
@@ -58,7 +62,7 @@ const styles = (theme: Theme) => ({ | |||
58 | label: { | 62 | label: { |
59 | '& > div': { | 63 | '& > div': { |
60 | marginTop: 5, | 64 | marginTop: 5, |
61 | } | 65 | }, |
62 | }, | 66 | }, |
63 | popup: { | 67 | popup: { |
64 | opacity: 0, | 68 | opacity: 0, |
@@ -153,9 +157,13 @@ class SelectComponent extends Component<IProps> { | |||
153 | }; | 157 | }; |
154 | 158 | ||
155 | private componentRef = createRef<HTMLDivElement>(); | 159 | private componentRef = createRef<HTMLDivElement>(); |
160 | |||
156 | private inputRef = createRef<HTMLInputElement>(); | 161 | private inputRef = createRef<HTMLInputElement>(); |
162 | |||
157 | private searchInputRef = createRef<HTMLInputElement>(); | 163 | private searchInputRef = createRef<HTMLInputElement>(); |
164 | |||
158 | private scrollContainerRef = createRef<HTMLDivElement>(); | 165 | private scrollContainerRef = createRef<HTMLDivElement>(); |
166 | |||
159 | private activeOptionRef = createRef<HTMLDivElement>(); | 167 | private activeOptionRef = createRef<HTMLDivElement>(); |
160 | 168 | ||
161 | private keyListener: any; | 169 | private keyListener: any; |
@@ -168,7 +176,7 @@ class SelectComponent extends Component<IProps> { | |||
168 | } | 176 | } |
169 | } | 177 | } |
170 | 178 | ||
171 | componentDidUpdate(prevProps: IProps, prevState: IState) { | 179 | componentDidUpdate() { |
172 | const { open } = this.state; | 180 | const { open } = this.state; |
173 | 181 | ||
174 | if (this.searchInputRef && this.searchInputRef.current) { | 182 | if (this.searchInputRef && this.searchInputRef.current) { |
@@ -183,7 +191,9 @@ class SelectComponent extends Component<IProps> { | |||
183 | const { data } = this.props; | 191 | const { data } = this.props; |
184 | 192 | ||
185 | if (data) { | 193 | if (data) { |
186 | Object.keys(data).map(key => this.inputRef.current!.dataset[key] = data[key]); | 194 | Object.keys(data).map( |
195 | key => (this.inputRef.current!.dataset[key] = data[key]), | ||
196 | ); | ||
187 | } | 197 | } |
188 | } | 198 | } |
189 | 199 | ||
@@ -194,7 +204,10 @@ class SelectComponent extends Component<IProps> { | |||
194 | const { value } = this.props; | 204 | const { value } = this.props; |
195 | 205 | ||
196 | if (this.componentRef && this.componentRef.current) { | 206 | if (this.componentRef && this.componentRef.current) { |
197 | this.componentRef.current.removeEventListener('keydown', this.keyListener); | 207 | this.componentRef.current.removeEventListener( |
208 | 'keydown', | ||
209 | this.keyListener, | ||
210 | ); | ||
198 | } | 211 | } |
199 | 212 | ||
200 | if (value) { | 213 | if (value) { |
@@ -210,13 +223,18 @@ class SelectComponent extends Component<IProps> { | |||
210 | window.removeEventListener('keydown', this.arrowKeysHandler.bind(this)); | 223 | window.removeEventListener('keydown', this.arrowKeysHandler.bind(this)); |
211 | } | 224 | } |
212 | 225 | ||
213 | setFilter(needle: string = '') { | 226 | setFilter(needle = '') { |
214 | const { options } = this.props; | 227 | const { options } = this.props; |
215 | 228 | ||
216 | let filteredOptions = {}; | 229 | let filteredOptions = {}; |
217 | if (needle) { | 230 | if (needle) { |
218 | Object.keys(options).map((key) => { | 231 | Object.keys(options).map(key => { |
219 | if (key.toLocaleLowerCase().startsWith(needle.toLocaleLowerCase()) || options[key].toLocaleLowerCase().startsWith(needle.toLocaleLowerCase())) { | 232 | if ( |
233 | key.toLocaleLowerCase().startsWith(needle.toLocaleLowerCase()) || | ||
234 | options[key] | ||
235 | .toLocaleLowerCase() | ||
236 | .startsWith(needle.toLocaleLowerCase()) | ||
237 | ) { | ||
220 | Object.assign(filteredOptions, { | 238 | Object.assign(filteredOptions, { |
221 | [`${key}`]: options[key], | 239 | [`${key}`]: options[key], |
222 | }); | 240 | }); |
@@ -234,7 +252,7 @@ class SelectComponent extends Component<IProps> { | |||
234 | } | 252 | } |
235 | 253 | ||
236 | select(key: string) { | 254 | select(key: string) { |
237 | this.setState((state: IState) => ({ | 255 | this.setState(() => ({ |
238 | value: key, | 256 | value: key, |
239 | open: false, | 257 | open: false, |
240 | })); | 258 | })); |
@@ -247,11 +265,7 @@ class SelectComponent extends Component<IProps> { | |||
247 | } | 265 | } |
248 | 266 | ||
249 | arrowKeysHandler(e: KeyboardEvent) { | 267 | arrowKeysHandler(e: KeyboardEvent) { |
250 | const { | 268 | const { selected, open, options } = this.state; |
251 | selected, | ||
252 | open, | ||
253 | options, | ||
254 | } = this.state; | ||
255 | 269 | ||
256 | if (!open) return; | 270 | if (!open) return; |
257 | 271 | ||
@@ -264,7 +278,10 @@ class SelectComponent extends Component<IProps> { | |||
264 | this.setState((state: IState) => ({ | 278 | this.setState((state: IState) => ({ |
265 | selected: state.selected - 1, | 279 | selected: state.selected - 1, |
266 | })); | 280 | })); |
267 | } else if (e.keyCode === 40 && selected < Object.keys(options!).length - 1) { | 281 | } else if ( |
282 | e.keyCode === 40 && | ||
283 | selected < Object.keys(options!).length - 1 | ||
284 | ) { | ||
268 | this.setState((state: IState) => ({ | 285 | this.setState((state: IState) => ({ |
269 | selected: state.selected + 1, | 286 | selected: state.selected + 1, |
270 | })); | 287 | })); |
@@ -272,7 +289,12 @@ class SelectComponent extends Component<IProps> { | |||
272 | this.select(Object.keys(options!)[selected]); | 289 | this.select(Object.keys(options!)[selected]); |
273 | } | 290 | } |
274 | 291 | ||
275 | if (this.activeOptionRef && this.activeOptionRef.current && this.scrollContainerRef && this.scrollContainerRef.current) { | 292 | if ( |
293 | this.activeOptionRef && | ||
294 | this.activeOptionRef.current && | ||
295 | this.scrollContainerRef && | ||
296 | this.scrollContainerRef.current | ||
297 | ) { | ||
276 | const containerTopOffset = this.scrollContainerRef.current.offsetTop; | 298 | const containerTopOffset = this.scrollContainerRef.current.offsetTop; |
277 | const optionTopOffset = this.activeOptionRef.current.offsetTop; | 299 | const optionTopOffset = this.activeOptionRef.current.offsetTop; |
278 | 300 | ||
@@ -282,10 +304,15 @@ class SelectComponent extends Component<IProps> { | |||
282 | } | 304 | } |
283 | } | 305 | } |
284 | 306 | ||
285 | switch (e.keyCode){ | 307 | switch (e.keyCode) { |
286 | case 37: case 39: case 38: case 40: // Arrow keys | 308 | case 37: |
287 | case 32: break; // Space | 309 | case 39: |
288 | default: break; // do not block other keys | 310 | case 38: |
311 | case 40: // Arrow keys | ||
312 | case 32: | ||
313 | break; // Space | ||
314 | default: | ||
315 | break; // do not block other keys | ||
289 | } | 316 | } |
290 | } | 317 | } |
291 | 318 | ||
@@ -307,13 +334,7 @@ class SelectComponent extends Component<IProps> { | |||
307 | required, | 334 | required, |
308 | } = this.props; | 335 | } = this.props; |
309 | 336 | ||
310 | const { | 337 | const { open, needle, value, selected, options } = this.state; |
311 | open, | ||
312 | needle, | ||
313 | value, | ||
314 | selected, | ||
315 | options, | ||
316 | } = this.state; | ||
317 | 338 | ||
318 | let selection = ''; | 339 | let selection = ''; |
319 | if (!value && defaultValue && options![defaultValue]) { | 340 | if (!value && defaultValue && options![defaultValue]) { |
@@ -325,10 +346,7 @@ class SelectComponent extends Component<IProps> { | |||
325 | } | 346 | } |
326 | 347 | ||
327 | return ( | 348 | return ( |
328 | <Wrapper | 349 | <Wrapper className={className} identifier="franz-select"> |
329 | className={className} | ||
330 | identifier="franz-select" | ||
331 | > | ||
332 | <Label | 350 | <Label |
333 | title={label} | 351 | title={label} |
334 | showLabel={showLabel} | 352 | showLabel={showLabel} |
@@ -345,14 +363,19 @@ class SelectComponent extends Component<IProps> { | |||
345 | > | 363 | > |
346 | <button | 364 | <button |
347 | type="button" | 365 | type="button" |
348 | className={classnames({ | 366 | className={classnames({ |
349 | [`${inputClassName}`]: inputClassName, | 367 | [`${inputClassName}`]: inputClassName, |
350 | [`${classes.select}`]: true, | 368 | [`${classes.select}`]: true, |
351 | [`${classes.hasError}`]: error, | 369 | [`${classes.hasError}`]: error, |
352 | })} | 370 | })} |
353 | onClick= {!disabled ? () => this.setState((state: IState) => ({ | 371 | onClick={ |
354 | open: !state.open, | 372 | !disabled |
355 | })) : () => {}} | 373 | ? () => |
374 | this.setState((state: IState) => ({ | ||
375 | open: !state.open, | ||
376 | })) | ||
377 | : () => {} | ||
378 | } | ||
356 | > | 379 | > |
357 | {selection} | 380 | {selection} |
358 | <Icon | 381 | <Icon |
@@ -366,10 +389,7 @@ class SelectComponent extends Component<IProps> { | |||
366 | </button> | 389 | </button> |
367 | {showSearch && open && ( | 390 | {showSearch && open && ( |
368 | <div className={classes.searchContainer}> | 391 | <div className={classes.searchContainer}> |
369 | <Icon | 392 | <Icon path={mdiMagnify} size={0.8} /> |
370 | path={mdiMagnify} | ||
371 | size={0.8} | ||
372 | /> | ||
373 | <input | 393 | <input |
374 | type="text" | 394 | type="text" |
375 | value={needle} | 395 | value={needle} |
@@ -384,10 +404,7 @@ class SelectComponent extends Component<IProps> { | |||
384 | className={classes.clearNeedle} | 404 | className={classes.clearNeedle} |
385 | onClick={() => this.setFilter()} | 405 | onClick={() => this.setFilter()} |
386 | > | 406 | > |
387 | <Icon | 407 | <Icon path={mdiCloseCircle} size={0.7} /> |
388 | path={mdiCloseCircle} | ||
389 | size={0.7} | ||
390 | /> | ||
391 | </button> | 408 | </button> |
392 | )} | 409 | )} |
393 | </div> | 410 | </div> |
@@ -399,7 +416,7 @@ class SelectComponent extends Component<IProps> { | |||
399 | })} | 416 | })} |
400 | ref={this.scrollContainerRef} | 417 | ref={this.scrollContainerRef} |
401 | > | 418 | > |
402 | {Object.keys(options!).map(((key, i) => ( | 419 | {Object.keys(options!).map((key, i) => ( |
403 | <div | 420 | <div |
404 | key={key} | 421 | key={key} |
405 | onClick={() => this.select(key)} | 422 | onClick={() => this.select(key)} |
@@ -413,7 +430,7 @@ class SelectComponent extends Component<IProps> { | |||
413 | > | 430 | > |
414 | {options![key]} | 431 | {options![key]} |
415 | </div> | 432 | </div> |
416 | )))} | 433 | ))} |
417 | </div> | 434 | </div> |
418 | </div> | 435 | </div> |
419 | <input | 436 | <input |
@@ -427,9 +444,7 @@ class SelectComponent extends Component<IProps> { | |||
427 | ref={this.inputRef} | 444 | ref={this.inputRef} |
428 | /> | 445 | /> |
429 | </Label> | 446 | </Label> |
430 | {error && ( | 447 | {error && <Error message={error} />} |
431 | <Error message={error} /> | ||
432 | )} | ||
433 | </Wrapper> | 448 | </Wrapper> |
434 | ); | 449 | ); |
435 | } | 450 | } |