mirror of
https://github.com/hexastack/hexabot
synced 2025-06-26 18:27:28 +00:00
feat(frontend): add useDialog
This commit is contained in:
parent
734838660a
commit
735e783864
@ -6,106 +6,34 @@
|
|||||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as React from "react";
|
import {
|
||||||
|
createContext,
|
||||||
|
FC,
|
||||||
|
useCallback,
|
||||||
|
useId,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
|
|
||||||
export interface OpenDialogOptions<R> {
|
import { ConfirmDialog, ConfirmDialogProps } from "@/app-components/dialogs";
|
||||||
/**
|
import {
|
||||||
* A function that is called before closing the dialog closes. The dialog
|
CloseDialog,
|
||||||
* stays open as long as the returned promise is not resolved. Use this if
|
DialogComponent,
|
||||||
* you want to perform an async action on close and show a loading state.
|
DialogProviderProps,
|
||||||
*
|
DialogStackEntry,
|
||||||
* @param result The result that the dialog will return after closing.
|
OpenDialog,
|
||||||
* @returns A promise that resolves when the dialog can be closed.
|
OpenDialogOptions,
|
||||||
*/
|
} from "@/types/common/dialogs.types";
|
||||||
onClose?: (result: R) => Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
export const DialogsContext = createContext<
|
||||||
* The props that are passed to a dialog component.
|
| {
|
||||||
*/
|
open: OpenDialog;
|
||||||
export interface DialogProps<P = undefined, R = void> {
|
close: CloseDialog;
|
||||||
/**
|
confirm: FC<ConfirmDialogProps>;
|
||||||
* The payload that was passed when the dialog was opened.
|
}
|
||||||
*/
|
| undefined
|
||||||
payload: P;
|
>(undefined);
|
||||||
/**
|
|
||||||
* Whether the dialog is open.
|
|
||||||
*/
|
|
||||||
open: boolean;
|
|
||||||
/**
|
|
||||||
* A function to call when the dialog should be closed. If the dialog has a return
|
|
||||||
* value, it should be passed as an argument to this function. You should use the promise
|
|
||||||
* that is returned to show a loading state while the dialog is performing async actions
|
|
||||||
* on close.
|
|
||||||
* @param result The result to return from the dialog.
|
|
||||||
* @returns A promise that resolves when the dialog can be fully closed.
|
|
||||||
*/
|
|
||||||
onClose: (result: R) => Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type DialogComponent<P, R> = React.ComponentType<DialogProps<P, R>>;
|
|
||||||
|
|
||||||
export interface OpenDialog {
|
|
||||||
/**
|
|
||||||
* Open a dialog without payload.
|
|
||||||
* @param Component The dialog component to open.
|
|
||||||
* @param options Additional options for the dialog.
|
|
||||||
*/
|
|
||||||
<P extends undefined, R>(
|
|
||||||
Component: DialogComponent<P, R>,
|
|
||||||
payload?: P,
|
|
||||||
options?: OpenDialogOptions<R>,
|
|
||||||
): Promise<R>;
|
|
||||||
/**
|
|
||||||
* Open a dialog and pass a payload.
|
|
||||||
* @param Component The dialog component to open.
|
|
||||||
* @param payload The payload to pass to the dialog.
|
|
||||||
* @param options Additional options for the dialog.
|
|
||||||
*/
|
|
||||||
<P, R>(
|
|
||||||
Component: DialogComponent<P, R>,
|
|
||||||
payload: P,
|
|
||||||
options?: OpenDialogOptions<R>,
|
|
||||||
): Promise<R>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CloseDialog {
|
|
||||||
/**
|
|
||||||
* Close a dialog and return a result.
|
|
||||||
* @param dialog The dialog to close. The promise returned by `open`.
|
|
||||||
* @param result The result to return from the dialog.
|
|
||||||
* @returns A promise that resolves when the dialog is fully closed.
|
|
||||||
*/
|
|
||||||
<R>(dialog: Promise<R>, result: R): Promise<R>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DialogHook {
|
|
||||||
// alert: OpenAlertDialog;
|
|
||||||
// confirm: OpenConfirmDialog;
|
|
||||||
// prompt: OpenPromptDialog;
|
|
||||||
open: OpenDialog;
|
|
||||||
close: CloseDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DialogsContext = React.createContext<{
|
|
||||||
open: OpenDialog;
|
|
||||||
close: CloseDialog;
|
|
||||||
} | null>(null);
|
|
||||||
|
|
||||||
interface DialogStackEntry<P, R> {
|
|
||||||
key: string;
|
|
||||||
open: boolean;
|
|
||||||
promise: Promise<R>;
|
|
||||||
Component: DialogComponent<P, R>;
|
|
||||||
payload: P;
|
|
||||||
onClose: (result: R) => Promise<void>;
|
|
||||||
resolve: (result: R) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DialogProviderProps {
|
|
||||||
children?: React.ReactNode;
|
|
||||||
unmountAfter?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provider for Dialog stacks. The subtree of this component can use the `useDialogs` hook to
|
* Provider for Dialog stacks. The subtree of this component can use the `useDialogs` hook to
|
||||||
@ -121,10 +49,10 @@ export interface DialogProviderProps {
|
|||||||
*/
|
*/
|
||||||
function DialogsProvider(props: DialogProviderProps) {
|
function DialogsProvider(props: DialogProviderProps) {
|
||||||
const { children, unmountAfter = 1000 } = props;
|
const { children, unmountAfter = 1000 } = props;
|
||||||
const [stack, setStack] = React.useState<DialogStackEntry<any, any>[]>([]);
|
const [stack, setStack] = useState<DialogStackEntry<any, any>[]>([]);
|
||||||
const keyPrefix = React.useId();
|
const keyPrefix = useId();
|
||||||
const nextId = React.useRef(0);
|
const nextId = useRef(0);
|
||||||
const requestDialog = React.useCallback<OpenDialog>(
|
const requestDialog = useCallback<OpenDialog>(
|
||||||
function open<P, R>(
|
function open<P, R>(
|
||||||
Component: DialogComponent<P, R>,
|
Component: DialogComponent<P, R>,
|
||||||
payload: P,
|
payload: P,
|
||||||
@ -160,7 +88,7 @@ function DialogsProvider(props: DialogProviderProps) {
|
|||||||
},
|
},
|
||||||
[keyPrefix],
|
[keyPrefix],
|
||||||
);
|
);
|
||||||
const closeDialogUi = React.useCallback(
|
const closeDialogUi = useCallback(
|
||||||
function closeDialogUi<R>(dialog: Promise<R>) {
|
function closeDialogUi<R>(dialog: Promise<R>) {
|
||||||
setStack((prevStack) =>
|
setStack((prevStack) =>
|
||||||
prevStack.map((entry) =>
|
prevStack.map((entry) =>
|
||||||
@ -176,7 +104,7 @@ function DialogsProvider(props: DialogProviderProps) {
|
|||||||
},
|
},
|
||||||
[unmountAfter],
|
[unmountAfter],
|
||||||
);
|
);
|
||||||
const closeDialog = React.useCallback(
|
const closeDialog = useCallback(
|
||||||
async function closeDialog<R>(dialog: Promise<R>, result: R) {
|
async function closeDialog<R>(dialog: Promise<R>, result: R) {
|
||||||
const entryToClose = stack.find((entry) => entry.promise === dialog);
|
const entryToClose = stack.find((entry) => entry.promise === dialog);
|
||||||
|
|
||||||
@ -192,8 +120,12 @@ function DialogsProvider(props: DialogProviderProps) {
|
|||||||
},
|
},
|
||||||
[stack, closeDialogUi],
|
[stack, closeDialogUi],
|
||||||
);
|
);
|
||||||
const contextValue = React.useMemo(
|
const contextValue = useMemo(
|
||||||
() => ({ open: requestDialog, close: closeDialog }),
|
() => ({
|
||||||
|
open: requestDialog,
|
||||||
|
close: closeDialog,
|
||||||
|
confirm: ConfirmDialog,
|
||||||
|
}),
|
||||||
[requestDialog, closeDialog],
|
[requestDialog, closeDialog],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -6,121 +6,56 @@
|
|||||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useContext, useMemo } from "react";
|
import React, { useContext, useMemo } from "react";
|
||||||
|
|
||||||
|
import { ConfirmDialog } from "@/app-components/dialogs";
|
||||||
|
import { DialogsContext } from "@/contexts/dialogs.context";
|
||||||
import {
|
import {
|
||||||
CloseDialog,
|
CloseDialog,
|
||||||
DialogsContext,
|
OpenConfirmDialog,
|
||||||
OpenDialog,
|
OpenDialog,
|
||||||
} from "@/contexts/dialogs.context";
|
} from "@/types/common/dialogs.types";
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright © 2025 Hexastack. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
|
||||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
|
||||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright © 2025 Hexastack. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
|
||||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
|
||||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright © 2025 Hexastack. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
|
||||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
|
||||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright © 2025 Hexastack. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
|
||||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
|
||||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright © 2025 Hexastack. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
|
||||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
|
||||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright © 2025 Hexastack. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
|
||||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
|
||||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright © 2025 Hexastack. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
|
||||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
|
||||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright © 2025 Hexastack. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
|
||||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
|
||||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright © 2025 Hexastack. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
|
||||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
|
||||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
|
||||||
*/
|
|
||||||
|
|
||||||
export interface DialogHook {
|
export interface DialogHook {
|
||||||
// alert: OpenAlertDialog;
|
|
||||||
// confirm: OpenConfirmDialog;
|
|
||||||
// prompt: OpenPromptDialog;
|
|
||||||
open: OpenDialog;
|
open: OpenDialog;
|
||||||
close: CloseDialog;
|
close: CloseDialog;
|
||||||
|
// alert: OpenAlertDialog;
|
||||||
|
// prompt: OpenPromptDialog;
|
||||||
|
confirm: OpenConfirmDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useDialogs(): DialogHook {
|
export const useDialogs = (): DialogHook => {
|
||||||
const { open, close } = useContext(DialogsContext);
|
const context = useContext(DialogsContext);
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
throw new Error("useDialogs must be used within a DialogsProvider");
|
||||||
|
}
|
||||||
|
|
||||||
|
const { open, close } = context;
|
||||||
// const alert = React.useCallback<OpenAlertDialog>(
|
// const alert = React.useCallback<OpenAlertDialog>(
|
||||||
// async (msg, { onClose, ...options } = {}) =>
|
// async (msg, { onClose, ...options } = {}) =>
|
||||||
// open(AlertDialog, { ...options, msg }, { onClose }),
|
// open(AlertDialog, { ...options, msg }, { onClose }),
|
||||||
// [open],
|
// [open],
|
||||||
// );
|
// );
|
||||||
// const confirm = React.useCallback<OpenConfirmDialog>(
|
|
||||||
// async (msg, { onClose, ...options } = {}) =>
|
|
||||||
// open(ConfirmDialog, { ...options, msg }, { onClose }),
|
|
||||||
// [open],
|
|
||||||
// );
|
|
||||||
// const prompt = React.useCallback<OpenPromptDialog>(
|
// const prompt = React.useCallback<OpenPromptDialog>(
|
||||||
// async (msg, { onClose, ...options } = {}) =>
|
// async (msg, { onClose, ...options } = {}) =>
|
||||||
// open(PromptDialog, { ...options, msg }, { onClose }),
|
// open(PromptDialog, { ...options, msg }, { onClose }),
|
||||||
// [open],
|
// [open],
|
||||||
// );
|
// );
|
||||||
|
const confirm = React.useCallback<OpenConfirmDialog>(
|
||||||
|
async (msg, { onClose, ...options } = {}) =>
|
||||||
|
open(ConfirmDialog, { ...options, msg }, { onClose }),
|
||||||
|
[open],
|
||||||
|
);
|
||||||
|
|
||||||
return useMemo(
|
return useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
// alert,
|
|
||||||
// confirm,
|
|
||||||
// prompt,
|
|
||||||
open,
|
open,
|
||||||
close,
|
close,
|
||||||
|
// alert,
|
||||||
|
// prompt,
|
||||||
|
confirm,
|
||||||
}),
|
}),
|
||||||
// [alert, close, confirm, open, prompt],
|
[close, open, confirm],
|
||||||
[close, open],
|
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
@ -86,17 +86,19 @@ const App = ({ Component, pageProps }: TAppPropsWithLayout) => {
|
|||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<ApiClientProvider>
|
<ApiClientProvider>
|
||||||
<BroadcastChannelProvider channelName="main-channel">
|
<DialogsProvider>
|
||||||
<AuthProvider>
|
<BroadcastChannelProvider channelName="main-channel">
|
||||||
<PermissionProvider>
|
<AuthProvider>
|
||||||
<SettingsProvider>
|
<PermissionProvider>
|
||||||
<SocketProvider>
|
<SettingsProvider>
|
||||||
{getLayout(<Component {...pageProps} />)}
|
<SocketProvider>
|
||||||
</SocketProvider>
|
{getLayout(<Component {...pageProps} />)}
|
||||||
</SettingsProvider>
|
</SocketProvider>
|
||||||
</PermissionProvider>
|
</SettingsProvider>
|
||||||
</AuthProvider>
|
</PermissionProvider>
|
||||||
</BroadcastChannelProvider>
|
</AuthProvider>
|
||||||
|
</BroadcastChannelProvider>
|
||||||
|
</DialogsProvider>
|
||||||
</ApiClientProvider>
|
</ApiClientProvider>
|
||||||
<ReactQueryDevtools initialIsOpen={false} />
|
<ReactQueryDevtools initialIsOpen={false} />
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
|
173
frontend/src/types/common/dialogs.types.ts
Normal file
173
frontend/src/types/common/dialogs.types.ts
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2025 Hexastack. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||||
|
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||||
|
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DialogProps as MuiDialogProps } from "@mui/material";
|
||||||
|
import { BaseSyntheticEvent, ReactNode } from "react";
|
||||||
|
|
||||||
|
// context
|
||||||
|
|
||||||
|
export interface OpenDialogOptions<R> {
|
||||||
|
/**
|
||||||
|
* A function that is called before closing the dialog closes. The dialog
|
||||||
|
* stays open as long as the returned promise is not resolved. Use this if
|
||||||
|
* you want to perform an async action on close and show a loading state.
|
||||||
|
*
|
||||||
|
* @param result The result that the dialog will return after closing.
|
||||||
|
* @returns A promise that resolves when the dialog can be closed.
|
||||||
|
*/
|
||||||
|
onClose?: (result: R) => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The props that are passed to a dialog component.
|
||||||
|
*/
|
||||||
|
export interface DialogProps<P = undefined, R = void> {
|
||||||
|
/**
|
||||||
|
* The payload that was passed when the dialog was opened.
|
||||||
|
*/
|
||||||
|
payload: P;
|
||||||
|
/**
|
||||||
|
* Whether the dialog is open.
|
||||||
|
*/
|
||||||
|
open: boolean;
|
||||||
|
/**
|
||||||
|
* A function to call when the dialog should be closed. If the dialog has a return
|
||||||
|
* value, it should be passed as an argument to this function. You should use the promise
|
||||||
|
* that is returned to show a loading state while the dialog is performing async actions
|
||||||
|
* on close.
|
||||||
|
* @param result The result to return from the dialog.
|
||||||
|
* @returns A promise that resolves when the dialog can be fully closed.
|
||||||
|
*/
|
||||||
|
onClose: (result: R) => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DialogComponent<P, R> = React.ComponentType<DialogProps<P, R>>;
|
||||||
|
|
||||||
|
export interface OpenDialog {
|
||||||
|
/**
|
||||||
|
* Open a dialog without payload.
|
||||||
|
* @param Component The dialog component to open.
|
||||||
|
* @param options Additional options for the dialog.
|
||||||
|
*/
|
||||||
|
<P extends undefined, R>(
|
||||||
|
Component: DialogComponent<P, R>,
|
||||||
|
payload?: P,
|
||||||
|
options?: OpenDialogOptions<R>,
|
||||||
|
): Promise<R>;
|
||||||
|
/**
|
||||||
|
* Open a dialog and pass a payload.
|
||||||
|
* @param Component The dialog component to open.
|
||||||
|
* @param payload The payload to pass to the dialog.
|
||||||
|
* @param options Additional options for the dialog.
|
||||||
|
*/
|
||||||
|
<P, R>(
|
||||||
|
Component: DialogComponent<P, R>,
|
||||||
|
payload: P,
|
||||||
|
options?: OpenDialogOptions<R>,
|
||||||
|
): Promise<R>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CloseDialog {
|
||||||
|
/**
|
||||||
|
* Close a dialog and return a result.
|
||||||
|
* @param dialog The dialog to close. The promise returned by `open`.
|
||||||
|
* @param result The result to return from the dialog.
|
||||||
|
* @returns A promise that resolves when the dialog is fully closed.
|
||||||
|
*/
|
||||||
|
<R>(dialog: Promise<R>, result: R): Promise<R>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ConfirmOptions extends OpenDialogOptions<boolean> {
|
||||||
|
/**
|
||||||
|
* A title for the dialog. Defaults to `'Confirm'`.
|
||||||
|
*/
|
||||||
|
title?: React.ReactNode;
|
||||||
|
/**
|
||||||
|
* The text to show in the "Ok" button. Defaults to `'Ok'`.
|
||||||
|
*/
|
||||||
|
okText?: React.ReactNode;
|
||||||
|
/**
|
||||||
|
* Denotes the purpose of the dialog. This will affect the color of the
|
||||||
|
* "Ok" button. Defaults to `undefined`.
|
||||||
|
*/
|
||||||
|
severity?: "error" | "info" | "success" | "warning";
|
||||||
|
/**
|
||||||
|
* The text to show in the "Cancel" button. Defaults to `'Cancel'`.
|
||||||
|
*/
|
||||||
|
cancelText?: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OpenConfirmDialog {
|
||||||
|
/**
|
||||||
|
* Open a confirmation dialog. Returns a promise that resolves to true if
|
||||||
|
* the user confirms, false if the user cancels.
|
||||||
|
*
|
||||||
|
* @param msg The message to show in the dialog.
|
||||||
|
* @param options Additional options for the dialog.
|
||||||
|
* @returns A promise that resolves to true if the user confirms, false if the user cancels.
|
||||||
|
*/
|
||||||
|
(msg: React.ReactNode, options?: ConfirmOptions): Promise<boolean>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DialogHook {
|
||||||
|
// alert: OpenAlertDialog;
|
||||||
|
confirm: OpenConfirmDialog;
|
||||||
|
// prompt: OpenPromptDialog;
|
||||||
|
open: OpenDialog;
|
||||||
|
close: CloseDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DialogStackEntry<P, R> {
|
||||||
|
key: string;
|
||||||
|
open: boolean;
|
||||||
|
promise: Promise<R>;
|
||||||
|
Component: DialogComponent<P, R>;
|
||||||
|
payload: P;
|
||||||
|
onClose: (result: R) => Promise<void>;
|
||||||
|
resolve: (result: R) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DialogProviderProps {
|
||||||
|
children?: React.ReactNode;
|
||||||
|
unmountAfter?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// form dialog
|
||||||
|
export interface FormDialogProps<T> extends MuiDialogProps {
|
||||||
|
title: string;
|
||||||
|
children: ReactNode;
|
||||||
|
onConfirm: (
|
||||||
|
e: BaseSyntheticEvent<object, any, any>,
|
||||||
|
) => Promise<T | undefined>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// form
|
||||||
|
export type ComponentFormProps<T> = {
|
||||||
|
data: T | null;
|
||||||
|
onError?: () => void;
|
||||||
|
onSuccess?: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface FormButtonsProps<T> {
|
||||||
|
onCancel?: () => void;
|
||||||
|
onConfirm?: (
|
||||||
|
e: BaseSyntheticEvent<object, any, any>,
|
||||||
|
) => Promise<T | undefined>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HTMLFormElementExtra<T> = {
|
||||||
|
submitAsync: (
|
||||||
|
e: BaseSyntheticEvent<object, any, any>,
|
||||||
|
) => Promise<T | undefined>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type HTMLFormElementExtension<T> =
|
||||||
|
| HTMLFormElement
|
||||||
|
| HTMLFormElementExtra<T>;
|
||||||
|
|
||||||
|
export type ComponentFormDialogProps<T> = DialogProps<T | null, boolean>;
|
Loading…
Reference in New Issue
Block a user