diff options
-rw-r--r-- | components/Sidebar/OrgImage.tsx | 9 | ||||
-rw-r--r-- | components/Sidebar/Toolbar.tsx | 36 | ||||
-rw-r--r-- | components/Sidebar/index.tsx | 27 | ||||
-rw-r--r-- | components/Sidebar/noteStyle.ts | 15 | ||||
-rw-r--r-- | package-lock.json | 73 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | pages/index.tsx | 42 | ||||
-rw-r--r-- | util/processOrg.tsx | 1 |
8 files changed, 181 insertions, 24 deletions
diff --git a/components/Sidebar/OrgImage.tsx b/components/Sidebar/OrgImage.tsx index a87fc4c..f9f508a 100644 --- a/components/Sidebar/OrgImage.tsx +++ b/components/Sidebar/OrgImage.tsx @@ -30,6 +30,13 @@ export const OrgImage = (props: OrgImageProps) => { } return ( - <Image layout="responsive" loader={dumbLoader} src={fullPath} alt="" width="70%" height="70%" /> + <Image + layout="responsive" + loader={dumbLoader} + src={fullPath} + alt="" + width="100%" + height="100%" + /> ) } diff --git a/components/Sidebar/Toolbar.tsx b/components/Sidebar/Toolbar.tsx index 458361f..f6f1e39 100644 --- a/components/Sidebar/Toolbar.tsx +++ b/components/Sidebar/Toolbar.tsx @@ -9,21 +9,51 @@ import { BiRightIndent, } from 'react-icons/bi' import { ChevronLeftIcon, ChevronRightIcon } from '@chakra-ui/icons' +import { NodeObject } from 'force-graph' export interface ToolbarProps { setJustification: any justification: number setIndent: any setFont: any + setPreviewNode: any + canUndo: any + canRedo: any + resetPreviewNode: any + previousPreviewNode: any + nextPreviewNode: any } export const Toolbar = (props: ToolbarProps) => { - const { setJustification, setIndent, setFont, justification } = props + const { + setJustification, + setIndent, + setFont, + justification, + setPreviewNode, + canUndo, + canRedo, + resetPreviewNode, + previousPreviewNode, + nextPreviewNode, + } = props return ( <Flex py={3} alignItems="center" justifyContent="space-between" pr={4}> <Flex> - <IconButton variant="ghost" icon={<ChevronLeftIcon />} aria-label="Previous node" /> - <IconButton variant="ghost" icon={<ChevronRightIcon />} aria-label="Previous node" /> + <IconButton + variant="ghost" + icon={<ChevronLeftIcon />} + aria-label="Previous node" + disabled={!canUndo} + onClick={() => previousPreviewNode()} + /> + <IconButton + variant="ghost" + icon={<ChevronRightIcon />} + aria-label="Next node" + disabled={!canRedo} + onClick={() => nextPreviewNode()} + /> </Flex> <Flex> <IconButton diff --git a/components/Sidebar/index.tsx b/components/Sidebar/index.tsx index 4d807ef..2e32f4f 100644 --- a/components/Sidebar/index.tsx +++ b/components/Sidebar/index.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useEffect, useState } from 'react' +import React, { useContext, useEffect, useRef, useState } from 'react' import { Toolbar } from './Toolbar' import { Note } from './Note' @@ -23,6 +23,11 @@ export interface SidebarProps { linksByNodeId: LinksByNodeId nodeByCite: NodeByCite setSidebarHighlightedNode: any + canUndo: any + canRedo: any + resetPreviewNode: any + previousPreviewNode: any + nextPreviewNode: any } const Sidebar = (props: SidebarProps) => { @@ -36,6 +41,11 @@ const Sidebar = (props: SidebarProps) => { linksByNodeId, nodeByCite, setSidebarHighlightedNode, + canUndo, + canRedo, + resetPreviewNode, + previousPreviewNode, + nextPreviewNode, } = props const { highlightColor } = useContext(ThemeContext) @@ -97,7 +107,20 @@ const Sidebar = (props: SidebarProps) => { onClick={onClose} /> </Flex> - <Toolbar {...{ setJustification, setIndent, setFont, justification }} /> + <Toolbar + {...{ + setJustification, + setIndent, + setFont, + justification, + setPreviewNode, + canUndo, + canRedo, + resetPreviewNode, + previousPreviewNode, + nextPreviewNode, + }} + /> <Scrollbars //autoHeight //autoHeightMax={600} diff --git a/components/Sidebar/noteStyle.ts b/components/Sidebar/noteStyle.ts index adf715d..42ecaf6 100644 --- a/components/Sidebar/noteStyle.ts +++ b/components/Sidebar/noteStyle.ts @@ -44,7 +44,7 @@ export const noteStyle = { fontWeight: 'bold', marginTop: 0, }, - '.todo': { fontFamily: 'monospace', color: 'red' }, + '.TODO': { color: 'red.500' }, '.equationContainer': { display: 'table', textAlign: 'center', @@ -71,7 +71,6 @@ export const noteStyle = { }, textarea: { overflowX: 'auto' }, '.linenr': { fontSize: 'smaller' }, - '.code-highlighted': { backgroundColor: '#ffff00' }, '.org-info-js_info-navigation': { borderStyle: 'none' }, '#org-info-js_console-label': { fontSize: '10px', @@ -84,10 +83,10 @@ export const noteStyle = { fontWeight: 'bold', }, '.org-svg': { width: '90%' }, - '.done': { fontFamily: 'monospace', color: 'green' }, + '.DONE': { color: 'green' }, '.priority': { fontFamily: 'monospace', color: 'orange' }, '.tag': { - backgroundColor: '#eee', + backgroundColor: 'white', fontFamily: 'monospace', padding: '2px', fontSize: '80%', @@ -103,9 +102,9 @@ export const noteStyle = { '#preamble p': { fontSize: '90%', margin: '.2em' }, 'p.verse': { marginLeft: '3%' }, pre: { - border: '1px solid #e6e6e6', + //border: '1px solid #e6e6e6', borderRadius: '3px', - backgroundColor: '#f2f2f2', + backgroundColor: 'white', padding: '8pt', fontFamily: 'monospace', overflow: 'auto', @@ -121,8 +120,8 @@ export const noteStyle = { top: '-8px', right: '12px', padding: '3px', - color: '#555', - backgroundColor: '#f2f2f299', + //color: '#555', + backgroundColor: 'white', }, 'caption.t-above': { captionSide: 'top' }, 'caption.t-bottom': { captionSide: 'bottom' }, diff --git a/package-lock.json b/package-lock.json index fe40c45..1a6f57f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "react-dom": "17.0.2", "react-force-graph": "^1.41.7", "react-icons": "^4.3.1", + "react-resizable": "^3.0.4", "react-spring": "^9.2.4", "reconnecting-websocket": "^4.4.0", "rehype": "^11.0.0", @@ -47,6 +48,7 @@ "uniorg-rehype": "^0.4.0", "uniorg-slug": "^0.4.0", "use-constant": "^1.1.0", + "use-undo": "^1.0.5", "vfile": "^4.2.1", "word-wrap": "^1.2.3" }, @@ -3180,6 +3182,14 @@ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" }, + "node_modules/clsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", + "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -7579,6 +7589,19 @@ "react": "17.0.2" } }, + "node_modules/react-draggable": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.4.tgz", + "integrity": "sha512-6e0WdcNLwpBx/YIDpoyd2Xb04PB0elrDrulKUgdrIlwuYvxh5Ok9M+F8cljm8kPXXs43PmMzek9RrB1b7mLMqA==", + "dependencies": { + "clsx": "^1.1.1", + "prop-types": "^15.6.0" + }, + "peerDependencies": { + "react": ">= 16.3.0", + "react-dom": ">= 16.3.0" + } + }, "node_modules/react-fast-compare": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", @@ -7707,6 +7730,18 @@ } } }, + "node_modules/react-resizable": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-3.0.4.tgz", + "integrity": "sha512-StnwmiESiamNzdRHbSSvA65b0ZQJ7eVQpPusrSmcpyGKzC0gojhtO62xxH6YOBmepk9dQTBi9yxidL3W4s3EBA==", + "dependencies": { + "prop-types": "15.x", + "react-draggable": "^4.0.3" + }, + "peerDependencies": { + "react": ">= 16.3" + } + }, "node_modules/react-spring": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/react-spring/-/react-spring-9.2.4.tgz", @@ -9411,6 +9446,15 @@ "react": "^16.8.0 || ^17.0.0" } }, + "node_modules/use-undo": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/use-undo/-/use-undo-1.0.5.tgz", + "integrity": "sha512-rLlwvcrioEqZ0t/M4hpgCsrCMgCpbodUXMRskK98g3ftdGFi7wr9DzxPY93vKHK17mMgxBY2ar7bgZ5cNFSiNQ==", + "peerDependencies": { + "react": "^16.8.6", + "react-dom": "^16.8.6" + } + }, "node_modules/util": { "version": "0.12.4", "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", @@ -12087,6 +12131,11 @@ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" }, + "clsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", + "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -15560,6 +15609,15 @@ "scheduler": "^0.20.2" } }, + "react-draggable": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.4.tgz", + "integrity": "sha512-6e0WdcNLwpBx/YIDpoyd2Xb04PB0elrDrulKUgdrIlwuYvxh5Ok9M+F8cljm8kPXXs43PmMzek9RrB1b7mLMqA==", + "requires": { + "clsx": "^1.1.1", + "prop-types": "^15.6.0" + } + }, "react-fast-compare": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", @@ -15647,6 +15705,15 @@ "tslib": "^1.0.0" } }, + "react-resizable": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-3.0.4.tgz", + "integrity": "sha512-StnwmiESiamNzdRHbSSvA65b0ZQJ7eVQpPusrSmcpyGKzC0gojhtO62xxH6YOBmepk9dQTBi9yxidL3W4s3EBA==", + "requires": { + "prop-types": "15.x", + "react-draggable": "^4.0.3" + } + }, "react-spring": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/react-spring/-/react-spring-9.2.4.tgz", @@ -16941,6 +17008,12 @@ "object-assign": "^4.1.1" } }, + "use-undo": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/use-undo/-/use-undo-1.0.5.tgz", + "integrity": "sha512-rLlwvcrioEqZ0t/M4hpgCsrCMgCpbodUXMRskK98g3ftdGFi7wr9DzxPY93vKHK17mMgxBY2ar7bgZ5cNFSiNQ==", + "requires": {} + }, "util": { "version": "0.12.4", "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", diff --git a/package.json b/package.json index 66aab66..a0b4777 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "react-dom": "17.0.2", "react-force-graph": "^1.41.7", "react-icons": "^4.3.1", + "react-resizable": "^3.0.4", "react-spring": "^9.2.4", "reconnecting-websocket": "^4.4.0", "rehype": "^11.0.0", @@ -50,6 +51,7 @@ "uniorg-rehype": "^0.4.0", "uniorg-slug": "^0.4.0", "use-constant": "^1.1.0", + "use-undo": "^1.0.5", "vfile": "^4.2.1", "word-wrap": "^1.2.3" }, diff --git a/pages/index.tsx b/pages/index.tsx index 59fae1a..a1df7e7 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -46,6 +46,7 @@ import ReconnectingWebSocket from 'reconnecting-websocket' import { deleteNodeInEmacs, openNodeInEmacs, createNodeInEmacs } from '../util/webSocketFunctions' import { ChevronLeftIcon, HamburgerIcon } from '@chakra-ui/icons' +import useUndo from 'use-undo' // react-force-graph fails on import when server-rendered // https://github.com/vasturiano/react-force-graph/issues/155 const ForceGraph2D = ( @@ -97,7 +98,22 @@ export function GraphPage() { const [emacsNodeId, setEmacsNodeId] = useState<string | null>(null) const [behavior, setBehavior] = usePersistantState('behavior', initialBehavior) const [mouse, setMouse] = usePersistantState('mouse', initialMouse) - const [previewNode, setPreviewNode] = useState<NodeObject>({}) + const [ + previewNodeState, + { + set: setPreviewNode, + reset: resetPreviewNode, + undo: previousPreviewNode, + redo: nextPreviewNode, + canUndo, + canRedo, + }, + ] = useUndo<NodeObject>({}) + const { + past: pastPreviewNodes, + present: previewNode, + future: futurePreviewNodes, + } = previewNodeState const [sidebarHighlightedNode, setSidebarHighlightedNode] = useState<OrgRoamNode | null>(null) const { isOpen, onOpen, onClose } = useDisclosure() @@ -509,6 +525,10 @@ export function GraphPage() { onClose, previewNode, setPreviewNode, + canUndo, + canRedo, + previousPreviewNode, + nextPreviewNode, setSidebarHighlightedNode, }} nodeById={nodeByIdRef.current!} @@ -843,14 +863,7 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) { algorithm: algos[visuals.algorithmName], }, ) - useEffect(() => { - console.log('aaa') - if (sidebarHighlightedNode?.id) { - setHoverNode(sidebarHighlightedNode) - } else { - setHoverNode(null) - } - }, [sidebarHighlightedNode]) + const highlightedNodes = useMemo(() => { if (!centralHighlightedNode.current) { return {} @@ -862,7 +875,7 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) { } return Object.fromEntries( [ - centralHighlightedNode.current.id! as string, + centralHighlightedNode.current?.id! as string, ...links.flatMap((link) => [link.source, link.target]), ].map((nodeId) => [nodeId, {}]), ) @@ -870,6 +883,15 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) { JSON.stringify(centralHighlightedNode.current), JSON.stringify(filteredLinksByNodeIdRef.current), ]) + + useEffect(() => { + if (sidebarHighlightedNode?.id) { + setHoverNode(sidebarHighlightedNode) + } else { + setHoverNode(null) + } + }, [sidebarHighlightedNode]) + const lastHoverNode = useRef<OrgRoamNode | null>(null) useEffect(() => { centralHighlightedNode.current = hoverNode diff --git a/util/processOrg.tsx b/util/processOrg.tsx index 3f32d30..1bab2cd 100644 --- a/util/processOrg.tsx +++ b/util/processOrg.tsx @@ -42,6 +42,7 @@ export const ProcessedOrg = (props: ProcessedOrgProps) => { .use(attachments) .use(uniorgSlug) .use(uniorg2rehype) + .use(highlight) .use(katex) .use(rehype2react, { createElement: React.createElement, |