Repository URL to install this package:
|
Version:
0.14.1 ▾
|
// @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,
}