@formily-design/formily-antd 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/package.json +8 -8
  2. package/.umirc.js +0 -44
  3. package/copy.ts +0 -6
  4. package/playground/components/AsyncSelect/AsyncSelect.tsx +0 -38
  5. package/playground/components/AsyncSelect/index.tsx +0 -1
  6. package/playground/components/AsyncSelect/preview.tsx +0 -36
  7. package/playground/components/ClickEventSetter/ActionConfigModal.tsx +0 -173
  8. package/playground/components/ClickEventSetter/ActionList.tsx +0 -67
  9. package/playground/components/ClickEventSetter/DownloadPanel.tsx +0 -24
  10. package/playground/components/ClickEventSetter/NavigationPanel.tsx +0 -42
  11. package/playground/components/ClickEventSetter/RequestPanel.tsx +0 -190
  12. package/playground/components/ClickEventSetter/index.tsx +0 -90
  13. package/playground/components/ClickEventSetter/styles.less +0 -89
  14. package/playground/components/ClickEventSetter/types.ts +0 -43
  15. package/playground/components/FormButton/FormButton.tsx +0 -189
  16. package/playground/components/FormButton/hooks/useEventActionExecutor.ts +0 -65
  17. package/playground/components/FormButton/index.ts +0 -1
  18. package/playground/components/FormButton/preview.tsx +0 -60
  19. package/playground/components/FormButton/utils/actionExecutors.ts +0 -96
  20. package/playground/components/FormButtonGroup/FormButtonGroup.tsx +0 -21
  21. package/playground/components/FormButtonGroup/index.ts +0 -1
  22. package/playground/components/FormButtonGroup/preview.tsx +0 -66
  23. package/playground/components/FormList/FormList.tsx +0 -164
  24. package/playground/components/FormList/index.tsx +0 -1
  25. package/playground/components/FormList/preview.tsx +0 -429
  26. package/playground/components/LocationPicker/LocationModal.tsx +0 -328
  27. package/playground/components/LocationPicker/LocationPicker.tsx +0 -163
  28. package/playground/components/LocationPicker/SearchBox.tsx +0 -122
  29. package/playground/components/LocationPicker/api.ts +0 -77
  30. package/playground/components/LocationPicker/constants.ts +0 -2
  31. package/playground/components/LocationPicker/index.tsx +0 -44
  32. package/playground/components/LocationPicker/types.ts +0 -160
  33. package/playground/components/LocationPicker/utils.ts +0 -46
  34. package/playground/components/ResourceIcon/index.module.less +0 -10
  35. package/playground/components/ResourceIcon/index.tsx +0 -10
  36. package/playground/designerLocales/en-US.ts +0 -38
  37. package/playground/designerLocales/index.ts +0 -6
  38. package/playground/designerLocales/ko-KR.ts +0 -10
  39. package/playground/designerLocales/zh-CN.ts +0 -38
  40. package/playground/locales/FormButton.ts +0 -38
  41. package/playground/locales/FormButtonGroup.ts +0 -29
  42. package/playground/locales/LocationPicker.ts +0 -30
  43. package/playground/locales/all.ts +0 -3
  44. package/playground/locales/index.ts +0 -3
  45. package/playground/main.tsx +0 -222
  46. package/playground/react-app-env.d.ts +0 -4
  47. package/playground/request.ts +0 -123
  48. package/playground/schemas/FormButton.ts +0 -42
  49. package/playground/schemas/FormButtonGroup.ts +0 -24
  50. package/playground/schemas/LocationPicker.ts +0 -14
  51. package/playground/schemas/all.ts +0 -3
  52. package/playground/schemas/index.ts +0 -3
  53. package/playground/service/index.ts +0 -1
  54. package/playground/service/schema.ts +0 -22
  55. package/playground/template.ejs +0 -20
  56. package/playground/utils.ts +0 -744
  57. package/playground/webpack.base.ts +0 -123
  58. package/playground/webpack.dev.ts +0 -64
  59. package/playground/webpack.prod.ts +0 -46
  60. package/playground/widgets/ActionsWidget.tsx +0 -58
  61. package/playground/widgets/LogoWidget.tsx +0 -20
  62. package/playground/widgets/MarkupSchemaWidget.tsx +0 -164
  63. package/playground/widgets/PreviewWidget.tsx +0 -188
  64. package/playground/widgets/SchemaEditorWidget.tsx +0 -27
  65. package/playground/widgets/index.ts +0 -5
  66. package/tsconfig.build.json +0 -12
@@ -1,90 +0,0 @@
1
- import React, { Fragment, useState, useMemo } from 'react'
2
- import { Modal, Button } from 'antd'
3
- import { usePrefix, TextWidget } from '@formily-design/react'
4
- import { IEventAction, IEventConfig } from './types'
5
- import { ActionList } from './ActionList'
6
- import { ActionConfigModal } from './ActionConfigModal'
7
- import './styles.less'
8
-
9
- export interface IClickEventSetterProps {
10
- className?: string
11
- style?: React.CSSProperties
12
- onChange: (value: IEventConfig) => void
13
- value?: IEventConfig
14
- }
15
-
16
- export const ClickEventSetter: React.FC<IClickEventSetterProps> = (props) => {
17
- const { value, onChange } = props
18
- const prefix = usePrefix('click-event-setter')
19
- const [modalVisible, setModalVisible] = useState(false)
20
- const [editingAction, setEditingAction] = useState<IEventAction | null>(null)
21
- const [editingIndex, setEditingIndex] = useState<number>(-1)
22
-
23
- const actions = useMemo(() => value?.actions || [], [value])
24
-
25
- const openModal = () => setModalVisible(true)
26
- const closeModal = () => {
27
- setModalVisible(false)
28
- setEditingAction(null)
29
- setEditingIndex(-1)
30
- }
31
-
32
- const handleEditAction = (action: IEventAction, index: number) => {
33
- setEditingAction(action)
34
- setEditingIndex(index)
35
- setModalVisible(true)
36
- }
37
-
38
- const handleDeleteAction = (index: number) => {
39
- const newActions = [...actions]
40
- newActions.splice(index, 1)
41
- onChange({ actions: newActions })
42
- }
43
-
44
- const handleSaveAction = (action: IEventAction) => {
45
- const newActions = [...actions]
46
- if (editingIndex >= 0) {
47
- newActions[editingIndex] = action
48
- } else {
49
- newActions.push(action)
50
- }
51
- onChange({ actions: newActions })
52
- closeModal()
53
- }
54
-
55
- return (
56
- <Fragment>
57
- <div className={`${prefix}-container`}>
58
- <Button block onClick={openModal} className={`${prefix}-trigger`}>
59
- <TextWidget token="SettingComponents.ClickEventSetter.configureEvents" />
60
- </Button>
61
- {actions.length > 0 && (
62
- <ActionList
63
- actions={actions}
64
- onEdit={handleEditAction}
65
- onDelete={handleDeleteAction}
66
- />
67
- )}
68
- </div>
69
- <Modal
70
- title={
71
- <TextWidget token="SettingComponents.ClickEventSetter.configureEvents" />
72
- }
73
- width={700}
74
- styles={{ body: { padding: 10 } }}
75
- transitionName=""
76
- maskTransitionName=""
77
- open={modalVisible}
78
- onCancel={closeModal}
79
- footer={null}
80
- destroyOnClose
81
- >
82
- <ActionConfigModal
83
- editingAction={editingAction}
84
- onSave={handleSaveAction}
85
- onCancel={closeModal}
86
- />
87
- </Modal>
88
- </Fragment>
89
- )
90
- }
@@ -1,89 +0,0 @@
1
- // @click-event-setter-prefix: ~'click-event-setter';
2
- @click-event-setter-prefix: 'dn-click-event-setter';
3
-
4
- .dn-click-event-setter-container {
5
- width: 100%;
6
- }
7
-
8
- .dn-click-event-setter-trigger {
9
- margin-bottom: 8px;
10
- }
11
-
12
- /* Action List Styles */
13
- .click-event-action-list {
14
- width: 100%;
15
- border: 1px solid #e8e8e8;
16
- border-radius: 4px;
17
-
18
- .click-event-action-item {
19
- padding: 4px;
20
- border-bottom: 1px solid #f0f0f0;
21
- word-break: break-all;
22
-
23
- &:last-child {
24
- border-bottom: none;
25
- }
26
-
27
- .ant-list-item-action {
28
- margin-inline-start: 0;
29
- }
30
-
31
- .click-event-action-title {
32
- display: flex;
33
- align-items: center;
34
- gap: 2px;
35
-
36
- .click-event-action-description {
37
- color: #666;
38
- font-size: 12px;
39
- overflow: hidden;
40
- text-overflow: ellipsis;
41
- white-space: nowrap;
42
- max-width: 300px;
43
- }
44
- }
45
- }
46
- }
47
-
48
- /* Action Config Modal Styles */
49
- .action-config-modal {
50
- .action-config-basic {
51
- padding: 8px 0;
52
- }
53
-
54
- .action-config-panel {
55
- padding: 8px 0;
56
- }
57
-
58
- .action-config-footer {
59
- display: flex;
60
- justify-content: flex-end;
61
- gap: 8px;
62
- margin-top: 16px;
63
- padding-top: 16px;
64
- border-top: 1px solid #f0f0f0;
65
- }
66
- }
67
-
68
- /* Request Panel Styles */
69
- .request-panel {
70
- &-section {
71
- padding: 8px 0;
72
- }
73
-
74
- &-row {
75
- display: flex;
76
- align-items: center;
77
- margin-bottom: 8px;
78
- }
79
- }
80
-
81
- /* Navigation Panel Styles */
82
- .navigation-panel {
83
- padding: 8px 0;
84
- }
85
-
86
- /* Download Panel Styles */
87
- .download-panel {
88
- padding: 8px 0;
89
- }
@@ -1,43 +0,0 @@
1
- // 事件动作类型
2
- export type EventActionType = 'navigation' | 'request' | 'download'
3
-
4
- // 事件配置结构
5
- export interface IEventConfig {
6
- actions: IEventAction[]
7
- }
8
-
9
- // 单个事件动作基础接口
10
- export interface IEventActionBase {
11
- id: string
12
- type: EventActionType
13
- description?: string
14
- }
15
-
16
- // 页面跳转动作
17
- export interface INavigationAction extends IEventActionBase {
18
- type: 'navigation'
19
- url: string
20
- target?: '_blank' | '_self'
21
- }
22
-
23
- // 服务请求动作
24
- export interface IRequestAction extends IEventActionBase {
25
- type: 'request'
26
- url: string
27
- method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
28
- headers?: Record<string, string>
29
- params?: Record<string, string>
30
- beforeRequest?: string
31
- dataHandler?: string
32
- successMessage?: string
33
- dataKey?: string
34
- }
35
-
36
- // 下载文件动作
37
- export interface IDownloadAction extends IEventActionBase {
38
- type: 'download'
39
- url: string
40
- }
41
-
42
- // 联合类型
43
- export type IEventAction = INavigationAction | IRequestAction | IDownloadAction
@@ -1,189 +0,0 @@
1
- import React from 'react'
2
- import { DnFC } from '@formily-design/react'
3
- import { Button as AntButton, ButtonProps } from 'antd'
4
- import { Reset, Submit } from '@formily/antd-v5'
5
- import { useForm, observer, useExpressionScope } from '@formily/react'
6
- import { IEventAction } from '../ClickEventSetter/types'
7
- import {
8
- useEventActionExecutor,
9
- hasActionOfType,
10
- } from './hooks/useEventActionExecutor'
11
-
12
- interface IFormButtonSetterProps {
13
- /** 是否禁用表单验证 */
14
- noValidate?: boolean
15
- /** 事件配置 */
16
- onEvent?: {
17
- /** 点击事件配置 */
18
- click?: {
19
- /** 点击事件动作列表 */
20
- actions: IEventAction[]
21
- }
22
- }
23
- }
24
-
25
- export interface IFormButtonProps extends IFormButtonSetterProps, ButtonProps {
26
- onClick?: (e: React.MouseEvent<Element, MouseEvent>) => void
27
- title?: string
28
- }
29
-
30
- export const FormButton: DnFC<IFormButtonProps> = (props: IFormButtonProps) => {
31
- const { htmlType } = props
32
-
33
- if (htmlType === 'reset')
34
- return <ResetButton {...props}>{props.title}</ResetButton>
35
- if (htmlType === 'submit')
36
- return <SubmitButton {...props}>{props.title}</SubmitButton>
37
- return <Button {...props}>{props.title}</Button>
38
- }
39
-
40
- /**
41
- * 获取点击事件动作列表
42
- */
43
- function getClickActions(
44
- onEvent?: IFormButtonSetterProps['onEvent']
45
- ): IEventAction[] | undefined {
46
- return onEvent?.click?.actions
47
- }
48
-
49
- /**
50
- * 重置
51
- * 为什么使用 observer 包裹?
52
- * 因为 useForm() 获取的 form 实例是响应式的,observer 可以确保组件在 form 状态变化时重新渲染。使用 connect 或 observer 都可以达到这个目的。
53
- * https://react.formilyjs.org/zh-CN/api/shared/observer
54
- */
55
- const ResetButton = observer(
56
- ({
57
- children,
58
- onEvent,
59
- ...props
60
- }: React.ComponentProps<typeof Reset> & IFormButtonSetterProps) => {
61
- const form = useForm()
62
- const actions = getClickActions(onEvent)
63
- const { execute: executeEvents, executing } = useEventActionExecutor(
64
- actions,
65
- form
66
- )
67
-
68
- const handleClick = async () => {
69
- if (actions && actions.length > 0) {
70
- await executeEvents()
71
- }
72
- // 执行表单重置
73
- form.reset()
74
- }
75
-
76
- return (
77
- <Reset
78
- {...props}
79
- htmlType="button"
80
- loading={executing}
81
- onClick={handleClick}
82
- >
83
- {children}
84
- </Reset>
85
- )
86
- }
87
- )
88
-
89
- /** 提交 */
90
- const SubmitButton = observer(
91
- ({
92
- children,
93
- noValidate,
94
- onEvent,
95
- ...props
96
- }: React.ComponentProps<typeof Submit> & IFormButtonSetterProps) => {
97
- const form = useForm()
98
- const actions = getClickActions(onEvent)
99
- const hasRequestAction = hasActionOfType(actions, 'request')
100
- const { execute: executeEvents, executing } = useEventActionExecutor(
101
- actions,
102
- form
103
- )
104
- // useExpressionScope 读取表达式作用域,获取表单配置的提交 API submitFormApi
105
- const { submitFormApi, apiParams } = useExpressionScope()
106
- const handleClick = async () => {
107
- if (noValidate) {
108
- // 获取表单值
109
- const values = form.values
110
- // 手动更新表单状态为提交中
111
- form.setSubmitting(true)
112
- try {
113
- if (hasRequestAction) {
114
- // 有 request 动作时,仅执行事件动作,不执行表单提交
115
- await executeEvents(values, apiParams)
116
- } else if (actions && actions.length > 0) {
117
- // 有事件但无 request 动作时,先执行事件再提交
118
- await executeEvents(values, apiParams)
119
- await doSubmit(values)
120
- } else {
121
- // 无事件配置时,直接提交
122
- await doSubmit(values)
123
- }
124
- } finally {
125
- form.setSubmitting(false)
126
- }
127
- } else {
128
- form.submit(async (values) => {
129
- if (hasRequestAction) {
130
- // 有 request 动作时,仅执行事件动作,不执行表单提交
131
- await executeEvents(values, apiParams)
132
- } else if (actions && actions.length > 0) {
133
- // 有事件但无 request 动作时,先执行事件再提交
134
- await executeEvents(values, apiParams)
135
- await doSubmit(values)
136
- } else {
137
- // 无事件配置时,直接提交
138
- await doSubmit(values)
139
- }
140
- })
141
- }
142
- }
143
-
144
- /** 表单提交 - 执行 form 配置的 API */
145
- const doSubmit = async (values: Record<string, any>) => {
146
- await submitFormApi?.(values)
147
- }
148
- return (
149
- <Submit
150
- {...props}
151
- htmlType="button"
152
- loading={executing || form.submitting}
153
- onClick={handleClick}
154
- >
155
- {children}
156
- </Submit>
157
- )
158
- }
159
- )
160
-
161
- /** 按钮 */
162
- const Button = observer(
163
- ({
164
- children,
165
- onEvent,
166
- ...props
167
- }: React.ComponentProps<typeof AntButton> & IFormButtonSetterProps) => {
168
- const form = useForm()
169
- const actions = getClickActions(onEvent)
170
- // useExpressionScope 读取表达式作用域
171
- const { apiParams } = useExpressionScope()
172
- const { execute: executeEvents, executing } = useEventActionExecutor(
173
- actions,
174
- form
175
- )
176
-
177
- const handleClick = async () => {
178
- if (actions && actions.length > 0) {
179
- await executeEvents(form.values, apiParams)
180
- }
181
- }
182
-
183
- return (
184
- <AntButton {...props} loading={executing} onClick={handleClick}>
185
- {children}
186
- </AntButton>
187
- )
188
- }
189
- )
@@ -1,65 +0,0 @@
1
- import { useState, useCallback } from 'react'
2
- import { IEventAction } from '../../ClickEventSetter/types'
3
- import { executeActions } from '../utils/actionExecutors'
4
- import { Form } from '@formily/core'
5
-
6
- interface UseEventActionExecutorOptions {
7
- onComplete?: () => void
8
- onError?: (error: Error) => void
9
- }
10
-
11
- interface UseEventActionExecutorReturn {
12
- executing: boolean
13
- execute: (
14
- formValues?: Record<string, any>,
15
- apiParams?: Record<string, any>
16
- ) => Promise<void>
17
- }
18
-
19
- export function useEventActionExecutor(
20
- actions: IEventAction[] | undefined,
21
- form: Form,
22
- options?: UseEventActionExecutorOptions
23
- ): UseEventActionExecutorReturn {
24
- const [executing, setExecuting] = useState(false)
25
-
26
- const execute = useCallback(
27
- async (
28
- formValues?: Record<string, any>,
29
- apiParams?: Record<string, any>
30
- ) => {
31
- if (!actions || actions.length === 0) {
32
- return
33
- }
34
- setExecuting(true)
35
- try {
36
- await executeActions(actions, formValues, apiParams, (error, index) => {
37
- console.error(`动作 ${index + 1} 执行失败:`, error)
38
- })
39
- options?.onComplete?.()
40
- } catch (error) {
41
- const err = error instanceof Error ? error : new Error(String(error))
42
- options?.onError?.(err)
43
- } finally {
44
- setExecuting(false)
45
- }
46
- },
47
- [actions, form, options]
48
- )
49
-
50
- return {
51
- executing,
52
- execute,
53
- }
54
- }
55
-
56
- /**
57
- * 检查动作配置中是否包含指定类型的动作
58
- */
59
- export function hasActionOfType(
60
- actions: IEventAction[] | undefined,
61
- type: string
62
- ): boolean {
63
- if (!actions) return false
64
- return actions.some((action) => action.type === type)
65
- }
@@ -1 +0,0 @@
1
- export * from './preview'
@@ -1,60 +0,0 @@
1
- import React from 'react'
2
- import { createBehavior, createResource } from '@formily-design/core'
3
- import { DnFC } from '@formily-design/react'
4
- import { ClickEventSetter } from '../ClickEventSetter'
5
- import { FormButton as FormButtonComponent } from './FormButton'
6
- import { CustomSchemas } from '../../schemas'
7
- import { CustomLocales } from '../../locales'
8
-
9
- export const FormButton: DnFC<
10
- React.ComponentProps<typeof FormButtonComponent>
11
- > = FormButtonComponent
12
-
13
- FormButton.Behavior = createBehavior({
14
- name: 'FormButton',
15
- extends: ['Field'],
16
- selector: (node) => node.props['x-component'] === 'FormButton',
17
- designerProps: {
18
- droppable: false,
19
- propsSchema: {
20
- type: 'object',
21
- properties: {
22
- 'component-group': {
23
- type: 'void',
24
- 'x-component': 'CollapseItem',
25
- properties: {
26
- 'x-component-props': CustomSchemas.FormButton,
27
- },
28
- },
29
- 'event-group': {
30
- type: 'void',
31
- 'x-component': 'CollapseItem',
32
- properties: {
33
- 'x-component-props.onEvent.click': {
34
- type: 'object',
35
- 'x-component': ClickEventSetter,
36
- },
37
- },
38
- },
39
- },
40
- },
41
- },
42
- designerLocales: CustomLocales.FormButton,
43
- })
44
-
45
- FormButton.Resource = createResource({
46
- icon: 'SelectSource',
47
- elements: [
48
- {
49
- componentName: 'Field',
50
- props: {
51
- type: 'void',
52
- title: 'FormButton',
53
- 'x-component': 'FormButton',
54
- 'x-component-props': {
55
- title: '按钮',
56
- },
57
- },
58
- },
59
- ],
60
- })
@@ -1,96 +0,0 @@
1
- import { message } from 'antd'
2
- import {
3
- IEventAction,
4
- INavigationAction,
5
- IRequestAction,
6
- IDownloadAction,
7
- } from '../../ClickEventSetter/types'
8
- import { executeFormApi } from '../../../utils'
9
-
10
- /**
11
- * 执行页面跳转动作
12
- */
13
- export function executeNavigationAction(action: INavigationAction) {
14
- const { url, target = '_self' } = action
15
- if (target === '_blank') {
16
- window.open(url, '_blank')
17
- } else {
18
- window.location.href = url
19
- }
20
- }
21
-
22
- /**
23
- * 执行服务请求动作
24
- */
25
- export async function executeRequestAction(
26
- action: IRequestAction,
27
- formValues?: Record<string, any>,
28
- apiParams?: Record<string, any>
29
- ): Promise<void> {
30
- const { successMessage } = action
31
-
32
- await executeFormApi(action, formValues, { apiParams })
33
-
34
- if (successMessage) {
35
- message.success(successMessage)
36
- }
37
- }
38
-
39
- /**
40
- * 执行下载文件动作
41
- */
42
- export function executeDownloadAction(action: IDownloadAction) {
43
- const { url } = action
44
- const link = document.createElement('a')
45
- link.href = url
46
- link.download = ''
47
- link.target = '_blank'
48
- link.style.display = 'none'
49
- document.body.appendChild(link)
50
- link.click()
51
- document.body.removeChild(link)
52
- }
53
-
54
- /**
55
- * 根据动作类型执行对应的动作
56
- */
57
- export async function executeAction(
58
- action: IEventAction,
59
- formValues?: Record<string, any>,
60
- apiParams?: Record<string, any>
61
- ): Promise<void> {
62
- switch (action.type) {
63
- case 'navigation':
64
- return executeNavigationAction(action)
65
- case 'request':
66
- return executeRequestAction(action, formValues, apiParams)
67
- case 'download':
68
- return executeDownloadAction(action)
69
- default:
70
- console.warn(`未知的动作类型: ${(action as any).type}`)
71
- }
72
- }
73
-
74
- /**
75
- * 按顺序执行所有动作
76
- */
77
- export async function executeActions(
78
- actions: IEventAction[],
79
- formValues?: Record<string, any>,
80
- apiParams?: Record<string, any>,
81
- onError?: (error: Error, index: number) => void
82
- ): Promise<void> {
83
- for (let i = 0; i < actions.length; i++) {
84
- try {
85
- await executeAction(actions[i], formValues, apiParams)
86
- } catch (error) {
87
- const err = error instanceof Error ? error : new Error(String(error))
88
- if (onError) {
89
- onError(err, i)
90
- } else {
91
- console.error(`动作 ${i + 1} 执行失败:`, err)
92
- }
93
- // 继续执行后续动作
94
- }
95
- }
96
- }
@@ -1,21 +0,0 @@
1
- import { connect, mapProps } from '@formily/react'
2
- import { FormButtonGroup as ButtonGroup } from '@formily/antd-v5'
3
-
4
- /**
5
- * 表单按钮组
6
- * 为了实现只读模式下不显示按钮,特殊处理一下 FormButtonGroup 组件
7
- * 判断表单模式,如果是只读模式,不显示内部所有按钮
8
- */
9
- export const FormButtonGroup = connect(
10
- ButtonGroup,
11
- mapProps((props, field) => {
12
- return {
13
- ...props,
14
- // 只读模式下不显示按钮
15
- children:
16
- field.form.pattern === 'readOnly' || field.form.pattern === 'readPretty'
17
- ? null
18
- : props.children,
19
- }
20
- })
21
- )
@@ -1 +0,0 @@
1
- export * from './preview'