@chris-c-brine/form-dialog 1.0.5 → 1.1.0

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 CHANGED
@@ -40,36 +40,82 @@ This package has the following peer dependencies that need to be installed in yo
40
40
 
41
41
  ## Login Form Usage Example
42
42
 
43
+ ```tsx
44
+ // LoginPage.tsx
45
+ import { type FC } from "react";
46
+ import { Container, IconButton } from "@mui/material";
47
+ import { useDialog } from "@chris-c-brine/form-dialog";
48
+ import LoginForm from "./components/forms/LoginForm";
49
+ import { Lock as LockIcon } from "@mui/icons-material";
50
+ import { LoginDialog } from "./LoginDialog";
51
+
52
+ const LoginPage: FC = () => {
53
+ const { dialogProps, openDialog } = useDialog();
54
+
55
+ return (
56
+ <Container
57
+ component="main"
58
+ maxWidth={"xs"}
59
+ sx={{
60
+ display: "flex",
61
+ alignItems: "center",
62
+ justifyContent: "center",
63
+ height: "85vh",
64
+ overflow: "hidden",
65
+ animation: "fadeIn 1s ease-in-out",
66
+ "@keyframes fadeIn": {
67
+ from: { opacity: 0 },
68
+ to: { opacity: 1 },
69
+ },
70
+ }}
71
+ >
72
+ <LoginForm>
73
+ <IconButton color="primary" onClick={openDialog} sx={{ py: 1 }}>
74
+ <LockIcon sx={{ fontSize: 50 }} />
75
+ </IconButton>
76
+ </LoginForm>
77
+ <LoginDialog dialogProps={dialogProps} />
78
+ </Container>
79
+ );
80
+ };
81
+
82
+ export default LoginPage;
83
+ ```
84
+ ```tsx
85
+ // LoginPageConstants.ts
86
+ import type { SubmitHandler } from "react-hook-form";
87
+
88
+ export const defaultLoginFormValues = { username: "", password: "" };
89
+ export type LoginFormValues = typeof defaultLoginFormValues;
90
+ ```
43
91
  ```tsx
44
92
  // LoginFormBase.tsx
45
- import {
46
- TextFieldElement,
47
- PasswordElement,
48
- type PasswordElementProps,
49
- useFormContext,
50
- } from "react-hook-form-mui";
93
+ import { TextFieldElement, PasswordElement, type PasswordElementProps, useFormContext} from "react-hook-form-mui";
51
94
  import { memo, useEffect } from "react";
52
- import { useFormDialog, AutoGrid, type AutoGridProps } from "@chris-c-brine/form-dialog";
95
+ import { useFormDialog, AutoGrid, type AutoGridProps } from "@chris-c-brine/form-dialog";
53
96
 
54
- export type NameProp = {name?: string; };
55
- export type LoginFormProps = NameProp & Pick<AutoGridProps, "columnCount">;
97
+ /**
98
+ * Login Form
99
+ */
100
+ export type NameProp = {
101
+ name?: string;
102
+ };
56
103
 
104
+ export type LoginFormProps = NameProp & Pick<AutoGridProps, "columnCount">;
57
105
  const LoginFormBase = memo(function ({ name, columnCount = 1 }: LoginFormProps) {
58
- const { disabled } = useFormDialog();
59
-
60
- useEffect(() => formNameLog(name), [name]);
61
-
62
- return (
63
- <AutoGrid
64
- columnCount={columnCount}
65
- columnSpacing={2}
66
- rowSpacing={1}
67
- components={[
68
- <UserName key={`${name}-username`} disabled={disabled} />,
69
- <Password key={`${name}-password`} disabled={disabled} />,
70
- ]}
71
- />
72
- );
106
+ const { disabled } = useFormDialog();
107
+
108
+ return (
109
+ <AutoGrid
110
+ columnCount={columnCount}
111
+ columnSpacing={2}
112
+ rowSpacing={1}
113
+ components={[
114
+ <UserName key={`${name}-username`} disabled={disabled} />,
115
+ <Password key={`${name}-password`} disabled={disabled} />,
116
+ ]}
117
+ />
118
+ );
73
119
  });
74
120
 
75
121
  LoginFormBase.displayName = "LoginForm";
@@ -80,37 +126,36 @@ export default LoginFormBase;
80
126
  * Inputs
81
127
  */
82
128
  const UserName = ({ disabled }: Pick<PasswordElementProps, "disabled">) => (
83
- <TextFieldElement
84
- name="username"
85
- label="Username"
86
- required
87
- autoFocus
88
- autoComplete="off"
89
- fullWidth
90
- margin={"dense"}
91
- size={"medium"}
92
- disabled={disabled}
93
- slotProps={{
94
- inputLabel: { shrink: true },
95
- }}
96
- />
129
+ <TextFieldElement
130
+ name="username"
131
+ label="Username"
132
+ required
133
+ autoFocus
134
+ autoComplete="off"
135
+ fullWidth
136
+ margin={"dense"}
137
+ size={"medium"}
138
+ disabled={disabled}
139
+ slotProps={{
140
+ inputLabel: { shrink: true },
141
+ }}
142
+ />
97
143
  );
98
-
99
144
  UserName.displayName = "UserName";
100
145
 
101
- const Password = function ({ disabled }: Pick<PasswordElementProps, "disabled">) {
146
+ const Password = ({ disabled }: Pick<PasswordElementProps, "disabled">) => {
102
147
  const { setValue, getValues } = useFormContext();
103
148
  const password = getValues("password");
104
149
 
105
150
  useEffect(() => {
106
151
  if (disabled && password !== "") {
107
- setValue("passwordDisabled", "");
152
+ setValue("disabledPassword", "");
108
153
  }
109
154
  }, [disabled, setValue, password]);
110
155
 
111
156
  return (
112
157
  <PasswordElement
113
- name={"passwordDisabled"}
158
+ name={"password"}
114
159
  label={"Password"}
115
160
  fullWidth
116
161
  required
@@ -125,71 +170,29 @@ const Password = function ({ disabled }: Pick<PasswordElementProps, "disabled">)
125
170
  />
126
171
  );
127
172
  };
128
- Password.displayName = "Password";
129
- ```
130
- ```tsx
131
- // LoginDialog.tsx
132
- import { FormDialog, FormDialogActions, type FormDialogProps, PersistForm } from "@chris-c-brine/form-dialog";
133
- import { useMemo, type FC } from "react";
134
- import { useForm } from "react-hook-form-mui";
135
- import LoginFormBase from "../forms/LoginFormBase";
136
- import {
137
- defaultLoginFormValues,
138
- type LoginForm,
139
- type SubmitLogin,
140
- } from "@pages/LoginPage/LoginPageConstants";
141
- import { useDialog } from "@hooks";
142
- import { devLog } from "@utils";
143
-
144
- const formKey = "dialog-login-form";
145
-
146
- /* Basic Form Dialog Test */
147
- type LoginDialogProps = Pick<ReturnType<typeof useDialog>, "dialogProps"> &
148
- Pick<FormDialogProps<LoginForm>, "onClose"> & {
149
- handleSubmit: SubmitLogin;
150
- };
151
173
 
152
- const LoginDialog: FC<LoginDialogProps> = ({ dialogProps, handleSubmit }) => {
153
- const formContext = useForm({ defaultValues: defaultLoginFormValues });
154
- const loginForm = useMemo(() => <LoginFormBase name={formKey} columnCount={2} />, []);
155
-
156
- return (
157
- <FormDialog
158
- {...dialogProps}
159
- formProps={{ onSuccess: handleSubmit, formContext, onError: devLog("Form Errors") }}
160
- title={"Basic Form Dialog Test"}
161
- titleProps={{ variant: "h5", textAlign: "center" }}
162
- actions={<FormDialogActions resetProps={{ formKey }} submitProps={{ maxAttempts: 3 }} />}
163
- >
164
- <PersistForm formName={formKey}>{loginForm}</PersistForm>
165
- </FormDialog>
166
- );
167
- };
168
-
169
- LoginDialog.displayName = "LoginDialog";
170
-
171
- export default LoginDialog;
174
+ Password.displayName = "Password";
172
175
  ```
173
176
  ```tsx
174
177
  // LoginForm.tsx
175
178
  import { Lock as LockIcon } from "@mui/icons-material";
176
179
  import { Box, Typography, type TypographyProps } from "@mui/material";
177
- import { type SubmitLogin, defaultLoginFormValues } from "@pages/LoginPage/LoginPageConstants";
178
- import { devLog } from "@utils";
179
180
  import { merge } from "lodash";
180
- import type { FC, PropsWithChildren } from "react";
181
- import LoginFormBase from "./LoginFormBase";
181
+ import { FC, PropsWithChildren, useCallback, useMemo } from "react";
182
182
  import { FormDialogActions, FormDialogProvider, PaperForm } from "@chris-c-brine/form-dialog";
183
+ import { SubmitHandler, useForm } from "react-hook-form-mui";
184
+ import { defaultLoginFormValues, LoginFormValues } from "./LoginPageConstants";
185
+ import LoginFormBase from "./LoginFormBase";
186
+ import { globalErrorAtom, useUser } from "@features";
187
+ import { useSetAtom } from "jotai/index";
188
+ import { Person as PersonIcon } from "@mui/icons-material";
183
189
 
184
190
  const AltIcon = () => <LockIcon sx={{ mr: 1, fontSize: 20 }} />;
185
191
 
186
- interface LoginFormProps extends PropsWithChildren {
187
- onSuccess: SubmitLogin;
188
- }
192
+ export const LoginForm: FC<PropsWithChildren> = ({ children }) => {
189
193
 
190
- const LoginForm: FC<LoginFormProps> = ({ onSuccess, children }) => {
191
194
  return (
192
- <LoginPaperForm onSuccess={onSuccess}>
195
+ <LoginPaperForm>
193
196
  <Box px={2}>
194
197
  {children}
195
198
  <SecureLoginText />
@@ -208,8 +211,6 @@ const LoginForm: FC<LoginFormProps> = ({ onSuccess, children }) => {
208
211
  );
209
212
  };
210
213
 
211
- export default LoginForm;
212
-
213
214
  const SecureLoginText: FC<TypographyProps> = (props) => {
214
215
  const typographyProps = merge(
215
216
  {
@@ -222,18 +223,38 @@ const SecureLoginText: FC<TypographyProps> = (props) => {
222
223
  return <Typography {...typographyProps}>Secure Login</Typography>;
223
224
  };
224
225
 
225
- type LoginPaperFormProps = PropsWithChildren & {
226
- onSuccess?: SubmitLogin;
227
- };
226
+ const LoginPaperForm: FC<PropsWithChildren> = ({ children }) => {
227
+ const formContext = useForm({defaultValues: defaultLoginFormValues});
228
+ const { setUser } = useUser();
229
+ const setError = useSetAtom(globalErrorAtom);
230
+ const reset = useMemo(() => formContext.reset, [formContext?.reset]);
231
+
232
+ const onSuccess: SubmitHandler<LoginFormValues> = useCallback(
233
+ (data, event) => {
234
+ event?.preventDefault(); // Stop default html form submit
235
+ event?.stopPropagation(); // STOP!!!!!
236
+
237
+ setUser({ name: data.username, isActive: true }); // Update User (and/or other business logic)
238
+ reset(); // reset form
239
+ setError({ // Signal Success!
240
+ message: <>Hello {data.username}!</>,
241
+ title: "Successful Login!",
242
+ severity: "success",
243
+ icon: <PersonIcon sx={{ fontSize: 35 }} />,
244
+ });
245
+ }, [setUser, setError, reset]);
228
246
 
229
- const LoginPaperForm: FC<LoginPaperFormProps> = ({ children, onSuccess }) => {
230
247
  return (
231
248
  <FormDialogProvider>
232
249
  <PaperForm
250
+ persistKey={'login-page-form'}
233
251
  formProps={{
234
- defaultValues: defaultLoginFormValues,
252
+ formContext,
235
253
  onSuccess,
236
- onError: devLog("Form Errors"),
254
+ onError: (errors, event) => {
255
+ event?.preventDefault();
256
+ console.log(errors)
257
+ },
237
258
  }}
238
259
  elevation={3}
239
260
  sx={{
@@ -247,79 +268,66 @@ const LoginPaperForm: FC<LoginPaperFormProps> = ({ children, onSuccess }) => {
247
268
  </FormDialogProvider>
248
269
  );
249
270
  };
250
-
251
271
  ```
252
272
  ```tsx
253
- // LoginPage.tsx
254
- import { useCallback, useEffect, useState, type FC, type PropsWithChildren } from "react";
255
- import { Container, IconButton } from "@mui/material";
256
- import { useUser } from "@features";
257
- import { useDialog } from "@chris-c-brine/form-dialog";
258
- import { useForm, type SubmitHandler } from "react-hook-form-mui";
259
- import { toast } from "react-toastify";
260
- import LoginDialog from "./components/dialogs/LoginDialog";
261
- import LoginForm from "./components/forms/LoginForm";
262
- import { Lock as LockIcon } from "@mui/icons-material";
273
+ // LoginDialog.tsx
274
+ import { useDialog, FormDialog, FormDialogActions } from "@chris-c-brine/form-dialog";
275
+ import { memo, useCallback, useMemo } from "react";
276
+ import LoginFormBase from "./LoginFormBase";
277
+ import { defaultLoginFormValues, LoginFormValues } from "./LoginPageConstants";
278
+ import { SubmitHandler, useForm } from "react-hook-form-mui";
279
+ import { globalErrorAtom, useUser } from "@features";
280
+ import { useSetAtom } from "jotai/index";
281
+ import { Person as PersonIcon } from "@mui/icons-material";
263
282
 
264
- const defaultLoginFormValues = { username: "", password: "" };
265
- type SubmitLogin = SubmitHandler<typeof defaultLoginFormValues>;
266
- const LoginPage: FC = () => {
267
- const { dialogProps, closeDialog, openDialog } = useDialog();
268
- const { setUser } = useUser();
269
- const [showDialog, setShowDialog] = useState(dialogProps.open);
283
+ const formKey = "dialog-login-form";
270
284
 
271
- useEffect(() => {
272
- if (!showDialog && dialogProps.open) {
273
- setShowDialog(true);
274
- }
275
- }, [dialogProps.open, showDialog]);
285
+ export type LoginDialogProps = {
286
+ dialogProps: ReturnType<typeof useDialog>["dialogProps"];
287
+ };
276
288
 
289
+ export const LoginDialog = memo(function ({ dialogProps }: LoginDialogProps) {
290
+ const setError = useSetAtom(globalErrorAtom);
291
+ const { setUser } = useUser();
277
292
  const formContext = useForm({ defaultValues: defaultLoginFormValues });
278
- const onSuccess: SubmitLogin = useCallback(
293
+
294
+ const reset = useMemo(() => formContext.reset, [formContext?.reset]);
295
+
296
+ const onSuccess: SubmitHandler<LoginFormValues> = useCallback(
279
297
  (data, event) => {
280
- event?.preventDefault(); // Stop default form submit
281
- formContext.reset(); // Reset form
298
+ event?.preventDefault();
299
+ event?.stopPropagation();
300
+
301
+ console.log(event);
282
302
  setUser({ name: data.username, isActive: true }); // Update User (and/or other business logic)
283
- closeDialog(); // Close Dialog
284
- toast.success("Error Dialog Test!"); // Signal success beyond just closing the dialog
303
+ reset(); // reset form
304
+ setError({
305
+ // Signal Success!
306
+ message: <>Hello {data.username}!</>,
307
+ title: "Successful Login!",
308
+ severity: "success",
309
+ icon: <PersonIcon sx={{ fontSize: 35 }} />,
310
+ });
311
+ dialogProps?.onClose();
285
312
  },
286
- [formContext, setUser, closeDialog],
313
+ [setUser, setError, dialogProps, reset],
287
314
  );
288
315
 
289
316
  return (
290
- <LoginFormContainer>
291
- <LoginForm onSuccess={onSuccess}>
292
- <IconButton color="primary" onClick={openDialog} sx={{ py: 1 }}>
293
- <LockIcon sx={{ fontSize: 50 }} />
294
- </IconButton>
295
- </LoginForm>
296
- {showDialog && (
297
- <LoginDialog dialogProps={dialogProps} handleSubmit={onSuccess} onClose={undefined} />
298
- )}
299
- </LoginFormContainer>
317
+ <FormDialog
318
+ {...dialogProps}
319
+ persistKey={formKey}
320
+ formProps={{ onSuccess, formContext }}
321
+ title={"Basic Persist Form Dialog Test"}
322
+ titleProps={{ variant: "h5", textAlign: "center" }}
323
+ actions={<FormDialogActions resetProps={{ formKey }} submitProps={{ maxAttempts: 3 }} />}
324
+ >
325
+ <LoginFormBase columnCount={2} />
326
+ </FormDialog>
300
327
  );
301
- };
328
+ });
329
+
330
+ LoginDialog.displayName = "LoginDialog";
302
331
 
303
- export default LoginPage;
304
332
 
305
- const LoginFormContainer: FC<PropsWithChildren> = ({ children }) => (
306
- <Container
307
- component="main"
308
- maxWidth={"xs"}
309
- sx={{
310
- display: "flex",
311
- alignItems: "center",
312
- justifyContent: "center",
313
- height: "85vh",
314
- overflow: "hidden",
315
- animation: "fadeIn 1s ease-in-out",
316
- "@keyframes fadeIn": {
317
- from: { opacity: 0 },
318
- to: { opacity: 1 },
319
- },
320
- }}
321
- >
322
- {children}
323
- </Container>
324
- );
325
333
  ```
@@ -31,10 +31,6 @@ export type FormResetButtonProps = Omit<ButtonProps, "onClick"> & {
31
31
  * - Form-wide disabled state from FormDialogContext
32
32
  *
33
33
  * @example
34
- * // Basic usage
35
- * <FormResetButton />
36
- *
37
- * @example
38
34
  * // With persistence integration
39
35
  * <FormResetButton formKey="user-profile-form" />
40
36
  *
@@ -14,7 +14,7 @@ export type FormSubmitButtonProps = Omit<LoadingButtonProps, "onClick"> & {
14
14
  maxAttempts?: number;
15
15
  };
16
16
  /**
17
- * A submit button for forms with loading state, attempt tracking and form context awareness
17
+ * A "submit button" for forms with loading state, attempt tracking and form context awareness
18
18
  *
19
19
  * This component extends the LoadingButton with form-specific features:
20
20
  * - Automatically displays loading state during form submission
@@ -28,9 +28,6 @@ export type FormSubmitButtonProps = Omit<LoadingButtonProps, "onClick"> & {
28
28
  * - Explicit-disabled prop
29
29
  * - Form-wide disabled state from FormDialogContext
30
30
  *
31
- * @example
32
- * // Basic usage
33
- * <FormSubmitButton />
34
31
  *
35
32
  * @example
36
33
  * // With custom text and max attempts
@@ -1,7 +1,7 @@
1
1
  import type { FC, ReactNode } from "react";
2
2
  import { type BlackoutDialogProps } from "./BlackoutDialog";
3
3
  import type { DialogContentProps, DialogTitleProps, DialogActionsProps } from "@mui/material";
4
- export type BaseDialogProps = Omit<BlackoutDialogProps, "children" | "title" | "content"> & {
4
+ export type BaseDialogProps = BlackoutDialogProps & {
5
5
  /**
6
6
  * Title content for the dialog
7
7
  * When provided, renders a DialogTitle component
@@ -9,17 +9,12 @@ export type BaseDialogProps = Omit<BlackoutDialogProps, "children" | "title" | "
9
9
  title?: ReactNode;
10
10
  /**
11
11
  * Props passed to the DialogTitle component
12
- * Only applied when title is provided
12
+ * Only applied when the title is provided
13
13
  */
14
14
  titleProps?: DialogTitleProps;
15
- /**
16
- * Main content of the dialog
17
- * When provided, renders a DialogContent component
18
- */
19
- children?: ReactNode;
20
15
  /**
21
16
  * Props passed to the DialogContent component
22
- * Only applied when children is provided
17
+ * Only applied when children are provided
23
18
  */
24
19
  contentProps?: DialogContentProps;
25
20
  /**
@@ -29,7 +24,7 @@ export type BaseDialogProps = Omit<BlackoutDialogProps, "children" | "title" | "
29
24
  actions?: ReactNode;
30
25
  /**
31
26
  * Props passed to the DialogActions component
32
- * Only applied when actions is provided
27
+ * Only applied when actions are provided
33
28
  */
34
29
  actionsProps?: DialogActionsProps;
35
30
  /**
@@ -57,27 +52,11 @@ export type BaseDialogProps = Omit<BlackoutDialogProps, "children" | "title" | "
57
52
  * consistent styling and behavior.
58
53
  *
59
54
  * @example
60
- * // Basic usage with all sections
61
- * <BaseDialog
62
- * open={open}
63
- * onClose={handleClose}
64
- * title="Confirmation"
65
- * actions={
66
- * <>
67
- * <Button onClick={handleCancel}>Cancel</Button>
68
- * <Button onClick={handleConfirm}>Confirm</Button>
69
- * </>
70
- * }
71
- * >
72
- * Are you sure you want to proceed?
73
- * </BaseDialog>
74
- *
75
- * @example
76
55
  * // Customized with section props
77
56
  * <BaseDialog
78
57
  * open={isOpen}
79
58
  * title="Advanced Settings"
80
- * titleProps={{ sx: { bgcolor: 'primary.main', color: 'white' } }}
59
+ * titleProps={{ sx: { backgroundColor: 'primary.main', color: 'white' } }}
81
60
  * contentProps={{ sx: { p: 3 } }}
82
61
  * actionsProps={{ sx: { justifyContent: 'space-between' } }}
83
62
  * actions={<SettingsDialogActions />}
@@ -1,6 +1,6 @@
1
1
  import { type DialogProps } from "@mui/material";
2
- import { type FC, type PropsWithChildren } from "react";
3
- export type BlackoutDialogProps = DialogProps & Partial<PropsWithChildren> & {
2
+ import { type FC } from "react";
3
+ export type BlackoutDialogProps = Omit<DialogProps, "title"> & {
4
4
  /**
5
5
  * An optional unique string identifier
6
6
  * @default 'blackout-dialog'
@@ -1,15 +1,10 @@
1
1
  import { type BaseDialogProps } from "./BaseDialog";
2
- import { type FieldValues, type FormContainerProps } from "react-hook-form-mui";
2
+ import { CommonFormProps } from "../forms/PaperForm";
3
+ import { type FieldValues } from "react-hook-form-mui";
3
4
  /**
4
5
  * Props for the FormDialog component
5
6
  */
6
- export type FormDialogProps<T extends FieldValues> = Omit<BaseDialogProps, "PaperComponent"> & {
7
- /**
8
- * Form methods from useForm hook
9
- * Establish the form context for child components
10
- */
11
- formProps: FormContainerProps<T>;
12
- };
7
+ export type FormDialogProps<T extends FieldValues> = Omit<BaseDialogProps, "PaperComponent"> & CommonFormProps<T>;
13
8
  /**
14
9
  * A dialog component specialized for forms with integrated context providers
15
10
  *
@@ -31,4 +26,7 @@ export type FormDialogProps<T extends FieldValues> = Omit<BaseDialogProps, "Pape
31
26
  * - useFormDialog() - Access dialog controls and state
32
27
  *
33
28
  */
34
- export declare const FormDialog: <T extends FieldValues>({ formProps, children, open, onClose, ...dialogProps }: FormDialogProps<T>) => import("react/jsx-runtime").JSX.Element;
29
+ export declare const FormDialog: {
30
+ <T extends FieldValues>({ formProps, children, open, onClose, persistKey, ...dialogProps }: FormDialogProps<T>): import("react/jsx-runtime").JSX.Element;
31
+ displayName: string;
32
+ };
@@ -6,7 +6,7 @@ import { FormSubmitButtonProps } from "../buttons/FormSubmitButton";
6
6
  /**
7
7
  * Props for the FormDialogActions component
8
8
  */
9
- export type FormDialogActionsProps = PropsWithChildren & {
9
+ export type FormDialogActionsProps = Partial<PropsWithChildren> & {
10
10
  /**
11
11
  * Props to customize the cancel button
12
12
  */
@@ -16,7 +16,7 @@ export type FormDialogActionsProps = PropsWithChildren & {
16
16
  */
17
17
  resetProps?: FormResetButtonProps;
18
18
  /**
19
- * Props to customize the submit button
19
+ * Props to customize the "submit button"
20
20
  */
21
21
  submitProps?: FormSubmitButtonProps;
22
22
  /**
@@ -1,15 +1,23 @@
1
1
  import { type PaperProps } from "@mui/material";
2
2
  import { type FieldValues, type FormContainerProps } from "react-hook-form-mui";
3
- /**
4
- * Props for the PaperForm component
5
- */
6
- export type PaperFormProps<T extends FieldValues> = PaperProps & {
3
+ export type CommonFormProps<T extends FieldValues> = {
7
4
  /**
8
5
  * Props to configure the form container
9
- * Includes settings for form state, validation, and submission handling
6
+ * This includes settings for form state, validation, and submission handling
10
7
  */
11
8
  formProps: FormContainerProps<T>;
9
+ /**
10
+ * Optional key to use for form state persistence
11
+ * When provided, the form state will be persisted in
12
+ * session storage with a fallback to local storage (TODO: make configurable)
13
+ * and restored on form reload/mount.
14
+ */
15
+ persistKey?: string;
12
16
  };
17
+ /**
18
+ * Props for the PaperForm component
19
+ */
20
+ export type PaperFormProps<T extends FieldValues> = PaperProps & CommonFormProps<T>;
13
21
  /**
14
22
  * A component that combines a Material UI Paper with a form container
15
23
  *
@@ -56,4 +64,4 @@ export type PaperFormProps<T extends FieldValues> = PaperProps & {
56
64
  *
57
65
  * @template T - The type of form values being handled
58
66
  */
59
- export declare const PaperForm: <T extends FieldValues>({ children, formProps, ...paperProps }: PaperFormProps<T>) => import("react/jsx-runtime").JSX.Element;
67
+ export declare const PaperForm: <T extends FieldValues>({ children, persistKey, formProps, ...paperProps }: PaperFormProps<T>) => import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,4 @@
1
- import type { FC, PropsWithChildren } from "react";
1
+ import { type PropsWithChildren } from "react";
2
2
  /**
3
3
  * Props for the PersistForm component
4
4
  */
@@ -50,4 +50,4 @@ export interface PersistFormProps extends PropsWithChildren {
50
50
  * </PersistForm>
51
51
  * </FormDialog>
52
52
  */
53
- export declare const PersistForm: FC<PersistFormProps>;
53
+ export declare const PersistForm: import("react").NamedExoticComponent<PersistFormProps>;
@@ -6,6 +6,7 @@ export * from "./forms/PersistForm";
6
6
  export * from "./buttons/FormCancelButton";
7
7
  export * from "./buttons/FormSubmitButton";
8
8
  export * from "./buttons/FormResetButton";
9
+ export * from "./buttons/LoadingButton";
9
10
  export * from "./dialogs/FormDialogActions";
10
11
  export * from "./AutoGrid";
11
12
  export * from "./GridSpacer";
@@ -1,5 +1,5 @@
1
1
  export * from "./useFormDialog";
2
2
  export * from "./useMaxAttempts";
3
- export * from "./usePersistedForm";
3
+ export * from "./usePersistForm";
4
4
  export * from "./useOnMount";
5
5
  export * from "./useDialog";