feat: add import modal

This commit is contained in:
QiShaoXuan
2022-12-09 22:00:16 +08:00
parent 9ba50ee1c4
commit 0abd68d721
9 changed files with 188 additions and 116 deletions
+3 -14
View File
@@ -16,7 +16,7 @@ export const FAQ = () => {
const [showContent, setShowContent] = useState(false); const [showContent, setShowContent] = useState(false);
const { mode } = useTheme(); const { mode } = useTheme();
const { mode: editorMode } = useEditor(); const { mode: editorMode } = useEditor();
const { shortcutsModalHandler, triggerContactModal } = useModal(); const { triggerShortcutsModal, triggerContactModal } = useModal();
const isEdgelessDark = mode === 'dark' && editorMode === 'edgeless'; const isEdgelessDark = mode === 'dark' && editorMode === 'edgeless';
return ( return (
@@ -38,7 +38,7 @@ export const FAQ = () => {
isEdgelessDark={isEdgelessDark} isEdgelessDark={isEdgelessDark}
onClick={() => { onClick={() => {
setShowContent(false); setShowContent(false);
triggerContactModal(true); triggerContactModal();
}} }}
> >
<ContactIcon /> <ContactIcon />
@@ -50,7 +50,7 @@ export const FAQ = () => {
isEdgelessDark={isEdgelessDark} isEdgelessDark={isEdgelessDark}
onClick={() => { onClick={() => {
setShowContent(false); setShowContent(false);
shortcutsModalHandler(true); triggerShortcutsModal();
}} }}
> >
<KeyboardIcon /> <KeyboardIcon />
@@ -74,14 +74,3 @@ export const FAQ = () => {
</> </>
); );
}; };
const routesLIst: any = [
{
path: '/',
children: [
{
element: <HelpIcon />,
},
],
},
];
@@ -0,0 +1,59 @@
import { Modal, ModalWrapper, ModalCloseButton } from '@/ui/modal';
import { StyledButtonWrapper, StyledTitle } from './styles';
import { Button } from '@/ui/button';
import { Wrapper } from '@/ui/layout';
import { Loading } from '@/components/loading';
import { useEffect, useState } from 'react';
type ImportModalProps = {
open: boolean;
onClose: () => void;
};
export const ImportModal = ({ open, onClose }: ImportModalProps) => {
const [status, setStatus] = useState<'unImported' | 'importing'>(
'unImported'
);
useEffect(() => {
if (status === 'importing') {
setTimeout(() => {
setStatus('unImported');
}, 3000);
}
}, [status]);
return (
<Modal open={open} onClose={onClose}>
<ModalWrapper width={460} height={240}>
<ModalCloseButton onClick={onClose} />
<StyledTitle>Import</StyledTitle>
{status === 'unImported' && (
<StyledButtonWrapper>
<Button
onClick={() => {
setStatus('importing');
}}
>
Markdown
</Button>
<Button
onClick={() => {
setStatus('importing');
}}
>
HTML
</Button>
</StyledButtonWrapper>
)}
{status === 'importing' && (
<Wrapper justifyContent="center" style={{ marginTop: 22 }}>
<Loading size={25}></Loading>
</Wrapper>
)}
</ModalWrapper>
</Modal>
);
};
export default ImportModal;
@@ -0,0 +1,30 @@
import { styled } from '@/styles';
export const StyledTitle = styled.div(({ theme }) => {
return {
fontSize: theme.font.h6,
fontWeight: 600,
textAlign: 'center',
marginTop: '45px',
color: theme.colors.popoverColor,
};
});
export const StyledButtonWrapper = styled.div(() => {
return {
width: '280px',
margin: '24px auto 0',
button: {
display: 'block',
width: '100%',
':not(:last-child)': {
marginBottom: '16px',
},
},
};
});
export const StyledLoadingWrapper = styled.div(() => {
return {
}
})
+14 -8
View File
@@ -1,13 +1,19 @@
import { StyledLoading, StyledLoadingItem } from './styled'; import {
StyledLoadingWrapper,
StyledLoading,
StyledLoadingItem,
} from './styled';
export const Loading = () => { export const Loading = ({ size = 40 }: { size?: number }) => {
return ( return (
<StyledLoading> <StyledLoadingWrapper size={size}>
<StyledLoadingItem /> <StyledLoading>
<StyledLoadingItem /> <StyledLoadingItem size={size} />
<StyledLoadingItem /> <StyledLoadingItem size={size} />
<StyledLoadingItem /> <StyledLoadingItem size={size} />
</StyledLoading> <StyledLoadingItem size={size} />
</StyledLoading>
</StyledLoadingWrapper>
); );
}; };
+19 -22
View File
@@ -1,14 +1,19 @@
import { styled } from '@/styles'; import { styled } from '@/styles';
// Inspired by https://codepen.io/graphilla/pen/rNvBMYY // Inspired by https://codepen.io/graphilla/pen/rNvBMYY
const loadingItemSize = '40px'; export const StyledLoadingWrapper = styled.div<{ size?: number }>(
({ size = 40 }) => {
return {
width: size * 4,
height: size * 4,
position: 'relative',
};
}
);
export const StyledLoading = styled.div` export const StyledLoading = styled.div`
position: relative; position: absolute;
left: 50%; left: 25%;
transform: rotateX(55deg) rotateZ(-45deg) top: 25%;
translate(calc(${loadingItemSize} * -2), 0);
margin-bottom: calc(3 * ${loadingItemSize});
@keyframes slide { @keyframes slide {
0% { 0% {
transform: translate(var(--sx), var(--sy)); transform: translate(var(--sx), var(--sy));
@@ -21,24 +26,14 @@ export const StyledLoading = styled.div`
transform: translate(var(--ex), var(--ey)); transform: translate(var(--ex), var(--ey));
} }
} }
@keyframes load {
20% {
content: '.';
}
40% {
content: '..';
}
80%,
100% {
content: '...';
}
}
`; `;
export const StyledLoadingItem = styled.div` export const StyledLoadingItem = styled.div<{ size: number }>(
({ size = 40 }) => {
return `
position: absolute; position: absolute;
width: ${loadingItemSize}; width: ${size}px;
height: ${loadingItemSize}; height: ${size}px;
background: #9dacf9; background: #9dacf9;
animation: slide 0.9s cubic-bezier(0.65, 0.53, 0.59, 0.93) infinite; animation: slide 0.9s cubic-bezier(0.65, 0.53, 0.59, 0.93) infinite;
@@ -92,3 +87,5 @@ export const StyledLoadingItem = styled.div`
--ey: -50%; --ey: -50%;
} }
`; `;
}
);
@@ -47,7 +47,7 @@ const FavoriteList = ({ showList }: { showList: boolean }) => {
); );
}; };
export const WorkSpaceSliderBar = () => { export const WorkSpaceSliderBar = () => {
const { triggerQuickSearchModal } = useModal(); const { triggerQuickSearchModal, triggerImportModal } = useModal();
const [show, setShow] = useState(false); const [show, setShow] = useState(false);
const [showSubFavorite, setShowSubFavorite] = useState(false); const [showSubFavorite, setShowSubFavorite] = useState(false);
const { createPage } = useEditor(); const { createPage } = useEditor();
@@ -58,7 +58,7 @@ export const WorkSpaceSliderBar = () => {
<StyledSliderBar show={show}> <StyledSliderBar show={show}>
<StyledListItem <StyledListItem
onClick={() => { onClick={() => {
triggerQuickSearchModal(true); triggerQuickSearchModal();
}} }}
> >
Quick search Quick search
@@ -102,7 +102,13 @@ export const WorkSpaceSliderBar = () => {
</StyledListItem> </StyledListItem>
<FavoriteList showList={showSubFavorite} /> <FavoriteList showList={showSubFavorite} />
<StyledListItem>Import</StyledListItem> <StyledListItem
onClick={() => {
triggerImportModal();
}}
>
Import
</StyledListItem>
<Link href={{ pathname: '/page-list/trash' }}> <Link href={{ pathname: '/page-list/trash' }}>
<StyledListItem active={router.pathname === '/page-list/trash'}> <StyledListItem active={router.pathname === '/page-list/trash'}>
@@ -10,7 +10,7 @@ const StyledLoadingContainer = styled('div')(({ theme }) => {
color: '#6880FF', color: '#6880FF',
h1: { h1: {
fontSize: '2em', fontSize: '2em',
marginTop: '150px', marginTop: '15px',
fontWeight: '600', fontWeight: '600',
}, },
}; };
@@ -3,17 +3,27 @@ import type { PropsWithChildren } from 'react';
import ShortcutsModal from '@/components/shortcuts-modal'; import ShortcutsModal from '@/components/shortcuts-modal';
import ContactModal from '@/components/contact-modal'; import ContactModal from '@/components/contact-modal';
import QuickSearch from '@/components/quick-search'; import QuickSearch from '@/components/quick-search';
import { ImportModal } from '@/components/import';
type ModalContextValue = { type ModalContextValue = {
shortcutsModalHandler: (visible: boolean) => void; triggerShortcutsModal: () => void;
triggerContactModal: (visible: boolean) => void; triggerContactModal: () => void;
triggerQuickSearchModal: (visible: boolean) => void; triggerQuickSearchModal: () => void;
triggerImportModal: () => void;
}; };
type ModalContextProps = PropsWithChildren<{}>; type ModalContextProps = PropsWithChildren<{}>;
type ModalMap = {
contact: boolean;
shortcuts: boolean;
quickSearch: boolean;
import: boolean;
};
export const ModalContext = createContext<ModalContextValue>({ export const ModalContext = createContext<ModalContextValue>({
shortcutsModalHandler: () => {}, triggerShortcutsModal: () => {},
triggerContactModal: () => {}, triggerContactModal: () => {},
triggerQuickSearchModal: () => {}, triggerQuickSearchModal: () => {},
triggerImportModal: () => {},
}); });
export const useModal = () => useContext(ModalContext); export const useModal = () => useContext(ModalContext);
@@ -21,59 +31,78 @@ export const useModal = () => useContext(ModalContext);
export const ModalProvider = ({ export const ModalProvider = ({
children, children,
}: PropsWithChildren<ModalContextProps>) => { }: PropsWithChildren<ModalContextProps>) => {
const [openContactModal, setOpenContactModal] = useState(false); const [modalMap, setModalMap] = useState<ModalMap>({
const [openShortcutsModal, setOpenShortcutsModal] = useState(false); contact: false,
const [openQuickSearchModal, setOpenQuickSearchModal] = useState(false); shortcuts: false,
quickSearch: false,
import: false,
});
const triggerHandler = (key: keyof ModalMap, visible?: boolean) => {
setModalMap({
...modalMap,
[key]: visible ?? !modalMap[key],
});
};
useEffect(() => { useEffect(() => {
const down = (e: KeyboardEvent) => { const down = (e: KeyboardEvent) => {
if (e.key === 'k' && e.metaKey) { if (e.key === 'k' && e.metaKey) {
const selection = window.getSelection(); const selection = window.getSelection();
if (selection?.toString()) { if (selection?.toString()) {
setOpenQuickSearchModal(false); triggerHandler('quickSearch', false);
return; return;
} }
if (selection?.isCollapsed) { if (selection?.isCollapsed) {
setOpenQuickSearchModal( triggerHandler('quickSearch');
openQuickSearchModal => !openQuickSearchModal
);
} }
} }
}; };
document.addEventListener('keydown', down); document.addEventListener('keydown', down);
return () => document.removeEventListener('keydown', down); return () => document.removeEventListener('keydown', down);
}, []); }, []);
return ( return (
<ModalContext.Provider <ModalContext.Provider
value={{ value={{
shortcutsModalHandler: visible => { triggerShortcutsModal: () => {
setOpenShortcutsModal(visible); triggerHandler('shortcuts');
}, },
triggerContactModal: visible => { triggerContactModal: () => {
setOpenContactModal(visible); triggerHandler('contact');
}, },
triggerQuickSearchModal: visible => { triggerQuickSearchModal: () => {
setOpenQuickSearchModal(visible); triggerHandler('quickSearch');
},
triggerImportModal: () => {
triggerHandler('import');
}, },
}} }}
> >
<ContactModal <ContactModal
open={openContactModal} open={modalMap.contact}
onClose={() => { onClose={() => {
setOpenContactModal(false); triggerHandler('contact', false);
}} }}
></ContactModal> ></ContactModal>
<ShortcutsModal <ShortcutsModal
open={openShortcutsModal} open={modalMap.shortcuts}
onClose={() => { onClose={() => {
setOpenShortcutsModal(false); triggerHandler('shortcuts', false);
}} }}
></ShortcutsModal> ></ShortcutsModal>
<QuickSearch <QuickSearch
open={openQuickSearchModal} open={modalMap.quickSearch}
onClose={() => { onClose={() => {
setOpenQuickSearchModal(false); triggerHandler('quickSearch', false);
}} }}
></QuickSearch> ></QuickSearch>
<ImportModal
open={modalMap.import}
onClose={() => {
triggerHandler('import', false);
}}
></ImportModal>
{children} {children}
</ModalContext.Provider> </ModalContext.Provider>
); );
+1 -45
View File
@@ -1,5 +1,4 @@
import { displayFlex, styled, AffineTheme } from '@/styles'; import { displayFlex, styled } from '@/styles';
import { ConfirmProps } from '@/ui/confirm/confirm';
import { ModalWrapper } from '@/ui/modal'; import { ModalWrapper } from '@/ui/modal';
export const StyledModalWrapper = styled(ModalWrapper)(({ theme }) => { export const StyledModalWrapper = styled(ModalWrapper)(({ theme }) => {
@@ -7,8 +6,6 @@ export const StyledModalWrapper = styled(ModalWrapper)(({ theme }) => {
width: '460px', width: '460px',
height: '240px', height: '240px',
padding: '0 60px', padding: '0 60px',
background: theme.colors.popoverBackground,
position: 'relative',
}; };
}); });
@@ -37,44 +34,3 @@ export const StyledButtonWrapper = styled.div(() => {
marginTop: '32px', marginTop: '32px',
}; };
}); });
const getButtonColors = (
theme: AffineTheme,
confirmType: ConfirmProps['confirmType']
) => {
switch (confirmType) {
case 'primary':
return {
background: theme.colors.primaryColor,
color: '#fff',
borderColor: theme.colors.primaryColor,
};
case 'warning':
return {
background: theme.colors.warningBackground,
color: theme.colors.warningColor,
borderColor: theme.colors.warningBackground,
':hover': {
borderColor: theme.colors.warningColor,
},
};
case 'danger':
return {
background: theme.colors.errorBackground,
color: theme.colors.errorColor,
borderColor: theme.colors.errorBackground,
':hover': {
borderColor: theme.colors.errorColor,
},
};
default:
return {
color: theme.colors.popoverColor,
borderColor: theme.colors.borderColor,
':hover': {
borderColor: theme.colors.primaryColor,
color: theme.colors.primaryColor,
},
};
}
};