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 / src / state / common.ts
Size: Mime:
/**
 * @file @todo convert to composable pieces
 * @file @todo all setter methods/fns use actions
 * @file @todo remove extra compat naming - pick 1
 * @file @todo would be nice to change most things into Map syntax instead...
 */
import { observer } from 'xmobx/mobx-react'
import { observable, decorate, action } from 'xmobx/mobx'
import decorateAllStatics from 'uxui-modules/observable-utils/deps/decorateHoistAllStatics'
import { Class } from 'typings/generic'
import { CommonState } from './typings'

// todo - types for faster popups
// const viewState = {}

export interface CommonPropsArg {
  isDefaultSelected?: boolean
  isSelected?: boolean
  isDisabled?: boolean
  isVisible?: boolean
  isActive?: boolean
  isFocused?: boolean

  state?: CommonState
  [key: string]: any
}
export interface CommonStateOptions {
  select?: boolean
  visible?: boolean
  active?: boolean
  focus?: boolean
  value?: boolean
  label?: boolean
}

// @see examples/reference
// here we make good use of the opposite
// - we want to lose the reference here for not-shared scoped optimized defaults
const defaultProps = {
  isVisible: false,

  isSelected: false,
  isDisabled: false,

  isActive: false,
  isFocused: false,
}

const defaultOptions = {
  select: true,
  visible: true,
  active: true,
  focus: true,
  value: true,
  label: true,
}
Object.freeze(defaultOptions)

// eslint-disable-next-line
function commonStateFactory(
  props: CommonPropsArg = defaultProps,
  options: CommonStateOptions = defaultOptions
): CommonState {
  // @todo needs conditionals in here
  // allow passing in props.state
  const commonState =
    props.state ||
    observable({
      isSelected: !!props.isSelected || !!props.isDefaultSelected,
      isDisabled: !!props.isDisabled,

      isVisible: !!props.isVisible,
      isActive: !!props.isActive,
      isFocused: !!props.isFocused,

      value: props.value || undefined,
      label: props.label || undefined,
      isDate: props.isDate || undefined,
    })
  const state = commonState

  if (Object.isExtensible(commonState) === false) {
    console.warn('@fixme')
    return state
  }

  const set = action((name, value = true) => {
    // console.dev('UPDATING_COMMON_STATE', { [name]: value })
    state[name] = value
  })

  const toggle = action(name => {
    state[name] = !state[name]
  })
  // curried set, toggle
  // const setFor = name => value => set(name, value)

  // @todo - pass name
  const setForDefault = (name, value) => overrideValue => {
    set(name, value)
  }
  const setFor = (name: string) => {
    const setFunction = value => {
      set(name, value)
    }
    return action(name, setFunction)
  }
  const toggleFor = name => event => {
    toggle(name)
  }

  // state.alias = (names, fn) => {
  //   names.forEach(name => {
  //     state[name] = fn
  //   })
  // }

  if (options.select) {
    // onSelected, onSelect
    // select, setSelected, handleSelect
    const select = setForDefault('isSelected', true)
    state.select = select
    state.setSelected = select
    state.handleSelect = select

    const unselect = setForDefault('isSelected', false)
    state.unselect = unselect
    state.handleUnSelect = unselect

    const toggleSelected = toggleFor('isSelected')
    state.toggleSelected = toggleSelected
    state.handleToggleSelected = toggleSelected
  }

  if (options.visible) {
    // setOpen handleShow setVisible handleOpen, onVisible
    const setVisible = setForDefault('isVisible', true)
    state.setOpen = setVisible
    // state.setVisible = setVisible
    state.handleShow = setVisible
    state.handleOpen = setVisible
    state.show = setVisible

    const toggleVisibility = toggleFor('isVisible')
    state.handleToggleVisibility = toggleVisibility
    state.toggleVisibility = toggleVisibility
    // was just using .isVisible o.o?
    // isClosed
    // const hide = state.setFor('isClosed')

    // onHide
    // setClosed, handleHide, setInvisible
    const hide = setForDefault('isVisible', false)
    state.setClosed = hide
    state.handleHide = hide
    state.hide = hide

    // @todo!
    // state.setIsVisible = action(value => set('isVisible', value))
    // state.setIsVisible = setFor('isVisible')

    // state.setInvisible = hide
  }

  if (options.active) {
    // setActive - like touch / pressed?
    // setActive activate handleActive
    const active = setForDefault('isActive', true)
    state.setActive = active
    state.activate = active
    state.handleActive = active

    const inactive = setForDefault('isActive', false)
    state.setInactive = inactive
    state.deactivate = inactive
    state.handleInactive = inactive

    const toggleActive = toggleFor('isActive')
    state.handleToggleActive = toggleActive
    state.toggleActive = toggleActive
  }

  if (options.focus) {
    // onFocus
    // setFocused, handleFocus, focus
    const focus = setForDefault('isFocused', true)
    state.handleFocus = focus
    state.setFocused = focus
    state.focus = focus

    // handleBlur, unfocus, blur
    const blur = setForDefault('isFocused', false)
    state.handleBlur = blur
    // state.unfocus = blur
    state.blur = blur
  }

  if (options.value) {
    const value = setForDefault('value', '@@empty')
    state.setValue = value
  }
  if (options.label) {
    const label = setForDefault('label', '@@empty')
    state.setLabel = label
  }

  state.toggle = toggle
  state.set = set

  return state
}

export { observer }
export { commonStateFactory as commonState }
export { commonStateFactory }
export { commonStateFactory as makeState }
export { commonStateFactory as makeCommonState }
export { commonStateFactory as toCommonState }
export default commonStateFactory