2020-06-12 11:08:22 +08:00

232 lines
5.6 KiB
TypeScript

import {
FieldConfig,
PropConfig,
PropType,
SetterType,
OneOf,
Shape,
ObjectOf,
ArrayOf,
TransformedComponentMetadata,
} from '@ali/lowcode-types';
function propConfigToFieldConfig(propConfig: PropConfig): FieldConfig {
const { name, description } = propConfig;
const title = {
label: {
type: 'i18n',
'en-US': name,
'zh-CN': description?.slice(0, 10) || name,
},
tip: description ? `${name} | ${description}` : undefined,
};
return {
title,
...propConfig,
setter: propTypeToSetter(propConfig.propType),
};
}
function propTypeToSetter(propType: PropType): SetterType {
let typeName: string;
let isRequired: boolean | undefined = false;
if (typeof propType === 'string') {
typeName = propType;
} else {
typeName = propType.type;
isRequired = propType.isRequired;
}
// TODO: use mixinSetter wrapper
switch (typeName) {
case 'string':
return {
componentName: 'StringSetter',
isRequired,
initialValue: '',
};
case 'number':
return {
componentName: 'NumberSetter',
isRequired,
initialValue: 0,
};
case 'bool':
return {
componentName: 'BoolSetter',
isRequired,
initialValue: false,
};
case 'oneOf':
const dataSource = ((propType as OneOf).value || []).map((value, index) => {
const t = typeof value;
return {
label: t === 'string' || t === 'number' || t === 'boolean' ? String(value) : `value ${index}`,
value,
};
});
const componentName = dataSource.length > 4 ? 'SelectSetter' : 'RadioGroupSetter';
return {
componentName,
props: { dataSource },
isRequired,
initialValue: dataSource[0] ? dataSource[0].value : null,
};
case 'element':
case 'node': // TODO: use Mixin
return {
// slotSetter
componentName: 'NodeSetter',
props: {
mode: typeName,
},
isRequired,
initialValue: {
type: 'JSSlot',
value: '',
},
};
case 'shape':
case 'exact':
const items = (propType as Shape).value.map((item) => propConfigToFieldConfig(item));
return {
componentName: 'ObjectSetter',
props: {
config: {
items,
extraSetter: typeName === 'shape' ? propTypeToSetter('any') : null,
},
},
isRequired,
initialValue: (field: any) => {
const data: any = {};
items.forEach((item) => {
let initial = item.defaultValue;
if (initial == null && item.setter && typeof item.setter === 'object') {
initial = (item.setter as any).initialValue;
}
data[item.name] = initial ? (typeof initial === 'function' ? initial(field) : initial) : null;
});
return data;
},
};
case 'object':
case 'objectOf':
return {
componentName: 'ObjectSetter',
props: {
config: {
extraSetter: propTypeToSetter(typeName === 'objectOf' ? (propType as ObjectOf).value : 'any'),
},
},
isRequired,
};
case 'array':
case 'arrayOf':
return {
componentName: 'ArraySetter',
props: {
itemSetter: propTypeToSetter(typeName === 'arrayOf' ? (propType as ArrayOf).value : 'any'),
},
isRequired,
initialValue: [],
};
case 'func':
return {
componentName: 'FunctionSetter',
isRequired,
initialValue: {
type: 'JSFunction',
value: 'function(){}',
},
};
case 'oneOfType':
return {
componentName: 'MixedSetter',
props: {
// TODO:
// setters: (propType as OneOfType).value.map(item => propTypeToSetter(item)),
},
isRequired,
};
}
return {
componentName: 'MixedSetter',
isRequired,
};
}
const EVENT_RE = /^on[A-Z][\w]*$/;
export default function(metadata: TransformedComponentMetadata): TransformedComponentMetadata {
const { configure } = metadata;
if (configure.props) {
return metadata;
}
if (!metadata.props) {
return {
...metadata,
configure: {
...configure,
props: [],
},
};
}
const { component = {}, supports = {} } = configure;
const supportedEvents: any[] | null = (supports as any).events ? null : [];
const props: FieldConfig[] = [];
metadata.props.forEach((prop) => {
const { name, propType, description } = prop;
if (
name === 'children' &&
(component.isContainer || propType === 'node' || propType === 'element' || propType === 'any')
) {
if (component.isContainer !== false) {
component.isContainer = true;
return;
}
}
if (EVENT_RE.test(name) && (propType === 'func' || propType === 'any')) {
if (supportedEvents) {
supportedEvents.push({
name,
description,
});
(supports as any).events = supportedEvents;
}
return;
}
if (name === 'className' && (propType === 'string' || propType === 'any')) {
if ((supports as any).className == null) {
(supports as any).className = true;
}
return;
}
if (name === 'style' && (propType === 'object' || propType === 'any')) {
if ((supports as any).style == null) {
(supports as any).style = true;
}
return;
}
props.push(propConfigToFieldConfig(prop));
});
return {
...metadata,
configure: {
...configure,
props,
supports,
component,
},
};
}