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 { mode } = useTheme();
const { mode: editorMode } = useEditor();
const { shortcutsModalHandler, triggerContactModal } = useModal();
const { triggerShortcutsModal, triggerContactModal } = useModal();
const isEdgelessDark = mode === 'dark' && editorMode === 'edgeless';
return (
@@ -38,7 +38,7 @@ export const FAQ = () => {
isEdgelessDark={isEdgelessDark}
onClick={() => {
setShowContent(false);
triggerContactModal(true);
triggerContactModal();
}}
>
<ContactIcon />
@@ -50,7 +50,7 @@ export const FAQ = () => {
isEdgelessDark={isEdgelessDark}
onClick={() => {
setShowContent(false);
shortcutsModalHandler(true);
triggerShortcutsModal();
}}
>
<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 (
<StyledLoading>
<StyledLoadingItem />
<StyledLoadingItem />
<StyledLoadingItem />
<StyledLoadingItem />
</StyledLoading>
<StyledLoadingWrapper size={size}>
<StyledLoading>
<StyledLoadingItem size={size} />
<StyledLoadingItem size={size} />
<StyledLoadingItem size={size} />
<StyledLoadingItem size={size} />
</StyledLoading>
</StyledLoadingWrapper>
);
};
+19 -22
View File
@@ -1,14 +1,19 @@
import { styled } from '@/styles';
// 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`
position: relative;
left: 50%;
transform: rotateX(55deg) rotateZ(-45deg)
translate(calc(${loadingItemSize} * -2), 0);
margin-bottom: calc(3 * ${loadingItemSize});
position: absolute;
left: 25%;
top: 25%;
@keyframes slide {
0% {
transform: translate(var(--sx), var(--sy));
@@ -21,24 +26,14 @@ export const StyledLoading = styled.div`
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;
width: ${loadingItemSize};
height: ${loadingItemSize};
width: ${size}px;
height: ${size}px;
background: #9dacf9;
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%;
}
`;
}
);
@@ -47,7 +47,7 @@ const FavoriteList = ({ showList }: { showList: boolean }) => {
);
};
export const WorkSpaceSliderBar = () => {
const { triggerQuickSearchModal } = useModal();
const { triggerQuickSearchModal, triggerImportModal } = useModal();
const [show, setShow] = useState(false);
const [showSubFavorite, setShowSubFavorite] = useState(false);
const { createPage } = useEditor();
@@ -58,7 +58,7 @@ export const WorkSpaceSliderBar = () => {
<StyledSliderBar show={show}>
<StyledListItem
onClick={() => {
triggerQuickSearchModal(true);
triggerQuickSearchModal();
}}
>
Quick search
@@ -102,7 +102,13 @@ export const WorkSpaceSliderBar = () => {
</StyledListItem>
<FavoriteList showList={showSubFavorite} />
<StyledListItem>Import</StyledListItem>
<StyledListItem
onClick={() => {
triggerImportModal();
}}
>
Import
</StyledListItem>
<Link href={{ pathname: '/page-list/trash' }}>
<StyledListItem active={router.pathname === '/page-list/trash'}>
@@ -10,7 +10,7 @@ const StyledLoadingContainer = styled('div')(({ theme }) => {
color: '#6880FF',
h1: {
fontSize: '2em',
marginTop: '150px',
marginTop: '15px',
fontWeight: '600',
},
};
@@ -3,17 +3,27 @@ import type { PropsWithChildren } from 'react';
import ShortcutsModal from '@/components/shortcuts-modal';
import ContactModal from '@/components/contact-modal';
import QuickSearch from '@/components/quick-search';
import { ImportModal } from '@/components/import';
type ModalContextValue = {
shortcutsModalHandler: (visible: boolean) => void;
triggerContactModal: (visible: boolean) => void;
triggerQuickSearchModal: (visible: boolean) => void;
triggerShortcutsModal: () => void;
triggerContactModal: () => void;
triggerQuickSearchModal: () => void;
triggerImportModal: () => void;
};
type ModalContextProps = PropsWithChildren<{}>;
type ModalMap = {
contact: boolean;
shortcuts: boolean;
quickSearch: boolean;
import: boolean;
};
export const ModalContext = createContext<ModalContextValue>({
shortcutsModalHandler: () => {},
triggerShortcutsModal: () => {},
triggerContactModal: () => {},
triggerQuickSearchModal: () => {},
triggerImportModal: () => {},
});
export const useModal = () => useContext(ModalContext);
@@ -21,59 +31,78 @@ export const useModal = () => useContext(ModalContext);
export const ModalProvider = ({
children,
}: PropsWithChildren<ModalContextProps>) => {
const [openContactModal, setOpenContactModal] = useState(false);
const [openShortcutsModal, setOpenShortcutsModal] = useState(false);
const [openQuickSearchModal, setOpenQuickSearchModal] = useState(false);
const [modalMap, setModalMap] = useState<ModalMap>({
contact: false,
shortcuts: false,
quickSearch: false,
import: false,
});
const triggerHandler = (key: keyof ModalMap, visible?: boolean) => {
setModalMap({
...modalMap,
[key]: visible ?? !modalMap[key],
});
};
useEffect(() => {
const down = (e: KeyboardEvent) => {
if (e.key === 'k' && e.metaKey) {
const selection = window.getSelection();
if (selection?.toString()) {
setOpenQuickSearchModal(false);
triggerHandler('quickSearch', false);
return;
}
if (selection?.isCollapsed) {
setOpenQuickSearchModal(
openQuickSearchModal => !openQuickSearchModal
);
triggerHandler('quickSearch');
}
}
};
document.addEventListener('keydown', down);
return () => document.removeEventListener('keydown', down);
}, []);
return (
<ModalContext.Provider
value={{
shortcutsModalHandler: visible => {
setOpenShortcutsModal(visible);
triggerShortcutsModal: () => {
triggerHandler('shortcuts');
},
triggerContactModal: visible => {
setOpenContactModal(visible);
triggerContactModal: () => {
triggerHandler('contact');
},
triggerQuickSearchModal: visible => {
setOpenQuickSearchModal(visible);
triggerQuickSearchModal: () => {
triggerHandler('quickSearch');
},
triggerImportModal: () => {
triggerHandler('import');
},
}}
>
<ContactModal
open={openContactModal}
open={modalMap.contact}
onClose={() => {
setOpenContactModal(false);
triggerHandler('contact', false);
}}
></ContactModal>
<ShortcutsModal
open={openShortcutsModal}
open={modalMap.shortcuts}
onClose={() => {
setOpenShortcutsModal(false);
triggerHandler('shortcuts', false);
}}
></ShortcutsModal>
<QuickSearch
open={openQuickSearchModal}
open={modalMap.quickSearch}
onClose={() => {
setOpenQuickSearchModal(false);
triggerHandler('quickSearch', false);
}}
></QuickSearch>
<ImportModal
open={modalMap.import}
onClose={() => {
triggerHandler('import', false);
}}
></ImportModal>
{children}
</ModalContext.Provider>
);
+1 -45
View File
@@ -1,5 +1,4 @@
import { displayFlex, styled, AffineTheme } from '@/styles';
import { ConfirmProps } from '@/ui/confirm/confirm';
import { displayFlex, styled } from '@/styles';
import { ModalWrapper } from '@/ui/modal';
export const StyledModalWrapper = styled(ModalWrapper)(({ theme }) => {
@@ -7,8 +6,6 @@ export const StyledModalWrapper = styled(ModalWrapper)(({ theme }) => {
width: '460px',
height: '240px',
padding: '0 60px',
background: theme.colors.popoverBackground,
position: 'relative',
};
});
@@ -37,44 +34,3 @@ export const StyledButtonWrapper = styled.div(() => {
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,
},
};
}
};