import type { AffineCloudWorkspace, LocalWorkspace, } from '@affine/env/workspace'; import { ExportIcon, PublishIcon, ShareIcon } from '@blocksuite/icons'; import type { Page } from '@blocksuite/store'; import { useBlockSuiteWorkspacePageIsPublic } from '@toeverything/hooks/use-block-suite-workspace-page-is-public'; import type { FC } from 'react'; import { useRef } from 'react'; import { useCallback, useState } from 'react'; import { Button } from '../../ui/button'; import { Menu } from '../../ui/menu/menu'; import { Export } from './export'; import { containerStyle, indicatorContainerStyle, tabStyle } from './index.css'; import { SharePage } from './share-page'; import { ShareWorkspace } from './share-workspace'; import { StyledIndicator, TabItem } from './styles'; type SharePanel = 'SharePage' | 'Export' | 'ShareWorkspace'; const MenuItems: Record> = { SharePage: SharePage, Export: Export, ShareWorkspace: ShareWorkspace, }; const tabIcons = { SharePage: , Export: , ShareWorkspace: , }; export type ShareMenuProps< Workspace extends AffineCloudWorkspace | LocalWorkspace = | AffineCloudWorkspace | LocalWorkspace, > = { workspace: Workspace; currentPage: Page; onEnableAffineCloud: (workspace: LocalWorkspace) => void; onOpenWorkspaceSettings: (workspace: Workspace) => void; togglePagePublic: (page: Page, isPublic: boolean) => Promise; toggleWorkspacePublish: ( workspace: Workspace, publish: boolean ) => Promise; }; function assertInstanceOf( obj: T, type: new (...args: any[]) => U ): asserts obj is U { if (!(obj instanceof type)) { throw new Error('Object is not instance of type'); } } export const ShareMenu: FC = props => { const [activeItem, setActiveItem] = useState('SharePage'); const [isPublic] = useBlockSuiteWorkspacePageIsPublic(props.currentPage); const [open, setOpen] = useState(false); const containerRef = useRef(null); const indicatorRef = useRef(null); const startTransaction = useCallback(() => { if (indicatorRef.current && containerRef.current) { const indicator = indicatorRef.current; const activeTabElement = containerRef.current.querySelector( `[data-tab-key="${activeItem}"]` ); assertInstanceOf(activeTabElement, HTMLElement); requestAnimationFrame(() => { indicator.style.left = `${activeTabElement.offsetLeft}px`; indicator.style.width = `${activeTabElement.offsetWidth}px`; }); } }, [activeItem]); const handleMenuChange = useCallback( (selectedItem: SharePanel) => { setActiveItem(selectedItem); startTransaction(); }, [setActiveItem, startTransaction] ); const ActiveComponent = MenuItems[activeItem]; interface ShareMenuProps { activeItem: SharePanel; onChangeTab: (selectedItem: SharePanel) => void; } const ShareMenu: FC = ({ activeItem, onChangeTab }) => { const handleButtonClick = (itemName: SharePanel) => { onChangeTab(itemName); setActiveItem(itemName); }; return (
{Object.keys(MenuItems).map(item => ( handleButtonClick(item as SharePanel)} > {tabIcons[item as SharePanel]} {isPublic ? (item === 'SharePage' ? 'SharedPage' : item) : item} ))}
); }; const Share = ( <>
{ indicatorRef.current = ref; startTransaction(); }} />
); return ( { setOpen(false); }} > ); };