Repository URL to install this package:
|
Version:
3.5.8 ▾
|
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>
)
}
}