feat: implement FormStack and FormControl

This commit is contained in:
xzdry 2022-03-02 13:14:04 +08:00
parent bb6aba3f83
commit 1a4cd734b9
7 changed files with 286 additions and 2 deletions

View File

@ -0,0 +1,15 @@
import { Typography } from '@arco-design/web-react';
const DragComponentTips: React.FC<{ componentName: string }> = ({ componentName }) => {
return (
<Typography.Paragraph style={{ color: '#b2b2b2' }}>
Please drag{' '}
<Typography.Text bold style={{ color: '#777' }}>
{componentName}
</Typography.Text>{' '}
components here
</Typography.Paragraph>
);
};
export { DragComponentTips };

View File

@ -0,0 +1,79 @@
import { Form as BaseForm } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent } from '@sunmao-ui/runtime';
import { css } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../../sunmao-helper';
import { FormPropsSchema as BaseFormPropsSchema } from '../../generated/types/Form';
import { DragComponentTips } from './DragComponentTips';
const FormPropsSchema = Type.Object(BaseFormPropsSchema);
const FormStateSchema = Type.Object({});
const FormImpl: ComponentImpl<Static<typeof FormPropsSchema>> = props => {
const { childrenLayout, bordered, ...cProps } = getComponentProps(props);
const { elementRef, customStyle, slotsElements } = props;
let formStyle;
if (cProps.layout === 'inline' && childrenLayout === 'vertical') {
formStyle = `
&& {
flex-direction: row;
flex-wrap: wrap;
}
&& > *{
margin:0 10px 10px 0;
display: block;
width: auto
}
`;
}
const borderStyle = css`
border: 1px solid #eee;
width: 100%;
height: 100%;
padding: 5px;
`;
return (
<div ref={elementRef} className={bordered ? borderStyle : ''}>
<BaseForm className={css(customStyle?.content, formStyle)} {...cProps}>
{slotsElements.content ? (
slotsElements.content
) : (
<DragComponentTips componentName="Form Control" />
)}
</BaseForm>
</div>
);
};
const exampleProperties: Static<typeof FormPropsSchema> = {
layout: 'horizontal',
size: 'default',
bordered: true,
labelAlign: 'left',
childrenLayout: 'horizontal',
};
const options = {
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: 'formStack',
displayName: 'Form Stack',
exampleProperties,
annotations: {
category: 'Display',
},
},
spec: {
properties: FormPropsSchema,
state: FormStateSchema,
methods: {},
slots: ['content'],
styleSlots: ['content'],
events: [],
},
};
export const Form = implementRuntimeComponent(options)(FormImpl);

View File

@ -0,0 +1,95 @@
import { Form } from '@arco-design/web-react';
import { ComponentImpl, implementRuntimeComponent, Text } from '@sunmao-ui/runtime';
import { css, cx } from '@emotion/css';
import { Type, Static } from '@sinclair/typebox';
import { FALLBACK_METADATA, getComponentProps } from '../../sunmao-helper';
import { FormControlPropsSchema as BaseFormControlPropsSchema } from '../../generated/types/Form';
import { DragComponentTips } from './DragComponentTips';
import { FormControlErrorMessage } from './FormControlErrorMessage';
const FormControlPropsSchema = Type.Object(BaseFormControlPropsSchema);
const BaseFormControl = Form.Item;
const FormControlImpl: ComponentImpl<Static<typeof FormControlPropsSchema>> = props => {
const { label, errorMsg, ...cProps } = getComponentProps(props);
const { elementRef, slotsElements, customStyle } = props;
if (!cProps.colon) {
Reflect.deleteProperty(cProps, 'colon');
}
if (cProps.labelAlign === 'unset') {
Reflect.deleteProperty(cProps, 'labelAlign');
}
const formControlProps = {
className: cx(
'sunmao-form-control-layout',
css`
${customStyle?.content}
svg {
display: inherit;
}
& * {
word-wrap: normal;
}
& label {
white-space: inherit !important;
}
`
),
};
return (
<BaseFormControl
label={<Text cssStyle="display:inline-block" value={label} />}
ref={elementRef}
{...formControlProps}
{...cProps}
labelAlign={cProps.labelAlign as any}
>
{slotsElements.content ? (
slotsElements.content
) : (
<DragComponentTips componentName="Form Control" />
)}
<FormControlErrorMessage errorMsg={errorMsg} />
</BaseFormControl>
);
};
const exampleProperties: Static<typeof FormControlPropsSchema> = {
label: {
format: 'md',
raw: '**label**',
},
required: false,
hidden: false,
extra: '',
errorMsg: '',
labelAlign: 'unset',
colon: false,
labelCol: { span: 5, offset: 0 },
wrapperCol: { span: 19, offset: 0 },
help: '',
};
export const FormControl = implementRuntimeComponent({
version: 'arco/v1',
metadata: {
...FALLBACK_METADATA,
name: 'formControl',
displayName: 'Form Control',
exampleProperties: exampleProperties,
annotations: {
category: 'Display',
},
},
spec: {
properties: FormControlPropsSchema,
state: Type.Object({}),
methods: {},
slots: ['content'],
styleSlots: ['content'],
events: [],
},
})(FormControlImpl);

View File

@ -0,0 +1,17 @@
import { css } from '@emotion/css';
const FormControlErrorMessage: React.FC<{ errorMsg: string }> = ({ errorMsg }) => {
return errorMsg ? (
<div
className={css`
color: rgb(245, 63, 63);
line-height: 20px;
min-height: 20px;
`}
>
{errorMsg}
</div>
) : null;
};
export { FormControlErrorMessage };

View File

@ -0,0 +1,73 @@
import { Type } from "@sinclair/typebox";
import { StringUnion } from '../../sunmao-helper';
import { PRESET_PROPERTY_CATEGORY } from '@sunmao-ui/editor'
import { TextPropertySchema } from "@sunmao-ui/runtime";
export const FormControlPropsSchema = {
label: TextPropertySchema,
required: Type.Boolean({
title: 'Required',
category: PRESET_PROPERTY_CATEGORY.Basic
}),
hidden: Type.Boolean({
title: 'Hidden',
category: PRESET_PROPERTY_CATEGORY.Basic
}),
extra: Type.String({
title: 'Extra',
category: PRESET_PROPERTY_CATEGORY.Basic
}),
errorMsg: Type.String({
title: 'Error Message',
category: PRESET_PROPERTY_CATEGORY.Basic
}),
help: Type.String({
title: 'Help Message',
category: PRESET_PROPERTY_CATEGORY.Basic
}),
labelAlign: StringUnion(['left', 'right', 'unset'], {
title: 'Label Align',
category: PRESET_PROPERTY_CATEGORY.Layout
}),
colon: Type.Boolean({
title: 'Colon',
category: PRESET_PROPERTY_CATEGORY.Style
}),
labelCol: Type.Object({
span: Type.Number(),
offset: Type.Number()
}, {
title: 'Label Col',
category: PRESET_PROPERTY_CATEGORY.Layout
}),
wrapperCol: Type.Object({
span: Type.Number(),
offset: Type.Number()
}, {
title: 'Wrapper Col',
category: PRESET_PROPERTY_CATEGORY.Layout
})
}
export const FormPropsSchema = {
layout: StringUnion(['horizontal', 'vertical', 'inline'], {
title: 'Layout',
category: PRESET_PROPERTY_CATEGORY.Layout
}),
childrenLayout: StringUnion(['vertical', 'horizontal'], {
title: 'Children Layout',
category: PRESET_PROPERTY_CATEGORY.Layout,
}),
labelAlign: StringUnion(['left', 'right'], {
title: 'Label Align',
category: PRESET_PROPERTY_CATEGORY.Layout
}),
size: StringUnion(['mini', 'small', 'default', 'large'], {
title: 'Size',
category: PRESET_PROPERTY_CATEGORY.Layout
}),
bordered: Type.Boolean({
title: 'Bordered',
category: PRESET_PROPERTY_CATEGORY.Layout
}),
};

View File

@ -34,6 +34,8 @@ import { Switch } from "./components/Switch";
import { PasswordInput } from "./components/PasswordInput";
import { TextArea } from "./components/TextArea";
import { Tabs } from "./components/Tabs";
import { Form } from "./components/Form/Form";
import { FormControl } from "./components/Form/FormControl";
type Component = Parameters<Registry["registerComponent"]>[0];
type Trait = Parameters<Registry["registerTrait"]>[0];
@ -74,7 +76,9 @@ export const components: Component[] = [
Switch,
PasswordInput,
TextArea,
Tabs
Tabs,
Form,
FormControl
];
export const traits: Trait[] = [];
export const modules: Module[] = [];

View File

@ -2,6 +2,7 @@ import { StrictMode } from 'react';
import ReactDOM from 'react-dom';
import { Registry } from '@sunmao-ui/runtime';
import { sunmaoChakraUILib } from '@sunmao-ui/chakra-ui-lib';
import { ArcoDesignLib } from '@sunmao-ui/arco-lib';
import { initSunmaoUIEditor } from './init';
import { LocalStorageManager } from './LocalStorageManager';
@ -14,7 +15,7 @@ type Options = Partial<{
const lsManager = new LocalStorageManager();
const { Editor, registry } = initSunmaoUIEditor({
libs: [sunmaoChakraUILib],
libs: [sunmaoChakraUILib, ArcoDesignLib],
storageHandler: {
onSaveApp(app) {
lsManager.saveAppInLS(app);