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/forms / src / new-forms / inputs / ObserverInput.tsx
Size: Mime:
import * as React from 'react'
import { FocusEvent, ChangeEvent, StatelessComponent } from 'react'
import { observer } from 'xmobx/mobx-react'
import { ValidationStrategyContext, ValidationStrategy } from '../strategies'
import {
  defaultRender,
  defaultRenderWrap,
  defaultRenderLabelText,
  defaultRenderError,
  defaultRenderAfterInput,
} from './renderProps'
import { InputProps, ObserverInputProps, InputRenderProps } from './typings'
import { Provider } from './InputContext'
import { fromPropsToInputState } from './deps'

/**
 * @thought
 *       observable stuff here should be probably in the render of plugin
 * @thought
 *       we *may* want to support `onChange` here
 *       but probably best to allow *only 1 way* (using state)
 */
@observer
export class ObserverInput<
  Props extends ObserverInputProps = ObserverInputProps
> extends React.Component<Props> {
  static contextType = ValidationStrategyContext
  static defaultProps = {
    renderInput: defaultRender,
    renderWrap: defaultRenderWrap,
    renderLabelText: defaultRenderLabelText,
    renderAfterInput: defaultRenderAfterInput,
    renderError: defaultRenderError,
  }
  context: ValidationStrategy
  observableState = fromPropsToInputState(this.props)

  handleChange = (event: ChangeEvent<any>) => {
    this.observableState.setValue(event.target.value)
    this.context.onChange({ state: this.observableState, event })
  }
  handleOnFocus = (event: FocusEvent<any>) => {
    this.observableState.setIsActive(true)
    this.context.onFocus({ state: this.observableState, event })
  }
  handleOnBlur = (event: FocusEvent<any>) => {
    this.observableState.setIsActive(false)
    this.context.onBlur({ state: this.observableState, event })
  }

  render() {
    const props = this.props as InputProps
    const {
      renderAfterInput,
      renderError,
      renderLabelText,
      renderWrap,
      renderInput,
      state,
      ...remainingProps
    } = props
    const {
      type,
      value,
      label,
      // identifier,
      // isActive,
      // isValid,
      onChange,
      onFocus,
      onBlur,
      ...strippedRemainingProps
    } = remainingProps
    /**
     * @todo we could probably get rid of most of this if we use context
     *      ^ ONLY THING TO NOTE IS PROPS VS STATE
     */
    const renderInputProps = {
      // @note !!! unsure whether props should override, or state !!!
      // ^ for 1 story when debugging at least making props override...
      // ...remainingProps,

      // @note - changed this to explicitly spread, but allow `attributes` spreading
      // ...this.observableState,
      // @note - not needed
      // validator: this.observableState.validator,
      // formState: this.observableState.formState,
      // propertyName: this.observableState.propertyName,

      ...this.observableState.attributes,

      identifier: this.observableState.identifier,
      type: type || this.observableState.type,
      value: this.observableState.value as string | number,
      label: this.observableState.label || label,

      state: this.observableState,
      isDisabled: this.observableState.isDisabled,
      isDirty: this.observableState.isDirty,
      isActive: this.observableState.isActive,
      isValid: this.observableState.isValid,
      onChange: this.handleChange,
      onFocus: this.handleOnFocus,
      onBlur: this.handleOnBlur,

      // @note changed this to avoid any confusion
      ...strippedRemainingProps,
    }

    const Wrap = renderWrap as StatelessComponent
    // @note was remainingProps
    const renderPropProps = { state, ...renderInputProps } as InputRenderProps

    return (
      <Provider value={this.observableState}>
        <Wrap {...remainingProps}>
          {renderLabelText(renderPropProps)}
          {renderInput(renderInputProps as InputRenderProps)}
          {renderAfterInput(renderPropProps)}
          {renderError(renderPropProps)}
        </Wrap>
      </Provider>
    )
  }
}