diff --git a/packages/core/client/.dumirc.ts b/packages/core/client/.dumirc.ts index f4549a394360f..ebb48d33a95f6 100644 --- a/packages/core/client/.dumirc.ts +++ b/packages/core/client/.dumirc.ts @@ -1,3 +1,5 @@ +import path from 'path'; +import glob from 'glob'; import _ from 'lodash' import { getUmiConfig } from '@nocobase/devtools/umiConfig'; import { defineConfig } from 'dumi'; @@ -9,6 +11,19 @@ const lang = process.env.DOC_LANG; console.log('process.env.DOC_LANG', lang); +const componentsDir = 'src/schema-component/antd'; + +function getComponentsMenu() { + const cwd = path.join(__dirname, componentsDir); + const ignores = ['table/index.md', 'form/index.md']; // 老版本,不需要展示 + const files = glob.sync('*/index.md', { cwd, ignore: ignores }); + + return files.map((file) => ({ + title: _.upperFirst(_.camelCase(file.replace('/index.md', ''))), + link: `/components/${file.replace('/index.md', '')}`, + })); +} + export default defineConfig({ hash: true, alias: { @@ -24,7 +39,7 @@ export default defineConfig({ resolve: { docDirs: [`./docs/${lang}`], atomDirs: [ - { type: 'component', dir: 'src/schema-component/antd' }, + { type: 'component', dir: componentsDir }, ], }, locales: [ @@ -77,10 +92,6 @@ export default defineConfig({ title: 'PluginSettingsManager', link: '/core/application/plugin-settings-manager', }, - { - title: 'Request', - link: '/core/request', - }, ], }, { @@ -214,172 +225,7 @@ export default defineConfig({ ] } ], - '/components': [ - { - title: 'Action', - type: 'group', - children: [ - { - "title": "Action", - "link": "/components/action" - }, - { - "title": "Filter", - "link": "/components/filter" - }, - ] - }, - { - title: 'Field', - type: 'group', - children: [ - { - "title": "Checkbox", - "link": "/components/checkbox" - }, - { - "title": "Cascader", - "link": "/components/cascader" - }, - { - "title": "ColorPicker", - "link": "/components/color-picker" - }, - { - "title": "ColorSelect", - "link": "/components/color-select" - }, - { - "title": "DatePicker", - "link": "/components/date-picker" - }, - { - "title": "TimePicker", - "link": "/components/time-picker" - }, - { - "title": "IconPicker", - "link": "/components/icon-picker" - }, - { - "title": "InputNumber", - "link": "/components/input-number" - }, - { - "title": "Input", - "link": "/components/input" - }, - { - "title": "Password", - "link": "/components/password" - }, - { - "title": "Percent", - "link": "/components/percent" - }, - { - "title": "Radio", - "link": "/components/radio" - }, - { - "title": "Select", - "link": "/components/select" - }, - { - "title": "RemoteSelect", - "link": "/components/remote-select" - }, - { - "title": "TreeSelect", - "link": "/components/tree-select" - }, - { - "title": "Upload", - "link": "/components/upload" - }, - { - "title": "CollectionSelect", - "link": "/components/collection-select" - }, - { - "title": "Cron", - "link": "/components/cron" - }, - { - "title": "Markdown", - "link": "/components/markdown" - }, - { - "title": "Variable", - "link": "/components/variable" - } - ] - }, - { - title: 'Block', - type: 'group', - children: [ - { - "title": "BlockItem", - "link": "/components/block-item" - }, - { - "title": "CardItem", - "link": "/components/card-item" - }, - { - "title": "FormItem", - "link": "/components/form-item" - }, - { - "title": "FormV2", - "link": "/components/form-v2" - }, - { - "title": "TableV2", - "link": "/components/table-v2" - }, - { - "title": "Details", - "link": "/components/details" - }, - { - "title": "GridCard", - "link": "/components/grid-card" - }, - { - "title": "Grid", - "link": "/components/grid" - }, - // { - // "title": "List", - // "link": "/components/list" - // }, - ] - }, - { - title: 'Others', - type: 'group', - children: [ - { - "title": "Tabs", - "link": "/components/tabs" - }, - { - "title": "ErrorFallback", - "link": "/components/error-fallback" - }, - { - "title": "G2Plot", - "link": "/components/g2plot" - }, - { - "title": "Preview", - "link": "/components/preview" - }, - ] - }, - ] + '/components': getComponentsMenu(), // '/ui-schema': [ // { // title: 'Overview', diff --git a/packages/core/client/docs/en-US/core/data-block/data-block-provider.md b/packages/core/client/docs/en-US/core/data-block/data-block-provider.md index 1ffc718afd7be..6aeaec0492026 100644 --- a/packages/core/client/docs/en-US/core/data-block/data-block-provider.md +++ b/packages/core/client/docs/en-US/core/data-block/data-block-provider.md @@ -37,7 +37,7 @@ Table 中的字段信息及列表数据,都是存储在数据库中的。 - `DataBlockProvider`:封装了下面的所有组件,并提供了区块属性 - [CollectionProvider](/core/data-source/collection-provider) / [AssociationProvider](/core/data-source/association-provider): 根据 `DataBlockProvider` 提供的上下文信息,查询对应数据表数据及关系字段信息并传递 - - [BlockResourceProvider](/core/data-block/data-block-resource-provider): 根据 `DataBlockProvider` 提供的上下文信息,构建区块 [Resource](/core/request) API,用于区块数据的增删改查 + - [BlockResourceProvider](/core/data-block/data-block-resource-provider): 根据 `DataBlockProvider` 提供的上下文信息,构建区块 [Resource](https://docs.nocobase.com/api/sdk#resource-action) API,用于区块数据的增删改查 - [BlockRequestProvider](/core/data-block/data-block-request-provider): 根据 `DataBlockProvider` 提供的上下文信息,自动调用 `BlockResourceProvider` 提供的 `resource.get()` 或 `resource.list()` 发起请求,得到区块数据,并传递 - [CollectionRecordProvider](/core/data-source/record-provider): 对于 `resource.get()` 场景,会自动嵌套 `CollectionRecordProvider` 并将 `resource.get()` 请求结果传递下去,`resource.list()` 场景则需要自行使用 `CollectionRecordProvider` 提供数据记录 diff --git a/packages/core/client/docs/en-US/core/data-block/data-block-resource-provider.md b/packages/core/client/docs/en-US/core/data-block/data-block-resource-provider.md index 50178dc86fffe..e94246b6c7f87 100644 --- a/packages/core/client/docs/en-US/core/data-block/data-block-resource-provider.md +++ b/packages/core/client/docs/en-US/core/data-block/data-block-resource-provider.md @@ -1,6 +1,6 @@ # DataBlockResourceProvider -根据 `DataBlockProvider` 中的 `collection`、`association`、`sourceId` 等属性,构建好 [resource](/core/request) 对象,方便子组件对区块数据的增删改查操作,其内置在 [DataBlockProvider](/core/data-block/data-block-provider) 中 +根据 `DataBlockProvider` 中的 `collection`、`association`、`sourceId` 等属性,构建好 [resource](https://docs.nocobase.com/api/sdk#resource-action) 对象,方便子组件对区块数据的增删改查操作,其内置在 [DataBlockProvider](/core/data-block/data-block-provider) 中 ## useDataBlockResource diff --git a/packages/core/client/docs/en-US/core/request/demos/demo1.tsx b/packages/core/client/docs/en-US/core/request/demos/demo1.tsx deleted file mode 100644 index dbc18123d2848..0000000000000 --- a/packages/core/client/docs/en-US/core/request/demos/demo1.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { APIClient, APIClientProvider, compose, useRequest } from '@nocobase/client'; -import MockAdapter from 'axios-mock-adapter'; -import React from 'react'; - -const apiClient = new APIClient(); - -const mock = new MockAdapter(apiClient.axios); - -mock.onGet('/users:get').reply(200, { - data: { id: 1, name: 'John Smith' }, -}); - -const providers = [[APIClientProvider, { apiClient }]]; - -export default compose(...providers)(() => { - const { data } = useRequest<{ - data: any; - }>({ - resource: 'users', - action: 'get', - params: {}, - }); - return
{data?.data?.name}
; -}); diff --git a/packages/core/client/docs/en-US/core/request/demos/demo2.tsx b/packages/core/client/docs/en-US/core/request/demos/demo2.tsx deleted file mode 100644 index 823a5dbb41aae..0000000000000 --- a/packages/core/client/docs/en-US/core/request/demos/demo2.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { APIClient, APIClientProvider, compose, useRequest } from '@nocobase/client'; -import MockAdapter from 'axios-mock-adapter'; -import React from 'react'; - -const apiClient = new APIClient(); - -const mock = new MockAdapter(apiClient.axios); - -mock.onGet('/users:get').reply(200, { - data: { id: 1, name: 'John Smith' }, -}); - -const providers = [[APIClientProvider, { apiClient }]]; - -export default compose(...providers)(() => { - const { data } = useRequest<{ - data: any; - }>({ - url: 'users:get', - method: 'get', - }); - return
{data?.data?.name}
; -}); diff --git a/packages/core/client/docs/en-US/core/request/demos/demo3.tsx b/packages/core/client/docs/en-US/core/request/demos/demo3.tsx deleted file mode 100644 index d27bf0470f48c..0000000000000 --- a/packages/core/client/docs/en-US/core/request/demos/demo3.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { uid } from '@formily/shared'; -import { APIClient, APIClientProvider, useAPIClient, useRequest } from '@nocobase/client'; -import { Button, Input, Space, Table } from 'antd'; -import MockAdapter from 'axios-mock-adapter'; -import React from 'react'; - -const apiClient = new APIClient(); - -const mock = new MockAdapter(apiClient.axios); -const sleep = (value: number) => new Promise((resolve) => setTimeout(resolve, value)); - -mock.onGet('/users:list').reply(async () => { - await sleep(1000); - return [ - 200, - { - data: [ - { id: 1, name: uid() }, - { id: 2, name: uid() }, - ], - }, - ]; -}); - -const ComponentA = () => { - console.log('ComponentA'); - const { data, loading } = useRequest<{ - data: any; - }>( - { - url: 'users:list', - method: 'get', - }, - { - uid: 'test', // 当指定了 uid 的 useRequest 的结果,可以通过 api.service(uid) 获取 - }, - ); - return ( - - ); -}; - -const ComponentB = () => { - console.log('ComponentB'); - const apiClient = useAPIClient(); - return ( - - - - - ); -}; - -export default () => { - return ( - - -
-
- -
- ); -}; diff --git a/packages/core/client/docs/en-US/core/request/index.md b/packages/core/client/docs/en-US/core/request/index.md deleted file mode 100644 index d442a201943fd..0000000000000 --- a/packages/core/client/docs/en-US/core/request/index.md +++ /dev/null @@ -1,167 +0,0 @@ -# APIClient - -## APIClient - -```ts -class APIClient { - // axios 实例 - axios: AxiosInstance; - // 缓存带 uid 的 useRequest({}, {uid}) 的结果,可供其他组件调用 - services: Record>; - // 构造器 - constructor(instance?: AxiosInstance | AxiosRequestConfig); - // 客户端请求,支持 AxiosRequestConfig 和 ResourceActionOptions - request, D = any>(config: AxiosRequestConfig | ResourceActionOptions): Promise; - // 获取资源 - resource(name: string, of?: any): R; -} -``` - -示例 - -```ts -import axios from 'axios'; - -// 不传参时,内部直接创建 axios 实例 -const apiClient = new APIClient(); - -// 提供 AxiosRequestConfig 配置参数 -const apiClient = new APIClient({ - baseURL: '', -}); - -// 提供 AxiosInstance -const instance = axios.create({ - baseURL: '', -}); -const apiClient = new APIClient(instance); - -// 常规请求 -const response = await apiClient.request({ url }); - -// NocoBase 特有的资源操作 -const response = await apiClient.resource('posts').list(); - -// 请求共享 -const { data, loading, run } = apiClient.service('uid'); -``` - -`api.service(uid)` 的例子,ComponentB 里刷新 ComponentA 的请求数据 - - - -## APIClientProvider - -提供 APIClient 实例的上下文。 - -```tsx | pure -const apiClient = new APIClient(); - - -``` - -## useAPIClient - -获取当前上下文的 APIClient 实例。 - -```ts -const apiClient = useAPIClient(); -``` - -## useRequest - -```ts -function useRequest

( - service: AxiosRequestConfig

| ResourceActionOptions

| FunctionService, - options?: Options, -); -``` - -支持 `axios.request(config)`,config 详情查看 [axios](https://github.com/axios/axios#request-config) - -```ts -const { data, loading, refresh, run, params } = useRequest({ url: '/users' }); - -// useRequest 里传的是 AxiosRequestConfig,所以 run 里传的也是 AxiosRequestConfig -run({ - params: { - pageSize: 20, - } -}); -``` - -例子如下: - - - -或者是 NocoBase 的 resource & action 请求: - -```ts -const { data, run } = useRequest({ - resource: 'users', - action: 'list', - params: { - pageSize: 20, - }, -}); - -// useRequest 传的是 ResourceActionOptions,所以 run 直接传 action params 就可以了。 -run({ - pageSize: 50, -}); -``` - -例子如下: - - - -也可以是自定义的异步函数: - -```ts -const { data, loading, run, refresh, params } = useRequest((...params) => Promise.resolve({})); - -run(...params); -``` - -更多用法查看 ahooks 的 [useRequest()](https://ahooks.js.org/hooks/use-request/index) - -## useResource - -```ts -function useResource(name: string, of?: string | number): IResource; -``` - -资源是 NocoBase 的核心概念,包括: - -- 独立资源,如 `posts` -- 关系资源,如 `posts.tags` `posts.user` `posts.comments` - -资源 URI - -```bash -# 独立资源,文章 -/api/posts -# 关系资源,文章 ID=1 的评论 -/api/posts/1/comments -``` - -通过 APIClient 获取资源 - -```ts -const api = new APIClient(); - -api.resource('posts'); -api.resource('posts.comments', 1); -``` - -useResource 用法: - -```ts -const resource = useResource('posts'); -const resource = useResource('posts.comments', 1); -``` - -resource 的实际场景用例参见: - -- [useCollection()](collection-manager#usecollection) -- [useCollectionField()](collection-manager#usecollectionfield) diff --git a/packages/core/client/docs/zh-CN/core/data-block/data-block-provider.md b/packages/core/client/docs/zh-CN/core/data-block/data-block-provider.md index 1ffc718afd7be..6aeaec0492026 100644 --- a/packages/core/client/docs/zh-CN/core/data-block/data-block-provider.md +++ b/packages/core/client/docs/zh-CN/core/data-block/data-block-provider.md @@ -37,7 +37,7 @@ Table 中的字段信息及列表数据,都是存储在数据库中的。 - `DataBlockProvider`:封装了下面的所有组件,并提供了区块属性 - [CollectionProvider](/core/data-source/collection-provider) / [AssociationProvider](/core/data-source/association-provider): 根据 `DataBlockProvider` 提供的上下文信息,查询对应数据表数据及关系字段信息并传递 - - [BlockResourceProvider](/core/data-block/data-block-resource-provider): 根据 `DataBlockProvider` 提供的上下文信息,构建区块 [Resource](/core/request) API,用于区块数据的增删改查 + - [BlockResourceProvider](/core/data-block/data-block-resource-provider): 根据 `DataBlockProvider` 提供的上下文信息,构建区块 [Resource](https://docs.nocobase.com/api/sdk#resource-action) API,用于区块数据的增删改查 - [BlockRequestProvider](/core/data-block/data-block-request-provider): 根据 `DataBlockProvider` 提供的上下文信息,自动调用 `BlockResourceProvider` 提供的 `resource.get()` 或 `resource.list()` 发起请求,得到区块数据,并传递 - [CollectionRecordProvider](/core/data-source/record-provider): 对于 `resource.get()` 场景,会自动嵌套 `CollectionRecordProvider` 并将 `resource.get()` 请求结果传递下去,`resource.list()` 场景则需要自行使用 `CollectionRecordProvider` 提供数据记录 diff --git a/packages/core/client/docs/zh-CN/core/data-block/data-block-resource-provider.md b/packages/core/client/docs/zh-CN/core/data-block/data-block-resource-provider.md index 50178dc86fffe..e94246b6c7f87 100644 --- a/packages/core/client/docs/zh-CN/core/data-block/data-block-resource-provider.md +++ b/packages/core/client/docs/zh-CN/core/data-block/data-block-resource-provider.md @@ -1,6 +1,6 @@ # DataBlockResourceProvider -根据 `DataBlockProvider` 中的 `collection`、`association`、`sourceId` 等属性,构建好 [resource](/core/request) 对象,方便子组件对区块数据的增删改查操作,其内置在 [DataBlockProvider](/core/data-block/data-block-provider) 中 +根据 `DataBlockProvider` 中的 `collection`、`association`、`sourceId` 等属性,构建好 [resource](https://docs.nocobase.com/api/sdk#resource-action) 对象,方便子组件对区块数据的增删改查操作,其内置在 [DataBlockProvider](/core/data-block/data-block-provider) 中 ## useDataBlockResource diff --git a/packages/core/client/docs/zh-CN/core/request/demos/demo1.tsx b/packages/core/client/docs/zh-CN/core/request/demos/demo1.tsx deleted file mode 100644 index dbc18123d2848..0000000000000 --- a/packages/core/client/docs/zh-CN/core/request/demos/demo1.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { APIClient, APIClientProvider, compose, useRequest } from '@nocobase/client'; -import MockAdapter from 'axios-mock-adapter'; -import React from 'react'; - -const apiClient = new APIClient(); - -const mock = new MockAdapter(apiClient.axios); - -mock.onGet('/users:get').reply(200, { - data: { id: 1, name: 'John Smith' }, -}); - -const providers = [[APIClientProvider, { apiClient }]]; - -export default compose(...providers)(() => { - const { data } = useRequest<{ - data: any; - }>({ - resource: 'users', - action: 'get', - params: {}, - }); - return

{data?.data?.name}
; -}); diff --git a/packages/core/client/docs/zh-CN/core/request/demos/demo2.tsx b/packages/core/client/docs/zh-CN/core/request/demos/demo2.tsx deleted file mode 100644 index 823a5dbb41aae..0000000000000 --- a/packages/core/client/docs/zh-CN/core/request/demos/demo2.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { APIClient, APIClientProvider, compose, useRequest } from '@nocobase/client'; -import MockAdapter from 'axios-mock-adapter'; -import React from 'react'; - -const apiClient = new APIClient(); - -const mock = new MockAdapter(apiClient.axios); - -mock.onGet('/users:get').reply(200, { - data: { id: 1, name: 'John Smith' }, -}); - -const providers = [[APIClientProvider, { apiClient }]]; - -export default compose(...providers)(() => { - const { data } = useRequest<{ - data: any; - }>({ - url: 'users:get', - method: 'get', - }); - return
{data?.data?.name}
; -}); diff --git a/packages/core/client/docs/zh-CN/core/request/demos/demo3.tsx b/packages/core/client/docs/zh-CN/core/request/demos/demo3.tsx deleted file mode 100644 index d27bf0470f48c..0000000000000 --- a/packages/core/client/docs/zh-CN/core/request/demos/demo3.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { uid } from '@formily/shared'; -import { APIClient, APIClientProvider, useAPIClient, useRequest } from '@nocobase/client'; -import { Button, Input, Space, Table } from 'antd'; -import MockAdapter from 'axios-mock-adapter'; -import React from 'react'; - -const apiClient = new APIClient(); - -const mock = new MockAdapter(apiClient.axios); -const sleep = (value: number) => new Promise((resolve) => setTimeout(resolve, value)); - -mock.onGet('/users:list').reply(async () => { - await sleep(1000); - return [ - 200, - { - data: [ - { id: 1, name: uid() }, - { id: 2, name: uid() }, - ], - }, - ]; -}); - -const ComponentA = () => { - console.log('ComponentA'); - const { data, loading } = useRequest<{ - data: any; - }>( - { - url: 'users:list', - method: 'get', - }, - { - uid: 'test', // 当指定了 uid 的 useRequest 的结果,可以通过 api.service(uid) 获取 - }, - ); - return ( -
- ); -}; - -const ComponentB = () => { - console.log('ComponentB'); - const apiClient = useAPIClient(); - return ( - - - - - ); -}; - -export default () => { - return ( - - -
-
- -
- ); -}; diff --git a/packages/core/client/docs/zh-CN/core/request/index.md b/packages/core/client/docs/zh-CN/core/request/index.md deleted file mode 100644 index d442a201943fd..0000000000000 --- a/packages/core/client/docs/zh-CN/core/request/index.md +++ /dev/null @@ -1,167 +0,0 @@ -# APIClient - -## APIClient - -```ts -class APIClient { - // axios 实例 - axios: AxiosInstance; - // 缓存带 uid 的 useRequest({}, {uid}) 的结果,可供其他组件调用 - services: Record>; - // 构造器 - constructor(instance?: AxiosInstance | AxiosRequestConfig); - // 客户端请求,支持 AxiosRequestConfig 和 ResourceActionOptions - request, D = any>(config: AxiosRequestConfig | ResourceActionOptions): Promise; - // 获取资源 - resource(name: string, of?: any): R; -} -``` - -示例 - -```ts -import axios from 'axios'; - -// 不传参时,内部直接创建 axios 实例 -const apiClient = new APIClient(); - -// 提供 AxiosRequestConfig 配置参数 -const apiClient = new APIClient({ - baseURL: '', -}); - -// 提供 AxiosInstance -const instance = axios.create({ - baseURL: '', -}); -const apiClient = new APIClient(instance); - -// 常规请求 -const response = await apiClient.request({ url }); - -// NocoBase 特有的资源操作 -const response = await apiClient.resource('posts').list(); - -// 请求共享 -const { data, loading, run } = apiClient.service('uid'); -``` - -`api.service(uid)` 的例子,ComponentB 里刷新 ComponentA 的请求数据 - - - -## APIClientProvider - -提供 APIClient 实例的上下文。 - -```tsx | pure -const apiClient = new APIClient(); - - -``` - -## useAPIClient - -获取当前上下文的 APIClient 实例。 - -```ts -const apiClient = useAPIClient(); -``` - -## useRequest - -```ts -function useRequest

( - service: AxiosRequestConfig

| ResourceActionOptions

| FunctionService, - options?: Options, -); -``` - -支持 `axios.request(config)`,config 详情查看 [axios](https://github.com/axios/axios#request-config) - -```ts -const { data, loading, refresh, run, params } = useRequest({ url: '/users' }); - -// useRequest 里传的是 AxiosRequestConfig,所以 run 里传的也是 AxiosRequestConfig -run({ - params: { - pageSize: 20, - } -}); -``` - -例子如下: - - - -或者是 NocoBase 的 resource & action 请求: - -```ts -const { data, run } = useRequest({ - resource: 'users', - action: 'list', - params: { - pageSize: 20, - }, -}); - -// useRequest 传的是 ResourceActionOptions,所以 run 直接传 action params 就可以了。 -run({ - pageSize: 50, -}); -``` - -例子如下: - - - -也可以是自定义的异步函数: - -```ts -const { data, loading, run, refresh, params } = useRequest((...params) => Promise.resolve({})); - -run(...params); -``` - -更多用法查看 ahooks 的 [useRequest()](https://ahooks.js.org/hooks/use-request/index) - -## useResource - -```ts -function useResource(name: string, of?: string | number): IResource; -``` - -资源是 NocoBase 的核心概念,包括: - -- 独立资源,如 `posts` -- 关系资源,如 `posts.tags` `posts.user` `posts.comments` - -资源 URI - -```bash -# 独立资源,文章 -/api/posts -# 关系资源,文章 ID=1 的评论 -/api/posts/1/comments -``` - -通过 APIClient 获取资源 - -```ts -const api = new APIClient(); - -api.resource('posts'); -api.resource('posts.comments', 1); -``` - -useResource 用法: - -```ts -const resource = useResource('posts'); -const resource = useResource('posts.comments', 1); -``` - -resource 的实际场景用例参见: - -- [useCollection()](collection-manager#usecollection) -- [useCollectionField()](collection-manager#usecollectionfield) diff --git a/packages/core/client/src/api-client/index.md b/packages/core/client/src/api-client/index.md index 1804df06b2a7d..e4c67d46d3492 100644 --- a/packages/core/client/src/api-client/index.md +++ b/packages/core/client/src/api-client/index.md @@ -166,3 +166,8 @@ useResource 用法: const resource = useResource('posts'); const resource = useResource('posts.comments', 1); ``` + +resource 的实际场景用例参见: + +- [useCollection()](collection-manager#usecollection) +- [useCollectionField()](collection-manager#usecollectionfield) diff --git a/packages/core/client/src/application/__tests__/Application.test.tsx b/packages/core/client/src/application/__tests__/Application.test.tsx index cd371c4ec4c98..d9fe6919db1b9 100644 --- a/packages/core/client/src/application/__tests__/Application.test.tsx +++ b/packages/core/client/src/application/__tests__/Application.test.tsx @@ -377,7 +377,7 @@ describe('Application', () => { render(); await sleep(10); - expect(screen.getByText('App Error')).toBeInTheDocument(); + expect(screen.getByText('Load Plugin Error')).toBeInTheDocument(); }); it('replace Component', async () => { diff --git a/packages/core/client/src/application/components/defaultComponents.tsx b/packages/core/client/src/application/components/defaultComponents.tsx index b7983a775238c..9be8c2a48806a 100644 --- a/packages/core/client/src/application/components/defaultComponents.tsx +++ b/packages/core/client/src/application/components/defaultComponents.tsx @@ -5,7 +5,7 @@ const Loading: FC = () =>

Loading...
; const AppError: FC<{ error: Error }> = ({ error }) => { return (
-
App Error
+
Load Plugin Error
{error?.message} {process.env.__TEST__ && error?.stack}
diff --git a/packages/core/client/src/application/hoc/withDynamicSchemaProps.tsx b/packages/core/client/src/application/hoc/withDynamicSchemaProps.tsx index df7c0147595f3..2125216614029 100644 --- a/packages/core/client/src/application/hoc/withDynamicSchemaProps.tsx +++ b/packages/core/client/src/application/hoc/withDynamicSchemaProps.tsx @@ -9,10 +9,7 @@ interface WithSchemaHookOptions { displayName?: string; } -export function withDynamicSchemaProps( - Component: React.ComponentType, - options: WithSchemaHookOptions = {}, -) { +export function withDynamicSchemaProps(Component: any, options: WithSchemaHookOptions = {}) { const displayName = options.displayName || Component.displayName || Component.name; const ComponentWithProps: ComponentType = (props) => { const { dn, findComponent } = useDesignable(); diff --git a/packages/core/client/src/index.ts b/packages/core/client/src/index.ts index 7902e8dc27282..edf5dc1e28635 100644 --- a/packages/core/client/src/index.ts +++ b/packages/core/client/src/index.ts @@ -54,10 +54,10 @@ export * from './variables'; export { withDynamicSchemaProps } from './application/hoc/withDynamicSchemaProps'; export * from './modules/blocks/BlockSchemaToolbar'; +export * from './modules/blocks/data-blocks/details-multi/setDataLoadingModeSettingsItem'; export * from './modules/blocks/data-blocks/form'; export * from './modules/blocks/data-blocks/table'; export * from './modules/blocks/data-blocks/table-selector'; export * from './modules/blocks/useParentRecordCommon'; -export * from './modules/blocks/index'; export { DeclareVariable } from './modules/variable/DeclareVariable'; diff --git a/packages/core/client/src/modules/blocks/data-blocks/details-multi/hooks/index.ts b/packages/core/client/src/modules/blocks/data-blocks/details-multi/hooks/index.ts deleted file mode 100644 index 8e61dbd1871f1..0000000000000 --- a/packages/core/client/src/modules/blocks/data-blocks/details-multi/hooks/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './useDetailsWithPaginationBlockParams'; -export * from './useDetailsWithPaginationProps'; -export * from './useDetailsWithPaginationDecoratorProps'; diff --git a/packages/core/client/src/modules/blocks/data-blocks/details-multi/index.ts b/packages/core/client/src/modules/blocks/data-blocks/details-multi/index.ts deleted file mode 100644 index 8f95a33778fb2..0000000000000 --- a/packages/core/client/src/modules/blocks/data-blocks/details-multi/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './hooks'; -export * from './setDataLoadingModeSettingsItem'; diff --git a/packages/core/client/src/modules/blocks/data-blocks/details-single/hooks/index.ts b/packages/core/client/src/modules/blocks/data-blocks/details-single/hooks/index.ts deleted file mode 100644 index 85a5c57245e83..0000000000000 --- a/packages/core/client/src/modules/blocks/data-blocks/details-single/hooks/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './useDetailsDecoratorProps'; -export * from './useDetailsProps'; diff --git a/packages/core/client/src/modules/blocks/data-blocks/details-single/index.ts b/packages/core/client/src/modules/blocks/data-blocks/details-single/index.ts deleted file mode 100644 index 4cc90d02bd5a6..0000000000000 --- a/packages/core/client/src/modules/blocks/data-blocks/details-single/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './hooks'; diff --git a/packages/core/client/src/modules/blocks/data-blocks/table/index.ts b/packages/core/client/src/modules/blocks/data-blocks/table/index.ts index c708fd851874b..5b35a76b890b8 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/table/index.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/table/index.ts @@ -7,4 +7,3 @@ export * from './tableColumnSettings'; export * from './TableColumnInitializers'; export * from './createTableBlockUISchema'; export * from './hooks/useTableBlockDecoratorProps'; -export * from './hooks/useTableBlockProps'; diff --git a/packages/core/client/src/modules/blocks/index.ts b/packages/core/client/src/modules/blocks/index.ts deleted file mode 100644 index dece9dd13bba7..0000000000000 --- a/packages/core/client/src/modules/blocks/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './data-blocks/details-multi'; -export * from './data-blocks/details-single'; diff --git a/packages/core/client/src/schema-component/antd/action/Action.Drawer.tsx b/packages/core/client/src/schema-component/antd/action/Action.Drawer.tsx index 4efd10c93c128..0dbb6a04c7bf2 100644 --- a/packages/core/client/src/schema-component/antd/action/Action.Drawer.tsx +++ b/packages/core/client/src/schema-component/antd/action/Action.Drawer.tsx @@ -2,7 +2,7 @@ import { observer, RecursionField, useField, useFieldSchema } from '@formily/rea import { Drawer } from 'antd'; import classNames from 'classnames'; import React from 'react'; -import { OpenSize } from './types'; +import { OpenSize } from './'; import { useStyles } from './Action.Drawer.style'; import { useActionContext } from './hooks'; import { useSetAriaLabelForDrawer } from './hooks/useSetAriaLabelForDrawer'; diff --git a/packages/core/client/src/schema-component/antd/action/Action.Modal.tsx b/packages/core/client/src/schema-component/antd/action/Action.Modal.tsx index 402af7b7d8f71..781f7069da3fc 100644 --- a/packages/core/client/src/schema-component/antd/action/Action.Modal.tsx +++ b/packages/core/client/src/schema-component/antd/action/Action.Modal.tsx @@ -3,10 +3,10 @@ import { observer, RecursionField, useField, useFieldSchema } from '@formily/rea import { Modal, ModalProps } from 'antd'; import classNames from 'classnames'; import React from 'react'; +import { OpenSize, useActionContext } from '.'; import { useToken } from '../../../style'; import { useSetAriaLabelForModal } from './hooks/useSetAriaLabelForModal'; -import { ComposedActionDrawer, OpenSize } from './types'; -import { useActionContext } from './hooks'; +import { ComposedActionDrawer } from './types'; const openSizeWidthMap = new Map([ ['small', '40%'], diff --git a/packages/core/client/src/schema-component/antd/action/Action.Popover.tsx b/packages/core/client/src/schema-component/antd/action/Action.Popover.tsx new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/packages/core/client/src/schema-component/antd/action/Action.tsx b/packages/core/client/src/schema-component/antd/action/Action.tsx index 638cd35e3249e..cdafda05243d5 100644 --- a/packages/core/client/src/schema-component/antd/action/Action.tsx +++ b/packages/core/client/src/schema-component/antd/action/Action.tsx @@ -33,11 +33,11 @@ import useStyles from './Action.style'; import { ActionContextProvider } from './context'; import { useA } from './hooks'; import { useGetAriaLabelOfAction } from './hooks/useGetAriaLabelOfAction'; -import { ActionProps, ComposedAction } from './types'; +import { ComposedAction } from './types'; import { linkageAction, setInitialActionState } from './utils'; export const Action: ComposedAction = withDynamicSchemaProps( - observer((props: ActionProps) => { + observer((props: any) => { const { popover, confirm, @@ -50,7 +50,6 @@ export const Action: ComposedAction = withDynamicSchemaProps( title, onClick, style, - loading, openSize: os, disabled: propsDisabled, actionCallback, @@ -172,14 +171,14 @@ export const Action: ComposedAction = withDynamicSchemaProps( aria-label={getAriaLabel()} {...others} onMouseEnter={handleMouseEnter} - loading={field?.data?.loading || loading} + loading={field?.data?.loading} icon={icon ? : null} disabled={disabled} style={buttonStyle} onClick={handleButtonClick} component={tarComponent || Button} className={classnames(componentCls, hashId, className, 'nb-action')} - type={(props as any).type === 'danger' ? undefined : props.type} + type={props.type === 'danger' ? undefined : props.type} > {actionTitle} diff --git a/packages/core/client/src/schema-component/antd/action/ActionBar.tsx b/packages/core/client/src/schema-component/antd/action/ActionBar.tsx index 6fbf89f447a53..f7d39635c0678 100644 --- a/packages/core/client/src/schema-component/antd/action/ActionBar.tsx +++ b/packages/core/client/src/schema-component/antd/action/ActionBar.tsx @@ -1,6 +1,6 @@ import { cx } from '@emotion/css'; import { RecursionField, observer, useFieldSchema } from '@formily/react'; -import { Space, SpaceProps } from 'antd'; +import { Space } from 'antd'; import React, { CSSProperties, useContext } from 'react'; import { createPortal } from 'react-dom'; import { DndContext } from '../../common'; @@ -8,11 +8,10 @@ import { useDesignable, useProps } from '../../hooks'; import { useSchemaInitializerRender } from '../../../application'; import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps'; -export interface ActionBarProps { - layout?: 'one-column' | 'two-columns'; +interface ActionBarContextForceProps { + layout?: 'one-column' | 'tow-columns'; style?: CSSProperties; className?: string; - spaceProps?: SpaceProps; } export interface ActionBarContextValue { @@ -20,7 +19,7 @@ export interface ActionBarContextValue { /** * override props */ - forceProps?: ActionBarProps; + forceProps?: ActionBarContextForceProps; parentComponents?: string[]; } @@ -53,7 +52,7 @@ export const ActionBar = withDynamicSchemaProps( const { forceProps = {} } = useActionBarContext(); // 新版 UISchema(1.0 之后)中已经废弃了 useProps,这里之所以继续保留是为了兼容旧版的 UISchema - const { layout = 'two-columns', style, spaceProps, ...others } = { ...useProps(props), ...forceProps } as any; + const { layout = 'tow-columns', style, spaceProps, ...others } = { ...useProps(props), ...forceProps } as any; const fieldSchema = useFieldSchema(); const { render } = useSchemaInitializerRender(fieldSchema['x-initializer'], fieldSchema['x-initializer-props']); diff --git a/packages/core/client/src/schema-component/antd/action/context.tsx b/packages/core/client/src/schema-component/antd/action/context.tsx index fc4f0fc7aed91..e3f1d13873962 100644 --- a/packages/core/client/src/schema-component/antd/action/context.tsx +++ b/packages/core/client/src/schema-component/antd/action/context.tsx @@ -1,7 +1,8 @@ +import { Schema } from '@formily/react'; +import { DrawerProps, ModalProps } from 'antd'; import React, { createContext, useEffect, useRef, useState } from 'react'; import { useActionContext } from './hooks'; import { useDataBlockRequest } from '../../../data-source'; -import { ActionContextProps } from './types'; export const ActionContext = createContext({}); ActionContext.displayName = 'ActionContext'; @@ -36,3 +37,21 @@ export const ActionContextProvider: React.FC ); }; + +export type OpenSize = 'small' | 'middle' | 'large'; +export interface ActionContextProps { + button?: any; + visible?: boolean; + setVisible?: (v: boolean) => void; + openMode?: 'drawer' | 'modal' | 'page'; + snapshot?: boolean; + openSize?: OpenSize; + containerRefKey?: string; + formValueChanged?: boolean; + setFormValueChanged?: (v: boolean) => void; + fieldSchema?: Schema; + drawerProps?: DrawerProps; + modalProps?: ModalProps; + submitted?: boolean; + setSubmitted?: (v: boolean) => void; +} diff --git a/packages/core/client/src/schema-component/antd/action/demos/new-demos/action-container.tsx b/packages/core/client/src/schema-component/antd/action/demos/new-demos/action-container.tsx deleted file mode 100644 index 71dc9d92795b0..0000000000000 --- a/packages/core/client/src/schema-component/antd/action/demos/new-demos/action-container.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { useActionContext } from '@nocobase/client'; -import { getAppComponent } from '@nocobase/test/web'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - properties: { - test: { - type: 'void', - 'x-component': 'Action', - title: 'Open', - 'x-component-props': { - openMode: 'drawer', - }, - properties: { - drawer: { - type: 'void', - 'x-component': 'Action.Container', - title: 'Title', - properties: { - footer: { - type: 'void', - 'x-component': 'Action.Container.Footer', - properties: { - close: { - title: 'Close', - 'x-component': 'Action', - 'x-use-component-props': function useActionProps() { - const { setVisible } = useActionContext(); - return { - type: 'default', - onClick() { - setVisible(false); - }, - }; - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/action/demos/new-demos/action-context.tsx b/packages/core/client/src/schema-component/antd/action/demos/new-demos/action-context.tsx deleted file mode 100644 index bec1655bbe6b9..0000000000000 --- a/packages/core/client/src/schema-component/antd/action/demos/new-demos/action-context.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { ISchema, observer } from '@formily/react'; -import { - Action, - ActionContextProvider, - Form, - FormItem, - Input, - SchemaComponent, - SchemaComponentProvider, - useActionContext, -} from '@nocobase/client'; -import React, { useState } from 'react'; - -const schema: ISchema = { - type: 'object', - properties: { - drawer1: { - 'x-component': 'Action.Drawer', - type: 'void', - title: 'Drawer Title', - properties: { - hello1: { - 'x-content': 'Hello', - title: 'T1', - }, - footer1: { - 'x-component': 'Action.Drawer.Footer', - type: 'void', - properties: { - close1: { - title: 'Close', - 'x-component': 'Action', - 'x-use-component-props': function useActionProps() { - const { setVisible } = useActionContext(); - return { - onClick() { - setVisible(false); - }, - }; - }, - }, - }, - }, - }, - }, - }, -}; - -export default observer(() => { - const [visible, setVisible] = useState(false); - return ( - - - setVisible(true)}>Open - - - - ); -}); diff --git a/packages/core/client/src/schema-component/antd/action/demos/new-demos/action-link.tsx b/packages/core/client/src/schema-component/antd/action/demos/new-demos/action-link.tsx deleted file mode 100644 index 83ce03763c19f..0000000000000 --- a/packages/core/client/src/schema-component/antd/action/demos/new-demos/action-link.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - properties: { - test: { - type: 'void', - 'x-component': 'Action.Link', - title: 'Edit', - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/action/demos/new-demos/action-modal.tsx b/packages/core/client/src/schema-component/antd/action/demos/new-demos/action-modal.tsx deleted file mode 100644 index 8aede324d1cd0..0000000000000 --- a/packages/core/client/src/schema-component/antd/action/demos/new-demos/action-modal.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; -import { Space, App as AntdApp } from 'antd'; -import { useAPIClient, useActionContext } from '@nocobase/client'; -import { useForm } from '@formily/react'; - -const useCloseActionProps = () => { - const { setVisible } = useActionContext(); - return { - type: 'default', - onClick() { - setVisible(false); - }, - }; -}; - -const useSubmitActionProps = () => { - const { setVisible } = useActionContext(); - const api = useAPIClient(); - const { message } = AntdApp.useApp(); - const form = useForm(); - - return { - type: 'primary', - async onClick() { - // Submit the form - await form.submit(); - const values = form.values; - - console.log('values:', values); - const { data } = await api.request({ url: 'test', data: values, method: 'POST' }); - if (data.data === 'ok') { - message.success('Submit success'); - setVisible(false); - form.reset(); // 提交成功后重置表单 - } - }, - }; -}; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-component': Space, - properties: { - test: { - type: 'void', - 'x-component': 'Action', - title: 'Open Modal', - 'x-component-props': { - openSize: 'small', - }, - properties: { - drawer: { - type: 'void', - 'x-component': 'Action.Modal', - title: 'Modal Title', - 'x-decorator': 'FormV2', - properties: { - username: { - type: 'string', - title: `Username`, - required: true, - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - footer: { - type: 'void', - 'x-component': 'Action.Modal.Footer', - properties: { - close: { - title: 'Close', - 'x-component': 'Action', - 'x-component-props': { - type: 'default', - }, - 'x-use-component-props': 'useCloseActionProps', - }, - submit: { - title: 'Submit', - 'x-component': 'Action', - 'x-use-component-props': 'useSubmitActionProps', - }, - }, - }, - }, - }, - }, - }, - }, - }, - appOptions: { - scopes: { - useSubmitActionProps, - useCloseActionProps, - }, - }, - apis: { - test: { data: 'ok' }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/action/demos/new-demos/action-popover.tsx b/packages/core/client/src/schema-component/antd/action/demos/new-demos/action-popover.tsx deleted file mode 100644 index 89832901d7b9b..0000000000000 --- a/packages/core/client/src/schema-component/antd/action/demos/new-demos/action-popover.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - properties: { - test: { - 'x-component': 'Action', - 'x-component-props': { - type: 'primary', - popover: true, - }, - type: 'void', - title: 'Open', - properties: { - popover: { - type: 'void', - 'x-component': 'Action.Popover', - properties: { - hello: { - type: 'void', - 'x-content': 'Hello', - }, - }, - }, - }, - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/action/demos/new-demos/actionbar-one-column.tsx b/packages/core/client/src/schema-component/antd/action/demos/new-demos/actionbar-one-column.tsx deleted file mode 100644 index 89cb6e106dedf..0000000000000 --- a/packages/core/client/src/schema-component/antd/action/demos/new-demos/actionbar-one-column.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { ActionInitializer, SchemaInitializer } from '@nocobase/client'; -import { getAppComponent } from '@nocobase/test/web'; - -const addActionButton = new SchemaInitializer({ - name: 'addActionButton', - designable: true, - title: 'Configure actions', - style: { - marginLeft: 8, - }, - items: [ - { - type: 'itemGroup', - title: 'Enable actions', - name: 'enableActions', - children: [ - { - name: 'action1', - title: '{{t("Action 1")}}', - Component: 'ActionInitializer', - schema: { - title: 'Action 1', - 'x-component': 'Action', - 'x-action': 'a1', // unique identifier - }, - }, - { - name: 'action2', - title: '{{t("Action 2")}}', - Component: 'ActionInitializer', - schema: { - title: 'Action 2', - 'x-component': 'Action', - 'x-action': 'a2', // unique identifier - }, - }, - ], - }, - ], -}); - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - properties: { - test: { - type: 'void', - 'x-component': 'ActionBar', - 'x-initializer': 'addActionButton', - 'x-component-props': { - layout: 'one-column', - }, - properties: { - a1: { - title: 'Action 1', - 'x-component': 'Action', - 'x-action': 'a1', - }, - a2: { - title: 'Action 2', - 'x-component': 'Action', - 'x-action': 'a2', - }, - }, - }, - }, - }, - appOptions: { - schemaInitializers: [addActionButton], - components: { - ActionInitializer, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/action/demos/new-demos/actionbar-two-columns.tsx b/packages/core/client/src/schema-component/antd/action/demos/new-demos/actionbar-two-columns.tsx deleted file mode 100644 index 4dce2ac3a9c5a..0000000000000 --- a/packages/core/client/src/schema-component/antd/action/demos/new-demos/actionbar-two-columns.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import { ActionInitializer, SchemaInitializer } from '@nocobase/client'; -import { getAppComponent } from '@nocobase/test/web'; - -const addActionButton = new SchemaInitializer({ - name: 'addActionButton', - designable: true, - title: 'Configure actions', - style: { - marginLeft: 8, - }, - items: [ - { - type: 'itemGroup', - title: 'Enable actions', - name: 'enableActions', - children: [ - { - name: 'action1', - title: '{{t("Action 1")}}', - Component: 'ActionInitializer', - schema: { - title: 'Action 1', - 'x-component': 'Action', - 'x-action': 'a1', - 'x-align': 'left', - }, - }, - { - name: 'action2', - title: '{{t("Action 2")}}', - Component: 'ActionInitializer', - schema: { - title: 'Action 2', - 'x-component': 'Action', - 'x-action': 'a2', - 'x-align': 'right', - }, - }, - ], - }, - ], -}); - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - properties: { - test: { - type: 'void', - 'x-component': 'ActionBar', - 'x-initializer': 'addActionButton', - 'x-component-props': { - layout: 'two-columns', - }, - properties: { - a1: { - title: 'Action 1', - 'x-component': 'Action', - 'x-action': 'a1', - 'x-align': 'left', - }, - a2: { - title: 'Action 2', - 'x-component': 'Action', - 'x-action': 'a2', - 'x-align': 'right', - }, - }, - }, - }, - }, - appOptions: { - schemaInitializers: [addActionButton], - components: { - ActionInitializer, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/action/demos/new-demos/basic.tsx b/packages/core/client/src/schema-component/antd/action/demos/new-demos/basic.tsx deleted file mode 100644 index e2025dbfb5007..0000000000000 --- a/packages/core/client/src/schema-component/antd/action/demos/new-demos/basic.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - properties: { - test: { - type: 'void', - 'x-component': 'Action', - 'x-component-props': { - ghost: true, // ButtonProps - type: 'dashed', // ButtonProps - danger: true, // ButtonProps - title: 'Open', // title - }, - // title: 'Open', // It's also possible here - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/action/demos/new-demos/confirm.tsx b/packages/core/client/src/schema-component/antd/action/demos/new-demos/confirm.tsx deleted file mode 100644 index fb357752e4b42..0000000000000 --- a/packages/core/client/src/schema-component/antd/action/demos/new-demos/confirm.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; -import { Space, App as AntdApp } from 'antd'; -import { ActionProps } from '@nocobase/client'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-component': Space, - properties: { - test: { - type: 'void', - 'x-component': 'Action', - title: 'Delete', - 'x-use-component-props': function useActionProps(): ActionProps { - const { message } = AntdApp.useApp(); - - return { - confirm: { - // confirm props - title: 'Delete', - content: 'Are you sure you want to delete it?', - }, - onClick() { - // after confirm ok - message.success('Deleted!'); - }, - }; - }, - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/action/demos/new-demos/custom-component.tsx b/packages/core/client/src/schema-component/antd/action/demos/new-demos/custom-component.tsx deleted file mode 100644 index 44576f6d202d8..0000000000000 --- a/packages/core/client/src/schema-component/antd/action/demos/new-demos/custom-component.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; -import { Button, Space } from 'antd'; -import React from 'react'; - -const ComponentButton = (props) => { - return ; -}; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-component': Space, - properties: { - test1: { - type: 'void', - 'x-component': 'Action', - 'x-component-props': { - component: 'ComponentButton', // string type - }, - }, - test2: { - type: 'void', - 'x-component': 'Action', - 'x-component-props': { - component: ComponentButton, // ComponentType type - }, - }, - }, - }, - appOptions: { - components: { - ComponentButton, // register custom component - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/action/demos/new-demos/drawer-basic.tsx b/packages/core/client/src/schema-component/antd/action/demos/new-demos/drawer-basic.tsx deleted file mode 100644 index f56e96e94e1f5..0000000000000 --- a/packages/core/client/src/schema-component/antd/action/demos/new-demos/drawer-basic.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; -import { Space } from 'antd'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-component': Space, - properties: { - test: { - type: 'void', - 'x-component': 'Action', - title: 'Open Drawer', - properties: { - drawer: { - type: 'void', - 'x-component': 'Action.Drawer', - title: 'Drawer Title', - }, - }, - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/action/demos/new-demos/drawer-footer.tsx b/packages/core/client/src/schema-component/antd/action/demos/new-demos/drawer-footer.tsx deleted file mode 100644 index ec41e92455bd1..0000000000000 --- a/packages/core/client/src/schema-component/antd/action/demos/new-demos/drawer-footer.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; -import { Space } from 'antd'; -import { useActionContext } from '@nocobase/client'; - -const useCloseActionProps = () => { - const { setVisible } = useActionContext(); - return { - type: 'default', - onClick() { - setVisible(false); - }, - }; -}; - -const useSubmitActionProps = () => { - const { setVisible } = useActionContext(); - return { - type: 'primary', - onClick() { - console.log('submit'); - setVisible(false); - }, - }; -}; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-component': Space, - properties: { - test: { - type: 'void', - 'x-component': 'Action', - title: 'Open Drawer', - properties: { - drawer: { - type: 'void', - 'x-component': 'Action.Drawer', - title: 'Drawer Title', - properties: { - content: { - type: 'void', - 'x-content': 'Hello', - }, - footer: { - type: 'void', - 'x-component': 'Action.Drawer.Footer', // must be `Action.Drawer.Footer` - properties: { - close: { - title: 'Close', - 'x-component': 'Action', - 'x-use-component-props': 'useCloseActionProps', - }, - submit: { - title: 'Submit', - 'x-component': 'Action', - 'x-use-component-props': 'useSubmitActionProps', - }, - }, - }, - }, - }, - }, - }, - }, - }, - appOptions: { - scopes: { - useCloseActionProps, - useSubmitActionProps, - }, - }, - apis: { - test: { data: 'ok' }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/action/demos/new-demos/drawer-openSize.tsx b/packages/core/client/src/schema-component/antd/action/demos/new-demos/drawer-openSize.tsx deleted file mode 100644 index 7a1be043ab193..0000000000000 --- a/packages/core/client/src/schema-component/antd/action/demos/new-demos/drawer-openSize.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; -import { Space } from 'antd'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-component': Space, - properties: { - test: { - type: 'void', - 'x-component': 'Action', - title: 'Open Drawer', - 'x-component-props': { - openSize: 'large', // open drawer size - }, - properties: { - drawer: { - type: 'void', - title: 'Drawer Title', - 'x-component': 'Action.Drawer', - properties: { - // Drawer content - hello: { - type: 'void', - 'x-content': 'Hello', - }, - }, - }, - }, - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/action/demos/new-demos/drawer-with-form.tsx b/packages/core/client/src/schema-component/antd/action/demos/new-demos/drawer-with-form.tsx deleted file mode 100644 index aec8eade748c8..0000000000000 --- a/packages/core/client/src/schema-component/antd/action/demos/new-demos/drawer-with-form.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; -import { Space, App as AntdApp } from 'antd'; -import { useAPIClient, useActionContext } from '@nocobase/client'; -import { useForm } from '@formily/react'; - -const useCloseActionProps = () => { - const { setVisible } = useActionContext(); - return { - type: 'default', - onClick() { - setVisible(false); - }, - }; -}; - -const useSubmitActionProps = () => { - const { setVisible } = useActionContext(); - const api = useAPIClient(); - const { message } = AntdApp.useApp(); - const form = useForm(); - - return { - type: 'primary', - async onClick() { - // Submit the form - await form.submit(); - const values = form.values; - - console.log('values:', values); - const { data } = await api.request({ url: 'test', data: values, method: 'POST' }); - if (data.data === 'ok') { - message.success('Submit success'); - setVisible(false); - form.reset(); // 提交成功后重置表单 - } - }, - }; -}; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-component': Space, - properties: { - test: { - type: 'void', - 'x-component': 'Action', - title: 'Open Drawer', - properties: { - drawer: { - type: 'void', - 'x-component': 'Action.Drawer', - title: 'Drawer Title', - 'x-decorator': 'FormV2', // This uses the `FormV2` component. - properties: { - username: { - // This is a form field. - type: 'string', - title: `Username`, - required: true, - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - footer: { - type: 'void', - 'x-component': 'Action.Drawer.Footer', - properties: { - close: { - title: 'Close', - 'x-component': 'Action', - 'x-component-props': { - type: 'default', - }, - 'x-use-component-props': 'useCloseActionProps', - }, - submit: { - title: 'Submit', - 'x-component': 'Action', - 'x-use-component-props': 'useSubmitActionProps', - }, - }, - }, - }, - }, - }, - }, - }, - }, - appOptions: { - scopes: { - useSubmitActionProps, - useCloseActionProps, - }, - }, - apis: { - test: { data: 'ok' }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/action/demos/new-demos/dynamic-props.tsx b/packages/core/client/src/schema-component/antd/action/demos/new-demos/dynamic-props.tsx deleted file mode 100644 index 441fa8b77e485..0000000000000 --- a/packages/core/client/src/schema-component/antd/action/demos/new-demos/dynamic-props.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; -import { Space, App as AntdApp } from 'antd'; -import { useAPIClient, ActionProps } from '@nocobase/client'; - -const useCustomActionProps = (): ActionProps => { - const api = useAPIClient(); - const { message } = AntdApp.useApp(); - - return { - onClick: async () => { - const { data } = await api.request({ url: 'test' }); - if (data.data.result === 'ok') { - message.success('Success!'); - } - }, - }; -}; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-component': Space, - properties: { - test1: { - type: 'void', - 'x-component': 'Action', - title: 'test1', - 'x-use-component-props': useCustomActionProps, // function type - }, - test2: { - type: 'void', - 'x-component': 'Action', - title: 'test2', - 'x-use-component-props': function useCustomActionProps(): ActionProps { - // inline function type - const api = useAPIClient(); - const { message } = AntdApp.useApp(); - - return { - onClick: async () => { - const { data } = await api.request({ url: 'test' }); - if (data.data.result === 'ok') { - message.success('Success!'); - } - }, - }; - }, - }, - test3: { - type: 'void', - 'x-component': 'Action', - title: 'test2', - 'x-use-component-props': 'useCustomActionProps', // string type - }, - }, - }, - appOptions: { - scopes: { - useCustomActionProps, - }, - }, - apis: { - test: { data: { result: 'ok' } }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/action/demos/new-demos/schema-toolbar.tsx b/packages/core/client/src/schema-component/antd/action/demos/new-demos/schema-toolbar.tsx deleted file mode 100644 index 17d65644d9462..0000000000000 --- a/packages/core/client/src/schema-component/antd/action/demos/new-demos/schema-toolbar.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { SchemaSettings } from '@nocobase/client'; -import { getAppComponent } from '@nocobase/test/web'; - -const myActionSettings = new SchemaSettings({ - name: 'myActionSettings', - items: [ - { - name: 'delete', - type: 'remove', - }, - ], -}); - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - properties: { - test: { - type: 'void', - 'x-component': 'ActionBar', - 'x-component-props': { - layout: 'two-columns', - }, - properties: { - a1: { - title: 'Action 1', - 'x-component': 'Action', - 'x-action': 'a1', - 'x-align': 'right', - 'x-settings': 'myActionSettings', - }, - a2: { - title: 'Action 2', - 'x-component': 'Action', - 'x-action': 'a2', - 'x-align': 'right', - 'x-settings': 'myActionSettings', - }, - a3: { - title: 'Action 3', - 'x-component': 'Action', - 'x-action': 'a1', - 'x-align': 'left', - 'x-settings': 'myActionSettings', - }, - a4: { - title: 'Action 4', - 'x-component': 'Action', - 'x-action': 'a2', - 'x-align': 'left', - 'x-settings': 'myActionSettings', - }, - }, - }, - }, - }, - appOptions: { - schemaSettings: [myActionSettings], - }, - designable: true, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/action/index.md b/packages/core/client/src/schema-component/antd/action/index.md index d1c99547ed142..490c1339b2faf 100644 --- a/packages/core/client/src/schema-component/antd/action/index.md +++ b/packages/core/client/src/schema-component/antd/action/index.md @@ -1,206 +1,46 @@ -# Action - -将按钮和各种操作结合在一起,提供了一种统一的方式来处理操作。 - -## Action - -操作的触发器,默认是 ant-design 的 `Button` 组件,并为后续的弹窗或者抽屉提供上下文。 - -```ts -export interface ActionProps extends ButtonProps { - /** - * button title - */ - title?: string; - - /** - * custom component, replace the default Button component - */ - component?: string | ComponentType; - - /** - * Dynamic rendering of the opened content in conjunction with `Action.Container`. - */ - openMode?: 'drawer' | 'modal' | 'page'; - /** - * The size of the pop-up window, only valid when `openMode: 'modal'` - */ - openSize?: 'small' | 'middle' | 'large'; - /** - * Customize the position of the pop-up window - */ - containerRefKey?: string; - - /** - * Whether to display the popover, only valid when `openMode: 'popover'` - */ - popover?: boolean; - - /** - * When the button is clicked, whether a pop-up confirmation is required - */ - confirm?: false | { - title: string; - content: string; - }; -} -``` - -### Basic Usage - -- `ButtonProp` -- title - - - -### Custom Component - -- component - - - -### Dynamic Props - -这里使用了 `x-use-component-props` 的能力,具体可以查看 [x-use-component-props](https://docs.nocobase.com/development/client/ui-schema/what-is-ui-schema#x-component-props-%E5%92%8C-x-use-component-props)。 - - - -### Confirm - -- confirm - - - -## Action.Link - -将 `Button` 组件替换为 `a` 标签。 - - - -## Action.Drawer - -主要用于在右侧弹出一个抽屉。 - -```ts -interface ActionDrawer extends DrawerProps {} -``` - -### Basic Usage +--- +group: + title: Schema Components + order: 3 +--- -- `DrawerProps` - - - -### openSize - - - -### Footer - -Footer 可以放一些按钮,比如取消或者提交等。 - -其 Schema `x-component` 必须为 `Action.Drawer.Footer` 组件。 - - - -### With Form - - - -## Action.Modal - -```ts -interface ActionModal extends ModalProps {} -``` - -其用法和 `Action.Drawer` 类似,这里只举一个例子。 - - - -## Action.Popover - -注意,此时 Action 的 `popover` 属性必须为 `true`。 - - - -## Action.Container - -当根据需要动态渲染内容时,可以使用 `Action.Container` + Action `openMode` 属性动态决定。 - - - -## ActionBar - -一般用于区块的顶部的操作按钮,其内部会自动处理布局和渲染 [schema-initializer](/core/ui-schema/schema-initializer)。 - -```ts -import { SpaceProps } from 'antd' - -interface ActionBarProps { - layout?: 'one-column' | 'two-columns'; - style?: CSSProperties; - className?: string; - spaceProps?: SpaceProps; -} -``` - -### one-column - -一列布局,全部靠左。 - -Schema 中的 `x-action` 是按钮的唯一标识,不能和已有的重复,用于 `ActionInitializer` 的查找和删除。 - - +# Action -### two-columns +## Nodes -左右布局,通过 `x-align` 控制。 +- Action +- Action.Drawer +- Action.Drawer.Footer +- Action.Modal +- Action.Modal.Footer +- Action.Drawer +- Action.Drawer.Footer +- Action.Container +- Action.Container.Footer +- ActionBar - +## Examples -## ActionContext +### Action + Action.Drawer -封装在 `Action` 组件内部,用于传递上下文。 + -```ts -export type OpenSize = 'small' | 'middle' | 'large'; -export interface ActionContextProps { - button?: React.JSX.Element; - visible?: boolean; - setVisible?: (v: boolean) => void; - openMode?: 'drawer' | 'modal' | 'page'; - snapshot?: boolean; - openSize?: OpenSize; - /** - * Customize the position of the pop-up window - */ - containerRefKey?: string; - formValueChanged?: boolean; - setFormValueChanged?: (v: boolean) => void; - fieldSchema?: Schema; - drawerProps?: DrawerProps; - modalProps?: ModalProps; - submitted?: boolean; - setSubmitted?: (v: boolean) => void; -} -``` +### ActionContext + Action.Drawer -假设 Action 组件无法满足需求,我们可以直接使用 ActionContext 组件进行自定义。 +只配置 Action.Drawer,而不需要 Action,结合 ActionContext 自定义按钮。 - + -## ActionSchemaToolbar +### 不同的打开方式 -用于单个按钮渲染 [SchemaToolbar](/core/ui-schema/schema-toolbar) 和 [SchemaSettings](/core/ui-schema/schema-settings)。 + - +### Action + Action.Popover -## Hooks + -### useActionContext() + -获取 `ActionContext` 上下文。 +### ActionBar -```ts -const { visible, setVisible, fieldSchema } = useActionContext(); -``` + diff --git a/packages/core/client/src/schema-component/antd/action/index.tsx b/packages/core/client/src/schema-component/antd/action/index.tsx index 030ae7c5e86b7..360304a157489 100644 --- a/packages/core/client/src/schema-component/antd/action/index.tsx +++ b/packages/core/client/src/schema-component/antd/action/index.tsx @@ -7,4 +7,3 @@ export * from './hooks/useGetAriaLabelOfDrawer'; export * from './hooks/useGetAriaLabelOfModal'; export * from './hooks/useGetAriaLabelOfPopover'; export * from './Action.Designer'; -export * from './types'; diff --git a/packages/core/client/src/schema-component/antd/action/types.ts b/packages/core/client/src/schema-component/antd/action/types.ts index ade4e031ea007..1049d6bb4b8ab 100644 --- a/packages/core/client/src/schema-component/antd/action/types.ts +++ b/packages/core/client/src/schema-component/antd/action/types.ts @@ -1,77 +1,12 @@ import { ButtonProps, DrawerProps, ModalProps } from 'antd'; -import { ComponentType } from 'react'; -import { Schema } from '@formily/react'; -export type OpenSize = 'small' | 'middle' | 'large'; -export interface ActionContextProps { - button?: React.JSX.Element; - visible?: boolean; - setVisible?: (v: boolean) => void; - openMode?: 'drawer' | 'modal' | 'page'; - snapshot?: boolean; - openSize?: OpenSize; - /** - * Customize the position of the pop-up window - */ - containerRefKey?: string; - formValueChanged?: boolean; - setFormValueChanged?: (v: boolean) => void; - fieldSchema?: Schema; - drawerProps?: DrawerProps; - modalProps?: ModalProps; - submitted?: boolean; - setSubmitted?: (v: boolean) => void; -} - -export type UseActionType = (callback?: () => void) => { - run: () => void | Promise; +export type ActionProps = ButtonProps & { + component?: any; + useAction?: () => { + run(): Promise; + }; }; -export interface ActionProps extends ButtonProps { - /** - * button title - */ - title?: string; - - /** - * custom component, replace the default Button component - */ - component?: string | ComponentType; - - openMode?: ActionContextProps['openMode']; - openSize?: ActionContextProps['openSize']; - containerRefKey?: ActionContextProps['containerRefKey']; - - /** - * Whether to display the popover, only valid when `openMode: 'popover'` - */ - popover?: boolean; - - /** - * When the button is clicked, whether a pop-up confirmation is required - */ - confirm?: - | false - | { - title: string; - content: string; - }; - - /** - * @deprecated - */ - useAction?: string | UseActionType; - /** - * @deprecated - */ - actionCallback?: () => void; - - /** - * @internal - */ - addChild?: boolean; -} - export type ComposedAction = React.FC & { Drawer?: ComposedActionDrawer; [key: string]: any; diff --git a/packages/core/client/src/schema-component/antd/association-select/demos/new-demos/basic.tsx b/packages/core/client/src/schema-component/antd/association-select/demos/new-demos/basic.tsx deleted file mode 100644 index bae26987f2f5a..0000000000000 --- a/packages/core/client/src/schema-component/antd/association-select/demos/new-demos/basic.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'FormV2', - 'x-component': 'ShowFormData', - properties: { - test: { - type: 'string', - title: 'Test', - 'x-decorator': 'FormItem', - 'x-component': 'AssociationSelect', - 'x-component-props': { - service: { - resource: 'roles', // roles 表 - action: 'list', // 列表接口 - }, - fieldNames: { - label: 'title', // 显示的字段 - value: 'name', // 值字段 - }, - }, - }, - }, - }, - delayResponse: 500, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/association-select/demos/new-demos/multiple.tsx b/packages/core/client/src/schema-component/antd/association-select/demos/new-demos/multiple.tsx deleted file mode 100644 index da678a00b755e..0000000000000 --- a/packages/core/client/src/schema-component/antd/association-select/demos/new-demos/multiple.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'FormV2', - 'x-component': 'ShowFormData', - properties: { - test: { - type: 'array', // 数组类型 - title: 'Test', - 'x-decorator': 'FormItem', - 'x-component': 'AssociationSelect', - 'x-component-props': { - multiple: true, // 多选 - service: { - resource: 'roles', - action: 'list', - }, - fieldNames: { - label: 'title', - value: 'name', - }, - }, - }, - }, - }, - delayResponse: 500, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/association-select/demos/new-demos/read-pretty.tsx b/packages/core/client/src/schema-component/antd/association-select/demos/new-demos/read-pretty.tsx deleted file mode 100644 index 39fedfdb6e6a6..0000000000000 --- a/packages/core/client/src/schema-component/antd/association-select/demos/new-demos/read-pretty.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'FormV2', - 'x-component': 'ShowFormData', - properties: { - test: { - type: 'string', - title: 'Test', - default: 'admin', - 'x-decorator': 'FormItem', - 'x-component': 'AssociationSelect', - 'x-pattern': 'readPretty', - 'x-component-props': { - service: { - resource: 'roles', - action: 'list', - }, - fieldNames: { - label: 'title', - value: 'name', - }, - }, - }, - }, - }, - delayResponse: 500, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/association-select/index.md b/packages/core/client/src/schema-component/antd/association-select/index.md index 6b425a6a9cd0e..3b63d043c3418 100644 --- a/packages/core/client/src/schema-component/antd/association-select/index.md +++ b/packages/core/client/src/schema-component/antd/association-select/index.md @@ -1,24 +1,27 @@ -# AssociationSelect - -通过指定数据表和字段,获取数据表的数据。 - -```ts -type AssociationSelectProps

= RemoteSelectProps

& { - action?: string; - multiple?: boolean; -}; -``` +--- +group: + title: Schema Components + order: 3 +--- -## Basic Usage +# AssociationSelect - +## Examples -## Multiple Selection + -`type` 需要改为 `array`,并且属性需要增加 `multiple: true`。 +## API - +基于 Ant Design 的 [Select](https://ant.design/components/select/#API),相关扩展属性有: -## Read Pretty +- `objectValue` 值为 object 类型 +- `fieldNames` 默认值有区别 - +```ts +export const defaultFieldNames = { + label: 'label', + value: 'value', + color: 'color', + options: 'children', +}; +``` diff --git a/packages/core/client/src/schema-component/antd/block-item/BlockItem.tsx b/packages/core/client/src/schema-component/antd/block-item/BlockItem.tsx index 2e1333d930736..172b357c4a34f 100644 --- a/packages/core/client/src/schema-component/antd/block-item/BlockItem.tsx +++ b/packages/core/client/src/schema-component/antd/block-item/BlockItem.tsx @@ -58,13 +58,7 @@ const useStyles = createStyles(({ css, token }: CustomCreateStylesUtils) => { `; }); -export interface BlockItemProps { - name?: string; - className?: string; - children?: React.ReactNode; -} - -export const BlockItem: React.FC = withDynamicSchemaProps( +export const BlockItem: React.FC = withDynamicSchemaProps( (props) => { // 新版 UISchema(1.0 之后)中已经废弃了 useProps,这里之所以继续保留是为了兼容旧版的 UISchema const { className, children } = useProps(props); diff --git a/packages/core/client/src/schema-component/antd/block-item/demos/new-demos/basic.tsx b/packages/core/client/src/schema-component/antd/block-item/demos/new-demos/basic.tsx deleted file mode 100644 index 55a8937cf7b7a..0000000000000 --- a/packages/core/client/src/schema-component/antd/block-item/demos/new-demos/basic.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; -import { DragHandler, SchemaSettings } from '@nocobase/client'; -import { useFieldSchema } from '@formily/react'; -import { observer } from '@formily/reactive-react'; -import React from 'react'; - -const simpleSettings = new SchemaSettings({ - name: 'simpleSettings', - items: [ - { - name: 'delete', - type: 'remove', - }, - ], -}); - -const MyBlock = observer( - () => { - const fieldSchema = useFieldSchema(); - return ( -

- {fieldSchema.name} - -
- ); - }, - { displayName: 'MyBlock' }, -); - -const App = getAppComponent({ - designable: true, - schema: { - type: 'void', - name: 'root', - 'x-component': 'DndContext', - properties: { - block1: { - type: 'void', - 'x-decorator': 'BlockItem', - 'x-component': 'MyBlock', - 'x-settings': 'simpleSettings', - }, - block2: { - type: 'void', - 'x-decorator': 'BlockItem', - 'x-component': 'MyBlock', - 'x-settings': 'simpleSettings', - }, - block3: { - type: 'void', - 'x-decorator': 'BlockItem', - 'x-component': 'MyBlock', - 'x-settings': 'simpleSettings', - }, - }, - }, - appOptions: { - schemaSettings: [simpleSettings], - components: { - MyBlock, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/block-item/index.md b/packages/core/client/src/schema-component/antd/block-item/index.md index 842def429dffd..c2f97b4ffe822 100644 --- a/packages/core/client/src/schema-component/antd/block-item/index.md +++ b/packages/core/client/src/schema-component/antd/block-item/index.md @@ -1,22 +1,11 @@ -# BlockItem - -普通的装饰器(Decorator)组件,无 UI 效果,一般用在 `x-decorator` 中。 - -主要提供了以下 2 个能力: +--- +group: + title: Schema Components + order: 3 +--- -- 拖拽功能 -- [SchemaToolbar](/core/ui-schema/schema-toolbar) 和 [SchemaSettings](/core/ui-schema/schema-settings) 的渲染 - -[CardItem](/components/card-item) 和 [FormItem](/components/form-item) 组件都是基于 BlockItem 实现,也具备以上相同功能。 - -```ts -interface BlockItemProps { - name?: string; - className?: string; - children?: React.ReactNode; -} -``` +# BlockItem -注意拖拽功能需要配置 `DndContext` 组件。 +普通的装饰器(Decorator)组件,无特殊 UI 效果,一般用在 x-decorator 中。用于提供区块的管理,如拖拽功能、当前节点的 SettingsForm。CardItem 和 FormItem 组件都是基于 BlockItem 实现,也具备以上相同功能。 - + diff --git a/packages/core/client/src/schema-component/antd/card-item/CardItem.tsx b/packages/core/client/src/schema-component/antd/card-item/CardItem.tsx index 495db07ea32ab..9cca65d1e3f1e 100644 --- a/packages/core/client/src/schema-component/antd/card-item/CardItem.tsx +++ b/packages/core/client/src/schema-component/antd/card-item/CardItem.tsx @@ -1,36 +1,30 @@ import { useFieldSchema } from '@formily/react'; -import { Skeleton, CardProps } from 'antd'; -import React, { FC } from 'react'; -import { IntersectionOptions, useInView } from 'react-intersection-observer'; +import { Skeleton } from 'antd'; +import React from 'react'; +import { useInView } from 'react-intersection-observer'; import { useSchemaTemplate } from '../../../schema-templates'; import { BlockItem } from '../block-item'; import { BlockItemCard } from '../block-item/BlockItemCard'; import { BlockItemError } from '../block-item/BlockItemError'; import useStyles from './style'; -interface CardItemProps extends CardProps { - name?: string; +interface Props { children?: React.ReactNode; - /** - * lazy render options - * @default { threshold: 0, initialInView: true, triggerOnce: true } - * @see https://github.com/thebuilder/react-intersection-observer - */ - lazyRender?: IntersectionOptions & { element?: React.JSX.Element }; + /** 区块标识 */ + name?: string; + [key: string]: any; } -export const CardItem: FC = (props) => { - const { children, name, lazyRender = {}, ...restProps } = props; +export const CardItem = (props: Props) => { + const { children, name, ...restProps } = props; const template = useSchemaTemplate(); const fieldSchema = useFieldSchema(); const templateKey = fieldSchema?.['x-template-key']; - const { element: lazyRenderElement, ...resetLazyRenderOptions } = lazyRender; const { ref, inView } = useInView({ threshold: 0, initialInView: true, triggerOnce: true, skip: !!process.env.__E2E__, - ...resetLazyRenderOptions, }); const { wrapSSR, componentCls, hashId } = useStyles(); @@ -39,7 +33,7 @@ export const CardItem: FC = (props) => { - {inView ? props.children : lazyRenderElement ?? } + {inView ? props.children : } , diff --git a/packages/core/client/src/schema-component/antd/card-item/demos/new-demos/basic.tsx b/packages/core/client/src/schema-component/antd/card-item/demos/new-demos/basic.tsx deleted file mode 100644 index 0fcaaccba3a5e..0000000000000 --- a/packages/core/client/src/schema-component/antd/card-item/demos/new-demos/basic.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; -import { SchemaSettings } from '@nocobase/client'; - -const simpleSettings = new SchemaSettings({ - name: 'simpleSettings', - items: [ - { - name: 'delete', - type: 'remove', - }, - ], -}); - -const App = getAppComponent({ - designable: true, - schema: { - type: 'void', - name: 'root', - 'x-component': 'DndContext', - properties: { - block1: { - type: 'void', - 'x-component': 'CardItem', - 'x-component-props': { - title: 'Block 1', - }, - 'x-settings': 'simpleSettings', - properties: { - hello: { - type: 'void', - 'x-component': 'div', - 'x-content': 'Hello Card!', - }, - }, - }, - block2: { - type: 'void', - 'x-component': 'CardItem', - 'x-settings': 'simpleSettings', - 'x-component-props': { - title: 'Block 2', - }, - properties: { - hello: { - type: 'void', - 'x-component': 'div', - 'x-content': 'Hello Card!', - }, - }, - }, - }, - }, - appOptions: { - schemaSettings: [simpleSettings], - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/card-item/demos/new-demos/lazy-render.tsx b/packages/core/client/src/schema-component/antd/card-item/demos/new-demos/lazy-render.tsx deleted file mode 100644 index e050ed30742e2..0000000000000 --- a/packages/core/client/src/schema-component/antd/card-item/demos/new-demos/lazy-render.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; -import { SchemaSettings } from '@nocobase/client'; - -const simpleSettings = new SchemaSettings({ - name: 'simpleSettings', - items: [ - { - name: 'delete', - type: 'remove', - }, - ], -}); - -const App = getAppComponent({ - designable: true, - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'DndContext', - 'x-component': 'div', - 'x-component-props': { - style: { - height: 300, - overflow: 'auto', - border: '1px solid #f0f0f0', - }, - }, - properties: { - block1: { - type: 'void', - 'x-component': 'CardItem', - 'x-component-props': { - title: 'Block 1', - }, - 'x-settings': 'simpleSettings', - properties: { - hello: { - type: 'void', - 'x-component': 'div', - 'x-content': 'Hello Card!', - }, - }, - }, - block2: { - type: 'void', - 'x-component': 'CardItem', - 'x-settings': 'simpleSettings', - 'x-component-props': { - title: 'Block 2', - }, - properties: { - hello: { - type: 'void', - 'x-component': 'div', - 'x-content': 'Hello Card!', - }, - }, - }, - block3: { - type: 'void', - 'x-component': 'CardItem', - 'x-settings': 'simpleSettings', - 'x-component-props': { - title: 'Block 3', - lazyRender: { - threshold: 1, - }, - }, - properties: { - hello: { - type: 'void', - 'x-component': 'div', - 'x-content': 'Hello Card!', - }, - }, - }, - }, - }, - appOptions: { - schemaSettings: [simpleSettings], - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/card-item/index.md b/packages/core/client/src/schema-component/antd/card-item/index.md index 78b426912d6c5..29a0ec13e8485 100644 --- a/packages/core/client/src/schema-component/antd/card-item/index.md +++ b/packages/core/client/src/schema-component/antd/card-item/index.md @@ -1,27 +1,13 @@ -# CardItem - -卡片装饰器。主要功能为: - -- 拖拽和 [SchemaToolbar](/core/ui-schema/schema-toolbar) 和 [SchemaSettings](/core/ui-schema/schema-settings) 的渲染,继承自[BlockItem](/components/block-item) -- 懒渲染 +--- +group: + title: Schema Components + order: 3 +--- -其基于 ant-design [Card](https://ant.design/components/card-cn/) 组件进行封装,懒加载基于 [react-intersection-observer](https://github.com/thebuilder/react-intersection-observer) 实现。 - -```ts -interface CardItemProps extends CardProps { - name?: string; - /** - * lazy render options - * @see https://github.com/thebuilder/react-intersection-observer - */ - lazyRender?: IntersectionOptions; -} -``` - -## Basic +# CardItem - +卡片装饰器。除此之外,也继承了 BlockItem 的功能。 -## Custom lazy render +## Example - + diff --git a/packages/core/client/src/schema-component/antd/cascader/Cascader.tsx b/packages/core/client/src/schema-component/antd/cascader/Cascader.tsx index ed3b82b6d4ed1..f5dccc375dfa7 100644 --- a/packages/core/client/src/schema-component/antd/cascader/Cascader.tsx +++ b/packages/core/client/src/schema-component/antd/cascader/Cascader.tsx @@ -2,139 +2,107 @@ import { LoadingOutlined } from '@ant-design/icons'; import { ArrayField } from '@formily/core'; import { connect, mapProps, mapReadPretty, useField } from '@formily/react'; import { toArr } from '@formily/shared'; -import { Cascader as AntdCascader, Space, CascaderProps as AntdCascaderProps } from 'antd'; +import { Cascader as AntdCascader, Space } from 'antd'; import { isBoolean, omit } from 'lodash'; import React from 'react'; -import { UseRequestResult, useRequest } from '../../../api-client'; +import { useRequest } from '../../../api-client'; import { ReadPretty } from './ReadPretty'; import { defaultFieldNames } from './defaultFieldNames'; -import { BaseOptionType } from 'antd/es/select'; -import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps'; -const useDefDataSource = (options, props: any) => { +const useDefDataSource = (options) => { const field = useField(); - return useRequest(() => Promise.resolve({ data: field.dataSource || props.options || [] }), { - ...options, - refreshDeps: [field.dataSource, props.options], - }); + return useRequest(() => Promise.resolve({ data: field.dataSource || [] }), options); }; const useDefLoadData = (props: any) => { return props?.loadData; }; -export type CascaderProps = AntdCascaderProps & { - /** - * @deprecated use `x-use-component-props` instead - */ - useLoadData: (props: CascaderProps) => AntdCascaderProps['loadData']; - /** - * @deprecated use `x-use-component-props` instead - */ - useDataSource?: (options: any) => UseRequestResult; - /** - * Whether to wrap the label of option into the value - */ - labelInValue?: boolean; - /** - * must select the last level - */ - changeOnSelectLast?: boolean; - onChange?: (value: any) => void; - maxLevel?: number; -}; - -export const Cascader = withDynamicSchemaProps( - connect( - (props: CascaderProps) => { - const field = useField(); - const { - value, - onChange, - labelInValue, - options, - // fieldNames = defaultFieldNames, - useDataSource = useDefDataSource, - useLoadData = useDefLoadData, - changeOnSelectLast, - changeOnSelect, - maxLevel, - ...others - } = props; - const fieldNames = { ...defaultFieldNames, ...props.fieldNames }; - const loadData = useLoadData(props); - const { loading, run } = useDataSource( - { - onSuccess(data) { - field.dataSource = data?.data || []; - }, - }, - props, - ); - // 兼容值为 object[] 的情况 - const toValue = () => { - return toArr(value).map((item) => { - if (typeof item === 'object') { - return item[fieldNames.value]; - } - return item; - }); - }; - const displayRender = (labels: string[], selectedOptions: any[]) => { - return ( - - {labels.map((label, index) => { - if (selectedOptions[index]) { - return {label}; - } - const item = toArr(value) - .filter(Boolean) - .find((item) => item[fieldNames.value] === label); - return {item?.[fieldNames.label] || label}; - })} - - ); - }; - const handelDropDownVisible = (value) => { - if (value && !field.dataSource?.length) { - run(); +export const Cascader = connect( + (props: any) => { + const field = useField(); + const { + value, + onChange, + labelInValue, + // fieldNames = defaultFieldNames, + useDataSource = useDefDataSource, + useLoadData = useDefLoadData, + changeOnSelectLast, + changeOnSelect, + maxLevel, + ...others + } = props; + const fieldNames = { ...defaultFieldNames, ...props.fieldNames }; + const loadData = useLoadData(props); + const { loading, run } = useDataSource({ + onSuccess(data) { + field.dataSource = data?.data || []; + }, + }); + // 兼容值为 object[] 的情况 + const toValue = () => { + return toArr(value).map((item) => { + if (typeof item === 'object') { + return item[fieldNames.value]; } - }; - + return item; + }); + }; + const displayRender = (labels: string[], selectedOptions: any[]) => { return ( - { - if (value && labelInValue) { - onChange(selectedOptions.map((option) => omit(option, [fieldNames.children]))); - } else { - onChange(value); + + {labels.map((label, index) => { + if (selectedOptions[index]) { + return {label}; } - }} - /> + const item = toArr(value) + .filter(Boolean) + .find((item) => item[fieldNames.value] === label); + return {item?.[fieldNames.label] || label}; + })} + ); + }; + const handelDropDownVisible = (value) => { + if (value && !field.dataSource?.length) { + run(); + } + }; + + return ( + { + if (value && labelInValue) { + onChange(selectedOptions.map((option) => omit(option, [fieldNames.children]))); + } else { + onChange(value); + } + }} + /> + ); + }, + mapProps( + { + dataSource: 'options', + }, + (props, field) => { + return { + ...props, + suffixIcon: field?.['loading'] || field?.['validating'] ? : props.suffixIcon, + }; }, - mapProps( - { - dataSource: 'options', - }, - (props, field) => { - return { - ...props, - suffixIcon: field?.['loading'] || field?.['validating'] ? : props.suffixIcon, - }; - }, - ), - mapReadPretty(ReadPretty), ), + mapReadPretty(ReadPretty), ); export default Cascader; diff --git a/packages/core/client/src/schema-component/antd/cascader/ReadPretty.tsx b/packages/core/client/src/schema-component/antd/cascader/ReadPretty.tsx index c90d30f762d71..aa4457e96ca68 100644 --- a/packages/core/client/src/schema-component/antd/cascader/ReadPretty.tsx +++ b/packages/core/client/src/schema-component/antd/cascader/ReadPretty.tsx @@ -4,18 +4,7 @@ import { toArr } from '@formily/shared'; import React from 'react'; import { defaultFieldNames } from './defaultFieldNames'; -interface FieldNames { - label: string; - value: string; - children: string; -} - -export interface CascaderReadPrettyProps { - fieldNames?: FieldNames; - value?: any; -} - -export const ReadPretty: React.FC = (props) => { +export const ReadPretty: React.FC = (props: any) => { const { fieldNames = defaultFieldNames } = props; const values = toArr(props.value); const len = values.length; diff --git a/packages/core/client/src/schema-component/antd/cascader/demos/new-demos/basic.tsx b/packages/core/client/src/schema-component/antd/cascader/demos/new-demos/basic.tsx deleted file mode 100644 index 5b8158838298c..0000000000000 --- a/packages/core/client/src/schema-component/antd/cascader/demos/new-demos/basic.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const options = [ - { - value: 'zhejiang', - label: 'Zhejiang', - children: [ - { - value: 'hangzhou', - label: 'Hangzhou', - children: [ - { - value: 'xihu', - label: 'West Lake', - }, - ], - }, - ], - }, - { - value: 'jiangsu', - label: 'Jiangsu', - children: [ - { - value: 'nanjing', - label: 'Nanjing', - children: [ - { - value: 'zhonghuamen', - label: 'Zhong Hua Men', - }, - ], - }, - ], - }, -]; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'FormV2', - 'x-component': 'ShowFormData', - properties: { - test: { - type: 'string', - title: 'Test', - 'x-decorator': 'FormItem', - enum: options, - 'x-component': 'Cascader', - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/cascader/demos/new-demos/changeOnSelectLast.tsx b/packages/core/client/src/schema-component/antd/cascader/demos/new-demos/changeOnSelectLast.tsx deleted file mode 100644 index 158fbc6654815..0000000000000 --- a/packages/core/client/src/schema-component/antd/cascader/demos/new-demos/changeOnSelectLast.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const options = [ - { - value: 'zhejiang', - label: 'Zhejiang', - children: [ - { - value: 'hangzhou', - label: 'Hangzhou', - children: [ - { - value: 'xihu', - label: 'West Lake', - }, - ], - }, - ], - }, - { - value: 'jiangsu', - label: 'Jiangsu', - children: [ - { - value: 'nanjing', - label: 'Nanjing', - children: [ - { - value: 'zhonghuamen', - label: 'Zhong Hua Men', - }, - ], - }, - ], - }, -]; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'FormV2', - 'x-component': 'ShowFormData', - properties: { - test: { - type: 'string', - title: 'Test', - 'x-decorator': 'FormItem', - enum: options, - 'x-component': 'Cascader', - 'x-component-props': { - changeOnSelectLast: false, - }, - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/cascader/demos/new-demos/labelInValue.tsx b/packages/core/client/src/schema-component/antd/cascader/demos/new-demos/labelInValue.tsx deleted file mode 100644 index 1d080b1745392..0000000000000 --- a/packages/core/client/src/schema-component/antd/cascader/demos/new-demos/labelInValue.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const options = [ - { - value: 'zhejiang', - label: 'Zhejiang', - children: [ - { - value: 'hangzhou', - label: 'Hangzhou', - children: [ - { - value: 'xihu', - label: 'West Lake', - }, - ], - }, - ], - }, - { - value: 'jiangsu', - label: 'Jiangsu', - children: [ - { - value: 'nanjing', - label: 'Nanjing', - children: [ - { - value: 'zhonghuamen', - label: 'Zhong Hua Men', - }, - ], - }, - ], - }, -]; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'FormV2', - 'x-component': 'ShowFormData', - properties: { - test: { - type: 'string', - title: 'Test', - 'x-decorator': 'FormItem', - enum: options, - 'x-component': 'Cascader', - 'x-component-props': { - labelInValue: true, - }, - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/cascader/demos/new-demos/loadData.tsx b/packages/core/client/src/schema-component/antd/cascader/demos/new-demos/loadData.tsx deleted file mode 100644 index 195172f74cfd0..0000000000000 --- a/packages/core/client/src/schema-component/antd/cascader/demos/new-demos/loadData.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { useField } from '@formily/react'; -import { getAppComponent } from '@nocobase/test/web'; -import React, { useState } from 'react'; - -interface Option { - value?: string | number | null; - label: React.ReactNode; - children?: Option[]; - isLeaf?: boolean; -} - -const optionLists: Option[] = [ - { - value: 'zhejiang', - label: 'Zhejiang', - isLeaf: false, - }, - { - value: 'jiangsu', - label: 'Jiangsu', - isLeaf: false, - }, -]; - -const useCustomCascaderProps = () => { - const field = useField(); - field.dataSource = optionLists; - const loadData = (selectedOptions: Option[]) => { - const targetOption = selectedOptions[selectedOptions.length - 1]; - - // load options lazily - setTimeout(() => { - targetOption.children = [ - { - label: `${targetOption.label} Dynamic 1`, - value: 'dynamic1', - }, - { - label: `${targetOption.label} Dynamic 2`, - value: 'dynamic2', - }, - ]; - field.dataSource = [...field.dataSource]; - }, 1000); - }; - - return { - changeOnSelect: true, - loadData, - }; -}; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'FormV2', - 'x-component': 'ShowFormData', - properties: { - test: { - type: 'string', - title: 'Test', - 'x-decorator': 'FormItem', - 'x-component': 'Cascader', - 'x-use-component-props': 'useCustomCascaderProps', - }, - }, - }, - appOptions: { - scopes: { - useCustomCascaderProps, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/cascader/demos/new-demos/read-pretty.tsx b/packages/core/client/src/schema-component/antd/cascader/demos/new-demos/read-pretty.tsx deleted file mode 100644 index b58e74d3429d4..0000000000000 --- a/packages/core/client/src/schema-component/antd/cascader/demos/new-demos/read-pretty.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const options = [ - { - value: 'zhejiang', - label: 'Zhejiang', - children: [ - { - value: 'hangzhou', - label: 'Hangzhou', - children: [ - { - value: 'xihu', - label: 'West Lake', - }, - ], - }, - ], - }, - { - value: 'jiangsu', - label: 'Jiangsu', - children: [ - { - value: 'nanjing', - label: 'Nanjing', - children: [ - { - value: 'zhonghuamen', - label: 'Zhong Hua Men', - }, - ], - }, - ], - }, -]; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'FormV2', - 'x-component': 'ShowFormData', - 'x-pattern': 'readPretty', - properties: { - test: { - type: 'string', - title: 'Test', - default: ['zhejiang', 'hangzhou', 'xihu'], - 'x-decorator': 'FormItem', - enum: options, - 'x-component': 'Cascader', - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/cascader/index.md b/packages/core/client/src/schema-component/antd/cascader/index.md index 78d63bd9c1310..abaeae22749af 100644 --- a/packages/core/client/src/schema-component/antd/cascader/index.md +++ b/packages/core/client/src/schema-component/antd/cascader/index.md @@ -1,53 +1,36 @@ -# Cascader - -级联选择器,其基于 ant-design [Cascader](https://ant.design/components/cascader-cn/) 组件封装。 - -```ts -type CascaderProps = AntdCascaderProps & { - /** - * Whether to wrap the label of option into the value - */ - labelInValue?: boolean; - /** - * must select the last level - */ - changeOnSelectLast?: boolean; -} -``` +--- +group: + title: Schema Components + order: 3 +--- -## Basic Usage - - - -## Asynchronous Data Source +# Cascader - +## Examples -## labelInValue +### Cascader -如果设置 `labelInValue` 为 `true`,则选中的数据为 `{ label: string, value: string }` 格式,否则为 `string` 格式。 + - +### Asynchronous Data Source -## changeOnSelectLast + -如果设置 `changeOnSelectLast` 为 `true`,则必须选择最后一级,如果为 `false`,则可以选择任意级。 +## API - +基于 antd 的 [Cascader](https://ant.design/components/cascader/#API) 附加的一些属性: -## Read Pretty +- `labelInValue` 是否把每个选项的 label 包装到 value 中 +- `changeOnSelectLast` 必须选到最后一级 +- `useLoadData` 可调用 hook 的 loadData ```ts -interface FieldNames { - label: string; - value: string; - children: string; -} - -export interface CascaderReadPrettyProps { - fieldNames?: FieldNames; - value?: any; +{ + useLoadData: (props) => { + // 这里可以写 hook + return function loadData(selectedOptions) { + // Cascader 的 loadData + } + } } ``` - - diff --git a/packages/core/client/src/schema-component/antd/checkbox/Checkbox.tsx b/packages/core/client/src/schema-component/antd/checkbox/Checkbox.tsx index 0a10d30d3f10b..75d1590cc036b 100644 --- a/packages/core/client/src/schema-component/antd/checkbox/Checkbox.tsx +++ b/packages/core/client/src/schema-component/antd/checkbox/Checkbox.tsx @@ -2,29 +2,21 @@ import { CheckOutlined, CloseOutlined } from '@ant-design/icons'; import { connect, mapProps, mapReadPretty, useField } from '@formily/react'; import { isValid } from '@formily/shared'; import { Checkbox as AntdCheckbox, Tag } from 'antd'; -import type { - CheckboxGroupProps as AntdCheckboxGroupProps, - CheckboxProps as AntdCheckboxProps, -} from 'antd/es/checkbox'; +import type { CheckboxGroupProps, CheckboxProps } from 'antd/es/checkbox'; import uniq from 'lodash/uniq'; -import React, { FC, useMemo } from 'react'; +import React, { useMemo } from 'react'; import { useCollectionField } from '../../../data-source/collection-field/CollectionFieldProvider'; import { EllipsisWithTooltip } from '../input/EllipsisWithTooltip'; type ComposedCheckbox = React.ForwardRefExoticComponent< Pick, string | number | symbol> & React.RefAttributes > & { - Group?: React.FC; + Group?: React.FC; __ANT_CHECKBOX?: boolean; - ReadPretty?: React.FC; + ReadPretty?: React.FC; }; -export interface CheckboxReadPrettyProps { - showUnchecked?: boolean; - value?: boolean; -} - -const ReadPretty: FC = (props) => { +const ReadPretty = (props) => { if (props.value) { return ; } @@ -32,7 +24,7 @@ const ReadPretty: FC = (props) => { }; export const Checkbox: ComposedCheckbox = connect( - (props: AntdCheckboxProps) => { + (props: any) => { const changeHandler = (val) => { props?.onChange(val); }; @@ -51,17 +43,12 @@ Checkbox.ReadPretty.displayName = 'Checkbox.ReadPretty'; Checkbox.__ANT_CHECKBOX = true; -export interface CheckboxGroupReadPrettyProps { - value?: any[]; - ellipsis?: boolean; -} - Checkbox.Group = connect( AntdCheckbox.Group, mapProps({ dataSource: 'options', }), - mapReadPretty((props: CheckboxGroupReadPrettyProps) => { + mapReadPretty((props) => { if (!isValid(props.value)) { return null; } diff --git a/packages/core/client/src/schema-component/antd/checkbox/demos/new-demos/basic.tsx b/packages/core/client/src/schema-component/antd/checkbox/demos/new-demos/basic.tsx deleted file mode 100644 index 780323b173873..0000000000000 --- a/packages/core/client/src/schema-component/antd/checkbox/demos/new-demos/basic.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'FormV2', - 'x-component': 'ShowFormData', - properties: { - test: { - type: 'boolean', - title: 'Test', - 'x-decorator': 'FormItem', - 'x-component': 'Checkbox', - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/checkbox/demos/new-demos/group-read-pretty.tsx b/packages/core/client/src/schema-component/antd/checkbox/demos/new-demos/group-read-pretty.tsx deleted file mode 100644 index 1ed3d01edf14b..0000000000000 --- a/packages/core/client/src/schema-component/antd/checkbox/demos/new-demos/group-read-pretty.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const options = [ - { - label: '选项1', - value: 1, - color: 'red', - }, - { - label: '选项2', - value: 2, - color: 'blue', - }, - { - label: '选项3', - value: 3, - color: 'yellow', - }, -]; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'FormV2', - 'x-component': 'ShowFormData', - 'x-pattern': 'readPretty', - properties: { - test1: { - type: 'array', - default: [1, 2], - title: 'Test1', - enum: options, - 'x-decorator': 'FormItem', - 'x-component': 'Checkbox.Group', - }, - test2: { - type: 'array', - default: [1, 2, 3], - title: 'Test2', - enum: options, - 'x-decorator': 'FormItem', - 'x-component': 'Checkbox.Group', - 'x-decorator-props': { - style: { - width: 100, - }, - }, - 'x-component-props': { - ellipsis: true, - }, - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/checkbox/demos/new-demos/group.tsx b/packages/core/client/src/schema-component/antd/checkbox/demos/new-demos/group.tsx deleted file mode 100644 index c1cfa50e6c2b0..0000000000000 --- a/packages/core/client/src/schema-component/antd/checkbox/demos/new-demos/group.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const options = [ - { - label: '选项1', - value: 1, - color: 'red', - }, - { - label: '选项2', - value: 2, - color: 'blue', - }, -]; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'FormV2', - 'x-component': 'ShowFormData', - properties: { - test: { - type: 'array', - title: 'Test', - enum: options, - 'x-decorator': 'FormItem', - 'x-component': 'Checkbox.Group', - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/checkbox/demos/new-demos/read-pretty.tsx b/packages/core/client/src/schema-component/antd/checkbox/demos/new-demos/read-pretty.tsx deleted file mode 100644 index 4b1348079c727..0000000000000 --- a/packages/core/client/src/schema-component/antd/checkbox/demos/new-demos/read-pretty.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'FormV2', - 'x-component': 'ShowFormData', - 'x-pattern': 'readPretty', - properties: { - test: { - type: 'boolean', - default: true, - title: 'Test1', - 'x-decorator': 'FormItem', - 'x-component': 'Checkbox', - }, - test2: { - type: 'boolean', - default: false, - title: 'Test2', - 'x-decorator': 'FormItem', - 'x-component': 'Checkbox', - }, - test3: { - type: 'boolean', - default: false, - title: 'Test3', - 'x-decorator': 'FormItem', - 'x-component': 'Checkbox', - 'x-component-props': { - showUnchecked: true, - }, - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/checkbox/index.md b/packages/core/client/src/schema-component/antd/checkbox/index.md index 57a25e1cff1cd..a24296c51ce6a 100644 --- a/packages/core/client/src/schema-component/antd/checkbox/index.md +++ b/packages/core/client/src/schema-component/antd/checkbox/index.md @@ -1,46 +1,17 @@ -# Checkbox - -复选框,其基于 ant-design [Checkbox](https://ant.design/components/checkbox/) 组件封装。 - - -## Basic Usage - -```ts -type CheckboxProps = AntdCheckboxProps; -``` - - +--- +group: + title: Schema Components + order: 3 +--- -## Read Pretty - -```ts -interface CheckboxReadPrettyProps { - showUnchecked?: boolean; - value?: boolean; -} -``` - -如果值为 `false`,默认情况下不显示内容,可以通过 `showUnchecked` 属性来显示未选中的复选框。 - - - -## Checkbox Group - -```ts -type CheckboxGroupProps = CheckboxGroupProps; -``` +# Checkbox -注意 schema 的 type 属性为 `array`。 +## Examples - +### 勾选 -## Checkbox Group Read Pretty + -```ts -export interface CheckboxGroupReadPrettyProps { - value?: any[]; - ellipsis?: boolean; -} -``` +### 组 - + diff --git a/packages/core/client/src/schema-component/antd/collection-select/demos/basic.tsx b/packages/core/client/src/schema-component/antd/collection-select/demos/basic.tsx deleted file mode 100644 index 1d5c91f958feb..0000000000000 --- a/packages/core/client/src/schema-component/antd/collection-select/demos/basic.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'FormV2', - 'x-component': 'ShowFormData', - properties: { - test: { - type: 'string', - title: 'Test', - 'x-decorator': 'FormItem', - 'x-component': 'CollectionSelect', - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/collection-select/demos/multiple.tsx b/packages/core/client/src/schema-component/antd/collection-select/demos/multiple.tsx deleted file mode 100644 index 7049ebb9ae17c..0000000000000 --- a/packages/core/client/src/schema-component/antd/collection-select/demos/multiple.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'FormV2', - 'x-component': 'ShowFormData', - properties: { - test: { - type: 'array', - title: 'Test', - 'x-decorator': 'FormItem', - 'x-component': 'CollectionSelect', - 'x-component-props': { - mode: 'multiple', - }, - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/collection-select/demos/read-pretty.tsx b/packages/core/client/src/schema-component/antd/collection-select/demos/read-pretty.tsx deleted file mode 100644 index 851d59d3c2a1d..0000000000000 --- a/packages/core/client/src/schema-component/antd/collection-select/demos/read-pretty.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-component': 'ShowFormData', - 'x-decorator': 'FormV2', - 'x-read-pretty': true, - properties: { - test: { - type: 'string', - default: 'users', - title: 'Test', - 'x-decorator': 'FormItem', - 'x-component': 'CollectionSelect', - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/collection-select/index.md b/packages/core/client/src/schema-component/antd/collection-select/index.md index 28fd4516552f3..a1d9a0c00577e 100644 --- a/packages/core/client/src/schema-component/antd/collection-select/index.md +++ b/packages/core/client/src/schema-component/antd/collection-select/index.md @@ -1,24 +1,8 @@ -# CollectionSelect - -用于选择当前数据源的数据表。 - -```ts -type CollectionSelectProps = SelectProps & { - filter?: (item: any, index: number, array: any[]) => boolean; - isTableOid?: boolean; -}; -``` - -## Basic Usage - - +--- +group: + title: Schema Components +--- -## Multiple Selection - -`type` 需要改为 `array`,并且属性需要增加 `mode: 'multiple'`。 - - - -## Read Pretty +# CollectionSelect - +## Example diff --git a/packages/core/client/src/schema-component/antd/color-picker/ColorPicker.tsx b/packages/core/client/src/schema-component/antd/color-picker/ColorPicker.tsx index 9d6a9384aa3bc..01e292ecd1f15 100644 --- a/packages/core/client/src/schema-component/antd/color-picker/ColorPicker.tsx +++ b/packages/core/client/src/schema-component/antd/color-picker/ColorPicker.tsx @@ -1,16 +1,12 @@ import { css } from '@emotion/css'; import { usePrefixCls } from '@formily/antd-v5/esm/__builtins__'; import { connect, mapProps, mapReadPretty } from '@formily/react'; -import { ColorPicker as AntdColorPicker, ColorPickerProps as AntdColorPickerProps } from 'antd'; +import { ColorPicker as AntdColorPicker } from 'antd'; import cls from 'classnames'; import React from 'react'; -export interface ColorPickerProps extends Omit { - onChange?: (color: string) => void; -} - export const ColorPicker = connect( - (props: ColorPickerProps) => { + (props) => { const { value, onChange, ...others } = props; return (
diff --git a/packages/core/client/src/schema-component/antd/color-picker/demos/new-demos/basic.tsx b/packages/core/client/src/schema-component/antd/color-picker/demos/new-demos/basic.tsx deleted file mode 100644 index f45203b915318..0000000000000 --- a/packages/core/client/src/schema-component/antd/color-picker/demos/new-demos/basic.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'FormV2', - 'x-component': 'ShowFormData', - properties: { - test: { - type: 'string', - title: 'Test', - 'x-decorator': 'FormItem', - 'x-component': 'ColorPicker', - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/color-picker/demos/new-demos/read-pretty.tsx b/packages/core/client/src/schema-component/antd/color-picker/demos/new-demos/read-pretty.tsx deleted file mode 100644 index d666c4ac11569..0000000000000 --- a/packages/core/client/src/schema-component/antd/color-picker/demos/new-demos/read-pretty.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { getAppComponent } from '@nocobase/test/web'; - -const App = getAppComponent({ - schema: { - type: 'void', - name: 'root', - 'x-decorator': 'FormV2', - 'x-component': 'ShowFormData', - 'x-pattern': 'readPretty', - properties: { - test: { - type: 'string', - default: '#8BBB11', - title: 'Test', - 'x-decorator': 'FormItem', - 'x-component': 'ColorPicker', - }, - }, - }, -}); - -export default App; diff --git a/packages/core/client/src/schema-component/antd/color-picker/index.md b/packages/core/client/src/schema-component/antd/color-picker/index.md index 9240492f547a8..f30325a4719c7 100644 --- a/packages/core/client/src/schema-component/antd/color-picker/index.md +++ b/packages/core/client/src/schema-component/antd/color-picker/index.md @@ -1,17 +1,18 @@ +--- +group: + title: Schema Components + order: 3 +--- + # ColorPicker -颜色选择器,其基于 ant-design [ColorPicker](https://ant.design/components/color-picker/) 组件进行封装。 +## Examples + +### Basic + + -```ts -interface ColorPickerProps extends Omit { - onChange?: (color: string) => void; -} -``` -## Basic Usage - -## Read Pretty - diff --git a/packages/core/client/src/schema-component/antd/color-select/ColorSelect.tsx b/packages/core/client/src/schema-component/antd/color-select/ColorSelect.tsx index c445dee807045..97cdb13fcb61f 100644 --- a/packages/core/client/src/schema-component/antd/color-select/ColorSelect.tsx +++ b/packages/core/client/src/schema-component/antd/color-select/ColorSelect.tsx @@ -1,6 +1,6 @@ import { LoadingOutlined } from '@ant-design/icons'; import { connect, mapProps, mapReadPretty } from '@formily/react'; -import { Select, SelectProps, Tag } from 'antd'; +import { Select, Tag } from 'antd'; import React from 'react'; import { useCompile } from '../../hooks/useCompile'; @@ -19,12 +19,8 @@ const colors = { default: '{{t("Default")}}', }; -export interface ColorSelectProps extends SelectProps { - suffix?: React.ReactNode; -} - export const ColorSelect = connect( - (props: ColorSelectProps) => { + (props) => { const compile = useCompile(); return (