UNPKG

mobx-react-form

Version:
202 lines (171 loc) 5.8 kB
import _ from "lodash"; import { ObservableMap, values as mobxValues, keys as mobxKeys } from "mobx"; import { FieldInterface } from "./models/FieldInterface"; import { AllowedFieldPropsTypes, FieldPropsEnum, FieldPropsOccurrence } from "./models/FieldProps"; import { props } from "./props"; const getObservableMapValues = (observableMap: ObservableMap): ReadonlyArray<FieldInterface> => mobxValues(observableMap); const getObservableMapKeys = (observableMap: ObservableMap): ReadonlyArray<FieldInterface> => mobxKeys(observableMap); const checkObserveItem = (change: any) => ({ key, to, type, exec }: any) => change.type === type && change.name === key && change.newValue === to && exec.apply(change, [change]); const checkObserve = (collection: object[]) => (change: any) => collection.map(checkObserveItem(change)); const checkPropOccurrence = ({ type, data }: any): boolean => { let $check: any; switch (type) { case FieldPropsOccurrence.some: $check = ($data: object) => _.some($data, Boolean); break; case FieldPropsOccurrence.every: $check = ($data: object) => _.every($data, Boolean); break; default: throw new Error('Occurrence not found for specified prop'); } return $check(data); }; const hasProps = ($type: string, $data: any): boolean => { let $props; switch ($type) { case AllowedFieldPropsTypes.computed: $props = props.computed; break; case AllowedFieldPropsTypes.observable: $props = [ FieldPropsEnum.fields, ...props.computed, ...props.editable, ]; break; case AllowedFieldPropsTypes.editable: $props = [ ...props.editable, ...props.validation, ...props.functions, ...props.handlers, ]; break; case AllowedFieldPropsTypes.all: $props = [ FieldPropsEnum.id, FieldPropsEnum.key, FieldPropsEnum.name, FieldPropsEnum.path, ...props.computed, ...props.editable, ...props.validation, ...props.functions, ...props.handlers, ]; break; default: $props = null; } return _.intersection($data, $props).length > 0; }; /** Check Allowed Properties */ const allowedProps = (type: string, data: string[]): void => { if (hasProps(type, data)) return; const $msg = "The selected property is not allowed"; throw new Error(`${$msg} (${JSON.stringify(data)})`); }; /** Throw Error if undefined Fields */ const throwError = (path: string, fields: any, msg: null | string = null): void => { if (!_.isNil(fields)) return; const $msg = _.isNil(msg) ? "The selected field is not defined" : msg; throw new Error(`${$msg} (${path})`); }; const pathToStruct = (path: string): string => { let struct; struct = _.replace(path, new RegExp("[.]\\d+($|.)", "g"), "[]."); struct = _.replace(struct, "..", "."); struct = _.trim(struct, "."); return struct; }; const isArrayFromStruct = (struct: string[], structPath: string): boolean => { if (isArrayOfStrings(struct)) return !!struct .filter((s) => s.startsWith(structPath)) .find((s) => s.substring(structPath.length) === "[]") || _.endsWith(struct?.find((e) => e === structPath), '[]'); else return false; }; const hasSome = (obj: any, keys: any): boolean => _.some(keys, _.partial(_.has, obj)); const isEmptyArray = (field: any): boolean => _.isEmpty(field) && Array.isArray(field); const isArrayOfStrings = (struct: any): boolean => Array.isArray(struct) && _.every(struct, _.isString); const isArrayOfObjects = (fields: any): boolean => Array.isArray(fields) && _.every(fields, _.isPlainObject); const getKeys = (fields: any) => _.union(..._.map(_.values(fields), (values) => _.keys(values))); const hasUnifiedProps = ({ fields }: any) => !isArrayOfStrings({ fields }) && hasProps(AllowedFieldPropsTypes.editable, getKeys(fields)); const hasSeparatedProps = (initial: any): boolean => hasSome(initial, props.separated) || hasSome(initial, props.validation); const allowNested = (field: any, strictProps: boolean): boolean => _.isObject(field) && !_.isDate(field) && !_.has(field, FieldPropsEnum.fields) && !_.has(field, FieldPropsEnum.class) && (!hasSome(field, [ ...props.editable, ...props.handlers, ...props.validation, ...props.functions, ]) || strictProps); const parseIntKeys = (fields: any) => _.map(getObservableMapKeys(fields), _.ary(_.toNumber, 1)); const hasIntKeys = (fields: any): boolean => _.every(parseIntKeys(fields), _.isInteger); const maxKey = (fields: any): number => { const max = _.max(parseIntKeys(fields)); return _.isUndefined(max) ? 0 : max + 1; }; const uniqueId = (field: any): string => _.uniqueId([_.replace(field.path, new RegExp("\\.", "g"), "-"), "--"].join("")); const isEvent = (obj: any): boolean => { if (_.isNil(obj) || typeof Event === "undefined") return false; return obj instanceof Event || !_.isNil(obj.target); }; const hasFiles = ($: any): boolean => $.target.files && $.target.files.length !== 0; const isBool = ($: any, val: any): boolean => _.isBoolean(val) && _.isBoolean($.target.checked); const $try = (...args: any) => { let found: any | null | undefined = undefined; args.map(( val: any ) => found === undefined && !_.isUndefined(val) && (found = val)); return found; }; export { props, checkObserve, checkPropOccurrence, hasProps, allowedProps, throwError, isArrayOfStrings, isEmptyArray, isArrayOfObjects, pathToStruct, isArrayFromStruct, hasUnifiedProps, hasSeparatedProps, allowNested, parseIntKeys, hasIntKeys, maxKey, uniqueId, isEvent, hasFiles, isBool, $try, getObservableMapKeys, getObservableMapValues, };