Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | // @flow
/* eslint-disable max-lines-per-function */
import type { OptionValue, SelectProps } from "@bluframe/blublocks"
import { prepareComponent, useToggle } from "@bluframe/grapple"
import { useMemo, useRef } from "react"
import Select from "./Select"
export type Props = {|
...SelectProps
|}
export type ComponentProps = {|
...SelectProps,
+displayValue: string | React$Node,
+isControlled: boolean,
+isLabelShrunk: boolean,
+isOpen: boolean,
+onChange: (value: OptionValue | null) => () => void,
+onToggleIsOpen: () => void,
+wrapperRef: { current: null | HTMLDivElement }
|}
const DEFAULT_IS_OPEN = false
const usePrepareComponent = (props: Props): ComponentProps => {
const [isOpen, toggleIsOpen] = useToggle(DEFAULT_IS_OPEN)
// Determine if the component is controlled
const isControlled = props.value !== undefined
const wrapperRef = useRef(null)
// Get displayValue and isLabelShrunk
const [displayValue, isLabelShrunk] = useMemo(() => {
// Get selected option
const selectedOption = props.options.find(
(option) =>
(!isControlled && option.value === props.defaultValue) ||
option.value === props.value
)
// If selected option exists, return its label and shrink the label
if (selectedOption) {
return [selectedOption.label, true]
}
// If no selected option and placeholder exists, return placeholder and shrink the label
if (props.placeholder) {
return [props.placeholder, true]
}
// Otherwise, return the label and shrink it when options are open
return ["", isOpen]
}, [
props.defaultValue,
props.options,
props.value,
props.placeholder,
isControlled,
isOpen
])
const onBlur = (event: SyntheticEvent<*>) => {
if (props.onBlur) {
props.onBlur(event)
}
}
const onToggleIsOpen = () => {
// If the dropdown is currently open and is being closed by a click, trigger onBlur
if (isOpen) {
if (wrapperRef.current) {
wrapperRef.current.blur()
}
}
// Toggle options dropdown
toggleIsOpen()
}
const onChange = (value: OptionValue | null) => () => {
// Select via onSelect from props
props.onChange(value)
// If open close options dropdown
if (isOpen) {
onToggleIsOpen()
}
}
return {
...props,
displayValue,
isControlled,
isLabelShrunk,
isOpen,
onBlur,
onChange,
onToggleIsOpen,
wrapperRef
}
}
export default (prepareComponent<Props, ComponentProps>(usePrepareComponent)(
Select
): React$ComponentType<Props>)
|