diff --git a/packages/client/src/schema-component/antd/grid/demos/demo2.tsx b/packages/client/src/schema-component/antd/grid/demos/demo2.tsx
new file mode 100644
index 000000000..99ec6eafa
--- /dev/null
+++ b/packages/client/src/schema-component/antd/grid/demos/demo2.tsx
@@ -0,0 +1,209 @@
+import { ISchema, observer, Schema, useFieldSchema } from '@formily/react';
+import { uid } from '@formily/shared';
+import {
+ Form,
+ FormItem,
+ Grid,
+ Input,
+ Markdown,
+ SchemaComponent,
+ SchemaComponentProvider,
+ SchemaInitializer,
+ useDesignable
+} from '@nocobase/client';
+import { Switch } from 'antd';
+import React from 'react';
+
+const schema: ISchema = {
+ type: 'void',
+ name: 'grid1',
+ 'x-decorator': 'Form',
+ 'x-component': 'Grid',
+ 'x-item-initializer': 'AddGridFormItem',
+ 'x-uid': uid(),
+ properties: {
+ row1: {
+ type: 'void',
+ 'x-component': 'Grid.Row',
+ 'x-uid': uid(),
+ properties: {
+ col11: {
+ type: 'void',
+ 'x-component': 'Grid.Col',
+ properties: {
+ name: {
+ type: 'string',
+ title: 'Name',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ 'x-collection-field': 'posts.name',
+ },
+ title: {
+ type: 'string',
+ title: 'Title',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ 'x-collection-field': 'posts.title',
+ },
+ },
+ },
+ col12: {
+ type: 'void',
+ 'x-component': 'Grid.Col',
+ properties: {
+ intro: {
+ type: 'string',
+ title: 'Intro',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+ },
+ },
+ },
+ },
+ },
+};
+
+const useFormItemInitializerFields = () => {
+ return [
+ {
+ key: 'name',
+ title: 'Name',
+ component: InitializeFormItem,
+ schema: {
+ type: 'string',
+ title: 'Name',
+ 'x-component': 'Input',
+ 'x-decorator': 'FormItem',
+ 'x-collection-field': 'posts.name',
+ },
+ },
+ {
+ key: 'title',
+ title: 'Title',
+ component: InitializeFormItem,
+ schema: {
+ type: 'string',
+ title: 'Title',
+ 'x-component': 'Input',
+ 'x-decorator': 'FormItem',
+ 'x-collection-field': 'posts.title',
+ },
+ },
+ ];
+};
+
+const gridRowColWrap = (schema: ISchema) => {
+ return {
+ type: 'void',
+ 'x-component': 'Grid.Row',
+ properties: {
+ [uid()]: {
+ type: 'void',
+ 'x-component': 'Grid.Col',
+ properties: {
+ [schema.name || uid()]: schema,
+ },
+ },
+ },
+ };
+};
+
+const AddGridFormItem = observer((props: any) => {
+ return (
+
+ Configure fields
+
+ );
+});
+
+const useCurrentFieldSchema = (path: string) => {
+ const fieldSchema = useFieldSchema();
+ const { remove } = useDesignable();
+ const findFieldSchema = (schema: Schema) => {
+ return schema.reduceProperties((buf, s) => {
+ if (s['x-collection-field'] === path) {
+ return s;
+ }
+ const child = findFieldSchema(s);
+ if (child) {
+ return child;
+ }
+ return buf;
+ });
+ };
+ const schema = findFieldSchema(fieldSchema);
+ return {
+ schema,
+ exists: !!schema,
+ remove() {
+ schema &&
+ remove(schema, {
+ removeEmptyParents: true,
+ });
+ },
+ };
+};
+
+const InitializeFormItem = (props) => {
+ const { title, schema, insert } = props;
+ const { exists, remove } = useCurrentFieldSchema(schema['x-collection-field']);
+ return (
+ {
+ if (exists) {
+ return remove();
+ }
+ insert({
+ ...schema,
+ });
+ }}
+ >
+
+ {title}
+
+
+ );
+};
+
+const InitializeTextFormItem = (props) => {
+ const { title, insert } = props;
+ return (
+ {
+ insert({
+ type: 'void',
+ 'x-component': 'Markdown.Void',
+ 'x-decorator': 'FormItem',
+ // 'x-editable': false,
+ });
+ }}
+ >
+ {title}
+
+ );
+};
+
+export default function App() {
+ return (
+
+
+
+ );
+}
diff --git a/packages/client/src/schema-component/antd/grid/demos/demo3.tsx b/packages/client/src/schema-component/antd/grid/demos/demo3.tsx
new file mode 100644
index 000000000..103140156
--- /dev/null
+++ b/packages/client/src/schema-component/antd/grid/demos/demo3.tsx
@@ -0,0 +1,149 @@
+import { FormOutlined, TableOutlined } from '@ant-design/icons';
+import { ISchema, observer } from '@formily/react';
+import { uid } from '@formily/shared';
+import {
+ CardItem,
+ Form,
+ Grid,
+ Markdown,
+ SchemaComponent,
+ SchemaComponentProvider,
+ SchemaInitializer,
+ VoidTable
+} from '@nocobase/client';
+import React from 'react';
+
+const schema: ISchema = {
+ type: 'void',
+ name: 'grid1',
+ 'x-component': 'Grid',
+ 'x-item-initializer': 'AddGridBlockItem',
+ 'x-uid': uid(),
+ properties: {
+ row1: {
+ type: 'void',
+ 'x-component': 'Grid.Row',
+ 'x-uid': uid(),
+ },
+ },
+};
+
+const gridRowColWrap = (schema: ISchema) => {
+ return {
+ type: 'void',
+ 'x-component': 'Grid.Row',
+ properties: {
+ [uid()]: {
+ type: 'void',
+ 'x-component': 'Grid.Col',
+ properties: {
+ [schema.name || uid()]: schema,
+ },
+ },
+ },
+ };
+};
+
+const AddGridBlockItem = observer((props: any) => {
+ return (
+
+ Add block
+
+ );
+});
+
+const TableBlockInitializerItem = (props) => {
+ const { insert } = props;
+ return (
+ }
+ onClick={(info) => {
+ insert({
+ type: 'void',
+ 'x-component': 'VoidTable',
+ 'x-decorator': 'CardItem',
+ });
+ }}
+ items={[
+ {
+ type: 'itemGroup',
+ title: 'select a data source',
+ children: [
+ {
+ key: 'users',
+ title: 'Users',
+ },
+ {
+ key: 'posts',
+ title: 'Posts',
+ },
+ ],
+ },
+ ]}
+ >
+ Table
+
+ );
+};
+
+const FormBlockInitializerItem = (props) => {
+ const { insert } = props;
+ return (
+ }
+ onClick={(info) => {
+ insert({
+ type: 'void',
+ 'x-component': 'Form',
+ 'x-decorator': 'CardItem',
+ });
+ }}
+ items={[
+ {
+ type: 'itemGroup',
+ title: 'select a data source',
+ children: [
+ {
+ key: 'users',
+ title: 'Users',
+ },
+ {
+ key: 'posts',
+ title: 'Posts',
+ },
+ ],
+ },
+ ]}
+ >
+ Form
+
+ );
+};
+
+export default function App() {
+ return (
+
+
+
+ );
+}
diff --git a/packages/client/src/schema-component/antd/grid/index.md b/packages/client/src/schema-component/antd/grid/index.md
index 0331d13ba..750ec3bd5 100644
--- a/packages/client/src/schema-component/antd/grid/index.md
+++ b/packages/client/src/schema-component/antd/grid/index.md
@@ -5,6 +5,10 @@ group:
path: /schema-components
---
-# Grid 待定
+# Grid
+
+
+
+
diff --git a/packages/client/src/schema-component/antd/grid/index.tsx b/packages/client/src/schema-component/antd/grid/index.tsx
index 4c4066023..107601a52 100644
--- a/packages/client/src/schema-component/antd/grid/index.tsx
+++ b/packages/client/src/schema-component/antd/grid/index.tsx
@@ -4,6 +4,7 @@ import { observer, RecursionField, Schema, useField, useFieldSchema } from '@for
import { uid } from '@formily/shared';
import cls from 'classnames';
import React, { useState } from 'react';
+import { useComponent } from '../..';
import { DndContext } from '../../common/dnd-context';
const ColDivider = (props) => {
@@ -65,6 +66,7 @@ const RowDivider = (props) => {
export const Grid: any = observer((props) => {
const field = useField();
const fieldSchema = useFieldSchema();
+ const ItemInitializer = useComponent(fieldSchema['x-item-initializer']);
const addr = field.address.toString();
const wrapSchema = (schema: Schema) => {
const row = new Schema({
@@ -97,6 +99,7 @@ export const Grid: any = observer((props) => {
);
})}
+
{ItemInitializer && }
);
});
diff --git a/packages/client/src/schema-initializer/demos/demo1.tsx b/packages/client/src/schema-initializer/demos/demo1.tsx
index a1e51c3fa..86a95390e 100644
--- a/packages/client/src/schema-initializer/demos/demo1.tsx
+++ b/packages/client/src/schema-initializer/demos/demo1.tsx
@@ -13,7 +13,7 @@ const Hello = observer((props) => {
);
});
-const InitializerButton = observer((props: any) => {
+const AddBlockButton = observer((props: any) => {
return (
schema}
@@ -34,7 +34,7 @@ const InitializerButton = observer((props: any) => {
},
]}
>
- Create block
+ Add block
);
});
@@ -94,7 +94,7 @@ const FormBlockInitializerItem = (props) => {
export default function App() {
return (
-
+
{
+const AddActionButton = observer((props: any) => {
return (
{
{
title: 'Create',
key: 'create',
- component: 'ActionInitializerItem',
+ component: InitializeAction,
schema: {
title: 'Create',
'x-action': 'posts:create',
@@ -36,7 +36,7 @@ const ActionInitializerButton = observer((props: any) => {
title: 'Update',
'x-action': 'posts:update',
},
- component: 'ActionInitializerItem',
+ component: InitializeAction,
},
],
},
@@ -65,7 +65,7 @@ const useCurrentActionSchema = (action: string) => {
};
};
-const ActionInitializerItem = (props) => {
+const InitializeAction = (props) => {
const { title, schema, insert } = props;
const { exists, remove } = useCurrentActionSchema(schema['x-action']);
return (
@@ -90,13 +90,13 @@ const ActionInitializerItem = (props) => {
export default function App() {
return (
-
+
diff --git a/packages/client/src/schema-initializer/demos/demo3.tsx b/packages/client/src/schema-initializer/demos/demo3.tsx
index fd89ecfa3..4e14ee1ee 100644
--- a/packages/client/src/schema-initializer/demos/demo3.tsx
+++ b/packages/client/src/schema-initializer/demos/demo3.tsx
@@ -16,7 +16,7 @@ const useFormItemInitializerFields = () => {
{
key: 'name',
title: 'Name',
- component: 'FormItemInitializer',
+ component: InitializeFormItem,
schema: {
type: 'string',
title: 'Name',
@@ -28,7 +28,7 @@ const useFormItemInitializerFields = () => {
{
key: 'title',
title: 'Title',
- component: 'FormItemInitializer',
+ component: InitializeFormItem,
schema: {
type: 'string',
title: 'Title',
@@ -40,7 +40,7 @@ const useFormItemInitializerFields = () => {
];
};
-const FormItemInitializerButton = observer((props: any) => {
+const AddFormItemButton = observer((props: any) => {
return (
schema}
@@ -55,7 +55,7 @@ const FormItemInitializerButton = observer((props: any) => {
},
{
title: 'Add text',
- component: 'AddTextFormItemInitializer',
+ component: InitializeTextFormItem,
},
]}
>
@@ -89,7 +89,7 @@ const useCurrentFieldSchema = (path: string) => {
};
};
-const FormItemInitializer = (props) => {
+const InitializeFormItem = (props) => {
const { title, schema, insert } = props;
const { exists, remove } = useCurrentFieldSchema(schema['x-collection-field']);
return (
@@ -110,7 +110,7 @@ const FormItemInitializer = (props) => {
);
};
-const AddTextFormItemInitializer = (props) => {
+const InitializeTextFormItem = (props) => {
const { title, insert } = props;
return (
{
return (
);
};
export default function App() {
return (
-
+
{
'x-collection-field': 'posts.name',
'x-component': 'Input',
},
- component: ColumnInitializer,
+ component: ColumnInitializerItem,
},
{
key: 'title',
@@ -32,13 +32,13 @@ const useTableColumnInitializerFields = () => {
'x-collection-field': 'posts.title',
'x-component': 'Input',
},
- component: ColumnInitializer,
+ component: ColumnInitializerItem,
},
];
return fields;
};
-export const InitializerButton = observer((props: any) => {
+export const AddTableColumn = observer((props: any) => {
return (
schema}
@@ -80,7 +80,7 @@ const useCurrentColumnSchema = (path: string) => {
};
};
-export const ColumnInitializer = (props) => {
+export const ColumnInitializerItem = (props) => {
const { title, schema, insert } = props;
const { exists, remove } = useCurrentColumnSchema(schema['x-collection-field']);
return (
@@ -120,7 +120,7 @@ const schema = {
{ id: 3, name: 'Name3' },
],
'x-component': 'ArrayTable',
- 'x-column-initializer': 'InitializerButton',
+ 'x-column-initializer': 'AddTableColumn',
'x-component-props': {
rowKey: 'id',
},
@@ -145,7 +145,7 @@ const schema = {
export default function App() {
return (
-
+
);