import React , { Fragment , useState , useEffect , useMemo , useCallback } from 'react' ; import { EuiSpacer , EuiButtonEmpty , EuiFlexItem , EuiFormErrorText } from '@elastic/eui' ; import { FormattedMessage } from '@osd/i18n/react' ; import { NumberRow , NumberRowModel } from './number_row' ; import { parse , EMPTY_STRING , getRange , getNextModel , getInitModelList , getValidatedModels , hasInvalidValues , } from './utils' ; import { useValidation } from '../../utils' ; export interface NumberListProps { labelledbyId : string ; numberArray : Array < number | undefined > ; range ? : string ; showValidation : boolean ; disallowDuplicates ? : boolean ; unitName : string ; validateAscendingOrder ? : boolean ; onChange ( list ) : void ; setTouched ( ) : void ; setValidity ( isValid ) : void ; } function NumberList ( { labelledbyId , numberArray , range , showValidation , unitName , validateAscendingOrder = false , disallowDuplicates = false , onChange , setTouched , setValidity , } ) { const numberRange = useMemo ( ( ) => getRange ( range ) , [ range ] ) ; const [ models , setModels ] = useState ( getInitModelList ( numberArray ) ) ; useEffect ( ( ) => { setModels ( ( state ) => getValidatedModels ( numberArray , state , numberRange , validateAscendingOrder , disallowDuplicates ) ) ; } , [ numberArray , numberRange , validateAscendingOrder , disallowDuplicates ] ) ; useEffect ( ( ) => { if ( ! numberArray . length ) { onChange ( [ models [ 0 ] . value as number ] ) ; } } , [ models , numberArray . length , onChange ] ) ; const isValid = ! hasInvalidValues ( models ) ; useValidation ( setValidity , isValid ) ; const onUpdate = useCallback ( ( modelList ) => { setModels ( modelList ) ; onChange ( modelList . map ( ( { value } ) => ( value === EMPTY_STRING ? undefined : value ) ) ) ; } , [ onChange ] ) ; const onChangeValue = useCallback ( ( { id , value } ) => { const parsedValue = parse ( value ) ; onUpdate ( models . map ( ( model ) => { if ( model . id === id ) { return { id , value : parsedValue , isInvalid : false , } ; } return model ; } ) ) ; } , [ models , onUpdate ] ) ; const onAdd = useCallback ( ( ) => { const newArray = [ ... models , getNextModel ( models , numberRange ) ] ; onUpdate ( newArray ) ; } , [ models , numberRange , onUpdate ] ) ; const onDelete = useCallback ( ( id ) => { const newArray = models . filter ( ( model ) => model . id !== id ) ; onUpdate ( newArray ) ; } , [ models , onUpdate ] ) ; return ( < > { models . map ( ( model , arrayIndex ) => ( < Fragment key = { model . id } > < NumberRow isInvalid = { showValidation ? model . isInvalid : false } disableDelete = { models . length === 1 } model = { model } labelledbyId = { labelledbyId } range = { numberRange } onDelete = { onDelete } onChange = { onChangeValue } onBlur = { setTouched } autoFocus = { models . length !== 1 && arrayIndex === models . length - 1 } / > { showValidation && model . isInvalid && model . error && ( < EuiFormErrorText > { model . error } < /EuiFormErrorText>)} { models . length - 1 !== arrayIndex && < EuiSpacer size = "s" />} < /Fragment>))} < EuiSpacer size = "s" / > < EuiFlexItem > < EuiButtonEmpty iconType = "plusInCircleFilled" onClick = { onAdd } size = "xs" > < FormattedMessage id = "visDefaultEditor.controls.numberList.addUnitButtonLabel" defaultMessage = "Add {unitName}" values = { { unitName } } / > < /EuiButtonEmpty> < /EuiFlexItem> < />); } export { NumberList } ;