mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-03-01 22:10:27 +00:00
232 lines
5.6 KiB
TypeScript
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,
|
|
},
|
|
};
|
|
}
|