2020-05-04 14:54:05 +08:00

187 lines
4.8 KiB
TypeScript

import VariableSetter from './variableSetter';
import context from '../context';
import { VE_HOOKS } from '../base/const';
import {
AccordionField,
BlockField,
EntryField,
InlineField,
PlainField,
PopupField
} from "./fields";
import { ComponentClass, Component, isValidElement, createElement } from 'react';
import { createSetterContent, getSetter } from '@ali/lowcode-editor-core';
function isReactClass(obj: any): obj is ComponentClass<any> {
return (
obj &&
obj.prototype &&
(obj.prototype.isReactComponent || obj.prototype instanceof Component)
);
}
interface IExtraProps {
stageName?: string;
isGroup?: boolean;
isExpand?: boolean;
propName?: string;
toggleExpand?: () => any;
onExpandChange?: () => any;
}
const FIELD_TYPE_MAP: any = {
accordion: AccordionField,
block: BlockField,
entry: EntryField,
inline: InlineField,
plain: PlainField,
popup: PopupField,
tab: AccordionField
};
export class SettingField extends Component {
public readonly props: {
prop: any;
selected?: boolean;
forceDisplay?: string;
className?: string;
children?: JSX.Element | string;
compact?: boolean;
key?: string;
addonProps?: object;
};
/**
* VariableSetter placeholder
*/
public variableSetter: any;
constructor(props: any) {
super(props);
this.variableSetter = getSetter('VariableSetter')?.component || VariableSetter;
}
public render() {
const { prop, selected, addonProps } = this.props;
const display = this.props.forceDisplay || prop.getDisplay();
if (display === "none") {
return null;
}
// 标准的属性,即每一个 Field 在 VE 下都拥有的属性
const standardProps = {
className: this.props.className,
compact: this.props.compact,
isSupportMultiSetter: this.supportMultiSetter(),
isSupportVariable: prop.isSupportVariable(),
isUseVariable: prop.isUseVariable(),
prop,
setUseVariable: () => prop.setUseVariable(!prop.isUseVariable()),
tip: prop.getTip(),
title: prop.getTitle()
};
// 部分 Field 所需要的额外 fieldProps
const extraProps = {};
const ctx = context;
const plugin = ctx.getPlugin(VE_HOOKS.VE_SETTING_FIELD_PROVIDER);
let Field;
if (typeof plugin === "function") {
Field = plugin(display, FIELD_TYPE_MAP, prop);
}
if (!Field) {
Field = FIELD_TYPE_MAP[display] || PlainField;
}
this._prepareProps(display, extraProps);
if (display === "entry") {
return <Field {...{ ...standardProps, ...extraProps }} />;
}
let setter;
const props: any = {
prop,
selected,
};
const fieldProps = { ...standardProps, ...extraProps };
if (prop.isUseVariable() && !this.variableSetter.isPopup) {
props.placeholder = "请输入表达式: ${var}";
props.key = `${prop.getId()}-variable`;
setter = createElement(this.variableSetter, props);
return <Field {...fieldProps}>{setter}</Field>;
}
// for composited prop
if (prop.getVisibleItems) {
setter = prop
.getVisibleItems()
.map((item: any) => (
<SettingField {...{ key: item.getId(), prop: item, selected }} />
));
return <Field {...fieldProps}>{setter}</Field>;
}
setter = prop.getSetter();
if (
typeof setter === "object" &&
"componentName" in setter &&
!(isValidElement(setter) || isReactClass(setter))
) {
const { componentName: setterType, props: setterProps } = setter as any;
setter = createSetterContent(setterType, {
...addonProps,
...setterProps,
...props
});
} else {
setter = createSetterContent(setter, {
...addonProps,
...props
});
}
return <Field {...fieldProps}>{setter}</Field>;
}
private supportMultiSetter() {
const { prop } = this.props;
const setter = prop && prop.getConfig && prop.getConfig("setter");
return prop.isSupportVariable() || Array.isArray(setter);
}
private _prepareProps(displayType: string, extraProps: IExtraProps): void {
const { prop } = this.props;
extraProps.propName = prop.isGroup()
? "组合属性,无属性名称"
: prop.getName();
switch (displayType) {
case "title":
break;
case "block":
Object.assign(extraProps, { isGroup: prop.isGroup() });
break;
case "accordion":
Object.assign(extraProps, {
headDIY: true,
isExpand: prop.isExpand(),
isGroup: prop.isGroup(),
onExpandChange: () => prop.onExpandChange(() => this.forceUpdate()),
toggleExpand: () => {
prop.toggleExpand();
}
});
break;
case "entry":
Object.assign(extraProps, { stageName: prop.getName() });
break;
default:
break;
}
}
}