@faasjs/ant-design 8.0.0-beta.16 → 8.0.0-beta.18
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 +2 -1
- package/dist/index.cjs +638 -207
- package/dist/index.d.ts +948 -292
- package/dist/index.mjs +638 -207
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -32,15 +32,24 @@ let dayjs = require("dayjs");
|
|
|
32
32
|
dayjs = __toESM(dayjs);
|
|
33
33
|
//#region src/Loading.tsx
|
|
34
34
|
/**
|
|
35
|
-
*
|
|
35
|
+
* Render an Ant Design loading spinner with an optional content fallback.
|
|
36
|
+
*
|
|
37
|
+
* @param {LoadingProps} props - Loading indicator props and optional wrapped children.
|
|
36
38
|
*
|
|
37
39
|
* @example
|
|
38
40
|
* ```tsx
|
|
39
|
-
*
|
|
41
|
+
* import { Loading } from '@faasjs/ant-design'
|
|
40
42
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
43
|
+
* export function Page({ remoteData }: { remoteData?: string }) {
|
|
44
|
+
* return (
|
|
45
|
+
* <>
|
|
46
|
+
* <Loading />
|
|
47
|
+
* <Loading loading={!remoteData}>
|
|
48
|
+
* <div>{remoteData}</div>
|
|
49
|
+
* </Loading>
|
|
50
|
+
* </>
|
|
51
|
+
* )
|
|
52
|
+
* }
|
|
44
53
|
* ```
|
|
45
54
|
*/
|
|
46
55
|
function Loading(props) {
|
|
@@ -59,18 +68,84 @@ function Loading(props) {
|
|
|
59
68
|
//#endregion
|
|
60
69
|
//#region src/FaasDataWrapper.tsx
|
|
61
70
|
/**
|
|
62
|
-
*
|
|
71
|
+
* Render the `@faasjs/react` data wrapper with an Ant Design loading fallback.
|
|
72
|
+
*
|
|
73
|
+
* When `loading` is not provided, the component renders {@link Loading} with `loadingProps` while
|
|
74
|
+
* the wrapped FaasJS request is pending.
|
|
75
|
+
*
|
|
76
|
+
* @template T - Action path or response data type used for inference.
|
|
77
|
+
* @param {FaasDataWrapperProps<T>} props - Wrapper props including loading fallbacks and request configuration.
|
|
63
78
|
*
|
|
64
79
|
* @example
|
|
65
80
|
* ```tsx
|
|
66
|
-
*
|
|
67
|
-
*
|
|
81
|
+
* import { Alert, Button } from 'antd'
|
|
82
|
+
* import { FaasDataWrapper } from '@faasjs/ant-design'
|
|
83
|
+
*
|
|
84
|
+
* type User = {
|
|
85
|
+
* name: string
|
|
86
|
+
* }
|
|
87
|
+
*
|
|
88
|
+
* function UserView(props: {
|
|
89
|
+
* data?: User
|
|
90
|
+
* error?: Error
|
|
91
|
+
* reload?: () => void
|
|
92
|
+
* }) {
|
|
93
|
+
* if (props.error) {
|
|
94
|
+
* return (
|
|
95
|
+
* <Alert
|
|
96
|
+
* type="error"
|
|
97
|
+
* message={props.error.message}
|
|
98
|
+
* action={
|
|
99
|
+
* <Button size="small" onClick={() => props.reload?.()}>
|
|
100
|
+
* Retry
|
|
101
|
+
* </Button>
|
|
102
|
+
* }
|
|
103
|
+
* />
|
|
104
|
+
* )
|
|
105
|
+
* }
|
|
106
|
+
*
|
|
107
|
+
* return <div>Hello, {props.data?.name}</div>
|
|
108
|
+
* }
|
|
109
|
+
*
|
|
110
|
+
* // Render-prop mode
|
|
111
|
+
* export function UserProfile(props: { id: number }) {
|
|
112
|
+
* return (
|
|
113
|
+
* <FaasDataWrapper<User>
|
|
114
|
+
* action="user/get"
|
|
115
|
+
* params={{ id: props.id }}
|
|
116
|
+
* loading={<div>Loading user...</div>}
|
|
117
|
+
* render={({ data, error, reload }) => {
|
|
118
|
+
* if (error) {
|
|
119
|
+
* return (
|
|
120
|
+
* <Alert
|
|
121
|
+
* type="error"
|
|
122
|
+
* message={error.message}
|
|
123
|
+
* action={
|
|
124
|
+
* <Button size="small" onClick={() => reload()}>
|
|
125
|
+
* Retry
|
|
126
|
+
* </Button>
|
|
127
|
+
* }
|
|
128
|
+
* />
|
|
129
|
+
* )
|
|
130
|
+
* }
|
|
131
|
+
*
|
|
132
|
+
* return <div>Hello, {data.name}</div>
|
|
133
|
+
* }}
|
|
134
|
+
* />
|
|
135
|
+
* )
|
|
68
136
|
* }
|
|
69
137
|
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
138
|
+
* // Children injection mode
|
|
139
|
+
* export function UserProfileWithChildren(props: { id: number }) {
|
|
140
|
+
* return (
|
|
141
|
+
* <FaasDataWrapper<User>
|
|
142
|
+
* action="user/get"
|
|
143
|
+
* params={{ id: props.id }}
|
|
144
|
+
* loading={<div>Loading user...</div>}
|
|
145
|
+
* >
|
|
146
|
+
* <UserView />
|
|
147
|
+
* </FaasDataWrapper>
|
|
148
|
+
* )
|
|
74
149
|
* }
|
|
75
150
|
* ```
|
|
76
151
|
*/
|
|
@@ -81,11 +156,27 @@ function FaasDataWrapper(props) {
|
|
|
81
156
|
});
|
|
82
157
|
}
|
|
83
158
|
/**
|
|
84
|
-
*
|
|
159
|
+
* Wrap a component with {@link FaasDataWrapper} and its Ant Design loading fallback.
|
|
160
|
+
*
|
|
161
|
+
* @template PathOrData - Action path or response data type used for inference.
|
|
162
|
+
* @template TComponentProps - Component props including injected Faas data fields.
|
|
163
|
+
* @param {React.FC<TComponentProps & Record<string, any>>} Component - Component that consumes injected Faas data props.
|
|
164
|
+
* @param {FaasDataWrapperProps<PathOrData>} faasProps - Request configuration forwarded to {@link FaasDataWrapper}.
|
|
165
|
+
* @returns Higher-order component that injects Faas data props.
|
|
85
166
|
*
|
|
86
167
|
* @example
|
|
87
168
|
* ```tsx
|
|
88
|
-
*
|
|
169
|
+
* import { withFaasData } from '@faasjs/ant-design'
|
|
170
|
+
*
|
|
171
|
+
* const UserCard = withFaasData(
|
|
172
|
+
* ({ data, error, reload }) =>
|
|
173
|
+
* error ? (
|
|
174
|
+
* <a onClick={() => reload()}>Retry</a>
|
|
175
|
+
* ) : (
|
|
176
|
+
* <div>{data.name}</div>
|
|
177
|
+
* ),
|
|
178
|
+
* { action: 'user/get', params: { id: 1 } },
|
|
179
|
+
* )
|
|
89
180
|
* ```
|
|
90
181
|
*/
|
|
91
182
|
function withFaasData(Component, faasProps) {
|
|
@@ -131,17 +222,29 @@ const baseTheme = {
|
|
|
131
222
|
},
|
|
132
223
|
Link: { style: {} }
|
|
133
224
|
};
|
|
225
|
+
/**
|
|
226
|
+
* React context storing the resolved FaasJS Ant Design theme.
|
|
227
|
+
*/
|
|
134
228
|
const ConfigContext = (0, react.createContext)({ theme: baseTheme });
|
|
135
229
|
/**
|
|
136
|
-
*
|
|
230
|
+
* Provide theme overrides and optional FaasJS client initialization for descendants.
|
|
231
|
+
*
|
|
232
|
+
* Theme overrides are merged with the built-in defaults. When `theme.lang` is omitted, the
|
|
233
|
+
* provider infers a default language from `navigator.language`.
|
|
234
|
+
*
|
|
235
|
+
* @param {ConfigProviderProps} props - Theme overrides and optional FaasJS client configuration.
|
|
137
236
|
*
|
|
138
237
|
* @example
|
|
139
238
|
* ```tsx
|
|
140
|
-
* import { ConfigProvider } from '@faasjs/ant-design'
|
|
239
|
+
* import { Blank, ConfigProvider } from '@faasjs/ant-design'
|
|
141
240
|
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
241
|
+
* export function Page() {
|
|
242
|
+
* return (
|
|
243
|
+
* <ConfigProvider theme={{ common: { blank: 'Empty' } }}>
|
|
244
|
+
* <Blank />
|
|
245
|
+
* </ConfigProvider>
|
|
246
|
+
* )
|
|
247
|
+
* }
|
|
145
248
|
* ```
|
|
146
249
|
*/
|
|
147
250
|
function ConfigProvider(props) {
|
|
@@ -162,24 +265,60 @@ function ConfigProvider(props) {
|
|
|
162
265
|
children: props.children
|
|
163
266
|
});
|
|
164
267
|
}
|
|
268
|
+
/**
|
|
269
|
+
* Read the current `@faasjs/ant-design` config context.
|
|
270
|
+
*
|
|
271
|
+
* @returns Current config context value containing the resolved theme.
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* ```tsx
|
|
275
|
+
* import { Blank, ConfigProvider, useConfigContext } from '@faasjs/ant-design'
|
|
276
|
+
*
|
|
277
|
+
* function EmptyState() {
|
|
278
|
+
* const { theme } = useConfigContext()
|
|
279
|
+
*
|
|
280
|
+
* return <span>{theme.common.blank}</span>
|
|
281
|
+
* }
|
|
282
|
+
*
|
|
283
|
+
* export function Page() {
|
|
284
|
+
* return (
|
|
285
|
+
* <ConfigProvider theme={{ common: { blank: 'N/A' } }}>
|
|
286
|
+
* <EmptyState />
|
|
287
|
+
* </ConfigProvider>
|
|
288
|
+
* )
|
|
289
|
+
* }
|
|
290
|
+
* ```
|
|
291
|
+
*/
|
|
165
292
|
function useConfigContext() {
|
|
166
293
|
return (0, react.useContext)(ConfigContext);
|
|
167
294
|
}
|
|
168
295
|
//#endregion
|
|
169
296
|
//#region src/Drawer.tsx
|
|
170
297
|
/**
|
|
171
|
-
*
|
|
298
|
+
* Create a hook-managed Ant Design drawer instance.
|
|
299
|
+
*
|
|
300
|
+
* The returned setter merges partial updates into the current drawer props instead of replacing the
|
|
301
|
+
* entire state object.
|
|
302
|
+
*
|
|
303
|
+
* @param {DrawerProps} [init] - Initial drawer props.
|
|
304
|
+
* @returns Hook-managed drawer element, current props, and a state-merging setter.
|
|
172
305
|
*
|
|
306
|
+
* @example
|
|
173
307
|
* ```tsx
|
|
308
|
+
* import { useDrawer } from '@faasjs/ant-design'
|
|
309
|
+
* import { Button } from 'antd'
|
|
310
|
+
*
|
|
174
311
|
* function Example() {
|
|
175
312
|
* const { drawer, setDrawerProps } = useDrawer()
|
|
176
313
|
*
|
|
177
|
-
* return
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
314
|
+
* return (
|
|
315
|
+
* <>
|
|
316
|
+
* <Button onClick={() => setDrawerProps({ open: true, title: 'Details', children: <div>Content</div> })}>
|
|
317
|
+
* Open
|
|
318
|
+
* </Button>
|
|
319
|
+
* {drawer}
|
|
320
|
+
* </>
|
|
321
|
+
* )
|
|
183
322
|
* }
|
|
184
323
|
* ```
|
|
185
324
|
*/
|
|
@@ -224,6 +363,24 @@ function ErrorChildren(props) {
|
|
|
224
363
|
}
|
|
225
364
|
/**
|
|
226
365
|
* Styled error boundary.
|
|
366
|
+
*
|
|
367
|
+
* When `errorChildren` is not provided, the fallback UI renders an Ant Design `Alert` containing
|
|
368
|
+
* the captured error message and description.
|
|
369
|
+
*
|
|
370
|
+
* @param {ErrorBoundaryProps} props - Error boundary props forwarded to the underlying React implementation.
|
|
371
|
+
*
|
|
372
|
+
* @example
|
|
373
|
+
* ```tsx
|
|
374
|
+
* import { ErrorBoundary } from '@faasjs/ant-design'
|
|
375
|
+
*
|
|
376
|
+
* export function Page() {
|
|
377
|
+
* return (
|
|
378
|
+
* <ErrorBoundary>
|
|
379
|
+
* <DangerousWidget />
|
|
380
|
+
* </ErrorBoundary>
|
|
381
|
+
* )
|
|
382
|
+
* }
|
|
383
|
+
* ```
|
|
227
384
|
*/
|
|
228
385
|
function ErrorBoundary(props) {
|
|
229
386
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_faasjs_react.ErrorBoundary, {
|
|
@@ -234,16 +391,30 @@ function ErrorBoundary(props) {
|
|
|
234
391
|
//#endregion
|
|
235
392
|
//#region src/Modal.tsx
|
|
236
393
|
/**
|
|
237
|
-
*
|
|
394
|
+
* Create a hook-managed Ant Design modal instance.
|
|
395
|
+
*
|
|
396
|
+
* The returned setter merges partial updates into the current modal props instead of replacing the
|
|
397
|
+
* entire state object.
|
|
238
398
|
*
|
|
399
|
+
* @param {ModalProps} [init] - Initial modal props.
|
|
400
|
+
* @returns Hook-managed modal element, current props, and a state-merging setter.
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
239
403
|
* ```tsx
|
|
404
|
+
* import { useModal } from '@faasjs/ant-design'
|
|
405
|
+
* import { Button } from 'antd'
|
|
406
|
+
*
|
|
240
407
|
* function Example() {
|
|
241
408
|
* const { modal, setModalProps } = useModal()
|
|
242
409
|
*
|
|
243
|
-
* return
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
410
|
+
* return (
|
|
411
|
+
* <>
|
|
412
|
+
* <Button onClick={() => setModalProps({ open: true, title: 'Delete', children: 'Are you sure?' })}>
|
|
413
|
+
* Open Modal
|
|
414
|
+
* </Button>
|
|
415
|
+
* {modal}
|
|
416
|
+
* </>
|
|
417
|
+
* )
|
|
247
418
|
* }
|
|
248
419
|
* ```
|
|
249
420
|
*/
|
|
@@ -273,6 +444,9 @@ function useModal(init) {
|
|
|
273
444
|
}
|
|
274
445
|
//#endregion
|
|
275
446
|
//#region src/useApp.ts
|
|
447
|
+
/**
|
|
448
|
+
* Shared context storing message, notification, modal, and drawer helpers.
|
|
449
|
+
*/
|
|
276
450
|
const AppContext = (0, _faasjs_react.createSplittingContext)([
|
|
277
451
|
"message",
|
|
278
452
|
"notification",
|
|
@@ -282,12 +456,38 @@ const AppContext = (0, _faasjs_react.createSplittingContext)([
|
|
|
282
456
|
"setDrawerProps"
|
|
283
457
|
]);
|
|
284
458
|
/**
|
|
285
|
-
*
|
|
459
|
+
* Read app-level services exposed by the root `App` component.
|
|
286
460
|
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
461
|
+
* @template NewT - Narrowed app context shape to read from `AppContext`.
|
|
462
|
+
* @returns Read-only app context value.
|
|
289
463
|
*
|
|
290
|
-
*
|
|
464
|
+
* @example
|
|
465
|
+
* ```tsx
|
|
466
|
+
* import { App, useApp } from '@faasjs/ant-design'
|
|
467
|
+
* import { Button } from 'antd'
|
|
468
|
+
*
|
|
469
|
+
* function Page() {
|
|
470
|
+
* const { message, setModalProps } = useApp()
|
|
471
|
+
*
|
|
472
|
+
* return (
|
|
473
|
+
* <Button
|
|
474
|
+
* onClick={() => {
|
|
475
|
+
* message.success('Saved')
|
|
476
|
+
* setModalProps({ open: true, title: 'Done', children: 'Profile updated.' })
|
|
477
|
+
* }}
|
|
478
|
+
* >
|
|
479
|
+
* Save
|
|
480
|
+
* </Button>
|
|
481
|
+
* )
|
|
482
|
+
* }
|
|
483
|
+
*
|
|
484
|
+
* export function Root() {
|
|
485
|
+
* return (
|
|
486
|
+
* <App>
|
|
487
|
+
* <Page />
|
|
488
|
+
* </App>
|
|
489
|
+
* )
|
|
490
|
+
* }
|
|
291
491
|
* ```
|
|
292
492
|
*/
|
|
293
493
|
function useApp() {
|
|
@@ -306,25 +506,25 @@ function RoutesApp(props) {
|
|
|
306
506
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: props.children });
|
|
307
507
|
}
|
|
308
508
|
/**
|
|
309
|
-
*
|
|
509
|
+
* Render the root provider shell for a FaasJS Ant Design application.
|
|
510
|
+
*
|
|
511
|
+
* `App` initializes Ant Design message and notification APIs, exposes hook-managed modal and
|
|
512
|
+
* drawer state through {@link AppContext}, wraps descendants with {@link ErrorBoundary}, and
|
|
513
|
+
* optionally mounts React Router's `BrowserRouter`.
|
|
310
514
|
*
|
|
311
|
-
* -
|
|
312
|
-
* - Integrated Ant Design's [Message](https://ant.design/components/message/) and [Notification](https://ant.design/components/notification/).
|
|
313
|
-
* - Based on FaasJS's [ConfigProvider](https://faasjs.com/doc/ant-design/#configprovider).
|
|
314
|
-
* - Integrated FaasJS's [Modal](https://faasjs.com/doc/ant-design/#usemodal), [Drawer](https://faasjs.com/doc/ant-design/#usedrawer) and [ErrorBoundary](https://faasjs.com/doc/ant-design/#errorboundary).
|
|
315
|
-
* - Integrated React Router's [BrowserRouter](https://api.reactrouter.com/v7/interfaces/react_router.BrowserRouterProps.html).
|
|
515
|
+
* @param {AppProps} props - App shell props including providers, routing, and error handling options.
|
|
316
516
|
*
|
|
317
517
|
* @example
|
|
318
518
|
* ```tsx
|
|
319
519
|
* import { App } from '@faasjs/ant-design'
|
|
320
520
|
*
|
|
321
|
-
* export default function () {
|
|
521
|
+
* export default function Page() {
|
|
322
522
|
* return (
|
|
323
523
|
* <App
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
*
|
|
524
|
+
* configProviderProps={{}}
|
|
525
|
+
* browserRouterProps={{}}
|
|
526
|
+
* errorBoundaryProps={{}}
|
|
527
|
+
* faasConfigProviderProps={{}}
|
|
328
528
|
* >
|
|
329
529
|
* <div>content</div>
|
|
330
530
|
* </App>
|
|
@@ -335,8 +535,8 @@ function RoutesApp(props) {
|
|
|
335
535
|
function App(props) {
|
|
336
536
|
const [messageApi, messageContextHolder] = antd.message.useMessage();
|
|
337
537
|
const [notificationApi, notificationContextHolder] = antd.notification.useNotification();
|
|
338
|
-
const { modal, modalProps, setModalProps } = useModal();
|
|
339
|
-
const { drawer, drawerProps, setDrawerProps } = useDrawer();
|
|
538
|
+
const { modal, modalProps, setModalProps } = useModal({ destroyOnHidden: true });
|
|
539
|
+
const { drawer, drawerProps, setDrawerProps } = useDrawer({ destroyOnHidden: true });
|
|
340
540
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_faasjs_react.OptionalWrapper, {
|
|
341
541
|
condition: !!props.configProviderProps,
|
|
342
542
|
Wrapper: antd.ConfigProvider,
|
|
@@ -382,15 +582,20 @@ function App(props) {
|
|
|
382
582
|
//#endregion
|
|
383
583
|
//#region src/Blank.tsx
|
|
384
584
|
/**
|
|
385
|
-
*
|
|
585
|
+
* Render a disabled placeholder when a value is empty.
|
|
386
586
|
*
|
|
387
|
-
*
|
|
587
|
+
* Empty values include `undefined`, `null`, empty strings, and empty arrays.
|
|
588
|
+
*
|
|
589
|
+
* @param {BlankProps} [options] - Placeholder text and value to render.
|
|
590
|
+
* @returns Rendered value or the configured placeholder text.
|
|
388
591
|
*
|
|
389
592
|
* @example
|
|
390
593
|
* ```tsx
|
|
391
594
|
* import { Blank } from '@faasjs/ant-design'
|
|
392
595
|
*
|
|
393
|
-
*
|
|
596
|
+
* export function FieldPreview() {
|
|
597
|
+
* return <Blank value={undefined} text="Empty" />
|
|
598
|
+
* }
|
|
394
599
|
* ```
|
|
395
600
|
*/
|
|
396
601
|
function Blank(options) {
|
|
@@ -403,17 +608,14 @@ function Blank(options) {
|
|
|
403
608
|
//#endregion
|
|
404
609
|
//#region src/data.ts
|
|
405
610
|
/**
|
|
406
|
-
*
|
|
407
|
-
*
|
|
408
|
-
* This function takes an identifier string with words separated by underscores,
|
|
409
|
-
* capitalizes the first letter of each word, and joins them together without spaces.
|
|
611
|
+
* Convert a snake_case, kebab-case, or spaced identifier into a title-style label.
|
|
410
612
|
*
|
|
411
|
-
* @param id -
|
|
412
|
-
* @returns
|
|
613
|
+
* @param {string | number} id - Identifier to convert.
|
|
614
|
+
* @returns Generated label string.
|
|
413
615
|
*
|
|
414
616
|
* @example
|
|
415
|
-
* ```
|
|
416
|
-
* idToTitle('example_id')
|
|
617
|
+
* ```ts
|
|
618
|
+
* idToTitle('example_id') // 'Example Id'
|
|
417
619
|
* ```
|
|
418
620
|
*/
|
|
419
621
|
function idToTitle(id) {
|
|
@@ -422,7 +624,24 @@ function idToTitle(id) {
|
|
|
422
624
|
return splitted.charAt(0).toUpperCase() + splitted.slice(1);
|
|
423
625
|
}
|
|
424
626
|
/**
|
|
425
|
-
*
|
|
627
|
+
* Normalize primitive options into explicit `{ label, value }` objects.
|
|
628
|
+
*
|
|
629
|
+
* String and number options are converted with {@link idToTitle}, while pre-shaped option objects
|
|
630
|
+
* are returned as-is.
|
|
631
|
+
*
|
|
632
|
+
* @param {BaseOption[]} options - Raw option list to normalize.
|
|
633
|
+
* @returns Normalized option list.
|
|
634
|
+
*
|
|
635
|
+
* @example
|
|
636
|
+
* ```ts
|
|
637
|
+
* import { transferOptions } from '@faasjs/ant-design'
|
|
638
|
+
*
|
|
639
|
+
* transferOptions(['draft', { label: 'Published', value: 'published' }])
|
|
640
|
+
* // [
|
|
641
|
+
* // { label: 'Draft', value: 'draft' },
|
|
642
|
+
* // { label: 'Published', value: 'published' },
|
|
643
|
+
* // ]
|
|
644
|
+
* ```
|
|
426
645
|
*/
|
|
427
646
|
function transferOptions(options) {
|
|
428
647
|
if (!options) return [];
|
|
@@ -431,6 +650,25 @@ function transferOptions(options) {
|
|
|
431
650
|
value: item
|
|
432
651
|
});
|
|
433
652
|
}
|
|
653
|
+
/**
|
|
654
|
+
* Normalize raw values into the runtime shape expected by FaasJS Ant Design components.
|
|
655
|
+
*
|
|
656
|
+
* Primitive strings such as `'null'` and `'undefined'` become `null`, comma-delimited array
|
|
657
|
+
* strings are split into arrays, and date or time values are converted to `dayjs` objects.
|
|
658
|
+
*
|
|
659
|
+
* @param {FaasItemType | null | undefined} type - Target field type.
|
|
660
|
+
* @param {any} value - Raw value to normalize.
|
|
661
|
+
* @returns Normalized value for rendering or form initialization.
|
|
662
|
+
*
|
|
663
|
+
* @example
|
|
664
|
+
* ```ts
|
|
665
|
+
* import { transferValue } from '@faasjs/ant-design'
|
|
666
|
+
*
|
|
667
|
+
* transferValue('number', '42') // 42
|
|
668
|
+
* transferValue('boolean', 'true') // true
|
|
669
|
+
* transferValue('string[]', 'a,b') // ['a', 'b']
|
|
670
|
+
* ```
|
|
671
|
+
*/
|
|
434
672
|
function transferValue(type, value) {
|
|
435
673
|
if (!type) type = "string";
|
|
436
674
|
if (!type.endsWith("[]") && (typeof value === "undefined" || value === null || value === "" || value === "null" || value === "undefined")) return null;
|
|
@@ -456,15 +694,27 @@ function transferValue(type, value) {
|
|
|
456
694
|
return value;
|
|
457
695
|
}
|
|
458
696
|
/**
|
|
459
|
-
* Clone a UnionFaasItemElement with
|
|
697
|
+
* Clone a {@link UnionFaasItemElement} with FaasJS injection props.
|
|
698
|
+
*
|
|
699
|
+
* React elements are cloned directly, while component references are first wrapped with
|
|
700
|
+
* `createElement`.
|
|
460
701
|
*
|
|
461
|
-
*
|
|
462
|
-
*
|
|
463
|
-
*
|
|
702
|
+
* @param {UnionFaasItemElement} element - Element or component to clone.
|
|
703
|
+
* @param {any} props - Injection props such as `scene`, `value`, `values`, and `index`.
|
|
704
|
+
* @returns Cloned React element ready for rendering.
|
|
464
705
|
*
|
|
465
|
-
* @
|
|
466
|
-
*
|
|
467
|
-
*
|
|
706
|
+
* @example
|
|
707
|
+
* ```tsx
|
|
708
|
+
* import { cloneUnionFaasItemElement, type UnionFaasItemElement } from '@faasjs/ant-design'
|
|
709
|
+
*
|
|
710
|
+
* const Cell: UnionFaasItemElement<string> = ({ value }) => <span>{value}</span>
|
|
711
|
+
*
|
|
712
|
+
* const element = cloneUnionFaasItemElement(Cell, {
|
|
713
|
+
* scene: 'table',
|
|
714
|
+
* value: 'Hello',
|
|
715
|
+
* index: 0,
|
|
716
|
+
* })
|
|
717
|
+
* ```
|
|
468
718
|
*/
|
|
469
719
|
function cloneUnionFaasItemElement(element, props) {
|
|
470
720
|
return (0, react.cloneElement)((0, react.isValidElement)(element) ? element : (0, react.createElement)(element), props);
|
|
@@ -547,31 +797,41 @@ function DescriptionItemContent(props) {
|
|
|
547
797
|
}
|
|
548
798
|
DescriptionItemContent.displayName = "DescriptionItemContent";
|
|
549
799
|
/**
|
|
550
|
-
*
|
|
800
|
+
* Render an Ant Design description list from FaasJS item metadata.
|
|
551
801
|
*
|
|
552
|
-
*
|
|
802
|
+
* The component can render a local `dataSource` directly or resolve one through `faasData`, and
|
|
803
|
+
* it applies the same item type normalization helpers used by the form and table components.
|
|
804
|
+
*
|
|
805
|
+
* @template T - Data record shape rendered by the component.
|
|
806
|
+
* @param {DescriptionProps<T>} props - Description props including items, data source, and optional Faas data config.
|
|
807
|
+
* @throws {Error} When an entry in `extendTypes` omits both `children` and `render`.
|
|
553
808
|
*
|
|
554
809
|
* @example
|
|
555
810
|
* ```tsx
|
|
556
811
|
* import { Description } from '@faasjs/ant-design'
|
|
557
812
|
*
|
|
558
|
-
*
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
*
|
|
565
|
-
*
|
|
566
|
-
*
|
|
567
|
-
*
|
|
568
|
-
*
|
|
813
|
+
* export function Detail() {
|
|
814
|
+
* return (
|
|
815
|
+
* <Description
|
|
816
|
+
* title="Title"
|
|
817
|
+
* items={[
|
|
818
|
+
* {
|
|
819
|
+
* id: 'id',
|
|
820
|
+
* title: 'Title',
|
|
821
|
+
* type: 'string',
|
|
822
|
+
* },
|
|
823
|
+
* ]}
|
|
824
|
+
* dataSource={{ id: 'value' }}
|
|
825
|
+
* />
|
|
826
|
+
* )
|
|
827
|
+
* }
|
|
569
828
|
* ```
|
|
570
829
|
*/
|
|
571
|
-
function Description(
|
|
830
|
+
function Description(props) {
|
|
831
|
+
const { faasData, dataSource, renderTitle, extendTypes, ...descriptionProps } = props;
|
|
572
832
|
if (faasData && !dataSource) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FaasDataWrapper, {
|
|
573
833
|
render: ({ data }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Description, {
|
|
574
|
-
...
|
|
834
|
+
...descriptionProps,
|
|
575
835
|
dataSource: data,
|
|
576
836
|
...renderTitle ? { renderTitle } : {},
|
|
577
837
|
...extendTypes ? { extendTypes } : {}
|
|
@@ -579,9 +839,9 @@ function Description({ faasData, dataSource, renderTitle, extendTypes, ...props
|
|
|
579
839
|
...faasData
|
|
580
840
|
});
|
|
581
841
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(antd.Descriptions, {
|
|
582
|
-
...
|
|
583
|
-
title: typeof renderTitle === "function" ? renderTitle(dataSource) :
|
|
584
|
-
items:
|
|
842
|
+
...descriptionProps,
|
|
843
|
+
title: typeof renderTitle === "function" ? renderTitle(dataSource) : descriptionProps.title,
|
|
844
|
+
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) => ({
|
|
585
845
|
...item,
|
|
586
846
|
key: item.id,
|
|
587
847
|
label: item.title ?? idToTitle(item.id),
|
|
@@ -633,20 +893,30 @@ function processProps(propsCopy, config) {
|
|
|
633
893
|
return propsCopy;
|
|
634
894
|
}
|
|
635
895
|
/**
|
|
636
|
-
*
|
|
896
|
+
* Render a FaasJS-aware Ant Design form field or nested field group.
|
|
897
|
+
*
|
|
898
|
+
* The component derives default labels from `id`, applies required validation messages from the
|
|
899
|
+
* active theme, supports surface-specific union renderers, and can render nested `object` or
|
|
900
|
+
* `object[]` field structures.
|
|
637
901
|
*
|
|
638
|
-
* -
|
|
639
|
-
* -
|
|
902
|
+
* @template T - Value type rendered or edited by the form item.
|
|
903
|
+
* @param {FormItemProps<T>} props - Form item props including field metadata, rules, and custom renderers.
|
|
640
904
|
*
|
|
641
905
|
* @example
|
|
642
906
|
* ```tsx
|
|
643
|
-
*
|
|
644
|
-
*
|
|
907
|
+
* import { FormItem } from '@faasjs/ant-design'
|
|
908
|
+
* import { Input } from 'antd'
|
|
645
909
|
*
|
|
646
|
-
*
|
|
647
|
-
*
|
|
648
|
-
*
|
|
649
|
-
*
|
|
910
|
+
* export function AccountFields() {
|
|
911
|
+
* return (
|
|
912
|
+
* <>
|
|
913
|
+
* <FormItem id="name" type="string" />
|
|
914
|
+
* <FormItem id="password">
|
|
915
|
+
* <Input.Password />
|
|
916
|
+
* </FormItem>
|
|
917
|
+
* </>
|
|
918
|
+
* )
|
|
919
|
+
* }
|
|
650
920
|
* ```
|
|
651
921
|
*/
|
|
652
922
|
function FormItem(props) {
|
|
@@ -895,108 +1165,189 @@ function isFormItemProps(item) {
|
|
|
895
1165
|
return item.id !== void 0;
|
|
896
1166
|
}
|
|
897
1167
|
/**
|
|
898
|
-
*
|
|
1168
|
+
* Render a data-aware Ant Design form with optional FaasJS submission helpers.
|
|
1169
|
+
*
|
|
1170
|
+
* The component normalizes `initialValues` with {@link transferValue}, renders item definitions
|
|
1171
|
+
* through {@link FormItem}, and can either delegate submission to a custom `onFinish` handler or
|
|
1172
|
+
* the built-in FaasJS request flow configured by `faas`.
|
|
1173
|
+
*
|
|
1174
|
+
* @template Values - Form values shape.
|
|
1175
|
+
* @param {FormProps<Values>} props - Form props including items, submit behavior, and FaasJS integration.
|
|
1176
|
+
*
|
|
1177
|
+
* @example
|
|
1178
|
+
* ```tsx
|
|
1179
|
+
* import { Form } from '@faasjs/ant-design'
|
|
1180
|
+
*
|
|
1181
|
+
* export function ProfileForm() {
|
|
1182
|
+
* return (
|
|
1183
|
+
* <Form
|
|
1184
|
+
* items={[
|
|
1185
|
+
* { id: 'name', required: true },
|
|
1186
|
+
* { id: 'email', required: true },
|
|
1187
|
+
* ]}
|
|
1188
|
+
* onFinish={async (values) => {
|
|
1189
|
+
* console.log(values)
|
|
1190
|
+
* }}
|
|
1191
|
+
* />
|
|
1192
|
+
* )
|
|
1193
|
+
* }
|
|
1194
|
+
* ```
|
|
1195
|
+
*
|
|
1196
|
+
* @example
|
|
1197
|
+
* ```tsx
|
|
1198
|
+
* import { Form } from '@faasjs/ant-design'
|
|
899
1199
|
*
|
|
900
|
-
*
|
|
1200
|
+
* export function CreateUserForm() {
|
|
1201
|
+
* return (
|
|
1202
|
+
* <Form
|
|
1203
|
+
* initialValues={{ role: 'user' }}
|
|
1204
|
+
* items={[
|
|
1205
|
+
* { id: 'name', required: true },
|
|
1206
|
+
* { id: 'role', options: ['user', 'admin'] },
|
|
1207
|
+
* ]}
|
|
1208
|
+
* faas={{
|
|
1209
|
+
* action: 'user/create',
|
|
1210
|
+
* params: (values) => ({
|
|
1211
|
+
* role: values.role || 'user',
|
|
1212
|
+
* }),
|
|
1213
|
+
* }}
|
|
1214
|
+
* />
|
|
1215
|
+
* )
|
|
1216
|
+
* }
|
|
1217
|
+
* ```
|
|
901
1218
|
*/
|
|
902
1219
|
function Form(props) {
|
|
903
1220
|
const [loading, setLoading] = (0, react.useState)(false);
|
|
904
|
-
const [
|
|
905
|
-
const [submit, setSubmit] = (0, react.useState)();
|
|
1221
|
+
const [antdProps, setAntdProps] = (0, react.useState)();
|
|
1222
|
+
const [submit, setSubmit] = (0, react.useState)(props.submit === false ? false : {});
|
|
1223
|
+
const [items, setItems] = (0, react.useState)([]);
|
|
906
1224
|
const config = useConfigContext();
|
|
907
1225
|
const [extendTypes, setExtendTypes] = (0, react.useState)();
|
|
908
1226
|
const [form] = antd.Form.useForm(props.form);
|
|
909
1227
|
const [initialValues, setInitialValues] = (0, react.useState)(props.initialValues || Object.create(null));
|
|
1228
|
+
const [onFinish, setOnFinish] = (0, react.useState)();
|
|
910
1229
|
(0, _faasjs_react.useEqualEffect)(() => {
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
}
|
|
923
|
-
if (propsCopy.items?.length) {
|
|
924
|
-
for (const item of propsCopy.items) if (isFormItemProps(item) && item.if) item.hidden = !item.if(nextInitialValues || Object.create(null));
|
|
1230
|
+
if (props.onFinish) {
|
|
1231
|
+
setOnFinish(() => async (values) => {
|
|
1232
|
+
if (!props.onFinish) return;
|
|
1233
|
+
setLoading(true);
|
|
1234
|
+
try {
|
|
1235
|
+
return await props.onFinish(values);
|
|
1236
|
+
} finally {
|
|
1237
|
+
setLoading(false);
|
|
1238
|
+
}
|
|
1239
|
+
});
|
|
1240
|
+
return;
|
|
925
1241
|
}
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
propsCopy.onFinish = async (values) => {
|
|
1242
|
+
if (props.faas?.action) {
|
|
1243
|
+
setOnFinish(() => async (values) => {
|
|
1244
|
+
if (!props.faas?.action) return;
|
|
930
1245
|
setLoading(true);
|
|
1246
|
+
let submitValues = values;
|
|
931
1247
|
try {
|
|
932
|
-
if (
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
1248
|
+
if (props.faas?.transformValues) submitValues = await props.faas.transformValues(values);
|
|
1249
|
+
const extraParams = typeof props.faas?.params === "function" ? props.faas.params(submitValues) : props.faas.params;
|
|
1250
|
+
if (extraParams) submitValues = {
|
|
1251
|
+
...submitValues,
|
|
1252
|
+
...extraParams
|
|
1253
|
+
};
|
|
1254
|
+
const result = await (0, _faasjs_react.faas)(props.faas.action, submitValues);
|
|
1255
|
+
props.faas.onSuccess?.(result, submitValues);
|
|
1256
|
+
return result;
|
|
937
1257
|
} catch (error) {
|
|
938
|
-
|
|
1258
|
+
props.faas.onError?.(error, submitValues);
|
|
1259
|
+
throw error;
|
|
1260
|
+
} finally {
|
|
1261
|
+
props.faas.onFinally?.();
|
|
1262
|
+
setLoading(false);
|
|
939
1263
|
}
|
|
940
|
-
setLoading(false);
|
|
941
|
-
};
|
|
942
|
-
} else if (submitTo?.action) propsCopy.onFinish = async (values) => {
|
|
943
|
-
setLoading(true);
|
|
944
|
-
return (0, _faasjs_react.faas)(submitTo.action, submitTo.params ? {
|
|
945
|
-
...values,
|
|
946
|
-
...submitTo.params
|
|
947
|
-
} : values).then((result) => {
|
|
948
|
-
submitTo.then?.(result);
|
|
949
|
-
return result;
|
|
950
|
-
}).catch((error) => {
|
|
951
|
-
submitTo.catch?.(error);
|
|
952
|
-
return Promise.reject(error);
|
|
953
|
-
}).finally(() => {
|
|
954
|
-
submitTo.finally?.();
|
|
955
|
-
setLoading(false);
|
|
956
1264
|
});
|
|
957
|
-
|
|
958
|
-
if (propsCopy.extendTypes) {
|
|
959
|
-
setExtendTypes(propsCopy.extendTypes);
|
|
960
|
-
delete propsCopy.extendTypes;
|
|
1265
|
+
return;
|
|
961
1266
|
}
|
|
962
|
-
|
|
963
|
-
}, [
|
|
1267
|
+
setOnFinish(void 0);
|
|
1268
|
+
}, [props.onFinish, props.faas]);
|
|
1269
|
+
(0, _faasjs_react.useEqualEffect)(() => {
|
|
1270
|
+
setExtendTypes(props.extendTypes);
|
|
1271
|
+
}, [props.extendTypes]);
|
|
1272
|
+
(0, _faasjs_react.useEqualEffect)(() => {
|
|
1273
|
+
setSubmit(props.submit === false ? false : props.submit || {});
|
|
1274
|
+
}, [props.submit]);
|
|
1275
|
+
(0, _faasjs_react.useEqualEffect)(() => {
|
|
1276
|
+
const nextInitialValues = props.initialValues ? JSON.parse(JSON.stringify(props.initialValues)) : Object.create(null);
|
|
1277
|
+
for (const key in nextInitialValues) nextInitialValues[key] = transferValue(props.items?.find((item) => isFormItemProps(item) && item.id === key)?.type, nextInitialValues[key]);
|
|
1278
|
+
if (props.items?.length) setItems(props.items.map((item) => {
|
|
1279
|
+
if (!isFormItemProps(item) || !item.if) return item;
|
|
1280
|
+
return {
|
|
1281
|
+
...item,
|
|
1282
|
+
hidden: !item.if(nextInitialValues)
|
|
1283
|
+
};
|
|
1284
|
+
}));
|
|
1285
|
+
else setItems([]);
|
|
1286
|
+
if (props.initialValues) {
|
|
1287
|
+
setInitialValues(nextInitialValues);
|
|
1288
|
+
return;
|
|
1289
|
+
}
|
|
1290
|
+
setInitialValues(null);
|
|
1291
|
+
}, [props.initialValues, props.items]);
|
|
1292
|
+
(0, _faasjs_react.useEqualEffect)(() => {
|
|
1293
|
+
const propsCopy = { ...props };
|
|
1294
|
+
delete propsCopy.onFinish;
|
|
1295
|
+
delete propsCopy.faas;
|
|
1296
|
+
delete propsCopy.extendTypes;
|
|
1297
|
+
delete propsCopy.submit;
|
|
1298
|
+
delete propsCopy.items;
|
|
1299
|
+
delete propsCopy.initialValues;
|
|
1300
|
+
setAntdProps(propsCopy);
|
|
1301
|
+
}, [props]);
|
|
964
1302
|
const onValuesChange = (0, _faasjs_react.useEqualCallback)((changedValues, allValues) => {
|
|
965
1303
|
console.debug("Form:onValuesChange", changedValues, allValues);
|
|
966
1304
|
if (props.onValuesChange) props.onValuesChange(changedValues, allValues);
|
|
967
|
-
if (!
|
|
1305
|
+
if (!items.length) return;
|
|
968
1306
|
for (const key in changedValues) {
|
|
969
|
-
const item =
|
|
1307
|
+
const item = items.find((i) => isFormItemProps(i) && i.id === key);
|
|
970
1308
|
if (item?.onValueChange) item.onValueChange(changedValues[key], allValues, form);
|
|
971
1309
|
}
|
|
972
|
-
}, [
|
|
1310
|
+
}, [
|
|
1311
|
+
items,
|
|
1312
|
+
props.onValuesChange,
|
|
1313
|
+
form
|
|
1314
|
+
]);
|
|
973
1315
|
(0, _faasjs_react.useEqualEffect)(() => {
|
|
974
1316
|
if (!initialValues) return;
|
|
975
1317
|
console.debug("Form:initialValues", initialValues);
|
|
976
1318
|
form.setFieldsValue(initialValues);
|
|
977
1319
|
setInitialValues(null);
|
|
978
|
-
}, [
|
|
979
|
-
|
|
1320
|
+
}, [
|
|
1321
|
+
form,
|
|
1322
|
+
initialValues,
|
|
1323
|
+
items
|
|
1324
|
+
]);
|
|
1325
|
+
if (!antdProps) return null;
|
|
1326
|
+
const submitButtonProps = typeof submit === "object" ? submit.buttonProps : void 0;
|
|
1327
|
+
const submitButtonLoading = loading ? true : submitButtonProps?.loading ?? false;
|
|
980
1328
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(antd.Form, {
|
|
981
|
-
...
|
|
1329
|
+
...antdProps,
|
|
1330
|
+
form,
|
|
1331
|
+
onFinish,
|
|
982
1332
|
onValuesChange,
|
|
983
1333
|
children: [
|
|
984
|
-
|
|
985
|
-
|
|
1334
|
+
props.beforeItems,
|
|
1335
|
+
items.map((item) => {
|
|
986
1336
|
if (isFormItemProps(item)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormItem, {
|
|
987
1337
|
...item,
|
|
988
1338
|
...extendTypes ? { extendTypes } : {}
|
|
989
1339
|
}, item.id);
|
|
990
1340
|
return item;
|
|
991
1341
|
}),
|
|
992
|
-
|
|
1342
|
+
props.children,
|
|
993
1343
|
typeof submit !== "boolean" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(antd.Button, {
|
|
1344
|
+
...submitButtonProps,
|
|
994
1345
|
htmlType: "submit",
|
|
995
|
-
type: "primary",
|
|
996
|
-
loading,
|
|
1346
|
+
type: submitButtonProps?.type || "primary",
|
|
1347
|
+
loading: submitButtonLoading,
|
|
997
1348
|
children: submit?.text || config.theme.Form.submit.text
|
|
998
1349
|
}),
|
|
999
|
-
|
|
1350
|
+
props.footer
|
|
1000
1351
|
]
|
|
1001
1352
|
});
|
|
1002
1353
|
}
|
|
@@ -1010,15 +1361,27 @@ Form.Provider = antd.Form.Provider;
|
|
|
1010
1361
|
//#endregion
|
|
1011
1362
|
//#region src/Link.tsx
|
|
1012
1363
|
/**
|
|
1013
|
-
*
|
|
1364
|
+
* Render a navigation-aware link or button.
|
|
1365
|
+
*
|
|
1366
|
+
* Internal links are pushed through React Router, while links with `_blank` targets are opened
|
|
1367
|
+
* with `window.open`.
|
|
1368
|
+
*
|
|
1369
|
+
* @param {LinkProps} props - Link props controlling navigation target, rendering mode, and button behavior.
|
|
1014
1370
|
*
|
|
1015
1371
|
* @example
|
|
1016
1372
|
* ```tsx
|
|
1017
|
-
*
|
|
1018
|
-
* <Link href="/">Home</Link>
|
|
1373
|
+
* import { Link } from '@faasjs/ant-design'
|
|
1019
1374
|
*
|
|
1020
|
-
*
|
|
1021
|
-
*
|
|
1375
|
+
* export function Navigation() {
|
|
1376
|
+
* return (
|
|
1377
|
+
* <>
|
|
1378
|
+
* <Link href="/">Home</Link>
|
|
1379
|
+
* <Link href="/users/new" button={{ type: 'primary' }}>
|
|
1380
|
+
* Create User
|
|
1381
|
+
* </Link>
|
|
1382
|
+
* </>
|
|
1383
|
+
* )
|
|
1384
|
+
* }
|
|
1022
1385
|
* ```
|
|
1023
1386
|
*/
|
|
1024
1387
|
function Link(props) {
|
|
@@ -1075,6 +1438,23 @@ function Link(props) {
|
|
|
1075
1438
|
}
|
|
1076
1439
|
//#endregion
|
|
1077
1440
|
//#region src/Routers.tsx
|
|
1441
|
+
/**
|
|
1442
|
+
* Default 404 route element that uses the configured localized title.
|
|
1443
|
+
*
|
|
1444
|
+
* @example
|
|
1445
|
+
* ```tsx
|
|
1446
|
+
* import { PageNotFound, Routes } from '@faasjs/ant-design'
|
|
1447
|
+
*
|
|
1448
|
+
* export function AppRoutes() {
|
|
1449
|
+
* return (
|
|
1450
|
+
* <Routes
|
|
1451
|
+
* routes={[{ path: '/', element: <div>Home</div> }]}
|
|
1452
|
+
* notFound={<PageNotFound />}
|
|
1453
|
+
* />
|
|
1454
|
+
* )
|
|
1455
|
+
* }
|
|
1456
|
+
* ```
|
|
1457
|
+
*/
|
|
1078
1458
|
function PageNotFound() {
|
|
1079
1459
|
const { theme } = useConfigContext();
|
|
1080
1460
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(antd.Result, {
|
|
@@ -1083,22 +1463,31 @@ function PageNotFound() {
|
|
|
1083
1463
|
});
|
|
1084
1464
|
}
|
|
1085
1465
|
/**
|
|
1086
|
-
*
|
|
1466
|
+
* Render React Router routes with lazy-page support and a default 404 route.
|
|
1467
|
+
*
|
|
1468
|
+
* The wrapper adds a catch-all route automatically and uses an Ant Design `Skeleton` fallback when
|
|
1469
|
+
* `fallback` is not provided.
|
|
1470
|
+
*
|
|
1471
|
+
* @param {RoutesProps} props - Route definitions and optional fallback or 404 elements.
|
|
1087
1472
|
*
|
|
1088
1473
|
* @example
|
|
1089
1474
|
* ```tsx
|
|
1090
1475
|
* import { Routes, lazy } from '@faasjs/ant-design'
|
|
1091
1476
|
* import { BrowserRouter } from 'react-router-dom'
|
|
1092
1477
|
*
|
|
1093
|
-
* export function App
|
|
1094
|
-
* return
|
|
1095
|
-
* <
|
|
1096
|
-
*
|
|
1097
|
-
*
|
|
1098
|
-
*
|
|
1099
|
-
*
|
|
1100
|
-
*
|
|
1101
|
-
*
|
|
1478
|
+
* export function App() {
|
|
1479
|
+
* return (
|
|
1480
|
+
* <BrowserRouter>
|
|
1481
|
+
* <Routes
|
|
1482
|
+
* routes={[
|
|
1483
|
+
* {
|
|
1484
|
+
* path: '/',
|
|
1485
|
+
* page: lazy(() => import('./pages/home')),
|
|
1486
|
+
* },
|
|
1487
|
+
* ]}
|
|
1488
|
+
* />
|
|
1489
|
+
* </BrowserRouter>
|
|
1490
|
+
* )
|
|
1102
1491
|
* }
|
|
1103
1492
|
* ```
|
|
1104
1493
|
*/
|
|
@@ -1139,12 +1528,39 @@ function processValue(item, value) {
|
|
|
1139
1528
|
return transferred;
|
|
1140
1529
|
}
|
|
1141
1530
|
/**
|
|
1142
|
-
*
|
|
1531
|
+
* Render an Ant Design table from FaasJS item metadata.
|
|
1532
|
+
*
|
|
1533
|
+
* The component can render local `dataSource` rows or resolve remote rows through `faasData`. It
|
|
1534
|
+
* also generates default filters and sorters for built-in item types unless you disable them with
|
|
1535
|
+
* the corresponding Ant Design column props.
|
|
1143
1536
|
*
|
|
1144
|
-
* -
|
|
1145
|
-
* -
|
|
1146
|
-
* -
|
|
1147
|
-
*
|
|
1537
|
+
* @template T - Row record type rendered by the table.
|
|
1538
|
+
* @template ExtendTypes - Additional item prop shape accepted by `items`.
|
|
1539
|
+
* @param {TableProps<T, ExtendTypes>} props - Table props including columns, data source, and optional Faas data config.
|
|
1540
|
+
* @throws {Error} When an entry in `extendTypes` omits both `children` and `render`.
|
|
1541
|
+
*
|
|
1542
|
+
* @example
|
|
1543
|
+
* ```tsx
|
|
1544
|
+
* import { Table } from '@faasjs/ant-design'
|
|
1545
|
+
*
|
|
1546
|
+
* const rows = [
|
|
1547
|
+
* { id: 1, name: 'Alice', active: true },
|
|
1548
|
+
* { id: 2, name: 'Bob', active: false },
|
|
1549
|
+
* ]
|
|
1550
|
+
*
|
|
1551
|
+
* export function UserTable() {
|
|
1552
|
+
* return (
|
|
1553
|
+
* <Table
|
|
1554
|
+
* rowKey="id"
|
|
1555
|
+
* dataSource={rows}
|
|
1556
|
+
* items={[
|
|
1557
|
+
* { id: 'name', title: 'Name' },
|
|
1558
|
+
* { id: 'active', type: 'boolean', title: 'Active' },
|
|
1559
|
+
* ]}
|
|
1560
|
+
* />
|
|
1561
|
+
* )
|
|
1562
|
+
* }
|
|
1563
|
+
* ```
|
|
1148
1564
|
*/
|
|
1149
1565
|
function Table(props) {
|
|
1150
1566
|
const [columns, setColumns] = (0, react.useState)();
|
|
@@ -1530,28 +1946,32 @@ function FaasDataTable({ props, columns, data, params, reload, loading }) {
|
|
|
1530
1946
|
//#endregion
|
|
1531
1947
|
//#region src/Tabs.tsx
|
|
1532
1948
|
/**
|
|
1533
|
-
*
|
|
1949
|
+
* Render an Ant Design tabs wrapper that accepts FaasJS-style tab definitions.
|
|
1950
|
+
*
|
|
1951
|
+
* Missing `key` and `label` values are derived from each tab's `id` and `title`.
|
|
1534
1952
|
*
|
|
1535
|
-
* -
|
|
1536
|
-
* - Support auto skip null/false tab item.
|
|
1537
|
-
* - Support `id` as key and label.
|
|
1953
|
+
* @param {TabsProps} props - Tabs props including tab items and Ant Design tab options.
|
|
1538
1954
|
*
|
|
1539
1955
|
* @example
|
|
1540
1956
|
* ```tsx
|
|
1541
1957
|
* import { Tabs } from '@faasjs/ant-design'
|
|
1542
1958
|
*
|
|
1543
|
-
*
|
|
1544
|
-
*
|
|
1545
|
-
*
|
|
1546
|
-
*
|
|
1547
|
-
*
|
|
1548
|
-
*
|
|
1549
|
-
*
|
|
1550
|
-
*
|
|
1551
|
-
*
|
|
1552
|
-
*
|
|
1553
|
-
*
|
|
1554
|
-
*
|
|
1959
|
+
* export function Page() {
|
|
1960
|
+
* return (
|
|
1961
|
+
* <Tabs
|
|
1962
|
+
* items={[
|
|
1963
|
+
* {
|
|
1964
|
+
* id: 'id',
|
|
1965
|
+
* children: 'content',
|
|
1966
|
+
* },
|
|
1967
|
+
* 1 === 0 && {
|
|
1968
|
+
* id: 'hidden',
|
|
1969
|
+
* children: 'content',
|
|
1970
|
+
* },
|
|
1971
|
+
* ]}
|
|
1972
|
+
* />
|
|
1973
|
+
* )
|
|
1974
|
+
* }
|
|
1555
1975
|
* ```
|
|
1556
1976
|
*/
|
|
1557
1977
|
function Tabs(props) {
|
|
@@ -1567,21 +1987,24 @@ function Tabs(props) {
|
|
|
1567
1987
|
//#endregion
|
|
1568
1988
|
//#region src/Title.tsx
|
|
1569
1989
|
/**
|
|
1570
|
-
*
|
|
1990
|
+
* Update `document.title` and optionally render the title inline.
|
|
1571
1991
|
*
|
|
1572
|
-
*
|
|
1992
|
+
* The component returns `null` by default and is often used only for its side effect.
|
|
1573
1993
|
*
|
|
1574
|
-
*
|
|
1575
|
-
* // return null
|
|
1576
|
-
* <Title title='hi' /> // => change the document.title to 'hi'
|
|
1577
|
-
* <Title title={['a', 'b']} /> // => change the document.title to 'a - b'
|
|
1994
|
+
* @param {TitleProps} props - Title props controlling document title updates and optional inline rendering.
|
|
1578
1995
|
*
|
|
1579
|
-
*
|
|
1580
|
-
*
|
|
1581
|
-
*
|
|
1996
|
+
* @example
|
|
1997
|
+
* ```tsx
|
|
1998
|
+
* import { Title } from '@faasjs/ant-design'
|
|
1582
1999
|
*
|
|
1583
|
-
*
|
|
1584
|
-
*
|
|
2000
|
+
* export function DetailPage() {
|
|
2001
|
+
* return (
|
|
2002
|
+
* <>
|
|
2003
|
+
* <Title title={['Orders', 'Detail']} h1 />
|
|
2004
|
+
* <div>...</div>
|
|
2005
|
+
* </>
|
|
2006
|
+
* )
|
|
2007
|
+
* }
|
|
1585
2008
|
* ```
|
|
1586
2009
|
*/
|
|
1587
2010
|
function Title(props) {
|
|
@@ -1605,12 +2028,20 @@ function Title(props) {
|
|
|
1605
2028
|
//#endregion
|
|
1606
2029
|
//#region src/useThemeToken.ts
|
|
1607
2030
|
/**
|
|
1608
|
-
*
|
|
2031
|
+
* Read the current Ant Design theme token.
|
|
1609
2032
|
*
|
|
1610
|
-
*
|
|
1611
|
-
* and returns the `token` property from the configuration.
|
|
2033
|
+
* @returns Ant Design global token object for the active theme.
|
|
1612
2034
|
*
|
|
1613
|
-
* @
|
|
2035
|
+
* @example
|
|
2036
|
+
* ```tsx
|
|
2037
|
+
* import { useThemeToken } from '@faasjs/ant-design'
|
|
2038
|
+
*
|
|
2039
|
+
* function PrimarySwatch() {
|
|
2040
|
+
* const { colorPrimary } = useThemeToken()
|
|
2041
|
+
*
|
|
2042
|
+
* return <div style={{ width: 24, height: 24, background: colorPrimary }} />
|
|
2043
|
+
* }
|
|
2044
|
+
* ```
|
|
1614
2045
|
*/
|
|
1615
2046
|
function useThemeToken() {
|
|
1616
2047
|
return antd.theme.useToken().token;
|