update docs

This commit is contained in:
chenos 2021-07-14 08:43:18 +08:00
parent e50267d64c
commit 03da153052
47 changed files with 583 additions and 978 deletions

View File

@ -1,27 +0,0 @@
---
title: API - 接口
nav:
title: 组件
path: /client
order: 99
group:
order: 3
title: 其他
path: /client/others
---
# API - 接口
## setGlobalState
## setGlobalActionState
## useGlobalState
## useGlobalAction
## refreshGlobalAction
## useAction
## doAction

View File

@ -1,110 +0,0 @@
---
title: Drawer - 抽屉
nav:
title: 组件
path: /client
group:
order: 3
title: 其他
path: /client/others
---
# Drawer - 抽屉
通过 `Drawer.open(props)` 方法打开抽屉,无需预渲染,可在触发事件中使用。
### 基础抽屉
```tsx
/**
* title: 基础抽屉
*/
import React from 'react';
import { Button } from 'antd';
import Drawer from './index.tsx';
export default () => (
<Button onClick={() => {
Drawer.open({
title: 'Basic Drawer',
content: () => {
return (
<div>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</div>
)
},
});
}}>Open Drawer</Button>
);
```
### 多层抽屉
```tsx
/**
* title: 多层抽屉
* desc: 有多少层就执行多少个 `Drawer.open(props)`
*/
import React from 'react';
import { Button } from 'antd';
import Drawer from './index.tsx';
export default () => (
<Button onClick={() => {
Drawer.open({
title: 'Multi-level drawer',
content: () => {
return (
<div>
<Button onClick={() => {
Drawer.open({
title: 'Two-level Drawer',
content: () => {
return (
<div>This is two-level drawer</div>
)
},
});
}}>Two-level Drawer</Button>
</div>
)
},
});
}}>Open drawer</Button>
);
```
### 关闭时提示
```tsx
/**
* title: 关闭时提示
* desc: 通过 `closeWithConfirm(props)` 方法触发,更多参数请参考 `Modal.confirm`
*/
import React from 'react';
import { Button } from 'antd';
import Drawer from './index.tsx';
export default () => (
<Button onClick={() => {
Drawer.open({
title: 'Basic Drawer',
content: ({ closeWithConfirm }) => {
closeWithConfirm({
title: '您确定关闭抽屉吗?'
});
return (
<div>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</div>
)
},
});
}}>Open Drawer</Button>
);
```

View File

@ -1,206 +0,0 @@
import React, { Fragment, useLayoutEffect, useRef, useState } from 'react';
import ReactDOM, { createPortal } from 'react-dom';
import { Modal, Drawer as AntdDrawer } from 'antd';
import { DrawerProps } from 'antd/lib/drawer';
import { useContext } from 'react';
import { ConfigProvider } from 'antd';
import zhCN from 'antd/lib/locale/zh_CN';
import { ModalFuncProps } from 'antd/lib/modal/Modal'
import isNum from 'lodash/isNumber';
import isBool from 'lodash/isBoolean';
import isStr from 'lodash/isString';
import './style.less';
export const usePrefixCls = (
tag?: string,
props?: {
prefixCls?: string;
},
) => {
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
return getPrefixCls(tag, props?.prefixCls);
};
type DrawerTitle = string | number | React.ReactElement;
const isDrawerTitle = (props: any): props is DrawerTitle => {
return (
isNum(props) || isStr(props) || isBool(props) || React.isValidElement(props)
);
};
const getDrawerProps = (props: any): DrawerProps => {
if (isDrawerTitle(props)) {
return {
title: props,
};
} else {
return props;
}
};
const createElement = (content, props?: any) => {
if (!content) {
return null;
}
if (typeof content === 'string') {
return content;
}
if (React.isValidElement(content)) {
return content;
}
return React.createElement(content, props);
};
export interface IDrawer {
open(props?: any): void;
close(): void;
}
export function Drawer(title: DrawerProps, content: any): IDrawer;
export function Drawer(title: DrawerTitle, content: any): IDrawer;
export function Drawer(title: any, content: any): IDrawer {
document.querySelectorAll('.env-root').forEach((el) => {
el.className = 'env-root env-root-push';
});
const env = {
root: document.createElement('div'),
promise: null,
};
env.root.className = 'env-root';
const props = getDrawerProps(title);
const drawerProps = {
width: '75%',
...props,
onClose: (e: any) => {
props?.onClose?.(e);
drawer.close();
},
afterVisibleChange: (visible: boolean) => {
props?.afterVisibleChange?.(visible);
if (visible) return;
ReactDOM.unmountComponentAtNode(env.root);
env.root?.parentNode?.removeChild(env.root);
env.root = undefined;
},
};
const drawer: any = {
open: (props: any) => {
render(
false,
() => {
drawer.closeWithConfirm = null;
drawer.close();
},
() => {
drawer.close();
},
);
setTimeout(() => {
render(
true,
() => {
drawer.closeWithConfirm = null;
drawer.close();
},
() => {
drawer.close();
},
);
});
},
close: () => {
if (!env.root) return;
if (drawer.closeWithConfirm) {
Modal.confirm({
okText: '确定',
cancelText: '取消',
...drawer.closeWithConfirm,
onOk() {
drawer.closeWithConfirm = null;
const els = document.querySelectorAll('.env-root-push');
if (els.length) {
const last = els[els.length - 1];
last.className = 'env-root';
}
render(false);
},
});
} else {
const els = document.querySelectorAll('.env-root-push');
if (els.length) {
const last = els[els.length - 1];
last.className = 'env-root';
}
render(false);
}
},
closeWithConfirm: null,
};
const closeWithConfirm = (props) => {
drawer.closeWithConfirm = props;
};
const render = (visible = true, resolve?: () => any, reject?: () => any) => {
ReactDOM.render(
<ConfigProvider locale={zhCN}>
<AntdDrawer {...drawerProps} className={'nb-drawer'} visible={visible}>
{createElement(content, {
resolve,
reject,
closeWithConfirm,
})}
</AntdDrawer>
</ConfigProvider>,
env.root,
);
};
document.body.appendChild(env.root);
return drawer;
}
const DrawerFooter: React.FC = (props) => {
const ref = useRef<HTMLDivElement>();
const [footer, setFooter] = useState<HTMLDivElement>();
const footerRef = useRef<HTMLDivElement>();
const prefixCls = usePrefixCls('drawer');
useLayoutEffect(() => {
const content = ref.current?.closest(`.${prefixCls}-wrapper-body`);
if (content) {
if (!footerRef.current) {
footerRef.current = content.querySelector(`.${prefixCls}-footer`);
if (!footerRef.current) {
footerRef.current = document.createElement('div');
footerRef.current.classList.add(`${prefixCls}-footer`);
content.appendChild(footerRef.current);
}
}
setFooter(footerRef.current);
}
});
footerRef.current = footer;
return (
<div ref={ref} style={{ display: 'none' }}>
{footer && createPortal(props.children, footer)}
</div>
);
};
interface ContentPorps {
resolve?: () => any;
closeWithConfirm?: (props: ModalFuncProps) => any;
}
Drawer.open = (props: DrawerProps & { content: (contentPorps?: ContentPorps) => any }) => {
const { content, visible, ...others } = props;
return Drawer(others, content).open({ visible });
};
Drawer.Footer = DrawerFooter;
export default Drawer;

View File

@ -1,18 +0,0 @@
.env-root-push + style + div > div {
transform: translateX(-10%);
}
.env-root-push + div > div {
transform: translateX(-10%);
}
.ant-drawer.nb-drawer .ant-drawer-content-wrapper {
width: 75%;
max-width: 1000px;
}
@media only screen and (max-width: 800px) {
.ant-drawer.nb-drawer .ant-drawer-content-wrapper {
width: 100% !important;
}
.ant-drawer.noco-drawer .ant-drawer-content-wrapper {
width: 100% !important;
}
}

View File

@ -1,14 +0,0 @@
---
title: AdminLayout - 后台布局
nav:
title: 组件
path: /client
group:
order: 2
title: Templates
path: /client/templates
---
# AdminLayout - 后台布局
内置的后台布局模板,提供了基础的菜单和路由切换。

View File

@ -1,14 +0,0 @@
---
title: AuthLayout - 登录布局
nav:
title: 组件
path: /client
group:
order: 2
title: Templates
path: /client/templates
---
# AuthLayout - 登录布局
内置的登录、注册页布局

View File

@ -0,0 +1,14 @@
---
title: 全站演示
nav:
title: 组件
path: /client
toc: menu
group:
order: 0
title: 概念
path: /client
---
<code src="./demos/demo1.tsx"/>

View File

@ -1,14 +1,14 @@
--- ---
title: 全站演示 title: 介绍
nav: nav:
title: 组件 title: 组件
path: /client path: /client
toc: menu toc: menu
group: group:
order: 0 order: 0
title: 全站演示 title: 概念
path: /client path: /client
--- ---
<code src="./demos/demo1.tsx"/> # 介绍

View File

@ -23,7 +23,7 @@ import { uid, clone } from '@formily/shared';
import { ArrayCollapse, ArrayTable, FormLayout } from '@formily/antd'; import { ArrayCollapse, ArrayTable, FormLayout } from '@formily/antd';
import { Space, Card, Modal, Spin } from 'antd'; import { Space, Card, Modal, Spin } from 'antd';
import { Action, useLogin, useRegister, useSubmit } from '../action'; import { Action, useLogin, useRegister, useSubmit, useDesignableValues } from '../action';
import { AddNew } from '../add-new'; import { AddNew } from '../add-new';
import { Cascader } from '../cascader'; import { Cascader } from '../cascader';
import { Checkbox } from '../checkbox'; import { Checkbox } from '../checkbox';
@ -73,6 +73,7 @@ export const scope = {
useTableFilterAction, useTableFilterAction,
useTableRow, useTableRow,
useTableUpdateAction, useTableUpdateAction,
useDesignableValues,
}; };
export const components = { export const components = {
@ -363,8 +364,8 @@ export const createDesignableSchemaField = (options) => {
}} }}
> >
<SchemaField scope={props.scope} components={props.components} schema={schema} /> <SchemaField scope={props.scope} components={props.components} schema={schema} />
<CodePreview schema={schema} /> {props.debug && <CodePreview schema={schema} />}
<FormValues /> {props.debug && <FormValues />}
</DesignableContext.Provider> </DesignableContext.Provider>
); );
}; };
@ -435,6 +436,7 @@ export interface SchemaRendererProps {
onlyRenderProperties?: boolean; onlyRenderProperties?: boolean;
scope?: any; scope?: any;
components?: any; components?: any;
debug?: boolean;
} }
export const SchemaRenderer = (props: SchemaRendererProps) => { export const SchemaRenderer = (props: SchemaRendererProps) => {
@ -463,6 +465,7 @@ export const SchemaRenderer = (props: SchemaRendererProps) => {
return ( return (
<FormProvider form={form}> <FormProvider form={form}>
<DesignableSchemaField <DesignableSchemaField
debug={props.debug}
scope={props.scope} scope={props.scope}
components={props.components} components={props.components}
onRefresh={props.onRefresh} onRefresh={props.onRefresh}

View File

@ -0,0 +1,61 @@
import { ISchema } from '@formily/react';
import {
useDesignableValues,
useDesignableUpdate,
useDesignableSchemaRemove,
} from '.';
export const DesignableBar: { [key: string]: ISchema } = {};
DesignableBar.Action = {
name: 'bar',
type: 'void',
// title: '操作栏2',
'x-component': 'Action.Dropdown',
'x-component-props': {
icon: 'MenuOutlined',
},
properties: {
edit: {
type: 'void',
title: '编辑按钮',
'x-component': 'Action',
'x-component-props': {
// icon,
},
properties: {
modal: {
type: 'void',
title: '修改按钮配置',
'x-decorator': 'Form',
'x-decorator-props': {
useValues: useDesignableValues,
},
'x-component': 'Action.Modal',
'x-component-props': {
width: '500px',
useAction: useDesignableUpdate,
},
properties: {
title: {
type: 'string',
title: '按钮标题',
required: true,
'x-component': 'Input',
'x-decorator': 'FormItem',
},
},
},
},
},
remove: {
type: 'void',
title: '删除按钮',
'x-component': 'Action',
'x-component-props': {
useAction: useDesignableSchemaRemove,
// icon,
},
},
},
};

View File

@ -11,8 +11,7 @@ group:
# Action - 操作 # Action - 操作
## Node Tree
## 组件节点树
<pre lang="tsx"> <pre lang="tsx">
////////// 单节点 ////////// ////////// 单节点 //////////
@ -67,17 +66,16 @@ group:
</Action.Dropdown> </Action.Dropdown>
</pre> </pre>
操作有三类: ## Designable Bar
- 常规操作Action - Action.DesignableBar
- 弹出层操作,弹出层可以是 Action.Drawer、Action.Modal、Action.Popover - Action.Modal.DesignableBar
- 指定容器内打开: Action.Container - Action.Drawer.DesignableBar
- 下拉菜单Action.Dropdown用于收纳多种操作 - Action.Popover.DesignableBar
- 跳转操作Action.Link、Action.URL
Action.Drawer、Action.Modal、Action.Popover 和 Action.Container 需要和 Action 搭配使用 ## Examples
## Action - 常规操作 ### Action - 常规操作
```tsx ```tsx
/** /**
@ -100,17 +98,18 @@ const schema = {
name: 'action1', name: 'action1',
title: '按钮', title: '按钮',
'x-component': 'Action', 'x-component': 'Action',
'x-designable-bar': 'Action.DesignableBar',
'x-component-props': { 'x-component-props': {
useAction, useAction: '{{ useAction }}',
}, },
}; };
export default () => { export default () => {
return <SchemaRenderer schema={schema} /> return <SchemaRenderer debug={true} scope={{ useAction }} schema={schema} />
} }
``` ```
## Action.Link - 内链跳转 ### Action.Link - 内链跳转
```tsx ```tsx
import React from 'react'; import React from 'react';
@ -131,7 +130,7 @@ export default () => {
} }
``` ```
## Action.URL - 外链跳转 ### Action.URL - 外链跳转
```tsx ```tsx
import React from 'react'; import React from 'react';
@ -152,7 +151,7 @@ export default () => {
} }
``` ```
## Action.Dropdown - 下拉操作 ### Action.Dropdown - 下拉操作
```tsx ```tsx
import React from 'react'; import React from 'react';
@ -253,7 +252,7 @@ export default () => {
} }
``` ```
## Action.Popover - 打开气泡 ### Action.Popover - 打开气泡
```tsx ```tsx
import React from 'react'; import React from 'react';
@ -285,7 +284,7 @@ export default () => {
} }
``` ```
## Action.Drawer - 打开抽屉 ### Action.Drawer - 打开抽屉
```tsx ```tsx
import React from 'react'; import React from 'react';
@ -338,10 +337,13 @@ export default () => {
} }
``` ```
## Action.Modal - 打开对话框 ### Action.Modal - 打开对话框
`x-decorator='Form'`Model 为 Form并自带按钮
```tsx ```tsx
import React from 'react'; import React from 'react';
import { Space } from 'antd';
import { SchemaRenderer } from '../'; import { SchemaRenderer } from '../';
import { useVisibleContext } from './'; import { useVisibleContext } from './';
@ -406,12 +408,40 @@ const schema = {
}, },
}; };
const schema2 = {
type: 'void',
name: 'action1',
title: 'x-decorator=Form',
'x-component': 'Action',
properties: {
drawer1: {
type: 'void',
title: '弹窗标题',
'x-component': 'Action.Modal',
'x-component-props': {},
'x-decorator': 'Form',
properties: {
input: {
type: 'string',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
},
},
},
};
export default () => { export default () => {
return <SchemaRenderer schema={schema} /> return (
<Space>
<SchemaRenderer schema={schema} />
<SchemaRenderer schema={schema2} />
</Space>
)
} }
``` ```
## Action.Container - 指定容器内打开 ### Action.Container - 指定容器内打开
```tsx ```tsx
import React, { useRef } from 'react'; import React, { useRef } from 'react';

View File

@ -9,6 +9,7 @@ import {
SchemaOptionsContext, SchemaOptionsContext,
Schema, Schema,
useField, useField,
SchemaExpressionScopeContext,
} from '@formily/react'; } from '@formily/react';
import { Button, Dropdown, Menu, Popover, Space, Drawer, Modal } from 'antd'; import { Button, Dropdown, Menu, Popover, Space, Drawer, Modal } from 'antd';
import { Link, useHistory, LinkProps } from 'react-router-dom'; import { Link, useHistory, LinkProps } from 'react-router-dom';
@ -22,6 +23,9 @@ import { uid } from '@formily/shared';
import './style.less'; import './style.less';
import constate from 'constate'; import constate from 'constate';
import { Icon } from '../icon-picker';
import { useMemo } from 'react';
import { createForm } from '@formily/core';
export function useDefaultAction() { export function useDefaultAction() {
return { return {
@ -109,6 +113,7 @@ const BaseAction = observer((props: any) => {
const { const {
ButtonComponent = Button, ButtonComponent = Button,
className, className,
icon,
useAction = useDefaultAction, useAction = useDefaultAction,
...others ...others
} = props; } = props;
@ -122,11 +127,10 @@ const BaseAction = observer((props: any) => {
field.componentProps.setVisible = setVisible; field.componentProps.setVisible = setVisible;
}, []); }, []);
console.log('BaseAction', { field, schema, fieldSchema }, field.title);
const renderButton = () => ( const renderButton = () => (
<ButtonComponent <ButtonComponent
{...others} {...others}
icon={<Icon type={icon} />}
className={classNames(className, `name-${schema.name}`)} className={classNames(className, `name-${schema.name}`)}
onClick={async (e) => { onClick={async (e) => {
e.stopPropagation && e.stopPropagation(); e.stopPropagation && e.stopPropagation();
@ -227,7 +231,24 @@ Action.Popover = observer((props) => {
Action.Drawer = observer((props) => { Action.Drawer = observer((props) => {
const field = useField(); const field = useField();
// const { visible, setVisible } = useVisibleContext();
const { useAction = () => ({ async run() {} }), ...others } = props;
const { schema } = useDesignable();
const { visible, setVisible } = useVisibleContext(); const { visible, setVisible } = useVisibleContext();
const { run } = useAction();
const form = useForm();
console.log(`schema['x-decorator']`, schema['x-decorator'])
if (schema['x-decorator'] === 'Form.Decorator') {
Object.assign(others, {
footer: (
<Space>
<Button type={'primary'}>Ok</Button>
<Button>Cancel</Button>
</Space>
),
});
}
return ( return (
<Drawer <Drawer
onClick={(e) => { onClick={(e) => {
@ -235,7 +256,7 @@ Action.Drawer = observer((props) => {
}} }}
title={field.title} title={field.title}
width={'50%'} width={'50%'}
{...props} {...others}
visible={visible} visible={visible}
onClose={(e) => { onClose={(e) => {
e.stopPropagation(); e.stopPropagation();
@ -247,103 +268,142 @@ Action.Drawer = observer((props) => {
); );
}); });
const [DesignableContextProvider, useDesignableContext] = constate(() => {
return useDesignable();
});
import { DesignableBar } from './designableBar';
import { cloneDeep } from 'lodash';
import { clone } from '@formily/shared';
export function useDesignableValues() {
const { schema } = useDesignableContext();
return schema
? {
title: schema.title,
}
: {};
}
export function useDesignableUpdate() {
const { schema, refresh } = useDesignableContext();
const form = useForm();
return {
async run() {
schema.title = form.values.title;
refresh();
console.log('useDesignableUpdate', schema, form.values);
},
};
}
export function useDesignableSchemaRemove() {
const { schema, refresh, remove } = useDesignableContext();
return {
async run() {
remove();
},
};
}
Action.Modal = observer((props) => { Action.Modal = observer((props) => {
const field = useField(); const { useAction = () => ({ async run() {} }), ...others } = props;
const { schema } = useDesignable();
const { setVisible: setDropdownVisible } = useDropdownVisibleContext();
const { visible, setVisible } = useVisibleContext(); const { visible, setVisible } = useVisibleContext();
const { run } = useAction();
const form = useForm();
if (schema['x-decorator'] !== 'Form.Decorator') {
Object.assign(others, { footer: null });
}
return ( return (
<Modal <Modal
// onClick={e => { title={schema.title}
// e.stopPropagation();
// }}
title={field.title}
width={'50%'} width={'50%'}
{...props} {...others}
visible={visible} visible={visible}
closable closable
maskClosable maskClosable
onCancel={(e) => { destroyOnClose
onCancel={async (e) => {
e.stopPropagation(); e.stopPropagation();
setVisible(false); setVisible(false);
setDropdownVisible && setDropdownVisible(false);
}}
onOk={async (e) => {
console.log('onOk', form.values);
// await form.submit();
await run();
// e.stopPropagation();
setVisible(false);
setDropdownVisible && setDropdownVisible(false);
}} }}
footer={null}
> >
<div onClick={(e) => e.stopPropagation()}>{props.children}</div> <div
//onClick={(e) => e.stopPropagation()}
>
{props.children}
</div>
</Modal> </Modal>
); );
}); });
Action.Dropdown = observer((props) => { const [DropdownVisibleProvider, useDropdownVisibleContext] = constate((props: any = {}) => {
// const { visible, setVisible } = useVisibleContext(); const { initialVisible = false } = props;
const [visible, setVisible] = useState(initialVisible);
return { visible, setVisible };
});
const ActionDropdown = observer((props: any) => {
const { icon, ...others } = props;
const schema = useFieldSchema(); const schema = useFieldSchema();
const { visible, setVisible } = useDropdownVisibleContext();
return ( return (
<>
<Popover <Popover
// visible={visible} visible={visible}
// onVisibleChange={(visible) => { onVisibleChange={(visible) => {
// setVisible(visible); setVisible(visible);
// }} }}
{...props} // {...props}
overlayClassName={'nb-action-group'} overlayClassName={'nb-action-group'}
// trigger={'click'} // trigger={'click'}
content={props.children} content={props.children}
placement={'bottomLeft'} placement={'bottomLeft'}
> >
<Button>{schema.title}</Button> <Button icon={<Icon type={icon} />} {...others}>
{schema.title}
</Button>
</Popover> </Popover>
{/* popover 的按钮初始化时并未渲染,暂时先这么处理 */} );
<div style={{display: 'none'}}>{props.children}</div> });
</>
Action.Dropdown = observer((props) => {
return (
<DropdownVisibleProvider>
<ActionDropdown {...props} />
<div style={{ display: 'none' }}>{props.children}</div>
</DropdownVisibleProvider>
); );
}); });
Action.DesignableBar = () => { Action.DesignableBar = () => {
const field = useField(); const field = useField();
// const schema = useFieldSchema(); // const schema = useFieldSchema();
const { schema, insertAfter } = useDesignable(); const { schema, insertAfter, refresh } = useDesignable();
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
return ( return (
<div className={classNames('designable-bar', { active: visible })}> <DesignableContextProvider>
<span <div className={classNames('designable-bar', { active: visible })}>
onClick={(e) => { <span
e.stopPropagation(); onClick={(e) => {
}} e.stopPropagation();
className={classNames('designable-bar-actions', { active: visible })}
>
<Dropdown
trigger={['click']}
visible={visible}
onVisibleChange={(visible) => {
setVisible(visible);
}} }}
overlay={ className={classNames('designable-bar-actions', { active: visible })}
<Menu>
<Menu.Item
onClick={(e) => {
console.log({ field, schema });
schema.title = '按钮文案被修改了';
field.setTitle('按钮文案被修改了');
schema.properties.drawer1.title = '抽屉标题文案被修改了';
setVisible(false);
}}
>
</Menu.Item>
<Menu.Item
onClick={() => {
insertAfter({
name: uid(),
'x-component': 'Input',
});
}}
>
insertAfter
</Menu.Item>
</Menu>
}
> >
<MenuOutlined /> <SchemaRenderer schema={DesignableBar.Action} />
</Dropdown> </span>
</span> </div>
</div> </DesignableContextProvider>
); );
}; };

View File

@ -80,3 +80,16 @@
} }
} }
} }
.designable-bar-actions {
.ant-btn {
border: 0;
padding: 0;
background: none;
height: auto;
line-height: 1em;
width: auto;
color: #fff;
}
}

View File

@ -11,7 +11,7 @@ group:
# AddNew - 新增 # AddNew - 新增
## 组件节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
// 简单场景,只支持上下拖拽布局 // 简单场景,只支持上下拖拽布局
@ -24,7 +24,7 @@ group:
// 栅格布局,支持行列等复杂的拖拽操作 // 栅格布局,支持行列等复杂的拖拽操作
<Grid> <Grid>
<Grid.Row> <Grid.Row locked>
<Grid.Col> <Grid.Col>
// 常规区块 // 常规区块
<AddNew.BlockItem/> <AddNew.BlockItem/>
@ -35,7 +35,11 @@ group:
</Grid> </Grid>
</pre> </pre>
## 代码演示 ## Designable Bar
暂无
## Examples
### AddNew.BlockItem ### AddNew.BlockItem

View File

@ -0,0 +1,26 @@
---
title: BlockItem - 区块项
nav:
title: 组件
path: /client
group:
order: 1
title: Schemas
path: /client/schemas
---
# BlockItem - 区块项
## Node Tree
通常 BlockItem 并不单独占用一个节点,而是节点的 x-decorator
<pre lang="tsx">
<Table x-decorator={'BlockItem'}/>
</pre>
BlockItem 的作用主要用于处理 DesignableBar
<pre lang="tsx">
<Table x-decorator={'BlockItem'} x-designable-bar={'Table.DesignableBar'}/>
</pre>

View File

@ -11,13 +11,17 @@ group:
# Cascader - 级联选择 # Cascader - 级联选择
## 组件节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
<Cascader/> <Cascader/>
</pre> </pre>
## 代码演示 ## Designable Bar
- Cascader.DesignableBar
## Examples
### 省市区级联 ### 省市区级联

View File

@ -11,7 +11,7 @@ group:
# Checkbox - 多选框 # Checkbox - 多选框
## 组件节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
// 勾选 // 勾选
@ -20,7 +20,11 @@ group:
<Checkbox.Group/> <Checkbox.Group/>
</pre> </pre>
## 代码演示 ## Designable Bar
- Checkbox.DesignableBar
## Examples
### 勾选 ### 勾选

View File

@ -11,13 +11,17 @@ group:
# ColorSelect - 颜色选择器 # ColorSelect - 颜色选择器
## 组件节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
<ColorSelect/> <ColorSelect/>
</pre> </pre>
## 代码演示 ## Designable Bar
- ColorSelect.DesignableBar
## Examples
### 颜色选择器 ### 颜色选择器

View File

@ -11,20 +11,23 @@ group:
# DatabaseField - 数据表字段 # DatabaseField - 数据表字段
## 组件节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
<DatabaseField/> <DatabaseField/>
</pre> </pre>
## 代码演示 ## Designable Bar
暂无
## Examples
```tsx ```tsx
import React from 'react'; import React from 'react';
import { createForm } from '@formily/core'; import { createForm } from '@formily/core';
import { SchemaRenderer } from '../'; import { SchemaRenderer } from '../';
import { observer, connect, useField } from '@formily/react'; import { observer, connect, useField } from '@formily/react';
import Editor from '@monaco-editor/react';
const schema = { const schema = {
type: 'object', type: 'object',
@ -66,11 +69,6 @@ export default observer(() => {
return ( return (
<div> <div>
<SchemaRenderer form={form} schema={schema} /> <SchemaRenderer form={form} schema={schema} />
<Editor
height="200px"
defaultLanguage="json"
value={JSON.stringify(form.values, null, 2)}
/>
</div> </div>
) )
}) })

View File

@ -11,13 +11,17 @@ group:
# DatePicker - 日期选择器 # DatePicker - 日期选择器
## 组件节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
<DatePicker/> <DatePicker/>
</pre> </pre>
## 代码演示 ## Designable Bar
- DatePicker.DesignableBar
## Examples
### 日期选择器 ### 日期选择器

View File

@ -0,0 +1,25 @@
---
title: DesignableBar - 配置操作栏
nav:
title: 组件
path: /client
group:
order: 1
title: Schemas
path: /client/schemas
---
# DesignableBar - 配置操作栏
用于修改节点的参数配置DesignableBar 是所有配置操作栏的统称,不是固定的,可以根据不同节点定义不同的 `**.DesignableBar`
## Node Tree
通常 DesignableBar 并不单独占用一个节点,而是节点的 x-designable-bar
<pre lang="tsx">
<Table x-decorator={'BlockItem'} x-designable-bar={'Table.DesignableBar'}/>
<Action x-designable-bar={'Action.DesignableBar'}/>
</pre>
数据组件的 DesignableBar 通常与 FormItem 搭配使用,非数据组件的 DesignableBar 通常与 BlockItem 搭配使用,也有少量如 Action、Menu 无需 BlockItem

View File

@ -11,7 +11,7 @@ group:
# Filter - 筛选器 # Filter - 筛选器
## 组件节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
<Filter> <Filter>
@ -24,16 +24,11 @@ group:
</Filter> </Filter>
</pre> </pre>
## 代码演示 ## Designable Bar
<!-- <Filter> - Filter.DesignableBar
<Filter.Column title={'字段1'} operations={[]}>
<Input/> ## Examples
</Filter.Column>
<Filter.Column title={'字段2'}>
<Input/>
</Filter.Column>
</Filter> -->
```tsx ```tsx
import React from 'react'; import React from 'react';

View File

@ -0,0 +1,26 @@
---
title: FormItem - 表单项
nav:
title: 组件
path: /client
group:
order: 1
title: Schemas
path: /client/schemas
---
# FormItem - 表单项
## Node Tree
通常 FormItem 并不单独占用一个节点,而是节点的 x-decorator
<pre lang="tsx">
<Input x-decorator={'FormItem'}/>
</pre>
FormItem 的作用主要用于处理表单项(控件)的校验、布局等
<pre lang="tsx">
<Input x-decorator={'FormItem'} x-designable-bar={'Input.DesignableBar'}/>
</pre>

View File

@ -11,7 +11,7 @@ group:
# Form - 表单 # Form - 表单
## 组件节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
<Form> <Form>
@ -19,9 +19,15 @@ group:
<Select/> <Select/>
// 添加其他节点 // 添加其他节点
</Form> </Form>
<Table x-decorator={'Form'}/>
</pre> </pre>
## 代码演示 ## Designable Bar
- Form.DesignableBar
## Examples
### 常规表单 ### 常规表单
@ -161,7 +167,7 @@ import { uid } from '@formily/shared';
const schema = { const schema = {
type: 'void', type: 'void',
name: uid(), name: uid(),
'x-decorator': 'Card', 'x-decorator': 'BlockItem',
'x-component': 'Form', 'x-component': 'Form',
'x-designable-bar': 'Form.DesignableBar', 'x-designable-bar': 'Form.DesignableBar',
properties: { properties: {

View File

@ -6,6 +6,8 @@ import {
useFieldSchema, useFieldSchema,
observer, observer,
SchemaExpressionScopeContext, SchemaExpressionScopeContext,
FormProvider,
ISchema,
} from '@formily/react'; } from '@formily/react';
import { SchemaRenderer, useDesignable } from '../DesignableSchemaField'; import { SchemaRenderer, useDesignable } from '../DesignableSchemaField';
import get from 'lodash/get'; import get from 'lodash/get';
@ -42,7 +44,6 @@ function useDefaultValues() {
export const Form: any = observer((props: any) => { export const Form: any = observer((props: any) => {
const scope = useContext(SchemaExpressionScopeContext); const scope = useContext(SchemaExpressionScopeContext);
const { useValues = useDefaultValues } = props; const { useValues = useDefaultValues } = props;
const values = useValues(); const values = useValues();
const form = useMemo(() => { const form = useMemo(() => {
@ -54,37 +55,37 @@ export const Form: any = observer((props: any) => {
}, [values]); }, [values]);
const schema = useFieldSchema(); const schema = useFieldSchema();
const { schema: designableSchema, refresh } = useDesignable(); const { schema: designableSchema, refresh } = useDesignable();
const { DesignableBar } = useDesignableBar(); const formSchema: ISchema = schema['x-decorator'] === 'Form' ? {
const ref = useRef(); type: 'void',
const [active, setActive] = useState(false); "x-component": 'Blank',
const { onMouseEnter, onMouseLeave, onMouseMove } = useMouseEvents(ref); properties: {
onMouseEnter((e: React.MouseEvent) => { [schema.name]: {
setActive(true); ...schema.toJSON(),
}); "x-decorator": 'Form.Decorator',
}
onMouseLeave((e: React.MouseEvent) => { }
setActive(false); } : {
}); ...schema.toJSON(),
'x-component': 'Form.Blank',
onMouseMove((e: React.MouseEvent) => {}); 'x-component-props': {},
};
return ( return (
<div ref={ref} className={'nb-form'}> <SchemaRenderer
<SchemaRenderer scope={scope}
scope={scope} // components={options.components}
// components={options.components} onRefresh={(subSchema: Schema) => {
onRefresh={(subSchema: Schema) => { designableSchema.properties = subSchema.properties;
designableSchema.properties = subSchema.properties; refresh();
refresh(); }}
}} form={form}
form={form} schema={formSchema}
schema={schema.toJSON()} onlyRenderProperties
onlyRenderProperties />
/>
<DesignableBar active={active} />
</div>
); );
}); });
Form.Decorator = ({children}) => children;
Form.DesignableBar = (props) => { Form.DesignableBar = (props) => {
const { active } = props; const { active } = props;
return ( return (

View File

@ -13,21 +13,6 @@ group:
基于行Row和列Col来定义区块Block的外部框架。 基于行Row和列Col来定义区块Block的外部框架。
## 组件节点树
<pre lang="tsx">
<Grid>
<Grid.Row>
<Grid.Col>
// 添加其他节点
</Grid.Col>
<Grid.Col>
// 添加其他节点
</Grid.Col>
</Grid.Row>
</Grid>
</pre>
## 列宽说明 ## 列宽说明
最大支持四列,如果要支持越多列,需要处理的比例也越多。 最大支持四列,如果要支持越多列,需要处理的比例也越多。
@ -88,4 +73,26 @@ group:
- 100% - 100%
## Node Tree
<pre lang="tsx">
<Grid>
<Grid.Row>
<Grid.Col>
// 添加其他节点
</Grid.Col>
<Grid.Col>
// 添加其他节点
</Grid.Col>
</Grid.Row>
</Grid>
</pre>
## Designable Bar
暂无
## Examples
<code src="./demos/demo1.tsx"/> <code src="./demos/demo1.tsx"/>

View File

@ -11,13 +11,17 @@ group:
# IconPicker - 图标选择器 # IconPicker - 图标选择器
## 节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
<IconPicker/> <IconPicker/>
</pre> </pre>
## 代码演示 ## Designable Bar
- IconPicker.DesignableBar
## Examples
```tsx ```tsx
/** /**

View File

@ -11,13 +11,17 @@ group:
# InputNumber - 数字框 # InputNumber - 数字框
## 节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
<InputNumber/> <InputNumber/>
</pre> </pre>
## 代码演示 ## Designable Bar
- InputNumber.DesignableBar
## Examples
### 数字框 ### 数字框

View File

@ -13,14 +13,19 @@ group:
输入框是非常常用的控件,参数可以组合成许多字段,如单行文本、多行文本、手机号、邮箱、网址等。 输入框是非常常用的控件,参数可以组合成许多字段,如单行文本、多行文本、手机号、邮箱、网址等。
## 节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
<Input/> <Input/>
<Input.TextArea/> <Input.TextArea/>
</pre> </pre>
## 代码演示 ## Designable Bar
- Input.DesignableBar
- Input.TextArea.DesignableBar
## Examples
### 单行文本 ### 单行文本

View File

@ -11,13 +11,17 @@ group:
# Markdown 编辑器 # Markdown 编辑器
## 节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
<Markdown/> <Markdown/>
</pre> </pre>
## 代码演示 ## Designable Bar
- Markdown.DesignableBar
## Examples
### Markdown 编辑器 ### Markdown 编辑器

View File

@ -13,7 +13,7 @@ group:
需要 antd v4.16+ 支持,在此之前的 Menu.Item 不支持 Fragment 包裹。 需要 antd v4.16+ 支持,在此之前的 Menu.Item 不支持 Fragment 包裹。
## 组件树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
<Menu> <Menu>
@ -43,7 +43,11 @@ group:
</Menu> </Menu>
</pre> </pre>
## 代码演示 ## Designable Bar
- Menu.DesignableBar
## Examples
### 横向菜单 ### 横向菜单

View File

@ -11,14 +11,18 @@ group:
# Password - 密码 # Password - 密码
## 节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
// 单选框 // 单选框
<Password/> <Password/>
</pre> </pre>
## 代码演示 ## Designable Bar
- Password.DesignableBar
## Examples
### 密码框 ### 密码框

View File

@ -11,7 +11,7 @@ group:
# Radio - 单选框 # Radio - 单选框
## 节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
// 单选框 // 单选框
@ -20,7 +20,11 @@ group:
<Radio.Group/> <Radio.Group/>
</pre> </pre>
## 代码演示 ## Designable Bar
- Radio.DesignableBar
## Examples
### 单选框 ### 单选框

View File

@ -11,7 +11,7 @@ group:
# Select - 选择器 # Select - 选择器
## 节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
// 常规选择器 // 常规选择器
@ -37,7 +37,14 @@ group:
</Select.Drawer> </Select.Drawer>
</pre> </pre>
## Select ## Designable Bar
- Select.DesignableBar
- Select.Drawer.DesignableBar
- Select.Options.DesignableBar
- Select.OptionTag.DesignableBar
## Examples
### 单选 ### 单选
@ -62,13 +69,11 @@ const schema = {
type: 'object', type: 'object',
properties: { properties: {
input: { input: {
interface: 'string', type: 'number',
type: 'string',
title: `编辑模式`, title: `编辑模式`,
name: 'name1',
enum: options, enum: options,
'x-decorator': 'FormItem', 'x-decorator': 'FormItem',
'x-component': 'Select', 'x-component': 'Select.Object',
'x-reactions': { 'x-reactions': {
target: 'read', target: 'read',
fulfill: { fulfill: {
@ -79,14 +84,12 @@ const schema = {
}, },
}, },
read: { read: {
interface: 'string', type: 'number',
type: 'string',
title: `阅读模式`, title: `阅读模式`,
enum: options, enum: options,
name: 'name2',
'x-read-pretty': true,
'x-decorator': 'FormItem', 'x-decorator': 'FormItem',
'x-component': 'Select', 'x-component': 'Select.Object',
'x-read-pretty': true,
}, },
} }
}; };
@ -257,8 +260,7 @@ const schema = {
type: 'object', type: 'object',
properties: { properties: {
input: { input: {
interface: 'select', type: 'object',
type: 'string',
title: `编辑模式`, title: `编辑模式`,
enum: dataSource, enum: dataSource,
'x-decorator': 'FormItem', 'x-decorator': 'FormItem',
@ -281,8 +283,7 @@ const schema = {
}, },
}, },
read: { read: {
interface: 'select', type: 'object',
type: 'string',
title: `阅读模式`, title: `阅读模式`,
enum: dataSource, enum: dataSource,
'x-read-pretty': true, 'x-read-pretty': true,
@ -332,8 +333,7 @@ const schema = {
type: 'object', type: 'object',
properties: { properties: {
input: { input: {
interface: 'select', type: 'array',
type: 'string',
title: `编辑模式`, title: `编辑模式`,
enum: dataSource, enum: dataSource,
'x-decorator': 'FormItem', 'x-decorator': 'FormItem',
@ -356,8 +356,7 @@ const schema = {
}, },
}, },
read: { read: {
interface: 'select', type: 'array',
type: 'string',
title: `阅读模式`, title: `阅读模式`,
enum: dataSource, enum: dataSource,
'x-read-pretty': true, 'x-read-pretty': true,
@ -571,22 +570,44 @@ export default () => {
}; };
``` ```
<!-- ## Schema API
<Select />
<Select.Object />
<Select.Drawer>
<Select.Options>
<Table />
<Action />
<Select.Options>
<Select.ItemDetails>
<Form/>
</Select.ItemDetails>
<Select.Drawer>
<Action /> ### Select
<Action> type 支持 string、number、object 和 arrayarray 元素可以是 string、number 或 object。如
<Drawer />
</Action> ```ts
--> {
properties: {
select: {
type: 'string', // 也可以是 number、object、array
'x-component': 'Select',
}
}
}
```
可以配置 dataSourceenum的 fieldNames
```ts
{
properties: {
select: {
type: 'string', // 也可以是 number、object、array
'x-component': 'Select',
'x-component-props': {
fieldNames: {
label: 'label', // 标签文案
value: 'value',
color: 'color', // 标签颜色
children: 'children', // 选项分组时,选项字段对应的 key
},
},
},
}
}
```
### Select.Drawer
type 支持 object 和 arraySelect.Drawer 的可选项是以抽屉方式展开,提供了 Select.Options 和 Select.OptionTag 用于配置可选项界面和选中项详情界面。

View File

@ -18,6 +18,8 @@ import { useDesignable } from '../DesignableSchemaField';
import { createContext } from 'react'; import { createContext } from 'react';
import { useContext } from 'react'; import { useContext } from 'react';
import { SelectedRowKeysContext, useTableContext } from '../table'; import { SelectedRowKeysContext, useTableContext } from '../table';
import { isEmpty } from 'lodash';
import { isField } from '@formily/core';
export const Select: any = connect( export const Select: any = connect(
(props) => { (props) => {
@ -189,10 +191,13 @@ Select.Object = connect(
), ),
mapReadPretty( mapReadPretty(
observer((props: any) => { observer((props: any) => {
const { value, fieldNames = { label: 'label' }, ...others } = props; const { value, fieldNames = { label: 'label', color: 'color' }, ...others } = props;
if (!value) { if (!value) {
return null; return null;
} }
if (isEmpty(value)) {
return null;
}
const values = toArr(value); const values = toArr(value);
return ( return (
<div> <div>

View File

@ -11,7 +11,7 @@ group:
# Table - 表格 # Table - 表格
## 组件节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
<Table> <Table>
@ -53,6 +53,11 @@ group:
</Table> </Table>
</pre> </pre>
## 代码演示 ## Designable Bar
- Table.DesignableBar
- Table.Column.DesignableBar
## Examples
<code src="./demos/demo1.tsx"/> <code src="./demos/demo1.tsx"/>

View File

@ -11,7 +11,7 @@ group:
# Tabs - 标签页 # Tabs - 标签页
## 组件节点树 ## Node
<pre lang="tsx"> <pre lang="tsx">
<Tabs> <Tabs>
@ -24,7 +24,11 @@ group:
</Tabs> </Tabs>
</pre> </pre>
## 代码演示 ## Designable Bar
- Tabs.DesignableBar
## Examples
### 基本使用 ### 基本使用

View File

@ -11,13 +11,17 @@ group:
# TimePicker - 时间选择器 # TimePicker - 时间选择器
## 节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
<TimePicker/> <TimePicker/>
</pre> </pre>
## 代码演示 ## Designable Bar
- TimePicker.DesignableBar
## Examples
### 日期选择器 ### 日期选择器

View File

@ -11,13 +11,17 @@ group:
# Upload - 上传 # Upload - 上传
## 节点树 ## Node Tree
<pre lang="tsx"> <pre lang="tsx">
<Upload/> <Upload/>
</pre> </pre>
## 代码演示 ## Designable Bar
- Upload.DesignableBar
## Examples
### 上传 ### 上传

View File

@ -1,14 +0,0 @@
---
title: AdminLayout - 后台布局
nav:
title: 组件
path: /client
group:
order: 2
title: Templates
path: /client/templates
---
# AdminLayout - 后台布局
内置的后台布局模板,提供了基础的菜单和路由切换。

View File

@ -1,229 +0,0 @@
import React, { useContext, useEffect, useRef, useState } from 'react';
import {
Button,
Spin,
Layout,
PageHeader,
Modal,
Menu,
Collapse,
Dropdown,
} from 'antd';
import isEmpty from 'lodash/isEmpty';
import {
Link,
useLocation,
useRouteMatch,
useHistory,
Redirect,
} from 'react-router-dom';
import {
useGlobalAction,
refreshGlobalAction,
RouteComponentContext,
} from '../../';
import { SchemaRenderer } from '../../schemas';
import { useRequest } from 'ahooks';
import {
DatabaseOutlined,
PlusOutlined,
DownOutlined,
} from '@ant-design/icons';
import { Tabs } from 'antd';
import '@formily/antd/esm/array-collapse/style';
import './style.less';
import { MenuContainerContext } from '../../schemas/menu';
function LogoutButton() {
const history = useHistory();
return (
<Button
onClick={async () => {
history.push('/login');
await refreshGlobalAction('routes:getAccessible');
}}
>
</Button>
);
}
function Database() {
const [visible, setVisible] = useState(false);
const schema = {
type: 'object',
properties: {
layout: {
type: 'void',
'x-component': 'FormLayout',
'x-component-props': {
layout: 'vertical',
},
properties: {
input: {
type: 'string',
title: '数据表名称',
required: true,
'x-decorator': 'FormItem',
'x-component': 'Input',
},
array: {
type: 'array',
title: '数据表字段',
'x-component': 'ArrayCollapse',
'x-component-props': {
accordion: true,
},
// maxItems: 3,
'x-decorator': 'FormItem',
items: {
type: 'object',
'x-component': 'ArrayCollapse.CollapsePanel',
'x-component-props': {
header: '字段',
},
properties: {
index: {
type: 'void',
'x-component': 'ArrayCollapse.Index',
},
input: {
type: 'string',
'x-decorator': 'FormItem',
title: 'Input',
required: true,
'x-component': 'Input',
},
remove: {
type: 'void',
'x-component': 'ArrayCollapse.Remove',
},
moveUp: {
type: 'void',
'x-component': 'ArrayCollapse.MoveUp',
},
moveDown: {
type: 'void',
'x-component': 'ArrayCollapse.MoveDown',
},
},
},
properties: {
addition: {
type: 'void',
title: '添加字段',
'x-component': 'ArrayCollapse.Addition',
},
},
},
},
},
},
};
return (
<>
<Modal
title={
<Dropdown
overlay={
<Menu>
<Menu.Item key={'1'}>1</Menu.Item>
<Menu.Item key={'2'}>2</Menu.Item>
<Menu.Item key={'3'}>3</Menu.Item>
<Menu.Item key={'4'}>4</Menu.Item>
<Menu.Divider></Menu.Divider>
<Menu.Item key={'5'}></Menu.Item>
</Menu>
}
>
<span>
1 <DownOutlined />
</span>
</Dropdown>
}
// width={'800px'}
visible={visible}
onCancel={() => setVisible(false)}
onOk={() => setVisible(false)}
// bodyStyle={{ padding: 0 }}
// footer={null}
>
<SchemaRenderer schema={schema} />
</Modal>
<DatabaseOutlined
onClick={() => setVisible(true)}
style={{ color: '#fff', lineHeight: '48px', width: 48 }}
/>
</>
);
}
function LayoutWithMenu({ schema }) {
const match = useRouteMatch<any>();
const location = useLocation();
const sideMenuRef = useRef();
const [activeKey, setActiveKey] = useState(match.params.name);
const onSelect = (info) => {
console.log('LayoutWithMenu', schema);
setActiveKey(info.key);
};
console.log({ match });
return (
<Layout>
<Layout.Header>
<SchemaRenderer
schema={schema}
scope={{ sideMenuRef, onSelect, selectedKeys: [activeKey].filter(Boolean) }}
/>
</Layout.Header>
<Layout>
<Layout.Sider
ref={sideMenuRef}
theme={'light'}
width={200}
></Layout.Sider>
<Layout.Content>
{location.pathname}
<Content activeKey={activeKey} />
</Layout.Content>
</Layout>
</Layout>
);
}
function Content({ activeKey }) {
const { data = {}, loading } = useRequest(
`/api/ui-schemas:getTree/${activeKey}?filter[parentId]=${activeKey}`,
{
refreshDeps: [activeKey],
formatResult: (result) => result?.data,
},
);
if (loading) {
return <Spin />;
}
return <SchemaRenderer schema={data} />;
}
export function AdminLayout({ route, children }: any) {
const { data = {}, loading } = useRequest(
`/api/ui-schemas:getTree/${route.schemaName}`,
{
refreshDeps: [route],
formatResult: (result) => result?.data,
},
);
if (loading) {
return <Spin />;
}
return <LayoutWithMenu schema={data} />;
}
export default AdminLayout;

View File

@ -1,49 +0,0 @@
// .fields-collapse {
// border: 1px solid #f0f0f0;
// border-bottom: 0;
// > .ant-collapse-item {
// border-bottom: 1px solid #f0f0f0;
// }
// .ant-collapse-content {
// &.ant-collapse-content-active {
// border-top: 1px solid #f0f0f0;
// }
// }
// > .ant-collapse-item > .ant-collapse-content {
// background: #fff;
// }
// > .ant-collapse-item > .ant-collapse-content > .ant-collapse-content-box {
// padding: 16px;
// padding-bottom: 1px;
// }
// }
.ant-collapse {
border: 1px solid #d9d9d9 !important;
border-bottom: 0 !important;
> .ant-collapse-item {
border-bottom: 1px solid #d9d9d9 !important;
}
.ant-collapse-content {
border-top: 1px solid #d9d9d9 !important;
}
.ant-collapse-content > .ant-collapse-content-box {
padding: 24px !important;
padding-bottom: 0 !important;
}
}
.database-sider {
background: #fafafa;
padding-top: 16px;
.ant-menu {
background: #fafafa;
border-right: 0;
}
.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected {
background: #fff;
&::after {
display: none;
}
}
}

View File

@ -1,14 +0,0 @@
---
title: AuthLayout - 登录布局
nav:
title: 组件
path: /client
group:
order: 2
title: Templates
path: /client/templates
---
# AuthLayout - 登录布局
内置的登录、注册页布局

View File

@ -1,15 +0,0 @@
import React from 'react';
import { useLocation, useHistory } from 'react-router-dom';
export function AuthLayout({ children, route }: any) {
const location = useLocation();
const history = useHistory();
return (
<div style={{ maxWidth: 320, margin: '0 auto' }}>
<h1>NocoBase</h1>
{children}
</div>
);
}
export default AuthLayout;

View File

@ -1,14 +0,0 @@
---
title: PageTemplate - 页面模板
nav:
title: 组件
path: /client
group:
order: 2
title: Templates
path: /client/templates
---
# PageTemplate - 页面模板
常规的页面模板,支持区块配置。

View File

@ -1,25 +0,0 @@
import React, { useContext, useEffect, useState } from 'react';
import { Spin } from 'antd';
import { Helmet } from 'react-helmet';
import { useRequest } from 'ahooks';
import { SchemaRenderer } from '../../schemas';
export function DefaultPage({ route }) {
const { data = {}, loading } = useRequest(
`/api/ui-schemas:getTree/${route.schemaName}`,
{
refreshDeps: [route],
formatResult: (result) => result?.data,
},
);
if (loading) {
return <Spin />;
}
return (
<div>
<SchemaRenderer schema={data} />
</div>
);
}
export default DefaultPage;

View File

@ -1,3 +0,0 @@
export * from './auth-layout';
export * from './admin-layout';
export * from './default-page';