diff --git a/src/app/storybook/common-dialog/page.tsx b/src/app/storybook/common-dialog/page.tsx new file mode 100644 index 00000000..d5935a72 --- /dev/null +++ b/src/app/storybook/common-dialog/page.tsx @@ -0,0 +1,70 @@ +"use client"; +import { + CommonDialogProvider, + useCommonDialog, +} from "@/components/common-dialog"; +import { Button } from "@/components/ui/button"; +import { TrashIcon } from "lucide-react"; + +function StorybookBody() { + const { showDialog } = useCommonDialog(); + + return ( +
+ + + +
+ ); +} + +export default function CommonDialogStorybook() { + return ( + + + + ); +} diff --git a/src/components/common-dialog/index.tsx b/src/components/common-dialog/index.tsx new file mode 100644 index 00000000..403a8be8 --- /dev/null +++ b/src/components/common-dialog/index.tsx @@ -0,0 +1,145 @@ +"use client"; +import { noop } from "lodash"; +import { + PropsWithChildren, + ReactElement, + createContext, + useCallback, + useContext, + useState, +} from "react"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, +} from "../ui/dialog"; +import { Button } from "../ui/button"; +import { Icon } from "@phosphor-icons/react"; +import { Loader } from "lucide-react"; +import CodePreview from "../gui/code-preview"; + +interface ShowDialogProps { + title: string; + content: string | ReactElement; + destructive?: boolean; + previewCode?: string; + actions?: { + text: string; + icon?: Icon; + onClick: () => Promise; + onComplete?: () => void; + }[]; +} + +interface CommonDialogContextProps { + showDialog(option: ShowDialogProps): void; +} + +const CommonDialogContext = createContext({ + showDialog: noop, +}); + +export function CommonDialogProvider({ children }: PropsWithChildren) { + const [dialogOption, setDialogOption] = useState( + null + ); + + const [errorMessage, setErrorMessage] = useState(""); + const [loading, setLoading] = useState(false); + + const hideDialog = useCallback(() => { + setErrorMessage(""); + setDialogOption(null); + }, []); + + return ( + + {children} + {dialogOption && ( + { + if (!openState) { + hideDialog(); + } + }} + > + + + {dialogOption.title} + + + {errorMessage && ( +
+

{errorMessage}

+
+ )} + +
{dialogOption.content}
+ {dialogOption.previewCode && ( + + )} +
+ + {dialogOption.actions?.map((action) => ( + + ))} + + + +
+
+ )} +
+ ); +} + +export function useCommonDialog() { + return useContext(CommonDialogContext); +} diff --git a/src/components/gui/studio.tsx b/src/components/gui/studio.tsx index 7cb6d836..93c4f64e 100644 --- a/src/components/gui/studio.tsx +++ b/src/components/gui/studio.tsx @@ -9,6 +9,7 @@ import { StudioContextMenuItem } from "@/messages/open-context-menu"; import { CollaborationBaseDriver } from "@/drivers/collaboration-driver-base"; import { SavedDocDriver } from "@/drivers/saved-doc/saved-doc-driver"; import { FullEditorProvider } from "./providers/full-editor-provider"; +import { CommonDialogProvider } from "../common-dialog"; export interface StudioExtension { contextMenu?: (state: OptimizeTableState) => StudioContextMenuItem[]; @@ -75,9 +76,11 @@ export function Studio({ onBack={onBack} sideBarFooterComponent={sideBarFooterComponent} > - - - + + + + + );