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/state / src / common.ts
Size: Mime:
/**
 * @todo we will want to finish this
 * @todo @file simplify
 */
/**
 * @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 { observable, action } from 'xmobx/mobx'
import { CommonPropsArgType, CommonStateOptionsType, CommonStateType, CommonStateInnerType } from './typings'

// @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 DEFAULT_COMMON_PROPS = Object.freeze({
  isVisible: false,

  isSelected: false,
  isDisabled: false,

  isActive: false,
  isFocused: false,
})

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

/**
 * @todo generics for better typings
 */
function toCommonState(
  props: CommonPropsArgType = DEFAULT_COMMON_PROPS,
  options: CommonStateOptionsType = DEFAULT_COMMON_OPTION
): CommonStateType {
  // @todo needs conditionals in here
  // allow passing in props.state
  const state: CommonStateType =
    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,
    }) as any

  /**
   * should never be used...
   */
  if (Object.isExtensible(state) === false) {
    console.warn('@fixme')
    return state
  }

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

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

  // @todo - pass name
  const setForDefault = (name: keyof CommonStateType, value?: unknown) => (overrideValue?: unknown) => {
    set(name, value)
  }
  const setFor = (name: keyof CommonStateType) => {
    const setFunction = (value: unknown) => {
      set(name, value)
    }
    return action(name, setFunction)
  }
  const toggleFor = (name: keyof CommonStateType) => (event?: unknown) => {
    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.setIsVisible = 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
  }

  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 { DEFAULT_COMMON_PROPS }
export { DEFAULT_COMMON_OPTION }
export { toCommonState }