Merge pull request #167 from webzard-io/editor-ex

introduce widgets and impl module widget
This commit is contained in:
tanbowensg 2021-12-15 16:20:17 +08:00 committed by GitHub
commit 5b7b21655b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 128 additions and 10 deletions

View File

@ -134,6 +134,7 @@ export const ComponentForm: React.FC<Props> = observer(props => {
})
);
}}
registry={registry}
/>
</VStack>
</VStack>

View File

@ -16,7 +16,7 @@ function swap<T>(arr: Array<T>, i1: number, i2: number): Array<T> {
}
const ArrayField: React.FC<Props> = props => {
const { schema, formData, onChange } = props;
const { schema, formData, onChange, registry } = props;
const subSchema = Array.isArray(schema.items) ? schema.items[0] : schema.items;
if (typeof subSchema === 'boolean' || !subSchema) {
return null;
@ -81,6 +81,7 @@ const ArrayField: React.FC<Props> = props => {
newFormData[idx] = value;
onChange(newFormData);
}}
registry={registry}
/>
</Box>
);

View File

@ -8,7 +8,7 @@ type Props = FieldProps;
const _Field: React.FC<
Omit<Props, 'schema'> & { schemas: NonNullable<FieldProps['schema']['anyOf']> }
> = props => {
const { schemas, formData, onChange } = props;
const { schemas, formData, onChange, registry } = props;
const [schemaIdx, setSchemaIdx] = useState(0);
const subSchema = schemas[schemaIdx];
@ -37,20 +37,35 @@ const _Field: React.FC<
label={subSchema.title || ''}
formData={formData}
onChange={value => onChange(value)}
registry={registry}
/>
</Box>
);
};
const MultiSchemaField: React.FC<Props> = props => {
const { schema, formData, onChange } = props;
const { schema, formData, onChange, registry } = props;
if (schema.anyOf) {
return <_Field formData={formData} onChange={onChange} schemas={schema.anyOf} />;
return (
<_Field
formData={formData}
onChange={onChange}
schemas={schema.anyOf}
registry={registry}
/>
);
}
if (schema.oneOf) {
return <_Field formData={formData} onChange={onChange} schemas={schema.oneOf} />;
return (
<_Field
formData={formData}
onChange={onChange}
schemas={schema.oneOf}
registry={registry}
/>
);
}
return null;

View File

@ -5,7 +5,7 @@ import { FieldProps } from './fields';
type Props = FieldProps;
const ObjectField: React.FC<Props> = props => {
const { schema, formData, onChange } = props;
const { schema, formData, onChange, registry } = props;
const properties = Object.keys(schema.properties || {});
return (
@ -27,6 +27,7 @@ const ObjectField: React.FC<Props> = props => {
[name]: value,
})
}
registry={registry}
/>
);
})}

View File

@ -8,6 +8,7 @@ import {
} from '@chakra-ui/react';
import { isEmpty } from 'lodash-es';
import { FieldProps, getDisplayLabel } from './fields';
import { widgets } from './widgets/widgets';
import StringField from './StringField';
import ObjectField from './ObjectField';
import ArrayField from './ArrayField';
@ -64,7 +65,7 @@ type Props = FieldProps & {
};
const SchemaField: React.FC<Props> = props => {
const { schema, label, formData, onChange } = props;
const { schema, label, formData, onChange, registry } = props;
if (isEmpty(schema)) {
return null;
@ -72,7 +73,12 @@ const SchemaField: React.FC<Props> = props => {
let Component = UnsupportedField;
if (schema.type === 'object') {
// customize widgets
if (schema.widget && widgets[schema.widget]) {
Component = widgets[schema.widget];
}
// type fields
else if (schema.type === 'object') {
Component = ObjectField;
} else if (schema.type === 'string') {
Component = StringField;
@ -94,7 +100,12 @@ const SchemaField: React.FC<Props> = props => {
return (
<DefaultTemplate label={label} displayLabel={displayLabel}>
<Component schema={schema} formData={formData} onChange={onChange} />
<Component
schema={schema}
formData={formData}
onChange={onChange}
registry={registry}
/>
</DefaultTemplate>
);
};

View File

@ -1,9 +1,14 @@
import { Component } from '@sunmao-ui/core';
import { Registry } from '@sunmao-ui/runtime';
type Schema = Component['spec']['properties'];
type EditorSchema = {
widget?: string;
};
export type FieldProps = {
schema: Schema;
schema: Schema & EditorSchema;
registry: Registry;
formData: any;
onChange: (v: any) => void;
};

View File

@ -0,0 +1,78 @@
import { Box, FormControl, FormLabel, Select } from '@chakra-ui/react';
import React, { useMemo } from 'react';
import { FieldProps } from '../fields';
import SchemaField from '../SchemaField';
type Props = FieldProps;
const ModuleWidget: React.FC<Props> = props => {
const { formData, onChange, schema, registry } = props;
const moduleTypes = useMemo(() => {
const res: string[] = [];
for (const version of registry.modules.keys()) {
for (const name of registry.modules.get(version)!.keys()) {
res.push(`${version}/${name}`);
}
}
return res;
}, [registry]);
const module = useMemo(() => {
if (!formData?.type) {
return null;
}
return registry.getModuleByType(formData.type);
}, [formData]);
return (
<Box p="2" border="1px solid" borderColor="gray.200" borderRadius="4">
<SchemaField
schema={schema.properties!.id! as FieldProps['schema']}
registry={registry}
label="Module ID"
formData={formData?.id}
onChange={v =>
onChange({
...formData,
id: v,
})
}
/>
<FormControl id="type">
<FormLabel>Module Type</FormLabel>
<Select
placeholder="select module"
value={formData?.type}
onChange={evt =>
onChange({
...formData,
type: evt.currentTarget.value,
})
}
>
{moduleTypes.map(type => (
<option key={type}>{type}</option>
))}
</Select>
</FormControl>
{module !== null && (
<SchemaField
schema={{
...module.spec.properties,
title: 'Module Properties',
}}
registry={registry}
label="Module Properties"
formData={formData?.properties}
onChange={v =>
onChange({
...formData,
properties: v,
})
}
/>
)}
</Box>
);
};
export default ModuleWidget;

View File

@ -0,0 +1,6 @@
import { FieldProps } from '../fields';
import ModuleWidget from './ModuleWidget';
export const widgets: Record<string, React.FC<FieldProps>> = {
module: ModuleWidget,
};