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 { EMPTY_ARRAY, isFunction } from 'exotic'
import {
  SelectionState,
  SelectableItemOnClick,
  SelectableItem,
  SelectableState,
  isEveryItemInListDecoratedWithOnClick,
} from 'src/state/SelectionState'
import { OptionType } from '../typings'
import { toList, toOnChange } from '../meta/_deps'
import { Option, renderItem as defaultRenderItem } from '../Option'
import {
  ActiveOption,
  renderActiveItem as defaultRenderActive,
} from '../ActiveOption'
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,
  }

  observableState = new SelectionState()

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


    if (isFunction(this.props.onChange)) {
      console.info('[adm:Select] onChange passed in')
      this.props.onChange(event, item, state)
    } else {
      console.warn('[adm:Select] had no onChangeProp')
    }

    this.observableState.setIsVisible(false)
  }
  private handleDecoratingList() {
    const onChange = this.handleChange
    const props = { ...this.props, onChange }
    console.debug('[Select] handleDecoratingList()')
    console.dir(props)
    this.observableState.decorateWithProps(props)
  }

  // maybe should be didMount?
  componentWillMount() {
    this.handleDecoratingList()
  }
  componentWillReact() {
    if (isEveryItemInListDecoratedWithOnClick(this.props) === false) {
      this.handleDecoratingList()
    }
  }

  render() {
    // computed & stateful
    const { props, observableState } = this
    const list = toList(props)
    const { isVisible, handleToggleVisibility } = observableState
    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 = () => observableState.setIsVisible(false),
      renderList,
      renderActiveItem,
      isDisabled,
      className,
      shouldBeAbsolute,
      dropDownAlignmentType,
    } = props

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

    // @todo improve, add to typings
    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,
    }

    const activeView = renderActiveItem(activeProps, observableState)

    // @todo TOO MANY PROPS PASSING THROUGH FOR LAYOUT
    // THIS IS WHY WE HAVE PRESETS
    const optionListView = (
      <StyledOptionList
        list={list}
        children={listView}
        isVisible={isVisible}
        shouldBeAbsolute={shouldBeAbsolute}
        dropDownAlignmentType={dropDownAlignmentType}
      />
    )

    // @todo - WHAT IS THIS?!!?!?!?!?!!?!? THIS IS A PRESET MOVE IT OUT
    // we can also EASILY style this
    const renderDropDownList = (item: string) => {
      switch (item) {
        case 'top':
          return (
            <React.Fragment>
              {optionListView}
              {activeView}
            </React.Fragment>
          )
        case 'bottom':
        default:
          return (
            <React.Fragment>
              {activeView}
              {optionListView}
            </React.Fragment>
          )
      }
    }

    return (
      <SelectBoundary
        className={className}
        onClickOutside={onClickOutside}
        isDisabled={isDisabled}
        isVisible={isVisible}
      >
        {renderDropDownList(dropDownAlignmentType)}
      </SelectBoundary>
    )
  }
}

export { Select }
export default Select