@faasjs/ant-design 8.0.0-beta.2 → 8.0.0-beta.21
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.
- package/README.md +5 -39
- package/dist/index.d.ts +1314 -598
- package/dist/index.mjs +1948 -1513
- package/package.json +25 -29
- package/dist/index.cjs +0 -1636
package/dist/index.mjs
CHANGED
|
@@ -1,899 +1,1342 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { ErrorBoundary as ErrorBoundary$1, FaasDataWrapper as FaasDataWrapper$1, FaasReactClient, OptionalWrapper, createSplittingContext, faas, useEqualCallback, useEqualEffect, useFaas, withFaasData as withFaasData$1 } from "@faasjs/react";
|
|
2
|
+
import { Alert, Button, Col, ConfigProvider as ConfigProvider$1, DatePicker, Descriptions, Drawer, Form as Form$1, Input, InputNumber, Modal, Radio, Result, Row, Select, Skeleton, Space, Spin, Switch, Table as Table$1, Tabs as Tabs$1, Typography, message, notification, theme } from "antd";
|
|
3
|
+
import { BrowserRouter, Route, Routes as Routes$1, useLocation, useNavigate } from "react-router-dom";
|
|
4
|
+
import { cloneDeep, defaultsDeep, isNil, uniqBy } from "lodash-es";
|
|
5
|
+
import { Suspense, cloneElement, createContext, createElement, isValidElement, lazy, useCallback, useContext, useState } from "react";
|
|
6
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { CheckOutlined, CloseOutlined, MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
|
|
8
|
+
import dayjs from "dayjs";
|
|
9
|
+
//#region src/Loading.tsx
|
|
10
|
+
/**
|
|
11
|
+
* Render an Ant Design loading spinner with an optional content fallback.
|
|
12
|
+
*
|
|
13
|
+
* @param {LoadingProps} props - Loading indicator props and optional wrapped children.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* import { Loading } from '@faasjs/ant-design'
|
|
18
|
+
*
|
|
19
|
+
* export function Page({ remoteData }: { remoteData?: string }) {
|
|
20
|
+
* return (
|
|
21
|
+
* <>
|
|
22
|
+
* <Loading />
|
|
23
|
+
* <Loading loading={!remoteData}>
|
|
24
|
+
* <div>{remoteData}</div>
|
|
25
|
+
* </Loading>
|
|
26
|
+
* </>
|
|
27
|
+
* )
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
13
31
|
function Loading(props) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
children: /* @__PURE__ */ jsx(Spin, { size: props.size || "large" })
|
|
26
|
-
}
|
|
27
|
-
);
|
|
32
|
+
if (props.loading === false) return /* @__PURE__ */ jsx(Fragment, { children: props.children });
|
|
33
|
+
return /* @__PURE__ */ jsx("div", {
|
|
34
|
+
style: {
|
|
35
|
+
...props.style,
|
|
36
|
+
...!props.size || props.size === "large" ? {
|
|
37
|
+
margin: "20vh auto",
|
|
38
|
+
textAlign: "center"
|
|
39
|
+
} : {}
|
|
40
|
+
},
|
|
41
|
+
children: /* @__PURE__ */ jsx(Spin, { size: props.size || "large" })
|
|
42
|
+
});
|
|
28
43
|
}
|
|
29
|
-
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/FaasDataWrapper.tsx
|
|
46
|
+
/**
|
|
47
|
+
* Render the `@faasjs/react` data wrapper with an Ant Design loading fallback.
|
|
48
|
+
*
|
|
49
|
+
* When `loading` is not provided, the component renders {@link Loading} with `loadingProps` while
|
|
50
|
+
* the wrapped FaasJS request is pending.
|
|
51
|
+
*
|
|
52
|
+
* @template T - Action path or response data type used for inference.
|
|
53
|
+
* @param {FaasDataWrapperProps<T>} props - Wrapper props including loading fallbacks and request configuration.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```tsx
|
|
57
|
+
* import { Alert, Button } from 'antd'
|
|
58
|
+
* import { FaasDataWrapper } from '@faasjs/ant-design'
|
|
59
|
+
*
|
|
60
|
+
* type User = {
|
|
61
|
+
* name: string
|
|
62
|
+
* }
|
|
63
|
+
*
|
|
64
|
+
* function UserView(props: {
|
|
65
|
+
* data?: User
|
|
66
|
+
* error?: Error
|
|
67
|
+
* reload?: () => void
|
|
68
|
+
* }) {
|
|
69
|
+
* if (props.error) {
|
|
70
|
+
* return (
|
|
71
|
+
* <Alert
|
|
72
|
+
* type="error"
|
|
73
|
+
* message={props.error.message}
|
|
74
|
+
* action={
|
|
75
|
+
* <Button size="small" onClick={() => props.reload?.()}>
|
|
76
|
+
* Retry
|
|
77
|
+
* </Button>
|
|
78
|
+
* }
|
|
79
|
+
* />
|
|
80
|
+
* )
|
|
81
|
+
* }
|
|
82
|
+
*
|
|
83
|
+
* return <div>Hello, {props.data?.name}</div>
|
|
84
|
+
* }
|
|
85
|
+
*
|
|
86
|
+
* // Render-prop mode
|
|
87
|
+
* export function UserProfile(props: { id: number }) {
|
|
88
|
+
* return (
|
|
89
|
+
* <FaasDataWrapper<User>
|
|
90
|
+
* action="user/get"
|
|
91
|
+
* params={{ id: props.id }}
|
|
92
|
+
* loading={<div>Loading user...</div>}
|
|
93
|
+
* render={({ data, error, reload }) => {
|
|
94
|
+
* if (error) {
|
|
95
|
+
* return (
|
|
96
|
+
* <Alert
|
|
97
|
+
* type="error"
|
|
98
|
+
* message={error.message}
|
|
99
|
+
* action={
|
|
100
|
+
* <Button size="small" onClick={() => reload()}>
|
|
101
|
+
* Retry
|
|
102
|
+
* </Button>
|
|
103
|
+
* }
|
|
104
|
+
* />
|
|
105
|
+
* )
|
|
106
|
+
* }
|
|
107
|
+
*
|
|
108
|
+
* return <div>Hello, {data.name}</div>
|
|
109
|
+
* }}
|
|
110
|
+
* />
|
|
111
|
+
* )
|
|
112
|
+
* }
|
|
113
|
+
*
|
|
114
|
+
* // Children injection mode
|
|
115
|
+
* export function UserProfileWithChildren(props: { id: number }) {
|
|
116
|
+
* return (
|
|
117
|
+
* <FaasDataWrapper<User>
|
|
118
|
+
* action="user/get"
|
|
119
|
+
* params={{ id: props.id }}
|
|
120
|
+
* loading={<div>Loading user...</div>}
|
|
121
|
+
* >
|
|
122
|
+
* <UserView />
|
|
123
|
+
* </FaasDataWrapper>
|
|
124
|
+
* )
|
|
125
|
+
* }
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
30
128
|
function FaasDataWrapper(props) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
...props
|
|
36
|
-
}
|
|
37
|
-
);
|
|
129
|
+
return /* @__PURE__ */ jsx(FaasDataWrapper$1, {
|
|
130
|
+
fallback: props.loading || /* @__PURE__ */ jsx(Loading, { ...props.loadingProps }),
|
|
131
|
+
...props
|
|
132
|
+
});
|
|
38
133
|
}
|
|
39
|
-
|
|
134
|
+
/**
|
|
135
|
+
* Wrap a component with {@link FaasDataWrapper} and its Ant Design loading fallback.
|
|
136
|
+
*
|
|
137
|
+
* @template PathOrData - Action path or response data type used for inference.
|
|
138
|
+
* @template TComponentProps - Component props including injected Faas data fields.
|
|
139
|
+
* @param {React.FC<TComponentProps & Record<string, any>>} Component - Component that consumes injected Faas data props.
|
|
140
|
+
* @param {FaasDataWrapperProps<PathOrData>} faasProps - Request configuration forwarded to {@link FaasDataWrapper}.
|
|
141
|
+
* @returns Higher-order component that injects Faas data props.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```tsx
|
|
145
|
+
* import { withFaasData } from '@faasjs/ant-design'
|
|
146
|
+
*
|
|
147
|
+
* const UserCard = withFaasData(
|
|
148
|
+
* ({ data, error, reload }) =>
|
|
149
|
+
* error ? (
|
|
150
|
+
* <a onClick={() => reload()}>Retry</a>
|
|
151
|
+
* ) : (
|
|
152
|
+
* <div>{data.name}</div>
|
|
153
|
+
* ),
|
|
154
|
+
* { action: 'user/get', params: { id: 1 } },
|
|
155
|
+
* )
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
40
158
|
function withFaasData(Component, faasProps) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
159
|
+
return withFaasData$1(Component, {
|
|
160
|
+
fallback: faasProps.loading || /* @__PURE__ */ jsx(Loading, { ...faasProps.loadingProps }),
|
|
161
|
+
...faasProps
|
|
162
|
+
});
|
|
45
163
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
164
|
+
//#endregion
|
|
165
|
+
//#region src/Config.tsx
|
|
166
|
+
const zh = {
|
|
167
|
+
lang: "zh",
|
|
168
|
+
blank: "空",
|
|
169
|
+
all: "全部",
|
|
170
|
+
submit: "提交",
|
|
171
|
+
pageNotFound: "页面未找到",
|
|
172
|
+
add: "添加",
|
|
173
|
+
delete: "删除",
|
|
174
|
+
required: "必填",
|
|
175
|
+
search: "搜索",
|
|
176
|
+
reset: "重置"
|
|
57
177
|
};
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
178
|
+
const en = {
|
|
179
|
+
lang: "en",
|
|
180
|
+
blank: "Empty",
|
|
181
|
+
all: "All",
|
|
182
|
+
submit: "Submit",
|
|
183
|
+
pageNotFound: "Page Not Found",
|
|
184
|
+
add: "Add",
|
|
185
|
+
delete: "Delete",
|
|
186
|
+
required: "is required",
|
|
187
|
+
search: "Search",
|
|
188
|
+
reset: "Reset"
|
|
69
189
|
};
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
190
|
+
const baseTheme = {
|
|
191
|
+
lang: "en",
|
|
192
|
+
common: en,
|
|
193
|
+
Blank: { text: en.blank },
|
|
194
|
+
Form: { submit: { text: en.submit } },
|
|
195
|
+
Title: {
|
|
196
|
+
separator: " - ",
|
|
197
|
+
suffix: ""
|
|
198
|
+
},
|
|
199
|
+
Link: { style: {} }
|
|
80
200
|
};
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
201
|
+
/**
|
|
202
|
+
* React context storing the resolved FaasJS Ant Design theme.
|
|
203
|
+
*/
|
|
204
|
+
const ConfigContext = createContext({ theme: baseTheme });
|
|
205
|
+
/**
|
|
206
|
+
* Provide theme overrides and optional FaasJS client initialization for descendants.
|
|
207
|
+
*
|
|
208
|
+
* Theme overrides are merged with the built-in defaults. When `theme.lang` is omitted, the
|
|
209
|
+
* provider infers a default language from `navigator.language`.
|
|
210
|
+
*
|
|
211
|
+
* @param {ConfigProviderProps} props - Theme overrides and optional FaasJS client configuration.
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```tsx
|
|
215
|
+
* import { Blank, ConfigProvider } from '@faasjs/ant-design'
|
|
216
|
+
*
|
|
217
|
+
* export function Page() {
|
|
218
|
+
* return (
|
|
219
|
+
* <ConfigProvider theme={{ common: { blank: 'Empty' } }}>
|
|
220
|
+
* <Blank />
|
|
221
|
+
* </ConfigProvider>
|
|
222
|
+
* )
|
|
223
|
+
* }
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
84
226
|
function ConfigProvider(props) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
} else setTheme(defaultsDeep(props.theme, baseTheme));
|
|
102
|
-
if (props.faasClientOptions) FaasReactClient(props.faasClientOptions);
|
|
103
|
-
}, [props.theme]);
|
|
104
|
-
if (!theme2) return null;
|
|
105
|
-
return /* @__PURE__ */ jsx(ConfigContext.Provider, { value: { theme: theme2 }, children: props.children });
|
|
227
|
+
const [theme, setTheme] = useState();
|
|
228
|
+
useEqualEffect(() => {
|
|
229
|
+
if ((props.theme?.lang || (!props.theme?.lang && /^zh/i.test(navigator.language) ? "zh" : "en")) === "zh") setTheme(defaultsDeep(props.theme, {
|
|
230
|
+
lang: "zh",
|
|
231
|
+
common: zh,
|
|
232
|
+
Blank: { text: zh.blank },
|
|
233
|
+
Form: { submit: { text: zh.submit } }
|
|
234
|
+
}, baseTheme));
|
|
235
|
+
else setTheme(defaultsDeep(props.theme, baseTheme));
|
|
236
|
+
if (props.faasClientOptions) FaasReactClient(props.faasClientOptions);
|
|
237
|
+
}, [props.theme]);
|
|
238
|
+
if (!theme) return null;
|
|
239
|
+
return /* @__PURE__ */ jsx(ConfigContext.Provider, {
|
|
240
|
+
value: { theme },
|
|
241
|
+
children: props.children
|
|
242
|
+
});
|
|
106
243
|
}
|
|
244
|
+
/**
|
|
245
|
+
* Read the current `@faasjs/ant-design` config context.
|
|
246
|
+
*
|
|
247
|
+
* @returns Current config context value containing the resolved theme.
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```tsx
|
|
251
|
+
* import { Blank, ConfigProvider, useConfigContext } from '@faasjs/ant-design'
|
|
252
|
+
*
|
|
253
|
+
* function EmptyState() {
|
|
254
|
+
* const { theme } = useConfigContext()
|
|
255
|
+
*
|
|
256
|
+
* return <span>{theme.common.blank}</span>
|
|
257
|
+
* }
|
|
258
|
+
*
|
|
259
|
+
* export function Page() {
|
|
260
|
+
* return (
|
|
261
|
+
* <ConfigProvider theme={{ common: { blank: 'N/A' } }}>
|
|
262
|
+
* <EmptyState />
|
|
263
|
+
* </ConfigProvider>
|
|
264
|
+
* )
|
|
265
|
+
* }
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
107
268
|
function useConfigContext() {
|
|
108
|
-
|
|
269
|
+
return useContext(ConfigContext);
|
|
109
270
|
}
|
|
110
|
-
|
|
111
|
-
Drawer.
|
|
271
|
+
//#endregion
|
|
272
|
+
//#region src/Drawer.tsx
|
|
273
|
+
/**
|
|
274
|
+
* Create a hook-managed Ant Design drawer instance.
|
|
275
|
+
*
|
|
276
|
+
* The returned setter merges partial updates into the current drawer props instead of replacing the
|
|
277
|
+
* entire state object.
|
|
278
|
+
*
|
|
279
|
+
* @param {DrawerProps} [init] - Initial drawer props.
|
|
280
|
+
* @returns Hook-managed drawer element, current props, and a state-merging setter.
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* ```tsx
|
|
284
|
+
* import { useDrawer } from '@faasjs/ant-design'
|
|
285
|
+
* import { Button } from 'antd'
|
|
286
|
+
*
|
|
287
|
+
* function Example() {
|
|
288
|
+
* const { drawer, setDrawerProps } = useDrawer()
|
|
289
|
+
*
|
|
290
|
+
* return (
|
|
291
|
+
* <>
|
|
292
|
+
* <Button onClick={() => setDrawerProps({ open: true, title: 'Details', children: <div>Content</div> })}>
|
|
293
|
+
* Open
|
|
294
|
+
* </Button>
|
|
295
|
+
* {drawer}
|
|
296
|
+
* </>
|
|
297
|
+
* )
|
|
298
|
+
* }
|
|
299
|
+
* ```
|
|
300
|
+
*/
|
|
112
301
|
function useDrawer(init) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
drawerProps: props,
|
|
136
|
-
setDrawerProps
|
|
137
|
-
};
|
|
302
|
+
const [props, setProps] = useState({
|
|
303
|
+
open: false,
|
|
304
|
+
...init
|
|
305
|
+
});
|
|
306
|
+
const setDrawerProps = useEqualCallback((changes) => {
|
|
307
|
+
const changed = typeof changes === "function" ? changes(props) : changes;
|
|
308
|
+
setProps((prev) => ({
|
|
309
|
+
...prev,
|
|
310
|
+
...changed
|
|
311
|
+
}));
|
|
312
|
+
}, [setProps]);
|
|
313
|
+
return {
|
|
314
|
+
drawer: /* @__PURE__ */ jsx(Drawer, {
|
|
315
|
+
onClose: () => setProps((prev) => ({
|
|
316
|
+
...prev,
|
|
317
|
+
open: false
|
|
318
|
+
})),
|
|
319
|
+
...props
|
|
320
|
+
}),
|
|
321
|
+
drawerProps: props,
|
|
322
|
+
setDrawerProps
|
|
323
|
+
};
|
|
138
324
|
}
|
|
325
|
+
//#endregion
|
|
326
|
+
//#region src/ErrorBoundary.tsx
|
|
139
327
|
function ErrorChildren(props) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
},
|
|
152
|
-
children: props.errorDescription
|
|
153
|
-
}
|
|
154
|
-
)
|
|
155
|
-
}
|
|
156
|
-
);
|
|
328
|
+
return /* @__PURE__ */ jsx(Alert, {
|
|
329
|
+
type: "error",
|
|
330
|
+
message: props.errorMessage,
|
|
331
|
+
description: /* @__PURE__ */ jsx("pre", {
|
|
332
|
+
style: {
|
|
333
|
+
fontSize: "0.9em",
|
|
334
|
+
overflowX: "auto"
|
|
335
|
+
},
|
|
336
|
+
children: props.errorDescription
|
|
337
|
+
})
|
|
338
|
+
});
|
|
157
339
|
}
|
|
340
|
+
/**
|
|
341
|
+
* Styled error boundary.
|
|
342
|
+
*
|
|
343
|
+
* When `errorChildren` is not provided, the fallback UI renders an Ant Design `Alert` containing
|
|
344
|
+
* the captured error message and description.
|
|
345
|
+
*
|
|
346
|
+
* @param {ErrorBoundaryProps} props - Error boundary props forwarded to the underlying React implementation.
|
|
347
|
+
*
|
|
348
|
+
* @example
|
|
349
|
+
* ```tsx
|
|
350
|
+
* import { ErrorBoundary } from '@faasjs/ant-design'
|
|
351
|
+
*
|
|
352
|
+
* export function Page() {
|
|
353
|
+
* return (
|
|
354
|
+
* <ErrorBoundary>
|
|
355
|
+
* <DangerousWidget />
|
|
356
|
+
* </ErrorBoundary>
|
|
357
|
+
* )
|
|
358
|
+
* }
|
|
359
|
+
* ```
|
|
360
|
+
*/
|
|
158
361
|
function ErrorBoundary(props) {
|
|
159
|
-
|
|
362
|
+
return /* @__PURE__ */ jsx(ErrorBoundary$1, {
|
|
363
|
+
errorChildren: /* @__PURE__ */ jsx(ErrorChildren, {}),
|
|
364
|
+
...props
|
|
365
|
+
});
|
|
160
366
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
367
|
+
//#endregion
|
|
368
|
+
//#region src/Modal.tsx
|
|
369
|
+
/**
|
|
370
|
+
* Create a hook-managed Ant Design modal instance.
|
|
371
|
+
*
|
|
372
|
+
* The returned setter merges partial updates into the current modal props instead of replacing the
|
|
373
|
+
* entire state object.
|
|
374
|
+
*
|
|
375
|
+
* @param {ModalProps} [init] - Initial modal props.
|
|
376
|
+
* @returns Hook-managed modal element, current props, and a state-merging setter.
|
|
377
|
+
*
|
|
378
|
+
* @example
|
|
379
|
+
* ```tsx
|
|
380
|
+
* import { useModal } from '@faasjs/ant-design'
|
|
381
|
+
* import { Button } from 'antd'
|
|
382
|
+
*
|
|
383
|
+
* function Example() {
|
|
384
|
+
* const { modal, setModalProps } = useModal()
|
|
385
|
+
*
|
|
386
|
+
* return (
|
|
387
|
+
* <>
|
|
388
|
+
* <Button onClick={() => setModalProps({ open: true, title: 'Delete', children: 'Are you sure?' })}>
|
|
389
|
+
* Open Modal
|
|
390
|
+
* </Button>
|
|
391
|
+
* {modal}
|
|
392
|
+
* </>
|
|
393
|
+
* )
|
|
394
|
+
* }
|
|
395
|
+
* ```
|
|
396
|
+
*/
|
|
164
397
|
function useModal(init) {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
398
|
+
const [props, setProps] = useState({
|
|
399
|
+
open: false,
|
|
400
|
+
...init
|
|
401
|
+
});
|
|
402
|
+
const setModalProps = useEqualCallback((changes) => {
|
|
403
|
+
const changed = typeof changes === "function" ? changes(props) : changes;
|
|
404
|
+
setProps((prev) => ({
|
|
405
|
+
...prev,
|
|
406
|
+
...changed
|
|
407
|
+
}));
|
|
408
|
+
}, [setProps]);
|
|
409
|
+
return {
|
|
410
|
+
modal: /* @__PURE__ */ jsx(Modal, {
|
|
411
|
+
onCancel: () => setProps((prev) => ({
|
|
412
|
+
...prev,
|
|
413
|
+
open: false
|
|
414
|
+
})),
|
|
415
|
+
...props
|
|
416
|
+
}),
|
|
417
|
+
modalProps: props,
|
|
418
|
+
setModalProps
|
|
419
|
+
};
|
|
187
420
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
421
|
+
//#endregion
|
|
422
|
+
//#region src/useApp.ts
|
|
423
|
+
/**
|
|
424
|
+
* Shared context storing message, notification, modal, and drawer helpers.
|
|
425
|
+
*/
|
|
426
|
+
const AppContext = createSplittingContext([
|
|
427
|
+
"message",
|
|
428
|
+
"notification",
|
|
429
|
+
"modalProps",
|
|
430
|
+
"setModalProps",
|
|
431
|
+
"drawerProps",
|
|
432
|
+
"setDrawerProps"
|
|
195
433
|
]);
|
|
434
|
+
/**
|
|
435
|
+
* Read app-level services exposed by the root `App` component.
|
|
436
|
+
*
|
|
437
|
+
* @template NewT - Narrowed app context shape to read from `AppContext`.
|
|
438
|
+
* @returns Read-only app context value.
|
|
439
|
+
*
|
|
440
|
+
* @example
|
|
441
|
+
* ```tsx
|
|
442
|
+
* import { App, useApp } from '@faasjs/ant-design'
|
|
443
|
+
* import { Button } from 'antd'
|
|
444
|
+
*
|
|
445
|
+
* function Page() {
|
|
446
|
+
* const { message, setModalProps } = useApp()
|
|
447
|
+
*
|
|
448
|
+
* return (
|
|
449
|
+
* <Button
|
|
450
|
+
* onClick={() => {
|
|
451
|
+
* message.success('Saved')
|
|
452
|
+
* setModalProps({ open: true, title: 'Done', children: 'Profile updated.' })
|
|
453
|
+
* }}
|
|
454
|
+
* >
|
|
455
|
+
* Save
|
|
456
|
+
* </Button>
|
|
457
|
+
* )
|
|
458
|
+
* }
|
|
459
|
+
*
|
|
460
|
+
* export function Root() {
|
|
461
|
+
* return (
|
|
462
|
+
* <App>
|
|
463
|
+
* <Page />
|
|
464
|
+
* </App>
|
|
465
|
+
* )
|
|
466
|
+
* }
|
|
467
|
+
* ```
|
|
468
|
+
*/
|
|
469
|
+
function useApp() {
|
|
470
|
+
return AppContext.use();
|
|
471
|
+
}
|
|
472
|
+
//#endregion
|
|
473
|
+
//#region src/App.tsx
|
|
196
474
|
function RoutesApp(props) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
475
|
+
const location = useLocation();
|
|
476
|
+
const { drawerProps, setDrawerProps, modalProps, setModalProps } = useApp();
|
|
477
|
+
useEqualEffect(() => {
|
|
478
|
+
console.debug("location", location);
|
|
479
|
+
if (drawerProps.open) setDrawerProps({ open: false });
|
|
480
|
+
if (modalProps.open) setModalProps({ open: false });
|
|
481
|
+
}, [location]);
|
|
482
|
+
return /* @__PURE__ */ jsx(Fragment, { children: props.children });
|
|
205
483
|
}
|
|
484
|
+
/**
|
|
485
|
+
* Render the root provider shell for a FaasJS Ant Design application.
|
|
486
|
+
*
|
|
487
|
+
* `App` initializes Ant Design message and notification APIs, exposes hook-managed modal and
|
|
488
|
+
* drawer state through {@link AppContext}, wraps descendants with {@link ErrorBoundary}, and
|
|
489
|
+
* optionally mounts React Router's `BrowserRouter`.
|
|
490
|
+
*
|
|
491
|
+
* @param {AppProps} props - App shell props including providers, routing, and error handling options.
|
|
492
|
+
*
|
|
493
|
+
* @example
|
|
494
|
+
* ```tsx
|
|
495
|
+
* import { App } from '@faasjs/ant-design'
|
|
496
|
+
*
|
|
497
|
+
* export default function Page() {
|
|
498
|
+
* return (
|
|
499
|
+
* <App
|
|
500
|
+
* configProviderProps={{}}
|
|
501
|
+
* browserRouterProps={{}}
|
|
502
|
+
* errorBoundaryProps={{}}
|
|
503
|
+
* faasConfigProviderProps={{}}
|
|
504
|
+
* >
|
|
505
|
+
* <div>content</div>
|
|
506
|
+
* </App>
|
|
507
|
+
* )
|
|
508
|
+
* }
|
|
509
|
+
* ```
|
|
510
|
+
*/
|
|
206
511
|
function App(props) {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
props.browserRouterProps !== false ? /* @__PURE__ */ jsx(RoutesApp, { children: props.children }) : props.children
|
|
253
|
-
]
|
|
254
|
-
}
|
|
255
|
-
) })
|
|
256
|
-
}
|
|
257
|
-
)
|
|
258
|
-
}
|
|
259
|
-
)
|
|
260
|
-
}
|
|
261
|
-
);
|
|
512
|
+
const [messageApi, messageContextHolder] = message.useMessage();
|
|
513
|
+
const [notificationApi, notificationContextHolder] = notification.useNotification();
|
|
514
|
+
const { modal, modalProps, setModalProps } = useModal({ destroyOnHidden: true });
|
|
515
|
+
const { drawer, drawerProps, setDrawerProps } = useDrawer({ destroyOnHidden: true });
|
|
516
|
+
return /* @__PURE__ */ jsx(OptionalWrapper, {
|
|
517
|
+
condition: !!props.configProviderProps,
|
|
518
|
+
Wrapper: ConfigProvider$1,
|
|
519
|
+
wrapperProps: props.configProviderProps,
|
|
520
|
+
children: /* @__PURE__ */ jsx(AppContext.Provider, {
|
|
521
|
+
value: {
|
|
522
|
+
message: messageApi,
|
|
523
|
+
notification: notificationApi,
|
|
524
|
+
drawerProps,
|
|
525
|
+
setDrawerProps,
|
|
526
|
+
modalProps,
|
|
527
|
+
setModalProps
|
|
528
|
+
},
|
|
529
|
+
children: /* @__PURE__ */ jsx(ConfigProvider, {
|
|
530
|
+
...props.faasConfigProviderProps,
|
|
531
|
+
faasClientOptions: {
|
|
532
|
+
onError: (action) => async (res) => {
|
|
533
|
+
if ("message" in res && res.toString().includes("AbortError")) return;
|
|
534
|
+
console.error(`[FaasJS][${action}]`, res);
|
|
535
|
+
messageApi.error("message" in res ? res.message : "Unknown error");
|
|
536
|
+
},
|
|
537
|
+
...props.faasConfigProviderProps ? props.faasConfigProviderProps.faasClientOptions : {}
|
|
538
|
+
},
|
|
539
|
+
children: /* @__PURE__ */ jsx(ErrorBoundary, {
|
|
540
|
+
...props.errorBoundaryProps,
|
|
541
|
+
children: /* @__PURE__ */ jsxs(OptionalWrapper, {
|
|
542
|
+
condition: typeof document !== "undefined" && props.browserRouterProps !== false,
|
|
543
|
+
Wrapper: BrowserRouter,
|
|
544
|
+
wrapperProps: props.browserRouterProps,
|
|
545
|
+
children: [
|
|
546
|
+
messageContextHolder,
|
|
547
|
+
notificationContextHolder,
|
|
548
|
+
modal,
|
|
549
|
+
drawer,
|
|
550
|
+
props.browserRouterProps !== false ? /* @__PURE__ */ jsx(RoutesApp, { children: props.children }) : props.children
|
|
551
|
+
]
|
|
552
|
+
})
|
|
553
|
+
})
|
|
554
|
+
})
|
|
555
|
+
})
|
|
556
|
+
});
|
|
262
557
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
558
|
+
//#endregion
|
|
559
|
+
//#region src/Blank.tsx
|
|
560
|
+
/**
|
|
561
|
+
* Render a disabled placeholder when a value is empty.
|
|
562
|
+
*
|
|
563
|
+
* Empty values include `undefined`, `null`, empty strings, and empty arrays.
|
|
564
|
+
*
|
|
565
|
+
* @param {BlankProps} [options] - Placeholder text and value to render.
|
|
566
|
+
* @returns Rendered value or the configured placeholder text.
|
|
567
|
+
*
|
|
568
|
+
* @example
|
|
569
|
+
* ```tsx
|
|
570
|
+
* import { Blank } from '@faasjs/ant-design'
|
|
571
|
+
*
|
|
572
|
+
* export function FieldPreview() {
|
|
573
|
+
* return <Blank value={undefined} text="Empty" />
|
|
574
|
+
* }
|
|
575
|
+
* ```
|
|
576
|
+
*/
|
|
266
577
|
function Blank(options) {
|
|
267
|
-
|
|
268
|
-
|
|
578
|
+
const { theme } = useConfigContext();
|
|
579
|
+
return !options || options.value === void 0 || options.value === null || Array.isArray(options.value) && !options.value.length || options.value === "" ? /* @__PURE__ */ jsx(Typography.Text, {
|
|
580
|
+
disabled: true,
|
|
581
|
+
children: options?.text || theme.Blank.text
|
|
582
|
+
}) : options.value;
|
|
269
583
|
}
|
|
270
|
-
|
|
584
|
+
//#endregion
|
|
585
|
+
//#region src/data.ts
|
|
586
|
+
/**
|
|
587
|
+
* Convert a snake_case, kebab-case, or spaced identifier into a title-style label.
|
|
588
|
+
*
|
|
589
|
+
* @param {string | number} id - Identifier to convert.
|
|
590
|
+
* @returns Generated label string.
|
|
591
|
+
*
|
|
592
|
+
* @example
|
|
593
|
+
* ```ts
|
|
594
|
+
* idToTitle('example_id') // 'Example Id'
|
|
595
|
+
* ```
|
|
596
|
+
*/
|
|
271
597
|
function idToTitle(id) {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
598
|
+
if (typeof id === "number") return id.toString();
|
|
599
|
+
const splitted = id.split(/(\s|_|-)/).filter((word) => !/(\s|_|-)/.test(word)).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
600
|
+
return splitted.charAt(0).toUpperCase() + splitted.slice(1);
|
|
275
601
|
}
|
|
602
|
+
/**
|
|
603
|
+
* Normalize primitive options into explicit `{ label, value }` objects.
|
|
604
|
+
*
|
|
605
|
+
* String and number options are converted with {@link idToTitle}, while pre-shaped option objects
|
|
606
|
+
* are returned as-is.
|
|
607
|
+
*
|
|
608
|
+
* @param {BaseOption[]} options - Raw option list to normalize.
|
|
609
|
+
* @returns Normalized option list.
|
|
610
|
+
*
|
|
611
|
+
* @example
|
|
612
|
+
* ```ts
|
|
613
|
+
* import { transferOptions } from '@faasjs/ant-design'
|
|
614
|
+
*
|
|
615
|
+
* transferOptions(['draft', { label: 'Published', value: 'published' }])
|
|
616
|
+
* // [
|
|
617
|
+
* // { label: 'Draft', value: 'draft' },
|
|
618
|
+
* // { label: 'Published', value: 'published' },
|
|
619
|
+
* // ]
|
|
620
|
+
* ```
|
|
621
|
+
*/
|
|
276
622
|
function transferOptions(options) {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
}
|
|
283
|
-
);
|
|
623
|
+
if (!options) return [];
|
|
624
|
+
return options.map((item) => typeof item === "object" ? item : {
|
|
625
|
+
label: idToTitle(item.toString()),
|
|
626
|
+
value: item
|
|
627
|
+
});
|
|
284
628
|
}
|
|
629
|
+
/**
|
|
630
|
+
* Normalize raw values into the runtime shape expected by FaasJS Ant Design components.
|
|
631
|
+
*
|
|
632
|
+
* Primitive strings such as `'null'` and `'undefined'` become `null`, comma-delimited array
|
|
633
|
+
* strings are split into arrays, and date or time values are converted to `dayjs` objects.
|
|
634
|
+
*
|
|
635
|
+
* @param {FaasItemType | null | undefined} type - Target field type.
|
|
636
|
+
* @param {any} value - Raw value to normalize.
|
|
637
|
+
* @returns Normalized value for rendering or form initialization.
|
|
638
|
+
*
|
|
639
|
+
* @example
|
|
640
|
+
* ```ts
|
|
641
|
+
* import { transferValue } from '@faasjs/ant-design'
|
|
642
|
+
*
|
|
643
|
+
* transferValue('number', '42') // 42
|
|
644
|
+
* transferValue('boolean', 'true') // true
|
|
645
|
+
* transferValue('string[]', 'a,b') // ['a', 'b']
|
|
646
|
+
* ```
|
|
647
|
+
*/
|
|
285
648
|
function transferValue(type, value) {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
if (!dayjs2.isDayjs(value)) value = dayjs2(value);
|
|
309
|
-
break;
|
|
310
|
-
}
|
|
311
|
-
return value;
|
|
649
|
+
if (!type) type = "string";
|
|
650
|
+
if (!type.endsWith("[]") && (typeof value === "undefined" || value === null || value === "" || value === "null" || value === "undefined")) return null;
|
|
651
|
+
if (type.endsWith("[]")) {
|
|
652
|
+
if (!value) value = [];
|
|
653
|
+
if (typeof value === "string") value = value.split(",").filter(Boolean);
|
|
654
|
+
if (!Array.isArray(value)) value = [value];
|
|
655
|
+
value = value.map((item) => transferValue(type.replace("[]", ""), item));
|
|
656
|
+
}
|
|
657
|
+
switch (type) {
|
|
658
|
+
case "boolean":
|
|
659
|
+
if (typeof value === "string") value = value === "true";
|
|
660
|
+
break;
|
|
661
|
+
case "number":
|
|
662
|
+
if (typeof value === "string") value = Number(value);
|
|
663
|
+
break;
|
|
664
|
+
case "date":
|
|
665
|
+
case "time":
|
|
666
|
+
if (typeof value === "number" && value.toString().length === 10) value = value * 1e3;
|
|
667
|
+
if (!dayjs.isDayjs(value)) value = dayjs(value);
|
|
668
|
+
break;
|
|
669
|
+
}
|
|
670
|
+
return value;
|
|
312
671
|
}
|
|
672
|
+
/**
|
|
673
|
+
* Clone a {@link UnionFaasItemElement} with FaasJS injection props.
|
|
674
|
+
*
|
|
675
|
+
* React elements are cloned directly, while component references are first wrapped with
|
|
676
|
+
* `createElement`.
|
|
677
|
+
*
|
|
678
|
+
* @param {UnionFaasItemElement} element - Element or component to clone.
|
|
679
|
+
* @param {any} props - Injection props such as `scene`, `value`, `values`, and `index`.
|
|
680
|
+
* @returns Cloned React element ready for rendering.
|
|
681
|
+
*
|
|
682
|
+
* @example
|
|
683
|
+
* ```tsx
|
|
684
|
+
* import { cloneUnionFaasItemElement, type UnionFaasItemElement } from '@faasjs/ant-design'
|
|
685
|
+
*
|
|
686
|
+
* const Cell: UnionFaasItemElement<string> = ({ value }) => <span>{value}</span>
|
|
687
|
+
*
|
|
688
|
+
* const element = cloneUnionFaasItemElement(Cell, {
|
|
689
|
+
* scene: 'table',
|
|
690
|
+
* value: 'Hello',
|
|
691
|
+
* index: 0,
|
|
692
|
+
* })
|
|
693
|
+
* ```
|
|
694
|
+
*/
|
|
313
695
|
function cloneUnionFaasItemElement(element, props) {
|
|
314
|
-
|
|
315
|
-
isValidElement(element) ? element : createElement(element),
|
|
316
|
-
props
|
|
317
|
-
);
|
|
696
|
+
return cloneElement(isValidElement(element) ? element : createElement(element), props);
|
|
318
697
|
}
|
|
698
|
+
//#endregion
|
|
699
|
+
//#region src/Description.tsx
|
|
319
700
|
function DescriptionItemContent(props) {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
{
|
|
393
|
-
style: {
|
|
394
|
-
marginTop: "4px",
|
|
395
|
-
color: "#ff4d4f"
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
);
|
|
399
|
-
case "time":
|
|
400
|
-
return /* @__PURE__ */ jsx(Fragment, { children: computedProps.value.format("YYYY-MM-DD HH:mm:ss") });
|
|
401
|
-
case "date":
|
|
402
|
-
return /* @__PURE__ */ jsx(Fragment, { children: computedProps.value.format("YYYY-MM-DD") });
|
|
403
|
-
case "object":
|
|
404
|
-
if (!computedProps.value) return /* @__PURE__ */ jsx(Blank, {});
|
|
405
|
-
return /* @__PURE__ */ jsx(
|
|
406
|
-
Description,
|
|
407
|
-
{
|
|
408
|
-
items: computedProps.item.object,
|
|
409
|
-
dataSource: computedProps.value,
|
|
410
|
-
column: 1
|
|
411
|
-
}
|
|
412
|
-
);
|
|
413
|
-
case "object[]":
|
|
414
|
-
if (!computedProps.value?.length)
|
|
415
|
-
return /* @__PURE__ */ jsx(Blank, {});
|
|
416
|
-
return /* @__PURE__ */ jsx(Space, { direction: "vertical", children: computedProps.value.map(
|
|
417
|
-
(value, index) => /* @__PURE__ */ jsx(
|
|
418
|
-
Description,
|
|
419
|
-
{
|
|
420
|
-
items: computedProps.item.object,
|
|
421
|
-
dataSource: value,
|
|
422
|
-
column: 1
|
|
423
|
-
},
|
|
424
|
-
index
|
|
425
|
-
)
|
|
426
|
-
) });
|
|
427
|
-
default:
|
|
428
|
-
return computedProps.value || null;
|
|
429
|
-
}
|
|
701
|
+
const [computedProps, setComputedProps] = useState();
|
|
702
|
+
useEqualEffect(() => {
|
|
703
|
+
const propsCopy = { ...props };
|
|
704
|
+
propsCopy.item.title = propsCopy.item.title ?? idToTitle(propsCopy.item.id);
|
|
705
|
+
if (!propsCopy.item.type) propsCopy.item.type = "string";
|
|
706
|
+
if (propsCopy.item.options?.length) propsCopy.item.options = transferOptions(propsCopy.item.options);
|
|
707
|
+
propsCopy.value = transferValue(propsCopy.item.type, propsCopy.value);
|
|
708
|
+
if (propsCopy.item.options && propsCopy.value !== null) {
|
|
709
|
+
if (propsCopy.item.type.endsWith("[]")) propsCopy.value = propsCopy.value.map((v) => propsCopy.item.options.find((option) => option.value === v)?.label || v);
|
|
710
|
+
else if ([
|
|
711
|
+
"string",
|
|
712
|
+
"number",
|
|
713
|
+
"boolean"
|
|
714
|
+
].includes(propsCopy.item.type)) propsCopy.value = props.item.options.find((option) => option.value === props.value)?.label || props.value;
|
|
715
|
+
}
|
|
716
|
+
setComputedProps(propsCopy);
|
|
717
|
+
}, [props]);
|
|
718
|
+
if (!computedProps) return null;
|
|
719
|
+
const itemType = computedProps.item.type ?? "string";
|
|
720
|
+
if (computedProps.item.descriptionChildren === null || computedProps.item.children === null || computedProps.item.descriptionRender === null || computedProps.item.render === null) return null;
|
|
721
|
+
const children = computedProps.item.descriptionChildren || computedProps.item.children;
|
|
722
|
+
if (children) return cloneUnionFaasItemElement(children, {
|
|
723
|
+
scene: "description",
|
|
724
|
+
value: computedProps.value,
|
|
725
|
+
values: computedProps.values,
|
|
726
|
+
index: 0
|
|
727
|
+
});
|
|
728
|
+
const render = computedProps.item.descriptionRender || computedProps.item.render;
|
|
729
|
+
if (render) return /* @__PURE__ */ jsx(Fragment, { children: render(computedProps.value, computedProps.values, 0, "description") });
|
|
730
|
+
if (computedProps.extendTypes?.[itemType]) {
|
|
731
|
+
const extendType = computedProps.extendTypes[itemType];
|
|
732
|
+
if (extendType.children) return cloneUnionFaasItemElement(extendType.children, {
|
|
733
|
+
scene: "description",
|
|
734
|
+
value: computedProps.value,
|
|
735
|
+
values: computedProps.values
|
|
736
|
+
});
|
|
737
|
+
if (extendType.render) return /* @__PURE__ */ jsx(Fragment, { children: extendType.render(computedProps.value, computedProps.values, 0, "description") });
|
|
738
|
+
throw Error(`${itemType} requires children or render`);
|
|
739
|
+
}
|
|
740
|
+
if (computedProps.value === null || Array.isArray(computedProps.value) && !computedProps.value.length) return /* @__PURE__ */ jsx(Blank, {});
|
|
741
|
+
switch (itemType) {
|
|
742
|
+
case "string[]": return /* @__PURE__ */ jsx(Fragment, { children: computedProps.value.join(", ") });
|
|
743
|
+
case "number": return computedProps.value || null;
|
|
744
|
+
case "number[]": return /* @__PURE__ */ jsx(Fragment, { children: computedProps.value.join(", ") });
|
|
745
|
+
case "boolean": return computedProps.value ? /* @__PURE__ */ jsx(CheckOutlined, { style: {
|
|
746
|
+
marginTop: "4px",
|
|
747
|
+
color: "#52c41a"
|
|
748
|
+
} }) : /* @__PURE__ */ jsx(CloseOutlined, { style: {
|
|
749
|
+
marginTop: "4px",
|
|
750
|
+
color: "#ff4d4f"
|
|
751
|
+
} });
|
|
752
|
+
case "time": return /* @__PURE__ */ jsx(Fragment, { children: computedProps.value.format("YYYY-MM-DD HH:mm:ss") });
|
|
753
|
+
case "date": return /* @__PURE__ */ jsx(Fragment, { children: computedProps.value.format("YYYY-MM-DD") });
|
|
754
|
+
case "object":
|
|
755
|
+
if (!computedProps.value) return /* @__PURE__ */ jsx(Blank, {});
|
|
756
|
+
return /* @__PURE__ */ jsx(Description, {
|
|
757
|
+
items: computedProps.item.object || [],
|
|
758
|
+
dataSource: computedProps.value,
|
|
759
|
+
column: 1
|
|
760
|
+
});
|
|
761
|
+
case "object[]":
|
|
762
|
+
if (!computedProps.value?.length) return /* @__PURE__ */ jsx(Blank, {});
|
|
763
|
+
return /* @__PURE__ */ jsx(Space, {
|
|
764
|
+
direction: "vertical",
|
|
765
|
+
children: computedProps.value.map((value, index) => /* @__PURE__ */ jsx(Description, {
|
|
766
|
+
items: computedProps.item.object || [],
|
|
767
|
+
dataSource: value,
|
|
768
|
+
column: 1
|
|
769
|
+
}, index))
|
|
770
|
+
});
|
|
771
|
+
default: return computedProps.value || null;
|
|
772
|
+
}
|
|
430
773
|
}
|
|
431
774
|
DescriptionItemContent.displayName = "DescriptionItemContent";
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
775
|
+
/**
|
|
776
|
+
* Render an Ant Design description list from FaasJS item metadata.
|
|
777
|
+
*
|
|
778
|
+
* The component can render a local `dataSource` directly or resolve one through `faasData`, and
|
|
779
|
+
* it applies the same item type normalization helpers used by the form and table components.
|
|
780
|
+
*
|
|
781
|
+
* @template T - Data record shape rendered by the component.
|
|
782
|
+
* @param {DescriptionProps<T>} props - Description props including items, data source, and optional Faas data config.
|
|
783
|
+
* @throws {Error} When an entry in `extendTypes` omits both `children` and `render`.
|
|
784
|
+
*
|
|
785
|
+
* @example
|
|
786
|
+
* ```tsx
|
|
787
|
+
* import { Description } from '@faasjs/ant-design'
|
|
788
|
+
*
|
|
789
|
+
* export function Detail() {
|
|
790
|
+
* return (
|
|
791
|
+
* <Description
|
|
792
|
+
* title="Title"
|
|
793
|
+
* items={[
|
|
794
|
+
* {
|
|
795
|
+
* id: 'id',
|
|
796
|
+
* title: 'Title',
|
|
797
|
+
* type: 'string',
|
|
798
|
+
* },
|
|
799
|
+
* ]}
|
|
800
|
+
* dataSource={{ id: 'value' }}
|
|
801
|
+
* />
|
|
802
|
+
* )
|
|
803
|
+
* }
|
|
804
|
+
* ```
|
|
805
|
+
*/
|
|
806
|
+
function Description(props) {
|
|
807
|
+
const { faasData, dataSource, renderTitle, extendTypes, ...descriptionProps } = props;
|
|
808
|
+
if (faasData && !dataSource) {
|
|
809
|
+
const faasDataProps = {
|
|
810
|
+
action: faasData.action,
|
|
811
|
+
render: ({ data }) => /* @__PURE__ */ jsx(Description, {
|
|
812
|
+
...descriptionProps,
|
|
813
|
+
dataSource: data,
|
|
814
|
+
...renderTitle ? { renderTitle } : {},
|
|
815
|
+
...extendTypes ? { extendTypes } : {}
|
|
816
|
+
})
|
|
817
|
+
};
|
|
818
|
+
if (faasData.baseUrl !== void 0) faasDataProps.baseUrl = faasData.baseUrl;
|
|
819
|
+
if (faasData.data !== void 0) faasDataProps.data = faasData.data;
|
|
820
|
+
if (faasData.fallback !== void 0) faasDataProps.fallback = faasData.fallback;
|
|
821
|
+
if (faasData.onDataChange !== void 0) faasDataProps.onDataChange = (args) => faasData.onDataChange?.(args);
|
|
822
|
+
if (faasData.params !== void 0) faasDataProps.params = faasData.params;
|
|
823
|
+
if (faasData.ref !== void 0) faasDataProps.ref = faasData.ref;
|
|
824
|
+
if (faasData.setData !== void 0) faasDataProps.setData = faasData.setData;
|
|
825
|
+
return /* @__PURE__ */ jsx(FaasDataWrapper, { ...faasDataProps });
|
|
826
|
+
}
|
|
827
|
+
return /* @__PURE__ */ jsx(Descriptions, {
|
|
828
|
+
...descriptionProps,
|
|
829
|
+
title: typeof renderTitle === "function" ? renderTitle(dataSource) : descriptionProps.title,
|
|
830
|
+
items: descriptionProps.items.filter((item) => item && !(item.descriptionChildren === null || item.children === null || item.descriptionRender === null || item.render === null) && (!item.if || item.if(dataSource))).map((item) => ({
|
|
831
|
+
...item,
|
|
832
|
+
key: item.id,
|
|
833
|
+
label: item.title ?? idToTitle(item.id),
|
|
834
|
+
children: /* @__PURE__ */ jsx(DescriptionItemContent, {
|
|
835
|
+
item,
|
|
836
|
+
value: dataSource ? dataSource[item.id] : null,
|
|
837
|
+
...dataSource ? { values: dataSource } : {},
|
|
838
|
+
...extendTypes ? { extendTypes } : {}
|
|
839
|
+
})
|
|
840
|
+
}))
|
|
841
|
+
});
|
|
479
842
|
}
|
|
480
843
|
Description.displayName = "Description";
|
|
481
|
-
|
|
844
|
+
//#endregion
|
|
845
|
+
//#region src/FormItem.tsx
|
|
482
846
|
function isOptionsProps(item) {
|
|
483
|
-
|
|
847
|
+
return item && Array.isArray(item.options);
|
|
484
848
|
}
|
|
485
849
|
function processProps(propsCopy, config) {
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
case "object":
|
|
517
|
-
if (!Array.isArray(propsCopy.name)) propsCopy.name = [propsCopy.name];
|
|
518
|
-
for (const sub of propsCopy.object) {
|
|
519
|
-
if (!sub.name) sub.name = propsCopy.name.concat(sub.id);
|
|
520
|
-
processProps(sub, config);
|
|
521
|
-
}
|
|
522
|
-
break;
|
|
523
|
-
}
|
|
524
|
-
return propsCopy;
|
|
850
|
+
propsCopy.title = propsCopy.title ?? idToTitle(propsCopy.id);
|
|
851
|
+
if (!propsCopy.label && propsCopy.label !== false) propsCopy.label = propsCopy.title;
|
|
852
|
+
if (!propsCopy.name) propsCopy.name = propsCopy.id;
|
|
853
|
+
if (!propsCopy.type) propsCopy.type = "string";
|
|
854
|
+
if (!propsCopy.rules) propsCopy.rules = [];
|
|
855
|
+
if (propsCopy.required) if (propsCopy.type.endsWith("[]")) propsCopy.rules.push({
|
|
856
|
+
required: true,
|
|
857
|
+
validator: async (_, values) => {
|
|
858
|
+
if (!values || values.length < 1) return Promise.reject(Error(`${propsCopy.label || propsCopy.title} ${config.required}`));
|
|
859
|
+
}
|
|
860
|
+
});
|
|
861
|
+
else propsCopy.rules.push({
|
|
862
|
+
required: true,
|
|
863
|
+
message: `${propsCopy.label || propsCopy.title} ${config.required}`
|
|
864
|
+
});
|
|
865
|
+
if (!propsCopy.input) propsCopy.input = {};
|
|
866
|
+
if (isOptionsProps(propsCopy)) propsCopy.input.options = transferOptions(propsCopy.options);
|
|
867
|
+
switch (propsCopy.type) {
|
|
868
|
+
case "boolean":
|
|
869
|
+
propsCopy.valuePropName = "checked";
|
|
870
|
+
break;
|
|
871
|
+
case "object":
|
|
872
|
+
if (!Array.isArray(propsCopy.name)) propsCopy.name = [propsCopy.name];
|
|
873
|
+
for (const sub of propsCopy.object || []) {
|
|
874
|
+
if (!sub.name) sub.name = propsCopy.name.concat(sub.id);
|
|
875
|
+
processProps(sub, config);
|
|
876
|
+
}
|
|
877
|
+
break;
|
|
878
|
+
}
|
|
879
|
+
return propsCopy;
|
|
525
880
|
}
|
|
881
|
+
/**
|
|
882
|
+
* Render a FaasJS-aware Ant Design form field or nested field group.
|
|
883
|
+
*
|
|
884
|
+
* The component derives default labels from `id`, applies required validation messages from the
|
|
885
|
+
* active theme, supports surface-specific union renderers, and can render nested `object` or
|
|
886
|
+
* `object[]` field structures.
|
|
887
|
+
*
|
|
888
|
+
* @template T - Value type rendered or edited by the form item.
|
|
889
|
+
* @param {FormItemProps<T>} props - Form item props including field metadata, rules, and custom renderers.
|
|
890
|
+
*
|
|
891
|
+
* @example
|
|
892
|
+
* ```tsx
|
|
893
|
+
* import { FormItem } from '@faasjs/ant-design'
|
|
894
|
+
* import { Input } from 'antd'
|
|
895
|
+
*
|
|
896
|
+
* export function AccountFields() {
|
|
897
|
+
* return (
|
|
898
|
+
* <>
|
|
899
|
+
* <FormItem id="name" type="string" />
|
|
900
|
+
* <FormItem id="password">
|
|
901
|
+
* <Input.Password />
|
|
902
|
+
* </FormItem>
|
|
903
|
+
* </>
|
|
904
|
+
* )
|
|
905
|
+
* }
|
|
906
|
+
* ```
|
|
907
|
+
*/
|
|
526
908
|
function FormItem(props) {
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
/* @__PURE__ */ jsx(Form$1.ErrorList, { errors })
|
|
765
|
-
] })
|
|
766
|
-
] })
|
|
767
|
-
}
|
|
768
|
-
);
|
|
769
|
-
default:
|
|
770
|
-
return null;
|
|
771
|
-
}
|
|
909
|
+
const [computedProps, setComputedProps] = useState();
|
|
910
|
+
const [extendTypes, setExtendTypes] = useState();
|
|
911
|
+
const { theme } = useConfigContext();
|
|
912
|
+
const [hidden, setHidden] = useState(props.hidden || false);
|
|
913
|
+
useEqualEffect(() => {
|
|
914
|
+
const { extendTypes, ...propsCopy } = { ...props };
|
|
915
|
+
if (extendTypes) setExtendTypes(extendTypes);
|
|
916
|
+
if (propsCopy.if) {
|
|
917
|
+
const condition = propsCopy.if;
|
|
918
|
+
const originShouldUpdate = propsCopy.shouldUpdate;
|
|
919
|
+
propsCopy.shouldUpdate = (prev, cur) => {
|
|
920
|
+
const show = condition(cur);
|
|
921
|
+
const shouldUpdate = hidden !== show;
|
|
922
|
+
setHidden(!show);
|
|
923
|
+
const origin = originShouldUpdate ? typeof originShouldUpdate === "boolean" ? originShouldUpdate : originShouldUpdate(prev, cur, {}) : true;
|
|
924
|
+
return shouldUpdate || origin;
|
|
925
|
+
};
|
|
926
|
+
delete propsCopy.if;
|
|
927
|
+
delete propsCopy.hidden;
|
|
928
|
+
}
|
|
929
|
+
setComputedProps(processProps(propsCopy, theme.common));
|
|
930
|
+
}, [
|
|
931
|
+
hidden,
|
|
932
|
+
props,
|
|
933
|
+
theme.common
|
|
934
|
+
]);
|
|
935
|
+
if (!computedProps) return null;
|
|
936
|
+
const itemType = computedProps.type ?? "string";
|
|
937
|
+
if (hidden) return /* @__PURE__ */ jsx(Form$1.Item, {
|
|
938
|
+
...computedProps,
|
|
939
|
+
id: computedProps.id.toString(),
|
|
940
|
+
noStyle: true,
|
|
941
|
+
rules: [],
|
|
942
|
+
children: /* @__PURE__ */ jsx(Input, {
|
|
943
|
+
type: "hidden",
|
|
944
|
+
hidden: true
|
|
945
|
+
})
|
|
946
|
+
});
|
|
947
|
+
if (computedProps.formChildren === null || computedProps.children === null || computedProps.formRender === null || computedProps.render === null) return null;
|
|
948
|
+
const children = computedProps.formChildren || computedProps.children;
|
|
949
|
+
if (children) return /* @__PURE__ */ jsx(Form$1.Item, {
|
|
950
|
+
...computedProps,
|
|
951
|
+
id: computedProps.id.toString(),
|
|
952
|
+
children: cloneUnionFaasItemElement(children, { scene: "form" })
|
|
953
|
+
});
|
|
954
|
+
const render = computedProps.formRender || computedProps.render;
|
|
955
|
+
if (render) return /* @__PURE__ */ jsx(Form$1.Item, {
|
|
956
|
+
...computedProps,
|
|
957
|
+
id: computedProps.id.toString(),
|
|
958
|
+
children: render(void 0, Object.create(null), 0, "form")
|
|
959
|
+
});
|
|
960
|
+
const extendType = extendTypes?.[itemType];
|
|
961
|
+
if (extendType?.children) return /* @__PURE__ */ jsx(Form$1.Item, {
|
|
962
|
+
...computedProps,
|
|
963
|
+
id: computedProps.id.toString(),
|
|
964
|
+
children: cloneUnionFaasItemElement(extendType.children, { scene: "form" })
|
|
965
|
+
});
|
|
966
|
+
const renderFormItemList = (inputElement) => /* @__PURE__ */ jsx(Form$1.List, {
|
|
967
|
+
name: computedProps.name,
|
|
968
|
+
rules: computedProps.rules,
|
|
969
|
+
children: (fields, { add, remove }, { errors }) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
970
|
+
computedProps.label && /* @__PURE__ */ jsx("div", {
|
|
971
|
+
className: "ant-form-item-label",
|
|
972
|
+
children: /* @__PURE__ */ jsx("label", {
|
|
973
|
+
className: (computedProps.rules || []).find((r) => r.required) && "ant-form-item-required",
|
|
974
|
+
children: computedProps.label
|
|
975
|
+
})
|
|
976
|
+
}),
|
|
977
|
+
fields.map((field) => {
|
|
978
|
+
const { key, ...fieldProps } = field;
|
|
979
|
+
return /* @__PURE__ */ jsx(Form$1.Item, {
|
|
980
|
+
id: key.toString(),
|
|
981
|
+
children: /* @__PURE__ */ jsxs(Row, {
|
|
982
|
+
gutter: 24,
|
|
983
|
+
style: { flexFlow: "row nowrap" },
|
|
984
|
+
children: [/* @__PURE__ */ jsx(Col, {
|
|
985
|
+
span: 23,
|
|
986
|
+
children: /* @__PURE__ */ jsx(Form$1.Item, {
|
|
987
|
+
...fieldProps,
|
|
988
|
+
noStyle: true,
|
|
989
|
+
children: inputElement
|
|
990
|
+
})
|
|
991
|
+
}), /* @__PURE__ */ jsx(Col, {
|
|
992
|
+
span: 1,
|
|
993
|
+
children: !computedProps.input?.disabled && (!(computedProps.rules || []).find((r) => r.required) || key > 0) && /* @__PURE__ */ jsx(Button, {
|
|
994
|
+
danger: true,
|
|
995
|
+
type: "link",
|
|
996
|
+
style: { float: "right" },
|
|
997
|
+
icon: /* @__PURE__ */ jsx(MinusCircleOutlined, {}),
|
|
998
|
+
onClick: () => remove(field.name)
|
|
999
|
+
})
|
|
1000
|
+
})]
|
|
1001
|
+
})
|
|
1002
|
+
}, key);
|
|
1003
|
+
}),
|
|
1004
|
+
/* @__PURE__ */ jsxs(Form$1.Item, { children: [
|
|
1005
|
+
!computedProps.input?.disabled && (!computedProps.maxCount || computedProps.maxCount > fields.length) && /* @__PURE__ */ jsx(Button, {
|
|
1006
|
+
type: "dashed",
|
|
1007
|
+
block: true,
|
|
1008
|
+
onClick: () => add(),
|
|
1009
|
+
icon: /* @__PURE__ */ jsx(PlusOutlined, {})
|
|
1010
|
+
}),
|
|
1011
|
+
computedProps.extra && /* @__PURE__ */ jsx("div", {
|
|
1012
|
+
className: "ant-form-item-extra",
|
|
1013
|
+
children: computedProps.extra
|
|
1014
|
+
}),
|
|
1015
|
+
/* @__PURE__ */ jsx(Form$1.ErrorList, { errors })
|
|
1016
|
+
] })
|
|
1017
|
+
] })
|
|
1018
|
+
});
|
|
1019
|
+
switch (itemType) {
|
|
1020
|
+
case "string":
|
|
1021
|
+
if (isOptionsProps(computedProps)) return /* @__PURE__ */ jsx(Form$1.Item, {
|
|
1022
|
+
...computedProps,
|
|
1023
|
+
id: computedProps.id.toString(),
|
|
1024
|
+
children: computedProps.options.length > 10 ? /* @__PURE__ */ jsx(Select, { ...computedProps.input }) : /* @__PURE__ */ jsx(Radio.Group, { ...computedProps.input })
|
|
1025
|
+
});
|
|
1026
|
+
return /* @__PURE__ */ jsx(Form$1.Item, {
|
|
1027
|
+
...computedProps,
|
|
1028
|
+
id: computedProps.id.toString(),
|
|
1029
|
+
children: /* @__PURE__ */ jsx(Input, { ...computedProps.input })
|
|
1030
|
+
});
|
|
1031
|
+
case "string[]":
|
|
1032
|
+
if (isOptionsProps(computedProps)) return /* @__PURE__ */ jsx(Form$1.Item, {
|
|
1033
|
+
...computedProps,
|
|
1034
|
+
id: computedProps.id.toString(),
|
|
1035
|
+
children: /* @__PURE__ */ jsx(Select, {
|
|
1036
|
+
mode: "multiple",
|
|
1037
|
+
...computedProps.input
|
|
1038
|
+
})
|
|
1039
|
+
});
|
|
1040
|
+
return renderFormItemList(/* @__PURE__ */ jsx(Input, { ...computedProps.input }));
|
|
1041
|
+
case "number":
|
|
1042
|
+
if (isOptionsProps(computedProps)) return /* @__PURE__ */ jsx(Form$1.Item, {
|
|
1043
|
+
...computedProps,
|
|
1044
|
+
id: computedProps.id.toString(),
|
|
1045
|
+
children: computedProps.options.length > 10 ? /* @__PURE__ */ jsx(Select, { ...computedProps.input }) : /* @__PURE__ */ jsx(Radio.Group, { ...computedProps.input })
|
|
1046
|
+
});
|
|
1047
|
+
return /* @__PURE__ */ jsx(Form$1.Item, {
|
|
1048
|
+
...computedProps,
|
|
1049
|
+
id: computedProps.id.toString(),
|
|
1050
|
+
children: /* @__PURE__ */ jsx(InputNumber, {
|
|
1051
|
+
style: { width: "100%" },
|
|
1052
|
+
...computedProps.input
|
|
1053
|
+
})
|
|
1054
|
+
});
|
|
1055
|
+
case "number[]":
|
|
1056
|
+
if (isOptionsProps(computedProps)) return /* @__PURE__ */ jsx(Form$1.Item, {
|
|
1057
|
+
...computedProps,
|
|
1058
|
+
id: computedProps.id.toString(),
|
|
1059
|
+
children: /* @__PURE__ */ jsx(Select, {
|
|
1060
|
+
mode: "multiple",
|
|
1061
|
+
...computedProps.input
|
|
1062
|
+
})
|
|
1063
|
+
});
|
|
1064
|
+
return renderFormItemList(/* @__PURE__ */ jsx(InputNumber, {
|
|
1065
|
+
style: { width: "100%" },
|
|
1066
|
+
...computedProps.input
|
|
1067
|
+
}));
|
|
1068
|
+
case "boolean": return /* @__PURE__ */ jsx(Form$1.Item, {
|
|
1069
|
+
...computedProps,
|
|
1070
|
+
id: computedProps.id.toString(),
|
|
1071
|
+
children: /* @__PURE__ */ jsx(Switch, { ...computedProps.input })
|
|
1072
|
+
});
|
|
1073
|
+
case "date": return /* @__PURE__ */ jsx(Form$1.Item, {
|
|
1074
|
+
...computedProps,
|
|
1075
|
+
id: computedProps.id.toString(),
|
|
1076
|
+
children: /* @__PURE__ */ jsx(DatePicker, { ...computedProps.input })
|
|
1077
|
+
});
|
|
1078
|
+
case "time": return /* @__PURE__ */ jsx(Form$1.Item, {
|
|
1079
|
+
...computedProps,
|
|
1080
|
+
id: computedProps.id.toString(),
|
|
1081
|
+
children: /* @__PURE__ */ jsx(DatePicker, {
|
|
1082
|
+
...computedProps.input,
|
|
1083
|
+
showTime: true
|
|
1084
|
+
})
|
|
1085
|
+
});
|
|
1086
|
+
case "object": {
|
|
1087
|
+
const objectItems = computedProps.object || [];
|
|
1088
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [computedProps.label && /* @__PURE__ */ jsx("div", {
|
|
1089
|
+
className: "ant-form-item-label",
|
|
1090
|
+
children: /* @__PURE__ */ jsx("label", {
|
|
1091
|
+
className: computedProps.rules?.find((r) => r.required) && "ant-form-item-required",
|
|
1092
|
+
children: computedProps.label
|
|
1093
|
+
})
|
|
1094
|
+
}), objectItems.map((o) => /* @__PURE__ */ jsx(FormItem, { ...o }, o.id))] });
|
|
1095
|
+
}
|
|
1096
|
+
case "object[]": return /* @__PURE__ */ jsx(Form$1.List, {
|
|
1097
|
+
name: computedProps.name,
|
|
1098
|
+
rules: computedProps.rules,
|
|
1099
|
+
children: (fields, { add, remove }, { errors }) => /* @__PURE__ */ jsxs(Fragment, { children: [fields.map((field) => /* @__PURE__ */ jsxs(Form$1.Item, {
|
|
1100
|
+
id: field.key.toString(),
|
|
1101
|
+
style: { marginBottom: 0 },
|
|
1102
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
1103
|
+
className: "ant-form-item-label",
|
|
1104
|
+
children: /* @__PURE__ */ jsxs("label", { children: [
|
|
1105
|
+
computedProps.label,
|
|
1106
|
+
" ",
|
|
1107
|
+
field.name + 1,
|
|
1108
|
+
!computedProps.disabled && (!(computedProps.rules || []).find((r) => r.required) || field.key > 0) && /* @__PURE__ */ jsx(Button, {
|
|
1109
|
+
danger: true,
|
|
1110
|
+
type: "link",
|
|
1111
|
+
onClick: () => remove(field.name),
|
|
1112
|
+
children: theme.common.delete
|
|
1113
|
+
})
|
|
1114
|
+
] })
|
|
1115
|
+
}), /* @__PURE__ */ jsx(Row, {
|
|
1116
|
+
gutter: 24,
|
|
1117
|
+
children: (computedProps.object || []).map((o) => /* @__PURE__ */ jsx(Col, {
|
|
1118
|
+
span: o.col || 24,
|
|
1119
|
+
children: /* @__PURE__ */ jsx(FormItem, {
|
|
1120
|
+
...o,
|
|
1121
|
+
name: [field.name, o.id]
|
|
1122
|
+
})
|
|
1123
|
+
}, o.id))
|
|
1124
|
+
})]
|
|
1125
|
+
}, field.key)), /* @__PURE__ */ jsxs(Form$1.Item, { children: [
|
|
1126
|
+
!computedProps.disabled && (!computedProps.maxCount || computedProps.maxCount > fields.length) && /* @__PURE__ */ jsxs(Button, {
|
|
1127
|
+
type: "dashed",
|
|
1128
|
+
block: true,
|
|
1129
|
+
onClick: () => add(),
|
|
1130
|
+
icon: /* @__PURE__ */ jsx(PlusOutlined, {}),
|
|
1131
|
+
children: [
|
|
1132
|
+
theme.common.add,
|
|
1133
|
+
" ",
|
|
1134
|
+
computedProps.label
|
|
1135
|
+
]
|
|
1136
|
+
}),
|
|
1137
|
+
computedProps.extra && /* @__PURE__ */ jsx("div", {
|
|
1138
|
+
className: "ant-form-item-extra",
|
|
1139
|
+
children: computedProps.extra
|
|
1140
|
+
}),
|
|
1141
|
+
/* @__PURE__ */ jsx(Form$1.ErrorList, { errors })
|
|
1142
|
+
] })] })
|
|
1143
|
+
});
|
|
1144
|
+
default: return null;
|
|
1145
|
+
}
|
|
772
1146
|
}
|
|
773
|
-
FormItem.whyDidYouRender = true;
|
|
774
1147
|
FormItem.useStatus = Form$1.Item.useStatus;
|
|
1148
|
+
//#endregion
|
|
1149
|
+
//#region src/Form.tsx
|
|
775
1150
|
function isFormItemProps(item) {
|
|
776
|
-
|
|
1151
|
+
return item.id !== void 0;
|
|
777
1152
|
}
|
|
1153
|
+
/**
|
|
1154
|
+
* Render a data-aware Ant Design form with optional FaasJS submission helpers.
|
|
1155
|
+
*
|
|
1156
|
+
* The component normalizes `initialValues` with {@link transferValue}, renders item definitions
|
|
1157
|
+
* through {@link FormItem}, and can either delegate submission to a custom `onFinish` handler or
|
|
1158
|
+
* the built-in FaasJS request flow configured by `faas`.
|
|
1159
|
+
*
|
|
1160
|
+
* @template Values - Form values shape.
|
|
1161
|
+
* @param {FormProps<Values>} props - Form props including items, submit behavior, and FaasJS integration.
|
|
1162
|
+
*
|
|
1163
|
+
* @example
|
|
1164
|
+
* ```tsx
|
|
1165
|
+
* import { Form } from '@faasjs/ant-design'
|
|
1166
|
+
*
|
|
1167
|
+
* export function ProfileForm() {
|
|
1168
|
+
* return (
|
|
1169
|
+
* <Form
|
|
1170
|
+
* items={[
|
|
1171
|
+
* { id: 'name', required: true },
|
|
1172
|
+
* { id: 'email', required: true },
|
|
1173
|
+
* ]}
|
|
1174
|
+
* onFinish={async (values) => {
|
|
1175
|
+
* console.log(values)
|
|
1176
|
+
* }}
|
|
1177
|
+
* />
|
|
1178
|
+
* )
|
|
1179
|
+
* }
|
|
1180
|
+
* ```
|
|
1181
|
+
*
|
|
1182
|
+
* @example
|
|
1183
|
+
* ```tsx
|
|
1184
|
+
* import { Form } from '@faasjs/ant-design'
|
|
1185
|
+
*
|
|
1186
|
+
* export function CreateUserForm() {
|
|
1187
|
+
* return (
|
|
1188
|
+
* <Form
|
|
1189
|
+
* initialValues={{ role: 'user' }}
|
|
1190
|
+
* items={[
|
|
1191
|
+
* { id: 'name', required: true },
|
|
1192
|
+
* { id: 'role', options: ['user', 'admin'] },
|
|
1193
|
+
* ]}
|
|
1194
|
+
* faas={{
|
|
1195
|
+
* action: 'user/create',
|
|
1196
|
+
* params: (values) => ({
|
|
1197
|
+
* role: values.role || 'user',
|
|
1198
|
+
* }),
|
|
1199
|
+
* }}
|
|
1200
|
+
* />
|
|
1201
|
+
* )
|
|
1202
|
+
* }
|
|
1203
|
+
* ```
|
|
1204
|
+
*/
|
|
778
1205
|
function Form(props) {
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
1206
|
+
const [loading, setLoading] = useState(false);
|
|
1207
|
+
const [antdProps, setAntdProps] = useState();
|
|
1208
|
+
const [submit, setSubmit] = useState(props.submit === false ? false : {});
|
|
1209
|
+
const [items, setItems] = useState([]);
|
|
1210
|
+
const config = useConfigContext();
|
|
1211
|
+
const [extendTypes, setExtendTypes] = useState();
|
|
1212
|
+
const [form] = Form$1.useForm(props.form);
|
|
1213
|
+
const [initialValues, setInitialValues] = useState(props.initialValues || Object.create(null));
|
|
1214
|
+
const [onFinish, setOnFinish] = useState();
|
|
1215
|
+
useEqualEffect(() => {
|
|
1216
|
+
if (props.onFinish) {
|
|
1217
|
+
setOnFinish(() => async (values) => {
|
|
1218
|
+
if (!props.onFinish) return;
|
|
1219
|
+
setLoading(true);
|
|
1220
|
+
try {
|
|
1221
|
+
return await props.onFinish(values);
|
|
1222
|
+
} finally {
|
|
1223
|
+
setLoading(false);
|
|
1224
|
+
}
|
|
1225
|
+
});
|
|
1226
|
+
return;
|
|
1227
|
+
}
|
|
1228
|
+
if (props.faas?.action) {
|
|
1229
|
+
setOnFinish(() => async (values) => {
|
|
1230
|
+
if (!props.faas?.action) return;
|
|
1231
|
+
setLoading(true);
|
|
1232
|
+
let submitValues = values;
|
|
1233
|
+
try {
|
|
1234
|
+
if (props.faas?.transformValues) submitValues = await props.faas.transformValues(values);
|
|
1235
|
+
const extraParams = typeof props.faas?.params === "function" ? props.faas.params(submitValues) : props.faas.params;
|
|
1236
|
+
if (extraParams) submitValues = {
|
|
1237
|
+
...submitValues,
|
|
1238
|
+
...extraParams
|
|
1239
|
+
};
|
|
1240
|
+
const result = await faas(props.faas.action, submitValues);
|
|
1241
|
+
props.faas.onSuccess?.(result, submitValues);
|
|
1242
|
+
return result;
|
|
1243
|
+
} catch (error) {
|
|
1244
|
+
props.faas.onError?.(error, submitValues);
|
|
1245
|
+
throw error;
|
|
1246
|
+
} finally {
|
|
1247
|
+
props.faas.onFinally?.();
|
|
1248
|
+
setLoading(false);
|
|
1249
|
+
}
|
|
1250
|
+
});
|
|
1251
|
+
return;
|
|
1252
|
+
}
|
|
1253
|
+
setOnFinish(void 0);
|
|
1254
|
+
}, [props.onFinish, props.faas]);
|
|
1255
|
+
useEqualEffect(() => {
|
|
1256
|
+
setExtendTypes(props.extendTypes);
|
|
1257
|
+
}, [props.extendTypes]);
|
|
1258
|
+
useEqualEffect(() => {
|
|
1259
|
+
setSubmit(props.submit === false ? false : props.submit || {});
|
|
1260
|
+
}, [props.submit]);
|
|
1261
|
+
useEqualEffect(() => {
|
|
1262
|
+
const nextInitialValues = props.initialValues ? JSON.parse(JSON.stringify(props.initialValues)) : Object.create(null);
|
|
1263
|
+
for (const key in nextInitialValues) nextInitialValues[key] = transferValue(props.items?.find((item) => isFormItemProps(item) && item.id === key)?.type, nextInitialValues[key]);
|
|
1264
|
+
if (props.items?.length) setItems(props.items.map((item) => {
|
|
1265
|
+
if (!isFormItemProps(item) || !item.if) return item;
|
|
1266
|
+
return {
|
|
1267
|
+
...item,
|
|
1268
|
+
hidden: !item.if(nextInitialValues)
|
|
1269
|
+
};
|
|
1270
|
+
}));
|
|
1271
|
+
else setItems([]);
|
|
1272
|
+
if (props.initialValues) {
|
|
1273
|
+
setInitialValues(nextInitialValues);
|
|
1274
|
+
return;
|
|
1275
|
+
}
|
|
1276
|
+
setInitialValues(null);
|
|
1277
|
+
}, [props.initialValues, props.items]);
|
|
1278
|
+
useEqualEffect(() => {
|
|
1279
|
+
const propsCopy = { ...props };
|
|
1280
|
+
delete propsCopy.onFinish;
|
|
1281
|
+
delete propsCopy.faas;
|
|
1282
|
+
delete propsCopy.extendTypes;
|
|
1283
|
+
delete propsCopy.submit;
|
|
1284
|
+
delete propsCopy.items;
|
|
1285
|
+
delete propsCopy.initialValues;
|
|
1286
|
+
setAntdProps(propsCopy);
|
|
1287
|
+
}, [props]);
|
|
1288
|
+
const onValuesChange = useEqualCallback((changedValues, allValues) => {
|
|
1289
|
+
console.debug("Form:onValuesChange", changedValues, allValues);
|
|
1290
|
+
if (props.onValuesChange) props.onValuesChange(changedValues, allValues);
|
|
1291
|
+
if (!items.length) return;
|
|
1292
|
+
for (const key in changedValues) {
|
|
1293
|
+
const item = items.find((i) => isFormItemProps(i) && i.id === key);
|
|
1294
|
+
if (item?.onValueChange) item.onValueChange(changedValues[key], allValues, form);
|
|
1295
|
+
}
|
|
1296
|
+
}, [
|
|
1297
|
+
items,
|
|
1298
|
+
props.onValuesChange,
|
|
1299
|
+
form
|
|
1300
|
+
]);
|
|
1301
|
+
useEqualEffect(() => {
|
|
1302
|
+
if (!initialValues) return;
|
|
1303
|
+
console.debug("Form:initialValues", initialValues);
|
|
1304
|
+
form.setFieldsValue(initialValues);
|
|
1305
|
+
setInitialValues(null);
|
|
1306
|
+
}, [
|
|
1307
|
+
form,
|
|
1308
|
+
initialValues,
|
|
1309
|
+
items
|
|
1310
|
+
]);
|
|
1311
|
+
if (!antdProps) return null;
|
|
1312
|
+
const submitButtonProps = typeof submit === "object" ? submit.buttonProps : void 0;
|
|
1313
|
+
const submitButtonLoading = loading ? true : submitButtonProps?.loading ?? false;
|
|
1314
|
+
return /* @__PURE__ */ jsxs(Form$1, {
|
|
1315
|
+
...antdProps,
|
|
1316
|
+
form,
|
|
1317
|
+
onFinish,
|
|
1318
|
+
onValuesChange,
|
|
1319
|
+
children: [
|
|
1320
|
+
props.beforeItems,
|
|
1321
|
+
items.map((item) => {
|
|
1322
|
+
if (isFormItemProps(item)) return /* @__PURE__ */ jsx(FormItem, {
|
|
1323
|
+
...item,
|
|
1324
|
+
...extendTypes ? { extendTypes } : {}
|
|
1325
|
+
}, item.id);
|
|
1326
|
+
return item;
|
|
1327
|
+
}),
|
|
1328
|
+
props.children,
|
|
1329
|
+
typeof submit !== "boolean" && /* @__PURE__ */ jsx(Button, {
|
|
1330
|
+
...submitButtonProps,
|
|
1331
|
+
htmlType: "submit",
|
|
1332
|
+
type: submitButtonProps?.type || "primary",
|
|
1333
|
+
loading: submitButtonLoading,
|
|
1334
|
+
children: submit?.text || config.theme.Form.submit.text
|
|
1335
|
+
}),
|
|
1336
|
+
props.footer
|
|
1337
|
+
]
|
|
1338
|
+
});
|
|
895
1339
|
}
|
|
896
|
-
Form.whyDidYouRender = true;
|
|
897
1340
|
Form.useForm = Form$1.useForm;
|
|
898
1341
|
Form.useFormInstance = Form$1.useFormInstance;
|
|
899
1342
|
Form.useWatch = Form$1.useWatch;
|
|
@@ -901,689 +1344,681 @@ Form.Item = FormItem;
|
|
|
901
1344
|
Form.List = Form$1.List;
|
|
902
1345
|
Form.ErrorList = Form$1.ErrorList;
|
|
903
1346
|
Form.Provider = Form$1.Provider;
|
|
1347
|
+
//#endregion
|
|
1348
|
+
//#region src/Link.tsx
|
|
1349
|
+
/**
|
|
1350
|
+
* Render a navigation-aware link or button.
|
|
1351
|
+
*
|
|
1352
|
+
* Internal links are pushed through React Router, while links with `_blank` targets are opened
|
|
1353
|
+
* with `window.open`.
|
|
1354
|
+
*
|
|
1355
|
+
* @param {LinkProps} props - Link props controlling navigation target, rendering mode, and button behavior.
|
|
1356
|
+
*
|
|
1357
|
+
* @example
|
|
1358
|
+
* ```tsx
|
|
1359
|
+
* import { Link } from '@faasjs/ant-design'
|
|
1360
|
+
*
|
|
1361
|
+
* export function Navigation() {
|
|
1362
|
+
* return (
|
|
1363
|
+
* <>
|
|
1364
|
+
* <Link href="/">Home</Link>
|
|
1365
|
+
* <Link href="/users/new" button={{ type: 'primary' }}>
|
|
1366
|
+
* Create User
|
|
1367
|
+
* </Link>
|
|
1368
|
+
* </>
|
|
1369
|
+
* )
|
|
1370
|
+
* }
|
|
1371
|
+
* ```
|
|
1372
|
+
*/
|
|
904
1373
|
function Link(props) {
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
);
|
|
1374
|
+
const { theme } = useConfigContext();
|
|
1375
|
+
const navigate = useNavigate();
|
|
1376
|
+
const target = props.target || theme.Link?.target || (props.href.startsWith("http") ? "_blank" : void 0);
|
|
1377
|
+
let computedStyle = {
|
|
1378
|
+
...theme.Link.style,
|
|
1379
|
+
cursor: "pointer",
|
|
1380
|
+
...props.style
|
|
1381
|
+
};
|
|
1382
|
+
if (props.block) computedStyle = Object.assign({
|
|
1383
|
+
display: "block",
|
|
1384
|
+
width: "100%"
|
|
1385
|
+
}, computedStyle);
|
|
1386
|
+
const buttonProps = props.button && typeof props.button === "object" ? props.button : void 0;
|
|
1387
|
+
const copyableProps = typeof props.copyable === "undefined" ? {} : { copyable: props.copyable };
|
|
1388
|
+
if (props.button) return /* @__PURE__ */ jsx(Button, {
|
|
1389
|
+
...buttonProps,
|
|
1390
|
+
style: computedStyle,
|
|
1391
|
+
onClick: (e) => {
|
|
1392
|
+
e.preventDefault();
|
|
1393
|
+
if (props.onClick) {
|
|
1394
|
+
props.onClick(e);
|
|
1395
|
+
return;
|
|
1396
|
+
}
|
|
1397
|
+
if (target === "_blank") {
|
|
1398
|
+
window.open(props.href);
|
|
1399
|
+
return;
|
|
1400
|
+
}
|
|
1401
|
+
navigate(props.href);
|
|
1402
|
+
},
|
|
1403
|
+
children: props.children ?? props.text
|
|
1404
|
+
});
|
|
1405
|
+
return /* @__PURE__ */ jsx(Typography.Link, {
|
|
1406
|
+
href: props.href,
|
|
1407
|
+
target,
|
|
1408
|
+
style: computedStyle,
|
|
1409
|
+
...copyableProps,
|
|
1410
|
+
onClick: (e) => {
|
|
1411
|
+
e.preventDefault();
|
|
1412
|
+
if (props.onClick) {
|
|
1413
|
+
props.onClick(e);
|
|
1414
|
+
return;
|
|
1415
|
+
}
|
|
1416
|
+
if (target === "_blank") {
|
|
1417
|
+
window.open(props.href);
|
|
1418
|
+
return;
|
|
1419
|
+
}
|
|
1420
|
+
navigate(props.href);
|
|
1421
|
+
},
|
|
1422
|
+
children: props.children ?? props.text
|
|
1423
|
+
});
|
|
956
1424
|
}
|
|
957
|
-
|
|
1425
|
+
//#endregion
|
|
1426
|
+
//#region src/Routers.tsx
|
|
1427
|
+
/**
|
|
1428
|
+
* Default 404 route element that uses the configured localized title.
|
|
1429
|
+
*
|
|
1430
|
+
* @example
|
|
1431
|
+
* ```tsx
|
|
1432
|
+
* import { PageNotFound, Routes } from '@faasjs/ant-design'
|
|
1433
|
+
*
|
|
1434
|
+
* export function AppRoutes() {
|
|
1435
|
+
* return (
|
|
1436
|
+
* <Routes
|
|
1437
|
+
* routes={[{ path: '/', element: <div>Home</div> }]}
|
|
1438
|
+
* notFound={<PageNotFound />}
|
|
1439
|
+
* />
|
|
1440
|
+
* )
|
|
1441
|
+
* }
|
|
1442
|
+
* ```
|
|
1443
|
+
*/
|
|
958
1444
|
function PageNotFound() {
|
|
959
|
-
|
|
960
|
-
|
|
1445
|
+
const { theme } = useConfigContext();
|
|
1446
|
+
return /* @__PURE__ */ jsx(Result, {
|
|
1447
|
+
status: "404",
|
|
1448
|
+
title: theme.common.pageNotFound
|
|
1449
|
+
});
|
|
961
1450
|
}
|
|
1451
|
+
/**
|
|
1452
|
+
* Render React Router routes with lazy-page support and a default 404 route.
|
|
1453
|
+
*
|
|
1454
|
+
* The wrapper adds a catch-all route automatically and uses an Ant Design `Skeleton` fallback when
|
|
1455
|
+
* `fallback` is not provided.
|
|
1456
|
+
*
|
|
1457
|
+
* @param {RoutesProps} props - Route definitions and optional fallback or 404 elements.
|
|
1458
|
+
*
|
|
1459
|
+
* @example
|
|
1460
|
+
* ```tsx
|
|
1461
|
+
* import { Routes, lazy } from '@faasjs/ant-design'
|
|
1462
|
+
* import { BrowserRouter } from 'react-router-dom'
|
|
1463
|
+
*
|
|
1464
|
+
* export function App() {
|
|
1465
|
+
* return (
|
|
1466
|
+
* <BrowserRouter>
|
|
1467
|
+
* <Routes
|
|
1468
|
+
* routes={[
|
|
1469
|
+
* {
|
|
1470
|
+
* path: '/',
|
|
1471
|
+
* page: lazy(() => import('./pages/home')),
|
|
1472
|
+
* },
|
|
1473
|
+
* ]}
|
|
1474
|
+
* />
|
|
1475
|
+
* </BrowserRouter>
|
|
1476
|
+
* )
|
|
1477
|
+
* }
|
|
1478
|
+
* ```
|
|
1479
|
+
*/
|
|
962
1480
|
function Routes(props) {
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
] });
|
|
1481
|
+
return /* @__PURE__ */ jsxs(Routes$1, { children: [props.routes.map((r) => {
|
|
1482
|
+
const Page = r.page;
|
|
1483
|
+
return /* @__PURE__ */ jsx(Route, {
|
|
1484
|
+
...r,
|
|
1485
|
+
element: r.element || (Page ? /* @__PURE__ */ jsx(Suspense, {
|
|
1486
|
+
fallback: props.fallback || /* @__PURE__ */ jsx("div", {
|
|
1487
|
+
style: { padding: "24px" },
|
|
1488
|
+
children: /* @__PURE__ */ jsx(Skeleton, { active: true })
|
|
1489
|
+
}),
|
|
1490
|
+
children: /* @__PURE__ */ jsx(Page, {})
|
|
1491
|
+
}) : void 0)
|
|
1492
|
+
}, r.path);
|
|
1493
|
+
}), /* @__PURE__ */ jsx(Route, {
|
|
1494
|
+
path: "*",
|
|
1495
|
+
element: props.notFound || /* @__PURE__ */ jsx(PageNotFound, {})
|
|
1496
|
+
}, "*")] });
|
|
980
1497
|
}
|
|
981
|
-
|
|
1498
|
+
//#endregion
|
|
1499
|
+
//#region src/Table.tsx
|
|
982
1500
|
function processValue(item, value) {
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
item.type === "date" ? "YYYY-MM-DD" : "YYYY-MM-DD HH:mm:ss"
|
|
998
|
-
);
|
|
999
|
-
return value;
|
|
1501
|
+
const itemType = item.type ?? "string";
|
|
1502
|
+
const transferred = transferValue(itemType, value);
|
|
1503
|
+
if (transferred === null || Array.isArray(transferred) && transferred.length === 0) return /* @__PURE__ */ jsx(Blank, {});
|
|
1504
|
+
if (item.options) {
|
|
1505
|
+
if (itemType.endsWith("[]")) return transferred.map((v) => item.options.find((option) => option.value === v)?.label || v).join(", ");
|
|
1506
|
+
if ([
|
|
1507
|
+
"string",
|
|
1508
|
+
"number",
|
|
1509
|
+
"boolean"
|
|
1510
|
+
].includes(itemType)) return item.options.find((option) => option.value === transferred)?.label || transferred;
|
|
1511
|
+
}
|
|
1512
|
+
if (itemType.endsWith("[]")) return transferred.join(", ");
|
|
1513
|
+
if (["date", "time"].includes(itemType)) return transferred.format(itemType === "date" ? "YYYY-MM-DD" : "YYYY-MM-DD HH:mm:ss");
|
|
1514
|
+
return transferred;
|
|
1000
1515
|
}
|
|
1516
|
+
/**
|
|
1517
|
+
* Render an Ant Design table from FaasJS item metadata.
|
|
1518
|
+
*
|
|
1519
|
+
* The component can render local `dataSource` rows or resolve remote rows through `faasData`. It
|
|
1520
|
+
* also generates default filters and sorters for built-in item types unless you disable them with
|
|
1521
|
+
* the corresponding Ant Design column props.
|
|
1522
|
+
*
|
|
1523
|
+
* @template T - Row record type rendered by the table.
|
|
1524
|
+
* @template ExtendTypes - Additional item prop shape accepted by `items`.
|
|
1525
|
+
* @param {TableProps<T, ExtendTypes>} props - Table props including columns, data source, and optional Faas data config.
|
|
1526
|
+
* @throws {Error} When an entry in `extendTypes` omits both `children` and `render`.
|
|
1527
|
+
*
|
|
1528
|
+
* @example
|
|
1529
|
+
* ```tsx
|
|
1530
|
+
* import { Table } from '@faasjs/ant-design'
|
|
1531
|
+
*
|
|
1532
|
+
* const rows = [
|
|
1533
|
+
* { id: 1, name: 'Alice', active: true },
|
|
1534
|
+
* { id: 2, name: 'Bob', active: false },
|
|
1535
|
+
* ]
|
|
1536
|
+
*
|
|
1537
|
+
* export function UserTable() {
|
|
1538
|
+
* return (
|
|
1539
|
+
* <Table
|
|
1540
|
+
* rowKey="id"
|
|
1541
|
+
* dataSource={rows}
|
|
1542
|
+
* items={[
|
|
1543
|
+
* { id: 'name', title: 'Name' },
|
|
1544
|
+
* { id: 'active', type: 'boolean', title: 'Active' },
|
|
1545
|
+
* ]}
|
|
1546
|
+
* />
|
|
1547
|
+
* )
|
|
1548
|
+
* }
|
|
1549
|
+
* ```
|
|
1550
|
+
*/
|
|
1001
1551
|
function Table(props) {
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
if (!item.onFilter && !props.faasData)
|
|
1302
|
-
item.onFilter = (value, row) => {
|
|
1303
|
-
switch (value) {
|
|
1304
|
-
case true:
|
|
1305
|
-
return !isNil(row[item.id]) && row[item.id] !== false;
|
|
1306
|
-
case false:
|
|
1307
|
-
return !isNil(row[item.id]) && !row[item.id];
|
|
1308
|
-
default:
|
|
1309
|
-
return isNil(row[item.id]);
|
|
1310
|
-
}
|
|
1311
|
-
};
|
|
1312
|
-
}
|
|
1313
|
-
break;
|
|
1314
|
-
case "date":
|
|
1315
|
-
if (!item.render) item.render = (value) => processValue(item, value);
|
|
1316
|
-
if (typeof item.sorter === "undefined")
|
|
1317
|
-
item.sorter = (a, b, order) => {
|
|
1318
|
-
if (isNil(a[item.id])) return order === "ascend" ? 1 : -1;
|
|
1319
|
-
if (isNil(b[item.id])) return order === "ascend" ? -1 : 1;
|
|
1320
|
-
return new Date(a[item.id]).getTime() < new Date(b[item.id]).getTime() ? -1 : 1;
|
|
1321
|
-
};
|
|
1322
|
-
if (item.filterDropdown !== false) {
|
|
1323
|
-
if (typeof item.filterDropdown === "undefined")
|
|
1324
|
-
item.filterDropdown = ({ setSelectedKeys, confirm }) => /* @__PURE__ */ jsx(
|
|
1325
|
-
DatePicker.RangePicker,
|
|
1326
|
-
{
|
|
1327
|
-
onChange: (dates) => {
|
|
1328
|
-
setSelectedKeys(
|
|
1329
|
-
dates?.[0] && dates[1] ? [
|
|
1330
|
-
[
|
|
1331
|
-
dates[0].startOf("day").toISOString(),
|
|
1332
|
-
dates[1].endOf("day").toISOString()
|
|
1333
|
-
]
|
|
1334
|
-
] : []
|
|
1335
|
-
);
|
|
1336
|
-
confirm();
|
|
1337
|
-
}
|
|
1338
|
-
}
|
|
1339
|
-
);
|
|
1340
|
-
if (!item.onFilter && !props.faasData)
|
|
1341
|
-
item.onFilter = (value, row) => {
|
|
1342
|
-
if (isNil(value[0])) return true;
|
|
1343
|
-
if (isNil(row[item.id])) return false;
|
|
1344
|
-
return dayjs2(row[item.id]) >= dayjs2(value[0]) && dayjs2(row[item.id]) <= dayjs2(value[1]);
|
|
1345
|
-
};
|
|
1346
|
-
}
|
|
1347
|
-
break;
|
|
1348
|
-
case "time":
|
|
1349
|
-
item.width = item.width ?? 200;
|
|
1350
|
-
if (!item.render) item.render = (value) => processValue(item, value);
|
|
1351
|
-
if (typeof item.sorter === "undefined")
|
|
1352
|
-
item.sorter = (a, b, order) => {
|
|
1353
|
-
if (isNil(a[item.id])) return order === "ascend" ? 1 : -1;
|
|
1354
|
-
if (isNil(b[item.id])) return order === "ascend" ? -1 : 1;
|
|
1355
|
-
return new Date(a[item.id]).getTime() < new Date(b[item.id]).getTime() ? -1 : 1;
|
|
1356
|
-
};
|
|
1357
|
-
if (item.filterDropdown !== false) {
|
|
1358
|
-
if (typeof item.filterDropdown === "undefined")
|
|
1359
|
-
item.filterDropdown = ({ setSelectedKeys, confirm }) => /* @__PURE__ */ jsx(
|
|
1360
|
-
DatePicker.RangePicker,
|
|
1361
|
-
{
|
|
1362
|
-
onChange: (dates) => {
|
|
1363
|
-
setSelectedKeys(
|
|
1364
|
-
dates?.[0] && dates[1] ? [
|
|
1365
|
-
[
|
|
1366
|
-
dates[0].startOf("day").toISOString(),
|
|
1367
|
-
dates[1].endOf("day").toISOString()
|
|
1368
|
-
]
|
|
1369
|
-
] : []
|
|
1370
|
-
);
|
|
1371
|
-
confirm();
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
);
|
|
1375
|
-
if (!item.onFilter && !props.faasData)
|
|
1376
|
-
item.onFilter = (value, row) => {
|
|
1377
|
-
if (isNil(value[0])) return true;
|
|
1378
|
-
if (isNil(row[item.id])) return false;
|
|
1379
|
-
return dayjs2(row[item.id]) >= dayjs2(value[0]) && dayjs2(row[item.id]) <= dayjs2(value[1]);
|
|
1380
|
-
};
|
|
1381
|
-
}
|
|
1382
|
-
break;
|
|
1383
|
-
case "object":
|
|
1384
|
-
if (!item.render)
|
|
1385
|
-
item.render = (value) => /* @__PURE__ */ jsx(
|
|
1386
|
-
Description,
|
|
1387
|
-
{
|
|
1388
|
-
items: item.object,
|
|
1389
|
-
dataSource: value || {},
|
|
1390
|
-
column: 1
|
|
1391
|
-
}
|
|
1392
|
-
);
|
|
1393
|
-
break;
|
|
1394
|
-
case "object[]":
|
|
1395
|
-
if (!item.render)
|
|
1396
|
-
item.render = (value) => /* @__PURE__ */ jsx(Fragment, { children: value.map((v, i) => /* @__PURE__ */ jsx(
|
|
1397
|
-
Description,
|
|
1398
|
-
{
|
|
1399
|
-
items: item.object,
|
|
1400
|
-
dataSource: v || [],
|
|
1401
|
-
column: 1
|
|
1402
|
-
},
|
|
1403
|
-
i
|
|
1404
|
-
)) });
|
|
1405
|
-
break;
|
|
1406
|
-
default:
|
|
1407
|
-
if (!item.render) item.render = (value) => processValue(item, value);
|
|
1408
|
-
if (item.filterDropdown !== false && !item.onFilter && !props.faasData)
|
|
1409
|
-
item.onFilter = (value, row) => {
|
|
1410
|
-
if (value === null && isNil(row[item.id])) return true;
|
|
1411
|
-
return value === row[item.id];
|
|
1412
|
-
};
|
|
1413
|
-
break;
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
setColumns(items);
|
|
1417
|
-
}, [props.items]);
|
|
1418
|
-
useEffect(() => {
|
|
1419
|
-
if (!props.dataSource || !columns) return;
|
|
1420
|
-
for (const column of columns) {
|
|
1421
|
-
if (column.optionsType === "auto" && !column.options && !column.filters) {
|
|
1422
|
-
const options = uniqBy(props.dataSource, column.id).map(
|
|
1423
|
-
(v) => ({
|
|
1424
|
-
label: v[column.id],
|
|
1425
|
-
value: v[column.id]
|
|
1426
|
-
})
|
|
1427
|
-
);
|
|
1428
|
-
if (options.length)
|
|
1429
|
-
setColumns((prev) => {
|
|
1430
|
-
const newColumns = [...prev];
|
|
1431
|
-
const index = newColumns.findIndex((item) => item.id === column.id);
|
|
1432
|
-
newColumns[index].options = options;
|
|
1433
|
-
generateFilterDropdown(newColumns[index]);
|
|
1434
|
-
return newColumns;
|
|
1435
|
-
});
|
|
1436
|
-
}
|
|
1437
|
-
}
|
|
1438
|
-
}, [props.dataSource, columns]);
|
|
1439
|
-
if (!columns) return null;
|
|
1440
|
-
if (props.dataSource)
|
|
1441
|
-
return /* @__PURE__ */ jsx(
|
|
1442
|
-
Table$1,
|
|
1443
|
-
{
|
|
1444
|
-
...props,
|
|
1445
|
-
rowKey: props.rowKey || "id",
|
|
1446
|
-
columns,
|
|
1447
|
-
dataSource: props.dataSource
|
|
1448
|
-
}
|
|
1449
|
-
);
|
|
1450
|
-
return /* @__PURE__ */ jsx(FaasDataWrapper, { ...props.faasData, children: /* @__PURE__ */ jsx(FaasDataTable, { props, columns }) });
|
|
1552
|
+
const [columns, setColumns] = useState();
|
|
1553
|
+
const { theme } = useConfigContext();
|
|
1554
|
+
const { all, blank, search } = theme.common;
|
|
1555
|
+
const generateFilterDropdown = useCallback((item) => {
|
|
1556
|
+
if (item.filterDropdown && item.filterDropdown !== true) return;
|
|
1557
|
+
if (!item.options?.length) return;
|
|
1558
|
+
if (item.options.length < 11) {
|
|
1559
|
+
if (!item.filters) item.filters = item.options.map((o) => ({
|
|
1560
|
+
text: o.label,
|
|
1561
|
+
value: o.value
|
|
1562
|
+
}));
|
|
1563
|
+
return;
|
|
1564
|
+
}
|
|
1565
|
+
item.filterDropdown = ({ setSelectedKeys, selectedKeys, confirm }) => /* @__PURE__ */ jsx("div", {
|
|
1566
|
+
style: {
|
|
1567
|
+
padding: 8,
|
|
1568
|
+
width: "200px"
|
|
1569
|
+
},
|
|
1570
|
+
onKeyDown: (e) => e.stopPropagation(),
|
|
1571
|
+
children: /* @__PURE__ */ jsx(Select, {
|
|
1572
|
+
options: item.options,
|
|
1573
|
+
allowClear: true,
|
|
1574
|
+
showSearch: true,
|
|
1575
|
+
style: { width: "100%" },
|
|
1576
|
+
placeholder: `${search} ${item.title}`,
|
|
1577
|
+
value: selectedKeys,
|
|
1578
|
+
onChange: (v) => {
|
|
1579
|
+
setSelectedKeys(v?.length ? v : []);
|
|
1580
|
+
confirm();
|
|
1581
|
+
},
|
|
1582
|
+
mode: "multiple",
|
|
1583
|
+
filterOption: (input, option) => {
|
|
1584
|
+
if (!input || !option) return true;
|
|
1585
|
+
if (typeof option.label !== "string") return option.value === input;
|
|
1586
|
+
input = input.trim();
|
|
1587
|
+
return option.value === input || option.label.toLowerCase().includes(input.toLowerCase());
|
|
1588
|
+
}
|
|
1589
|
+
})
|
|
1590
|
+
});
|
|
1591
|
+
return item;
|
|
1592
|
+
}, [search]);
|
|
1593
|
+
useEqualEffect(() => {
|
|
1594
|
+
const items = cloneDeep(props.items).filter((item) => !(item.tableChildren === null || item.children === null || item.tableRender === null || item.render === null));
|
|
1595
|
+
const createTextSearchFilterDropdown = (item, transformValue) => ({ setSelectedKeys, confirm, clearFilters }) => /* @__PURE__ */ jsx(Input.Search, {
|
|
1596
|
+
placeholder: `${search} ${item.title}`,
|
|
1597
|
+
allowClear: true,
|
|
1598
|
+
onSearch: (v) => {
|
|
1599
|
+
if (v) setSelectedKeys(transformValue ? [transformValue(v)] : [v]);
|
|
1600
|
+
else {
|
|
1601
|
+
setSelectedKeys([]);
|
|
1602
|
+
clearFilters?.();
|
|
1603
|
+
}
|
|
1604
|
+
confirm();
|
|
1605
|
+
}
|
|
1606
|
+
});
|
|
1607
|
+
for (const item of items) {
|
|
1608
|
+
if (!item.key) item.key = item.id;
|
|
1609
|
+
if (!item.dataIndex) item.dataIndex = item.id;
|
|
1610
|
+
const itemType = item.type ?? "string";
|
|
1611
|
+
item.title = item.title ?? idToTitle(item.id);
|
|
1612
|
+
item.type = itemType;
|
|
1613
|
+
if (item.options?.length) {
|
|
1614
|
+
item.options = transferOptions(item.options);
|
|
1615
|
+
item.filters = item.options.map((o) => ({
|
|
1616
|
+
text: o.label,
|
|
1617
|
+
value: o.value
|
|
1618
|
+
})).concat({
|
|
1619
|
+
text: /* @__PURE__ */ jsx(Blank, {}),
|
|
1620
|
+
value: null
|
|
1621
|
+
});
|
|
1622
|
+
generateFilterDropdown(item);
|
|
1623
|
+
}
|
|
1624
|
+
const children = item.tableChildren || item.children;
|
|
1625
|
+
if (children) {
|
|
1626
|
+
item.render = (value, values) => cloneUnionFaasItemElement(children, {
|
|
1627
|
+
scene: "table",
|
|
1628
|
+
value,
|
|
1629
|
+
values,
|
|
1630
|
+
index: 0
|
|
1631
|
+
});
|
|
1632
|
+
delete item.children;
|
|
1633
|
+
delete item.tableChildren;
|
|
1634
|
+
continue;
|
|
1635
|
+
}
|
|
1636
|
+
const render = item.tableRender || item.render;
|
|
1637
|
+
if (render) {
|
|
1638
|
+
item.render = (value, values) => render(value, values, 0, "table");
|
|
1639
|
+
delete item.tableRender;
|
|
1640
|
+
continue;
|
|
1641
|
+
}
|
|
1642
|
+
const extendType = props.extendTypes?.[itemType];
|
|
1643
|
+
if (extendType) {
|
|
1644
|
+
const extendChildren = extendType.children;
|
|
1645
|
+
if (extendChildren) item.render = (value, values) => cloneUnionFaasItemElement(extendChildren, {
|
|
1646
|
+
scene: "table",
|
|
1647
|
+
value,
|
|
1648
|
+
values,
|
|
1649
|
+
index: 0
|
|
1650
|
+
});
|
|
1651
|
+
else {
|
|
1652
|
+
const extendRender = extendType.render;
|
|
1653
|
+
if (extendRender) item.render = (value, values) => extendRender(value, values, 0, "table");
|
|
1654
|
+
else throw Error(`${itemType} requires children or render`);
|
|
1655
|
+
}
|
|
1656
|
+
continue;
|
|
1657
|
+
}
|
|
1658
|
+
switch (itemType) {
|
|
1659
|
+
case "string":
|
|
1660
|
+
if (!item.render) item.render = (value) => processValue(item, value);
|
|
1661
|
+
if (item.filterDropdown !== false) {
|
|
1662
|
+
if (!item.onFilter && !props.faasData) item.onFilter = (value, row) => {
|
|
1663
|
+
if (!value || isNil(value)) return true;
|
|
1664
|
+
if (isNil(row[item.id])) return false;
|
|
1665
|
+
return row[item.id].trim().toLowerCase().includes(value.trim().toLowerCase());
|
|
1666
|
+
};
|
|
1667
|
+
if (typeof item.filterDropdown === "undefined" && !item.filters && item.optionsType !== "auto") item.filterDropdown = createTextSearchFilterDropdown(item);
|
|
1668
|
+
}
|
|
1669
|
+
break;
|
|
1670
|
+
case "string[]":
|
|
1671
|
+
if (!item.render) item.render = (value) => processValue(item, value);
|
|
1672
|
+
if (item.filterDropdown !== false) {
|
|
1673
|
+
if (!item.onFilter && !props.faasData) item.onFilter = (value, row) => {
|
|
1674
|
+
if (value === null && (!row[item.id] || !row[item.id].length)) return true;
|
|
1675
|
+
if (!row[item.id] || !row[item.id].length || !value) return false;
|
|
1676
|
+
return row[item.id].some((v) => v.trim().toLowerCase().includes(value.trim().toLowerCase()));
|
|
1677
|
+
};
|
|
1678
|
+
if (typeof item.filterDropdown === "undefined" && !item.filters && item.optionsType !== "auto") item.filterDropdown = createTextSearchFilterDropdown(item);
|
|
1679
|
+
}
|
|
1680
|
+
break;
|
|
1681
|
+
case "number":
|
|
1682
|
+
if (!item.render) item.render = (value) => processValue(item, value);
|
|
1683
|
+
if (typeof item.sorter === "undefined") item.sorter = (a, b) => a[item.id] - b[item.id];
|
|
1684
|
+
if (item.filterDropdown !== false) {
|
|
1685
|
+
if (!item.onFilter && !props.faasData) item.onFilter = (value, row) => {
|
|
1686
|
+
if (value === null) return true;
|
|
1687
|
+
if (isNil(row[item.id])) return false;
|
|
1688
|
+
return value == row[item.id];
|
|
1689
|
+
};
|
|
1690
|
+
if (typeof item.filterDropdown === "undefined" && !item.filters) item.filterDropdown = createTextSearchFilterDropdown(item, Number);
|
|
1691
|
+
}
|
|
1692
|
+
break;
|
|
1693
|
+
case "number[]":
|
|
1694
|
+
if (!item.render) item.render = (value) => processValue(item, value);
|
|
1695
|
+
if (item.filterDropdown !== false) {
|
|
1696
|
+
if (!item.onFilter && !props.faasData) item.onFilter = (value, row) => {
|
|
1697
|
+
if (value === null && (!row[item.id] || !row[item.id].length)) return true;
|
|
1698
|
+
if (!row[item.id] || !row[item.id].length) return false;
|
|
1699
|
+
return row[item.id].includes(Number(value));
|
|
1700
|
+
};
|
|
1701
|
+
if (typeof item.filterDropdown === "undefined" && !item.filters) item.filterDropdown = createTextSearchFilterDropdown(item, Number);
|
|
1702
|
+
}
|
|
1703
|
+
break;
|
|
1704
|
+
case "boolean":
|
|
1705
|
+
if (!item.render) item.render = (value) => isNil(value) ? /* @__PURE__ */ jsx(Blank, {}) : value ? /* @__PURE__ */ jsx(CheckOutlined, { style: {
|
|
1706
|
+
marginTop: "4px",
|
|
1707
|
+
color: "#52c41a"
|
|
1708
|
+
} }) : /* @__PURE__ */ jsx(CloseOutlined, { style: {
|
|
1709
|
+
marginTop: "4px",
|
|
1710
|
+
color: "#ff4d4f"
|
|
1711
|
+
} });
|
|
1712
|
+
if (item.filterDropdown !== false) {
|
|
1713
|
+
if (typeof item.filterDropdown === "undefined") item.filterDropdown = ({ setSelectedKeys, selectedKeys, confirm: confirmFilter }) => /* @__PURE__ */ jsxs(Radio.Group, {
|
|
1714
|
+
style: { padding: 8 },
|
|
1715
|
+
buttonStyle: "solid",
|
|
1716
|
+
value: JSON.stringify(selectedKeys[0]),
|
|
1717
|
+
onChange: (e) => {
|
|
1718
|
+
setSelectedKeys(e.target.value ? [{
|
|
1719
|
+
true: true,
|
|
1720
|
+
false: false,
|
|
1721
|
+
null: null
|
|
1722
|
+
}[e.target.value]] : []);
|
|
1723
|
+
confirmFilter();
|
|
1724
|
+
},
|
|
1725
|
+
children: [
|
|
1726
|
+
/* @__PURE__ */ jsx(Radio.Button, { children: all }),
|
|
1727
|
+
/* @__PURE__ */ jsx(Radio.Button, {
|
|
1728
|
+
value: "true",
|
|
1729
|
+
children: /* @__PURE__ */ jsx(CheckOutlined, { style: {
|
|
1730
|
+
color: "#52c41a",
|
|
1731
|
+
verticalAlign: "middle"
|
|
1732
|
+
} })
|
|
1733
|
+
}),
|
|
1734
|
+
/* @__PURE__ */ jsx(Radio.Button, {
|
|
1735
|
+
value: "false",
|
|
1736
|
+
children: /* @__PURE__ */ jsx(CloseOutlined, { style: {
|
|
1737
|
+
verticalAlign: "middle",
|
|
1738
|
+
color: "#ff4d4f"
|
|
1739
|
+
} })
|
|
1740
|
+
}),
|
|
1741
|
+
/* @__PURE__ */ jsx(Radio.Button, {
|
|
1742
|
+
value: "null",
|
|
1743
|
+
children: blank
|
|
1744
|
+
})
|
|
1745
|
+
]
|
|
1746
|
+
});
|
|
1747
|
+
if (!item.onFilter && !props.faasData) item.onFilter = (value, row) => {
|
|
1748
|
+
switch (value) {
|
|
1749
|
+
case true: return !isNil(row[item.id]) && row[item.id] !== false;
|
|
1750
|
+
case false: return !isNil(row[item.id]) && !row[item.id];
|
|
1751
|
+
default: return isNil(row[item.id]);
|
|
1752
|
+
}
|
|
1753
|
+
};
|
|
1754
|
+
}
|
|
1755
|
+
break;
|
|
1756
|
+
case "date":
|
|
1757
|
+
case "time":
|
|
1758
|
+
if (itemType === "time") item.width = item.width ?? 200;
|
|
1759
|
+
if (!item.render) item.render = (value) => processValue(item, value);
|
|
1760
|
+
if (typeof item.sorter === "undefined") item.sorter = (a, b, order) => {
|
|
1761
|
+
if (isNil(a[item.id])) return order === "ascend" ? 1 : -1;
|
|
1762
|
+
if (isNil(b[item.id])) return order === "ascend" ? -1 : 1;
|
|
1763
|
+
return new Date(a[item.id]).getTime() < new Date(b[item.id]).getTime() ? -1 : 1;
|
|
1764
|
+
};
|
|
1765
|
+
if (item.filterDropdown !== false) {
|
|
1766
|
+
if (typeof item.filterDropdown === "undefined") item.filterDropdown = ({ setSelectedKeys, confirm }) => /* @__PURE__ */ jsx(DatePicker.RangePicker, { onChange: (dates) => {
|
|
1767
|
+
const start = dates?.[0];
|
|
1768
|
+
const end = dates?.[1];
|
|
1769
|
+
setSelectedKeys(start && end ? [[start.startOf("day").toISOString(), end.endOf("day").toISOString()]] : []);
|
|
1770
|
+
confirm();
|
|
1771
|
+
} });
|
|
1772
|
+
if (!item.onFilter && !props.faasData) item.onFilter = (value, row) => {
|
|
1773
|
+
if (isNil(value[0])) return true;
|
|
1774
|
+
if (isNil(row[item.id])) return false;
|
|
1775
|
+
return dayjs(row[item.id]) >= dayjs(value[0]) && dayjs(row[item.id]) <= dayjs(value[1]);
|
|
1776
|
+
};
|
|
1777
|
+
}
|
|
1778
|
+
break;
|
|
1779
|
+
case "object":
|
|
1780
|
+
if (!item.render) item.render = (value) => /* @__PURE__ */ jsx(Description, {
|
|
1781
|
+
items: item.object || [],
|
|
1782
|
+
dataSource: value || {},
|
|
1783
|
+
column: 1
|
|
1784
|
+
});
|
|
1785
|
+
break;
|
|
1786
|
+
case "object[]":
|
|
1787
|
+
if (!item.render) item.render = (value) => /* @__PURE__ */ jsx(Fragment, { children: value.map((v, i) => /* @__PURE__ */ jsx(Description, {
|
|
1788
|
+
items: item.object || [],
|
|
1789
|
+
dataSource: v || [],
|
|
1790
|
+
column: 1
|
|
1791
|
+
}, i)) });
|
|
1792
|
+
break;
|
|
1793
|
+
default:
|
|
1794
|
+
if (!item.render) item.render = (value) => processValue(item, value);
|
|
1795
|
+
if (item.filterDropdown !== false && !item.onFilter && !props.faasData) item.onFilter = (value, row) => {
|
|
1796
|
+
if (value === null && isNil(row[item.id])) return true;
|
|
1797
|
+
return value === row[item.id];
|
|
1798
|
+
};
|
|
1799
|
+
break;
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
setColumns(items);
|
|
1803
|
+
}, [
|
|
1804
|
+
all,
|
|
1805
|
+
blank,
|
|
1806
|
+
generateFilterDropdown,
|
|
1807
|
+
props.extendTypes,
|
|
1808
|
+
props.faasData,
|
|
1809
|
+
props.items,
|
|
1810
|
+
search
|
|
1811
|
+
]);
|
|
1812
|
+
useEqualEffect(() => {
|
|
1813
|
+
if (!props.dataSource || !columns) return;
|
|
1814
|
+
for (const column of columns) if (column.optionsType === "auto" && !column.options && !column.filters) {
|
|
1815
|
+
const options = uniqBy(props.dataSource, column.id).map((v) => ({
|
|
1816
|
+
label: v[column.id],
|
|
1817
|
+
value: v[column.id]
|
|
1818
|
+
}));
|
|
1819
|
+
if (options.length) setColumns((prev) => {
|
|
1820
|
+
const newColumns = [...prev || []];
|
|
1821
|
+
const index = newColumns.findIndex((item) => item.id === column.id);
|
|
1822
|
+
if (index < 0) return newColumns;
|
|
1823
|
+
newColumns[index].options = options;
|
|
1824
|
+
generateFilterDropdown(newColumns[index]);
|
|
1825
|
+
return newColumns;
|
|
1826
|
+
});
|
|
1827
|
+
}
|
|
1828
|
+
}, [
|
|
1829
|
+
props.dataSource,
|
|
1830
|
+
columns,
|
|
1831
|
+
generateFilterDropdown
|
|
1832
|
+
]);
|
|
1833
|
+
if (!columns) return null;
|
|
1834
|
+
if (props.dataSource) return /* @__PURE__ */ jsx(Table$1, {
|
|
1835
|
+
...props,
|
|
1836
|
+
rowKey: props.rowKey || "id",
|
|
1837
|
+
columns,
|
|
1838
|
+
dataSource: props.dataSource
|
|
1839
|
+
});
|
|
1840
|
+
if (!props.faasData) return /* @__PURE__ */ jsx(FaasDataTable, {
|
|
1841
|
+
props,
|
|
1842
|
+
columns
|
|
1843
|
+
});
|
|
1844
|
+
return /* @__PURE__ */ jsx(FaasDataWrapper, {
|
|
1845
|
+
...props.faasData,
|
|
1846
|
+
children: /* @__PURE__ */ jsx(FaasDataTable, {
|
|
1847
|
+
props,
|
|
1848
|
+
columns
|
|
1849
|
+
})
|
|
1850
|
+
});
|
|
1451
1851
|
}
|
|
1452
|
-
function FaasDataTable({
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
Table$1,
|
|
1520
|
-
{
|
|
1521
|
-
...props,
|
|
1522
|
-
loading,
|
|
1523
|
-
rowKey: props.rowKey || "id",
|
|
1524
|
-
columns: currentColumns,
|
|
1525
|
-
dataSource: data.rows,
|
|
1526
|
-
pagination: props.pagination === false ? false : {
|
|
1527
|
-
...props.pagination || /* @__PURE__ */ Object.create(null),
|
|
1528
|
-
...data.pagination || /* @__PURE__ */ Object.create(null)
|
|
1529
|
-
},
|
|
1530
|
-
onChange: (pagination, filters, sorter, extra) => {
|
|
1531
|
-
if (props.onChange) {
|
|
1532
|
-
const processed = props.onChange(pagination, filters, sorter, extra);
|
|
1533
|
-
reload({
|
|
1534
|
-
...params || /* @__PURE__ */ Object.create(null),
|
|
1535
|
-
pagination: processed.pagination,
|
|
1536
|
-
filters: processed.filters,
|
|
1537
|
-
sorter: processed.sorter,
|
|
1538
|
-
extra: processed.extra
|
|
1539
|
-
});
|
|
1540
|
-
return;
|
|
1541
|
-
}
|
|
1542
|
-
reload({
|
|
1543
|
-
...params || /* @__PURE__ */ Object.create(null),
|
|
1544
|
-
pagination,
|
|
1545
|
-
filters,
|
|
1546
|
-
sorter
|
|
1547
|
-
});
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
);
|
|
1852
|
+
function FaasDataTable({ props, columns, data, params, reload, loading }) {
|
|
1853
|
+
const [currentColumns, setCurrentColumns] = useState(columns);
|
|
1854
|
+
useEqualEffect(() => {
|
|
1855
|
+
if (!data || Array.isArray(data)) return;
|
|
1856
|
+
setCurrentColumns((prev) => {
|
|
1857
|
+
const newColumns = [...prev];
|
|
1858
|
+
for (const column of newColumns) if (data.options?.[column.id]) {
|
|
1859
|
+
column.options = transferOptions(data.options[column.id]);
|
|
1860
|
+
column.filters = column.options.map((v) => ({
|
|
1861
|
+
text: v.label,
|
|
1862
|
+
value: v.value
|
|
1863
|
+
})).concat({
|
|
1864
|
+
text: /* @__PURE__ */ jsx(Blank, {}),
|
|
1865
|
+
value: null
|
|
1866
|
+
});
|
|
1867
|
+
column.render = (value) => processValue(column, value);
|
|
1868
|
+
if (column.filterDropdown) delete column.filterDropdown;
|
|
1869
|
+
continue;
|
|
1870
|
+
}
|
|
1871
|
+
return newColumns;
|
|
1872
|
+
});
|
|
1873
|
+
}, [data]);
|
|
1874
|
+
if (!data) return /* @__PURE__ */ jsx(Table$1, {
|
|
1875
|
+
...props,
|
|
1876
|
+
...typeof loading === "undefined" ? {} : { loading },
|
|
1877
|
+
rowKey: props.rowKey || "id",
|
|
1878
|
+
columns: currentColumns,
|
|
1879
|
+
dataSource: []
|
|
1880
|
+
});
|
|
1881
|
+
if (Array.isArray(data)) return /* @__PURE__ */ jsx(Table$1, {
|
|
1882
|
+
...props,
|
|
1883
|
+
...typeof loading === "undefined" ? {} : { loading },
|
|
1884
|
+
rowKey: props.rowKey || "id",
|
|
1885
|
+
columns: currentColumns,
|
|
1886
|
+
dataSource: data
|
|
1887
|
+
});
|
|
1888
|
+
return /* @__PURE__ */ jsx(Table$1, {
|
|
1889
|
+
...props,
|
|
1890
|
+
...typeof loading === "undefined" ? {} : { loading },
|
|
1891
|
+
rowKey: props.rowKey || "id",
|
|
1892
|
+
columns: currentColumns,
|
|
1893
|
+
dataSource: data.rows,
|
|
1894
|
+
pagination: props.pagination === false ? false : {
|
|
1895
|
+
...props.pagination || Object.create(null),
|
|
1896
|
+
...data.pagination || Object.create(null)
|
|
1897
|
+
},
|
|
1898
|
+
onChange: (pagination, filters, sorter, extra) => {
|
|
1899
|
+
if (!reload) return;
|
|
1900
|
+
if (props.onChange) {
|
|
1901
|
+
const processed = props.onChange(pagination, filters, sorter, extra);
|
|
1902
|
+
reload({
|
|
1903
|
+
...params || Object.create(null),
|
|
1904
|
+
pagination: processed.pagination,
|
|
1905
|
+
filters: processed.filters,
|
|
1906
|
+
sorter: processed.sorter,
|
|
1907
|
+
extra: processed.extra
|
|
1908
|
+
});
|
|
1909
|
+
return;
|
|
1910
|
+
}
|
|
1911
|
+
reload({
|
|
1912
|
+
...params || Object.create(null),
|
|
1913
|
+
pagination,
|
|
1914
|
+
filters,
|
|
1915
|
+
sorter
|
|
1916
|
+
});
|
|
1917
|
+
}
|
|
1918
|
+
});
|
|
1551
1919
|
}
|
|
1920
|
+
//#endregion
|
|
1921
|
+
//#region src/Tabs.tsx
|
|
1922
|
+
/**
|
|
1923
|
+
* Render an Ant Design tabs wrapper that accepts FaasJS-style tab definitions.
|
|
1924
|
+
*
|
|
1925
|
+
* Missing `key` and `label` values are derived from each tab's `id` and `title`.
|
|
1926
|
+
*
|
|
1927
|
+
* @param {TabsProps} props - Tabs props including tab items and Ant Design tab options.
|
|
1928
|
+
*
|
|
1929
|
+
* @example
|
|
1930
|
+
* ```tsx
|
|
1931
|
+
* import { Tabs } from '@faasjs/ant-design'
|
|
1932
|
+
*
|
|
1933
|
+
* export function Page() {
|
|
1934
|
+
* return (
|
|
1935
|
+
* <Tabs
|
|
1936
|
+
* items={[
|
|
1937
|
+
* {
|
|
1938
|
+
* id: 'id',
|
|
1939
|
+
* children: 'content',
|
|
1940
|
+
* },
|
|
1941
|
+
* 1 === 0 && {
|
|
1942
|
+
* id: 'hidden',
|
|
1943
|
+
* children: 'content',
|
|
1944
|
+
* },
|
|
1945
|
+
* ]}
|
|
1946
|
+
* />
|
|
1947
|
+
* )
|
|
1948
|
+
* }
|
|
1949
|
+
* ```
|
|
1950
|
+
*/
|
|
1552
1951
|
function Tabs(props) {
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
}))
|
|
1562
|
-
}
|
|
1563
|
-
);
|
|
1952
|
+
return /* @__PURE__ */ jsx(Tabs$1, {
|
|
1953
|
+
...props,
|
|
1954
|
+
items: props.items.filter(Boolean).map((i) => ({
|
|
1955
|
+
...i,
|
|
1956
|
+
key: i.key ?? i.id,
|
|
1957
|
+
label: i.label ?? i.title ?? i.id
|
|
1958
|
+
}))
|
|
1959
|
+
});
|
|
1564
1960
|
}
|
|
1565
|
-
|
|
1961
|
+
//#endregion
|
|
1962
|
+
//#region src/Title.tsx
|
|
1963
|
+
/**
|
|
1964
|
+
* Update `document.title` and optionally render the title inline.
|
|
1965
|
+
*
|
|
1966
|
+
* The component returns `null` by default and is often used only for its side effect.
|
|
1967
|
+
*
|
|
1968
|
+
* @param {TitleProps} props - Title props controlling document title updates and optional inline rendering.
|
|
1969
|
+
*
|
|
1970
|
+
* @example
|
|
1971
|
+
* ```tsx
|
|
1972
|
+
* import { Title } from '@faasjs/ant-design'
|
|
1973
|
+
*
|
|
1974
|
+
* export function DetailPage() {
|
|
1975
|
+
* return (
|
|
1976
|
+
* <>
|
|
1977
|
+
* <Title title={['Orders', 'Detail']} h1 />
|
|
1978
|
+
* <div>...</div>
|
|
1979
|
+
* </>
|
|
1980
|
+
* )
|
|
1981
|
+
* }
|
|
1982
|
+
* ```
|
|
1983
|
+
*/
|
|
1566
1984
|
function Title(props) {
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1985
|
+
const { theme } = useConfigContext();
|
|
1986
|
+
useEqualEffect(() => {
|
|
1987
|
+
const title = Array.isArray(props.title) ? props.title : [props.title];
|
|
1988
|
+
document.title = title.concat(props.suffix || theme.Title.suffix).filter((t) => !!t).join(props.separator || theme.Title.separator);
|
|
1989
|
+
}, [props, theme.Title]);
|
|
1990
|
+
if (props.h1) {
|
|
1991
|
+
if (typeof props.h1 === "boolean") return /* @__PURE__ */ jsx("h1", { children: Array.isArray(props.title) ? props.title[0] : props.title });
|
|
1992
|
+
return /* @__PURE__ */ jsx("h1", {
|
|
1993
|
+
className: props.h1.className,
|
|
1994
|
+
style: props.h1.style,
|
|
1995
|
+
children: Array.isArray(props.title) ? props.title[0] : props.title
|
|
1996
|
+
});
|
|
1997
|
+
}
|
|
1998
|
+
if (props.plain) return /* @__PURE__ */ jsx(Fragment, { children: Array.isArray(props.title) ? props.title[0] : props.title });
|
|
1999
|
+
if (props.children) return cloneElement(props.children, { title: props.title });
|
|
2000
|
+
return null;
|
|
1582
2001
|
}
|
|
1583
|
-
|
|
2002
|
+
//#endregion
|
|
2003
|
+
//#region src/useThemeToken.ts
|
|
2004
|
+
/**
|
|
2005
|
+
* Read the current Ant Design theme token.
|
|
2006
|
+
*
|
|
2007
|
+
* @returns Ant Design global token object for the active theme.
|
|
2008
|
+
*
|
|
2009
|
+
* @example
|
|
2010
|
+
* ```tsx
|
|
2011
|
+
* import { useThemeToken } from '@faasjs/ant-design'
|
|
2012
|
+
*
|
|
2013
|
+
* function PrimarySwatch() {
|
|
2014
|
+
* const { colorPrimary } = useThemeToken()
|
|
2015
|
+
*
|
|
2016
|
+
* return <div style={{ width: 24, height: 24, background: colorPrimary }} />
|
|
2017
|
+
* }
|
|
2018
|
+
* ```
|
|
2019
|
+
*/
|
|
1584
2020
|
function useThemeToken() {
|
|
1585
|
-
|
|
1586
|
-
return config.token;
|
|
2021
|
+
return theme.useToken().token;
|
|
1587
2022
|
}
|
|
1588
|
-
|
|
1589
|
-
export { App, Blank, ConfigContext, ConfigProvider, Description, Drawer, ErrorBoundary, FaasDataWrapper, Form, FormItem, Link, Loading, Modal, PageNotFound, Routes, Table, Tabs, Title, cloneUnionFaasItemElement, idToTitle, transferOptions, transferValue, useApp, useConfigContext, useDrawer, useModal, useThemeToken, withFaasData };
|
|
2023
|
+
//#endregion
|
|
2024
|
+
export { App, AppContext, Blank, ConfigContext, ConfigProvider, Description, Drawer, ErrorBoundary, FaasDataWrapper, FaasReactClient, Form, FormItem, Link, Loading, Modal, PageNotFound, Routes, Table, Tabs, Title, cloneUnionFaasItemElement, faas, idToTitle, lazy, transferOptions, transferValue, useApp, useConfigContext, useDrawer, useFaas, useModal, useThemeToken, withFaasData };
|