From a4534542504f8f752dea475e71f4e0480a5785a8 Mon Sep 17 00:00:00 2001 From: QiShaoXuan Date: Wed, 21 Dec 2022 15:31:35 +0800 Subject: [PATCH] feat: support header right slot --- .../src/components/header/editor-header.tsx | 14 +- .../header-right-items/editor-option-menu.tsx | 108 +++++++++++ .../sync-user.tsx} | 4 +- .../theme-mode-switch/icons.tsx | 0 .../theme-mode-switch/index.tsx | 0 .../theme-mode-switch/style.ts | 0 .../header-right-items/trash-button-group.tsx | 53 ++++++ packages/app/src/components/header/header.tsx | 180 +++--------------- 8 files changed, 196 insertions(+), 163 deletions(-) create mode 100644 packages/app/src/components/header/header-right-items/editor-option-menu.tsx rename packages/app/src/components/header/{sync-icon.tsx => header-right-items/sync-user.tsx} (90%) rename packages/app/src/components/{ => header/header-right-items}/theme-mode-switch/icons.tsx (100%) rename packages/app/src/components/{ => header/header-right-items}/theme-mode-switch/index.tsx (100%) rename packages/app/src/components/{ => header/header-right-items}/theme-mode-switch/style.ts (100%) create mode 100644 packages/app/src/components/header/header-right-items/trash-button-group.tsx diff --git a/packages/app/src/components/header/editor-header.tsx b/packages/app/src/components/header/editor-header.tsx index 14ee04c21f..c1b52ec464 100644 --- a/packages/app/src/components/header/editor-header.tsx +++ b/packages/app/src/components/header/editor-header.tsx @@ -17,7 +17,7 @@ export const EditorHeader = () => { const [title, setTitle] = useState(''); const [isHover, setIsHover] = useState(false); const { editor } = useAppState(); - const pageMeta = useCurrentPageMeta(); + const { trash: isTrash = false } = useCurrentPageMeta() || {}; const onPropsUpdated = usePropsUpdated(); useEffect(() => { @@ -34,16 +34,22 @@ export const EditorHeader = () => { }, [editor]); return ( -
+
{title && ( { - if (pageMeta?.trash) return; + if (isTrash) return; setIsHover(true); }} onMouseLeave={() => { - if (pageMeta?.trash) return; + if (isTrash) return; setIsHover(false); }} diff --git a/packages/app/src/components/header/header-right-items/editor-option-menu.tsx b/packages/app/src/components/header/header-right-items/editor-option-menu.tsx new file mode 100644 index 0000000000..462367e916 --- /dev/null +++ b/packages/app/src/components/header/header-right-items/editor-option-menu.tsx @@ -0,0 +1,108 @@ +import { Menu, MenuItem } from '@/ui/menu'; +import { IconButton } from '@/ui/button'; +import { + EdgelessIcon, + ExportIcon, + ExportToHtmlIcon, + ExportToMarkdownIcon, + FavouritedIcon, + FavouritesIcon, + MoreVerticalIcon, + PaperIcon, + TrashIcon, +} from '@blocksuite/icons'; +import { useAppState } from '@/providers/app-state-provider'; +import { usePageHelper } from '@/hooks/use-page-helper'; +import { useConfirm } from '@/providers/confirm-provider'; +import useCurrentPageMeta from '@/hooks/use-current-page-meta'; +import { toast } from '@/ui/toast'; + +const PopoverContent = () => { + const { editor } = useAppState(); + const { toggleFavoritePage, toggleDeletePage } = usePageHelper(); + const { changePageMode } = usePageHelper(); + const { confirm } = useConfirm(); + const { + mode = 'page', + id = '', + favorite = false, + title = '', + } = useCurrentPageMeta() || {}; + + return ( + <> + { + toggleFavoritePage(id); + toast(!favorite ? 'Removed to Favourites' : 'Added to Favourites'); + }} + icon={favorite ? : } + > + {favorite ? 'Remove' : 'Add'} to favourites + + : } + onClick={() => { + changePageMode(id, mode === 'page' ? 'edgeless' : 'page'); + }} + > + Convert to {mode === 'page' ? 'Edgeless' : 'Page'} + + + { + editor && editor.contentParser.onExportHtml(); + }} + icon={} + > + Export to HTML + + { + editor && editor.contentParser.onExportMarkdown(); + }} + icon={} + > + Export to Markdown + + + } + > + } isDir={true}> + Export + + + { + confirm({ + title: 'Delete page?', + content: `${title || 'Untitled'} will be moved to Trash`, + confirmText: 'Delete', + confirmType: 'danger', + }).then(confirm => { + confirm && toggleDeletePage(id); + toast('Moved to Trash'); + }); + }} + icon={} + > + Delete + + + ); +}; + +export const EditorOptionMenu = () => { + return ( + } placement="bottom-end"> + + + + + ); +}; + +export default EditorOptionMenu; diff --git a/packages/app/src/components/header/sync-icon.tsx b/packages/app/src/components/header/header-right-items/sync-user.tsx similarity index 90% rename from packages/app/src/components/header/sync-icon.tsx rename to packages/app/src/components/header/header-right-items/sync-user.tsx index 3d791c0056..87d7b2f603 100644 --- a/packages/app/src/components/header/sync-icon.tsx +++ b/packages/app/src/components/header/header-right-items/sync-user.tsx @@ -3,7 +3,7 @@ import { useModal } from '@/providers/global-modal-provider'; import { useAppState } from '@/providers/app-state-provider/context'; import { IconButton } from '@/ui/button'; -export const SyncIcon = () => { +export const SyncUser = () => { const { triggerLoginModal } = useModal(); const appState = useAppState(); @@ -17,3 +17,5 @@ export const SyncIcon = () => { ); }; + +export default SyncUser; diff --git a/packages/app/src/components/theme-mode-switch/icons.tsx b/packages/app/src/components/header/header-right-items/theme-mode-switch/icons.tsx similarity index 100% rename from packages/app/src/components/theme-mode-switch/icons.tsx rename to packages/app/src/components/header/header-right-items/theme-mode-switch/icons.tsx diff --git a/packages/app/src/components/theme-mode-switch/index.tsx b/packages/app/src/components/header/header-right-items/theme-mode-switch/index.tsx similarity index 100% rename from packages/app/src/components/theme-mode-switch/index.tsx rename to packages/app/src/components/header/header-right-items/theme-mode-switch/index.tsx diff --git a/packages/app/src/components/theme-mode-switch/style.ts b/packages/app/src/components/header/header-right-items/theme-mode-switch/style.ts similarity index 100% rename from packages/app/src/components/theme-mode-switch/style.ts rename to packages/app/src/components/header/header-right-items/theme-mode-switch/style.ts diff --git a/packages/app/src/components/header/header-right-items/trash-button-group.tsx b/packages/app/src/components/header/header-right-items/trash-button-group.tsx new file mode 100644 index 0000000000..02345e9680 --- /dev/null +++ b/packages/app/src/components/header/header-right-items/trash-button-group.tsx @@ -0,0 +1,53 @@ +import { Button } from '@/ui/button'; +import { usePageHelper } from '@/hooks/use-page-helper'; +import { useAppState } from '@/providers/app-state-provider'; +import { useConfirm } from '@/providers/confirm-provider'; +import { useRouter } from 'next/router'; +import useCurrentPageMeta from '@/hooks/use-current-page-meta'; + +export const TrashButtonGroup = () => { + const { permanentlyDeletePage } = usePageHelper(); + const { currentWorkspaceId } = useAppState(); + const { toggleDeletePage } = usePageHelper(); + const { confirm } = useConfirm(); + const router = useRouter(); + const { id = '' } = useCurrentPageMeta() || {}; + + return ( + <> + + + + ); +}; + +export default TrashButtonGroup; diff --git a/packages/app/src/components/header/header.tsx b/packages/app/src/components/header/header.tsx index 40103af3d3..82f0558ae9 100644 --- a/packages/app/src/components/header/header.tsx +++ b/packages/app/src/components/header/header.tsx @@ -1,4 +1,4 @@ -import React, { PropsWithChildren, useState } from 'react'; +import React, { PropsWithChildren, ReactNode, useState } from 'react'; import { StyledHeader, StyledHeaderRightSide, @@ -6,106 +6,12 @@ import { StyledBrowserWarning, StyledCloseButton, } from './styles'; -import { - ExportIcon, - EdgelessIcon, - PaperIcon, - ExportToHtmlIcon, - ExportToMarkdownIcon, - MoreVerticalIcon, - FavouritesIcon, - FavouritedIcon, - TrashIcon, -} from '@blocksuite/icons'; -import { useAppState } from '@/providers/app-state-provider/context'; -import ThemeModeSwitch from '@/components/theme-mode-switch'; -import { IconButton, Button } from '@/ui/button'; import CloseIcon from '@mui/icons-material/Close'; import { getWarningMessage, shouldShowWarning } from './utils'; -import { Menu, MenuItem } from '@/ui/menu'; -import { useRouter } from 'next/router'; -import { useConfirm } from '@/providers/confirm-provider'; -import { SyncIcon } from './sync-icon'; -import { toast } from '@/ui/toast'; -import useCurrentPageMeta from '@/hooks/use-current-page-meta'; -import { usePageHelper } from '@/hooks/use-page-helper'; -const PopoverContent = () => { - const { editor } = useAppState(); - const { toggleFavoritePage, toggleDeletePage } = usePageHelper(); - const { changePageMode } = usePageHelper(); - const { confirm } = useConfirm(); - const { - mode = 'page', - id = '', - favorite = false, - title = '', - } = useCurrentPageMeta() || {}; - - return ( - <> - { - toggleFavoritePage(id); - toast(!favorite ? 'Removed to Favourites' : 'Added to Favourites'); - }} - icon={favorite ? : } - > - {favorite ? 'Remove' : 'Add'} to favourites - - : } - onClick={() => { - changePageMode(id, mode === 'page' ? 'edgeless' : 'page'); - }} - > - Convert to {mode === 'page' ? 'Edgeless' : 'Page'} - - - { - editor && editor.contentParser.onExportHtml(); - }} - icon={} - > - Export to HTML - - { - editor && editor.contentParser.onExportMarkdown(); - }} - icon={} - > - Export to Markdown - - - } - > - } isDir={true}> - Export - - - { - confirm({ - title: 'Delete page?', - content: `${title || 'Untitled'} will be moved to Trash`, - confirmText: 'Delete', - confirmType: 'danger', - }).then(confirm => { - confirm && toggleDeletePage(id); - toast('Moved to Trash'); - }); - }} - icon={} - > - Delete - - - ); -}; +import EditorOptionMenu from './header-right-items/editor-option-menu'; +import TrashButtonGroup from './header-right-items/trash-button-group'; +import ThemeModeSwitch from './header-right-items/theme-mode-switch'; +import SyncUser from './header-right-items/sync-user'; const BrowserWarning = ({ show, @@ -124,67 +30,23 @@ const BrowserWarning = ({ ); }; -const HeaderRight = () => { - const { permanentlyDeletePage } = usePageHelper(); - const { currentWorkspaceId } = useAppState(); - const { toggleDeletePage } = usePageHelper(); - const { confirm } = useConfirm(); - const router = useRouter(); - const currentPageMeta = useCurrentPageMeta(); - const isTrash = !!currentPageMeta?.trash; +type HeaderRightItemNames = + | 'editorOptionMenu' + | 'trashButtonGroup' + | 'themeModeSwitch' + | 'syncUser'; - if (isTrash) { - const { id } = currentPageMeta; - return ( - <> - - - - ); - } - return ( - <> - - - } placement="bottom-end"> - - - - - - ); +const HeaderRightItems: Record = { + editorOptionMenu: , + trashButtonGroup: , + themeModeSwitch: , + syncUser: , }; -export const Header = ({ children }: PropsWithChildren<{}>) => { +export const Header = ({ + rightItems = ['syncUser'], + children, +}: PropsWithChildren<{ rightItems?: HeaderRightItemNames[] }>) => { const [showWarning, setShowWarning] = useState(shouldShowWarning()); return ( @@ -197,7 +59,9 @@ export const Header = ({ children }: PropsWithChildren<{}>) => { {children} - + {rightItems.map(itemName => { + return HeaderRightItems[itemName]; + })}