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    
Size: Mime:
import React from 'react'
import { observer } from 'xmobx/mobx-react'
import { isFunction } from 'exotic'
import {
  SelectionState,
  SelectableItemOnClick,
  SelectableItem,
  SelectableState,
  isEveryItemInListDecoratedWithOnClick,
} from 'src/state/SelectionState'
import { toList } from '../meta/_deps'
import { renderItem as defaultRenderItem } from '../Option'
import { renderActiveItem as defaultRenderActive } from '../ActiveOption/_circularRenderProp'
import { StyledOptionList } from './styled'
import { SelectBoundary } from './SelectBoundary'
import { SelectProps } from './typings'
import { renderList as defaultRenderList } from './renderProps'

@observer
class Select extends React.Component<SelectProps> {
  static defaultProps = {
    renderList: defaultRenderList,
    renderItem: defaultRenderItem,
    renderActiveItem: defaultRenderActive,
    shouldBeAbsolute: false,
    dropDownAlignmentType: false,
  }

  /**
   * @todo could make this a normal prop
   */
  observableState = new SelectionState()

  protected handleChange: SelectableItemOnClick = (
    event: Event,
    item: SelectableItem,
    state: SelectableState
  ): void => {
    console.debug('[adm:Select] handleChange()')
    this.observableState.handleToggleVisibility()
    // this.observableState.setIsVisible(false)

    if (isFunction(this.props.onChange)) {
      console.info('[adm:Select] onChange passed in')
      /**
       * @todo should be this.props.onChange({event, item, state})
       */
      this.props.onChange(event, item, state)
    } else {
      console.warn('[adm:Select] had no onChangeProp')
    }
  }
  protected handleDecoratingList() {
    const onChange = this.handleChange
    const props = { ...this.props, onChange }

    console.debug('[Select] handleDecoratingList()')
    console.dir(props)

    this.observableState.decorateWithProps(props)
  }

  /**
   * @todo this code makes no sense
   *  - after setting isVisible to false, onBlur never calls
   */
  protected handleClickOutside = () => {
    const { onBlur } = this.props
    if (this.observableState.isVisible) {
      this.observableState.setIsVisible(false)
      if (isFunction(onBlur)) {
        onBlur()
      }
    }
  }

  /**
   * @todo this area is probably the confusing part
   *       perhaps we separate the state decorating out of here
   */
  componentWillMount() {
    this.handleDecoratingList()
  }
  componentWillReact() {
    if (isEveryItemInListDecoratedWithOnClick(this.props) === false) {
      this.handleDecoratingList()
    }
  }

  render() {
    // computed & stateful
    const { props, observableState } = this
    /**
     * @todo for perf & simplicity, change to props.list
     */
    const list = toList(props)
    const { isVisible, handleToggleVisibility } = observableState
    const { onBlur, onFocus } = props
    const {
      /**
       * @see https://www.typescriptlang.org/play/#src=const%20obj%20%3D%20%7B%7D%0D%0Aconst%20%7B%0D%0A%20%20defaulted%20%3D%20()%20%3D%3E%20'eh'%2C%0D%0A%7D%20%3D%20obj
       * @description inline `hide`
       * @todo probably should make a function that is the default for this
       *       and pass in props + observable state
       */
      onClickOutside = this.handleClickOutside,
      renderList,
      renderActiveItem,
      isDisabled,
      className,
      shouldBeAbsolute,
      dropDownAlignmentType,
    } = props

    /**
     * @todo !!! this is probably where we have issues, log here
     */
    const activeProps = {
      /**
       * @nagavelli
       * - props needed here since overwriiten function should be supported
       *
       * @james ^
       * - why do we spread observable state?
       * 1. this is error prone
       * 2. we already pass in state
       */
      ...observableState.selectedItem,
      ...props,
      ...observableState,
      onClick: handleToggleVisibility,
    }

    if (isFunction(onFocus) && isVisible) {
      onFocus()
    }

    const listView = renderList({ ...this.props, list }, this.observableState)
    const activeView = renderActiveItem(activeProps, observableState)

    const optionListView = (
      <StyledOptionList
        list={list}
        children={listView}
        isVisible={isVisible}
        shouldBeAbsolute={shouldBeAbsolute}
        dropDownAlignmentType={dropDownAlignmentType}
      />
    )

    return (
      <SelectBoundary
        className={className}
        onClickOutside={onClickOutside}
        isDisabled={isDisabled}
        isVisible={isVisible}
        data-qa={this.props['data-qa']}
      >
        {activeView}
        {optionListView}
      </SelectBoundary>
    )
  }
}

export { Select }
export default Select