mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 21:27:20 +00:00
refactor(core): remove all MUI related components and utilities (#4941)
This commit is contained in:
@@ -20,12 +20,6 @@ export const productionCacheGroups = {
|
||||
priority: Number.MAX_SAFE_INTEGER,
|
||||
chunks: 'async' as const,
|
||||
},
|
||||
mui: {
|
||||
name: `npm-mui`,
|
||||
test: testPackageName(/[\\/]node_modules[\\/](mui|@mui)[\\/]/),
|
||||
priority: 200,
|
||||
enforce: true,
|
||||
},
|
||||
blocksuite: {
|
||||
name: `npm-blocksuite`,
|
||||
test: testPackageName(/[\\/]node_modules[\\/](@blocksuite)[\\/]/),
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
"@emotion/server": "^11.11.0",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@marsidev/react-turnstile": "^0.3.1",
|
||||
"@mui/material": "^5.14.14",
|
||||
"@radix-ui/react-collapsible": "^1.0.3",
|
||||
"@radix-ui/react-dialog": "^1.0.4",
|
||||
"@radix-ui/react-scroll-area": "^1.0.5",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Skeleton } from '@affine/component';
|
||||
import { Pagination } from '@affine/component/member-components';
|
||||
import {
|
||||
SettingHeader,
|
||||
@@ -19,7 +20,6 @@ import { Trans } from '@affine/i18n';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useMutation, useQuery } from '@affine/workspace/affine/gql';
|
||||
import { ArrowRightSmallIcon } from '@blocksuite/icons';
|
||||
import { Skeleton } from '@mui/material';
|
||||
import { Button, IconButton } from '@toeverything/components/button';
|
||||
import { Loading } from '@toeverything/components/loading';
|
||||
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Skeleton } from '@mui/material';
|
||||
import { Skeleton } from '@affine/component';
|
||||
|
||||
import { PlanLayout } from './layout';
|
||||
import * as styles from './skeleton.css';
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { MenuItem, PureMenu } from '@affine/component';
|
||||
import { MuiClickAwayListener } from '@affine/component';
|
||||
import type { SerializedBlock } from '@blocksuite/blocks';
|
||||
import type { BaseBlockModel } from '@blocksuite/store';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
import type { VEditor } from '@blocksuite/virgo';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Menu, MenuItem } from '@toeverything/components/menu';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
|
||||
type ShortcutMap = {
|
||||
[key: string]: (e: KeyboardEvent, page: Page) => void;
|
||||
@@ -121,60 +121,6 @@ export type BookmarkProps = {
|
||||
|
||||
export const Bookmark = ({ page }: BookmarkProps) => {
|
||||
const [anchor, setAnchor] = useState<Range | null>(null);
|
||||
const [selectedOption, setSelectedOption] = useState<string>(
|
||||
menuOptions[0].id
|
||||
);
|
||||
const shortcutMap = useMemo<ShortcutMap>(
|
||||
() => ({
|
||||
ArrowUp: () => {
|
||||
const curIndex = menuOptions.findIndex(
|
||||
({ id }) => id === selectedOption
|
||||
);
|
||||
if (menuOptions[curIndex - 1]) {
|
||||
setSelectedOption(menuOptions[curIndex - 1].id);
|
||||
} else if (curIndex === -1) {
|
||||
setSelectedOption(menuOptions[0].id);
|
||||
} else {
|
||||
setSelectedOption(menuOptions[menuOptions.length - 1].id);
|
||||
}
|
||||
},
|
||||
ArrowDown: () => {
|
||||
const curIndex = menuOptions.findIndex(
|
||||
({ id }) => id === selectedOption
|
||||
);
|
||||
if (curIndex !== -1 && menuOptions[curIndex + 1]) {
|
||||
setSelectedOption(menuOptions[curIndex + 1].id);
|
||||
} else {
|
||||
setSelectedOption(menuOptions[0].id);
|
||||
}
|
||||
},
|
||||
Enter: () =>
|
||||
handleEnter({
|
||||
page,
|
||||
selectedOption,
|
||||
callback: () => {
|
||||
setAnchor(null);
|
||||
},
|
||||
}),
|
||||
Escape: () => {
|
||||
setAnchor(null);
|
||||
},
|
||||
}),
|
||||
[page, selectedOption]
|
||||
);
|
||||
const onKeydown = useCallback(
|
||||
(e: KeyboardEvent) => {
|
||||
const shortcut = shortcutMap[e.key];
|
||||
if (shortcut) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
shortcut(e, page);
|
||||
} else {
|
||||
setAnchor(null);
|
||||
}
|
||||
},
|
||||
[page, shortcutMap]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const disposer = page.slots.pasted.on(pastedBlocks => {
|
||||
@@ -189,56 +135,35 @@ export const Bookmark = ({ page }: BookmarkProps) => {
|
||||
return () => {
|
||||
disposer.dispose();
|
||||
};
|
||||
}, [onKeydown, page, shortcutMap]);
|
||||
}, [page]);
|
||||
|
||||
useEffect(() => {
|
||||
if (anchor) {
|
||||
document.addEventListener('keydown', onKeydown, { capture: true });
|
||||
} else {
|
||||
// reset status and remove event
|
||||
setSelectedOption(menuOptions[0].id);
|
||||
document.removeEventListener('keydown', onKeydown, { capture: true });
|
||||
}
|
||||
const portalContainer = anchor?.startContainer.parentElement;
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('keydown', onKeydown, { capture: true });
|
||||
};
|
||||
}, [anchor, onKeydown]);
|
||||
|
||||
return anchor ? (
|
||||
<MuiClickAwayListener
|
||||
onClickAway={() => {
|
||||
setAnchor(null);
|
||||
setSelectedOption('');
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<PureMenu open={!!anchor} anchorEl={anchor} placement="bottom-start">
|
||||
{menuOptions.map(({ id, label }) => {
|
||||
return (
|
||||
<MenuItem
|
||||
key={id}
|
||||
active={selectedOption === id}
|
||||
onClick={() => {
|
||||
handleEnter({
|
||||
page,
|
||||
selectedOption: id,
|
||||
callback: () => {
|
||||
setAnchor(null);
|
||||
},
|
||||
});
|
||||
}}
|
||||
disableHover={true}
|
||||
onMouseEnter={() => {
|
||||
setSelectedOption(id);
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
</PureMenu>
|
||||
</div>
|
||||
</MuiClickAwayListener>
|
||||
) : null;
|
||||
return anchor && portalContainer
|
||||
? createPortal(
|
||||
<Menu
|
||||
rootOptions={{
|
||||
defaultOpen: true,
|
||||
onOpenChange: (e: boolean) => !e && setAnchor(null),
|
||||
}}
|
||||
items={menuOptions.map(({ id, label }) => (
|
||||
<MenuItem
|
||||
key={id}
|
||||
onClick={() =>
|
||||
handleEnter({
|
||||
page,
|
||||
selectedOption: id,
|
||||
callback: () => setAnchor(null),
|
||||
})
|
||||
}
|
||||
>
|
||||
{label}
|
||||
</MenuItem>
|
||||
))}
|
||||
>
|
||||
<span></span>
|
||||
</Menu>,
|
||||
portalContainer
|
||||
)
|
||||
: null;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { MuiFade } from '@affine/component';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { CloseIcon, NewIcon, UserGuideIcon } from '@blocksuite/icons';
|
||||
import { Tooltip } from '@toeverything/components/tooltip';
|
||||
@@ -8,7 +7,7 @@ import { useCallback, useState } from 'react';
|
||||
|
||||
import { openOnboardingModalAtom, openSettingModalAtom } from '../../../atoms';
|
||||
import { currentModeAtom } from '../../../atoms/mode';
|
||||
import { ShortcutsModal } from '../shortcuts-modal';
|
||||
import type { SettingProps } from '../../affine/setting-modal';
|
||||
import { ContactIcon, HelpIcon, KeyboardIcon } from './icons';
|
||||
import {
|
||||
StyledAnimateWrapper,
|
||||
@@ -36,113 +35,106 @@ export const HelpIsland = ({
|
||||
const [spread, setShowSpread] = useState(false);
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
const [openShortCut, setOpenShortCut] = useState(false);
|
||||
const openSettingModal = useCallback(
|
||||
(tab: SettingProps['activeTab']) => {
|
||||
setShowSpread(false);
|
||||
|
||||
const openAbout = useCallback(() => {
|
||||
setShowSpread(false);
|
||||
|
||||
setOpenSettingModalAtom({
|
||||
open: true,
|
||||
activeTab: 'about',
|
||||
workspaceId: null,
|
||||
});
|
||||
}, [setOpenSettingModalAtom]);
|
||||
setOpenSettingModalAtom({
|
||||
open: true,
|
||||
activeTab: tab,
|
||||
workspaceId: null,
|
||||
});
|
||||
},
|
||||
[setOpenSettingModalAtom]
|
||||
);
|
||||
const openAbout = useCallback(
|
||||
() => openSettingModal('about'),
|
||||
[openSettingModal]
|
||||
);
|
||||
const openShortcuts = useCallback(
|
||||
() => openSettingModal('shortcuts'),
|
||||
[openSettingModal]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledIsland
|
||||
spread={spread}
|
||||
data-testid="help-island"
|
||||
onClick={() => {
|
||||
setShowSpread(!spread);
|
||||
}}
|
||||
inEdgelessPage={mode === 'edgeless'}
|
||||
<StyledIsland
|
||||
spread={spread}
|
||||
data-testid="help-island"
|
||||
onClick={() => {
|
||||
setShowSpread(!spread);
|
||||
}}
|
||||
inEdgelessPage={mode === 'edgeless'}
|
||||
>
|
||||
<StyledAnimateWrapper
|
||||
style={{ height: spread ? `${showList.length * 40 + 4}px` : 0 }}
|
||||
>
|
||||
<StyledAnimateWrapper
|
||||
style={{ height: spread ? `${showList.length * 40 + 4}px` : 0 }}
|
||||
>
|
||||
{showList.includes('whatNew') && (
|
||||
<Tooltip
|
||||
content={t['com.affine.appUpdater.whatsNew']()}
|
||||
side="left"
|
||||
{showList.includes('whatNew') && (
|
||||
<Tooltip content={t['com.affine.appUpdater.whatsNew']()} side="left">
|
||||
<StyledIconWrapper
|
||||
data-testid="right-bottom-change-log-icon"
|
||||
onClick={() => {
|
||||
window.open(runtimeConfig.changelogUrl, '_blank');
|
||||
}}
|
||||
>
|
||||
<StyledIconWrapper
|
||||
data-testid="right-bottom-change-log-icon"
|
||||
onClick={() => {
|
||||
window.open(runtimeConfig.changelogUrl, '_blank');
|
||||
}}
|
||||
>
|
||||
<NewIcon />
|
||||
</StyledIconWrapper>
|
||||
</Tooltip>
|
||||
)}
|
||||
{showList.includes('contact') && (
|
||||
<Tooltip
|
||||
content={t['com.affine.helpIsland.contactUs']()}
|
||||
side="left"
|
||||
<NewIcon />
|
||||
</StyledIconWrapper>
|
||||
</Tooltip>
|
||||
)}
|
||||
{showList.includes('contact') && (
|
||||
<Tooltip content={t['com.affine.helpIsland.contactUs']()} side="left">
|
||||
<StyledIconWrapper
|
||||
data-testid="right-bottom-contact-us-icon"
|
||||
onClick={openAbout}
|
||||
>
|
||||
<StyledIconWrapper
|
||||
data-testid="right-bottom-contact-us-icon"
|
||||
onClick={openAbout}
|
||||
>
|
||||
<ContactIcon />
|
||||
</StyledIconWrapper>
|
||||
</Tooltip>
|
||||
)}
|
||||
{showList.includes('shortcuts') && (
|
||||
<Tooltip
|
||||
content={t['com.affine.keyboardShortcuts.title']()}
|
||||
side="left"
|
||||
<ContactIcon />
|
||||
</StyledIconWrapper>
|
||||
</Tooltip>
|
||||
)}
|
||||
{showList.includes('shortcuts') && (
|
||||
<Tooltip
|
||||
content={t['com.affine.keyboardShortcuts.title']()}
|
||||
side="left"
|
||||
>
|
||||
<StyledIconWrapper
|
||||
data-testid="shortcuts-icon"
|
||||
onClick={openShortcuts}
|
||||
>
|
||||
<StyledIconWrapper
|
||||
data-testid="shortcuts-icon"
|
||||
onClick={() => {
|
||||
setShowSpread(false);
|
||||
setOpenShortCut(true);
|
||||
}}
|
||||
>
|
||||
<KeyboardIcon />
|
||||
</StyledIconWrapper>
|
||||
</Tooltip>
|
||||
)}
|
||||
{showList.includes('guide') && (
|
||||
<Tooltip
|
||||
content={t['com.affine.helpIsland.gettingStarted']()}
|
||||
side="left"
|
||||
<KeyboardIcon />
|
||||
</StyledIconWrapper>
|
||||
</Tooltip>
|
||||
)}
|
||||
{showList.includes('guide') && (
|
||||
<Tooltip
|
||||
content={t['com.affine.helpIsland.gettingStarted']()}
|
||||
side="left"
|
||||
>
|
||||
<StyledIconWrapper
|
||||
data-testid="easy-guide"
|
||||
onClick={() => {
|
||||
setShowSpread(false);
|
||||
setOpenOnboarding(true);
|
||||
}}
|
||||
>
|
||||
<StyledIconWrapper
|
||||
data-testid="easy-guide"
|
||||
onClick={() => {
|
||||
setShowSpread(false);
|
||||
setOpenOnboarding(true);
|
||||
}}
|
||||
>
|
||||
<UserGuideIcon />
|
||||
</StyledIconWrapper>
|
||||
</Tooltip>
|
||||
)}
|
||||
</StyledAnimateWrapper>
|
||||
<UserGuideIcon />
|
||||
</StyledIconWrapper>
|
||||
</Tooltip>
|
||||
)}
|
||||
</StyledAnimateWrapper>
|
||||
|
||||
{spread ? (
|
||||
<StyledTriggerWrapper spread>
|
||||
<CloseIcon />
|
||||
</StyledTriggerWrapper>
|
||||
) : (
|
||||
<Tooltip
|
||||
content={t['com.affine.helpIsland.helpAndFeedback']()}
|
||||
side="left"
|
||||
>
|
||||
<MuiFade in={!spread} data-testid="faq-icon">
|
||||
<StyledTriggerWrapper>
|
||||
<HelpIcon />
|
||||
</StyledTriggerWrapper>
|
||||
</MuiFade>
|
||||
</Tooltip>
|
||||
<MuiFade in={spread}>
|
||||
<StyledTriggerWrapper spread>
|
||||
<CloseIcon />
|
||||
<StyledTriggerWrapper data-testid="faq-icon">
|
||||
<HelpIcon />
|
||||
</StyledTriggerWrapper>
|
||||
</MuiFade>
|
||||
</StyledIsland>
|
||||
<ShortcutsModal
|
||||
open={openShortCut}
|
||||
onClose={() => setOpenShortCut(false)}
|
||||
/>
|
||||
</>
|
||||
</Tooltip>
|
||||
)}
|
||||
</StyledIsland>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -19,8 +19,8 @@ export const StyledIsland = styled('div')<{
|
||||
? 'var(--affine-background-overlay-panel-color)'
|
||||
: 'var(--affine-background-primary-color)',
|
||||
':hover': {
|
||||
background: spread ? null : 'var(--affine-white)',
|
||||
boxShadow: spread ? null : 'var(--affine-menu-shadow)',
|
||||
background: spread ? undefined : 'var(--affine-white)',
|
||||
boxShadow: spread ? undefined : 'var(--affine-menu-shadow)',
|
||||
},
|
||||
'::after': {
|
||||
content: '""',
|
||||
@@ -73,7 +73,7 @@ export const StyledTriggerWrapper = styled('div')<{
|
||||
...displayFlex('center', 'center'),
|
||||
...positionAbsolute({ left: '4px', bottom: '4px' }),
|
||||
':hover': {
|
||||
backgroundColor: spread ? 'var(--affine-hover-color)' : null,
|
||||
backgroundColor: spread ? 'var(--affine-hover-color)' : undefined,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
export const CloseIcon = () => {
|
||||
return (
|
||||
<svg
|
||||
width="14"
|
||||
height="14"
|
||||
viewBox="0 0 14 14"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M7.94 7.00014L13.4667 1.47348C13.5759 1.34594 13.633 1.18189 13.6265 1.01411C13.62 0.846324 13.5504 0.687165 13.4317 0.568435C13.313 0.449706 13.1538 0.38015 12.986 0.37367C12.8183 0.367189 12.6542 0.42426 12.5267 0.533477L7 6.06014L1.47334 0.526811C1.3478 0.401275 1.17754 0.33075 1 0.33075C0.822468 0.33075 0.652205 0.401275 0.526669 0.526811C0.401133 0.652346 0.330608 0.82261 0.330608 1.00014C0.330608 1.17768 0.401133 1.34794 0.526669 1.47348L6.06 7.00014L0.526669 12.5268C0.456881 12.5866 0.400201 12.6601 0.360186 12.7428C0.32017 12.8255 0.297683 12.9156 0.294137 13.0074C0.290591 13.0993 0.306061 13.1908 0.339577 13.2764C0.373094 13.3619 0.423932 13.4396 0.488902 13.5046C0.553872 13.5695 0.63157 13.6204 0.71712 13.6539C0.80267 13.6874 0.894225 13.7029 0.986038 13.6993C1.07785 13.6958 1.16794 13.6733 1.25065 13.6333C1.33336 13.5933 1.4069 13.5366 1.46667 13.4668L7 7.94014L12.5267 13.4668C12.6542 13.576 12.8183 13.6331 12.986 13.6266C13.1538 13.6201 13.313 13.5506 13.4317 13.4319C13.5504 13.3131 13.62 13.154 13.6265 12.9862C13.633 12.8184 13.5759 12.6543 13.4667 12.5268L7.94 7.00014Z" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export const KeyboardIcon = () => {
|
||||
return (
|
||||
<svg
|
||||
width="20"
|
||||
height="15"
|
||||
viewBox="0 0 20 15"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M17.745 0C18.3417 0 18.914 0.237053 19.336 0.65901C19.7579 1.08097 19.995 1.65326 19.995 2.25V11.755C19.995 12.3517 19.7579 12.924 19.336 13.346C18.914 13.7679 18.3417 14.005 17.745 14.005H2.25C1.95453 14.005 1.66194 13.9468 1.38896 13.8337C1.11598 13.7207 0.867941 13.5549 0.65901 13.346C0.450078 13.1371 0.284344 12.889 0.171271 12.616C0.058198 12.3431 0 12.0505 0 11.755V2.25C0 1.65326 0.237053 1.08097 0.65901 0.65901C1.08097 0.237053 1.65326 0 2.25 0H17.745ZM17.745 1.5H2.25C2.05109 1.5 1.86032 1.57902 1.71967 1.71967C1.57902 1.86032 1.5 2.05109 1.5 2.25V11.755C1.5 12.169 1.836 12.505 2.25 12.505H17.745C17.9439 12.505 18.1347 12.426 18.2753 12.2853C18.416 12.1447 18.495 11.9539 18.495 11.755V2.25C18.495 2.05109 18.416 1.86032 18.2753 1.71967C18.1347 1.57902 17.9439 1.5 17.745 1.5ZM4.75 9.5H15.25C15.44 9.50006 15.6229 9.57224 15.7618 9.70197C15.9006 9.8317 15.9851 10.0093 15.998 10.1989C16.011 10.3885 15.9515 10.5759 15.8316 10.7233C15.7117 10.8707 15.5402 10.9671 15.352 10.993L15.25 11H4.75C4.55998 10.9999 4.37706 10.9278 4.23821 10.798C4.09936 10.6683 4.01493 10.4907 4.00197 10.3011C3.98902 10.1115 4.04852 9.92411 4.16843 9.7767C4.28835 9.62929 4.45975 9.5329 4.648 9.507L4.75 9.5H15.25H4.75ZM14.5 6C14.7652 6 15.0196 6.10536 15.2071 6.29289C15.3946 6.48043 15.5 6.73478 15.5 7C15.5 7.26522 15.3946 7.51957 15.2071 7.70711C15.0196 7.89464 14.7652 8 14.5 8C14.2348 8 13.9804 7.89464 13.7929 7.70711C13.6054 7.51957 13.5 7.26522 13.5 7C13.5 6.73478 13.6054 6.48043 13.7929 6.29289C13.9804 6.10536 14.2348 6 14.5 6ZM8.505 6C8.77022 6 9.02457 6.10536 9.21211 6.29289C9.39964 6.48043 9.505 6.73478 9.505 7C9.505 7.26522 9.39964 7.51957 9.21211 7.70711C9.02457 7.89464 8.77022 8 8.505 8C8.23978 8 7.98543 7.89464 7.79789 7.70711C7.61036 7.51957 7.505 7.26522 7.505 7C7.505 6.73478 7.61036 6.48043 7.79789 6.29289C7.98543 6.10536 8.23978 6 8.505 6ZM5.505 6C5.77022 6 6.02457 6.10536 6.21211 6.29289C6.39964 6.48043 6.505 6.73478 6.505 7C6.505 7.26522 6.39964 7.51957 6.21211 7.70711C6.02457 7.89464 5.77022 8 5.505 8C5.23978 8 4.98543 7.89464 4.79789 7.70711C4.61036 7.51957 4.505 7.26522 4.505 7C4.505 6.73478 4.61036 6.48043 4.79789 6.29289C4.98543 6.10536 5.23978 6 5.505 6ZM11.505 6C11.7702 6 12.0246 6.10536 12.2121 6.29289C12.3996 6.48043 12.505 6.73478 12.505 7C12.505 7.26522 12.3996 7.51957 12.2121 7.70711C12.0246 7.89464 11.7702 8 11.505 8C11.2398 8 10.9854 7.89464 10.7979 7.70711C10.6104 7.51957 10.505 7.26522 10.505 7C10.505 6.73478 10.6104 6.48043 10.7979 6.29289C10.9854 6.10536 11.2398 6 11.505 6ZM4 3C4.26522 3 4.51957 3.10536 4.70711 3.29289C4.89464 3.48043 5 3.73478 5 4C5 4.26522 4.89464 4.51957 4.70711 4.70711C4.51957 4.89464 4.26522 5 4 5C3.73478 5 3.48043 4.89464 3.29289 4.70711C3.10536 4.51957 3 4.26522 3 4C3 3.73478 3.10536 3.48043 3.29289 3.29289C3.48043 3.10536 3.73478 3 4 3ZM6.995 3C7.26022 3 7.51457 3.10536 7.70211 3.29289C7.88964 3.48043 7.995 3.73478 7.995 4C7.995 4.26522 7.88964 4.51957 7.70211 4.70711C7.51457 4.89464 7.26022 5 6.995 5C6.72978 5 6.47543 4.89464 6.28789 4.70711C6.10036 4.51957 5.995 4.26522 5.995 4C5.995 3.73478 6.10036 3.48043 6.28789 3.29289C6.47543 3.10536 6.72978 3 6.995 3ZM9.995 3C10.2602 3 10.5146 3.10536 10.7021 3.29289C10.8896 3.48043 10.995 3.73478 10.995 4C10.995 4.26522 10.8896 4.51957 10.7021 4.70711C10.5146 4.89464 10.2602 5 9.995 5C9.72978 5 9.47543 4.89464 9.28789 4.70711C9.10036 4.51957 8.995 4.26522 8.995 4C8.995 3.73478 9.10036 3.48043 9.28789 3.29289C9.47543 3.10536 9.72978 3 9.995 3ZM12.995 3C13.2602 3 13.5146 3.10536 13.7021 3.29289C13.8896 3.48043 13.995 3.73478 13.995 4C13.995 4.26522 13.8896 4.51957 13.7021 4.70711C13.5146 4.89464 13.2602 5 12.995 5C12.7298 5 12.4754 4.89464 12.2879 4.70711C12.1004 4.51957 11.995 4.26522 11.995 4C11.995 3.73478 12.1004 3.48043 12.2879 3.29289C12.4754 3.10536 12.7298 3 12.995 3ZM15.995 3C16.2602 3 16.5146 3.10536 16.7021 3.29289C16.8896 3.48043 16.995 3.73478 16.995 4C16.995 4.26522 16.8896 4.51957 16.7021 4.70711C16.5146 4.89464 16.2602 5 15.995 5C15.7298 5 15.4754 4.89464 15.2879 4.70711C15.1004 4.51957 14.995 4.26522 14.995 4C14.995 3.73478 15.1004 3.48043 15.2879 3.29289C15.4754 3.10536 15.7298 3 15.995 3Z" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
@@ -1,97 +0,0 @@
|
||||
import { MuiClickAwayListener, MuiSlide } from '@affine/component';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { CloseIcon } from '@blocksuite/icons';
|
||||
import { IconButton } from '@toeverything/components/button';
|
||||
|
||||
import {
|
||||
type ShortcutsInfo,
|
||||
useEdgelessShortcuts,
|
||||
useGeneralShortcuts,
|
||||
useMarkdownShortcuts,
|
||||
usePageShortcuts,
|
||||
} from '../../../hooks/affine/use-shortcuts';
|
||||
import { KeyboardIcon } from './icons';
|
||||
import * as styles from './style.css';
|
||||
|
||||
type ModalProps = {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const ShortcutsPanel = ({
|
||||
shortcutsInfo,
|
||||
}: {
|
||||
shortcutsInfo: ShortcutsInfo;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<div className={styles.subtitle}>{shortcutsInfo.title}</div>
|
||||
|
||||
{Object.entries(shortcutsInfo.shortcuts).map(([title, shortcuts]) => {
|
||||
return (
|
||||
<div className={styles.listItem} key={title}>
|
||||
<span>{title}</span>
|
||||
<div className={styles.keyContainer}>
|
||||
{shortcuts.map(key => {
|
||||
return (
|
||||
<span className={styles.key} key={key}>
|
||||
{key}
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const ShortcutsModal = ({ open, onClose }: ModalProps) => {
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
const markdownShortcutsInfo = useMarkdownShortcuts();
|
||||
const pageShortcutsInfo = usePageShortcuts();
|
||||
const edgelessShortcutsInfo = useEdgelessShortcuts();
|
||||
const generalShortcutsInfo = useGeneralShortcuts();
|
||||
|
||||
return (
|
||||
<MuiSlide direction="left" in={open} mountOnEnter unmountOnExit>
|
||||
<div className={styles.shortcutsModal} data-testid="shortcuts-modal">
|
||||
<MuiClickAwayListener
|
||||
onClickAway={() => {
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
className={styles.modalHeader}
|
||||
style={{ marginBottom: '-28px' }}
|
||||
>
|
||||
<div className={styles.title}>
|
||||
<KeyboardIcon />
|
||||
{t['Shortcuts']()}
|
||||
</div>
|
||||
|
||||
<IconButton
|
||||
style={{
|
||||
position: 'absolute',
|
||||
right: 6,
|
||||
top: 6,
|
||||
}}
|
||||
onClick={() => {
|
||||
onClose();
|
||||
}}
|
||||
icon={<CloseIcon />}
|
||||
/>
|
||||
</div>
|
||||
<ShortcutsPanel shortcutsInfo={generalShortcutsInfo} />
|
||||
<ShortcutsPanel shortcutsInfo={pageShortcutsInfo} />
|
||||
<ShortcutsPanel shortcutsInfo={edgelessShortcutsInfo} />
|
||||
<ShortcutsPanel shortcutsInfo={markdownShortcutsInfo} />
|
||||
</div>
|
||||
</MuiClickAwayListener>
|
||||
</div>
|
||||
</MuiSlide>
|
||||
);
|
||||
};
|
||||
@@ -1,89 +0,0 @@
|
||||
import { globalStyle, style } from '@vanilla-extract/css';
|
||||
|
||||
export const shortcutsModal = style({
|
||||
width: '288px',
|
||||
height: '74vh',
|
||||
paddingBottom: '28px',
|
||||
backgroundColor: 'var(--affine-white)',
|
||||
boxShadow: 'var(--affine-popover-shadow)',
|
||||
borderRadius: `var(--affine-popover-radius)`,
|
||||
overflow: 'auto',
|
||||
position: 'fixed',
|
||||
right: '12px',
|
||||
top: '0',
|
||||
bottom: '0',
|
||||
margin: 'auto',
|
||||
zIndex: 'var(--affine-z-index-modal)',
|
||||
});
|
||||
// export const shortcutsModal = style({
|
||||
// color: 'var(--affine-text-primary-color)',
|
||||
// fontWeight: '500',
|
||||
// fontSize: 'var(--affine-font-sm)',
|
||||
// height: '44px',
|
||||
// display: 'flex',
|
||||
// justifyContent: 'center',
|
||||
// alignItems: 'center',
|
||||
// svg: {
|
||||
// width: '20px',
|
||||
// marginRight: '14px',
|
||||
// color: 'var(--affine-primary-color)',
|
||||
// },
|
||||
// });
|
||||
export const title = style({
|
||||
color: 'var(--affine-text-primary-color)',
|
||||
fontWeight: '500',
|
||||
fontSize: 'var(--affine-font-sm)',
|
||||
height: '44px',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
});
|
||||
|
||||
globalStyle(`${title} svg`, {
|
||||
width: '20px',
|
||||
marginRight: '14px',
|
||||
color: 'var(--affine-primary-color)',
|
||||
});
|
||||
|
||||
export const subtitle = style({
|
||||
fontWeight: '500',
|
||||
fontSize: 'var(--affine-font-sm)',
|
||||
height: '34px',
|
||||
lineHeight: '36px',
|
||||
marginTop: '28px',
|
||||
padding: '0 16px',
|
||||
});
|
||||
export const modalHeader = style({
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
paddingTop: '8px 4px 0 4px',
|
||||
width: '100%',
|
||||
padding: '8px 16px 0 16px',
|
||||
position: 'sticky',
|
||||
left: '0',
|
||||
top: '0',
|
||||
background: 'var(--affine-white)',
|
||||
transition: 'background-color 0.5s',
|
||||
});
|
||||
|
||||
export const listItem = style({
|
||||
height: '34px',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
fontSize: 'var(--affine-font-sm)',
|
||||
padding: '0 16px',
|
||||
});
|
||||
export const keyContainer = style({
|
||||
display: 'flex',
|
||||
});
|
||||
|
||||
export const key = style({
|
||||
selectors: {
|
||||
'&:not(:last-child)::after': {
|
||||
content: '+',
|
||||
margin: '0 4px',
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1,130 +0,0 @@
|
||||
import { alpha, displayFlex, styled, textEllipsis } from '@affine/component';
|
||||
|
||||
export const StyledListItem = styled('div')<{
|
||||
active?: boolean;
|
||||
disabled?: boolean;
|
||||
}>(({ active, disabled }) => {
|
||||
return {
|
||||
height: '32px',
|
||||
color: active
|
||||
? 'var(--affine-primary-color)'
|
||||
: 'var(--affine-text-primary-color)',
|
||||
paddingLeft: '2px',
|
||||
paddingRight: '2px',
|
||||
borderRadius: '8px',
|
||||
cursor: 'pointer',
|
||||
marginBottom: '4px',
|
||||
position: 'relative',
|
||||
flexShrink: 0,
|
||||
userSelect: 'none',
|
||||
...displayFlex('flex-start', 'stretch'),
|
||||
...(disabled
|
||||
? {
|
||||
cursor: 'not-allowed',
|
||||
color: 'var(--affine-border-color)',
|
||||
}
|
||||
: {}),
|
||||
|
||||
'a > svg, div > svg': {
|
||||
fontSize: '20px',
|
||||
marginLeft: '14px',
|
||||
marginRight: '12px',
|
||||
color: active
|
||||
? 'var(--affine-primary-color)'
|
||||
: 'var(--affine-icon-color)',
|
||||
},
|
||||
':hover:not([disabled])': {
|
||||
backgroundColor: 'var(--affine-hover-color)',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledCollapseButton = styled('button')<{
|
||||
collapse: boolean;
|
||||
show?: boolean;
|
||||
}>(({ collapse, show = true }) => {
|
||||
return {
|
||||
width: '16px',
|
||||
height: '100%',
|
||||
...displayFlex('center', 'center'),
|
||||
fontSize: '16px',
|
||||
position: 'absolute',
|
||||
left: '0',
|
||||
top: '0',
|
||||
bottom: '0',
|
||||
margin: 'auto',
|
||||
color: 'var(--affine-icon-color)',
|
||||
opacity: '.6',
|
||||
transition: 'opacity .15s ease-in-out',
|
||||
display: show ? 'flex' : 'none',
|
||||
svg: {
|
||||
transform: `rotate(${collapse ? '0' : '-90'}deg)`,
|
||||
},
|
||||
':hover': {
|
||||
opacity: '1',
|
||||
},
|
||||
':focus-visible': {
|
||||
outline: '-webkit-focus-ring-color auto 1px',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledCollapseItem = styled('div')<{
|
||||
disable?: boolean;
|
||||
active?: boolean;
|
||||
isOver?: boolean;
|
||||
textWrap?: boolean;
|
||||
}>(({ disable = false, active = false, isOver, textWrap = false }) => {
|
||||
return {
|
||||
width: '100%',
|
||||
lineHeight: '1.5',
|
||||
minHeight: '32px',
|
||||
borderRadius: '8px',
|
||||
...displayFlex('flex-start', 'center'),
|
||||
paddingRight: '2px',
|
||||
position: 'relative',
|
||||
color: disable
|
||||
? 'var(--affine-text-disable-color)'
|
||||
: active
|
||||
? 'var(--affine-primary-color)'
|
||||
: 'var(--affine-text-primary-color)',
|
||||
cursor: disable ? 'not-allowed' : 'pointer',
|
||||
background: isOver ? alpha('var(--affine-primary-color)', 0.06) : '',
|
||||
userSelect: 'none',
|
||||
...(textWrap
|
||||
? {
|
||||
wordBreak: 'break-word',
|
||||
whiteSpace: 'pre-wrap',
|
||||
}
|
||||
: {}),
|
||||
span: {
|
||||
flexGrow: '1',
|
||||
textAlign: 'left',
|
||||
...textEllipsis(1),
|
||||
},
|
||||
'> svg': {
|
||||
fontSize: '20px',
|
||||
marginRight: '8px',
|
||||
flexShrink: '0',
|
||||
color: active
|
||||
? 'var(--affine-primary-color)'
|
||||
: 'var(--affine-icon-color)',
|
||||
},
|
||||
|
||||
':hover': disable
|
||||
? {}
|
||||
: {
|
||||
backgroundColor: 'var(--affine-hover-color)',
|
||||
'.operation-button': {
|
||||
visibility: 'visible',
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledRouteNavigationWrapper = styled('div')({
|
||||
height: '32px',
|
||||
width: '80px',
|
||||
marginRight: '16px',
|
||||
...displayFlex('space-between', 'center'),
|
||||
});
|
||||
@@ -1,85 +0,0 @@
|
||||
import { displayFlex, styled, textEllipsis } from '@affine/component';
|
||||
import { Link } from '@mui/material';
|
||||
import { baseTheme } from '@toeverything/theme';
|
||||
|
||||
export const StyledSliderBarInnerWrapper = styled('div')(() => {
|
||||
return {
|
||||
flexGrow: 1,
|
||||
margin: '0 2px',
|
||||
position: 'relative',
|
||||
height: 'calc(100% - 52px * 2)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledLink = styled(Link)(() => {
|
||||
return {
|
||||
flexGrow: 1,
|
||||
textAlign: 'left',
|
||||
color: 'inherit',
|
||||
...displayFlex('flex-start', 'center'),
|
||||
':visited': {
|
||||
color: 'inherit',
|
||||
},
|
||||
overflow: 'hidden',
|
||||
div: {
|
||||
wordBreak: 'break-all',
|
||||
wordWrap: 'break-word',
|
||||
whiteSpace: 'nowrap',
|
||||
...textEllipsis(1),
|
||||
},
|
||||
userDrag: 'none',
|
||||
userSelect: 'none',
|
||||
appRegion: 'no-drag',
|
||||
WebkitUserSelect: 'none',
|
||||
WebkitUserDrag: 'none',
|
||||
WebkitAppRegion: 'no-drag',
|
||||
};
|
||||
});
|
||||
export const StyledNewPageButton = styled('button')(() => {
|
||||
return {
|
||||
width: '100%',
|
||||
height: '52px',
|
||||
...displayFlex('flex-start', 'center'),
|
||||
padding: '0 16px',
|
||||
svg: {
|
||||
fontSize: '20px',
|
||||
color: 'var(--affine-icon-color)',
|
||||
marginRight: '12px',
|
||||
},
|
||||
':hover': {
|
||||
color: 'var(--affine-primary-color)',
|
||||
svg: {
|
||||
color: 'var(--affine-primary-color)',
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
export const StyledSliderModalBackground = styled('div')<{ active: boolean }>(({
|
||||
active,
|
||||
}) => {
|
||||
return {
|
||||
transition: 'opacity .15s',
|
||||
pointerEvents: active ? 'auto' : 'none',
|
||||
opacity: active ? 1 : 0,
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: active ? 0 : '100%',
|
||||
bottom: 0,
|
||||
zIndex: parseInt(baseTheme.zIndexModal) - 1,
|
||||
background: 'var(--affine-background-modal-color)',
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledScrollWrapper = styled('div')<{
|
||||
showTopBorder: boolean;
|
||||
}>(({ showTopBorder }) => {
|
||||
return {
|
||||
maxHeight: '50%',
|
||||
overflowY: 'auto',
|
||||
borderTop: '1px solid',
|
||||
borderColor: showTopBorder ? 'var(--affine-border-color)' : 'transparent',
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user