summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--components/config.ts24
-rw-r--r--components/tweaks.tsx732
-rw-r--r--org-roam-ui.el14
-rw-r--r--pages/_app.tsx6
-rw-r--r--pages/index.tsx66
5 files changed, 582 insertions, 260 deletions
diff --git a/components/config.ts b/components/config.ts
index d538941..5c0a922 100644
--- a/components/config.ts
+++ b/components/config.ts
@@ -84,15 +84,33 @@ export const initialVisuals = {
algorithms: algorithms,
algorithmOptions: options,
algorithmName: 'CubicOut',
- linkColorScheme: '500',
- nodeColorScheme: ['gray', 'red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'pink', 'purple'],
+ linkColorScheme: 'gray.500',
+ nodeColorScheme: [
+ 'red.500',
+ 'orange.500',
+ 'yellow.500',
+ 'green.500',
+ 'cyan.500',
+ 'blue.500',
+ 'pink.500',
+ 'purple.500',
+ ],
nodeHighlight: '',
- linkHighlight: '',
+ linkHighlight: 'purple.500',
backgroundColor: 'white',
emacsNodeColor: '',
+ labelTextColor: 'black',
+ labelBackgroundColor: 'white',
+ labelBackgroundOpacity: 0.7,
}
export const initialBehavior = {
follow: 'Zoom',
followLocalOrZoom: true,
}
+
+export const initialMouse = {
+ highlight: 'hover',
+ local: 'click',
+ follow: 'double',
+}
diff --git a/components/tweaks.tsx b/components/tweaks.tsx
index e9ab582..fb20cb3 100644
--- a/components/tweaks.tsx
+++ b/components/tweaks.tsx
@@ -36,10 +36,11 @@ import {
Heading,
Collapse,
Grid,
+ Portal,
} from '@chakra-ui/react'
import React, { useState, useContext } from 'react'
import Scrollbars from 'react-custom-scrollbars-2'
-import { initialPhysics, initialFilter, initialVisuals } from './config'
+import { initialPhysics, initialFilter, initialVisuals, initialMouse } from './config'
import { ThemeContext } from '../pages/themecontext'
@@ -52,15 +53,53 @@ export interface TweakProps {
setFilter: any
visuals: typeof initialVisuals
setVisuals: any
+ mouse: typeof initialMouse
+ setMouse: any
}
export const Tweaks = (props: TweakProps) => {
- const { physics, setPhysics, threeDim, setThreeDim, filter, setFilter, visuals, setVisuals } =
- props
+ const {
+ physics,
+ setPhysics,
+ threeDim,
+ setThreeDim,
+ filter,
+ setFilter,
+ visuals,
+ setVisuals,
+ mouse,
+ setMouse,
+ } = props
const [showTweaks, setShowTweaks] = useState(true)
const { highlightColor, setHighlightColor } = useContext(ThemeContext)
- const colorList = ['red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'pink', 'purple', 'gray']
- const grays = ['100', '200', '300', '400', '500', '600', '700', '800', '900']
+ const colorList = [
+ 'red.500',
+ 'orange.500',
+ 'yellow.500',
+ 'green.500',
+ 'cyan.500',
+ 'blue.500',
+ 'pink.500',
+ 'purple.500',
+ 'gray.400',
+ 'gray.500',
+ 'gray.600',
+ 'white',
+ 'black',
+ ]
+ const grays = [
+ 'black',
+ 'gray.100',
+ 'gray.200',
+ 'gray.300',
+ 'gray.400',
+ 'gray.500',
+ 'gray.600',
+ 'gray.700',
+ 'gray.800',
+ 'gray.900',
+ 'white',
+ ]
return (
<>
<Box
@@ -362,59 +401,63 @@ export const Tweaks = (props: TweakProps) => {
{visuals.nodeColorScheme.map((color) => (
<Box
key={color}
- bgColor={color + '.500'}
+ bgColor={color}
flex="1 1 8px"
borderRadius="2xl"
></Box>
))}
</Flex>
</MenuButton>
- <MenuList bgColor="gray.200" width={50}>
- <MenuOptionGroup
- type="checkbox"
- defaultValue={visuals.nodeColorScheme}
- onChange={(colors) => {
- if (!colors.length) {
- return
- }
- setVisuals({ ...visuals, nodeColorScheme: colors })
- console.log(visuals.nodeColorScheme)
- }}
- >
- {colorList.map((color) => (
- <MenuItemOption
- key={color}
- isChecked={visuals.nodeColorScheme.some(
- (c) => c === color,
- )}
- value={color}
- isDisabled={
- visuals.nodeColorScheme.length === 1 &&
- visuals.nodeColorScheme[0] === color
+ <Portal>
+ {' '}
+ <MenuList zIndex="popover" bgColor="gray.200" width={50}>
+ <MenuOptionGroup
+ type="checkbox"
+ defaultValue={visuals.nodeColorScheme}
+ onChange={(colors) => {
+ if (!colors.length) {
+ return
}
- >
- <Box
- justifyContent="space-between"
- alignItems="center"
- display="flex"
+ setVisuals({ ...visuals, nodeColorScheme: colors })
+ }}
+ >
+ {colorList.map((color) => (
+ <MenuItemOption
+ key={color}
+ isChecked={visuals.nodeColorScheme.some(
+ (c) => c === color,
+ )}
+ value={color}
+ isDisabled={
+ visuals.nodeColorScheme.length === 1 &&
+ visuals.nodeColorScheme[0] === color
+ }
>
- <Text>{color[0]!.toUpperCase() + color!.slice(1)}</Text>
<Box
- bgColor={color + '.500'}
- borderRadius="sm"
- height={6}
- width={6}
- ></Box>
- </Box>
- </MenuItemOption>
- ))}
- </MenuOptionGroup>
- </MenuList>
+ justifyContent="space-between"
+ alignItems="center"
+ display="flex"
+ >
+ <Text>
+ {color[0]!.toUpperCase() + color!.slice(1)}
+ </Text>
+ <Box
+ bgColor={color}
+ borderRadius="sm"
+ height={6}
+ width={6}
+ ></Box>
+ </Box>
+ </MenuItemOption>
+ ))}
+ </MenuOptionGroup>
+ </MenuList>
+ </Portal>
</Menu>
</Flex>
<Flex alignItems="center" justifyContent="space-between">
<Text>Links</Text>
- <Menu isLazy>
+ <Menu>
<MenuButton
as={Button}
colorScheme=""
@@ -439,7 +482,7 @@ export const Tweaks = (props: TweakProps) => {
{visuals.nodeColorScheme.map((color) => (
<Box
key={color}
- bgColor={color + '.500'}
+ bgColor={color}
flex="1 1 8px"
borderRadius="2xl"
></Box>
@@ -448,60 +491,61 @@ export const Tweaks = (props: TweakProps) => {
)}
</Box>
</MenuButton>
- <MenuList bgColor="gray.200" width={50}>
- <MenuItem
- onClick={() =>
- setVisuals({ ...visuals, linkColorScheme: '' })
- }
- justifyContent="space-between"
- alignItems="center"
- display="flex"
- >
- <Text>Match nodes</Text>
- <Flex
- height={6}
- width={6}
- flexDirection="column"
- flexWrap="wrap"
- >
- {visuals.nodeColorScheme.map((color) => (
- <Box
- key={color}
- bgColor={color + '.500'}
- flex="1 1 8px"
- borderRadius="2xl"
- ></Box>
- ))}
- </Flex>
- </MenuItem>
- {grays.map((color) => (
+ <Portal>
+ {' '}
+ <MenuList zIndex="popover" bgColor="gray.200" width={50}>
<MenuItem
- key={color}
onClick={() =>
- setVisuals({
- ...visuals,
- linkColorScheme: color,
- })
+ setVisuals({ ...visuals, linkColorScheme: '' })
}
justifyContent="space-between"
alignItems="center"
display="flex"
>
- <Text>{color[0]!.toUpperCase() + color!.slice(1)}</Text>
- <Box
- bgColor={'gray.' + color}
- borderRadius="sm"
+ <Flex
height={6}
width={6}
- ></Box>
+ flexDirection="column"
+ flexWrap="wrap"
+ >
+ {visuals.nodeColorScheme.map((color) => (
+ <Box
+ key={color}
+ bgColor={color + '.500'}
+ flex="1 1 8px"
+ borderRadius="2xl"
+ ></Box>
+ ))}
+ </Flex>
</MenuItem>
- ))}
- </MenuList>
+ {grays.map((color) => (
+ <MenuItem
+ key={color}
+ onClick={() =>
+ setVisuals({
+ ...visuals,
+ linkColorScheme: color,
+ })
+ }
+ justifyContent="space-between"
+ alignItems="center"
+ display="flex"
+ >
+ <Box
+ bgColor={color}
+ borderRadius="sm"
+ height={6}
+ width={6}
+ ></Box>
+ </MenuItem>
+ ))}
+ </MenuList>
+ </Portal>
</Menu>
</Flex>
<Flex alignItems="center" justifyContent="space-between">
<Text>Accent</Text>
- <Menu isLazy>
+ <Menu>
<MenuButton
as={Button}
colorScheme=""
@@ -517,30 +561,33 @@ export const Tweaks = (props: TweakProps) => {
></Box>
}
</MenuButton>
- <MenuList bgColor="gray.200" width={50}>
- {colorList.map((color) => (
- <MenuItem
- key={color}
- onClick={() => setHighlightColor(color)}
- justifyContent="space-between"
- alignItems="center"
- display="flex"
- >
- <Text>{color[0]!.toUpperCase() + color!.slice(1)}</Text>
- <Box
- bgColor={color + '.500'}
- borderRadius="sm"
- height={6}
- width={6}
- ></Box>
- </MenuItem>
- ))}
- </MenuList>
+ <Portal>
+ {' '}
+ <MenuList zIndex="popover" bgColor="gray.200" width={50}>
+ {colorList.map((color) => (
+ <MenuItem
+ key={color}
+ onClick={() => setHighlightColor(color)}
+ justifyContent="space-between"
+ alignItems="center"
+ display="flex"
+ >
+ <Text>{color[0]!.toUpperCase() + color!.slice(1)}</Text>
+ <Box
+ bgColor={color + '.500'}
+ borderRadius="sm"
+ height={6}
+ width={6}
+ ></Box>
+ </MenuItem>
+ ))}
+ </MenuList>
+ </Portal>
</Menu>
</Flex>
<Flex alignItems="center" justifyContent="space-between">
<Text>Link Highlight</Text>
- <Menu isLazy>
+ <Menu>
<MenuButton
as={Button}
colorScheme=""
@@ -556,41 +603,46 @@ export const Tweaks = (props: TweakProps) => {
></Box>
}
</MenuButton>
- <MenuList bgColor="gray.200" width={50}>
- <MenuItem
- key={'none'}
- onClick={() => setVisuals({ ...visuals, linkHighlight: '' })}
- justifyContent="space-between"
- alignItems="center"
- display="flex"
- >
- <Text>Match current color</Text>
- </MenuItem>
- {colorList.map((color) => (
+ <Portal>
+ {' '}
+ <MenuList zIndex="popover" bgColor="gray.200" width={50}>
<MenuItem
- key={color}
+ key={'none'}
onClick={() =>
- setVisuals({ ...visuals, linkHighlight: color })
+ setVisuals({ ...visuals, linkHighlight: '' })
}
justifyContent="space-between"
alignItems="center"
display="flex"
>
- <Text>{color[0]!.toUpperCase() + color!.slice(1)}</Text>
- <Box
- bgColor={color + '.500'}
- borderRadius="sm"
- height={6}
- width={6}
- ></Box>
+ <Text>Match current color</Text>
</MenuItem>
- ))}
- </MenuList>
+ {colorList.map((color) => (
+ <MenuItem
+ key={color}
+ onClick={() =>
+ setVisuals({ ...visuals, linkHighlight: color })
+ }
+ justifyContent="space-between"
+ alignItems="center"
+ display="flex"
+ >
+ <Text>{color[0]!.toUpperCase() + color!.slice(1)}</Text>
+ <Box
+ bgColor={color + '.500'}
+ borderRadius="sm"
+ height={6}
+ width={6}
+ ></Box>
+ </MenuItem>
+ ))}
+ </MenuList>
+ </Portal>
</Menu>
</Flex>
<Flex alignItems="center" justifyContent="space-between">
<Text>Node Highlight</Text>
- <Menu isLazy>
+ <Menu>
<MenuButton
as={Button}
colorScheme=""
@@ -606,41 +658,46 @@ export const Tweaks = (props: TweakProps) => {
></Box>
}
</MenuButton>
- <MenuList bgColor="gray.200" width={50}>
- <MenuItem
- key={'none'}
- onClick={() => setVisuals({ ...visuals, nodeHighlight: '' })}
- justifyContent="space-between"
- alignItems="center"
- display="flex"
- >
- <Text>Match current color</Text>
- </MenuItem>
- {colorList.map((color) => (
+ <Portal>
+ {' '}
+ <MenuList zIndex="popover" bgColor="gray.200" width={50}>
<MenuItem
- key={color}
+ key={'none'}
onClick={() =>
- setVisuals({ ...visuals, nodeHighlight: color })
+ setVisuals({ ...visuals, nodeHighlight: '' })
}
justifyContent="space-between"
alignItems="center"
display="flex"
>
- <Text>{color[0]!.toUpperCase() + color!.slice(1)}</Text>
- <Box
- bgColor={color + '.500'}
- borderRadius="sm"
- height={6}
- width={6}
- ></Box>
+ <Text>Match current color</Text>
</MenuItem>
- ))}
- </MenuList>
+ {colorList.map((color) => (
+ <MenuItem
+ key={color}
+ onClick={() =>
+ setVisuals({ ...visuals, nodeHighlight: color })
+ }
+ justifyContent="space-between"
+ alignItems="center"
+ display="flex"
+ >
+ <Text>{color[0]!.toUpperCase() + color!.slice(1)}</Text>
+ <Box
+ bgColor={color + '.500'}
+ borderRadius="sm"
+ height={6}
+ width={6}
+ ></Box>
+ </MenuItem>
+ ))}
+ </MenuList>
+ </Portal>
</Menu>
</Flex>
<Flex alignItems="center" justifyContent="space-between">
<Text>Background</Text>
- <Menu isLazy>
+ <Menu>
<MenuButton
as={Button}
colorScheme=""
@@ -656,32 +713,35 @@ export const Tweaks = (props: TweakProps) => {
></Box>
}
</MenuButton>
- <MenuList bgColor="gray.200" width={50}>
- {grays.map((color) => (
- <MenuItem
- key={color}
- onClick={() =>
- setVisuals({ ...visuals, backgroundColor: color })
- }
- justifyContent="space-between"
- alignItems="center"
- display="flex"
- >
- <Text>{color[0]!.toUpperCase() + color!.slice(1)}</Text>
- <Box
- bgColor={'gray.' + color}
- borderRadius="sm"
- height={6}
- width={6}
- ></Box>
- </MenuItem>
- ))}
- </MenuList>
+ <Portal>
+ {' '}
+ <MenuList zIndex="popover" bgColor="gray.200" width={50}>
+ {grays.map((color) => (
+ <MenuItem
+ key={color}
+ onClick={() =>
+ setVisuals({ ...visuals, backgroundColor: color })
+ }
+ justifyContent="space-between"
+ alignItems="center"
+ display="flex"
+ >
+ <Text>{color[0]!.toUpperCase() + color!.slice(1)}</Text>
+ <Box
+ bgColor={'gray.' + color}
+ borderRadius="sm"
+ height={6}
+ width={6}
+ ></Box>
+ </MenuItem>
+ ))}
+ </MenuList>
+ </Portal>
</Menu>
</Flex>
<Flex alignItems="center" justifyContent="space-between">
<Text>Emacs Node</Text>
- <Menu isLazy>
+ <Menu>
<MenuButton
as={Button}
colorScheme=""
@@ -697,37 +757,42 @@ export const Tweaks = (props: TweakProps) => {
></Box>
}
</MenuButton>
- <MenuList bgColor="gray.200" width={50}>
- <MenuItem
- key={'none'}
- onClick={() => setVisuals({ ...visuals, emacsNodeColor: '' })}
- justifyContent="space-between"
- alignItems="center"
- display="flex"
- >
- <Text>No change</Text>
- <Box borderRadius="sm" height={6} width={6}></Box>
- </MenuItem>
- {colorList.map((color) => (
+ <Portal>
+ {' '}
+ <MenuList zIndex="popover" bgColor="gray.200" width={50}>
<MenuItem
- key={color}
+ key={'none'}
onClick={() =>
- setVisuals({ ...visuals, emacsNodeColor: color })
+ setVisuals({ ...visuals, emacsNodeColor: '' })
}
justifyContent="space-between"
alignItems="center"
display="flex"
>
- <Text>{color[0]!.toUpperCase() + color!.slice(1)}</Text>
- <Box
- bgColor={color + '.500'}
- borderRadius="sm"
- height={6}
- width={6}
- ></Box>
+ <Text>No change</Text>
+ <Box borderRadius="sm" height={6} width={6}></Box>
</MenuItem>
- ))}
- </MenuList>
+ {colorList.map((color) => (
+ <MenuItem
+ key={color}
+ onClick={() =>
+ setVisuals({ ...visuals, emacsNodeColor: color })
+ }
+ justifyContent="space-between"
+ alignItems="center"
+ display="flex"
+ >
+ <Text>{color[0]!.toUpperCase() + color!.slice(1)}</Text>
+ <Box
+ bgColor={color + '.500'}
+ borderRadius="sm"
+ height={6}
+ width={6}
+ ></Box>
+ </MenuItem>
+ ))}
+ </MenuList>
+ </Portal>
</Menu>
</Flex>
</Box>
@@ -781,23 +846,24 @@ export const Tweaks = (props: TweakProps) => {
onChange={(value) => setPhysics({ ...physics, linkOpacity: value })}
/>
)}
- <Box>
- <Flex alignItems="center" justifyContent="space-between">
- <Text>Labels</Text>
- <Menu>
- <MenuButton
- as={Button}
- colorScheme=""
- color="black"
- rightIcon={<ChevronDownIcon />}
- >
- {!physics.labels
- ? 'Never'
- : physics.labels < 2
- ? 'On Highlight'
- : 'Always'}
- </MenuButton>
- <MenuList bgColor="gray.200">
+ <Flex alignItems="center" justifyContent="space-between">
+ <Text>Labels</Text>
+ <Menu>
+ <MenuButton
+ as={Button}
+ colorScheme=""
+ color="black"
+ rightIcon={<ChevronDownIcon />}
+ >
+ {!physics.labels
+ ? 'Never'
+ : physics.labels < 2
+ ? 'On Highlight'
+ : 'Always'}
+ </MenuButton>
+ <Portal>
+ {' '}
+ <MenuList zIndex="popover" bgColor="gray.200">
<MenuItem onClick={() => setPhysics({ ...physics, labels: 0 })}>
Never
</MenuItem>
@@ -807,21 +873,152 @@ export const Tweaks = (props: TweakProps) => {
<MenuItem onClick={() => setPhysics({ ...physics, labels: 2 })}>
Always
</MenuItem>
+ <MenuItem onClick={() => setPhysics({ ...physics, labels: 3 })}>
+ Always (even in 3D)
+ </MenuItem>
</MenuList>
- </Menu>
- </Flex>
- <Collapse in={physics.labels > 1} animateOpacity>
- <Box paddingLeft={4} paddingTop={2}>
- <SliderWithInfo
- label="Label Appearance Scale"
- value={physics.labelScale * 5}
- onChange={(value) =>
- setPhysics({ ...physics, labelScale: value / 5 })
- }
- />
- </Box>
- </Collapse>
- </Box>
+ </Portal>
+ </Menu>
+ </Flex>
+ <Collapse in={physics.labels > 0} animateOpacity>
+ <VStack
+ spacing={1}
+ justifyContent="flex-start"
+ divider={<StackDivider borderColor="gray.400" />}
+ align="stretch"
+ paddingLeft={2}
+ color="gray.800"
+ >
+ <Flex alignItems="center" justifyContent="space-between">
+ <Text>Text</Text>
+ <Menu matchWidth>
+ <MenuButton
+ as={Button}
+ rightIcon={<ChevronDownIcon />}
+ color="black"
+ colorScheme=""
+ >
+ {
+ <Box
+ bgColor={visuals.labelTextColor}
+ borderRadius="sm"
+ height={6}
+ width={6}
+ ></Box>
+ }
+ </MenuButton>
+ <Portal>
+ {' '}
+ <MenuList zIndex="popover" bg="gray.200">
+ {grays.map((color) => (
+ <MenuItem
+ key={color}
+ onClick={() =>
+ setVisuals({
+ ...visuals,
+ labelTextColor: color,
+ })
+ }
+ >
+ <Box
+ bgColor={color}
+ borderRadius="sm"
+ height={6}
+ width={6}
+ ></Box>
+ </MenuItem>
+ ))}
+ </MenuList>
+ </Portal>
+ </Menu>
+ </Flex>
+ <Flex alignItems="center" justifyContent="space-between">
+ <Text>Background</Text>
+ <Menu>
+ <MenuButton
+ as={Button}
+ rightIcon={<ChevronDownIcon />}
+ color="black"
+ colorScheme=""
+ >
+ {
+ <Box
+ bgColor={visuals.labelBackgroundColor}
+ borderRadius="sm"
+ height={6}
+ width={6}
+ ></Box>
+ }
+ </MenuButton>
+ <Portal>
+ {' '}
+ <MenuList zIndex="popover" bg="gray.200">
+ <MenuItem
+ onClick={() =>
+ setVisuals({
+ ...visuals,
+ labelBackgroundColor: '',
+ })
+ }
+ justifyContent="space-between"
+ alignItems="center"
+ display="flex"
+ >
+ None
+ </MenuItem>
+ {grays.map((color) => (
+ <MenuItem
+ key={color}
+ onClick={() =>
+ setVisuals({
+ ...visuals,
+ labelBackgroundColor: color,
+ })
+ }
+ justifyContent="space-between"
+ alignItems="center"
+ display="flex"
+ >
+ <Box
+ bgColor={color}
+ borderRadius="sm"
+ height={6}
+ width={6}
+ ></Box>
+ </MenuItem>
+ ))}
+ </MenuList>
+ </Portal>
+ </Menu>
+ </Flex>
+ <Collapse in={!!visuals.labelBackgroundColor} animateOpacity>
+ <Box paddingTop={2}>
+ <SliderWithInfo
+ label="Background opacity"
+ value={visuals.labelBackgroundOpacity}
+ onChange={(value) => {
+ console.log(visuals.labelBackgroundOpacity)
+ setVisuals({ ...visuals, labelBackgroundOpacity: value })
+ }}
+ min={0}
+ max={1}
+ step={0.01}
+ />
+ </Box>
+ </Collapse>
+ <Collapse in={physics.labels > 1} animateOpacity>
+ <Box paddingTop={2}>
+ <SliderWithInfo
+ label="Label Appearance Scale"
+ value={physics.labelScale * 5}
+ onChange={(value) =>
+ setPhysics({ ...physics, labelScale: value / 5 })
+ }
+ />
+ </Box>
+ </Collapse>
+ </VStack>
+ </Collapse>
<EnableSection
label="Directional Particles"
value={physics.particles}
@@ -927,7 +1124,71 @@ export const Tweaks = (props: TweakProps) => {
align="stretch"
paddingLeft={7}
color="gray.800"
- ></VStack>
+ >
+ <Flex alignItems="center" justifyContent="space-between">
+ <Flex>
+ <Text>Expand Node</Text>
+ <InfoTooltip infoText="View only the node and its direct neighbors" />
+ </Flex>
+ <Menu>
+ <MenuButton
+ as={Button}
+ rightIcon={<ChevronDownIcon />}
+ colorScheme=""
+ color="black"
+ >
+ <Text>{mouse.local[0]!.toUpperCase() + mouse.local!.slice(1)}</Text>
+ </MenuButton>
+ <Portal>
+ {' '}
+ <MenuList zIndex="popover" bgColor="gray.200">
+ <MenuItem onClick={() => setMouse({ ...mouse, local: '' })}>
+ Never
+ </MenuItem>
+ <MenuItem onClick={() => setMouse({ ...mouse, local: 'click' })}>
+ Click
+ </MenuItem>
+ <MenuItem onClick={() => setMouse({ ...mouse, local: 'double' })}>
+ Double Click
+ </MenuItem>
+ <MenuItem onClick={() => setMouse({ ...mouse, local: 'right' })}>
+ Right Click
+ </MenuItem>
+ </MenuList>
+ </Portal>
+ </Menu>
+ </Flex>
+ <Flex alignItems="center" justifyContent="space-between">
+ <Text>Open in Emacs</Text>
+ <Menu>
+ <MenuButton
+ as={Button}
+ rightIcon={<ChevronDownIcon />}
+ colorScheme=""
+ color="black"
+ >
+ <Text>{mouse.follow[0]!.toUpperCase() + mouse.follow!.slice(1)}</Text>
+ </MenuButton>
+ <Portal>
+ {' '}
+ <MenuList zIndex="popover" bgColor="gray.200" zIndex="popover">
+ <MenuItem onClick={() => setMouse({ ...mouse, follow: '' })}>
+ Never
+ </MenuItem>
+ <MenuItem onClick={() => setMouse({ ...mouse, follow: 'click' })}>
+ Click
+ </MenuItem>
+ <MenuItem onClick={() => setMouse({ ...mouse, follow: 'double' })}>
+ Double Click
+ </MenuItem>
+ <MenuItem onClick={() => setMouse({ ...mouse, follow: 'right' })}>
+ Right Click
+ </MenuItem>
+ </MenuList>
+ </Portal>
+ </Menu>
+ </Flex>
+ </VStack>
</AccordionPanel>
</AccordionItem>
</Accordion>
@@ -1028,11 +1289,14 @@ export const DropDownMenu = (props: DropDownMenuProps) => {
<MenuButton as={Button} rightIcon={<ChevronDownIcon />}>
{displayValue}
</MenuButton>
- <MenuList>
- {textArray.map((option, i) => {
- ;<MenuItem onClick={onClickArray[i]}> {option} </MenuItem>
- })}
- </MenuList>
+ <Portal>
+ {' '}
+ <MenuList zIndex="popover">
+ {textArray.map((option, i) => {
+ ;<MenuItem onClick={onClickArray[i]}> {option} </MenuItem>
+ })}
+ </MenuList>
+ </Portal>
</Menu>
)
}
diff --git a/org-roam-ui.el b/org-roam-ui.el
index 94d8e61..5ecc704 100644
--- a/org-roam-ui.el
+++ b/org-roam-ui.el
@@ -106,21 +106,18 @@ This serves the web-build and API over HTTP."
:on-open (lambda (ws) (progn
(setq oru-ws ws)
(org-roam-ui--send-graphdata)
- (add-hook 'after-save-hook #'org-roam-ui--send-graphdata)
-
+ (add-hook 'after-save-hook #'org-roam-ui--on-save)
(message "Connection established with org-roam-ui")
(add-hook 'post-command-hook #'org-roam-ui--update-current-node)))
:on-close (lambda (_websocket)
- (setq oru-ws nil)
(remove-hook 'post-command-hook #'org-roam-ui--update-current-node)
- (add-hook 'after-save-hook #'org-roam-ui--send-graphdata)
+ (remove-hook 'after-save-hook #'org-roam-ui--on-save)
(message "Connection with org-roam-ui closed succesfully."))))
(if
(boundp 'counsel-load-theme)
(advice-add 'counsel-load-theme :after #'org-roam-ui-sync-theme--advice)
- (advice-add 'load-theme :around #'org-roam-ui-sync-theme--advice)))
-
+ (advice-add 'load-theme :after #'org-roam-ui-sync-theme--advice)))
(t
(progn
(websocket-server-close org-roam-ui-ws)
@@ -129,6 +126,11 @@ This serves the web-build and API over HTTP."
(advice-remove 'load-theme #'org-roam-ui-sync-theme--advice))
(httpd-stop)))))
+(defun org-roam-ui--on-save ()
+ "Send graphdata on saving an only org-roam buffer."
+ (when (org-roam-buffer-p)
+ (org-roam-ui--send-graphdata))
+ )
(defun org-roam-ui--send-graphdata ()
"Get roam data, make JSON, send through websocket to org-roam-ui."
diff --git a/pages/_app.tsx b/pages/_app.tsx
index f8ff942..9f580f6 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -175,6 +175,12 @@ function SubApp(props: any) {
},
},
},
+ SliderThumb: {
+ bg: highlightColor + '.500',
+ },
+ SliderFilledTrack: {
+ bg: 'gray.400',
+ },
},
}
}, [highlightColor, JSON.stringify(emacsTheme)])
diff --git a/pages/index.tsx b/pages/index.tsx
index afd0ed3..ae3c048 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -28,6 +28,7 @@ import {
initialFilter,
initialVisuals,
initialBehavior,
+ initialMouse,
} from '../components/config'
import { Tweaks } from '../components/tweaks'
@@ -73,6 +74,7 @@ export function GraphPage() {
const [graphData, setGraphData] = useState<GraphData | null>(null)
const [emacsNodeId, setEmacsNodeId] = useState<string | null>(null)
const [behavior, setBehavior] = usePersistantState('behavior', initialBehavior)
+ const [mouse, setMouse] = usePersistantState('mouse', initialMouse)
const nodeByIdRef = useRef<NodeById>({})
const linksByNodeIdRef = useRef<LinksByNodeId>({})
@@ -185,6 +187,8 @@ export function GraphPage() {
setFilter,
visuals,
setVisuals,
+ mouse,
+ setMouse,
}}
/>
<Box position="absolute" alignItems="top">
@@ -421,6 +425,8 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
const theme = useTheme()
const themeContext = useContext<ThemeContextProps>(ThemeContext)
+ const getThemeColor = (name: string) => name.split('.').reduce((o, i) => o[i], theme.colors)
+
const highlightColors = useMemo(() => {
const allColors = visuals.nodeColorScheme.concat(
visuals.linkColorScheme || [],
@@ -428,13 +434,12 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
visuals.nodeHighlight || [],
)
- const getColor = (c: any) => (isNaN(c) ? theme.colors[c][500] : theme.colors.gray[c])
return Object.fromEntries(
allColors.map((color) => {
- const color1 = getColor(color)
+ const color1 = getThemeColor(color)
const crisscross = allColors.map((color2) => [
color2,
- d3int.interpolate(color1, getColor(color2)),
+ d3int.interpolate(color1, getThemeColor(color2)),
])
return [color, Object.fromEntries(crisscross)]
}),
@@ -479,25 +484,25 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
// or we don't have our own scheme and we're not being highlighted
if (!visuals.linkHighlight && !visuals.linkColorScheme && !needsHighlighting) {
const nodeColor = getLinkNodeColor(sourceId, targetId)
- return theme.colors[nodeColor][500]
+ return getThemeColor(nodeColor)
}
if (!needsHighlighting && !visuals.linkColorScheme) {
const nodeColor = getLinkNodeColor(sourceId, targetId)
- return theme.colors[nodeColor][500]
+ return getThemeColor(nodeColor)
}
if (!needsHighlighting) {
- return theme.colors.gray[visuals.linkColorScheme]
+ return getThemeColor(visuals.linkColorScheme)
}
if (!visuals.linkHighlight && !visuals.linkColorScheme) {
const nodeColor = getLinkNodeColor(sourceId, targetId)
- return theme.colors[nodeColor][500]
+ return getThemeColor(nodeColor)
}
if (!visuals.linkHighlight) {
- return theme.colors.gray[visuals.linkColorScheme]
+ return getThemeColor(visuals.linkColorScheme)
}
if (!visuals.linkColorScheme) {
@@ -512,16 +517,37 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
// if we are matching the node color and don't have a highlight color
// or we don't have our own scheme and we're not being highlighted
if (visuals.emacsNodeColor && node.id === emacsNodeId) {
- return theme.colors[visuals.emacsNodeColor][500]
+ return getThemeColor(visuals.emacsNodeColor)
}
if (!needsHighlighting) {
- return theme.colors[getNodeColorById(node.id)][500]
+ return getThemeColor(getNodeColorById(node.id))
}
if (!visuals.nodeHighlight) {
- return theme.colors[getNodeColorById(node.id)][500]
+ return getThemeColor(getNodeColorById(node.id))
}
return highlightColors[getNodeColorById(node.id)][visuals.nodeHighlight](opacity)
}
+
+ const hexToRGBA = (hex: string, opacity: number) =>
+ 'rgba(' +
+ (hex = hex.replace('#', ''))
+ .match(new RegExp('(.{' + hex.length / 3 + '})', 'g'))!
+ .map(function (l) {
+ return parseInt(hex.length % 2 ? l + l : l, 16)
+ })
+ .concat(isFinite(opacity) ? opacity : 1)
+ .join(',') +
+ ')'
+
+ const labelTextColor = useMemo(
+ () => getThemeColor(visuals.labelTextColor),
+ [visuals.labelTextColor],
+ )
+ const labelBackgroundColor = useMemo(
+ () => getThemeColor(visuals.labelBackgroundColor),
+ [visuals.labelBackgroundColor],
+ )
+
const graphCommonProps: ComponentPropsWithoutRef<typeof TForceGraph2D> = {
graphData: scopedGraphData,
width: windowWidth,
@@ -582,26 +608,28 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
if (globalScale <= physics.labelScale) {
return opacity
}
-
return highlightedNodes[node.id!] || previouslyHighlightedNodes[node.id!]
? Math.max(fadeFactor, opacity)
: 1 * fadeFactor * (-1 * (0.5 * opacity - 1))
}
- if (physics.labels === 2) {
- const backgroundOpacity = 0.5 * getLabelOpacity()
- ctx.fillStyle = `rgba(20, 20, 20, ${backgroundOpacity})`
+ if (visuals.labelBackgroundColor && visuals.labelBackgroundOpacity) {
+ const backgroundOpacity = getLabelOpacity() * visuals.labelBackgroundOpacity
+ const labelBackground = hexToRGBA(labelBackgroundColor, backgroundOpacity)
+ ctx.fillStyle = labelBackground
ctx.fillRect(
node.x! - bckgDimensions[0] / 2,
node.y! - bckgDimensions[1] / 2,
...bckgDimensions,
)
}
+
// draw label text
const textOpacity = getLabelOpacity()
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
- ctx.fillStyle = `rgb(255, 255, 255, ${textOpacity})`
+ const labelText = hexToRGBA(labelTextColor, textOpacity)
+ ctx.fillStyle = labelText
ctx.font = `${fontSize}px Sans-Serif`
ctx.fillText(label, node.x!, node.y!)
},
@@ -633,6 +661,7 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
onNodeClick: (node: NodeObject, event: any) => {
const isDoubleClick = event.timeStamp - lastNodeClickRef.current < 400
lastNodeClickRef.current = event.timeStamp
+ console.log(event)
if (isDoubleClick) {
window.open('org-protocol://roam-node?node=' + node.id, '_self')
@@ -683,8 +712,11 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
return
}
const sprite = new SpriteText(node.title.substring(0, 30))
- sprite.color = '#ffffff'
+ sprite.color = getThemeColor(visuals.labelTextColor)
+ sprite.backgroundColor = getThemeColor(visuals.labelBackgroundColor)
+ sprite.padding = 2
sprite.textHeight = 8
+
return sprite
}}
/>