Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
@skava/forms / src / new-forms / plugins / SelectDropDownPlugin.tsx
Size: Mime:
import * as React from 'react'
import { isFunction } from 'exotic'
import { Text, Empty } from '@skava/ui'
import { SelectDropDown, SelectProps } from '@skava/ui'
import { computed } from 'xmobx/mobx'
import { styled } from 'styleh-components'
import { observer } from 'xmobx/mobx-react'
import { isValidSelect } from '../../validators'
import { InputProps, InputState } from '../inputs'

// @todo !!!
const StyledErrorMessage = Text
const StyledLabel = Text
const StyledWrapper = styled.label ``

const renderErrorMessage = (props: { errorText: string; isValid: boolean }) => {
  if (props.isValid) {
    return <Empty key="textbox-error-message" />
  } else {
    return (
      <StyledErrorMessage
        key="textbox-error-message"
        content={props.errorText}
        className={'input-error-message'}
      />
    )
  }
}
const renderLabel = (props: { labelText: string }) => {
  return <StyledLabel className={'label-text'} content={props.labelText} />
}
const renderSelectDropDown = (props: SelectProps) => {
  return <SelectDropDown {...props} />
}

export type SelectDropDownPluginProps = InputProps & React.HTMLAttributes<HTMLSelectElement> & ({ attributes: SelectProps } | SelectProps)

@observer
class SelectDropDownPlugin extends React.Component<SelectDropDownPluginProps> {
  static isSatisfiedByProps(props: { type: string }): boolean {
    return props.type === 'select'
  }
  static defaultState = (inputState: InputState) => {
    return {
      validate: isValidSelect,
    }
  }

  @computed
  get isValid() {
    const options = this.props.state.attributes.options
    const selectedValue = this.props.state.value
    const hasSelected = options.some(item => selectedValue === item.value)
    return hasSelected
  }
  /**
   * @todo !!! these 3 are good examples of why we need validation strategy
   */
  handleChange = (args: string) => {
    this.props.state.setValue(args)
    const isValid = this.props.state.validator(args)
    this.props.state.setIsValid(isValid)
  }
  handleBlur = () => {
    const value = this.props.state.value
    const isValid = this.isValid
      ? this.props.state.validator(value)
      : this.props.state.validator()
    this.props.state.setIsValid(isValid)
  }
  handleFocus = () => {
    // this.props.state.setIsValid(true)
  }

  render() {
    const {
      // remove label keep labelText?
      label,
      labelText = this.props.state.attributes.labelText,

      // remove
      // wrapperClassName,

      // should name this properly
      options = this.props.state.attributes.options,

      // should not support classNames in form config...
      className,

      // remove
      dataQa,

      // removing state
      // state,

      ...remainingProps
    } = this.props

    // remove state right now...
    const { state } = remainingProps

    const view = (
      <StyledWrapper className={className}>
        {renderLabel({
          labelText,
        })}
        {renderSelectDropDown({
          list: options!,
          options: options!,

          onChange: this.handleChange,
          onBlur: this.handleBlur,
          // onFocus: this.handleFocus,

          // aria
          'aria-invalid': state.isValid === false,
          // should not need this
          'data-qa': dataQa,
          // this will override the ^ props
          // and is probably why we named it `onDropDownChange`
          ...remainingProps,
        })}
        {renderErrorMessage({
          isValid: state.isValid,
          errorText: state.attributes.errorText,
        })}
      </StyledWrapper>
    )

    // can do renderWrap here if needed
    return view
  }
}

export { SelectDropDownPlugin }
export default SelectDropDownPlugin