formily/next/src/components/Field/preview.tsx (155 lines of code) (raw):

import React from 'react' import { FormPath } from '@formily/core' import { toJS } from '@formily/reactive' import { ArrayField, Field as InternalField, ObjectField, VoidField, observer, ISchema, Schema, } from '@formily/react' import { FormItem } from '@formily/next' import { each, reduce } from '@formily/shared' import { createBehavior } from '@designable/core' import { useDesigner, useTreeNode, useComponents, DnFC, } from '@designable/react' import { isArr, isStr } from '@designable/shared' import { Container } from '../../common/Container' import { AllLocales } from '../../locales' Schema.silent(true) const SchemaStateMap = { title: 'title', description: 'description', default: 'value', enum: 'dataSource', readOnly: 'readOnly', writeOnly: 'editable', required: 'required', 'x-content': 'content', 'x-value': 'value', 'x-editable': 'editable', 'x-disabled': 'disabled', 'x-read-pretty': 'readPretty', 'x-read-only': 'readOnly', 'x-visible': 'visible', 'x-hidden': 'hidden', 'x-display': 'display', 'x-pattern': 'pattern', } const NeedShownExpression = { title: true, description: true, default: true, 'x-content': true, 'x-value': true, } const isExpression = (val: any) => isStr(val) && /^\{\{.*\}\}$/.test(val) const filterExpression = (val: any) => { if (typeof val === 'object') { const isArray = isArr(val) const results = reduce( val, (buf: any, value, key) => { if (isExpression(value)) { return buf } else { const results = filterExpression(value) if (results === undefined || results === null) return buf if (isArray) { return buf.concat([results]) } buf[key] = results return buf } }, isArray ? [] : {} ) return results } if (isExpression(val)) { return } return val } const toDesignableFieldProps = ( schema: ISchema, components: any, nodeIdAttrName: string, id: string ) => { const results: any = {} each(SchemaStateMap, (fieldKey, schemaKey) => { const value = schema[schemaKey] if (isExpression(value)) { if (!NeedShownExpression[schemaKey]) return if (value) { results[fieldKey] = value return } } else if (value) { results[fieldKey] = filterExpression(value) } }) if (!components['FormItem']) { components['FormItem'] = FormItem } const decorator = schema['x-decorator'] && FormPath.getIn(components, schema['x-decorator']) const component = schema['x-component'] && FormPath.getIn(components, schema['x-component']) const decoratorProps = schema['x-decorator-props'] || {} const componentProps = schema['x-component-props'] || {} if (decorator) { results.decorator = [decorator, toJS(decoratorProps)] } if (component) { results.component = [component, toJS(componentProps)] } if (decorator) { FormPath.setIn(results['decorator'][1], nodeIdAttrName, id) } else if (component) { FormPath.setIn(results['component'][1], nodeIdAttrName, id) } results.title = results.title && ( <span data-content-editable="title">{results.title}</span> ) results.description = results.description && ( <span data-content-editable="description">{results.description}</span> ) return results } export const Field: DnFC<ISchema> = observer((props) => { const designer = useDesigner() const components = useComponents() const node = useTreeNode() if (!node) return null const fieldProps = toDesignableFieldProps( props, components, designer.props.nodeIdAttrName, node.id ) if (props.type === 'object') { return ( <Container> <ObjectField {...fieldProps} name={node.id}> {props.children} </ObjectField> </Container> ) } else if (props.type === 'array') { return <ArrayField {...fieldProps} name={node.id} /> } else if (node.props.type === 'void') { return ( <VoidField {...fieldProps} name={node.id}> {props.children} </VoidField> ) } return <InternalField {...fieldProps} name={node.id} /> }) Field.Behavior = createBehavior({ name: 'Field', selector: 'Field', designerLocales: AllLocales.Field, })