WIP
This commit is contained in:
parent
02fc3ca102
commit
acc2ba4a48
|
|
@ -13,9 +13,16 @@
|
|||
"@chakra-ui/react": "^2.8.2",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@xeger/quill-image-actions": "^0.7.2",
|
||||
"@xeger/quill-image-formats": "^0.7.2",
|
||||
"framer-motion": "^11.0.8",
|
||||
"next": "14.1.3",
|
||||
"quill": "^1.3.7",
|
||||
"quill-image-drop-module": "^1.0.3",
|
||||
"quill-image-edit-module": "^0.1.6",
|
||||
"quill-image-resize-module": "^3.0.0",
|
||||
"quill-image-resize-module-react": "^3.0.0",
|
||||
"quill-resize-module": "^1.2.4",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"react-icons": "^5.0.1",
|
||||
|
|
@ -1678,6 +1685,29 @@
|
|||
"integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==",
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/@xeger/quill-image-actions": {
|
||||
"version": "0.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@xeger/quill-image-actions/-/quill-image-actions-0.7.2.tgz",
|
||||
"integrity": "sha512-OhaZnYCie9J1ZLx2+Nsznj+qkdHn9Yx7q3iOCCKFs6kAzcZUVBPv2fMjK+nzURySLyCVQOP3Ur2mZx1yYqgppw==",
|
||||
"dependencies": {
|
||||
"core-js": "^3.0",
|
||||
"deepmerge": "^4.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"quill": "^1.3.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@xeger/quill-image-formats": {
|
||||
"version": "0.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@xeger/quill-image-formats/-/quill-image-formats-0.7.2.tgz",
|
||||
"integrity": "sha512-L9beiJKWzjHxBJEZB21I8YjFgOHYROsrfFMvIqP+kjc/u/MecHY1mXzR9VySLr+Qvj55t+vkKKuJ0ZPKvQSaPA==",
|
||||
"dependencies": {
|
||||
"core-js": "^3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"quill": "^1.3.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@zag-js/dom-query": {
|
||||
"version": "0.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-0.16.0.tgz",
|
||||
|
|
@ -1858,6 +1888,16 @@
|
|||
"toggle-selection": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/core-js": {
|
||||
"version": "3.36.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.36.0.tgz",
|
||||
"integrity": "sha512-mt7+TUBbTFg5+GngsAxeKBTl5/VS0guFeJacYge9OmHb+m058UwwIm41SE9T4Den7ClatV57B6TYTuJ0CX1MAw==",
|
||||
"hasInstallScript": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/core-js"
|
||||
}
|
||||
},
|
||||
"node_modules/cosmiconfig": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
|
||||
|
|
@ -1905,6 +1945,14 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/deepmerge": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/define-data-property": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||
|
|
@ -2520,6 +2568,55 @@
|
|||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/quill-image-drop-module": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/quill-image-drop-module/-/quill-image-drop-module-1.0.3.tgz",
|
||||
"integrity": "sha512-HP0Y2kb3nQk1QbRKZzEe1j3mArRQerN5B/U/MlXrOnxmhy3m/xYmVv0YoE13vWnGnBOIcoXGJ/9fi7l6AwsP8Q==",
|
||||
"dependencies": {
|
||||
"quill": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/quill-image-edit-module": {
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmjs.org/quill-image-edit-module/-/quill-image-edit-module-0.1.6.tgz",
|
||||
"integrity": "sha512-yB5YiXqX8Scxxk9AaqKRAekqUB/WHFqrFHWDq6E1+Q/KjIFAmYTB8az1XuXiz8M7M/LL5689p5ZdqyYppS8R/Q==",
|
||||
"dependencies": {
|
||||
"deepmerge": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/quill-image-resize-module": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/quill-image-resize-module/-/quill-image-resize-module-3.0.0.tgz",
|
||||
"integrity": "sha512-1TZBnUxU/WIx5dPyVjQ9yN7C6mLZSp04HyWBEMqT320DIq4MW4JgzlOPDZX5ZpBM3bU6sacU4kTLUc8VgYQZYw==",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.4",
|
||||
"quill": "^1.2.2",
|
||||
"raw-loader": "^0.5.1"
|
||||
}
|
||||
},
|
||||
"node_modules/quill-image-resize-module-react": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/quill-image-resize-module-react/-/quill-image-resize-module-react-3.0.0.tgz",
|
||||
"integrity": "sha512-3jVChLoXh+fwEELx3OswOEEuF+1KU3r/B9RAqZ//s+d+UMduVZzUepU1g/XoxjKoBJvWD2lJwBIFBRUNb8ebCw==",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.4",
|
||||
"quill": "^1.2.2",
|
||||
"raw-loader": "^0.5.1"
|
||||
}
|
||||
},
|
||||
"node_modules/quill-resize-module": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/quill-resize-module/-/quill-resize-module-1.2.4.tgz",
|
||||
"integrity": "sha512-toBGslzfzxXlokN7d7naL6iq2Da5mDS4zzvyES2YpqwBqO/yrxHR1rylz0D1zLHAZcF+aeDWBNwktrYQMN5vGw==",
|
||||
"dependencies": {
|
||||
"extend": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/raw-loader": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz",
|
||||
"integrity": "sha512-sf7oGoLuaYAScB4VGr0tzetsYlS8EJH6qnTCfQ/WVEa89hALQ4RQfCKt5xCyPQKPDUbVUAIP1QsxAwfAjlDp7Q=="
|
||||
},
|
||||
"node_modules/react": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
||||
|
|
|
|||
|
|
@ -14,9 +14,16 @@
|
|||
"@chakra-ui/react": "^2.8.2",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@xeger/quill-image-actions": "^0.7.2",
|
||||
"@xeger/quill-image-formats": "^0.7.2",
|
||||
"framer-motion": "^11.0.8",
|
||||
"next": "14.1.3",
|
||||
"quill": "^1.3.7",
|
||||
"quill-image-drop-module": "^1.0.3",
|
||||
"quill-image-edit-module": "^0.1.6",
|
||||
"quill-image-resize-module": "^3.0.0",
|
||||
"quill-image-resize-module-react": "^3.0.0",
|
||||
"quill-resize-module": "^1.2.4",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"react-icons": "^5.0.1",
|
||||
|
|
|
|||
|
|
@ -91,8 +91,7 @@ body {
|
|||
to bottom,
|
||||
transparent,
|
||||
rgb(var(--background-end-rgb))
|
||||
)
|
||||
rgb(var(--background-start-rgb));
|
||||
) rgb(var(--background-start-rgb));
|
||||
}
|
||||
|
||||
a {
|
||||
|
|
@ -101,16 +100,57 @@ a {
|
|||
}
|
||||
|
||||
.ql-editor::before {
|
||||
left: 0!important;
|
||||
right: 0!important;
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.ql-editor {
|
||||
padding: 12px 0!important;
|
||||
padding: 12px 0 !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.quill {
|
||||
container-type: inline-size;
|
||||
}
|
||||
|
||||
.quill .ql-editor::-webkit-scrollbar {
|
||||
width: var(--chakra-sizes-2);
|
||||
}
|
||||
|
||||
.quill .ql-editor::-webkit-scrollbar-track {
|
||||
background: var(--chakra-colors-gray-50)
|
||||
}
|
||||
|
||||
.quill .ql-editor::-webkit-scrollbar-thumb {
|
||||
background: var(--chakra-colors-gray-400);
|
||||
border-radius: var(--chakra-sizes-4)
|
||||
}
|
||||
|
||||
.quill .ql-toolbar {
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.quill .ql-container {
|
||||
margin-top: .5rem;
|
||||
height: calc(100% - 43px - .5rem);
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.quill .ql-container img {
|
||||
max-width: 1100px;
|
||||
}
|
||||
|
||||
.quill .ql-container p {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
@container (width < 600px) {
|
||||
.ql-container {
|
||||
height: calc(100% - 68px) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html {
|
||||
color-scheme: dark;
|
||||
|
|
|
|||
|
|
@ -7,28 +7,50 @@ import {
|
|||
Divider,
|
||||
Flex,
|
||||
Heading,
|
||||
HStack,
|
||||
HStack, Icon, IconButton,
|
||||
Input,
|
||||
Link,
|
||||
Link, Menu, MenuButton, MenuDivider, MenuItem, MenuList,
|
||||
Text,
|
||||
VStack,
|
||||
Wrap
|
||||
} from "@chakra-ui/react";
|
||||
import {Logo} from "@/components/shared/Logo";
|
||||
import {BsPlus} from "react-icons/bs";
|
||||
import {BsCopy, BsGlobe, BsPlus, BsThreeDotsVertical, BsTrash} from "react-icons/bs";
|
||||
|
||||
import 'react-quill/dist/quill.snow.css';
|
||||
import dynamic from "next/dynamic";
|
||||
import {useState} from "react";
|
||||
import {useEffect, useState} from "react";
|
||||
import Quill from "quill";
|
||||
import {ImageDrop} from 'quill-image-drop-module';
|
||||
|
||||
const QuillEditor = dynamic(() => import('react-quill'), {ssr: false});
|
||||
Quill.register('modules/imageDrop', ImageDrop);
|
||||
|
||||
let titleTimeout: NodeJS.Timeout | null = null;
|
||||
let contentTimeout: NodeJS.Timeout | null = null;
|
||||
|
||||
export default function NotesChakraPage() {
|
||||
const [title, setTitle] = useState('')
|
||||
const [content, setContent] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== "undefined" && window.localStorage) {
|
||||
setTitle(window.localStorage.getItem("qnote:current-note-title") || '')
|
||||
setContent(window.localStorage.getItem("qnote:current-note") || '');
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (contentTimeout !== null) {
|
||||
clearTimeout(contentTimeout);
|
||||
}
|
||||
if (titleTimeout !== null) {
|
||||
clearTimeout(titleTimeout);
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
const quillModules = {
|
||||
imageDrop: true,
|
||||
toolbar: [
|
||||
[{header: [1, 2, 3, false]}],
|
||||
['bold', 'italic', 'underline', 'strike', 'blockquote'],
|
||||
|
|
@ -41,7 +63,6 @@ export default function NotesChakraPage() {
|
|||
],
|
||||
};
|
||||
|
||||
|
||||
const quillFormats = [
|
||||
'header',
|
||||
'bold',
|
||||
|
|
@ -58,9 +79,30 @@ export default function NotesChakraPage() {
|
|||
'code-block',
|
||||
];
|
||||
|
||||
const handleTitleChange = (newTitle: string) => {
|
||||
setTitle(newTitle);
|
||||
|
||||
const handleEditorChange = (newContent) => {
|
||||
if (titleTimeout !== null) {
|
||||
clearTimeout(titleTimeout);
|
||||
}
|
||||
titleTimeout = setTimeout(() => {
|
||||
if (typeof window !== 'undefined' && window.localStorage) {
|
||||
window.localStorage.setItem("qnote:current-note-title", newTitle);
|
||||
}
|
||||
}, 750)
|
||||
}
|
||||
|
||||
const handleEditorChange = (newContent: string) => {
|
||||
setContent(newContent);
|
||||
|
||||
if (contentTimeout !== null) {
|
||||
clearTimeout(contentTimeout);
|
||||
}
|
||||
contentTimeout = setTimeout(() => {
|
||||
if (typeof window !== 'undefined' && window.localStorage) {
|
||||
window.localStorage.setItem("qnote:current-note", newContent);
|
||||
}
|
||||
}, 750)
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -71,16 +113,17 @@ export default function NotesChakraPage() {
|
|||
display="flex"
|
||||
flexDirection="column"
|
||||
height="100%"
|
||||
overflowY="hidden"
|
||||
overflow="hidden"
|
||||
>
|
||||
<Flex
|
||||
px={{base: '4', sm: '10'}}
|
||||
justifyContent="center"
|
||||
flexDirection={{base: "column", xl: "row"}}
|
||||
justifyContent={{base: "start", xl: "center"}}
|
||||
alignItems="start"
|
||||
h="auto"
|
||||
minH="100%"
|
||||
gap={5}>
|
||||
<VStack w="100%" maxW="sm" h="100%" minH="100%">
|
||||
<VStack w="100%" maxW="sm" h={{base: "96px", xl: "100%"}} minH={{base: "96px", xl: "100%"}}>
|
||||
<Link href="/" w="100%" border="none" outline="none" _before={{display: "none"}}>
|
||||
<HStack justifyContent="start" alignItems="center" w="100%">
|
||||
<Logo w={24}/>
|
||||
|
|
@ -88,7 +131,7 @@ export default function NotesChakraPage() {
|
|||
</HStack>
|
||||
</Link>
|
||||
<Container
|
||||
display="flex"
|
||||
display={{base: "none", xl: "flex"}}
|
||||
flex={1}
|
||||
flexDirection="column"
|
||||
w="100%"
|
||||
|
|
@ -98,7 +141,7 @@ export default function NotesChakraPage() {
|
|||
bg={{base: 'transparent', sm: 'bg.surface'}}
|
||||
boxShadow={{base: 'none', sm: 'xl'}}
|
||||
borderRadius={{base: 'none', sm: 'xl'}}
|
||||
overflowY="hidden"
|
||||
overflow="hidden"
|
||||
>
|
||||
<VStack spacing={3} w="100%" h="100%" minH="100%">
|
||||
<Flex w="100%" justifyContent="space-between" alignItems="center" px={4}>
|
||||
|
|
@ -124,12 +167,12 @@ export default function NotesChakraPage() {
|
|||
}}>
|
||||
<VStack spacing={1} w="100%" px={1} py={1}>
|
||||
{Array.from(Array(50).keys()).map(i => (
|
||||
<Wrap key={i} w="100%">
|
||||
<Box w="100%" px={4} py={2}>
|
||||
<Wrap key={i} w="100%" _hover={{bg: 'gray.50'}}>
|
||||
<Box w="100%" px={4} py={4}>
|
||||
<Text fontWeight="black">Note name ${i + 1}</Text>
|
||||
<Text>Note text preview...</Text>
|
||||
</Box>
|
||||
<Divider my={2}/>
|
||||
<Divider my={0}/>
|
||||
</Wrap>
|
||||
))}
|
||||
</VStack>
|
||||
|
|
@ -139,18 +182,17 @@ export default function NotesChakraPage() {
|
|||
</VStack>
|
||||
|
||||
<Container
|
||||
display="flex"
|
||||
flex={1}
|
||||
flexDirection="column"
|
||||
w="100%"
|
||||
h="auto"
|
||||
minH="100%"
|
||||
h="100%"
|
||||
maxHeight={{base: 'calc(100% - 130px)', xl: '100%'}}
|
||||
mx={0}
|
||||
py={{base: '0', sm: '8'}}
|
||||
bg={{base: 'transparent', sm: 'bg.surface'}}
|
||||
boxShadow={{base: 'none', sm: 'xl'}}
|
||||
borderRadius={{base: 'none', sm: 'xl'}}
|
||||
>
|
||||
<HStack w="100%" alignItems="start" justifyContent="space-between" spacing={3}>
|
||||
<Input size="xl"
|
||||
placeholder="Unnamed note"
|
||||
px={0}
|
||||
|
|
@ -164,10 +206,23 @@ export default function NotesChakraPage() {
|
|||
outline: "none",
|
||||
borderBottomColor: "brand.500"
|
||||
}}
|
||||
value={title}
|
||||
onChange={(e) => handleTitleChange(e.target.value)}
|
||||
mb={3}
|
||||
/>
|
||||
|
||||
<Box flex={1} w="100%" overflowY="auto" w="100%">
|
||||
<Menu>
|
||||
<MenuButton as={IconButton} aria-label="Note menu" icon={<BsThreeDotsVertical/>} variant="ghost"/>
|
||||
<MenuList>
|
||||
<MenuItem icon={<Icon as={BsGlobe} boxSize={3}/>}>Publish</MenuItem>
|
||||
<MenuItem icon={<Icon as={BsCopy} boxSize={3}/>}>Duplicate</MenuItem>
|
||||
<MenuDivider/>
|
||||
<MenuItem icon={<Icon as={BsTrash} boxSize={3}/>} color="red">Delete</MenuItem>
|
||||
</MenuList>
|
||||
</Menu>
|
||||
</HStack>
|
||||
|
||||
<Box w="100%" overflowY="auto" h="calc(100% - var(--chakra-sizes-12))">
|
||||
<QuillEditor
|
||||
theme="snow"
|
||||
placeholder="Write down all your thoughts..."
|
||||
|
|
@ -175,7 +230,7 @@ export default function NotesChakraPage() {
|
|||
onChange={handleEditorChange}
|
||||
modules={quillModules}
|
||||
formats={quillFormats}
|
||||
style={{width: '100%', height: '100%', overflowY: 'auto' }}
|
||||
style={{width: '100%', height: '100%', overflowY: 'auto'}}
|
||||
/>
|
||||
</Box>
|
||||
</Container>
|
||||
|
|
|
|||
Loading…
Reference in New Issue