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    
ui-component-library / stories / molecules / SelectDropDown.story.tsx
Size: Mime:
import React from 'react'
// import { cloneJSON } from 'chain-able-boost'
import { observable, action } from 'xmobx/mobx'
import { observer } from 'xmobx/mobx-react'
import { storiesOf } from '@storybook/react'
import { OnSelectChange, SelectProps } from 'molecules/SelectDropDown'
import {
  SelectDropDown,
  Option,
  ActiveOption,
  Select,
  ActiveOptionProps,
  OptionType,
  OptionLabelValueType,
} from 'molecules/SelectDropDown'
import {
  SelectionState,
} from 'src/state/SelectionState'

const cloneJSON = x => JSON.parse(JSON.stringify(x || {}))
const list = [
  {
    label: 'Apple',
    value: 'apple',
    isSelected: false,
  },
  {
    label: 'Orange',
    value: 'orange',
    isSelected: false,
  },
  {
    label: 'Mango',
    value: 'mango',
    isSelected: false,

    isDisabled: true,
  },
  {
    // for hidden - or isDisabled works for this if we filter
    isVisible: false,

    // isSelected
    // isDisabled

    label: 'Watermelon',
    value: 'watermelon',
    isSelected: false,
  },
]

const handleDropDownChange = () => {
  console.info('[Story/SelectDropdown] handleDropdownChange() called')
}

// @todo renderProp & radioGroup example
storiesOf('molecules/SelectDropDown', module)
  .add('list', () => <SelectDropDown options={list} />)
  .add('renderProp', () => {
    const renderList = (props: SelectProps, state: SelectionState) => {
      return <span>eh</span>
    }
    return <SelectDropDown label="eh" renderList={renderList} options={list} />
  })
  .add('custom ActiveOption', () => {
    const renderActiveItem = (props: ActiveOptionProps) => (
      <ActiveOption {...props} label="color" />
    )
    return (
      <SelectDropDown
        name="noname"
        renderActiveItem={renderActiveItem}
        options={list}
      />
    )
  })
  .add('dropdown issue on rendering top and button view together', () => {
    const state = new SelectionState()
    const listJustInCaseOtherStory = cloneJSON(list)
    state.decorateWithProps({ list: listJustInCaseOtherStory })


    /**
     * if `forwardRef` we can check if click includes EITHER dom
     */

    return (
      <React.Fragment>

        <SelectDropDown
          onClickOutside={() => { }}
          state={state}
          options={listJustInCaseOtherStory}
          onChange={handleDropDownChange}
        />
        <SelectDropDown
          onClickOutside={() => { }}
          state={state}
          options={listJustInCaseOtherStory}
          onChange={handleDropDownChange}
          shouldBeAbsolute={true}
          dropDownAlignmentType={'top'}
        />
      </React.Fragment>
    )
  })
  // .add('dropdown issue on rendering top and button view together', () => {
  //   const list1 = cloneJSON(list)
  //   const state = new SelectionState()
  //   state.decorateWithProps({ list })
  //   const list2 = cloneJSON(list)
  //   const state2 = new SelectionState()
  //   state2.decorateWithProps({ list: list2 })
  //   return (
  //     <React.Fragment>
  //       <SelectDropDown state={state} options={list2} onChange={handleDropDownChange} />
  //       <SelectDropDown
  //         state={state2}
  //         options={list2}
  //         onChange={handleDropDownChange}
  //         shouldBeAbsolute={true}
  //         dropDownAlignmentType={'top'}
  //       />
  //     </React.Fragment>
  //   )
  // })
  // .add('dropdown issue on rendering top and button view together', () => {
  //   const list1 = cloneJSON(list)
  //   const list2 = cloneJSON(list)
  //   return (
  //     <React.Fragment>
  //       <SelectDropDown options={list} onChange={handleDropDownChange} />
  //       <SelectDropDown
  //         options={list2}
  //         onChange={handleDropDownChange}
  //         shouldBeAbsolute={true}
  //         dropDownAlignmentType={'top'}
  //       />
  //     </React.Fragment>
  //   )
  // })
  // .add('dropdown issue on rendering top and button view together', () => {
  //   const state = new SelectionState()
  //   // we could check
  //   // 1. the current scroll
  //   // 2. the distance to the bottom / left / right / top of the page
  //   // 3. according to scroll position, update the styles
  //   class SelectDropDownResponsive extends React.PureComponent {
  //     render() {
  //       const view = <SelectDropDown state={state} options={list} onChange={handleDropDownChange} />
  //       return view
  //     }
  //   }
  //   const view = <SelectDropDownResponsive />
  //   return (
  //     <React.Fragment>
  //       {view}
  //       {view}
  //     </React.Fragment>
  //   )
  // })
  .add('Absolute Dropdown', () => {
    const renderActiveItem = (props: ActiveOptionProps) => (
      <ActiveOption {...props} label="color" />
    )
    return (
      <SelectDropDown
        name="noname"
        renderActiveItem={renderActiveItem}
        options={list}
        shouldBeAbsolute={true}
      />
    )
  })
  .add('Top Alignment Dropdown', () => {
    const renderActiveItem = (props: ActiveOptionProps) => (
      <ActiveOption {...props} label="color" />
    )
    return (
      <SelectDropDown
        name="noname"
        renderActiveItem={renderActiveItem}
        options={list}
        dropDownAlignmentType="top"
      />
    )
  })
  .add('Top Alignment Dropdown with Absolute', () => {
    const renderActiveItem = (props: ActiveOptionProps) => (
      <ActiveOption {...props} label="color" />
    )
    return (
      <SelectDropDown
        name="noname"
        renderActiveItem={renderActiveItem}
        options={list}
        shouldBeAbsolute={true}
        dropDownAlignmentType="top"
      />
    )
  })
  .add('isDisabled', () => {
    return <SelectDropDown isDisabled={true} label={'eh'} list={[]} />
  })
  // @todo styled.withComponent
  .add('with color', () => {
    const colorList = [
      {
        label: 'Blue',
        value: 'blue',
        image: 'https://eh.com',
        title: 'blues clues',
        type: 'color',
        name: 'color',
      },
      {
        label: 'Green',
        value: 'green',
        image: 'https://green.com',
        title: 'greens clues',
        type: 'color',
        name: 'color',
      },
    ]
    return <SelectDropDown name="colored" options={colorList} />
  })
  // .add('renderEmpty', () => {
  //   return '@todo'
  //   // @todo
  //   // if (list.length === 0) {
  //   //   return renderEmpty(this.props, this.state)
  //   // }
  // })
  // .add('RadioGroup', () => {
  //   // const renderStoreLocatorFilter = (props, state) => {
  //   //   return props.list.map(renderStoreLocatorItem)
  //   // }
  //   // <SelectDropDropDown renderList={renderStoreLocatorFilter} />
  // })
  .add('events', () => {
    const onSelectChange: OnSelectChange = (
      value,
      props: SelectProps,
      state: SelectionState
    ) => {
      console.log('onSelectChange', value)
      console.dir({ props, state })
    }
    return (
      <SelectDropDown
        name="eh"
        onSelectChange={onSelectChange}
        options={list}
      />
    )
  })
  .add('SIMPLE MagicLabel option label', () => {
    const MagicLabelActiveOption = styled.withComponent(ActiveOption) `
      transition: color .5s cubic-bezier(0.075, 0.82, 0.165, 1);

      ${props =>
        props.isVisible &&
        props.isMagicLabel &&
        styled.css `
          color: grey;
        `};

      ${props =>
        !props.isVisible &&
        props.isMagicLabel &&
        styled.css `
          color: red;
        `};
    `

    class MagicSelect extends React.Component {
      static defaultProps = {
        label: 'Magic',
      }

      render() {
        const renderActiveItem = (props: ActiveOptionProps, state) => {
          const attributes = { ...props }
          console.log('[SelectDropDown]', props)
          // example: you have "Color", until you pick one (like "Blue")
          if (!props.label) {
            attributes.label = this.props.label
          }
          // example: you expand "Blue" => "Color" (since "Blue" is an option)
          if (state.isVisible) {
            attributes.label = this.props.label
            // then we could do
            // some extra styles when it's open and we show a label
            attributes.isVisible = state.isVisible
            attributes.isMagicLabel = true
          }

          return <MagicLabelActiveOption {...attributes} />
        }

        return (
          <SelectDropDown renderActiveItem={renderActiveItem} options={list} />
        )
      }
    }

    return <MagicSelect label="@todo: Fix when auto selected" />
  })
  .add('reproducing updating props', () => {
    /**
     * @note - if these are not observable
     *         it always will reset when we make
     *         this.list = [one, two, three, four]
     */
    const one = observable({
      label: 'eh',
      value: 'eh',
      isDisabled: false,
      isSelected: true,
    })
    const two = observable({
      label: 'moose',
      value: 'moose',
      isDisabled: false,
      isSelected: false,
    })
    const three = observable({
      label: 'beaver',
      value: 'beaver',
      isDisabled: false,
      isSelected: false,
    })

    /**
     * @note - in this example, notice the 4th item isn't even added
     *       ^ now is fixed with componentWillReact
     */
    const four = observable({
      label: 'igloo',
      value: 'igloo',
      isDisabled: false,
      isSelected: false,
    })

    class OneProduct {
      // @note - when it is observable, it accurately reproduces
      @observable list = [one, two, three]
      // @note - reproducing it not being observable...
      // when it is not obsrvable, adding an item only makes the last itejm added (after clicking) not update
      // list = [one, two, three]

      // for making sure NonUpdatingSelectDropDownProductOptions updates
      @observable index: number = 0

      @action
      selectSku(value: OptionLabelValueType): void {
        console.debug('[SelectDropDownStory] selectSku')
        console.log(value)

        // @note - this isn't reflected
        // disable
        this.list[0].isDisabled = true

        // making a new list each time
        this.index += 1

        // could add/remove or enable/disable
        // based on options
        // for full reproducing
        this.list = [one, two, three, four]
        // if (this.list.length === 3) {
        //   this.list.push(four)
        // }
      }
    }

    const state = new OneProduct()

    @observer
    class NonUpdatingSelectDropDownProductOptions extends React.Component {
      handleOnChange(event: Event, item: OptionType, selectState: SelectionState) {
        console.debug('[SelectDropDownStory] handleOnChange')
        state.selectSku(item.value)
      }

      render() {
        // triggering index, if list isn't observable
        console.debug('[SelectDropDownStory] render: ' + state.index)
        // dir doesn't trigger until it's expanded
        console.dir({ list: state.list, index: state.index })
        return <SelectDropDown list={state.list} onChange={this.handleOnChange} />
      }
    }

    return <NonUpdatingSelectDropDownProductOptions />
  })
// .add('OVERCOMPLICATED NOT WORKING MagicLabel option label', () => {
//   /**
//    * 1. by default, this magic label isSelected - so it shows
//    * 2. when we expand, we take it out of the array
//    */
//   const magicLabelItem = {
//     label: 'Fruit',
//     value: 'fruit',
//     isSelected: true,
//   }
//   const magicList = [
//     magicLabelItem,
//     {
//       label: 'Apple',
//       value: 'apple',
//       isSelected: false,
//     },
//     {
//       label: 'Orange',
//       value: 'orange',
//       isSelected: false,
//     },
//   ].map(toCommonState)
//   @observer
//   class MagicLabel extends React.Component {
//     render() {
//       const onSelectChange: OnSelectChange = (
//         value,
//         props: SelectProps,
//         state: SelectableState
//       ) => {
//         console.debug('[SelectDropDown_Story] onSelectChange')
//         console.dir({ props, state, value })
//       }
//       // @note - this probably would need to be called onChange
//       // event
//       const onClickActiveOption = (activeOptionProps, activeState) => {
//         console.debug('[SelectDropDown_Story] onClickActiveOption')
//         console.dir(activeOptionProps)
//         // is hidden, and after calling original click handler, isVisible = true
//         if (activeState.isVisible === false) {
//           // then we want to do the pop shift stuff
//         } else {
//           // would mean we closed it
//           return
//         }
//         // could also be done with isVisible & isSelected
//         if (magicList.length === 3) {
//           // if we have 3, remove the first one
//           magicList.shift()
//         } else {
//           // otherwise, add to the begining
//           magicList.unshift(magicLabelItem)
//         }
//       }
//       const attributes = {
//         renderActiveItem: undefined,
//         // onSelectChange,
//         // onChange: onSelectChange,
//         list: magicList,
//       }
//       /**
//        * @note - we also could handle this in the active item
//        */
//       attributes.renderActiveItem = (activeProps: OptionType, activeState: SelectableState) => {
//         const onClick = event => {
//           // so this is called before
//           onClickActiveOption(activeProps, activeState)
//           // this will make it visible...
//           activeProps.onClick(activeProps, activeState)
//         }
//         return <ActiveOption {...activeProps} onClick={onClick} state={activeState} />
//       }
//       return (
//         <SelectDropDown {...attributes} />
//       )
//     }
//   }
//   return <MagicLabel />
// // })
// .add('Option', () => <Option />)
// .add('Select', () => <Select />)