From 6ec259a0e71174651bae95d4628138bf6fd68742 Mon Sep 17 00:00:00 2001 From: kj_sh604 Date: Sun, 15 Mar 2026 16:19:35 -0400 Subject: refactor: packages/ --- .../OverwriteConfirm/OverwriteConfirm.scss | 126 +++++++++++++++++++++ .../OverwriteConfirm/OverwriteConfirm.tsx | 74 ++++++++++++ .../OverwriteConfirm/OverwriteConfirmActions.tsx | 85 ++++++++++++++ .../OverwriteConfirm/OverwriteConfirmState.ts | 45 ++++++++ 4 files changed, 330 insertions(+) create mode 100644 packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.scss create mode 100644 packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.tsx create mode 100644 packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmActions.tsx create mode 100644 packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.ts (limited to 'packages/excalidraw/components/OverwriteConfirm') diff --git a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.scss b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.scss new file mode 100644 index 0000000..4aad0cb --- /dev/null +++ b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.scss @@ -0,0 +1,126 @@ +@import "../../css/variables.module.scss"; + +.excalidraw { + .OverwriteConfirm { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.75rem; + isolation: isolate; + + h3 { + margin: 0; + + font-weight: 700; + font-size: 1.3125rem; + line-height: 130%; + align-self: flex-start; + + color: var(--text-primary-color); + } + + &__Description { + box-sizing: border-box; + + display: flex; + flex-direction: row; + align-items: center; + width: 100%; + gap: 1rem; + + @include isMobile { + flex-direction: column; + text-align: center; + } + + padding: 2.5rem; + + background: var(--color-danger-background); + border-radius: 0.5rem; + + font-family: "Assistant"; + font-style: normal; + font-weight: 400; + font-size: 1rem; + line-height: 150%; + + color: var(--color-danger-color); + + &__spacer { + flex-grow: 1; + } + + &__icon { + box-sizing: border-box; + display: flex; + align-items: center; + justify-content: center; + border-radius: 2.5rem; + background: var(--color-danger-icon-background); + width: 3.5rem; + height: 3.5rem; + + padding: 0.75rem; + + svg { + color: var(--color-danger-icon-color); + width: 1.5rem; + height: 1.5rem; + } + } + + &.OverwriteConfirm__Description--color-warning { + background: var(--color-warning-background); + color: var(--color-warning-color); + + .OverwriteConfirm__Description__icon { + background: var(--color-warning-icon-background); + flex: 0 0 auto; + + svg { + color: var(--color-warning-icon-color); + } + } + } + } + + &__Actions { + display: flex; + flex-direction: row; + align-items: stretch; + justify-items: stretch; + justify-content: center; + gap: 1.5rem; + + @include isMobile { + flex-direction: column; + } + + &__Action { + display: flex; + flex-direction: column; + align-items: center; + padding: 1.5rem; + gap: 0.75rem; + flex-basis: 50%; + flex-grow: 0; + + &__content { + height: 100%; + font-size: 0.875rem; + text-align: center; + } + + h4 { + font-weight: 700; + font-size: 1.125rem; + line-height: 130%; + + margin: 0; + + color: var(--text-primary-color); + } + } + } + } +} diff --git a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.tsx b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.tsx new file mode 100644 index 0000000..4bf8d67 --- /dev/null +++ b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.tsx @@ -0,0 +1,74 @@ +import React from "react"; + +import { useTunnels } from "../../context/tunnels"; +import { useAtom } from "../../editor-jotai"; +import { Dialog } from "../Dialog"; +import { withInternalFallback } from "../hoc/withInternalFallback"; +import { overwriteConfirmStateAtom } from "./OverwriteConfirmState"; + +import { FilledButton } from "../FilledButton"; +import { alertTriangleIcon } from "../icons"; +import { Actions, Action } from "./OverwriteConfirmActions"; +import "./OverwriteConfirm.scss"; + +export type OverwriteConfirmDialogProps = { + children: React.ReactNode; +}; + +const OverwriteConfirmDialog = Object.assign( + withInternalFallback( + "OverwriteConfirmDialog", + ({ children }: OverwriteConfirmDialogProps) => { + const { OverwriteConfirmDialogTunnel } = useTunnels(); + const [overwriteConfirmState, setState] = useAtom( + overwriteConfirmStateAtom, + ); + + if (!overwriteConfirmState.active) { + return null; + } + + const handleClose = () => { + overwriteConfirmState.onClose(); + setState((state) => ({ ...state, active: false })); + }; + + const handleConfirm = () => { + overwriteConfirmState.onConfirm(); + setState((state) => ({ ...state, active: false })); + }; + + return ( + + +
+

{overwriteConfirmState.title}

+
+
+ {alertTriangleIcon} +
+
{overwriteConfirmState.description}
+
+ +
+ {children} +
+
+
+ ); + }, + ), + { + Actions, + Action, + }, +); + +export { OverwriteConfirmDialog }; diff --git a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmActions.tsx b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmActions.tsx new file mode 100644 index 0000000..5da0a08 --- /dev/null +++ b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmActions.tsx @@ -0,0 +1,85 @@ +import React from "react"; +import { FilledButton } from "../FilledButton"; +import { useExcalidrawActionManager, useExcalidrawSetAppState } from "../App"; +import { actionSaveFileToDisk } from "../../actions"; +import { useI18n } from "../../i18n"; +import { actionChangeExportEmbedScene } from "../../actions/actionExport"; + +export type ActionProps = { + title: string; + children: React.ReactNode; + actionLabel: string; + onClick: () => void; +}; + +export const Action = ({ + title, + children, + actionLabel, + onClick, +}: ActionProps) => { + return ( +
+

{title}

+
+ {children} +
+ +
+ ); +}; + +export const ExportToImage = () => { + const { t } = useI18n(); + const actionManager = useExcalidrawActionManager(); + const setAppState = useExcalidrawSetAppState(); + + return ( + { + actionManager.executeAction(actionChangeExportEmbedScene, "ui", true); + setAppState({ openDialog: { name: "imageExport" } }); + }} + > + {t("overwriteConfirm.action.exportToImage.description")} + + ); +}; + +export const SaveToDisk = () => { + const { t } = useI18n(); + const actionManager = useExcalidrawActionManager(); + + return ( + { + actionManager.executeAction(actionSaveFileToDisk, "ui"); + }} + > + {t("overwriteConfirm.action.saveToDisk.description")} + + ); +}; + +const Actions = Object.assign( + ({ children }: { children: React.ReactNode }) => { + return
{children}
; + }, + { + ExportToImage, + SaveToDisk, + }, +); + +export { Actions }; diff --git a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.ts b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.ts new file mode 100644 index 0000000..04616aa --- /dev/null +++ b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.ts @@ -0,0 +1,45 @@ +import { atom, editorJotaiStore } from "../../editor-jotai"; +import type React from "react"; + +export type OverwriteConfirmState = + | { + active: true; + title: string; + description: React.ReactNode; + actionLabel: string; + color: "danger" | "warning"; + + onClose: () => void; + onConfirm: () => void; + onReject: () => void; + } + | { active: false }; + +export const overwriteConfirmStateAtom = atom({ + active: false, +}); + +export async function openConfirmModal({ + title, + description, + actionLabel, + color, +}: { + title: string; + description: React.ReactNode; + actionLabel: string; + color: "danger" | "warning"; +}) { + return new Promise((resolve) => { + editorJotaiStore.set(overwriteConfirmStateAtom, { + active: true, + onConfirm: () => resolve(true), + onClose: () => resolve(false), + onReject: () => resolve(false), + title, + description, + actionLabel, + color, + }); + }); +} -- cgit v1.2.3