diff --git a/packages/app/package.json b/packages/app/package.json index f9f0091cc6..cd200c5982 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -19,6 +19,7 @@ "@emotion/styled": "^11.10.4", "@mui/base": "^5.0.0-alpha.87", "@mui/material": "^5.8.6", + "@mui/icons-material": "^5.10.9", "css-spring": "^4.1.0", "lit": "^2.3.1", "next": "12.3.1", diff --git a/packages/app/public/globals.css b/packages/app/public/globals.css index 62b1feadfd..7388399c01 100644 --- a/packages/app/public/globals.css +++ b/packages/app/public/globals.css @@ -145,7 +145,7 @@ button, select, keygen, legend { - color: var(--page-text-color); + color: var(--affine-text-color); outline: 0; font-size: 18px; line-height: 1.5; @@ -156,7 +156,7 @@ body { } a, a:hover { - color: var(--page-text-color); + color: var(--affine-link-color); } input { @@ -181,3 +181,11 @@ input[type='number']::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; } + +* { + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE 10+ */ +} +::-webkit-scrollbar { + display: none; /* Chrome Safari */ +} diff --git a/packages/app/src/components/Header/icons.tsx b/packages/app/src/components/Header/icons.tsx index 9e27fc7875..6f9d5ebee1 100644 --- a/packages/app/src/components/Header/icons.tsx +++ b/packages/app/src/components/Header/icons.tsx @@ -22,46 +22,6 @@ export const LogoIcon = ({ style = {}, ...props }: IconProps) => { ); }; -export const MoonIcon = ({ style = {}, ...props }: IconProps) => { - return ( - - - - ); -}; - -export const SunIcon = ({ style = {}, ...props }: IconProps) => { - return ( - - - - ); -}; - export const MoreIcon = ({ style = {}, ...props }: IconProps) => { return ( { - const { changeMode, mode } = useTheme(); - - return ( - <> - {mode === 'dark' ? ( - { - changeMode('light'); - }} - > - ) : ( - { - changeMode('dark'); - }} - > - )} - > - ); -}; +import ThemeModeSwitch from '@/components/theme-mode-switch'; +import ContactModal from '@/components/contact-modal'; const PopoverContent = () => { const { editor, mode, setMode } = useEditor(); @@ -74,6 +51,7 @@ const PopoverContent = () => { export const Header = () => { const [title, setTitle] = useState(''); const [isHover, setIsHover] = useState(false); + const [showContactModal, setShowContactModal] = useState(false); const { editor } = useEditor(); @@ -87,38 +65,48 @@ export const Header = () => { }, [editor]); return ( - - - {}} /> - - { - setIsHover(true); - }} - onMouseLeave={() => { - setIsHover(false); - }} - > - + setShowContactModal(false)} + /> + + + { + setShowContactModal(true); + }} + /> + + { + setIsHover(true); + }} + onMouseLeave={() => { + setIsHover(false); }} - /> - {title} - - - - - } - style={{ marginLeft: '20px' }} > - - - - - - + + {title} + + + + + } + style={{ marginLeft: '20px' }} + > + + + + + + + > ); }; diff --git a/packages/app/src/components/Header/styles.ts b/packages/app/src/components/Header/styles.ts index 8162ca2eaa..16ac015e7a 100644 --- a/packages/app/src/components/Header/styles.ts +++ b/packages/app/src/components/Header/styles.ts @@ -33,14 +33,10 @@ export const StyledTitleWrapper = styled('div')({ position: 'relative', }); -export const StyledLogo = styled('div')({}); - -export const StyledModeSwitch = styled('div')({ - height: '100%', - display: 'flex', - alignItems: 'center', - marginRight: '12px', -}); +export const StyledLogo = styled('div')(({ theme }) => ({ + color: theme.colors.primaryColor, + cursor: 'pointer', +})); export const StyledHeaderRightSide = styled('div')({ height: '100%', @@ -48,27 +44,25 @@ export const StyledHeaderRightSide = styled('div')({ alignItems: 'center', }); -export const StyledMoreMenuItem = styled('div')({ - height: '32px', - display: 'flex', - alignItems: 'center', - borderRadius: '5px', - fontSize: '14px', - color: '#4C6275', - padding: '0 14px', - svg: { - fill: '#4C6275', - width: '16px', - height: '16px', - marginRight: '14px', - }, - ':hover': { - color: 'var(--affine-highlight-color)', - background: '#F1F3FF', +export const StyledMoreMenuItem = styled('div')(({ theme }) => { + return { + height: '32px', + display: 'flex', + alignItems: 'center', + borderRadius: '5px', + fontSize: '14px', + color: theme.colors.popoverColor, + padding: '0 14px', svg: { - fill: 'var(--affine-highlight-color)', + width: '16px', + height: '16px', + marginRight: '14px', }, - }, + ':hover': { + color: theme.colors.primaryColor, + background: theme.colors.hoverBackground, + }, + }; }); export const IconButton = styled('div')(({ theme }) => { @@ -78,12 +72,11 @@ export const IconButton = styled('div')(({ theme }) => { display: 'flex', justifyContent: 'center', alignItems: 'center', - color: theme.colors.disabled, - background: 'transparent', + color: theme.colors.iconColor, borderRadius: '5px', ':hover': { - color: theme.colors.highlight, - background: '#F1F3FF', + color: theme.colors.primaryColor, + background: theme.colors.hoverBackground, }, }; }); diff --git a/packages/app/src/components/contact-modal/affine-text-logo.png b/packages/app/src/components/contact-modal/affine-text-logo.png new file mode 100644 index 0000000000..a136ab17fa Binary files /dev/null and b/packages/app/src/components/contact-modal/affine-text-logo.png differ diff --git a/packages/app/src/components/contact-modal/icons.tsx b/packages/app/src/components/contact-modal/icons.tsx new file mode 100644 index 0000000000..d267dbe9c3 --- /dev/null +++ b/packages/app/src/components/contact-modal/icons.tsx @@ -0,0 +1,55 @@ +// export const CloseIcon = () => { +// return ( +// +// +// +// ); +// }; + +export const LogoIcon = () => { + return ( + + + + ); +}; + +export const DiscordIcon = (props: any) => { + return ( + + + + + + + + + + + ); +}; diff --git a/packages/app/src/components/contact-modal/index.tsx b/packages/app/src/components/contact-modal/index.tsx new file mode 100644 index 0000000000..2c2d75430d --- /dev/null +++ b/packages/app/src/components/contact-modal/index.tsx @@ -0,0 +1,141 @@ +import { createPortal } from 'react-dom'; +import Fade from '@mui/material/Fade'; +import GitHubIcon from '@mui/icons-material/GitHub'; +import RedditIcon from '@mui/icons-material/Reddit'; +import TelegramIcon from '@mui/icons-material/Telegram'; +import TwitterIcon from '@mui/icons-material/Twitter'; +import CloseIcon from '@mui/icons-material/Close'; + +import { LogoIcon, DiscordIcon } from './icons'; +import logo from './affine-text-logo.png'; +import { + StyledModalContainer, + StyledModalWrapper, + StyledYellowBall, + StyledBlueBall, + StyledBigLink, + StyledSmallLink, + StyledSubTitle, + StyledLeftContainer, + StyledRightContainer, + StyledContent, + StyledBackdrop, + StyledLogo, + StyledModalHeader, + StyledModalHeaderLeft, + CloseButton, + StyledModalFooter, +} from './style'; + +const linkList = [ + { + icon: , + title: 'Github', + link: 'https://github.com/toeverything/AFFiNE', + }, + { + icon: , + title: 'Reddit', + link: 'https://www.reddit.com/r/Affine/', + }, + { + icon: , + title: 'Twitter', + link: 'https://twitter.com/AffineOfficial', + }, + { + icon: , + title: 'Telegram', + link: 'https://t.me/affineworkos', + }, + { + icon: , + title: 'Discord', + link: 'https://discord.gg/Arn7TqJBvG', + }, +]; +const rightLinkList = [ + { + icon: , + title: 'Official Website AFFiNE.pro', + link: 'https://affine.pro', + }, + { + icon: , + title: 'Check Our Docs Open Source', + link: 'https://github.com/toeverything/AFFiNE', + }, +]; + +type TransitionsModalProps = { + open: boolean; + onClose: () => void; +}; + +export const ContactModal = ({ open, onClose }: TransitionsModalProps) => { + return createPortal( + + + + + + + + + + + 2.0 + live demo + + { + onClose(); + }} + > + + + + + + + {rightLinkList.map(({ icon, title, link }) => { + return ( + + {icon} + {title} + + ); + })} + + + + Get in touch! + Join our community. + + {linkList.map(({ icon, title, link }) => { + return ( + + {icon} + {title} + + ); + })} + + + + + + + What is the different from the affine 1.0? + + + Copyright © 2022 Toeverything + + + + , + document.body + ); +}; + +export default ContactModal; diff --git a/packages/app/src/components/contact-modal/style.ts b/packages/app/src/components/contact-modal/style.ts new file mode 100644 index 0000000000..1527fa6faa --- /dev/null +++ b/packages/app/src/components/contact-modal/style.ts @@ -0,0 +1,216 @@ +import { styled } from '@/styles'; + +export const StyledModalContainer = styled('div')(({ theme }) => { + return { + width: '100vw', + height: '100vh', + position: 'fixed', + left: '0', + top: '0', + zIndex: theme.zIndex.modal, + }; +}); + +export const StyledModalWrapper = styled('div')(({ theme }) => { + return { + width: '1000px', + height: '626px', + background: theme.colors.popoverBackground, + padding: '0 48px', + borderRadius: '20px', + position: 'absolute', + left: 0, + right: 0, + top: 0, + bottom: 0, + margin: 'auto', + }; +}); + +export const StyledYellowBall = styled('div')` + position: absolute; + top: 189px; + left: 186px; + display: block; + width: 122px; + height: 122px; + background-color: #dda82a; + opacity: 0.45; + filter: blur(78px); +`; +export const StyledBlueBall = styled('div')` + content: ''; + position: absolute; + top: 332px; + left: 296px; + display: block; + width: 122px; + height: 122px; + background-color: #4461f2; + filter: blur(78px); +`; + +export const StyledBigLink = styled('a')(({ theme }) => { + return { + width: '335px', + height: '110px', + marginBottom: '52px', + display: 'flex', + alignItems: 'center', + fontSize: '24px', + lineHeight: '36px', + padding: '0 24px', + fontWeight: '600', + color: theme.colors.textColor, + borderRadius: '10px', + + ':visited': { + color: theme.colors.textColor, + }, + ':hover': { + color: theme.colors.primaryColor, + background: theme.colors.hoverBackground, + }, + ':last-of-type': { + marginBottom: 0, + }, + svg: { + width: '50px', + height: '50px', + marginRight: '40px', + color: theme.colors.primaryColor, + }, + p: { + width: '197px', + height: '73px', + }, + }; +}); +export const StyledSmallLink = styled('a')(({ theme }) => { + return { + width: '214px', + height: '37px', + display: 'flex', + alignItems: 'center', + fontSize: '18px', + fontWeight: '500', + paddingLeft: '24px', + borderRadius: '5px', + color: theme.colors.textColor, + ':visited': { + color: theme.colors.textColor, + }, + ':hover': { + color: theme.colors.primaryColor, + background: theme.colors.hoverBackground, + }, + svg: { + width: '22px', + marginRight: '30px', + color: theme.colors.primaryColor, + }, + }; +}); +export const StyledSubTitle = styled('div')(({ theme }) => { + return { + width: '189px', + fontSize: '18px', + fontWeight: '600', + color: theme.colors.textColor, + marginBottom: '24px', + }; +}); + +export const StyledLeftContainer = styled('div')({ + // height: '100%', + display: 'flex', + flexDirection: 'column', + justifyContent: 'space-between', +}); +export const StyledRightContainer = styled('div')({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'flex-end', +}); + +export const StyledContent = styled('div')({ + height: '276px', + width: '100%', + padding: '0 160px', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + color: '#3A4C5C', + marginTop: '100px', +}); + +export const StyledBackdrop = styled('div')(({ theme }) => { + return { width: '100%', height: '100%', background: 'rgba(58, 76, 92, 0.2)' }; +}); +export const StyledLogo = styled('img')({ + height: '22px', + width: 'auto', +}); + +export const StyledModalHeader = styled('div')(({ theme }) => { + return { + height: '30px', + marginTop: '54px', + padding: '0 48px', + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + }; +}); + +export const StyledModalHeaderLeft = styled('div')(({ theme }) => { + return { + display: 'flex', + alignItems: 'center', + color: theme.colors.primaryColor, + + 'span:first-of-type': { + fontSize: '28px', + lineHeight: 1, + fontWeight: '600', + margin: '0 12px', + }, + 'span:last-of-type': { + height: '26px', + border: `1px solid ${theme.colors.primaryColor}`, + borderRadius: '10px', + padding: '0 10px', + lineHeight: '26px', + fontSize: '16px', + }, + }; +}); + +export const CloseButton = styled('div')(({ theme }) => { + return { + width: '24px', + height: '24px', + borderRadius: '5px', + color: theme.colors.iconColor, + cursor: 'pointer', + ':hover': { + background: theme.colors.hoverBackground, + }, + }; +}); + +export const StyledModalFooter = styled('div')(({ theme }) => { + return { + fontSize: '14px', + lineHeight: '20px', + textAlign: 'center', + color: theme.colors.textColor, + + marginTop: '75px', + 'p:first-of-type': { + color: theme.colors.primaryColor, + marginBottom: '10px', + }, + }; +}); diff --git a/packages/app/src/components/editor-mode-switch/index.tsx b/packages/app/src/components/editor-mode-switch/index.tsx index 9558abc756..94bc5c5204 100644 --- a/packages/app/src/components/editor-mode-switch/index.tsx +++ b/packages/app/src/components/editor-mode-switch/index.tsx @@ -1,7 +1,6 @@ import React, { useState, useEffect, cloneElement } from 'react'; import { StyledAnimateRadioContainer, - StyledRadioMiddle, StyledMiddleLine, StyledRadioItem, StyledLabel, @@ -19,21 +18,21 @@ import { useEditor } from '@/components/editor-provider'; const PaperItem = ({ active }: { active?: boolean }) => { const { theme: { - colors: { highlight, disabled }, + colors: { iconColor, primaryColor }, }, } = useTheme(); - return ; + return ; }; const EdgelessItem = ({ active }: { active?: boolean }) => { const { theme: { - colors: { highlight, disabled }, + colors: { iconColor, primaryColor }, }, } = useTheme(); - return ; + return ; }; const AnimateRadioItem = ({ @@ -57,24 +56,11 @@ const AnimateRadioItem = ({ ); }; -const RadioMiddle = ({ - isHover, - direction, -}: { - isHover: boolean; - direction: 'left' | 'right' | 'middle'; -}) => { - return ( - - - - ); -}; - export const EditorModeSwitch = ({ isHover, style = {}, }: AnimateRadioProps) => { + const { mode: themeMode } = useTheme(); const { mode, setMode } = useEditor(); const modifyRadioItemStatus = (): RadioItemStatus => { return { @@ -124,7 +110,7 @@ export const EditorModeSwitch = ({ setRadioItemStatus(modifyRadioItemStatus()); }} /> - + ( - ({ shrink }) => { + ({ shrink, theme }) => { const animateScaleStretch = keyframes`${toString( spring({ width: '36px' }, { width: '160px' }, { preset: 'gentle' }) )}`; @@ -27,7 +27,7 @@ export const StyledAnimateRadioContainer = styled('div')<{ shrink: boolean }>( return { height: '36px', borderRadius: '18px', - background: '#F1F3FF', + background: theme.colors.hoverBackground, position: 'relative', display: 'flex', transition: `background ${ANIMATE_DURATION}ms`, @@ -36,31 +36,21 @@ export const StyledAnimateRadioContainer = styled('div')<{ shrink: boolean }>( } ); -export const StyledRadioMiddle = styled('div')<{ +export const StyledMiddleLine = styled('div')<{ hidden: boolean; -}>(({ hidden }) => { + dark: boolean; +}>(({ hidden, dark }) => { return { width: '1px', - height: '100%', - position: 'relative', + height: '16px', + background: dark ? '#4d4c53' : '#D0D7E3', + top: '0', + bottom: '0', + margin: 'auto', opacity: hidden ? '0' : '1', }; }); -export const StyledMiddleLine = styled('div')<{ hidden: boolean }>( - ({ hidden }) => { - return { - width: '1px', - height: '16px', - background: '#D0D7E3', - top: '0', - bottom: '0', - margin: 'auto', - opacity: hidden ? '0' : '1', - }; - } -); - export const StyledRadioItem = styled('div')<{ status: ItemStatus; active: boolean; @@ -89,7 +79,7 @@ export const StyledRadioItem = styled('div')<{ : {}; const { - colors: { highlight, disabled }, + colors: { iconColor, primaryColor }, } = theme; return { width: '0', @@ -97,7 +87,7 @@ export const StyledRadioItem = styled('div')<{ display: 'flex', cursor: 'pointer', overflow: 'hidden', - color: active ? highlight : disabled, + color: active ? primaryColor : iconColor, ...dynamicStyle, }; }); diff --git a/packages/app/src/components/faq/icons.tsx b/packages/app/src/components/faq/icons.tsx index 9a4eba69ae..7c8797265d 100644 --- a/packages/app/src/components/faq/icons.tsx +++ b/packages/app/src/components/faq/icons.tsx @@ -43,3 +43,17 @@ export const KeyboardIcon = () => { ); }; + +export const CloseIcon = () => { + return ( + + + + ); +}; diff --git a/packages/app/src/components/faq/index.tsx b/packages/app/src/components/faq/index.tsx index 2eec3dbf3d..af9d84a2d0 100644 --- a/packages/app/src/components/faq/index.tsx +++ b/packages/app/src/components/faq/index.tsx @@ -1,21 +1,20 @@ -import React from 'react'; -import { StyledFAQ, StyledIconWrapper, StyledFAQWrapper } from './style'; -import { ContactIcon, HelpIcon, KeyboardIcon } from './icons'; +import { useState } from 'react'; +import { + StyledFAQ, + StyledIconWrapper, + StyledFAQWrapper, + StyledTransformIcon, +} from './style'; +import { CloseIcon, ContactIcon, HelpIcon, KeyboardIcon } from './icons'; import Grow from '@mui/material/Grow'; import { Tooltip } from '../tooltip'; -import { Modal } from '@/components/modal'; +import ContactModal from '@/components/contact-modal'; +import ShortcutsModal from '@/components/shortcuts-modal'; const Contact = () => { - const [openModal, setOpenModal] = React.useState(false); + const [openModal, setOpenModal] = useState(false); return ( <> - { - setOpenModal(false); - }} - > - modal content - + setOpenModal(false)} /> { @@ -28,32 +27,59 @@ const Contact = () => { > ); }; -export const FAQ = () => { - const [showContent, setShowContent] = React.useState(false); - return ( - { - setShowContent(true); - }} - onMouseLeave={() => { - setShowContent(false); - }} - > - - - - - - - - - - - - - - +const Shortcuts = () => { + const [openModal, setOpenModal] = useState(false); + return ( + <> + { + setOpenModal(false); + }} + /> + + + { + setOpenModal(true); + }} + > + + + + > + ); +}; +export const FAQ = () => { + const [showContent, setShowContent] = useState(false); + return ( + <> + { + setShowContent(true); + }} + onMouseLeave={() => { + setShowContent(false); + }} + > + + + + + + + + + + + + + + + + + > ); }; diff --git a/packages/app/src/components/faq/style.ts b/packages/app/src/components/faq/style.ts index a5710e2fb9..f82ed8ccba 100644 --- a/packages/app/src/components/faq/style.ts +++ b/packages/app/src/components/faq/style.ts @@ -4,35 +4,55 @@ export const StyledFAQ = styled('div')(({ theme }) => { return { width: '32px', height: '32px', - backgroundColor: '#fff', - color: theme.colors.disabled, + color: theme.colors.iconColor, position: 'fixed', right: '30px', bottom: '30px', borderRadius: '50%', - zIndex: 1000, + zIndex: theme.zIndex.popover, ':hover': { - backgroundColor: '#F1F3FF', - color: theme.colors.highlight, + backgroundColor: theme.colors.popoverBackground, + color: theme.colors.primaryColor, }, }; }); - +export const StyledTransformIcon = styled.div<{ in: boolean }>( + ({ in: isIn, theme }) => ({ + height: '32px', + width: '32px', + borderRadius: '50%', + position: 'absolute', + left: '0', + right: '0', + bottom: '0', + top: '0', + margin: 'auto', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + opacity: isIn ? 1 : 0, + backgroundColor: isIn + ? theme.colors.hoverBackground + : theme.colors.pageBackground, + }) +); export const StyledIconWrapper = styled('div')(({ theme }) => { return { - color: theme.colors.disabled, + color: theme.colors.iconColor, marginBottom: '24px', display: 'flex', justifyContent: 'center', alignItems: 'center', cursor: 'pointer', - backgroundColor: 'transparent', + backgroundColor: theme.colors.pageBackground, borderRadius: '50%', width: '32px', height: '32px', + transition: 'background-color 0.3s', + position: 'relative', ':hover': { - color: theme.colors.highlight, - backgroundColor: '#F1F3FF', + color: theme.colors.primaryColor, + backgroundColor: theme.colors.hoverBackground, }, }; }); @@ -43,12 +63,9 @@ export const StyledFAQWrapper = styled('div')(({ theme }) => { bottom: '100%', left: '0', width: '100%', - color: theme.colors.disabled, + color: theme.colors.iconColor, ':hover': { - '> svg': { - color: theme.colors.highlight, - }, - color: theme.colors.highlight, + color: theme.colors.popoverColor, }, }; }); diff --git a/packages/app/src/components/modal/index.tsx b/packages/app/src/components/modal/index.tsx deleted file mode 100644 index b734727f30..0000000000 --- a/packages/app/src/components/modal/index.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import ModalUnstyled from '@mui/base/ModalUnstyled'; -import { styled } from '@/styles'; -import Fade from '@mui/material/Fade'; - -import { ClickAwayListener } from '@mui/material'; - -const StyledModal = styled(ModalUnstyled)` - position: fixed; - z-index: 1300; - right: 0; - bottom: 0; - top: 0; - left: 0; - display: flex; - align-items: center; - justify-content: center; -`; - -type TransitionsModalProps = { - open: boolean; - onClose: () => void; - children: JSX.Element; -}; - -export const Modal = (props: TransitionsModalProps) => { - return ( - - - - {props.children} - - - - ); -}; diff --git a/packages/app/src/components/popover/index.tsx b/packages/app/src/components/popover/index.tsx index f02d38bddd..0d0f790984 100644 --- a/packages/app/src/components/popover/index.tsx +++ b/packages/app/src/components/popover/index.tsx @@ -21,12 +21,12 @@ const StyledPopoverWrapper = styled('div')({ paddingTop: '46px', zIndex: 1000, }); -const StyledPopover = styled('div')(() => { +const StyledPopover = styled('div')(({ theme }) => { return { width: '248px', - background: '#fff', - boxShadow: - '0px 1px 10px -6px rgba(24, 39, 75, 0.5), 0px 3px 16px -6px rgba(24, 39, 75, 0.04)', + background: theme.colors.popoverBackground, + boxShadow: theme.shadow.popover, + color: theme.colors.popoverColor, borderRadius: '10px 0px 10px 10px', padding: '8px 4px', position: 'absolute', diff --git a/packages/app/src/components/shortcuts-modal/config.ts b/packages/app/src/components/shortcuts-modal/config.ts new file mode 100644 index 0000000000..707ff48a20 --- /dev/null +++ b/packages/app/src/components/shortcuts-modal/config.ts @@ -0,0 +1,66 @@ +export const macKeyboardShortcuts = { + Undo: 'cmd + Z', + Redo: 'cmd + shift + Z', + Bold: 'cmd + B', + Italic: 'cmd + I', + Underline: 'cmd + U', + Strikethrough: 'cmd + Shit + S', + 'Inline code': ' cmd + E', + Link: 'cmd + K', + 'Body text': 'cmd + Option + 0', + 'Heading 1': 'cmd + Option + 1', + 'Heading 2': 'cmd + Option + 2', + 'Heading 3': 'cmd + Option + 3', + 'Heading 4': 'cmd + Option + 4', + 'Heading 5': 'cmd + Option + 5', + 'Heading 6': 'cmd + Option + 6', + 'Increase indent': 'Tab', + 'Reduce indent': 'Shift + Tab', +}; + +export const macMarkdownShortcuts = { + Bold: '**Text**', + Italic: '*Text*', + Underline: '~Text~', + Strikethrough: '~~Text~~', + 'Inline code': '`Code`', + 'Heading 1': '# + Space', + 'Heading 2': '## + Space', + 'Heading 3': '### + Space', + 'Heading 4': '#### + Space', + 'Heading 5': '##### + Space', + 'Heading 6': '###### + Space', +}; + +export const windowsKeyboardShortcuts = { + Undo: 'Ctrl + Z', + Redo: 'Ctrl + Y', + Bold: 'Ctrl + B', + Italic: 'Ctrl + I', + Underline: 'Ctrl + U', + Strikethrough: 'Ctrl + Shit + S', + 'Inline code': ' Ctrl + E', + Link: 'Ctrl + K', + 'Body text': 'Ctrl + Shift + 0', + 'Heading 1': 'Ctrl + Shift + 1', + 'Heading 2': 'Ctrl + Shift + 2', + 'Heading 3': 'Ctrl + Shift + 3', + 'Heading 4': 'Ctrl + Shift + 4', + 'Heading 5': 'Ctrl + Shift + 5', + 'Heading 6': 'Ctrl + Shift + 6', + 'Increase indent': 'Tab', + 'Reduce indent': 'Shift + Tab', +}; +export const winMarkdownShortcuts = { + Bold: '**Text** + Space', + Italic: '*Text* + Space', + Underline: '~Text~ + Space', + Strikethrough: '~~Text~~ + Space', + 'Inline code': '`Code` + Space', + 'Heading 1': '# + Space', + 'Heading 2': '## + Space', + 'Heading 3': '### + Space', + 'Heading 4': '#### + Space', + 'Heading 5': '##### + Space', + 'Heading 6': '###### + Space', +}; diff --git a/packages/app/src/components/shortcuts-modal/icons.tsx b/packages/app/src/components/shortcuts-modal/icons.tsx new file mode 100644 index 0000000000..13eb2d3cea --- /dev/null +++ b/packages/app/src/components/shortcuts-modal/icons.tsx @@ -0,0 +1,27 @@ +export const CloseIcon = () => { + return ( + + + + ); +}; + +export const KeyboardIcon = () => { + return ( + + + + ); +}; diff --git a/packages/app/src/components/shortcuts-modal/index.tsx b/packages/app/src/components/shortcuts-modal/index.tsx new file mode 100644 index 0000000000..2d079525f7 --- /dev/null +++ b/packages/app/src/components/shortcuts-modal/index.tsx @@ -0,0 +1,78 @@ +import { createPortal } from 'react-dom'; +import { KeyboardIcon } from './icons'; +import { + StyledListItem, + StyledModalHeader, + StyledShortcutsModal, + StyledSubTitle, + StyledTitle, + CloseButton, +} from './style'; +import { + macKeyboardShortcuts, + macMarkdownShortcuts, + windowsKeyboardShortcuts, + winMarkdownShortcuts, +} from '@/components/shortcuts-modal/config'; +import CloseIcon from '@mui/icons-material/Close'; +import Slide from '@mui/material/Slide'; +type ModalProps = { + open: boolean; + onClose: () => void; +}; + +const isMac = () => { + return /macintosh|mac os x/i.test(navigator.userAgent); +}; + +export const ShortcutsModal = ({ open, onClose }: ModalProps) => { + const markdownShortcuts = isMac() + ? macMarkdownShortcuts + : winMarkdownShortcuts; + const keyboardShortcuts = isMac() + ? macKeyboardShortcuts + : windowsKeyboardShortcuts; + return createPortal( + + + <> + + + + Shortcuts + + + { + onClose(); + }} + > + + + + Keyboard shortcuts + {Object.entries(keyboardShortcuts).map(([title, shortcuts]) => { + return ( + + {title} + {shortcuts} + + ); + })} + Markdown shortcuts + {Object.entries(markdownShortcuts).map(([title, shortcuts]) => { + return ( + + {title} + {shortcuts} + + ); + })} + > + + , + document.body + ); +}; + +export default ShortcutsModal; diff --git a/packages/app/src/components/shortcuts-modal/style.ts b/packages/app/src/components/shortcuts-modal/style.ts new file mode 100644 index 0000000000..e1924b513f --- /dev/null +++ b/packages/app/src/components/shortcuts-modal/style.ts @@ -0,0 +1,65 @@ +import { styled } from '@/styles'; + +export const StyledShortcutsModal = styled.div(({ theme }) => ({ + width: '268px', + height: '66vh', + backgroundColor: theme.colors.popoverBackground, + boxShadow: theme.shadow.popover, + color: theme.colors.popoverColor, + padding: '8px 16px', + overflow: 'auto', + boxRadius: '10px', + position: 'fixed', + right: '12px', + top: '0', + bottom: '0', + margin: 'auto', + zIndex: theme.zIndex.modal, +})); +export const StyledTitle = styled.div(({ theme }) => ({ + color: theme.colors.textColor, + fontWeight: '600', + fontSize: theme.font.sm, + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + svg: { + width: '20px', + marginRight: '14px', + color: theme.colors.primaryColor, + }, +})); +export const StyledSubTitle = styled.div(({ theme }) => ({ + color: theme.colors.textColor, + fontWeight: '500', + fontSize: '12px', + height: '36px', + lineHeight: '36px', +})); +export const StyledModalHeader = styled.div(({ theme }) => ({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + height: '36px', +})); + +export const StyledListItem = styled.div(({ theme }) => ({ + height: '32px', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + fontSize: theme.font.xs, +})); + +export const CloseButton = styled('div')(({ theme }) => { + return { + width: '24px', + height: '24px', + borderRadius: '5px', + color: theme.colors.iconColor, + cursor: 'pointer', + ':hover': { + background: theme.colors.hoverBackground, + }, + }; +}); diff --git a/packages/app/src/components/simple-counter/index.ts b/packages/app/src/components/simple-counter/index.ts index 6f99529c1b..8b7f8cbe96 100644 --- a/packages/app/src/components/simple-counter/index.ts +++ b/packages/app/src/components/simple-counter/index.ts @@ -27,7 +27,7 @@ export class Counter extends LitElement { static styles = css` .counter-container { display: flex; - color: var(--color-primary); + color: var(--affine-text-color); } button { margin: 0 5px; diff --git a/packages/app/src/components/theme-mode-switch/icons.tsx b/packages/app/src/components/theme-mode-switch/icons.tsx new file mode 100644 index 0000000000..43d9688d08 --- /dev/null +++ b/packages/app/src/components/theme-mode-switch/icons.tsx @@ -0,0 +1,44 @@ +import type { DOMAttributes, CSSProperties } from 'react'; +type IconProps = { + style?: CSSProperties; +} & DOMAttributes; + +export const MoonIcon = ({ style = {}, ...props }: IconProps) => { + return ( + + + + ); +}; + +export const SunIcon = ({ style = {}, ...props }: IconProps) => { + return ( + + + + ); +}; diff --git a/packages/app/src/components/theme-mode-switch/index.tsx b/packages/app/src/components/theme-mode-switch/index.tsx new file mode 100644 index 0000000000..324a3cfdae --- /dev/null +++ b/packages/app/src/components/theme-mode-switch/index.tsx @@ -0,0 +1,46 @@ +import { useState } from 'react'; +import { useTheme } from '@/styles'; +import { MoonIcon, SunIcon } from './icons'; +import { StyledThemeModeSwitch, StyledSwitchItem } from './style'; + +export const ThemeModeSwitch = () => { + const { mode, changeMode } = useTheme(); + const [isHover, setIsHover] = useState(false); + const [firstTrigger, setFirstTrigger] = useState(false); + return ( + { + setIsHover(true); + if (!firstTrigger) { + setFirstTrigger(true); + } + }} + onMouseLeave={() => { + setIsHover(false); + }} + > + { + changeMode('light'); + }} + > + + + { + changeMode('dark'); + }} + > + + + + ); +}; + +export default ThemeModeSwitch; diff --git a/packages/app/src/components/theme-mode-switch/style.ts b/packages/app/src/components/theme-mode-switch/style.ts new file mode 100644 index 0000000000..b40f7d3439 --- /dev/null +++ b/packages/app/src/components/theme-mode-switch/style.ts @@ -0,0 +1,67 @@ +import { keyframes, styled } from '@/styles'; +import { CSSProperties } from 'react'; +// @ts-ignore +import spring, { toString } from 'css-spring'; + +const ANIMATE_DURATION = 400; + +export const StyledThemeModeSwitch = styled('div')({ + width: '32px', + height: '32px', + borderRadius: '5px', + overflow: 'hidden', + backgroundColor: 'transparent', + position: 'relative', +}); +export const StyledSwitchItem = styled('div')<{ + active: boolean; + isHover: boolean; + firstTrigger: boolean; +}>(({ active, isHover, firstTrigger, theme }) => { + const activeRaiseAnimate = keyframes`${toString( + spring({ top: '0' }, { top: '-100%' }, { preset: 'gentle' }) + )}`; + const raiseAnimate = keyframes`${toString( + spring({ top: '100%' }, { top: '0' }, { preset: 'gentle' }) + )}`; + const activeDeclineAnimate = keyframes`${toString( + spring({ top: '-100%' }, { top: '0' }, { preset: 'gentle' }) + )}`; + const declineAnimate = keyframes`${toString( + spring({ top: '0' }, { top: '100%' }, { preset: 'gentle' }) + )}`; + const activeStyle = active + ? { + color: theme.colors.iconColor, + top: '0', + animation: firstTrigger + ? `${ + isHover ? activeRaiseAnimate : activeDeclineAnimate + } ${ANIMATE_DURATION}ms forwards` + : 'unset', + animationDirection: isHover ? 'normal' : 'alternate', + } + : ({ + top: '100%', + color: theme.colors.primaryColor, + backgroundColor: theme.colors.hoverBackground, + animation: firstTrigger + ? `${ + isHover ? raiseAnimate : declineAnimate + } ${ANIMATE_DURATION}ms forwards` + : 'unset', + animationDirection: isHover ? 'normal' : 'alternate', + } as CSSProperties); + + return { + width: '32px', + height: '32px', + display: 'flex', + position: 'absolute', + left: '0', + justifyContent: 'center', + alignItems: 'center', + cursor: 'pointer', + ...activeStyle, + }; +}); diff --git a/packages/app/src/components/tooltip/Tooltip.tsx b/packages/app/src/components/tooltip/Tooltip.tsx index bea79371c7..8b33bb9b35 100644 --- a/packages/app/src/components/tooltip/Tooltip.tsx +++ b/packages/app/src/components/tooltip/Tooltip.tsx @@ -30,7 +30,7 @@ const useTooltipStyle = (): CSSProperties => { return { boxShadow: '1px 1px 4px rgba(0, 0, 0, 0.14)', padding: '4px 12px', - backgroundColor: theme.colors.highlight, + backgroundColor: theme.colors.primaryColor, color: '#fff', fontSize: theme.font.xs, }; diff --git a/packages/app/src/pages/affine.tsx b/packages/app/src/pages/affine.tsx index 73b35a6689..2d5bbe9b30 100644 --- a/packages/app/src/pages/affine.tsx +++ b/packages/app/src/pages/affine.tsx @@ -1,5 +1,23 @@ +import { styled } from '@/styles'; +import { ThemeModeSwitch } from '@/components/theme-mode-switch'; + +export const StyledHeader = styled('div')({ + height: '60px', + width: '100vw', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + position: 'relative', + padding: '0 22px', + borderBottom: '1px solid #e5e5e5', +}); + const Affine = () => { - return affine page; + return ( + + + + ); }; export default Affine; diff --git a/packages/app/src/pages/index.tsx b/packages/app/src/pages/index.tsx index aa8e9ae95b..5089d75b1b 100644 --- a/packages/app/src/pages/index.tsx +++ b/packages/app/src/pages/index.tsx @@ -12,12 +12,14 @@ const StyledEditorContainer = styled('div')(({ theme }) => { }; }); -const StyledPage = styled('div')({ - height: '100vh', - display: 'flex', - flexDirection: 'column', - backgroundColor: 'var(--page-background-color)', - transition: 'background-color .5s', +const StyledPage = styled('div')(({ theme }) => { + return { + height: '100vh', + display: 'flex', + flexDirection: 'column', + backgroundColor: theme.colors.pageBackground, + transition: 'background-color .5s', + }; }); const DynamicEditor = dynamic(() => import('../components/editor'), { diff --git a/packages/app/src/pages/temporary.css b/packages/app/src/pages/temporary.css index b9b56e502a..de63ef2492 100644 --- a/packages/app/src/pages/temporary.css +++ b/packages/app/src/pages/temporary.css @@ -1,44 +1,44 @@ debug-menu { display: none !important; } -.affine-editor-container { - height: 100%; - padding: 0 !important; -} -.affine-default-page-block-container { - width: 720px; - height: 100%; - margin: 0 auto; -} +/*.affine-editor-container {*/ +/* height: 100%;*/ +/* padding: 0 !important;*/ +/*}*/ +/*.affine-default-page-block-container {*/ +/* width: 720px;*/ +/* height: 100%;*/ +/* margin: 0 auto;*/ +/*}*/ -u { - text-decoration: none; - border-bottom: 1px solid #4c6275 !important; -} -u::after { - display: none; -} +/*u {*/ +/* text-decoration: none;*/ +/* border-bottom: 1px solid #4c6275 !important;*/ +/*}*/ +/*u::after {*/ +/* display: none;*/ +/*}*/ -.affine-paragraph-block-container.text { - margin-top: 18px !important; -} +/*.affine-paragraph-block-container.text {*/ +/* margin-top: 18px !important;*/ +/*}*/ -.affine-default-page-block-title { - width: 100%; -} -s { - text-decoration: line-through !important; -} +/*.affine-default-page-block-title {*/ +/* width: 100%;*/ +/*}*/ +/*s {*/ +/* text-decoration: line-through !important;*/ +/*}*/ -.affine-edgeless-page-block-container { - height: 100% !important; -} -.affine-block-children-container.edgeless { - height: 100% !important; -} -.affine-list-rich-text-wrapper > div { - box-sizing: content-box; - color: var(--affine-highlight-color); - min-width: unset !important; - max-width: 26px; -} +/*.affine-edgeless-page-block-container {*/ +/* height: 100% !important;*/ +/*}*/ +/*.affine-block-children-container.edgeless {*/ +/* height: 100% !important;*/ +/*}*/ +/*.affine-list-rich-text-wrapper > div {*/ +/* box-sizing: content-box;*/ +/* color: var(--affine-highlight-color);*/ +/* min-width: unset !important;*/ +/* max-width: 26px;*/ +/*}*/ diff --git a/packages/app/src/styles/theme.ts b/packages/app/src/styles/theme.ts index 5b00dd2583..fb011861c3 100644 --- a/packages/app/src/styles/theme.ts +++ b/packages/app/src/styles/theme.ts @@ -1,47 +1,109 @@ import '@emotion/react'; -import { AffineTheme, ThemeMode } from './types'; +import { AffineTheme, AffineThemeCSSVariables, ThemeMode } from './types'; + +const basicFontFamily = + 'apple-system, BlinkMacSystemFont,Helvetica Neue, Tahoma, PingFang SC, Microsoft Yahei, Arial,Hiragino Sans GB, sans-serif, Apple Color Emoji, Segoe UI Emoji,Segoe UI Symbol, Noto Color Emoji'; export const lightTheme: AffineTheme = { colors: { - primary: '#3A4C5C', - highlight: '#7389FD', - disabled: '#9096A5', - background: '#fff', + primaryColor: '#6880FF', + + pageBackground: '#fff', + hoverBackground: '#F1F3FF', + popoverBackground: '#fff', + codeBackground: '#f2f5f9', + + textColor: '#3A4C5C', + iconColor: '#9096A5', + linkColor: '#6880FF', + linkColor2: '#6880FF', + linkVisitedColor: '#ABB8FE', + popoverColor: '#4C6275', + codeColor: '#517ea6', + quoteColor: '#4C6275', + placeHolderColor: '#C7C7C7', + selectedColor: 'rgba(104, 128, 255, 0.1)', }, font: { xs: '12px', sm: '16px', base: '18px', + family: `Avenir Next, ${basicFontFamily}`, + family2: `Roboto Mono, ${basicFontFamily}`, + }, + zIndex: { + modal: 1000, + popover: 100, + }, + shadow: { + popover: + '4px 4px 7px rgba(58, 76, 92, 0.04), -4px -4px 13px rgba(58, 76, 92, 0.02), 6px 6px 36px rgba(58, 76, 92, 0.06);', + modal: + '4px 4px 7px rgba(58, 76, 92, 0.04), -4px -4px 13px rgba(58, 76, 92, 0.02), 6px 6px 36px rgba(58, 76, 92, 0.06);', }, }; export const darkTheme: AffineTheme = { ...lightTheme, colors: { - primary: '#fff', - highlight: '#7389FD', - disabled: '#9096A5', - background: '#3d3c3f', + primaryColor: '#6880FF', + + pageBackground: '#2c2c2c', + hoverBackground: '#3C3C42', + popoverBackground: '#1F2021', + codeBackground: '#505662', + + textColor: '#fff', + iconColor: '#9096A5', + linkColor: '#6880FF', + linkColor2: '#7D91FF', + linkVisitedColor: '#505FAB', + popoverColor: '#A9B1C6', + codeColor: '#BDDBFD', + quoteColor: '#A9B1C6', + placeHolderColor: '#C7C7C7', + selectedColor: 'rgba(240, 242, 255, 0.8)', + }, + shadow: { + popover: + '0px 1px 10px -6px rgba(24, 39, 75, 0.08), 0px 3px 16px -6px rgba(24, 39, 75, 0.04)', + modal: + '0px 1px 10px -6px rgba(24, 39, 75, 0.08), 0px 3px 16px -6px rgba(24, 39, 75, 0.04)', }, }; -export const globalThemeConstant = (mode: ThemeMode, theme: AffineTheme) => { - const isDark = mode === 'dark'; +export const globalThemeVariables: ( + mode: ThemeMode, + theme: AffineTheme +) => AffineThemeCSSVariables = (mode, theme) => { return { - '--page-background-color': theme.colors.background, - '--page-text-color': theme.colors.primary, + '--affine-primary-color': theme.colors.primaryColor, - // editor style variables - '--affine-primary-color': theme.colors.primary, - '--affine-muted-color': '#a6abb7', - '--affine-highlight-color': '#6880ff', - '--affine-placeholder-color': '#c7c7c7', - '--affine-selected-color': 'rgba(104, 128, 255, 0.1)', + '--affine-page-background': theme.colors.pageBackground, + '--affine-popover-background': theme.colors.popoverBackground, + '--affine-hover-background': theme.colors.hoverBackground, + '--affine-code-background': theme.colors.codeBackground, - '--affine-font-family': - 'Avenir Next, apple-system, BlinkMacSystemFont,Helvetica Neue, Tahoma, PingFang SC, Microsoft Yahei, Arial,Hiragino Sans GB, sans-serif, Apple Color Emoji, Segoe UI Emoji,Segoe UI Symbol, Noto Color Emoji', + '--affine-text-color': theme.colors.textColor, + '--affine-link-color': theme.colors.linkColor, + // In dark mode, normal text`s (not bold) color + '--affine-link-color2': theme.colors.linkColor2, + '--affine-link-visited-color': theme.colors.linkVisitedColor, + '--affine-icon-color': theme.colors.iconColor, + '--affine-popover-color': theme.colors.popoverColor, + '--affine-code-color': theme.colors.codeColor, + '--affine-quote-color': theme.colors.quoteColor, + '--affine-selected-color': theme.colors.selectedColor, + '--affine-placeholder-color': theme.colors.placeHolderColor, - '--affine-font-family2': - 'Roboto Mono, apple-system, BlinkMacSystemFont,Helvetica Neue, Tahoma, PingFang SC, Microsoft Yahei, Arial,Hiragino Sans GB, sans-serif, Apple Color Emoji, Segoe UI Emoji,Segoe UI Symbol, Noto Color Emoji', + '--affine-modal-shadow': theme.shadow.modal, + '--affine-popover-shadow': theme.shadow.popover, + + '--affine-font-xs': theme.font.xs, // tiny + '--affine-font-sm': theme.font.sm, // small + '--affine-font-base': theme.font.base, + + '--affine-font-family': theme.font.family, + '--affine-font-family2': theme.font.family2, }; }; diff --git a/packages/app/src/styles/themeProvider.tsx b/packages/app/src/styles/themeProvider.tsx index 4cdd4e9b00..307d71eba8 100644 --- a/packages/app/src/styles/themeProvider.tsx +++ b/packages/app/src/styles/themeProvider.tsx @@ -11,7 +11,7 @@ import { ThemeProviderProps, ThemeProviderValue, } from './types'; -import { lightTheme, darkTheme, globalThemeConstant } from './theme'; +import { lightTheme, darkTheme, globalThemeVariables } from './theme'; import { SystemThemeHelper, localStorageThemeHelper } from './utils'; export const ThemeContext = createContext({ @@ -67,7 +67,7 @@ export const ThemeProvider = ({ diff --git a/packages/app/src/styles/types.ts b/packages/app/src/styles/types.ts index 7c042957c5..da54956d91 100644 --- a/packages/app/src/styles/types.ts +++ b/packages/app/src/styles/types.ts @@ -13,16 +13,71 @@ export type ThemeProviderValue = { export interface AffineTheme { colors: { - primary: string; - highlight: string; - disabled: string; - background: string; + primaryColor: string; + + pageBackground: string; + popoverBackground: string; + hoverBackground: string; + codeBackground: string; + + textColor: string; + linkColor: string; + // In dark mode, normal text`s (not bold) color + linkColor2: string; + linkVisitedColor: string; + iconColor: string; + popoverColor: string; + codeColor: string; + quoteColor: string; + placeHolderColor: string; + selectedColor: string; }; font: { xs: string; // tiny sm: string; // small base: string; + + family: string; + family2: string; }; + zIndex: { + modal: number; + popover: number; + }; + shadow: { + modal: string; + popover: string; + }; +} + +export interface AffineThemeCSSVariables { + '--affine-primary-color': AffineTheme['colors']['primaryColor']; + '--affine-page-background': AffineTheme['colors']['pageBackground']; + '--affine-popover-background': AffineTheme['colors']['popoverBackground']; + '--affine-hover-background': AffineTheme['colors']['hoverBackground']; + '--affine-code-background': AffineTheme['colors']['codeBackground']; + + '--affine-text-color': AffineTheme['colors']['textColor']; + '--affine-link-color': AffineTheme['colors']['linkColor']; + // In dark mode, normal text`s (not bold) color + '--affine-link-color2': AffineTheme['colors']['linkColor2']; + '--affine-link-visited-color': AffineTheme['colors']['linkVisitedColor']; + '--affine-icon-color': AffineTheme['colors']['iconColor']; + '--affine-popover-color': AffineTheme['colors']['popoverColor']; + '--affine-code-color': AffineTheme['colors']['codeColor']; + '--affine-quote-color': AffineTheme['colors']['quoteColor']; + '--affine-placeholder-color': AffineTheme['colors']['placeHolderColor']; + '--affine-selected-color': AffineTheme['colors']['selectedColor']; + + '--affine-modal-shadow': AffineTheme['shadow']['popover']; + '--affine-popover-shadow': AffineTheme['shadow']['modal']; + + '--affine-font-xs': AffineTheme['font']['xs']; // tiny + '--affine-font-sm': AffineTheme['font']['sm']; // small + '--affine-font-base': AffineTheme['font']['base']; + + '--affine-font-family': AffineTheme['font']['family']; + '--affine-font-family2': AffineTheme['font']['family2']; } declare module '@emotion/react' { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 514188f1c6..b40fe92f85 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,7 @@ importers: '@emotion/server': ^11.10.0 '@emotion/styled': ^11.10.4 '@mui/base': ^5.0.0-alpha.87 + '@mui/icons-material': ^5.10.9 '@mui/material': ^5.8.6 '@types/node': 18.7.18 '@types/react': 18.0.20 @@ -52,6 +53,7 @@ importers: '@emotion/server': 11.10.0_@emotion+css@11.10.0 '@emotion/styled': 11.10.4_yiaqs725o7pcd7rteavrnhgj4y '@mui/base': 5.0.0-alpha.101_7ey2zzynotv32rpkwno45fsx4e + '@mui/icons-material': 5.10.9_5fncb4nagb4cvvcnwamw2rozfa '@mui/material': 5.10.9_af5ln35zuaotaffazii6n6bke4 css-spring: 4.1.0 lit: 2.4.0 @@ -407,6 +409,23 @@ packages: resolution: {integrity: sha512-rqoFu4qww6KJBbXYhyRd9YXjwBHa3ylnBPSWbGf1bdfG0AYMKmVzg8zxkWvxAWOp97kvx3M2kNPb0xMIDZiogQ==} dev: false + /@mui/icons-material/5.10.9_5fncb4nagb4cvvcnwamw2rozfa: + resolution: {integrity: sha512-sqClXdEM39WKQJOQ0ZCPTptaZgqwibhj2EFV9N0v7BU1PO8y4OcX/a2wIQHn4fNuDjIZktJIBrmU23h7aqlGgg==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@mui/material': ^5.0.0 + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.19.0 + '@mui/material': 5.10.9_af5ln35zuaotaffazii6n6bke4 + '@types/react': 18.0.20 + react: 18.2.0 + dev: false + /@mui/material/5.10.9_af5ln35zuaotaffazii6n6bke4: resolution: {integrity: sha512-sdOzlgpCmyw48je+E7o9UGGJpgBaF+60FlTRpVpcd/z+LUhnuzzuis891yPI5dPPXLBDL/bO4SsGg51lgNeLBw==} engines: {node: '>=12.0.0'} @@ -1370,7 +1389,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.38.0_eslint@8.22.0 + '@typescript-eslint/parser': 5.38.0_76twfck5d7crjqrmw4yltga7zm debug: 3.2.7 eslint: 8.22.0 eslint-import-resolver-node: 0.3.6 @@ -1389,7 +1408,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.38.0_eslint@8.22.0 + '@typescript-eslint/parser': 5.38.0_76twfck5d7crjqrmw4yltga7zm array-includes: 3.1.5 array.prototype.flat: 1.3.0 debug: 2.6.9
+ + What is the different from the affine 1.0? + +
Copyright © 2022 Toeverything