/* eslint-disable max-lines */ /* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable filename-rules/match */ import { useEffect, useMemo, useState } from 'react'; import clsx from 'clsx'; import { CssVarsProvider, styled } from '@mui/joy/styles'; import { Box, Button, Container, Grid, SvgIcon, Typography } from '@mui/joy'; import GitHubIcon from '@mui/icons-material/GitHub'; import RedditIcon from '@mui/icons-material/Reddit'; import TelegramIcon from '@mui/icons-material/Telegram'; // eslint-disable-next-line no-restricted-imports import { useMediaQuery } from '@mui/material'; import LogoImage from './logo.png'; import CollaborationImage from './collaboration.png'; import PageImage from './page.png'; import ShapeImage from './shape.png'; import TaskImage from './task.png'; const DiscordIcon = (props: any) => { return ( ); }; const VenusContainer = styled(Container)({ margin: '1em auto', }); const Alternatives = styled(Box)<{ width: string }>(({ width }) => ({ position: 'relative', width: '24em', height: '128px', transform: 'translateY(-8px)', overflowY: 'hidden', '@media (max-width: 1024px)': { width, height: '48px', transform: 'translateY(0)', }, '& .scroll-element': { width: 'inherit', height: 'inherit', position: 'absolute', left: '0%', top: '0%', lineHeight: '96px', '@media (max-width: 1024px)': { lineHeight: '32px', }, }, '& .scroll-element.active': { animation: 'primary 500ms linear infinite', }, '.primary.active': { animation: 'primary 500ms linear infinite', }, '.secondary.active': { animation: 'secondary 500ms linear infinite', }, '@keyframes primary': { from: { top: '0%', }, to: { top: '-100%', }, }, '@keyframes secondary': { from: { top: '100%', }, to: { top: '0%', }, }, })); const _alternatives = ['Notion', 'Miro', 'Monday']; const _alternativesSize = [8, 6, 10]; const Product = () => { const [idx, setIdx] = useState(0); const [last, current] = useMemo( () => [ _alternatives[idx], _alternatives[idx + 1] ? _alternatives[idx + 1] : _alternatives[0], ], [idx] ); const maxWidth = useMemo(() => _alternativesSize[idx], [idx]); const [active, setActive] = useState(false); const matches = useMediaQuery('(max-width: 1024px)'); useEffect(() => { const handle = setInterval(() => { setActive(true); setTimeout( () => { setIdx(idx => (_alternatives[idx + 1] ? idx + 1 : 0)); setActive(false); }, matches ? 450 : 380 ); }, 2000); return () => clearInterval(handle); }, [matches]); return ( {last} {current} ); }; const AffineImage = styled('img')({ maxWidth: '100%', objectFit: 'contain', }); const GitHub = (props: { center?: boolean; flat?: boolean }) => { const matches = useMediaQuery('(max-width: 1024px)'); return ( ); }; export function App() { const matches = useMediaQuery('(max-width: 1024px)'); return ( div': { marginTop: '1em', }, }} > Open Source, Privacy First Alternative Affine is the next-generation collaborative knowledge base for professionals. Try it on It’s not just add-up of Docs, whiteboard, and tables. Transform any building blocks as you like. Say goodbye to redundancy, and keep all your knowledge minimal, in your way. Shape Your Page Docs, kanban, and databases are all fully functional at any place. You always keep what-you-see-is-what-you-get. All pages come with docs and whiteboard mode. Plan Your Task No more chaos between so many views. Set a TODO with Markdown, and manage it in Kanban. Managing multi-dimensional tables should be simple as that. Privacy-first, and collaborative. No compromises whatsoever. We don’t like cloud lock-in. Your data is always locally stored and secured, while you can still collaborate in real-time with others. Privacy is the foundation of everything we do. But it is no excuse for the bad experience. Build for an open and semantic future Keep Updated on Join Our Community AFFiNE is an #OpenSource company Copyright © 2022 AFFiNE. ); } export default App;