@axinom/mosaic-ui 0.74.0 → 0.74.1
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/dist/cjs/components/FormStation/FormStation.d.ts +17 -1
- package/dist/cjs/components/FormStation/FormStation.d.ts.map +1 -1
- package/dist/cjs/components/FormStation/FormStationHeader/FormStationHeader.d.ts +2 -0
- package/dist/cjs/components/FormStation/FormStationHeader/FormStationHeader.d.ts.map +1 -1
- package/dist/cjs/components/FormStation/ModalForm/ModalForm.d.ts +41 -0
- package/dist/cjs/components/FormStation/ModalForm/ModalForm.d.ts.map +1 -0
- package/dist/cjs/components/FormStation/ModalForm/useModalForm.d.ts +19 -0
- package/dist/cjs/components/FormStation/ModalForm/useModalForm.d.ts.map +1 -0
- package/dist/cjs/components/FormStation/index.d.ts +2 -0
- package/dist/cjs/components/FormStation/index.d.ts.map +1 -1
- package/dist/cjs/index.js +4 -4
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/components/FormStation/FormStation.d.ts +17 -1
- package/dist/esm/components/FormStation/FormStation.d.ts.map +1 -1
- package/dist/esm/components/FormStation/FormStationHeader/FormStationHeader.d.ts +2 -0
- package/dist/esm/components/FormStation/FormStationHeader/FormStationHeader.d.ts.map +1 -1
- package/dist/esm/components/FormStation/ModalForm/ModalForm.d.ts +41 -0
- package/dist/esm/components/FormStation/ModalForm/ModalForm.d.ts.map +1 -0
- package/dist/esm/components/FormStation/ModalForm/useModalForm.d.ts +19 -0
- package/dist/esm/components/FormStation/ModalForm/useModalForm.d.ts.map +1 -0
- package/dist/esm/components/FormStation/index.d.ts +2 -0
- package/dist/esm/components/FormStation/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/FormStation/FormStation.tsx +22 -1
- package/src/components/FormStation/FormStationHeader/FormStationHeader.tsx +34 -2
- package/src/components/FormStation/ModalForm/ModalForm.module.scss +18 -0
- package/src/components/FormStation/ModalForm/ModalForm.spec.tsx +290 -0
- package/src/components/FormStation/ModalForm/ModalForm.stories.tsx +191 -0
- package/src/components/FormStation/ModalForm/ModalForm.tsx +80 -0
- package/src/components/FormStation/ModalForm/useModalForm.tsx +30 -0
- package/src/components/FormStation/index.ts +5 -0
- package/src/components/Modal/Modal.module.scss +4 -3
- package/src/styles/variables.scss +4 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import React, { type PropsWithChildren } from 'react';
|
|
3
|
+
import type { Data } from '../../../types/data';
|
|
4
|
+
import { FormStation, type FormStationProps } from '../FormStation';
|
|
5
|
+
import classes from './ModalForm.module.scss';
|
|
6
|
+
|
|
7
|
+
export type ModalFormProps<
|
|
8
|
+
TValues extends Data,
|
|
9
|
+
TSubmitResponse = unknown,
|
|
10
|
+
> = Omit<
|
|
11
|
+
FormStationProps<TValues, TSubmitResponse>,
|
|
12
|
+
| 'cancelNavigationUrl'
|
|
13
|
+
| 'onCancel'
|
|
14
|
+
| 'onSaveCompleted'
|
|
15
|
+
| 'saveOnNavigate'
|
|
16
|
+
| 'defaultTitle'
|
|
17
|
+
| 'titleProperty'
|
|
18
|
+
| 'setTabTitle'
|
|
19
|
+
> & {
|
|
20
|
+
/** The title of the form, shown in the modal's header */
|
|
21
|
+
title: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Closes the modal hosting the form. Pass the `closeModal` callback the
|
|
25
|
+
* `useModal` hook provides to the modal component.
|
|
26
|
+
*/
|
|
27
|
+
closeModal: () => void;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The width of the form inside the modal (as CSS width).
|
|
31
|
+
* Defaults to the full width the modal leaves over.
|
|
32
|
+
*/
|
|
33
|
+
width?: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* This component is the basic building block for forms shown inside a modal.
|
|
38
|
+
*
|
|
39
|
+
* Its header actions are bound to the hosting modal instead of the router:
|
|
40
|
+
* 'Cancel' discards the changes and closes the modal, 'Save' calls `saveData`
|
|
41
|
+
* and closes the modal once the data was saved. A failed save keeps the modal
|
|
42
|
+
* open and shows the error.
|
|
43
|
+
*
|
|
44
|
+
* Use it with the `useModal` hook, or with `useModalForm`, which combines both.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* const { ModalWrapper, openModal } = useModal(({ closeModal }) => (
|
|
48
|
+
* <ModalForm<Genre>
|
|
49
|
+
* title="Edit Genre"
|
|
50
|
+
* closeModal={closeModal}
|
|
51
|
+
* initialData={{ loading, data }}
|
|
52
|
+
* saveData={saveData}
|
|
53
|
+
* >
|
|
54
|
+
* <Field name="title" label="Title" as={SingleLineTextField} />
|
|
55
|
+
* </ModalForm>
|
|
56
|
+
* ));
|
|
57
|
+
*/
|
|
58
|
+
export const ModalForm = <TValues extends Data, TSubmitResponse = unknown>({
|
|
59
|
+
title,
|
|
60
|
+
closeModal,
|
|
61
|
+
width,
|
|
62
|
+
className,
|
|
63
|
+
...props
|
|
64
|
+
}: PropsWithChildren<
|
|
65
|
+
ModalFormProps<TValues, TSubmitResponse>
|
|
66
|
+
>): JSX.Element => (
|
|
67
|
+
<div className={classes.container} style={{ width }}>
|
|
68
|
+
<FormStation<TValues, TSubmitResponse>
|
|
69
|
+
{...props}
|
|
70
|
+
defaultTitle={title}
|
|
71
|
+
onCancel={closeModal}
|
|
72
|
+
onSaveCompleted={closeModal}
|
|
73
|
+
// Navigating away is not a commit point for a modal - only 'Save' is.
|
|
74
|
+
saveOnNavigate={false}
|
|
75
|
+
// The modal is not a page of its own.
|
|
76
|
+
setTabTitle={false}
|
|
77
|
+
className={clsx(classes.station, className)}
|
|
78
|
+
/>
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, { type PropsWithChildren } from 'react';
|
|
2
|
+
import type { Data } from '../../../types/data';
|
|
3
|
+
import { type UseModalResult, useModal } from '../../Modal';
|
|
4
|
+
import { ModalForm, type ModalFormProps } from './ModalForm';
|
|
5
|
+
|
|
6
|
+
export type UseModalFormOptions<
|
|
7
|
+
TValues extends Data,
|
|
8
|
+
TSubmitResponse = unknown,
|
|
9
|
+
> = PropsWithChildren<
|
|
10
|
+
Omit<ModalFormProps<TValues, TSubmitResponse>, 'closeModal'>
|
|
11
|
+
>;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The `useModal` hook with a `ModalForm` already wired up: shows the form in a
|
|
15
|
+
* modal and returns the methods to control it.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* const { ModalWrapper, openModal } = useModalForm<Genre>({
|
|
19
|
+
* title: 'Edit Genre',
|
|
20
|
+
* initialData: { loading, data },
|
|
21
|
+
* saveData,
|
|
22
|
+
* children: <Field name="title" label="Title" as={SingleLineTextField} />,
|
|
23
|
+
* });
|
|
24
|
+
*/
|
|
25
|
+
export const useModalForm = <TValues extends Data, TSubmitResponse = unknown>(
|
|
26
|
+
options: UseModalFormOptions<TValues, TSubmitResponse>,
|
|
27
|
+
): UseModalResult =>
|
|
28
|
+
useModal(({ closeModal }) => (
|
|
29
|
+
<ModalForm<TValues, TSubmitResponse> {...options} closeModal={closeModal} />
|
|
30
|
+
));
|
|
@@ -3,3 +3,8 @@ export { Details, type DetailsProps } from './Details/Details';
|
|
|
3
3
|
export { FormGrid } from './FormGrid';
|
|
4
4
|
export { FormStation, type FormStationProps } from './FormStation';
|
|
5
5
|
export * from './FormStation.models';
|
|
6
|
+
export { ModalForm, type ModalFormProps } from './ModalForm/ModalForm';
|
|
7
|
+
export {
|
|
8
|
+
useModalForm,
|
|
9
|
+
type UseModalFormOptions,
|
|
10
|
+
} from './ModalForm/useModalForm';
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
justify-content: center;
|
|
17
17
|
z-index: 9999;
|
|
18
18
|
|
|
19
|
-
padding:
|
|
19
|
+
padding: $modal-padding-top $modal-padding-side $modal-padding-bottom
|
|
20
|
+
$modal-padding-side;
|
|
20
21
|
background-color: var(--modal-back-drop-color, $modal-back-drop-color);
|
|
21
22
|
|
|
22
23
|
.child {
|
|
@@ -31,7 +32,8 @@
|
|
|
31
32
|
|
|
32
33
|
// To avoid the Modal container padding overwritten by parent container
|
|
33
34
|
&.container {
|
|
34
|
-
padding:
|
|
35
|
+
padding: $modal-padding-top $modal-padding-side $modal-padding-bottom
|
|
36
|
+
$modal-padding-side;
|
|
35
37
|
}
|
|
36
38
|
}
|
|
37
39
|
|
|
@@ -60,4 +62,3 @@
|
|
|
60
62
|
transform: translateY(100vh);
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
|
-
|
|
@@ -305,6 +305,10 @@ $fallback-image-bg-color: var(--mosaic-neutral-3, #efefef);
|
|
|
305
305
|
/* Modal */
|
|
306
306
|
$modal-back-drop-color: rgba(169, 169, 169, 0.75);
|
|
307
307
|
$modal-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
|
|
308
|
+
// Back-drop padding. Content that fills the modal sizes itself against these.
|
|
309
|
+
$modal-padding-top: 70px;
|
|
310
|
+
$modal-padding-bottom: 30px;
|
|
311
|
+
$modal-padding-side: 30px;
|
|
308
312
|
|
|
309
313
|
/* ProgressBar */
|
|
310
314
|
$progress-bar-processing-indicator: var(--mosaic-secondary);
|