Merge branch 'feat/dev' into feat/quick-search

This commit is contained in:
JimmFly
2022-12-09 13:34:30 +08:00
committed by GitHub
30 changed files with 561 additions and 220 deletions
+3 -3
View File
@@ -9,10 +9,10 @@
"lint": "next lint"
},
"dependencies": {
"@blocksuite/blocks": "0.3.0-alpha.5",
"@blocksuite/editor": "0.3.0-alpha.5",
"@blocksuite/blocks": "0.3.0-alpha.6",
"@blocksuite/editor": "0.3.0-alpha.6",
"@blocksuite/icons": "^1.0.5",
"@blocksuite/store": "0.3.0-alpha.5",
"@blocksuite/store": "0.3.0-alpha.6",
"@emotion/css": "^11.10.0",
"@emotion/react": "^11.10.4",
"@emotion/server": "^11.10.0",
@@ -1,4 +1,4 @@
import { Modal, ModalCloseButton } from '@/ui/modal';
import { Modal, ModalCloseButton, ModalWrapper } from '@/ui/modal';
import {
LogoIcon,
DocIcon,
@@ -11,7 +11,6 @@ import {
} from './icons';
import logo from './affine-text-logo.png';
import {
StyledModalWrapper,
StyledBigLink,
StyledSmallLink,
StyledSubTitle,
@@ -23,6 +22,7 @@ import {
StyledModalHeaderLeft,
StyledModalFooter,
} from './style';
import bg from '@/components/contact-modal/bg.png';
const linkList = [
{
@@ -74,7 +74,11 @@ type TransitionsModalProps = {
export const ContactModal = ({ open, onClose }: TransitionsModalProps) => {
return (
<Modal open={open} onClose={onClose}>
<StyledModalWrapper data-testid="contact-us-modal-content">
<ModalWrapper
width={860}
height={540}
style={{ backgroundImage: `url(${bg.src})` }}
>
<StyledModalHeader>
<StyledModalHeaderLeft>
<StyledLogo src={logo.src} alt="" />
@@ -83,8 +87,6 @@ export const ContactModal = ({ open, onClose }: TransitionsModalProps) => {
<ModalCloseButton
top={6}
right={6}
size={[30, 30]}
iconSize={[20, 20]}
onClick={() => {
onClose();
}}
@@ -134,7 +136,7 @@ export const ContactModal = ({ open, onClose }: TransitionsModalProps) => {
</p>
<p>Copyright &copy; 2022 Toeverything</p>
</StyledModalFooter>
</StyledModalWrapper>
</ModalWrapper>
</Modal>
);
};
@@ -1,21 +1,4 @@
import { absoluteCenter, displayFlex, styled } from '@/styles';
import bg from './bg.png';
export const StyledModalWrapper = styled('div')(({ theme }) => {
return {
width: '860px',
height: '540px',
backgroundColor: theme.colors.popoverBackground,
backgroundImage: `url(${bg.src})`,
borderRadius: '20px',
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
margin: 'auto',
};
});
export const StyledBigLink = styled('a')(({ theme }) => {
return {
+1 -1
View File
@@ -12,7 +12,7 @@ export const Editor = () => {
editorContainer.current?.appendChild(editor);
initDefaultContent(editor);
// initDefaultContent(editor);
}
}, [editor]);
@@ -1,12 +1,8 @@
import React, { useState } from 'react';
import Modal, { ModalCloseButton } from '@/ui/modal';
import Modal, { ModalCloseButton, ModalWrapper } from '@/ui/modal';
import getIsMobile from '@/utils/get-is-mobile';
import {
ModalWrapper,
StyledButton,
StyledContent,
StyledTitle,
} from './styles';
import { StyledButton, StyledContent, StyledTitle } from './styles';
import bg from './bg.png';
export const MobileModal = () => {
const [showModal, setShowModal] = useState(getIsMobile());
return (
@@ -16,7 +12,11 @@ export const MobileModal = () => {
setShowModal(false);
}}
>
<ModalWrapper>
<ModalWrapper
width={348}
height={388}
style={{ backgroundImage: `url(${bg.src})` }}
>
<ModalCloseButton
size={[30, 30]}
iconSize={[20, 20]}
@@ -1,16 +1,4 @@
import { displayFlex, styled } from '@/styles';
import bg from './bg.png';
export const ModalWrapper = styled.div(({ theme }) => {
return {
width: '348px',
height: '388px',
background: theme.colors.popoverBackground,
borderRadius: '28px',
position: 'relative',
backgroundImage: `url(${bg.src})`,
};
});
export const StyledTitle = styled.div(({ theme }) => {
return {
@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import Router from 'next/router';
import { useRouter } from 'next/router';
import {
StyledArrowButton,
StyledListItem,
@@ -8,11 +8,13 @@ import {
StyledSubListItem,
} from './style';
import { Arrow } from './icons';
import { useModal } from '@/providers/global-modal-provider';
import Link from 'next/link';
import { useEditor } from '@/providers/editor-provider';
export const WorkSpaceSliderBar = () => {
const { triggerQuickSearchModal } = useModal();
const [show, setShow] = useState(false);
const { createPage } = useEditor();
const router = useRouter();
return (
<>
<StyledSliderBar show={show}>
@@ -25,11 +27,19 @@ export const WorkSpaceSliderBar = () => {
</StyledListItem>
<StyledListItem
onClick={() => {
Router.push('/all-page');
router.push({
pathname: '/',
query: {
pageId: new Date().getTime().toString(),
},
});
}}
>
All pages
Back to Doc
</StyledListItem>
<Link href={{ pathname: '/all-page', query: { name: 'test' } }}>
<StyledListItem>All pages</StyledListItem>
</Link>
<StyledListItem>Favourites</StyledListItem>
<StyledSubListItem>
document 1, this is a paper icondocument 1
@@ -39,7 +49,13 @@ export const WorkSpaceSliderBar = () => {
<StyledListItem>Import</StyledListItem>
<StyledListItem>Bin</StyledListItem>
<StyledNewPageButton>New Page</StyledNewPageButton>
<StyledNewPageButton
onClick={() => {
createPage();
}}
>
New Page
</StyledNewPageButton>
</StyledSliderBar>
<StyledArrowButton
isShow={show}
+107 -24
View File
@@ -1,11 +1,18 @@
import React from 'react';
import { Header } from '@/components/header';
import { styled } from '@/styles';
import { displayFlex, styled, textEllipsis } from '@/styles';
import { Table, TableCell, TableHead, TableRow, TableBody } from '../ui/table';
import { useConfirm } from '@/providers/confirm-provider';
import { IconButton } from '@/ui/button';
import { MoreVertical_24pxIcon } from '@blocksuite/icons';
import { Menu, MenuItem } from '@/ui/menu';
import { PageMeta, useEditor } from '@/providers/editor-provider';
import { Wrapper } from '@/ui/layout';
import {
MiddleFavouritesIcon,
MiddleFavouritedStatus2Icon,
} from '@blocksuite/icons';
const StyledTableContainer = styled.div(() => {
return {
@@ -14,19 +21,87 @@ const StyledTableContainer = styled.div(() => {
overflowY: 'auto',
};
});
const StyledTitleWrapper = styled.div(({ theme }) => {
return {
...displayFlex('flex-start', 'center'),
'favorite-heart': {},
};
});
const StyledTitleContent = styled.div(({ theme }) => {
return {
maxWidth: '90%',
marginRight: '18px',
...textEllipsis(1),
};
});
const StyledFavoriteButton = styled.button<{ favorite: boolean }>(
({ theme, favorite }) => {
return {
width: '32px',
height: '32px',
justifyContent: 'center',
alignItems: 'center',
display: 'none',
color: favorite ? theme.colors.primaryColor : theme.colors.iconColor,
'&:hover': {
color: theme.colors.primaryColor,
},
};
}
);
const StyledTableRow = styled(TableRow)(({ theme }) => {
return {
'&:hover': {
'.favorite-button': {
display: 'flex',
},
},
};
});
const OperationMenu = () => {
return (
const OperationArea = ({ pageMeta }: { pageMeta: PageMeta }) => {
const { id, favorite } = pageMeta;
const { openPage, toggleFavoritePage, toggleDeletePage } = useEditor();
const OperationMenu = (
<>
<MenuItem>Add to favourites</MenuItem>
<MenuItem>Open in new tab</MenuItem>
<MenuItem>Delete</MenuItem>
<MenuItem
onClick={() => {
toggleFavoritePage(id);
}}
>
{favorite ? 'Remove' : 'Add'} to favourites
</MenuItem>
<MenuItem
onClick={() => {
openPage(id);
}}
>
Open in new tab
</MenuItem>
<MenuItem
onClick={() => {
toggleDeletePage(id);
}}
>
Delete
</MenuItem>
</>
);
return (
<Wrapper alignItems="center" justifyContent="center">
<Menu content={OperationMenu} placement="bottom-end" disablePortal={true}>
<IconButton hoverBackground="#E0E6FF">
<MoreVertical_24pxIcon />
</IconButton>
</Menu>
</Wrapper>
);
};
export const AllPage = () => {
const { confirm } = useConfirm();
const { pageList, toggleFavoritePage } = useEditor();
return (
<>
<Header />
@@ -53,27 +128,35 @@ export const AllPage = () => {
</TableRow>
</TableHead>
<TableBody>
{new Array(100).fill(0).map((_, index) => {
{pageList.map((pageMeta, index) => {
return (
<TableRow key={index}>
<TableCell ellipsis={true}>
This is a long, very long, extremely long, incredibly long,
exceedingly long, very long document title
</TableCell>
<TableCell ellipsis={true}>2022-11-02 18:30</TableCell>
<TableCell ellipsis={true}>2022-11-02 18:30</TableCell>
<StyledTableRow key={`${pageMeta.id}-${index}`}>
<TableCell>
<Menu
content={<OperationMenu />}
placement="bottom-end"
disablePortal={true}
>
<IconButton hoverBackground="#E0E6FF">
<MoreVertical_24pxIcon />
</IconButton>
</Menu>
<StyledTitleWrapper>
<StyledTitleContent>
{pageMeta.title || pageMeta.id}
</StyledTitleContent>
<StyledFavoriteButton
className="favorite-button"
favorite={pageMeta.favorite}
onClick={() => {
toggleFavoritePage(pageMeta.id);
}}
>
{pageMeta.favorite ? (
<MiddleFavouritedStatus2Icon />
) : (
<MiddleFavouritesIcon />
)}
</StyledFavoriteButton>
</StyledTitleWrapper>
</TableCell>
</TableRow>
<TableCell ellipsis={true}>{pageMeta.createDate}</TableCell>
<TableCell ellipsis={true}>{pageMeta.createDate}</TableCell>
<TableCell>
<OperationArea pageMeta={pageMeta} />
</TableCell>
</StyledTableRow>
);
})}
</TableBody>
-2
View File
@@ -6,8 +6,6 @@ import EdgelessToolbar from '@/components/edgeless-toolbar';
import MobileModal from '@/components/mobile-modal';
import Editor from '@/components/editor';
import '@/components/simple-counter';
const StyledEditorContainer = styled('div')(({ theme }) => {
return {
height: 'calc(100vh - 60px)',
@@ -1,25 +1,64 @@
import type { EditorContainer } from '@blocksuite/editor';
import { createContext, useContext, useEffect, useState } from 'react';
import { createContext, useContext, useEffect, useRef, useState } from 'react';
import type { PropsWithChildren } from 'react';
import dynamic from 'next/dynamic';
import Loading from './loading';
import { Page, Workspace } from '@blocksuite/store';
import { BlockSchema } from '@blocksuite/editor/dist/block-loader';
import { useRouter } from 'next/router';
export interface PageMeta {
id: string;
title: string;
favorite: boolean;
trash: boolean;
createDate: number;
trashDate: number | null;
}
// Blocksuite has to be imported dynamically since it has a lot of effects
const DynamicEditor = dynamic(() => import('./initial-editor'), {
ssr: false,
});
type EditorContextValue = {
editor: EditorContainer | null;
mode: EditorContainer['mode'];
setMode: (mode: EditorContainer['mode']) => void;
currentPage: Page | null;
editor: EditorContainer | null;
pageList: PageMeta[];
} & EditorHandlers;
type EditorHandlers = {
createPage: (pageId?: string) => void;
openPage: (
pageId: string,
query?: { [key: string]: string }
) => Promise<boolean>;
deletePage: (pageId: string) => void;
recyclePage: (pageId: string) => void;
toggleDeletePage: (pageId: string) => void;
favoritePage: (pageId: string) => void;
unFavoritePage: (pageId: string) => void;
toggleFavoritePage: (pageId: string) => void;
};
type EditorContextProps = PropsWithChildren<{}>;
export const EditorContext = createContext<EditorContextValue>({
editor: null,
mode: 'page',
setMode: () => {},
pageList: [],
currentPage: null,
editor: null,
createPage: () => {},
openPage: async () => {
return false;
},
deletePage: () => {},
recyclePage: () => {},
toggleDeletePage: () => {},
favoritePage: () => {},
unFavoritePage: () => {},
toggleFavoritePage: () => {},
});
export const useEditor = () => useContext(EditorContext);
@@ -27,6 +66,11 @@ export const useEditor = () => useContext(EditorContext);
export const EditorProvider = ({
children,
}: PropsWithChildren<EditorContextProps>) => {
const router = useRouter();
const blockSchemaRef = useRef<typeof BlockSchema | null>(null);
const [workspace, setWorkspace] = useState<Workspace | null>(null);
const [currentPage, setCurrentPage] = useState<Page | null>(null);
const [pageList, setPageList] = useState<PageMeta[]>([]);
const [editor, setEditor] = useState<EditorContainer | null>(null);
const [mode, setMode] = useState<EditorContainer['mode']>('page');
@@ -35,10 +79,77 @@ export const EditorProvider = ({
window.dispatchEvent(event);
}, [mode]);
useEffect(() => {
if (!workspace) {
return;
}
setPageList(workspace.meta.pages as PageMeta[]);
workspace.meta.pagesUpdated.on(res => {
setPageList(workspace.meta.pages as PageMeta[]);
});
return () => {
// TODO: Does it need to be removed?
workspace.meta.pagesUpdated.dispose();
};
}, [workspace]);
const editorHandler: EditorHandlers = {
createPage: (pageId = new Date().getTime().toString()) => {
blockSchemaRef.current &&
workspace?.createPage(pageId).register(blockSchemaRef.current);
},
openPage: (pageId, query = {}) => {
return router.push({
pathname: '/',
query: {
pageId,
...query,
},
});
},
deletePage: pageId => {
workspace?.setPage(pageId, { trash: true });
},
recyclePage: pageId => {
workspace?.setPage(pageId, { trash: false });
},
toggleDeletePage: pageId => {
const pageMeta = workspace?.meta.pages.find(p => p.id === pageId);
if (pageMeta) {
workspace?.setPage(pageId, { trash: !pageMeta.trash });
}
},
favoritePage: pageId => {
workspace?.setPage(pageId, { favorite: true });
},
unFavoritePage: pageId => {
workspace?.setPageMeta(pageId, { favorite: true });
},
toggleFavoritePage: pageId => {
const pageMeta = workspace?.meta.pages.find(p => p.id === pageId);
if (pageMeta) {
workspace?.setPageMeta(pageId, { favorite: !pageMeta.favorite });
}
},
};
return (
<EditorContext.Provider value={{ editor, mode, setMode }}>
<DynamicEditor setEditor={setEditor} />
{editor ? children : <Loading />}
<EditorContext.Provider
value={{ editor, currentPage, mode, setMode, pageList, ...editorHandler }}
>
<DynamicEditor
workspace={workspace}
currentPage={currentPage}
setBlockSchema={blockSchema => {
if (!blockSchemaRef.current) {
blockSchemaRef.current = blockSchema;
}
}}
setEditor={setEditor}
setWorkspace={setWorkspace}
setCurrentPage={setCurrentPage}
/>
{workspace && currentPage && editor ? children : <Loading />}
</EditorContext.Provider>
);
};
@@ -4,45 +4,103 @@ import type { EditorContainer } from '@blocksuite/editor';
import { BlockSchema, createEditor } from '@blocksuite/editor';
import { useEffect } from 'react';
import pkg from '../../../package.json';
import { createWebsocketDocProvider, Workspace } from '@blocksuite/store';
import {
createWebsocketDocProvider,
Workspace,
IndexedDBDocProvider,
Page,
} from '@blocksuite/store';
import { useRouter } from 'next/router';
const getEditorParams = () => {
const providers = [];
const params = new URLSearchParams(location.search);
if (params.get('syncModes') === 'websocket') {
const room = params.get('room') ?? 'AFFINE-pathfinder';
if (params.get('syncMode') === 'websocket') {
const WebsocketDocProvider = createWebsocketDocProvider(
'ws://127.0.0.1:3000/collaboration/AFFiNE'
);
providers.push(WebsocketDocProvider);
}
if (params.get('syncMode') === 'indexeddb') {
providers.push(IndexedDBDocProvider);
}
return {
room,
providers,
};
};
const InitialEditor = ({
workspace,
currentPage,
setBlockSchema,
setEditor,
setWorkspace,
setCurrentPage,
}: {
workspace: Workspace | null;
currentPage: Page | null;
setBlockSchema: (blockSchema: typeof BlockSchema) => void;
setEditor: (editor: EditorContainer) => void;
setWorkspace: (workspace: Workspace) => void;
setCurrentPage: (Page: Page) => void;
}) => {
setBlockSchema(BlockSchema);
const router = useRouter();
useEffect(() => {
const store = new Workspace({
const workspace = new Workspace({
...getEditorParams(),
});
const page = store.createPage('page0').register(BlockSchema);
const editor = createEditor(page);
//@ts-ignore
window.workspace = workspace;
const indexDBProvider = workspace.providers.find(
p => p instanceof IndexedDBDocProvider
);
if (indexDBProvider) {
(indexDBProvider as IndexedDBDocProvider)?.on('synced', () => {
setWorkspace(workspace);
});
} else {
setWorkspace(workspace);
}
}, [setWorkspace]);
setEditor(editor);
useEffect(() => {
if (!workspace) {
return;
}
return () => {
editor.remove();
};
}, [setEditor]);
// const initialPageId =
// workspace.meta.pages.find(p => p.id === (router.query.pageId as string))
// ?.id ??
// workspace.meta.pages[0]?.id ??
// 'page0';
const initialPageId =
workspace.meta.pages.find(p => p.id === (router.query.pageId as string))
?.id ?? 'page0';
console.log('initialPageId', initialPageId);
const initialPage = workspace
.createPage(initialPageId)
.register(BlockSchema);
setCurrentPage(initialPage);
}, [workspace, router.query.pageId, setCurrentPage]);
useEffect(() => {
if (!currentPage) {
return;
}
setEditor(createEditor(currentPage));
}, [currentPage, setEditor]);
useEffect(() => {
const version = pkg.dependencies['@blocksuite/editor'].substring(1);
console.log(`BlockSuite live demo ${version}`);
console.log(`BlockSuite version: ${version}`);
}, []);
return <div />;
+17
View File
@@ -17,6 +17,23 @@ export const displayFlex = (
alignContent,
};
};
export const displayInlineFlex = (
justifyContent: CSSProperties['justifyContent'] = 'unset',
alignItems: CSSProperties['alignContent'] = 'unset',
alignContent: CSSProperties['alignContent'] = 'unset'
): {
display: CSSProperties['display'];
justifyContent: CSSProperties['justifyContent'];
alignItems: CSSProperties['alignContent'];
alignContent: CSSProperties['alignContent'];
} => {
return {
display: 'inline-flex',
justifyContent,
alignItems,
alignContent,
};
};
export const absoluteCenter = ({
horizontal = false,
+2 -2
View File
@@ -1,4 +1,4 @@
import { absoluteCenter, displayFlex, styled } from '@/styles';
import { absoluteCenter, displayInlineFlex, styled } from '@/styles';
import { CSSProperties } from 'react';
export const StyledIconButton = styled.button<{
@@ -23,7 +23,7 @@ export const StyledIconButton = styled.button<{
width,
height,
color: theme.colors.iconColor,
...displayFlex('center', 'center'),
...displayInlineFlex('center', 'center'),
position: 'relative',
...(disabled ? { cursor: 'not-allowed', pointerEvents: 'none' } : {}),
transition: 'background .15s',
+2 -2
View File
@@ -1,13 +1,13 @@
import { displayFlex, styled, AffineTheme } from '@/styles';
import { ConfirmProps } from '@/ui/confirm/confirm';
import { ModalWrapper } from '@/ui/modal';
export const StyledModalWrapper = styled.div(({ theme }) => {
export const StyledModalWrapper = styled(ModalWrapper)(({ theme }) => {
return {
width: '460px',
height: '240px',
padding: '0 60px',
background: theme.colors.popoverBackground,
borderRadius: '28px',
position: 'relative',
};
});
+42
View File
@@ -0,0 +1,42 @@
import React, { CSSProperties } from 'react';
import { styled, textEllipsis } from '@/styles';
// This component should be just used to be contained the text content
export type ContentProps = {
width?: CSSProperties['width'];
maxWidth?: CSSProperties['maxWidth'];
color?: CSSProperties['color'];
fontSize?: CSSProperties['fontSize'];
fontWeight?: CSSProperties['fontWeight'];
lineHeight?: CSSProperties['lineHeight'];
ellipsis?: boolean;
lineNum?: number;
children: string;
};
export const Content = styled.div<ContentProps>(
({
theme,
color,
fontSize,
fontWeight,
lineHeight,
ellipsis,
lineNum,
width,
maxWidth,
}) => {
return {
width,
maxWidth,
display: 'inline-block',
color: color ?? theme.colors.textColor,
fontSize: fontSize ?? theme.font.base,
fontWeight: fontWeight ?? 400,
lineHeight: lineHeight ?? 1.5,
...(ellipsis ? textEllipsis(lineNum) : {}),
};
}
);
export default Content;
+2
View File
@@ -0,0 +1,2 @@
export * from './wrapper';
export * from './content';
+37
View File
@@ -0,0 +1,37 @@
import type { CSSProperties, HTMLAttributes, PropsWithChildren } from 'react';
import { styled } from '@/styles';
export type WrapperProps = {
display?: CSSProperties['display'];
flexDirection?: CSSProperties['flexDirection'];
justifyContent?: CSSProperties['justifyContent'];
alignItems?: CSSProperties['alignItems'];
flexWrap?: CSSProperties['flexWrap'];
flexShrink?: CSSProperties['flexShrink'];
flexGrow?: CSSProperties['flexGrow'];
};
// Sometimes we just want to wrap a component with a div to set flex or other styles, but we don't want to create a new component for it.
export const Wrapper = styled.div<WrapperProps>(
({
display = 'flex',
justifyContent = 'flex-start',
alignItems = 'center',
flexWrap = 'nowrap',
flexDirection = 'row',
flexShrink = '0',
flexGrow = '0',
}) => {
return {
display,
justifyContent,
alignItems,
flexWrap,
flexDirection,
flexShrink,
flexGrow,
};
}
);
export default Wrapper;
+1
View File
@@ -1,6 +1,7 @@
import Modal from './modal';
export * from './modal-close-button';
export * from './modal-wrapper';
export * from './modal';
export default Modal;
@@ -1,24 +1,28 @@
import { HTMLAttributes } from 'react';
import { StyledCloseButton } from './style';
import { CloseIcon } from '@blocksuite/icons';
import { IconButton, IconButtonProps } from '@/ui/button';
import { styled } from '@/styles';
export type ModalCloseButtonProps = {
top?: number;
right?: number;
triggerSize?: [number, number];
size?: [number, number];
iconSize?: [number, number];
} & HTMLAttributes<HTMLButtonElement>;
} & Omit<IconButtonProps, 'children'> &
HTMLAttributes<HTMLButtonElement>;
export const ModalCloseButton = ({
iconSize = [24, 24],
...props
}: ModalCloseButtonProps) => {
const [iconWidth, iconHeight] = iconSize;
const StyledIconButton = styled(IconButton)<
Pick<ModalCloseButtonProps, 'top' | 'right'>
>(({ top, right }) => {
return {
position: 'absolute',
top: top ?? 6,
right: right ?? 6,
};
});
export const ModalCloseButton = ({ ...props }: ModalCloseButtonProps) => {
return (
<StyledCloseButton {...props}>
<CloseIcon width={iconWidth} height={iconHeight} />
</StyledCloseButton>
<StyledIconButton {...props}>
<CloseIcon />
</StyledIconButton>
);
};
@@ -0,0 +1,17 @@
import React, { CSSProperties, HTMLAttributes, PropsWithChildren } from 'react';
import { styled } from '@/styles';
export const ModalWrapper = styled.div<{
width?: CSSProperties['width'];
height?: CSSProperties['height'];
}>(({ theme, width, height }) => {
return {
width,
height,
backgroundColor: theme.colors.popoverBackground,
borderRadius: '12px',
position: 'relative',
};
});
export default ModalWrapper;
+4 -6
View File
@@ -1,5 +1,5 @@
import Fade from '@mui/material/Fade';
import { StyledModal, StyledBackdrop } from './style';
import { StyledModal, StyledBackdrop } from './styles';
import { ModalUnstyledOwnProps } from '@mui/base/ModalUnstyled';
const Backdrop = ({
@@ -21,11 +21,9 @@ export type ModalProps = ModalUnstyledOwnProps;
export const Modal = (props: ModalProps) => {
const { components, open, children, ...otherProps } = props;
return (
<div>
<StyledModal {...otherProps} open={open} components={{ Backdrop }}>
<Fade in={open}>{children}</Fade>
</StyledModal>
</div>
<StyledModal {...otherProps} open={open} components={{ Backdrop }}>
<Fade in={open}>{children}</Fade>
</StyledModal>
);
};
-68
View File
@@ -1,68 +0,0 @@
import { absoluteCenter, displayFlex, fixedCenter, styled } from '@/styles';
import ModalUnstyled from '@mui/base/ModalUnstyled';
import { ModalCloseButtonProps } from '@/ui/modal/modal-close-button';
export const StyledBackdrop = styled.div<{ open?: boolean }>(({ open }) => {
return {
zIndex: '-1',
position: 'fixed',
right: '0',
bottom: '0',
top: '0',
left: '0',
backgroundColor: 'rgba(58, 76, 92, 0.2)',
};
});
export const StyledModal = styled(ModalUnstyled)(({ theme }) => {
return {
width: '100vw',
height: '100vh',
position: 'fixed',
left: '0',
top: '0',
zIndex: theme.zIndex.modal,
...displayFlex('center', 'center'),
'*': {
WebkitTapHighlightColor: 'transparent',
outline: 'none',
},
};
});
export const StyledCloseButton = styled.button<
Pick<ModalCloseButtonProps, 'size' | 'triggerSize' | 'top' | 'right'>
>(({ theme, triggerSize = [], size = [32, 32], top, right }) => {
const [triggerWidth, triggerHeight] = triggerSize;
const [width, height] = size;
return {
width: triggerWidth ?? width * 2,
height: triggerHeight ?? height * 2,
color: theme.colors.iconColor,
cursor: 'pointer',
...displayFlex('center', 'center'),
position: 'absolute',
top: top ?? 0,
right: right ?? 0,
// TODO: we need to add @emotion/babel-plugin
'::after': {
content: '""',
width,
height,
borderRadius: '6px',
...absoluteCenter({ horizontal: true, vertical: true }),
},
':hover': {
color: theme.colors.primaryColor,
'::after': {
background: theme.colors.hoverBackground,
},
},
svg: {
position: 'relative',
zIndex: 1,
},
};
});
+32
View File
@@ -0,0 +1,32 @@
import { absoluteCenter, displayFlex, fixedCenter, styled } from '@/styles';
import ModalUnstyled from '@mui/base/ModalUnstyled';
import { ModalCloseButtonProps } from '@/ui/modal/modal-close-button';
export const StyledBackdrop = styled.div<{ open?: boolean }>(({ open }) => {
return {
zIndex: '-1',
position: 'fixed',
right: '0',
bottom: '0',
top: '0',
left: '0',
backgroundColor: 'rgba(58, 76, 92, 0.2)',
};
});
export const StyledModal = styled(ModalUnstyled)(({ theme }) => {
return {
width: '100vw',
height: '100vh',
position: 'fixed',
left: '0',
top: '0',
zIndex: theme.zIndex.modal,
...displayFlex('center', 'center'),
'*': {
WebkitTapHighlightColor: 'transparent',
outline: 'none',
},
};
});
+3 -2
View File
@@ -26,11 +26,12 @@ export const StyledTableCell = styled.td<
const width = proportion ? `${proportion * 100}%` : 'auto';
return {
width,
height: '54px',
lineHeight: '54px',
height: '52px',
lineHeight: '52px',
padding: '0 30px',
boxSizing: 'border-box',
textAlign: align,
verticalAlign: 'middle',
...(ellipsis ? textEllipsis(1) : {}),
overflowWrap: 'break-word',
};
+6 -3
View File
@@ -1,8 +1,11 @@
import { PropsWithChildren } from 'react';
import { HTMLAttributes, PropsWithChildren } from 'react';
import { StyledTableBody } from '@/ui/table/styles';
export const TableBody = ({ children }: PropsWithChildren<{}>) => {
return <StyledTableBody>{children}</StyledTableBody>;
export const TableBody = ({
children,
...props
}: PropsWithChildren<HTMLAttributes<HTMLTableSectionElement>>) => {
return <StyledTableBody {...props}>{children}</StyledTableBody>;
};
export default TableBody;
+5 -2
View File
@@ -1,11 +1,14 @@
import { PropsWithChildren, useLayoutEffect } from 'react';
import { HTMLAttributes, PropsWithChildren } from 'react';
import { TableCellProps } from './interface';
import { StyledTableCell } from './styles';
export const TableCell = ({
children,
ellipsis,
...props
}: PropsWithChildren<TableCellProps>) => {
}: PropsWithChildren<
TableCellProps & HTMLAttributes<HTMLTableCellElement>
>) => {
return <StyledTableCell {...props}>{children}</StyledTableCell>;
};
+6 -3
View File
@@ -1,8 +1,11 @@
import { PropsWithChildren } from 'react';
import { HTMLAttributes, PropsWithChildren } from 'react';
import { StyledTableHead } from './styles';
export const TableHead = ({ children }: PropsWithChildren<{}>) => {
return <StyledTableHead>{children}</StyledTableHead>;
export const TableHead = ({
children,
...props
}: PropsWithChildren<HTMLAttributes<HTMLTableSectionElement>>) => {
return <StyledTableHead {...props}>{children}</StyledTableHead>;
};
export default TableHead;
+6 -3
View File
@@ -1,8 +1,11 @@
import { PropsWithChildren } from 'react';
import { HTMLAttributes, PropsWithChildren } from 'react';
import { StyledTableRow } from './styles';
export const TableRow = ({ children }: PropsWithChildren<{}>) => {
return <StyledTableRow>{children}</StyledTableRow>;
export const TableRow = ({
children,
...props
}: PropsWithChildren<HTMLAttributes<HTMLTableRowElement>>) => {
return <StyledTableRow {...props}>{children}</StyledTableRow>;
};
export default TableRow;
+10 -3
View File
@@ -1,4 +1,4 @@
import { PropsWithChildren, Children, ReactNode } from 'react';
import { PropsWithChildren, Children, ReactNode, HTMLAttributes } from 'react';
import { StyledTable } from './styles';
const childrenHasEllipsis = (children: ReactNode | ReactNode[]): boolean => {
@@ -14,10 +14,17 @@ const childrenHasEllipsis = (children: ReactNode | ReactNode[]): boolean => {
});
};
export const Table = ({ children }: PropsWithChildren<{}>) => {
export const Table = ({
children,
...props
}: PropsWithChildren<HTMLAttributes<HTMLTableElement>>) => {
const tableLayout = childrenHasEllipsis(children) ? 'fixed' : 'auto';
return <StyledTable tableLayout={tableLayout}>{children}</StyledTable>;
return (
<StyledTable tableLayout={tableLayout} {...props}>
{children}
</StyledTable>
);
};
export default Table;
+15 -15
View File
@@ -22,10 +22,10 @@ importers:
packages/app:
specifiers:
'@blocksuite/blocks': 0.3.0-alpha.5
'@blocksuite/editor': 0.3.0-alpha.5
'@blocksuite/blocks': 0.3.0-alpha.6
'@blocksuite/editor': 0.3.0-alpha.6
'@blocksuite/icons': ^1.0.5
'@blocksuite/store': 0.3.0-alpha.5
'@blocksuite/store': 0.3.0-alpha.6
'@emotion/css': ^11.10.0
'@emotion/react': ^11.10.4
'@emotion/server': ^11.10.0
@@ -53,10 +53,10 @@ importers:
react-dom: 18.2.0
typescript: 4.8.3
dependencies:
'@blocksuite/blocks': 0.3.0-alpha.5
'@blocksuite/editor': 0.3.0-alpha.5
'@blocksuite/blocks': 0.3.0-alpha.6
'@blocksuite/editor': 0.3.0-alpha.6
'@blocksuite/icons': 1.0.5_w5j4k42lgipnm43s3brx6h3c34
'@blocksuite/store': 0.3.0-alpha.5
'@blocksuite/store': 0.3.0-alpha.6
'@emotion/css': 11.10.0
'@emotion/react': 11.10.4_w5j4k42lgipnm43s3brx6h3c34
'@emotion/server': 11.10.0_@emotion+css@11.10.0
@@ -172,10 +172,10 @@ packages:
to-fast-properties: 2.0.0
dev: false
/@blocksuite/blocks/0.3.0-alpha.5:
resolution: {integrity: sha512-jZy1mXaC2s/b227Yf/wNPRwMAFGa1USH/Q0OJ6KAcmY8YQdeGXKAoNTz4p7K5rMJgtE1t17/Mzwo5+exCRbIkg==}
/@blocksuite/blocks/0.3.0-alpha.6:
resolution: {integrity: sha512-pa8wP0hRIDlufae+ABAQFLW8TNOGsfh8AqyTKF/+LVYFCGr+9tlW55X3OlWtU51vFxawst1Wd3FnjCAW6XiaKQ==}
dependencies:
'@blocksuite/store': 0.3.0-alpha.5
'@blocksuite/store': 0.3.0-alpha.6
hotkeys-js: 3.10.0
lit: 2.4.0
quill: 1.3.7
@@ -186,11 +186,11 @@ packages:
- utf-8-validate
dev: false
/@blocksuite/editor/0.3.0-alpha.5:
resolution: {integrity: sha512-H7RZkG3ptyzLs0+6YgwQnp6H8hByfWRSjDi388ZIz3/exgliyBz2QkQwY4Tj2nlAYSq/U5/8hdDMjw4a092Ivw==}
/@blocksuite/editor/0.3.0-alpha.6:
resolution: {integrity: sha512-2wFkOlCKqC4BrfCIzuxjUyVnE/mmGOyUnqVTQNmHrToDS81RLIq0r+lj1IrzLv+LZQCfTyhoAlJyaxUNrUw3sw==}
dependencies:
'@blocksuite/blocks': 0.3.0-alpha.5
'@blocksuite/store': 0.3.0-alpha.5
'@blocksuite/blocks': 0.3.0-alpha.6
'@blocksuite/store': 0.3.0-alpha.6
lit: 2.4.0
marked: 4.1.1
turndown: 7.1.1
@@ -210,8 +210,8 @@ packages:
react: 18.2.0
dev: false
/@blocksuite/store/0.3.0-alpha.5:
resolution: {integrity: sha512-pkbSrwB7KTfW56iH4ZFPkrS6shIU8QpmJlZmKVY95Gp5QSISW2ffKUsFrrHVHT+GoOV7+RPZQrphUnC57grPNg==}
/@blocksuite/store/0.3.0-alpha.6:
resolution: {integrity: sha512-rI7cUVSqoMh1bsNLwL8MAgyaUq0Ix+SRBqweYwVjeDoqFIbHjnRSwkVw48K/FgxN6ekN96HLSf3Sj/HK1ivPpw==}
dependencies:
buffer: 6.0.3
flexsearch: 0.7.21