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:
// @todo - final todo will be remove the atoms/Radio
/* eslint-disable brace-style */
import React from 'react'
import { isFunction, isObj, hasOwnProp } from 'exotic'
import { observable } from 'xmobx/mobx'
import { observer } from 'xmobx/mobx-react'
import { withConsumer } from 'uxui-modules/view-container'
import { makeCommonState } from 'src/state/common'
// we know this works on it's own
// we don't need it in the same file
// we know it's safe, has no side-effects
import { toIsSelected } from './deps'
import { ToggleProps as Props, ToggleState as State } from './typings'

// if context isn't given, this can be used
// we can also separate the data being given from the class
// we can also swap contexts for compatible interfaces
//
// now we have a clear indication about our end API
// that we are opinionated about
// meaning, we only allow... 1 way.
//
// @see /ProductIconButtons/ProductCompareIcon.js:81
// ^ is always working because it doesn't use this crap :(
const RenderContext = React.createContext({
  // === html/static ===
  // could go in `meta` or `dynamicState`
  // sick of so many props
  // index: '',

  identifier: '',

  // === core ===

  // can do much better handling of this here
  isSelected: false,
  // children, or text
  text: 'eh',

  // === events ===

  onChange(DEFAULT) {
    //
  },

  // === renderers ===

  renderLabel() {
    //
  },
  // state: makeCommonState(),
})

const { Provider, Consumer } = RenderContext

// can use state.isSelected = boxed()
@observer
class ToggleProvider extends React.Component<Props, State> {
  // !!! => when we use this, the data is passed always with state
  // cannot configure props, because they loose reference
  // but can pass in initial state value of isSelected
  // can also pass in state
  // @example $r.contextProps.state.isSelected = true
  //
  // now we can statefully handle, configurably

  // !! should use those defaultProps get state


  state = makeCommonState(this.props)

  // something similar is needed
  // _setSelected(isSelected: boolean): void {
  //   // also has `select`
  //   if (isFunction(this.props.state.setSelected) === true) {
  //     this.props.state.setSelected(!isSelected)
  //   } else {
  //     this.props.state.isSelected = isSelected
  //   }
  // }

  // ============ render =========
  // @todo - move setRenderIcon here
  // ============ handlers =========

  // @todo !!! handle only 1 standard fn here
  handleChange = event => {
    console.log('[Toggle] handleChange')

    event.preventDefault()
    event.stopPropagation()

    const { onClick, label } = this.props

    if (
      isObj(this.state) &&
      isFunction(this.state.toggleSelected) === true
    ) {
      // common state
      this.state.toggleSelected()
    }

    if (isFunction(onClick)) {
      onClick(this.props)
    }

  }

  render() {
    const context = {
      ...this.props,
      // for now, lower priority than attributes, will take out
      ...this.htmlAttributes,
      ...this.attributes,
      state: this.state,
    }

    // console.log('CONTEXT_________')
    // console.log({ context })

    return <Provider value={context}>{this.props.children}</Provider>
  }

  // ============ computing =========
  // ============ ^v these can go in deps too, like state/transform ======
  // then we can reuse them, and keep them all simple & reusable
  //
  // the core fundemental (of FOOP/Functional-Object-Oriented-Programming)
  // 1. lots of small functions, with no mutation, reusable
  // 2. classes to define what they DO with the combination of those funcs

  // @todo
  // need to get rid of this - is only used in 2 components, not helpful to have here

  /**
   * @todo
   */
  get htmlAttributes() {
    const {
      label,
      labelText,
      index,
      identifier,
      isSelected,
      value,
      name,
      // note, we are using attributes, which is the COMPUTED PROPS!!
    } = this.attributes

    // @TODO aria-controls?
    const attributes = {
      // see this one doesn't matter at all for this level, no remapping is being done
      // it's just USING our isSelected
      // 'aria-checked': isSelected,

      // accessed on higher-level component
      // tabindex: "0"

      // props
      index,

      // required on radio, optional checkbox,
      // but if part of a group this prop makes sense
      name: name || identifier,

      // react
      id: identifier,

      // see this is why we don't need to do DOM factory in context
      // just data remap to standard consumable names
      // otherwise, the dom factories can't just spread this so
      text: value || label || labelText || name || identifier,
      value: value || name || identifier,
      // 'defaultChecked': isSelected,
    }
    return attributes
  }

  /**
   * @todo !!! needs typings
   */
  get attributes() {
    // NOW WE ONLY CHANGE THIS 1X EVER
    const isSelected = toIsSelected(this)

    // here... we take all the props, n change them :3
    // because changing them in 3-5 places is what caused any issues at all
    const {
      // no need for this
      state,

      // metadata
      index,
      identifier,
      // these ones are DEADLY
      name,
      label,
      labelText,
      text,
      // ===
      // 2nd thing we can break is this one
      // we know it's only used 1x (refine - the most important)
      // ===
      // secondaryText / extraText
      // additionalMessage: string,
      // label
      // filterLabel: string,
      // dynamicState: obj,
      // count: number,

      // !!!
      value,
      // isChecked,

      // === customization
      // first thing we can break are these, they don't matter
      // classes,
      // classList,
      // shouldAlignRight,
      // === functionality
      onClick,
      // onChange,
      // onToggle,

      // may pass in type=, like you did
      // ideally, we don't pass this in at all, but meh
      isRadio,
      isCheckbox,
      // isColor,
      type,
    } = this.props

    // finish this one
    const attributes = {
      isRadio: isRadio || type === 'radio',
      isCheckbox: isCheckbox || type === 'checkbox',
      // isColor: isColor || type === 'color',
      // only input
      // isNumber: isNumber || type === 'number'
      // onChange,
      onClick,
      isSelected,
      identifier,
      name,
      index,
      value,
      label,
      // shouldAlignRight,
    }
    return attributes
  }
}

// just simple, optional, an idea
Consumer.connect = withConsumer(Consumer)

export {
  withConsumer,
  Consumer,
  // wrong provider
  // Provider,
  ToggleProvider,
  ToggleProvider as Provider,
}