diff options
Diffstat (limited to 'components/Tweaks/Visual')
-rw-r--r-- | components/Tweaks/Visual/ColorMenu.tsx | 88 | ||||
-rw-r--r-- | components/Tweaks/Visual/ColorsPanel.tsx | 237 | ||||
-rw-r--r-- | components/Tweaks/Visual/GraphColorSelect.tsx | 64 | ||||
-rw-r--r-- | components/Tweaks/Visual/HighlightingPanel.tsx | 116 | ||||
-rw-r--r-- | components/Tweaks/Visual/LabelsPanel.tsx | 162 | ||||
-rw-r--r-- | components/Tweaks/Visual/NodesNLinksPanel.tsx | 131 | ||||
-rw-r--r-- | components/Tweaks/Visual/ThemeSelect.tsx | 63 | ||||
-rw-r--r-- | components/Tweaks/Visual/VisualsPanel.tsx | 121 |
8 files changed, 982 insertions, 0 deletions
diff --git a/components/Tweaks/Visual/ColorMenu.tsx b/components/Tweaks/Visual/ColorMenu.tsx new file mode 100644 index 0000000..a792f12 --- /dev/null +++ b/components/Tweaks/Visual/ColorMenu.tsx @@ -0,0 +1,88 @@ +import { ChevronDownIcon } from '@chakra-ui/icons' +import { + Text, + Box, + Button, + Flex, + Menu, + MenuButton, + MenuItem, + MenuList, + Portal, + PopoverTrigger, + PopoverContent, + Popover, +} from '@chakra-ui/react' +import React, { useCallback } from 'react' +import { initialVisuals } from '../../config' + +export interface ColorMenuProps { + label: string + colorList: string[] + value: string + visValue: string + setVisuals?: any + noEmpty?: boolean +} + +export const ColorMenu = (props: ColorMenuProps) => { + const { label, colorList, value, visValue, setVisuals, noEmpty } = props + + const clickCallback = useCallback( + (color) => + setVisuals((curr: typeof initialVisuals) => { + return { + ...curr, + [value]: color, + } + }), + [], + ) + return ( + <Flex alignItems="center" justifyContent="space-between"> + <Text>{label}</Text> + <Popover isLazy placement="right"> + <PopoverTrigger> + <Button colorScheme="" color="black" rightIcon={<ChevronDownIcon />}> + {<Box bgColor={visValue} borderRadius="sm" height={6} width={6}></Box>} + </Button> + </PopoverTrigger> + <Portal> + <PopoverContent zIndex="tooltip" maxW={36} position="relative"> + <Flex flexWrap="wrap" bgColor="gray.200"> + {!noEmpty && ( + <Box + onClick={() => clickCallback('')} + justifyContent="space-between" + alignItems="center" + display="flex" + m={1} + > + <Box + height={6} + width={6} + borderColor="gray.600" + borderRadius="xl" + borderWidth={1} + ></Box> + </Box> + )} + {colorList.map((color: string) => ( + <Box + m={1} + key={color} + onClick={() => clickCallback(color)} + justifyContent="space-between" + alignItems="center" + display="flex" + > + <Box bgColor={color} borderRadius="xl" height={6} width={6}></Box> + </Box> + ))} + </Flex> + </PopoverContent> + </Portal> + </Popover> + </Flex> + ) +} diff --git a/components/Tweaks/Visual/ColorsPanel.tsx b/components/Tweaks/Visual/ColorsPanel.tsx new file mode 100644 index 0000000..fe4cd7b --- /dev/null +++ b/components/Tweaks/Visual/ColorsPanel.tsx @@ -0,0 +1,237 @@ +import { ArrowRightIcon, ChevronDownIcon, RepeatIcon } from '@chakra-ui/icons' +import { + Text, + Box, + Flex, + IconButton, + StackDivider, + Tooltip, + VStack, + MenuButton, + Menu, + Portal, + MenuList, + MenuOptionGroup, + MenuItemOption, + Button, + MenuItem, +} from '@chakra-ui/react' +import React from 'react' +import { ColorMenu } from './ColorMenu' +import { colorList, initialVisuals } from '../../config' + +export interface ColorsPanelProps { + visuals: typeof initialVisuals + setVisualsCallback: any + highlightColor: string + setHighlightColor: any +} + +export const ColorsPanel = (props: ColorsPanelProps) => { + const { visuals, setVisualsCallback, highlightColor, setHighlightColor } = props + + return ( + <VStack + spacing={2} + justifyContent="flex-start" + divider={<StackDivider borderColor="gray.500" />} + align="stretch" + color="gray.800" + > + <Box> + <Flex alignItems="center" justifyContent="space-between"> + <Text>Nodes</Text> + <Tooltip label="Shuffle node colors"> + <IconButton + aria-label="Shuffle node colors" + size="sm" + icon={<RepeatIcon />} + variant="ghost" + onClick={() => { + const arr = visuals.nodeColorScheme ?? [] + setVisualsCallback({ + ...visuals, + //shuffle that guy + //definitely thought of this myself + nodeColorScheme: arr + .map((x: any) => [Math.random(), x]) + .sort(([a], [b]) => a - b) + .map(([_, x]) => x), + }) + }} + /> + </Tooltip> + <Tooltip label="Cycle node colors"> + <IconButton + aria-label="Shift node colors" + icon={<ArrowRightIcon />} + size="sm" + variant="ghost" + onClick={() => { + const arr = visuals.nodeColorScheme ?? [] + setVisualsCallback({ + ...visuals, + nodeColorScheme: [...arr.slice(1, arr.length), arr[0]], + }) + }} + /> + </Tooltip> + <Menu isLazy placement="right" closeOnSelect={false} matchWidth> + <MenuButton + width={20} + as={Button} + colorScheme="" + color="black" + rightIcon={<ChevronDownIcon />} + > + <Flex height={6} width={6} flexDirection="column" flexWrap="wrap"> + {visuals.nodeColorScheme.map((color) => ( + <Box key={color} bgColor={color} flex="1 1 8px" borderRadius="2xl"></Box> + ))} + </Flex> + </MenuButton> + <Portal> + {' '} + <MenuList minW={10} zIndex="popover" bgColor="gray.200"> + <MenuOptionGroup + width={500} + type="checkbox" + defaultValue={visuals.nodeColorScheme} + onChange={(colors) => { + if (!colors.length) { + return + } + setVisualsCallback({ ...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 + } + > + <Box justifyContent="space-between" alignItems="center" display="flex"> + <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 placement="right"> + <MenuButton as={Button} colorScheme="" color="black" rightIcon={<ChevronDownIcon />}> + <Box> + {visuals.linkColorScheme ? ( + <Box + bgColor={visuals.linkColorScheme} + borderRadius="sm" + height={6} + width={6} + ></Box> + ) : ( + <Flex height={6} width={6} flexDirection="column" flexWrap="wrap"> + {visuals.nodeColorScheme.map((color) => ( + <Box key={color} bgColor={color} flex="1 1 8px" borderRadius="2xl"></Box> + ))} + </Flex> + )} + </Box> + </MenuButton> + <Portal> + {' '} + <MenuList minW={10} zIndex="popover" bgColor="gray.200"> + <MenuItem + onClick={() => setVisualsCallback({ ...visuals, linkColorScheme: '' })} + justifyContent="space-between" + alignItems="center" + display="flex" + > + <Flex height={6} width={6} flexDirection="column" flexWrap="wrap"> + {visuals.nodeColorScheme.map((color) => ( + <Box key={color} bgColor={color} flex="1 1 8px" borderRadius="2xl"></Box> + ))} + </Flex> + </MenuItem> + {colorList.map((color) => ( + <MenuItem + key={color} + onClick={() => + setVisualsCallback({ + ...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 placement="right"> + <MenuButton as={Button} colorScheme="" color="black" rightIcon={<ChevronDownIcon />}> + {<Box bgColor={highlightColor} borderRadius="sm" height={6} width={6}></Box>} + </MenuButton> + <Portal> + {' '} + <MenuList minW={10} zIndex="popover" bgColor="gray.200"> + {colorList.map((color) => ( + <MenuItem + key={color} + onClick={() => setHighlightColor(color)} + justifyContent="space-between" + alignItems="center" + display="flex" + > + <Box bgColor={color} borderRadius="sm" height={6} width={6}></Box> + </MenuItem> + ))} + </MenuList> + </Portal> + </Menu> + </Flex> + <ColorMenu + colorList={colorList} + label="Link highlight" + setVisuals={setVisualsCallback} + value="linkHighlight" + visValue={visuals.linkHighlight} + /> + <ColorMenu + colorList={colorList} + label="Node highlight" + setVisuals={setVisualsCallback} + value="nodeHighlight" + visValue={visuals.nodeHighlight} + /> + <ColorMenu + colorList={colorList} + label="Background" + setVisuals={setVisualsCallback} + value="backgroundColor" + visValue={visuals.backgroundColor} + /> + <ColorMenu + colorList={colorList} + label="Emacs node" + setVisuals={setVisualsCallback} + value="emacsNodeColor" + visValue={visuals.emacsNodeColor} + /> + </Box> + </VStack> + ) +} diff --git a/components/Tweaks/Visual/GraphColorSelect.tsx b/components/Tweaks/Visual/GraphColorSelect.tsx new file mode 100644 index 0000000..5b49672 --- /dev/null +++ b/components/Tweaks/Visual/GraphColorSelect.tsx @@ -0,0 +1,64 @@ +import React, { useContext } from 'react' +import { + Box, + Button, + Flex, + Menu, + MenuButton, + MenuItem, + MenuList, + Portal, + Text, +} from '@chakra-ui/react' +import { ChevronDownIcon } from '@chakra-ui/icons' +import { initialColoring } from '../../config' + +export interface GraphColorSelectProps { + coloring: typeof initialColoring + setColoring: any +} + +export const GraphColorSelect = (props: GraphColorSelectProps) => { + type Theme = { [key: string]: string } + const { coloring, setColoring } = props + return ( + <Flex alignItems="center" justifyContent="space-between" pl={7} pr={2}> + <Text>Graph coloring</Text> + <Menu isLazy placement="right"> + <MenuButton + as={Button} + size="sm" + colorScheme="" + color="black" + rightIcon={<ChevronDownIcon />} + > + {coloring.method === 'degree' ? 'Links' : 'Communities'} + </MenuButton> + <Portal> + <MenuList minW={10} zIndex="popover" bgColor="gray.200"> + <MenuItem + onClick={() => + setColoring((curr: typeof initialColoring) => ({ ...curr, method: 'degree' })) + } + justifyContent="space-between" + alignItems="center" + display="flex" + > + Number of links + </MenuItem> + <MenuItem + onClick={() => + setColoring((curr: typeof initialColoring) => ({ ...curr, method: 'community' })) + } + justifyContent="space-between" + alignItems="center" + display="flex" + > + Communities + </MenuItem> + </MenuList> + </Portal> + </Menu> + </Flex> + ) +} diff --git a/components/Tweaks/Visual/HighlightingPanel.tsx b/components/Tweaks/Visual/HighlightingPanel.tsx new file mode 100644 index 0000000..357d137 --- /dev/null +++ b/components/Tweaks/Visual/HighlightingPanel.tsx @@ -0,0 +1,116 @@ +import { Box, Select, StackDivider, VStack } from '@chakra-ui/react' +import React from 'react' +import { initialVisuals } from '../../config' +import { EnableSection } from '../EnableSection' +import { SliderWithInfo } from '../SliderWithInfo' + +export interface HighlightingPanelProps { + visuals: typeof initialVisuals + setVisuals: any +} +export const HighlightingPanel = (props: HighlightingPanelProps) => { + const { visuals, setVisuals } = props + return ( + <VStack + spacing={2} + justifyContent="flex-start" + divider={<StackDivider borderColor="gray.500" />} + align="stretch" + color="gray.800" + > + <Box> + <EnableSection + label="Highlight" + onChange={() => + setVisuals((visuals: typeof initialVisuals) => ({ + ...visuals, + highlight: !visuals.highlight, + })) + } + value={visuals.highlight} + > + <VStack + spacing={1} + justifyContent="flex-start" + divider={<StackDivider borderColor="gray.400" />} + align="stretch" + paddingLeft={0} + > + <SliderWithInfo + label="Highlight Link Thickness" + value={visuals.highlightLinkSize} + onChange={(value) => + setVisuals((visuals: typeof initialVisuals) => ({ + ...visuals, + highlightLinkSize: value, + })) + } + /> + <SliderWithInfo + label="Highlight Node Size" + value={visuals.highlightNodeSize} + onChange={(value) => + setVisuals((visuals: typeof initialVisuals) => ({ + ...visuals, + highlightNodeSize: value, + })) + } + /> + <SliderWithInfo + min={0} + max={1} + label="Highlight Fade" + value={visuals.highlightFade} + onChange={(value) => + setVisuals((visuals: typeof initialVisuals) => ({ + ...visuals, + highlightFade: value, + })) + } + /> + <EnableSection + label="Highlight Animation" + onChange={() => { + setVisuals((visuals: typeof initialVisuals) => ({ + ...visuals, + highlightAnim: !visuals.highlightAnim, + })) + }} + value={visuals.highlightAnim} + > + <SliderWithInfo + label="Animation speed" + onChange={(v) => + setVisuals((visuals: typeof initialVisuals) => ({ + ...visuals, + animationSpeed: v, + })) + } + value={visuals.animationSpeed} + infoText="Slower speed has a chance of being buggy" + min={50} + max={1000} + step={10} + /> + <Select + placeholder={visuals.algorithmName} + onChange={(v) => { + setVisuals((visuals: typeof initialVisuals) => ({ + ...visuals, + algorithmName: v.target.value, + })) + }} + > + {visuals.algorithmOptions.map((opt: string) => ( + <option key={opt} value={opt}> + {opt} + </option> + ))} + </Select> + </EnableSection> + </VStack> + </EnableSection> + </Box> + </VStack> + ) +} diff --git a/components/Tweaks/Visual/LabelsPanel.tsx b/components/Tweaks/Visual/LabelsPanel.tsx new file mode 100644 index 0000000..b0044f1 --- /dev/null +++ b/components/Tweaks/Visual/LabelsPanel.tsx @@ -0,0 +1,162 @@ +import { ChevronDownIcon } from '@chakra-ui/icons' +import { + Box, + Button, + Collapse, + Flex, + Menu, + MenuButton, + MenuItem, + MenuList, + Portal, + StackDivider, + VStack, + Text, +} from '@chakra-ui/react' +import React from 'react' +import { ColorMenu } from './ColorMenu' +import { colorList, initialVisuals } from '../../config' +import { SliderWithInfo } from '../SliderWithInfo' + +export interface LabelsPanelProps { + visuals: typeof initialVisuals + setVisuals: any +} +export const LabelsPanel = (props: LabelsPanelProps) => { + const { visuals, setVisuals } = props + return ( + <VStack + spacing={2} + justifyContent="flex-start" + divider={<StackDivider borderColor="gray.400" />} + align="stretch" + color="gray.800" + > + <Flex alignItems="center" justifyContent="space-between"> + <Text>Show labels</Text> + <Menu isLazy placement="right"> + <MenuButton as={Button} colorScheme="" color="black" rightIcon={<ChevronDownIcon />}> + {!visuals.labels ? 'Never' : visuals.labels < 2 ? 'On Highlight' : 'Always'} + </MenuButton> + <Portal> + {' '} + <MenuList zIndex="popover" bgColor="gray.200"> + <MenuItem onClick={() => setVisuals({ ...visuals, labels: 0 })}>Never</MenuItem> + <MenuItem onClick={() => setVisuals({ ...visuals, labels: 1 })}> + On Highlight + </MenuItem> + <MenuItem onClick={() => setVisuals({ ...visuals, labels: 2 })}>Always</MenuItem> + <MenuItem onClick={() => setVisuals({ ...visuals, labels: 3 })}> + Always (even in 3D) + </MenuItem> + </MenuList> + </Portal> + </Menu> + </Flex> + <Collapse in={visuals.labels > 1} animateOpacity> + <Box paddingTop={2}> + <SliderWithInfo + label="Label Appearance Scale" + value={visuals.labelScale * 2} + onChange={(value) => setVisuals({ ...visuals, labelScale: value / 2 })} + /> + </Box> + <Box paddingTop={2}> + <SliderWithInfo + label="Label dynamicity" + infoText="By default, labels of nodes with more links will appear earlier than those with fewer. This slider changes the strength of this effect, put it at zero to disable it." + value={visuals.labelDynamicStrength} + min={0} + max={1} + step={0.05} + onChange={(value) => + setVisuals((curr: typeof initialVisuals) => ({ + ...curr, + labelDynamicStrength: value, + })) + } + /> + <Collapse in={visuals.labelDynamicStrength > 0}> + <SliderWithInfo + label="Dynamic zoom degree cap" + infoText="The maximum number of links that is considered for the 'dynamic zoom effect'. Past this number all number of links are treated the same." + value={visuals.labelDynamicDegree} + min={1} + max={15} + step={1} + onChange={(value) => + setVisuals((curr: typeof initialVisuals) => ({ + ...curr, + labelDynamicDegree: value, + })) + } + /> + </Collapse> + </Box> + </Collapse> + <ColorMenu + colorList={colorList} + label="Text" + setVisuals={setVisuals} + value="labelTextColor" + visValue={visuals.labelTextColor} + /> + <Box> + <ColorMenu + colorList={colorList} + label="Background" + setVisuals={setVisuals} + value="labelBackgroundColor" + visValue={visuals.labelBackgroundColor} + /> + <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> + </Box> + <SliderWithInfo + label="Label font size" + value={visuals.labelFontSize} + min={5} + max={20} + step={0.5} + onChange={(value) => setVisuals({ ...visuals, labelFontSize: value })} + /> + <SliderWithInfo + label="Max. label characters" + value={visuals.labelLength} + min={10} + max={100} + step={1} + onChange={(value) => setVisuals({ ...visuals, labelLength: value })} + /> + <SliderWithInfo + label="Max. label line length" + value={visuals.labelWordWrap} + min={10} + max={100} + step={1} + onChange={(value) => setVisuals({ ...visuals, labelWordWrap: value })} + /> + <SliderWithInfo + label="Space between label lines" + value={visuals.labelLineSpace} + min={0.2} + max={3} + step={0.1} + onChange={(value) => setVisuals({ ...visuals, labelLineSpace: value })} + /> + </VStack> + ) +} diff --git a/components/Tweaks/Visual/NodesNLinksPanel.tsx b/components/Tweaks/Visual/NodesNLinksPanel.tsx new file mode 100644 index 0000000..40072fb --- /dev/null +++ b/components/Tweaks/Visual/NodesNLinksPanel.tsx @@ -0,0 +1,131 @@ +import { Box, StackDivider, VStack } from '@chakra-ui/react' +import React from 'react' +import { ColorMenu } from './ColorMenu' +import { colorList, initialVisuals } from '../../config' +import { EnableSection } from '../EnableSection' +import { SliderWithInfo } from '../SliderWithInfo' + +export interface NodesNLinksPanelProps { + visuals: typeof initialVisuals + setVisuals: any + threeDim: boolean +} + +export const NodesNLinksPanel = (props: NodesNLinksPanelProps) => { + const { visuals, setVisuals, threeDim } = props + return ( + <VStack + spacing={2} + justifyContent="flex-start" + divider={<StackDivider borderColor="gray.500" />} + align="stretch" + color="gray.800" + > + <Box> + <SliderWithInfo + label="Node size" + value={visuals.nodeRel} + onChange={(value) => setVisuals({ ...visuals, nodeRel: value })} + /> + <SliderWithInfo + label="Node degree size multiplier" + value={visuals.nodeSizeLinks} + min={0} + max={2} + onChange={(value) => setVisuals({ ...visuals, nodeSizeLinks: value })} + /> + <SliderWithInfo + label="Node zoom invariance" + value={visuals.nodeZoomSize} + min={0} + max={2} + infoText="How much the graph will try to keep the nodesize consistent across zoom scales. 0 is no consistency, node will always be their true size, 1 is linear, 2 is quadratic." + onChange={(value) => + setVisuals((prev: typeof initialVisuals) => ({ + ...prev, + nodeZoomSize: value, + })) + } + /> + {threeDim && ( + <> + <SliderWithInfo + label="Node opacity" + value={visuals.nodeOpacity} + min={0} + max={1} + onChange={(value) => setVisuals({ ...visuals, nodeOpacity: value })} + /> + <SliderWithInfo + label="Node resolution" + value={visuals.nodeResolution} + min={5} + max={32} + step={1} + onChange={(value) => setVisuals({ ...visuals, nodeResolution: value })} + /> + </> + )} + <SliderWithInfo + label="Link width" + value={visuals.linkWidth} + onChange={(value) => setVisuals({ ...visuals, linkWidth: value })} + /> + {threeDim && ( + <SliderWithInfo + label="Link opacity" + min={0} + max={1} + value={visuals.linkOpacity} + onChange={(value) => setVisuals({ ...visuals, linkOpacity: value })} + /> + )} + <EnableSection + label="Link arrows" + value={visuals.arrows} + onChange={() => setVisuals({ ...visuals, arrows: !visuals.arrows })} + > + <SliderWithInfo + label="Arrow size" + value={visuals.arrowsLength / 10} + onChange={(value) => setVisuals({ ...visuals, arrowsLength: 10 * value })} + /> + <SliderWithInfo + label="Arrow Position" + value={visuals.arrowsPos} + min={0} + max={1} + step={0.01} + onChange={(value) => setVisuals({ ...visuals, arrowsPos: value })} + /> + <ColorMenu + colorList={colorList} + label="Arrow Color" + key="arrow" + setVisuals={setVisuals} + value="arrowsColor" + visValue={visuals.arrowsColor} + /> + </EnableSection> + <EnableSection + label="Directional Particles" + value={visuals.particles} + onChange={() => setVisuals({ ...visuals, particles: !visuals.particles })} + > + <SliderWithInfo + label="Particle Number" + value={visuals.particlesNumber} + max={5} + step={1} + onChange={(value) => setVisuals({ ...visuals, particlesNumber: value })} + /> + <SliderWithInfo + label="Particle Size" + value={visuals.particlesWidth} + onChange={(value) => setVisuals({ ...visuals, particlesWidth: value })} + /> + </EnableSection> + </Box> + </VStack> + ) +} diff --git a/components/Tweaks/Visual/ThemeSelect.tsx b/components/Tweaks/Visual/ThemeSelect.tsx new file mode 100644 index 0000000..eed6daf --- /dev/null +++ b/components/Tweaks/Visual/ThemeSelect.tsx @@ -0,0 +1,63 @@ +import React, { useContext } from 'react' +import { + Box, + Button, + Flex, + Menu, + MenuButton, + MenuItem, + MenuList, + Portal, + Text, +} from '@chakra-ui/react' + +import { themes } from '../../themes' +import { ChevronDownIcon } from '@chakra-ui/icons' +import { ThemeContext } from '../../../util/themecontext' + +export const ThemeSelect = () => { + type Theme = { [key: string]: string } + const { emacsTheme, setEmacsTheme, highlightColor } = useContext(ThemeContext) + return ( + <Flex alignItems="center" justifyContent="space-between" pl={7} pr={2}> + <Text>Theme</Text> + <Menu isLazy placement="bottom" closeOnSelect={false}> + <MenuButton + as={Button} + size="sm" + colorScheme="" + color="black" + rightIcon={<ChevronDownIcon />} + > + {emacsTheme[0]} + </MenuButton> + <MenuList minW={10} zIndex="popover" bgColor="gray.200"> + <MenuItem + onClick={() => ''} + justifyContent="space-between" + alignItems="center" + display="flex" + > + <Box height={6} width={6}></Box> + </MenuItem> + {Object.keys(themes).map((theme: string, i: number) => ( + <MenuItem + key={theme} + onClick={() => setEmacsTheme([theme, themes[theme]])} + justifyContent="space-between" + alignItems="center" + display="flex" + > + <Text>{theme}</Text> + <Flex height={6} width={20} flexDirection="column" flexWrap="wrap"> + {Object.values(themes[theme as string]).map((color: string) => { + return <Box key={color} bgColor={color} flex="1 1 8px"></Box> + })} + </Flex> + </MenuItem> + ))} + </MenuList> + </Menu> + </Flex> + ) +} diff --git a/components/Tweaks/Visual/VisualsPanel.tsx b/components/Tweaks/Visual/VisualsPanel.tsx new file mode 100644 index 0000000..82b365f --- /dev/null +++ b/components/Tweaks/Visual/VisualsPanel.tsx @@ -0,0 +1,121 @@ +import { + Text, + Accordion, + AccordionButton, + AccordionItem, + Flex, + VStack, + AccordionIcon, + AccordionPanel, + MenuButton, + Menu, + Button, + Box, + Portal, + MenuList, + MenuItem, +} from '@chakra-ui/react' +import React, { useCallback } from 'react' +import { HighlightingPanel } from './HighlightingPanel' +import { ColorsPanel } from './ColorsPanel' +import { initialColoring, initialVisuals } from '../../config' +import { NodesNLinksPanel } from './NodesNLinksPanel' +import { LabelsPanel } from './LabelsPanel' +import { ThemeSelect } from './ThemeSelect' +import { CitationsPanel } from '../NodesNLinks/CitationsPanel' +import { GraphColorSelect } from './GraphColorSelect' + +export interface VisualsPanelProps { + visuals: typeof initialVisuals + setVisuals: any + highlightColor: string + setHighlightColor: any + threeDim: boolean + coloring: typeof initialColoring + setColoring: any +} + +export const VisualsPanel = (props: VisualsPanelProps) => { + const { + coloring, + setColoring, + visuals, + setVisuals, + highlightColor, + setHighlightColor, + threeDim, + } = props + const setVisualsCallback = useCallback((val) => setVisuals(val), []) + return ( + <VStack justifyContent="flex-start" align="stretch"> + <ThemeSelect /> + <GraphColorSelect {...{ coloring, setColoring }} /> + <Accordion allowToggle defaultIndex={[0]} paddingLeft={3}> + <AccordionItem> + <AccordionButton> + <Flex justifyContent="space-between" w="100%"> + <Text>Colors</Text> + <AccordionIcon marginRight={2} /> + </Flex> + </AccordionButton> + <AccordionPanel> + <ColorsPanel + visuals={visuals} + setVisualsCallback={setVisualsCallback} + highlightColor={highlightColor} + setHighlightColor={setHighlightColor} + /> + </AccordionPanel> + </AccordionItem> + <AccordionItem> + <AccordionButton> + <Flex justifyContent="space-between" w="100%"> + <Text>Nodes & Links</Text> + <AccordionIcon marginRight={2} /> + </Flex> + </AccordionButton> + <AccordionPanel> + <NodesNLinksPanel + visuals={visuals} + setVisuals={setVisualsCallback} + threeDim={threeDim} + /> + </AccordionPanel> + </AccordionItem> + <AccordionItem> + <AccordionButton> + <Flex justifyContent="space-between" w="100%"> + <Text>Labels</Text> + <AccordionIcon marginRight={2} /> + </Flex> + </AccordionButton> + <AccordionPanel> + <LabelsPanel visuals={visuals} setVisuals={setVisualsCallback} /> + </AccordionPanel> + </AccordionItem> + <AccordionItem> + <AccordionButton> + <Flex justifyContent="space-between" w="100%"> + <Text>Highlighting</Text> + <AccordionIcon marginRight={2} /> + </Flex> + </AccordionButton> + <AccordionPanel> + <HighlightingPanel visuals={visuals} setVisuals={setVisualsCallback} /> + </AccordionPanel> + </AccordionItem> + <AccordionItem> + <AccordionButton> + <Flex justifyContent="space-between" w="100%"> + <Text>Citations</Text> + <AccordionIcon marginRight={2} /> + </Flex> + </AccordionButton> + <AccordionPanel> + <CitationsPanel visuals={visuals} setVisuals={setVisualsCallback} /> + </AccordionPanel> + </AccordionItem> + </Accordion> + </VStack> + ) +} |