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/ui / src / components / features / Debug / index.ts
Size: Mime:
/**
 * @see https://codesandbox.io/s/ppw027o70 (.map example)
 * @see https://codesandbox.io/s/m33vrr37r8 (this code in this file)
 */
import React from 'react'
import { isObservable, observable } from 'xmobx/mobx'
import { ReactChild, ReactElement, Ref } from 'react'
import { isString, isNumber, isObj } from 'exotic'

type ObservableDebugItem = {
  component: ReactElement<any> | any
  state: any
}
type Scoped = {
  ref: Ref<any> | ReactElement<any>
  // setRef(ref: Ref<any>): void
}

const observableList: ObservableDebugItem[] = []
window.observableList = observableList

const fromComponentToPropsThatPickupObservablesAndRef = (
  component: ReactElement<any>
) => {
  // scope this so we can lazily get the ref
  const scoped: Scoped = {
    ref: component,
  }

  // @note it's frozen
  const props = {
    ...component.props,
    /**
     * @see https://github.com/facebook/react/issues/8873#issuecomment-275423780
     */
    ref: (ref: any) => {
      scoped.ref = ref
    },
  }

  // find the observables, put them in the list
  Object.keys(props).forEach(key => {
    const value = props[key]
    if (isObj(value) && isObservable(value)) {
      const entry = {
        state: value,
        get component() {
          return scoped.ref
        },
      }
      observableList.push(entry)
    }
  })

  return props
}

const traverseChildren = (child: ReactChild) => {
  if (isString(child) || isNumber(child)) {
    return child
  }

  const props = fromComponentToPropsThatPickupObservablesAndRef(child)

  // traverse
  if (props.children) {
    props.children = traverseChildren(props.children)
  }

  return React.cloneElement(child, props)
}

/**
 * @example <Debug>{...anything}</Debug>
 */
class Debug extends React.Component {
  render() {
    const { children } = this.props
    return React.Children.map(children, traverseChildren)
  }
}

export { Debug }
export default Debug