Repository URL to install this package:
|
Version:
0.14.1 ▾
|
/* eslint-disable brace-style */
import toClassName from 'classnames'
import {
isObj,
isFunction,
Serializable,
EMPTY_OBJ,
isArray,
} from 'exotic'
import { InputState } from '../input/InputState'
import { GetInputValueType, InputStateComposedType } from '../input/typings'
import { KeyValueSpreadType, FormState } from './typings'
import { classes } from './fixture'
/**
* === added these 4 fns to split out serializing ===
*/
export function toSerialized(serializable: Serializable): string {
return serializable.toJSON
? serializable.toJSON()
: JSON.stringify(serializable)
}
export function fromInputToSpread(inputData: Serializable): KeyValueSpreadType {
const keyArray = Object.keys(inputData)
const key = keyArray[0]
const value = inputData[key]
return { value, key }
}
export function fromInputToSerializable(
input: InputStateComposedType,
getInputValue: GetInputValueType
) {
if (input.type === 'groupElements') {
return input.elementList.slice(0).map(getInputValue)
} else {
return input
}
}
/**
* we pass getInputValue here because it's used as a recursive tail call
* @see http://2ality.com/2015/06/tail-call-optimization.html
*/
export function fromInputToSerializedKeyValue(
input: InputStateComposedType,
getInputValue: GetInputValueType
) {
const serializable = fromInputToSerializable(input, getInputValue)
const inputData = toSerialized(serializable)
return fromInputToSpread(inputData)
}
/**
* @todo - this should be InputState.from
* @description ensure the value is coerced to inputstate
*/
export function toInputState(input: InputStateComposedType, index?: number) {
// console.log('formstate input', input)
if (input.type === 'groupElements') {
input.elementList = input.elementList.map(toInputState)
}
// already something that extends input state
if (isFunction(input.setValue)) {
return input
} else {
return InputState.init(input)
}
}
/**
* @todo split
* @param {ObserverForm} instance
*/
export function toClassList(instance) {
const {
formClassName,
// @deprecated
SubmitCustomClass,
CancelCustomClass,
ButtonGroupCustomClass,
// cache stringified
cachedClassList,
} = instance
const customClasslist = instance.classList || EMPTY_OBJ
const custom = {
form: formClassName,
buttonGroup: customClasslist.buttonClass || ButtonGroupCustomClass,
submitButton: customClasslist.submitButton || SubmitCustomClass,
cancelButton: customClasslist.cancelButton || CancelCustomClass,
}
if (JSON.stringify(custom) === JSON.stringify(cachedClassList)) {
return cachedClassList
}
const classList = {
/**
* classNames
* @todo - variable names are camelCase...
*/
// form: [classes.form, custom.form],
form: toClassName(classes.form, custom.form),
/**
* is usually Blue
* there is no need for custom classname
* use scoped styles
*/
// submitButton: [classes.submitButton, custom.submitButton],
submitButton: toClassName(classes.submitButton, custom.submitButton),
/**
* is usually GhostButton or BlueButton.grey
*/
// cancelButton: [classes.cancelButton, custom.cancelButton],
cancelButton: toClassName(classes.cancelButton, custom.cancelButton),
/**
* meh
*/
// buttonGroup: [classes.buttonGroup, custom.buttonGroup],
buttonGroup: toClassName(classes.buttonGroup, custom.buttonGroup),
}
instance.cachedClassList = classList
return classList
}
/**
* @example
* <label for='eh'>
* <?img /> to show an image instead of the input for custom styles
* <input id='eh'/>
* <span|div> children|text
* </label>
*/
export const isInputState = input => isObj(input) && isFunction(input.setValue)
export function handleRecursive(state: FormState, index: number) {
const input = state.inputsList[index]
const { elementList } = input
if (isArray(elementList) === false) {
return
}
const toChild = (nested, nestedIndex) => {
const nestedState = toInputStateAt(input, nestedIndex)
// just metadata, can remove
// nestedState.parent = input
// nestedState.form = state
return nestedState
}
// for toInputStateAt...
input.inputsList = input.elementList
input.elementList = input.elementList.map(toChild)
input.elementList = input.inputsList
delete input.inputsList
}
export function toInputStateAt(
state: FormState,
index: number
): InputStateComposedType {
// annoyingly named
const inputsList = state.inputsList
const initialState = inputsList[index]
// !!!! THIS IS THE ISSUE
// initialState && initialState instanceof InputState
const isAlreadyState = isInputState(initialState)
// for sanity
if (isAlreadyState === true) {
return initialState
}
// should call action...
if (isAlreadyState === false) {
// could pass in form as a parent (, state)
state.inputsList[index] = new InputState(initialState)
handleRecursive(state, index)
}
const instantiated = inputsList[index]
return instantiated
}